diff --git a/.aztec-sync-commit b/.aztec-sync-commit index c97738f7226..fdbc14d511e 100644 --- a/.aztec-sync-commit +++ b/.aztec-sync-commit @@ -1 +1 @@ -9e246c1289fa40c35c4b28d2f0081dfdc2aa9d19 +1d785fd1087d7387fc29213ca3be50b2fc9c4725 diff --git a/.dockerignore b/.dockerignore deleted file mode 100644 index 559b271bf38..00000000000 --- a/.dockerignore +++ /dev/null @@ -1,27 +0,0 @@ -Dockerfile* -.dockerignore - -# Yarn -.pnp.* -.yarn/* -!.yarn/patches -!.yarn/plugins -!.yarn/releases -!.yarn/sdks -!.yarn/versions - -packages -**/package.tgz -**/target -**/node_modules -**/outputs - -# Noir.js -tooling/noir_js/lib - -# Wasm build artifacts -compiler/wasm/nodejs -compiler/wasm/web -tooling/noirc_abi_wasm/nodejs -tooling/noirc_abi_wasm/web -tooling/noir_js/lib diff --git a/.envrc b/.envrc deleted file mode 100644 index b2f868b1898..00000000000 --- a/.envrc +++ /dev/null @@ -1,20 +0,0 @@ -# Based on https://github.com/direnv/direnv-vscode/blob/158e8302c2594cc0eaa5f8b4f0cafedd4e1c0315/.envrc - -# You can define your system-specific logic (like Git settings or GH tokens) in .envrc.local -# If that logic is usable by other people and might improve development environment, consider -# contributing it to this file! - -source_env_if_exists .envrc.local - -if [[ -z "${SKIP_NIX:-}" ]] && has nix; then - - if nix flake metadata &>/dev/null && has use_flake; then - # use flakes if possible - use flake - - else - # Otherwise fall back to pure nix - use nix - fi - -fi diff --git a/.github/ACVM_NOT_PUBLISHABLE.md b/.github/ACVM_NOT_PUBLISHABLE.md index e7eacb3b523..33230f8e8d8 100644 --- a/.github/ACVM_NOT_PUBLISHABLE.md +++ b/.github/ACVM_NOT_PUBLISHABLE.md @@ -1,9 +1,8 @@ --- title: "ACVM crates are not publishable" -assignees: TomAFrench kevaundray savio-sou +assignees: TomAFrench, Savio-Sou --- - The ACVM crates are currently unpublishable, making a release will NOT push our crates to crates.io. This is likely due to a crate we depend on bumping its MSRV above our own. Our lockfile is not taken into account when publishing to crates.io (as people downloading our crate don't use it) so we need to be able to use the most up to date versions of our dependencies (including transient dependencies) specified. diff --git a/.github/ACVM_PUBLISH_FAILED.md b/.github/ACVM_PUBLISH_FAILED.md new file mode 100644 index 00000000000..00e692a64d8 --- /dev/null +++ b/.github/ACVM_PUBLISH_FAILED.md @@ -0,0 +1,10 @@ +--- +title: "ACVM crates failed to publish" +assignees: TomAFrench, Savio-Sou +--- + +The {{env.CRATE_VERSION}} release of the ACVM crates failed. + +Check the [Publish ACVM crates]({{env.WORKFLOW_URL}}) workflow for details. + +This issue was raised by the workflow `{{env.WORKFLOW_NAME}}` diff --git a/.github/CRATES_IO_PUBLISH_FAILED.md b/.github/CRATES_IO_PUBLISH_FAILED.md index ec4de319772..5e2d4b7b77f 100644 --- a/.github/CRATES_IO_PUBLISH_FAILED.md +++ b/.github/CRATES_IO_PUBLISH_FAILED.md @@ -1,6 +1,6 @@ --- title: "ACVM crates failed to publish" -assignees: TomAFrench kevaundray savio-sou +assignees: TomAFrench, Savio-Sou --- The {{env.CRATE_VERSION}} release of the ACVM crates failed. diff --git a/.github/Cross.toml b/.github/Cross.toml index 09e6316a59c..d8516b9ae09 100644 --- a/.github/Cross.toml +++ b/.github/Cross.toml @@ -2,7 +2,6 @@ passthrough = [ "HOME", "RUST_BACKTRACE", - "BARRETENBERG_BIN_DIR" ] volumes = [ "HOME", diff --git a/.github/DEAD_LINKS_IN_DOCS.md b/.github/DEAD_LINKS_IN_DOCS.md index b1671276dcf..dcd4f44cdf2 100644 --- a/.github/DEAD_LINKS_IN_DOCS.md +++ b/.github/DEAD_LINKS_IN_DOCS.md @@ -1,6 +1,6 @@ --- title: "Docs contains dead links" -assignees: signorecello catmcgee critesjosh jzaki Savio-Sou +assignees: signorecello, catmcgee, critesjosh, jzaki, Savio-Sou labels: documentation --- diff --git a/.github/JS_PUBLISH_FAILED.md b/.github/JS_PUBLISH_FAILED.md index 5b9f79aac1f..f91af361d7d 100644 --- a/.github/JS_PUBLISH_FAILED.md +++ b/.github/JS_PUBLISH_FAILED.md @@ -1,6 +1,6 @@ --- title: "JS packages failed to publish" -assignees: TomAFrench kevaundray savio-sou +assignees: TomAFrench, Savio-Sou labels: js --- diff --git a/.github/actions/install-playwright/action.yml b/.github/actions/install-playwright/action.yml index be835a422cc..0bd61b38c49 100644 --- a/.github/actions/install-playwright/action.yml +++ b/.github/actions/install-playwright/action.yml @@ -4,20 +4,23 @@ description: Installs Playwright and its dependencies and caches them. runs: using: composite steps: - - name: Query playwright version - shell: bash - run: echo "PLAYWRIGHT_VERSION=$(yarn workspace @noir-lang/noirc_abi info @web/test-runner-playwright --json | jq .children.Version | tr -d '"')" >> $GITHUB_ENV + # - name: Query playwright version + # shell: bash + # run: echo "PLAYWRIGHT_VERSION=$(yarn workspace @noir-lang/noirc_abi info @web/test-runner-playwright --json | jq .children.Version | tr -d '"')" >> $GITHUB_ENV - - name: Cache playwright binaries - uses: actions/cache@v4 - id: playwright-cache - with: - path: | - ~/.cache/ms-playwright - key: ${{ runner.os }}-playwright-${{ env.PLAYWRIGHT_VERSION }} + # - name: Cache playwright binaries + # uses: actions/cache@v4 + # id: playwright-cache + # with: + # path: | + # ~/.cache/ms-playwright + # key: ${{ runner.os }}-playwright-${{ env.PLAYWRIGHT_VERSION }} - name: Install playwright deps shell: bash - if: steps.playwright-cache.outputs.cache-hit != 'true' - run: ./.github/scripts/playwright-install.sh + # if: steps.playwright-cache.outputs.cache-hit != 'true' + run: | + # Workaround: https://github.com/microsoft/playwright/issues/30503#issuecomment-2074783821 + sudo rm /etc/apt/sources.list.d/microsoft-prod.list + ./.github/scripts/playwright-install.sh diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index e81ede7199d..dfb141e29f7 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -17,7 +17,7 @@ Resolves Check one: - [ ] No documentation needed. - [ ] Documentation included in this PR. -- [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. +- [ ] **[For Experimental Features]** Documentation to be submitted in a separate PR. # PR Checklist\* diff --git a/.github/scripts/acvm_js-build.sh b/.github/scripts/acvm_js-build.sh index 95bd1efc8b9..e79967e3a8f 100755 --- a/.github/scripts/acvm_js-build.sh +++ b/.github/scripts/acvm_js-build.sh @@ -2,4 +2,5 @@ set -eu .github/scripts/wasm-bindgen-install.sh +.github/scripts/wasm-opt-install.sh yarn workspace @noir-lang/acvm_js build diff --git a/.github/scripts/noir-wasm-build.sh b/.github/scripts/noir-wasm-build.sh index f799387b6f6..6c0336ee0c5 100755 --- a/.github/scripts/noir-wasm-build.sh +++ b/.github/scripts/noir-wasm-build.sh @@ -2,4 +2,6 @@ set -eu .github/scripts/wasm-pack-install.sh +.github/scripts/wasm-opt-install.sh +yarn workspace @noir-lang/types build yarn workspace @noir-lang/noir_wasm build diff --git a/.github/scripts/noirc-abi-build.sh b/.github/scripts/noirc-abi-build.sh index 23b8393088e..99de474eb75 100755 --- a/.github/scripts/noirc-abi-build.sh +++ b/.github/scripts/noirc-abi-build.sh @@ -2,4 +2,5 @@ set -eu .github/scripts/wasm-bindgen-install.sh +.github/scripts/wasm-opt-install.sh yarn workspace @noir-lang/noirc_abi build diff --git a/.github/scripts/wasm-bindgen-install.sh b/.github/scripts/wasm-bindgen-install.sh index a548372ee2c..20908003693 100755 --- a/.github/scripts/wasm-bindgen-install.sh +++ b/.github/scripts/wasm-bindgen-install.sh @@ -6,7 +6,7 @@ cd $(dirname "$0") ./cargo-binstall-install.sh # Install wasm-bindgen-cli. -if [ "$(wasm-bindgen --version | cut -d' ' -f2)" != "0.2.86" ]; then +if [ "$(wasm-bindgen --version &> /dev/null | cut -d' ' -f2)" != "0.2.86" ]; then echo "Building wasm-bindgen..." cargo binstall wasm-bindgen-cli@0.2.86 --force --no-confirm fi diff --git a/.github/scripts/wasm-opt-install.sh b/.github/scripts/wasm-opt-install.sh index cbdeb8f2bfe..218778edac6 100755 --- a/.github/scripts/wasm-opt-install.sh +++ b/.github/scripts/wasm-opt-install.sh @@ -5,4 +5,4 @@ cd $(dirname "$0") ./cargo-binstall-install.sh -cargo-binstall wasm-opt --version 0.116.0 -y +cargo-binstall wasm-opt --version 0.116.0 -y --force diff --git a/.github/workflows/docker-test-flow.yml b/.github/workflows/docker-test-flow.yml deleted file mode 100644 index c8b4f53fadd..00000000000 --- a/.github/workflows/docker-test-flow.yml +++ /dev/null @@ -1,808 +0,0 @@ -name: Test Nargo and JS packages - -on: - push: - branches: - - 'master' - -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.ref || github.run_id }} - cancel-in-progress: true - -jobs: - build-base-nargo: - name: Build base nargo docker image - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v4 - - name: Get current date - id: date - run: echo "date=$(date +'%Y.%m.%d.%H.%M')" >> $GITHUB_STATE - - name: prepare docker images tags - id: prep - run: | - REGISTRY="ghcr.io" - IMG_RAW="${REGISTRY}/${{ github.repository }}" - IMAGE=$(echo "$IMG_RAW" | tr '[:upper:]' '[:lower:]') - TAGS="${IMAGE}:${{ github.sha }}-nargo" - FULL_TAGS="${TAGS},${IMAGE}:latest-nargo,${IMAGE}:v${{ steps.date.outputs.date }}-nargo" - echo "tags=$FULL_TAGS" >> $GITHUB_OUTPUT - echo "image=$IMAGE" >> $GITHUB_OUTPUT - - name: Set up Docker Buildx - id: buildx - uses: docker/setup-buildx-action@v3 - - name: Login to GitHub Container Registry - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - name: Build nargo base dockerfile - uses: docker/build-push-action@v5 - with: - context: . - file: Dockerfile.ci - tags: ${{ steps.prep.outputs.tags }} - target: base-nargo - cache-from: type=gha - cache-to: type=gha,mode=max - push: true - - build-base-js: - name: Build base js docker image - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v4 - - name: Get current date - id: date - run: echo "date=$(date +'%Y.%m.%d.%H.%M')" >> $GITHUB_STATE - - name: Prepare docker image tags - id: prep - run: | - REGISTRY="ghcr.io" - IMG_RAW="${REGISTRY}/${{ github.repository }}" - IMAGE=$(echo "$IMG_RAW" | tr '[:upper:]' '[:lower:]') - TAGS="${IMAGE}:${{ github.sha }}-js" - FULL_TAGS="${TAGS},${IMAGE}:latest-js,${IMAGE}:v${{ steps.date.outputs.date }}-js" - echo "tags=$FULL_TAGS" >> $GITHUB_OUTPUT - echo "image=$IMAGE" >> $GITHUB_OUTPUT - - name: Set up Docker Buildx - id: buildx - uses: docker/setup-buildx-action@v3 - - name: Login to GitHub Container Registry - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - name: Build js base dockerfile - uses: docker/build-push-action@v5 - with: - context: . - file: Dockerfile.ci - tags: ${{ steps.prep.outputs.tags }} - target: base-js - cache-from: type=gha - cache-to: type=gha,mode=max - push: true - - artifact-nargo: - name: Artifact nargo - runs-on: ubuntu-latest - needs: [build-base-nargo] - container: - image: ghcr.io/noir-lang/noir:${{ github.sha }}-nargo - credentials: - username: ${{ github.actor }} - password: ${{ secrets.github_token }} - steps: - - name: Artifact nargo - uses: actions/upload-artifact@v4 - with: - name: nargo - path: /usr/src/noir/target/release/nargo - if-no-files-found: error - compression-level: 0 - - test-nargo: - name: Test nargo - runs-on: ubuntu-latest - needs: [build-base-nargo] - container: - image: ghcr.io/noir-lang/noir:${{ github.sha }}-nargo - credentials: - username: ${{ github.actor }} - password: ${{ secrets.github_token }} - steps: - - name: Test - working-directory: /usr/src/noir - run: | - .github/scripts/nargo-test.sh - - build-noir-wasm: - name: Build noir wasm - runs-on: ubuntu-latest - needs: [build-base-js, build-noirc-abi] - container: - image: ghcr.io/noir-lang/noir:${{ github.sha }}-js - credentials: - username: ${{ github.actor }} - password: ${{ secrets.github_token }} - steps: - - name: Download noirc abi - uses: actions/download-artifact@v4 - with: - name: noirc_abi_wasm - path: | - /usr/src/noir/tooling/noirc_abi_wasm - - name: Build - working-directory: /usr/src/noir - run: | - ./.github/scripts/noir-wasm-build.sh - - name: Artifact - uses: actions/upload-artifact@v4 - with: - name: noir_wasm - path: /usr/src/noir/compiler/wasm - retention-days: 10 - - test-noir-wasm: - name: Test noir wasm - runs-on: ubuntu-latest - needs: [build-base-js, artifact-nargo, build-noir-wasm] - container: - image: ghcr.io/noir-lang/noir:${{ github.sha }}-js - credentials: - username: ${{ github.actor }} - password: ${{ secrets.github_token }} - steps: - - name: Download nargo - uses: actions/download-artifact@v4 - with: - name: nargo - path: /usr/src/noir/target/release - - name: Prep downloaded artifact - run: | - chmod +x /usr/src/noir/target/release/nargo - - name: Download noirc abi - uses: actions/download-artifact@v4 - with: - name: noirc_abi_wasm - path: | - /usr/src/noir/tooling/noirc_abi_wasm - - name: Download noir_wasm artifact - uses: actions/download-artifact@v4 - with: - name: noir_wasm - path: /usr/src/noir/compiler/wasm - - name: Test - working-directory: /usr/src/noir - run: | - ./.github/scripts/noir-wasm-test.sh - - test-noir-wasm-browser: - name: Test noir wasm browser - runs-on: ubuntu-latest - needs: [build-base-js, artifact-nargo, build-noir-wasm] - container: - image: ghcr.io/noir-lang/noir:${{ github.sha }}-js - credentials: - username: ${{ github.actor }} - password: ${{ secrets.github_token }} - steps: - - name: Download nargo - uses: actions/download-artifact@v4 - with: - name: nargo - path: /usr/src/noir/target/release - - name: Prep downloaded artifact - run: | - chmod +x /usr/src/noir/target/release/nargo - - name: Download noirc abi - uses: actions/download-artifact@v4 - with: - name: noirc_abi_wasm - path: | - /usr/src/noir/tooling/noirc_abi_wasm - - name: Download noir_wasm artifact - uses: actions/download-artifact@v4 - with: - name: noir_wasm - path: /usr/src/noir/compiler/wasm - - name: Test - working-directory: /usr/src/noir - run: | - ./.github/scripts/noir-wasm-test-browser.sh - - build-acvm_js: - name: Build acvm js - runs-on: ubuntu-latest - needs: [build-base-js] - container: - image: ghcr.io/noir-lang/noir:${{ github.sha }}-js - credentials: - username: ${{ github.actor }} - password: ${{ secrets.github_token }} - steps: - - name: Build - working-directory: /usr/src/noir - run: | - ./.github/scripts/acvm_js-build.sh - - name: Artifact - uses: actions/upload-artifact@v4 - with: - name: acvm_js - path: - /usr/src/noir/acvm-repo/acvm_js/outputs/out/acvm_js - if-no-files-found: error - compression-level: 0 - - test-acvm_js: - name: Test acvm js - runs-on: ubuntu-latest - needs: [build-base-js, build-acvm_js] - container: - image: ghcr.io/noir-lang/noir:${{ github.sha }}-js - credentials: - username: ${{ github.actor }} - password: ${{ secrets.github_token }} - steps: - - name: Download acvm js - uses: actions/download-artifact@v4 - with: - name: acvm_js - path: | - /usr/src/noir/acvm-repo/acvm_js - - name: Test - working-directory: /usr/src/noir - run: | - ./.github/scripts/acvm_js-test.sh - - test-acvm_js-browser: - name: Test acvm js browser - runs-on: ubuntu-latest - needs: [build-base-js, build-acvm_js] - container: - image: ghcr.io/noir-lang/noir:${{ github.sha }}-js - credentials: - username: ${{ github.actor }} - password: ${{ secrets.github_token }} - steps: - - name: Download acvm js - uses: actions/download-artifact@v4 - with: - name: acvm_js - path: | - /usr/src/noir/acvm-repo/acvm_js - - name: Test - working-directory: /usr/src/noir - run: | - ./.github/scripts/acvm_js-test-browser.sh - - build-noirc-abi: - name: Build noirc abi - runs-on: ubuntu-latest - needs: [build-base-js] - container: - image: ghcr.io/noir-lang/noir:${{ github.sha }}-js - credentials: - username: ${{ github.actor }} - password: ${{ secrets.github_token }} - steps: - - name: Build - working-directory: /usr/src/noir - run: | - ./.github/scripts/noirc-abi-build.sh - - name: Artifact - uses: actions/upload-artifact@v4 - with: - name: noirc_abi_wasm - path: - /usr/src/noir/tooling/noirc_abi_wasm/outputs/out/noirc_abi_wasm - if-no-files-found: error - compression-level: 0 - - test-noirc-abi: - name: Test noirc abi - runs-on: ubuntu-latest - needs: [build-base-js, build-noirc-abi] - container: - image: ghcr.io/noir-lang/noir:${{ github.sha }}-js - credentials: - username: ${{ github.actor }} - password: ${{ secrets.github_token }} - steps: - - name: Download noirc abi - uses: actions/download-artifact@v4 - with: - name: noirc_abi_wasm - path: | - /usr/src/noir/tooling/noirc_abi_wasm - - name: Test - working-directory: /usr/src/noir - run: | - ./.github/scripts/noirc-abi-test.sh - - test-noirc-abi-browser: - name: Test noirc abi browser - runs-on: ubuntu-latest - needs: [build-base-js, build-noirc-abi] - container: - image: ghcr.io/noir-lang/noir:${{ github.sha }}-js - credentials: - username: ${{ github.actor }} - password: ${{ secrets.github_token }} - steps: - - name: Download noirc abi - uses: actions/download-artifact@v4 - with: - name: noirc_abi_wasm - path: | - /usr/src/noir/tooling/noirc_abi_wasm - - name: Test - working-directory: /usr/src/noir - run: | - ./.github/scripts/noirc-abi-test-browser.sh - - build-noir-js-types: - name: Build noir js types - runs-on: ubuntu-latest - needs: [build-base-js, build-noirc-abi] - container: - image: ghcr.io/noir-lang/noir:${{ github.sha }}-js - credentials: - username: ${{ github.actor }} - password: ${{ secrets.github_token }} - steps: - - name: Download noirc abi - uses: actions/download-artifact@v4 - with: - name: noirc_abi_wasm - path: | - /usr/src/noir/tooling/noirc_abi_wasm - - name: Build - working-directory: /usr/src/noir - run: | - ./.github/scripts/noir-js-types-build.sh - - name: Artifact - uses: actions/upload-artifact@v4 - with: - name: noir-js-types - path: | - /usr/src/noir/tooling/noir_js_types/lib - if-no-files-found: error - compression-level: 0 - - build-barretenberg-backend: - name: Build Barretenberg backend - runs-on: ubuntu-latest - needs: [build-base-js, build-noirc-abi, build-noir-js-types] - container: - image: ghcr.io/noir-lang/noir:${{ github.sha }}-js - credentials: - username: ${{ github.actor }} - password: ${{ secrets.github_token }} - steps: - - name: Download noirc abi - uses: actions/download-artifact@v4 - with: - name: noirc_abi_wasm - path: | - /usr/src/noir/tooling/noirc_abi_wasm - - name: Download noir js types - uses: actions/download-artifact@v4 - with: - name: noir-js-types - path: /usr/src/noir/tooling/noir_js_types/lib/ - - name: Build - working-directory: /usr/src/noir - run: | - ./.github/scripts/backend-barretenberg-build.sh - - name: Artifact - uses: actions/upload-artifact@v4 - with: - name: barretenberg-backend - path: - /usr/src/noir/tooling/noir_js_backend_barretenberg/lib - if-no-files-found: error - compression-level: 0 - - test-barretenberg-backend: - name: Test Barretenberg backend - runs-on: ubuntu-latest - needs: [build-base-js, build-noirc-abi, build-noir-js-types, build-barretenberg-backend] - container: - image: ghcr.io/noir-lang/noir:${{ github.sha }}-js - credentials: - username: ${{ github.actor }} - password: ${{ secrets.github_token }} - steps: - - name: Download artifact - uses: actions/download-artifact@v4 - with: - name: noirc_abi_wasm - path: | - /usr/src/noir/tooling/noirc_abi_wasm - - name: Download noir js types - uses: actions/download-artifact@v4 - with: - name: noir-js-types - path: /usr/src/noir/tooling/noir_js_types/lib/ - - name: Download Backend barretenberg - uses: actions/download-artifact@v4 - with: - name: barretenberg-backend - path: - /usr/src/noir/tooling/noir_js_backend_barretenberg/lib - - name: Test - working-directory: /usr/src/noir - run: | - ./.github/scripts/backend-barretenberg-test.sh - - build-noir_js: - name: Build noirjs - runs-on: ubuntu-latest - needs: [build-base-js, artifact-nargo, build-noirc-abi, build-acvm_js, build-barretenberg-backend, build-noir-js-types] - container: - image: ghcr.io/noir-lang/noir:${{ github.sha }}-js - credentials: - username: ${{ github.actor }} - password: ${{ secrets.github_token }} - steps: - - name: Download nargo - uses: actions/download-artifact@v4 - with: - name: nargo - path: /usr/src/noir/target/release - - name: prep downloaded artifact - run: | - chmod +x /usr/src/noir/target/release/nargo - - name: Download noirc abi - uses: actions/download-artifact@v4 - with: - name: noirc_abi_wasm - path: | - /usr/src/noir/tooling/noirc_abi_wasm - - name: Download acvm js - uses: actions/download-artifact@v4 - with: - name: acvm_js - path: | - /usr/src/noir/acvm-repo/acvm_js - - name: Download Barretenberg backend - uses: actions/download-artifact@v4 - with: - name: barretenberg-backend - path: - /usr/src/noir/tooling/noir_js_backend_barretenberg/lib - - name: Download noir js types - uses: actions/download-artifact@v4 - with: - name: noir-js-types - path: | - /usr/src/noir/tooling/noir_js_types/lib - - name: Build - working-directory: /usr/src/noir - run: | - ./.github/scripts/noir-js-build.sh - - name: Artifact - uses: actions/upload-artifact@v4 - with: - name: noir_js - path: - /usr/src/noir/tooling/noir_js/lib - - test-noir_js: - name: Test noirjs - runs-on: ubuntu-latest - needs: [ - build-base-js, - build-noirc-abi, - artifact-nargo, - build-acvm_js, - build-barretenberg-backend, - build-noir_js, - build-noir-js-types - ] - container: - image: ghcr.io/noir-lang/noir:${{ github.sha }}-js - credentials: - username: ${{ github.actor }} - password: ${{ secrets.github_token }} - steps: - - name: Download nargo - uses: actions/download-artifact@v4 - with: - name: nargo - path: /usr/src/noir/target/release - - name: Prep downloaded artifact - run: | - chmod +x /usr/src/noir/target/release/nargo - - name: Download noirc abi - uses: actions/download-artifact@v4 - with: - name: noirc_abi_wasm - path: | - /usr/src/noir/tooling/noirc_abi_wasm - - name: Download acvm js - uses: actions/download-artifact@v4 - with: - name: acvm_js - path: | - /usr/src/noir/acvm-repo/acvm_js - - name: Download Barretenberg backend - uses: actions/download-artifact@v4 - with: - name: barretenberg-backend - path: - /usr/src/noir/tooling/noir_js_backend_barretenberg/lib - - name: Download noir js types - uses: actions/download-artifact@v4 - with: - name: noir-js-types - path: | - /usr/src/noir/tooling/noir_js_types/lib - - name: Download noir js - uses: actions/download-artifact@v4 - with: - name: noir_js - path: - /usr/src/noir/tooling/noir_js/lib - - name: Test - working-directory: /usr/src/noir - run: | - ./.github/scripts/noir-js-test.sh - - build-noir_codegen: - name: Build noir codegen - runs-on: ubuntu-latest - needs: [build-base-js, build-noirc-abi, build-acvm_js, build-noir-js-types, build-noir_js] - container: - image: ghcr.io/noir-lang/noir:${{ github.sha }}-js - credentials: - username: ${{ github.actor }} - password: ${{ secrets.github_token }} - steps: - - name: Download nargo - uses: actions/download-artifact@v4 - with: - name: nargo - path: /usr/src/noir/target/release - - name: Prep downloaded artifact - run: | - chmod +x /usr/src/noir/target/release/nargo - - name: Download noirc abi package - uses: actions/download-artifact@v4 - with: - name: noirc_abi_wasm - path: /usr/src/noir/tooling/noirc_abi_wasm - - name: Download acvm js - uses: actions/download-artifact@v4 - with: - name: acvm_js - path: /usr/src/noir/acvm-repo/acvm_js - - name: Download noir js types - uses: actions/download-artifact@v4 - with: - name: noir-js-types - path: | - /usr/src/noir/tooling/noir_js_types/lib - - name: Download noir js - uses: actions/download-artifact@v4 - with: - name: noir_js - path: - /usr/src/noir/tooling/noir_js/lib - - name: Build - working-directory: /usr/src/noir - run: | - ./.github/scripts/noir-codegen-build.sh - - name: Artifact - uses: actions/upload-artifact@v4 - with: - name: noir_codegen - path: - /usr/src/noir/tooling/noir_codegen/lib - - test-noir_codegen: - name: Test noir codegen - runs-on: ubuntu-latest - needs: [build-base-js, artifact-nargo, build-noirc-abi, build-acvm_js, build-noir-js-types, build-noir_js, build-noir_codegen] - container: - image: ghcr.io/noir-lang/noir:${{ github.sha }}-js - credentials: - username: ${{ github.actor }} - password: ${{ secrets.github_token }} - steps: - - name: Download nargo - uses: actions/download-artifact@v4 - with: - name: nargo - path: /usr/src/noir/target/release - - name: Prep downloaded artifact - run: | - chmod +x /usr/src/noir/target/release/nargo - - name: Download noirc abi - uses: actions/download-artifact@v4 - with: - name: noirc_abi_wasm - path: /usr/src/noir/tooling/noirc_abi_wasm - - name: Download acvm js - uses: actions/download-artifact@v4 - with: - name: acvm_js - path: /usr/src/noir/acvm-repo/acvm_js - - name: Download noir js types - uses: actions/download-artifact@v4 - with: - name: noir-js-types - path: | - /usr/src/noir/tooling/noir_js_types/lib - - name: Download noir js - uses: actions/download-artifact@v4 - with: - name: noir_js - path: - /usr/src/noir/tooling/noir_js/lib - - name: Download noir codegen - uses: actions/download-artifact@v4 - with: - name: noir_codegen - path: - /usr/src/noir/tooling/noir_codegen/lib - - name: Test - working-directory: /usr/src/noir - run: | - ./.github/scripts/noir-codegen-test.sh - - test-integration: - name: Integration test - runs-on: ubuntu-latest - needs: [ - build-base-js, - artifact-nargo, - build-noir-wasm, - build-noirc-abi, - build-acvm_js, - build-noir-js-types, - build-noir_js, - build-barretenberg-backend - ] - container: - image: ghcr.io/noir-lang/noir:${{ github.sha }}-js - credentials: - username: ${{ github.actor }} - password: ${{ secrets.github_token }} - steps: - - name: Download nargo - uses: actions/download-artifact@v4 - with: - name: nargo - path: /usr/src/noir/target/release - - name: Prep downloaded artifact - run: | - chmod +x /usr/src/noir/target/release/nargo - - name: Download noir wasm - uses: actions/download-artifact@v4 - with: - name: noir_wasm - path: /usr/src/noir/compiler/wasm - - name: Download noirc abi - uses: actions/download-artifact@v4 - with: - name: noirc_abi_wasm - path: /usr/src/noir/tooling/noirc_abi_wasm - - name: Download acvm js - uses: actions/download-artifact@v4 - with: - name: acvm_js - path: /usr/src/noir/acvm-repo/acvm_js - - name: Download noir js types - uses: actions/download-artifact@v4 - with: - name: noir-js-types - path: | - /usr/src/noir/tooling/noir_js_types/lib - - name: Download noir js - uses: actions/download-artifact@v4 - with: - name: noir_js - path: - /usr/src/noir/tooling/noir_js/lib - - name: Download Barretenberg backend - uses: actions/download-artifact@v4 - with: - name: barretenberg-backend - path: - /usr/src/noir/tooling/noir_js_backend_barretenberg/lib - - name: Test - working-directory: /usr/src/noir - run: | - ./.github/scripts/integration-test-node.sh - - test-integration-browser: - name: Integration test browser - runs-on: ubuntu-latest - needs: [ - build-base-js, - build-noir-wasm, - build-noirc-abi, - build-acvm_js, - build-noir-js-types, - build-noir_js, - build-barretenberg-backend - ] - container: - image: ghcr.io/noir-lang/noir:${{ github.sha }}-js - credentials: - username: ${{ github.actor }} - password: ${{ secrets.github_token }} - steps: - - name: Download noir wasm - uses: actions/download-artifact@v4 - with: - name: noir_wasm - path: /usr/src/noir/compiler/wasm - - name: Download noirc abi - uses: actions/download-artifact@v4 - with: - name: noirc_abi_wasm - path: /usr/src/noir/tooling/noirc_abi_wasm - - name: Download acvm js - uses: actions/download-artifact@v4 - with: - name: acvm_js - path: /usr/src/noir/acvm-repo/acvm_js - - name: Download noir js types - uses: actions/download-artifact@v4 - with: - name: noir-js-types - path: | - /usr/src/noir/tooling/noir_js_types/lib - - name: Download noir js - uses: actions/download-artifact@v4 - with: - name: noir_js - path: - /usr/src/noir/tooling/noir_js/lib - - name: Download Barretenberg backend - uses: actions/download-artifact@v4 - with: - name: barretenberg-backend - path: - /usr/src/noir/tooling/noir_js_backend_barretenberg/lib - - name: Test - working-directory: /usr/src/noir - run: | - ./.github/scripts/integration-test-browser.sh - - tests-end: - name: End - runs-on: ubuntu-latest - if: ${{ always() }} - needs: - - test-nargo - - test-noirc-abi - - test-noirc-abi-browser - - test-noir-wasm - - test-noir-wasm-browser - - test-integration - - test-integration-browser - - test-noir_codegen - - test-acvm_js - - test-acvm_js-browser - - test-barretenberg-backend - - test-noir_js - - steps: - - name: Report overall success - run: | - if [[ $FAIL == true ]]; then - exit 1 - else - exit 0 - fi - env: - FAIL: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') || contains(needs.*.result, 'skipped') }} diff --git a/.github/workflows/docs-pr.yml b/.github/workflows/docs-pr.yml index 5d0b72c6ad8..9cb6775bfb7 100644 --- a/.github/workflows/docs-pr.yml +++ b/.github/workflows/docs-pr.yml @@ -55,7 +55,7 @@ jobs: uses: actions/checkout@v4 - name: Setup toolchain - uses: dtolnay/rust-toolchain@1.73.0 + uses: dtolnay/rust-toolchain@1.74.1 - uses: Swatinem/rust-cache@v2 with: @@ -75,9 +75,13 @@ jobs: run: | npm i wasm-opt -g + - name: Query active docs versions + run: yarn workspace docs version::stables + - name: Build docs - run: - yarn workspaces foreach -Rpt --from docs run build + env: + MATOMO_ENV: staging # not really a secret, it will show in the footer anyway + run: yarn workspaces foreach -Rpt --from docs run build - name: Upload artifact uses: actions/upload-artifact@v4 @@ -126,4 +130,4 @@ jobs: with: message: | FYI @noir-lang/developerrelations on Noir doc changes. - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/formatting.yml b/.github/workflows/formatting.yml index 279e90f5f6f..08c02af519f 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.73.0 + uses: dtolnay/rust-toolchain@1.74.1 with: targets: ${{ matrix.target }} components: clippy, rustfmt @@ -44,7 +44,7 @@ jobs: save-if: ${{ github.event_name != 'merge_group' }} - name: Run `cargo clippy` - run: cargo clippy --workspace --locked --release + run: cargo clippy --all-targets --workspace --locked --release - name: Run `cargo fmt` run: cargo fmt --all --check @@ -73,7 +73,7 @@ jobs: uses: actions/checkout@v4 - name: Setup toolchain - uses: dtolnay/rust-toolchain@1.73.0 + uses: dtolnay/rust-toolchain@1.74.1 - uses: Swatinem/rust-cache@v2 with: diff --git a/.github/workflows/gates_report.yml b/.github/workflows/gates_report.yml index f3f798fc5ea..0cc94a1a04d 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.73.0 + uses: dtolnay/rust-toolchain@1.74.1 - uses: Swatinem/rust-cache@v2 with: @@ -43,7 +43,7 @@ jobs: retention-days: 3 - compare_gas_reports: + compare_gates_reports: needs: [build-nargo] runs-on: ubuntu-latest permissions: @@ -52,6 +52,11 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Install `bb` + run: | + ./scripts/install_bb.sh + echo "$HOME/.bb/" >> $GITHUB_PATH + - name: Download nargo binary uses: actions/download-artifact@v4 with: @@ -69,12 +74,13 @@ jobs: - name: Generate gates report working-directory: ./test_programs run: | + ./rebuild.sh ./gates_report.sh mv gates_report.json ../gates_report.json - + - name: Compare gates reports id: gates_diff - uses: TomAFrench/noir-gates-diff@e7cf131b7e7f044c01615f93f0b855f65ddc02d4 + uses: vezenovm/noir-gates-diff@acf12797860f237117e15c0d6e08d64253af52b6 with: report: gates_report.json summaryQuantile: 0.9 # only display the 10% most significant circuit size diffs in the summary (defaults to 20%) diff --git a/.github/workflows/publish-acvm.yml b/.github/workflows/publish-acvm.yml index 959cd8e4bca..feb4d4216c3 100644 --- a/.github/workflows/publish-acvm.yml +++ b/.github/workflows/publish-acvm.yml @@ -18,7 +18,7 @@ jobs: ref: ${{ inputs.noir-ref }} - name: Setup toolchain - uses: dtolnay/rust-toolchain@1.73.0 + uses: dtolnay/rust-toolchain@1.74.1 # These steps are in a specific order so crate dependencies are updated first - name: Publish acir_field @@ -74,4 +74,4 @@ jobs: WORKFLOW_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} with: update_existing: true - filename: .github/JS_PUBLISH_FAILED.md \ No newline at end of file + filename: .github/ACVM_PUBLISH_FAILED.md \ No newline at end of file diff --git a/.github/workflows/publish-docs.yml b/.github/workflows/publish-docs.yml index a56583b34eb..8896e613608 100644 --- a/.github/workflows/publish-docs.yml +++ b/.github/workflows/publish-docs.yml @@ -28,10 +28,11 @@ jobs: run: | npm i wasm-opt -g + - name: Query active docs versions + run: yarn workspace docs version::stables + - name: Build docs for deploying - working-directory: docs - run: - yarn workspaces foreach -Rt run build + run: yarn workspaces foreach -Rpt --from docs run build - name: Deploy to Netlify uses: nwtgck/actions-netlify@v2.1 diff --git a/.github/workflows/publish-es-packages.yml b/.github/workflows/publish-es-packages.yml index f72a97b2684..682fed69c7b 100644 --- a/.github/workflows/publish-es-packages.yml +++ b/.github/workflows/publish-es-packages.yml @@ -20,9 +20,11 @@ jobs: steps: - name: Checkout Noir repo uses: actions/checkout@v4 - + with: + ref: ${{ inputs.noir-ref }} + - name: Setup toolchain - uses: dtolnay/rust-toolchain@1.73.0 + uses: dtolnay/rust-toolchain@1.74.1 - uses: Swatinem/rust-cache@v2 with: @@ -42,7 +44,9 @@ jobs: uses: actions/upload-artifact@v4 with: name: noirc_abi_wasm - path: ./tooling/noirc_abi_wasm/outputs/out/noirc_abi_wasm + path: | + ./tooling/noirc_abi_wasm/nodejs + ./tooling/noirc_abi_wasm/web retention-days: 10 build-noir_wasm: @@ -54,7 +58,7 @@ jobs: ref: ${{ inputs.noir-ref }} - name: Setup toolchain - uses: dtolnay/rust-toolchain@1.73.0 + uses: dtolnay/rust-toolchain@1.74.1 - uses: Swatinem/rust-cache@v2 with: @@ -87,9 +91,11 @@ jobs: steps: - name: Checkout sources uses: actions/checkout@v4 + with: + ref: ${{ inputs.noir-ref }} - name: Setup toolchain - uses: dtolnay/rust-toolchain@1.73.0 + uses: dtolnay/rust-toolchain@1.74.1 - uses: Swatinem/rust-cache@v2 with: @@ -109,7 +115,9 @@ jobs: uses: actions/upload-artifact@v4 with: name: acvm-js - path: ./acvm-repo/acvm_js/outputs/out/acvm_js + path: | + ./acvm-repo/acvm_js/nodejs + ./acvm-repo/acvm_js/web retention-days: 3 publish-es-packages: @@ -164,4 +172,4 @@ jobs: WORKFLOW_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} with: update_existing: true - filename: .github/JS_PUBLISH_FAILED.md \ No newline at end of file + filename: .github/JS_PUBLISH_FAILED.md diff --git a/.github/workflows/publish-nargo.yml b/.github/workflows/publish-nargo.yml index e47e1a13053..26a4c701c5b 100644 --- a/.github/workflows/publish-nargo.yml +++ b/.github/workflows/publish-nargo.yml @@ -23,7 +23,7 @@ permissions: jobs: build-apple-darwin: - runs-on: macos-latest + runs-on: macos-12 env: CROSS_CONFIG: ${{ github.workspace }}/.github/Cross.toml NIGHTLY_RELEASE: ${{ inputs.tag == '' }} @@ -46,7 +46,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.73.0 + uses: dtolnay/rust-toolchain@1.74.1 with: targets: ${{ matrix.target }} @@ -120,7 +120,7 @@ jobs: ref: ${{ inputs.tag || env.GITHUB_REF }} - name: Setup toolchain - uses: dtolnay/rust-toolchain@1.73.0 + uses: dtolnay/rust-toolchain@1.74.1 with: targets: ${{ matrix.target }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 83e8e479181..d27fac0e039 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -79,6 +79,15 @@ jobs: - name: Install Yarn dependencies uses: ./.github/actions/setup + - 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: Query new noir version id: noir-version run: | @@ -100,6 +109,39 @@ jobs: git commit -m "chore(docs): cut new docs version for tag ${{ steps.noir-version.outputs.semver }}" git push + release-end: + name: Release End + runs-on: ubuntu-latest + # We want this job to always run (even if the dependant jobs fail) as we need apply changes to the sticky comment. + if: ${{ always() }} + + needs: + - release-please + - update-acvm-workspace-package-versions + - update-docs + + env: + # We treat any skipped or failing jobs as a failure for the workflow as a whole. + FAIL: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') || contains(needs.*.result, 'skipped') }} + + steps: + - name: Add warning to sticky comment + uses: marocchino/sticky-pull-request-comment@v2 + with: + # We need to specify the PR on which to make the comment as workflow is triggered by push. + number: ${{ fromJSON(needs.release-please.outputs.release-pr).number }} + # delete the comment in case failures have been fixed + delete: ${{ env.FAIL == false }} + message: "The release workflow has not completed successfully. Releasing now will result in a broken release" + + - name: Report overall success + run: | + if [[ $FAIL == true ]]; then + exit 1 + else + exit 0 + fi + build-binaries: name: Build binaries needs: [release-please] diff --git a/.github/workflows/test-js-packages.yml b/.github/workflows/test-js-packages.yml index b3908ee5d3e..db162e21269 100644 --- a/.github/workflows/test-js-packages.yml +++ b/.github/workflows/test-js-packages.yml @@ -22,7 +22,7 @@ jobs: uses: actions/checkout@v4 - name: Setup toolchain - uses: dtolnay/rust-toolchain@1.73.0 + uses: dtolnay/rust-toolchain@1.74.1 - uses: Swatinem/rust-cache@v2 with: @@ -55,7 +55,7 @@ jobs: uses: actions/checkout@v4 - name: Setup toolchain - uses: dtolnay/rust-toolchain@1.73.0 + uses: dtolnay/rust-toolchain@1.74.1 - uses: Swatinem/rust-cache@v2 with: @@ -66,9 +66,6 @@ jobs: - name: Install Yarn dependencies uses: ./.github/actions/setup - - name: Install wasm-opt - run: ./.github/scripts/wasm-opt-install.sh - - name: Build noirc_abi run: ./.github/scripts/noirc-abi-build.sh @@ -76,7 +73,9 @@ jobs: uses: actions/upload-artifact@v4 with: name: noirc_abi_wasm - path: ./tooling/noirc_abi_wasm/outputs/out/noirc_abi_wasm + path: | + ./tooling/noirc_abi_wasm/nodejs + ./tooling/noirc_abi_wasm/web retention-days: 10 @@ -89,7 +88,7 @@ jobs: uses: actions/checkout@v4 - name: Setup toolchain - uses: dtolnay/rust-toolchain@1.73.0 + uses: dtolnay/rust-toolchain@1.74.1 - uses: Swatinem/rust-cache@v2 with: @@ -100,9 +99,6 @@ jobs: - name: Install Yarn dependencies uses: ./.github/actions/setup - - name: Install wasm-opt - run: ./.github/scripts/wasm-opt-install.sh - - name: Build noir_js_types run: yarn workspace @noir-lang/types build @@ -127,7 +123,7 @@ jobs: uses: actions/checkout@v4 - name: Setup toolchain - uses: dtolnay/rust-toolchain@1.73.0 + uses: dtolnay/rust-toolchain@1.74.1 - uses: Swatinem/rust-cache@v2 with: @@ -138,9 +134,6 @@ jobs: - name: Install Yarn dependencies uses: ./.github/actions/setup - - name: Install wasm-opt - run: ./.github/scripts/wasm-opt-install.sh - - name: Build acvm_js run: ./.github/scripts/acvm_js-build.sh @@ -148,7 +141,9 @@ jobs: uses: actions/upload-artifact@v4 with: name: acvm-js - path: ./acvm-repo/acvm_js/outputs/out/acvm_js + path: | + ./acvm-repo/acvm_js/nodejs + ./acvm-repo/acvm_js/web retention-days: 3 test-acvm_js-node: @@ -193,7 +188,7 @@ jobs: uses: ./.github/actions/setup - name: Install Playwright - run: ./.github/scripts/playwright-install.sh + uses: ./.github/actions/install-playwright - name: Run browser tests run: yarn workspace @noir-lang/acvm_js test:browser @@ -404,6 +399,11 @@ jobs: - name: Checkout uses: actions/checkout@v4 + - name: Install `bb` + run: | + ./scripts/install_bb.sh + echo "$HOME/.bb/" >> $GITHUB_PATH + - name: Download nargo binary uses: actions/download-artifact@v4 with: @@ -453,7 +453,7 @@ jobs: test-integration-browser: name: Integration Tests (Browser) runs-on: ubuntu-latest - needs: [build-acvm-js, build-noir-wasm, build-nargo, build-noirc-abi] + needs: [build-acvm-js, build-noir-wasm, build-noirc-abi] timeout-minutes: 30 steps: @@ -495,6 +495,46 @@ jobs: run: | yarn test:browser + test-examples: + name: Example scripts + runs-on: ubuntu-latest + needs: [build-nargo] + timeout-minutes: 30 + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install Foundry + uses: foundry-rs/foundry-toolchain@v1.2.0 + + - name: Install `bb` + run: | + ./scripts/install_bb.sh + echo "$HOME/.bb/" >> $GITHUB_PATH + + - name: Download nargo binary + uses: actions/download-artifact@v4 + with: + name: nargo + path: ./nargo + + - name: Set nargo on PATH + run: | + nargo_binary="${{ github.workspace }}/nargo/nargo" + chmod +x $nargo_binary + echo "$(dirname $nargo_binary)" >> $GITHUB_PATH + export PATH="$PATH:$(dirname $nargo_binary)" + nargo -V + + - name: Run `prove_and_verify` + working-directory: ./examples/prove_and_verify + run: ./test.sh + + - name: Run `codegen_verifier` + working-directory: ./examples/codegen_verifier + run: ./test.sh + # This is a job which depends on all test jobs and reports the overall status. # This allows us to add/remove test jobs without having to update the required workflows. tests-end: @@ -512,6 +552,7 @@ jobs: - test-noir-codegen - test-integration-node - test-integration-browser + - test-examples steps: - name: Report overall success diff --git a/.github/workflows/test-rust-workspace-msrv.yml b/.github/workflows/test-rust-workspace-msrv.yml index 0b2855fa834..ae016169830 100644 --- a/.github/workflows/test-rust-workspace-msrv.yml +++ b/.github/workflows/test-rust-workspace-msrv.yml @@ -29,7 +29,7 @@ jobs: uses: actions/checkout@v4 - name: Setup toolchain - uses: dtolnay/rust-toolchain@1.73.0 + uses: dtolnay/rust-toolchain@1.74.1 with: targets: x86_64-unknown-linux-gnu @@ -72,7 +72,7 @@ jobs: - uses: actions/checkout@v4 - name: Setup toolchain - uses: dtolnay/rust-toolchain@1.73.0 + uses: dtolnay/rust-toolchain@1.74.1 with: targets: x86_64-unknown-linux-gnu @@ -88,7 +88,8 @@ jobs: - name: Run tests run: | cargo nextest run --archive-file nextest-archive.tar.zst \ - --partition count:${{ matrix.partition }}/4 + --partition count:${{ matrix.partition }}/4 \ + --no-fail-fast # This is a job which depends on all test jobs and reports the overall status. # This allows us to add/remove test jobs without having to update the required workflows. @@ -110,8 +111,12 @@ jobs: fi env: # We treat any cancelled, skipped or failing jobs as a failure for the workflow as a whole. - FAIL: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') || contains(needs.*.result, 'skipped') }} + FAIL: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'skipped') }} + - name: Checkout + if: ${{ failure() }} + uses: actions/checkout@v4 + # Raise an issue if the tests failed - name: Alert on failed publish uses: JasonEtco/create-an-issue@v2 @@ -122,4 +127,4 @@ jobs: WORKFLOW_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} with: update_existing: true - filename: .github/JS_PUBLISH_FAILED.md \ No newline at end of file + filename: .github/ACVM_NOT_PUBLISHABLE.md diff --git a/.github/workflows/test-rust-workspace.yml b/.github/workflows/test-rust-workspace.yml index 22684de3044..1f3ee5e2268 100644 --- a/.github/workflows/test-rust-workspace.yml +++ b/.github/workflows/test-rust-workspace.yml @@ -23,7 +23,7 @@ jobs: uses: actions/checkout@v4 - name: Setup toolchain - uses: dtolnay/rust-toolchain@1.73.0 + uses: dtolnay/rust-toolchain@1.74.1 with: targets: x86_64-unknown-linux-gnu @@ -59,7 +59,7 @@ jobs: - uses: actions/checkout@v4 - name: Setup toolchain - uses: dtolnay/rust-toolchain@1.73.0 + uses: dtolnay/rust-toolchain@1.74.1 with: targets: x86_64-unknown-linux-gnu @@ -75,7 +75,8 @@ jobs: - name: Run tests run: | cargo nextest run --archive-file nextest-archive.tar.zst \ - --partition count:${{ matrix.partition }}/4 + --partition count:${{ matrix.partition }}/4 \ + --no-fail-fast # This is a job which depends on all test jobs and reports the overall status. # This allows us to add/remove test jobs without having to update the required workflows. diff --git a/.gitignore b/.gitignore index 8d02d34d463..2c877a4d02c 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ examples/**/target/ examples/9 node_modules pkg/ +.idea # Yarn .pnp.* @@ -17,12 +18,6 @@ pkg/ # Noir.js tooling/noir_js/lib -# Nix stuff -**/outputs -result -.envrc.local -.direnv/ - # Nargo output *.proof *.acir @@ -50,8 +45,5 @@ tooling/noirc_abi_wasm/nodejs tooling/noirc_abi_wasm/web tooling/noir_js/lib -**/package.tgz -packages - # docs autogen build /docs/docs/noir_js/reference/ diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 8916585d7f1..83338327d88 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,4 +1,4 @@ { - ".": "0.24.0", - "acvm-repo": "0.40.0" -} \ No newline at end of file + ".": "0.30.0", + "acvm-repo": "0.46.0" +} diff --git a/.tokeignore b/.tokeignore new file mode 100644 index 00000000000..55f24e41dbd --- /dev/null +++ b/.tokeignore @@ -0,0 +1,12 @@ +docs +scripts + +# aztec_macros is explicitly considered OOS for Noir audit +aztec_macros + +# config files +*.toml +*.md +*.json +*.txt +*.config.mjs diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 1fb1def7ce1..efb17cb0085 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -4,7 +4,6 @@ // List of extensions which should be recommended for users of this workspace. "recommendations": [ "mkhl.direnv", - "jnoortheen.nix-ide", "rust-lang.rust-analyzer", "redhat.vscode-yaml", "esbenp.prettier-vscode", diff --git a/.vscode/settings.json b/.vscode/settings.json index 171d36f4e04..fb8ea527881 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -2,17 +2,6 @@ "direnv.restart.automatic": true, "redhat.telemetry.enabled": false, "yaml.recommendations.show": false, - "nix.serverPath": "nil", - "nix.enableLanguageServer": true, - "nix.serverSettings": { - "nil": { - "formatting": { - "command": [ - "nixpkgs-fmt" - ] - } - } - }, "yaml.schemas": { "https://json.schemastore.org/github-workflow.json": "${workspaceRoot}/.github/workflows/*.yml" }, diff --git a/.yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs b/.yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs new file mode 100644 index 00000000000..bc2ca19f116 --- /dev/null +++ b/.yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs @@ -0,0 +1,541 @@ +/* eslint-disable */ +//prettier-ignore +module.exports = { +name: "@yarnpkg/plugin-interactive-tools", +factory: function (require) { +var plugin=(()=>{var bF=Object.create;var D_=Object.defineProperty;var BF=Object.getOwnPropertyDescriptor;var UF=Object.getOwnPropertyNames;var jF=Object.getPrototypeOf,zF=Object.prototype.hasOwnProperty;var hi=(o=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(o,{get:(l,f)=>(typeof require<"u"?require:l)[f]}):o)(function(o){if(typeof require<"u")return require.apply(this,arguments);throw new Error('Dynamic require of "'+o+'" is not supported')});var nt=(o,l)=>()=>(l||o((l={exports:{}}).exports,l),l.exports),HF=(o,l)=>{for(var f in l)D_(o,f,{get:l[f],enumerable:!0})},j8=(o,l,f,h)=>{if(l&&typeof l=="object"||typeof l=="function")for(let E of UF(l))!zF.call(o,E)&&E!==f&&D_(o,E,{get:()=>l[E],enumerable:!(h=BF(l,E))||h.enumerable});return o};var V0=(o,l,f)=>(f=o!=null?bF(jF(o)):{},j8(l||!o||!o.__esModule?D_(f,"default",{value:o,enumerable:!0}):f,o)),qF=o=>j8(D_({},"__esModule",{value:!0}),o);var Py=nt((Xz,H8)=>{"use strict";var z8=Object.getOwnPropertySymbols,WF=Object.prototype.hasOwnProperty,VF=Object.prototype.propertyIsEnumerable;function GF(o){if(o==null)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(o)}function YF(){try{if(!Object.assign)return!1;var o=new String("abc");if(o[5]="de",Object.getOwnPropertyNames(o)[0]==="5")return!1;for(var l={},f=0;f<10;f++)l["_"+String.fromCharCode(f)]=f;var h=Object.getOwnPropertyNames(l).map(function(t){return l[t]});if(h.join("")!=="0123456789")return!1;var E={};return"abcdefghijklmnopqrst".split("").forEach(function(t){E[t]=t}),Object.keys(Object.assign({},E)).join("")==="abcdefghijklmnopqrst"}catch{return!1}}H8.exports=YF()?Object.assign:function(o,l){for(var f,h=GF(o),E,t=1;t{"use strict";var qE=Py(),Zf=typeof Symbol=="function"&&Symbol.for,Iy=Zf?Symbol.for("react.element"):60103,KF=Zf?Symbol.for("react.portal"):60106,XF=Zf?Symbol.for("react.fragment"):60107,QF=Zf?Symbol.for("react.strict_mode"):60108,JF=Zf?Symbol.for("react.profiler"):60114,ZF=Zf?Symbol.for("react.provider"):60109,$F=Zf?Symbol.for("react.context"):60110,eP=Zf?Symbol.for("react.forward_ref"):60112,tP=Zf?Symbol.for("react.suspense"):60113,nP=Zf?Symbol.for("react.memo"):60115,rP=Zf?Symbol.for("react.lazy"):60116,q8=typeof Symbol=="function"&&Symbol.iterator;function by(o){for(var l="https://reactjs.org/docs/error-decoder.html?invariant="+o,f=1;fw_.length&&w_.push(o)}function jE(o,l,f,h){var E=typeof o;(E==="undefined"||E==="boolean")&&(o=null);var t=!1;if(o===null)t=!0;else switch(E){case"string":case"number":t=!0;break;case"object":switch(o.$$typeof){case Iy:case KF:t=!0}}if(t)return f(h,o,l===""?"."+UE(o,0):l),1;if(t=0,l=l===""?".":l+":",Array.isArray(o))for(var N=0;N{"use strict";var aP="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED";tS.exports=aP});var XE=nt((Zz,oS)=>{"use strict";var KE=function(){};process.env.NODE_ENV!=="production"&&(rS=nS(),S_={},iS=Function.call.bind(Object.prototype.hasOwnProperty),KE=function(o){var l="Warning: "+o;typeof console<"u"&&console.error(l);try{throw new Error(l)}catch{}});var rS,S_,iS;function uS(o,l,f,h,E){if(process.env.NODE_ENV!=="production"){for(var t in o)if(iS(o,t)){var N;try{if(typeof o[t]!="function"){var F=Error((h||"React class")+": "+f+" type `"+t+"` is invalid; it must be a function, usually from the `prop-types` package, but received `"+typeof o[t]+"`.");throw F.name="Invariant Violation",F}N=o[t](l,t,h,f,null,rS)}catch(x){N=x}if(N&&!(N instanceof Error)&&KE((h||"React class")+": type specification of "+f+" `"+t+"` is invalid; the type checker function must return `null` or an `Error` but returned a "+typeof N+". You may have forgotten to pass an argument to the type checker creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and shape all require an argument)."),N instanceof Error&&!(N.message in S_)){S_[N.message]=!0;var k=E?E():"";KE("Failed "+f+" type: "+N.message+(k!=null?k:""))}}}}uS.resetWarningCache=function(){process.env.NODE_ENV!=="production"&&(S_={})};oS.exports=uS});var lS=nt(_u=>{"use strict";process.env.NODE_ENV!=="production"&&function(){"use strict";var o=Py(),l=XE(),f="16.13.1",h=typeof Symbol=="function"&&Symbol.for,E=h?Symbol.for("react.element"):60103,t=h?Symbol.for("react.portal"):60106,N=h?Symbol.for("react.fragment"):60107,F=h?Symbol.for("react.strict_mode"):60108,k=h?Symbol.for("react.profiler"):60114,x=h?Symbol.for("react.provider"):60109,j=h?Symbol.for("react.context"):60110,q=h?Symbol.for("react.concurrent_mode"):60111,V=h?Symbol.for("react.forward_ref"):60112,re=h?Symbol.for("react.suspense"):60113,y=h?Symbol.for("react.suspense_list"):60120,me=h?Symbol.for("react.memo"):60115,De=h?Symbol.for("react.lazy"):60116,ge=h?Symbol.for("react.block"):60121,ae=h?Symbol.for("react.fundamental"):60117,we=h?Symbol.for("react.responder"):60118,he=h?Symbol.for("react.scope"):60119,ve=typeof Symbol=="function"&&Symbol.iterator,ue="@@iterator";function Ae(Q){if(Q===null||typeof Q!="object")return null;var Se=ve&&Q[ve]||Q[ue];return typeof Se=="function"?Se:null}var ze={current:null},We={suspense:null},gt={current:null},_t=/^(.*)[\\\/]/;function Qe(Q,Se,Fe){var Le="";if(Se){var pt=Se.fileName,Yn=pt.replace(_t,"");if(/^index\./.test(Yn)){var Cn=pt.match(_t);if(Cn){var cr=Cn[1];if(cr){var Si=cr.replace(_t,"");Yn=Si+"/"+Yn}}}Le=" (at "+Yn+":"+Se.lineNumber+")"}else Fe&&(Le=" (created by "+Fe+")");return` + in `+(Q||"Unknown")+Le}var ot=1;function Ve(Q){return Q._status===ot?Q._result:null}function Pt(Q,Se,Fe){var Le=Se.displayName||Se.name||"";return Q.displayName||(Le!==""?Fe+"("+Le+")":Fe)}function Jt(Q){if(Q==null)return null;if(typeof Q.tag=="number"&&dt("Received an unexpected object in getComponentName(). This is likely a bug in React. Please file an issue."),typeof Q=="function")return Q.displayName||Q.name||null;if(typeof Q=="string")return Q;switch(Q){case N:return"Fragment";case t:return"Portal";case k:return"Profiler";case F:return"StrictMode";case re:return"Suspense";case y:return"SuspenseList"}if(typeof Q=="object")switch(Q.$$typeof){case j:return"Context.Consumer";case x:return"Context.Provider";case V:return Pt(Q,Q.render,"ForwardRef");case me:return Jt(Q.type);case ge:return Jt(Q.render);case De:{var Se=Q,Fe=Ve(Se);if(Fe)return Jt(Fe);break}}return null}var it={},J=null;function ce(Q){J=Q}it.getCurrentStack=null,it.getStackAddendum=function(){var Q="";if(J){var Se=Jt(J.type),Fe=J._owner;Q+=Qe(Se,J._source,Fe&&Jt(Fe.type))}var Le=it.getCurrentStack;return Le&&(Q+=Le()||""),Q};var Re={current:!1},le={ReactCurrentDispatcher:ze,ReactCurrentBatchConfig:We,ReactCurrentOwner:gt,IsSomeRendererActing:Re,assign:o};o(le,{ReactDebugCurrentFrame:it,ReactComponentTreeHook:{}});function He(Q){{for(var Se=arguments.length,Fe=new Array(Se>1?Se-1:0),Le=1;Le1?Se-1:0),Le=1;Le0&&typeof Fe[Fe.length-1]=="string"&&Fe[Fe.length-1].indexOf(` + in`)===0;if(!Le){var pt=le.ReactDebugCurrentFrame,Yn=pt.getStackAddendum();Yn!==""&&(Se+="%s",Fe=Fe.concat([Yn]))}var Cn=Fe.map(function(Ou){return""+Ou});Cn.unshift("Warning: "+Se),Function.prototype.apply.call(console[Q],console,Cn);try{var cr=0,Si="Warning: "+Se.replace(/%s/g,function(){return Fe[cr++]});throw new Error(Si)}catch{}}}var nn={};function an(Q,Se){{var Fe=Q.constructor,Le=Fe&&(Fe.displayName||Fe.name)||"ReactClass",pt=Le+"."+Se;if(nn[pt])return;dt("Can't call %s on a component that is not yet mounted. This is a no-op, but it might indicate a bug in your application. Instead, assign to `this.state` directly or define a `state = {};` class property with the desired state in the %s component.",Se,Le),nn[pt]=!0}}var On={isMounted:function(Q){return!1},enqueueForceUpdate:function(Q,Se,Fe){an(Q,"forceUpdate")},enqueueReplaceState:function(Q,Se,Fe,Le){an(Q,"replaceState")},enqueueSetState:function(Q,Se,Fe,Le){an(Q,"setState")}},lr={};Object.freeze(lr);function ln(Q,Se,Fe){this.props=Q,this.context=Se,this.refs=lr,this.updater=Fe||On}ln.prototype.isReactComponent={},ln.prototype.setState=function(Q,Se){if(!(typeof Q=="object"||typeof Q=="function"||Q==null))throw Error("setState(...): takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,Q,Se,"setState")},ln.prototype.forceUpdate=function(Q){this.updater.enqueueForceUpdate(this,Q,"forceUpdate")};{var Vt={isMounted:["isMounted","Instead, make sure to clean up subscriptions and pending requests in componentWillUnmount to prevent memory leaks."],replaceState:["replaceState","Refactor your code to use setState instead (see https://github.com/facebook/react/issues/3236)."]},Er=function(Q,Se){Object.defineProperty(ln.prototype,Q,{get:function(){He("%s(...) is deprecated in plain JavaScript React classes. %s",Se[0],Se[1])}})};for(var S in Vt)Vt.hasOwnProperty(S)&&Er(S,Vt[S])}function zt(){}zt.prototype=ln.prototype;function Xn(Q,Se,Fe){this.props=Q,this.context=Se,this.refs=lr,this.updater=Fe||On}var vr=Xn.prototype=new zt;vr.constructor=Xn,o(vr,ln.prototype),vr.isPureReactComponent=!0;function jr(){var Q={current:null};return Object.seal(Q),Q}var fr=Object.prototype.hasOwnProperty,zr={key:!0,ref:!0,__self:!0,__source:!0},Xt,Du,c0;c0={};function Ao(Q){if(fr.call(Q,"ref")){var Se=Object.getOwnPropertyDescriptor(Q,"ref").get;if(Se&&Se.isReactWarning)return!1}return Q.ref!==void 0}function Jo(Q){if(fr.call(Q,"key")){var Se=Object.getOwnPropertyDescriptor(Q,"key").get;if(Se&&Se.isReactWarning)return!1}return Q.key!==void 0}function Fs(Q,Se){var Fe=function(){Xt||(Xt=!0,dt("%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://fb.me/react-special-props)",Se))};Fe.isReactWarning=!0,Object.defineProperty(Q,"key",{get:Fe,configurable:!0})}function Zo(Q,Se){var Fe=function(){Du||(Du=!0,dt("%s: `ref` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://fb.me/react-special-props)",Se))};Fe.isReactWarning=!0,Object.defineProperty(Q,"ref",{get:Fe,configurable:!0})}function $o(Q){if(typeof Q.ref=="string"&>.current&&Q.__self&>.current.stateNode!==Q.__self){var Se=Jt(gt.current.type);c0[Se]||(dt('Component "%s" contains the string ref "%s". Support for string refs will be removed in a future major release. This case cannot be automatically converted to an arrow function. We ask you to manually fix this case by using useRef() or createRef() instead. Learn more about using refs safely here: https://fb.me/react-strict-mode-string-ref',Jt(gt.current.type),Q.ref),c0[Se]=!0)}}var qt=function(Q,Se,Fe,Le,pt,Yn,Cn){var cr={$$typeof:E,type:Q,key:Se,ref:Fe,props:Cn,_owner:Yn};return cr._store={},Object.defineProperty(cr._store,"validated",{configurable:!1,enumerable:!1,writable:!0,value:!1}),Object.defineProperty(cr,"_self",{configurable:!1,enumerable:!1,writable:!1,value:Le}),Object.defineProperty(cr,"_source",{configurable:!1,enumerable:!1,writable:!1,value:pt}),Object.freeze&&(Object.freeze(cr.props),Object.freeze(cr)),cr};function xi(Q,Se,Fe){var Le,pt={},Yn=null,Cn=null,cr=null,Si=null;if(Se!=null){Ao(Se)&&(Cn=Se.ref,$o(Se)),Jo(Se)&&(Yn=""+Se.key),cr=Se.__self===void 0?null:Se.__self,Si=Se.__source===void 0?null:Se.__source;for(Le in Se)fr.call(Se,Le)&&!zr.hasOwnProperty(Le)&&(pt[Le]=Se[Le])}var Ou=arguments.length-2;if(Ou===1)pt.children=Fe;else if(Ou>1){for(var ju=Array(Ou),zu=0;zu1){for(var wu=Array(zu),Ti=0;Ti is not supported and will be removed in a future major release. Did you mean to render instead?")),Fe.Provider},set:function(Cn){Fe.Provider=Cn}},_currentValue:{get:function(){return Fe._currentValue},set:function(Cn){Fe._currentValue=Cn}},_currentValue2:{get:function(){return Fe._currentValue2},set:function(Cn){Fe._currentValue2=Cn}},_threadCount:{get:function(){return Fe._threadCount},set:function(Cn){Fe._threadCount=Cn}},Consumer:{get:function(){return Le||(Le=!0,dt("Rendering is not supported and will be removed in a future major release. Did you mean to render instead?")),Fe.Consumer}}}),Fe.Consumer=Yn}return Fe._currentRenderer=null,Fe._currentRenderer2=null,Fe}function Wt(Q){var Se={$$typeof:De,_ctor:Q,_status:-1,_result:null};{var Fe,Le;Object.defineProperties(Se,{defaultProps:{configurable:!0,get:function(){return Fe},set:function(pt){dt("React.lazy(...): It is not supported to assign `defaultProps` to a lazy component import. Either specify them where the component is defined, or create a wrapping component around it."),Fe=pt,Object.defineProperty(Se,"defaultProps",{enumerable:!0})}},propTypes:{configurable:!0,get:function(){return Le},set:function(pt){dt("React.lazy(...): It is not supported to assign `propTypes` to a lazy component import. Either specify them where the component is defined, or create a wrapping component around it."),Le=pt,Object.defineProperty(Se,"propTypes",{enumerable:!0})}}})}return Se}function Ru(Q){return Q!=null&&Q.$$typeof===me?dt("forwardRef requires a render function but received a `memo` component. Instead of forwardRef(memo(...)), use memo(forwardRef(...))."):typeof Q!="function"?dt("forwardRef requires a render function but was given %s.",Q===null?"null":typeof Q):Q.length!==0&&Q.length!==2&&dt("forwardRef render functions accept exactly two parameters: props and ref. %s",Q.length===1?"Did you forget to use the ref parameter?":"Any additional parameter will be undefined."),Q!=null&&(Q.defaultProps!=null||Q.propTypes!=null)&&dt("forwardRef render functions do not support propTypes or defaultProps. Did you accidentally pass a React component?"),{$$typeof:V,render:Q}}function eu(Q){return typeof Q=="string"||typeof Q=="function"||Q===N||Q===q||Q===k||Q===F||Q===re||Q===y||typeof Q=="object"&&Q!==null&&(Q.$$typeof===De||Q.$$typeof===me||Q.$$typeof===x||Q.$$typeof===j||Q.$$typeof===V||Q.$$typeof===ae||Q.$$typeof===we||Q.$$typeof===he||Q.$$typeof===ge)}function Q0(Q,Se){return eu(Q)||dt("memo: The first argument must be a component. Instead received: %s",Q===null?"null":typeof Q),{$$typeof:me,type:Q,compare:Se===void 0?null:Se}}function Yi(){var Q=ze.current;if(Q===null)throw Error(`Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: +1. You might have mismatching versions of React and the renderer (such as React DOM) +2. You might be breaking the Rules of Hooks +3. You might have more than one copy of React in the same app +See https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem.`);return Q}function Xl(Q,Se){var Fe=Yi();if(Se!==void 0&&dt("useContext() second argument is reserved for future use in React. Passing it is not supported. You passed: %s.%s",Se,typeof Se=="number"&&Array.isArray(arguments[2])?` + +Did you call array.map(useContext)? Calling Hooks inside a loop is not supported. Learn more at https://fb.me/rules-of-hooks`:""),Q._context!==void 0){var Le=Q._context;Le.Consumer===Q?dt("Calling useContext(Context.Consumer) is not supported, may cause bugs, and will be removed in a future major release. Did you mean to call useContext(Context) instead?"):Le.Provider===Q&&dt("Calling useContext(Context.Provider) is not supported. Did you mean to call useContext(Context) instead?")}return Fe.useContext(Q,Se)}function ko(Q){var Se=Yi();return Se.useState(Q)}function li(Q,Se,Fe){var Le=Yi();return Le.useReducer(Q,Se,Fe)}function ao(Q){var Se=Yi();return Se.useRef(Q)}function Ql(Q,Se){var Fe=Yi();return Fe.useEffect(Q,Se)}function No(Q,Se){var Fe=Yi();return Fe.useLayoutEffect(Q,Se)}function Is(Q,Se){var Fe=Yi();return Fe.useCallback(Q,Se)}function $n(Q,Se){var Fe=Yi();return Fe.useMemo(Q,Se)}function tl(Q,Se,Fe){var Le=Yi();return Le.useImperativeHandle(Q,Se,Fe)}function fo(Q,Se){{var Fe=Yi();return Fe.useDebugValue(Q,Se)}}var I0;I0=!1;function Sl(){if(gt.current){var Q=Jt(gt.current.type);if(Q)return` + +Check the render method of \``+Q+"`."}return""}function Lo(Q){if(Q!==void 0){var Se=Q.fileName.replace(/^.*[\\\/]/,""),Fe=Q.lineNumber;return` + +Check your code at `+Se+":"+Fe+"."}return""}function St(Q){return Q!=null?Lo(Q.__source):""}var Bt={};function Hn(Q){var Se=Sl();if(!Se){var Fe=typeof Q=="string"?Q:Q.displayName||Q.name;Fe&&(Se=` + +Check the top-level render call using <`+Fe+">.")}return Se}function qr(Q,Se){if(!(!Q._store||Q._store.validated||Q.key!=null)){Q._store.validated=!0;var Fe=Hn(Se);if(!Bt[Fe]){Bt[Fe]=!0;var Le="";Q&&Q._owner&&Q._owner!==gt.current&&(Le=" It was passed a child from "+Jt(Q._owner.type)+"."),ce(Q),dt('Each child in a list should have a unique "key" prop.%s%s See https://fb.me/react-warning-keys for more information.',Fe,Le),ce(null)}}}function Ki(Q,Se){if(typeof Q=="object"){if(Array.isArray(Q))for(var Fe=0;Fe",pt=" Did you accidentally export a JSX literal instead of a component?"):Cn=typeof Q,dt("React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: %s.%s",Cn,pt)}var cr=xi.apply(this,arguments);if(cr==null)return cr;if(Le)for(var Si=2;Si{"use strict";process.env.NODE_ENV==="production"?QE.exports=eS():QE.exports=lS()});var sS=nt((Wv,By)=>{(function(){var o,l="4.17.21",f=200,h="Unsupported core-js use. Try https://npms.io/search?q=ponyfill.",E="Expected a function",t="Invalid `variable` option passed into `_.template`",N="__lodash_hash_undefined__",F=500,k="__lodash_placeholder__",x=1,j=2,q=4,V=1,re=2,y=1,me=2,De=4,ge=8,ae=16,we=32,he=64,ve=128,ue=256,Ae=512,ze=30,We="...",gt=800,_t=16,Qe=1,ot=2,Ve=3,Pt=1/0,Jt=9007199254740991,it=17976931348623157e292,J=0/0,ce=4294967295,Re=ce-1,le=ce>>>1,He=[["ary",ve],["bind",y],["bindKey",me],["curry",ge],["curryRight",ae],["flip",Ae],["partial",we],["partialRight",he],["rearg",ue]],dt="[object Arguments]",At="[object Array]",nn="[object AsyncFunction]",an="[object Boolean]",On="[object Date]",lr="[object DOMException]",ln="[object Error]",Vt="[object Function]",Er="[object GeneratorFunction]",S="[object Map]",zt="[object Number]",Xn="[object Null]",vr="[object Object]",jr="[object Promise]",fr="[object Proxy]",zr="[object RegExp]",Xt="[object Set]",Du="[object String]",c0="[object Symbol]",Ao="[object Undefined]",Jo="[object WeakMap]",Fs="[object WeakSet]",Zo="[object ArrayBuffer]",$o="[object DataView]",qt="[object Float32Array]",xi="[object Float64Array]",lu="[object Int8Array]",vi="[object Int16Array]",Dr="[object Int32Array]",el="[object Uint8Array]",Y0="[object Uint8ClampedArray]",Bu="[object Uint16Array]",K0="[object Uint32Array]",Kr=/\b__p \+= '';/g,Oo=/\b(__p \+=) '' \+/g,Mo=/(__e\(.*?\)|\b__t\)) \+\n'';/g,F0=/&(?:amp|lt|gt|quot|#39);/g,su=/[&<>"']/g,ki=RegExp(F0.source),Ps=RegExp(su.source),Kl=/<%-([\s\S]+?)%>/g,P0=/<%([\s\S]+?)%>/g,d0=/<%=([\s\S]+?)%>/g,Hr=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,Ri=/^\w*$/,X0=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,mi=/[\\^$.*+?()[\]{}|]/g,en=RegExp(mi.source),In=/^\s+/,Ai=/\s/,yi=/\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,Wt=/\{\n\/\* \[wrapped with (.+)\] \*/,Ru=/,? & /,eu=/[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g,Q0=/[()=,{}\[\]\/\s]/,Yi=/\\(\\)?/g,Xl=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,ko=/\w*$/,li=/^[-+]0x[0-9a-f]+$/i,ao=/^0b[01]+$/i,Ql=/^\[object .+?Constructor\]$/,No=/^0o[0-7]+$/i,Is=/^(?:0|[1-9]\d*)$/,$n=/[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g,tl=/($^)/,fo=/['\n\r\u2028\u2029\\]/g,I0="\\ud800-\\udfff",Sl="\\u0300-\\u036f",Lo="\\ufe20-\\ufe2f",St="\\u20d0-\\u20ff",Bt=Sl+Lo+St,Hn="\\u2700-\\u27bf",qr="a-z\\xdf-\\xf6\\xf8-\\xff",Ki="\\xac\\xb1\\xd7\\xf7",Xr="\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf",Au="\\u2000-\\u206f",p0=" \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000",Ni="A-Z\\xc0-\\xd6\\xd8-\\xde",h0="\\ufe0e\\ufe0f",hs=Ki+Xr+Au+p0,Ct="['\u2019]",co="["+I0+"]",nl="["+hs+"]",Jl="["+Bt+"]",Uu="\\d+",vs="["+Hn+"]",b0="["+qr+"]",Q="[^"+I0+hs+Uu+Hn+qr+Ni+"]",Se="\\ud83c[\\udffb-\\udfff]",Fe="(?:"+Jl+"|"+Se+")",Le="[^"+I0+"]",pt="(?:\\ud83c[\\udde6-\\uddff]){2}",Yn="[\\ud800-\\udbff][\\udc00-\\udfff]",Cn="["+Ni+"]",cr="\\u200d",Si="(?:"+b0+"|"+Q+")",Ou="(?:"+Cn+"|"+Q+")",ju="(?:"+Ct+"(?:d|ll|m|re|s|t|ve))?",zu="(?:"+Ct+"(?:D|LL|M|RE|S|T|VE))?",wu=Fe+"?",Ti="["+h0+"]?",Fo="(?:"+cr+"(?:"+[Le,pt,Yn].join("|")+")"+Ti+wu+")*",Mu="\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])",po="\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])",Hu=Ti+wu+Fo,Pa="(?:"+[vs,pt,Yn].join("|")+")"+Hu,v0="(?:"+[Le+Jl+"?",Jl,pt,Yn,co].join("|")+")",ia=RegExp(Ct,"g"),J0=RegExp(Jl,"g"),ua=RegExp(Se+"(?="+Se+")|"+v0+Hu,"g"),Ia=RegExp([Cn+"?"+b0+"+"+ju+"(?="+[nl,Cn,"$"].join("|")+")",Ou+"+"+zu+"(?="+[nl,Cn+Si,"$"].join("|")+")",Cn+"?"+Si+"+"+ju,Cn+"+"+zu,po,Mu,Uu,Pa].join("|"),"g"),ms=RegExp("["+cr+I0+Bt+h0+"]"),S0=/[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/,Qn=["Array","Buffer","DataView","Date","Error","Float32Array","Float64Array","Function","Int8Array","Int16Array","Int32Array","Map","Math","Object","Promise","RegExp","Set","String","Symbol","TypeError","Uint8Array","Uint8ClampedArray","Uint16Array","Uint32Array","WeakMap","_","clearTimeout","isFinite","parseInt","setTimeout"],ac=-1,si={};si[qt]=si[xi]=si[lu]=si[vi]=si[Dr]=si[el]=si[Y0]=si[Bu]=si[K0]=!0,si[dt]=si[At]=si[Zo]=si[an]=si[$o]=si[On]=si[ln]=si[Vt]=si[S]=si[zt]=si[vr]=si[zr]=si[Xt]=si[Du]=si[Jo]=!1;var Jr={};Jr[dt]=Jr[At]=Jr[Zo]=Jr[$o]=Jr[an]=Jr[On]=Jr[qt]=Jr[xi]=Jr[lu]=Jr[vi]=Jr[Dr]=Jr[S]=Jr[zt]=Jr[vr]=Jr[zr]=Jr[Xt]=Jr[Du]=Jr[c0]=Jr[el]=Jr[Y0]=Jr[Bu]=Jr[K0]=!0,Jr[ln]=Jr[Vt]=Jr[Jo]=!1;var Zl={\u00C0:"A",\u00C1:"A",\u00C2:"A",\u00C3:"A",\u00C4:"A",\u00C5:"A",\u00E0:"a",\u00E1:"a",\u00E2:"a",\u00E3:"a",\u00E4:"a",\u00E5:"a",\u00C7:"C",\u00E7:"c",\u00D0:"D",\u00F0:"d",\u00C8:"E",\u00C9:"E",\u00CA:"E",\u00CB:"E",\u00E8:"e",\u00E9:"e",\u00EA:"e",\u00EB:"e",\u00CC:"I",\u00CD:"I",\u00CE:"I",\u00CF:"I",\u00EC:"i",\u00ED:"i",\u00EE:"i",\u00EF:"i",\u00D1:"N",\u00F1:"n",\u00D2:"O",\u00D3:"O",\u00D4:"O",\u00D5:"O",\u00D6:"O",\u00D8:"O",\u00F2:"o",\u00F3:"o",\u00F4:"o",\u00F5:"o",\u00F6:"o",\u00F8:"o",\u00D9:"U",\u00DA:"U",\u00DB:"U",\u00DC:"U",\u00F9:"u",\u00FA:"u",\u00FB:"u",\u00FC:"u",\u00DD:"Y",\u00FD:"y",\u00FF:"y",\u00C6:"Ae",\u00E6:"ae",\u00DE:"Th",\u00FE:"th",\u00DF:"ss",\u0100:"A",\u0102:"A",\u0104:"A",\u0101:"a",\u0103:"a",\u0105:"a",\u0106:"C",\u0108:"C",\u010A:"C",\u010C:"C",\u0107:"c",\u0109:"c",\u010B:"c",\u010D:"c",\u010E:"D",\u0110:"D",\u010F:"d",\u0111:"d",\u0112:"E",\u0114:"E",\u0116:"E",\u0118:"E",\u011A:"E",\u0113:"e",\u0115:"e",\u0117:"e",\u0119:"e",\u011B:"e",\u011C:"G",\u011E:"G",\u0120:"G",\u0122:"G",\u011D:"g",\u011F:"g",\u0121:"g",\u0123:"g",\u0124:"H",\u0126:"H",\u0125:"h",\u0127:"h",\u0128:"I",\u012A:"I",\u012C:"I",\u012E:"I",\u0130:"I",\u0129:"i",\u012B:"i",\u012D:"i",\u012F:"i",\u0131:"i",\u0134:"J",\u0135:"j",\u0136:"K",\u0137:"k",\u0138:"k",\u0139:"L",\u013B:"L",\u013D:"L",\u013F:"L",\u0141:"L",\u013A:"l",\u013C:"l",\u013E:"l",\u0140:"l",\u0142:"l",\u0143:"N",\u0145:"N",\u0147:"N",\u014A:"N",\u0144:"n",\u0146:"n",\u0148:"n",\u014B:"n",\u014C:"O",\u014E:"O",\u0150:"O",\u014D:"o",\u014F:"o",\u0151:"o",\u0154:"R",\u0156:"R",\u0158:"R",\u0155:"r",\u0157:"r",\u0159:"r",\u015A:"S",\u015C:"S",\u015E:"S",\u0160:"S",\u015B:"s",\u015D:"s",\u015F:"s",\u0161:"s",\u0162:"T",\u0164:"T",\u0166:"T",\u0163:"t",\u0165:"t",\u0167:"t",\u0168:"U",\u016A:"U",\u016C:"U",\u016E:"U",\u0170:"U",\u0172:"U",\u0169:"u",\u016B:"u",\u016D:"u",\u016F:"u",\u0171:"u",\u0173:"u",\u0174:"W",\u0175:"w",\u0176:"Y",\u0177:"y",\u0178:"Y",\u0179:"Z",\u017B:"Z",\u017D:"Z",\u017A:"z",\u017C:"z",\u017E:"z",\u0132:"IJ",\u0133:"ij",\u0152:"Oe",\u0153:"oe",\u0149:"'n",\u017F:"s"},oa={"&":"&","<":"<",">":">",'"':""","'":"'"},pf={"&":"&","<":"<",">":">",""":'"',"'":"'"},bs={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},ba=parseFloat,Bs=parseInt,m0=typeof global=="object"&&global&&global.Object===Object&&global,Us=typeof self=="object"&&self&&self.Object===Object&&self,zi=m0||Us||Function("return this")(),U=typeof Wv=="object"&&Wv&&!Wv.nodeType&&Wv,H=U&&typeof By=="object"&&By&&!By.nodeType&&By,Y=H&&H.exports===U,ee=Y&&m0.process,Ce=function(){try{var xe=H&&H.require&&H.require("util").types;return xe||ee&&ee.binding&&ee.binding("util")}catch{}}(),_e=Ce&&Ce.isArrayBuffer,Oe=Ce&&Ce.isDate,$=Ce&&Ce.isMap,Ne=Ce&&Ce.isRegExp,Je=Ce&&Ce.isSet,vt=Ce&&Ce.isTypedArray;function oe(xe,tt,Ke){switch(Ke.length){case 0:return xe.call(tt);case 1:return xe.call(tt,Ke[0]);case 2:return xe.call(tt,Ke[0],Ke[1]);case 3:return xe.call(tt,Ke[0],Ke[1],Ke[2])}return xe.apply(tt,Ke)}function qe(xe,tt,Ke,Yt){for(var Kt=-1,pr=xe==null?0:xe.length;++Kt-1}function rn(xe,tt,Ke){for(var Yt=-1,Kt=xe==null?0:xe.length;++Yt-1;);return Ke}function Tl(xe,tt){for(var Ke=xe.length;Ke--&&wt(tt,xe[Ke],0)>-1;);return Ke}function vf(xe,tt){for(var Ke=xe.length,Yt=0;Ke--;)xe[Ke]===tt&&++Yt;return Yt}var Io=Jn(Zl),ys=Jn(oa);function js(xe){return"\\"+bs[xe]}function bo(xe,tt){return xe==null?o:xe[tt]}function Bo(xe){return ms.test(xe)}function gs(xe){return S0.test(xe)}function Xu(xe){for(var tt,Ke=[];!(tt=xe.next()).done;)Ke.push(tt.value);return Ke}function Su(xe){var tt=-1,Ke=Array(xe.size);return xe.forEach(function(Yt,Kt){Ke[++tt]=[Kt,Yt]}),Ke}function _i(xe,tt){return function(Ke){return xe(tt(Ke))}}function C0(xe,tt){for(var Ke=-1,Yt=xe.length,Kt=0,pr=[];++Ke-1}function fa(p,m){var R=this.__data__,I=ts(R,p);return I<0?(++this.size,R.push([p,m])):R[I][1]=m,this}io.prototype.clear=Ba,io.prototype.delete=_f,io.prototype.get=fc,io.prototype.has=Ds,io.prototype.set=fa;function U0(p){var m=-1,R=p==null?0:p.length;for(this.clear();++m=m?p:m)),p}function j0(p,m,R,I,W,te){var pe,Ee=m&x,be=m&j,Dt=m&q;if(R&&(pe=W?R(p,I,W,te):R(p)),pe!==o)return pe;if(!Iu(p))return p;var Tt=tr(p);if(Tt){if(pe=Cs(p),!Ee)return iu(p,pe)}else{var Ot=Pu(p),on=Ot==Vt||Ot==Er;if(Js(p))return vc(p,Ee);if(Ot==vr||Ot==dt||on&&!W){if(pe=be||on?{}:Ec(p),!Ee)return be?ns(p,ol(pe,p)):u0(p,Ef(pe,p))}else{if(!Jr[Ot])return W?p:{};pe=Th(p,Ot,Ee)}}te||(te=new ul);var Mn=te.get(p);if(Mn)return Mn;te.set(p,pe),Pd(p)?p.forEach(function(ar){pe.add(j0(ar,m,R,ar,p,te))}):_p(p)&&p.forEach(function(ar,ri){pe.set(ri,j0(ar,m,R,ri,p,te))});var rr=Dt?be?sr:r1:be?dn:N0,br=Tt?o:rr(p);return rt(br||p,function(ar,ri){br&&(ri=ar,ar=p[ri]),Ss(pe,ri,j0(ar,m,R,ri,p,te))}),pe}function Df(p){var m=N0(p);return function(R){return Wc(R,p,m)}}function Wc(p,m,R){var I=R.length;if(p==null)return!I;for(p=bn(p);I--;){var W=R[I],te=m[W],pe=p[W];if(pe===o&&!(W in p)||!te(pe))return!1}return!0}function dc(p,m,R){if(typeof p!="function")throw new $r(E);return Qa(function(){p.apply(o,R)},m)}function Ol(p,m,R,I){var W=-1,te=sn,pe=!0,Ee=p.length,be=[],Dt=m.length;if(!Ee)return be;R&&(m=Ft(m,gi(R))),I?(te=rn,pe=!1):m.length>=f&&(te=rl,pe=!1,m=new yo(m));e:for(;++WW?0:W+R),I=I===o||I>W?W:Mr(I),I<0&&(I+=W),I=R>I?0:Dp(I);R0&&R(Ee)?m>1?Wi(Ee,m-1,R,I,W):Dn(W,Ee):I||(W[W.length]=Ee)}return W}var _=yc(),g=yc(!0);function A(p,m){return p&&_(p,m,N0)}function P(p,m){return p&&g(p,m,N0)}function B(p,m){return bt(m,function(R){return xa(p[R])})}function Z(p,m){m=Ws(m,p);for(var R=0,I=m.length;p!=null&&Rm}function Nt(p,m){return p!=null&&ui.call(p,m)}function xr(p,m){return p!=null&&m in bn(p)}function r0(p,m,R){return p>=Kn(m,R)&&p=120&&Tt.length>=120)?new yo(pe&&Tt):o}Tt=p[0];var Ot=-1,on=Ee[0];e:for(;++Ot-1;)Ee!==p&&O0.call(Ee,be,1),O0.call(p,be,1);return p}function sd(p,m){for(var R=p?m.length:0,I=R-1;R--;){var W=m[R];if(R==I||W!==te){var te=W;Do(W)?O0.call(p,W,1):x2(p,W)}}return p}function ad(p,m){return p+Es(_0()*(m-p+1))}function S2(p,m,R,I){for(var W=-1,te=ei(Zu((m-p)/(R||1)),0),pe=Ke(te);te--;)pe[I?te:++W]=p,p+=R;return pe}function Yc(p,m){var R="";if(!p||m<1||m>Jt)return R;do m%2&&(R+=p),m=Es(m/2),m&&(p+=p);while(m);return R}function Ir(p,m){return l1(L2(p,m,l0),p+"")}function fd(p){return za(Nc(p))}function cd(p,m){var R=Nc(p);return wc(R,n0(m,0,R.length))}function Ga(p,m,R,I){if(!Iu(p))return p;m=Ws(m,p);for(var W=-1,te=m.length,pe=te-1,Ee=p;Ee!=null&&++WW?0:W+m),R=R>W?W:R,R<0&&(R+=W),W=m>R?0:R-m>>>0,m>>>=0;for(var te=Ke(W);++I>>1,pe=p[te];pe!==null&&!Bl(pe)&&(R?pe<=m:pe=f){var Dt=m?null:am(p);if(Dt)return $0(Dt);pe=!1,W=rl,be=new yo}else be=m?[]:Ee;e:for(;++I=I?p:sl(p,m,R)}var Zc=_s||function(p){return zi.clearTimeout(p)};function vc(p,m){if(m)return p.slice();var R=p.length,I=qi?qi(R):new p.constructor(R);return p.copy(I),I}function mc(p){var m=new p.constructor(p.byteLength);return new A0(m).set(new A0(p)),m}function pd(p,m){var R=m?mc(p.buffer):p.buffer;return new p.constructor(R,p.byteOffset,p.byteLength)}function Eh(p){var m=new p.constructor(p.source,ko.exec(p));return m.lastIndex=p.lastIndex,m}function Tf(p){return Ar?bn(Ar.call(p)):{}}function $c(p,m){var R=m?mc(p.buffer):p.buffer;return new p.constructor(R,p.byteOffset,p.length)}function Dh(p,m){if(p!==m){var R=p!==o,I=p===null,W=p===p,te=Bl(p),pe=m!==o,Ee=m===null,be=m===m,Dt=Bl(m);if(!Ee&&!Dt&&!te&&p>m||te&&pe&&be&&!Ee&&!Dt||I&&pe&&be||!R&&be||!W)return 1;if(!I&&!te&&!Dt&&p=Ee)return be;var Dt=R[I];return be*(Dt=="desc"?-1:1)}}return p.index-m.index}function Vs(p,m,R,I){for(var W=-1,te=p.length,pe=R.length,Ee=-1,be=m.length,Dt=ei(te-pe,0),Tt=Ke(be+Dt),Ot=!I;++Ee1?R[W-1]:o,pe=W>2?R[2]:o;for(te=p.length>3&&typeof te=="function"?(W--,te):o,pe&&lo(R[0],R[1],pe)&&(te=W<3?o:te,W=1),m=bn(m);++I-1?W[te?m[pe]:pe]:o}}function t1(p){return cl(function(m){var R=m.length,I=R,W=Wr.prototype.thru;for(p&&m.reverse();I--;){var te=m[I];if(typeof te!="function")throw new $r(E);if(W&&!pe&&qo(te)=="wrapper")var pe=new Wr([],!0)}for(I=pe?I:R;++I1&&fi.reverse(),Tt&&beEe))return!1;var Dt=te.get(p),Tt=te.get(m);if(Dt&&Tt)return Dt==m&&Tt==p;var Ot=-1,on=!0,Mn=R&re?new yo:o;for(te.set(p,m),te.set(m,p);++Ot1?"& ":"")+m[I],m=m.join(R>2?", ":" "),p.replace(yi,`{ +/* [wrapped with `+m+`] */ +`)}function is(p){return tr(p)||pl(p)||!!(vo&&p&&p[vo])}function Do(p,m){var R=typeof p;return m=m==null?Jt:m,!!m&&(R=="number"||R!="symbol"&&Is.test(p))&&p>-1&&p%1==0&&p0){if(++m>=gt)return arguments[0]}else m=0;return p.apply(o,arguments)}}function wc(p,m){var R=-1,I=p.length,W=I-1;for(m=m===o?I:m;++R1?p[m-1]:o;return R=typeof R=="function"?(p.pop(),R):o,wd(p,R)});function zh(p){var m=K(p);return m.__chain__=!0,m}function Hh(p,m){return m(p),p}function g1(p,m){return m(p)}var J2=cl(function(p){var m=p.length,R=m?p[0]:0,I=this.__wrapped__,W=function(te){return qa(te,p)};return m>1||this.__actions__.length||!(I instanceof ft)||!Do(R)?this.thru(W):(I=I.slice(R,+R+(m?1:0)),I.__actions__.push({func:g1,args:[W],thisArg:o}),new Wr(I,this.__chain__).thru(function(te){return m&&!te.length&&te.push(o),te}))});function qh(){return zh(this)}function Z2(){return new Wr(this.value(),this.__chain__)}function Wh(){this.__values__===o&&(this.__values__=fv(this.value()));var p=this.__index__>=this.__values__.length,m=p?o:this.__values__[this.__index__++];return{done:p,value:m}}function _m(){return this}function Em(p){for(var m,R=this;R instanceof ni;){var I=P2(R);I.__index__=0,I.__values__=o,m?W.__wrapped__=I:m=I;var W=I;R=R.__wrapped__}return W.__wrapped__=p,m}function Pf(){var p=this.__wrapped__;if(p instanceof ft){var m=p;return this.__actions__.length&&(m=new ft(this)),m=m.reverse(),m.__actions__.push({func:g1,args:[W2],thisArg:o}),new Wr(m,this.__chain__)}return this.thru(W2)}function If(){return _h(this.__wrapped__,this.__actions__)}var Sd=Ya(function(p,m,R){ui.call(p,R)?++p[R]:Vu(p,R,1)});function Dm(p,m,R){var I=tr(p)?kt:ud;return R&&lo(p,m,R)&&(m=o),I(p,Vn(m,3))}function $2(p,m){var R=tr(p)?bt:Vc;return R(p,Vn(m,3))}var Td=Nl(U2),ep=Nl(a1);function Vh(p,m){return Wi(_1(p,m),1)}function tp(p,m){return Wi(_1(p,m),Pt)}function Gh(p,m,R){return R=R===o?1:Mr(R),Wi(_1(p,m),R)}function Yh(p,m){var R=tr(p)?rt:Ts;return R(p,Vn(m,3))}function np(p,m){var R=tr(p)?xt:da;return R(p,Vn(m,3))}var wm=Ya(function(p,m,R){ui.call(p,R)?p[R].push(m):Vu(p,R,[m])});function Sm(p,m,R,I){p=hl(p)?p:Nc(p),R=R&&!I?Mr(R):0;var W=p.length;return R<0&&(R=ei(W+R,0)),S1(p)?R<=W&&p.indexOf(m,R)>-1:!!W&&wt(p,m,R)>-1}var Tm=Ir(function(p,m,R){var I=-1,W=typeof m=="function",te=hl(p)?Ke(p.length):[];return Ts(p,function(pe){te[++I]=W?oe(m,pe,R):Ml(pe,m,R)}),te}),Kh=Ya(function(p,m,R){Vu(p,R,m)});function _1(p,m){var R=tr(p)?Ft:D2;return R(p,Vn(m,3))}function Cm(p,m,R,I){return p==null?[]:(tr(m)||(m=m==null?[]:[m]),R=I?o:R,tr(R)||(R=R==null?[]:[R]),go(p,m,R))}var rp=Ya(function(p,m,R){p[R?0:1].push(m)},function(){return[[],[]]});function ip(p,m,R){var I=tr(p)?dr:wr,W=arguments.length<3;return I(p,Vn(m,4),R,W,Ts)}function xm(p,m,R){var I=tr(p)?er:wr,W=arguments.length<3;return I(p,Vn(m,4),R,W,da)}function Rm(p,m){var R=tr(p)?bt:Vc;return R(p,Rd(Vn(m,3)))}function Xh(p){var m=tr(p)?za:fd;return m(p)}function Am(p,m,R){(R?lo(p,m,R):m===o)?m=1:m=Mr(m);var I=tr(p)?Ha:cd;return I(p,m)}function Om(p){var m=tr(p)?ca:ll;return m(p)}function up(p){if(p==null)return 0;if(hl(p))return S1(p)?tu(p):p.length;var m=Pu(p);return m==S||m==Xt?p.size:Wa(p).length}function op(p,m,R){var I=tr(p)?Cr:yh;return R&&lo(p,m,R)&&(m=o),I(p,Vn(m,3))}var Ta=Ir(function(p,m){if(p==null)return[];var R=m.length;return R>1&&lo(p,m[0],m[1])?m=[]:R>2&&lo(m[0],m[1],m[2])&&(m=[m[0]]),go(p,Wi(m,1),[])}),E1=aa||function(){return zi.Date.now()};function lp(p,m){if(typeof m!="function")throw new $r(E);return p=Mr(p),function(){if(--p<1)return m.apply(this,arguments)}}function Qh(p,m,R){return m=R?o:m,m=p&&m==null?p.length:m,hn(p,ve,o,o,o,o,m)}function Cd(p,m){var R;if(typeof m!="function")throw new $r(E);return p=Mr(p),function(){return--p>0&&(R=m.apply(this,arguments)),p<=1&&(m=o),R}}var D1=Ir(function(p,m,R){var I=y;if(R.length){var W=C0(R,yr(D1));I|=we}return hn(p,I,m,R,W)}),Jh=Ir(function(p,m,R){var I=y|me;if(R.length){var W=C0(R,yr(Jh));I|=we}return hn(m,I,p,R,W)});function sp(p,m,R){m=R?o:m;var I=hn(p,ge,o,o,o,o,o,m);return I.placeholder=sp.placeholder,I}function Zh(p,m,R){m=R?o:m;var I=hn(p,ae,o,o,o,o,o,m);return I.placeholder=Zh.placeholder,I}function ap(p,m,R){var I,W,te,pe,Ee,be,Dt=0,Tt=!1,Ot=!1,on=!0;if(typeof p!="function")throw new $r(E);m=vl(m)||0,Iu(R)&&(Tt=!!R.leading,Ot="maxWait"in R,te=Ot?ei(vl(R.maxWait)||0,m):te,on="trailing"in R?!!R.trailing:on);function Mn(s0){var Os=I,Co=W;return I=W=o,Dt=s0,pe=p.apply(Co,Os),pe}function rr(s0){return Dt=s0,Ee=Qa(ri,m),Tt?Mn(s0):pe}function br(s0){var Os=s0-be,Co=s0-Dt,kv=m-Os;return Ot?Kn(kv,te-Co):kv}function ar(s0){var Os=s0-be,Co=s0-Dt;return be===o||Os>=m||Os<0||Ot&&Co>=te}function ri(){var s0=E1();if(ar(s0))return fi(s0);Ee=Qa(ri,br(s0))}function fi(s0){return Ee=o,on&&I?Mn(s0):(I=W=o,pe)}function zl(){Ee!==o&&Zc(Ee),Dt=0,I=be=W=Ee=o}function Zi(){return Ee===o?pe:fi(E1())}function so(){var s0=E1(),Os=ar(s0);if(I=arguments,W=this,be=s0,Os){if(Ee===o)return rr(be);if(Ot)return Zc(Ee),Ee=Qa(ri,m),Mn(be)}return Ee===o&&(Ee=Qa(ri,m)),pe}return so.cancel=zl,so.flush=Zi,so}var $h=Ir(function(p,m){return dc(p,1,m)}),ev=Ir(function(p,m,R){return dc(p,vl(m)||0,R)});function fp(p){return hn(p,Ae)}function xd(p,m){if(typeof p!="function"||m!=null&&typeof m!="function")throw new $r(E);var R=function(){var I=arguments,W=m?m.apply(this,I):I[0],te=R.cache;if(te.has(W))return te.get(W);var pe=p.apply(this,I);return R.cache=te.set(W,pe)||te,pe};return R.cache=new(xd.Cache||U0),R}xd.Cache=U0;function Rd(p){if(typeof p!="function")throw new $r(E);return function(){var m=arguments;switch(m.length){case 0:return!p.call(this);case 1:return!p.call(this,m[0]);case 2:return!p.call(this,m[0],m[1]);case 3:return!p.call(this,m[0],m[1],m[2])}return!p.apply(this,m)}}function H0(p){return Cd(2,p)}var Ad=O2(function(p,m){m=m.length==1&&tr(m[0])?Ft(m[0],gi(Vn())):Ft(Wi(m,1),gi(Vn()));var R=m.length;return Ir(function(I){for(var W=-1,te=Kn(I.length,R);++W=m}),pl=i0(function(){return arguments}())?i0:function(p){return Gu(p)&&ui.call(p,"callee")&&!B0.call(p,"callee")},tr=Ke.isArray,Qs=_e?gi(_e):Ge;function hl(p){return p!=null&&Ld(p.length)&&!xa(p)}function o0(p){return Gu(p)&&hl(p)}function rv(p){return p===!0||p===!1||Gu(p)&&yt(p)==an}var Js=no||Bp,vp=Oe?gi(Oe):je;function Fm(p){return Gu(p)&&p.nodeType===1&&!Cc(p)}function iv(p){if(p==null)return!0;if(hl(p)&&(tr(p)||typeof p=="string"||typeof p.splice=="function"||Js(p)||Ra(p)||pl(p)))return!p.length;var m=Pu(p);if(m==S||m==Xt)return!p.size;if(Nf(p))return!Wa(p).length;for(var R in p)if(ui.call(p,R))return!1;return!0}function mp(p,m){return st(p,m)}function Pm(p,m,R){R=typeof R=="function"?R:o;var I=R?R(p,m):o;return I===o?st(p,m,o,R):!!I}function yp(p){if(!Gu(p))return!1;var m=yt(p);return m==ln||m==lr||typeof p.message=="string"&&typeof p.name=="string"&&!Cc(p)}function Tc(p){return typeof p=="number"&&nu(p)}function xa(p){if(!Iu(p))return!1;var m=yt(p);return m==Vt||m==Er||m==nn||m==fr}function gp(p){return typeof p=="number"&&p==Mr(p)}function Ld(p){return typeof p=="number"&&p>-1&&p%1==0&&p<=Jt}function Iu(p){var m=typeof p;return p!=null&&(m=="object"||m=="function")}function Gu(p){return p!=null&&typeof p=="object"}var _p=$?gi($):Wn;function Ep(p,m){return p===m||oi(p,m,jn(m))}function uv(p,m,R){return R=typeof R=="function"?R:o,oi(p,m,jn(m),R)}function Im(p){return ov(p)&&p!=+p}function bm(p){if(Ll(p))throw new Kt(h);return ur(p)}function Bm(p){return p===null}function Fd(p){return p==null}function ov(p){return typeof p=="number"||Gu(p)&&yt(p)==zt}function Cc(p){if(!Gu(p)||yt(p)!=vr)return!1;var m=il(p);if(m===null)return!0;var R=ui.call(m,"constructor")&&m.constructor;return typeof R=="function"&&R instanceof R&&Lu.call(R)==sa}var w1=Ne?gi(Ne):ai;function Um(p){return gp(p)&&p>=-Jt&&p<=Jt}var Pd=Je?gi(Je):Qi;function S1(p){return typeof p=="string"||!tr(p)&&Gu(p)&&yt(p)==Du}function Bl(p){return typeof p=="symbol"||Gu(p)&&yt(p)==c0}var Ra=vt?gi(vt):Vr;function lv(p){return p===o}function jm(p){return Gu(p)&&Pu(p)==Jo}function sv(p){return Gu(p)&&yt(p)==Fs}var av=md(od),zm=md(function(p,m){return p<=m});function fv(p){if(!p)return[];if(hl(p))return S1(p)?Zr(p):iu(p);if(Fu&&p[Fu])return Xu(p[Fu]());var m=Pu(p),R=m==S?Su:m==Xt?$0:Nc;return R(p)}function Aa(p){if(!p)return p===0?p:0;if(p=vl(p),p===Pt||p===-Pt){var m=p<0?-1:1;return m*it}return p===p?p:0}function Mr(p){var m=Aa(p),R=m%1;return m===m?R?m-R:m:0}function Dp(p){return p?n0(Mr(p),0,ce):0}function vl(p){if(typeof p=="number")return p;if(Bl(p))return J;if(Iu(p)){var m=typeof p.valueOf=="function"?p.valueOf():p;p=Iu(m)?m+"":m}if(typeof p!="string")return p===0?p:+p;p=Nu(p);var R=ao.test(p);return R||No.test(p)?Bs(p.slice(2),R?2:8):li.test(p)?J:+p}function yu(p){return M0(p,dn(p))}function T1(p){return p?n0(Mr(p),-Jt,Jt):p===0?p:0}function Ui(p){return p==null?"":al(p)}var wp=uo(function(p,m){if(Nf(m)||hl(m)){M0(m,N0(m),p);return}for(var R in m)ui.call(m,R)&&Ss(p,R,m[R])}),Id=uo(function(p,m){M0(m,dn(m),p)}),To=uo(function(p,m,R,I){M0(m,dn(m),p,I)}),As=uo(function(p,m,R,I){M0(m,N0(m),p,I)}),bf=cl(qa);function bd(p,m){var R=ti(p);return m==null?R:Ef(R,m)}var Sp=Ir(function(p,m){p=bn(p);var R=-1,I=m.length,W=I>2?m[2]:o;for(W&&lo(m[0],m[1],W)&&(I=1);++R1),te}),M0(p,sr(p),R),I&&(R=j0(R,x|j|q,fm));for(var W=m.length;W--;)x2(R,m[W]);return R});function A1(p,m){return ef(p,Rd(Vn(m)))}var xp=cl(function(p,m){return p==null?{}:vh(p,m)});function ef(p,m){if(p==null)return{};var R=Ft(sr(p),function(I){return[I]});return m=Vn(m),mh(p,R,function(I,W){return m(I,W[0])})}function Hm(p,m,R){m=Ws(m,p);var I=-1,W=m.length;for(W||(W=1,p=o);++Im){var I=p;p=m,m=I}if(R||p%1||m%1){var W=_0();return Kn(p+W*(m-p+ba("1e-"+((W+"").length-1))),m)}return ad(p,m)}var Wd=Cf(function(p,m,R){return m=m.toLowerCase(),p+(R?Wo(m):m)});function Wo(p){return Op(Ui(p).toLowerCase())}function Vd(p){return p=Ui(p),p&&p.replace($n,Io).replace(J0,"")}function Wm(p,m,R){p=Ui(p),m=al(m);var I=p.length;R=R===o?I:n0(Mr(R),0,I);var W=R;return R-=m.length,R>=0&&p.slice(R,W)==m}function k1(p){return p=Ui(p),p&&Ps.test(p)?p.replace(su,ys):p}function Vm(p){return p=Ui(p),p&&en.test(p)?p.replace(mi,"\\$&"):p}var Gm=Cf(function(p,m,R){return p+(R?"-":"")+m.toLowerCase()}),dv=Cf(function(p,m,R){return p+(R?" ":"")+m.toLowerCase()}),Ym=wh("toLowerCase");function pv(p,m,R){p=Ui(p),m=Mr(m);var I=m?tu(p):0;if(!m||I>=m)return p;var W=(m-I)/2;return ga(Es(W),R)+p+ga(Zu(W),R)}function Km(p,m,R){p=Ui(p),m=Mr(m);var I=m?tu(p):0;return m&&I>>0,R?(p=Ui(p),p&&(typeof m=="string"||m!=null&&!w1(m))&&(m=al(m),!m&&Bo(p))?va(Zr(p),0,R):p.split(m,R)):[]}var zf=Cf(function(p,m,R){return p+(R?" ":"")+Op(m)});function vv(p,m,R){return p=Ui(p),R=R==null?0:n0(Mr(R),0,p.length),m=al(m),p.slice(R,R+m.length)==m}function mv(p,m,R){var I=K.templateSettings;R&&lo(p,m,R)&&(m=o),p=Ui(p),m=To({},m,I,Rf);var W=To({},m.imports,I.imports,Rf),te=N0(W),pe=Po(W,te),Ee,be,Dt=0,Tt=m.interpolate||tl,Ot="__p += '",on=mu((m.escape||tl).source+"|"+Tt.source+"|"+(Tt===d0?Xl:tl).source+"|"+(m.evaluate||tl).source+"|$","g"),Mn="//# sourceURL="+(ui.call(m,"sourceURL")?(m.sourceURL+"").replace(/\s/g," "):"lodash.templateSources["+ ++ac+"]")+` +`;p.replace(on,function(ar,ri,fi,zl,Zi,so){return fi||(fi=zl),Ot+=p.slice(Dt,so).replace(fo,js),ri&&(Ee=!0,Ot+=`' + +__e(`+ri+`) + +'`),Zi&&(be=!0,Ot+=`'; +`+Zi+`; +__p += '`),fi&&(Ot+=`' + +((__t = (`+fi+`)) == null ? '' : __t) + +'`),Dt=so+ar.length,ar}),Ot+=`'; +`;var rr=ui.call(m,"variable")&&m.variable;if(!rr)Ot=`with (obj) { +`+Ot+` +} +`;else if(Q0.test(rr))throw new Kt(t);Ot=(be?Ot.replace(Kr,""):Ot).replace(Oo,"$1").replace(Mo,"$1;"),Ot="function("+(rr||"obj")+`) { +`+(rr?"":`obj || (obj = {}); +`)+"var __t, __p = ''"+(Ee?", __e = _.escape":"")+(be?`, __j = Array.prototype.join; +function print() { __p += __j.call(arguments, '') } +`:`; +`)+Ot+`return __p +}`;var br=wv(function(){return pr(te,Mn+"return "+Ot).apply(o,pe)});if(br.source=Ot,yp(br))throw br;return br}function yv(p){return Ui(p).toLowerCase()}function Gd(p){return Ui(p).toUpperCase()}function Yd(p,m,R){if(p=Ui(p),p&&(R||m===o))return Nu(p);if(!p||!(m=al(m)))return p;var I=Zr(p),W=Zr(m),te=hf(I,W),pe=Tl(I,W)+1;return va(I,te,pe).join("")}function Ap(p,m,R){if(p=Ui(p),p&&(R||m===o))return p.slice(0,ho(p)+1);if(!p||!(m=al(m)))return p;var I=Zr(p),W=Tl(I,Zr(m))+1;return va(I,0,W).join("")}function gv(p,m,R){if(p=Ui(p),p&&(R||m===o))return p.replace(In,"");if(!p||!(m=al(m)))return p;var I=Zr(p),W=hf(I,Zr(m));return va(I,W).join("")}function Kd(p,m){var R=ze,I=We;if(Iu(m)){var W="separator"in m?m.separator:W;R="length"in m?Mr(m.length):R,I="omission"in m?al(m.omission):I}p=Ui(p);var te=p.length;if(Bo(p)){var pe=Zr(p);te=pe.length}if(R>=te)return p;var Ee=R-tu(I);if(Ee<1)return I;var be=pe?va(pe,0,Ee).join(""):p.slice(0,Ee);if(W===o)return be+I;if(pe&&(Ee+=be.length-Ee),w1(W)){if(p.slice(Ee).search(W)){var Dt,Tt=be;for(W.global||(W=mu(W.source,Ui(ko.exec(W))+"g")),W.lastIndex=0;Dt=W.exec(Tt);)var Ot=Dt.index;be=be.slice(0,Ot===o?Ee:Ot)}}else if(p.indexOf(al(W),Ee)!=Ee){var on=be.lastIndexOf(W);on>-1&&(be=be.slice(0,on))}return be+I}function _v(p){return p=Ui(p),p&&ki.test(p)?p.replace(F0,Bi):p}var Ev=Cf(function(p,m,R){return p+(R?" ":"")+m.toUpperCase()}),Op=wh("toUpperCase");function Dv(p,m,R){return p=Ui(p),m=R?o:m,m===o?gs(p)?yf(p):y0(p):p.match(m)||[]}var wv=Ir(function(p,m){try{return oe(p,o,m)}catch(R){return yp(R)?R:new Kt(R)}}),$m=cl(function(p,m){return rt(m,function(R){R=Fl(R),Vu(p,R,D1(p[R],p))}),p});function Sv(p){var m=p==null?0:p.length,R=Vn();return p=m?Ft(p,function(I){if(typeof I[1]!="function")throw new $r(E);return[R(I[0]),I[1]]}):[],Ir(function(I){for(var W=-1;++WJt)return[];var R=ce,I=Kn(p,ce);m=Vn(m),p-=ce;for(var W=T0(I,m);++R0||m<0)?new ft(R):(p<0?R=R.takeRight(-p):p&&(R=R.drop(p)),m!==o&&(m=Mr(m),R=m<0?R.dropRight(-m):R.take(m-p)),R)},ft.prototype.takeRightWhile=function(p){return this.reverse().takeWhile(p).reverse()},ft.prototype.toArray=function(){return this.take(ce)},A(ft.prototype,function(p,m){var R=/^(?:filter|find|map|reject)|While$/.test(m),I=/^(?:head|last)$/.test(m),W=K[I?"take"+(m=="last"?"Right":""):m],te=I||/^find/.test(m);!W||(K.prototype[m]=function(){var pe=this.__wrapped__,Ee=I?[1]:arguments,be=pe instanceof ft,Dt=Ee[0],Tt=be||tr(pe),Ot=function(ri){var fi=W.apply(K,Dn([ri],Ee));return I&&on?fi[0]:fi};Tt&&R&&typeof Dt=="function"&&Dt.length!=1&&(be=Tt=!1);var on=this.__chain__,Mn=!!this.__actions__.length,rr=te&&!on,br=be&&!Mn;if(!te&&Tt){pe=br?pe:new ft(this);var ar=p.apply(pe,Ee);return ar.__actions__.push({func:g1,args:[Ot],thisArg:o}),new Wr(ar,on)}return rr&&br?p.apply(this,Ee):(ar=this.thru(Ot),rr?I?ar.value()[0]:ar.value():ar)})}),rt(["pop","push","shift","sort","splice","unshift"],function(p){var m=Qr[p],R=/^(?:push|sort|unshift)$/.test(p)?"tap":"thru",I=/^(?:pop|shift)$/.test(p);K.prototype[p]=function(){var W=arguments;if(I&&!this.__chain__){var te=this.value();return m.apply(tr(te)?te:[],W)}return this[R](function(pe){return m.apply(tr(pe)?pe:[],W)})}}),A(ft.prototype,function(p,m){var R=K[m];if(R){var I=R.name+"";ui.call(An,I)||(An[I]=[]),An[I].push({name:m,func:R})}}),An[ya(o,me).name]=[{name:"wrapper",func:o}],ft.prototype.clone=Di,ft.prototype.reverse=ru,ft.prototype.value=E0,K.prototype.at=J2,K.prototype.chain=qh,K.prototype.commit=Z2,K.prototype.next=Wh,K.prototype.plant=Em,K.prototype.reverse=Pf,K.prototype.toJSON=K.prototype.valueOf=K.prototype.value=If,K.prototype.first=K.prototype.head,Fu&&(K.prototype[Fu]=_m),K},to=eo();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(zi._=to,define(function(){return to})):H?((H.exports=to)._=to,U._=to):zi._=to}).call(Wv)});var ZE=nt((tH,JE)=>{"use strict";var Pi=JE.exports;JE.exports.default=Pi;var Eu="\x1B[",Uy="\x1B]",Vv="\x07",T_=";",aS=process.env.TERM_PROGRAM==="Apple_Terminal";Pi.cursorTo=(o,l)=>{if(typeof o!="number")throw new TypeError("The `x` argument is required");return typeof l!="number"?Eu+(o+1)+"G":Eu+(l+1)+";"+(o+1)+"H"};Pi.cursorMove=(o,l)=>{if(typeof o!="number")throw new TypeError("The `x` argument is required");let f="";return o<0?f+=Eu+-o+"D":o>0&&(f+=Eu+o+"C"),l<0?f+=Eu+-l+"A":l>0&&(f+=Eu+l+"B"),f};Pi.cursorUp=(o=1)=>Eu+o+"A";Pi.cursorDown=(o=1)=>Eu+o+"B";Pi.cursorForward=(o=1)=>Eu+o+"C";Pi.cursorBackward=(o=1)=>Eu+o+"D";Pi.cursorLeft=Eu+"G";Pi.cursorSavePosition=aS?"\x1B7":Eu+"s";Pi.cursorRestorePosition=aS?"\x1B8":Eu+"u";Pi.cursorGetPosition=Eu+"6n";Pi.cursorNextLine=Eu+"E";Pi.cursorPrevLine=Eu+"F";Pi.cursorHide=Eu+"?25l";Pi.cursorShow=Eu+"?25h";Pi.eraseLines=o=>{let l="";for(let f=0;f[Uy,"8",T_,T_,l,Vv,o,Uy,"8",T_,T_,Vv].join("");Pi.image=(o,l={})=>{let f=`${Uy}1337;File=inline=1`;return l.width&&(f+=`;width=${l.width}`),l.height&&(f+=`;height=${l.height}`),l.preserveAspectRatio===!1&&(f+=";preserveAspectRatio=0"),f+":"+o.toString("base64")+Vv};Pi.iTerm={setCwd:(o=process.cwd())=>`${Uy}50;CurrentDir=${o}${Vv}`,annotation:(o,l={})=>{let f=`${Uy}1337;`,h=typeof l.x<"u",E=typeof l.y<"u";if((h||E)&&!(h&&E&&typeof l.length<"u"))throw new Error("`x`, `y` and `length` must be defined when `x` or `y` is defined");return o=o.replace(/\|/g,""),f+=l.isHidden?"AddHiddenAnnotation=":"AddAnnotation=",l.length>0?f+=(h?[o,l.length,l.x,l.y]:[l.length,o]).join("|"):f+=o,f+Vv}}});var cS=nt((nH,$E)=>{"use strict";var fS=(o,l)=>{for(let f of Reflect.ownKeys(l))Object.defineProperty(o,f,Object.getOwnPropertyDescriptor(l,f));return o};$E.exports=fS;$E.exports.default=fS});var pS=nt((rH,x_)=>{"use strict";var fP=cS(),C_=new WeakMap,dS=(o,l={})=>{if(typeof o!="function")throw new TypeError("Expected a function");let f,h=0,E=o.displayName||o.name||"",t=function(...N){if(C_.set(t,++h),h===1)f=o.apply(this,N),o=null;else if(l.throw===!0)throw new Error(`Function \`${E}\` can only be called once`);return f};return fP(t,o),C_.set(t,h),t};x_.exports=dS;x_.exports.default=dS;x_.exports.callCount=o=>{if(!C_.has(o))throw new Error(`The given function \`${o.name}\` is not wrapped by the \`onetime\` package`);return C_.get(o)}});var hS=nt((iH,R_)=>{R_.exports=["SIGABRT","SIGALRM","SIGHUP","SIGINT","SIGTERM"];process.platform!=="win32"&&R_.exports.push("SIGVTALRM","SIGXCPU","SIGXFSZ","SIGUSR2","SIGTRAP","SIGSYS","SIGQUIT","SIGIOT");process.platform==="linux"&&R_.exports.push("SIGIO","SIGPOLL","SIGPWR","SIGSTKFLT","SIGUNUSED")});var nD=nt((uH,Kv)=>{var w0=global.process,Jp=function(o){return o&&typeof o=="object"&&typeof o.removeListener=="function"&&typeof o.emit=="function"&&typeof o.reallyExit=="function"&&typeof o.listeners=="function"&&typeof o.kill=="function"&&typeof o.pid=="number"&&typeof o.on=="function"};Jp(w0)?(vS=hi("assert"),Gv=hS(),mS=/^win/i.test(w0.platform),jy=hi("events"),typeof jy!="function"&&(jy=jy.EventEmitter),w0.__signal_exit_emitter__?wl=w0.__signal_exit_emitter__:(wl=w0.__signal_exit_emitter__=new jy,wl.count=0,wl.emitted={}),wl.infinite||(wl.setMaxListeners(1/0),wl.infinite=!0),Kv.exports=function(o,l){if(!Jp(global.process))return function(){};vS.equal(typeof o,"function","a callback must be provided for exit handler"),Yv===!1&&eD();var f="exit";l&&l.alwaysLast&&(f="afterexit");var h=function(){wl.removeListener(f,o),wl.listeners("exit").length===0&&wl.listeners("afterexit").length===0&&A_()};return wl.on(f,o),h},A_=function(){!Yv||!Jp(global.process)||(Yv=!1,Gv.forEach(function(l){try{w0.removeListener(l,O_[l])}catch{}}),w0.emit=M_,w0.reallyExit=tD,wl.count-=1)},Kv.exports.unload=A_,Zp=function(l,f,h){wl.emitted[l]||(wl.emitted[l]=!0,wl.emit(l,f,h))},O_={},Gv.forEach(function(o){O_[o]=function(){if(!!Jp(global.process)){var f=w0.listeners(o);f.length===wl.count&&(A_(),Zp("exit",null,o),Zp("afterexit",null,o),mS&&o==="SIGHUP"&&(o="SIGINT"),w0.kill(w0.pid,o))}}}),Kv.exports.signals=function(){return Gv},Yv=!1,eD=function(){Yv||!Jp(global.process)||(Yv=!0,wl.count+=1,Gv=Gv.filter(function(l){try{return w0.on(l,O_[l]),!0}catch{return!1}}),w0.emit=gS,w0.reallyExit=yS)},Kv.exports.load=eD,tD=w0.reallyExit,yS=function(l){!Jp(global.process)||(w0.exitCode=l||0,Zp("exit",w0.exitCode,null),Zp("afterexit",w0.exitCode,null),tD.call(w0,w0.exitCode))},M_=w0.emit,gS=function(l,f){if(l==="exit"&&Jp(global.process)){f!==void 0&&(w0.exitCode=f);var h=M_.apply(this,arguments);return Zp("exit",w0.exitCode,null),Zp("afterexit",w0.exitCode,null),h}else return M_.apply(this,arguments)}):Kv.exports=function(){return function(){}};var vS,Gv,mS,jy,wl,A_,Zp,O_,Yv,eD,tD,yS,M_,gS});var ES=nt((oH,_S)=>{"use strict";var cP=pS(),dP=nD();_S.exports=cP(()=>{dP(()=>{process.stderr.write("\x1B[?25h")},{alwaysLast:!0})})});var rD=nt(Xv=>{"use strict";var pP=ES(),k_=!1;Xv.show=(o=process.stderr)=>{!o.isTTY||(k_=!1,o.write("\x1B[?25h"))};Xv.hide=(o=process.stderr)=>{!o.isTTY||(pP(),k_=!0,o.write("\x1B[?25l"))};Xv.toggle=(o,l)=>{o!==void 0&&(k_=o),k_?Xv.show(l):Xv.hide(l)}});var TS=nt(zy=>{"use strict";var SS=zy&&zy.__importDefault||function(o){return o&&o.__esModule?o:{default:o}};Object.defineProperty(zy,"__esModule",{value:!0});var DS=SS(ZE()),wS=SS(rD()),hP=(o,{showCursor:l=!1}={})=>{let f=0,h="",E=!1,t=N=>{!l&&!E&&(wS.default.hide(),E=!0);let F=N+` +`;F!==h&&(h=F,o.write(DS.default.eraseLines(f)+F),f=F.split(` +`).length)};return t.clear=()=>{o.write(DS.default.eraseLines(f)),h="",f=0},t.done=()=>{h="",f=0,l||(wS.default.show(),E=!1)},t};zy.default={create:hP}});var CS=nt((aH,vP)=>{vP.exports=[{name:"AppVeyor",constant:"APPVEYOR",env:"APPVEYOR",pr:"APPVEYOR_PULL_REQUEST_NUMBER"},{name:"Azure Pipelines",constant:"AZURE_PIPELINES",env:"SYSTEM_TEAMFOUNDATIONCOLLECTIONURI",pr:"SYSTEM_PULLREQUEST_PULLREQUESTID"},{name:"Bamboo",constant:"BAMBOO",env:"bamboo_planKey"},{name:"Bitbucket Pipelines",constant:"BITBUCKET",env:"BITBUCKET_COMMIT",pr:"BITBUCKET_PR_ID"},{name:"Bitrise",constant:"BITRISE",env:"BITRISE_IO",pr:"BITRISE_PULL_REQUEST"},{name:"Buddy",constant:"BUDDY",env:"BUDDY_WORKSPACE_ID",pr:"BUDDY_EXECUTION_PULL_REQUEST_ID"},{name:"Buildkite",constant:"BUILDKITE",env:"BUILDKITE",pr:{env:"BUILDKITE_PULL_REQUEST",ne:"false"}},{name:"CircleCI",constant:"CIRCLE",env:"CIRCLECI",pr:"CIRCLE_PULL_REQUEST"},{name:"Cirrus CI",constant:"CIRRUS",env:"CIRRUS_CI",pr:"CIRRUS_PR"},{name:"AWS CodeBuild",constant:"CODEBUILD",env:"CODEBUILD_BUILD_ARN"},{name:"Codeship",constant:"CODESHIP",env:{CI_NAME:"codeship"}},{name:"Drone",constant:"DRONE",env:"DRONE",pr:{DRONE_BUILD_EVENT:"pull_request"}},{name:"dsari",constant:"DSARI",env:"DSARI"},{name:"GitLab CI",constant:"GITLAB",env:"GITLAB_CI"},{name:"GoCD",constant:"GOCD",env:"GO_PIPELINE_LABEL"},{name:"Hudson",constant:"HUDSON",env:"HUDSON_URL"},{name:"Jenkins",constant:"JENKINS",env:["JENKINS_URL","BUILD_ID"],pr:{any:["ghprbPullId","CHANGE_ID"]}},{name:"Magnum CI",constant:"MAGNUM",env:"MAGNUM"},{name:"Netlify CI",constant:"NETLIFY",env:"NETLIFY_BUILD_BASE",pr:{env:"PULL_REQUEST",ne:"false"}},{name:"Sail CI",constant:"SAIL",env:"SAILCI",pr:"SAIL_PULL_REQUEST_NUMBER"},{name:"Semaphore",constant:"SEMAPHORE",env:"SEMAPHORE",pr:"PULL_REQUEST_NUMBER"},{name:"Shippable",constant:"SHIPPABLE",env:"SHIPPABLE",pr:{IS_PULL_REQUEST:"true"}},{name:"Solano CI",constant:"SOLANO",env:"TDDIUM",pr:"TDDIUM_PR_ID"},{name:"Strider CD",constant:"STRIDER",env:"STRIDER"},{name:"TaskCluster",constant:"TASKCLUSTER",env:["TASK_ID","RUN_ID"]},{name:"TeamCity",constant:"TEAMCITY",env:"TEAMCITY_VERSION"},{name:"Travis CI",constant:"TRAVIS",env:"TRAVIS",pr:{env:"TRAVIS_PULL_REQUEST",ne:"false"}}]});var AS=nt(Fa=>{"use strict";var RS=CS(),Uc=process.env;Object.defineProperty(Fa,"_vendors",{value:RS.map(function(o){return o.constant})});Fa.name=null;Fa.isPR=null;RS.forEach(function(o){var l=Array.isArray(o.env)?o.env:[o.env],f=l.every(function(h){return xS(h)});if(Fa[o.constant]=f,f)switch(Fa.name=o.name,typeof o.pr){case"string":Fa.isPR=!!Uc[o.pr];break;case"object":"env"in o.pr?Fa.isPR=o.pr.env in Uc&&Uc[o.pr.env]!==o.pr.ne:"any"in o.pr?Fa.isPR=o.pr.any.some(function(h){return!!Uc[h]}):Fa.isPR=xS(o.pr);break;default:Fa.isPR=null}});Fa.isCI=!!(Uc.CI||Uc.CONTINUOUS_INTEGRATION||Uc.BUILD_NUMBER||Uc.RUN_ID||Fa.name);function xS(o){return typeof o=="string"?!!Uc[o]:Object.keys(o).every(function(l){return Uc[l]===o[l]})}});var MS=nt((cH,OS)=>{"use strict";OS.exports=AS().isCI});var NS=nt((dH,kS)=>{"use strict";var mP=o=>{let l=new Set;do for(let f of Reflect.ownKeys(o))l.add([o,f]);while((o=Reflect.getPrototypeOf(o))&&o!==Object.prototype);return l};kS.exports=(o,{include:l,exclude:f}={})=>{let h=E=>{let t=N=>typeof N=="string"?E===N:N.test(E);return l?l.some(t):f?!f.some(t):!0};for(let[E,t]of mP(o.constructor.prototype)){if(t==="constructor"||!h(t))continue;let N=Reflect.getOwnPropertyDescriptor(E,t);N&&typeof N.value=="function"&&(o[t]=o[t].bind(o))}return o}});var jS=nt(ou=>{"use strict";Object.defineProperty(ou,"__esModule",{value:!0});var Jv,Wy,I_,b_,fD;typeof window>"u"||typeof MessageChannel!="function"?(Qv=null,iD=null,uD=function(){if(Qv!==null)try{var o=ou.unstable_now();Qv(!0,o),Qv=null}catch(l){throw setTimeout(uD,0),l}},LS=Date.now(),ou.unstable_now=function(){return Date.now()-LS},Jv=function(o){Qv!==null?setTimeout(Jv,0,o):(Qv=o,setTimeout(uD,0))},Wy=function(o,l){iD=setTimeout(o,l)},I_=function(){clearTimeout(iD)},b_=function(){return!1},fD=ou.unstable_forceFrameRate=function(){}):(N_=window.performance,oD=window.Date,PS=window.setTimeout,IS=window.clearTimeout,typeof console<"u"&&(bS=window.cancelAnimationFrame,typeof window.requestAnimationFrame!="function"&&console.error("This browser doesn't support requestAnimationFrame. Make sure that you load a polyfill in older browsers. https://fb.me/react-polyfills"),typeof bS!="function"&&console.error("This browser doesn't support cancelAnimationFrame. Make sure that you load a polyfill in older browsers. https://fb.me/react-polyfills")),typeof N_=="object"&&typeof N_.now=="function"?ou.unstable_now=function(){return N_.now()}:(BS=oD.now(),ou.unstable_now=function(){return oD.now()-BS}),Hy=!1,qy=null,L_=-1,lD=5,sD=0,b_=function(){return ou.unstable_now()>=sD},fD=function(){},ou.unstable_forceFrameRate=function(o){0>o||125P_(N,f))k!==void 0&&0>P_(k,N)?(o[h]=k,o[F]=f,h=F):(o[h]=N,o[t]=f,h=t);else if(k!==void 0&&0>P_(k,f))o[h]=k,o[F]=f,h=F;else break e}}return l}return null}function P_(o,l){var f=o.sortIndex-l.sortIndex;return f!==0?f:o.id-l.id}var $f=[],f2=[],yP=1,Ls=null,ds=3,U_=!1,$p=!1,Vy=!1;function j_(o){for(var l=cf(f2);l!==null;){if(l.callback===null)B_(f2);else if(l.startTime<=o)B_(f2),l.sortIndex=l.expirationTime,cD($f,l);else break;l=cf(f2)}}function dD(o){if(Vy=!1,j_(o),!$p)if(cf($f)!==null)$p=!0,Jv(pD);else{var l=cf(f2);l!==null&&Wy(dD,l.startTime-o)}}function pD(o,l){$p=!1,Vy&&(Vy=!1,I_()),U_=!0;var f=ds;try{for(j_(l),Ls=cf($f);Ls!==null&&(!(Ls.expirationTime>l)||o&&!b_());){var h=Ls.callback;if(h!==null){Ls.callback=null,ds=Ls.priorityLevel;var E=h(Ls.expirationTime<=l);l=ou.unstable_now(),typeof E=="function"?Ls.callback=E:Ls===cf($f)&&B_($f),j_(l)}else B_($f);Ls=cf($f)}if(Ls!==null)var t=!0;else{var N=cf(f2);N!==null&&Wy(dD,N.startTime-l),t=!1}return t}finally{Ls=null,ds=f,U_=!1}}function US(o){switch(o){case 1:return-1;case 2:return 250;case 5:return 1073741823;case 4:return 1e4;default:return 5e3}}var gP=fD;ou.unstable_ImmediatePriority=1;ou.unstable_UserBlockingPriority=2;ou.unstable_NormalPriority=3;ou.unstable_IdlePriority=5;ou.unstable_LowPriority=4;ou.unstable_runWithPriority=function(o,l){switch(o){case 1:case 2:case 3:case 4:case 5:break;default:o=3}var f=ds;ds=o;try{return l()}finally{ds=f}};ou.unstable_next=function(o){switch(ds){case 1:case 2:case 3:var l=3;break;default:l=ds}var f=ds;ds=l;try{return o()}finally{ds=f}};ou.unstable_scheduleCallback=function(o,l,f){var h=ou.unstable_now();if(typeof f=="object"&&f!==null){var E=f.delay;E=typeof E=="number"&&0h?(o.sortIndex=E,cD(f2,o),cf($f)===null&&o===cf(f2)&&(Vy?I_():Vy=!0,Wy(dD,E-h))):(o.sortIndex=f,cD($f,o),$p||U_||($p=!0,Jv(pD))),o};ou.unstable_cancelCallback=function(o){o.callback=null};ou.unstable_wrapCallback=function(o){var l=ds;return function(){var f=ds;ds=l;try{return o.apply(this,arguments)}finally{ds=f}}};ou.unstable_getCurrentPriorityLevel=function(){return ds};ou.unstable_shouldYield=function(){var o=ou.unstable_now();j_(o);var l=cf($f);return l!==Ls&&Ls!==null&&l!==null&&l.callback!==null&&l.startTime<=o&&l.expirationTime{"use strict";process.env.NODE_ENV!=="production"&&function(){"use strict";Object.defineProperty(Ii,"__esModule",{value:!0});var o=!1,l=!1,f=!0,h,E,t,N,F;if(typeof window>"u"||typeof MessageChannel!="function"){var k=null,x=null,j=function(){if(k!==null)try{var St=Ii.unstable_now(),Bt=!0;k(Bt,St),k=null}catch(Hn){throw setTimeout(j,0),Hn}},q=Date.now();Ii.unstable_now=function(){return Date.now()-q},h=function(St){k!==null?setTimeout(h,0,St):(k=St,setTimeout(j,0))},E=function(St,Bt){x=setTimeout(St,Bt)},t=function(){clearTimeout(x)},N=function(){return!1},F=Ii.unstable_forceFrameRate=function(){}}else{var V=window.performance,re=window.Date,y=window.setTimeout,me=window.clearTimeout;if(typeof console<"u"){var De=window.requestAnimationFrame,ge=window.cancelAnimationFrame;typeof De!="function"&&console.error("This browser doesn't support requestAnimationFrame. Make sure that you load a polyfill in older browsers. https://fb.me/react-polyfills"),typeof ge!="function"&&console.error("This browser doesn't support cancelAnimationFrame. Make sure that you load a polyfill in older browsers. https://fb.me/react-polyfills")}if(typeof V=="object"&&typeof V.now=="function")Ii.unstable_now=function(){return V.now()};else{var ae=re.now();Ii.unstable_now=function(){return re.now()-ae}}var we=!1,he=null,ve=-1,ue=5,Ae=0,ze=300,We=!1;if(l&&navigator!==void 0&&navigator.scheduling!==void 0&&navigator.scheduling.isInputPending!==void 0){var gt=navigator.scheduling;N=function(){var St=Ii.unstable_now();return St>=Ae?We||gt.isInputPending()?!0:St>=ze:!1},F=function(){We=!0}}else N=function(){return Ii.unstable_now()>=Ae},F=function(){};Ii.unstable_forceFrameRate=function(St){if(St<0||St>125){console.error("forceFrameRate takes a positive int between 0 and 125, forcing framerates higher than 125 fps is not unsupported");return}St>0?ue=Math.floor(1e3/St):ue=5};var _t=function(){if(he!==null){var St=Ii.unstable_now();Ae=St+ue;var Bt=!0;try{var Hn=he(Bt,St);Hn?ot.postMessage(null):(we=!1,he=null)}catch(qr){throw ot.postMessage(null),qr}}else we=!1;We=!1},Qe=new MessageChannel,ot=Qe.port2;Qe.port1.onmessage=_t,h=function(St){he=St,we||(we=!0,ot.postMessage(null))},E=function(St,Bt){ve=y(function(){St(Ii.unstable_now())},Bt)},t=function(){me(ve),ve=-1}}function Ve(St,Bt){var Hn=St.length;St.push(Bt),it(St,Bt,Hn)}function Pt(St){var Bt=St[0];return Bt===void 0?null:Bt}function Jt(St){var Bt=St[0];if(Bt!==void 0){var Hn=St.pop();return Hn!==Bt&&(St[0]=Hn,J(St,Hn,0)),Bt}else return null}function it(St,Bt,Hn){for(var qr=Hn;;){var Ki=Math.floor((qr-1)/2),Xr=St[Ki];if(Xr!==void 0&&ce(Xr,Bt)>0)St[Ki]=Bt,St[qr]=Xr,qr=Ki;else return}}function J(St,Bt,Hn){for(var qr=Hn,Ki=St.length;qrfr){if(fr*=2,fr>jr){console.error("Scheduler Profiling: Event log exceeded maximum size. Don't forget to call `stopLoggingProfilingEvents()`."),Dr();return}var Hn=new Int32Array(fr*4);Hn.set(Xt),zr=Hn.buffer,Xt=Hn}Xt.set(St,Bt)}}function vi(){fr=vr,zr=new ArrayBuffer(fr*4),Xt=new Int32Array(zr),Du=0}function Dr(){var St=zr;return fr=0,zr=null,Xt=null,Du=0,St}function el(St,Bt){f&&(Vt[Xn]++,Xt!==null&&lu([c0,Bt*1e3,St.id,St.priorityLevel]))}function Y0(St,Bt){f&&(Vt[Er]=Re,Vt[S]=0,Vt[Xn]--,Xt!==null&&lu([Ao,Bt*1e3,St.id]))}function Bu(St,Bt){f&&(Vt[Xn]--,Xt!==null&&lu([Fs,Bt*1e3,St.id]))}function K0(St,Bt){f&&(Vt[Er]=Re,Vt[S]=0,Vt[Xn]--,Xt!==null&&lu([Jo,Bt*1e3,St.id]))}function Kr(St,Bt){f&&(an++,Vt[Er]=St.priorityLevel,Vt[S]=St.id,Vt[zt]=an,Xt!==null&&lu([Zo,Bt*1e3,St.id,an]))}function Oo(St,Bt){f&&(Vt[Er]=Re,Vt[S]=0,Vt[zt]=0,Xt!==null&&lu([$o,Bt*1e3,St.id,an]))}function Mo(St){f&&(On++,Xt!==null&&lu([qt,St*1e3,On]))}function F0(St){f&&Xt!==null&&lu([xi,St*1e3,On])}var su=1073741823,ki=-1,Ps=250,Kl=5e3,P0=1e4,d0=su,Hr=[],Ri=[],X0=1,mi=!1,en=null,In=dt,Ai=!1,yi=!1,Wt=!1;function Ru(St){for(var Bt=Pt(Ri);Bt!==null;){if(Bt.callback===null)Jt(Ri);else if(Bt.startTime<=St)Jt(Ri),Bt.sortIndex=Bt.expirationTime,Ve(Hr,Bt),f&&(el(Bt,St),Bt.isQueued=!0);else return;Bt=Pt(Ri)}}function eu(St){if(Wt=!1,Ru(St),!yi)if(Pt(Hr)!==null)yi=!0,h(Q0);else{var Bt=Pt(Ri);Bt!==null&&E(eu,Bt.startTime-St)}}function Q0(St,Bt){f&&F0(Bt),yi=!1,Wt&&(Wt=!1,t()),Ai=!0;var Hn=In;try{if(f)try{return Yi(St,Bt)}catch(Xr){if(en!==null){var qr=Ii.unstable_now();K0(en,qr),en.isQueued=!1}throw Xr}else return Yi(St,Bt)}finally{if(en=null,In=Hn,Ai=!1,f){var Ki=Ii.unstable_now();Mo(Ki)}}}function Yi(St,Bt){var Hn=Bt;for(Ru(Hn),en=Pt(Hr);en!==null&&!(o&&mi)&&!(en.expirationTime>Hn&&(!St||N()));){var qr=en.callback;if(qr!==null){en.callback=null,In=en.priorityLevel;var Ki=en.expirationTime<=Hn;Kr(en,Hn);var Xr=qr(Ki);Hn=Ii.unstable_now(),typeof Xr=="function"?(en.callback=Xr,Oo(en,Hn)):(f&&(Y0(en,Hn),en.isQueued=!1),en===Pt(Hr)&&Jt(Hr)),Ru(Hn)}else Jt(Hr);en=Pt(Hr)}if(en!==null)return!0;var Au=Pt(Ri);return Au!==null&&E(eu,Au.startTime-Hn),!1}function Xl(St,Bt){switch(St){case le:case He:case dt:case At:case nn:break;default:St=dt}var Hn=In;In=St;try{return Bt()}finally{In=Hn}}function ko(St){var Bt;switch(In){case le:case He:case dt:Bt=dt;break;default:Bt=In;break}var Hn=In;In=Bt;try{return St()}finally{In=Hn}}function li(St){var Bt=In;return function(){var Hn=In;In=Bt;try{return St.apply(this,arguments)}finally{In=Hn}}}function ao(St){switch(St){case le:return ki;case He:return Ps;case nn:return d0;case At:return P0;case dt:default:return Kl}}function Ql(St,Bt,Hn){var qr=Ii.unstable_now(),Ki,Xr;if(typeof Hn=="object"&&Hn!==null){var Au=Hn.delay;typeof Au=="number"&&Au>0?Ki=qr+Au:Ki=qr,Xr=typeof Hn.timeout=="number"?Hn.timeout:ao(St)}else Xr=ao(St),Ki=qr;var p0=Ki+Xr,Ni={id:X0++,callback:Bt,priorityLevel:St,startTime:Ki,expirationTime:p0,sortIndex:-1};return f&&(Ni.isQueued=!1),Ki>qr?(Ni.sortIndex=Ki,Ve(Ri,Ni),Pt(Hr)===null&&Ni===Pt(Ri)&&(Wt?t():Wt=!0,E(eu,Ki-qr))):(Ni.sortIndex=p0,Ve(Hr,Ni),f&&(el(Ni,qr),Ni.isQueued=!0),!yi&&!Ai&&(yi=!0,h(Q0))),Ni}function No(){mi=!0}function Is(){mi=!1,!yi&&!Ai&&(yi=!0,h(Q0))}function $n(){return Pt(Hr)}function tl(St){if(f&&St.isQueued){var Bt=Ii.unstable_now();Bu(St,Bt),St.isQueued=!1}St.callback=null}function fo(){return In}function I0(){var St=Ii.unstable_now();Ru(St);var Bt=Pt(Hr);return Bt!==en&&en!==null&&Bt!==null&&Bt.callback!==null&&Bt.startTime<=St&&Bt.expirationTime{"use strict";process.env.NODE_ENV==="production"?hD.exports=jS():hD.exports=zS()});var HS=nt((mH,Gy)=>{Gy.exports=function o(l){"use strict";var f=Py(),h=Mi(),E=z_();function t(_){for(var g="https://reactjs.org/docs/error-decoder.html?invariant="+_,A=1;AX0||(_.current=Ri[X0],Ri[X0]=null,X0--)}function en(_,g){X0++,Ri[X0]=_.current,_.current=g}var In={},Ai={current:In},yi={current:!1},Wt=In;function Ru(_,g){var A=_.type.contextTypes;if(!A)return In;var P=_.stateNode;if(P&&P.__reactInternalMemoizedUnmaskedChildContext===g)return P.__reactInternalMemoizedMaskedChildContext;var B={},Z;for(Z in A)B[Z]=g[Z];return P&&(_=_.stateNode,_.__reactInternalMemoizedUnmaskedChildContext=g,_.__reactInternalMemoizedMaskedChildContext=B),B}function eu(_){return _=_.childContextTypes,_!=null}function Q0(_){mi(yi,_),mi(Ai,_)}function Yi(_){mi(yi,_),mi(Ai,_)}function Xl(_,g,A){if(Ai.current!==In)throw Error(t(168));en(Ai,g,_),en(yi,A,_)}function ko(_,g,A){var P=_.stateNode;if(_=g.childContextTypes,typeof P.getChildContext!="function")return A;P=P.getChildContext();for(var B in P)if(!(B in _))throw Error(t(108,ze(g)||"Unknown",B));return f({},A,{},P)}function li(_){var g=_.stateNode;return g=g&&g.__reactInternalMemoizedMergedChildContext||In,Wt=Ai.current,en(Ai,g,_),en(yi,yi.current,_),!0}function ao(_,g,A){var P=_.stateNode;if(!P)throw Error(t(169));A?(g=ko(_,g,Wt),P.__reactInternalMemoizedMergedChildContext=g,mi(yi,_),mi(Ai,_),en(Ai,g,_)):mi(yi,_),en(yi,A,_)}var Ql=E.unstable_runWithPriority,No=E.unstable_scheduleCallback,Is=E.unstable_cancelCallback,$n=E.unstable_shouldYield,tl=E.unstable_requestPaint,fo=E.unstable_now,I0=E.unstable_getCurrentPriorityLevel,Sl=E.unstable_ImmediatePriority,Lo=E.unstable_UserBlockingPriority,St=E.unstable_NormalPriority,Bt=E.unstable_LowPriority,Hn=E.unstable_IdlePriority,qr={},Ki=tl!==void 0?tl:function(){},Xr=null,Au=null,p0=!1,Ni=fo(),h0=1e4>Ni?fo:function(){return fo()-Ni};function hs(){switch(I0()){case Sl:return 99;case Lo:return 98;case St:return 97;case Bt:return 96;case Hn:return 95;default:throw Error(t(332))}}function Ct(_){switch(_){case 99:return Sl;case 98:return Lo;case 97:return St;case 96:return Bt;case 95:return Hn;default:throw Error(t(332))}}function co(_,g){return _=Ct(_),Ql(_,g)}function nl(_,g,A){return _=Ct(_),No(_,g,A)}function Jl(_){return Xr===null?(Xr=[_],Au=No(Sl,vs)):Xr.push(_),qr}function Uu(){if(Au!==null){var _=Au;Au=null,Is(_)}vs()}function vs(){if(!p0&&Xr!==null){p0=!0;var _=0;try{var g=Xr;co(99,function(){for(;_=g&&(ho=!0),_.firstContext=null)}function Mu(_,g){if(Ou!==_&&g!==!1&&g!==0)if((typeof g!="number"||g===1073741823)&&(Ou=_,g=1073741823),g={context:_,observedBits:g,next:null},Si===null){if(cr===null)throw Error(t(308));Si=g,cr.dependencies={expirationTime:0,firstContext:g,responders:null}}else Si=Si.next=g;return ln?_._currentValue:_._currentValue2}var po=!1;function Hu(_){return{baseState:_,firstUpdate:null,lastUpdate:null,firstCapturedUpdate:null,lastCapturedUpdate:null,firstEffect:null,lastEffect:null,firstCapturedEffect:null,lastCapturedEffect:null}}function Pa(_){return{baseState:_.baseState,firstUpdate:_.firstUpdate,lastUpdate:_.lastUpdate,firstCapturedUpdate:null,lastCapturedUpdate:null,firstEffect:null,lastEffect:null,firstCapturedEffect:null,lastCapturedEffect:null}}function v0(_,g){return{expirationTime:_,suspenseConfig:g,tag:0,payload:null,callback:null,next:null,nextEffect:null}}function ia(_,g){_.lastUpdate===null?_.firstUpdate=_.lastUpdate=g:(_.lastUpdate.next=g,_.lastUpdate=g)}function J0(_,g){var A=_.alternate;if(A===null){var P=_.updateQueue,B=null;P===null&&(P=_.updateQueue=Hu(_.memoizedState))}else P=_.updateQueue,B=A.updateQueue,P===null?B===null?(P=_.updateQueue=Hu(_.memoizedState),B=A.updateQueue=Hu(A.memoizedState)):P=_.updateQueue=Pa(B):B===null&&(B=A.updateQueue=Pa(P));B===null||P===B?ia(P,g):P.lastUpdate===null||B.lastUpdate===null?(ia(P,g),ia(B,g)):(ia(P,g),B.lastUpdate=g)}function ua(_,g){var A=_.updateQueue;A=A===null?_.updateQueue=Hu(_.memoizedState):Ia(_,A),A.lastCapturedUpdate===null?A.firstCapturedUpdate=A.lastCapturedUpdate=g:(A.lastCapturedUpdate.next=g,A.lastCapturedUpdate=g)}function Ia(_,g){var A=_.alternate;return A!==null&&g===A.updateQueue&&(g=_.updateQueue=Pa(g)),g}function ms(_,g,A,P,B,Z){switch(A.tag){case 1:return _=A.payload,typeof _=="function"?_.call(Z,P,B):_;case 3:_.effectTag=_.effectTag&-4097|64;case 0:if(_=A.payload,B=typeof _=="function"?_.call(Z,P,B):_,B==null)break;return f({},P,B);case 2:po=!0}return P}function S0(_,g,A,P,B){po=!1,g=Ia(_,g);for(var Z=g.baseState,de=null,yt=0,Rt=g.firstUpdate,Nt=Z;Rt!==null;){var xr=Rt.expirationTime;xrai?(Qi=ur,ur=null):Qi=ur.sibling;var Vr=cu(Ge,ur,st[ai],$t);if(Vr===null){ur===null&&(ur=Qi);break}_&&ur&&Vr.alternate===null&&g(Ge,ur),je=Z(Vr,je,ai),oi===null?Wn=Vr:oi.sibling=Vr,oi=Vr,ur=Qi}if(ai===st.length)return A(Ge,ur),Wn;if(ur===null){for(;aiai?(Qi=ur,ur=null):Qi=ur.sibling;var Tu=cu(Ge,ur,Vr.value,$t);if(Tu===null){ur===null&&(ur=Qi);break}_&&ur&&Tu.alternate===null&&g(Ge,ur),je=Z(Tu,je,ai),oi===null?Wn=Tu:oi.sibling=Tu,oi=Tu,ur=Qi}if(Vr.done)return A(Ge,ur),Wn;if(ur===null){for(;!Vr.done;ai++,Vr=st.next())Vr=r0(Ge,Vr.value,$t),Vr!==null&&(je=Z(Vr,je,ai),oi===null?Wn=Vr:oi.sibling=Vr,oi=Vr);return Wn}for(ur=P(Ge,ur);!Vr.done;ai++,Vr=st.next())Vr=z0(ur,Ge,ai,Vr.value,$t),Vr!==null&&(_&&Vr.alternate!==null&&ur.delete(Vr.key===null?ai:Vr.key),je=Z(Vr,je,ai),oi===null?Wn=Vr:oi.sibling=Vr,oi=Vr);return _&&ur.forEach(function(Wa){return g(Ge,Wa)}),Wn}return function(Ge,je,st,$t){var Wn=typeof st=="object"&&st!==null&&st.type===j&&st.key===null;Wn&&(st=st.props.children);var oi=typeof st=="object"&&st!==null;if(oi)switch(st.$$typeof){case k:e:{for(oi=st.key,Wn=je;Wn!==null;){if(Wn.key===oi)if(Wn.tag===7?st.type===j:Wn.elementType===st.type){A(Ge,Wn.sibling),je=B(Wn,st.type===j?st.props.children:st.props,$t),je.ref=Us(Ge,Wn,st),je.return=Ge,Ge=je;break e}else{A(Ge,Wn);break}else g(Ge,Wn);Wn=Wn.sibling}st.type===j?(je=n0(st.props.children,Ge.mode,$t,st.key),je.return=Ge,Ge=je):($t=qa(st.type,st.key,st.props,null,Ge.mode,$t),$t.ref=Us(Ge,je,st),$t.return=Ge,Ge=$t)}return de(Ge);case x:e:{for(Wn=st.key;je!==null;){if(je.key===Wn)if(je.tag===4&&je.stateNode.containerInfo===st.containerInfo&&je.stateNode.implementation===st.implementation){A(Ge,je.sibling),je=B(je,st.children||[],$t),je.return=Ge,Ge=je;break e}else{A(Ge,je);break}else g(Ge,je);je=je.sibling}je=Df(st,Ge.mode,$t),je.return=Ge,Ge=je}return de(Ge)}if(typeof st=="string"||typeof st=="number")return st=""+st,je!==null&&je.tag===6?(A(Ge,je.sibling),je=B(je,st,$t),je.return=Ge,Ge=je):(A(Ge,je),je=j0(st,Ge.mode,$t),je.return=Ge,Ge=je),de(Ge);if(m0(st))return Ml(Ge,je,st,$t);if(ue(st))return i0(Ge,je,st,$t);if(oi&&zi(Ge,st),typeof st>"u"&&!Wn)switch(Ge.tag){case 1:case 0:throw Ge=Ge.type,Error(t(152,Ge.displayName||Ge.name||"Component"))}return A(Ge,je)}}var H=U(!0),Y=U(!1),ee={},Ce={current:ee},_e={current:ee},Oe={current:ee};function $(_){if(_===ee)throw Error(t(174));return _}function Ne(_,g){en(Oe,g,_),en(_e,_,_),en(Ce,ee,_),g=Pt(g),mi(Ce,_),en(Ce,g,_)}function Je(_){mi(Ce,_),mi(_e,_),mi(Oe,_)}function vt(_){var g=$(Oe.current),A=$(Ce.current);g=Jt(A,_.type,g),A!==g&&(en(_e,_,_),en(Ce,g,_))}function oe(_){_e.current===_&&(mi(Ce,_),mi(_e,_))}var qe={current:0};function rt(_){for(var g=_;g!==null;){if(g.tag===13){var A=g.memoizedState;if(A!==null&&(A=A.dehydrated,A===null||Kr(A)||Oo(A)))return g}else if(g.tag===19&&g.memoizedProps.revealOrder!==void 0){if((g.effectTag&64)!==0)return g}else if(g.child!==null){g.child.return=g,g=g.child;continue}if(g===_)break;for(;g.sibling===null;){if(g.return===null||g.return===_)return null;g=g.return}g.sibling.return=g.return,g=g.sibling}return null}function xt(_,g){return{responder:_,props:g}}var kt=N.ReactCurrentDispatcher,bt=N.ReactCurrentBatchConfig,sn=0,rn=null,Ft=null,Dn=null,dr=null,er=null,Cr=null,Rn=0,Nr=null,y0=0,Lr=!1,ut=null,wt=0;function et(){throw Error(t(321))}function It(_,g){if(g===null)return!1;for(var A=0;ARn&&(Rn=xr,Ua(Rn))):(cc(xr,Rt.suspenseConfig),Z=Rt.eagerReducer===_?Rt.eagerState:_(Z,Rt.action)),de=Rt,Rt=Rt.next}while(Rt!==null&&Rt!==P);Nt||(yt=de,B=Z),Fe(Z,g.memoizedState)||(ho=!0),g.memoizedState=Z,g.baseUpdate=yt,g.baseState=B,A.lastRenderedState=Z}return[g.memoizedState,A.dispatch]}function T0(_){var g=Jn();return typeof _=="function"&&(_=_()),g.memoizedState=g.baseState=_,_=g.queue={last:null,dispatch:null,lastRenderedReducer:au,lastRenderedState:_},_=_.dispatch=js.bind(null,rn,_),[g.memoizedState,_]}function Z0(_){return ku(au,_)}function Nu(_,g,A,P){return _={tag:_,create:g,destroy:A,deps:P,next:null},Nr===null?(Nr={lastEffect:null},Nr.lastEffect=_.next=_):(g=Nr.lastEffect,g===null?Nr.lastEffect=_.next=_:(A=g.next,g.next=_,_.next=A,Nr.lastEffect=_)),_}function gi(_,g,A,P){var B=Jn();y0|=_,B.memoizedState=Nu(g,A,void 0,P===void 0?null:P)}function Po(_,g,A,P){var B=wr();P=P===void 0?null:P;var Z=void 0;if(Ft!==null){var de=Ft.memoizedState;if(Z=de.destroy,P!==null&&It(P,de.deps)){Nu(0,A,Z,P);return}}y0|=_,B.memoizedState=Nu(g,A,Z,P)}function rl(_,g){return gi(516,192,_,g)}function hf(_,g){return Po(516,192,_,g)}function Tl(_,g){if(typeof g=="function")return _=_(),g(_),function(){g(null)};if(g!=null)return _=_(),g.current=_,function(){g.current=null}}function vf(){}function Io(_,g){return Jn().memoizedState=[_,g===void 0?null:g],_}function ys(_,g){var A=wr();g=g===void 0?null:g;var P=A.memoizedState;return P!==null&&g!==null&&It(g,P[1])?P[0]:(A.memoizedState=[_,g],_)}function js(_,g,A){if(!(25>wt))throw Error(t(301));var P=_.alternate;if(_===rn||P!==null&&P===rn)if(Lr=!0,_={expirationTime:sn,suspenseConfig:null,action:A,eagerReducer:null,eagerState:null,next:null},ut===null&&(ut=new Map),A=ut.get(g),A===void 0)ut.set(g,_);else{for(g=A;g.next!==null;)g=g.next;g.next=_}else{var B=E0(),Z=si.suspense;B=Un(B,_,Z),Z={expirationTime:B,suspenseConfig:Z,action:A,eagerReducer:null,eagerState:null,next:null};var de=g.last;if(de===null)Z.next=Z;else{var yt=de.next;yt!==null&&(Z.next=yt),de.next=Z}if(g.last=Z,_.expirationTime===0&&(P===null||P.expirationTime===0)&&(P=g.lastRenderedReducer,P!==null))try{var Rt=g.lastRenderedState,Nt=P(Rt,A);if(Z.eagerReducer=P,Z.eagerState=Nt,Fe(Nt,Rt))return}catch{}finally{}e0(_,B)}}var bo={readContext:Mu,useCallback:et,useContext:et,useEffect:et,useImperativeHandle:et,useLayoutEffect:et,useMemo:et,useReducer:et,useRef:et,useState:et,useDebugValue:et,useResponder:et,useDeferredValue:et,useTransition:et},Bo={readContext:Mu,useCallback:Io,useContext:Mu,useEffect:rl,useImperativeHandle:function(_,g,A){return A=A!=null?A.concat([_]):null,gi(4,36,Tl.bind(null,g,_),A)},useLayoutEffect:function(_,g){return gi(4,36,_,g)},useMemo:function(_,g){var A=Jn();return g=g===void 0?null:g,_=_(),A.memoizedState=[_,g],_},useReducer:function(_,g,A){var P=Jn();return g=A!==void 0?A(g):g,P.memoizedState=P.baseState=g,_=P.queue={last:null,dispatch:null,lastRenderedReducer:_,lastRenderedState:g},_=_.dispatch=js.bind(null,rn,_),[P.memoizedState,_]},useRef:function(_){var g=Jn();return _={current:_},g.memoizedState=_},useState:T0,useDebugValue:vf,useResponder:xt,useDeferredValue:function(_,g){var A=T0(_),P=A[0],B=A[1];return rl(function(){E.unstable_next(function(){var Z=bt.suspense;bt.suspense=g===void 0?null:g;try{B(_)}finally{bt.suspense=Z}})},[_,g]),P},useTransition:function(_){var g=T0(!1),A=g[0],P=g[1];return[Io(function(B){P(!0),E.unstable_next(function(){var Z=bt.suspense;bt.suspense=_===void 0?null:_;try{P(!1),B()}finally{bt.suspense=Z}})},[_,A]),A]}},gs={readContext:Mu,useCallback:ys,useContext:Mu,useEffect:hf,useImperativeHandle:function(_,g,A){return A=A!=null?A.concat([_]):null,Po(4,36,Tl.bind(null,g,_),A)},useLayoutEffect:function(_,g){return Po(4,36,_,g)},useMemo:function(_,g){var A=wr();g=g===void 0?null:g;var P=A.memoizedState;return P!==null&&g!==null&&It(g,P[1])?P[0]:(_=_(),A.memoizedState=[_,g],_)},useReducer:ku,useRef:function(){return wr().memoizedState},useState:Z0,useDebugValue:vf,useResponder:xt,useDeferredValue:function(_,g){var A=Z0(_),P=A[0],B=A[1];return hf(function(){E.unstable_next(function(){var Z=bt.suspense;bt.suspense=g===void 0?null:g;try{B(_)}finally{bt.suspense=Z}})},[_,g]),P},useTransition:function(_){var g=Z0(!1),A=g[0],P=g[1];return[ys(function(B){P(!0),E.unstable_next(function(){var Z=bt.suspense;bt.suspense=_===void 0?null:_;try{P(!1),B()}finally{bt.suspense=Z}})},[_,A]),A]}},Xu=null,Su=null,_i=!1;function C0(_,g){var A=Ho(5,null,null,0);A.elementType="DELETED",A.type="DELETED",A.stateNode=g,A.return=_,A.effectTag=8,_.lastEffect!==null?(_.lastEffect.nextEffect=A,_.lastEffect=A):_.firstEffect=_.lastEffect=A}function $0(_,g){switch(_.tag){case 5:return g=Bu(g,_.type,_.pendingProps),g!==null?(_.stateNode=g,!0):!1;case 6:return g=K0(g,_.pendingProps),g!==null?(_.stateNode=g,!0):!1;case 13:return!1;default:return!1}}function Uo(_){if(_i){var g=Su;if(g){var A=g;if(!$0(_,g)){if(g=Mo(A),!g||!$0(_,g)){_.effectTag=_.effectTag&-1025|2,_i=!1,Xu=_;return}C0(Xu,A)}Xu=_,Su=F0(g)}else _.effectTag=_.effectTag&-1025|2,_i=!1,Xu=_}}function la(_){for(_=_.return;_!==null&&_.tag!==5&&_.tag!==3&&_.tag!==13;)_=_.return;Xu=_}function $l(_){if(!S||_!==Xu)return!1;if(!_i)return la(_),_i=!0,!1;var g=_.type;if(_.tag!==5||g!=="head"&&g!=="body"&&!dt(g,_.memoizedProps))for(g=Su;g;)C0(_,g),g=Mo(g);if(la(_),_.tag===13){if(!S)throw Error(t(316));if(_=_.memoizedState,_=_!==null?_.dehydrated:null,!_)throw Error(t(317));Su=Ps(_)}else Su=Xu?Mo(_.stateNode):null;return!0}function tu(){S&&(Su=Xu=null,_i=!1)}var Zr=N.ReactCurrentOwner,ho=!1;function Bi(_,g,A,P){g.child=_===null?Y(g,null,A,P):H(g,_.child,A,P)}function Ci(_,g,A,P,B){A=A.render;var Z=g.ref;return Fo(g,B),P=un(_,g,A,P,Z,B),_!==null&&!ho?(g.updateQueue=_.updateQueue,g.effectTag&=-517,_.expirationTime<=B&&(_.expirationTime=0),mu(_,g,B)):(g.effectTag|=1,Bi(_,g,P,B),g.child)}function mf(_,g,A,P,B,Z){if(_===null){var de=A.type;return typeof de=="function"&&!Ef(de)&&de.defaultProps===void 0&&A.compare===null&&A.defaultProps===void 0?(g.tag=15,g.type=de,yf(_,g,de,P,B,Z)):(_=qa(A.type,null,P,null,g.mode,Z),_.ref=g.ref,_.return=g,g.child=_)}return de=_.child,Bg)&&Wr.set(_,g)))}}function ro(_,g){_.expirationTime_?g:_)}function t0(_){if(_.lastExpiredTime!==0)_.callbackExpirationTime=1073741823,_.callbackPriority=99,_.callbackNode=Jl(io.bind(null,_));else{var g=mo(_),A=_.callbackNode;if(g===0)A!==null&&(_.callbackNode=null,_.callbackExpirationTime=0,_.callbackPriority=90);else{var P=E0();if(g===1073741823?P=99:g===1||g===2?P=95:(P=10*(1073741821-g)-10*(1073741821-P),P=0>=P?99:250>=P?98:5250>=P?97:95),A!==null){var B=_.callbackPriority;if(_.callbackExpirationTime===g&&B>=P)return;A!==qr&&Is(A)}_.callbackExpirationTime=g,_.callbackPriority=P,g=g===1073741823?Jl(io.bind(null,_)):nl(P,jo.bind(null,_),{timeout:10*(1073741821-g)-h0()}),_.callbackNode=g}}}function jo(_,g){if(ru=0,g)return g=E0(),da(_,g),t0(_),null;var A=mo(_);if(A!==0){if(g=_.callbackNode,(Ln&(nu|fu))!==Rr)throw Error(t(327));if(qs(),_===fe&&A===Pe||Ds(_,A),ie!==null){var P=Ln;Ln|=nu;var B=U0(_);do try{nd();break}catch(yt){fa(_,yt)}while(1);if(ju(),Ln=P,Zu.current=B,Me===ei)throw g=at,Ds(_,A),Ol(_,A),t0(_),g;if(ie===null)switch(B=_.finishedWork=_.current.alternate,_.finishedExpirationTime=A,P=Me,fe=null,P){case Li:case ei:throw Error(t(345));case Kn:da(_,2=A){_.lastPingedTime=A,Ds(_,A);break}}if(Z=mo(_),Z!==0&&Z!==A)break;if(P!==0&&P!==A){_.lastPingedTime=P;break}_.timeoutHandle=an(Rl.bind(null,_),B);break}Rl(_);break;case g0:if(Ol(_,A),P=_.lastSuspendedTime,A===P&&(_.nextKnownPendingLevel=qc(B)),_n&&(B=_.lastPingedTime,B===0||B>=A)){_.lastPingedTime=A,Ds(_,A);break}if(B=mo(_),B!==0&&B!==A)break;if(P!==0&&P!==A){_.lastPingedTime=P;break}if(Qt!==1073741823?P=10*(1073741821-Qt)-h0():mt===1073741823?P=0:(P=10*(1073741821-mt)-5e3,B=h0(),A=10*(1073741821-A)-B,P=B-P,0>P&&(P=0),P=(120>P?120:480>P?480:1080>P?1080:1920>P?1920:3e3>P?3e3:4320>P?4320:1960*gf(P/1960))-P,A=P?P=0:(B=de.busyDelayMs|0,Z=h0()-(10*(1073741821-Z)-(de.timeoutMs|0||5e3)),P=Z<=B?0:B+P-Z),10 component higher in the tree to provide a loading indicator or placeholder to display.`+Hr(B))}Me!==_0&&(Me=Kn),Z=Cl(Z,B),Rt=P;do{switch(Rt.tag){case 3:de=Z,Rt.effectTag|=4096,Rt.expirationTime=g;var je=_s(Rt,de,g);ua(Rt,je);break e;case 1:de=Z;var st=Rt.type,$t=Rt.stateNode;if((Rt.effectTag&64)===0&&(typeof st.getDerivedStateFromError=="function"||$t!==null&&typeof $t.componentDidCatch=="function"&&(mr===null||!mr.has($t)))){Rt.effectTag|=4096,Rt.expirationTime=g;var Wn=aa(Rt,de,g);ua(Rt,Wn);break e}}Rt=Rt.return}while(Rt!==null)}ie=yo(ie)}catch(oi){g=oi;continue}break}while(1)}function U0(){var _=Zu.current;return Zu.current=bo,_===null?bo:_}function cc(_,g){_Sn&&(Sn=_)}function _2(){for(;ie!==null;)ie=rd(ie)}function nd(){for(;ie!==null&&!$n();)ie=rd(ie)}function rd(_){var g=Ha(_.alternate,_,Pe);return _.memoizedProps=_.pendingProps,g===null&&(g=yo(_)),Es.current=null,g}function yo(_){ie=_;do{var g=ie.alternate;if(_=ie.return,(ie.effectTag&2048)===0){e:{var A=g;g=ie;var P=Pe,B=g.pendingProps;switch(g.tag){case 2:break;case 16:break;case 15:case 0:break;case 1:eu(g.type)&&Q0(g);break;case 3:Je(g),Yi(g),B=g.stateNode,B.pendingContext&&(B.context=B.pendingContext,B.pendingContext=null),(A===null||A.child===null)&&$l(g)&&Qu(g),Qr(g);break;case 5:oe(g);var Z=$(Oe.current);if(P=g.type,A!==null&&g.stateNode!=null)qu(A,g,P,B,Z),A.ref!==g.ref&&(g.effectTag|=128);else if(B){if(A=$(Ce.current),$l(g)){if(B=g,!S)throw Error(t(175));A=su(B.stateNode,B.type,B.memoizedProps,Z,A,B),B.updateQueue=A,A=A!==null,A&&Qu(g)}else{var de=ce(P,B,Z,A,g);$r(de,g,!1,!1),g.stateNode=de,le(de,P,B,Z,A)&&Qu(g)}g.ref!==null&&(g.effectTag|=128)}else if(g.stateNode===null)throw Error(t(166));break;case 6:if(A&&g.stateNode!=null)xn(A,g,A.memoizedProps,B);else{if(typeof B!="string"&&g.stateNode===null)throw Error(t(166));if(A=$(Oe.current),Z=$(Ce.current),$l(g)){if(A=g,!S)throw Error(t(176));(A=ki(A.stateNode,A.memoizedProps,A))&&Qu(g)}else g.stateNode=nn(B,A,Z,g)}break;case 11:break;case 13:if(mi(qe,g),B=g.memoizedState,(g.effectTag&64)!==0){g.expirationTime=P;break e}B=B!==null,Z=!1,A===null?g.memoizedProps.fallback!==void 0&&$l(g):(P=A.memoizedState,Z=P!==null,B||P===null||(P=A.child.sibling,P!==null&&(de=g.firstEffect,de!==null?(g.firstEffect=P,P.nextEffect=de):(g.firstEffect=g.lastEffect=P,P.nextEffect=null),P.effectTag=8))),B&&!Z&&(g.mode&2)!==0&&(A===null&&g.memoizedProps.unstable_avoidThisFallback!==!0||(qe.current&1)!==0?Me===Li&&(Me=$u):((Me===Li||Me===$u)&&(Me=g0),Sn!==0&&fe!==null&&(Ol(fe,Pe),Ts(fe,Sn)))),Er&&B&&(g.effectTag|=4),Vt&&(B||Z)&&(g.effectTag|=4);break;case 7:break;case 8:break;case 12:break;case 4:Je(g),Qr(g);break;case 10:wu(g);break;case 9:break;case 14:break;case 17:eu(g.type)&&Q0(g);break;case 19:if(mi(qe,g),B=g.memoizedState,B===null)break;if(Z=(g.effectTag&64)!==0,de=B.rendering,de===null){if(Z)Lu(B,!1);else if(Me!==Li||A!==null&&(A.effectTag&64)!==0)for(A=g.child;A!==null;){if(de=rt(A),de!==null){for(g.effectTag|=64,Lu(B,!1),A=de.updateQueue,A!==null&&(g.updateQueue=A,g.effectTag|=4),B.lastEffect===null&&(g.firstEffect=null),g.lastEffect=B.lastEffect,A=P,B=g.child;B!==null;)Z=B,P=A,Z.effectTag&=2,Z.nextEffect=null,Z.firstEffect=null,Z.lastEffect=null,de=Z.alternate,de===null?(Z.childExpirationTime=0,Z.expirationTime=P,Z.child=null,Z.memoizedProps=null,Z.memoizedState=null,Z.updateQueue=null,Z.dependencies=null):(Z.childExpirationTime=de.childExpirationTime,Z.expirationTime=de.expirationTime,Z.child=de.child,Z.memoizedProps=de.memoizedProps,Z.memoizedState=de.memoizedState,Z.updateQueue=de.updateQueue,P=de.dependencies,Z.dependencies=P===null?null:{expirationTime:P.expirationTime,firstContext:P.firstContext,responders:P.responders}),B=B.sibling;en(qe,qe.current&1|2,g),g=g.child;break e}A=A.sibling}}else{if(!Z)if(A=rt(de),A!==null){if(g.effectTag|=64,Z=!0,A=A.updateQueue,A!==null&&(g.updateQueue=A,g.effectTag|=4),Lu(B,!0),B.tail===null&&B.tailMode==="hidden"&&!de.alternate){g=g.lastEffect=B.lastEffect,g!==null&&(g.nextEffect=null);break}}else h0()>B.tailExpiration&&1B&&(B=P),de>B&&(B=de),Z=Z.sibling;A.childExpirationTime=B}if(g!==null)return g;_!==null&&(_.effectTag&2048)===0&&(_.firstEffect===null&&(_.firstEffect=ie.firstEffect),ie.lastEffect!==null&&(_.lastEffect!==null&&(_.lastEffect.nextEffect=ie.firstEffect),_.lastEffect=ie.lastEffect),1_?g:_}function Rl(_){var g=hs();return co(99,ul.bind(null,_,g)),null}function ul(_,g){do qs();while(ti!==null);if((Ln&(nu|fu))!==Rr)throw Error(t(327));var A=_.finishedWork,P=_.finishedExpirationTime;if(A===null)return null;if(_.finishedWork=null,_.finishedExpirationTime=0,A===_.current)throw Error(t(177));_.callbackNode=null,_.callbackExpirationTime=0,_.callbackPriority=90,_.nextKnownPendingLevel=0;var B=qc(A);if(_.firstPendingTime=B,P<=_.lastSuspendedTime?_.firstSuspendedTime=_.lastSuspendedTime=_.nextKnownPendingLevel=0:P<=_.firstSuspendedTime&&(_.firstSuspendedTime=P-1),P<=_.lastPingedTime&&(_.lastPingedTime=0),P<=_.lastExpiredTime&&(_.lastExpiredTime=0),_===fe&&(ie=fe=null,Pe=0),1=A?Kt(_,g,A):(en(qe,qe.current&1,g),g=mu(_,g,A),g!==null?g.sibling:null);en(qe,qe.current&1,g);break;case 19:if(P=g.childExpirationTime>=A,(_.effectTag&64)!==0){if(P)return bn(_,g,A);g.effectTag|=64}if(B=g.memoizedState,B!==null&&(B.rendering=null,B.tail=null),en(qe,qe.current,g),!P)return null}return mu(_,g,A)}ho=!1}}else ho=!1;switch(g.expirationTime=0,g.tag){case 2:if(P=g.type,_!==null&&(_.alternate=null,g.alternate=null,g.effectTag|=2),_=g.pendingProps,B=Ru(g,Ai.current),Fo(g,A),B=un(null,g,P,_,B,A),g.effectTag|=1,typeof B=="object"&&B!==null&&typeof B.render=="function"&&B.$$typeof===void 0){if(g.tag=1,fn(),eu(P)){var Z=!0;li(g)}else Z=!1;g.memoizedState=B.state!==null&&B.state!==void 0?B.state:null;var de=P.getDerivedStateFromProps;typeof de=="function"&&Zl(g,P,de,_),B.updater=oa,g.stateNode=B,B._reactInternalFiber=g,Bs(g,P,_,A),g=tt(null,g,P,!0,Z,A)}else g.tag=0,Bi(null,g,B,A),g=g.child;return g;case 16:if(B=g.elementType,_!==null&&(_.alternate=null,g.alternate=null,g.effectTag|=2),_=g.pendingProps,Ae(B),B._status!==1)throw B._result;switch(B=B._result,g.type=B,Z=g.tag=ol(B),_=Yn(B,_),Z){case 0:g=to(null,g,B,_,A);break;case 1:g=xe(null,g,B,_,A);break;case 11:g=Ci(null,g,B,_,A);break;case 14:g=mf(null,g,B,Yn(B.type,_),P,A);break;default:throw Error(t(306,B,""))}return g;case 0:return P=g.type,B=g.pendingProps,B=g.elementType===P?B:Yn(P,B),to(_,g,P,B,A);case 1:return P=g.type,B=g.pendingProps,B=g.elementType===P?B:Yn(P,B),xe(_,g,P,B,A);case 3:if(Ke(g),P=g.updateQueue,P===null)throw Error(t(282));if(B=g.memoizedState,B=B!==null?B.element:null,S0(g,P,g.pendingProps,null,A),P=g.memoizedState.element,P===B)tu(),g=mu(_,g,A);else{if((B=g.stateNode.hydrate)&&(S?(Su=F0(g.stateNode.containerInfo),Xu=g,B=_i=!0):B=!1),B)for(A=Y(g,null,P,A),g.child=A;A;)A.effectTag=A.effectTag&-3|1024,A=A.sibling;else Bi(_,g,P,A),tu();g=g.child}return g;case 5:return vt(g),_===null&&Uo(g),P=g.type,B=g.pendingProps,Z=_!==null?_.memoizedProps:null,de=B.children,dt(P,B)?de=null:Z!==null&&dt(P,Z)&&(g.effectTag|=16),eo(_,g),g.mode&4&&A!==1&&At(P,B)?(g.expirationTime=g.childExpirationTime=1,g=null):(Bi(_,g,de,A),g=g.child),g;case 6:return _===null&&Uo(g),null;case 13:return Kt(_,g,A);case 4:return Ne(g,g.stateNode.containerInfo),P=g.pendingProps,_===null?g.child=H(g,null,P,A):Bi(_,g,P,A),g.child;case 11:return P=g.type,B=g.pendingProps,B=g.elementType===P?B:Yn(P,B),Ci(_,g,P,B,A);case 7:return Bi(_,g,g.pendingProps,A),g.child;case 8:return Bi(_,g,g.pendingProps.children,A),g.child;case 12:return Bi(_,g,g.pendingProps.children,A),g.child;case 10:e:{if(P=g.type._context,B=g.pendingProps,de=g.memoizedProps,Z=B.value,zu(g,Z),de!==null){var yt=de.value;if(Z=Fe(yt,Z)?0:(typeof P._calculateChangedBits=="function"?P._calculateChangedBits(yt,Z):1073741823)|0,Z===0){if(de.children===B.children&&!yi.current){g=mu(_,g,A);break e}}else for(yt=g.child,yt!==null&&(yt.return=g);yt!==null;){var Rt=yt.dependencies;if(Rt!==null){de=yt.child;for(var Nt=Rt.firstContext;Nt!==null;){if(Nt.context===P&&(Nt.observedBits&Z)!==0){yt.tag===1&&(Nt=v0(A,null),Nt.tag=2,J0(yt,Nt)),yt.expirationTime"u")return!1;var g=__REACT_DEVTOOLS_GLOBAL_HOOK__;if(g.isDisabled||!g.supportsFiber)return!0;try{var A=g.inject(_);ca=function(P){try{g.onCommitFiberRoot(A,P,void 0,(P.current.effectTag&64)===64)}catch{}},ws=function(P){try{g.onCommitFiberUnmount(A,P)}catch{}}}catch{}return!0}function ts(_,g,A,P){this.tag=_,this.key=A,this.sibling=this.child=this.return=this.stateNode=this.type=this.elementType=null,this.index=0,this.ref=null,this.pendingProps=g,this.dependencies=this.memoizedState=this.updateQueue=this.memoizedProps=null,this.mode=P,this.effectTag=0,this.lastEffect=this.firstEffect=this.nextEffect=null,this.childExpirationTime=this.expirationTime=0,this.alternate=null}function Ho(_,g,A,P){return new ts(_,g,A,P)}function Ef(_){return _=_.prototype,!(!_||!_.isReactComponent)}function ol(_){if(typeof _=="function")return Ef(_)?1:0;if(_!=null){if(_=_.$$typeof,_===De)return 11;if(_===we)return 14}return 2}function Vu(_,g){var A=_.alternate;return A===null?(A=Ho(_.tag,g,_.key,_.mode),A.elementType=_.elementType,A.type=_.type,A.stateNode=_.stateNode,A.alternate=_,_.alternate=A):(A.pendingProps=g,A.effectTag=0,A.nextEffect=null,A.firstEffect=null,A.lastEffect=null),A.childExpirationTime=_.childExpirationTime,A.expirationTime=_.expirationTime,A.child=_.child,A.memoizedProps=_.memoizedProps,A.memoizedState=_.memoizedState,A.updateQueue=_.updateQueue,g=_.dependencies,A.dependencies=g===null?null:{expirationTime:g.expirationTime,firstContext:g.firstContext,responders:g.responders},A.sibling=_.sibling,A.index=_.index,A.ref=_.ref,A}function qa(_,g,A,P,B,Z){var de=2;if(P=_,typeof _=="function")Ef(_)&&(de=1);else if(typeof _=="string")de=5;else e:switch(_){case j:return n0(A.children,B,Z,g);case me:de=8,B|=7;break;case q:de=8,B|=1;break;case V:return _=Ho(12,A,g,B|8),_.elementType=V,_.type=V,_.expirationTime=Z,_;case ge:return _=Ho(13,A,g,B),_.type=ge,_.elementType=ge,_.expirationTime=Z,_;case ae:return _=Ho(19,A,g,B),_.elementType=ae,_.expirationTime=Z,_;default:if(typeof _=="object"&&_!==null)switch(_.$$typeof){case re:de=10;break e;case y:de=9;break e;case De:de=11;break e;case we:de=14;break e;case he:de=16,P=null;break e}throw Error(t(130,_==null?_:typeof _,""))}return g=Ho(de,A,g,B),g.elementType=_,g.type=P,g.expirationTime=Z,g}function n0(_,g,A,P){return _=Ho(7,_,P,g),_.expirationTime=A,_}function j0(_,g,A){return _=Ho(6,_,null,g),_.expirationTime=A,_}function Df(_,g,A){return g=Ho(4,_.children!==null?_.children:[],_.key,g),g.expirationTime=A,g.stateNode={containerInfo:_.containerInfo,pendingChildren:null,implementation:_.implementation},g}function Wc(_,g,A){this.tag=g,this.current=null,this.containerInfo=_,this.pingCache=this.pendingChildren=null,this.finishedExpirationTime=0,this.finishedWork=null,this.timeoutHandle=lr,this.pendingContext=this.context=null,this.hydrate=A,this.callbackNode=null,this.callbackPriority=90,this.lastExpiredTime=this.lastPingedTime=this.nextKnownPendingLevel=this.lastSuspendedTime=this.firstSuspendedTime=this.firstPendingTime=0}function dc(_,g){var A=_.firstSuspendedTime;return _=_.lastSuspendedTime,A!==0&&A>=g&&_<=g}function Ol(_,g){var A=_.firstSuspendedTime,P=_.lastSuspendedTime;Ag||A===0)&&(_.lastSuspendedTime=g),g<=_.lastPingedTime&&(_.lastPingedTime=0),g<=_.lastExpiredTime&&(_.lastExpiredTime=0)}function Ts(_,g){g>_.firstPendingTime&&(_.firstPendingTime=g);var A=_.firstSuspendedTime;A!==0&&(g>=A?_.firstSuspendedTime=_.lastSuspendedTime=_.nextKnownPendingLevel=0:g>=_.lastSuspendedTime&&(_.lastSuspendedTime=g+1),g>_.nextKnownPendingLevel&&(_.nextKnownPendingLevel=g))}function da(_,g){var A=_.lastExpiredTime;(A===0||A>g)&&(_.lastExpiredTime=g)}function ud(_){var g=_._reactInternalFiber;if(g===void 0)throw typeof _.render=="function"?Error(t(188)):Error(t(268,Object.keys(_)));return _=Qe(g),_===null?null:_.stateNode}function pa(_,g){_=_.memoizedState,_!==null&&_.dehydrated!==null&&_.retryTime{"use strict";Object.defineProperty(ec,"__esModule",{value:!0});var _P=0;ec.__interactionsRef=null;ec.__subscriberRef=null;ec.unstable_clear=function(o){return o()};ec.unstable_getCurrent=function(){return null};ec.unstable_getThreadID=function(){return++_P};ec.unstable_trace=function(o,l,f){return f()};ec.unstable_wrap=function(o){return o};ec.unstable_subscribe=function(){};ec.unstable_unsubscribe=function(){}});var WS=nt(vu=>{"use strict";process.env.NODE_ENV!=="production"&&function(){"use strict";Object.defineProperty(vu,"__esModule",{value:!0});var o=!0,l=0,f=0,h=0;vu.__interactionsRef=null,vu.__subscriberRef=null,o&&(vu.__interactionsRef={current:new Set},vu.__subscriberRef={current:null});function E(ae){if(!o)return ae();var we=vu.__interactionsRef.current;vu.__interactionsRef.current=new Set;try{return ae()}finally{vu.__interactionsRef.current=we}}function t(){return o?vu.__interactionsRef.current:null}function N(){return++h}function F(ae,we,he){var ve=arguments.length>3&&arguments[3]!==void 0?arguments[3]:l;if(!o)return he();var ue={__count:1,id:f++,name:ae,timestamp:we},Ae=vu.__interactionsRef.current,ze=new Set(Ae);ze.add(ue),vu.__interactionsRef.current=ze;var We=vu.__subscriberRef.current,gt;try{We!==null&&We.onInteractionTraced(ue)}finally{try{We!==null&&We.onWorkStarted(ze,ve)}finally{try{gt=he()}finally{vu.__interactionsRef.current=Ae;try{We!==null&&We.onWorkStopped(ze,ve)}finally{ue.__count--,We!==null&&ue.__count===0&&We.onInteractionScheduledWorkCompleted(ue)}}}}return gt}function k(ae){var we=arguments.length>1&&arguments[1]!==void 0?arguments[1]:l;if(!o)return ae;var he=vu.__interactionsRef.current,ve=vu.__subscriberRef.current;ve!==null&&ve.onWorkScheduled(he,we),he.forEach(function(ze){ze.__count++});var ue=!1;function Ae(){var ze=vu.__interactionsRef.current;vu.__interactionsRef.current=he,ve=vu.__subscriberRef.current;try{var We;try{ve!==null&&ve.onWorkStarted(he,we)}finally{try{We=ae.apply(void 0,arguments)}finally{vu.__interactionsRef.current=ze,ve!==null&&ve.onWorkStopped(he,we)}}return We}finally{ue||(ue=!0,he.forEach(function(gt){gt.__count--,ve!==null&>.__count===0&&ve.onInteractionScheduledWorkCompleted(gt)}))}}return Ae.cancel=function(){ve=vu.__subscriberRef.current;try{ve!==null&&ve.onWorkCanceled(he,we)}finally{he.forEach(function(We){We.__count--,ve&&We.__count===0&&ve.onInteractionScheduledWorkCompleted(We)})}},Ae}var x=null;o&&(x=new Set);function j(ae){o&&(x.add(ae),x.size===1&&(vu.__subscriberRef.current={onInteractionScheduledWorkCompleted:re,onInteractionTraced:V,onWorkCanceled:ge,onWorkScheduled:y,onWorkStarted:me,onWorkStopped:De}))}function q(ae){o&&(x.delete(ae),x.size===0&&(vu.__subscriberRef.current=null))}function V(ae){var we=!1,he=null;if(x.forEach(function(ve){try{ve.onInteractionTraced(ae)}catch(ue){we||(we=!0,he=ue)}}),we)throw he}function re(ae){var we=!1,he=null;if(x.forEach(function(ve){try{ve.onInteractionScheduledWorkCompleted(ae)}catch(ue){we||(we=!0,he=ue)}}),we)throw he}function y(ae,we){var he=!1,ve=null;if(x.forEach(function(ue){try{ue.onWorkScheduled(ae,we)}catch(Ae){he||(he=!0,ve=Ae)}}),he)throw ve}function me(ae,we){var he=!1,ve=null;if(x.forEach(function(ue){try{ue.onWorkStarted(ae,we)}catch(Ae){he||(he=!0,ve=Ae)}}),he)throw ve}function De(ae,we){var he=!1,ve=null;if(x.forEach(function(ue){try{ue.onWorkStopped(ae,we)}catch(Ae){he||(he=!0,ve=Ae)}}),he)throw ve}function ge(ae,we){var he=!1,ve=null;if(x.forEach(function(ue){try{ue.onWorkCanceled(ae,we)}catch(Ae){he||(he=!0,ve=Ae)}}),he)throw ve}vu.unstable_clear=E,vu.unstable_getCurrent=t,vu.unstable_getThreadID=N,vu.unstable_trace=F,vu.unstable_wrap=k,vu.unstable_subscribe=j,vu.unstable_unsubscribe=q}()});var VS=nt((_H,vD)=>{"use strict";process.env.NODE_ENV==="production"?vD.exports=qS():vD.exports=WS()});var GS=nt((EH,Yy)=>{"use strict";process.env.NODE_ENV!=="production"&&(Yy.exports=function o(l){"use strict";var f=Py(),h=Mi(),E=XE(),t=z_(),N=VS(),F=0,k=1,x=2,j=3,q=4,V=5,re=6,y=7,me=8,De=9,ge=10,ae=11,we=12,he=13,ve=14,ue=15,Ae=16,ze=17,We=18,gt=19,_t=20,Qe=21,ot=function(){};ot=function(c,d){for(var D=arguments.length,C=new Array(D>2?D-2:0),O=2;O8)throw new Error("warningWithoutStack() currently supports at most 8 arguments.");if(!c){if(typeof console<"u"){var z=C.map(function(se){return""+se});z.unshift("Warning: "+d),Function.prototype.apply.call(console.error,console,z)}try{var G=0,ne="Warning: "+d.replace(/%s/g,function(){return C[G++]});throw new Error(ne)}catch{}}};var Ve=ot;function Pt(c){return c._reactInternalFiber}function Jt(c,d){c._reactInternalFiber=d}var it=h.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;it.hasOwnProperty("ReactCurrentDispatcher")||(it.ReactCurrentDispatcher={current:null}),it.hasOwnProperty("ReactCurrentBatchConfig")||(it.ReactCurrentBatchConfig={suspense:null});var J=typeof Symbol=="function"&&Symbol.for,ce=J?Symbol.for("react.element"):60103,Re=J?Symbol.for("react.portal"):60106,le=J?Symbol.for("react.fragment"):60107,He=J?Symbol.for("react.strict_mode"):60108,dt=J?Symbol.for("react.profiler"):60114,At=J?Symbol.for("react.provider"):60109,nn=J?Symbol.for("react.context"):60110,an=J?Symbol.for("react.concurrent_mode"):60111,On=J?Symbol.for("react.forward_ref"):60112,lr=J?Symbol.for("react.suspense"):60113,ln=J?Symbol.for("react.suspense_list"):60120,Vt=J?Symbol.for("react.memo"):60115,Er=J?Symbol.for("react.lazy"):60116,S=J?Symbol.for("react.fundamental"):60117,zt=J?Symbol.for("react.responder"):60118,Xn=J?Symbol.for("react.scope"):60119,vr=typeof Symbol=="function"&&Symbol.iterator,jr="@@iterator";function fr(c){if(c===null||typeof c!="object")return null;var d=vr&&c[vr]||c[jr];return typeof d=="function"?d:null}var zr=Ve;zr=function(c,d){if(!c){for(var D=it.ReactDebugCurrentFrame,C=D.getStackAddendum(),O=arguments.length,z=new Array(O>2?O-2:0),G=2;G import('./MyComponent'))`,C),c._status=Ao,c._result=O}},function(C){c._status===c0&&(c._status=Jo,c._result=C)})}}function $o(c,d,D){var C=d.displayName||d.name||"";return c.displayName||(C!==""?D+"("+C+")":D)}function qt(c){if(c==null)return null;if(typeof c.tag=="number"&&Ve(!1,"Received an unexpected object in getComponentName(). This is likely a bug in React. Please file an issue."),typeof c=="function")return c.displayName||c.name||null;if(typeof c=="string")return c;switch(c){case le:return"Fragment";case Re:return"Portal";case dt:return"Profiler";case He:return"StrictMode";case lr:return"Suspense";case ln:return"SuspenseList"}if(typeof c=="object")switch(c.$$typeof){case nn:return"Context.Consumer";case At:return"Context.Provider";case On:return $o(c,c.render,"ForwardRef");case Vt:return qt(c.type);case Er:{var d=c,D=Fs(d);if(D)return qt(D);break}}return null}var xi=0,lu=1,vi=2,Dr=4,el=6,Y0=8,Bu=16,K0=32,Kr=64,Oo=128,Mo=256,F0=512,su=1024,ki=1028,Ps=932,Kl=2047,P0=2048,d0=4096,Hr=!0,Ri=!0,X0=!0,mi=!0,en=!0,In=!0,Ai=!1,yi=!1,Wt=!1,Ru=!1,eu=!1,Q0=!0,Yi=!1,Xl=!1,ko=!1,li=!1,ao=!1,Ql=it.ReactCurrentOwner;function No(c){var d=c,D=c;if(c.alternate)for(;d.return;)d=d.return;else{var C=d;do d=C,(d.effectTag&(vi|su))!==xi&&(D=d.return),C=d.return;while(C)}return d.tag===j?D:null}function Is(c){return No(c)===c}function $n(c){{var d=Ql.current;if(d!==null&&d.tag===k){var D=d,C=D.stateNode;C._warnedAboutRefsInRender||Ve(!1,"%s is accessing isMounted inside its render() function. render() should be a pure function of props and state. It should never access something that requires stale data from the previous render, such as refs. Move this logic to componentDidMount and componentDidUpdate instead.",qt(D.type)||"A component"),C._warnedAboutRefsInRender=!0}}var O=Pt(c);return O?No(O)===O:!1}function tl(c){if(No(c)!==c)throw Error("Unable to find node on an unmounted component.")}function fo(c){var d=c.alternate;if(!d){var D=No(c);if(D===null)throw Error("Unable to find node on an unmounted component.");return D!==c?null:c}for(var C=c,O=d;;){var z=C.return;if(z===null)break;var G=z.alternate;if(G===null){var ne=z.return;if(ne!==null){C=O=ne;continue}break}if(z.child===G.child){for(var se=z.child;se;){if(se===C)return tl(z),c;if(se===O)return tl(z),d;se=se.sibling}throw Error("Unable to find node on an unmounted component.")}if(C.return!==O.return)C=z,O=G;else{for(var Ue=!1,Xe=z.child;Xe;){if(Xe===C){Ue=!0,C=z,O=G;break}if(Xe===O){Ue=!0,O=z,C=G;break}Xe=Xe.sibling}if(!Ue){for(Xe=G.child;Xe;){if(Xe===C){Ue=!0,C=G,O=z;break}if(Xe===O){Ue=!0,O=G,C=z;break}Xe=Xe.sibling}if(!Ue)throw Error("Child was not found in either parent set. This indicates a bug in React related to the return pointer. Please file an issue.")}}if(C.alternate!==O)throw Error("Return fibers should always be each others' alternates. This error is likely caused by a bug in React. Please file an issue.")}if(C.tag!==j)throw Error("Unable to find node on an unmounted component.");return C.stateNode.current===C?c:d}function I0(c){var d=fo(c);if(!d)return null;for(var D=d;;){if(D.tag===V||D.tag===re)return D;if(D.child){D.child.return=D,D=D.child;continue}if(D===d)return null;for(;!D.sibling;){if(!D.return||D.return===d)return null;D=D.return}D.sibling.return=D.return,D=D.sibling}return null}function Sl(c){var d=fo(c);if(!d)return null;for(var D=d;;){if(D.tag===V||D.tag===re||Wt&&D.tag===_t)return D;if(D.child&&D.tag!==q){D.child.return=D,D=D.child;continue}if(D===d)return null;for(;!D.sibling;){if(!D.return||D.return===d)return null;D=D.return}D.sibling.return=D.return,D=D.sibling}return null}var Lo=l.getPublicInstance,St=l.getRootHostContext,Bt=l.getChildHostContext,Hn=l.prepareForCommit,qr=l.resetAfterCommit,Ki=l.createInstance,Xr=l.appendInitialChild,Au=l.finalizeInitialChildren,p0=l.prepareUpdate,Ni=l.shouldSetTextContent,h0=l.shouldDeprioritizeSubtree,hs=l.createTextInstance,Ct=l.setTimeout,co=l.clearTimeout,nl=l.noTimeout,Jl=l.now,Uu=l.isPrimaryRenderer,vs=l.warnsIfNotActing,b0=l.supportsMutation,Q=l.supportsPersistence,Se=l.supportsHydration,Fe=l.mountResponderInstance,Le=l.unmountResponderInstance,pt=l.getFundamentalComponentInstance,Yn=l.mountFundamentalComponent,Cn=l.shouldUpdateFundamentalComponent,cr=l.getInstanceFromNode,Si=l.appendChild,Ou=l.appendChildToContainer,ju=l.commitTextUpdate,zu=l.commitMount,wu=l.commitUpdate,Ti=l.insertBefore,Fo=l.insertInContainerBefore,Mu=l.removeChild,po=l.removeChildFromContainer,Hu=l.resetTextContent,Pa=l.hideInstance,v0=l.hideTextInstance,ia=l.unhideInstance,J0=l.unhideTextInstance,ua=l.updateFundamentalComponent,Ia=l.unmountFundamentalComponent,ms=l.cloneInstance,S0=l.createContainerChildSet,Qn=l.appendChildToContainerChildSet,ac=l.finalizeContainerChildren,si=l.replaceContainerChildren,Jr=l.cloneHiddenInstance,Zl=l.cloneHiddenTextInstance,oa=l.cloneInstance,pf=l.canHydrateInstance,bs=l.canHydrateTextInstance,ba=l.canHydrateSuspenseInstance,Bs=l.isSuspenseInstancePending,m0=l.isSuspenseInstanceFallback,Us=l.registerSuspenseInstanceRetry,zi=l.getNextHydratableSibling,U=l.getFirstHydratableChild,H=l.hydrateInstance,Y=l.hydrateTextInstance,ee=l.hydrateSuspenseInstance,Ce=l.getNextHydratableInstanceAfterSuspenseInstance,_e=l.commitHydratedContainer,Oe=l.commitHydratedSuspenseInstance,$=l.clearSuspenseBoundary,Ne=l.clearSuspenseBoundaryFromContainer,Je=l.didNotMatchHydratedContainerTextInstance,vt=l.didNotMatchHydratedTextInstance,oe=l.didNotHydrateContainerInstance,qe=l.didNotHydrateInstance,rt=l.didNotFindHydratableContainerInstance,xt=l.didNotFindHydratableContainerTextInstance,kt=l.didNotFindHydratableContainerSuspenseInstance,bt=l.didNotFindHydratableInstance,sn=l.didNotFindHydratableTextInstance,rn=l.didNotFindHydratableSuspenseInstance,Ft=/^(.*)[\\\/]/,Dn=function(c,d,D){var C="";if(d){var O=d.fileName,z=O.replace(Ft,"");if(/^index\./.test(z)){var G=O.match(Ft);if(G){var ne=G[1];if(ne){var se=ne.replace(Ft,"");z=se+"/"+z}}}C=" (at "+z+":"+d.lineNumber+")"}else D&&(C=" (created by "+D+")");return` + in `+(c||"Unknown")+C},dr=it.ReactDebugCurrentFrame;function er(c){switch(c.tag){case j:case q:case re:case y:case ge:case De:return"";default:var d=c._debugOwner,D=c._debugSource,C=qt(c.type),O=null;return d&&(O=qt(d.type)),Dn(C,D,O)}}function Cr(c){var d="",D=c;do d+=er(D),D=D.return;while(D);return d}var Rn=null,Nr=null;function y0(){{if(Rn===null)return null;var c=Rn._debugOwner;if(c!==null&&typeof c<"u")return qt(c.type)}return null}function Lr(){return Rn===null?"":Cr(Rn)}function ut(){dr.getCurrentStack=null,Rn=null,Nr=null}function wt(c){dr.getCurrentStack=Lr,Rn=c,Nr=null}function et(c){Nr=c}var It="\u269B",un="\u26D4",fn=typeof performance<"u"&&typeof performance.mark=="function"&&typeof performance.clearMarks=="function"&&typeof performance.measure=="function"&&typeof performance.clearMeasures=="function",Jn=null,wr=null,au=null,ku=!1,T0=!1,Z0=!1,Nu=0,gi=0,Po=new Set,rl=function(c){return It+" "+c},hf=function(c,d){var D=d?un+" ":It+" ",C=d?" Warning: "+d:"";return""+D+c+C},Tl=function(c){performance.mark(rl(c))},vf=function(c){performance.clearMarks(rl(c))},Io=function(c,d,D){var C=rl(d),O=hf(c,D);try{performance.measure(O,C)}catch{}performance.clearMarks(C),performance.clearMeasures(O)},ys=function(c,d){return c+" (#"+d+")"},js=function(c,d,D){return D===null?c+" ["+(d?"update":"mount")+"]":c+"."+D},bo=function(c,d){var D=qt(c.type)||"Unknown",C=c._debugID,O=c.alternate!==null,z=js(D,O,d);if(ku&&Po.has(z))return!1;Po.add(z);var G=ys(z,C);return Tl(G),!0},Bo=function(c,d){var D=qt(c.type)||"Unknown",C=c._debugID,O=c.alternate!==null,z=js(D,O,d),G=ys(z,C);vf(G)},gs=function(c,d,D){var C=qt(c.type)||"Unknown",O=c._debugID,z=c.alternate!==null,G=js(C,z,d),ne=ys(G,O);Io(G,ne,D)},Xu=function(c){switch(c.tag){case j:case V:case re:case q:case y:case ge:case De:case me:return!0;default:return!1}},Su=function(){wr!==null&&au!==null&&Bo(au,wr),au=null,wr=null,Z0=!1},_i=function(){for(var c=Jn;c;)c._debugIsCurrentlyTiming&&gs(c,null,null),c=c.return},C0=function(c){c.return!==null&&C0(c.return),c._debugIsCurrentlyTiming&&bo(c,null)},$0=function(){Jn!==null&&C0(Jn)};function Uo(){Hr&&gi++}function la(){Hr&&(ku&&(T0=!0),wr!==null&&wr!=="componentWillMount"&&wr!=="componentWillReceiveProps"&&(Z0=!0))}function $l(c){if(Hr){if(!fn||Xu(c)||(Jn=c,!bo(c,null)))return;c._debugIsCurrentlyTiming=!0}}function tu(c){if(Hr){if(!fn||Xu(c))return;c._debugIsCurrentlyTiming=!1,Bo(c,null)}}function Zr(c){if(Hr){if(!fn||Xu(c)||(Jn=c.return,!c._debugIsCurrentlyTiming))return;c._debugIsCurrentlyTiming=!1,gs(c,null,null)}}function ho(c){if(Hr){if(!fn||Xu(c)||(Jn=c.return,!c._debugIsCurrentlyTiming))return;c._debugIsCurrentlyTiming=!1;var d=c.tag===he?"Rendering was suspended":"An error was thrown inside this error boundary";gs(c,null,d)}}function Bi(c,d){if(Hr){if(!fn||(Su(),!bo(c,d)))return;au=c,wr=d}}function Ci(){if(Hr){if(!fn)return;if(wr!==null&&au!==null){var c=Z0?"Scheduled a cascading update":null;gs(au,wr,c)}wr=null,au=null}}function mf(c){if(Hr){if(Jn=c,!fn)return;Nu=0,Tl("(React Tree Reconciliation)"),$0()}}function yf(c,d){if(Hr){if(!fn)return;var D=null;if(c!==null)if(c.tag===j)D="A top-level update interrupted the previous render";else{var C=qt(c.type)||"Unknown";D="An update to "+C+" interrupted the previous render"}else Nu>1&&(D="There were cascading updates");Nu=0;var O=d?"(React Tree Reconciliation: Completed Root)":"(React Tree Reconciliation: Yielded)";_i(),Io(O,"(React Tree Reconciliation)",D)}}function eo(){if(Hr){if(!fn)return;ku=!0,T0=!1,Po.clear(),Tl("(Committing Changes)")}}function to(){if(Hr){if(!fn)return;var c=null;T0?c="Lifecycle hook scheduled a cascading update":Nu>0&&(c="Caused by a cascading update in earlier commit"),T0=!1,Nu++,ku=!1,Po.clear(),Io("(Committing Changes)","(Committing Changes)",c)}}function xe(){if(Hr){if(!fn)return;gi=0,Tl("(Committing Snapshot Effects)")}}function tt(){if(Hr){if(!fn)return;var c=gi;gi=0,Io("(Committing Snapshot Effects: "+c+" Total)","(Committing Snapshot Effects)",null)}}function Ke(){if(Hr){if(!fn)return;gi=0,Tl("(Committing Host Effects)")}}function Yt(){if(Hr){if(!fn)return;var c=gi;gi=0,Io("(Committing Host Effects: "+c+" Total)","(Committing Host Effects)",null)}}function Kt(){if(Hr){if(!fn)return;gi=0,Tl("(Calling Lifecycle Methods)")}}function pr(){if(Hr){if(!fn)return;var c=gi;gi=0,Io("(Calling Lifecycle Methods: "+c+" Total)","(Calling Lifecycle Methods)",null)}}var Ei=[],bn;bn=[];var mu=-1;function Qu(c){return{current:c}}function $r(c,d){if(mu<0){Ve(!1,"Unexpected pop.");return}d!==bn[mu]&&Ve(!1,"Unexpected Fiber popped."),c.current=Ei[mu],Ei[mu]=null,bn[mu]=null,mu--}function Qr(c,d,D){mu++,Ei[mu]=c.current,bn[mu]=D,c.current=d}var qu;qu={};var xn={};Object.freeze(xn);var x0=Qu(xn),Lu=Qu(!1),ui=xn;function Cl(c,d,D){return li?xn:D&&Xi(d)?ui:x0.current}function zs(c,d,D){if(!li){var C=c.stateNode;C.__reactInternalMemoizedUnmaskedChildContext=d,C.__reactInternalMemoizedMaskedChildContext=D}}function Wu(c,d){if(li)return xn;var D=c.type,C=D.contextTypes;if(!C)return xn;var O=c.stateNode;if(O&&O.__reactInternalMemoizedUnmaskedChildContext===d)return O.__reactInternalMemoizedMaskedChildContext;var z={};for(var G in C)z[G]=d[G];{var ne=qt(D)||"Unknown";E(C,z,"context",ne,Lr)}return O&&zs(c,d,z),z}function sa(){return li?!1:Lu.current}function Xi(c){if(li)return!1;var d=c.childContextTypes;return d!=null}function Hs(c){li||($r(Lu,c),$r(x0,c))}function R0(c){li||($r(Lu,c),$r(x0,c))}function Hi(c,d,D){if(!li){if(x0.current!==xn)throw Error("Unexpected context found on stack. This error is likely caused by a bug in React. Please file an issue.");Qr(x0,d,c),Qr(Lu,D,c)}}function A0(c,d,D){if(li)return D;var C=c.stateNode,O=d.childContextTypes;if(typeof C.getChildContext!="function"){{var z=qt(d)||"Unknown";qu[z]||(qu[z]=!0,Ve(!1,"%s.childContextTypes is specified but there is no getChildContext() method on the instance. You can either define getChildContext() on %s or remove childContextTypes from it.",z,z))}return D}var G;et("getChildContext"),Bi(c,"getChildContext"),G=C.getChildContext(),Ci(),et(null);for(var ne in G)if(!(ne in O))throw Error((qt(d)||"Unknown")+'.getChildContext(): key "'+ne+'" is not defined in childContextTypes.');{var se=qt(d)||"Unknown";E(O,G,"child context",se,Lr)}return f({},D,{},G)}function qi(c){if(li)return!1;var d=c.stateNode,D=d&&d.__reactInternalMemoizedMergedChildContext||xn;return ui=x0.current,Qr(x0,D,c),Qr(Lu,Lu.current,c),!0}function il(c,d,D){if(!li){var C=c.stateNode;if(!C)throw Error("Expected to have an instance by this point. This error is likely caused by a bug in React. Please file an issue.");if(D){var O=A0(c,d,ui);C.__reactInternalMemoizedMergedChildContext=O,$r(Lu,c),$r(x0,c),Qr(x0,O,c),Qr(Lu,D,c)}else $r(Lu,c),Qr(Lu,D,c)}}function xl(c){if(li)return xn;if(!(Is(c)&&c.tag===k))throw Error("Expected subtree parent to be a mounted class component. This error is likely caused by a bug in React. Please file an issue.");var d=c;do{switch(d.tag){case j:return d.stateNode.context;case k:{var D=d.type;if(Xi(D))return d.stateNode.__reactInternalMemoizedMergedChildContext;break}}d=d.return}while(d!==null);throw Error("Found unexpected detached subtree parent. This error is likely caused by a bug in React. Please file an issue.")}var B0=1,O0=2,vo=t.unstable_runWithPriority,Fu=t.unstable_scheduleCallback,Ju=t.unstable_cancelCallback,es=t.unstable_shouldYield,_s=t.unstable_requestPaint,aa=t.unstable_now,gf=t.unstable_getCurrentPriorityLevel,Zu=t.unstable_ImmediatePriority,Es=t.unstable_UserBlockingPriority,Rr=t.unstable_NormalPriority,no=t.unstable_LowPriority,nu=t.unstable_IdlePriority;if(In&&!(N.__interactionsRef!=null&&N.__interactionsRef.current!=null))throw Error("It is not supported to run the profiling version of a renderer (for example, `react-dom/profiling`) without also replacing the `scheduler/tracing` module with `scheduler/tracing-profiling`. Your bundler might have a setting for aliasing both modules. Learn more at http://fb.me/react-profiling");var fu={},Li=99,ei=98,Kn=97,$u=96,g0=95,_0=90,Ln=es,fe=_s!==void 0?_s:function(){},ie=null,Pe=null,Me=!1,at=aa(),mt=at<1e4?aa:function(){return aa()-at};function Qt(){switch(gf()){case Zu:return Li;case Es:return ei;case Rr:return Kn;case no:return $u;case nu:return g0;default:throw Error("Unknown priority level.")}}function An(c){switch(c){case Li:return Zu;case ei:return Es;case Kn:return Rr;case $u:return no;case g0:return nu;default:throw Error("Unknown priority level.")}}function Sn(c,d){var D=An(c);return vo(D,d)}function _n(c,d,D){var C=An(c);return Fu(C,d,D)}function Tn(c){return ie===null?(ie=[c],Pe=Fu(Zu,Fi)):ie.push(c),fu}function ir(c){c!==fu&&Ju(c)}function Ut(){if(Pe!==null){var c=Pe;Pe=null,Ju(c)}Fi()}function Fi(){if(!Me&&ie!==null){Me=!0;var c=0;try{var d=!0,D=ie;Sn(Li,function(){for(;c1?d-1:0),C=1;C2?D-2:0),O=2;O0&&(ja.forEach(function(Lt){c.add(qt(Lt.type)||"Component"),ts.add(Lt.type)}),ja=[]);var d=new Set;za.length>0&&(za.forEach(function(Lt){d.add(qt(Lt.type)||"Component"),ts.add(Lt.type)}),za=[]);var D=new Set;Ha.length>0&&(Ha.forEach(function(Lt){D.add(qt(Lt.type)||"Component"),ts.add(Lt.type)}),Ha=[]);var C=new Set;ca.length>0&&(ca.forEach(function(Lt){C.add(qt(Lt.type)||"Component"),ts.add(Lt.type)}),ca=[]);var O=new Set;ws.length>0&&(ws.forEach(function(Lt){O.add(qt(Lt.type)||"Component"),ts.add(Lt.type)}),ws=[]);var z=new Set;if(Ss.length>0&&(Ss.forEach(function(Lt){z.add(qt(Lt.type)||"Component"),ts.add(Lt.type)}),Ss=[]),d.size>0){var G=zo(d);Ve(!1,`Using UNSAFE_componentWillMount in strict mode is not recommended and may indicate bugs in your code. See https://fb.me/react-unsafe-component-lifecycles for details. + +* Move code with side effects to componentDidMount, and set initial state in the constructor. + +Please update the following components: %s`,G)}if(C.size>0){var ne=zo(C);Ve(!1,`Using UNSAFE_componentWillReceiveProps in strict mode is not recommended and may indicate bugs in your code. See https://fb.me/react-unsafe-component-lifecycles for details. + +* Move data fetching code or side effects to componentDidUpdate. +* If you're updating state whenever props change, refactor your code to use memoization techniques or move it to static getDerivedStateFromProps. Learn more at: https://fb.me/react-derived-state + +Please update the following components: %s`,ne)}if(z.size>0){var se=zo(z);Ve(!1,`Using UNSAFE_componentWillUpdate in strict mode is not recommended and may indicate bugs in your code. See https://fb.me/react-unsafe-component-lifecycles for details. + +* Move data fetching code or side effects to componentDidUpdate. + +Please update the following components: %s`,se)}if(c.size>0){var Ue=zo(c);qs(!1,`componentWillMount has been renamed, and is not recommended for use. See https://fb.me/react-unsafe-component-lifecycles for details. + +* Move code with side effects to componentDidMount, and set initial state in the constructor. +* Rename componentWillMount to UNSAFE_componentWillMount to suppress this warning in non-strict mode. In React 17.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, you can run \`npx react-codemod rename-unsafe-lifecycles\` in your project source folder. + +Please update the following components: %s`,Ue)}if(D.size>0){var Xe=zo(D);qs(!1,`componentWillReceiveProps has been renamed, and is not recommended for use. See https://fb.me/react-unsafe-component-lifecycles for details. + +* Move data fetching code or side effects to componentDidUpdate. +* If you're updating state whenever props change, refactor your code to use memoization techniques or move it to static getDerivedStateFromProps. Learn more at: https://fb.me/react-derived-state +* Rename componentWillReceiveProps to UNSAFE_componentWillReceiveProps to suppress this warning in non-strict mode. In React 17.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, you can run \`npx react-codemod rename-unsafe-lifecycles\` in your project source folder. + +Please update the following components: %s`,Xe)}if(O.size>0){var ht=zo(O);qs(!1,`componentWillUpdate has been renamed, and is not recommended for use. See https://fb.me/react-unsafe-component-lifecycles for details. + +* Move data fetching code or side effects to componentDidUpdate. +* Rename componentWillUpdate to UNSAFE_componentWillUpdate to suppress this warning in non-strict mode. In React 17.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, you can run \`npx react-codemod rename-unsafe-lifecycles\` in your project source folder. + +Please update the following components: %s`,ht)}};var Ho=new Map,Ef=new Set;Al.recordLegacyContextWarning=function(c,d){var D=id(c);if(D===null){Ve(!1,"Expected to find a StrictMode component in a strict mode tree. This error is likely caused by a bug in React. Please file an issue.");return}if(!Ef.has(c.type)){var C=Ho.get(D);(c.type.contextTypes!=null||c.type.childContextTypes!=null||d!==null&&typeof d.getChildContext=="function")&&(C===void 0&&(C=[],Ho.set(D,C)),C.push(c))}},Al.flushLegacyContextWarning=function(){Ho.forEach(function(c,d){var D=new Set;c.forEach(function(z){D.add(qt(z.type)||"Component"),Ef.add(z.type)});var C=zo(D),O=Cr(d);Ve(!1,`Legacy context API has been detected within a strict-mode tree. + +The old API will be supported in all 16.x releases, but applications using it should migrate to the new version. + +Please update the following components: %s + +Learn more about this warning here: https://fb.me/react-legacy-context%s`,C,O)})},Al.discardPendingWarnings=function(){ja=[],za=[],Ha=[],ca=[],ws=[],Ss=[],Ho=new Map}}var ol=null,Vu=null,qa=function(c){ol=c};function n0(c){{if(ol===null)return c;var d=ol(c);return d===void 0?c:d.current}}function j0(c){return n0(c)}function Df(c){{if(ol===null)return c;var d=ol(c);if(d===void 0){if(c!=null&&typeof c.render=="function"){var D=n0(c.render);if(c.render!==D){var C={$$typeof:On,render:D};return c.displayName!==void 0&&(C.displayName=c.displayName),C}}return c}return d.current}}function Wc(c,d){{if(ol===null)return!1;var D=c.elementType,C=d.type,O=!1,z=typeof C=="object"&&C!==null?C.$$typeof:null;switch(c.tag){case k:{typeof C=="function"&&(O=!0);break}case F:{(typeof C=="function"||z===Er)&&(O=!0);break}case ae:{(z===On||z===Er)&&(O=!0);break}case ve:case ue:{(z===Vt||z===Er)&&(O=!0);break}default:return!1}if(O){var G=ol(D);if(G!==void 0&&G===ol(C))return!0}return!1}}function dc(c){{if(ol===null||typeof WeakSet!="function")return;Vu===null&&(Vu=new WeakSet),Vu.add(c)}}var Ol=function(c,d){{if(ol===null)return;var D=d.staleFamilies,C=d.updatedFamilies;tf(),Rp(function(){da(c.current,C,D)})}},Ts=function(c,d){{if(c.context!==xn)return;tf(),pv(function(){Xg(d,c,null,null)})}};function da(c,d,D){{var C=c.alternate,O=c.child,z=c.sibling,G=c.tag,ne=c.type,se=null;switch(G){case F:case ue:case k:se=ne;break;case ae:se=ne.render;break;default:break}if(ol===null)throw new Error("Expected resolveFamily to be set during hot reload.");var Ue=!1,Xe=!1;if(se!==null){var ht=ol(se);ht!==void 0&&(D.has(ht)?Xe=!0:d.has(ht)&&(G===k?Xe=!0:Ue=!0))}Vu!==null&&(Vu.has(c)||C!==null&&Vu.has(C))&&(Xe=!0),Xe&&(c._debugNeedsRemount=!0),(Xe||Ue)&&yl(c,Un),O!==null&&!Xe&&da(O,d,D),z!==null&&da(z,d,D)}}var ud=function(c,d){{var D=new Set,C=new Set(d.map(function(O){return O.current}));return pa(c.current,C,D),D}};function pa(c,d,D){{var C=c.child,O=c.sibling,z=c.tag,G=c.type,ne=null;switch(z){case F:case ue:case k:ne=G;break;case ae:ne=G.render;break;default:break}var se=!1;ne!==null&&d.has(ne)&&(se=!0),se?pc(c,D):C!==null&&pa(C,d,D),O!==null&&pa(O,d,D)}}function pc(c,d){{var D=Vc(c,d);if(D)return;for(var C=c;;){switch(C.tag){case V:d.add(C.stateNode);return;case q:d.add(C.stateNode.containerInfo);return;case j:d.add(C.stateNode.containerInfo);return}if(C.return===null)throw new Error("Expected to reach root first.");C=C.return}}}function Vc(c,d){for(var D=c,C=!1;;){if(D.tag===V)C=!0,d.add(D.stateNode);else if(D.child!==null){D.child.return=D,D=D.child;continue}if(D===c)return C;for(;D.sibling===null;){if(D.return===null||D.return===c)return C;D=D.return}D.sibling.return=D.return,D=D.sibling}return!1}function Wi(c,d){if(c&&c.defaultProps){var D=f({},d),C=c.defaultProps;for(var O in C)D[O]===void 0&&(D[O]=C[O]);return D}return d}function _(c){if(Zo(c),c._status!==Ao)throw c._result;return c._result}var g=Qu(null),A;A={};var P=null,B=null,Z=null,de=!1;function yt(){P=null,B=null,Z=null,de=!1}function Rt(){de=!0}function Nt(){de=!1}function xr(c,d){var D=c.type._context;Uu?(Qr(g,D._currentValue,c),D._currentValue=d,D._currentRenderer===void 0||D._currentRenderer===null||D._currentRenderer===A||Ve(!1,"Detected multiple renderers concurrently rendering the same context provider. This is currently unsupported."),D._currentRenderer=A):(Qr(g,D._currentValue2,c),D._currentValue2=d,D._currentRenderer2===void 0||D._currentRenderer2===null||D._currentRenderer2===A||Ve(!1,"Detected multiple renderers concurrently rendering the same context provider. This is currently unsupported."),D._currentRenderer2=A)}function r0(c){var d=g.current;$r(g,c);var D=c.type._context;Uu?D._currentValue=d:D._currentValue2=d}function cu(c,d,D){if(yo(D,d))return 0;var C=typeof c._calculateChangedBits=="function"?c._calculateChangedBits(D,d):Wr;return(C&Wr)!==C&&Xt(!1,"calculateChangedBits: Expected the return value to be a 31-bit integer. Instead received: %s",C),C|0}function z0(c,d){for(var D=c;D!==null;){var C=D.alternate;if(D.childExpirationTime=d&&op(),D.firstContext=null)}}function Ge(c,d){if(de&&Xt(!1,"Context can only be read while React is rendering. In classes, you can read it in the render method or getDerivedStateFromProps. In function components, you can read it directly in the function body, but not inside Hooks like useReducer() or useMemo()."),Z!==c){if(!(d===!1||d===0)){var D;typeof d!="number"||d===Wr?(Z=c,D=Wr):D=d;var C={context:c,observedBits:D,next:null};if(B===null){if(P===null)throw Error("Context can only be read while React is rendering. In classes, you can read it in the render method or getDerivedStateFromProps. In function components, you can read it directly in the function body, but not inside Hooks like useReducer() or useMemo().");B=C,P.dependencies={expirationTime:ft,firstContext:C,responders:null}}else B=B.next=C}}return Uu?c._currentValue:c._currentValue2}var je=0,st=1,$t=2,Wn=3,oi=!1,ur,ai;ur=!1,ai=null;function Qi(c){var d={baseState:c,firstUpdate:null,lastUpdate:null,firstCapturedUpdate:null,lastCapturedUpdate:null,firstEffect:null,lastEffect:null,firstCapturedEffect:null,lastCapturedEffect:null};return d}function Vr(c){var d={baseState:c.baseState,firstUpdate:c.firstUpdate,lastUpdate:c.lastUpdate,firstCapturedUpdate:null,lastCapturedUpdate:null,firstEffect:null,lastEffect:null,firstCapturedEffect:null,lastCapturedEffect:null};return d}function Tu(c,d){var D={expirationTime:c,suspenseConfig:d,tag:je,payload:null,callback:null,next:null,nextEffect:null};return D.priority=Qt(),D}function Wa(c,d){c.lastUpdate===null?c.firstUpdate=c.lastUpdate=d:(c.lastUpdate.next=d,c.lastUpdate=d)}function Va(c,d){var D=c.alternate,C,O;D===null?(C=c.updateQueue,O=null,C===null&&(C=c.updateQueue=Qi(c.memoizedState))):(C=c.updateQueue,O=D.updateQueue,C===null?O===null?(C=c.updateQueue=Qi(c.memoizedState),O=D.updateQueue=Qi(D.memoizedState)):C=c.updateQueue=Vr(O):O===null&&(O=D.updateQueue=Vr(C))),O===null||C===O?Wa(C,d):C.lastUpdate===null||O.lastUpdate===null?(Wa(C,d),Wa(O,d)):(Wa(C,d),O.lastUpdate=d),c.tag===k&&(ai===C||O!==null&&ai===O)&&!ur&&(Ve(!1,"An update (setState, replaceState, or forceUpdate) was scheduled from inside an update function. Update functions should be pure, with zero side-effects. Consider using componentDidUpdate or a callback."),ur=!0)}function od(c,d){var D=c.updateQueue;D===null?D=c.updateQueue=Qi(c.memoizedState):D=D2(c,D),D.lastCapturedUpdate===null?D.firstCapturedUpdate=D.lastCapturedUpdate=d:(D.lastCapturedUpdate.next=d,D.lastCapturedUpdate=d)}function D2(c,d){var D=c.alternate;return D!==null&&d===D.updateQueue&&(d=c.updateQueue=Vr(d)),d}function w2(c,d,D,C,O,z){switch(D.tag){case st:{var G=D.payload;if(typeof G=="function"){Rt(),Ri&&c.mode&mr&&G.call(z,C,O);var ne=G.call(z,C,O);return Nt(),ne}return G}case Wn:c.effectTag=c.effectTag&~d0|Kr;case je:{var se=D.payload,Ue;return typeof se=="function"?(Rt(),Ri&&c.mode&mr&&se.call(z,C,O),Ue=se.call(z,C,O),Nt()):Ue=se,Ue==null?C:f({},C,Ue)}case $t:return oi=!0,C}return C}function wf(c,d,D,C,O){oi=!1,d=D2(c,d),ai=d;for(var z=d.baseState,G=null,ne=ft,se=d.firstUpdate,Ue=z;se!==null;){var Xe=se.expirationTime;if(Xe from render. Or maybe you meant to call this function rather than return it."))}function Eh(c){function d(lt,Mt){if(!!c){var $e=lt.lastEffect;$e!==null?($e.nextEffect=Mt,lt.lastEffect=Mt):lt.firstEffect=lt.lastEffect=Mt,Mt.nextEffect=null,Mt.effectTag=Y0}}function D(lt,Mt){if(!c)return null;for(var $e=Mt;$e!==null;)d(lt,$e),$e=$e.sibling;return null}function C(lt,Mt){for(var $e=new Map,jt=Mt;jt!==null;)jt.key!==null?$e.set(jt.key,jt):$e.set(jt.index,jt),jt=jt.sibling;return $e}function O(lt,Mt,$e){var jt=Co(lt,Mt,$e);return jt.index=0,jt.sibling=null,jt}function z(lt,Mt,$e){if(lt.index=$e,!c)return Mt;var jt=lt.alternate;if(jt!==null){var Fn=jt.index;return FnYr?(Cu=hr,hr=null):Cu=hr.sibling;var D0=Lt(lt,hr,$e[Yr],jt);if(D0===null){hr===null&&(hr=Cu);break}c&&hr&&D0.alternate===null&&d(lt,hr),pu=z(D0,pu,Yr),Yu===null?ci=D0:Yu.sibling=D0,Yu=D0,hr=Cu}if(Yr===$e.length)return D(lt,hr),ci;if(hr===null){for(;Yr<$e.length;Yr++){var W0=ht(lt,$e[Yr],jt);W0!==null&&(pu=z(W0,pu,Yr),Yu===null?ci=W0:Yu.sibling=W0,Yu=W0)}return ci}for(var Ms=C(lt,hr);Yr<$e.length;Yr++){var Ku=Gt(Ms,lt,Yr,$e[Yr],jt);Ku!==null&&(c&&Ku.alternate!==null&&Ms.delete(Ku.key===null?Yr:Ku.key),pu=z(Ku,pu,Yr),Yu===null?ci=Ku:Yu.sibling=Ku,Yu=Ku)}return c&&Ms.forEach(function(gl){return d(lt,gl)}),ci}function kr(lt,Mt,$e,jt){var Fn=fr($e);if(typeof Fn!="function")throw Error("An object is not an iterable. This error is likely caused by a bug in React. Please file an issue.");{typeof Symbol=="function"&&$e[Symbol.toStringTag]==="Generator"&&(Qc||Xt(!1,"Using Generators as children is unsupported and will likely yield unexpected results because enumerating a generator mutates it. You may convert it to an array with `Array.from()` or the `[...spread]` operator before rendering. Keep in mind you might need to polyfill these features for older browsers."),Qc=!0),$e.entries===Fn&&(dd||Xt(!1,"Using Maps as children is unsupported and will likely yield unexpected results. Convert it to a sequence/iterable of keyed ReactElements instead."),dd=!0);var vn=Fn.call($e);if(vn)for(var Vi=null,ci=vn.next();!ci.done;ci=vn.next()){var Yu=ci.value;Vi=Ht(Yu,Vi)}}var hr=Fn.call($e);if(hr==null)throw Error("An iterable object provided no iterator.");for(var pu=null,Yr=null,Cu=Mt,D0=0,W0=0,Ms=null,Ku=hr.next();Cu!==null&&!Ku.done;W0++,Ku=hr.next()){Cu.index>W0?(Ms=Cu,Cu=null):Ms=Cu.sibling;var gl=Lt(lt,Cu,Ku.value,jt);if(gl===null){Cu===null&&(Cu=Ms);break}c&&Cu&&gl.alternate===null&&d(lt,Cu),D0=z(gl,D0,W0),Yr===null?pu=gl:Yr.sibling=gl,Yr=gl,Cu=Ms}if(Ku.done)return D(lt,Cu),pu;if(Cu===null){for(;!Ku.done;W0++,Ku=hr.next()){var rf=ht(lt,Ku.value,jt);rf!==null&&(D0=z(rf,D0,W0),Yr===null?pu=rf:Yr.sibling=rf,Yr=rf)}return pu}for(var Vo=C(lt,Cu);!Ku.done;W0++,Ku=hr.next()){var ks=Gt(Vo,lt,W0,Ku.value,jt);ks!==null&&(c&&ks.alternate!==null&&Vo.delete(ks.key===null?W0:ks.key),D0=z(ks,D0,W0),Yr===null?pu=ks:Yr.sibling=ks,Yr=ks)}return c&&Vo.forEach(function(Jd){return d(lt,Jd)}),pu}function ii(lt,Mt,$e,jt){if(Mt!==null&&Mt.tag===re){D(lt,Mt.sibling);var Fn=O(Mt,$e,jt);return Fn.return=lt,Fn}D(lt,Mt);var vn=_y($e,lt.mode,jt);return vn.return=lt,vn}function Oi(lt,Mt,$e,jt){for(var Fn=$e.key,vn=Mt;vn!==null;){if(vn.key===Fn)if(vn.tag===y?$e.type===le:vn.elementType===$e.type||Wc(vn,$e)){D(lt,vn.sibling);var Vi=O(vn,$e.type===le?$e.props.children:$e.props,jt);return Vi.ref=vc(lt,vn,$e),Vi.return=lt,Vi._debugSource=$e._source,Vi._debugOwner=$e._owner,Vi}else{D(lt,vn);break}else d(lt,vn);vn=vn.sibling}if($e.type===le){var ci=nf($e.props.children,lt.mode,jt,$e.key);return ci.return=lt,ci}else{var Yu=gy($e,lt.mode,jt);return Yu.ref=vc(lt,Mt,$e),Yu.return=lt,Yu}}function L0(lt,Mt,$e,jt){for(var Fn=$e.key,vn=Mt;vn!==null;){if(vn.key===Fn)if(vn.tag===q&&vn.stateNode.containerInfo===$e.containerInfo&&vn.stateNode.implementation===$e.implementation){D(lt,vn.sibling);var Vi=O(vn,$e.children||[],jt);return Vi.return=lt,Vi}else{D(lt,vn);break}else d(lt,vn);vn=vn.sibling}var ci=Ey($e,lt.mode,jt);return ci.return=lt,ci}function $i(lt,Mt,$e,jt){var Fn=typeof $e=="object"&&$e!==null&&$e.type===le&&$e.key===null;Fn&&($e=$e.props.children);var vn=typeof $e=="object"&&$e!==null;if(vn)switch($e.$$typeof){case ce:return G(Oi(lt,Mt,$e,jt));case Re:return G(L0(lt,Mt,$e,jt))}if(typeof $e=="string"||typeof $e=="number")return G(ii(lt,Mt,""+$e,jt));if(Zc($e))return yn(lt,Mt,$e,jt);if(fr($e))return kr(lt,Mt,$e,jt);if(vn&&mc(lt,$e),typeof $e=="function"&&pd(),typeof $e>"u"&&!Fn)switch(lt.tag){case k:{var Vi=lt.stateNode;if(Vi.render._isMockFunction)break}case F:{var ci=lt.type;throw Error((ci.displayName||ci.name||"Component")+"(...): Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null.")}}return D(lt,Mt)}return $i}var Tf=Eh(!0),$c=Eh(!1);function Dh(c,d){if(!(c===null||d.child===c.child))throw Error("Resuming work not yet implemented.");if(d.child!==null){var D=d.child,C=Co(D,D.pendingProps,D.expirationTime);for(d.child=C,C.return=d;D.sibling!==null;)D=D.sibling,C=C.sibling=Co(D,D.pendingProps,D.expirationTime),C.return=d;C.sibling=null}}function sm(c,d){for(var D=c.child;D!==null;)kv(D,d),D=D.sibling}var Vs={},ma=Qu(Vs),iu=Qu(Vs),M0=Qu(Vs);function u0(c){if(c===Vs)throw Error("Expected host context to exist. This error is likely caused by a bug in React. Please file an issue.");return c}function ns(){var c=u0(M0.current);return c}function Ya(c,d){Qr(M0,d,c),Qr(iu,c,c),Qr(ma,Vs,c);var D=St(d);$r(ma,c),Qr(ma,D,c)}function uo(c){$r(ma,c),$r(iu,c),$r(M0,c)}function fl(){var c=u0(ma.current);return c}function yc(c){var d=u0(M0.current),D=u0(ma.current),C=Bt(D,c.type,d);D!==C&&(Qr(iu,c,c),Qr(ma,C,c))}function M2(c){iu.current===c&&($r(ma,c),$r(iu,c))}var wh=0,Cf=1,xf=1,e1=2,Nl=Qu(wh);function t1(c,d){return(c&d)!==0}function ya(c){return c&Cf}function hd(c,d){return c&Cf|d}function vd(c,d){return c|d}function Fr(c,d){Qr(Nl,d,c)}function ga(c){$r(Nl,c)}function k2(c,d){var D=c.memoizedState;if(D!==null)return D.dehydrated!==null;var C=c.memoizedProps;return C.fallback===void 0?!1:C.unstable_avoidThisFallback!==!0?!0:!d}function n1(c){for(var d=c;d!==null;){if(d.tag===he){var D=d.memoizedState;if(D!==null){var C=D.dehydrated;if(C===null||Bs(C)||m0(C))return d}}else if(d.tag===gt&&d.memoizedProps.revealOrder!==void 0){var O=(d.effectTag&Kr)!==xi;if(O)return d}else if(d.child!==null){d.child.return=d,d=d.child;continue}if(d===c)return null;for(;d.sibling===null;){if(d.return===null||d.return===c)return null;d=d.return}d.sibling.return=d.return,d=d.sibling}return null}var md={},wi=Array.isArray;function N2(c,d,D,C){return{fiber:C,props:d,responder:c,rootEventTypes:null,state:D}}function am(c,d,D,C,O){var z=md,G=c.getInitialState;G!==null&&(z=G(d));var ne=N2(c,d,z,D);if(!O)for(var se=D;se!==null;){var Ue=se.tag;if(Ue===V){O=se.stateNode;break}else if(Ue===j){O=se.stateNode.containerInfo;break}se=se.return}Fe(c,ne,d,z,O),C.set(c,ne)}function yd(c,d,D,C,O){var z,G;if(c&&(z=c.responder,G=c.props),!(z&&z.$$typeof===zt))throw Error("An invalid value was used as an event listener. Expect one or many event listeners created via React.unstable_useResponder().");var ne=G;if(D.has(z)){Xt(!1,'Duplicate event responder "%s" found in event listeners. Event listeners passed to elements cannot use the same event responder more than once.',z.displayName);return}D.add(z);var se=C.get(z);se===void 0?am(z,ne,d,C,O):(se.props=ne,se.fiber=d)}function hn(c,d,D){var C=new Set,O=d.dependencies;if(c!=null){O===null&&(O=d.dependencies={expirationTime:ft,firstContext:null,responders:new Map});var z=O.responders;if(z===null&&(z=new Map),wi(c))for(var G=0,ne=c.length;G0){var z=O.dispatch;if(Cs!==null){var G=Cs.get(O);if(G!==void 0){Cs.delete(O);var ne=C.memoizedState,se=G;do{var Ue=se.action;ne=c(ne,Ue),se=se.next}while(se!==null);return yo(ne,C.memoizedState)||op(),C.memoizedState=ne,C.baseUpdate===O.last&&(C.baseState=ne),O.lastRenderedState=ne,[ne,z]}}return[C.memoizedState,z]}var Xe=O.last,ht=C.baseUpdate,Lt=C.baseState,Gt;if(ht!==null?(Xe!==null&&(Xe.next=null),Gt=ht.next):Gt=Xe!==null?Xe.next:null,Gt!==null){var Ht=Lt,yn=null,kr=null,ii=ht,Oi=Gt,L0=!1;do{var $i=Oi.expirationTime;if($iPu&&(Pu=$i,Kd(Pu));else if(gv($i,Oi.suspenseConfig),Oi.eagerReducer===c)Ht=Oi.eagerState;else{var lt=Oi.action;Ht=c(Ht,lt)}ii=Oi,Oi=Oi.next}while(Oi!==null&&Oi!==Gt);L0||(kr=ii,yn=Ht),yo(Ht,C.memoizedState)||op(),C.memoizedState=Ht,C.baseUpdate=kr,C.baseState=yn,O.lastRenderedState=Ht}var Mt=O.dispatch;return[C.memoizedState,Mt]}function Ff(c){var d=Dc();typeof c=="function"&&(c=c()),d.memoizedState=d.baseState=c;var D=d.queue={last:null,dispatch:null,lastRenderedReducer:L2,lastRenderedState:c},C=D.dispatch=a1.bind(null,dl,D);return[d.memoizedState,C]}function o1(c){return u1(L2,c)}function Qa(c,d,D,C){var O={tag:c,create:d,destroy:D,deps:C,next:null};if(rs===null)rs=Xa(),rs.lastEffect=O.next=O;else{var z=rs.lastEffect;if(z===null)rs.lastEffect=O.next=O;else{var G=z.next;z.next=O,O.next=G,rs.lastEffect=O}}return O}function l1(c){var d=Dc(),D={current:c};return Object.seal(D),d.memoizedState=D,D}function F2(c){var d=i1();return d.memoizedState}function Dd(c,d,D,C){var O=Dc(),z=C===void 0?null:C;Mf|=c,O.memoizedState=Qa(d,D,void 0,z)}function wc(c,d,D,C){var O=i1(),z=C===void 0?null:C,G=void 0;if(jn!==null){var ne=jn.memoizedState;if(G=ne.destroy,z!==null){var se=ne.deps;if(Nf(z,se)){Qa(Af,D,G,z);return}}}Mf|=c,O.memoizedState=Qa(d,D,G,z)}function s1(c,d){return typeof jest<"u"&&Mv(dl),Dd(Dr|F0,sr|r1,c,d)}function Fl(c,d){return typeof jest<"u"&&Mv(dl),wc(Dr|F0,sr|r1,c,d)}function Ea(c,d){return Dd(Dr,Of|cl,c,d)}function Ch(c,d){return wc(Dr,Of|cl,c,d)}function P2(c,d){if(typeof d=="function"){var D=d,C=c();return D(C),function(){D(null)}}else if(d!=null){var O=d;O.hasOwnProperty("current")||Xt(!1,"Expected useImperativeHandle() first argument to either be a ref callback or React.createRef() object. Instead received: %s.","an object with keys {"+Object.keys(O).join(", ")+"}");var z=c();return O.current=z,function(){O.current=null}}}function I2(c,d,D){typeof d!="function"&&Xt(!1,"Expected useImperativeHandle() second argument to be a function that creates a handle. Instead received: %s.",d!==null?typeof d:"null");var C=D!=null?D.concat([c]):null;return Dd(Dr,Of|cl,P2.bind(null,d,c),C)}function xh(c,d,D){typeof d!="function"&&Xt(!1,"Expected useImperativeHandle() second argument to be a function that creates a handle. Instead received: %s.",d!==null?typeof d:"null");var C=D!=null?D.concat([c]):null;return wc(Dr,Of|cl,P2.bind(null,d,c),C)}function pm(c,d){}var Rh=pm;function Pl(c,d){var D=Dc(),C=d===void 0?null:d;return D.memoizedState=[c,C],c}function us(c,d){var D=i1(),C=d===void 0?null:d,O=D.memoizedState;if(O!==null&&C!==null){var z=O[1];if(Nf(C,z))return O[0]}return D.memoizedState=[c,C],c}function xs(c,d){var D=Dc(),C=d===void 0?null:d,O=c();return D.memoizedState=[O,C],O}function Gs(c,d){var D=i1(),C=d===void 0?null:d,O=D.memoizedState;if(O!==null&&C!==null){var z=O[1];if(Nf(C,z))return O[0]}var G=c();return D.memoizedState=[G,C],G}function b2(c,d){var D=Ff(c),C=D[0],O=D[1];return s1(function(){t.unstable_next(function(){var z=qo.suspense;qo.suspense=d===void 0?null:d;try{O(c)}finally{qo.suspense=z}})},[c,d]),C}function Ah(c,d){var D=o1(c),C=D[0],O=D[1];return Fl(function(){t.unstable_next(function(){var z=qo.suspense;qo.suspense=d===void 0?null:d;try{O(c)}finally{qo.suspense=z}})},[c,d]),C}function B2(c){var d=Ff(!1),D=d[0],C=d[1],O=Pl(function(z){C(!0),t.unstable_next(function(){var G=qo.suspense;qo.suspense=c===void 0?null:c;try{C(!1),z()}finally{qo.suspense=G}})},[c,D]);return[O,D]}function U2(c){var d=o1(!1),D=d[0],C=d[1],O=us(function(z){C(!0),t.unstable_next(function(){var G=qo.suspense;qo.suspense=c===void 0?null:c;try{C(!1),z()}finally{qo.suspense=G}})},[c,D]);return[O,D]}function a1(c,d,D){if(!(Ec=0){var D=c1()-d1;c.actualDuration+=D,d&&(c.selfBaseDuration=D),d1=-1}}var bl=null,Za=null,Da=!1;function q2(){Da&&Xt(!1,"We should not be hydrating here. This is a bug in React. Please file a bug.")}function W2(c){if(!Se)return!1;var d=c.stateNode.containerInfo;return Za=U(d),bl=c,Da=!0,!0}function hm(c,d){return Se?(Za=zi(d),Y2(c),Da=!0,!0):!1}function V2(c,d){switch(c.tag){case j:oe(c.stateNode.containerInfo,d);break;case V:qe(c.type,c.memoizedProps,c.stateNode,d);break}var D=U4();D.stateNode=d,D.return=c,D.effectTag=Y0,c.lastEffect!==null?(c.lastEffect.nextEffect=D,c.lastEffect=D):c.firstEffect=c.lastEffect=D}function Fh(c,d){switch(d.effectTag=d.effectTag&~su|vi,c.tag){case j:{var D=c.stateNode.containerInfo;switch(d.tag){case V:var C=d.type,O=d.pendingProps;rt(D,C,O);break;case re:var z=d.pendingProps;xt(D,z);break;case he:kt(D);break}break}case V:{var G=c.type,ne=c.memoizedProps,se=c.stateNode;switch(d.tag){case V:var Ue=d.type,Xe=d.pendingProps;bt(G,ne,se,Ue,Xe);break;case re:var ht=d.pendingProps;sn(G,ne,se,ht);break;case he:rn(G,ne,se);break}break}default:return}}function Ph(c,d){switch(c.tag){case V:{var D=c.type,C=c.pendingProps,O=pf(d,D,C);return O!==null?(c.stateNode=O,!0):!1}case re:{var z=c.pendingProps,G=bs(d,z);return G!==null?(c.stateNode=G,!0):!1}case he:{if(Ai){var ne=ba(d);if(ne!==null){var se={dehydrated:ne,retryTime:Di};c.memoizedState=se;var Ue=j4(ne);return Ue.return=c,c.child=Ue,!0}}return!1}default:return!1}}function G2(c){if(!!Da){var d=Za;if(!d){Fh(bl,c),Da=!1,bl=c;return}var D=d;if(!Ph(c,d)){if(d=zi(D),!d||!Ph(c,d)){Fh(bl,c),Da=!1,bl=c;return}V2(bl,D)}bl=c,Za=U(d)}}function vm(c,d,D){if(!Se)throw Error("Expected prepareToHydrateHostInstance() to never be called. This error is likely caused by a bug in React. Please file an issue.");var C=c.stateNode,O=H(C,c.type,c.memoizedProps,d,D,c);return c.updateQueue=O,O!==null}function mm(c){if(!Se)throw Error("Expected prepareToHydrateHostTextInstance() to never be called. This error is likely caused by a bug in React. Please file an issue.");var d=c.stateNode,D=c.memoizedProps,C=Y(d,D,c);if(C){var O=bl;if(O!==null)switch(O.tag){case j:{var z=O.stateNode.containerInfo;Je(z,d,D);break}case V:{var G=O.type,ne=O.memoizedProps,se=O.stateNode;vt(G,ne,se,d,D);break}}}return C}function Ih(c){if(!Se)throw Error("Expected prepareToHydrateHostSuspenseInstance() to never be called. This error is likely caused by a bug in React. Please file an issue.");var d=c.memoizedState,D=d!==null?d.dehydrated:null;if(!D)throw Error("Expected to have a hydrated suspense instance. This error is likely caused by a bug in React. Please file an issue.");ee(D,c)}function ym(c){if(!Se)throw Error("Expected skipPastDehydratedSuspenseInstance() to never be called. This error is likely caused by a bug in React. Please file an issue.");var d=c.memoizedState,D=d!==null?d.dehydrated:null;if(!D)throw Error("Expected to have a hydrated suspense instance. This error is likely caused by a bug in React. Please file an issue.");return Ce(D)}function Y2(c){for(var d=c.return;d!==null&&d.tag!==V&&d.tag!==j&&d.tag!==he;)d=d.return;bl=d}function h1(c){if(!Se||c!==bl)return!1;if(!Da)return Y2(c),Da=!0,!1;var d=c.type;if(c.tag!==V||d!=="head"&&d!=="body"&&!Ni(d,c.memoizedProps))for(var D=Za;D;)V2(c,D),D=zi(D);return Y2(c),c.tag===he?Za=ym(c):Za=bl?zi(c.stateNode):null,!0}function v1(){!Se||(bl=null,Za=null,Da=!1)}var m1=it.ReactCurrentOwner,wa=!1,K2,Ys,Ks,Xs,X2,Sa,y1,wd,Sc,Q2;K2={},Ys={},Ks={},Xs={},X2={},Sa=!1,y1=!1,wd={},Sc={},Q2={};function wo(c,d,D,C){c===null?d.child=$c(d,null,D,C):d.child=Tf(d,c.child,D,C)}function bh(c,d,D,C){d.child=Tf(d,c.child,null,C),d.child=Tf(d,null,D,C)}function Bh(c,d,D,C,O){if(d.type!==d.elementType){var z=D.propTypes;z&&E(z,C,"prop",qt(D),Lr)}var G=D.render,ne=d.ref,se;return i0(d,O),m1.current=d,et("render"),se=Lf(c,d,G,C,ne,O),Ri&&d.mode&mr&&d.memoizedState!==null&&(se=Lf(c,d,G,C,ne,O)),et(null),c!==null&&!wa?(gd(c,d,O),Ta(c,d,O)):(d.effectTag|=lu,wo(c,d,se,O),d.child)}function Uh(c,d,D,C,O,z){if(c===null){var G=D.type;if(s0(G)&&D.compare===null&&D.defaultProps===void 0){var ne=G;return ne=n0(G),d.tag=ue,d.type=ne,$2(d,G),jh(c,d,ne,C,O,z)}{var se=G.propTypes;se&&E(se,C,"prop",qt(G),Lr)}var Ue=yy(D.type,null,C,null,d.mode,z);return Ue.ref=d.ref,Ue.return=d,d.child=Ue,Ue}{var Xe=D.type,ht=Xe.propTypes;ht&&E(ht,C,"prop",qt(Xe),Lr)}var Lt=c.child;if(O component appears to have a render method, but doesn't extend React.Component. This is likely to cause errors. Change %s to extend React.Component instead.",se,se),K2[se]=!0)}d.mode&mr&&Al.recordLegacyContextWarning(d,null),m1.current=d,ne=Lf(null,d,D,O,z,C)}if(d.effectTag|=lu,typeof ne=="object"&&ne!==null&&typeof ne.render=="function"&&ne.$$typeof===void 0){{var Ue=qt(D)||"Unknown";Ys[Ue]||(Ve(!1,"The <%s /> component appears to be a function component that returns a class instance. Change %s to a class that extends React.Component instead. If you can't use a class try assigning the prototype on the function as a workaround. `%s.prototype = React.Component.prototype`. Don't use an arrow function since it cannot be called with `new` by React.",Ue,Ue,Ue),Ys[Ue]=!0)}d.tag=k,_d();var Xe=!1;Xi(D)?(Xe=!0,qi(d)):Xe=!1,d.memoizedState=ne.state!==null&&ne.state!==void 0?ne.state:null;var ht=D.getDerivedStateFromProps;return typeof ht=="function"&&Sf(d,D,ht,O),al(d,ne),hc(d,D,O,C),Z2(null,d,D,!0,Xe,C)}else return d.tag=F,li&&D.contextTypes&&Ve(!1,"%s uses the legacy contextTypes API which is no longer supported. Use React.createContext() with React.useContext() instead.",qt(D)||"Unknown"),Ri&&d.mode&mr&&d.memoizedState!==null&&(ne=Lf(null,d,D,O,z,C)),wo(null,d,ne,C),$2(d,D),d.child}function $2(c,d){if(d&&d.childContextTypes&&Ve(!1,"%s(...): childContextTypes cannot be defined on a function component.",d.displayName||d.name||"Component"),c.ref!==null){var D="",C=y0();C&&(D+=` + +Check the render method of \``+C+"`.");var O=C||c._debugID||"",z=c._debugSource;z&&(O=z.fileName+":"+z.lineNumber),X2[O]||(X2[O]=!0,Xt(!1,"Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?%s",D))}if(Xl&&d.defaultProps!==void 0){var G=qt(d)||"Unknown";Q2[G]||(Ve(!1,"%s: Support for defaultProps will be removed from function components in a future major release. Use JavaScript default parameters instead.",G),Q2[G]=!0)}if(typeof d.getDerivedStateFromProps=="function"){var ne=qt(d)||"Unknown";Xs[ne]||(Ve(!1,"%s: Function components do not support getDerivedStateFromProps.",ne),Xs[ne]=!0)}if(typeof d.contextType=="object"&&d.contextType!==null){var se=qt(d)||"Unknown";Ks[se]||(Ve(!1,"%s: Function components do not support contextType.",se),Ks[se]=!0)}}var Td={dehydrated:null,retryTime:ft};function ep(c,d,D){return t1(c,e1)&&(d===null||d.memoizedState!==null)}function Vh(c,d,D){var C=d.mode,O=d.pendingProps;Jg(d)&&(d.effectTag|=Kr);var z=Nl.current,G=!1,ne=(d.effectTag&Kr)!==xi;if(ne||ep(z,c,d)?(G=!0,d.effectTag&=~Kr):(c===null||c.memoizedState!==null)&&O.fallback!==void 0&&O.unstable_avoidThisFallback!==!0&&(z=vd(z,xf)),z=ya(z),Fr(d,z),"maxDuration"in O&&(y1||(y1=!0,Xt(!1,"maxDuration has been removed from React. Remove the maxDuration prop."))),c===null){if(O.fallback!==void 0&&(G2(d),Ai)){var se=d.memoizedState;if(se!==null){var Ue=se.dehydrated;if(Ue!==null)return Gh(d,Ue,D)}}if(G){var Xe=O.fallback,ht=nf(null,C,ft,null);if(ht.return=d,(d.mode&K)===Ar){var Lt=d.memoizedState,Gt=Lt!==null?d.child.child:d.child;ht.child=Gt;for(var Ht=Gt;Ht!==null;)Ht.return=ht,Ht=Ht.sibling}var yn=nf(Xe,C,D,null);return yn.return=d,ht.sibling=yn,d.memoizedState=Td,d.child=ht,yn}else{var kr=O.children;return d.memoizedState=null,d.child=$c(d,null,kr,D)}}else{var ii=c.memoizedState;if(ii!==null){if(Ai){var Oi=ii.dehydrated;if(Oi!==null)if(ne){if(d.memoizedState!==null)return d.child=c.child,d.effectTag|=Kr,null;var L0=O.fallback,$i=nf(null,C,ft,null);if($i.return=d,$i.child=null,(d.mode&K)===Ar)for(var lt=$i.child=d.child;lt!==null;)lt.return=$i,lt=lt.sibling;else Tf(d,c.child,null,D);if(en&&d.mode&ni){for(var Mt=0,$e=$i.child;$e!==null;)Mt+=$e.treeBaseDuration,$e=$e.sibling;$i.treeBaseDuration=Mt}var jt=nf(L0,C,D,null);return jt.return=d,$i.sibling=jt,jt.effectTag|=vi,$i.childExpirationTime=ft,d.memoizedState=Td,d.child=$i,jt}else return Yh(c,d,Oi,ii,D)}var Fn=c.child,vn=Fn.sibling;if(G){var Vi=O.fallback,ci=Co(Fn,Fn.pendingProps,ft);if(ci.return=d,(d.mode&K)===Ar){var Yu=d.memoizedState,hr=Yu!==null?d.child.child:d.child;if(hr!==Fn.child){ci.child=hr;for(var pu=hr;pu!==null;)pu.return=ci,pu=pu.sibling}}if(en&&d.mode&ni){for(var Yr=0,Cu=ci.child;Cu!==null;)Yr+=Cu.treeBaseDuration,Cu=Cu.sibling;ci.treeBaseDuration=Yr}var D0=Co(vn,Vi,vn.expirationTime);return D0.return=d,ci.sibling=D0,ci.childExpirationTime=ft,d.memoizedState=Td,d.child=ci,D0}else{var W0=O.children,Ms=Fn.child,Ku=Tf(d,Ms,W0,D);return d.memoizedState=null,d.child=Ku}}else{var gl=c.child;if(G){var rf=O.fallback,Vo=nf(null,C,ft,null);if(Vo.return=d,Vo.child=gl,gl!==null&&(gl.return=Vo),(d.mode&K)===Ar){var ks=d.memoizedState,Jd=ks!==null?d.child.child:d.child;Vo.child=Jd;for(var Vf=Jd;Vf!==null;)Vf.return=Vo,Vf=Vf.sibling}if(en&&d.mode&ni){for(var Lc=0,Hl=Vo.child;Hl!==null;)Lc+=Hl.treeBaseDuration,Hl=Hl.sibling;Vo.treeBaseDuration=Lc}var Go=nf(rf,C,D,null);return Go.return=d,Vo.sibling=Go,Go.effectTag|=vi,Vo.childExpirationTime=ft,d.memoizedState=Td,d.child=Vo,Go}else{d.memoizedState=null;var L1=O.children;return d.child=Tf(d,gl,L1,D)}}}}function tp(c,d,D){d.memoizedState=null;var C=d.pendingProps,O=C.children;return wo(c,d,O,D),d.child}function Gh(c,d,D){if((c.mode&K)===Ar)Xt(!1,"Cannot hydrate Suspense in legacy mode. Switch from ReactDOM.hydrate(element, container) to ReactDOM.createBlockingRoot(container, { hydrate: true }).render(element) or remove the Suspense components from the server rendered components."),c.expirationTime=Un;else if(m0(d)){var C=jl(),O=Ds(C);In&&R(O),c.expirationTime=O}else c.expirationTime=Di,In&&R(Di);return null}function Yh(c,d,D,C,O){if(q2(),(d.mode&K)===Ar||m0(D))return tp(c,d,O);var z=c.childExpirationTime>=O;if(wa||z){if(O. Use lowercase "%s" instead.',c,c.toLowerCase());break}case"forward":case"backward":{Xt(!1,'"%s" is not a valid value for revealOrder on . React uses the -s suffix in the spelling. Use "%ss" instead.',c,c.toLowerCase());break}default:Xt(!1,'"%s" is not a supported revealOrder on . Did you mean "together", "forwards" or "backwards"?',c);break}else Xt(!1,'%s is not a supported value for revealOrder on . Did you mean "together", "forwards" or "backwards"?',c)}function Kh(c,d){c!==void 0&&!Sc[c]&&(c!=="collapsed"&&c!=="hidden"?(Sc[c]=!0,Xt(!1,'"%s" is not a supported value for tail on . Did you mean "collapsed" or "hidden"?',c)):d!=="forwards"&&d!=="backwards"&&(Sc[c]=!0,Xt(!1,' is only valid if revealOrder is "forwards" or "backwards". Did you mean to specify revealOrder="forwards"?',c)))}function _1(c,d){{var D=Array.isArray(c),C=!D&&typeof fr(c)=="function";if(D||C){var O=D?"array":"iterable";return Xt(!1,"A nested %s was passed to row #%s in . Wrap it in an additional SuspenseList to configure its revealOrder: ... {%s} ... ",O,d,O),!1}}return!0}function Cm(c,d){if((d==="forwards"||d==="backwards")&&c!==void 0&&c!==null&&c!==!1)if(Array.isArray(c)){for(var D=0;D. This is not useful since it needs multiple rows. Did you mean to pass multiple children or an array?',d)}}function rp(c,d,D,C,O,z){var G=c.memoizedState;G===null?c.memoizedState={isBackwards:d,rendering:null,last:C,tail:D,tailExpiration:0,tailMode:O,lastEffect:z}:(G.isBackwards=d,G.rendering=null,G.last=C,G.tail=D,G.tailExpiration=0,G.tailMode=O,G.lastEffect=z)}function ip(c,d,D){var C=d.pendingProps,O=C.revealOrder,z=C.tail,G=C.children;Tm(O),Kh(z,O),Cm(G,O),wo(c,d,G,D);var ne=Nl.current,se=t1(ne,e1);if(se)ne=hd(ne,e1),d.effectTag|=Kr;else{var Ue=c!==null&&(c.effectTag&Kr)!==xi;Ue&&wm(d,d.child,D),ne=ya(ne)}if(Fr(d,ne),(d.mode&K)===Ar)d.memoizedState=null;else switch(O){case"forwards":{var Xe=Sm(d.child),ht;Xe===null?(ht=d.child,d.child=null):(ht=Xe.sibling,Xe.sibling=null),rp(d,!1,ht,Xe,z,d.lastEffect);break}case"backwards":{var Lt=null,Gt=d.child;for(d.child=null;Gt!==null;){var Ht=Gt.alternate;if(Ht!==null&&n1(Ht)===null){d.child=Gt;break}var yn=Gt.sibling;Gt.sibling=Lt,Lt=Gt,Gt=yn}rp(d,!0,Lt,null,z,d.lastEffect);break}case"together":{rp(d,!1,null,null,void 0,d.lastEffect);break}default:d.memoizedState=null}return d.child}function xm(c,d,D){Ya(d,d.stateNode.containerInfo);var C=d.pendingProps;return c===null?d.child=Tf(d,null,C,D):wo(c,d,C,D),d.child}function Rm(c,d,D){var C=d.type,O=C._context,z=d.pendingProps,G=d.memoizedProps,ne=z.value;{var se=d.type.propTypes;se&&E(se,z,"prop","Context.Provider",Lr)}if(xr(d,ne),G!==null){var Ue=G.value,Xe=cu(O,ne,Ue);if(Xe===0){if(G.children===z.children&&!sa())return Ta(c,d,D)}else Ml(d,O,Xe,D)}var ht=z.children;return wo(c,d,ht,D),d.child}var Xh=!1;function Am(c,d,D){var C=d.type;C._context===void 0?C!==C.Consumer&&(Xh||(Xh=!0,Xt(!1,"Rendering directly is not supported and will be removed in a future major release. Did you mean to render instead?"))):C=C._context;var O=d.pendingProps,z=O.children;typeof z!="function"&&Ve(!1,"A context consumer was rendered with multiple children, or a child that isn't a function. A context consumer expects a single child that is a function. If you did pass a function, make sure there is no trailing or leading whitespace around it."),i0(d,D);var G=Ge(C,O.unstable_observedBits),ne;return m1.current=d,et("render"),ne=z(G),et(null),d.effectTag|=lu,wo(c,d,ne,D),d.child}function Om(c,d,D){var C=d.type.impl;if(C.reconcileChildren===!1)return null;var O=d.pendingProps,z=O.children;return wo(c,d,z,D),d.child}function up(c,d,D){var C=d.pendingProps,O=C.children;return wo(c,d,O,D),d.child}function op(){wa=!0}function Ta(c,d,D){tu(d),c!==null&&(d.dependencies=c.dependencies),en&&Lh(d);var C=d.expirationTime;C!==ft&&Kd(C);var O=d.childExpirationTime;return O=D;se&&(d.effectTag|=Dr)}break;case he:{var Ue=d.memoizedState;if(Ue!==null){if(Ai&&Ue.dehydrated!==null){Fr(d,ya(Nl.current)),d.effectTag|=Kr;break}var Xe=d.child,ht=Xe.childExpirationTime;if(ht!==ft&&ht>=D)return Vh(c,d,D);Fr(d,ya(Nl.current));var Lt=Ta(c,d,D);return Lt!==null?Lt.sibling:null}else Fr(d,ya(Nl.current));break}case gt:{var Gt=(c.effectTag&Kr)!==xi,Ht=d.childExpirationTime>=D;if(Gt){if(Ht)return ip(c,d,D);d.effectTag|=Kr}var yn=d.memoizedState;if(yn!==null&&(yn.rendering=null,yn.tail=null),Fr(d,Nl.current),Ht)break;return null}}return Ta(c,d,D)}else wa=!1}else wa=!1;switch(d.expirationTime=ft,d.tag){case x:return Dm(c,d,d.type,D);case Ae:{var kr=d.elementType;return If(c,d,kr,C,D)}case F:{var ii=d.type,Oi=d.pendingProps,L0=d.elementType===ii?Oi:Wi(ii,Oi);return J2(c,d,ii,L0,D)}case k:{var $i=d.type,lt=d.pendingProps,Mt=d.elementType===$i?lt:Wi($i,lt);return qh(c,d,$i,Mt,D)}case j:return _m(c,d,D);case V:return Em(c,d,D);case re:return Pf(c,d);case he:return Vh(c,d,D);case q:return xm(c,d,D);case ae:{var $e=d.type,jt=d.pendingProps,Fn=d.elementType===$e?jt:Wi($e,jt);return Bh(c,d,$e,Fn,D)}case y:return gm(c,d,D);case me:return zh(c,d,D);case we:return Hh(c,d,D);case ge:return Rm(c,d,D);case De:return Am(c,d,D);case ve:{var vn=d.type,Vi=d.pendingProps,ci=Wi(vn,Vi);if(d.type!==d.elementType){var Yu=vn.propTypes;Yu&&E(Yu,ci,"prop",qt(vn),Lr)}return ci=Wi(vn.type,ci),Uh(c,d,vn,ci,C,D)}case ue:return jh(c,d,d.type,d.pendingProps,C,D);case ze:{var hr=d.type,pu=d.pendingProps,Yr=d.elementType===hr?pu:Wi(hr,pu);return Sd(c,d,hr,Yr,D)}case gt:return ip(c,d,D);case _t:{if(Wt)return Om(c,d,D);break}case Qe:{if(Ru)return up(c,d,D);break}}throw Error("Unknown unit of work tag ("+d.tag+"). This error is likely caused by a bug in React. Please file an issue.")}function Qh(c,d,D,C){return{currentFiber:c,impl:D,instance:null,prevProps:null,props:d,state:C}}function Cd(c){return c.tag===he&&c.memoizedState!==null}function D1(c){return c.child.sibling.child}var Jh={};function sp(c,d,D){if(Ru){if(c.tag===V){var C=c.type,O=c.memoizedProps,z=c.stateNode,G=Lo(z);G!==null&&d(C,O||Jh,G)===!0&&D.push(G)}var ne=c.child;Cd(c)&&(ne=D1(c)),ne!==null&&ap(ne,d,D)}}function Zh(c,d){if(Ru){if(c.tag===V){var D=c.type,C=c.memoizedProps,O=c.stateNode,z=Lo(O);if(z!==null&&d(D,C,z)===!0)return z}var G=c.child;if(Cd(c)&&(G=D1(c)),G!==null)return $h(G,d)}return null}function ap(c,d,D){for(var C=c;C!==null;)sp(C,d,D),C=C.sibling}function $h(c,d){for(var D=c;D!==null;){var C=Zh(D,d);if(C!==null)return C;D=D.sibling}return null}function ev(c,d,D){if(xd(c,d))D.push(c.stateNode.methods);else{var C=c.child;Cd(c)&&(C=D1(c)),C!==null&&fp(C,d,D)}}function fp(c,d,D){for(var C=c;C!==null;)ev(C,d,D),C=C.sibling}function xd(c,d){return c.tag===Qe&&c.type===d&&c.stateNode!==null}function Rd(c,d){return{getChildren:function(){var D=d.fiber,C=D.child,O=[];return C!==null&&fp(C,c,O),O.length===0?null:O},getChildrenFromRoot:function(){for(var D=d.fiber,C=D;C!==null;){var O=C.return;if(O===null||(C=O,C.tag===Qe&&C.type===c))break}var z=[];return fp(C.child,c,z),z.length===0?null:z},getParent:function(){for(var D=d.fiber.return;D!==null;){if(D.tag===Qe&&D.type===c)return D.stateNode.methods;D=D.return}return null},getProps:function(){var D=d.fiber;return D.memoizedProps},queryAllNodes:function(D){var C=d.fiber,O=C.child,z=[];return O!==null&&ap(O,D,z),z.length===0?null:z},queryFirstNode:function(D){var C=d.fiber,O=C.child;return O!==null?$h(O,D):null},containsNode:function(D){for(var C=cr(D);C!==null;){if(C.tag===Qe&&C.type===c&&C.stateNode===d)return!0;C=C.return}return!1}}}function H0(c){c.effectTag|=Dr}function Ad(c){c.effectTag|=Oo}var Ca,$a,Od,Md;if(b0)Ca=function(c,d,D,C){for(var O=d.child;O!==null;){if(O.tag===V||O.tag===re)Xr(c,O.stateNode);else if(Wt&&O.tag===_t)Xr(c,O.stateNode.instance);else if(O.tag!==q){if(O.child!==null){O.child.return=O,O=O.child;continue}}if(O===d)return;for(;O.sibling===null;){if(O.return===null||O.return===d)return;O=O.return}O.sibling.return=O.return,O=O.sibling}},$a=function(c){},Od=function(c,d,D,C,O){var z=c.memoizedProps;if(z!==C){var G=d.stateNode,ne=fl(),se=p0(G,D,z,C,O,ne);d.updateQueue=se,se&&H0(d)}},Md=function(c,d,D,C){D!==C&&H0(d)};else if(Q){Ca=function(c,d,D,C){for(var O=d.child;O!==null;){e:if(O.tag===V){var z=O.stateNode;if(D&&C){var G=O.memoizedProps,ne=O.type;z=Jr(z,ne,G,O)}Xr(c,z)}else if(O.tag===re){var se=O.stateNode;if(D&&C){var Ue=O.memoizedProps;se=Zl(se,Ue,O)}Xr(c,se)}else if(Wt&&O.tag===_t){var Xe=O.stateNode.instance;if(D&&C){var ht=O.memoizedProps,Lt=O.type;Xe=Jr(Xe,Lt,ht,O)}Xr(c,Xe)}else if(O.tag!==q){if(O.tag===he){if((O.effectTag&Dr)!==xi){var Gt=O.memoizedState!==null;if(Gt){var Ht=O.child;if(Ht!==null){Ht.child!==null&&(Ht.child.return=Ht,Ca(c,Ht,!0,Gt));var yn=Ht.sibling;if(yn!==null){yn.return=O,O=yn;continue}}}}if(O.child!==null){O.child.return=O,O=O.child;continue}}else if(O.child!==null){O.child.return=O,O=O.child;continue}}if(O=O,O===d)return;for(;O.sibling===null;){if(O.return===null||O.return===d)return;O=O.return}O.sibling.return=O.return,O=O.sibling}};var cp=function(c,d,D,C){for(var O=d.child;O!==null;){e:if(O.tag===V){var z=O.stateNode;if(D&&C){var G=O.memoizedProps,ne=O.type;z=Jr(z,ne,G,O)}Qn(c,z)}else if(O.tag===re){var se=O.stateNode;if(D&&C){var Ue=O.memoizedProps;se=Zl(se,Ue,O)}Qn(c,se)}else if(Wt&&O.tag===_t){var Xe=O.stateNode.instance;if(D&&C){var ht=O.memoizedProps,Lt=O.type;Xe=Jr(Xe,Lt,ht,O)}Qn(c,Xe)}else if(O.tag!==q){if(O.tag===he){if((O.effectTag&Dr)!==xi){var Gt=O.memoizedState!==null;if(Gt){var Ht=O.child;if(Ht!==null){Ht.child!==null&&(Ht.child.return=Ht,cp(c,Ht,!0,Gt));var yn=Ht.sibling;if(yn!==null){yn.return=O,O=yn;continue}}}}if(O.child!==null){O.child.return=O,O=O.child;continue}}else if(O.child!==null){O.child.return=O,O=O.child;continue}}if(O=O,O===d)return;for(;O.sibling===null;){if(O.return===null||O.return===d)return;O=O.return}O.sibling.return=O.return,O=O.sibling}};$a=function(c){var d=c.stateNode,D=c.firstEffect===null;if(!D){var C=d.containerInfo,O=S0(C);cp(O,c,!1,!1),d.pendingChildren=O,H0(c),ac(C,O)}},Od=function(c,d,D,C,O){var z=c.stateNode,G=c.memoizedProps,ne=d.firstEffect===null;if(ne&&G===C){d.stateNode=z;return}var se=d.stateNode,Ue=fl(),Xe=null;if(G!==C&&(Xe=p0(se,D,G,C,O,Ue)),ne&&Xe===null){d.stateNode=z;return}var ht=ms(z,Xe,D,G,C,d,ne,se);Au(ht,D,C,O,Ue)&&H0(d),d.stateNode=ht,ne?H0(d):Ca(ht,d,!1,!1)},Md=function(c,d,D,C){if(D!==C){var O=ns(),z=fl();d.stateNode=hs(C,O,z,d),H0(d)}}}else $a=function(c){},Od=function(c,d,D,C,O){},Md=function(c,d,D,C){};function kd(c,d){switch(c.tailMode){case"hidden":{for(var D=c.tail,C=null;D!==null;)D.alternate!==null&&(C=D),D=D.sibling;C===null?c.tail=null:C.sibling=null;break}case"collapsed":{for(var O=c.tail,z=null;O!==null;)O.alternate!==null&&(z=O),O=O.sibling;z===null?!d&&c.tail!==null?c.tail.sibling=null:c.tail=null:z.sibling=null;break}}}function tv(c,d,D){var C=d.pendingProps;switch(d.tag){case x:break;case Ae:break;case ue:case F:break;case k:{var O=d.type;Xi(O)&&Hs(d);break}case j:{uo(d),R0(d);var z=d.stateNode;if(z.pendingContext&&(z.context=z.pendingContext,z.pendingContext=null),c===null||c.child===null){var G=h1(d);G&&H0(d)}$a(d);break}case V:{M2(d);var ne=ns(),se=d.type;if(c!==null&&d.stateNode!=null){if(Od(c,d,se,C,ne),yi){var Ue=c.memoizedProps.listeners,Xe=C.listeners;Ue!==Xe&&H0(d)}c.ref!==d.ref&&Ad(d)}else{if(!C){if(d.stateNode===null)throw Error("We must have new props for new mounts. This error is likely caused by a bug in React. Please file an issue.");break}var ht=fl(),Lt=h1(d);if(Lt){if(vm(d,ne,ht)&&H0(d),yi){var Gt=C.listeners;Gt!=null&&hn(Gt,d,ne)}}else{var Ht=Ki(se,C,ne,ht,d);if(Ca(Ht,d,!1,!1),d.stateNode=Ht,yi){var yn=C.listeners;yn!=null&&hn(yn,d,ne)}Au(Ht,se,C,ne,ht)&&H0(d)}d.ref!==null&&Ad(d)}break}case re:{var kr=C;if(c&&d.stateNode!=null){var ii=c.memoizedProps;Md(c,d,ii,kr)}else{if(typeof kr!="string"&&d.stateNode===null)throw Error("We must have new props for new mounts. This error is likely caused by a bug in React. Please file an issue.");var Oi=ns(),L0=fl(),$i=h1(d);$i?mm(d)&&H0(d):d.stateNode=hs(kr,Oi,L0,d)}break}case ae:break;case he:{ga(d);var lt=d.memoizedState;if(Ai&<!==null&<.dehydrated!==null)if(c===null){var Mt=h1(d);if(!Mt)throw Error("A dehydrated suspense component was completed without a hydrated node. This is probably a bug in React.");return Ih(d),In&&R(Di),null}else return v1(),(d.effectTag&Kr)===xi&&(d.memoizedState=null),d.effectTag|=Dr,null;if((d.effectTag&Kr)!==xi)return d.expirationTime=D,d;var $e=lt!==null,jt=!1;if(c===null)d.memoizedProps.fallback!==void 0&&h1(d);else{var Fn=c.memoizedState;if(jt=Fn!==null,!$e&&Fn!==null){var vn=c.child.sibling;if(vn!==null){var Vi=d.firstEffect;Vi!==null?(d.firstEffect=vn,vn.nextEffect=Vi):(d.firstEffect=d.lastEffect=vn,vn.nextEffect=null),vn.effectTag=Y0}}}if($e&&!jt&&(d.mode&K)!==Ar){var ci=c===null&&d.memoizedProps.unstable_avoidThisFallback!==!0;ci||t1(Nl.current,xf)?_v():Ev()}Q&&$e&&(d.effectTag|=Dr),b0&&($e||jt)&&(d.effectTag|=Dr),Yi&&d.updateQueue!==null&&d.memoizedProps.suspenseCallback!=null&&(d.effectTag|=Dr);break}case y:break;case me:break;case we:break;case q:uo(d),$a(d);break;case ge:r0(d);break;case De:break;case ve:break;case ze:{var Yu=d.type;Xi(Yu)&&Hs(d);break}case gt:{ga(d);var hr=d.memoizedState;if(hr===null)break;var pu=(d.effectTag&Kr)!==xi,Yr=hr.rendering;if(Yr===null)if(pu)kd(hr,!1);else{var Cu=Dv()&&(c===null||(c.effectTag&Kr)===xi);if(!Cu)for(var D0=d.child;D0!==null;){var W0=n1(D0);if(W0!==null){pu=!0,d.effectTag|=Kr,kd(hr,!1);var Ms=W0.updateQueue;return Ms!==null&&(d.updateQueue=Ms,d.effectTag|=Dr),hr.lastEffect===null&&(d.firstEffect=null),d.lastEffect=hr.lastEffect,sm(d,D),Fr(d,hd(Nl.current,e1)),d.child}D0=D0.sibling}}else{if(!pu){var Ku=n1(Yr);if(Ku!==null){d.effectTag|=Kr,pu=!0;var gl=Ku.updateQueue;if(gl!==null&&(d.updateQueue=gl,d.effectTag|=Dr),kd(hr,!0),hr.tail===null&&hr.tailMode==="hidden"&&!Yr.alternate){var rf=d.lastEffect=hr.lastEffect;return rf!==null&&(rf.nextEffect=null),null}}else if(mt()>hr.tailExpiration&&D>Di){d.effectTag|=Kr,pu=!0,kd(hr,!1);var Vo=D-1;d.expirationTime=d.childExpirationTime=Vo,In&&R(Vo)}}if(hr.isBackwards)Yr.sibling=d.child,d.child=Yr;else{var ks=hr.last;ks!==null?ks.sibling=Yr:d.child=Yr,hr.last=Yr}}if(hr.tail!==null){if(hr.tailExpiration===0){var Jd=500;hr.tailExpiration=mt()+Jd}var Vf=hr.tail;hr.rendering=Vf,hr.tail=Vf.sibling,hr.lastEffect=d.lastEffect,Vf.sibling=null;var Lc=Nl.current;return pu?Lc=hd(Lc,e1):Lc=ya(Lc),Fr(d,Lc),Vf}break}case _t:{if(Wt){var Hl=d.type.impl,Go=d.stateNode;if(Go===null){var L1=Hl.getInitialState,i_;L1!==void 0&&(i_=L1(C)),Go=d.stateNode=Qh(d,C,Hl,i_||{});var u_=pt(Go);if(Go.instance=u_,Hl.reconcileChildren===!1)return null;Ca(u_,d,!1,!1),Yn(Go)}else{var nE=Go.props;if(Go.prevProps=nE,Go.props=C,Go.currentFiber=d,Q){var o_=oa(Go);Go.instance=o_,Ca(o_,d,!1,!1)}var rE=Cn(Go);rE&&H0(d)}}break}case Qe:{if(Ru)if(c===null){var iE=d.type,Ry={fiber:d,methods:null};if(d.stateNode=Ry,Ry.methods=Rd(iE,Ry),yi){var l_=C.listeners;if(l_!=null){var uE=ns();hn(l_,d,uE)}}d.ref!==null&&(Ad(d),H0(d))}else{if(yi){var oE=c.memoizedProps.listeners,lE=C.listeners;(oE!==lE||d.ref!==null)&&H0(d)}else d.ref!==null&&H0(d);c.ref!==d.ref&&Ad(d)}break}default:throw Error("Unknown unit of work tag ("+d.tag+"). This error is likely caused by a bug in React. Please file an issue.")}return null}function Mm(c,d){switch(c.tag){case k:{var D=c.type;Xi(D)&&Hs(c);var C=c.effectTag;return C&d0?(c.effectTag=C&~d0|Kr,c):null}case j:{uo(c),R0(c);var O=c.effectTag;if((O&Kr)!==xi)throw Error("The root failed to unmount after an error. This is likely a bug in React. Please file an issue.");return c.effectTag=O&~d0|Kr,c}case V:return M2(c),null;case he:{if(ga(c),Ai){var z=c.memoizedState;if(z!==null&&z.dehydrated!==null){if(c.alternate===null)throw Error("Threw in newly mounted dehydrated component. This is likely a bug in React. Please file an issue.");v1()}}var G=c.effectTag;return G&d0?(c.effectTag=G&~d0|Kr,c):null}case gt:return ga(c),null;case q:return uo(c),null;case ge:return r0(c),null;default:return null}}function nv(c){switch(c.tag){case k:{var d=c.type.childContextTypes;d!=null&&Hs(c);break}case j:{uo(c),R0(c);break}case V:{M2(c);break}case q:uo(c);break;case he:ga(c);break;case gt:ga(c);break;case ge:r0(c);break;default:break}}function dp(c,d){return{value:c,source:d,stack:Cr(d)}}var pp=function(c,d,D,C,O,z,G,ne,se){var Ue=Array.prototype.slice.call(arguments,3);try{d.apply(D,Ue)}catch(Xe){this.onError(Xe)}};if(typeof window<"u"&&typeof window.dispatchEvent=="function"&&typeof document<"u"&&typeof document.createEvent=="function"){var hp=document.createElement("react"),km=function(c,d,D,C,O,z,G,ne,se){if(!(typeof document<"u"))throw Error("The `document` global was defined when React was initialized, but is not defined anymore. This can happen in a test environment if a component schedules an update from an asynchronous callback, but the test has already finished running. To solve this, you can either unmount the component at the end of your test (and ensure that any asynchronous operations get canceled in `componentWillUnmount`), or you can change the test itself to be asynchronous.");var Ue=document.createEvent("Event"),Xe=!0,ht=window.event,Lt=Object.getOwnPropertyDescriptor(window,"event"),Gt=Array.prototype.slice.call(arguments,3);function Ht(){hp.removeEventListener(L0,Ht,!1),typeof window.event<"u"&&window.hasOwnProperty("event")&&(window.event=ht),d.apply(D,Gt),Xe=!1}var yn,kr=!1,ii=!1;function Oi($i){if(yn=$i.error,kr=!0,yn===null&&$i.colno===0&&$i.lineno===0&&(ii=!0),$i.defaultPrevented&&yn!=null&&typeof yn=="object")try{yn._suppressLogging=!0}catch{}}var L0="react-"+(c||"invokeguardedcallback");window.addEventListener("error",Oi),hp.addEventListener(L0,Ht,!1),Ue.initEvent(L0,!1,!1),hp.dispatchEvent(Ue),Lt&&Object.defineProperty(window,"event",Lt),Xe&&(kr?ii&&(yn=new Error("A cross-origin error was thrown. React doesn't have access to the actual error object in development. See https://fb.me/react-crossorigin-error for more information.")):yn=new Error(`An error was thrown inside one of your components, but React doesn't know what it was. This is likely due to browser flakiness. React does its best to preserve the "Pause on exceptions" behavior of the DevTools, which requires some DEV-mode only tricks. It's possible that these don't work in your browser. Try triggering the error in production mode, or switching to a modern browser. If you suspect that this is actually an issue with React, please file an issue.`),this.onError(yn)),window.removeEventListener("error",Oi)};pp=km}var Nm=pp,So=!1,Nd=null,Lm={onError:function(c){So=!0,Nd=c}};function pl(c,d,D,C,O,z,G,ne,se){So=!1,Nd=null,Nm.apply(Lm,arguments)}function tr(){return So}function Qs(){if(So){var c=Nd;return So=!1,Nd=null,c}else throw Error("clearCaughtError was called but no error was captured. This error is likely caused by a bug in React. Please file an issue.")}function hl(c){return!0}function o0(c){var d=hl(c);if(d!==!1){var D=c.error;{var C=c.componentName,O=c.componentStack,z=c.errorBoundaryName,G=c.errorBoundaryFound,ne=c.willRetry;if(D!=null&&D._suppressLogging){if(G&&ne)return;console.error(D)}var se=C?"The above error occurred in the <"+C+"> component:":"The above error occurred in one of your React components:",Ue;G&&z?ne?Ue="React will try to recreate this component tree from scratch "+("using the error boundary you provided, "+z+"."):Ue="This error was initially handled by the error boundary "+z+`. +Recreating the tree from scratch failed so React will unmount the tree.`:Ue=`Consider adding an error boundary to your tree to customize error handling behavior. +Visit https://fb.me/react-error-boundaries to learn more about error boundaries.`;var Xe=""+se+O+` + +`+(""+Ue);console.error(Xe)}}}var rv=null;rv=new Set;var Js=typeof WeakSet=="function"?WeakSet:Set;function vp(c,d){var D=d.source,C=d.stack;C===null&&D!==null&&(C=Cr(D));var O={componentName:D!==null?qt(D.type):null,componentStack:C!==null?C:"",error:d.value,errorBoundary:null,errorBoundaryName:null,errorBoundaryFound:!1,willRetry:!1};c!==null&&c.tag===k&&(O.errorBoundary=c.stateNode,O.errorBoundaryName=qt(c.type),O.errorBoundaryFound=!0,O.willRetry=!0);try{o0(O)}catch(z){setTimeout(function(){throw z})}}var Fm=function(c,d){Bi(c,"componentWillUnmount"),d.props=c.memoizedProps,d.state=c.memoizedState,d.componentWillUnmount(),Ci()};function iv(c,d){if(pl(null,Fm,null,c,d),tr()){var D=Qs();Hf(c,D)}}function mp(c){var d=c.ref;if(d!==null)if(typeof d=="function"){if(pl(null,d,null,null),tr()){var D=Qs();Hf(c,D)}}else d.current=null}function Pm(c,d){if(pl(null,d,null),tr()){var D=Qs();Hf(c,D)}}function yp(c,d){switch(d.tag){case F:case ae:case ue:{Tc(fm,Af,d);return}case k:{if(d.effectTag&Mo&&c!==null){var D=c.memoizedProps,C=c.memoizedState;Bi(d,"getSnapshotBeforeUpdate");var O=d.stateNode;d.type===d.elementType&&!Sa&&(O.props!==d.memoizedProps&&Xt(!1,"Expected %s props to match memoized props before getSnapshotBeforeUpdate. This might either be because of a bug in React, or because a component reassigns its own `this.props`. Please file an issue.",qt(d.type)||"instance"),O.state!==d.memoizedState&&Xt(!1,"Expected %s state to match memoized state before getSnapshotBeforeUpdate. This might either be because of a bug in React, or because a component reassigns its own `this.props`. Please file an issue.",qt(d.type)||"instance"));var z=O.getSnapshotBeforeUpdate(d.elementType===d.type?D:Wi(d.type,D),C);{var G=rv;z===void 0&&!G.has(d.type)&&(G.add(d.type),Ve(!1,"%s.getSnapshotBeforeUpdate(): A snapshot value (or null) must be returned. You have returned undefined.",qt(d.type)))}O.__reactInternalSnapshotBeforeUpdate=z,Ci()}return}case j:case V:case re:case q:case ze:return;default:throw Error("This unit of work tag should not have side-effects. This error is likely caused by a bug in React. Please file an issue.")}}function Tc(c,d,D){var C=D.updateQueue,O=C!==null?C.lastEffect:null;if(O!==null){var z=O.next,G=z;do{if((G.tag&c)!==Af){var ne=G.destroy;G.destroy=void 0,ne!==void 0&&ne()}if((G.tag&d)!==Af){var se=G.create;G.destroy=se();{var Ue=G.destroy;if(Ue!==void 0&&typeof Ue!="function"){var Xe=void 0;Ue===null?Xe=" You returned null. If your effect does not require clean up, return undefined (or nothing).":typeof Ue.then=="function"?Xe=` + +It looks like you wrote useEffect(async () => ...) or returned a Promise. Instead, write the async function inside your effect and call it immediately: + +useEffect(() => { + async function fetchData() { + // You can await here + const response = await MyAPI.getData(someId); + // ... + } + fetchData(); +}, [someId]); // Or [] if effect doesn't need props or state + +Learn more about data fetching with Hooks: https://fb.me/react-hooks-data-fetching`:Xe=" You returned: "+Ue,Ve(!1,"An effect function must not return anything besides a function, which is used for clean-up.%s%s",Xe,Cr(D))}}}G=G.next}while(G!==z)}}function xa(c){if((c.effectTag&F0)!==xi)switch(c.tag){case F:case ae:case ue:{Tc(sr,Af,c),Tc(Af,r1,c);break}default:break}}function gp(c,d,D,C){switch(D.tag){case F:case ae:case ue:{Tc(cm,cl,D);break}case k:{var O=D.stateNode;if(D.effectTag&Dr)if(d===null)Bi(D,"componentDidMount"),D.type===D.elementType&&!Sa&&(O.props!==D.memoizedProps&&Xt(!1,"Expected %s props to match memoized props before componentDidMount. This might either be because of a bug in React, or because a component reassigns its own `this.props`. Please file an issue.",qt(D.type)||"instance"),O.state!==D.memoizedState&&Xt(!1,"Expected %s state to match memoized state before componentDidMount. This might either be because of a bug in React, or because a component reassigns its own `this.props`. Please file an issue.",qt(D.type)||"instance")),O.componentDidMount(),Ci();else{var z=D.elementType===D.type?d.memoizedProps:Wi(D.type,d.memoizedProps),G=d.memoizedState;Bi(D,"componentDidUpdate"),D.type===D.elementType&&!Sa&&(O.props!==D.memoizedProps&&Xt(!1,"Expected %s props to match memoized props before componentDidUpdate. This might either be because of a bug in React, or because a component reassigns its own `this.props`. Please file an issue.",qt(D.type)||"instance"),O.state!==D.memoizedState&&Xt(!1,"Expected %s state to match memoized state before componentDidUpdate. This might either be because of a bug in React, or because a component reassigns its own `this.props`. Please file an issue.",qt(D.type)||"instance")),O.componentDidUpdate(z,G,O.__reactInternalSnapshotBeforeUpdate),Ci()}var ne=D.updateQueue;ne!==null&&(D.type===D.elementType&&!Sa&&(O.props!==D.memoizedProps&&Xt(!1,"Expected %s props to match memoized props before processing the update queue. This might either be because of a bug in React, or because a component reassigns its own `this.props`. Please file an issue.",qt(D.type)||"instance"),O.state!==D.memoizedState&&Xt(!1,"Expected %s state to match memoized state before processing the update queue. This might either be because of a bug in React, or because a component reassigns its own `this.props`. Please file an issue.",qt(D.type)||"instance")),go(D,ne,O,C));return}case j:{var se=D.updateQueue;if(se!==null){var Ue=null;if(D.child!==null)switch(D.child.tag){case V:Ue=Lo(D.child.stateNode);break;case k:Ue=D.child.stateNode;break}go(D,se,Ue,C)}return}case V:{var Xe=D.stateNode;if(d===null&&D.effectTag&Dr){var ht=D.type,Lt=D.memoizedProps;zu(Xe,ht,Lt,D)}return}case re:return;case q:return;case we:{if(en){var Gt=D.memoizedProps.onRender;typeof Gt=="function"&&(In?Gt(D.memoizedProps.id,d===null?"mount":"update",D.actualDuration,D.treeBaseDuration,D.actualStartTime,Il(),c.memoizedInteractions):Gt(D.memoizedProps.id,d===null?"mount":"update",D.actualDuration,D.treeBaseDuration,D.actualStartTime,Il()))}return}case he:{Bl(c,D);return}case gt:case ze:case _t:case Qe:return;default:throw Error("This unit of work tag should not have side-effects. This error is likely caused by a bug in React. Please file an issue.")}}function Ld(c,d){if(b0)for(var D=c;;){if(D.tag===V){var C=D.stateNode;d?Pa(C):ia(D.stateNode,D.memoizedProps)}else if(D.tag===re){var O=D.stateNode;d?v0(O):J0(O,D.memoizedProps)}else if(D.tag===he&&D.memoizedState!==null&&D.memoizedState.dehydrated===null){var z=D.child.sibling;z.return=D,D=z;continue}else if(D.child!==null){D.child.return=D,D=D.child;continue}if(D===c)return;for(;D.sibling===null;){if(D.return===null||D.return===c)return;D=D.return}D.sibling.return=D.return,D=D.sibling}}function Iu(c){var d=c.ref;if(d!==null){var D=c.stateNode,C;switch(c.tag){case V:C=Lo(D);break;default:C=D}Ru&&c.tag===Qe&&(C=D.methods),typeof d=="function"?d(C):(d.hasOwnProperty("current")||Ve(!1,"Unexpected ref object provided for %s. Use either a ref-setter function or React.createRef().%s",qt(c.type),Cr(c)),d.current=C)}}function Gu(c){var d=c.ref;d!==null&&(typeof d=="function"?d(null):d.current=null)}function _p(c,d,D){switch(Mn(d),d.tag){case F:case ae:case ve:case ue:{var C=d.updateQueue;if(C!==null){var O=C.lastEffect;if(O!==null){var z=O.next,G=D>Kn?Kn:D;Sn(G,function(){var ii=z;do{var Oi=ii.destroy;Oi!==void 0&&Pm(d,Oi),ii=ii.next}while(ii!==z)})}}break}case k:{mp(d);var ne=d.stateNode;typeof ne.componentWillUnmount=="function"&&iv(d,ne);return}case V:{if(yi){var se=d.dependencies;if(se!==null){var Ue=se.responders;if(Ue!==null){for(var Xe=Array.from(Ue.values()),ht=0,Lt=Xe.length;ht component higher in the tree to provide a loading indicator or placeholder to display.`+Cr(D))}Op(),C=dp(C,D);var Lt=d;do{switch(Lt.tag){case j:{var Gt=C;Lt.effectTag|=d0,Lt.expirationTime=O;var Ht=sv(Lt,Gt,O);od(Lt,Ht);return}case k:var yn=C,kr=Lt.type,ii=Lt.stateNode;if((Lt.effectTag&Kr)===xi&&(typeof kr.getDerivedStateFromError=="function"||ii!==null&&typeof ii.componentDidCatch=="function"&&!Fp(ii))){Lt.effectTag|=d0,Lt.expirationTime=O;var Oi=av(Lt,yn,O);od(Lt,Oi);return}break;default:break}Lt=Lt.return}while(Lt!==null)}var Aa=Math.ceil,Mr=it.ReactCurrentDispatcher,Dp=it.ReactCurrentOwner,vl=it.IsSomeRendererActing,yu=0,T1=1,Ui=2,wp=4,Id=8,To=16,As=32,bf=0,bd=1,Sp=2,C1=3,x1=4,Tp=5,nr=yu,ml=null,Gn=null,q0=ft,k0=bf,Bd=null,Ul=Un,R1=Un,xc=null,Rc=ft,Ud=!1,Cp=0,N0=500,dn=null,jd=!1,zd=null,Ac=null,Oc=!1,Mc=null,A1=_0,xp=ft,ef=null,Hm=50,kc=0,Hd=null,cv=50,O1=0,Bf=null,Uf=null,M1=ft;function jl(){return(nr&(To|As))!==yu?t0(mt()):(M1!==ft||(M1=t0(mt())),M1)}function Nc(){return t0(mt())}function jf(c,d,D){var C=d.mode;if((C&K)===Ar)return Un;var O=Qt();if((C&ti)===Ar)return O===Li?Un:e0;if((nr&To)!==yu)return q0;var z;if(D!==null)z=fa(c,D.timeoutMs|0||_f);else switch(O){case Li:z=Un;break;case ei:z=Ua(c);break;case Kn:case $u:z=Ds(c);break;case g0:z=ru;break;default:throw Error("Expected a valid priority level")}return ml!==null&&z===q0&&(z-=1),z}function qm(c,d){sy(),dy(c);var D=qd(c,d);if(D===null){fy(c);return}jp(c,d),la();var C=Qt();if(d===Un?(nr&Id)!==yu&&(nr&(To|As))===yu?(W(D,d),k1(D)):(Wo(D),W(D,d),nr===yu&&Ut()):(Wo(D),W(D,d)),(nr&wp)!==yu&&(C===ei||C===Li))if(ef===null)ef=new Map([[D,d]]);else{var O=ef.get(D);(O===void 0||O>d)&&ef.set(D,d)}}var yl=qm;function qd(c,d){c.expirationTimeO?C:O}function Wo(c){var d=c.lastExpiredTime;if(d!==ft){c.callbackExpirationTime=Un,c.callbackPriority=Li,c.callbackNode=Tn(k1.bind(null,c));return}var D=Wd(c),C=c.callbackNode;if(D===ft){C!==null&&(c.callbackNode=null,c.callbackExpirationTime=ft,c.callbackPriority=_0);return}var O=jl(),z=nd(O,D);if(C!==null){var G=c.callbackPriority,ne=c.callbackExpirationTime;if(ne===D&&G>=z)return;ir(C)}c.callbackExpirationTime=D,c.callbackPriority=z;var se;D===Un?se=Tn(k1.bind(null,c)):ao?se=_n(z,Vd.bind(null,c)):se=_n(z,Vd.bind(null,c),{timeout:jo(D)-mt()}),c.callbackNode=se}function Vd(c,d){if(M1=ft,d){var D=jl();return qp(c,D),Wo(c),null}var C=Wd(c);if(C!==ft){var O=c.callbackNode;if((nr&(To|As))!==yu)throw Error("Should not already be working.");if(tf(),(c!==ml||C!==q0)&&(zf(c,C),te(c,C)),Gn!==null){var z=nr;nr|=To;var G=mv(c),ne=Gd(c);mf(Gn);do try{ey();break}catch(Xe){vv(c,Xe)}while(!0);if(yt(),nr=z,yv(G),In&&Yd(ne),k0===bd){var se=Bd;throw Up(),zf(c,C),Wf(c,C),Wo(c),se}if(Gn!==null)Up();else{Rv();var Ue=c.finishedWork=c.current.alternate;c.finishedExpirationTime=C,Wm(c,Ue,k0,C)}if(Wo(c),c.callbackNode===O)return Vd.bind(null,c)}}return null}function Wm(c,d,D,C){switch(ml=null,D){case bf:case bd:throw Error("Root did not complete. This is a bug in React.");case Sp:{qp(c,C>ru?ru:C);break}case C1:{Wf(c,C);var O=c.lastSuspendedTime;C===O&&(c.nextKnownPendingLevel=Mp(d)),p();var z=Ul===Un;if(z&&!(Q0&&qf.current)){var G=Cp+N0-mt();if(G>10){if(Ud){var ne=c.lastPingedTime;if(ne===ft||ne>=C){c.lastPingedTime=C,zf(c,C);break}}var se=Wd(c);if(se!==ft&&se!==C)break;if(O!==ft&&O!==C){c.lastPingedTime=O;break}c.timeoutHandle=Ct(l0.bind(null,c),G);break}}l0(c);break}case x1:{Wf(c,C);var Ue=c.lastSuspendedTime;if(C===Ue&&(c.nextKnownPendingLevel=Mp(d)),p(),!(Q0&&qf.current)){if(Ud){var Xe=c.lastPingedTime;if(Xe===ft||Xe>=C){c.lastPingedTime=C,zf(c,C);break}}var ht=Wd(c);if(ht!==ft&&ht!==C)break;if(Ue!==ft&&Ue!==C){c.lastPingedTime=Ue;break}var Lt;if(R1!==Un)Lt=jo(R1)-mt();else if(Ul===Un)Lt=0;else{var Gt=wv(Ul),Ht=mt(),yn=jo(C)-Ht,kr=Ht-Gt;kr<0&&(kr=0),Lt=bp(kr)-kr,yn10){c.timeoutHandle=Ct(l0.bind(null,c),Lt);break}}l0(c);break}case Tp:{if(!(Q0&&qf.current)&&Ul!==Un&&xc!==null){var ii=Bp(Ul,C,xc);if(ii>10){Wf(c,C),c.timeoutHandle=Ct(l0.bind(null,c),ii);break}}l0(c);break}default:throw Error("Unknown root exit status.")}}function k1(c){var d=c.lastExpiredTime,D=d!==ft?d:Un;if(c.finishedExpirationTime===D)l0(c);else{if((nr&(To|As))!==yu)throw Error("Should not already be working.");if(tf(),(c!==ml||D!==q0)&&(zf(c,D),te(c,D)),Gn!==null){var C=nr;nr|=To;var O=mv(c),z=Gd(c);mf(Gn);do try{Sv();break}catch(ne){vv(c,ne)}while(!0);if(yt(),nr=C,yv(O),In&&Yd(z),k0===bd){var G=Bd;throw Up(),zf(c,D),Wf(c,D),Wo(c),G}if(Gn!==null)throw Error("Cannot commit an incomplete root. This error is likely caused by a bug in React. Please file an issue.");Rv(),c.finishedWork=c.current.alternate,c.finishedExpirationTime=D,Vm(c,k0,D),Wo(c)}}return null}function Vm(c,d,D){ml=null,(d===C1||d===x1)&&p(),l0(c)}function Gm(c,d){qp(c,d),Wo(c),(nr&(To|As))===yu&&Ut()}function dv(){if((nr&(T1|To|As))!==yu){(nr&To)!==yu&&Xt(!1,"unstable_flushDiscreteUpdates: Cannot flush updates when React is already rendering.");return}Km(),tf()}function Ym(c){return Sn(Kn,c)}function pv(c,d,D,C){return Sn(Li,c.bind(null,d,D,C))}function Km(){if(ef!==null){var c=ef;ef=null,c.forEach(function(d,D){qp(D,d),Wo(D)}),Ut()}}function Xm(c,d){var D=nr;nr|=T1;try{return c(d)}finally{nr=D,nr===yu&&Ut()}}function Qm(c,d){var D=nr;nr|=Ui;try{return c(d)}finally{nr=D,nr===yu&&Ut()}}function hv(c,d,D,C){var O=nr;nr|=wp;try{return Sn(ei,c.bind(null,d,D,C))}finally{nr=O,nr===yu&&Ut()}}function Jm(c,d){var D=nr;nr&=~T1,nr|=Id;try{return c(d)}finally{nr=D,nr===yu&&Ut()}}function Rp(c,d){if((nr&(To|As))!==yu)throw Error("flushSync was called from inside a lifecycle method. It cannot be called when React is already rendering.");var D=nr;nr|=T1;try{return Sn(Li,c.bind(null,d))}finally{nr=D,Ut()}}function Zm(c){var d=nr;nr|=T1;try{Sn(Li,c)}finally{nr=d,nr===yu&&Ut()}}function zf(c,d){c.finishedWork=null,c.finishedExpirationTime=ft;var D=c.timeoutHandle;if(D!==nl&&(c.timeoutHandle=nl,co(D)),Gn!==null)for(var C=Gn.return;C!==null;)nv(C),C=C.return;ml=c,Gn=Co(c.current,null,d),q0=d,k0=bf,Bd=null,Ul=Un,R1=Un,xc=null,Rc=ft,Ud=!1,In&&(Uf=null),Al.discardPendingWarnings(),Zs=null}function vv(c,d){do{try{if(yt(),_d(),ut(),Gn===null||Gn.return===null)return k0=bd,Bd=d,null;en&&Gn.mode&ni&&p1(Gn,!0),fv(c,Gn.return,Gn,d,q0),Gn=Tv(Gn)}catch(D){d=D;continue}return}while(!0)}function mv(c){var d=Mr.current;return Mr.current=f1,d===null?f1:d}function yv(c){Mr.current=c}function Gd(c){if(In){var d=N.__interactionsRef.current;return N.__interactionsRef.current=c.memoizedInteractions,d}return null}function Yd(c){In&&(N.__interactionsRef.current=c)}function Ap(){Cp=mt()}function gv(c,d){cru&&(Ul=c),d!==null&&cru&&(R1=c,xc=d)}function Kd(c){c>Rc&&(Rc=c)}function _v(){k0===bf&&(k0=C1)}function Ev(){(k0===bf||k0===C1)&&(k0=x1),Rc!==ft&&ml!==null&&(Wf(ml,q0),Kg(ml,Rc))}function Op(){k0!==Tp&&(k0=Sp)}function Dv(){return k0===bf}function wv(c){var d=jo(c);return d-_f}function $m(c,d){var D=jo(c);return D-(d.timeoutMs|0||_f)}function Sv(){for(;Gn!==null;)Gn=Xd(Gn)}function ey(){for(;Gn!==null&&!Ln();)Gn=Xd(Gn)}function Xd(c){var d=c.alternate;$l(c),wt(c);var D;return en&&(c.mode&ni)!==Ar?(H2(c),D=N1(d,c,q0),p1(c,!0)):D=N1(d,c,q0),ut(),c.memoizedProps=c.pendingProps,D===null&&(D=Tv(c)),Dp.current=null,D}function Tv(c){Gn=c;do{var d=Gn.alternate,D=Gn.return;if((Gn.effectTag&P0)===xi){wt(Gn);var C=void 0;if(!en||(Gn.mode&ni)===Ar?C=tv(d,Gn,q0):(H2(Gn),C=tv(d,Gn,q0),p1(Gn,!1)),Zr(Gn),ut(),ty(Gn),C!==null)return C;if(D!==null&&(D.effectTag&P0)===xi){D.firstEffect===null&&(D.firstEffect=Gn.firstEffect),Gn.lastEffect!==null&&(D.lastEffect!==null&&(D.lastEffect.nextEffect=Gn.firstEffect),D.lastEffect=Gn.lastEffect);var O=Gn.effectTag;O>lu&&(D.lastEffect!==null?D.lastEffect.nextEffect=Gn:D.firstEffect=Gn,D.lastEffect=Gn)}}else{var z=Mm(Gn,q0);if(en&&(Gn.mode&ni)!==Ar){p1(Gn,!1);for(var G=Gn.actualDuration,ne=Gn.child;ne!==null;)G+=ne.actualDuration,ne=ne.sibling;Gn.actualDuration=G}if(z!==null)return ho(Gn),z.effectTag&=Kl,z;Zr(Gn),D!==null&&(D.firstEffect=D.lastEffect=null,D.effectTag|=P0)}var se=Gn.sibling;if(se!==null)return se;Gn=D}while(Gn!==null);return k0===bf&&(k0=Tp),null}function Mp(c){var d=c.expirationTime,D=c.childExpirationTime;return d>D?d:D}function ty(c){if(!(q0!==Di&&c.childExpirationTime===Di)){var d=ft;if(en&&(c.mode&ni)!==Ar){for(var D=c.actualDuration,C=c.selfBaseDuration,O=c.alternate===null||c.child!==c.alternate.child,z=c.child;z!==null;){var G=z.expirationTime,ne=z.childExpirationTime;G>d&&(d=G),ne>d&&(d=ne),O&&(D+=z.actualDuration),C+=z.treeBaseDuration,z=z.sibling}c.actualDuration=D,c.treeBaseDuration=C}else for(var se=c.child;se!==null;){var Ue=se.expirationTime,Xe=se.childExpirationTime;Ue>d&&(d=Ue),Xe>d&&(d=Xe),se=se.sibling}c.childExpirationTime=d}}function l0(c){var d=Qt();return Sn(Li,kp.bind(null,c,d)),null}function kp(c,d){do tf();while(Mc!==null);if(ay(),(nr&(To|As))!==yu)throw Error("Should not already be working.");var D=c.finishedWork,C=c.finishedExpirationTime;if(D===null)return null;if(c.finishedWork=null,c.finishedExpirationTime=ft,D===c.current)throw Error("Cannot commit the same tree as before. This error is likely caused by a bug in React. Please file an issue.");c.callbackNode=null,c.callbackExpirationTime=ft,c.callbackPriority=_0,c.nextKnownPendingLevel=ft,eo();var O=Mp(D);q4(c,C,O),c===ml&&(ml=null,Gn=null,q0=ft);var z;if(D.effectTag>lu?D.lastEffect!==null?(D.lastEffect.nextEffect=D,z=D.firstEffect):z=D:z=D.firstEffect,z!==null){var G=nr;nr|=As;var ne=Gd(c);Dp.current=null,xe(),Hn(c.containerInfo),dn=z;do if(pl(null,ny,null),tr()){if(dn===null)throw Error("Should be working on an effect.");var se=Qs();Hf(dn,se),dn=dn.nextEffect}while(dn!==null);tt(),en&&Nh(),Ke(),dn=z;do if(pl(null,ry,null,c,d),tr()){if(dn===null)throw Error("Should be working on an effect.");var Ue=Qs();Hf(dn,Ue),dn=dn.nextEffect}while(dn!==null);Yt(),qr(c.containerInfo),c.current=D,Kt(),dn=z;do if(pl(null,Np,null,c,C),tr()){if(dn===null)throw Error("Should be working on an effect.");var Xe=Qs();Hf(dn,Xe),dn=dn.nextEffect}while(dn!==null);pr(),dn=null,fe(),In&&Yd(ne),nr=G}else c.current=D,xe(),tt(),en&&Nh(),Ke(),Yt(),Kt(),pr();to();var ht=Oc;if(Oc)Oc=!1,Mc=c,xp=C,A1=d;else for(dn=z;dn!==null;){var Lt=dn.nextEffect;dn.nextEffect=null,dn=Lt}var Gt=c.firstPendingTime;if(Gt!==ft){if(In){if(Uf!==null){var Ht=Uf;Uf=null;for(var yn=0;ynKn?Kn:A1;return A1=_0,Sn(c,Lp)}}function Lp(){if(Mc===null)return!1;var c=Mc,d=xp;if(Mc=null,xp=ft,(nr&(To|As))!==yu)throw Error("Cannot flush passive effects while already rendering.");var D=nr;nr|=As;for(var C=Gd(c),O=c.current.firstEffect;O!==null;){{if(wt(O),pl(null,xa,null,O),tr()){if(O===null)throw Error("Should be working on an effect.");var z=Qs();Hf(O,z)}ut()}var G=O.nextEffect;O.nextEffect=null,O=G}return In&&(Yd(C),pe(c,d)),nr=D,Ut(),O1=Mc===null?0:O1+1,!0}function Fp(c){return Ac!==null&&Ac.has(c)}function Pp(c){Ac===null?Ac=new Set([c]):Ac.add(c)}function iy(c){jd||(jd=!0,zd=c)}var uy=iy;function Cv(c,d,D){var C=dp(D,d),O=sv(c,C,Un);Va(c,O);var z=qd(c,Un);z!==null&&(Wo(z),W(z,Un))}function Hf(c,d){if(c.tag===j){Cv(c,c,d);return}for(var D=c.return;D!==null;){if(D.tag===j){Cv(D,c,d);return}else if(D.tag===k){var C=D.type,O=D.stateNode;if(typeof C.getDerivedStateFromError=="function"||typeof O.componentDidCatch=="function"&&!Fp(O)){var z=dp(d,c),G=av(D,z,Un);Va(D,G);var ne=qd(D,Un);ne!==null&&(Wo(ne),W(ne,Un));return}}D=D.return}}function Ip(c,d,D){var C=c.pingCache;if(C!==null&&C.delete(d),ml===c&&q0===D){k0===x1||k0===C1&&Ul===Un&&mt()-CpHm)throw kc=0,Hd=null,Error("Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.");O1>cv&&(O1=0,Xt(!1,"Maximum update depth exceeded. This can happen when a component calls setState inside useEffect, but useEffect either doesn't have a dependency array, or one of the dependencies changes on every render."))}function ay(){Al.flushLegacyContextWarning(),mi&&Al.flushPendingUnsafeLifecycleWarnings()}function Rv(){var c=!0;yf(Bf,c),Bf=null}function Up(){var c=!1;yf(Bf,c),Bf=null}function jp(c,d){Hr&&ml!==null&&d>q0&&(Bf=c)}var Qd=null;function fy(c){{var d=c.tag;if(d!==j&&d!==k&&d!==F&&d!==ae&&d!==ve&&d!==ue)return;var D=qt(c.type)||"ReactComponent";if(Qd!==null){if(Qd.has(D))return;Qd.add(D)}else Qd=new Set([D]);Ve(!1,"Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in %s.%s",d===k?"the componentWillUnmount method":"a useEffect cleanup function",Cr(c))}}var N1;if(X0){var cy=null;N1=function(c,d,D){var C=Gg(cy,d);try{return lp(c,d,D)}catch(z){if(z!==null&&typeof z=="object"&&typeof z.then=="function")throw z;if(yt(),_d(),nv(d),Gg(d,C),en&&d.mode&ni&&H2(d),pl(null,lp,null,c,d,D),tr()){var O=Qs();throw O}else throw z}}}else N1=lp;var Av=!1,Ov=!1;function dy(c){if(c.tag===k)switch(Nr){case"getChildContext":if(Ov)return;Ve(!1,"setState(...): Cannot call setState() inside getChildContext()"),Ov=!0;break;case"render":if(Av)return;Ve(!1,"Cannot update during an existing state transition (such as within `render`). Render methods should be a pure function of props and state."),Av=!0;break}}var qf={current:!1};function zp(c){vs===!0&&vl.current===!0&&qf.current!==!0&&Ve(!1,`It looks like you're using the wrong act() around your test interactions. +Be sure to use the matching version of act() corresponding to your renderer: + +// for react-dom: +import {act} from 'react-dom/test-utils'; +// ... +act(() => ...); + +// for react-test-renderer: +import TestRenderer from 'react-test-renderer'; +const {act} = TestRenderer; +// ... +act(() => ...);%s`,Cr(c))}function Mv(c){vs===!0&&(c.mode&mr)!==Ar&&vl.current===!1&&qf.current===!1&&Ve(!1,`An update to %s ran an effect, but was not wrapped in act(...). + +When testing, code that causes React state updates should be wrapped into act(...): + +act(() => { + /* fire events that update state */ +}); +/* assert on the output */ + +This ensures that you're testing the behavior the user would see in the browser. Learn more at https://fb.me/react-wrap-tests-with-act%s`,qt(c.type),Cr(c))}function py(c){vs===!0&&nr===yu&&vl.current===!1&&qf.current===!1&&Ve(!1,`An update to %s inside a test was not wrapped in act(...). + +When testing, code that causes React state updates should be wrapped into act(...): + +act(() => { + /* fire events that update state */ +}); +/* assert on the output */ + +This ensures that you're testing the behavior the user would see in the browser. Learn more at https://fb.me/react-wrap-tests-with-act%s`,qt(c.type),Cr(c))}var hy=py,Hp=!1;function vy(c){Hp===!1&&t.unstable_flushAllWithoutAsserting===void 0&&(c.mode&K||c.mode&ti?(Hp=!0,Ve(!1,`In Concurrent or Sync modes, the "scheduler" module needs to be mocked to guarantee consistent behaviour across tests and browsers. For example, with jest: +jest.mock('scheduler', () => require('scheduler/unstable_mock')); + +For more info, visit https://fb.me/react-mock-scheduler`)):eu===!0&&(Hp=!0,Ve(!1,`Starting from React v17, the "scheduler" module will need to be mocked to guarantee consistent behaviour across tests and browsers. For example, with jest: +jest.mock('scheduler', () => require('scheduler/unstable_mock')); + +For more info, visit https://fb.me/react-mock-scheduler`)))}var Zs=null;function my(c){{var d=Qt();if((c.mode&ti)!==xi&&(d===ei||d===Li))for(var D=c;D!==null;){var C=D.alternate;if(C!==null)switch(D.tag){case k:var O=C.updateQueue;if(O!==null)for(var z=O.firstUpdate;z!==null;){var G=z.priority;if(G===ei||G===Li){Zs===null?Zs=new Set([qt(D.type)]):Zs.add(qt(D.type));break}z=z.next}break;case F:case ae:case ue:if(D.memoizedState!==null&&D.memoizedState.baseUpdate!==null)for(var ne=D.memoizedState.baseUpdate;ne!==null;){var se=ne.priority;if(se===ei||se===Li){Zs===null?Zs=new Set([qt(D.type)]):Zs.add(qt(D.type));break}if(ne.next===D.memoizedState.baseUpdate)break;ne=ne.next}break;default:break}D=D.return}}}function p(){if(Zs!==null){var c=[];Zs.forEach(function(d){return c.push(d)}),Zs=null,c.length>0&&Ve(!1,`%s triggered a user-blocking update that suspended. + +The fix is to split the update into multiple parts: a user-blocking update to provide immediate feedback, and another update that triggers the bulk of the changes. + +Refer to the documentation for useTransition to learn how to implement this pattern.`,c.sort().join(", "))}}function m(c,d){return d*1e3+c.interactionThreadID}function R(c){!In||(Uf===null?Uf=[c]:Uf.push(c))}function I(c,d,D){if(!!In&&D.size>0){var C=c.pendingInteractionMap,O=C.get(d);O!=null?D.forEach(function(ne){O.has(ne)||ne.__count++,O.add(ne)}):(C.set(d,new Set(D)),D.forEach(function(ne){ne.__count++}));var z=N.__subscriberRef.current;if(z!==null){var G=m(c,d);z.onWorkScheduled(D,G)}}}function W(c,d){!In||I(c,d,N.__interactionsRef.current)}function te(c,d){if(!!In){var D=new Set;if(c.pendingInteractionMap.forEach(function(z,G){G>=d&&z.forEach(function(ne){return D.add(ne)})}),c.memoizedInteractions=D,D.size>0){var C=N.__subscriberRef.current;if(C!==null){var O=m(c,d);try{C.onWorkStarted(D,O)}catch(z){_n(Li,function(){throw z})}}}}}function pe(c,d){if(!!In){var D=c.firstPendingTime,C;try{if(C=N.__subscriberRef.current,C!==null&&c.memoizedInteractions.size>0){var O=m(c,d);C.onWorkStopped(c.memoizedInteractions,O)}}catch(G){_n(Li,function(){throw G})}finally{var z=c.pendingInteractionMap;z.forEach(function(G,ne){ne>D&&(z.delete(ne),G.forEach(function(se){if(se.__count--,C!==null&&se.__count===0)try{C.onInteractionScheduledWorkCompleted(se)}catch(Ue){_n(Li,function(){throw Ue})}}))})}}}var Ee=null,be=null,Dt=!1,Tt=typeof __REACT_DEVTOOLS_GLOBAL_HOOK__<"u";function Ot(c){if(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>"u")return!1;var d=__REACT_DEVTOOLS_GLOBAL_HOOK__;if(d.isDisabled)return!0;if(!d.supportsFiber)return Ve(!1,"The installed version of React DevTools is too old and will not work with the current version of React. Please update React DevTools. https://fb.me/react-devtools"),!0;try{var D=d.inject(c);Ee=function(C,O){try{var z=(C.current.effectTag&Kr)===Kr;if(en){var G=Nc(),ne=nd(G,O);d.onCommitFiberRoot(D,C,ne,z)}else d.onCommitFiberRoot(D,C,void 0,z)}catch(se){Dt||(Dt=!0,Ve(!1,"React DevTools encountered an error: %s",se))}},be=function(C){try{d.onCommitFiberUnmount(D,C)}catch(O){Dt||(Dt=!0,Ve(!1,"React DevTools encountered an error: %s",O))}}}catch(C){Ve(!1,"React DevTools encountered an error: %s.",C)}return!0}function on(c,d){typeof Ee=="function"&&Ee(c,d)}function Mn(c){typeof be=="function"&&be(c)}var rr;{rr=!1;try{var br=Object.preventExtensions({}),ar=new Map([[br,null]]),ri=new Set([br]);ar.set(0,0),ri.add(0)}catch{rr=!0}}var fi=1;function zl(c,d,D,C){this.tag=c,this.key=D,this.elementType=null,this.type=null,this.stateNode=null,this.return=null,this.child=null,this.sibling=null,this.index=0,this.ref=null,this.pendingProps=d,this.memoizedProps=null,this.updateQueue=null,this.memoizedState=null,this.dependencies=null,this.mode=C,this.effectTag=xi,this.nextEffect=null,this.firstEffect=null,this.lastEffect=null,this.expirationTime=ft,this.childExpirationTime=ft,this.alternate=null,en&&(this.actualDuration=Number.NaN,this.actualStartTime=Number.NaN,this.selfBaseDuration=Number.NaN,this.treeBaseDuration=Number.NaN,this.actualDuration=0,this.actualStartTime=-1,this.selfBaseDuration=0,this.treeBaseDuration=0),Hr&&(this._debugID=fi++,this._debugIsCurrentlyTiming=!1),this._debugSource=null,this._debugOwner=null,this._debugNeedsRemount=!1,this._debugHookTypes=null,!rr&&typeof Object.preventExtensions=="function"&&Object.preventExtensions(this)}var Zi=function(c,d,D,C){return new zl(c,d,D,C)};function so(c){var d=c.prototype;return!!(d&&d.isReactComponent)}function s0(c){return typeof c=="function"&&!so(c)&&c.defaultProps===void 0}function Os(c){if(typeof c=="function")return so(c)?k:F;if(c!=null){var d=c.$$typeof;if(d===On)return ae;if(d===Vt)return ve}return x}function Co(c,d,D){var C=c.alternate;C===null?(C=Zi(c.tag,d,c.key,c.mode),C.elementType=c.elementType,C.type=c.type,C.stateNode=c.stateNode,C._debugID=c._debugID,C._debugSource=c._debugSource,C._debugOwner=c._debugOwner,C._debugHookTypes=c._debugHookTypes,C.alternate=c,c.alternate=C):(C.pendingProps=d,C.effectTag=xi,C.nextEffect=null,C.firstEffect=null,C.lastEffect=null,en&&(C.actualDuration=0,C.actualStartTime=-1)),C.childExpirationTime=c.childExpirationTime,C.expirationTime=c.expirationTime,C.child=c.child,C.memoizedProps=c.memoizedProps,C.memoizedState=c.memoizedState,C.updateQueue=c.updateQueue;var O=c.dependencies;switch(C.dependencies=O===null?null:{expirationTime:O.expirationTime,firstContext:O.firstContext,responders:O.responders},C.sibling=c.sibling,C.index=c.index,C.ref=c.ref,en&&(C.selfBaseDuration=c.selfBaseDuration,C.treeBaseDuration=c.treeBaseDuration),C._debugNeedsRemount=c._debugNeedsRemount,C.tag){case x:case F:case ue:C.type=n0(c.type);break;case k:C.type=j0(c.type);break;case ae:C.type=Df(c.type);break;default:break}return C}function kv(c,d){c.effectTag&=vi,c.nextEffect=null,c.firstEffect=null,c.lastEffect=null;var D=c.alternate;if(D===null)c.childExpirationTime=ft,c.expirationTime=d,c.child=null,c.memoizedProps=null,c.memoizedState=null,c.updateQueue=null,c.dependencies=null,en&&(c.selfBaseDuration=0,c.treeBaseDuration=0);else{c.childExpirationTime=D.childExpirationTime,c.expirationTime=D.expirationTime,c.child=D.child,c.memoizedProps=D.memoizedProps,c.memoizedState=D.memoizedState,c.updateQueue=D.updateQueue;var C=D.dependencies;c.dependencies=C===null?null:{expirationTime:C.expirationTime,firstContext:C.firstContext,responders:C.responders},en&&(c.selfBaseDuration=D.selfBaseDuration,c.treeBaseDuration=D.treeBaseDuration)}return c}function F4(c){var d;return c===O0?d=ti|K|mr:c===B0?d=K|mr:d=Ar,en&&Tt&&(d|=ni),Zi(j,null,null,d)}function yy(c,d,D,C,O,z){var G,ne=x,se=c;if(typeof c=="function")so(c)?(ne=k,se=j0(se)):se=n0(se);else if(typeof c=="string")ne=V;else{e:switch(c){case le:return nf(D.children,O,z,d);case an:ne=me,O|=ti|K|mr;break;case He:ne=me,O|=mr;break;case dt:return I4(D,O,z,d);case lr:return b4(D,O,z,d);case ln:return B4(D,O,z,d);default:{if(typeof c=="object"&&c!==null)switch(c.$$typeof){case At:ne=ge;break e;case nn:ne=De;break e;case On:ne=ae,se=Df(se);break e;case Vt:ne=ve;break e;case Er:ne=Ae,se=null;break e;case S:if(Wt)return Vg(c,D,O,z,d);break;case Xn:if(Ru)return P4(c,D,O,z,d)}var Ue="";{(c===void 0||typeof c=="object"&&c!==null&&Object.keys(c).length===0)&&(Ue+=" You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.");var Xe=C?qt(C.type):null;Xe&&(Ue+=` + +Check the render method of \``+Xe+"`.")}throw Error("Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: "+(c==null?c:typeof c)+"."+Ue)}}}return G=Zi(ne,D,d,O),G.elementType=c,G.type=se,G.expirationTime=z,G}function gy(c,d,D){var C=null;C=c._owner;var O=c.type,z=c.key,G=c.props,ne=yy(O,z,G,C,d,D);return ne._debugSource=c._source,ne._debugOwner=c._owner,ne}function nf(c,d,D,C){var O=Zi(y,c,C,d);return O.expirationTime=D,O}function Vg(c,d,D,C,O){var z=Zi(_t,d,O,D);return z.elementType=c,z.type=c,z.expirationTime=C,z}function P4(c,d,D,C,O){var z=Zi(Qe,d,O,D);return z.type=c,z.elementType=c,z.expirationTime=C,z}function I4(c,d,D,C){(typeof c.id!="string"||typeof c.onRender!="function")&&Ve(!1,'Profiler must specify an "id" string and "onRender" function as props');var O=Zi(we,c,C,d|ni);return O.elementType=dt,O.type=dt,O.expirationTime=D,O}function b4(c,d,D,C){var O=Zi(he,c,C,d);return O.type=lr,O.elementType=lr,O.expirationTime=D,O}function B4(c,d,D,C){var O=Zi(gt,c,C,d);return O.type=ln,O.elementType=ln,O.expirationTime=D,O}function _y(c,d,D){var C=Zi(re,c,null,d);return C.expirationTime=D,C}function U4(){var c=Zi(V,null,null,Ar);return c.elementType="DELETED",c.type="DELETED",c}function j4(c){var d=Zi(We,null,null,Ar);return d.stateNode=c,d}function Ey(c,d,D){var C=c.children!==null?c.children:[],O=Zi(q,C,c.key,d);return O.expirationTime=D,O.stateNode={containerInfo:c.containerInfo,pendingChildren:null,implementation:c.implementation},O}function Gg(c,d){return c===null&&(c=Zi(x,null,null,Ar)),c.tag=d.tag,c.key=d.key,c.elementType=d.elementType,c.type=d.type,c.stateNode=d.stateNode,c.return=d.return,c.child=d.child,c.sibling=d.sibling,c.index=d.index,c.ref=d.ref,c.pendingProps=d.pendingProps,c.memoizedProps=d.memoizedProps,c.updateQueue=d.updateQueue,c.memoizedState=d.memoizedState,c.dependencies=d.dependencies,c.mode=d.mode,c.effectTag=d.effectTag,c.nextEffect=d.nextEffect,c.firstEffect=d.firstEffect,c.lastEffect=d.lastEffect,c.expirationTime=d.expirationTime,c.childExpirationTime=d.childExpirationTime,c.alternate=d.alternate,en&&(c.actualDuration=d.actualDuration,c.actualStartTime=d.actualStartTime,c.selfBaseDuration=d.selfBaseDuration,c.treeBaseDuration=d.treeBaseDuration),c._debugID=d._debugID,c._debugSource=d._debugSource,c._debugOwner=d._debugOwner,c._debugIsCurrentlyTiming=d._debugIsCurrentlyTiming,c._debugNeedsRemount=d._debugNeedsRemount,c._debugHookTypes=d._debugHookTypes,c}function z4(c,d,D){this.tag=d,this.current=null,this.containerInfo=c,this.pendingChildren=null,this.pingCache=null,this.finishedExpirationTime=ft,this.finishedWork=null,this.timeoutHandle=nl,this.context=null,this.pendingContext=null,this.hydrate=D,this.callbackNode=null,this.callbackPriority=_0,this.firstPendingTime=ft,this.firstSuspendedTime=ft,this.lastSuspendedTime=ft,this.nextKnownPendingLevel=ft,this.lastPingedTime=ft,this.lastExpiredTime=ft,In&&(this.interactionThreadID=N.unstable_getThreadID(),this.memoizedInteractions=new Set,this.pendingInteractionMap=new Map),Yi&&(this.hydrationCallbacks=null)}function H4(c,d,D,C){var O=new z4(c,d,D);Yi&&(O.hydrationCallbacks=C);var z=F4(d);return O.current=z,z.stateNode=O,O}function Yg(c,d){var D=c.firstSuspendedTime,C=c.lastSuspendedTime;return D!==ft&&D>=d&&C<=d}function Wf(c,d){var D=c.firstSuspendedTime,C=c.lastSuspendedTime;Dd||D===ft)&&(c.lastSuspendedTime=d),d<=c.lastPingedTime&&(c.lastPingedTime=ft),d<=c.lastExpiredTime&&(c.lastExpiredTime=ft)}function Kg(c,d){var D=c.firstPendingTime;d>D&&(c.firstPendingTime=d);var C=c.firstSuspendedTime;C!==ft&&(d>=C?c.firstSuspendedTime=c.lastSuspendedTime=c.nextKnownPendingLevel=ft:d>=c.lastSuspendedTime&&(c.lastSuspendedTime=d+1),d>c.nextKnownPendingLevel&&(c.nextKnownPendingLevel=d))}function q4(c,d,D){c.firstPendingTime=D,d<=c.lastSuspendedTime?c.firstSuspendedTime=c.lastSuspendedTime=c.nextKnownPendingLevel=ft:d<=c.firstSuspendedTime&&(c.firstSuspendedTime=d-1),d<=c.lastPingedTime&&(c.lastPingedTime=ft),d<=c.lastExpiredTime&&(c.lastExpiredTime=ft)}function qp(c,d){var D=c.lastExpiredTime;(D===ft||D>d)&&(c.lastExpiredTime=d)}var W4={debugTool:null},Nv=W4,Dy,wy;Dy=!1,wy={};function V4(c){if(!c)return xn;var d=Pt(c),D=xl(d);if(d.tag===k){var C=d.type;if(Xi(C))return A0(d,C,D)}return D}function Sy(c){var d=Pt(c);if(d===void 0)throw typeof c.render=="function"?Error("Unable to find node on an unmounted component."):Error("Argument appears to not be a ReactComponent. Keys: "+Object.keys(c));var D=I0(d);return D===null?null:D.stateNode}function G4(c,d){{var D=Pt(c);if(D===void 0)throw typeof c.render=="function"?Error("Unable to find node on an unmounted component."):Error("Argument appears to not be a ReactComponent. Keys: "+Object.keys(c));var C=I0(D);if(C===null)return null;if(C.mode&mr){var O=qt(D.type)||"Component";wy[O]||(wy[O]=!0,D.mode&mr?Ve(!1,"%s is deprecated in StrictMode. %s was passed an instance of %s which is inside StrictMode. Instead, add a ref directly to the element you want to reference. Learn more about using refs safely here: https://fb.me/react-strict-mode-find-node%s",d,d,O,Cr(C)):Ve(!1,"%s is deprecated in StrictMode. %s was passed an instance of %s which renders StrictMode children. Instead, add a ref directly to the element you want to reference. Learn more about using refs safely here: https://fb.me/react-strict-mode-find-node%s",d,d,O,Cr(C)))}return C.stateNode}return Sy(c)}function Y4(c,d,D,C){return H4(c,d,D,C)}function Xg(c,d,D,C){var O=d.current,z=jl();typeof jest<"u"&&(vy(O),zp(O));var G=_o(),ne=jf(z,O,G);Nv.debugTool&&(O.alternate===null?Nv.debugTool.onMountContainer(d):c===null?Nv.debugTool.onUnmountContainer(d):Nv.debugTool.onUpdateContainer(d));var se=V4(D);d.context===null?d.context=se:d.pendingContext=se,Nr==="render"&&Rn!==null&&!Dy&&(Dy=!0,Ve(!1,`Render methods should be a pure function of props and state; triggering nested component updates from render is not allowed. If necessary, trigger nested updates in componentDidUpdate. + +Check the render method of %s.`,qt(Rn.type)||"Unknown"));var Ue=Tu(ne,G);return Ue.payload={element:c},C=C===void 0?null:C,C!==null&&(typeof C!="function"&&Ve(!1,"render(...): Expected the last optional `callback` argument to be a function. Instead received: %s.",C),Ue.callback=C),Va(O,Ue),yl(O,ne),ne}function K4(c){var d=c.current;if(!d.child)return null;switch(d.child.tag){case V:return Lo(d.child.stateNode);default:return d.child.stateNode}}function X4(c){switch(c.tag){case j:var d=c.stateNode;d.hydrate&&Gm(d,d.firstPendingTime);break;case he:Rp(function(){return yl(c,Un)});var D=Ua(jl());Lv(c,D);break}}function Qg(c,d){var D=c.memoizedState;D!==null&&D.dehydrated!==null&&D.retryTime=d.length)return C;var O=d[D],z=Array.isArray(c)?c.slice():f({},c);return z[O]=xy(c[O],d,D+1,C),z},n_=function(c,d,D){return xy(c,d,0,D)};Zg=function(c,d,D,C){for(var O=c.memoizedState;O!==null&&d>0;)O=O.next,d--;if(O!==null){var z=n_(O.memoizedState,D,C);O.memoizedState=z,O.baseState=z,c.memoizedProps=f({},c.memoizedProps),yl(c,Un)}},$g=function(c,d,D){c.pendingProps=n_(c.memoizedProps,d,D),c.alternate&&(c.alternate.pendingProps=c.pendingProps),yl(c,Un)},e_=function(c){yl(c,Un)},t_=function(c){Cy=c}}function $4(c){var d=c.findFiberByHostInstance,D=it.ReactCurrentDispatcher;return Ot(f({},c,{overrideHookState:Zg,overrideProps:$g,setSuspenseHandler:t_,scheduleUpdate:e_,currentDispatcherRef:D,findHostInstanceByFiber:function(C){var O=I0(C);return O===null?null:O.stateNode},findFiberByHostInstance:function(C){return d?d(C):null},findHostInstancesForRefresh:ud,scheduleRefresh:Ol,scheduleRoot:Ts,setRefreshHandler:qa,getCurrentFiber:function(){return Rn}}))}var r_=Object.freeze({createContainer:Y4,updateContainer:Xg,batchedEventUpdates:Qm,batchedUpdates:Xm,unbatchedUpdates:Jm,deferredUpdates:Ym,syncUpdates:pv,discreteUpdates:hv,flushDiscreteUpdates:dv,flushControlled:Zm,flushSync:Rp,flushPassiveEffects:tf,IsThisRendererActing:qf,getPublicRootInstance:K4,attemptSynchronousHydration:X4,attemptUserBlockingHydration:Q4,attemptContinuousHydration:Ty,attemptHydrationAtCurrentPriority:J4,findHostInstance:Sy,findHostInstanceWithWarning:G4,findHostInstanceWithNoPortals:Z4,shouldSuspend:Jg,injectIntoDevTools:$4}),eE=r_.default||r_;Yy.exports=eE;var tE=Yy.exports;return Yy.exports=o,tE})});var YS=nt((DH,mD)=>{"use strict";process.env.NODE_ENV==="production"?mD.exports=HS():mD.exports=GS()});var XS=nt((wH,KS)=>{"use strict";var EP={ALIGN_COUNT:8,ALIGN_AUTO:0,ALIGN_FLEX_START:1,ALIGN_CENTER:2,ALIGN_FLEX_END:3,ALIGN_STRETCH:4,ALIGN_BASELINE:5,ALIGN_SPACE_BETWEEN:6,ALIGN_SPACE_AROUND:7,DIMENSION_COUNT:2,DIMENSION_WIDTH:0,DIMENSION_HEIGHT:1,DIRECTION_COUNT:3,DIRECTION_INHERIT:0,DIRECTION_LTR:1,DIRECTION_RTL:2,DISPLAY_COUNT:2,DISPLAY_FLEX:0,DISPLAY_NONE:1,EDGE_COUNT:9,EDGE_LEFT:0,EDGE_TOP:1,EDGE_RIGHT:2,EDGE_BOTTOM:3,EDGE_START:4,EDGE_END:5,EDGE_HORIZONTAL:6,EDGE_VERTICAL:7,EDGE_ALL:8,EXPERIMENTAL_FEATURE_COUNT:1,EXPERIMENTAL_FEATURE_WEB_FLEX_BASIS:0,FLEX_DIRECTION_COUNT:4,FLEX_DIRECTION_COLUMN:0,FLEX_DIRECTION_COLUMN_REVERSE:1,FLEX_DIRECTION_ROW:2,FLEX_DIRECTION_ROW_REVERSE:3,JUSTIFY_COUNT:6,JUSTIFY_FLEX_START:0,JUSTIFY_CENTER:1,JUSTIFY_FLEX_END:2,JUSTIFY_SPACE_BETWEEN:3,JUSTIFY_SPACE_AROUND:4,JUSTIFY_SPACE_EVENLY:5,LOG_LEVEL_COUNT:6,LOG_LEVEL_ERROR:0,LOG_LEVEL_WARN:1,LOG_LEVEL_INFO:2,LOG_LEVEL_DEBUG:3,LOG_LEVEL_VERBOSE:4,LOG_LEVEL_FATAL:5,MEASURE_MODE_COUNT:3,MEASURE_MODE_UNDEFINED:0,MEASURE_MODE_EXACTLY:1,MEASURE_MODE_AT_MOST:2,NODE_TYPE_COUNT:2,NODE_TYPE_DEFAULT:0,NODE_TYPE_TEXT:1,OVERFLOW_COUNT:3,OVERFLOW_VISIBLE:0,OVERFLOW_HIDDEN:1,OVERFLOW_SCROLL:2,POSITION_TYPE_COUNT:2,POSITION_TYPE_RELATIVE:0,POSITION_TYPE_ABSOLUTE:1,PRINT_OPTIONS_COUNT:3,PRINT_OPTIONS_LAYOUT:1,PRINT_OPTIONS_STYLE:2,PRINT_OPTIONS_CHILDREN:4,UNIT_COUNT:4,UNIT_UNDEFINED:0,UNIT_POINT:1,UNIT_PERCENT:2,UNIT_AUTO:3,WRAP_COUNT:3,WRAP_NO_WRAP:0,WRAP_WRAP:1,WRAP_WRAP_REVERSE:2};KS.exports=EP});var $S=nt((SH,ZS)=>{"use strict";var DP=Object.assign||function(o){for(var l=1;l"}}]),o}(),QS=function(){H_(o,null,[{key:"fromJS",value:function(f){var h=f.width,E=f.height;return new o(h,E)}}]);function o(l,f){gD(this,o),this.width=l,this.height=f}return H_(o,[{key:"fromJS",value:function(f){f(this.width,this.height)}},{key:"toString",value:function(){return""}}]),o}(),JS=function(){function o(l,f){gD(this,o),this.unit=l,this.value=f}return H_(o,[{key:"fromJS",value:function(f){f(this.unit,this.value)}},{key:"toString",value:function(){switch(this.unit){case tc.UNIT_POINT:return String(this.value);case tc.UNIT_PERCENT:return this.value+"%";case tc.UNIT_AUTO:return"auto";default:return this.value+"?"}}},{key:"valueOf",value:function(){return this.value}}]),o}();ZS.exports=function(o,l){function f(N,F,k){var x=N[F];N[F]=function(){for(var j=arguments.length,q=Array(j),V=0;V1?q-1:0),re=1;re1&&arguments[1]!==void 0?arguments[1]:NaN,k=arguments.length>2&&arguments[2]!==void 0?arguments[2]:NaN,x=arguments.length>3&&arguments[3]!==void 0?arguments[3]:tc.DIRECTION_LTR;return N.call(this,F,k,x)}),DP({Config:l.Config,Node:l.Node,Layout:o("Layout",wP),Size:o("Size",QS),Value:o("Value",JS),getInstanceCount:function(){return l.getInstanceCount.apply(l,arguments)}},tc)}});var eT=nt((exports,module)=>{(function(o,l){typeof define=="function"&&define.amd?define([],function(){return l}):typeof module=="object"&&module.exports?module.exports=l:(o.nbind=o.nbind||{}).init=l})(exports,function(Module,cb){typeof Module=="function"&&(cb=Module,Module={}),Module.onRuntimeInitialized=function(o,l){return function(){o&&o.apply(this,arguments);try{Module.ccall("nbind_init")}catch(f){l(f);return}l(null,{bind:Module._nbind_value,reflect:Module.NBind.reflect,queryType:Module.NBind.queryType,toggleLightGC:Module.toggleLightGC,lib:Module})}}(Module.onRuntimeInitialized,cb);var Module;Module||(Module=(typeof Module<"u"?Module:null)||{});var moduleOverrides={};for(var key in Module)Module.hasOwnProperty(key)&&(moduleOverrides[key]=Module[key]);var ENVIRONMENT_IS_WEB=!1,ENVIRONMENT_IS_WORKER=!1,ENVIRONMENT_IS_NODE=!1,ENVIRONMENT_IS_SHELL=!1;if(Module.ENVIRONMENT)if(Module.ENVIRONMENT==="WEB")ENVIRONMENT_IS_WEB=!0;else if(Module.ENVIRONMENT==="WORKER")ENVIRONMENT_IS_WORKER=!0;else if(Module.ENVIRONMENT==="NODE")ENVIRONMENT_IS_NODE=!0;else if(Module.ENVIRONMENT==="SHELL")ENVIRONMENT_IS_SHELL=!0;else throw new Error("The provided Module['ENVIRONMENT'] value is not valid. It must be one of: WEB|WORKER|NODE|SHELL.");else ENVIRONMENT_IS_WEB=typeof window=="object",ENVIRONMENT_IS_WORKER=typeof importScripts=="function",ENVIRONMENT_IS_NODE=typeof process=="object"&&typeof hi=="function"&&!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_WORKER,ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;if(ENVIRONMENT_IS_NODE){Module.print||(Module.print=console.log),Module.printErr||(Module.printErr=console.warn);var nodeFS,nodePath;Module.read=function(l,f){nodeFS||(nodeFS={}("")),nodePath||(nodePath={}("")),l=nodePath.normalize(l);var h=nodeFS.readFileSync(l);return f?h:h.toString()},Module.readBinary=function(l){var f=Module.read(l,!0);return f.buffer||(f=new Uint8Array(f)),assert(f.buffer),f},Module.load=function(l){globalEval(read(l))},Module.thisProgram||(process.argv.length>1?Module.thisProgram=process.argv[1].replace(/\\/g,"/"):Module.thisProgram="unknown-program"),Module.arguments=process.argv.slice(2),typeof module<"u"&&(module.exports=Module),Module.inspect=function(){return"[Emscripten Module object]"}}else if(ENVIRONMENT_IS_SHELL)Module.print||(Module.print=print),typeof printErr<"u"&&(Module.printErr=printErr),typeof read<"u"?Module.read=read:Module.read=function(){throw"no read() available"},Module.readBinary=function(l){if(typeof readbuffer=="function")return new Uint8Array(readbuffer(l));var f=read(l,"binary");return assert(typeof f=="object"),f},typeof scriptArgs<"u"?Module.arguments=scriptArgs:typeof arguments<"u"&&(Module.arguments=arguments),typeof quit=="function"&&(Module.quit=function(o,l){quit(o)});else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(Module.read=function(l){var f=new XMLHttpRequest;return f.open("GET",l,!1),f.send(null),f.responseText},ENVIRONMENT_IS_WORKER&&(Module.readBinary=function(l){var f=new XMLHttpRequest;return f.open("GET",l,!1),f.responseType="arraybuffer",f.send(null),new Uint8Array(f.response)}),Module.readAsync=function(l,f,h){var E=new XMLHttpRequest;E.open("GET",l,!0),E.responseType="arraybuffer",E.onload=function(){E.status==200||E.status==0&&E.response?f(E.response):h()},E.onerror=h,E.send(null)},typeof arguments<"u"&&(Module.arguments=arguments),typeof console<"u")Module.print||(Module.print=function(l){console.log(l)}),Module.printErr||(Module.printErr=function(l){console.warn(l)});else{var TRY_USE_DUMP=!1;Module.print||(Module.print=TRY_USE_DUMP&&typeof dump<"u"?function(o){dump(o)}:function(o){})}ENVIRONMENT_IS_WORKER&&(Module.load=importScripts),typeof Module.setWindowTitle>"u"&&(Module.setWindowTitle=function(o){document.title=o})}else throw"Unknown runtime environment. Where are we?";function globalEval(o){eval.call(null,o)}!Module.load&&Module.read&&(Module.load=function(l){globalEval(Module.read(l))}),Module.print||(Module.print=function(){}),Module.printErr||(Module.printErr=Module.print),Module.arguments||(Module.arguments=[]),Module.thisProgram||(Module.thisProgram="./this.program"),Module.quit||(Module.quit=function(o,l){throw l}),Module.print=Module.print,Module.printErr=Module.printErr,Module.preRun=[],Module.postRun=[];for(var key in moduleOverrides)moduleOverrides.hasOwnProperty(key)&&(Module[key]=moduleOverrides[key]);moduleOverrides=void 0;var Runtime={setTempRet0:function(o){return tempRet0=o,o},getTempRet0:function(){return tempRet0},stackSave:function(){return STACKTOP},stackRestore:function(o){STACKTOP=o},getNativeTypeSize:function(o){switch(o){case"i1":case"i8":return 1;case"i16":return 2;case"i32":return 4;case"i64":return 8;case"float":return 4;case"double":return 8;default:{if(o[o.length-1]==="*")return Runtime.QUANTUM_SIZE;if(o[0]==="i"){var l=parseInt(o.substr(1));return assert(l%8===0),l/8}else return 0}}},getNativeFieldSize:function(o){return Math.max(Runtime.getNativeTypeSize(o),Runtime.QUANTUM_SIZE)},STACK_ALIGN:16,prepVararg:function(o,l){return l==="double"||l==="i64"?o&7&&(assert((o&7)===4),o+=4):assert((o&3)===0),o},getAlignSize:function(o,l,f){return!f&&(o=="i64"||o=="double")?8:o?Math.min(l||(o?Runtime.getNativeFieldSize(o):0),Runtime.QUANTUM_SIZE):Math.min(l,8)},dynCall:function(o,l,f){return f&&f.length?Module["dynCall_"+o].apply(null,[l].concat(f)):Module["dynCall_"+o].call(null,l)},functionPointers:[],addFunction:function(o){for(var l=0;l>2],f=(l+o+15|0)&-16;if(HEAP32[DYNAMICTOP_PTR>>2]=f,f>=TOTAL_MEMORY){var h=enlargeMemory();if(!h)return HEAP32[DYNAMICTOP_PTR>>2]=l,0}return l},alignMemory:function(o,l){var f=o=Math.ceil(o/(l||16))*(l||16);return f},makeBigInt:function(o,l,f){var h=f?+(o>>>0)+ +(l>>>0)*4294967296:+(o>>>0)+ +(l|0)*4294967296;return h},GLOBAL_BASE:8,QUANTUM_SIZE:4,__dummy__:0};Module.Runtime=Runtime;var ABORT=0,EXITSTATUS=0;function assert(o,l){o||abort("Assertion failed: "+l)}function getCFunc(ident){var func=Module["_"+ident];if(!func)try{func=eval("_"+ident)}catch(o){}return assert(func,"Cannot call unknown function "+ident+" (perhaps LLVM optimizations or closure removed it?)"),func}var cwrap,ccall;(function(){var JSfuncs={stackSave:function(){Runtime.stackSave()},stackRestore:function(){Runtime.stackRestore()},arrayToC:function(o){var l=Runtime.stackAlloc(o.length);return writeArrayToMemory(o,l),l},stringToC:function(o){var l=0;if(o!=null&&o!==0){var f=(o.length<<2)+1;l=Runtime.stackAlloc(f),stringToUTF8(o,l,f)}return l}},toC={string:JSfuncs.stringToC,array:JSfuncs.arrayToC};ccall=function(l,f,h,E,t){var N=getCFunc(l),F=[],k=0;if(E)for(var x=0;x>0]=l;break;case"i8":HEAP8[o>>0]=l;break;case"i16":HEAP16[o>>1]=l;break;case"i32":HEAP32[o>>2]=l;break;case"i64":tempI64=[l>>>0,(tempDouble=l,+Math_abs(tempDouble)>=1?tempDouble>0?(Math_min(+Math_floor(tempDouble/4294967296),4294967295)|0)>>>0:~~+Math_ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[o>>2]=tempI64[0],HEAP32[o+4>>2]=tempI64[1];break;case"float":HEAPF32[o>>2]=l;break;case"double":HEAPF64[o>>3]=l;break;default:abort("invalid type for setValue: "+f)}}Module.setValue=setValue;function getValue(o,l,f){switch(l=l||"i8",l.charAt(l.length-1)==="*"&&(l="i32"),l){case"i1":return HEAP8[o>>0];case"i8":return HEAP8[o>>0];case"i16":return HEAP16[o>>1];case"i32":return HEAP32[o>>2];case"i64":return HEAP32[o>>2];case"float":return HEAPF32[o>>2];case"double":return HEAPF64[o>>3];default:abort("invalid type for setValue: "+l)}return null}Module.getValue=getValue;var ALLOC_NORMAL=0,ALLOC_STACK=1,ALLOC_STATIC=2,ALLOC_DYNAMIC=3,ALLOC_NONE=4;Module.ALLOC_NORMAL=ALLOC_NORMAL,Module.ALLOC_STACK=ALLOC_STACK,Module.ALLOC_STATIC=ALLOC_STATIC,Module.ALLOC_DYNAMIC=ALLOC_DYNAMIC,Module.ALLOC_NONE=ALLOC_NONE;function allocate(o,l,f,h){var E,t;typeof o=="number"?(E=!0,t=o):(E=!1,t=o.length);var N=typeof l=="string"?l:null,F;if(f==ALLOC_NONE?F=h:F=[typeof _malloc=="function"?_malloc:Runtime.staticAlloc,Runtime.stackAlloc,Runtime.staticAlloc,Runtime.dynamicAlloc][f===void 0?ALLOC_STATIC:f](Math.max(t,N?1:l.length)),E){var h=F,k;for(assert((F&3)==0),k=F+(t&-4);h>2]=0;for(k=F+t;h>0]=0;return F}if(N==="i8")return o.subarray||o.slice?HEAPU8.set(o,F):HEAPU8.set(new Uint8Array(o),F),F;for(var x=0,j,q,V;x>0],f|=h,!(h==0&&!l||(E++,l&&E==l)););l||(l=E);var t="";if(f<128){for(var N=1024,F;l>0;)F=String.fromCharCode.apply(String,HEAPU8.subarray(o,o+Math.min(l,N))),t=t?t+F:F,o+=N,l-=N;return t}return Module.UTF8ToString(o)}Module.Pointer_stringify=Pointer_stringify;function AsciiToString(o){for(var l="";;){var f=HEAP8[o++>>0];if(!f)return l;l+=String.fromCharCode(f)}}Module.AsciiToString=AsciiToString;function stringToAscii(o,l){return writeAsciiToMemory(o,l,!1)}Module.stringToAscii=stringToAscii;var UTF8Decoder=typeof TextDecoder<"u"?new TextDecoder("utf8"):void 0;function UTF8ArrayToString(o,l){for(var f=l;o[f];)++f;if(f-l>16&&o.subarray&&UTF8Decoder)return UTF8Decoder.decode(o.subarray(l,f));for(var h,E,t,N,F,k,x="";;){if(h=o[l++],!h)return x;if(!(h&128)){x+=String.fromCharCode(h);continue}if(E=o[l++]&63,(h&224)==192){x+=String.fromCharCode((h&31)<<6|E);continue}if(t=o[l++]&63,(h&240)==224?h=(h&15)<<12|E<<6|t:(N=o[l++]&63,(h&248)==240?h=(h&7)<<18|E<<12|t<<6|N:(F=o[l++]&63,(h&252)==248?h=(h&3)<<24|E<<18|t<<12|N<<6|F:(k=o[l++]&63,h=(h&1)<<30|E<<24|t<<18|N<<12|F<<6|k))),h<65536)x+=String.fromCharCode(h);else{var j=h-65536;x+=String.fromCharCode(55296|j>>10,56320|j&1023)}}}Module.UTF8ArrayToString=UTF8ArrayToString;function UTF8ToString(o){return UTF8ArrayToString(HEAPU8,o)}Module.UTF8ToString=UTF8ToString;function stringToUTF8Array(o,l,f,h){if(!(h>0))return 0;for(var E=f,t=f+h-1,N=0;N=55296&&F<=57343&&(F=65536+((F&1023)<<10)|o.charCodeAt(++N)&1023),F<=127){if(f>=t)break;l[f++]=F}else if(F<=2047){if(f+1>=t)break;l[f++]=192|F>>6,l[f++]=128|F&63}else if(F<=65535){if(f+2>=t)break;l[f++]=224|F>>12,l[f++]=128|F>>6&63,l[f++]=128|F&63}else if(F<=2097151){if(f+3>=t)break;l[f++]=240|F>>18,l[f++]=128|F>>12&63,l[f++]=128|F>>6&63,l[f++]=128|F&63}else if(F<=67108863){if(f+4>=t)break;l[f++]=248|F>>24,l[f++]=128|F>>18&63,l[f++]=128|F>>12&63,l[f++]=128|F>>6&63,l[f++]=128|F&63}else{if(f+5>=t)break;l[f++]=252|F>>30,l[f++]=128|F>>24&63,l[f++]=128|F>>18&63,l[f++]=128|F>>12&63,l[f++]=128|F>>6&63,l[f++]=128|F&63}}return l[f]=0,f-E}Module.stringToUTF8Array=stringToUTF8Array;function stringToUTF8(o,l,f){return stringToUTF8Array(o,HEAPU8,l,f)}Module.stringToUTF8=stringToUTF8;function lengthBytesUTF8(o){for(var l=0,f=0;f=55296&&h<=57343&&(h=65536+((h&1023)<<10)|o.charCodeAt(++f)&1023),h<=127?++l:h<=2047?l+=2:h<=65535?l+=3:h<=2097151?l+=4:h<=67108863?l+=5:l+=6}return l}Module.lengthBytesUTF8=lengthBytesUTF8;var UTF16Decoder=typeof TextDecoder<"u"?new TextDecoder("utf-16le"):void 0;function demangle(o){var l=Module.___cxa_demangle||Module.__cxa_demangle;if(l){try{var f=o.substr(1),h=lengthBytesUTF8(f)+1,E=_malloc(h);stringToUTF8(f,E,h);var t=_malloc(4),N=l(E,0,0,t);if(getValue(t,"i32")===0&&N)return Pointer_stringify(N)}catch{}finally{E&&_free(E),t&&_free(t),N&&_free(N)}return o}return Runtime.warnOnce("warning: build with -s DEMANGLE_SUPPORT=1 to link in libcxxabi demangling"),o}function demangleAll(o){var l=/__Z[\w\d_]+/g;return o.replace(l,function(f){var h=demangle(f);return f===h?f:f+" ["+h+"]"})}function jsStackTrace(){var o=new Error;if(!o.stack){try{throw new Error(0)}catch(l){o=l}if(!o.stack)return"(no stack trace available)"}return o.stack.toString()}function stackTrace(){var o=jsStackTrace();return Module.extraStackTrace&&(o+=` +`+Module.extraStackTrace()),demangleAll(o)}Module.stackTrace=stackTrace;var HEAP,buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferViews(){Module.HEAP8=HEAP8=new Int8Array(buffer),Module.HEAP16=HEAP16=new Int16Array(buffer),Module.HEAP32=HEAP32=new Int32Array(buffer),Module.HEAPU8=HEAPU8=new Uint8Array(buffer),Module.HEAPU16=HEAPU16=new Uint16Array(buffer),Module.HEAPU32=HEAPU32=new Uint32Array(buffer),Module.HEAPF32=HEAPF32=new Float32Array(buffer),Module.HEAPF64=HEAPF64=new Float64Array(buffer)}var STATIC_BASE,STATICTOP,staticSealed,STACK_BASE,STACKTOP,STACK_MAX,DYNAMIC_BASE,DYNAMICTOP_PTR;STATIC_BASE=STATICTOP=STACK_BASE=STACKTOP=STACK_MAX=DYNAMIC_BASE=DYNAMICTOP_PTR=0,staticSealed=!1;function abortOnCannotGrowMemory(){abort("Cannot enlarge memory arrays. Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value "+TOTAL_MEMORY+", (2) compile with -s ALLOW_MEMORY_GROWTH=1 which allows increasing the size at runtime but prevents some optimizations, (3) set Module.TOTAL_MEMORY to a higher value before the program runs, or (4) if you want malloc to return NULL (0) instead of this abort, compile with -s ABORTING_MALLOC=0 ")}function enlargeMemory(){abortOnCannotGrowMemory()}var TOTAL_STACK=Module.TOTAL_STACK||5242880,TOTAL_MEMORY=Module.TOTAL_MEMORY||134217728;TOTAL_MEMORY0;){var l=o.shift();if(typeof l=="function"){l();continue}var f=l.func;typeof f=="number"?l.arg===void 0?Module.dynCall_v(f):Module.dynCall_vi(f,l.arg):f(l.arg===void 0?null:l.arg)}}var __ATPRERUN__=[],__ATINIT__=[],__ATMAIN__=[],__ATEXIT__=[],__ATPOSTRUN__=[],runtimeInitialized=!1,runtimeExited=!1;function preRun(){if(Module.preRun)for(typeof Module.preRun=="function"&&(Module.preRun=[Module.preRun]);Module.preRun.length;)addOnPreRun(Module.preRun.shift());callRuntimeCallbacks(__ATPRERUN__)}function ensureInitRuntime(){runtimeInitialized||(runtimeInitialized=!0,callRuntimeCallbacks(__ATINIT__))}function preMain(){callRuntimeCallbacks(__ATMAIN__)}function exitRuntime(){callRuntimeCallbacks(__ATEXIT__),runtimeExited=!0}function postRun(){if(Module.postRun)for(typeof Module.postRun=="function"&&(Module.postRun=[Module.postRun]);Module.postRun.length;)addOnPostRun(Module.postRun.shift());callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(o){__ATPRERUN__.unshift(o)}Module.addOnPreRun=addOnPreRun;function addOnInit(o){__ATINIT__.unshift(o)}Module.addOnInit=addOnInit;function addOnPreMain(o){__ATMAIN__.unshift(o)}Module.addOnPreMain=addOnPreMain;function addOnExit(o){__ATEXIT__.unshift(o)}Module.addOnExit=addOnExit;function addOnPostRun(o){__ATPOSTRUN__.unshift(o)}Module.addOnPostRun=addOnPostRun;function intArrayFromString(o,l,f){var h=f>0?f:lengthBytesUTF8(o)+1,E=new Array(h),t=stringToUTF8Array(o,E,0,E.length);return l&&(E.length=t),E}Module.intArrayFromString=intArrayFromString;function intArrayToString(o){for(var l=[],f=0;f255&&(h&=255),l.push(String.fromCharCode(h))}return l.join("")}Module.intArrayToString=intArrayToString;function writeStringToMemory(o,l,f){Runtime.warnOnce("writeStringToMemory is deprecated and should not be called! Use stringToUTF8() instead!");var h,E;f&&(E=l+lengthBytesUTF8(o),h=HEAP8[E]),stringToUTF8(o,l,1/0),f&&(HEAP8[E]=h)}Module.writeStringToMemory=writeStringToMemory;function writeArrayToMemory(o,l){HEAP8.set(o,l)}Module.writeArrayToMemory=writeArrayToMemory;function writeAsciiToMemory(o,l,f){for(var h=0;h>0]=o.charCodeAt(h);f||(HEAP8[l>>0]=0)}if(Module.writeAsciiToMemory=writeAsciiToMemory,(!Math.imul||Math.imul(4294967295,5)!==-5)&&(Math.imul=function o(l,f){var h=l>>>16,E=l&65535,t=f>>>16,N=f&65535;return E*N+(h*N+E*t<<16)|0}),Math.imul=Math.imul,!Math.fround){var froundBuffer=new Float32Array(1);Math.fround=function(o){return froundBuffer[0]=o,froundBuffer[0]}}Math.fround=Math.fround,Math.clz32||(Math.clz32=function(o){o=o>>>0;for(var l=0;l<32;l++)if(o&1<<31-l)return l;return 32}),Math.clz32=Math.clz32,Math.trunc||(Math.trunc=function(o){return o<0?Math.ceil(o):Math.floor(o)}),Math.trunc=Math.trunc;var Math_abs=Math.abs,Math_cos=Math.cos,Math_sin=Math.sin,Math_tan=Math.tan,Math_acos=Math.acos,Math_asin=Math.asin,Math_atan=Math.atan,Math_atan2=Math.atan2,Math_exp=Math.exp,Math_log=Math.log,Math_sqrt=Math.sqrt,Math_ceil=Math.ceil,Math_floor=Math.floor,Math_pow=Math.pow,Math_imul=Math.imul,Math_fround=Math.fround,Math_round=Math.round,Math_min=Math.min,Math_clz32=Math.clz32,Math_trunc=Math.trunc,runDependencies=0,runDependencyWatcher=null,dependenciesFulfilled=null;function getUniqueRunDependency(o){return o}function addRunDependency(o){runDependencies++,Module.monitorRunDependencies&&Module.monitorRunDependencies(runDependencies)}Module.addRunDependency=addRunDependency;function removeRunDependency(o){if(runDependencies--,Module.monitorRunDependencies&&Module.monitorRunDependencies(runDependencies),runDependencies==0&&(runDependencyWatcher!==null&&(clearInterval(runDependencyWatcher),runDependencyWatcher=null),dependenciesFulfilled)){var l=dependenciesFulfilled;dependenciesFulfilled=null,l()}}Module.removeRunDependency=removeRunDependency,Module.preloadedImages={},Module.preloadedAudios={};var ASM_CONSTS=[function(o,l,f,h,E,t,N,F){return _nbind.callbackSignatureList[o].apply(this,arguments)}];function _emscripten_asm_const_iiiiiiii(o,l,f,h,E,t,N,F){return ASM_CONSTS[o](l,f,h,E,t,N,F)}function _emscripten_asm_const_iiiii(o,l,f,h,E){return ASM_CONSTS[o](l,f,h,E)}function _emscripten_asm_const_iiidddddd(o,l,f,h,E,t,N,F,k){return ASM_CONSTS[o](l,f,h,E,t,N,F,k)}function _emscripten_asm_const_iiididi(o,l,f,h,E,t,N){return ASM_CONSTS[o](l,f,h,E,t,N)}function _emscripten_asm_const_iiii(o,l,f,h){return ASM_CONSTS[o](l,f,h)}function _emscripten_asm_const_iiiid(o,l,f,h,E){return ASM_CONSTS[o](l,f,h,E)}function _emscripten_asm_const_iiiiii(o,l,f,h,E,t){return ASM_CONSTS[o](l,f,h,E,t)}STATIC_BASE=Runtime.GLOBAL_BASE,STATICTOP=STATIC_BASE+12800,__ATINIT__.push({func:function(){__GLOBAL__sub_I_Yoga_cpp()}},{func:function(){__GLOBAL__sub_I_nbind_cc()}},{func:function(){__GLOBAL__sub_I_common_cc()}},{func:function(){__GLOBAL__sub_I_Binding_cc()}}),allocate([0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,127,0,0,192,127,0,0,192,127,0,0,192,127,3,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,3,0,0,0,0,0,192,127,3,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,127,0,0,192,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,127,0,0,0,0,0,0,0,0,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,127,0,0,192,127,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,0,0,128,191,0,0,128,191,0,0,192,127,0,0,0,0,0,0,0,0,0,0,128,63,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,3,0,0,0,1,0,0,0,2,0,0,0,0,0,0,0,190,12,0,0,200,12,0,0,208,12,0,0,216,12,0,0,230,12,0,0,242,12,0,0,1,0,0,0,3,0,0,0,0,0,0,0,2,0,0,0,0,0,192,127,3,0,0,0,180,45,0,0,181,45,0,0,182,45,0,0,181,45,0,0,182,45,0,0,0,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0,3,0,0,0,1,0,0,0,4,0,0,0,183,45,0,0,181,45,0,0,181,45,0,0,181,45,0,0,181,45,0,0,181,45,0,0,181,45,0,0,184,45,0,0,185,45,0,0,181,45,0,0,181,45,0,0,182,45,0,0,186,45,0,0,185,45,0,0,148,4,0,0,3,0,0,0,187,45,0,0,164,4,0,0,188,45,0,0,2,0,0,0,189,45,0,0,164,4,0,0,188,45,0,0,185,45,0,0,164,4,0,0,185,45,0,0,164,4,0,0,188,45,0,0,181,45,0,0,182,45,0,0,181,45,0,0,0,0,0,0,0,0,0,0,1,0,0,0,5,0,0,0,6,0,0,0,1,0,0,0,7,0,0,0,183,45,0,0,182,45,0,0,181,45,0,0,190,45,0,0,190,45,0,0,182,45,0,0,182,45,0,0,185,45,0,0,181,45,0,0,185,45,0,0,182,45,0,0,181,45,0,0,185,45,0,0,182,45,0,0,185,45,0,0,48,5,0,0,3,0,0,0,56,5,0,0,1,0,0,0,189,45,0,0,185,45,0,0,164,4,0,0,76,5,0,0,2,0,0,0,191,45,0,0,186,45,0,0,182,45,0,0,185,45,0,0,192,45,0,0,185,45,0,0,182,45,0,0,186,45,0,0,185,45,0,0,76,5,0,0,76,5,0,0,136,5,0,0,182,45,0,0,181,45,0,0,2,0,0,0,190,45,0,0,136,5,0,0,56,19,0,0,156,5,0,0,2,0,0,0,184,45,0,0,0,0,0,0,0,0,0,0,1,0,0,0,8,0,0,0,9,0,0,0,1,0,0,0,10,0,0,0,204,5,0,0,181,45,0,0,181,45,0,0,2,0,0,0,180,45,0,0,204,5,0,0,2,0,0,0,195,45,0,0,236,5,0,0,97,19,0,0,198,45,0,0,211,45,0,0,212,45,0,0,213,45,0,0,214,45,0,0,215,45,0,0,188,45,0,0,182,45,0,0,216,45,0,0,217,45,0,0,218,45,0,0,219,45,0,0,192,45,0,0,181,45,0,0,0,0,0,0,185,45,0,0,110,19,0,0,186,45,0,0,115,19,0,0,221,45,0,0,120,19,0,0,148,4,0,0,132,19,0,0,96,6,0,0,145,19,0,0,222,45,0,0,164,19,0,0,223,45,0,0,173,19,0,0,0,0,0,0,3,0,0,0,104,6,0,0,1,0,0,0,187,45,0,0,0,0,0,0,0,0,0,0,1,0,0,0,11,0,0,0,12,0,0,0,1,0,0,0,13,0,0,0,185,45,0,0,224,45,0,0,164,6,0,0,188,45,0,0,172,6,0,0,180,6,0,0,2,0,0,0,188,6,0,0,7,0,0,0,224,45,0,0,7,0,0,0,164,6,0,0,1,0,0,0,213,45,0,0,185,45,0,0,224,45,0,0,172,6,0,0,185,45,0,0,224,45,0,0,164,6,0,0,185,45,0,0,224,45,0,0,211,45,0,0,211,45,0,0,222,45,0,0,211,45,0,0,224,45,0,0,222,45,0,0,211,45,0,0,224,45,0,0,172,6,0,0,222,45,0,0,211,45,0,0,224,45,0,0,188,45,0,0,222,45,0,0,211,45,0,0,40,7,0,0,188,45,0,0,2,0,0,0,224,45,0,0,185,45,0,0,188,45,0,0,188,45,0,0,188,45,0,0,188,45,0,0,222,45,0,0,224,45,0,0,148,4,0,0,185,45,0,0,148,4,0,0,148,4,0,0,148,4,0,0,148,4,0,0,148,4,0,0,185,45,0,0,164,6,0,0,148,4,0,0,0,0,0,0,0,0,0,0,1,0,0,0,14,0,0,0,15,0,0,0,1,0,0,0,16,0,0,0,148,7,0,0,2,0,0,0,225,45,0,0,183,45,0,0,188,45,0,0,168,7,0,0,5,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0,234,45,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,148,45,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,28,9,0,0,5,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,2,0,0,0,242,45,0,0,0,4,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67,111,117,108,100,32,110,111,116,32,97,108,108,111,99,97,116,101,32,109,101,109,111,114,121,32,102,111,114,32,110,111,100,101,0,67,97,110,110,111,116,32,114,101,115,101,116,32,97,32,110,111,100,101,32,119,104,105,99,104,32,115,116,105,108,108,32,104,97,115,32,99,104,105,108,100,114,101,110,32,97,116,116,97,99,104,101,100,0,67,97,110,110,111,116,32,114,101,115,101,116,32,97,32,110,111,100,101,32,115,116,105,108,108,32,97,116,116,97,99,104,101,100,32,116,111,32,97,32,112,97,114,101,110,116,0,67,111,117,108,100,32,110,111,116,32,97,108,108,111,99,97,116,101,32,109,101,109,111,114,121,32,102,111,114,32,99,111,110,102,105,103,0,67,97,110,110,111,116,32,115,101,116,32,109,101,97,115,117,114,101,32,102,117,110,99,116,105,111,110,58,32,78,111,100,101,115,32,119,105,116,104,32,109,101,97,115,117,114,101,32,102,117,110,99,116,105,111,110,115,32,99,97,110,110,111,116,32,104,97,118,101,32,99,104,105,108,100,114,101,110,46,0,67,104,105,108,100,32,97,108,114,101,97,100,121,32,104,97,115,32,97,32,112,97,114,101,110,116,44,32,105,116,32,109,117,115,116,32,98,101,32,114,101,109,111,118,101,100,32,102,105,114,115,116,46,0,67,97,110,110,111,116,32,97,100,100,32,99,104,105,108,100,58,32,78,111,100,101,115,32,119,105,116,104,32,109,101,97,115,117,114,101,32,102,117,110,99,116,105,111,110,115,32,99,97,110,110,111,116,32,104,97,118,101,32,99,104,105,108,100,114,101,110,46,0,79,110,108,121,32,108,101,97,102,32,110,111,100,101,115,32,119,105,116,104,32,99,117,115,116,111,109,32,109,101,97,115,117,114,101,32,102,117,110,99,116,105,111,110,115,115,104,111,117,108,100,32,109,97,110,117,97,108,108,121,32,109,97,114,107,32,116,104,101,109,115,101,108,118,101,115,32,97,115,32,100,105,114,116,121,0,67,97,110,110,111,116,32,103,101,116,32,108,97,121,111,117,116,32,112,114,111,112,101,114,116,105,101,115,32,111,102,32,109,117,108,116,105,45,101,100,103,101,32,115,104,111,114,116,104,97,110,100,115,0,37,115,37,100,46,123,91,115,107,105,112,112,101,100,93,32,0,119,109,58,32,37,115,44,32,104,109,58,32,37,115,44,32,97,119,58,32,37,102,32,97,104,58,32,37,102,32,61,62,32,100,58,32,40,37,102,44,32,37,102,41,32,37,115,10,0,37,115,37,100,46,123,37,115,0,42,0,119,109,58,32,37,115,44,32,104,109,58,32,37,115,44,32,97,119,58,32,37,102,32,97,104,58,32,37,102,32,37,115,10,0,37,115,37,100,46,125,37,115,0,119,109,58,32,37,115,44,32,104,109,58,32,37,115,44,32,100,58,32,40,37,102,44,32,37,102,41,32,37,115,10,0,79,117,116,32,111,102,32,99,97,99,104,101,32,101,110,116,114,105,101,115,33,10,0,83,99,97,108,101,32,102,97,99,116,111,114,32,115,104,111,117,108,100,32,110,111,116,32,98,101,32,108,101,115,115,32,116,104,97,110,32,122,101,114,111,0,105,110,105,116,105,97,108,0,37,115,10,0,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,0,85,78,68,69,70,73,78,69,68,0,69,88,65,67,84,76,89,0,65,84,95,77,79,83,84,0,76,65,89,95,85,78,68,69,70,73,78,69,68,0,76,65,89,95,69,88,65,67,84,76,89,0,76,65,89,95,65,84,95,77,79,83,84,0,97,118,97,105,108,97,98,108,101,87,105,100,116,104,32,105,115,32,105,110,100,101,102,105,110,105,116,101,32,115,111,32,119,105,100,116,104,77,101,97,115,117,114,101,77,111,100,101,32,109,117,115,116,32,98,101,32,89,71,77,101,97,115,117,114,101,77,111,100,101,85,110,100,101,102,105,110,101,100,0,97,118,97,105,108,97,98,108,101,72,101,105,103,104,116,32,105,115,32,105,110,100,101,102,105,110,105,116,101,32,115,111,32,104,101,105,103,104,116,77,101,97,115,117,114,101,77,111,100,101,32,109,117,115,116,32,98,101,32,89,71,77,101,97,115,117,114,101,77,111,100,101,85,110,100,101,102,105,110,101,100,0,102,108,101,120,0,115,116,114,101,116,99,104,0,109,117,108,116,105,108,105,110,101,45,115,116,114,101,116,99,104,0,69,120,112,101,99,116,101,100,32,110,111,100,101,32,116,111,32,104,97,118,101,32,99,117,115,116,111,109,32,109,101,97,115,117,114,101,32,102,117,110,99,116,105,111,110,0,109,101,97,115,117,114,101,0,69,120,112,101,99,116,32,99,117,115,116,111,109,32,98,97,115,101,108,105,110,101,32,102,117,110,99,116,105,111,110,32,116,111,32,110,111,116,32,114,101,116,117,114,110,32,78,97,78,0,97,98,115,45,109,101,97,115,117,114,101,0,97,98,115,45,108,97,121,111,117,116,0,78,111,100,101,0,99,114,101,97,116,101,68,101,102,97,117,108,116,0,99,114,101,97,116,101,87,105,116,104,67,111,110,102,105,103,0,100,101,115,116,114,111,121,0,114,101,115,101,116,0,99,111,112,121,83,116,121,108,101,0,115,101,116,80,111,115,105,116,105,111,110,84,121,112,101,0,115,101,116,80,111,115,105,116,105,111,110,0,115,101,116,80,111,115,105,116,105,111,110,80,101,114,99,101,110,116,0,115,101,116,65,108,105,103,110,67,111,110,116,101,110,116,0,115,101,116,65,108,105,103,110,73,116,101,109,115,0,115,101,116,65,108,105,103,110,83,101,108,102,0,115,101,116,70,108,101,120,68,105,114,101,99,116,105,111,110,0,115,101,116,70,108,101,120,87,114,97,112,0,115,101,116,74,117,115,116,105,102,121,67,111,110,116,101,110,116,0,115,101,116,77,97,114,103,105,110,0,115,101,116,77,97,114,103,105,110,80,101,114,99,101,110,116,0,115,101,116,77,97,114,103,105,110,65,117,116,111,0,115,101,116,79,118,101,114,102,108,111,119,0,115,101,116,68,105,115,112,108,97,121,0,115,101,116,70,108,101,120,0,115,101,116,70,108,101,120,66,97,115,105,115,0,115,101,116,70,108,101,120,66,97,115,105,115,80,101,114,99,101,110,116,0,115,101,116,70,108,101,120,71,114,111,119,0,115,101,116,70,108,101,120,83,104,114,105,110,107,0,115,101,116,87,105,100,116,104,0,115,101,116,87,105,100,116,104,80,101,114,99,101,110,116,0,115,101,116,87,105,100,116,104,65,117,116,111,0,115,101,116,72,101,105,103,104,116,0,115,101,116,72,101,105,103,104,116,80,101,114,99,101,110,116,0,115,101,116,72,101,105,103,104,116,65,117,116,111,0,115,101,116,77,105,110,87,105,100,116,104,0,115,101,116,77,105,110,87,105,100,116,104,80,101,114,99,101,110,116,0,115,101,116,77,105,110,72,101,105,103,104,116,0,115,101,116,77,105,110,72,101,105,103,104,116,80,101,114,99,101,110,116,0,115,101,116,77,97,120,87,105,100,116,104,0,115,101,116,77,97,120,87,105,100,116,104,80,101,114,99,101,110,116,0,115,101,116,77,97,120,72,101,105,103,104,116,0,115,101,116,77,97,120,72,101,105,103,104,116,80,101,114,99,101,110,116,0,115,101,116,65,115,112,101,99,116,82,97,116,105,111,0,115,101,116,66,111,114,100,101,114,0,115,101,116,80,97,100,100,105,110,103,0,115,101,116,80,97,100,100,105,110,103,80,101,114,99,101,110,116,0,103,101,116,80,111,115,105,116,105,111,110,84,121,112,101,0,103,101,116,80,111,115,105,116,105,111,110,0,103,101,116,65,108,105,103,110,67,111,110,116,101,110,116,0,103,101,116,65,108,105,103,110,73,116,101,109,115,0,103,101,116,65,108,105,103,110,83,101,108,102,0,103,101,116,70,108,101,120,68,105,114,101,99,116,105,111,110,0,103,101,116,70,108,101,120,87,114,97,112,0,103,101,116,74,117,115,116,105,102,121,67,111,110,116,101,110,116,0,103,101,116,77,97,114,103,105,110,0,103,101,116,70,108,101,120,66,97,115,105,115,0,103,101,116,70,108,101,120,71,114,111,119,0,103,101,116,70,108,101,120,83,104,114,105,110,107,0,103,101,116,87,105,100,116,104,0,103,101,116,72,101,105,103,104,116,0,103,101,116,77,105,110,87,105,100,116,104,0,103,101,116,77,105,110,72,101,105,103,104,116,0,103,101,116,77,97,120,87,105,100,116,104,0,103,101,116,77,97,120,72,101,105,103,104,116,0,103,101,116,65,115,112,101,99,116,82,97,116,105,111,0,103,101,116,66,111,114,100,101,114,0,103,101,116,79,118,101,114,102,108,111,119,0,103,101,116,68,105,115,112,108,97,121,0,103,101,116,80,97,100,100,105,110,103,0,105,110,115,101,114,116,67,104,105,108,100,0,114,101,109,111,118,101,67,104,105,108,100,0,103,101,116,67,104,105,108,100,67,111,117,110,116,0,103,101,116,80,97,114,101,110,116,0,103,101,116,67,104,105,108,100,0,115,101,116,77,101,97,115,117,114,101,70,117,110,99,0,117,110,115,101,116,77,101,97,115,117,114,101,70,117,110,99,0,109,97,114,107,68,105,114,116,121,0,105,115,68,105,114,116,121,0,99,97,108,99,117,108,97,116,101,76,97,121,111,117,116,0,103,101,116,67,111,109,112,117,116,101,100,76,101,102,116,0,103,101,116,67,111,109,112,117,116,101,100,82,105,103,104,116,0,103,101,116,67,111,109,112,117,116,101,100,84,111,112,0,103,101,116,67,111,109,112,117,116,101,100,66,111,116,116,111,109,0,103,101,116,67,111,109,112,117,116,101,100,87,105,100,116,104,0,103,101,116,67,111,109,112,117,116,101,100,72,101,105,103,104,116,0,103,101,116,67,111,109,112,117,116,101,100,76,97,121,111,117,116,0,103,101,116,67,111,109,112,117,116,101,100,77,97,114,103,105,110,0,103,101,116,67,111,109,112,117,116,101,100,66,111,114,100,101,114,0,103,101,116,67,111,109,112,117,116,101,100,80,97,100,100,105,110,103,0,67,111,110,102,105,103,0,99,114,101,97,116,101,0,115,101,116,69,120,112,101,114,105,109,101,110,116,97,108,70,101,97,116,117,114,101,69,110,97,98,108,101,100,0,115,101,116,80,111,105,110,116,83,99,97,108,101,70,97,99,116,111,114,0,105,115,69,120,112,101,114,105,109,101,110,116,97,108,70,101,97,116,117,114,101,69,110,97,98,108,101,100,0,86,97,108,117,101,0,76,97,121,111,117,116,0,83,105,122,101,0,103,101,116,73,110,115,116,97,110,99,101,67,111,117,110,116,0,73,110,116,54,52,0,1,1,1,2,2,4,4,4,4,8,8,4,8,118,111,105,100,0,98,111,111,108,0,115,116,100,58,58,115,116,114,105,110,103,0,99,98,70,117,110,99,116,105,111,110,32,38,0,99,111,110,115,116,32,99,98,70,117,110,99,116,105,111,110,32,38,0,69,120,116,101,114,110,97,108,0,66,117,102,102,101,114,0,78,66,105,110,100,73,68,0,78,66,105,110,100,0,98,105,110,100,95,118,97,108,117,101,0,114,101,102,108,101,99,116,0,113,117,101,114,121,84,121,112,101,0,108,97,108,108,111,99,0,108,114,101,115,101,116,0,123,114,101,116,117,114,110,40,95,110,98,105,110,100,46,99,97,108,108,98,97,99,107,83,105,103,110,97,116,117,114,101,76,105,115,116,91,36,48,93,46,97,112,112,108,121,40,116,104,105,115,44,97,114,103,117,109,101,110,116,115,41,41,59,125,0,95,110,98,105,110,100,95,110,101,119,0,17,0,10,0,17,17,17,0,0,0,0,5,0,0,0,0,0,0,9,0,0,0,0,11,0,0,0,0,0,0,0,0,17,0,15,10,17,17,17,3,10,7,0,1,19,9,11,11,0,0,9,6,11,0,0,11,0,6,17,0,0,0,17,17,17,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,17,0,10,10,17,17,17,0,10,0,0,2,0,9,11,0,0,0,9,0,11,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,12,0,0,0,0,9,12,0,0,0,0,0,12,0,0,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,0,0,0,0,0,13,0,0,0,4,13,0,0,0,0,9,14,0,0,0,0,0,14,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,15,0,0,0,0,15,0,0,0,0,9,16,0,0,0,0,0,16,0,0,16,0,0,18,0,0,0,18,18,18,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,0,0,0,18,18,18,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,10,0,0,0,0,10,0,0,0,0,9,11,0,0,0,0,0,11,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,12,0,0,0,0,9,12,0,0,0,0,0,12,0,0,12,0,0,45,43,32,32,32,48,88,48,120,0,40,110,117,108,108,41,0,45,48,88,43,48,88,32,48,88,45,48,120,43,48,120,32,48,120,0,105,110,102,0,73,78,70,0,110,97,110,0,78,65,78,0,48,49,50,51,52,53,54,55,56,57,65,66,67,68,69,70,46,0,84,33,34,25,13,1,2,3,17,75,28,12,16,4,11,29,18,30,39,104,110,111,112,113,98,32,5,6,15,19,20,21,26,8,22,7,40,36,23,24,9,10,14,27,31,37,35,131,130,125,38,42,43,60,61,62,63,67,71,74,77,88,89,90,91,92,93,94,95,96,97,99,100,101,102,103,105,106,107,108,114,115,116,121,122,123,124,0,73,108,108,101,103,97,108,32,98,121,116,101,32,115,101,113,117,101,110,99,101,0,68,111,109,97,105,110,32,101,114,114,111,114,0,82,101,115,117,108,116,32,110,111,116,32,114,101,112,114,101,115,101,110,116,97,98,108,101,0,78,111,116,32,97,32,116,116,121,0,80,101,114,109,105,115,115,105,111,110,32,100,101,110,105,101,100,0,79,112,101,114,97,116,105,111,110,32,110,111,116,32,112,101,114,109,105,116,116,101,100,0,78,111,32,115,117,99,104,32,102,105,108,101,32,111,114,32,100,105,114,101,99,116,111,114,121,0,78,111,32,115,117,99,104,32,112,114,111,99,101,115,115,0,70,105,108,101,32,101,120,105,115,116,115,0,86,97,108,117,101,32,116,111,111,32,108,97,114,103,101,32,102,111,114,32,100,97,116,97,32,116,121,112,101,0,78,111,32,115,112,97,99,101,32,108,101,102,116,32,111,110,32,100,101,118,105,99,101,0,79,117,116,32,111,102,32,109,101,109,111,114,121,0,82,101,115,111,117,114,99,101,32,98,117,115,121,0,73,110,116,101,114,114,117,112,116,101,100,32,115,121,115,116,101,109,32,99,97,108,108,0,82,101,115,111,117,114,99,101,32,116,101,109,112,111,114,97,114,105,108,121,32,117,110,97,118,97,105,108,97,98,108,101,0,73,110,118,97,108,105,100,32,115,101,101,107,0,67,114,111,115,115,45,100,101,118,105,99,101,32,108,105,110,107,0,82,101,97,100,45,111,110,108,121,32,102,105,108,101,32,115,121,115,116,101,109,0,68,105,114,101,99,116,111,114,121,32,110,111,116,32,101,109,112,116,121,0,67,111,110,110,101,99,116,105,111,110,32,114,101,115,101,116,32,98,121,32,112,101,101,114,0,79,112,101,114,97,116,105,111,110,32,116,105,109,101,100,32,111,117,116,0,67,111,110,110,101,99,116,105,111,110,32,114,101,102,117,115,101,100,0,72,111,115,116,32,105,115,32,100,111,119,110,0,72,111,115,116,32,105,115,32,117,110,114,101,97,99,104,97,98,108,101,0,65,100,100,114,101,115,115,32,105,110,32,117,115,101,0,66,114,111,107,101,110,32,112,105,112,101,0,73,47,79,32,101,114,114,111,114,0,78,111,32,115,117,99,104,32,100,101,118,105,99,101,32,111,114,32,97,100,100,114,101,115,115,0,66,108,111,99,107,32,100,101,118,105,99,101,32,114,101,113,117,105,114,101,100,0,78,111,32,115,117,99,104,32,100,101,118,105,99,101,0,78,111,116,32,97,32,100,105,114,101,99,116,111,114,121,0,73,115,32,97,32,100,105,114,101,99,116,111,114,121,0,84,101,120,116,32,102,105,108,101,32,98,117,115,121,0,69,120,101,99,32,102,111,114,109,97,116,32,101,114,114,111,114,0,73,110,118,97,108,105,100,32,97,114,103,117,109,101,110,116,0,65,114,103,117,109,101,110,116,32,108,105,115,116,32,116,111,111,32,108,111,110,103,0,83,121,109,98,111,108,105,99,32,108,105,110,107,32,108,111,111,112,0,70,105,108,101,110,97,109,101,32,116,111,111,32,108,111,110,103,0,84,111,111,32,109,97,110,121,32,111,112,101,110,32,102,105,108,101,115,32,105,110,32,115,121,115,116,101,109,0,78,111,32,102,105,108,101,32,100,101,115,99,114,105,112,116,111,114,115,32,97,118,97,105,108,97,98,108,101,0,66,97,100,32,102,105,108,101,32,100,101,115,99,114,105,112,116,111,114,0,78,111,32,99,104,105,108,100,32,112,114,111,99,101,115,115,0,66,97,100,32,97,100,100,114,101,115,115,0,70,105,108,101,32,116,111,111,32,108,97,114,103,101,0,84,111,111,32,109,97,110,121,32,108,105,110,107,115,0,78,111,32,108,111,99,107,115,32,97,118,97,105,108,97,98,108,101,0,82,101,115,111,117,114,99,101,32,100,101,97,100,108,111,99,107,32,119,111,117,108,100,32,111,99,99,117,114,0,83,116,97,116,101,32,110,111,116,32,114,101,99,111,118,101,114,97,98,108,101,0,80,114,101,118,105,111,117,115,32,111,119,110,101,114,32,100,105,101,100,0,79,112,101,114,97,116,105,111,110,32,99,97,110,99,101,108,101,100,0,70,117,110,99,116,105,111,110,32,110,111,116,32,105,109,112,108,101,109,101,110,116,101,100,0,78,111,32,109,101,115,115,97,103,101,32,111,102,32,100,101,115,105,114,101,100,32,116,121,112,101,0,73,100,101,110,116,105,102,105,101,114,32,114,101,109,111,118,101,100,0,68,101,118,105,99,101,32,110,111,116,32,97,32,115,116,114,101,97,109,0,78,111,32,100,97,116,97,32,97,118,97,105,108,97,98,108,101,0,68,101,118,105,99,101,32,116,105,109,101,111,117,116,0,79,117,116,32,111,102,32,115,116,114,101,97,109,115,32,114,101,115,111,117,114,99,101,115,0,76,105,110,107,32,104,97,115,32,98,101,101,110,32,115,101,118,101,114,101,100,0,80,114,111,116,111,99,111,108,32,101,114,114,111,114,0,66,97,100,32,109,101,115,115,97,103,101,0,70,105,108,101,32,100,101,115,99,114,105,112,116,111,114,32,105,110,32,98,97,100,32,115,116,97,116,101,0,78,111,116,32,97,32,115,111,99,107,101,116,0,68,101,115,116,105,110,97,116,105,111,110,32,97,100,100,114,101,115,115,32,114,101,113,117,105,114,101,100,0,77,101,115,115,97,103,101,32,116,111,111,32,108,97,114,103,101,0,80,114,111,116,111,99,111,108,32,119,114,111,110,103,32,116,121,112,101,32,102,111,114,32,115,111,99,107,101,116,0,80,114,111,116,111,99,111,108,32,110,111,116,32,97,118,97,105,108,97,98,108,101,0,80,114,111,116,111,99,111,108,32,110,111,116,32,115,117,112,112,111,114,116,101,100,0,83,111,99,107,101,116,32,116,121,112,101,32,110,111,116,32,115,117,112,112,111,114,116,101,100,0,78,111,116,32,115,117,112,112,111,114,116,101,100,0,80,114,111,116,111,99,111,108,32,102,97,109,105,108,121,32,110,111,116,32,115,117,112,112,111,114,116,101,100,0,65,100,100,114,101,115,115,32,102,97,109,105,108,121,32,110,111,116,32,115,117,112,112,111,114,116,101,100,32,98,121,32,112,114,111,116,111,99,111,108,0,65,100,100,114,101,115,115,32,110,111,116,32,97,118,97,105,108,97,98,108,101,0,78,101,116,119,111,114,107,32,105,115,32,100,111,119,110,0,78,101,116,119,111,114,107,32,117,110,114,101,97,99,104,97,98,108,101,0,67,111,110,110,101,99,116,105,111,110,32,114,101,115,101,116,32,98,121,32,110,101,116,119,111,114,107,0,67,111,110,110,101,99,116,105,111,110,32,97,98,111,114,116,101,100,0,78,111,32,98,117,102,102,101,114,32,115,112,97,99,101,32,97,118,97,105,108,97,98,108,101,0,83,111,99,107,101,116,32,105,115,32,99,111,110,110,101,99,116,101,100,0,83,111,99,107,101,116,32,110,111,116,32,99,111,110,110,101,99,116,101,100,0,67,97,110,110,111,116,32,115,101,110,100,32,97,102,116,101,114,32,115,111,99,107,101,116,32,115,104,117,116,100,111,119,110,0,79,112,101,114,97,116,105,111,110,32,97,108,114,101,97,100,121,32,105,110,32,112,114,111,103,114,101,115,115,0,79,112,101,114,97,116,105,111,110,32,105,110,32,112,114,111,103,114,101,115,115,0,83,116,97,108,101,32,102,105,108,101,32,104,97,110,100,108,101,0,82,101,109,111,116,101,32,73,47,79,32,101,114,114,111,114,0,81,117,111,116,97,32,101,120,99,101,101,100,101,100,0,78,111,32,109,101,100,105,117,109,32,102,111,117,110,100,0,87,114,111,110,103,32,109,101,100,105,117,109,32,116,121,112,101,0,78,111,32,101,114,114,111,114,32,105,110,102,111,114,109,97,116,105,111,110,0,0],"i8",ALLOC_NONE,Runtime.GLOBAL_BASE);var tempDoublePtr=STATICTOP;STATICTOP+=16;function _atexit(o,l){__ATEXIT__.unshift({func:o,arg:l})}function ___cxa_atexit(){return _atexit.apply(null,arguments)}function _abort(){Module.abort()}function __ZN8facebook4yoga14YGNodeToStringEPNSt3__212basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEP6YGNode14YGPrintOptionsj(){Module.printErr("missing function: _ZN8facebook4yoga14YGNodeToStringEPNSt3__212basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEP6YGNode14YGPrintOptionsj"),abort(-1)}function __decorate(o,l,f,h){var E=arguments.length,t=E<3?l:h===null?h=Object.getOwnPropertyDescriptor(l,f):h,N;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")t=Reflect.decorate(o,l,f,h);else for(var F=o.length-1;F>=0;F--)(N=o[F])&&(t=(E<3?N(t):E>3?N(l,f,t):N(l,f))||t);return E>3&&t&&Object.defineProperty(l,f,t),t}function _defineHidden(o){return function(l,f){Object.defineProperty(l,f,{configurable:!1,enumerable:!1,value:o,writable:!0})}}var _nbind={};function __nbind_free_external(o){_nbind.externalList[o].dereference(o)}function __nbind_reference_external(o){_nbind.externalList[o].reference()}function _llvm_stackrestore(o){var l=_llvm_stacksave,f=l.LLVM_SAVEDSTACKS[o];l.LLVM_SAVEDSTACKS.splice(o,1),Runtime.stackRestore(f)}function __nbind_register_pool(o,l,f,h){_nbind.Pool.pageSize=o,_nbind.Pool.usedPtr=l/4,_nbind.Pool.rootPtr=f,_nbind.Pool.pagePtr=h/4,HEAP32[l/4]=16909060,HEAP8[l]==1&&(_nbind.bigEndian=!0),HEAP32[l/4]=0,_nbind.makeTypeKindTbl=(t={},t[1024]=_nbind.PrimitiveType,t[64]=_nbind.Int64Type,t[2048]=_nbind.BindClass,t[3072]=_nbind.BindClassPtr,t[4096]=_nbind.SharedClassPtr,t[5120]=_nbind.ArrayType,t[6144]=_nbind.ArrayType,t[7168]=_nbind.CStringType,t[9216]=_nbind.CallbackType,t[10240]=_nbind.BindType,t),_nbind.makeTypeNameTbl={Buffer:_nbind.BufferType,External:_nbind.ExternalType,Int64:_nbind.Int64Type,_nbind_new:_nbind.CreateValueType,bool:_nbind.BooleanType,"cbFunction &":_nbind.CallbackType,"const cbFunction &":_nbind.CallbackType,"const std::string &":_nbind.StringType,"std::string":_nbind.StringType},Module.toggleLightGC=_nbind.toggleLightGC,_nbind.callUpcast=Module.dynCall_ii;var E=_nbind.makeType(_nbind.constructType,{flags:2048,id:0,name:""});E.proto=Module,_nbind.BindClass.list.push(E);var t}function _emscripten_set_main_loop_timing(o,l){if(Browser.mainLoop.timingMode=o,Browser.mainLoop.timingValue=l,!Browser.mainLoop.func)return 1;if(o==0)Browser.mainLoop.scheduler=function(){var N=Math.max(0,Browser.mainLoop.tickStartTime+l-_emscripten_get_now())|0;setTimeout(Browser.mainLoop.runner,N)},Browser.mainLoop.method="timeout";else if(o==1)Browser.mainLoop.scheduler=function(){Browser.requestAnimationFrame(Browser.mainLoop.runner)},Browser.mainLoop.method="rAF";else if(o==2){if(!window.setImmediate){let t=function(N){N.source===window&&N.data===h&&(N.stopPropagation(),f.shift()())};var E=t,f=[],h="setimmediate";window.addEventListener("message",t,!0),window.setImmediate=function(F){f.push(F),ENVIRONMENT_IS_WORKER?(Module.setImmediates===void 0&&(Module.setImmediates=[]),Module.setImmediates.push(F),window.postMessage({target:h})):window.postMessage(h,"*")}}Browser.mainLoop.scheduler=function(){window.setImmediate(Browser.mainLoop.runner)},Browser.mainLoop.method="immediate"}return 0}function _emscripten_get_now(){abort()}function _emscripten_set_main_loop(o,l,f,h,E){Module.noExitRuntime=!0,assert(!Browser.mainLoop.func,"emscripten_set_main_loop: there can only be one main loop function at once: call emscripten_cancel_main_loop to cancel the previous one before setting a new one with different parameters."),Browser.mainLoop.func=o,Browser.mainLoop.arg=h;var t;typeof h<"u"?t=function(){Module.dynCall_vi(o,h)}:t=function(){Module.dynCall_v(o)};var N=Browser.mainLoop.currentlyRunningMainloop;if(Browser.mainLoop.runner=function(){if(!ABORT){if(Browser.mainLoop.queue.length>0){var k=Date.now(),x=Browser.mainLoop.queue.shift();if(x.func(x.arg),Browser.mainLoop.remainingBlockers){var j=Browser.mainLoop.remainingBlockers,q=j%1==0?j-1:Math.floor(j);x.counted?Browser.mainLoop.remainingBlockers=q:(q=q+.5,Browser.mainLoop.remainingBlockers=(8*j+q)/9)}if(console.log('main loop blocker "'+x.name+'" took '+(Date.now()-k)+" ms"),Browser.mainLoop.updateStatus(),N1&&Browser.mainLoop.currentFrameNumber%Browser.mainLoop.timingValue!=0){Browser.mainLoop.scheduler();return}else Browser.mainLoop.timingMode==0&&(Browser.mainLoop.tickStartTime=_emscripten_get_now());Browser.mainLoop.method==="timeout"&&Module.ctx&&(Module.printErr("Looks like you are rendering without using requestAnimationFrame for the main loop. You should use 0 for the frame rate in emscripten_set_main_loop in order to use requestAnimationFrame, as that can greatly improve your frame rates!"),Browser.mainLoop.method=""),Browser.mainLoop.runIter(t),!(N0?_emscripten_set_main_loop_timing(0,1e3/l):_emscripten_set_main_loop_timing(1,1),Browser.mainLoop.scheduler()),f)throw"SimulateInfiniteLoop"}var Browser={mainLoop:{scheduler:null,method:"",currentlyRunningMainloop:0,func:null,arg:0,timingMode:0,timingValue:0,currentFrameNumber:0,queue:[],pause:function(){Browser.mainLoop.scheduler=null,Browser.mainLoop.currentlyRunningMainloop++},resume:function(){Browser.mainLoop.currentlyRunningMainloop++;var o=Browser.mainLoop.timingMode,l=Browser.mainLoop.timingValue,f=Browser.mainLoop.func;Browser.mainLoop.func=null,_emscripten_set_main_loop(f,0,!1,Browser.mainLoop.arg,!0),_emscripten_set_main_loop_timing(o,l),Browser.mainLoop.scheduler()},updateStatus:function(){if(Module.setStatus){var o=Module.statusMessage||"Please wait...",l=Browser.mainLoop.remainingBlockers,f=Browser.mainLoop.expectedBlockers;l?l"u"&&(console.log("warning: Browser does not support creating object URLs. Built-in browser image decoding will not be available."),Module.noImageDecoding=!0);var o={};o.canHandle=function(t){return!Module.noImageDecoding&&/\.(jpg|jpeg|png|bmp)$/i.test(t)},o.handle=function(t,N,F,k){var x=null;if(Browser.hasBlobConstructor)try{x=new Blob([t],{type:Browser.getMimetype(N)}),x.size!==t.length&&(x=new Blob([new Uint8Array(t).buffer],{type:Browser.getMimetype(N)}))}catch(re){Runtime.warnOnce("Blob constructor present but fails: "+re+"; falling back to blob builder")}if(!x){var j=new Browser.BlobBuilder;j.append(new Uint8Array(t).buffer),x=j.getBlob()}var q=Browser.URLObject.createObjectURL(x),V=new Image;V.onload=function(){assert(V.complete,"Image "+N+" could not be decoded");var y=document.createElement("canvas");y.width=V.width,y.height=V.height;var me=y.getContext("2d");me.drawImage(V,0,0),Module.preloadedImages[N]=y,Browser.URLObject.revokeObjectURL(q),F&&F(t)},V.onerror=function(y){console.log("Image "+q+" could not be decoded"),k&&k()},V.src=q},Module.preloadPlugins.push(o);var l={};l.canHandle=function(t){return!Module.noAudioDecoding&&t.substr(-4)in{".ogg":1,".wav":1,".mp3":1}},l.handle=function(t,N,F,k){var x=!1;function j(me){x||(x=!0,Module.preloadedAudios[N]=me,F&&F(t))}function q(){x||(x=!0,Module.preloadedAudios[N]=new Audio,k&&k())}if(Browser.hasBlobConstructor){try{var V=new Blob([t],{type:Browser.getMimetype(N)})}catch{return q()}var re=Browser.URLObject.createObjectURL(V),y=new Audio;y.addEventListener("canplaythrough",function(){j(y)},!1),y.onerror=function(De){if(x)return;console.log("warning: browser could not fully decode audio "+N+", trying slower base64 approach");function ge(ae){for(var we="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",he="=",ve="",ue=0,Ae=0,ze=0;ze=6;){var We=ue>>Ae-6&63;Ae-=6,ve+=we[We]}return Ae==2?(ve+=we[(ue&3)<<4],ve+=he+he):Ae==4&&(ve+=we[(ue&15)<<2],ve+=he),ve}y.src="data:audio/x-"+N.substr(-3)+";base64,"+ge(t),j(y)},y.src=re,Browser.safeSetTimeout(function(){j(y)},1e4)}else return q()},Module.preloadPlugins.push(l);function f(){Browser.pointerLock=document.pointerLockElement===Module.canvas||document.mozPointerLockElement===Module.canvas||document.webkitPointerLockElement===Module.canvas||document.msPointerLockElement===Module.canvas}var h=Module.canvas;h&&(h.requestPointerLock=h.requestPointerLock||h.mozRequestPointerLock||h.webkitRequestPointerLock||h.msRequestPointerLock||function(){},h.exitPointerLock=document.exitPointerLock||document.mozExitPointerLock||document.webkitExitPointerLock||document.msExitPointerLock||function(){},h.exitPointerLock=h.exitPointerLock.bind(document),document.addEventListener("pointerlockchange",f,!1),document.addEventListener("mozpointerlockchange",f,!1),document.addEventListener("webkitpointerlockchange",f,!1),document.addEventListener("mspointerlockchange",f,!1),Module.elementPointerLock&&h.addEventListener("click",function(E){!Browser.pointerLock&&Module.canvas.requestPointerLock&&(Module.canvas.requestPointerLock(),E.preventDefault())},!1))},createContext:function(o,l,f,h){if(l&&Module.ctx&&o==Module.canvas)return Module.ctx;var E,t;if(l){var N={antialias:!1,alpha:!1};if(h)for(var F in h)N[F]=h[F];t=GL.createContext(o,N),t&&(E=GL.getContext(t).GLctx)}else E=o.getContext("2d");return E?(f&&(l||assert(typeof GLctx>"u","cannot set in module if GLctx is used, but we are a non-GL context that would replace it"),Module.ctx=E,l&&GL.makeContextCurrent(t),Module.useWebGL=l,Browser.moduleContextCreatedCallbacks.forEach(function(k){k()}),Browser.init()),E):null},destroyContext:function(o,l,f){},fullscreenHandlersInstalled:!1,lockPointer:void 0,resizeCanvas:void 0,requestFullscreen:function(o,l,f){Browser.lockPointer=o,Browser.resizeCanvas=l,Browser.vrDevice=f,typeof Browser.lockPointer>"u"&&(Browser.lockPointer=!0),typeof Browser.resizeCanvas>"u"&&(Browser.resizeCanvas=!1),typeof Browser.vrDevice>"u"&&(Browser.vrDevice=null);var h=Module.canvas;function E(){Browser.isFullscreen=!1;var N=h.parentNode;(document.fullscreenElement||document.mozFullScreenElement||document.msFullscreenElement||document.webkitFullscreenElement||document.webkitCurrentFullScreenElement)===N?(h.exitFullscreen=document.exitFullscreen||document.cancelFullScreen||document.mozCancelFullScreen||document.msExitFullscreen||document.webkitCancelFullScreen||function(){},h.exitFullscreen=h.exitFullscreen.bind(document),Browser.lockPointer&&h.requestPointerLock(),Browser.isFullscreen=!0,Browser.resizeCanvas&&Browser.setFullscreenCanvasSize()):(N.parentNode.insertBefore(h,N),N.parentNode.removeChild(N),Browser.resizeCanvas&&Browser.setWindowedCanvasSize()),Module.onFullScreen&&Module.onFullScreen(Browser.isFullscreen),Module.onFullscreen&&Module.onFullscreen(Browser.isFullscreen),Browser.updateCanvasDimensions(h)}Browser.fullscreenHandlersInstalled||(Browser.fullscreenHandlersInstalled=!0,document.addEventListener("fullscreenchange",E,!1),document.addEventListener("mozfullscreenchange",E,!1),document.addEventListener("webkitfullscreenchange",E,!1),document.addEventListener("MSFullscreenChange",E,!1));var t=document.createElement("div");h.parentNode.insertBefore(t,h),t.appendChild(h),t.requestFullscreen=t.requestFullscreen||t.mozRequestFullScreen||t.msRequestFullscreen||(t.webkitRequestFullscreen?function(){t.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT)}:null)||(t.webkitRequestFullScreen?function(){t.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT)}:null),f?t.requestFullscreen({vrDisplay:f}):t.requestFullscreen()},requestFullScreen:function(o,l,f){return Module.printErr("Browser.requestFullScreen() is deprecated. Please call Browser.requestFullscreen instead."),Browser.requestFullScreen=function(h,E,t){return Browser.requestFullscreen(h,E,t)},Browser.requestFullscreen(o,l,f)},nextRAF:0,fakeRequestAnimationFrame:function(o){var l=Date.now();if(Browser.nextRAF===0)Browser.nextRAF=l+1e3/60;else for(;l+2>=Browser.nextRAF;)Browser.nextRAF+=1e3/60;var f=Math.max(Browser.nextRAF-l,0);setTimeout(o,f)},requestAnimationFrame:function o(l){typeof window>"u"?Browser.fakeRequestAnimationFrame(l):(window.requestAnimationFrame||(window.requestAnimationFrame=window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||window.msRequestAnimationFrame||window.oRequestAnimationFrame||Browser.fakeRequestAnimationFrame),window.requestAnimationFrame(l))},safeCallback:function(o){return function(){if(!ABORT)return o.apply(null,arguments)}},allowAsyncCallbacks:!0,queuedAsyncCallbacks:[],pauseAsyncCallbacks:function(){Browser.allowAsyncCallbacks=!1},resumeAsyncCallbacks:function(){if(Browser.allowAsyncCallbacks=!0,Browser.queuedAsyncCallbacks.length>0){var o=Browser.queuedAsyncCallbacks;Browser.queuedAsyncCallbacks=[],o.forEach(function(l){l()})}},safeRequestAnimationFrame:function(o){return Browser.requestAnimationFrame(function(){ABORT||(Browser.allowAsyncCallbacks?o():Browser.queuedAsyncCallbacks.push(o))})},safeSetTimeout:function(o,l){return Module.noExitRuntime=!0,setTimeout(function(){ABORT||(Browser.allowAsyncCallbacks?o():Browser.queuedAsyncCallbacks.push(o))},l)},safeSetInterval:function(o,l){return Module.noExitRuntime=!0,setInterval(function(){ABORT||Browser.allowAsyncCallbacks&&o()},l)},getMimetype:function(o){return{jpg:"image/jpeg",jpeg:"image/jpeg",png:"image/png",bmp:"image/bmp",ogg:"audio/ogg",wav:"audio/wav",mp3:"audio/mpeg"}[o.substr(o.lastIndexOf(".")+1)]},getUserMedia:function(o){window.getUserMedia||(window.getUserMedia=navigator.getUserMedia||navigator.mozGetUserMedia),window.getUserMedia(o)},getMovementX:function(o){return o.movementX||o.mozMovementX||o.webkitMovementX||0},getMovementY:function(o){return o.movementY||o.mozMovementY||o.webkitMovementY||0},getMouseWheelDelta:function(o){var l=0;switch(o.type){case"DOMMouseScroll":l=o.detail;break;case"mousewheel":l=o.wheelDelta;break;case"wheel":l=o.deltaY;break;default:throw"unrecognized mouse wheel event: "+o.type}return l},mouseX:0,mouseY:0,mouseMovementX:0,mouseMovementY:0,touches:{},lastTouches:{},calculateMouseEvent:function(o){if(Browser.pointerLock)o.type!="mousemove"&&"mozMovementX"in o?Browser.mouseMovementX=Browser.mouseMovementY=0:(Browser.mouseMovementX=Browser.getMovementX(o),Browser.mouseMovementY=Browser.getMovementY(o)),typeof SDL<"u"?(Browser.mouseX=SDL.mouseX+Browser.mouseMovementX,Browser.mouseY=SDL.mouseY+Browser.mouseMovementY):(Browser.mouseX+=Browser.mouseMovementX,Browser.mouseY+=Browser.mouseMovementY);else{var l=Module.canvas.getBoundingClientRect(),f=Module.canvas.width,h=Module.canvas.height,E=typeof window.scrollX<"u"?window.scrollX:window.pageXOffset,t=typeof window.scrollY<"u"?window.scrollY:window.pageYOffset;if(o.type==="touchstart"||o.type==="touchend"||o.type==="touchmove"){var N=o.touch;if(N===void 0)return;var F=N.pageX-(E+l.left),k=N.pageY-(t+l.top);F=F*(f/l.width),k=k*(h/l.height);var x={x:F,y:k};if(o.type==="touchstart")Browser.lastTouches[N.identifier]=x,Browser.touches[N.identifier]=x;else if(o.type==="touchend"||o.type==="touchmove"){var j=Browser.touches[N.identifier];j||(j=x),Browser.lastTouches[N.identifier]=j,Browser.touches[N.identifier]=x}return}var q=o.pageX-(E+l.left),V=o.pageY-(t+l.top);q=q*(f/l.width),V=V*(h/l.height),Browser.mouseMovementX=q-Browser.mouseX,Browser.mouseMovementY=V-Browser.mouseY,Browser.mouseX=q,Browser.mouseY=V}},asyncLoad:function(o,l,f,h){var E=h?"":"al "+o;Module.readAsync(o,function(t){assert(t,'Loading data file "'+o+'" failed (no arrayBuffer).'),l(new Uint8Array(t)),E&&removeRunDependency(E)},function(t){if(f)f();else throw'Loading data file "'+o+'" failed.'}),E&&addRunDependency(E)},resizeListeners:[],updateResizeListeners:function(){var o=Module.canvas;Browser.resizeListeners.forEach(function(l){l(o.width,o.height)})},setCanvasSize:function(o,l,f){var h=Module.canvas;Browser.updateCanvasDimensions(h,o,l),f||Browser.updateResizeListeners()},windowedWidth:0,windowedHeight:0,setFullscreenCanvasSize:function(){if(typeof SDL<"u"){var o=HEAPU32[SDL.screen+Runtime.QUANTUM_SIZE*0>>2];o=o|8388608,HEAP32[SDL.screen+Runtime.QUANTUM_SIZE*0>>2]=o}Browser.updateResizeListeners()},setWindowedCanvasSize:function(){if(typeof SDL<"u"){var o=HEAPU32[SDL.screen+Runtime.QUANTUM_SIZE*0>>2];o=o&-8388609,HEAP32[SDL.screen+Runtime.QUANTUM_SIZE*0>>2]=o}Browser.updateResizeListeners()},updateCanvasDimensions:function(o,l,f){l&&f?(o.widthNative=l,o.heightNative=f):(l=o.widthNative,f=o.heightNative);var h=l,E=f;if(Module.forcedAspectRatio&&Module.forcedAspectRatio>0&&(h/E>2];return l},getStr:function(){var o=Pointer_stringify(SYSCALLS.get());return o},get64:function(){var o=SYSCALLS.get(),l=SYSCALLS.get();return o>=0?assert(l===0):assert(l===-1),o},getZero:function(){assert(SYSCALLS.get()===0)}};function ___syscall6(o,l){SYSCALLS.varargs=l;try{var f=SYSCALLS.getStreamFromFD();return FS.close(f),0}catch(h){return(typeof FS>"u"||!(h instanceof FS.ErrnoError))&&abort(h),-h.errno}}function ___syscall54(o,l){SYSCALLS.varargs=l;try{return 0}catch(f){return(typeof FS>"u"||!(f instanceof FS.ErrnoError))&&abort(f),-f.errno}}function _typeModule(o){var l=[[0,1,"X"],[1,1,"const X"],[128,1,"X *"],[256,1,"X &"],[384,1,"X &&"],[512,1,"std::shared_ptr"],[640,1,"std::unique_ptr"],[5120,1,"std::vector"],[6144,2,"std::array"],[9216,-1,"std::function"]];function f(k,x,j,q,V,re){if(x==1){var y=q&896;(y==128||y==256||y==384)&&(k="X const")}var me;return re?me=j.replace("X",k).replace("Y",V):me=k.replace("X",j).replace("Y",V),me.replace(/([*&]) (?=[*&])/g,"$1")}function h(k,x,j,q,V){throw new Error(k+" type "+j.replace("X",x+"?")+(q?" with flag "+q:"")+" in "+V)}function E(k,x,j,q,V,re,y,me){re===void 0&&(re="X"),me===void 0&&(me=1);var De=j(k);if(De)return De;var ge=q(k),ae=ge.placeholderFlag,we=l[ae];y&&we&&(re=f(y[2],y[0],re,we[0],"?",!0));var he;ae==0&&(he="Unbound"),ae>=10&&(he="Corrupt"),me>20&&(he="Deeply nested"),he&&h(he,k,re,ae,V||"?");var ve=ge.paramList[0],ue=E(ve,x,j,q,V,re,we,me+1),Ae,ze={flags:we[0],id:k,name:"",paramList:[ue]},We=[],gt="?";switch(ge.placeholderFlag){case 1:Ae=ue.spec;break;case 2:if((ue.flags&15360)==1024&&ue.spec.ptrSize==1){ze.flags=7168;break}case 3:case 6:case 5:Ae=ue.spec,ue.flags&15360;break;case 8:gt=""+ge.paramList[1],ze.paramList.push(ge.paramList[1]);break;case 9:for(var _t=0,Qe=ge.paramList[1];_t>2]=o),o}function _llvm_stacksave(){var o=_llvm_stacksave;return o.LLVM_SAVEDSTACKS||(o.LLVM_SAVEDSTACKS=[]),o.LLVM_SAVEDSTACKS.push(Runtime.stackSave()),o.LLVM_SAVEDSTACKS.length-1}function ___syscall140(o,l){SYSCALLS.varargs=l;try{var f=SYSCALLS.getStreamFromFD(),h=SYSCALLS.get(),E=SYSCALLS.get(),t=SYSCALLS.get(),N=SYSCALLS.get(),F=E;return FS.llseek(f,F,N),HEAP32[t>>2]=f.position,f.getdents&&F===0&&N===0&&(f.getdents=null),0}catch(k){return(typeof FS>"u"||!(k instanceof FS.ErrnoError))&&abort(k),-k.errno}}function ___syscall146(o,l){SYSCALLS.varargs=l;try{var f=SYSCALLS.get(),h=SYSCALLS.get(),E=SYSCALLS.get(),t=0;___syscall146.buffer||(___syscall146.buffers=[null,[],[]],___syscall146.printChar=function(j,q){var V=___syscall146.buffers[j];assert(V),q===0||q===10?((j===1?Module.print:Module.printErr)(UTF8ArrayToString(V,0)),V.length=0):V.push(q)});for(var N=0;N>2],k=HEAP32[h+(N*8+4)>>2],x=0;x"u"||!(j instanceof FS.ErrnoError))&&abort(j),-j.errno}}function __nbind_finish(){for(var o=0,l=_nbind.BindClass.list;oo.pageSize/2||l>o.pageSize-f){var h=_nbind.typeNameTbl.NBind.proto;return h.lalloc(l)}else return HEAPU32[o.usedPtr]=f+l,o.rootPtr+f},o.lreset=function(l,f){var h=HEAPU32[o.pagePtr];if(h){var E=_nbind.typeNameTbl.NBind.proto;E.lreset(l,f)}else HEAPU32[o.usedPtr]=l},o}();_nbind.Pool=Pool;function constructType(o,l){var f=o==10240?_nbind.makeTypeNameTbl[l.name]||_nbind.BindType:_nbind.makeTypeKindTbl[o],h=new f(l);return typeIdTbl[l.id]=h,_nbind.typeNameTbl[l.name]=h,h}_nbind.constructType=constructType;function getType(o){return typeIdTbl[o]}_nbind.getType=getType;function queryType(o){var l=HEAPU8[o],f=_nbind.structureList[l][1];o/=4,f<0&&(++o,f=HEAPU32[o]+1);var h=Array.prototype.slice.call(HEAPU32.subarray(o+1,o+1+f));return l==9&&(h=[h[0],h.slice(1)]),{paramList:h,placeholderFlag:l}}_nbind.queryType=queryType;function getTypes(o,l){return o.map(function(f){return typeof f=="number"?_nbind.getComplexType(f,constructType,getType,queryType,l):_nbind.typeNameTbl[f]})}_nbind.getTypes=getTypes;function readTypeIdList(o,l){return Array.prototype.slice.call(HEAPU32,o/4,o/4+l)}_nbind.readTypeIdList=readTypeIdList;function readAsciiString(o){for(var l=o;HEAPU8[l++];);return String.fromCharCode.apply("",HEAPU8.subarray(o,l-1))}_nbind.readAsciiString=readAsciiString;function readPolicyList(o){var l={};if(o)for(;;){var f=HEAPU32[o/4];if(!f)break;l[readAsciiString(f)]=!0,o+=4}return l}_nbind.readPolicyList=readPolicyList;function getDynCall(o,l){var f={float32_t:"d",float64_t:"d",int64_t:"d",uint64_t:"d",void:"v"},h=o.map(function(t){return f[t.name]||"i"}).join(""),E=Module["dynCall_"+h];if(!E)throw new Error("dynCall_"+h+" not found for "+l+"("+o.map(function(t){return t.name}).join(", ")+")");return E}_nbind.getDynCall=getDynCall;function addMethod(o,l,f,h){var E=o[l];o.hasOwnProperty(l)&&E?((E.arity||E.arity===0)&&(E=_nbind.makeOverloader(E,E.arity),o[l]=E),E.addMethod(f,h)):(f.arity=h,o[l]=f)}_nbind.addMethod=addMethod;function throwError(o){throw new Error(o)}_nbind.throwError=throwError,_nbind.bigEndian=!1,_a=_typeModule(_typeModule),_nbind.Type=_a.Type,_nbind.makeType=_a.makeType,_nbind.getComplexType=_a.getComplexType,_nbind.structureList=_a.structureList;var BindType=function(o){__extends(l,o);function l(){var f=o!==null&&o.apply(this,arguments)||this;return f.heap=HEAPU32,f.ptrSize=4,f}return l.prototype.needsWireRead=function(f){return!!this.wireRead||!!this.makeWireRead},l.prototype.needsWireWrite=function(f){return!!this.wireWrite||!!this.makeWireWrite},l}(_nbind.Type);_nbind.BindType=BindType;var PrimitiveType=function(o){__extends(l,o);function l(f){var h=o.call(this,f)||this,E=f.flags&32?{32:HEAPF32,64:HEAPF64}:f.flags&8?{8:HEAPU8,16:HEAPU16,32:HEAPU32}:{8:HEAP8,16:HEAP16,32:HEAP32};return h.heap=E[f.ptrSize*8],h.ptrSize=f.ptrSize,h}return l.prototype.needsWireWrite=function(f){return!!f&&!!f.Strict},l.prototype.makeWireWrite=function(f,h){return h&&h.Strict&&function(E){if(typeof E=="number")return E;throw new Error("Type mismatch")}},l}(BindType);_nbind.PrimitiveType=PrimitiveType;function pushCString(o,l){if(o==null){if(l&&l.Nullable)return 0;throw new Error("Type mismatch")}if(l&&l.Strict){if(typeof o!="string")throw new Error("Type mismatch")}else o=o.toString();var f=Module.lengthBytesUTF8(o)+1,h=_nbind.Pool.lalloc(f);return Module.stringToUTF8Array(o,HEAPU8,h,f),h}_nbind.pushCString=pushCString;function popCString(o){return o===0?null:Module.Pointer_stringify(o)}_nbind.popCString=popCString;var CStringType=function(o){__extends(l,o);function l(){var f=o!==null&&o.apply(this,arguments)||this;return f.wireRead=popCString,f.wireWrite=pushCString,f.readResources=[_nbind.resources.pool],f.writeResources=[_nbind.resources.pool],f}return l.prototype.makeWireWrite=function(f,h){return function(E){return pushCString(E,h)}},l}(BindType);_nbind.CStringType=CStringType;var BooleanType=function(o){__extends(l,o);function l(){var f=o!==null&&o.apply(this,arguments)||this;return f.wireRead=function(h){return!!h},f}return l.prototype.needsWireWrite=function(f){return!!f&&!!f.Strict},l.prototype.makeWireRead=function(f){return"!!("+f+")"},l.prototype.makeWireWrite=function(f,h){return h&&h.Strict&&function(E){if(typeof E=="boolean")return E;throw new Error("Type mismatch")}||f},l}(BindType);_nbind.BooleanType=BooleanType;var Wrapper=function(){function o(){}return o.prototype.persist=function(){this.__nbindState|=1},o}();_nbind.Wrapper=Wrapper;function makeBound(o,l){var f=function(h){__extends(E,h);function E(t,N,F,k){var x=h.call(this)||this;if(!(x instanceof E))return new(Function.prototype.bind.apply(E,Array.prototype.concat.apply([null],arguments)));var j=N,q=F,V=k;if(t!==_nbind.ptrMarker){var re=x.__nbindConstructor.apply(x,arguments);j=4608,V=HEAPU32[re/4],q=HEAPU32[re/4+1]}var y={configurable:!0,enumerable:!1,value:null,writable:!1},me={__nbindFlags:j,__nbindPtr:q};V&&(me.__nbindShared=V,_nbind.mark(x));for(var De=0,ge=Object.keys(me);De>=1;var f=_nbind.valueList[o];return _nbind.valueList[o]=firstFreeValue,firstFreeValue=o,f}else{if(l)return _nbind.popShared(o,l);throw new Error("Invalid value slot "+o)}}_nbind.popValue=popValue;var valueBase=18446744073709552e3;function push64(o){return typeof o=="number"?o:pushValue(o)*4096+valueBase}function pop64(o){return o=3?N=Buffer.from(t):N=new Buffer(t),N.copy(h)}else getBuffer(h).set(t)}}_nbind.commitBuffer=commitBuffer;var dirtyList=[],gcTimer=0;function sweep(){for(var o=0,l=dirtyList;o>2]=DYNAMIC_BASE,staticSealed=!0;function invoke_viiiii(o,l,f,h,E,t){try{Module.dynCall_viiiii(o,l,f,h,E,t)}catch(N){if(typeof N!="number"&&N!=="longjmp")throw N;Module.setThrew(1,0)}}function invoke_vif(o,l,f){try{Module.dynCall_vif(o,l,f)}catch(h){if(typeof h!="number"&&h!=="longjmp")throw h;Module.setThrew(1,0)}}function invoke_vid(o,l,f){try{Module.dynCall_vid(o,l,f)}catch(h){if(typeof h!="number"&&h!=="longjmp")throw h;Module.setThrew(1,0)}}function invoke_fiff(o,l,f,h){try{return Module.dynCall_fiff(o,l,f,h)}catch(E){if(typeof E!="number"&&E!=="longjmp")throw E;Module.setThrew(1,0)}}function invoke_vi(o,l){try{Module.dynCall_vi(o,l)}catch(f){if(typeof f!="number"&&f!=="longjmp")throw f;Module.setThrew(1,0)}}function invoke_vii(o,l,f){try{Module.dynCall_vii(o,l,f)}catch(h){if(typeof h!="number"&&h!=="longjmp")throw h;Module.setThrew(1,0)}}function invoke_ii(o,l){try{return Module.dynCall_ii(o,l)}catch(f){if(typeof f!="number"&&f!=="longjmp")throw f;Module.setThrew(1,0)}}function invoke_viddi(o,l,f,h,E){try{Module.dynCall_viddi(o,l,f,h,E)}catch(t){if(typeof t!="number"&&t!=="longjmp")throw t;Module.setThrew(1,0)}}function invoke_vidd(o,l,f,h){try{Module.dynCall_vidd(o,l,f,h)}catch(E){if(typeof E!="number"&&E!=="longjmp")throw E;Module.setThrew(1,0)}}function invoke_iiii(o,l,f,h){try{return Module.dynCall_iiii(o,l,f,h)}catch(E){if(typeof E!="number"&&E!=="longjmp")throw E;Module.setThrew(1,0)}}function invoke_diii(o,l,f,h){try{return Module.dynCall_diii(o,l,f,h)}catch(E){if(typeof E!="number"&&E!=="longjmp")throw E;Module.setThrew(1,0)}}function invoke_di(o,l){try{return Module.dynCall_di(o,l)}catch(f){if(typeof f!="number"&&f!=="longjmp")throw f;Module.setThrew(1,0)}}function invoke_iid(o,l,f){try{return Module.dynCall_iid(o,l,f)}catch(h){if(typeof h!="number"&&h!=="longjmp")throw h;Module.setThrew(1,0)}}function invoke_iii(o,l,f){try{return Module.dynCall_iii(o,l,f)}catch(h){if(typeof h!="number"&&h!=="longjmp")throw h;Module.setThrew(1,0)}}function invoke_viiddi(o,l,f,h,E,t){try{Module.dynCall_viiddi(o,l,f,h,E,t)}catch(N){if(typeof N!="number"&&N!=="longjmp")throw N;Module.setThrew(1,0)}}function invoke_viiiiii(o,l,f,h,E,t,N){try{Module.dynCall_viiiiii(o,l,f,h,E,t,N)}catch(F){if(typeof F!="number"&&F!=="longjmp")throw F;Module.setThrew(1,0)}}function invoke_dii(o,l,f){try{return Module.dynCall_dii(o,l,f)}catch(h){if(typeof h!="number"&&h!=="longjmp")throw h;Module.setThrew(1,0)}}function invoke_i(o){try{return Module.dynCall_i(o)}catch(l){if(typeof l!="number"&&l!=="longjmp")throw l;Module.setThrew(1,0)}}function invoke_iiiiii(o,l,f,h,E,t){try{return Module.dynCall_iiiiii(o,l,f,h,E,t)}catch(N){if(typeof N!="number"&&N!=="longjmp")throw N;Module.setThrew(1,0)}}function invoke_viiid(o,l,f,h,E){try{Module.dynCall_viiid(o,l,f,h,E)}catch(t){if(typeof t!="number"&&t!=="longjmp")throw t;Module.setThrew(1,0)}}function invoke_viififi(o,l,f,h,E,t,N){try{Module.dynCall_viififi(o,l,f,h,E,t,N)}catch(F){if(typeof F!="number"&&F!=="longjmp")throw F;Module.setThrew(1,0)}}function invoke_viii(o,l,f,h){try{Module.dynCall_viii(o,l,f,h)}catch(E){if(typeof E!="number"&&E!=="longjmp")throw E;Module.setThrew(1,0)}}function invoke_v(o){try{Module.dynCall_v(o)}catch(l){if(typeof l!="number"&&l!=="longjmp")throw l;Module.setThrew(1,0)}}function invoke_viid(o,l,f,h){try{Module.dynCall_viid(o,l,f,h)}catch(E){if(typeof E!="number"&&E!=="longjmp")throw E;Module.setThrew(1,0)}}function invoke_idd(o,l,f){try{return Module.dynCall_idd(o,l,f)}catch(h){if(typeof h!="number"&&h!=="longjmp")throw h;Module.setThrew(1,0)}}function invoke_viiii(o,l,f,h,E){try{Module.dynCall_viiii(o,l,f,h,E)}catch(t){if(typeof t!="number"&&t!=="longjmp")throw t;Module.setThrew(1,0)}}Module.asmGlobalArg={Math,Int8Array,Int16Array,Int32Array,Uint8Array,Uint16Array,Uint32Array,Float32Array,Float64Array,NaN:NaN,Infinity:1/0},Module.asmLibraryArg={abort,assert,enlargeMemory,getTotalMemory,abortOnCannotGrowMemory,invoke_viiiii,invoke_vif,invoke_vid,invoke_fiff,invoke_vi,invoke_vii,invoke_ii,invoke_viddi,invoke_vidd,invoke_iiii,invoke_diii,invoke_di,invoke_iid,invoke_iii,invoke_viiddi,invoke_viiiiii,invoke_dii,invoke_i,invoke_iiiiii,invoke_viiid,invoke_viififi,invoke_viii,invoke_v,invoke_viid,invoke_idd,invoke_viiii,_emscripten_asm_const_iiiii,_emscripten_asm_const_iiidddddd,_emscripten_asm_const_iiiid,__nbind_reference_external,_emscripten_asm_const_iiiiiiii,_removeAccessorPrefix,_typeModule,__nbind_register_pool,__decorate,_llvm_stackrestore,___cxa_atexit,__extends,__nbind_get_value_object,__ZN8facebook4yoga14YGNodeToStringEPNSt3__212basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEP6YGNode14YGPrintOptionsj,_emscripten_set_main_loop_timing,__nbind_register_primitive,__nbind_register_type,_emscripten_memcpy_big,__nbind_register_function,___setErrNo,__nbind_register_class,__nbind_finish,_abort,_nbind_value,_llvm_stacksave,___syscall54,_defineHidden,_emscripten_set_main_loop,_emscripten_get_now,__nbind_register_callback_signature,_emscripten_asm_const_iiiiii,__nbind_free_external,_emscripten_asm_const_iiii,_emscripten_asm_const_iiididi,___syscall6,_atexit,___syscall140,___syscall146,DYNAMICTOP_PTR,tempDoublePtr,ABORT,STACKTOP,STACK_MAX,cttz_i8,___dso_handle};var asm=function(o,l,f){var h=new o.Int8Array(f),E=new o.Int16Array(f),t=new o.Int32Array(f),N=new o.Uint8Array(f),F=new o.Uint16Array(f),k=new o.Uint32Array(f),x=new o.Float32Array(f),j=new o.Float64Array(f),q=l.DYNAMICTOP_PTR|0,V=l.tempDoublePtr|0,re=l.ABORT|0,y=l.STACKTOP|0,me=l.STACK_MAX|0,De=l.cttz_i8|0,ge=l.___dso_handle|0,ae=0,we=0,he=0,ve=0,ue=o.NaN,Ae=o.Infinity,ze=0,We=0,gt=0,_t=0,Qe=0,ot=0,Ve=o.Math.floor,Pt=o.Math.abs,Jt=o.Math.sqrt,it=o.Math.pow,J=o.Math.cos,ce=o.Math.sin,Re=o.Math.tan,le=o.Math.acos,He=o.Math.asin,dt=o.Math.atan,At=o.Math.atan2,nn=o.Math.exp,an=o.Math.log,On=o.Math.ceil,lr=o.Math.imul,ln=o.Math.min,Vt=o.Math.max,Er=o.Math.clz32,S=o.Math.fround,zt=l.abort,Xn=l.assert,vr=l.enlargeMemory,jr=l.getTotalMemory,fr=l.abortOnCannotGrowMemory,zr=l.invoke_viiiii,Xt=l.invoke_vif,Du=l.invoke_vid,c0=l.invoke_fiff,Ao=l.invoke_vi,Jo=l.invoke_vii,Fs=l.invoke_ii,Zo=l.invoke_viddi,$o=l.invoke_vidd,qt=l.invoke_iiii,xi=l.invoke_diii,lu=l.invoke_di,vi=l.invoke_iid,Dr=l.invoke_iii,el=l.invoke_viiddi,Y0=l.invoke_viiiiii,Bu=l.invoke_dii,K0=l.invoke_i,Kr=l.invoke_iiiiii,Oo=l.invoke_viiid,Mo=l.invoke_viififi,F0=l.invoke_viii,su=l.invoke_v,ki=l.invoke_viid,Ps=l.invoke_idd,Kl=l.invoke_viiii,P0=l._emscripten_asm_const_iiiii,d0=l._emscripten_asm_const_iiidddddd,Hr=l._emscripten_asm_const_iiiid,Ri=l.__nbind_reference_external,X0=l._emscripten_asm_const_iiiiiiii,mi=l._removeAccessorPrefix,en=l._typeModule,In=l.__nbind_register_pool,Ai=l.__decorate,yi=l._llvm_stackrestore,Wt=l.___cxa_atexit,Ru=l.__extends,eu=l.__nbind_get_value_object,Q0=l.__ZN8facebook4yoga14YGNodeToStringEPNSt3__212basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEP6YGNode14YGPrintOptionsj,Yi=l._emscripten_set_main_loop_timing,Xl=l.__nbind_register_primitive,ko=l.__nbind_register_type,li=l._emscripten_memcpy_big,ao=l.__nbind_register_function,Ql=l.___setErrNo,No=l.__nbind_register_class,Is=l.__nbind_finish,$n=l._abort,tl=l._nbind_value,fo=l._llvm_stacksave,I0=l.___syscall54,Sl=l._defineHidden,Lo=l._emscripten_set_main_loop,St=l._emscripten_get_now,Bt=l.__nbind_register_callback_signature,Hn=l._emscripten_asm_const_iiiiii,qr=l.__nbind_free_external,Ki=l._emscripten_asm_const_iiii,Xr=l._emscripten_asm_const_iiididi,Au=l.___syscall6,p0=l._atexit,Ni=l.___syscall140,h0=l.___syscall146,hs=S(0);let Ct=S(0);function co(e){e=e|0;var n=0;return n=y,y=y+e|0,y=y+15&-16,n|0}function nl(){return y|0}function Jl(e){e=e|0,y=e}function Uu(e,n){e=e|0,n=n|0,y=e,me=n}function vs(e,n){e=e|0,n=n|0,ae||(ae=e,we=n)}function b0(e){e=e|0,ot=e}function Q(){return ot|0}function Se(){var e=0,n=0;gr(8104,8,400)|0,gr(8504,408,540)|0,e=9044,n=e+44|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));h[9088]=0,h[9089]=1,t[2273]=0,t[2274]=948,t[2275]=948,Wt(17,8104,ge|0)|0}function Fe(e){e=e|0,ac(e+948|0)}function Le(e){return e=S(e),((mr(e)|0)&2147483647)>>>0>2139095040|0}function pt(e,n,r){e=e|0,n=n|0,r=r|0;e:do if(t[e+(n<<3)+4>>2]|0)e=e+(n<<3)|0;else{if((n|2|0)==3&&t[e+60>>2]|0){e=e+56|0;break}switch(n|0){case 0:case 2:case 4:case 5:{if(t[e+52>>2]|0){e=e+48|0;break e}break}default:}if(t[e+68>>2]|0){e=e+64|0;break}else{e=(n|1|0)==5?948:r;break}}while(0);return e|0}function Yn(e){e=e|0;var n=0;return n=p_(1e3)|0,Cn(e,(n|0)!=0,2456),t[2276]=(t[2276]|0)+1,gr(n|0,8104,1e3)|0,h[e+2>>0]|0&&(t[n+4>>2]=2,t[n+12>>2]=4),t[n+976>>2]=e,n|0}function Cn(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0;s=y,y=y+16|0,u=s,n||(t[u>>2]=r,Cl(e,5,3197,u)),y=s}function cr(){return Yn(956)|0}function Si(e){e=e|0;var n=0;return n=pn(1e3)|0,Ou(n,e),Cn(t[e+976>>2]|0,1,2456),t[2276]=(t[2276]|0)+1,t[n+944>>2]=0,n|0}function Ou(e,n){e=e|0,n=n|0;var r=0;gr(e|0,n|0,948)|0,sa(e+948|0,n+948|0),r=e+960|0,e=n+960|0,n=r+40|0;do t[r>>2]=t[e>>2],r=r+4|0,e=e+4|0;while((r|0)<(n|0))}function ju(e){e=e|0;var n=0,r=0,u=0,s=0;if(n=e+944|0,r=t[n>>2]|0,r|0&&(zu(r+948|0,e)|0,t[n>>2]=0),r=wu(e)|0,r|0){n=0;do t[(Ti(e,n)|0)+944>>2]=0,n=n+1|0;while((n|0)!=(r|0))}r=e+948|0,u=t[r>>2]|0,s=e+952|0,n=t[s>>2]|0,(n|0)!=(u|0)&&(t[s>>2]=n+(~((n+-4-u|0)>>>2)<<2)),Fo(r),h_(e),t[2276]=(t[2276]|0)+-1}function zu(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0,w=0;u=t[e>>2]|0,w=e+4|0,r=t[w>>2]|0,a=r;e:do if((u|0)==(r|0))s=u,v=4;else for(e=u;;){if((t[e>>2]|0)==(n|0)){s=e,v=4;break e}if(e=e+4|0,(e|0)==(r|0)){e=0;break}}while(0);return(v|0)==4&&((s|0)!=(r|0)?(u=s+4|0,e=a-u|0,n=e>>2,n&&(ky(s|0,u|0,e|0)|0,r=t[w>>2]|0),e=s+(n<<2)|0,(r|0)==(e|0)||(t[w>>2]=r+(~((r+-4-e|0)>>>2)<<2)),e=1):e=0),e|0}function wu(e){return e=e|0,(t[e+952>>2]|0)-(t[e+948>>2]|0)>>2|0}function Ti(e,n){e=e|0,n=n|0;var r=0;return r=t[e+948>>2]|0,(t[e+952>>2]|0)-r>>2>>>0>n>>>0?e=t[r+(n<<2)>>2]|0:e=0,e|0}function Fo(e){e=e|0;var n=0,r=0,u=0,s=0;u=y,y=y+32|0,n=u,s=t[e>>2]|0,r=(t[e+4>>2]|0)-s|0,((t[e+8>>2]|0)-s|0)>>>0>r>>>0&&(s=r>>2,K(n,s,s,e+8|0),ti(e,n),ni(n)),y=u}function Mu(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0,w=0,T=0,L=0;L=wu(e)|0;do if(L|0){if((t[(Ti(e,0)|0)+944>>2]|0)==(e|0)){if(!(zu(e+948|0,n)|0))break;gr(n+400|0,8504,540)|0,t[n+944>>2]=0,Qn(e);break}v=t[(t[e+976>>2]|0)+12>>2]|0,w=e+948|0,T=(v|0)==0,r=0,a=0;do u=t[(t[w>>2]|0)+(a<<2)>>2]|0,(u|0)==(n|0)?Qn(e):(s=Si(u)|0,t[(t[w>>2]|0)+(r<<2)>>2]=s,t[s+944>>2]=e,T||BE[v&15](u,s,e,r),r=r+1|0),a=a+1|0;while((a|0)!=(L|0));if(r>>>0>>0){T=e+948|0,w=e+952|0,v=r,r=t[w>>2]|0;do a=(t[T>>2]|0)+(v<<2)|0,u=a+4|0,s=r-u|0,n=s>>2,n&&(ky(a|0,u|0,s|0)|0,r=t[w>>2]|0),s=r,u=a+(n<<2)|0,(s|0)!=(u|0)&&(r=s+(~((s+-4-u|0)>>>2)<<2)|0,t[w>>2]=r),v=v+1|0;while((v|0)!=(L|0))}}while(0)}function po(e){e=e|0;var n=0,r=0,u=0,s=0;Hu(e,(wu(e)|0)==0,2491),Hu(e,(t[e+944>>2]|0)==0,2545),n=e+948|0,r=t[n>>2]|0,u=e+952|0,s=t[u>>2]|0,(s|0)!=(r|0)&&(t[u>>2]=s+(~((s+-4-r|0)>>>2)<<2)),Fo(n),n=e+976|0,r=t[n>>2]|0,gr(e|0,8104,1e3)|0,h[r+2>>0]|0&&(t[e+4>>2]=2,t[e+12>>2]=4),t[n>>2]=r}function Hu(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0;s=y,y=y+16|0,u=s,n||(t[u>>2]=r,pr(e,5,3197,u)),y=s}function Pa(){return t[2276]|0}function v0(){var e=0;return e=p_(20)|0,ia((e|0)!=0,2592),t[2277]=(t[2277]|0)+1,t[e>>2]=t[239],t[e+4>>2]=t[240],t[e+8>>2]=t[241],t[e+12>>2]=t[242],t[e+16>>2]=t[243],e|0}function ia(e,n){e=e|0,n=n|0;var r=0,u=0;u=y,y=y+16|0,r=u,e||(t[r>>2]=n,pr(0,5,3197,r)),y=u}function J0(e){e=e|0,h_(e),t[2277]=(t[2277]|0)+-1}function ua(e,n){e=e|0,n=n|0;var r=0;n?(Hu(e,(wu(e)|0)==0,2629),r=1):(r=0,n=0),t[e+964>>2]=n,t[e+988>>2]=r}function Ia(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0;u=y,y=y+16|0,a=u+8|0,s=u+4|0,v=u,t[s>>2]=n,Hu(e,(t[n+944>>2]|0)==0,2709),Hu(e,(t[e+964>>2]|0)==0,2763),ms(e),n=e+948|0,t[v>>2]=(t[n>>2]|0)+(r<<2),t[a>>2]=t[v>>2],S0(n,a,s)|0,t[(t[s>>2]|0)+944>>2]=e,Qn(e),y=u}function ms(e){e=e|0;var n=0,r=0,u=0,s=0,a=0,v=0,w=0;if(r=wu(e)|0,r|0&&(t[(Ti(e,0)|0)+944>>2]|0)!=(e|0)){u=t[(t[e+976>>2]|0)+12>>2]|0,s=e+948|0,a=(u|0)==0,n=0;do v=t[(t[s>>2]|0)+(n<<2)>>2]|0,w=Si(v)|0,t[(t[s>>2]|0)+(n<<2)>>2]=w,t[w+944>>2]=e,a||BE[u&15](v,w,e,n),n=n+1|0;while((n|0)!=(r|0))}}function S0(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0,b=0,X=0,Be=0,Te=0,ye=0,Ze=0,Ye=0;Ze=y,y=y+64|0,b=Ze+52|0,w=Ze+48|0,X=Ze+28|0,Be=Ze+24|0,Te=Ze+20|0,ye=Ze,u=t[e>>2]|0,a=u,n=u+((t[n>>2]|0)-a>>2<<2)|0,u=e+4|0,s=t[u>>2]|0,v=e+8|0;do if(s>>>0<(t[v>>2]|0)>>>0){if((n|0)==(s|0)){t[n>>2]=t[r>>2],t[u>>2]=(t[u>>2]|0)+4;break}Wr(e,n,s,n+4|0),n>>>0<=r>>>0&&(r=(t[u>>2]|0)>>>0>r>>>0?r+4|0:r),t[n>>2]=t[r>>2]}else{u=(s-a>>2)+1|0,s=R0(e)|0,s>>>0>>0&&di(e),M=t[e>>2]|0,L=(t[v>>2]|0)-M|0,a=L>>1,K(ye,L>>2>>>0>>1>>>0?a>>>0>>0?u:a:s,n-M>>2,e+8|0),M=ye+8|0,u=t[M>>2]|0,a=ye+12|0,L=t[a>>2]|0,v=L,T=u;do if((u|0)==(L|0)){if(L=ye+4|0,u=t[L>>2]|0,Ye=t[ye>>2]|0,s=Ye,u>>>0<=Ye>>>0){u=v-s>>1,u=(u|0)==0?1:u,K(X,u,u>>>2,t[ye+16>>2]|0),t[Be>>2]=t[L>>2],t[Te>>2]=t[M>>2],t[w>>2]=t[Be>>2],t[b>>2]=t[Te>>2],Di(X,w,b),u=t[ye>>2]|0,t[ye>>2]=t[X>>2],t[X>>2]=u,u=X+4|0,Ye=t[L>>2]|0,t[L>>2]=t[u>>2],t[u>>2]=Ye,u=X+8|0,Ye=t[M>>2]|0,t[M>>2]=t[u>>2],t[u>>2]=Ye,u=X+12|0,Ye=t[a>>2]|0,t[a>>2]=t[u>>2],t[u>>2]=Ye,ni(X),u=t[M>>2]|0;break}a=u,v=((a-s>>2)+1|0)/-2|0,w=u+(v<<2)|0,s=T-a|0,a=s>>2,a&&(ky(w|0,u|0,s|0)|0,u=t[L>>2]|0),Ye=w+(a<<2)|0,t[M>>2]=Ye,t[L>>2]=u+(v<<2),u=Ye}while(0);t[u>>2]=t[r>>2],t[M>>2]=(t[M>>2]|0)+4,n=ft(e,ye,n)|0,ni(ye)}while(0);return y=Ze,n|0}function Qn(e){e=e|0;var n=0;do{if(n=e+984|0,h[n>>0]|0)break;h[n>>0]=1,x[e+504>>2]=S(ue),e=t[e+944>>2]|0}while((e|0)!=0)}function ac(e){e=e|0;var n=0,r=0,u=0;r=t[e>>2]|0,u=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-4-u|0)>>>2)<<2)),Et(r))}function si(e){return e=e|0,t[e+944>>2]|0}function Jr(e){e=e|0,Hu(e,(t[e+964>>2]|0)!=0,2832),Qn(e)}function Zl(e){return e=e|0,(h[e+984>>0]|0)!=0|0}function oa(e,n){e=e|0,n=n|0,vL(e,n,400)|0&&(gr(e|0,n|0,400)|0,Qn(e))}function pf(e){e=e|0;var n=Ct;return n=S(x[e+44>>2]),e=Le(n)|0,S(e?S(0):n)}function bs(e){e=e|0;var n=Ct;return n=S(x[e+48>>2]),Le(n)|0&&(n=h[(t[e+976>>2]|0)+2>>0]|0?S(1):S(0)),S(n)}function ba(e,n){e=e|0,n=n|0,t[e+980>>2]=n}function Bs(e){return e=e|0,t[e+980>>2]|0}function m0(e,n){e=e|0,n=n|0;var r=0;r=e+4|0,(t[r>>2]|0)!=(n|0)&&(t[r>>2]=n,Qn(e))}function Us(e){return e=e|0,t[e+4>>2]|0}function zi(e,n){e=e|0,n=n|0;var r=0;r=e+8|0,(t[r>>2]|0)!=(n|0)&&(t[r>>2]=n,Qn(e))}function U(e){return e=e|0,t[e+8>>2]|0}function H(e,n){e=e|0,n=n|0;var r=0;r=e+12|0,(t[r>>2]|0)!=(n|0)&&(t[r>>2]=n,Qn(e))}function Y(e){return e=e|0,t[e+12>>2]|0}function ee(e,n){e=e|0,n=n|0;var r=0;r=e+16|0,(t[r>>2]|0)!=(n|0)&&(t[r>>2]=n,Qn(e))}function Ce(e){return e=e|0,t[e+16>>2]|0}function _e(e,n){e=e|0,n=n|0;var r=0;r=e+20|0,(t[r>>2]|0)!=(n|0)&&(t[r>>2]=n,Qn(e))}function Oe(e){return e=e|0,t[e+20>>2]|0}function $(e,n){e=e|0,n=n|0;var r=0;r=e+24|0,(t[r>>2]|0)!=(n|0)&&(t[r>>2]=n,Qn(e))}function Ne(e){return e=e|0,t[e+24>>2]|0}function Je(e,n){e=e|0,n=n|0;var r=0;r=e+28|0,(t[r>>2]|0)!=(n|0)&&(t[r>>2]=n,Qn(e))}function vt(e){return e=e|0,t[e+28>>2]|0}function oe(e,n){e=e|0,n=n|0;var r=0;r=e+32|0,(t[r>>2]|0)!=(n|0)&&(t[r>>2]=n,Qn(e))}function qe(e){return e=e|0,t[e+32>>2]|0}function rt(e,n){e=e|0,n=n|0;var r=0;r=e+36|0,(t[r>>2]|0)!=(n|0)&&(t[r>>2]=n,Qn(e))}function xt(e){return e=e|0,t[e+36>>2]|0}function kt(e,n){e=e|0,n=S(n);var r=0;r=e+40|0,S(x[r>>2])!=n&&(x[r>>2]=n,Qn(e))}function bt(e,n){e=e|0,n=S(n);var r=0;r=e+44|0,S(x[r>>2])!=n&&(x[r>>2]=n,Qn(e))}function sn(e,n){e=e|0,n=S(n);var r=0;r=e+48|0,S(x[r>>2])!=n&&(x[r>>2]=n,Qn(e))}function rn(e,n){e=e|0,n=S(n);var r=0,u=0,s=0,a=0;a=Le(n)|0,r=(a^1)&1,u=e+52|0,s=e+56|0,a|S(x[u>>2])==n&&(t[s>>2]|0)==(r|0)||(x[u>>2]=n,t[s>>2]=r,Qn(e))}function Ft(e,n){e=e|0,n=S(n);var r=0,u=0;u=e+52|0,r=e+56|0,S(x[u>>2])==n&&(t[r>>2]|0)==2||(x[u>>2]=n,u=Le(n)|0,t[r>>2]=u?3:2,Qn(e))}function Dn(e,n){e=e|0,n=n|0;var r=0,u=0;u=n+52|0,r=t[u+4>>2]|0,n=e,t[n>>2]=t[u>>2],t[n+4>>2]=r}function dr(e,n,r){e=e|0,n=n|0,r=S(r);var u=0,s=0,a=0;a=Le(r)|0,u=(a^1)&1,s=e+132+(n<<3)|0,n=e+132+(n<<3)+4|0,a|S(x[s>>2])==r&&(t[n>>2]|0)==(u|0)||(x[s>>2]=r,t[n>>2]=u,Qn(e))}function er(e,n,r){e=e|0,n=n|0,r=S(r);var u=0,s=0,a=0;a=Le(r)|0,u=a?0:2,s=e+132+(n<<3)|0,n=e+132+(n<<3)+4|0,a|S(x[s>>2])==r&&(t[n>>2]|0)==(u|0)||(x[s>>2]=r,t[n>>2]=u,Qn(e))}function Cr(e,n,r){e=e|0,n=n|0,r=r|0;var u=0;u=n+132+(r<<3)|0,n=t[u+4>>2]|0,r=e,t[r>>2]=t[u>>2],t[r+4>>2]=n}function Rn(e,n,r){e=e|0,n=n|0,r=S(r);var u=0,s=0,a=0;a=Le(r)|0,u=(a^1)&1,s=e+60+(n<<3)|0,n=e+60+(n<<3)+4|0,a|S(x[s>>2])==r&&(t[n>>2]|0)==(u|0)||(x[s>>2]=r,t[n>>2]=u,Qn(e))}function Nr(e,n,r){e=e|0,n=n|0,r=S(r);var u=0,s=0,a=0;a=Le(r)|0,u=a?0:2,s=e+60+(n<<3)|0,n=e+60+(n<<3)+4|0,a|S(x[s>>2])==r&&(t[n>>2]|0)==(u|0)||(x[s>>2]=r,t[n>>2]=u,Qn(e))}function y0(e,n,r){e=e|0,n=n|0,r=r|0;var u=0;u=n+60+(r<<3)|0,n=t[u+4>>2]|0,r=e,t[r>>2]=t[u>>2],t[r+4>>2]=n}function Lr(e,n){e=e|0,n=n|0;var r=0;r=e+60+(n<<3)+4|0,(t[r>>2]|0)!=3&&(x[e+60+(n<<3)>>2]=S(ue),t[r>>2]=3,Qn(e))}function ut(e,n,r){e=e|0,n=n|0,r=S(r);var u=0,s=0,a=0;a=Le(r)|0,u=(a^1)&1,s=e+204+(n<<3)|0,n=e+204+(n<<3)+4|0,a|S(x[s>>2])==r&&(t[n>>2]|0)==(u|0)||(x[s>>2]=r,t[n>>2]=u,Qn(e))}function wt(e,n,r){e=e|0,n=n|0,r=S(r);var u=0,s=0,a=0;a=Le(r)|0,u=a?0:2,s=e+204+(n<<3)|0,n=e+204+(n<<3)+4|0,a|S(x[s>>2])==r&&(t[n>>2]|0)==(u|0)||(x[s>>2]=r,t[n>>2]=u,Qn(e))}function et(e,n,r){e=e|0,n=n|0,r=r|0;var u=0;u=n+204+(r<<3)|0,n=t[u+4>>2]|0,r=e,t[r>>2]=t[u>>2],t[r+4>>2]=n}function It(e,n,r){e=e|0,n=n|0,r=S(r);var u=0,s=0,a=0;a=Le(r)|0,u=(a^1)&1,s=e+276+(n<<3)|0,n=e+276+(n<<3)+4|0,a|S(x[s>>2])==r&&(t[n>>2]|0)==(u|0)||(x[s>>2]=r,t[n>>2]=u,Qn(e))}function un(e,n){return e=e|0,n=n|0,S(x[e+276+(n<<3)>>2])}function fn(e,n){e=e|0,n=S(n);var r=0,u=0,s=0,a=0;a=Le(n)|0,r=(a^1)&1,u=e+348|0,s=e+352|0,a|S(x[u>>2])==n&&(t[s>>2]|0)==(r|0)||(x[u>>2]=n,t[s>>2]=r,Qn(e))}function Jn(e,n){e=e|0,n=S(n);var r=0,u=0;u=e+348|0,r=e+352|0,S(x[u>>2])==n&&(t[r>>2]|0)==2||(x[u>>2]=n,u=Le(n)|0,t[r>>2]=u?3:2,Qn(e))}function wr(e){e=e|0;var n=0;n=e+352|0,(t[n>>2]|0)!=3&&(x[e+348>>2]=S(ue),t[n>>2]=3,Qn(e))}function au(e,n){e=e|0,n=n|0;var r=0,u=0;u=n+348|0,r=t[u+4>>2]|0,n=e,t[n>>2]=t[u>>2],t[n+4>>2]=r}function ku(e,n){e=e|0,n=S(n);var r=0,u=0,s=0,a=0;a=Le(n)|0,r=(a^1)&1,u=e+356|0,s=e+360|0,a|S(x[u>>2])==n&&(t[s>>2]|0)==(r|0)||(x[u>>2]=n,t[s>>2]=r,Qn(e))}function T0(e,n){e=e|0,n=S(n);var r=0,u=0;u=e+356|0,r=e+360|0,S(x[u>>2])==n&&(t[r>>2]|0)==2||(x[u>>2]=n,u=Le(n)|0,t[r>>2]=u?3:2,Qn(e))}function Z0(e){e=e|0;var n=0;n=e+360|0,(t[n>>2]|0)!=3&&(x[e+356>>2]=S(ue),t[n>>2]=3,Qn(e))}function Nu(e,n){e=e|0,n=n|0;var r=0,u=0;u=n+356|0,r=t[u+4>>2]|0,n=e,t[n>>2]=t[u>>2],t[n+4>>2]=r}function gi(e,n){e=e|0,n=S(n);var r=0,u=0,s=0,a=0;a=Le(n)|0,r=(a^1)&1,u=e+364|0,s=e+368|0,a|S(x[u>>2])==n&&(t[s>>2]|0)==(r|0)||(x[u>>2]=n,t[s>>2]=r,Qn(e))}function Po(e,n){e=e|0,n=S(n);var r=0,u=0,s=0,a=0;a=Le(n)|0,r=a?0:2,u=e+364|0,s=e+368|0,a|S(x[u>>2])==n&&(t[s>>2]|0)==(r|0)||(x[u>>2]=n,t[s>>2]=r,Qn(e))}function rl(e,n){e=e|0,n=n|0;var r=0,u=0;u=n+364|0,r=t[u+4>>2]|0,n=e,t[n>>2]=t[u>>2],t[n+4>>2]=r}function hf(e,n){e=e|0,n=S(n);var r=0,u=0,s=0,a=0;a=Le(n)|0,r=(a^1)&1,u=e+372|0,s=e+376|0,a|S(x[u>>2])==n&&(t[s>>2]|0)==(r|0)||(x[u>>2]=n,t[s>>2]=r,Qn(e))}function Tl(e,n){e=e|0,n=S(n);var r=0,u=0,s=0,a=0;a=Le(n)|0,r=a?0:2,u=e+372|0,s=e+376|0,a|S(x[u>>2])==n&&(t[s>>2]|0)==(r|0)||(x[u>>2]=n,t[s>>2]=r,Qn(e))}function vf(e,n){e=e|0,n=n|0;var r=0,u=0;u=n+372|0,r=t[u+4>>2]|0,n=e,t[n>>2]=t[u>>2],t[n+4>>2]=r}function Io(e,n){e=e|0,n=S(n);var r=0,u=0,s=0,a=0;a=Le(n)|0,r=(a^1)&1,u=e+380|0,s=e+384|0,a|S(x[u>>2])==n&&(t[s>>2]|0)==(r|0)||(x[u>>2]=n,t[s>>2]=r,Qn(e))}function ys(e,n){e=e|0,n=S(n);var r=0,u=0,s=0,a=0;a=Le(n)|0,r=a?0:2,u=e+380|0,s=e+384|0,a|S(x[u>>2])==n&&(t[s>>2]|0)==(r|0)||(x[u>>2]=n,t[s>>2]=r,Qn(e))}function js(e,n){e=e|0,n=n|0;var r=0,u=0;u=n+380|0,r=t[u+4>>2]|0,n=e,t[n>>2]=t[u>>2],t[n+4>>2]=r}function bo(e,n){e=e|0,n=S(n);var r=0,u=0,s=0,a=0;a=Le(n)|0,r=(a^1)&1,u=e+388|0,s=e+392|0,a|S(x[u>>2])==n&&(t[s>>2]|0)==(r|0)||(x[u>>2]=n,t[s>>2]=r,Qn(e))}function Bo(e,n){e=e|0,n=S(n);var r=0,u=0,s=0,a=0;a=Le(n)|0,r=a?0:2,u=e+388|0,s=e+392|0,a|S(x[u>>2])==n&&(t[s>>2]|0)==(r|0)||(x[u>>2]=n,t[s>>2]=r,Qn(e))}function gs(e,n){e=e|0,n=n|0;var r=0,u=0;u=n+388|0,r=t[u+4>>2]|0,n=e,t[n>>2]=t[u>>2],t[n+4>>2]=r}function Xu(e,n){e=e|0,n=S(n);var r=0;r=e+396|0,S(x[r>>2])!=n&&(x[r>>2]=n,Qn(e))}function Su(e){return e=e|0,S(x[e+396>>2])}function _i(e){return e=e|0,S(x[e+400>>2])}function C0(e){return e=e|0,S(x[e+404>>2])}function $0(e){return e=e|0,S(x[e+408>>2])}function Uo(e){return e=e|0,S(x[e+412>>2])}function la(e){return e=e|0,S(x[e+416>>2])}function $l(e){return e=e|0,S(x[e+420>>2])}function tu(e,n){switch(e=e|0,n=n|0,Hu(e,(n|0)<6,2918),n|0){case 0:{n=(t[e+496>>2]|0)==2?5:4;break}case 2:{n=(t[e+496>>2]|0)==2?4:5;break}default:}return S(x[e+424+(n<<2)>>2])}function Zr(e,n){switch(e=e|0,n=n|0,Hu(e,(n|0)<6,2918),n|0){case 0:{n=(t[e+496>>2]|0)==2?5:4;break}case 2:{n=(t[e+496>>2]|0)==2?4:5;break}default:}return S(x[e+448+(n<<2)>>2])}function ho(e,n){switch(e=e|0,n=n|0,Hu(e,(n|0)<6,2918),n|0){case 0:{n=(t[e+496>>2]|0)==2?5:4;break}case 2:{n=(t[e+496>>2]|0)==2?4:5;break}default:}return S(x[e+472+(n<<2)>>2])}function Bi(e,n){e=e|0,n=n|0;var r=0,u=Ct;return r=t[e+4>>2]|0,(r|0)==(t[n+4>>2]|0)?r?(u=S(x[e>>2]),e=S(Pt(S(u-S(x[n>>2]))))>2]=0,t[u+4>>2]=0,t[u+8>>2]=0,Q0(u|0,e|0,n|0,0),pr(e,3,(h[u+11>>0]|0)<0?t[u>>2]|0:u,r),BL(u),y=r}function eo(e,n,r,u){e=S(e),n=S(n),r=r|0,u=u|0;var s=Ct;e=S(e*n),s=S(NE(e,S(1)));do if(Ci(s,S(0))|0)e=S(e-s);else{if(e=S(e-s),Ci(s,S(1))|0){e=S(e+S(1));break}if(r){e=S(e+S(1));break}u||(s>S(.5)?s=S(1):(u=Ci(s,S(.5))|0,s=S(u?1:0)),e=S(e+s))}while(0);return S(e/n)}function to(e,n,r,u,s,a,v,w,T,L,M,b,X){e=e|0,n=S(n),r=r|0,u=S(u),s=s|0,a=S(a),v=v|0,w=S(w),T=S(T),L=S(L),M=S(M),b=S(b),X=X|0;var Be=0,Te=Ct,ye=Ct,Ze=Ct,Ye=Ct,ct=Ct,ke=Ct;return T>2]),Te!=S(0))?(Ze=S(eo(n,Te,0,0)),Ye=S(eo(u,Te,0,0)),ye=S(eo(a,Te,0,0)),Te=S(eo(w,Te,0,0))):(ye=a,Ze=n,Te=w,Ye=u),(s|0)==(e|0)?Be=Ci(ye,Ze)|0:Be=0,(v|0)==(r|0)?X=Ci(Te,Ye)|0:X=0,!Be&&(ct=S(n-M),!(xe(e,ct,T)|0))&&!(tt(e,ct,s,T)|0)?Be=Ke(e,ct,s,a,T)|0:Be=1,!X&&(ke=S(u-b),!(xe(r,ke,L)|0))&&!(tt(r,ke,v,L)|0)?X=Ke(r,ke,v,w,L)|0:X=1,X=Be&X),X|0}function xe(e,n,r){return e=e|0,n=S(n),r=S(r),(e|0)==1?e=Ci(n,r)|0:e=0,e|0}function tt(e,n,r,u){return e=e|0,n=S(n),r=r|0,u=S(u),(e|0)==2&(r|0)==0?n>=u?e=1:e=Ci(n,u)|0:e=0,e|0}function Ke(e,n,r,u,s){return e=e|0,n=S(n),r=r|0,u=S(u),s=S(s),(e|0)==2&(r|0)==2&u>n?s<=n?e=1:e=Ci(n,s)|0:e=0,e|0}function Yt(e,n,r,u,s,a,v,w,T,L,M){e=e|0,n=S(n),r=S(r),u=u|0,s=s|0,a=a|0,v=S(v),w=S(w),T=T|0,L=L|0,M=M|0;var b=0,X=0,Be=0,Te=0,ye=Ct,Ze=Ct,Ye=0,ct=0,ke=0,Ie=0,Zt=0,Br=0,Pn=0,gn=0,_r=0,Pr=0,kn=0,uu=Ct,os=Ct,ls=Ct,ss=0,ea=0;kn=y,y=y+160|0,gn=kn+152|0,Pn=kn+120|0,Br=kn+104|0,ke=kn+72|0,Te=kn+56|0,Zt=kn+8|0,ct=kn,Ie=(t[2279]|0)+1|0,t[2279]=Ie,_r=e+984|0,(h[_r>>0]|0)!=0&&(t[e+512>>2]|0)!=(t[2278]|0)?Ye=4:(t[e+516>>2]|0)==(u|0)?Pr=0:Ye=4,(Ye|0)==4&&(t[e+520>>2]=0,t[e+924>>2]=-1,t[e+928>>2]=-1,x[e+932>>2]=S(-1),x[e+936>>2]=S(-1),Pr=1);e:do if(t[e+964>>2]|0)if(ye=S(Kt(e,2,v)),Ze=S(Kt(e,0,v)),b=e+916|0,ls=S(x[b>>2]),os=S(x[e+920>>2]),uu=S(x[e+932>>2]),to(s,n,a,r,t[e+924>>2]|0,ls,t[e+928>>2]|0,os,uu,S(x[e+936>>2]),ye,Ze,M)|0)Ye=22;else if(Be=t[e+520>>2]|0,!Be)Ye=21;else for(X=0;;){if(b=e+524+(X*24|0)|0,uu=S(x[b>>2]),os=S(x[e+524+(X*24|0)+4>>2]),ls=S(x[e+524+(X*24|0)+16>>2]),to(s,n,a,r,t[e+524+(X*24|0)+8>>2]|0,uu,t[e+524+(X*24|0)+12>>2]|0,os,ls,S(x[e+524+(X*24|0)+20>>2]),ye,Ze,M)|0){Ye=22;break e}if(X=X+1|0,X>>>0>=Be>>>0){Ye=21;break}}else{if(T){if(b=e+916|0,!(Ci(S(x[b>>2]),n)|0)){Ye=21;break}if(!(Ci(S(x[e+920>>2]),r)|0)){Ye=21;break}if((t[e+924>>2]|0)!=(s|0)){Ye=21;break}b=(t[e+928>>2]|0)==(a|0)?b:0,Ye=22;break}if(Be=t[e+520>>2]|0,!Be)Ye=21;else for(X=0;;){if(b=e+524+(X*24|0)|0,Ci(S(x[b>>2]),n)|0&&Ci(S(x[e+524+(X*24|0)+4>>2]),r)|0&&(t[e+524+(X*24|0)+8>>2]|0)==(s|0)&&(t[e+524+(X*24|0)+12>>2]|0)==(a|0)){Ye=22;break e}if(X=X+1|0,X>>>0>=Be>>>0){Ye=21;break}}}while(0);do if((Ye|0)==21)h[11697]|0?(b=0,Ye=28):(b=0,Ye=31);else if((Ye|0)==22){if(X=(h[11697]|0)!=0,!((b|0)!=0&(Pr^1)))if(X){Ye=28;break}else{Ye=31;break}Te=b+16|0,t[e+908>>2]=t[Te>>2],Be=b+20|0,t[e+912>>2]=t[Be>>2],(h[11698]|0)==0|X^1||(t[ct>>2]=Ei(Ie)|0,t[ct+4>>2]=Ie,pr(e,4,2972,ct),X=t[e+972>>2]|0,X|0&&P1[X&127](e),s=bn(s,T)|0,a=bn(a,T)|0,ea=+S(x[Te>>2]),ss=+S(x[Be>>2]),t[Zt>>2]=s,t[Zt+4>>2]=a,j[Zt+8>>3]=+n,j[Zt+16>>3]=+r,j[Zt+24>>3]=ea,j[Zt+32>>3]=ss,t[Zt+40>>2]=L,pr(e,4,2989,Zt))}while(0);return(Ye|0)==28&&(X=Ei(Ie)|0,t[Te>>2]=X,t[Te+4>>2]=Ie,t[Te+8>>2]=Pr?3047:11699,pr(e,4,3038,Te),X=t[e+972>>2]|0,X|0&&P1[X&127](e),Zt=bn(s,T)|0,Ye=bn(a,T)|0,t[ke>>2]=Zt,t[ke+4>>2]=Ye,j[ke+8>>3]=+n,j[ke+16>>3]=+r,t[ke+24>>2]=L,pr(e,4,3049,ke),Ye=31),(Ye|0)==31&&(mu(e,n,r,u,s,a,v,w,T,M),h[11697]|0&&(X=t[2279]|0,Zt=Ei(X)|0,t[Br>>2]=Zt,t[Br+4>>2]=X,t[Br+8>>2]=Pr?3047:11699,pr(e,4,3083,Br),X=t[e+972>>2]|0,X|0&&P1[X&127](e),Zt=bn(s,T)|0,Br=bn(a,T)|0,ss=+S(x[e+908>>2]),ea=+S(x[e+912>>2]),t[Pn>>2]=Zt,t[Pn+4>>2]=Br,j[Pn+8>>3]=ss,j[Pn+16>>3]=ea,t[Pn+24>>2]=L,pr(e,4,3092,Pn)),t[e+516>>2]=u,b||(X=e+520|0,b=t[X>>2]|0,(b|0)==16&&(h[11697]|0&&pr(e,4,3124,gn),t[X>>2]=0,b=0),T?b=e+916|0:(t[X>>2]=b+1,b=e+524+(b*24|0)|0),x[b>>2]=n,x[b+4>>2]=r,t[b+8>>2]=s,t[b+12>>2]=a,t[b+16>>2]=t[e+908>>2],t[b+20>>2]=t[e+912>>2],b=0)),T&&(t[e+416>>2]=t[e+908>>2],t[e+420>>2]=t[e+912>>2],h[e+985>>0]=1,h[_r>>0]=0),t[2279]=(t[2279]|0)+-1,t[e+512>>2]=t[2278],y=kn,Pr|(b|0)==0|0}function Kt(e,n,r){e=e|0,n=n|0,r=S(r);var u=Ct;return u=S(Hi(e,n,r)),S(u+S(A0(e,n,r)))}function pr(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0,a=0;a=y,y=y+16|0,s=a,t[s>>2]=u,e?u=t[e+976>>2]|0:u=0,zs(u,e,n,r,s),y=a}function Ei(e){return e=e|0,(e>>>0>60?3201:3201+(60-e)|0)|0}function bn(e,n){e=e|0,n=n|0;var r=0,u=0,s=0;return s=y,y=y+32|0,r=s+12|0,u=s,t[r>>2]=t[254],t[r+4>>2]=t[255],t[r+8>>2]=t[256],t[u>>2]=t[257],t[u+4>>2]=t[258],t[u+8>>2]=t[259],(e|0)>2?e=11699:e=t[(n?u:r)+(e<<2)>>2]|0,y=s,e|0}function mu(e,n,r,u,s,a,v,w,T,L){e=e|0,n=S(n),r=S(r),u=u|0,s=s|0,a=a|0,v=S(v),w=S(w),T=T|0,L=L|0;var M=0,b=0,X=0,Be=0,Te=Ct,ye=Ct,Ze=Ct,Ye=Ct,ct=Ct,ke=Ct,Ie=Ct,Zt=0,Br=0,Pn=0,gn=Ct,_r=Ct,Pr=0,kn=Ct,uu=0,os=0,ls=0,ss=0,ea=0,t2=0,n2=0,uf=0,r2=0,Fc=0,Pc=0,i2=0,u2=0,o2=0,pi=0,of=0,l2=0,Yf=0,s2=Ct,a2=Ct,Ic=Ct,bc=Ct,Kf=Ct,ql=0,La=0,Ns=0,lf=0,b1=0,B1=Ct,Bc=Ct,U1=Ct,j1=Ct,Wl=Ct,El=Ct,sf=0,hu=Ct,z1=Ct,as=Ct,Xf=Ct,fs=Ct,Qf=Ct,H1=0,q1=0,Jf=Ct,Vl=Ct,af=0,W1=0,V1=0,G1=0,Sr=Ct,bu=0,Dl=0,cs=0,Gl=0,Or=0,Bn=0,ff=0,mn=Ct,Y1=0,a0=0;ff=y,y=y+16|0,ql=ff+12|0,La=ff+8|0,Ns=ff+4|0,lf=ff,Hu(e,(s|0)==0|(Le(n)|0)^1,3326),Hu(e,(a|0)==0|(Le(r)|0)^1,3406),Dl=xl(e,u)|0,t[e+496>>2]=Dl,Or=B0(2,Dl)|0,Bn=B0(0,Dl)|0,x[e+440>>2]=S(Hi(e,Or,v)),x[e+444>>2]=S(A0(e,Or,v)),x[e+428>>2]=S(Hi(e,Bn,v)),x[e+436>>2]=S(A0(e,Bn,v)),x[e+464>>2]=S(O0(e,Or)),x[e+468>>2]=S(vo(e,Or)),x[e+452>>2]=S(O0(e,Bn)),x[e+460>>2]=S(vo(e,Bn)),x[e+488>>2]=S(Fu(e,Or,v)),x[e+492>>2]=S(Ju(e,Or,v)),x[e+476>>2]=S(Fu(e,Bn,v)),x[e+484>>2]=S(Ju(e,Bn,v));do if(t[e+964>>2]|0)es(e,n,r,s,a,v,w);else{if(cs=e+948|0,Gl=(t[e+952>>2]|0)-(t[cs>>2]|0)>>2,!Gl){_s(e,n,r,s,a,v,w);break}if(!T&&aa(e,n,r,s,a,v,w)|0)break;ms(e),of=e+508|0,h[of>>0]=0,Or=B0(t[e+4>>2]|0,Dl)|0,Bn=gf(Or,Dl)|0,bu=qi(Or)|0,l2=t[e+8>>2]|0,W1=e+28|0,Yf=(t[W1>>2]|0)!=0,fs=bu?v:w,Jf=bu?w:v,s2=S(Zu(e,Or,v)),a2=S(Es(e,Or,v)),Te=S(Zu(e,Bn,v)),Qf=S(Rr(e,Or,v)),Vl=S(Rr(e,Bn,v)),Pn=bu?s:a,af=bu?a:s,Sr=bu?Qf:Vl,ct=bu?Vl:Qf,Xf=S(Kt(e,2,v)),Ye=S(Kt(e,0,v)),ye=S(S(xn(e+364|0,v))-Sr),Ze=S(S(xn(e+380|0,v))-Sr),ke=S(S(xn(e+372|0,w))-ct),Ie=S(S(xn(e+388|0,w))-ct),Ic=bu?ye:ke,bc=bu?Ze:Ie,Xf=S(n-Xf),n=S(Xf-Sr),Le(n)|0?Sr=n:Sr=S(xu(S(Kp(n,Ze)),ye)),z1=S(r-Ye),n=S(z1-ct),Le(n)|0?as=n:as=S(xu(S(Kp(n,Ie)),ke)),ye=bu?Sr:as,hu=bu?as:Sr;e:do if((Pn|0)==1)for(u=0,b=0;;){if(M=Ti(e,b)|0,!u)S(nu(M))>S(0)&&S(fu(M))>S(0)?u=M:u=0;else if(no(M)|0){Be=0;break e}if(b=b+1|0,b>>>0>=Gl>>>0){Be=u;break}}else Be=0;while(0);Zt=Be+500|0,Br=Be+504|0,u=0,M=0,n=S(0),X=0;do{if(b=t[(t[cs>>2]|0)+(X<<2)>>2]|0,(t[b+36>>2]|0)==1)Li(b),h[b+985>>0]=1,h[b+984>>0]=0;else{Qr(b),T&&x0(b,xl(b,Dl)|0,ye,hu,Sr);do if((t[b+24>>2]|0)!=1)if((b|0)==(Be|0)){t[Zt>>2]=t[2278],x[Br>>2]=S(0);break}else{ei(e,b,Sr,s,as,Sr,as,a,Dl,L);break}else M|0&&(t[M+960>>2]=b),t[b+960>>2]=0,M=b,u=(u|0)==0?b:u;while(0);El=S(x[b+504>>2]),n=S(n+S(El+S(Kt(b,Or,Sr))))}X=X+1|0}while((X|0)!=(Gl|0));for(ls=n>ye,sf=Yf&((Pn|0)==2&ls)?1:Pn,uu=(af|0)==1,ea=uu&(T^1),t2=(sf|0)==1,n2=(sf|0)==2,uf=976+(Or<<2)|0,r2=(af|2|0)==2,o2=uu&(Yf^1),Fc=1040+(Bn<<2)|0,Pc=1040+(Or<<2)|0,i2=976+(Bn<<2)|0,u2=(af|0)!=1,ls=Yf&((Pn|0)!=0&ls),os=e+976|0,uu=uu^1,n=ye,Pr=0,ss=0,El=S(0),Kf=S(0);;){e:do if(Pr>>>0>>0)for(Br=t[cs>>2]|0,X=0,Ie=S(0),ke=S(0),Ze=S(0),ye=S(0),b=0,M=0,Be=Pr;;){if(Zt=t[Br+(Be<<2)>>2]|0,(t[Zt+36>>2]|0)!=1&&(t[Zt+940>>2]=ss,(t[Zt+24>>2]|0)!=1)){if(Ye=S(Kt(Zt,Or,Sr)),pi=t[uf>>2]|0,r=S(xn(Zt+380+(pi<<3)|0,fs)),ct=S(x[Zt+504>>2]),r=S(Kp(r,ct)),r=S(xu(S(xn(Zt+364+(pi<<3)|0,fs)),r)),Yf&(X|0)!=0&S(Ye+S(ke+r))>n){a=X,Ye=Ie,Pn=Be;break e}Ye=S(Ye+r),r=S(ke+Ye),Ye=S(Ie+Ye),no(Zt)|0&&(Ze=S(Ze+S(nu(Zt))),ye=S(ye-S(ct*S(fu(Zt))))),M|0&&(t[M+960>>2]=Zt),t[Zt+960>>2]=0,X=X+1|0,M=Zt,b=(b|0)==0?Zt:b}else Ye=Ie,r=ke;if(Be=Be+1|0,Be>>>0>>0)Ie=Ye,ke=r;else{a=X,Pn=Be;break}}else a=0,Ye=S(0),Ze=S(0),ye=S(0),b=0,Pn=Pr;while(0);pi=Ze>S(0)&ZeS(0)&yebc&((Le(bc)|0)^1))n=bc,pi=51;else if(h[(t[os>>2]|0)+3>>0]|0)pi=51;else{if(gn!=S(0)&&S(nu(e))!=S(0)){pi=53;break}n=Ye,pi=53}while(0);if((pi|0)==51&&(pi=0,Le(n)|0?pi=53:(_r=S(n-Ye),kn=n)),(pi|0)==53&&(pi=0,Ye>2]|0,Be=_rS(0),ke=S(_r/gn),Ze=S(0),Ye=S(0),n=S(0),M=b;do r=S(xn(M+380+(X<<3)|0,fs)),ye=S(xn(M+364+(X<<3)|0,fs)),ye=S(Kp(r,S(xu(ye,S(x[M+504>>2]))))),Be?(r=S(ye*S(fu(M))),r!=S(-0)&&(mn=S(ye-S(ct*r)),B1=S(Kn(M,Or,mn,kn,Sr)),mn!=B1)&&(Ze=S(Ze-S(B1-ye)),n=S(n+r))):Zt&&(Bc=S(nu(M)),Bc!=S(0))&&(mn=S(ye+S(ke*Bc)),U1=S(Kn(M,Or,mn,kn,Sr)),mn!=U1)&&(Ze=S(Ze-S(U1-ye)),Ye=S(Ye-Bc)),M=t[M+960>>2]|0;while((M|0)!=0);if(n=S(Ie+n),ye=S(_r+Ze),b1)n=S(0);else{ct=S(gn+Ye),Be=t[uf>>2]|0,Zt=yeS(0),ct=S(ye/ct),n=S(0);do{mn=S(xn(b+380+(Be<<3)|0,fs)),Ze=S(xn(b+364+(Be<<3)|0,fs)),Ze=S(Kp(mn,S(xu(Ze,S(x[b+504>>2]))))),Zt?(mn=S(Ze*S(fu(b))),ye=S(-mn),mn!=S(-0)?(mn=S(ke*ye),ye=S(Kn(b,Or,S(Ze+(Br?ye:mn)),kn,Sr))):ye=Ze):X&&(j1=S(nu(b)),j1!=S(0))?ye=S(Kn(b,Or,S(Ze+S(ct*j1)),kn,Sr)):ye=Ze,n=S(n-S(ye-Ze)),Ye=S(Kt(b,Or,Sr)),r=S(Kt(b,Bn,Sr)),ye=S(ye+Ye),x[La>>2]=ye,t[lf>>2]=1,Ze=S(x[b+396>>2]);e:do if(Le(Ze)|0){M=Le(hu)|0;do if(!M){if(ls|(qu(b,Bn,hu)|0|uu)||($u(e,b)|0)!=4||(t[(g0(b,Bn)|0)+4>>2]|0)==3||(t[(_0(b,Bn)|0)+4>>2]|0)==3)break;x[ql>>2]=hu,t[Ns>>2]=1;break e}while(0);if(qu(b,Bn,hu)|0){M=t[b+992+(t[i2>>2]<<2)>>2]|0,mn=S(r+S(xn(M,hu))),x[ql>>2]=mn,M=u2&(t[M+4>>2]|0)==2,t[Ns>>2]=((Le(mn)|0|M)^1)&1;break}else{x[ql>>2]=hu,t[Ns>>2]=M?0:2;break}}else mn=S(ye-Ye),gn=S(mn/Ze),mn=S(Ze*mn),t[Ns>>2]=1,x[ql>>2]=S(r+(bu?gn:mn));while(0);Ln(b,Or,kn,Sr,lf,La),Ln(b,Bn,hu,Sr,Ns,ql);do if(!(qu(b,Bn,hu)|0)&&($u(e,b)|0)==4){if((t[(g0(b,Bn)|0)+4>>2]|0)==3){M=0;break}M=(t[(_0(b,Bn)|0)+4>>2]|0)!=3}else M=0;while(0);mn=S(x[La>>2]),gn=S(x[ql>>2]),Y1=t[lf>>2]|0,a0=t[Ns>>2]|0,Yt(b,bu?mn:gn,bu?gn:mn,Dl,bu?Y1:a0,bu?a0:Y1,Sr,as,T&(M^1),3488,L)|0,h[of>>0]=h[of>>0]|h[b+508>>0],b=t[b+960>>2]|0}while((b|0)!=0)}}else n=S(0);if(n=S(_r+n),a0=n>0]=a0|N[of>>0],n2&n>S(0)?(M=t[uf>>2]|0,(t[e+364+(M<<3)+4>>2]|0)!=0&&(Wl=S(xn(e+364+(M<<3)|0,fs)),Wl>=S(0))?ye=S(xu(S(0),S(Wl-S(kn-n)))):ye=S(0)):ye=n,Zt=Pr>>>0>>0,Zt){Be=t[cs>>2]|0,X=Pr,M=0;do b=t[Be+(X<<2)>>2]|0,t[b+24>>2]|0||(M=((t[(g0(b,Or)|0)+4>>2]|0)==3&1)+M|0,M=M+((t[(_0(b,Or)|0)+4>>2]|0)==3&1)|0),X=X+1|0;while((X|0)!=(Pn|0));M?(Ye=S(0),r=S(0)):pi=101}else pi=101;e:do if((pi|0)==101)switch(pi=0,l2|0){case 1:{M=0,Ye=S(ye*S(.5)),r=S(0);break e}case 2:{M=0,Ye=ye,r=S(0);break e}case 3:{if(a>>>0<=1){M=0,Ye=S(0),r=S(0);break e}r=S((a+-1|0)>>>0),M=0,Ye=S(0),r=S(S(xu(ye,S(0)))/r);break e}case 5:{r=S(ye/S((a+1|0)>>>0)),M=0,Ye=r;break e}case 4:{r=S(ye/S(a>>>0)),M=0,Ye=S(r*S(.5));break e}default:{M=0,Ye=S(0),r=S(0);break e}}while(0);if(n=S(s2+Ye),Zt){Ze=S(ye/S(M|0)),X=t[cs>>2]|0,b=Pr,ye=S(0);do{M=t[X+(b<<2)>>2]|0;e:do if((t[M+36>>2]|0)!=1){switch(t[M+24>>2]|0){case 1:{if(fe(M,Or)|0){if(!T)break e;mn=S(ie(M,Or,kn)),mn=S(mn+S(O0(e,Or))),mn=S(mn+S(Hi(M,Or,Sr))),x[M+400+(t[Pc>>2]<<2)>>2]=mn;break e}break}case 0:if(a0=(t[(g0(M,Or)|0)+4>>2]|0)==3,mn=S(Ze+n),n=a0?mn:n,T&&(a0=M+400+(t[Pc>>2]<<2)|0,x[a0>>2]=S(n+S(x[a0>>2]))),a0=(t[(_0(M,Or)|0)+4>>2]|0)==3,mn=S(Ze+n),n=a0?mn:n,ea){mn=S(r+S(Kt(M,Or,Sr))),ye=hu,n=S(n+S(mn+S(x[M+504>>2])));break e}else{n=S(n+S(r+S(Pe(M,Or,Sr)))),ye=S(xu(ye,S(Pe(M,Bn,Sr))));break e}default:}T&&(mn=S(Ye+S(O0(e,Or))),a0=M+400+(t[Pc>>2]<<2)|0,x[a0>>2]=S(mn+S(x[a0>>2])))}while(0);b=b+1|0}while((b|0)!=(Pn|0))}else ye=S(0);if(r=S(a2+n),r2?Ye=S(S(Kn(e,Bn,S(Vl+ye),Jf,v))-Vl):Ye=hu,Ze=S(S(Kn(e,Bn,S(Vl+(o2?hu:ye)),Jf,v))-Vl),Zt&T){b=Pr;do{X=t[(t[cs>>2]|0)+(b<<2)>>2]|0;do if((t[X+36>>2]|0)!=1){if((t[X+24>>2]|0)==1){if(fe(X,Bn)|0){if(mn=S(ie(X,Bn,hu)),mn=S(mn+S(O0(e,Bn))),mn=S(mn+S(Hi(X,Bn,Sr))),M=t[Fc>>2]|0,x[X+400+(M<<2)>>2]=mn,!(Le(mn)|0))break}else M=t[Fc>>2]|0;mn=S(O0(e,Bn)),x[X+400+(M<<2)>>2]=S(mn+S(Hi(X,Bn,Sr)));break}M=$u(e,X)|0;do if((M|0)==4){if((t[(g0(X,Bn)|0)+4>>2]|0)==3){pi=139;break}if((t[(_0(X,Bn)|0)+4>>2]|0)==3){pi=139;break}if(qu(X,Bn,hu)|0){n=Te;break}Y1=t[X+908+(t[uf>>2]<<2)>>2]|0,t[ql>>2]=Y1,n=S(x[X+396>>2]),a0=Le(n)|0,ye=(t[V>>2]=Y1,S(x[V>>2])),a0?n=Ze:(_r=S(Kt(X,Bn,Sr)),mn=S(ye/n),n=S(n*ye),n=S(_r+(bu?mn:n))),x[La>>2]=n,x[ql>>2]=S(S(Kt(X,Or,Sr))+ye),t[Ns>>2]=1,t[lf>>2]=1,Ln(X,Or,kn,Sr,Ns,ql),Ln(X,Bn,hu,Sr,lf,La),n=S(x[ql>>2]),_r=S(x[La>>2]),mn=bu?n:_r,n=bu?_r:n,a0=((Le(mn)|0)^1)&1,Yt(X,mn,n,Dl,a0,((Le(n)|0)^1)&1,Sr,as,1,3493,L)|0,n=Te}else pi=139;while(0);e:do if((pi|0)==139){pi=0,n=S(Ye-S(Pe(X,Bn,Sr)));do if((t[(g0(X,Bn)|0)+4>>2]|0)==3){if((t[(_0(X,Bn)|0)+4>>2]|0)!=3)break;n=S(Te+S(xu(S(0),S(n*S(.5)))));break e}while(0);if((t[(_0(X,Bn)|0)+4>>2]|0)==3){n=Te;break}if((t[(g0(X,Bn)|0)+4>>2]|0)==3){n=S(Te+S(xu(S(0),n)));break}switch(M|0){case 1:{n=Te;break e}case 2:{n=S(Te+S(n*S(.5)));break e}default:{n=S(Te+n);break e}}}while(0);mn=S(El+n),a0=X+400+(t[Fc>>2]<<2)|0,x[a0>>2]=S(mn+S(x[a0>>2]))}while(0);b=b+1|0}while((b|0)!=(Pn|0))}if(El=S(El+Ze),Kf=S(xu(Kf,r)),a=ss+1|0,Pn>>>0>=Gl>>>0)break;n=kn,Pr=Pn,ss=a}do if(T){if(M=a>>>0>1,!M&&!(Me(e)|0))break;if(!(Le(hu)|0)){n=S(hu-El);e:do switch(t[e+12>>2]|0){case 3:{Te=S(Te+n),ke=S(0);break}case 2:{Te=S(Te+S(n*S(.5))),ke=S(0);break}case 4:{hu>El?ke=S(n/S(a>>>0)):ke=S(0);break}case 7:if(hu>El){Te=S(Te+S(n/S(a<<1>>>0))),ke=S(n/S(a>>>0)),ke=M?ke:S(0);break e}else{Te=S(Te+S(n*S(.5))),ke=S(0);break e}case 6:{ke=S(n/S(ss>>>0)),ke=hu>El&M?ke:S(0);break}default:ke=S(0)}while(0);if(a|0)for(Zt=1040+(Bn<<2)|0,Br=976+(Bn<<2)|0,Be=0,b=0;;){e:do if(b>>>0>>0)for(ye=S(0),Ze=S(0),n=S(0),X=b;;){M=t[(t[cs>>2]|0)+(X<<2)>>2]|0;do if((t[M+36>>2]|0)!=1&&(t[M+24>>2]|0)==0){if((t[M+940>>2]|0)!=(Be|0))break e;if(at(M,Bn)|0&&(mn=S(x[M+908+(t[Br>>2]<<2)>>2]),n=S(xu(n,S(mn+S(Kt(M,Bn,Sr)))))),($u(e,M)|0)!=5)break;Wl=S(mt(M)),Wl=S(Wl+S(Hi(M,0,Sr))),mn=S(x[M+912>>2]),mn=S(S(mn+S(Kt(M,0,Sr)))-Wl),Wl=S(xu(Ze,Wl)),mn=S(xu(ye,mn)),ye=mn,Ze=Wl,n=S(xu(n,S(Wl+mn)))}while(0);if(M=X+1|0,M>>>0>>0)X=M;else{X=M;break}}else Ze=S(0),n=S(0),X=b;while(0);if(ct=S(ke+n),r=Te,Te=S(Te+ct),b>>>0>>0){Ye=S(r+Ze),M=b;do{b=t[(t[cs>>2]|0)+(M<<2)>>2]|0;e:do if((t[b+36>>2]|0)!=1&&(t[b+24>>2]|0)==0)switch($u(e,b)|0){case 1:{mn=S(r+S(Hi(b,Bn,Sr))),x[b+400+(t[Zt>>2]<<2)>>2]=mn;break e}case 3:{mn=S(S(Te-S(A0(b,Bn,Sr)))-S(x[b+908+(t[Br>>2]<<2)>>2])),x[b+400+(t[Zt>>2]<<2)>>2]=mn;break e}case 2:{mn=S(r+S(S(ct-S(x[b+908+(t[Br>>2]<<2)>>2]))*S(.5))),x[b+400+(t[Zt>>2]<<2)>>2]=mn;break e}case 4:{if(mn=S(r+S(Hi(b,Bn,Sr))),x[b+400+(t[Zt>>2]<<2)>>2]=mn,qu(b,Bn,hu)|0||(bu?(ye=S(x[b+908>>2]),n=S(ye+S(Kt(b,Or,Sr))),Ze=ct):(Ze=S(x[b+912>>2]),Ze=S(Ze+S(Kt(b,Bn,Sr))),n=ct,ye=S(x[b+908>>2])),Ci(n,ye)|0&&Ci(Ze,S(x[b+912>>2]))|0))break e;Yt(b,n,Ze,Dl,1,1,Sr,as,1,3501,L)|0;break e}case 5:{x[b+404>>2]=S(S(Ye-S(mt(b)))+S(ie(b,0,hu)));break e}default:break e}while(0);M=M+1|0}while((M|0)!=(X|0))}if(Be=Be+1|0,(Be|0)==(a|0))break;b=X}}}while(0);if(x[e+908>>2]=S(Kn(e,2,Xf,v,v)),x[e+912>>2]=S(Kn(e,0,z1,w,v)),(sf|0)!=0&&(H1=t[e+32>>2]|0,q1=(sf|0)==2,!(q1&(H1|0)!=2))?q1&(H1|0)==2&&(n=S(Qf+kn),n=S(xu(S(Kp(n,S(Qt(e,Or,Kf,fs)))),Qf)),pi=198):(n=S(Kn(e,Or,Kf,fs,v)),pi=198),(pi|0)==198&&(x[e+908+(t[976+(Or<<2)>>2]<<2)>>2]=n),(af|0)!=0&&(V1=t[e+32>>2]|0,G1=(af|0)==2,!(G1&(V1|0)!=2))?G1&(V1|0)==2&&(n=S(Vl+hu),n=S(xu(S(Kp(n,S(Qt(e,Bn,S(Vl+El),Jf)))),Vl)),pi=204):(n=S(Kn(e,Bn,S(Vl+El),Jf,v)),pi=204),(pi|0)==204&&(x[e+908+(t[976+(Bn<<2)>>2]<<2)>>2]=n),T){if((t[W1>>2]|0)==2){b=976+(Bn<<2)|0,X=1040+(Bn<<2)|0,M=0;do Be=Ti(e,M)|0,t[Be+24>>2]|0||(Y1=t[b>>2]|0,mn=S(x[e+908+(Y1<<2)>>2]),a0=Be+400+(t[X>>2]<<2)|0,mn=S(mn-S(x[a0>>2])),x[a0>>2]=S(mn-S(x[Be+908+(Y1<<2)>>2]))),M=M+1|0;while((M|0)!=(Gl|0))}if(u|0){M=bu?sf:s;do An(e,u,Sr,M,as,Dl,L),u=t[u+960>>2]|0;while((u|0)!=0)}if(M=(Or|2|0)==3,b=(Bn|2|0)==3,M|b){u=0;do X=t[(t[cs>>2]|0)+(u<<2)>>2]|0,(t[X+36>>2]|0)!=1&&(M&&Sn(e,X,Or),b&&Sn(e,X,Bn)),u=u+1|0;while((u|0)!=(Gl|0))}}}while(0);y=ff}function Qu(e,n){e=e|0,n=S(n);var r=0;Cn(e,n>=S(0),3147),r=n==S(0),x[e+4>>2]=r?S(0):n}function $r(e,n,r,u){e=e|0,n=S(n),r=S(r),u=u|0;var s=Ct,a=Ct,v=0,w=0,T=0;t[2278]=(t[2278]|0)+1,Qr(e),qu(e,2,n)|0?(s=S(xn(t[e+992>>2]|0,n)),T=1,s=S(s+S(Kt(e,2,n)))):(s=S(xn(e+380|0,n)),s>=S(0)?T=2:(T=((Le(n)|0)^1)&1,s=n)),qu(e,0,r)|0?(a=S(xn(t[e+996>>2]|0,r)),w=1,a=S(a+S(Kt(e,0,n)))):(a=S(xn(e+388|0,r)),a>=S(0)?w=2:(w=((Le(r)|0)^1)&1,a=r)),v=e+976|0,Yt(e,s,a,u,T,w,n,r,1,3189,t[v>>2]|0)|0&&(x0(e,t[e+496>>2]|0,n,r,n),Lu(e,S(x[(t[v>>2]|0)+4>>2]),S(0),S(0)),h[11696]|0)&&mf(e,7)}function Qr(e){e=e|0;var n=0,r=0,u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0;w=y,y=y+32|0,v=w+24|0,a=w+16|0,u=w+8|0,s=w,r=0;do n=e+380+(r<<3)|0,(t[e+380+(r<<3)+4>>2]|0)!=0&&(T=n,L=t[T+4>>2]|0,M=u,t[M>>2]=t[T>>2],t[M+4>>2]=L,M=e+364+(r<<3)|0,L=t[M+4>>2]|0,T=s,t[T>>2]=t[M>>2],t[T+4>>2]=L,t[a>>2]=t[u>>2],t[a+4>>2]=t[u+4>>2],t[v>>2]=t[s>>2],t[v+4>>2]=t[s+4>>2],Bi(a,v)|0)||(n=e+348+(r<<3)|0),t[e+992+(r<<2)>>2]=n,r=r+1|0;while((r|0)!=2);y=w}function qu(e,n,r){e=e|0,n=n|0,r=S(r);var u=0;switch(e=t[e+992+(t[976+(n<<2)>>2]<<2)>>2]|0,t[e+4>>2]|0){case 0:case 3:{e=0;break}case 1:{S(x[e>>2])>2])>2]|0){case 2:{n=S(S(S(x[e>>2])*n)/S(100));break}case 1:{n=S(x[e>>2]);break}default:n=S(ue)}return S(n)}function x0(e,n,r,u,s){e=e|0,n=n|0,r=S(r),u=S(u),s=S(s);var a=0,v=Ct;n=t[e+944>>2]|0?n:1,a=B0(t[e+4>>2]|0,n)|0,n=gf(a,n)|0,r=S(Ar(e,a,r)),u=S(Ar(e,n,u)),v=S(r+S(Hi(e,a,s))),x[e+400+(t[1040+(a<<2)>>2]<<2)>>2]=v,r=S(r+S(A0(e,a,s))),x[e+400+(t[1e3+(a<<2)>>2]<<2)>>2]=r,r=S(u+S(Hi(e,n,s))),x[e+400+(t[1040+(n<<2)>>2]<<2)>>2]=r,s=S(u+S(A0(e,n,s))),x[e+400+(t[1e3+(n<<2)>>2]<<2)>>2]=s}function Lu(e,n,r,u){e=e|0,n=S(n),r=S(r),u=S(u);var s=0,a=0,v=Ct,w=Ct,T=0,L=0,M=Ct,b=0,X=Ct,Be=Ct,Te=Ct,ye=Ct;if(n!=S(0)&&(s=e+400|0,ye=S(x[s>>2]),a=e+404|0,Te=S(x[a>>2]),b=e+416|0,Be=S(x[b>>2]),L=e+420|0,v=S(x[L>>2]),X=S(ye+r),M=S(Te+u),u=S(X+Be),w=S(M+v),T=(t[e+988>>2]|0)==1,x[s>>2]=S(eo(ye,n,0,T)),x[a>>2]=S(eo(Te,n,0,T)),r=S(NE(S(Be*n),S(1))),Ci(r,S(0))|0?a=0:a=(Ci(r,S(1))|0)^1,r=S(NE(S(v*n),S(1))),Ci(r,S(0))|0?s=0:s=(Ci(r,S(1))|0)^1,ye=S(eo(u,n,T&a,T&(a^1))),x[b>>2]=S(ye-S(eo(X,n,0,T))),ye=S(eo(w,n,T&s,T&(s^1))),x[L>>2]=S(ye-S(eo(M,n,0,T))),a=(t[e+952>>2]|0)-(t[e+948>>2]|0)>>2,a|0)){s=0;do Lu(Ti(e,s)|0,n,X,M),s=s+1|0;while((s|0)!=(a|0))}}function ui(e,n,r,u,s){switch(e=e|0,n=n|0,r=r|0,u=u|0,s=s|0,r|0){case 5:case 0:{e=v8(t[489]|0,u,s)|0;break}default:e=FL(u,s)|0}return e|0}function Cl(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0,a=0;s=y,y=y+16|0,a=s,t[a>>2]=u,zs(e,0,n,r,a),y=s}function zs(e,n,r,u,s){if(e=e|0,n=n|0,r=r|0,u=u|0,s=s|0,e=e|0?e:956,I8[t[e+8>>2]&1](e,n,r,u,s)|0,(r|0)==5)$n();else return}function Wu(e,n,r){e=e|0,n=n|0,r=r|0,h[e+n>>0]=r&1}function sa(e,n){e=e|0,n=n|0;var r=0,u=0;t[e>>2]=0,t[e+4>>2]=0,t[e+8>>2]=0,r=n+4|0,u=(t[r>>2]|0)-(t[n>>2]|0)>>2,u|0&&(Xi(e,u),Hs(e,t[n>>2]|0,t[r>>2]|0,u))}function Xi(e,n){e=e|0,n=n|0;var r=0;if((R0(e)|0)>>>0>>0&&di(e),n>>>0>1073741823)$n();else{r=pn(n<<2)|0,t[e+4>>2]=r,t[e>>2]=r,t[e+8>>2]=r+(n<<2);return}}function Hs(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0,u=e+4|0,e=r-n|0,(e|0)>0&&(gr(t[u>>2]|0,n|0,e|0)|0,t[u>>2]=(t[u>>2]|0)+(e>>>2<<2))}function R0(e){return e=e|0,1073741823}function Hi(e,n,r){return e=e|0,n=n|0,r=S(r),qi(n)|0&&(t[e+96>>2]|0)!=0?e=e+92|0:e=pt(e+60|0,t[1040+(n<<2)>>2]|0,992)|0,S(il(e,r))}function A0(e,n,r){return e=e|0,n=n|0,r=S(r),qi(n)|0&&(t[e+104>>2]|0)!=0?e=e+100|0:e=pt(e+60|0,t[1e3+(n<<2)>>2]|0,992)|0,S(il(e,r))}function qi(e){return e=e|0,(e|1|0)==3|0}function il(e,n){return e=e|0,n=S(n),(t[e+4>>2]|0)==3?n=S(0):n=S(xn(e,n)),S(n)}function xl(e,n){return e=e|0,n=n|0,e=t[e>>2]|0,((e|0)==0?(n|0)>1?n:1:e)|0}function B0(e,n){e=e|0,n=n|0;var r=0;e:do if((n|0)==2){switch(e|0){case 2:{e=3;break e}case 3:break;default:{r=4;break e}}e=2}else r=4;while(0);return e|0}function O0(e,n){e=e|0,n=n|0;var r=Ct;return qi(n)|0&&(t[e+312>>2]|0)!=0&&(r=S(x[e+308>>2]),r>=S(0))||(r=S(xu(S(x[(pt(e+276|0,t[1040+(n<<2)>>2]|0,992)|0)>>2]),S(0)))),S(r)}function vo(e,n){e=e|0,n=n|0;var r=Ct;return qi(n)|0&&(t[e+320>>2]|0)!=0&&(r=S(x[e+316>>2]),r>=S(0))||(r=S(xu(S(x[(pt(e+276|0,t[1e3+(n<<2)>>2]|0,992)|0)>>2]),S(0)))),S(r)}function Fu(e,n,r){e=e|0,n=n|0,r=S(r);var u=Ct;return qi(n)|0&&(t[e+240>>2]|0)!=0&&(u=S(xn(e+236|0,r)),u>=S(0))||(u=S(xu(S(xn(pt(e+204|0,t[1040+(n<<2)>>2]|0,992)|0,r)),S(0)))),S(u)}function Ju(e,n,r){e=e|0,n=n|0,r=S(r);var u=Ct;return qi(n)|0&&(t[e+248>>2]|0)!=0&&(u=S(xn(e+244|0,r)),u>=S(0))||(u=S(xu(S(xn(pt(e+204|0,t[1e3+(n<<2)>>2]|0,992)|0,r)),S(0)))),S(u)}function es(e,n,r,u,s,a,v){e=e|0,n=S(n),r=S(r),u=u|0,s=s|0,a=S(a),v=S(v);var w=Ct,T=Ct,L=Ct,M=Ct,b=Ct,X=Ct,Be=0,Te=0,ye=0;ye=y,y=y+16|0,Be=ye,Te=e+964|0,Hu(e,(t[Te>>2]|0)!=0,3519),w=S(Rr(e,2,n)),T=S(Rr(e,0,n)),L=S(Kt(e,2,n)),M=S(Kt(e,0,n)),Le(n)|0?b=n:b=S(xu(S(0),S(S(n-L)-w))),Le(r)|0?X=r:X=S(xu(S(0),S(S(r-M)-T))),(u|0)==1&(s|0)==1?(x[e+908>>2]=S(Kn(e,2,S(n-L),a,a)),n=S(Kn(e,0,S(r-M),v,a))):(b8[t[Te>>2]&1](Be,e,b,u,X,s),b=S(w+S(x[Be>>2])),X=S(n-L),x[e+908>>2]=S(Kn(e,2,(u|2|0)==2?b:X,a,a)),X=S(T+S(x[Be+4>>2])),n=S(r-M),n=S(Kn(e,0,(s|2|0)==2?X:n,v,a))),x[e+912>>2]=n,y=ye}function _s(e,n,r,u,s,a,v){e=e|0,n=S(n),r=S(r),u=u|0,s=s|0,a=S(a),v=S(v);var w=Ct,T=Ct,L=Ct,M=Ct;L=S(Rr(e,2,a)),w=S(Rr(e,0,a)),M=S(Kt(e,2,a)),T=S(Kt(e,0,a)),n=S(n-M),x[e+908>>2]=S(Kn(e,2,(u|2|0)==2?L:n,a,a)),r=S(r-T),x[e+912>>2]=S(Kn(e,0,(s|2|0)==2?w:r,v,a))}function aa(e,n,r,u,s,a,v){e=e|0,n=S(n),r=S(r),u=u|0,s=s|0,a=S(a),v=S(v);var w=0,T=Ct,L=Ct;return w=(u|0)==2,!(n<=S(0)&w)&&!(r<=S(0)&(s|0)==2)&&!((u|0)==1&(s|0)==1)?e=0:(T=S(Kt(e,0,a)),L=S(Kt(e,2,a)),w=n>2]=S(Kn(e,2,w?S(0):n,a,a)),n=S(r-T),w=r>2]=S(Kn(e,0,w?S(0):n,v,a)),e=1),e|0}function gf(e,n){return e=e|0,n=n|0,_n(e)|0?e=B0(2,n)|0:e=0,e|0}function Zu(e,n,r){return e=e|0,n=n|0,r=S(r),r=S(Fu(e,n,r)),S(r+S(O0(e,n)))}function Es(e,n,r){return e=e|0,n=n|0,r=S(r),r=S(Ju(e,n,r)),S(r+S(vo(e,n)))}function Rr(e,n,r){e=e|0,n=n|0,r=S(r);var u=Ct;return u=S(Zu(e,n,r)),S(u+S(Es(e,n,r)))}function no(e){return e=e|0,t[e+24>>2]|0?e=0:S(nu(e))!=S(0)?e=1:e=S(fu(e))!=S(0),e|0}function nu(e){e=e|0;var n=Ct;if(t[e+944>>2]|0){if(n=S(x[e+44>>2]),Le(n)|0)return n=S(x[e+40>>2]),e=n>S(0)&((Le(n)|0)^1),S(e?n:S(0))}else n=S(0);return S(n)}function fu(e){e=e|0;var n=Ct,r=0,u=Ct;do if(t[e+944>>2]|0){if(n=S(x[e+48>>2]),Le(n)|0){if(r=h[(t[e+976>>2]|0)+2>>0]|0,r<<24>>24==0&&(u=S(x[e+40>>2]),u>24?S(1):S(0)}}else n=S(0);while(0);return S(n)}function Li(e){e=e|0;var n=0,r=0;if(jv(e+400|0,0,540)|0,h[e+985>>0]=1,ms(e),r=wu(e)|0,r|0){n=e+948|0,e=0;do Li(t[(t[n>>2]|0)+(e<<2)>>2]|0),e=e+1|0;while((e|0)!=(r|0))}}function ei(e,n,r,u,s,a,v,w,T,L){e=e|0,n=n|0,r=S(r),u=u|0,s=S(s),a=S(a),v=S(v),w=w|0,T=T|0,L=L|0;var M=0,b=Ct,X=0,Be=0,Te=Ct,ye=Ct,Ze=0,Ye=Ct,ct=0,ke=Ct,Ie=0,Zt=0,Br=0,Pn=0,gn=0,_r=0,Pr=0,kn=0,uu=0,os=0;uu=y,y=y+16|0,Br=uu+12|0,Pn=uu+8|0,gn=uu+4|0,_r=uu,kn=B0(t[e+4>>2]|0,T)|0,Ie=qi(kn)|0,b=S(xn(Tn(n)|0,Ie?a:v)),Zt=qu(n,2,a)|0,Pr=qu(n,0,v)|0;do if(!(Le(b)|0)&&!(Le(Ie?r:s)|0)){if(M=n+504|0,!(Le(S(x[M>>2]))|0)&&(!(ir(t[n+976>>2]|0,0)|0)||(t[n+500>>2]|0)==(t[2278]|0)))break;x[M>>2]=S(xu(b,S(Rr(n,kn,a))))}else X=7;while(0);do if((X|0)==7){if(ct=Ie^1,!(ct|Zt^1)){v=S(xn(t[n+992>>2]|0,a)),x[n+504>>2]=S(xu(v,S(Rr(n,2,a))));break}if(!(Ie|Pr^1)){v=S(xn(t[n+996>>2]|0,v)),x[n+504>>2]=S(xu(v,S(Rr(n,0,a))));break}x[Br>>2]=S(ue),x[Pn>>2]=S(ue),t[gn>>2]=0,t[_r>>2]=0,Ye=S(Kt(n,2,a)),ke=S(Kt(n,0,a)),Zt?(Te=S(Ye+S(xn(t[n+992>>2]|0,a))),x[Br>>2]=Te,t[gn>>2]=1,Be=1):(Be=0,Te=S(ue)),Pr?(b=S(ke+S(xn(t[n+996>>2]|0,v))),x[Pn>>2]=b,t[_r>>2]=1,M=1):(M=0,b=S(ue)),X=t[e+32>>2]|0,Ie&(X|0)==2?X=2:Le(Te)|0&&!(Le(r)|0)&&(x[Br>>2]=r,t[gn>>2]=2,Be=2,Te=r),!((X|0)==2&ct)&&Le(b)|0&&!(Le(s)|0)&&(x[Pn>>2]=s,t[_r>>2]=2,M=2,b=s),ye=S(x[n+396>>2]),Ze=Le(ye)|0;do if(Ze)X=Be;else{if((Be|0)==1&ct){x[Pn>>2]=S(S(Te-Ye)/ye),t[_r>>2]=1,M=1,X=1;break}Ie&(M|0)==1?(x[Br>>2]=S(ye*S(b-ke)),t[gn>>2]=1,M=1,X=1):X=Be}while(0);os=Le(r)|0,Be=($u(e,n)|0)!=4,!(Ie|Zt|((u|0)!=1|os)|(Be|(X|0)==1))&&(x[Br>>2]=r,t[gn>>2]=1,!Ze)&&(x[Pn>>2]=S(S(r-Ye)/ye),t[_r>>2]=1,M=1),!(Pr|ct|((w|0)!=1|(Le(s)|0))|(Be|(M|0)==1))&&(x[Pn>>2]=s,t[_r>>2]=1,!Ze)&&(x[Br>>2]=S(ye*S(s-ke)),t[gn>>2]=1),Ln(n,2,a,a,gn,Br),Ln(n,0,v,a,_r,Pn),r=S(x[Br>>2]),s=S(x[Pn>>2]),Yt(n,r,s,T,t[gn>>2]|0,t[_r>>2]|0,a,v,0,3565,L)|0,v=S(x[n+908+(t[976+(kn<<2)>>2]<<2)>>2]),x[n+504>>2]=S(xu(v,S(Rr(n,kn,a))))}while(0);t[n+500>>2]=t[2278],y=uu}function Kn(e,n,r,u,s){return e=e|0,n=n|0,r=S(r),u=S(u),s=S(s),u=S(Qt(e,n,r,u)),S(xu(u,S(Rr(e,n,s))))}function $u(e,n){return e=e|0,n=n|0,n=n+20|0,n=t[((t[n>>2]|0)==0?e+16|0:n)>>2]|0,(n|0)==5&&_n(t[e+4>>2]|0)|0&&(n=1),n|0}function g0(e,n){return e=e|0,n=n|0,qi(n)|0&&(t[e+96>>2]|0)!=0?n=4:n=t[1040+(n<<2)>>2]|0,e+60+(n<<3)|0}function _0(e,n){return e=e|0,n=n|0,qi(n)|0&&(t[e+104>>2]|0)!=0?n=5:n=t[1e3+(n<<2)>>2]|0,e+60+(n<<3)|0}function Ln(e,n,r,u,s,a){switch(e=e|0,n=n|0,r=S(r),u=S(u),s=s|0,a=a|0,r=S(xn(e+380+(t[976+(n<<2)>>2]<<3)|0,r)),r=S(r+S(Kt(e,n,u))),t[s>>2]|0){case 2:case 1:{s=Le(r)|0,u=S(x[a>>2]),x[a>>2]=s|u>2]=2,x[a>>2]=r);break}default:}}function fe(e,n){return e=e|0,n=n|0,e=e+132|0,qi(n)|0&&(t[(pt(e,4,948)|0)+4>>2]|0)!=0?e=1:e=(t[(pt(e,t[1040+(n<<2)>>2]|0,948)|0)+4>>2]|0)!=0,e|0}function ie(e,n,r){e=e|0,n=n|0,r=S(r);var u=0,s=0;return e=e+132|0,qi(n)|0&&(u=pt(e,4,948)|0,(t[u+4>>2]|0)!=0)?s=4:(u=pt(e,t[1040+(n<<2)>>2]|0,948)|0,t[u+4>>2]|0?s=4:r=S(0)),(s|0)==4&&(r=S(xn(u,r))),S(r)}function Pe(e,n,r){e=e|0,n=n|0,r=S(r);var u=Ct;return u=S(x[e+908+(t[976+(n<<2)>>2]<<2)>>2]),u=S(u+S(Hi(e,n,r))),S(u+S(A0(e,n,r)))}function Me(e){e=e|0;var n=0,r=0,u=0;e:do if(_n(t[e+4>>2]|0)|0)n=0;else if((t[e+16>>2]|0)!=5)if(r=wu(e)|0,!r)n=0;else for(n=0;;){if(u=Ti(e,n)|0,(t[u+24>>2]|0)==0&&(t[u+20>>2]|0)==5){n=1;break e}if(n=n+1|0,n>>>0>=r>>>0){n=0;break}}else n=1;while(0);return n|0}function at(e,n){e=e|0,n=n|0;var r=Ct;return r=S(x[e+908+(t[976+(n<<2)>>2]<<2)>>2]),r>=S(0)&((Le(r)|0)^1)|0}function mt(e){e=e|0;var n=Ct,r=0,u=0,s=0,a=0,v=0,w=0,T=Ct;if(r=t[e+968>>2]|0,r)T=S(x[e+908>>2]),n=S(x[e+912>>2]),n=S(N8[r&0](e,T,n)),Hu(e,(Le(n)|0)^1,3573);else{a=wu(e)|0;do if(a|0){for(r=0,s=0;;){if(u=Ti(e,s)|0,t[u+940>>2]|0){v=8;break}if((t[u+24>>2]|0)!=1)if(w=($u(e,u)|0)==5,w){r=u;break}else r=(r|0)==0?u:r;if(s=s+1|0,s>>>0>=a>>>0){v=8;break}}if((v|0)==8&&!r)break;return n=S(mt(r)),S(n+S(x[r+404>>2]))}while(0);n=S(x[e+912>>2])}return S(n)}function Qt(e,n,r,u){e=e|0,n=n|0,r=S(r),u=S(u);var s=Ct,a=0;return _n(n)|0?(n=1,a=3):qi(n)|0?(n=0,a=3):(u=S(ue),s=S(ue)),(a|0)==3&&(s=S(xn(e+364+(n<<3)|0,u)),u=S(xn(e+380+(n<<3)|0,u))),a=u=S(0)&((Le(u)|0)^1)),r=a?u:r,a=s>=S(0)&((Le(s)|0)^1)&r>2]|0,a)|0,Te=gf(Ze,a)|0,ye=qi(Ze)|0,b=S(Kt(n,2,r)),X=S(Kt(n,0,r)),qu(n,2,r)|0?w=S(b+S(xn(t[n+992>>2]|0,r))):fe(n,2)|0&&Ut(n,2)|0?(w=S(x[e+908>>2]),T=S(O0(e,2)),T=S(w-S(T+S(vo(e,2)))),w=S(ie(n,2,r)),w=S(Kn(n,2,S(T-S(w+S(Fi(n,2,r)))),r,r))):w=S(ue),qu(n,0,s)|0?T=S(X+S(xn(t[n+996>>2]|0,s))):fe(n,0)|0&&Ut(n,0)|0?(T=S(x[e+912>>2]),ct=S(O0(e,0)),ct=S(T-S(ct+S(vo(e,0)))),T=S(ie(n,0,s)),T=S(Kn(n,0,S(ct-S(T+S(Fi(n,0,s)))),s,r))):T=S(ue),L=Le(w)|0,M=Le(T)|0;do if(L^M&&(Be=S(x[n+396>>2]),!(Le(Be)|0)))if(L){w=S(b+S(S(T-X)*Be));break}else{ct=S(X+S(S(w-b)/Be)),T=M?ct:T;break}while(0);M=Le(w)|0,L=Le(T)|0,M|L&&(ke=(M^1)&1,u=r>S(0)&((u|0)!=0&M),w=ye?w:u?r:w,Yt(n,w,T,a,ye?ke:u?2:ke,M&(L^1)&1,w,T,0,3623,v)|0,w=S(x[n+908>>2]),w=S(w+S(Kt(n,2,r))),T=S(x[n+912>>2]),T=S(T+S(Kt(n,0,r)))),Yt(n,w,T,a,1,1,w,T,1,3635,v)|0,Ut(n,Ze)|0&&!(fe(n,Ze)|0)?(ke=t[976+(Ze<<2)>>2]|0,ct=S(x[e+908+(ke<<2)>>2]),ct=S(ct-S(x[n+908+(ke<<2)>>2])),ct=S(ct-S(vo(e,Ze))),ct=S(ct-S(A0(n,Ze,r))),ct=S(ct-S(Fi(n,Ze,ye?r:s))),x[n+400+(t[1040+(Ze<<2)>>2]<<2)>>2]=ct):Ye=21;do if((Ye|0)==21){if(!(fe(n,Ze)|0)&&(t[e+8>>2]|0)==1){ke=t[976+(Ze<<2)>>2]|0,ct=S(x[e+908+(ke<<2)>>2]),ct=S(S(ct-S(x[n+908+(ke<<2)>>2]))*S(.5)),x[n+400+(t[1040+(Ze<<2)>>2]<<2)>>2]=ct;break}!(fe(n,Ze)|0)&&(t[e+8>>2]|0)==2&&(ke=t[976+(Ze<<2)>>2]|0,ct=S(x[e+908+(ke<<2)>>2]),ct=S(ct-S(x[n+908+(ke<<2)>>2])),x[n+400+(t[1040+(Ze<<2)>>2]<<2)>>2]=ct)}while(0);Ut(n,Te)|0&&!(fe(n,Te)|0)?(ke=t[976+(Te<<2)>>2]|0,ct=S(x[e+908+(ke<<2)>>2]),ct=S(ct-S(x[n+908+(ke<<2)>>2])),ct=S(ct-S(vo(e,Te))),ct=S(ct-S(A0(n,Te,r))),ct=S(ct-S(Fi(n,Te,ye?s:r))),x[n+400+(t[1040+(Te<<2)>>2]<<2)>>2]=ct):Ye=30;do if((Ye|0)==30&&!(fe(n,Te)|0)){if(($u(e,n)|0)==2){ke=t[976+(Te<<2)>>2]|0,ct=S(x[e+908+(ke<<2)>>2]),ct=S(S(ct-S(x[n+908+(ke<<2)>>2]))*S(.5)),x[n+400+(t[1040+(Te<<2)>>2]<<2)>>2]=ct;break}ke=($u(e,n)|0)==3,ke^(t[e+28>>2]|0)==2&&(ke=t[976+(Te<<2)>>2]|0,ct=S(x[e+908+(ke<<2)>>2]),ct=S(ct-S(x[n+908+(ke<<2)>>2])),x[n+400+(t[1040+(Te<<2)>>2]<<2)>>2]=ct)}while(0)}function Sn(e,n,r){e=e|0,n=n|0,r=r|0;var u=Ct,s=0;s=t[976+(r<<2)>>2]|0,u=S(x[n+908+(s<<2)>>2]),u=S(S(x[e+908+(s<<2)>>2])-u),u=S(u-S(x[n+400+(t[1040+(r<<2)>>2]<<2)>>2])),x[n+400+(t[1e3+(r<<2)>>2]<<2)>>2]=u}function _n(e){return e=e|0,(e|1|0)==1|0}function Tn(e){e=e|0;var n=Ct;switch(t[e+56>>2]|0){case 0:case 3:{n=S(x[e+40>>2]),n>S(0)&((Le(n)|0)^1)?e=h[(t[e+976>>2]|0)+2>>0]|0?1056:992:e=1056;break}default:e=e+52|0}return e|0}function ir(e,n){return e=e|0,n=n|0,(h[e+n>>0]|0)!=0|0}function Ut(e,n){return e=e|0,n=n|0,e=e+132|0,qi(n)|0&&(t[(pt(e,5,948)|0)+4>>2]|0)!=0?e=1:e=(t[(pt(e,t[1e3+(n<<2)>>2]|0,948)|0)+4>>2]|0)!=0,e|0}function Fi(e,n,r){e=e|0,n=n|0,r=S(r);var u=0,s=0;return e=e+132|0,qi(n)|0&&(u=pt(e,5,948)|0,(t[u+4>>2]|0)!=0)?s=4:(u=pt(e,t[1e3+(n<<2)>>2]|0,948)|0,t[u+4>>2]|0?s=4:r=S(0)),(s|0)==4&&(r=S(xn(u,r))),S(r)}function Ar(e,n,r){return e=e|0,n=n|0,r=S(r),fe(e,n)|0?r=S(ie(e,n,r)):r=S(-S(Fi(e,n,r))),S(r)}function mr(e){return e=S(e),x[V>>2]=e,t[V>>2]|0|0}function K(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=u;do if(n)if(n>>>0>1073741823)$n();else{s=pn(n<<2)|0;break}else s=0;while(0);t[e>>2]=s,u=s+(r<<2)|0,t[e+8>>2]=u,t[e+4>>2]=u,t[e+12>>2]=s+(n<<2)}function ti(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0;u=t[e>>2]|0,v=e+4|0,a=n+4|0,s=(t[v>>2]|0)-u|0,r=(t[a>>2]|0)+(0-(s>>2)<<2)|0,t[a>>2]=r,(s|0)>0?(gr(r|0,u|0,s|0)|0,u=a,r=t[a>>2]|0):u=a,a=t[e>>2]|0,t[e>>2]=r,t[u>>2]=a,a=n+8|0,s=t[v>>2]|0,t[v>>2]=t[a>>2],t[a>>2]=s,a=e+8|0,v=n+12|0,e=t[a>>2]|0,t[a>>2]=t[v>>2],t[v>>2]=e,t[n>>2]=t[u>>2]}function ni(e){e=e|0;var n=0,r=0,u=0;n=t[e+4>>2]|0,r=e+8|0,u=t[r>>2]|0,(u|0)!=(n|0)&&(t[r>>2]=u+(~((u+-4-n|0)>>>2)<<2)),e=t[e>>2]|0,e|0&&Et(e)}function Wr(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0,a=0,v=0,w=0;if(v=e+4|0,w=t[v>>2]|0,s=w-u|0,a=s>>2,e=n+(a<<2)|0,e>>>0>>0){u=w;do t[u>>2]=t[e>>2],e=e+4|0,u=(t[v>>2]|0)+4|0,t[v>>2]=u;while(e>>>0>>0)}a|0&&ky(w+(0-a<<2)|0,n|0,s|0)|0}function ft(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0,T=0;return w=n+4|0,T=t[w>>2]|0,s=t[e>>2]|0,v=r,a=v-s|0,u=T+(0-(a>>2)<<2)|0,t[w>>2]=u,(a|0)>0&&gr(u|0,s|0,a|0)|0,s=e+4|0,a=n+8|0,u=(t[s>>2]|0)-v|0,(u|0)>0&&(gr(t[a>>2]|0,r|0,u|0)|0,t[a>>2]=(t[a>>2]|0)+(u>>>2<<2)),v=t[e>>2]|0,t[e>>2]=t[w>>2],t[w>>2]=v,v=t[s>>2]|0,t[s>>2]=t[a>>2],t[a>>2]=v,v=e+8|0,r=n+12|0,e=t[v>>2]|0,t[v>>2]=t[r>>2],t[r>>2]=e,t[n>>2]=t[w>>2],T|0}function Di(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0;if(v=t[n>>2]|0,a=t[r>>2]|0,(v|0)!=(a|0)){s=e+8|0,r=((a+-4-v|0)>>>2)+1|0,e=v,u=t[s>>2]|0;do t[u>>2]=t[e>>2],u=(t[s>>2]|0)+4|0,t[s>>2]=u,e=e+4|0;while((e|0)!=(a|0));t[n>>2]=v+(r<<2)}}function ru(){Se()}function E0(){var e=0;return e=pn(4)|0,Un(e),e|0}function Un(e){e=e|0,t[e>>2]=v0()|0}function e0(e){e=e|0,e|0&&(ro(e),Et(e))}function ro(e){e=e|0,J0(t[e>>2]|0)}function mo(e,n,r){e=e|0,n=n|0,r=r|0,Wu(t[e>>2]|0,n,r)}function t0(e,n){e=e|0,n=S(n),Qu(t[e>>2]|0,n)}function jo(e,n){return e=e|0,n=n|0,ir(t[e>>2]|0,n)|0}function io(){var e=0;return e=pn(8)|0,Ba(e,0),e|0}function Ba(e,n){e=e|0,n=n|0,n?n=Yn(t[n>>2]|0)|0:n=cr()|0,t[e>>2]=n,t[e+4>>2]=0,ba(n,e)}function _f(e){e=e|0;var n=0;return n=pn(8)|0,Ba(n,e),n|0}function fc(e){e=e|0,e|0&&(Ds(e),Et(e))}function Ds(e){e=e|0;var n=0;ju(t[e>>2]|0),n=e+4|0,e=t[n>>2]|0,t[n>>2]=0,e|0&&(fa(e),Et(e))}function fa(e){e=e|0,U0(e)}function U0(e){e=e|0,e=t[e>>2]|0,e|0&&qr(e|0)}function cc(e){return e=e|0,Bs(e)|0}function Ua(e){e=e|0;var n=0,r=0;r=e+4|0,n=t[r>>2]|0,t[r>>2]=0,n|0&&(fa(n),Et(n)),po(t[e>>2]|0)}function _2(e,n){e=e|0,n=n|0,oa(t[e>>2]|0,t[n>>2]|0)}function nd(e,n){e=e|0,n=n|0,$(t[e>>2]|0,n)}function rd(e,n,r){e=e|0,n=n|0,r=+r,dr(t[e>>2]|0,n,S(r))}function yo(e,n,r){e=e|0,n=n|0,r=+r,er(t[e>>2]|0,n,S(r))}function qc(e,n){e=e|0,n=n|0,H(t[e>>2]|0,n)}function Rl(e,n){e=e|0,n=n|0,ee(t[e>>2]|0,n)}function ul(e,n){e=e|0,n=n|0,_e(t[e>>2]|0,n)}function E2(e,n){e=e|0,n=n|0,m0(t[e>>2]|0,n)}function qs(e,n){e=e|0,n=n|0,Je(t[e>>2]|0,n)}function Al(e,n){e=e|0,n=n|0,zi(t[e>>2]|0,n)}function id(e,n,r){e=e|0,n=n|0,r=+r,Rn(t[e>>2]|0,n,S(r))}function zo(e,n,r){e=e|0,n=n|0,r=+r,Nr(t[e>>2]|0,n,S(r))}function ja(e,n){e=e|0,n=n|0,Lr(t[e>>2]|0,n)}function za(e,n){e=e|0,n=n|0,oe(t[e>>2]|0,n)}function Ha(e,n){e=e|0,n=n|0,rt(t[e>>2]|0,n)}function ca(e,n){e=e|0,n=+n,kt(t[e>>2]|0,S(n))}function ws(e,n){e=e|0,n=+n,rn(t[e>>2]|0,S(n))}function Ss(e,n){e=e|0,n=+n,Ft(t[e>>2]|0,S(n))}function ts(e,n){e=e|0,n=+n,bt(t[e>>2]|0,S(n))}function Ho(e,n){e=e|0,n=+n,sn(t[e>>2]|0,S(n))}function Ef(e,n){e=e|0,n=+n,fn(t[e>>2]|0,S(n))}function ol(e,n){e=e|0,n=+n,Jn(t[e>>2]|0,S(n))}function Vu(e){e=e|0,wr(t[e>>2]|0)}function qa(e,n){e=e|0,n=+n,ku(t[e>>2]|0,S(n))}function n0(e,n){e=e|0,n=+n,T0(t[e>>2]|0,S(n))}function j0(e){e=e|0,Z0(t[e>>2]|0)}function Df(e,n){e=e|0,n=+n,gi(t[e>>2]|0,S(n))}function Wc(e,n){e=e|0,n=+n,Po(t[e>>2]|0,S(n))}function dc(e,n){e=e|0,n=+n,hf(t[e>>2]|0,S(n))}function Ol(e,n){e=e|0,n=+n,Tl(t[e>>2]|0,S(n))}function Ts(e,n){e=e|0,n=+n,Io(t[e>>2]|0,S(n))}function da(e,n){e=e|0,n=+n,ys(t[e>>2]|0,S(n))}function ud(e,n){e=e|0,n=+n,bo(t[e>>2]|0,S(n))}function pa(e,n){e=e|0,n=+n,Bo(t[e>>2]|0,S(n))}function pc(e,n){e=e|0,n=+n,Xu(t[e>>2]|0,S(n))}function Vc(e,n,r){e=e|0,n=n|0,r=+r,It(t[e>>2]|0,n,S(r))}function Wi(e,n,r){e=e|0,n=n|0,r=+r,ut(t[e>>2]|0,n,S(r))}function _(e,n,r){e=e|0,n=n|0,r=+r,wt(t[e>>2]|0,n,S(r))}function g(e){return e=e|0,Ne(t[e>>2]|0)|0}function A(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0;u=y,y=y+16|0,s=u,Cr(s,t[n>>2]|0,r),P(e,s),y=u}function P(e,n){e=e|0,n=n|0,B(e,t[n+4>>2]|0,+S(x[n>>2]))}function B(e,n,r){e=e|0,n=n|0,r=+r,t[e>>2]=n,j[e+8>>3]=r}function Z(e){return e=e|0,Y(t[e>>2]|0)|0}function de(e){return e=e|0,Ce(t[e>>2]|0)|0}function yt(e){return e=e|0,Oe(t[e>>2]|0)|0}function Rt(e){return e=e|0,Us(t[e>>2]|0)|0}function Nt(e){return e=e|0,vt(t[e>>2]|0)|0}function xr(e){return e=e|0,U(t[e>>2]|0)|0}function r0(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0;u=y,y=y+16|0,s=u,y0(s,t[n>>2]|0,r),P(e,s),y=u}function cu(e){return e=e|0,qe(t[e>>2]|0)|0}function z0(e){return e=e|0,xt(t[e>>2]|0)|0}function Ml(e,n){e=e|0,n=n|0;var r=0,u=0;r=y,y=y+16|0,u=r,Dn(u,t[n>>2]|0),P(e,u),y=r}function i0(e){return e=e|0,+ +S(pf(t[e>>2]|0))}function Ge(e){return e=e|0,+ +S(bs(t[e>>2]|0))}function je(e,n){e=e|0,n=n|0;var r=0,u=0;r=y,y=y+16|0,u=r,au(u,t[n>>2]|0),P(e,u),y=r}function st(e,n){e=e|0,n=n|0;var r=0,u=0;r=y,y=y+16|0,u=r,Nu(u,t[n>>2]|0),P(e,u),y=r}function $t(e,n){e=e|0,n=n|0;var r=0,u=0;r=y,y=y+16|0,u=r,rl(u,t[n>>2]|0),P(e,u),y=r}function Wn(e,n){e=e|0,n=n|0;var r=0,u=0;r=y,y=y+16|0,u=r,vf(u,t[n>>2]|0),P(e,u),y=r}function oi(e,n){e=e|0,n=n|0;var r=0,u=0;r=y,y=y+16|0,u=r,js(u,t[n>>2]|0),P(e,u),y=r}function ur(e,n){e=e|0,n=n|0;var r=0,u=0;r=y,y=y+16|0,u=r,gs(u,t[n>>2]|0),P(e,u),y=r}function ai(e){return e=e|0,+ +S(Su(t[e>>2]|0))}function Qi(e,n){return e=e|0,n=n|0,+ +S(un(t[e>>2]|0,n))}function Vr(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0;u=y,y=y+16|0,s=u,et(s,t[n>>2]|0,r),P(e,s),y=u}function Tu(e,n,r){e=e|0,n=n|0,r=r|0,Ia(t[e>>2]|0,t[n>>2]|0,r)}function Wa(e,n){e=e|0,n=n|0,Mu(t[e>>2]|0,t[n>>2]|0)}function Va(e){return e=e|0,wu(t[e>>2]|0)|0}function od(e){return e=e|0,e=si(t[e>>2]|0)|0,e?e=cc(e)|0:e=0,e|0}function D2(e,n){return e=e|0,n=n|0,e=Ti(t[e>>2]|0,n)|0,e?e=cc(e)|0:e=0,e|0}function w2(e,n){e=e|0,n=n|0;var r=0,u=0;u=pn(4)|0,wf(u,n),r=e+4|0,n=t[r>>2]|0,t[r>>2]=u,n|0&&(fa(n),Et(n)),ua(t[e>>2]|0,1)}function wf(e,n){e=e|0,n=n|0,sl(e,n)}function ld(e,n,r,u,s,a){e=e|0,n=n|0,r=S(r),u=u|0,s=S(s),a=a|0;var v=0,w=0;v=y,y=y+16|0,w=v,hh(w,Bs(n)|0,+r,u,+s,a),x[e>>2]=S(+j[w>>3]),x[e+4>>2]=S(+j[w+8>>3]),y=v}function hh(e,n,r,u,s,a){e=e|0,n=n|0,r=+r,u=u|0,s=+s,a=a|0;var v=0,w=0,T=0,L=0,M=0;v=y,y=y+32|0,M=v+8|0,L=v+20|0,T=v,w=v+16|0,j[M>>3]=r,t[L>>2]=u,j[T>>3]=s,t[w>>2]=a,Gc(e,t[n+4>>2]|0,M,L,T,w),y=v}function Gc(e,n,r,u,s,a){e=e|0,n=n|0,r=r|0,u=u|0,s=s|0,a=a|0;var v=0,w=0;v=y,y=y+16|0,w=v,Ma(w),n=go(n)|0,vh(e,n,+j[r>>3],t[u>>2]|0,+j[s>>3],t[a>>2]|0),ka(w),y=v}function go(e){return e=e|0,t[e>>2]|0}function vh(e,n,r,u,s,a){e=e|0,n=n|0,r=+r,u=u|0,s=+s,a=a|0;var v=0;v=_o(mh()|0)|0,r=+kl(r),u=sd(u)|0,s=+kl(s),ad(e,Xr(0,v|0,n|0,+r,u|0,+s,sd(a)|0)|0)}function mh(){var e=0;return h[7608]|0||(Kc(9120),e=7608,t[e>>2]=1,t[e+4>>2]=0),9120}function _o(e){return e=e|0,t[e+8>>2]|0}function kl(e){return e=+e,+ +Ga(e)}function sd(e){return e=e|0,cd(e)|0}function ad(e,n){e=e|0,n=n|0;var r=0,u=0,s=0;s=y,y=y+32|0,r=s,u=n,u&1?(S2(r,0),eu(u|0,r|0)|0,Yc(e,r),Ir(r)):(t[e>>2]=t[n>>2],t[e+4>>2]=t[n+4>>2],t[e+8>>2]=t[n+8>>2],t[e+12>>2]=t[n+12>>2]),y=s}function S2(e,n){e=e|0,n=n|0,fd(e,n),t[e+8>>2]=0,h[e+24>>0]=0}function Yc(e,n){e=e|0,n=n|0,n=n+8|0,t[e>>2]=t[n>>2],t[e+4>>2]=t[n+4>>2],t[e+8>>2]=t[n+8>>2],t[e+12>>2]=t[n+12>>2]}function Ir(e){e=e|0,h[e+24>>0]=0}function fd(e,n){e=e|0,n=n|0,t[e>>2]=n}function cd(e){return e=e|0,e|0}function Ga(e){return e=+e,+e}function Kc(e){e=e|0,ll(e,T2()|0,4)}function T2(){return 1064}function ll(e,n,r){e=e|0,n=n|0,r=r|0,t[e>>2]=n,t[e+4>>2]=r,t[e+8>>2]=Bt(n|0,r+1|0)|0}function sl(e,n){e=e|0,n=n|0,n=t[n>>2]|0,t[e>>2]=n,Ri(n|0)}function yh(e){e=e|0;var n=0,r=0;r=e+4|0,n=t[r>>2]|0,t[r>>2]=0,n|0&&(fa(n),Et(n)),ua(t[e>>2]|0,0)}function Sf(e){e=e|0,Jr(t[e>>2]|0)}function Xc(e){return e=e|0,Zl(t[e>>2]|0)|0}function C2(e,n,r,u){e=e|0,n=+n,r=+r,u=u|0,$r(t[e>>2]|0,S(n),S(r),u)}function gh(e){return e=e|0,+ +S(_i(t[e>>2]|0))}function al(e){return e=e|0,+ +S($0(t[e>>2]|0))}function ha(e){return e=e|0,+ +S(C0(t[e>>2]|0))}function x2(e){return e=e|0,+ +S(Uo(t[e>>2]|0))}function R2(e){return e=e|0,+ +S(la(t[e>>2]|0))}function hc(e){return e=e|0,+ +S($l(t[e>>2]|0))}function _h(e,n){e=e|0,n=n|0,j[e>>3]=+S(_i(t[n>>2]|0)),j[e+8>>3]=+S($0(t[n>>2]|0)),j[e+16>>3]=+S(C0(t[n>>2]|0)),j[e+24>>3]=+S(Uo(t[n>>2]|0)),j[e+32>>3]=+S(la(t[n>>2]|0)),j[e+40>>3]=+S($l(t[n>>2]|0))}function A2(e,n){return e=e|0,n=n|0,+ +S(tu(t[e>>2]|0,n))}function dd(e,n){return e=e|0,n=n|0,+ +S(Zr(t[e>>2]|0,n))}function Qc(e,n){return e=e|0,n=n|0,+ +S(ho(t[e>>2]|0,n))}function Jc(){return Pa()|0}function Ws(){O2(),va(),Zc(),vc(),mc(),pd()}function O2(){E7(11713,4938,1)}function va(){UA(10448)}function Zc(){EA(10408)}function vc(){qR(10324)}function mc(){nE(10096)}function pd(){Eh(9132)}function Eh(e){e=e|0;var n=0,r=0,u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0,b=0,X=0,Be=0,Te=0,ye=0,Ze=0,Ye=0,ct=0,ke=0,Ie=0,Zt=0,Br=0,Pn=0,gn=0,_r=0,Pr=0,kn=0,uu=0,os=0,ls=0,ss=0,ea=0,t2=0,n2=0,uf=0,r2=0,Fc=0,Pc=0,i2=0,u2=0,o2=0,pi=0,of=0,l2=0,Yf=0,s2=0,a2=0,Ic=0,bc=0,Kf=0,ql=0,La=0,Ns=0,lf=0,b1=0,B1=0,Bc=0,U1=0,j1=0,Wl=0,El=0,sf=0,hu=0,z1=0,as=0,Xf=0,fs=0,Qf=0,H1=0,q1=0,Jf=0,Vl=0,af=0,W1=0,V1=0,G1=0,Sr=0,bu=0,Dl=0,cs=0,Gl=0,Or=0,Bn=0,ff=0;n=y,y=y+672|0,r=n+656|0,ff=n+648|0,Bn=n+640|0,Or=n+632|0,Gl=n+624|0,cs=n+616|0,Dl=n+608|0,bu=n+600|0,Sr=n+592|0,G1=n+584|0,V1=n+576|0,W1=n+568|0,af=n+560|0,Vl=n+552|0,Jf=n+544|0,q1=n+536|0,H1=n+528|0,Qf=n+520|0,fs=n+512|0,Xf=n+504|0,as=n+496|0,z1=n+488|0,hu=n+480|0,sf=n+472|0,El=n+464|0,Wl=n+456|0,j1=n+448|0,U1=n+440|0,Bc=n+432|0,B1=n+424|0,b1=n+416|0,lf=n+408|0,Ns=n+400|0,La=n+392|0,ql=n+384|0,Kf=n+376|0,bc=n+368|0,Ic=n+360|0,a2=n+352|0,s2=n+344|0,Yf=n+336|0,l2=n+328|0,of=n+320|0,pi=n+312|0,o2=n+304|0,u2=n+296|0,i2=n+288|0,Pc=n+280|0,Fc=n+272|0,r2=n+264|0,uf=n+256|0,n2=n+248|0,t2=n+240|0,ea=n+232|0,ss=n+224|0,ls=n+216|0,os=n+208|0,uu=n+200|0,kn=n+192|0,Pr=n+184|0,_r=n+176|0,gn=n+168|0,Pn=n+160|0,Br=n+152|0,Zt=n+144|0,Ie=n+136|0,ke=n+128|0,ct=n+120|0,Ye=n+112|0,Ze=n+104|0,ye=n+96|0,Te=n+88|0,Be=n+80|0,X=n+72|0,b=n+64|0,M=n+56|0,L=n+48|0,T=n+40|0,w=n+32|0,v=n+24|0,a=n+16|0,s=n+8|0,u=n,Tf(e,3646),$c(e,3651,2)|0,Dh(e,3665,2)|0,sm(e,3682,18)|0,t[ff>>2]=19,t[ff+4>>2]=0,t[r>>2]=t[ff>>2],t[r+4>>2]=t[ff+4>>2],Vs(e,3690,r)|0,t[Bn>>2]=1,t[Bn+4>>2]=0,t[r>>2]=t[Bn>>2],t[r+4>>2]=t[Bn+4>>2],ma(e,3696,r)|0,t[Or>>2]=2,t[Or+4>>2]=0,t[r>>2]=t[Or>>2],t[r+4>>2]=t[Or+4>>2],iu(e,3706,r)|0,t[Gl>>2]=1,t[Gl+4>>2]=0,t[r>>2]=t[Gl>>2],t[r+4>>2]=t[Gl+4>>2],M0(e,3722,r)|0,t[cs>>2]=2,t[cs+4>>2]=0,t[r>>2]=t[cs>>2],t[r+4>>2]=t[cs+4>>2],M0(e,3734,r)|0,t[Dl>>2]=3,t[Dl+4>>2]=0,t[r>>2]=t[Dl>>2],t[r+4>>2]=t[Dl+4>>2],iu(e,3753,r)|0,t[bu>>2]=4,t[bu+4>>2]=0,t[r>>2]=t[bu>>2],t[r+4>>2]=t[bu+4>>2],iu(e,3769,r)|0,t[Sr>>2]=5,t[Sr+4>>2]=0,t[r>>2]=t[Sr>>2],t[r+4>>2]=t[Sr+4>>2],iu(e,3783,r)|0,t[G1>>2]=6,t[G1+4>>2]=0,t[r>>2]=t[G1>>2],t[r+4>>2]=t[G1+4>>2],iu(e,3796,r)|0,t[V1>>2]=7,t[V1+4>>2]=0,t[r>>2]=t[V1>>2],t[r+4>>2]=t[V1+4>>2],iu(e,3813,r)|0,t[W1>>2]=8,t[W1+4>>2]=0,t[r>>2]=t[W1>>2],t[r+4>>2]=t[W1+4>>2],iu(e,3825,r)|0,t[af>>2]=3,t[af+4>>2]=0,t[r>>2]=t[af>>2],t[r+4>>2]=t[af+4>>2],M0(e,3843,r)|0,t[Vl>>2]=4,t[Vl+4>>2]=0,t[r>>2]=t[Vl>>2],t[r+4>>2]=t[Vl+4>>2],M0(e,3853,r)|0,t[Jf>>2]=9,t[Jf+4>>2]=0,t[r>>2]=t[Jf>>2],t[r+4>>2]=t[Jf+4>>2],iu(e,3870,r)|0,t[q1>>2]=10,t[q1+4>>2]=0,t[r>>2]=t[q1>>2],t[r+4>>2]=t[q1+4>>2],iu(e,3884,r)|0,t[H1>>2]=11,t[H1+4>>2]=0,t[r>>2]=t[H1>>2],t[r+4>>2]=t[H1+4>>2],iu(e,3896,r)|0,t[Qf>>2]=1,t[Qf+4>>2]=0,t[r>>2]=t[Qf>>2],t[r+4>>2]=t[Qf+4>>2],u0(e,3907,r)|0,t[fs>>2]=2,t[fs+4>>2]=0,t[r>>2]=t[fs>>2],t[r+4>>2]=t[fs+4>>2],u0(e,3915,r)|0,t[Xf>>2]=3,t[Xf+4>>2]=0,t[r>>2]=t[Xf>>2],t[r+4>>2]=t[Xf+4>>2],u0(e,3928,r)|0,t[as>>2]=4,t[as+4>>2]=0,t[r>>2]=t[as>>2],t[r+4>>2]=t[as+4>>2],u0(e,3948,r)|0,t[z1>>2]=5,t[z1+4>>2]=0,t[r>>2]=t[z1>>2],t[r+4>>2]=t[z1+4>>2],u0(e,3960,r)|0,t[hu>>2]=6,t[hu+4>>2]=0,t[r>>2]=t[hu>>2],t[r+4>>2]=t[hu+4>>2],u0(e,3974,r)|0,t[sf>>2]=7,t[sf+4>>2]=0,t[r>>2]=t[sf>>2],t[r+4>>2]=t[sf+4>>2],u0(e,3983,r)|0,t[El>>2]=20,t[El+4>>2]=0,t[r>>2]=t[El>>2],t[r+4>>2]=t[El+4>>2],Vs(e,3999,r)|0,t[Wl>>2]=8,t[Wl+4>>2]=0,t[r>>2]=t[Wl>>2],t[r+4>>2]=t[Wl+4>>2],u0(e,4012,r)|0,t[j1>>2]=9,t[j1+4>>2]=0,t[r>>2]=t[j1>>2],t[r+4>>2]=t[j1+4>>2],u0(e,4022,r)|0,t[U1>>2]=21,t[U1+4>>2]=0,t[r>>2]=t[U1>>2],t[r+4>>2]=t[U1+4>>2],Vs(e,4039,r)|0,t[Bc>>2]=10,t[Bc+4>>2]=0,t[r>>2]=t[Bc>>2],t[r+4>>2]=t[Bc+4>>2],u0(e,4053,r)|0,t[B1>>2]=11,t[B1+4>>2]=0,t[r>>2]=t[B1>>2],t[r+4>>2]=t[B1+4>>2],u0(e,4065,r)|0,t[b1>>2]=12,t[b1+4>>2]=0,t[r>>2]=t[b1>>2],t[r+4>>2]=t[b1+4>>2],u0(e,4084,r)|0,t[lf>>2]=13,t[lf+4>>2]=0,t[r>>2]=t[lf>>2],t[r+4>>2]=t[lf+4>>2],u0(e,4097,r)|0,t[Ns>>2]=14,t[Ns+4>>2]=0,t[r>>2]=t[Ns>>2],t[r+4>>2]=t[Ns+4>>2],u0(e,4117,r)|0,t[La>>2]=15,t[La+4>>2]=0,t[r>>2]=t[La>>2],t[r+4>>2]=t[La+4>>2],u0(e,4129,r)|0,t[ql>>2]=16,t[ql+4>>2]=0,t[r>>2]=t[ql>>2],t[r+4>>2]=t[ql+4>>2],u0(e,4148,r)|0,t[Kf>>2]=17,t[Kf+4>>2]=0,t[r>>2]=t[Kf>>2],t[r+4>>2]=t[Kf+4>>2],u0(e,4161,r)|0,t[bc>>2]=18,t[bc+4>>2]=0,t[r>>2]=t[bc>>2],t[r+4>>2]=t[bc+4>>2],u0(e,4181,r)|0,t[Ic>>2]=5,t[Ic+4>>2]=0,t[r>>2]=t[Ic>>2],t[r+4>>2]=t[Ic+4>>2],M0(e,4196,r)|0,t[a2>>2]=6,t[a2+4>>2]=0,t[r>>2]=t[a2>>2],t[r+4>>2]=t[a2+4>>2],M0(e,4206,r)|0,t[s2>>2]=7,t[s2+4>>2]=0,t[r>>2]=t[s2>>2],t[r+4>>2]=t[s2+4>>2],M0(e,4217,r)|0,t[Yf>>2]=3,t[Yf+4>>2]=0,t[r>>2]=t[Yf>>2],t[r+4>>2]=t[Yf+4>>2],ns(e,4235,r)|0,t[l2>>2]=1,t[l2+4>>2]=0,t[r>>2]=t[l2>>2],t[r+4>>2]=t[l2+4>>2],Ya(e,4251,r)|0,t[of>>2]=4,t[of+4>>2]=0,t[r>>2]=t[of>>2],t[r+4>>2]=t[of+4>>2],ns(e,4263,r)|0,t[pi>>2]=5,t[pi+4>>2]=0,t[r>>2]=t[pi>>2],t[r+4>>2]=t[pi+4>>2],ns(e,4279,r)|0,t[o2>>2]=6,t[o2+4>>2]=0,t[r>>2]=t[o2>>2],t[r+4>>2]=t[o2+4>>2],ns(e,4293,r)|0,t[u2>>2]=7,t[u2+4>>2]=0,t[r>>2]=t[u2>>2],t[r+4>>2]=t[u2+4>>2],ns(e,4306,r)|0,t[i2>>2]=8,t[i2+4>>2]=0,t[r>>2]=t[i2>>2],t[r+4>>2]=t[i2+4>>2],ns(e,4323,r)|0,t[Pc>>2]=9,t[Pc+4>>2]=0,t[r>>2]=t[Pc>>2],t[r+4>>2]=t[Pc+4>>2],ns(e,4335,r)|0,t[Fc>>2]=2,t[Fc+4>>2]=0,t[r>>2]=t[Fc>>2],t[r+4>>2]=t[Fc+4>>2],Ya(e,4353,r)|0,t[r2>>2]=12,t[r2+4>>2]=0,t[r>>2]=t[r2>>2],t[r+4>>2]=t[r2+4>>2],uo(e,4363,r)|0,t[uf>>2]=1,t[uf+4>>2]=0,t[r>>2]=t[uf>>2],t[r+4>>2]=t[uf+4>>2],fl(e,4376,r)|0,t[n2>>2]=2,t[n2+4>>2]=0,t[r>>2]=t[n2>>2],t[r+4>>2]=t[n2+4>>2],fl(e,4388,r)|0,t[t2>>2]=13,t[t2+4>>2]=0,t[r>>2]=t[t2>>2],t[r+4>>2]=t[t2+4>>2],uo(e,4402,r)|0,t[ea>>2]=14,t[ea+4>>2]=0,t[r>>2]=t[ea>>2],t[r+4>>2]=t[ea+4>>2],uo(e,4411,r)|0,t[ss>>2]=15,t[ss+4>>2]=0,t[r>>2]=t[ss>>2],t[r+4>>2]=t[ss+4>>2],uo(e,4421,r)|0,t[ls>>2]=16,t[ls+4>>2]=0,t[r>>2]=t[ls>>2],t[r+4>>2]=t[ls+4>>2],uo(e,4433,r)|0,t[os>>2]=17,t[os+4>>2]=0,t[r>>2]=t[os>>2],t[r+4>>2]=t[os+4>>2],uo(e,4446,r)|0,t[uu>>2]=18,t[uu+4>>2]=0,t[r>>2]=t[uu>>2],t[r+4>>2]=t[uu+4>>2],uo(e,4458,r)|0,t[kn>>2]=3,t[kn+4>>2]=0,t[r>>2]=t[kn>>2],t[r+4>>2]=t[kn+4>>2],fl(e,4471,r)|0,t[Pr>>2]=1,t[Pr+4>>2]=0,t[r>>2]=t[Pr>>2],t[r+4>>2]=t[Pr+4>>2],yc(e,4486,r)|0,t[_r>>2]=10,t[_r+4>>2]=0,t[r>>2]=t[_r>>2],t[r+4>>2]=t[_r+4>>2],ns(e,4496,r)|0,t[gn>>2]=11,t[gn+4>>2]=0,t[r>>2]=t[gn>>2],t[r+4>>2]=t[gn+4>>2],ns(e,4508,r)|0,t[Pn>>2]=3,t[Pn+4>>2]=0,t[r>>2]=t[Pn>>2],t[r+4>>2]=t[Pn+4>>2],Ya(e,4519,r)|0,t[Br>>2]=4,t[Br+4>>2]=0,t[r>>2]=t[Br>>2],t[r+4>>2]=t[Br+4>>2],M2(e,4530,r)|0,t[Zt>>2]=19,t[Zt+4>>2]=0,t[r>>2]=t[Zt>>2],t[r+4>>2]=t[Zt+4>>2],wh(e,4542,r)|0,t[Ie>>2]=12,t[Ie+4>>2]=0,t[r>>2]=t[Ie>>2],t[r+4>>2]=t[Ie+4>>2],Cf(e,4554,r)|0,t[ke>>2]=13,t[ke+4>>2]=0,t[r>>2]=t[ke>>2],t[r+4>>2]=t[ke+4>>2],xf(e,4568,r)|0,t[ct>>2]=2,t[ct+4>>2]=0,t[r>>2]=t[ct>>2],t[r+4>>2]=t[ct+4>>2],e1(e,4578,r)|0,t[Ye>>2]=20,t[Ye+4>>2]=0,t[r>>2]=t[Ye>>2],t[r+4>>2]=t[Ye+4>>2],Nl(e,4587,r)|0,t[Ze>>2]=22,t[Ze+4>>2]=0,t[r>>2]=t[Ze>>2],t[r+4>>2]=t[Ze+4>>2],Vs(e,4602,r)|0,t[ye>>2]=23,t[ye+4>>2]=0,t[r>>2]=t[ye>>2],t[r+4>>2]=t[ye+4>>2],Vs(e,4619,r)|0,t[Te>>2]=14,t[Te+4>>2]=0,t[r>>2]=t[Te>>2],t[r+4>>2]=t[Te+4>>2],t1(e,4629,r)|0,t[Be>>2]=1,t[Be+4>>2]=0,t[r>>2]=t[Be>>2],t[r+4>>2]=t[Be+4>>2],ya(e,4637,r)|0,t[X>>2]=4,t[X+4>>2]=0,t[r>>2]=t[X>>2],t[r+4>>2]=t[X+4>>2],fl(e,4653,r)|0,t[b>>2]=5,t[b+4>>2]=0,t[r>>2]=t[b>>2],t[r+4>>2]=t[b+4>>2],fl(e,4669,r)|0,t[M>>2]=6,t[M+4>>2]=0,t[r>>2]=t[M>>2],t[r+4>>2]=t[M+4>>2],fl(e,4686,r)|0,t[L>>2]=7,t[L+4>>2]=0,t[r>>2]=t[L>>2],t[r+4>>2]=t[L+4>>2],fl(e,4701,r)|0,t[T>>2]=8,t[T+4>>2]=0,t[r>>2]=t[T>>2],t[r+4>>2]=t[T+4>>2],fl(e,4719,r)|0,t[w>>2]=9,t[w+4>>2]=0,t[r>>2]=t[w>>2],t[r+4>>2]=t[w+4>>2],fl(e,4736,r)|0,t[v>>2]=21,t[v+4>>2]=0,t[r>>2]=t[v>>2],t[r+4>>2]=t[v+4>>2],hd(e,4754,r)|0,t[a>>2]=2,t[a+4>>2]=0,t[r>>2]=t[a>>2],t[r+4>>2]=t[a+4>>2],yc(e,4772,r)|0,t[s>>2]=3,t[s+4>>2]=0,t[r>>2]=t[s>>2],t[r+4>>2]=t[s+4>>2],yc(e,4790,r)|0,t[u>>2]=4,t[u+4>>2]=0,t[r>>2]=t[u>>2],t[r+4>>2]=t[u+4>>2],yc(e,4808,r)|0,y=n}function Tf(e,n){e=e|0,n=n|0;var r=0;r=rf()|0,t[e>>2]=r,Vo(r,n),Zd(t[e>>2]|0)}function $c(e,n,r){return e=e|0,n=n|0,r=r|0,Mt(e,Fr(n)|0,r,0),e|0}function Dh(e,n,r){return e=e|0,n=n|0,r=r|0,d(e,Fr(n)|0,r,0),e|0}function sm(e,n,r){return e=e|0,n=n|0,r=r|0,Q4(e,Fr(n)|0,r,0),e|0}function Vs(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0;return u=y,y=y+16|0,s=u+8|0,a=u,v=t[r+4>>2]|0,t[a>>2]=t[r>>2],t[a+4>>2]=v,t[s>>2]=t[a>>2],t[s+4>>2]=t[a+4>>2],H4(e,n,s),y=u,e|0}function ma(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0;return u=y,y=y+16|0,s=u+8|0,a=u,v=t[r+4>>2]|0,t[a>>2]=t[r>>2],t[a+4>>2]=v,t[s>>2]=t[a>>2],t[s+4>>2]=t[a+4>>2],zl(e,n,s),y=u,e|0}function iu(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0;return u=y,y=y+16|0,s=u+8|0,a=u,v=t[r+4>>2]|0,t[a>>2]=t[r>>2],t[a+4>>2]=v,t[s>>2]=t[a>>2],t[s+4>>2]=t[a+4>>2],p(e,n,s),y=u,e|0}function M0(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0;return u=y,y=y+16|0,s=u+8|0,a=u,v=t[r+4>>2]|0,t[a>>2]=t[r>>2],t[a+4>>2]=v,t[s>>2]=t[a>>2],t[s+4>>2]=t[a+4>>2],Rv(e,n,s),y=u,e|0}function u0(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0;return u=y,y=y+16|0,s=u+8|0,a=u,v=t[r+4>>2]|0,t[a>>2]=t[r>>2],t[a+4>>2]=v,t[s>>2]=t[a>>2],t[s+4>>2]=t[a+4>>2],ny(e,n,s),y=u,e|0}function ns(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0;return u=y,y=y+16|0,s=u+8|0,a=u,v=t[r+4>>2]|0,t[a>>2]=t[r>>2],t[a+4>>2]=v,t[s>>2]=t[a>>2],t[s+4>>2]=t[a+4>>2],Gd(e,n,s),y=u,e|0}function Ya(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0;return u=y,y=y+16|0,s=u+8|0,a=u,v=t[r+4>>2]|0,t[a>>2]=t[r>>2],t[a+4>>2]=v,t[s>>2]=t[a>>2],t[s+4>>2]=t[a+4>>2],Vd(e,n,s),y=u,e|0}function uo(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0;return u=y,y=y+16|0,s=u+8|0,a=u,v=t[r+4>>2]|0,t[a>>2]=t[r>>2],t[a+4>>2]=v,t[s>>2]=t[a>>2],t[s+4>>2]=t[a+4>>2],k0(e,n,s),y=u,e|0}function fl(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0;return u=y,y=y+16|0,s=u+8|0,a=u,v=t[r+4>>2]|0,t[a>>2]=t[r>>2],t[a+4>>2]=v,t[s>>2]=t[a>>2],t[s+4>>2]=t[a+4>>2],Dp(e,n,s),y=u,e|0}function yc(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0;return u=y,y=y+16|0,s=u+8|0,a=u,v=t[r+4>>2]|0,t[a>>2]=t[r>>2],t[a+4>>2]=v,t[s>>2]=t[a>>2],t[s+4>>2]=t[a+4>>2],bm(e,n,s),y=u,e|0}function M2(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0;return u=y,y=y+16|0,s=u+8|0,a=u,v=t[r+4>>2]|0,t[a>>2]=t[r>>2],t[a+4>>2]=v,t[s>>2]=t[a>>2],t[s+4>>2]=t[a+4>>2],o0(e,n,s),y=u,e|0}function wh(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0;return u=y,y=y+16|0,s=u+8|0,a=u,v=t[r+4>>2]|0,t[a>>2]=t[r>>2],t[a+4>>2]=v,t[s>>2]=t[a>>2],t[s+4>>2]=t[a+4>>2],Ad(e,n,s),y=u,e|0}function Cf(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0;return u=y,y=y+16|0,s=u+8|0,a=u,v=t[r+4>>2]|0,t[a>>2]=t[r>>2],t[a+4>>2]=v,t[s>>2]=t[a>>2],t[s+4>>2]=t[a+4>>2],Am(e,n,s),y=u,e|0}function xf(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0;return u=y,y=y+16|0,s=u+8|0,a=u,v=t[r+4>>2]|0,t[a>>2]=t[r>>2],t[a+4>>2]=v,t[s>>2]=t[a>>2],t[s+4>>2]=t[a+4>>2],$2(e,n,s),y=u,e|0}function e1(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0;return u=y,y=y+16|0,s=u+8|0,a=u,v=t[r+4>>2]|0,t[a>>2]=t[r>>2],t[a+4>>2]=v,t[s>>2]=t[a>>2],t[s+4>>2]=t[a+4>>2],y1(e,n,s),y=u,e|0}function Nl(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0;return u=y,y=y+16|0,s=u+8|0,a=u,v=t[r+4>>2]|0,t[a>>2]=t[r>>2],t[a+4>>2]=v,t[s>>2]=t[a>>2],t[s+4>>2]=t[a+4>>2],Za(e,n,s),y=u,e|0}function t1(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0;return u=y,y=y+16|0,s=u+8|0,a=u,v=t[r+4>>2]|0,t[a>>2]=t[r>>2],t[a+4>>2]=v,t[s>>2]=t[a>>2],t[s+4>>2]=t[a+4>>2],B2(e,n,s),y=u,e|0}function ya(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0;return u=y,y=y+16|0,s=u+8|0,a=u,v=t[r+4>>2]|0,t[a>>2]=t[r>>2],t[a+4>>2]=v,t[s>>2]=t[a>>2],t[s+4>>2]=t[a+4>>2],L2(e,n,s),y=u,e|0}function hd(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0;return u=y,y=y+16|0,s=u+8|0,a=u,v=t[r+4>>2]|0,t[a>>2]=t[r>>2],t[a+4>>2]=v,t[s>>2]=t[a>>2],t[s+4>>2]=t[a+4>>2],vd(e,n,s),y=u,e|0}function vd(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0;u=y,y=y+16|0,s=u+8|0,a=u,w=t[r>>2]|0,v=t[r+4>>2]|0,r=Fr(n)|0,t[a>>2]=w,t[a+4>>2]=v,t[s>>2]=t[a>>2],t[s+4>>2]=t[a+4>>2],ga(e,r,s,1),y=u}function Fr(e){return e=e|0,e|0}function ga(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0,a=0,v=0,w=0,T=0,L=0,M=0;s=y,y=y+32|0,a=s+16|0,M=s+8|0,w=s,L=t[r>>2]|0,T=t[r+4>>2]|0,v=t[e>>2]|0,e=k2()|0,t[M>>2]=L,t[M+4>>2]=T,t[a>>2]=t[M>>2],t[a+4>>2]=t[M+4>>2],r=n1(a)|0,t[w>>2]=L,t[w+4>>2]=T,t[a>>2]=t[w>>2],t[a+4>>2]=t[w+4>>2],wi(v,n,e,r,md(a,u)|0,u),y=s}function k2(){var e=0,n=0;if(h[7616]|0||(cl(9136),Wt(24,9136,ge|0)|0,n=7616,t[n>>2]=1,t[n+4>>2]=0),!(sr(9136)|0)){e=9136,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));cl(9136)}return 9136}function n1(e){return e=e|0,0}function md(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0,b=0;return M=y,y=y+32|0,s=M+24|0,v=M+16|0,w=M,T=M+8|0,a=t[e>>2]|0,u=t[e+4>>2]|0,t[w>>2]=a,t[w+4>>2]=u,b=k2()|0,L=b+24|0,e=hn(n,4)|0,t[T>>2]=e,n=b+28|0,r=t[n>>2]|0,r>>>0<(t[b+32>>2]|0)>>>0?(t[v>>2]=a,t[v+4>>2]=u,t[s>>2]=t[v>>2],t[s+4>>2]=t[v+4>>2],Rf(r,s,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(Af(L,w,T),e=t[n>>2]|0),y=M,((e-(t[L>>2]|0)|0)/12|0)+-1|0}function wi(e,n,r,u,s,a){e=e|0,n=n|0,r=r|0,u=u|0,s=s|0,a=a|0;var v=0,w=0,T=0,L=0,M=0,b=0,X=0,Be=0;v=y,y=y+32|0,X=v+24|0,b=v+20|0,T=v+16|0,M=v+12|0,L=v+8|0,w=v+4|0,Be=v,t[b>>2]=n,t[T>>2]=r,t[M>>2]=u,t[L>>2]=s,t[w>>2]=a,a=e+28|0,t[Be>>2]=t[a>>2],t[X>>2]=t[Be>>2],N2(e+24|0,X,b,M,L,T,w)|0,t[a>>2]=t[t[a>>2]>>2],y=v}function N2(e,n,r,u,s,a,v){return e=e|0,n=n|0,r=r|0,u=u|0,s=s|0,a=a|0,v=v|0,e=am(n)|0,n=pn(24)|0,yd(n+4|0,t[r>>2]|0,t[u>>2]|0,t[s>>2]|0,t[a>>2]|0,t[v>>2]|0),t[n>>2]=t[e>>2],t[e>>2]=n,n|0}function am(e){return e=e|0,t[e>>2]|0}function yd(e,n,r,u,s,a){e=e|0,n=n|0,r=r|0,u=u|0,s=s|0,a=a|0,t[e>>2]=n,t[e+4>>2]=r,t[e+8>>2]=u,t[e+12>>2]=s,t[e+16>>2]=a}function hn(e,n){return e=e|0,n=n|0,n|e|0}function Rf(e,n,r){e=e|0,n=n|0,r=r|0;var u=0;u=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=u,t[e+8>>2]=r}function Af(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0,b=0,X=0;if(L=y,y=y+48|0,u=L+32|0,v=L+24|0,w=L,T=e+4|0,s=(((t[T>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,a=fm(e)|0,a>>>0>>0)di(e);else{M=t[e>>2]|0,X=((t[e+8>>2]|0)-M|0)/12|0,b=X<<1,Of(w,X>>>0>>1>>>0?b>>>0>>0?s:b:a,((t[T>>2]|0)-M|0)/12|0,e+8|0),T=w+8|0,a=t[T>>2]|0,s=t[n+4>>2]|0,r=t[r>>2]|0,t[v>>2]=t[n>>2],t[v+4>>2]=s,t[u>>2]=t[v>>2],t[u+4>>2]=t[v+4>>2],Rf(a,u,r),t[T>>2]=(t[T>>2]|0)+12,Sh(e,w),cm(w),y=L;return}}function fm(e){return e=e|0,357913941}function Of(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=u;do if(n)if(n>>>0>357913941)$n();else{s=pn(n*12|0)|0;break}else s=0;while(0);t[e>>2]=s,u=s+(r*12|0)|0,t[e+8>>2]=u,t[e+4>>2]=u,t[e+12>>2]=s+(n*12|0)}function Sh(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0;u=t[e>>2]|0,v=e+4|0,a=n+4|0,s=(t[v>>2]|0)-u|0,r=(t[a>>2]|0)+(((s|0)/-12|0)*12|0)|0,t[a>>2]=r,(s|0)>0?(gr(r|0,u|0,s|0)|0,u=a,r=t[a>>2]|0):u=a,a=t[e>>2]|0,t[e>>2]=r,t[u>>2]=a,a=n+8|0,s=t[v>>2]|0,t[v>>2]=t[a>>2],t[a>>2]=s,a=e+8|0,v=n+12|0,e=t[a>>2]|0,t[a>>2]=t[v>>2],t[v>>2]=e,t[n>>2]=t[u>>2]}function cm(e){e=e|0;var n=0,r=0,u=0;n=t[e+4>>2]|0,r=e+8|0,u=t[r>>2]|0,(u|0)!=(n|0)&&(t[r>>2]=u+(~(((u+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&Et(e)}function cl(e){e=e|0,qo(e)}function r1(e){e=e|0,qn(e+24|0)}function sr(e){return e=e|0,t[e>>2]|0}function qn(e){e=e|0;var n=0,r=0,u=0;r=t[e>>2]|0,u=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-u|0)>>>0)/12|0)*12|0)),Et(r))}function qo(e){e=e|0;var n=0;n=yr()|0,jn(e,2,3,n,Vn()|0,0),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function yr(){return 9228}function Vn(){return 1140}function dl(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0;return r=y,y=y+16|0,u=r+8|0,s=r,a=Eo(e)|0,e=t[a+4>>2]|0,t[s>>2]=t[a>>2],t[s+4>>2]=e,t[u>>2]=t[s>>2],t[u+4>>2]=t[s+4>>2],n=gc(n,u)|0,y=r,n|0}function jn(e,n,r,u,s,a){e=e|0,n=n|0,r=r|0,u=u|0,s=s|0,a=a|0,t[e>>2]=n,t[e+4>>2]=r,t[e+8>>2]=u,t[e+12>>2]=s,t[e+16>>2]=a}function Eo(e){return e=e|0,(t[(k2()|0)+24>>2]|0)+(e*12|0)|0}function gc(e,n){e=e|0,n=n|0;var r=0,u=0,s=0;return s=y,y=y+48|0,u=s,r=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(r=t[(t[e>>2]|0)+r>>2]|0),I1[r&31](u,e),u=oo(u)|0,y=s,u|0}function oo(e){e=e|0;var n=0,r=0,u=0,s=0;return s=y,y=y+32|0,n=s+12|0,r=s,u=Pu(Ka()|0)|0,u?(rs(n,u),Mf(r,n),_c(e,r),e=Cs(n)|0):e=Ec(e)|0,y=s,e|0}function Ka(){var e=0;return h[7632]|0||(Nf(9184),Wt(25,9184,ge|0)|0,e=7632,t[e>>2]=1,t[e+4>>2]=0),9184}function Pu(e){return e=e|0,t[e+36>>2]|0}function rs(e,n){e=e|0,n=n|0,t[e>>2]=n,t[e+4>>2]=e,t[e+8>>2]=0}function Mf(e,n){e=e|0,n=n|0,t[e>>2]=t[n>>2],t[e+4>>2]=t[n+4>>2],t[e+8>>2]=0}function _c(e,n){e=e|0,n=n|0,lo(n,e,e+8|0,e+16|0,e+24|0,e+32|0,e+40|0)|0}function Cs(e){return e=e|0,t[(t[e+4>>2]|0)+8>>2]|0}function Ec(e){e=e|0;var n=0,r=0,u=0,s=0,a=0,v=0,w=0,T=0;T=y,y=y+16|0,r=T+4|0,u=T,s=Oa(8)|0,a=s,v=pn(48)|0,w=v,n=w+48|0;do t[w>>2]=t[e>>2],w=w+4|0,e=e+4|0;while((w|0)<(n|0));return n=a+4|0,t[n>>2]=v,w=pn(8)|0,v=t[n>>2]|0,t[u>>2]=0,t[r>>2]=t[u>>2],Th(w,v,r),t[s>>2]=w,y=T,a|0}function Th(e,n,r){e=e|0,n=n|0,r=r|0,t[e>>2]=n,r=pn(16)|0,t[r+4>>2]=0,t[r+8>>2]=0,t[r>>2]=1092,t[r+12>>2]=n,t[e+4>>2]=r}function cn(e){e=e|0,Uv(e),Et(e)}function is(e){e=e|0,e=t[e+12>>2]|0,e|0&&Et(e)}function Do(e){e=e|0,Et(e)}function lo(e,n,r,u,s,a,v){return e=e|0,n=n|0,r=r|0,u=u|0,s=s|0,a=a|0,v=v|0,a=Ji(t[e>>2]|0,n,r,u,s,a,v)|0,v=e+4|0,t[(t[v>>2]|0)+8>>2]=a,t[(t[v>>2]|0)+8>>2]|0}function Ji(e,n,r,u,s,a,v){e=e|0,n=n|0,r=r|0,u=u|0,s=s|0,a=a|0,v=v|0;var w=0,T=0;return w=y,y=y+16|0,T=w,Ma(T),e=go(e)|0,v=Gr(e,+j[n>>3],+j[r>>3],+j[u>>3],+j[s>>3],+j[a>>3],+j[v>>3])|0,ka(T),y=w,v|0}function Gr(e,n,r,u,s,a,v){e=e|0,n=+n,r=+r,u=+u,s=+s,a=+a,v=+v;var w=0;return w=_o(kf()|0)|0,n=+kl(n),r=+kl(r),u=+kl(u),s=+kl(s),a=+kl(a),d0(0,w|0,e|0,+n,+r,+u,+s,+a,+ +kl(v))|0}function kf(){var e=0;return h[7624]|0||(dm(9172),e=7624,t[e>>2]=1,t[e+4>>2]=0),9172}function dm(e){e=e|0,ll(e,Ll()|0,6)}function Ll(){return 1112}function Nf(e){e=e|0,Xa(e)}function Lf(e){e=e|0,gd(e+24|0),_d(e+16|0)}function gd(e){e=e|0,i1(e)}function _d(e){e=e|0,Dc(e)}function Dc(e){e=e|0;var n=0,r=0;if(n=t[e>>2]|0,n|0)do r=n,n=t[n>>2]|0,Et(r);while((n|0)!=0);t[e>>2]=0}function i1(e){e=e|0;var n=0,r=0;if(n=t[e>>2]|0,n|0)do r=n,n=t[n>>2]|0,Et(r);while((n|0)!=0);t[e>>2]=0}function Xa(e){e=e|0;var n=0;t[e+16>>2]=0,t[e+20>>2]=0,n=e+24|0,t[n>>2]=0,t[e+28>>2]=n,t[e+36>>2]=0,h[e+40>>0]=0,h[e+41>>0]=0}function L2(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0;u=y,y=y+16|0,s=u+8|0,a=u,w=t[r>>2]|0,v=t[r+4>>2]|0,r=Fr(n)|0,t[a>>2]=w,t[a+4>>2]=v,t[s>>2]=t[a>>2],t[s+4>>2]=t[a+4>>2],Ed(e,r,s,0),y=u}function Ed(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0,a=0,v=0,w=0,T=0,L=0,M=0;s=y,y=y+32|0,a=s+16|0,M=s+8|0,w=s,L=t[r>>2]|0,T=t[r+4>>2]|0,v=t[e>>2]|0,e=u1()|0,t[M>>2]=L,t[M+4>>2]=T,t[a>>2]=t[M>>2],t[a+4>>2]=t[M+4>>2],r=Ff(a)|0,t[w>>2]=L,t[w+4>>2]=T,t[a>>2]=t[w>>2],t[a+4>>2]=t[w+4>>2],wi(v,n,e,r,o1(a,u)|0,u),y=s}function u1(){var e=0,n=0;if(h[7640]|0||(Fl(9232),Wt(26,9232,ge|0)|0,n=7640,t[n>>2]=1,t[n+4>>2]=0),!(sr(9232)|0)){e=9232,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));Fl(9232)}return 9232}function Ff(e){return e=e|0,0}function o1(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0,b=0;return M=y,y=y+32|0,s=M+24|0,v=M+16|0,w=M,T=M+8|0,a=t[e>>2]|0,u=t[e+4>>2]|0,t[w>>2]=a,t[w+4>>2]=u,b=u1()|0,L=b+24|0,e=hn(n,4)|0,t[T>>2]=e,n=b+28|0,r=t[n>>2]|0,r>>>0<(t[b+32>>2]|0)>>>0?(t[v>>2]=a,t[v+4>>2]=u,t[s>>2]=t[v>>2],t[s+4>>2]=t[v+4>>2],Qa(r,s,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(l1(L,w,T),e=t[n>>2]|0),y=M,((e-(t[L>>2]|0)|0)/12|0)+-1|0}function Qa(e,n,r){e=e|0,n=n|0,r=r|0;var u=0;u=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=u,t[e+8>>2]=r}function l1(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0,b=0,X=0;if(L=y,y=y+48|0,u=L+32|0,v=L+24|0,w=L,T=e+4|0,s=(((t[T>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,a=F2(e)|0,a>>>0>>0)di(e);else{M=t[e>>2]|0,X=((t[e+8>>2]|0)-M|0)/12|0,b=X<<1,Dd(w,X>>>0>>1>>>0?b>>>0>>0?s:b:a,((t[T>>2]|0)-M|0)/12|0,e+8|0),T=w+8|0,a=t[T>>2]|0,s=t[n+4>>2]|0,r=t[r>>2]|0,t[v>>2]=t[n>>2],t[v+4>>2]=s,t[u>>2]=t[v>>2],t[u+4>>2]=t[v+4>>2],Qa(a,u,r),t[T>>2]=(t[T>>2]|0)+12,wc(e,w),s1(w),y=L;return}}function F2(e){return e=e|0,357913941}function Dd(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=u;do if(n)if(n>>>0>357913941)$n();else{s=pn(n*12|0)|0;break}else s=0;while(0);t[e>>2]=s,u=s+(r*12|0)|0,t[e+8>>2]=u,t[e+4>>2]=u,t[e+12>>2]=s+(n*12|0)}function wc(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0;u=t[e>>2]|0,v=e+4|0,a=n+4|0,s=(t[v>>2]|0)-u|0,r=(t[a>>2]|0)+(((s|0)/-12|0)*12|0)|0,t[a>>2]=r,(s|0)>0?(gr(r|0,u|0,s|0)|0,u=a,r=t[a>>2]|0):u=a,a=t[e>>2]|0,t[e>>2]=r,t[u>>2]=a,a=n+8|0,s=t[v>>2]|0,t[v>>2]=t[a>>2],t[a>>2]=s,a=e+8|0,v=n+12|0,e=t[a>>2]|0,t[a>>2]=t[v>>2],t[v>>2]=e,t[n>>2]=t[u>>2]}function s1(e){e=e|0;var n=0,r=0,u=0;n=t[e+4>>2]|0,r=e+8|0,u=t[r>>2]|0,(u|0)!=(n|0)&&(t[r>>2]=u+(~(((u+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&Et(e)}function Fl(e){e=e|0,P2(e)}function Ea(e){e=e|0,Ch(e+24|0)}function Ch(e){e=e|0;var n=0,r=0,u=0;r=t[e>>2]|0,u=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-u|0)>>>0)/12|0)*12|0)),Et(r))}function P2(e){e=e|0;var n=0;n=yr()|0,jn(e,2,1,n,I2()|0,3),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function I2(){return 1144}function xh(e,n,r,u,s){e=e|0,n=n|0,r=+r,u=+u,s=s|0;var a=0,v=0,w=0,T=0;a=y,y=y+16|0,v=a+8|0,w=a,T=pm(e)|0,e=t[T+4>>2]|0,t[w>>2]=t[T>>2],t[w+4>>2]=e,t[v>>2]=t[w>>2],t[v+4>>2]=t[w+4>>2],Rh(n,v,r,u,s),y=a}function pm(e){return e=e|0,(t[(u1()|0)+24>>2]|0)+(e*12|0)|0}function Rh(e,n,r,u,s){e=e|0,n=n|0,r=+r,u=+u,s=s|0;var a=0,v=0,w=0,T=0,L=0;L=y,y=y+16|0,v=L+2|0,w=L+1|0,T=L,a=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(a=t[(t[e>>2]|0)+a>>2]|0),Pl(v,r),r=+us(v,r),Pl(w,u),u=+us(w,u),xs(T,s),T=Gs(T,s)|0,L8[a&1](e,r,u,T),y=L}function Pl(e,n){e=e|0,n=+n}function us(e,n){return e=e|0,n=+n,+ +Ah(n)}function xs(e,n){e=e|0,n=n|0}function Gs(e,n){return e=e|0,n=n|0,b2(n)|0}function b2(e){return e=e|0,e|0}function Ah(e){return e=+e,+e}function B2(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0;u=y,y=y+16|0,s=u+8|0,a=u,w=t[r>>2]|0,v=t[r+4>>2]|0,r=Fr(n)|0,t[a>>2]=w,t[a+4>>2]=v,t[s>>2]=t[a>>2],t[s+4>>2]=t[a+4>>2],U2(e,r,s,1),y=u}function U2(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0,a=0,v=0,w=0,T=0,L=0,M=0;s=y,y=y+32|0,a=s+16|0,M=s+8|0,w=s,L=t[r>>2]|0,T=t[r+4>>2]|0,v=t[e>>2]|0,e=a1()|0,t[M>>2]=L,t[M+4>>2]=T,t[a>>2]=t[M>>2],t[a+4>>2]=t[M+4>>2],r=f1(a)|0,t[w>>2]=L,t[w+4>>2]=T,t[a>>2]=t[w>>2],t[a+4>>2]=t[w+4>>2],wi(v,n,e,r,Oh(a,u)|0,u),y=s}function a1(){var e=0,n=0;if(h[7648]|0||(c1(9268),Wt(27,9268,ge|0)|0,n=7648,t[n>>2]=1,t[n+4>>2]=0),!(sr(9268)|0)){e=9268,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));c1(9268)}return 9268}function f1(e){return e=e|0,0}function Oh(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0,b=0;return M=y,y=y+32|0,s=M+24|0,v=M+16|0,w=M,T=M+8|0,a=t[e>>2]|0,u=t[e+4>>2]|0,t[w>>2]=a,t[w+4>>2]=u,b=a1()|0,L=b+24|0,e=hn(n,4)|0,t[T>>2]=e,n=b+28|0,r=t[n>>2]|0,r>>>0<(t[b+32>>2]|0)>>>0?(t[v>>2]=a,t[v+4>>2]=u,t[s>>2]=t[v>>2],t[s+4>>2]=t[v+4>>2],j2(r,s,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(z2(L,w,T),e=t[n>>2]|0),y=M,((e-(t[L>>2]|0)|0)/12|0)+-1|0}function j2(e,n,r){e=e|0,n=n|0,r=r|0;var u=0;u=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=u,t[e+8>>2]=r}function z2(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0,b=0,X=0;if(L=y,y=y+48|0,u=L+32|0,v=L+24|0,w=L,T=e+4|0,s=(((t[T>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,a=Rs(e)|0,a>>>0>>0)di(e);else{M=t[e>>2]|0,X=((t[e+8>>2]|0)-M|0)/12|0,b=X<<1,Ja(w,X>>>0>>1>>>0?b>>>0>>0?s:b:a,((t[T>>2]|0)-M|0)/12|0,e+8|0),T=w+8|0,a=t[T>>2]|0,s=t[n+4>>2]|0,r=t[r>>2]|0,t[v>>2]=t[n>>2],t[v+4>>2]=s,t[u>>2]=t[v>>2],t[u+4>>2]=t[v+4>>2],j2(a,u,r),t[T>>2]=(t[T>>2]|0)+12,Mh(e,w),du(w),y=L;return}}function Rs(e){return e=e|0,357913941}function Ja(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=u;do if(n)if(n>>>0>357913941)$n();else{s=pn(n*12|0)|0;break}else s=0;while(0);t[e>>2]=s,u=s+(r*12|0)|0,t[e+8>>2]=u,t[e+4>>2]=u,t[e+12>>2]=s+(n*12|0)}function Mh(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0;u=t[e>>2]|0,v=e+4|0,a=n+4|0,s=(t[v>>2]|0)-u|0,r=(t[a>>2]|0)+(((s|0)/-12|0)*12|0)|0,t[a>>2]=r,(s|0)>0?(gr(r|0,u|0,s|0)|0,u=a,r=t[a>>2]|0):u=a,a=t[e>>2]|0,t[e>>2]=r,t[u>>2]=a,a=n+8|0,s=t[v>>2]|0,t[v>>2]=t[a>>2],t[a>>2]=s,a=e+8|0,v=n+12|0,e=t[a>>2]|0,t[a>>2]=t[v>>2],t[v>>2]=e,t[n>>2]=t[u>>2]}function du(e){e=e|0;var n=0,r=0,u=0;n=t[e+4>>2]|0,r=e+8|0,u=t[r>>2]|0,(u|0)!=(n|0)&&(t[r>>2]=u+(~(((u+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&Et(e)}function c1(e){e=e|0,Il(e)}function kh(e){e=e|0,d1(e+24|0)}function d1(e){e=e|0;var n=0,r=0,u=0;r=t[e>>2]|0,u=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-u|0)>>>0)/12|0)*12|0)),Et(r))}function Il(e){e=e|0;var n=0;n=yr()|0,jn(e,2,4,n,Nh()|0,0),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function Nh(){return 1160}function H2(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0;return r=y,y=y+16|0,u=r+8|0,s=r,a=Lh(e)|0,e=t[a+4>>2]|0,t[s>>2]=t[a>>2],t[s+4>>2]=e,t[u>>2]=t[s>>2],t[u+4>>2]=t[s+4>>2],n=p1(n,u)|0,y=r,n|0}function Lh(e){return e=e|0,(t[(a1()|0)+24>>2]|0)+(e*12|0)|0}function p1(e,n){e=e|0,n=n|0;var r=0;return r=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(r=t[(t[e>>2]|0)+r>>2]|0),bl(Qp[r&31](e)|0)|0}function bl(e){return e=e|0,e&1|0}function Za(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0;u=y,y=y+16|0,s=u+8|0,a=u,w=t[r>>2]|0,v=t[r+4>>2]|0,r=Fr(n)|0,t[a>>2]=w,t[a+4>>2]=v,t[s>>2]=t[a>>2],t[s+4>>2]=t[a+4>>2],Da(e,r,s,0),y=u}function Da(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0,a=0,v=0,w=0,T=0,L=0,M=0;s=y,y=y+32|0,a=s+16|0,M=s+8|0,w=s,L=t[r>>2]|0,T=t[r+4>>2]|0,v=t[e>>2]|0,e=q2()|0,t[M>>2]=L,t[M+4>>2]=T,t[a>>2]=t[M>>2],t[a+4>>2]=t[M+4>>2],r=W2(a)|0,t[w>>2]=L,t[w+4>>2]=T,t[a>>2]=t[w>>2],t[a+4>>2]=t[w+4>>2],wi(v,n,e,r,hm(a,u)|0,u),y=s}function q2(){var e=0,n=0;if(h[7656]|0||(Ih(9304),Wt(28,9304,ge|0)|0,n=7656,t[n>>2]=1,t[n+4>>2]=0),!(sr(9304)|0)){e=9304,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));Ih(9304)}return 9304}function W2(e){return e=e|0,0}function hm(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0,b=0;return M=y,y=y+32|0,s=M+24|0,v=M+16|0,w=M,T=M+8|0,a=t[e>>2]|0,u=t[e+4>>2]|0,t[w>>2]=a,t[w+4>>2]=u,b=q2()|0,L=b+24|0,e=hn(n,4)|0,t[T>>2]=e,n=b+28|0,r=t[n>>2]|0,r>>>0<(t[b+32>>2]|0)>>>0?(t[v>>2]=a,t[v+4>>2]=u,t[s>>2]=t[v>>2],t[s+4>>2]=t[v+4>>2],V2(r,s,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(Fh(L,w,T),e=t[n>>2]|0),y=M,((e-(t[L>>2]|0)|0)/12|0)+-1|0}function V2(e,n,r){e=e|0,n=n|0,r=r|0;var u=0;u=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=u,t[e+8>>2]=r}function Fh(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0,b=0,X=0;if(L=y,y=y+48|0,u=L+32|0,v=L+24|0,w=L,T=e+4|0,s=(((t[T>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,a=Ph(e)|0,a>>>0>>0)di(e);else{M=t[e>>2]|0,X=((t[e+8>>2]|0)-M|0)/12|0,b=X<<1,G2(w,X>>>0>>1>>>0?b>>>0>>0?s:b:a,((t[T>>2]|0)-M|0)/12|0,e+8|0),T=w+8|0,a=t[T>>2]|0,s=t[n+4>>2]|0,r=t[r>>2]|0,t[v>>2]=t[n>>2],t[v+4>>2]=s,t[u>>2]=t[v>>2],t[u+4>>2]=t[v+4>>2],V2(a,u,r),t[T>>2]=(t[T>>2]|0)+12,vm(e,w),mm(w),y=L;return}}function Ph(e){return e=e|0,357913941}function G2(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=u;do if(n)if(n>>>0>357913941)$n();else{s=pn(n*12|0)|0;break}else s=0;while(0);t[e>>2]=s,u=s+(r*12|0)|0,t[e+8>>2]=u,t[e+4>>2]=u,t[e+12>>2]=s+(n*12|0)}function vm(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0;u=t[e>>2]|0,v=e+4|0,a=n+4|0,s=(t[v>>2]|0)-u|0,r=(t[a>>2]|0)+(((s|0)/-12|0)*12|0)|0,t[a>>2]=r,(s|0)>0?(gr(r|0,u|0,s|0)|0,u=a,r=t[a>>2]|0):u=a,a=t[e>>2]|0,t[e>>2]=r,t[u>>2]=a,a=n+8|0,s=t[v>>2]|0,t[v>>2]=t[a>>2],t[a>>2]=s,a=e+8|0,v=n+12|0,e=t[a>>2]|0,t[a>>2]=t[v>>2],t[v>>2]=e,t[n>>2]=t[u>>2]}function mm(e){e=e|0;var n=0,r=0,u=0;n=t[e+4>>2]|0,r=e+8|0,u=t[r>>2]|0,(u|0)!=(n|0)&&(t[r>>2]=u+(~(((u+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&Et(e)}function Ih(e){e=e|0,h1(e)}function ym(e){e=e|0,Y2(e+24|0)}function Y2(e){e=e|0;var n=0,r=0,u=0;r=t[e>>2]|0,u=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-u|0)>>>0)/12|0)*12|0)),Et(r))}function h1(e){e=e|0;var n=0;n=yr()|0,jn(e,2,5,n,v1()|0,1),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function v1(){return 1164}function m1(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0;u=y,y=y+16|0,s=u+8|0,a=u,v=wa(e)|0,e=t[v+4>>2]|0,t[a>>2]=t[v>>2],t[a+4>>2]=e,t[s>>2]=t[a>>2],t[s+4>>2]=t[a+4>>2],K2(n,s,r),y=u}function wa(e){return e=e|0,(t[(q2()|0)+24>>2]|0)+(e*12|0)|0}function K2(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0;a=y,y=y+16|0,s=a,u=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(u=t[(t[e>>2]|0)+u>>2]|0),Ys(s,r),r=Ks(s,r)|0,I1[u&31](e,r),Xs(s),y=a}function Ys(e,n){e=e|0,n=n|0,X2(e,n)}function Ks(e,n){return e=e|0,n=n|0,e|0}function Xs(e){e=e|0,fa(e)}function X2(e,n){e=e|0,n=n|0,Sa(e,n)}function Sa(e,n){e=e|0,n=n|0,t[e>>2]=n}function y1(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0;u=y,y=y+16|0,s=u+8|0,a=u,w=t[r>>2]|0,v=t[r+4>>2]|0,r=Fr(n)|0,t[a>>2]=w,t[a+4>>2]=v,t[s>>2]=t[a>>2],t[s+4>>2]=t[a+4>>2],wd(e,r,s,0),y=u}function wd(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0,a=0,v=0,w=0,T=0,L=0,M=0;s=y,y=y+32|0,a=s+16|0,M=s+8|0,w=s,L=t[r>>2]|0,T=t[r+4>>2]|0,v=t[e>>2]|0,e=Sc()|0,t[M>>2]=L,t[M+4>>2]=T,t[a>>2]=t[M>>2],t[a+4>>2]=t[M+4>>2],r=Q2(a)|0,t[w>>2]=L,t[w+4>>2]=T,t[a>>2]=t[w>>2],t[a+4>>2]=t[w+4>>2],wi(v,n,e,r,wo(a,u)|0,u),y=s}function Sc(){var e=0,n=0;if(h[7664]|0||(Hh(9340),Wt(29,9340,ge|0)|0,n=7664,t[n>>2]=1,t[n+4>>2]=0),!(sr(9340)|0)){e=9340,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));Hh(9340)}return 9340}function Q2(e){return e=e|0,0}function wo(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0,b=0;return M=y,y=y+32|0,s=M+24|0,v=M+16|0,w=M,T=M+8|0,a=t[e>>2]|0,u=t[e+4>>2]|0,t[w>>2]=a,t[w+4>>2]=u,b=Sc()|0,L=b+24|0,e=hn(n,4)|0,t[T>>2]=e,n=b+28|0,r=t[n>>2]|0,r>>>0<(t[b+32>>2]|0)>>>0?(t[v>>2]=a,t[v+4>>2]=u,t[s>>2]=t[v>>2],t[s+4>>2]=t[v+4>>2],bh(r,s,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(Bh(L,w,T),e=t[n>>2]|0),y=M,((e-(t[L>>2]|0)|0)/12|0)+-1|0}function bh(e,n,r){e=e|0,n=n|0,r=r|0;var u=0;u=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=u,t[e+8>>2]=r}function Bh(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0,b=0,X=0;if(L=y,y=y+48|0,u=L+32|0,v=L+24|0,w=L,T=e+4|0,s=(((t[T>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,a=Uh(e)|0,a>>>0>>0)di(e);else{M=t[e>>2]|0,X=((t[e+8>>2]|0)-M|0)/12|0,b=X<<1,jh(w,X>>>0>>1>>>0?b>>>0>>0?s:b:a,((t[T>>2]|0)-M|0)/12|0,e+8|0),T=w+8|0,a=t[T>>2]|0,s=t[n+4>>2]|0,r=t[r>>2]|0,t[v>>2]=t[n>>2],t[v+4>>2]=s,t[u>>2]=t[v>>2],t[u+4>>2]=t[v+4>>2],bh(a,u,r),t[T>>2]=(t[T>>2]|0)+12,gm(e,w),zh(w),y=L;return}}function Uh(e){return e=e|0,357913941}function jh(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=u;do if(n)if(n>>>0>357913941)$n();else{s=pn(n*12|0)|0;break}else s=0;while(0);t[e>>2]=s,u=s+(r*12|0)|0,t[e+8>>2]=u,t[e+4>>2]=u,t[e+12>>2]=s+(n*12|0)}function gm(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0;u=t[e>>2]|0,v=e+4|0,a=n+4|0,s=(t[v>>2]|0)-u|0,r=(t[a>>2]|0)+(((s|0)/-12|0)*12|0)|0,t[a>>2]=r,(s|0)>0?(gr(r|0,u|0,s|0)|0,u=a,r=t[a>>2]|0):u=a,a=t[e>>2]|0,t[e>>2]=r,t[u>>2]=a,a=n+8|0,s=t[v>>2]|0,t[v>>2]=t[a>>2],t[a>>2]=s,a=e+8|0,v=n+12|0,e=t[a>>2]|0,t[a>>2]=t[v>>2],t[v>>2]=e,t[n>>2]=t[u>>2]}function zh(e){e=e|0;var n=0,r=0,u=0;n=t[e+4>>2]|0,r=e+8|0,u=t[r>>2]|0,(u|0)!=(n|0)&&(t[r>>2]=u+(~(((u+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&Et(e)}function Hh(e){e=e|0,qh(e)}function g1(e){e=e|0,J2(e+24|0)}function J2(e){e=e|0;var n=0,r=0,u=0;r=t[e>>2]|0,u=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-u|0)>>>0)/12|0)*12|0)),Et(r))}function qh(e){e=e|0;var n=0;n=yr()|0,jn(e,2,4,n,Z2()|0,1),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function Z2(){return 1180}function Wh(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0;return u=y,y=y+16|0,s=u+8|0,a=u,v=_m(e)|0,e=t[v+4>>2]|0,t[a>>2]=t[v>>2],t[a+4>>2]=e,t[s>>2]=t[a>>2],t[s+4>>2]=t[a+4>>2],r=Em(n,s,r)|0,y=u,r|0}function _m(e){return e=e|0,(t[(Sc()|0)+24>>2]|0)+(e*12|0)|0}function Em(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0;return a=y,y=y+16|0,s=a,u=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(u=t[(t[e>>2]|0)+u>>2]|0),Pf(s,r),s=If(s,r)|0,s=Sd(bE[u&15](e,s)|0)|0,y=a,s|0}function Pf(e,n){e=e|0,n=n|0}function If(e,n){return e=e|0,n=n|0,Dm(n)|0}function Sd(e){return e=e|0,e|0}function Dm(e){return e=e|0,e|0}function $2(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0;u=y,y=y+16|0,s=u+8|0,a=u,w=t[r>>2]|0,v=t[r+4>>2]|0,r=Fr(n)|0,t[a>>2]=w,t[a+4>>2]=v,t[s>>2]=t[a>>2],t[s+4>>2]=t[a+4>>2],Td(e,r,s,0),y=u}function Td(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0,a=0,v=0,w=0,T=0,L=0,M=0;s=y,y=y+32|0,a=s+16|0,M=s+8|0,w=s,L=t[r>>2]|0,T=t[r+4>>2]|0,v=t[e>>2]|0,e=ep()|0,t[M>>2]=L,t[M+4>>2]=T,t[a>>2]=t[M>>2],t[a+4>>2]=t[M+4>>2],r=Vh(a)|0,t[w>>2]=L,t[w+4>>2]=T,t[a>>2]=t[w>>2],t[a+4>>2]=t[w+4>>2],wi(v,n,e,r,tp(a,u)|0,u),y=s}function ep(){var e=0,n=0;if(h[7672]|0||(Kh(9376),Wt(30,9376,ge|0)|0,n=7672,t[n>>2]=1,t[n+4>>2]=0),!(sr(9376)|0)){e=9376,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));Kh(9376)}return 9376}function Vh(e){return e=e|0,0}function tp(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0,b=0;return M=y,y=y+32|0,s=M+24|0,v=M+16|0,w=M,T=M+8|0,a=t[e>>2]|0,u=t[e+4>>2]|0,t[w>>2]=a,t[w+4>>2]=u,b=ep()|0,L=b+24|0,e=hn(n,4)|0,t[T>>2]=e,n=b+28|0,r=t[n>>2]|0,r>>>0<(t[b+32>>2]|0)>>>0?(t[v>>2]=a,t[v+4>>2]=u,t[s>>2]=t[v>>2],t[s+4>>2]=t[v+4>>2],Gh(r,s,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(Yh(L,w,T),e=t[n>>2]|0),y=M,((e-(t[L>>2]|0)|0)/12|0)+-1|0}function Gh(e,n,r){e=e|0,n=n|0,r=r|0;var u=0;u=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=u,t[e+8>>2]=r}function Yh(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0,b=0,X=0;if(L=y,y=y+48|0,u=L+32|0,v=L+24|0,w=L,T=e+4|0,s=(((t[T>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,a=np(e)|0,a>>>0>>0)di(e);else{M=t[e>>2]|0,X=((t[e+8>>2]|0)-M|0)/12|0,b=X<<1,wm(w,X>>>0>>1>>>0?b>>>0>>0?s:b:a,((t[T>>2]|0)-M|0)/12|0,e+8|0),T=w+8|0,a=t[T>>2]|0,s=t[n+4>>2]|0,r=t[r>>2]|0,t[v>>2]=t[n>>2],t[v+4>>2]=s,t[u>>2]=t[v>>2],t[u+4>>2]=t[v+4>>2],Gh(a,u,r),t[T>>2]=(t[T>>2]|0)+12,Sm(e,w),Tm(w),y=L;return}}function np(e){return e=e|0,357913941}function wm(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=u;do if(n)if(n>>>0>357913941)$n();else{s=pn(n*12|0)|0;break}else s=0;while(0);t[e>>2]=s,u=s+(r*12|0)|0,t[e+8>>2]=u,t[e+4>>2]=u,t[e+12>>2]=s+(n*12|0)}function Sm(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0;u=t[e>>2]|0,v=e+4|0,a=n+4|0,s=(t[v>>2]|0)-u|0,r=(t[a>>2]|0)+(((s|0)/-12|0)*12|0)|0,t[a>>2]=r,(s|0)>0?(gr(r|0,u|0,s|0)|0,u=a,r=t[a>>2]|0):u=a,a=t[e>>2]|0,t[e>>2]=r,t[u>>2]=a,a=n+8|0,s=t[v>>2]|0,t[v>>2]=t[a>>2],t[a>>2]=s,a=e+8|0,v=n+12|0,e=t[a>>2]|0,t[a>>2]=t[v>>2],t[v>>2]=e,t[n>>2]=t[u>>2]}function Tm(e){e=e|0;var n=0,r=0,u=0;n=t[e+4>>2]|0,r=e+8|0,u=t[r>>2]|0,(u|0)!=(n|0)&&(t[r>>2]=u+(~(((u+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&Et(e)}function Kh(e){e=e|0,rp(e)}function _1(e){e=e|0,Cm(e+24|0)}function Cm(e){e=e|0;var n=0,r=0,u=0;r=t[e>>2]|0,u=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-u|0)>>>0)/12|0)*12|0)),Et(r))}function rp(e){e=e|0;var n=0;n=yr()|0,jn(e,2,5,n,ip()|0,0),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function ip(){return 1196}function xm(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0;return r=y,y=y+16|0,u=r+8|0,s=r,a=Rm(e)|0,e=t[a+4>>2]|0,t[s>>2]=t[a>>2],t[s+4>>2]=e,t[u>>2]=t[s>>2],t[u+4>>2]=t[s+4>>2],n=Xh(n,u)|0,y=r,n|0}function Rm(e){return e=e|0,(t[(ep()|0)+24>>2]|0)+(e*12|0)|0}function Xh(e,n){e=e|0,n=n|0;var r=0;return r=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(r=t[(t[e>>2]|0)+r>>2]|0),Sd(Qp[r&31](e)|0)|0}function Am(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0;u=y,y=y+16|0,s=u+8|0,a=u,w=t[r>>2]|0,v=t[r+4>>2]|0,r=Fr(n)|0,t[a>>2]=w,t[a+4>>2]=v,t[s>>2]=t[a>>2],t[s+4>>2]=t[a+4>>2],Om(e,r,s,1),y=u}function Om(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0,a=0,v=0,w=0,T=0,L=0,M=0;s=y,y=y+32|0,a=s+16|0,M=s+8|0,w=s,L=t[r>>2]|0,T=t[r+4>>2]|0,v=t[e>>2]|0,e=up()|0,t[M>>2]=L,t[M+4>>2]=T,t[a>>2]=t[M>>2],t[a+4>>2]=t[M+4>>2],r=op(a)|0,t[w>>2]=L,t[w+4>>2]=T,t[a>>2]=t[w>>2],t[a+4>>2]=t[w+4>>2],wi(v,n,e,r,Ta(a,u)|0,u),y=s}function up(){var e=0,n=0;if(h[7680]|0||(sp(9412),Wt(31,9412,ge|0)|0,n=7680,t[n>>2]=1,t[n+4>>2]=0),!(sr(9412)|0)){e=9412,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));sp(9412)}return 9412}function op(e){return e=e|0,0}function Ta(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0,b=0;return M=y,y=y+32|0,s=M+24|0,v=M+16|0,w=M,T=M+8|0,a=t[e>>2]|0,u=t[e+4>>2]|0,t[w>>2]=a,t[w+4>>2]=u,b=up()|0,L=b+24|0,e=hn(n,4)|0,t[T>>2]=e,n=b+28|0,r=t[n>>2]|0,r>>>0<(t[b+32>>2]|0)>>>0?(t[v>>2]=a,t[v+4>>2]=u,t[s>>2]=t[v>>2],t[s+4>>2]=t[v+4>>2],E1(r,s,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(lp(L,w,T),e=t[n>>2]|0),y=M,((e-(t[L>>2]|0)|0)/12|0)+-1|0}function E1(e,n,r){e=e|0,n=n|0,r=r|0;var u=0;u=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=u,t[e+8>>2]=r}function lp(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0,b=0,X=0;if(L=y,y=y+48|0,u=L+32|0,v=L+24|0,w=L,T=e+4|0,s=(((t[T>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,a=Qh(e)|0,a>>>0>>0)di(e);else{M=t[e>>2]|0,X=((t[e+8>>2]|0)-M|0)/12|0,b=X<<1,Cd(w,X>>>0>>1>>>0?b>>>0>>0?s:b:a,((t[T>>2]|0)-M|0)/12|0,e+8|0),T=w+8|0,a=t[T>>2]|0,s=t[n+4>>2]|0,r=t[r>>2]|0,t[v>>2]=t[n>>2],t[v+4>>2]=s,t[u>>2]=t[v>>2],t[u+4>>2]=t[v+4>>2],E1(a,u,r),t[T>>2]=(t[T>>2]|0)+12,D1(e,w),Jh(w),y=L;return}}function Qh(e){return e=e|0,357913941}function Cd(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=u;do if(n)if(n>>>0>357913941)$n();else{s=pn(n*12|0)|0;break}else s=0;while(0);t[e>>2]=s,u=s+(r*12|0)|0,t[e+8>>2]=u,t[e+4>>2]=u,t[e+12>>2]=s+(n*12|0)}function D1(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0;u=t[e>>2]|0,v=e+4|0,a=n+4|0,s=(t[v>>2]|0)-u|0,r=(t[a>>2]|0)+(((s|0)/-12|0)*12|0)|0,t[a>>2]=r,(s|0)>0?(gr(r|0,u|0,s|0)|0,u=a,r=t[a>>2]|0):u=a,a=t[e>>2]|0,t[e>>2]=r,t[u>>2]=a,a=n+8|0,s=t[v>>2]|0,t[v>>2]=t[a>>2],t[a>>2]=s,a=e+8|0,v=n+12|0,e=t[a>>2]|0,t[a>>2]=t[v>>2],t[v>>2]=e,t[n>>2]=t[u>>2]}function Jh(e){e=e|0;var n=0,r=0,u=0;n=t[e+4>>2]|0,r=e+8|0,u=t[r>>2]|0,(u|0)!=(n|0)&&(t[r>>2]=u+(~(((u+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&Et(e)}function sp(e){e=e|0,$h(e)}function Zh(e){e=e|0,ap(e+24|0)}function ap(e){e=e|0;var n=0,r=0,u=0;r=t[e>>2]|0,u=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-u|0)>>>0)/12|0)*12|0)),Et(r))}function $h(e){e=e|0;var n=0;n=yr()|0,jn(e,2,6,n,ev()|0,0),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function ev(){return 1200}function fp(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0;return r=y,y=y+16|0,u=r+8|0,s=r,a=xd(e)|0,e=t[a+4>>2]|0,t[s>>2]=t[a>>2],t[s+4>>2]=e,t[u>>2]=t[s>>2],t[u+4>>2]=t[s+4>>2],n=Rd(n,u)|0,y=r,n|0}function xd(e){return e=e|0,(t[(up()|0)+24>>2]|0)+(e*12|0)|0}function Rd(e,n){e=e|0,n=n|0;var r=0;return r=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(r=t[(t[e>>2]|0)+r>>2]|0),H0(Qp[r&31](e)|0)|0}function H0(e){return e=e|0,e|0}function Ad(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0;u=y,y=y+16|0,s=u+8|0,a=u,w=t[r>>2]|0,v=t[r+4>>2]|0,r=Fr(n)|0,t[a>>2]=w,t[a+4>>2]=v,t[s>>2]=t[a>>2],t[s+4>>2]=t[a+4>>2],Ca(e,r,s,0),y=u}function Ca(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0,a=0,v=0,w=0,T=0,L=0,M=0;s=y,y=y+32|0,a=s+16|0,M=s+8|0,w=s,L=t[r>>2]|0,T=t[r+4>>2]|0,v=t[e>>2]|0,e=$a()|0,t[M>>2]=L,t[M+4>>2]=T,t[a>>2]=t[M>>2],t[a+4>>2]=t[M+4>>2],r=Od(a)|0,t[w>>2]=L,t[w+4>>2]=T,t[a>>2]=t[w>>2],t[a+4>>2]=t[w+4>>2],wi(v,n,e,r,Md(a,u)|0,u),y=s}function $a(){var e=0,n=0;if(h[7688]|0||(pp(9448),Wt(32,9448,ge|0)|0,n=7688,t[n>>2]=1,t[n+4>>2]=0),!(sr(9448)|0)){e=9448,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));pp(9448)}return 9448}function Od(e){return e=e|0,0}function Md(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0,b=0;return M=y,y=y+32|0,s=M+24|0,v=M+16|0,w=M,T=M+8|0,a=t[e>>2]|0,u=t[e+4>>2]|0,t[w>>2]=a,t[w+4>>2]=u,b=$a()|0,L=b+24|0,e=hn(n,4)|0,t[T>>2]=e,n=b+28|0,r=t[n>>2]|0,r>>>0<(t[b+32>>2]|0)>>>0?(t[v>>2]=a,t[v+4>>2]=u,t[s>>2]=t[v>>2],t[s+4>>2]=t[v+4>>2],cp(r,s,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(kd(L,w,T),e=t[n>>2]|0),y=M,((e-(t[L>>2]|0)|0)/12|0)+-1|0}function cp(e,n,r){e=e|0,n=n|0,r=r|0;var u=0;u=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=u,t[e+8>>2]=r}function kd(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0,b=0,X=0;if(L=y,y=y+48|0,u=L+32|0,v=L+24|0,w=L,T=e+4|0,s=(((t[T>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,a=tv(e)|0,a>>>0>>0)di(e);else{M=t[e>>2]|0,X=((t[e+8>>2]|0)-M|0)/12|0,b=X<<1,Mm(w,X>>>0>>1>>>0?b>>>0>>0?s:b:a,((t[T>>2]|0)-M|0)/12|0,e+8|0),T=w+8|0,a=t[T>>2]|0,s=t[n+4>>2]|0,r=t[r>>2]|0,t[v>>2]=t[n>>2],t[v+4>>2]=s,t[u>>2]=t[v>>2],t[u+4>>2]=t[v+4>>2],cp(a,u,r),t[T>>2]=(t[T>>2]|0)+12,nv(e,w),dp(w),y=L;return}}function tv(e){return e=e|0,357913941}function Mm(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=u;do if(n)if(n>>>0>357913941)$n();else{s=pn(n*12|0)|0;break}else s=0;while(0);t[e>>2]=s,u=s+(r*12|0)|0,t[e+8>>2]=u,t[e+4>>2]=u,t[e+12>>2]=s+(n*12|0)}function nv(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0;u=t[e>>2]|0,v=e+4|0,a=n+4|0,s=(t[v>>2]|0)-u|0,r=(t[a>>2]|0)+(((s|0)/-12|0)*12|0)|0,t[a>>2]=r,(s|0)>0?(gr(r|0,u|0,s|0)|0,u=a,r=t[a>>2]|0):u=a,a=t[e>>2]|0,t[e>>2]=r,t[u>>2]=a,a=n+8|0,s=t[v>>2]|0,t[v>>2]=t[a>>2],t[a>>2]=s,a=e+8|0,v=n+12|0,e=t[a>>2]|0,t[a>>2]=t[v>>2],t[v>>2]=e,t[n>>2]=t[u>>2]}function dp(e){e=e|0;var n=0,r=0,u=0;n=t[e+4>>2]|0,r=e+8|0,u=t[r>>2]|0,(u|0)!=(n|0)&&(t[r>>2]=u+(~(((u+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&Et(e)}function pp(e){e=e|0,Nm(e)}function hp(e){e=e|0,km(e+24|0)}function km(e){e=e|0;var n=0,r=0,u=0;r=t[e>>2]|0,u=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-u|0)>>>0)/12|0)*12|0)),Et(r))}function Nm(e){e=e|0;var n=0;n=yr()|0,jn(e,2,6,n,So()|0,1),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function So(){return 1204}function Nd(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0;u=y,y=y+16|0,s=u+8|0,a=u,v=Lm(e)|0,e=t[v+4>>2]|0,t[a>>2]=t[v>>2],t[a+4>>2]=e,t[s>>2]=t[a>>2],t[s+4>>2]=t[a+4>>2],pl(n,s,r),y=u}function Lm(e){return e=e|0,(t[($a()|0)+24>>2]|0)+(e*12|0)|0}function pl(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0;a=y,y=y+16|0,s=a,u=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(u=t[(t[e>>2]|0)+u>>2]|0),tr(s,r),s=Qs(s,r)|0,I1[u&31](e,s),y=a}function tr(e,n){e=e|0,n=n|0}function Qs(e,n){return e=e|0,n=n|0,hl(n)|0}function hl(e){return e=e|0,e|0}function o0(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0;u=y,y=y+16|0,s=u+8|0,a=u,w=t[r>>2]|0,v=t[r+4>>2]|0,r=Fr(n)|0,t[a>>2]=w,t[a+4>>2]=v,t[s>>2]=t[a>>2],t[s+4>>2]=t[a+4>>2],rv(e,r,s,0),y=u}function rv(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0,a=0,v=0,w=0,T=0,L=0,M=0;s=y,y=y+32|0,a=s+16|0,M=s+8|0,w=s,L=t[r>>2]|0,T=t[r+4>>2]|0,v=t[e>>2]|0,e=Js()|0,t[M>>2]=L,t[M+4>>2]=T,t[a>>2]=t[M>>2],t[a+4>>2]=t[M+4>>2],r=vp(a)|0,t[w>>2]=L,t[w+4>>2]=T,t[a>>2]=t[w>>2],t[a+4>>2]=t[w+4>>2],wi(v,n,e,r,Fm(a,u)|0,u),y=s}function Js(){var e=0,n=0;if(h[7696]|0||(gp(9484),Wt(33,9484,ge|0)|0,n=7696,t[n>>2]=1,t[n+4>>2]=0),!(sr(9484)|0)){e=9484,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));gp(9484)}return 9484}function vp(e){return e=e|0,0}function Fm(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0,b=0;return M=y,y=y+32|0,s=M+24|0,v=M+16|0,w=M,T=M+8|0,a=t[e>>2]|0,u=t[e+4>>2]|0,t[w>>2]=a,t[w+4>>2]=u,b=Js()|0,L=b+24|0,e=hn(n,4)|0,t[T>>2]=e,n=b+28|0,r=t[n>>2]|0,r>>>0<(t[b+32>>2]|0)>>>0?(t[v>>2]=a,t[v+4>>2]=u,t[s>>2]=t[v>>2],t[s+4>>2]=t[v+4>>2],iv(r,s,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(mp(L,w,T),e=t[n>>2]|0),y=M,((e-(t[L>>2]|0)|0)/12|0)+-1|0}function iv(e,n,r){e=e|0,n=n|0,r=r|0;var u=0;u=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=u,t[e+8>>2]=r}function mp(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0,b=0,X=0;if(L=y,y=y+48|0,u=L+32|0,v=L+24|0,w=L,T=e+4|0,s=(((t[T>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,a=Pm(e)|0,a>>>0>>0)di(e);else{M=t[e>>2]|0,X=((t[e+8>>2]|0)-M|0)/12|0,b=X<<1,yp(w,X>>>0>>1>>>0?b>>>0>>0?s:b:a,((t[T>>2]|0)-M|0)/12|0,e+8|0),T=w+8|0,a=t[T>>2]|0,s=t[n+4>>2]|0,r=t[r>>2]|0,t[v>>2]=t[n>>2],t[v+4>>2]=s,t[u>>2]=t[v>>2],t[u+4>>2]=t[v+4>>2],iv(a,u,r),t[T>>2]=(t[T>>2]|0)+12,Tc(e,w),xa(w),y=L;return}}function Pm(e){return e=e|0,357913941}function yp(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=u;do if(n)if(n>>>0>357913941)$n();else{s=pn(n*12|0)|0;break}else s=0;while(0);t[e>>2]=s,u=s+(r*12|0)|0,t[e+8>>2]=u,t[e+4>>2]=u,t[e+12>>2]=s+(n*12|0)}function Tc(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0;u=t[e>>2]|0,v=e+4|0,a=n+4|0,s=(t[v>>2]|0)-u|0,r=(t[a>>2]|0)+(((s|0)/-12|0)*12|0)|0,t[a>>2]=r,(s|0)>0?(gr(r|0,u|0,s|0)|0,u=a,r=t[a>>2]|0):u=a,a=t[e>>2]|0,t[e>>2]=r,t[u>>2]=a,a=n+8|0,s=t[v>>2]|0,t[v>>2]=t[a>>2],t[a>>2]=s,a=e+8|0,v=n+12|0,e=t[a>>2]|0,t[a>>2]=t[v>>2],t[v>>2]=e,t[n>>2]=t[u>>2]}function xa(e){e=e|0;var n=0,r=0,u=0;n=t[e+4>>2]|0,r=e+8|0,u=t[r>>2]|0,(u|0)!=(n|0)&&(t[r>>2]=u+(~(((u+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&Et(e)}function gp(e){e=e|0,Gu(e)}function Ld(e){e=e|0,Iu(e+24|0)}function Iu(e){e=e|0;var n=0,r=0,u=0;r=t[e>>2]|0,u=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-u|0)>>>0)/12|0)*12|0)),Et(r))}function Gu(e){e=e|0;var n=0;n=yr()|0,jn(e,2,1,n,_p()|0,2),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function _p(){return 1212}function Ep(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0,a=0,v=0,w=0;s=y,y=y+16|0,a=s+8|0,v=s,w=uv(e)|0,e=t[w+4>>2]|0,t[v>>2]=t[w>>2],t[v+4>>2]=e,t[a>>2]=t[v>>2],t[a+4>>2]=t[v+4>>2],Im(n,a,r,u),y=s}function uv(e){return e=e|0,(t[(Js()|0)+24>>2]|0)+(e*12|0)|0}function Im(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0,a=0,v=0,w=0;w=y,y=y+16|0,a=w+1|0,v=w,s=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(s=t[(t[e>>2]|0)+s>>2]|0),tr(a,r),a=Qs(a,r)|0,Pf(v,u),v=If(v,u)|0,Fy[s&15](e,a,v),y=w}function bm(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0;u=y,y=y+16|0,s=u+8|0,a=u,w=t[r>>2]|0,v=t[r+4>>2]|0,r=Fr(n)|0,t[a>>2]=w,t[a+4>>2]=v,t[s>>2]=t[a>>2],t[s+4>>2]=t[a+4>>2],Bm(e,r,s,1),y=u}function Bm(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0,a=0,v=0,w=0,T=0,L=0,M=0;s=y,y=y+32|0,a=s+16|0,M=s+8|0,w=s,L=t[r>>2]|0,T=t[r+4>>2]|0,v=t[e>>2]|0,e=Fd()|0,t[M>>2]=L,t[M+4>>2]=T,t[a>>2]=t[M>>2],t[a+4>>2]=t[M+4>>2],r=ov(a)|0,t[w>>2]=L,t[w+4>>2]=T,t[a>>2]=t[w>>2],t[a+4>>2]=t[w+4>>2],wi(v,n,e,r,Cc(a,u)|0,u),y=s}function Fd(){var e=0,n=0;if(h[7704]|0||(lv(9520),Wt(34,9520,ge|0)|0,n=7704,t[n>>2]=1,t[n+4>>2]=0),!(sr(9520)|0)){e=9520,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));lv(9520)}return 9520}function ov(e){return e=e|0,0}function Cc(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0,b=0;return M=y,y=y+32|0,s=M+24|0,v=M+16|0,w=M,T=M+8|0,a=t[e>>2]|0,u=t[e+4>>2]|0,t[w>>2]=a,t[w+4>>2]=u,b=Fd()|0,L=b+24|0,e=hn(n,4)|0,t[T>>2]=e,n=b+28|0,r=t[n>>2]|0,r>>>0<(t[b+32>>2]|0)>>>0?(t[v>>2]=a,t[v+4>>2]=u,t[s>>2]=t[v>>2],t[s+4>>2]=t[v+4>>2],w1(r,s,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(Um(L,w,T),e=t[n>>2]|0),y=M,((e-(t[L>>2]|0)|0)/12|0)+-1|0}function w1(e,n,r){e=e|0,n=n|0,r=r|0;var u=0;u=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=u,t[e+8>>2]=r}function Um(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0,b=0,X=0;if(L=y,y=y+48|0,u=L+32|0,v=L+24|0,w=L,T=e+4|0,s=(((t[T>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,a=Pd(e)|0,a>>>0>>0)di(e);else{M=t[e>>2]|0,X=((t[e+8>>2]|0)-M|0)/12|0,b=X<<1,S1(w,X>>>0>>1>>>0?b>>>0>>0?s:b:a,((t[T>>2]|0)-M|0)/12|0,e+8|0),T=w+8|0,a=t[T>>2]|0,s=t[n+4>>2]|0,r=t[r>>2]|0,t[v>>2]=t[n>>2],t[v+4>>2]=s,t[u>>2]=t[v>>2],t[u+4>>2]=t[v+4>>2],w1(a,u,r),t[T>>2]=(t[T>>2]|0)+12,Bl(e,w),Ra(w),y=L;return}}function Pd(e){return e=e|0,357913941}function S1(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=u;do if(n)if(n>>>0>357913941)$n();else{s=pn(n*12|0)|0;break}else s=0;while(0);t[e>>2]=s,u=s+(r*12|0)|0,t[e+8>>2]=u,t[e+4>>2]=u,t[e+12>>2]=s+(n*12|0)}function Bl(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0;u=t[e>>2]|0,v=e+4|0,a=n+4|0,s=(t[v>>2]|0)-u|0,r=(t[a>>2]|0)+(((s|0)/-12|0)*12|0)|0,t[a>>2]=r,(s|0)>0?(gr(r|0,u|0,s|0)|0,u=a,r=t[a>>2]|0):u=a,a=t[e>>2]|0,t[e>>2]=r,t[u>>2]=a,a=n+8|0,s=t[v>>2]|0,t[v>>2]=t[a>>2],t[a>>2]=s,a=e+8|0,v=n+12|0,e=t[a>>2]|0,t[a>>2]=t[v>>2],t[v>>2]=e,t[n>>2]=t[u>>2]}function Ra(e){e=e|0;var n=0,r=0,u=0;n=t[e+4>>2]|0,r=e+8|0,u=t[r>>2]|0,(u|0)!=(n|0)&&(t[r>>2]=u+(~(((u+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&Et(e)}function lv(e){e=e|0,av(e)}function jm(e){e=e|0,sv(e+24|0)}function sv(e){e=e|0;var n=0,r=0,u=0;r=t[e>>2]|0,u=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-u|0)>>>0)/12|0)*12|0)),Et(r))}function av(e){e=e|0;var n=0;n=yr()|0,jn(e,2,1,n,zm()|0,1),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function zm(){return 1224}function fv(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0;return s=y,y=y+16|0,a=s+8|0,v=s,w=Aa(e)|0,e=t[w+4>>2]|0,t[v>>2]=t[w>>2],t[v+4>>2]=e,t[a>>2]=t[v>>2],t[a+4>>2]=t[v+4>>2],u=+Mr(n,a,r),y=s,+u}function Aa(e){return e=e|0,(t[(Fd()|0)+24>>2]|0)+(e*12|0)|0}function Mr(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0;return a=y,y=y+16|0,s=a,u=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(u=t[(t[e>>2]|0)+u>>2]|0),xs(s,r),s=Gs(s,r)|0,v=+Ga(+P8[u&7](e,s)),y=a,+v}function Dp(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0;u=y,y=y+16|0,s=u+8|0,a=u,w=t[r>>2]|0,v=t[r+4>>2]|0,r=Fr(n)|0,t[a>>2]=w,t[a+4>>2]=v,t[s>>2]=t[a>>2],t[s+4>>2]=t[a+4>>2],vl(e,r,s,1),y=u}function vl(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0,a=0,v=0,w=0,T=0,L=0,M=0;s=y,y=y+32|0,a=s+16|0,M=s+8|0,w=s,L=t[r>>2]|0,T=t[r+4>>2]|0,v=t[e>>2]|0,e=yu()|0,t[M>>2]=L,t[M+4>>2]=T,t[a>>2]=t[M>>2],t[a+4>>2]=t[M+4>>2],r=T1(a)|0,t[w>>2]=L,t[w+4>>2]=T,t[a>>2]=t[w>>2],t[a+4>>2]=t[w+4>>2],wi(v,n,e,r,Ui(a,u)|0,u),y=s}function yu(){var e=0,n=0;if(h[7712]|0||(Sp(9556),Wt(35,9556,ge|0)|0,n=7712,t[n>>2]=1,t[n+4>>2]=0),!(sr(9556)|0)){e=9556,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));Sp(9556)}return 9556}function T1(e){return e=e|0,0}function Ui(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0,b=0;return M=y,y=y+32|0,s=M+24|0,v=M+16|0,w=M,T=M+8|0,a=t[e>>2]|0,u=t[e+4>>2]|0,t[w>>2]=a,t[w+4>>2]=u,b=yu()|0,L=b+24|0,e=hn(n,4)|0,t[T>>2]=e,n=b+28|0,r=t[n>>2]|0,r>>>0<(t[b+32>>2]|0)>>>0?(t[v>>2]=a,t[v+4>>2]=u,t[s>>2]=t[v>>2],t[s+4>>2]=t[v+4>>2],wp(r,s,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(Id(L,w,T),e=t[n>>2]|0),y=M,((e-(t[L>>2]|0)|0)/12|0)+-1|0}function wp(e,n,r){e=e|0,n=n|0,r=r|0;var u=0;u=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=u,t[e+8>>2]=r}function Id(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0,b=0,X=0;if(L=y,y=y+48|0,u=L+32|0,v=L+24|0,w=L,T=e+4|0,s=(((t[T>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,a=To(e)|0,a>>>0>>0)di(e);else{M=t[e>>2]|0,X=((t[e+8>>2]|0)-M|0)/12|0,b=X<<1,As(w,X>>>0>>1>>>0?b>>>0>>0?s:b:a,((t[T>>2]|0)-M|0)/12|0,e+8|0),T=w+8|0,a=t[T>>2]|0,s=t[n+4>>2]|0,r=t[r>>2]|0,t[v>>2]=t[n>>2],t[v+4>>2]=s,t[u>>2]=t[v>>2],t[u+4>>2]=t[v+4>>2],wp(a,u,r),t[T>>2]=(t[T>>2]|0)+12,bf(e,w),bd(w),y=L;return}}function To(e){return e=e|0,357913941}function As(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=u;do if(n)if(n>>>0>357913941)$n();else{s=pn(n*12|0)|0;break}else s=0;while(0);t[e>>2]=s,u=s+(r*12|0)|0,t[e+8>>2]=u,t[e+4>>2]=u,t[e+12>>2]=s+(n*12|0)}function bf(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0;u=t[e>>2]|0,v=e+4|0,a=n+4|0,s=(t[v>>2]|0)-u|0,r=(t[a>>2]|0)+(((s|0)/-12|0)*12|0)|0,t[a>>2]=r,(s|0)>0?(gr(r|0,u|0,s|0)|0,u=a,r=t[a>>2]|0):u=a,a=t[e>>2]|0,t[e>>2]=r,t[u>>2]=a,a=n+8|0,s=t[v>>2]|0,t[v>>2]=t[a>>2],t[a>>2]=s,a=e+8|0,v=n+12|0,e=t[a>>2]|0,t[a>>2]=t[v>>2],t[v>>2]=e,t[n>>2]=t[u>>2]}function bd(e){e=e|0;var n=0,r=0,u=0;n=t[e+4>>2]|0,r=e+8|0,u=t[r>>2]|0,(u|0)!=(n|0)&&(t[r>>2]=u+(~(((u+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&Et(e)}function Sp(e){e=e|0,Tp(e)}function C1(e){e=e|0,x1(e+24|0)}function x1(e){e=e|0;var n=0,r=0,u=0;r=t[e>>2]|0,u=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-u|0)>>>0)/12|0)*12|0)),Et(r))}function Tp(e){e=e|0;var n=0;n=yr()|0,jn(e,2,5,n,nr()|0,0),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function nr(){return 1232}function ml(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0;return u=y,y=y+16|0,s=u+8|0,a=u,v=Gn(e)|0,e=t[v+4>>2]|0,t[a>>2]=t[v>>2],t[a+4>>2]=e,t[s>>2]=t[a>>2],t[s+4>>2]=t[a+4>>2],r=+q0(n,s),y=u,+r}function Gn(e){return e=e|0,(t[(yu()|0)+24>>2]|0)+(e*12|0)|0}function q0(e,n){e=e|0,n=n|0;var r=0;return r=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(r=t[(t[e>>2]|0)+r>>2]|0),+ +Ga(+F8[r&15](e))}function k0(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0;u=y,y=y+16|0,s=u+8|0,a=u,w=t[r>>2]|0,v=t[r+4>>2]|0,r=Fr(n)|0,t[a>>2]=w,t[a+4>>2]=v,t[s>>2]=t[a>>2],t[s+4>>2]=t[a+4>>2],Bd(e,r,s,1),y=u}function Bd(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0,a=0,v=0,w=0,T=0,L=0,M=0;s=y,y=y+32|0,a=s+16|0,M=s+8|0,w=s,L=t[r>>2]|0,T=t[r+4>>2]|0,v=t[e>>2]|0,e=Ul()|0,t[M>>2]=L,t[M+4>>2]=T,t[a>>2]=t[M>>2],t[a+4>>2]=t[M+4>>2],r=R1(a)|0,t[w>>2]=L,t[w+4>>2]=T,t[a>>2]=t[w>>2],t[a+4>>2]=t[w+4>>2],wi(v,n,e,r,xc(a,u)|0,u),y=s}function Ul(){var e=0,n=0;if(h[7720]|0||(zd(9592),Wt(36,9592,ge|0)|0,n=7720,t[n>>2]=1,t[n+4>>2]=0),!(sr(9592)|0)){e=9592,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));zd(9592)}return 9592}function R1(e){return e=e|0,0}function xc(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0,b=0;return M=y,y=y+32|0,s=M+24|0,v=M+16|0,w=M,T=M+8|0,a=t[e>>2]|0,u=t[e+4>>2]|0,t[w>>2]=a,t[w+4>>2]=u,b=Ul()|0,L=b+24|0,e=hn(n,4)|0,t[T>>2]=e,n=b+28|0,r=t[n>>2]|0,r>>>0<(t[b+32>>2]|0)>>>0?(t[v>>2]=a,t[v+4>>2]=u,t[s>>2]=t[v>>2],t[s+4>>2]=t[v+4>>2],Rc(r,s,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(Ud(L,w,T),e=t[n>>2]|0),y=M,((e-(t[L>>2]|0)|0)/12|0)+-1|0}function Rc(e,n,r){e=e|0,n=n|0,r=r|0;var u=0;u=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=u,t[e+8>>2]=r}function Ud(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0,b=0,X=0;if(L=y,y=y+48|0,u=L+32|0,v=L+24|0,w=L,T=e+4|0,s=(((t[T>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,a=Cp(e)|0,a>>>0>>0)di(e);else{M=t[e>>2]|0,X=((t[e+8>>2]|0)-M|0)/12|0,b=X<<1,N0(w,X>>>0>>1>>>0?b>>>0>>0?s:b:a,((t[T>>2]|0)-M|0)/12|0,e+8|0),T=w+8|0,a=t[T>>2]|0,s=t[n+4>>2]|0,r=t[r>>2]|0,t[v>>2]=t[n>>2],t[v+4>>2]=s,t[u>>2]=t[v>>2],t[u+4>>2]=t[v+4>>2],Rc(a,u,r),t[T>>2]=(t[T>>2]|0)+12,dn(e,w),jd(w),y=L;return}}function Cp(e){return e=e|0,357913941}function N0(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=u;do if(n)if(n>>>0>357913941)$n();else{s=pn(n*12|0)|0;break}else s=0;while(0);t[e>>2]=s,u=s+(r*12|0)|0,t[e+8>>2]=u,t[e+4>>2]=u,t[e+12>>2]=s+(n*12|0)}function dn(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0;u=t[e>>2]|0,v=e+4|0,a=n+4|0,s=(t[v>>2]|0)-u|0,r=(t[a>>2]|0)+(((s|0)/-12|0)*12|0)|0,t[a>>2]=r,(s|0)>0?(gr(r|0,u|0,s|0)|0,u=a,r=t[a>>2]|0):u=a,a=t[e>>2]|0,t[e>>2]=r,t[u>>2]=a,a=n+8|0,s=t[v>>2]|0,t[v>>2]=t[a>>2],t[a>>2]=s,a=e+8|0,v=n+12|0,e=t[a>>2]|0,t[a>>2]=t[v>>2],t[v>>2]=e,t[n>>2]=t[u>>2]}function jd(e){e=e|0;var n=0,r=0,u=0;n=t[e+4>>2]|0,r=e+8|0,u=t[r>>2]|0,(u|0)!=(n|0)&&(t[r>>2]=u+(~(((u+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&Et(e)}function zd(e){e=e|0,Mc(e)}function Ac(e){e=e|0,Oc(e+24|0)}function Oc(e){e=e|0;var n=0,r=0,u=0;r=t[e>>2]|0,u=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-u|0)>>>0)/12|0)*12|0)),Et(r))}function Mc(e){e=e|0;var n=0;n=yr()|0,jn(e,2,7,n,A1()|0,0),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function A1(){return 1276}function xp(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0;return r=y,y=y+16|0,u=r+8|0,s=r,a=ef(e)|0,e=t[a+4>>2]|0,t[s>>2]=t[a>>2],t[s+4>>2]=e,t[u>>2]=t[s>>2],t[u+4>>2]=t[s+4>>2],n=Hm(n,u)|0,y=r,n|0}function ef(e){return e=e|0,(t[(Ul()|0)+24>>2]|0)+(e*12|0)|0}function Hm(e,n){e=e|0,n=n|0;var r=0,u=0,s=0;return s=y,y=y+16|0,u=s,r=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(r=t[(t[e>>2]|0)+r>>2]|0),I1[r&31](u,e),u=kc(u)|0,y=s,u|0}function kc(e){e=e|0;var n=0,r=0,u=0,s=0;return s=y,y=y+32|0,n=s+12|0,r=s,u=Pu(Hd()|0)|0,u?(rs(n,u),Mf(r,n),cv(e,r),e=Cs(n)|0):e=O1(e)|0,y=s,e|0}function Hd(){var e=0;return h[7736]|0||(Wo(9640),Wt(25,9640,ge|0)|0,e=7736,t[e>>2]=1,t[e+4>>2]=0),9640}function cv(e,n){e=e|0,n=n|0,Nc(n,e,e+8|0)|0}function O1(e){e=e|0;var n=0,r=0,u=0,s=0,a=0,v=0,w=0;return r=y,y=y+16|0,s=r+4|0,v=r,u=Oa(8)|0,n=u,w=pn(16)|0,t[w>>2]=t[e>>2],t[w+4>>2]=t[e+4>>2],t[w+8>>2]=t[e+8>>2],t[w+12>>2]=t[e+12>>2],a=n+4|0,t[a>>2]=w,e=pn(8)|0,a=t[a>>2]|0,t[v>>2]=0,t[s>>2]=t[v>>2],Bf(e,a,s),t[u>>2]=e,y=r,n|0}function Bf(e,n,r){e=e|0,n=n|0,r=r|0,t[e>>2]=n,r=pn(16)|0,t[r+4>>2]=0,t[r+8>>2]=0,t[r>>2]=1244,t[r+12>>2]=n,t[e+4>>2]=r}function Uf(e){e=e|0,Uv(e),Et(e)}function M1(e){e=e|0,e=t[e+12>>2]|0,e|0&&Et(e)}function jl(e){e=e|0,Et(e)}function Nc(e,n,r){return e=e|0,n=n|0,r=r|0,n=jf(t[e>>2]|0,n,r)|0,r=e+4|0,t[(t[r>>2]|0)+8>>2]=n,t[(t[r>>2]|0)+8>>2]|0}function jf(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0;return u=y,y=y+16|0,s=u,Ma(s),e=go(e)|0,r=qm(e,t[n>>2]|0,+j[r>>3])|0,ka(s),y=u,r|0}function qm(e,n,r){e=e|0,n=n|0,r=+r;var u=0;return u=_o(yl()|0)|0,n=sd(n)|0,Hr(0,u|0,e|0,n|0,+ +kl(r))|0}function yl(){var e=0;return h[7728]|0||(qd(9628),e=7728,t[e>>2]=1,t[e+4>>2]=0),9628}function qd(e){e=e|0,ll(e,Wd()|0,2)}function Wd(){return 1264}function Wo(e){e=e|0,Xa(e)}function Vd(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0;u=y,y=y+16|0,s=u+8|0,a=u,w=t[r>>2]|0,v=t[r+4>>2]|0,r=Fr(n)|0,t[a>>2]=w,t[a+4>>2]=v,t[s>>2]=t[a>>2],t[s+4>>2]=t[a+4>>2],Wm(e,r,s,1),y=u}function Wm(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0,a=0,v=0,w=0,T=0,L=0,M=0;s=y,y=y+32|0,a=s+16|0,M=s+8|0,w=s,L=t[r>>2]|0,T=t[r+4>>2]|0,v=t[e>>2]|0,e=k1()|0,t[M>>2]=L,t[M+4>>2]=T,t[a>>2]=t[M>>2],t[a+4>>2]=t[M+4>>2],r=Vm(a)|0,t[w>>2]=L,t[w+4>>2]=T,t[a>>2]=t[w>>2],t[a+4>>2]=t[w+4>>2],wi(v,n,e,r,Gm(a,u)|0,u),y=s}function k1(){var e=0,n=0;if(h[7744]|0||(hv(9684),Wt(37,9684,ge|0)|0,n=7744,t[n>>2]=1,t[n+4>>2]=0),!(sr(9684)|0)){e=9684,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));hv(9684)}return 9684}function Vm(e){return e=e|0,0}function Gm(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0,b=0;return M=y,y=y+32|0,s=M+24|0,v=M+16|0,w=M,T=M+8|0,a=t[e>>2]|0,u=t[e+4>>2]|0,t[w>>2]=a,t[w+4>>2]=u,b=k1()|0,L=b+24|0,e=hn(n,4)|0,t[T>>2]=e,n=b+28|0,r=t[n>>2]|0,r>>>0<(t[b+32>>2]|0)>>>0?(t[v>>2]=a,t[v+4>>2]=u,t[s>>2]=t[v>>2],t[s+4>>2]=t[v+4>>2],dv(r,s,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(Ym(L,w,T),e=t[n>>2]|0),y=M,((e-(t[L>>2]|0)|0)/12|0)+-1|0}function dv(e,n,r){e=e|0,n=n|0,r=r|0;var u=0;u=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=u,t[e+8>>2]=r}function Ym(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0,b=0,X=0;if(L=y,y=y+48|0,u=L+32|0,v=L+24|0,w=L,T=e+4|0,s=(((t[T>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,a=pv(e)|0,a>>>0>>0)di(e);else{M=t[e>>2]|0,X=((t[e+8>>2]|0)-M|0)/12|0,b=X<<1,Km(w,X>>>0>>1>>>0?b>>>0>>0?s:b:a,((t[T>>2]|0)-M|0)/12|0,e+8|0),T=w+8|0,a=t[T>>2]|0,s=t[n+4>>2]|0,r=t[r>>2]|0,t[v>>2]=t[n>>2],t[v+4>>2]=s,t[u>>2]=t[v>>2],t[u+4>>2]=t[v+4>>2],dv(a,u,r),t[T>>2]=(t[T>>2]|0)+12,Xm(e,w),Qm(w),y=L;return}}function pv(e){return e=e|0,357913941}function Km(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=u;do if(n)if(n>>>0>357913941)$n();else{s=pn(n*12|0)|0;break}else s=0;while(0);t[e>>2]=s,u=s+(r*12|0)|0,t[e+8>>2]=u,t[e+4>>2]=u,t[e+12>>2]=s+(n*12|0)}function Xm(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0;u=t[e>>2]|0,v=e+4|0,a=n+4|0,s=(t[v>>2]|0)-u|0,r=(t[a>>2]|0)+(((s|0)/-12|0)*12|0)|0,t[a>>2]=r,(s|0)>0?(gr(r|0,u|0,s|0)|0,u=a,r=t[a>>2]|0):u=a,a=t[e>>2]|0,t[e>>2]=r,t[u>>2]=a,a=n+8|0,s=t[v>>2]|0,t[v>>2]=t[a>>2],t[a>>2]=s,a=e+8|0,v=n+12|0,e=t[a>>2]|0,t[a>>2]=t[v>>2],t[v>>2]=e,t[n>>2]=t[u>>2]}function Qm(e){e=e|0;var n=0,r=0,u=0;n=t[e+4>>2]|0,r=e+8|0,u=t[r>>2]|0,(u|0)!=(n|0)&&(t[r>>2]=u+(~(((u+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&Et(e)}function hv(e){e=e|0,Zm(e)}function Jm(e){e=e|0,Rp(e+24|0)}function Rp(e){e=e|0;var n=0,r=0,u=0;r=t[e>>2]|0,u=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-u|0)>>>0)/12|0)*12|0)),Et(r))}function Zm(e){e=e|0;var n=0;n=yr()|0,jn(e,2,5,n,zf()|0,1),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function zf(){return 1280}function vv(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0;return u=y,y=y+16|0,s=u+8|0,a=u,v=mv(e)|0,e=t[v+4>>2]|0,t[a>>2]=t[v>>2],t[a+4>>2]=e,t[s>>2]=t[a>>2],t[s+4>>2]=t[a+4>>2],r=yv(n,s,r)|0,y=u,r|0}function mv(e){return e=e|0,(t[(k1()|0)+24>>2]|0)+(e*12|0)|0}function yv(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0;return v=y,y=y+32|0,s=v,a=v+16|0,u=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(u=t[(t[e>>2]|0)+u>>2]|0),xs(a,r),a=Gs(a,r)|0,Fy[u&15](s,e,a),a=kc(s)|0,y=v,a|0}function Gd(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0;u=y,y=y+16|0,s=u+8|0,a=u,w=t[r>>2]|0,v=t[r+4>>2]|0,r=Fr(n)|0,t[a>>2]=w,t[a+4>>2]=v,t[s>>2]=t[a>>2],t[s+4>>2]=t[a+4>>2],Yd(e,r,s,1),y=u}function Yd(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0,a=0,v=0,w=0,T=0,L=0,M=0;s=y,y=y+32|0,a=s+16|0,M=s+8|0,w=s,L=t[r>>2]|0,T=t[r+4>>2]|0,v=t[e>>2]|0,e=Ap()|0,t[M>>2]=L,t[M+4>>2]=T,t[a>>2]=t[M>>2],t[a+4>>2]=t[M+4>>2],r=gv(a)|0,t[w>>2]=L,t[w+4>>2]=T,t[a>>2]=t[w>>2],t[a+4>>2]=t[w+4>>2],wi(v,n,e,r,Kd(a,u)|0,u),y=s}function Ap(){var e=0,n=0;if(h[7752]|0||(Sv(9720),Wt(38,9720,ge|0)|0,n=7752,t[n>>2]=1,t[n+4>>2]=0),!(sr(9720)|0)){e=9720,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));Sv(9720)}return 9720}function gv(e){return e=e|0,0}function Kd(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0,b=0;return M=y,y=y+32|0,s=M+24|0,v=M+16|0,w=M,T=M+8|0,a=t[e>>2]|0,u=t[e+4>>2]|0,t[w>>2]=a,t[w+4>>2]=u,b=Ap()|0,L=b+24|0,e=hn(n,4)|0,t[T>>2]=e,n=b+28|0,r=t[n>>2]|0,r>>>0<(t[b+32>>2]|0)>>>0?(t[v>>2]=a,t[v+4>>2]=u,t[s>>2]=t[v>>2],t[s+4>>2]=t[v+4>>2],_v(r,s,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(Ev(L,w,T),e=t[n>>2]|0),y=M,((e-(t[L>>2]|0)|0)/12|0)+-1|0}function _v(e,n,r){e=e|0,n=n|0,r=r|0;var u=0;u=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=u,t[e+8>>2]=r}function Ev(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0,b=0,X=0;if(L=y,y=y+48|0,u=L+32|0,v=L+24|0,w=L,T=e+4|0,s=(((t[T>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,a=Op(e)|0,a>>>0>>0)di(e);else{M=t[e>>2]|0,X=((t[e+8>>2]|0)-M|0)/12|0,b=X<<1,Dv(w,X>>>0>>1>>>0?b>>>0>>0?s:b:a,((t[T>>2]|0)-M|0)/12|0,e+8|0),T=w+8|0,a=t[T>>2]|0,s=t[n+4>>2]|0,r=t[r>>2]|0,t[v>>2]=t[n>>2],t[v+4>>2]=s,t[u>>2]=t[v>>2],t[u+4>>2]=t[v+4>>2],_v(a,u,r),t[T>>2]=(t[T>>2]|0)+12,wv(e,w),$m(w),y=L;return}}function Op(e){return e=e|0,357913941}function Dv(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=u;do if(n)if(n>>>0>357913941)$n();else{s=pn(n*12|0)|0;break}else s=0;while(0);t[e>>2]=s,u=s+(r*12|0)|0,t[e+8>>2]=u,t[e+4>>2]=u,t[e+12>>2]=s+(n*12|0)}function wv(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0;u=t[e>>2]|0,v=e+4|0,a=n+4|0,s=(t[v>>2]|0)-u|0,r=(t[a>>2]|0)+(((s|0)/-12|0)*12|0)|0,t[a>>2]=r,(s|0)>0?(gr(r|0,u|0,s|0)|0,u=a,r=t[a>>2]|0):u=a,a=t[e>>2]|0,t[e>>2]=r,t[u>>2]=a,a=n+8|0,s=t[v>>2]|0,t[v>>2]=t[a>>2],t[a>>2]=s,a=e+8|0,v=n+12|0,e=t[a>>2]|0,t[a>>2]=t[v>>2],t[v>>2]=e,t[n>>2]=t[u>>2]}function $m(e){e=e|0;var n=0,r=0,u=0;n=t[e+4>>2]|0,r=e+8|0,u=t[r>>2]|0,(u|0)!=(n|0)&&(t[r>>2]=u+(~(((u+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&Et(e)}function Sv(e){e=e|0,Tv(e)}function ey(e){e=e|0,Xd(e+24|0)}function Xd(e){e=e|0;var n=0,r=0,u=0;r=t[e>>2]|0,u=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-u|0)>>>0)/12|0)*12|0)),Et(r))}function Tv(e){e=e|0;var n=0;n=yr()|0,jn(e,2,8,n,Mp()|0,0),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function Mp(){return 1288}function ty(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0;return r=y,y=y+16|0,u=r+8|0,s=r,a=l0(e)|0,e=t[a+4>>2]|0,t[s>>2]=t[a>>2],t[s+4>>2]=e,t[u>>2]=t[s>>2],t[u+4>>2]=t[s+4>>2],n=kp(n,u)|0,y=r,n|0}function l0(e){return e=e|0,(t[(Ap()|0)+24>>2]|0)+(e*12|0)|0}function kp(e,n){e=e|0,n=n|0;var r=0;return r=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(r=t[(t[e>>2]|0)+r>>2]|0),cd(Qp[r&31](e)|0)|0}function ny(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0;u=y,y=y+16|0,s=u+8|0,a=u,w=t[r>>2]|0,v=t[r+4>>2]|0,r=Fr(n)|0,t[a>>2]=w,t[a+4>>2]=v,t[s>>2]=t[a>>2],t[s+4>>2]=t[a+4>>2],ry(e,r,s,0),y=u}function ry(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0,a=0,v=0,w=0,T=0,L=0,M=0;s=y,y=y+32|0,a=s+16|0,M=s+8|0,w=s,L=t[r>>2]|0,T=t[r+4>>2]|0,v=t[e>>2]|0,e=Np()|0,t[M>>2]=L,t[M+4>>2]=T,t[a>>2]=t[M>>2],t[a+4>>2]=t[M+4>>2],r=tf(a)|0,t[w>>2]=L,t[w+4>>2]=T,t[a>>2]=t[w>>2],t[a+4>>2]=t[w+4>>2],wi(v,n,e,r,Lp(a,u)|0,u),y=s}function Np(){var e=0,n=0;if(h[7760]|0||(Ip(9756),Wt(39,9756,ge|0)|0,n=7760,t[n>>2]=1,t[n+4>>2]=0),!(sr(9756)|0)){e=9756,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));Ip(9756)}return 9756}function tf(e){return e=e|0,0}function Lp(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0,b=0;return M=y,y=y+32|0,s=M+24|0,v=M+16|0,w=M,T=M+8|0,a=t[e>>2]|0,u=t[e+4>>2]|0,t[w>>2]=a,t[w+4>>2]=u,b=Np()|0,L=b+24|0,e=hn(n,4)|0,t[T>>2]=e,n=b+28|0,r=t[n>>2]|0,r>>>0<(t[b+32>>2]|0)>>>0?(t[v>>2]=a,t[v+4>>2]=u,t[s>>2]=t[v>>2],t[s+4>>2]=t[v+4>>2],Fp(r,s,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(Pp(L,w,T),e=t[n>>2]|0),y=M,((e-(t[L>>2]|0)|0)/12|0)+-1|0}function Fp(e,n,r){e=e|0,n=n|0,r=r|0;var u=0;u=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=u,t[e+8>>2]=r}function Pp(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0,b=0,X=0;if(L=y,y=y+48|0,u=L+32|0,v=L+24|0,w=L,T=e+4|0,s=(((t[T>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,a=iy(e)|0,a>>>0>>0)di(e);else{M=t[e>>2]|0,X=((t[e+8>>2]|0)-M|0)/12|0,b=X<<1,uy(w,X>>>0>>1>>>0?b>>>0>>0?s:b:a,((t[T>>2]|0)-M|0)/12|0,e+8|0),T=w+8|0,a=t[T>>2]|0,s=t[n+4>>2]|0,r=t[r>>2]|0,t[v>>2]=t[n>>2],t[v+4>>2]=s,t[u>>2]=t[v>>2],t[u+4>>2]=t[v+4>>2],Fp(a,u,r),t[T>>2]=(t[T>>2]|0)+12,Cv(e,w),Hf(w),y=L;return}}function iy(e){return e=e|0,357913941}function uy(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=u;do if(n)if(n>>>0>357913941)$n();else{s=pn(n*12|0)|0;break}else s=0;while(0);t[e>>2]=s,u=s+(r*12|0)|0,t[e+8>>2]=u,t[e+4>>2]=u,t[e+12>>2]=s+(n*12|0)}function Cv(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0;u=t[e>>2]|0,v=e+4|0,a=n+4|0,s=(t[v>>2]|0)-u|0,r=(t[a>>2]|0)+(((s|0)/-12|0)*12|0)|0,t[a>>2]=r,(s|0)>0?(gr(r|0,u|0,s|0)|0,u=a,r=t[a>>2]|0):u=a,a=t[e>>2]|0,t[e>>2]=r,t[u>>2]=a,a=n+8|0,s=t[v>>2]|0,t[v>>2]=t[a>>2],t[a>>2]=s,a=e+8|0,v=n+12|0,e=t[a>>2]|0,t[a>>2]=t[v>>2],t[v>>2]=e,t[n>>2]=t[u>>2]}function Hf(e){e=e|0;var n=0,r=0,u=0;n=t[e+4>>2]|0,r=e+8|0,u=t[r>>2]|0,(u|0)!=(n|0)&&(t[r>>2]=u+(~(((u+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&Et(e)}function Ip(e){e=e|0,ly(e)}function xv(e){e=e|0,oy(e+24|0)}function oy(e){e=e|0;var n=0,r=0,u=0;r=t[e>>2]|0,u=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-u|0)>>>0)/12|0)*12|0)),Et(r))}function ly(e){e=e|0;var n=0;n=yr()|0,jn(e,2,8,n,bp()|0,1),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function bp(){return 1292}function Bp(e,n,r){e=e|0,n=n|0,r=+r;var u=0,s=0,a=0,v=0;u=y,y=y+16|0,s=u+8|0,a=u,v=sy(e)|0,e=t[v+4>>2]|0,t[a>>2]=t[v>>2],t[a+4>>2]=e,t[s>>2]=t[a>>2],t[s+4>>2]=t[a+4>>2],ay(n,s,r),y=u}function sy(e){return e=e|0,(t[(Np()|0)+24>>2]|0)+(e*12|0)|0}function ay(e,n,r){e=e|0,n=n|0,r=+r;var u=0,s=0,a=0;a=y,y=y+16|0,s=a,u=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(u=t[(t[e>>2]|0)+u>>2]|0),Pl(s,r),r=+us(s,r),k8[u&31](e,r),y=a}function Rv(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0;u=y,y=y+16|0,s=u+8|0,a=u,w=t[r>>2]|0,v=t[r+4>>2]|0,r=Fr(n)|0,t[a>>2]=w,t[a+4>>2]=v,t[s>>2]=t[a>>2],t[s+4>>2]=t[a+4>>2],Up(e,r,s,0),y=u}function Up(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0,a=0,v=0,w=0,T=0,L=0,M=0;s=y,y=y+32|0,a=s+16|0,M=s+8|0,w=s,L=t[r>>2]|0,T=t[r+4>>2]|0,v=t[e>>2]|0,e=jp()|0,t[M>>2]=L,t[M+4>>2]=T,t[a>>2]=t[M>>2],t[a+4>>2]=t[M+4>>2],r=Qd(a)|0,t[w>>2]=L,t[w+4>>2]=T,t[a>>2]=t[w>>2],t[a+4>>2]=t[w+4>>2],wi(v,n,e,r,fy(a,u)|0,u),y=s}function jp(){var e=0,n=0;if(h[7768]|0||(zp(9792),Wt(40,9792,ge|0)|0,n=7768,t[n>>2]=1,t[n+4>>2]=0),!(sr(9792)|0)){e=9792,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));zp(9792)}return 9792}function Qd(e){return e=e|0,0}function fy(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0,b=0;return M=y,y=y+32|0,s=M+24|0,v=M+16|0,w=M,T=M+8|0,a=t[e>>2]|0,u=t[e+4>>2]|0,t[w>>2]=a,t[w+4>>2]=u,b=jp()|0,L=b+24|0,e=hn(n,4)|0,t[T>>2]=e,n=b+28|0,r=t[n>>2]|0,r>>>0<(t[b+32>>2]|0)>>>0?(t[v>>2]=a,t[v+4>>2]=u,t[s>>2]=t[v>>2],t[s+4>>2]=t[v+4>>2],N1(r,s,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(cy(L,w,T),e=t[n>>2]|0),y=M,((e-(t[L>>2]|0)|0)/12|0)+-1|0}function N1(e,n,r){e=e|0,n=n|0,r=r|0;var u=0;u=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=u,t[e+8>>2]=r}function cy(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0,b=0,X=0;if(L=y,y=y+48|0,u=L+32|0,v=L+24|0,w=L,T=e+4|0,s=(((t[T>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,a=Av(e)|0,a>>>0>>0)di(e);else{M=t[e>>2]|0,X=((t[e+8>>2]|0)-M|0)/12|0,b=X<<1,Ov(w,X>>>0>>1>>>0?b>>>0>>0?s:b:a,((t[T>>2]|0)-M|0)/12|0,e+8|0),T=w+8|0,a=t[T>>2]|0,s=t[n+4>>2]|0,r=t[r>>2]|0,t[v>>2]=t[n>>2],t[v+4>>2]=s,t[u>>2]=t[v>>2],t[u+4>>2]=t[v+4>>2],N1(a,u,r),t[T>>2]=(t[T>>2]|0)+12,dy(e,w),qf(w),y=L;return}}function Av(e){return e=e|0,357913941}function Ov(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=u;do if(n)if(n>>>0>357913941)$n();else{s=pn(n*12|0)|0;break}else s=0;while(0);t[e>>2]=s,u=s+(r*12|0)|0,t[e+8>>2]=u,t[e+4>>2]=u,t[e+12>>2]=s+(n*12|0)}function dy(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0;u=t[e>>2]|0,v=e+4|0,a=n+4|0,s=(t[v>>2]|0)-u|0,r=(t[a>>2]|0)+(((s|0)/-12|0)*12|0)|0,t[a>>2]=r,(s|0)>0?(gr(r|0,u|0,s|0)|0,u=a,r=t[a>>2]|0):u=a,a=t[e>>2]|0,t[e>>2]=r,t[u>>2]=a,a=n+8|0,s=t[v>>2]|0,t[v>>2]=t[a>>2],t[a>>2]=s,a=e+8|0,v=n+12|0,e=t[a>>2]|0,t[a>>2]=t[v>>2],t[v>>2]=e,t[n>>2]=t[u>>2]}function qf(e){e=e|0;var n=0,r=0,u=0;n=t[e+4>>2]|0,r=e+8|0,u=t[r>>2]|0,(u|0)!=(n|0)&&(t[r>>2]=u+(~(((u+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&Et(e)}function zp(e){e=e|0,hy(e)}function Mv(e){e=e|0,py(e+24|0)}function py(e){e=e|0;var n=0,r=0,u=0;r=t[e>>2]|0,u=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-u|0)>>>0)/12|0)*12|0)),Et(r))}function hy(e){e=e|0;var n=0;n=yr()|0,jn(e,2,1,n,Hp()|0,2),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function Hp(){return 1300}function vy(e,n,r,u){e=e|0,n=n|0,r=r|0,u=+u;var s=0,a=0,v=0,w=0;s=y,y=y+16|0,a=s+8|0,v=s,w=Zs(e)|0,e=t[w+4>>2]|0,t[v>>2]=t[w>>2],t[v+4>>2]=e,t[a>>2]=t[v>>2],t[a+4>>2]=t[v+4>>2],my(n,a,r,u),y=s}function Zs(e){return e=e|0,(t[(jp()|0)+24>>2]|0)+(e*12|0)|0}function my(e,n,r,u){e=e|0,n=n|0,r=r|0,u=+u;var s=0,a=0,v=0,w=0;w=y,y=y+16|0,a=w+1|0,v=w,s=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(s=t[(t[e>>2]|0)+s>>2]|0),xs(a,r),a=Gs(a,r)|0,Pl(v,u),u=+us(v,u),U8[s&15](e,a,u),y=w}function p(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0;u=y,y=y+16|0,s=u+8|0,a=u,w=t[r>>2]|0,v=t[r+4>>2]|0,r=Fr(n)|0,t[a>>2]=w,t[a+4>>2]=v,t[s>>2]=t[a>>2],t[s+4>>2]=t[a+4>>2],m(e,r,s,0),y=u}function m(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0,a=0,v=0,w=0,T=0,L=0,M=0;s=y,y=y+32|0,a=s+16|0,M=s+8|0,w=s,L=t[r>>2]|0,T=t[r+4>>2]|0,v=t[e>>2]|0,e=R()|0,t[M>>2]=L,t[M+4>>2]=T,t[a>>2]=t[M>>2],t[a+4>>2]=t[M+4>>2],r=I(a)|0,t[w>>2]=L,t[w+4>>2]=T,t[a>>2]=t[w>>2],t[a+4>>2]=t[w+4>>2],wi(v,n,e,r,W(a,u)|0,u),y=s}function R(){var e=0,n=0;if(h[7776]|0||(Ot(9828),Wt(41,9828,ge|0)|0,n=7776,t[n>>2]=1,t[n+4>>2]=0),!(sr(9828)|0)){e=9828,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));Ot(9828)}return 9828}function I(e){return e=e|0,0}function W(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0,b=0;return M=y,y=y+32|0,s=M+24|0,v=M+16|0,w=M,T=M+8|0,a=t[e>>2]|0,u=t[e+4>>2]|0,t[w>>2]=a,t[w+4>>2]=u,b=R()|0,L=b+24|0,e=hn(n,4)|0,t[T>>2]=e,n=b+28|0,r=t[n>>2]|0,r>>>0<(t[b+32>>2]|0)>>>0?(t[v>>2]=a,t[v+4>>2]=u,t[s>>2]=t[v>>2],t[s+4>>2]=t[v+4>>2],te(r,s,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(pe(L,w,T),e=t[n>>2]|0),y=M,((e-(t[L>>2]|0)|0)/12|0)+-1|0}function te(e,n,r){e=e|0,n=n|0,r=r|0;var u=0;u=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=u,t[e+8>>2]=r}function pe(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0,b=0,X=0;if(L=y,y=y+48|0,u=L+32|0,v=L+24|0,w=L,T=e+4|0,s=(((t[T>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,a=Ee(e)|0,a>>>0>>0)di(e);else{M=t[e>>2]|0,X=((t[e+8>>2]|0)-M|0)/12|0,b=X<<1,be(w,X>>>0>>1>>>0?b>>>0>>0?s:b:a,((t[T>>2]|0)-M|0)/12|0,e+8|0),T=w+8|0,a=t[T>>2]|0,s=t[n+4>>2]|0,r=t[r>>2]|0,t[v>>2]=t[n>>2],t[v+4>>2]=s,t[u>>2]=t[v>>2],t[u+4>>2]=t[v+4>>2],te(a,u,r),t[T>>2]=(t[T>>2]|0)+12,Dt(e,w),Tt(w),y=L;return}}function Ee(e){return e=e|0,357913941}function be(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=u;do if(n)if(n>>>0>357913941)$n();else{s=pn(n*12|0)|0;break}else s=0;while(0);t[e>>2]=s,u=s+(r*12|0)|0,t[e+8>>2]=u,t[e+4>>2]=u,t[e+12>>2]=s+(n*12|0)}function Dt(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0;u=t[e>>2]|0,v=e+4|0,a=n+4|0,s=(t[v>>2]|0)-u|0,r=(t[a>>2]|0)+(((s|0)/-12|0)*12|0)|0,t[a>>2]=r,(s|0)>0?(gr(r|0,u|0,s|0)|0,u=a,r=t[a>>2]|0):u=a,a=t[e>>2]|0,t[e>>2]=r,t[u>>2]=a,a=n+8|0,s=t[v>>2]|0,t[v>>2]=t[a>>2],t[a>>2]=s,a=e+8|0,v=n+12|0,e=t[a>>2]|0,t[a>>2]=t[v>>2],t[v>>2]=e,t[n>>2]=t[u>>2]}function Tt(e){e=e|0;var n=0,r=0,u=0;n=t[e+4>>2]|0,r=e+8|0,u=t[r>>2]|0,(u|0)!=(n|0)&&(t[r>>2]=u+(~(((u+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&Et(e)}function Ot(e){e=e|0,rr(e)}function on(e){e=e|0,Mn(e+24|0)}function Mn(e){e=e|0;var n=0,r=0,u=0;r=t[e>>2]|0,u=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-u|0)>>>0)/12|0)*12|0)),Et(r))}function rr(e){e=e|0;var n=0;n=yr()|0,jn(e,2,7,n,br()|0,1),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function br(){return 1312}function ar(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0;u=y,y=y+16|0,s=u+8|0,a=u,v=ri(e)|0,e=t[v+4>>2]|0,t[a>>2]=t[v>>2],t[a+4>>2]=e,t[s>>2]=t[a>>2],t[s+4>>2]=t[a+4>>2],fi(n,s,r),y=u}function ri(e){return e=e|0,(t[(R()|0)+24>>2]|0)+(e*12|0)|0}function fi(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0;a=y,y=y+16|0,s=a,u=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(u=t[(t[e>>2]|0)+u>>2]|0),xs(s,r),s=Gs(s,r)|0,I1[u&31](e,s),y=a}function zl(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0;u=y,y=y+16|0,s=u+8|0,a=u,w=t[r>>2]|0,v=t[r+4>>2]|0,r=Fr(n)|0,t[a>>2]=w,t[a+4>>2]=v,t[s>>2]=t[a>>2],t[s+4>>2]=t[a+4>>2],Zi(e,r,s,0),y=u}function Zi(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0,a=0,v=0,w=0,T=0,L=0,M=0;s=y,y=y+32|0,a=s+16|0,M=s+8|0,w=s,L=t[r>>2]|0,T=t[r+4>>2]|0,v=t[e>>2]|0,e=so()|0,t[M>>2]=L,t[M+4>>2]=T,t[a>>2]=t[M>>2],t[a+4>>2]=t[M+4>>2],r=s0(a)|0,t[w>>2]=L,t[w+4>>2]=T,t[a>>2]=t[w>>2],t[a+4>>2]=t[w+4>>2],wi(v,n,e,r,Os(a,u)|0,u),y=s}function so(){var e=0,n=0;if(h[7784]|0||(Vg(9864),Wt(42,9864,ge|0)|0,n=7784,t[n>>2]=1,t[n+4>>2]=0),!(sr(9864)|0)){e=9864,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));Vg(9864)}return 9864}function s0(e){return e=e|0,0}function Os(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0,b=0;return M=y,y=y+32|0,s=M+24|0,v=M+16|0,w=M,T=M+8|0,a=t[e>>2]|0,u=t[e+4>>2]|0,t[w>>2]=a,t[w+4>>2]=u,b=so()|0,L=b+24|0,e=hn(n,4)|0,t[T>>2]=e,n=b+28|0,r=t[n>>2]|0,r>>>0<(t[b+32>>2]|0)>>>0?(t[v>>2]=a,t[v+4>>2]=u,t[s>>2]=t[v>>2],t[s+4>>2]=t[v+4>>2],Co(r,s,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(kv(L,w,T),e=t[n>>2]|0),y=M,((e-(t[L>>2]|0)|0)/12|0)+-1|0}function Co(e,n,r){e=e|0,n=n|0,r=r|0;var u=0;u=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=u,t[e+8>>2]=r}function kv(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0,b=0,X=0;if(L=y,y=y+48|0,u=L+32|0,v=L+24|0,w=L,T=e+4|0,s=(((t[T>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,a=F4(e)|0,a>>>0>>0)di(e);else{M=t[e>>2]|0,X=((t[e+8>>2]|0)-M|0)/12|0,b=X<<1,yy(w,X>>>0>>1>>>0?b>>>0>>0?s:b:a,((t[T>>2]|0)-M|0)/12|0,e+8|0),T=w+8|0,a=t[T>>2]|0,s=t[n+4>>2]|0,r=t[r>>2]|0,t[v>>2]=t[n>>2],t[v+4>>2]=s,t[u>>2]=t[v>>2],t[u+4>>2]=t[v+4>>2],Co(a,u,r),t[T>>2]=(t[T>>2]|0)+12,gy(e,w),nf(w),y=L;return}}function F4(e){return e=e|0,357913941}function yy(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=u;do if(n)if(n>>>0>357913941)$n();else{s=pn(n*12|0)|0;break}else s=0;while(0);t[e>>2]=s,u=s+(r*12|0)|0,t[e+8>>2]=u,t[e+4>>2]=u,t[e+12>>2]=s+(n*12|0)}function gy(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0;u=t[e>>2]|0,v=e+4|0,a=n+4|0,s=(t[v>>2]|0)-u|0,r=(t[a>>2]|0)+(((s|0)/-12|0)*12|0)|0,t[a>>2]=r,(s|0)>0?(gr(r|0,u|0,s|0)|0,u=a,r=t[a>>2]|0):u=a,a=t[e>>2]|0,t[e>>2]=r,t[u>>2]=a,a=n+8|0,s=t[v>>2]|0,t[v>>2]=t[a>>2],t[a>>2]=s,a=e+8|0,v=n+12|0,e=t[a>>2]|0,t[a>>2]=t[v>>2],t[v>>2]=e,t[n>>2]=t[u>>2]}function nf(e){e=e|0;var n=0,r=0,u=0;n=t[e+4>>2]|0,r=e+8|0,u=t[r>>2]|0,(u|0)!=(n|0)&&(t[r>>2]=u+(~(((u+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&Et(e)}function Vg(e){e=e|0,b4(e)}function P4(e){e=e|0,I4(e+24|0)}function I4(e){e=e|0;var n=0,r=0,u=0;r=t[e>>2]|0,u=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-u|0)>>>0)/12|0)*12|0)),Et(r))}function b4(e){e=e|0;var n=0;n=yr()|0,jn(e,2,8,n,B4()|0,1),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function B4(){return 1320}function _y(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0;u=y,y=y+16|0,s=u+8|0,a=u,v=U4(e)|0,e=t[v+4>>2]|0,t[a>>2]=t[v>>2],t[a+4>>2]=e,t[s>>2]=t[a>>2],t[s+4>>2]=t[a+4>>2],j4(n,s,r),y=u}function U4(e){return e=e|0,(t[(so()|0)+24>>2]|0)+(e*12|0)|0}function j4(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0;a=y,y=y+16|0,s=a,u=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(u=t[(t[e>>2]|0)+u>>2]|0),Ey(s,r),s=Gg(s,r)|0,I1[u&31](e,s),y=a}function Ey(e,n){e=e|0,n=n|0}function Gg(e,n){return e=e|0,n=n|0,z4(n)|0}function z4(e){return e=e|0,e|0}function H4(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0;u=y,y=y+16|0,s=u+8|0,a=u,w=t[r>>2]|0,v=t[r+4>>2]|0,r=Fr(n)|0,t[a>>2]=w,t[a+4>>2]=v,t[s>>2]=t[a>>2],t[s+4>>2]=t[a+4>>2],Yg(e,r,s,0),y=u}function Yg(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0,a=0,v=0,w=0,T=0,L=0,M=0;s=y,y=y+32|0,a=s+16|0,M=s+8|0,w=s,L=t[r>>2]|0,T=t[r+4>>2]|0,v=t[e>>2]|0,e=Wf()|0,t[M>>2]=L,t[M+4>>2]=T,t[a>>2]=t[M>>2],t[a+4>>2]=t[M+4>>2],r=Kg(a)|0,t[w>>2]=L,t[w+4>>2]=T,t[a>>2]=t[w>>2],t[a+4>>2]=t[w+4>>2],wi(v,n,e,r,q4(a,u)|0,u),y=s}function Wf(){var e=0,n=0;if(h[7792]|0||(Sy(9900),Wt(43,9900,ge|0)|0,n=7792,t[n>>2]=1,t[n+4>>2]=0),!(sr(9900)|0)){e=9900,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));Sy(9900)}return 9900}function Kg(e){return e=e|0,0}function q4(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0,b=0;return M=y,y=y+32|0,s=M+24|0,v=M+16|0,w=M,T=M+8|0,a=t[e>>2]|0,u=t[e+4>>2]|0,t[w>>2]=a,t[w+4>>2]=u,b=Wf()|0,L=b+24|0,e=hn(n,4)|0,t[T>>2]=e,n=b+28|0,r=t[n>>2]|0,r>>>0<(t[b+32>>2]|0)>>>0?(t[v>>2]=a,t[v+4>>2]=u,t[s>>2]=t[v>>2],t[s+4>>2]=t[v+4>>2],qp(r,s,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(W4(L,w,T),e=t[n>>2]|0),y=M,((e-(t[L>>2]|0)|0)/12|0)+-1|0}function qp(e,n,r){e=e|0,n=n|0,r=r|0;var u=0;u=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=u,t[e+8>>2]=r}function W4(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0,b=0,X=0;if(L=y,y=y+48|0,u=L+32|0,v=L+24|0,w=L,T=e+4|0,s=(((t[T>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,a=Nv(e)|0,a>>>0>>0)di(e);else{M=t[e>>2]|0,X=((t[e+8>>2]|0)-M|0)/12|0,b=X<<1,Dy(w,X>>>0>>1>>>0?b>>>0>>0?s:b:a,((t[T>>2]|0)-M|0)/12|0,e+8|0),T=w+8|0,a=t[T>>2]|0,s=t[n+4>>2]|0,r=t[r>>2]|0,t[v>>2]=t[n>>2],t[v+4>>2]=s,t[u>>2]=t[v>>2],t[u+4>>2]=t[v+4>>2],qp(a,u,r),t[T>>2]=(t[T>>2]|0)+12,wy(e,w),V4(w),y=L;return}}function Nv(e){return e=e|0,357913941}function Dy(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=u;do if(n)if(n>>>0>357913941)$n();else{s=pn(n*12|0)|0;break}else s=0;while(0);t[e>>2]=s,u=s+(r*12|0)|0,t[e+8>>2]=u,t[e+4>>2]=u,t[e+12>>2]=s+(n*12|0)}function wy(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0;u=t[e>>2]|0,v=e+4|0,a=n+4|0,s=(t[v>>2]|0)-u|0,r=(t[a>>2]|0)+(((s|0)/-12|0)*12|0)|0,t[a>>2]=r,(s|0)>0?(gr(r|0,u|0,s|0)|0,u=a,r=t[a>>2]|0):u=a,a=t[e>>2]|0,t[e>>2]=r,t[u>>2]=a,a=n+8|0,s=t[v>>2]|0,t[v>>2]=t[a>>2],t[a>>2]=s,a=e+8|0,v=n+12|0,e=t[a>>2]|0,t[a>>2]=t[v>>2],t[v>>2]=e,t[n>>2]=t[u>>2]}function V4(e){e=e|0;var n=0,r=0,u=0;n=t[e+4>>2]|0,r=e+8|0,u=t[r>>2]|0,(u|0)!=(n|0)&&(t[r>>2]=u+(~(((u+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&Et(e)}function Sy(e){e=e|0,Xg(e)}function G4(e){e=e|0,Y4(e+24|0)}function Y4(e){e=e|0;var n=0,r=0,u=0;r=t[e>>2]|0,u=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-u|0)>>>0)/12|0)*12|0)),Et(r))}function Xg(e){e=e|0;var n=0;n=yr()|0,jn(e,2,22,n,K4()|0,0),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function K4(){return 1344}function X4(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0;r=y,y=y+16|0,u=r+8|0,s=r,a=Qg(e)|0,e=t[a+4>>2]|0,t[s>>2]=t[a>>2],t[s+4>>2]=e,t[u>>2]=t[s>>2],t[u+4>>2]=t[s+4>>2],Lv(n,u),y=r}function Qg(e){return e=e|0,(t[(Wf()|0)+24>>2]|0)+(e*12|0)|0}function Lv(e,n){e=e|0,n=n|0;var r=0;r=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(r=t[(t[e>>2]|0)+r>>2]|0),P1[r&127](e)}function Q4(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0,a=0;a=t[e>>2]|0,s=Ty()|0,e=J4(r)|0,wi(a,n,s,e,Z4(r,u)|0,u)}function Ty(){var e=0,n=0;if(h[7800]|0||(xy(9936),Wt(44,9936,ge|0)|0,n=7800,t[n>>2]=1,t[n+4>>2]=0),!(sr(9936)|0)){e=9936,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));xy(9936)}return 9936}function J4(e){return e=e|0,e|0}function Z4(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0,w=0,T=0;return w=y,y=y+16|0,s=w,a=w+4|0,t[s>>2]=e,T=Ty()|0,v=T+24|0,n=hn(n,4)|0,t[a>>2]=n,r=T+28|0,u=t[r>>2]|0,u>>>0<(t[T+32>>2]|0)>>>0?(Cy(u,e,n),n=(t[r>>2]|0)+8|0,t[r>>2]=n):(Jg(v,s,a),n=t[r>>2]|0),y=w,(n-(t[v>>2]|0)>>3)+-1|0}function Cy(e,n,r){e=e|0,n=n|0,r=r|0,t[e>>2]=n,t[e+4>>2]=r}function Jg(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0;if(w=y,y=y+32|0,s=w,a=e+4|0,v=((t[a>>2]|0)-(t[e>>2]|0)>>3)+1|0,u=Zg(e)|0,u>>>0>>0)di(e);else{T=t[e>>2]|0,M=(t[e+8>>2]|0)-T|0,L=M>>2,$g(s,M>>3>>>0>>1>>>0?L>>>0>>0?v:L:u,(t[a>>2]|0)-T>>3,e+8|0),v=s+8|0,Cy(t[v>>2]|0,t[n>>2]|0,t[r>>2]|0),t[v>>2]=(t[v>>2]|0)+8,e_(e,s),t_(s),y=w;return}}function Zg(e){return e=e|0,536870911}function $g(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=u;do if(n)if(n>>>0>536870911)$n();else{s=pn(n<<3)|0;break}else s=0;while(0);t[e>>2]=s,u=s+(r<<3)|0,t[e+8>>2]=u,t[e+4>>2]=u,t[e+12>>2]=s+(n<<3)}function e_(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0;u=t[e>>2]|0,v=e+4|0,a=n+4|0,s=(t[v>>2]|0)-u|0,r=(t[a>>2]|0)+(0-(s>>3)<<3)|0,t[a>>2]=r,(s|0)>0?(gr(r|0,u|0,s|0)|0,u=a,r=t[a>>2]|0):u=a,a=t[e>>2]|0,t[e>>2]=r,t[u>>2]=a,a=n+8|0,s=t[v>>2]|0,t[v>>2]=t[a>>2],t[a>>2]=s,a=e+8|0,v=n+12|0,e=t[a>>2]|0,t[a>>2]=t[v>>2],t[v>>2]=e,t[n>>2]=t[u>>2]}function t_(e){e=e|0;var n=0,r=0,u=0;n=t[e+4>>2]|0,r=e+8|0,u=t[r>>2]|0,(u|0)!=(n|0)&&(t[r>>2]=u+(~((u+-8-n|0)>>>3)<<3)),e=t[e>>2]|0,e|0&&Et(e)}function xy(e){e=e|0,r_(e)}function n_(e){e=e|0,$4(e+24|0)}function $4(e){e=e|0;var n=0,r=0,u=0;r=t[e>>2]|0,u=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-8-u|0)>>>3)<<3)),Et(r))}function r_(e){e=e|0;var n=0;n=yr()|0,jn(e,1,23,n,So()|0,1),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function eE(e,n){e=e|0,n=n|0,c(t[(tE(e)|0)>>2]|0,n)}function tE(e){return e=e|0,(t[(Ty()|0)+24>>2]|0)+(e<<3)|0}function c(e,n){e=e|0,n=n|0;var r=0,u=0;r=y,y=y+16|0,u=r,tr(u,n),n=Qs(u,n)|0,P1[e&127](n),y=r}function d(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0,a=0;a=t[e>>2]|0,s=D()|0,e=C(r)|0,wi(a,n,s,e,O(r,u)|0,u)}function D(){var e=0,n=0;if(h[7808]|0||(ht(9972),Wt(45,9972,ge|0)|0,n=7808,t[n>>2]=1,t[n+4>>2]=0),!(sr(9972)|0)){e=9972,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));ht(9972)}return 9972}function C(e){return e=e|0,e|0}function O(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0,w=0,T=0;return w=y,y=y+16|0,s=w,a=w+4|0,t[s>>2]=e,T=D()|0,v=T+24|0,n=hn(n,4)|0,t[a>>2]=n,r=T+28|0,u=t[r>>2]|0,u>>>0<(t[T+32>>2]|0)>>>0?(z(u,e,n),n=(t[r>>2]|0)+8|0,t[r>>2]=n):(G(v,s,a),n=t[r>>2]|0),y=w,(n-(t[v>>2]|0)>>3)+-1|0}function z(e,n,r){e=e|0,n=n|0,r=r|0,t[e>>2]=n,t[e+4>>2]=r}function G(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0;if(w=y,y=y+32|0,s=w,a=e+4|0,v=((t[a>>2]|0)-(t[e>>2]|0)>>3)+1|0,u=ne(e)|0,u>>>0>>0)di(e);else{T=t[e>>2]|0,M=(t[e+8>>2]|0)-T|0,L=M>>2,se(s,M>>3>>>0>>1>>>0?L>>>0>>0?v:L:u,(t[a>>2]|0)-T>>3,e+8|0),v=s+8|0,z(t[v>>2]|0,t[n>>2]|0,t[r>>2]|0),t[v>>2]=(t[v>>2]|0)+8,Ue(e,s),Xe(s),y=w;return}}function ne(e){return e=e|0,536870911}function se(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=u;do if(n)if(n>>>0>536870911)$n();else{s=pn(n<<3)|0;break}else s=0;while(0);t[e>>2]=s,u=s+(r<<3)|0,t[e+8>>2]=u,t[e+4>>2]=u,t[e+12>>2]=s+(n<<3)}function Ue(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0;u=t[e>>2]|0,v=e+4|0,a=n+4|0,s=(t[v>>2]|0)-u|0,r=(t[a>>2]|0)+(0-(s>>3)<<3)|0,t[a>>2]=r,(s|0)>0?(gr(r|0,u|0,s|0)|0,u=a,r=t[a>>2]|0):u=a,a=t[e>>2]|0,t[e>>2]=r,t[u>>2]=a,a=n+8|0,s=t[v>>2]|0,t[v>>2]=t[a>>2],t[a>>2]=s,a=e+8|0,v=n+12|0,e=t[a>>2]|0,t[a>>2]=t[v>>2],t[v>>2]=e,t[n>>2]=t[u>>2]}function Xe(e){e=e|0;var n=0,r=0,u=0;n=t[e+4>>2]|0,r=e+8|0,u=t[r>>2]|0,(u|0)!=(n|0)&&(t[r>>2]=u+(~((u+-8-n|0)>>>3)<<3)),e=t[e>>2]|0,e|0&&Et(e)}function ht(e){e=e|0,Ht(e)}function Lt(e){e=e|0,Gt(e+24|0)}function Gt(e){e=e|0;var n=0,r=0,u=0;r=t[e>>2]|0,u=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-8-u|0)>>>3)<<3)),Et(r))}function Ht(e){e=e|0;var n=0;n=yr()|0,jn(e,1,9,n,yn()|0,1),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function yn(){return 1348}function kr(e,n){return e=e|0,n=n|0,Oi(t[(ii(e)|0)>>2]|0,n)|0}function ii(e){return e=e|0,(t[(D()|0)+24>>2]|0)+(e<<3)|0}function Oi(e,n){e=e|0,n=n|0;var r=0,u=0;return r=y,y=y+16|0,u=r,L0(u,n),n=$i(u,n)|0,n=Sd(Qp[e&31](n)|0)|0,y=r,n|0}function L0(e,n){e=e|0,n=n|0}function $i(e,n){return e=e|0,n=n|0,lt(n)|0}function lt(e){return e=e|0,e|0}function Mt(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0,a=0;a=t[e>>2]|0,s=$e()|0,e=jt(r)|0,wi(a,n,s,e,Fn(r,u)|0,u)}function $e(){var e=0,n=0;if(h[7816]|0||(Yr(10008),Wt(46,10008,ge|0)|0,n=7816,t[n>>2]=1,t[n+4>>2]=0),!(sr(10008)|0)){e=10008,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));Yr(10008)}return 10008}function jt(e){return e=e|0,e|0}function Fn(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0,w=0,T=0;return w=y,y=y+16|0,s=w,a=w+4|0,t[s>>2]=e,T=$e()|0,v=T+24|0,n=hn(n,4)|0,t[a>>2]=n,r=T+28|0,u=t[r>>2]|0,u>>>0<(t[T+32>>2]|0)>>>0?(vn(u,e,n),n=(t[r>>2]|0)+8|0,t[r>>2]=n):(Vi(v,s,a),n=t[r>>2]|0),y=w,(n-(t[v>>2]|0)>>3)+-1|0}function vn(e,n,r){e=e|0,n=n|0,r=r|0,t[e>>2]=n,t[e+4>>2]=r}function Vi(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0;if(w=y,y=y+32|0,s=w,a=e+4|0,v=((t[a>>2]|0)-(t[e>>2]|0)>>3)+1|0,u=ci(e)|0,u>>>0>>0)di(e);else{T=t[e>>2]|0,M=(t[e+8>>2]|0)-T|0,L=M>>2,Yu(s,M>>3>>>0>>1>>>0?L>>>0>>0?v:L:u,(t[a>>2]|0)-T>>3,e+8|0),v=s+8|0,vn(t[v>>2]|0,t[n>>2]|0,t[r>>2]|0),t[v>>2]=(t[v>>2]|0)+8,hr(e,s),pu(s),y=w;return}}function ci(e){return e=e|0,536870911}function Yu(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=u;do if(n)if(n>>>0>536870911)$n();else{s=pn(n<<3)|0;break}else s=0;while(0);t[e>>2]=s,u=s+(r<<3)|0,t[e+8>>2]=u,t[e+4>>2]=u,t[e+12>>2]=s+(n<<3)}function hr(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0;u=t[e>>2]|0,v=e+4|0,a=n+4|0,s=(t[v>>2]|0)-u|0,r=(t[a>>2]|0)+(0-(s>>3)<<3)|0,t[a>>2]=r,(s|0)>0?(gr(r|0,u|0,s|0)|0,u=a,r=t[a>>2]|0):u=a,a=t[e>>2]|0,t[e>>2]=r,t[u>>2]=a,a=n+8|0,s=t[v>>2]|0,t[v>>2]=t[a>>2],t[a>>2]=s,a=e+8|0,v=n+12|0,e=t[a>>2]|0,t[a>>2]=t[v>>2],t[v>>2]=e,t[n>>2]=t[u>>2]}function pu(e){e=e|0;var n=0,r=0,u=0;n=t[e+4>>2]|0,r=e+8|0,u=t[r>>2]|0,(u|0)!=(n|0)&&(t[r>>2]=u+(~((u+-8-n|0)>>>3)<<3)),e=t[e>>2]|0,e|0&&Et(e)}function Yr(e){e=e|0,W0(e)}function Cu(e){e=e|0,D0(e+24|0)}function D0(e){e=e|0;var n=0,r=0,u=0;r=t[e>>2]|0,u=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-8-u|0)>>>3)<<3)),Et(r))}function W0(e){e=e|0;var n=0;n=yr()|0,jn(e,1,15,n,ip()|0,0),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function Ms(e){return e=e|0,gl(t[(Ku(e)|0)>>2]|0)|0}function Ku(e){return e=e|0,(t[($e()|0)+24>>2]|0)+(e<<3)|0}function gl(e){return e=e|0,Sd(E_[e&7]()|0)|0}function rf(){var e=0;return h[7832]|0||(u_(10052),Wt(25,10052,ge|0)|0,e=7832,t[e>>2]=1,t[e+4>>2]=0),10052}function Vo(e,n){e=e|0,n=n|0,t[e>>2]=ks()|0,t[e+4>>2]=Jd()|0,t[e+12>>2]=n,t[e+8>>2]=Vf()|0,t[e+32>>2]=2}function ks(){return 11709}function Jd(){return 1188}function Vf(){return L1()|0}function Lc(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0,(Hl(u,896)|0)==512?r|0&&(Go(r),Et(r)):n|0&&(Ds(n),Et(n))}function Hl(e,n){return e=e|0,n=n|0,n&e|0}function Go(e){e=e|0,e=t[e+4>>2]|0,e|0&&$d(e)}function L1(){var e=0;return h[7824]|0||(t[2511]=i_()|0,t[2512]=0,e=7824,t[e>>2]=1,t[e+4>>2]=0),10044}function i_(){return 0}function u_(e){e=e|0,Xa(e)}function nE(e){e=e|0;var n=0,r=0,u=0,s=0,a=0;n=y,y=y+32|0,r=n+24|0,a=n+16|0,s=n+8|0,u=n,o_(e,4827),rE(e,4834,3)|0,iE(e,3682,47)|0,t[a>>2]=9,t[a+4>>2]=0,t[r>>2]=t[a>>2],t[r+4>>2]=t[a+4>>2],Ry(e,4841,r)|0,t[s>>2]=1,t[s+4>>2]=0,t[r>>2]=t[s>>2],t[r+4>>2]=t[s+4>>2],l_(e,4871,r)|0,t[u>>2]=10,t[u+4>>2]=0,t[r>>2]=t[u>>2],t[r+4>>2]=t[u+4>>2],uE(e,4891,r)|0,y=n}function o_(e,n){e=e|0,n=n|0;var r=0;r=PR()|0,t[e>>2]=r,IR(r,n),Zd(t[e>>2]|0)}function rE(e,n,r){return e=e|0,n=n|0,r=r|0,_R(e,Fr(n)|0,r,0),e|0}function iE(e,n,r){return e=e|0,n=n|0,r=r|0,iR(e,Fr(n)|0,r,0),e|0}function Ry(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0;return u=y,y=y+16|0,s=u+8|0,a=u,v=t[r+4>>2]|0,t[a>>2]=t[r>>2],t[a+4>>2]=v,t[s>>2]=t[a>>2],t[s+4>>2]=t[a+4>>2],U9(e,n,s),y=u,e|0}function l_(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0;return u=y,y=y+16|0,s=u+8|0,a=u,v=t[r+4>>2]|0,t[a>>2]=t[r>>2],t[a+4>>2]=v,t[s>>2]=t[a>>2],t[s+4>>2]=t[a+4>>2],E9(e,n,s),y=u,e|0}function uE(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0;return u=y,y=y+16|0,s=u+8|0,a=u,v=t[r+4>>2]|0,t[a>>2]=t[r>>2],t[a+4>>2]=v,t[s>>2]=t[a>>2],t[s+4>>2]=t[a+4>>2],oE(e,n,s),y=u,e|0}function oE(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0;u=y,y=y+16|0,s=u+8|0,a=u,w=t[r>>2]|0,v=t[r+4>>2]|0,r=Fr(n)|0,t[a>>2]=w,t[a+4>>2]=v,t[s>>2]=t[a>>2],t[s+4>>2]=t[a+4>>2],lE(e,r,s,1),y=u}function lE(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0,a=0,v=0,w=0,T=0,L=0,M=0;s=y,y=y+32|0,a=s+16|0,M=s+8|0,w=s,L=t[r>>2]|0,T=t[r+4>>2]|0,v=t[e>>2]|0,e=sE()|0,t[M>>2]=L,t[M+4>>2]=T,t[a>>2]=t[M>>2],t[a+4>>2]=t[M+4>>2],r=o9(a)|0,t[w>>2]=L,t[w+4>>2]=T,t[a>>2]=t[w>>2],t[a+4>>2]=t[w+4>>2],wi(v,n,e,r,l9(a,u)|0,u),y=s}function sE(){var e=0,n=0;if(h[7840]|0||(hw(10100),Wt(48,10100,ge|0)|0,n=7840,t[n>>2]=1,t[n+4>>2]=0),!(sr(10100)|0)){e=10100,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));hw(10100)}return 10100}function o9(e){return e=e|0,0}function l9(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0,b=0;return M=y,y=y+32|0,s=M+24|0,v=M+16|0,w=M,T=M+8|0,a=t[e>>2]|0,u=t[e+4>>2]|0,t[w>>2]=a,t[w+4>>2]=u,b=sE()|0,L=b+24|0,e=hn(n,4)|0,t[T>>2]=e,n=b+28|0,r=t[n>>2]|0,r>>>0<(t[b+32>>2]|0)>>>0?(t[v>>2]=a,t[v+4>>2]=u,t[s>>2]=t[v>>2],t[s+4>>2]=t[v+4>>2],pw(r,s,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(s9(L,w,T),e=t[n>>2]|0),y=M,((e-(t[L>>2]|0)|0)/12|0)+-1|0}function pw(e,n,r){e=e|0,n=n|0,r=r|0;var u=0;u=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=u,t[e+8>>2]=r}function s9(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0,b=0,X=0;if(L=y,y=y+48|0,u=L+32|0,v=L+24|0,w=L,T=e+4|0,s=(((t[T>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,a=a9(e)|0,a>>>0>>0)di(e);else{M=t[e>>2]|0,X=((t[e+8>>2]|0)-M|0)/12|0,b=X<<1,f9(w,X>>>0>>1>>>0?b>>>0>>0?s:b:a,((t[T>>2]|0)-M|0)/12|0,e+8|0),T=w+8|0,a=t[T>>2]|0,s=t[n+4>>2]|0,r=t[r>>2]|0,t[v>>2]=t[n>>2],t[v+4>>2]=s,t[u>>2]=t[v>>2],t[u+4>>2]=t[v+4>>2],pw(a,u,r),t[T>>2]=(t[T>>2]|0)+12,c9(e,w),d9(w),y=L;return}}function a9(e){return e=e|0,357913941}function f9(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=u;do if(n)if(n>>>0>357913941)$n();else{s=pn(n*12|0)|0;break}else s=0;while(0);t[e>>2]=s,u=s+(r*12|0)|0,t[e+8>>2]=u,t[e+4>>2]=u,t[e+12>>2]=s+(n*12|0)}function c9(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0;u=t[e>>2]|0,v=e+4|0,a=n+4|0,s=(t[v>>2]|0)-u|0,r=(t[a>>2]|0)+(((s|0)/-12|0)*12|0)|0,t[a>>2]=r,(s|0)>0?(gr(r|0,u|0,s|0)|0,u=a,r=t[a>>2]|0):u=a,a=t[e>>2]|0,t[e>>2]=r,t[u>>2]=a,a=n+8|0,s=t[v>>2]|0,t[v>>2]=t[a>>2],t[a>>2]=s,a=e+8|0,v=n+12|0,e=t[a>>2]|0,t[a>>2]=t[v>>2],t[v>>2]=e,t[n>>2]=t[u>>2]}function d9(e){e=e|0;var n=0,r=0,u=0;n=t[e+4>>2]|0,r=e+8|0,u=t[r>>2]|0,(u|0)!=(n|0)&&(t[r>>2]=u+(~(((u+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&Et(e)}function hw(e){e=e|0,v9(e)}function p9(e){e=e|0,h9(e+24|0)}function h9(e){e=e|0;var n=0,r=0,u=0;r=t[e>>2]|0,u=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-u|0)>>>0)/12|0)*12|0)),Et(r))}function v9(e){e=e|0;var n=0;n=yr()|0,jn(e,2,6,n,m9()|0,1),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function m9(){return 1364}function y9(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0;return u=y,y=y+16|0,s=u+8|0,a=u,v=g9(e)|0,e=t[v+4>>2]|0,t[a>>2]=t[v>>2],t[a+4>>2]=e,t[s>>2]=t[a>>2],t[s+4>>2]=t[a+4>>2],r=_9(n,s,r)|0,y=u,r|0}function g9(e){return e=e|0,(t[(sE()|0)+24>>2]|0)+(e*12|0)|0}function _9(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0;return a=y,y=y+16|0,s=a,u=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(u=t[(t[e>>2]|0)+u>>2]|0),xs(s,r),s=Gs(s,r)|0,s=bl(bE[u&15](e,s)|0)|0,y=a,s|0}function E9(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0;u=y,y=y+16|0,s=u+8|0,a=u,w=t[r>>2]|0,v=t[r+4>>2]|0,r=Fr(n)|0,t[a>>2]=w,t[a+4>>2]=v,t[s>>2]=t[a>>2],t[s+4>>2]=t[a+4>>2],D9(e,r,s,0),y=u}function D9(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0,a=0,v=0,w=0,T=0,L=0,M=0;s=y,y=y+32|0,a=s+16|0,M=s+8|0,w=s,L=t[r>>2]|0,T=t[r+4>>2]|0,v=t[e>>2]|0,e=aE()|0,t[M>>2]=L,t[M+4>>2]=T,t[a>>2]=t[M>>2],t[a+4>>2]=t[M+4>>2],r=w9(a)|0,t[w>>2]=L,t[w+4>>2]=T,t[a>>2]=t[w>>2],t[a+4>>2]=t[w+4>>2],wi(v,n,e,r,S9(a,u)|0,u),y=s}function aE(){var e=0,n=0;if(h[7848]|0||(mw(10136),Wt(49,10136,ge|0)|0,n=7848,t[n>>2]=1,t[n+4>>2]=0),!(sr(10136)|0)){e=10136,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));mw(10136)}return 10136}function w9(e){return e=e|0,0}function S9(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0,b=0;return M=y,y=y+32|0,s=M+24|0,v=M+16|0,w=M,T=M+8|0,a=t[e>>2]|0,u=t[e+4>>2]|0,t[w>>2]=a,t[w+4>>2]=u,b=aE()|0,L=b+24|0,e=hn(n,4)|0,t[T>>2]=e,n=b+28|0,r=t[n>>2]|0,r>>>0<(t[b+32>>2]|0)>>>0?(t[v>>2]=a,t[v+4>>2]=u,t[s>>2]=t[v>>2],t[s+4>>2]=t[v+4>>2],vw(r,s,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(T9(L,w,T),e=t[n>>2]|0),y=M,((e-(t[L>>2]|0)|0)/12|0)+-1|0}function vw(e,n,r){e=e|0,n=n|0,r=r|0;var u=0;u=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=u,t[e+8>>2]=r}function T9(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0,b=0,X=0;if(L=y,y=y+48|0,u=L+32|0,v=L+24|0,w=L,T=e+4|0,s=(((t[T>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,a=C9(e)|0,a>>>0>>0)di(e);else{M=t[e>>2]|0,X=((t[e+8>>2]|0)-M|0)/12|0,b=X<<1,x9(w,X>>>0>>1>>>0?b>>>0>>0?s:b:a,((t[T>>2]|0)-M|0)/12|0,e+8|0),T=w+8|0,a=t[T>>2]|0,s=t[n+4>>2]|0,r=t[r>>2]|0,t[v>>2]=t[n>>2],t[v+4>>2]=s,t[u>>2]=t[v>>2],t[u+4>>2]=t[v+4>>2],vw(a,u,r),t[T>>2]=(t[T>>2]|0)+12,R9(e,w),A9(w),y=L;return}}function C9(e){return e=e|0,357913941}function x9(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=u;do if(n)if(n>>>0>357913941)$n();else{s=pn(n*12|0)|0;break}else s=0;while(0);t[e>>2]=s,u=s+(r*12|0)|0,t[e+8>>2]=u,t[e+4>>2]=u,t[e+12>>2]=s+(n*12|0)}function R9(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0;u=t[e>>2]|0,v=e+4|0,a=n+4|0,s=(t[v>>2]|0)-u|0,r=(t[a>>2]|0)+(((s|0)/-12|0)*12|0)|0,t[a>>2]=r,(s|0)>0?(gr(r|0,u|0,s|0)|0,u=a,r=t[a>>2]|0):u=a,a=t[e>>2]|0,t[e>>2]=r,t[u>>2]=a,a=n+8|0,s=t[v>>2]|0,t[v>>2]=t[a>>2],t[a>>2]=s,a=e+8|0,v=n+12|0,e=t[a>>2]|0,t[a>>2]=t[v>>2],t[v>>2]=e,t[n>>2]=t[u>>2]}function A9(e){e=e|0;var n=0,r=0,u=0;n=t[e+4>>2]|0,r=e+8|0,u=t[r>>2]|0,(u|0)!=(n|0)&&(t[r>>2]=u+(~(((u+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&Et(e)}function mw(e){e=e|0,k9(e)}function O9(e){e=e|0,M9(e+24|0)}function M9(e){e=e|0;var n=0,r=0,u=0;r=t[e>>2]|0,u=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-u|0)>>>0)/12|0)*12|0)),Et(r))}function k9(e){e=e|0;var n=0;n=yr()|0,jn(e,2,9,n,N9()|0,1),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function N9(){return 1372}function L9(e,n,r){e=e|0,n=n|0,r=+r;var u=0,s=0,a=0,v=0;u=y,y=y+16|0,s=u+8|0,a=u,v=F9(e)|0,e=t[v+4>>2]|0,t[a>>2]=t[v>>2],t[a+4>>2]=e,t[s>>2]=t[a>>2],t[s+4>>2]=t[a+4>>2],P9(n,s,r),y=u}function F9(e){return e=e|0,(t[(aE()|0)+24>>2]|0)+(e*12|0)|0}function P9(e,n,r){e=e|0,n=n|0,r=+r;var u=0,s=0,a=0,v=Ct;a=y,y=y+16|0,s=a,u=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(u=t[(t[e>>2]|0)+u>>2]|0),I9(s,r),v=S(b9(s,r)),M8[u&1](e,v),y=a}function I9(e,n){e=e|0,n=+n}function b9(e,n){return e=e|0,n=+n,S(B9(n))}function B9(e){return e=+e,S(e)}function U9(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0;u=y,y=y+16|0,s=u+8|0,a=u,w=t[r>>2]|0,v=t[r+4>>2]|0,r=Fr(n)|0,t[a>>2]=w,t[a+4>>2]=v,t[s>>2]=t[a>>2],t[s+4>>2]=t[a+4>>2],j9(e,r,s,0),y=u}function j9(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0,a=0,v=0,w=0,T=0,L=0,M=0;s=y,y=y+32|0,a=s+16|0,M=s+8|0,w=s,L=t[r>>2]|0,T=t[r+4>>2]|0,v=t[e>>2]|0,e=fE()|0,t[M>>2]=L,t[M+4>>2]=T,t[a>>2]=t[M>>2],t[a+4>>2]=t[M+4>>2],r=z9(a)|0,t[w>>2]=L,t[w+4>>2]=T,t[a>>2]=t[w>>2],t[a+4>>2]=t[w+4>>2],wi(v,n,e,r,H9(a,u)|0,u),y=s}function fE(){var e=0,n=0;if(h[7856]|0||(gw(10172),Wt(50,10172,ge|0)|0,n=7856,t[n>>2]=1,t[n+4>>2]=0),!(sr(10172)|0)){e=10172,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));gw(10172)}return 10172}function z9(e){return e=e|0,0}function H9(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0,b=0;return M=y,y=y+32|0,s=M+24|0,v=M+16|0,w=M,T=M+8|0,a=t[e>>2]|0,u=t[e+4>>2]|0,t[w>>2]=a,t[w+4>>2]=u,b=fE()|0,L=b+24|0,e=hn(n,4)|0,t[T>>2]=e,n=b+28|0,r=t[n>>2]|0,r>>>0<(t[b+32>>2]|0)>>>0?(t[v>>2]=a,t[v+4>>2]=u,t[s>>2]=t[v>>2],t[s+4>>2]=t[v+4>>2],yw(r,s,e),e=(t[n>>2]|0)+12|0,t[n>>2]=e):(q9(L,w,T),e=t[n>>2]|0),y=M,((e-(t[L>>2]|0)|0)/12|0)+-1|0}function yw(e,n,r){e=e|0,n=n|0,r=r|0;var u=0;u=t[n+4>>2]|0,t[e>>2]=t[n>>2],t[e+4>>2]=u,t[e+8>>2]=r}function q9(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0,b=0,X=0;if(L=y,y=y+48|0,u=L+32|0,v=L+24|0,w=L,T=e+4|0,s=(((t[T>>2]|0)-(t[e>>2]|0)|0)/12|0)+1|0,a=W9(e)|0,a>>>0>>0)di(e);else{M=t[e>>2]|0,X=((t[e+8>>2]|0)-M|0)/12|0,b=X<<1,V9(w,X>>>0>>1>>>0?b>>>0>>0?s:b:a,((t[T>>2]|0)-M|0)/12|0,e+8|0),T=w+8|0,a=t[T>>2]|0,s=t[n+4>>2]|0,r=t[r>>2]|0,t[v>>2]=t[n>>2],t[v+4>>2]=s,t[u>>2]=t[v>>2],t[u+4>>2]=t[v+4>>2],yw(a,u,r),t[T>>2]=(t[T>>2]|0)+12,G9(e,w),Y9(w),y=L;return}}function W9(e){return e=e|0,357913941}function V9(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=u;do if(n)if(n>>>0>357913941)$n();else{s=pn(n*12|0)|0;break}else s=0;while(0);t[e>>2]=s,u=s+(r*12|0)|0,t[e+8>>2]=u,t[e+4>>2]=u,t[e+12>>2]=s+(n*12|0)}function G9(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0;u=t[e>>2]|0,v=e+4|0,a=n+4|0,s=(t[v>>2]|0)-u|0,r=(t[a>>2]|0)+(((s|0)/-12|0)*12|0)|0,t[a>>2]=r,(s|0)>0?(gr(r|0,u|0,s|0)|0,u=a,r=t[a>>2]|0):u=a,a=t[e>>2]|0,t[e>>2]=r,t[u>>2]=a,a=n+8|0,s=t[v>>2]|0,t[v>>2]=t[a>>2],t[a>>2]=s,a=e+8|0,v=n+12|0,e=t[a>>2]|0,t[a>>2]=t[v>>2],t[v>>2]=e,t[n>>2]=t[u>>2]}function Y9(e){e=e|0;var n=0,r=0,u=0;n=t[e+4>>2]|0,r=e+8|0,u=t[r>>2]|0,(u|0)!=(n|0)&&(t[r>>2]=u+(~(((u+-12-n|0)>>>0)/12|0)*12|0)),e=t[e>>2]|0,e|0&&Et(e)}function gw(e){e=e|0,Q9(e)}function K9(e){e=e|0,X9(e+24|0)}function X9(e){e=e|0;var n=0,r=0,u=0;r=t[e>>2]|0,u=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~(((n+-12-u|0)>>>0)/12|0)*12|0)),Et(r))}function Q9(e){e=e|0;var n=0;n=yr()|0,jn(e,2,3,n,J9()|0,2),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function J9(){return 1380}function Z9(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0,a=0,v=0,w=0;s=y,y=y+16|0,a=s+8|0,v=s,w=$9(e)|0,e=t[w+4>>2]|0,t[v>>2]=t[w>>2],t[v+4>>2]=e,t[a>>2]=t[v>>2],t[a+4>>2]=t[v+4>>2],eR(n,a,r,u),y=s}function $9(e){return e=e|0,(t[(fE()|0)+24>>2]|0)+(e*12|0)|0}function eR(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0,a=0,v=0,w=0;w=y,y=y+16|0,a=w+1|0,v=w,s=t[n>>2]|0,n=t[n+4>>2]|0,e=e+(n>>1)|0,n&1&&(s=t[(t[e>>2]|0)+s>>2]|0),xs(a,r),a=Gs(a,r)|0,tR(v,u),v=nR(v,u)|0,Fy[s&15](e,a,v),y=w}function tR(e,n){e=e|0,n=n|0}function nR(e,n){return e=e|0,n=n|0,rR(n)|0}function rR(e){return e=e|0,(e|0)!=0|0}function iR(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0,a=0;a=t[e>>2]|0,s=cE()|0,e=uR(r)|0,wi(a,n,s,e,oR(r,u)|0,u)}function cE(){var e=0,n=0;if(h[7864]|0||(Ew(10208),Wt(51,10208,ge|0)|0,n=7864,t[n>>2]=1,t[n+4>>2]=0),!(sr(10208)|0)){e=10208,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));Ew(10208)}return 10208}function uR(e){return e=e|0,e|0}function oR(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0,w=0,T=0;return w=y,y=y+16|0,s=w,a=w+4|0,t[s>>2]=e,T=cE()|0,v=T+24|0,n=hn(n,4)|0,t[a>>2]=n,r=T+28|0,u=t[r>>2]|0,u>>>0<(t[T+32>>2]|0)>>>0?(_w(u,e,n),n=(t[r>>2]|0)+8|0,t[r>>2]=n):(lR(v,s,a),n=t[r>>2]|0),y=w,(n-(t[v>>2]|0)>>3)+-1|0}function _w(e,n,r){e=e|0,n=n|0,r=r|0,t[e>>2]=n,t[e+4>>2]=r}function lR(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0;if(w=y,y=y+32|0,s=w,a=e+4|0,v=((t[a>>2]|0)-(t[e>>2]|0)>>3)+1|0,u=sR(e)|0,u>>>0>>0)di(e);else{T=t[e>>2]|0,M=(t[e+8>>2]|0)-T|0,L=M>>2,aR(s,M>>3>>>0>>1>>>0?L>>>0>>0?v:L:u,(t[a>>2]|0)-T>>3,e+8|0),v=s+8|0,_w(t[v>>2]|0,t[n>>2]|0,t[r>>2]|0),t[v>>2]=(t[v>>2]|0)+8,fR(e,s),cR(s),y=w;return}}function sR(e){return e=e|0,536870911}function aR(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=u;do if(n)if(n>>>0>536870911)$n();else{s=pn(n<<3)|0;break}else s=0;while(0);t[e>>2]=s,u=s+(r<<3)|0,t[e+8>>2]=u,t[e+4>>2]=u,t[e+12>>2]=s+(n<<3)}function fR(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0;u=t[e>>2]|0,v=e+4|0,a=n+4|0,s=(t[v>>2]|0)-u|0,r=(t[a>>2]|0)+(0-(s>>3)<<3)|0,t[a>>2]=r,(s|0)>0?(gr(r|0,u|0,s|0)|0,u=a,r=t[a>>2]|0):u=a,a=t[e>>2]|0,t[e>>2]=r,t[u>>2]=a,a=n+8|0,s=t[v>>2]|0,t[v>>2]=t[a>>2],t[a>>2]=s,a=e+8|0,v=n+12|0,e=t[a>>2]|0,t[a>>2]=t[v>>2],t[v>>2]=e,t[n>>2]=t[u>>2]}function cR(e){e=e|0;var n=0,r=0,u=0;n=t[e+4>>2]|0,r=e+8|0,u=t[r>>2]|0,(u|0)!=(n|0)&&(t[r>>2]=u+(~((u+-8-n|0)>>>3)<<3)),e=t[e>>2]|0,e|0&&Et(e)}function Ew(e){e=e|0,hR(e)}function dR(e){e=e|0,pR(e+24|0)}function pR(e){e=e|0;var n=0,r=0,u=0;r=t[e>>2]|0,u=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-8-u|0)>>>3)<<3)),Et(r))}function hR(e){e=e|0;var n=0;n=yr()|0,jn(e,1,24,n,vR()|0,1),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function vR(){return 1392}function mR(e,n){e=e|0,n=n|0,gR(t[(yR(e)|0)>>2]|0,n)}function yR(e){return e=e|0,(t[(cE()|0)+24>>2]|0)+(e<<3)|0}function gR(e,n){e=e|0,n=n|0;var r=0,u=0;r=y,y=y+16|0,u=r,L0(u,n),n=$i(u,n)|0,P1[e&127](n),y=r}function _R(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0,a=0;a=t[e>>2]|0,s=dE()|0,e=ER(r)|0,wi(a,n,s,e,DR(r,u)|0,u)}function dE(){var e=0,n=0;if(h[7872]|0||(ww(10244),Wt(52,10244,ge|0)|0,n=7872,t[n>>2]=1,t[n+4>>2]=0),!(sr(10244)|0)){e=10244,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));ww(10244)}return 10244}function ER(e){return e=e|0,e|0}function DR(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0,w=0,T=0;return w=y,y=y+16|0,s=w,a=w+4|0,t[s>>2]=e,T=dE()|0,v=T+24|0,n=hn(n,4)|0,t[a>>2]=n,r=T+28|0,u=t[r>>2]|0,u>>>0<(t[T+32>>2]|0)>>>0?(Dw(u,e,n),n=(t[r>>2]|0)+8|0,t[r>>2]=n):(wR(v,s,a),n=t[r>>2]|0),y=w,(n-(t[v>>2]|0)>>3)+-1|0}function Dw(e,n,r){e=e|0,n=n|0,r=r|0,t[e>>2]=n,t[e+4>>2]=r}function wR(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0;if(w=y,y=y+32|0,s=w,a=e+4|0,v=((t[a>>2]|0)-(t[e>>2]|0)>>3)+1|0,u=SR(e)|0,u>>>0>>0)di(e);else{T=t[e>>2]|0,M=(t[e+8>>2]|0)-T|0,L=M>>2,TR(s,M>>3>>>0>>1>>>0?L>>>0>>0?v:L:u,(t[a>>2]|0)-T>>3,e+8|0),v=s+8|0,Dw(t[v>>2]|0,t[n>>2]|0,t[r>>2]|0),t[v>>2]=(t[v>>2]|0)+8,CR(e,s),xR(s),y=w;return}}function SR(e){return e=e|0,536870911}function TR(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=u;do if(n)if(n>>>0>536870911)$n();else{s=pn(n<<3)|0;break}else s=0;while(0);t[e>>2]=s,u=s+(r<<3)|0,t[e+8>>2]=u,t[e+4>>2]=u,t[e+12>>2]=s+(n<<3)}function CR(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0;u=t[e>>2]|0,v=e+4|0,a=n+4|0,s=(t[v>>2]|0)-u|0,r=(t[a>>2]|0)+(0-(s>>3)<<3)|0,t[a>>2]=r,(s|0)>0?(gr(r|0,u|0,s|0)|0,u=a,r=t[a>>2]|0):u=a,a=t[e>>2]|0,t[e>>2]=r,t[u>>2]=a,a=n+8|0,s=t[v>>2]|0,t[v>>2]=t[a>>2],t[a>>2]=s,a=e+8|0,v=n+12|0,e=t[a>>2]|0,t[a>>2]=t[v>>2],t[v>>2]=e,t[n>>2]=t[u>>2]}function xR(e){e=e|0;var n=0,r=0,u=0;n=t[e+4>>2]|0,r=e+8|0,u=t[r>>2]|0,(u|0)!=(n|0)&&(t[r>>2]=u+(~((u+-8-n|0)>>>3)<<3)),e=t[e>>2]|0,e|0&&Et(e)}function ww(e){e=e|0,OR(e)}function RR(e){e=e|0,AR(e+24|0)}function AR(e){e=e|0;var n=0,r=0,u=0;r=t[e>>2]|0,u=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-8-u|0)>>>3)<<3)),Et(r))}function OR(e){e=e|0;var n=0;n=yr()|0,jn(e,1,16,n,MR()|0,0),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function MR(){return 1400}function kR(e){return e=e|0,LR(t[(NR(e)|0)>>2]|0)|0}function NR(e){return e=e|0,(t[(dE()|0)+24>>2]|0)+(e<<3)|0}function LR(e){return e=e|0,FR(E_[e&7]()|0)|0}function FR(e){return e=e|0,e|0}function PR(){var e=0;return h[7880]|0||(HR(10280),Wt(25,10280,ge|0)|0,e=7880,t[e>>2]=1,t[e+4>>2]=0),10280}function IR(e,n){e=e|0,n=n|0,t[e>>2]=bR()|0,t[e+4>>2]=BR()|0,t[e+12>>2]=n,t[e+8>>2]=UR()|0,t[e+32>>2]=4}function bR(){return 11711}function BR(){return 1356}function UR(){return L1()|0}function jR(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0,(Hl(u,896)|0)==512?r|0&&(zR(r),Et(r)):n|0&&(ro(n),Et(n))}function zR(e){e=e|0,e=t[e+4>>2]|0,e|0&&$d(e)}function HR(e){e=e|0,Xa(e)}function qR(e){e=e|0,WR(e,4920),VR(e)|0,GR(e)|0}function WR(e,n){e=e|0,n=n|0;var r=0;r=Hd()|0,t[e>>2]=r,pA(r,n),Zd(t[e>>2]|0)}function VR(e){e=e|0;var n=0;return n=t[e>>2]|0,Wp(n,rA()|0),e|0}function GR(e){e=e|0;var n=0;return n=t[e>>2]|0,Wp(n,YR()|0),e|0}function YR(){var e=0;return h[7888]|0||(Sw(10328),Wt(53,10328,ge|0)|0,e=7888,t[e>>2]=1,t[e+4>>2]=0),sr(10328)|0||Sw(10328),10328}function Wp(e,n){e=e|0,n=n|0,wi(e,0,n,0,0,0)}function Sw(e){e=e|0,QR(e),Vp(e,10)}function KR(e){e=e|0,XR(e+24|0)}function XR(e){e=e|0;var n=0,r=0,u=0;r=t[e>>2]|0,u=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-8-u|0)>>>3)<<3)),Et(r))}function QR(e){e=e|0;var n=0;n=yr()|0,jn(e,5,1,n,eA()|0,2),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function JR(e,n,r){e=e|0,n=n|0,r=+r,ZR(e,n,r)}function Vp(e,n){e=e|0,n=n|0,t[e+20>>2]=n}function ZR(e,n,r){e=e|0,n=n|0,r=+r;var u=0,s=0,a=0,v=0,w=0;u=y,y=y+16|0,a=u+8|0,w=u+13|0,s=u,v=u+12|0,xs(w,n),t[a>>2]=Gs(w,n)|0,Pl(v,r),j[s>>3]=+us(v,r),$R(e,a,s),y=u}function $R(e,n,r){e=e|0,n=n|0,r=r|0,B(e+8|0,t[n>>2]|0,+j[r>>3]),h[e+24>>0]=1}function eA(){return 1404}function tA(e,n){return e=e|0,n=+n,nA(e,n)|0}function nA(e,n){e=e|0,n=+n;var r=0,u=0,s=0,a=0,v=0,w=0,T=0;return u=y,y=y+16|0,a=u+4|0,v=u+8|0,w=u,s=Oa(8)|0,r=s,T=pn(16)|0,xs(a,e),e=Gs(a,e)|0,Pl(v,n),B(T,e,+us(v,n)),v=r+4|0,t[v>>2]=T,e=pn(8)|0,v=t[v>>2]|0,t[w>>2]=0,t[a>>2]=t[w>>2],Bf(e,v,a),t[s>>2]=e,y=u,r|0}function rA(){var e=0;return h[7896]|0||(Tw(10364),Wt(54,10364,ge|0)|0,e=7896,t[e>>2]=1,t[e+4>>2]=0),sr(10364)|0||Tw(10364),10364}function Tw(e){e=e|0,oA(e),Vp(e,55)}function iA(e){e=e|0,uA(e+24|0)}function uA(e){e=e|0;var n=0,r=0,u=0;r=t[e>>2]|0,u=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-8-u|0)>>>3)<<3)),Et(r))}function oA(e){e=e|0;var n=0;n=yr()|0,jn(e,5,4,n,fA()|0,0),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function lA(e){e=e|0,sA(e)}function sA(e){e=e|0,aA(e)}function aA(e){e=e|0,Cw(e+8|0),h[e+24>>0]=1}function Cw(e){e=e|0,t[e>>2]=0,j[e+8>>3]=0}function fA(){return 1424}function cA(){return dA()|0}function dA(){var e=0,n=0,r=0,u=0,s=0,a=0,v=0;return n=y,y=y+16|0,s=n+4|0,v=n,r=Oa(8)|0,e=r,u=pn(16)|0,Cw(u),a=e+4|0,t[a>>2]=u,u=pn(8)|0,a=t[a>>2]|0,t[v>>2]=0,t[s>>2]=t[v>>2],Bf(u,a,s),t[r>>2]=u,y=n,e|0}function pA(e,n){e=e|0,n=n|0,t[e>>2]=hA()|0,t[e+4>>2]=vA()|0,t[e+12>>2]=n,t[e+8>>2]=mA()|0,t[e+32>>2]=5}function hA(){return 11710}function vA(){return 1416}function mA(){return s_()|0}function yA(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0,(Hl(u,896)|0)==512?r|0&&(gA(r),Et(r)):n|0&&Et(n)}function gA(e){e=e|0,e=t[e+4>>2]|0,e|0&&$d(e)}function s_(){var e=0;return h[7904]|0||(t[2600]=_A()|0,t[2601]=0,e=7904,t[e>>2]=1,t[e+4>>2]=0),10400}function _A(){return t[357]|0}function EA(e){e=e|0,DA(e,4926),wA(e)|0}function DA(e,n){e=e|0,n=n|0;var r=0;r=Ka()|0,t[e>>2]=r,LA(r,n),Zd(t[e>>2]|0)}function wA(e){e=e|0;var n=0;return n=t[e>>2]|0,Wp(n,SA()|0),e|0}function SA(){var e=0;return h[7912]|0||(xw(10412),Wt(56,10412,ge|0)|0,e=7912,t[e>>2]=1,t[e+4>>2]=0),sr(10412)|0||xw(10412),10412}function xw(e){e=e|0,xA(e),Vp(e,57)}function TA(e){e=e|0,CA(e+24|0)}function CA(e){e=e|0;var n=0,r=0,u=0;r=t[e>>2]|0,u=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-8-u|0)>>>3)<<3)),Et(r))}function xA(e){e=e|0;var n=0;n=yr()|0,jn(e,5,5,n,MA()|0,0),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function RA(e){e=e|0,AA(e)}function AA(e){e=e|0,OA(e)}function OA(e){e=e|0;var n=0,r=0;n=e+8|0,r=n+48|0;do t[n>>2]=0,n=n+4|0;while((n|0)<(r|0));h[e+56>>0]=1}function MA(){return 1432}function kA(){return NA()|0}function NA(){var e=0,n=0,r=0,u=0,s=0,a=0,v=0,w=0;v=y,y=y+16|0,e=v+4|0,n=v,r=Oa(8)|0,u=r,s=pn(48)|0,a=s,w=a+48|0;do t[a>>2]=0,a=a+4|0;while((a|0)<(w|0));return a=u+4|0,t[a>>2]=s,w=pn(8)|0,a=t[a>>2]|0,t[n>>2]=0,t[e>>2]=t[n>>2],Th(w,a,e),t[r>>2]=w,y=v,u|0}function LA(e,n){e=e|0,n=n|0,t[e>>2]=FA()|0,t[e+4>>2]=PA()|0,t[e+12>>2]=n,t[e+8>>2]=IA()|0,t[e+32>>2]=6}function FA(){return 11704}function PA(){return 1436}function IA(){return s_()|0}function bA(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0,(Hl(u,896)|0)==512?r|0&&(BA(r),Et(r)):n|0&&Et(n)}function BA(e){e=e|0,e=t[e+4>>2]|0,e|0&&$d(e)}function UA(e){e=e|0,jA(e,4933),zA(e)|0,HA(e)|0}function jA(e,n){e=e|0,n=n|0;var r=0;r=d7()|0,t[e>>2]=r,p7(r,n),Zd(t[e>>2]|0)}function zA(e){e=e|0;var n=0;return n=t[e>>2]|0,Wp(n,n7()|0),e|0}function HA(e){e=e|0;var n=0;return n=t[e>>2]|0,Wp(n,qA()|0),e|0}function qA(){var e=0;return h[7920]|0||(Rw(10452),Wt(58,10452,ge|0)|0,e=7920,t[e>>2]=1,t[e+4>>2]=0),sr(10452)|0||Rw(10452),10452}function Rw(e){e=e|0,GA(e),Vp(e,1)}function WA(e){e=e|0,VA(e+24|0)}function VA(e){e=e|0;var n=0,r=0,u=0;r=t[e>>2]|0,u=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-8-u|0)>>>3)<<3)),Et(r))}function GA(e){e=e|0;var n=0;n=yr()|0,jn(e,5,1,n,QA()|0,2),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function YA(e,n,r){e=e|0,n=+n,r=+r,KA(e,n,r)}function KA(e,n,r){e=e|0,n=+n,r=+r;var u=0,s=0,a=0,v=0,w=0;u=y,y=y+32|0,a=u+8|0,w=u+17|0,s=u,v=u+16|0,Pl(w,n),j[a>>3]=+us(w,n),Pl(v,r),j[s>>3]=+us(v,r),XA(e,a,s),y=u}function XA(e,n,r){e=e|0,n=n|0,r=r|0,Aw(e+8|0,+j[n>>3],+j[r>>3]),h[e+24>>0]=1}function Aw(e,n,r){e=e|0,n=+n,r=+r,j[e>>3]=n,j[e+8>>3]=r}function QA(){return 1472}function JA(e,n){return e=+e,n=+n,ZA(e,n)|0}function ZA(e,n){e=+e,n=+n;var r=0,u=0,s=0,a=0,v=0,w=0,T=0;return u=y,y=y+16|0,v=u+4|0,w=u+8|0,T=u,s=Oa(8)|0,r=s,a=pn(16)|0,Pl(v,e),e=+us(v,e),Pl(w,n),Aw(a,e,+us(w,n)),w=r+4|0,t[w>>2]=a,a=pn(8)|0,w=t[w>>2]|0,t[T>>2]=0,t[v>>2]=t[T>>2],Ow(a,w,v),t[s>>2]=a,y=u,r|0}function Ow(e,n,r){e=e|0,n=n|0,r=r|0,t[e>>2]=n,r=pn(16)|0,t[r+4>>2]=0,t[r+8>>2]=0,t[r>>2]=1452,t[r+12>>2]=n,t[e+4>>2]=r}function $A(e){e=e|0,Uv(e),Et(e)}function e7(e){e=e|0,e=t[e+12>>2]|0,e|0&&Et(e)}function t7(e){e=e|0,Et(e)}function n7(){var e=0;return h[7928]|0||(Mw(10488),Wt(59,10488,ge|0)|0,e=7928,t[e>>2]=1,t[e+4>>2]=0),sr(10488)|0||Mw(10488),10488}function Mw(e){e=e|0,u7(e),Vp(e,60)}function r7(e){e=e|0,i7(e+24|0)}function i7(e){e=e|0;var n=0,r=0,u=0;r=t[e>>2]|0,u=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-8-u|0)>>>3)<<3)),Et(r))}function u7(e){e=e|0;var n=0;n=yr()|0,jn(e,5,6,n,a7()|0,0),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function o7(e){e=e|0,l7(e)}function l7(e){e=e|0,s7(e)}function s7(e){e=e|0,kw(e+8|0),h[e+24>>0]=1}function kw(e){e=e|0,t[e>>2]=0,t[e+4>>2]=0,t[e+8>>2]=0,t[e+12>>2]=0}function a7(){return 1492}function f7(){return c7()|0}function c7(){var e=0,n=0,r=0,u=0,s=0,a=0,v=0;return n=y,y=y+16|0,s=n+4|0,v=n,r=Oa(8)|0,e=r,u=pn(16)|0,kw(u),a=e+4|0,t[a>>2]=u,u=pn(8)|0,a=t[a>>2]|0,t[v>>2]=0,t[s>>2]=t[v>>2],Ow(u,a,s),t[r>>2]=u,y=n,e|0}function d7(){var e=0;return h[7936]|0||(_7(10524),Wt(25,10524,ge|0)|0,e=7936,t[e>>2]=1,t[e+4>>2]=0),10524}function p7(e,n){e=e|0,n=n|0,t[e>>2]=h7()|0,t[e+4>>2]=v7()|0,t[e+12>>2]=n,t[e+8>>2]=m7()|0,t[e+32>>2]=7}function h7(){return 11700}function v7(){return 1484}function m7(){return s_()|0}function y7(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0,(Hl(u,896)|0)==512?r|0&&(g7(r),Et(r)):n|0&&Et(n)}function g7(e){e=e|0,e=t[e+4>>2]|0,e|0&&$d(e)}function _7(e){e=e|0,Xa(e)}function E7(e,n,r){e=e|0,n=n|0,r=r|0,e=Fr(n)|0,n=D7(r)|0,r=w7(r,0)|0,Z7(e,n,r,pE()|0,0)}function D7(e){return e=e|0,e|0}function w7(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0,w=0,T=0;return w=y,y=y+16|0,s=w,a=w+4|0,t[s>>2]=e,T=pE()|0,v=T+24|0,n=hn(n,4)|0,t[a>>2]=n,r=T+28|0,u=t[r>>2]|0,u>>>0<(t[T+32>>2]|0)>>>0?(Lw(u,e,n),n=(t[r>>2]|0)+8|0,t[r>>2]=n):(O7(v,s,a),n=t[r>>2]|0),y=w,(n-(t[v>>2]|0)>>3)+-1|0}function pE(){var e=0,n=0;if(h[7944]|0||(Nw(10568),Wt(61,10568,ge|0)|0,n=7944,t[n>>2]=1,t[n+4>>2]=0),!(sr(10568)|0)){e=10568,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));Nw(10568)}return 10568}function Nw(e){e=e|0,C7(e)}function S7(e){e=e|0,T7(e+24|0)}function T7(e){e=e|0;var n=0,r=0,u=0;r=t[e>>2]|0,u=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-8-u|0)>>>3)<<3)),Et(r))}function C7(e){e=e|0;var n=0;n=yr()|0,jn(e,1,17,n,ev()|0,0),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function x7(e){return e=e|0,A7(t[(R7(e)|0)>>2]|0)|0}function R7(e){return e=e|0,(t[(pE()|0)+24>>2]|0)+(e<<3)|0}function A7(e){return e=e|0,H0(E_[e&7]()|0)|0}function Lw(e,n,r){e=e|0,n=n|0,r=r|0,t[e>>2]=n,t[e+4>>2]=r}function O7(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0;if(w=y,y=y+32|0,s=w,a=e+4|0,v=((t[a>>2]|0)-(t[e>>2]|0)>>3)+1|0,u=M7(e)|0,u>>>0>>0)di(e);else{T=t[e>>2]|0,M=(t[e+8>>2]|0)-T|0,L=M>>2,k7(s,M>>3>>>0>>1>>>0?L>>>0>>0?v:L:u,(t[a>>2]|0)-T>>3,e+8|0),v=s+8|0,Lw(t[v>>2]|0,t[n>>2]|0,t[r>>2]|0),t[v>>2]=(t[v>>2]|0)+8,N7(e,s),L7(s),y=w;return}}function M7(e){return e=e|0,536870911}function k7(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=u;do if(n)if(n>>>0>536870911)$n();else{s=pn(n<<3)|0;break}else s=0;while(0);t[e>>2]=s,u=s+(r<<3)|0,t[e+8>>2]=u,t[e+4>>2]=u,t[e+12>>2]=s+(n<<3)}function N7(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0;u=t[e>>2]|0,v=e+4|0,a=n+4|0,s=(t[v>>2]|0)-u|0,r=(t[a>>2]|0)+(0-(s>>3)<<3)|0,t[a>>2]=r,(s|0)>0?(gr(r|0,u|0,s|0)|0,u=a,r=t[a>>2]|0):u=a,a=t[e>>2]|0,t[e>>2]=r,t[u>>2]=a,a=n+8|0,s=t[v>>2]|0,t[v>>2]=t[a>>2],t[a>>2]=s,a=e+8|0,v=n+12|0,e=t[a>>2]|0,t[a>>2]=t[v>>2],t[v>>2]=e,t[n>>2]=t[u>>2]}function L7(e){e=e|0;var n=0,r=0,u=0;n=t[e+4>>2]|0,r=e+8|0,u=t[r>>2]|0,(u|0)!=(n|0)&&(t[r>>2]=u+(~((u+-8-n|0)>>>3)<<3)),e=t[e>>2]|0,e|0&&Et(e)}function F7(){P7()}function P7(){I7(10604)}function I7(e){e=e|0,b7(e,4955)}function b7(e,n){e=e|0,n=n|0;var r=0;r=B7()|0,t[e>>2]=r,U7(r,n),Zd(t[e>>2]|0)}function B7(){var e=0;return h[7952]|0||(K7(10612),Wt(25,10612,ge|0)|0,e=7952,t[e>>2]=1,t[e+4>>2]=0),10612}function U7(e,n){e=e|0,n=n|0,t[e>>2]=q7()|0,t[e+4>>2]=W7()|0,t[e+12>>2]=n,t[e+8>>2]=V7()|0,t[e+32>>2]=8}function Zd(e){e=e|0;var n=0,r=0;n=y,y=y+16|0,r=n,Fv()|0,t[r>>2]=e,j7(10608,r),y=n}function Fv(){return h[11714]|0||(t[2652]=0,Wt(62,10608,ge|0)|0,h[11714]=1),10608}function j7(e,n){e=e|0,n=n|0;var r=0;r=pn(8)|0,t[r+4>>2]=t[n>>2],t[r>>2]=t[e>>2],t[e>>2]=r}function z7(e){e=e|0,H7(e)}function H7(e){e=e|0;var n=0,r=0;if(n=t[e>>2]|0,n|0)do r=n,n=t[n>>2]|0,Et(r);while((n|0)!=0);t[e>>2]=0}function q7(){return 11715}function W7(){return 1496}function V7(){return L1()|0}function G7(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0,(Hl(u,896)|0)==512?r|0&&(Y7(r),Et(r)):n|0&&Et(n)}function Y7(e){e=e|0,e=t[e+4>>2]|0,e|0&&$d(e)}function K7(e){e=e|0,Xa(e)}function X7(e,n){e=e|0,n=n|0;var r=0,u=0;Fv()|0,r=t[2652]|0;e:do if(r|0){for(;u=t[r+4>>2]|0,!(u|0&&(h8(hE(u)|0,e)|0)==0);)if(r=t[r>>2]|0,!r)break e;Q7(u,n)}while(0)}function hE(e){return e=e|0,t[e+12>>2]|0}function Q7(e,n){e=e|0,n=n|0;var r=0;e=e+36|0,r=t[e>>2]|0,r|0&&(fa(r),Et(r)),r=pn(4)|0,wf(r,n),t[e>>2]=r}function vE(){return h[11716]|0||(t[2664]=0,Wt(63,10656,ge|0)|0,h[11716]=1),10656}function Fw(){var e=0;return h[11717]|0?e=t[2665]|0:(J7(),t[2665]=1504,h[11717]=1,e=1504),e|0}function J7(){h[11740]|0||(h[11718]=hn(hn(8,0)|0,0)|0,h[11719]=hn(hn(0,0)|0,0)|0,h[11720]=hn(hn(0,16)|0,0)|0,h[11721]=hn(hn(8,0)|0,0)|0,h[11722]=hn(hn(0,0)|0,0)|0,h[11723]=hn(hn(8,0)|0,0)|0,h[11724]=hn(hn(0,0)|0,0)|0,h[11725]=hn(hn(8,0)|0,0)|0,h[11726]=hn(hn(0,0)|0,0)|0,h[11727]=hn(hn(8,0)|0,0)|0,h[11728]=hn(hn(0,0)|0,0)|0,h[11729]=hn(hn(0,0)|0,32)|0,h[11730]=hn(hn(0,0)|0,32)|0,h[11740]=1)}function Pw(){return 1572}function Z7(e,n,r,u,s){e=e|0,n=n|0,r=r|0,u=u|0,s=s|0;var a=0,v=0,w=0,T=0,L=0,M=0;a=y,y=y+32|0,M=a+16|0,L=a+12|0,T=a+8|0,w=a+4|0,v=a,t[M>>2]=e,t[L>>2]=n,t[T>>2]=r,t[w>>2]=u,t[v>>2]=s,vE()|0,$7(10656,M,L,T,w,v),y=a}function $7(e,n,r,u,s,a){e=e|0,n=n|0,r=r|0,u=u|0,s=s|0,a=a|0;var v=0;v=pn(24)|0,yd(v+4|0,t[n>>2]|0,t[r>>2]|0,t[u>>2]|0,t[s>>2]|0,t[a>>2]|0),t[v>>2]=t[e>>2],t[e>>2]=v}function Iw(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0,b=0,X=0,Be=0,Te=0,ye=0,Ze=0,Ye=0,ct=0;if(ct=y,y=y+32|0,Te=ct+20|0,ye=ct+8|0,Ze=ct+4|0,Ye=ct,n=t[n>>2]|0,n|0){Be=Te+4|0,T=Te+8|0,L=ye+4|0,M=ye+8|0,b=ye+8|0,X=Te+8|0;do{if(v=n+4|0,w=mE(v)|0,w|0){if(s=Ay(w)|0,t[Te>>2]=0,t[Be>>2]=0,t[T>>2]=0,u=(Oy(w)|0)+1|0,eO(Te,u),u|0)for(;u=u+-1|0,Gf(ye,t[s>>2]|0),a=t[Be>>2]|0,a>>>0<(t[X>>2]|0)>>>0?(t[a>>2]=t[ye>>2],t[Be>>2]=(t[Be>>2]|0)+4):yE(Te,ye),u;)s=s+4|0;u=My(w)|0,t[ye>>2]=0,t[L>>2]=0,t[M>>2]=0;e:do if(t[u>>2]|0)for(s=0,a=0;;){if((s|0)==(a|0)?tO(ye,u):(t[s>>2]=t[u>>2],t[L>>2]=(t[L>>2]|0)+4),u=u+4|0,!(t[u>>2]|0))break e;s=t[L>>2]|0,a=t[b>>2]|0}while(0);t[Ze>>2]=a_(v)|0,t[Ye>>2]=sr(w)|0,nO(r,e,Ze,Ye,Te,ye),gE(ye),F1(Te)}n=t[n>>2]|0}while((n|0)!=0)}y=ct}function mE(e){return e=e|0,t[e+12>>2]|0}function Ay(e){return e=e|0,t[e+12>>2]|0}function Oy(e){return e=e|0,t[e+16>>2]|0}function eO(e,n){e=e|0,n=n|0;var r=0,u=0,s=0;s=y,y=y+32|0,r=s,u=t[e>>2]|0,(t[e+8>>2]|0)-u>>2>>>0>>0&&(Ww(r,n,(t[e+4>>2]|0)-u>>2,e+8|0),Vw(e,r),Gw(r)),y=s}function yE(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0,w=0,T=0,L=0;if(v=y,y=y+32|0,r=v,u=e+4|0,s=((t[u>>2]|0)-(t[e>>2]|0)>>2)+1|0,a=qw(e)|0,a>>>0>>0)di(e);else{w=t[e>>2]|0,L=(t[e+8>>2]|0)-w|0,T=L>>1,Ww(r,L>>2>>>0>>1>>>0?T>>>0>>0?s:T:a,(t[u>>2]|0)-w>>2,e+8|0),a=r+8|0,t[t[a>>2]>>2]=t[n>>2],t[a>>2]=(t[a>>2]|0)+4,Vw(e,r),Gw(r),y=v;return}}function My(e){return e=e|0,t[e+8>>2]|0}function tO(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0,w=0,T=0,L=0;if(v=y,y=y+32|0,r=v,u=e+4|0,s=((t[u>>2]|0)-(t[e>>2]|0)>>2)+1|0,a=Hw(e)|0,a>>>0>>0)di(e);else{w=t[e>>2]|0,L=(t[e+8>>2]|0)-w|0,T=L>>1,DO(r,L>>2>>>0>>1>>>0?T>>>0>>0?s:T:a,(t[u>>2]|0)-w>>2,e+8|0),a=r+8|0,t[t[a>>2]>>2]=t[n>>2],t[a>>2]=(t[a>>2]|0)+4,wO(e,r),SO(r),y=v;return}}function a_(e){return e=e|0,t[e>>2]|0}function nO(e,n,r,u,s,a){e=e|0,n=n|0,r=r|0,u=u|0,s=s|0,a=a|0,rO(e,n,r,u,s,a)}function gE(e){e=e|0;var n=0,r=0,u=0;r=t[e>>2]|0,u=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-4-u|0)>>>2)<<2)),Et(r))}function F1(e){e=e|0;var n=0,r=0,u=0;r=t[e>>2]|0,u=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-4-u|0)>>>2)<<2)),Et(r))}function rO(e,n,r,u,s,a){e=e|0,n=n|0,r=r|0,u=u|0,s=s|0,a=a|0;var v=0,w=0,T=0,L=0,M=0,b=0;v=y,y=y+48|0,M=v+40|0,w=v+32|0,b=v+24|0,T=v+12|0,L=v,Ma(w),e=go(e)|0,t[b>>2]=t[n>>2],r=t[r>>2]|0,u=t[u>>2]|0,_E(T,s),iO(L,a),t[M>>2]=t[b>>2],uO(e,M,r,u,T,L),gE(L),F1(T),ka(w),y=v}function _E(e,n){e=e|0,n=n|0;var r=0,u=0;t[e>>2]=0,t[e+4>>2]=0,t[e+8>>2]=0,r=n+4|0,u=(t[r>>2]|0)-(t[n>>2]|0)>>2,u|0&&(_O(e,u),EO(e,t[n>>2]|0,t[r>>2]|0,u))}function iO(e,n){e=e|0,n=n|0;var r=0,u=0;t[e>>2]=0,t[e+4>>2]=0,t[e+8>>2]=0,r=n+4|0,u=(t[r>>2]|0)-(t[n>>2]|0)>>2,u|0&&(yO(e,u),gO(e,t[n>>2]|0,t[r>>2]|0,u))}function uO(e,n,r,u,s,a){e=e|0,n=n|0,r=r|0,u=u|0,s=s|0,a=a|0;var v=0,w=0,T=0,L=0,M=0,b=0;v=y,y=y+32|0,M=v+28|0,b=v+24|0,w=v+12|0,T=v,L=_o(oO()|0)|0,t[b>>2]=t[n>>2],t[M>>2]=t[b>>2],n=Gp(M)|0,r=bw(r)|0,u=EE(u)|0,t[w>>2]=t[s>>2],M=s+4|0,t[w+4>>2]=t[M>>2],b=s+8|0,t[w+8>>2]=t[b>>2],t[b>>2]=0,t[M>>2]=0,t[s>>2]=0,s=DE(w)|0,t[T>>2]=t[a>>2],M=a+4|0,t[T+4>>2]=t[M>>2],b=a+8|0,t[T+8>>2]=t[b>>2],t[b>>2]=0,t[M>>2]=0,t[a>>2]=0,X0(0,L|0,e|0,n|0,r|0,u|0,s|0,lO(T)|0)|0,gE(T),F1(w),y=v}function oO(){var e=0;return h[7968]|0||(vO(10708),e=7968,t[e>>2]=1,t[e+4>>2]=0),10708}function Gp(e){return e=e|0,Uw(e)|0}function bw(e){return e=e|0,Bw(e)|0}function EE(e){return e=e|0,H0(e)|0}function DE(e){return e=e|0,aO(e)|0}function lO(e){return e=e|0,sO(e)|0}function sO(e){e=e|0;var n=0,r=0,u=0;if(u=(t[e+4>>2]|0)-(t[e>>2]|0)|0,r=u>>2,u=Oa(u+4|0)|0,t[u>>2]=r,r|0){n=0;do t[u+4+(n<<2)>>2]=Bw(t[(t[e>>2]|0)+(n<<2)>>2]|0)|0,n=n+1|0;while((n|0)!=(r|0))}return u|0}function Bw(e){return e=e|0,e|0}function aO(e){e=e|0;var n=0,r=0,u=0;if(u=(t[e+4>>2]|0)-(t[e>>2]|0)|0,r=u>>2,u=Oa(u+4|0)|0,t[u>>2]=r,r|0){n=0;do t[u+4+(n<<2)>>2]=Uw((t[e>>2]|0)+(n<<2)|0)|0,n=n+1|0;while((n|0)!=(r|0))}return u|0}function Uw(e){e=e|0;var n=0,r=0,u=0,s=0;return s=y,y=y+32|0,n=s+12|0,r=s,u=Pu(jw()|0)|0,u?(rs(n,u),Mf(r,n),VN(e,r),e=Cs(n)|0):e=fO(e)|0,y=s,e|0}function jw(){var e=0;return h[7960]|0||(hO(10664),Wt(25,10664,ge|0)|0,e=7960,t[e>>2]=1,t[e+4>>2]=0),10664}function fO(e){e=e|0;var n=0,r=0,u=0,s=0,a=0,v=0,w=0;return r=y,y=y+16|0,s=r+4|0,v=r,u=Oa(8)|0,n=u,w=pn(4)|0,t[w>>2]=t[e>>2],a=n+4|0,t[a>>2]=w,e=pn(8)|0,a=t[a>>2]|0,t[v>>2]=0,t[s>>2]=t[v>>2],zw(e,a,s),t[u>>2]=e,y=r,n|0}function zw(e,n,r){e=e|0,n=n|0,r=r|0,t[e>>2]=n,r=pn(16)|0,t[r+4>>2]=0,t[r+8>>2]=0,t[r>>2]=1656,t[r+12>>2]=n,t[e+4>>2]=r}function cO(e){e=e|0,Uv(e),Et(e)}function dO(e){e=e|0,e=t[e+12>>2]|0,e|0&&Et(e)}function pO(e){e=e|0,Et(e)}function hO(e){e=e|0,Xa(e)}function vO(e){e=e|0,ll(e,mO()|0,5)}function mO(){return 1676}function yO(e,n){e=e|0,n=n|0;var r=0;if((Hw(e)|0)>>>0>>0&&di(e),n>>>0>1073741823)$n();else{r=pn(n<<2)|0,t[e+4>>2]=r,t[e>>2]=r,t[e+8>>2]=r+(n<<2);return}}function gO(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0,u=e+4|0,e=r-n|0,(e|0)>0&&(gr(t[u>>2]|0,n|0,e|0)|0,t[u>>2]=(t[u>>2]|0)+(e>>>2<<2))}function Hw(e){return e=e|0,1073741823}function _O(e,n){e=e|0,n=n|0;var r=0;if((qw(e)|0)>>>0>>0&&di(e),n>>>0>1073741823)$n();else{r=pn(n<<2)|0,t[e+4>>2]=r,t[e>>2]=r,t[e+8>>2]=r+(n<<2);return}}function EO(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0,u=e+4|0,e=r-n|0,(e|0)>0&&(gr(t[u>>2]|0,n|0,e|0)|0,t[u>>2]=(t[u>>2]|0)+(e>>>2<<2))}function qw(e){return e=e|0,1073741823}function DO(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=u;do if(n)if(n>>>0>1073741823)$n();else{s=pn(n<<2)|0;break}else s=0;while(0);t[e>>2]=s,u=s+(r<<2)|0,t[e+8>>2]=u,t[e+4>>2]=u,t[e+12>>2]=s+(n<<2)}function wO(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0;u=t[e>>2]|0,v=e+4|0,a=n+4|0,s=(t[v>>2]|0)-u|0,r=(t[a>>2]|0)+(0-(s>>2)<<2)|0,t[a>>2]=r,(s|0)>0?(gr(r|0,u|0,s|0)|0,u=a,r=t[a>>2]|0):u=a,a=t[e>>2]|0,t[e>>2]=r,t[u>>2]=a,a=n+8|0,s=t[v>>2]|0,t[v>>2]=t[a>>2],t[a>>2]=s,a=e+8|0,v=n+12|0,e=t[a>>2]|0,t[a>>2]=t[v>>2],t[v>>2]=e,t[n>>2]=t[u>>2]}function SO(e){e=e|0;var n=0,r=0,u=0;n=t[e+4>>2]|0,r=e+8|0,u=t[r>>2]|0,(u|0)!=(n|0)&&(t[r>>2]=u+(~((u+-4-n|0)>>>2)<<2)),e=t[e>>2]|0,e|0&&Et(e)}function Ww(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=u;do if(n)if(n>>>0>1073741823)$n();else{s=pn(n<<2)|0;break}else s=0;while(0);t[e>>2]=s,u=s+(r<<2)|0,t[e+8>>2]=u,t[e+4>>2]=u,t[e+12>>2]=s+(n<<2)}function Vw(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0;u=t[e>>2]|0,v=e+4|0,a=n+4|0,s=(t[v>>2]|0)-u|0,r=(t[a>>2]|0)+(0-(s>>2)<<2)|0,t[a>>2]=r,(s|0)>0?(gr(r|0,u|0,s|0)|0,u=a,r=t[a>>2]|0):u=a,a=t[e>>2]|0,t[e>>2]=r,t[u>>2]=a,a=n+8|0,s=t[v>>2]|0,t[v>>2]=t[a>>2],t[a>>2]=s,a=e+8|0,v=n+12|0,e=t[a>>2]|0,t[a>>2]=t[v>>2],t[v>>2]=e,t[n>>2]=t[u>>2]}function Gw(e){e=e|0;var n=0,r=0,u=0;n=t[e+4>>2]|0,r=e+8|0,u=t[r>>2]|0,(u|0)!=(n|0)&&(t[r>>2]=u+(~((u+-4-n|0)>>>2)<<2)),e=t[e>>2]|0,e|0&&Et(e)}function TO(e,n,r,u,s){e=e|0,n=n|0,r=r|0,u=u|0,s=s|0;var a=0,v=0,w=0,T=0,L=0,M=0,b=0,X=0,Be=0,Te=0,ye=0;if(ye=y,y=y+32|0,M=ye+20|0,b=ye+12|0,L=ye+16|0,X=ye+4|0,Be=ye,Te=ye+8|0,w=Fw()|0,a=t[w>>2]|0,v=t[a>>2]|0,v|0)for(T=t[w+8>>2]|0,w=t[w+4>>2]|0;Gf(M,v),CO(e,M,w,T),a=a+4|0,v=t[a>>2]|0,v;)T=T+1|0,w=w+1|0;if(a=Pw()|0,v=t[a>>2]|0,v|0)do Gf(M,v),t[b>>2]=t[a+4>>2],xO(n,M,b),a=a+8|0,v=t[a>>2]|0;while((v|0)!=0);if(a=t[(Fv()|0)>>2]|0,a|0)do n=t[a+4>>2]|0,Gf(M,t[(Pv(n)|0)>>2]|0),t[b>>2]=hE(n)|0,RO(r,M,b),a=t[a>>2]|0;while((a|0)!=0);if(Gf(L,0),a=vE()|0,t[M>>2]=t[L>>2],Iw(M,a,s),a=t[(Fv()|0)>>2]|0,a|0){e=M+4|0,n=M+8|0,r=M+8|0;do{if(T=t[a+4>>2]|0,Gf(b,t[(Pv(T)|0)>>2]|0),AO(X,Yw(T)|0),v=t[X>>2]|0,v|0){t[M>>2]=0,t[e>>2]=0,t[n>>2]=0;do Gf(Be,t[(Pv(t[v+4>>2]|0)|0)>>2]|0),w=t[e>>2]|0,w>>>0<(t[r>>2]|0)>>>0?(t[w>>2]=t[Be>>2],t[e>>2]=(t[e>>2]|0)+4):yE(M,Be),v=t[v>>2]|0;while((v|0)!=0);OO(u,b,M),F1(M)}t[Te>>2]=t[b>>2],L=Kw(T)|0,t[M>>2]=t[Te>>2],Iw(M,L,s),_d(X),a=t[a>>2]|0}while((a|0)!=0)}y=ye}function CO(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0,zO(e,n,r,u)}function xO(e,n,r){e=e|0,n=n|0,r=r|0,jO(e,n,r)}function Pv(e){return e=e|0,e|0}function RO(e,n,r){e=e|0,n=n|0,r=r|0,IO(e,n,r)}function Yw(e){return e=e|0,e+16|0}function AO(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0,w=0,T=0;if(a=y,y=y+16|0,s=a+8|0,r=a,t[e>>2]=0,u=t[n>>2]|0,t[s>>2]=u,t[r>>2]=e,r=PO(r)|0,u|0){if(u=pn(12)|0,v=(Xw(s)|0)+4|0,e=t[v+4>>2]|0,n=u+4|0,t[n>>2]=t[v>>2],t[n+4>>2]=e,n=t[t[s>>2]>>2]|0,t[s>>2]=n,!n)e=u;else for(n=u;e=pn(12)|0,T=(Xw(s)|0)+4|0,w=t[T+4>>2]|0,v=e+4|0,t[v>>2]=t[T>>2],t[v+4>>2]=w,t[n>>2]=e,v=t[t[s>>2]>>2]|0,t[s>>2]=v,v;)n=e;t[e>>2]=t[r>>2],t[r>>2]=u}y=a}function OO(e,n,r){e=e|0,n=n|0,r=r|0,MO(e,n,r)}function Kw(e){return e=e|0,e+24|0}function MO(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0;u=y,y=y+32|0,v=u+24|0,s=u+16|0,w=u+12|0,a=u,Ma(s),e=go(e)|0,t[w>>2]=t[n>>2],_E(a,r),t[v>>2]=t[w>>2],kO(e,v,a),F1(a),ka(s),y=u}function kO(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0;u=y,y=y+32|0,v=u+16|0,w=u+12|0,s=u,a=_o(NO()|0)|0,t[w>>2]=t[n>>2],t[v>>2]=t[w>>2],n=Gp(v)|0,t[s>>2]=t[r>>2],v=r+4|0,t[s+4>>2]=t[v>>2],w=r+8|0,t[s+8>>2]=t[w>>2],t[w>>2]=0,t[v>>2]=0,t[r>>2]=0,P0(0,a|0,e|0,n|0,DE(s)|0)|0,F1(s),y=u}function NO(){var e=0;return h[7976]|0||(LO(10720),e=7976,t[e>>2]=1,t[e+4>>2]=0),10720}function LO(e){e=e|0,ll(e,FO()|0,2)}function FO(){return 1732}function PO(e){return e=e|0,t[e>>2]|0}function Xw(e){return e=e|0,t[e>>2]|0}function IO(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0;u=y,y=y+32|0,a=u+16|0,s=u+8|0,v=u,Ma(s),e=go(e)|0,t[v>>2]=t[n>>2],r=t[r>>2]|0,t[a>>2]=t[v>>2],Qw(e,a,r),ka(s),y=u}function Qw(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0;u=y,y=y+16|0,a=u+4|0,v=u,s=_o(bO()|0)|0,t[v>>2]=t[n>>2],t[a>>2]=t[v>>2],n=Gp(a)|0,P0(0,s|0,e|0,n|0,bw(r)|0)|0,y=u}function bO(){var e=0;return h[7984]|0||(BO(10732),e=7984,t[e>>2]=1,t[e+4>>2]=0),10732}function BO(e){e=e|0,ll(e,UO()|0,2)}function UO(){return 1744}function jO(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0;u=y,y=y+32|0,a=u+16|0,s=u+8|0,v=u,Ma(s),e=go(e)|0,t[v>>2]=t[n>>2],r=t[r>>2]|0,t[a>>2]=t[v>>2],Qw(e,a,r),ka(s),y=u}function zO(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0,a=0,v=0,w=0;s=y,y=y+32|0,v=s+16|0,a=s+8|0,w=s,Ma(a),e=go(e)|0,t[w>>2]=t[n>>2],r=h[r>>0]|0,u=h[u>>0]|0,t[v>>2]=t[w>>2],HO(e,v,r,u),ka(a),y=s}function HO(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0,a=0,v=0,w=0;s=y,y=y+16|0,v=s+4|0,w=s,a=_o(qO()|0)|0,t[w>>2]=t[n>>2],t[v>>2]=t[w>>2],n=Gp(v)|0,r=Iv(r)|0,Hn(0,a|0,e|0,n|0,r|0,Iv(u)|0)|0,y=s}function qO(){var e=0;return h[7992]|0||(VO(10744),e=7992,t[e>>2]=1,t[e+4>>2]=0),10744}function Iv(e){return e=e|0,WO(e)|0}function WO(e){return e=e|0,e&255|0}function VO(e){e=e|0,ll(e,GO()|0,3)}function GO(){return 1756}function YO(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0,b=0,X=0;switch(X=y,y=y+32|0,w=X+8|0,T=X+4|0,L=X+20|0,M=X,Sa(e,0),u=WN(n)|0,t[w>>2]=0,b=w+4|0,t[b>>2]=0,t[w+8>>2]=0,u<<24>>24){case 0:{h[L>>0]=0,KO(T,r,L),f_(e,T)|0,U0(T);break}case 8:{b=RE(n)|0,h[L>>0]=8,Gf(M,t[b+4>>2]|0),XO(T,r,L,M,b+8|0),f_(e,T)|0,U0(T);break}case 9:{if(a=RE(n)|0,n=t[a+4>>2]|0,n|0)for(v=w+8|0,s=a+12|0;n=n+-1|0,Gf(T,t[s>>2]|0),u=t[b>>2]|0,u>>>0<(t[v>>2]|0)>>>0?(t[u>>2]=t[T>>2],t[b>>2]=(t[b>>2]|0)+4):yE(w,T),n;)s=s+4|0;h[L>>0]=9,Gf(M,t[a+8>>2]|0),QO(T,r,L,M,w),f_(e,T)|0,U0(T);break}default:b=RE(n)|0,h[L>>0]=u,Gf(M,t[b+4>>2]|0),JO(T,r,L,M),f_(e,T)|0,U0(T)}F1(w),y=X}function KO(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0;u=y,y=y+16|0,s=u,Ma(s),n=go(n)|0,fM(e,n,h[r>>0]|0),ka(s),y=u}function f_(e,n){e=e|0,n=n|0;var r=0;return r=t[e>>2]|0,r|0&&qr(r|0),t[e>>2]=t[n>>2],t[n>>2]=0,e|0}function XO(e,n,r,u,s){e=e|0,n=n|0,r=r|0,u=u|0,s=s|0;var a=0,v=0,w=0,T=0;a=y,y=y+32|0,w=a+16|0,v=a+8|0,T=a,Ma(v),n=go(n)|0,r=h[r>>0]|0,t[T>>2]=t[u>>2],s=t[s>>2]|0,t[w>>2]=t[T>>2],oM(e,n,r,w,s),ka(v),y=a}function QO(e,n,r,u,s){e=e|0,n=n|0,r=r|0,u=u|0,s=s|0;var a=0,v=0,w=0,T=0,L=0;a=y,y=y+32|0,T=a+24|0,v=a+16|0,L=a+12|0,w=a,Ma(v),n=go(n)|0,r=h[r>>0]|0,t[L>>2]=t[u>>2],_E(w,s),t[T>>2]=t[L>>2],nM(e,n,r,T,w),F1(w),ka(v),y=a}function JO(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0,a=0,v=0,w=0;s=y,y=y+32|0,v=s+16|0,a=s+8|0,w=s,Ma(a),n=go(n)|0,r=h[r>>0]|0,t[w>>2]=t[u>>2],t[v>>2]=t[w>>2],ZO(e,n,r,v),ka(a),y=s}function ZO(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0,a=0,v=0,w=0;s=y,y=y+16|0,a=s+4|0,w=s,v=_o($O()|0)|0,r=Iv(r)|0,t[w>>2]=t[u>>2],t[a>>2]=t[w>>2],c_(e,P0(0,v|0,n|0,r|0,Gp(a)|0)|0),y=s}function $O(){var e=0;return h[8e3]|0||(eM(10756),e=8e3,t[e>>2]=1,t[e+4>>2]=0),10756}function c_(e,n){e=e|0,n=n|0,Sa(e,n)}function eM(e){e=e|0,ll(e,tM()|0,2)}function tM(){return 1772}function nM(e,n,r,u,s){e=e|0,n=n|0,r=r|0,u=u|0,s=s|0;var a=0,v=0,w=0,T=0,L=0;a=y,y=y+32|0,T=a+16|0,L=a+12|0,v=a,w=_o(rM()|0)|0,r=Iv(r)|0,t[L>>2]=t[u>>2],t[T>>2]=t[L>>2],u=Gp(T)|0,t[v>>2]=t[s>>2],T=s+4|0,t[v+4>>2]=t[T>>2],L=s+8|0,t[v+8>>2]=t[L>>2],t[L>>2]=0,t[T>>2]=0,t[s>>2]=0,c_(e,Hn(0,w|0,n|0,r|0,u|0,DE(v)|0)|0),F1(v),y=a}function rM(){var e=0;return h[8008]|0||(iM(10768),e=8008,t[e>>2]=1,t[e+4>>2]=0),10768}function iM(e){e=e|0,ll(e,uM()|0,3)}function uM(){return 1784}function oM(e,n,r,u,s){e=e|0,n=n|0,r=r|0,u=u|0,s=s|0;var a=0,v=0,w=0,T=0;a=y,y=y+16|0,w=a+4|0,T=a,v=_o(lM()|0)|0,r=Iv(r)|0,t[T>>2]=t[u>>2],t[w>>2]=t[T>>2],u=Gp(w)|0,c_(e,Hn(0,v|0,n|0,r|0,u|0,EE(s)|0)|0),y=a}function lM(){var e=0;return h[8016]|0||(sM(10780),e=8016,t[e>>2]=1,t[e+4>>2]=0),10780}function sM(e){e=e|0,ll(e,aM()|0,3)}function aM(){return 1800}function fM(e,n,r){e=e|0,n=n|0,r=r|0;var u=0;u=_o(cM()|0)|0,c_(e,Ki(0,u|0,n|0,Iv(r)|0)|0)}function cM(){var e=0;return h[8024]|0||(dM(10792),e=8024,t[e>>2]=1,t[e+4>>2]=0),10792}function dM(e){e=e|0,ll(e,pM()|0,1)}function pM(){return 1816}function hM(){vM(),mM(),yM()}function vM(){t[2702]=T8(65536)|0}function mM(){bM(10856)}function yM(){gM(10816)}function gM(e){e=e|0,_M(e,5044),EM(e)|0}function _M(e,n){e=e|0,n=n|0;var r=0;r=jw()|0,t[e>>2]=r,kM(r,n),Zd(t[e>>2]|0)}function EM(e){e=e|0;var n=0;return n=t[e>>2]|0,Wp(n,DM()|0),e|0}function DM(){var e=0;return h[8032]|0||(Jw(10820),Wt(64,10820,ge|0)|0,e=8032,t[e>>2]=1,t[e+4>>2]=0),sr(10820)|0||Jw(10820),10820}function Jw(e){e=e|0,TM(e),Vp(e,25)}function wM(e){e=e|0,SM(e+24|0)}function SM(e){e=e|0;var n=0,r=0,u=0;r=t[e>>2]|0,u=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-8-u|0)>>>3)<<3)),Et(r))}function TM(e){e=e|0;var n=0;n=yr()|0,jn(e,5,18,n,AM()|0,1),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function CM(e,n){e=e|0,n=n|0,xM(e,n)}function xM(e,n){e=e|0,n=n|0;var r=0,u=0,s=0;r=y,y=y+16|0,u=r,s=r+4|0,Pf(s,n),t[u>>2]=If(s,n)|0,RM(e,u),y=r}function RM(e,n){e=e|0,n=n|0,Zw(e+4|0,t[n>>2]|0),h[e+8>>0]=1}function Zw(e,n){e=e|0,n=n|0,t[e>>2]=n}function AM(){return 1824}function OM(e){return e=e|0,MM(e)|0}function MM(e){e=e|0;var n=0,r=0,u=0,s=0,a=0,v=0,w=0;return r=y,y=y+16|0,s=r+4|0,v=r,u=Oa(8)|0,n=u,w=pn(4)|0,Pf(s,e),Zw(w,If(s,e)|0),a=n+4|0,t[a>>2]=w,e=pn(8)|0,a=t[a>>2]|0,t[v>>2]=0,t[s>>2]=t[v>>2],zw(e,a,s),t[u>>2]=e,y=r,n|0}function Oa(e){e=e|0;var n=0,r=0;return e=e+7&-8,e>>>0<=32768&&(n=t[2701]|0,e>>>0<=(65536-n|0)>>>0)?(r=(t[2702]|0)+n|0,t[2701]=n+e,e=r):(e=T8(e+8|0)|0,t[e>>2]=t[2703],t[2703]=e,e=e+8|0),e|0}function kM(e,n){e=e|0,n=n|0,t[e>>2]=NM()|0,t[e+4>>2]=LM()|0,t[e+12>>2]=n,t[e+8>>2]=FM()|0,t[e+32>>2]=9}function NM(){return 11744}function LM(){return 1832}function FM(){return s_()|0}function PM(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0,(Hl(u,896)|0)==512?r|0&&(IM(r),Et(r)):n|0&&Et(n)}function IM(e){e=e|0,e=t[e+4>>2]|0,e|0&&$d(e)}function bM(e){e=e|0,BM(e,5052),UM(e)|0,jM(e,5058,26)|0,zM(e,5069,1)|0,HM(e,5077,10)|0,qM(e,5087,19)|0,WM(e,5094,27)|0}function BM(e,n){e=e|0,n=n|0;var r=0;r=IN()|0,t[e>>2]=r,bN(r,n),Zd(t[e>>2]|0)}function UM(e){e=e|0;var n=0;return n=t[e>>2]|0,Wp(n,wN()|0),e|0}function jM(e,n,r){return e=e|0,n=n|0,r=r|0,iN(e,Fr(n)|0,r,0),e|0}function zM(e,n,r){return e=e|0,n=n|0,r=r|0,qk(e,Fr(n)|0,r,0),e|0}function HM(e,n,r){return e=e|0,n=n|0,r=r|0,Dk(e,Fr(n)|0,r,0),e|0}function qM(e,n,r){return e=e|0,n=n|0,r=r|0,ok(e,Fr(n)|0,r,0),e|0}function $w(e,n){e=e|0,n=n|0;var r=0,u=0;e:for(;;){for(r=t[2703]|0;;){if((r|0)==(n|0))break e;if(u=t[r>>2]|0,t[2703]=u,!r)r=u;else break}Et(r)}t[2701]=e}function WM(e,n,r){return e=e|0,n=n|0,r=r|0,VM(e,Fr(n)|0,r,0),e|0}function VM(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0,a=0;a=t[e>>2]|0,s=wE()|0,e=GM(r)|0,wi(a,n,s,e,YM(r,u)|0,u)}function wE(){var e=0,n=0;if(h[8040]|0||(t8(10860),Wt(65,10860,ge|0)|0,n=8040,t[n>>2]=1,t[n+4>>2]=0),!(sr(10860)|0)){e=10860,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));t8(10860)}return 10860}function GM(e){return e=e|0,e|0}function YM(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0,w=0,T=0;return w=y,y=y+16|0,s=w,a=w+4|0,t[s>>2]=e,T=wE()|0,v=T+24|0,n=hn(n,4)|0,t[a>>2]=n,r=T+28|0,u=t[r>>2]|0,u>>>0<(t[T+32>>2]|0)>>>0?(e8(u,e,n),n=(t[r>>2]|0)+8|0,t[r>>2]=n):(KM(v,s,a),n=t[r>>2]|0),y=w,(n-(t[v>>2]|0)>>3)+-1|0}function e8(e,n,r){e=e|0,n=n|0,r=r|0,t[e>>2]=n,t[e+4>>2]=r}function KM(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0;if(w=y,y=y+32|0,s=w,a=e+4|0,v=((t[a>>2]|0)-(t[e>>2]|0)>>3)+1|0,u=XM(e)|0,u>>>0>>0)di(e);else{T=t[e>>2]|0,M=(t[e+8>>2]|0)-T|0,L=M>>2,QM(s,M>>3>>>0>>1>>>0?L>>>0>>0?v:L:u,(t[a>>2]|0)-T>>3,e+8|0),v=s+8|0,e8(t[v>>2]|0,t[n>>2]|0,t[r>>2]|0),t[v>>2]=(t[v>>2]|0)+8,JM(e,s),ZM(s),y=w;return}}function XM(e){return e=e|0,536870911}function QM(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=u;do if(n)if(n>>>0>536870911)$n();else{s=pn(n<<3)|0;break}else s=0;while(0);t[e>>2]=s,u=s+(r<<3)|0,t[e+8>>2]=u,t[e+4>>2]=u,t[e+12>>2]=s+(n<<3)}function JM(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0;u=t[e>>2]|0,v=e+4|0,a=n+4|0,s=(t[v>>2]|0)-u|0,r=(t[a>>2]|0)+(0-(s>>3)<<3)|0,t[a>>2]=r,(s|0)>0?(gr(r|0,u|0,s|0)|0,u=a,r=t[a>>2]|0):u=a,a=t[e>>2]|0,t[e>>2]=r,t[u>>2]=a,a=n+8|0,s=t[v>>2]|0,t[v>>2]=t[a>>2],t[a>>2]=s,a=e+8|0,v=n+12|0,e=t[a>>2]|0,t[a>>2]=t[v>>2],t[v>>2]=e,t[n>>2]=t[u>>2]}function ZM(e){e=e|0;var n=0,r=0,u=0;n=t[e+4>>2]|0,r=e+8|0,u=t[r>>2]|0,(u|0)!=(n|0)&&(t[r>>2]=u+(~((u+-8-n|0)>>>3)<<3)),e=t[e>>2]|0,e|0&&Et(e)}function t8(e){e=e|0,tk(e)}function $M(e){e=e|0,ek(e+24|0)}function ek(e){e=e|0;var n=0,r=0,u=0;r=t[e>>2]|0,u=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-8-u|0)>>>3)<<3)),Et(r))}function tk(e){e=e|0;var n=0;n=yr()|0,jn(e,1,11,n,nk()|0,2),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function nk(){return 1840}function rk(e,n,r){e=e|0,n=n|0,r=r|0,uk(t[(ik(e)|0)>>2]|0,n,r)}function ik(e){return e=e|0,(t[(wE()|0)+24>>2]|0)+(e<<3)|0}function uk(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0;u=y,y=y+16|0,a=u+1|0,s=u,Pf(a,n),n=If(a,n)|0,Pf(s,r),r=If(s,r)|0,I1[e&31](n,r),y=u}function ok(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0,a=0;a=t[e>>2]|0,s=SE()|0,e=lk(r)|0,wi(a,n,s,e,sk(r,u)|0,u)}function SE(){var e=0,n=0;if(h[8048]|0||(r8(10896),Wt(66,10896,ge|0)|0,n=8048,t[n>>2]=1,t[n+4>>2]=0),!(sr(10896)|0)){e=10896,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));r8(10896)}return 10896}function lk(e){return e=e|0,e|0}function sk(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0,w=0,T=0;return w=y,y=y+16|0,s=w,a=w+4|0,t[s>>2]=e,T=SE()|0,v=T+24|0,n=hn(n,4)|0,t[a>>2]=n,r=T+28|0,u=t[r>>2]|0,u>>>0<(t[T+32>>2]|0)>>>0?(n8(u,e,n),n=(t[r>>2]|0)+8|0,t[r>>2]=n):(ak(v,s,a),n=t[r>>2]|0),y=w,(n-(t[v>>2]|0)>>3)+-1|0}function n8(e,n,r){e=e|0,n=n|0,r=r|0,t[e>>2]=n,t[e+4>>2]=r}function ak(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0;if(w=y,y=y+32|0,s=w,a=e+4|0,v=((t[a>>2]|0)-(t[e>>2]|0)>>3)+1|0,u=fk(e)|0,u>>>0>>0)di(e);else{T=t[e>>2]|0,M=(t[e+8>>2]|0)-T|0,L=M>>2,ck(s,M>>3>>>0>>1>>>0?L>>>0>>0?v:L:u,(t[a>>2]|0)-T>>3,e+8|0),v=s+8|0,n8(t[v>>2]|0,t[n>>2]|0,t[r>>2]|0),t[v>>2]=(t[v>>2]|0)+8,dk(e,s),pk(s),y=w;return}}function fk(e){return e=e|0,536870911}function ck(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=u;do if(n)if(n>>>0>536870911)$n();else{s=pn(n<<3)|0;break}else s=0;while(0);t[e>>2]=s,u=s+(r<<3)|0,t[e+8>>2]=u,t[e+4>>2]=u,t[e+12>>2]=s+(n<<3)}function dk(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0;u=t[e>>2]|0,v=e+4|0,a=n+4|0,s=(t[v>>2]|0)-u|0,r=(t[a>>2]|0)+(0-(s>>3)<<3)|0,t[a>>2]=r,(s|0)>0?(gr(r|0,u|0,s|0)|0,u=a,r=t[a>>2]|0):u=a,a=t[e>>2]|0,t[e>>2]=r,t[u>>2]=a,a=n+8|0,s=t[v>>2]|0,t[v>>2]=t[a>>2],t[a>>2]=s,a=e+8|0,v=n+12|0,e=t[a>>2]|0,t[a>>2]=t[v>>2],t[v>>2]=e,t[n>>2]=t[u>>2]}function pk(e){e=e|0;var n=0,r=0,u=0;n=t[e+4>>2]|0,r=e+8|0,u=t[r>>2]|0,(u|0)!=(n|0)&&(t[r>>2]=u+(~((u+-8-n|0)>>>3)<<3)),e=t[e>>2]|0,e|0&&Et(e)}function r8(e){e=e|0,mk(e)}function hk(e){e=e|0,vk(e+24|0)}function vk(e){e=e|0;var n=0,r=0,u=0;r=t[e>>2]|0,u=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-8-u|0)>>>3)<<3)),Et(r))}function mk(e){e=e|0;var n=0;n=yr()|0,jn(e,1,11,n,yk()|0,1),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function yk(){return 1852}function gk(e,n){return e=e|0,n=n|0,Ek(t[(_k(e)|0)>>2]|0,n)|0}function _k(e){return e=e|0,(t[(SE()|0)+24>>2]|0)+(e<<3)|0}function Ek(e,n){e=e|0,n=n|0;var r=0,u=0;return r=y,y=y+16|0,u=r,Pf(u,n),n=If(u,n)|0,n=H0(Qp[e&31](n)|0)|0,y=r,n|0}function Dk(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0,a=0;a=t[e>>2]|0,s=TE()|0,e=wk(r)|0,wi(a,n,s,e,Sk(r,u)|0,u)}function TE(){var e=0,n=0;if(h[8056]|0||(u8(10932),Wt(67,10932,ge|0)|0,n=8056,t[n>>2]=1,t[n+4>>2]=0),!(sr(10932)|0)){e=10932,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));u8(10932)}return 10932}function wk(e){return e=e|0,e|0}function Sk(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0,w=0,T=0;return w=y,y=y+16|0,s=w,a=w+4|0,t[s>>2]=e,T=TE()|0,v=T+24|0,n=hn(n,4)|0,t[a>>2]=n,r=T+28|0,u=t[r>>2]|0,u>>>0<(t[T+32>>2]|0)>>>0?(i8(u,e,n),n=(t[r>>2]|0)+8|0,t[r>>2]=n):(Tk(v,s,a),n=t[r>>2]|0),y=w,(n-(t[v>>2]|0)>>3)+-1|0}function i8(e,n,r){e=e|0,n=n|0,r=r|0,t[e>>2]=n,t[e+4>>2]=r}function Tk(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0;if(w=y,y=y+32|0,s=w,a=e+4|0,v=((t[a>>2]|0)-(t[e>>2]|0)>>3)+1|0,u=Ck(e)|0,u>>>0>>0)di(e);else{T=t[e>>2]|0,M=(t[e+8>>2]|0)-T|0,L=M>>2,xk(s,M>>3>>>0>>1>>>0?L>>>0>>0?v:L:u,(t[a>>2]|0)-T>>3,e+8|0),v=s+8|0,i8(t[v>>2]|0,t[n>>2]|0,t[r>>2]|0),t[v>>2]=(t[v>>2]|0)+8,Rk(e,s),Ak(s),y=w;return}}function Ck(e){return e=e|0,536870911}function xk(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=u;do if(n)if(n>>>0>536870911)$n();else{s=pn(n<<3)|0;break}else s=0;while(0);t[e>>2]=s,u=s+(r<<3)|0,t[e+8>>2]=u,t[e+4>>2]=u,t[e+12>>2]=s+(n<<3)}function Rk(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0;u=t[e>>2]|0,v=e+4|0,a=n+4|0,s=(t[v>>2]|0)-u|0,r=(t[a>>2]|0)+(0-(s>>3)<<3)|0,t[a>>2]=r,(s|0)>0?(gr(r|0,u|0,s|0)|0,u=a,r=t[a>>2]|0):u=a,a=t[e>>2]|0,t[e>>2]=r,t[u>>2]=a,a=n+8|0,s=t[v>>2]|0,t[v>>2]=t[a>>2],t[a>>2]=s,a=e+8|0,v=n+12|0,e=t[a>>2]|0,t[a>>2]=t[v>>2],t[v>>2]=e,t[n>>2]=t[u>>2]}function Ak(e){e=e|0;var n=0,r=0,u=0;n=t[e+4>>2]|0,r=e+8|0,u=t[r>>2]|0,(u|0)!=(n|0)&&(t[r>>2]=u+(~((u+-8-n|0)>>>3)<<3)),e=t[e>>2]|0,e|0&&Et(e)}function u8(e){e=e|0,kk(e)}function Ok(e){e=e|0,Mk(e+24|0)}function Mk(e){e=e|0;var n=0,r=0,u=0;r=t[e>>2]|0,u=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-8-u|0)>>>3)<<3)),Et(r))}function kk(e){e=e|0;var n=0;n=yr()|0,jn(e,1,7,n,Nk()|0,2),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function Nk(){return 1860}function Lk(e,n,r){return e=e|0,n=n|0,r=r|0,Pk(t[(Fk(e)|0)>>2]|0,n,r)|0}function Fk(e){return e=e|0,(t[(TE()|0)+24>>2]|0)+(e<<3)|0}function Pk(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0,T=0;return u=y,y=y+32|0,v=u+12|0,a=u+8|0,w=u,T=u+16|0,s=u+4|0,Ik(T,n),bk(w,T,n),Ys(s,r),r=Ks(s,r)|0,t[v>>2]=t[w>>2],Fy[e&15](a,v,r),r=Bk(a)|0,U0(a),Xs(s),y=u,r|0}function Ik(e,n){e=e|0,n=n|0}function bk(e,n,r){e=e|0,n=n|0,r=r|0,Uk(e,r)}function Bk(e){return e=e|0,go(e)|0}function Uk(e,n){e=e|0,n=n|0;var r=0,u=0,s=0;s=y,y=y+16|0,r=s,u=n,u&1?(jk(r,0),eu(u|0,r|0)|0,zk(e,r),Hk(r)):t[e>>2]=t[n>>2],y=s}function jk(e,n){e=e|0,n=n|0,fd(e,n),t[e+4>>2]=0,h[e+8>>0]=0}function zk(e,n){e=e|0,n=n|0,t[e>>2]=t[n+4>>2]}function Hk(e){e=e|0,h[e+8>>0]=0}function qk(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0,a=0;a=t[e>>2]|0,s=CE()|0,e=Wk(r)|0,wi(a,n,s,e,Vk(r,u)|0,u)}function CE(){var e=0,n=0;if(h[8064]|0||(l8(10968),Wt(68,10968,ge|0)|0,n=8064,t[n>>2]=1,t[n+4>>2]=0),!(sr(10968)|0)){e=10968,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));l8(10968)}return 10968}function Wk(e){return e=e|0,e|0}function Vk(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0,w=0,T=0;return w=y,y=y+16|0,s=w,a=w+4|0,t[s>>2]=e,T=CE()|0,v=T+24|0,n=hn(n,4)|0,t[a>>2]=n,r=T+28|0,u=t[r>>2]|0,u>>>0<(t[T+32>>2]|0)>>>0?(o8(u,e,n),n=(t[r>>2]|0)+8|0,t[r>>2]=n):(Gk(v,s,a),n=t[r>>2]|0),y=w,(n-(t[v>>2]|0)>>3)+-1|0}function o8(e,n,r){e=e|0,n=n|0,r=r|0,t[e>>2]=n,t[e+4>>2]=r}function Gk(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0;if(w=y,y=y+32|0,s=w,a=e+4|0,v=((t[a>>2]|0)-(t[e>>2]|0)>>3)+1|0,u=Yk(e)|0,u>>>0>>0)di(e);else{T=t[e>>2]|0,M=(t[e+8>>2]|0)-T|0,L=M>>2,Kk(s,M>>3>>>0>>1>>>0?L>>>0>>0?v:L:u,(t[a>>2]|0)-T>>3,e+8|0),v=s+8|0,o8(t[v>>2]|0,t[n>>2]|0,t[r>>2]|0),t[v>>2]=(t[v>>2]|0)+8,Xk(e,s),Qk(s),y=w;return}}function Yk(e){return e=e|0,536870911}function Kk(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=u;do if(n)if(n>>>0>536870911)$n();else{s=pn(n<<3)|0;break}else s=0;while(0);t[e>>2]=s,u=s+(r<<3)|0,t[e+8>>2]=u,t[e+4>>2]=u,t[e+12>>2]=s+(n<<3)}function Xk(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0;u=t[e>>2]|0,v=e+4|0,a=n+4|0,s=(t[v>>2]|0)-u|0,r=(t[a>>2]|0)+(0-(s>>3)<<3)|0,t[a>>2]=r,(s|0)>0?(gr(r|0,u|0,s|0)|0,u=a,r=t[a>>2]|0):u=a,a=t[e>>2]|0,t[e>>2]=r,t[u>>2]=a,a=n+8|0,s=t[v>>2]|0,t[v>>2]=t[a>>2],t[a>>2]=s,a=e+8|0,v=n+12|0,e=t[a>>2]|0,t[a>>2]=t[v>>2],t[v>>2]=e,t[n>>2]=t[u>>2]}function Qk(e){e=e|0;var n=0,r=0,u=0;n=t[e+4>>2]|0,r=e+8|0,u=t[r>>2]|0,(u|0)!=(n|0)&&(t[r>>2]=u+(~((u+-8-n|0)>>>3)<<3)),e=t[e>>2]|0,e|0&&Et(e)}function l8(e){e=e|0,$k(e)}function Jk(e){e=e|0,Zk(e+24|0)}function Zk(e){e=e|0;var n=0,r=0,u=0;r=t[e>>2]|0,u=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-8-u|0)>>>3)<<3)),Et(r))}function $k(e){e=e|0;var n=0;n=yr()|0,jn(e,1,1,n,eN()|0,5),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function eN(){return 1872}function tN(e,n,r,u,s,a){e=e|0,n=n|0,r=r|0,u=u|0,s=s|0,a=a|0,rN(t[(nN(e)|0)>>2]|0,n,r,u,s,a)}function nN(e){return e=e|0,(t[(CE()|0)+24>>2]|0)+(e<<3)|0}function rN(e,n,r,u,s,a){e=e|0,n=n|0,r=r|0,u=u|0,s=s|0,a=a|0;var v=0,w=0,T=0,L=0,M=0,b=0;v=y,y=y+32|0,w=v+16|0,T=v+12|0,L=v+8|0,M=v+4|0,b=v,Ys(w,n),n=Ks(w,n)|0,Ys(T,r),r=Ks(T,r)|0,Ys(L,u),u=Ks(L,u)|0,Ys(M,s),s=Ks(M,s)|0,Ys(b,a),a=Ks(b,a)|0,O8[e&1](n,r,u,s,a),Xs(b),Xs(M),Xs(L),Xs(T),Xs(w),y=v}function iN(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0,a=0;a=t[e>>2]|0,s=xE()|0,e=uN(r)|0,wi(a,n,s,e,oN(r,u)|0,u)}function xE(){var e=0,n=0;if(h[8072]|0||(a8(11004),Wt(69,11004,ge|0)|0,n=8072,t[n>>2]=1,t[n+4>>2]=0),!(sr(11004)|0)){e=11004,n=e+36|0;do t[e>>2]=0,e=e+4|0;while((e|0)<(n|0));a8(11004)}return 11004}function uN(e){return e=e|0,e|0}function oN(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0,w=0,T=0;return w=y,y=y+16|0,s=w,a=w+4|0,t[s>>2]=e,T=xE()|0,v=T+24|0,n=hn(n,4)|0,t[a>>2]=n,r=T+28|0,u=t[r>>2]|0,u>>>0<(t[T+32>>2]|0)>>>0?(s8(u,e,n),n=(t[r>>2]|0)+8|0,t[r>>2]=n):(lN(v,s,a),n=t[r>>2]|0),y=w,(n-(t[v>>2]|0)>>3)+-1|0}function s8(e,n,r){e=e|0,n=n|0,r=r|0,t[e>>2]=n,t[e+4>>2]=r}function lN(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0;if(w=y,y=y+32|0,s=w,a=e+4|0,v=((t[a>>2]|0)-(t[e>>2]|0)>>3)+1|0,u=sN(e)|0,u>>>0>>0)di(e);else{T=t[e>>2]|0,M=(t[e+8>>2]|0)-T|0,L=M>>2,aN(s,M>>3>>>0>>1>>>0?L>>>0>>0?v:L:u,(t[a>>2]|0)-T>>3,e+8|0),v=s+8|0,s8(t[v>>2]|0,t[n>>2]|0,t[r>>2]|0),t[v>>2]=(t[v>>2]|0)+8,fN(e,s),cN(s),y=w;return}}function sN(e){return e=e|0,536870911}function aN(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0;t[e+12>>2]=0,t[e+16>>2]=u;do if(n)if(n>>>0>536870911)$n();else{s=pn(n<<3)|0;break}else s=0;while(0);t[e>>2]=s,u=s+(r<<3)|0,t[e+8>>2]=u,t[e+4>>2]=u,t[e+12>>2]=s+(n<<3)}function fN(e,n){e=e|0,n=n|0;var r=0,u=0,s=0,a=0,v=0;u=t[e>>2]|0,v=e+4|0,a=n+4|0,s=(t[v>>2]|0)-u|0,r=(t[a>>2]|0)+(0-(s>>3)<<3)|0,t[a>>2]=r,(s|0)>0?(gr(r|0,u|0,s|0)|0,u=a,r=t[a>>2]|0):u=a,a=t[e>>2]|0,t[e>>2]=r,t[u>>2]=a,a=n+8|0,s=t[v>>2]|0,t[v>>2]=t[a>>2],t[a>>2]=s,a=e+8|0,v=n+12|0,e=t[a>>2]|0,t[a>>2]=t[v>>2],t[v>>2]=e,t[n>>2]=t[u>>2]}function cN(e){e=e|0;var n=0,r=0,u=0;n=t[e+4>>2]|0,r=e+8|0,u=t[r>>2]|0,(u|0)!=(n|0)&&(t[r>>2]=u+(~((u+-8-n|0)>>>3)<<3)),e=t[e>>2]|0,e|0&&Et(e)}function a8(e){e=e|0,hN(e)}function dN(e){e=e|0,pN(e+24|0)}function pN(e){e=e|0;var n=0,r=0,u=0;r=t[e>>2]|0,u=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-8-u|0)>>>3)<<3)),Et(r))}function hN(e){e=e|0;var n=0;n=yr()|0,jn(e,1,12,n,vN()|0,2),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function vN(){return 1896}function mN(e,n,r){e=e|0,n=n|0,r=r|0,gN(t[(yN(e)|0)>>2]|0,n,r)}function yN(e){return e=e|0,(t[(xE()|0)+24>>2]|0)+(e<<3)|0}function gN(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0;u=y,y=y+16|0,a=u+4|0,s=u,_N(a,n),n=EN(a,n)|0,Ys(s,r),r=Ks(s,r)|0,I1[e&31](n,r),Xs(s),y=u}function _N(e,n){e=e|0,n=n|0}function EN(e,n){return e=e|0,n=n|0,DN(n)|0}function DN(e){return e=e|0,e|0}function wN(){var e=0;return h[8080]|0||(f8(11040),Wt(70,11040,ge|0)|0,e=8080,t[e>>2]=1,t[e+4>>2]=0),sr(11040)|0||f8(11040),11040}function f8(e){e=e|0,CN(e),Vp(e,71)}function SN(e){e=e|0,TN(e+24|0)}function TN(e){e=e|0;var n=0,r=0,u=0;r=t[e>>2]|0,u=r,r|0&&(e=e+4|0,n=t[e>>2]|0,(n|0)!=(r|0)&&(t[e>>2]=n+(~((n+-8-u|0)>>>3)<<3)),Et(r))}function CN(e){e=e|0;var n=0;n=yr()|0,jn(e,5,7,n,ON()|0,0),t[e+24>>2]=0,t[e+28>>2]=0,t[e+32>>2]=0}function xN(e){e=e|0,RN(e)}function RN(e){e=e|0,AN(e)}function AN(e){e=e|0,h[e+8>>0]=1}function ON(){return 1936}function MN(){return kN()|0}function kN(){var e=0,n=0,r=0,u=0,s=0,a=0,v=0;return n=y,y=y+16|0,s=n+4|0,v=n,r=Oa(8)|0,e=r,a=e+4|0,t[a>>2]=pn(1)|0,u=pn(8)|0,a=t[a>>2]|0,t[v>>2]=0,t[s>>2]=t[v>>2],NN(u,a,s),t[r>>2]=u,y=n,e|0}function NN(e,n,r){e=e|0,n=n|0,r=r|0,t[e>>2]=n,r=pn(16)|0,t[r+4>>2]=0,t[r+8>>2]=0,t[r>>2]=1916,t[r+12>>2]=n,t[e+4>>2]=r}function LN(e){e=e|0,Uv(e),Et(e)}function FN(e){e=e|0,e=t[e+12>>2]|0,e|0&&Et(e)}function PN(e){e=e|0,Et(e)}function IN(){var e=0;return h[8088]|0||(qN(11076),Wt(25,11076,ge|0)|0,e=8088,t[e>>2]=1,t[e+4>>2]=0),11076}function bN(e,n){e=e|0,n=n|0,t[e>>2]=BN()|0,t[e+4>>2]=UN()|0,t[e+12>>2]=n,t[e+8>>2]=jN()|0,t[e+32>>2]=10}function BN(){return 11745}function UN(){return 1940}function jN(){return L1()|0}function zN(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0,(Hl(u,896)|0)==512?r|0&&(HN(r),Et(r)):n|0&&Et(n)}function HN(e){e=e|0,e=t[e+4>>2]|0,e|0&&$d(e)}function qN(e){e=e|0,Xa(e)}function Gf(e,n){e=e|0,n=n|0,t[e>>2]=n}function RE(e){return e=e|0,t[e>>2]|0}function WN(e){return e=e|0,h[t[e>>2]>>0]|0}function VN(e,n){e=e|0,n=n|0;var r=0,u=0;r=y,y=y+16|0,u=r,t[u>>2]=t[e>>2],GN(n,u)|0,y=r}function GN(e,n){e=e|0,n=n|0;var r=0;return r=YN(t[e>>2]|0,n)|0,n=e+4|0,t[(t[n>>2]|0)+8>>2]=r,t[(t[n>>2]|0)+8>>2]|0}function YN(e,n){e=e|0,n=n|0;var r=0,u=0;return r=y,y=y+16|0,u=r,Ma(u),e=go(e)|0,n=KN(e,t[n>>2]|0)|0,ka(u),y=r,n|0}function Ma(e){e=e|0,t[e>>2]=t[2701],t[e+4>>2]=t[2703]}function KN(e,n){e=e|0,n=n|0;var r=0;return r=_o(XN()|0)|0,Ki(0,r|0,e|0,EE(n)|0)|0}function ka(e){e=e|0,$w(t[e>>2]|0,t[e+4>>2]|0)}function XN(){var e=0;return h[8096]|0||(QN(11120),e=8096,t[e>>2]=1,t[e+4>>2]=0),11120}function QN(e){e=e|0,ll(e,JN()|0,1)}function JN(){return 1948}function ZN(){$N()}function $N(){var e=0,n=0,r=0,u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0,b=0,X=0,Be=0,Te=0,ye=0;if(Te=y,y=y+16|0,M=Te+4|0,b=Te,In(65536,10804,t[2702]|0,10812),r=Fw()|0,n=t[r>>2]|0,e=t[n>>2]|0,e|0)for(u=t[r+8>>2]|0,r=t[r+4>>2]|0;Xl(e|0,N[r>>0]|0|0,h[u>>0]|0),n=n+4|0,e=t[n>>2]|0,e;)u=u+1|0,r=r+1|0;if(e=Pw()|0,n=t[e>>2]|0,n|0)do ko(n|0,t[e+4>>2]|0),e=e+8|0,n=t[e>>2]|0;while((n|0)!=0);ko(eL()|0,5167),L=Fv()|0,e=t[L>>2]|0;e:do if(e|0){do tL(t[e+4>>2]|0),e=t[e>>2]|0;while((e|0)!=0);if(e=t[L>>2]|0,e|0){T=L;do{for(;s=e,e=t[e>>2]|0,s=t[s+4>>2]|0,!!(nL(s)|0);)if(t[b>>2]=T,t[M>>2]=t[b>>2],rL(L,M)|0,!e)break e;if(iL(s),T=t[T>>2]|0,n=c8(s)|0,a=fo()|0,v=y,y=y+((1*(n<<2)|0)+15&-16)|0,w=y,y=y+((1*(n<<2)|0)+15&-16)|0,n=t[(Yw(s)|0)>>2]|0,n|0)for(r=v,u=w;t[r>>2]=t[(Pv(t[n+4>>2]|0)|0)>>2],t[u>>2]=t[n+8>>2],n=t[n>>2]|0,n;)r=r+4|0,u=u+4|0;ye=Pv(s)|0,n=uL(s)|0,r=c8(s)|0,u=oL(s)|0,No(ye|0,n|0,v|0,w|0,r|0,u|0,hE(s)|0),yi(a|0)}while((e|0)!=0)}}while(0);if(e=t[(vE()|0)>>2]|0,e|0)do ye=e+4|0,L=mE(ye)|0,s=My(L)|0,a=Ay(L)|0,v=(Oy(L)|0)+1|0,w=d_(L)|0,T=d8(ye)|0,L=sr(L)|0,M=a_(ye)|0,b=AE(ye)|0,ao(0,s|0,a|0,v|0,w|0,T|0,L|0,M|0,b|0,OE(ye)|0),e=t[e>>2]|0;while((e|0)!=0);e=t[(Fv()|0)>>2]|0;e:do if(e|0){t:for(;;){if(n=t[e+4>>2]|0,n|0&&(X=t[(Pv(n)|0)>>2]|0,Be=t[(Kw(n)|0)>>2]|0,Be|0)){r=Be;do{n=r+4|0,u=mE(n)|0;n:do if(u|0)switch(sr(u)|0){case 0:break t;case 4:case 3:case 2:{w=My(u)|0,T=Ay(u)|0,L=(Oy(u)|0)+1|0,M=d_(u)|0,b=sr(u)|0,ye=a_(n)|0,ao(X|0,w|0,T|0,L|0,M|0,0,b|0,ye|0,AE(n)|0,OE(n)|0);break n}case 1:{v=My(u)|0,w=Ay(u)|0,T=(Oy(u)|0)+1|0,L=d_(u)|0,M=d8(n)|0,b=sr(u)|0,ye=a_(n)|0,ao(X|0,v|0,w|0,T|0,L|0,M|0,b|0,ye|0,AE(n)|0,OE(n)|0);break n}case 5:{L=My(u)|0,M=Ay(u)|0,b=(Oy(u)|0)+1|0,ye=d_(u)|0,ao(X|0,L|0,M|0,b|0,ye|0,lL(u)|0,sr(u)|0,0,0,0);break n}default:break n}while(0);r=t[r>>2]|0}while((r|0)!=0)}if(e=t[e>>2]|0,!e)break e}$n()}while(0);Is(),y=Te}function eL(){return 11703}function tL(e){e=e|0,h[e+40>>0]=0}function nL(e){return e=e|0,(h[e+40>>0]|0)!=0|0}function rL(e,n){return e=e|0,n=n|0,n=sL(n)|0,e=t[n>>2]|0,t[n>>2]=t[e>>2],Et(e),t[n>>2]|0}function iL(e){e=e|0,h[e+40>>0]=1}function c8(e){return e=e|0,t[e+20>>2]|0}function uL(e){return e=e|0,t[e+8>>2]|0}function oL(e){return e=e|0,t[e+32>>2]|0}function d_(e){return e=e|0,t[e+4>>2]|0}function d8(e){return e=e|0,t[e+4>>2]|0}function AE(e){return e=e|0,t[e+8>>2]|0}function OE(e){return e=e|0,t[e+16>>2]|0}function lL(e){return e=e|0,t[e+20>>2]|0}function sL(e){return e=e|0,t[e>>2]|0}function p_(e){e=e|0;var n=0,r=0,u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0,b=0,X=0,Be=0,Te=0,ye=0,Ze=0,Ye=0,ct=0,ke=0,Ie=0,Zt=0;Zt=y,y=y+16|0,X=Zt;do if(e>>>0<245){if(L=e>>>0<11?16:e+11&-8,e=L>>>3,b=t[2783]|0,r=b>>>e,r&3|0)return n=(r&1^1)+e|0,e=11172+(n<<1<<2)|0,r=e+8|0,u=t[r>>2]|0,s=u+8|0,a=t[s>>2]|0,(e|0)==(a|0)?t[2783]=b&~(1<>2]=e,t[r>>2]=a),Ie=n<<3,t[u+4>>2]=Ie|3,Ie=u+Ie+4|0,t[Ie>>2]=t[Ie>>2]|1,Ie=s,y=Zt,Ie|0;if(M=t[2785]|0,L>>>0>M>>>0){if(r|0)return n=2<>>12&16,n=n>>>v,r=n>>>5&8,n=n>>>r,s=n>>>2&4,n=n>>>s,e=n>>>1&2,n=n>>>e,u=n>>>1&1,u=(r|v|s|e|u)+(n>>>u)|0,n=11172+(u<<1<<2)|0,e=n+8|0,s=t[e>>2]|0,v=s+8|0,r=t[v>>2]|0,(n|0)==(r|0)?(e=b&~(1<>2]=n,t[e>>2]=r,e=b),a=(u<<3)-L|0,t[s+4>>2]=L|3,u=s+L|0,t[u+4>>2]=a|1,t[u+a>>2]=a,M|0&&(s=t[2788]|0,n=M>>>3,r=11172+(n<<1<<2)|0,n=1<>2]|0):(t[2783]=e|n,n=r,e=r+8|0),t[e>>2]=s,t[n+12>>2]=s,t[s+8>>2]=n,t[s+12>>2]=r),t[2785]=a,t[2788]=u,Ie=v,y=Zt,Ie|0;if(w=t[2784]|0,w){if(r=(w&0-w)+-1|0,v=r>>>12&16,r=r>>>v,a=r>>>5&8,r=r>>>a,T=r>>>2&4,r=r>>>T,u=r>>>1&2,r=r>>>u,e=r>>>1&1,e=t[11436+((a|v|T|u|e)+(r>>>e)<<2)>>2]|0,r=(t[e+4>>2]&-8)-L|0,u=t[e+16+(((t[e+16>>2]|0)==0&1)<<2)>>2]|0,!u)T=e,a=r;else{do v=(t[u+4>>2]&-8)-L|0,T=v>>>0>>0,r=T?v:r,e=T?u:e,u=t[u+16+(((t[u+16>>2]|0)==0&1)<<2)>>2]|0;while((u|0)!=0);T=e,a=r}if(v=T+L|0,T>>>0>>0){s=t[T+24>>2]|0,n=t[T+12>>2]|0;do if((n|0)==(T|0)){if(e=T+20|0,n=t[e>>2]|0,!n&&(e=T+16|0,n=t[e>>2]|0,!n)){r=0;break}for(;;){if(r=n+20|0,u=t[r>>2]|0,u|0){n=u,e=r;continue}if(r=n+16|0,u=t[r>>2]|0,u)n=u,e=r;else break}t[e>>2]=0,r=n}else r=t[T+8>>2]|0,t[r+12>>2]=n,t[n+8>>2]=r,r=n;while(0);do if(s|0){if(n=t[T+28>>2]|0,e=11436+(n<<2)|0,(T|0)==(t[e>>2]|0)){if(t[e>>2]=r,!r){t[2784]=w&~(1<>2]|0)!=(T|0)&1)<<2)>>2]=r,!r)break;t[r+24>>2]=s,n=t[T+16>>2]|0,n|0&&(t[r+16>>2]=n,t[n+24>>2]=r),n=t[T+20>>2]|0,n|0&&(t[r+20>>2]=n,t[n+24>>2]=r)}while(0);return a>>>0<16?(Ie=a+L|0,t[T+4>>2]=Ie|3,Ie=T+Ie+4|0,t[Ie>>2]=t[Ie>>2]|1):(t[T+4>>2]=L|3,t[v+4>>2]=a|1,t[v+a>>2]=a,M|0&&(u=t[2788]|0,n=M>>>3,r=11172+(n<<1<<2)|0,n=1<>2]|0):(t[2783]=b|n,n=r,e=r+8|0),t[e>>2]=u,t[n+12>>2]=u,t[u+8>>2]=n,t[u+12>>2]=r),t[2785]=a,t[2788]=v),Ie=T+8|0,y=Zt,Ie|0}else b=L}else b=L}else b=L}else if(e>>>0<=4294967231)if(e=e+11|0,L=e&-8,T=t[2784]|0,T){u=0-L|0,e=e>>>8,e?L>>>0>16777215?w=31:(b=(e+1048320|0)>>>16&8,ke=e<>>16&4,ke=ke<>>16&2,w=14-(M|b|w)+(ke<>>15)|0,w=L>>>(w+7|0)&1|w<<1):w=0,r=t[11436+(w<<2)>>2]|0;e:do if(!r)r=0,e=0,ke=57;else for(e=0,v=L<<((w|0)==31?0:25-(w>>>1)|0),a=0;;){if(s=(t[r+4>>2]&-8)-L|0,s>>>0>>0)if(s)e=r,u=s;else{e=r,u=0,s=r,ke=61;break e}if(s=t[r+20>>2]|0,r=t[r+16+(v>>>31<<2)>>2]|0,a=(s|0)==0|(s|0)==(r|0)?a:s,s=(r|0)==0,s){r=a,ke=57;break}else v=v<<((s^1)&1)}while(0);if((ke|0)==57){if((r|0)==0&(e|0)==0){if(e=2<>>12&16,b=b>>>v,a=b>>>5&8,b=b>>>a,w=b>>>2&4,b=b>>>w,M=b>>>1&2,b=b>>>M,r=b>>>1&1,e=0,r=t[11436+((a|v|w|M|r)+(b>>>r)<<2)>>2]|0}r?(s=r,ke=61):(w=e,v=u)}if((ke|0)==61)for(;;)if(ke=0,r=(t[s+4>>2]&-8)-L|0,b=r>>>0>>0,r=b?r:u,e=b?s:e,s=t[s+16+(((t[s+16>>2]|0)==0&1)<<2)>>2]|0,s)u=r,ke=61;else{w=e,v=r;break}if((w|0)!=0&&v>>>0<((t[2785]|0)-L|0)>>>0){if(a=w+L|0,w>>>0>=a>>>0)return Ie=0,y=Zt,Ie|0;s=t[w+24>>2]|0,n=t[w+12>>2]|0;do if((n|0)==(w|0)){if(e=w+20|0,n=t[e>>2]|0,!n&&(e=w+16|0,n=t[e>>2]|0,!n)){n=0;break}for(;;){if(r=n+20|0,u=t[r>>2]|0,u|0){n=u,e=r;continue}if(r=n+16|0,u=t[r>>2]|0,u)n=u,e=r;else break}t[e>>2]=0}else Ie=t[w+8>>2]|0,t[Ie+12>>2]=n,t[n+8>>2]=Ie;while(0);do if(s){if(e=t[w+28>>2]|0,r=11436+(e<<2)|0,(w|0)==(t[r>>2]|0)){if(t[r>>2]=n,!n){u=T&~(1<>2]|0)!=(w|0)&1)<<2)>>2]=n,!n){u=T;break}t[n+24>>2]=s,e=t[w+16>>2]|0,e|0&&(t[n+16>>2]=e,t[e+24>>2]=n),e=t[w+20>>2]|0,e&&(t[n+20>>2]=e,t[e+24>>2]=n),u=T}else u=T;while(0);do if(v>>>0>=16){if(t[w+4>>2]=L|3,t[a+4>>2]=v|1,t[a+v>>2]=v,n=v>>>3,v>>>0<256){r=11172+(n<<1<<2)|0,e=t[2783]|0,n=1<>2]|0):(t[2783]=e|n,n=r,e=r+8|0),t[e>>2]=a,t[n+12>>2]=a,t[a+8>>2]=n,t[a+12>>2]=r;break}if(n=v>>>8,n?v>>>0>16777215?n=31:(ke=(n+1048320|0)>>>16&8,Ie=n<>>16&4,Ie=Ie<>>16&2,n=14-(ct|ke|n)+(Ie<>>15)|0,n=v>>>(n+7|0)&1|n<<1):n=0,r=11436+(n<<2)|0,t[a+28>>2]=n,e=a+16|0,t[e+4>>2]=0,t[e>>2]=0,e=1<>2]=a,t[a+24>>2]=r,t[a+12>>2]=a,t[a+8>>2]=a;break}for(e=v<<((n|0)==31?0:25-(n>>>1)|0),r=t[r>>2]|0;;){if((t[r+4>>2]&-8|0)==(v|0)){ke=97;break}if(u=r+16+(e>>>31<<2)|0,n=t[u>>2]|0,n)e=e<<1,r=n;else{ke=96;break}}if((ke|0)==96){t[u>>2]=a,t[a+24>>2]=r,t[a+12>>2]=a,t[a+8>>2]=a;break}else if((ke|0)==97){ke=r+8|0,Ie=t[ke>>2]|0,t[Ie+12>>2]=a,t[ke>>2]=a,t[a+8>>2]=Ie,t[a+12>>2]=r,t[a+24>>2]=0;break}}else Ie=v+L|0,t[w+4>>2]=Ie|3,Ie=w+Ie+4|0,t[Ie>>2]=t[Ie>>2]|1;while(0);return Ie=w+8|0,y=Zt,Ie|0}else b=L}else b=L;else b=-1;while(0);if(r=t[2785]|0,r>>>0>=b>>>0)return n=r-b|0,e=t[2788]|0,n>>>0>15?(Ie=e+b|0,t[2788]=Ie,t[2785]=n,t[Ie+4>>2]=n|1,t[Ie+n>>2]=n,t[e+4>>2]=b|3):(t[2785]=0,t[2788]=0,t[e+4>>2]=r|3,Ie=e+r+4|0,t[Ie>>2]=t[Ie>>2]|1),Ie=e+8|0,y=Zt,Ie|0;if(v=t[2786]|0,v>>>0>b>>>0)return ct=v-b|0,t[2786]=ct,Ie=t[2789]|0,ke=Ie+b|0,t[2789]=ke,t[ke+4>>2]=ct|1,t[Ie+4>>2]=b|3,Ie=Ie+8|0,y=Zt,Ie|0;if(t[2901]|0?e=t[2903]|0:(t[2903]=4096,t[2902]=4096,t[2904]=-1,t[2905]=-1,t[2906]=0,t[2894]=0,e=X&-16^1431655768,t[X>>2]=e,t[2901]=e,e=4096),w=b+48|0,T=b+47|0,a=e+T|0,s=0-e|0,L=a&s,L>>>0<=b>>>0||(e=t[2893]|0,e|0&&(M=t[2891]|0,X=M+L|0,X>>>0<=M>>>0|X>>>0>e>>>0)))return Ie=0,y=Zt,Ie|0;e:do if(t[2894]&4)n=0,ke=133;else{r=t[2789]|0;t:do if(r){for(u=11580;e=t[u>>2]|0,!(e>>>0<=r>>>0&&(ye=u+4|0,(e+(t[ye>>2]|0)|0)>>>0>r>>>0));)if(e=t[u+8>>2]|0,e)u=e;else{ke=118;break t}if(n=a-v&s,n>>>0<2147483647)if(e=e2(n|0)|0,(e|0)==((t[u>>2]|0)+(t[ye>>2]|0)|0)){if((e|0)!=-1){v=n,a=e,ke=135;break e}}else u=e,ke=126;else n=0}else ke=118;while(0);do if((ke|0)==118)if(r=e2(0)|0,(r|0)!=-1&&(n=r,Be=t[2902]|0,Te=Be+-1|0,n=((Te&n|0)==0?0:(Te+n&0-Be)-n|0)+L|0,Be=t[2891]|0,Te=n+Be|0,n>>>0>b>>>0&n>>>0<2147483647)){if(ye=t[2893]|0,ye|0&&Te>>>0<=Be>>>0|Te>>>0>ye>>>0){n=0;break}if(e=e2(n|0)|0,(e|0)==(r|0)){v=n,a=r,ke=135;break e}else u=e,ke=126}else n=0;while(0);do if((ke|0)==126){if(r=0-n|0,!(w>>>0>n>>>0&(n>>>0<2147483647&(u|0)!=-1)))if((u|0)==-1){n=0;break}else{v=n,a=u,ke=135;break e}if(e=t[2903]|0,e=T-n+e&0-e,e>>>0>=2147483647){v=n,a=u,ke=135;break e}if((e2(e|0)|0)==-1){e2(r|0)|0,n=0;break}else{v=e+n|0,a=u,ke=135;break e}}while(0);t[2894]=t[2894]|4,ke=133}while(0);if((ke|0)==133&&L>>>0<2147483647&&(ct=e2(L|0)|0,ye=e2(0)|0,Ze=ye-ct|0,Ye=Ze>>>0>(b+40|0)>>>0,!((ct|0)==-1|Ye^1|ct>>>0>>0&((ct|0)!=-1&(ye|0)!=-1)^1))&&(v=Ye?Ze:n,a=ct,ke=135),(ke|0)==135){n=(t[2891]|0)+v|0,t[2891]=n,n>>>0>(t[2892]|0)>>>0&&(t[2892]=n),T=t[2789]|0;do if(T){for(n=11580;;){if(e=t[n>>2]|0,r=n+4|0,u=t[r>>2]|0,(a|0)==(e+u|0)){ke=145;break}if(s=t[n+8>>2]|0,s)n=s;else break}if((ke|0)==145&&(t[n+12>>2]&8|0)==0&&T>>>0>>0&T>>>0>=e>>>0){t[r>>2]=u+v,Ie=T+8|0,Ie=(Ie&7|0)==0?0:0-Ie&7,ke=T+Ie|0,Ie=(t[2786]|0)+(v-Ie)|0,t[2789]=ke,t[2786]=Ie,t[ke+4>>2]=Ie|1,t[ke+Ie+4>>2]=40,t[2790]=t[2905];break}for(a>>>0<(t[2787]|0)>>>0&&(t[2787]=a),r=a+v|0,n=11580;;){if((t[n>>2]|0)==(r|0)){ke=153;break}if(e=t[n+8>>2]|0,e)n=e;else break}if((ke|0)==153&&(t[n+12>>2]&8|0)==0){t[n>>2]=a,M=n+4|0,t[M>>2]=(t[M>>2]|0)+v,M=a+8|0,M=a+((M&7|0)==0?0:0-M&7)|0,n=r+8|0,n=r+((n&7|0)==0?0:0-n&7)|0,L=M+b|0,w=n-M-b|0,t[M+4>>2]=b|3;do if((n|0)!=(T|0)){if((n|0)==(t[2788]|0)){Ie=(t[2785]|0)+w|0,t[2785]=Ie,t[2788]=L,t[L+4>>2]=Ie|1,t[L+Ie>>2]=Ie;break}if(e=t[n+4>>2]|0,(e&3|0)==1){v=e&-8,u=e>>>3;e:do if(e>>>0<256)if(e=t[n+8>>2]|0,r=t[n+12>>2]|0,(r|0)==(e|0)){t[2783]=t[2783]&~(1<>2]=r,t[r+8>>2]=e;break}else{a=t[n+24>>2]|0,e=t[n+12>>2]|0;do if((e|0)==(n|0)){if(u=n+16|0,r=u+4|0,e=t[r>>2]|0,!e)if(e=t[u>>2]|0,e)r=u;else{e=0;break}for(;;){if(u=e+20|0,s=t[u>>2]|0,s|0){e=s,r=u;continue}if(u=e+16|0,s=t[u>>2]|0,s)e=s,r=u;else break}t[r>>2]=0}else Ie=t[n+8>>2]|0,t[Ie+12>>2]=e,t[e+8>>2]=Ie;while(0);if(!a)break;r=t[n+28>>2]|0,u=11436+(r<<2)|0;do if((n|0)!=(t[u>>2]|0)){if(t[a+16+(((t[a+16>>2]|0)!=(n|0)&1)<<2)>>2]=e,!e)break e}else{if(t[u>>2]=e,e|0)break;t[2784]=t[2784]&~(1<>2]=a,r=n+16|0,u=t[r>>2]|0,u|0&&(t[e+16>>2]=u,t[u+24>>2]=e),r=t[r+4>>2]|0,!r)break;t[e+20>>2]=r,t[r+24>>2]=e}while(0);n=n+v|0,s=v+w|0}else s=w;if(n=n+4|0,t[n>>2]=t[n>>2]&-2,t[L+4>>2]=s|1,t[L+s>>2]=s,n=s>>>3,s>>>0<256){r=11172+(n<<1<<2)|0,e=t[2783]|0,n=1<>2]|0):(t[2783]=e|n,n=r,e=r+8|0),t[e>>2]=L,t[n+12>>2]=L,t[L+8>>2]=n,t[L+12>>2]=r;break}n=s>>>8;do if(!n)n=0;else{if(s>>>0>16777215){n=31;break}ke=(n+1048320|0)>>>16&8,Ie=n<>>16&4,Ie=Ie<>>16&2,n=14-(ct|ke|n)+(Ie<>>15)|0,n=s>>>(n+7|0)&1|n<<1}while(0);if(u=11436+(n<<2)|0,t[L+28>>2]=n,e=L+16|0,t[e+4>>2]=0,t[e>>2]=0,e=t[2784]|0,r=1<>2]=L,t[L+24>>2]=u,t[L+12>>2]=L,t[L+8>>2]=L;break}for(e=s<<((n|0)==31?0:25-(n>>>1)|0),r=t[u>>2]|0;;){if((t[r+4>>2]&-8|0)==(s|0)){ke=194;break}if(u=r+16+(e>>>31<<2)|0,n=t[u>>2]|0,n)e=e<<1,r=n;else{ke=193;break}}if((ke|0)==193){t[u>>2]=L,t[L+24>>2]=r,t[L+12>>2]=L,t[L+8>>2]=L;break}else if((ke|0)==194){ke=r+8|0,Ie=t[ke>>2]|0,t[Ie+12>>2]=L,t[ke>>2]=L,t[L+8>>2]=Ie,t[L+12>>2]=r,t[L+24>>2]=0;break}}else Ie=(t[2786]|0)+w|0,t[2786]=Ie,t[2789]=L,t[L+4>>2]=Ie|1;while(0);return Ie=M+8|0,y=Zt,Ie|0}for(n=11580;e=t[n>>2]|0,!(e>>>0<=T>>>0&&(Ie=e+(t[n+4>>2]|0)|0,Ie>>>0>T>>>0));)n=t[n+8>>2]|0;s=Ie+-47|0,e=s+8|0,e=s+((e&7|0)==0?0:0-e&7)|0,s=T+16|0,e=e>>>0>>0?T:e,n=e+8|0,r=a+8|0,r=(r&7|0)==0?0:0-r&7,ke=a+r|0,r=v+-40-r|0,t[2789]=ke,t[2786]=r,t[ke+4>>2]=r|1,t[ke+r+4>>2]=40,t[2790]=t[2905],r=e+4|0,t[r>>2]=27,t[n>>2]=t[2895],t[n+4>>2]=t[2896],t[n+8>>2]=t[2897],t[n+12>>2]=t[2898],t[2895]=a,t[2896]=v,t[2898]=0,t[2897]=n,n=e+24|0;do ke=n,n=n+4|0,t[n>>2]=7;while((ke+8|0)>>>0>>0);if((e|0)!=(T|0)){if(a=e-T|0,t[r>>2]=t[r>>2]&-2,t[T+4>>2]=a|1,t[e>>2]=a,n=a>>>3,a>>>0<256){r=11172+(n<<1<<2)|0,e=t[2783]|0,n=1<>2]|0):(t[2783]=e|n,n=r,e=r+8|0),t[e>>2]=T,t[n+12>>2]=T,t[T+8>>2]=n,t[T+12>>2]=r;break}if(n=a>>>8,n?a>>>0>16777215?r=31:(ke=(n+1048320|0)>>>16&8,Ie=n<>>16&4,Ie=Ie<>>16&2,r=14-(ct|ke|r)+(Ie<>>15)|0,r=a>>>(r+7|0)&1|r<<1):r=0,u=11436+(r<<2)|0,t[T+28>>2]=r,t[T+20>>2]=0,t[s>>2]=0,n=t[2784]|0,e=1<>2]=T,t[T+24>>2]=u,t[T+12>>2]=T,t[T+8>>2]=T;break}for(e=a<<((r|0)==31?0:25-(r>>>1)|0),r=t[u>>2]|0;;){if((t[r+4>>2]&-8|0)==(a|0)){ke=216;break}if(u=r+16+(e>>>31<<2)|0,n=t[u>>2]|0,n)e=e<<1,r=n;else{ke=215;break}}if((ke|0)==215){t[u>>2]=T,t[T+24>>2]=r,t[T+12>>2]=T,t[T+8>>2]=T;break}else if((ke|0)==216){ke=r+8|0,Ie=t[ke>>2]|0,t[Ie+12>>2]=T,t[ke>>2]=T,t[T+8>>2]=Ie,t[T+12>>2]=r,t[T+24>>2]=0;break}}}else{Ie=t[2787]|0,(Ie|0)==0|a>>>0>>0&&(t[2787]=a),t[2895]=a,t[2896]=v,t[2898]=0,t[2792]=t[2901],t[2791]=-1,n=0;do Ie=11172+(n<<1<<2)|0,t[Ie+12>>2]=Ie,t[Ie+8>>2]=Ie,n=n+1|0;while((n|0)!=32);Ie=a+8|0,Ie=(Ie&7|0)==0?0:0-Ie&7,ke=a+Ie|0,Ie=v+-40-Ie|0,t[2789]=ke,t[2786]=Ie,t[ke+4>>2]=Ie|1,t[ke+Ie+4>>2]=40,t[2790]=t[2905]}while(0);if(n=t[2786]|0,n>>>0>b>>>0)return ct=n-b|0,t[2786]=ct,Ie=t[2789]|0,ke=Ie+b|0,t[2789]=ke,t[ke+4>>2]=ct|1,t[Ie+4>>2]=b|3,Ie=Ie+8|0,y=Zt,Ie|0}return t[(bv()|0)>>2]=12,Ie=0,y=Zt,Ie|0}function h_(e){e=e|0;var n=0,r=0,u=0,s=0,a=0,v=0,w=0,T=0;if(!!e){r=e+-8|0,s=t[2787]|0,e=t[e+-4>>2]|0,n=e&-8,T=r+n|0;do if(e&1)w=r,v=r;else{if(u=t[r>>2]|0,!(e&3)||(v=r+(0-u)|0,a=u+n|0,v>>>0>>0))return;if((v|0)==(t[2788]|0)){if(e=T+4|0,n=t[e>>2]|0,(n&3|0)!=3){w=v,n=a;break}t[2785]=a,t[e>>2]=n&-2,t[v+4>>2]=a|1,t[v+a>>2]=a;return}if(r=u>>>3,u>>>0<256)if(e=t[v+8>>2]|0,n=t[v+12>>2]|0,(n|0)==(e|0)){t[2783]=t[2783]&~(1<>2]=n,t[n+8>>2]=e,w=v,n=a;break}s=t[v+24>>2]|0,e=t[v+12>>2]|0;do if((e|0)==(v|0)){if(r=v+16|0,n=r+4|0,e=t[n>>2]|0,!e)if(e=t[r>>2]|0,e)n=r;else{e=0;break}for(;;){if(r=e+20|0,u=t[r>>2]|0,u|0){e=u,n=r;continue}if(r=e+16|0,u=t[r>>2]|0,u)e=u,n=r;else break}t[n>>2]=0}else w=t[v+8>>2]|0,t[w+12>>2]=e,t[e+8>>2]=w;while(0);if(s){if(n=t[v+28>>2]|0,r=11436+(n<<2)|0,(v|0)==(t[r>>2]|0)){if(t[r>>2]=e,!e){t[2784]=t[2784]&~(1<>2]|0)!=(v|0)&1)<<2)>>2]=e,!e){w=v,n=a;break}t[e+24>>2]=s,n=v+16|0,r=t[n>>2]|0,r|0&&(t[e+16>>2]=r,t[r+24>>2]=e),n=t[n+4>>2]|0,n?(t[e+20>>2]=n,t[n+24>>2]=e,w=v,n=a):(w=v,n=a)}else w=v,n=a}while(0);if(!(v>>>0>=T>>>0)&&(e=T+4|0,u=t[e>>2]|0,!!(u&1))){if(u&2)t[e>>2]=u&-2,t[w+4>>2]=n|1,t[v+n>>2]=n,s=n;else{if(e=t[2788]|0,(T|0)==(t[2789]|0)){if(T=(t[2786]|0)+n|0,t[2786]=T,t[2789]=w,t[w+4>>2]=T|1,(w|0)!=(e|0))return;t[2788]=0,t[2785]=0;return}if((T|0)==(e|0)){T=(t[2785]|0)+n|0,t[2785]=T,t[2788]=v,t[w+4>>2]=T|1,t[v+T>>2]=T;return}s=(u&-8)+n|0,r=u>>>3;do if(u>>>0<256)if(n=t[T+8>>2]|0,e=t[T+12>>2]|0,(e|0)==(n|0)){t[2783]=t[2783]&~(1<>2]=e,t[e+8>>2]=n;break}else{a=t[T+24>>2]|0,e=t[T+12>>2]|0;do if((e|0)==(T|0)){if(r=T+16|0,n=r+4|0,e=t[n>>2]|0,!e)if(e=t[r>>2]|0,e)n=r;else{r=0;break}for(;;){if(r=e+20|0,u=t[r>>2]|0,u|0){e=u,n=r;continue}if(r=e+16|0,u=t[r>>2]|0,u)e=u,n=r;else break}t[n>>2]=0,r=e}else r=t[T+8>>2]|0,t[r+12>>2]=e,t[e+8>>2]=r,r=e;while(0);if(a|0){if(e=t[T+28>>2]|0,n=11436+(e<<2)|0,(T|0)==(t[n>>2]|0)){if(t[n>>2]=r,!r){t[2784]=t[2784]&~(1<>2]|0)!=(T|0)&1)<<2)>>2]=r,!r)break;t[r+24>>2]=a,e=T+16|0,n=t[e>>2]|0,n|0&&(t[r+16>>2]=n,t[n+24>>2]=r),e=t[e+4>>2]|0,e|0&&(t[r+20>>2]=e,t[e+24>>2]=r)}}while(0);if(t[w+4>>2]=s|1,t[v+s>>2]=s,(w|0)==(t[2788]|0)){t[2785]=s;return}}if(e=s>>>3,s>>>0<256){r=11172+(e<<1<<2)|0,n=t[2783]|0,e=1<>2]|0):(t[2783]=n|e,e=r,n=r+8|0),t[n>>2]=w,t[e+12>>2]=w,t[w+8>>2]=e,t[w+12>>2]=r;return}e=s>>>8,e?s>>>0>16777215?e=31:(v=(e+1048320|0)>>>16&8,T=e<>>16&4,T=T<>>16&2,e=14-(a|v|e)+(T<>>15)|0,e=s>>>(e+7|0)&1|e<<1):e=0,u=11436+(e<<2)|0,t[w+28>>2]=e,t[w+20>>2]=0,t[w+16>>2]=0,n=t[2784]|0,r=1<>>1)|0),r=t[u>>2]|0;;){if((t[r+4>>2]&-8|0)==(s|0)){e=73;break}if(u=r+16+(n>>>31<<2)|0,e=t[u>>2]|0,e)n=n<<1,r=e;else{e=72;break}}if((e|0)==72){t[u>>2]=w,t[w+24>>2]=r,t[w+12>>2]=w,t[w+8>>2]=w;break}else if((e|0)==73){v=r+8|0,T=t[v>>2]|0,t[T+12>>2]=w,t[v>>2]=w,t[w+8>>2]=T,t[w+12>>2]=r,t[w+24>>2]=0;break}}else t[2784]=n|r,t[u>>2]=w,t[w+24>>2]=u,t[w+12>>2]=w,t[w+8>>2]=w;while(0);if(T=(t[2791]|0)+-1|0,t[2791]=T,!T)e=11588;else return;for(;e=t[e>>2]|0,e;)e=e+8|0;t[2791]=-1}}}function aL(){return 11628}function fL(e){e=e|0;var n=0,r=0;return n=y,y=y+16|0,r=n,t[r>>2]=pL(t[e+60>>2]|0)|0,e=v_(Au(6,r|0)|0)|0,y=n,e|0}function p8(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0,b=0,X=0,Be=0;b=y,y=y+48|0,L=b+16|0,a=b,s=b+32|0,w=e+28|0,u=t[w>>2]|0,t[s>>2]=u,T=e+20|0,u=(t[T>>2]|0)-u|0,t[s+4>>2]=u,t[s+8>>2]=n,t[s+12>>2]=r,u=u+r|0,v=e+60|0,t[a>>2]=t[v>>2],t[a+4>>2]=s,t[a+8>>2]=2,a=v_(h0(146,a|0)|0)|0;e:do if((u|0)!=(a|0)){for(n=2;!((a|0)<0);)if(u=u-a|0,Be=t[s+4>>2]|0,X=a>>>0>Be>>>0,s=X?s+8|0:s,n=(X<<31>>31)+n|0,Be=a-(X?Be:0)|0,t[s>>2]=(t[s>>2]|0)+Be,X=s+4|0,t[X>>2]=(t[X>>2]|0)-Be,t[L>>2]=t[v>>2],t[L+4>>2]=s,t[L+8>>2]=n,a=v_(h0(146,L|0)|0)|0,(u|0)==(a|0)){M=3;break e}t[e+16>>2]=0,t[w>>2]=0,t[T>>2]=0,t[e>>2]=t[e>>2]|32,(n|0)==2?r=0:r=r-(t[s+4>>2]|0)|0}else M=3;while(0);return(M|0)==3&&(Be=t[e+44>>2]|0,t[e+16>>2]=Be+(t[e+48>>2]|0),t[w>>2]=Be,t[T>>2]=Be),y=b,r|0}function cL(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0;return s=y,y=y+32|0,a=s,u=s+20|0,t[a>>2]=t[e+60>>2],t[a+4>>2]=0,t[a+8>>2]=n,t[a+12>>2]=u,t[a+16>>2]=r,(v_(Ni(140,a|0)|0)|0)<0?(t[u>>2]=-1,e=-1):e=t[u>>2]|0,y=s,e|0}function v_(e){return e=e|0,e>>>0>4294963200&&(t[(bv()|0)>>2]=0-e,e=-1),e|0}function bv(){return(dL()|0)+64|0}function dL(){return ME()|0}function ME(){return 2084}function pL(e){return e=e|0,e|0}function hL(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0;return s=y,y=y+32|0,u=s,t[e+36>>2]=1,(t[e>>2]&64|0)==0&&(t[u>>2]=t[e+60>>2],t[u+4>>2]=21523,t[u+8>>2]=s+16,I0(54,u|0)|0)&&(h[e+75>>0]=-1),u=p8(e,n,r)|0,y=s,u|0}function h8(e,n){e=e|0,n=n|0;var r=0,u=0;if(r=h[e>>0]|0,u=h[n>>0]|0,r<<24>>24==0||r<<24>>24!=u<<24>>24)e=u;else{do e=e+1|0,n=n+1|0,r=h[e>>0]|0,u=h[n>>0]|0;while(!(r<<24>>24==0||r<<24>>24!=u<<24>>24));e=u}return(r&255)-(e&255)|0}function vL(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0;e:do if(!r)e=0;else{for(;u=h[e>>0]|0,s=h[n>>0]|0,u<<24>>24==s<<24>>24;)if(r=r+-1|0,r)e=e+1|0,n=n+1|0;else{e=0;break e}e=(u&255)-(s&255)|0}while(0);return e|0}function v8(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0,b=0,X=0,Be=0,Te=0,ye=0;ye=y,y=y+224|0,M=ye+120|0,b=ye+80|0,Be=ye,Te=ye+136|0,u=b,s=u+40|0;do t[u>>2]=0,u=u+4|0;while((u|0)<(s|0));return t[M>>2]=t[r>>2],(kE(0,n,M,Be,b)|0)<0?r=-1:((t[e+76>>2]|0)>-1?X=mL(e)|0:X=0,r=t[e>>2]|0,L=r&32,(h[e+74>>0]|0)<1&&(t[e>>2]=r&-33),u=e+48|0,t[u>>2]|0?r=kE(e,n,M,Be,b)|0:(s=e+44|0,a=t[s>>2]|0,t[s>>2]=Te,v=e+28|0,t[v>>2]=Te,w=e+20|0,t[w>>2]=Te,t[u>>2]=80,T=e+16|0,t[T>>2]=Te+80,r=kE(e,n,M,Be,b)|0,a&&(__[t[e+36>>2]&7](e,0,0)|0,r=(t[w>>2]|0)==0?-1:r,t[s>>2]=a,t[u>>2]=0,t[T>>2]=0,t[v>>2]=0,t[w>>2]=0)),u=t[e>>2]|0,t[e>>2]=u|L,X|0&&yL(e),r=(u&32|0)==0?r:-1),y=ye,r|0}function kE(e,n,r,u,s){e=e|0,n=n|0,r=r|0,u=u|0,s=s|0;var a=0,v=0,w=0,T=0,L=0,M=0,b=0,X=0,Be=0,Te=0,ye=0,Ze=0,Ye=0,ct=0,ke=0,Ie=0,Zt=0,Br=0,Pn=0,gn=0,_r=0,Pr=0,kn=0;kn=y,y=y+64|0,Pn=kn+16|0,gn=kn,Zt=kn+24|0,_r=kn+8|0,Pr=kn+20|0,t[Pn>>2]=n,ct=(e|0)!=0,ke=Zt+40|0,Ie=ke,Zt=Zt+39|0,Br=_r+4|0,v=0,a=0,M=0;e:for(;;){do if((a|0)>-1)if((v|0)>(2147483647-a|0)){t[(bv()|0)>>2]=75,a=-1;break}else{a=v+a|0;break}while(0);if(v=h[n>>0]|0,v<<24>>24)w=n;else{Ye=87;break}t:for(;;){switch(v<<24>>24){case 37:{v=w,Ye=9;break t}case 0:{v=w;break t}default:}Ze=w+1|0,t[Pn>>2]=Ze,v=h[Ze>>0]|0,w=Ze}t:do if((Ye|0)==9)for(;;){if(Ye=0,(h[w+1>>0]|0)!=37)break t;if(v=v+1|0,w=w+2|0,t[Pn>>2]=w,(h[w>>0]|0)==37)Ye=9;else break}while(0);if(v=v-n|0,ct&&Yo(e,n,v),v|0){n=w;continue}T=w+1|0,v=(h[T>>0]|0)+-48|0,v>>>0<10?(Ze=(h[w+2>>0]|0)==36,ye=Ze?v:-1,M=Ze?1:M,T=Ze?w+3|0:T):ye=-1,t[Pn>>2]=T,v=h[T>>0]|0,w=(v<<24>>24)+-32|0;t:do if(w>>>0<32)for(L=0,b=v;;){if(v=1<>2]=T,v=h[T>>0]|0,w=(v<<24>>24)+-32|0,w>>>0>=32)break;b=v}else L=0;while(0);if(v<<24>>24==42){if(w=T+1|0,v=(h[w>>0]|0)+-48|0,v>>>0<10&&(h[T+2>>0]|0)==36)t[s+(v<<2)>>2]=10,v=t[u+((h[w>>0]|0)+-48<<3)>>2]|0,M=1,T=T+3|0;else{if(M|0){a=-1;break}ct?(M=(t[r>>2]|0)+(4-1)&~(4-1),v=t[M>>2]|0,t[r>>2]=M+4,M=0,T=w):(v=0,M=0,T=w)}t[Pn>>2]=T,Ze=(v|0)<0,v=Ze?0-v|0:v,L=Ze?L|8192:L}else{if(v=m8(Pn)|0,(v|0)<0){a=-1;break}T=t[Pn>>2]|0}do if((h[T>>0]|0)==46){if((h[T+1>>0]|0)!=42){t[Pn>>2]=T+1,w=m8(Pn)|0,T=t[Pn>>2]|0;break}if(b=T+2|0,w=(h[b>>0]|0)+-48|0,w>>>0<10&&(h[T+3>>0]|0)==36){t[s+(w<<2)>>2]=10,w=t[u+((h[b>>0]|0)+-48<<3)>>2]|0,T=T+4|0,t[Pn>>2]=T;break}if(M|0){a=-1;break e}ct?(Ze=(t[r>>2]|0)+(4-1)&~(4-1),w=t[Ze>>2]|0,t[r>>2]=Ze+4):w=0,t[Pn>>2]=b,T=b}else w=-1;while(0);for(Te=0;;){if(((h[T>>0]|0)+-65|0)>>>0>57){a=-1;break e}if(Ze=T+1|0,t[Pn>>2]=Ze,b=h[(h[T>>0]|0)+-65+(5178+(Te*58|0))>>0]|0,X=b&255,(X+-1|0)>>>0<8)Te=X,T=Ze;else break}if(!(b<<24>>24)){a=-1;break}Be=(ye|0)>-1;do if(b<<24>>24==19)if(Be){a=-1;break e}else Ye=49;else{if(Be){t[s+(ye<<2)>>2]=X,Be=u+(ye<<3)|0,ye=t[Be+4>>2]|0,Ye=gn,t[Ye>>2]=t[Be>>2],t[Ye+4>>2]=ye,Ye=49;break}if(!ct){a=0;break e}y8(gn,X,r)}while(0);if((Ye|0)==49&&(Ye=0,!ct)){v=0,n=Ze;continue}T=h[T>>0]|0,T=(Te|0)!=0&(T&15|0)==3?T&-33:T,Be=L&-65537,ye=(L&8192|0)==0?L:Be;t:do switch(T|0){case 110:switch((Te&255)<<24>>24){case 0:{t[t[gn>>2]>>2]=a,v=0,n=Ze;continue e}case 1:{t[t[gn>>2]>>2]=a,v=0,n=Ze;continue e}case 2:{v=t[gn>>2]|0,t[v>>2]=a,t[v+4>>2]=((a|0)<0)<<31>>31,v=0,n=Ze;continue e}case 3:{E[t[gn>>2]>>1]=a,v=0,n=Ze;continue e}case 4:{h[t[gn>>2]>>0]=a,v=0,n=Ze;continue e}case 6:{t[t[gn>>2]>>2]=a,v=0,n=Ze;continue e}case 7:{v=t[gn>>2]|0,t[v>>2]=a,t[v+4>>2]=((a|0)<0)<<31>>31,v=0,n=Ze;continue e}default:{v=0,n=Ze;continue e}}case 112:{T=120,w=w>>>0>8?w:8,n=ye|8,Ye=61;break}case 88:case 120:{n=ye,Ye=61;break}case 111:{T=gn,n=t[T>>2]|0,T=t[T+4>>2]|0,X=_L(n,T,ke)|0,Be=Ie-X|0,L=0,b=5642,w=(ye&8|0)==0|(w|0)>(Be|0)?w:Be+1|0,Be=ye,Ye=67;break}case 105:case 100:if(T=gn,n=t[T>>2]|0,T=t[T+4>>2]|0,(T|0)<0){n=m_(0,0,n|0,T|0)|0,T=ot,L=gn,t[L>>2]=n,t[L+4>>2]=T,L=1,b=5642,Ye=66;break t}else{L=(ye&2049|0)!=0&1,b=(ye&2048|0)==0?(ye&1|0)==0?5642:5644:5643,Ye=66;break t}case 117:{T=gn,L=0,b=5642,n=t[T>>2]|0,T=t[T+4>>2]|0,Ye=66;break}case 99:{h[Zt>>0]=t[gn>>2],n=Zt,L=0,b=5642,X=ke,T=1,w=Be;break}case 109:{T=EL(t[(bv()|0)>>2]|0)|0,Ye=71;break}case 115:{T=t[gn>>2]|0,T=T|0?T:5652,Ye=71;break}case 67:{t[_r>>2]=t[gn>>2],t[Br>>2]=0,t[gn>>2]=_r,X=-1,T=_r,Ye=75;break}case 83:{n=t[gn>>2]|0,w?(X=w,T=n,Ye=75):(_l(e,32,v,0,ye),n=0,Ye=84);break}case 65:case 71:case 70:case 69:case 97:case 103:case 102:case 101:{v=wL(e,+j[gn>>3],v,w,ye,T)|0,n=Ze;continue e}default:L=0,b=5642,X=ke,T=w,w=ye}while(0);t:do if((Ye|0)==61)ye=gn,Te=t[ye>>2]|0,ye=t[ye+4>>2]|0,X=gL(Te,ye,ke,T&32)|0,b=(n&8|0)==0|(Te|0)==0&(ye|0)==0,L=b?0:2,b=b?5642:5642+(T>>4)|0,Be=n,n=Te,T=ye,Ye=67;else if((Ye|0)==66)X=Bv(n,T,ke)|0,Be=ye,Ye=67;else if((Ye|0)==71)Ye=0,ye=DL(T,0,w)|0,Te=(ye|0)==0,n=T,L=0,b=5642,X=Te?T+w|0:ye,T=Te?w:ye-T|0,w=Be;else if((Ye|0)==75){for(Ye=0,b=T,n=0,w=0;L=t[b>>2]|0,!(!L||(w=g8(Pr,L)|0,(w|0)<0|w>>>0>(X-n|0)>>>0));)if(n=w+n|0,X>>>0>n>>>0)b=b+4|0;else break;if((w|0)<0){a=-1;break e}if(_l(e,32,v,n,ye),!n)n=0,Ye=84;else for(L=0;;){if(w=t[T>>2]|0,!w){Ye=84;break t}if(w=g8(Pr,w)|0,L=w+L|0,(L|0)>(n|0)){Ye=84;break t}if(Yo(e,Pr,w),L>>>0>=n>>>0){Ye=84;break}else T=T+4|0}}while(0);if((Ye|0)==67)Ye=0,T=(n|0)!=0|(T|0)!=0,ye=(w|0)!=0|T,T=((T^1)&1)+(Ie-X)|0,n=ye?X:ke,X=ke,T=ye?(w|0)>(T|0)?w:T:w,w=(w|0)>-1?Be&-65537:Be;else if((Ye|0)==84){Ye=0,_l(e,32,v,n,ye^8192),v=(v|0)>(n|0)?v:n,n=Ze;continue}Te=X-n|0,Be=(T|0)<(Te|0)?Te:T,ye=Be+L|0,v=(v|0)<(ye|0)?ye:v,_l(e,32,v,ye,w),Yo(e,b,L),_l(e,48,v,ye,w^65536),_l(e,48,Be,Te,0),Yo(e,n,Te),_l(e,32,v,ye,w^8192),n=Ze}e:do if((Ye|0)==87&&!e)if(!M)a=0;else{for(a=1;n=t[s+(a<<2)>>2]|0,!!n;)if(y8(u+(a<<3)|0,n,r),a=a+1|0,(a|0)>=10){a=1;break e}for(;;){if(t[s+(a<<2)>>2]|0){a=-1;break e}if(a=a+1|0,(a|0)>=10){a=1;break}}}while(0);return y=kn,a|0}function mL(e){return e=e|0,0}function yL(e){e=e|0}function Yo(e,n,r){e=e|0,n=n|0,r=r|0,t[e>>2]&32||kL(n,r,e)|0}function m8(e){e=e|0;var n=0,r=0,u=0;if(r=t[e>>2]|0,u=(h[r>>0]|0)+-48|0,u>>>0<10){n=0;do n=u+(n*10|0)|0,r=r+1|0,t[e>>2]=r,u=(h[r>>0]|0)+-48|0;while(u>>>0<10)}else n=0;return n|0}function y8(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0;e:do if(n>>>0<=20)do switch(n|0){case 9:{u=(t[r>>2]|0)+(4-1)&~(4-1),n=t[u>>2]|0,t[r>>2]=u+4,t[e>>2]=n;break e}case 10:{u=(t[r>>2]|0)+(4-1)&~(4-1),n=t[u>>2]|0,t[r>>2]=u+4,u=e,t[u>>2]=n,t[u+4>>2]=((n|0)<0)<<31>>31;break e}case 11:{u=(t[r>>2]|0)+(4-1)&~(4-1),n=t[u>>2]|0,t[r>>2]=u+4,u=e,t[u>>2]=n,t[u+4>>2]=0;break e}case 12:{u=(t[r>>2]|0)+(8-1)&~(8-1),n=u,s=t[n>>2]|0,n=t[n+4>>2]|0,t[r>>2]=u+8,u=e,t[u>>2]=s,t[u+4>>2]=n;break e}case 13:{s=(t[r>>2]|0)+(4-1)&~(4-1),u=t[s>>2]|0,t[r>>2]=s+4,u=(u&65535)<<16>>16,s=e,t[s>>2]=u,t[s+4>>2]=((u|0)<0)<<31>>31;break e}case 14:{s=(t[r>>2]|0)+(4-1)&~(4-1),u=t[s>>2]|0,t[r>>2]=s+4,s=e,t[s>>2]=u&65535,t[s+4>>2]=0;break e}case 15:{s=(t[r>>2]|0)+(4-1)&~(4-1),u=t[s>>2]|0,t[r>>2]=s+4,u=(u&255)<<24>>24,s=e,t[s>>2]=u,t[s+4>>2]=((u|0)<0)<<31>>31;break e}case 16:{s=(t[r>>2]|0)+(4-1)&~(4-1),u=t[s>>2]|0,t[r>>2]=s+4,s=e,t[s>>2]=u&255,t[s+4>>2]=0;break e}case 17:{s=(t[r>>2]|0)+(8-1)&~(8-1),a=+j[s>>3],t[r>>2]=s+8,j[e>>3]=a;break e}case 18:{s=(t[r>>2]|0)+(8-1)&~(8-1),a=+j[s>>3],t[r>>2]=s+8,j[e>>3]=a;break e}default:break e}while(0);while(0)}function gL(e,n,r,u){if(e=e|0,n=n|0,r=r|0,u=u|0,!((e|0)==0&(n|0)==0))do r=r+-1|0,h[r>>0]=N[5694+(e&15)>>0]|0|u,e=y_(e|0,n|0,4)|0,n=ot;while(!((e|0)==0&(n|0)==0));return r|0}function _L(e,n,r){if(e=e|0,n=n|0,r=r|0,!((e|0)==0&(n|0)==0))do r=r+-1|0,h[r>>0]=e&7|48,e=y_(e|0,n|0,3)|0,n=ot;while(!((e|0)==0&(n|0)==0));return r|0}function Bv(e,n,r){e=e|0,n=n|0,r=r|0;var u=0;if(n>>>0>0|(n|0)==0&e>>>0>4294967295){for(;u=PE(e|0,n|0,10,0)|0,r=r+-1|0,h[r>>0]=u&255|48,u=e,e=FE(e|0,n|0,10,0)|0,n>>>0>9|(n|0)==9&u>>>0>4294967295;)n=ot;n=e}else n=e;if(n)for(;r=r+-1|0,h[r>>0]=(n>>>0)%10|0|48,!(n>>>0<10);)n=(n>>>0)/10|0;return r|0}function EL(e){return e=e|0,RL(e,t[(xL()|0)+188>>2]|0)|0}function DL(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0;a=n&255,u=(r|0)!=0;e:do if(u&(e&3|0)!=0)for(s=n&255;;){if((h[e>>0]|0)==s<<24>>24){v=6;break e}if(e=e+1|0,r=r+-1|0,u=(r|0)!=0,!(u&(e&3|0)!=0)){v=5;break}}else v=5;while(0);(v|0)==5&&(u?v=6:r=0);e:do if((v|0)==6&&(s=n&255,(h[e>>0]|0)!=s<<24>>24)){u=lr(a,16843009)|0;t:do if(r>>>0>3){for(;a=t[e>>2]^u,!((a&-2139062144^-2139062144)&a+-16843009|0);)if(e=e+4|0,r=r+-4|0,r>>>0<=3){v=11;break t}}else v=11;while(0);if((v|0)==11&&!r){r=0;break}for(;;){if((h[e>>0]|0)==s<<24>>24)break e;if(e=e+1|0,r=r+-1|0,!r){r=0;break}}}while(0);return(r|0?e:0)|0}function _l(e,n,r,u,s){e=e|0,n=n|0,r=r|0,u=u|0,s=s|0;var a=0,v=0;if(v=y,y=y+256|0,a=v,(r|0)>(u|0)&(s&73728|0)==0){if(s=r-u|0,jv(a|0,n|0,(s>>>0<256?s:256)|0)|0,s>>>0>255){n=r-u|0;do Yo(e,a,256),s=s+-256|0;while(s>>>0>255);s=n&255}Yo(e,a,s)}y=v}function g8(e,n){return e=e|0,n=n|0,e?e=TL(e,n,0)|0:e=0,e|0}function wL(e,n,r,u,s,a){e=e|0,n=+n,r=r|0,u=u|0,s=s|0,a=a|0;var v=0,w=0,T=0,L=0,M=0,b=0,X=0,Be=0,Te=0,ye=0,Ze=0,Ye=0,ct=0,ke=0,Ie=0,Zt=0,Br=0,Pn=0,gn=0,_r=0,Pr=0,kn=0,uu=0;uu=y,y=y+560|0,T=uu+8|0,Ze=uu,kn=uu+524|0,Pr=kn,L=uu+512|0,t[Ze>>2]=0,_r=L+12|0,_8(n)|0,(ot|0)<0?(n=-n,Pn=1,Br=5659):(Pn=(s&2049|0)!=0&1,Br=(s&2048|0)==0?(s&1|0)==0?5660:5665:5662),_8(n)|0,gn=ot&2146435072;do if(gn>>>0<2146435072|(gn|0)==2146435072&0<0){if(Be=+SL(n,Ze)*2,v=Be!=0,v&&(t[Ze>>2]=(t[Ze>>2]|0)+-1),ct=a|32,(ct|0)==97){Te=a&32,X=(Te|0)==0?Br:Br+9|0,b=Pn|2,v=12-u|0;do if(u>>>0>11|(v|0)==0)n=Be;else{n=8;do v=v+-1|0,n=n*16;while((v|0)!=0);if((h[X>>0]|0)==45){n=-(n+(-Be-n));break}else{n=Be+n-n;break}}while(0);w=t[Ze>>2]|0,v=(w|0)<0?0-w|0:w,v=Bv(v,((v|0)<0)<<31>>31,_r)|0,(v|0)==(_r|0)&&(v=L+11|0,h[v>>0]=48),h[v+-1>>0]=(w>>31&2)+43,M=v+-2|0,h[M>>0]=a+15,L=(u|0)<1,T=(s&8|0)==0,v=kn;do gn=~~n,w=v+1|0,h[v>>0]=N[5694+gn>>0]|Te,n=(n-+(gn|0))*16,(w-Pr|0)==1&&!(T&(L&n==0))?(h[w>>0]=46,v=v+2|0):v=w;while(n!=0);gn=v-Pr|0,Pr=_r-M|0,_r=(u|0)!=0&(gn+-2|0)<(u|0)?u+2|0:gn,v=Pr+b+_r|0,_l(e,32,r,v,s),Yo(e,X,b),_l(e,48,r,v,s^65536),Yo(e,kn,gn),_l(e,48,_r-gn|0,0,0),Yo(e,M,Pr),_l(e,32,r,v,s^8192);break}w=(u|0)<0?6:u,v?(v=(t[Ze>>2]|0)+-28|0,t[Ze>>2]=v,n=Be*268435456):(n=Be,v=t[Ze>>2]|0),gn=(v|0)<0?T:T+288|0,T=gn;do Ie=~~n>>>0,t[T>>2]=Ie,T=T+4|0,n=(n-+(Ie>>>0))*1e9;while(n!=0);if((v|0)>0)for(L=gn,b=T;;){if(M=(v|0)<29?v:29,v=b+-4|0,v>>>0>=L>>>0){T=0;do ke=C8(t[v>>2]|0,0,M|0)|0,ke=LE(ke|0,ot|0,T|0,0)|0,Ie=ot,Ye=PE(ke|0,Ie|0,1e9,0)|0,t[v>>2]=Ye,T=FE(ke|0,Ie|0,1e9,0)|0,v=v+-4|0;while(v>>>0>=L>>>0);T&&(L=L+-4|0,t[L>>2]=T)}for(T=b;!(T>>>0<=L>>>0);)if(v=T+-4|0,!(t[v>>2]|0))T=v;else break;if(v=(t[Ze>>2]|0)-M|0,t[Ze>>2]=v,(v|0)>0)b=T;else break}else L=gn;if((v|0)<0){u=((w+25|0)/9|0)+1|0,ye=(ct|0)==102;do{if(Te=0-v|0,Te=(Te|0)<9?Te:9,L>>>0>>0){M=(1<>>Te,X=0,v=L;do Ie=t[v>>2]|0,t[v>>2]=(Ie>>>Te)+X,X=lr(Ie&M,b)|0,v=v+4|0;while(v>>>0>>0);v=(t[L>>2]|0)==0?L+4|0:L,X?(t[T>>2]=X,L=v,v=T+4|0):(L=v,v=T)}else L=(t[L>>2]|0)==0?L+4|0:L,v=T;T=ye?gn:L,T=(v-T>>2|0)>(u|0)?T+(u<<2)|0:v,v=(t[Ze>>2]|0)+Te|0,t[Ze>>2]=v}while((v|0)<0);v=L,u=T}else v=L,u=T;if(Ie=gn,v>>>0>>0){if(T=(Ie-v>>2)*9|0,M=t[v>>2]|0,M>>>0>=10){L=10;do L=L*10|0,T=T+1|0;while(M>>>0>=L>>>0)}}else T=0;if(ye=(ct|0)==103,Ye=(w|0)!=0,L=w-((ct|0)!=102?T:0)+((Ye&ye)<<31>>31)|0,(L|0)<(((u-Ie>>2)*9|0)+-9|0)){if(L=L+9216|0,Te=gn+4+(((L|0)/9|0)+-1024<<2)|0,L=((L|0)%9|0)+1|0,(L|0)<9){M=10;do M=M*10|0,L=L+1|0;while((L|0)!=9)}else M=10;if(b=t[Te>>2]|0,X=(b>>>0)%(M>>>0)|0,L=(Te+4|0)==(u|0),L&(X|0)==0)L=Te;else if(Be=(((b>>>0)/(M>>>0)|0)&1|0)==0?9007199254740992:9007199254740994,ke=(M|0)/2|0,n=X>>>0>>0?.5:L&(X|0)==(ke|0)?1:1.5,Pn&&(ke=(h[Br>>0]|0)==45,n=ke?-n:n,Be=ke?-Be:Be),L=b-X|0,t[Te>>2]=L,Be+n!=Be){if(ke=L+M|0,t[Te>>2]=ke,ke>>>0>999999999)for(T=Te;L=T+-4|0,t[T>>2]=0,L>>>0>>0&&(v=v+-4|0,t[v>>2]=0),ke=(t[L>>2]|0)+1|0,t[L>>2]=ke,ke>>>0>999999999;)T=L;else L=Te;if(T=(Ie-v>>2)*9|0,b=t[v>>2]|0,b>>>0>=10){M=10;do M=M*10|0,T=T+1|0;while(b>>>0>=M>>>0)}}else L=Te;L=L+4|0,L=u>>>0>L>>>0?L:u,ke=v}else L=u,ke=v;for(ct=L;;){if(ct>>>0<=ke>>>0){Ze=0;break}if(v=ct+-4|0,!(t[v>>2]|0))ct=v;else{Ze=1;break}}u=0-T|0;do if(ye)if(v=((Ye^1)&1)+w|0,(v|0)>(T|0)&(T|0)>-5?(M=a+-1|0,w=v+-1-T|0):(M=a+-2|0,w=v+-1|0),v=s&8,v)Te=v;else{if(Ze&&(Zt=t[ct+-4>>2]|0,(Zt|0)!=0))if((Zt>>>0)%10|0)L=0;else{L=0,v=10;do v=v*10|0,L=L+1|0;while(!((Zt>>>0)%(v>>>0)|0|0))}else L=9;if(v=((ct-Ie>>2)*9|0)+-9|0,(M|32|0)==102){Te=v-L|0,Te=(Te|0)>0?Te:0,w=(w|0)<(Te|0)?w:Te,Te=0;break}else{Te=v+T-L|0,Te=(Te|0)>0?Te:0,w=(w|0)<(Te|0)?w:Te,Te=0;break}}else M=a,Te=s&8;while(0);if(ye=w|Te,b=(ye|0)!=0&1,X=(M|32|0)==102,X)Ye=0,v=(T|0)>0?T:0;else{if(v=(T|0)<0?u:T,v=Bv(v,((v|0)<0)<<31>>31,_r)|0,L=_r,(L-v|0)<2)do v=v+-1|0,h[v>>0]=48;while((L-v|0)<2);h[v+-1>>0]=(T>>31&2)+43,v=v+-2|0,h[v>>0]=M,Ye=v,v=L-v|0}if(v=Pn+1+w+b+v|0,_l(e,32,r,v,s),Yo(e,Br,Pn),_l(e,48,r,v,s^65536),X){M=ke>>>0>gn>>>0?gn:ke,Te=kn+9|0,b=Te,X=kn+8|0,L=M;do{if(T=Bv(t[L>>2]|0,0,Te)|0,(L|0)==(M|0))(T|0)==(Te|0)&&(h[X>>0]=48,T=X);else if(T>>>0>kn>>>0){jv(kn|0,48,T-Pr|0)|0;do T=T+-1|0;while(T>>>0>kn>>>0)}Yo(e,T,b-T|0),L=L+4|0}while(L>>>0<=gn>>>0);if(ye|0&&Yo(e,5710,1),L>>>0>>0&(w|0)>0)for(;;){if(T=Bv(t[L>>2]|0,0,Te)|0,T>>>0>kn>>>0){jv(kn|0,48,T-Pr|0)|0;do T=T+-1|0;while(T>>>0>kn>>>0)}if(Yo(e,T,(w|0)<9?w:9),L=L+4|0,T=w+-9|0,L>>>0>>0&(w|0)>9)w=T;else{w=T;break}}_l(e,48,w+9|0,9,0)}else{if(ye=Ze?ct:ke+4|0,(w|0)>-1){Ze=kn+9|0,Te=(Te|0)==0,u=Ze,b=0-Pr|0,X=kn+8|0,M=ke;do{T=Bv(t[M>>2]|0,0,Ze)|0,(T|0)==(Ze|0)&&(h[X>>0]=48,T=X);do if((M|0)==(ke|0)){if(L=T+1|0,Yo(e,T,1),Te&(w|0)<1){T=L;break}Yo(e,5710,1),T=L}else{if(T>>>0<=kn>>>0)break;jv(kn|0,48,T+b|0)|0;do T=T+-1|0;while(T>>>0>kn>>>0)}while(0);Pr=u-T|0,Yo(e,T,(w|0)>(Pr|0)?Pr:w),w=w-Pr|0,M=M+4|0}while(M>>>0>>0&(w|0)>-1)}_l(e,48,w+18|0,18,0),Yo(e,Ye,_r-Ye|0)}_l(e,32,r,v,s^8192)}else kn=(a&32|0)!=0,v=Pn+3|0,_l(e,32,r,v,s&-65537),Yo(e,Br,Pn),Yo(e,n!=n|!1?kn?5686:5690:kn?5678:5682,3),_l(e,32,r,v,s^8192);while(0);return y=uu,((v|0)<(r|0)?r:v)|0}function _8(e){e=+e;var n=0;return j[V>>3]=e,n=t[V>>2]|0,ot=t[V+4>>2]|0,n|0}function SL(e,n){return e=+e,n=n|0,+ +E8(e,n)}function E8(e,n){e=+e,n=n|0;var r=0,u=0,s=0;switch(j[V>>3]=e,r=t[V>>2]|0,u=t[V+4>>2]|0,s=y_(r|0,u|0,52)|0,s&2047){case 0:{e!=0?(e=+E8(e*18446744073709552e3,n),r=(t[n>>2]|0)+-64|0):r=0,t[n>>2]=r;break}case 2047:break;default:t[n>>2]=(s&2047)+-1022,t[V>>2]=r,t[V+4>>2]=u&-2146435073|1071644672,e=+j[V>>3]}return+e}function TL(e,n,r){e=e|0,n=n|0,r=r|0;do if(e){if(n>>>0<128){h[e>>0]=n,e=1;break}if(!(t[t[(CL()|0)+188>>2]>>2]|0))if((n&-128|0)==57216){h[e>>0]=n,e=1;break}else{t[(bv()|0)>>2]=84,e=-1;break}if(n>>>0<2048){h[e>>0]=n>>>6|192,h[e+1>>0]=n&63|128,e=2;break}if(n>>>0<55296|(n&-8192|0)==57344){h[e>>0]=n>>>12|224,h[e+1>>0]=n>>>6&63|128,h[e+2>>0]=n&63|128,e=3;break}if((n+-65536|0)>>>0<1048576){h[e>>0]=n>>>18|240,h[e+1>>0]=n>>>12&63|128,h[e+2>>0]=n>>>6&63|128,h[e+3>>0]=n&63|128,e=4;break}else{t[(bv()|0)>>2]=84,e=-1;break}}else e=1;while(0);return e|0}function CL(){return ME()|0}function xL(){return ME()|0}function RL(e,n){e=e|0,n=n|0;var r=0,u=0;for(u=0;;){if((N[5712+u>>0]|0)==(e|0)){e=2;break}if(r=u+1|0,(r|0)==87){r=5800,u=87,e=5;break}else u=r}if((e|0)==2&&(u?(r=5800,e=5):r=5800),(e|0)==5)for(;;){do e=r,r=r+1|0;while((h[e>>0]|0)!=0);if(u=u+-1|0,u)e=5;else break}return AL(r,t[n+20>>2]|0)|0}function AL(e,n){return e=e|0,n=n|0,OL(e,n)|0}function OL(e,n){return e=e|0,n=n|0,n?n=ML(t[n>>2]|0,t[n+4>>2]|0,e)|0:n=0,(n|0?n:e)|0}function ML(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0,T=0,L=0,M=0,b=0,X=0;X=(t[e>>2]|0)+1794895138|0,a=Yp(t[e+8>>2]|0,X)|0,u=Yp(t[e+12>>2]|0,X)|0,s=Yp(t[e+16>>2]|0,X)|0;e:do if(a>>>0>>2>>>0&&(b=n-(a<<2)|0,u>>>0>>0&s>>>0>>0)&&((s|u)&3|0)==0){for(b=u>>>2,M=s>>>2,L=0;;){if(w=a>>>1,T=L+w|0,v=T<<1,s=v+b|0,u=Yp(t[e+(s<<2)>>2]|0,X)|0,s=Yp(t[e+(s+1<<2)>>2]|0,X)|0,!(s>>>0>>0&u>>>0<(n-s|0)>>>0)){u=0;break e}if(h[e+(s+u)>>0]|0){u=0;break e}if(u=h8(r,e+s|0)|0,!u)break;if(u=(u|0)<0,(a|0)==1){u=0;break e}else L=u?L:T,a=u?w:a-w|0}u=v+M|0,s=Yp(t[e+(u<<2)>>2]|0,X)|0,u=Yp(t[e+(u+1<<2)>>2]|0,X)|0,u>>>0>>0&s>>>0<(n-u|0)>>>0?u=(h[e+(u+s)>>0]|0)==0?e+u|0:0:u=0}else u=0;while(0);return u|0}function Yp(e,n){e=e|0,n=n|0;var r=0;return r=A8(e|0)|0,((n|0)==0?e:r)|0}function kL(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0,w=0;u=r+16|0,s=t[u>>2]|0,s?a=5:NL(r)|0?u=0:(s=t[u>>2]|0,a=5);e:do if((a|0)==5){if(w=r+20|0,v=t[w>>2]|0,u=v,(s-v|0)>>>0>>0){u=__[t[r+36>>2]&7](r,e,n)|0;break}t:do if((h[r+75>>0]|0)>-1){for(v=n;;){if(!v){a=0,s=e;break t}if(s=v+-1|0,(h[e+s>>0]|0)==10)break;v=s}if(u=__[t[r+36>>2]&7](r,e,v)|0,u>>>0>>0)break e;a=v,s=e+v|0,n=n-v|0,u=t[w>>2]|0}else a=0,s=e;while(0);gr(u|0,s|0,n|0)|0,t[w>>2]=(t[w>>2]|0)+n,u=a+n|0}while(0);return u|0}function NL(e){e=e|0;var n=0,r=0;return n=e+74|0,r=h[n>>0]|0,h[n>>0]=r+255|r,n=t[e>>2]|0,n&8?(t[e>>2]=n|32,e=-1):(t[e+8>>2]=0,t[e+4>>2]=0,r=t[e+44>>2]|0,t[e+28>>2]=r,t[e+20>>2]=r,t[e+16>>2]=r+(t[e+48>>2]|0),e=0),e|0}function xu(e,n){e=S(e),n=S(n);var r=0,u=0;r=D8(e)|0;do if((r&2147483647)>>>0<=2139095040){if(u=D8(n)|0,(u&2147483647)>>>0<=2139095040)if((u^r|0)<0){e=(r|0)<0?n:e;break}else{e=e>2]=e,t[V>>2]|0|0}function Kp(e,n){e=S(e),n=S(n);var r=0,u=0;r=w8(e)|0;do if((r&2147483647)>>>0<=2139095040){if(u=w8(n)|0,(u&2147483647)>>>0<=2139095040)if((u^r|0)<0){e=(r|0)<0?e:n;break}else{e=e>2]=e,t[V>>2]|0|0}function NE(e,n){e=S(e),n=S(n);var r=0,u=0,s=0,a=0,v=0,w=0,T=0,L=0;a=(x[V>>2]=e,t[V>>2]|0),w=(x[V>>2]=n,t[V>>2]|0),r=a>>>23&255,v=w>>>23&255,T=a&-2147483648,s=w<<1;e:do if((s|0)!=0&&!((r|0)==255|((LL(n)|0)&2147483647)>>>0>2139095040)){if(u=a<<1,u>>>0<=s>>>0)return n=S(e*S(0)),S((u|0)==(s|0)?n:e);if(r)u=a&8388607|8388608;else{if(r=a<<9,(r|0)>-1){u=r,r=0;do r=r+-1|0,u=u<<1;while((u|0)>-1)}else r=0;u=a<<1-r}if(v)w=w&8388607|8388608;else{if(a=w<<9,(a|0)>-1){s=0;do s=s+-1|0,a=a<<1;while((a|0)>-1)}else s=0;v=s,w=w<<1-s}s=u-w|0,a=(s|0)>-1;t:do if((r|0)>(v|0)){for(;;){if(a)if(s)u=s;else break;if(u=u<<1,r=r+-1|0,s=u-w|0,a=(s|0)>-1,(r|0)<=(v|0))break t}n=S(e*S(0));break e}while(0);if(a)if(s)u=s;else{n=S(e*S(0));break}if(u>>>0<8388608)do u=u<<1,r=r+-1|0;while(u>>>0<8388608);(r|0)>0?r=u+-8388608|r<<23:r=u>>>(1-r|0),n=(t[V>>2]=r|T,S(x[V>>2]))}else L=3;while(0);return(L|0)==3&&(n=S(e*n),n=S(n/n)),S(n)}function LL(e){return e=S(e),x[V>>2]=e,t[V>>2]|0|0}function FL(e,n){return e=e|0,n=n|0,v8(t[582]|0,e,n)|0}function di(e){e=e|0,$n()}function Uv(e){e=e|0}function PL(e,n){return e=e|0,n=n|0,0}function IL(e){return e=e|0,(S8(e+4|0)|0)==-1?(P1[t[(t[e>>2]|0)+8>>2]&127](e),e=1):e=0,e|0}function S8(e){e=e|0;var n=0;return n=t[e>>2]|0,t[e>>2]=n+-1,n+-1|0}function $d(e){e=e|0,IL(e)|0&&bL(e)}function bL(e){e=e|0;var n=0;n=e+8|0,(t[n>>2]|0)!=0&&(S8(n)|0)!=-1||P1[t[(t[e>>2]|0)+16>>2]&127](e)}function pn(e){e=e|0;var n=0;for(n=(e|0)==0?1:e;e=p_(n)|0,!(e|0);){if(e=UL()|0,!e){e=0;break}B8[e&0]()}return e|0}function T8(e){return e=e|0,pn(e)|0}function Et(e){e=e|0,h_(e)}function BL(e){e=e|0,(h[e+11>>0]|0)<0&&Et(t[e>>2]|0)}function UL(){var e=0;return e=t[2923]|0,t[2923]=e+0,e|0}function jL(){}function m_(e,n,r,u){return e=e|0,n=n|0,r=r|0,u=u|0,u=n-u-(r>>>0>e>>>0|0)>>>0,ot=u,e-r>>>0|0|0}function LE(e,n,r,u){return e=e|0,n=n|0,r=r|0,u=u|0,r=e+r>>>0,ot=n+u+(r>>>0>>0|0)>>>0,r|0|0}function jv(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0,v=0;if(a=e+r|0,n=n&255,(r|0)>=67){for(;e&3;)h[e>>0]=n,e=e+1|0;for(u=a&-4|0,s=u-64|0,v=n|n<<8|n<<16|n<<24;(e|0)<=(s|0);)t[e>>2]=v,t[e+4>>2]=v,t[e+8>>2]=v,t[e+12>>2]=v,t[e+16>>2]=v,t[e+20>>2]=v,t[e+24>>2]=v,t[e+28>>2]=v,t[e+32>>2]=v,t[e+36>>2]=v,t[e+40>>2]=v,t[e+44>>2]=v,t[e+48>>2]=v,t[e+52>>2]=v,t[e+56>>2]=v,t[e+60>>2]=v,e=e+64|0;for(;(e|0)<(u|0);)t[e>>2]=v,e=e+4|0}for(;(e|0)<(a|0);)h[e>>0]=n,e=e+1|0;return a-r|0}function C8(e,n,r){return e=e|0,n=n|0,r=r|0,(r|0)<32?(ot=n<>>32-r,e<>>r,e>>>r|(n&(1<>>r-32|0)}function gr(e,n,r){e=e|0,n=n|0,r=r|0;var u=0,s=0,a=0;if((r|0)>=8192)return li(e|0,n|0,r|0)|0;if(a=e|0,s=e+r|0,(e&3)==(n&3)){for(;e&3;){if(!r)return a|0;h[e>>0]=h[n>>0]|0,e=e+1|0,n=n+1|0,r=r-1|0}for(r=s&-4|0,u=r-64|0;(e|0)<=(u|0);)t[e>>2]=t[n>>2],t[e+4>>2]=t[n+4>>2],t[e+8>>2]=t[n+8>>2],t[e+12>>2]=t[n+12>>2],t[e+16>>2]=t[n+16>>2],t[e+20>>2]=t[n+20>>2],t[e+24>>2]=t[n+24>>2],t[e+28>>2]=t[n+28>>2],t[e+32>>2]=t[n+32>>2],t[e+36>>2]=t[n+36>>2],t[e+40>>2]=t[n+40>>2],t[e+44>>2]=t[n+44>>2],t[e+48>>2]=t[n+48>>2],t[e+52>>2]=t[n+52>>2],t[e+56>>2]=t[n+56>>2],t[e+60>>2]=t[n+60>>2],e=e+64|0,n=n+64|0;for(;(e|0)<(r|0);)t[e>>2]=t[n>>2],e=e+4|0,n=n+4|0}else for(r=s-4|0;(e|0)<(r|0);)h[e>>0]=h[n>>0]|0,h[e+1>>0]=h[n+1>>0]|0,h[e+2>>0]=h[n+2>>0]|0,h[e+3>>0]=h[n+3>>0]|0,e=e+4|0,n=n+4|0;for(;(e|0)<(s|0);)h[e>>0]=h[n>>0]|0,e=e+1|0,n=n+1|0;return a|0}function x8(e){e=e|0;var n=0;return n=h[De+(e&255)>>0]|0,(n|0)<8?n|0:(n=h[De+(e>>8&255)>>0]|0,(n|0)<8?n+8|0:(n=h[De+(e>>16&255)>>0]|0,(n|0)<8?n+16|0:(h[De+(e>>>24)>>0]|0)+24|0))}function R8(e,n,r,u,s){e=e|0,n=n|0,r=r|0,u=u|0,s=s|0;var a=0,v=0,w=0,T=0,L=0,M=0,b=0,X=0,Be=0,Te=0;if(M=e,T=n,L=T,v=r,X=u,w=X,!L)return a=(s|0)!=0,w?a?(t[s>>2]=e|0,t[s+4>>2]=n&0,X=0,s=0,ot=X,s|0):(X=0,s=0,ot=X,s|0):(a&&(t[s>>2]=(M>>>0)%(v>>>0),t[s+4>>2]=0),X=0,s=(M>>>0)/(v>>>0)>>>0,ot=X,s|0);a=(w|0)==0;do if(v){if(!a){if(a=(Er(w|0)|0)-(Er(L|0)|0)|0,a>>>0<=31){b=a+1|0,w=31-a|0,n=a-31>>31,v=b,e=M>>>(b>>>0)&n|L<>>(b>>>0)&n,a=0,w=M<>2]=e|0,t[s+4>>2]=T|n&0,X=0,s=0,ot=X,s|0):(X=0,s=0,ot=X,s|0)}if(a=v-1|0,a&v|0){w=(Er(v|0)|0)+33-(Er(L|0)|0)|0,Te=64-w|0,b=32-w|0,T=b>>31,Be=w-32|0,n=Be>>31,v=w,e=b-1>>31&L>>>(Be>>>0)|(L<>>(w>>>0))&n,n=n&L>>>(w>>>0),a=M<>>(Be>>>0))&T|M<>31;break}return s|0&&(t[s>>2]=a&M,t[s+4>>2]=0),(v|0)==1?(Be=T|n&0,Te=e|0|0,ot=Be,Te|0):(Te=x8(v|0)|0,Be=L>>>(Te>>>0)|0,Te=L<<32-Te|M>>>(Te>>>0)|0,ot=Be,Te|0)}else{if(a)return s|0&&(t[s>>2]=(L>>>0)%(v>>>0),t[s+4>>2]=0),Be=0,Te=(L>>>0)/(v>>>0)>>>0,ot=Be,Te|0;if(!M)return s|0&&(t[s>>2]=0,t[s+4>>2]=(L>>>0)%(w>>>0)),Be=0,Te=(L>>>0)/(w>>>0)>>>0,ot=Be,Te|0;if(a=w-1|0,!(a&w))return s|0&&(t[s>>2]=e|0,t[s+4>>2]=a&L|n&0),Be=0,Te=L>>>((x8(w|0)|0)>>>0),ot=Be,Te|0;if(a=(Er(w|0)|0)-(Er(L|0)|0)|0,a>>>0<=30){n=a+1|0,w=31-a|0,v=n,e=L<>>(n>>>0),n=L>>>(n>>>0),a=0,w=M<>2]=e|0,t[s+4>>2]=T|n&0,Be=0,Te=0,ot=Be,Te|0):(Be=0,Te=0,ot=Be,Te|0)}while(0);if(!v)L=w,T=0,w=0;else{b=r|0|0,M=X|u&0,L=LE(b|0,M|0,-1,-1)|0,r=ot,T=w,w=0;do u=T,T=a>>>31|T<<1,a=w|a<<1,u=e<<1|u>>>31|0,X=e>>>31|n<<1|0,m_(L|0,r|0,u|0,X|0)|0,Te=ot,Be=Te>>31|((Te|0)<0?-1:0)<<1,w=Be&1,e=m_(u|0,X|0,Be&b|0,(((Te|0)<0?-1:0)>>31|((Te|0)<0?-1:0)<<1)&M|0)|0,n=ot,v=v-1|0;while((v|0)!=0);L=T,T=0}return v=0,s|0&&(t[s>>2]=e,t[s+4>>2]=n),Be=(a|0)>>>31|(L|v)<<1|(v<<1|a>>>31)&0|T,Te=(a<<1|0>>>31)&-2|w,ot=Be,Te|0}function FE(e,n,r,u){return e=e|0,n=n|0,r=r|0,u=u|0,R8(e,n,r,u,0)|0}function e2(e){e=e|0;var n=0,r=0;return r=e+15&-16|0,n=t[q>>2]|0,e=n+r|0,(r|0)>0&(e|0)<(n|0)|(e|0)<0?(fr()|0,Ql(12),-1):(t[q>>2]=e,(e|0)>(jr()|0)&&(vr()|0)==0?(t[q>>2]=n,Ql(12),-1):n|0)}function ky(e,n,r){e=e|0,n=n|0,r=r|0;var u=0;if((n|0)<(e|0)&(e|0)<(n+r|0)){for(u=e,n=n+r|0,e=e+r|0;(r|0)>0;)e=e-1|0,n=n-1|0,r=r-1|0,h[e>>0]=h[n>>0]|0;e=u}else gr(e,n,r)|0;return e|0}function PE(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0;var s=0,a=0;return a=y,y=y+16|0,s=a|0,R8(e,n,r,u,s)|0,y=a,ot=t[s+4>>2]|0,t[s>>2]|0|0}function A8(e){return e=e|0,(e&255)<<24|(e>>8&255)<<16|(e>>16&255)<<8|e>>>24|0}function zL(e,n,r,u,s,a){e=e|0,n=n|0,r=r|0,u=u|0,s=s|0,a=a|0,O8[e&1](n|0,r|0,u|0,s|0,a|0)}function HL(e,n,r){e=e|0,n=n|0,r=S(r),M8[e&1](n|0,S(r))}function qL(e,n,r){e=e|0,n=n|0,r=+r,k8[e&31](n|0,+r)}function WL(e,n,r,u){return e=e|0,n=n|0,r=S(r),u=S(u),S(N8[e&0](n|0,S(r),S(u)))}function VL(e,n){e=e|0,n=n|0,P1[e&127](n|0)}function YL(e,n,r){e=e|0,n=n|0,r=r|0,I1[e&31](n|0,r|0)}function KL(e,n){return e=e|0,n=n|0,Qp[e&31](n|0)|0}function XL(e,n,r,u,s){e=e|0,n=n|0,r=+r,u=+u,s=s|0,L8[e&1](n|0,+r,+u,s|0)}function QL(e,n,r,u){e=e|0,n=n|0,r=+r,u=+u,MF[e&1](n|0,+r,+u)}function JL(e,n,r,u){return e=e|0,n=n|0,r=r|0,u=u|0,__[e&7](n|0,r|0,u|0)|0}function ZL(e,n,r,u){return e=e|0,n=n|0,r=r|0,u=u|0,+kF[e&1](n|0,r|0,u|0)}function $L(e,n){return e=e|0,n=n|0,+F8[e&15](n|0)}function eF(e,n,r){return e=e|0,n=n|0,r=+r,NF[e&1](n|0,+r)|0}function tF(e,n,r){return e=e|0,n=n|0,r=r|0,bE[e&15](n|0,r|0)|0}function nF(e,n,r,u,s,a){e=e|0,n=n|0,r=r|0,u=+u,s=+s,a=a|0,LF[e&1](n|0,r|0,+u,+s,a|0)}function rF(e,n,r,u,s,a,v){e=e|0,n=n|0,r=r|0,u=u|0,s=s|0,a=a|0,v=v|0,FF[e&1](n|0,r|0,u|0,s|0,a|0,v|0)}function iF(e,n,r){return e=e|0,n=n|0,r=r|0,+P8[e&7](n|0,r|0)}function uF(e){return e=e|0,E_[e&7]()|0}function oF(e,n,r,u,s,a){return e=e|0,n=n|0,r=r|0,u=u|0,s=s|0,a=a|0,I8[e&1](n|0,r|0,u|0,s|0,a|0)|0}function lF(e,n,r,u,s){e=e|0,n=n|0,r=r|0,u=u|0,s=+s,PF[e&1](n|0,r|0,u|0,+s)}function sF(e,n,r,u,s,a,v){e=e|0,n=n|0,r=r|0,u=S(u),s=s|0,a=S(a),v=v|0,b8[e&1](n|0,r|0,S(u),s|0,S(a),v|0)}function aF(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0,Fy[e&15](n|0,r|0,u|0)}function fF(e){e=e|0,B8[e&0]()}function cF(e,n,r,u){e=e|0,n=n|0,r=r|0,u=+u,U8[e&15](n|0,r|0,+u)}function dF(e,n,r){return e=e|0,n=+n,r=+r,IF[e&1](+n,+r)|0}function pF(e,n,r,u,s){e=e|0,n=n|0,r=r|0,u=u|0,s=s|0,BE[e&15](n|0,r|0,u|0,s|0)}function hF(e,n,r,u,s){e=e|0,n=n|0,r=r|0,u=u|0,s=s|0,zt(0)}function vF(e,n){e=e|0,n=S(n),zt(1)}function $s(e,n){e=e|0,n=+n,zt(2)}function mF(e,n,r){return e=e|0,n=S(n),r=S(r),zt(3),Ct}function Zn(e){e=e|0,zt(4)}function Ny(e,n){e=e|0,n=n|0,zt(5)}function Na(e){return e=e|0,zt(6),0}function yF(e,n,r,u){e=e|0,n=+n,r=+r,u=u|0,zt(7)}function gF(e,n,r){e=e|0,n=+n,r=+r,zt(8)}function _F(e,n,r){return e=e|0,n=n|0,r=r|0,zt(9),0}function EF(e,n,r){return e=e|0,n=n|0,r=r|0,zt(10),0}function Xp(e){return e=e|0,zt(11),0}function DF(e,n){return e=e|0,n=+n,zt(12),0}function Ly(e,n){return e=e|0,n=n|0,zt(13),0}function wF(e,n,r,u,s){e=e|0,n=n|0,r=+r,u=+u,s=s|0,zt(14)}function SF(e,n,r,u,s,a){e=e|0,n=n|0,r=r|0,u=u|0,s=s|0,a=a|0,zt(15)}function IE(e,n){return e=e|0,n=n|0,zt(16),0}function TF(){return zt(17),0}function CF(e,n,r,u,s){return e=e|0,n=n|0,r=r|0,u=u|0,s=s|0,zt(18),0}function xF(e,n,r,u){e=e|0,n=n|0,r=r|0,u=+u,zt(19)}function RF(e,n,r,u,s,a){e=e|0,n=n|0,r=S(r),u=u|0,s=S(s),a=a|0,zt(20)}function g_(e,n,r){e=e|0,n=n|0,r=r|0,zt(21)}function AF(){zt(22)}function zv(e,n,r){e=e|0,n=n|0,r=+r,zt(23)}function OF(e,n){return e=+e,n=+n,zt(24),0}function Hv(e,n,r,u){e=e|0,n=n|0,r=r|0,u=u|0,zt(25)}var O8=[hF,TO],M8=[vF,t0],k8=[$s,ca,ws,Ss,ts,Ho,Ef,ol,qa,n0,Df,Wc,dc,Ol,Ts,da,ud,pa,pc,$s,$s,$s,$s,$s,$s,$s,$s,$s,$s,$s,$s,$s],N8=[mF],P1=[Zn,Uv,cn,is,Do,Uf,M1,jl,$A,e7,t7,cO,dO,pO,LN,FN,PN,Fe,fc,Ua,Vu,j0,yh,Sf,r1,Lf,Ea,kh,ym,g1,_1,Zh,hp,Ld,jm,C1,Ac,Jm,ey,xv,Mv,on,P4,G4,n_,Lt,Cu,e0,p9,O9,K9,dR,RR,KR,iA,lA,TA,RA,WA,r7,o7,S7,z7,gd,wM,$M,hk,Ok,Jk,dN,SN,xN,Zn,Zn,Zn,Zn,Zn,Zn,Zn,Zn,Zn,Zn,Zn,Zn,Zn,Zn,Zn,Zn,Zn,Zn,Zn,Zn,Zn,Zn,Zn,Zn,Zn,Zn,Zn,Zn,Zn,Zn,Zn,Zn,Zn,Zn,Zn,Zn,Zn,Zn,Zn,Zn,Zn,Zn,Zn,Zn,Zn,Zn,Zn,Zn,Zn,Zn,Zn,Zn,Zn,Zn,Zn,Zn],I1=[Ny,_2,nd,qc,Rl,ul,E2,qs,Al,ja,za,Ha,Ml,je,st,$t,Wn,oi,ur,Wa,w2,_h,X4,eE,mR,CM,X7,$w,Ny,Ny,Ny,Ny],Qp=[Na,fL,_f,g,Z,de,yt,Rt,Nt,xr,cu,z0,Va,od,Xc,Ms,kR,x7,OM,Oa,Na,Na,Na,Na,Na,Na,Na,Na,Na,Na,Na,Na],L8=[yF,C2],MF=[gF,YA],__=[_F,p8,cL,hL,Wh,vv,y9,Lk],kF=[EF,fv],F8=[Xp,i0,Ge,ai,gh,al,ha,x2,R2,hc,Xp,Xp,Xp,Xp,Xp,Xp],NF=[DF,tA],bE=[Ly,PL,D2,dl,H2,xm,fp,xp,ty,kr,jo,gk,Ly,Ly,Ly,Ly],LF=[wF,xh],FF=[SF,tN],P8=[IE,Qi,A2,dd,Qc,ml,IE,IE],E_=[TF,Jc,io,E0,cA,kA,f7,MN],I8=[CF,ui],PF=[xF,vy],b8=[RF,ld],Fy=[g_,A,r0,Vr,Tu,m1,Nd,ar,_y,mo,YO,rk,mN,g_,g_,g_],B8=[AF],U8=[zv,rd,yo,id,zo,Vc,Wi,_,Bp,L9,JR,zv,zv,zv,zv,zv],IF=[OF,JA],BE=[Hv,Ep,Lc,Z9,jR,yA,bA,y7,G7,PM,zN,Hv,Hv,Hv,Hv,Hv];return{_llvm_bswap_i32:A8,dynCall_idd:dF,dynCall_i:uF,_i64Subtract:m_,___udivdi3:FE,dynCall_vif:HL,setThrew:vs,dynCall_viii:aF,_bitshift64Lshr:y_,_bitshift64Shl:C8,dynCall_vi:VL,dynCall_viiddi:nF,dynCall_diii:ZL,dynCall_iii:tF,_memset:jv,_sbrk:e2,_memcpy:gr,__GLOBAL__sub_I_Yoga_cpp:ru,dynCall_vii:YL,___uremdi3:PE,dynCall_vid:qL,stackAlloc:co,_nbind_init:ZN,getTempRet0:Q,dynCall_di:$L,dynCall_iid:eF,setTempRet0:b0,_i64Add:LE,dynCall_fiff:WL,dynCall_iiii:JL,_emscripten_get_global_libc:aL,dynCall_viid:cF,dynCall_viiid:lF,dynCall_viififi:sF,dynCall_ii:KL,__GLOBAL__sub_I_Binding_cc:hM,dynCall_viiii:pF,dynCall_iiiiii:oF,stackSave:nl,dynCall_viiiii:zL,__GLOBAL__sub_I_nbind_cc:Ws,dynCall_vidd:QL,_free:h_,runPostSets:jL,dynCall_viiiiii:rF,establishStackSpace:Uu,_memmove:ky,stackRestore:Jl,_malloc:p_,__GLOBAL__sub_I_common_cc:F7,dynCall_viddi:XL,dynCall_dii:iF,dynCall_v:fF}}(Module.asmGlobalArg,Module.asmLibraryArg,buffer),_llvm_bswap_i32=Module._llvm_bswap_i32=asm._llvm_bswap_i32,getTempRet0=Module.getTempRet0=asm.getTempRet0,___udivdi3=Module.___udivdi3=asm.___udivdi3,setThrew=Module.setThrew=asm.setThrew,_bitshift64Lshr=Module._bitshift64Lshr=asm._bitshift64Lshr,_bitshift64Shl=Module._bitshift64Shl=asm._bitshift64Shl,_memset=Module._memset=asm._memset,_sbrk=Module._sbrk=asm._sbrk,_memcpy=Module._memcpy=asm._memcpy,stackAlloc=Module.stackAlloc=asm.stackAlloc,___uremdi3=Module.___uremdi3=asm.___uremdi3,_nbind_init=Module._nbind_init=asm._nbind_init,_i64Subtract=Module._i64Subtract=asm._i64Subtract,setTempRet0=Module.setTempRet0=asm.setTempRet0,_i64Add=Module._i64Add=asm._i64Add,_emscripten_get_global_libc=Module._emscripten_get_global_libc=asm._emscripten_get_global_libc,__GLOBAL__sub_I_Yoga_cpp=Module.__GLOBAL__sub_I_Yoga_cpp=asm.__GLOBAL__sub_I_Yoga_cpp,__GLOBAL__sub_I_Binding_cc=Module.__GLOBAL__sub_I_Binding_cc=asm.__GLOBAL__sub_I_Binding_cc,stackSave=Module.stackSave=asm.stackSave,__GLOBAL__sub_I_nbind_cc=Module.__GLOBAL__sub_I_nbind_cc=asm.__GLOBAL__sub_I_nbind_cc,_free=Module._free=asm._free,runPostSets=Module.runPostSets=asm.runPostSets,establishStackSpace=Module.establishStackSpace=asm.establishStackSpace,_memmove=Module._memmove=asm._memmove,stackRestore=Module.stackRestore=asm.stackRestore,_malloc=Module._malloc=asm._malloc,__GLOBAL__sub_I_common_cc=Module.__GLOBAL__sub_I_common_cc=asm.__GLOBAL__sub_I_common_cc,dynCall_viiiii=Module.dynCall_viiiii=asm.dynCall_viiiii,dynCall_vif=Module.dynCall_vif=asm.dynCall_vif,dynCall_vid=Module.dynCall_vid=asm.dynCall_vid,dynCall_fiff=Module.dynCall_fiff=asm.dynCall_fiff,dynCall_vi=Module.dynCall_vi=asm.dynCall_vi,dynCall_vii=Module.dynCall_vii=asm.dynCall_vii,dynCall_ii=Module.dynCall_ii=asm.dynCall_ii,dynCall_viddi=Module.dynCall_viddi=asm.dynCall_viddi,dynCall_vidd=Module.dynCall_vidd=asm.dynCall_vidd,dynCall_iiii=Module.dynCall_iiii=asm.dynCall_iiii,dynCall_diii=Module.dynCall_diii=asm.dynCall_diii,dynCall_di=Module.dynCall_di=asm.dynCall_di,dynCall_iid=Module.dynCall_iid=asm.dynCall_iid,dynCall_iii=Module.dynCall_iii=asm.dynCall_iii,dynCall_viiddi=Module.dynCall_viiddi=asm.dynCall_viiddi,dynCall_viiiiii=Module.dynCall_viiiiii=asm.dynCall_viiiiii,dynCall_dii=Module.dynCall_dii=asm.dynCall_dii,dynCall_i=Module.dynCall_i=asm.dynCall_i,dynCall_iiiiii=Module.dynCall_iiiiii=asm.dynCall_iiiiii,dynCall_viiid=Module.dynCall_viiid=asm.dynCall_viiid,dynCall_viififi=Module.dynCall_viififi=asm.dynCall_viififi,dynCall_viii=Module.dynCall_viii=asm.dynCall_viii,dynCall_v=Module.dynCall_v=asm.dynCall_v,dynCall_viid=Module.dynCall_viid=asm.dynCall_viid,dynCall_idd=Module.dynCall_idd=asm.dynCall_idd,dynCall_viiii=Module.dynCall_viiii=asm.dynCall_viiii;Runtime.stackAlloc=Module.stackAlloc,Runtime.stackSave=Module.stackSave,Runtime.stackRestore=Module.stackRestore,Runtime.establishStackSpace=Module.establishStackSpace,Runtime.setTempRet0=Module.setTempRet0,Runtime.getTempRet0=Module.getTempRet0,Module.asm=asm;function ExitStatus(o){this.name="ExitStatus",this.message="Program terminated with exit("+o+")",this.status=o}ExitStatus.prototype=new Error,ExitStatus.prototype.constructor=ExitStatus;var initialStackTop,preloadStartTime=null,calledMain=!1;dependenciesFulfilled=function o(){Module.calledRun||run(),Module.calledRun||(dependenciesFulfilled=o)},Module.callMain=Module.callMain=function o(l){l=l||[],ensureInitRuntime();var f=l.length+1;function h(){for(var k=0;k<4-1;k++)E.push(0)}var E=[allocate(intArrayFromString(Module.thisProgram),"i8",ALLOC_NORMAL)];h();for(var t=0;t0||(preRun(),runDependencies>0)||Module.calledRun)return;function l(){Module.calledRun||(Module.calledRun=!0,!ABORT&&(ensureInitRuntime(),preMain(),Module.onRuntimeInitialized&&Module.onRuntimeInitialized(),Module._main&&shouldRunNow&&Module.callMain(o),postRun()))}Module.setStatus?(Module.setStatus("Running..."),setTimeout(function(){setTimeout(function(){Module.setStatus("")},1),l()},1)):l()}Module.run=Module.run=run;function exit(o,l){l&&Module.noExitRuntime||(Module.noExitRuntime||(ABORT=!0,EXITSTATUS=o,STACKTOP=initialStackTop,exitRuntime(),Module.onExit&&Module.onExit(o)),ENVIRONMENT_IS_NODE&&process.exit(o),Module.quit(o,new ExitStatus(o)))}Module.exit=Module.exit=exit;var abortDecorators=[];function abort(o){Module.onAbort&&Module.onAbort(o),o!==void 0?(Module.print(o),Module.printErr(o),o=JSON.stringify(o)):o="",ABORT=!0,EXITSTATUS=1;var l=` +If this abort() is unexpected, build with -s ASSERTIONS=1 which can give more information.`,f="abort("+o+") at "+stackTrace()+l;throw abortDecorators&&abortDecorators.forEach(function(h){f=h(f,o)}),f}if(Module.abort=Module.abort=abort,Module.preInit)for(typeof Module.preInit=="function"&&(Module.preInit=[Module.preInit]);Module.preInit.length>0;)Module.preInit.pop()();var shouldRunNow=!0;Module.noInitialRun&&(shouldRunNow=!1),run()})});var eh=nt((CH,tT)=>{"use strict";var SP=$S(),TP=eT(),_D=!1,ED=null;TP({},function(o,l){if(!_D){if(_D=!0,o)throw o;ED=l}});if(!_D)throw new Error("Failed to load the yoga module - it needed to be loaded synchronously, but didn't");tT.exports=SP(ED.bind,ED.lib)});var rT=nt((xH,nT)=>{"use strict";nT.exports=({onlyFirst:o=!1}={})=>{let l=["[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)","(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))"].join("|");return new RegExp(l,o?void 0:"g")}});var DD=nt((RH,iT)=>{"use strict";var CP=rT();iT.exports=o=>typeof o=="string"?o.replace(CP(),""):o});var SD=nt((AH,wD)=>{"use strict";var uT=o=>Number.isNaN(o)?!1:o>=4352&&(o<=4447||o===9001||o===9002||11904<=o&&o<=12871&&o!==12351||12880<=o&&o<=19903||19968<=o&&o<=42182||43360<=o&&o<=43388||44032<=o&&o<=55203||63744<=o&&o<=64255||65040<=o&&o<=65049||65072<=o&&o<=65131||65281<=o&&o<=65376||65504<=o&&o<=65510||110592<=o&&o<=110593||127488<=o&&o<=127569||131072<=o&&o<=262141);wD.exports=uT;wD.exports.default=uT});var lT=nt((OH,oT)=>{"use strict";oT.exports=function(){return/\uD83C\uDFF4\uDB40\uDC67\uDB40\uDC62(?:\uDB40\uDC65\uDB40\uDC6E\uDB40\uDC67|\uDB40\uDC73\uDB40\uDC63\uDB40\uDC74|\uDB40\uDC77\uDB40\uDC6C\uDB40\uDC73)\uDB40\uDC7F|\uD83D\uDC68(?:\uD83C\uDFFC\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68\uD83C\uDFFB|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFE])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFE\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFD])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFC])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83D\uDC68|(?:\uD83D[\uDC68\uDC69])\u200D(?:\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67]))|\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67])|(?:\uD83D[\uDC68\uDC69])\u200D(?:\uD83D[\uDC66\uDC67])|[\u2695\u2696\u2708]\uFE0F|\uD83D[\uDC66\uDC67]|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|(?:\uD83C\uDFFB\u200D[\u2695\u2696\u2708]|\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708])\uFE0F|\uD83C\uDFFB\u200D(?:\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C[\uDFFB-\uDFFF])|(?:\uD83E\uDDD1\uD83C\uDFFB\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFC\u200D\uD83E\uDD1D\u200D\uD83D\uDC69)\uD83C\uDFFB|\uD83E\uDDD1(?:\uD83C\uDFFF\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1(?:\uD83C[\uDFFB-\uDFFF])|\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1)|(?:\uD83E\uDDD1\uD83C\uDFFE\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFF\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB-\uDFFE])|(?:\uD83E\uDDD1\uD83C\uDFFC\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFD\u200D\uD83E\uDD1D\u200D\uD83D\uDC69)(?:\uD83C[\uDFFB\uDFFC])|\uD83D\uDC69(?:\uD83C\uDFFE\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFD\uDFFF])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFC\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFD-\uDFFF])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFB\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFC-\uDFFF])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD]))|\uD83D\uDC69\u200D\uD83D\uDC69\u200D(?:\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67]))|(?:\uD83E\uDDD1\uD83C\uDFFD\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFE\u200D\uD83E\uDD1D\u200D\uD83D\uDC69)(?:\uD83C[\uDFFB-\uDFFD])|\uD83D\uDC69\u200D\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC69\u200D\uD83D\uDC69\u200D(?:\uD83D[\uDC66\uDC67])|(?:\uD83D\uDC41\uFE0F\u200D\uD83D\uDDE8|\uD83D\uDC69(?:\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708]|\uD83C\uDFFB\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])|(?:(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)\uFE0F|\uD83D\uDC6F|\uD83E[\uDD3C\uDDDE\uDDDF])\u200D[\u2640\u2642]|(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)(?:\uD83C[\uDFFB-\uDFFF])\u200D[\u2640\u2642]|(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD6-\uDDDD])(?:(?:\uD83C[\uDFFB-\uDFFF])\u200D[\u2640\u2642]|\u200D[\u2640\u2642])|\uD83C\uDFF4\u200D\u2620)\uFE0F|\uD83D\uDC69\u200D\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67])|\uD83C\uDFF3\uFE0F\u200D\uD83C\uDF08|\uD83D\uDC15\u200D\uD83E\uDDBA|\uD83D\uDC69\u200D\uD83D\uDC66|\uD83D\uDC69\u200D\uD83D\uDC67|\uD83C\uDDFD\uD83C\uDDF0|\uD83C\uDDF4\uD83C\uDDF2|\uD83C\uDDF6\uD83C\uDDE6|[#\*0-9]\uFE0F\u20E3|\uD83C\uDDE7(?:\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEF\uDDF1-\uDDF4\uDDF6-\uDDF9\uDDFB\uDDFC\uDDFE\uDDFF])|\uD83C\uDDF9(?:\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDED\uDDEF-\uDDF4\uDDF7\uDDF9\uDDFB\uDDFC\uDDFF])|\uD83C\uDDEA(?:\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDED\uDDF7-\uDDFA])|\uD83E\uDDD1(?:\uD83C[\uDFFB-\uDFFF])|\uD83C\uDDF7(?:\uD83C[\uDDEA\uDDF4\uDDF8\uDDFA\uDDFC])|\uD83D\uDC69(?:\uD83C[\uDFFB-\uDFFF])|\uD83C\uDDF2(?:\uD83C[\uDDE6\uDDE8-\uDDED\uDDF0-\uDDFF])|\uD83C\uDDE6(?:\uD83C[\uDDE8-\uDDEC\uDDEE\uDDF1\uDDF2\uDDF4\uDDF6-\uDDFA\uDDFC\uDDFD\uDDFF])|\uD83C\uDDF0(?:\uD83C[\uDDEA\uDDEC-\uDDEE\uDDF2\uDDF3\uDDF5\uDDF7\uDDFC\uDDFE\uDDFF])|\uD83C\uDDED(?:\uD83C[\uDDF0\uDDF2\uDDF3\uDDF7\uDDF9\uDDFA])|\uD83C\uDDE9(?:\uD83C[\uDDEA\uDDEC\uDDEF\uDDF0\uDDF2\uDDF4\uDDFF])|\uD83C\uDDFE(?:\uD83C[\uDDEA\uDDF9])|\uD83C\uDDEC(?:\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEE\uDDF1-\uDDF3\uDDF5-\uDDFA\uDDFC\uDDFE])|\uD83C\uDDF8(?:\uD83C[\uDDE6-\uDDEA\uDDEC-\uDDF4\uDDF7-\uDDF9\uDDFB\uDDFD-\uDDFF])|\uD83C\uDDEB(?:\uD83C[\uDDEE-\uDDF0\uDDF2\uDDF4\uDDF7])|\uD83C\uDDF5(?:\uD83C[\uDDE6\uDDEA-\uDDED\uDDF0-\uDDF3\uDDF7-\uDDF9\uDDFC\uDDFE])|\uD83C\uDDFB(?:\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDEE\uDDF3\uDDFA])|\uD83C\uDDF3(?:\uD83C[\uDDE6\uDDE8\uDDEA-\uDDEC\uDDEE\uDDF1\uDDF4\uDDF5\uDDF7\uDDFA\uDDFF])|\uD83C\uDDE8(?:\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDEE\uDDF0-\uDDF5\uDDF7\uDDFA-\uDDFF])|\uD83C\uDDF1(?:\uD83C[\uDDE6-\uDDE8\uDDEE\uDDF0\uDDF7-\uDDFB\uDDFE])|\uD83C\uDDFF(?:\uD83C[\uDDE6\uDDF2\uDDFC])|\uD83C\uDDFC(?:\uD83C[\uDDEB\uDDF8])|\uD83C\uDDFA(?:\uD83C[\uDDE6\uDDEC\uDDF2\uDDF3\uDDF8\uDDFE\uDDFF])|\uD83C\uDDEE(?:\uD83C[\uDDE8-\uDDEA\uDDF1-\uDDF4\uDDF6-\uDDF9])|\uD83C\uDDEF(?:\uD83C[\uDDEA\uDDF2\uDDF4\uDDF5])|(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD6-\uDDDD])(?:\uD83C[\uDFFB-\uDFFF])|(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)(?:\uD83C[\uDFFB-\uDFFF])|(?:[\u261D\u270A-\u270D]|\uD83C[\uDF85\uDFC2\uDFC7]|\uD83D[\uDC42\uDC43\uDC46-\uDC50\uDC66\uDC67\uDC6B-\uDC6D\uDC70\uDC72\uDC74-\uDC76\uDC78\uDC7C\uDC83\uDC85\uDCAA\uDD74\uDD7A\uDD90\uDD95\uDD96\uDE4C\uDE4F\uDEC0\uDECC]|\uD83E[\uDD0F\uDD18-\uDD1C\uDD1E\uDD1F\uDD30-\uDD36\uDDB5\uDDB6\uDDBB\uDDD2-\uDDD5])(?:\uD83C[\uDFFB-\uDFFF])|(?:[\u231A\u231B\u23E9-\u23EC\u23F0\u23F3\u25FD\u25FE\u2614\u2615\u2648-\u2653\u267F\u2693\u26A1\u26AA\u26AB\u26BD\u26BE\u26C4\u26C5\u26CE\u26D4\u26EA\u26F2\u26F3\u26F5\u26FA\u26FD\u2705\u270A\u270B\u2728\u274C\u274E\u2753-\u2755\u2757\u2795-\u2797\u27B0\u27BF\u2B1B\u2B1C\u2B50\u2B55]|\uD83C[\uDC04\uDCCF\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE1A\uDE2F\uDE32-\uDE36\uDE38-\uDE3A\uDE50\uDE51\uDF00-\uDF20\uDF2D-\uDF35\uDF37-\uDF7C\uDF7E-\uDF93\uDFA0-\uDFCA\uDFCF-\uDFD3\uDFE0-\uDFF0\uDFF4\uDFF8-\uDFFF]|\uD83D[\uDC00-\uDC3E\uDC40\uDC42-\uDCFC\uDCFF-\uDD3D\uDD4B-\uDD4E\uDD50-\uDD67\uDD7A\uDD95\uDD96\uDDA4\uDDFB-\uDE4F\uDE80-\uDEC5\uDECC\uDED0-\uDED2\uDED5\uDEEB\uDEEC\uDEF4-\uDEFA\uDFE0-\uDFEB]|\uD83E[\uDD0D-\uDD3A\uDD3C-\uDD45\uDD47-\uDD71\uDD73-\uDD76\uDD7A-\uDDA2\uDDA5-\uDDAA\uDDAE-\uDDCA\uDDCD-\uDDFF\uDE70-\uDE73\uDE78-\uDE7A\uDE80-\uDE82\uDE90-\uDE95])|(?:[#\*0-9\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u231A\u231B\u2328\u23CF\u23E9-\u23F3\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB-\u25FE\u2600-\u2604\u260E\u2611\u2614\u2615\u2618\u261D\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u2648-\u2653\u265F\u2660\u2663\u2665\u2666\u2668\u267B\u267E\u267F\u2692-\u2697\u2699\u269B\u269C\u26A0\u26A1\u26AA\u26AB\u26B0\u26B1\u26BD\u26BE\u26C4\u26C5\u26C8\u26CE\u26CF\u26D1\u26D3\u26D4\u26E9\u26EA\u26F0-\u26F5\u26F7-\u26FA\u26FD\u2702\u2705\u2708-\u270D\u270F\u2712\u2714\u2716\u271D\u2721\u2728\u2733\u2734\u2744\u2747\u274C\u274E\u2753-\u2755\u2757\u2763\u2764\u2795-\u2797\u27A1\u27B0\u27BF\u2934\u2935\u2B05-\u2B07\u2B1B\u2B1C\u2B50\u2B55\u3030\u303D\u3297\u3299]|\uD83C[\uDC04\uDCCF\uDD70\uDD71\uDD7E\uDD7F\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE02\uDE1A\uDE2F\uDE32-\uDE3A\uDE50\uDE51\uDF00-\uDF21\uDF24-\uDF93\uDF96\uDF97\uDF99-\uDF9B\uDF9E-\uDFF0\uDFF3-\uDFF5\uDFF7-\uDFFF]|\uD83D[\uDC00-\uDCFD\uDCFF-\uDD3D\uDD49-\uDD4E\uDD50-\uDD67\uDD6F\uDD70\uDD73-\uDD7A\uDD87\uDD8A-\uDD8D\uDD90\uDD95\uDD96\uDDA4\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDE8\uDDEF\uDDF3\uDDFA-\uDE4F\uDE80-\uDEC5\uDECB-\uDED2\uDED5\uDEE0-\uDEE5\uDEE9\uDEEB\uDEEC\uDEF0\uDEF3-\uDEFA\uDFE0-\uDFEB]|\uD83E[\uDD0D-\uDD3A\uDD3C-\uDD45\uDD47-\uDD71\uDD73-\uDD76\uDD7A-\uDDA2\uDDA5-\uDDAA\uDDAE-\uDDCA\uDDCD-\uDDFF\uDE70-\uDE73\uDE78-\uDE7A\uDE80-\uDE82\uDE90-\uDE95])\uFE0F|(?:[\u261D\u26F9\u270A-\u270D]|\uD83C[\uDF85\uDFC2-\uDFC4\uDFC7\uDFCA-\uDFCC]|\uD83D[\uDC42\uDC43\uDC46-\uDC50\uDC66-\uDC78\uDC7C\uDC81-\uDC83\uDC85-\uDC87\uDC8F\uDC91\uDCAA\uDD74\uDD75\uDD7A\uDD90\uDD95\uDD96\uDE45-\uDE47\uDE4B-\uDE4F\uDEA3\uDEB4-\uDEB6\uDEC0\uDECC]|\uD83E[\uDD0F\uDD18-\uDD1F\uDD26\uDD30-\uDD39\uDD3C-\uDD3E\uDDB5\uDDB6\uDDB8\uDDB9\uDDBB\uDDCD-\uDDCF\uDDD1-\uDDDD])/g}});var q_=nt((MH,TD)=>{"use strict";var xP=DD(),RP=SD(),AP=lT(),sT=o=>{if(typeof o!="string"||o.length===0||(o=xP(o),o.length===0))return 0;o=o.replace(AP()," ");let l=0;for(let f=0;f=127&&h<=159||h>=768&&h<=879||(h>65535&&f++,l+=RP(h)?2:1)}return l};TD.exports=sT;TD.exports.default=sT});var xD=nt((kH,CD)=>{"use strict";var OP=q_(),aT=o=>{let l=0;for(let f of o.split(` +`))l=Math.max(l,OP(f));return l};CD.exports=aT;CD.exports.default=aT});var fT=nt(Ky=>{"use strict";var MP=Ky&&Ky.__importDefault||function(o){return o&&o.__esModule?o:{default:o}};Object.defineProperty(Ky,"__esModule",{value:!0});var kP=MP(xD()),RD={};Ky.default=o=>{if(o.length===0)return{width:0,height:0};if(RD[o])return RD[o];let l=kP.default(o),f=o.split(` +`).length;return RD[o]={width:l,height:f},{width:l,height:f}}});var cT=nt(Xy=>{"use strict";var NP=Xy&&Xy.__importDefault||function(o){return o&&o.__esModule?o:{default:o}};Object.defineProperty(Xy,"__esModule",{value:!0});var Gi=NP(eh()),LP=(o,l)=>{"position"in l&&o.setPositionType(l.position==="absolute"?Gi.default.POSITION_TYPE_ABSOLUTE:Gi.default.POSITION_TYPE_RELATIVE)},FP=(o,l)=>{"marginLeft"in l&&o.setMargin(Gi.default.EDGE_START,l.marginLeft||0),"marginRight"in l&&o.setMargin(Gi.default.EDGE_END,l.marginRight||0),"marginTop"in l&&o.setMargin(Gi.default.EDGE_TOP,l.marginTop||0),"marginBottom"in l&&o.setMargin(Gi.default.EDGE_BOTTOM,l.marginBottom||0)},PP=(o,l)=>{"paddingLeft"in l&&o.setPadding(Gi.default.EDGE_LEFT,l.paddingLeft||0),"paddingRight"in l&&o.setPadding(Gi.default.EDGE_RIGHT,l.paddingRight||0),"paddingTop"in l&&o.setPadding(Gi.default.EDGE_TOP,l.paddingTop||0),"paddingBottom"in l&&o.setPadding(Gi.default.EDGE_BOTTOM,l.paddingBottom||0)},IP=(o,l)=>{var f;"flexGrow"in l&&o.setFlexGrow((f=l.flexGrow)!==null&&f!==void 0?f:0),"flexShrink"in l&&o.setFlexShrink(typeof l.flexShrink=="number"?l.flexShrink:1),"flexDirection"in l&&(l.flexDirection==="row"&&o.setFlexDirection(Gi.default.FLEX_DIRECTION_ROW),l.flexDirection==="row-reverse"&&o.setFlexDirection(Gi.default.FLEX_DIRECTION_ROW_REVERSE),l.flexDirection==="column"&&o.setFlexDirection(Gi.default.FLEX_DIRECTION_COLUMN),l.flexDirection==="column-reverse"&&o.setFlexDirection(Gi.default.FLEX_DIRECTION_COLUMN_REVERSE)),"flexBasis"in l&&(typeof l.flexBasis=="number"?o.setFlexBasis(l.flexBasis):typeof l.flexBasis=="string"?o.setFlexBasisPercent(Number.parseInt(l.flexBasis,10)):o.setFlexBasis(NaN)),"alignItems"in l&&((l.alignItems==="stretch"||!l.alignItems)&&o.setAlignItems(Gi.default.ALIGN_STRETCH),l.alignItems==="flex-start"&&o.setAlignItems(Gi.default.ALIGN_FLEX_START),l.alignItems==="center"&&o.setAlignItems(Gi.default.ALIGN_CENTER),l.alignItems==="flex-end"&&o.setAlignItems(Gi.default.ALIGN_FLEX_END)),"alignSelf"in l&&((l.alignSelf==="auto"||!l.alignSelf)&&o.setAlignSelf(Gi.default.ALIGN_AUTO),l.alignSelf==="flex-start"&&o.setAlignSelf(Gi.default.ALIGN_FLEX_START),l.alignSelf==="center"&&o.setAlignSelf(Gi.default.ALIGN_CENTER),l.alignSelf==="flex-end"&&o.setAlignSelf(Gi.default.ALIGN_FLEX_END)),"justifyContent"in l&&((l.justifyContent==="flex-start"||!l.justifyContent)&&o.setJustifyContent(Gi.default.JUSTIFY_FLEX_START),l.justifyContent==="center"&&o.setJustifyContent(Gi.default.JUSTIFY_CENTER),l.justifyContent==="flex-end"&&o.setJustifyContent(Gi.default.JUSTIFY_FLEX_END),l.justifyContent==="space-between"&&o.setJustifyContent(Gi.default.JUSTIFY_SPACE_BETWEEN),l.justifyContent==="space-around"&&o.setJustifyContent(Gi.default.JUSTIFY_SPACE_AROUND))},bP=(o,l)=>{var f,h;"width"in l&&(typeof l.width=="number"?o.setWidth(l.width):typeof l.width=="string"?o.setWidthPercent(Number.parseInt(l.width,10)):o.setWidthAuto()),"height"in l&&(typeof l.height=="number"?o.setHeight(l.height):typeof l.height=="string"?o.setHeightPercent(Number.parseInt(l.height,10)):o.setHeightAuto()),"minWidth"in l&&(typeof l.minWidth=="string"?o.setMinWidthPercent(Number.parseInt(l.minWidth,10)):o.setMinWidth((f=l.minWidth)!==null&&f!==void 0?f:0)),"minHeight"in l&&(typeof l.minHeight=="string"?o.setMinHeightPercent(Number.parseInt(l.minHeight,10)):o.setMinHeight((h=l.minHeight)!==null&&h!==void 0?h:0))},BP=(o,l)=>{"display"in l&&o.setDisplay(l.display==="flex"?Gi.default.DISPLAY_FLEX:Gi.default.DISPLAY_NONE)},UP=(o,l)=>{if("borderStyle"in l){let f=typeof l.borderStyle=="string"?1:0;o.setBorder(Gi.default.EDGE_TOP,f),o.setBorder(Gi.default.EDGE_BOTTOM,f),o.setBorder(Gi.default.EDGE_LEFT,f),o.setBorder(Gi.default.EDGE_RIGHT,f)}};Xy.default=(o,l={})=>{LP(o,l),FP(o,l),PP(o,l),IP(o,l),bP(o,l),BP(o,l),UP(o,l)}});var pT=nt((FH,dT)=>{"use strict";dT.exports={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]}});var AD=nt((PH,vT)=>{var Qy=pT(),hT={};for(let o of Object.keys(Qy))hT[Qy[o]]=o;var zn={rgb:{channels:3,labels:"rgb"},hsl:{channels:3,labels:"hsl"},hsv:{channels:3,labels:"hsv"},hwb:{channels:3,labels:"hwb"},cmyk:{channels:4,labels:"cmyk"},xyz:{channels:3,labels:"xyz"},lab:{channels:3,labels:"lab"},lch:{channels:3,labels:"lch"},hex:{channels:1,labels:["hex"]},keyword:{channels:1,labels:["keyword"]},ansi16:{channels:1,labels:["ansi16"]},ansi256:{channels:1,labels:["ansi256"]},hcg:{channels:3,labels:["h","c","g"]},apple:{channels:3,labels:["r16","g16","b16"]},gray:{channels:1,labels:["gray"]}};vT.exports=zn;for(let o of Object.keys(zn)){if(!("channels"in zn[o]))throw new Error("missing channels property: "+o);if(!("labels"in zn[o]))throw new Error("missing channel labels property: "+o);if(zn[o].labels.length!==zn[o].channels)throw new Error("channel and label counts mismatch: "+o);let{channels:l,labels:f}=zn[o];delete zn[o].channels,delete zn[o].labels,Object.defineProperty(zn[o],"channels",{value:l}),Object.defineProperty(zn[o],"labels",{value:f})}zn.rgb.hsl=function(o){let l=o[0]/255,f=o[1]/255,h=o[2]/255,E=Math.min(l,f,h),t=Math.max(l,f,h),N=t-E,F,k;t===E?F=0:l===t?F=(f-h)/N:f===t?F=2+(h-l)/N:h===t&&(F=4+(l-f)/N),F=Math.min(F*60,360),F<0&&(F+=360);let x=(E+t)/2;return t===E?k=0:x<=.5?k=N/(t+E):k=N/(2-t-E),[F,k*100,x*100]};zn.rgb.hsv=function(o){let l,f,h,E,t,N=o[0]/255,F=o[1]/255,k=o[2]/255,x=Math.max(N,F,k),j=x-Math.min(N,F,k),q=function(V){return(x-V)/6/j+1/2};return j===0?(E=0,t=0):(t=j/x,l=q(N),f=q(F),h=q(k),N===x?E=h-f:F===x?E=1/3+l-h:k===x&&(E=2/3+f-l),E<0?E+=1:E>1&&(E-=1)),[E*360,t*100,x*100]};zn.rgb.hwb=function(o){let l=o[0],f=o[1],h=o[2],E=zn.rgb.hsl(o)[0],t=1/255*Math.min(l,Math.min(f,h));return h=1-1/255*Math.max(l,Math.max(f,h)),[E,t*100,h*100]};zn.rgb.cmyk=function(o){let l=o[0]/255,f=o[1]/255,h=o[2]/255,E=Math.min(1-l,1-f,1-h),t=(1-l-E)/(1-E)||0,N=(1-f-E)/(1-E)||0,F=(1-h-E)/(1-E)||0;return[t*100,N*100,F*100,E*100]};function jP(o,l){return(o[0]-l[0])**2+(o[1]-l[1])**2+(o[2]-l[2])**2}zn.rgb.keyword=function(o){let l=hT[o];if(l)return l;let f=1/0,h;for(let E of Object.keys(Qy)){let t=Qy[E],N=jP(o,t);N.04045?((l+.055)/1.055)**2.4:l/12.92,f=f>.04045?((f+.055)/1.055)**2.4:f/12.92,h=h>.04045?((h+.055)/1.055)**2.4:h/12.92;let E=l*.4124+f*.3576+h*.1805,t=l*.2126+f*.7152+h*.0722,N=l*.0193+f*.1192+h*.9505;return[E*100,t*100,N*100]};zn.rgb.lab=function(o){let l=zn.rgb.xyz(o),f=l[0],h=l[1],E=l[2];f/=95.047,h/=100,E/=108.883,f=f>.008856?f**(1/3):7.787*f+16/116,h=h>.008856?h**(1/3):7.787*h+16/116,E=E>.008856?E**(1/3):7.787*E+16/116;let t=116*h-16,N=500*(f-h),F=200*(h-E);return[t,N,F]};zn.hsl.rgb=function(o){let l=o[0]/360,f=o[1]/100,h=o[2]/100,E,t,N;if(f===0)return N=h*255,[N,N,N];h<.5?E=h*(1+f):E=h+f-h*f;let F=2*h-E,k=[0,0,0];for(let x=0;x<3;x++)t=l+1/3*-(x-1),t<0&&t++,t>1&&t--,6*t<1?N=F+(E-F)*6*t:2*t<1?N=E:3*t<2?N=F+(E-F)*(2/3-t)*6:N=F,k[x]=N*255;return k};zn.hsl.hsv=function(o){let l=o[0],f=o[1]/100,h=o[2]/100,E=f,t=Math.max(h,.01);h*=2,f*=h<=1?h:2-h,E*=t<=1?t:2-t;let N=(h+f)/2,F=h===0?2*E/(t+E):2*f/(h+f);return[l,F*100,N*100]};zn.hsv.rgb=function(o){let l=o[0]/60,f=o[1]/100,h=o[2]/100,E=Math.floor(l)%6,t=l-Math.floor(l),N=255*h*(1-f),F=255*h*(1-f*t),k=255*h*(1-f*(1-t));switch(h*=255,E){case 0:return[h,k,N];case 1:return[F,h,N];case 2:return[N,h,k];case 3:return[N,F,h];case 4:return[k,N,h];case 5:return[h,N,F]}};zn.hsv.hsl=function(o){let l=o[0],f=o[1]/100,h=o[2]/100,E=Math.max(h,.01),t,N;N=(2-f)*h;let F=(2-f)*E;return t=f*E,t/=F<=1?F:2-F,t=t||0,N/=2,[l,t*100,N*100]};zn.hwb.rgb=function(o){let l=o[0]/360,f=o[1]/100,h=o[2]/100,E=f+h,t;E>1&&(f/=E,h/=E);let N=Math.floor(6*l),F=1-h;t=6*l-N,(N&1)!==0&&(t=1-t);let k=f+t*(F-f),x,j,q;switch(N){default:case 6:case 0:x=F,j=k,q=f;break;case 1:x=k,j=F,q=f;break;case 2:x=f,j=F,q=k;break;case 3:x=f,j=k,q=F;break;case 4:x=k,j=f,q=F;break;case 5:x=F,j=f,q=k;break}return[x*255,j*255,q*255]};zn.cmyk.rgb=function(o){let l=o[0]/100,f=o[1]/100,h=o[2]/100,E=o[3]/100,t=1-Math.min(1,l*(1-E)+E),N=1-Math.min(1,f*(1-E)+E),F=1-Math.min(1,h*(1-E)+E);return[t*255,N*255,F*255]};zn.xyz.rgb=function(o){let l=o[0]/100,f=o[1]/100,h=o[2]/100,E,t,N;return E=l*3.2406+f*-1.5372+h*-.4986,t=l*-.9689+f*1.8758+h*.0415,N=l*.0557+f*-.204+h*1.057,E=E>.0031308?1.055*E**(1/2.4)-.055:E*12.92,t=t>.0031308?1.055*t**(1/2.4)-.055:t*12.92,N=N>.0031308?1.055*N**(1/2.4)-.055:N*12.92,E=Math.min(Math.max(0,E),1),t=Math.min(Math.max(0,t),1),N=Math.min(Math.max(0,N),1),[E*255,t*255,N*255]};zn.xyz.lab=function(o){let l=o[0],f=o[1],h=o[2];l/=95.047,f/=100,h/=108.883,l=l>.008856?l**(1/3):7.787*l+16/116,f=f>.008856?f**(1/3):7.787*f+16/116,h=h>.008856?h**(1/3):7.787*h+16/116;let E=116*f-16,t=500*(l-f),N=200*(f-h);return[E,t,N]};zn.lab.xyz=function(o){let l=o[0],f=o[1],h=o[2],E,t,N;t=(l+16)/116,E=f/500+t,N=t-h/200;let F=t**3,k=E**3,x=N**3;return t=F>.008856?F:(t-16/116)/7.787,E=k>.008856?k:(E-16/116)/7.787,N=x>.008856?x:(N-16/116)/7.787,E*=95.047,t*=100,N*=108.883,[E,t,N]};zn.lab.lch=function(o){let l=o[0],f=o[1],h=o[2],E;E=Math.atan2(h,f)*360/2/Math.PI,E<0&&(E+=360);let N=Math.sqrt(f*f+h*h);return[l,N,E]};zn.lch.lab=function(o){let l=o[0],f=o[1],E=o[2]/360*2*Math.PI,t=f*Math.cos(E),N=f*Math.sin(E);return[l,t,N]};zn.rgb.ansi16=function(o,l=null){let[f,h,E]=o,t=l===null?zn.rgb.hsv(o)[2]:l;if(t=Math.round(t/50),t===0)return 30;let N=30+(Math.round(E/255)<<2|Math.round(h/255)<<1|Math.round(f/255));return t===2&&(N+=60),N};zn.hsv.ansi16=function(o){return zn.rgb.ansi16(zn.hsv.rgb(o),o[2])};zn.rgb.ansi256=function(o){let l=o[0],f=o[1],h=o[2];return l===f&&f===h?l<8?16:l>248?231:Math.round((l-8)/247*24)+232:16+36*Math.round(l/255*5)+6*Math.round(f/255*5)+Math.round(h/255*5)};zn.ansi16.rgb=function(o){let l=o%10;if(l===0||l===7)return o>50&&(l+=3.5),l=l/10.5*255,[l,l,l];let f=(~~(o>50)+1)*.5,h=(l&1)*f*255,E=(l>>1&1)*f*255,t=(l>>2&1)*f*255;return[h,E,t]};zn.ansi256.rgb=function(o){if(o>=232){let t=(o-232)*10+8;return[t,t,t]}o-=16;let l,f=Math.floor(o/36)/5*255,h=Math.floor((l=o%36)/6)/5*255,E=l%6/5*255;return[f,h,E]};zn.rgb.hex=function(o){let f=(((Math.round(o[0])&255)<<16)+((Math.round(o[1])&255)<<8)+(Math.round(o[2])&255)).toString(16).toUpperCase();return"000000".substring(f.length)+f};zn.hex.rgb=function(o){let l=o.toString(16).match(/[a-f0-9]{6}|[a-f0-9]{3}/i);if(!l)return[0,0,0];let f=l[0];l[0].length===3&&(f=f.split("").map(F=>F+F).join(""));let h=parseInt(f,16),E=h>>16&255,t=h>>8&255,N=h&255;return[E,t,N]};zn.rgb.hcg=function(o){let l=o[0]/255,f=o[1]/255,h=o[2]/255,E=Math.max(Math.max(l,f),h),t=Math.min(Math.min(l,f),h),N=E-t,F,k;return N<1?F=t/(1-N):F=0,N<=0?k=0:E===l?k=(f-h)/N%6:E===f?k=2+(h-l)/N:k=4+(l-f)/N,k/=6,k%=1,[k*360,N*100,F*100]};zn.hsl.hcg=function(o){let l=o[1]/100,f=o[2]/100,h=f<.5?2*l*f:2*l*(1-f),E=0;return h<1&&(E=(f-.5*h)/(1-h)),[o[0],h*100,E*100]};zn.hsv.hcg=function(o){let l=o[1]/100,f=o[2]/100,h=l*f,E=0;return h<1&&(E=(f-h)/(1-h)),[o[0],h*100,E*100]};zn.hcg.rgb=function(o){let l=o[0]/360,f=o[1]/100,h=o[2]/100;if(f===0)return[h*255,h*255,h*255];let E=[0,0,0],t=l%1*6,N=t%1,F=1-N,k=0;switch(Math.floor(t)){case 0:E[0]=1,E[1]=N,E[2]=0;break;case 1:E[0]=F,E[1]=1,E[2]=0;break;case 2:E[0]=0,E[1]=1,E[2]=N;break;case 3:E[0]=0,E[1]=F,E[2]=1;break;case 4:E[0]=N,E[1]=0,E[2]=1;break;default:E[0]=1,E[1]=0,E[2]=F}return k=(1-f)*h,[(f*E[0]+k)*255,(f*E[1]+k)*255,(f*E[2]+k)*255]};zn.hcg.hsv=function(o){let l=o[1]/100,f=o[2]/100,h=l+f*(1-l),E=0;return h>0&&(E=l/h),[o[0],E*100,h*100]};zn.hcg.hsl=function(o){let l=o[1]/100,h=o[2]/100*(1-l)+.5*l,E=0;return h>0&&h<.5?E=l/(2*h):h>=.5&&h<1&&(E=l/(2*(1-h))),[o[0],E*100,h*100]};zn.hcg.hwb=function(o){let l=o[1]/100,f=o[2]/100,h=l+f*(1-l);return[o[0],(h-l)*100,(1-h)*100]};zn.hwb.hcg=function(o){let l=o[1]/100,h=1-o[2]/100,E=h-l,t=0;return E<1&&(t=(h-E)/(1-E)),[o[0],E*100,t*100]};zn.apple.rgb=function(o){return[o[0]/65535*255,o[1]/65535*255,o[2]/65535*255]};zn.rgb.apple=function(o){return[o[0]/255*65535,o[1]/255*65535,o[2]/255*65535]};zn.gray.rgb=function(o){return[o[0]/100*255,o[0]/100*255,o[0]/100*255]};zn.gray.hsl=function(o){return[0,0,o[0]]};zn.gray.hsv=zn.gray.hsl;zn.gray.hwb=function(o){return[0,100,o[0]]};zn.gray.cmyk=function(o){return[0,0,0,o[0]]};zn.gray.lab=function(o){return[o[0],0,0]};zn.gray.hex=function(o){let l=Math.round(o[0]/100*255)&255,h=((l<<16)+(l<<8)+l).toString(16).toUpperCase();return"000000".substring(h.length)+h};zn.rgb.gray=function(o){return[(o[0]+o[1]+o[2])/3/255*100]}});var yT=nt((IH,mT)=>{var W_=AD();function zP(){let o={},l=Object.keys(W_);for(let f=l.length,h=0;h{var OD=AD(),VP=yT(),Zv={},GP=Object.keys(OD);function YP(o){let l=function(...f){let h=f[0];return h==null?h:(h.length>1&&(f=h),o(f))};return"conversion"in o&&(l.conversion=o.conversion),l}function KP(o){let l=function(...f){let h=f[0];if(h==null)return h;h.length>1&&(f=h);let E=o(f);if(typeof E=="object")for(let t=E.length,N=0;N{Zv[o]={},Object.defineProperty(Zv[o],"channels",{value:OD[o].channels}),Object.defineProperty(Zv[o],"labels",{value:OD[o].labels});let l=VP(o);Object.keys(l).forEach(h=>{let E=l[h];Zv[o][h]=KP(E),Zv[o][h].raw=YP(E)})});gT.exports=Zv});var G_=nt((BH,TT)=>{"use strict";var ET=(o,l)=>(...f)=>`\x1B[${o(...f)+l}m`,DT=(o,l)=>(...f)=>{let h=o(...f);return`\x1B[${38+l};5;${h}m`},wT=(o,l)=>(...f)=>{let h=o(...f);return`\x1B[${38+l};2;${h[0]};${h[1]};${h[2]}m`},V_=o=>o,ST=(o,l,f)=>[o,l,f],$v=(o,l,f)=>{Object.defineProperty(o,l,{get:()=>{let h=f();return Object.defineProperty(o,l,{value:h,enumerable:!0,configurable:!0}),h},enumerable:!0,configurable:!0})},MD,em=(o,l,f,h)=>{MD===void 0&&(MD=_T());let E=h?10:0,t={};for(let[N,F]of Object.entries(MD)){let k=N==="ansi16"?"ansi":N;N===l?t[k]=o(f,E):typeof F=="object"&&(t[k]=o(F[l],E))}return t};function XP(){let o=new Map,l={modifier:{reset:[0,0],bold:[1,22],dim:[2,22],italic:[3,23],underline:[4,24],inverse:[7,27],hidden:[8,28],strikethrough:[9,29]},color:{black:[30,39],red:[31,39],green:[32,39],yellow:[33,39],blue:[34,39],magenta:[35,39],cyan:[36,39],white:[37,39],blackBright:[90,39],redBright:[91,39],greenBright:[92,39],yellowBright:[93,39],blueBright:[94,39],magentaBright:[95,39],cyanBright:[96,39],whiteBright:[97,39]},bgColor:{bgBlack:[40,49],bgRed:[41,49],bgGreen:[42,49],bgYellow:[43,49],bgBlue:[44,49],bgMagenta:[45,49],bgCyan:[46,49],bgWhite:[47,49],bgBlackBright:[100,49],bgRedBright:[101,49],bgGreenBright:[102,49],bgYellowBright:[103,49],bgBlueBright:[104,49],bgMagentaBright:[105,49],bgCyanBright:[106,49],bgWhiteBright:[107,49]}};l.color.gray=l.color.blackBright,l.bgColor.bgGray=l.bgColor.bgBlackBright,l.color.grey=l.color.blackBright,l.bgColor.bgGrey=l.bgColor.bgBlackBright;for(let[f,h]of Object.entries(l)){for(let[E,t]of Object.entries(h))l[E]={open:`\x1B[${t[0]}m`,close:`\x1B[${t[1]}m`},h[E]=l[E],o.set(t[0],t[1]);Object.defineProperty(l,f,{value:h,enumerable:!1})}return Object.defineProperty(l,"codes",{value:o,enumerable:!1}),l.color.close="\x1B[39m",l.bgColor.close="\x1B[49m",$v(l.color,"ansi",()=>em(ET,"ansi16",V_,!1)),$v(l.color,"ansi256",()=>em(DT,"ansi256",V_,!1)),$v(l.color,"ansi16m",()=>em(wT,"rgb",ST,!1)),$v(l.bgColor,"ansi",()=>em(ET,"ansi16",V_,!0)),$v(l.bgColor,"ansi256",()=>em(DT,"ansi256",V_,!0)),$v(l.bgColor,"ansi16m",()=>em(wT,"rgb",ST,!0)),l}Object.defineProperty(TT,"exports",{enumerable:!0,get:XP})});var RT=nt((UH,xT)=>{"use strict";var Jy=q_(),QP=DD(),JP=G_(),ND=new Set(["\x1B","\x9B"]),ZP=39,CT=o=>`${ND.values().next().value}[${o}m`,$P=o=>o.split(" ").map(l=>Jy(l)),kD=(o,l,f)=>{let h=[...l],E=!1,t=Jy(QP(o[o.length-1]));for(let[N,F]of h.entries()){let k=Jy(F);if(t+k<=f?o[o.length-1]+=F:(o.push(F),t=0),ND.has(F))E=!0;else if(E&&F==="m"){E=!1;continue}E||(t+=k,t===f&&N0&&o.length>1&&(o[o.length-2]+=o.pop())},eI=o=>{let l=o.split(" "),f=l.length;for(;f>0&&!(Jy(l[f-1])>0);)f--;return f===l.length?o:l.slice(0,f).join(" ")+l.slice(f).join("")},tI=(o,l,f={})=>{if(f.trim!==!1&&o.trim()==="")return"";let h="",E="",t,N=$P(o),F=[""];for(let[k,x]of o.split(" ").entries()){f.trim!==!1&&(F[F.length-1]=F[F.length-1].trimLeft());let j=Jy(F[F.length-1]);if(k!==0&&(j>=l&&(f.wordWrap===!1||f.trim===!1)&&(F.push(""),j=0),(j>0||f.trim===!1)&&(F[F.length-1]+=" ",j++)),f.hard&&N[k]>l){let q=l-j,V=1+Math.floor((N[k]-q-1)/l);Math.floor((N[k]-1)/l)l&&j>0&&N[k]>0){if(f.wordWrap===!1&&jl&&f.wordWrap===!1){kD(F,x,l);continue}F[F.length-1]+=x}f.trim!==!1&&(F=F.map(eI)),h=F.join(` +`);for(let[k,x]of[...h].entries()){if(E+=x,ND.has(x)){let q=parseFloat(/\d[^m]*/.exec(h.slice(k,k+4)));t=q===ZP?null:q}let j=JP.codes.get(Number(t));t&&j&&(h[k+1]===` +`?E+=CT(j):x===` +`&&(E+=CT(t)))}return E};xT.exports=(o,l,f)=>String(o).normalize().replace(/\r\n/g,` +`).split(` +`).map(h=>tI(h,l,f)).join(` +`)});var MT=nt((jH,OT)=>{"use strict";var AT="[\uD800-\uDBFF][\uDC00-\uDFFF]",nI=o=>o&&o.exact?new RegExp(`^${AT}$`):new RegExp(AT,"g");OT.exports=nI});var LD=nt((zH,FT)=>{"use strict";var rI=SD(),iI=MT(),kT=G_(),LT=["\x1B","\x9B"],Y_=o=>`${LT[0]}[${o}m`,NT=(o,l,f)=>{let h=[];o=[...o];for(let E of o){let t=E;E.match(";")&&(E=E.split(";")[0][0]+"0");let N=kT.codes.get(parseInt(E,10));if(N){let F=o.indexOf(N.toString());F>=0?o.splice(F,1):h.push(Y_(l?N:t))}else if(l){h.push(Y_(0));break}else h.push(Y_(t))}if(l&&(h=h.filter((E,t)=>h.indexOf(E)===t),f!==void 0)){let E=Y_(kT.codes.get(parseInt(f,10)));h=h.reduce((t,N)=>N===E?[N,...t]:[...t,N],[])}return h.join("")};FT.exports=(o,l,f)=>{let h=[...o.normalize()],E=[];f=typeof f=="number"?f:h.length;let t=!1,N,F=0,k="";for(let[x,j]of h.entries()){let q=!1;if(LT.includes(j)){let V=/\d[^m]*/.exec(o.slice(x,x+18));N=V&&V.length>0?V[0]:void 0,Fl&&F<=f)k+=j;else if(F===l&&!t&&N!==void 0)k=NT(E);else if(F>=f){k+=NT(E,!0,N);break}}return k}});var IT=nt((HH,PT)=>{"use strict";var c2=LD(),uI=q_();function K_(o,l,f){if(o.charAt(l)===" ")return l;for(let h=1;h<=3;h++)if(f){if(o.charAt(l+h)===" ")return l+h}else if(o.charAt(l-h)===" ")return l-h;return l}PT.exports=(o,l,f)=>{f={position:"end",preferTruncationOnSpace:!1,...f};let{position:h,space:E,preferTruncationOnSpace:t}=f,N="\u2026",F=1;if(typeof o!="string")throw new TypeError(`Expected \`input\` to be a string, got ${typeof o}`);if(typeof l!="number")throw new TypeError(`Expected \`columns\` to be a number, got ${typeof l}`);if(l<1)return"";if(l===1)return N;let k=uI(o);if(k<=l)return o;if(h==="start"){if(t){let x=K_(o,k-l+1,!0);return N+c2(o,x,k).trim()}return E===!0&&(N+=" ",F=2),N+c2(o,k-l+F,k)}if(h==="middle"){E===!0&&(N=" "+N+" ",F=3);let x=Math.floor(l/2);if(t){let j=K_(o,x),q=K_(o,k-(l-x)+1,!0);return c2(o,0,j)+N+c2(o,q,k).trim()}return c2(o,0,x)+N+c2(o,k-(l-x)+F,k)}if(h==="end"){if(t){let x=K_(o,l-1);return c2(o,0,x)+N}return E===!0&&(N=" "+N,F=2),c2(o,0,l-F)+N}throw new Error(`Expected \`options.position\` to be either \`start\`, \`middle\` or \`end\`, got ${h}`)}});var PD=nt(Zy=>{"use strict";var bT=Zy&&Zy.__importDefault||function(o){return o&&o.__esModule?o:{default:o}};Object.defineProperty(Zy,"__esModule",{value:!0});var oI=bT(RT()),lI=bT(IT()),FD={};Zy.default=(o,l,f)=>{let h=o+String(l)+String(f);if(FD[h])return FD[h];let E=o;if(f==="wrap"&&(E=oI.default(o,l,{trim:!1,hard:!0})),f.startsWith("truncate")){let t="end";f==="truncate-middle"&&(t="middle"),f==="truncate-start"&&(t="start"),E=lI.default(o,l,{position:t})}return FD[h]=E,E}});var bD=nt(ID=>{"use strict";Object.defineProperty(ID,"__esModule",{value:!0});var BT=o=>{let l="";if(o.childNodes.length>0)for(let f of o.childNodes){let h="";f.nodeName==="#text"?h=f.nodeValue:((f.nodeName==="ink-text"||f.nodeName==="ink-virtual-text")&&(h=BT(f)),h.length>0&&typeof f.internal_transform=="function"&&(h=f.internal_transform(h))),l+=h}return l};ID.default=BT});var BD=nt(f0=>{"use strict";var $y=f0&&f0.__importDefault||function(o){return o&&o.__esModule?o:{default:o}};Object.defineProperty(f0,"__esModule",{value:!0});f0.setTextNodeValue=f0.createTextNode=f0.setStyle=f0.setAttribute=f0.removeChildNode=f0.insertBeforeNode=f0.appendChildNode=f0.createNode=f0.TEXT_NAME=void 0;var sI=$y(eh()),UT=$y(fT()),aI=$y(cT()),fI=$y(PD()),cI=$y(bD());f0.TEXT_NAME="#text";f0.createNode=o=>{var l;let f={nodeName:o,style:{},attributes:{},childNodes:[],parentNode:null,yogaNode:o==="ink-virtual-text"?void 0:sI.default.Node.create()};return o==="ink-text"&&((l=f.yogaNode)===null||l===void 0||l.setMeasureFunc(dI.bind(null,f))),f};f0.appendChildNode=(o,l)=>{var f;l.parentNode&&f0.removeChildNode(l.parentNode,l),l.parentNode=o,o.childNodes.push(l),l.yogaNode&&((f=o.yogaNode)===null||f===void 0||f.insertChild(l.yogaNode,o.yogaNode.getChildCount())),(o.nodeName==="ink-text"||o.nodeName==="ink-virtual-text")&&X_(o)};f0.insertBeforeNode=(o,l,f)=>{var h,E;l.parentNode&&f0.removeChildNode(l.parentNode,l),l.parentNode=o;let t=o.childNodes.indexOf(f);if(t>=0){o.childNodes.splice(t,0,l),l.yogaNode&&((h=o.yogaNode)===null||h===void 0||h.insertChild(l.yogaNode,t));return}o.childNodes.push(l),l.yogaNode&&((E=o.yogaNode)===null||E===void 0||E.insertChild(l.yogaNode,o.yogaNode.getChildCount())),(o.nodeName==="ink-text"||o.nodeName==="ink-virtual-text")&&X_(o)};f0.removeChildNode=(o,l)=>{var f,h;l.yogaNode&&((h=(f=l.parentNode)===null||f===void 0?void 0:f.yogaNode)===null||h===void 0||h.removeChild(l.yogaNode)),l.parentNode=null;let E=o.childNodes.indexOf(l);E>=0&&o.childNodes.splice(E,1),(o.nodeName==="ink-text"||o.nodeName==="ink-virtual-text")&&X_(o)};f0.setAttribute=(o,l,f)=>{o.attributes[l]=f};f0.setStyle=(o,l)=>{o.style=l,o.yogaNode&&aI.default(o.yogaNode,l)};f0.createTextNode=o=>{let l={nodeName:"#text",nodeValue:o,yogaNode:void 0,parentNode:null,style:{}};return f0.setTextNodeValue(l,o),l};var dI=function(o,l){var f,h;let E=o.nodeName==="#text"?o.nodeValue:cI.default(o),t=UT.default(E);if(t.width<=l||t.width>=1&&l>0&&l<1)return t;let N=(h=(f=o.style)===null||f===void 0?void 0:f.textWrap)!==null&&h!==void 0?h:"wrap",F=fI.default(E,l,N);return UT.default(F)},jT=o=>{var l;if(!(!o||!o.parentNode))return(l=o.yogaNode)!==null&&l!==void 0?l:jT(o.parentNode)},X_=o=>{let l=jT(o);l==null||l.markDirty()};f0.setTextNodeValue=(o,l)=>{typeof l!="string"&&(l=String(l)),o.nodeValue=l,X_(o)}});var th=nt((GH,zT)=>{"use strict";zT.exports={BINARY_TYPES:["nodebuffer","arraybuffer","fragments"],GUID:"258EAFA5-E914-47DA-95CA-C5AB0DC85B11",kStatusCode:Symbol("status-code"),kWebSocket:Symbol("websocket"),EMPTY_BUFFER:Buffer.alloc(0),NOOP:()=>{}}});var eg=nt((YH,UD)=>{"use strict";var{EMPTY_BUFFER:pI}=th();function HT(o,l){if(o.length===0)return pI;if(o.length===1)return o[0];let f=Buffer.allocUnsafe(l),h=0;for(let E=0;E{"use strict";var GT=Symbol("kDone"),jD=Symbol("kRun"),zD=class{constructor(l){this[GT]=()=>{this.pending--,this[jD]()},this.concurrency=l||1/0,this.jobs=[],this.pending=0}add(l){this.jobs.push(l),this[jD]()}[jD](){if(this.pending!==this.concurrency&&this.jobs.length){let l=this.jobs.shift();this.pending++,l(this[GT])}}};YT.exports=zD});var rg=nt((XH,ZT)=>{"use strict";var tg=hi("zlib"),XT=eg(),hI=KT(),{kStatusCode:QT,NOOP:vI}=th(),mI=Buffer.from([0,0,255,255]),Z_=Symbol("permessage-deflate"),X1=Symbol("total-length"),ng=Symbol("callback"),d2=Symbol("buffers"),HD=Symbol("error"),J_,qD=class{constructor(l,f,h){if(this._maxPayload=h|0,this._options=l||{},this._threshold=this._options.threshold!==void 0?this._options.threshold:1024,this._isServer=!!f,this._deflate=null,this._inflate=null,this.params=null,!J_){let E=this._options.concurrencyLimit!==void 0?this._options.concurrencyLimit:10;J_=new hI(E)}}static get extensionName(){return"permessage-deflate"}offer(){let l={};return this._options.serverNoContextTakeover&&(l.server_no_context_takeover=!0),this._options.clientNoContextTakeover&&(l.client_no_context_takeover=!0),this._options.serverMaxWindowBits&&(l.server_max_window_bits=this._options.serverMaxWindowBits),this._options.clientMaxWindowBits?l.client_max_window_bits=this._options.clientMaxWindowBits:this._options.clientMaxWindowBits==null&&(l.client_max_window_bits=!0),l}accept(l){return l=this.normalizeParams(l),this.params=this._isServer?this.acceptAsServer(l):this.acceptAsClient(l),this.params}cleanup(){if(this._inflate&&(this._inflate.close(),this._inflate=null),this._deflate){let l=this._deflate[ng];this._deflate.close(),this._deflate=null,l&&l(new Error("The deflate stream was closed while data was being processed"))}}acceptAsServer(l){let f=this._options,h=l.find(E=>!(f.serverNoContextTakeover===!1&&E.server_no_context_takeover||E.server_max_window_bits&&(f.serverMaxWindowBits===!1||typeof f.serverMaxWindowBits=="number"&&f.serverMaxWindowBits>E.server_max_window_bits)||typeof f.clientMaxWindowBits=="number"&&!E.client_max_window_bits));if(!h)throw new Error("None of the extension offers can be accepted");return f.serverNoContextTakeover&&(h.server_no_context_takeover=!0),f.clientNoContextTakeover&&(h.client_no_context_takeover=!0),typeof f.serverMaxWindowBits=="number"&&(h.server_max_window_bits=f.serverMaxWindowBits),typeof f.clientMaxWindowBits=="number"?h.client_max_window_bits=f.clientMaxWindowBits:(h.client_max_window_bits===!0||f.clientMaxWindowBits===!1)&&delete h.client_max_window_bits,h}acceptAsClient(l){let f=l[0];if(this._options.clientNoContextTakeover===!1&&f.client_no_context_takeover)throw new Error('Unexpected parameter "client_no_context_takeover"');if(!f.client_max_window_bits)typeof this._options.clientMaxWindowBits=="number"&&(f.client_max_window_bits=this._options.clientMaxWindowBits);else if(this._options.clientMaxWindowBits===!1||typeof this._options.clientMaxWindowBits=="number"&&f.client_max_window_bits>this._options.clientMaxWindowBits)throw new Error('Unexpected or invalid parameter "client_max_window_bits"');return f}normalizeParams(l){return l.forEach(f=>{Object.keys(f).forEach(h=>{let E=f[h];if(E.length>1)throw new Error(`Parameter "${h}" must have only a single value`);if(E=E[0],h==="client_max_window_bits"){if(E!==!0){let t=+E;if(!Number.isInteger(t)||t<8||t>15)throw new TypeError(`Invalid value for parameter "${h}": ${E}`);E=t}else if(!this._isServer)throw new TypeError(`Invalid value for parameter "${h}": ${E}`)}else if(h==="server_max_window_bits"){let t=+E;if(!Number.isInteger(t)||t<8||t>15)throw new TypeError(`Invalid value for parameter "${h}": ${E}`);E=t}else if(h==="client_no_context_takeover"||h==="server_no_context_takeover"){if(E!==!0)throw new TypeError(`Invalid value for parameter "${h}": ${E}`)}else throw new Error(`Unknown parameter "${h}"`);f[h]=E})}),l}decompress(l,f,h){J_.add(E=>{this._decompress(l,f,(t,N)=>{E(),h(t,N)})})}compress(l,f,h){J_.add(E=>{this._compress(l,f,(t,N)=>{E(),h(t,N)})})}_decompress(l,f,h){let E=this._isServer?"client":"server";if(!this._inflate){let t=`${E}_max_window_bits`,N=typeof this.params[t]!="number"?tg.Z_DEFAULT_WINDOWBITS:this.params[t];this._inflate=tg.createInflateRaw({...this._options.zlibInflateOptions,windowBits:N}),this._inflate[Z_]=this,this._inflate[X1]=0,this._inflate[d2]=[],this._inflate.on("error",gI),this._inflate.on("data",JT)}this._inflate[ng]=h,this._inflate.write(l),f&&this._inflate.write(mI),this._inflate.flush(()=>{let t=this._inflate[HD];if(t){this._inflate.close(),this._inflate=null,h(t);return}let N=XT.concat(this._inflate[d2],this._inflate[X1]);this._inflate._readableState.endEmitted?(this._inflate.close(),this._inflate=null):(this._inflate[X1]=0,this._inflate[d2]=[],f&&this.params[`${E}_no_context_takeover`]&&this._inflate.reset()),h(null,N)})}_compress(l,f,h){let E=this._isServer?"server":"client";if(!this._deflate){let t=`${E}_max_window_bits`,N=typeof this.params[t]!="number"?tg.Z_DEFAULT_WINDOWBITS:this.params[t];this._deflate=tg.createDeflateRaw({...this._options.zlibDeflateOptions,windowBits:N}),this._deflate[X1]=0,this._deflate[d2]=[],this._deflate.on("error",vI),this._deflate.on("data",yI)}this._deflate[ng]=h,this._deflate.write(l),this._deflate.flush(tg.Z_SYNC_FLUSH,()=>{if(!this._deflate)return;let t=XT.concat(this._deflate[d2],this._deflate[X1]);f&&(t=t.slice(0,t.length-4)),this._deflate[ng]=null,this._deflate[X1]=0,this._deflate[d2]=[],f&&this.params[`${E}_no_context_takeover`]&&this._deflate.reset(),h(null,t)})}};ZT.exports=qD;function yI(o){this[d2].push(o),this[X1]+=o.length}function JT(o){if(this[X1]+=o.length,this[Z_]._maxPayload<1||this[X1]<=this[Z_]._maxPayload){this[d2].push(o);return}this[HD]=new RangeError("Max payload size exceeded"),this[HD][QT]=1009,this.removeListener("data",JT),this.reset()}function gI(o){this[Z_]._inflate=null,o[QT]=1007,this[ng](o)}});var VD=nt((QH,WD)=>{"use strict";function $T(o){return o>=1e3&&o<=1014&&o!==1004&&o!==1005&&o!==1006||o>=3e3&&o<=4999}function eC(o){let l=o.length,f=0;for(;f=l||(o[f+1]&192)!==128||(o[f+2]&192)!==128||o[f]===224&&(o[f+1]&224)===128||o[f]===237&&(o[f+1]&224)===160)return!1;f+=3}else if((o[f]&248)===240){if(f+3>=l||(o[f+1]&192)!==128||(o[f+2]&192)!==128||(o[f+3]&192)!==128||o[f]===240&&(o[f+1]&240)===128||o[f]===244&&o[f+1]>143||o[f]>244)return!1;f+=4}else return!1;return!0}try{let o=hi("utf-8-validate");typeof o=="object"&&(o=o.Validation.isValidUTF8),WD.exports={isValidStatusCode:$T,isValidUTF8(l){return l.length<150?eC(l):o(l)}}}catch{WD.exports={isValidStatusCode:$T,isValidUTF8:eC}}});var XD=nt((JH,oC)=>{"use strict";var{Writable:_I}=hi("stream"),tC=rg(),{BINARY_TYPES:EI,EMPTY_BUFFER:DI,kStatusCode:wI,kWebSocket:SI}=th(),{concat:GD,toArrayBuffer:TI,unmask:CI}=eg(),{isValidStatusCode:xI,isValidUTF8:nC}=VD(),ig=0,rC=1,iC=2,uC=3,YD=4,RI=5,KD=class extends _I{constructor(l,f,h,E){super(),this._binaryType=l||EI[0],this[SI]=void 0,this._extensions=f||{},this._isServer=!!h,this._maxPayload=E|0,this._bufferedBytes=0,this._buffers=[],this._compressed=!1,this._payloadLength=0,this._mask=void 0,this._fragmented=0,this._masked=!1,this._fin=!1,this._opcode=0,this._totalPayloadLength=0,this._messageLength=0,this._fragments=[],this._state=ig,this._loop=!1}_write(l,f,h){if(this._opcode===8&&this._state==ig)return h();this._bufferedBytes+=l.length,this._buffers.push(l),this.startLoop(h)}consume(l){if(this._bufferedBytes-=l,l===this._buffers[0].length)return this._buffers.shift();if(l=h.length?f.set(this._buffers.shift(),E):(f.set(new Uint8Array(h.buffer,h.byteOffset,l),E),this._buffers[0]=h.slice(l)),l-=h.length}while(l>0);return f}startLoop(l){let f;this._loop=!0;do switch(this._state){case ig:f=this.getInfo();break;case rC:f=this.getPayloadLength16();break;case iC:f=this.getPayloadLength64();break;case uC:this.getMask();break;case YD:f=this.getData(l);break;default:this._loop=!1;return}while(this._loop);l(f)}getInfo(){if(this._bufferedBytes<2){this._loop=!1;return}let l=this.consume(2);if((l[0]&48)!==0)return this._loop=!1,Ko(RangeError,"RSV2 and RSV3 must be clear",!0,1002);let f=(l[0]&64)===64;if(f&&!this._extensions[tC.extensionName])return this._loop=!1,Ko(RangeError,"RSV1 must be clear",!0,1002);if(this._fin=(l[0]&128)===128,this._opcode=l[0]&15,this._payloadLength=l[1]&127,this._opcode===0){if(f)return this._loop=!1,Ko(RangeError,"RSV1 must be clear",!0,1002);if(!this._fragmented)return this._loop=!1,Ko(RangeError,"invalid opcode 0",!0,1002);this._opcode=this._fragmented}else if(this._opcode===1||this._opcode===2){if(this._fragmented)return this._loop=!1,Ko(RangeError,`invalid opcode ${this._opcode}`,!0,1002);this._compressed=f}else if(this._opcode>7&&this._opcode<11){if(!this._fin)return this._loop=!1,Ko(RangeError,"FIN must be set",!0,1002);if(f)return this._loop=!1,Ko(RangeError,"RSV1 must be clear",!0,1002);if(this._payloadLength>125)return this._loop=!1,Ko(RangeError,`invalid payload length ${this._payloadLength}`,!0,1002)}else return this._loop=!1,Ko(RangeError,`invalid opcode ${this._opcode}`,!0,1002);if(!this._fin&&!this._fragmented&&(this._fragmented=this._opcode),this._masked=(l[1]&128)===128,this._isServer){if(!this._masked)return this._loop=!1,Ko(RangeError,"MASK must be set",!0,1002)}else if(this._masked)return this._loop=!1,Ko(RangeError,"MASK must be clear",!0,1002);if(this._payloadLength===126)this._state=rC;else if(this._payloadLength===127)this._state=iC;else return this.haveLength()}getPayloadLength16(){if(this._bufferedBytes<2){this._loop=!1;return}return this._payloadLength=this.consume(2).readUInt16BE(0),this.haveLength()}getPayloadLength64(){if(this._bufferedBytes<8){this._loop=!1;return}let l=this.consume(8),f=l.readUInt32BE(0);return f>Math.pow(2,53-32)-1?(this._loop=!1,Ko(RangeError,"Unsupported WebSocket frame: payload length > 2^53 - 1",!1,1009)):(this._payloadLength=f*Math.pow(2,32)+l.readUInt32BE(4),this.haveLength())}haveLength(){if(this._payloadLength&&this._opcode<8&&(this._totalPayloadLength+=this._payloadLength,this._totalPayloadLength>this._maxPayload&&this._maxPayload>0))return this._loop=!1,Ko(RangeError,"Max payload size exceeded",!1,1009);this._masked?this._state=uC:this._state=YD}getMask(){if(this._bufferedBytes<4){this._loop=!1;return}this._mask=this.consume(4),this._state=YD}getData(l){let f=DI;if(this._payloadLength){if(this._bufferedBytes7)return this.controlMessage(f);if(this._compressed){this._state=RI,this.decompress(f,l);return}return f.length&&(this._messageLength=this._totalPayloadLength,this._fragments.push(f)),this.dataMessage()}decompress(l,f){this._extensions[tC.extensionName].decompress(l,this._fin,(E,t)=>{if(E)return f(E);if(t.length){if(this._messageLength+=t.length,this._messageLength>this._maxPayload&&this._maxPayload>0)return f(Ko(RangeError,"Max payload size exceeded",!1,1009));this._fragments.push(t)}let N=this.dataMessage();if(N)return f(N);this.startLoop(f)})}dataMessage(){if(this._fin){let l=this._messageLength,f=this._fragments;if(this._totalPayloadLength=0,this._messageLength=0,this._fragmented=0,this._fragments=[],this._opcode===2){let h;this._binaryType==="nodebuffer"?h=GD(f,l):this._binaryType==="arraybuffer"?h=TI(GD(f,l)):h=f,this.emit("message",h)}else{let h=GD(f,l);if(!nC(h))return this._loop=!1,Ko(Error,"invalid UTF-8 sequence",!0,1007);this.emit("message",h.toString())}}this._state=ig}controlMessage(l){if(this._opcode===8)if(this._loop=!1,l.length===0)this.emit("conclude",1005,""),this.end();else{if(l.length===1)return Ko(RangeError,"invalid payload length 1",!0,1002);{let f=l.readUInt16BE(0);if(!xI(f))return Ko(RangeError,`invalid status code ${f}`,!0,1002);let h=l.slice(2);if(!nC(h))return Ko(Error,"invalid UTF-8 sequence",!0,1007);this.emit("conclude",f,h.toString()),this.end()}}else this._opcode===9?this.emit("ping",l):this.emit("pong",l);this._state=ig}};oC.exports=KD;function Ko(o,l,f,h){let E=new o(f?`Invalid WebSocket frame: ${l}`:l);return Error.captureStackTrace(E,Ko),E[wI]=h,E}});var QD=nt((ZH,aC)=>{"use strict";var{randomFillSync:AI}=hi("crypto"),lC=rg(),{EMPTY_BUFFER:OI}=th(),{isValidStatusCode:MI}=VD(),{mask:sC,toBuffer:Q1}=eg(),nh=Buffer.alloc(4),jc=class{constructor(l,f){this._extensions=f||{},this._socket=l,this._firstFragment=!0,this._compress=!1,this._bufferedBytes=0,this._deflating=!1,this._queue=[]}static frame(l,f){let h=f.mask&&f.readOnly,E=f.mask?6:2,t=l.length;l.length>=65536?(E+=8,t=127):l.length>125&&(E+=2,t=126);let N=Buffer.allocUnsafe(h?l.length+E:E);return N[0]=f.fin?f.opcode|128:f.opcode,f.rsv1&&(N[0]|=64),N[1]=t,t===126?N.writeUInt16BE(l.length,2):t===127&&(N.writeUInt32BE(0,2),N.writeUInt32BE(l.length,6)),f.mask?(AI(nh,0,4),N[1]|=128,N[E-4]=nh[0],N[E-3]=nh[1],N[E-2]=nh[2],N[E-1]=nh[3],h?(sC(l,nh,N,E,l.length),[N]):(sC(l,nh,l,0,l.length),[N,l])):[N,l]}close(l,f,h,E){let t;if(l===void 0)t=OI;else{if(typeof l!="number"||!MI(l))throw new TypeError("First argument must be a valid error code number");if(f===void 0||f==="")t=Buffer.allocUnsafe(2),t.writeUInt16BE(l,0);else{let N=Buffer.byteLength(f);if(N>123)throw new RangeError("The message must not be greater than 123 bytes");t=Buffer.allocUnsafe(2+N),t.writeUInt16BE(l,0),t.write(f,2)}}this._deflating?this.enqueue([this.doClose,t,h,E]):this.doClose(t,h,E)}doClose(l,f,h){this.sendFrame(jc.frame(l,{fin:!0,rsv1:!1,opcode:8,mask:f,readOnly:!1}),h)}ping(l,f,h){let E=Q1(l);if(E.length>125)throw new RangeError("The data size must not be greater than 125 bytes");this._deflating?this.enqueue([this.doPing,E,f,Q1.readOnly,h]):this.doPing(E,f,Q1.readOnly,h)}doPing(l,f,h,E){this.sendFrame(jc.frame(l,{fin:!0,rsv1:!1,opcode:9,mask:f,readOnly:h}),E)}pong(l,f,h){let E=Q1(l);if(E.length>125)throw new RangeError("The data size must not be greater than 125 bytes");this._deflating?this.enqueue([this.doPong,E,f,Q1.readOnly,h]):this.doPong(E,f,Q1.readOnly,h)}doPong(l,f,h,E){this.sendFrame(jc.frame(l,{fin:!0,rsv1:!1,opcode:10,mask:f,readOnly:h}),E)}send(l,f,h){let E=Q1(l),t=this._extensions[lC.extensionName],N=f.binary?2:1,F=f.compress;if(this._firstFragment?(this._firstFragment=!1,F&&t&&(F=E.length>=t._threshold),this._compress=F):(F=!1,N=0),f.fin&&(this._firstFragment=!0),t){let k={fin:f.fin,rsv1:F,opcode:N,mask:f.mask,readOnly:Q1.readOnly};this._deflating?this.enqueue([this.dispatch,E,this._compress,k,h]):this.dispatch(E,this._compress,k,h)}else this.sendFrame(jc.frame(E,{fin:f.fin,rsv1:!1,opcode:N,mask:f.mask,readOnly:Q1.readOnly}),h)}dispatch(l,f,h,E){if(!f){this.sendFrame(jc.frame(l,h),E);return}let t=this._extensions[lC.extensionName];this._bufferedBytes+=l.length,this._deflating=!0,t.compress(l,h.fin,(N,F)=>{if(this._socket.destroyed){let k=new Error("The socket was closed while data was being compressed");typeof E=="function"&&E(k);for(let x=0;x{"use strict";var tm=class{constructor(l,f){this.target=f,this.type=l}},JD=class extends tm{constructor(l,f){super("message",f),this.data=l}},ZD=class extends tm{constructor(l,f,h){super("close",h),this.wasClean=h._closeFrameReceived&&h._closeFrameSent,this.reason=f,this.code=l}},$D=class extends tm{constructor(l){super("open",l)}},e3=class extends tm{constructor(l,f){super("error",f),this.message=l.message,this.error=l}},kI={addEventListener(o,l,f){if(typeof l!="function")return;function h(k){l.call(this,new JD(k,this))}function E(k,x){l.call(this,new ZD(k,x,this))}function t(k){l.call(this,new e3(k,this))}function N(){l.call(this,new $D(this))}let F=f&&f.once?"once":"on";o==="message"?(h._listener=l,this[F](o,h)):o==="close"?(E._listener=l,this[F](o,E)):o==="error"?(t._listener=l,this[F](o,t)):o==="open"?(N._listener=l,this[F](o,N)):this[F](o,l)},removeEventListener(o,l){let f=this.listeners(o);for(let h=0;h{"use strict";var ug=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,1,1,1,0,0,1,1,0,1,1,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,1,0];function zc(o,l,f){o[l]===void 0?o[l]=[f]:o[l].push(f)}function NI(o){let l=Object.create(null);if(o===void 0||o==="")return l;let f=Object.create(null),h=!1,E=!1,t=!1,N,F,k=-1,x=-1,j=0;for(;j{let f=o[l];return Array.isArray(f)||(f=[f]),f.map(h=>[l].concat(Object.keys(h).map(E=>{let t=h[E];return Array.isArray(t)||(t=[t]),t.map(N=>N===!0?E:`${E}=${N}`).join("; ")})).join("; ")).join(", ")}).join(", ")}dC.exports={format:LI,parse:NI}});var o3=nt((tq,wC)=>{"use strict";var FI=hi("events"),PI=hi("https"),II=hi("http"),vC=hi("net"),bI=hi("tls"),{randomBytes:BI,createHash:UI}=hi("crypto"),{URL:n3}=hi("url"),p2=rg(),jI=XD(),zI=QD(),{BINARY_TYPES:pC,EMPTY_BUFFER:r3,GUID:HI,kStatusCode:qI,kWebSocket:ta,NOOP:mC}=th(),{addEventListener:WI,removeEventListener:VI}=cC(),{format:GI,parse:YI}=t3(),{toBuffer:KI}=eg(),yC=["CONNECTING","OPEN","CLOSING","CLOSED"],i3=[8,13],XI=30*1e3,ji=class extends FI{constructor(l,f,h){super(),this._binaryType=pC[0],this._closeCode=1006,this._closeFrameReceived=!1,this._closeFrameSent=!1,this._closeMessage="",this._closeTimer=null,this._extensions={},this._protocol="",this._readyState=ji.CONNECTING,this._receiver=null,this._sender=null,this._socket=null,l!==null?(this._bufferedAmount=0,this._isServer=!1,this._redirects=0,Array.isArray(f)?f=f.join(", "):typeof f=="object"&&f!==null&&(h=f,f=void 0),gC(this,l,f,h)):this._isServer=!0}get binaryType(){return this._binaryType}set binaryType(l){!pC.includes(l)||(this._binaryType=l,this._receiver&&(this._receiver._binaryType=l))}get bufferedAmount(){return this._socket?this._socket._writableState.length+this._sender._bufferedBytes:this._bufferedAmount}get extensions(){return Object.keys(this._extensions).join()}get protocol(){return this._protocol}get readyState(){return this._readyState}get url(){return this._url}setSocket(l,f,h){let E=new jI(this.binaryType,this._extensions,this._isServer,h);this._sender=new zI(l,this._extensions),this._receiver=E,this._socket=l,E[ta]=this,l[ta]=this,E.on("conclude",ZI),E.on("drain",$I),E.on("error",eb),E.on("message",tb),E.on("ping",nb),E.on("pong",rb),l.setTimeout(0),l.setNoDelay(),f.length>0&&l.unshift(f),l.on("close",_C),l.on("data",$_),l.on("end",EC),l.on("error",DC),this._readyState=ji.OPEN,this.emit("open")}emitClose(){if(!this._socket){this._readyState=ji.CLOSED,this.emit("close",this._closeCode,this._closeMessage);return}this._extensions[p2.extensionName]&&this._extensions[p2.extensionName].cleanup(),this._receiver.removeAllListeners(),this._readyState=ji.CLOSED,this.emit("close",this._closeCode,this._closeMessage)}close(l,f){if(this.readyState!==ji.CLOSED){if(this.readyState===ji.CONNECTING){let h="WebSocket was closed before the connection was established";return J1(this,this._req,h)}if(this.readyState===ji.CLOSING){this._closeFrameSent&&this._closeFrameReceived&&this._socket.end();return}this._readyState=ji.CLOSING,this._sender.close(l,f,!this._isServer,h=>{h||(this._closeFrameSent=!0,this._closeFrameReceived&&this._socket.end())}),this._closeTimer=setTimeout(this._socket.destroy.bind(this._socket),XI)}}ping(l,f,h){if(this.readyState===ji.CONNECTING)throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");if(typeof l=="function"?(h=l,l=f=void 0):typeof f=="function"&&(h=f,f=void 0),typeof l=="number"&&(l=l.toString()),this.readyState!==ji.OPEN){u3(this,l,h);return}f===void 0&&(f=!this._isServer),this._sender.ping(l||r3,f,h)}pong(l,f,h){if(this.readyState===ji.CONNECTING)throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");if(typeof l=="function"?(h=l,l=f=void 0):typeof f=="function"&&(h=f,f=void 0),typeof l=="number"&&(l=l.toString()),this.readyState!==ji.OPEN){u3(this,l,h);return}f===void 0&&(f=!this._isServer),this._sender.pong(l||r3,f,h)}send(l,f,h){if(this.readyState===ji.CONNECTING)throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");if(typeof f=="function"&&(h=f,f={}),typeof l=="number"&&(l=l.toString()),this.readyState!==ji.OPEN){u3(this,l,h);return}let E={binary:typeof l!="string",mask:!this._isServer,compress:!0,fin:!0,...f};this._extensions[p2.extensionName]||(E.compress=!1),this._sender.send(l||r3,E,h)}terminate(){if(this.readyState!==ji.CLOSED){if(this.readyState===ji.CONNECTING){let l="WebSocket was closed before the connection was established";return J1(this,this._req,l)}this._socket&&(this._readyState=ji.CLOSING,this._socket.destroy())}}};yC.forEach((o,l)=>{let f={enumerable:!0,value:l};Object.defineProperty(ji.prototype,o,f),Object.defineProperty(ji,o,f)});["binaryType","bufferedAmount","extensions","protocol","readyState","url"].forEach(o=>{Object.defineProperty(ji.prototype,o,{enumerable:!0})});["open","error","close","message"].forEach(o=>{Object.defineProperty(ji.prototype,`on${o}`,{configurable:!0,enumerable:!0,get(){let l=this.listeners(o);for(let f=0;f{J1(o,V,"Opening handshake has timed out")}),V.on("error",re=>{V===null||V.aborted||(V=o._req=null,o._readyState=ji.CLOSING,o.emit("error",re),o.emitClose())}),V.on("response",re=>{let y=re.headers.location,me=re.statusCode;if(y&&E.followRedirects&&me>=300&&me<400){if(++o._redirects>E.maxRedirects){J1(o,V,"Maximum redirects exceeded");return}V.abort();let De=new n3(y,l);gC(o,De,f,h)}else o.emit("unexpected-response",V,re)||J1(o,V,`Unexpected server response: ${re.statusCode}`)}),V.on("upgrade",(re,y,me)=>{if(o.emit("upgrade",re),o.readyState!==ji.CONNECTING)return;V=o._req=null;let De=UI("sha1").update(x+HI).digest("base64");if(re.headers["sec-websocket-accept"]!==De){J1(o,y,"Invalid Sec-WebSocket-Accept header");return}let ge=re.headers["sec-websocket-protocol"],ae=(f||"").split(/, */),we;if(!f&&ge?we="Server sent a subprotocol but none was requested":f&&!ge?we="Server sent no subprotocol":ge&&!ae.includes(ge)&&(we="Server sent an invalid subprotocol"),we){J1(o,y,we);return}if(ge&&(o._protocol=ge),q)try{let he=YI(re.headers["sec-websocket-extensions"]);he[p2.extensionName]&&(q.accept(he[p2.extensionName]),o._extensions[p2.extensionName]=q)}catch{J1(o,y,"Invalid Sec-WebSocket-Extensions header");return}o.setSocket(y,me,E.maxPayload)})}function QI(o){return o.path=o.socketPath,vC.connect(o)}function JI(o){return o.path=void 0,!o.servername&&o.servername!==""&&(o.servername=vC.isIP(o.host)?"":o.host),bI.connect(o)}function J1(o,l,f){o._readyState=ji.CLOSING;let h=new Error(f);Error.captureStackTrace(h,J1),l.setHeader?(l.abort(),l.socket&&!l.socket.destroyed&&l.socket.destroy(),l.once("abort",o.emitClose.bind(o)),o.emit("error",h)):(l.destroy(h),l.once("error",o.emit.bind(o,"error")),l.once("close",o.emitClose.bind(o)))}function u3(o,l,f){if(l){let h=KI(l).length;o._socket?o._sender._bufferedBytes+=h:o._bufferedAmount+=h}if(f){let h=new Error(`WebSocket is not open: readyState ${o.readyState} (${yC[o.readyState]})`);f(h)}}function ZI(o,l){let f=this[ta];f._socket.removeListener("data",$_),f._socket.resume(),f._closeFrameReceived=!0,f._closeMessage=l,f._closeCode=o,o===1005?f.close():f.close(o,l)}function $I(){this[ta]._socket.resume()}function eb(o){let l=this[ta];l._socket.removeListener("data",$_),l._readyState=ji.CLOSING,l._closeCode=o[qI],l.emit("error",o),l._socket.destroy()}function hC(){this[ta].emitClose()}function tb(o){this[ta].emit("message",o)}function nb(o){let l=this[ta];l.pong(o,!l._isServer,mC),l.emit("ping",o)}function rb(o){this[ta].emit("pong",o)}function _C(){let o=this[ta];this.removeListener("close",_C),this.removeListener("end",EC),o._readyState=ji.CLOSING,o._socket.read(),o._receiver.end(),this.removeListener("data",$_),this[ta]=void 0,clearTimeout(o._closeTimer),o._receiver._writableState.finished||o._receiver._writableState.errorEmitted?o.emitClose():(o._receiver.on("error",hC),o._receiver.on("finish",hC))}function $_(o){this[ta]._receiver.write(o)||this.pause()}function EC(){let o=this[ta];o._readyState=ji.CLOSING,o._receiver.end(),this.end()}function DC(){let o=this[ta];this.removeListener("error",DC),this.on("error",mC),o&&(o._readyState=ji.CLOSING,this.destroy())}});var xC=nt((nq,CC)=>{"use strict";var{Duplex:ib}=hi("stream");function SC(o){o.emit("close")}function ub(){!this.destroyed&&this._writableState.finished&&this.destroy()}function TC(o){this.removeListener("error",TC),this.destroy(),this.listenerCount("error")===0&&this.emit("error",o)}function ob(o,l){let f=!0;function h(){f&&o._socket.resume()}o.readyState===o.CONNECTING?o.once("open",function(){o._receiver.removeAllListeners("drain"),o._receiver.on("drain",h)}):(o._receiver.removeAllListeners("drain"),o._receiver.on("drain",h));let E=new ib({...l,autoDestroy:!1,emitClose:!1,objectMode:!1,writableObjectMode:!1});return o.on("message",function(N){E.push(N)||(f=!1,o._socket.pause())}),o.once("error",function(N){E.destroyed||E.destroy(N)}),o.once("close",function(){E.destroyed||E.push(null)}),E._destroy=function(t,N){if(o.readyState===o.CLOSED){N(t),process.nextTick(SC,E);return}let F=!1;o.once("error",function(x){F=!0,N(x)}),o.once("close",function(){F||N(t),process.nextTick(SC,E)}),o.terminate()},E._final=function(t){if(o.readyState===o.CONNECTING){o.once("open",function(){E._final(t)});return}o._socket!==null&&(o._socket._writableState.finished?(t(),E._readableState.endEmitted&&E.destroy()):(o._socket.once("finish",function(){t()}),o.close()))},E._read=function(){o.readyState===o.OPEN&&!f&&(f=!0,o._receiver._writableState.needDrain||o._socket.resume())},E._write=function(t,N,F){if(o.readyState===o.CONNECTING){o.once("open",function(){E._write(t,N,F)});return}o.send(t,F)},E.on("end",ub),E.on("error",TC),E}CC.exports=ob});var AC=nt((rq,RC)=>{"use strict";var lb=hi("events"),{createHash:sb}=hi("crypto"),{createServer:ab,STATUS_CODES:l3}=hi("http"),rh=rg(),fb=o3(),{format:db,parse:pb}=t3(),{GUID:hb,kWebSocket:vb}=th(),mb=/^[+/0-9A-Za-z]{22}==$/,s3=class extends lb{constructor(l,f){if(super(),l={maxPayload:100*1024*1024,perMessageDeflate:!1,handleProtocols:null,clientTracking:!0,verifyClient:null,noServer:!1,backlog:null,server:null,host:null,path:null,port:null,...l},l.port==null&&!l.server&&!l.noServer)throw new TypeError('One of the "port", "server", or "noServer" options must be specified');if(l.port!=null?(this._server=ab((h,E)=>{let t=l3[426];E.writeHead(426,{"Content-Length":t.length,"Content-Type":"text/plain"}),E.end(t)}),this._server.listen(l.port,l.host,l.backlog,f)):l.server&&(this._server=l.server),this._server){let h=this.emit.bind(this,"connection");this._removeListeners=yb(this._server,{listening:this.emit.bind(this,"listening"),error:this.emit.bind(this,"error"),upgrade:(E,t,N)=>{this.handleUpgrade(E,t,N,h)}})}l.perMessageDeflate===!0&&(l.perMessageDeflate={}),l.clientTracking&&(this.clients=new Set),this.options=l}address(){if(this.options.noServer)throw new Error('The server is operating in "noServer" mode');return this._server?this._server.address():null}close(l){if(l&&this.once("close",l),this.clients)for(let h of this.clients)h.terminate();let f=this._server;if(f&&(this._removeListeners(),this._removeListeners=this._server=null,this.options.port!=null)){f.close(()=>this.emit("close"));return}process.nextTick(gb,this)}shouldHandle(l){if(this.options.path){let f=l.url.indexOf("?");if((f!==-1?l.url.slice(0,f):l.url)!==this.options.path)return!1}return!0}handleUpgrade(l,f,h,E){f.on("error",a3);let t=l.headers["sec-websocket-key"]!==void 0?l.headers["sec-websocket-key"].trim():!1,N=+l.headers["sec-websocket-version"],F={};if(l.method!=="GET"||l.headers.upgrade.toLowerCase()!=="websocket"||!t||!mb.test(t)||N!==8&&N!==13||!this.shouldHandle(l))return e4(f,400);if(this.options.perMessageDeflate){let k=new rh(this.options.perMessageDeflate,!0,this.options.maxPayload);try{let x=pb(l.headers["sec-websocket-extensions"]);x[rh.extensionName]&&(k.accept(x[rh.extensionName]),F[rh.extensionName]=k)}catch{return e4(f,400)}}if(this.options.verifyClient){let k={origin:l.headers[`${N===8?"sec-websocket-origin":"origin"}`],secure:!!(l.socket.authorized||l.socket.encrypted),req:l};if(this.options.verifyClient.length===2){this.options.verifyClient(k,(x,j,q,V)=>{if(!x)return e4(f,j||401,q,V);this.completeUpgrade(t,F,l,f,h,E)});return}if(!this.options.verifyClient(k))return e4(f,401)}this.completeUpgrade(t,F,l,f,h,E)}completeUpgrade(l,f,h,E,t,N){if(!E.readable||!E.writable)return E.destroy();if(E[vb])throw new Error("server.handleUpgrade() was called more than once with the same socket, possibly due to a misconfiguration");let k=["HTTP/1.1 101 Switching Protocols","Upgrade: websocket","Connection: Upgrade",`Sec-WebSocket-Accept: ${sb("sha1").update(l+hb).digest("base64")}`],x=new fb(null),j=h.headers["sec-websocket-protocol"];if(j&&(j=j.split(",").map(_b),this.options.handleProtocols?j=this.options.handleProtocols(j,h):j=j[0],j&&(k.push(`Sec-WebSocket-Protocol: ${j}`),x._protocol=j)),f[rh.extensionName]){let q=f[rh.extensionName].params,V=db({[rh.extensionName]:[q]});k.push(`Sec-WebSocket-Extensions: ${V}`),x._extensions=f}this.emit("headers",k,h),E.write(k.concat(`\r +`).join(`\r +`)),E.removeListener("error",a3),x.setSocket(E,t,this.options.maxPayload),this.clients&&(this.clients.add(x),x.on("close",()=>this.clients.delete(x))),N(x,h)}};RC.exports=s3;function yb(o,l){for(let f of Object.keys(l))o.on(f,l[f]);return function(){for(let h of Object.keys(l))o.removeListener(h,l[h])}}function gb(o){o.emit("close")}function a3(){this.destroy()}function e4(o,l,f,h){o.writable&&(f=f||l3[l],h={Connection:"close","Content-Type":"text/html","Content-Length":Buffer.byteLength(f),...h},o.write(`HTTP/1.1 ${l} ${l3[l]}\r +`+Object.keys(h).map(E=>`${E}: ${h[E]}`).join(`\r +`)+`\r +\r +`+f)),o.removeListener("error",a3),o.destroy()}function _b(o){return o.trim()}});var MC=nt((iq,OC)=>{"use strict";var og=o3();og.createWebSocketStream=xC();og.Server=AC();og.Receiver=XD();og.Sender=QD();OC.exports=og});var kC=nt(t4=>{"use strict";var Eb=t4&&t4.__importDefault||function(o){return o&&o.__esModule?o:{default:o}};Object.defineProperty(t4,"__esModule",{value:!0});var Db=Eb(MC()),lg=global;lg.WebSocket||(lg.WebSocket=Db.default);lg.window||(lg.window=global);lg.window.__REACT_DEVTOOLS_COMPONENT_FILTERS__=[{type:1,value:7,isEnabled:!0},{type:2,value:"InternalApp",isEnabled:!0,isValid:!0},{type:2,value:"InternalAppContext",isEnabled:!0,isValid:!0},{type:2,value:"InternalStdoutContext",isEnabled:!0,isValid:!0},{type:2,value:"InternalStderrContext",isEnabled:!0,isValid:!0},{type:2,value:"InternalStdinContext",isEnabled:!0,isValid:!0},{type:2,value:"InternalFocusContext",isEnabled:!0,isValid:!0}]});var NC=nt((n4,f3)=>{(function(o,l){typeof n4=="object"&&typeof f3=="object"?f3.exports=l():typeof define=="function"&&define.amd?define([],l):typeof n4=="object"?n4.ReactDevToolsBackend=l():o.ReactDevToolsBackend=l()})(window,function(){return function(o){var l={};function f(h){if(l[h])return l[h].exports;var E=l[h]={i:h,l:!1,exports:{}};return o[h].call(E.exports,E,E.exports,f),E.l=!0,E.exports}return f.m=o,f.c=l,f.d=function(h,E,t){f.o(h,E)||Object.defineProperty(h,E,{enumerable:!0,get:t})},f.r=function(h){typeof Symbol<"u"&&Symbol.toStringTag&&Object.defineProperty(h,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(h,"__esModule",{value:!0})},f.t=function(h,E){if(1&E&&(h=f(h)),8&E||4&E&&typeof h=="object"&&h&&h.__esModule)return h;var t=Object.create(null);if(f.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:h}),2&E&&typeof h!="string")for(var N in h)f.d(t,N,function(F){return h[F]}.bind(null,N));return t},f.n=function(h){var E=h&&h.__esModule?function(){return h.default}:function(){return h};return f.d(E,"a",E),E},f.o=function(h,E){return Object.prototype.hasOwnProperty.call(h,E)},f.p="",f(f.s=20)}([function(o,l,f){"use strict";o.exports=f(12)},function(o,l,f){"use strict";var h=Object.getOwnPropertySymbols,E=Object.prototype.hasOwnProperty,t=Object.prototype.propertyIsEnumerable;function N(F){if(F==null)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(F)}o.exports=function(){try{if(!Object.assign)return!1;var F=new String("abc");if(F[5]="de",Object.getOwnPropertyNames(F)[0]==="5")return!1;for(var k={},x=0;x<10;x++)k["_"+String.fromCharCode(x)]=x;if(Object.getOwnPropertyNames(k).map(function(q){return k[q]}).join("")!=="0123456789")return!1;var j={};return"abcdefghijklmnopqrst".split("").forEach(function(q){j[q]=q}),Object.keys(Object.assign({},j)).join("")==="abcdefghijklmnopqrst"}catch{return!1}}()?Object.assign:function(F,k){for(var x,j,q=N(F),V=1;V"u"?"undefined":E(self))=="object"&&self&&self.Object===Object&&self,V=j||q||Function("return this")(),re=Object.prototype.toString,y=Math.max,me=Math.min,De=function(){return V.Date.now()};function ge(ve,ue,Ae){var ze,We,gt,_t,Qe,ot,Ve=0,Pt=!1,Jt=!1,it=!0;if(typeof ve!="function")throw new TypeError("Expected a function");function J(At){var nn=ze,an=We;return ze=We=void 0,Ve=At,_t=ve.apply(an,nn)}function ce(At){return Ve=At,Qe=setTimeout(le,ue),Pt?J(At):_t}function Re(At){var nn=At-ot;return ot===void 0||nn>=ue||nn<0||Jt&&At-Ve>=gt}function le(){var At=De();if(Re(At))return He(At);Qe=setTimeout(le,function(nn){var an=ue-(nn-ot);return Jt?me(an,gt-(nn-Ve)):an}(At))}function He(At){return Qe=void 0,it&&ze?J(At):(ze=We=void 0,_t)}function dt(){var At=De(),nn=Re(At);if(ze=arguments,We=this,ot=At,nn){if(Qe===void 0)return ce(ot);if(Jt)return Qe=setTimeout(le,ue),J(ot)}return Qe===void 0&&(Qe=setTimeout(le,ue)),_t}return ue=he(ue)||0,ae(Ae)&&(Pt=!!Ae.leading,gt=(Jt="maxWait"in Ae)?y(he(Ae.maxWait)||0,ue):gt,it="trailing"in Ae?!!Ae.trailing:it),dt.cancel=function(){Qe!==void 0&&clearTimeout(Qe),Ve=0,ze=ot=We=Qe=void 0},dt.flush=function(){return Qe===void 0?_t:He(De())},dt}function ae(ve){var ue=E(ve);return!!ve&&(ue=="object"||ue=="function")}function we(ve){return E(ve)=="symbol"||function(ue){return!!ue&&E(ue)=="object"}(ve)&&re.call(ve)=="[object Symbol]"}function he(ve){if(typeof ve=="number")return ve;if(we(ve))return NaN;if(ae(ve)){var ue=typeof ve.valueOf=="function"?ve.valueOf():ve;ve=ae(ue)?ue+"":ue}if(typeof ve!="string")return ve===0?ve:+ve;ve=ve.replace(t,"");var Ae=F.test(ve);return Ae||k.test(ve)?x(ve.slice(2),Ae?2:8):N.test(ve)?NaN:+ve}o.exports=function(ve,ue,Ae){var ze=!0,We=!0;if(typeof ve!="function")throw new TypeError("Expected a function");return ae(Ae)&&(ze="leading"in Ae?!!Ae.leading:ze,We="trailing"in Ae?!!Ae.trailing:We),ge(ve,ue,{leading:ze,maxWait:ue,trailing:We})}}).call(this,f(4))},function(o,l,f){(function(h){function E(J){return(E=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(ce){return typeof ce}:function(ce){return ce&&typeof Symbol=="function"&&ce.constructor===Symbol&&ce!==Symbol.prototype?"symbol":typeof ce})(J)}var t;l=o.exports=y,t=(h===void 0?"undefined":E(h))==="object"&&h.env&&h.env.NODE_DEBUG&&/\bsemver\b/i.test(h.env.NODE_DEBUG)?function(){var J=Array.prototype.slice.call(arguments,0);J.unshift("SEMVER"),console.log.apply(console,J)}:function(){},l.SEMVER_SPEC_VERSION="2.0.0";var N=Number.MAX_SAFE_INTEGER||9007199254740991,F=l.re=[],k=l.src=[],x=l.tokens={},j=0;function q(J){x[J]=j++}q("NUMERICIDENTIFIER"),k[x.NUMERICIDENTIFIER]="0|[1-9]\\d*",q("NUMERICIDENTIFIERLOOSE"),k[x.NUMERICIDENTIFIERLOOSE]="[0-9]+",q("NONNUMERICIDENTIFIER"),k[x.NONNUMERICIDENTIFIER]="\\d*[a-zA-Z-][a-zA-Z0-9-]*",q("MAINVERSION"),k[x.MAINVERSION]="("+k[x.NUMERICIDENTIFIER]+")\\.("+k[x.NUMERICIDENTIFIER]+")\\.("+k[x.NUMERICIDENTIFIER]+")",q("MAINVERSIONLOOSE"),k[x.MAINVERSIONLOOSE]="("+k[x.NUMERICIDENTIFIERLOOSE]+")\\.("+k[x.NUMERICIDENTIFIERLOOSE]+")\\.("+k[x.NUMERICIDENTIFIERLOOSE]+")",q("PRERELEASEIDENTIFIER"),k[x.PRERELEASEIDENTIFIER]="(?:"+k[x.NUMERICIDENTIFIER]+"|"+k[x.NONNUMERICIDENTIFIER]+")",q("PRERELEASEIDENTIFIERLOOSE"),k[x.PRERELEASEIDENTIFIERLOOSE]="(?:"+k[x.NUMERICIDENTIFIERLOOSE]+"|"+k[x.NONNUMERICIDENTIFIER]+")",q("PRERELEASE"),k[x.PRERELEASE]="(?:-("+k[x.PRERELEASEIDENTIFIER]+"(?:\\."+k[x.PRERELEASEIDENTIFIER]+")*))",q("PRERELEASELOOSE"),k[x.PRERELEASELOOSE]="(?:-?("+k[x.PRERELEASEIDENTIFIERLOOSE]+"(?:\\."+k[x.PRERELEASEIDENTIFIERLOOSE]+")*))",q("BUILDIDENTIFIER"),k[x.BUILDIDENTIFIER]="[0-9A-Za-z-]+",q("BUILD"),k[x.BUILD]="(?:\\+("+k[x.BUILDIDENTIFIER]+"(?:\\."+k[x.BUILDIDENTIFIER]+")*))",q("FULL"),q("FULLPLAIN"),k[x.FULLPLAIN]="v?"+k[x.MAINVERSION]+k[x.PRERELEASE]+"?"+k[x.BUILD]+"?",k[x.FULL]="^"+k[x.FULLPLAIN]+"$",q("LOOSEPLAIN"),k[x.LOOSEPLAIN]="[v=\\s]*"+k[x.MAINVERSIONLOOSE]+k[x.PRERELEASELOOSE]+"?"+k[x.BUILD]+"?",q("LOOSE"),k[x.LOOSE]="^"+k[x.LOOSEPLAIN]+"$",q("GTLT"),k[x.GTLT]="((?:<|>)?=?)",q("XRANGEIDENTIFIERLOOSE"),k[x.XRANGEIDENTIFIERLOOSE]=k[x.NUMERICIDENTIFIERLOOSE]+"|x|X|\\*",q("XRANGEIDENTIFIER"),k[x.XRANGEIDENTIFIER]=k[x.NUMERICIDENTIFIER]+"|x|X|\\*",q("XRANGEPLAIN"),k[x.XRANGEPLAIN]="[v=\\s]*("+k[x.XRANGEIDENTIFIER]+")(?:\\.("+k[x.XRANGEIDENTIFIER]+")(?:\\.("+k[x.XRANGEIDENTIFIER]+")(?:"+k[x.PRERELEASE]+")?"+k[x.BUILD]+"?)?)?",q("XRANGEPLAINLOOSE"),k[x.XRANGEPLAINLOOSE]="[v=\\s]*("+k[x.XRANGEIDENTIFIERLOOSE]+")(?:\\.("+k[x.XRANGEIDENTIFIERLOOSE]+")(?:\\.("+k[x.XRANGEIDENTIFIERLOOSE]+")(?:"+k[x.PRERELEASELOOSE]+")?"+k[x.BUILD]+"?)?)?",q("XRANGE"),k[x.XRANGE]="^"+k[x.GTLT]+"\\s*"+k[x.XRANGEPLAIN]+"$",q("XRANGELOOSE"),k[x.XRANGELOOSE]="^"+k[x.GTLT]+"\\s*"+k[x.XRANGEPLAINLOOSE]+"$",q("COERCE"),k[x.COERCE]="(^|[^\\d])(\\d{1,16})(?:\\.(\\d{1,16}))?(?:\\.(\\d{1,16}))?(?:$|[^\\d])",q("COERCERTL"),F[x.COERCERTL]=new RegExp(k[x.COERCE],"g"),q("LONETILDE"),k[x.LONETILDE]="(?:~>?)",q("TILDETRIM"),k[x.TILDETRIM]="(\\s*)"+k[x.LONETILDE]+"\\s+",F[x.TILDETRIM]=new RegExp(k[x.TILDETRIM],"g"),q("TILDE"),k[x.TILDE]="^"+k[x.LONETILDE]+k[x.XRANGEPLAIN]+"$",q("TILDELOOSE"),k[x.TILDELOOSE]="^"+k[x.LONETILDE]+k[x.XRANGEPLAINLOOSE]+"$",q("LONECARET"),k[x.LONECARET]="(?:\\^)",q("CARETTRIM"),k[x.CARETTRIM]="(\\s*)"+k[x.LONECARET]+"\\s+",F[x.CARETTRIM]=new RegExp(k[x.CARETTRIM],"g"),q("CARET"),k[x.CARET]="^"+k[x.LONECARET]+k[x.XRANGEPLAIN]+"$",q("CARETLOOSE"),k[x.CARETLOOSE]="^"+k[x.LONECARET]+k[x.XRANGEPLAINLOOSE]+"$",q("COMPARATORLOOSE"),k[x.COMPARATORLOOSE]="^"+k[x.GTLT]+"\\s*("+k[x.LOOSEPLAIN]+")$|^$",q("COMPARATOR"),k[x.COMPARATOR]="^"+k[x.GTLT]+"\\s*("+k[x.FULLPLAIN]+")$|^$",q("COMPARATORTRIM"),k[x.COMPARATORTRIM]="(\\s*)"+k[x.GTLT]+"\\s*("+k[x.LOOSEPLAIN]+"|"+k[x.XRANGEPLAIN]+")",F[x.COMPARATORTRIM]=new RegExp(k[x.COMPARATORTRIM],"g"),q("HYPHENRANGE"),k[x.HYPHENRANGE]="^\\s*("+k[x.XRANGEPLAIN]+")\\s+-\\s+("+k[x.XRANGEPLAIN]+")\\s*$",q("HYPHENRANGELOOSE"),k[x.HYPHENRANGELOOSE]="^\\s*("+k[x.XRANGEPLAINLOOSE]+")\\s+-\\s+("+k[x.XRANGEPLAINLOOSE]+")\\s*$",q("STAR"),k[x.STAR]="(<|>)?=?\\s*\\*";for(var V=0;V256||!(ce.loose?F[x.LOOSE]:F[x.FULL]).test(J))return null;try{return new y(J,ce)}catch{return null}}function y(J,ce){if(ce&&E(ce)==="object"||(ce={loose:!!ce,includePrerelease:!1}),J instanceof y){if(J.loose===ce.loose)return J;J=J.version}else if(typeof J!="string")throw new TypeError("Invalid Version: "+J);if(J.length>256)throw new TypeError("version is longer than 256 characters");if(!(this instanceof y))return new y(J,ce);t("SemVer",J,ce),this.options=ce,this.loose=!!ce.loose;var Re=J.trim().match(ce.loose?F[x.LOOSE]:F[x.FULL]);if(!Re)throw new TypeError("Invalid Version: "+J);if(this.raw=J,this.major=+Re[1],this.minor=+Re[2],this.patch=+Re[3],this.major>N||this.major<0)throw new TypeError("Invalid major version");if(this.minor>N||this.minor<0)throw new TypeError("Invalid minor version");if(this.patch>N||this.patch<0)throw new TypeError("Invalid patch version");Re[4]?this.prerelease=Re[4].split(".").map(function(le){if(/^[0-9]+$/.test(le)){var He=+le;if(He>=0&&He=0;)typeof this.prerelease[Re]=="number"&&(this.prerelease[Re]++,Re=-2);Re===-1&&this.prerelease.push(0)}ce&&(this.prerelease[0]===ce?isNaN(this.prerelease[1])&&(this.prerelease=[ce,0]):this.prerelease=[ce,0]);break;default:throw new Error("invalid increment argument: "+J)}return this.format(),this.raw=this.version,this},l.inc=function(J,ce,Re,le){typeof Re=="string"&&(le=Re,Re=void 0);try{return new y(J,Re).inc(ce,le).version}catch{return null}},l.diff=function(J,ce){if(he(J,ce))return null;var Re=re(J),le=re(ce),He="";if(Re.prerelease.length||le.prerelease.length){He="pre";var dt="prerelease"}for(var At in Re)if((At==="major"||At==="minor"||At==="patch")&&Re[At]!==le[At])return He+At;return dt},l.compareIdentifiers=De;var me=/^[0-9]+$/;function De(J,ce){var Re=me.test(J),le=me.test(ce);return Re&&le&&(J=+J,ce=+ce),J===ce?0:Re&&!le?-1:le&&!Re?1:J0}function we(J,ce,Re){return ge(J,ce,Re)<0}function he(J,ce,Re){return ge(J,ce,Re)===0}function ve(J,ce,Re){return ge(J,ce,Re)!==0}function ue(J,ce,Re){return ge(J,ce,Re)>=0}function Ae(J,ce,Re){return ge(J,ce,Re)<=0}function ze(J,ce,Re,le){switch(ce){case"===":return E(J)==="object"&&(J=J.version),E(Re)==="object"&&(Re=Re.version),J===Re;case"!==":return E(J)==="object"&&(J=J.version),E(Re)==="object"&&(Re=Re.version),J!==Re;case"":case"=":case"==":return he(J,Re,le);case"!=":return ve(J,Re,le);case">":return ae(J,Re,le);case">=":return ue(J,Re,le);case"<":return we(J,Re,le);case"<=":return Ae(J,Re,le);default:throw new TypeError("Invalid operator: "+ce)}}function We(J,ce){if(ce&&E(ce)==="object"||(ce={loose:!!ce,includePrerelease:!1}),J instanceof We){if(J.loose===!!ce.loose)return J;J=J.value}if(!(this instanceof We))return new We(J,ce);t("comparator",J,ce),this.options=ce,this.loose=!!ce.loose,this.parse(J),this.semver===gt?this.value="":this.value=this.operator+this.semver.version,t("comp",this)}l.rcompareIdentifiers=function(J,ce){return De(ce,J)},l.major=function(J,ce){return new y(J,ce).major},l.minor=function(J,ce){return new y(J,ce).minor},l.patch=function(J,ce){return new y(J,ce).patch},l.compare=ge,l.compareLoose=function(J,ce){return ge(J,ce,!0)},l.compareBuild=function(J,ce,Re){var le=new y(J,Re),He=new y(ce,Re);return le.compare(He)||le.compareBuild(He)},l.rcompare=function(J,ce,Re){return ge(ce,J,Re)},l.sort=function(J,ce){return J.sort(function(Re,le){return l.compareBuild(Re,le,ce)})},l.rsort=function(J,ce){return J.sort(function(Re,le){return l.compareBuild(le,Re,ce)})},l.gt=ae,l.lt=we,l.eq=he,l.neq=ve,l.gte=ue,l.lte=Ae,l.cmp=ze,l.Comparator=We;var gt={};function _t(J,ce){if(ce&&E(ce)==="object"||(ce={loose:!!ce,includePrerelease:!1}),J instanceof _t)return J.loose===!!ce.loose&&J.includePrerelease===!!ce.includePrerelease?J:new _t(J.raw,ce);if(J instanceof We)return new _t(J.value,ce);if(!(this instanceof _t))return new _t(J,ce);if(this.options=ce,this.loose=!!ce.loose,this.includePrerelease=!!ce.includePrerelease,this.raw=J,this.set=J.split(/\s*\|\|\s*/).map(function(Re){return this.parseRange(Re.trim())},this).filter(function(Re){return Re.length}),!this.set.length)throw new TypeError("Invalid SemVer Range: "+J);this.format()}function Qe(J,ce){for(var Re=!0,le=J.slice(),He=le.pop();Re&&le.length;)Re=le.every(function(dt){return He.intersects(dt,ce)}),He=le.pop();return Re}function ot(J){return!J||J.toLowerCase()==="x"||J==="*"}function Ve(J,ce,Re,le,He,dt,At,nn,an,On,lr,ln,Vt){return((ce=ot(Re)?"":ot(le)?">="+Re+".0.0":ot(He)?">="+Re+"."+le+".0":">="+ce)+" "+(nn=ot(an)?"":ot(On)?"<"+(+an+1)+".0.0":ot(lr)?"<"+an+"."+(+On+1)+".0":ln?"<="+an+"."+On+"."+lr+"-"+ln:"<="+nn)).trim()}function Pt(J,ce,Re){for(var le=0;le0){var He=J[le].semver;if(He.major===ce.major&&He.minor===ce.minor&&He.patch===ce.patch)return!0}return!1}return!0}function Jt(J,ce,Re){try{ce=new _t(ce,Re)}catch{return!1}return ce.test(J)}function it(J,ce,Re,le){var He,dt,At,nn,an;switch(J=new y(J,le),ce=new _t(ce,le),Re){case">":He=ae,dt=Ae,At=we,nn=">",an=">=";break;case"<":He=we,dt=ue,At=ae,nn="<",an="<=";break;default:throw new TypeError('Must provide a hilo val of "<" or ">"')}if(Jt(J,ce,le))return!1;for(var On=0;On=0.0.0")),ln=ln||Er,Vt=Vt||Er,He(Er.semver,ln.semver,le)?ln=Er:At(Er.semver,Vt.semver,le)&&(Vt=Er)}),ln.operator===nn||ln.operator===an||(!Vt.operator||Vt.operator===nn)&&dt(J,Vt.semver)||Vt.operator===an&&At(J,Vt.semver))return!1}return!0}We.prototype.parse=function(J){var ce=this.options.loose?F[x.COMPARATORLOOSE]:F[x.COMPARATOR],Re=J.match(ce);if(!Re)throw new TypeError("Invalid comparator: "+J);this.operator=Re[1]!==void 0?Re[1]:"",this.operator==="="&&(this.operator=""),Re[2]?this.semver=new y(Re[2],this.options.loose):this.semver=gt},We.prototype.toString=function(){return this.value},We.prototype.test=function(J){if(t("Comparator.test",J,this.options.loose),this.semver===gt||J===gt)return!0;if(typeof J=="string")try{J=new y(J,this.options)}catch{return!1}return ze(J,this.operator,this.semver,this.options)},We.prototype.intersects=function(J,ce){if(!(J instanceof We))throw new TypeError("a Comparator is required");var Re;if(ce&&E(ce)==="object"||(ce={loose:!!ce,includePrerelease:!1}),this.operator==="")return this.value===""||(Re=new _t(J.value,ce),Jt(this.value,Re,ce));if(J.operator==="")return J.value===""||(Re=new _t(this.value,ce),Jt(J.semver,Re,ce));var le=!(this.operator!==">="&&this.operator!==">"||J.operator!==">="&&J.operator!==">"),He=!(this.operator!=="<="&&this.operator!=="<"||J.operator!=="<="&&J.operator!=="<"),dt=this.semver.version===J.semver.version,At=!(this.operator!==">="&&this.operator!=="<="||J.operator!==">="&&J.operator!=="<="),nn=ze(this.semver,"<",J.semver,ce)&&(this.operator===">="||this.operator===">")&&(J.operator==="<="||J.operator==="<"),an=ze(this.semver,">",J.semver,ce)&&(this.operator==="<="||this.operator==="<")&&(J.operator===">="||J.operator===">");return le||He||dt&&At||nn||an},l.Range=_t,_t.prototype.format=function(){return this.range=this.set.map(function(J){return J.join(" ").trim()}).join("||").trim(),this.range},_t.prototype.toString=function(){return this.range},_t.prototype.parseRange=function(J){var ce=this.options.loose;J=J.trim();var Re=ce?F[x.HYPHENRANGELOOSE]:F[x.HYPHENRANGE];J=J.replace(Re,Ve),t("hyphen replace",J),J=J.replace(F[x.COMPARATORTRIM],"$1$2$3"),t("comparator trim",J,F[x.COMPARATORTRIM]),J=(J=(J=J.replace(F[x.TILDETRIM],"$1~")).replace(F[x.CARETTRIM],"$1^")).split(/\s+/).join(" ");var le=ce?F[x.COMPARATORLOOSE]:F[x.COMPARATOR],He=J.split(" ").map(function(dt){return function(At,nn){return t("comp",At,nn),At=function(an,On){return an.trim().split(/\s+/).map(function(lr){return function(ln,Vt){t("caret",ln,Vt);var Er=Vt.loose?F[x.CARETLOOSE]:F[x.CARET];return ln.replace(Er,function(S,zt,Xn,vr,jr){var fr;return t("caret",ln,S,zt,Xn,vr,jr),ot(zt)?fr="":ot(Xn)?fr=">="+zt+".0.0 <"+(+zt+1)+".0.0":ot(vr)?fr=zt==="0"?">="+zt+"."+Xn+".0 <"+zt+"."+(+Xn+1)+".0":">="+zt+"."+Xn+".0 <"+(+zt+1)+".0.0":jr?(t("replaceCaret pr",jr),fr=zt==="0"?Xn==="0"?">="+zt+"."+Xn+"."+vr+"-"+jr+" <"+zt+"."+Xn+"."+(+vr+1):">="+zt+"."+Xn+"."+vr+"-"+jr+" <"+zt+"."+(+Xn+1)+".0":">="+zt+"."+Xn+"."+vr+"-"+jr+" <"+(+zt+1)+".0.0"):(t("no pr"),fr=zt==="0"?Xn==="0"?">="+zt+"."+Xn+"."+vr+" <"+zt+"."+Xn+"."+(+vr+1):">="+zt+"."+Xn+"."+vr+" <"+zt+"."+(+Xn+1)+".0":">="+zt+"."+Xn+"."+vr+" <"+(+zt+1)+".0.0"),t("caret return",fr),fr})}(lr,On)}).join(" ")}(At,nn),t("caret",At),At=function(an,On){return an.trim().split(/\s+/).map(function(lr){return function(ln,Vt){var Er=Vt.loose?F[x.TILDELOOSE]:F[x.TILDE];return ln.replace(Er,function(S,zt,Xn,vr,jr){var fr;return t("tilde",ln,S,zt,Xn,vr,jr),ot(zt)?fr="":ot(Xn)?fr=">="+zt+".0.0 <"+(+zt+1)+".0.0":ot(vr)?fr=">="+zt+"."+Xn+".0 <"+zt+"."+(+Xn+1)+".0":jr?(t("replaceTilde pr",jr),fr=">="+zt+"."+Xn+"."+vr+"-"+jr+" <"+zt+"."+(+Xn+1)+".0"):fr=">="+zt+"."+Xn+"."+vr+" <"+zt+"."+(+Xn+1)+".0",t("tilde return",fr),fr})}(lr,On)}).join(" ")}(At,nn),t("tildes",At),At=function(an,On){return t("replaceXRanges",an,On),an.split(/\s+/).map(function(lr){return function(ln,Vt){ln=ln.trim();var Er=Vt.loose?F[x.XRANGELOOSE]:F[x.XRANGE];return ln.replace(Er,function(S,zt,Xn,vr,jr,fr){t("xRange",ln,S,zt,Xn,vr,jr,fr);var zr=ot(Xn),Xt=zr||ot(vr),Du=Xt||ot(jr),c0=Du;return zt==="="&&c0&&(zt=""),fr=Vt.includePrerelease?"-0":"",zr?S=zt===">"||zt==="<"?"<0.0.0-0":"*":zt&&c0?(Xt&&(vr=0),jr=0,zt===">"?(zt=">=",Xt?(Xn=+Xn+1,vr=0,jr=0):(vr=+vr+1,jr=0)):zt==="<="&&(zt="<",Xt?Xn=+Xn+1:vr=+vr+1),S=zt+Xn+"."+vr+"."+jr+fr):Xt?S=">="+Xn+".0.0"+fr+" <"+(+Xn+1)+".0.0"+fr:Du&&(S=">="+Xn+"."+vr+".0"+fr+" <"+Xn+"."+(+vr+1)+".0"+fr),t("xRange return",S),S})}(lr,On)}).join(" ")}(At,nn),t("xrange",At),At=function(an,On){return t("replaceStars",an,On),an.trim().replace(F[x.STAR],"")}(At,nn),t("stars",At),At}(dt,this.options)},this).join(" ").split(/\s+/);return this.options.loose&&(He=He.filter(function(dt){return!!dt.match(le)})),He=He.map(function(dt){return new We(dt,this.options)},this)},_t.prototype.intersects=function(J,ce){if(!(J instanceof _t))throw new TypeError("a Range is required");return this.set.some(function(Re){return Qe(Re,ce)&&J.set.some(function(le){return Qe(le,ce)&&Re.every(function(He){return le.every(function(dt){return He.intersects(dt,ce)})})})})},l.toComparators=function(J,ce){return new _t(J,ce).set.map(function(Re){return Re.map(function(le){return le.value}).join(" ").trim().split(" ")})},_t.prototype.test=function(J){if(!J)return!1;if(typeof J=="string")try{J=new y(J,this.options)}catch{return!1}for(var ce=0;ce":dt.prerelease.length===0?dt.patch++:dt.prerelease.push(0),dt.raw=dt.format();case"":case">=":Re&&!ae(Re,dt)||(Re=dt);break;case"<":case"<=":break;default:throw new Error("Unexpected operation: "+He.operator)}});return Re&&J.test(Re)?Re:null},l.validRange=function(J,ce){try{return new _t(J,ce).range||"*"}catch{return null}},l.ltr=function(J,ce,Re){return it(J,ce,"<",Re)},l.gtr=function(J,ce,Re){return it(J,ce,">",Re)},l.outside=it,l.prerelease=function(J,ce){var Re=re(J,ce);return Re&&Re.prerelease.length?Re.prerelease:null},l.intersects=function(J,ce,Re){return J=new _t(J,Re),ce=new _t(ce,Re),J.intersects(ce)},l.coerce=function(J,ce){if(J instanceof y)return J;if(typeof J=="number"&&(J=String(J)),typeof J!="string")return null;var Re=null;if((ce=ce||{}).rtl){for(var le;(le=F[x.COERCERTL].exec(J))&&(!Re||Re.index+Re[0].length!==J.length);)Re&&le.index+le[0].length===Re.index+Re[0].length||(Re=le),F[x.COERCERTL].lastIndex=le.index+le[1].length+le[2].length;F[x.COERCERTL].lastIndex=-1}else Re=J.match(F[x.COERCE]);return Re===null?null:re(Re[2]+"."+(Re[3]||"0")+"."+(Re[4]||"0"),ce)}}).call(this,f(5))},function(o,l){function f(E){return(f=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(t){return typeof t}:function(t){return t&&typeof Symbol=="function"&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(E)}var h;h=function(){return this}();try{h=h||new Function("return this")()}catch{(typeof window>"u"?"undefined":f(window))==="object"&&(h=window)}o.exports=h},function(o,l){var f,h,E=o.exports={};function t(){throw new Error("setTimeout has not been defined")}function N(){throw new Error("clearTimeout has not been defined")}function F(De){if(f===setTimeout)return setTimeout(De,0);if((f===t||!f)&&setTimeout)return f=setTimeout,setTimeout(De,0);try{return f(De,0)}catch{try{return f.call(null,De,0)}catch{return f.call(this,De,0)}}}(function(){try{f=typeof setTimeout=="function"?setTimeout:t}catch{f=t}try{h=typeof clearTimeout=="function"?clearTimeout:N}catch{h=N}})();var k,x=[],j=!1,q=-1;function V(){j&&k&&(j=!1,k.length?x=k.concat(x):q=-1,x.length&&re())}function re(){if(!j){var De=F(V);j=!0;for(var ge=x.length;ge;){for(k=x,x=[];++q1)for(var ae=1;aethis[N])return ve(this,this[y].get(Qe)),!1;var it=this[y].get(Qe).value;return this[q]&&(this[V]||this[q](Qe,it.value)),it.now=Pt,it.maxAge=Ve,it.value=ot,this[F]+=Jt-it.length,it.length=Jt,this.get(Qe),he(this),!0}var J=new ue(Qe,ot,Jt,Pt,Ve);return J.length>this[N]?(this[q]&&this[q](Qe,ot),!1):(this[F]+=J.length,this[re].unshift(J),this[y].set(Qe,this[re].head),he(this),!0)}},{key:"has",value:function(Qe){if(!this[y].has(Qe))return!1;var ot=this[y].get(Qe).value;return!we(this,ot)}},{key:"get",value:function(Qe){return ae(this,Qe,!0)}},{key:"peek",value:function(Qe){return ae(this,Qe,!1)}},{key:"pop",value:function(){var Qe=this[re].tail;return Qe?(ve(this,Qe),Qe.value):null}},{key:"del",value:function(Qe){ve(this,this[y].get(Qe))}},{key:"load",value:function(Qe){this.reset();for(var ot=Date.now(),Ve=Qe.length-1;Ve>=0;Ve--){var Pt=Qe[Ve],Jt=Pt.e||0;if(Jt===0)this.set(Pt.k,Pt.v);else{var it=Jt-ot;it>0&&this.set(Pt.k,Pt.v,it)}}}},{key:"prune",value:function(){var Qe=this;this[y].forEach(function(ot,Ve){return ae(Qe,Ve,!1)})}},{key:"max",set:function(Qe){if(typeof Qe!="number"||Qe<0)throw new TypeError("max must be a non-negative number");this[N]=Qe||1/0,he(this)},get:function(){return this[N]}},{key:"allowStale",set:function(Qe){this[x]=!!Qe},get:function(){return this[x]}},{key:"maxAge",set:function(Qe){if(typeof Qe!="number")throw new TypeError("maxAge must be a non-negative number");this[j]=Qe,he(this)},get:function(){return this[j]}},{key:"lengthCalculator",set:function(Qe){var ot=this;typeof Qe!="function"&&(Qe=De),Qe!==this[k]&&(this[k]=Qe,this[F]=0,this[re].forEach(function(Ve){Ve.length=ot[k](Ve.value,Ve.key),ot[F]+=Ve.length})),he(this)},get:function(){return this[k]}},{key:"length",get:function(){return this[F]}},{key:"itemCount",get:function(){return this[re].length}}])&&E(We.prototype,gt),_t&&E(We,_t),ze}(),ae=function(ze,We,gt){var _t=ze[y].get(We);if(_t){var Qe=_t.value;if(we(ze,Qe)){if(ve(ze,_t),!ze[x])return}else gt&&(ze[me]&&(_t.value.now=Date.now()),ze[re].unshiftNode(_t));return Qe.value}},we=function(ze,We){if(!We||!We.maxAge&&!ze[j])return!1;var gt=Date.now()-We.now;return We.maxAge?gt>We.maxAge:ze[j]&>>ze[j]},he=function(ze){if(ze[F]>ze[N])for(var We=ze[re].tail;ze[F]>ze[N]&&We!==null;){var gt=We.prev;ve(ze,We),We=gt}},ve=function(ze,We){if(We){var gt=We.value;ze[q]&&ze[q](gt.key,gt.value),ze[F]-=gt.length,ze[y].delete(gt.key),ze[re].removeNode(We)}},ue=function ze(We,gt,_t,Qe,ot){h(this,ze),this.key=We,this.value=gt,this.length=_t,this.now=Qe,this.maxAge=ot||0},Ae=function(ze,We,gt,_t){var Qe=gt.value;we(ze,Qe)&&(ve(ze,gt),ze[x]||(Qe=void 0)),Qe&&We.call(_t,Qe.value,Qe.key,ze)};o.exports=ge},function(o,l,f){(function(h){function E(t){return(E=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(N){return typeof N}:function(N){return N&&typeof Symbol=="function"&&N.constructor===Symbol&&N!==Symbol.prototype?"symbol":typeof N})(t)}o.exports=function(){if(typeof document>"u"||!document.addEventListener)return null;var t,N,F,k={};return k.copy=function(){var x=!1,j=null,q=!1;function V(){x=!1,j=null,q&&window.getSelection().removeAllRanges(),q=!1}return document.addEventListener("copy",function(re){if(x){for(var y in j)re.clipboardData.setData(y,j[y]);re.preventDefault()}}),function(re){return new Promise(function(y,me){x=!0,typeof re=="string"?j={"text/plain":re}:re instanceof Node?j={"text/html":new XMLSerializer().serializeToString(re)}:re instanceof Object?j=re:me("Invalid data type. Must be string, DOM node, or an object mapping MIME types to strings."),function De(ge){try{if(document.execCommand("copy"))V(),y();else{if(ge)throw V(),new Error("Unable to copy. Perhaps it's not available in your browser?");(function(){var ae=document.getSelection();if(!document.queryCommandEnabled("copy")&&ae.isCollapsed){var we=document.createRange();we.selectNodeContents(document.body),ae.removeAllRanges(),ae.addRange(we),q=!0}})(),De(!0)}}catch(ae){V(),me(ae)}}(!1)})}}(),k.paste=(F=!1,document.addEventListener("paste",function(x){if(F){F=!1,x.preventDefault();var j=t;t=null,j(x.clipboardData.getData(N))}}),function(x){return new Promise(function(j,q){F=!0,t=j,N=x||"text/plain";try{document.execCommand("paste")||(F=!1,q(new Error("Unable to paste. Pasting only works in Internet Explorer at the moment.")))}catch(V){F=!1,q(new Error(V))}})}),typeof ClipboardEvent>"u"&&window.clipboardData!==void 0&&window.clipboardData.setData!==void 0&&(function(x){function j(he,ve){return function(){he.apply(ve,arguments)}}function q(he){if(E(this)!="object")throw new TypeError("Promises must be constructed via new");if(typeof he!="function")throw new TypeError("not a function");this._state=null,this._value=null,this._deferreds=[],ge(he,j(re,this),j(y,this))}function V(he){var ve=this;return this._state===null?void this._deferreds.push(he):void ae(function(){var ue=ve._state?he.onFulfilled:he.onRejected;if(ue!==null){var Ae;try{Ae=ue(ve._value)}catch(ze){return void he.reject(ze)}he.resolve(Ae)}else(ve._state?he.resolve:he.reject)(ve._value)})}function re(he){try{if(he===this)throw new TypeError("A promise cannot be resolved with itself.");if(he&&(E(he)=="object"||typeof he=="function")){var ve=he.then;if(typeof ve=="function")return void ge(j(ve,he),j(re,this),j(y,this))}this._state=!0,this._value=he,me.call(this)}catch(ue){y.call(this,ue)}}function y(he){this._state=!1,this._value=he,me.call(this)}function me(){for(var he=0,ve=this._deferreds.length;ve>he;he++)V.call(this,this._deferreds[he]);this._deferreds=null}function De(he,ve,ue,Ae){this.onFulfilled=typeof he=="function"?he:null,this.onRejected=typeof ve=="function"?ve:null,this.resolve=ue,this.reject=Ae}function ge(he,ve,ue){var Ae=!1;try{he(function(ze){Ae||(Ae=!0,ve(ze))},function(ze){Ae||(Ae=!0,ue(ze))})}catch(ze){if(Ae)return;Ae=!0,ue(ze)}}var ae=q.immediateFn||typeof h=="function"&&h||function(he){setTimeout(he,1)},we=Array.isArray||function(he){return Object.prototype.toString.call(he)==="[object Array]"};q.prototype.catch=function(he){return this.then(null,he)},q.prototype.then=function(he,ve){var ue=this;return new q(function(Ae,ze){V.call(ue,new De(he,ve,Ae,ze))})},q.all=function(){var he=Array.prototype.slice.call(arguments.length===1&&we(arguments[0])?arguments[0]:arguments);return new q(function(ve,ue){function Ae(gt,_t){try{if(_t&&(E(_t)=="object"||typeof _t=="function")){var Qe=_t.then;if(typeof Qe=="function")return void Qe.call(_t,function(ot){Ae(gt,ot)},ue)}he[gt]=_t,--ze==0&&ve(he)}catch(ot){ue(ot)}}if(he.length===0)return ve([]);for(var ze=he.length,We=0;WeAe;Ae++)he[Ae].then(ve,ue)})},o.exports?o.exports=q:x.Promise||(x.Promise=q)}(this),k.copy=function(x){return new Promise(function(j,q){if(typeof x!="string"&&!("text/plain"in x))throw new Error("You must provide a text/plain type.");var V=typeof x=="string"?x:x["text/plain"];window.clipboardData.setData("Text",V)?j():q(new Error("Copying was rejected."))})},k.paste=function(){return new Promise(function(x,j){var q=window.clipboardData.getData("Text");q?x(q):j(new Error("Pasting was rejected."))})}),k}()}).call(this,f(13).setImmediate)},function(o,l,f){"use strict";o.exports=f(15)},function(o,l,f){"use strict";f.r(l),l.default=`:root { + /** + * IMPORTANT: When new theme variables are added below\u2013 also add them to SettingsContext updateThemeVariables() + */ + + /* Light theme */ + --light-color-attribute-name: #ef6632; + --light-color-attribute-name-not-editable: #23272f; + --light-color-attribute-name-inverted: rgba(255, 255, 255, 0.7); + --light-color-attribute-value: #1a1aa6; + --light-color-attribute-value-inverted: #ffffff; + --light-color-attribute-editable-value: #1a1aa6; + --light-color-background: #ffffff; + --light-color-background-hover: rgba(0, 136, 250, 0.1); + --light-color-background-inactive: #e5e5e5; + --light-color-background-invalid: #fff0f0; + --light-color-background-selected: #0088fa; + --light-color-button-background: #ffffff; + --light-color-button-background-focus: #ededed; + --light-color-button: #5f6673; + --light-color-button-disabled: #cfd1d5; + --light-color-button-active: #0088fa; + --light-color-button-focus: #23272f; + --light-color-button-hover: #23272f; + --light-color-border: #eeeeee; + --light-color-commit-did-not-render-fill: #cfd1d5; + --light-color-commit-did-not-render-fill-text: #000000; + --light-color-commit-did-not-render-pattern: #cfd1d5; + --light-color-commit-did-not-render-pattern-text: #333333; + --light-color-commit-gradient-0: #37afa9; + --light-color-commit-gradient-1: #63b19e; + --light-color-commit-gradient-2: #80b393; + --light-color-commit-gradient-3: #97b488; + --light-color-commit-gradient-4: #abb67d; + --light-color-commit-gradient-5: #beb771; + --light-color-commit-gradient-6: #cfb965; + --light-color-commit-gradient-7: #dfba57; + --light-color-commit-gradient-8: #efbb49; + --light-color-commit-gradient-9: #febc38; + --light-color-commit-gradient-text: #000000; + --light-color-component-name: #6a51b2; + --light-color-component-name-inverted: #ffffff; + --light-color-component-badge-background: rgba(0, 0, 0, 0.1); + --light-color-component-badge-background-inverted: rgba(255, 255, 255, 0.25); + --light-color-component-badge-count: #777d88; + --light-color-component-badge-count-inverted: rgba(255, 255, 255, 0.7); + --light-color-context-background: rgba(0,0,0,.9); + --light-color-context-background-hover: rgba(255, 255, 255, 0.1); + --light-color-context-background-selected: #178fb9; + --light-color-context-border: #3d424a; + --light-color-context-text: #ffffff; + --light-color-context-text-selected: #ffffff; + --light-color-dim: #777d88; + --light-color-dimmer: #cfd1d5; + --light-color-dimmest: #eff0f1; + --light-color-error-background: hsl(0, 100%, 97%); + --light-color-error-border: hsl(0, 100%, 92%); + --light-color-error-text: #ff0000; + --light-color-expand-collapse-toggle: #777d88; + --light-color-link: #0000ff; + --light-color-modal-background: rgba(255, 255, 255, 0.75); + --light-color-record-active: #fc3a4b; + --light-color-record-hover: #3578e5; + --light-color-record-inactive: #0088fa; + --light-color-scroll-thumb: #c2c2c2; + --light-color-scroll-track: #fafafa; + --light-color-search-match: yellow; + --light-color-search-match-current: #f7923b; + --light-color-selected-tree-highlight-active: rgba(0, 136, 250, 0.1); + --light-color-selected-tree-highlight-inactive: rgba(0, 0, 0, 0.05); + --light-color-shadow: rgba(0, 0, 0, 0.25); + --light-color-tab-selected-border: #0088fa; + --light-color-text: #000000; + --light-color-text-invalid: #ff0000; + --light-color-text-selected: #ffffff; + --light-color-toggle-background-invalid: #fc3a4b; + --light-color-toggle-background-on: #0088fa; + --light-color-toggle-background-off: #cfd1d5; + --light-color-toggle-text: #ffffff; + --light-color-tooltip-background: rgba(0, 0, 0, 0.9); + --light-color-tooltip-text: #ffffff; + + /* Dark theme */ + --dark-color-attribute-name: #9d87d2; + --dark-color-attribute-name-not-editable: #ededed; + --dark-color-attribute-name-inverted: #282828; + --dark-color-attribute-value: #cedae0; + --dark-color-attribute-value-inverted: #ffffff; + --dark-color-attribute-editable-value: yellow; + --dark-color-background: #282c34; + --dark-color-background-hover: rgba(255, 255, 255, 0.1); + --dark-color-background-inactive: #3d424a; + --dark-color-background-invalid: #5c0000; + --dark-color-background-selected: #178fb9; + --dark-color-button-background: #282c34; + --dark-color-button-background-focus: #3d424a; + --dark-color-button: #afb3b9; + --dark-color-button-active: #61dafb; + --dark-color-button-disabled: #4f5766; + --dark-color-button-focus: #a2e9fc; + --dark-color-button-hover: #ededed; + --dark-color-border: #3d424a; + --dark-color-commit-did-not-render-fill: #777d88; + --dark-color-commit-did-not-render-fill-text: #000000; + --dark-color-commit-did-not-render-pattern: #666c77; + --dark-color-commit-did-not-render-pattern-text: #ffffff; + --dark-color-commit-gradient-0: #37afa9; + --dark-color-commit-gradient-1: #63b19e; + --dark-color-commit-gradient-2: #80b393; + --dark-color-commit-gradient-3: #97b488; + --dark-color-commit-gradient-4: #abb67d; + --dark-color-commit-gradient-5: #beb771; + --dark-color-commit-gradient-6: #cfb965; + --dark-color-commit-gradient-7: #dfba57; + --dark-color-commit-gradient-8: #efbb49; + --dark-color-commit-gradient-9: #febc38; + --dark-color-commit-gradient-text: #000000; + --dark-color-component-name: #61dafb; + --dark-color-component-name-inverted: #282828; + --dark-color-component-badge-background: rgba(255, 255, 255, 0.25); + --dark-color-component-badge-background-inverted: rgba(0, 0, 0, 0.25); + --dark-color-component-badge-count: #8f949d; + --dark-color-component-badge-count-inverted: rgba(255, 255, 255, 0.7); + --dark-color-context-background: rgba(255,255,255,.9); + --dark-color-context-background-hover: rgba(0, 136, 250, 0.1); + --dark-color-context-background-selected: #0088fa; + --dark-color-context-border: #eeeeee; + --dark-color-context-text: #000000; + --dark-color-context-text-selected: #ffffff; + --dark-color-dim: #8f949d; + --dark-color-dimmer: #777d88; + --dark-color-dimmest: #4f5766; + --dark-color-error-background: #200; + --dark-color-error-border: #900; + --dark-color-error-text: #f55; + --dark-color-expand-collapse-toggle: #8f949d; + --dark-color-link: #61dafb; + --dark-color-modal-background: rgba(0, 0, 0, 0.75); + --dark-color-record-active: #fc3a4b; + --dark-color-record-hover: #a2e9fc; + --dark-color-record-inactive: #61dafb; + --dark-color-scroll-thumb: #afb3b9; + --dark-color-scroll-track: #313640; + --dark-color-search-match: yellow; + --dark-color-search-match-current: #f7923b; + --dark-color-selected-tree-highlight-active: rgba(23, 143, 185, 0.15); + --dark-color-selected-tree-highlight-inactive: rgba(255, 255, 255, 0.05); + --dark-color-shadow: rgba(0, 0, 0, 0.5); + --dark-color-tab-selected-border: #178fb9; + --dark-color-text: #ffffff; + --dark-color-text-invalid: #ff8080; + --dark-color-text-selected: #ffffff; + --dark-color-toggle-background-invalid: #fc3a4b; + --dark-color-toggle-background-on: #178fb9; + --dark-color-toggle-background-off: #777d88; + --dark-color-toggle-text: #ffffff; + --dark-color-tooltip-background: rgba(255, 255, 255, 0.9); + --dark-color-tooltip-text: #000000; + + /* Font smoothing */ + --light-font-smoothing: auto; + --dark-font-smoothing: antialiased; + --font-smoothing: auto; + + /* Compact density */ + --compact-font-size-monospace-small: 9px; + --compact-font-size-monospace-normal: 11px; + --compact-font-size-monospace-large: 15px; + --compact-font-size-sans-small: 10px; + --compact-font-size-sans-normal: 12px; + --compact-font-size-sans-large: 14px; + --compact-line-height-data: 18px; + --compact-root-font-size: 16px; + + /* Comfortable density */ + --comfortable-font-size-monospace-small: 10px; + --comfortable-font-size-monospace-normal: 13px; + --comfortable-font-size-monospace-large: 17px; + --comfortable-font-size-sans-small: 12px; + --comfortable-font-size-sans-normal: 14px; + --comfortable-font-size-sans-large: 16px; + --comfortable-line-height-data: 22px; + --comfortable-root-font-size: 20px; + + /* GitHub.com system fonts */ + --font-family-monospace: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, + Courier, monospace; + --font-family-sans: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, + Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol; + + /* Constant values shared between JS and CSS */ + --interaction-commit-size: 10px; + --interaction-label-width: 200px; +} +`},function(o,l,f){"use strict";function h(k){var x=this;if(x instanceof h||(x=new h),x.tail=null,x.head=null,x.length=0,k&&typeof k.forEach=="function")k.forEach(function(V){x.push(V)});else if(arguments.length>0)for(var j=0,q=arguments.length;j1)j=x;else{if(!this.head)throw new TypeError("Reduce of empty list with no initial value");q=this.head.next,j=this.head.value}for(var V=0;q!==null;V++)j=k(j,q.value,V),q=q.next;return j},h.prototype.reduceReverse=function(k,x){var j,q=this.tail;if(arguments.length>1)j=x;else{if(!this.tail)throw new TypeError("Reduce of empty list with no initial value");q=this.tail.prev,j=this.tail.value}for(var V=this.length-1;q!==null;V--)j=k(j,q.value,V),q=q.prev;return j},h.prototype.toArray=function(){for(var k=new Array(this.length),x=0,j=this.head;j!==null;x++)k[x]=j.value,j=j.next;return k},h.prototype.toArrayReverse=function(){for(var k=new Array(this.length),x=0,j=this.tail;j!==null;x++)k[x]=j.value,j=j.prev;return k},h.prototype.slice=function(k,x){(x=x||this.length)<0&&(x+=this.length),(k=k||0)<0&&(k+=this.length);var j=new h;if(xthis.length&&(x=this.length);for(var q=0,V=this.head;V!==null&&qthis.length&&(x=this.length);for(var q=this.length,V=this.tail;V!==null&&q>x;q--)V=V.prev;for(;V!==null&&q>k;q--,V=V.prev)j.push(V.value);return j},h.prototype.splice=function(k,x){k>this.length&&(k=this.length-1),k<0&&(k=this.length+k);for(var j=0,q=this.head;q!==null&&j=0&&(F._idleTimeoutId=setTimeout(function(){F._onTimeout&&F._onTimeout()},k))},f(14),l.setImmediate=typeof self<"u"&&self.setImmediate||h!==void 0&&h.setImmediate||this&&this.setImmediate,l.clearImmediate=typeof self<"u"&&self.clearImmediate||h!==void 0&&h.clearImmediate||this&&this.clearImmediate}).call(this,f(4))},function(o,l,f){(function(h,E){(function(t,N){"use strict";if(!t.setImmediate){var F,k,x,j,q,V=1,re={},y=!1,me=t.document,De=Object.getPrototypeOf&&Object.getPrototypeOf(t);De=De&&De.setTimeout?De:t,{}.toString.call(t.process)==="[object process]"?F=function(we){E.nextTick(function(){ae(we)})}:function(){if(t.postMessage&&!t.importScripts){var we=!0,he=t.onmessage;return t.onmessage=function(){we=!1},t.postMessage("","*"),t.onmessage=he,we}}()?(j="setImmediate$"+Math.random()+"$",q=function(we){we.source===t&&typeof we.data=="string"&&we.data.indexOf(j)===0&&ae(+we.data.slice(j.length))},t.addEventListener?t.addEventListener("message",q,!1):t.attachEvent("onmessage",q),F=function(we){t.postMessage(j+we,"*")}):t.MessageChannel?((x=new MessageChannel).port1.onmessage=function(we){ae(we.data)},F=function(we){x.port2.postMessage(we)}):me&&"onreadystatechange"in me.createElement("script")?(k=me.documentElement,F=function(we){var he=me.createElement("script");he.onreadystatechange=function(){ae(we),he.onreadystatechange=null,k.removeChild(he),he=null},k.appendChild(he)}):F=function(we){setTimeout(ae,0,we)},De.setImmediate=function(we){typeof we!="function"&&(we=new Function(""+we));for(var he=new Array(arguments.length-1),ve=0;ve"u"?h===void 0?this:h:self)}).call(this,f(4),f(5))},function(o,l,f){"use strict";function h(ue){return(h=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(Ae){return typeof Ae}:function(Ae){return Ae&&typeof Symbol=="function"&&Ae.constructor===Symbol&&Ae!==Symbol.prototype?"symbol":typeof Ae})(ue)}var E=f(1),t=f(16),N=f(18).__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,F=60128;if(typeof Symbol=="function"&&Symbol.for){var k=Symbol.for;F=k("react.opaque.id")}var x=[],j=null,q=null;function V(){if(j===null){var ue=new Map;try{me.useContext({_currentValue:null}),me.useState(null),me.useReducer(function(gt){return gt},null),me.useRef(null),me.useLayoutEffect(function(){}),me.useEffect(function(){}),me.useImperativeHandle(void 0,function(){return null}),me.useDebugValue(null),me.useCallback(function(){}),me.useMemo(function(){return null})}finally{var Ae=x;x=[]}for(var ze=0;zece;ce++)if((J=ge(it,Pt,ce))!==-1){De=ce,Pt=J;break e}Pt=-1}}e:{if(it=Jt,(J=V().get(Ve.primitive))!==void 0){for(ce=0;cePt-it?null:Jt.slice(it,Pt-1))!==null){if(Pt=0,We!==null){for(;PtPt;We--)gt=Qe.pop()}for(We=Jt.length-Pt-1;1<=We;We--)Pt=[],gt.push({id:null,isStateEditable:!1,name:we(Jt[We-1].functionName),value:void 0,subHooks:Pt}),Qe.push(gt),gt=Pt;We=Jt}Pt=(Jt=Ve.primitive)==="Context"||Jt==="DebugValue"?null:_t++,gt.push({id:Pt,isStateEditable:Jt==="Reducer"||Jt==="State",name:Jt,value:Ve.value,subHooks:[]})}return function Re(le,He){for(var dt=[],At=0;At-1&&(re=re.replace(/eval code/g,"eval").replace(/(\(eval at [^()]*)|(\),.*$)/g,""));var y=re.replace(/^\s+/,"").replace(/\(eval code/g,"("),me=y.match(/ (\((.+):(\d+):(\d+)\)$)/),De=(y=me?y.replace(me[0],""):y).split(/\s+/).slice(1),ge=this.extractLocation(me?me[1]:De.pop()),ae=De.join(" ")||void 0,we=["eval",""].indexOf(ge[0])>-1?void 0:ge[0];return new k({functionName:ae,fileName:we,lineNumber:ge[1],columnNumber:ge[2],source:re})},this)},parseFFOrSafari:function(V){return V.stack.split(` +`).filter(function(re){return!re.match(q)},this).map(function(re){if(re.indexOf(" > eval")>-1&&(re=re.replace(/ line (\d+)(?: > eval line \d+)* > eval:\d+:\d+/g,":$1")),re.indexOf("@")===-1&&re.indexOf(":")===-1)return new k({functionName:re});var y=/((.*".+"[^@]*)?[^@]*)(?:@)/,me=re.match(y),De=me&&me[1]?me[1]:void 0,ge=this.extractLocation(re.replace(y,""));return new k({functionName:De,fileName:ge[0],lineNumber:ge[1],columnNumber:ge[2],source:re})},this)},parseOpera:function(V){return!V.stacktrace||V.message.indexOf(` +`)>-1&&V.message.split(` +`).length>V.stacktrace.split(` +`).length?this.parseOpera9(V):V.stack?this.parseOpera11(V):this.parseOpera10(V)},parseOpera9:function(V){for(var re=/Line (\d+).*script (?:in )?(\S+)/i,y=V.message.split(` +`),me=[],De=2,ge=y.length;De/,"$2").replace(/\([^)]*\)/g,"")||void 0;ge.match(/\(([^)]*)\)/)&&(y=ge.replace(/^[^(]+\(([^)]*)\)$/,"$1"));var we=y===void 0||y==="[arguments not available]"?void 0:y.split(",");return new k({functionName:ae,args:we,fileName:De[0],lineNumber:De[1],columnNumber:De[2],source:re})},this)}}})=="function"?h.apply(l,E):h)===void 0||(o.exports=t)})()},function(o,l,f){var h,E,t;(function(N,F){"use strict";E=[],(t=typeof(h=function(){function k(ae){return ae.charAt(0).toUpperCase()+ae.substring(1)}function x(ae){return function(){return this[ae]}}var j=["isConstructor","isEval","isNative","isToplevel"],q=["columnNumber","lineNumber"],V=["fileName","functionName","source"],re=j.concat(q,V,["args"]);function y(ae){if(ae)for(var we=0;we1?Oe-1:0),Ne=1;Ne=0&&Oe.splice($,1)}}}])&&h(H.prototype,Y),ee&&h(H,ee),U}(),t=f(2),N=f.n(t);try{var F=f(9).default,k=function(U){var H=new RegExp("".concat(U,": ([0-9]+)")),Y=F.match(H);return parseInt(Y[1],10)};k("comfortable-line-height-data"),k("compact-line-height-data")}catch{}function x(U){try{return sessionStorage.getItem(U)}catch{return null}}function j(U){try{sessionStorage.removeItem(U)}catch{}}function q(U,H){try{return sessionStorage.setItem(U,H)}catch{}}var V=function(U,H){return U===H},re=f(1),y=f.n(re);function me(U){return U.ownerDocument?U.ownerDocument.defaultView:null}function De(U){var H=me(U);return H?H.frameElement:null}function ge(U){var H=he(U);return ae([U.getBoundingClientRect(),{top:H.borderTop,left:H.borderLeft,bottom:H.borderBottom,right:H.borderRight,width:0,height:0}])}function ae(U){return U.reduce(function(H,Y){return H==null?Y:{top:H.top+Y.top,left:H.left+Y.left,width:H.width,height:H.height,bottom:H.bottom+Y.bottom,right:H.right+Y.right}})}function we(U,H){var Y=De(U);if(Y&&Y!==H){for(var ee=[U.getBoundingClientRect()],Ce=Y,_e=!1;Ce;){var Oe=ge(Ce);if(ee.push(Oe),Ce=De(Ce),_e)break;Ce&&me(Ce)===H&&(_e=!0)}return ae(ee)}return U.getBoundingClientRect()}function he(U){var H=window.getComputedStyle(U);return{borderLeft:parseInt(H.borderLeftWidth,10),borderRight:parseInt(H.borderRightWidth,10),borderTop:parseInt(H.borderTopWidth,10),borderBottom:parseInt(H.borderBottomWidth,10),marginLeft:parseInt(H.marginLeft,10),marginRight:parseInt(H.marginRight,10),marginTop:parseInt(H.marginTop,10),marginBottom:parseInt(H.marginBottom,10),paddingLeft:parseInt(H.paddingLeft,10),paddingRight:parseInt(H.paddingRight,10),paddingTop:parseInt(H.paddingTop,10),paddingBottom:parseInt(H.paddingBottom,10)}}function ve(U,H){var Y;if(typeof Symbol>"u"||U[Symbol.iterator]==null){if(Array.isArray(U)||(Y=function(Ne,Je){if(!!Ne){if(typeof Ne=="string")return ue(Ne,Je);var vt=Object.prototype.toString.call(Ne).slice(8,-1);if(vt==="Object"&&Ne.constructor&&(vt=Ne.constructor.name),vt==="Map"||vt==="Set")return Array.from(Ne);if(vt==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(vt))return ue(Ne,Je)}}(U))||H&&U&&typeof U.length=="number"){Y&&(U=Y);var ee=0,Ce=function(){};return{s:Ce,n:function(){return ee>=U.length?{done:!0}:{done:!1,value:U[ee++]}},e:function(Ne){throw Ne},f:Ce}}throw new TypeError(`Invalid attempt to iterate non-iterable instance. +In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}var _e,Oe=!0,$=!1;return{s:function(){Y=U[Symbol.iterator]()},n:function(){var Ne=Y.next();return Oe=Ne.done,Ne},e:function(Ne){$=!0,_e=Ne},f:function(){try{Oe||Y.return==null||Y.return()}finally{if($)throw _e}}}}function ue(U,H){(H==null||H>U.length)&&(H=U.length);for(var Y=0,ee=new Array(H);YOe.left+Oe.width&&(oe=Oe.left+Oe.width-vt-5),{style:{top:Ne+="px",left:oe+="px"}}}(H,Y,{width:ee.width,height:ee.height});y()(this.tip.style,Ce.style)}}]),U}(),Qe=function(){function U(){Ae(this,U);var H=window.__REACT_DEVTOOLS_TARGET_WINDOW__||window;this.window=H;var Y=window.__REACT_DEVTOOLS_TARGET_WINDOW__||window;this.tipBoundsWindow=Y;var ee=H.document;this.container=ee.createElement("div"),this.container.style.zIndex="10000000",this.tip=new _t(ee,this.container),this.rects=[],ee.body.appendChild(this.container)}return We(U,[{key:"remove",value:function(){this.tip.remove(),this.rects.forEach(function(H){H.remove()}),this.rects.length=0,this.container.parentNode&&this.container.parentNode.removeChild(this.container)}},{key:"inspect",value:function(H,Y){for(var ee=this,Ce=H.filter(function(xt){return xt.nodeType===Node.ELEMENT_NODE});this.rects.length>Ce.length;)this.rects.pop().remove();if(Ce.length!==0){for(;this.rects.length1&&arguments[1]!==void 0?arguments[1]:V,rt=void 0,xt=[],kt=void 0,bt=!1,sn=function(Ft,Dn){return qe(Ft,xt[Dn])},rn=function(){for(var Ft=arguments.length,Dn=Array(Ft),dr=0;dr"u"?"undefined":At(performance))==="object"&&typeof performance.now=="function"?function(){return performance.now()}:function(){return Date.now()},an=new Map,On=null,lr=!1,ln=null;function Vt(U){(lr=U)||(an.clear(),On!==null&&(cancelAnimationFrame(On),On=null),ln!==null&&(clearTimeout(ln),ln=null),He!==null&&(He.parentNode!=null&&He.parentNode.removeChild(He),He=null))}function Er(U){lr&&(U.forEach(function(H){var Y=an.get(H),ee=nn(),Ce=Y!=null?Y.lastMeasuredAt:0,_e=Y!=null?Y.rect:null;(_e===null||Ce+2505&&arguments[5]!==void 0?arguments[5]:0,$=Mo(U);switch($){case"html_element":return H.push(ee),{inspectable:!1,preview_short:ki(U,!1),preview_long:ki(U,!0),name:U.tagName,type:$};case"function":return H.push(ee),{inspectable:!1,preview_short:ki(U,!1),preview_long:ki(U,!0),name:typeof U.name!="function"&&U.name?U.name:"function",type:$};case"string":return U.length<=500?U:U.slice(0,500)+"...";case"bigint":case"symbol":return H.push(ee),{inspectable:!1,preview_short:ki(U,!1),preview_long:ki(U,!0),name:U.toString(),type:$};case"react_element":return H.push(ee),{inspectable:!1,preview_short:ki(U,!1),preview_long:ki(U,!0),name:F0(U)||"Unknown",type:$};case"array_buffer":case"data_view":return H.push(ee),{inspectable:!1,preview_short:ki(U,!1),preview_long:ki(U,!0),name:$==="data_view"?"DataView":"ArrayBuffer",size:U.byteLength,type:$};case"array":return _e=Ce(ee),Oe>=2&&!_e?c0($,!0,U,H,ee):U.map(function(vt,oe){return Ao(vt,H,Y,ee.concat([oe]),Ce,_e?1:Oe+1)});case"html_all_collection":case"typed_array":case"iterator":if(_e=Ce(ee),Oe>=2&&!_e)return c0($,!0,U,H,ee);var Ne={unserializable:!0,type:$,readonly:!0,size:$==="typed_array"?U.length:void 0,preview_short:ki(U,!1),preview_long:ki(U,!0),name:U.constructor&&U.constructor.name!=="Object"?U.constructor.name:""};return Xt(U[Symbol.iterator])&&Array.from(U).forEach(function(vt,oe){return Ne[oe]=Ao(vt,H,Y,ee.concat([oe]),Ce,_e?1:Oe+1)}),Y.push(ee),Ne;case"opaque_iterator":return H.push(ee),{inspectable:!1,preview_short:ki(U,!1),preview_long:ki(U,!0),name:U[Symbol.toStringTag],type:$};case"date":case"regexp":return H.push(ee),{inspectable:!1,preview_short:ki(U,!1),preview_long:ki(U,!0),name:U.toString(),type:$};case"object":if(_e=Ce(ee),Oe>=2&&!_e)return c0($,!0,U,H,ee);var Je={};return lu(U).forEach(function(vt){var oe=vt.toString();Je[oe]=Ao(U[vt],H,Y,ee.concat([oe]),Ce,_e?1:Oe+1)}),Je;case"infinity":case"nan":case"undefined":return H.push(ee),{type:$};default:return U}}function Jo(U){return(Jo=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(H){return typeof H}:function(H){return H&&typeof Symbol=="function"&&H.constructor===Symbol&&H!==Symbol.prototype?"symbol":typeof H})(U)}function Fs(U){return function(H){if(Array.isArray(H))return Zo(H)}(U)||function(H){if(typeof Symbol<"u"&&Symbol.iterator in Object(H))return Array.from(H)}(U)||function(H,Y){if(!!H){if(typeof H=="string")return Zo(H,Y);var ee=Object.prototype.toString.call(H).slice(8,-1);if(ee==="Object"&&H.constructor&&(ee=H.constructor.name),ee==="Map"||ee==="Set")return Array.from(H);if(ee==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(ee))return Zo(H,Y)}}(U)||function(){throw new TypeError(`Invalid attempt to spread non-iterable instance. +In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}()}function Zo(U,H){(H==null||H>U.length)&&(H=U.length);for(var Y=0,ee=new Array(H);YH.toString()?1:H.toString()>U.toString()?-1:0}function lu(U){for(var H=[],Y=U,ee=function(){var Ce=[].concat(Fs(Object.keys(Y)),Fs(Object.getOwnPropertySymbols(Y))),_e=Object.getOwnPropertyDescriptors(Y);Ce.forEach(function(Oe){_e[Oe].enumerable&&H.push(Oe)}),Y=Object.getPrototypeOf(Y)};Y!=null;)ee();return H}function vi(U){var H=arguments.length>1&&arguments[1]!==void 0?arguments[1]:"Anonymous",Y=$o.get(U);if(Y!=null)return Y;var ee=H;return typeof U.displayName=="string"?ee=U.displayName:typeof U.name=="string"&&U.name!==""&&(ee=U.name),$o.set(U,ee),ee}var Dr=0;function el(){return++Dr}function Y0(U){var H=qt.get(U);if(H!==void 0)return H;for(var Y=new Array(U.length),ee=0;ee1&&arguments[1]!==void 0?arguments[1]:50;return U.length>H?U.substr(0,H)+"\u2026":U}function ki(U,H){if(U!=null&&hasOwnProperty.call(U,Du.type))return H?U[Du.preview_long]:U[Du.preview_short];switch(Mo(U)){case"html_element":return"<".concat(su(U.tagName.toLowerCase())," />");case"function":return su("\u0192 ".concat(typeof U.name=="function"?"":U.name,"() {}"));case"string":return'"'.concat(U,'"');case"bigint":return su(U.toString()+"n");case"regexp":case"symbol":return su(U.toString());case"react_element":return"<".concat(su(F0(U)||"Unknown")," />");case"array_buffer":return"ArrayBuffer(".concat(U.byteLength,")");case"data_view":return"DataView(".concat(U.buffer.byteLength,")");case"array":if(H){for(var Y="",ee=0;ee0&&(Y+=", "),!((Y+=ki(U[ee],!1)).length>50));ee++);return"[".concat(su(Y),"]")}var Ce=hasOwnProperty.call(U,Du.size)?U[Du.size]:U.length;return"Array(".concat(Ce,")");case"typed_array":var _e="".concat(U.constructor.name,"(").concat(U.length,")");if(H){for(var Oe="",$=0;$0&&(Oe+=", "),!((Oe+=U[$]).length>50));$++);return"".concat(_e," [").concat(su(Oe),"]")}return _e;case"iterator":var Ne=U.constructor.name;if(H){for(var Je=Array.from(U),vt="",oe=0;oe0&&(vt+=", "),Array.isArray(qe)){var rt=ki(qe[0],!0),xt=ki(qe[1],!1);vt+="".concat(rt," => ").concat(xt)}else vt+=ki(qe,!1);if(vt.length>50)break}return"".concat(Ne,"(").concat(U.size,") {").concat(su(vt),"}")}return"".concat(Ne,"(").concat(U.size,")");case"opaque_iterator":return U[Symbol.toStringTag];case"date":return U.toString();case"object":if(H){for(var kt=lu(U).sort(xi),bt="",sn=0;sn0&&(bt+=", "),(bt+="".concat(rn.toString(),": ").concat(ki(U[rn],!1))).length>50)break}return"{".concat(su(bt),"}")}return"{\u2026}";case"boolean":case"number":case"infinity":case"nan":case"null":case"undefined":return U;default:try{return su(""+U)}catch{return"unserializable"}}}var Ps=f(7);function Kl(U){return(Kl=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(H){return typeof H}:function(H){return H&&typeof Symbol=="function"&&H.constructor===Symbol&&H!==Symbol.prototype?"symbol":typeof H})(U)}function P0(U,H){var Y=Object.keys(U);if(Object.getOwnPropertySymbols){var ee=Object.getOwnPropertySymbols(U);H&&(ee=ee.filter(function(Ce){return Object.getOwnPropertyDescriptor(U,Ce).enumerable})),Y.push.apply(Y,ee)}return Y}function d0(U){for(var H=1;H2&&arguments[2]!==void 0?arguments[2]:[];if(U!==null){var ee=[],Ce=[],_e=Ao(U,ee,Ce,Y,H);return{data:_e,cleaned:ee,unserializable:Ce}}return null}function X0(U){var H,Y,ee=(H=U,Y=new Set,JSON.stringify(H,function(Oe,$){if(Kl($)==="object"&&$!==null){if(Y.has($))return;Y.add($)}return typeof $=="bigint"?$.toString()+"n":$})),Ce=ee===void 0?"undefined":ee,_e=window.__REACT_DEVTOOLS_GLOBAL_HOOK__.clipboardCopyText;typeof _e=="function"?_e(Ce).catch(function(Oe){}):Object(Ps.copy)(Ce)}function mi(U,H){var Y=arguments.length>2&&arguments[2]!==void 0?arguments[2]:0,ee=H[Y],Ce=Array.isArray(U)?U.slice():d0({},U);return Y+1===H.length?Array.isArray(Ce)?Ce.splice(ee,1):delete Ce[ee]:Ce[ee]=mi(U[ee],H,Y+1),Ce}function en(U,H,Y){var ee=arguments.length>3&&arguments[3]!==void 0?arguments[3]:0,Ce=H[ee],_e=Array.isArray(U)?U.slice():d0({},U);if(ee+1===H.length){var Oe=Y[ee];_e[Oe]=_e[Ce],Array.isArray(_e)?_e.splice(Ce,1):delete _e[Ce]}else _e[Ce]=en(U[Ce],H,Y,ee+1);return _e}function In(U,H,Y){var ee=arguments.length>3&&arguments[3]!==void 0?arguments[3]:0;if(ee>=H.length)return Y;var Ce=H[ee],_e=Array.isArray(U)?U.slice():d0({},U);return _e[Ce]=In(U[Ce],H,Y,ee+1),_e}var Ai=f(8);function yi(U,H){var Y=Object.keys(U);if(Object.getOwnPropertySymbols){var ee=Object.getOwnPropertySymbols(U);H&&(ee=ee.filter(function(Ce){return Object.getOwnPropertyDescriptor(U,Ce).enumerable})),Y.push.apply(Y,ee)}return Y}function Wt(U){for(var H=1;H"u"||!(Symbol.iterator in Object(Y)))){var Ce=[],_e=!0,Oe=!1,$=void 0;try{for(var Ne,Je=Y[Symbol.iterator]();!(_e=(Ne=Je.next()).done)&&(Ce.push(Ne.value),!ee||Ce.length!==ee);_e=!0);}catch(vt){Oe=!0,$=vt}finally{try{_e||Je.return==null||Je.return()}finally{if(Oe)throw $}}return Ce}}(U,H)||Xl(U,H)||function(){throw new TypeError(`Invalid attempt to destructure non-iterable instance. +In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}()}function Yi(U,H){var Y;if(typeof Symbol>"u"||U[Symbol.iterator]==null){if(Array.isArray(U)||(Y=Xl(U))||H&&U&&typeof U.length=="number"){Y&&(U=Y);var ee=0,Ce=function(){};return{s:Ce,n:function(){return ee>=U.length?{done:!0}:{done:!1,value:U[ee++]}},e:function(Ne){throw Ne},f:Ce}}throw new TypeError(`Invalid attempt to iterate non-iterable instance. +In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}var _e,Oe=!0,$=!1;return{s:function(){Y=U[Symbol.iterator]()},n:function(){var Ne=Y.next();return Oe=Ne.done,Ne},e:function(Ne){$=!0,_e=Ne},f:function(){try{Oe||Y.return==null||Y.return()}finally{if($)throw _e}}}}function Xl(U,H){if(U){if(typeof U=="string")return ko(U,H);var Y=Object.prototype.toString.call(U).slice(8,-1);return Y==="Object"&&U.constructor&&(Y=U.constructor.name),Y==="Map"||Y==="Set"?Array.from(U):Y==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(Y)?ko(U,H):void 0}}function ko(U,H){(H==null||H>U.length)&&(H=U.length);for(var Y=0,ee=new Array(H);Y"u"?"undefined":li(performance))==="object"&&typeof performance.now=="function"?function(){return performance.now()}:function(){return Date.now()};function No(U){var H=null;function Y(rn){var Ft=li(rn)==="object"&&rn!==null?rn.$$typeof:rn;return li(Ft)==="symbol"?Ft.toString():Ft}var ee=H=Object(zt.gte)(U,"17.0.0-alpha")?{Block:22,ClassComponent:1,ContextConsumer:9,ContextProvider:10,CoroutineComponent:-1,CoroutineHandlerPhase:-1,DehydratedSuspenseComponent:18,ForwardRef:11,Fragment:7,FunctionComponent:0,HostComponent:5,HostPortal:4,HostRoot:3,HostText:6,IncompleteClassComponent:17,IndeterminateComponent:2,LazyComponent:16,MemoComponent:14,Mode:8,OffscreenComponent:23,Profiler:12,SimpleMemoComponent:15,SuspenseComponent:13,SuspenseListComponent:19,YieldComponent:-1}:Object(zt.gte)(U,"16.6.0-beta.0")?{Block:22,ClassComponent:1,ContextConsumer:9,ContextProvider:10,CoroutineComponent:-1,CoroutineHandlerPhase:-1,DehydratedSuspenseComponent:18,ForwardRef:11,Fragment:7,FunctionComponent:0,HostComponent:5,HostPortal:4,HostRoot:3,HostText:6,IncompleteClassComponent:17,IndeterminateComponent:2,LazyComponent:16,MemoComponent:14,Mode:8,OffscreenComponent:-1,Profiler:12,SimpleMemoComponent:15,SuspenseComponent:13,SuspenseListComponent:19,YieldComponent:-1}:Object(zt.gte)(U,"16.4.3-alpha")?{Block:-1,ClassComponent:2,ContextConsumer:11,ContextProvider:12,CoroutineComponent:-1,CoroutineHandlerPhase:-1,DehydratedSuspenseComponent:-1,ForwardRef:13,Fragment:9,FunctionComponent:0,HostComponent:7,HostPortal:6,HostRoot:5,HostText:8,IncompleteClassComponent:-1,IndeterminateComponent:4,LazyComponent:-1,MemoComponent:-1,Mode:10,OffscreenComponent:-1,Profiler:15,SimpleMemoComponent:-1,SuspenseComponent:16,SuspenseListComponent:-1,YieldComponent:-1}:{Block:-1,ClassComponent:2,ContextConsumer:12,ContextProvider:13,CoroutineComponent:7,CoroutineHandlerPhase:8,DehydratedSuspenseComponent:-1,ForwardRef:14,Fragment:10,FunctionComponent:1,HostComponent:5,HostPortal:4,HostRoot:3,HostText:6,IncompleteClassComponent:-1,IndeterminateComponent:0,LazyComponent:-1,MemoComponent:-1,Mode:11,OffscreenComponent:-1,Profiler:15,SimpleMemoComponent:-1,SuspenseComponent:16,SuspenseListComponent:-1,YieldComponent:9},Ce=ee.ClassComponent,_e=ee.IncompleteClassComponent,Oe=ee.FunctionComponent,$=ee.IndeterminateComponent,Ne=ee.ForwardRef,Je=ee.HostRoot,vt=ee.HostComponent,oe=ee.HostPortal,qe=ee.HostText,rt=ee.Fragment,xt=ee.MemoComponent,kt=ee.SimpleMemoComponent,bt=ee.SuspenseComponent,sn=ee.SuspenseListComponent;return{getDisplayNameForFiber:function(rn){var Ft=rn.type,Dn=rn.tag,dr=Ft;li(Ft)==="object"&&Ft!==null&&(dr=function Cr(Rn){switch(Y(Rn)){case 60115:case"Symbol(react.memo)":return Cr(Rn.type);case 60112:case"Symbol(react.forward_ref)":return Rn.render;default:return Rn}}(Ft));var er=null;switch(Dn){case Ce:case _e:return vi(dr);case Oe:case $:return vi(dr);case Ne:return Ft&&Ft.displayName||vi(dr,"Anonymous");case Je:return null;case vt:return Ft;case oe:case qe:case rt:return null;case xt:case kt:return vi(dr,"Anonymous");case bt:return"Suspense";case sn:return"SuspenseList";default:switch(Y(Ft)){case 60111:case"Symbol(react.concurrent_mode)":case"Symbol(react.async_mode)":return null;case 60109:case"Symbol(react.provider)":return er=rn.type._context||rn.type.context,"".concat(er.displayName||"Context",".Provider");case 60110:case"Symbol(react.context)":return er=rn.type._context||rn.type,"".concat(er.displayName||"Context",".Consumer");case 60108:case"Symbol(react.strict_mode)":return null;case 60114:case"Symbol(react.profiler)":return"Profiler(".concat(rn.memoizedProps.id,")");case 60119:case"Symbol(react.scope)":return"Scope";default:return null}}},getTypeSymbol:Y,ReactPriorityLevels:{ImmediatePriority:99,UserBlockingPriority:98,NormalPriority:97,LowPriority:96,IdlePriority:95,NoPriority:90},ReactTypeOfWork:H,ReactTypeOfSideEffect:{NoFlags:0,PerformedWork:1,Placement:2}}}function Is(U,H,Y,ee){var Ce=No(Y.version),_e=Ce.getDisplayNameForFiber,Oe=Ce.getTypeSymbol,$=Ce.ReactPriorityLevels,Ne=Ce.ReactTypeOfWork,Je=Ce.ReactTypeOfSideEffect,vt=Je.NoFlags,oe=Je.PerformedWork,qe=Je.Placement,rt=Ne.FunctionComponent,xt=Ne.ClassComponent,kt=Ne.ContextConsumer,bt=Ne.DehydratedSuspenseComponent,sn=Ne.Fragment,rn=Ne.ForwardRef,Ft=Ne.HostRoot,Dn=Ne.HostPortal,dr=Ne.HostComponent,er=Ne.HostText,Cr=Ne.IncompleteClassComponent,Rn=Ne.IndeterminateComponent,Nr=Ne.MemoComponent,y0=Ne.OffscreenComponent,Lr=Ne.SimpleMemoComponent,ut=Ne.SuspenseComponent,wt=Ne.SuspenseListComponent,et=$.ImmediatePriority,It=$.UserBlockingPriority,un=$.NormalPriority,fn=$.LowPriority,Jn=$.IdlePriority,wr=$.NoPriority,au=Y.overrideHookState,ku=Y.overrideHookStateDeletePath,T0=Y.overrideHookStateRenamePath,Z0=Y.overrideProps,Nu=Y.overridePropsDeletePath,gi=Y.overridePropsRenamePath,Po=Y.setSuspenseHandler,rl=Y.scheduleUpdate,hf=typeof Po=="function"&&typeof rl=="function";co(Y);var Tl=window.__REACT_DEVTOOLS_APPEND_COMPONENT_STACK__!==!1,vf=window.__REACT_DEVTOOLS_BREAK_ON_CONSOLE_ERRORS__===!0;(Tl||vf)&&Jl({appendComponentStack:Tl,breakOnConsoleErrors:vf});var Io=new Set,ys=new Set,js=new Set,bo=!1,Bo=new Set;function gs(fe){js.clear(),Io.clear(),ys.clear(),fe.forEach(function(ie){if(ie.isEnabled)switch(ie.type){case 2:ie.isValid&&ie.value!==""&&Io.add(new RegExp(ie.value,"i"));break;case 1:js.add(ie.value);break;case 3:ie.isValid&&ie.value!==""&&ys.add(new RegExp(ie.value,"i"));break;case 4:Io.add(new RegExp("\\("));break;default:console.warn('Invalid component filter type "'.concat(ie.type,'"'))}})}function Xu(fe){var ie=fe._debugSource,Pe=fe.tag,Me=fe.type;switch(Pe){case bt:return!0;case Dn:case er:case sn:case y0:return!0;case Ft:return!1;default:switch(Oe(Me)){case 60111:case"Symbol(react.concurrent_mode)":case"Symbol(react.async_mode)":case 60108:case"Symbol(react.strict_mode)":return!0}}var at=Su(fe);if(js.has(at))return!0;if(Io.size>0){var mt=_e(fe);if(mt!=null){var Qt,An=Yi(Io);try{for(An.s();!(Qt=An.n()).done;)if(Qt.value.test(mt))return!0}catch(ir){An.e(ir)}finally{An.f()}}}if(ie!=null&&ys.size>0){var Sn,_n=ie.fileName,Tn=Yi(ys);try{for(Tn.s();!(Sn=Tn.n()).done;)if(Sn.value.test(_n))return!0}catch(ir){Tn.e(ir)}finally{Tn.f()}}return!1}function Su(fe){var ie=fe.type;switch(fe.tag){case xt:case Cr:return 1;case rt:case Rn:return 5;case rn:return 6;case Ft:return 11;case dr:return 7;case Dn:case er:case sn:return 9;case Nr:case Lr:return 8;case ut:return 12;case wt:return 13;default:switch(Oe(ie)){case 60111:case"Symbol(react.concurrent_mode)":case"Symbol(react.async_mode)":return 9;case 60109:case"Symbol(react.provider)":return 2;case 60110:case"Symbol(react.context)":return 2;case 60108:case"Symbol(react.strict_mode)":return 9;case 60114:case"Symbol(react.profiler)":return 10;default:return 9}}}function _i(fe){if(Uo.has(fe))return fe;var ie=fe.alternate;return ie!=null&&Uo.has(ie)?ie:(Uo.add(fe),fe)}window.__REACT_DEVTOOLS_COMPONENT_FILTERS__!=null?gs(window.__REACT_DEVTOOLS_COMPONENT_FILTERS__):gs([{type:1,value:7,isEnabled:!0}]);var C0=new Map,$0=new Map,Uo=new Set,la=new Map,$l=new Map,tu=-1;function Zr(fe){if(!C0.has(fe)){var ie=el();C0.set(fe,ie),$0.set(ie,fe)}return C0.get(fe)}function ho(fe){switch(Su(fe)){case 1:if(B0!==null){var ie=Zr(_i(fe)),Pe=Ci(fe);Pe!==null&&B0.set(ie,Pe)}}}var Bi={};function Ci(fe){switch(Su(fe)){case 1:var ie=fe.stateNode,Pe=Bi,Me=Bi;return ie!=null&&(ie.constructor&&ie.constructor.contextType!=null?Me=ie.context:(Pe=ie.context)&&Object.keys(Pe).length===0&&(Pe=Bi)),[Pe,Me];default:return null}}function mf(fe){switch(Su(fe)){case 1:if(B0!==null){var ie=Zr(_i(fe)),Pe=B0.has(ie)?B0.get(ie):null,Me=Ci(fe);if(Pe==null||Me==null)return null;var at=Q0(Pe,2),mt=at[0],Qt=at[1],An=Q0(Me,2),Sn=An[0],_n=An[1];if(Sn!==Bi)return eo(mt,Sn);if(_n!==Bi)return Qt!==_n}}return null}function yf(fe,ie){if(fe==null||ie==null)return!1;if(ie.hasOwnProperty("baseState")&&ie.hasOwnProperty("memoizedState")&&ie.hasOwnProperty("next")&&ie.hasOwnProperty("queue"))for(;ie!==null;){if(ie.memoizedState!==fe.memoizedState)return!0;ie=ie.next,fe=fe.next}return!1}function eo(fe,ie){if(fe==null||ie==null||ie.hasOwnProperty("baseState")&&ie.hasOwnProperty("memoizedState")&&ie.hasOwnProperty("next")&&ie.hasOwnProperty("queue"))return null;var Pe,Me=[],at=Yi(new Set([].concat(eu(Object.keys(fe)),eu(Object.keys(ie)))));try{for(at.s();!(Pe=at.n()).done;){var mt=Pe.value;fe[mt]!==ie[mt]&&Me.push(mt)}}catch(Qt){at.e(Qt)}finally{at.f()}return Me}function to(fe,ie){switch(ie.tag){case xt:case rt:case kt:case Nr:case Lr:return(ao(ie)&oe)===oe;default:return fe.memoizedProps!==ie.memoizedProps||fe.memoizedState!==ie.memoizedState||fe.ref!==ie.ref}}var xe=[],tt=[],Ke=[],Yt=[],Kt=new Map,pr=0,Ei=null;function bn(fe){xe.push(fe)}function mu(fe){if(xe.length!==0||tt.length!==0||Ke.length!==0||Ei!==null||Fu){var ie=tt.length+Ke.length+(Ei===null?0:1),Pe=new Array(3+pr+(ie>0?2+ie:0)+xe.length),Me=0;if(Pe[Me++]=H,Pe[Me++]=tu,Pe[Me++]=pr,Kt.forEach(function(An,Sn){Pe[Me++]=Sn.length;for(var _n=Y0(Sn),Tn=0;Tn<_n.length;Tn++)Pe[Me+Tn]=_n[Tn];Me+=Sn.length}),ie>0){Pe[Me++]=2,Pe[Me++]=ie;for(var at=tt.length-1;at>=0;at--)Pe[Me++]=tt[at];for(var mt=0;mt0?fe.forEach(function(ie){U.emit("operations",ie)}):(Rr!==null&&(fu=!0),U.getFiberRoots(H).forEach(function(ie){$u(tu=Zr(_i(ie.current)),ie.current),Fu&&ie.memoizedInteractions!=null&&(il={changeDescriptions:es?new Map:null,durations:[],commitTime:Ql()-Ju,interactions:Array.from(ie.memoizedInteractions).map(function(Pe){return Wt(Wt({},Pe),{},{timestamp:Pe.timestamp-Ju})}),maxActualDuration:0,priorityLevel:null}),Qr(ie.current,null,!1,!1),mu(),tu=-1}))},getBestMatchForTrackedPath:function(){if(Rr===null||no===null)return null;for(var fe=no;fe!==null&&Xu(fe);)fe=fe.return;return fe===null?null:{id:Zr(_i(fe)),isFullMatch:nu===Rr.length-1}},getDisplayNameForFiberID:function(fe){var ie=$0.get(fe);return ie!=null?_e(ie):null},getFiberIDForNative:function(fe){var ie=arguments.length>1&&arguments[1]!==void 0&&arguments[1],Pe=Y.findFiberByHostInstance(fe);if(Pe!=null){if(ie)for(;Pe!==null&&Xu(Pe);)Pe=Pe.return;return Zr(_i(Pe))}return null},getInstanceAndStyle:function(fe){var ie=null,Pe=null,Me=Wu(fe);return Me!==null&&(ie=Me.stateNode,Me.memoizedProps!==null&&(Pe=Me.memoizedProps.style)),{instance:ie,style:Pe}},getOwnersList:function(fe){var ie=Wu(fe);if(ie==null)return null;var Pe=ie._debugOwner,Me=[{displayName:_e(ie)||"Anonymous",id:fe,type:Su(ie)}];if(Pe)for(var at=Pe;at!==null;)Me.unshift({displayName:_e(at)||"Anonymous",id:Zr(_i(at)),type:Su(at)}),at=at._debugOwner||null;return Me},getPathForElement:function(fe){var ie=$0.get(fe);if(ie==null)return null;for(var Pe=[];ie!==null;)Pe.push(_0(ie)),ie=ie.return;return Pe.reverse(),Pe},getProfilingData:function(){var fe=[];if(_s===null)throw Error("getProfilingData() called before any profiling data was recorded");return _s.forEach(function(ie,Pe){var Me=[],at=[],mt=new Map,Qt=new Map,An=xl!==null&&xl.get(Pe)||"Unknown";O0!=null&&O0.forEach(function(Sn,_n){vo!=null&&vo.get(_n)===Pe&&at.push([_n,Sn])}),ie.forEach(function(Sn,_n){var Tn=Sn.changeDescriptions,ir=Sn.durations,Ut=Sn.interactions,Fi=Sn.maxActualDuration,Ar=Sn.priorityLevel,mr=Sn.commitTime,K=[];Ut.forEach(function(Di){mt.has(Di.id)||mt.set(Di.id,Di),K.push(Di.id);var ru=Qt.get(Di.id);ru!=null?ru.push(_n):Qt.set(Di.id,[_n])});for(var ti=[],ni=[],Wr=0;Wr1?Kn.set(Tn,ir-1):Kn.delete(Tn),ei.delete(Sn)}(tu),$r(Pe,!1))}else $u(tu,Pe),Qr(Pe,null,!1,!1);if(Fu&&at){var An=_s.get(tu);An!=null?An.push(il):_s.set(tu,[il])}mu(),bo&&U.emit("traceUpdates",Bo),tu=-1},handleCommitFiberUnmount:function(fe){$r(fe,!1)},inspectElement:function(fe,ie){if(Hi(fe)){if(ie!=null){A0(ie);var Pe=null;return ie[0]==="hooks"&&(Pe="hooks"),{id:fe,type:"hydrated-path",path:ie,value:Ri(Bu(Xi,ie),qi(null,Pe),ie)}}return{id:fe,type:"no-change"}}if(Hs=!1,Xi!==null&&Xi.id===fe||(R0={}),(Xi=sa(fe))===null)return{id:fe,type:"not-found"};ie!=null&&A0(ie),function(at){var mt=at.hooks,Qt=at.id,An=at.props,Sn=$0.get(Qt);if(Sn!=null){var _n=Sn.elementType,Tn=Sn.stateNode,ir=Sn.tag,Ut=Sn.type;switch(ir){case xt:case Cr:case Rn:ee.$r=Tn;break;case rt:ee.$r={hooks:mt,props:An,type:Ut};break;case rn:ee.$r={props:An,type:Ut.render};break;case Nr:case Lr:ee.$r={props:An,type:_n!=null&&_n.type!=null?_n.type:Ut};break;default:ee.$r=null}}else console.warn('Could not find Fiber with id "'.concat(Qt,'"'))}(Xi);var Me=Wt({},Xi);return Me.context=Ri(Me.context,qi("context",null)),Me.hooks=Ri(Me.hooks,qi("hooks","hooks")),Me.props=Ri(Me.props,qi("props",null)),Me.state=Ri(Me.state,qi("state",null)),{id:fe,type:"full-data",value:Me}},logElementToConsole:function(fe){var ie=Hi(fe)?Xi:sa(fe);if(ie!==null){var Pe=typeof console.groupCollapsed=="function";Pe&&console.groupCollapsed("[Click to expand] %c<".concat(ie.displayName||"Component"," />"),"color: var(--dom-tag-name-color); font-weight: normal;"),ie.props!==null&&console.log("Props:",ie.props),ie.state!==null&&console.log("State:",ie.state),ie.hooks!==null&&console.log("Hooks:",ie.hooks);var Me=Cl(fe);Me!==null&&console.log("Nodes:",Me),ie.source!==null&&console.log("Location:",ie.source),(window.chrome||/firefox/i.test(navigator.userAgent))&&console.log("Right-click any value to save it as a global variable for further inspection."),Pe&&console.groupEnd()}else console.warn('Could not find Fiber with id "'.concat(fe,'"'))},prepareViewAttributeSource:function(fe,ie){Hi(fe)&&(window.$attribute=Bu(Xi,ie))},prepareViewElementSource:function(fe){var ie=$0.get(fe);if(ie!=null){var Pe=ie.elementType,Me=ie.tag,at=ie.type;switch(Me){case xt:case Cr:case Rn:case rt:ee.$type=at;break;case rn:ee.$type=at.render;break;case Nr:case Lr:ee.$type=Pe!=null&&Pe.type!=null?Pe.type:at;break;default:ee.$type=null}}else console.warn('Could not find Fiber with id "'.concat(fe,'"'))},overrideSuspense:function(fe,ie){if(typeof Po!="function"||typeof rl!="function")throw new Error("Expected overrideSuspense() to not get called for earlier React versions.");ie?(Zu.add(fe),Zu.size===1&&Po(Es)):(Zu.delete(fe),Zu.size===0&&Po(gf));var Pe=$0.get(fe);Pe!=null&&rl(Pe)},overrideValueAtPath:function(fe,ie,Pe,Me,at){var mt=Wu(ie);if(mt!==null){var Qt=mt.stateNode;switch(fe){case"context":switch(Me=Me.slice(1),mt.tag){case xt:Me.length===0?Qt.context=at:Oo(Qt.context,Me,at),Qt.forceUpdate()}break;case"hooks":typeof au=="function"&&au(mt,Pe,Me,at);break;case"props":switch(mt.tag){case xt:mt.pendingProps=In(Qt.props,Me,at),Qt.forceUpdate();break;default:typeof Z0=="function"&&Z0(mt,Me,at)}break;case"state":switch(mt.tag){case xt:Oo(Qt.state,Me,at),Qt.forceUpdate()}}}},renamePath:function(fe,ie,Pe,Me,at){var mt=Wu(ie);if(mt!==null){var Qt=mt.stateNode;switch(fe){case"context":switch(Me=Me.slice(1),at=at.slice(1),mt.tag){case xt:Me.length===0||Kr(Qt.context,Me,at),Qt.forceUpdate()}break;case"hooks":typeof T0=="function"&&T0(mt,Pe,Me,at);break;case"props":Qt===null?typeof gi=="function"&&gi(mt,Me,at):(mt.pendingProps=en(Qt.props,Me,at),Qt.forceUpdate());break;case"state":Kr(Qt.state,Me,at),Qt.forceUpdate()}}},renderer:Y,setTraceUpdatesEnabled:function(fe){bo=fe},setTrackedPath:Li,startProfiling:aa,stopProfiling:function(){Fu=!1,es=!1},storeAsGlobal:function(fe,ie,Pe){if(Hi(fe)){var Me=Bu(Xi,ie),at="$reactTemp".concat(Pe);window[at]=Me,console.log(at),console.log(Me)}},updateComponentFilters:function(fe){if(Fu)throw Error("Cannot modify filter preferences while profiling");U.getFiberRoots(H).forEach(function(ie){tu=Zr(_i(ie.current)),qu(ie.current),$r(ie.current,!1),tu=-1}),gs(fe),Kn.clear(),U.getFiberRoots(H).forEach(function(ie){$u(tu=Zr(_i(ie.current)),ie.current),Qr(ie.current,null,!1,!1),mu(ie),tu=-1})}}}var $n;function tl(U){return(tl=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(H){return typeof H}:function(H){return H&&typeof Symbol=="function"&&H.constructor===Symbol&&H!==Symbol.prototype?"symbol":typeof H})(U)}function fo(U,H,Y){if($n===void 0)try{throw Error()}catch(Ce){var ee=Ce.stack.trim().match(/\n( *(at )?)/);$n=ee&&ee[1]||""}return` +`+$n+U}var I0=!1;function Sl(U,H,Y){if(!U||I0)return"";var ee,Ce=Error.prepareStackTrace;Error.prepareStackTrace=void 0,I0=!0;var _e=Y.current;Y.current=null;try{if(H){var Oe=function(){throw Error()};if(Object.defineProperty(Oe.prototype,"props",{set:function(){throw Error()}}),(typeof Reflect>"u"?"undefined":tl(Reflect))==="object"&&Reflect.construct){try{Reflect.construct(Oe,[])}catch(qe){ee=qe}Reflect.construct(U,[],Oe)}else{try{Oe.call()}catch(qe){ee=qe}U.call(Oe.prototype)}}else{try{throw Error()}catch(qe){ee=qe}U()}}catch(qe){if(qe&&ee&&typeof qe.stack=="string"){for(var $=qe.stack.split(` +`),Ne=ee.stack.split(` +`),Je=$.length-1,vt=Ne.length-1;Je>=1&&vt>=0&&$[Je]!==Ne[vt];)vt--;for(;Je>=1&&vt>=0;Je--,vt--)if($[Je]!==Ne[vt]){if(Je!==1||vt!==1)do if(Je--,--vt<0||$[Je]!==Ne[vt])return` +`+$[Je].replace(" at new "," at ");while(Je>=1&&vt>=0);break}}}finally{I0=!1,Error.prepareStackTrace=Ce,Y.current=_e}var oe=U?U.displayName||U.name:"";return oe?fo(oe):""}function Lo(U,H,Y,ee){return Sl(U,!1,ee)}function St(U,H,Y){var ee=U.HostComponent,Ce=U.LazyComponent,_e=U.SuspenseComponent,Oe=U.SuspenseListComponent,$=U.FunctionComponent,Ne=U.IndeterminateComponent,Je=U.SimpleMemoComponent,vt=U.ForwardRef,oe=U.Block,qe=U.ClassComponent;switch(H.tag){case ee:return fo(H.type);case Ce:return fo("Lazy");case _e:return fo("Suspense");case Oe:return fo("SuspenseList");case $:case Ne:case Je:return Lo(H.type,0,0,Y);case vt:return Lo(H.type.render,0,0,Y);case oe:return Lo(H.type._render,0,0,Y);case qe:return function(rt,xt,kt,bt){return Sl(rt,!0,bt)}(H.type,0,0,Y);default:return""}}function Bt(U,H,Y){try{var ee="",Ce=H;do ee+=St(U,Ce,Y),Ce=Ce.return;while(Ce);return ee}catch(_e){return` +Error generating stack: `+_e.message+` +`+_e.stack}}function Hn(U,H){var Y;if(typeof Symbol>"u"||U[Symbol.iterator]==null){if(Array.isArray(U)||(Y=function(Ne,Je){if(!!Ne){if(typeof Ne=="string")return qr(Ne,Je);var vt=Object.prototype.toString.call(Ne).slice(8,-1);if(vt==="Object"&&Ne.constructor&&(vt=Ne.constructor.name),vt==="Map"||vt==="Set")return Array.from(Ne);if(vt==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(vt))return qr(Ne,Je)}}(U))||H&&U&&typeof U.length=="number"){Y&&(U=Y);var ee=0,Ce=function(){};return{s:Ce,n:function(){return ee>=U.length?{done:!0}:{done:!1,value:U[ee++]}},e:function(Ne){throw Ne},f:Ce}}throw new TypeError(`Invalid attempt to iterate non-iterable instance. +In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}var _e,Oe=!0,$=!1;return{s:function(){Y=U[Symbol.iterator]()},n:function(){var Ne=Y.next();return Oe=Ne.done,Ne},e:function(Ne){$=!0,_e=Ne},f:function(){try{Oe||Y.return==null||Y.return()}finally{if($)throw _e}}}}function qr(U,H){(H==null||H>U.length)&&(H=U.length);for(var Y=0,ee=new Array(H);Y0?Je[Je.length-1]:null,qe=oe!==null&&(Xr.test(oe)||Au.test(oe));if(!qe){var rt,xt=Hn(p0.values());try{for(xt.s();!(rt=xt.n()).done;){var kt=rt.value,bt=kt.currentDispatcherRef,sn=kt.getCurrentFiber,rn=kt.workTagMap,Ft=sn();if(Ft!=null){var Dn=Bt(rn,Ft,bt);Dn!==""&&Je.push(Dn);break}}}catch(dr){xt.e(dr)}finally{xt.f()}}}catch{}_e.apply(void 0,Je)};Oe.__REACT_DEVTOOLS_ORIGINAL_METHOD__=_e,Ni[Ce]=Oe}catch{}})}}function Uu(U){return(Uu=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(H){return typeof H}:function(H){return H&&typeof Symbol=="function"&&H.constructor===Symbol&&H!==Symbol.prototype?"symbol":typeof H})(U)}function vs(U,H){for(var Y=0;Y"u"||!Reflect.construct||Reflect.construct.sham)return!1;if(typeof Proxy=="function")return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],function(){})),!0}catch{return!1}}();return function(){var Y,ee=Le(U);if(H){var Ce=Le(this).constructor;Y=Reflect.construct(ee,arguments,Ce)}else Y=ee.apply(this,arguments);return Se(this,Y)}}function Se(U,H){return!H||Uu(H)!=="object"&&typeof H!="function"?Fe(U):H}function Fe(U){if(U===void 0)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return U}function Le(U){return(Le=Object.setPrototypeOf?Object.getPrototypeOf:function(H){return H.__proto__||Object.getPrototypeOf(H)})(U)}function pt(U,H,Y){return H in U?Object.defineProperty(U,H,{value:Y,enumerable:!0,configurable:!0,writable:!0}):U[H]=Y,U}var Yn=function(U){(function(Oe,$){if(typeof $!="function"&&$!==null)throw new TypeError("Super expression must either be null or a function");Oe.prototype=Object.create($&&$.prototype,{constructor:{value:Oe,writable:!0,configurable:!0}}),$&&b0(Oe,$)})(_e,U);var H,Y,ee,Ce=Q(_e);function _e(Oe){var $;(function(oe,qe){if(!(oe instanceof qe))throw new TypeError("Cannot call a class as a function")})(this,_e),pt(Fe($=Ce.call(this)),"_isProfiling",!1),pt(Fe($),"_recordChangeDescriptions",!1),pt(Fe($),"_rendererInterfaces",{}),pt(Fe($),"_persistedSelection",null),pt(Fe($),"_persistedSelectionMatch",null),pt(Fe($),"_traceUpdatesEnabled",!1),pt(Fe($),"copyElementPath",function(oe){var qe=oe.id,rt=oe.path,xt=oe.rendererID,kt=$._rendererInterfaces[xt];kt==null?console.warn('Invalid renderer id "'.concat(xt,'" for element "').concat(qe,'"')):kt.copyElementPath(qe,rt)}),pt(Fe($),"deletePath",function(oe){var qe=oe.hookID,rt=oe.id,xt=oe.path,kt=oe.rendererID,bt=oe.type,sn=$._rendererInterfaces[kt];sn==null?console.warn('Invalid renderer id "'.concat(kt,'" for element "').concat(rt,'"')):sn.deletePath(bt,rt,qe,xt)}),pt(Fe($),"getProfilingData",function(oe){var qe=oe.rendererID,rt=$._rendererInterfaces[qe];rt==null&&console.warn('Invalid renderer id "'.concat(qe,'"')),$._bridge.send("profilingData",rt.getProfilingData())}),pt(Fe($),"getProfilingStatus",function(){$._bridge.send("profilingStatus",$._isProfiling)}),pt(Fe($),"getOwnersList",function(oe){var qe=oe.id,rt=oe.rendererID,xt=$._rendererInterfaces[rt];if(xt==null)console.warn('Invalid renderer id "'.concat(rt,'" for element "').concat(qe,'"'));else{var kt=xt.getOwnersList(qe);$._bridge.send("ownersList",{id:qe,owners:kt})}}),pt(Fe($),"inspectElement",function(oe){var qe=oe.id,rt=oe.path,xt=oe.rendererID,kt=$._rendererInterfaces[xt];kt==null?console.warn('Invalid renderer id "'.concat(xt,'" for element "').concat(qe,'"')):($._bridge.send("inspectedElement",kt.inspectElement(qe,rt)),$._persistedSelectionMatch!==null&&$._persistedSelectionMatch.id===qe||($._persistedSelection=null,$._persistedSelectionMatch=null,kt.setTrackedPath(null),$._throttledPersistSelection(xt,qe)))}),pt(Fe($),"logElementToConsole",function(oe){var qe=oe.id,rt=oe.rendererID,xt=$._rendererInterfaces[rt];xt==null?console.warn('Invalid renderer id "'.concat(rt,'" for element "').concat(qe,'"')):xt.logElementToConsole(qe)}),pt(Fe($),"overrideSuspense",function(oe){var qe=oe.id,rt=oe.rendererID,xt=oe.forceFallback,kt=$._rendererInterfaces[rt];kt==null?console.warn('Invalid renderer id "'.concat(rt,'" for element "').concat(qe,'"')):kt.overrideSuspense(qe,xt)}),pt(Fe($),"overrideValueAtPath",function(oe){var qe=oe.hookID,rt=oe.id,xt=oe.path,kt=oe.rendererID,bt=oe.type,sn=oe.value,rn=$._rendererInterfaces[kt];rn==null?console.warn('Invalid renderer id "'.concat(kt,'" for element "').concat(rt,'"')):rn.overrideValueAtPath(bt,rt,qe,xt,sn)}),pt(Fe($),"overrideContext",function(oe){var qe=oe.id,rt=oe.path,xt=oe.rendererID,kt=oe.wasForwarded,bt=oe.value;kt||$.overrideValueAtPath({id:qe,path:rt,rendererID:xt,type:"context",value:bt})}),pt(Fe($),"overrideHookState",function(oe){var qe=oe.id,rt=(oe.hookID,oe.path),xt=oe.rendererID,kt=oe.wasForwarded,bt=oe.value;kt||$.overrideValueAtPath({id:qe,path:rt,rendererID:xt,type:"hooks",value:bt})}),pt(Fe($),"overrideProps",function(oe){var qe=oe.id,rt=oe.path,xt=oe.rendererID,kt=oe.wasForwarded,bt=oe.value;kt||$.overrideValueAtPath({id:qe,path:rt,rendererID:xt,type:"props",value:bt})}),pt(Fe($),"overrideState",function(oe){var qe=oe.id,rt=oe.path,xt=oe.rendererID,kt=oe.wasForwarded,bt=oe.value;kt||$.overrideValueAtPath({id:qe,path:rt,rendererID:xt,type:"state",value:bt})}),pt(Fe($),"reloadAndProfile",function(oe){q("React::DevTools::reloadAndProfile","true"),q("React::DevTools::recordChangeDescriptions",oe?"true":"false"),$._bridge.send("reloadAppForProfiling")}),pt(Fe($),"renamePath",function(oe){var qe=oe.hookID,rt=oe.id,xt=oe.newPath,kt=oe.oldPath,bt=oe.rendererID,sn=oe.type,rn=$._rendererInterfaces[bt];rn==null?console.warn('Invalid renderer id "'.concat(bt,'" for element "').concat(rt,'"')):rn.renamePath(sn,rt,qe,kt,xt)}),pt(Fe($),"setTraceUpdatesEnabled",function(oe){for(var qe in $._traceUpdatesEnabled=oe,Vt(oe),$._rendererInterfaces)$._rendererInterfaces[qe].setTraceUpdatesEnabled(oe)}),pt(Fe($),"syncSelectionFromNativeElementsPanel",function(){var oe=window.__REACT_DEVTOOLS_GLOBAL_HOOK__.$0;oe!=null&&$.selectNode(oe)}),pt(Fe($),"shutdown",function(){$.emit("shutdown")}),pt(Fe($),"startProfiling",function(oe){for(var qe in $._recordChangeDescriptions=oe,$._isProfiling=!0,$._rendererInterfaces)$._rendererInterfaces[qe].startProfiling(oe);$._bridge.send("profilingStatus",$._isProfiling)}),pt(Fe($),"stopProfiling",function(){for(var oe in $._isProfiling=!1,$._recordChangeDescriptions=!1,$._rendererInterfaces)$._rendererInterfaces[oe].stopProfiling();$._bridge.send("profilingStatus",$._isProfiling)}),pt(Fe($),"storeAsGlobal",function(oe){var qe=oe.count,rt=oe.id,xt=oe.path,kt=oe.rendererID,bt=$._rendererInterfaces[kt];bt==null?console.warn('Invalid renderer id "'.concat(kt,'" for element "').concat(rt,'"')):bt.storeAsGlobal(rt,xt,qe)}),pt(Fe($),"updateConsolePatchSettings",function(oe){var qe=oe.appendComponentStack,rt=oe.breakOnConsoleErrors;qe||rt?Jl({appendComponentStack:qe,breakOnConsoleErrors:rt}):Ct!==null&&(Ct(),Ct=null)}),pt(Fe($),"updateComponentFilters",function(oe){for(var qe in $._rendererInterfaces)$._rendererInterfaces[qe].updateComponentFilters(oe)}),pt(Fe($),"viewAttributeSource",function(oe){var qe=oe.id,rt=oe.path,xt=oe.rendererID,kt=$._rendererInterfaces[xt];kt==null?console.warn('Invalid renderer id "'.concat(xt,'" for element "').concat(qe,'"')):kt.prepareViewAttributeSource(qe,rt)}),pt(Fe($),"viewElementSource",function(oe){var qe=oe.id,rt=oe.rendererID,xt=$._rendererInterfaces[rt];xt==null?console.warn('Invalid renderer id "'.concat(rt,'" for element "').concat(qe,'"')):xt.prepareViewElementSource(qe)}),pt(Fe($),"onTraceUpdates",function(oe){$.emit("traceUpdates",oe)}),pt(Fe($),"onHookOperations",function(oe){if($._bridge.send("operations",oe),$._persistedSelection!==null){var qe=oe[0];if($._persistedSelection.rendererID===qe){var rt=$._rendererInterfaces[qe];if(rt==null)console.warn('Invalid renderer id "'.concat(qe,'"'));else{var xt=$._persistedSelectionMatch,kt=rt.getBestMatchForTrackedPath();$._persistedSelectionMatch=kt;var bt=xt!==null?xt.id:null,sn=kt!==null?kt.id:null;bt!==sn&&sn!==null&&$._bridge.send("selectFiber",sn),kt!==null&&kt.isFullMatch&&($._persistedSelection=null,$._persistedSelectionMatch=null,rt.setTrackedPath(null))}}}}),pt(Fe($),"_throttledPersistSelection",N()(function(oe,qe){var rt=$._rendererInterfaces[oe],xt=rt!=null?rt.getPathForElement(qe):null;xt!==null?q("React::DevTools::lastSelection",JSON.stringify({rendererID:oe,path:xt})):j("React::DevTools::lastSelection")},1e3)),x("React::DevTools::reloadAndProfile")==="true"&&($._recordChangeDescriptions=x("React::DevTools::recordChangeDescriptions")==="true",$._isProfiling=!0,j("React::DevTools::recordChangeDescriptions"),j("React::DevTools::reloadAndProfile"));var Ne=x("React::DevTools::lastSelection");Ne!=null&&($._persistedSelection=JSON.parse(Ne)),$._bridge=Oe,Oe.addListener("copyElementPath",$.copyElementPath),Oe.addListener("deletePath",$.deletePath),Oe.addListener("getProfilingData",$.getProfilingData),Oe.addListener("getProfilingStatus",$.getProfilingStatus),Oe.addListener("getOwnersList",$.getOwnersList),Oe.addListener("inspectElement",$.inspectElement),Oe.addListener("logElementToConsole",$.logElementToConsole),Oe.addListener("overrideSuspense",$.overrideSuspense),Oe.addListener("overrideValueAtPath",$.overrideValueAtPath),Oe.addListener("reloadAndProfile",$.reloadAndProfile),Oe.addListener("renamePath",$.renamePath),Oe.addListener("setTraceUpdatesEnabled",$.setTraceUpdatesEnabled),Oe.addListener("startProfiling",$.startProfiling),Oe.addListener("stopProfiling",$.stopProfiling),Oe.addListener("storeAsGlobal",$.storeAsGlobal),Oe.addListener("syncSelectionFromNativeElementsPanel",$.syncSelectionFromNativeElementsPanel),Oe.addListener("shutdown",$.shutdown),Oe.addListener("updateConsolePatchSettings",$.updateConsolePatchSettings),Oe.addListener("updateComponentFilters",$.updateComponentFilters),Oe.addListener("viewAttributeSource",$.viewAttributeSource),Oe.addListener("viewElementSource",$.viewElementSource),Oe.addListener("overrideContext",$.overrideContext),Oe.addListener("overrideHookState",$.overrideHookState),Oe.addListener("overrideProps",$.overrideProps),Oe.addListener("overrideState",$.overrideState),$._isProfiling&&Oe.send("profilingStatus",!0);var Je,vt=!1;try{localStorage.getItem("test"),vt=!0}catch{}return Oe.send("isBackendStorageAPISupported",vt),Re(Oe,Fe($)),Je=Fe($),Je.addListener("traceUpdates",Er),$}return H=_e,(Y=[{key:"getInstanceAndStyle",value:function(Oe){var $=Oe.id,Ne=Oe.rendererID,Je=this._rendererInterfaces[Ne];return Je==null?(console.warn('Invalid renderer id "'.concat(Ne,'"')),null):Je.getInstanceAndStyle($)}},{key:"getIDForNode",value:function(Oe){for(var $ in this._rendererInterfaces){var Ne=this._rendererInterfaces[$];try{var Je=Ne.getFiberIDForNative(Oe,!0);if(Je!==null)return Je}catch{}}return null}},{key:"selectNode",value:function(Oe){var $=this.getIDForNode(Oe);$!==null&&this._bridge.send("selectFiber",$)}},{key:"setRendererInterface",value:function(Oe,$){this._rendererInterfaces[Oe]=$,this._isProfiling&&$.startProfiling(this._recordChangeDescriptions),$.setTraceUpdatesEnabled(this._traceUpdatesEnabled);var Ne=this._persistedSelection;Ne!==null&&Ne.rendererID===Oe&&$.setTrackedPath(Ne.path)}},{key:"onUnsupportedRenderer",value:function(Oe){this._bridge.send("unsupportedRendererVersion",Oe)}},{key:"rendererInterfaces",get:function(){return this._rendererInterfaces}}])&&vs(H.prototype,Y),ee&&vs(H,ee),_e}(E);function Cn(U){return(Cn=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(H){return typeof H}:function(H){return H&&typeof Symbol=="function"&&H.constructor===Symbol&&H!==Symbol.prototype?"symbol":typeof H})(U)}function cr(U){return function(H){if(Array.isArray(H))return Si(H)}(U)||function(H){if(typeof Symbol<"u"&&Symbol.iterator in Object(H))return Array.from(H)}(U)||function(H,Y){if(!!H){if(typeof H=="string")return Si(H,Y);var ee=Object.prototype.toString.call(H).slice(8,-1);if(ee==="Object"&&H.constructor&&(ee=H.constructor.name),ee==="Map"||ee==="Set")return Array.from(H);if(ee==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(ee))return Si(H,Y)}}(U)||function(){throw new TypeError(`Invalid attempt to spread non-iterable instance. +In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}()}function Si(U,H){(H==null||H>U.length)&&(H=U.length);for(var Y=0,ee=new Array(H);Y"u"||!Reflect.construct||Reflect.construct.sham)return!1;if(typeof Proxy=="function")return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],function(){})),!0}catch{return!1}}();return function(){var Y,ee=Fo(U);if(H){var Ce=Fo(this).constructor;Y=Reflect.construct(ee,arguments,Ce)}else Y=ee.apply(this,arguments);return wu(this,Y)}}function wu(U,H){return!H||Cn(H)!=="object"&&typeof H!="function"?Ti(U):H}function Ti(U){if(U===void 0)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return U}function Fo(U){return(Fo=Object.setPrototypeOf?Object.getPrototypeOf:function(H){return H.__proto__||Object.getPrototypeOf(H)})(U)}function Mu(U,H,Y){return H in U?Object.defineProperty(U,H,{value:Y,enumerable:!0,configurable:!0,writable:!0}):U[H]=Y,U}var po=function(U){(function(Oe,$){if(typeof $!="function"&&$!==null)throw new TypeError("Super expression must either be null or a function");Oe.prototype=Object.create($&&$.prototype,{constructor:{value:Oe,writable:!0,configurable:!0}}),$&&ju(Oe,$)})(_e,U);var H,Y,ee,Ce=zu(_e);function _e(Oe){var $;return function(Ne,Je){if(!(Ne instanceof Je))throw new TypeError("Cannot call a class as a function")}(this,_e),Mu(Ti($=Ce.call(this)),"_isShutdown",!1),Mu(Ti($),"_messageQueue",[]),Mu(Ti($),"_timeoutID",null),Mu(Ti($),"_wallUnlisten",null),Mu(Ti($),"_flush",function(){if($._timeoutID!==null&&(clearTimeout($._timeoutID),$._timeoutID=null),$._messageQueue.length){for(var Ne=0;Ne<$._messageQueue.length;Ne+=2){var Je;(Je=$._wall).send.apply(Je,[$._messageQueue[Ne]].concat(cr($._messageQueue[Ne+1])))}$._messageQueue.length=0,$._timeoutID=setTimeout($._flush,100)}}),Mu(Ti($),"overrideValueAtPath",function(Ne){var Je=Ne.id,vt=Ne.path,oe=Ne.rendererID,qe=Ne.type,rt=Ne.value;switch(qe){case"context":$.send("overrideContext",{id:Je,path:vt,rendererID:oe,wasForwarded:!0,value:rt});break;case"hooks":$.send("overrideHookState",{id:Je,path:vt,rendererID:oe,wasForwarded:!0,value:rt});break;case"props":$.send("overrideProps",{id:Je,path:vt,rendererID:oe,wasForwarded:!0,value:rt});break;case"state":$.send("overrideState",{id:Je,path:vt,rendererID:oe,wasForwarded:!0,value:rt})}}),$._wall=Oe,$._wallUnlisten=Oe.listen(function(Ne){Ti($).emit(Ne.event,Ne.payload)})||null,$.addListener("overrideValueAtPath",$.overrideValueAtPath),$}return H=_e,(Y=[{key:"send",value:function(Oe){if(this._isShutdown)console.warn('Cannot send message "'.concat(Oe,'" through a Bridge that has been shutdown.'));else{for(var $=arguments.length,Ne=new Array($>1?$-1:0),Je=1;Je<$;Je++)Ne[Je-1]=arguments[Je];this._messageQueue.push(Oe,Ne),this._timeoutID||(this._timeoutID=setTimeout(this._flush,0))}}},{key:"shutdown",value:function(){if(this._isShutdown)console.warn("Bridge was already shutdown.");else{this.send("shutdown"),this._isShutdown=!0,this.addListener=function(){},this.emit=function(){},this.removeAllListeners();var Oe=this._wallUnlisten;Oe&&Oe();do this._flush();while(this._messageQueue.length);this._timeoutID!==null&&(clearTimeout(this._timeoutID),this._timeoutID=null)}}},{key:"wall",get:function(){return this._wall}}])&&Ou(H.prototype,Y),ee&&Ou(H,ee),_e}(E);function Hu(U,H,Y){var ee=U[H];return U[H]=function(Ce){return Y.call(this,ee,arguments)},ee}function Pa(U,H){for(var Y in H)U[Y]=H[Y]}function v0(U){typeof U.forceUpdate=="function"?U.forceUpdate():U.updater!=null&&typeof U.updater.enqueueForceUpdate=="function"&&U.updater.enqueueForceUpdate(this,function(){},"forceUpdate")}function ia(U,H){var Y=Object.keys(U);if(Object.getOwnPropertySymbols){var ee=Object.getOwnPropertySymbols(U);H&&(ee=ee.filter(function(Ce){return Object.getOwnPropertyDescriptor(U,Ce).enumerable})),Y.push.apply(Y,ee)}return Y}function J0(U){for(var H=1;H0?oe[oe.length-1]:0),oe.push(un),$.set(et,Je(It._topLevelWrapper));try{var fn=ut.apply(this,wt);return oe.pop(),fn}catch(wr){throw oe=[],wr}finally{if(oe.length===0){var Jn=$.get(et);if(Jn===void 0)throw new Error("Expected to find root ID.");dr(Jn)}}},performUpdateIfNecessary:function(ut,wt){var et=wt[0];if(S0(et)===9)return ut.apply(this,wt);var It=Je(et);oe.push(It);var un=Qn(et);try{var fn=ut.apply(this,wt),Jn=Qn(et);return vt(un,Jn)||xt(et,It,Jn),oe.pop(),fn}catch(au){throw oe=[],au}finally{if(oe.length===0){var wr=$.get(et);if(wr===void 0)throw new Error("Expected to find root ID.");dr(wr)}}},receiveComponent:function(ut,wt){var et=wt[0];if(S0(et)===9)return ut.apply(this,wt);var It=Je(et);oe.push(It);var un=Qn(et);try{var fn=ut.apply(this,wt),Jn=Qn(et);return vt(un,Jn)||xt(et,It,Jn),oe.pop(),fn}catch(au){throw oe=[],au}finally{if(oe.length===0){var wr=$.get(et);if(wr===void 0)throw new Error("Expected to find root ID.");dr(wr)}}},unmountComponent:function(ut,wt){var et=wt[0];if(S0(et)===9)return ut.apply(this,wt);var It=Je(et);oe.push(It);try{var un=ut.apply(this,wt);return oe.pop(),function(Jn,wr){rn.push(wr),_e.delete(wr)}(0,It),un}catch(Jn){throw oe=[],Jn}finally{if(oe.length===0){var fn=$.get(et);if(fn===void 0)throw new Error("Expected to find root ID.");dr(fn)}}}}));var bt=[],sn=new Map,rn=[],Ft=0,Dn=null;function dr(ut){if(bt.length!==0||rn.length!==0||Dn!==null){var wt=rn.length+(Dn===null?0:1),et=new Array(3+Ft+(wt>0?2+wt:0)+bt.length),It=0;if(et[It++]=H,et[It++]=ut,et[It++]=Ft,sn.forEach(function(Jn,wr){et[It++]=wr.length;for(var au=Y0(wr),ku=0;ku0){et[It++]=2,et[It++]=wt;for(var un=0;un"),"color: var(--dom-tag-name-color); font-weight: normal;"),wt.props!==null&&console.log("Props:",wt.props),wt.state!==null&&console.log("State:",wt.state),wt.context!==null&&console.log("Context:",wt.context);var It=Ce(ut);It!==null&&console.log("Node:",It),(window.chrome||/firefox/i.test(navigator.userAgent))&&console.log("Right-click any value to save it as a global variable for further inspection."),et&&console.groupEnd()}else console.warn('Could not find element with id "'.concat(ut,'"'))},overrideSuspense:function(){throw new Error("overrideSuspense not supported by this renderer")},overrideValueAtPath:function(ut,wt,et,It,un){var fn=_e.get(wt);if(fn!=null){var Jn=fn._instance;if(Jn!=null)switch(ut){case"context":Oo(Jn.context,It,un),v0(Jn);break;case"hooks":throw new Error("Hooks not supported by this renderer");case"props":var wr=fn._currentElement;fn._currentElement=J0(J0({},wr),{},{props:In(wr.props,It,un)}),v0(Jn);break;case"state":Oo(Jn.state,It,un),v0(Jn)}}},renamePath:function(ut,wt,et,It,un){var fn=_e.get(wt);if(fn!=null){var Jn=fn._instance;if(Jn!=null)switch(ut){case"context":Kr(Jn.context,It,un),v0(Jn);break;case"hooks":throw new Error("Hooks not supported by this renderer");case"props":var wr=fn._currentElement;fn._currentElement=J0(J0({},wr),{},{props:en(wr.props,It,un)}),v0(Jn);break;case"state":Kr(Jn.state,It,un),v0(Jn)}}},prepareViewAttributeSource:function(ut,wt){var et=Lr(ut);et!==null&&(window.$attribute=Bu(et,wt))},prepareViewElementSource:function(ut){var wt=_e.get(ut);if(wt!=null){var et=wt._currentElement;et!=null?ee.$type=et.type:console.warn('Could not find element with id "'.concat(ut,'"'))}else console.warn('Could not find instance with id "'.concat(ut,'"'))},renderer:Y,setTraceUpdatesEnabled:function(ut){},setTrackedPath:function(ut){},startProfiling:function(){},stopProfiling:function(){},storeAsGlobal:function(ut,wt,et){var It=Lr(ut);if(It!==null){var un=Bu(It,wt),fn="$reactTemp".concat(et);window[fn]=un,console.log(fn),console.log(un)}},updateComponentFilters:function(ut){}}}function si(U,H){var Y=!1,ee={bottom:0,left:0,right:0,top:0},Ce=H[U];if(Ce!=null){for(var _e=0,Oe=Object.keys(ee);_e0?"development":"production";var bt=Function.prototype.toString;if(kt.Mount&&kt.Mount._renderNewRootComponent){var sn=bt.call(kt.Mount._renderNewRootComponent);return sn.indexOf("function")!==0?"production":sn.indexOf("storedMeasure")!==-1?"development":sn.indexOf("should be a pure function")!==-1?sn.indexOf("NODE_ENV")!==-1||sn.indexOf("development")!==-1||sn.indexOf("true")!==-1?"development":sn.indexOf("nextElement")!==-1||sn.indexOf("nextComponent")!==-1?"unminified":"development":sn.indexOf("nextElement")!==-1||sn.indexOf("nextComponent")!==-1?"unminified":"outdated"}}catch{}return"production"}(Ne);try{var oe=window.__REACT_DEVTOOLS_APPEND_COMPONENT_STACK__!==!1,qe=window.__REACT_DEVTOOLS_BREAK_ON_CONSOLE_ERRORS__===!0;(oe||qe)&&(co(Ne),Jl({appendComponentStack:oe,breakOnConsoleErrors:qe}))}catch{}var rt=U.__REACT_DEVTOOLS_ATTACH__;if(typeof rt=="function"){var xt=rt($,Je,Ne,U);$.rendererInterfaces.set(Je,xt)}return $.emit("renderer",{id:Je,renderer:Ne,reactBuildType:vt}),Je},on:function(Ne,Je){_e[Ne]||(_e[Ne]=[]),_e[Ne].push(Je)},off:function(Ne,Je){if(_e[Ne]){var vt=_e[Ne].indexOf(Je);vt!==-1&&_e[Ne].splice(vt,1),_e[Ne].length||delete _e[Ne]}},sub:function(Ne,Je){return $.on(Ne,Je),function(){return $.off(Ne,Je)}},supportsFiber:!0,checkDCE:function(Ne){try{Function.prototype.toString.call(Ne).indexOf("^_^")>-1&&(Y=!0,setTimeout(function(){throw new Error("React is running in production mode, but dead code elimination has not been applied. Read how to correctly configure React for production: https://reactjs.org/link/perf-use-production-build")}))}catch{}},onCommitFiberUnmount:function(Ne,Je){var vt=Ce.get(Ne);vt!=null&&vt.handleCommitFiberUnmount(Je)},onCommitFiberRoot:function(Ne,Je,vt){var oe=$.getFiberRoots(Ne),qe=Je.current,rt=oe.has(Je),xt=qe.memoizedState==null||qe.memoizedState.element==null;rt||xt?rt&&xt&&oe.delete(Je):oe.add(Je);var kt=Ce.get(Ne);kt!=null&&kt.handleCommitFiberRoot(Je,vt)}};Object.defineProperty(U,"__REACT_DEVTOOLS_GLOBAL_HOOK__",{configurable:!1,enumerable:!1,get:function(){return $}})})(window);var m0=window.__REACT_DEVTOOLS_GLOBAL_HOOK__,Us=[{type:1,value:7,isEnabled:!0}];function zi(U){if(m0!=null){var H=U||{},Y=H.host,ee=Y===void 0?"localhost":Y,Ce=H.nativeStyleEditorValidAttributes,_e=H.useHttps,Oe=_e!==void 0&&_e,$=H.port,Ne=$===void 0?8097:$,Je=H.websocket,vt=H.resolveRNStyle,oe=vt===void 0?null:vt,qe=H.isAppActive,rt=Oe?"wss":"ws",xt=null;if((qe===void 0?function(){return!0}:qe)()){var kt=null,bt=[],sn=rt+"://"+ee+":"+Ne,rn=Je||new window.WebSocket(sn);rn.onclose=function(){kt!==null&&kt.emit("shutdown"),Ft()},rn.onerror=function(){Ft()},rn.onmessage=function(Dn){var dr;try{if(typeof Dn.data!="string")throw Error();dr=JSON.parse(Dn.data)}catch{return void console.error("[React DevTools] Failed to parse JSON: "+Dn.data)}bt.forEach(function(er){try{er(dr)}catch(Cr){throw console.log("[React DevTools] Error calling listener",dr),console.log("error:",Cr),Cr}})},rn.onopen=function(){(kt=new po({listen:function(Rn){return bt.push(Rn),function(){var Nr=bt.indexOf(Rn);Nr>=0&&bt.splice(Nr,1)}},send:function(Rn,Nr,y0){rn.readyState===rn.OPEN?rn.send(JSON.stringify({event:Rn,payload:Nr})):(kt!==null&&kt.shutdown(),Ft())}})).addListener("inspectElement",function(Rn){var Nr=Rn.id,y0=Rn.rendererID,Lr=Dn.rendererInterfaces[y0];if(Lr!=null){var ut=Lr.findNativeNodesForFiberID(Nr);ut!=null&&ut[0]!=null&&Dn.emit("showNativeHighlight",ut[0])}}),kt.addListener("updateComponentFilters",function(Rn){Us=Rn}),window.__REACT_DEVTOOLS_COMPONENT_FILTERS__==null&&kt.send("overrideComponentFilters",Us);var Dn=new Yn(kt);if(Dn.addListener("shutdown",function(){m0.emit("shutdown")}),function(Rn,Nr,y0){if(Rn==null)return function(){};var Lr=[Rn.sub("renderer-attached",function(et){var It=et.id,un=(et.renderer,et.rendererInterface);Nr.setRendererInterface(It,un),un.flushInitialOperations()}),Rn.sub("unsupported-renderer-version",function(et){Nr.onUnsupportedRenderer(et)}),Rn.sub("operations",Nr.onHookOperations),Rn.sub("traceUpdates",Nr.onTraceUpdates)],ut=function(et,It){var un=Rn.rendererInterfaces.get(et);un==null&&(typeof It.findFiberByHostInstance=="function"?un=Is(Rn,et,It,y0):It.ComponentTree&&(un=ac(Rn,et,It,y0)),un!=null&&Rn.rendererInterfaces.set(et,un)),un!=null?Rn.emit("renderer-attached",{id:et,renderer:It,rendererInterface:un}):Rn.emit("unsupported-renderer-version",et)};Rn.renderers.forEach(function(et,It){ut(It,et)}),Lr.push(Rn.sub("renderer",function(et){var It=et.id,un=et.renderer;ut(It,un)})),Rn.emit("react-devtools",Nr),Rn.reactDevtoolsAgent=Nr;var wt=function(){Lr.forEach(function(et){return et()}),Rn.rendererInterfaces.forEach(function(et){et.cleanup()}),Rn.reactDevtoolsAgent=null};Nr.addListener("shutdown",wt),Lr.push(function(){Nr.removeListener("shutdown",wt)})}(m0,Dn,window),oe!=null||m0.resolveRNStyle!=null)oa(kt,Dn,oe||m0.resolveRNStyle,Ce||m0.nativeStyleEditorValidAttributes||null);else{var dr,er,Cr=function(){kt!==null&&oa(kt,Dn,dr,er)};m0.hasOwnProperty("resolveRNStyle")||Object.defineProperty(m0,"resolveRNStyle",{enumerable:!1,get:function(){return dr},set:function(Rn){dr=Rn,Cr()}}),m0.hasOwnProperty("nativeStyleEditorValidAttributes")||Object.defineProperty(m0,"nativeStyleEditorValidAttributes",{enumerable:!1,get:function(){return er},set:function(Rn){er=Rn,Cr()}})}}}else Ft()}function Ft(){xt===null&&(xt=setTimeout(function(){return zi(U)},2e3))}}}])})});var FC=nt(LC=>{"use strict";Object.defineProperty(LC,"__esModule",{value:!0});kC();var wb=NC();wb.connectToDevTools()});var UC=nt(sg=>{"use strict";var BC=sg&&sg.__importDefault||function(o){return o&&o.__esModule?o:{default:o}};Object.defineProperty(sg,"__esModule",{value:!0});var PC=z_(),Sb=BC(YS()),IC=BC(eh()),ps=BD();process.env.DEV==="true"&&FC();var bC=o=>{o==null||o.unsetMeasureFunc(),o==null||o.freeRecursive()};sg.default=Sb.default({schedulePassiveEffects:PC.unstable_scheduleCallback,cancelPassiveEffects:PC.unstable_cancelCallback,now:Date.now,getRootHostContext:()=>({isInsideText:!1}),prepareForCommit:()=>{},resetAfterCommit:o=>{if(o.isStaticDirty){o.isStaticDirty=!1,typeof o.onImmediateRender=="function"&&o.onImmediateRender();return}typeof o.onRender=="function"&&o.onRender()},getChildHostContext:(o,l)=>{let f=o.isInsideText,h=l==="ink-text"||l==="ink-virtual-text";return f===h?o:{isInsideText:h}},shouldSetTextContent:()=>!1,createInstance:(o,l,f,h)=>{if(h.isInsideText&&o==="ink-box")throw new Error(" can\u2019t be nested inside component");let E=o==="ink-text"&&h.isInsideText?"ink-virtual-text":o,t=ps.createNode(E);for(let[N,F]of Object.entries(l))N!=="children"&&(N==="style"?ps.setStyle(t,F):N==="internal_transform"?t.internal_transform=F:N==="internal_static"?t.internal_static=!0:ps.setAttribute(t,N,F));return t},createTextInstance:(o,l,f)=>{if(!f.isInsideText)throw new Error(`Text string "${o}" must be rendered inside component`);return ps.createTextNode(o)},resetTextContent:()=>{},hideTextInstance:o=>{ps.setTextNodeValue(o,"")},unhideTextInstance:(o,l)=>{ps.setTextNodeValue(o,l)},getPublicInstance:o=>o,hideInstance:o=>{var l;(l=o.yogaNode)===null||l===void 0||l.setDisplay(IC.default.DISPLAY_NONE)},unhideInstance:o=>{var l;(l=o.yogaNode)===null||l===void 0||l.setDisplay(IC.default.DISPLAY_FLEX)},appendInitialChild:ps.appendChildNode,appendChild:ps.appendChildNode,insertBefore:ps.insertBeforeNode,finalizeInitialChildren:(o,l,f,h)=>(o.internal_static&&(h.isStaticDirty=!0,h.staticNode=o),!1),supportsMutation:!0,appendChildToContainer:ps.appendChildNode,insertInContainerBefore:ps.insertBeforeNode,removeChildFromContainer:(o,l)=>{ps.removeChildNode(o,l),bC(l.yogaNode)},prepareUpdate:(o,l,f,h,E)=>{o.internal_static&&(E.isStaticDirty=!0);let t={},N=Object.keys(h);for(let F of N)if(h[F]!==f[F]){if(F==="style"&&typeof h.style=="object"&&typeof f.style=="object"){let x=h.style,j=f.style,q=Object.keys(x);for(let V of q){if(V==="borderStyle"||V==="borderColor"){if(typeof t.style!="object"){let re={};t.style=re}t.style.borderStyle=x.borderStyle,t.style.borderColor=x.borderColor}if(x[V]!==j[V]){if(typeof t.style!="object"){let re={};t.style=re}t.style[V]=x[V]}}continue}t[F]=h[F]}return t},commitUpdate:(o,l)=>{for(let[f,h]of Object.entries(l))f!=="children"&&(f==="style"?ps.setStyle(o,h):f==="internal_transform"?o.internal_transform=h:f==="internal_static"?o.internal_static=!0:ps.setAttribute(o,f,h))},commitTextUpdate:(o,l,f)=>{ps.setTextNodeValue(o,f)},removeChild:(o,l)=>{ps.removeChildNode(o,l),bC(l.yogaNode)}})});var zC=nt((sq,jC)=>{"use strict";jC.exports=(o,l=1,f)=>{if(f={indent:" ",includeEmptyLines:!1,...f},typeof o!="string")throw new TypeError(`Expected \`input\` to be a \`string\`, got \`${typeof o}\``);if(typeof l!="number")throw new TypeError(`Expected \`count\` to be a \`number\`, got \`${typeof l}\``);if(typeof f.indent!="string")throw new TypeError(`Expected \`options.indent\` to be a \`string\`, got \`${typeof f.indent}\``);if(l===0)return o;let h=f.includeEmptyLines?/^/gm:/^(?!\s*$)/gm;return o.replace(h,f.indent.repeat(l))}});var HC=nt(ag=>{"use strict";var Tb=ag&&ag.__importDefault||function(o){return o&&o.__esModule?o:{default:o}};Object.defineProperty(ag,"__esModule",{value:!0});var r4=Tb(eh());ag.default=o=>o.getComputedWidth()-o.getComputedPadding(r4.default.EDGE_LEFT)-o.getComputedPadding(r4.default.EDGE_RIGHT)-o.getComputedBorder(r4.default.EDGE_LEFT)-o.getComputedBorder(r4.default.EDGE_RIGHT)});var qC=nt((fq,Cb)=>{Cb.exports={single:{topLeft:"\u250C",topRight:"\u2510",bottomRight:"\u2518",bottomLeft:"\u2514",vertical:"\u2502",horizontal:"\u2500"},double:{topLeft:"\u2554",topRight:"\u2557",bottomRight:"\u255D",bottomLeft:"\u255A",vertical:"\u2551",horizontal:"\u2550"},round:{topLeft:"\u256D",topRight:"\u256E",bottomRight:"\u256F",bottomLeft:"\u2570",vertical:"\u2502",horizontal:"\u2500"},bold:{topLeft:"\u250F",topRight:"\u2513",bottomRight:"\u251B",bottomLeft:"\u2517",vertical:"\u2503",horizontal:"\u2501"},singleDouble:{topLeft:"\u2553",topRight:"\u2556",bottomRight:"\u255C",bottomLeft:"\u2559",vertical:"\u2551",horizontal:"\u2500"},doubleSingle:{topLeft:"\u2552",topRight:"\u2555",bottomRight:"\u255B",bottomLeft:"\u2558",vertical:"\u2502",horizontal:"\u2550"},classic:{topLeft:"+",topRight:"+",bottomRight:"+",bottomLeft:"+",vertical:"|",horizontal:"-"}}});var VC=nt((cq,c3)=>{"use strict";var WC=qC();c3.exports=WC;c3.exports.default=WC});var YC=nt((dq,GC)=>{"use strict";GC.exports=(o,l=process.argv)=>{let f=o.startsWith("-")?"":o.length===1?"-":"--",h=l.indexOf(f+o),E=l.indexOf("--");return h!==-1&&(E===-1||h{"use strict";var xb=hi("os"),KC=hi("tty"),df=YC(),{env:Xo}=process,h2;df("no-color")||df("no-colors")||df("color=false")||df("color=never")?h2=0:(df("color")||df("colors")||df("color=true")||df("color=always"))&&(h2=1);"FORCE_COLOR"in Xo&&(Xo.FORCE_COLOR==="true"?h2=1:Xo.FORCE_COLOR==="false"?h2=0:h2=Xo.FORCE_COLOR.length===0?1:Math.min(parseInt(Xo.FORCE_COLOR,10),3));function d3(o){return o===0?!1:{level:o,hasBasic:!0,has256:o>=2,has16m:o>=3}}function p3(o,l){if(h2===0)return 0;if(df("color=16m")||df("color=full")||df("color=truecolor"))return 3;if(df("color=256"))return 2;if(o&&!l&&h2===void 0)return 0;let f=h2||0;if(Xo.TERM==="dumb")return f;if(process.platform==="win32"){let h=xb.release().split(".");return Number(h[0])>=10&&Number(h[2])>=10586?Number(h[2])>=14931?3:2:1}if("CI"in Xo)return["TRAVIS","CIRCLECI","APPVEYOR","GITLAB_CI"].some(h=>h in Xo)||Xo.CI_NAME==="codeship"?1:f;if("TEAMCITY_VERSION"in Xo)return/^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(Xo.TEAMCITY_VERSION)?1:0;if("GITHUB_ACTIONS"in Xo)return 1;if(Xo.COLORTERM==="truecolor")return 3;if("TERM_PROGRAM"in Xo){let h=parseInt((Xo.TERM_PROGRAM_VERSION||"").split(".")[0],10);switch(Xo.TERM_PROGRAM){case"iTerm.app":return h>=3?3:2;case"Apple_Terminal":return 2}}return/-256(color)?$/i.test(Xo.TERM)?2:/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(Xo.TERM)||"COLORTERM"in Xo?1:f}function Rb(o){let l=p3(o,o&&o.isTTY);return d3(l)}XC.exports={supportsColor:Rb,stdout:d3(p3(!0,KC.isatty(1))),stderr:d3(p3(!0,KC.isatty(2)))}});var ZC=nt((hq,JC)=>{"use strict";var Ab=(o,l,f)=>{let h=o.indexOf(l);if(h===-1)return o;let E=l.length,t=0,N="";do N+=o.substr(t,h-t)+l+f,t=h+E,h=o.indexOf(l,t);while(h!==-1);return N+=o.substr(t),N},Ob=(o,l,f,h)=>{let E=0,t="";do{let N=o[h-1]==="\r";t+=o.substr(E,(N?h-1:h)-E)+l+(N?`\r +`:` +`)+f,E=h+1,h=o.indexOf(` +`,E)}while(h!==-1);return t+=o.substr(E),t};JC.exports={stringReplaceAll:Ab,stringEncaseCRLFWithFirstIndex:Ob}});var r6=nt((vq,n6)=>{"use strict";var Mb=/(?:\\(u(?:[a-f\d]{4}|\{[a-f\d]{1,6}\})|x[a-f\d]{2}|.))|(?:\{(~)?(\w+(?:\([^)]*\))?(?:\.\w+(?:\([^)]*\))?)*)(?:[ \t]|(?=\r?\n)))|(\})|((?:.|[\r\n\f])+?)/gi,$C=/(?:^|\.)(\w+)(?:\(([^)]*)\))?/g,kb=/^(['"])((?:\\.|(?!\1)[^\\])*)\1$/,Nb=/\\(u(?:[a-f\d]{4}|{[a-f\d]{1,6}})|x[a-f\d]{2}|.)|([^\\])/gi,Lb=new Map([["n",` +`],["r","\r"],["t"," "],["b","\b"],["f","\f"],["v","\v"],["0","\0"],["\\","\\"],["e","\x1B"],["a","\x07"]]);function t6(o){let l=o[0]==="u",f=o[1]==="{";return l&&!f&&o.length===5||o[0]==="x"&&o.length===3?String.fromCharCode(parseInt(o.slice(1),16)):l&&f?String.fromCodePoint(parseInt(o.slice(2,-1),16)):Lb.get(o)||o}function Fb(o,l){let f=[],h=l.trim().split(/\s*,\s*/g),E;for(let t of h){let N=Number(t);if(!Number.isNaN(N))f.push(N);else if(E=t.match(kb))f.push(E[2].replace(Nb,(F,k,x)=>k?t6(k):x));else throw new Error(`Invalid Chalk template style argument: ${t} (in style '${o}')`)}return f}function Pb(o){$C.lastIndex=0;let l=[],f;for(;(f=$C.exec(o))!==null;){let h=f[1];if(f[2]){let E=Fb(h,f[2]);l.push([h].concat(E))}else l.push([h])}return l}function e6(o,l){let f={};for(let E of l)for(let t of E.styles)f[t[0]]=E.inverse?null:t.slice(1);let h=o;for(let[E,t]of Object.entries(f))if(!!Array.isArray(t)){if(!(E in h))throw new Error(`Unknown Chalk style: ${E}`);h=t.length>0?h[E](...t):h[E]}return h}n6.exports=(o,l)=>{let f=[],h=[],E=[];if(l.replace(Mb,(t,N,F,k,x,j)=>{if(N)E.push(t6(N));else if(k){let q=E.join("");E=[],h.push(f.length===0?q:e6(o,f)(q)),f.push({inverse:F,styles:Pb(k)})}else if(x){if(f.length===0)throw new Error("Found extraneous } in Chalk template literal");h.push(e6(o,f)(E.join(""))),E=[],f.pop()}else E.push(j)}),h.push(E.join("")),f.length>0){let t=`Chalk template literal is missing ${f.length} closing bracket${f.length===1?"":"s"} (\`}\`)`;throw new Error(t)}return h.join("")}});var s4=nt((mq,a6)=>{"use strict";var fg=G_(),{stdout:v3,stderr:m3}=QC(),{stringReplaceAll:Ib,stringEncaseCRLFWithFirstIndex:bb}=ZC(),{isArray:i4}=Array,u6=["ansi","ansi","ansi256","ansi16m"],nm=Object.create(null),Bb=(o,l={})=>{if(l.level&&!(Number.isInteger(l.level)&&l.level>=0&&l.level<=3))throw new Error("The `level` option should be an integer from 0 to 3");let f=v3?v3.level:0;o.level=l.level===void 0?f:l.level},y3=class{constructor(l){return o6(l)}},o6=o=>{let l={};return Bb(l,o),l.template=(...f)=>s6(l.template,...f),Object.setPrototypeOf(l,u4.prototype),Object.setPrototypeOf(l.template,l),l.template.constructor=()=>{throw new Error("`chalk.constructor()` is deprecated. Use `new chalk.Instance()` instead.")},l.template.Instance=y3,l.template};function u4(o){return o6(o)}for(let[o,l]of Object.entries(fg))nm[o]={get(){let f=o4(this,g3(l.open,l.close,this._styler),this._isEmpty);return Object.defineProperty(this,o,{value:f}),f}};nm.visible={get(){let o=o4(this,this._styler,!0);return Object.defineProperty(this,"visible",{value:o}),o}};var l6=["rgb","hex","keyword","hsl","hsv","hwb","ansi","ansi256"];for(let o of l6)nm[o]={get(){let{level:l}=this;return function(...f){let h=g3(fg.color[u6[l]][o](...f),fg.color.close,this._styler);return o4(this,h,this._isEmpty)}}};for(let o of l6){let l="bg"+o[0].toUpperCase()+o.slice(1);nm[l]={get(){let{level:f}=this;return function(...h){let E=g3(fg.bgColor[u6[f]][o](...h),fg.bgColor.close,this._styler);return o4(this,E,this._isEmpty)}}}}var Ub=Object.defineProperties(()=>{},{...nm,level:{enumerable:!0,get(){return this._generator.level},set(o){this._generator.level=o}}}),g3=(o,l,f)=>{let h,E;return f===void 0?(h=o,E=l):(h=f.openAll+o,E=l+f.closeAll),{open:o,close:l,openAll:h,closeAll:E,parent:f}},o4=(o,l,f)=>{let h=(...E)=>i4(E[0])&&i4(E[0].raw)?i6(h,s6(h,...E)):i6(h,E.length===1?""+E[0]:E.join(" "));return Object.setPrototypeOf(h,Ub),h._generator=o,h._styler=l,h._isEmpty=f,h},i6=(o,l)=>{if(o.level<=0||!l)return o._isEmpty?"":l;let f=o._styler;if(f===void 0)return l;let{openAll:h,closeAll:E}=f;if(l.indexOf("\x1B")!==-1)for(;f!==void 0;)l=Ib(l,f.close,f.open),f=f.parent;let t=l.indexOf(` +`);return t!==-1&&(l=bb(l,E,h,t)),h+l+E},h3,s6=(o,...l)=>{let[f]=l;if(!i4(f)||!i4(f.raw))return l.join(" ");let h=l.slice(1),E=[f.raw[0]];for(let t=1;t{"use strict";var jb=dg&&dg.__importDefault||function(o){return o&&o.__esModule?o:{default:o}};Object.defineProperty(dg,"__esModule",{value:!0});var cg=jb(s4()),zb=/^(rgb|hsl|hsv|hwb)\(\s?(\d+),\s?(\d+),\s?(\d+)\s?\)$/,Hb=/^(ansi|ansi256)\(\s?(\d+)\s?\)$/,a4=(o,l)=>l==="foreground"?o:"bg"+o[0].toUpperCase()+o.slice(1);dg.default=(o,l,f)=>{if(!l)return o;if(l in cg.default){let E=a4(l,f);return cg.default[E](o)}if(l.startsWith("#")){let E=a4("hex",f);return cg.default[E](l)(o)}if(l.startsWith("ansi")){let E=Hb.exec(l);if(!E)return o;let t=a4(E[1],f),N=Number(E[2]);return cg.default[t](N)(o)}if(l.startsWith("rgb")||l.startsWith("hsl")||l.startsWith("hsv")||l.startsWith("hwb")){let E=zb.exec(l);if(!E)return o;let t=a4(E[1],f),N=Number(E[2]),F=Number(E[3]),k=Number(E[4]);return cg.default[t](N,F,k)(o)}return o}});var c6=nt(pg=>{"use strict";var f6=pg&&pg.__importDefault||function(o){return o&&o.__esModule?o:{default:o}};Object.defineProperty(pg,"__esModule",{value:!0});var qb=f6(VC()),E3=f6(_3());pg.default=(o,l,f,h)=>{if(typeof f.style.borderStyle=="string"){let E=f.yogaNode.getComputedWidth(),t=f.yogaNode.getComputedHeight(),N=f.style.borderColor,F=qb.default[f.style.borderStyle],k=E3.default(F.topLeft+F.horizontal.repeat(E-2)+F.topRight,N,"foreground"),x=(E3.default(F.vertical,N,"foreground")+` +`).repeat(t-2),j=E3.default(F.bottomLeft+F.horizontal.repeat(E-2)+F.bottomRight,N,"foreground");h.write(o,l,k,{transformers:[]}),h.write(o,l+1,x,{transformers:[]}),h.write(o+E-1,l+1,x,{transformers:[]}),h.write(o,l+t-1,j,{transformers:[]})}}});var p6=nt(hg=>{"use strict";var ih=hg&&hg.__importDefault||function(o){return o&&o.__esModule?o:{default:o}};Object.defineProperty(hg,"__esModule",{value:!0});var Wb=ih(eh()),Vb=ih(xD()),Gb=ih(zC()),Yb=ih(PD()),Kb=ih(HC()),Xb=ih(bD()),Qb=ih(c6()),Jb=(o,l)=>{var f;let h=(f=o.childNodes[0])===null||f===void 0?void 0:f.yogaNode;if(h){let E=h.getComputedLeft(),t=h.getComputedTop();l=` +`.repeat(t)+Gb.default(l,E)}return l},d6=(o,l,f)=>{var h;let{offsetX:E=0,offsetY:t=0,transformers:N=[],skipStaticElements:F}=f;if(F&&o.internal_static)return;let{yogaNode:k}=o;if(k){if(k.getDisplay()===Wb.default.DISPLAY_NONE)return;let x=E+k.getComputedLeft(),j=t+k.getComputedTop(),q=N;if(typeof o.internal_transform=="function"&&(q=[o.internal_transform,...N]),o.nodeName==="ink-text"){let V=Xb.default(o);if(V.length>0){let re=Vb.default(V),y=Kb.default(k);if(re>y){let me=(h=o.style.textWrap)!==null&&h!==void 0?h:"wrap";V=Yb.default(V,y,me)}V=Jb(o,V),l.write(x,j,V,{transformers:q})}return}if(o.nodeName==="ink-box"&&Qb.default(x,j,o,l),o.nodeName==="ink-root"||o.nodeName==="ink-box")for(let V of o.childNodes)d6(V,l,{offsetX:x,offsetY:j,transformers:q,skipStaticElements:F})}};hg.default=d6});var v6=nt((Eq,h6)=>{"use strict";h6.exports=o=>{o=Object.assign({onlyFirst:!1},o);let l=["[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)","(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))"].join("|");return new RegExp(l,o.onlyFirst?void 0:"g")}});var y6=nt((Dq,D3)=>{"use strict";var Zb=v6(),m6=o=>typeof o=="string"?o.replace(Zb(),""):o;D3.exports=m6;D3.exports.default=m6});var E6=nt((wq,_6)=>{"use strict";var g6="[\uD800-\uDBFF][\uDC00-\uDFFF]";_6.exports=o=>o&&o.exact?new RegExp(`^${g6}$`):new RegExp(g6,"g")});var w6=nt((Sq,w3)=>{"use strict";var $b=y6(),eB=E6(),D6=o=>$b(o).replace(eB()," ").length;w3.exports=D6;w3.exports.default=D6});var C6=nt(vg=>{"use strict";var T6=vg&&vg.__importDefault||function(o){return o&&o.__esModule?o:{default:o}};Object.defineProperty(vg,"__esModule",{value:!0});var S6=T6(LD()),tB=T6(w6()),S3=class{constructor(l){this.writes=[];let{width:f,height:h}=l;this.width=f,this.height=h}write(l,f,h,E){let{transformers:t}=E;!h||this.writes.push({x:l,y:f,text:h,transformers:t})}get(){let l=[];for(let h=0;hh.trimRight()).join(` +`),height:l.length}}};vg.default=S3});var A6=nt(mg=>{"use strict";var T3=mg&&mg.__importDefault||function(o){return o&&o.__esModule?o:{default:o}};Object.defineProperty(mg,"__esModule",{value:!0});var nB=T3(eh()),x6=T3(p6()),R6=T3(C6());mg.default=(o,l)=>{var f;if(o.yogaNode.setWidth(l),o.yogaNode){o.yogaNode.calculateLayout(void 0,void 0,nB.default.DIRECTION_LTR);let h=new R6.default({width:o.yogaNode.getComputedWidth(),height:o.yogaNode.getComputedHeight()});x6.default(o,h,{skipStaticElements:!0});let E;!((f=o.staticNode)===null||f===void 0)&&f.yogaNode&&(E=new R6.default({width:o.staticNode.yogaNode.getComputedWidth(),height:o.staticNode.yogaNode.getComputedHeight()}),x6.default(o.staticNode,E,{skipStaticElements:!1}));let{output:t,height:N}=h.get();return{output:t,outputHeight:N,staticOutput:E?`${E.get().output} +`:""}}return{output:"",outputHeight:0,staticOutput:""}}});var N6=nt((xq,k6)=>{"use strict";var O6=hi("stream"),M6=["assert","count","countReset","debug","dir","dirxml","error","group","groupCollapsed","groupEnd","info","log","table","time","timeEnd","timeLog","trace","warn"],C3={},rB=o=>{let l=new O6.PassThrough,f=new O6.PassThrough;l.write=E=>o("stdout",E),f.write=E=>o("stderr",E);let h=new console.Console(l,f);for(let E of M6)C3[E]=console[E],console[E]=h[E];return()=>{for(let E of M6)console[E]=C3[E];C3={}}};k6.exports=rB});var R3=nt(x3=>{"use strict";Object.defineProperty(x3,"__esModule",{value:!0});x3.default=new WeakMap});var O3=nt(A3=>{"use strict";Object.defineProperty(A3,"__esModule",{value:!0});var iB=Mi(),L6=iB.createContext({exit:()=>{}});L6.displayName="InternalAppContext";A3.default=L6});var k3=nt(M3=>{"use strict";Object.defineProperty(M3,"__esModule",{value:!0});var uB=Mi(),F6=uB.createContext({stdin:void 0,setRawMode:()=>{},isRawModeSupported:!1,internal_exitOnCtrlC:!0});F6.displayName="InternalStdinContext";M3.default=F6});var L3=nt(N3=>{"use strict";Object.defineProperty(N3,"__esModule",{value:!0});var oB=Mi(),P6=oB.createContext({stdout:void 0,write:()=>{}});P6.displayName="InternalStdoutContext";N3.default=P6});var P3=nt(F3=>{"use strict";Object.defineProperty(F3,"__esModule",{value:!0});var lB=Mi(),I6=lB.createContext({stderr:void 0,write:()=>{}});I6.displayName="InternalStderrContext";F3.default=I6});var f4=nt(I3=>{"use strict";Object.defineProperty(I3,"__esModule",{value:!0});var sB=Mi(),b6=sB.createContext({activeId:void 0,add:()=>{},remove:()=>{},activate:()=>{},deactivate:()=>{},enableFocus:()=>{},disableFocus:()=>{},focusNext:()=>{},focusPrevious:()=>{}});b6.displayName="InternalFocusContext";I3.default=b6});var U6=nt((Lq,B6)=>{"use strict";var aB=/[|\\{}()[\]^$+*?.-]/g;B6.exports=o=>{if(typeof o!="string")throw new TypeError("Expected a string");return o.replace(aB,"\\$&")}});var q6=nt((Fq,H6)=>{"use strict";var fB=U6(),z6=[].concat(hi("module").builtinModules,"bootstrap_node","node").map(o=>new RegExp(`(?:\\(${o}\\.js:\\d+:\\d+\\)$|^\\s*at ${o}\\.js:\\d+:\\d+$)`));z6.push(/\(internal\/[^:]+:\d+:\d+\)$/,/\s*at internal\/[^:]+:\d+:\d+$/,/\/\.node-spawn-wrap-\w+-\w+\/node:\d+:\d+\)?$/);var yg=class{constructor(l){l={ignoredPackages:[],...l},"internals"in l||(l.internals=yg.nodeInternals()),"cwd"in l||(l.cwd=process.cwd()),this._cwd=l.cwd.replace(/\\/g,"/"),this._internals=[].concat(l.internals,cB(l.ignoredPackages)),this._wrapCallSite=l.wrapCallSite||!1}static nodeInternals(){return[...z6]}clean(l,f=0){f=" ".repeat(f),Array.isArray(l)||(l=l.split(` +`)),!/^\s*at /.test(l[0])&&/^\s*at /.test(l[1])&&(l=l.slice(1));let h=!1,E=null,t=[];return l.forEach(N=>{if(N=N.replace(/\\/g,"/"),this._internals.some(k=>k.test(N)))return;let F=/^\s*at /.test(N);h?N=N.trimEnd().replace(/^(\s+)at /,"$1"):(N=N.trim(),F&&(N=N.slice(3))),N=N.replace(`${this._cwd}/`,""),N&&(F?(E&&(t.push(E),E=null),t.push(N)):(h=!0,E=N))}),t.map(N=>`${f}${N} +`).join("")}captureString(l,f=this.captureString){typeof l=="function"&&(f=l,l=1/0);let{stackTraceLimit:h}=Error;l&&(Error.stackTraceLimit=l);let E={};Error.captureStackTrace(E,f);let{stack:t}=E;return Error.stackTraceLimit=h,this.clean(t)}capture(l,f=this.capture){typeof l=="function"&&(f=l,l=1/0);let{prepareStackTrace:h,stackTraceLimit:E}=Error;Error.prepareStackTrace=(F,k)=>this._wrapCallSite?k.map(this._wrapCallSite):k,l&&(Error.stackTraceLimit=l);let t={};Error.captureStackTrace(t,f);let{stack:N}=t;return Object.assign(Error,{prepareStackTrace:h,stackTraceLimit:E}),N}at(l=this.at){let[f]=this.capture(1,l);if(!f)return{};let h={line:f.getLineNumber(),column:f.getColumnNumber()};j6(h,f.getFileName(),this._cwd),f.isConstructor()&&(h.constructor=!0),f.isEval()&&(h.evalOrigin=f.getEvalOrigin()),f.isNative()&&(h.native=!0);let E;try{E=f.getTypeName()}catch{}E&&E!=="Object"&&E!=="[object Object]"&&(h.type=E);let t=f.getFunctionName();t&&(h.function=t);let N=f.getMethodName();return N&&t!==N&&(h.method=N),h}parseLine(l){let f=l&&l.match(dB);if(!f)return null;let h=f[1]==="new",E=f[2],t=f[3],N=f[4],F=Number(f[5]),k=Number(f[6]),x=f[7],j=f[8],q=f[9],V=f[10]==="native",re=f[11]===")",y,me={};if(j&&(me.line=Number(j)),q&&(me.column=Number(q)),re&&x){let De=0;for(let ge=x.length-1;ge>0;ge--)if(x.charAt(ge)===")")De++;else if(x.charAt(ge)==="("&&x.charAt(ge-1)===" "&&(De--,De===-1&&x.charAt(ge-1)===" ")){let ae=x.slice(0,ge-1);x=x.slice(ge+1),E+=` (${ae}`;break}}if(E){let De=E.match(pB);De&&(E=De[1],y=De[2])}return j6(me,x,this._cwd),h&&(me.constructor=!0),t&&(me.evalOrigin=t,me.evalLine=F,me.evalColumn=k,me.evalFile=N&&N.replace(/\\/g,"/")),V&&(me.native=!0),E&&(me.function=E),y&&E!==y&&(me.method=y),me}};function j6(o,l,f){l&&(l=l.replace(/\\/g,"/"),l.startsWith(`${f}/`)&&(l=l.slice(f.length+1)),o.file=l)}function cB(o){if(o.length===0)return[];let l=o.map(f=>fB(f));return new RegExp(`[/\\\\]node_modules[/\\\\](?:${l.join("|")})[/\\\\][^:]+:\\d+:\\d+`)}var dB=new RegExp("^(?:\\s*at )?(?:(new) )?(?:(.*?) \\()?(?:eval at ([^ ]+) \\((.+?):(\\d+):(\\d+)\\), )?(?:(.+?):(\\d+):(\\d+)|(native))(\\)?)$"),pB=/^(.*?) \[as (.*?)\]$/;H6.exports=yg});var V6=nt((Pq,W6)=>{"use strict";W6.exports=(o,l)=>o.replace(/^\t+/gm,f=>" ".repeat(f.length*(l||2)))});var Y6=nt((Iq,G6)=>{"use strict";var hB=V6(),vB=(o,l)=>{let f=[],h=o-l,E=o+l;for(let t=h;t<=E;t++)f.push(t);return f};G6.exports=(o,l,f)=>{if(typeof o!="string")throw new TypeError("Source code is missing.");if(!l||l<1)throw new TypeError("Line number must start from `1`.");if(o=hB(o).split(/\r?\n/),!(l>o.length))return f={around:3,...f},vB(l,f.around).filter(h=>o[h-1]!==void 0).map(h=>({line:h,value:o[h-1]}))}});var c4=nt(nc=>{"use strict";var mB=nc&&nc.__createBinding||(Object.create?function(o,l,f,h){h===void 0&&(h=f),Object.defineProperty(o,h,{enumerable:!0,get:function(){return l[f]}})}:function(o,l,f,h){h===void 0&&(h=f),o[h]=l[f]}),yB=nc&&nc.__setModuleDefault||(Object.create?function(o,l){Object.defineProperty(o,"default",{enumerable:!0,value:l})}:function(o,l){o.default=l}),gB=nc&&nc.__importStar||function(o){if(o&&o.__esModule)return o;var l={};if(o!=null)for(var f in o)f!=="default"&&Object.hasOwnProperty.call(o,f)&&mB(l,o,f);return yB(l,o),l},_B=nc&&nc.__rest||function(o,l){var f={};for(var h in o)Object.prototype.hasOwnProperty.call(o,h)&&l.indexOf(h)<0&&(f[h]=o[h]);if(o!=null&&typeof Object.getOwnPropertySymbols=="function")for(var E=0,h=Object.getOwnPropertySymbols(o);E{var{children:f}=o,h=_B(o,["children"]);let E=Object.assign(Object.assign({},h),{marginLeft:h.marginLeft||h.marginX||h.margin||0,marginRight:h.marginRight||h.marginX||h.margin||0,marginTop:h.marginTop||h.marginY||h.margin||0,marginBottom:h.marginBottom||h.marginY||h.margin||0,paddingLeft:h.paddingLeft||h.paddingX||h.padding||0,paddingRight:h.paddingRight||h.paddingX||h.padding||0,paddingTop:h.paddingTop||h.paddingY||h.padding||0,paddingBottom:h.paddingBottom||h.paddingY||h.padding||0});return K6.default.createElement("ink-box",{ref:l,style:E},f)});b3.displayName="Box";b3.defaultProps={flexDirection:"row",flexGrow:0,flexShrink:1};nc.default=b3});var j3=nt(gg=>{"use strict";var B3=gg&&gg.__importDefault||function(o){return o&&o.__esModule?o:{default:o}};Object.defineProperty(gg,"__esModule",{value:!0});var EB=B3(Mi()),rm=B3(s4()),X6=B3(_3()),U3=({color:o,backgroundColor:l,dimColor:f,bold:h,italic:E,underline:t,strikethrough:N,inverse:F,wrap:k,children:x})=>{if(x==null)return null;let j=q=>(f&&(q=rm.default.dim(q)),o&&(q=X6.default(q,o,"foreground")),l&&(q=X6.default(q,l,"background")),h&&(q=rm.default.bold(q)),E&&(q=rm.default.italic(q)),t&&(q=rm.default.underline(q)),N&&(q=rm.default.strikethrough(q)),F&&(q=rm.default.inverse(q)),q);return EB.default.createElement("ink-text",{style:{flexGrow:0,flexShrink:1,flexDirection:"row",textWrap:k},internal_transform:j},x)};U3.displayName="Text";U3.defaultProps={dimColor:!1,bold:!1,italic:!1,underline:!1,strikethrough:!1,wrap:"wrap"};gg.default=U3});var $6=nt(rc=>{"use strict";var DB=rc&&rc.__createBinding||(Object.create?function(o,l,f,h){h===void 0&&(h=f),Object.defineProperty(o,h,{enumerable:!0,get:function(){return l[f]}})}:function(o,l,f,h){h===void 0&&(h=f),o[h]=l[f]}),wB=rc&&rc.__setModuleDefault||(Object.create?function(o,l){Object.defineProperty(o,"default",{enumerable:!0,value:l})}:function(o,l){o.default=l}),SB=rc&&rc.__importStar||function(o){if(o&&o.__esModule)return o;var l={};if(o!=null)for(var f in o)f!=="default"&&Object.hasOwnProperty.call(o,f)&&DB(l,o,f);return wB(l,o),l},_g=rc&&rc.__importDefault||function(o){return o&&o.__esModule?o:{default:o}};Object.defineProperty(rc,"__esModule",{value:!0});var Q6=SB(hi("fs")),Qo=_g(Mi()),J6=_g(q6()),TB=_g(Y6()),Z1=_g(c4()),Hc=_g(j3()),Z6=new J6.default({cwd:process.cwd(),internals:J6.default.nodeInternals()}),CB=({error:o})=>{let l=o.stack?o.stack.split(` +`).slice(1):void 0,f=l?Z6.parseLine(l[0]):void 0,h,E=0;if((f==null?void 0:f.file)&&(f==null?void 0:f.line)&&Q6.existsSync(f.file)){let t=Q6.readFileSync(f.file,"utf8");if(h=TB.default(t,f.line),h)for(let{line:N}of h)E=Math.max(E,String(N).length)}return Qo.default.createElement(Z1.default,{flexDirection:"column",padding:1},Qo.default.createElement(Z1.default,null,Qo.default.createElement(Hc.default,{backgroundColor:"red",color:"white"}," ","ERROR"," "),Qo.default.createElement(Hc.default,null," ",o.message)),f&&Qo.default.createElement(Z1.default,{marginTop:1},Qo.default.createElement(Hc.default,{dimColor:!0},f.file,":",f.line,":",f.column)),f&&h&&Qo.default.createElement(Z1.default,{marginTop:1,flexDirection:"column"},h.map(({line:t,value:N})=>Qo.default.createElement(Z1.default,{key:t},Qo.default.createElement(Z1.default,{width:E+1},Qo.default.createElement(Hc.default,{dimColor:t!==f.line,backgroundColor:t===f.line?"red":void 0,color:t===f.line?"white":void 0},String(t).padStart(E," "),":")),Qo.default.createElement(Hc.default,{key:t,backgroundColor:t===f.line?"red":void 0,color:t===f.line?"white":void 0}," "+N)))),o.stack&&Qo.default.createElement(Z1.default,{marginTop:1,flexDirection:"column"},o.stack.split(` +`).slice(1).map(t=>{let N=Z6.parseLine(t);return N?Qo.default.createElement(Z1.default,{key:t},Qo.default.createElement(Hc.default,{dimColor:!0},"- "),Qo.default.createElement(Hc.default,{dimColor:!0,bold:!0},N.function),Qo.default.createElement(Hc.default,{dimColor:!0,color:"gray"}," ","(",N.file,":",N.line,":",N.column,")")):Qo.default.createElement(Z1.default,{key:t},Qo.default.createElement(Hc.default,{dimColor:!0},"- "),Qo.default.createElement(Hc.default,{dimColor:!0,bold:!0},t))})))};rc.default=CB});var tx=nt(ic=>{"use strict";var xB=ic&&ic.__createBinding||(Object.create?function(o,l,f,h){h===void 0&&(h=f),Object.defineProperty(o,h,{enumerable:!0,get:function(){return l[f]}})}:function(o,l,f,h){h===void 0&&(h=f),o[h]=l[f]}),RB=ic&&ic.__setModuleDefault||(Object.create?function(o,l){Object.defineProperty(o,"default",{enumerable:!0,value:l})}:function(o,l){o.default=l}),AB=ic&&ic.__importStar||function(o){if(o&&o.__esModule)return o;var l={};if(o!=null)for(var f in o)f!=="default"&&Object.hasOwnProperty.call(o,f)&&xB(l,o,f);return RB(l,o),l},oh=ic&&ic.__importDefault||function(o){return o&&o.__esModule?o:{default:o}};Object.defineProperty(ic,"__esModule",{value:!0});var uh=AB(Mi()),ex=oh(rD()),OB=oh(O3()),MB=oh(k3()),kB=oh(L3()),NB=oh(P3()),LB=oh(f4()),FB=oh($6()),PB=" ",IB="\x1B[Z",bB="\x1B",d4=class extends uh.PureComponent{constructor(){super(...arguments),this.state={isFocusEnabled:!0,activeFocusId:void 0,focusables:[],error:void 0},this.rawModeEnabledCount=0,this.handleSetRawMode=l=>{let{stdin:f}=this.props;if(!this.isRawModeSupported())throw f===process.stdin?new Error(`Raw mode is not supported on the current process.stdin, which Ink uses as input stream by default. +Read about how to prevent this error on https://github.com/vadimdemedes/ink/#israwmodesupported`):new Error(`Raw mode is not supported on the stdin provided to Ink. +Read about how to prevent this error on https://github.com/vadimdemedes/ink/#israwmodesupported`);if(f.setEncoding("utf8"),l){this.rawModeEnabledCount===0&&(f.addListener("data",this.handleInput),f.resume(),f.setRawMode(!0)),this.rawModeEnabledCount++;return}--this.rawModeEnabledCount===0&&(f.setRawMode(!1),f.removeListener("data",this.handleInput),f.pause())},this.handleInput=l=>{l===""&&this.props.exitOnCtrlC&&this.handleExit(),l===bB&&this.state.activeFocusId&&this.setState({activeFocusId:void 0}),this.state.isFocusEnabled&&this.state.focusables.length>0&&(l===PB&&this.focusNext(),l===IB&&this.focusPrevious())},this.handleExit=l=>{this.isRawModeSupported()&&this.handleSetRawMode(!1),this.props.onExit(l)},this.enableFocus=()=>{this.setState({isFocusEnabled:!0})},this.disableFocus=()=>{this.setState({isFocusEnabled:!1})},this.focusNext=()=>{this.setState(l=>{let f=l.focusables[0].id;return{activeFocusId:this.findNextFocusable(l)||f}})},this.focusPrevious=()=>{this.setState(l=>{let f=l.focusables[l.focusables.length-1].id;return{activeFocusId:this.findPreviousFocusable(l)||f}})},this.addFocusable=(l,{autoFocus:f})=>{this.setState(h=>{let E=h.activeFocusId;return!E&&f&&(E=l),{activeFocusId:E,focusables:[...h.focusables,{id:l,isActive:!0}]}})},this.removeFocusable=l=>{this.setState(f=>({activeFocusId:f.activeFocusId===l?void 0:f.activeFocusId,focusables:f.focusables.filter(h=>h.id!==l)}))},this.activateFocusable=l=>{this.setState(f=>({focusables:f.focusables.map(h=>h.id!==l?h:{id:l,isActive:!0})}))},this.deactivateFocusable=l=>{this.setState(f=>({activeFocusId:f.activeFocusId===l?void 0:f.activeFocusId,focusables:f.focusables.map(h=>h.id!==l?h:{id:l,isActive:!1})}))},this.findNextFocusable=l=>{let f=l.focusables.findIndex(h=>h.id===l.activeFocusId);for(let h=f+1;h{let f=l.focusables.findIndex(h=>h.id===l.activeFocusId);for(let h=f-1;h>=0;h--)if(l.focusables[h].isActive)return l.focusables[h].id}}static getDerivedStateFromError(l){return{error:l}}isRawModeSupported(){return this.props.stdin.isTTY}render(){return uh.default.createElement(OB.default.Provider,{value:{exit:this.handleExit}},uh.default.createElement(MB.default.Provider,{value:{stdin:this.props.stdin,setRawMode:this.handleSetRawMode,isRawModeSupported:this.isRawModeSupported(),internal_exitOnCtrlC:this.props.exitOnCtrlC}},uh.default.createElement(kB.default.Provider,{value:{stdout:this.props.stdout,write:this.props.writeToStdout}},uh.default.createElement(NB.default.Provider,{value:{stderr:this.props.stderr,write:this.props.writeToStderr}},uh.default.createElement(LB.default.Provider,{value:{activeId:this.state.activeFocusId,add:this.addFocusable,remove:this.removeFocusable,activate:this.activateFocusable,deactivate:this.deactivateFocusable,enableFocus:this.enableFocus,disableFocus:this.disableFocus,focusNext:this.focusNext,focusPrevious:this.focusPrevious}},this.state.error?uh.default.createElement(FB.default,{error:this.state.error}):this.props.children)))))}componentDidMount(){ex.default.hide(this.props.stdout)}componentWillUnmount(){ex.default.show(this.props.stdout),this.isRawModeSupported()&&this.handleSetRawMode(!1)}componentDidCatch(l){this.handleExit(l)}};ic.default=d4;d4.displayName="InternalApp"});var ix=nt(uc=>{"use strict";var BB=uc&&uc.__createBinding||(Object.create?function(o,l,f,h){h===void 0&&(h=f),Object.defineProperty(o,h,{enumerable:!0,get:function(){return l[f]}})}:function(o,l,f,h){h===void 0&&(h=f),o[h]=l[f]}),UB=uc&&uc.__setModuleDefault||(Object.create?function(o,l){Object.defineProperty(o,"default",{enumerable:!0,value:l})}:function(o,l){o.default=l}),jB=uc&&uc.__importStar||function(o){if(o&&o.__esModule)return o;var l={};if(o!=null)for(var f in o)f!=="default"&&Object.hasOwnProperty.call(o,f)&&BB(l,o,f);return UB(l,o),l},oc=uc&&uc.__importDefault||function(o){return o&&o.__esModule?o:{default:o}};Object.defineProperty(uc,"__esModule",{value:!0});var zB=oc(Mi()),nx=sS(),HB=oc(TS()),qB=oc(ZE()),WB=oc(MS()),VB=oc(NS()),p4=oc(UC()),GB=oc(A6()),YB=oc(nD()),KB=oc(N6()),XB=jB(BD()),QB=oc(R3()),JB=oc(tx()),im=process.env.CI==="false"?!1:WB.default,rx=()=>{},z3=class{constructor(l){this.resolveExitPromise=()=>{},this.rejectExitPromise=()=>{},this.unsubscribeExit=()=>{},this.onRender=()=>{if(this.isUnmounted)return;let{output:f,outputHeight:h,staticOutput:E}=GB.default(this.rootNode,this.options.stdout.columns||80),t=E&&E!==` +`;if(this.options.debug){t&&(this.fullStaticOutput+=E),this.options.stdout.write(this.fullStaticOutput+f);return}if(im){t&&this.options.stdout.write(E),this.lastOutput=f;return}if(t&&(this.fullStaticOutput+=E),h>=this.options.stdout.rows){this.options.stdout.write(qB.default.clearTerminal+this.fullStaticOutput+f),this.lastOutput=f;return}t&&(this.log.clear(),this.options.stdout.write(E),this.log(f)),!t&&f!==this.lastOutput&&this.throttledLog(f),this.lastOutput=f},VB.default(this),this.options=l,this.rootNode=XB.createNode("ink-root"),this.rootNode.onRender=l.debug?this.onRender:nx.throttle(this.onRender,32,{leading:!0,trailing:!0}),this.rootNode.onImmediateRender=this.onRender,this.log=HB.default.create(l.stdout),this.throttledLog=l.debug?this.log:nx.throttle(this.log,void 0,{leading:!0,trailing:!0}),this.isUnmounted=!1,this.lastOutput="",this.fullStaticOutput="",this.container=p4.default.createContainer(this.rootNode,!1,!1),this.unsubscribeExit=YB.default(this.unmount,{alwaysLast:!1}),process.env.DEV==="true"&&p4.default.injectIntoDevTools({bundleType:0,version:"16.13.1",rendererPackageName:"ink"}),l.patchConsole&&this.patchConsole(),im||(l.stdout.on("resize",this.onRender),this.unsubscribeResize=()=>{l.stdout.off("resize",this.onRender)})}render(l){let f=zB.default.createElement(JB.default,{stdin:this.options.stdin,stdout:this.options.stdout,stderr:this.options.stderr,writeToStdout:this.writeToStdout,writeToStderr:this.writeToStderr,exitOnCtrlC:this.options.exitOnCtrlC,onExit:this.unmount},l);p4.default.updateContainer(f,this.container,null,rx)}writeToStdout(l){if(!this.isUnmounted){if(this.options.debug){this.options.stdout.write(l+this.fullStaticOutput+this.lastOutput);return}if(im){this.options.stdout.write(l);return}this.log.clear(),this.options.stdout.write(l),this.log(this.lastOutput)}}writeToStderr(l){if(!this.isUnmounted){if(this.options.debug){this.options.stderr.write(l),this.options.stdout.write(this.fullStaticOutput+this.lastOutput);return}if(im){this.options.stderr.write(l);return}this.log.clear(),this.options.stderr.write(l),this.log(this.lastOutput)}}unmount(l){this.isUnmounted||(this.onRender(),this.unsubscribeExit(),typeof this.restoreConsole=="function"&&this.restoreConsole(),typeof this.unsubscribeResize=="function"&&this.unsubscribeResize(),im?this.options.stdout.write(this.lastOutput+` +`):this.options.debug||this.log.done(),this.isUnmounted=!0,p4.default.updateContainer(null,this.container,null,rx),QB.default.delete(this.options.stdout),l instanceof Error?this.rejectExitPromise(l):this.resolveExitPromise())}waitUntilExit(){return this.exitPromise||(this.exitPromise=new Promise((l,f)=>{this.resolveExitPromise=l,this.rejectExitPromise=f})),this.exitPromise}clear(){!im&&!this.options.debug&&this.log.clear()}patchConsole(){this.options.debug||(this.restoreConsole=KB.default((l,f)=>{l==="stdout"&&this.writeToStdout(f),l==="stderr"&&(f.startsWith("The above error occurred")||this.writeToStderr(f))}))}};uc.default=z3});var ox=nt(Eg=>{"use strict";var ux=Eg&&Eg.__importDefault||function(o){return o&&o.__esModule?o:{default:o}};Object.defineProperty(Eg,"__esModule",{value:!0});var ZB=ux(ix()),h4=ux(R3()),$B=hi("stream"),eU=(o,l)=>{let f=Object.assign({stdout:process.stdout,stdin:process.stdin,stderr:process.stderr,debug:!1,exitOnCtrlC:!0,patchConsole:!0},tU(l)),h=nU(f.stdout,()=>new ZB.default(f));return h.render(o),{rerender:h.render,unmount:()=>h.unmount(),waitUntilExit:h.waitUntilExit,cleanup:()=>h4.default.delete(f.stdout),clear:h.clear}};Eg.default=eU;var tU=(o={})=>o instanceof $B.Stream?{stdout:o,stdin:process.stdin}:o,nU=(o,l)=>{let f;return h4.default.has(o)?f=h4.default.get(o):(f=l(),h4.default.set(o,f)),f}});var sx=nt($1=>{"use strict";var rU=$1&&$1.__createBinding||(Object.create?function(o,l,f,h){h===void 0&&(h=f),Object.defineProperty(o,h,{enumerable:!0,get:function(){return l[f]}})}:function(o,l,f,h){h===void 0&&(h=f),o[h]=l[f]}),iU=$1&&$1.__setModuleDefault||(Object.create?function(o,l){Object.defineProperty(o,"default",{enumerable:!0,value:l})}:function(o,l){o.default=l}),uU=$1&&$1.__importStar||function(o){if(o&&o.__esModule)return o;var l={};if(o!=null)for(var f in o)f!=="default"&&Object.hasOwnProperty.call(o,f)&&rU(l,o,f);return iU(l,o),l};Object.defineProperty($1,"__esModule",{value:!0});var Dg=uU(Mi()),lx=o=>{let{items:l,children:f,style:h}=o,[E,t]=Dg.useState(0),N=Dg.useMemo(()=>l.slice(E),[l,E]);Dg.useLayoutEffect(()=>{t(l.length)},[l.length]);let F=N.map((x,j)=>f(x,E+j)),k=Dg.useMemo(()=>Object.assign({position:"absolute",flexDirection:"column"},h),[h]);return Dg.default.createElement("ink-box",{internal_static:!0,style:k},F)};lx.displayName="Static";$1.default=lx});var fx=nt(wg=>{"use strict";var oU=wg&&wg.__importDefault||function(o){return o&&o.__esModule?o:{default:o}};Object.defineProperty(wg,"__esModule",{value:!0});var lU=oU(Mi()),ax=({children:o,transform:l})=>o==null?null:lU.default.createElement("ink-text",{style:{flexGrow:0,flexShrink:1,flexDirection:"row"},internal_transform:l},o);ax.displayName="Transform";wg.default=ax});var dx=nt(Sg=>{"use strict";var sU=Sg&&Sg.__importDefault||function(o){return o&&o.__esModule?o:{default:o}};Object.defineProperty(Sg,"__esModule",{value:!0});var aU=sU(Mi()),cx=({count:o=1})=>aU.default.createElement("ink-text",null,` +`.repeat(o));cx.displayName="Newline";Sg.default=cx});var vx=nt(Tg=>{"use strict";var px=Tg&&Tg.__importDefault||function(o){return o&&o.__esModule?o:{default:o}};Object.defineProperty(Tg,"__esModule",{value:!0});var fU=px(Mi()),cU=px(c4()),hx=()=>fU.default.createElement(cU.default,{flexGrow:1});hx.displayName="Spacer";Tg.default=hx});var v4=nt(Cg=>{"use strict";var dU=Cg&&Cg.__importDefault||function(o){return o&&o.__esModule?o:{default:o}};Object.defineProperty(Cg,"__esModule",{value:!0});var pU=Mi(),hU=dU(k3()),vU=()=>pU.useContext(hU.default);Cg.default=vU});var yx=nt(xg=>{"use strict";var mU=xg&&xg.__importDefault||function(o){return o&&o.__esModule?o:{default:o}};Object.defineProperty(xg,"__esModule",{value:!0});var mx=Mi(),yU=mU(v4()),gU=(o,l={})=>{let{stdin:f,setRawMode:h,internal_exitOnCtrlC:E}=yU.default();mx.useEffect(()=>{if(l.isActive!==!1)return h(!0),()=>{h(!1)}},[l.isActive,h]),mx.useEffect(()=>{if(l.isActive===!1)return;let t=N=>{let F=String(N),k={upArrow:F==="\x1B[A",downArrow:F==="\x1B[B",leftArrow:F==="\x1B[D",rightArrow:F==="\x1B[C",pageDown:F==="\x1B[6~",pageUp:F==="\x1B[5~",return:F==="\r",escape:F==="\x1B",ctrl:!1,shift:!1,tab:F===" "||F==="\x1B[Z",backspace:F==="\b",delete:F==="\x7F"||F==="\x1B[3~",meta:!1};F<=""&&!k.return&&(F=String.fromCharCode(F.charCodeAt(0)+"a".charCodeAt(0)-1),k.ctrl=!0),F.startsWith("\x1B")&&(F=F.slice(1),k.meta=!0);let x=F>="A"&&F<="Z",j=F>="\u0410"&&F<="\u042F";F.length===1&&(x||j)&&(k.shift=!0),k.tab&&F==="[Z"&&(k.shift=!0),(k.tab||k.backspace||k.delete)&&(F=""),(!(F==="c"&&k.ctrl)||!E)&&o(F,k)};return f==null||f.on("data",t),()=>{f==null||f.off("data",t)}},[l.isActive,f,E,o])};xg.default=gU});var gx=nt(Rg=>{"use strict";var _U=Rg&&Rg.__importDefault||function(o){return o&&o.__esModule?o:{default:o}};Object.defineProperty(Rg,"__esModule",{value:!0});var EU=Mi(),DU=_U(O3()),wU=()=>EU.useContext(DU.default);Rg.default=wU});var _x=nt(Ag=>{"use strict";var SU=Ag&&Ag.__importDefault||function(o){return o&&o.__esModule?o:{default:o}};Object.defineProperty(Ag,"__esModule",{value:!0});var TU=Mi(),CU=SU(L3()),xU=()=>TU.useContext(CU.default);Ag.default=xU});var Ex=nt(Og=>{"use strict";var RU=Og&&Og.__importDefault||function(o){return o&&o.__esModule?o:{default:o}};Object.defineProperty(Og,"__esModule",{value:!0});var AU=Mi(),OU=RU(P3()),MU=()=>AU.useContext(OU.default);Og.default=MU});var wx=nt(kg=>{"use strict";var Dx=kg&&kg.__importDefault||function(o){return o&&o.__esModule?o:{default:o}};Object.defineProperty(kg,"__esModule",{value:!0});var Mg=Mi(),kU=Dx(f4()),NU=Dx(v4()),LU=({isActive:o=!0,autoFocus:l=!1}={})=>{let{isRawModeSupported:f,setRawMode:h}=NU.default(),{activeId:E,add:t,remove:N,activate:F,deactivate:k}=Mg.useContext(kU.default),x=Mg.useMemo(()=>Math.random().toString().slice(2,7),[]);return Mg.useEffect(()=>(t(x,{autoFocus:l}),()=>{N(x)}),[x,l]),Mg.useEffect(()=>{o?F(x):k(x)},[o,x]),Mg.useEffect(()=>{if(!(!f||!o))return h(!0),()=>{h(!1)}},[o]),{isFocused:Boolean(x)&&E===x}};kg.default=LU});var Sx=nt(Ng=>{"use strict";var FU=Ng&&Ng.__importDefault||function(o){return o&&o.__esModule?o:{default:o}};Object.defineProperty(Ng,"__esModule",{value:!0});var PU=Mi(),IU=FU(f4()),bU=()=>{let o=PU.useContext(IU.default);return{enableFocus:o.enableFocus,disableFocus:o.disableFocus,focusNext:o.focusNext,focusPrevious:o.focusPrevious}};Ng.default=bU});var Tx=nt(H3=>{"use strict";Object.defineProperty(H3,"__esModule",{value:!0});H3.default=o=>{var l,f,h,E;return{width:(f=(l=o.yogaNode)===null||l===void 0?void 0:l.getComputedWidth())!==null&&f!==void 0?f:0,height:(E=(h=o.yogaNode)===null||h===void 0?void 0:h.getComputedHeight())!==null&&E!==void 0?E:0}}});var lc=nt(Yl=>{"use strict";Object.defineProperty(Yl,"__esModule",{value:!0});var BU=ox();Object.defineProperty(Yl,"render",{enumerable:!0,get:function(){return BU.default}});var UU=c4();Object.defineProperty(Yl,"Box",{enumerable:!0,get:function(){return UU.default}});var jU=j3();Object.defineProperty(Yl,"Text",{enumerable:!0,get:function(){return jU.default}});var zU=sx();Object.defineProperty(Yl,"Static",{enumerable:!0,get:function(){return zU.default}});var HU=fx();Object.defineProperty(Yl,"Transform",{enumerable:!0,get:function(){return HU.default}});var qU=dx();Object.defineProperty(Yl,"Newline",{enumerable:!0,get:function(){return qU.default}});var WU=vx();Object.defineProperty(Yl,"Spacer",{enumerable:!0,get:function(){return WU.default}});var VU=yx();Object.defineProperty(Yl,"useInput",{enumerable:!0,get:function(){return VU.default}});var GU=gx();Object.defineProperty(Yl,"useApp",{enumerable:!0,get:function(){return GU.default}});var YU=v4();Object.defineProperty(Yl,"useStdin",{enumerable:!0,get:function(){return YU.default}});var KU=_x();Object.defineProperty(Yl,"useStdout",{enumerable:!0,get:function(){return KU.default}});var XU=Ex();Object.defineProperty(Yl,"useStderr",{enumerable:!0,get:function(){return XU.default}});var QU=wx();Object.defineProperty(Yl,"useFocus",{enumerable:!0,get:function(){return QU.default}});var JU=Sx();Object.defineProperty(Yl,"useFocusManager",{enumerable:!0,get:function(){return JU.default}});var ZU=Tx();Object.defineProperty(Yl,"measureElement",{enumerable:!0,get:function(){return ZU.default}})});var Fx=nt(Lg=>{"use strict";Object.defineProperty(Lg,"__esModule",{value:!0});Lg.UncontrolledTextInput=void 0;var Nx=Mi(),V3=Mi(),kx=lc(),ah=s4(),Lx=({value:o,placeholder:l="",focus:f=!0,mask:h,highlightPastedText:E=!1,showCursor:t=!0,onChange:N,onSubmit:F})=>{let[{cursorOffset:k,cursorWidth:x},j]=V3.useState({cursorOffset:(o||"").length,cursorWidth:0});V3.useEffect(()=>{j(me=>{if(!f||!t)return me;let De=o||"";return me.cursorOffset>De.length-1?{cursorOffset:De.length,cursorWidth:0}:me})},[o,f,t]);let q=E?x:0,V=h?h.repeat(o.length):o,re=V,y=l?ah.grey(l):void 0;if(t&&f){y=l.length>0?ah.inverse(l[0])+ah.grey(l.slice(1)):ah.inverse(" "),re=V.length>0?"":ah.inverse(" ");let me=0;for(let De of V)me>=k-q&&me<=k?re+=ah.inverse(De):re+=De,me++;V.length>0&&k===V.length&&(re+=ah.inverse(" "))}return kx.useInput((me,De)=>{if(De.upArrow||De.downArrow||De.ctrl&&me==="c"||De.tab||De.shift&&De.tab)return;if(De.return){F&&F(o);return}let ge=k,ae=o,we=0;De.leftArrow?t&&ge--:De.rightArrow?t&&ge++:De.backspace||De.delete?k>0&&(ae=o.slice(0,k-1)+o.slice(k,o.length),ge--):(ae=o.slice(0,k)+me+o.slice(k,o.length),ge+=me.length,me.length>1&&(we=me.length)),k<0&&(ge=0),k>o.length&&(ge=o.length),j({cursorOffset:ge,cursorWidth:we}),ae!==o&&N(ae)},{isActive:f}),Nx.createElement(kx.Text,null,l?V.length>0?re:y:re)};Lg.default=Lx;Lg.UncontrolledTextInput=o=>{let[l,f]=V3.useState("");return Nx.createElement(Lx,Object.assign({},o,{value:l,onChange:f}))}});var Ix=nt(S4=>{"use strict";Object.defineProperty(S4,"__esModule",{value:!0});function Fg(o){let l=[...o.caches],f=l.shift();return f===void 0?Px():{get(h,E,t={miss:()=>Promise.resolve()}){return f.get(h,E,t).catch(()=>Fg({caches:l}).get(h,E,t))},set(h,E){return f.set(h,E).catch(()=>Fg({caches:l}).set(h,E))},delete(h){return f.delete(h).catch(()=>Fg({caches:l}).delete(h))},clear(){return f.clear().catch(()=>Fg({caches:l}).clear())}}}function Px(){return{get(o,l,f={miss:()=>Promise.resolve()}){return l().then(E=>Promise.all([E,f.miss(E)])).then(([E])=>E)},set(o,l){return Promise.resolve(l)},delete(o){return Promise.resolve()},clear(){return Promise.resolve()}}}S4.createFallbackableCache=Fg;S4.createNullCache=Px});var Bx=nt((EW,bx)=>{bx.exports=Ix()});var Ux=nt(G3=>{"use strict";Object.defineProperty(G3,"__esModule",{value:!0});function $U(o={serializable:!0}){let l={};return{get(f,h,E={miss:()=>Promise.resolve()}){let t=JSON.stringify(f);if(t in l)return Promise.resolve(o.serializable?JSON.parse(l[t]):l[t]);let N=h(),F=E&&E.miss||(()=>Promise.resolve());return N.then(k=>F(k)).then(()=>N)},set(f,h){return l[JSON.stringify(f)]=o.serializable?JSON.stringify(h):h,Promise.resolve(h)},delete(f){return delete l[JSON.stringify(f)],Promise.resolve()},clear(){return l={},Promise.resolve()}}}G3.createInMemoryCache=$U});var zx=nt((wW,jx)=>{jx.exports=Ux()});var qx=nt(sc=>{"use strict";Object.defineProperty(sc,"__esModule",{value:!0});function ej(o,l,f){let h={"x-algolia-api-key":f,"x-algolia-application-id":l};return{headers(){return o===Y3.WithinHeaders?h:{}},queryParameters(){return o===Y3.WithinQueryParameters?h:{}}}}function tj(o){let l=0,f=()=>(l++,new Promise(h=>{setTimeout(()=>{h(o(f))},Math.min(100*l,1e3))}));return o(f)}function Hx(o,l=(f,h)=>Promise.resolve()){return Object.assign(o,{wait(f){return Hx(o.then(h=>Promise.all([l(h,f),h])).then(h=>h[1]))}})}function nj(o){let l=o.length-1;for(l;l>0;l--){let f=Math.floor(Math.random()*(l+1)),h=o[l];o[l]=o[f],o[f]=h}return o}function rj(o,l){return Object.keys(l!==void 0?l:{}).forEach(f=>{o[f]=l[f](o)}),o}function ij(o,...l){let f=0;return o.replace(/%s/g,()=>encodeURIComponent(l[f++]))}var uj="4.2.0",oj=o=>()=>o.transporter.requester.destroy(),Y3={WithinQueryParameters:0,WithinHeaders:1};sc.AuthMode=Y3;sc.addMethods=rj;sc.createAuth=ej;sc.createRetryablePromise=tj;sc.createWaitablePromise=Hx;sc.destroy=oj;sc.encode=ij;sc.shuffle=nj;sc.version=uj});var Pg=nt((TW,Wx)=>{Wx.exports=qx()});var Vx=nt(K3=>{"use strict";Object.defineProperty(K3,"__esModule",{value:!0});var lj={Delete:"DELETE",Get:"GET",Post:"POST",Put:"PUT"};K3.MethodEnum=lj});var Ig=nt((xW,Gx)=>{Gx.exports=Vx()});var l5=nt(G0=>{"use strict";Object.defineProperty(G0,"__esModule",{value:!0});var Kx=Ig();function X3(o,l){let f=o||{},h=f.data||{};return Object.keys(f).forEach(E=>{["timeout","headers","queryParameters","data","cacheable"].indexOf(E)===-1&&(h[E]=f[E])}),{data:Object.entries(h).length>0?h:void 0,timeout:f.timeout||l,headers:f.headers||{},queryParameters:f.queryParameters||{},cacheable:f.cacheable}}var T4={Read:1,Write:2,Any:3},um={Up:1,Down:2,Timeouted:3},Xx=2*60*1e3;function J3(o,l=um.Up){return{...o,status:l,lastUpdate:Date.now()}}function Qx(o){return o.status===um.Up||Date.now()-o.lastUpdate>Xx}function Jx(o){return o.status===um.Timeouted&&Date.now()-o.lastUpdate<=Xx}function Z3(o){return{protocol:o.protocol||"https",url:o.url,accept:o.accept||T4.Any}}function sj(o,l){return Promise.all(l.map(f=>o.get(f,()=>Promise.resolve(J3(f))))).then(f=>{let h=f.filter(F=>Qx(F)),E=f.filter(F=>Jx(F)),t=[...h,...E],N=t.length>0?t.map(F=>Z3(F)):l;return{getTimeout(F,k){return(E.length===0&&F===0?1:E.length+3+F)*k},statelessHosts:N}})}var aj=({isTimedOut:o,status:l})=>!o&&~~l===0,fj=o=>{let l=o.status;return o.isTimedOut||aj(o)||~~(l/100)!==2&&~~(l/100)!==4},cj=({status:o})=>~~(o/100)===2,dj=(o,l)=>fj(o)?l.onRetry(o):cj(o)?l.onSucess(o):l.onFail(o);function Yx(o,l,f,h){let E=[],t=n5(f,h),N=r5(o,h),F=f.method,k=f.method!==Kx.MethodEnum.Get?{}:{...f.data,...h.data},x={"x-algolia-agent":o.userAgent.value,...o.queryParameters,...k,...h.queryParameters},j=0,q=(V,re)=>{let y=V.pop();if(y===void 0)throw o5(Q3(E));let me={data:t,headers:N,method:F,url:e5(y,f.path,x),connectTimeout:re(j,o.timeouts.connect),responseTimeout:re(j,h.timeout)},De=ae=>{let we={request:me,response:ae,host:y,triesLeft:V.length};return E.push(we),we},ge={onSucess:ae=>Zx(ae),onRetry(ae){let we=De(ae);return ae.isTimedOut&&j++,Promise.all([o.logger.info("Retryable failure",$3(we)),o.hostsCache.set(y,J3(y,ae.isTimedOut?um.Timeouted:um.Down))]).then(()=>q(V,re))},onFail(ae){throw De(ae),$x(ae,Q3(E))}};return o.requester.send(me).then(ae=>dj(ae,ge))};return sj(o.hostsCache,l).then(V=>q([...V.statelessHosts].reverse(),V.getTimeout))}function pj(o){let{hostsCache:l,logger:f,requester:h,requestsCache:E,responsesCache:t,timeouts:N,userAgent:F,hosts:k,queryParameters:x,headers:j}=o,q={hostsCache:l,logger:f,requester:h,requestsCache:E,responsesCache:t,timeouts:N,userAgent:F,headers:j,queryParameters:x,hosts:k.map(V=>Z3(V)),read(V,re){let y=X3(re,q.timeouts.read),me=()=>Yx(q,q.hosts.filter(ae=>(ae.accept&T4.Read)!==0),V,y);if((y.cacheable!==void 0?y.cacheable:V.cacheable)!==!0)return me();let ge={request:V,mappedRequestOptions:y,transporter:{queryParameters:q.queryParameters,headers:q.headers}};return q.responsesCache.get(ge,()=>q.requestsCache.get(ge,()=>q.requestsCache.set(ge,me()).then(ae=>Promise.all([q.requestsCache.delete(ge),ae]),ae=>Promise.all([q.requestsCache.delete(ge),Promise.reject(ae)])).then(([ae,we])=>we)),{miss:ae=>q.responsesCache.set(ge,ae)})},write(V,re){return Yx(q,q.hosts.filter(y=>(y.accept&T4.Write)!==0),V,X3(re,q.timeouts.write))}};return q}function hj(o){let l={value:`Algolia for JavaScript (${o})`,add(f){let h=`; ${f.segment}${f.version!==void 0?` (${f.version})`:""}`;return l.value.indexOf(h)===-1&&(l.value=`${l.value}${h}`),l}};return l}function Zx(o){try{return JSON.parse(o.content)}catch(l){throw u5(l.message,o)}}function $x({content:o,status:l},f){let h=o;try{h=JSON.parse(o).message}catch{}return i5(h,l,f)}function vj(o,...l){let f=0;return o.replace(/%s/g,()=>encodeURIComponent(l[f++]))}function e5(o,l,f){let h=t5(f),E=`${o.protocol}://${o.url}/${l.charAt(0)==="/"?l.substr(1):l}`;return h.length&&(E+=`?${h}`),E}function t5(o){let l=f=>Object.prototype.toString.call(f)==="[object Object]"||Object.prototype.toString.call(f)==="[object Array]";return Object.keys(o).map(f=>vj("%s=%s",f,l(o[f])?JSON.stringify(o[f]):o[f])).join("&")}function n5(o,l){if(o.method===Kx.MethodEnum.Get||o.data===void 0&&l.data===void 0)return;let f=Array.isArray(o.data)?o.data:{...o.data,...l.data};return JSON.stringify(f)}function r5(o,l){let f={...o.headers,...l.headers},h={};return Object.keys(f).forEach(E=>{let t=f[E];h[E.toLowerCase()]=t}),h}function Q3(o){return o.map(l=>$3(l))}function $3(o){let l=o.request.headers["x-algolia-api-key"]?{"x-algolia-api-key":"*****"}:{};return{...o,request:{...o.request,headers:{...o.request.headers,...l}}}}function i5(o,l,f){return{name:"ApiError",message:o,status:l,transporterStackTrace:f}}function u5(o,l){return{name:"DeserializationError",message:o,response:l}}function o5(o){return{name:"RetryError",message:"Unreachable hosts - your application id may be incorrect. If the error persists, contact support@algolia.com.",transporterStackTrace:o}}G0.CallEnum=T4;G0.HostStatusEnum=um;G0.createApiError=i5;G0.createDeserializationError=u5;G0.createMappedRequestOptions=X3;G0.createRetryError=o5;G0.createStatefulHost=J3;G0.createStatelessHost=Z3;G0.createTransporter=pj;G0.createUserAgent=hj;G0.deserializeFailure=$x;G0.deserializeSuccess=Zx;G0.isStatefulHostTimeouted=Jx;G0.isStatefulHostUp=Qx;G0.serializeData=n5;G0.serializeHeaders=r5;G0.serializeQueryParameters=t5;G0.serializeUrl=e5;G0.stackFrameWithoutCredentials=$3;G0.stackTraceWithoutCredentials=Q3});var bg=nt((AW,s5)=>{s5.exports=l5()});var a5=nt(y2=>{"use strict";Object.defineProperty(y2,"__esModule",{value:!0});var om=Pg(),mj=bg(),Bg=Ig(),yj=o=>{let l=o.region||"us",f=om.createAuth(om.AuthMode.WithinHeaders,o.appId,o.apiKey),h=mj.createTransporter({hosts:[{url:`analytics.${l}.algolia.com`}],...o,headers:{...f.headers(),"content-type":"application/json",...o.headers},queryParameters:{...f.queryParameters(),...o.queryParameters}}),E=o.appId;return om.addMethods({appId:E,transporter:h},o.methods)},gj=o=>(l,f)=>o.transporter.write({method:Bg.MethodEnum.Post,path:"2/abtests",data:l},f),_j=o=>(l,f)=>o.transporter.write({method:Bg.MethodEnum.Delete,path:om.encode("2/abtests/%s",l)},f),Ej=o=>(l,f)=>o.transporter.read({method:Bg.MethodEnum.Get,path:om.encode("2/abtests/%s",l)},f),Dj=o=>l=>o.transporter.read({method:Bg.MethodEnum.Get,path:"2/abtests"},l),wj=o=>(l,f)=>o.transporter.write({method:Bg.MethodEnum.Post,path:om.encode("2/abtests/%s/stop",l)},f);y2.addABTest=gj;y2.createAnalyticsClient=yj;y2.deleteABTest=_j;y2.getABTest=Ej;y2.getABTests=Dj;y2.stopABTest=wj});var c5=nt((MW,f5)=>{f5.exports=a5()});var p5=nt(Ug=>{"use strict";Object.defineProperty(Ug,"__esModule",{value:!0});var ew=Pg(),Sj=bg(),d5=Ig(),Tj=o=>{let l=o.region||"us",f=ew.createAuth(ew.AuthMode.WithinHeaders,o.appId,o.apiKey),h=Sj.createTransporter({hosts:[{url:`recommendation.${l}.algolia.com`}],...o,headers:{...f.headers(),"content-type":"application/json",...o.headers},queryParameters:{...f.queryParameters(),...o.queryParameters}});return ew.addMethods({appId:o.appId,transporter:h},o.methods)},Cj=o=>l=>o.transporter.read({method:d5.MethodEnum.Get,path:"1/strategies/personalization"},l),xj=o=>(l,f)=>o.transporter.write({method:d5.MethodEnum.Post,path:"1/strategies/personalization",data:l},f);Ug.createRecommendationClient=Tj;Ug.getPersonalizationStrategy=Cj;Ug.setPersonalizationStrategy=xj});var v5=nt((NW,h5)=>{h5.exports=p5()});var A5=nt(tn=>{"use strict";Object.defineProperty(tn,"__esModule",{value:!0});var Nn=Pg(),ra=bg(),Ur=Ig(),Rj=hi("crypto");function C4(o){let l=f=>o.request(f).then(h=>{if(o.batch!==void 0&&o.batch(h.hits),!o.shouldStop(h))return h.cursor?l({cursor:h.cursor}):l({page:(f.page||0)+1})});return l({})}var Aj=o=>{let l=o.appId,f=Nn.createAuth(o.authMode!==void 0?o.authMode:Nn.AuthMode.WithinHeaders,l,o.apiKey),h=ra.createTransporter({hosts:[{url:`${l}-dsn.algolia.net`,accept:ra.CallEnum.Read},{url:`${l}.algolia.net`,accept:ra.CallEnum.Write}].concat(Nn.shuffle([{url:`${l}-1.algolianet.com`},{url:`${l}-2.algolianet.com`},{url:`${l}-3.algolianet.com`}])),...o,headers:{...f.headers(),"content-type":"application/x-www-form-urlencoded",...o.headers},queryParameters:{...f.queryParameters(),...o.queryParameters}}),E={transporter:h,appId:l,addAlgoliaAgent(t,N){h.userAgent.add({segment:t,version:N})},clearCache(){return Promise.all([h.requestsCache.clear(),h.responsesCache.clear()]).then(()=>{})}};return Nn.addMethods(E,o.methods)};function m5(){return{name:"MissingObjectIDError",message:"All objects must have an unique objectID (like a primary key) to be valid. Algolia is also able to generate objectIDs automatically but *it's not recommended*. To do it, use the `{'autoGenerateObjectIDIfNotExist': true}` option."}}function y5(){return{name:"ObjectNotFoundError",message:"Object not found."}}function g5(){return{name:"ValidUntilNotFoundError",message:"ValidUntil not found in given secured api key."}}var Oj=o=>(l,f)=>{let{queryParameters:h,...E}=f||{},t={acl:l,...h!==void 0?{queryParameters:h}:{}},N=(F,k)=>Nn.createRetryablePromise(x=>jg(o)(F.key,k).catch(j=>{if(j.status!==404)throw j;return x()}));return Nn.createWaitablePromise(o.transporter.write({method:Ur.MethodEnum.Post,path:"1/keys",data:t},E),N)},Mj=o=>(l,f,h)=>{let E=ra.createMappedRequestOptions(h);return E.queryParameters["X-Algolia-User-ID"]=l,o.transporter.write({method:Ur.MethodEnum.Post,path:"1/clusters/mapping",data:{cluster:f}},E)},kj=o=>(l,f,h)=>o.transporter.write({method:Ur.MethodEnum.Post,path:"1/clusters/mapping/batch",data:{users:l,cluster:f}},h),x4=o=>(l,f,h)=>{let E=(t,N)=>zg(o)(l,{methods:{waitTask:xo}}).waitTask(t.taskID,N);return Nn.createWaitablePromise(o.transporter.write({method:Ur.MethodEnum.Post,path:Nn.encode("1/indexes/%s/operation",l),data:{operation:"copy",destination:f}},h),E)},Nj=o=>(l,f,h)=>x4(o)(l,f,{...h,scope:[A4.Rules]}),Lj=o=>(l,f,h)=>x4(o)(l,f,{...h,scope:[A4.Settings]}),Fj=o=>(l,f,h)=>x4(o)(l,f,{...h,scope:[A4.Synonyms]}),Pj=o=>(l,f)=>{let h=(E,t)=>Nn.createRetryablePromise(N=>jg(o)(l,t).then(N).catch(F=>{if(F.status!==404)throw F}));return Nn.createWaitablePromise(o.transporter.write({method:Ur.MethodEnum.Delete,path:Nn.encode("1/keys/%s",l)},f),h)},Ij=()=>(o,l)=>{let f=ra.serializeQueryParameters(l),h=Rj.createHmac("sha256",o).update(f).digest("hex");return Buffer.from(h+f).toString("base64")},jg=o=>(l,f)=>o.transporter.read({method:Ur.MethodEnum.Get,path:Nn.encode("1/keys/%s",l)},f),bj=o=>l=>o.transporter.read({method:Ur.MethodEnum.Get,path:"1/logs"},l),Bj=()=>o=>{let l=Buffer.from(o,"base64").toString("ascii"),f=/validUntil=(\d+)/,h=l.match(f);if(h===null)throw g5();return parseInt(h[1],10)-Math.round(new Date().getTime()/1e3)},Uj=o=>l=>o.transporter.read({method:Ur.MethodEnum.Get,path:"1/clusters/mapping/top"},l),jj=o=>(l,f)=>o.transporter.read({method:Ur.MethodEnum.Get,path:Nn.encode("1/clusters/mapping/%s",l)},f),zj=o=>l=>{let{retrieveMappings:f,...h}=l||{};return f===!0&&(h.getClusters=!0),o.transporter.read({method:Ur.MethodEnum.Get,path:"1/clusters/mapping/pending"},h)},zg=o=>(l,f={})=>{let h={transporter:o.transporter,appId:o.appId,indexName:l};return Nn.addMethods(h,f.methods)},Hj=o=>l=>o.transporter.read({method:Ur.MethodEnum.Get,path:"1/keys"},l),qj=o=>l=>o.transporter.read({method:Ur.MethodEnum.Get,path:"1/clusters"},l),Wj=o=>l=>o.transporter.read({method:Ur.MethodEnum.Get,path:"1/indexes"},l),Vj=o=>l=>o.transporter.read({method:Ur.MethodEnum.Get,path:"1/clusters/mapping"},l),Gj=o=>(l,f,h)=>{let E=(t,N)=>zg(o)(l,{methods:{waitTask:xo}}).waitTask(t.taskID,N);return Nn.createWaitablePromise(o.transporter.write({method:Ur.MethodEnum.Post,path:Nn.encode("1/indexes/%s/operation",l),data:{operation:"move",destination:f}},h),E)},Yj=o=>(l,f)=>{let h=(E,t)=>Promise.all(Object.keys(E.taskID).map(N=>zg(o)(N,{methods:{waitTask:xo}}).waitTask(E.taskID[N],t)));return Nn.createWaitablePromise(o.transporter.write({method:Ur.MethodEnum.Post,path:"1/indexes/*/batch",data:{requests:l}},f),h)},Kj=o=>(l,f)=>o.transporter.read({method:Ur.MethodEnum.Post,path:"1/indexes/*/objects",data:{requests:l}},f),Xj=o=>(l,f)=>{let h=l.map(E=>({...E,params:ra.serializeQueryParameters(E.params||{})}));return o.transporter.read({method:Ur.MethodEnum.Post,path:"1/indexes/*/queries",data:{requests:h},cacheable:!0},f)},Qj=o=>(l,f)=>Promise.all(l.map(h=>{let{facetName:E,facetQuery:t,...N}=h.params;return zg(o)(h.indexName,{methods:{searchForFacetValues:C5}}).searchForFacetValues(E,t,{...f,...N})})),Jj=o=>(l,f)=>{let h=ra.createMappedRequestOptions(f);return h.queryParameters["X-Algolia-User-ID"]=l,o.transporter.write({method:Ur.MethodEnum.Delete,path:"1/clusters/mapping"},h)},Zj=o=>(l,f)=>{let h=(E,t)=>Nn.createRetryablePromise(N=>jg(o)(l,t).catch(F=>{if(F.status!==404)throw F;return N()}));return Nn.createWaitablePromise(o.transporter.write({method:Ur.MethodEnum.Post,path:Nn.encode("1/keys/%s/restore",l)},f),h)},$j=o=>(l,f)=>o.transporter.read({method:Ur.MethodEnum.Post,path:"1/clusters/mapping/search",data:{query:l}},f),ez=o=>(l,f)=>{let h=Object.assign({},f),{queryParameters:E,...t}=f||{},N=E?{queryParameters:E}:{},F=["acl","indexes","referers","restrictSources","queryParameters","description","maxQueriesPerIPPerHour","maxHitsPerQuery"],k=j=>Object.keys(h).filter(q=>F.indexOf(q)!==-1).every(q=>j[q]===h[q]),x=(j,q)=>Nn.createRetryablePromise(V=>jg(o)(l,q).then(re=>k(re)?Promise.resolve():V()));return Nn.createWaitablePromise(o.transporter.write({method:Ur.MethodEnum.Put,path:Nn.encode("1/keys/%s",l),data:N},t),x)},_5=o=>(l,f)=>{let h=(E,t)=>xo(o)(E.taskID,t);return Nn.createWaitablePromise(o.transporter.write({method:Ur.MethodEnum.Post,path:Nn.encode("1/indexes/%s/batch",o.indexName),data:{requests:l}},f),h)},tz=o=>l=>C4({...l,shouldStop:f=>f.cursor===void 0,request:f=>o.transporter.read({method:Ur.MethodEnum.Post,path:Nn.encode("1/indexes/%s/browse",o.indexName),data:f},l)}),nz=o=>l=>{let f={hitsPerPage:1e3,...l};return C4({...f,shouldStop:h=>h.hits.length({...E,hits:E.hits.map(t=>(delete t._highlightResult,t))}))}})},rz=o=>l=>{let f={hitsPerPage:1e3,...l};return C4({...f,shouldStop:h=>h.hits.length({...E,hits:E.hits.map(t=>(delete t._highlightResult,t))}))}})},R4=o=>(l,f,h)=>{let{batchSize:E,...t}=h||{},N={taskIDs:[],objectIDs:[]},F=(k=0)=>{let x=[],j;for(j=k;j({action:f,body:q})),t).then(q=>(N.objectIDs=N.objectIDs.concat(q.objectIDs),N.taskIDs.push(q.taskID),j++,F(j)))};return Nn.createWaitablePromise(F(),(k,x)=>Promise.all(k.taskIDs.map(j=>xo(o)(j,x))))},iz=o=>l=>Nn.createWaitablePromise(o.transporter.write({method:Ur.MethodEnum.Post,path:Nn.encode("1/indexes/%s/clear",o.indexName)},l),(f,h)=>xo(o)(f.taskID,h)),uz=o=>l=>{let{forwardToReplicas:f,...h}=l||{},E=ra.createMappedRequestOptions(h);return f&&(E.queryParameters.forwardToReplicas=1),Nn.createWaitablePromise(o.transporter.write({method:Ur.MethodEnum.Post,path:Nn.encode("1/indexes/%s/rules/clear",o.indexName)},E),(t,N)=>xo(o)(t.taskID,N))},oz=o=>l=>{let{forwardToReplicas:f,...h}=l||{},E=ra.createMappedRequestOptions(h);return f&&(E.queryParameters.forwardToReplicas=1),Nn.createWaitablePromise(o.transporter.write({method:Ur.MethodEnum.Post,path:Nn.encode("1/indexes/%s/synonyms/clear",o.indexName)},E),(t,N)=>xo(o)(t.taskID,N))},lz=o=>(l,f)=>Nn.createWaitablePromise(o.transporter.write({method:Ur.MethodEnum.Post,path:Nn.encode("1/indexes/%s/deleteByQuery",o.indexName),data:l},f),(h,E)=>xo(o)(h.taskID,E)),sz=o=>l=>Nn.createWaitablePromise(o.transporter.write({method:Ur.MethodEnum.Delete,path:Nn.encode("1/indexes/%s",o.indexName)},l),(f,h)=>xo(o)(f.taskID,h)),az=o=>(l,f)=>Nn.createWaitablePromise(E5(o)([l],f).then(h=>({taskID:h.taskIDs[0]})),(h,E)=>xo(o)(h.taskID,E)),E5=o=>(l,f)=>{let h=l.map(E=>({objectID:E}));return R4(o)(h,fh.DeleteObject,f)},fz=o=>(l,f)=>{let{forwardToReplicas:h,...E}=f||{},t=ra.createMappedRequestOptions(E);return h&&(t.queryParameters.forwardToReplicas=1),Nn.createWaitablePromise(o.transporter.write({method:Ur.MethodEnum.Delete,path:Nn.encode("1/indexes/%s/rules/%s",o.indexName,l)},t),(N,F)=>xo(o)(N.taskID,F))},cz=o=>(l,f)=>{let{forwardToReplicas:h,...E}=f||{},t=ra.createMappedRequestOptions(E);return h&&(t.queryParameters.forwardToReplicas=1),Nn.createWaitablePromise(o.transporter.write({method:Ur.MethodEnum.Delete,path:Nn.encode("1/indexes/%s/synonyms/%s",o.indexName,l)},t),(N,F)=>xo(o)(N.taskID,F))},dz=o=>l=>D5(o)(l).then(()=>!0).catch(f=>{if(f.status!==404)throw f;return!1}),pz=o=>(l,f)=>{let{query:h,paginate:E,...t}=f||{},N=0,F=()=>T5(o)(h||"",{...t,page:N}).then(k=>{for(let[x,j]of Object.entries(k.hits))if(l(j))return{object:j,position:parseInt(x,10),page:N};if(N++,E===!1||N>=k.nbPages)throw y5();return F()});return F()},hz=o=>(l,f)=>o.transporter.read({method:Ur.MethodEnum.Get,path:Nn.encode("1/indexes/%s/%s",o.indexName,l)},f),vz=()=>(o,l)=>{for(let[f,h]of Object.entries(o.hits))if(h.objectID===l)return parseInt(f,10);return-1},mz=o=>(l,f)=>{let{attributesToRetrieve:h,...E}=f||{},t=l.map(N=>({indexName:o.indexName,objectID:N,...h?{attributesToRetrieve:h}:{}}));return o.transporter.read({method:Ur.MethodEnum.Post,path:"1/indexes/*/objects",data:{requests:t}},E)},yz=o=>(l,f)=>o.transporter.read({method:Ur.MethodEnum.Get,path:Nn.encode("1/indexes/%s/rules/%s",o.indexName,l)},f),D5=o=>l=>o.transporter.read({method:Ur.MethodEnum.Get,path:Nn.encode("1/indexes/%s/settings",o.indexName),data:{getVersion:2}},l),gz=o=>(l,f)=>o.transporter.read({method:Ur.MethodEnum.Get,path:Nn.encode("1/indexes/%s/synonyms/%s",o.indexName,l)},f),w5=o=>(l,f)=>o.transporter.read({method:Ur.MethodEnum.Get,path:Nn.encode("1/indexes/%s/task/%s",o.indexName,l.toString())},f),_z=o=>(l,f)=>Nn.createWaitablePromise(S5(o)([l],f).then(h=>({objectID:h.objectIDs[0],taskID:h.taskIDs[0]})),(h,E)=>xo(o)(h.taskID,E)),S5=o=>(l,f)=>{let{createIfNotExists:h,...E}=f||{},t=h?fh.PartialUpdateObject:fh.PartialUpdateObjectNoCreate;return R4(o)(l,t,E)},Ez=o=>(l,f)=>{let{safe:h,autoGenerateObjectIDIfNotExist:E,batchSize:t,...N}=f||{},F=(y,me,De,ge)=>Nn.createWaitablePromise(o.transporter.write({method:Ur.MethodEnum.Post,path:Nn.encode("1/indexes/%s/operation",y),data:{operation:De,destination:me}},ge),(ae,we)=>xo(o)(ae.taskID,we)),k=Math.random().toString(36).substring(7),x=`${o.indexName}_tmp_${k}`,j=tw({appId:o.appId,transporter:o.transporter,indexName:x}),q=[],V=F(o.indexName,x,"copy",{...N,scope:["settings","synonyms","rules"]});q.push(V);let re=(h?V.wait(N):V).then(()=>{let y=j(l,{...N,autoGenerateObjectIDIfNotExist:E,batchSize:t});return q.push(y),h?y.wait(N):y}).then(()=>{let y=F(x,o.indexName,"move",N);return q.push(y),h?y.wait(N):y}).then(()=>Promise.all(q)).then(([y,me,De])=>({objectIDs:me.objectIDs,taskIDs:[y.taskID,...me.taskIDs,De.taskID]}));return Nn.createWaitablePromise(re,(y,me)=>Promise.all(q.map(De=>De.wait(me))))},Dz=o=>(l,f)=>nw(o)(l,{...f,clearExistingRules:!0}),wz=o=>(l,f)=>rw(o)(l,{...f,replaceExistingSynonyms:!0}),Sz=o=>(l,f)=>Nn.createWaitablePromise(tw(o)([l],f).then(h=>({objectID:h.objectIDs[0],taskID:h.taskIDs[0]})),(h,E)=>xo(o)(h.taskID,E)),tw=o=>(l,f)=>{let{autoGenerateObjectIDIfNotExist:h,...E}=f||{},t=h?fh.AddObject:fh.UpdateObject;if(t===fh.UpdateObject){for(let N of l)if(N.objectID===void 0)return Nn.createWaitablePromise(Promise.reject(m5()))}return R4(o)(l,t,E)},Tz=o=>(l,f)=>nw(o)([l],f),nw=o=>(l,f)=>{let{forwardToReplicas:h,clearExistingRules:E,...t}=f||{},N=ra.createMappedRequestOptions(t);return h&&(N.queryParameters.forwardToReplicas=1),E&&(N.queryParameters.clearExistingRules=1),Nn.createWaitablePromise(o.transporter.write({method:Ur.MethodEnum.Post,path:Nn.encode("1/indexes/%s/rules/batch",o.indexName),data:l},N),(F,k)=>xo(o)(F.taskID,k))},Cz=o=>(l,f)=>rw(o)([l],f),rw=o=>(l,f)=>{let{forwardToReplicas:h,replaceExistingSynonyms:E,...t}=f||{},N=ra.createMappedRequestOptions(t);return h&&(N.queryParameters.forwardToReplicas=1),E&&(N.queryParameters.replaceExistingSynonyms=1),Nn.createWaitablePromise(o.transporter.write({method:Ur.MethodEnum.Post,path:Nn.encode("1/indexes/%s/synonyms/batch",o.indexName),data:l},N),(F,k)=>xo(o)(F.taskID,k))},T5=o=>(l,f)=>o.transporter.read({method:Ur.MethodEnum.Post,path:Nn.encode("1/indexes/%s/query",o.indexName),data:{query:l},cacheable:!0},f),C5=o=>(l,f,h)=>o.transporter.read({method:Ur.MethodEnum.Post,path:Nn.encode("1/indexes/%s/facets/%s/query",o.indexName,l),data:{facetQuery:f},cacheable:!0},h),x5=o=>(l,f)=>o.transporter.read({method:Ur.MethodEnum.Post,path:Nn.encode("1/indexes/%s/rules/search",o.indexName),data:{query:l}},f),R5=o=>(l,f)=>o.transporter.read({method:Ur.MethodEnum.Post,path:Nn.encode("1/indexes/%s/synonyms/search",o.indexName),data:{query:l}},f),xz=o=>(l,f)=>{let{forwardToReplicas:h,...E}=f||{},t=ra.createMappedRequestOptions(E);return h&&(t.queryParameters.forwardToReplicas=1),Nn.createWaitablePromise(o.transporter.write({method:Ur.MethodEnum.Put,path:Nn.encode("1/indexes/%s/settings",o.indexName),data:l},t),(N,F)=>xo(o)(N.taskID,F))},xo=o=>(l,f)=>Nn.createRetryablePromise(h=>w5(o)(l,f).then(E=>E.status!=="published"?h():void 0)),Rz={AddObject:"addObject",Analytics:"analytics",Browser:"browse",DeleteIndex:"deleteIndex",DeleteObject:"deleteObject",EditSettings:"editSettings",ListIndexes:"listIndexes",Logs:"logs",Recommendation:"recommendation",Search:"search",SeeUnretrievableAttributes:"seeUnretrievableAttributes",Settings:"settings",Usage:"usage"},fh={AddObject:"addObject",UpdateObject:"updateObject",PartialUpdateObject:"partialUpdateObject",PartialUpdateObjectNoCreate:"partialUpdateObjectNoCreate",DeleteObject:"deleteObject"},A4={Settings:"settings",Synonyms:"synonyms",Rules:"rules"},Az={None:"none",StopIfEnoughMatches:"stopIfEnoughMatches"},Oz={Synonym:"synonym",OneWaySynonym:"oneWaySynonym",AltCorrection1:"altCorrection1",AltCorrection2:"altCorrection2",Placeholder:"placeholder"};tn.ApiKeyACLEnum=Rz;tn.BatchActionEnum=fh;tn.ScopeEnum=A4;tn.StrategyEnum=Az;tn.SynonymEnum=Oz;tn.addApiKey=Oj;tn.assignUserID=Mj;tn.assignUserIDs=kj;tn.batch=_5;tn.browseObjects=tz;tn.browseRules=nz;tn.browseSynonyms=rz;tn.chunkedBatch=R4;tn.clearObjects=iz;tn.clearRules=uz;tn.clearSynonyms=oz;tn.copyIndex=x4;tn.copyRules=Nj;tn.copySettings=Lj;tn.copySynonyms=Fj;tn.createBrowsablePromise=C4;tn.createMissingObjectIDError=m5;tn.createObjectNotFoundError=y5;tn.createSearchClient=Aj;tn.createValidUntilNotFoundError=g5;tn.deleteApiKey=Pj;tn.deleteBy=lz;tn.deleteIndex=sz;tn.deleteObject=az;tn.deleteObjects=E5;tn.deleteRule=fz;tn.deleteSynonym=cz;tn.exists=dz;tn.findObject=pz;tn.generateSecuredApiKey=Ij;tn.getApiKey=jg;tn.getLogs=bj;tn.getObject=hz;tn.getObjectPosition=vz;tn.getObjects=mz;tn.getRule=yz;tn.getSecuredApiKeyRemainingValidity=Bj;tn.getSettings=D5;tn.getSynonym=gz;tn.getTask=w5;tn.getTopUserIDs=Uj;tn.getUserID=jj;tn.hasPendingMappings=zj;tn.initIndex=zg;tn.listApiKeys=Hj;tn.listClusters=qj;tn.listIndices=Wj;tn.listUserIDs=Vj;tn.moveIndex=Gj;tn.multipleBatch=Yj;tn.multipleGetObjects=Kj;tn.multipleQueries=Xj;tn.multipleSearchForFacetValues=Qj;tn.partialUpdateObject=_z;tn.partialUpdateObjects=S5;tn.removeUserID=Jj;tn.replaceAllObjects=Ez;tn.replaceAllRules=Dz;tn.replaceAllSynonyms=wz;tn.restoreApiKey=Zj;tn.saveObject=Sz;tn.saveObjects=tw;tn.saveRule=Tz;tn.saveRules=nw;tn.saveSynonym=Cz;tn.saveSynonyms=rw;tn.search=T5;tn.searchForFacetValues=C5;tn.searchRules=x5;tn.searchSynonyms=R5;tn.searchUserIDs=$j;tn.setSettings=xz;tn.updateApiKey=ez;tn.waitTask=xo});var M5=nt((FW,O5)=>{O5.exports=A5()});var k5=nt(O4=>{"use strict";Object.defineProperty(O4,"__esModule",{value:!0});function Mz(){return{debug(o,l){return Promise.resolve()},info(o,l){return Promise.resolve()},error(o,l){return Promise.resolve()}}}var kz={Debug:1,Info:2,Error:3};O4.LogLevelEnum=kz;O4.createNullLogger=Mz});var L5=nt((IW,N5)=>{N5.exports=k5()});var I5=nt(iw=>{"use strict";Object.defineProperty(iw,"__esModule",{value:!0});var F5=hi("http"),P5=hi("https"),Nz=hi("url");function Lz(){let o={keepAlive:!0},l=new F5.Agent(o),f=new P5.Agent(o);return{send(h){return new Promise(E=>{let t=Nz.parse(h.url),N=t.query===null?t.pathname:`${t.pathname}?${t.query}`,F={agent:t.protocol==="https:"?f:l,hostname:t.hostname,path:N,method:h.method,headers:h.headers,...t.port!==void 0?{port:t.port||""}:{}},k=(t.protocol==="https:"?P5:F5).request(F,V=>{let re="";V.on("data",y=>re+=y),V.on("end",()=>{clearTimeout(j),clearTimeout(q),E({status:V.statusCode||0,content:re,isTimedOut:!1})})}),x=(V,re)=>setTimeout(()=>{k.abort(),E({status:0,content:re,isTimedOut:!0})},V*1e3),j=x(h.connectTimeout,"Connection timeout"),q;k.on("error",V=>{clearTimeout(j),clearTimeout(q),E({status:0,content:V.message,isTimedOut:!1})}),k.once("response",()=>{clearTimeout(j),q=x(h.responseTimeout,"Socket timeout")}),h.data!==void 0&&k.write(h.data),k.end()})},destroy(){return l.destroy(),f.destroy(),Promise.resolve()}}}iw.createNodeHttpRequester=Lz});var B5=nt((BW,b5)=>{b5.exports=I5()});var H5=nt((UW,z5)=>{"use strict";var U5=Bx(),Fz=zx(),lm=c5(),ow=Pg(),uw=v5(),wn=M5(),Pz=L5(),Iz=B5(),bz=bg();function j5(o,l,f){let h={appId:o,apiKey:l,timeouts:{connect:2,read:5,write:30},requester:Iz.createNodeHttpRequester(),logger:Pz.createNullLogger(),responsesCache:U5.createNullCache(),requestsCache:U5.createNullCache(),hostsCache:Fz.createInMemoryCache(),userAgent:bz.createUserAgent(ow.version).add({segment:"Node.js",version:process.versions.node})};return wn.createSearchClient({...h,...f,methods:{search:wn.multipleQueries,searchForFacetValues:wn.multipleSearchForFacetValues,multipleBatch:wn.multipleBatch,multipleGetObjects:wn.multipleGetObjects,multipleQueries:wn.multipleQueries,copyIndex:wn.copyIndex,copySettings:wn.copySettings,copyRules:wn.copyRules,copySynonyms:wn.copySynonyms,moveIndex:wn.moveIndex,listIndices:wn.listIndices,getLogs:wn.getLogs,listClusters:wn.listClusters,multipleSearchForFacetValues:wn.multipleSearchForFacetValues,getApiKey:wn.getApiKey,addApiKey:wn.addApiKey,listApiKeys:wn.listApiKeys,updateApiKey:wn.updateApiKey,deleteApiKey:wn.deleteApiKey,restoreApiKey:wn.restoreApiKey,assignUserID:wn.assignUserID,assignUserIDs:wn.assignUserIDs,getUserID:wn.getUserID,searchUserIDs:wn.searchUserIDs,listUserIDs:wn.listUserIDs,getTopUserIDs:wn.getTopUserIDs,removeUserID:wn.removeUserID,hasPendingMappings:wn.hasPendingMappings,generateSecuredApiKey:wn.generateSecuredApiKey,getSecuredApiKeyRemainingValidity:wn.getSecuredApiKeyRemainingValidity,destroy:ow.destroy,initIndex:E=>t=>wn.initIndex(E)(t,{methods:{batch:wn.batch,delete:wn.deleteIndex,getObject:wn.getObject,getObjects:wn.getObjects,saveObject:wn.saveObject,saveObjects:wn.saveObjects,search:wn.search,searchForFacetValues:wn.searchForFacetValues,waitTask:wn.waitTask,setSettings:wn.setSettings,getSettings:wn.getSettings,partialUpdateObject:wn.partialUpdateObject,partialUpdateObjects:wn.partialUpdateObjects,deleteObject:wn.deleteObject,deleteObjects:wn.deleteObjects,deleteBy:wn.deleteBy,clearObjects:wn.clearObjects,browseObjects:wn.browseObjects,getObjectPosition:wn.getObjectPosition,findObject:wn.findObject,exists:wn.exists,saveSynonym:wn.saveSynonym,saveSynonyms:wn.saveSynonyms,getSynonym:wn.getSynonym,searchSynonyms:wn.searchSynonyms,browseSynonyms:wn.browseSynonyms,deleteSynonym:wn.deleteSynonym,clearSynonyms:wn.clearSynonyms,replaceAllObjects:wn.replaceAllObjects,replaceAllSynonyms:wn.replaceAllSynonyms,searchRules:wn.searchRules,getRule:wn.getRule,deleteRule:wn.deleteRule,saveRule:wn.saveRule,saveRules:wn.saveRules,replaceAllRules:wn.replaceAllRules,browseRules:wn.browseRules,clearRules:wn.clearRules}}),initAnalytics:()=>E=>lm.createAnalyticsClient({...h,...E,methods:{addABTest:lm.addABTest,getABTest:lm.getABTest,getABTests:lm.getABTests,stopABTest:lm.stopABTest,deleteABTest:lm.deleteABTest}}),initRecommendation:()=>E=>uw.createRecommendationClient({...h,...E,methods:{getPersonalizationStrategy:uw.getPersonalizationStrategy,setPersonalizationStrategy:uw.setPersonalizationStrategy}})}})}j5.version=ow.version;z5.exports=j5});var W5=nt((jW,lw)=>{var q5=H5();lw.exports=q5;lw.exports.default=q5});var Yz={};HF(Yz,{default:()=>Gz});var G5=hi("@yarnpkg/cli"),ch=hi("@yarnpkg/core");var Cx=V0(lc()),lh=V0(Mi()),m4=(0,lh.memo)(({active:o})=>{let l=(0,lh.useMemo)(()=>o?"\u25C9":"\u25EF",[o]),f=(0,lh.useMemo)(()=>o?"green":"yellow",[o]);return lh.default.createElement(Cx.Text,{color:f},l)});var m2=V0(lc()),na=V0(Mi());var xx=V0(lc()),y4=V0(Mi());function v2({active:o},l,f){let{stdin:h}=(0,xx.useStdin)(),E=(0,y4.useCallback)((t,N)=>l(t,N),f);(0,y4.useEffect)(()=>{if(!(!o||!h))return h.on("keypress",E),()=>{h.off("keypress",E)}},[o,E,h])}var Rx=function({active:o},l,f){v2({active:o},(h,E)=>{E.name==="tab"&&(E.shift?l("before"):l("after"))},f)};var g4=function(o,l,{active:f,minus:h,plus:E,set:t,loop:N=!0}){v2({active:f},(F,k)=>{let x=l.indexOf(o);switch(k.name){case h:{let j=x-1;if(N){t(l[(l.length+j)%l.length]);return}if(j<0)return;t(l[j])}break;case E:{let j=x+1;if(N){t(l[j%l.length]);return}if(j>=l.length)return;t(l[j])}break}},[l,o,E,t,N])};var _4=({active:o=!0,children:l=[],radius:f=10,size:h=1,loop:E=!0,onFocusRequest:t,willReachEnd:N})=>{let F=De=>{if(De.key===null)throw new Error("Expected all children to have a key");return De.key},k=na.default.Children.map(l,De=>F(De)),x=k[0],[j,q]=(0,na.useState)(x),V=k.indexOf(j);(0,na.useEffect)(()=>{k.includes(j)||q(x)},[l]),(0,na.useEffect)(()=>{N&&V>=k.length-2&&N()},[V]),Rx({active:o&&!!t},De=>{t==null||t(De)},[t]),g4(j,k,{active:o,minus:"up",plus:"down",set:q,loop:E});let re=V-f,y=V+f;y>k.length&&(re-=y-k.length,y=k.length),re<0&&(y+=-re,re=0),y>=k.length&&(y=k.length-1);let me=[];for(let De=re;De<=y;++De){let ge=k[De],ae=o&&ge===j;me.push(na.default.createElement(m2.Box,{key:ge,height:h},na.default.createElement(m2.Box,{marginLeft:1,marginRight:1},na.default.createElement(m2.Text,null,ae?na.default.createElement(m2.Text,{color:"cyan",bold:!0},">"):" ")),na.default.createElement(m2.Box,null,na.default.cloneElement(l[De],{active:ae}))))}return na.default.createElement(m2.Box,{flexDirection:"column",width:"100%"},me)};var E4=V0(Mi());var Ax=V0(lc()),ed=V0(Mi()),Ox=hi("readline"),q3=ed.default.createContext(null),Mx=({children:o})=>{let{stdin:l,setRawMode:f}=(0,Ax.useStdin)();(0,ed.useEffect)(()=>{f&&f(!0),l&&(0,Ox.emitKeypressEvents)(l)},[l,f]);let[h,E]=(0,ed.useState)(new Map),t=(0,ed.useMemo)(()=>({getAll:()=>h,get:N=>h.get(N),set:(N,F)=>E(new Map([...h,[N,F]]))}),[h,E]);return ed.default.createElement(q3.Provider,{value:t,children:o})};function sh(o,l){let f=(0,E4.useContext)(q3);if(f===null)throw new Error("Expected this hook to run with a ministore context attached");if(typeof o>"u")return f.getAll();let h=(0,E4.useCallback)(t=>{f.set(o,t)},[o,f.set]),E=f.get(o);return typeof E>"u"&&(E=l),[E,h]}var D4=V0(lc()),W3=V0(Mi());async function w4(o,l,{stdin:f,stdout:h,stderr:E}={}){let t,N=k=>{let{exit:x}=(0,D4.useApp)();v2({active:!0},(j,q)=>{q.name==="return"&&(t=k,x())},[x,k])},{waitUntilExit:F}=(0,D4.render)(W3.default.createElement(Mx,null,W3.default.createElement(o,{...l,useSubmit:N})),{stdin:f,stdout:h,stderr:E});return await F(),t}var Y5=hi("clipanion"),K5=V0(Fx()),or=V0(lc()),En=V0(Mi());var V5=V0(W5()),sw={appId:"OFCNCOG2CU",apiKey:"6fe4476ee5a1832882e326b506d14126",indexName:"npm-search"},Bz=(0,V5.default)(sw.appId,sw.apiKey).initIndex(sw.indexName),aw=async(o,l=0)=>await Bz.search(o,{analyticsTags:["yarn-plugin-interactive-tools"],attributesToRetrieve:["name","version","owner","repository","humanDownloadsLast30Days"],page:l,hitsPerPage:10});var Hg=["regular","dev","peer"],dh=class extends G5.BaseCommand{async execute(){let l=await ch.Configuration.find(this.context.cwd,this.context.plugins),f=()=>En.default.createElement(or.Box,{flexDirection:"row"},En.default.createElement(or.Box,{flexDirection:"column",width:48},En.default.createElement(or.Box,null,En.default.createElement(or.Text,null,"Press ",En.default.createElement(or.Text,{bold:!0,color:"cyanBright"},""),"/",En.default.createElement(or.Text,{bold:!0,color:"cyanBright"},"")," to move between packages.")),En.default.createElement(or.Box,null,En.default.createElement(or.Text,null,"Press ",En.default.createElement(or.Text,{bold:!0,color:"cyanBright"},"")," to select a package.")),En.default.createElement(or.Box,null,En.default.createElement(or.Text,null,"Press ",En.default.createElement(or.Text,{bold:!0,color:"cyanBright"},"")," again to change the target."))),En.default.createElement(or.Box,{flexDirection:"column"},En.default.createElement(or.Box,{marginLeft:1},En.default.createElement(or.Text,null,"Press ",En.default.createElement(or.Text,{bold:!0,color:"cyanBright"},"")," to install the selected packages.")),En.default.createElement(or.Box,{marginLeft:1},En.default.createElement(or.Text,null,"Press ",En.default.createElement(or.Text,{bold:!0,color:"cyanBright"},"")," to abort.")))),h=()=>En.default.createElement(En.default.Fragment,null,En.default.createElement(or.Box,{width:15},En.default.createElement(or.Text,{bold:!0,underline:!0,color:"gray"},"Owner")),En.default.createElement(or.Box,{width:11},En.default.createElement(or.Text,{bold:!0,underline:!0,color:"gray"},"Version")),En.default.createElement(or.Box,{width:10},En.default.createElement(or.Text,{bold:!0,underline:!0,color:"gray"},"Downloads"))),E=()=>En.default.createElement(or.Box,{width:17},En.default.createElement(or.Text,{bold:!0,underline:!0,color:"gray"},"Target")),t=({hit:re,active:y})=>{let[me,De]=sh(re.name,null);v2({active:y},(we,he)=>{if(he.name!=="space")return;if(!me){De(Hg[0]);return}let ve=Hg.indexOf(me)+1;ve===Hg.length?De(null):De(Hg[ve])},[me,De]);let ge=ch.structUtils.parseIdent(re.name),ae=ch.structUtils.prettyIdent(l,ge);return En.default.createElement(or.Box,null,En.default.createElement(or.Box,{width:45},En.default.createElement(or.Text,{bold:!0,wrap:"wrap"},ae)),En.default.createElement(or.Box,{width:14,marginLeft:1},En.default.createElement(or.Text,{bold:!0,wrap:"truncate"},re.owner.name)),En.default.createElement(or.Box,{width:10,marginLeft:1},En.default.createElement(or.Text,{italic:!0,wrap:"truncate"},re.version)),En.default.createElement(or.Box,{width:16,marginLeft:1},En.default.createElement(or.Text,null,re.humanDownloadsLast30Days)))},N=({name:re,active:y})=>{let[me]=sh(re,null),De=ch.structUtils.parseIdent(re);return En.default.createElement(or.Box,null,En.default.createElement(or.Box,{width:47},En.default.createElement(or.Text,{bold:!0}," - ",ch.structUtils.prettyIdent(l,De))),Hg.map(ge=>En.default.createElement(or.Box,{key:ge,width:14,marginLeft:1},En.default.createElement(or.Text,null," ",En.default.createElement(m4,{active:me===ge})," ",En.default.createElement(or.Text,{bold:!0},ge)))))},F=()=>En.default.createElement(or.Box,{marginTop:1},En.default.createElement(or.Text,null,"Powered by Algolia.")),x=await w4(({useSubmit:re})=>{let y=sh();re(y);let me=Array.from(y.keys()).filter(We=>y.get(We)!==null),[De,ge]=(0,En.useState)(""),[ae,we]=(0,En.useState)(0),[he,ve]=(0,En.useState)([]),ue=We=>{We.match(/\t| /)||ge(We)},Ae=async()=>{we(0);let We=await aw(De);We.query===De&&ve(We.hits)},ze=async()=>{let We=await aw(De,ae+1);We.query===De&&We.page-1===ae&&(we(We.page),ve([...he,...We.hits]))};return(0,En.useEffect)(()=>{De?Ae():ve([])},[De]),En.default.createElement(or.Box,{flexDirection:"column"},En.default.createElement(f,null),En.default.createElement(or.Box,{flexDirection:"row",marginTop:1},En.default.createElement(or.Text,{bold:!0},"Search: "),En.default.createElement(or.Box,{width:41},En.default.createElement(K5.default,{value:De,onChange:ue,placeholder:"i.e. babel, webpack, react...",showCursor:!1})),En.default.createElement(h,null)),he.length?En.default.createElement(_4,{radius:2,loop:!1,children:he.map(We=>En.default.createElement(t,{key:We.name,hit:We,active:!1})),willReachEnd:ze}):En.default.createElement(or.Text,{color:"gray"},"Start typing..."),En.default.createElement(or.Box,{flexDirection:"row",marginTop:1},En.default.createElement(or.Box,{width:49},En.default.createElement(or.Text,{bold:!0},"Selected:")),En.default.createElement(E,null)),me.length?me.map(We=>En.default.createElement(N,{key:We,name:We,active:!1})):En.default.createElement(or.Text,{color:"gray"},"No selected packages..."),En.default.createElement(F,null))},{},{stdin:this.context.stdin,stdout:this.context.stdout,stderr:this.context.stderr});if(typeof x>"u")return 1;let j=Array.from(x.keys()).filter(re=>x.get(re)==="regular"),q=Array.from(x.keys()).filter(re=>x.get(re)==="dev"),V=Array.from(x.keys()).filter(re=>x.get(re)==="peer");return j.length&&await this.cli.run(["add",...j]),q.length&&await this.cli.run(["add","--dev",...q]),V&&await this.cli.run(["add","--peer",...V]),0}};dh.paths=[["search"]],dh.usage=Y5.Command.Usage({category:"Interactive commands",description:"open the search interface",details:` + This command opens a fullscreen terminal interface where you can search for and install packages from the npm registry. + `,examples:[["Open the search window","yarn search"]]});var N4=hi("@yarnpkg/cli"),Ro=hi("@yarnpkg/core");var qg=V0(lc()),g2=V0(Mi());var X5=V0(lc()),Q5=V0(Mi()),M4=({length:o,active:l})=>{if(o===0)return null;let f=o>1?` ${"-".repeat(o-1)}`:" ";return Q5.default.createElement(X5.Text,{dimColor:!l},f)};var J5=function({active:o,skewer:l,options:f,value:h,onChange:E,sizes:t=[]}){let N=f.filter(({label:k})=>!!k).map(({value:k})=>k),F=f.findIndex(k=>k.value===h&&k.label!="");return g4(h,N,{active:o,minus:"left",plus:"right",set:E}),g2.default.createElement(g2.default.Fragment,null,f.map(({label:k},x)=>{let j=x===F,q=t[x]-1||0,V=k.replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g,""),re=Math.max(0,q-V.length-2);return k?g2.default.createElement(qg.Box,{key:k,width:q,marginLeft:1},g2.default.createElement(qg.Text,{wrap:"truncate"},g2.default.createElement(m4,{active:j})," ",k),l?g2.default.createElement(M4,{active:o,length:re}):null):g2.default.createElement(qg.Box,{key:`spacer-${x}`,width:q,marginLeft:1})}))};var r9=hi("@yarnpkg/plugin-essentials"),L4=hi("clipanion");function td(){}td.prototype={diff:function(l,f){var h=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{},E=h.callback;typeof h=="function"&&(E=h,h={}),this.options=h;var t=this;function N(me){return E?(setTimeout(function(){E(void 0,me)},0),!0):me}l=this.castInput(l),f=this.castInput(f),l=this.removeEmpty(this.tokenize(l)),f=this.removeEmpty(this.tokenize(f));var F=f.length,k=l.length,x=1,j=F+k;h.maxEditLength&&(j=Math.min(j,h.maxEditLength));var q=[{newPos:-1,components:[]}],V=this.extractCommon(q[0],f,l,0);if(q[0].newPos+1>=F&&V+1>=k)return N([{value:this.join(f),count:f.length}]);function re(){for(var me=-1*x;me<=x;me+=2){var De=void 0,ge=q[me-1],ae=q[me+1],we=(ae?ae.newPos:0)-me;ge&&(q[me-1]=void 0);var he=ge&&ge.newPos+1=F&&we+1>=k)return N(Uz(t,De.components,f,l,t.useLongestToken));q[me]=De}x++}if(E)(function me(){setTimeout(function(){if(x>j)return E();re()||me()},0)})();else for(;x<=j;){var y=re();if(y)return y}},pushComponent:function(l,f,h){var E=l[l.length-1];E&&E.added===f&&E.removed===h?l[l.length-1]={count:E.count+1,added:f,removed:h}:l.push({count:1,added:f,removed:h})},extractCommon:function(l,f,h,E){for(var t=f.length,N=h.length,F=l.newPos,k=F-E,x=0;F+1re.length?me:re}),x.value=o.join(j)}else x.value=o.join(f.slice(F,F+x.count));F+=x.count,x.added||(k+=x.count)}}var V=l[N-1];return N>1&&typeof V.value=="string"&&(V.added||V.removed)&&o.equals("",V.value)&&(l[N-2].value+=V.value,l.pop()),l}function jz(o){return{newPos:o.newPos,components:o.components.slice(0)}}var rV=new td;function zz(o,l){if(typeof o=="function")l.callback=o;else if(o)for(var f in o)o.hasOwnProperty(f)&&(l[f]=o[f]);return l}var Z5=/^[A-Za-z\xC0-\u02C6\u02C8-\u02D7\u02DE-\u02FF\u1E00-\u1EFF]+$/,$5=/\S/,dw=new td;dw.equals=function(o,l){return this.options.ignoreCase&&(o=o.toLowerCase(),l=l.toLowerCase()),o===l||this.options.ignoreWhitespace&&!$5.test(o)&&!$5.test(l)};dw.tokenize=function(o){for(var l=o.split(/([^\S\r\n]+|[()[\]{}'"\r\n]|\b)/),f=0;f"u"?f:N}:h;return typeof o=="string"?o:JSON.stringify(fw(o,null,null,E),E," ")};Wg.equals=function(o,l){return td.prototype.equals.call(Wg,o.replace(/,([\r\n])/g,"$1"),l.replace(/,([\r\n])/g,"$1"))};function fw(o,l,f,h,E){l=l||[],f=f||[],h&&(o=h(E,o));var t;for(t=0;t=?)?)([0-9]+)(\.[0-9]+)(\.[0-9]+)((?:-\S+)?)$/,u9=(o,l)=>o.length>0?[o.slice(0,l)].concat(u9(o.slice(l),l)):[],ph=class extends N4.BaseCommand{async execute(){if(!this.context.stdout.isTTY)throw new L4.UsageError("This command can only be run in a TTY environment");let l=await Ro.Configuration.find(this.context.cwd,this.context.plugins),{project:f,workspace:h}=await Ro.Project.find(l,this.context.cwd),E=await Ro.Cache.find(l);if(!h)throw new N4.WorkspaceRequiredError(f.cwd,this.context.cwd);await f.restoreInstallState({restoreResolutions:!1});let t=this.context.stdout.rows-7,N=(ae,we)=>{let he=e9(ae,we),ve="";for(let ue of he)ue.added?ve+=Ro.formatUtils.pretty(l,ue.value,"green"):ue.removed||(ve+=ue.value);return ve},F=(ae,we)=>{if(ae===we)return we;let he=Ro.structUtils.parseRange(ae),ve=Ro.structUtils.parseRange(we),ue=he.selector.match(n9),Ae=ve.selector.match(n9);if(!ue||!Ae)return N(ae,we);let ze=["gray","red","yellow","green","magenta"],We=null,gt="";for(let _t=1;_t{let ve=await r9.suggestUtils.fetchDescriptorFrom(ae,he,{project:f,cache:E,preserveModifier:we,workspace:h});return ve!==null?ve.range:ae.range},x=async ae=>{let we=i9.default.valid(ae.range)?`^${ae.range}`:ae.range,[he,ve]=await Promise.all([k(ae,ae.range,we).catch(()=>null),k(ae,ae.range,"latest").catch(()=>null)]),ue=[{value:null,label:ae.range}];return he&&he!==ae.range?ue.push({value:he,label:F(ae.range,he)}):ue.push({value:null,label:""}),ve&&ve!==he&&ve!==ae.range?ue.push({value:ve,label:F(ae.range,ve)}):ue.push({value:null,label:""}),ue},j=()=>Tr.default.createElement(bi.Box,{flexDirection:"row"},Tr.default.createElement(bi.Box,{flexDirection:"column",width:49},Tr.default.createElement(bi.Box,{marginLeft:1},Tr.default.createElement(bi.Text,null,"Press ",Tr.default.createElement(bi.Text,{bold:!0,color:"cyanBright"},""),"/",Tr.default.createElement(bi.Text,{bold:!0,color:"cyanBright"},"")," to select packages.")),Tr.default.createElement(bi.Box,{marginLeft:1},Tr.default.createElement(bi.Text,null,"Press ",Tr.default.createElement(bi.Text,{bold:!0,color:"cyanBright"},""),"/",Tr.default.createElement(bi.Text,{bold:!0,color:"cyanBright"},"")," to select versions."))),Tr.default.createElement(bi.Box,{flexDirection:"column"},Tr.default.createElement(bi.Box,{marginLeft:1},Tr.default.createElement(bi.Text,null,"Press ",Tr.default.createElement(bi.Text,{bold:!0,color:"cyanBright"},"")," to install.")),Tr.default.createElement(bi.Box,{marginLeft:1},Tr.default.createElement(bi.Text,null,"Press ",Tr.default.createElement(bi.Text,{bold:!0,color:"cyanBright"},"")," to abort.")))),q=()=>Tr.default.createElement(bi.Box,{flexDirection:"row",paddingTop:1,paddingBottom:1},Tr.default.createElement(bi.Box,{width:50},Tr.default.createElement(bi.Text,{bold:!0},Tr.default.createElement(bi.Text,{color:"greenBright"},"?")," Pick the packages you want to upgrade.")),Tr.default.createElement(bi.Box,{width:17},Tr.default.createElement(bi.Text,{bold:!0,underline:!0,color:"gray"},"Current")),Tr.default.createElement(bi.Box,{width:17},Tr.default.createElement(bi.Text,{bold:!0,underline:!0,color:"gray"},"Range")),Tr.default.createElement(bi.Box,{width:17},Tr.default.createElement(bi.Text,{bold:!0,underline:!0,color:"gray"},"Latest"))),V=({active:ae,descriptor:we,suggestions:he})=>{let[ve,ue]=sh(we.descriptorHash,null),Ae=Ro.structUtils.stringifyIdent(we),ze=Math.max(0,45-Ae.length);return Tr.default.createElement(Tr.default.Fragment,null,Tr.default.createElement(bi.Box,null,Tr.default.createElement(bi.Box,{width:45},Tr.default.createElement(bi.Text,{bold:!0},Ro.structUtils.prettyIdent(l,we)),Tr.default.createElement(M4,{active:ae,length:ze})),Tr.default.createElement(J5,{active:ae,options:he,value:ve,skewer:!0,onChange:ue,sizes:[17,17,17]})))},re=({dependencies:ae})=>{let[we,he]=(0,Tr.useState)(ae.map(()=>null)),ve=(0,Tr.useRef)(!0),ue=async Ae=>{let ze=await x(Ae);return ze.filter(We=>We.label!=="").length<=1?null:{descriptor:Ae,suggestions:ze}};return(0,Tr.useEffect)(()=>()=>{ve.current=!1},[]),(0,Tr.useEffect)(()=>{let Ae=Math.trunc(t*1.75),ze=ae.slice(0,Ae),We=ae.slice(Ae),gt=u9(We,t),_t=ze.map(ue).reduce(async(Qe,ot)=>{await Qe;let Ve=await ot;Ve!==null&&(!ve.current||he(Pt=>{let Jt=Pt.findIndex(J=>J===null),it=[...Pt];return it[Jt]=Ve,it}))},Promise.resolve());gt.reduce((Qe,ot)=>Promise.all(ot.map(Ve=>Promise.resolve().then(()=>ue(Ve)))).then(async Ve=>{Ve=Ve.filter(Pt=>Pt!==null),await Qe,ve.current&&he(Pt=>{let Jt=Pt.findIndex(it=>it===null);return Pt.slice(0,Jt).concat(Ve).concat(Pt.slice(Jt+Ve.length))})}),_t).then(()=>{ve.current&&he(Qe=>Qe.filter(ot=>ot!==null))})},[]),we.length?Tr.default.createElement(_4,{radius:t>>1,children:we.map((Ae,ze)=>Ae!==null?Tr.default.createElement(V,{key:ze,active:!1,descriptor:Ae.descriptor,suggestions:Ae.suggestions}):Tr.default.createElement(bi.Text,{key:ze},"Loading..."))}):Tr.default.createElement(bi.Text,null,"No upgrades found")},me=await w4(({useSubmit:ae})=>{ae(sh());let we=new Map;for(let ve of f.workspaces)for(let ue of["dependencies","devDependencies"])for(let Ae of ve.manifest[ue].values())f.tryWorkspaceByDescriptor(Ae)===null&&(Ae.range.startsWith("link:")||we.set(Ae.descriptorHash,Ae));let he=Ro.miscUtils.sortMap(we.values(),ve=>Ro.structUtils.stringifyDescriptor(ve));return Tr.default.createElement(bi.Box,{flexDirection:"column"},Tr.default.createElement(j,null),Tr.default.createElement(q,null),Tr.default.createElement(re,{dependencies:he}))},{},{stdin:this.context.stdin,stdout:this.context.stdout,stderr:this.context.stderr});if(typeof me>"u")return 1;let De=!1;for(let ae of f.workspaces)for(let we of["dependencies","devDependencies"]){let he=ae.manifest[we];for(let ve of he.values()){let ue=me.get(ve.descriptorHash);typeof ue<"u"&&ue!==null&&(he.set(ve.identHash,Ro.structUtils.makeDescriptor(ve,ue)),De=!0)}}return De?(await Ro.StreamReport.start({configuration:l,stdout:this.context.stdout,includeLogs:!this.context.quiet},async ae=>{await f.install({cache:E,report:ae})})).exitCode():0}};ph.paths=[["upgrade-interactive"]],ph.usage=L4.Command.Usage({category:"Interactive commands",description:"open the upgrade interface",details:` + This command opens a fullscreen terminal interface where you can see any out of date packages used by your application, their status compared to the latest versions available on the remote registry, and select packages to upgrade. + `,examples:[["Open the upgrade window","yarn upgrade-interactive"]]});var Vz={commands:[dh,ph]},Gz=Vz;return qF(Yz);})(); +/* +object-assign +(c) Sindre Sorhus +@license MIT +*/ +/** + * @license + * Lodash + * Copyright OpenJS Foundation and other contributors + * Released under MIT license + * Based on Underscore.js 1.8.3 + * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + */ +/** @license React v0.0.0-experimental-51a3aa6af + * react-debug-tools.production.min.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +/** @license React v0.0.0-experimental-51a3aa6af + * react-is.production.min.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +/** @license React v0.0.0-experimental-51a3aa6af + * react.production.min.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +/** @license React v0.18.0 + * scheduler-tracing.development.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +/** @license React v0.18.0 + * scheduler-tracing.production.min.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +/** @license React v0.18.0 + * scheduler.development.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +/** @license React v0.18.0 + * scheduler.production.min.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +/** @license React v0.24.0 + * react-reconciler.development.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +/** @license React v0.24.0 + * react-reconciler.production.min.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +/** @license React v16.13.1 + * react.development.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +/** @license React v16.13.1 + * react.production.min.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +return plugin; +} +}; diff --git a/.yarnrc.yml b/.yarnrc.yml index 6d27afaac27..c513a5dbaaa 100644 --- a/.yarnrc.yml +++ b/.yarnrc.yml @@ -1,3 +1,7 @@ +logFilters: + - code: YN0013 + level: discard + nodeLinker: node-modules plugins: @@ -5,8 +9,7 @@ plugins: spec: "@yarnpkg/plugin-typescript" - path: .yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs spec: "@yarnpkg/plugin-workspace-tools" + - path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs + spec: "@yarnpkg/plugin-interactive-tools" yarnPath: .yarn/releases/yarn-3.6.3.cjs -logFilters: - - code: YN0013 - level: discard diff --git a/CHANGELOG.md b/CHANGELOG.md index e9b2dfb48a5..db4ec8f4567 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,340 @@ # Changelog +## [0.30.0](https://github.com/noir-lang/noir/compare/v0.29.0...v0.30.0) (2024-05-20) + + +### ⚠ BREAKING CHANGES + +* remove `Opcode::Brillig` from ACIR (https://github.com/AztecProtocol/aztec-packages/pull/5995) +* AES blackbox (https://github.com/AztecProtocol/aztec-packages/pull/6016) + +### Features + +* `multi_scalar_mul` blackbox func (https://github.com/AztecProtocol/aztec-packages/pull/6097) ([73a635e](https://github.com/noir-lang/noir/commit/73a635e5086cf3407f9846ce39807cd15b4e485a)) +* `variable_base_scalar_mul` blackbox func (https://github.com/AztecProtocol/aztec-packages/pull/6039) ([73a635e](https://github.com/noir-lang/noir/commit/73a635e5086cf3407f9846ce39807cd15b4e485a)) +* Add `Not` trait to stdlib ([#4999](https://github.com/noir-lang/noir/issues/4999)) ([95d4d13](https://github.com/noir-lang/noir/commit/95d4d133d1eb5e0eb44cd928d8183d890e970a13)) +* Add `std::ops::Neg` trait to stdlib ([07930d4](https://github.com/noir-lang/noir/commit/07930d4373a393146210efae69e6ec40171f047b)) +* Add native rust implementations of pedersen functions ([#4871](https://github.com/noir-lang/noir/issues/4871)) ([fb039f7](https://github.com/noir-lang/noir/commit/fb039f74df23aea39bc0593a5d538d82b4efadf0)) +* Add support for u16/i16 ([#4985](https://github.com/noir-lang/noir/issues/4985)) ([e43661d](https://github.com/noir-lang/noir/commit/e43661d16c1cd07e2af2392b88d29c689889ff9a)) +* AES blackbox (https://github.com/AztecProtocol/aztec-packages/pull/6016) ([73a635e](https://github.com/noir-lang/noir/commit/73a635e5086cf3407f9846ce39807cd15b4e485a)) +* Do not return databus returndata, keep it private. ([#5023](https://github.com/noir-lang/noir/issues/5023)) ([a5b7df1](https://github.com/noir-lang/noir/commit/a5b7df12faf9d71ff24f8c5cde5e78da44558caf)) +* Dynamic assertion payloads v2 (https://github.com/AztecProtocol/aztec-packages/pull/5949) ([73a635e](https://github.com/noir-lang/noir/commit/73a635e5086cf3407f9846ce39807cd15b4e485a)) +* Implement `From` array trait for `BoundedVec` ([#4927](https://github.com/noir-lang/noir/issues/4927)) ([bf491dc](https://github.com/noir-lang/noir/commit/bf491dce9595d0e37057ae6d6721eb7a83cec0e2)) +* Implement `ops` traits on `u16`/`i16` ([#4996](https://github.com/noir-lang/noir/issues/4996)) ([8b65663](https://github.com/noir-lang/noir/commit/8b65663f9e836c11a87e458bd7c6a52920448d5c)) +* Implement `std::ops::Sub` on `EmbeddedCurvePoint` ([07930d4](https://github.com/noir-lang/noir/commit/07930d4373a393146210efae69e6ec40171f047b)) +* Increase default expression width to 4 ([#4995](https://github.com/noir-lang/noir/issues/4995)) ([f01d309](https://github.com/noir-lang/noir/commit/f01d3090759a5ff0f1f83c5616d22890c6bd76be)) +* Parsing non-string assertion payloads in noir js (https://github.com/AztecProtocol/aztec-packages/pull/6079) ([73a635e](https://github.com/noir-lang/noir/commit/73a635e5086cf3407f9846ce39807cd15b4e485a)) +* Remove query to backend to get expression width ([#4975](https://github.com/noir-lang/noir/issues/4975)) ([e5f356b](https://github.com/noir-lang/noir/commit/e5f356b063fe4facbd14320b7eafed664d0bb027)) +* Set aztec private functions to be recursive (https://github.com/AztecProtocol/aztec-packages/pull/6192) ([73a635e](https://github.com/noir-lang/noir/commit/73a635e5086cf3407f9846ce39807cd15b4e485a)) + + +### Bug Fixes + +* Compute the correct slice length when coercing from a literal array of complex types ([#4986](https://github.com/noir-lang/noir/issues/4986)) ([f3f1150](https://github.com/noir-lang/noir/commit/f3f11507983009771656811f9570bdbe6849c7ef)) +* Defer overflow checks for unsigned integers to acir-gen ([#4832](https://github.com/noir-lang/noir/issues/4832)) ([b577761](https://github.com/noir-lang/noir/commit/b5777613c51f26fb4f580b9168c4190b1f4bd8f7)) +* Fix no predicates for brillig with intermediate functions ([#5015](https://github.com/noir-lang/noir/issues/5015)) ([9c6de4b](https://github.com/noir-lang/noir/commit/9c6de4b25d318c6d211361dd62a112a9d2432c56)) +* Fixed several vulnerabilities in U128, added some tests ([#5024](https://github.com/noir-lang/noir/issues/5024)) ([e5ab24d](https://github.com/noir-lang/noir/commit/e5ab24d6a4154d11b3c8ae08f4431b7b93c76f23)) +* Ignore no_predicates in brillig functions ([#5012](https://github.com/noir-lang/noir/issues/5012)) ([b541e79](https://github.com/noir-lang/noir/commit/b541e793e20fa3c991e0328ec2ff7926bdcdfd45)) +* Set index and value to 0 for array_get with predicate ([#4971](https://github.com/noir-lang/noir/issues/4971)) ([c49d3a9](https://github.com/noir-lang/noir/commit/c49d3a9ded819b828cffdfc031e86614da21e329)) + + +### Miscellaneous Chores + +* Remove `Opcode::Brillig` from ACIR (https://github.com/AztecProtocol/aztec-packages/pull/5995) ([73a635e](https://github.com/noir-lang/noir/commit/73a635e5086cf3407f9846ce39807cd15b4e485a)) + +## [0.29.0](https://github.com/noir-lang/noir/compare/v0.28.0...v0.29.0) (2024-05-03) + + +### ⚠ BREAKING CHANGES + +* use `distinct` return value witnesses by default ([#4951](https://github.com/noir-lang/noir/issues/4951)) +* Bit shift is restricted to u8 right operand ([#4907](https://github.com/noir-lang/noir/issues/4907)) + +### Features + +* Add `#[inline(tag)]` attribute and codegen ([#4913](https://github.com/noir-lang/noir/issues/4913)) ([1ec9cdc](https://github.com/noir-lang/noir/commit/1ec9cdc7013e867db3672d27e3a6104e4b7e7eef)) +* Add de-sugaring for `impl Trait` in function parameters ([#4919](https://github.com/noir-lang/noir/issues/4919)) ([8aad2e4](https://github.com/noir-lang/noir/commit/8aad2e45acbe08afc3902db95a83324f822c35eb)) +* Add variable size sha256 ([#4920](https://github.com/noir-lang/noir/issues/4920)) ([dbfca58](https://github.com/noir-lang/noir/commit/dbfca58a817ee1f1512e3e02138119f363c3d12b)) +* Bit shift is restricted to u8 right operand ([#4907](https://github.com/noir-lang/noir/issues/4907)) ([c4b0369](https://github.com/noir-lang/noir/commit/c4b03691feca17ef268acab523292f3051f672ea)) +* Complex outputs from acir call ([#4952](https://github.com/noir-lang/noir/issues/4952)) ([2e085b9](https://github.com/noir-lang/noir/commit/2e085b935b143c1305b70cd7ae86907b61a45fc0)) +* **experimental:** `comptime` globals ([#4918](https://github.com/noir-lang/noir/issues/4918)) ([8a3c7f1](https://github.com/noir-lang/noir/commit/8a3c7f1c11666ed5140a63a5aa296ef417c97bfa)) +* Handle `BrilligCall` opcodes in the debugger ([#4897](https://github.com/noir-lang/noir/issues/4897)) ([b380dc4](https://github.com/noir-lang/noir/commit/b380dc44de5c9f8de278ece3d531ebbc2c9238ba)) +* Handle `no_predicates` attribute ([#4942](https://github.com/noir-lang/noir/issues/4942)) ([0ce04d3](https://github.com/noir-lang/noir/commit/0ce04d3ea8734b76d96f5dd0fb2a6cdd4081969e)) +* Handle empty response foreign calls without an external resolver ([#4959](https://github.com/noir-lang/noir/issues/4959)) ([0154bde](https://github.com/noir-lang/noir/commit/0154bdef9f6dfe45497d77ecbf3904dcc138b8d7)) +* Optimize array sets in if conditions (alternate version) ([#4716](https://github.com/noir-lang/noir/issues/4716)) ([a87c655](https://github.com/noir-lang/noir/commit/a87c655c6c8c077c71e3372cc9181b7870348a3d)) +* Use `distinct` return value witnesses by default ([#4951](https://github.com/noir-lang/noir/issues/4951)) ([5f1b584](https://github.com/noir-lang/noir/commit/5f1b58470779e977293323d10ab9a8f0857ea29e)) + + +### Bug Fixes + +* Ban self-referential structs ([#4883](https://github.com/noir-lang/noir/issues/4883)) ([800f670](https://github.com/noir-lang/noir/commit/800f670b63a5a2ae08f09a86dae767089f7f67af)) +* Discard ref counts during unrolling ([#4923](https://github.com/noir-lang/noir/issues/4923)) ([91062db](https://github.com/noir-lang/noir/commit/91062db84a749bf191eae9ce487a2315cc74bfb2)) +* Ensure where clauses propagated to trait default definitions ([#4894](https://github.com/noir-lang/noir/issues/4894)) ([aaac0f6](https://github.com/noir-lang/noir/commit/aaac0f6bffbe11eb090145354f1b82919bb93cb7)) +* Move remove_if_else pass after second inlining ([#4976](https://github.com/noir-lang/noir/issues/4976)) ([96fb3e9](https://github.com/noir-lang/noir/commit/96fb3e94b3a2f7b586d17ea9445f44267f5d9c6d)) +* Nested array equality ([#4903](https://github.com/noir-lang/noir/issues/4903)) ([0cf2e2a](https://github.com/noir-lang/noir/commit/0cf2e2a1b8d247bed03ba5b7b1be5cd30f0d51b2)) +* Require for all foldable functions to use distinct return ([#4949](https://github.com/noir-lang/noir/issues/4949)) ([d4c6806](https://github.com/noir-lang/noir/commit/d4c68066ab35ce1c52510cf0c038fb627a0677c3)) +* Use annotated type when checking declaration ([#4966](https://github.com/noir-lang/noir/issues/4966)) ([f7fa696](https://github.com/noir-lang/noir/commit/f7fa69661006e1e10ddeecee1cdf8f024d6bc3e9)) + +## [0.28.0](https://github.com/noir-lang/noir/compare/v0.27.0...v0.28.0) (2024-04-24) + + +### ⚠ BREAKING CHANGES + +* Add `as_array` and remove `_slice` variants of hash functions ([#4675](https://github.com/noir-lang/noir/issues/4675)) +* reserve keyword `super` ([#4836](https://github.com/noir-lang/noir/issues/4836)) +* contract interfaces and better function calls (https://github.com/AztecProtocol/aztec-packages/pull/5687) +* change backend width to 4 (https://github.com/AztecProtocol/aztec-packages/pull/5374) +* Use fixed size arrays in black box functions where sizes are known (https://github.com/AztecProtocol/aztec-packages/pull/5620) +* trap with revert data (https://github.com/AztecProtocol/aztec-packages/pull/5732) +* **acir:** BrilligCall opcode (https://github.com/AztecProtocol/aztec-packages/pull/5709) +* remove fixed-length keccak256 (https://github.com/AztecProtocol/aztec-packages/pull/5617) +* storage_layout and `#[aztec(storage)]` (https://github.com/AztecProtocol/aztec-packages/pull/5387) +* **acir:** Add predicate to call opcode (https://github.com/AztecProtocol/aztec-packages/pull/5616) +* contract_abi-exports (https://github.com/AztecProtocol/aztec-packages/pull/5386) + +### Features + +* **acir_gen:** Brillig stdlib ([#4848](https://github.com/noir-lang/noir/issues/4848)) ([0c8175c](https://github.com/noir-lang/noir/commit/0c8175cb539efd9427c73ae5af0d48abe688ebab)) +* **acir:** Add predicate to call opcode (https://github.com/AztecProtocol/aztec-packages/pull/5616) ([2bd006a](https://github.com/noir-lang/noir/commit/2bd006ae07499e8702b0fa9565855f0a5ef1a589)) +* **acir:** BrilligCall opcode (https://github.com/AztecProtocol/aztec-packages/pull/5709) ([0f9ae0a](https://github.com/noir-lang/noir/commit/0f9ae0ac1d68714b56ba4524aedcc67212494f1b)) +* Add `min` and `max` functions to the stdlib ([#4839](https://github.com/noir-lang/noir/issues/4839)) ([6cfb328](https://github.com/noir-lang/noir/commit/6cfb328d0d162eaa20ad1a118d085e03a52d049d)) +* Add `NARGO_FOREIGN_CALL_TIMEOUT` environment variable ([#4780](https://github.com/noir-lang/noir/issues/4780)) ([791f1c8](https://github.com/noir-lang/noir/commit/791f1c8522d49972dad4eb940f9cad437e28b25b)) +* Add comptime Interpreter ([#4821](https://github.com/noir-lang/noir/issues/4821)) ([5992436](https://github.com/noir-lang/noir/commit/599243633281e6827f0f4f095fb12d313e0125fa)) +* Add return values to aztec fns (https://github.com/AztecProtocol/aztec-packages/pull/5389) ([2bd006a](https://github.com/noir-lang/noir/commit/2bd006ae07499e8702b0fa9565855f0a5ef1a589)) +* Allow numeric generics to non inlined ACIR functions ([#4834](https://github.com/noir-lang/noir/issues/4834)) ([9cc03a4](https://github.com/noir-lang/noir/commit/9cc03a4d6f714a1b2d31c6982eb8e791ba5c869c)) +* **avm:** Integrate AVM with initializers (https://github.com/AztecProtocol/aztec-packages/pull/5469) ([2bd006a](https://github.com/noir-lang/noir/commit/2bd006ae07499e8702b0fa9565855f0a5ef1a589)) +* Brillig heterogeneous memory cells (https://github.com/AztecProtocol/aztec-packages/pull/5608) ([305bcdc](https://github.com/noir-lang/noir/commit/305bcdcbd01cb84dbaac900f14cb6cf867f83bda)) +* Brillig pointer codegen and execution (https://github.com/AztecProtocol/aztec-packages/pull/5737) ([0f9ae0a](https://github.com/noir-lang/noir/commit/0f9ae0ac1d68714b56ba4524aedcc67212494f1b)) +* Change backend width to 4 (https://github.com/AztecProtocol/aztec-packages/pull/5374) ([0f9ae0a](https://github.com/noir-lang/noir/commit/0f9ae0ac1d68714b56ba4524aedcc67212494f1b)) +* Contract interfaces and better function calls (https://github.com/AztecProtocol/aztec-packages/pull/5687) ([0f9ae0a](https://github.com/noir-lang/noir/commit/0f9ae0ac1d68714b56ba4524aedcc67212494f1b)) +* Contract_abi-exports (https://github.com/AztecProtocol/aztec-packages/pull/5386) ([2bd006a](https://github.com/noir-lang/noir/commit/2bd006ae07499e8702b0fa9565855f0a5ef1a589)) +* **experimental:** Add `comptime` keyword ([#4840](https://github.com/noir-lang/noir/issues/4840)) ([4dfd7f0](https://github.com/noir-lang/noir/commit/4dfd7f03bc1b9cf57f5829c435a560bed53b7f46)) +* Get last mock oracles params ([#4789](https://github.com/noir-lang/noir/issues/4789)) ([1d96937](https://github.com/noir-lang/noir/commit/1d96937a8e94a91c0c17c97102498d067fca76c3)) +* Impl of missing functionality in new key store (https://github.com/AztecProtocol/aztec-packages/pull/5750) ([0f9ae0a](https://github.com/noir-lang/noir/commit/0f9ae0ac1d68714b56ba4524aedcc67212494f1b)) +* Implement `Eq` trait on `BoundedVec` ([#4830](https://github.com/noir-lang/noir/issues/4830)) ([6cefe16](https://github.com/noir-lang/noir/commit/6cefe16deb643951c0cc552d08e22272900ed456)) +* Lalrpop lexer prototype ([#4656](https://github.com/noir-lang/noir/issues/4656)) ([25ad018](https://github.com/noir-lang/noir/commit/25ad018a55b61dd861e899f050c48200f0a00430)) +* **nargo:** Handle call stacks for multiple Acir calls ([#4711](https://github.com/noir-lang/noir/issues/4711)) ([5b23171](https://github.com/noir-lang/noir/commit/5b231714740447d82cde7cdbe65d4a8b46a31df4)) +* Narrow ABI encoding errors down to target problem argument/field ([#4798](https://github.com/noir-lang/noir/issues/4798)) ([e412e6e](https://github.com/noir-lang/noir/commit/e412e6e30910472b9d5f9000370ce5138ad39ce7)) +* Proving the rollup circuits (https://github.com/AztecProtocol/aztec-packages/pull/5599) ([5b352d6](https://github.com/noir-lang/noir/commit/5b352d6266c40522f5626f79d2f36a409b482aaa)) +* Reserve keyword `super` ([#4836](https://github.com/noir-lang/noir/issues/4836)) ([d5028a6](https://github.com/noir-lang/noir/commit/d5028a613e5a65ad1286dd20ce0fb0313f19f6ee)) +* Restore hashing args via slice for performance (https://github.com/AztecProtocol/aztec-packages/pull/5539) ([2bd006a](https://github.com/noir-lang/noir/commit/2bd006ae07499e8702b0fa9565855f0a5ef1a589)) +* Simplify `BoundedVec::eq` ([#4838](https://github.com/noir-lang/noir/issues/4838)) ([3d33a33](https://github.com/noir-lang/noir/commit/3d33a33e74c3e7d0fc511059b07f0ef9ddd9b667)) +* **simulator:** Fetch return values at circuit execution (https://github.com/AztecProtocol/aztec-packages/pull/5642) ([305bcdc](https://github.com/noir-lang/noir/commit/305bcdcbd01cb84dbaac900f14cb6cf867f83bda)) +* Split `backend_barretenburg` into prover and verifier classes ([#4769](https://github.com/noir-lang/noir/issues/4769)) ([ce1e662](https://github.com/noir-lang/noir/commit/ce1e6624ece3c91f06b0273af9ba88e703c1b589)) +* Storage_layout and `#[aztec(storage)]` (https://github.com/AztecProtocol/aztec-packages/pull/5387) ([2bd006a](https://github.com/noir-lang/noir/commit/2bd006ae07499e8702b0fa9565855f0a5ef1a589)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/5572) ([2bd006a](https://github.com/noir-lang/noir/commit/2bd006ae07499e8702b0fa9565855f0a5ef1a589)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/5619) ([2bd006a](https://github.com/noir-lang/noir/commit/2bd006ae07499e8702b0fa9565855f0a5ef1a589)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/5697) ([305bcdc](https://github.com/noir-lang/noir/commit/305bcdcbd01cb84dbaac900f14cb6cf867f83bda)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/5725) ([5b352d6](https://github.com/noir-lang/noir/commit/5b352d6266c40522f5626f79d2f36a409b482aaa)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/5794) ([0f9ae0a](https://github.com/noir-lang/noir/commit/0f9ae0ac1d68714b56ba4524aedcc67212494f1b)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/5814) ([0f9ae0a](https://github.com/noir-lang/noir/commit/0f9ae0ac1d68714b56ba4524aedcc67212494f1b)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/5935) ([1b867b1](https://github.com/noir-lang/noir/commit/1b867b121fba5db3087ca845b4934e6732b23fd1)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/5955) ([1b867b1](https://github.com/noir-lang/noir/commit/1b867b121fba5db3087ca845b4934e6732b23fd1)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/5999) ([1b867b1](https://github.com/noir-lang/noir/commit/1b867b121fba5db3087ca845b4934e6732b23fd1)) +* Trap with revert data (https://github.com/AztecProtocol/aztec-packages/pull/5732) ([0f9ae0a](https://github.com/noir-lang/noir/commit/0f9ae0ac1d68714b56ba4524aedcc67212494f1b)) +* Unroll loops iteratively ([#4779](https://github.com/noir-lang/noir/issues/4779)) ([f831b0b](https://github.com/noir-lang/noir/commit/f831b0bdbf99cab1bcd24d494c4546a36309465e)) +* Use fixed size arrays in black box functions where sizes are known (https://github.com/AztecProtocol/aztec-packages/pull/5620) ([0f9ae0a](https://github.com/noir-lang/noir/commit/0f9ae0ac1d68714b56ba4524aedcc67212494f1b)) +* Variable length returns (https://github.com/AztecProtocol/aztec-packages/pull/5633) ([305bcdc](https://github.com/noir-lang/noir/commit/305bcdcbd01cb84dbaac900f14cb6cf867f83bda)) + + +### Bug Fixes + +* ArrayGet and Set are not pure ([#4783](https://github.com/noir-lang/noir/issues/4783)) ([90ee479](https://github.com/noir-lang/noir/commit/90ee4792c8e7115e55a3b1dadd1e43066ad8ac66)) +* Avoid huge unrolling in hash_args (https://github.com/AztecProtocol/aztec-packages/pull/5703) ([305bcdc](https://github.com/noir-lang/noir/commit/305bcdcbd01cb84dbaac900f14cb6cf867f83bda)) +* Catch panics from EC point creation (e.g. the point is at infinity) ([#4790](https://github.com/noir-lang/noir/issues/4790)) ([645dba1](https://github.com/noir-lang/noir/commit/645dba192f16ef34018828186ffb297422a8dc73)) +* Don't reuse brillig with slice arguments (https://github.com/AztecProtocol/aztec-packages/pull/5800) ([0f9ae0a](https://github.com/noir-lang/noir/commit/0f9ae0ac1d68714b56ba4524aedcc67212494f1b)) +* **experimental:** Skip over comptime functions in scan pass ([#4893](https://github.com/noir-lang/noir/issues/4893)) ([f267d42](https://github.com/noir-lang/noir/commit/f267d4205b46317eacb1c247c9dca0e7698d1259)) +* Fix curve parameters for bigints ([#4900](https://github.com/noir-lang/noir/issues/4900)) ([5985e42](https://github.com/noir-lang/noir/commit/5985e4285de9e29f7c986103a49fdaec59228887)) +* Fix panic when returning a zeroed unit value ([#4797](https://github.com/noir-lang/noir/issues/4797)) ([2ea9292](https://github.com/noir-lang/noir/commit/2ea92926956658ea99d8fb97734831eba00d3a4b)) +* Issue 4682 and add solver for unconstrained bigintegers ([#4729](https://github.com/noir-lang/noir/issues/4729)) ([e4d33c1](https://github.com/noir-lang/noir/commit/e4d33c126a2795d9aaa6048d4e91b64cb4bbe4f2)) +* Primary_message typo in errors.rs (https://github.com/AztecProtocol/aztec-packages/pull/5646) ([5b352d6](https://github.com/noir-lang/noir/commit/5b352d6266c40522f5626f79d2f36a409b482aaa)) +* Proper field inversion for bigints ([#4802](https://github.com/noir-lang/noir/issues/4802)) ([b46d0e3](https://github.com/noir-lang/noir/commit/b46d0e39f4252f8bbaa987f88d112e4c233b3d61)) +* Reset the noir-gates-diff report on master ([#4878](https://github.com/noir-lang/noir/issues/4878)) ([50bc325](https://github.com/noir-lang/noir/commit/50bc32587a837c930ed14175c98ace1530c54bef)) +* Update noir-gates-diff commit to use master reference report ([#4891](https://github.com/noir-lang/noir/issues/4891)) ([4a3ffb7](https://github.com/noir-lang/noir/commit/4a3ffb7b4c5cdd5fcadb19e7f251b1ee27b0c02b)) + + +### Miscellaneous Chores + +* Add `as_array` and remove `_slice` variants of hash functions ([#4675](https://github.com/noir-lang/noir/issues/4675)) ([8e39706](https://github.com/noir-lang/noir/commit/8e39706cbb51f27b42fbe851aaa6a67070d07c74)) +* Remove fixed-length keccak256 (https://github.com/AztecProtocol/aztec-packages/pull/5617) ([305bcdc](https://github.com/noir-lang/noir/commit/305bcdcbd01cb84dbaac900f14cb6cf867f83bda)) + +## [0.27.0](https://github.com/noir-lang/noir/compare/v0.26.0...v0.27.0) (2024-04-10) + + +### ⚠ BREAKING CHANGES + +* Brillig typed memory (https://github.com/AztecProtocol/aztec-packages/pull/5395) + +### Features + +* **acir_gen:** Fold attribute at compile-time and initial non inlined ACIR (https://github.com/AztecProtocol/aztec-packages/pull/5341) ([a0f7474](https://github.com/noir-lang/noir/commit/a0f7474ae6bd74132efdb945d2eb2383f3913cce)) +* **acvm_js:** Execute program ([#4694](https://github.com/noir-lang/noir/issues/4694)) ([386f6d0](https://github.com/noir-lang/noir/commit/386f6d0a5822912db878285cb001032a7c0ff622)) +* **acvm:** Execute multiple circuits (https://github.com/AztecProtocol/aztec-packages/pull/5380) ([a0f7474](https://github.com/noir-lang/noir/commit/a0f7474ae6bd74132efdb945d2eb2383f3913cce)) +* Add `remove_enable_side_effects` SSA pass ([#4224](https://github.com/noir-lang/noir/issues/4224)) ([94952db](https://github.com/noir-lang/noir/commit/94952db604b70a1ec18115b291de3c52565a641e)) +* Allow slices to brillig entry points ([#4713](https://github.com/noir-lang/noir/issues/4713)) ([62423d5](https://github.com/noir-lang/noir/commit/62423d552beca749b6f86b1330555aab18db58d0)) +* Brillig typed memory (https://github.com/AztecProtocol/aztec-packages/pull/5395) ([0bc18c4](https://github.com/noir-lang/noir/commit/0bc18c4f78171590dd58bded959f68f53a44cc8c)) +* **docs:** Documenting noir codegen ([#4454](https://github.com/noir-lang/noir/issues/4454)) ([24f6d85](https://github.com/noir-lang/noir/commit/24f6d85f2467a109399d21729f8bb0f97c5ba6db)) +* Improve nargo check cli with --override flag and feedback for existing files ([#4575](https://github.com/noir-lang/noir/issues/4575)) ([5e7fbd4](https://github.com/noir-lang/noir/commit/5e7fbd4e706b1691ba2dd960469cfa3b31dfb753)) +* Improve optimisations on range constraints ([#4690](https://github.com/noir-lang/noir/issues/4690)) ([96b8110](https://github.com/noir-lang/noir/commit/96b811079b0e7c0345210cfc705c00345b0b3334)) +* Improve SSA type-awareness in EQ and MUL instructions ([#4691](https://github.com/noir-lang/noir/issues/4691)) ([669f1a0](https://github.com/noir-lang/noir/commit/669f1a0fa47ad9093888a8ce8e525cb02bcf19b5)) +* **nargo:** Multiple circuits info for binary programs ([#4719](https://github.com/noir-lang/noir/issues/4719)) ([50d2735](https://github.com/noir-lang/noir/commit/50d2735825454a8638a308156d4ea23b3c4420d8)) + + +### Bug Fixes + +* "Types in a binary operation should match, but found T and T" ([#4648](https://github.com/noir-lang/noir/issues/4648)) ([30c9f31](https://github.com/noir-lang/noir/commit/30c9f3151d447de8c7467ccbee82e32b8c46a396)) +* **acvm:** Mark outputs of Opcode::Call solvable ([#4708](https://github.com/noir-lang/noir/issues/4708)) ([8fea405](https://github.com/noir-lang/noir/commit/8fea40576f262bd5bb588923c0660d8967404e56)) +* Correct ICE panic messages in brillig `convert_black_box_call` ([#4761](https://github.com/noir-lang/noir/issues/4761)) ([f3eee6c](https://github.com/noir-lang/noir/commit/f3eee6c00a9b1ea939c5757d91faac693e909301)) +* Error when a type variable is unbound during monomorphization instead of defaulting to Field ([#4674](https://github.com/noir-lang/noir/issues/4674)) ([03cdba4](https://github.com/noir-lang/noir/commit/03cdba45ac073fd6fdd91549736f36f1abaef15a)) +* Field comparisons ([#4704](https://github.com/noir-lang/noir/issues/4704)) ([079cb2a](https://github.com/noir-lang/noir/commit/079cb2a99d2d50b50688bfb56fa014acde3e3d71)) +* Impl search no longer selects an impl if multiple are applicable ([#4662](https://github.com/noir-lang/noir/issues/4662)) ([0150600](https://github.com/noir-lang/noir/commit/0150600922ee8b3e67c9b592338e8832f446685b)) +* Last use analysis & make it an SSA pass ([#4686](https://github.com/noir-lang/noir/issues/4686)) ([0d3d5fd](https://github.com/noir-lang/noir/commit/0d3d5fda9659a563ba9c2014b7c1af9e1d332ab0)) +* Slice coercions ([#4640](https://github.com/noir-lang/noir/issues/4640)) ([c0bae17](https://github.com/noir-lang/noir/commit/c0bae17e70f55ebf4b1639e0dfb075d8c5c97892)) +* **ssa:** Accurate constant type for slice dummy data in flattening ([#4661](https://github.com/noir-lang/noir/issues/4661)) ([b87654e](https://github.com/noir-lang/noir/commit/b87654e2b4761dfacc916dac70d43c1b572ec636)) +* **ssa:** Do not use get_value_max_num_bits when we want pure type information ([#4700](https://github.com/noir-lang/noir/issues/4700)) ([b55a580](https://github.com/noir-lang/noir/commit/b55a580388abc95bab6c6ef8c50eae3c5497eb3f)) +* **ssa:** Fix slice intrinsic handling in the capacity tracker ([#4643](https://github.com/noir-lang/noir/issues/4643)) ([1b50ce1](https://github.com/noir-lang/noir/commit/1b50ce155cf95193937729c2a23f34b0ade42ea0)) +* Unknown slice lengths coming from as_slice ([#4725](https://github.com/noir-lang/noir/issues/4725)) ([f21129e](https://github.com/noir-lang/noir/commit/f21129ef05efb76c5df6ee15a134f1ea535d8e90)) +* Update commit for noir-gates-diff ([#4773](https://github.com/noir-lang/noir/issues/4773)) ([a9766c5](https://github.com/noir-lang/noir/commit/a9766c5e9650160bcafc693f2617e441ed47721a)) + +## [0.26.0](https://github.com/noir-lang/noir/compare/v0.25.0...v0.26.0) (2024-03-25) + + +### ⚠ BREAKING CHANGES + +* **acir:** Program and witness stack structure (https://github.com/AztecProtocol/aztec-packages/pull/5149) +* automatic NoteInterface and NoteGetterOptions auto select (https://github.com/AztecProtocol/aztec-packages/pull/4508) +* separating out array and slice types in the AST ([#4504](https://github.com/noir-lang/noir/issues/4504)) +* Acir call opcode (https://github.com/AztecProtocol/aztec-packages/pull/4773) +* Support contracts with no constructor (https://github.com/AztecProtocol/aztec-packages/pull/5175) +* Remove open keyword from Noir (https://github.com/AztecProtocol/aztec-packages/pull/4967) + +### Features + +* Acir call opcode (https://github.com/AztecProtocol/aztec-packages/pull/4773) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* **acir:** Program and witness stack structure (https://github.com/AztecProtocol/aztec-packages/pull/5149) ([13eb71b](https://github.com/noir-lang/noir/commit/13eb71b8de44eb6aad9c37943ad06fc73db589f5)) +* Add `break` and `continue` in unconstrained code ([#4569](https://github.com/noir-lang/noir/issues/4569)) ([f2f827d](https://github.com/noir-lang/noir/commit/f2f827d51e6fe99fa3d17f125b22743da25e25be)) +* Add `nargo compile --watch` command ([#4464](https://github.com/noir-lang/noir/issues/4464)) ([44e60b6](https://github.com/noir-lang/noir/commit/44e60b67469de88f20842c4eead64d736f7bd4a0)) +* Add as_slice builtin function, add execution test ([#4523](https://github.com/noir-lang/noir/issues/4523)) ([6a9ea35](https://github.com/noir-lang/noir/commit/6a9ea35c4f1578058179aa08eedf44eb18bad4a1)) +* Add checks for bit size consistency on brillig gen ([#4542](https://github.com/noir-lang/noir/issues/4542)) ([f3243b7](https://github.com/noir-lang/noir/commit/f3243b763c0b15ae90beb8e35630df27f3d314c0)) +* Add CMOV instruction to brillig and brillig gen (https://github.com/AztecProtocol/aztec-packages/pull/5308) ([13eb71b](https://github.com/noir-lang/noir/commit/13eb71b8de44eb6aad9c37943ad06fc73db589f5)) +* Add experimental `quote` expression to parser ([#4595](https://github.com/noir-lang/noir/issues/4595)) ([4c3a30b](https://github.com/noir-lang/noir/commit/4c3a30b4991a329d3c52e1dfa59d854d7e6910db)) +* Add more impls on Option ([#4549](https://github.com/noir-lang/noir/issues/4549)) ([4cf700b](https://github.com/noir-lang/noir/commit/4cf700bcfe157ebc82cdf7321a16959b7a4add57)) +* Add specific error for attempting `string[x] = ".."` ([#4611](https://github.com/noir-lang/noir/issues/4611)) ([ff95fd9](https://github.com/noir-lang/noir/commit/ff95fd93451b2053360a16b7d3204ca251199296)) +* Allow usage of noir `#[test]` syntax in stdlib ([#4553](https://github.com/noir-lang/noir/issues/4553)) ([a8b7cdb](https://github.com/noir-lang/noir/commit/a8b7cdb8a3698bc8923b6fa8714deebb8bf3923f)) +* Automatic NoteInterface and NoteGetterOptions auto select (https://github.com/AztecProtocol/aztec-packages/pull/4508) ([13eb71b](https://github.com/noir-lang/noir/commit/13eb71b8de44eb6aad9c37943ad06fc73db589f5)) +* **avm:** Brillig CONST of size > u128 (https://github.com/AztecProtocol/aztec-packages/pull/5217) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* Brillig IR refactor (https://github.com/AztecProtocol/aztec-packages/pull/5233) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* Check initialization arguments in constructors (https://github.com/AztecProtocol/aztec-packages/pull/5144) ([d4213a0](https://github.com/noir-lang/noir/commit/d4213a03c9f77ee8e7663fc965a825258d90a368)) +* Check initializer msg.sender matches deployer from address preimage (https://github.com/AztecProtocol/aztec-packages/pull/5222) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* Initial Earthly CI (https://github.com/AztecProtocol/aztec-packages/pull/5069) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* Integrated native ACVM (https://github.com/AztecProtocol/aztec-packages/pull/4903) ([a6016b4](https://github.com/noir-lang/noir/commit/a6016b46abf6da6de4566cf6d35a675d805dd9b5)) +* Make brillig-gen more AVM-friendly (https://github.com/AztecProtocol/aztec-packages/pull/5091) ([a6016b4](https://github.com/noir-lang/noir/commit/a6016b46abf6da6de4566cf6d35a675d805dd9b5)) +* New brillig field operations and refactor of binary operations (https://github.com/AztecProtocol/aztec-packages/pull/5208) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* Optimize sha2 implementation ([#4441](https://github.com/noir-lang/noir/issues/4441)) ([80373d6](https://github.com/noir-lang/noir/commit/80373d612c023e3e165b49b6d1729486b0ba3b4b)) +* RC optimization pass ([#4560](https://github.com/noir-lang/noir/issues/4560)) ([dfa5126](https://github.com/noir-lang/noir/commit/dfa5126f2c65843c34701cacddf2cbcfb0d7ff11)) +* Remove curly braces with fmt ([#4529](https://github.com/noir-lang/noir/issues/4529)) ([fe9a437](https://github.com/noir-lang/noir/commit/fe9a437b6d7ddc3f78665df1a576236555880c51)) +* Separating out array and slice types in the AST ([#4504](https://github.com/noir-lang/noir/issues/4504)) ([9a241f9](https://github.com/noir-lang/noir/commit/9a241f9622b342cd9d56bf8481219cfc374c0510)) +* Signed integer division and modulus in brillig gen (https://github.com/AztecProtocol/aztec-packages/pull/5279) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* Support contracts with no constructor (https://github.com/AztecProtocol/aztec-packages/pull/5175) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/5234) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/5286) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* Visible aliases for nargo commands ([#4453](https://github.com/noir-lang/noir/issues/4453)) ([773cf19](https://github.com/noir-lang/noir/commit/773cf190ee21381d826ba80391a5d7d5efae9174)) + + +### Bug Fixes + +* **acir_gen:** More granular element sizes array check ([#4528](https://github.com/noir-lang/noir/issues/4528)) ([f93d16e](https://github.com/noir-lang/noir/commit/f93d16e3e89c5df358c982deae4f3c2d4c82b77f)) +* Added error messages for passing oracles and references from unconstrained to constrained functions ([#4570](https://github.com/noir-lang/noir/issues/4570)) ([265bd8b](https://github.com/noir-lang/noir/commit/265bd8b284e5acd572a3812a94a99fc102227ff2)) +* Allow non-integer globals to reference struct methods ([#4490](https://github.com/noir-lang/noir/issues/4490)) ([00d6494](https://github.com/noir-lang/noir/commit/00d6494ae70b10e1872d96fb4e57ecb0b5f01787)) +* Dynamic assert messages in brillig ([#4531](https://github.com/noir-lang/noir/issues/4531)) ([e24d3fc](https://github.com/noir-lang/noir/commit/e24d3fc5a084610d9511e3c5421275cb9c84a548)) +* Evaluate operators in globals in types ([#4537](https://github.com/noir-lang/noir/issues/4537)) ([c8aa16b](https://github.com/noir-lang/noir/commit/c8aa16bc7e78456cce1736fac82496996a8761f4)) +* Make `nargo` the default binary for cargo run ([#4554](https://github.com/noir-lang/noir/issues/4554)) ([de4986e](https://github.com/noir-lang/noir/commit/de4986eb74b28b2e1065fa6b413d02457ddf61b0)) +* Signed integer comparisons in brillig ([#4579](https://github.com/noir-lang/noir/issues/4579)) ([938d5e8](https://github.com/noir-lang/noir/commit/938d5e85eda00a05de5014e64d3dc9fc7c24936d)) +* **ssa:** Use accurate type during SSA AsSlice simplficiation ([#4610](https://github.com/noir-lang/noir/issues/4610)) ([0473497](https://github.com/noir-lang/noir/commit/04734976e92475b1ab94257e30bc3438c7358681)) +* Substitute generics when checking the field count of a type ([#4547](https://github.com/noir-lang/noir/issues/4547)) ([eeeebac](https://github.com/noir-lang/noir/commit/eeeebacd10698e847f773e26dac8a4a5eb8e84ed)) + + +### Miscellaneous Chores + +* Remove open keyword from Noir (https://github.com/AztecProtocol/aztec-packages/pull/4967) ([a6016b4](https://github.com/noir-lang/noir/commit/a6016b46abf6da6de4566cf6d35a675d805dd9b5)) + +## [0.25.0](https://github.com/noir-lang/noir/compare/v0.24.0...v0.25.0) (2024-03-11) + + +### ⚠ BREAKING CHANGES + +* Internal as a macro (https://github.com/AztecProtocol/aztec-packages/pull/4898) +* reserve `unchecked` keyword ([#4432](https://github.com/noir-lang/noir/issues/4432)) +* Remove empty value from bounded vec ([#4431](https://github.com/noir-lang/noir/issues/4431)) +* Ban Fields in for loop indices and bitwise ops ([#4376](https://github.com/noir-lang/noir/issues/4376)) +* Bump msrv to 1.73.0 ([#4406](https://github.com/noir-lang/noir/issues/4406)) +* **ci:** Bump MSRV to 1.72.1 and enforce that ACVM can be published using updated lockfile ([#4385](https://github.com/noir-lang/noir/issues/4385)) +* Restrict bit sizes ([#4235](https://github.com/noir-lang/noir/issues/4235)) +* move noir out of yarn-project (https://github.com/AztecProtocol/aztec-packages/pull/4479) +* note type ids (https://github.com/AztecProtocol/aztec-packages/pull/4500) + +### Features + +* Add eddsa_poseidon_to_pub function to stdlib with test + docs ([#4473](https://github.com/noir-lang/noir/issues/4473)) ([00d2c32](https://github.com/noir-lang/noir/commit/00d2c32e58176cc5de3574c8435a54d415c4a5fa)) +* Add HashMap to the stdlib ([#4242](https://github.com/noir-lang/noir/issues/4242)) ([650ffc5](https://github.com/noir-lang/noir/commit/650ffc5053cdca4b6ad2e027fa1f4fd90ef64871)) +* Add option to set max memory for bb.js ([#4227](https://github.com/noir-lang/noir/issues/4227)) ([8a6b131](https://github.com/noir-lang/noir/commit/8a6b131402892a570bc2de6f5869de73b0bd979e)) +* Add overflow and underflow checks for unsigned integers in brillig ([#4445](https://github.com/noir-lang/noir/issues/4445)) ([21fc4b8](https://github.com/noir-lang/noir/commit/21fc4b85763dccae6dce0a46a318718c3c913471)) +* Add poseidon2 opcode implementation for acvm/brillig, and Noir ([#4398](https://github.com/noir-lang/noir/issues/4398)) ([10e8292](https://github.com/noir-lang/noir/commit/10e82920798380f50046e52db4a20ca205191ab7)) +* Added cast opcode and cast calldata (https://github.com/AztecProtocol/aztec-packages/pull/4423) ([78ef013](https://github.com/noir-lang/noir/commit/78ef0134b82e76a73dadb6c7975def22290e3a1a)) +* Allow type aliases to reference other aliases ([#4353](https://github.com/noir-lang/noir/issues/4353)) ([c44ef14](https://github.com/noir-lang/noir/commit/c44ef14847a436733206b6dd9590a7ab214ecd97)) +* Backpropagate constants in ACIR during optimization ([#3926](https://github.com/noir-lang/noir/issues/3926)) ([aad0da0](https://github.com/noir-lang/noir/commit/aad0da024c69663f42e6913e674682d5864b26ae)) +* **ci:** Use wasm-opt when compiling wasm packages ([#4334](https://github.com/noir-lang/noir/issues/4334)) ([e382921](https://github.com/noir-lang/noir/commit/e3829213d8411f84e117a14b43816967925095e0)) +* DAP Preflight and debugger compilation options ([#4185](https://github.com/noir-lang/noir/issues/4185)) ([e0ad0b2](https://github.com/noir-lang/noir/commit/e0ad0b2b31f6d46be75d23aec6a82850a9c4bd75)) +* Expose separate functions to compile programs vs contracts in `noir_wasm` ([#4413](https://github.com/noir-lang/noir/issues/4413)) ([7cd5fdb](https://github.com/noir-lang/noir/commit/7cd5fdb3d2a53475b7c8681231d517cab30f9f9b)) +* Internal as a macro (https://github.com/AztecProtocol/aztec-packages/pull/4898) ([5f57ebb](https://github.com/noir-lang/noir/commit/5f57ebb7ff4b810802f90699a10f4325ef904f2e)) +* Note type ids (https://github.com/AztecProtocol/aztec-packages/pull/4500) ([78ef013](https://github.com/noir-lang/noir/commit/78ef0134b82e76a73dadb6c7975def22290e3a1a)) +* Restrict bit sizes ([#4235](https://github.com/noir-lang/noir/issues/4235)) ([1048f81](https://github.com/noir-lang/noir/commit/1048f815abb1f27e9c84ab5b9568a3673c12a50a)) +* Run tests in parallel in `nargo test` ([#4484](https://github.com/noir-lang/noir/issues/4484)) ([761734e](https://github.com/noir-lang/noir/commit/761734e6cb3ff5911aa85d0cee96ad26092b4905)) +* Skip redundant range checks in brillig ([#4460](https://github.com/noir-lang/noir/issues/4460)) ([cb4c1c5](https://github.com/noir-lang/noir/commit/cb4c1c5264b95d01f69d99f916ced71ad9cdc9d1)) +* Sync from aztec-packages ([#4483](https://github.com/noir-lang/noir/issues/4483)) ([fe8f277](https://github.com/noir-lang/noir/commit/fe8f2776ccfde29209a2c3fc162311c99e4f59be)) +* Track stack frames and their variables in the debugger ([#4188](https://github.com/noir-lang/noir/issues/4188)) ([ae1a9d9](https://github.com/noir-lang/noir/commit/ae1a9d923998177516919bbba6ff4b0584fa1e9f)) +* TypeVariableKind for just Integers ([#4118](https://github.com/noir-lang/noir/issues/4118)) ([c956be8](https://github.com/noir-lang/noir/commit/c956be870fb47403a6da6585fce6bea2d40ee268)) +* Update error message when trying to load workspace as dependency ([#4393](https://github.com/noir-lang/noir/issues/4393)) ([d2585e7](https://github.com/noir-lang/noir/commit/d2585e738a63208fca3c9e26242e896d7f1df1e4)) + + +### Bug Fixes + +* **acir:** Array dynamic flatten ([#4351](https://github.com/noir-lang/noir/issues/4351)) ([b2aaeab](https://github.com/noir-lang/noir/commit/b2aaeab319a0c66c431a7db6852f743eccde8e98)) +* **acir:** Use types on dynamic arrays ([#4364](https://github.com/noir-lang/noir/issues/4364)) ([ba2c541](https://github.com/noir-lang/noir/commit/ba2c541ec45de92bba98de34771b73cbb7865c93)) +* Add `follow_bindings` to follow `Type::Alias` links ([#4521](https://github.com/noir-lang/noir/issues/4521)) ([b94adb9](https://github.com/noir-lang/noir/commit/b94adb92657e2b4a51dc7216a88e080aed1cf8b0)) +* Add handling to `noir_wasm` for projects without dependencies ([#4344](https://github.com/noir-lang/noir/issues/4344)) ([4982251](https://github.com/noir-lang/noir/commit/49822511710a7f1c42b8ed343e80456f8e6db2d9)) +* Allow type aliases in main ([#4505](https://github.com/noir-lang/noir/issues/4505)) ([8a5359c](https://github.com/noir-lang/noir/commit/8a5359c012579e54c2766de1074482a36ecada32)) +* Ban Fields in for loop indices and bitwise ops ([#4376](https://github.com/noir-lang/noir/issues/4376)) ([601fd9a](https://github.com/noir-lang/noir/commit/601fd9afc502236af1db0c4492698ba2298c7501)) +* Brillig range check with consistent bit size ([#4357](https://github.com/noir-lang/noir/issues/4357)) ([ea47d4a](https://github.com/noir-lang/noir/commit/ea47d4a67c6a18e4a7d3a49079d9eb24a1026a25)) +* Build noir_codegen when publishing ([#4448](https://github.com/noir-lang/noir/issues/4448)) ([cb1ceee](https://github.com/noir-lang/noir/commit/cb1ceee58b11b0ce6f8845361af3418d13c506bd)) +* Consistent bit size for truncate ([#4370](https://github.com/noir-lang/noir/issues/4370)) ([dcd7a1e](https://github.com/noir-lang/noir/commit/dcd7a1e561a68504b9038ffbb3c80f5c981f9f0c)) +* Correct formatting for databus visibility types ([#4423](https://github.com/noir-lang/noir/issues/4423)) ([cd796de](https://github.com/noir-lang/noir/commit/cd796dea4937dd1a261f154e5f2e599bbc649165)) +* Correct invalid brillig codegen for `EmbeddedCurvePoint.add` ([#4382](https://github.com/noir-lang/noir/issues/4382)) ([5051ec4](https://github.com/noir-lang/noir/commit/5051ec4d434a9e5cf405c68357faaf213e68de9e)) +* **docs:** Update install versions ([#4396](https://github.com/noir-lang/noir/issues/4396)) ([b283637](https://github.com/noir-lang/noir/commit/b283637e092038eb296c468168aec2d41e1c2734)) +* **docs:** Update noirjs_app for 0.23 ([#4378](https://github.com/noir-lang/noir/issues/4378)) ([f77f702](https://github.com/noir-lang/noir/commit/f77f702e0cfb81dcce4dd97e274b831e887ba5d2)) +* Enforce matching types of binary ops in SSA ([#4391](https://github.com/noir-lang/noir/issues/4391)) ([70866ae](https://github.com/noir-lang/noir/commit/70866aea976d59dbcbd4af34067fdd8f46555673)) +* Fix brillig slowdown when assigning arrays in loops ([#4472](https://github.com/noir-lang/noir/issues/4472)) ([2a53545](https://github.com/noir-lang/noir/commit/2a53545f4238c9b8535e6bc5b0720fa15f44f946)) +* **flake:** Stop flake.nix removing ignored-tests.txt ([#4455](https://github.com/noir-lang/noir/issues/4455)) ([ebaf05a](https://github.com/noir-lang/noir/commit/ebaf05ab10834dd10e04c7ea5130f96c6cdf98ed)) +* Force src impl for == on slices ([#4507](https://github.com/noir-lang/noir/issues/4507)) ([1691274](https://github.com/noir-lang/noir/commit/169127444e8b16a8aad4acfe29ba812894fd897c)) +* Handling of gh deps in noir_wasm ([#4499](https://github.com/noir-lang/noir/issues/4499)) ([1d65370](https://github.com/noir-lang/noir/commit/1d653704715bf9999eb6a40ed7500e752e2c73b7)) +* Iterative flattening pass ([#4492](https://github.com/noir-lang/noir/issues/4492)) ([33c1ef7](https://github.com/noir-lang/noir/commit/33c1ef70e7859fdee7babfb5d38191f53e73a0df)) +* Noir test incorrect reporting (https://github.com/AztecProtocol/aztec-packages/pull/4925) ([5f57ebb](https://github.com/noir-lang/noir/commit/5f57ebb7ff4b810802f90699a10f4325ef904f2e)) +* Only add `.nr` files to file manager ([#4380](https://github.com/noir-lang/noir/issues/4380)) ([8536c7c](https://github.com/noir-lang/noir/commit/8536c7c8ea8fc6b740b2ae6d1aef3bc7e1907b8c)) +* Remove panic when generic array length is not resolvable ([#4408](https://github.com/noir-lang/noir/issues/4408)) ([00ab3db](https://github.com/noir-lang/noir/commit/00ab3db86b06111d144516e862902b8604284611)) +* Remove print from monomorphization pass ([#4417](https://github.com/noir-lang/noir/issues/4417)) ([27c66b3](https://github.com/noir-lang/noir/commit/27c66b3d0741e68ed591ae8a16b47b30bc87175f)) +* **ssa:** Handle mergers of slices returned from calls ([#4496](https://github.com/noir-lang/noir/issues/4496)) ([f988d02](https://github.com/noir-lang/noir/commit/f988d020e43cdf36a38613f2052d4518de39193a)) +* Use correct type for numeric generics ([#4386](https://github.com/noir-lang/noir/issues/4386)) ([0a1d109](https://github.com/noir-lang/noir/commit/0a1d109f478c997da5c43876fd12464af638bb15)) +* Variables from trait constraints being permanently bound over when used within a trait impl ([#4450](https://github.com/noir-lang/noir/issues/4450)) ([ac60ef5](https://github.com/noir-lang/noir/commit/ac60ef5e12fcfb907fbdcff709d7cbad05f2b939)) + + +### Miscellaneous Chores + +* Bump msrv to 1.73.0 ([#4406](https://github.com/noir-lang/noir/issues/4406)) ([b5e5c30](https://github.com/noir-lang/noir/commit/b5e5c30f4db52c79ef556e80660f39db369b1911)) +* **ci:** Bump MSRV to 1.72.1 and enforce that ACVM can be published using updated lockfile ([#4385](https://github.com/noir-lang/noir/issues/4385)) ([2fc95d2](https://github.com/noir-lang/noir/commit/2fc95d2d82b3220267ce7d5815e7073e00ef1360)) +* Move noir out of yarn-project (https://github.com/AztecProtocol/aztec-packages/pull/4479) ([78ef013](https://github.com/noir-lang/noir/commit/78ef0134b82e76a73dadb6c7975def22290e3a1a)) +* Remove empty value from bounded vec ([#4431](https://github.com/noir-lang/noir/issues/4431)) ([b9384fb](https://github.com/noir-lang/noir/commit/b9384fb23abf4ab15e880fb7e03c21509a9fa8a6)) +* Reserve `unchecked` keyword ([#4432](https://github.com/noir-lang/noir/issues/4432)) ([9544813](https://github.com/noir-lang/noir/commit/9544813fabbd18a87dd88456e6a5b781bd0cf008)) + ## [0.24.0](https://github.com/noir-lang/noir/compare/v0.23.0...v0.24.0) (2024-02-12) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d2553b003f8..c02d24e91b8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -196,7 +196,7 @@ 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. -You can then open a Pull Request according to the the [PR section](#pull-requests) +You can then open a Pull Request according to the [PR section](#pull-requests) ## Changelog diff --git a/Cargo.lock b/Cargo.lock index c0438eaf81f..61bfdd08c0e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,15 +4,18 @@ version = 3 [[package]] name = "acir" -version = "0.40.0" +version = "0.46.0" dependencies = [ "acir_field", "base64 0.21.2", "bincode", "brillig", + "criterion", "flate2", "fxhash", + "pprof 0.13.0", "serde", + "serde-big-array", "serde-generate", "serde-reflection", "serde_json", @@ -23,7 +26,7 @@ dependencies = [ [[package]] name = "acir_field" -version = "0.40.0" +version = "0.46.0" dependencies = [ "ark-bls12-381", "ark-bn254", @@ -31,16 +34,16 @@ dependencies = [ "cfg-if 1.0.0", "hex", "num-bigint", - "num-traits", "serde", ] [[package]] name = "acvm" -version = "0.40.0" +version = "0.46.0" dependencies = [ "acir", "acvm_blackbox_solver", + "ark-bls12-381", "brillig_vm", "indexmap 1.9.3", "num-bigint", @@ -53,13 +56,15 @@ dependencies = [ [[package]] name = "acvm_blackbox_solver" -version = "0.40.0" +version = "0.46.0" dependencies = [ "acir", "blake2", "blake3", "k256", "keccak", + "libaes", + "num-bigint", "p256", "sha2", "sha3", @@ -67,15 +72,35 @@ dependencies = [ ] [[package]] -name = "acvm_js" +name = "acvm_cli" version = "0.40.0" +dependencies = [ + "acir", + "acvm", + "bn254_blackbox_solver", + "clap", + "color-eyre", + "const_format", + "nargo", + "paste", + "proptest", + "rand 0.8.5", + "thiserror", + "toml 0.7.6", + "tracing-appender", + "tracing-subscriber", +] + +[[package]] +name = "acvm_js" +version = "0.46.0" dependencies = [ "acvm", "bn254_blackbox_solver", "build-data", - "cfg-if 1.0.0", "console_error_panic_hook", "const-str", + "getrandom 0.2.15", "gloo-utils", "js-sys", "pkg-config", @@ -93,7 +118,7 @@ version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" dependencies = [ - "gimli 0.27.3", + "gimli", ] [[package]] @@ -104,23 +129,23 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "ahash" -version = "0.7.7" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a824f2aa7e75a0c98c5a504fceb80649e9c35265d44525b5f94de4771a395cd" +checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" dependencies = [ - "getrandom 0.2.10", + "getrandom 0.2.15", "once_cell", "version_check", ] [[package]] name = "ahash" -version = "0.8.6" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ "cfg-if 1.0.0", - "getrandom 0.2.10", + "getrandom 0.2.15", "once_cell", "version_check", "zerocopy", @@ -210,10 +235,6 @@ version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" -[[package]] -name = "arena" -version = "0.24.0" - [[package]] name = "ark-bls12-381" version = "0.4.0" @@ -249,7 +270,7 @@ dependencies = [ "ark-std", "derivative", "hashbrown 0.13.2", - "itertools", + "itertools 0.10.5", "num-traits", "zeroize", ] @@ -266,7 +287,7 @@ dependencies = [ "ark-std", "derivative", "digest", - "itertools", + "itertools 0.10.5", "num-bigint", "num-traits", "paste", @@ -355,6 +376,15 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +[[package]] +name = "ascii-canvas" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8824ecca2e851cec16968d54a01dd372ef8f95b244fb84b84e70128be347c3c6" +dependencies = [ + "term", +] + [[package]] name = "assert_cmd" version = "2.0.12" @@ -391,7 +421,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "138985dd8aefbefeaa66b01b7f5b2b6b4c333fcef1cc5f32c63a2aabe37d6de3" dependencies = [ - "futures 0.3.28", + "futures 0.3.30", "lsp-types 0.94.1", "pin-project-lite", "rustix", @@ -413,32 +443,14 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "aztec_macros" -version = "0.24.0" +version = "0.30.0" dependencies = [ + "acvm", "convert_case 0.6.0", "iter-extended", "noirc_errors", "noirc_frontend", -] - -[[package]] -name = "backend-interface" -version = "0.11.0" -dependencies = [ - "acvm", - "bb_abstraction_leaks", - "build-target", - "const_format", - "dirs", - "flate2", - "reqwest", - "serde", - "serde_json", - "tar", - "tempfile", - "test-binary", - "thiserror", - "tracing", + "regex", ] [[package]] @@ -480,15 +492,6 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" -[[package]] -name = "bb_abstraction_leaks" -version = "0.11.0" -dependencies = [ - "acvm", - "build-target", - "const_format", -] - [[package]] name = "bincode" version = "1.3.3" @@ -521,9 +524,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.3.3" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" [[package]] name = "bitmaps" @@ -534,18 +537,6 @@ dependencies = [ "typenum", ] -[[package]] -name = "bitvec" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" -dependencies = [ - "funty", - "radium", - "tap", - "wyz", -] - [[package]] name = "blake2" version = "0.10.6" @@ -579,30 +570,24 @@ dependencies = [ [[package]] name = "bn254_blackbox_solver" -version = "0.39.0" +version = "0.46.0" dependencies = [ "acir", "acvm_blackbox_solver", "ark-ec", "ark-ff", - "flate2", - "getrandom 0.2.10", - "js-sys", + "ark-std", + "criterion", + "hex", + "lazy_static", "noir_grumpkin", "num-bigint", - "num-traits", - "pkg-config", - "reqwest", - "rust-embed", - "tar", - "thiserror", - "wasm-bindgen-futures", - "wasmer", + "pprof 0.12.1", ] [[package]] name = "brillig" -version = "0.40.0" +version = "0.46.0" dependencies = [ "acir_field", "serde", @@ -610,12 +595,13 @@ dependencies = [ [[package]] name = "brillig_vm" -version = "0.40.0" +version = "0.46.0" dependencies = [ "acir", "acvm_blackbox_solver", "num-bigint", "num-traits", + "thiserror", ] [[package]] @@ -651,40 +637,12 @@ dependencies = [ "safe-regex", ] -[[package]] -name = "build-target" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "832133bbabbbaa9fbdba793456a2827627a7d2b8fb96032fa1e7666d7895832b" - [[package]] name = "bumpalo" version = "3.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" -[[package]] -name = "bytecheck" -version = "0.6.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6372023ac861f6e6dc89c8344a8f398fb42aaba2b5dbc649ca0c0e9dbcb627" -dependencies = [ - "bytecheck_derive", - "ptr_meta", - "simdutf8", -] - -[[package]] -name = "bytecheck_derive" -version = "0.6.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7ec4c6f261935ad534c0c22dbef2201b45918860eb1c574b972bd213a76af61" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "bytecount" version = "0.6.3" @@ -749,9 +707,12 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.0.79" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] [[package]] name = "cfg-if" @@ -767,9 +728,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.30" +version = "0.4.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "defd4e7873dbddba6c7c91e199c7fcb946abc4a6a4ac3195400bcfb01b5de877" +checksum = "8a0d04d43504c61aa6c7531f1871dd0d418d91130162063b789da00fd7057a5e" dependencies = [ "android-tzdata", "iana-time-zone", @@ -777,7 +738,7 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-targets 0.48.1", + "windows-targets 0.52.4", ] [[package]] @@ -817,9 +778,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.7" +version = "4.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac495e00dcec98c83465d5ad66c5c4fabd652fd6686e7c6269b117e729a6f17b" +checksum = "bfaff671f6b22ca62406885ece523383b9b64022e341e53e009a62ebc47a45f2" dependencies = [ "clap_builder", "clap_derive", @@ -835,9 +796,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.7" +version = "4.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c77ed9a32a62e6ca27175d00d29d05ca32e396ea1eb5fb01d8256b669cec7663" +checksum = "a216b506622bb1d316cd51328dce24e07bdff4a6128a47c7e7fad11878d5adbb" dependencies = [ "anstream", "anstyle", @@ -854,7 +815,7 @@ dependencies = [ "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.64", ] [[package]] @@ -892,7 +853,7 @@ checksum = "fc4159b76af02757139baf42c0c971c6dc155330999fbfd8eddb29b97fb2db68" dependencies = [ "codespan-reporting", "lsp-types 0.88.0", - "url 2.4.0", + "url 2.5.0", ] [[package]] @@ -947,14 +908,14 @@ checksum = "55b672471b4e9f9e95499ea597ff64941a309b2cdbffcc46f2cc5e2d971fd335" [[package]] name = "console" -version = "0.15.7" +version = "0.15.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8" +checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb" dependencies = [ "encode_unicode 0.3.6", "lazy_static", "libc", - "windows-sys 0.45.0", + "windows-sys 0.52.0", ] [[package]] @@ -1022,22 +983,9 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" - -[[package]] -name = "corosensei" -version = "0.1.4" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80128832c58ea9cbd041d2a759ec449224487b2c1e400453d99d244eead87a8e" -dependencies = [ - "autocfg", - "cfg-if 1.0.0", - "libc", - "scopeguard", - "windows-sys 0.33.0", -] +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "cpp_demangle" @@ -1057,89 +1005,6 @@ dependencies = [ "libc", ] -[[package]] -name = "cranelift-bforest" -version = "0.91.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a2ab4512dfd3a6f4be184403a195f76e81a8a9f9e6c898e19d2dc3ce20e0115" -dependencies = [ - "cranelift-entity", -] - -[[package]] -name = "cranelift-codegen" -version = "0.91.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98b022ed2a5913a38839dfbafe6cf135342661293b08049843362df4301261dc" -dependencies = [ - "arrayvec", - "bumpalo", - "cranelift-bforest", - "cranelift-codegen-meta", - "cranelift-codegen-shared", - "cranelift-egraph", - "cranelift-entity", - "cranelift-isle", - "gimli 0.26.2", - "log", - "regalloc2", - "smallvec", - "target-lexicon", -] - -[[package]] -name = "cranelift-codegen-meta" -version = "0.91.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "639307b45434ad112a98f8300c0f0ab085cbefcd767efcdef9ef19d4c0756e74" -dependencies = [ - "cranelift-codegen-shared", -] - -[[package]] -name = "cranelift-codegen-shared" -version = "0.91.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "278e52e29c53fcf32431ef08406c295699a70306d05a0715c5b1bf50e33a9ab7" - -[[package]] -name = "cranelift-egraph" -version = "0.91.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624b54323b06e675293939311943ba82d323bb340468ce1889be5da7932c8d73" -dependencies = [ - "cranelift-entity", - "fxhash", - "hashbrown 0.12.3", - "indexmap 1.9.3", - "log", - "smallvec", -] - -[[package]] -name = "cranelift-entity" -version = "0.91.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a59bcbca89c3f1b70b93ab3cbba5e5e0cbf3e63dadb23c7525cb142e21a9d4c" - -[[package]] -name = "cranelift-frontend" -version = "0.91.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d70abacb8cfef3dc8ff7e8836e9c1d70f7967dfdac824a4cd5e30223415aca6" -dependencies = [ - "cranelift-codegen", - "log", - "smallvec", - "target-lexicon", -] - -[[package]] -name = "cranelift-isle" -version = "0.91.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "393bc73c451830ff8dbb3a07f61843d6cb41a084f9996319917c0b291ed785bb" - [[package]] name = "crc32fast" version = "1.3.2" @@ -1161,7 +1026,7 @@ dependencies = [ "clap", "criterion-plot", "is-terminal", - "itertools", + "itertools 0.10.5", "num-traits", "once_cell", "oorandom", @@ -1182,7 +1047,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" dependencies = [ "cast", - "itertools", + "itertools 0.10.5", ] [[package]] @@ -1220,23 +1085,16 @@ dependencies = [ ] [[package]] -name = "crossbeam-queue" -version = "0.3.8" +name = "crossbeam-utils" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add" -dependencies = [ - "cfg-if 1.0.0", - "crossbeam-utils", -] +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" [[package]] -name = "crossbeam-utils" -version = "0.8.17" +name = "crunchy" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d96137f14f244c37f989d9fff8f95e6c18b918e71f36638f8c49112e4c78f" -dependencies = [ - "cfg-if 1.0.0", -] +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] name = "crypto-bigint" @@ -1313,7 +1171,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.32", + "syn 2.0.64", ] [[package]] @@ -1324,20 +1182,7 @@ checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" dependencies = [ "darling_core", "quote", - "syn 2.0.32", -] - -[[package]] -name = "dashmap" -version = "5.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" -dependencies = [ - "cfg-if 1.0.0", - "hashbrown 0.14.0", - "lock_api", - "once_cell", - "parking_lot_core 0.9.8", + "syn 2.0.64", ] [[package]] @@ -1509,6 +1354,15 @@ dependencies = [ "zeroize", ] +[[package]] +name = "ena" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c533630cf40e9caa44bd91aadc88a75d75a4c3a12b4cfde353cbed41daa1e1f1" +dependencies = [ + "log", +] + [[package]] name = "encode_unicode" version = "0.3.6" @@ -1521,62 +1375,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" -[[package]] -name = "encoding_rs" -version = "0.8.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" -dependencies = [ - "cfg-if 1.0.0", -] - [[package]] name = "endian-type" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" -[[package]] -name = "enum-iterator" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eeac5c5edb79e4e39fe8439ef35207780a11f69c52cbe424ce3dfad4cb78de6" -dependencies = [ - "enum-iterator-derive", -] - -[[package]] -name = "enum-iterator-derive" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c134c37760b27a871ba422106eedbb8247da973a09e82558bf26d619c882b159" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "enumset" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e875f1719c16de097dee81ed675e2d9bb63096823ed3f0ca827b7dea3028bbbb" -dependencies = [ - "enumset_derive", -] - -[[package]] -name = "enumset_derive" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08b6c6ab82d70f08844964ba10c7babb716de2ecaeab9be5717918a5177d3af" -dependencies = [ - "darling", - "proc-macro2", - "quote", - "syn 2.0.32", -] - [[package]] name = "equivalent" version = "1.0.1" @@ -1613,12 +1417,6 @@ dependencies = [ "once_cell", ] -[[package]] -name = "fallible-iterator" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" - [[package]] name = "fastrand" version = "2.0.1" @@ -1655,6 +1453,15 @@ dependencies = [ "rayon", ] +[[package]] +name = "file-id" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6584280525fb2059cba3db2c04abf947a1a29a45ddae89f3870f8281704fafc9" +dependencies = [ + "windows-sys 0.48.0", +] + [[package]] name = "filetime" version = "0.2.22" @@ -1706,7 +1513,7 @@ dependencies = [ [[package]] name = "fm" -version = "0.24.0" +version = "0.30.0" dependencies = [ "codespan-reporting", "iter-extended", @@ -1722,18 +1529,21 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "form_urlencoded" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ - "percent-encoding 2.3.0", + "percent-encoding 2.3.1", ] [[package]] -name = "funty" -version = "2.0.0" +name = "fsevent-sys" +version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" +checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2" +dependencies = [ + "libc", +] [[package]] name = "futures" @@ -1743,9 +1553,9 @@ checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678" [[package]] name = "futures" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" dependencies = [ "futures-channel", "futures-core", @@ -1758,9 +1568,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" dependencies = [ "futures-core", "futures-sink", @@ -1768,15 +1578,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" [[package]] name = "futures-executor" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" dependencies = [ "futures-core", "futures-task", @@ -1786,38 +1596,38 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" [[package]] name = "futures-macro" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.64", ] [[package]] name = "futures-sink" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" [[package]] name = "futures-task" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" [[package]] name = "futures-util" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ "futures 0.1.31", "futures-channel", @@ -1864,9 +1674,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.10" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -1877,18 +1687,7 @@ dependencies = [ [[package]] name = "gimli" -version = "0.26.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" -dependencies = [ - "fallible-iterator", - "indexmap 1.9.3", - "stable_deref_trait", -] - -[[package]] -name = "gimli" -version = "0.27.3" +version = "0.27.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" @@ -1946,25 +1745,6 @@ dependencies = [ "subtle", ] -[[package]] -name = "h2" -version = "0.3.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb2c4422095b67ee78da96fbb51a4cc413b3b25883c7717ff7ca1ab31022c9c9" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http", - "indexmap 2.0.0", - "slab", - "tokio", - "tokio-util 0.7.8", - "tracing", -] - [[package]] name = "half" version = "1.8.2" @@ -1977,7 +1757,7 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" dependencies = [ - "ahash 0.7.7", + "ahash 0.7.8", ] [[package]] @@ -1985,9 +1765,6 @@ name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" -dependencies = [ - "ahash 0.7.7", -] [[package]] name = "hashbrown" @@ -1995,14 +1772,14 @@ version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" dependencies = [ - "ahash 0.8.6", + "ahash 0.8.11", ] [[package]] name = "hashbrown" -version = "0.14.0" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" [[package]] name = "heck" @@ -2076,42 +1853,27 @@ checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" [[package]] name = "hyper" -version = "0.14.27" +version = "0.14.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" +checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" dependencies = [ "bytes", "futures-channel", "futures-core", "futures-util", - "h2", "http", "http-body", "httparse", "httpdate", "itoa", "pin-project-lite", - "socket2 0.4.9", + "socket2", "tokio", "tower-service", "tracing", "want", ] -[[package]] -name = "hyper-rustls" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d78e1e73ec14cf7375674f74d7dde185c8206fd9dea6fb6295e8a98098aaa97" -dependencies = [ - "futures-util", - "http", - "hyper", - "rustls", - "tokio", - "tokio-rustls", -] - [[package]] name = "iai" version = "0.1.1" @@ -2160,9 +1922,9 @@ dependencies = [ [[package]] name = "idna" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ "unicode-bidi", "unicode-normalization", @@ -2243,12 +2005,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.0.0" +version = "2.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", - "hashbrown 0.14.0", + "hashbrown 0.14.5", "serde", ] @@ -2258,7 +2020,7 @@ version = "0.11.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2fb7c1b80a1dfa604bb4a649a5c5aeef3d913f7c520cb42b40e534e8a61bcdfc" dependencies = [ - "ahash 0.8.6", + "ahash 0.8.11", "indexmap 1.9.3", "is-terminal", "itoa", @@ -2270,6 +2032,26 @@ dependencies = [ "str_stack", ] +[[package]] +name = "inotify" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff" +dependencies = [ + "bitflags 1.3.2", + "inotify-sys", + "libc", +] + +[[package]] +name = "inotify-sys" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" +dependencies = [ + "libc", +] + [[package]] name = "instant" version = "0.1.12" @@ -2279,12 +2061,6 @@ dependencies = [ "cfg-if 1.0.0", ] -[[package]] -name = "ipnet" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6" - [[package]] name = "is-terminal" version = "0.4.9" @@ -2298,7 +2074,7 @@ dependencies = [ [[package]] name = "iter-extended" -version = "0.24.0" +version = "0.30.0" [[package]] name = "itertools" @@ -2309,6 +2085,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.9" @@ -2343,7 +2128,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2b99d4207e2a04fb4581746903c2bb7eb376f88de9c699d0f3e10feeac0cd3a" dependencies = [ "derive_more", - "futures 0.3.28", + "futures 0.3.30", "jsonrpc-core", "jsonrpc-pubsub", "log", @@ -2358,7 +2143,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14f7f76aef2d054868398427f6c54943cf3d1caa9a7ec7d0c38d69df97a965eb" dependencies = [ - "futures 0.3.28", + "futures 0.3.30", "futures-executor", "futures-util", "log", @@ -2373,7 +2158,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b51da17abecbdab3e3d4f26b01c5ec075e88d3abe3ab3b05dc9aa69392764ec0" dependencies = [ - "futures 0.3.28", + "futures 0.3.30", "jsonrpc-client-transports", ] @@ -2395,7 +2180,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1dea6e07251d9ce6a552abfb5d7ad6bc290a4596c8dcc3d795fae2bbdc1f3ff" dependencies = [ - "futures 0.3.28", + "futures 0.3.30", "hyper", "jsonrpc-core", "jsonrpc-server-utils", @@ -2411,7 +2196,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240f87695e6c6f62fb37f05c02c04953cf68d6408b8c1c89de85c7a0125b1011" dependencies = [ - "futures 0.3.28", + "futures 0.3.30", "jsonrpc-core", "lazy_static", "log", @@ -2427,7 +2212,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa4fdea130485b572c39a460d50888beb00afb3e35de23ccd7fad8ff19f0e0d4" dependencies = [ "bytes", - "futures 0.3.28", + "futures 0.3.30", "globset", "jsonrpc-core", "lazy_static", @@ -2459,6 +2244,57 @@ dependencies = [ "cpufeatures", ] +[[package]] +name = "kqueue" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7447f1ca1b7b563588a205fe93dea8df60fd981423a768bc1c0ded35ed147d0c" +dependencies = [ + "kqueue-sys", + "libc", +] + +[[package]] +name = "kqueue-sys" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b" +dependencies = [ + "bitflags 1.3.2", + "libc", +] + +[[package]] +name = "lalrpop" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55cb077ad656299f160924eb2912aa147d7339ea7d69e1b5517326fdcec3c1ca" +dependencies = [ + "ascii-canvas", + "bit-set", + "ena", + "itertools 0.11.0", + "lalrpop-util", + "petgraph", + "pico-args", + "regex", + "regex-syntax 0.8.2", + "string_cache", + "term", + "tiny-keccak", + "unicode-xid", + "walkdir", +] + +[[package]] +name = "lalrpop-util" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "507460a910eb7b32ee961886ff48539633b788a36b65692b95f225b844c82553" +dependencies = [ + "regex-automata 0.4.5", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -2466,16 +2302,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] -name = "leb128" -version = "0.2.5" +name = "libaes" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" +checksum = "82903360c009b816f5ab72a9b68158c27c301ee2c3f20655b55c5e589e7d3bb7" [[package]] name = "libc" -version = "0.2.151" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "libm" @@ -2483,6 +2319,17 @@ version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4" +[[package]] +name = "libredox" +version = "0.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3af92c55d7d839293953fcd0fda5ecfe93297cfde6ffbdec13b41d99c0ba6607" +dependencies = [ + "bitflags 2.5.0", + "libc", + "redox_syscall 0.4.1", +] + [[package]] name = "linux-raw-sys" version = "0.4.3" @@ -2524,7 +2371,7 @@ dependencies = [ "serde", "serde_json", "serde_repr", - "url 2.4.0", + "url 2.5.0", ] [[package]] @@ -2537,16 +2384,7 @@ dependencies = [ "serde", "serde_json", "serde_repr", - "url 2.4.0", -] - -[[package]] -name = "mach" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa" -dependencies = [ - "libc", + "url 2.5.0", ] [[package]] @@ -2566,9 +2404,9 @@ checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" [[package]] name = "memchr" -version = "2.5.0" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" [[package]] name = "memmap2" @@ -2579,15 +2417,6 @@ 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" @@ -2606,12 +2435,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "mime" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" - [[package]] name = "miniz_oxide" version = "0.7.1" @@ -2634,24 +2457,19 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.10" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", + "log", "wasi 0.11.0+wasi-snapshot-preview1", "windows-sys 0.48.0", ] -[[package]] -name = "more-asserts" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7843ec2de400bcbc6a6328c958dc38e5359da6e93e72e37bc5246bf1ae776389" - [[package]] name = "nargo" -version = "0.24.0" +version = "0.30.0" dependencies = [ "acvm", "codespan-reporting", @@ -2665,11 +2483,9 @@ dependencies = [ "noirc_abi", "noirc_driver", "noirc_errors", - "noirc_evaluator", "noirc_frontend", "noirc_printable_type", "rayon", - "rustc_version", "serde", "tempfile", "thiserror", @@ -2678,13 +2494,12 @@ dependencies = [ [[package]] name = "nargo_cli" -version = "0.24.0" +version = "0.30.0" dependencies = [ "acvm", "assert_cmd", "assert_fs", "async-lsp", - "backend-interface", "bn254_blackbox_solver", "build-data", "clap", @@ -2695,7 +2510,6 @@ dependencies = [ "dap", "dirs", "fm", - "hex", "iai", "iter-extended", "nargo", @@ -2707,21 +2521,23 @@ dependencies = [ "noirc_driver", "noirc_errors", "noirc_frontend", + "notify", + "notify-debouncer-full", "paste", - "pprof", + "pprof 0.13.0", "predicates 2.1.5", "prettytable-rs", "rayon", - "rustc_version", "serde", "serde_json", "similar-asserts", "tempfile", "termcolor", + "termion", "test-binary", "thiserror", "tokio", - "tokio-util 0.7.8", + "tokio-util 0.7.10", "toml 0.7.6", "tower", "tracing-appender", @@ -2730,7 +2546,7 @@ dependencies = [ [[package]] name = "nargo_fmt" -version = "0.24.0" +version = "0.30.0" dependencies = [ "bytecount", "noirc_frontend", @@ -2742,7 +2558,7 @@ dependencies = [ [[package]] name = "nargo_toml" -version = "0.24.0" +version = "0.30.0" dependencies = [ "dirs", "fm", @@ -2752,7 +2568,7 @@ dependencies = [ "serde", "thiserror", "toml 0.7.6", - "url 2.4.0", + "url 2.5.0", ] [[package]] @@ -2766,6 +2582,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + [[package]] name = "nibble_vec" version = "0.1.0" @@ -2815,7 +2637,7 @@ dependencies = [ [[package]] name = "noir_debugger" -version = "0.24.0" +version = "0.30.0" dependencies = [ "acvm", "assert_cmd", @@ -2850,7 +2672,7 @@ dependencies = [ [[package]] name = "noir_lsp" -version = "0.24.0" +version = "0.30.0" dependencies = [ "acvm", "async-lsp", @@ -2876,13 +2698,13 @@ dependencies = [ [[package]] name = "noir_wasm" -version = "0.24.0" +version = "0.30.0" dependencies = [ "acvm", "build-data", "console_error_panic_hook", "fm", - "getrandom 0.2.10", + "getrandom 0.2.15", "gloo-utils", "js-sys", "nargo", @@ -2899,11 +2721,12 @@ dependencies = [ [[package]] name = "noirc_abi" -version = "0.24.0" +version = "0.30.0" dependencies = [ "acvm", "iter-extended", "noirc_frontend", + "noirc_printable_type", "num-bigint", "num-traits", "serde", @@ -2916,12 +2739,12 @@ dependencies = [ [[package]] name = "noirc_abi_wasm" -version = "0.24.0" +version = "0.30.0" dependencies = [ "acvm", "build-data", "console_error_panic_hook", - "getrandom 0.2.10", + "getrandom 0.2.15", "gloo-utils", "iter-extended", "js-sys", @@ -2931,9 +2754,13 @@ dependencies = [ "wasm-bindgen-test", ] +[[package]] +name = "noirc_arena" +version = "0.30.0" + [[package]] name = "noirc_driver" -version = "0.24.0" +version = "0.30.0" dependencies = [ "acvm", "aztec_macros", @@ -2946,16 +2773,14 @@ dependencies = [ "noirc_errors", "noirc_evaluator", "noirc_frontend", - "noirc_macros", "rust-embed", "serde", - "thiserror", "tracing", ] [[package]] name = "noirc_errors" -version = "0.24.0" +version = "0.30.0" dependencies = [ "acvm", "base64 0.21.2", @@ -2973,9 +2798,10 @@ dependencies = [ [[package]] name = "noirc_evaluator" -version = "0.24.0" +version = "0.30.0" dependencies = [ "acvm", + "chrono", "fxhash", "im", "iter-extended", @@ -2989,15 +2815,22 @@ dependencies = [ [[package]] name = "noirc_frontend" -version = "0.24.0" +version = "0.30.0" dependencies = [ "acvm", - "arena", + "base64 0.21.2", + "cfg-if 1.0.0", "chumsky", "fm", + "im", "iter-extended", + "lalrpop", + "lalrpop-util", + "noirc_arena", "noirc_errors", "noirc_printable_type", + "num-bigint", + "num-traits", "petgraph", "regex", "rustc-hash", @@ -3012,17 +2845,9 @@ dependencies = [ "tracing", ] -[[package]] -name = "noirc_macros" -version = "0.24.0" -dependencies = [ - "iter-extended", - "noirc_frontend", -] - [[package]] name = "noirc_printable_type" -version = "0.24.0" +version = "0.30.0" dependencies = [ "acvm", "iter-extended", @@ -3039,6 +2864,39 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" +[[package]] +name = "notify" +version = "6.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d" +dependencies = [ + "bitflags 2.5.0", + "crossbeam-channel", + "filetime", + "fsevent-sys", + "inotify", + "kqueue", + "libc", + "log", + "mio", + "walkdir", + "windows-sys 0.48.0", +] + +[[package]] +name = "notify-debouncer-full" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f5dab59c348b9b50cf7f261960a20e389feb2713636399cd9082cd4b536154" +dependencies = [ + "crossbeam-channel", + "file-id", + "log", + "notify", + "parking_lot 0.12.1", + "walkdir", +] + [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -3100,6 +2958,12 @@ dependencies = [ "libc", ] +[[package]] +name = "numtoa" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef" + [[package]] name = "object" version = "0.31.1" @@ -3206,9 +3070,9 @@ checksum = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" [[package]] name = "percent-encoding" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "petgraph" @@ -3217,7 +3081,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" dependencies = [ "fixedbitset", - "indexmap 2.0.0", + "indexmap 2.2.6", ] [[package]] @@ -3264,6 +3128,12 @@ dependencies = [ "siphasher", ] +[[package]] +name = "pico-args" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" + [[package]] name = "pin-project-lite" version = "0.2.13" @@ -3342,12 +3212,40 @@ dependencies = [ "thiserror", ] +[[package]] +name = "pprof" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef5c97c51bd34c7e742402e216abdeb44d415fbe6ae41d56b114723e953711cb" +dependencies = [ + "backtrace", + "cfg-if 1.0.0", + "criterion", + "findshlibs", + "inferno", + "libc", + "log", + "nix 0.26.4", + "once_cell", + "parking_lot 0.12.1", + "smallvec", + "symbolic-demangle", + "tempfile", + "thiserror", +] + [[package]] name = "ppv-lite86" version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + [[package]] name = "predicates" version = "2.1.5" @@ -3356,7 +3254,7 @@ checksum = "59230a63c37f3e18569bdb90e4a89cbf5bf8b06fea0b84e65ea10cc4df47addd" dependencies = [ "difflib", "float-cmp", - "itertools", + "itertools 0.10.5", "normalize-line-endings", "predicates-core", "regex", @@ -3370,7 +3268,7 @@ checksum = "09963355b9f467184c04017ced4a2ba2d75cbcb4e7462690d388233253d4b1a9" dependencies = [ "anstyle", "difflib", - "itertools", + "itertools 0.10.5", "predicates-core", ] @@ -3413,30 +3311,6 @@ dependencies = [ "toml 0.5.11", ] -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn 1.0.109", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - [[package]] name = "proc-macro-hack" version = "0.5.20+deprecated" @@ -3445,9 +3319,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.66" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b" dependencies = [ "unicode-ident", ] @@ -3460,7 +3334,7 @@ checksum = "7c003ac8c77cb07bb74f5f198bce836a689bcd5a42574612bf14d17bfd08c20e" dependencies = [ "bit-set", "bit-vec", - "bitflags 2.3.3", + "bitflags 2.5.0", "lazy_static", "num-traits", "rand 0.8.5", @@ -3472,26 +3346,6 @@ dependencies = [ "unarray", ] -[[package]] -name = "ptr_meta" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1" -dependencies = [ - "ptr_meta_derive", -] - -[[package]] -name = "ptr_meta_derive" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "quick-error" version = "1.2.3" @@ -3509,19 +3363,13 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.31" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fe8a65d69dd0808184ebb5f836ab526bb259db23c657efa38711b1072ee47f0" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] -[[package]] -name = "radium" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" - [[package]] name = "radix_trie" version = "0.2.1" @@ -3591,7 +3439,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.10", + "getrandom 0.2.15", ] [[package]] @@ -3659,39 +3507,42 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_termios" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20145670ba436b55d91fc92d25e71160fbfbdd57831631c8d7d36377a476f1cb" + [[package]] name = "redox_users" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" dependencies = [ - "getrandom 0.2.10", + "getrandom 0.2.15", "redox_syscall 0.2.16", "thiserror", ] [[package]] -name = "regalloc2" -version = "0.5.1" +name = "regex" +version = "1.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "300d4fbfb40c1c66a78ba3ddd41c1110247cf52f97b87d0f2fc9209bd49b030c" -dependencies = [ - "fxhash", - "log", - "slice-group-by", - "smallvec", -] - -[[package]] -name = "regex" -version = "1.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575" +checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.3.3", - "regex-syntax 0.7.4", + "regex-automata 0.4.5", + "regex-syntax 0.8.2", ] [[package]] @@ -3708,10 +3559,16 @@ name = "regex-automata" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39354c10dd07468c2e73926b23bb9c2caca74c5501e38a35da70406f1d923310" + +[[package]] +name = "regex-automata" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.7.4", + "regex-syntax 0.8.2", ] [[package]] @@ -3727,64 +3584,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" [[package]] -name = "region" -version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76e189c2369884dce920945e2ddf79b3dff49e071a167dd1817fa9c4c00d512e" -dependencies = [ - "bitflags 1.3.2", - "libc", - "mach", - "winapi", -] - -[[package]] -name = "rend" -version = "0.4.0" +name = "regex-syntax" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581008d2099240d37fb08d77ad713bcaec2c4d89d50b5b21a8bb1996bbab68ab" -dependencies = [ - "bytecheck", -] - -[[package]] -name = "reqwest" -version = "0.11.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e9ad3fe7488d7e34558a2033d45a0c90b72d97b4f80705666fea71472e2e6a1" -dependencies = [ - "base64 0.21.2", - "bytes", - "encoding_rs", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "hyper", - "hyper-rustls", - "ipnet", - "js-sys", - "log", - "mime", - "once_cell", - "percent-encoding 2.3.0", - "pin-project-lite", - "rustls", - "rustls-pemfile", - "serde", - "serde_json", - "serde_urlencoded", - "tokio", - "tokio-rustls", - "tower-service", - "url 2.4.0", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "webpki-roots", - "winreg", -] +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "rexpect" @@ -3819,50 +3622,6 @@ dependencies = [ "bytemuck", ] -[[package]] -name = "ring" -version = "0.16.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" -dependencies = [ - "cc", - "libc", - "once_cell", - "spin", - "untrusted", - "web-sys", - "winapi", -] - -[[package]] -name = "rkyv" -version = "0.7.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0200c8230b013893c0b2d6213d6ec64ed2b9be2e0e016682b7224ff82cff5c58" -dependencies = [ - "bitvec", - "bytecheck", - "hashbrown 0.12.3", - "indexmap 1.9.3", - "ptr_meta", - "rend", - "rkyv_derive", - "seahash", - "tinyvec", - "uuid", -] - -[[package]] -name = "rkyv_derive" -version = "0.7.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2e06b915b5c230a17d7a736d1e2e63ee753c256a8614ef3f5147b13a4f5541d" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "rust-embed" version = "6.8.1" @@ -3883,8 +3642,7 @@ dependencies = [ "proc-macro2", "quote", "rust-embed-utils", - "shellexpand", - "syn 2.0.32", + "syn 2.0.64", "walkdir", ] @@ -3894,7 +3652,6 @@ version = "7.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d38ff6bf570dc3bb7100fce9f7b60c33fa71d80e88da3f2580df4ff2bdded74" dependencies = [ - "globset", "sha2", "walkdir", ] @@ -3926,44 +3683,13 @@ version = "0.38.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0a962918ea88d644592894bc6dc55acc6c0956488adcebbfb6e273506b7fd6e5" dependencies = [ - "bitflags 2.3.3", + "bitflags 2.5.0", "errno", "libc", "linux-raw-sys", "windows-sys 0.48.0", ] -[[package]] -name = "rustls" -version = "0.21.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd8d6c9f025a446bc4d18ad9632e69aec8f287aa84499ee335599fabd20c3fd8" -dependencies = [ - "log", - "ring", - "rustls-webpki", - "sct", -] - -[[package]] -name = "rustls-pemfile" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2" -dependencies = [ - "base64 0.21.2", -] - -[[package]] -name = "rustls-webpki" -version = "0.101.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d93931baf2d282fff8d3a532bbfd7653f734643161b87e3e01e59a04439bf0d" -dependencies = [ - "ring", - "untrusted", -] - [[package]] name = "rustversion" version = "1.0.14" @@ -4096,22 +3822,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" -[[package]] -name = "sct" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" -dependencies = [ - "ring", - "untrusted", -] - -[[package]] -name = "seahash" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" - [[package]] name = "sec1" version = "0.3.0" @@ -4126,12 +3836,6 @@ 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.20" @@ -4143,13 +3847,22 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.179" +version = "1.0.202" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a5bf42b8d227d4abf38a1ddb08602e229108a517cd4e5bb28f9c7eaafdce5c0" +checksum = "226b61a0d411b2ba5ff6d7f73a476ac4f8bb900373459cd00fab8512828ba395" dependencies = [ "serde_derive", ] +[[package]] +name = "serde-big-array" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11fc7cc2c76d73e0f27ee52abbd64eec84d46f370c88371120433196934e4b7f" +dependencies = [ + "serde", +] + [[package]] name = "serde-generate" version = "0.25.1" @@ -4175,26 +3888,15 @@ dependencies = [ "thiserror", ] -[[package]] -name = "serde-wasm-bindgen" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3b4c031cd0d9014307d82b8abf653c0290fbdaeb4c02d00c63cf52f728628bf" -dependencies = [ - "js-sys", - "serde", - "wasm-bindgen", -] - [[package]] name = "serde_derive" -version = "1.0.179" +version = "1.0.202" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "741e124f5485c7e60c03b043f79f320bff3527f4bbf12cf3831750dc46a0ec2c" +checksum = "6048858004bcff69094cd972ed40a32500f153bd3be9f716b2eed2e8217c4838" dependencies = [ "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.64", ] [[package]] @@ -4216,7 +3918,7 @@ checksum = "1d89a8107374290037607734c0b73a85db7ed80cae314b3c5791f192a496e731" dependencies = [ "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.64", ] [[package]] @@ -4228,18 +3930,6 @@ dependencies = [ "serde", ] -[[package]] -name = "serde_urlencoded" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" -dependencies = [ - "form_urlencoded", - "itoa", - "ryu", - "serde", -] - [[package]] name = "serde_with" version = "3.2.0" @@ -4250,7 +3940,7 @@ dependencies = [ "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.0.0", + "indexmap 2.2.6", "serde", "serde_json", "serde_with_macros", @@ -4266,7 +3956,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.64", ] [[package]] @@ -4299,31 +3989,12 @@ 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" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" -[[package]] -name = "shellexpand" -version = "2.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ccc8076840c4da029af4f87e4e8daeb0fca6b87bbb02e10cb60b791450e11e4" -dependencies = [ - "dirs", -] - [[package]] name = "signature" version = "1.6.4" @@ -4334,12 +4005,6 @@ dependencies = [ "rand_core 0.6.4", ] -[[package]] -name = "simdutf8" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a" - [[package]] name = "similar" version = "2.3.0" @@ -4385,12 +4050,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "slice-group-by" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "826167069c09b99d56f31e9ae5c99049e932a98c9dc2dac47645b08dbbf76ba7" - [[package]] name = "small-ord-set" version = "0.1.3" @@ -4402,9 +4061,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.0" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "smawk" @@ -4421,16 +4080,6 @@ dependencies = [ "serde", ] -[[package]] -name = "socket2" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" -dependencies = [ - "libc", - "winapi", -] - [[package]] name = "socket2" version = "0.5.5" @@ -4441,12 +4090,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "spin" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" - [[package]] name = "spki" version = "0.6.0" @@ -4475,6 +4118,19 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9091b6114800a5f2141aee1d1b9d6ca3592ac062dc5decb3764ec5895a47b4eb" +[[package]] +name = "string_cache" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" +dependencies = [ + "new_debug_unreachable", + "once_cell", + "parking_lot 0.12.1", + "phf_shared", + "precomputed-hash", +] + [[package]] name = "strsim" version = "0.10.0" @@ -4513,7 +4169,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "167a4ffd7c35c143fd1030aa3c2caf76ba42220bd5a6b5f4781896434723b8c3" dependencies = [ "debugid", - "memmap2 0.5.10", + "memmap2", "stable_deref_trait", "uuid", ] @@ -4542,38 +4198,15 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.32" +version = "2.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "239814284fd6f1a4ffe4ca893952cdd93c224b6a1571c9a9eadd670295c0c9e2" +checksum = "7ad3dee41f36859875573074334c200d1add8e4a87bb37113ebd31d926b7b11f" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] -[[package]] -name = "tap" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" - -[[package]] -name = "tar" -version = "0.4.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16afcea1f22891c49a00c751c7b63b2233284064f11a200fc624137c51e2ddb" -dependencies = [ - "filetime", - "libc", - "xattr", -] - -[[package]] -name = "target-lexicon" -version = "0.12.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d0e916b1148c8e263850e1ebcbd046f333e0683c724876bb0da63ea4373dc8a" - [[package]] name = "tempfile" version = "3.8.0" @@ -4607,6 +4240,18 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "termion" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "417813675a504dfbbf21bfde32c03e5bf9f2413999962b479023c02848c1c7a5" +dependencies = [ + "libc", + "libredox", + "numtoa", + "redox_termios", +] + [[package]] name = "termtree" version = "0.4.1" @@ -4664,7 +4309,7 @@ checksum = "463fe12d7993d3b327787537ce8dd4dfa058de32fc2b195ef3cde03dc4771e8f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.64", ] [[package]] @@ -4705,6 +4350,15 @@ dependencies = [ "time-core", ] +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + [[package]] name = "tinytemplate" version = "1.2.1" @@ -4732,9 +4386,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.35.0" +version = "1.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841d45b238a16291a4e1584e61820b8ae57d696cc5015c459c229ccc6990cc1c" +checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" dependencies = [ "backtrace", "bytes", @@ -4742,7 +4396,7 @@ dependencies = [ "mio", "num_cpus", "pin-project-lite", - "socket2 0.5.5", + "socket2", "tokio-macros", "windows-sys 0.48.0", ] @@ -4755,24 +4409,14 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.32", -] - -[[package]] -name = "tokio-rustls" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" -dependencies = [ - "rustls", - "tokio", + "syn 2.0.64", ] [[package]] name = "tokio-stream" -version = "0.1.14" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" +checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" dependencies = [ "futures-core", "pin-project-lite", @@ -4795,9 +4439,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.8" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d" +checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" dependencies = [ "bytes", "futures-core", @@ -4805,7 +4449,6 @@ dependencies = [ "futures-sink", "pin-project-lite", "tokio", - "tracing", ] [[package]] @@ -4844,7 +4487,7 @@ version = "0.19.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8123f27e969974a3dfba720fdb560be359f57b44302d280ba72e76a74480e8a" dependencies = [ - "indexmap 2.0.0", + "indexmap 2.2.6", "serde", "serde_spanned", "toml_datetime", @@ -4906,7 +4549,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.64", ] [[package]] @@ -5052,12 +4695,6 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" -[[package]] -name = "untrusted" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" - [[package]] name = "url" version = "1.7.2" @@ -5071,13 +4708,13 @@ dependencies = [ [[package]] name = "url" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" dependencies = [ "form_urlencoded", - "idna 0.4.0", - "percent-encoding 2.3.0", + "idna 0.5.0", + "percent-encoding 2.3.1", "serde", ] @@ -5126,9 +4763,9 @@ dependencies = [ [[package]] name = "walkdir" -version = "2.3.3" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ "same-file", "winapi-util", @@ -5178,7 +4815,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.64", "wasm-bindgen-shared", ] @@ -5212,7 +4849,7 @@ checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.64", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -5247,184 +4884,6 @@ dependencies = [ "quote", ] -[[package]] -name = "wasm-encoder" -version = "0.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ba64e81215916eaeb48fee292f29401d69235d62d8b8fd92a7b2844ec5ae5f7" -dependencies = [ - "leb128", -] - -[[package]] -name = "wasmer" -version = "4.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce45cc009177ca345a6d041f9062305ad467d15e7d41494f5b81ab46d62d7a58" -dependencies = [ - "bytes", - "cfg-if 1.0.0", - "derivative", - "indexmap 1.9.3", - "js-sys", - "more-asserts", - "rustc-demangle", - "serde", - "serde-wasm-bindgen", - "shared-buffer", - "target-lexicon", - "thiserror", - "wasm-bindgen", - "wasmer-compiler", - "wasmer-compiler-cranelift", - "wasmer-derive", - "wasmer-types", - "wasmer-vm", - "wasmparser 0.83.0", - "wasmparser 0.95.0", - "wat", - "winapi", -] - -[[package]] -name = "wasmer-compiler" -version = "4.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e044f6140c844602b920deb4526aea3cc9c0d7cf23f00730bb9b2034669f522a" -dependencies = [ - "backtrace", - "bytes", - "cfg-if 1.0.0", - "enum-iterator", - "enumset", - "lazy_static", - "leb128", - "memmap2 0.5.10", - "more-asserts", - "region", - "rkyv", - "self_cell", - "shared-buffer", - "smallvec", - "thiserror", - "wasmer-types", - "wasmer-vm", - "wasmparser 0.95.0", - "winapi", -] - -[[package]] -name = "wasmer-compiler-cranelift" -version = "4.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32ce02358eb44a149d791c1d6648fb7f8b2f99cd55e3c4eef0474653ec8cc889" -dependencies = [ - "cranelift-codegen", - "cranelift-entity", - "cranelift-frontend", - "gimli 0.26.2", - "more-asserts", - "rayon", - "smallvec", - "target-lexicon", - "tracing", - "wasmer-compiler", - "wasmer-types", -] - -[[package]] -name = "wasmer-derive" -version = "4.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c782d80401edb08e1eba206733f7859db6c997fc5a7f5fb44edc3ecd801468f6" -dependencies = [ - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "wasmer-types" -version = "4.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd09e80d4d74bb9fd0ce6c3c106b1ceba1a050f9948db9d9b78ae53c172d6157" -dependencies = [ - "bytecheck", - "enum-iterator", - "enumset", - "indexmap 1.9.3", - "more-asserts", - "rkyv", - "target-lexicon", - "thiserror", -] - -[[package]] -name = "wasmer-vm" -version = "4.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdcd8a4fd36414a7b6a003dbfbd32393bce3e155d715dd877c05c1b7a41d224d" -dependencies = [ - "backtrace", - "cc", - "cfg-if 1.0.0", - "corosensei", - "crossbeam-queue", - "dashmap", - "derivative", - "enum-iterator", - "fnv", - "indexmap 1.9.3", - "lazy_static", - "libc", - "mach", - "memoffset 0.9.0", - "more-asserts", - "region", - "scopeguard", - "thiserror", - "wasmer-types", - "winapi", -] - -[[package]] -name = "wasmparser" -version = "0.83.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "718ed7c55c2add6548cca3ddd6383d738cd73b892df400e96b9aa876f0141d7a" - -[[package]] -name = "wasmparser" -version = "0.95.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2ea896273ea99b15132414be1da01ab0d8836415083298ecaffbe308eaac87a" -dependencies = [ - "indexmap 1.9.3", - "url 2.4.0", -] - -[[package]] -name = "wast" -version = "64.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a259b226fd6910225aa7baeba82f9d9933b6d00f2ce1b49b80fa4214328237cc" -dependencies = [ - "leb128", - "memchr", - "unicode-width", - "wasm-encoder", -] - -[[package]] -name = "wat" -version = "1.0.71" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53253d920ab413fca1c7dc2161d601c79b4fdf631d0ba51dd4343bf9b556c3f6" -dependencies = [ - "wast", -] - [[package]] name = "web-sys" version = "0.3.63" @@ -5435,12 +4894,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "webpki-roots" -version = "0.25.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14247bb57be4f377dfb94c72830b8ce8fc6beac03cf4bf7b9732eadd414123fc" - [[package]] name = "winapi" version = "0.3.9" @@ -5481,28 +4934,6 @@ dependencies = [ "windows-targets 0.48.1", ] -[[package]] -name = "windows-sys" -version = "0.33.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43dbb096663629518eb1dfa72d80243ca5a6aca764cae62a2df70af760a9be75" -dependencies = [ - "windows_aarch64_msvc 0.33.0", - "windows_i686_gnu 0.33.0", - "windows_i686_msvc 0.33.0", - "windows_x86_64_gnu 0.33.0", - "windows_x86_64_msvc 0.33.0", -] - -[[package]] -name = "windows-sys" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" -dependencies = [ - "windows-targets 0.42.2", -] - [[package]] name = "windows-sys" version = "0.48.0" @@ -5513,18 +4944,12 @@ dependencies = [ ] [[package]] -name = "windows-targets" -version = "0.42.2" +name = "windows-sys" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", + "windows-targets 0.52.4", ] [[package]] @@ -5543,10 +4968,19 @@ dependencies = [ ] [[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" +name = "windows-targets" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" +checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +dependencies = [ + "windows_aarch64_gnullvm 0.52.4", + "windows_aarch64_msvc 0.52.4", + "windows_i686_gnu 0.52.4", + "windows_i686_msvc 0.52.4", + "windows_x86_64_gnu 0.52.4", + "windows_x86_64_gnullvm 0.52.4", + "windows_x86_64_msvc 0.52.4", +] [[package]] name = "windows_aarch64_gnullvm" @@ -5555,16 +4989,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" [[package]] -name = "windows_aarch64_msvc" -version = "0.33.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd761fd3eb9ab8cc1ed81e56e567f02dd82c4c837e48ac3b2181b9ffc5060807" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" +name = "windows_aarch64_gnullvm" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" +checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" [[package]] name = "windows_aarch64_msvc" @@ -5573,16 +5001,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" [[package]] -name = "windows_i686_gnu" -version = "0.33.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cab0cf703a96bab2dc0c02c0fa748491294bf9b7feb27e1f4f96340f208ada0e" - -[[package]] -name = "windows_i686_gnu" -version = "0.42.2" +name = "windows_aarch64_msvc" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" +checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" [[package]] name = "windows_i686_gnu" @@ -5591,16 +5013,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" [[package]] -name = "windows_i686_msvc" -version = "0.33.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cfdbe89cc9ad7ce618ba34abc34bbb6c36d99e96cae2245b7943cd75ee773d0" - -[[package]] -name = "windows_i686_msvc" -version = "0.42.2" +name = "windows_i686_gnu" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" +checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" [[package]] name = "windows_i686_msvc" @@ -5609,16 +5025,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" [[package]] -name = "windows_x86_64_gnu" -version = "0.33.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4dd9b0c0e9ece7bb22e84d70d01b71c6d6248b81a3c60d11869451b4cb24784" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" +name = "windows_i686_msvc" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" +checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" [[package]] name = "windows_x86_64_gnu" @@ -5627,10 +5037,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" [[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" +name = "windows_x86_64_gnu" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" +checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" [[package]] name = "windows_x86_64_gnullvm" @@ -5639,22 +5049,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" [[package]] -name = "windows_x86_64_msvc" -version = "0.33.0" +name = "windows_x86_64_gnullvm" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff1e4aa646495048ec7f3ffddc411e1d829c026a2ec62b39da15c1055e406eaa" +checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" [[package]] name = "windows_x86_64_msvc" -version = "0.42.2" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" +checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" [[package]] name = "windows_x86_64_msvc" -version = "0.48.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" [[package]] name = "winnow" @@ -5665,34 +5075,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "winreg" -version = "0.50.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" -dependencies = [ - "cfg-if 1.0.0", - "windows-sys 0.48.0", -] - -[[package]] -name = "wyz" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" -dependencies = [ - "tap", -] - -[[package]] -name = "xattr" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4686009f71ff3e5c4dbcf1a282d0a44db3f021ba69350cd42086b3e5f1c6985" -dependencies = [ - "libc", -] - [[package]] name = "zerocopy" version = "0.7.32" @@ -5710,7 +5092,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.64", ] [[package]] @@ -5730,5 +5112,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.64", ] diff --git a/Cargo.toml b/Cargo.toml index 7d5da7b00d0..182580f8d67 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,10 +1,10 @@ [workspace] members = [ - # Macros crates for metaprogramming + # Aztec Macro crate for metaprogramming "aztec_macros", - "noirc_macros", # Compiler crates + "compiler/noirc_arena", "compiler/noirc_evaluator", "compiler/noirc_frontend", "compiler/noirc_errors", @@ -12,12 +12,7 @@ members = [ "compiler/noirc_printable_type", "compiler/fm", "compiler/wasm", - # Utility crates used by the Noir compiler - "compiler/utils/arena", - "compiler/utils/iter-extended", - # Crates related to tooling built ontop of the Noir compiler - "tooling/backend_interface", - "tooling/bb_abstraction_leaks", + # Crates related to tooling built on top of the Noir compiler "tooling/lsp", "tooling/debugger", "tooling/nargo", @@ -26,6 +21,7 @@ members = [ "tooling/nargo_toml", "tooling/noirc_abi", "tooling/noirc_abi_wasm", + "tooling/acvm_cli", # ACVM "acvm-repo/acir_field", "acvm-repo/acir", @@ -35,35 +31,36 @@ members = [ "acvm-repo/brillig_vm", "acvm-repo/blackbox_solver", "acvm-repo/bn254_blackbox_solver", + # Utility crates + "utils/iter-extended", ] -default-members = ["tooling/nargo_cli"] +default-members = ["tooling/nargo_cli", "tooling/acvm_cli"] resolver = "2" [workspace.package] # x-release-please-start-version -version = "0.24.0" +version = "0.30.0" # x-release-please-end authors = ["The Noir Team "] edition = "2021" -rust-version = "1.73.0" +rust-version = "1.74.1" license = "MIT OR Apache-2.0" repository = "https://github.com/noir-lang/noir/" [workspace.dependencies] # ACVM workspace dependencies -acir_field = { version = "0.40.0", path = "acvm-repo/acir_field", default-features = false } -acir = { version = "0.40.0", path = "acvm-repo/acir", default-features = false } -acvm = { version = "0.40.0", path = "acvm-repo/acvm" } -brillig = { version = "0.40.0", path = "acvm-repo/brillig", default-features = false } -brillig_vm = { version = "0.40.0", path = "acvm-repo/brillig_vm", default-features = false } -acvm_blackbox_solver = { version = "0.40.0", path = "acvm-repo/blackbox_solver", default-features = false } -bn254_blackbox_solver = { version = "0.39.0", path = "acvm-repo/bn254_blackbox_solver", default-features = false } +acir_field = { version = "0.46.0", path = "acvm-repo/acir_field", default-features = false } +acir = { version = "0.46.0", path = "acvm-repo/acir", default-features = false } +acvm = { version = "0.46.0", path = "acvm-repo/acvm" } +brillig = { version = "0.46.0", path = "acvm-repo/brillig", default-features = false } +brillig_vm = { version = "0.46.0", path = "acvm-repo/brillig_vm", default-features = false } +acvm_blackbox_solver = { version = "0.46.0", path = "acvm-repo/blackbox_solver", default-features = false } +bn254_blackbox_solver = { version = "0.46.0", path = "acvm-repo/bn254_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_arena = { path = "compiler/noirc_arena" } noirc_driver = { path = "compiler/noirc_driver" } noirc_errors = { path = "compiler/noirc_errors" } noirc_evaluator = { path = "compiler/noirc_evaluator" } @@ -78,6 +75,10 @@ noir_lsp = { path = "tooling/lsp" } noir_debugger = { path = "tooling/debugger" } noirc_abi = { path = "tooling/noirc_abi" } bb_abstraction_leaks = { path = "tooling/bb_abstraction_leaks" } +acvm_cli = { path = "tooling/acvm_cli" } + +# Misc utils crates +iter-extended = { path = "utils/iter-extended" } # LSP async-lsp = { version = "0.1.0", default-features = false } @@ -103,6 +104,14 @@ chumsky = { git = "https://github.com/jfecher/chumsky", rev = "ad9d312", default "ahash", "std", ] } + +# Benchmarking +criterion = "0.5.0" +# Note that using the "frame-pointer" feature breaks framegraphs on linux +# https://github.com/tikv/pprof-rs/pull/172 +pprof = { version = "0.13", features = ["flamegraph", "criterion"] } + + dirs = "4" serde = { version = "1.0.136", features = ["derive"] } serde_json = "1.0" @@ -123,6 +132,7 @@ tempfile = "3.6.0" jsonrpc = { version = "0.16.0", features = ["minreq_http"] } flate2 = "1.0.24" +im = { version = "15.1", features = ["serde"] } tracing = "0.1.40" tracing-web = "0.1.3" tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 3a478c3f95a..00000000000 --- a/Dockerfile +++ /dev/null @@ -1,12 +0,0 @@ -FROM rust:bullseye -WORKDIR /usr/src/noir -COPY . . -RUN ./scripts/bootstrap_native.sh - -# When running the container, mount the users home directory to same location. -FROM ubuntu:focal -# Install Tini as nargo doesn't handle signals properly. -# Install git as nargo needs it to clone. -RUN apt-get update && apt-get install -y git tini && rm -rf /var/lib/apt/lists/* && apt-get clean -COPY --from=0 /usr/src/noir/target/release/nargo /usr/src/noir/target/release/nargo -ENTRYPOINT ["/usr/bin/tini", "--", "/usr/src/noir/target/release/nargo"] diff --git a/Dockerfile.ci b/Dockerfile.ci deleted file mode 100644 index e0dc030980c..00000000000 --- a/Dockerfile.ci +++ /dev/null @@ -1,30 +0,0 @@ -FROM rust:1.73.0-slim-bookworm as base -RUN apt-get update && apt-get upgrade -y && apt-get install build-essential git -y -WORKDIR /usr/src/noir -ENV PATH="${PATH}:/usr/src/noir/target/release" - -FROM base as base-nargo -COPY . . -RUN .github/scripts/nargo-build.sh - -FROM base as base-js -RUN apt-get install -y ca-certificates curl gnupg -RUN mkdir -p /etc/apt/keyrings -RUN curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg -RUN echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_20.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list -RUN apt-get update && apt-get install nodejs -y -RUN corepack enable -RUN apt-get install -y jq -COPY yarn.lock package.json .yarnrc.yml ./ -COPY .yarn/ ./.yarn/ -COPY ./acvm-repo/acvm_js/package.json ./acvm-repo/acvm_js/ -COPY ./tooling/noirc_abi_wasm/package.json ./tooling/noirc_abi_wasm/ -COPY ./compiler/wasm/package.json ./compiler/wasm/ -COPY ./tooling/noir_js_types/package.json ./tooling/noir_js_types/ -COPY ./tooling/noir_js_backend_barretenberg/package.json ./tooling/noir_js_backend_barretenberg/ -COPY ./tooling/noir_js/package.json ./tooling/noir_js/ -COPY ./tooling/noir_codegen/package.json ./tooling/noir_codegen/ -COPY ./compiler/integration-tests/package.json ./compiler/integration-tests/ -COPY ./docs/package.json ./docs/ -RUN yarn --immutable -COPY . . diff --git a/Dockerfile.packages b/Dockerfile.packages deleted file mode 100644 index f40670c19e4..00000000000 --- a/Dockerfile.packages +++ /dev/null @@ -1,22 +0,0 @@ -FROM rust:alpine3.17 -RUN apk update \ - && apk upgrade \ - && apk add --no-cache \ - build-base \ - pkgconfig \ - openssl-dev \ - npm \ - yarn \ - bash \ - jq \ - git \ - curl - -WORKDIR /usr/src/noir -COPY . . -RUN ./scripts/bootstrap_packages.sh - -FROM scratch -COPY --from=0 /usr/src/noir/packages /usr/src/noir/packages -# For some unknown reason, on alpine only, we need this to exist. -COPY --from=0 /usr/src/noir/node_modules/@noir-lang /usr/src/noir/node_modules/@noir-lang diff --git a/README.md b/README.md index 5c93512ae26..eea2280c50c 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,13 @@ +
+ + The Noir Programming Language + + +[Website][Noir] | [Getting started] | [Documentation] | [Contributing] +
+ + + # The Noir Programming Language Noir is a Domain Specific Language for SNARK proving systems. It has been designed to use any ACIR compatible proving system. @@ -6,78 +16,35 @@ Noir is a Domain Specific Language for SNARK proving systems. It has been design ## Quick Start -Read the installation section [here](https://noir-lang.org/docs/dev/getting_started/installation/). +Read the [installation section][Getting started] from the [Noir docs][Documentation]. Once you have read through the documentation, you can visit [Awesome Noir](https://github.com/noir-lang/awesome-noir) to run some of the examples that others have created. -## Current Features - -Backends: +## Getting Help -- Barretenberg via FFI -- Marlin via arkworks (Note -- latest interfaces may not be updated to support Marlin backend. Please open an issue if this is relevant to your project and requires attention.) +Join the Noir [forum][Forum] or [Discord][Discord] -Compiler: +## Contributing -- 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 -- Pedersen -- HashToField +See [CONTRIBUTING.md][CONTRIBUTING]. ## Future Work The current focus is to gather as much feedback as possible while in the alpha phase. The main focuses of Noir are _safety_ and _developer experience_. If you find a feature that does not seem to be in line with these goals, please open an issue! -Concretely the following items are on the road map: - -- General code sanitization and documentation (ongoing effort) -- Prover and Verifier Key logic. (Prover and Verifier pre-process per compile) -- Fallback mechanism for backend unsupported opcodes -- Visibility modifiers -- Signed integers -- Backend integration: (Bulletproofs) -- Recursion -- Big integers - ## Minimum Rust version -This crate's minimum supported rustc version is 1.73.0. - -## Working on this project - -This project uses [Nix](https://nixos.org/) and [direnv](https://direnv.net/) to streamline the development experience. Please follow [our guidelines](https://noir-lang.org/docs/getting_started/installation/other_install_methods#option-3-compile-from-source) to setup your environment for working on the project. - -### Building against a different local/remote version of Barretenberg - -If you are working on this project and want a different version of Barretenberg (instead of the version this project is pinned against), you'll want to replace the lockfile version with your version. This can be done by running: - -```sh -nix flake lock --override-input barretenberg /absolute/path/to/your/barretenberg -``` - -You can also point at a fork and/or branch on GitHub using: - -```sh -nix flake lock --override-input barretenberg github:username/barretenberg/branch_name -``` - -__Note:__ You don't want to commit the updated lockfile, as it will fail in CI! +This workspace's minimum supported rustc version is 1.74.1. ## License Noir is free and open source. It is distributed under a dual license. (MIT/APACHE) -Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this repository by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. + +[Noir]: https://www.noir-lang.org/ +[Getting Started]: https://noir-lang.org/docs/getting_started/installation/ +[Forum]: https://forum.aztec.network/c/noir +[Discord]: https://discord.gg/JtqzkdeQ6G +[Documentation]: https://noir-lang.org/docs +[Contributing]: CONTRIBUTING.md \ No newline at end of file diff --git a/acvm-repo/CHANGELOG.md b/acvm-repo/CHANGELOG.md index acb465e5cc9..c9bb0d610eb 100644 --- a/acvm-repo/CHANGELOG.md +++ b/acvm-repo/CHANGELOG.md @@ -5,6 +5,602 @@ 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.46.0](https://github.com/noir-lang/noir/compare/v0.45.0...v0.46.0) (2024-05-20) + + +### ⚠ BREAKING CHANGES + +* remove `Opcode::Brillig` from ACIR (https://github.com/AztecProtocol/aztec-packages/pull/5995) +* AES blackbox (https://github.com/AztecProtocol/aztec-packages/pull/6016) +* Bit shift is restricted to u8 right operand ([#4907](https://github.com/noir-lang/noir/issues/4907)) +* contract interfaces and better function calls (https://github.com/AztecProtocol/aztec-packages/pull/5687) +* change backend width to 4 (https://github.com/AztecProtocol/aztec-packages/pull/5374) +* Use fixed size arrays in black box functions where sizes are known (https://github.com/AztecProtocol/aztec-packages/pull/5620) +* trap with revert data (https://github.com/AztecProtocol/aztec-packages/pull/5732) +* **acir:** BrilligCall opcode (https://github.com/AztecProtocol/aztec-packages/pull/5709) +* remove fixed-length keccak256 (https://github.com/AztecProtocol/aztec-packages/pull/5617) +* storage_layout and `#[aztec(storage)]` (https://github.com/AztecProtocol/aztec-packages/pull/5387) +* **acir:** Add predicate to call opcode (https://github.com/AztecProtocol/aztec-packages/pull/5616) +* contract_abi-exports (https://github.com/AztecProtocol/aztec-packages/pull/5386) +* Brillig typed memory (https://github.com/AztecProtocol/aztec-packages/pull/5395) +* **acir:** Program and witness stack structure (https://github.com/AztecProtocol/aztec-packages/pull/5149) +* automatic NoteInterface and NoteGetterOptions auto select (https://github.com/AztecProtocol/aztec-packages/pull/4508) +* Acir call opcode (https://github.com/AztecProtocol/aztec-packages/pull/4773) +* Support contracts with no constructor (https://github.com/AztecProtocol/aztec-packages/pull/5175) +* Internal as a macro (https://github.com/AztecProtocol/aztec-packages/pull/4898) +* move noir out of yarn-project (https://github.com/AztecProtocol/aztec-packages/pull/4479) +* note type ids (https://github.com/AztecProtocol/aztec-packages/pull/4500) +* rename bigint_neg into bigint_sub (https://github.com/AztecProtocol/aztec-packages/pull/4420) +* Add expression width into acir (https://github.com/AztecProtocol/aztec-packages/pull/4014) +* init storage macro (https://github.com/AztecProtocol/aztec-packages/pull/4200) +* **acir:** Move `is_recursive` flag to be part of the circuit definition (https://github.com/AztecProtocol/aztec-packages/pull/4221) +* Sync commits from `aztec-packages` ([#4144](https://github.com/noir-lang/noir/issues/4144)) + +### Features + +* `multi_scalar_mul` blackbox func (https://github.com/AztecProtocol/aztec-packages/pull/6097) ([73a635e](https://github.com/noir-lang/noir/commit/73a635e5086cf3407f9846ce39807cd15b4e485a)) +* `variable_base_scalar_mul` blackbox func (https://github.com/AztecProtocol/aztec-packages/pull/6039) ([73a635e](https://github.com/noir-lang/noir/commit/73a635e5086cf3407f9846ce39807cd15b4e485a)) +* Acir call opcode (https://github.com/AztecProtocol/aztec-packages/pull/4773) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* **acir_gen:** Brillig stdlib ([#4848](https://github.com/noir-lang/noir/issues/4848)) ([0c8175c](https://github.com/noir-lang/noir/commit/0c8175cb539efd9427c73ae5af0d48abe688ebab)) +* **acir_gen:** Fold attribute at compile-time and initial non inlined ACIR (https://github.com/AztecProtocol/aztec-packages/pull/5341) ([a0f7474](https://github.com/noir-lang/noir/commit/a0f7474ae6bd74132efdb945d2eb2383f3913cce)) +* **acir:** Add predicate to call opcode (https://github.com/AztecProtocol/aztec-packages/pull/5616) ([2bd006a](https://github.com/noir-lang/noir/commit/2bd006ae07499e8702b0fa9565855f0a5ef1a589)) +* **acir:** BrilligCall opcode (https://github.com/AztecProtocol/aztec-packages/pull/5709) ([0f9ae0a](https://github.com/noir-lang/noir/commit/0f9ae0ac1d68714b56ba4524aedcc67212494f1b)) +* **acir:** Program and witness stack structure (https://github.com/AztecProtocol/aztec-packages/pull/5149) ([13eb71b](https://github.com/noir-lang/noir/commit/13eb71b8de44eb6aad9c37943ad06fc73db589f5)) +* **acvm_js:** Execute program ([#4694](https://github.com/noir-lang/noir/issues/4694)) ([386f6d0](https://github.com/noir-lang/noir/commit/386f6d0a5822912db878285cb001032a7c0ff622)) +* **acvm:** Execute multiple circuits (https://github.com/AztecProtocol/aztec-packages/pull/5380) ([a0f7474](https://github.com/noir-lang/noir/commit/a0f7474ae6bd74132efdb945d2eb2383f3913cce)) +* Add bit size to const opcode (https://github.com/AztecProtocol/aztec-packages/pull/4385) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* Add CMOV instruction to brillig and brillig gen (https://github.com/AztecProtocol/aztec-packages/pull/5308) ([13eb71b](https://github.com/noir-lang/noir/commit/13eb71b8de44eb6aad9c37943ad06fc73db589f5)) +* Add expression width into acir (https://github.com/AztecProtocol/aztec-packages/pull/4014) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* Add instrumentation for tracking variables in debugging ([#4122](https://github.com/noir-lang/noir/issues/4122)) ([c58d691](https://github.com/noir-lang/noir/commit/c58d69141b54a918cd1675400c00bfd48720f896)) +* Add native rust implementations of pedersen functions ([#4871](https://github.com/noir-lang/noir/issues/4871)) ([fb039f7](https://github.com/noir-lang/noir/commit/fb039f74df23aea39bc0593a5d538d82b4efadf0)) +* Add poseidon2 opcode implementation for acvm/brillig, and Noir ([#4398](https://github.com/noir-lang/noir/issues/4398)) ([10e8292](https://github.com/noir-lang/noir/commit/10e82920798380f50046e52db4a20ca205191ab7)) +* Add return values to aztec fns (https://github.com/AztecProtocol/aztec-packages/pull/5389) ([2bd006a](https://github.com/noir-lang/noir/commit/2bd006ae07499e8702b0fa9565855f0a5ef1a589)) +* Add support for overriding expression width ([#4117](https://github.com/noir-lang/noir/issues/4117)) ([c8026d5](https://github.com/noir-lang/noir/commit/c8026d557d535b10fe455165d6445076df7a03de)) +* Added cast opcode and cast calldata (https://github.com/AztecProtocol/aztec-packages/pull/4423) ([78ef013](https://github.com/noir-lang/noir/commit/78ef0134b82e76a73dadb6c7975def22290e3a1a)) +* AES blackbox (https://github.com/AztecProtocol/aztec-packages/pull/6016) ([73a635e](https://github.com/noir-lang/noir/commit/73a635e5086cf3407f9846ce39807cd15b4e485a)) +* Allow brillig to read arrays directly from memory (https://github.com/AztecProtocol/aztec-packages/pull/4460) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* Allow nested arrays and vectors in Brillig foreign calls (https://github.com/AztecProtocol/aztec-packages/pull/4478) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* Allow variables and stack trace inspection in the debugger ([#4184](https://github.com/noir-lang/noir/issues/4184)) ([bf263fc](https://github.com/noir-lang/noir/commit/bf263fc8d843940f328a90f6366edd2671fb2682)) +* Automatic NoteInterface and NoteGetterOptions auto select (https://github.com/AztecProtocol/aztec-packages/pull/4508) ([13eb71b](https://github.com/noir-lang/noir/commit/13eb71b8de44eb6aad9c37943ad06fc73db589f5)) +* **avm:** Back in avm context with macro - refactor context (https://github.com/AztecProtocol/aztec-packages/pull/4438) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* **avm:** Brillig CONST of size > u128 (https://github.com/AztecProtocol/aztec-packages/pull/5217) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* **avm:** Integrate AVM with initializers (https://github.com/AztecProtocol/aztec-packages/pull/5469) ([2bd006a](https://github.com/noir-lang/noir/commit/2bd006ae07499e8702b0fa9565855f0a5ef1a589)) +* **aztec-nr:** Initial work for aztec public vm macro (https://github.com/AztecProtocol/aztec-packages/pull/4400) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* Backpropagate constants in ACIR during optimization ([#3926](https://github.com/noir-lang/noir/issues/3926)) ([aad0da0](https://github.com/noir-lang/noir/commit/aad0da024c69663f42e6913e674682d5864b26ae)) +* Bit shift is restricted to u8 right operand ([#4907](https://github.com/noir-lang/noir/issues/4907)) ([c4b0369](https://github.com/noir-lang/noir/commit/c4b03691feca17ef268acab523292f3051f672ea)) +* Brillig heterogeneous memory cells (https://github.com/AztecProtocol/aztec-packages/pull/5608) ([305bcdc](https://github.com/noir-lang/noir/commit/305bcdcbd01cb84dbaac900f14cb6cf867f83bda)) +* Brillig IR refactor (https://github.com/AztecProtocol/aztec-packages/pull/5233) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* Brillig pointer codegen and execution (https://github.com/AztecProtocol/aztec-packages/pull/5737) ([0f9ae0a](https://github.com/noir-lang/noir/commit/0f9ae0ac1d68714b56ba4524aedcc67212494f1b)) +* Brillig typed memory (https://github.com/AztecProtocol/aztec-packages/pull/5395) ([0bc18c4](https://github.com/noir-lang/noir/commit/0bc18c4f78171590dd58bded959f68f53a44cc8c)) +* Change backend width to 4 (https://github.com/AztecProtocol/aztec-packages/pull/5374) ([0f9ae0a](https://github.com/noir-lang/noir/commit/0f9ae0ac1d68714b56ba4524aedcc67212494f1b)) +* Check initializer msg.sender matches deployer from address preimage (https://github.com/AztecProtocol/aztec-packages/pull/5222) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* Contract interfaces and better function calls (https://github.com/AztecProtocol/aztec-packages/pull/5687) ([0f9ae0a](https://github.com/noir-lang/noir/commit/0f9ae0ac1d68714b56ba4524aedcc67212494f1b)) +* Contract_abi-exports (https://github.com/AztecProtocol/aztec-packages/pull/5386) ([2bd006a](https://github.com/noir-lang/noir/commit/2bd006ae07499e8702b0fa9565855f0a5ef1a589)) +* Dynamic assertion payloads v2 (https://github.com/AztecProtocol/aztec-packages/pull/5949) ([73a635e](https://github.com/noir-lang/noir/commit/73a635e5086cf3407f9846ce39807cd15b4e485a)) +* Evaluation of dynamic assert messages ([#4101](https://github.com/noir-lang/noir/issues/4101)) ([c284e01](https://github.com/noir-lang/noir/commit/c284e01bfe20ceae4414dc123624b5cbb8b66d09)) +* Handle `BrilligCall` opcodes in the debugger ([#4897](https://github.com/noir-lang/noir/issues/4897)) ([b380dc4](https://github.com/noir-lang/noir/commit/b380dc44de5c9f8de278ece3d531ebbc2c9238ba)) +* Impl of missing functionality in new key store (https://github.com/AztecProtocol/aztec-packages/pull/5750) ([0f9ae0a](https://github.com/noir-lang/noir/commit/0f9ae0ac1d68714b56ba4524aedcc67212494f1b)) +* Increase default expression width to 4 ([#4995](https://github.com/noir-lang/noir/issues/4995)) ([f01d309](https://github.com/noir-lang/noir/commit/f01d3090759a5ff0f1f83c5616d22890c6bd76be)) +* Init storage macro (https://github.com/AztecProtocol/aztec-packages/pull/4200) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* Initial Earthly CI (https://github.com/AztecProtocol/aztec-packages/pull/5069) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* Internal as a macro (https://github.com/AztecProtocol/aztec-packages/pull/4898) ([5f57ebb](https://github.com/noir-lang/noir/commit/5f57ebb7ff4b810802f90699a10f4325ef904f2e)) +* **nargo:** Handle call stacks for multiple Acir calls ([#4711](https://github.com/noir-lang/noir/issues/4711)) ([5b23171](https://github.com/noir-lang/noir/commit/5b231714740447d82cde7cdbe65d4a8b46a31df4)) +* New brillig field operations and refactor of binary operations (https://github.com/AztecProtocol/aztec-packages/pull/5208) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* Note type ids (https://github.com/AztecProtocol/aztec-packages/pull/4500) ([78ef013](https://github.com/noir-lang/noir/commit/78ef0134b82e76a73dadb6c7975def22290e3a1a)) +* Parsing non-string assertion payloads in noir js (https://github.com/AztecProtocol/aztec-packages/pull/6079) ([73a635e](https://github.com/noir-lang/noir/commit/73a635e5086cf3407f9846ce39807cd15b4e485a)) +* Remove replacement of boolean range opcodes with `AssertZero` opcodes ([#4107](https://github.com/noir-lang/noir/issues/4107)) ([dac0e87](https://github.com/noir-lang/noir/commit/dac0e87ee3be3446b92bbb12ef4832fd493fcee3)) +* Restore hashing args via slice for performance (https://github.com/AztecProtocol/aztec-packages/pull/5539) ([2bd006a](https://github.com/noir-lang/noir/commit/2bd006ae07499e8702b0fa9565855f0a5ef1a589)) +* Set aztec private functions to be recursive (https://github.com/AztecProtocol/aztec-packages/pull/6192) ([73a635e](https://github.com/noir-lang/noir/commit/73a635e5086cf3407f9846ce39807cd15b4e485a)) +* Signed integer division and modulus in brillig gen (https://github.com/AztecProtocol/aztec-packages/pull/5279) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* **simulator:** Fetch return values at circuit execution (https://github.com/AztecProtocol/aztec-packages/pull/5642) ([305bcdc](https://github.com/noir-lang/noir/commit/305bcdcbd01cb84dbaac900f14cb6cf867f83bda)) +* Storage_layout and `#[aztec(storage)]` (https://github.com/AztecProtocol/aztec-packages/pull/5387) ([2bd006a](https://github.com/noir-lang/noir/commit/2bd006ae07499e8702b0fa9565855f0a5ef1a589)) +* Support contracts with no constructor (https://github.com/AztecProtocol/aztec-packages/pull/5175) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* Sync `aztec-packages` ([#4011](https://github.com/noir-lang/noir/issues/4011)) ([fee2452](https://github.com/noir-lang/noir/commit/fee24523c427c27f0bdaf98ea09a852a2da3e94c)) +* Sync commits from `aztec-packages` ([#4068](https://github.com/noir-lang/noir/issues/4068)) ([7a8f3a3](https://github.com/noir-lang/noir/commit/7a8f3a33b57875e681e3d81e667e3570a1cdbdcc)) +* Sync commits from `aztec-packages` ([#4144](https://github.com/noir-lang/noir/issues/4144)) ([0205d3b](https://github.com/noir-lang/noir/commit/0205d3b4ad0cf5ffd775a43eb5af273a772cf138)) +* Sync from aztec-packages ([#4483](https://github.com/noir-lang/noir/issues/4483)) ([fe8f277](https://github.com/noir-lang/noir/commit/fe8f2776ccfde29209a2c3fc162311c99e4f59be)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/5234) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/5286) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/5572) ([2bd006a](https://github.com/noir-lang/noir/commit/2bd006ae07499e8702b0fa9565855f0a5ef1a589)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/5619) ([2bd006a](https://github.com/noir-lang/noir/commit/2bd006ae07499e8702b0fa9565855f0a5ef1a589)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/5697) ([305bcdc](https://github.com/noir-lang/noir/commit/305bcdcbd01cb84dbaac900f14cb6cf867f83bda)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/5794) ([0f9ae0a](https://github.com/noir-lang/noir/commit/0f9ae0ac1d68714b56ba4524aedcc67212494f1b)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/5814) ([0f9ae0a](https://github.com/noir-lang/noir/commit/0f9ae0ac1d68714b56ba4524aedcc67212494f1b)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/5935) ([1b867b1](https://github.com/noir-lang/noir/commit/1b867b121fba5db3087ca845b4934e6732b23fd1)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/5955) ([1b867b1](https://github.com/noir-lang/noir/commit/1b867b121fba5db3087ca845b4934e6732b23fd1)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/5999) ([1b867b1](https://github.com/noir-lang/noir/commit/1b867b121fba5db3087ca845b4934e6732b23fd1)) +* Trap with revert data (https://github.com/AztecProtocol/aztec-packages/pull/5732) ([0f9ae0a](https://github.com/noir-lang/noir/commit/0f9ae0ac1d68714b56ba4524aedcc67212494f1b)) +* Use fixed size arrays in black box functions where sizes are known (https://github.com/AztecProtocol/aztec-packages/pull/5620) ([0f9ae0a](https://github.com/noir-lang/noir/commit/0f9ae0ac1d68714b56ba4524aedcc67212494f1b)) +* Variable length returns (https://github.com/AztecProtocol/aztec-packages/pull/5633) ([305bcdc](https://github.com/noir-lang/noir/commit/305bcdcbd01cb84dbaac900f14cb6cf867f83bda)) + + +### Bug Fixes + +* **acvm:** Mark outputs of Opcode::Call solvable ([#4708](https://github.com/noir-lang/noir/issues/4708)) ([8fea405](https://github.com/noir-lang/noir/commit/8fea40576f262bd5bb588923c0660d8967404e56)) +* Avoid huge unrolling in hash_args (https://github.com/AztecProtocol/aztec-packages/pull/5703) ([305bcdc](https://github.com/noir-lang/noir/commit/305bcdcbd01cb84dbaac900f14cb6cf867f83bda)) +* Catch panics from EC point creation (e.g. the point is at infinity) ([#4790](https://github.com/noir-lang/noir/issues/4790)) ([645dba1](https://github.com/noir-lang/noir/commit/645dba192f16ef34018828186ffb297422a8dc73)) +* Don't reuse brillig with slice arguments (https://github.com/AztecProtocol/aztec-packages/pull/5800) ([0f9ae0a](https://github.com/noir-lang/noir/commit/0f9ae0ac1d68714b56ba4524aedcc67212494f1b)) +* Issue 4682 and add solver for unconstrained bigintegers ([#4729](https://github.com/noir-lang/noir/issues/4729)) ([e4d33c1](https://github.com/noir-lang/noir/commit/e4d33c126a2795d9aaa6048d4e91b64cb4bbe4f2)) +* Noir test incorrect reporting (https://github.com/AztecProtocol/aztec-packages/pull/4925) ([5f57ebb](https://github.com/noir-lang/noir/commit/5f57ebb7ff4b810802f90699a10f4325ef904f2e)) +* Proper field inversion for bigints ([#4802](https://github.com/noir-lang/noir/issues/4802)) ([b46d0e3](https://github.com/noir-lang/noir/commit/b46d0e39f4252f8bbaa987f88d112e4c233b3d61)) +* Remove panic from `init_log_level` in `acvm_js` ([#4195](https://github.com/noir-lang/noir/issues/4195)) ([2e26530](https://github.com/noir-lang/noir/commit/2e26530bf53006c1ed4fee310bcaa905c95dd95b)) + + +### Miscellaneous Chores + +* **acir:** Move `is_recursive` flag to be part of the circuit definition (https://github.com/AztecProtocol/aztec-packages/pull/4221) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* Move noir out of yarn-project (https://github.com/AztecProtocol/aztec-packages/pull/4479) ([78ef013](https://github.com/noir-lang/noir/commit/78ef0134b82e76a73dadb6c7975def22290e3a1a)) +* Remove `Opcode::Brillig` from ACIR (https://github.com/AztecProtocol/aztec-packages/pull/5995) ([73a635e](https://github.com/noir-lang/noir/commit/73a635e5086cf3407f9846ce39807cd15b4e485a)) +* Remove fixed-length keccak256 (https://github.com/AztecProtocol/aztec-packages/pull/5617) ([305bcdc](https://github.com/noir-lang/noir/commit/305bcdcbd01cb84dbaac900f14cb6cf867f83bda)) +* Rename bigint_neg into bigint_sub (https://github.com/AztecProtocol/aztec-packages/pull/4420) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) + +## [0.45.0](https://github.com/noir-lang/noir/compare/v0.44.0...v0.45.0) (2024-05-03) + + +### ⚠ BREAKING CHANGES + +* Bit shift is restricted to u8 right operand ([#4907](https://github.com/noir-lang/noir/issues/4907)) +* contract interfaces and better function calls (https://github.com/AztecProtocol/aztec-packages/pull/5687) +* change backend width to 4 (https://github.com/AztecProtocol/aztec-packages/pull/5374) +* Use fixed size arrays in black box functions where sizes are known (https://github.com/AztecProtocol/aztec-packages/pull/5620) +* trap with revert data (https://github.com/AztecProtocol/aztec-packages/pull/5732) +* **acir:** BrilligCall opcode (https://github.com/AztecProtocol/aztec-packages/pull/5709) +* remove fixed-length keccak256 (https://github.com/AztecProtocol/aztec-packages/pull/5617) +* storage_layout and `#[aztec(storage)]` (https://github.com/AztecProtocol/aztec-packages/pull/5387) +* **acir:** Add predicate to call opcode (https://github.com/AztecProtocol/aztec-packages/pull/5616) +* contract_abi-exports (https://github.com/AztecProtocol/aztec-packages/pull/5386) +* Brillig typed memory (https://github.com/AztecProtocol/aztec-packages/pull/5395) +* **acir:** Program and witness stack structure (https://github.com/AztecProtocol/aztec-packages/pull/5149) +* automatic NoteInterface and NoteGetterOptions auto select (https://github.com/AztecProtocol/aztec-packages/pull/4508) +* Acir call opcode (https://github.com/AztecProtocol/aztec-packages/pull/4773) +* Support contracts with no constructor (https://github.com/AztecProtocol/aztec-packages/pull/5175) +* Internal as a macro (https://github.com/AztecProtocol/aztec-packages/pull/4898) +* move noir out of yarn-project (https://github.com/AztecProtocol/aztec-packages/pull/4479) +* note type ids (https://github.com/AztecProtocol/aztec-packages/pull/4500) +* rename bigint_neg into bigint_sub (https://github.com/AztecProtocol/aztec-packages/pull/4420) +* Add expression width into acir (https://github.com/AztecProtocol/aztec-packages/pull/4014) +* init storage macro (https://github.com/AztecProtocol/aztec-packages/pull/4200) +* **acir:** Move `is_recursive` flag to be part of the circuit definition (https://github.com/AztecProtocol/aztec-packages/pull/4221) +* Sync commits from `aztec-packages` ([#4144](https://github.com/noir-lang/noir/issues/4144)) +* Breaking changes from aztec-packages ([#3955](https://github.com/noir-lang/noir/issues/3955)) + +### Features + +* Acir call opcode (https://github.com/AztecProtocol/aztec-packages/pull/4773) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* **acir_gen:** Brillig stdlib ([#4848](https://github.com/noir-lang/noir/issues/4848)) ([0c8175c](https://github.com/noir-lang/noir/commit/0c8175cb539efd9427c73ae5af0d48abe688ebab)) +* **acir_gen:** Fold attribute at compile-time and initial non inlined ACIR (https://github.com/AztecProtocol/aztec-packages/pull/5341) ([a0f7474](https://github.com/noir-lang/noir/commit/a0f7474ae6bd74132efdb945d2eb2383f3913cce)) +* **acir:** Add predicate to call opcode (https://github.com/AztecProtocol/aztec-packages/pull/5616) ([2bd006a](https://github.com/noir-lang/noir/commit/2bd006ae07499e8702b0fa9565855f0a5ef1a589)) +* **acir:** BrilligCall opcode (https://github.com/AztecProtocol/aztec-packages/pull/5709) ([0f9ae0a](https://github.com/noir-lang/noir/commit/0f9ae0ac1d68714b56ba4524aedcc67212494f1b)) +* **acir:** Program and witness stack structure (https://github.com/AztecProtocol/aztec-packages/pull/5149) ([13eb71b](https://github.com/noir-lang/noir/commit/13eb71b8de44eb6aad9c37943ad06fc73db589f5)) +* **acvm_js:** Execute program ([#4694](https://github.com/noir-lang/noir/issues/4694)) ([386f6d0](https://github.com/noir-lang/noir/commit/386f6d0a5822912db878285cb001032a7c0ff622)) +* **acvm:** Execute multiple circuits (https://github.com/AztecProtocol/aztec-packages/pull/5380) ([a0f7474](https://github.com/noir-lang/noir/commit/a0f7474ae6bd74132efdb945d2eb2383f3913cce)) +* Add bit size to const opcode (https://github.com/AztecProtocol/aztec-packages/pull/4385) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* Add CMOV instruction to brillig and brillig gen (https://github.com/AztecProtocol/aztec-packages/pull/5308) ([13eb71b](https://github.com/noir-lang/noir/commit/13eb71b8de44eb6aad9c37943ad06fc73db589f5)) +* Add expression width into acir (https://github.com/AztecProtocol/aztec-packages/pull/4014) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* Add instrumentation for tracking variables in debugging ([#4122](https://github.com/noir-lang/noir/issues/4122)) ([c58d691](https://github.com/noir-lang/noir/commit/c58d69141b54a918cd1675400c00bfd48720f896)) +* Add poseidon2 opcode implementation for acvm/brillig, and Noir ([#4398](https://github.com/noir-lang/noir/issues/4398)) ([10e8292](https://github.com/noir-lang/noir/commit/10e82920798380f50046e52db4a20ca205191ab7)) +* Add return values to aztec fns (https://github.com/AztecProtocol/aztec-packages/pull/5389) ([2bd006a](https://github.com/noir-lang/noir/commit/2bd006ae07499e8702b0fa9565855f0a5ef1a589)) +* Add support for overriding expression width ([#4117](https://github.com/noir-lang/noir/issues/4117)) ([c8026d5](https://github.com/noir-lang/noir/commit/c8026d557d535b10fe455165d6445076df7a03de)) +* Added cast opcode and cast calldata (https://github.com/AztecProtocol/aztec-packages/pull/4423) ([78ef013](https://github.com/noir-lang/noir/commit/78ef0134b82e76a73dadb6c7975def22290e3a1a)) +* Allow brillig to read arrays directly from memory (https://github.com/AztecProtocol/aztec-packages/pull/4460) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* Allow nested arrays and vectors in Brillig foreign calls (https://github.com/AztecProtocol/aztec-packages/pull/4478) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* Allow variables and stack trace inspection in the debugger ([#4184](https://github.com/noir-lang/noir/issues/4184)) ([bf263fc](https://github.com/noir-lang/noir/commit/bf263fc8d843940f328a90f6366edd2671fb2682)) +* Automatic NoteInterface and NoteGetterOptions auto select (https://github.com/AztecProtocol/aztec-packages/pull/4508) ([13eb71b](https://github.com/noir-lang/noir/commit/13eb71b8de44eb6aad9c37943ad06fc73db589f5)) +* **avm:** Back in avm context with macro - refactor context (https://github.com/AztecProtocol/aztec-packages/pull/4438) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* **avm:** Brillig CONST of size > u128 (https://github.com/AztecProtocol/aztec-packages/pull/5217) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* **avm:** Integrate AVM with initializers (https://github.com/AztecProtocol/aztec-packages/pull/5469) ([2bd006a](https://github.com/noir-lang/noir/commit/2bd006ae07499e8702b0fa9565855f0a5ef1a589)) +* **aztec-nr:** Initial work for aztec public vm macro (https://github.com/AztecProtocol/aztec-packages/pull/4400) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* Backpropagate constants in ACIR during optimization ([#3926](https://github.com/noir-lang/noir/issues/3926)) ([aad0da0](https://github.com/noir-lang/noir/commit/aad0da024c69663f42e6913e674682d5864b26ae)) +* Bit shift is restricted to u8 right operand ([#4907](https://github.com/noir-lang/noir/issues/4907)) ([c4b0369](https://github.com/noir-lang/noir/commit/c4b03691feca17ef268acab523292f3051f672ea)) +* Breaking changes from aztec-packages ([#3955](https://github.com/noir-lang/noir/issues/3955)) ([5be049e](https://github.com/noir-lang/noir/commit/5be049eee6c342649462282ee04f6411e6ea392c)) +* Brillig heterogeneous memory cells (https://github.com/AztecProtocol/aztec-packages/pull/5608) ([305bcdc](https://github.com/noir-lang/noir/commit/305bcdcbd01cb84dbaac900f14cb6cf867f83bda)) +* Brillig IR refactor (https://github.com/AztecProtocol/aztec-packages/pull/5233) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* Brillig pointer codegen and execution (https://github.com/AztecProtocol/aztec-packages/pull/5737) ([0f9ae0a](https://github.com/noir-lang/noir/commit/0f9ae0ac1d68714b56ba4524aedcc67212494f1b)) +* Brillig typed memory (https://github.com/AztecProtocol/aztec-packages/pull/5395) ([0bc18c4](https://github.com/noir-lang/noir/commit/0bc18c4f78171590dd58bded959f68f53a44cc8c)) +* Change backend width to 4 (https://github.com/AztecProtocol/aztec-packages/pull/5374) ([0f9ae0a](https://github.com/noir-lang/noir/commit/0f9ae0ac1d68714b56ba4524aedcc67212494f1b)) +* Check initializer msg.sender matches deployer from address preimage (https://github.com/AztecProtocol/aztec-packages/pull/5222) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* Contract interfaces and better function calls (https://github.com/AztecProtocol/aztec-packages/pull/5687) ([0f9ae0a](https://github.com/noir-lang/noir/commit/0f9ae0ac1d68714b56ba4524aedcc67212494f1b)) +* Contract_abi-exports (https://github.com/AztecProtocol/aztec-packages/pull/5386) ([2bd006a](https://github.com/noir-lang/noir/commit/2bd006ae07499e8702b0fa9565855f0a5ef1a589)) +* Evaluation of dynamic assert messages ([#4101](https://github.com/noir-lang/noir/issues/4101)) ([c284e01](https://github.com/noir-lang/noir/commit/c284e01bfe20ceae4414dc123624b5cbb8b66d09)) +* Handle `BrilligCall` opcodes in the debugger ([#4897](https://github.com/noir-lang/noir/issues/4897)) ([b380dc4](https://github.com/noir-lang/noir/commit/b380dc44de5c9f8de278ece3d531ebbc2c9238ba)) +* Impl of missing functionality in new key store (https://github.com/AztecProtocol/aztec-packages/pull/5750) ([0f9ae0a](https://github.com/noir-lang/noir/commit/0f9ae0ac1d68714b56ba4524aedcc67212494f1b)) +* Init storage macro (https://github.com/AztecProtocol/aztec-packages/pull/4200) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* Initial Earthly CI (https://github.com/AztecProtocol/aztec-packages/pull/5069) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* Internal as a macro (https://github.com/AztecProtocol/aztec-packages/pull/4898) ([5f57ebb](https://github.com/noir-lang/noir/commit/5f57ebb7ff4b810802f90699a10f4325ef904f2e)) +* **nargo:** Handle call stacks for multiple Acir calls ([#4711](https://github.com/noir-lang/noir/issues/4711)) ([5b23171](https://github.com/noir-lang/noir/commit/5b231714740447d82cde7cdbe65d4a8b46a31df4)) +* New brillig field operations and refactor of binary operations (https://github.com/AztecProtocol/aztec-packages/pull/5208) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* Note type ids (https://github.com/AztecProtocol/aztec-packages/pull/4500) ([78ef013](https://github.com/noir-lang/noir/commit/78ef0134b82e76a73dadb6c7975def22290e3a1a)) +* Remove replacement of boolean range opcodes with `AssertZero` opcodes ([#4107](https://github.com/noir-lang/noir/issues/4107)) ([dac0e87](https://github.com/noir-lang/noir/commit/dac0e87ee3be3446b92bbb12ef4832fd493fcee3)) +* Restore hashing args via slice for performance (https://github.com/AztecProtocol/aztec-packages/pull/5539) ([2bd006a](https://github.com/noir-lang/noir/commit/2bd006ae07499e8702b0fa9565855f0a5ef1a589)) +* Signed integer division and modulus in brillig gen (https://github.com/AztecProtocol/aztec-packages/pull/5279) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* **simulator:** Fetch return values at circuit execution (https://github.com/AztecProtocol/aztec-packages/pull/5642) ([305bcdc](https://github.com/noir-lang/noir/commit/305bcdcbd01cb84dbaac900f14cb6cf867f83bda)) +* Storage_layout and `#[aztec(storage)]` (https://github.com/AztecProtocol/aztec-packages/pull/5387) ([2bd006a](https://github.com/noir-lang/noir/commit/2bd006ae07499e8702b0fa9565855f0a5ef1a589)) +* Support contracts with no constructor (https://github.com/AztecProtocol/aztec-packages/pull/5175) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* Sync `aztec-packages` ([#4011](https://github.com/noir-lang/noir/issues/4011)) ([fee2452](https://github.com/noir-lang/noir/commit/fee24523c427c27f0bdaf98ea09a852a2da3e94c)) +* Sync commits from `aztec-packages` ([#4068](https://github.com/noir-lang/noir/issues/4068)) ([7a8f3a3](https://github.com/noir-lang/noir/commit/7a8f3a33b57875e681e3d81e667e3570a1cdbdcc)) +* Sync commits from `aztec-packages` ([#4144](https://github.com/noir-lang/noir/issues/4144)) ([0205d3b](https://github.com/noir-lang/noir/commit/0205d3b4ad0cf5ffd775a43eb5af273a772cf138)) +* Sync from aztec-packages ([#4483](https://github.com/noir-lang/noir/issues/4483)) ([fe8f277](https://github.com/noir-lang/noir/commit/fe8f2776ccfde29209a2c3fc162311c99e4f59be)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/5234) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/5286) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/5572) ([2bd006a](https://github.com/noir-lang/noir/commit/2bd006ae07499e8702b0fa9565855f0a5ef1a589)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/5619) ([2bd006a](https://github.com/noir-lang/noir/commit/2bd006ae07499e8702b0fa9565855f0a5ef1a589)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/5697) ([305bcdc](https://github.com/noir-lang/noir/commit/305bcdcbd01cb84dbaac900f14cb6cf867f83bda)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/5794) ([0f9ae0a](https://github.com/noir-lang/noir/commit/0f9ae0ac1d68714b56ba4524aedcc67212494f1b)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/5814) ([0f9ae0a](https://github.com/noir-lang/noir/commit/0f9ae0ac1d68714b56ba4524aedcc67212494f1b)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/5935) ([1b867b1](https://github.com/noir-lang/noir/commit/1b867b121fba5db3087ca845b4934e6732b23fd1)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/5955) ([1b867b1](https://github.com/noir-lang/noir/commit/1b867b121fba5db3087ca845b4934e6732b23fd1)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/5999) ([1b867b1](https://github.com/noir-lang/noir/commit/1b867b121fba5db3087ca845b4934e6732b23fd1)) +* Trap with revert data (https://github.com/AztecProtocol/aztec-packages/pull/5732) ([0f9ae0a](https://github.com/noir-lang/noir/commit/0f9ae0ac1d68714b56ba4524aedcc67212494f1b)) +* Use fixed size arrays in black box functions where sizes are known (https://github.com/AztecProtocol/aztec-packages/pull/5620) ([0f9ae0a](https://github.com/noir-lang/noir/commit/0f9ae0ac1d68714b56ba4524aedcc67212494f1b)) +* Variable length returns (https://github.com/AztecProtocol/aztec-packages/pull/5633) ([305bcdc](https://github.com/noir-lang/noir/commit/305bcdcbd01cb84dbaac900f14cb6cf867f83bda)) + + +### Bug Fixes + +* **acvm:** Mark outputs of Opcode::Call solvable ([#4708](https://github.com/noir-lang/noir/issues/4708)) ([8fea405](https://github.com/noir-lang/noir/commit/8fea40576f262bd5bb588923c0660d8967404e56)) +* Avoid huge unrolling in hash_args (https://github.com/AztecProtocol/aztec-packages/pull/5703) ([305bcdc](https://github.com/noir-lang/noir/commit/305bcdcbd01cb84dbaac900f14cb6cf867f83bda)) +* Catch panics from EC point creation (e.g. the point is at infinity) ([#4790](https://github.com/noir-lang/noir/issues/4790)) ([645dba1](https://github.com/noir-lang/noir/commit/645dba192f16ef34018828186ffb297422a8dc73)) +* Don't reuse brillig with slice arguments (https://github.com/AztecProtocol/aztec-packages/pull/5800) ([0f9ae0a](https://github.com/noir-lang/noir/commit/0f9ae0ac1d68714b56ba4524aedcc67212494f1b)) +* Issue 4682 and add solver for unconstrained bigintegers ([#4729](https://github.com/noir-lang/noir/issues/4729)) ([e4d33c1](https://github.com/noir-lang/noir/commit/e4d33c126a2795d9aaa6048d4e91b64cb4bbe4f2)) +* Noir test incorrect reporting (https://github.com/AztecProtocol/aztec-packages/pull/4925) ([5f57ebb](https://github.com/noir-lang/noir/commit/5f57ebb7ff4b810802f90699a10f4325ef904f2e)) +* Proper field inversion for bigints ([#4802](https://github.com/noir-lang/noir/issues/4802)) ([b46d0e3](https://github.com/noir-lang/noir/commit/b46d0e39f4252f8bbaa987f88d112e4c233b3d61)) +* Remove panic from `init_log_level` in `acvm_js` ([#4195](https://github.com/noir-lang/noir/issues/4195)) ([2e26530](https://github.com/noir-lang/noir/commit/2e26530bf53006c1ed4fee310bcaa905c95dd95b)) +* Return error rather instead of panicking on invalid circuit ([#3976](https://github.com/noir-lang/noir/issues/3976)) ([67201bf](https://github.com/noir-lang/noir/commit/67201bfc21a9c8858aa86be9cd47d463fb78d925)) + + +### Miscellaneous Chores + +* **acir:** Move `is_recursive` flag to be part of the circuit definition (https://github.com/AztecProtocol/aztec-packages/pull/4221) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* Move noir out of yarn-project (https://github.com/AztecProtocol/aztec-packages/pull/4479) ([78ef013](https://github.com/noir-lang/noir/commit/78ef0134b82e76a73dadb6c7975def22290e3a1a)) +* Remove fixed-length keccak256 (https://github.com/AztecProtocol/aztec-packages/pull/5617) ([305bcdc](https://github.com/noir-lang/noir/commit/305bcdcbd01cb84dbaac900f14cb6cf867f83bda)) +* Rename bigint_neg into bigint_sub (https://github.com/AztecProtocol/aztec-packages/pull/4420) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) + +## [0.44.0](https://github.com/noir-lang/noir/compare/v0.43.0...v0.44.0) (2024-04-24) + + +### ⚠ BREAKING CHANGES + +* contract interfaces and better function calls (https://github.com/AztecProtocol/aztec-packages/pull/5687) +* change backend width to 4 (https://github.com/AztecProtocol/aztec-packages/pull/5374) +* Use fixed size arrays in black box functions where sizes are known (https://github.com/AztecProtocol/aztec-packages/pull/5620) +* trap with revert data (https://github.com/AztecProtocol/aztec-packages/pull/5732) +* **acir:** BrilligCall opcode (https://github.com/AztecProtocol/aztec-packages/pull/5709) +* remove fixed-length keccak256 (https://github.com/AztecProtocol/aztec-packages/pull/5617) +* storage_layout and `#[aztec(storage)]` (https://github.com/AztecProtocol/aztec-packages/pull/5387) +* **acir:** Add predicate to call opcode (https://github.com/AztecProtocol/aztec-packages/pull/5616) +* contract_abi-exports (https://github.com/AztecProtocol/aztec-packages/pull/5386) +* Brillig typed memory (https://github.com/AztecProtocol/aztec-packages/pull/5395) +* **acir:** Program and witness stack structure (https://github.com/AztecProtocol/aztec-packages/pull/5149) +* automatic NoteInterface and NoteGetterOptions auto select (https://github.com/AztecProtocol/aztec-packages/pull/4508) +* Acir call opcode (https://github.com/AztecProtocol/aztec-packages/pull/4773) +* Support contracts with no constructor (https://github.com/AztecProtocol/aztec-packages/pull/5175) +* Internal as a macro (https://github.com/AztecProtocol/aztec-packages/pull/4898) +* move noir out of yarn-project (https://github.com/AztecProtocol/aztec-packages/pull/4479) +* note type ids (https://github.com/AztecProtocol/aztec-packages/pull/4500) +* rename bigint_neg into bigint_sub (https://github.com/AztecProtocol/aztec-packages/pull/4420) +* Add expression width into acir (https://github.com/AztecProtocol/aztec-packages/pull/4014) +* init storage macro (https://github.com/AztecProtocol/aztec-packages/pull/4200) +* **acir:** Move `is_recursive` flag to be part of the circuit definition (https://github.com/AztecProtocol/aztec-packages/pull/4221) +* Sync commits from `aztec-packages` ([#4144](https://github.com/noir-lang/noir/issues/4144)) +* Breaking changes from aztec-packages ([#3955](https://github.com/noir-lang/noir/issues/3955)) + +### Features + +* Acir call opcode (https://github.com/AztecProtocol/aztec-packages/pull/4773) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* **acir_gen:** Brillig stdlib ([#4848](https://github.com/noir-lang/noir/issues/4848)) ([0c8175c](https://github.com/noir-lang/noir/commit/0c8175cb539efd9427c73ae5af0d48abe688ebab)) +* **acir_gen:** Fold attribute at compile-time and initial non inlined ACIR (https://github.com/AztecProtocol/aztec-packages/pull/5341) ([a0f7474](https://github.com/noir-lang/noir/commit/a0f7474ae6bd74132efdb945d2eb2383f3913cce)) +* **acir:** Add predicate to call opcode (https://github.com/AztecProtocol/aztec-packages/pull/5616) ([2bd006a](https://github.com/noir-lang/noir/commit/2bd006ae07499e8702b0fa9565855f0a5ef1a589)) +* **acir:** BrilligCall opcode (https://github.com/AztecProtocol/aztec-packages/pull/5709) ([0f9ae0a](https://github.com/noir-lang/noir/commit/0f9ae0ac1d68714b56ba4524aedcc67212494f1b)) +* **acir:** Program and witness stack structure (https://github.com/AztecProtocol/aztec-packages/pull/5149) ([13eb71b](https://github.com/noir-lang/noir/commit/13eb71b8de44eb6aad9c37943ad06fc73db589f5)) +* **acvm_js:** Execute program ([#4694](https://github.com/noir-lang/noir/issues/4694)) ([386f6d0](https://github.com/noir-lang/noir/commit/386f6d0a5822912db878285cb001032a7c0ff622)) +* **acvm:** Execute multiple circuits (https://github.com/AztecProtocol/aztec-packages/pull/5380) ([a0f7474](https://github.com/noir-lang/noir/commit/a0f7474ae6bd74132efdb945d2eb2383f3913cce)) +* Add bit size to const opcode (https://github.com/AztecProtocol/aztec-packages/pull/4385) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* Add CMOV instruction to brillig and brillig gen (https://github.com/AztecProtocol/aztec-packages/pull/5308) ([13eb71b](https://github.com/noir-lang/noir/commit/13eb71b8de44eb6aad9c37943ad06fc73db589f5)) +* Add expression width into acir (https://github.com/AztecProtocol/aztec-packages/pull/4014) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* Add instrumentation for tracking variables in debugging ([#4122](https://github.com/noir-lang/noir/issues/4122)) ([c58d691](https://github.com/noir-lang/noir/commit/c58d69141b54a918cd1675400c00bfd48720f896)) +* Add poseidon2 opcode implementation for acvm/brillig, and Noir ([#4398](https://github.com/noir-lang/noir/issues/4398)) ([10e8292](https://github.com/noir-lang/noir/commit/10e82920798380f50046e52db4a20ca205191ab7)) +* Add return values to aztec fns (https://github.com/AztecProtocol/aztec-packages/pull/5389) ([2bd006a](https://github.com/noir-lang/noir/commit/2bd006ae07499e8702b0fa9565855f0a5ef1a589)) +* Add support for overriding expression width ([#4117](https://github.com/noir-lang/noir/issues/4117)) ([c8026d5](https://github.com/noir-lang/noir/commit/c8026d557d535b10fe455165d6445076df7a03de)) +* Added cast opcode and cast calldata (https://github.com/AztecProtocol/aztec-packages/pull/4423) ([78ef013](https://github.com/noir-lang/noir/commit/78ef0134b82e76a73dadb6c7975def22290e3a1a)) +* Allow brillig to read arrays directly from memory (https://github.com/AztecProtocol/aztec-packages/pull/4460) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* Allow nested arrays and vectors in Brillig foreign calls (https://github.com/AztecProtocol/aztec-packages/pull/4478) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* Allow variables and stack trace inspection in the debugger ([#4184](https://github.com/noir-lang/noir/issues/4184)) ([bf263fc](https://github.com/noir-lang/noir/commit/bf263fc8d843940f328a90f6366edd2671fb2682)) +* Automatic NoteInterface and NoteGetterOptions auto select (https://github.com/AztecProtocol/aztec-packages/pull/4508) ([13eb71b](https://github.com/noir-lang/noir/commit/13eb71b8de44eb6aad9c37943ad06fc73db589f5)) +* **avm:** Back in avm context with macro - refactor context (https://github.com/AztecProtocol/aztec-packages/pull/4438) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* **avm:** Brillig CONST of size > u128 (https://github.com/AztecProtocol/aztec-packages/pull/5217) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* **avm:** Integrate AVM with initializers (https://github.com/AztecProtocol/aztec-packages/pull/5469) ([2bd006a](https://github.com/noir-lang/noir/commit/2bd006ae07499e8702b0fa9565855f0a5ef1a589)) +* **aztec-nr:** Initial work for aztec public vm macro (https://github.com/AztecProtocol/aztec-packages/pull/4400) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* Backpropagate constants in ACIR during optimization ([#3926](https://github.com/noir-lang/noir/issues/3926)) ([aad0da0](https://github.com/noir-lang/noir/commit/aad0da024c69663f42e6913e674682d5864b26ae)) +* Breaking changes from aztec-packages ([#3955](https://github.com/noir-lang/noir/issues/3955)) ([5be049e](https://github.com/noir-lang/noir/commit/5be049eee6c342649462282ee04f6411e6ea392c)) +* Brillig heterogeneous memory cells (https://github.com/AztecProtocol/aztec-packages/pull/5608) ([305bcdc](https://github.com/noir-lang/noir/commit/305bcdcbd01cb84dbaac900f14cb6cf867f83bda)) +* Brillig IR refactor (https://github.com/AztecProtocol/aztec-packages/pull/5233) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* Brillig pointer codegen and execution (https://github.com/AztecProtocol/aztec-packages/pull/5737) ([0f9ae0a](https://github.com/noir-lang/noir/commit/0f9ae0ac1d68714b56ba4524aedcc67212494f1b)) +* Brillig typed memory (https://github.com/AztecProtocol/aztec-packages/pull/5395) ([0bc18c4](https://github.com/noir-lang/noir/commit/0bc18c4f78171590dd58bded959f68f53a44cc8c)) +* Change backend width to 4 (https://github.com/AztecProtocol/aztec-packages/pull/5374) ([0f9ae0a](https://github.com/noir-lang/noir/commit/0f9ae0ac1d68714b56ba4524aedcc67212494f1b)) +* Check initializer msg.sender matches deployer from address preimage (https://github.com/AztecProtocol/aztec-packages/pull/5222) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* Contract interfaces and better function calls (https://github.com/AztecProtocol/aztec-packages/pull/5687) ([0f9ae0a](https://github.com/noir-lang/noir/commit/0f9ae0ac1d68714b56ba4524aedcc67212494f1b)) +* Contract_abi-exports (https://github.com/AztecProtocol/aztec-packages/pull/5386) ([2bd006a](https://github.com/noir-lang/noir/commit/2bd006ae07499e8702b0fa9565855f0a5ef1a589)) +* Evaluation of dynamic assert messages ([#4101](https://github.com/noir-lang/noir/issues/4101)) ([c284e01](https://github.com/noir-lang/noir/commit/c284e01bfe20ceae4414dc123624b5cbb8b66d09)) +* Impl of missing functionality in new key store (https://github.com/AztecProtocol/aztec-packages/pull/5750) ([0f9ae0a](https://github.com/noir-lang/noir/commit/0f9ae0ac1d68714b56ba4524aedcc67212494f1b)) +* Init storage macro (https://github.com/AztecProtocol/aztec-packages/pull/4200) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* Initial Earthly CI (https://github.com/AztecProtocol/aztec-packages/pull/5069) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* Internal as a macro (https://github.com/AztecProtocol/aztec-packages/pull/4898) ([5f57ebb](https://github.com/noir-lang/noir/commit/5f57ebb7ff4b810802f90699a10f4325ef904f2e)) +* **nargo:** Handle call stacks for multiple Acir calls ([#4711](https://github.com/noir-lang/noir/issues/4711)) ([5b23171](https://github.com/noir-lang/noir/commit/5b231714740447d82cde7cdbe65d4a8b46a31df4)) +* New brillig field operations and refactor of binary operations (https://github.com/AztecProtocol/aztec-packages/pull/5208) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* Note type ids (https://github.com/AztecProtocol/aztec-packages/pull/4500) ([78ef013](https://github.com/noir-lang/noir/commit/78ef0134b82e76a73dadb6c7975def22290e3a1a)) +* Remove range constraints from witnesses which are constrained to be constants ([#3928](https://github.com/noir-lang/noir/issues/3928)) ([afe9c7a](https://github.com/noir-lang/noir/commit/afe9c7a38bb9d4245205d3aa46d4ce23d70a5671)) +* Remove replacement of boolean range opcodes with `AssertZero` opcodes ([#4107](https://github.com/noir-lang/noir/issues/4107)) ([dac0e87](https://github.com/noir-lang/noir/commit/dac0e87ee3be3446b92bbb12ef4832fd493fcee3)) +* Restore hashing args via slice for performance (https://github.com/AztecProtocol/aztec-packages/pull/5539) ([2bd006a](https://github.com/noir-lang/noir/commit/2bd006ae07499e8702b0fa9565855f0a5ef1a589)) +* Signed integer division and modulus in brillig gen (https://github.com/AztecProtocol/aztec-packages/pull/5279) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* **simulator:** Fetch return values at circuit execution (https://github.com/AztecProtocol/aztec-packages/pull/5642) ([305bcdc](https://github.com/noir-lang/noir/commit/305bcdcbd01cb84dbaac900f14cb6cf867f83bda)) +* Storage_layout and `#[aztec(storage)]` (https://github.com/AztecProtocol/aztec-packages/pull/5387) ([2bd006a](https://github.com/noir-lang/noir/commit/2bd006ae07499e8702b0fa9565855f0a5ef1a589)) +* Support contracts with no constructor (https://github.com/AztecProtocol/aztec-packages/pull/5175) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* Sync `aztec-packages` ([#4011](https://github.com/noir-lang/noir/issues/4011)) ([fee2452](https://github.com/noir-lang/noir/commit/fee24523c427c27f0bdaf98ea09a852a2da3e94c)) +* Sync commits from `aztec-packages` ([#4068](https://github.com/noir-lang/noir/issues/4068)) ([7a8f3a3](https://github.com/noir-lang/noir/commit/7a8f3a33b57875e681e3d81e667e3570a1cdbdcc)) +* Sync commits from `aztec-packages` ([#4144](https://github.com/noir-lang/noir/issues/4144)) ([0205d3b](https://github.com/noir-lang/noir/commit/0205d3b4ad0cf5ffd775a43eb5af273a772cf138)) +* Sync from aztec-packages ([#4483](https://github.com/noir-lang/noir/issues/4483)) ([fe8f277](https://github.com/noir-lang/noir/commit/fe8f2776ccfde29209a2c3fc162311c99e4f59be)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/5234) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/5286) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/5572) ([2bd006a](https://github.com/noir-lang/noir/commit/2bd006ae07499e8702b0fa9565855f0a5ef1a589)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/5619) ([2bd006a](https://github.com/noir-lang/noir/commit/2bd006ae07499e8702b0fa9565855f0a5ef1a589)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/5697) ([305bcdc](https://github.com/noir-lang/noir/commit/305bcdcbd01cb84dbaac900f14cb6cf867f83bda)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/5794) ([0f9ae0a](https://github.com/noir-lang/noir/commit/0f9ae0ac1d68714b56ba4524aedcc67212494f1b)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/5814) ([0f9ae0a](https://github.com/noir-lang/noir/commit/0f9ae0ac1d68714b56ba4524aedcc67212494f1b)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/5935) ([1b867b1](https://github.com/noir-lang/noir/commit/1b867b121fba5db3087ca845b4934e6732b23fd1)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/5955) ([1b867b1](https://github.com/noir-lang/noir/commit/1b867b121fba5db3087ca845b4934e6732b23fd1)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/5999) ([1b867b1](https://github.com/noir-lang/noir/commit/1b867b121fba5db3087ca845b4934e6732b23fd1)) +* Trap with revert data (https://github.com/AztecProtocol/aztec-packages/pull/5732) ([0f9ae0a](https://github.com/noir-lang/noir/commit/0f9ae0ac1d68714b56ba4524aedcc67212494f1b)) +* Use fixed size arrays in black box functions where sizes are known (https://github.com/AztecProtocol/aztec-packages/pull/5620) ([0f9ae0a](https://github.com/noir-lang/noir/commit/0f9ae0ac1d68714b56ba4524aedcc67212494f1b)) +* Variable length returns (https://github.com/AztecProtocol/aztec-packages/pull/5633) ([305bcdc](https://github.com/noir-lang/noir/commit/305bcdcbd01cb84dbaac900f14cb6cf867f83bda)) + + +### Bug Fixes + +* **acvm:** Mark outputs of Opcode::Call solvable ([#4708](https://github.com/noir-lang/noir/issues/4708)) ([8fea405](https://github.com/noir-lang/noir/commit/8fea40576f262bd5bb588923c0660d8967404e56)) +* Avoid huge unrolling in hash_args (https://github.com/AztecProtocol/aztec-packages/pull/5703) ([305bcdc](https://github.com/noir-lang/noir/commit/305bcdcbd01cb84dbaac900f14cb6cf867f83bda)) +* Catch panics from EC point creation (e.g. the point is at infinity) ([#4790](https://github.com/noir-lang/noir/issues/4790)) ([645dba1](https://github.com/noir-lang/noir/commit/645dba192f16ef34018828186ffb297422a8dc73)) +* Don't reuse brillig with slice arguments (https://github.com/AztecProtocol/aztec-packages/pull/5800) ([0f9ae0a](https://github.com/noir-lang/noir/commit/0f9ae0ac1d68714b56ba4524aedcc67212494f1b)) +* Issue 4682 and add solver for unconstrained bigintegers ([#4729](https://github.com/noir-lang/noir/issues/4729)) ([e4d33c1](https://github.com/noir-lang/noir/commit/e4d33c126a2795d9aaa6048d4e91b64cb4bbe4f2)) +* Noir test incorrect reporting (https://github.com/AztecProtocol/aztec-packages/pull/4925) ([5f57ebb](https://github.com/noir-lang/noir/commit/5f57ebb7ff4b810802f90699a10f4325ef904f2e)) +* Proper field inversion for bigints ([#4802](https://github.com/noir-lang/noir/issues/4802)) ([b46d0e3](https://github.com/noir-lang/noir/commit/b46d0e39f4252f8bbaa987f88d112e4c233b3d61)) +* Remove panic from `init_log_level` in `acvm_js` ([#4195](https://github.com/noir-lang/noir/issues/4195)) ([2e26530](https://github.com/noir-lang/noir/commit/2e26530bf53006c1ed4fee310bcaa905c95dd95b)) +* Return error rather instead of panicking on invalid circuit ([#3976](https://github.com/noir-lang/noir/issues/3976)) ([67201bf](https://github.com/noir-lang/noir/commit/67201bfc21a9c8858aa86be9cd47d463fb78d925)) + + +### Miscellaneous Chores + +* **acir:** Move `is_recursive` flag to be part of the circuit definition (https://github.com/AztecProtocol/aztec-packages/pull/4221) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* Move noir out of yarn-project (https://github.com/AztecProtocol/aztec-packages/pull/4479) ([78ef013](https://github.com/noir-lang/noir/commit/78ef0134b82e76a73dadb6c7975def22290e3a1a)) +* Remove fixed-length keccak256 (https://github.com/AztecProtocol/aztec-packages/pull/5617) ([305bcdc](https://github.com/noir-lang/noir/commit/305bcdcbd01cb84dbaac900f14cb6cf867f83bda)) +* Rename bigint_neg into bigint_sub (https://github.com/AztecProtocol/aztec-packages/pull/4420) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) + +## [0.43.0](https://github.com/noir-lang/noir/compare/v0.42.0...v0.43.0) (2024-04-10) + + +### ⚠ BREAKING CHANGES + +* Brillig typed memory (https://github.com/AztecProtocol/aztec-packages/pull/5395) +* **acir:** Program and witness stack structure (https://github.com/AztecProtocol/aztec-packages/pull/5149) +* automatic NoteInterface and NoteGetterOptions auto select (https://github.com/AztecProtocol/aztec-packages/pull/4508) +* Acir call opcode (https://github.com/AztecProtocol/aztec-packages/pull/4773) +* Support contracts with no constructor (https://github.com/AztecProtocol/aztec-packages/pull/5175) +* Internal as a macro (https://github.com/AztecProtocol/aztec-packages/pull/4898) +* move noir out of yarn-project (https://github.com/AztecProtocol/aztec-packages/pull/4479) +* note type ids (https://github.com/AztecProtocol/aztec-packages/pull/4500) +* rename bigint_neg into bigint_sub (https://github.com/AztecProtocol/aztec-packages/pull/4420) +* Add expression width into acir (https://github.com/AztecProtocol/aztec-packages/pull/4014) +* init storage macro (https://github.com/AztecProtocol/aztec-packages/pull/4200) +* **acir:** Move `is_recursive` flag to be part of the circuit definition (https://github.com/AztecProtocol/aztec-packages/pull/4221) +* Sync commits from `aztec-packages` ([#4144](https://github.com/noir-lang/noir/issues/4144)) +* Breaking changes from aztec-packages ([#3955](https://github.com/noir-lang/noir/issues/3955)) +* Rename Arithmetic opcode to AssertZero ([#3840](https://github.com/noir-lang/noir/issues/3840)) +* Remove unused methods on ACIR opcodes ([#3841](https://github.com/noir-lang/noir/issues/3841)) + +### Features + +* Acir call opcode (https://github.com/AztecProtocol/aztec-packages/pull/4773) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* **acir_gen:** Fold attribute at compile-time and initial non inlined ACIR (https://github.com/AztecProtocol/aztec-packages/pull/5341) ([a0f7474](https://github.com/noir-lang/noir/commit/a0f7474ae6bd74132efdb945d2eb2383f3913cce)) +* **acir:** Program and witness stack structure (https://github.com/AztecProtocol/aztec-packages/pull/5149) ([13eb71b](https://github.com/noir-lang/noir/commit/13eb71b8de44eb6aad9c37943ad06fc73db589f5)) +* **acvm_js:** Execute program ([#4694](https://github.com/noir-lang/noir/issues/4694)) ([386f6d0](https://github.com/noir-lang/noir/commit/386f6d0a5822912db878285cb001032a7c0ff622)) +* **acvm:** Execute multiple circuits (https://github.com/AztecProtocol/aztec-packages/pull/5380) ([a0f7474](https://github.com/noir-lang/noir/commit/a0f7474ae6bd74132efdb945d2eb2383f3913cce)) +* Add bit size to const opcode (https://github.com/AztecProtocol/aztec-packages/pull/4385) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* Add CMOV instruction to brillig and brillig gen (https://github.com/AztecProtocol/aztec-packages/pull/5308) ([13eb71b](https://github.com/noir-lang/noir/commit/13eb71b8de44eb6aad9c37943ad06fc73db589f5)) +* Add expression width into acir (https://github.com/AztecProtocol/aztec-packages/pull/4014) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* Add instrumentation for tracking variables in debugging ([#4122](https://github.com/noir-lang/noir/issues/4122)) ([c58d691](https://github.com/noir-lang/noir/commit/c58d69141b54a918cd1675400c00bfd48720f896)) +* Add poseidon2 opcode implementation for acvm/brillig, and Noir ([#4398](https://github.com/noir-lang/noir/issues/4398)) ([10e8292](https://github.com/noir-lang/noir/commit/10e82920798380f50046e52db4a20ca205191ab7)) +* Add support for overriding expression width ([#4117](https://github.com/noir-lang/noir/issues/4117)) ([c8026d5](https://github.com/noir-lang/noir/commit/c8026d557d535b10fe455165d6445076df7a03de)) +* Added cast opcode and cast calldata (https://github.com/AztecProtocol/aztec-packages/pull/4423) ([78ef013](https://github.com/noir-lang/noir/commit/78ef0134b82e76a73dadb6c7975def22290e3a1a)) +* Allow brillig to read arrays directly from memory (https://github.com/AztecProtocol/aztec-packages/pull/4460) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* Allow nested arrays and vectors in Brillig foreign calls (https://github.com/AztecProtocol/aztec-packages/pull/4478) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* Allow variables and stack trace inspection in the debugger ([#4184](https://github.com/noir-lang/noir/issues/4184)) ([bf263fc](https://github.com/noir-lang/noir/commit/bf263fc8d843940f328a90f6366edd2671fb2682)) +* Automatic NoteInterface and NoteGetterOptions auto select (https://github.com/AztecProtocol/aztec-packages/pull/4508) ([13eb71b](https://github.com/noir-lang/noir/commit/13eb71b8de44eb6aad9c37943ad06fc73db589f5)) +* **avm:** Back in avm context with macro - refactor context (https://github.com/AztecProtocol/aztec-packages/pull/4438) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* **avm:** Brillig CONST of size > u128 (https://github.com/AztecProtocol/aztec-packages/pull/5217) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* **aztec-nr:** Initial work for aztec public vm macro (https://github.com/AztecProtocol/aztec-packages/pull/4400) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* Backpropagate constants in ACIR during optimization ([#3926](https://github.com/noir-lang/noir/issues/3926)) ([aad0da0](https://github.com/noir-lang/noir/commit/aad0da024c69663f42e6913e674682d5864b26ae)) +* Breaking changes from aztec-packages ([#3955](https://github.com/noir-lang/noir/issues/3955)) ([5be049e](https://github.com/noir-lang/noir/commit/5be049eee6c342649462282ee04f6411e6ea392c)) +* Brillig IR refactor (https://github.com/AztecProtocol/aztec-packages/pull/5233) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* Brillig typed memory (https://github.com/AztecProtocol/aztec-packages/pull/5395) ([0bc18c4](https://github.com/noir-lang/noir/commit/0bc18c4f78171590dd58bded959f68f53a44cc8c)) +* Check initializer msg.sender matches deployer from address preimage (https://github.com/AztecProtocol/aztec-packages/pull/5222) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* Evaluation of dynamic assert messages ([#4101](https://github.com/noir-lang/noir/issues/4101)) ([c284e01](https://github.com/noir-lang/noir/commit/c284e01bfe20ceae4414dc123624b5cbb8b66d09)) +* Init storage macro (https://github.com/AztecProtocol/aztec-packages/pull/4200) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* Initial Earthly CI (https://github.com/AztecProtocol/aztec-packages/pull/5069) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* Internal as a macro (https://github.com/AztecProtocol/aztec-packages/pull/4898) ([5f57ebb](https://github.com/noir-lang/noir/commit/5f57ebb7ff4b810802f90699a10f4325ef904f2e)) +* New brillig field operations and refactor of binary operations (https://github.com/AztecProtocol/aztec-packages/pull/5208) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* Note type ids (https://github.com/AztecProtocol/aztec-packages/pull/4500) ([78ef013](https://github.com/noir-lang/noir/commit/78ef0134b82e76a73dadb6c7975def22290e3a1a)) +* Remove range constraints from witnesses which are constrained to be constants ([#3928](https://github.com/noir-lang/noir/issues/3928)) ([afe9c7a](https://github.com/noir-lang/noir/commit/afe9c7a38bb9d4245205d3aa46d4ce23d70a5671)) +* Remove replacement of boolean range opcodes with `AssertZero` opcodes ([#4107](https://github.com/noir-lang/noir/issues/4107)) ([dac0e87](https://github.com/noir-lang/noir/commit/dac0e87ee3be3446b92bbb12ef4832fd493fcee3)) +* Signed integer division and modulus in brillig gen (https://github.com/AztecProtocol/aztec-packages/pull/5279) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* Support contracts with no constructor (https://github.com/AztecProtocol/aztec-packages/pull/5175) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* Sync `aztec-packages` ([#4011](https://github.com/noir-lang/noir/issues/4011)) ([fee2452](https://github.com/noir-lang/noir/commit/fee24523c427c27f0bdaf98ea09a852a2da3e94c)) +* Sync commits from `aztec-packages` ([#4068](https://github.com/noir-lang/noir/issues/4068)) ([7a8f3a3](https://github.com/noir-lang/noir/commit/7a8f3a33b57875e681e3d81e667e3570a1cdbdcc)) +* Sync commits from `aztec-packages` ([#4144](https://github.com/noir-lang/noir/issues/4144)) ([0205d3b](https://github.com/noir-lang/noir/commit/0205d3b4ad0cf5ffd775a43eb5af273a772cf138)) +* Sync from aztec-packages ([#4483](https://github.com/noir-lang/noir/issues/4483)) ([fe8f277](https://github.com/noir-lang/noir/commit/fe8f2776ccfde29209a2c3fc162311c99e4f59be)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/5234) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/5286) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) + + +### Bug Fixes + +* **acvm:** Mark outputs of Opcode::Call solvable ([#4708](https://github.com/noir-lang/noir/issues/4708)) ([8fea405](https://github.com/noir-lang/noir/commit/8fea40576f262bd5bb588923c0660d8967404e56)) +* Noir test incorrect reporting (https://github.com/AztecProtocol/aztec-packages/pull/4925) ([5f57ebb](https://github.com/noir-lang/noir/commit/5f57ebb7ff4b810802f90699a10f4325ef904f2e)) +* Remove panic from `init_log_level` in `acvm_js` ([#4195](https://github.com/noir-lang/noir/issues/4195)) ([2e26530](https://github.com/noir-lang/noir/commit/2e26530bf53006c1ed4fee310bcaa905c95dd95b)) +* Return error rather instead of panicking on invalid circuit ([#3976](https://github.com/noir-lang/noir/issues/3976)) ([67201bf](https://github.com/noir-lang/noir/commit/67201bfc21a9c8858aa86be9cd47d463fb78d925)) + + +### Miscellaneous Chores + +* **acir:** Move `is_recursive` flag to be part of the circuit definition (https://github.com/AztecProtocol/aztec-packages/pull/4221) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* Move noir out of yarn-project (https://github.com/AztecProtocol/aztec-packages/pull/4479) ([78ef013](https://github.com/noir-lang/noir/commit/78ef0134b82e76a73dadb6c7975def22290e3a1a)) +* Remove unused methods on ACIR opcodes ([#3841](https://github.com/noir-lang/noir/issues/3841)) ([9e5d0e8](https://github.com/noir-lang/noir/commit/9e5d0e813d61a0bfb5ee68174ed287c5a20f1579)) +* Rename Arithmetic opcode to AssertZero ([#3840](https://github.com/noir-lang/noir/issues/3840)) ([836f171](https://github.com/noir-lang/noir/commit/836f17145c2901060706294461c2d282dd121b3e)) +* Rename bigint_neg into bigint_sub (https://github.com/AztecProtocol/aztec-packages/pull/4420) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) + +## [0.42.0](https://github.com/noir-lang/noir/compare/v0.41.0...v0.42.0) (2024-03-25) + + +### ⚠ BREAKING CHANGES + +* **acir:** Program and witness stack structure (https://github.com/AztecProtocol/aztec-packages/pull/5149) +* automatic NoteInterface and NoteGetterOptions auto select (https://github.com/AztecProtocol/aztec-packages/pull/4508) +* Acir call opcode (https://github.com/AztecProtocol/aztec-packages/pull/4773) +* Support contracts with no constructor (https://github.com/AztecProtocol/aztec-packages/pull/5175) +* Internal as a macro (https://github.com/AztecProtocol/aztec-packages/pull/4898) +* move noir out of yarn-project (https://github.com/AztecProtocol/aztec-packages/pull/4479) +* note type ids (https://github.com/AztecProtocol/aztec-packages/pull/4500) +* rename bigint_neg into bigint_sub (https://github.com/AztecProtocol/aztec-packages/pull/4420) +* Add expression width into acir (https://github.com/AztecProtocol/aztec-packages/pull/4014) +* init storage macro (https://github.com/AztecProtocol/aztec-packages/pull/4200) +* **acir:** Move `is_recursive` flag to be part of the circuit definition (https://github.com/AztecProtocol/aztec-packages/pull/4221) +* Sync commits from `aztec-packages` ([#4144](https://github.com/noir-lang/noir/issues/4144)) +* Breaking changes from aztec-packages ([#3955](https://github.com/noir-lang/noir/issues/3955)) +* Rename Arithmetic opcode to AssertZero ([#3840](https://github.com/noir-lang/noir/issues/3840)) +* Remove unused methods on ACIR opcodes ([#3841](https://github.com/noir-lang/noir/issues/3841)) +* Remove partial backend feature ([#3805](https://github.com/noir-lang/noir/issues/3805)) + +### Features + +* Acir call opcode (https://github.com/AztecProtocol/aztec-packages/pull/4773) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* **acir:** Program and witness stack structure (https://github.com/AztecProtocol/aztec-packages/pull/5149) ([13eb71b](https://github.com/noir-lang/noir/commit/13eb71b8de44eb6aad9c37943ad06fc73db589f5)) +* Add bit size to const opcode (https://github.com/AztecProtocol/aztec-packages/pull/4385) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* Add CMOV instruction to brillig and brillig gen (https://github.com/AztecProtocol/aztec-packages/pull/5308) ([13eb71b](https://github.com/noir-lang/noir/commit/13eb71b8de44eb6aad9c37943ad06fc73db589f5)) +* Add expression width into acir (https://github.com/AztecProtocol/aztec-packages/pull/4014) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* Add instrumentation for tracking variables in debugging ([#4122](https://github.com/noir-lang/noir/issues/4122)) ([c58d691](https://github.com/noir-lang/noir/commit/c58d69141b54a918cd1675400c00bfd48720f896)) +* Add poseidon2 opcode implementation for acvm/brillig, and Noir ([#4398](https://github.com/noir-lang/noir/issues/4398)) ([10e8292](https://github.com/noir-lang/noir/commit/10e82920798380f50046e52db4a20ca205191ab7)) +* Add support for overriding expression width ([#4117](https://github.com/noir-lang/noir/issues/4117)) ([c8026d5](https://github.com/noir-lang/noir/commit/c8026d557d535b10fe455165d6445076df7a03de)) +* Added cast opcode and cast calldata (https://github.com/AztecProtocol/aztec-packages/pull/4423) ([78ef013](https://github.com/noir-lang/noir/commit/78ef0134b82e76a73dadb6c7975def22290e3a1a)) +* Allow brillig to read arrays directly from memory (https://github.com/AztecProtocol/aztec-packages/pull/4460) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* Allow nested arrays and vectors in Brillig foreign calls (https://github.com/AztecProtocol/aztec-packages/pull/4478) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* Allow variables and stack trace inspection in the debugger ([#4184](https://github.com/noir-lang/noir/issues/4184)) ([bf263fc](https://github.com/noir-lang/noir/commit/bf263fc8d843940f328a90f6366edd2671fb2682)) +* Automatic NoteInterface and NoteGetterOptions auto select (https://github.com/AztecProtocol/aztec-packages/pull/4508) ([13eb71b](https://github.com/noir-lang/noir/commit/13eb71b8de44eb6aad9c37943ad06fc73db589f5)) +* **avm:** Back in avm context with macro - refactor context (https://github.com/AztecProtocol/aztec-packages/pull/4438) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* **avm:** Brillig CONST of size > u128 (https://github.com/AztecProtocol/aztec-packages/pull/5217) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* **aztec-nr:** Initial work for aztec public vm macro (https://github.com/AztecProtocol/aztec-packages/pull/4400) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* Aztec-packages ([#3754](https://github.com/noir-lang/noir/issues/3754)) ([c043265](https://github.com/noir-lang/noir/commit/c043265e550b59bd4296504826fe15d3ce3e9ad2)) +* Backpropagate constants in ACIR during optimization ([#3926](https://github.com/noir-lang/noir/issues/3926)) ([aad0da0](https://github.com/noir-lang/noir/commit/aad0da024c69663f42e6913e674682d5864b26ae)) +* Breaking changes from aztec-packages ([#3955](https://github.com/noir-lang/noir/issues/3955)) ([5be049e](https://github.com/noir-lang/noir/commit/5be049eee6c342649462282ee04f6411e6ea392c)) +* Brillig IR refactor (https://github.com/AztecProtocol/aztec-packages/pull/5233) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* Check initializer msg.sender matches deployer from address preimage (https://github.com/AztecProtocol/aztec-packages/pull/5222) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* Evaluation of dynamic assert messages ([#4101](https://github.com/noir-lang/noir/issues/4101)) ([c284e01](https://github.com/noir-lang/noir/commit/c284e01bfe20ceae4414dc123624b5cbb8b66d09)) +* Init storage macro (https://github.com/AztecProtocol/aztec-packages/pull/4200) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* Initial Earthly CI (https://github.com/AztecProtocol/aztec-packages/pull/5069) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* Internal as a macro (https://github.com/AztecProtocol/aztec-packages/pull/4898) ([5f57ebb](https://github.com/noir-lang/noir/commit/5f57ebb7ff4b810802f90699a10f4325ef904f2e)) +* New brillig field operations and refactor of binary operations (https://github.com/AztecProtocol/aztec-packages/pull/5208) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* Note type ids (https://github.com/AztecProtocol/aztec-packages/pull/4500) ([78ef013](https://github.com/noir-lang/noir/commit/78ef0134b82e76a73dadb6c7975def22290e3a1a)) +* Remove range constraints from witnesses which are constrained to be constants ([#3928](https://github.com/noir-lang/noir/issues/3928)) ([afe9c7a](https://github.com/noir-lang/noir/commit/afe9c7a38bb9d4245205d3aa46d4ce23d70a5671)) +* Remove replacement of boolean range opcodes with `AssertZero` opcodes ([#4107](https://github.com/noir-lang/noir/issues/4107)) ([dac0e87](https://github.com/noir-lang/noir/commit/dac0e87ee3be3446b92bbb12ef4832fd493fcee3)) +* Signed integer division and modulus in brillig gen (https://github.com/AztecProtocol/aztec-packages/pull/5279) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* Speed up transformation of debug messages ([#3815](https://github.com/noir-lang/noir/issues/3815)) ([2a8af1e](https://github.com/noir-lang/noir/commit/2a8af1e4141ffff61547ee1c2837a6392bd5db48)) +* Support contracts with no constructor (https://github.com/AztecProtocol/aztec-packages/pull/5175) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* Sync `aztec-packages` ([#4011](https://github.com/noir-lang/noir/issues/4011)) ([fee2452](https://github.com/noir-lang/noir/commit/fee24523c427c27f0bdaf98ea09a852a2da3e94c)) +* Sync commits from `aztec-packages` ([#4068](https://github.com/noir-lang/noir/issues/4068)) ([7a8f3a3](https://github.com/noir-lang/noir/commit/7a8f3a33b57875e681e3d81e667e3570a1cdbdcc)) +* Sync commits from `aztec-packages` ([#4144](https://github.com/noir-lang/noir/issues/4144)) ([0205d3b](https://github.com/noir-lang/noir/commit/0205d3b4ad0cf5ffd775a43eb5af273a772cf138)) +* Sync from aztec-packages ([#4483](https://github.com/noir-lang/noir/issues/4483)) ([fe8f277](https://github.com/noir-lang/noir/commit/fe8f2776ccfde29209a2c3fc162311c99e4f59be)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/5234) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/5286) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) + + +### Bug Fixes + +* Deserialize odd length hex literals ([#3747](https://github.com/noir-lang/noir/issues/3747)) ([4000fb2](https://github.com/noir-lang/noir/commit/4000fb279221eb07187d657bfaa7f1c7b311abf2)) +* Noir test incorrect reporting (https://github.com/AztecProtocol/aztec-packages/pull/4925) ([5f57ebb](https://github.com/noir-lang/noir/commit/5f57ebb7ff4b810802f90699a10f4325ef904f2e)) +* Remove panic from `init_log_level` in `acvm_js` ([#4195](https://github.com/noir-lang/noir/issues/4195)) ([2e26530](https://github.com/noir-lang/noir/commit/2e26530bf53006c1ed4fee310bcaa905c95dd95b)) +* Return error rather instead of panicking on invalid circuit ([#3976](https://github.com/noir-lang/noir/issues/3976)) ([67201bf](https://github.com/noir-lang/noir/commit/67201bfc21a9c8858aa86be9cd47d463fb78d925)) + + +### Miscellaneous Chores + +* **acir:** Move `is_recursive` flag to be part of the circuit definition (https://github.com/AztecProtocol/aztec-packages/pull/4221) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* Move noir out of yarn-project (https://github.com/AztecProtocol/aztec-packages/pull/4479) ([78ef013](https://github.com/noir-lang/noir/commit/78ef0134b82e76a73dadb6c7975def22290e3a1a)) +* Remove partial backend feature ([#3805](https://github.com/noir-lang/noir/issues/3805)) ([0383100](https://github.com/noir-lang/noir/commit/0383100853a80a5b28b797cdfeae0d271f1b7805)) +* Remove unused methods on ACIR opcodes ([#3841](https://github.com/noir-lang/noir/issues/3841)) ([9e5d0e8](https://github.com/noir-lang/noir/commit/9e5d0e813d61a0bfb5ee68174ed287c5a20f1579)) +* Rename Arithmetic opcode to AssertZero ([#3840](https://github.com/noir-lang/noir/issues/3840)) ([836f171](https://github.com/noir-lang/noir/commit/836f17145c2901060706294461c2d282dd121b3e)) +* Rename bigint_neg into bigint_sub (https://github.com/AztecProtocol/aztec-packages/pull/4420) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) + +## [0.41.0](https://github.com/noir-lang/noir/compare/v0.40.0...v0.41.0) (2024-03-11) + + +### ⚠ BREAKING CHANGES + +* Internal as a macro (https://github.com/AztecProtocol/aztec-packages/pull/4898) +* move noir out of yarn-project (https://github.com/AztecProtocol/aztec-packages/pull/4479) +* note type ids (https://github.com/AztecProtocol/aztec-packages/pull/4500) +* rename bigint_neg into bigint_sub (https://github.com/AztecProtocol/aztec-packages/pull/4420) +* Add expression width into acir (https://github.com/AztecProtocol/aztec-packages/pull/4014) +* init storage macro (https://github.com/AztecProtocol/aztec-packages/pull/4200) +* **acir:** Move `is_recursive` flag to be part of the circuit definition (https://github.com/AztecProtocol/aztec-packages/pull/4221) +* Sync commits from `aztec-packages` ([#4144](https://github.com/noir-lang/noir/issues/4144)) +* Breaking changes from aztec-packages ([#3955](https://github.com/noir-lang/noir/issues/3955)) +* Rename Arithmetic opcode to AssertZero ([#3840](https://github.com/noir-lang/noir/issues/3840)) +* Remove unused methods on ACIR opcodes ([#3841](https://github.com/noir-lang/noir/issues/3841)) +* Remove partial backend feature ([#3805](https://github.com/noir-lang/noir/issues/3805)) + +### Features + +* Add bit size to const opcode (https://github.com/AztecProtocol/aztec-packages/pull/4385) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* Add expression width into acir (https://github.com/AztecProtocol/aztec-packages/pull/4014) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* Add instrumentation for tracking variables in debugging ([#4122](https://github.com/noir-lang/noir/issues/4122)) ([c58d691](https://github.com/noir-lang/noir/commit/c58d69141b54a918cd1675400c00bfd48720f896)) +* Add poseidon2 opcode implementation for acvm/brillig, and Noir ([#4398](https://github.com/noir-lang/noir/issues/4398)) ([10e8292](https://github.com/noir-lang/noir/commit/10e82920798380f50046e52db4a20ca205191ab7)) +* Add support for overriding expression width ([#4117](https://github.com/noir-lang/noir/issues/4117)) ([c8026d5](https://github.com/noir-lang/noir/commit/c8026d557d535b10fe455165d6445076df7a03de)) +* Added cast opcode and cast calldata (https://github.com/AztecProtocol/aztec-packages/pull/4423) ([78ef013](https://github.com/noir-lang/noir/commit/78ef0134b82e76a73dadb6c7975def22290e3a1a)) +* Allow brillig to read arrays directly from memory (https://github.com/AztecProtocol/aztec-packages/pull/4460) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* Allow nested arrays and vectors in Brillig foreign calls (https://github.com/AztecProtocol/aztec-packages/pull/4478) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* Allow variables and stack trace inspection in the debugger ([#4184](https://github.com/noir-lang/noir/issues/4184)) ([bf263fc](https://github.com/noir-lang/noir/commit/bf263fc8d843940f328a90f6366edd2671fb2682)) +* **avm:** Back in avm context with macro - refactor context (https://github.com/AztecProtocol/aztec-packages/pull/4438) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* **aztec-nr:** Initial work for aztec public vm macro (https://github.com/AztecProtocol/aztec-packages/pull/4400) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* Aztec-packages ([#3754](https://github.com/noir-lang/noir/issues/3754)) ([c043265](https://github.com/noir-lang/noir/commit/c043265e550b59bd4296504826fe15d3ce3e9ad2)) +* Backpropagate constants in ACIR during optimization ([#3926](https://github.com/noir-lang/noir/issues/3926)) ([aad0da0](https://github.com/noir-lang/noir/commit/aad0da024c69663f42e6913e674682d5864b26ae)) +* Breaking changes from aztec-packages ([#3955](https://github.com/noir-lang/noir/issues/3955)) ([5be049e](https://github.com/noir-lang/noir/commit/5be049eee6c342649462282ee04f6411e6ea392c)) +* Evaluation of dynamic assert messages ([#4101](https://github.com/noir-lang/noir/issues/4101)) ([c284e01](https://github.com/noir-lang/noir/commit/c284e01bfe20ceae4414dc123624b5cbb8b66d09)) +* Init storage macro (https://github.com/AztecProtocol/aztec-packages/pull/4200) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* Internal as a macro (https://github.com/AztecProtocol/aztec-packages/pull/4898) ([5f57ebb](https://github.com/noir-lang/noir/commit/5f57ebb7ff4b810802f90699a10f4325ef904f2e)) +* Note type ids (https://github.com/AztecProtocol/aztec-packages/pull/4500) ([78ef013](https://github.com/noir-lang/noir/commit/78ef0134b82e76a73dadb6c7975def22290e3a1a)) +* Remove range constraints from witnesses which are constrained to be constants ([#3928](https://github.com/noir-lang/noir/issues/3928)) ([afe9c7a](https://github.com/noir-lang/noir/commit/afe9c7a38bb9d4245205d3aa46d4ce23d70a5671)) +* Remove replacement of boolean range opcodes with `AssertZero` opcodes ([#4107](https://github.com/noir-lang/noir/issues/4107)) ([dac0e87](https://github.com/noir-lang/noir/commit/dac0e87ee3be3446b92bbb12ef4832fd493fcee3)) +* Speed up transformation of debug messages ([#3815](https://github.com/noir-lang/noir/issues/3815)) ([2a8af1e](https://github.com/noir-lang/noir/commit/2a8af1e4141ffff61547ee1c2837a6392bd5db48)) +* Sync `aztec-packages` ([#4011](https://github.com/noir-lang/noir/issues/4011)) ([fee2452](https://github.com/noir-lang/noir/commit/fee24523c427c27f0bdaf98ea09a852a2da3e94c)) +* Sync commits from `aztec-packages` ([#4068](https://github.com/noir-lang/noir/issues/4068)) ([7a8f3a3](https://github.com/noir-lang/noir/commit/7a8f3a33b57875e681e3d81e667e3570a1cdbdcc)) +* Sync commits from `aztec-packages` ([#4144](https://github.com/noir-lang/noir/issues/4144)) ([0205d3b](https://github.com/noir-lang/noir/commit/0205d3b4ad0cf5ffd775a43eb5af273a772cf138)) +* Sync from aztec-packages ([#4483](https://github.com/noir-lang/noir/issues/4483)) ([fe8f277](https://github.com/noir-lang/noir/commit/fe8f2776ccfde29209a2c3fc162311c99e4f59be)) + + +### Bug Fixes + +* Deserialize odd length hex literals ([#3747](https://github.com/noir-lang/noir/issues/3747)) ([4000fb2](https://github.com/noir-lang/noir/commit/4000fb279221eb07187d657bfaa7f1c7b311abf2)) +* Noir test incorrect reporting (https://github.com/AztecProtocol/aztec-packages/pull/4925) ([5f57ebb](https://github.com/noir-lang/noir/commit/5f57ebb7ff4b810802f90699a10f4325ef904f2e)) +* Remove panic from `init_log_level` in `acvm_js` ([#4195](https://github.com/noir-lang/noir/issues/4195)) ([2e26530](https://github.com/noir-lang/noir/commit/2e26530bf53006c1ed4fee310bcaa905c95dd95b)) +* Return error rather instead of panicking on invalid circuit ([#3976](https://github.com/noir-lang/noir/issues/3976)) ([67201bf](https://github.com/noir-lang/noir/commit/67201bfc21a9c8858aa86be9cd47d463fb78d925)) + + +### Miscellaneous Chores + +* **acir:** Move `is_recursive` flag to be part of the circuit definition (https://github.com/AztecProtocol/aztec-packages/pull/4221) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* Move noir out of yarn-project (https://github.com/AztecProtocol/aztec-packages/pull/4479) ([78ef013](https://github.com/noir-lang/noir/commit/78ef0134b82e76a73dadb6c7975def22290e3a1a)) +* Remove partial backend feature ([#3805](https://github.com/noir-lang/noir/issues/3805)) ([0383100](https://github.com/noir-lang/noir/commit/0383100853a80a5b28b797cdfeae0d271f1b7805)) +* Remove unused methods on ACIR opcodes ([#3841](https://github.com/noir-lang/noir/issues/3841)) ([9e5d0e8](https://github.com/noir-lang/noir/commit/9e5d0e813d61a0bfb5ee68174ed287c5a20f1579)) +* Rename Arithmetic opcode to AssertZero ([#3840](https://github.com/noir-lang/noir/issues/3840)) ([836f171](https://github.com/noir-lang/noir/commit/836f17145c2901060706294461c2d282dd121b3e)) +* Rename bigint_neg into bigint_sub (https://github.com/AztecProtocol/aztec-packages/pull/4420) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) + ## [0.40.0](https://github.com/noir-lang/noir/compare/v0.39.0...v0.40.0) (2024-02-12) diff --git a/acvm-repo/acir/Cargo.toml b/acvm-repo/acir/Cargo.toml index 7021333486f..101ce7a0f39 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.40.0" +version = "0.46.0" # x-release-please-end authors.workspace = true edition.workspace = true @@ -20,6 +20,7 @@ thiserror.workspace = true flate2.workspace = true bincode.workspace = true base64.workspace = true +serde-big-array = "0.5.1" [dev-dependencies] serde_json = "1.0" @@ -28,8 +29,13 @@ strum_macros = "0.24" serde-reflection = "0.3.6" serde-generate = "0.25.1" fxhash.workspace = true +criterion.workspace = true +pprof.workspace = true [features] -default = ["bn254"] -bn254 = ["acir_field/bn254", "brillig/bn254"] -bls12_381 = ["acir_field/bls12_381", "brillig/bls12_381"] +bn254 = ["acir_field/bn254"] +bls12_381 = ["acir_field/bls12_381"] + +[[bench]] +name = "serialization" +harness = false diff --git a/acvm-repo/acir/README.md b/acvm-repo/acir/README.md index 801aeac1140..902769e3ad7 100644 --- a/acvm-repo/acir/README.md +++ b/acvm-repo/acir/README.md @@ -1,206 +1,291 @@ # ACIR documentation (draft) ## Abstract -This document describes the purpose of ACIR, what it is and how ACIR programs can be used by compilers and proving systems. It is intended to be a reference documentation for ACIR. + +This document describes the purpose of ACIR, what it is and how ACIR programs +can be used by compilers and proving systems. It is intended to be a reference +documentation for ACIR. ## Introduction -The purpose of ACIR is to make the link between a generic proving system, such as Aztec's Barretenberg, and a frontend, such as Noir, which describes user-specific computations. -More precisely, Noir is a programming language for zero-knowledge proofs (ZKP) which allows users to write programs in an intuitive way using a high-level language close to Rust syntax. Noir is able to generate a proof of execution of a Noir program, using an external proving system. However, proving systems use specific low-level constrain-based languages. Similarly, frontends have their own internal representation in order to represent user programs. +The purpose of ACIR is to make the link between a generic proving system, such +as Aztec's Barretenberg, and a frontend, such as Noir, which describes user +specific computations. + +More precisely, Noir is a programming language for zero-knowledge proofs (ZKP) +which allows users to write programs in an intuitive way using a high-level +language close to Rust syntax. Noir is able to generate a proof of execution of +a Noir program, using an external proving system. However, proving systems use +specific low-level constrain-based languages. Similarly, frontends have their +own internal representation in order to represent user programs. -The goal of ACIR is to provide a generic open-source intermediate representation close to proving system 'languages', but agnostic to a specific proving system, that can be used both by proving system as well as a target for frontends. So, at the end of the day, an ACIR program is just another representation of a program, dedicated to proving systems. +The goal of ACIR is to provide a generic open-source intermediate +representation close to proving system 'languages', but agnostic to a specific +proving system, that can be used both by proving system as well as a target for +frontends. So, at the end of the day, an ACIR program is just another +representation of a program, dedicated to proving systems. ## Abstract Circuit Intermediate Representation ACIR stands for abstract circuit intermediate representation: -- **abstract circuit**: circuits are a simple computation model where basic computation units, named gates, are connected with wires. Data flows through the wires while gates compute output wires based on their input. More formally, they are directed acyclic graphs (DAG) where the vertices are the gates and the edges are the wires. Due to the immutability nature of the wires (their value does not change during an execution), they are well suited for describing computations for ZKPs. Furthermore, we do not lose any expressiveness when using a circuit as it is well known that any bounded computation can be translated into an arithmetic circuit (i.e a circuit with only addition and multiplication gates). -The term abstract here simply means that we do not refer to an actual physical circuit (such as an electronic circuit). Furthermore, we will not exactly use the circuit model, but another model even better suited to ZKPs, the constraint model (see below). -- **intermediate representation**: The ACIR representation is intermediate because it lies between a frontend and its proving system. ACIR bytecode makes the link between noir compiler output and the proving system backend input. +- **abstract circuit**: circuits are a simple computation model where basic + computation units, named gates, are connected with wires. Data flows + through the wires while gates compute output wires based on their input. + More formally, they are directed acyclic graphs (DAG) where the vertices + are the gates and the edges are the wires. Due to the immutability nature + of the wires (their value does not change during an execution), they are + well suited for describing computations for ZKPs. Furthermore, we do not + lose any expressiveness when using a circuit as it is well known that any + bounded computation can be translated into an arithmetic circuit (i.e a + circuit with only addition and multiplication gates). +The term abstract here simply means that we do not refer to an actual physical +circuit (such as an electronic circuit). Furthermore, we will not exactly use +the circuit model, but another model even better suited to ZKPs, the constraint +model (see below). +- **intermediate representation**: The ACIR representation is intermediate +because it lies between a frontend and its proving system. ACIR bytecode makes +the link between noir compiler output and the proving system backend input. ## The constraint model -The first step for generating a proof that a specific program was executed, is to execute this program. Since the proving system is going to handle ACIR programs, we need in fact to execute an ACIR program, using the user-supplied inputs. -In ACIR terminology, the gates are called opcodes and the wires are called partial witnesses. However, instead of connecting the opcodes together through wires, we create constraints: an opcode constraints together a set of wires. -This constraint model trivially supersedes the circuit model. For instance, an addition gate output_wire = input_wire_1 + input_wire_2 can be expressed with the following arithmetic constraint: output_wire - (input_wire_1 + input_wire_2) = 0 +The first step for generating a proof that a specific program was executed, is +to execute this program. Since the proving system is going to handle ACIR +programs, we need in fact to execute an ACIR program, using the user-supplied +inputs. +In ACIR terminology, the gates are called opcodes and the wires are called +partial witnesses. However, instead of connecting the opcodes together through +wires, we create constraints: an opcode constraints together a set of wires. +This constraint model trivially supersedes the circuit model. For instance, an +addition gate `output_wire = input_wire_1 + input_wire_2` can be expressed with +the following arithmetic constraint: +`output_wire - (input_wire_1 + input_wire_2) = 0` ## Solving -Because of these constraints, executing an ACIR program is called solving the witnesses. From the witnesses representing the inputs of the program, whose values are supplied by the user, we find out what the other witnesses should be by executing/solving the constraints one-by-one in the order they were defined. -For instance, if input_wire_1 and input_wire_2 values are supplied as 3 and 8, then we can solve the opcode output_wire - (input_wire_1 + input_wire_2) = 0 by saying that output_wire is 11. +Because of these constraints, executing an ACIR program is called solving the +witnesses. From the witnesses representing the inputs of the program, whose +values are supplied by the user, we find out what the other witnesses should be +by executing/solving the constraints one-by-one in the order they were defined. + +For instance, if `input_wire_1` and `input_wire_2` values are supplied as `3` and +`8`, then we can solve the opcode +`output_wire - (input_wire_1 + input_wire_2) = 0` by saying that `output_wire` is +`11`. In summary, the workflow is the following: -1. user program -> (compilation) ACIR, a list of opcodes which constrain (partial) witnesses -2. user inputs + ACIR -> (execution/solving) assign values to all the (partial) witnesses +1. user program -> (compilation) ACIR, a list of opcodes which constrain + (partial) witnesses +2. user inputs + ACIR -> (execution/solving) assign values to all the + (partial) witnesses 3. witness assignment + ACIR -> (proving system) proof +Although the ordering of opcode does not matter in theory, since a system of +equations is not dependent on its ordering, in practice it matters a lot for the +solving (i.e the performance of the execution). ACIR opcodes **must be ordered** +so that each opcode can be resolved one after the other. -Although the ordering of opcode does not matter in theory, since a system of equations is not dependent on its ordering, in practice it matters a lot for the solving (i.e the performance of the execution). ACIR opcodes **must be ordered** so that each opcode can be resolved one after the other. +The values of the witnesses lie in the scalar field of the proving system. We +will refer to it as `FieldElement` or ACIR field. The proving system needs the +values of all the partial witnesses and all the constraints in order to generate +a proof. +*Remark*: The value of a partial witness is unique and fixed throughout a program + execution, although in some rare cases, multiple values are possible for a + same execution and witness (when there are several valid solutions to the + constraints). Having multiple possible values for a witness may indicate that + the circuit is not safe. -The values of the witnesses lie in the scalar field of the proving system. We will refer to it as FieldElement or ACIR field. The proving system needs the values of all the partial witnesses and all the constraints in order to generate a proof. +*Remark*: Why do we use the term partial witnesses? It is because the proving + system may create other constraints and witnesses (especially with + `BlackBoxFuncCall`, see below). A proof refers to a full witness assignments + and their constraints. ACIR opcodes and their partial witnesses are still an + intermediate representation before getting the full list of constraints and + witnesses. For the sake of simplicity, we will refer to witness instead of + partial witness from now on. -*Remark*: The value of a partial witness is unique and fixed throughout a program execution, although in some rare cases, multiple values are possible for a same execution and witness (when there are several valid solutions to the constraints). Having multiple possible values for a witness may indicate that the circuit is not safe. +## ACIR Reference -*Remark*: Why do we use the term partial witnesses? It is because the proving system may create other constraints and witnesses (especially with BlackBoxFuncCall, see below). A proof refers to a full witness assignments and their constraints. ACIR opcodes and their partial witnesses are still an intermediate representation before getting the full list of constraints and witnesses. For the sake of simplicity, we will refer to witness instead of partial witness from now on. +We assume here that the proving system is Barretenberg. Some parameters may +slightly change with another proving system, in particular the bit size of +`FieldElement`, which is 254 for Barretenberg. +Some opcodes have inputs and outputs, which means that the output is constrained +to be the result of the opcode computation from the inputs. The solver expects +that all inputs are known when solving such opcodes. -## ACIR Reference -We assume here that the proving system is Barretenberg. Some parameters may slightly change with another proving system, in particular the bit size of FieldElement, which is 254 for Barretenberg. +Some opcodes are not constrained, which means they will not be used by the +proving system and are only used by the solver. -Some opcodes have inputs and outputs, which means that the output is constrained to be the result of the opcode computation from the inputs. The solver expects that all inputs are known when solving such opcodes. +Finally, some opcodes will have a predicate, whose value is `0` or `1`. Its +purpose is to nullify the opcode when the value is `0`, so that it has no +effect. Note that removing the opcode is not a solution because this modifies +the circuit (the circuit being mainly the list of the opcodes). -Some opcodes are not constrained, which means they will not be used by the proving system and are only used by the solver. +*Remark*: Opcodes operate on witnesses, but we will see that some opcode work on + expressions of witnesses. We call an expression a linear combination of + witnesses and/or products of two witnesses (and also a constant term). A + single witness is a (simple) expression, and conversely, an expression can + be turned into a single witness using an assert-zero opcode (see below). So + basically, using witnesses or expressions is equivalent, but the latter can + avoid the creation of witness in some cases. -Finally, some opcodes will have a predicate, whose value is 0 or 1. Its purpose is to nullify the opcode when the value is 0, so that it has no effect. Note that removing the opcode is not a solution because this modifies the circuit (the circuit being mainly the list of the opcodes). +### AssertZero opcode -*Remark*: Opcodes operate on witnesses, but we will see that some opcode work on expressions of witnesses. We call an expression a linear combination of witnesses and/or products of two witnesses (and also a constant term). A single witness is a (simple) expression, and conversely, an expression can be turned into a single witness using an assert-zero opcode (see below). So basically, using witnesses or expressions is equivalent, but the latter can avoid the creation of witness in some cases. +An `AssertZero` opcode adds the constraint that `P(w) = 0`, where +`w=(w_1,..w_n)` is a tuple of `n` witnesses, and `P` is a multi-variate +polynomial of total degree at most `2`. -### AssertZero opcode -An AssertZero opcode adds the constraint that P(w) = 0, where w=(w_1,..w_n) is a tuple of n witnesses, and P is a multi-variate polynomial of total degree at most 2. -The coefficients ${q_M}_{i,j}, q_i,q_c$ of the polynomial are known values which define the opcode. -A general expression of assert-zero opcode is the following: $\sum_{i,j} {q_M}_{i,j}w_iw_j + \sum_i q_iw_i +q_c = 0$ +### BlackBoxFuncCall opcode -An assert-zero opcode can be used to: -- **express a constraint** on witnesses; for instance to express that a witness $w$ is a boolean, you can add the opcode: $w*w-w=0$ -- or, to **compute the value** of an arithmetic operation of some inputs. For instance, to multiply two witnesses $x$ and $y$, you would use the opcode $z-x*y=0$, which would constraint $z$ to be $x*y$. +These opcodes represent a specific computation. Even if any computation can be +done using only assert-zero opcodes, it is not always efficient. Some proving +systems, and in particular the proving system from Aztec, can implement several +computations more efficiently using for instance look-up tables. The +`BlackBoxFuncCall` opcode is used to ask the proving system to handle the +computation by itself. +All black box functions take as input a tuple `(witness, num_bits)`, where +`num_bits` is a constant representing the bit size of the input witness, and they +have one or several witnesses as output. -The solver expects that at most one witness is not known when executing the opcode. +Some more advanced computations assume that the proving system has an +"embedded curve". It is a curve that cycles with the main curve of the proving +system, i.e the scalar field of the embedded curve is the base field of the main +one, and vice-versa. The curves used by the proving system are dependent on the +proving system (and/or its configuration). Aztec's Barretenberg uses BN254 as the +main curve and Grumpkin as the embedded curve. -### BlackBoxFuncCall opcode -These opcodes represent a specific computation. Even if any computation can be done using only assert-zero opcodes, it is not always efficient. Some proving systems, and in particular the proving system from Aztec, can implement several computations more efficiently using for instance look-up tables. The BlackBoxFuncCall opcode is used to ask the proving system to handle the computation by itself. -All black box functions take as input a tuple (witness, num_bits), where num_bits is a constant representing the bit size of the input witness, and they have one or several witnesses as output. -Some more advanced computations assume that the proving system has an 'embedded curve'. It is a curve that cycle with the main curve of the proving system, i.e the scalar field of the embedded curve is the base field of the main one, and vice-versa. The curves used by the proving system are dependent on the proving system (and/or its configuration). Aztec's Barretenberg uses BN254 as the main curve and Grumpkin as the embedded curve. +NOTE: see the [black_box_functions](src/circuit/black_box_functions.rs) file for +the most up-to-date documentation on these opcodes. The black box functions supported by ACIR are: -**AND**: performs the bitwise AND of lhs and rhs. bit_size must be the same for both inputs. -- lhs: (witness, bit_size) -- rhs: (witness, bit_size) -- output: a witness whose value is constrained to be lhs AND rhs, as bit_size bit integers +**AES128Encrypt**: ciphers the provided plaintext using AES128 in CBC mode, padding the input using PKCS#7. + +**AND**: performs the bitwise AND of `lhs` and `rhs`. `bit_size` must be the same for both inputs. -**XOR**: performs the bitwise XOR of lhs and rhs. bit_size must be the same for both inputs. -- lhs: (witness, bit_size) -- rhs: (witness, bit_size) -- output: a witness whose value is constrained to be lhs XOR rhs, as bit_size bit integers +**XOR**: performs the bitwise XOR of `lhs` and `rhs`. `bit_size` must be the same for both inputs. **RANGE**: constraint the input to be of the provided bit size -input: (witness, bit_size) **SHA256**: computes sha256 of the inputs -- inputs are a byte array, i.e a vector of (FieldElement, 8) -- output is a byte array of len 32, i.e a vector of 32 (FieldElement, 8), constrained to be the sha256 of the inputs. **Blake2s**: computes the Blake2s hash of the inputs, as specified in https://tools.ietf.org/html/rfc7693 -- inputs are a byte array, i.e a vector of (FieldElement, 8) -- output is a byte array of length 32, i.e a vector of 32 (FieldElement, 8), constrained to be the blake2s of the inputs. +**Blake3**: computes the Blake3 hash of the inputs **SchnorrVerify**: Verify a Schnorr signature over the embedded curve -- inputs are: - - Public key as 2 (FieldElement, 254) - - signature as a vector of 64 bytes (FieldElement, 8) - - message as a vector of (FieldElement, 8) -- output: A witness representing the result of the signature verification; 0 for failure and 1 for success. - -Since the scalar field of the embedded curve is NOT the ACIR field, the (r,s) signature is represented as a 64 bytes array for the two field elements. On the other hand, the public key coordinates are ACIR fields. -The proving system decides how the message is to be hashed. Barretenberg uses Blake2s. - **PedersenCommitment**: Computes a Pedersen commitments of the inputs using generators of the embedded curve -- input: vector of (FieldElement, 254) -- output: 2 witnesses representing the x,y coordinates of the resulting Grumpkin point -- domain separator: a constant public value (a field element) that you can use so that the commitment also depends on the domain separator. Noir uses 0 as domain separator. - -The backend should handle proper conversion between the inputs being ACIR field elements and the scalar field of the embedded curve. In the case of Aztec's Barretenberg, the latter is bigger than the ACIR field so it is straightforward. The Pedersen generators are managed by the proving system. - **PedersenHash**: Computes a Pedersen commitments of the inputs and their number, using generators of the embedded curve -- input: vector of (FieldElement, 254) -- output: the x-coordinate of the pedersen commitment of the 'prepended input' (see below) -- domain separator: a constant public value (a field element) that you can use so that the hash also depends on the domain separator. Noir uses 0 as domain separator. -In Barretenberg, PedersenHash is doing the same as PedersenCommitment, except that it prepends the inputs with their length. +**EcdsaSecp256k1**: Verify an ECDSA signature over Secp256k1 +**EcdsaSecp256r1**: Same as EcdsaSecp256k1, but done over another curve. -**HashToField128Security**: This opcode is deprecated and will be removed. +**MultiScalarMul**: scalar multiplication with a variable base/input point (`P`) of the embedded curve -**EcdsaSecp256k1**: Verify an ECDSA signature over Secp256k1 -- inputs: - - x coordinate of public key as 32 bytes - - y coordinate of public key as 32 bytes - - the signature, as a 64 bytes array - - the hash of the message, as a vector of bytes -- output: 0 for failure and 1 for success +**Keccak256**: Computes the Keccak-256 (Ethereum version) of the inputs. -Inputs and outputs are similar to SchnorrVerify, except that because we use a different curve (secp256k1), the field elements involved in the signature and the public key are defined as an array of 32 bytes. Another difference is that we assume the message is already hashed. +**Keccakf1600**: Keccak Permutation function of width 1600 -**EcdsaSecp256r1**: Same as EcdsaSecp256k1, but done over another curve. +**EmbeddedCurveAdd**: Embedded curve addition -**FixedBaseScalarMul**: scalar multiplication with a fixed generator of the embedded curve -- input: low, high are 2 (field , 254), representing the low and high part of the input. For Barretenberg, they must both be less than 128 bits. -- output: x and y coordinates of $low*G+high*2^{128}*G$, where G is a fixed generator +**BigIntAdd**: BigInt addition -Because the Grumpkin scalar field is bigger than the ACIR field, we provide 2 ACIR fields representing the low and high parts of the Grumpkin scalar $a$: -$a=low+high*2^{128},$ with $low, high < 2^{128}$ +**BigIntSub**: BigInt subtraction -**Keccak256**: Computes the Keccak-256 (Ethereum version) of the inputs. -- inputs: Vector of bytes (FieldElement, 8) -- outputs: Vector of 32 bytes (FieldElement, 8) +**BigIntMul**: BigInt multiplication + +**BigIntDiv**: BigInt division +**BigIntFromLeBytes**: BigInt from le bytes -**Keccak256VariableLength**: Computes the Keccak-256 (Ethereum version) of the inputs, restricted to the given length. -- inputs: Vector of bytes (FieldElement, 8) -- var_message_size: number of inputs to hash; it must be less (or equal) than the inputs length -- outputs: a vector of 32 bytes (FieldElement, 8) +**BigIntToLeBytes**: BigInt to le bytes +**Poseidon2Permutation**: Permutation function of Poseidon2 +**Sha256Compression**: SHA256 compression function **RecursiveAggregation**: verify a proof inside the circuit. **Warning: this opcode is subject to change.** -- verification_key: Vector of (FieldElement, 254) representing the verification key of the circuit being verified -- public_inputs: Vector of (FieldElement, 254) representing the public inputs corresponding to the proof being verified -- key_hash: one (FieldElement, 254). It should be the hash of the verification key. Barretenberg expects the Pedersen hash of the verification key -- input_aggregation_object: an optional vector of (FieldElement, 254). It is a blob of data specific to the proving system. -- output_aggregation_object: Some witnesses returned by the function, representing some data internal to the proving system. -This black box function does not fully verify a proof, what it does is verifying that the key_hash is indeed a hash of verification_key, allowing the user to use the verification key as private inputs and only have the key_hash as public input, which is more performant. -Another thing that it does is preparing the verification of the proof. In order to fully verify a proof, some operations may still be required to be done by the final verifier. This is why this black box function does not say if verification is passing or not. -If you have several proofs to verify in one ACIR program, you would call RecursiveAggregation() multiple times and passing the output_aggregation_object as input_aggregation_object to the next RecursiveAggregation() call, except for the first call where you do not have any input_aggregation_object. -If one of the proof you verify with the black box function does not verify, then the verification of the proof of the main ACIR program will ultimately fail. +This black box function does not fully verify a proof, what it does is verify +that the provided `key_hash` is indeed a hash of `verification_key`, allowing +the user to use the verification key as private inputs and only have the +`key_hash` as public input, which is more performant. +Another thing that it does is preparing the verification of the proof. In order +to fully verify a proof, some operations may still be required to be done by the +final verifier. This is why this black box function does not say if verification +is passing or not. -### Brillig -This opcode is used as a hint for the solver when executing (solving) the circuit. The opcode does not generate any constraint and is usually the result of the compilation of an unconstrained noir function. -- inputs: inputs to the opcode, as 'arithmetic expressions'. -- outputs: opcode outputs, as witnesses -- bytecode: assembly code representing the computation to perform within this opcode. The noir assembly specification is not part of this document. -- predicate: an arithmetic expression that disable the opcode when it is null. +If you have several proofs to verify in one ACIR program, you would call +`RecursiveAggregation()` multiple times while passing the +`output_aggregation_object` as `input_aggregation_object` to the next +`RecursiveAggregation()` call, except for the first call where you do not have +any `input_aggregation_object`. -Let's see an example with euclidean division. -The normal way to compute a/b, where a and b are 8-bits integers, is to implement Euclid algorithm which computes in a loop (or recursively) modulus of the kind 'a mod b'. Doing this computation requires a lot of steps to be properly implemented in ACIR, especially the loop with a condition. However, euclidean division can be easily constrained with one assert-zero opcode: a = bq+r, assuming q is 8 bits and r Program { + let assert_zero_opcodes: Vec> = (0..num_opcodes) + .map(|i| { + Opcode::AssertZero(Expression { + mul_terms: vec![( + FieldElement::from(2 * i), + Witness(i as u32), + Witness(i as u32 + 10), + )], + linear_combinations: vec![ + (FieldElement::from(2 * i), Witness(i as u32)), + (FieldElement::from(3 * i), Witness(i as u32 + 1)), + ], + q_c: FieldElement::from(i), + }) + }) + .collect(); + + Program { + functions: vec![Circuit { + current_witness_index: 4000, + opcodes: assert_zero_opcodes.to_vec(), + expression_width: ExpressionWidth::Bounded { width: 4 }, + private_parameters: BTreeSet::from([Witness(1), Witness(2), Witness(3), Witness(4)]), + public_parameters: PublicInputs(BTreeSet::from([Witness(5)])), + return_values: PublicInputs(BTreeSet::from([Witness(6)])), + assert_messages: Vec::new(), + recursive: false, + }], + unconstrained_functions: Vec::new(), + } +} + +fn bench_serialization(c: &mut Criterion) { + let mut group = c.benchmark_group("serialize_program"); + for size in SIZES.iter() { + let program = sample_program(*size); + + group.throughput(Throughput::Elements(*size as u64)); + group.bench_with_input(BenchmarkId::from_parameter(size), &program, |b, program| { + b.iter(|| Program::serialize_program(program)); + }); + } + group.finish(); + + let mut group = c.benchmark_group("serialize_program_json"); + for size in SIZES.iter() { + let program = sample_program(*size); + + group.throughput(Throughput::Elements(*size as u64)); + group.bench_with_input(BenchmarkId::from_parameter(size), &program, |b, program| { + b.iter(|| { + let mut bytes = Vec::new(); + let mut serializer = serde_json::Serializer::new(&mut bytes); + Program::serialize_program_base64(program, &mut serializer) + }); + }); + } + group.finish(); +} + +fn bench_deserialization(c: &mut Criterion) { + let mut group = c.benchmark_group("deserialize_program"); + for size in SIZES.iter() { + let program = sample_program(*size); + let serialized_program = Program::serialize_program(&program); + + group.throughput(Throughput::Elements(*size as u64)); + group.bench_with_input( + BenchmarkId::from_parameter(size), + &serialized_program, + |b, program| { + b.iter(|| Program::::deserialize_program(program)); + }, + ); + } + group.finish(); + + let mut group = c.benchmark_group("deserialize_program_json"); + for size in SIZES.iter() { + let program = sample_program(*size); + + let serialized_program = { + let mut bytes = Vec::new(); + let mut serializer = serde_json::Serializer::new(&mut bytes); + Program::serialize_program_base64(&program, &mut serializer).expect("should succeed"); + bytes + }; + + group.throughput(Throughput::Elements(*size as u64)); + group.bench_with_input( + BenchmarkId::from_parameter(size), + &serialized_program, + |b, program| { + b.iter(|| { + let mut deserializer = serde_json::Deserializer::from_slice(program); + Program::::deserialize_program_base64(&mut deserializer) + }); + }, + ); + } + group.finish(); +} + +criterion_group!( + name = benches; + config = Criterion::default().sample_size(40).measurement_time(Duration::from_secs(20)).with_profiler(PProfProfiler::new(100, Output::Flamegraph(None))); + targets = bench_serialization, bench_deserialization +); + +criterion_main!(benches); diff --git a/acvm-repo/acir/codegen/acir.cpp b/acvm-repo/acir/codegen/acir.cpp index 0fc84d47a0f..47e184a6332 100644 --- a/acvm-repo/acir/codegen/acir.cpp +++ b/acvm-repo/acir/codegen/acir.cpp @@ -3,174 +3,78 @@ #include "serde.hpp" #include "bincode.hpp" -namespace Circuit { +namespace Program { - struct BinaryFieldOp { - - struct Add { - friend bool operator==(const Add&, const Add&); - std::vector bincodeSerialize() const; - static Add bincodeDeserialize(std::vector); - }; - - struct Sub { - friend bool operator==(const Sub&, const Sub&); - std::vector bincodeSerialize() const; - static Sub bincodeDeserialize(std::vector); - }; - - struct Mul { - friend bool operator==(const Mul&, const Mul&); - std::vector bincodeSerialize() const; - static Mul bincodeDeserialize(std::vector); - }; - - struct Div { - friend bool operator==(const Div&, const Div&); - std::vector bincodeSerialize() const; - static Div bincodeDeserialize(std::vector); - }; - - struct Equals { - friend bool operator==(const Equals&, const Equals&); - std::vector bincodeSerialize() const; - static Equals bincodeDeserialize(std::vector); - }; - - std::variant value; + struct Witness { + uint32_t value; - friend bool operator==(const BinaryFieldOp&, const BinaryFieldOp&); + friend bool operator==(const Witness&, const Witness&); std::vector bincodeSerialize() const; - static BinaryFieldOp bincodeDeserialize(std::vector); + static Witness bincodeDeserialize(std::vector); }; - struct BinaryIntOp { - - struct Add { - friend bool operator==(const Add&, const Add&); - std::vector bincodeSerialize() const; - static Add bincodeDeserialize(std::vector); - }; - - struct Sub { - friend bool operator==(const Sub&, const Sub&); - std::vector bincodeSerialize() const; - static Sub bincodeDeserialize(std::vector); - }; - - struct Mul { - friend bool operator==(const Mul&, const Mul&); - std::vector bincodeSerialize() const; - static Mul bincodeDeserialize(std::vector); - }; + struct FunctionInput { + Program::Witness witness; + uint32_t num_bits; - struct SignedDiv { - friend bool operator==(const SignedDiv&, const SignedDiv&); - std::vector bincodeSerialize() const; - static SignedDiv bincodeDeserialize(std::vector); - }; + friend bool operator==(const FunctionInput&, const FunctionInput&); + std::vector bincodeSerialize() const; + static FunctionInput bincodeDeserialize(std::vector); + }; - struct UnsignedDiv { - friend bool operator==(const UnsignedDiv&, const UnsignedDiv&); - std::vector bincodeSerialize() const; - static UnsignedDiv bincodeDeserialize(std::vector); - }; + struct BlackBoxFuncCall { - struct Equals { - friend bool operator==(const Equals&, const Equals&); - std::vector bincodeSerialize() const; - static Equals bincodeDeserialize(std::vector); - }; + struct AES128Encrypt { + std::vector inputs; + std::array iv; + std::array key; + std::vector outputs; - struct LessThan { - friend bool operator==(const LessThan&, const LessThan&); + friend bool operator==(const AES128Encrypt&, const AES128Encrypt&); std::vector bincodeSerialize() const; - static LessThan bincodeDeserialize(std::vector); + static AES128Encrypt bincodeDeserialize(std::vector); }; - struct LessThanEquals { - friend bool operator==(const LessThanEquals&, const LessThanEquals&); - std::vector bincodeSerialize() const; - static LessThanEquals bincodeDeserialize(std::vector); - }; + struct AND { + Program::FunctionInput lhs; + Program::FunctionInput rhs; + Program::Witness output; - struct And { - friend bool operator==(const And&, const And&); + friend bool operator==(const AND&, const AND&); std::vector bincodeSerialize() const; - static And bincodeDeserialize(std::vector); + static AND bincodeDeserialize(std::vector); }; - struct Or { - friend bool operator==(const Or&, const Or&); - std::vector bincodeSerialize() const; - static Or bincodeDeserialize(std::vector); - }; + struct XOR { + Program::FunctionInput lhs; + Program::FunctionInput rhs; + Program::Witness output; - struct Xor { - friend bool operator==(const Xor&, const Xor&); + friend bool operator==(const XOR&, const XOR&); std::vector bincodeSerialize() const; - static Xor bincodeDeserialize(std::vector); + static XOR bincodeDeserialize(std::vector); }; - struct Shl { - friend bool operator==(const Shl&, const Shl&); - std::vector bincodeSerialize() const; - static Shl bincodeDeserialize(std::vector); - }; + struct RANGE { + Program::FunctionInput input; - struct Shr { - friend bool operator==(const Shr&, const Shr&); + friend bool operator==(const RANGE&, const RANGE&); std::vector bincodeSerialize() const; - static Shr bincodeDeserialize(std::vector); + static RANGE bincodeDeserialize(std::vector); }; - std::variant value; - - friend bool operator==(const BinaryIntOp&, const BinaryIntOp&); - std::vector bincodeSerialize() const; - static BinaryIntOp bincodeDeserialize(std::vector); - }; - - struct MemoryAddress { - uint64_t value; - - friend bool operator==(const MemoryAddress&, const MemoryAddress&); - std::vector bincodeSerialize() const; - static MemoryAddress bincodeDeserialize(std::vector); - }; - - struct HeapArray { - Circuit::MemoryAddress pointer; - uint64_t size; - - friend bool operator==(const HeapArray&, const HeapArray&); - std::vector bincodeSerialize() const; - static HeapArray bincodeDeserialize(std::vector); - }; - - struct HeapVector { - Circuit::MemoryAddress pointer; - Circuit::MemoryAddress size; - - friend bool operator==(const HeapVector&, const HeapVector&); - std::vector bincodeSerialize() const; - static HeapVector bincodeDeserialize(std::vector); - }; - - struct BlackBoxOp { - - struct Sha256 { - Circuit::HeapVector message; - Circuit::HeapArray output; + struct SHA256 { + std::vector inputs; + std::array outputs; - friend bool operator==(const Sha256&, const Sha256&); + friend bool operator==(const SHA256&, const SHA256&); std::vector bincodeSerialize() const; - static Sha256 bincodeDeserialize(std::vector); + static SHA256 bincodeDeserialize(std::vector); }; struct Blake2s { - Circuit::HeapVector message; - Circuit::HeapArray output; + std::vector inputs; + std::array outputs; friend bool operator==(const Blake2s&, const Blake2s&); std::vector bincodeSerialize() const; @@ -178,38 +82,52 @@ namespace Circuit { }; struct Blake3 { - Circuit::HeapVector message; - Circuit::HeapArray output; + std::vector inputs; + std::array outputs; friend bool operator==(const Blake3&, const Blake3&); std::vector bincodeSerialize() const; static Blake3 bincodeDeserialize(std::vector); }; - struct Keccak256 { - Circuit::HeapVector message; - Circuit::HeapArray output; + struct SchnorrVerify { + Program::FunctionInput public_key_x; + Program::FunctionInput public_key_y; + std::array signature; + std::vector message; + Program::Witness output; - friend bool operator==(const Keccak256&, const Keccak256&); + friend bool operator==(const SchnorrVerify&, const SchnorrVerify&); std::vector bincodeSerialize() const; - static Keccak256 bincodeDeserialize(std::vector); + static SchnorrVerify bincodeDeserialize(std::vector); }; - struct Keccakf1600 { - Circuit::HeapVector message; - Circuit::HeapArray output; + struct PedersenCommitment { + std::vector inputs; + uint32_t domain_separator; + std::array outputs; - friend bool operator==(const Keccakf1600&, const Keccakf1600&); + friend bool operator==(const PedersenCommitment&, const PedersenCommitment&); std::vector bincodeSerialize() const; - static Keccakf1600 bincodeDeserialize(std::vector); + static PedersenCommitment bincodeDeserialize(std::vector); + }; + + struct PedersenHash { + std::vector inputs; + uint32_t domain_separator; + Program::Witness output; + + friend bool operator==(const PedersenHash&, const PedersenHash&); + std::vector bincodeSerialize() const; + static PedersenHash bincodeDeserialize(std::vector); }; struct EcdsaSecp256k1 { - Circuit::HeapVector hashed_msg; - Circuit::HeapArray public_key_x; - Circuit::HeapArray public_key_y; - Circuit::HeapArray signature; - Circuit::MemoryAddress result; + std::array public_key_x; + std::array public_key_y; + std::array signature; + std::array hashed_message; + Program::Witness output; friend bool operator==(const EcdsaSecp256k1&, const EcdsaSecp256k1&); std::vector bincodeSerialize() const; @@ -217,75 +135,71 @@ namespace Circuit { }; struct EcdsaSecp256r1 { - Circuit::HeapVector hashed_msg; - Circuit::HeapArray public_key_x; - Circuit::HeapArray public_key_y; - Circuit::HeapArray signature; - Circuit::MemoryAddress result; + std::array public_key_x; + std::array public_key_y; + std::array signature; + std::array hashed_message; + Program::Witness output; friend bool operator==(const EcdsaSecp256r1&, const EcdsaSecp256r1&); std::vector bincodeSerialize() const; static EcdsaSecp256r1 bincodeDeserialize(std::vector); }; - struct SchnorrVerify { - Circuit::MemoryAddress public_key_x; - Circuit::MemoryAddress public_key_y; - Circuit::HeapVector message; - Circuit::HeapVector signature; - Circuit::MemoryAddress result; + struct MultiScalarMul { + std::vector points; + std::vector scalars; + std::array outputs; - friend bool operator==(const SchnorrVerify&, const SchnorrVerify&); + friend bool operator==(const MultiScalarMul&, const MultiScalarMul&); std::vector bincodeSerialize() const; - static SchnorrVerify bincodeDeserialize(std::vector); + static MultiScalarMul bincodeDeserialize(std::vector); }; - struct PedersenCommitment { - Circuit::HeapVector inputs; - Circuit::MemoryAddress domain_separator; - Circuit::HeapArray output; + struct EmbeddedCurveAdd { + std::array input1; + std::array input2; + std::array outputs; - friend bool operator==(const PedersenCommitment&, const PedersenCommitment&); + friend bool operator==(const EmbeddedCurveAdd&, const EmbeddedCurveAdd&); std::vector bincodeSerialize() const; - static PedersenCommitment bincodeDeserialize(std::vector); + static EmbeddedCurveAdd bincodeDeserialize(std::vector); }; - struct PedersenHash { - Circuit::HeapVector inputs; - Circuit::MemoryAddress domain_separator; - Circuit::MemoryAddress output; + struct Keccak256 { + std::vector inputs; + Program::FunctionInput var_message_size; + std::array outputs; - friend bool operator==(const PedersenHash&, const PedersenHash&); + friend bool operator==(const Keccak256&, const Keccak256&); std::vector bincodeSerialize() const; - static PedersenHash bincodeDeserialize(std::vector); + static Keccak256 bincodeDeserialize(std::vector); }; - struct FixedBaseScalarMul { - Circuit::MemoryAddress low; - Circuit::MemoryAddress high; - Circuit::HeapArray result; + struct Keccakf1600 { + std::array inputs; + std::array outputs; - friend bool operator==(const FixedBaseScalarMul&, const FixedBaseScalarMul&); + friend bool operator==(const Keccakf1600&, const Keccakf1600&); std::vector bincodeSerialize() const; - static FixedBaseScalarMul bincodeDeserialize(std::vector); + static Keccakf1600 bincodeDeserialize(std::vector); }; - struct EmbeddedCurveAdd { - Circuit::MemoryAddress input1_x; - Circuit::MemoryAddress input1_y; - Circuit::MemoryAddress input2_x; - Circuit::MemoryAddress input2_y; - Circuit::HeapArray result; + struct RecursiveAggregation { + std::vector verification_key; + std::vector proof; + std::vector public_inputs; + Program::FunctionInput key_hash; - friend bool operator==(const EmbeddedCurveAdd&, const EmbeddedCurveAdd&); + friend bool operator==(const RecursiveAggregation&, const RecursiveAggregation&); std::vector bincodeSerialize() const; - static EmbeddedCurveAdd bincodeDeserialize(std::vector); + static RecursiveAggregation bincodeDeserialize(std::vector); }; struct BigIntAdd { - Circuit::MemoryAddress lhs; - Circuit::MemoryAddress rhs; - Circuit::MemoryAddress output; + uint32_t lhs; + uint32_t rhs; + uint32_t output; friend bool operator==(const BigIntAdd&, const BigIntAdd&); std::vector bincodeSerialize() const; @@ -293,9 +207,9 @@ namespace Circuit { }; struct BigIntSub { - Circuit::MemoryAddress lhs; - Circuit::MemoryAddress rhs; - Circuit::MemoryAddress output; + uint32_t lhs; + uint32_t rhs; + uint32_t output; friend bool operator==(const BigIntSub&, const BigIntSub&); std::vector bincodeSerialize() const; @@ -303,9 +217,9 @@ namespace Circuit { }; struct BigIntMul { - Circuit::MemoryAddress lhs; - Circuit::MemoryAddress rhs; - Circuit::MemoryAddress output; + uint32_t lhs; + uint32_t rhs; + uint32_t output; friend bool operator==(const BigIntMul&, const BigIntMul&); std::vector bincodeSerialize() const; @@ -313,9 +227,9 @@ namespace Circuit { }; struct BigIntDiv { - Circuit::MemoryAddress lhs; - Circuit::MemoryAddress rhs; - Circuit::MemoryAddress output; + uint32_t lhs; + uint32_t rhs; + uint32_t output; friend bool operator==(const BigIntDiv&, const BigIntDiv&); std::vector bincodeSerialize() const; @@ -323,9 +237,9 @@ namespace Circuit { }; struct BigIntFromLeBytes { - Circuit::HeapVector inputs; - Circuit::HeapVector modulus; - Circuit::MemoryAddress output; + std::vector inputs; + std::vector modulus; + uint32_t output; friend bool operator==(const BigIntFromLeBytes&, const BigIntFromLeBytes&); std::vector bincodeSerialize() const; @@ -333,8 +247,8 @@ namespace Circuit { }; struct BigIntToLeBytes { - Circuit::MemoryAddress input; - Circuit::HeapVector output; + uint32_t input; + std::vector outputs; friend bool operator==(const BigIntToLeBytes&, const BigIntToLeBytes&); std::vector bincodeSerialize() const; @@ -342,9 +256,9 @@ namespace Circuit { }; struct Poseidon2Permutation { - Circuit::HeapVector message; - Circuit::HeapArray output; - Circuit::MemoryAddress len; + std::vector inputs; + std::vector outputs; + uint32_t len; friend bool operator==(const Poseidon2Permutation&, const Poseidon2Permutation&); std::vector bincodeSerialize() const; @@ -352,320 +266,418 @@ namespace Circuit { }; struct Sha256Compression { - Circuit::HeapVector input; - Circuit::HeapVector hash_values; - Circuit::HeapArray output; + std::array inputs; + std::array hash_values; + std::array outputs; friend bool operator==(const Sha256Compression&, const Sha256Compression&); std::vector bincodeSerialize() const; static Sha256Compression bincodeDeserialize(std::vector); }; - std::variant value; + std::variant value; - friend bool operator==(const BlackBoxOp&, const BlackBoxOp&); + friend bool operator==(const BlackBoxFuncCall&, const BlackBoxFuncCall&); std::vector bincodeSerialize() const; - static BlackBoxOp bincodeDeserialize(std::vector); + static BlackBoxFuncCall bincodeDeserialize(std::vector); }; - struct HeapValueType; + struct BlockId { + uint32_t value; - struct HeapValueType { + friend bool operator==(const BlockId&, const BlockId&); + std::vector bincodeSerialize() const; + static BlockId bincodeDeserialize(std::vector); + }; - struct Simple { - friend bool operator==(const Simple&, const Simple&); + struct BlockType { + + struct Memory { + friend bool operator==(const Memory&, const Memory&); std::vector bincodeSerialize() const; - static Simple bincodeDeserialize(std::vector); + static Memory bincodeDeserialize(std::vector); }; - struct Array { - std::vector value_types; - uint64_t size; - - friend bool operator==(const Array&, const Array&); + struct CallData { + friend bool operator==(const CallData&, const CallData&); std::vector bincodeSerialize() const; - static Array bincodeDeserialize(std::vector); + static CallData bincodeDeserialize(std::vector); }; - struct Vector { - std::vector value_types; - - friend bool operator==(const Vector&, const Vector&); + struct ReturnData { + friend bool operator==(const ReturnData&, const ReturnData&); std::vector bincodeSerialize() const; - static Vector bincodeDeserialize(std::vector); + static ReturnData bincodeDeserialize(std::vector); }; - std::variant value; + std::variant value; - friend bool operator==(const HeapValueType&, const HeapValueType&); + friend bool operator==(const BlockType&, const BlockType&); std::vector bincodeSerialize() const; - static HeapValueType bincodeDeserialize(std::vector); + static BlockType bincodeDeserialize(std::vector); }; - struct Value { - std::string inner; + struct Expression { + std::vector> mul_terms; + std::vector> linear_combinations; + std::string q_c; - friend bool operator==(const Value&, const Value&); + friend bool operator==(const Expression&, const Expression&); std::vector bincodeSerialize() const; - static Value bincodeDeserialize(std::vector); + static Expression bincodeDeserialize(std::vector); }; - struct ValueOrArray { + struct BrilligInputs { - struct MemoryAddress { - Circuit::MemoryAddress value; + struct Single { + Program::Expression value; - friend bool operator==(const MemoryAddress&, const MemoryAddress&); + friend bool operator==(const Single&, const Single&); std::vector bincodeSerialize() const; - static MemoryAddress bincodeDeserialize(std::vector); + static Single bincodeDeserialize(std::vector); }; - struct HeapArray { - Circuit::HeapArray value; + struct Array { + std::vector value; - friend bool operator==(const HeapArray&, const HeapArray&); + friend bool operator==(const Array&, const Array&); std::vector bincodeSerialize() const; - static HeapArray bincodeDeserialize(std::vector); + static Array bincodeDeserialize(std::vector); }; - struct HeapVector { - Circuit::HeapVector value; + struct MemoryArray { + Program::BlockId value; - friend bool operator==(const HeapVector&, const HeapVector&); + friend bool operator==(const MemoryArray&, const MemoryArray&); std::vector bincodeSerialize() const; - static HeapVector bincodeDeserialize(std::vector); + static MemoryArray bincodeDeserialize(std::vector); }; - std::variant value; + std::variant value; - friend bool operator==(const ValueOrArray&, const ValueOrArray&); + friend bool operator==(const BrilligInputs&, const BrilligInputs&); std::vector bincodeSerialize() const; - static ValueOrArray bincodeDeserialize(std::vector); + static BrilligInputs bincodeDeserialize(std::vector); }; - struct BrilligOpcode { + struct BrilligOutputs { - struct BinaryFieldOp { - Circuit::MemoryAddress destination; - Circuit::BinaryFieldOp op; - Circuit::MemoryAddress lhs; - Circuit::MemoryAddress rhs; + struct Simple { + Program::Witness value; - friend bool operator==(const BinaryFieldOp&, const BinaryFieldOp&); + friend bool operator==(const Simple&, const Simple&); std::vector bincodeSerialize() const; - static BinaryFieldOp bincodeDeserialize(std::vector); + static Simple bincodeDeserialize(std::vector); }; - struct BinaryIntOp { - Circuit::MemoryAddress destination; - Circuit::BinaryIntOp op; - uint32_t bit_size; - Circuit::MemoryAddress lhs; - Circuit::MemoryAddress rhs; + struct Array { + std::vector value; - friend bool operator==(const BinaryIntOp&, const BinaryIntOp&); + friend bool operator==(const Array&, const Array&); std::vector bincodeSerialize() const; - static BinaryIntOp bincodeDeserialize(std::vector); + static Array bincodeDeserialize(std::vector); }; - struct Cast { - Circuit::MemoryAddress destination; - Circuit::MemoryAddress source; - uint32_t bit_size; + std::variant value; - friend bool operator==(const Cast&, const Cast&); + friend bool operator==(const BrilligOutputs&, const BrilligOutputs&); + std::vector bincodeSerialize() const; + static BrilligOutputs bincodeDeserialize(std::vector); + }; + + struct Directive { + + struct ToLeRadix { + Program::Expression a; + std::vector b; + uint32_t radix; + + friend bool operator==(const ToLeRadix&, const ToLeRadix&); std::vector bincodeSerialize() const; - static Cast bincodeDeserialize(std::vector); + static ToLeRadix bincodeDeserialize(std::vector); }; - struct JumpIfNot { - Circuit::MemoryAddress condition; - uint64_t location; + std::variant value; - friend bool operator==(const JumpIfNot&, const JumpIfNot&); + friend bool operator==(const Directive&, const Directive&); + std::vector bincodeSerialize() const; + static Directive bincodeDeserialize(std::vector); + }; + + struct MemOp { + Program::Expression operation; + Program::Expression index; + Program::Expression value; + + friend bool operator==(const MemOp&, const MemOp&); + std::vector bincodeSerialize() const; + static MemOp bincodeDeserialize(std::vector); + }; + + struct Opcode { + + struct AssertZero { + Program::Expression value; + + friend bool operator==(const AssertZero&, const AssertZero&); std::vector bincodeSerialize() const; - static JumpIfNot bincodeDeserialize(std::vector); + static AssertZero bincodeDeserialize(std::vector); }; - struct JumpIf { - Circuit::MemoryAddress condition; - uint64_t location; + struct BlackBoxFuncCall { + Program::BlackBoxFuncCall value; - friend bool operator==(const JumpIf&, const JumpIf&); + friend bool operator==(const BlackBoxFuncCall&, const BlackBoxFuncCall&); std::vector bincodeSerialize() const; - static JumpIf bincodeDeserialize(std::vector); + static BlackBoxFuncCall bincodeDeserialize(std::vector); }; - struct Jump { - uint64_t location; + struct Directive { + Program::Directive value; - friend bool operator==(const Jump&, const Jump&); + friend bool operator==(const Directive&, const Directive&); std::vector bincodeSerialize() const; - static Jump bincodeDeserialize(std::vector); + static Directive bincodeDeserialize(std::vector); }; - struct CalldataCopy { - Circuit::MemoryAddress destination_address; - uint64_t size; - uint64_t offset; + struct MemoryOp { + Program::BlockId block_id; + Program::MemOp op; + std::optional predicate; - friend bool operator==(const CalldataCopy&, const CalldataCopy&); + friend bool operator==(const MemoryOp&, const MemoryOp&); std::vector bincodeSerialize() const; - static CalldataCopy bincodeDeserialize(std::vector); + static MemoryOp bincodeDeserialize(std::vector); + }; + + struct MemoryInit { + Program::BlockId block_id; + std::vector init; + Program::BlockType block_type; + + friend bool operator==(const MemoryInit&, const MemoryInit&); + std::vector bincodeSerialize() const; + static MemoryInit bincodeDeserialize(std::vector); + }; + + struct BrilligCall { + uint32_t id; + std::vector inputs; + std::vector outputs; + std::optional predicate; + + friend bool operator==(const BrilligCall&, const BrilligCall&); + std::vector bincodeSerialize() const; + static BrilligCall bincodeDeserialize(std::vector); }; struct Call { - uint64_t location; + uint32_t id; + std::vector inputs; + std::vector outputs; + std::optional predicate; friend bool operator==(const Call&, const Call&); std::vector bincodeSerialize() const; static Call bincodeDeserialize(std::vector); }; - struct Const { - Circuit::MemoryAddress destination; - uint32_t bit_size; - Circuit::Value value; + std::variant value; - friend bool operator==(const Const&, const Const&); + friend bool operator==(const Opcode&, const Opcode&); + std::vector bincodeSerialize() const; + static Opcode bincodeDeserialize(std::vector); + }; + + struct BinaryFieldOp { + + struct Add { + friend bool operator==(const Add&, const Add&); std::vector bincodeSerialize() const; - static Const bincodeDeserialize(std::vector); + static Add bincodeDeserialize(std::vector); }; - struct Return { - friend bool operator==(const Return&, const Return&); + struct Sub { + friend bool operator==(const Sub&, const Sub&); std::vector bincodeSerialize() const; - static Return bincodeDeserialize(std::vector); + static Sub bincodeDeserialize(std::vector); }; - struct ForeignCall { - std::string function; - std::vector destinations; - std::vector destination_value_types; - std::vector inputs; - std::vector input_value_types; + struct Mul { + friend bool operator==(const Mul&, const Mul&); + std::vector bincodeSerialize() const; + static Mul bincodeDeserialize(std::vector); + }; - friend bool operator==(const ForeignCall&, const ForeignCall&); + struct Div { + friend bool operator==(const Div&, const Div&); std::vector bincodeSerialize() const; - static ForeignCall bincodeDeserialize(std::vector); + static Div bincodeDeserialize(std::vector); }; - struct Mov { - Circuit::MemoryAddress destination; - Circuit::MemoryAddress source; + struct IntegerDiv { + friend bool operator==(const IntegerDiv&, const IntegerDiv&); + std::vector bincodeSerialize() const; + static IntegerDiv bincodeDeserialize(std::vector); + }; - friend bool operator==(const Mov&, const Mov&); + struct Equals { + friend bool operator==(const Equals&, const Equals&); std::vector bincodeSerialize() const; - static Mov bincodeDeserialize(std::vector); + static Equals bincodeDeserialize(std::vector); }; - struct Load { - Circuit::MemoryAddress destination; - Circuit::MemoryAddress source_pointer; + struct LessThan { + friend bool operator==(const LessThan&, const LessThan&); + std::vector bincodeSerialize() const; + static LessThan bincodeDeserialize(std::vector); + }; - friend bool operator==(const Load&, const Load&); + struct LessThanEquals { + friend bool operator==(const LessThanEquals&, const LessThanEquals&); std::vector bincodeSerialize() const; - static Load bincodeDeserialize(std::vector); + static LessThanEquals bincodeDeserialize(std::vector); }; - struct Store { - Circuit::MemoryAddress destination_pointer; - Circuit::MemoryAddress source; + std::variant value; - friend bool operator==(const Store&, const Store&); + friend bool operator==(const BinaryFieldOp&, const BinaryFieldOp&); + std::vector bincodeSerialize() const; + static BinaryFieldOp bincodeDeserialize(std::vector); + }; + + struct BinaryIntOp { + + struct Add { + friend bool operator==(const Add&, const Add&); std::vector bincodeSerialize() const; - static Store bincodeDeserialize(std::vector); + static Add bincodeDeserialize(std::vector); }; - struct BlackBox { - Circuit::BlackBoxOp value; + struct Sub { + friend bool operator==(const Sub&, const Sub&); + std::vector bincodeSerialize() const; + static Sub bincodeDeserialize(std::vector); + }; - friend bool operator==(const BlackBox&, const BlackBox&); + struct Mul { + friend bool operator==(const Mul&, const Mul&); std::vector bincodeSerialize() const; - static BlackBox bincodeDeserialize(std::vector); + static Mul bincodeDeserialize(std::vector); }; - struct Trap { - friend bool operator==(const Trap&, const Trap&); + struct Div { + friend bool operator==(const Div&, const Div&); std::vector bincodeSerialize() const; - static Trap bincodeDeserialize(std::vector); + static Div bincodeDeserialize(std::vector); }; - struct Stop { - uint64_t return_data_offset; - uint64_t return_data_size; + struct Equals { + friend bool operator==(const Equals&, const Equals&); + std::vector bincodeSerialize() const; + static Equals bincodeDeserialize(std::vector); + }; - friend bool operator==(const Stop&, const Stop&); + struct LessThan { + friend bool operator==(const LessThan&, const LessThan&); std::vector bincodeSerialize() const; - static Stop bincodeDeserialize(std::vector); + static LessThan bincodeDeserialize(std::vector); }; - std::variant value; + struct LessThanEquals { + friend bool operator==(const LessThanEquals&, const LessThanEquals&); + std::vector bincodeSerialize() const; + static LessThanEquals bincodeDeserialize(std::vector); + }; - friend bool operator==(const BrilligOpcode&, const BrilligOpcode&); - std::vector bincodeSerialize() const; - static BrilligOpcode bincodeDeserialize(std::vector); - }; + struct And { + friend bool operator==(const And&, const And&); + std::vector bincodeSerialize() const; + static And bincodeDeserialize(std::vector); + }; - struct Witness { - uint32_t value; + struct Or { + friend bool operator==(const Or&, const Or&); + std::vector bincodeSerialize() const; + static Or bincodeDeserialize(std::vector); + }; - friend bool operator==(const Witness&, const Witness&); + struct Xor { + friend bool operator==(const Xor&, const Xor&); + std::vector bincodeSerialize() const; + static Xor bincodeDeserialize(std::vector); + }; + + struct Shl { + friend bool operator==(const Shl&, const Shl&); + std::vector bincodeSerialize() const; + static Shl bincodeDeserialize(std::vector); + }; + + struct Shr { + friend bool operator==(const Shr&, const Shr&); + std::vector bincodeSerialize() const; + static Shr bincodeDeserialize(std::vector); + }; + + std::variant value; + + friend bool operator==(const BinaryIntOp&, const BinaryIntOp&); std::vector bincodeSerialize() const; - static Witness bincodeDeserialize(std::vector); + static BinaryIntOp bincodeDeserialize(std::vector); }; - struct FunctionInput { - Circuit::Witness witness; - uint32_t num_bits; + struct MemoryAddress { + uint64_t value; - friend bool operator==(const FunctionInput&, const FunctionInput&); + friend bool operator==(const MemoryAddress&, const MemoryAddress&); std::vector bincodeSerialize() const; - static FunctionInput bincodeDeserialize(std::vector); + static MemoryAddress bincodeDeserialize(std::vector); }; - struct BlackBoxFuncCall { + struct HeapArray { + Program::MemoryAddress pointer; + uint64_t size; - struct AND { - Circuit::FunctionInput lhs; - Circuit::FunctionInput rhs; - Circuit::Witness output; + friend bool operator==(const HeapArray&, const HeapArray&); + std::vector bincodeSerialize() const; + static HeapArray bincodeDeserialize(std::vector); + }; - friend bool operator==(const AND&, const AND&); - std::vector bincodeSerialize() const; - static AND bincodeDeserialize(std::vector); - }; + struct HeapVector { + Program::MemoryAddress pointer; + Program::MemoryAddress size; - struct XOR { - Circuit::FunctionInput lhs; - Circuit::FunctionInput rhs; - Circuit::Witness output; + friend bool operator==(const HeapVector&, const HeapVector&); + std::vector bincodeSerialize() const; + static HeapVector bincodeDeserialize(std::vector); + }; - friend bool operator==(const XOR&, const XOR&); - std::vector bincodeSerialize() const; - static XOR bincodeDeserialize(std::vector); - }; + struct BlackBoxOp { - struct RANGE { - Circuit::FunctionInput input; + struct AES128Encrypt { + Program::HeapVector inputs; + Program::HeapArray iv; + Program::HeapArray key; + Program::HeapVector outputs; - friend bool operator==(const RANGE&, const RANGE&); + friend bool operator==(const AES128Encrypt&, const AES128Encrypt&); std::vector bincodeSerialize() const; - static RANGE bincodeDeserialize(std::vector); + static AES128Encrypt bincodeDeserialize(std::vector); }; - struct SHA256 { - std::vector inputs; - std::vector outputs; + struct Sha256 { + Program::HeapVector message; + Program::HeapArray output; - friend bool operator==(const SHA256&, const SHA256&); + friend bool operator==(const Sha256&, const Sha256&); std::vector bincodeSerialize() const; - static SHA256 bincodeDeserialize(std::vector); + static Sha256 bincodeDeserialize(std::vector); }; struct Blake2s { - std::vector inputs; - std::vector outputs; + Program::HeapVector message; + Program::HeapArray output; friend bool operator==(const Blake2s&, const Blake2s&); std::vector bincodeSerialize() const; @@ -673,52 +685,38 @@ namespace Circuit { }; struct Blake3 { - std::vector inputs; - std::vector outputs; + Program::HeapVector message; + Program::HeapArray output; friend bool operator==(const Blake3&, const Blake3&); std::vector bincodeSerialize() const; static Blake3 bincodeDeserialize(std::vector); }; - struct SchnorrVerify { - Circuit::FunctionInput public_key_x; - Circuit::FunctionInput public_key_y; - std::vector signature; - std::vector message; - Circuit::Witness output; - - friend bool operator==(const SchnorrVerify&, const SchnorrVerify&); - std::vector bincodeSerialize() const; - static SchnorrVerify bincodeDeserialize(std::vector); - }; - - struct PedersenCommitment { - std::vector inputs; - uint32_t domain_separator; - std::array outputs; + struct Keccak256 { + Program::HeapVector message; + Program::HeapArray output; - friend bool operator==(const PedersenCommitment&, const PedersenCommitment&); + friend bool operator==(const Keccak256&, const Keccak256&); std::vector bincodeSerialize() const; - static PedersenCommitment bincodeDeserialize(std::vector); + static Keccak256 bincodeDeserialize(std::vector); }; - struct PedersenHash { - std::vector inputs; - uint32_t domain_separator; - Circuit::Witness output; + struct Keccakf1600 { + Program::HeapVector message; + Program::HeapArray output; - friend bool operator==(const PedersenHash&, const PedersenHash&); + friend bool operator==(const Keccakf1600&, const Keccakf1600&); std::vector bincodeSerialize() const; - static PedersenHash bincodeDeserialize(std::vector); + static Keccakf1600 bincodeDeserialize(std::vector); }; struct EcdsaSecp256k1 { - std::vector public_key_x; - std::vector public_key_y; - std::vector signature; - std::vector hashed_message; - Circuit::Witness output; + Program::HeapVector hashed_msg; + Program::HeapArray public_key_x; + Program::HeapArray public_key_y; + Program::HeapArray signature; + Program::MemoryAddress result; friend bool operator==(const EcdsaSecp256k1&, const EcdsaSecp256k1&); std::vector bincodeSerialize() const; @@ -726,82 +724,77 @@ namespace Circuit { }; struct EcdsaSecp256r1 { - std::vector public_key_x; - std::vector public_key_y; - std::vector signature; - std::vector hashed_message; - Circuit::Witness output; - - friend bool operator==(const EcdsaSecp256r1&, const EcdsaSecp256r1&); - std::vector bincodeSerialize() const; - static EcdsaSecp256r1 bincodeDeserialize(std::vector); - }; - - struct FixedBaseScalarMul { - Circuit::FunctionInput low; - Circuit::FunctionInput high; - std::array outputs; + Program::HeapVector hashed_msg; + Program::HeapArray public_key_x; + Program::HeapArray public_key_y; + Program::HeapArray signature; + Program::MemoryAddress result; - friend bool operator==(const FixedBaseScalarMul&, const FixedBaseScalarMul&); + friend bool operator==(const EcdsaSecp256r1&, const EcdsaSecp256r1&); std::vector bincodeSerialize() const; - static FixedBaseScalarMul bincodeDeserialize(std::vector); + static EcdsaSecp256r1 bincodeDeserialize(std::vector); }; - struct EmbeddedCurveAdd { - Circuit::FunctionInput input1_x; - Circuit::FunctionInput input1_y; - Circuit::FunctionInput input2_x; - Circuit::FunctionInput input2_y; - std::array outputs; + struct SchnorrVerify { + Program::MemoryAddress public_key_x; + Program::MemoryAddress public_key_y; + Program::HeapVector message; + Program::HeapVector signature; + Program::MemoryAddress result; - friend bool operator==(const EmbeddedCurveAdd&, const EmbeddedCurveAdd&); + friend bool operator==(const SchnorrVerify&, const SchnorrVerify&); std::vector bincodeSerialize() const; - static EmbeddedCurveAdd bincodeDeserialize(std::vector); + static SchnorrVerify bincodeDeserialize(std::vector); }; - struct Keccak256 { - std::vector inputs; - std::vector outputs; + struct PedersenCommitment { + Program::HeapVector inputs; + Program::MemoryAddress domain_separator; + Program::HeapArray output; - friend bool operator==(const Keccak256&, const Keccak256&); + friend bool operator==(const PedersenCommitment&, const PedersenCommitment&); std::vector bincodeSerialize() const; - static Keccak256 bincodeDeserialize(std::vector); + static PedersenCommitment bincodeDeserialize(std::vector); }; - struct Keccak256VariableLength { - std::vector inputs; - Circuit::FunctionInput var_message_size; - std::vector outputs; + struct PedersenHash { + Program::HeapVector inputs; + Program::MemoryAddress domain_separator; + Program::MemoryAddress output; - friend bool operator==(const Keccak256VariableLength&, const Keccak256VariableLength&); + friend bool operator==(const PedersenHash&, const PedersenHash&); std::vector bincodeSerialize() const; - static Keccak256VariableLength bincodeDeserialize(std::vector); + static PedersenHash bincodeDeserialize(std::vector); }; - struct Keccakf1600 { - std::vector inputs; - std::vector outputs; + struct MultiScalarMul { + Program::HeapVector points; + Program::HeapVector scalars; + Program::HeapArray outputs; - friend bool operator==(const Keccakf1600&, const Keccakf1600&); + friend bool operator==(const MultiScalarMul&, const MultiScalarMul&); std::vector bincodeSerialize() const; - static Keccakf1600 bincodeDeserialize(std::vector); + static MultiScalarMul bincodeDeserialize(std::vector); }; - struct RecursiveAggregation { - std::vector verification_key; - std::vector proof; - std::vector public_inputs; - Circuit::FunctionInput key_hash; + struct EmbeddedCurveAdd { + Program::MemoryAddress input1_x; + Program::MemoryAddress input1_y; + Program::MemoryAddress input1_infinite; + Program::MemoryAddress input2_x; + Program::MemoryAddress input2_y; + Program::MemoryAddress input2_infinite; + Program::HeapArray result; - friend bool operator==(const RecursiveAggregation&, const RecursiveAggregation&); + friend bool operator==(const EmbeddedCurveAdd&, const EmbeddedCurveAdd&); std::vector bincodeSerialize() const; - static RecursiveAggregation bincodeDeserialize(std::vector); + static EmbeddedCurveAdd bincodeDeserialize(std::vector); }; struct BigIntAdd { - uint32_t lhs; - uint32_t rhs; - uint32_t output; + Program::MemoryAddress lhs; + Program::MemoryAddress rhs; + Program::MemoryAddress output; friend bool operator==(const BigIntAdd&, const BigIntAdd&); std::vector bincodeSerialize() const; @@ -809,9 +802,9 @@ namespace Circuit { }; struct BigIntSub { - uint32_t lhs; - uint32_t rhs; - uint32_t output; + Program::MemoryAddress lhs; + Program::MemoryAddress rhs; + Program::MemoryAddress output; friend bool operator==(const BigIntSub&, const BigIntSub&); std::vector bincodeSerialize() const; @@ -819,9 +812,9 @@ namespace Circuit { }; struct BigIntMul { - uint32_t lhs; - uint32_t rhs; - uint32_t output; + Program::MemoryAddress lhs; + Program::MemoryAddress rhs; + Program::MemoryAddress output; friend bool operator==(const BigIntMul&, const BigIntMul&); std::vector bincodeSerialize() const; @@ -829,9 +822,9 @@ namespace Circuit { }; struct BigIntDiv { - uint32_t lhs; - uint32_t rhs; - uint32_t output; + Program::MemoryAddress lhs; + Program::MemoryAddress rhs; + Program::MemoryAddress output; friend bool operator==(const BigIntDiv&, const BigIntDiv&); std::vector bincodeSerialize() const; @@ -839,9 +832,9 @@ namespace Circuit { }; struct BigIntFromLeBytes { - std::vector inputs; - std::vector modulus; - uint32_t output; + Program::HeapVector inputs; + Program::HeapVector modulus; + Program::MemoryAddress output; friend bool operator==(const BigIntFromLeBytes&, const BigIntFromLeBytes&); std::vector bincodeSerialize() const; @@ -849,8 +842,8 @@ namespace Circuit { }; struct BigIntToLeBytes { - uint32_t input; - std::vector outputs; + Program::MemoryAddress input; + Program::HeapVector output; friend bool operator==(const BigIntToLeBytes&, const BigIntToLeBytes&); std::vector bincodeSerialize() const; @@ -858,9 +851,9 @@ namespace Circuit { }; struct Poseidon2Permutation { - std::vector inputs; - std::vector outputs; - uint32_t len; + Program::HeapVector message; + Program::HeapArray output; + Program::MemoryAddress len; friend bool operator==(const Poseidon2Permutation&, const Poseidon2Permutation&); std::vector bincodeSerialize() const; @@ -868,196 +861,326 @@ namespace Circuit { }; struct Sha256Compression { - std::vector inputs; - std::vector hash_values; - std::vector outputs; + Program::HeapVector input; + Program::HeapVector hash_values; + Program::HeapArray output; friend bool operator==(const Sha256Compression&, const Sha256Compression&); std::vector bincodeSerialize() const; static Sha256Compression bincodeDeserialize(std::vector); }; - std::variant value; + struct ToRadix { + Program::MemoryAddress input; + uint32_t radix; + Program::HeapArray output; - friend bool operator==(const BlackBoxFuncCall&, const BlackBoxFuncCall&); - std::vector bincodeSerialize() const; - static BlackBoxFuncCall bincodeDeserialize(std::vector); - }; + friend bool operator==(const ToRadix&, const ToRadix&); + std::vector bincodeSerialize() const; + static ToRadix bincodeDeserialize(std::vector); + }; - struct BlockId { - uint32_t value; + std::variant value; - friend bool operator==(const BlockId&, const BlockId&); + friend bool operator==(const BlackBoxOp&, const BlackBoxOp&); std::vector bincodeSerialize() const; - static BlockId bincodeDeserialize(std::vector); + static BlackBoxOp bincodeDeserialize(std::vector); }; - struct Expression { - std::vector> mul_terms; - std::vector> linear_combinations; - std::string q_c; - - friend bool operator==(const Expression&, const Expression&); - std::vector bincodeSerialize() const; - static Expression bincodeDeserialize(std::vector); - }; + struct HeapValueType; - struct BrilligInputs { + struct HeapValueType { - struct Single { - Circuit::Expression value; + struct Simple { + uint32_t value; - friend bool operator==(const Single&, const Single&); + friend bool operator==(const Simple&, const Simple&); std::vector bincodeSerialize() const; - static Single bincodeDeserialize(std::vector); + static Simple bincodeDeserialize(std::vector); }; struct Array { - std::vector value; + std::vector value_types; + uint64_t size; friend bool operator==(const Array&, const Array&); std::vector bincodeSerialize() const; static Array bincodeDeserialize(std::vector); }; - struct MemoryArray { - Circuit::BlockId value; + struct Vector { + std::vector value_types; - friend bool operator==(const MemoryArray&, const MemoryArray&); + friend bool operator==(const Vector&, const Vector&); std::vector bincodeSerialize() const; - static MemoryArray bincodeDeserialize(std::vector); + static Vector bincodeDeserialize(std::vector); }; - std::variant value; + std::variant value; - friend bool operator==(const BrilligInputs&, const BrilligInputs&); + friend bool operator==(const HeapValueType&, const HeapValueType&); std::vector bincodeSerialize() const; - static BrilligInputs bincodeDeserialize(std::vector); + static HeapValueType bincodeDeserialize(std::vector); }; - struct BrilligOutputs { + struct ValueOrArray { - struct Simple { - Circuit::Witness value; + struct MemoryAddress { + Program::MemoryAddress value; - friend bool operator==(const Simple&, const Simple&); + friend bool operator==(const MemoryAddress&, const MemoryAddress&); std::vector bincodeSerialize() const; - static Simple bincodeDeserialize(std::vector); + static MemoryAddress bincodeDeserialize(std::vector); }; - struct Array { - std::vector value; + struct HeapArray { + Program::HeapArray value; - friend bool operator==(const Array&, const Array&); + friend bool operator==(const HeapArray&, const HeapArray&); std::vector bincodeSerialize() const; - static Array bincodeDeserialize(std::vector); + static HeapArray bincodeDeserialize(std::vector); }; - std::variant value; + struct HeapVector { + Program::HeapVector value; - friend bool operator==(const BrilligOutputs&, const BrilligOutputs&); - std::vector bincodeSerialize() const; - static BrilligOutputs bincodeDeserialize(std::vector); - }; + friend bool operator==(const HeapVector&, const HeapVector&); + std::vector bincodeSerialize() const; + static HeapVector bincodeDeserialize(std::vector); + }; - struct Brillig { - std::vector inputs; - std::vector outputs; - std::vector bytecode; - std::optional predicate; + std::variant value; - friend bool operator==(const Brillig&, const Brillig&); + friend bool operator==(const ValueOrArray&, const ValueOrArray&); std::vector bincodeSerialize() const; - static Brillig bincodeDeserialize(std::vector); + static ValueOrArray bincodeDeserialize(std::vector); }; - struct Directive { + struct BrilligOpcode { - struct ToLeRadix { - Circuit::Expression a; - std::vector b; - uint32_t radix; + struct BinaryFieldOp { + Program::MemoryAddress destination; + Program::BinaryFieldOp op; + Program::MemoryAddress lhs; + Program::MemoryAddress rhs; - friend bool operator==(const ToLeRadix&, const ToLeRadix&); + friend bool operator==(const BinaryFieldOp&, const BinaryFieldOp&); std::vector bincodeSerialize() const; - static ToLeRadix bincodeDeserialize(std::vector); + static BinaryFieldOp bincodeDeserialize(std::vector); }; - std::variant value; + struct BinaryIntOp { + Program::MemoryAddress destination; + Program::BinaryIntOp op; + uint32_t bit_size; + Program::MemoryAddress lhs; + Program::MemoryAddress rhs; - friend bool operator==(const Directive&, const Directive&); - std::vector bincodeSerialize() const; - static Directive bincodeDeserialize(std::vector); - }; + friend bool operator==(const BinaryIntOp&, const BinaryIntOp&); + std::vector bincodeSerialize() const; + static BinaryIntOp bincodeDeserialize(std::vector); + }; - struct MemOp { - Circuit::Expression operation; - Circuit::Expression index; - Circuit::Expression value; + struct Cast { + Program::MemoryAddress destination; + Program::MemoryAddress source; + uint32_t bit_size; - friend bool operator==(const MemOp&, const MemOp&); - std::vector bincodeSerialize() const; - static MemOp bincodeDeserialize(std::vector); - }; + friend bool operator==(const Cast&, const Cast&); + std::vector bincodeSerialize() const; + static Cast bincodeDeserialize(std::vector); + }; - struct Opcode { + struct JumpIfNot { + Program::MemoryAddress condition; + uint64_t location; - struct AssertZero { - Circuit::Expression value; + friend bool operator==(const JumpIfNot&, const JumpIfNot&); + std::vector bincodeSerialize() const; + static JumpIfNot bincodeDeserialize(std::vector); + }; - friend bool operator==(const AssertZero&, const AssertZero&); + struct JumpIf { + Program::MemoryAddress condition; + uint64_t location; + + friend bool operator==(const JumpIf&, const JumpIf&); std::vector bincodeSerialize() const; - static AssertZero bincodeDeserialize(std::vector); + static JumpIf bincodeDeserialize(std::vector); + }; + + struct Jump { + uint64_t location; + + friend bool operator==(const Jump&, const Jump&); + std::vector bincodeSerialize() const; + static Jump bincodeDeserialize(std::vector); + }; + + struct CalldataCopy { + Program::MemoryAddress destination_address; + uint64_t size; + uint64_t offset; + + friend bool operator==(const CalldataCopy&, const CalldataCopy&); + std::vector bincodeSerialize() const; + static CalldataCopy bincodeDeserialize(std::vector); + }; + + struct Call { + uint64_t location; + + friend bool operator==(const Call&, const Call&); + std::vector bincodeSerialize() const; + static Call bincodeDeserialize(std::vector); + }; + + struct Const { + Program::MemoryAddress destination; + uint32_t bit_size; + std::string value; + + friend bool operator==(const Const&, const Const&); + std::vector bincodeSerialize() const; + static Const bincodeDeserialize(std::vector); + }; + + struct Return { + friend bool operator==(const Return&, const Return&); + std::vector bincodeSerialize() const; + static Return bincodeDeserialize(std::vector); + }; + + struct ForeignCall { + std::string function; + std::vector destinations; + std::vector destination_value_types; + std::vector inputs; + std::vector input_value_types; + + friend bool operator==(const ForeignCall&, const ForeignCall&); + std::vector bincodeSerialize() const; + static ForeignCall bincodeDeserialize(std::vector); + }; + + struct Mov { + Program::MemoryAddress destination; + Program::MemoryAddress source; + + friend bool operator==(const Mov&, const Mov&); + std::vector bincodeSerialize() const; + static Mov bincodeDeserialize(std::vector); + }; + + struct ConditionalMov { + Program::MemoryAddress destination; + Program::MemoryAddress source_a; + Program::MemoryAddress source_b; + Program::MemoryAddress condition; + + friend bool operator==(const ConditionalMov&, const ConditionalMov&); + std::vector bincodeSerialize() const; + static ConditionalMov bincodeDeserialize(std::vector); + }; + + struct Load { + Program::MemoryAddress destination; + Program::MemoryAddress source_pointer; + + friend bool operator==(const Load&, const Load&); + std::vector bincodeSerialize() const; + static Load bincodeDeserialize(std::vector); + }; + + struct Store { + Program::MemoryAddress destination_pointer; + Program::MemoryAddress source; + + friend bool operator==(const Store&, const Store&); + std::vector bincodeSerialize() const; + static Store bincodeDeserialize(std::vector); + }; + + struct BlackBox { + Program::BlackBoxOp value; + + friend bool operator==(const BlackBox&, const BlackBox&); + std::vector bincodeSerialize() const; + static BlackBox bincodeDeserialize(std::vector); + }; + + struct Trap { + Program::HeapArray revert_data; + + friend bool operator==(const Trap&, const Trap&); + std::vector bincodeSerialize() const; + static Trap bincodeDeserialize(std::vector); + }; + + struct Stop { + uint64_t return_data_offset; + uint64_t return_data_size; + + friend bool operator==(const Stop&, const Stop&); + std::vector bincodeSerialize() const; + static Stop bincodeDeserialize(std::vector); }; - struct BlackBoxFuncCall { - Circuit::BlackBoxFuncCall value; + std::variant value; + + friend bool operator==(const BrilligOpcode&, const BrilligOpcode&); + std::vector bincodeSerialize() const; + static BrilligOpcode bincodeDeserialize(std::vector); + }; + + struct ExpressionOrMemory { - friend bool operator==(const BlackBoxFuncCall&, const BlackBoxFuncCall&); + struct Expression { + Program::Expression value; + + friend bool operator==(const Expression&, const Expression&); std::vector bincodeSerialize() const; - static BlackBoxFuncCall bincodeDeserialize(std::vector); + static Expression bincodeDeserialize(std::vector); }; - struct Directive { - Circuit::Directive value; + struct Memory { + Program::BlockId value; - friend bool operator==(const Directive&, const Directive&); + friend bool operator==(const Memory&, const Memory&); std::vector bincodeSerialize() const; - static Directive bincodeDeserialize(std::vector); + static Memory bincodeDeserialize(std::vector); }; - struct Brillig { - Circuit::Brillig value; + std::variant value; - friend bool operator==(const Brillig&, const Brillig&); - std::vector bincodeSerialize() const; - static Brillig bincodeDeserialize(std::vector); - }; + friend bool operator==(const ExpressionOrMemory&, const ExpressionOrMemory&); + std::vector bincodeSerialize() const; + static ExpressionOrMemory bincodeDeserialize(std::vector); + }; - struct MemoryOp { - Circuit::BlockId block_id; - Circuit::MemOp op; - std::optional predicate; + struct AssertionPayload { - friend bool operator==(const MemoryOp&, const MemoryOp&); + struct StaticString { + std::string value; + + friend bool operator==(const StaticString&, const StaticString&); std::vector bincodeSerialize() const; - static MemoryOp bincodeDeserialize(std::vector); + static StaticString bincodeDeserialize(std::vector); }; - struct MemoryInit { - Circuit::BlockId block_id; - std::vector init; + struct Dynamic { + std::tuple> value; - friend bool operator==(const MemoryInit&, const MemoryInit&); + friend bool operator==(const Dynamic&, const Dynamic&); std::vector bincodeSerialize() const; - static MemoryInit bincodeDeserialize(std::vector); + static Dynamic bincodeDeserialize(std::vector); }; - std::variant value; + std::variant value; - friend bool operator==(const Opcode&, const Opcode&); + friend bool operator==(const AssertionPayload&, const AssertionPayload&); std::vector bincodeSerialize() const; - static Opcode bincodeDeserialize(std::vector); + static AssertionPayload bincodeDeserialize(std::vector); }; struct ExpressionWidth { @@ -1110,7 +1233,7 @@ namespace Circuit { }; struct PublicInputs { - std::vector value; + std::vector value; friend bool operator==(const PublicInputs&, const PublicInputs&); std::vector bincodeSerialize() const; @@ -1119,12 +1242,12 @@ namespace Circuit { struct Circuit { uint32_t current_witness_index; - std::vector opcodes; - Circuit::ExpressionWidth expression_width; - std::vector private_parameters; - Circuit::PublicInputs public_parameters; - Circuit::PublicInputs return_values; - std::vector> assert_messages; + std::vector opcodes; + Program::ExpressionWidth expression_width; + std::vector private_parameters; + Program::PublicInputs public_parameters; + Program::PublicInputs return_values; + std::vector> assert_messages; bool recursive; friend bool operator==(const Circuit&, const Circuit&); @@ -1132,10 +1255,145 @@ namespace Circuit { static Circuit bincodeDeserialize(std::vector); }; -} // end of namespace Circuit + struct BrilligBytecode { + std::vector bytecode; + + friend bool operator==(const BrilligBytecode&, const BrilligBytecode&); + std::vector bincodeSerialize() const; + static BrilligBytecode bincodeDeserialize(std::vector); + }; + + struct Program { + std::vector functions; + std::vector unconstrained_functions; + + friend bool operator==(const Program&, const Program&); + std::vector bincodeSerialize() const; + static Program bincodeDeserialize(std::vector); + }; + +} // end of namespace Program + + +namespace Program { + + inline bool operator==(const AssertionPayload &lhs, const AssertionPayload &rhs) { + if (!(lhs.value == rhs.value)) { return false; } + return true; + } + + inline std::vector AssertionPayload::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } + + inline AssertionPayload AssertionPayload::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } + +} // end of namespace Program + +template <> +template +void serde::Serializable::serialize(const Program::AssertionPayload &obj, Serializer &serializer) { + serializer.increase_container_depth(); + serde::Serializable::serialize(obj.value, serializer); + serializer.decrease_container_depth(); +} + +template <> +template +Program::AssertionPayload serde::Deserializable::deserialize(Deserializer &deserializer) { + deserializer.increase_container_depth(); + Program::AssertionPayload obj; + obj.value = serde::Deserializable::deserialize(deserializer); + deserializer.decrease_container_depth(); + return obj; +} + +namespace Program { + + inline bool operator==(const AssertionPayload::StaticString &lhs, const AssertionPayload::StaticString &rhs) { + if (!(lhs.value == rhs.value)) { return false; } + return true; + } + + inline std::vector AssertionPayload::StaticString::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } + + inline AssertionPayload::StaticString AssertionPayload::StaticString::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } + +} // end of namespace Program + +template <> +template +void serde::Serializable::serialize(const Program::AssertionPayload::StaticString &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.value, serializer); +} + +template <> +template +Program::AssertionPayload::StaticString serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::AssertionPayload::StaticString obj; + obj.value = serde::Deserializable::deserialize(deserializer); + return obj; +} + +namespace Program { + + inline bool operator==(const AssertionPayload::Dynamic &lhs, const AssertionPayload::Dynamic &rhs) { + if (!(lhs.value == rhs.value)) { return false; } + return true; + } + + inline std::vector AssertionPayload::Dynamic::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } + + inline AssertionPayload::Dynamic AssertionPayload::Dynamic::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } + +} // end of namespace Program + +template <> +template +void serde::Serializable::serialize(const Program::AssertionPayload::Dynamic &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.value, serializer); +} +template <> +template +Program::AssertionPayload::Dynamic serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::AssertionPayload::Dynamic obj; + obj.value = serde::Deserializable::deserialize(deserializer); + return obj; +} -namespace Circuit { +namespace Program { inline bool operator==(const BinaryFieldOp &lhs, const BinaryFieldOp &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -1157,11 +1415,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryFieldOp &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryFieldOp &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -1169,15 +1427,15 @@ void serde::Serializable::serialize(const Circuit::Binar template <> template -Circuit::BinaryFieldOp serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::BinaryFieldOp serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::BinaryFieldOp obj; + Program::BinaryFieldOp obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryFieldOp::Add &lhs, const BinaryFieldOp::Add &rhs) { return true; @@ -1198,21 +1456,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryFieldOp::Add &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryFieldOp::Add &obj, Serializer &serializer) { } template <> template -Circuit::BinaryFieldOp::Add serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BinaryFieldOp::Add obj; +Program::BinaryFieldOp::Add serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryFieldOp::Add obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryFieldOp::Sub &lhs, const BinaryFieldOp::Sub &rhs) { return true; @@ -1233,21 +1491,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryFieldOp::Sub &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryFieldOp::Sub &obj, Serializer &serializer) { } template <> template -Circuit::BinaryFieldOp::Sub serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BinaryFieldOp::Sub obj; +Program::BinaryFieldOp::Sub serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryFieldOp::Sub obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryFieldOp::Mul &lhs, const BinaryFieldOp::Mul &rhs) { return true; @@ -1268,21 +1526,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryFieldOp::Mul &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryFieldOp::Mul &obj, Serializer &serializer) { } template <> template -Circuit::BinaryFieldOp::Mul serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BinaryFieldOp::Mul obj; +Program::BinaryFieldOp::Mul serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryFieldOp::Mul obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryFieldOp::Div &lhs, const BinaryFieldOp::Div &rhs) { return true; @@ -1303,21 +1561,56 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program + +template <> +template +void serde::Serializable::serialize(const Program::BinaryFieldOp::Div &obj, Serializer &serializer) { +} + +template <> +template +Program::BinaryFieldOp::Div serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryFieldOp::Div obj; + return obj; +} + +namespace Program { + + inline bool operator==(const BinaryFieldOp::IntegerDiv &lhs, const BinaryFieldOp::IntegerDiv &rhs) { + return true; + } + + inline std::vector BinaryFieldOp::IntegerDiv::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } + + inline BinaryFieldOp::IntegerDiv BinaryFieldOp::IntegerDiv::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } + +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryFieldOp::Div &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryFieldOp::IntegerDiv &obj, Serializer &serializer) { } template <> template -Circuit::BinaryFieldOp::Div serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BinaryFieldOp::Div obj; +Program::BinaryFieldOp::IntegerDiv serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryFieldOp::IntegerDiv obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryFieldOp::Equals &lhs, const BinaryFieldOp::Equals &rhs) { return true; @@ -1338,21 +1631,91 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program + +template <> +template +void serde::Serializable::serialize(const Program::BinaryFieldOp::Equals &obj, Serializer &serializer) { +} + +template <> +template +Program::BinaryFieldOp::Equals serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryFieldOp::Equals obj; + return obj; +} + +namespace Program { + + inline bool operator==(const BinaryFieldOp::LessThan &lhs, const BinaryFieldOp::LessThan &rhs) { + return true; + } + + inline std::vector BinaryFieldOp::LessThan::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } + + inline BinaryFieldOp::LessThan BinaryFieldOp::LessThan::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } + +} // end of namespace Program + +template <> +template +void serde::Serializable::serialize(const Program::BinaryFieldOp::LessThan &obj, Serializer &serializer) { +} + +template <> +template +Program::BinaryFieldOp::LessThan serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryFieldOp::LessThan obj; + return obj; +} + +namespace Program { + + inline bool operator==(const BinaryFieldOp::LessThanEquals &lhs, const BinaryFieldOp::LessThanEquals &rhs) { + return true; + } + + inline std::vector BinaryFieldOp::LessThanEquals::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } + + inline BinaryFieldOp::LessThanEquals BinaryFieldOp::LessThanEquals::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } + +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryFieldOp::Equals &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryFieldOp::LessThanEquals &obj, Serializer &serializer) { } template <> template -Circuit::BinaryFieldOp::Equals serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BinaryFieldOp::Equals obj; +Program::BinaryFieldOp::LessThanEquals serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryFieldOp::LessThanEquals obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp &lhs, const BinaryIntOp &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -1374,11 +1737,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryIntOp &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryIntOp &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -1386,15 +1749,15 @@ void serde::Serializable::serialize(const Circuit::BinaryI template <> template -Circuit::BinaryIntOp serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::BinaryIntOp serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::BinaryIntOp obj; + Program::BinaryIntOp obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::Add &lhs, const BinaryIntOp::Add &rhs) { return true; @@ -1415,21 +1778,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::Add &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryIntOp::Add &obj, Serializer &serializer) { } template <> template -Circuit::BinaryIntOp::Add serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BinaryIntOp::Add obj; +Program::BinaryIntOp::Add serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryIntOp::Add obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::Sub &lhs, const BinaryIntOp::Sub &rhs) { return true; @@ -1450,21 +1813,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::Sub &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryIntOp::Sub &obj, Serializer &serializer) { } template <> template -Circuit::BinaryIntOp::Sub serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BinaryIntOp::Sub obj; +Program::BinaryIntOp::Sub serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryIntOp::Sub obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::Mul &lhs, const BinaryIntOp::Mul &rhs) { return true; @@ -1485,91 +1848,56 @@ namespace Circuit { return value; } -} // end of namespace Circuit - -template <> -template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::Mul &obj, Serializer &serializer) { -} - -template <> -template -Circuit::BinaryIntOp::Mul serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BinaryIntOp::Mul obj; - return obj; -} - -namespace Circuit { - - inline bool operator==(const BinaryIntOp::SignedDiv &lhs, const BinaryIntOp::SignedDiv &rhs) { - return true; - } - - inline std::vector BinaryIntOp::SignedDiv::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); - } - - inline BinaryIntOp::SignedDiv BinaryIntOp::SignedDiv::bincodeDeserialize(std::vector input) { - auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); - if (deserializer.get_buffer_offset() < input.size()) { - throw serde::deserialization_error("Some input bytes were not read"); - } - return value; - } - -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::SignedDiv &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryIntOp::Mul &obj, Serializer &serializer) { } template <> template -Circuit::BinaryIntOp::SignedDiv serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BinaryIntOp::SignedDiv obj; +Program::BinaryIntOp::Mul serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryIntOp::Mul obj; return obj; } -namespace Circuit { +namespace Program { - inline bool operator==(const BinaryIntOp::UnsignedDiv &lhs, const BinaryIntOp::UnsignedDiv &rhs) { + inline bool operator==(const BinaryIntOp::Div &lhs, const BinaryIntOp::Div &rhs) { return true; } - inline std::vector BinaryIntOp::UnsignedDiv::bincodeSerialize() const { + inline std::vector BinaryIntOp::Div::bincodeSerialize() const { auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); + serde::Serializable::serialize(*this, serializer); return std::move(serializer).bytes(); } - inline BinaryIntOp::UnsignedDiv BinaryIntOp::UnsignedDiv::bincodeDeserialize(std::vector input) { + inline BinaryIntOp::Div BinaryIntOp::Div::bincodeDeserialize(std::vector input) { auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); + auto value = serde::Deserializable::deserialize(deserializer); if (deserializer.get_buffer_offset() < input.size()) { throw serde::deserialization_error("Some input bytes were not read"); } return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::UnsignedDiv &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryIntOp::Div &obj, Serializer &serializer) { } template <> template -Circuit::BinaryIntOp::UnsignedDiv serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BinaryIntOp::UnsignedDiv obj; +Program::BinaryIntOp::Div serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryIntOp::Div obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::Equals &lhs, const BinaryIntOp::Equals &rhs) { return true; @@ -1590,21 +1918,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::Equals &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryIntOp::Equals &obj, Serializer &serializer) { } template <> template -Circuit::BinaryIntOp::Equals serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BinaryIntOp::Equals obj; +Program::BinaryIntOp::Equals serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryIntOp::Equals obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::LessThan &lhs, const BinaryIntOp::LessThan &rhs) { return true; @@ -1625,21 +1953,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::LessThan &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryIntOp::LessThan &obj, Serializer &serializer) { } template <> template -Circuit::BinaryIntOp::LessThan serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BinaryIntOp::LessThan obj; +Program::BinaryIntOp::LessThan serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryIntOp::LessThan obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::LessThanEquals &lhs, const BinaryIntOp::LessThanEquals &rhs) { return true; @@ -1660,21 +1988,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::LessThanEquals &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryIntOp::LessThanEquals &obj, Serializer &serializer) { } template <> template -Circuit::BinaryIntOp::LessThanEquals serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BinaryIntOp::LessThanEquals obj; +Program::BinaryIntOp::LessThanEquals serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryIntOp::LessThanEquals obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::And &lhs, const BinaryIntOp::And &rhs) { return true; @@ -1695,21 +2023,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::And &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryIntOp::And &obj, Serializer &serializer) { } template <> template -Circuit::BinaryIntOp::And serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BinaryIntOp::And obj; +Program::BinaryIntOp::And serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryIntOp::And obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::Or &lhs, const BinaryIntOp::Or &rhs) { return true; @@ -1730,21 +2058,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::Or &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryIntOp::Or &obj, Serializer &serializer) { } template <> template -Circuit::BinaryIntOp::Or serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BinaryIntOp::Or obj; +Program::BinaryIntOp::Or serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryIntOp::Or obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::Xor &lhs, const BinaryIntOp::Xor &rhs) { return true; @@ -1765,21 +2093,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::Xor &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryIntOp::Xor &obj, Serializer &serializer) { } template <> template -Circuit::BinaryIntOp::Xor serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BinaryIntOp::Xor obj; +Program::BinaryIntOp::Xor serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryIntOp::Xor obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::Shl &lhs, const BinaryIntOp::Shl &rhs) { return true; @@ -1800,21 +2128,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::Shl &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryIntOp::Shl &obj, Serializer &serializer) { } template <> template -Circuit::BinaryIntOp::Shl serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BinaryIntOp::Shl obj; +Program::BinaryIntOp::Shl serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryIntOp::Shl obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::Shr &lhs, const BinaryIntOp::Shr &rhs) { return true; @@ -1835,21 +2163,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::Shr &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryIntOp::Shr &obj, Serializer &serializer) { } template <> template -Circuit::BinaryIntOp::Shr serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BinaryIntOp::Shr obj; +Program::BinaryIntOp::Shr serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryIntOp::Shr obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall &lhs, const BlackBoxFuncCall &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -1862,36 +2190,83 @@ namespace Circuit { return std::move(serializer).bytes(); } - inline BlackBoxFuncCall BlackBoxFuncCall::bincodeDeserialize(std::vector input) { + inline BlackBoxFuncCall BlackBoxFuncCall::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } + +} // end of namespace Program + +template <> +template +void serde::Serializable::serialize(const Program::BlackBoxFuncCall &obj, Serializer &serializer) { + serializer.increase_container_depth(); + serde::Serializable::serialize(obj.value, serializer); + serializer.decrease_container_depth(); +} + +template <> +template +Program::BlackBoxFuncCall serde::Deserializable::deserialize(Deserializer &deserializer) { + deserializer.increase_container_depth(); + Program::BlackBoxFuncCall obj; + obj.value = serde::Deserializable::deserialize(deserializer); + deserializer.decrease_container_depth(); + return obj; +} + +namespace Program { + + inline bool operator==(const BlackBoxFuncCall::AES128Encrypt &lhs, const BlackBoxFuncCall::AES128Encrypt &rhs) { + if (!(lhs.inputs == rhs.inputs)) { return false; } + if (!(lhs.iv == rhs.iv)) { return false; } + if (!(lhs.key == rhs.key)) { return false; } + if (!(lhs.outputs == rhs.outputs)) { return false; } + return true; + } + + inline std::vector BlackBoxFuncCall::AES128Encrypt::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } + + inline BlackBoxFuncCall::AES128Encrypt BlackBoxFuncCall::AES128Encrypt::bincodeDeserialize(std::vector input) { auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); + auto value = serde::Deserializable::deserialize(deserializer); if (deserializer.get_buffer_offset() < input.size()) { throw serde::deserialization_error("Some input bytes were not read"); } return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall &obj, Serializer &serializer) { - serializer.increase_container_depth(); - serde::Serializable::serialize(obj.value, serializer); - serializer.decrease_container_depth(); +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::AES128Encrypt &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.inputs, serializer); + serde::Serializable::serialize(obj.iv, serializer); + serde::Serializable::serialize(obj.key, serializer); + serde::Serializable::serialize(obj.outputs, serializer); } template <> template -Circuit::BlackBoxFuncCall serde::Deserializable::deserialize(Deserializer &deserializer) { - deserializer.increase_container_depth(); - Circuit::BlackBoxFuncCall obj; - obj.value = serde::Deserializable::deserialize(deserializer); - deserializer.decrease_container_depth(); +Program::BlackBoxFuncCall::AES128Encrypt serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::AES128Encrypt obj; + obj.inputs = serde::Deserializable::deserialize(deserializer); + obj.iv = serde::Deserializable::deserialize(deserializer); + obj.key = serde::Deserializable::deserialize(deserializer); + obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::AND &lhs, const BlackBoxFuncCall::AND &rhs) { if (!(lhs.lhs == rhs.lhs)) { return false; } @@ -1915,11 +2290,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::AND &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::AND &obj, Serializer &serializer) { serde::Serializable::serialize(obj.lhs, serializer); serde::Serializable::serialize(obj.rhs, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -1927,15 +2302,15 @@ void serde::Serializable::serialize(const Circui template <> template -Circuit::BlackBoxFuncCall::AND serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::AND obj; +Program::BlackBoxFuncCall::AND serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::AND obj; obj.lhs = serde::Deserializable::deserialize(deserializer); obj.rhs = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::XOR &lhs, const BlackBoxFuncCall::XOR &rhs) { if (!(lhs.lhs == rhs.lhs)) { return false; } @@ -1959,11 +2334,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::XOR &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::XOR &obj, Serializer &serializer) { serde::Serializable::serialize(obj.lhs, serializer); serde::Serializable::serialize(obj.rhs, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -1971,15 +2346,15 @@ void serde::Serializable::serialize(const Circui template <> template -Circuit::BlackBoxFuncCall::XOR serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::XOR obj; +Program::BlackBoxFuncCall::XOR serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::XOR obj; obj.lhs = serde::Deserializable::deserialize(deserializer); obj.rhs = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::RANGE &lhs, const BlackBoxFuncCall::RANGE &rhs) { if (!(lhs.input == rhs.input)) { return false; } @@ -2001,23 +2376,23 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::RANGE &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::RANGE &obj, Serializer &serializer) { serde::Serializable::serialize(obj.input, serializer); } template <> template -Circuit::BlackBoxFuncCall::RANGE serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::RANGE obj; +Program::BlackBoxFuncCall::RANGE serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::RANGE obj; obj.input = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::SHA256 &lhs, const BlackBoxFuncCall::SHA256 &rhs) { if (!(lhs.inputs == rhs.inputs)) { return false; } @@ -2040,25 +2415,25 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::SHA256 &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::SHA256 &obj, Serializer &serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.outputs, serializer); } template <> template -Circuit::BlackBoxFuncCall::SHA256 serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::SHA256 obj; +Program::BlackBoxFuncCall::SHA256 serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::SHA256 obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::Blake2s &lhs, const BlackBoxFuncCall::Blake2s &rhs) { if (!(lhs.inputs == rhs.inputs)) { return false; } @@ -2081,25 +2456,25 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::Blake2s &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::Blake2s &obj, Serializer &serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.outputs, serializer); } template <> template -Circuit::BlackBoxFuncCall::Blake2s serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::Blake2s obj; +Program::BlackBoxFuncCall::Blake2s serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::Blake2s obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::Blake3 &lhs, const BlackBoxFuncCall::Blake3 &rhs) { if (!(lhs.inputs == rhs.inputs)) { return false; } @@ -2122,25 +2497,25 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::Blake3 &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::Blake3 &obj, Serializer &serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.outputs, serializer); } template <> template -Circuit::BlackBoxFuncCall::Blake3 serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::Blake3 obj; +Program::BlackBoxFuncCall::Blake3 serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::Blake3 obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::SchnorrVerify &lhs, const BlackBoxFuncCall::SchnorrVerify &rhs) { if (!(lhs.public_key_x == rhs.public_key_x)) { return false; } @@ -2166,11 +2541,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::SchnorrVerify &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::SchnorrVerify &obj, Serializer &serializer) { serde::Serializable::serialize(obj.public_key_x, serializer); serde::Serializable::serialize(obj.public_key_y, serializer); serde::Serializable::serialize(obj.signature, serializer); @@ -2180,8 +2555,8 @@ void serde::Serializable::serialize(co template <> template -Circuit::BlackBoxFuncCall::SchnorrVerify serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::SchnorrVerify obj; +Program::BlackBoxFuncCall::SchnorrVerify serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::SchnorrVerify obj; obj.public_key_x = serde::Deserializable::deserialize(deserializer); obj.public_key_y = serde::Deserializable::deserialize(deserializer); obj.signature = serde::Deserializable::deserialize(deserializer); @@ -2190,7 +2565,7 @@ Circuit::BlackBoxFuncCall::SchnorrVerify serde::Deserializable template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::PedersenCommitment &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::PedersenCommitment &obj, Serializer &serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.domain_separator, serializer); serde::Serializable::serialize(obj.outputs, serializer); @@ -2226,15 +2601,15 @@ void serde::Serializable::seriali template <> template -Circuit::BlackBoxFuncCall::PedersenCommitment serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::PedersenCommitment obj; +Program::BlackBoxFuncCall::PedersenCommitment serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::PedersenCommitment obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.domain_separator = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::PedersenHash &lhs, const BlackBoxFuncCall::PedersenHash &rhs) { if (!(lhs.inputs == rhs.inputs)) { return false; } @@ -2258,11 +2633,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::PedersenHash &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::PedersenHash &obj, Serializer &serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.domain_separator, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -2270,15 +2645,15 @@ void serde::Serializable::serialize(con template <> template -Circuit::BlackBoxFuncCall::PedersenHash serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::PedersenHash obj; +Program::BlackBoxFuncCall::PedersenHash serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::PedersenHash obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.domain_separator = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::EcdsaSecp256k1 &lhs, const BlackBoxFuncCall::EcdsaSecp256k1 &rhs) { if (!(lhs.public_key_x == rhs.public_key_x)) { return false; } @@ -2304,11 +2679,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::EcdsaSecp256k1 &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::EcdsaSecp256k1 &obj, Serializer &serializer) { serde::Serializable::serialize(obj.public_key_x, serializer); serde::Serializable::serialize(obj.public_key_y, serializer); serde::Serializable::serialize(obj.signature, serializer); @@ -2318,8 +2693,8 @@ void serde::Serializable::serialize(c template <> template -Circuit::BlackBoxFuncCall::EcdsaSecp256k1 serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::EcdsaSecp256k1 obj; +Program::BlackBoxFuncCall::EcdsaSecp256k1 serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::EcdsaSecp256k1 obj; obj.public_key_x = serde::Deserializable::deserialize(deserializer); obj.public_key_y = serde::Deserializable::deserialize(deserializer); obj.signature = serde::Deserializable::deserialize(deserializer); @@ -2328,7 +2703,7 @@ Circuit::BlackBoxFuncCall::EcdsaSecp256k1 serde::Deserializable template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::EcdsaSecp256r1 &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::EcdsaSecp256r1 &obj, Serializer &serializer) { serde::Serializable::serialize(obj.public_key_x, serializer); serde::Serializable::serialize(obj.public_key_y, serializer); serde::Serializable::serialize(obj.signature, serializer); @@ -2368,8 +2743,8 @@ void serde::Serializable::serialize(c template <> template -Circuit::BlackBoxFuncCall::EcdsaSecp256r1 serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::EcdsaSecp256r1 obj; +Program::BlackBoxFuncCall::EcdsaSecp256r1 serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::EcdsaSecp256r1 obj; obj.public_key_x = serde::Deserializable::deserialize(deserializer); obj.public_key_y = serde::Deserializable::deserialize(deserializer); obj.signature = serde::Deserializable::deserialize(deserializer); @@ -2378,57 +2753,55 @@ Circuit::BlackBoxFuncCall::EcdsaSecp256r1 serde::Deserializable BlackBoxFuncCall::FixedBaseScalarMul::bincodeSerialize() const { + inline std::vector BlackBoxFuncCall::MultiScalarMul::bincodeSerialize() const { auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); + serde::Serializable::serialize(*this, serializer); return std::move(serializer).bytes(); } - inline BlackBoxFuncCall::FixedBaseScalarMul BlackBoxFuncCall::FixedBaseScalarMul::bincodeDeserialize(std::vector input) { + inline BlackBoxFuncCall::MultiScalarMul BlackBoxFuncCall::MultiScalarMul::bincodeDeserialize(std::vector input) { auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); + auto value = serde::Deserializable::deserialize(deserializer); if (deserializer.get_buffer_offset() < input.size()) { throw serde::deserialization_error("Some input bytes were not read"); } return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::FixedBaseScalarMul &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.low, serializer); - serde::Serializable::serialize(obj.high, serializer); +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::MultiScalarMul &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.points, serializer); + serde::Serializable::serialize(obj.scalars, serializer); serde::Serializable::serialize(obj.outputs, serializer); } template <> template -Circuit::BlackBoxFuncCall::FixedBaseScalarMul serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::FixedBaseScalarMul obj; - obj.low = serde::Deserializable::deserialize(deserializer); - obj.high = serde::Deserializable::deserialize(deserializer); +Program::BlackBoxFuncCall::MultiScalarMul serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::MultiScalarMul obj; + obj.points = serde::Deserializable::deserialize(deserializer); + obj.scalars = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::EmbeddedCurveAdd &lhs, const BlackBoxFuncCall::EmbeddedCurveAdd &rhs) { - if (!(lhs.input1_x == rhs.input1_x)) { return false; } - if (!(lhs.input1_y == rhs.input1_y)) { return false; } - if (!(lhs.input2_x == rhs.input2_x)) { return false; } - if (!(lhs.input2_y == rhs.input2_y)) { return false; } + if (!(lhs.input1 == rhs.input1)) { return false; } + if (!(lhs.input2 == rhs.input2)) { return false; } if (!(lhs.outputs == rhs.outputs)) { return false; } return true; } @@ -2448,34 +2821,31 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::EmbeddedCurveAdd &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.input1_x, serializer); - serde::Serializable::serialize(obj.input1_y, serializer); - serde::Serializable::serialize(obj.input2_x, serializer); - serde::Serializable::serialize(obj.input2_y, serializer); +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::EmbeddedCurveAdd &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.input1, serializer); + serde::Serializable::serialize(obj.input2, serializer); serde::Serializable::serialize(obj.outputs, serializer); } template <> template -Circuit::BlackBoxFuncCall::EmbeddedCurveAdd serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::EmbeddedCurveAdd obj; - obj.input1_x = serde::Deserializable::deserialize(deserializer); - obj.input1_y = serde::Deserializable::deserialize(deserializer); - obj.input2_x = serde::Deserializable::deserialize(deserializer); - obj.input2_y = serde::Deserializable::deserialize(deserializer); +Program::BlackBoxFuncCall::EmbeddedCurveAdd serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::EmbeddedCurveAdd obj; + obj.input1 = serde::Deserializable::deserialize(deserializer); + obj.input2 = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::Keccak256 &lhs, const BlackBoxFuncCall::Keccak256 &rhs) { if (!(lhs.inputs == rhs.inputs)) { return false; } + if (!(lhs.var_message_size == rhs.var_message_size)) { return false; } if (!(lhs.outputs == rhs.outputs)) { return false; } return true; } @@ -2495,53 +2865,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit - -template <> -template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::Keccak256 &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.inputs, serializer); - serde::Serializable::serialize(obj.outputs, serializer); -} - -template <> -template -Circuit::BlackBoxFuncCall::Keccak256 serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::Keccak256 obj; - obj.inputs = serde::Deserializable::deserialize(deserializer); - obj.outputs = serde::Deserializable::deserialize(deserializer); - return obj; -} - -namespace Circuit { - - inline bool operator==(const BlackBoxFuncCall::Keccak256VariableLength &lhs, const BlackBoxFuncCall::Keccak256VariableLength &rhs) { - if (!(lhs.inputs == rhs.inputs)) { return false; } - if (!(lhs.var_message_size == rhs.var_message_size)) { return false; } - if (!(lhs.outputs == rhs.outputs)) { return false; } - return true; - } - - inline std::vector BlackBoxFuncCall::Keccak256VariableLength::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); - } - - inline BlackBoxFuncCall::Keccak256VariableLength BlackBoxFuncCall::Keccak256VariableLength::bincodeDeserialize(std::vector input) { - auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); - if (deserializer.get_buffer_offset() < input.size()) { - throw serde::deserialization_error("Some input bytes were not read"); - } - return value; - } - -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::Keccak256VariableLength &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::Keccak256 &obj, Serializer &serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.var_message_size, serializer); serde::Serializable::serialize(obj.outputs, serializer); @@ -2549,15 +2877,15 @@ void serde::Serializable::se template <> template -Circuit::BlackBoxFuncCall::Keccak256VariableLength serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::Keccak256VariableLength obj; +Program::BlackBoxFuncCall::Keccak256 serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::Keccak256 obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.var_message_size = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::Keccakf1600 &lhs, const BlackBoxFuncCall::Keccakf1600 &rhs) { if (!(lhs.inputs == rhs.inputs)) { return false; } @@ -2580,25 +2908,25 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::Keccakf1600 &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::Keccakf1600 &obj, Serializer &serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.outputs, serializer); } template <> template -Circuit::BlackBoxFuncCall::Keccakf1600 serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::Keccakf1600 obj; +Program::BlackBoxFuncCall::Keccakf1600 serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::Keccakf1600 obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::RecursiveAggregation &lhs, const BlackBoxFuncCall::RecursiveAggregation &rhs) { if (!(lhs.verification_key == rhs.verification_key)) { return false; } @@ -2623,11 +2951,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::RecursiveAggregation &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::RecursiveAggregation &obj, Serializer &serializer) { serde::Serializable::serialize(obj.verification_key, serializer); serde::Serializable::serialize(obj.proof, serializer); serde::Serializable::serialize(obj.public_inputs, serializer); @@ -2636,8 +2964,8 @@ void serde::Serializable::seria template <> template -Circuit::BlackBoxFuncCall::RecursiveAggregation serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::RecursiveAggregation obj; +Program::BlackBoxFuncCall::RecursiveAggregation serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::RecursiveAggregation obj; obj.verification_key = serde::Deserializable::deserialize(deserializer); obj.proof = serde::Deserializable::deserialize(deserializer); obj.public_inputs = serde::Deserializable::deserialize(deserializer); @@ -2645,7 +2973,7 @@ Circuit::BlackBoxFuncCall::RecursiveAggregation serde::Deserializable template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::BigIntAdd &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::BigIntAdd &obj, Serializer &serializer) { serde::Serializable::serialize(obj.lhs, serializer); serde::Serializable::serialize(obj.rhs, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -2681,15 +3009,15 @@ void serde::Serializable::serialize(const template <> template -Circuit::BlackBoxFuncCall::BigIntAdd serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::BigIntAdd obj; +Program::BlackBoxFuncCall::BigIntAdd serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::BigIntAdd obj; obj.lhs = serde::Deserializable::deserialize(deserializer); obj.rhs = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::BigIntSub &lhs, const BlackBoxFuncCall::BigIntSub &rhs) { if (!(lhs.lhs == rhs.lhs)) { return false; } @@ -2713,11 +3041,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::BigIntSub &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::BigIntSub &obj, Serializer &serializer) { serde::Serializable::serialize(obj.lhs, serializer); serde::Serializable::serialize(obj.rhs, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -2725,15 +3053,15 @@ void serde::Serializable::serialize(const template <> template -Circuit::BlackBoxFuncCall::BigIntSub serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::BigIntSub obj; +Program::BlackBoxFuncCall::BigIntSub serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::BigIntSub obj; obj.lhs = serde::Deserializable::deserialize(deserializer); obj.rhs = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::BigIntMul &lhs, const BlackBoxFuncCall::BigIntMul &rhs) { if (!(lhs.lhs == rhs.lhs)) { return false; } @@ -2757,11 +3085,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::BigIntMul &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::BigIntMul &obj, Serializer &serializer) { serde::Serializable::serialize(obj.lhs, serializer); serde::Serializable::serialize(obj.rhs, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -2769,15 +3097,15 @@ void serde::Serializable::serialize(const template <> template -Circuit::BlackBoxFuncCall::BigIntMul serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::BigIntMul obj; +Program::BlackBoxFuncCall::BigIntMul serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::BigIntMul obj; obj.lhs = serde::Deserializable::deserialize(deserializer); obj.rhs = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::BigIntDiv &lhs, const BlackBoxFuncCall::BigIntDiv &rhs) { if (!(lhs.lhs == rhs.lhs)) { return false; } @@ -2801,11 +3129,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::BigIntDiv &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::BigIntDiv &obj, Serializer &serializer) { serde::Serializable::serialize(obj.lhs, serializer); serde::Serializable::serialize(obj.rhs, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -2813,15 +3141,15 @@ void serde::Serializable::serialize(const template <> template -Circuit::BlackBoxFuncCall::BigIntDiv serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::BigIntDiv obj; +Program::BlackBoxFuncCall::BigIntDiv serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::BigIntDiv obj; obj.lhs = serde::Deserializable::deserialize(deserializer); obj.rhs = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::BigIntFromLeBytes &lhs, const BlackBoxFuncCall::BigIntFromLeBytes &rhs) { if (!(lhs.inputs == rhs.inputs)) { return false; } @@ -2845,11 +3173,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::BigIntFromLeBytes &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::BigIntFromLeBytes &obj, Serializer &serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.modulus, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -2857,15 +3185,15 @@ void serde::Serializable::serializ template <> template -Circuit::BlackBoxFuncCall::BigIntFromLeBytes serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::BigIntFromLeBytes obj; +Program::BlackBoxFuncCall::BigIntFromLeBytes serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::BigIntFromLeBytes obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.modulus = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::BigIntToLeBytes &lhs, const BlackBoxFuncCall::BigIntToLeBytes &rhs) { if (!(lhs.input == rhs.input)) { return false; } @@ -2888,25 +3216,25 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::BigIntToLeBytes &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::BigIntToLeBytes &obj, Serializer &serializer) { serde::Serializable::serialize(obj.input, serializer); serde::Serializable::serialize(obj.outputs, serializer); } template <> template -Circuit::BlackBoxFuncCall::BigIntToLeBytes serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::BigIntToLeBytes obj; +Program::BlackBoxFuncCall::BigIntToLeBytes serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::BigIntToLeBytes obj; obj.input = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::Poseidon2Permutation &lhs, const BlackBoxFuncCall::Poseidon2Permutation &rhs) { if (!(lhs.inputs == rhs.inputs)) { return false; } @@ -2930,11 +3258,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::Poseidon2Permutation &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::Poseidon2Permutation &obj, Serializer &serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.outputs, serializer); serde::Serializable::serialize(obj.len, serializer); @@ -2942,15 +3270,15 @@ void serde::Serializable::seria template <> template -Circuit::BlackBoxFuncCall::Poseidon2Permutation serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::Poseidon2Permutation obj; +Program::BlackBoxFuncCall::Poseidon2Permutation serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::Poseidon2Permutation obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); obj.len = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::Sha256Compression &lhs, const BlackBoxFuncCall::Sha256Compression &rhs) { if (!(lhs.inputs == rhs.inputs)) { return false; } @@ -2974,11 +3302,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::Sha256Compression &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::Sha256Compression &obj, Serializer &serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.hash_values, serializer); serde::Serializable::serialize(obj.outputs, serializer); @@ -2986,15 +3314,15 @@ void serde::Serializable::serializ template <> template -Circuit::BlackBoxFuncCall::Sha256Compression serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::Sha256Compression obj; +Program::BlackBoxFuncCall::Sha256Compression serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::Sha256Compression obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.hash_values = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxOp &lhs, const BlackBoxOp &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -3016,11 +3344,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxOp &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -3028,15 +3356,62 @@ void serde::Serializable::serialize(const Circuit::BlackBox template <> template -Circuit::BlackBoxOp serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::BlackBoxOp serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::BlackBoxOp obj; + Program::BlackBoxOp obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { + + inline bool operator==(const BlackBoxOp::AES128Encrypt &lhs, const BlackBoxOp::AES128Encrypt &rhs) { + if (!(lhs.inputs == rhs.inputs)) { return false; } + if (!(lhs.iv == rhs.iv)) { return false; } + if (!(lhs.key == rhs.key)) { return false; } + if (!(lhs.outputs == rhs.outputs)) { return false; } + return true; + } + + inline std::vector BlackBoxOp::AES128Encrypt::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } + + inline BlackBoxOp::AES128Encrypt BlackBoxOp::AES128Encrypt::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } + +} // end of namespace Program + +template <> +template +void serde::Serializable::serialize(const Program::BlackBoxOp::AES128Encrypt &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.inputs, serializer); + serde::Serializable::serialize(obj.iv, serializer); + serde::Serializable::serialize(obj.key, serializer); + serde::Serializable::serialize(obj.outputs, serializer); +} + +template <> +template +Program::BlackBoxOp::AES128Encrypt serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::AES128Encrypt obj; + obj.inputs = serde::Deserializable::deserialize(deserializer); + obj.iv = serde::Deserializable::deserialize(deserializer); + obj.key = serde::Deserializable::deserialize(deserializer); + obj.outputs = serde::Deserializable::deserialize(deserializer); + return obj; +} + +namespace Program { inline bool operator==(const BlackBoxOp::Sha256 &lhs, const BlackBoxOp::Sha256 &rhs) { if (!(lhs.message == rhs.message)) { return false; } @@ -3059,25 +3434,25 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::Sha256 &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxOp::Sha256 &obj, Serializer &serializer) { serde::Serializable::serialize(obj.message, serializer); serde::Serializable::serialize(obj.output, serializer); } template <> template -Circuit::BlackBoxOp::Sha256 serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxOp::Sha256 obj; +Program::BlackBoxOp::Sha256 serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::Sha256 obj; obj.message = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxOp::Blake2s &lhs, const BlackBoxOp::Blake2s &rhs) { if (!(lhs.message == rhs.message)) { return false; } @@ -3100,25 +3475,25 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::Blake2s &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxOp::Blake2s &obj, Serializer &serializer) { serde::Serializable::serialize(obj.message, serializer); serde::Serializable::serialize(obj.output, serializer); } template <> template -Circuit::BlackBoxOp::Blake2s serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxOp::Blake2s obj; +Program::BlackBoxOp::Blake2s serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::Blake2s obj; obj.message = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxOp::Blake3 &lhs, const BlackBoxOp::Blake3 &rhs) { if (!(lhs.message == rhs.message)) { return false; } @@ -3141,25 +3516,25 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::Blake3 &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxOp::Blake3 &obj, Serializer &serializer) { serde::Serializable::serialize(obj.message, serializer); serde::Serializable::serialize(obj.output, serializer); } template <> template -Circuit::BlackBoxOp::Blake3 serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxOp::Blake3 obj; +Program::BlackBoxOp::Blake3 serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::Blake3 obj; obj.message = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxOp::Keccak256 &lhs, const BlackBoxOp::Keccak256 &rhs) { if (!(lhs.message == rhs.message)) { return false; } @@ -3182,25 +3557,25 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::Keccak256 &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxOp::Keccak256 &obj, Serializer &serializer) { serde::Serializable::serialize(obj.message, serializer); serde::Serializable::serialize(obj.output, serializer); } template <> template -Circuit::BlackBoxOp::Keccak256 serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxOp::Keccak256 obj; +Program::BlackBoxOp::Keccak256 serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::Keccak256 obj; obj.message = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxOp::Keccakf1600 &lhs, const BlackBoxOp::Keccakf1600 &rhs) { if (!(lhs.message == rhs.message)) { return false; } @@ -3223,25 +3598,25 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::Keccakf1600 &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxOp::Keccakf1600 &obj, Serializer &serializer) { serde::Serializable::serialize(obj.message, serializer); serde::Serializable::serialize(obj.output, serializer); } template <> template -Circuit::BlackBoxOp::Keccakf1600 serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxOp::Keccakf1600 obj; +Program::BlackBoxOp::Keccakf1600 serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::Keccakf1600 obj; obj.message = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxOp::EcdsaSecp256k1 &lhs, const BlackBoxOp::EcdsaSecp256k1 &rhs) { if (!(lhs.hashed_msg == rhs.hashed_msg)) { return false; } @@ -3267,11 +3642,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::EcdsaSecp256k1 &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxOp::EcdsaSecp256k1 &obj, Serializer &serializer) { serde::Serializable::serialize(obj.hashed_msg, serializer); serde::Serializable::serialize(obj.public_key_x, serializer); serde::Serializable::serialize(obj.public_key_y, serializer); @@ -3281,8 +3656,8 @@ void serde::Serializable::serialize(const C template <> template -Circuit::BlackBoxOp::EcdsaSecp256k1 serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxOp::EcdsaSecp256k1 obj; +Program::BlackBoxOp::EcdsaSecp256k1 serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::EcdsaSecp256k1 obj; obj.hashed_msg = serde::Deserializable::deserialize(deserializer); obj.public_key_x = serde::Deserializable::deserialize(deserializer); obj.public_key_y = serde::Deserializable::deserialize(deserializer); @@ -3291,7 +3666,7 @@ Circuit::BlackBoxOp::EcdsaSecp256k1 serde::Deserializable template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::EcdsaSecp256r1 &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxOp::EcdsaSecp256r1 &obj, Serializer &serializer) { serde::Serializable::serialize(obj.hashed_msg, serializer); serde::Serializable::serialize(obj.public_key_x, serializer); serde::Serializable::serialize(obj.public_key_y, serializer); @@ -3331,8 +3706,8 @@ void serde::Serializable::serialize(const C template <> template -Circuit::BlackBoxOp::EcdsaSecp256r1 serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxOp::EcdsaSecp256r1 obj; +Program::BlackBoxOp::EcdsaSecp256r1 serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::EcdsaSecp256r1 obj; obj.hashed_msg = serde::Deserializable::deserialize(deserializer); obj.public_key_x = serde::Deserializable::deserialize(deserializer); obj.public_key_y = serde::Deserializable::deserialize(deserializer); @@ -3341,7 +3716,7 @@ Circuit::BlackBoxOp::EcdsaSecp256r1 serde::Deserializable template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::SchnorrVerify &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxOp::SchnorrVerify &obj, Serializer &serializer) { serde::Serializable::serialize(obj.public_key_x, serializer); serde::Serializable::serialize(obj.public_key_y, serializer); serde::Serializable::serialize(obj.message, serializer); @@ -3381,8 +3756,8 @@ void serde::Serializable::serialize(const Ci template <> template -Circuit::BlackBoxOp::SchnorrVerify serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxOp::SchnorrVerify obj; +Program::BlackBoxOp::SchnorrVerify serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::SchnorrVerify obj; obj.public_key_x = serde::Deserializable::deserialize(deserializer); obj.public_key_y = serde::Deserializable::deserialize(deserializer); obj.message = serde::Deserializable::deserialize(deserializer); @@ -3391,7 +3766,7 @@ Circuit::BlackBoxOp::SchnorrVerify serde::Deserializable template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::PedersenCommitment &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxOp::PedersenCommitment &obj, Serializer &serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.domain_separator, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -3427,15 +3802,15 @@ void serde::Serializable::serialize(con template <> template -Circuit::BlackBoxOp::PedersenCommitment serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxOp::PedersenCommitment obj; +Program::BlackBoxOp::PedersenCommitment serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::PedersenCommitment obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.domain_separator = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxOp::PedersenHash &lhs, const BlackBoxOp::PedersenHash &rhs) { if (!(lhs.inputs == rhs.inputs)) { return false; } @@ -3459,11 +3834,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::PedersenHash &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxOp::PedersenHash &obj, Serializer &serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.domain_separator, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -3471,65 +3846,67 @@ void serde::Serializable::serialize(const Cir template <> template -Circuit::BlackBoxOp::PedersenHash serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxOp::PedersenHash obj; +Program::BlackBoxOp::PedersenHash serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::PedersenHash obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.domain_separator = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { - inline bool operator==(const BlackBoxOp::FixedBaseScalarMul &lhs, const BlackBoxOp::FixedBaseScalarMul &rhs) { - if (!(lhs.low == rhs.low)) { return false; } - if (!(lhs.high == rhs.high)) { return false; } - if (!(lhs.result == rhs.result)) { return false; } + inline bool operator==(const BlackBoxOp::MultiScalarMul &lhs, const BlackBoxOp::MultiScalarMul &rhs) { + if (!(lhs.points == rhs.points)) { return false; } + if (!(lhs.scalars == rhs.scalars)) { return false; } + if (!(lhs.outputs == rhs.outputs)) { return false; } return true; } - inline std::vector BlackBoxOp::FixedBaseScalarMul::bincodeSerialize() const { + inline std::vector BlackBoxOp::MultiScalarMul::bincodeSerialize() const { auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); + serde::Serializable::serialize(*this, serializer); return std::move(serializer).bytes(); } - inline BlackBoxOp::FixedBaseScalarMul BlackBoxOp::FixedBaseScalarMul::bincodeDeserialize(std::vector input) { + inline BlackBoxOp::MultiScalarMul BlackBoxOp::MultiScalarMul::bincodeDeserialize(std::vector input) { auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); + auto value = serde::Deserializable::deserialize(deserializer); if (deserializer.get_buffer_offset() < input.size()) { throw serde::deserialization_error("Some input bytes were not read"); } return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::FixedBaseScalarMul &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.low, serializer); - serde::Serializable::serialize(obj.high, serializer); - serde::Serializable::serialize(obj.result, serializer); +void serde::Serializable::serialize(const Program::BlackBoxOp::MultiScalarMul &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.points, serializer); + serde::Serializable::serialize(obj.scalars, serializer); + serde::Serializable::serialize(obj.outputs, serializer); } template <> template -Circuit::BlackBoxOp::FixedBaseScalarMul serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxOp::FixedBaseScalarMul obj; - obj.low = serde::Deserializable::deserialize(deserializer); - obj.high = serde::Deserializable::deserialize(deserializer); - obj.result = serde::Deserializable::deserialize(deserializer); +Program::BlackBoxOp::MultiScalarMul serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::MultiScalarMul obj; + obj.points = serde::Deserializable::deserialize(deserializer); + obj.scalars = serde::Deserializable::deserialize(deserializer); + obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxOp::EmbeddedCurveAdd &lhs, const BlackBoxOp::EmbeddedCurveAdd &rhs) { if (!(lhs.input1_x == rhs.input1_x)) { return false; } if (!(lhs.input1_y == rhs.input1_y)) { return false; } + if (!(lhs.input1_infinite == rhs.input1_infinite)) { return false; } if (!(lhs.input2_x == rhs.input2_x)) { return false; } if (!(lhs.input2_y == rhs.input2_y)) { return false; } + if (!(lhs.input2_infinite == rhs.input2_infinite)) { return false; } if (!(lhs.result == rhs.result)) { return false; } return true; } @@ -3549,31 +3926,35 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::EmbeddedCurveAdd &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxOp::EmbeddedCurveAdd &obj, Serializer &serializer) { serde::Serializable::serialize(obj.input1_x, serializer); serde::Serializable::serialize(obj.input1_y, serializer); + serde::Serializable::serialize(obj.input1_infinite, serializer); serde::Serializable::serialize(obj.input2_x, serializer); serde::Serializable::serialize(obj.input2_y, serializer); + serde::Serializable::serialize(obj.input2_infinite, serializer); serde::Serializable::serialize(obj.result, serializer); } template <> template -Circuit::BlackBoxOp::EmbeddedCurveAdd serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxOp::EmbeddedCurveAdd obj; +Program::BlackBoxOp::EmbeddedCurveAdd serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::EmbeddedCurveAdd obj; obj.input1_x = serde::Deserializable::deserialize(deserializer); obj.input1_y = serde::Deserializable::deserialize(deserializer); + obj.input1_infinite = serde::Deserializable::deserialize(deserializer); obj.input2_x = serde::Deserializable::deserialize(deserializer); obj.input2_y = serde::Deserializable::deserialize(deserializer); + obj.input2_infinite = serde::Deserializable::deserialize(deserializer); obj.result = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxOp::BigIntAdd &lhs, const BlackBoxOp::BigIntAdd &rhs) { if (!(lhs.lhs == rhs.lhs)) { return false; } @@ -3597,11 +3978,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::BigIntAdd &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxOp::BigIntAdd &obj, Serializer &serializer) { serde::Serializable::serialize(obj.lhs, serializer); serde::Serializable::serialize(obj.rhs, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -3609,15 +3990,15 @@ void serde::Serializable::serialize(const Circui template <> template -Circuit::BlackBoxOp::BigIntAdd serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxOp::BigIntAdd obj; +Program::BlackBoxOp::BigIntAdd serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::BigIntAdd obj; obj.lhs = serde::Deserializable::deserialize(deserializer); obj.rhs = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxOp::BigIntSub &lhs, const BlackBoxOp::BigIntSub &rhs) { if (!(lhs.lhs == rhs.lhs)) { return false; } @@ -3641,11 +4022,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::BigIntSub &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxOp::BigIntSub &obj, Serializer &serializer) { serde::Serializable::serialize(obj.lhs, serializer); serde::Serializable::serialize(obj.rhs, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -3653,15 +4034,15 @@ void serde::Serializable::serialize(const Circui template <> template -Circuit::BlackBoxOp::BigIntSub serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxOp::BigIntSub obj; +Program::BlackBoxOp::BigIntSub serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::BigIntSub obj; obj.lhs = serde::Deserializable::deserialize(deserializer); obj.rhs = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxOp::BigIntMul &lhs, const BlackBoxOp::BigIntMul &rhs) { if (!(lhs.lhs == rhs.lhs)) { return false; } @@ -3685,11 +4066,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::BigIntMul &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxOp::BigIntMul &obj, Serializer &serializer) { serde::Serializable::serialize(obj.lhs, serializer); serde::Serializable::serialize(obj.rhs, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -3697,15 +4078,15 @@ void serde::Serializable::serialize(const Circui template <> template -Circuit::BlackBoxOp::BigIntMul serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxOp::BigIntMul obj; +Program::BlackBoxOp::BigIntMul serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::BigIntMul obj; obj.lhs = serde::Deserializable::deserialize(deserializer); obj.rhs = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxOp::BigIntDiv &lhs, const BlackBoxOp::BigIntDiv &rhs) { if (!(lhs.lhs == rhs.lhs)) { return false; } @@ -3729,11 +4110,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::BigIntDiv &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxOp::BigIntDiv &obj, Serializer &serializer) { serde::Serializable::serialize(obj.lhs, serializer); serde::Serializable::serialize(obj.rhs, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -3741,15 +4122,15 @@ void serde::Serializable::serialize(const Circui template <> template -Circuit::BlackBoxOp::BigIntDiv serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxOp::BigIntDiv obj; +Program::BlackBoxOp::BigIntDiv serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::BigIntDiv obj; obj.lhs = serde::Deserializable::deserialize(deserializer); obj.rhs = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxOp::BigIntFromLeBytes &lhs, const BlackBoxOp::BigIntFromLeBytes &rhs) { if (!(lhs.inputs == rhs.inputs)) { return false; } @@ -3773,11 +4154,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::BigIntFromLeBytes &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxOp::BigIntFromLeBytes &obj, Serializer &serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.modulus, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -3785,15 +4166,15 @@ void serde::Serializable::serialize(cons template <> template -Circuit::BlackBoxOp::BigIntFromLeBytes serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxOp::BigIntFromLeBytes obj; +Program::BlackBoxOp::BigIntFromLeBytes serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::BigIntFromLeBytes obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.modulus = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxOp::BigIntToLeBytes &lhs, const BlackBoxOp::BigIntToLeBytes &rhs) { if (!(lhs.input == rhs.input)) { return false; } @@ -3816,25 +4197,25 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::BigIntToLeBytes &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxOp::BigIntToLeBytes &obj, Serializer &serializer) { serde::Serializable::serialize(obj.input, serializer); serde::Serializable::serialize(obj.output, serializer); } template <> template -Circuit::BlackBoxOp::BigIntToLeBytes serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxOp::BigIntToLeBytes obj; +Program::BlackBoxOp::BigIntToLeBytes serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::BigIntToLeBytes obj; obj.input = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxOp::Poseidon2Permutation &lhs, const BlackBoxOp::Poseidon2Permutation &rhs) { if (!(lhs.message == rhs.message)) { return false; } @@ -3858,11 +4239,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::Poseidon2Permutation &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxOp::Poseidon2Permutation &obj, Serializer &serializer) { serde::Serializable::serialize(obj.message, serializer); serde::Serializable::serialize(obj.output, serializer); serde::Serializable::serialize(obj.len, serializer); @@ -3870,15 +4251,15 @@ void serde::Serializable::serialize(c template <> template -Circuit::BlackBoxOp::Poseidon2Permutation serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxOp::Poseidon2Permutation obj; +Program::BlackBoxOp::Poseidon2Permutation serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::Poseidon2Permutation obj; obj.message = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); obj.len = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxOp::Sha256Compression &lhs, const BlackBoxOp::Sha256Compression &rhs) { if (!(lhs.input == rhs.input)) { return false; } @@ -3889,133 +4270,315 @@ namespace Circuit { inline std::vector BlackBoxOp::Sha256Compression::bincodeSerialize() const { auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } + + inline BlackBoxOp::Sha256Compression BlackBoxOp::Sha256Compression::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } + +} // end of namespace Program + +template <> +template +void serde::Serializable::serialize(const Program::BlackBoxOp::Sha256Compression &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.input, serializer); + serde::Serializable::serialize(obj.hash_values, serializer); + serde::Serializable::serialize(obj.output, serializer); +} + +template <> +template +Program::BlackBoxOp::Sha256Compression serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::Sha256Compression obj; + obj.input = serde::Deserializable::deserialize(deserializer); + obj.hash_values = serde::Deserializable::deserialize(deserializer); + obj.output = serde::Deserializable::deserialize(deserializer); + return obj; +} + +namespace Program { + + inline bool operator==(const BlackBoxOp::ToRadix &lhs, const BlackBoxOp::ToRadix &rhs) { + if (!(lhs.input == rhs.input)) { return false; } + if (!(lhs.radix == rhs.radix)) { return false; } + if (!(lhs.output == rhs.output)) { return false; } + return true; + } + + inline std::vector BlackBoxOp::ToRadix::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } + + inline BlackBoxOp::ToRadix BlackBoxOp::ToRadix::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } + +} // end of namespace Program + +template <> +template +void serde::Serializable::serialize(const Program::BlackBoxOp::ToRadix &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.input, serializer); + serde::Serializable::serialize(obj.radix, serializer); + serde::Serializable::serialize(obj.output, serializer); +} + +template <> +template +Program::BlackBoxOp::ToRadix serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::ToRadix obj; + obj.input = serde::Deserializable::deserialize(deserializer); + obj.radix = serde::Deserializable::deserialize(deserializer); + obj.output = serde::Deserializable::deserialize(deserializer); + return obj; +} + +namespace Program { + + inline bool operator==(const BlockId &lhs, const BlockId &rhs) { + if (!(lhs.value == rhs.value)) { return false; } + return true; + } + + inline std::vector BlockId::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } + + inline BlockId BlockId::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } + +} // end of namespace Program + +template <> +template +void serde::Serializable::serialize(const Program::BlockId &obj, Serializer &serializer) { + serializer.increase_container_depth(); + serde::Serializable::serialize(obj.value, serializer); + serializer.decrease_container_depth(); +} + +template <> +template +Program::BlockId serde::Deserializable::deserialize(Deserializer &deserializer) { + deserializer.increase_container_depth(); + Program::BlockId obj; + obj.value = serde::Deserializable::deserialize(deserializer); + deserializer.decrease_container_depth(); + return obj; +} + +namespace Program { + + inline bool operator==(const BlockType &lhs, const BlockType &rhs) { + if (!(lhs.value == rhs.value)) { return false; } + return true; + } + + inline std::vector BlockType::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } + + inline BlockType BlockType::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } + +} // end of namespace Program + +template <> +template +void serde::Serializable::serialize(const Program::BlockType &obj, Serializer &serializer) { + serializer.increase_container_depth(); + serde::Serializable::serialize(obj.value, serializer); + serializer.decrease_container_depth(); +} + +template <> +template +Program::BlockType serde::Deserializable::deserialize(Deserializer &deserializer) { + deserializer.increase_container_depth(); + Program::BlockType obj; + obj.value = serde::Deserializable::deserialize(deserializer); + deserializer.decrease_container_depth(); + return obj; +} + +namespace Program { + + inline bool operator==(const BlockType::Memory &lhs, const BlockType::Memory &rhs) { + return true; + } + + inline std::vector BlockType::Memory::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } + + inline BlockType::Memory BlockType::Memory::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } + +} // end of namespace Program + +template <> +template +void serde::Serializable::serialize(const Program::BlockType::Memory &obj, Serializer &serializer) { +} + +template <> +template +Program::BlockType::Memory serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlockType::Memory obj; + return obj; +} + +namespace Program { + + inline bool operator==(const BlockType::CallData &lhs, const BlockType::CallData &rhs) { + return true; + } + + inline std::vector BlockType::CallData::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); return std::move(serializer).bytes(); } - inline BlackBoxOp::Sha256Compression BlackBoxOp::Sha256Compression::bincodeDeserialize(std::vector input) { + inline BlockType::CallData BlockType::CallData::bincodeDeserialize(std::vector input) { auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); + auto value = serde::Deserializable::deserialize(deserializer); if (deserializer.get_buffer_offset() < input.size()) { throw serde::deserialization_error("Some input bytes were not read"); } return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::Sha256Compression &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.input, serializer); - serde::Serializable::serialize(obj.hash_values, serializer); - serde::Serializable::serialize(obj.output, serializer); +void serde::Serializable::serialize(const Program::BlockType::CallData &obj, Serializer &serializer) { } template <> template -Circuit::BlackBoxOp::Sha256Compression serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxOp::Sha256Compression obj; - obj.input = serde::Deserializable::deserialize(deserializer); - obj.hash_values = serde::Deserializable::deserialize(deserializer); - obj.output = serde::Deserializable::deserialize(deserializer); +Program::BlockType::CallData serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlockType::CallData obj; return obj; } -namespace Circuit { +namespace Program { - inline bool operator==(const BlockId &lhs, const BlockId &rhs) { - if (!(lhs.value == rhs.value)) { return false; } + inline bool operator==(const BlockType::ReturnData &lhs, const BlockType::ReturnData &rhs) { return true; } - inline std::vector BlockId::bincodeSerialize() const { + inline std::vector BlockType::ReturnData::bincodeSerialize() const { auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); + serde::Serializable::serialize(*this, serializer); return std::move(serializer).bytes(); } - inline BlockId BlockId::bincodeDeserialize(std::vector input) { + inline BlockType::ReturnData BlockType::ReturnData::bincodeDeserialize(std::vector input) { auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); + auto value = serde::Deserializable::deserialize(deserializer); if (deserializer.get_buffer_offset() < input.size()) { throw serde::deserialization_error("Some input bytes were not read"); } return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlockId &obj, Serializer &serializer) { - serializer.increase_container_depth(); - serde::Serializable::serialize(obj.value, serializer); - serializer.decrease_container_depth(); +void serde::Serializable::serialize(const Program::BlockType::ReturnData &obj, Serializer &serializer) { } template <> template -Circuit::BlockId serde::Deserializable::deserialize(Deserializer &deserializer) { - deserializer.increase_container_depth(); - Circuit::BlockId obj; - obj.value = serde::Deserializable::deserialize(deserializer); - deserializer.decrease_container_depth(); +Program::BlockType::ReturnData serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlockType::ReturnData obj; return obj; } -namespace Circuit { +namespace Program { - inline bool operator==(const Brillig &lhs, const Brillig &rhs) { - if (!(lhs.inputs == rhs.inputs)) { return false; } - if (!(lhs.outputs == rhs.outputs)) { return false; } + inline bool operator==(const BrilligBytecode &lhs, const BrilligBytecode &rhs) { if (!(lhs.bytecode == rhs.bytecode)) { return false; } - if (!(lhs.predicate == rhs.predicate)) { return false; } return true; } - inline std::vector Brillig::bincodeSerialize() const { + inline std::vector BrilligBytecode::bincodeSerialize() const { auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); + serde::Serializable::serialize(*this, serializer); return std::move(serializer).bytes(); } - inline Brillig Brillig::bincodeDeserialize(std::vector input) { + inline BrilligBytecode BrilligBytecode::bincodeDeserialize(std::vector input) { auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); + auto value = serde::Deserializable::deserialize(deserializer); if (deserializer.get_buffer_offset() < input.size()) { throw serde::deserialization_error("Some input bytes were not read"); } return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Brillig &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligBytecode &obj, Serializer &serializer) { serializer.increase_container_depth(); - serde::Serializable::serialize(obj.inputs, serializer); - serde::Serializable::serialize(obj.outputs, serializer); serde::Serializable::serialize(obj.bytecode, serializer); - serde::Serializable::serialize(obj.predicate, serializer); serializer.decrease_container_depth(); } template <> template -Circuit::Brillig serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::BrilligBytecode serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::Brillig obj; - obj.inputs = serde::Deserializable::deserialize(deserializer); - obj.outputs = serde::Deserializable::deserialize(deserializer); + Program::BrilligBytecode obj; obj.bytecode = serde::Deserializable::deserialize(deserializer); - obj.predicate = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligInputs &lhs, const BrilligInputs &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -4037,11 +4600,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligInputs &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligInputs &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -4049,15 +4612,15 @@ void serde::Serializable::serialize(const Circuit::Brill template <> template -Circuit::BrilligInputs serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::BrilligInputs serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::BrilligInputs obj; + Program::BrilligInputs obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligInputs::Single &lhs, const BrilligInputs::Single &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -4079,23 +4642,23 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligInputs::Single &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligInputs::Single &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Circuit::BrilligInputs::Single serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligInputs::Single obj; +Program::BrilligInputs::Single serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligInputs::Single obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligInputs::Array &lhs, const BrilligInputs::Array &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -4117,23 +4680,23 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligInputs::Array &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligInputs::Array &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Circuit::BrilligInputs::Array serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligInputs::Array obj; +Program::BrilligInputs::Array serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligInputs::Array obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligInputs::MemoryArray &lhs, const BrilligInputs::MemoryArray &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -4155,23 +4718,23 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligInputs::MemoryArray &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligInputs::MemoryArray &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Circuit::BrilligInputs::MemoryArray serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligInputs::MemoryArray obj; +Program::BrilligInputs::MemoryArray serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligInputs::MemoryArray obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode &lhs, const BrilligOpcode &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -4193,11 +4756,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOpcode &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -4205,15 +4768,15 @@ void serde::Serializable::serialize(const Circuit::Brill template <> template -Circuit::BrilligOpcode serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::BrilligOpcode serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::BrilligOpcode obj; + Program::BrilligOpcode obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::BinaryFieldOp &lhs, const BrilligOpcode::BinaryFieldOp &rhs) { if (!(lhs.destination == rhs.destination)) { return false; } @@ -4238,11 +4801,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::BinaryFieldOp &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOpcode::BinaryFieldOp &obj, Serializer &serializer) { serde::Serializable::serialize(obj.destination, serializer); serde::Serializable::serialize(obj.op, serializer); serde::Serializable::serialize(obj.lhs, serializer); @@ -4251,8 +4814,8 @@ void serde::Serializable::serialize(const template <> template -Circuit::BrilligOpcode::BinaryFieldOp serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligOpcode::BinaryFieldOp obj; +Program::BrilligOpcode::BinaryFieldOp serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::BinaryFieldOp obj; obj.destination = serde::Deserializable::deserialize(deserializer); obj.op = serde::Deserializable::deserialize(deserializer); obj.lhs = serde::Deserializable::deserialize(deserializer); @@ -4260,7 +4823,7 @@ Circuit::BrilligOpcode::BinaryFieldOp serde::Deserializable template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::BinaryIntOp &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOpcode::BinaryIntOp &obj, Serializer &serializer) { serde::Serializable::serialize(obj.destination, serializer); serde::Serializable::serialize(obj.op, serializer); serde::Serializable::serialize(obj.bit_size, serializer); @@ -4300,8 +4863,8 @@ void serde::Serializable::serialize(const C template <> template -Circuit::BrilligOpcode::BinaryIntOp serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligOpcode::BinaryIntOp obj; +Program::BrilligOpcode::BinaryIntOp serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::BinaryIntOp obj; obj.destination = serde::Deserializable::deserialize(deserializer); obj.op = serde::Deserializable::deserialize(deserializer); obj.bit_size = serde::Deserializable::deserialize(deserializer); @@ -4310,7 +4873,7 @@ Circuit::BrilligOpcode::BinaryIntOp serde::Deserializable template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::Cast &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOpcode::Cast &obj, Serializer &serializer) { serde::Serializable::serialize(obj.destination, serializer); serde::Serializable::serialize(obj.source, serializer); serde::Serializable::serialize(obj.bit_size, serializer); @@ -4346,15 +4909,15 @@ void serde::Serializable::serialize(const Circuit: template <> template -Circuit::BrilligOpcode::Cast serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligOpcode::Cast obj; +Program::BrilligOpcode::Cast serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::Cast obj; obj.destination = serde::Deserializable::deserialize(deserializer); obj.source = serde::Deserializable::deserialize(deserializer); obj.bit_size = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::JumpIfNot &lhs, const BrilligOpcode::JumpIfNot &rhs) { if (!(lhs.condition == rhs.condition)) { return false; } @@ -4377,25 +4940,25 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::JumpIfNot &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOpcode::JumpIfNot &obj, Serializer &serializer) { serde::Serializable::serialize(obj.condition, serializer); serde::Serializable::serialize(obj.location, serializer); } template <> template -Circuit::BrilligOpcode::JumpIfNot serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligOpcode::JumpIfNot obj; +Program::BrilligOpcode::JumpIfNot serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::JumpIfNot obj; obj.condition = serde::Deserializable::deserialize(deserializer); obj.location = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::JumpIf &lhs, const BrilligOpcode::JumpIf &rhs) { if (!(lhs.condition == rhs.condition)) { return false; } @@ -4418,25 +4981,25 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::JumpIf &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOpcode::JumpIf &obj, Serializer &serializer) { serde::Serializable::serialize(obj.condition, serializer); serde::Serializable::serialize(obj.location, serializer); } template <> template -Circuit::BrilligOpcode::JumpIf serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligOpcode::JumpIf obj; +Program::BrilligOpcode::JumpIf serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::JumpIf obj; obj.condition = serde::Deserializable::deserialize(deserializer); obj.location = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::Jump &lhs, const BrilligOpcode::Jump &rhs) { if (!(lhs.location == rhs.location)) { return false; } @@ -4458,23 +5021,23 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::Jump &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOpcode::Jump &obj, Serializer &serializer) { serde::Serializable::serialize(obj.location, serializer); } template <> template -Circuit::BrilligOpcode::Jump serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligOpcode::Jump obj; +Program::BrilligOpcode::Jump serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::Jump obj; obj.location = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::CalldataCopy &lhs, const BrilligOpcode::CalldataCopy &rhs) { if (!(lhs.destination_address == rhs.destination_address)) { return false; } @@ -4498,11 +5061,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::CalldataCopy &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOpcode::CalldataCopy &obj, Serializer &serializer) { serde::Serializable::serialize(obj.destination_address, serializer); serde::Serializable::serialize(obj.size, serializer); serde::Serializable::serialize(obj.offset, serializer); @@ -4510,15 +5073,15 @@ void serde::Serializable::serialize(const template <> template -Circuit::BrilligOpcode::CalldataCopy serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligOpcode::CalldataCopy obj; +Program::BrilligOpcode::CalldataCopy serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::CalldataCopy obj; obj.destination_address = serde::Deserializable::deserialize(deserializer); obj.size = serde::Deserializable::deserialize(deserializer); obj.offset = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::Call &lhs, const BrilligOpcode::Call &rhs) { if (!(lhs.location == rhs.location)) { return false; } @@ -4540,23 +5103,23 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::Call &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOpcode::Call &obj, Serializer &serializer) { serde::Serializable::serialize(obj.location, serializer); } template <> template -Circuit::BrilligOpcode::Call serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligOpcode::Call obj; +Program::BrilligOpcode::Call serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::Call obj; obj.location = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::Const &lhs, const BrilligOpcode::Const &rhs) { if (!(lhs.destination == rhs.destination)) { return false; } @@ -4580,11 +5143,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::Const &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOpcode::Const &obj, Serializer &serializer) { serde::Serializable::serialize(obj.destination, serializer); serde::Serializable::serialize(obj.bit_size, serializer); serde::Serializable::serialize(obj.value, serializer); @@ -4592,15 +5155,15 @@ void serde::Serializable::serialize(const Circuit template <> template -Circuit::BrilligOpcode::Const serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligOpcode::Const obj; +Program::BrilligOpcode::Const serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::Const obj; obj.destination = serde::Deserializable::deserialize(deserializer); obj.bit_size = serde::Deserializable::deserialize(deserializer); obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::Return &lhs, const BrilligOpcode::Return &rhs) { return true; @@ -4621,21 +5184,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::Return &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOpcode::Return &obj, Serializer &serializer) { } template <> template -Circuit::BrilligOpcode::Return serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligOpcode::Return obj; +Program::BrilligOpcode::Return serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::Return obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::ForeignCall &lhs, const BrilligOpcode::ForeignCall &rhs) { if (!(lhs.function == rhs.function)) { return false; } @@ -4661,11 +5224,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::ForeignCall &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOpcode::ForeignCall &obj, Serializer &serializer) { serde::Serializable::serialize(obj.function, serializer); serde::Serializable::serialize(obj.destinations, serializer); serde::Serializable::serialize(obj.destination_value_types, serializer); @@ -4675,8 +5238,8 @@ void serde::Serializable::serialize(const C template <> template -Circuit::BrilligOpcode::ForeignCall serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligOpcode::ForeignCall obj; +Program::BrilligOpcode::ForeignCall serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::ForeignCall obj; obj.function = serde::Deserializable::deserialize(deserializer); obj.destinations = serde::Deserializable::deserialize(deserializer); obj.destination_value_types = serde::Deserializable::deserialize(deserializer); @@ -4685,7 +5248,7 @@ Circuit::BrilligOpcode::ForeignCall serde::Deserializable template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::Mov &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOpcode::Mov &obj, Serializer &serializer) { serde::Serializable::serialize(obj.destination, serializer); serde::Serializable::serialize(obj.source, serializer); } template <> template -Circuit::BrilligOpcode::Mov serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligOpcode::Mov obj; +Program::BrilligOpcode::Mov serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::Mov obj; obj.destination = serde::Deserializable::deserialize(deserializer); obj.source = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { + + inline bool operator==(const BrilligOpcode::ConditionalMov &lhs, const BrilligOpcode::ConditionalMov &rhs) { + if (!(lhs.destination == rhs.destination)) { return false; } + if (!(lhs.source_a == rhs.source_a)) { return false; } + if (!(lhs.source_b == rhs.source_b)) { return false; } + if (!(lhs.condition == rhs.condition)) { return false; } + return true; + } + + inline std::vector BrilligOpcode::ConditionalMov::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } + + inline BrilligOpcode::ConditionalMov BrilligOpcode::ConditionalMov::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } + +} // end of namespace Program + +template <> +template +void serde::Serializable::serialize(const Program::BrilligOpcode::ConditionalMov &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.destination, serializer); + serde::Serializable::serialize(obj.source_a, serializer); + serde::Serializable::serialize(obj.source_b, serializer); + serde::Serializable::serialize(obj.condition, serializer); +} + +template <> +template +Program::BrilligOpcode::ConditionalMov serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::ConditionalMov obj; + obj.destination = serde::Deserializable::deserialize(deserializer); + obj.source_a = serde::Deserializable::deserialize(deserializer); + obj.source_b = serde::Deserializable::deserialize(deserializer); + obj.condition = serde::Deserializable::deserialize(deserializer); + return obj; +} + +namespace Program { inline bool operator==(const BrilligOpcode::Load &lhs, const BrilligOpcode::Load &rhs) { if (!(lhs.destination == rhs.destination)) { return false; } @@ -4749,25 +5359,25 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::Load &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOpcode::Load &obj, Serializer &serializer) { serde::Serializable::serialize(obj.destination, serializer); serde::Serializable::serialize(obj.source_pointer, serializer); } template <> template -Circuit::BrilligOpcode::Load serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligOpcode::Load obj; +Program::BrilligOpcode::Load serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::Load obj; obj.destination = serde::Deserializable::deserialize(deserializer); obj.source_pointer = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::Store &lhs, const BrilligOpcode::Store &rhs) { if (!(lhs.destination_pointer == rhs.destination_pointer)) { return false; } @@ -4790,25 +5400,25 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::Store &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOpcode::Store &obj, Serializer &serializer) { serde::Serializable::serialize(obj.destination_pointer, serializer); serde::Serializable::serialize(obj.source, serializer); } template <> template -Circuit::BrilligOpcode::Store serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligOpcode::Store obj; +Program::BrilligOpcode::Store serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::Store obj; obj.destination_pointer = serde::Deserializable::deserialize(deserializer); obj.source = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::BlackBox &lhs, const BrilligOpcode::BlackBox &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -4830,25 +5440,26 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::BlackBox &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOpcode::BlackBox &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Circuit::BrilligOpcode::BlackBox serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligOpcode::BlackBox obj; +Program::BrilligOpcode::BlackBox serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::BlackBox obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::Trap &lhs, const BrilligOpcode::Trap &rhs) { + if (!(lhs.revert_data == rhs.revert_data)) { return false; } return true; } @@ -4867,21 +5478,23 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::Trap &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOpcode::Trap &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.revert_data, serializer); } template <> template -Circuit::BrilligOpcode::Trap serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligOpcode::Trap obj; +Program::BrilligOpcode::Trap serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::Trap obj; + obj.revert_data = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::Stop &lhs, const BrilligOpcode::Stop &rhs) { if (!(lhs.return_data_offset == rhs.return_data_offset)) { return false; } @@ -4904,25 +5517,25 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::Stop &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOpcode::Stop &obj, Serializer &serializer) { serde::Serializable::serialize(obj.return_data_offset, serializer); serde::Serializable::serialize(obj.return_data_size, serializer); } template <> template -Circuit::BrilligOpcode::Stop serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligOpcode::Stop obj; +Program::BrilligOpcode::Stop serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::Stop obj; obj.return_data_offset = serde::Deserializable::deserialize(deserializer); obj.return_data_size = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOutputs &lhs, const BrilligOutputs &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -4944,11 +5557,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOutputs &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOutputs &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -4956,15 +5569,15 @@ void serde::Serializable::serialize(const Circuit::Bril template <> template -Circuit::BrilligOutputs serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::BrilligOutputs serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::BrilligOutputs obj; + Program::BrilligOutputs obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOutputs::Simple &lhs, const BrilligOutputs::Simple &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -4986,23 +5599,23 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOutputs::Simple &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOutputs::Simple &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Circuit::BrilligOutputs::Simple serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligOutputs::Simple obj; +Program::BrilligOutputs::Simple serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOutputs::Simple obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOutputs::Array &lhs, const BrilligOutputs::Array &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -5024,23 +5637,23 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOutputs::Array &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOutputs::Array &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Circuit::BrilligOutputs::Array serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligOutputs::Array obj; +Program::BrilligOutputs::Array serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOutputs::Array obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Circuit &lhs, const Circuit &rhs) { if (!(lhs.current_witness_index == rhs.current_witness_index)) { return false; } @@ -5069,11 +5682,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Circuit &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::Circuit &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.current_witness_index, serializer); serde::Serializable::serialize(obj.opcodes, serializer); @@ -5088,9 +5701,9 @@ void serde::Serializable::serialize(const Circuit::Circuit &ob template <> template -Circuit::Circuit serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::Circuit serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::Circuit obj; + Program::Circuit obj; obj.current_witness_index = serde::Deserializable::deserialize(deserializer); obj.opcodes = serde::Deserializable::deserialize(deserializer); obj.expression_width = serde::Deserializable::deserialize(deserializer); @@ -5103,7 +5716,7 @@ Circuit::Circuit serde::Deserializable::deserialize(Deserializ return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Directive &lhs, const Directive &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -5125,11 +5738,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Directive &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::Directive &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -5137,15 +5750,15 @@ void serde::Serializable::serialize(const Circuit::Directive template <> template -Circuit::Directive serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::Directive serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::Directive obj; + Program::Directive obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Directive::ToLeRadix &lhs, const Directive::ToLeRadix &rhs) { if (!(lhs.a == rhs.a)) { return false; } @@ -5169,11 +5782,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Directive::ToLeRadix &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::Directive::ToLeRadix &obj, Serializer &serializer) { serde::Serializable::serialize(obj.a, serializer); serde::Serializable::serialize(obj.b, serializer); serde::Serializable::serialize(obj.radix, serializer); @@ -5181,15 +5794,15 @@ void serde::Serializable::serialize(const Circuit template <> template -Circuit::Directive::ToLeRadix serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::Directive::ToLeRadix obj; +Program::Directive::ToLeRadix serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::Directive::ToLeRadix obj; obj.a = serde::Deserializable::deserialize(deserializer); obj.b = serde::Deserializable::deserialize(deserializer); obj.radix = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Expression &lhs, const Expression &rhs) { if (!(lhs.mul_terms == rhs.mul_terms)) { return false; } @@ -5213,11 +5826,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Expression &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::Expression &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.mul_terms, serializer); serde::Serializable::serialize(obj.linear_combinations, serializer); @@ -5227,9 +5840,9 @@ void serde::Serializable::serialize(const Circuit::Expressi template <> template -Circuit::Expression serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::Expression serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::Expression obj; + Program::Expression obj; obj.mul_terms = serde::Deserializable::deserialize(deserializer); obj.linear_combinations = serde::Deserializable::deserialize(deserializer); obj.q_c = serde::Deserializable::deserialize(deserializer); @@ -5237,7 +5850,125 @@ Circuit::Expression serde::Deserializable::deserialize(Dese return obj; } -namespace Circuit { +namespace Program { + + inline bool operator==(const ExpressionOrMemory &lhs, const ExpressionOrMemory &rhs) { + if (!(lhs.value == rhs.value)) { return false; } + return true; + } + + inline std::vector ExpressionOrMemory::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } + + inline ExpressionOrMemory ExpressionOrMemory::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } + +} // end of namespace Program + +template <> +template +void serde::Serializable::serialize(const Program::ExpressionOrMemory &obj, Serializer &serializer) { + serializer.increase_container_depth(); + serde::Serializable::serialize(obj.value, serializer); + serializer.decrease_container_depth(); +} + +template <> +template +Program::ExpressionOrMemory serde::Deserializable::deserialize(Deserializer &deserializer) { + deserializer.increase_container_depth(); + Program::ExpressionOrMemory obj; + obj.value = serde::Deserializable::deserialize(deserializer); + deserializer.decrease_container_depth(); + return obj; +} + +namespace Program { + + inline bool operator==(const ExpressionOrMemory::Expression &lhs, const ExpressionOrMemory::Expression &rhs) { + if (!(lhs.value == rhs.value)) { return false; } + return true; + } + + inline std::vector ExpressionOrMemory::Expression::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } + + inline ExpressionOrMemory::Expression ExpressionOrMemory::Expression::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } + +} // end of namespace Program + +template <> +template +void serde::Serializable::serialize(const Program::ExpressionOrMemory::Expression &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.value, serializer); +} + +template <> +template +Program::ExpressionOrMemory::Expression serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::ExpressionOrMemory::Expression obj; + obj.value = serde::Deserializable::deserialize(deserializer); + return obj; +} + +namespace Program { + + inline bool operator==(const ExpressionOrMemory::Memory &lhs, const ExpressionOrMemory::Memory &rhs) { + if (!(lhs.value == rhs.value)) { return false; } + return true; + } + + inline std::vector ExpressionOrMemory::Memory::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } + + inline ExpressionOrMemory::Memory ExpressionOrMemory::Memory::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } + +} // end of namespace Program + +template <> +template +void serde::Serializable::serialize(const Program::ExpressionOrMemory::Memory &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.value, serializer); +} + +template <> +template +Program::ExpressionOrMemory::Memory serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::ExpressionOrMemory::Memory obj; + obj.value = serde::Deserializable::deserialize(deserializer); + return obj; +} + +namespace Program { inline bool operator==(const ExpressionWidth &lhs, const ExpressionWidth &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -5259,11 +5990,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::ExpressionWidth &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::ExpressionWidth &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -5271,15 +6002,15 @@ void serde::Serializable::serialize(const Circuit::Exp template <> template -Circuit::ExpressionWidth serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::ExpressionWidth serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::ExpressionWidth obj; + Program::ExpressionWidth obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const ExpressionWidth::Unbounded &lhs, const ExpressionWidth::Unbounded &rhs) { return true; @@ -5300,21 +6031,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::ExpressionWidth::Unbounded &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::ExpressionWidth::Unbounded &obj, Serializer &serializer) { } template <> template -Circuit::ExpressionWidth::Unbounded serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::ExpressionWidth::Unbounded obj; +Program::ExpressionWidth::Unbounded serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::ExpressionWidth::Unbounded obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const ExpressionWidth::Bounded &lhs, const ExpressionWidth::Bounded &rhs) { if (!(lhs.width == rhs.width)) { return false; } @@ -5336,23 +6067,23 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::ExpressionWidth::Bounded &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::ExpressionWidth::Bounded &obj, Serializer &serializer) { serde::Serializable::serialize(obj.width, serializer); } template <> template -Circuit::ExpressionWidth::Bounded serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::ExpressionWidth::Bounded obj; +Program::ExpressionWidth::Bounded serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::ExpressionWidth::Bounded obj; obj.width = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const FunctionInput &lhs, const FunctionInput &rhs) { if (!(lhs.witness == rhs.witness)) { return false; } @@ -5375,11 +6106,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::FunctionInput &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::FunctionInput &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.witness, serializer); serde::Serializable::serialize(obj.num_bits, serializer); @@ -5388,16 +6119,16 @@ void serde::Serializable::serialize(const Circuit::Funct template <> template -Circuit::FunctionInput serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::FunctionInput serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::FunctionInput obj; + Program::FunctionInput obj; obj.witness = serde::Deserializable::deserialize(deserializer); obj.num_bits = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const HeapArray &lhs, const HeapArray &rhs) { if (!(lhs.pointer == rhs.pointer)) { return false; } @@ -5420,11 +6151,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::HeapArray &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::HeapArray &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.pointer, serializer); serde::Serializable::serialize(obj.size, serializer); @@ -5433,16 +6164,16 @@ void serde::Serializable::serialize(const Circuit::HeapArray template <> template -Circuit::HeapArray serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::HeapArray serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::HeapArray obj; + Program::HeapArray obj; obj.pointer = serde::Deserializable::deserialize(deserializer); obj.size = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const HeapValueType &lhs, const HeapValueType &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -5464,11 +6195,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::HeapValueType &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::HeapValueType &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -5476,17 +6207,18 @@ void serde::Serializable::serialize(const Circuit::HeapV template <> template -Circuit::HeapValueType serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::HeapValueType serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::HeapValueType obj; + Program::HeapValueType obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const HeapValueType::Simple &lhs, const HeapValueType::Simple &rhs) { + if (!(lhs.value == rhs.value)) { return false; } return true; } @@ -5505,21 +6237,23 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::HeapValueType::Simple &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::HeapValueType::Simple &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.value, serializer); } template <> template -Circuit::HeapValueType::Simple serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::HeapValueType::Simple obj; +Program::HeapValueType::Simple serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::HeapValueType::Simple obj; + obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const HeapValueType::Array &lhs, const HeapValueType::Array &rhs) { if (!(lhs.value_types == rhs.value_types)) { return false; } @@ -5542,25 +6276,25 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::HeapValueType::Array &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::HeapValueType::Array &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value_types, serializer); serde::Serializable::serialize(obj.size, serializer); } template <> template -Circuit::HeapValueType::Array serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::HeapValueType::Array obj; +Program::HeapValueType::Array serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::HeapValueType::Array obj; obj.value_types = serde::Deserializable::deserialize(deserializer); obj.size = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const HeapValueType::Vector &lhs, const HeapValueType::Vector &rhs) { if (!(lhs.value_types == rhs.value_types)) { return false; } @@ -5582,23 +6316,23 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::HeapValueType::Vector &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::HeapValueType::Vector &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value_types, serializer); } template <> template -Circuit::HeapValueType::Vector serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::HeapValueType::Vector obj; +Program::HeapValueType::Vector serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::HeapValueType::Vector obj; obj.value_types = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const HeapVector &lhs, const HeapVector &rhs) { if (!(lhs.pointer == rhs.pointer)) { return false; } @@ -5621,11 +6355,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::HeapVector &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::HeapVector &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.pointer, serializer); serde::Serializable::serialize(obj.size, serializer); @@ -5634,16 +6368,16 @@ void serde::Serializable::serialize(const Circuit::HeapVect template <> template -Circuit::HeapVector serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::HeapVector serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::HeapVector obj; + Program::HeapVector obj; obj.pointer = serde::Deserializable::deserialize(deserializer); obj.size = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const MemOp &lhs, const MemOp &rhs) { if (!(lhs.operation == rhs.operation)) { return false; } @@ -5667,11 +6401,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::MemOp &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::MemOp &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.operation, serializer); serde::Serializable::serialize(obj.index, serializer); @@ -5681,9 +6415,9 @@ void serde::Serializable::serialize(const Circuit::MemOp &obj, S template <> template -Circuit::MemOp serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::MemOp serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::MemOp obj; + Program::MemOp obj; obj.operation = serde::Deserializable::deserialize(deserializer); obj.index = serde::Deserializable::deserialize(deserializer); obj.value = serde::Deserializable::deserialize(deserializer); @@ -5691,7 +6425,7 @@ Circuit::MemOp serde::Deserializable::deserialize(Deserializer & return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const MemoryAddress &lhs, const MemoryAddress &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -5713,11 +6447,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::MemoryAddress &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::MemoryAddress &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -5725,15 +6459,15 @@ void serde::Serializable::serialize(const Circuit::Memor template <> template -Circuit::MemoryAddress serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::MemoryAddress serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::MemoryAddress obj; + Program::MemoryAddress obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Opcode &lhs, const Opcode &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -5755,11 +6489,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Opcode &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::Opcode &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -5767,15 +6501,15 @@ void serde::Serializable::serialize(const Circuit::Opcode &obj, template <> template -Circuit::Opcode serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::Opcode serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::Opcode obj; + Program::Opcode obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Opcode::AssertZero &lhs, const Opcode::AssertZero &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -5797,23 +6531,23 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Opcode::AssertZero &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::Opcode::AssertZero &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Circuit::Opcode::AssertZero serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::Opcode::AssertZero obj; +Program::Opcode::AssertZero serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::Opcode::AssertZero obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Opcode::BlackBoxFuncCall &lhs, const Opcode::BlackBoxFuncCall &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -5835,23 +6569,23 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Opcode::BlackBoxFuncCall &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::Opcode::BlackBoxFuncCall &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Circuit::Opcode::BlackBoxFuncCall serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::Opcode::BlackBoxFuncCall obj; +Program::Opcode::BlackBoxFuncCall serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::Opcode::BlackBoxFuncCall obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Opcode::Directive &lhs, const Opcode::Directive &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -5873,146 +6607,205 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Opcode::Directive &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::Opcode::Directive &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Circuit::Opcode::Directive serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::Opcode::Directive obj; +Program::Opcode::Directive serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::Opcode::Directive obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { - inline bool operator==(const Opcode::Brillig &lhs, const Opcode::Brillig &rhs) { - if (!(lhs.value == rhs.value)) { return false; } + inline bool operator==(const Opcode::MemoryOp &lhs, const Opcode::MemoryOp &rhs) { + if (!(lhs.block_id == rhs.block_id)) { return false; } + if (!(lhs.op == rhs.op)) { return false; } + if (!(lhs.predicate == rhs.predicate)) { return false; } return true; } - inline std::vector Opcode::Brillig::bincodeSerialize() const { + inline std::vector Opcode::MemoryOp::bincodeSerialize() const { auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); + serde::Serializable::serialize(*this, serializer); return std::move(serializer).bytes(); } - inline Opcode::Brillig Opcode::Brillig::bincodeDeserialize(std::vector input) { + inline Opcode::MemoryOp Opcode::MemoryOp::bincodeDeserialize(std::vector input) { auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); + auto value = serde::Deserializable::deserialize(deserializer); if (deserializer.get_buffer_offset() < input.size()) { throw serde::deserialization_error("Some input bytes were not read"); } return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Opcode::Brillig &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.value, serializer); +void serde::Serializable::serialize(const Program::Opcode::MemoryOp &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.block_id, serializer); + serde::Serializable::serialize(obj.op, serializer); + serde::Serializable::serialize(obj.predicate, serializer); } template <> template -Circuit::Opcode::Brillig serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::Opcode::Brillig obj; - obj.value = serde::Deserializable::deserialize(deserializer); +Program::Opcode::MemoryOp serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::Opcode::MemoryOp obj; + obj.block_id = serde::Deserializable::deserialize(deserializer); + obj.op = serde::Deserializable::deserialize(deserializer); + obj.predicate = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { - inline bool operator==(const Opcode::MemoryOp &lhs, const Opcode::MemoryOp &rhs) { + inline bool operator==(const Opcode::MemoryInit &lhs, const Opcode::MemoryInit &rhs) { if (!(lhs.block_id == rhs.block_id)) { return false; } - if (!(lhs.op == rhs.op)) { return false; } - if (!(lhs.predicate == rhs.predicate)) { return false; } + if (!(lhs.init == rhs.init)) { return false; } + if (!(lhs.block_type == rhs.block_type)) { return false; } return true; } - inline std::vector Opcode::MemoryOp::bincodeSerialize() const { + inline std::vector Opcode::MemoryInit::bincodeSerialize() const { auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); + serde::Serializable::serialize(*this, serializer); return std::move(serializer).bytes(); } - inline Opcode::MemoryOp Opcode::MemoryOp::bincodeDeserialize(std::vector input) { + inline Opcode::MemoryInit Opcode::MemoryInit::bincodeDeserialize(std::vector input) { auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); + auto value = serde::Deserializable::deserialize(deserializer); if (deserializer.get_buffer_offset() < input.size()) { throw serde::deserialization_error("Some input bytes were not read"); } return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Opcode::MemoryOp &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::Opcode::MemoryInit &obj, Serializer &serializer) { serde::Serializable::serialize(obj.block_id, serializer); - serde::Serializable::serialize(obj.op, serializer); - serde::Serializable::serialize(obj.predicate, serializer); + serde::Serializable::serialize(obj.init, serializer); + serde::Serializable::serialize(obj.block_type, serializer); } template <> template -Circuit::Opcode::MemoryOp serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::Opcode::MemoryOp obj; +Program::Opcode::MemoryInit serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::Opcode::MemoryInit obj; obj.block_id = serde::Deserializable::deserialize(deserializer); - obj.op = serde::Deserializable::deserialize(deserializer); + obj.init = serde::Deserializable::deserialize(deserializer); + obj.block_type = serde::Deserializable::deserialize(deserializer); + return obj; +} + +namespace Program { + + inline bool operator==(const Opcode::BrilligCall &lhs, const Opcode::BrilligCall &rhs) { + if (!(lhs.id == rhs.id)) { return false; } + if (!(lhs.inputs == rhs.inputs)) { return false; } + if (!(lhs.outputs == rhs.outputs)) { return false; } + if (!(lhs.predicate == rhs.predicate)) { return false; } + return true; + } + + inline std::vector Opcode::BrilligCall::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } + + inline Opcode::BrilligCall Opcode::BrilligCall::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } + +} // end of namespace Program + +template <> +template +void serde::Serializable::serialize(const Program::Opcode::BrilligCall &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.id, serializer); + serde::Serializable::serialize(obj.inputs, serializer); + serde::Serializable::serialize(obj.outputs, serializer); + serde::Serializable::serialize(obj.predicate, serializer); +} + +template <> +template +Program::Opcode::BrilligCall serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::Opcode::BrilligCall obj; + obj.id = serde::Deserializable::deserialize(deserializer); + obj.inputs = serde::Deserializable::deserialize(deserializer); + obj.outputs = serde::Deserializable::deserialize(deserializer); obj.predicate = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { - inline bool operator==(const Opcode::MemoryInit &lhs, const Opcode::MemoryInit &rhs) { - if (!(lhs.block_id == rhs.block_id)) { return false; } - if (!(lhs.init == rhs.init)) { return false; } + inline bool operator==(const Opcode::Call &lhs, const Opcode::Call &rhs) { + if (!(lhs.id == rhs.id)) { return false; } + if (!(lhs.inputs == rhs.inputs)) { return false; } + if (!(lhs.outputs == rhs.outputs)) { return false; } + if (!(lhs.predicate == rhs.predicate)) { return false; } return true; } - inline std::vector Opcode::MemoryInit::bincodeSerialize() const { + inline std::vector Opcode::Call::bincodeSerialize() const { auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); + serde::Serializable::serialize(*this, serializer); return std::move(serializer).bytes(); } - inline Opcode::MemoryInit Opcode::MemoryInit::bincodeDeserialize(std::vector input) { + inline Opcode::Call Opcode::Call::bincodeDeserialize(std::vector input) { auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); + auto value = serde::Deserializable::deserialize(deserializer); if (deserializer.get_buffer_offset() < input.size()) { throw serde::deserialization_error("Some input bytes were not read"); } return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Opcode::MemoryInit &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.block_id, serializer); - serde::Serializable::serialize(obj.init, serializer); +void serde::Serializable::serialize(const Program::Opcode::Call &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.id, serializer); + serde::Serializable::serialize(obj.inputs, serializer); + serde::Serializable::serialize(obj.outputs, serializer); + serde::Serializable::serialize(obj.predicate, serializer); } template <> template -Circuit::Opcode::MemoryInit serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::Opcode::MemoryInit obj; - obj.block_id = serde::Deserializable::deserialize(deserializer); - obj.init = serde::Deserializable::deserialize(deserializer); +Program::Opcode::Call serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::Opcode::Call obj; + obj.id = serde::Deserializable::deserialize(deserializer); + obj.inputs = serde::Deserializable::deserialize(deserializer); + obj.outputs = serde::Deserializable::deserialize(deserializer); + obj.predicate = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const OpcodeLocation &lhs, const OpcodeLocation &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -6034,11 +6827,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::OpcodeLocation &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::OpcodeLocation &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -6046,15 +6839,15 @@ void serde::Serializable::serialize(const Circuit::Opco template <> template -Circuit::OpcodeLocation serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::OpcodeLocation serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::OpcodeLocation obj; + Program::OpcodeLocation obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const OpcodeLocation::Acir &lhs, const OpcodeLocation::Acir &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -6076,23 +6869,23 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::OpcodeLocation::Acir &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::OpcodeLocation::Acir &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Circuit::OpcodeLocation::Acir serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::OpcodeLocation::Acir obj; +Program::OpcodeLocation::Acir serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::OpcodeLocation::Acir obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const OpcodeLocation::Brillig &lhs, const OpcodeLocation::Brillig &rhs) { if (!(lhs.acir_index == rhs.acir_index)) { return false; } @@ -6115,109 +6908,112 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::OpcodeLocation::Brillig &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::OpcodeLocation::Brillig &obj, Serializer &serializer) { serde::Serializable::serialize(obj.acir_index, serializer); serde::Serializable::serialize(obj.brillig_index, serializer); } template <> template -Circuit::OpcodeLocation::Brillig serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::OpcodeLocation::Brillig obj; +Program::OpcodeLocation::Brillig serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::OpcodeLocation::Brillig obj; obj.acir_index = serde::Deserializable::deserialize(deserializer); obj.brillig_index = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { - inline bool operator==(const PublicInputs &lhs, const PublicInputs &rhs) { - if (!(lhs.value == rhs.value)) { return false; } + inline bool operator==(const Program &lhs, const Program &rhs) { + if (!(lhs.functions == rhs.functions)) { return false; } + if (!(lhs.unconstrained_functions == rhs.unconstrained_functions)) { return false; } return true; } - inline std::vector PublicInputs::bincodeSerialize() const { + inline std::vector Program::bincodeSerialize() const { auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); + serde::Serializable::serialize(*this, serializer); return std::move(serializer).bytes(); } - inline PublicInputs PublicInputs::bincodeDeserialize(std::vector input) { + inline Program Program::bincodeDeserialize(std::vector input) { auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); + auto value = serde::Deserializable::deserialize(deserializer); if (deserializer.get_buffer_offset() < input.size()) { throw serde::deserialization_error("Some input bytes were not read"); } return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::PublicInputs &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::Program &obj, Serializer &serializer) { serializer.increase_container_depth(); - serde::Serializable::serialize(obj.value, serializer); + serde::Serializable::serialize(obj.functions, serializer); + serde::Serializable::serialize(obj.unconstrained_functions, serializer); serializer.decrease_container_depth(); } template <> template -Circuit::PublicInputs serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::Program serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::PublicInputs obj; - obj.value = serde::Deserializable::deserialize(deserializer); + Program::Program obj; + obj.functions = serde::Deserializable::deserialize(deserializer); + obj.unconstrained_functions = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { - inline bool operator==(const Value &lhs, const Value &rhs) { - if (!(lhs.inner == rhs.inner)) { return false; } + inline bool operator==(const PublicInputs &lhs, const PublicInputs &rhs) { + if (!(lhs.value == rhs.value)) { return false; } return true; } - inline std::vector Value::bincodeSerialize() const { + inline std::vector PublicInputs::bincodeSerialize() const { auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); + serde::Serializable::serialize(*this, serializer); return std::move(serializer).bytes(); } - inline Value Value::bincodeDeserialize(std::vector input) { + inline PublicInputs PublicInputs::bincodeDeserialize(std::vector input) { auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); + auto value = serde::Deserializable::deserialize(deserializer); if (deserializer.get_buffer_offset() < input.size()) { throw serde::deserialization_error("Some input bytes were not read"); } return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Value &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::PublicInputs &obj, Serializer &serializer) { serializer.increase_container_depth(); - serde::Serializable::serialize(obj.inner, serializer); + serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); } template <> template -Circuit::Value serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::PublicInputs serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::Value obj; - obj.inner = serde::Deserializable::deserialize(deserializer); + Program::PublicInputs obj; + obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const ValueOrArray &lhs, const ValueOrArray &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -6239,11 +7035,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::ValueOrArray &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::ValueOrArray &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -6251,15 +7047,15 @@ void serde::Serializable::serialize(const Circuit::ValueO template <> template -Circuit::ValueOrArray serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::ValueOrArray serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::ValueOrArray obj; + Program::ValueOrArray obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const ValueOrArray::MemoryAddress &lhs, const ValueOrArray::MemoryAddress &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -6281,23 +7077,23 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::ValueOrArray::MemoryAddress &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::ValueOrArray::MemoryAddress &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Circuit::ValueOrArray::MemoryAddress serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::ValueOrArray::MemoryAddress obj; +Program::ValueOrArray::MemoryAddress serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::ValueOrArray::MemoryAddress obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const ValueOrArray::HeapArray &lhs, const ValueOrArray::HeapArray &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -6319,23 +7115,23 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::ValueOrArray::HeapArray &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::ValueOrArray::HeapArray &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Circuit::ValueOrArray::HeapArray serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::ValueOrArray::HeapArray obj; +Program::ValueOrArray::HeapArray serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::ValueOrArray::HeapArray obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const ValueOrArray::HeapVector &lhs, const ValueOrArray::HeapVector &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -6357,23 +7153,23 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::ValueOrArray::HeapVector &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::ValueOrArray::HeapVector &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Circuit::ValueOrArray::HeapVector serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::ValueOrArray::HeapVector obj; +Program::ValueOrArray::HeapVector serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::ValueOrArray::HeapVector obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Witness &lhs, const Witness &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -6395,11 +7191,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Witness &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::Witness &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -6407,9 +7203,9 @@ void serde::Serializable::serialize(const Circuit::Witness &ob template <> template -Circuit::Witness serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::Witness serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::Witness obj; + Program::Witness obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; diff --git a/acvm-repo/acir/codegen/witness.cpp b/acvm-repo/acir/codegen/witness.cpp index 118d4ca7ac5..ad2b0550db2 100644 --- a/acvm-repo/acir/codegen/witness.cpp +++ b/acvm-repo/acir/codegen/witness.cpp @@ -3,7 +3,7 @@ #include "serde.hpp" #include "bincode.hpp" -namespace WitnessMap { +namespace WitnessStack { struct Witness { uint32_t value; @@ -14,17 +14,79 @@ namespace WitnessMap { }; struct WitnessMap { - std::map value; + std::map value; friend bool operator==(const WitnessMap&, const WitnessMap&); std::vector bincodeSerialize() const; static WitnessMap bincodeDeserialize(std::vector); }; -} // end of namespace WitnessMap + struct StackItem { + uint32_t index; + WitnessStack::WitnessMap witness; + friend bool operator==(const StackItem&, const StackItem&); + std::vector bincodeSerialize() const; + static StackItem bincodeDeserialize(std::vector); + }; + + struct WitnessStack { + std::vector stack; + + friend bool operator==(const WitnessStack&, const WitnessStack&); + std::vector bincodeSerialize() const; + static WitnessStack bincodeDeserialize(std::vector); + }; + +} // end of namespace WitnessStack + + +namespace WitnessStack { + + inline bool operator==(const StackItem &lhs, const StackItem &rhs) { + if (!(lhs.index == rhs.index)) { return false; } + if (!(lhs.witness == rhs.witness)) { return false; } + return true; + } + + inline std::vector StackItem::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } + + inline StackItem StackItem::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } + +} // end of namespace WitnessStack + +template <> +template +void serde::Serializable::serialize(const WitnessStack::StackItem &obj, Serializer &serializer) { + serializer.increase_container_depth(); + serde::Serializable::serialize(obj.index, serializer); + serde::Serializable::serialize(obj.witness, serializer); + serializer.decrease_container_depth(); +} + +template <> +template +WitnessStack::StackItem serde::Deserializable::deserialize(Deserializer &deserializer) { + deserializer.increase_container_depth(); + WitnessStack::StackItem obj; + obj.index = serde::Deserializable::deserialize(deserializer); + obj.witness = serde::Deserializable::deserialize(deserializer); + deserializer.decrease_container_depth(); + return obj; +} -namespace WitnessMap { +namespace WitnessStack { inline bool operator==(const Witness &lhs, const Witness &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -46,11 +108,11 @@ namespace WitnessMap { return value; } -} // end of namespace WitnessMap +} // end of namespace WitnessStack template <> template -void serde::Serializable::serialize(const WitnessMap::Witness &obj, Serializer &serializer) { +void serde::Serializable::serialize(const WitnessStack::Witness &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -58,15 +120,15 @@ void serde::Serializable::serialize(const WitnessMap::Witne template <> template -WitnessMap::Witness serde::Deserializable::deserialize(Deserializer &deserializer) { +WitnessStack::Witness serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - WitnessMap::Witness obj; + WitnessStack::Witness obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace WitnessMap { +namespace WitnessStack { inline bool operator==(const WitnessMap &lhs, const WitnessMap &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -88,11 +150,11 @@ namespace WitnessMap { return value; } -} // end of namespace WitnessMap +} // end of namespace WitnessStack template <> template -void serde::Serializable::serialize(const WitnessMap::WitnessMap &obj, Serializer &serializer) { +void serde::Serializable::serialize(const WitnessStack::WitnessMap &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -100,10 +162,52 @@ void serde::Serializable::serialize(const WitnessMap::Wi template <> template -WitnessMap::WitnessMap serde::Deserializable::deserialize(Deserializer &deserializer) { +WitnessStack::WitnessMap serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - WitnessMap::WitnessMap obj; + WitnessStack::WitnessMap obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } + +namespace WitnessStack { + + inline bool operator==(const WitnessStack &lhs, const WitnessStack &rhs) { + if (!(lhs.stack == rhs.stack)) { return false; } + return true; + } + + inline std::vector WitnessStack::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } + + inline WitnessStack WitnessStack::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } + +} // end of namespace WitnessStack + +template <> +template +void serde::Serializable::serialize(const WitnessStack::WitnessStack &obj, Serializer &serializer) { + serializer.increase_container_depth(); + serde::Serializable::serialize(obj.stack, serializer); + serializer.decrease_container_depth(); +} + +template <> +template +WitnessStack::WitnessStack serde::Deserializable::deserialize(Deserializer &deserializer) { + deserializer.increase_container_depth(); + WitnessStack::WitnessStack obj; + obj.stack = serde::Deserializable::deserialize(deserializer); + deserializer.decrease_container_depth(); + return obj; +} diff --git a/acvm-repo/acir/src/circuit/black_box_functions.rs b/acvm-repo/acir/src/circuit/black_box_functions.rs index 0a7ee244a5e..419c0266b69 100644 --- a/acvm-repo/acir/src/circuit/black_box_functions.rs +++ b/acvm-repo/acir/src/circuit/black_box_functions.rs @@ -1,5 +1,7 @@ -//! Black box functions are ACIR opcodes which rely on backends implementing support for specialized constraints. -//! This makes certain zk-snark unfriendly computations cheaper than if they were implemented in more basic constraints. +//! Black box functions are ACIR opcodes which rely on backends implementing +//! support for specialized constraints. +//! This makes certain zk-snark unfriendly computations cheaper than if they were +//! implemented in more basic constraints. use serde::{Deserialize, Serialize}; #[cfg(test)] @@ -9,59 +11,220 @@ use strum_macros::EnumIter; #[derive(Clone, Debug, Hash, Copy, PartialEq, Eq, Serialize, Deserialize)] #[cfg_attr(test, derive(EnumIter))] pub enum BlackBoxFunc { - /// Bitwise AND. + /// Ciphers (encrypts) the provided plaintext using AES128 in CBC mode, + /// padding the input using PKCS#7. + /// - inputs: byte array `[u8; N]` + /// - iv: initialization vector `[u8; 16]` + /// - key: user key `[u8; 16]` + /// - outputs: byte vector `[u8]` of length `input.len() + (16 - input.len() % 16)` + AES128Encrypt, + + /// Performs the bitwise AND of `lhs` and `rhs`. `bit_size` must be the same for + /// both inputs. + /// - lhs: (witness, bit_size) + /// - rhs: (witness, bit_size) + /// - output: a witness whose value is constrained to be lhs AND rhs, as + /// bit_size bit integers AND, - /// Bitwise XOR. + + /// Performs the bitwise XOR of `lhs` and `rhs`. `bit_size` must be the same for + /// both inputs. + /// - lhs: (witness, bit_size) + /// - rhs: (witness, bit_size) + /// - output: a witness whose value is constrained to be lhs XOR rhs, as + /// bit_size bit integers XOR, - /// Range constraint to ensure that a [`FieldElement`][acir_field::FieldElement] can be represented in a specified number of bits. + + /// Range constraint to ensure that a witness + /// can be represented in the specified number of bits. + /// - input: (witness, bit_size) RANGE, - /// Calculates the SHA256 hash of the inputs. + + /// Computes SHA256 of the inputs + /// - inputs are a byte array, i.e a vector of (witness, 8) + /// - output is a byte array of len 32, i.e an array of 32 (witness, 8), + /// constrained to be the sha256 of the inputs. SHA256, - /// Calculates the Blake2s hash of the inputs. + + /// Computes the Blake2s hash of the inputs, as specified in + /// https://tools.ietf.org/html/rfc7693 + /// - inputs are a byte array, i.e a vector of (witness, 8) + /// - output is a byte array of length 32, i.e. an array of 32 + /// (witness, 8), constrained to be the blake2s of the inputs. Blake2s, - /// Calculates the Blake3 hash of the inputs. + + /// Computes the Blake3 hash of the inputs + /// - inputs are a byte array, i.e a vector of (witness, 8) + /// - output is a byte array of length 32, i.e an array of 32 + /// (witness, 8), constrained to be the blake3 of the inputs. Blake3, - /// Verifies a Schnorr signature over a curve which is "pairing friendly" with the curve on which the ACIR circuit is defined. + + /// Verify a Schnorr signature over the embedded curve + /// - inputs are: + /// - Public key as 2 (witness, 254) + /// - signature as a vector of 64 bytes (witness, 8) + /// - message as a vector of (witness, 8) + /// - output: A witness representing the result of the signature + /// verification; 0 for failure and 1 for success. + /// + /// Since the scalar field of the embedded curve is NOT the ACIR field, the + /// `(r,s)` signature is represented as a 64 bytes array for the two field + /// elements. On the other hand, the public key coordinates are ACIR fields. + /// The proving system decides how the message is to be hashed. Barretenberg + /// uses Blake2s. /// - /// The exact curve which this signature uses will vary based on the curve being used by ACIR. - /// For example, the BN254 curve supports Schnorr signatures over the [Grumpkin][grumpkin] curve. + /// Verifies a Schnorr signature over a curve which is "pairing friendly" + /// with the curve on which the ACIR circuit is defined. + /// + /// The exact curve which this signature uses will vary based on the curve + /// being used by ACIR. For example, the BN254 curve supports Schnorr + /// signatures over the [Grumpkin][grumpkin] curve. /// /// [grumpkin]: https://hackmd.io/@aztec-network/ByzgNxBfd#2-Grumpkin---A-curve-on-top-of-BN-254-for-SNARK-efficient-group-operations SchnorrVerify, + /// Calculates a Pedersen commitment to the inputs. + /// + /// Computes a Pedersen commitment of the inputs using generators of the + /// embedded curve + /// - input: vector of (witness, 254) + /// - output: 2 witnesses representing the x,y coordinates of the resulting + /// Grumpkin point + /// - domain separator: a constant public value (a field element) that you + /// can use so that the commitment also depends on the domain separator. + /// Noir uses 0 as domain separator. + /// + /// The backend should handle proper conversion between the inputs being ACIR + /// field elements and the scalar field of the embedded curve. In the case of + /// Aztec's Barretenberg, the latter is bigger than the ACIR field so it is + /// straightforward. The Pedersen generators are managed by the proving + /// system. + /// + /// The commitment is expected to be additively homomorphic PedersenCommitment, + /// Calculates a Pedersen hash to the inputs. + /// + /// Computes a Pedersen hash of the inputs and their number, using + /// generators of the embedded curve + /// - input: vector of (witness, 254) + /// - output: the x-coordinate of the pedersen commitment of the + /// 'prepended input' (see below) + /// - domain separator: a constant public value (a field element) that you + /// can use so that the hash also depends on the domain separator. Noir + /// uses 0 as domain separator. + /// + /// In Barretenberg, PedersenHash is doing the same as PedersenCommitment, + /// except that it prepends the inputs with their length. This is expected + /// to not be additively homomorphic. PedersenHash, + /// Verifies a ECDSA signature over the secp256k1 curve. + /// - inputs: + /// - x coordinate of public key as 32 bytes + /// - y coordinate of public key as 32 bytes + /// - the signature, as a 64 bytes array + /// - the hash of the message, as a vector of bytes + /// - output: 0 for failure and 1 for success + /// + /// Inputs and outputs are similar to SchnorrVerify, except that because we + /// use a different curve (secp256k1), the field elements involved in the + /// signature and the public key are defined as an array of 32 bytes. + /// Another difference is that we assume the message is already hashed. EcdsaSecp256k1, + /// Verifies a ECDSA signature over the secp256r1 curve. + /// + /// Same as EcdsaSecp256k1, but done over another curve. EcdsaSecp256r1, - /// Performs scalar multiplication over the embedded curve on which [`FieldElement`][acir_field::FieldElement] is defined. - FixedBaseScalarMul, - /// Calculates the Keccak256 hash of the inputs. + + /// Multiple scalar multiplication (MSM) with a variable base/input point + /// (P) of the embedded curve. An MSM multiplies the points and scalars and + /// sums the results. + /// - input: + /// points (witness, N) a vector of x and y coordinates of input + /// points `[x1, y1, x2, y2,...]`. + /// scalars (witness, N) a vector of low and high limbs of input + /// scalars `[s1_low, s1_high, s2_low, s2_high, ...]`. (witness, N) + /// For Barretenberg, they must both be less than 128 bits. + /// - output: + /// a tuple of `x` and `y` coordinates of output. + /// Points computed as `s_low*P+s_high*2^{128}*P` + /// + /// Because the Grumpkin scalar field is bigger than the ACIR field, we + /// provide 2 ACIR fields representing the low and high parts of the Grumpkin + /// scalar $a$: `a=low+high*2^{128}`, with `low, high < 2^{128}` + MultiScalarMul, + + /// Computes the Keccak-256 (Ethereum version) of the inputs. + /// - inputs: Vector of bytes (witness, 8) + /// - outputs: Array of 32 bytes (witness, 8) Keccak256, - /// Keccak Permutation function of 1600 width + + /// Keccak Permutation function of width 1600 + /// - inputs: An array of 25 64-bit Keccak lanes that represent a keccak sponge of 1600 bits + /// - outputs: The result of a keccak f1600 permutation on the input state. Also an array of 25 Keccak lanes. Keccakf1600, - /// Compute a recursive aggregation object when verifying a proof inside another circuit. - /// This outputted aggregation object will then be either checked in a top-level verifier or aggregated upon again. + + /// Compute a recursive aggregation object when verifying a proof inside + /// another circuit. + /// This outputted aggregation object will then be either checked in a + /// top-level verifier or aggregated upon again. + /// + /// **Warning: this opcode is subject to change.** + /// Note that the `254` in `(witness, 254)` refers to the upper bound of + /// the `witness`. + /// - verification_key: Vector of (witness, 254) representing the + /// verification key of the circuit being verified + /// - public_inputs: Vector of (witness, 254) representing the public + /// inputs corresponding to the proof being verified + /// - key_hash: one (witness, 254). It should be the hash of the + /// verification key. Barretenberg expects the Pedersen hash of the + /// verification key + /// + /// Another thing that it does is preparing the verification of the proof. + /// In order to fully verify a proof, some operations may still be required + /// to be done by the final verifier. This is why this black box function + /// does not say if verification is passing or not. + /// + /// This black box function does not fully verify a proof, what it does is + /// verifying that the key_hash is indeed a hash of verification_key, + /// allowing the user to use the verification key as private inputs and only + /// have the key_hash as public input, which is more performant. + /// + /// If one of the recursive proofs you verify with the black box function does not + /// verify, then the verification of the proof of the main ACIR program will + /// ultimately fail. RecursiveAggregation, - /// Addition over the embedded curve on which [`FieldElement`][acir_field::FieldElement] is defined. + + /// Addition over the embedded curve on which the witness is defined. EmbeddedCurveAdd, + /// BigInt addition BigIntAdd, + /// BigInt subtraction BigIntSub, + /// BigInt multiplication BigIntMul, + /// BigInt division BigIntDiv, + /// BigInt from le bytes BigIntFromLeBytes, + /// BigInt to le bytes BigIntToLeBytes, + /// Permutation function of Poseidon2 Poseidon2Permutation, + /// SHA256 compression function + /// - input: [(witness, 32); 16] + /// - state: [(witness, 32); 8] + /// - output: [(witness, 32); 8] Sha256Compression, } @@ -74,6 +237,7 @@ impl std::fmt::Display for BlackBoxFunc { impl BlackBoxFunc { pub fn name(&self) -> &'static str { match self { + BlackBoxFunc::AES128Encrypt => "aes128_encrypt", BlackBoxFunc::SHA256 => "sha256", BlackBoxFunc::SchnorrVerify => "schnorr_verify", BlackBoxFunc::Blake2s => "blake2s", @@ -81,7 +245,7 @@ impl BlackBoxFunc { BlackBoxFunc::PedersenCommitment => "pedersen_commitment", BlackBoxFunc::PedersenHash => "pedersen_hash", BlackBoxFunc::EcdsaSecp256k1 => "ecdsa_secp256k1", - BlackBoxFunc::FixedBaseScalarMul => "fixed_base_scalar_mul", + BlackBoxFunc::MultiScalarMul => "multi_scalar_mul", BlackBoxFunc::EmbeddedCurveAdd => "embedded_curve_add", BlackBoxFunc::AND => "and", BlackBoxFunc::XOR => "xor", @@ -103,6 +267,7 @@ impl BlackBoxFunc { pub fn lookup(op_name: &str) -> Option { match op_name { + "aes128_encrypt" => Some(BlackBoxFunc::AES128Encrypt), "sha256" => Some(BlackBoxFunc::SHA256), "schnorr_verify" => Some(BlackBoxFunc::SchnorrVerify), "blake2s" => Some(BlackBoxFunc::Blake2s), @@ -111,7 +276,7 @@ impl BlackBoxFunc { "pedersen_hash" => Some(BlackBoxFunc::PedersenHash), "ecdsa_secp256k1" => Some(BlackBoxFunc::EcdsaSecp256k1), "ecdsa_secp256r1" => Some(BlackBoxFunc::EcdsaSecp256r1), - "fixed_base_scalar_mul" => Some(BlackBoxFunc::FixedBaseScalarMul), + "multi_scalar_mul" => Some(BlackBoxFunc::MultiScalarMul), "embedded_curve_add" => Some(BlackBoxFunc::EmbeddedCurveAdd), "and" => Some(BlackBoxFunc::AND), "xor" => Some(BlackBoxFunc::XOR), diff --git a/acvm-repo/acir/src/circuit/brillig.rs b/acvm-repo/acir/src/circuit/brillig.rs index f394a46ff82..ee25d05afb0 100644 --- a/acvm-repo/acir/src/circuit/brillig.rs +++ b/acvm-repo/acir/src/circuit/brillig.rs @@ -6,9 +6,9 @@ use serde::{Deserialize, Serialize}; /// Inputs for the Brillig VM. These are the initial inputs /// that the Brillig VM will use to start. #[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] -pub enum BrilligInputs { - Single(Expression), - Array(Vec), +pub enum BrilligInputs { + Single(Expression), + Array(Vec>), MemoryArray(BlockId), } @@ -20,12 +20,10 @@ pub enum BrilligOutputs { Array(Vec), } -#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] -pub struct Brillig { - pub inputs: Vec, - pub outputs: Vec, - /// The Brillig VM bytecode to be executed by this ACIR opcode. - pub bytecode: Vec, - /// Predicate of the Brillig execution - indicates if it should be skipped - pub predicate: Option, +/// This is purely a wrapper struct around a list of Brillig opcode's which represents +/// a full Brillig function to be executed by the Brillig VM. +/// This is stored separately on a program and accessed through a [BrilligPointer]. +#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Default, Debug)] +pub struct BrilligBytecode { + pub bytecode: Vec>, } diff --git a/acvm-repo/acir/src/circuit/directives.rs b/acvm-repo/acir/src/circuit/directives.rs index 099d0634399..3bc66288590 100644 --- a/acvm-repo/acir/src/circuit/directives.rs +++ b/acvm-repo/acir/src/circuit/directives.rs @@ -5,7 +5,7 @@ use serde::{Deserialize, Serialize}; /// Directives do not apply any constraints. /// You can think of them as opcodes that allow one to use non-determinism /// In the future, this can be replaced with asm non-determinism blocks -pub enum Directive { +pub enum Directive { //decomposition of a: a=\sum b[i]*radix^i where b is an array of witnesses < radix in little endian form - ToLeRadix { a: Expression, b: Vec, radix: u32 }, + ToLeRadix { a: Expression, b: Vec, radix: u32 }, } diff --git a/acvm-repo/acir/src/circuit/mod.rs b/acvm-repo/acir/src/circuit/mod.rs index 7e6cbf23803..7f3c1890717 100644 --- a/acvm-repo/acir/src/circuit/mod.rs +++ b/acvm-repo/acir/src/circuit/mod.rs @@ -3,7 +3,8 @@ pub mod brillig; pub mod directives; pub mod opcodes; -use crate::native_types::Witness; +use crate::native_types::{Expression, Witness}; +use acir_field::AcirField; pub use opcodes::Opcode; use thiserror::Error; @@ -15,6 +16,8 @@ use serde::{de::Error as DeserializationError, Deserialize, Deserializer, Serial use std::collections::BTreeSet; +use self::{brillig::BrilligBytecode, opcodes::BlockId}; + /// Specifies the maximum width of the expressions which will be constrained. /// /// Unbounded Expressions are useful if you are eventually going to pass the ACIR @@ -32,12 +35,20 @@ pub enum ExpressionWidth { }, } +/// A program represented by multiple ACIR circuits. The execution trace of these +/// circuits is dictated by construction of the [crate::native_types::WitnessStack]. #[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Default)] -pub struct Circuit { +pub struct Program { + pub functions: Vec>, + pub unconstrained_functions: Vec>, +} + +#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Default)] +pub struct Circuit { // current_witness_index is the highest witness index in the circuit. The next witness to be added to this circuit // will take on this value. (The value is cached here as an optimization.) pub current_witness_index: u32, - pub opcodes: Vec, + pub opcodes: Vec>, pub expression_width: ExpressionWidth, /// The set of private inputs to the circuit. @@ -49,18 +60,14 @@ pub struct Circuit { pub public_parameters: PublicInputs, /// The set of public inputs calculated within the circuit. pub return_values: PublicInputs, - /// Maps opcode locations to failed assertion messages. - /// These messages are embedded in the circuit to provide useful feedback to users + /// Maps opcode locations to failed assertion payloads. + /// The data in the payload is embedded in the circuit to provide useful feedback to users /// when a constraint in the circuit is not satisfied. /// // Note: This should be a BTreeMap, but serde-reflect is creating invalid // c++ code at the moment when it is, due to OpcodeLocation needing a comparison // implementation which is never generated. - // - // TODO: These are only used for constraints that are explicitly created during code generation (such as index out of bounds on slices) - // TODO: We should move towards having all the checks being evaluated in the same manner - // TODO: as runtime assert messages specified by the user. This will also be a breaking change as the `Circuit` structure will change. - pub assert_messages: Vec<(OpcodeLocation, String)>, + pub assert_messages: Vec<(OpcodeLocation, AssertionPayload)>, /// States whether the backend should use a SNARK recursion friendly prover. /// If implemented by a backend, this means that proofs generated with this circuit @@ -68,17 +75,79 @@ pub struct Circuit { pub recursive: bool, } -impl Circuit { - /// Returns the assert message associated with the provided [`OpcodeLocation`]. - /// Returns `None` if no such assert message exists. - pub fn get_assert_message(&self, opcode_location: OpcodeLocation) -> Option<&str> { - self.assert_messages - .iter() - .find(|(loc, _)| *loc == opcode_location) - .map(|(_, message)| message.as_str()) +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub enum ExpressionOrMemory { + Expression(Expression), + Memory(BlockId), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub enum AssertionPayload { + StaticString(String), + Dynamic(/* error_selector */ u64, Vec>), +} + +#[derive(Debug, Copy, PartialEq, Eq, Hash, Clone, PartialOrd, Ord)] +pub struct ErrorSelector(u64); + +impl ErrorSelector { + pub fn new(integer: u64) -> Self { + ErrorSelector(integer) + } + + pub fn as_u64(&self) -> u64 { + self.0 + } +} + +impl Serialize for ErrorSelector { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + self.0.to_string().serialize(serializer) } } +impl<'de> Deserialize<'de> for ErrorSelector { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s: String = Deserialize::deserialize(deserializer)?; + let as_u64 = s.parse().map_err(serde::de::Error::custom)?; + Ok(ErrorSelector(as_u64)) + } +} + +/// This selector indicates that the payload is a string. +/// This is used to parse any error with a string payload directly, +/// to avoid users having to parse the error externally to the ACVM. +/// Only non-string errors need to be parsed externally to the ACVM using the circuit ABI. +pub const STRING_ERROR_SELECTOR: ErrorSelector = ErrorSelector(0); + +#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)] +pub struct RawAssertionPayload { + pub selector: ErrorSelector, + pub data: Vec, +} + +#[derive(Clone, PartialEq, Eq, Debug)] +pub enum ResolvedAssertionPayload { + String(String), + Raw(RawAssertionPayload), +} + +#[derive(Debug, Copy, Clone)] +/// The opcode location for a call to a separate ACIR circuit +/// This includes the function index of the caller within a [program][Program] +/// and the index in the callers ACIR to the specific call opcode. +/// This is only resolved and set during circuit execution. +pub struct ResolvedOpcodeLocation { + pub acir_function_index: usize, + pub opcode_location: OpcodeLocation, +} + #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)] /// Opcodes are locatable so that callers can /// map opcodes to debug information related to their context. @@ -135,7 +204,7 @@ impl FromStr for OpcodeLocation { } } -impl Circuit { +impl Circuit { pub fn num_vars(&self) -> u32 { self.current_witness_index + 1 } @@ -152,7 +221,9 @@ impl Circuit { self.public_parameters.0.union(&self.return_values.0).cloned().collect(); PublicInputs(public_inputs) } +} +impl Program { fn write(&self, writer: W) -> std::io::Result<()> { let buf = bincode::serialize(self).unwrap(); let mut encoder = flate2::write::GzEncoder::new(writer, Compression::default()); @@ -161,6 +232,24 @@ impl Circuit { Ok(()) } + pub fn serialize_program(program: &Self) -> Vec { + let mut program_bytes: Vec = Vec::new(); + program.write(&mut program_bytes).expect("expected circuit to be serializable"); + program_bytes + } + + // Serialize and base64 encode program + pub fn serialize_program_base64(program: &Self, s: S) -> Result + where + S: Serializer, + { + let program_bytes = Program::serialize_program(program); + let encoded_b64 = base64::engine::general_purpose::STANDARD.encode(program_bytes); + s.serialize_str(&encoded_b64) + } +} + +impl Deserialize<'a>> Program { fn read(reader: R) -> std::io::Result { let mut gz_decoder = flate2::read::GzDecoder::new(reader); let mut buf_d = Vec::new(); @@ -169,63 +258,55 @@ impl Circuit { .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) + pub fn deserialize_program(serialized_circuit: &[u8]) -> std::io::Result { + Program::read(serialized_circuit) } - // Deserialize and base64 decode circuit - pub fn deserialize_circuit_base64<'de, D>(deserializer: D) -> Result + // Deserialize and base64 decode program + pub fn deserialize_program_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 + let program_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)?; + let circuit = Self::deserialize_program(&program_bytes).map_err(D::Error::custom)?; Ok(circuit) } } -impl std::fmt::Display for Circuit { +impl std::fmt::Display for Circuit { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { writeln!(f, "current witness index : {}", self.current_witness_index)?; - let write_public_inputs = |f: &mut std::fmt::Formatter<'_>, - public_inputs: &PublicInputs| - -> Result<(), std::fmt::Error> { - write!(f, "[")?; - let public_input_indices = public_inputs.indices(); - for (index, public_input) in public_input_indices.iter().enumerate() { - write!(f, "{public_input}")?; - if index != public_input_indices.len() - 1 { - write!(f, ", ")?; + let write_witness_indices = + |f: &mut std::fmt::Formatter<'_>, indices: &[u32]| -> Result<(), std::fmt::Error> { + write!(f, "[")?; + for (index, witness_index) in indices.iter().enumerate() { + write!(f, "{witness_index}")?; + if index != indices.len() - 1 { + write!(f, ", ")?; + } } - } - writeln!(f, "]") - }; + writeln!(f, "]") + }; + + write!(f, "private parameters indices : ")?; + write_witness_indices( + f, + &self + .private_parameters + .iter() + .map(|witness| witness.witness_index()) + .collect::>(), + )?; write!(f, "public parameters indices : ")?; - write_public_inputs(f, &self.public_parameters)?; + write_witness_indices(f, &self.public_parameters.indices())?; write!(f, "return value indices : ")?; - write_public_inputs(f, &self.return_values)?; + write_witness_indices(f, &self.return_values.indices())?; for opcode in &self.opcodes { writeln!(f, "{opcode}")?; @@ -234,7 +315,27 @@ impl std::fmt::Display for Circuit { } } -impl std::fmt::Debug for Circuit { +impl std::fmt::Debug for Circuit { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self, f) + } +} + +impl std::fmt::Display for Program { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + for (func_index, function) in self.functions.iter().enumerate() { + writeln!(f, "func {}", func_index)?; + writeln!(f, "{}", function)?; + } + for (func_index, function) in self.unconstrained_functions.iter().enumerate() { + writeln!(f, "unconstrained func {}", func_index)?; + writeln!(f, "{:?}", function.bytecode)?; + } + Ok(()) + } +} + +impl std::fmt::Debug for Program { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(self, f) } @@ -262,77 +363,51 @@ mod tests { opcodes::{BlackBoxFuncCall, FunctionInput}, Circuit, Compression, Opcode, PublicInputs, }; - use crate::{circuit::ExpressionWidth, native_types::Witness}; - use acir_field::FieldElement; + use crate::{ + circuit::{ExpressionWidth, Program}, + native_types::Witness, + }; + use acir_field::{AcirField, FieldElement}; + use serde::{Deserialize, Serialize}; - fn and_opcode() -> Opcode { + fn and_opcode() -> Opcode { Opcode::BlackBoxFuncCall(BlackBoxFuncCall::AND { lhs: FunctionInput { witness: Witness(1), num_bits: 4 }, rhs: FunctionInput { witness: Witness(2), num_bits: 4 }, output: Witness(3), }) } - fn range_opcode() -> Opcode { + fn range_opcode() -> Opcode { Opcode::BlackBoxFuncCall(BlackBoxFuncCall::RANGE { input: FunctionInput { witness: Witness(1), num_bits: 8 }, }) } - fn keccakf1600_opcode() -> Opcode { - Opcode::BlackBoxFuncCall(BlackBoxFuncCall::Keccakf1600 { - inputs: vec![ - FunctionInput { witness: Witness(1), num_bits: 64 }, - FunctionInput { witness: Witness(2), num_bits: 64 }, - FunctionInput { witness: Witness(3), num_bits: 64 }, - FunctionInput { witness: Witness(4), num_bits: 64 }, - FunctionInput { witness: Witness(5), num_bits: 64 }, - FunctionInput { witness: Witness(6), num_bits: 64 }, - FunctionInput { witness: Witness(7), num_bits: 64 }, - FunctionInput { witness: Witness(8), num_bits: 64 }, - FunctionInput { witness: Witness(9), num_bits: 64 }, - FunctionInput { witness: Witness(10), num_bits: 64 }, - FunctionInput { witness: Witness(11), num_bits: 64 }, - FunctionInput { witness: Witness(12), num_bits: 64 }, - FunctionInput { witness: Witness(13), num_bits: 64 }, - FunctionInput { witness: Witness(14), num_bits: 64 }, - FunctionInput { witness: Witness(15), num_bits: 64 }, - FunctionInput { witness: Witness(16), num_bits: 64 }, - FunctionInput { witness: Witness(17), num_bits: 64 }, - FunctionInput { witness: Witness(18), num_bits: 64 }, - FunctionInput { witness: Witness(19), num_bits: 64 }, - FunctionInput { witness: Witness(20), num_bits: 64 }, - FunctionInput { witness: Witness(21), num_bits: 64 }, - FunctionInput { witness: Witness(22), num_bits: 64 }, - FunctionInput { witness: Witness(23), num_bits: 64 }, - FunctionInput { witness: Witness(24), num_bits: 64 }, - FunctionInput { witness: Witness(25), num_bits: 64 }, - ], - outputs: vec![ - Witness(26), - Witness(27), - Witness(28), - Witness(29), - Witness(30), - Witness(31), - Witness(32), - Witness(33), - Witness(34), - Witness(35), - Witness(36), - Witness(37), - Witness(38), - Witness(39), - Witness(40), - Witness(41), - Witness(42), - Witness(43), - Witness(44), - Witness(45), - Witness(46), - Witness(47), - Witness(48), - Witness(49), - Witness(50), - ], + fn keccakf1600_opcode() -> Opcode { + let inputs: Box<[FunctionInput; 25]> = Box::new(std::array::from_fn(|i| FunctionInput { + witness: Witness(i as u32 + 1), + num_bits: 8, + })); + let outputs: Box<[Witness; 25]> = Box::new(std::array::from_fn(|i| Witness(i as u32 + 26))); + + Opcode::BlackBoxFuncCall(BlackBoxFuncCall::Keccakf1600 { inputs, outputs }) + } + fn schnorr_verify_opcode() -> Opcode { + let public_key_x = + FunctionInput { witness: Witness(1), num_bits: FieldElement::max_num_bits() }; + let public_key_y = + FunctionInput { witness: Witness(2), num_bits: FieldElement::max_num_bits() }; + let signature: Box<[FunctionInput; 64]> = Box::new(std::array::from_fn(|i| { + FunctionInput { witness: Witness(i as u32 + 3), num_bits: 8 } + })); + let message: Vec = vec![FunctionInput { witness: Witness(67), num_bits: 8 }]; + let output = Witness(68); + + Opcode::BlackBoxFuncCall(BlackBoxFuncCall::SchnorrVerify { + public_key_x, + public_key_y, + signature, + message, + output, }) } @@ -341,21 +416,24 @@ mod tests { let circuit = Circuit { current_witness_index: 5, expression_width: ExpressionWidth::Unbounded, - opcodes: vec![and_opcode(), range_opcode()], + opcodes: vec![and_opcode::(), range_opcode(), schnorr_verify_opcode()], private_parameters: BTreeSet::new(), public_parameters: PublicInputs(BTreeSet::from_iter(vec![Witness(2), Witness(12)])), return_values: PublicInputs(BTreeSet::from_iter(vec![Witness(4), Witness(12)])), assert_messages: Default::default(), recursive: false, }; - - fn read_write(circuit: Circuit) -> (Circuit, Circuit) { - let bytes = Circuit::serialize_circuit(&circuit); - let got_circuit = Circuit::deserialize_circuit(&bytes).unwrap(); - (circuit, got_circuit) + let program = Program { functions: vec![circuit], unconstrained_functions: Vec::new() }; + + fn read_write Deserialize<'a>>( + program: Program, + ) -> (Program, Program) { + let bytes = Program::serialize_program(&program); + let got_program = Program::deserialize_program(&bytes).unwrap(); + (program, got_program) } - let (circ, got_circ) = read_write(circuit); + let (circ, got_circ) = read_write(program); assert_eq!(circ, got_circ); } @@ -373,6 +451,7 @@ mod tests { range_opcode(), and_opcode(), keccakf1600_opcode(), + schnorr_verify_opcode(), ], private_parameters: BTreeSet::new(), public_parameters: PublicInputs(BTreeSet::from_iter(vec![Witness(2)])), @@ -380,11 +459,12 @@ mod tests { assert_messages: Default::default(), recursive: false, }; + let program = Program { functions: vec![circuit], unconstrained_functions: Vec::new() }; - let json = serde_json::to_string_pretty(&circuit).unwrap(); + let json = serde_json::to_string_pretty(&program).unwrap(); let deserialized = serde_json::from_str(&json).unwrap(); - assert_eq!(circuit, deserialized); + assert_eq!(program, deserialized); } #[test] @@ -400,7 +480,8 @@ mod tests { encoder.write_all(bad_circuit).unwrap(); encoder.finish().unwrap(); - let deserialization_result = Circuit::deserialize_circuit(&zipped_bad_circuit); + let deserialization_result: Result, _> = + Program::deserialize_program(&zipped_bad_circuit); assert!(deserialization_result.is_err()); } } diff --git a/acvm-repo/acir/src/circuit/opcodes.rs b/acvm-repo/acir/src/circuit/opcodes.rs index f725ba8c32a..984422c5e3a 100644 --- a/acvm-repo/acir/src/circuit/opcodes.rs +++ b/acvm-repo/acir/src/circuit/opcodes.rs @@ -1,5 +1,9 @@ -use super::{brillig::Brillig, directives::Directive}; +use super::{ + brillig::{BrilligInputs, BrilligOutputs}, + directives::Directive, +}; use crate::native_types::{Expression, Witness}; +use acir_field::AcirField; use serde::{Deserialize, Serialize}; mod black_box_function_call; @@ -8,30 +12,130 @@ mod memory_operation; pub use black_box_function_call::{BlackBoxFuncCall, FunctionInput}; pub use memory_operation::{BlockId, MemOp}; +#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] +pub enum BlockType { + Memory, + CallData, + ReturnData, +} + +impl BlockType { + pub fn is_databus(&self) -> bool { + matches!(self, BlockType::CallData | BlockType::ReturnData) + } +} + #[allow(clippy::large_enum_variant)] #[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] -pub enum Opcode { - AssertZero(Expression), - /// Calls to "gadgets" which rely on backends implementing support for specialized constraints. +pub enum Opcode { + /// An `AssertZero` opcode adds the constraint that `P(w) = 0`, where + /// `w=(w_1,..w_n)` is a tuple of `n` witnesses, and `P` is a multi-variate + /// polynomial of total degree at most `2`. + /// + /// The coefficients `{q_M}_{i,j}, q_i,q_c` of the polynomial are known + /// values which define the opcode. + /// + /// A general expression of assert-zero opcode is the following: + /// ``` + /// \sum_{i,j} {q_M}_{i,j}w_iw_j + \sum_i q_iw_i +q_c = 0 + /// ``` + /// + /// An assert-zero opcode can be used to: + /// - **express a constraint** on witnesses; for instance to express that a + /// witness `w` is a boolean, you can add the opcode: `w*w-w=0` + /// - or, to **compute the value** of an arithmetic operation of some inputs. + /// For instance, to multiply two witnesses `x` and `y`, you would use the + /// opcode `z-x*y=0`, which would constrain `z` to be `x*y`. /// - /// Often used for exposing more efficient implementations of SNARK-unfriendly computations. + /// The solver expects that at most one witness is not known when executing the opcode. + AssertZero(Expression), + + /// Calls to "gadgets" which rely on backends implementing support for + /// specialized constraints. + /// + /// Often used for exposing more efficient implementations of + /// SNARK-unfriendly computations. + /// + /// All black box functions take as input a tuple `(witness, num_bits)`, + /// where `num_bits` is a constant representing the bit size of the input + /// witness, and they have one or several witnesses as output. + /// + /// Some more advanced computations assume that the proving system has an + /// 'embedded curve'. It is a curve that cycles with the main curve of the + /// proving system, i.e the scalar field of the embedded curve is the base + /// field of the main one, and vice-versa. + /// + /// Aztec's Barretenberg uses BN254 as the main curve and Grumpkin as the + /// embedded curve. BlackBoxFuncCall(BlackBoxFuncCall), - Directive(Directive), - Brillig(Brillig), + + /// This opcode is a specialization of a Brillig opcode. Instead of having + /// some generic assembly code like Brillig, a directive has a hardcoded + /// name which tells the solver which computation to do: with Brillig, the + /// computation refers to the compiled bytecode of an unconstrained Noir + /// function, but with a directive, the computation is hardcoded inside the + /// compiler. + /// + /// Directives will be replaced by Brillig opcodes in the future. + Directive(Directive), + /// Atomic operation on a block of memory + /// + /// ACIR is able to address any array of witnesses. Each array is assigned + /// an id (BlockId) and needs to be initialized with the MemoryInit opcode. + /// Then it is possible to read and write from/to an array by providing the + /// index and the value we read/write as arithmetic expressions. Note that + /// ACIR arrays all have a known fixed length (given in the MemoryInit + /// opcode below) + /// + /// - predicate: an arithmetic expression that disables the execution of the + /// opcode when the expression evaluates to zero MemoryOp { + /// identifier of the array block_id: BlockId, - op: MemOp, + /// describe the memory operation to perform + op: MemOp, /// Predicate of the memory operation - indicates if it should be skipped - predicate: Option, + predicate: Option>, }, - MemoryInit { - block_id: BlockId, - init: Vec, + + /// Initialize an ACIR array from a vector of witnesses. + /// - block_id: identifier of the array + /// - init: Vector of witnesses specifying the initial value of the array + /// + /// There must be only one MemoryInit per block_id, and MemoryOp opcodes must + /// come after the MemoryInit. + MemoryInit { block_id: BlockId, init: Vec, block_type: BlockType }, + + /// Calls to unconstrained functions + BrilligCall { + /// Id for the function being called. It is the responsibility of the executor + /// to fetch the appropriate Brillig bytecode from this id. + id: u32, + /// Inputs to the function call + inputs: Vec>, + /// Outputs to the function call + outputs: Vec, + /// Predicate of the Brillig execution - indicates if it should be skipped + predicate: Option>, + }, + + /// Calls to functions represented as a separate circuit. A call opcode allows us + /// to build a call stack when executing the outer-most circuit. + Call { + /// Id for the function being called. It is the responsibility of the executor + /// to fetch the appropriate circuit from this id. + id: u32, + /// Inputs to the function call + inputs: Vec, + /// Outputs of the function call + outputs: Vec, + /// Predicate of the circuit execution - indicates if it should be skipped + predicate: Option>, }, } -impl std::fmt::Display for Opcode { +impl std::fmt::Display for Opcode { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Opcode::AssertZero(expr) => { @@ -60,12 +164,6 @@ impl std::fmt::Display for Opcode { b.last().unwrap().witness_index(), ) } - Opcode::Brillig(brillig) => { - write!(f, "BRILLIG: ")?; - writeln!(f, "inputs: {:?}", brillig.inputs)?; - writeln!(f, "outputs: {:?}", brillig.outputs)?; - writeln!(f, "{:?}", brillig.bytecode) - } Opcode::MemoryOp { block_id, op, predicate } => { write!(f, "MEM ")?; if let Some(pred) = predicate { @@ -82,15 +180,37 @@ impl std::fmt::Display for Opcode { write!(f, "(id: {}, op {} at: {}) ", block_id.0, op.operation, op.index) } } - Opcode::MemoryInit { block_id, init } => { - write!(f, "INIT ")?; + Opcode::MemoryInit { block_id, init, block_type: databus } => { + match databus { + BlockType::Memory => write!(f, "INIT ")?, + BlockType::CallData => write!(f, "INIT CALLDATA ")?, + BlockType::ReturnData => write!(f, "INIT RETURNDATA ")?, + } write!(f, "(id: {}, len: {}) ", block_id.0, init.len()) } + // We keep the display for a BrilligCall and circuit Call separate as they + // are distinct in their functionality and we should maintain this separation for debugging. + Opcode::BrilligCall { id, inputs, outputs, predicate } => { + write!(f, "BRILLIG CALL func {}: ", id)?; + if let Some(pred) = predicate { + writeln!(f, "PREDICATE = {pred}")?; + } + write!(f, "inputs: {:?}, ", inputs)?; + write!(f, "outputs: {:?}", outputs) + } + Opcode::Call { id, inputs, outputs, predicate } => { + write!(f, "CALL func {}: ", id)?; + if let Some(pred) = predicate { + writeln!(f, "PREDICATE = {pred}")?; + } + write!(f, "inputs: {:?}, ", inputs)?; + write!(f, "outputs: {:?}", outputs) + } } } } -impl std::fmt::Debug for Opcode { +impl std::fmt::Debug for Opcode { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(self, f) } diff --git a/acvm-repo/acir/src/circuit/opcodes/black_box_function_call.rs b/acvm-repo/acir/src/circuit/opcodes/black_box_function_call.rs index f73417a4b5b..362e9ba5936 100644 --- a/acvm-repo/acir/src/circuit/opcodes/black_box_function_call.rs +++ b/acvm-repo/acir/src/circuit/opcodes/black_box_function_call.rs @@ -1,6 +1,6 @@ use crate::native_types::Witness; use crate::BlackBoxFunc; -use serde::{Deserialize, Serialize}; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; // Note: Some functions will not use all of the witness // So we need to supply how many bits of the witness is needed @@ -10,14 +10,14 @@ pub struct FunctionInput { pub num_bits: u32, } -impl FunctionInput { - pub fn dummy() -> Self { - Self { witness: Witness(0), num_bits: 0 } - } -} - #[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] pub enum BlackBoxFuncCall { + AES128Encrypt { + inputs: Vec, + iv: Box<[FunctionInput; 16]>, + key: Box<[FunctionInput; 16]>, + outputs: Vec, + }, AND { lhs: FunctionInput, rhs: FunctionInput, @@ -33,20 +33,24 @@ pub enum BlackBoxFuncCall { }, SHA256 { inputs: Vec, - outputs: Vec, + outputs: Box<[Witness; 32]>, }, Blake2s { inputs: Vec, - outputs: Vec, + outputs: Box<[Witness; 32]>, }, Blake3 { inputs: Vec, - outputs: Vec, + outputs: Box<[Witness; 32]>, }, SchnorrVerify { public_key_x: FunctionInput, public_key_y: FunctionInput, - signature: Vec, + #[serde( + serialize_with = "serialize_big_array", + deserialize_with = "deserialize_big_array_into_box" + )] + signature: Box<[FunctionInput; 64]>, message: Vec, output: Witness, }, @@ -61,47 +65,49 @@ pub enum BlackBoxFuncCall { output: Witness, }, EcdsaSecp256k1 { - public_key_x: Vec, - public_key_y: Vec, - signature: Vec, - hashed_message: Vec, + public_key_x: Box<[FunctionInput; 32]>, + public_key_y: Box<[FunctionInput; 32]>, + #[serde( + serialize_with = "serialize_big_array", + deserialize_with = "deserialize_big_array_into_box" + )] + signature: Box<[FunctionInput; 64]>, + hashed_message: Box<[FunctionInput; 32]>, output: Witness, }, EcdsaSecp256r1 { - public_key_x: Vec, - public_key_y: Vec, - signature: Vec, - hashed_message: Vec, + public_key_x: Box<[FunctionInput; 32]>, + public_key_y: Box<[FunctionInput; 32]>, + #[serde( + serialize_with = "serialize_big_array", + deserialize_with = "deserialize_big_array_into_box" + )] + signature: Box<[FunctionInput; 64]>, + hashed_message: Box<[FunctionInput; 32]>, output: Witness, }, - FixedBaseScalarMul { - low: FunctionInput, - high: FunctionInput, - outputs: (Witness, Witness), + MultiScalarMul { + points: Vec, + scalars: Vec, + outputs: (Witness, Witness, Witness), }, EmbeddedCurveAdd { - input1_x: FunctionInput, - input1_y: FunctionInput, - input2_x: FunctionInput, - input2_y: FunctionInput, - outputs: (Witness, Witness), + input1: Box<[FunctionInput; 3]>, + input2: Box<[FunctionInput; 3]>, + outputs: (Witness, Witness, Witness), }, Keccak256 { - inputs: Vec, - outputs: Vec, - }, - Keccak256VariableLength { inputs: Vec, /// This is the number of bytes to take /// from the input. Note: if `var_message_size` /// is more than the number of bytes in the input, /// then an error is returned. var_message_size: FunctionInput, - outputs: Vec, + outputs: Box<[Witness; 32]>, }, Keccakf1600 { - inputs: Vec, - outputs: Vec, + inputs: Box<[FunctionInput; 25]>, + outputs: Box<[Witness; 25]>, }, RecursiveAggregation { verification_key: Vec, @@ -164,17 +170,18 @@ pub enum BlackBoxFuncCall { /// * `outputs` - result of the input compressed into 256 bits Sha256Compression { /// 512 bits of the input message, represented by 16 u32s - inputs: Vec, + inputs: Box<[FunctionInput; 16]>, /// Vector of 8 u32s used to compress the input - hash_values: Vec, + hash_values: Box<[FunctionInput; 8]>, /// Output of the compression, represented by 8 u32s - outputs: Vec, + outputs: Box<[Witness; 8]>, }, } impl BlackBoxFuncCall { pub fn get_black_box_func(&self) -> BlackBoxFunc { match self { + BlackBoxFuncCall::AES128Encrypt { .. } => BlackBoxFunc::AES128Encrypt, BlackBoxFuncCall::AND { .. } => BlackBoxFunc::AND, BlackBoxFuncCall::XOR { .. } => BlackBoxFunc::XOR, BlackBoxFuncCall::RANGE { .. } => BlackBoxFunc::RANGE, @@ -186,10 +193,9 @@ impl BlackBoxFuncCall { BlackBoxFuncCall::PedersenHash { .. } => BlackBoxFunc::PedersenHash, BlackBoxFuncCall::EcdsaSecp256k1 { .. } => BlackBoxFunc::EcdsaSecp256k1, BlackBoxFuncCall::EcdsaSecp256r1 { .. } => BlackBoxFunc::EcdsaSecp256r1, - BlackBoxFuncCall::FixedBaseScalarMul { .. } => BlackBoxFunc::FixedBaseScalarMul, + BlackBoxFuncCall::MultiScalarMul { .. } => BlackBoxFunc::MultiScalarMul, BlackBoxFuncCall::EmbeddedCurveAdd { .. } => BlackBoxFunc::EmbeddedCurveAdd, BlackBoxFuncCall::Keccak256 { .. } => BlackBoxFunc::Keccak256, - BlackBoxFuncCall::Keccak256VariableLength { .. } => BlackBoxFunc::Keccak256, BlackBoxFuncCall::Keccakf1600 { .. } => BlackBoxFunc::Keccakf1600, BlackBoxFuncCall::RecursiveAggregation { .. } => BlackBoxFunc::RecursiveAggregation, BlackBoxFuncCall::BigIntAdd { .. } => BlackBoxFunc::BigIntAdd, @@ -209,16 +215,20 @@ impl BlackBoxFuncCall { pub fn get_inputs_vec(&self) -> Vec { match self { - BlackBoxFuncCall::SHA256 { inputs, .. } + BlackBoxFuncCall::AES128Encrypt { inputs, .. } + | BlackBoxFuncCall::SHA256 { inputs, .. } | BlackBoxFuncCall::Blake2s { inputs, .. } | BlackBoxFuncCall::Blake3 { inputs, .. } - | BlackBoxFuncCall::Keccak256 { inputs, .. } - | BlackBoxFuncCall::Keccakf1600 { inputs, .. } | BlackBoxFuncCall::PedersenCommitment { inputs, .. } | BlackBoxFuncCall::PedersenHash { inputs, .. } | BlackBoxFuncCall::BigIntFromLeBytes { inputs, .. } - | BlackBoxFuncCall::Poseidon2Permutation { inputs, .. } - | BlackBoxFuncCall::Sha256Compression { inputs, .. } => inputs.to_vec(), + | BlackBoxFuncCall::Poseidon2Permutation { inputs, .. } => inputs.to_vec(), + + BlackBoxFuncCall::Keccakf1600 { inputs, .. } => inputs.to_vec(), + + BlackBoxFuncCall::Sha256Compression { inputs, hash_values, .. } => { + inputs.iter().chain(hash_values.as_ref()).copied().collect() + } BlackBoxFuncCall::AND { lhs, rhs, .. } | BlackBoxFuncCall::XOR { lhs, rhs, .. } => { vec![*lhs, *rhs] } @@ -227,10 +237,15 @@ impl BlackBoxFuncCall { | BlackBoxFuncCall::BigIntMul { .. } | BlackBoxFuncCall::BigIntDiv { .. } | BlackBoxFuncCall::BigIntToLeBytes { .. } => Vec::new(), - BlackBoxFuncCall::FixedBaseScalarMul { low, high, .. } => vec![*low, *high], - BlackBoxFuncCall::EmbeddedCurveAdd { - input1_x, input1_y, input2_x, input2_y, .. - } => vec![*input1_x, *input1_y, *input2_x, *input2_y], + BlackBoxFuncCall::MultiScalarMul { points, scalars, .. } => { + let mut inputs: Vec = Vec::with_capacity(points.len() * 2); + inputs.extend(points.iter().copied()); + inputs.extend(scalars.iter().copied()); + inputs + } + BlackBoxFuncCall::EmbeddedCurveAdd { input1, input2, .. } => { + vec![input1[0], input1[1], input2[0], input2[1]] + } BlackBoxFuncCall::RANGE { input } => vec![*input], BlackBoxFuncCall::SchnorrVerify { public_key_x, @@ -239,7 +254,8 @@ impl BlackBoxFuncCall { message, .. } => { - let mut inputs = Vec::with_capacity(2 + signature.len() + message.len()); + let mut inputs: Vec = + Vec::with_capacity(2 + signature.len() + message.len()); inputs.push(*public_key_x); inputs.push(*public_key_y); inputs.extend(signature.iter().copied()); @@ -284,7 +300,7 @@ impl BlackBoxFuncCall { inputs.extend(hashed_message.iter().copied()); inputs } - BlackBoxFuncCall::Keccak256VariableLength { inputs, var_message_size, .. } => { + BlackBoxFuncCall::Keccak256 { inputs, var_message_size, .. } => { let mut inputs = inputs.clone(); inputs.push(*var_message_size); inputs @@ -310,20 +326,26 @@ impl BlackBoxFuncCall { BlackBoxFuncCall::SHA256 { outputs, .. } | BlackBoxFuncCall::Blake2s { outputs, .. } | BlackBoxFuncCall::Blake3 { outputs, .. } - | BlackBoxFuncCall::Keccak256 { outputs, .. } - | BlackBoxFuncCall::Keccakf1600 { outputs, .. } - | BlackBoxFuncCall::Keccak256VariableLength { outputs, .. } - | BlackBoxFuncCall::Poseidon2Permutation { outputs, .. } - | BlackBoxFuncCall::Sha256Compression { outputs, .. } => outputs.to_vec(), + | BlackBoxFuncCall::Keccak256 { outputs, .. } => outputs.to_vec(), + + BlackBoxFuncCall::Keccakf1600 { outputs, .. } => outputs.to_vec(), + + BlackBoxFuncCall::Sha256Compression { outputs, .. } => outputs.to_vec(), + + BlackBoxFuncCall::AES128Encrypt { outputs, .. } + | BlackBoxFuncCall::Poseidon2Permutation { outputs, .. } => outputs.to_vec(), + BlackBoxFuncCall::AND { output, .. } | BlackBoxFuncCall::XOR { output, .. } | BlackBoxFuncCall::SchnorrVerify { output, .. } | BlackBoxFuncCall::EcdsaSecp256k1 { output, .. } | BlackBoxFuncCall::PedersenHash { output, .. } | BlackBoxFuncCall::EcdsaSecp256r1 { output, .. } => vec![*output], - BlackBoxFuncCall::FixedBaseScalarMul { outputs, .. } - | BlackBoxFuncCall::PedersenCommitment { outputs, .. } - | BlackBoxFuncCall::EmbeddedCurveAdd { outputs, .. } => vec![outputs.0, outputs.1], + BlackBoxFuncCall::PedersenCommitment { outputs, .. } => vec![outputs.0, outputs.1], + BlackBoxFuncCall::MultiScalarMul { outputs, .. } + | BlackBoxFuncCall::EmbeddedCurveAdd { outputs, .. } => { + vec![outputs.0, outputs.1, outputs.2] + } BlackBoxFuncCall::RANGE { .. } | BlackBoxFuncCall::RecursiveAggregation { .. } | BlackBoxFuncCall::BigIntFromLeBytes { .. } @@ -433,3 +455,78 @@ impl std::fmt::Debug for BlackBoxFuncCall { std::fmt::Display::fmt(self, f) } } + +fn serialize_big_array(big_array: &[FunctionInput; 64], s: S) -> Result +where + S: Serializer, +{ + use serde_big_array::BigArray; + + (*big_array).serialize(s) +} + +fn deserialize_big_array_into_box<'de, D>( + deserializer: D, +) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + use serde_big_array::BigArray; + + let big_array: [FunctionInput; 64] = BigArray::deserialize(deserializer)?; + Ok(Box::new(big_array)) +} + +#[cfg(test)] +mod tests { + + use crate::{circuit::Opcode, native_types::Witness}; + use acir_field::{AcirField, FieldElement}; + + use super::{BlackBoxFuncCall, FunctionInput}; + + fn keccakf1600_opcode() -> Opcode { + let inputs: Box<[FunctionInput; 25]> = Box::new(std::array::from_fn(|i| FunctionInput { + witness: Witness(i as u32 + 1), + num_bits: 8, + })); + let outputs: Box<[Witness; 25]> = Box::new(std::array::from_fn(|i| Witness(i as u32 + 26))); + + Opcode::BlackBoxFuncCall(BlackBoxFuncCall::Keccakf1600 { inputs, outputs }) + } + fn schnorr_verify_opcode() -> Opcode { + let public_key_x = + FunctionInput { witness: Witness(1), num_bits: FieldElement::max_num_bits() }; + let public_key_y = + FunctionInput { witness: Witness(2), num_bits: FieldElement::max_num_bits() }; + let signature: Box<[FunctionInput; 64]> = Box::new(std::array::from_fn(|i| { + FunctionInput { witness: Witness(i as u32 + 3), num_bits: 8 } + })); + let message: Vec = vec![FunctionInput { witness: Witness(67), num_bits: 8 }]; + let output = Witness(68); + + Opcode::BlackBoxFuncCall(BlackBoxFuncCall::SchnorrVerify { + public_key_x, + public_key_y, + signature, + message, + output, + }) + } + + #[test] + fn keccakf1600_serialization_roundtrip() { + let opcode = keccakf1600_opcode::(); + let buf = bincode::serialize(&opcode).unwrap(); + let recovered_opcode = bincode::deserialize(&buf).unwrap(); + assert_eq!(opcode, recovered_opcode); + } + + #[test] + fn schnorr_serialization_roundtrip() { + let opcode = schnorr_verify_opcode::(); + let buf = bincode::serialize(&opcode).unwrap(); + let recovered_opcode = bincode::deserialize(&buf).unwrap(); + assert_eq!(opcode, recovered_opcode); + } +} diff --git a/acvm-repo/acir/src/circuit/opcodes/memory_operation.rs b/acvm-repo/acir/src/circuit/opcodes/memory_operation.rs index 0e94c0f051e..90e3ee0563a 100644 --- a/acvm-repo/acir/src/circuit/opcodes/memory_operation.rs +++ b/acvm-repo/acir/src/circuit/opcodes/memory_operation.rs @@ -1,4 +1,5 @@ use crate::native_types::{Expression, Witness}; +use acir_field::AcirField; use serde::{Deserialize, Serialize}; #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Hash, Copy, Default)] @@ -7,22 +8,25 @@ pub struct BlockId(pub u32); /// Operation on a block of memory /// We can either write or read at an index in memory #[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] -pub struct MemOp { - /// Can be 0 (read) or 1 (write) - pub operation: Expression, - pub index: Expression, - pub value: Expression, +pub struct MemOp { + /// A constant expression that can be 0 (read) or 1 (write) + pub operation: Expression, + /// array index, it must be less than the array length + pub index: Expression, + /// the value we are reading, when operation is 0, or the value we write at + /// the specified index, when operation is 1 + pub value: Expression, } -impl MemOp { +impl MemOp { /// Creates a `MemOp` which reads from memory at `index` and inserts the read value /// into the [`WitnessMap`][crate::native_types::WitnessMap] at `witness` - pub fn read_at_mem_index(index: Expression, witness: Witness) -> Self { + pub fn read_at_mem_index(index: Expression, witness: Witness) -> Self { MemOp { operation: Expression::zero(), index, value: witness.into() } } /// Creates a `MemOp` which writes the [`Expression`] `value` into memory at `index`. - pub fn write_to_mem_index(index: Expression, value: Expression) -> Self { + pub fn write_to_mem_index(index: Expression, value: Expression) -> Self { MemOp { operation: Expression::one(), index, value } } } diff --git a/acvm-repo/acir/src/lib.rs b/acvm-repo/acir/src/lib.rs index c7be5026850..f064cfaca0e 100644 --- a/acvm-repo/acir/src/lib.rs +++ b/acvm-repo/acir/src/lib.rs @@ -9,7 +9,7 @@ pub mod circuit; pub mod native_types; pub use acir_field; -pub use acir_field::FieldElement; +pub use acir_field::{AcirField, FieldElement}; pub use brillig; pub use circuit::black_box_functions::BlackBoxFunc; @@ -31,6 +31,7 @@ mod reflection { path::{Path, PathBuf}, }; + use acir_field::FieldElement; use brillig::{ BinaryFieldOp, BinaryIntOp, BlackBoxOp, HeapValueType, Opcode as BrilligOpcode, ValueOrArray, @@ -41,10 +42,11 @@ mod reflection { circuit::{ brillig::{BrilligInputs, BrilligOutputs}, directives::Directive, - opcodes::BlackBoxFuncCall, - Circuit, ExpressionWidth, Opcode, OpcodeLocation, + opcodes::{BlackBoxFuncCall, BlockType}, + AssertionPayload, Circuit, ExpressionOrMemory, ExpressionWidth, Opcode, OpcodeLocation, + Program, }, - native_types::{Witness, WitnessMap}, + native_types::{Witness, WitnessMap, WitnessStack}, }; #[test] @@ -59,26 +61,30 @@ mod reflection { }; let mut tracer = Tracer::new(TracerConfig::default()); - tracer.trace_simple_type::().unwrap(); + tracer.trace_simple_type::().unwrap(); + tracer.trace_simple_type::>().unwrap(); + tracer.trace_simple_type::>().unwrap(); tracer.trace_simple_type::().unwrap(); - tracer.trace_simple_type::().unwrap(); + tracer.trace_simple_type::>().unwrap(); tracer.trace_simple_type::().unwrap(); tracer.trace_simple_type::().unwrap(); tracer.trace_simple_type::().unwrap(); - tracer.trace_simple_type::().unwrap(); + tracer.trace_simple_type::>().unwrap(); tracer.trace_simple_type::().unwrap(); - tracer.trace_simple_type::().unwrap(); + tracer.trace_simple_type::>().unwrap(); tracer.trace_simple_type::().unwrap(); tracer.trace_simple_type::().unwrap(); - tracer.trace_simple_type::().unwrap(); + tracer.trace_simple_type::>().unwrap(); tracer.trace_simple_type::().unwrap(); tracer.trace_simple_type::().unwrap(); + tracer.trace_simple_type::>().unwrap(); + tracer.trace_simple_type::>().unwrap(); let registry = tracer.registry().unwrap(); // Create C++ class definitions. let mut source = Vec::new(); - let config = serde_generate::CodeGeneratorConfig::new("Circuit".to_string()) + let config = serde_generate::CodeGeneratorConfig::new("Program".to_string()) .with_encodings(vec![serde_generate::Encoding::Bincode]); let generator = serde_generate::cpp::CodeGenerator::new(&config); generator.output(&mut source, ®istry).unwrap(); @@ -105,13 +111,14 @@ mod reflection { let mut tracer = Tracer::new(TracerConfig::default()); tracer.trace_simple_type::().unwrap(); - tracer.trace_simple_type::().unwrap(); + tracer.trace_simple_type::>().unwrap(); + tracer.trace_simple_type::>().unwrap(); let registry = tracer.registry().unwrap(); // Create C++ class definitions. let mut source = Vec::new(); - let config = serde_generate::CodeGeneratorConfig::new("WitnessMap".to_string()) + let config = serde_generate::CodeGeneratorConfig::new("WitnessStack".to_string()) .with_encodings(vec![serde_generate::Encoding::Bincode]); let generator = serde_generate::cpp::CodeGenerator::new(&config); generator.output(&mut source, ®istry).unwrap(); diff --git a/acvm-repo/acir/src/native_types/expression/mod.rs b/acvm-repo/acir/src/native_types/expression/mod.rs index 402aa3eb3a6..1feda5703c8 100644 --- a/acvm-repo/acir/src/native_types/expression/mod.rs +++ b/acvm-repo/acir/src/native_types/expression/mod.rs @@ -1,8 +1,7 @@ use crate::native_types::Witness; -use acir_field::FieldElement; +use acir_field::AcirField; use serde::{Deserialize, Serialize}; use std::cmp::Ordering; - mod operators; mod ordering; @@ -14,30 +13,26 @@ mod ordering; // In the multiplication polynomial // XXX: If we allow the degree of the quotient polynomial to be arbitrary, then we will need a vector of wire values #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Hash)] -pub struct Expression { +pub struct Expression { // To avoid having to create intermediate variables pre-optimization // We collect all of the multiplication terms in the assert-zero opcode // A multiplication term if of the form q_M * wL * wR // Hence this vector represents the following sum: q_M1 * wL1 * wR1 + q_M2 * wL2 * wR2 + .. + - pub mul_terms: Vec<(FieldElement, Witness, Witness)>, + pub mul_terms: Vec<(F, Witness, Witness)>, - pub linear_combinations: Vec<(FieldElement, Witness)>, + pub linear_combinations: Vec<(F, Witness)>, // TODO: rename q_c to `constant` moreover q_X is not clear to those who // TODO are not familiar with PLONK - pub q_c: FieldElement, + pub q_c: F, } -impl Default for Expression { - fn default() -> Expression { - Expression { - mul_terms: Vec::new(), - linear_combinations: Vec::new(), - q_c: FieldElement::zero(), - } +impl Default for Expression { + fn default() -> Self { + Expression { mul_terms: Vec::new(), linear_combinations: Vec::new(), q_c: F::zero() } } } -impl std::fmt::Display for Expression { +impl std::fmt::Display for Expression { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { if let Some(witness) = self.to_witness() { write!(f, "x{}", witness.witness_index()) @@ -47,41 +42,19 @@ impl std::fmt::Display for Expression { } } -impl Expression { - // TODO: possibly remove, and move to noir repo. - pub const fn can_defer_constraint(&self) -> bool { - false - } - +impl Expression { /// Returns the number of multiplication terms pub fn num_mul_terms(&self) -> usize { self.mul_terms.len() } - pub fn from_field(q_c: FieldElement) -> Expression { - Self { q_c, ..Default::default() } - } - - pub fn one() -> Expression { - Self::from_field(FieldElement::one()) - } - - pub fn zero() -> Expression { - Self::default() - } - /// Adds a new linear term to the `Expression`. - pub fn push_addition_term(&mut self, coefficient: FieldElement, variable: Witness) { + pub fn push_addition_term(&mut self, coefficient: F, variable: Witness) { self.linear_combinations.push((coefficient, variable)); } /// Adds a new quadratic term to the `Expression`. - pub fn push_multiplication_term( - &mut self, - coefficient: FieldElement, - lhs: Witness, - rhs: Witness, - ) { + pub fn push_multiplication_term(&mut self, coefficient: F, lhs: Witness, rhs: Witness) { self.mul_terms.push((coefficient, lhs, rhs)); } @@ -95,6 +68,19 @@ impl Expression { self.mul_terms.is_empty() && self.linear_combinations.is_empty() } + /// Returns a `FieldElement` if the expression represents a constant polynomial. + /// Otherwise returns `None`. + /// + /// Examples: + /// - f(x,y) = x would return `None` + /// - f(x,y) = x + 6 would return `None` + /// - f(x,y) = 2*y + 6 would return `None` + /// - f(x,y) = x + y would return `None` + /// - f(x,y) = 5 would return `FieldElement(5)` + pub fn to_const(&self) -> Option<&F> { + self.is_const().then_some(&self.q_c) + } + /// Returns `true` if highest degree term in the expression is one or less. /// /// - `mul_term` in an expression contains degree-2 terms @@ -132,21 +118,29 @@ impl Expression { self.is_linear() && self.linear_combinations.len() == 1 } + /// Sorts opcode in a deterministic order + /// XXX: We can probably make this more efficient by sorting on each phase. We only care if it is deterministic + pub fn sort(&mut self) { + self.mul_terms.sort_by(|a, b| a.1.cmp(&b.1).then(a.2.cmp(&b.2))); + self.linear_combinations.sort_by(|a, b| a.1.cmp(&b.1)); + } +} + +impl Expression { + pub fn from_field(q_c: F) -> Self { + Self { q_c, ..Default::default() } + } + + pub fn zero() -> Self { + Self::default() + } + pub fn is_zero(&self) -> bool { *self == Self::zero() } - /// Returns a `FieldElement` if the expression represents a constant polynomial. - /// Otherwise returns `None`. - /// - /// Examples: - /// - f(x,y) = x would return `None` - /// - f(x,y) = x + 6 would return `None` - /// - f(x,y) = 2*y + 6 would return `None` - /// - f(x,y) = x + y would return `None` - /// - f(x,y) = 5 would return `FieldElement(5)` - pub fn to_const(&self) -> Option { - self.is_const().then_some(self.q_c) + pub fn one() -> Self { + Self::from_field(F::one()) } /// Returns a `Witness` if the `Expression` can be represented as a degree-1 @@ -171,87 +165,20 @@ impl Expression { None } - /// Sorts opcode in a deterministic order - /// XXX: We can probably make this more efficient by sorting on each phase. We only care if it is deterministic - pub fn sort(&mut self) { - self.mul_terms.sort_by(|a, b| a.1.cmp(&b.1).then(a.2.cmp(&b.2))); - self.linear_combinations.sort_by(|a, b| a.1.cmp(&b.1)); - } - - /// Checks if this expression can fit into one arithmetic identity - /// TODO: This needs to be reworded, arithmetic identity only makes sense in the context - /// TODO of PLONK, whereas we want expressions to be generic. - /// TODO: We just need to reword it to say exactly what its doing and - /// TODO then reference the fact that this is what plonk will accept. - /// TODO alternatively, we can define arithmetic identity in the context of expressions - /// TODO and then reference that. - pub fn fits_in_one_identity(&self, width: usize) -> bool { - // A Polynomial with more than one mul term cannot fit into one opcode - if self.mul_terms.len() > 1 { - return false; - }; - // A Polynomial with more terms than fan-in cannot fit within a single opcode - if self.linear_combinations.len() > width { - return false; - } - - // A polynomial with no mul term and a fan-in that fits inside of the width can fit into a single opcode - if self.mul_terms.is_empty() { - return true; - } - - // A polynomial with width-2 fan-in terms and a single non-zero mul term can fit into one opcode - // Example: Axy + Dz . Notice, that the mul term places a constraint on the first two terms, but not the last term - // XXX: This would change if our arithmetic polynomial equation was changed to Axyz for example, but for now it is not. - if self.linear_combinations.len() <= (width - 2) { - return true; - } - - // We now know that we have a single mul term. We also know that the mul term must match up with two other terms - // A polynomial whose mul terms are non zero which do not match up with two terms in the fan-in cannot fit into one opcode - // An example of this is: Axy + Bx + Cy + ... - // Notice how the bivariate monomial xy has two univariate monomials with their respective coefficients - // XXX: note that if x or y is zero, then we could apply a further optimization, but this would be done in another algorithm. - // It would be the same as when we have zero coefficients - Can only work if wire is constrained to be zero publicly - let mul_term = &self.mul_terms[0]; - - // The coefficient should be non-zero, as this method is ran after the compiler removes all zero coefficient terms - assert_ne!(mul_term.0, FieldElement::zero()); - - let mut found_x = false; - let mut found_y = false; - - for term in self.linear_combinations.iter() { - let witness = &term.1; - let x = &mul_term.1; - let y = &mul_term.2; - if witness == x { - found_x = true; - }; - if witness == y { - found_y = true; - }; - if found_x & found_y { - break; - } - } - - found_x & found_y - } - /// Returns `self + k*b` - pub fn add_mul(&self, k: FieldElement, b: &Expression) -> Expression { + pub fn add_mul(&self, k: F, b: &Self) -> Self { if k.is_zero() { return self.clone(); } else if self.is_const() { - return self.q_c + (k * b); + let kb = b * k; + return kb + self.q_c; } else if b.is_const() { return self.clone() + (k * b.q_c); } - let mut mul_terms: Vec<(FieldElement, Witness, Witness)> = + let mut mul_terms: Vec<(F, Witness, Witness)> = Vec::with_capacity(self.mul_terms.len() + b.mul_terms.len()); - let mut linear_combinations: Vec<(FieldElement, Witness)> = + let mut linear_combinations: Vec<(F, Witness)> = Vec::with_capacity(self.linear_combinations.len() + b.linear_combinations.len()); let q_c = self.q_c + k * b.q_c; @@ -338,7 +265,7 @@ impl Expression { while i2 < b.mul_terms.len() { let (b_c, b_wl, b_wr) = b.mul_terms[i2]; let coeff = b_c * k; - if coeff != FieldElement::zero() { + if coeff != F::zero() { mul_terms.push((coeff, b_wl, b_wr)); } i2 += 1; @@ -348,57 +275,63 @@ impl Expression { } } -impl From for Expression { - fn from(constant: FieldElement) -> Expression { +impl From for Expression { + fn from(constant: F) -> Self { Expression { q_c: constant, linear_combinations: Vec::new(), mul_terms: Vec::new() } } } -impl From for Expression { +impl From for Expression { /// Creates an Expression from a Witness. /// /// This is infallible since an `Expression` is /// a multi-variate polynomial and a `Witness` /// can be seen as a univariate polynomial - fn from(wit: Witness) -> Expression { + fn from(wit: Witness) -> Self { Expression { - q_c: FieldElement::zero(), - linear_combinations: vec![(FieldElement::one(), wit)], + q_c: F::zero(), + linear_combinations: vec![(F::one(), wit)], mul_terms: Vec::new(), } } } -#[test] -fn add_mul_smoketest() { - let a = Expression { - mul_terms: vec![(FieldElement::from(2u128), Witness(1), Witness(2))], - ..Default::default() - }; - - let k = FieldElement::from(10u128); - - let b = Expression { - mul_terms: vec![ - (FieldElement::from(3u128), Witness(0), Witness(2)), - (FieldElement::from(3u128), Witness(1), Witness(2)), - (FieldElement::from(4u128), Witness(4), Witness(5)), - ], - linear_combinations: vec![(FieldElement::from(4u128), Witness(4))], - q_c: FieldElement::one(), - }; - - let result = a.add_mul(k, &b); - assert_eq!( - result, - Expression { +#[cfg(test)] +mod tests { + use super::*; + use acir_field::{AcirField, FieldElement}; + + #[test] + fn add_mul_smoketest() { + let a = Expression { + mul_terms: vec![(FieldElement::from(2u128), Witness(1), Witness(2))], + ..Default::default() + }; + + let k = FieldElement::from(10u128); + + let b = Expression { mul_terms: vec![ - (FieldElement::from(30u128), Witness(0), Witness(2)), - (FieldElement::from(32u128), Witness(1), Witness(2)), - (FieldElement::from(40u128), Witness(4), Witness(5)), + (FieldElement::from(3u128), Witness(0), Witness(2)), + (FieldElement::from(3u128), Witness(1), Witness(2)), + (FieldElement::from(4u128), Witness(4), Witness(5)), ], - linear_combinations: vec![(FieldElement::from(40u128), Witness(4))], - q_c: FieldElement::from(10u128) - } - ); + linear_combinations: vec![(FieldElement::from(4u128), Witness(4))], + q_c: FieldElement::one(), + }; + + let result = a.add_mul(k, &b); + assert_eq!( + result, + Expression { + mul_terms: vec![ + (FieldElement::from(30u128), Witness(0), Witness(2)), + (FieldElement::from(32u128), Witness(1), Witness(2)), + (FieldElement::from(40u128), Witness(4), Witness(5)), + ], + linear_combinations: vec![(FieldElement::from(40u128), Witness(4))], + q_c: FieldElement::from(10u128) + } + ); + } } diff --git a/acvm-repo/acir/src/native_types/expression/operators.rs b/acvm-repo/acir/src/native_types/expression/operators.rs index 29cdc6967bb..a8f5dc8e7ad 100644 --- a/acvm-repo/acir/src/native_types/expression/operators.rs +++ b/acvm-repo/acir/src/native_types/expression/operators.rs @@ -1,5 +1,5 @@ use crate::native_types::Witness; -use acir_field::FieldElement; +use acir_field::AcirField; use std::{ cmp::Ordering, ops::{Add, Mul, Neg, Sub}, @@ -9,8 +9,8 @@ use super::Expression; // Negation -impl Neg for &Expression { - type Output = Expression; +impl Neg for &Expression { + type Output = Expression; fn neg(self) -> Self::Output { // XXX(med) : Implement an efficient way to do this @@ -27,9 +27,9 @@ impl Neg for &Expression { // FieldElement -impl Add for Expression { - type Output = Expression; - fn add(self, rhs: FieldElement) -> Self::Output { +impl Add for Expression { + type Output = Self; + fn add(self, rhs: F) -> Self::Output { // Increase the constant let q_c = self.q_c + rhs; @@ -37,17 +37,9 @@ impl Add for Expression { } } -impl Add for FieldElement { - type Output = Expression; - #[inline] - fn add(self, rhs: Expression) -> Self::Output { - rhs + self - } -} - -impl Sub for Expression { - type Output = Expression; - fn sub(self, rhs: FieldElement) -> Self::Output { +impl Sub for Expression { + type Output = Self; + fn sub(self, rhs: F) -> Self::Output { // Increase the constant let q_c = self.q_c - rhs; @@ -55,17 +47,9 @@ impl Sub for Expression { } } -impl Sub for FieldElement { - type Output = Expression; - #[inline] - fn sub(self, rhs: Expression) -> Self::Output { - rhs - self - } -} - -impl Mul for &Expression { - type Output = Expression; - fn mul(self, rhs: FieldElement) -> Self::Output { +impl Mul for &Expression { + type Output = Expression; + fn mul(self, rhs: F) -> Self::Output { // Scale the mul terms let mul_terms: Vec<_> = self.mul_terms.iter().map(|(q_m, w_l, w_r)| (*q_m * rhs, *w_l, *w_r)).collect(); @@ -81,42 +65,34 @@ impl Mul for &Expression { } } -impl Mul<&Expression> for FieldElement { - type Output = Expression; - #[inline] - fn mul(self, rhs: &Expression) -> Self::Output { - rhs * self - } -} - // Witness -impl Add for &Expression { - type Output = Expression; - fn add(self, rhs: Witness) -> Expression { +impl Add for &Expression { + type Output = Expression; + fn add(self, rhs: Witness) -> Self::Output { self + &Expression::from(rhs) } } -impl Add<&Expression> for Witness { - type Output = Expression; +impl Add<&Expression> for Witness { + type Output = Expression; #[inline] - fn add(self, rhs: &Expression) -> Expression { + fn add(self, rhs: &Expression) -> Self::Output { rhs + self } } -impl Sub for &Expression { - type Output = Expression; - fn sub(self, rhs: Witness) -> Expression { +impl Sub for &Expression { + type Output = Expression; + fn sub(self, rhs: Witness) -> Self::Output { self - &Expression::from(rhs) } } -impl Sub<&Expression> for Witness { - type Output = Expression; +impl Sub<&Expression> for Witness { + type Output = Expression; #[inline] - fn sub(self, rhs: &Expression) -> Expression { + fn sub(self, rhs: &Expression) -> Self::Output { rhs - self } } @@ -125,25 +101,25 @@ impl Sub<&Expression> for Witness { // Expression -impl Add<&Expression> for &Expression { - type Output = Expression; - fn add(self, rhs: &Expression) -> Expression { - self.add_mul(FieldElement::one(), rhs) +impl Add<&Expression> for &Expression { + type Output = Expression; + fn add(self, rhs: &Expression) -> Self::Output { + self.add_mul(F::one(), rhs) } } -impl Sub<&Expression> for &Expression { - type Output = Expression; - fn sub(self, rhs: &Expression) -> Expression { - self.add_mul(-FieldElement::one(), rhs) +impl Sub<&Expression> for &Expression { + type Output = Expression; + fn sub(self, rhs: &Expression) -> Self::Output { + self.add_mul(-F::one(), rhs) } } -impl Mul<&Expression> for &Expression { - type Output = Option; - fn mul(self, rhs: &Expression) -> Option { +impl Mul<&Expression> for &Expression { + type Output = Option>; + fn mul(self, rhs: &Expression) -> Self::Output { if self.is_const() { - return Some(self.q_c * rhs); + return Some(rhs * self.q_c); } else if rhs.is_const() { return Some(self * rhs.q_c); } else if !(self.is_linear() && rhs.is_linear()) { @@ -215,7 +191,7 @@ impl Mul<&Expression> for &Expression { } /// Returns `w*b.linear_combinations` -fn single_mul(w: Witness, b: &Expression) -> Expression { +fn single_mul(w: Witness, b: &Expression) -> Expression { Expression { mul_terms: b .linear_combinations @@ -229,62 +205,68 @@ fn single_mul(w: Witness, b: &Expression) -> Expression { } } -#[test] -fn add_smoke_test() { - let a = Expression { - mul_terms: vec![], - linear_combinations: vec![(FieldElement::from(2u128), Witness(2))], - q_c: FieldElement::from(2u128), - }; - - let b = Expression { - mul_terms: vec![], - linear_combinations: vec![(FieldElement::from(4u128), Witness(4))], - q_c: FieldElement::one(), - }; - - assert_eq!( - &a + &b, - Expression { +#[cfg(test)] +mod tests { + use super::*; + use acir_field::{AcirField, FieldElement}; + + #[test] + fn add_smoke_test() { + let a = Expression { mul_terms: vec![], - linear_combinations: vec![ - (FieldElement::from(2u128), Witness(2)), - (FieldElement::from(4u128), Witness(4)) - ], - q_c: FieldElement::from(3u128) - } - ); + linear_combinations: vec![(FieldElement::from(2u128), Witness(2))], + q_c: FieldElement::from(2u128), + }; - // Enforce commutativity - assert_eq!(&a + &b, &b + &a); -} + let b = Expression { + mul_terms: vec![], + linear_combinations: vec![(FieldElement::from(4u128), Witness(4))], + q_c: FieldElement::one(), + }; + + assert_eq!( + &a + &b, + Expression { + mul_terms: vec![], + linear_combinations: vec![ + (FieldElement::from(2u128), Witness(2)), + (FieldElement::from(4u128), Witness(4)) + ], + q_c: FieldElement::from(3u128) + } + ); -#[test] -fn mul_smoke_test() { - let a = Expression { - mul_terms: vec![], - linear_combinations: vec![(FieldElement::from(2u128), Witness(2))], - q_c: FieldElement::from(2u128), - }; - - let b = Expression { - mul_terms: vec![], - linear_combinations: vec![(FieldElement::from(4u128), Witness(4))], - q_c: FieldElement::one(), - }; - - assert_eq!( - (&a * &b).unwrap(), - Expression { - mul_terms: vec![(FieldElement::from(8u128), Witness(2), Witness(4)),], - linear_combinations: vec![ - (FieldElement::from(2u128), Witness(2)), - (FieldElement::from(8u128), Witness(4)) - ], - q_c: FieldElement::from(2u128) - } - ); + // Enforce commutativity + assert_eq!(&a + &b, &b + &a); + } - // Enforce commutativity - assert_eq!(&a * &b, &b * &a); + #[test] + fn mul_smoke_test() { + let a = Expression { + mul_terms: vec![], + linear_combinations: vec![(FieldElement::from(2u128), Witness(2))], + q_c: FieldElement::from(2u128), + }; + + let b = Expression { + mul_terms: vec![], + linear_combinations: vec![(FieldElement::from(4u128), Witness(4))], + q_c: FieldElement::one(), + }; + + assert_eq!( + (&a * &b).unwrap(), + Expression { + mul_terms: vec![(FieldElement::from(8u128), Witness(2), Witness(4)),], + linear_combinations: vec![ + (FieldElement::from(2u128), Witness(2)), + (FieldElement::from(8u128), Witness(4)) + ], + q_c: FieldElement::from(2u128) + } + ); + + // Enforce commutativity + assert_eq!(&a * &b, &b * &a); + } } diff --git a/acvm-repo/acir/src/native_types/expression/ordering.rs b/acvm-repo/acir/src/native_types/expression/ordering.rs index e24a25ec3af..f1d217b3bd9 100644 --- a/acvm-repo/acir/src/native_types/expression/ordering.rs +++ b/acvm-repo/acir/src/native_types/expression/ordering.rs @@ -6,7 +6,7 @@ use super::Expression; // TODO: It's undecided whether `Expression` should implement `Ord/PartialOrd`. // This is currently used in ACVM in the compiler. -impl Ord for Expression { +impl Ord for Expression { fn cmp(&self, other: &Self) -> Ordering { let mut i1 = self.get_max_idx(); let mut i2 = other.get_max_idx(); @@ -17,13 +17,13 @@ impl Ord for Expression { if m1.is_none() && m2.is_none() { return Ordering::Equal; } - result = Expression::cmp_max(m1, m2); + result = Expression::::cmp_max(m1, m2); } result } } -impl PartialOrd for Expression { +impl PartialOrd for Expression { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } @@ -35,7 +35,7 @@ struct WitnessIdx { second_term: bool, } -impl Expression { +impl Expression { fn get_max_idx(&self) -> WitnessIdx { WitnessIdx { linear: self.linear_combinations.len(), diff --git a/acvm-repo/acir/src/native_types/mod.rs b/acvm-repo/acir/src/native_types/mod.rs index 66c822bfff8..eb9d1f6fd03 100644 --- a/acvm-repo/acir/src/native_types/mod.rs +++ b/acvm-repo/acir/src/native_types/mod.rs @@ -1,8 +1,10 @@ mod expression; mod witness; mod witness_map; +mod witness_stack; pub use expression::Expression; pub use witness::Witness; pub use witness_map::WitnessMap; -pub use witness_map::WitnessMapError; +pub use witness_stack::WitnessStack; +pub use witness_stack::WitnessStackError; diff --git a/acvm-repo/acir/src/native_types/witness.rs b/acvm-repo/acir/src/native_types/witness.rs index 740d10d2951..a570968f948 100644 --- a/acvm-repo/acir/src/native_types/witness.rs +++ b/acvm-repo/acir/src/native_types/witness.rs @@ -1,10 +1,5 @@ -use std::ops::Add; - -use acir_field::FieldElement; use serde::{Deserialize, Serialize}; -use super::Expression; - // Witness might be a misnomer. This is an index that represents the position a witness will take #[derive( Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Default, Serialize, Deserialize, @@ -22,10 +17,6 @@ impl Witness { // This is safe as long as the architecture is 32bits minimum self.0 as usize } - - pub const fn can_defer_constraint(&self) -> bool { - true - } } impl From for Witness { @@ -33,11 +24,3 @@ impl From for Witness { Self(value) } } - -impl Add for Witness { - type Output = Expression; - - fn add(self, rhs: Witness) -> Self::Output { - Expression::from(self).add_mul(FieldElement::one(), &Expression::from(rhs)) - } -} diff --git a/acvm-repo/acir/src/native_types/witness_map.rs b/acvm-repo/acir/src/native_types/witness_map.rs index 00245d5842c..e508fe5b186 100644 --- a/acvm-repo/acir/src/native_types/witness_map.rs +++ b/acvm-repo/acir/src/native_types/witness_map.rs @@ -4,7 +4,6 @@ use std::{ ops::Index, }; -use acir_field::FieldElement; use flate2::bufread::GzDecoder; use flate2::bufread::GzEncoder; use flate2::Compression; @@ -25,63 +24,63 @@ pub struct WitnessMapError(#[from] SerializationError); /// A map from the witnesses in a constraint system to the field element values #[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Default, Serialize, Deserialize)] -pub struct WitnessMap(BTreeMap); +pub struct WitnessMap(BTreeMap); -impl WitnessMap { +impl WitnessMap { pub fn new() -> Self { Self(BTreeMap::new()) } - pub fn get(&self, witness: &Witness) -> Option<&FieldElement> { + pub fn get(&self, witness: &Witness) -> Option<&F> { self.0.get(witness) } - pub fn get_index(&self, index: u32) -> Option<&FieldElement> { + pub fn get_index(&self, index: u32) -> Option<&F> { self.0.get(&index.into()) } pub fn contains_key(&self, key: &Witness) -> bool { self.0.contains_key(key) } - pub fn insert(&mut self, key: Witness, value: FieldElement) -> Option { + pub fn insert(&mut self, key: Witness, value: F) -> Option { self.0.insert(key, value) } } -impl Index<&Witness> for WitnessMap { - type Output = FieldElement; +impl Index<&Witness> for WitnessMap { + type Output = F; fn index(&self, index: &Witness) -> &Self::Output { &self.0[index] } } -pub struct IntoIter(btree_map::IntoIter); +pub struct IntoIter(btree_map::IntoIter); -impl Iterator for IntoIter { - type Item = (Witness, FieldElement); +impl Iterator for IntoIter { + type Item = (Witness, F); fn next(&mut self) -> Option { self.0.next() } } -impl IntoIterator for WitnessMap { - type Item = (Witness, FieldElement); - type IntoIter = IntoIter; +impl IntoIterator for WitnessMap { + type Item = (Witness, F); + type IntoIter = IntoIter; fn into_iter(self) -> Self::IntoIter { IntoIter(self.0.into_iter()) } } -impl From> for WitnessMap { - fn from(value: BTreeMap) -> Self { +impl From> for WitnessMap { + fn from(value: BTreeMap) -> Self { Self(value) } } -impl TryFrom for Vec { +impl TryFrom> for Vec { type Error = WitnessMapError; - fn try_from(val: WitnessMap) -> Result { + fn try_from(val: WitnessMap) -> Result { let buf = bincode::serialize(&val).unwrap(); let mut deflater = GzEncoder::new(buf.as_slice(), Compression::best()); let mut buf_c = Vec::new(); @@ -90,7 +89,7 @@ impl TryFrom for Vec { } } -impl TryFrom<&[u8]> for WitnessMap { +impl Deserialize<'a>> TryFrom<&[u8]> for WitnessMap { type Error = WitnessMapError; fn try_from(bytes: &[u8]) -> Result { diff --git a/acvm-repo/acir/src/native_types/witness_stack.rs b/acvm-repo/acir/src/native_types/witness_stack.rs new file mode 100644 index 00000000000..8a4fffa1577 --- /dev/null +++ b/acvm-repo/acir/src/native_types/witness_stack.rs @@ -0,0 +1,82 @@ +use std::io::Read; + +use flate2::bufread::GzDecoder; +use flate2::bufread::GzEncoder; +use flate2::Compression; +use serde::{Deserialize, Serialize}; +use thiserror::Error; + +use super::WitnessMap; + +#[derive(Debug, Error)] +enum SerializationError { + #[error(transparent)] + Deflate(#[from] std::io::Error), +} + +#[derive(Debug, Error)] +#[error(transparent)] +pub struct WitnessStackError(#[from] SerializationError); + +/// An ordered set of witness maps for separate circuits +#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Default, Serialize, Deserialize)] +pub struct WitnessStack { + stack: Vec>, +} + +#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Default, Serialize, Deserialize)] +pub struct StackItem { + /// Index into a [crate::circuit::Program] function list for which we have an associated witness + pub index: u32, + /// A full witness for the respective constraint system specified by the index + pub witness: WitnessMap, +} + +impl WitnessStack { + pub fn push(&mut self, index: u32, witness: WitnessMap) { + self.stack.push(StackItem { index, witness }); + } + + pub fn pop(&mut self) -> Option> { + self.stack.pop() + } + + pub fn peek(&self) -> Option<&StackItem> { + self.stack.last() + } + + pub fn length(&self) -> usize { + self.stack.len() + } +} + +impl From> for WitnessStack { + fn from(witness: WitnessMap) -> Self { + let stack = vec![StackItem { index: 0, witness }]; + Self { stack } + } +} + +impl TryFrom> for Vec { + type Error = WitnessStackError; + + fn try_from(val: WitnessStack) -> Result { + let buf = bincode::serialize(&val).unwrap(); + let mut deflater = GzEncoder::new(buf.as_slice(), Compression::best()); + let mut buf_c = Vec::new(); + deflater.read_to_end(&mut buf_c).map_err(|err| WitnessStackError(err.into()))?; + Ok(buf_c) + } +} + +impl Deserialize<'a>> TryFrom<&[u8]> for WitnessStack { + type Error = WitnessStackError; + + fn try_from(bytes: &[u8]) -> Result { + let mut deflater = GzDecoder::new(bytes); + let mut buf_d = Vec::new(); + deflater.read_to_end(&mut buf_d).map_err(|err| WitnessStackError(err.into()))?; + let witness_stack = bincode::deserialize(&buf_d).unwrap(); + Ok(witness_stack) + } +} diff --git a/acvm-repo/acir/tests/test_program_serialization.rs b/acvm-repo/acir/tests/test_program_serialization.rs index 2c8ad2b9986..dfcb1a8bb86 100644 --- a/acvm-repo/acir/tests/test_program_serialization.rs +++ b/acvm-repo/acir/tests/test_program_serialization.rs @@ -1,25 +1,25 @@ //! This integration test defines a set of circuits which are used in order to test the acvm_js package. //! -//! The acvm_js test suite contains serialized [circuits][`Circuit`] which must be kept in sync with the format +//! The acvm_js test suite contains serialized program [circuits][`Program`] which must be kept in sync with the format //! outputted from the [ACIR crate][acir]. //! Breaking changes to the serialization format then require refreshing acvm_js's test suite. //! This file contains Rust definitions of these circuits and outputs the updated serialized format. //! //! These tests also check this circuit serialization against an expected value, erroring if the serialization changes. //! Generally in this situation we just need to refresh the `expected_serialization` variables to match the -//! actual output, **HOWEVER** note that this results in a breaking change to the ACIR format. +//! actual output, **HOWEVER** note that this results in a breaking change to the backend ACIR format. use std::collections::BTreeSet; use acir::{ circuit::{ - brillig::{Brillig, BrilligInputs, BrilligOutputs}, + brillig::{BrilligBytecode, BrilligInputs, BrilligOutputs}, opcodes::{BlackBoxFuncCall, BlockId, FunctionInput, MemOp}, - Circuit, Opcode, PublicInputs, + Circuit, Opcode, Program, PublicInputs, }, native_types::{Expression, Witness}, }; -use acir_field::FieldElement; +use acir_field::{AcirField, FieldElement}; use brillig::{HeapArray, HeapValueType, MemoryAddress, ValueOrArray}; #[test] @@ -34,50 +34,67 @@ fn addition_circuit() { q_c: FieldElement::zero(), }); - let circuit = Circuit { + let circuit: Circuit = Circuit { current_witness_index: 4, opcodes: vec![addition], private_parameters: BTreeSet::from([Witness(1), Witness(2)]), return_values: PublicInputs([Witness(3)].into()), - ..Circuit::default() + ..Circuit::::default() }; + let program = Program { functions: vec![circuit], unconstrained_functions: vec![] }; - let bytes = Circuit::serialize_circuit(&circuit); + let bytes = Program::serialize_program(&program); let expected_serialization: Vec = vec![ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 208, 49, 14, 192, 32, 8, 5, 80, 212, 30, 8, 4, 20, - 182, 94, 165, 166, 122, 255, 35, 52, 77, 28, 76, 58, 214, 191, 124, 166, 23, 242, 15, 0, 8, - 240, 77, 154, 125, 206, 198, 127, 161, 176, 209, 138, 139, 197, 88, 68, 122, 205, 157, 152, - 46, 204, 222, 76, 81, 180, 21, 35, 35, 53, 189, 179, 49, 119, 19, 171, 222, 188, 162, 147, - 112, 167, 161, 206, 99, 98, 105, 223, 95, 248, 26, 113, 90, 97, 185, 97, 217, 56, 173, 35, - 63, 243, 81, 87, 163, 125, 1, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 144, 65, 14, 128, 32, 12, 4, 65, 124, 80, 75, 91, + 104, 111, 126, 69, 34, 252, 255, 9, 106, 228, 64, 162, 55, 153, 164, 217, 158, 38, 155, + 245, 238, 97, 189, 206, 187, 55, 161, 231, 214, 19, 254, 129, 126, 162, 107, 25, 92, 4, + 137, 185, 230, 88, 145, 112, 135, 104, 69, 5, 88, 74, 82, 84, 20, 149, 35, 42, 81, 85, 214, + 108, 197, 50, 24, 50, 85, 108, 98, 212, 186, 44, 204, 235, 5, 183, 99, 233, 46, 63, 252, + 110, 216, 56, 184, 15, 78, 146, 74, 173, 20, 141, 1, 0, 0, ]; assert_eq!(bytes, expected_serialization) } #[test] -fn fixed_base_scalar_mul_circuit() { - let fixed_base_scalar_mul = Opcode::BlackBoxFuncCall(BlackBoxFuncCall::FixedBaseScalarMul { - low: FunctionInput { witness: Witness(1), num_bits: 128 }, - high: FunctionInput { witness: Witness(2), num_bits: 128 }, - outputs: (Witness(3), Witness(4)), - }); +fn multi_scalar_mul_circuit() { + let multi_scalar_mul: Opcode = + Opcode::BlackBoxFuncCall(BlackBoxFuncCall::MultiScalarMul { + points: vec![ + FunctionInput { witness: Witness(1), num_bits: 128 }, + FunctionInput { witness: Witness(2), num_bits: 128 }, + FunctionInput { witness: Witness(3), num_bits: 1 }, + ], + scalars: vec![ + FunctionInput { witness: Witness(4), num_bits: 128 }, + FunctionInput { witness: Witness(5), num_bits: 128 }, + ], + outputs: (Witness(6), Witness(7), Witness(8)), + }); let circuit = Circuit { - current_witness_index: 5, - opcodes: vec![fixed_base_scalar_mul], - private_parameters: BTreeSet::from([Witness(1), Witness(2)]), - return_values: PublicInputs(BTreeSet::from_iter(vec![Witness(3), Witness(4)])), + current_witness_index: 9, + opcodes: vec![multi_scalar_mul], + private_parameters: BTreeSet::from([ + Witness(1), + Witness(2), + Witness(3), + Witness(4), + Witness(5), + ]), + return_values: PublicInputs(BTreeSet::from_iter(vec![Witness(6), Witness(7), Witness(8)])), ..Circuit::default() }; + let program = Program { functions: vec![circuit], unconstrained_functions: vec![] }; - let bytes = Circuit::serialize_circuit(&circuit); + let bytes = Program::serialize_program(&program); let expected_serialization: Vec = vec![ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 77, 138, 91, 10, 0, 32, 16, 2, 109, 171, 175, 46, 221, - 209, 247, 229, 130, 130, 140, 200, 92, 0, 11, 157, 228, 35, 127, 212, 200, 29, 61, 116, 76, - 220, 217, 250, 171, 91, 113, 160, 66, 104, 242, 97, 0, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 93, 141, 219, 10, 0, 32, 8, 67, 243, 214, 5, 250, 232, + 62, 189, 69, 123, 176, 132, 195, 116, 50, 149, 114, 107, 0, 97, 127, 116, 2, 75, 243, 2, + 74, 53, 122, 202, 189, 211, 15, 106, 5, 13, 116, 238, 35, 221, 81, 230, 61, 249, 37, 253, + 250, 179, 79, 109, 218, 22, 67, 227, 173, 0, 0, 0, ]; assert_eq!(bytes, expected_serialization) @@ -91,22 +108,22 @@ fn pedersen_circuit() { domain_separator: 0, }); - let circuit = Circuit { + let circuit: Circuit = Circuit { current_witness_index: 4, opcodes: vec![pedersen], private_parameters: BTreeSet::from([Witness(1)]), return_values: PublicInputs(BTreeSet::from_iter(vec![Witness(2), Witness(3)])), ..Circuit::default() }; + let program = Program { functions: vec![circuit], unconstrained_functions: vec![] }; - let bytes = Circuit::serialize_circuit(&circuit); + let bytes = Program::serialize_program(&program); let expected_serialization: Vec = vec![ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 93, 74, 135, 9, 0, 48, 8, 75, 171, 224, 255, 15, 139, - 27, 196, 64, 200, 100, 0, 15, 133, 80, 57, 89, 219, 127, 39, 173, 126, 235, 236, 247, 151, - 48, 224, 71, 90, 33, 97, 0, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 93, 74, 73, 10, 0, 0, 4, 180, 29, 252, 255, 193, 66, 40, + 76, 77, 179, 34, 20, 36, 136, 237, 83, 245, 101, 107, 79, 65, 94, 253, 214, 217, 255, 239, + 192, 1, 43, 124, 181, 238, 113, 0, 0, 0, ]; - assert_eq!(bytes, expected_serialization) } @@ -116,8 +133,11 @@ fn schnorr_verify_circuit() { FunctionInput { witness: Witness(1), num_bits: FieldElement::max_num_bits() }; let public_key_y = FunctionInput { witness: Witness(2), num_bits: FieldElement::max_num_bits() }; - let signature = - (3..(3 + 64)).map(|i| FunctionInput { witness: Witness(i), num_bits: 8 }).collect(); + let signature: [FunctionInput; 64] = (3..(3 + 64)) + .map(|i| FunctionInput { witness: Witness(i), num_bits: 8 }) + .collect::>() + .try_into() + .unwrap(); let message = ((3 + 64)..(3 + 64 + 10)) .map(|i| FunctionInput { witness: Witness(i), num_bits: 8 }) .collect(); @@ -127,38 +147,39 @@ fn schnorr_verify_circuit() { let schnorr = Opcode::BlackBoxFuncCall(BlackBoxFuncCall::SchnorrVerify { public_key_x, public_key_y, - signature, + signature: Box::new(signature), message, output, }); - let circuit = Circuit { + let circuit: Circuit = Circuit { current_witness_index: 100, opcodes: vec![schnorr], private_parameters: BTreeSet::from_iter((1..=last_input).map(Witness)), return_values: PublicInputs(BTreeSet::from([output])), ..Circuit::default() }; + let program = Program { functions: vec![circuit], unconstrained_functions: vec![] }; - let bytes = Circuit::serialize_circuit(&circuit); + let bytes = Program::serialize_program(&program); let expected_serialization: Vec = vec![ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 77, 210, 7, 74, 3, 1, 20, 69, 209, 177, 247, 222, 123, - 239, 189, 119, 141, 93, 99, 220, 133, 251, 95, 130, 152, 103, 78, 32, 3, 195, 33, 4, 66, - 248, 239, 254, 20, 69, 209, 84, 212, 158, 216, 206, 223, 234, 219, 204, 146, 239, 91, 170, - 111, 103, 245, 109, 101, 27, 219, 217, 193, 250, 219, 197, 110, 246, 176, 151, 125, 236, - 231, 0, 7, 57, 196, 97, 142, 112, 148, 99, 28, 231, 4, 39, 57, 197, 105, 206, 112, 150, - 115, 156, 231, 2, 23, 185, 196, 101, 174, 112, 149, 107, 92, 231, 6, 55, 185, 197, 109, - 238, 112, 151, 123, 220, 231, 1, 15, 121, 196, 99, 158, 240, 148, 103, 60, 231, 5, 47, 121, - 197, 107, 222, 240, 150, 119, 188, 231, 3, 75, 124, 228, 83, 195, 142, 121, 158, 125, 126, - 225, 43, 223, 248, 206, 15, 126, 178, 204, 47, 86, 248, 237, 119, 43, 76, 127, 105, 47, - 189, 165, 181, 116, 150, 198, 234, 125, 117, 249, 47, 233, 41, 45, 165, 163, 52, 148, 126, - 210, 78, 186, 73, 51, 233, 37, 173, 164, 147, 52, 146, 62, 210, 70, 186, 72, 19, 233, 33, - 45, 164, 131, 52, 144, 253, 23, 139, 218, 238, 217, 60, 123, 103, 235, 236, 156, 141, 179, - 239, 166, 93, 183, 237, 185, 107, 199, 125, 251, 29, 218, 237, 216, 94, 167, 118, 58, 183, - 207, 165, 93, 174, 237, 113, 107, 135, 123, 247, 47, 185, 251, 147, 59, 191, 184, 239, 155, - 187, 126, 184, 103, 217, 29, 235, 55, 171, 223, 173, 104, 184, 231, 255, 243, 7, 236, 52, - 239, 128, 225, 3, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 85, 210, 85, 78, 67, 81, 24, 133, 209, 226, 238, 238, + 238, 238, 238, 165, 148, 82, 102, 193, 252, 135, 64, 232, 78, 87, 147, 114, 147, 147, 5, + 47, 132, 252, 251, 107, 41, 212, 191, 159, 218, 107, 241, 115, 236, 226, 111, 237, 181, + 178, 173, 246, 186, 107, 175, 157, 29, 236, 100, 23, 27, 175, 135, 189, 236, 99, 63, 7, 56, + 200, 33, 14, 115, 132, 163, 28, 227, 56, 39, 56, 201, 41, 78, 115, 134, 179, 156, 227, 60, + 23, 184, 200, 37, 46, 115, 133, 171, 92, 227, 58, 55, 184, 201, 45, 110, 115, 135, 187, + 220, 227, 62, 15, 120, 200, 35, 30, 243, 132, 167, 60, 227, 57, 47, 120, 201, 43, 94, 243, + 134, 183, 188, 227, 61, 31, 248, 200, 39, 62, 243, 133, 175, 77, 59, 230, 123, 243, 123, + 145, 239, 44, 241, 131, 101, 126, 178, 194, 47, 86, 249, 237, 239, 86, 153, 238, 210, 92, + 122, 75, 107, 233, 44, 141, 53, 250, 234, 241, 191, 164, 167, 180, 148, 142, 210, 80, 250, + 73, 59, 233, 38, 205, 164, 151, 180, 146, 78, 210, 72, 250, 72, 27, 233, 34, 77, 164, 135, + 180, 144, 14, 210, 64, 246, 95, 46, 212, 119, 207, 230, 217, 59, 91, 103, 231, 108, 156, + 125, 183, 237, 186, 107, 207, 125, 59, 30, 218, 239, 216, 110, 167, 246, 58, 183, 211, 165, + 125, 174, 237, 114, 107, 143, 123, 59, 60, 186, 255, 179, 187, 191, 186, 115, 209, 125, 75, + 238, 90, 118, 207, 138, 59, 54, 110, 214, 184, 91, 161, 233, 158, 255, 190, 63, 71, 59, 68, + 130, 233, 3, 0, 0, ]; assert_eq!(bytes, expected_serialization) @@ -169,14 +190,7 @@ fn simple_brillig_foreign_call() { let w_input = Witness(1); let w_inverted = Witness(2); - let brillig_data = Brillig { - inputs: vec![ - BrilligInputs::Single(w_input.into()), // Input Register 0, - ], - // This tells the BrilligSolver which witnesses its output values correspond to - outputs: vec![ - BrilligOutputs::Simple(w_inverted), // Output Register 1 - ], + let brillig_bytecode = BrilligBytecode { bytecode: vec![ brillig::Opcode::CalldataCopy { destination_address: MemoryAddress(0), @@ -186,31 +200,44 @@ fn simple_brillig_foreign_call() { brillig::Opcode::ForeignCall { function: "invert".into(), destinations: vec![ValueOrArray::MemoryAddress(MemoryAddress::from(0))], - destination_value_types: vec![HeapValueType::Simple], + destination_value_types: vec![HeapValueType::field()], inputs: vec![ValueOrArray::MemoryAddress(MemoryAddress::from(0))], - input_value_types: vec![HeapValueType::Simple], + input_value_types: vec![HeapValueType::field()], }, brillig::Opcode::Stop { return_data_offset: 0, return_data_size: 1 }, ], - predicate: None, }; - let opcodes = vec![Opcode::Brillig(brillig_data)]; - let circuit = Circuit { + let opcodes = vec![Opcode::BrilligCall { + id: 0, + inputs: vec![ + BrilligInputs::Single(w_input.into()), // Input Register 0, + ], + // This tells the BrilligSolver which witnesses its output values correspond to + outputs: vec![ + BrilligOutputs::Simple(w_inverted), // Output Register 1 + ], + predicate: None, + }]; + + let circuit: Circuit = Circuit { current_witness_index: 8, opcodes, private_parameters: BTreeSet::from([Witness(1), Witness(2)]), ..Circuit::default() }; + let program = + Program { functions: vec![circuit], unconstrained_functions: vec![brillig_bytecode] }; - let bytes = Circuit::serialize_circuit(&circuit); + let bytes = Program::serialize_program(&program); let expected_serialization: Vec = vec![ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 143, 177, 10, 192, 32, 16, 67, 227, 21, 74, 233, - 212, 79, 177, 127, 208, 159, 233, 224, 226, 32, 226, 247, 139, 168, 16, 68, 93, 244, 45, - 119, 228, 142, 144, 92, 0, 20, 50, 7, 237, 76, 213, 190, 50, 245, 26, 175, 218, 231, 165, - 57, 175, 148, 14, 137, 179, 147, 191, 114, 211, 221, 216, 240, 59, 63, 107, 221, 115, 104, - 181, 103, 244, 43, 36, 10, 38, 68, 108, 25, 253, 238, 136, 1, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 144, 193, 10, 192, 32, 8, 134, 117, 99, 99, 236, + 182, 55, 105, 111, 176, 151, 217, 161, 75, 135, 136, 30, 63, 42, 82, 144, 8, 47, 245, 65, + 252, 230, 47, 162, 34, 52, 174, 242, 144, 226, 131, 148, 255, 18, 206, 125, 164, 102, 142, + 23, 215, 245, 50, 114, 222, 173, 15, 80, 38, 65, 217, 108, 39, 61, 7, 30, 115, 11, 223, + 186, 248, 251, 160, 221, 170, 146, 64, 191, 39, 215, 60, 3, 47, 3, 99, 171, 188, 84, 164, + 1, 0, 0, ]; assert_eq!(bytes, expected_serialization) @@ -230,27 +257,7 @@ fn complex_brillig_foreign_call() { let a_plus_b_plus_c = Witness(7); let a_plus_b_plus_c_times_2 = Witness(8); - let brillig_data = Brillig { - inputs: vec![ - // Input 0,1,2 - BrilligInputs::Array(vec![ - Expression::from(a), - Expression::from(b), - Expression::from(c), - ]), - // Input 3 - BrilligInputs::Single(Expression { - mul_terms: vec![], - linear_combinations: vec![(fe_1, a), (fe_1, b), (fe_1, c)], - q_c: fe_0, - }), - ], - // This tells the BrilligSolver which witnesses its output values correspond to - outputs: vec![ - BrilligOutputs::Array(vec![a_times_2, b_times_3, c_times_4]), // Output 0,1,2 - BrilligOutputs::Simple(a_plus_b_plus_c), // Output 3 - BrilligOutputs::Simple(a_plus_b_plus_c_times_2), // Output 4 - ], + let brillig_bytecode = BrilligBytecode { bytecode: vec![ brillig::Opcode::CalldataCopy { destination_address: MemoryAddress(32), @@ -259,7 +266,7 @@ fn complex_brillig_foreign_call() { }, brillig::Opcode::Const { destination: MemoryAddress(0), - value: brillig::Value::from(32_usize), + value: FieldElement::from(32_usize), bit_size: 32, }, brillig::Opcode::CalldataCopy { @@ -275,8 +282,8 @@ fn complex_brillig_foreign_call() { ValueOrArray::MemoryAddress(MemoryAddress::from(1)), ], input_value_types: vec![ - HeapValueType::Array { size: 3, value_types: vec![HeapValueType::Simple] }, - HeapValueType::Simple, + HeapValueType::Array { size: 3, value_types: vec![HeapValueType::field()] }, + HeapValueType::field(), ], destinations: vec![ ValueOrArray::HeapArray(HeapArray { pointer: 0.into(), size: 3 }), @@ -284,36 +291,60 @@ fn complex_brillig_foreign_call() { ValueOrArray::MemoryAddress(MemoryAddress::from(36)), ], destination_value_types: vec![ - HeapValueType::Array { size: 3, value_types: vec![HeapValueType::Simple] }, - HeapValueType::Simple, - HeapValueType::Simple, + HeapValueType::Array { size: 3, value_types: vec![HeapValueType::field()] }, + HeapValueType::field(), + HeapValueType::field(), ], }, brillig::Opcode::Stop { return_data_offset: 32, return_data_size: 5 }, ], - predicate: None, }; - let opcodes = vec![Opcode::Brillig(brillig_data)]; + let opcodes = vec![Opcode::BrilligCall { + id: 0, + inputs: vec![ + // Input 0,1,2 + BrilligInputs::Array(vec![ + Expression::from(a), + Expression::from(b), + Expression::from(c), + ]), + // Input 3 + BrilligInputs::Single(Expression { + mul_terms: vec![], + linear_combinations: vec![(fe_1, a), (fe_1, b), (fe_1, c)], + q_c: fe_0, + }), + ], + // This tells the BrilligSolver which witnesses its output values correspond to + outputs: vec![ + BrilligOutputs::Array(vec![a_times_2, b_times_3, c_times_4]), // Output 0,1,2 + BrilligOutputs::Simple(a_plus_b_plus_c), // Output 3 + BrilligOutputs::Simple(a_plus_b_plus_c_times_2), // Output 4 + ], + predicate: None, + }]; + let circuit = Circuit { current_witness_index: 8, opcodes, private_parameters: BTreeSet::from([Witness(1), Witness(2), Witness(3)]), ..Circuit::default() }; + let program = + Program { functions: vec![circuit], unconstrained_functions: vec![brillig_bytecode] }; - let bytes = Circuit::serialize_circuit(&circuit); - + let bytes = Program::serialize_program(&program); let expected_serialization: Vec = vec![ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 84, 75, 10, 132, 48, 12, 125, 177, 163, 35, 179, - 154, 35, 8, 51, 7, 232, 204, 9, 188, 139, 184, 83, 116, 233, 241, 173, 152, 98, 12, 213, - 141, 21, 244, 65, 232, 39, 175, 233, 35, 73, 155, 3, 32, 204, 48, 206, 18, 158, 19, 175, - 37, 60, 175, 228, 209, 30, 195, 143, 226, 197, 178, 103, 105, 76, 110, 160, 209, 156, 160, - 209, 247, 195, 69, 235, 29, 179, 46, 81, 243, 103, 2, 239, 231, 225, 44, 117, 150, 241, - 250, 201, 99, 206, 251, 96, 95, 161, 242, 14, 193, 243, 40, 162, 105, 253, 219, 12, 75, 47, - 146, 186, 251, 37, 116, 86, 93, 219, 55, 245, 96, 20, 85, 75, 253, 136, 249, 87, 249, 105, - 231, 220, 4, 249, 237, 132, 56, 20, 224, 109, 113, 223, 88, 82, 153, 34, 64, 34, 14, 164, - 69, 172, 48, 2, 23, 243, 6, 31, 25, 5, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 84, 75, 10, 131, 64, 12, 77, 102, 90, 43, 221, 245, + 6, 133, 246, 0, 211, 158, 192, 187, 136, 59, 69, 151, 158, 94, 116, 48, 131, 241, 233, 70, + 28, 65, 3, 195, 155, 79, 62, 47, 9, 25, 166, 81, 210, 97, 177, 236, 239, 130, 70, 208, 223, + 91, 154, 75, 208, 205, 4, 221, 62, 249, 113, 60, 95, 238, 40, 142, 230, 2, 28, 237, 1, 28, + 73, 245, 255, 132, 253, 142, 217, 151, 168, 245, 179, 43, 243, 115, 163, 113, 190, 18, 57, + 63, 4, 83, 44, 180, 55, 50, 180, 28, 188, 153, 224, 196, 122, 175, 111, 112, 68, 24, 65, + 116, 178, 40, 89, 254, 93, 162, 120, 48, 196, 126, 170, 12, 243, 186, 106, 202, 162, 181, + 160, 138, 84, 63, 106, 255, 133, 119, 6, 187, 14, 108, 59, 133, 250, 243, 90, 139, 19, 238, + 205, 6, 223, 47, 154, 202, 27, 74, 222, 3, 234, 73, 242, 82, 65, 5, 0, 0, ]; assert_eq!(bytes, expected_serialization) @@ -323,7 +354,11 @@ fn complex_brillig_foreign_call() { fn memory_op_circuit() { let init = vec![Witness(1), Witness(2)]; - let memory_init = Opcode::MemoryInit { block_id: BlockId(0), init }; + let memory_init = Opcode::MemoryInit { + block_id: BlockId(0), + init, + block_type: acir::circuit::opcodes::BlockType::Memory, + }; let write = Opcode::MemoryOp { block_id: BlockId(0), op: MemOp::write_to_mem_index(FieldElement::from(1u128).into(), Witness(3).into()), @@ -342,14 +377,123 @@ fn memory_op_circuit() { return_values: PublicInputs([Witness(4)].into()), ..Circuit::default() }; - let bytes = Circuit::serialize_circuit(&circuit); + let program = Program { functions: vec![circuit], unconstrained_functions: vec![] }; + + let bytes = Program::serialize_program(&program); let expected_serialization: Vec = vec![ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 145, 187, 17, 0, 32, 8, 67, 195, 111, 31, 220, 192, - 253, 167, 178, 144, 2, 239, 236, 132, 194, 52, 129, 230, 93, 8, 6, 64, 176, 101, 225, 28, - 78, 49, 43, 238, 154, 225, 254, 166, 209, 205, 165, 98, 174, 212, 177, 188, 187, 92, 255, - 173, 92, 173, 190, 93, 82, 80, 78, 123, 14, 127, 60, 97, 1, 210, 144, 46, 242, 19, 3, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 82, 65, 10, 0, 32, 8, 211, 180, 255, 216, 15, 250, + 255, 171, 10, 82, 176, 232, 150, 30, 26, 200, 118, 144, 49, 135, 8, 11, 117, 14, 169, 102, + 229, 162, 140, 78, 219, 206, 137, 174, 44, 111, 104, 217, 190, 24, 236, 75, 113, 94, 146, + 93, 174, 252, 86, 46, 71, 223, 78, 46, 104, 129, 253, 155, 45, 60, 195, 5, 3, 89, 11, 161, + 73, 39, 3, 0, 0, ]; assert_eq!(bytes, expected_serialization) } + +#[test] +fn nested_acir_call_circuit() { + // Circuit for the following program: + // fn main(x: Field, y: pub Field) { + // let z = nested_call(x, y); + // let z2 = nested_call(x, y); + // assert(z == z2); + // } + // #[fold] + // fn nested_call(x: Field, y: Field) -> Field { + // inner_call(x + 2, y) + // } + // #[fold] + // fn inner_call(x: Field, y: Field) -> Field { + // assert(x == y); + // x + // } + let nested_call = Opcode::Call { + id: 1, + inputs: vec![Witness(0), Witness(1)], + outputs: vec![Witness(2)], + predicate: None, + }; + let nested_call_two = Opcode::Call { + id: 1, + inputs: vec![Witness(0), Witness(1)], + outputs: vec![Witness(3)], + predicate: None, + }; + + let assert_nested_call_results = Opcode::AssertZero(Expression { + mul_terms: Vec::new(), + linear_combinations: vec![ + (FieldElement::one(), Witness(2)), + (-FieldElement::one(), Witness(3)), + ], + q_c: FieldElement::zero(), + }); + + let main = Circuit { + current_witness_index: 3, + private_parameters: BTreeSet::from([Witness(0)]), + public_parameters: PublicInputs([Witness(1)].into()), + opcodes: vec![nested_call, nested_call_two, assert_nested_call_results], + ..Circuit::default() + }; + + let call_parameter_addition = Opcode::AssertZero(Expression { + mul_terms: Vec::new(), + linear_combinations: vec![ + (FieldElement::one(), Witness(0)), + (-FieldElement::one(), Witness(2)), + ], + q_c: FieldElement::one() + FieldElement::one(), + }); + let call = Opcode::Call { + id: 2, + inputs: vec![Witness(2), Witness(1)], + outputs: vec![Witness(3)], + predicate: None, + }; + + let nested_call = Circuit { + current_witness_index: 3, + private_parameters: BTreeSet::from([Witness(0), Witness(1)]), + return_values: PublicInputs([Witness(3)].into()), + opcodes: vec![call_parameter_addition, call], + ..Circuit::default() + }; + + let assert_param_equality = Opcode::AssertZero(Expression { + mul_terms: Vec::new(), + linear_combinations: vec![ + (FieldElement::one(), Witness(0)), + (-FieldElement::one(), Witness(1)), + ], + q_c: FieldElement::zero(), + }); + + let inner_call = Circuit { + current_witness_index: 1, + private_parameters: BTreeSet::from([Witness(0), Witness(1)]), + return_values: PublicInputs([Witness(0)].into()), + opcodes: vec![assert_param_equality], + ..Circuit::default() + }; + + let program = + Program { functions: vec![main, nested_call, inner_call], unconstrained_functions: vec![] }; + + let bytes = Program::serialize_program(&program); + + let expected_serialization: Vec = vec![ + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 205, 146, 97, 10, 195, 32, 12, 133, 163, 66, 207, 147, + 24, 173, 241, 223, 174, 50, 153, 189, 255, 17, 214, 177, 148, 57, 17, 250, 99, 14, 250, + 224, 97, 144, 16, 146, 143, 231, 224, 45, 167, 126, 105, 217, 109, 118, 91, 248, 200, 168, + 225, 248, 63, 107, 114, 208, 233, 104, 188, 233, 139, 191, 137, 108, 51, 139, 113, 13, 161, + 38, 95, 137, 233, 142, 62, 23, 137, 24, 98, 89, 133, 132, 162, 196, 135, 23, 230, 42, 65, + 82, 46, 57, 97, 166, 192, 149, 182, 152, 121, 211, 97, 110, 222, 94, 8, 13, 132, 182, 54, + 48, 144, 235, 8, 254, 11, 22, 76, 132, 101, 231, 237, 229, 23, 189, 213, 54, 119, 15, 83, + 212, 199, 172, 175, 191, 226, 102, 96, 140, 251, 202, 84, 13, 204, 141, 224, 25, 176, 161, + 158, 53, 121, 144, 73, 14, 4, 0, 0, + ]; + assert_eq!(bytes, expected_serialization); +} diff --git a/acvm-repo/acir_field/Cargo.toml b/acvm-repo/acir_field/Cargo.toml index 6f4971770bd..f182c6c4aba 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.40.0" +version = "0.46.0" # x-release-please-end authors.workspace = true edition.workspace = true @@ -16,19 +16,13 @@ repository.workspace = true hex.workspace = true num-bigint.workspace = true serde.workspace = true -num-traits.workspace = true -ark-bn254 = { version = "^0.4.0", optional = true, default-features = false, features = [ - "curve", -] } -ark-bls12-381 = { version = "^0.4.0", optional = true, default-features = false, features = [ - "curve", -] } -ark-ff = { version = "^0.4.0", optional = true, default-features = false } +ark-bn254 = { version = "^0.4.0", default-features = false, features = ["curve"] } +ark-bls12-381 = { version = "^0.4.0", optional = true, default-features = false, features = ["curve"] } +ark-ff = { version = "^0.4.0", default-features = false } cfg-if = "1.0.0" [features] -default = ["bn254"] -bn254 = ["dep:ark-bn254", "dep:ark-ff"] -bls12_381 = ["dep:ark-bls12-381", "dep:ark-ff"] +bn254 = [] +bls12_381 = ["dep:ark-bls12-381"] diff --git a/acvm-repo/acir_field/src/field_element.rs b/acvm-repo/acir_field/src/field_element.rs new file mode 100644 index 00000000000..7810578ff73 --- /dev/null +++ b/acvm-repo/acir_field/src/field_element.rs @@ -0,0 +1,547 @@ +use ark_ff::PrimeField; +use ark_ff::Zero; +use num_bigint::BigUint; +use serde::{Deserialize, Serialize}; +use std::borrow::Cow; +use std::ops::{Add, AddAssign, Div, Mul, Neg, Sub, SubAssign}; + +use crate::AcirField; + +// XXX: Switch out for a trait and proper implementations +// This implementation is in-efficient, can definitely remove hex usage and Iterator instances for trivial functionality +#[derive(Default, Clone, Copy, Eq, PartialOrd, Ord)] +pub struct FieldElement(F); + +impl std::fmt::Display for FieldElement { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + // First check if the number is zero + // + let number = BigUint::from_bytes_be(&self.to_be_bytes()); + if number == BigUint::zero() { + return write!(f, "0"); + } + // Check if the negative version is smaller to represent + // + let minus_number = BigUint::from_bytes_be(&(self.neg()).to_be_bytes()); + let (smaller_repr, is_negative) = + if minus_number.to_string().len() < number.to_string().len() { + (minus_number, true) + } else { + (number, false) + }; + if is_negative { + write!(f, "-")?; + } + + // Number of bits needed to represent the smaller representation + let num_bits = smaller_repr.bits(); + + // Check if the number represents a power of 2 + if smaller_repr.count_ones() == 1 { + let mut bit_index = 0; + for i in 0..num_bits { + if smaller_repr.bit(i) { + bit_index = i; + break; + } + } + return match bit_index { + 0 => write!(f, "1"), + 1 => write!(f, "2"), + 2 => write!(f, "4"), + 3 => write!(f, "8"), + _ => write!(f, "2{}", superscript(bit_index)), + }; + } + + // Check if number is a multiple of a power of 2. + // This is used because when computing the quotient + // we usually have numbers in the form 2^t * q + r + // We focus on 2^64, 2^32, 2^16, 2^8, 2^4 because + // they are common. We could extend this to a more + // general factorization strategy, but we pay in terms of CPU time + let mul_sign = "×"; + for power in [64, 32, 16, 8, 4] { + let power_of_two = BigUint::from(2_u128).pow(power); + if &smaller_repr % &power_of_two == BigUint::zero() { + return write!( + f, + "2{}{}{}", + superscript(power as u64), + mul_sign, + smaller_repr / &power_of_two, + ); + } + } + write!(f, "{smaller_repr}") + } +} + +impl std::fmt::Debug for FieldElement { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self, f) + } +} + +impl std::hash::Hash for FieldElement { + fn hash(&self, state: &mut H) { + state.write(&self.to_be_bytes()); + } +} + +impl PartialEq for FieldElement { + fn eq(&self, other: &Self) -> bool { + self.to_be_bytes() == other.to_be_bytes() + } +} + +impl From for FieldElement { + fn from(mut a: i128) -> FieldElement { + let mut negative = false; + if a < 0 { + a = -a; + negative = true; + } + + let mut result = match F::from_str(&a.to_string()) { + Ok(result) => result, + Err(_) => panic!("Cannot convert i128 as a string to a field element"), + }; + + if negative { + result = -result; + } + FieldElement(result) + } +} + +impl Serialize for FieldElement { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + self.to_hex().serialize(serializer) + } +} + +impl<'de, T: ark_ff::PrimeField> Deserialize<'de> for FieldElement { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s: Cow<'de, str> = Deserialize::deserialize(deserializer)?; + match Self::from_hex(&s) { + Some(value) => Ok(value), + None => Err(serde::de::Error::custom(format!("Invalid hex for FieldElement: {s}",))), + } + } +} + +impl From for FieldElement { + fn from(a: u128) -> FieldElement { + let result = match F::from_str(&a.to_string()) { + Ok(result) => result, + Err(_) => panic!("Cannot convert u128 as a string to a field element"), + }; + FieldElement(result) + } +} + +impl From for FieldElement { + fn from(a: usize) -> FieldElement { + FieldElement::from(a as u128) + } +} + +impl From for FieldElement { + fn from(boolean: bool) -> FieldElement { + if boolean { + FieldElement::one() + } else { + FieldElement::zero() + } + } +} + +impl FieldElement { + pub fn from_repr(field: F) -> Self { + Self(field) + } + + // XXX: This method is used while this field element + // implementation is not generic. + pub fn into_repr(self) -> F { + self.0 + } + + fn is_negative(&self) -> bool { + self.neg().num_bits() < self.num_bits() + } + + fn fits_in_u128(&self) -> bool { + self.num_bits() <= 128 + } + + /// Returns None, if the string is not a canonical + /// representation of a field element; less than the order + /// or if the hex string is invalid. + /// This method can be used for both hex and decimal representations. + pub fn try_from_str(input: &str) -> Option> { + if input.contains('x') { + return FieldElement::from_hex(input); + } + + let fr = F::from_str(input).ok()?; + Some(FieldElement(fr)) + } + + // mask_to methods will not remove any bytes from the field + // they are simply zeroed out + // Whereas truncate_to will remove those bits and make the byte array smaller + fn mask_to_be_bytes(&self, num_bits: u32) -> Vec { + let mut bytes = self.to_be_bytes(); + mask_vector_le(&mut bytes, num_bits as usize); + bytes + } + + fn bits(&self) -> Vec { + fn byte_to_bit(byte: u8) -> Vec { + let mut bits = Vec::with_capacity(8); + for index in (0..=7).rev() { + bits.push((byte & (1 << index)) >> index == 1); + } + bits + } + + let bytes = self.to_be_bytes(); + let mut bits = Vec::with_capacity(bytes.len() * 8); + for byte in bytes { + bits.extend(byte_to_bit(byte)); + } + bits + } + + fn and_xor(&self, rhs: &FieldElement, num_bits: u32, is_xor: bool) -> FieldElement { + // XXX: Gadgets like SHA256 need to have their input be a multiple of 8 + // This is not a restriction caused by SHA256, as it works on bits + // but most backends assume bytes. + // We could implicitly pad, however this may not be intuitive for users. + // assert!( + // num_bits % 8 == 0, + // "num_bits is not a multiple of 8, it is {}", + // num_bits + // ); + + let lhs_bytes = self.mask_to_be_bytes(num_bits); + let rhs_bytes = rhs.mask_to_be_bytes(num_bits); + + let and_byte_arr: Vec<_> = lhs_bytes + .into_iter() + .zip(rhs_bytes) + .map(|(lhs, rhs)| if is_xor { lhs ^ rhs } else { lhs & rhs }) + .collect(); + + FieldElement::from_be_bytes_reduce(&and_byte_arr) + } +} + +impl AcirField for FieldElement { + fn one() -> FieldElement { + FieldElement(F::one()) + } + fn zero() -> FieldElement { + FieldElement(F::zero()) + } + + fn is_zero(&self) -> bool { + self == &Self::zero() + } + fn is_one(&self) -> bool { + self == &Self::one() + } + + fn pow(&self, exponent: &Self) -> Self { + FieldElement(self.0.pow(exponent.0.into_bigint())) + } + + /// Maximum number of bits needed to represent a field element + /// This is not the amount of bits being used to represent a field element + /// Example, you only need 254 bits to represent a field element in BN256 + /// But the representation uses 256 bits, so the top two bits are always zero + /// This method would return 254 + fn max_num_bits() -> u32 { + F::MODULUS_BIT_SIZE + } + + /// Maximum numbers of bytes needed to represent a field element + /// We are not guaranteed that the number of bits being used to represent a field element + /// will always be divisible by 8. If the case that it is not, we add one to the max number of bytes + /// For example, a max bit size of 254 would give a max byte size of 32. + fn max_num_bytes() -> u32 { + let num_bytes = Self::max_num_bits() / 8; + if Self::max_num_bits() % 8 == 0 { + num_bytes + } else { + num_bytes + 1 + } + } + + fn modulus() -> BigUint { + F::MODULUS.into() + } + + /// This is the number of bits required to represent this specific field element + fn num_bits(&self) -> u32 { + let bits = self.bits(); + // Iterate the number of bits and pop off all leading zeroes + let iter = bits.iter().skip_while(|x| !(**x)); + // Note: count will panic if it goes over usize::MAX. + // This may not be suitable for devices whose usize < u16 + iter.count() as u32 + } + + fn to_u128(self) -> u128 { + let bytes = self.to_be_bytes(); + u128::from_be_bytes(bytes[16..32].try_into().unwrap()) + } + + fn try_into_u128(self) -> Option { + self.fits_in_u128().then(|| self.to_u128()) + } + + fn to_i128(self) -> i128 { + let is_negative = self.is_negative(); + let bytes = if is_negative { self.neg() } else { self }.to_be_bytes(); + i128::from_be_bytes(bytes[16..32].try_into().unwrap()) * if is_negative { -1 } else { 1 } + } + + fn try_to_u64(&self) -> Option { + (self.num_bits() <= 64).then(|| self.to_u128() as u64) + } + + fn try_to_u32(&self) -> Option { + (self.num_bits() <= 32).then(|| self.to_u128() as u32) + } + + /// Computes the inverse or returns zero if the inverse does not exist + /// Before using this FieldElement, please ensure that this behavior is necessary + fn inverse(&self) -> FieldElement { + let inv = self.0.inverse().unwrap_or_else(F::zero); + FieldElement(inv) + } + + fn to_hex(self) -> String { + let mut bytes = Vec::new(); + self.0.serialize_uncompressed(&mut bytes).unwrap(); + bytes.reverse(); + hex::encode(bytes) + } + fn from_hex(hex_str: &str) -> Option> { + let value = hex_str.strip_prefix("0x").unwrap_or(hex_str); + // Values of odd length require an additional "0" prefix + let sanitized_value = + if value.len() % 2 == 0 { value.to_string() } else { format!("0{}", value) }; + let hex_as_bytes = hex::decode(sanitized_value).ok()?; + Some(FieldElement::from_be_bytes_reduce(&hex_as_bytes)) + } + + fn to_be_bytes(self) -> Vec { + // to_be_bytes! uses little endian which is why we reverse the output + // TODO: Add a little endian equivalent, so the caller can use whichever one + // TODO they desire + let mut bytes = Vec::new(); + self.0.serialize_uncompressed(&mut bytes).unwrap(); + bytes.reverse(); + bytes + } + + /// Converts bytes into a FieldElement and applies a + /// reduction if needed. + fn from_be_bytes_reduce(bytes: &[u8]) -> FieldElement { + FieldElement(F::from_be_bytes_mod_order(bytes)) + } + + /// Returns the closest number of bytes to the bits specified + /// This method truncates + fn fetch_nearest_bytes(&self, num_bits: usize) -> Vec { + fn nearest_bytes(num_bits: usize) -> usize { + ((num_bits + 7) / 8) * 8 + } + + let num_bytes = nearest_bytes(num_bits); + let num_elements = num_bytes / 8; + + let mut bytes = self.to_be_bytes(); + bytes.reverse(); // put it in big endian format. XXX(next refactor): we should be explicit about endianness. + + bytes[0..num_elements].to_vec() + } + + fn and(&self, rhs: &FieldElement, num_bits: u32) -> FieldElement { + self.and_xor(rhs, num_bits, false) + } + fn xor(&self, rhs: &FieldElement, num_bits: u32) -> FieldElement { + self.and_xor(rhs, num_bits, true) + } +} + +impl Neg for FieldElement { + type Output = FieldElement; + + fn neg(self) -> Self::Output { + FieldElement(-self.0) + } +} + +impl Mul for FieldElement { + type Output = FieldElement; + fn mul(mut self, rhs: FieldElement) -> Self::Output { + self.0.mul_assign(&rhs.0); + FieldElement(self.0) + } +} +impl Div for FieldElement { + type Output = FieldElement; + #[allow(clippy::suspicious_arithmetic_impl)] + fn div(self, rhs: FieldElement) -> Self::Output { + self * rhs.inverse() + } +} +impl Add for FieldElement { + type Output = FieldElement; + fn add(mut self, rhs: FieldElement) -> Self::Output { + self.0.add_assign(&rhs.0); + FieldElement(self.0) + } +} +impl AddAssign for FieldElement { + fn add_assign(&mut self, rhs: FieldElement) { + self.0.add_assign(&rhs.0); + } +} + +impl Sub for FieldElement { + type Output = FieldElement; + fn sub(mut self, rhs: FieldElement) -> Self::Output { + self.0.sub_assign(&rhs.0); + FieldElement(self.0) + } +} +impl SubAssign for FieldElement { + fn sub_assign(&mut self, rhs: FieldElement) { + self.0.sub_assign(&rhs.0); + } +} + +fn mask_vector_le(bytes: &mut [u8], num_bits: usize) { + // reverse to big endian format + bytes.reverse(); + + let mask_power = num_bits % 8; + let array_mask_index = num_bits / 8; + + for (index, byte) in bytes.iter_mut().enumerate() { + match index.cmp(&array_mask_index) { + std::cmp::Ordering::Less => { + // do nothing if the current index is less than + // the array index. + } + std::cmp::Ordering::Equal => { + let mask = 2u8.pow(mask_power as u32) - 1; + // mask the byte + *byte &= mask; + } + std::cmp::Ordering::Greater => { + // Anything greater than the array index + // will be set to zero + *byte = 0; + } + } + } + // reverse back to little endian + bytes.reverse(); +} + +// For pretty printing powers +fn superscript(n: u64) -> String { + if n == 0 { + "⁰".to_owned() + } else if n == 1 { + "¹".to_owned() + } else if n == 2 { + "²".to_owned() + } else if n == 3 { + "³".to_owned() + } else if n == 4 { + "⁴".to_owned() + } else if n == 5 { + "⁵".to_owned() + } else if n == 6 { + "⁶".to_owned() + } else if n == 7 { + "⁷".to_owned() + } else if n == 8 { + "⁸".to_owned() + } else if n == 9 { + "⁹".to_owned() + } else if n >= 10 { + superscript(n / 10) + &superscript(n % 10) + } else { + panic!("{}", n.to_string() + " can't be converted to superscript."); + } +} + +#[cfg(test)] +mod tests { + use super::{AcirField, FieldElement}; + + #[test] + fn and() { + let max = 10_000u32; + + let num_bits = (std::mem::size_of::() * 8) as u32 - max.leading_zeros(); + + for x in 0..max { + let x = FieldElement::::from(x as i128); + let res = x.and(&x, num_bits); + assert_eq!(res.to_be_bytes(), x.to_be_bytes()); + } + } + + #[test] + fn serialize_fixed_test_vectors() { + // Serialized field elements from of 0, -1, -2, -3 + let hex_strings = vec![ + "0000000000000000000000000000000000000000000000000000000000000000", + "30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000", + "30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffffff", + "30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffffe", + ]; + + for (i, string) in hex_strings.into_iter().enumerate() { + let minus_i_field_element = -FieldElement::::from(i as i128); + assert_eq!(minus_i_field_element.to_hex(), string); + } + } + + #[test] + fn deserialize_even_and_odd_length_hex() { + // Test cases of (odd, even) length hex strings + let hex_strings = + vec![("0x0", "0x00"), ("0x1", "0x01"), ("0x002", "0x0002"), ("0x00003", "0x000003")]; + for (i, case) in hex_strings.into_iter().enumerate() { + let i_field_element = FieldElement::::from(i as i128); + let odd_field_element = FieldElement::::from_hex(case.0).unwrap(); + let even_field_element = FieldElement::::from_hex(case.1).unwrap(); + + assert_eq!(i_field_element, odd_field_element); + assert_eq!(odd_field_element, even_field_element); + } + } + + #[test] + fn max_num_bits_smoke() { + let max_num_bits_bn254 = FieldElement::::max_num_bits(); + assert_eq!(max_num_bits_bn254, 254); + } +} diff --git a/acvm-repo/acir_field/src/generic_ark.rs b/acvm-repo/acir_field/src/generic_ark.rs index 3178011a075..3d93de5a992 100644 --- a/acvm-repo/acir_field/src/generic_ark.rs +++ b/acvm-repo/acir_field/src/generic_ark.rs @@ -1,545 +1,84 @@ -use ark_ff::PrimeField; -use ark_ff::Zero; use num_bigint::BigUint; -use serde::{Deserialize, Serialize}; -use std::borrow::Cow; -// XXX: Switch out for a trait and proper implementations -// This implementation is in-efficient, can definitely remove hex usage and Iterator instances for trivial functionality -#[derive(Clone, Copy, Eq, PartialOrd, Ord)] -pub struct FieldElement(F); - -impl std::fmt::Display for FieldElement { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - // First check if the number is zero - // - let number = BigUint::from_bytes_be(&self.to_be_bytes()); - if number == BigUint::zero() { - return write!(f, "0"); - } - // Check if the negative version is smaller to represent - // - let minus_number = BigUint::from_bytes_be(&(self.neg()).to_be_bytes()); - let (smaller_repr, is_negative) = - if minus_number.to_string().len() < number.to_string().len() { - (minus_number, true) - } else { - (number, false) - }; - if is_negative { - write!(f, "-")?; - } - - // Number of bits needed to represent the smaller representation - let num_bits = smaller_repr.bits(); - - // Check if the number represents a power of 2 - if smaller_repr.count_ones() == 1 { - let mut bit_index = 0; - for i in 0..num_bits { - if smaller_repr.bit(i) { - bit_index = i; - break; - } - } - return match bit_index { - 0 => write!(f, "1"), - 1 => write!(f, "2"), - 2 => write!(f, "4"), - 3 => write!(f, "8"), - _ => write!(f, "2{}", superscript(bit_index)), - }; - } - - // Check if number is a multiple of a power of 2. - // This is used because when computing the quotient - // we usually have numbers in the form 2^t * q + r - // We focus on 2^64, 2^32, 2^16, 2^8, 2^4 because - // they are common. We could extend this to a more - // general factorization strategy, but we pay in terms of CPU time - let mul_sign = "×"; - for power in [64, 32, 16, 8, 4] { - let power_of_two = BigUint::from(2_u128).pow(power); - if &smaller_repr % &power_of_two == BigUint::zero() { - return write!( - f, - "2{}{}{}", - superscript(power as u64), - mul_sign, - smaller_repr / &power_of_two, - ); - } - } - write!(f, "{smaller_repr}") - } -} - -impl std::fmt::Debug for FieldElement { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - std::fmt::Display::fmt(self, f) - } -} - -impl std::hash::Hash for FieldElement { - fn hash(&self, state: &mut H) { - state.write(&self.to_be_bytes()); - } -} - -impl PartialEq for FieldElement { - fn eq(&self, other: &Self) -> bool { - self.to_be_bytes() == other.to_be_bytes() - } -} - -impl From for FieldElement { - fn from(mut a: i128) -> FieldElement { - let mut negative = false; - if a < 0 { - a = -a; - negative = true; - } - - let mut result = match F::from_str(&a.to_string()) { - Ok(result) => result, - Err(_) => panic!("Cannot convert i128 as a string to a field element"), - }; - - if negative { - result = -result; - } - FieldElement(result) - } -} - -impl Serialize for FieldElement { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - self.to_hex().serialize(serializer) - } -} - -impl<'de, T: ark_ff::PrimeField> Deserialize<'de> for FieldElement { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - let s: Cow<'de, str> = Deserialize::deserialize(deserializer)?; - match Self::from_hex(&s) { - Some(value) => Ok(value), - None => Err(serde::de::Error::custom(format!("Invalid hex for FieldElement: {s}",))), - } - } -} - -impl From for FieldElement { - fn from(a: u128) -> FieldElement { - let result = match F::from_str(&a.to_string()) { - Ok(result) => result, - Err(_) => panic!("Cannot convert u128 as a string to a field element"), - }; - FieldElement(result) - } -} - -impl From for FieldElement { - fn from(a: usize) -> FieldElement { - FieldElement::from(a as u128) - } -} - -impl From for FieldElement { - fn from(boolean: bool) -> FieldElement { - if boolean { - FieldElement::one() - } else { - FieldElement::zero() - } - } -} - -impl FieldElement { - pub fn one() -> FieldElement { - FieldElement(F::one()) - } - pub fn zero() -> FieldElement { - FieldElement(F::zero()) - } - - pub fn is_zero(&self) -> bool { - self == &Self::zero() - } - pub fn is_one(&self) -> bool { - self == &Self::one() - } - - pub fn is_negative(&self) -> bool { - self.neg().num_bits() < self.num_bits() - } - - pub fn pow(&self, exponent: &Self) -> Self { - FieldElement(self.0.pow(exponent.0.into_bigint())) - } +/// This trait is extremely unstable and WILL have breaking changes. +pub trait AcirField: + std::marker::Sized + + std::fmt::Display + + std::fmt::Debug + + Default + + Clone + + Copy + + std::ops::Neg + + std::ops::Add + + std::ops::Sub + + std::ops::Mul + + std::ops::Div + + std::ops::AddAssign + + std::ops::SubAssign + + PartialOrd + + From + + From + // + From + // + From + // + From + // + From + + From + + std::hash::Hash + + std::cmp::Eq +{ + fn one() -> Self; + fn zero() -> Self; + + fn is_zero(&self) -> bool; + fn is_one(&self) -> bool; + + fn pow(&self, exponent: &Self) -> Self; /// Maximum number of bits needed to represent a field element /// This is not the amount of bits being used to represent a field element /// Example, you only need 254 bits to represent a field element in BN256 /// But the representation uses 256 bits, so the top two bits are always zero /// This method would return 254 - pub const fn max_num_bits() -> u32 { - F::MODULUS_BIT_SIZE - } + fn max_num_bits() -> u32; /// Maximum numbers of bytes needed to represent a field element /// We are not guaranteed that the number of bits being used to represent a field element /// will always be divisible by 8. If the case that it is not, we add one to the max number of bytes /// For example, a max bit size of 254 would give a max byte size of 32. - pub const fn max_num_bytes() -> u32 { - let num_bytes = Self::max_num_bits() / 8; - if Self::max_num_bits() % 8 == 0 { - num_bytes - } else { - num_bytes + 1 - } - } - - pub fn modulus() -> BigUint { - F::MODULUS.into() - } - /// Returns None, if the string is not a canonical - /// representation of a field element; less than the order - /// or if the hex string is invalid. - /// This method can be used for both hex and decimal representations. - pub fn try_from_str(input: &str) -> Option> { - if input.contains('x') { - return FieldElement::from_hex(input); - } + fn max_num_bytes() -> u32; - let fr = F::from_str(input).ok()?; - Some(FieldElement(fr)) - } + fn modulus() -> BigUint; /// This is the number of bits required to represent this specific field element - pub fn num_bits(&self) -> u32 { - let bits = self.bits(); - // Iterate the number of bits and pop off all leading zeroes - let iter = bits.iter().skip_while(|x| !(**x)); - // Note: count will panic if it goes over usize::MAX. - // This may not be suitable for devices whose usize < u16 - iter.count() as u32 - } + fn num_bits(&self) -> u32; - pub fn fits_in_u128(&self) -> bool { - self.num_bits() <= 128 - } + fn to_u128(self) -> u128; - pub fn to_u128(self) -> u128 { - let bytes = self.to_be_bytes(); - u128::from_be_bytes(bytes[16..32].try_into().unwrap()) - } + fn try_into_u128(self) -> Option; - pub fn try_into_u128(self) -> Option { - self.fits_in_u128().then(|| self.to_u128()) - } + fn to_i128(self) -> i128; - pub fn to_i128(self) -> i128 { - let is_negative = self.is_negative(); - let bytes = if is_negative { self.neg() } else { self }.to_be_bytes(); - i128::from_be_bytes(bytes[16..32].try_into().unwrap()) * if is_negative { -1 } else { 1 } - } + fn try_to_u64(&self) -> Option; - pub fn try_to_u64(&self) -> Option { - (self.num_bits() <= 64).then(|| self.to_u128() as u64) - } + fn try_to_u32(&self) -> Option; /// Computes the inverse or returns zero if the inverse does not exist /// Before using this FieldElement, please ensure that this behavior is necessary - pub fn inverse(&self) -> FieldElement { - let inv = self.0.inverse().unwrap_or_else(F::zero); - FieldElement(inv) - } - - pub fn try_inverse(mut self) -> Option { - self.0.inverse_in_place().map(|f| FieldElement(*f)) - } - - pub fn from_repr(field: F) -> Self { - Self(field) - } - - // XXX: This method is used while this field element - // implementation is not generic. - pub fn into_repr(self) -> F { - self.0 - } - - pub fn to_hex(self) -> String { - let mut bytes = Vec::new(); - self.0.serialize_uncompressed(&mut bytes).unwrap(); - bytes.reverse(); - hex::encode(bytes) - } - pub fn from_hex(hex_str: &str) -> Option> { - let value = hex_str.strip_prefix("0x").unwrap_or(hex_str); - // Values of odd length require an additional "0" prefix - let sanitized_value = - if value.len() % 2 == 0 { value.to_string() } else { format!("0{}", value) }; - let hex_as_bytes = hex::decode(sanitized_value).ok()?; - Some(FieldElement::from_be_bytes_reduce(&hex_as_bytes)) - } + fn inverse(&self) -> Self; - pub fn to_be_bytes(self) -> Vec { - // to_be_bytes! uses little endian which is why we reverse the output - // TODO: Add a little endian equivalent, so the caller can use whichever one - // TODO they desire - let mut bytes = Vec::new(); - self.0.serialize_uncompressed(&mut bytes).unwrap(); - bytes.reverse(); - bytes - } + fn to_hex(self) -> String; - /// Converts bytes into a FieldElement and applies a - /// reduction if needed. - pub fn from_be_bytes_reduce(bytes: &[u8]) -> FieldElement { - FieldElement(F::from_be_bytes_mod_order(bytes)) - } + fn from_hex(hex_str: &str) -> Option; - pub fn bits(&self) -> Vec { - let bytes = self.to_be_bytes(); - let mut bits = Vec::with_capacity(bytes.len() * 8); - for byte in bytes { - let _bits = FieldElement::::byte_to_bit(byte); - bits.extend(_bits); - } - bits - } + fn to_be_bytes(self) -> Vec; - fn byte_to_bit(byte: u8) -> Vec { - let mut bits = Vec::with_capacity(8); - for index in (0..=7).rev() { - bits.push((byte & (1 << index)) >> index == 1); - } - bits - } + /// Converts bytes into a FieldElement and applies a reduction if needed. + fn from_be_bytes_reduce(bytes: &[u8]) -> Self; /// Returns the closest number of bytes to the bits specified /// This method truncates - pub fn fetch_nearest_bytes(&self, num_bits: usize) -> Vec { - fn nearest_bytes(num_bits: usize) -> usize { - ((num_bits + 7) / 8) * 8 - } - - let num_bytes = nearest_bytes(num_bits); - let num_elements = num_bytes / 8; - - let mut bytes = self.to_be_bytes(); - bytes.reverse(); // put it in big endian format. XXX(next refactor): we should be explicit about endianness. - - bytes[0..num_elements].to_vec() - } - - // mask_to methods will not remove any bytes from the field - // they are simply zeroed out - // Whereas truncate_to will remove those bits and make the byte array smaller - fn mask_to_be_bytes(&self, num_bits: u32) -> Vec { - let mut bytes = self.to_be_bytes(); - mask_vector_le(&mut bytes, num_bits as usize); - bytes - } - - fn and_xor(&self, rhs: &FieldElement, num_bits: u32, is_xor: bool) -> FieldElement { - // XXX: Gadgets like SHA256 need to have their input be a multiple of 8 - // This is not a restriction caused by SHA256, as it works on bits - // but most backends assume bytes. - // We could implicitly pad, however this may not be intuitive for users. - // assert!( - // num_bits % 8 == 0, - // "num_bits is not a multiple of 8, it is {}", - // num_bits - // ); - - let lhs_bytes = self.mask_to_be_bytes(num_bits); - let rhs_bytes = rhs.mask_to_be_bytes(num_bits); - - let and_byte_arr: Vec<_> = lhs_bytes - .into_iter() - .zip(rhs_bytes) - .map(|(lhs, rhs)| if is_xor { lhs ^ rhs } else { lhs & rhs }) - .collect(); - - FieldElement::from_be_bytes_reduce(&and_byte_arr) - } - pub fn and(&self, rhs: &FieldElement, num_bits: u32) -> FieldElement { - self.and_xor(rhs, num_bits, false) - } - pub fn xor(&self, rhs: &FieldElement, num_bits: u32) -> FieldElement { - self.and_xor(rhs, num_bits, true) - } -} - -use std::ops::{Add, AddAssign, Div, Mul, Neg, Sub, SubAssign}; - -impl Neg for FieldElement { - type Output = FieldElement; - - fn neg(self) -> Self::Output { - FieldElement(-self.0) - } -} - -impl Mul for FieldElement { - type Output = FieldElement; - fn mul(mut self, rhs: FieldElement) -> Self::Output { - self.0.mul_assign(&rhs.0); - FieldElement(self.0) - } -} -impl Div for FieldElement { - type Output = FieldElement; - #[allow(clippy::suspicious_arithmetic_impl)] - fn div(self, rhs: FieldElement) -> Self::Output { - self * rhs.inverse() - } -} -impl Add for FieldElement { - type Output = FieldElement; - fn add(mut self, rhs: FieldElement) -> Self::Output { - self.0.add_assign(&rhs.0); - FieldElement(self.0) - } -} -impl AddAssign for FieldElement { - fn add_assign(&mut self, rhs: FieldElement) { - self.0.add_assign(&rhs.0); - } -} - -impl Sub for FieldElement { - type Output = FieldElement; - fn sub(mut self, rhs: FieldElement) -> Self::Output { - self.0.sub_assign(&rhs.0); - FieldElement(self.0) - } -} -impl SubAssign for FieldElement { - fn sub_assign(&mut self, rhs: FieldElement) { - self.0.sub_assign(&rhs.0); - } -} - -fn mask_vector_le(bytes: &mut [u8], num_bits: usize) { - // reverse to big endian format - bytes.reverse(); - - let mask_power = num_bits % 8; - let array_mask_index = num_bits / 8; - - for (index, byte) in bytes.iter_mut().enumerate() { - match index.cmp(&array_mask_index) { - std::cmp::Ordering::Less => { - // do nothing if the current index is less than - // the array index. - } - std::cmp::Ordering::Equal => { - let mask = 2u8.pow(mask_power as u32) - 1; - // mask the byte - *byte &= mask; - } - std::cmp::Ordering::Greater => { - // Anything greater than the array index - // will be set to zero - *byte = 0; - } - } - } - // reverse back to little endian - bytes.reverse(); -} - -// For pretty printing powers -fn superscript(n: u64) -> String { - if n == 0 { - "⁰".to_owned() - } else if n == 1 { - "¹".to_owned() - } else if n == 2 { - "²".to_owned() - } else if n == 3 { - "³".to_owned() - } else if n == 4 { - "⁴".to_owned() - } else if n == 5 { - "⁵".to_owned() - } else if n == 6 { - "⁶".to_owned() - } else if n == 7 { - "⁷".to_owned() - } else if n == 8 { - "⁸".to_owned() - } else if n == 9 { - "⁹".to_owned() - } else if n >= 10 { - superscript(n / 10) + &superscript(n % 10) - } else { - panic!("{}", n.to_string() + " can't be converted to superscript."); - } -} - -#[cfg(test)] -mod tests { - #[test] - fn and() { - let max = 10_000u32; - - let num_bits = (std::mem::size_of::() * 8) as u32 - max.leading_zeros(); - - for x in 0..max { - let x = crate::generic_ark::FieldElement::::from(x as i128); - let res = x.and(&x, num_bits); - assert_eq!(res.to_be_bytes(), x.to_be_bytes()); - } - } - - #[test] - fn serialize_fixed_test_vectors() { - // Serialized field elements from of 0, -1, -2, -3 - let hex_strings = vec![ - "0000000000000000000000000000000000000000000000000000000000000000", - "30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000", - "30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffffff", - "30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffffe", - ]; - - for (i, string) in hex_strings.into_iter().enumerate() { - let minus_i_field_element = - -crate::generic_ark::FieldElement::::from(i as i128); - assert_eq!(minus_i_field_element.to_hex(), string); - } - } - - #[test] - fn deserialize_even_and_odd_length_hex() { - // Test cases of (odd, even) length hex strings - let hex_strings = - vec![("0x0", "0x00"), ("0x1", "0x01"), ("0x002", "0x0002"), ("0x00003", "0x000003")]; - for (i, case) in hex_strings.into_iter().enumerate() { - let i_field_element = - crate::generic_ark::FieldElement::::from(i as i128); - let odd_field_element = - crate::generic_ark::FieldElement::::from_hex(case.0).unwrap(); - let even_field_element = - crate::generic_ark::FieldElement::::from_hex(case.1).unwrap(); - - assert_eq!(i_field_element, odd_field_element); - assert_eq!(odd_field_element, even_field_element); - } - } + fn fetch_nearest_bytes(&self, num_bits: usize) -> Vec; - #[test] - fn max_num_bits_smoke() { - let max_num_bits_bn254 = crate::generic_ark::FieldElement::::max_num_bits(); - assert_eq!(max_num_bits_bn254, 254); - } + fn and(&self, rhs: &Self, num_bits: u32) -> Self; + fn xor(&self, rhs: &Self, num_bits: u32) -> Self; } diff --git a/acvm-repo/acir_field/src/lib.rs b/acvm-repo/acir_field/src/lib.rs index eafe4bb2ad4..1ad9a5b0037 100644 --- a/acvm-repo/acir_field/src/lib.rs +++ b/acvm-repo/acir_field/src/lib.rs @@ -3,51 +3,22 @@ #![warn(clippy::semicolon_if_nothing_returned)] #![cfg_attr(not(test), warn(unused_crate_dependencies, unused_extern_crates))] -use num_bigint::BigUint; -use num_traits::Num; +mod field_element; +mod generic_ark; -cfg_if::cfg_if! { - if #[cfg(feature = "bn254")] { - mod generic_ark; - pub type FieldElement = generic_ark::FieldElement; - pub const CHOSEN_FIELD : FieldOptions = FieldOptions::BN254; +pub use generic_ark::AcirField; + +/// Temporarily exported generic field to aid migration to `AcirField` +pub use field_element::FieldElement as GenericFieldElement; - } else if #[cfg(feature = "bls12_381")] { - mod generic_ark; - pub type FieldElement = generic_ark::FieldElement; - pub const CHOSEN_FIELD : FieldOptions = FieldOptions::BLS12_381; +cfg_if::cfg_if! { + if #[cfg(feature = "bls12_381")] { + pub type FieldElement = field_element::FieldElement; } else { - compile_error!("please specify a field to compile with"); + pub type FieldElement = field_element::FieldElement; } } -#[derive(Debug, PartialEq, Eq)] -pub enum FieldOptions { - BN254, - BLS12_381, -} - -impl FieldOptions { - pub fn to_string(&self) -> &str { - match self { - FieldOptions::BN254 => "bn254", - FieldOptions::BLS12_381 => "bls12_381", - } - } - - pub fn is_native_field(str: &str) -> bool { - let big_num = if let Some(hex) = str.strip_prefix("0x") { - BigUint::from_str_radix(hex, 16) - } else { - BigUint::from_str_radix(str, 10) - }; - if let Ok(big_num) = big_num { - big_num == FieldElement::modulus() - } else { - CHOSEN_FIELD.to_string() == str - } - } -} // This is needed because features are additive through the dependency graph; if a dependency turns on the bn254, then it // will be turned on in all crates that depend on it #[macro_export] diff --git a/acvm-repo/acvm/Cargo.toml b/acvm-repo/acvm/Cargo.toml index fce9a8e8e8b..577978939b0 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.40.0" +version = "0.46.0" # x-release-please-end authors.workspace = true edition.workspace = true @@ -24,7 +24,6 @@ acvm_blackbox_solver.workspace = true indexmap = "1.7.0" [features] -default = ["bn254"] bn254 = [ "acir/bn254", "brillig_vm/bn254", @@ -40,3 +39,4 @@ bls12_381 = [ rand = "0.8.5" proptest = "1.2.0" paste = "1.0.14" +ark-bls12-381 = { version = "^0.4.0", default-features = false, features = ["curve"] } \ No newline at end of file diff --git a/acvm-repo/acvm/src/compiler/mod.rs b/acvm-repo/acvm/src/compiler/mod.rs index 6543c70958b..5ece3d19a6e 100644 --- a/acvm-repo/acvm/src/compiler/mod.rs +++ b/acvm-repo/acvm/src/compiler/mod.rs @@ -1,6 +1,9 @@ use std::collections::HashMap; -use acir::circuit::{Circuit, ExpressionWidth, OpcodeLocation}; +use acir::{ + circuit::{AssertionPayload, Circuit, ExpressionWidth, OpcodeLocation}, + AcirField, +}; // The various passes that we can use over ACIR mod optimizers; @@ -53,10 +56,10 @@ impl AcirTransformationMap { } } -fn transform_assert_messages( - assert_messages: Vec<(OpcodeLocation, String)>, +fn transform_assert_messages( + assert_messages: Vec<(OpcodeLocation, AssertionPayload)>, map: &AcirTransformationMap, -) -> Vec<(OpcodeLocation, String)> { +) -> Vec<(OpcodeLocation, AssertionPayload)> { assert_messages .into_iter() .flat_map(|(location, message)| { @@ -67,10 +70,10 @@ fn transform_assert_messages( } /// Applies [`ProofSystemCompiler`][crate::ProofSystemCompiler] specific optimizations to a [`Circuit`]. -pub fn compile( - acir: Circuit, +pub fn compile( + acir: Circuit, expression_width: ExpressionWidth, -) -> (Circuit, AcirTransformationMap) { +) -> (Circuit, AcirTransformationMap) { let (acir, acir_opcode_positions) = optimize_internal(acir); let (mut acir, acir_opcode_positions) = diff --git a/acvm-repo/acvm/src/compiler/optimizers/constant_backpropagation.rs b/acvm-repo/acvm/src/compiler/optimizers/constant_backpropagation.rs new file mode 100644 index 00000000000..5b778f63f07 --- /dev/null +++ b/acvm-repo/acvm/src/compiler/optimizers/constant_backpropagation.rs @@ -0,0 +1,331 @@ +use std::collections::{BTreeMap, BTreeSet, HashMap}; + +use crate::{ + compiler::optimizers::GeneralOptimizer, + pwg::{ + arithmetic::ExpressionSolver, blackbox::solve_range_opcode, directives::solve_directives, + BrilligSolver, BrilligSolverStatus, + }, +}; +use acir::{ + circuit::{ + brillig::{Brillig, BrilligInputs, BrilligOutputs}, + directives::Directive, + opcodes::BlackBoxFuncCall, + Circuit, Opcode, + }, + native_types::{Expression, Witness, WitnessMap}, +}; +use acvm_blackbox_solver::StubbedBlackBoxSolver; + +/// `ConstantBackpropagationOptimizer` will attempt to determine any constant witnesses within the program. +/// It does this by attempting to solve the program without any inputs (i.e. using an empty witness map), +/// any values which it can determine are then enforced to be constant values. +/// +/// The optimizer will then replace any witnesses wherever they appear within the circuit with these constant values. +/// This is repeated until the circuit stabilizes. +pub(crate) struct ConstantBackpropagationOptimizer { + circuit: Circuit, +} + +impl ConstantBackpropagationOptimizer { + /// Creates a new `ConstantBackpropagationOptimizer` + pub(crate) fn new(circuit: Circuit) -> Self { + Self { circuit } + } + + fn gather_known_witnesses(&self) -> (WitnessMap, BTreeSet) { + // We do not want to affect the circuit's interface so avoid optimizing away these witnesses. + let mut required_witnesses: BTreeSet = self + .circuit + .private_parameters + .union(&self.circuit.public_parameters.0) + .chain(&self.circuit.return_values.0) + .copied() + .collect(); + + for opcode in &self.circuit.opcodes { + match &opcode { + Opcode::BlackBoxFuncCall(func_call) => { + required_witnesses.extend( + func_call.get_inputs_vec().into_iter().map(|func_input| func_input.witness), + ); + required_witnesses.extend(func_call.get_outputs_vec()); + } + + Opcode::MemoryInit { init, .. } => { + required_witnesses.extend(init); + } + + Opcode::MemoryOp { op, .. } => { + required_witnesses.insert(op.index.to_witness().unwrap()); + required_witnesses.insert(op.value.to_witness().unwrap()); + } + + _ => (), + }; + } + + let mut known_witnesses = WitnessMap::new(); + for opcode in self.circuit.opcodes.iter().rev() { + if let Opcode::AssertZero(expr) = opcode { + let solve_result = ExpressionSolver::solve(&mut known_witnesses, expr); + // It doesn't matter what the result is. We expect most opcodes to not be solved successfully so we discard errors. + // At the same time, if the expression can be solved then we track this by the updates to `known_witnesses` + drop(solve_result); + } + } + + // We want to retain any references to required witnesses so we "forget" these assignments. + let known_witnesses: BTreeMap<_, _> = known_witnesses + .into_iter() + .filter(|(witness, _)| !required_witnesses.contains(witness)) + .collect(); + + (known_witnesses.into(), required_witnesses) + } + + /// Returns a `Circuit` where with any constant witnesses replaced with the constant they resolve to. + #[tracing::instrument(level = "trace", skip_all)] + pub(crate) fn backpropagate_constants( + circuit: Circuit, + order_list: Vec, + ) -> (Circuit, Vec) { + let old_circuit_size = circuit.opcodes.len(); + + let optimizer = Self::new(circuit); + let (circuit, order_list) = optimizer.backpropagate_constants_iteration(order_list); + + let new_circuit_size = circuit.opcodes.len(); + if new_circuit_size < old_circuit_size { + Self::backpropagate_constants(circuit, order_list) + } else { + (circuit, order_list) + } + } + + /// Applies a single round of constant backpropagation to a `Circuit`. + pub(crate) fn backpropagate_constants_iteration( + mut self, + order_list: Vec, + ) -> (Circuit, Vec) { + let (mut known_witnesses, required_witnesses) = self.gather_known_witnesses(); + + let opcodes = std::mem::take(&mut self.circuit.opcodes); + + fn remap_expression(known_witnesses: &WitnessMap, expression: Expression) -> Expression { + GeneralOptimizer::optimize(ExpressionSolver::evaluate(&expression, known_witnesses)) + } + + let mut new_order_list = Vec::with_capacity(order_list.len()); + let mut new_opcodes = Vec::with_capacity(opcodes.len()); + for (idx, opcode) in opcodes.into_iter().enumerate() { + let new_opcode = match opcode { + Opcode::AssertZero(expression) => { + let new_expr = remap_expression(&known_witnesses, expression); + if new_expr.is_zero() { + continue; + } + + // Attempt to solve the opcode to see if we can determine the value of any witnesses in the expression. + // We only do this _after_ we apply any simplifications to create the new opcode as we want to + // keep the constraint on the witness which we are solving for here. + let solve_result = ExpressionSolver::solve(&mut known_witnesses, &new_expr); + // It doesn't matter what the result is. We expect most opcodes to not be solved successfully so we discard errors. + // At the same time, if the expression can be solved then we track this by the updates to `known_witnesses` + drop(solve_result); + + Opcode::AssertZero(new_expr) + } + Opcode::Brillig(brillig) => { + let remapped_inputs = brillig + .inputs + .into_iter() + .map(|input| match input { + BrilligInputs::Single(expr) => { + BrilligInputs::Single(remap_expression(&known_witnesses, expr)) + } + BrilligInputs::Array(expr_array) => { + let new_input: Vec<_> = expr_array + .into_iter() + .map(|expr| remap_expression(&known_witnesses, expr)) + .collect(); + + BrilligInputs::Array(new_input) + } + input @ BrilligInputs::MemoryArray(_) => input, + }) + .collect(); + + let remapped_predicate = brillig + .predicate + .map(|predicate| remap_expression(&known_witnesses, predicate)); + + let new_brillig = Brillig { + inputs: remapped_inputs, + predicate: remapped_predicate, + ..brillig + }; + + let brillig_output_is_required_witness = + new_brillig.outputs.iter().any(|output| match output { + BrilligOutputs::Simple(witness) => required_witnesses.contains(witness), + BrilligOutputs::Array(witness_array) => witness_array + .iter() + .any(|witness| required_witnesses.contains(witness)), + }); + + if brillig_output_is_required_witness { + // If one of the brillig opcode's outputs is a required witness then we can't remove the opcode. In this case we can't replace + // all of the uses of this witness with the calculated constant so we'll be attempting to use an uninitialized witness. + // + // We then do not attempt execution of this opcode and just simplify the inputs. + Opcode::Brillig(new_brillig) + } else if let Ok(mut solver) = BrilligSolver::new( + &known_witnesses, + &HashMap::new(), + &new_brillig, + &StubbedBlackBoxSolver, + idx, + ) { + match solver.solve() { + Ok(BrilligSolverStatus::Finished) => { + // Write execution outputs + match solver.finalize(&mut known_witnesses, &new_brillig) { + Ok(()) => { + // If we've managed to execute the brillig opcode at compile time, we can now just write in the + // results as constants for the rest of the circuit. + continue; + } + _ => Opcode::Brillig(new_brillig), + } + } + Ok(BrilligSolverStatus::InProgress) => unreachable!( + "Solver should either finish, block on foreign call, or error." + ), + Ok(BrilligSolverStatus::ForeignCallWait(_)) | Err(_) => { + Opcode::Brillig(new_brillig) + } + } + } else { + Opcode::Brillig(new_brillig) + } + } + + Opcode::Directive(Directive::ToLeRadix { a, b, radix }) => { + if b.iter().all(|output| known_witnesses.contains_key(output)) { + continue; + } else if b.iter().any(|witness| required_witnesses.contains(witness)) { + // If one of the brillig opcode's outputs is a required witness then we can't remove the opcode. In this case we can't replace + // all of the uses of this witness with the calculated constant so we'll be attempting to use an uninitialized witness. + // + // We then do not attempt execution of this opcode and just simplify the inputs. + Opcode::Directive(Directive::ToLeRadix { + a: remap_expression(&known_witnesses, a), + b, + radix, + }) + } else { + let directive = Directive::ToLeRadix { + a: remap_expression(&known_witnesses, a), + b, + radix, + }; + let result = solve_directives(&mut known_witnesses, &directive); + + match result { + Ok(()) => continue, + Err(_) => Opcode::Directive(directive), + } + } + } + + Opcode::BlackBoxFuncCall(BlackBoxFuncCall::RANGE { input }) => { + if solve_range_opcode(&known_witnesses, &input).is_ok() { + continue; + } else { + opcode + } + } + + Opcode::BlackBoxFuncCall(_) + | Opcode::MemoryOp { .. } + | Opcode::MemoryInit { .. } => opcode, + }; + + new_opcodes.push(new_opcode); + new_order_list.push(order_list[idx]); + } + + self.circuit.opcodes = new_opcodes; + + (self.circuit, new_order_list) + } +} + +#[cfg(test)] +mod tests { + use std::collections::BTreeSet; + + use crate::compiler::optimizers::constant_backpropagation::ConstantBackpropagationOptimizer; + use acir::{ + brillig::MemoryAddress, + circuit::{ + brillig::{Brillig, BrilligOutputs}, + opcodes::{BlackBoxFuncCall, FunctionInput}, + Circuit, ExpressionWidth, Opcode, PublicInputs, + }, + native_types::Witness, + }; + use brillig_vm::brillig::Opcode as BrilligOpcode; + + fn test_circuit(opcodes: Vec) -> Circuit { + Circuit { + current_witness_index: 1, + expression_width: ExpressionWidth::Bounded { width: 4 }, + opcodes, + private_parameters: BTreeSet::new(), + public_parameters: PublicInputs::default(), + return_values: PublicInputs::default(), + assert_messages: Default::default(), + recursive: false, + } + } + + #[test] + fn retain_brillig_with_required_witness_outputs() { + let brillig_opcode = Opcode::Brillig(Brillig { + inputs: Vec::new(), + outputs: vec![BrilligOutputs::Simple(Witness(1))], + bytecode: vec![ + BrilligOpcode::Const { + destination: MemoryAddress(0), + bit_size: 32, + value: 1u128.into(), + }, + BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 1 }, + ], + predicate: None, + }); + let blackbox_opcode = Opcode::BlackBoxFuncCall(BlackBoxFuncCall::AND { + lhs: FunctionInput { witness: Witness(1), num_bits: 64 }, + rhs: FunctionInput { witness: Witness(2), num_bits: 64 }, + output: Witness(3), + }); + + let opcodes = vec![brillig_opcode, blackbox_opcode]; + // The optimizer should keep the lowest bit size range constraint + let circuit = test_circuit(opcodes); + let acir_opcode_positions = circuit.opcodes.iter().enumerate().map(|(i, _)| i).collect(); + let optimizer = ConstantBackpropagationOptimizer::new(circuit); + + let (optimized_circuit, _) = + optimizer.backpropagate_constants_iteration(acir_opcode_positions); + + assert_eq!( + optimized_circuit.opcodes.len(), + 2, + "The brillig opcode should not be removed as the output is needed as a witness" + ); + } +} diff --git a/acvm-repo/acvm/src/compiler/optimizers/general.rs b/acvm-repo/acvm/src/compiler/optimizers/general.rs index 2bd781f7bb5..39a01a38cac 100644 --- a/acvm-repo/acvm/src/compiler/optimizers/general.rs +++ b/acvm-repo/acvm/src/compiler/optimizers/general.rs @@ -1,6 +1,6 @@ use acir::{ native_types::{Expression, Witness}, - FieldElement, + AcirField, }; use indexmap::IndexMap; @@ -10,15 +10,16 @@ use indexmap::IndexMap; pub(crate) struct GeneralOptimizer; impl GeneralOptimizer { - pub(crate) fn optimize(opcode: Expression) -> Expression { + pub(crate) fn optimize(opcode: Expression) -> Expression { // XXX: Perhaps this optimization can be done on the fly let opcode = remove_zero_coefficients(opcode); - simplify_mul_terms(opcode) + let opcode = simplify_mul_terms(opcode); + simplify_linear_terms(opcode) } } // Remove all terms with zero as a coefficient -fn remove_zero_coefficients(mut opcode: Expression) -> Expression { +fn remove_zero_coefficients(mut opcode: Expression) -> Expression { // Check the mul terms opcode.mul_terms.retain(|(scale, _, _)| !scale.is_zero()); // Check the linear combination terms @@ -27,8 +28,8 @@ fn remove_zero_coefficients(mut opcode: Expression) -> Expression { } // Simplifies all mul terms with the same bi-variate variables -fn simplify_mul_terms(mut gate: Expression) -> Expression { - let mut hash_map: IndexMap<(Witness, Witness), FieldElement> = IndexMap::new(); +fn simplify_mul_terms(mut gate: Expression) -> Expression { + let mut hash_map: IndexMap<(Witness, Witness), F> = IndexMap::new(); // Canonicalize the ordering of the multiplication, lets just order by variable name for (scale, w_l, w_r) in gate.mul_terms.into_iter() { @@ -36,9 +37,26 @@ fn simplify_mul_terms(mut gate: Expression) -> Expression { // Sort using rust sort algorithm pair.sort(); - *hash_map.entry((pair[0], pair[1])).or_insert_with(FieldElement::zero) += scale; + *hash_map.entry((pair[0], pair[1])).or_insert_with(F::zero) += scale; } gate.mul_terms = hash_map.into_iter().map(|((w_l, w_r), scale)| (scale, w_l, w_r)).collect(); gate } + +// Simplifies all linear terms with the same variables +fn simplify_linear_terms(mut gate: Expression) -> Expression { + let mut hash_map: IndexMap = IndexMap::new(); + + // Canonicalize the ordering of the terms, lets just order by variable name + for (scale, witness) in gate.linear_combinations.into_iter() { + *hash_map.entry(witness).or_insert_with(F::zero) += scale; + } + + gate.linear_combinations = hash_map + .into_iter() + .filter(|(_, scale)| !scale.is_zero()) + .map(|(witness, scale)| (scale, witness)) + .collect(); + gate +} diff --git a/acvm-repo/acvm/src/compiler/optimizers/mod.rs b/acvm-repo/acvm/src/compiler/optimizers/mod.rs index 923756580b3..e20ad97a108 100644 --- a/acvm-repo/acvm/src/compiler/optimizers/mod.rs +++ b/acvm-repo/acvm/src/compiler/optimizers/mod.rs @@ -1,5 +1,9 @@ -use acir::circuit::{Circuit, Opcode}; +use acir::{ + circuit::{Circuit, Opcode}, + AcirField, +}; +// mod constant_backpropagation; mod general; mod redundant_range; mod unused_memory; @@ -8,12 +12,13 @@ pub(crate) use general::GeneralOptimizer; pub(crate) use redundant_range::RangeOptimizer; use tracing::info; +// use self::constant_backpropagation::ConstantBackpropagationOptimizer; use self::unused_memory::UnusedMemoryOptimizer; use super::{transform_assert_messages, AcirTransformationMap}; /// Applies [`ProofSystemCompiler`][crate::ProofSystemCompiler] independent optimizations to a [`Circuit`]. -pub fn optimize(acir: Circuit) -> (Circuit, AcirTransformationMap) { +pub fn optimize(acir: Circuit) -> (Circuit, AcirTransformationMap) { let (mut acir, new_opcode_positions) = optimize_internal(acir); let transformation_map = AcirTransformationMap::new(new_opcode_positions); @@ -25,11 +30,20 @@ pub fn optimize(acir: Circuit) -> (Circuit, AcirTransformationMap) { /// Applies [`ProofSystemCompiler`][crate::ProofSystemCompiler] independent optimizations to a [`Circuit`]. #[tracing::instrument(level = "trace", name = "optimize_acir" skip(acir))] -pub(super) fn optimize_internal(acir: Circuit) -> (Circuit, Vec) { +pub(super) fn optimize_internal(acir: Circuit) -> (Circuit, Vec) { + // Track original acir opcode positions throughout the transformation passes of the compilation + // by applying the modifications done to the circuit opcodes and also to the opcode_positions (delete and insert) + let acir_opcode_positions = (0..acir.opcodes.len()).collect(); + + if acir.opcodes.len() == 1 && matches!(acir.opcodes[0], Opcode::BrilligCall { .. }) { + info!("Program is fully unconstrained, skipping optimization pass"); + return (acir, acir_opcode_positions); + } + info!("Number of opcodes before: {}", acir.opcodes.len()); // General optimizer pass - let opcodes: Vec = acir + let opcodes: Vec> = acir .opcodes .into_iter() .map(|opcode| { @@ -42,20 +56,22 @@ pub(super) fn optimize_internal(acir: Circuit) -> (Circuit, Vec) { .collect(); let acir = Circuit { opcodes, ..acir }; - // Track original acir opcode positions throughout the transformation passes of the compilation - // by applying the modifications done to the circuit opcodes and also to the opcode_positions (delete and insert) - let acir_opcode_positions = (0..acir.opcodes.len()).collect(); - // Unused memory optimization pass let memory_optimizer = UnusedMemoryOptimizer::new(acir); let (acir, acir_opcode_positions) = memory_optimizer.remove_unused_memory_initializations(acir_opcode_positions); + // let (acir, acir_opcode_positions) = + // ConstantBackpropagationOptimizer::backpropagate_constants(acir, acir_opcode_positions); + // Range optimization pass let range_optimizer = RangeOptimizer::new(acir); let (acir, acir_opcode_positions) = range_optimizer.replace_redundant_ranges(acir_opcode_positions); + // let (acir, acir_opcode_positions) = + // ConstantBackpropagationOptimizer::backpropagate_constants(acir, acir_opcode_positions); + info!("Number of opcodes after: {}", acir.opcodes.len()); (acir, acir_opcode_positions) diff --git a/acvm-repo/acvm/src/compiler/optimizers/redundant_range.rs b/acvm-repo/acvm/src/compiler/optimizers/redundant_range.rs index c6ca18d30ae..7001c953d63 100644 --- a/acvm-repo/acvm/src/compiler/optimizers/redundant_range.rs +++ b/acvm-repo/acvm/src/compiler/optimizers/redundant_range.rs @@ -4,6 +4,7 @@ use acir::{ Circuit, Opcode, }, native_types::Witness, + AcirField, }; use std::collections::{BTreeMap, HashSet}; @@ -26,16 +27,16 @@ use std::collections::{BTreeMap, HashSet}; /// /// This optimization pass will keep the 16-bit range constraint /// and remove the 32-bit range constraint opcode. -pub(crate) struct RangeOptimizer { +pub(crate) struct RangeOptimizer { /// Maps witnesses to their lowest known bit sizes. lists: BTreeMap, - circuit: Circuit, + circuit: Circuit, } -impl RangeOptimizer { +impl RangeOptimizer { /// Creates a new `RangeOptimizer` by collecting all known range /// constraints from `Circuit`. - pub(crate) fn new(circuit: Circuit) -> Self { + pub(crate) fn new(circuit: Circuit) -> Self { let range_list = Self::collect_ranges(&circuit); Self { circuit, lists: range_list } } @@ -46,7 +47,7 @@ impl RangeOptimizer { /// both 32 bits and 16 bits. This function will /// only store the fact that we have constrained it to /// be 16 bits. - fn collect_ranges(circuit: &Circuit) -> BTreeMap { + fn collect_ranges(circuit: &Circuit) -> BTreeMap { let mut witness_to_bit_sizes: BTreeMap = BTreeMap::new(); for opcode in &circuit.opcodes { @@ -95,7 +96,10 @@ impl RangeOptimizer { /// Returns a `Circuit` where each Witness is only range constrained /// once to the lowest number `bit size` possible. - pub(crate) fn replace_redundant_ranges(self, order_list: Vec) -> (Circuit, Vec) { + pub(crate) fn replace_redundant_ranges( + self, + order_list: Vec, + ) -> (Circuit, Vec) { let mut already_seen_witness = HashSet::new(); let mut new_order_list = Vec::with_capacity(order_list.len()); @@ -148,10 +152,11 @@ mod tests { Circuit, ExpressionWidth, Opcode, PublicInputs, }, native_types::{Expression, Witness}, + FieldElement, }; - fn test_circuit(ranges: Vec<(Witness, u32)>) -> Circuit { - fn test_range_constraint(witness: Witness, num_bits: u32) -> Opcode { + fn test_circuit(ranges: Vec<(Witness, u32)>) -> Circuit { + fn test_range_constraint(witness: Witness, num_bits: u32) -> Opcode { Opcode::BlackBoxFuncCall(BlackBoxFuncCall::RANGE { input: FunctionInput { witness, num_bits }, }) @@ -164,7 +169,7 @@ mod tests { Circuit { current_witness_index: 1, - expression_width: ExpressionWidth::Bounded { width: 3 }, + expression_width: ExpressionWidth::Bounded { width: 4 }, opcodes, private_parameters: BTreeSet::new(), public_parameters: PublicInputs::default(), diff --git a/acvm-repo/acvm/src/compiler/optimizers/unused_memory.rs b/acvm-repo/acvm/src/compiler/optimizers/unused_memory.rs index 18eefa79ac2..1963430210f 100644 --- a/acvm-repo/acvm/src/compiler/optimizers/unused_memory.rs +++ b/acvm-repo/acvm/src/compiler/optimizers/unused_memory.rs @@ -2,15 +2,15 @@ use acir::circuit::{opcodes::BlockId, Circuit, Opcode}; use std::collections::HashSet; /// `UnusedMemoryOptimizer` will remove initializations of memory blocks which are unused. -pub(crate) struct UnusedMemoryOptimizer { +pub(crate) struct UnusedMemoryOptimizer { unused_memory_initializations: HashSet, - circuit: Circuit, + circuit: Circuit, } -impl UnusedMemoryOptimizer { +impl UnusedMemoryOptimizer { /// Creates a new `UnusedMemoryOptimizer ` by collecting unused memory init /// opcodes from `Circuit`. - pub(crate) fn new(circuit: Circuit) -> Self { + pub(crate) fn new(circuit: Circuit) -> Self { let unused_memory_initializations = Self::collect_unused_memory_initializations(&circuit); Self { circuit, unused_memory_initializations } } @@ -18,7 +18,7 @@ impl UnusedMemoryOptimizer { /// Creates a set of ids for memory blocks for which no [`Opcode::MemoryOp`]s exist. /// /// These memory blocks can be safely removed. - fn collect_unused_memory_initializations(circuit: &Circuit) -> HashSet { + fn collect_unused_memory_initializations(circuit: &Circuit) -> HashSet { let mut unused_memory_initialization = HashSet::new(); for opcode in &circuit.opcodes { @@ -39,13 +39,14 @@ impl UnusedMemoryOptimizer { pub(crate) fn remove_unused_memory_initializations( self, order_list: Vec, - ) -> (Circuit, Vec) { + ) -> (Circuit, Vec) { let mut new_order_list = Vec::with_capacity(order_list.len()); let mut optimized_opcodes = Vec::with_capacity(self.circuit.opcodes.len()); for (idx, opcode) in self.circuit.opcodes.into_iter().enumerate() { match opcode { - Opcode::MemoryInit { block_id, .. } - if self.unused_memory_initializations.contains(&block_id) => + Opcode::MemoryInit { block_id, block_type, .. } + if !block_type.is_databus() + && self.unused_memory_initializations.contains(&block_id) => { // Drop opcode } diff --git a/acvm-repo/acvm/src/compiler/transformers/csat.rs b/acvm-repo/acvm/src/compiler/transformers/csat.rs index 9e2e3091c74..f2a3cc2c84e 100644 --- a/acvm-repo/acvm/src/compiler/transformers/csat.rs +++ b/acvm-repo/acvm/src/compiler/transformers/csat.rs @@ -2,7 +2,7 @@ use std::{cmp::Ordering, collections::HashSet}; use acir::{ native_types::{Expression, Witness}, - FieldElement, + AcirField, }; use indexmap::IndexMap; @@ -30,7 +30,7 @@ impl CSatTransformer { } /// Check if the equation 'expression=0' can be solved, and if yes, add the solved witness to set of solvable witness - fn try_solve(&mut self, opcode: &Expression) { + fn try_solve(&mut self, opcode: &Expression) { let mut unresolved = Vec::new(); for (_, w1, w2) in &opcode.mul_terms { if !self.solvable_witness.contains(w1) { @@ -64,12 +64,12 @@ impl CSatTransformer { // Still missing dead witness optimization. // To do this, we will need the whole set of assert-zero opcodes // I think it can also be done before the local optimization seen here, as dead variables will come from the user - pub(crate) fn transform( + pub(crate) fn transform( &mut self, - opcode: Expression, - intermediate_variables: &mut IndexMap, + opcode: Expression, + intermediate_variables: &mut IndexMap, (F, Witness)>, num_witness: &mut u32, - ) -> Expression { + ) -> Expression { // Here we create intermediate variables and constrain them to be equal to any subset of the polynomial that can be represented as a full opcode let opcode = self.full_opcode_scan_optimization(opcode, intermediate_variables, num_witness); @@ -107,12 +107,12 @@ impl CSatTransformer { // The polynomial now looks like so t + t2 // We can no longer extract another full opcode, hence the algorithm terminates. Creating two intermediate variables t and t2. // This stage of preprocessing does not guarantee that all polynomials can fit into a opcode. It only guarantees that all full opcodes have been extracted from each polynomial - fn full_opcode_scan_optimization( + fn full_opcode_scan_optimization( &mut self, - mut opcode: Expression, - intermediate_variables: &mut IndexMap, + mut opcode: Expression, + intermediate_variables: &mut IndexMap, (F, Witness)>, num_witness: &mut u32, - ) -> Expression { + ) -> Expression { // We pass around this intermediate variable IndexMap, so that we do not create intermediate variables that we have created before // One instance where this might happen is t1 = wL * wR and t2 = wR * wL @@ -210,16 +210,16 @@ impl CSatTransformer { } } else { // No more usable elements left in the old opcode - opcode.linear_combinations = remaining_linear_terms; break; } } + opcode.linear_combinations.extend(remaining_linear_terms); + // Constraint this intermediate_opcode to be equal to the temp variable by adding it into the IndexMap // We need a unique name for our intermediate variable // XXX: Another optimization, which could be applied in another algorithm // If two opcodes have a large fan-in/out and they share a few common terms, then we should create intermediate variables for them // Do some sort of subset matching algorithm for this on the terms of the polynomial - let inter_var = Self::get_or_create_intermediate_vars( intermediate_variables, intermediate_opcode, @@ -245,7 +245,7 @@ impl CSatTransformer { /// Normalize an expression by dividing it by its first coefficient /// The first coefficient here means coefficient of the first linear term, or of the first quadratic term if no linear terms exist. /// The function panic if the input expression is constant - fn normalize(mut expr: Expression) -> (FieldElement, Expression) { + fn normalize(mut expr: Expression) -> (F, Expression) { expr.sort(); let a = if !expr.linear_combinations.is_empty() { expr.linear_combinations[0].0 @@ -259,11 +259,11 @@ impl CSatTransformer { /// The sets of previously generated witness and their (normalized) expression is cached in the intermediate_variables map /// If there is no cache hit, we generate a new witness (and add the expression to the cache) /// else, we return the cached witness along with the scaling factor so it is equal to the provided expression - fn get_or_create_intermediate_vars( - intermediate_variables: &mut IndexMap, - expr: Expression, + fn get_or_create_intermediate_vars( + intermediate_variables: &mut IndexMap, (F, Witness)>, + expr: Expression, num_witness: &mut u32, - ) -> (FieldElement, Witness) { + ) -> (F, Witness) { let (k, normalized_expr) = Self::normalize(expr); if intermediate_variables.contains_key(&normalized_expr) { @@ -274,7 +274,7 @@ impl CSatTransformer { *num_witness += 1; // Add intermediate opcode and variable to map intermediate_variables.insert(normalized_expr, (k, inter_var)); - (FieldElement::one(), inter_var) + (F::one(), inter_var) } } @@ -315,18 +315,18 @@ impl CSatTransformer { // Also remember that since we did full opcode scan, there is no way we can have a non-zero mul term along with the wL and wR terms being non-zero // // Cases, a lot of mul terms, a lot of fan-in terms, 50/50 - fn partial_opcode_scan_optimization( + fn partial_opcode_scan_optimization( &mut self, - mut opcode: Expression, - intermediate_variables: &mut IndexMap, + mut opcode: Expression, + intermediate_variables: &mut IndexMap, (F, Witness)>, num_witness: &mut u32, - ) -> Expression { + ) -> Expression { // We will go for the easiest route, which is to convert all multiplications into additions using intermediate variables // Then use intermediate variables again to squash the fan-in, so that it can fit into the appropriate width // First check if this polynomial actually needs a partial opcode optimization // There is the chance that it fits perfectly within the assert-zero opcode - if opcode.fits_in_one_identity(self.width) { + if fits_in_one_identity(&opcode, self.width) { return opcode; } @@ -409,101 +409,168 @@ impl CSatTransformer { } } -#[test] -fn simple_reduction_smoke_test() { - let a = Witness(0); - let b = Witness(1); - let c = Witness(2); - let d = Witness(3); - - // a = b + c + d; - let opcode_a = Expression { - mul_terms: vec![], - linear_combinations: vec![ - (FieldElement::one(), a), - (-FieldElement::one(), b), - (-FieldElement::one(), c), - (-FieldElement::one(), d), - ], - q_c: FieldElement::zero(), +/// Checks if this expression can fit into one arithmetic identity +fn fits_in_one_identity(expr: &Expression, width: usize) -> bool { + // A Polynomial with more than one mul term cannot fit into one opcode + if expr.mul_terms.len() > 1 { + return false; }; + // A Polynomial with more terms than fan-in cannot fit within a single opcode + if expr.linear_combinations.len() > width { + return false; + } - let mut intermediate_variables: IndexMap = IndexMap::new(); + // A polynomial with no mul term and a fan-in that fits inside of the width can fit into a single opcode + if expr.mul_terms.is_empty() { + return true; + } - let mut num_witness = 4; + // A polynomial with width-2 fan-in terms and a single non-zero mul term can fit into one opcode + // Example: Axy + Dz . Notice, that the mul term places a constraint on the first two terms, but not the last term + // XXX: This would change if our arithmetic polynomial equation was changed to Axyz for example, but for now it is not. + if expr.linear_combinations.len() <= (width - 2) { + return true; + } - let mut optimizer = CSatTransformer::new(3); - optimizer.mark_solvable(b); - optimizer.mark_solvable(c); - optimizer.mark_solvable(d); - let got_optimized_opcode_a = - optimizer.transform(opcode_a, &mut intermediate_variables, &mut num_witness); + // We now know that we have a single mul term. We also know that the mul term must match up with two other terms + // A polynomial whose mul terms are non zero which do not match up with two terms in the fan-in cannot fit into one opcode + // An example of this is: Axy + Bx + Cy + ... + // Notice how the bivariate monomial xy has two univariate monomials with their respective coefficients + // XXX: note that if x or y is zero, then we could apply a further optimization, but this would be done in another algorithm. + // It would be the same as when we have zero coefficients - Can only work if wire is constrained to be zero publicly + let mul_term = &expr.mul_terms[0]; + + // The coefficient should be non-zero, as this method is ran after the compiler removes all zero coefficient terms + assert_ne!(mul_term.0, F::zero()); + + let mut found_x = false; + let mut found_y = false; + + for term in expr.linear_combinations.iter() { + let witness = &term.1; + let x = &mul_term.1; + let y = &mul_term.2; + if witness == x { + found_x = true; + }; + if witness == y { + found_y = true; + }; + if found_x & found_y { + break; + } + } - // a = b + c + d => a - b - c - d = 0 - // For width3, the result becomes: - // a - d + e = 0 - // - c - b - e = 0 - // - // a - b + e = 0 - let e = Witness(4); - let expected_optimized_opcode_a = Expression { - mul_terms: vec![], - linear_combinations: vec![ - (FieldElement::one(), a), - (-FieldElement::one(), d), - (FieldElement::one(), e), - ], - q_c: FieldElement::zero(), - }; - assert_eq!(expected_optimized_opcode_a, got_optimized_opcode_a); + found_x & found_y +} - assert_eq!(intermediate_variables.len(), 1); +#[cfg(test)] +mod tests { + use super::*; + use acir::{AcirField, FieldElement}; + + #[test] + fn simple_reduction_smoke_test() { + let a = Witness(0); + let b = Witness(1); + let c = Witness(2); + let d = Witness(3); + + // a = b + c + d; + let opcode_a = Expression { + mul_terms: vec![], + linear_combinations: vec![ + (FieldElement::one(), a), + (-FieldElement::one(), b), + (-FieldElement::one(), c), + (-FieldElement::one(), d), + ], + q_c: FieldElement::zero(), + }; - // e = - c - b - let expected_intermediate_opcode = Expression { - mul_terms: vec![], - linear_combinations: vec![(-FieldElement::one(), c), (-FieldElement::one(), b)], - q_c: FieldElement::zero(), - }; - let (_, normalized_opcode) = CSatTransformer::normalize(expected_intermediate_opcode); - assert!(intermediate_variables.contains_key(&normalized_opcode)); - assert_eq!(intermediate_variables[&normalized_opcode].1, e); -} + let mut intermediate_variables: IndexMap< + Expression, + (FieldElement, Witness), + > = IndexMap::new(); -#[test] -fn stepwise_reduction_test() { - let a = Witness(0); - let b = Witness(1); - let c = Witness(2); - let d = Witness(3); - let e = Witness(4); - - // a = b + c + d + e; - let opcode_a = Expression { - mul_terms: vec![], - linear_combinations: vec![ - (-FieldElement::one(), a), - (FieldElement::one(), b), - (FieldElement::one(), c), - (FieldElement::one(), d), - (FieldElement::one(), e), - ], - q_c: FieldElement::zero(), - }; + let mut num_witness = 4; - let mut intermediate_variables: IndexMap = IndexMap::new(); + let mut optimizer = CSatTransformer::new(3); + optimizer.mark_solvable(b); + optimizer.mark_solvable(c); + optimizer.mark_solvable(d); + let got_optimized_opcode_a = + optimizer.transform(opcode_a, &mut intermediate_variables, &mut num_witness); - let mut num_witness = 4; + // a = b + c + d => a - b - c - d = 0 + // For width3, the result becomes: + // a - d + e = 0 + // - c - b - e = 0 + // + // a - b + e = 0 + let e = Witness(4); + let expected_optimized_opcode_a = Expression { + mul_terms: vec![], + linear_combinations: vec![ + (FieldElement::one(), a), + (-FieldElement::one(), d), + (FieldElement::one(), e), + ], + q_c: FieldElement::zero(), + }; + assert_eq!(expected_optimized_opcode_a, got_optimized_opcode_a); - let mut optimizer = CSatTransformer::new(3); - optimizer.mark_solvable(a); - optimizer.mark_solvable(c); - optimizer.mark_solvable(d); - optimizer.mark_solvable(e); - let got_optimized_opcode_a = - optimizer.transform(opcode_a, &mut intermediate_variables, &mut num_witness); + assert_eq!(intermediate_variables.len(), 1); + + // e = - c - b + let expected_intermediate_opcode = Expression { + mul_terms: vec![], + linear_combinations: vec![(-FieldElement::one(), c), (-FieldElement::one(), b)], + q_c: FieldElement::zero(), + }; + let (_, normalized_opcode) = CSatTransformer::normalize(expected_intermediate_opcode); + assert!(intermediate_variables.contains_key(&normalized_opcode)); + assert_eq!(intermediate_variables[&normalized_opcode].1, e); + } - // Since b is not known, it cannot be put inside intermediate opcodes, so it must belong to the transformed opcode. - let contains_b = got_optimized_opcode_a.linear_combinations.iter().any(|(_, w)| *w == b); - assert!(contains_b); + #[test] + fn stepwise_reduction_test() { + let a = Witness(0); + let b = Witness(1); + let c = Witness(2); + let d = Witness(3); + let e = Witness(4); + + // a = b + c + d + e; + let opcode_a = Expression { + mul_terms: vec![], + linear_combinations: vec![ + (-FieldElement::one(), a), + (FieldElement::one(), b), + (FieldElement::one(), c), + (FieldElement::one(), d), + (FieldElement::one(), e), + ], + q_c: FieldElement::zero(), + }; + + let mut intermediate_variables: IndexMap< + Expression, + (FieldElement, Witness), + > = IndexMap::new(); + + let mut num_witness = 4; + + let mut optimizer = CSatTransformer::new(3); + optimizer.mark_solvable(a); + optimizer.mark_solvable(c); + optimizer.mark_solvable(d); + optimizer.mark_solvable(e); + let got_optimized_opcode_a = + optimizer.transform(opcode_a, &mut intermediate_variables, &mut num_witness); + + // Since b is not known, it cannot be put inside intermediate opcodes, so it must belong to the transformed opcode. + let contains_b = got_optimized_opcode_a.linear_combinations.iter().any(|(_, w)| *w == b); + assert!(contains_b); + } } diff --git a/acvm-repo/acvm/src/compiler/transformers/mod.rs b/acvm-repo/acvm/src/compiler/transformers/mod.rs index 214243d9360..4fd8ba7883f 100644 --- a/acvm-repo/acvm/src/compiler/transformers/mod.rs +++ b/acvm-repo/acvm/src/compiler/transformers/mod.rs @@ -1,23 +1,21 @@ use acir::{ circuit::{brillig::BrilligOutputs, directives::Directive, Circuit, ExpressionWidth, Opcode}, native_types::{Expression, Witness}, - FieldElement, + AcirField, }; use indexmap::IndexMap; mod csat; -mod r1cs; pub(crate) use csat::CSatTransformer; -pub(crate) use r1cs::R1CSTransformer; use super::{transform_assert_messages, AcirTransformationMap}; /// Applies [`ProofSystemCompiler`][crate::ProofSystemCompiler] specific optimizations to a [`Circuit`]. -pub fn transform( - acir: Circuit, +pub fn transform( + acir: Circuit, expression_width: ExpressionWidth, -) -> (Circuit, AcirTransformationMap) { +) -> (Circuit, AcirTransformationMap) { // Track original acir opcode positions throughout the transformation passes of the compilation // by applying the modifications done to the circuit opcodes and also to the opcode_positions (delete and insert) let acir_opcode_positions = acir.opcodes.iter().enumerate().map(|(i, _)| i).collect(); @@ -36,15 +34,14 @@ pub fn transform( /// /// Accepts an injected `acir_opcode_positions` to allow transformations to be applied directly after optimizations. #[tracing::instrument(level = "trace", name = "transform_acir", skip(acir, acir_opcode_positions))] -pub(super) fn transform_internal( - acir: Circuit, +pub(super) fn transform_internal( + acir: Circuit, expression_width: ExpressionWidth, acir_opcode_positions: Vec, -) -> (Circuit, Vec) { +) -> (Circuit, Vec) { let mut transformer = match &expression_width { ExpressionWidth::Unbounded => { - let transformer = R1CSTransformer::new(acir); - return (transformer.transform(), acir_opcode_positions); + return (acir, acir_opcode_positions); } ExpressionWidth::Bounded { width } => { let mut csat = CSatTransformer::new(*width); @@ -67,7 +64,7 @@ pub(super) fn transform_internal( let mut next_witness_index = acir.current_witness_index + 1; // maps a normalized expression to the intermediate variable which represents the expression, along with its 'norm' // the 'norm' is simply the value of the first non zero coefficient in the expression, taken from the linear terms, or quadratic terms if there is none. - let mut intermediate_variables: IndexMap = IndexMap::new(); + let mut intermediate_variables: IndexMap, (F, Witness)> = IndexMap::new(); for (index, opcode) in acir.opcodes.into_iter().enumerate() { match opcode { Opcode::AssertZero(arith_expr) => { @@ -86,7 +83,7 @@ pub(super) fn transform_internal( // de-normalize let mut intermediate_opcode = g * *norm; // constrain the intermediate opcode to the intermediate variable - intermediate_opcode.linear_combinations.push((-FieldElement::one(), *w)); + intermediate_opcode.linear_combinations.push((-F::one(), *w)); intermediate_opcode.sort(); new_opcodes.push(intermediate_opcode); } @@ -131,8 +128,8 @@ pub(super) fn transform_internal( new_acir_opcode_positions.push(acir_opcode_positions[index]); transformed_opcodes.push(opcode); } - Opcode::Brillig(ref brillig) => { - for output in &brillig.outputs { + Opcode::BrilligCall { ref outputs, .. } => { + for output in outputs { match output { BrilligOutputs::Simple(w) => transformer.mark_solvable(*w), BrilligOutputs::Array(v) => { @@ -142,6 +139,17 @@ pub(super) fn transform_internal( } } } + + new_acir_opcode_positions.push(acir_opcode_positions[index]); + transformed_opcodes.push(opcode); + } + Opcode::Call { ref outputs, .. } => { + for witness in outputs { + transformer.mark_solvable(*witness); + } + + // `Call` does not write values to the `WitnessMap` + // A separate ACIR function should have its own respective `WitnessMap` new_acir_opcode_positions.push(acir_opcode_positions[index]); transformed_opcodes.push(opcode); } diff --git a/acvm-repo/acvm/src/compiler/transformers/r1cs.rs b/acvm-repo/acvm/src/compiler/transformers/r1cs.rs deleted file mode 100644 index 3bdd29c9c53..00000000000 --- a/acvm-repo/acvm/src/compiler/transformers/r1cs.rs +++ /dev/null @@ -1,16 +0,0 @@ -use acir::circuit::Circuit; - -/// Currently a "noop" transformer. -pub(crate) struct R1CSTransformer { - acir: Circuit, -} - -impl R1CSTransformer { - pub(crate) fn new(acir: Circuit) -> Self { - Self { acir } - } - // TODO: We could possibly make sure that all polynomials are at most degree-2 - pub(crate) fn transform(self) -> Circuit { - self.acir - } -} diff --git a/acvm-repo/acvm/src/lib.rs b/acvm-repo/acvm/src/lib.rs index 00a253fde07..4c64e1da749 100644 --- a/acvm-repo/acvm/src/lib.rs +++ b/acvm-repo/acvm/src/lib.rs @@ -11,7 +11,7 @@ use pwg::OpcodeResolutionError; // re-export acir pub use acir; -pub use acir::FieldElement; +pub use acir::{AcirField, FieldElement}; // re-export brillig vm pub use brillig_vm; // re-export blackbox solver diff --git a/acvm-repo/acvm/src/pwg/arithmetic.rs b/acvm-repo/acvm/src/pwg/arithmetic.rs index 81462ea495e..5eeabd8a833 100644 --- a/acvm-repo/acvm/src/pwg/arithmetic.rs +++ b/acvm-repo/acvm/src/pwg/arithmetic.rs @@ -1,36 +1,41 @@ use acir::{ native_types::{Expression, Witness, WitnessMap}, - FieldElement, + AcirField, }; use super::{insert_value, ErrorLocation, OpcodeNotSolvable, OpcodeResolutionError}; /// An Expression solver will take a Circuit's assert-zero opcodes with witness assignments /// and create the other witness variables -pub(super) struct ExpressionSolver; +pub(crate) struct ExpressionSolver; #[allow(clippy::enum_variant_names)] -pub(super) enum OpcodeStatus { - OpcodeSatisfied(FieldElement), - OpcodeSolvable(FieldElement, (FieldElement, Witness)), +pub(super) enum OpcodeStatus { + OpcodeSatisfied(F), + OpcodeSolvable(F, (F, Witness)), OpcodeUnsolvable, } -pub(crate) enum MulTerm { - OneUnknown(FieldElement, Witness), // (qM * known_witness, unknown_witness) +pub(crate) enum MulTerm { + OneUnknown(F, Witness), // (qM * known_witness, unknown_witness) TooManyUnknowns, - Solved(FieldElement), + Solved(F), } impl ExpressionSolver { /// Derives the rest of the witness based on the initial low level variables - pub(super) fn solve( - initial_witness: &mut WitnessMap, - opcode: &Expression, - ) -> Result<(), OpcodeResolutionError> { + pub(crate) fn solve( + initial_witness: &mut WitnessMap, + opcode: &Expression, + ) -> Result<(), OpcodeResolutionError> { let opcode = &ExpressionSolver::evaluate(opcode, initial_witness); // Evaluate multiplication term - let mul_result = ExpressionSolver::solve_mul_term(opcode, initial_witness); + let mul_result = + ExpressionSolver::solve_mul_term(opcode, initial_witness).map_err(|_| { + OpcodeResolutionError::OpcodeNotSolvable( + OpcodeNotSolvable::ExpressionHasTooManyUnknowns(opcode.clone()), + ) + })?; // Evaluate the fan-in terms let opcode_status = ExpressionSolver::solve_fan_in_term(opcode, initial_witness); @@ -48,15 +53,14 @@ impl ExpressionSolver { if !total_sum.is_zero() { Err(OpcodeResolutionError::UnsatisfiedConstrain { opcode_location: ErrorLocation::Unresolved, + payload: None, }) } else { Ok(()) } } else { let assignment = -total_sum / (q + b); - // Add this into the witness assignments - insert_value(&w1, assignment, initial_witness)?; - Ok(()) + insert_value(&w1, assignment, initial_witness) } } else { // TODO: can we be more specific with this error? @@ -78,15 +82,14 @@ impl ExpressionSolver { if !total_sum.is_zero() { Err(OpcodeResolutionError::UnsatisfiedConstrain { opcode_location: ErrorLocation::Unresolved, + payload: None, }) } else { Ok(()) } } else { let assignment = -(total_sum / partial_prod); - // Add this into the witness assignments - insert_value(&unknown_var, assignment, initial_witness)?; - Ok(()) + insert_value(&unknown_var, assignment, initial_witness) } } (MulTerm::Solved(a), OpcodeStatus::OpcodeSatisfied(b)) => { @@ -95,6 +98,7 @@ impl ExpressionSolver { if !(a + b + opcode.q_c).is_zero() { Err(OpcodeResolutionError::UnsatisfiedConstrain { opcode_location: ErrorLocation::Unresolved, + payload: None, }) } else { Ok(()) @@ -112,15 +116,14 @@ impl ExpressionSolver { if !total_sum.is_zero() { Err(OpcodeResolutionError::UnsatisfiedConstrain { opcode_location: ErrorLocation::Unresolved, + payload: None, }) } else { Ok(()) } } else { let assignment = -(total_sum / coeff); - // Add this into the witness assignments - insert_value(&unknown_var, assignment, initial_witness)?; - Ok(()) + insert_value(&unknown_var, assignment, initial_witness) } } } @@ -130,23 +133,26 @@ impl ExpressionSolver { /// If the witness values are not known, then the function returns a None /// XXX: Do we need to account for the case where 5xy + 6x = 0 ? We do not know y, but it can be solved given x . But I believe x can be solved with another opcode /// XXX: What about making a mul opcode = a constant 5xy + 7 = 0 ? This is the same as the above. - fn solve_mul_term(arith_opcode: &Expression, witness_assignments: &WitnessMap) -> MulTerm { + fn solve_mul_term( + arith_opcode: &Expression, + witness_assignments: &WitnessMap, + ) -> Result, OpcodeStatus> { // First note that the mul term can only contain one/zero term // We are assuming it has been optimized. match arith_opcode.mul_terms.len() { - 0 => MulTerm::Solved(FieldElement::zero()), - 1 => ExpressionSolver::solve_mul_term_helper( + 0 => Ok(MulTerm::Solved(F::zero())), + 1 => Ok(ExpressionSolver::solve_mul_term_helper( &arith_opcode.mul_terms[0], witness_assignments, - ), - _ => panic!("Mul term in the assert-zero opcode must contain either zero or one term"), + )), + _ => Err(OpcodeStatus::OpcodeUnsolvable), } } - fn solve_mul_term_helper( - term: &(FieldElement, Witness, Witness), - witness_assignments: &WitnessMap, - ) -> MulTerm { + fn solve_mul_term_helper( + term: &(F, Witness, Witness), + witness_assignments: &WitnessMap, + ) -> MulTerm { let (q_m, w_l, w_r) = term; // Check if these values are in the witness assignments let w_l_value = witness_assignments.get(w_l); @@ -160,10 +166,10 @@ impl ExpressionSolver { } } - fn solve_fan_in_term_helper( - term: &(FieldElement, Witness), - witness_assignments: &WitnessMap, - ) -> Option { + fn solve_fan_in_term_helper( + term: &(F, Witness), + witness_assignments: &WitnessMap, + ) -> Option { let (q_l, w_l) = term; // Check if we have w_l let w_l_value = witness_assignments.get(w_l); @@ -173,17 +179,17 @@ impl ExpressionSolver { /// Returns the summation of all of the variables, plus the unknown variable /// Returns None, if there is more than one unknown variable /// We cannot assign - pub(super) fn solve_fan_in_term( - arith_opcode: &Expression, - witness_assignments: &WitnessMap, - ) -> OpcodeStatus { + pub(super) fn solve_fan_in_term( + arith_opcode: &Expression, + witness_assignments: &WitnessMap, + ) -> OpcodeStatus { // This is assuming that the fan-in is more than 0 // This is the variable that we want to assign the value to - let mut unknown_variable = (FieldElement::zero(), Witness::default()); + let mut unknown_variable = (F::zero(), Witness::default()); let mut num_unknowns = 0; // This is the sum of all of the known variables - let mut result = FieldElement::zero(); + let mut result = F::zero(); for term in arith_opcode.linear_combinations.iter() { let value = ExpressionSolver::solve_fan_in_term_helper(term, witness_assignments); @@ -209,7 +215,10 @@ impl ExpressionSolver { } // Partially evaluate the opcode using the known witnesses - pub(super) fn evaluate(expr: &Expression, initial_witness: &WitnessMap) -> Expression { + pub(crate) fn evaluate( + expr: &Expression, + initial_witness: &WitnessMap, + ) -> Expression { let mut result = Expression::default(); for &(c, w1, w2) in &expr.mul_terms { let mul_result = ExpressionSolver::solve_mul_term_helper(&(c, w1, w2), initial_witness); @@ -239,43 +248,49 @@ impl ExpressionSolver { } } -#[test] -fn expression_solver_smoke_test() { - let a = Witness(0); - let b = Witness(1); - let c = Witness(2); - let d = Witness(3); +#[cfg(test)] +mod tests { + use super::*; + use acir::FieldElement; + + #[test] + fn expression_solver_smoke_test() { + let a = Witness(0); + let b = Witness(1); + let c = Witness(2); + let d = Witness(3); - // a = b + c + d; - let opcode_a = Expression { - mul_terms: vec![], - linear_combinations: vec![ - (FieldElement::one(), a), - (-FieldElement::one(), b), - (-FieldElement::one(), c), - (-FieldElement::one(), d), - ], - q_c: FieldElement::zero(), - }; + // a = b + c + d; + let opcode_a = Expression { + mul_terms: vec![], + linear_combinations: vec![ + (FieldElement::one(), a), + (-FieldElement::one(), b), + (-FieldElement::one(), c), + (-FieldElement::one(), d), + ], + q_c: FieldElement::zero(), + }; - let e = Witness(4); - let opcode_b = Expression { - mul_terms: vec![], - linear_combinations: vec![ - (FieldElement::one(), e), - (-FieldElement::one(), a), - (-FieldElement::one(), b), - ], - q_c: FieldElement::zero(), - }; + let e = Witness(4); + let opcode_b = Expression { + mul_terms: vec![], + linear_combinations: vec![ + (FieldElement::one(), e), + (-FieldElement::one(), a), + (-FieldElement::one(), b), + ], + q_c: FieldElement::zero(), + }; - let mut values = WitnessMap::new(); - values.insert(b, FieldElement::from(2_i128)); - values.insert(c, FieldElement::from(1_i128)); - values.insert(d, FieldElement::from(1_i128)); + let mut values = WitnessMap::new(); + values.insert(b, FieldElement::from(2_i128)); + values.insert(c, FieldElement::from(1_i128)); + values.insert(d, FieldElement::from(1_i128)); - assert_eq!(ExpressionSolver::solve(&mut values, &opcode_a), Ok(())); - assert_eq!(ExpressionSolver::solve(&mut values, &opcode_b), Ok(())); + assert_eq!(ExpressionSolver::solve(&mut values, &opcode_a), Ok(())); + assert_eq!(ExpressionSolver::solve(&mut values, &opcode_b), Ok(())); - assert_eq!(values.get(&a).unwrap(), &FieldElement::from(4_i128)); + assert_eq!(values.get(&a).unwrap(), &FieldElement::from(4_i128)); + } } diff --git a/acvm-repo/acvm/src/pwg/blackbox/aes128.rs b/acvm-repo/acvm/src/pwg/blackbox/aes128.rs new file mode 100644 index 00000000000..181a78a2a6a --- /dev/null +++ b/acvm-repo/acvm/src/pwg/blackbox/aes128.rs @@ -0,0 +1,32 @@ +use acir::{ + circuit::opcodes::FunctionInput, + native_types::{Witness, WitnessMap}, + AcirField, +}; +use acvm_blackbox_solver::aes128_encrypt; + +use crate::{pwg::insert_value, OpcodeResolutionError}; + +use super::utils::{to_u8_array, to_u8_vec}; + +pub(super) fn solve_aes128_encryption_opcode( + initial_witness: &mut WitnessMap, + inputs: &[FunctionInput], + iv: &[FunctionInput; 16], + key: &[FunctionInput; 16], + outputs: &[Witness], +) -> Result<(), OpcodeResolutionError> { + let scalars = to_u8_vec(initial_witness, inputs)?; + + let iv = to_u8_array(initial_witness, iv)?; + let key = to_u8_array(initial_witness, key)?; + + let ciphertext = aes128_encrypt(&scalars, iv, key)?; + + // Write witness assignments + for (output_witness, value) in outputs.iter().zip(ciphertext.into_iter()) { + insert_value(output_witness, F::from(value as u128), initial_witness)?; + } + + Ok(()) +} diff --git a/acvm-repo/acvm/src/pwg/blackbox/bigint.rs b/acvm-repo/acvm/src/pwg/blackbox/bigint.rs index f094bb1ba20..be5a4613a55 100644 --- a/acvm-repo/acvm/src/pwg/blackbox/bigint.rs +++ b/acvm-repo/acvm/src/pwg/blackbox/bigint.rs @@ -1,120 +1,62 @@ -use std::collections::HashMap; - use acir::{ circuit::opcodes::FunctionInput, native_types::{Witness, WitnessMap}, - BlackBoxFunc, FieldElement, + AcirField, BlackBoxFunc, }; -use num_bigint::BigUint; +use acvm_blackbox_solver::BigIntSolver; use crate::pwg::OpcodeResolutionError; -/// Resolve BigInt opcodes by storing BigInt values (and their moduli) by their ID in a HashMap: +/// Resolve BigInt opcodes by storing BigInt values (and their moduli) by their ID in the BigIntSolver /// - When it encounters a bigint operation opcode, it performs the operation on the stored values /// and store the result using the provided ID. /// - When it gets a to_bytes opcode, it simply looks up the value and resolves the output witness accordingly. #[derive(Default)] -pub(crate) struct BigIntSolver { - bigint_id_to_value: HashMap, - bigint_id_to_modulus: HashMap, +pub(crate) struct AcvmBigIntSolver { + bigint_solver: BigIntSolver, } -impl BigIntSolver { - pub(crate) fn get_bigint( - &self, - id: u32, - func: BlackBoxFunc, - ) -> Result { - self.bigint_id_to_value - .get(&id) - .ok_or(OpcodeResolutionError::BlackBoxFunctionFailed( - func, - format!("could not find bigint of id {id}"), - )) - .cloned() - } - - pub(crate) fn get_modulus( - &self, - id: u32, - func: BlackBoxFunc, - ) -> Result { - self.bigint_id_to_modulus - .get(&id) - .ok_or(OpcodeResolutionError::BlackBoxFunctionFailed( - func, - format!("could not find bigint of id {id}"), - )) - .cloned() - } - pub(crate) fn bigint_from_bytes( +impl AcvmBigIntSolver { + pub(crate) fn bigint_from_bytes( &mut self, inputs: &[FunctionInput], modulus: &[u8], output: u32, - initial_witness: &mut WitnessMap, - ) -> Result<(), OpcodeResolutionError> { + initial_witness: &mut WitnessMap, + ) -> Result<(), OpcodeResolutionError> { let bytes = inputs .iter() .map(|input| initial_witness.get(&input.witness).unwrap().to_u128() as u8) .collect::>(); - let bigint = BigUint::from_bytes_le(&bytes); - self.bigint_id_to_value.insert(output, bigint); - let modulus = BigUint::from_bytes_le(modulus); - self.bigint_id_to_modulus.insert(output, modulus); + self.bigint_solver.bigint_from_bytes(&bytes, modulus, output)?; Ok(()) } - pub(crate) fn bigint_to_bytes( + pub(crate) fn bigint_to_bytes( &self, input: u32, outputs: &[Witness], - initial_witness: &mut WitnessMap, - ) -> Result<(), OpcodeResolutionError> { - let bigint = self.get_bigint(input, BlackBoxFunc::BigIntToLeBytes)?; - - let mut bytes = bigint.to_bytes_le(); + initial_witness: &mut WitnessMap, + ) -> Result<(), OpcodeResolutionError> { + let mut bytes = self.bigint_solver.bigint_to_bytes(input)?; while bytes.len() < outputs.len() { bytes.push(0); } bytes.iter().zip(outputs.iter()).for_each(|(byte, output)| { - initial_witness.insert(*output, FieldElement::from(*byte as u128)); + initial_witness.insert(*output, F::from(*byte as u128)); }); Ok(()) } - pub(crate) fn bigint_op( + pub(crate) fn bigint_op( &mut self, lhs: u32, rhs: u32, output: u32, func: BlackBoxFunc, - ) -> Result<(), OpcodeResolutionError> { - let modulus = self.get_modulus(lhs, func)?; - let lhs = self.get_bigint(lhs, func)?; - let rhs = self.get_bigint(rhs, func)?; - let mut result = match func { - BlackBoxFunc::BigIntAdd => lhs + rhs, - BlackBoxFunc::BigIntSub => { - if lhs >= rhs { - &lhs - &rhs - } else { - &lhs + &modulus - &rhs - } - } - BlackBoxFunc::BigIntMul => lhs * rhs, - BlackBoxFunc::BigIntDiv => { - lhs * rhs.modpow(&(&modulus - BigUint::from(1_u32)), &modulus) - } //TODO ensure that modulus is prime - _ => unreachable!("ICE - bigint_op must be called for an operation"), - }; - if result > modulus { - let q = &result / &modulus; - result -= q * &modulus; - } - self.bigint_id_to_value.insert(output, result); - self.bigint_id_to_modulus.insert(output, modulus); + ) -> Result<(), OpcodeResolutionError> { + self.bigint_solver.bigint_op(lhs, rhs, output, func)?; Ok(()) } } diff --git a/acvm-repo/acvm/src/pwg/blackbox/embedded_curve_ops.rs b/acvm-repo/acvm/src/pwg/blackbox/embedded_curve_ops.rs new file mode 100644 index 00000000000..411a6d1b737 --- /dev/null +++ b/acvm-repo/acvm/src/pwg/blackbox/embedded_curve_ops.rs @@ -0,0 +1,63 @@ +use acir::{ + circuit::opcodes::FunctionInput, + native_types::{Witness, WitnessMap}, + AcirField, +}; +use acvm_blackbox_solver::BlackBoxFunctionSolver; + +use crate::pwg::{insert_value, witness_to_value, OpcodeResolutionError}; + +pub(super) fn multi_scalar_mul( + backend: &impl BlackBoxFunctionSolver, + initial_witness: &mut WitnessMap, + points: &[FunctionInput], + scalars: &[FunctionInput], + outputs: (Witness, Witness, Witness), +) -> Result<(), OpcodeResolutionError> { + let points: Result, _> = + points.iter().map(|input| witness_to_value(initial_witness, input.witness)).collect(); + let points: Vec<_> = points?.into_iter().cloned().collect(); + + let scalars: Result, _> = + scalars.iter().map(|input| witness_to_value(initial_witness, input.witness)).collect(); + let mut scalars_lo = Vec::new(); + let mut scalars_hi = Vec::new(); + for (i, scalar) in scalars?.into_iter().enumerate() { + if i % 2 == 0 { + scalars_lo.push(*scalar); + } else { + scalars_hi.push(*scalar); + } + } + // Call the backend's multi-scalar multiplication function + let (res_x, res_y, is_infinite) = + backend.multi_scalar_mul(&points, &scalars_lo, &scalars_hi)?; + + // Insert the resulting point into the witness map + insert_value(&outputs.0, res_x, initial_witness)?; + insert_value(&outputs.1, res_y, initial_witness)?; + insert_value(&outputs.2, is_infinite, initial_witness)?; + Ok(()) +} + +pub(super) fn embedded_curve_add( + backend: &impl BlackBoxFunctionSolver, + initial_witness: &mut WitnessMap, + input1: [FunctionInput; 3], + input2: [FunctionInput; 3], + outputs: (Witness, Witness, Witness), +) -> Result<(), OpcodeResolutionError> { + let input1_x = witness_to_value(initial_witness, input1[0].witness)?; + let input1_y = witness_to_value(initial_witness, input1[1].witness)?; + let input1_infinite = witness_to_value(initial_witness, input1[2].witness)?; + let input2_x = witness_to_value(initial_witness, input2[0].witness)?; + let input2_y = witness_to_value(initial_witness, input2[1].witness)?; + let input2_infinite = witness_to_value(initial_witness, input2[2].witness)?; + let (res_x, res_y, res_infinite) = + backend.ec_add(input1_x, input1_y, input1_infinite, input2_x, input2_y, input2_infinite)?; + + insert_value(&outputs.0, res_x, initial_witness)?; + insert_value(&outputs.1, res_y, initial_witness)?; + insert_value(&outputs.2, res_infinite, initial_witness)?; + Ok(()) +} diff --git a/acvm-repo/acvm/src/pwg/blackbox/fixed_base_scalar_mul.rs b/acvm-repo/acvm/src/pwg/blackbox/fixed_base_scalar_mul.rs deleted file mode 100644 index c5bfd1d5646..00000000000 --- a/acvm-repo/acvm/src/pwg/blackbox/fixed_base_scalar_mul.rs +++ /dev/null @@ -1,46 +0,0 @@ -use acir::{ - circuit::opcodes::FunctionInput, - native_types::{Witness, WitnessMap}, -}; -use acvm_blackbox_solver::BlackBoxFunctionSolver; - -use crate::pwg::{insert_value, witness_to_value, OpcodeResolutionError}; - -pub(super) fn fixed_base_scalar_mul( - backend: &impl BlackBoxFunctionSolver, - initial_witness: &mut WitnessMap, - low: FunctionInput, - high: FunctionInput, - outputs: (Witness, Witness), -) -> Result<(), OpcodeResolutionError> { - let low = witness_to_value(initial_witness, low.witness)?; - let high = witness_to_value(initial_witness, high.witness)?; - - let (pub_x, pub_y) = backend.fixed_base_scalar_mul(low, high)?; - - insert_value(&outputs.0, pub_x, initial_witness)?; - insert_value(&outputs.1, pub_y, initial_witness)?; - - Ok(()) -} - -pub(super) fn embedded_curve_add( - backend: &impl BlackBoxFunctionSolver, - initial_witness: &mut WitnessMap, - input1_x: FunctionInput, - input1_y: FunctionInput, - input2_x: FunctionInput, - input2_y: FunctionInput, - outputs: (Witness, Witness), -) -> Result<(), OpcodeResolutionError> { - let input1_x = witness_to_value(initial_witness, input1_x.witness)?; - let input1_y = witness_to_value(initial_witness, input1_y.witness)?; - let input2_x = witness_to_value(initial_witness, input2_x.witness)?; - let input2_y = witness_to_value(initial_witness, input2_y.witness)?; - let (res_x, res_y) = backend.ec_add(input1_x, input1_y, input2_x, input2_y)?; - - insert_value(&outputs.0, res_x, initial_witness)?; - insert_value(&outputs.1, res_y, initial_witness)?; - - Ok(()) -} diff --git a/acvm-repo/acvm/src/pwg/blackbox/hash.rs b/acvm-repo/acvm/src/pwg/blackbox/hash.rs index 24c835a636a..fe9bd46b091 100644 --- a/acvm-repo/acvm/src/pwg/blackbox/hash.rs +++ b/acvm-repo/acvm/src/pwg/blackbox/hash.rs @@ -1,7 +1,7 @@ use acir::{ circuit::opcodes::FunctionInput, native_types::{Witness, WitnessMap}, - BlackBoxFunc, FieldElement, + AcirField, }; use acvm_blackbox_solver::{sha256compression, BlackBoxFunctionSolver, BlackBoxResolutionError}; @@ -10,34 +10,25 @@ use crate::OpcodeResolutionError; /// Attempts to solve a 256 bit hash function opcode. /// If successful, `initial_witness` will be mutated to contain the new witness assignment. -pub(super) fn solve_generic_256_hash_opcode( - initial_witness: &mut WitnessMap, +pub(super) fn solve_generic_256_hash_opcode( + initial_witness: &mut WitnessMap, inputs: &[FunctionInput], var_message_size: Option<&FunctionInput>, - outputs: &[Witness], + outputs: &[Witness; 32], hash_function: fn(data: &[u8]) -> Result<[u8; 32], BlackBoxResolutionError>, - black_box_func: BlackBoxFunc, -) -> Result<(), OpcodeResolutionError> { +) -> Result<(), OpcodeResolutionError> { let message_input = get_hash_input(initial_witness, inputs, var_message_size)?; let digest: [u8; 32] = hash_function(&message_input)?; - let outputs: [Witness; 32] = outputs.try_into().map_err(|_| { - OpcodeResolutionError::BlackBoxFunctionFailed( - black_box_func, - format!("Expected 32 outputs but encountered {}", outputs.len()), - ) - })?; - write_digest_to_outputs(initial_witness, outputs, digest)?; - - Ok(()) + write_digest_to_outputs(initial_witness, outputs, digest) } /// Reads the hash function input from a [`WitnessMap`]. -fn get_hash_input( - initial_witness: &WitnessMap, +fn get_hash_input( + initial_witness: &WitnessMap, inputs: &[FunctionInput], message_size: Option<&FunctionInput>, -) -> Result, OpcodeResolutionError> { +) -> Result, OpcodeResolutionError> { // Read witness assignments. let mut message_input = Vec::new(); for input in inputs.iter() { @@ -71,74 +62,55 @@ fn get_hash_input( } /// Writes a `digest` to the [`WitnessMap`] at witness indices `outputs`. -fn write_digest_to_outputs( - initial_witness: &mut WitnessMap, - outputs: [Witness; 32], +fn write_digest_to_outputs( + initial_witness: &mut WitnessMap, + outputs: &[Witness; 32], digest: [u8; 32], -) -> Result<(), OpcodeResolutionError> { +) -> Result<(), OpcodeResolutionError> { for (output_witness, value) in outputs.iter().zip(digest.into_iter()) { - insert_value( - output_witness, - FieldElement::from_be_bytes_reduce(&[value]), - initial_witness, - )?; + insert_value(output_witness, F::from_be_bytes_reduce(&[value]), initial_witness)?; } Ok(()) } -pub(crate) fn solve_sha_256_permutation_opcode( - initial_witness: &mut WitnessMap, - inputs: &[FunctionInput], - hash_values: &[FunctionInput], - outputs: &[Witness], - black_box_func: BlackBoxFunc, -) -> Result<(), OpcodeResolutionError> { - let mut message = [0; 16]; - if inputs.len() != 16 { - return Err(OpcodeResolutionError::BlackBoxFunctionFailed( - black_box_func, - format!("Expected 16 inputs but encountered {}", &message.len()), - )); - } - for (i, input) in inputs.iter().enumerate() { - let value = witness_to_value(initial_witness, input.witness)?; - message[i] = value.to_u128() as u32; +fn to_u32_array( + initial_witness: &WitnessMap, + inputs: &[FunctionInput; N], +) -> Result<[u32; N], OpcodeResolutionError> { + let mut result = [0; N]; + for (it, input) in result.iter_mut().zip(inputs) { + let witness_value = witness_to_value(initial_witness, input.witness)?; + *it = witness_value.to_u128() as u32; } + Ok(result) +} - if hash_values.len() != 8 { - return Err(OpcodeResolutionError::BlackBoxFunctionFailed( - black_box_func, - format!("Expected 8 values but encountered {}", hash_values.len()), - )); - } - let mut state = [0; 8]; - for (i, hash) in hash_values.iter().enumerate() { - let value = witness_to_value(initial_witness, hash.witness)?; - state[i] = value.to_u128() as u32; - } +pub(crate) fn solve_sha_256_permutation_opcode( + initial_witness: &mut WitnessMap, + inputs: &[FunctionInput; 16], + hash_values: &[FunctionInput; 8], + outputs: &[Witness; 8], +) -> Result<(), OpcodeResolutionError> { + let message = to_u32_array(initial_witness, inputs)?; + let mut state = to_u32_array(initial_witness, hash_values)?; sha256compression(&mut state, &message); - let outputs: [Witness; 8] = outputs.try_into().map_err(|_| { - OpcodeResolutionError::BlackBoxFunctionFailed( - black_box_func, - format!("Expected 8 outputs but encountered {}", outputs.len()), - ) - })?; + for (output_witness, value) in outputs.iter().zip(state.into_iter()) { - insert_value(output_witness, FieldElement::from(value as u128), initial_witness)?; + insert_value(output_witness, F::from(value as u128), initial_witness)?; } Ok(()) } -pub(crate) fn solve_poseidon2_permutation_opcode( - backend: &impl BlackBoxFunctionSolver, - initial_witness: &mut WitnessMap, +pub(crate) fn solve_poseidon2_permutation_opcode( + backend: &impl BlackBoxFunctionSolver, + initial_witness: &mut WitnessMap, inputs: &[FunctionInput], outputs: &[Witness], len: u32, -) -> Result<(), OpcodeResolutionError> { +) -> Result<(), OpcodeResolutionError> { if len as usize != inputs.len() { return Err(OpcodeResolutionError::BlackBoxFunctionFailed( acir::BlackBoxFunc::Poseidon2Permutation, diff --git a/acvm-repo/acvm/src/pwg/blackbox/logic.rs b/acvm-repo/acvm/src/pwg/blackbox/logic.rs index 8e69730f71d..6e2ade3c49b 100644 --- a/acvm-repo/acvm/src/pwg/blackbox/logic.rs +++ b/acvm-repo/acvm/src/pwg/blackbox/logic.rs @@ -3,17 +3,17 @@ use crate::OpcodeResolutionError; use acir::{ circuit::opcodes::FunctionInput, native_types::{Witness, WitnessMap}, - FieldElement, + AcirField, }; /// Solves a [`BlackBoxFunc::And`][acir::circuit::black_box_functions::BlackBoxFunc::AND] opcode and inserts /// the result into the supplied witness map -pub(super) fn and( - initial_witness: &mut WitnessMap, +pub(super) fn and( + initial_witness: &mut WitnessMap, lhs: &FunctionInput, rhs: &FunctionInput, output: &Witness, -) -> Result<(), OpcodeResolutionError> { +) -> Result<(), OpcodeResolutionError> { assert_eq!( lhs.num_bits, rhs.num_bits, "number of bits specified for each input must be the same" @@ -25,12 +25,12 @@ pub(super) fn and( /// Solves a [`BlackBoxFunc::XOR`][acir::circuit::black_box_functions::BlackBoxFunc::XOR] opcode and inserts /// the result into the supplied witness map -pub(super) fn xor( - initial_witness: &mut WitnessMap, +pub(super) fn xor( + initial_witness: &mut WitnessMap, lhs: &FunctionInput, rhs: &FunctionInput, output: &Witness, -) -> Result<(), OpcodeResolutionError> { +) -> Result<(), OpcodeResolutionError> { assert_eq!( lhs.num_bits, rhs.num_bits, "number of bits specified for each input must be the same" @@ -41,13 +41,13 @@ pub(super) fn xor( } /// Derives the rest of the witness based on the initial low level variables -fn solve_logic_opcode( - initial_witness: &mut WitnessMap, +fn solve_logic_opcode( + initial_witness: &mut WitnessMap, a: &Witness, b: &Witness, result: Witness, - logic_op: impl Fn(&FieldElement, &FieldElement) -> FieldElement, -) -> Result<(), OpcodeResolutionError> { + logic_op: impl Fn(&F, &F) -> F, +) -> Result<(), OpcodeResolutionError> { let w_l_value = witness_to_value(initial_witness, *a)?; let w_r_value = witness_to_value(initial_witness, *b)?; let assignment = logic_op(w_l_value, w_r_value); diff --git a/acvm-repo/acvm/src/pwg/blackbox/mod.rs b/acvm-repo/acvm/src/pwg/blackbox/mod.rs index 4309cad1b2e..8bda9221d8a 100644 --- a/acvm-repo/acvm/src/pwg/blackbox/mod.rs +++ b/acvm-repo/acvm/src/pwg/blackbox/mod.rs @@ -1,31 +1,34 @@ use acir::{ circuit::opcodes::{BlackBoxFuncCall, FunctionInput}, native_types::{Witness, WitnessMap}, - FieldElement, + AcirField, }; use acvm_blackbox_solver::{blake2s, blake3, keccak256, keccakf1600, sha256}; use self::{ - bigint::BigIntSolver, hash::solve_poseidon2_permutation_opcode, pedersen::pedersen_hash, + aes128::solve_aes128_encryption_opcode, bigint::AcvmBigIntSolver, + hash::solve_poseidon2_permutation_opcode, pedersen::pedersen_hash, }; use super::{insert_value, OpcodeNotSolvable, OpcodeResolutionError}; use crate::{pwg::witness_to_value, BlackBoxFunctionSolver}; +mod aes128; pub(crate) mod bigint; -mod fixed_base_scalar_mul; +mod embedded_curve_ops; mod hash; mod logic; mod pedersen; mod range; mod signature; +pub(crate) mod utils; -use fixed_base_scalar_mul::{embedded_curve_add, fixed_base_scalar_mul}; +use embedded_curve_ops::{embedded_curve_add, multi_scalar_mul}; // Hash functions should eventually be exposed for external consumers. use hash::{solve_generic_256_hash_opcode, solve_sha_256_permutation_opcode}; use logic::{and, xor}; use pedersen::pedersen; -use range::solve_range_opcode; +pub(crate) use range::solve_range_opcode; use signature::{ ecdsa::{secp256k1_prehashed, secp256r1_prehashed}, schnorr::schnorr_verify, @@ -34,8 +37,8 @@ use signature::{ /// Check if all of the inputs to the function have assignments /// /// Returns the first missing assignment if any are missing -fn first_missing_assignment( - witness_assignments: &WitnessMap, +fn first_missing_assignment( + witness_assignments: &WitnessMap, inputs: &[FunctionInput], ) -> Option { inputs.iter().find_map(|input| { @@ -48,16 +51,16 @@ fn first_missing_assignment( } /// Check if all of the inputs to the function have assignments -fn contains_all_inputs(witness_assignments: &WitnessMap, inputs: &[FunctionInput]) -> bool { +fn contains_all_inputs(witness_assignments: &WitnessMap, inputs: &[FunctionInput]) -> bool { inputs.iter().all(|input| witness_assignments.contains_key(&input.witness)) } -pub(crate) fn solve( - backend: &impl BlackBoxFunctionSolver, - initial_witness: &mut WitnessMap, +pub(crate) fn solve( + backend: &impl BlackBoxFunctionSolver, + initial_witness: &mut WitnessMap, bb_func: &BlackBoxFuncCall, - bigint_solver: &mut BigIntSolver, -) -> Result<(), OpcodeResolutionError> { + bigint_solver: &mut AcvmBigIntSolver, +) -> Result<(), OpcodeResolutionError> { let inputs = bb_func.get_inputs_vec(); if !contains_all_inputs(initial_witness, &inputs) { let unassigned_witness = first_missing_assignment(initial_witness, &inputs) @@ -68,64 +71,44 @@ pub(crate) fn solve( } match bb_func { + BlackBoxFuncCall::AES128Encrypt { inputs, iv, key, outputs } => { + solve_aes128_encryption_opcode(initial_witness, inputs, iv, key, outputs) + } BlackBoxFuncCall::AND { lhs, rhs, output } => and(initial_witness, lhs, rhs, output), BlackBoxFuncCall::XOR { lhs, rhs, output } => xor(initial_witness, lhs, rhs, output), BlackBoxFuncCall::RANGE { input } => solve_range_opcode(initial_witness, input), - BlackBoxFuncCall::SHA256 { inputs, outputs } => solve_generic_256_hash_opcode( - initial_witness, - inputs, - None, - outputs, - sha256, - bb_func.get_black_box_func(), - ), - BlackBoxFuncCall::Blake2s { inputs, outputs } => solve_generic_256_hash_opcode( - initial_witness, - inputs, - None, - outputs, - blake2s, - bb_func.get_black_box_func(), - ), - BlackBoxFuncCall::Blake3 { inputs, outputs } => solve_generic_256_hash_opcode( - initial_witness, - inputs, - None, - outputs, - blake3, - bb_func.get_black_box_func(), - ), - BlackBoxFuncCall::Keccak256 { inputs, outputs } => solve_generic_256_hash_opcode( - initial_witness, - inputs, - None, - outputs, - keccak256, - bb_func.get_black_box_func(), - ), - BlackBoxFuncCall::Keccak256VariableLength { inputs, var_message_size, outputs } => { + BlackBoxFuncCall::SHA256 { inputs, outputs } => { + solve_generic_256_hash_opcode(initial_witness, inputs, None, outputs, sha256) + } + BlackBoxFuncCall::Blake2s { inputs, outputs } => { + solve_generic_256_hash_opcode(initial_witness, inputs, None, outputs, blake2s) + } + BlackBoxFuncCall::Blake3 { inputs, outputs } => { + solve_generic_256_hash_opcode(initial_witness, inputs, None, outputs, blake3) + } + + BlackBoxFuncCall::Keccak256 { inputs, var_message_size, outputs } => { solve_generic_256_hash_opcode( initial_witness, inputs, Some(var_message_size), outputs, keccak256, - bb_func.get_black_box_func(), ) } BlackBoxFuncCall::Keccakf1600 { inputs, outputs } => { let mut state = [0; 25]; - for (i, input) in inputs.iter().enumerate() { + for (it, input) in state.iter_mut().zip(inputs.as_ref()) { let witness = input.witness; let num_bits = input.num_bits as usize; assert_eq!(num_bits, 64); let witness_assignment = witness_to_value(initial_witness, witness)?; let lane = witness_assignment.try_to_u64(); - state[i] = lane.unwrap(); + *it = lane.unwrap(); } let output_state = keccakf1600(state)?; for (output_witness, value) in outputs.iter().zip(output_state.into_iter()) { - insert_value(output_witness, FieldElement::from(value as u128), initial_witness)?; + insert_value(output_witness, F::from(value as u128), initial_witness)?; } Ok(()) } @@ -140,7 +123,7 @@ pub(crate) fn solve( initial_witness, *public_key_x, *public_key_y, - signature, + signature.as_ref(), message, *output, ), @@ -161,7 +144,7 @@ pub(crate) fn solve( public_key_x, public_key_y, signature, - message, + message.as_ref(), *output, ), BlackBoxFuncCall::EcdsaSecp256r1 { @@ -175,22 +158,14 @@ pub(crate) fn solve( public_key_x, public_key_y, signature, - message, + message.as_ref(), *output, ), - BlackBoxFuncCall::FixedBaseScalarMul { low, high, outputs } => { - fixed_base_scalar_mul(backend, initial_witness, *low, *high, *outputs) + BlackBoxFuncCall::MultiScalarMul { points, scalars, outputs } => { + multi_scalar_mul(backend, initial_witness, points, scalars, *outputs) } - BlackBoxFuncCall::EmbeddedCurveAdd { input1_x, input1_y, input2_x, input2_y, outputs } => { - embedded_curve_add( - backend, - initial_witness, - *input1_x, - *input1_y, - *input2_x, - *input2_y, - *outputs, - ) + BlackBoxFuncCall::EmbeddedCurveAdd { input1, input2, outputs } => { + embedded_curve_add(backend, initial_witness, **input1, **input2, *outputs) } // Recursive aggregation will be entirely handled by the backend and is not solved by the ACVM BlackBoxFuncCall::RecursiveAggregation { .. } => Ok(()), @@ -207,13 +182,7 @@ pub(crate) fn solve( bigint_solver.bigint_to_bytes(*input, outputs, initial_witness) } BlackBoxFuncCall::Sha256Compression { inputs, hash_values, outputs } => { - solve_sha_256_permutation_opcode( - initial_witness, - inputs, - hash_values, - outputs, - bb_func.get_black_box_func(), - ) + solve_sha_256_permutation_opcode(initial_witness, inputs, hash_values, outputs) } BlackBoxFuncCall::Poseidon2Permutation { inputs, outputs, len } => { solve_poseidon2_permutation_opcode(backend, initial_witness, inputs, outputs, *len) diff --git a/acvm-repo/acvm/src/pwg/blackbox/pedersen.rs b/acvm-repo/acvm/src/pwg/blackbox/pedersen.rs index bb214c1ceaf..f64a3a79465 100644 --- a/acvm-repo/acvm/src/pwg/blackbox/pedersen.rs +++ b/acvm-repo/acvm/src/pwg/blackbox/pedersen.rs @@ -1,6 +1,7 @@ use acir::{ circuit::opcodes::FunctionInput, native_types::{Witness, WitnessMap}, + AcirField, }; use crate::{ @@ -8,13 +9,13 @@ use crate::{ BlackBoxFunctionSolver, }; -pub(super) fn pedersen( - backend: &impl BlackBoxFunctionSolver, - initial_witness: &mut WitnessMap, +pub(super) fn pedersen( + backend: &impl BlackBoxFunctionSolver, + initial_witness: &mut WitnessMap, inputs: &[FunctionInput], domain_separator: u32, outputs: (Witness, Witness), -) -> Result<(), OpcodeResolutionError> { +) -> Result<(), OpcodeResolutionError> { let scalars: Result, _> = inputs.iter().map(|input| witness_to_value(initial_witness, input.witness)).collect(); let scalars: Vec<_> = scalars?.into_iter().cloned().collect(); @@ -27,13 +28,13 @@ pub(super) fn pedersen( Ok(()) } -pub(super) fn pedersen_hash( - backend: &impl BlackBoxFunctionSolver, - initial_witness: &mut WitnessMap, +pub(super) fn pedersen_hash( + backend: &impl BlackBoxFunctionSolver, + initial_witness: &mut WitnessMap, inputs: &[FunctionInput], domain_separator: u32, output: Witness, -) -> Result<(), OpcodeResolutionError> { +) -> Result<(), OpcodeResolutionError> { let scalars: Result, _> = inputs.iter().map(|input| witness_to_value(initial_witness, input.witness)).collect(); let scalars: Vec<_> = scalars?.into_iter().cloned().collect(); diff --git a/acvm-repo/acvm/src/pwg/blackbox/range.rs b/acvm-repo/acvm/src/pwg/blackbox/range.rs index 1b976e30ed5..0ca001aff7a 100644 --- a/acvm-repo/acvm/src/pwg/blackbox/range.rs +++ b/acvm-repo/acvm/src/pwg/blackbox/range.rs @@ -2,16 +2,17 @@ use crate::{ pwg::{witness_to_value, ErrorLocation}, OpcodeResolutionError, }; -use acir::{circuit::opcodes::FunctionInput, native_types::WitnessMap}; +use acir::{circuit::opcodes::FunctionInput, native_types::WitnessMap, AcirField}; -pub(super) fn solve_range_opcode( - initial_witness: &WitnessMap, +pub(crate) fn solve_range_opcode( + initial_witness: &WitnessMap, input: &FunctionInput, -) -> Result<(), OpcodeResolutionError> { +) -> Result<(), OpcodeResolutionError> { let w_value = witness_to_value(initial_witness, input.witness)?; if w_value.num_bits() > input.num_bits { return Err(OpcodeResolutionError::UnsatisfiedConstrain { opcode_location: ErrorLocation::Unresolved, + payload: None, }); } Ok(()) diff --git a/acvm-repo/acvm/src/pwg/blackbox/signature/ecdsa.rs b/acvm-repo/acvm/src/pwg/blackbox/signature/ecdsa.rs index 8f0df8378ad..707e3f26af0 100644 --- a/acvm-repo/acvm/src/pwg/blackbox/signature/ecdsa.rs +++ b/acvm-repo/acvm/src/pwg/blackbox/signature/ecdsa.rs @@ -1,91 +1,52 @@ use acir::{ circuit::opcodes::FunctionInput, native_types::{Witness, WitnessMap}, - FieldElement, + AcirField, }; use acvm_blackbox_solver::{ecdsa_secp256k1_verify, ecdsa_secp256r1_verify}; -use crate::{pwg::insert_value, OpcodeResolutionError}; - -use super::to_u8_vec; +use crate::{ + pwg::{ + blackbox::utils::{to_u8_array, to_u8_vec}, + insert_value, + }, + OpcodeResolutionError, +}; -pub(crate) fn secp256k1_prehashed( - initial_witness: &mut WitnessMap, - public_key_x_inputs: &[FunctionInput], - public_key_y_inputs: &[FunctionInput], - signature_inputs: &[FunctionInput], +pub(crate) fn secp256k1_prehashed( + initial_witness: &mut WitnessMap, + public_key_x_inputs: &[FunctionInput; 32], + public_key_y_inputs: &[FunctionInput; 32], + signature_inputs: &[FunctionInput; 64], hashed_message_inputs: &[FunctionInput], output: Witness, -) -> Result<(), OpcodeResolutionError> { +) -> Result<(), OpcodeResolutionError> { let hashed_message = to_u8_vec(initial_witness, hashed_message_inputs)?; - // These errors should never be emitted in practice as they would imply malformed ACIR generation. - let pub_key_x: [u8; 32] = - to_u8_vec(initial_witness, public_key_x_inputs)?.try_into().map_err(|_| { - OpcodeResolutionError::BlackBoxFunctionFailed( - acir::BlackBoxFunc::EcdsaSecp256k1, - format!("expected pubkey_x size 32 but received {}", public_key_x_inputs.len()), - ) - })?; - - let pub_key_y: [u8; 32] = - to_u8_vec(initial_witness, public_key_y_inputs)?.try_into().map_err(|_| { - OpcodeResolutionError::BlackBoxFunctionFailed( - acir::BlackBoxFunc::EcdsaSecp256k1, - format!("expected pubkey_y size 32 but received {}", public_key_y_inputs.len()), - ) - })?; - - let signature: [u8; 64] = - to_u8_vec(initial_witness, signature_inputs)?.try_into().map_err(|_| { - OpcodeResolutionError::BlackBoxFunctionFailed( - acir::BlackBoxFunc::EcdsaSecp256k1, - format!("expected signature size 64 but received {}", signature_inputs.len()), - ) - })?; + let pub_key_x: [u8; 32] = to_u8_array(initial_witness, public_key_x_inputs)?; + let pub_key_y: [u8; 32] = to_u8_array(initial_witness, public_key_y_inputs)?; + let signature: [u8; 64] = to_u8_array(initial_witness, signature_inputs)?; let is_valid = ecdsa_secp256k1_verify(&hashed_message, &pub_key_x, &pub_key_y, &signature)?; - insert_value(&output, FieldElement::from(is_valid), initial_witness)?; - Ok(()) + insert_value(&output, F::from(is_valid), initial_witness) } -pub(crate) fn secp256r1_prehashed( - initial_witness: &mut WitnessMap, - public_key_x_inputs: &[FunctionInput], - public_key_y_inputs: &[FunctionInput], - signature_inputs: &[FunctionInput], +pub(crate) fn secp256r1_prehashed( + initial_witness: &mut WitnessMap, + public_key_x_inputs: &[FunctionInput; 32], + public_key_y_inputs: &[FunctionInput; 32], + signature_inputs: &[FunctionInput; 64], hashed_message_inputs: &[FunctionInput], output: Witness, -) -> Result<(), OpcodeResolutionError> { +) -> Result<(), OpcodeResolutionError> { let hashed_message = to_u8_vec(initial_witness, hashed_message_inputs)?; - let pub_key_x: [u8; 32] = - to_u8_vec(initial_witness, public_key_x_inputs)?.try_into().map_err(|_| { - OpcodeResolutionError::BlackBoxFunctionFailed( - acir::BlackBoxFunc::EcdsaSecp256r1, - format!("expected pubkey_x size 32 but received {}", public_key_x_inputs.len()), - ) - })?; - - let pub_key_y: [u8; 32] = - to_u8_vec(initial_witness, public_key_y_inputs)?.try_into().map_err(|_| { - OpcodeResolutionError::BlackBoxFunctionFailed( - acir::BlackBoxFunc::EcdsaSecp256r1, - format!("expected pubkey_y size 32 but received {}", public_key_y_inputs.len()), - ) - })?; - - let signature: [u8; 64] = - to_u8_vec(initial_witness, signature_inputs)?.try_into().map_err(|_| { - OpcodeResolutionError::BlackBoxFunctionFailed( - acir::BlackBoxFunc::EcdsaSecp256r1, - format!("expected signature size 64 but received {}", signature_inputs.len()), - ) - })?; + let pub_key_x: [u8; 32] = to_u8_array(initial_witness, public_key_x_inputs)?; + let pub_key_y: [u8; 32] = to_u8_array(initial_witness, public_key_y_inputs)?; + let signature: [u8; 64] = to_u8_array(initial_witness, signature_inputs)?; let is_valid = ecdsa_secp256r1_verify(&hashed_message, &pub_key_x, &pub_key_y, &signature)?; - insert_value(&output, FieldElement::from(is_valid), initial_witness)?; - Ok(()) + insert_value(&output, F::from(is_valid), initial_witness) } diff --git a/acvm-repo/acvm/src/pwg/blackbox/signature/mod.rs b/acvm-repo/acvm/src/pwg/blackbox/signature/mod.rs index 0e28a63ff68..0cfb96740b8 100644 --- a/acvm-repo/acvm/src/pwg/blackbox/signature/mod.rs +++ b/acvm-repo/acvm/src/pwg/blackbox/signature/mod.rs @@ -1,21 +1,2 @@ -use acir::{circuit::opcodes::FunctionInput, native_types::WitnessMap}; - -use crate::pwg::{witness_to_value, OpcodeResolutionError}; - -fn to_u8_vec( - initial_witness: &WitnessMap, - inputs: &[FunctionInput], -) -> Result, OpcodeResolutionError> { - let mut result = Vec::with_capacity(inputs.len()); - for input in inputs { - let witness_value_bytes = witness_to_value(initial_witness, input.witness)?.to_be_bytes(); - let byte = witness_value_bytes - .last() - .expect("Field element must be represented by non-zero amount of bytes"); - result.push(*byte); - } - Ok(result) -} - pub(super) mod ecdsa; pub(super) mod schnorr; diff --git a/acvm-repo/acvm/src/pwg/blackbox/signature/schnorr.rs b/acvm-repo/acvm/src/pwg/blackbox/signature/schnorr.rs index 7f5381cee91..5e0ac94f8be 100644 --- a/acvm-repo/acvm/src/pwg/blackbox/signature/schnorr.rs +++ b/acvm-repo/acvm/src/pwg/blackbox/signature/schnorr.rs @@ -1,35 +1,36 @@ -use super::to_u8_vec; use crate::{ - pwg::{insert_value, witness_to_value, OpcodeResolutionError}, + pwg::{ + blackbox::utils::{to_u8_array, to_u8_vec}, + insert_value, witness_to_value, OpcodeResolutionError, + }, BlackBoxFunctionSolver, }; use acir::{ circuit::opcodes::FunctionInput, native_types::{Witness, WitnessMap}, - FieldElement, + AcirField, }; #[allow(clippy::too_many_arguments)] -pub(crate) fn schnorr_verify( - backend: &impl BlackBoxFunctionSolver, - initial_witness: &mut WitnessMap, +pub(crate) fn schnorr_verify( + backend: &impl BlackBoxFunctionSolver, + initial_witness: &mut WitnessMap, public_key_x: FunctionInput, public_key_y: FunctionInput, - signature: &[FunctionInput], + signature: &[FunctionInput; 64], message: &[FunctionInput], output: Witness, -) -> Result<(), OpcodeResolutionError> { - let public_key_x: &FieldElement = witness_to_value(initial_witness, public_key_x.witness)?; - let public_key_y: &FieldElement = witness_to_value(initial_witness, public_key_y.witness)?; - - let signature = to_u8_vec(initial_witness, signature)?; +) -> Result<(), OpcodeResolutionError> { + let public_key_x: &F = witness_to_value(initial_witness, public_key_x.witness)?; + let public_key_y: &F = witness_to_value(initial_witness, public_key_y.witness)?; + let signature = to_u8_array(initial_witness, signature)?; let message = to_u8_vec(initial_witness, message)?; let valid_signature = backend.schnorr_verify(public_key_x, public_key_y, &signature, &message)?; - insert_value(&output, FieldElement::from(valid_signature), initial_witness)?; + insert_value(&output, F::from(valid_signature), initial_witness)?; Ok(()) } diff --git a/acvm-repo/acvm/src/pwg/blackbox/utils.rs b/acvm-repo/acvm/src/pwg/blackbox/utils.rs new file mode 100644 index 00000000000..6880d21a324 --- /dev/null +++ b/acvm-repo/acvm/src/pwg/blackbox/utils.rs @@ -0,0 +1,33 @@ +use acir::{circuit::opcodes::FunctionInput, native_types::WitnessMap, AcirField}; + +use crate::pwg::{witness_to_value, OpcodeResolutionError}; + +pub(crate) fn to_u8_array( + initial_witness: &WitnessMap, + inputs: &[FunctionInput; N], +) -> Result<[u8; N], OpcodeResolutionError> { + let mut result = [0; N]; + for (it, input) in result.iter_mut().zip(inputs) { + let witness_value_bytes = witness_to_value(initial_witness, input.witness)?.to_be_bytes(); + let byte = witness_value_bytes + .last() + .expect("Field element must be represented by non-zero amount of bytes"); + *it = *byte; + } + Ok(result) +} + +pub(crate) fn to_u8_vec( + initial_witness: &WitnessMap, + inputs: &[FunctionInput], +) -> Result, OpcodeResolutionError> { + let mut result = Vec::with_capacity(inputs.len()); + for input in inputs { + let witness_value_bytes = witness_to_value(initial_witness, input.witness)?.to_be_bytes(); + let byte = witness_value_bytes + .last() + .expect("Field element must be represented by non-zero amount of bytes"); + result.push(*byte); + } + Ok(result) +} diff --git a/acvm-repo/acvm/src/pwg/brillig.rs b/acvm-repo/acvm/src/pwg/brillig.rs index b0fb7469fd9..7e6c207b69a 100644 --- a/acvm-repo/acvm/src/pwg/brillig.rs +++ b/acvm-repo/acvm/src/pwg/brillig.rs @@ -1,61 +1,49 @@ use std::collections::HashMap; use acir::{ - brillig::{ForeignCallParam, ForeignCallResult, Value}, + brillig::{ForeignCallParam, ForeignCallResult, Opcode as BrilligOpcode}, circuit::{ - brillig::{Brillig, BrilligInputs, BrilligOutputs}, + brillig::{BrilligInputs, BrilligOutputs}, opcodes::BlockId, - OpcodeLocation, + ErrorSelector, OpcodeLocation, RawAssertionPayload, ResolvedAssertionPayload, + STRING_ERROR_SELECTOR, }, native_types::WitnessMap, - FieldElement, + AcirField, }; use acvm_blackbox_solver::BlackBoxFunctionSolver; -use brillig_vm::{VMStatus, VM}; +use brillig_vm::{FailureReason, MemoryValue, VMStatus, VM}; use crate::{pwg::OpcodeNotSolvable, OpcodeResolutionError}; use super::{get_value, insert_value, memory_op::MemoryOpSolver}; #[derive(Debug)] -pub enum BrilligSolverStatus { +pub enum BrilligSolverStatus { Finished, InProgress, - ForeignCallWait(ForeignCallWaitInfo), + ForeignCallWait(ForeignCallWaitInfo), } -pub struct BrilligSolver<'b, B: BlackBoxFunctionSolver> { - vm: VM<'b, B>, +pub struct BrilligSolver<'b, F, B: BlackBoxFunctionSolver> { + vm: VM<'b, F, B>, acir_index: usize, } -impl<'b, B: BlackBoxFunctionSolver> BrilligSolver<'b, B> { - /// Evaluates if the Brillig block should be skipped entirely - pub(super) fn should_skip( - witness: &WitnessMap, - brillig: &Brillig, - ) -> Result { - // If the predicate is `None`, the block should never be skipped - // If the predicate is `Some` but we cannot find a value, then we return stalled - match &brillig.predicate { - Some(pred) => Ok(get_value(pred, witness)?.is_zero()), - None => Ok(false), - } - } - +impl<'b, B: BlackBoxFunctionSolver, F: AcirField> BrilligSolver<'b, F, B> { /// Assigns the zero value to all outputs of the given [`Brillig`] bytecode. pub(super) fn zero_out_brillig_outputs( - initial_witness: &mut WitnessMap, - brillig: &Brillig, - ) -> Result<(), OpcodeResolutionError> { - for output in &brillig.outputs { + initial_witness: &mut WitnessMap, + outputs: &[BrilligOutputs], + ) -> Result<(), OpcodeResolutionError> { + for output in outputs { match output { BrilligOutputs::Simple(witness) => { - insert_value(witness, FieldElement::zero(), initial_witness)?; + insert_value(witness, F::zero(), initial_witness)?; } BrilligOutputs::Array(witness_arr) => { for witness in witness_arr { - insert_value(witness, FieldElement::zero(), initial_witness)?; + insert_value(witness, F::zero(), initial_witness)?; } } } @@ -65,23 +53,36 @@ impl<'b, B: BlackBoxFunctionSolver> BrilligSolver<'b, B> { /// Constructs a solver for a Brillig block given the bytecode and initial /// witness. - pub(super) fn new( - initial_witness: &WitnessMap, - memory: &HashMap, - brillig: &'b Brillig, + pub(crate) fn new_call( + initial_witness: &WitnessMap, + memory: &HashMap>, + inputs: &'b [BrilligInputs], + brillig_bytecode: &'b [BrilligOpcode], bb_solver: &'b B, acir_index: usize, - ) -> Result { + ) -> Result> { + let vm = + Self::setup_brillig_vm(initial_witness, memory, inputs, brillig_bytecode, bb_solver)?; + Ok(Self { vm, acir_index }) + } + + fn setup_brillig_vm( + initial_witness: &WitnessMap, + memory: &HashMap>, + inputs: &[BrilligInputs], + brillig_bytecode: &'b [BrilligOpcode], + bb_solver: &'b B, + ) -> Result, OpcodeResolutionError> { // Set input values - let mut calldata: Vec = Vec::new(); + let mut calldata: Vec = Vec::new(); // Each input represents an expression or array of expressions to evaluate. // Iterate over each input and evaluate the expression(s) associated with it. // Push the results into memory. // If a certain expression is not solvable, we stall the ACVM and do not proceed with Brillig VM execution. - for input in &brillig.inputs { + for input in inputs { match input { BrilligInputs::Single(expr) => match get_value(expr, initial_witness) { - Ok(value) => calldata.push(value.into()), + Ok(value) => calldata.push(value), Err(_) => { return Err(OpcodeResolutionError::OpcodeNotSolvable( OpcodeNotSolvable::ExpressionHasTooManyUnknowns(expr.clone()), @@ -92,7 +93,7 @@ impl<'b, B: BlackBoxFunctionSolver> BrilligSolver<'b, B> { // Attempt to fetch all array input values for expr in expr_arr.iter() { match get_value(expr, initial_witness) { - Ok(value) => calldata.push(value.into()), + Ok(value) => calldata.push(value), Err(_) => { return Err(OpcodeResolutionError::OpcodeNotSolvable( OpcodeNotSolvable::ExpressionHasTooManyUnknowns(expr.clone()), @@ -110,7 +111,7 @@ impl<'b, B: BlackBoxFunctionSolver> BrilligSolver<'b, B> { .block_value .get(&memory_index) .expect("All memory is initialized on creation"); - calldata.push((*memory_value).into()); + calldata.push(*memory_value); } } } @@ -118,15 +119,15 @@ impl<'b, B: BlackBoxFunctionSolver> BrilligSolver<'b, B> { // Instantiate a Brillig VM given the solved calldata // along with the Brillig bytecode. - let vm = VM::new(calldata, &brillig.bytecode, vec![], bb_solver); - Ok(Self { vm, acir_index }) + let vm = VM::new(calldata, brillig_bytecode, vec![], bb_solver); + Ok(vm) } - pub fn get_memory(&self) -> &[Value] { + pub fn get_memory(&self) -> &[MemoryValue] { self.vm.get_memory() } - pub fn write_memory_at(&mut self, ptr: usize, value: Value) { + pub fn write_memory_at(&mut self, ptr: usize, value: MemoryValue) { self.vm.write_memory_at(ptr, value); } @@ -134,12 +135,12 @@ impl<'b, B: BlackBoxFunctionSolver> BrilligSolver<'b, B> { self.vm.get_call_stack() } - pub(super) fn solve(&mut self) -> Result { + pub(crate) fn solve(&mut self) -> Result, OpcodeResolutionError> { let status = self.vm.process_opcodes(); self.handle_vm_status(status) } - pub fn step(&mut self) -> Result { + pub fn step(&mut self) -> Result, OpcodeResolutionError> { let status = self.vm.process_opcode(); self.handle_vm_status(status) } @@ -150,8 +151,8 @@ impl<'b, B: BlackBoxFunctionSolver> BrilligSolver<'b, B> { fn handle_vm_status( &self, - vm_status: VMStatus, - ) -> Result { + vm_status: VMStatus, + ) -> Result, OpcodeResolutionError> { // Check the status of the Brillig VM and return a resolution. // It may be finished, in-progress, failed, or may be waiting for results of a foreign call. // Return the "resolution" to the caller who may choose to make subsequent calls @@ -159,9 +160,56 @@ impl<'b, B: BlackBoxFunctionSolver> BrilligSolver<'b, B> { match vm_status { VMStatus::Finished { .. } => Ok(BrilligSolverStatus::Finished), VMStatus::InProgress => Ok(BrilligSolverStatus::InProgress), - VMStatus::Failure { message, call_stack } => { + VMStatus::Failure { reason, call_stack } => { + let payload = match reason { + FailureReason::RuntimeError { message } => { + Some(ResolvedAssertionPayload::String(message)) + } + FailureReason::Trap { revert_data_offset, revert_data_size } => { + // Since noir can only revert with strings currently, we can parse return data as a string + if revert_data_size == 0 { + None + } else { + let memory = self.vm.get_memory(); + let mut revert_values_iter = memory + [revert_data_offset..(revert_data_offset + revert_data_size)] + .iter(); + let error_selector = ErrorSelector::new( + revert_values_iter + .next() + .expect("Incorrect revert data size") + .try_into() + .expect("Error selector is not u64"), + ); + + match error_selector { + STRING_ERROR_SELECTOR => { + // If the error selector is 0, it means the error is a string + let string = revert_values_iter + .map(|memory_value| { + let as_u8: u8 = memory_value + .try_into() + .expect("String item is not u8"); + as_u8 as char + }) + .collect(); + Some(ResolvedAssertionPayload::String(string)) + } + _ => { + // If the error selector is not 0, it means the error is a custom error + Some(ResolvedAssertionPayload::Raw(RawAssertionPayload { + selector: error_selector, + data: revert_values_iter + .map(|value| value.to_field()) + .collect(), + })) + } + } + } + } + }; Err(OpcodeResolutionError::BrilligFunctionFailed { - message, + payload, call_stack: call_stack .iter() .map(|brillig_index| OpcodeLocation::Brillig { @@ -177,16 +225,16 @@ impl<'b, B: BlackBoxFunctionSolver> BrilligSolver<'b, B> { } } - pub(super) fn finalize( + pub(crate) fn finalize( self, - witness: &mut WitnessMap, - brillig: &Brillig, - ) -> Result<(), OpcodeResolutionError> { + witness: &mut WitnessMap, + outputs: &[BrilligOutputs], + ) -> Result<(), OpcodeResolutionError> { // Finish the Brillig execution by writing the outputs to the witness map let vm_status = self.vm.get_status(); match vm_status { VMStatus::Finished { return_data_offset, return_data_size } => { - self.write_brillig_outputs(witness, return_data_offset, return_data_size, brillig)?; + self.write_brillig_outputs(witness, return_data_offset, return_data_size, outputs)?; Ok(()) } _ => panic!("Brillig VM has not completed execution"), @@ -195,15 +243,15 @@ impl<'b, B: BlackBoxFunctionSolver> BrilligSolver<'b, B> { fn write_brillig_outputs( &self, - witness_map: &mut WitnessMap, + witness_map: &mut WitnessMap, return_data_offset: usize, return_data_size: usize, - brillig: &Brillig, - ) -> Result<(), OpcodeResolutionError> { + outputs: &[BrilligOutputs], + ) -> Result<(), OpcodeResolutionError> { // Write VM execution results into the witness map let memory = self.vm.get_memory(); let mut current_ret_data_idx = return_data_offset; - for output in brillig.outputs.iter() { + for output in outputs.iter() { match output { BrilligOutputs::Simple(witness) => { insert_value(witness, memory[current_ret_data_idx].to_field(), witness_map)?; @@ -211,13 +259,14 @@ impl<'b, B: BlackBoxFunctionSolver> BrilligSolver<'b, B> { } BrilligOutputs::Array(witness_arr) => { for witness in witness_arr.iter() { - let value = memory[current_ret_data_idx]; + let value = &memory[current_ret_data_idx]; insert_value(witness, value.to_field(), witness_map)?; current_ret_data_idx += 1; } } } } + assert!( current_ret_data_idx == return_data_offset + return_data_size, "Brillig VM did not write the expected number of return values" @@ -225,7 +274,7 @@ impl<'b, B: BlackBoxFunctionSolver> BrilligSolver<'b, B> { Ok(()) } - pub fn resolve_pending_foreign_call(&mut self, foreign_call_result: ForeignCallResult) { + pub fn resolve_pending_foreign_call(&mut self, foreign_call_result: ForeignCallResult) { match self.vm.get_status() { VMStatus::ForeignCallWait { .. } => self.vm.resolve_foreign_call(foreign_call_result), _ => unreachable!("Brillig VM is not waiting for a foreign call"), @@ -238,9 +287,9 @@ impl<'b, B: BlackBoxFunctionSolver> BrilligSolver<'b, B> { /// /// The caller must resolve this opcode externally based upon the information in the request. #[derive(Debug, PartialEq, Clone)] -pub struct ForeignCallWaitInfo { +pub struct ForeignCallWaitInfo { /// An identifier interpreted by the caller process pub function: String, /// Resolved inputs to a foreign call computed in the previous steps of a Brillig VM process - pub inputs: Vec, + pub inputs: Vec>, } diff --git a/acvm-repo/acvm/src/pwg/directives/mod.rs b/acvm-repo/acvm/src/pwg/directives/mod.rs index 07226c85b27..d7bee88c278 100644 --- a/acvm-repo/acvm/src/pwg/directives/mod.rs +++ b/acvm-repo/acvm/src/pwg/directives/mod.rs @@ -1,4 +1,4 @@ -use acir::{circuit::directives::Directive, native_types::WitnessMap, FieldElement}; +use acir::{circuit::directives::Directive, native_types::WitnessMap, AcirField}; use num_bigint::BigUint; use crate::OpcodeResolutionError; @@ -11,10 +11,10 @@ use super::{get_value, insert_value, ErrorLocation}; /// Returns `Ok(OpcodeResolution)` to signal whether the directive was successful solved. /// /// Returns `Err(OpcodeResolutionError)` if a circuit constraint is unsatisfied. -pub(super) fn solve_directives( - initial_witness: &mut WitnessMap, - directive: &Directive, -) -> Result<(), OpcodeResolutionError> { +pub(crate) fn solve_directives( + initial_witness: &mut WitnessMap, + directive: &Directive, +) -> Result<(), OpcodeResolutionError> { match directive { Directive::ToLeRadix { a, b, radix } => { let value_a = get_value(a, initial_witness)?; @@ -26,6 +26,7 @@ pub(super) fn solve_directives( if b.len() < decomposed_integer.len() { return Err(OpcodeResolutionError::UnsatisfiedConstrain { opcode_location: ErrorLocation::Unresolved, + payload: None, }); } @@ -35,8 +36,8 @@ pub(super) fn solve_directives( // If it is not available, which can happen when the decomposed integer // list is shorter than the witness list, we return 0. let value = match decomposed_integer.get(i) { - Some(digit) => FieldElement::from_be_bytes_reduce(&[*digit]), - None => FieldElement::zero(), + Some(digit) => F::from_be_bytes_reduce(&[*digit]), + None => F::zero(), }; insert_value(witness, value, initial_witness)?; diff --git a/acvm-repo/acvm/src/pwg/memory_op.rs b/acvm-repo/acvm/src/pwg/memory_op.rs index 49ec652289e..a9ed7f5d15b 100644 --- a/acvm-repo/acvm/src/pwg/memory_op.rs +++ b/acvm-repo/acvm/src/pwg/memory_op.rs @@ -3,27 +3,29 @@ use std::collections::HashMap; use acir::{ circuit::opcodes::MemOp, native_types::{Expression, Witness, WitnessMap}, - FieldElement, + AcirField, }; -use super::{arithmetic::ExpressionSolver, get_value, insert_value, witness_to_value}; +use super::{ + arithmetic::ExpressionSolver, get_value, insert_value, is_predicate_false, witness_to_value, +}; use super::{ErrorLocation, OpcodeResolutionError}; type MemoryIndex = u32; /// Maintains the state for solving [`MemoryInit`][`acir::circuit::Opcode::MemoryInit`] and [`MemoryOp`][`acir::circuit::Opcode::MemoryOp`] opcodes. #[derive(Default)] -pub(super) struct MemoryOpSolver { - pub(super) block_value: HashMap, +pub(crate) struct MemoryOpSolver { + pub(super) block_value: HashMap, pub(super) block_len: u32, } -impl MemoryOpSolver { +impl MemoryOpSolver { fn write_memory_index( &mut self, index: MemoryIndex, - value: FieldElement, - ) -> Result<(), OpcodeResolutionError> { + value: F, + ) -> Result<(), OpcodeResolutionError> { if index >= self.block_len { return Err(OpcodeResolutionError::IndexOutOfBounds { opcode_location: ErrorLocation::Unresolved, @@ -35,7 +37,7 @@ impl MemoryOpSolver { Ok(()) } - fn read_memory_index(&self, index: MemoryIndex) -> Result { + fn read_memory_index(&self, index: MemoryIndex) -> Result> { self.block_value.get(&index).copied().ok_or(OpcodeResolutionError::IndexOutOfBounds { opcode_location: ErrorLocation::Unresolved, index, @@ -47,8 +49,8 @@ impl MemoryOpSolver { pub(crate) fn init( &mut self, init: &[Witness], - initial_witness: &WitnessMap, - ) -> Result<(), OpcodeResolutionError> { + initial_witness: &WitnessMap, + ) -> Result<(), OpcodeResolutionError> { self.block_len = init.len() as u32; for (memory_index, witness) in init.iter().enumerate() { self.write_memory_index( @@ -61,10 +63,10 @@ impl MemoryOpSolver { pub(crate) fn solve_memory_op( &mut self, - op: &MemOp, - initial_witness: &mut WitnessMap, - predicate: &Option, - ) -> Result<(), OpcodeResolutionError> { + op: &MemOp, + initial_witness: &mut WitnessMap, + predicate: &Option>, + ) -> Result<(), OpcodeResolutionError> { let operation = get_value(&op.operation, initial_witness)?; // Find the memory index associated with this memory operation. @@ -80,11 +82,8 @@ impl MemoryOpSolver { // `operation == 0` implies a read operation. (`operation == 1` implies write operation). let is_read_operation = operation.is_zero(); - // If the predicate is `None`, then we simply return the value 1 - let pred_value = match predicate { - Some(pred) => get_value(pred, initial_witness), - None => Ok(FieldElement::one()), - }?; + // Fetch whether or not the predicate is false (e.g. equal to zero) + let skip_operation = is_predicate_false(initial_witness, predicate)?; if is_read_operation { // `value_read = arr[memory_index]` @@ -97,11 +96,8 @@ impl MemoryOpSolver { // A zero predicate indicates that we should skip the read operation // and zero out the operation's output. - let value_in_array = if pred_value.is_zero() { - FieldElement::zero() - } else { - self.read_memory_index(memory_index)? - }; + let value_in_array = + if skip_operation { F::zero() } else { self.read_memory_index(memory_index)? }; insert_value(&value_read_witness, value_in_array, initial_witness) } else { // `arr[memory_index] = value_write` @@ -111,7 +107,7 @@ impl MemoryOpSolver { let value_write = value; // A zero predicate indicates that we should skip the write operation. - if pred_value.is_zero() { + if skip_operation { // We only want to write to already initialized memory. // Do nothing if the predicate is zero. Ok(()) @@ -130,7 +126,7 @@ mod tests { use acir::{ circuit::opcodes::MemOp, native_types::{Expression, Witness, WitnessMap}, - FieldElement, + AcirField, FieldElement, }; use super::MemoryOpSolver; diff --git a/acvm-repo/acvm/src/pwg/mod.rs b/acvm-repo/acvm/src/pwg/mod.rs index 2ee39a289e7..4f88e17d109 100644 --- a/acvm-repo/acvm/src/pwg/mod.rs +++ b/acvm-repo/acvm/src/pwg/mod.rs @@ -4,14 +4,18 @@ use std::collections::HashMap; use acir::{ brillig::ForeignCallResult, - circuit::{opcodes::BlockId, Opcode, OpcodeLocation}, + circuit::{ + brillig::BrilligBytecode, opcodes::BlockId, AssertionPayload, ErrorSelector, + ExpressionOrMemory, Opcode, OpcodeLocation, RawAssertionPayload, ResolvedAssertionPayload, + STRING_ERROR_SELECTOR, + }, native_types::{Expression, Witness, WitnessMap}, - BlackBoxFunc, FieldElement, + AcirField, BlackBoxFunc, }; use acvm_blackbox_solver::BlackBoxResolutionError; use self::{ - arithmetic::ExpressionSolver, blackbox::bigint::BigIntSolver, directives::solve_directives, + arithmetic::ExpressionSolver, blackbox::bigint::AcvmBigIntSolver, directives::solve_directives, memory_op::MemoryOpSolver, }; use crate::BlackBoxFunctionSolver; @@ -21,18 +25,18 @@ use thiserror::Error; // arithmetic pub(crate) mod arithmetic; // Brillig bytecode -mod brillig; +pub(crate) mod brillig; // Directives -mod directives; +pub(crate) mod directives; // black box functions -mod blackbox; +pub(crate) mod blackbox; mod memory_op; pub use self::brillig::{BrilligSolver, BrilligSolverStatus}; pub use brillig::ForeignCallWaitInfo; #[derive(Debug, Clone, PartialEq)] -pub enum ACVMStatus { +pub enum ACVMStatus { /// All opcodes have been solved. Solved, @@ -41,30 +45,37 @@ pub enum ACVMStatus { /// The ACVM has encountered an irrecoverable error while executing the circuit and can not progress. /// Most commonly this will be due to an unsatisfied constraint due to invalid inputs to the circuit. - Failure(OpcodeResolutionError), + Failure(OpcodeResolutionError), /// The ACVM has encountered a request for a Brillig [foreign call][acir::brillig_vm::Opcode::ForeignCall] /// to retrieve information from outside of the ACVM. The result of the foreign call must be passed back /// to the ACVM using [`ACVM::resolve_pending_foreign_call`]. /// /// Once this is done, the ACVM can be restarted to solve the remaining opcodes. - RequiresForeignCall(ForeignCallWaitInfo), + RequiresForeignCall(ForeignCallWaitInfo), + + /// The ACVM has encountered a request for an ACIR [call][acir::circuit::Opcode] + /// to execute a separate ACVM instance. The result of the ACIR call must be passd back to the ACVM. + /// + /// Once this is done, the ACVM can be restarted to solve the remaining opcodes. + RequiresAcirCall(AcirCallWaitInfo), } -impl std::fmt::Display for ACVMStatus { +impl std::fmt::Display for ACVMStatus { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { ACVMStatus::Solved => write!(f, "Solved"), ACVMStatus::InProgress => write!(f, "In progress"), ACVMStatus::Failure(_) => write!(f, "Execution failure"), ACVMStatus::RequiresForeignCall(_) => write!(f, "Waiting on foreign call"), + ACVMStatus::RequiresAcirCall(_) => write!(f, "Waiting on acir call"), } } } -pub enum StepResult<'a, B: BlackBoxFunctionSolver> { - Status(ACVMStatus), - IntoBrillig(BrilligSolver<'a, B>), +pub enum StepResult<'a, F, B: BlackBoxFunctionSolver> { + Status(ACVMStatus), + IntoBrillig(BrilligSolver<'a, F, B>), } // This enum represents the different cases in which an @@ -76,13 +87,13 @@ pub enum StepResult<'a, B: BlackBoxFunctionSolver> { // TODO: we could have a error enum for expression solver failure cases in that module // TODO that can be converted into an OpcodeNotSolvable or OpcodeResolutionError enum #[derive(Clone, PartialEq, Eq, Debug, Error)] -pub enum OpcodeNotSolvable { +pub enum OpcodeNotSolvable { #[error("missing assignment for witness index {0}")] MissingAssignment(u32), #[error("Attempted to load uninitialized memory block")] MissingMemoryBlock(u32), #[error("expression has too many unknowns {0}")] - ExpressionHasTooManyUnknowns(Expression), + ExpressionHasTooManyUnknowns(Expression), } /// Allows to point to a specific opcode as cause in errors. @@ -106,20 +117,30 @@ impl std::fmt::Display for ErrorLocation { } #[derive(Clone, PartialEq, Eq, Debug, Error)] -pub enum OpcodeResolutionError { +pub enum OpcodeResolutionError { #[error("Cannot solve opcode: {0}")] - OpcodeNotSolvable(#[from] OpcodeNotSolvable), + OpcodeNotSolvable(#[from] OpcodeNotSolvable), #[error("Cannot satisfy constraint")] - UnsatisfiedConstrain { opcode_location: ErrorLocation }, + UnsatisfiedConstrain { + opcode_location: ErrorLocation, + payload: Option>, + }, #[error("Index out of bounds, array has size {array_size:?}, but index was {index:?}")] IndexOutOfBounds { opcode_location: ErrorLocation, index: u32, array_size: u32 }, #[error("Failed to solve blackbox function: {0}, reason: {1}")] BlackBoxFunctionFailed(BlackBoxFunc, String), - #[error("Failed to solve brillig function, reason: {message}")] - BrilligFunctionFailed { message: String, call_stack: Vec }, + #[error("Failed to solve brillig function")] + BrilligFunctionFailed { + call_stack: Vec, + payload: Option>, + }, + #[error("Attempted to call `main` with a `Call` opcode")] + AcirMainCallAttempted { opcode_location: ErrorLocation }, + #[error("{results_size:?} result values were provided for {outputs_size:?} call output witnesses, most likely due to bad ACIR codegen")] + AcirCallOutputsMismatch { opcode_location: ErrorLocation, results_size: u32, outputs_size: u32 }, } -impl From for OpcodeResolutionError { +impl From for OpcodeResolutionError { fn from(value: BlackBoxResolutionError) -> Self { match value { BlackBoxResolutionError::Failed(func, reason) => { @@ -129,58 +150,76 @@ impl From for OpcodeResolutionError { } } -pub struct ACVM<'a, B: BlackBoxFunctionSolver> { - status: ACVMStatus, +pub struct ACVM<'a, F, B: BlackBoxFunctionSolver> { + status: ACVMStatus, backend: &'a B, /// Stores the solver for memory operations acting on blocks of memory disambiguated by [block][`BlockId`]. - block_solvers: HashMap, + block_solvers: HashMap>, - bigint_solver: BigIntSolver, + bigint_solver: AcvmBigIntSolver, /// A list of opcodes which are to be executed by the ACVM. - opcodes: &'a [Opcode], + opcodes: &'a [Opcode], /// Index of the next opcode to be executed. instruction_pointer: usize, - witness_map: WitnessMap, + witness_map: WitnessMap, + + brillig_solver: Option>, + + /// A counter maintained throughout an ACVM process that determines + /// whether the caller has resolved the results of an ACIR [call][Opcode::Call]. + acir_call_counter: usize, + /// Represents the outputs of all ACIR calls during an ACVM process + /// List is appended onto by the caller upon reaching a [ACVMStatus::RequiresAcirCall] + acir_call_results: Vec>, - brillig_solver: Option>, + // Each unconstrained function referenced in the program + unconstrained_functions: &'a [BrilligBytecode], + + assertion_payloads: &'a [(OpcodeLocation, AssertionPayload)], } -impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> { - pub fn new(backend: &'a B, opcodes: &'a [Opcode], initial_witness: WitnessMap) -> Self { +impl<'a, F: AcirField, B: BlackBoxFunctionSolver> ACVM<'a, F, B> { + pub fn new( + backend: &'a B, + opcodes: &'a [Opcode], + initial_witness: WitnessMap, + unconstrained_functions: &'a [BrilligBytecode], + assertion_payloads: &'a [(OpcodeLocation, AssertionPayload)], + ) -> Self { let status = if opcodes.is_empty() { ACVMStatus::Solved } else { ACVMStatus::InProgress }; ACVM { status, backend, block_solvers: HashMap::default(), - bigint_solver: BigIntSolver::default(), + bigint_solver: AcvmBigIntSolver::default(), opcodes, instruction_pointer: 0, witness_map: initial_witness, brillig_solver: None, + acir_call_counter: 0, + acir_call_results: Vec::default(), + unconstrained_functions, + assertion_payloads, } } /// Returns a reference to the current state of the ACVM's [`WitnessMap`]. /// /// Once execution has completed, the witness map can be extracted using [`ACVM::finalize`] - pub fn witness_map(&self) -> &WitnessMap { + pub fn witness_map(&self) -> &WitnessMap { &self.witness_map } - pub fn overwrite_witness( - &mut self, - witness: Witness, - value: FieldElement, - ) -> Option { + pub fn overwrite_witness(&mut self, witness: Witness, value: F) -> Option { self.witness_map.insert(witness, value) } /// Returns a slice containing the opcodes of the circuit being executed. - pub fn opcodes(&self) -> &[Opcode] { + pub fn opcodes(&self) -> &[Opcode] { self.opcodes } @@ -190,7 +229,7 @@ impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> { } /// Finalize the ACVM execution, returning the resulting [`WitnessMap`]. - pub fn finalize(self) -> WitnessMap { + pub fn finalize(self) -> WitnessMap { if self.status != ACVMStatus::Solved { panic!("ACVM execution is not complete: ({})", self.status); } @@ -199,29 +238,29 @@ impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> { /// Updates the current status of the VM. /// Returns the given status. - fn status(&mut self, status: ACVMStatus) -> ACVMStatus { + fn status(&mut self, status: ACVMStatus) -> ACVMStatus { self.status = status.clone(); status } - pub fn get_status(&self) -> &ACVMStatus { + 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 { + fn fail(&mut self, error: OpcodeResolutionError) -> ACVMStatus { self.status(ACVMStatus::Failure(error)) } /// Sets the status of the VM to `RequiresForeignCall`. /// Indicating that the VM is now waiting for a foreign call to be resolved. - fn wait_for_foreign_call(&mut self, foreign_call: ForeignCallWaitInfo) -> ACVMStatus { + fn wait_for_foreign_call(&mut self, foreign_call: ForeignCallWaitInfo) -> ACVMStatus { self.status(ACVMStatus::RequiresForeignCall(foreign_call)) } /// Return a reference to the arguments for the next pending foreign call, if one exists. - pub fn get_pending_foreign_call(&self) -> Option<&ForeignCallWaitInfo> { + pub fn get_pending_foreign_call(&self) -> Option<&ForeignCallWaitInfo> { if let ACVMStatus::RequiresForeignCall(foreign_call) = &self.status { Some(foreign_call) } else { @@ -232,7 +271,7 @@ impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> { /// Resolves a foreign call's [result][acir::brillig_vm::ForeignCallResult] using a result calculated outside of the ACVM. /// /// The ACVM can then be restarted to solve the remaining Brillig VM process as well as the remaining ACIR opcodes. - pub fn resolve_pending_foreign_call(&mut self, foreign_call_result: ForeignCallResult) { + pub fn resolve_pending_foreign_call(&mut self, foreign_call_result: ForeignCallResult) { if !matches!(self.status, ACVMStatus::RequiresForeignCall(_)) { panic!("ACVM is not expecting a foreign call response as no call was made"); } @@ -244,20 +283,43 @@ impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> { self.status(ACVMStatus::InProgress); } + /// Sets the status of the VM to `RequiresAcirCall` + /// Indicating that the VM is now waiting for an ACIR call to be resolved + fn wait_for_acir_call(&mut self, acir_call: AcirCallWaitInfo) -> ACVMStatus { + self.status(ACVMStatus::RequiresAcirCall(acir_call)) + } + + /// Resolves an ACIR call's result (simply a list of fields) using a result calculated by a separate ACVM instance. + /// + /// The current ACVM instance can then be restarted to solve the remaining ACIR opcodes. + pub fn resolve_pending_acir_call(&mut self, call_result: Vec) { + if !matches!(self.status, ACVMStatus::RequiresAcirCall(_)) { + panic!("ACVM is not expecting an ACIR call response as no call was made"); + } + + if self.acir_call_counter < self.acir_call_results.len() { + panic!("No unresolved ACIR calls"); + } + self.acir_call_results.push(call_result); + + // Now that the ACIR call has been resolved then we can resume execution. + self.status(ACVMStatus::InProgress); + } + /// Executes the ACVM's circuit until execution halts. /// /// Execution can halt due to three reasons: /// 1. All opcodes have been executed successfully. /// 2. The circuit has been found to be unsatisfiable. /// 2. A Brillig [foreign call][`ForeignCallWaitInfo`] has been encountered and must be resolved. - pub fn solve(&mut self) -> ACVMStatus { + pub fn solve(&mut self) -> ACVMStatus { while self.status == ACVMStatus::InProgress { self.solve_opcode(); } self.status.clone() } - pub fn solve_opcode(&mut self) -> ACVMStatus { + pub fn solve_opcode(&mut self) -> ACVMStatus { let opcode = &self.opcodes[self.instruction_pointer]; let resolution = match opcode { @@ -269,7 +331,7 @@ impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> { &mut self.bigint_solver, ), Opcode::Directive(directive) => solve_directives(&mut self.witness_map, directive), - Opcode::MemoryInit { block_id, init } => { + Opcode::MemoryInit { block_id, init, .. } => { let solver = self.block_solvers.entry(*block_id).or_default(); solver.init(init, &self.witness_map) } @@ -277,18 +339,22 @@ impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> { let solver = self.block_solvers.entry(*block_id).or_default(); solver.solve_memory_op(op, &mut self.witness_map, predicate) } - Opcode::Brillig(_) => match self.solve_brillig_opcode() { + Opcode::BrilligCall { .. } => match self.solve_brillig_call_opcode() { Ok(Some(foreign_call)) => return self.wait_for_foreign_call(foreign_call), res => res.map(|_| ()), }, + Opcode::Call { .. } => match self.solve_call_opcode() { + Ok(Some(input_values)) => return self.wait_for_acir_call(input_values), + res => res.map(|_| ()), + }, }; self.handle_opcode_resolution(resolution) } fn handle_opcode_resolution( &mut self, - resolution: Result<(), OpcodeResolutionError>, - ) -> ACVMStatus { + resolution: Result<(), OpcodeResolutionError>, + ) -> ACVMStatus { match resolution { Ok(()) => { self.instruction_pointer += 1; @@ -306,14 +372,19 @@ impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> { OpcodeResolutionError::IndexOutOfBounds { opcode_location: opcode_index, .. - } - | OpcodeResolutionError::UnsatisfiedConstrain { - opcode_location: opcode_index, } => { *opcode_index = ErrorLocation::Resolved(OpcodeLocation::Acir( self.instruction_pointer(), )); } + OpcodeResolutionError::UnsatisfiedConstrain { + opcode_location: opcode_index, + payload: assertion_payload, + } => { + let location = OpcodeLocation::Acir(self.instruction_pointer()); + *opcode_index = ErrorLocation::Resolved(location); + *assertion_payload = self.extract_assertion_payload(location); + } // All other errors are thrown normally. _ => (), }; @@ -322,31 +393,96 @@ impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> { } } - fn solve_brillig_opcode( + fn extract_assertion_payload( + &self, + location: OpcodeLocation, + ) -> Option> { + let (_, found_assertion_payload) = + self.assertion_payloads.iter().find(|(loc, _)| location == *loc)?; + match found_assertion_payload { + AssertionPayload::StaticString(string) => { + Some(ResolvedAssertionPayload::String(string.clone())) + } + AssertionPayload::Dynamic(error_selector, expression) => { + let mut fields = vec![]; + for expr in expression { + match expr { + ExpressionOrMemory::Expression(expr) => { + let value = get_value(expr, &self.witness_map).ok()?; + fields.push(value); + } + ExpressionOrMemory::Memory(block_id) => { + let memory_block = self.block_solvers.get(block_id)?; + fields.extend((0..memory_block.block_len).map(|memory_index| { + *memory_block + .block_value + .get(&memory_index) + .expect("All memory is initialized on creation") + })); + } + } + } + let error_selector = ErrorSelector::new(*error_selector); + + Some(match error_selector { + STRING_ERROR_SELECTOR => { + // If the error selector is 0, it means the error is a string + let string = fields + .iter() + .map(|field| { + let as_u8: u8 = field + .try_to_u64() + .expect("String character doesn't fit in u64") + .try_into() + .expect("String character doesn't fit in u8"); + as_u8 as char + }) + .collect(); + ResolvedAssertionPayload::String(string) + } + _ => { + // If the error selector is not 0, it means the error is a custom error + ResolvedAssertionPayload::Raw(RawAssertionPayload { + selector: error_selector, + data: fields, + }) + } + }) + } + } + } + + fn solve_brillig_call_opcode( &mut self, - ) -> Result, OpcodeResolutionError> { - let Opcode::Brillig(brillig) = &self.opcodes[self.instruction_pointer] else { - unreachable!("Not executing a Brillig opcode"); + ) -> Result>, OpcodeResolutionError> { + let Opcode::BrilligCall { id, inputs, outputs, predicate } = + &self.opcodes[self.instruction_pointer] + else { + unreachable!("Not executing a BrilligCall opcode"); }; - let witness = &mut self.witness_map; - if BrilligSolver::::should_skip(witness, brillig)? { - return BrilligSolver::::zero_out_brillig_outputs(witness, brillig).map(|_| None); + if is_predicate_false(&self.witness_map, predicate)? { + return BrilligSolver::::zero_out_brillig_outputs(&mut self.witness_map, outputs) + .map(|_| None); } // If we're resuming execution after resolving a foreign call then // there will be a cached `BrilligSolver` to avoid recomputation. - let mut solver: BrilligSolver<'_, B> = match self.brillig_solver.take() { + let mut solver: BrilligSolver<'_, F, B> = match self.brillig_solver.take() { Some(solver) => solver, - None => BrilligSolver::new( - witness, + None => BrilligSolver::new_call( + &self.witness_map, &self.block_solvers, - brillig, + inputs, + &self.unconstrained_functions[*id as usize].bytecode, self.backend, self.instruction_pointer, )?, }; - match solver.solve()? { + + let result = solver.solve().map_err(|err| self.map_brillig_error(err))?; + + match result { BrilligSolverStatus::ForeignCallWait(foreign_call) => { // Cache the current state of the solver self.brillig_solver = Some(solver); @@ -357,32 +493,59 @@ impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> { } BrilligSolverStatus::Finished => { // Write execution outputs - solver.finalize(witness, brillig)?; + solver.finalize(&mut self.witness_map, outputs)?; Ok(None) } } } - pub fn step_into_brillig_opcode(&mut self) -> StepResult<'a, B> { - let Opcode::Brillig(brillig) = &self.opcodes[self.instruction_pointer] else { + fn map_brillig_error(&self, mut err: OpcodeResolutionError) -> OpcodeResolutionError { + match &mut err { + OpcodeResolutionError::BrilligFunctionFailed { call_stack, payload } => { + // Some brillig errors have static strings as payloads, we can resolve them here + let last_location = + call_stack.last().expect("Call stacks should have at least one item"); + let assertion_descriptor = + self.assertion_payloads.iter().find_map(|(loc, payload)| { + if loc == last_location { + Some(payload) + } else { + None + } + }); + + if let Some(AssertionPayload::StaticString(string)) = assertion_descriptor { + *payload = Some(ResolvedAssertionPayload::String(string.clone())); + } + + err + } + _ => err, + } + } + + pub fn step_into_brillig(&mut self) -> StepResult<'a, F, B> { + let Opcode::BrilligCall { id, inputs, outputs, predicate } = + &self.opcodes[self.instruction_pointer] + else { return StepResult::Status(self.solve_opcode()); }; let witness = &mut self.witness_map; - let should_skip = match BrilligSolver::::should_skip(witness, brillig) { + let should_skip = match is_predicate_false(witness, predicate) { Ok(result) => result, Err(err) => return StepResult::Status(self.handle_opcode_resolution(Err(err))), }; - if should_skip { - let resolution = BrilligSolver::::zero_out_brillig_outputs(witness, brillig); + let resolution = BrilligSolver::::zero_out_brillig_outputs(witness, outputs); return StepResult::Status(self.handle_opcode_resolution(resolution)); } - let solver = BrilligSolver::new( + let solver = BrilligSolver::new_call( witness, &self.block_solvers, - brillig, + inputs, + &self.unconstrained_functions[*id as usize].bytecode, self.backend, self.instruction_pointer, ); @@ -392,22 +555,74 @@ impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> { } } - pub fn finish_brillig_with_solver(&mut self, solver: BrilligSolver<'a, B>) -> ACVMStatus { - if !matches!(&self.opcodes[self.instruction_pointer], Opcode::Brillig(..)) { - unreachable!("Not executing a Brillig opcode"); + pub fn finish_brillig_with_solver(&mut self, solver: BrilligSolver<'a, F, B>) -> ACVMStatus { + if !matches!(self.opcodes[self.instruction_pointer], Opcode::BrilligCall { .. }) { + unreachable!("Not executing a Brillig/BrilligCall opcode"); } self.brillig_solver = Some(solver); self.solve_opcode() } + + pub fn solve_call_opcode( + &mut self, + ) -> Result>, OpcodeResolutionError> { + let Opcode::Call { id, inputs, outputs, predicate } = + &self.opcodes[self.instruction_pointer] + else { + unreachable!("Not executing a Call opcode"); + }; + if *id == 0 { + return Err(OpcodeResolutionError::AcirMainCallAttempted { + opcode_location: ErrorLocation::Resolved(OpcodeLocation::Acir( + self.instruction_pointer(), + )), + }); + } + + if is_predicate_false(&self.witness_map, predicate)? { + // Zero out the outputs if we have a false predicate + for output in outputs { + insert_value(output, F::zero(), &mut self.witness_map)?; + } + return Ok(None); + } + + if self.acir_call_counter >= self.acir_call_results.len() { + let mut initial_witness = WitnessMap::default(); + for (i, input_witness) in inputs.iter().enumerate() { + let input_value = *witness_to_value(&self.witness_map, *input_witness)?; + initial_witness.insert(Witness(i as u32), input_value); + } + return Ok(Some(AcirCallWaitInfo { id: *id, initial_witness })); + } + + let result_values = &self.acir_call_results[self.acir_call_counter]; + if outputs.len() != result_values.len() { + return Err(OpcodeResolutionError::AcirCallOutputsMismatch { + opcode_location: ErrorLocation::Resolved(OpcodeLocation::Acir( + self.instruction_pointer(), + )), + results_size: result_values.len() as u32, + outputs_size: outputs.len() as u32, + }); + } + + for (output_witness, result_value) in outputs.iter().zip(result_values) { + insert_value(output_witness, *result_value, &mut self.witness_map)?; + } + + self.acir_call_counter += 1; + Ok(None) + } } // Returns the concrete value for a particular witness // If the witness has no assignment, then // an error is returned -pub fn witness_to_value( - initial_witness: &WitnessMap, +pub fn witness_to_value( + initial_witness: &WitnessMap, witness: Witness, -) -> Result<&FieldElement, OpcodeResolutionError> { +) -> Result<&F, OpcodeResolutionError> { match initial_witness.get(&witness) { Some(value) => Ok(value), None => Err(OpcodeNotSolvable::MissingAssignment(witness.0).into()), @@ -416,13 +631,13 @@ pub fn witness_to_value( // TODO: There is an issue open to decide on whether we need to get values from Expressions // TODO versus just getting values from Witness -pub fn get_value( - expr: &Expression, - initial_witness: &WitnessMap, -) -> Result { +pub fn get_value( + expr: &Expression, + initial_witness: &WitnessMap, +) -> Result> { let expr = ExpressionSolver::evaluate(expr, initial_witness); match expr.to_const() { - Some(value) => Ok(value), + Some(value) => Ok(*value), None => Err(OpcodeResolutionError::OpcodeNotSolvable( OpcodeNotSolvable::MissingAssignment(any_witness_from_expression(&expr).unwrap().0), )), @@ -433,11 +648,11 @@ pub fn get_value( /// /// Returns an error if there was already a value in the map /// which does not match the value that one is about to insert -pub fn insert_value( +pub fn insert_value( witness: &Witness, - value_to_insert: FieldElement, - initial_witness: &mut WitnessMap, -) -> Result<(), OpcodeResolutionError> { + value_to_insert: F, + initial_witness: &mut WitnessMap, +) -> Result<(), OpcodeResolutionError> { let optional_old_value = initial_witness.insert(*witness, value_to_insert); let old_value = match optional_old_value { @@ -448,6 +663,7 @@ pub fn insert_value( if old_value != value_to_insert { return Err(OpcodeResolutionError::UnsatisfiedConstrain { opcode_location: ErrorLocation::Unresolved, + payload: None, }); } @@ -457,7 +673,7 @@ pub fn insert_value( // Returns one witness belonging to an expression, in no relevant order // Returns None if the expression is const // The function is used during partial witness generation to report unsolved witness -fn any_witness_from_expression(expr: &Expression) -> Option { +fn any_witness_from_expression(expr: &Expression) -> Option { if expr.linear_combinations.is_empty() { if expr.mul_terms.is_empty() { None @@ -468,3 +684,25 @@ fn any_witness_from_expression(expr: &Expression) -> Option { Some(expr.linear_combinations[0].1) } } + +/// Returns `true` if the predicate is zero +/// A predicate is used to indicate whether we should skip a certain operation. +/// If we have a zero predicate it means the operation should be skipped. +pub(crate) fn is_predicate_false( + witness: &WitnessMap, + predicate: &Option>, +) -> Result> { + match predicate { + Some(pred) => get_value(pred, witness).map(|pred_value| pred_value.is_zero()), + // If the predicate is `None`, then we treat it as an unconditional `true` + None => Ok(false), + } +} + +#[derive(Debug, Clone, PartialEq)] +pub struct AcirCallWaitInfo { + /// Index in the list of ACIR function's that should be called + pub id: u32, + /// Initial witness for the given circuit to be called + pub initial_witness: WitnessMap, +} diff --git a/acvm-repo/acvm/tests/solver.rs b/acvm-repo/acvm/tests/solver.rs index b267c3005a8..e55dbb73ae1 100644 --- a/acvm-repo/acvm/tests/solver.rs +++ b/acvm-repo/acvm/tests/solver.rs @@ -1,14 +1,15 @@ use std::collections::BTreeMap; use acir::{ - brillig::{BinaryFieldOp, MemoryAddress, Opcode as BrilligOpcode, Value, ValueOrArray}, + acir_field::GenericFieldElement, + brillig::{BinaryFieldOp, HeapArray, MemoryAddress, Opcode as BrilligOpcode, ValueOrArray}, circuit::{ - brillig::{Brillig, BrilligInputs, BrilligOutputs}, - opcodes::{BlockId, MemOp}, + brillig::{BrilligBytecode, BrilligInputs, BrilligOutputs}, + opcodes::{BlockId, BlockType, MemOp}, Opcode, OpcodeLocation, }, native_types::{Expression, Witness, WitnessMap}, - FieldElement, + AcirField, FieldElement, }; use acvm::pwg::{ACVMStatus, ErrorLocation, ForeignCallWaitInfo, OpcodeResolutionError, ACVM}; @@ -17,6 +18,38 @@ use brillig_vm::brillig::HeapValueType; // Reenable these test cases once we move the brillig implementation of inversion down into the acvm stdlib. +#[test] +fn bls12_381_circuit() { + type Bls12FieldElement = GenericFieldElement; + + let addition = Opcode::AssertZero(Expression { + mul_terms: Vec::new(), + linear_combinations: vec![ + (Bls12FieldElement::one(), Witness(1)), + (Bls12FieldElement::one(), Witness(2)), + (-Bls12FieldElement::one(), Witness(3)), + ], + q_c: Bls12FieldElement::zero(), + }); + let opcodes = [addition]; + + let witness_assignments = BTreeMap::from([ + (Witness(1), Bls12FieldElement::from(2u128)), + (Witness(2), Bls12FieldElement::from(3u128)), + ]) + .into(); + + let mut acvm = ACVM::new(&StubbedBlackBoxSolver, &opcodes, witness_assignments, &[], &[]); + // use the partial witness generation solver with our acir program + let solver_status = acvm.solve(); + assert_eq!(solver_status, ACVMStatus::Solved, "should be fully solved"); + + // ACVM should be able to be finalized in `Solved` state. + let witness_stack = acvm.finalize(); + + assert_eq!(witness_stack.get(&Witness(3)).unwrap(), &Bls12FieldElement::from(5u128)); +} + #[test] fn inversion_brillig_oracle_equivalence() { // Opcodes below describe the following: @@ -43,44 +76,26 @@ fn inversion_brillig_oracle_equivalence() { destination: MemoryAddress::from(2), }; - let brillig_data = Brillig { - inputs: vec![ - BrilligInputs::Single(Expression { - // Input Register 0 - mul_terms: vec![], - linear_combinations: vec![(fe_1, w_x), (fe_1, w_y)], - q_c: fe_0, - }), - BrilligInputs::Single(Expression::default()), // Input Register 1 - ], - // This tells the BrilligSolver which witnesses its output values correspond to - outputs: vec![ - BrilligOutputs::Simple(w_x_plus_y), // Output Register 0 - from input - BrilligOutputs::Simple(w_oracle), // Output Register 1 - BrilligOutputs::Simple(w_equal_res), // Output Register 2 - ], - bytecode: vec![ - BrilligOpcode::CalldataCopy { - destination_address: MemoryAddress(0), - size: 2, - offset: 0, - }, - equal_opcode, - // Oracles are named 'foreign calls' in brillig - BrilligOpcode::ForeignCall { - function: "invert".into(), - destinations: vec![ValueOrArray::MemoryAddress(MemoryAddress::from(1))], - destination_value_types: vec![HeapValueType::Simple], - inputs: vec![ValueOrArray::MemoryAddress(MemoryAddress::from(0))], - input_value_types: vec![HeapValueType::Simple], - }, - BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 3 }, - ], - predicate: None, - }; - let opcodes = vec![ - Opcode::Brillig(brillig_data), + Opcode::BrilligCall { + id: 0, + inputs: vec![ + BrilligInputs::Single(Expression { + // Input Register 0 + mul_terms: vec![], + linear_combinations: vec![(fe_1, w_x), (fe_1, w_y)], + q_c: fe_0, + }), + BrilligInputs::Single(Expression::default()), // Input Register 1 + ], + // This tells the BrilligSolver which witnesses its output values correspond to + outputs: vec![ + BrilligOutputs::Simple(w_x_plus_y), // Output Register 0 - from input + BrilligOutputs::Simple(w_oracle), // Output Register 1 + BrilligOutputs::Simple(w_equal_res), // Output Register 2 + ], + predicate: None, + }, Opcode::AssertZero(Expression { mul_terms: vec![], linear_combinations: vec![(fe_1, w_x), (fe_1, w_y), (-fe_1, w_z)], @@ -99,13 +114,39 @@ fn inversion_brillig_oracle_equivalence() { }), ]; + let brillig_bytecode = BrilligBytecode { + bytecode: vec![ + BrilligOpcode::CalldataCopy { + destination_address: MemoryAddress(0), + size: 2, + offset: 0, + }, + equal_opcode, + // Oracles are named 'foreign calls' in brillig + BrilligOpcode::ForeignCall { + function: "invert".into(), + destinations: vec![ValueOrArray::MemoryAddress(MemoryAddress::from(1))], + destination_value_types: vec![HeapValueType::field()], + inputs: vec![ValueOrArray::MemoryAddress(MemoryAddress::from(0))], + input_value_types: vec![HeapValueType::field()], + }, + BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 3 }, + ], + }; + let witness_assignments = BTreeMap::from([ (Witness(1), FieldElement::from(2u128)), (Witness(2), FieldElement::from(3u128)), ]) .into(); - - let mut acvm = ACVM::new(&StubbedBlackBoxSolver, &opcodes, witness_assignments); + let unconstrained_functions = vec![brillig_bytecode]; + let mut acvm = ACVM::new( + &StubbedBlackBoxSolver, + &opcodes, + witness_assignments, + &unconstrained_functions, + &[], + ); // use the partial witness generation solver with our acir program let solver_status = acvm.solve(); @@ -115,13 +156,12 @@ fn inversion_brillig_oracle_equivalence() { ); assert_eq!(acvm.instruction_pointer(), 0, "brillig should have been removed"); - let foreign_call_wait_info: &ForeignCallWaitInfo = + let foreign_call_wait_info: &ForeignCallWaitInfo = acvm.get_pending_foreign_call().expect("should have a brillig foreign call request"); assert_eq!(foreign_call_wait_info.inputs.len(), 1, "Should be waiting for a single input"); // As caller of VM, need to resolve foreign calls - let foreign_call_result = - Value::from(foreign_call_wait_info.inputs[0].unwrap_value().to_field().inverse()); + let foreign_call_result = foreign_call_wait_info.inputs[0].unwrap_field().inverse(); // Alter Brillig oracle opcode with foreign call resolution acvm.resolve_pending_foreign_call(foreign_call_result.into()); @@ -165,29 +205,52 @@ fn double_inversion_brillig_oracle() { destination: MemoryAddress::from(4), }; - let brillig_data = Brillig { - inputs: vec![ - BrilligInputs::Single(Expression { - // Input Register 0 - mul_terms: vec![], - linear_combinations: vec![(fe_1, w_x), (fe_1, w_y)], - q_c: fe_0, - }), - BrilligInputs::Single(Expression::default()), // Input Register 1 - BrilligInputs::Single(Expression { - // Input Register 2 - mul_terms: vec![], - linear_combinations: vec![(fe_1, w_i), (fe_1, w_j)], - q_c: fe_0, - }), - ], - outputs: vec![ - BrilligOutputs::Simple(w_x_plus_y), // Output Register 0 - from input - BrilligOutputs::Simple(w_oracle), // Output Register 1 - BrilligOutputs::Simple(w_i_plus_j), // Output Register 2 - from input - BrilligOutputs::Simple(w_ij_oracle), // Output Register 3 - BrilligOutputs::Simple(w_equal_res), // Output Register 4 - ], + let opcodes = vec![ + Opcode::BrilligCall { + id: 0, + inputs: vec![ + BrilligInputs::Single(Expression { + // Input Register 0 + mul_terms: vec![], + linear_combinations: vec![(fe_1, w_x), (fe_1, w_y)], + q_c: fe_0, + }), + BrilligInputs::Single(Expression::default()), // Input Register 1 + BrilligInputs::Single(Expression { + // Input Register 2 + mul_terms: vec![], + linear_combinations: vec![(fe_1, w_i), (fe_1, w_j)], + q_c: fe_0, + }), + ], + outputs: vec![ + BrilligOutputs::Simple(w_x_plus_y), // Output Register 0 - from input + BrilligOutputs::Simple(w_oracle), // Output Register 1 + BrilligOutputs::Simple(w_i_plus_j), // Output Register 2 - from input + BrilligOutputs::Simple(w_ij_oracle), // Output Register 3 + BrilligOutputs::Simple(w_equal_res), // Output Register 4 + ], + predicate: None, + }, + Opcode::AssertZero(Expression { + mul_terms: vec![], + linear_combinations: vec![(fe_1, w_x), (fe_1, w_y), (-fe_1, w_z)], + q_c: fe_0, + }), + // Opcode::Directive(Directive::Invert { x: w_z, result: w_z_inverse }), + Opcode::AssertZero(Expression { + mul_terms: vec![(fe_1, w_z, w_z_inverse)], + linear_combinations: vec![], + q_c: -fe_1, + }), + Opcode::AssertZero(Expression { + mul_terms: vec![], + linear_combinations: vec![(-fe_1, w_oracle), (fe_1, w_z_inverse)], + q_c: fe_0, + }), + ]; + + let brillig_bytecode = BrilligBytecode { bytecode: vec![ BrilligOpcode::CalldataCopy { destination_address: MemoryAddress(0), @@ -199,42 +262,21 @@ fn double_inversion_brillig_oracle() { BrilligOpcode::ForeignCall { function: "invert".into(), destinations: vec![ValueOrArray::MemoryAddress(MemoryAddress::from(1))], - destination_value_types: vec![HeapValueType::Simple], + destination_value_types: vec![HeapValueType::field()], inputs: vec![ValueOrArray::MemoryAddress(MemoryAddress::from(0))], - input_value_types: vec![HeapValueType::Simple], + input_value_types: vec![HeapValueType::field()], }, BrilligOpcode::ForeignCall { function: "invert".into(), destinations: vec![ValueOrArray::MemoryAddress(MemoryAddress::from(3))], - destination_value_types: vec![HeapValueType::Simple], + destination_value_types: vec![HeapValueType::field()], inputs: vec![ValueOrArray::MemoryAddress(MemoryAddress::from(2))], - input_value_types: vec![HeapValueType::Simple], + input_value_types: vec![HeapValueType::field()], }, BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 5 }, ], - predicate: None, }; - let opcodes = vec![ - Opcode::Brillig(brillig_data), - Opcode::AssertZero(Expression { - mul_terms: vec![], - linear_combinations: vec![(fe_1, w_x), (fe_1, w_y), (-fe_1, w_z)], - q_c: fe_0, - }), - // Opcode::Directive(Directive::Invert { x: w_z, result: w_z_inverse }), - Opcode::AssertZero(Expression { - mul_terms: vec![(fe_1, w_z, w_z_inverse)], - linear_combinations: vec![], - q_c: -fe_1, - }), - Opcode::AssertZero(Expression { - mul_terms: vec![], - linear_combinations: vec![(-fe_1, w_oracle), (fe_1, w_z_inverse)], - q_c: fe_0, - }), - ]; - let witness_assignments = BTreeMap::from([ (Witness(1), FieldElement::from(2u128)), (Witness(2), FieldElement::from(3u128)), @@ -242,8 +284,14 @@ fn double_inversion_brillig_oracle() { (Witness(9), FieldElement::from(10u128)), ]) .into(); - - let mut acvm = ACVM::new(&StubbedBlackBoxSolver, &opcodes, witness_assignments); + let unconstrained_functions = vec![brillig_bytecode]; + let mut acvm = ACVM::new( + &StubbedBlackBoxSolver, + &opcodes, + witness_assignments, + &unconstrained_functions, + &[], + ); // use the partial witness generation solver with our acir program let solver_status = acvm.solve(); @@ -253,12 +301,11 @@ fn double_inversion_brillig_oracle() { ); assert_eq!(acvm.instruction_pointer(), 0, "should stall on brillig"); - let foreign_call_wait_info: &ForeignCallWaitInfo = + let foreign_call_wait_info: &ForeignCallWaitInfo = acvm.get_pending_foreign_call().expect("should have a brillig foreign call request"); assert_eq!(foreign_call_wait_info.inputs.len(), 1, "Should be waiting for a single input"); - let x_plus_y_inverse = - Value::from(foreign_call_wait_info.inputs[0].unwrap_value().to_field().inverse()); + let x_plus_y_inverse = foreign_call_wait_info.inputs[0].unwrap_field().inverse(); // Resolve Brillig foreign call acvm.resolve_pending_foreign_call(x_plus_y_inverse.into()); @@ -275,8 +322,7 @@ fn double_inversion_brillig_oracle() { acvm.get_pending_foreign_call().expect("should have a brillig foreign call request"); assert_eq!(foreign_call_wait_info.inputs.len(), 1, "Should be waiting for a single input"); - let i_plus_j_inverse = - Value::from(foreign_call_wait_info.inputs[0].unwrap_value().to_field().inverse()); + let i_plus_j_inverse = foreign_call_wait_info.inputs[0].unwrap_field().inverse(); assert_ne!(x_plus_y_inverse, i_plus_j_inverse); // Alter Brillig oracle opcode @@ -312,18 +358,7 @@ fn oracle_dependent_execution() { let w_x_inv = Witness(3); let w_y_inv = Witness(4); - let brillig_data = Brillig { - inputs: vec![ - BrilligInputs::Single(w_x.into()), // Input Register 0 - BrilligInputs::Single(Expression::default()), // Input Register 1 - BrilligInputs::Single(w_y.into()), // Input Register 2, - ], - outputs: vec![ - BrilligOutputs::Simple(w_x), // Output Register 0 - from input - BrilligOutputs::Simple(w_y_inv), // Output Register 1 - BrilligOutputs::Simple(w_y), // Output Register 2 - from input - BrilligOutputs::Simple(w_y_inv), // Output Register 3 - ], + let brillig_bytecode = BrilligBytecode { bytecode: vec![ BrilligOpcode::CalldataCopy { destination_address: MemoryAddress(0), @@ -334,20 +369,19 @@ fn oracle_dependent_execution() { BrilligOpcode::ForeignCall { function: "invert".into(), destinations: vec![ValueOrArray::MemoryAddress(MemoryAddress::from(1))], - destination_value_types: vec![HeapValueType::Simple], + destination_value_types: vec![HeapValueType::field()], inputs: vec![ValueOrArray::MemoryAddress(MemoryAddress::from(0))], - input_value_types: vec![HeapValueType::Simple], + input_value_types: vec![HeapValueType::field()], }, BrilligOpcode::ForeignCall { function: "invert".into(), destinations: vec![ValueOrArray::MemoryAddress(MemoryAddress::from(3))], - destination_value_types: vec![HeapValueType::Simple], + destination_value_types: vec![HeapValueType::field()], inputs: vec![ValueOrArray::MemoryAddress(MemoryAddress::from(2))], - input_value_types: vec![HeapValueType::Simple], + input_value_types: vec![HeapValueType::field()], }, BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 4 }, ], - predicate: None, }; // This equality check can be executed immediately before resolving any foreign calls. @@ -367,14 +401,34 @@ fn oracle_dependent_execution() { let opcodes = vec![ Opcode::AssertZero(equality_check), - Opcode::Brillig(brillig_data), + Opcode::BrilligCall { + id: 0, + inputs: vec![ + BrilligInputs::Single(w_x.into()), // Input Register 0 + BrilligInputs::Single(Expression::default()), // Input Register 1 + BrilligInputs::Single(w_y.into()), // Input Register 2, + ], + outputs: vec![ + BrilligOutputs::Simple(w_x), // Output Register 0 - from input + BrilligOutputs::Simple(w_y_inv), // Output Register 1 + BrilligOutputs::Simple(w_y), // Output Register 2 - from input + BrilligOutputs::Simple(w_y_inv), // Output Register 3 + ], + predicate: None, + }, Opcode::AssertZero(inverse_equality_check), ]; let witness_assignments = BTreeMap::from([(w_x, FieldElement::from(2u128)), (w_y, FieldElement::from(2u128))]).into(); - - let mut acvm = ACVM::new(&StubbedBlackBoxSolver, &opcodes, witness_assignments); + let unconstrained_functions = vec![brillig_bytecode]; + let mut acvm = ACVM::new( + &StubbedBlackBoxSolver, + &opcodes, + witness_assignments, + &unconstrained_functions, + &[], + ); // use the partial witness generation solver with our acir program let solver_status = acvm.solve(); @@ -384,13 +438,12 @@ fn oracle_dependent_execution() { ); assert_eq!(acvm.instruction_pointer(), 1, "should stall on brillig"); - let foreign_call_wait_info: &ForeignCallWaitInfo = + let foreign_call_wait_info: &ForeignCallWaitInfo = acvm.get_pending_foreign_call().expect("should have a brillig foreign call request"); assert_eq!(foreign_call_wait_info.inputs.len(), 1, "Should be waiting for a single input"); // Resolve Brillig foreign call - let x_inverse = - Value::from(foreign_call_wait_info.inputs[0].unwrap_value().to_field().inverse()); + let x_inverse = foreign_call_wait_info.inputs[0].unwrap_field().inverse(); acvm.resolve_pending_foreign_call(x_inverse.into()); // After filling data request, continue solving @@ -401,13 +454,12 @@ fn oracle_dependent_execution() { ); assert_eq!(acvm.instruction_pointer(), 1, "should stall on brillig"); - let foreign_call_wait_info: &ForeignCallWaitInfo = + let foreign_call_wait_info: &ForeignCallWaitInfo = acvm.get_pending_foreign_call().expect("should have a brillig foreign call request"); assert_eq!(foreign_call_wait_info.inputs.len(), 1, "Should be waiting for a single input"); // Resolve Brillig foreign call - let y_inverse = - Value::from(foreign_call_wait_info.inputs[0].unwrap_value().to_field().inverse()); + let y_inverse = foreign_call_wait_info.inputs[0].unwrap_field().inverse(); acvm.resolve_pending_foreign_call(y_inverse.into()); // We've resolved all the brillig foreign calls so we should be able to complete execution now. @@ -438,21 +490,7 @@ fn brillig_oracle_predicate() { destination: MemoryAddress::from(2), }; - let brillig_opcode = Opcode::Brillig(Brillig { - inputs: vec![ - BrilligInputs::Single(Expression { - mul_terms: vec![], - linear_combinations: vec![(fe_1, w_x), (fe_1, w_y)], - q_c: fe_0, - }), - BrilligInputs::Single(Expression::default()), - ], - outputs: vec![ - BrilligOutputs::Simple(w_x_plus_y), - BrilligOutputs::Simple(w_oracle), - BrilligOutputs::Simple(w_equal_res), - BrilligOutputs::Simple(w_lt_res), - ], + let brillig_bytecode = BrilligBytecode { bytecode: vec![ BrilligOpcode::CalldataCopy { destination_address: MemoryAddress(0), @@ -464,23 +502,45 @@ fn brillig_oracle_predicate() { BrilligOpcode::ForeignCall { function: "invert".into(), destinations: vec![ValueOrArray::MemoryAddress(MemoryAddress::from(1))], - destination_value_types: vec![HeapValueType::Simple], + destination_value_types: vec![HeapValueType::field()], inputs: vec![ValueOrArray::MemoryAddress(MemoryAddress::from(0))], - input_value_types: vec![HeapValueType::Simple], + input_value_types: vec![HeapValueType::field()], }, ], - predicate: Some(Expression::default()), - }); + }; - let opcodes = vec![brillig_opcode]; + let opcodes = vec![Opcode::BrilligCall { + id: 0, + inputs: vec![ + BrilligInputs::Single(Expression { + mul_terms: vec![], + linear_combinations: vec![(fe_1, w_x), (fe_1, w_y)], + q_c: fe_0, + }), + BrilligInputs::Single(Expression::default()), + ], + outputs: vec![ + BrilligOutputs::Simple(w_x_plus_y), + BrilligOutputs::Simple(w_oracle), + BrilligOutputs::Simple(w_equal_res), + BrilligOutputs::Simple(w_lt_res), + ], + predicate: Some(Expression::default()), + }]; let witness_assignments = BTreeMap::from([ (Witness(1), FieldElement::from(2u128)), (Witness(2), FieldElement::from(3u128)), ]) .into(); - - let mut acvm = ACVM::new(&StubbedBlackBoxSolver, &opcodes, witness_assignments); + let unconstrained_functions = vec![brillig_bytecode]; + let mut acvm = ACVM::new( + &StubbedBlackBoxSolver, + &opcodes, + witness_assignments, + &unconstrained_functions, + &[], + ); let solver_status = acvm.solve(); assert_eq!(solver_status, ACVMStatus::Solved, "should be fully solved"); @@ -514,12 +574,15 @@ fn unsatisfied_opcode_resolved() { values.insert(d, FieldElement::from(2_i128)); let opcodes = vec![Opcode::AssertZero(opcode_a)]; - let mut acvm = ACVM::new(&StubbedBlackBoxSolver, &opcodes, values); + let unconstrained_functions = vec![]; + let mut acvm = + ACVM::new(&StubbedBlackBoxSolver, &opcodes, values, &unconstrained_functions, &[]); let solver_status = acvm.solve(); assert_eq!( solver_status, ACVMStatus::Failure(OpcodeResolutionError::UnsatisfiedConstrain { opcode_location: ErrorLocation::Resolved(OpcodeLocation::Acir(0)), + payload: None }), "The first opcode is not satisfiable, expected an error indicating this" ); @@ -554,26 +617,12 @@ fn unsatisfied_opcode_resolved_brillig() { let jmp_if_opcode = BrilligOpcode::JumpIf { condition: MemoryAddress::from(2), location: location_of_stop }; - let trap_opcode = BrilligOpcode::Trap; + let trap_opcode = BrilligOpcode::Trap { revert_data: HeapArray::default() }; let stop_opcode = BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 0 }; - let brillig_opcode = Opcode::Brillig(Brillig { - inputs: vec![ - BrilligInputs::Single(Expression { - mul_terms: vec![], - linear_combinations: vec![(fe_1, w_x)], - q_c: fe_0, - }), - BrilligInputs::Single(Expression { - mul_terms: vec![], - linear_combinations: vec![(fe_1, w_y)], - q_c: fe_0, - }), - ], - outputs: vec![BrilligOutputs::Simple(w_result)], + let brillig_bytecode = BrilligBytecode { bytecode: vec![calldata_copy_opcode, equal_opcode, jmp_if_opcode, trap_opcode, stop_opcode], - predicate: Some(Expression::one()), - }); + }; let opcode_a = Expression { mul_terms: vec![], @@ -595,14 +644,34 @@ fn unsatisfied_opcode_resolved_brillig() { values.insert(w_y, FieldElement::from(1_i128)); values.insert(w_result, FieldElement::from(0_i128)); - let opcodes = vec![brillig_opcode, Opcode::AssertZero(opcode_a)]; - - let mut acvm = ACVM::new(&StubbedBlackBoxSolver, &opcodes, values); + let opcodes = vec![ + Opcode::BrilligCall { + id: 0, + inputs: vec![ + BrilligInputs::Single(Expression { + mul_terms: vec![], + linear_combinations: vec![(fe_1, w_x)], + q_c: fe_0, + }), + BrilligInputs::Single(Expression { + mul_terms: vec![], + linear_combinations: vec![(fe_1, w_y)], + q_c: fe_0, + }), + ], + outputs: vec![BrilligOutputs::Simple(w_result)], + predicate: Some(Expression::one()), + }, + Opcode::AssertZero(opcode_a), + ]; + let unconstrained_functions = vec![brillig_bytecode]; + let mut acvm = + ACVM::new(&StubbedBlackBoxSolver, &opcodes, values, &unconstrained_functions, &[]); let solver_status = acvm.solve(); assert_eq!( solver_status, ACVMStatus::Failure(OpcodeResolutionError::BrilligFunctionFailed { - message: "explicit trap hit in brillig".to_string(), + payload: None, call_stack: vec![OpcodeLocation::Brillig { acir_index: 0, brillig_index: 3 }] }), "The first opcode is not satisfiable, expected an error indicating this" @@ -622,7 +691,11 @@ fn memory_operations() { let block_id = BlockId(0); - let init = Opcode::MemoryInit { block_id, init: (1..6).map(Witness).collect() }; + let init = Opcode::MemoryInit { + block_id, + init: (1..6).map(Witness).collect(), + block_type: BlockType::Memory, + }; let read_op = Opcode::MemoryOp { block_id, @@ -640,8 +713,9 @@ fn memory_operations() { }); let opcodes = vec![init, read_op, expression]; - - let mut acvm = ACVM::new(&StubbedBlackBoxSolver, &opcodes, initial_witness); + let unconstrained_functions = vec![]; + let mut acvm = + ACVM::new(&StubbedBlackBoxSolver, &opcodes, initial_witness, &unconstrained_functions, &[]); let solver_status = acvm.solve(); assert_eq!(solver_status, ACVMStatus::Solved); let witness_map = acvm.finalize(); diff --git a/acvm-repo/acvm_js/Cargo.toml b/acvm-repo/acvm_js/Cargo.toml index 7ec814a72e5..63f64e97729 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.40.0" +version = "0.46.0" # x-release-please-end authors.workspace = true edition.workspace = true @@ -16,22 +16,23 @@ repository.workspace = true crate-type = ["cdylib"] [dependencies] -cfg-if = "1.0.0" - -[target.'cfg(target_arch = "wasm32")'.dependencies] acvm.workspace = true bn254_blackbox_solver = { workspace = true, optional = true } wasm-bindgen.workspace = true wasm-bindgen-futures.workspace = true console_error_panic_hook.workspace = true gloo-utils.workspace = true -js-sys.workspace = true +js-sys.workspace = true +serde.workspace = true tracing-subscriber.workspace = true tracing-web.workspace = true -serde = { version = "1.0.136", features = ["derive"] } const-str = "0.5.5" +# This is an unused dependency, we are adding it +# so that we can enable the js feature in getrandom. +getrandom = { workspace = true, features = ["js"] } + [build-dependencies] build-data.workspace = true pkg-config = "0.3" diff --git a/acvm-repo/acvm_js/build.sh b/acvm-repo/acvm_js/build.sh index 24af149bcea..ee93413ab85 100755 --- a/acvm-repo/acvm_js/build.sh +++ b/acvm-repo/acvm_js/build.sh @@ -6,13 +6,6 @@ function require_command { exit 1 fi } -function check_installed { - if ! command -v "$1" >/dev/null 2>&1; then - echo "$1 is not installed. Please install it." >&2 - return 1 - fi - return 0 -} function run_or_fail { "$@" local status=$? @@ -21,27 +14,40 @@ function run_or_fail { exit $status fi } +function run_if_available { + if command -v "$1" >/dev/null 2>&1; then + "$@" + else + echo "$1 is not installed. Please install it to use this feature." >&2 + fi +} require_command jq require_command cargo require_command wasm-bindgen -check_installed wasm-opt +# require_command wasm-opt self_path=$(dirname "$(readlink -f "$0")") -export pname=$(cargo read-manifest | jq -r '.name') -export CARGO_TARGET_DIR=$self_path/target +pname=$(cargo read-manifest | jq -r '.name') -rm -rf $self_path/outputs >/dev/null 2>&1 -rm -rf $self_path/result >/dev/null 2>&1 +NODE_DIR=$self_path/nodejs +BROWSER_DIR=$self_path/web -if [ -n "$out" ]; then - echo "Will install package to $out (defined outside installPhase.sh script)" -else - export out="$self_path/outputs/out" - echo "Will install package to $out" +# Clear out the existing build artifacts as these aren't automatically removed by wasm-bindgen. +if [ -d ./pkg/ ]; then + rm -r $NODE_DIR + rm -r $BROWSER_DIR fi -run_or_fail $self_path/buildPhaseCargoCommand.sh -run_or_fail $self_path/installPhase.sh +TARGET=wasm32-unknown-unknown +WASM_BINARY=${self_path}/../../target/$TARGET/release/${pname}.wasm + +NODE_WASM=${NODE_DIR}/${pname}_bg.wasm +BROWSER_WASM=${BROWSER_DIR}/${pname}_bg.wasm -ln -s $out $self_path/result +# Build the new wasm package +run_or_fail cargo build --lib --release --target $TARGET --package ${pname} +run_or_fail wasm-bindgen $WASM_BINARY --out-dir $NODE_DIR --typescript --target nodejs +run_or_fail wasm-bindgen $WASM_BINARY --out-dir $BROWSER_DIR --typescript --target web +run_if_available wasm-opt $NODE_WASM -o $NODE_WASM -O +run_if_available wasm-opt $BROWSER_WASM -o $BROWSER_WASM -O diff --git a/acvm-repo/acvm_js/buildPhaseCargoCommand.sh b/acvm-repo/acvm_js/buildPhaseCargoCommand.sh deleted file mode 100755 index 6c710bc938f..00000000000 --- a/acvm-repo/acvm_js/buildPhaseCargoCommand.sh +++ /dev/null @@ -1,42 +0,0 @@ -#!/usr/bin/env bash - -function run_or_fail { - "$@" - local status=$? - if [ $status -ne 0 ]; then - echo "Command '$*' failed with exit code $status" >&2 - exit $status - fi -} -function run_if_available { - if command -v "$1" >/dev/null 2>&1; then - "$@" - else - echo "$1 is not installed. Please install it to use this feature." >&2 - fi -} - -export self_path=$(dirname "$(readlink -f "$0")") - - -NODE_DIR=$self_path/nodejs/ -BROWSER_DIR=$self_path/web/ - -# Clear out the existing build artifacts as these aren't automatically removed by wasm-pack. -if [ -d ./pkg/ ]; then - rm -r $NODE_DIR - rm -r $BROWSER_DIR -fi - -TARGET=wasm32-unknown-unknown -WASM_BINARY=$CARGO_TARGET_DIR/$TARGET/release/${pname}.wasm - -NODE_WASM=${NODE_DIR}/${pname}_bg.wasm -BROWSER_WASM=${BROWSER_DIR}/${pname}_bg.wasm - -# Build the new wasm package -run_or_fail cargo build --lib --release --target $TARGET --package ${pname} -run_or_fail wasm-bindgen $WASM_BINARY --out-dir $NODE_DIR --typescript --target nodejs -run_or_fail wasm-bindgen $WASM_BINARY --out-dir $BROWSER_DIR --typescript --target web -run_if_available wasm-opt $NODE_WASM -o $NODE_WASM -O -run_if_available wasm-opt $BROWSER_WASM -o $BROWSER_WASM -O diff --git a/acvm-repo/acvm_js/installPhase.sh b/acvm-repo/acvm_js/installPhase.sh deleted file mode 100755 index 34ddb8155e1..00000000000 --- a/acvm-repo/acvm_js/installPhase.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env bash -export self_path=$(dirname "$(readlink -f "$0")") - -export out_path=$out/acvm_js - -mkdir -p $out_path -cp $self_path/README.md $out_path/ -cp $self_path/package.json $out_path/ -cp -r $self_path/nodejs $out_path/ -cp -r $self_path/web $out_path/ diff --git a/acvm-repo/acvm_js/package.json b/acvm-repo/acvm_js/package.json index 876db9ccb62..48c5b2a8644 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.40.0", + "version": "0.46.0", "publishConfig": { "access": "public" }, @@ -34,21 +34,19 @@ "lint": "NODE_NO_WARNINGS=1 eslint . --ext .ts --ignore-path ./.eslintignore --max-warnings 0", "publish": "echo 📡 publishing `$npm_package_name` && yarn npm publish", "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", - "clean": "chmod u+w web nodejs || true && rm -rf web nodejs", - "build:nix": "nix build -L .#acvm_js", - "install:from:nix": "yarn clean && yarn build:nix && cp -rL ./result/acvm_js/nodejs ./ && cp -rL ./result/acvm_js/web ./" + "clean": "chmod u+w web nodejs || true && rm -rf web nodejs" }, "devDependencies": { "@esm-bundle/chai": "^4.3.4-fix.0", "@web/dev-server-esbuild": "^0.3.6", - "@web/test-runner": "^0.15.3", + "@web/test-runner": "^0.18.1", "@web/test-runner-playwright": "^0.10.0", - "chai": "^4.3.7", - "eslint": "^8.56.0", - "eslint-plugin-prettier": "^5.0.0", + "chai": "^4.4.1", + "eslint": "^8.57.0", + "eslint-plugin-prettier": "^5.1.3", "mocha": "^10.2.0", - "prettier": "3.0.3", + "prettier": "3.2.5", "ts-node": "^10.9.1", - "typescript": "^5.0.4" + "typescript": "^5.4.2" } } diff --git a/acvm-repo/acvm_js/src/black_box_solvers.rs b/acvm-repo/acvm_js/src/black_box_solvers.rs index fc0e3b28ebf..4f2676f8d2f 100644 --- a/acvm-repo/acvm_js/src/black_box_solvers.rs +++ b/acvm-repo/acvm_js/src/black_box_solvers.rs @@ -2,7 +2,7 @@ use js_sys::JsString; use wasm_bindgen::prelude::*; use crate::js_witness_map::{field_element_to_js_string, js_value_to_field_element}; -use acvm::FieldElement; +use acvm::{acir::AcirField, FieldElement}; /// Performs a bitwise AND operation between `lhs` and `rhs` #[wasm_bindgen] @@ -59,7 +59,6 @@ pub fn ecdsa_secp256k1_verify( signature, ) .unwrap() - .into() } /// Verifies a ECDSA signature over the secp256r1 curve. @@ -81,5 +80,4 @@ pub fn ecdsa_secp256r1_verify( signature, ) .unwrap() - .into() } diff --git a/acvm-repo/acvm_js/src/compression.rs b/acvm-repo/acvm_js/src/compression.rs index fedaa514bf0..8114e0d57d2 100644 --- a/acvm-repo/acvm_js/src/compression.rs +++ b/acvm-repo/acvm_js/src/compression.rs @@ -1,25 +1,27 @@ -use acvm::acir::native_types::WitnessMap; +use acvm::acir::native_types::{WitnessMap, WitnessStack}; use js_sys::JsString; use wasm_bindgen::prelude::wasm_bindgen; -use crate::JsWitnessMap; +use crate::{JsWitnessMap, JsWitnessStack}; /// Compresses a `WitnessMap` into the binary format outputted by Nargo. /// -/// @param {Uint8Array} compressed_witness - A witness map. -/// @returns {WitnessMap} A compressed witness map +/// @param {WitnessMap} witness_map - A witness map. +/// @returns {Uint8Array} A compressed witness map #[wasm_bindgen(js_name = compressWitness, skip_jsdoc)] pub fn compress_witness(witness_map: JsWitnessMap) -> Result, JsString> { console_error_panic_hook::set_once(); let witness_map = WitnessMap::from(witness_map); - let compressed_witness_map: Vec = - Vec::::try_from(witness_map).map_err(|err| err.to_string())?; + let witness_stack = WitnessStack::from(witness_map); + let compressed_witness_stack: Vec = + Vec::::try_from(witness_stack).map_err(|err| err.to_string())?; - Ok(compressed_witness_map) + Ok(compressed_witness_stack) } /// Decompresses a compressed witness as outputted by Nargo into a `WitnessMap`. +/// This should be used to only fetch the witness map for the main function. /// /// @param {Uint8Array} compressed_witness - A compressed witness. /// @returns {WitnessMap} The decompressed witness map. @@ -27,8 +29,39 @@ pub fn compress_witness(witness_map: JsWitnessMap) -> Result, JsString> pub fn decompress_witness(compressed_witness: Vec) -> Result { console_error_panic_hook::set_once(); - let witness_map = - WitnessMap::try_from(compressed_witness.as_slice()).map_err(|err| err.to_string())?; + let mut witness_stack = + WitnessStack::try_from(compressed_witness.as_slice()).map_err(|err| err.to_string())?; - Ok(witness_map.into()) + let witness = + witness_stack.pop().expect("Should have at least one witness on the stack").witness; + Ok(witness.into()) +} + +/// Compresses a `WitnessStack` into the binary format outputted by Nargo. +/// +/// @param {WitnessStack} witness_stack - A witness stack. +/// @returns {Uint8Array} A compressed witness stack +#[wasm_bindgen(js_name = compressWitnessStack, skip_jsdoc)] +pub fn compress_witness_stack(witness_stack: JsWitnessStack) -> Result, JsString> { + console_error_panic_hook::set_once(); + + let witness_stack = WitnessStack::from(witness_stack); + let compressed_witness_stack: Vec = + Vec::::try_from(witness_stack).map_err(|err| err.to_string())?; + + Ok(compressed_witness_stack) +} + +/// Decompresses a compressed witness stack as outputted by Nargo into a `WitnessStack`. +/// +/// @param {Uint8Array} compressed_witness - A compressed witness. +/// @returns {WitnessStack} The decompressed witness stack. +#[wasm_bindgen(js_name = decompressWitnessStack, skip_jsdoc)] +pub fn decompress_witness_stack(compressed_witness: Vec) -> Result { + console_error_panic_hook::set_once(); + + let witness_stack = + WitnessStack::try_from(compressed_witness.as_slice()).map_err(|err| err.to_string())?; + + Ok(witness_stack.into()) } diff --git a/acvm-repo/acvm_js/src/execute.rs b/acvm-repo/acvm_js/src/execute.rs index 3f691e1abf2..94ef30604e2 100644 --- a/acvm-repo/acvm_js/src/execute.rs +++ b/acvm-repo/acvm_js/src/execute.rs @@ -1,7 +1,13 @@ +use std::{future::Future, pin::Pin}; + +use acvm::acir::circuit::brillig::BrilligBytecode; +use acvm::acir::circuit::ResolvedAssertionPayload; use acvm::{ - acir::circuit::Circuit, + acir::circuit::{Circuit, Program}, + acir::native_types::{WitnessMap, WitnessStack}, pwg::{ACVMStatus, ErrorLocation, OpcodeResolutionError, ACVM}, }; +use acvm::{BlackBoxFunctionSolver, FieldElement}; use bn254_blackbox_solver::Bn254BlackBoxSolver; use js_sys::Error; @@ -9,23 +15,10 @@ use wasm_bindgen::prelude::wasm_bindgen; use crate::{ foreign_call::{resolve_brillig, ForeignCallHandler}, - JsExecutionError, JsWitnessMap, + public_witness::extract_indices, + JsExecutionError, JsSolvedAndReturnWitness, JsWitnessMap, JsWitnessStack, }; -#[wasm_bindgen] -pub struct WasmBlackBoxFunctionSolver(Bn254BlackBoxSolver); - -impl WasmBlackBoxFunctionSolver { - async fn initialize() -> WasmBlackBoxFunctionSolver { - WasmBlackBoxFunctionSolver(Bn254BlackBoxSolver::initialize().await) - } -} - -#[wasm_bindgen(js_name = "createBlackBoxSolver")] -pub async fn create_black_box_solver() -> WasmBlackBoxFunctionSolver { - WasmBlackBoxFunctionSolver::initialize().await -} - /// Executes an ACIR circuit to generate the solved witness from the initial witness. /// /// @param {Uint8Array} circuit - A serialized representation of an ACIR circuit @@ -34,80 +27,242 @@ pub async fn create_black_box_solver() -> WasmBlackBoxFunctionSolver { /// @returns {WitnessMap} The solved witness calculated by executing the circuit on the provided inputs. #[wasm_bindgen(js_name = executeCircuit, skip_jsdoc)] pub async fn execute_circuit( - circuit: Vec, + program: Vec, initial_witness: JsWitnessMap, foreign_call_handler: ForeignCallHandler, ) -> Result { console_error_panic_hook::set_once(); - let solver = WasmBlackBoxFunctionSolver::initialize().await; - - execute_circuit_with_black_box_solver(&solver, circuit, initial_witness, foreign_call_handler) - .await + let mut witness_stack = + execute_program_with_native_type_return(program, initial_witness, &foreign_call_handler) + .await?; + let witness_map = + witness_stack.pop().expect("Should have at least one witness on the stack").witness; + Ok(witness_map.into()) } /// Executes an ACIR circuit to generate the solved witness from the initial witness. +/// This method also extracts the public return values from the solved witness into its own return witness. /// -/// @param {&WasmBlackBoxFunctionSolver} solver - A black box solver. /// @param {Uint8Array} circuit - A serialized representation of an ACIR circuit /// @param {WitnessMap} initial_witness - The initial witness map defining all of the inputs to `circuit`.. /// @param {ForeignCallHandler} foreign_call_handler - A callback to process any foreign calls from the circuit. -/// @returns {WitnessMap} The solved witness calculated by executing the circuit on the provided inputs. -#[wasm_bindgen(js_name = executeCircuitWithBlackBoxSolver, skip_jsdoc)] -pub async fn execute_circuit_with_black_box_solver( - solver: &WasmBlackBoxFunctionSolver, - circuit: Vec, +/// @returns {SolvedAndReturnWitness} The solved witness calculated by executing the circuit on the provided inputs, as well as the return witness indices as specified by the circuit. +#[wasm_bindgen(js_name = executeCircuitWithReturnWitness, skip_jsdoc)] +pub async fn execute_circuit_with_return_witness( + program: Vec, initial_witness: JsWitnessMap, foreign_call_handler: ForeignCallHandler, -) -> Result { +) -> Result { console_error_panic_hook::set_once(); - let circuit: Circuit = Circuit::deserialize_circuit(&circuit) - .map_err(|_| JsExecutionError::new("Failed to deserialize circuit. This is likely due to differing serialization formats between ACVM_JS and your compiler".to_string(), None))?; - let mut acvm = ACVM::new(&solver.0, &circuit.opcodes, initial_witness.into()); + let program: Program = Program::deserialize_program(&program) + .map_err(|_| JsExecutionError::new("Failed to deserialize circuit. This is likely due to differing serialization formats between ACVM_JS and your compiler".to_string(), None, None))?; - loop { - let solver_status = acvm.solve(); + let mut witness_stack = execute_program_with_native_program_and_return( + &program, + initial_witness, + &foreign_call_handler, + ) + .await?; + let solved_witness = + witness_stack.pop().expect("Should have at least one witness on the stack").witness; - match solver_status { - ACVMStatus::Solved => break, - ACVMStatus::InProgress => { - unreachable!("Execution should not stop while in `InProgress` state.") - } - ACVMStatus::Failure(error) => { - let (assert_message, call_stack) = match &error { - OpcodeResolutionError::UnsatisfiedConstrain { - opcode_location: ErrorLocation::Resolved(opcode_location), - } - | OpcodeResolutionError::IndexOutOfBounds { - opcode_location: ErrorLocation::Resolved(opcode_location), - .. - } => { - (circuit.get_assert_message(*opcode_location), Some(vec![*opcode_location])) - } - OpcodeResolutionError::BrilligFunctionFailed { call_stack, .. } => { - let failing_opcode = - call_stack.last().expect("Brillig error call stacks cannot be empty"); - (circuit.get_assert_message(*failing_opcode), Some(call_stack.clone())) - } - _ => (None, None), - }; + let main_circuit = &program.functions[0]; + let return_witness = + extract_indices(&solved_witness, main_circuit.return_values.0.iter().copied().collect()) + .map_err(|err| JsExecutionError::new(err, None, None))?; - let error_string = match &assert_message { - Some(assert_message) => format!("Assertion failed: {}", assert_message), - None => error.to_string(), - }; + Ok((solved_witness, return_witness).into()) +} - return Err(JsExecutionError::new(error_string.into(), call_stack).into()); - } - ACVMStatus::RequiresForeignCall(foreign_call) => { - let result = resolve_brillig(&foreign_call_handler, &foreign_call).await?; +/// Executes an ACIR circuit to generate the solved witness from the initial witness. +/// +/// @param {Uint8Array} program - A serialized representation of an ACIR program +/// @param {WitnessMap} initial_witness - The initial witness map defining all of the inputs to `program`. +/// @param {ForeignCallHandler} foreign_call_handler - A callback to process any foreign calls from the program. +/// @returns {WitnessStack} The solved witness calculated by executing the program on the provided inputs. +#[wasm_bindgen(js_name = executeProgram, skip_jsdoc)] +pub async fn execute_program( + program: Vec, + initial_witness: JsWitnessMap, + foreign_call_handler: ForeignCallHandler, +) -> Result { + console_error_panic_hook::set_once(); - acvm.resolve_pending_foreign_call(result); - } + let witness_stack = + execute_program_with_native_type_return(program, initial_witness, &foreign_call_handler) + .await?; + + Ok(witness_stack.into()) +} + +async fn execute_program_with_native_type_return( + program: Vec, + initial_witness: JsWitnessMap, + foreign_call_executor: &ForeignCallHandler, +) -> Result, Error> { + let program: Program = Program::deserialize_program(&program) + .map_err(|_| JsExecutionError::new( + "Failed to deserialize circuit. This is likely due to differing serialization formats between ACVM_JS and your compiler".to_string(), + None, + None))?; + + execute_program_with_native_program_and_return(&program, initial_witness, foreign_call_executor) + .await +} + +async fn execute_program_with_native_program_and_return( + program: &Program, + initial_witness: JsWitnessMap, + foreign_call_executor: &ForeignCallHandler, +) -> Result, Error> { + let blackbox_solver = Bn254BlackBoxSolver; + let executor = ProgramExecutor::new( + &program.functions, + &program.unconstrained_functions, + &blackbox_solver, + foreign_call_executor, + ); + let witness_stack = executor.execute(initial_witness.into()).await?; + + Ok(witness_stack) +} + +struct ProgramExecutor<'a, B: BlackBoxFunctionSolver> { + functions: &'a [Circuit], + + unconstrained_functions: &'a [BrilligBytecode], + + blackbox_solver: &'a B, + + foreign_call_handler: &'a ForeignCallHandler, +} + +impl<'a, B: BlackBoxFunctionSolver> ProgramExecutor<'a, B> { + fn new( + functions: &'a [Circuit], + unconstrained_functions: &'a [BrilligBytecode], + blackbox_solver: &'a B, + foreign_call_handler: &'a ForeignCallHandler, + ) -> Self { + ProgramExecutor { + functions, + unconstrained_functions, + blackbox_solver, + foreign_call_handler, } } - let witness_map = acvm.finalize(); - Ok(witness_map.into()) + async fn execute( + &self, + initial_witness: WitnessMap, + ) -> Result, Error> { + let main = &self.functions[0]; + + let mut witness_stack = WitnessStack::default(); + let main_witness = self.execute_circuit(main, initial_witness, &mut witness_stack).await?; + witness_stack.push(0, main_witness); + Ok(witness_stack) + } + + fn execute_circuit( + &'a self, + circuit: &'a Circuit, + initial_witness: WitnessMap, + witness_stack: &'a mut WitnessStack, + ) -> Pin, Error>> + 'a>> { + Box::pin(async { + let mut acvm = ACVM::new( + self.blackbox_solver, + &circuit.opcodes, + initial_witness, + self.unconstrained_functions, + &circuit.assert_messages, + ); + + loop { + let solver_status = acvm.solve(); + + match solver_status { + ACVMStatus::Solved => break, + ACVMStatus::InProgress => { + unreachable!("Execution should not stop while in `InProgress` state.") + } + ACVMStatus::Failure(error) => { + // Fetch call stack + let call_stack = match &error { + OpcodeResolutionError::UnsatisfiedConstrain { + opcode_location: ErrorLocation::Resolved(opcode_location), + .. + } + | OpcodeResolutionError::IndexOutOfBounds { + opcode_location: ErrorLocation::Resolved(opcode_location), + .. + } => Some(vec![*opcode_location]), + OpcodeResolutionError::BrilligFunctionFailed { call_stack, .. } => { + Some(call_stack.clone()) + } + _ => None, + }; + // If the failed opcode has an assertion message, integrate it into the error message for backwards compatibility. + // Otherwise, pass the raw assertion payload as is. + let (message, raw_assertion_payload) = match error { + OpcodeResolutionError::UnsatisfiedConstrain { + payload: Some(payload), + .. + } + | OpcodeResolutionError::BrilligFunctionFailed { + payload: Some(payload), + .. + } => match payload { + ResolvedAssertionPayload::Raw(raw_payload) => { + ("Assertion failed".to_string(), Some(raw_payload)) + } + ResolvedAssertionPayload::String(message) => { + (format!("Assertion failed: {}", message), None) + } + }, + _ => (error.to_string(), None), + }; + + return Err(JsExecutionError::new( + message, + call_stack, + raw_assertion_payload, + ) + .into()); + } + ACVMStatus::RequiresForeignCall(foreign_call) => { + let result = + resolve_brillig(self.foreign_call_handler, &foreign_call).await?; + + acvm.resolve_pending_foreign_call(result); + } + ACVMStatus::RequiresAcirCall(call_info) => { + let acir_to_call = &self.functions[call_info.id as usize]; + let initial_witness = call_info.initial_witness; + let call_solved_witness = self + .execute_circuit(acir_to_call, initial_witness, witness_stack) + .await?; + let mut call_resolved_outputs = Vec::new(); + for return_witness_index in acir_to_call.return_values.indices() { + if let Some(return_value) = + call_solved_witness.get_index(return_witness_index) + { + call_resolved_outputs.push(*return_value); + } else { + // TODO: look at changing this call stack from None + return Err(JsExecutionError::new(format!("Failed to read from solved witness of ACIR call at witness {}", return_witness_index), None, None).into()); + } + } + acvm.resolve_pending_acir_call(call_resolved_outputs); + witness_stack.push(call_info.id, call_solved_witness.clone()); + } + } + } + + Ok(acvm.finalize()) + }) + } } diff --git a/acvm-repo/acvm_js/src/foreign_call/inputs.rs b/acvm-repo/acvm_js/src/foreign_call/inputs.rs index 728fc2d3d2f..dd12bc639ec 100644 --- a/acvm-repo/acvm_js/src/foreign_call/inputs.rs +++ b/acvm-repo/acvm_js/src/foreign_call/inputs.rs @@ -1,15 +1,15 @@ -use acvm::brillig_vm::brillig::ForeignCallParam; +use acvm::{brillig_vm::brillig::ForeignCallParam, FieldElement}; use crate::js_witness_map::field_element_to_js_string; pub(super) fn encode_foreign_call_inputs( - foreign_call_inputs: &[ForeignCallParam], + foreign_call_inputs: &[ForeignCallParam], ) -> js_sys::Array { let inputs = js_sys::Array::default(); for input in foreign_call_inputs { let input_array = js_sys::Array::default(); - for value in input.values() { - let hex_js_string = field_element_to_js_string(&value.to_field()); + for value in input.fields() { + let hex_js_string = field_element_to_js_string(&value); input_array.push(&hex_js_string); } inputs.push(&input_array); diff --git a/acvm-repo/acvm_js/src/foreign_call/mod.rs b/acvm-repo/acvm_js/src/foreign_call/mod.rs index 9ccaf733f84..4884c1173dc 100644 --- a/acvm-repo/acvm_js/src/foreign_call/mod.rs +++ b/acvm-repo/acvm_js/src/foreign_call/mod.rs @@ -1,4 +1,4 @@ -use acvm::{brillig_vm::brillig::ForeignCallResult, pwg::ForeignCallWaitInfo}; +use acvm::{brillig_vm::brillig::ForeignCallResult, pwg::ForeignCallWaitInfo, FieldElement}; use js_sys::{Error, JsString}; use wasm_bindgen::{prelude::wasm_bindgen, JsValue}; @@ -29,8 +29,8 @@ extern "C" { pub(super) async fn resolve_brillig( foreign_call_callback: &ForeignCallHandler, - foreign_call_wait_info: &ForeignCallWaitInfo, -) -> Result { + foreign_call_wait_info: &ForeignCallWaitInfo, +) -> Result, Error> { // Prepare to call let name = JsString::from(foreign_call_wait_info.function.clone()); let inputs = inputs::encode_foreign_call_inputs(&foreign_call_wait_info.inputs); diff --git a/acvm-repo/acvm_js/src/foreign_call/outputs.rs b/acvm-repo/acvm_js/src/foreign_call/outputs.rs index 630b1afb6fd..2b3f44fe98d 100644 --- a/acvm-repo/acvm_js/src/foreign_call/outputs.rs +++ b/acvm-repo/acvm_js/src/foreign_call/outputs.rs @@ -1,18 +1,21 @@ -use acvm::brillig_vm::brillig::{ForeignCallParam, ForeignCallResult, Value}; +use acvm::{ + brillig_vm::brillig::{ForeignCallParam, ForeignCallResult}, + FieldElement, +}; use wasm_bindgen::JsValue; use crate::js_witness_map::js_value_to_field_element; -fn decode_foreign_call_output(output: JsValue) -> Result { +fn decode_foreign_call_output(output: JsValue) -> Result, String> { if output.is_string() { - let value = Value::from(js_value_to_field_element(output)?); + let value = js_value_to_field_element(output)?; Ok(ForeignCallParam::Single(value)) } else if output.is_array() { let output = js_sys::Array::from(&output); - let mut values: Vec = Vec::with_capacity(output.length() as usize); + let mut values: Vec<_> = Vec::with_capacity(output.length() as usize); for elem in output.iter() { - values.push(Value::from(js_value_to_field_element(elem)?)); + values.push(js_value_to_field_element(elem)?); } Ok(ForeignCallParam::Array(values)) } else { @@ -22,8 +25,9 @@ fn decode_foreign_call_output(output: JsValue) -> Result Result { - let mut values: Vec = Vec::with_capacity(js_array.length() as usize); +) -> Result, String> { + let mut values: Vec> = + Vec::with_capacity(js_array.length() as usize); for elem in js_array.iter() { values.push(decode_foreign_call_output(elem)?); } diff --git a/acvm-repo/acvm_js/src/js_execution_error.rs b/acvm-repo/acvm_js/src/js_execution_error.rs index d91a9425f7e..e51a912a63a 100644 --- a/acvm-repo/acvm_js/src/js_execution_error.rs +++ b/acvm-repo/acvm_js/src/js_execution_error.rs @@ -1,11 +1,20 @@ -use acvm::acir::circuit::OpcodeLocation; +use acvm::{ + acir::circuit::{OpcodeLocation, RawAssertionPayload}, + FieldElement, +}; +use gloo_utils::format::JsValueSerdeExt; use js_sys::{Array, Error, JsString, Reflect}; use wasm_bindgen::prelude::{wasm_bindgen, JsValue}; #[wasm_bindgen(typescript_custom_section)] const EXECUTION_ERROR: &'static str = r#" +export type RawAssertionPayload = { + selector: string; + data: string[]; +}; export type ExecutionError = Error & { callStack?: string[]; + rawAssertionPayload?: RawAssertionPayload; }; "#; @@ -25,7 +34,11 @@ extern "C" { impl JsExecutionError { /// Creates a new execution error with the given call stack. /// Call stacks won't be optional in the future, after removing ErrorLocation in ACVM. - pub fn new(message: String, call_stack: Option>) -> Self { + pub fn new( + message: String, + call_stack: Option>, + assertion_payload: Option>, + ) -> Self { let mut error = JsExecutionError::constructor(JsString::from(message)); let js_call_stack = match call_stack { Some(call_stack) => { @@ -37,8 +50,14 @@ impl JsExecutionError { } None => JsValue::UNDEFINED, }; + let assertion_payload = match assertion_payload { + Some(raw) => ::from_serde(&raw) + .expect("Cannot serialize assertion payload"), + None => JsValue::UNDEFINED, + }; error.set_property("callStack", js_call_stack); + error.set_property("rawAssertionPayload", assertion_payload); error } diff --git a/acvm-repo/acvm_js/src/js_witness_map.rs b/acvm-repo/acvm_js/src/js_witness_map.rs index 481b8caaa2d..8316059e21a 100644 --- a/acvm-repo/acvm_js/src/js_witness_map.rs +++ b/acvm-repo/acvm_js/src/js_witness_map.rs @@ -1,14 +1,25 @@ use acvm::{ acir::native_types::{Witness, WitnessMap}, + acir::AcirField, FieldElement, }; -use js_sys::{JsString, Map}; +use js_sys::{JsString, Map, Object}; use wasm_bindgen::prelude::{wasm_bindgen, JsValue}; #[wasm_bindgen(typescript_custom_section)] const WITNESS_MAP: &'static str = r#" // Map from witness index to hex string value of witness. export type WitnessMap = Map; + +/** + * An execution result containing two witnesses. + * 1. The full solved witness of the execution. + * 2. The return witness which contains the given public return values within the full witness. + */ +export type SolvedAndReturnWitness = { + solvedWitness: WitnessMap; + returnWitness: WitnessMap; +} "#; // WitnessMap @@ -21,6 +32,12 @@ extern "C" { #[wasm_bindgen(constructor, js_class = "Map")] pub fn new() -> JsWitnessMap; + #[wasm_bindgen(extends = Object, js_name = "SolvedAndReturnWitness", typescript_type = "SolvedAndReturnWitness")] + #[derive(Clone, Debug, PartialEq, Eq)] + pub type JsSolvedAndReturnWitness; + + #[wasm_bindgen(constructor, js_class = "Object")] + pub fn new() -> JsSolvedAndReturnWitness; } impl Default for JsWitnessMap { @@ -29,8 +46,14 @@ impl Default for JsWitnessMap { } } -impl From for JsWitnessMap { - fn from(witness_map: WitnessMap) -> Self { +impl Default for JsSolvedAndReturnWitness { + fn default() -> Self { + Self::new() + } +} + +impl From> for JsWitnessMap { + fn from(witness_map: WitnessMap) -> Self { let js_map = JsWitnessMap::new(); for (key, value) in witness_map { js_map.set( @@ -42,7 +65,7 @@ impl From for JsWitnessMap { } } -impl From for WitnessMap { +impl From for WitnessMap { fn from(js_map: JsWitnessMap) -> Self { let mut witness_map = WitnessMap::new(); js_map.for_each(&mut |value, key| { @@ -54,6 +77,20 @@ impl From for WitnessMap { } } +impl From<(WitnessMap, WitnessMap)> for JsSolvedAndReturnWitness { + fn from(witness_maps: (WitnessMap, WitnessMap)) -> Self { + let js_solved_witness = JsWitnessMap::from(witness_maps.0); + let js_return_witness = JsWitnessMap::from(witness_maps.1); + + let entry_map = Map::new(); + entry_map.set(&JsValue::from_str("solvedWitness"), &js_solved_witness); + entry_map.set(&JsValue::from_str("returnWitness"), &js_return_witness); + + let solved_and_return_witness = Object::from_entries(&entry_map).unwrap(); + JsSolvedAndReturnWitness { obj: solved_and_return_witness } + } +} + pub(crate) fn js_value_to_field_element(js_value: JsValue) -> Result { let hex_str = js_value.as_string().ok_or("failed to parse field element from non-string")?; @@ -77,7 +114,7 @@ mod test { use acvm::{ acir::native_types::{Witness, WitnessMap}, - FieldElement, + AcirField, FieldElement, }; use wasm_bindgen::JsValue; diff --git a/acvm-repo/acvm_js/src/js_witness_stack.rs b/acvm-repo/acvm_js/src/js_witness_stack.rs new file mode 100644 index 00000000000..d59ee508086 --- /dev/null +++ b/acvm-repo/acvm_js/src/js_witness_stack.rs @@ -0,0 +1,71 @@ +use acvm::{acir::native_types::WitnessStack, FieldElement}; +use js_sys::{Array, Map, Object}; +use wasm_bindgen::prelude::{wasm_bindgen, JsValue}; + +use crate::JsWitnessMap; + +#[wasm_bindgen(typescript_custom_section)] +const WITNESS_STACK: &'static str = r#" +export type StackItem = { + index: number; + witness: WitnessMap; +} + +export type WitnessStack = Array; +"#; + +// WitnessStack +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(extends = Array, js_name = "WitnessStack", typescript_type = "WitnessStack")] + #[derive(Clone, Debug, PartialEq, Eq)] + pub type JsWitnessStack; + + #[wasm_bindgen(constructor, js_class = "Array")] + pub fn new() -> JsWitnessStack; + + #[wasm_bindgen(extends = Object, js_name = "StackItem", typescript_type = "StackItem")] + #[derive(Clone, Debug, PartialEq, Eq)] + pub type JsStackItem; + + #[wasm_bindgen(constructor, js_class = "Object")] + pub fn new() -> JsStackItem; +} + +impl Default for JsWitnessStack { + fn default() -> Self { + Self::new() + } +} + +impl From> for JsWitnessStack { + fn from(mut witness_stack: WitnessStack) -> Self { + let js_witness_stack = JsWitnessStack::new(); + while let Some(stack_item) = witness_stack.pop() { + let js_map = JsWitnessMap::from(stack_item.witness); + let js_index = JsValue::from_f64(stack_item.index.into()); + + let entry_map = Map::new(); + entry_map.set(&JsValue::from_str("index"), &js_index); + entry_map.set(&JsValue::from_str("witness"), &js_map); + let stack_item = Object::from_entries(&entry_map).unwrap(); + + js_witness_stack.push(&stack_item); + } + // `reverse()` returns an `Array` so we have to wrap it + JsWitnessStack { obj: js_witness_stack.reverse() } + } +} + +impl From for WitnessStack { + fn from(js_witness_stack: JsWitnessStack) -> Self { + let mut witness_stack = WitnessStack::default(); + js_witness_stack.for_each(&mut |stack_item, _, _| { + let values_array = Object::values(&Object::from(stack_item)); + let index = values_array.get(0).as_f64().unwrap() as u32; + let js_witness_map: JsWitnessMap = values_array.get(1).into(); + witness_stack.push(index, js_witness_map.into()); + }); + witness_stack + } +} diff --git a/acvm-repo/acvm_js/src/lib.rs b/acvm-repo/acvm_js/src/lib.rs index 88afd1767c9..fdb8d5ffe08 100644 --- a/acvm-repo/acvm_js/src/lib.rs +++ b/acvm-repo/acvm_js/src/lib.rs @@ -1,31 +1,32 @@ -#![forbid(unsafe_code)] #![warn(unreachable_pub)] #![warn(clippy::semicolon_if_nothing_returned)] #![cfg_attr(not(test), warn(unused_crate_dependencies, unused_extern_crates))] -// TODO: Absence of per package targets -// https://doc.rust-lang.org/cargo/reference/unstable.html#per-package-target -// otherwise could be reorganized to make this file more pretty. +// See Cargo.toml for explanation. +use getrandom as _; -cfg_if::cfg_if! { - if #[cfg(target_arch = "wasm32")] { - mod build_info; - mod compression; - mod execute; - mod foreign_call; - mod js_witness_map; - mod logging; - mod public_witness; - mod js_execution_error; - mod black_box_solvers; +mod black_box_solvers; +mod build_info; +mod compression; +mod execute; +mod foreign_call; +mod js_execution_error; +mod js_witness_map; +mod js_witness_stack; +mod logging; +mod public_witness; - pub use black_box_solvers::{and, xor, sha256, blake2s256, keccak256, ecdsa_secp256k1_verify, ecdsa_secp256r1_verify}; - pub use build_info::build_info; - pub use compression::{compress_witness, decompress_witness}; - pub use execute::{execute_circuit, execute_circuit_with_black_box_solver, create_black_box_solver}; - pub use js_witness_map::JsWitnessMap; - pub use logging::init_log_level; - pub use public_witness::{get_public_parameters_witness, get_public_witness, get_return_witness}; - pub use js_execution_error::JsExecutionError; - } -} +pub use black_box_solvers::{ + and, blake2s256, ecdsa_secp256k1_verify, ecdsa_secp256r1_verify, keccak256, sha256, xor, +}; +pub use build_info::build_info; +pub use compression::{ + compress_witness, compress_witness_stack, decompress_witness, decompress_witness_stack, +}; +pub use execute::{execute_circuit, execute_circuit_with_return_witness, execute_program}; +pub use js_execution_error::JsExecutionError; +pub use js_witness_map::JsSolvedAndReturnWitness; +pub use js_witness_map::JsWitnessMap; +pub use js_witness_stack::JsWitnessStack; +pub use logging::init_log_level; +pub use public_witness::{get_public_parameters_witness, get_public_witness, get_return_witness}; diff --git a/acvm-repo/acvm_js/src/public_witness.rs b/acvm-repo/acvm_js/src/public_witness.rs index 8dc66c435b3..245d5b4dd0a 100644 --- a/acvm-repo/acvm_js/src/public_witness.rs +++ b/acvm-repo/acvm_js/src/public_witness.rs @@ -1,13 +1,19 @@ -use acvm::acir::{ - circuit::Circuit, - native_types::{Witness, WitnessMap}, +use acvm::{ + acir::{ + circuit::Program, + native_types::{Witness, WitnessMap}, + }, + FieldElement, }; use js_sys::JsString; use wasm_bindgen::prelude::wasm_bindgen; use crate::JsWitnessMap; -fn extract_indices(witness_map: &WitnessMap, indices: Vec) -> Result { +pub(crate) fn extract_indices( + witness_map: &WitnessMap, + indices: Vec, +) -> Result, String> { let mut extracted_witness_map = WitnessMap::new(); for witness in indices { let witness_value = witness_map.get(&witness).ok_or(format!( @@ -26,16 +32,25 @@ fn extract_indices(witness_map: &WitnessMap, indices: Vec) -> Result, + // TODO(https://github.com/noir-lang/noir/issues/4428): These need to be updated to match the same interfaces + // as the native ACVM executor. Right now native execution still only handles one circuit so I do not feel the need + // to break the JS interface just yet. + program: Vec, witness_map: JsWitnessMap, ) -> Result { console_error_panic_hook::set_once(); - let circuit: Circuit = - Circuit::deserialize_circuit(&circuit).expect("Failed to deserialize circuit"); + let program: Program = + Program::deserialize_program(&program).expect("Failed to deserialize circuit"); + let circuit = match program.functions.len() { + 0 => return Ok(JsWitnessMap::from(WitnessMap::new())), + 1 => &program.functions[0], + _ => return Err(JsString::from("Program contains multiple circuits however ACVM currently only supports programs containing a single circuit")) + }; + let witness_map = WitnessMap::from(witness_map); let return_witness = - extract_indices(&witness_map, circuit.return_values.0.into_iter().collect())?; + extract_indices(&witness_map, circuit.return_values.0.iter().copied().collect())?; Ok(JsWitnessMap::from(return_witness)) } @@ -47,16 +62,22 @@ pub fn get_return_witness( /// @returns {WitnessMap} A witness map containing the circuit's public parameters. #[wasm_bindgen(js_name = getPublicParametersWitness)] pub fn get_public_parameters_witness( - circuit: Vec, + program: Vec, solved_witness: JsWitnessMap, ) -> Result { console_error_panic_hook::set_once(); - let circuit: Circuit = - Circuit::deserialize_circuit(&circuit).expect("Failed to deserialize circuit"); + let program: Program = + Program::deserialize_program(&program).expect("Failed to deserialize circuit"); + let circuit = match program.functions.len() { + 0 => return Ok(JsWitnessMap::from(WitnessMap::new())), + 1 => &program.functions[0], + _ => return Err(JsString::from("Program contains multiple circuits however ACVM currently only supports programs containing a single circuit")) + }; + let witness_map = WitnessMap::from(solved_witness); let public_params_witness = - extract_indices(&witness_map, circuit.public_parameters.0.into_iter().collect())?; + extract_indices(&witness_map, circuit.public_parameters.0.iter().copied().collect())?; Ok(JsWitnessMap::from(public_params_witness)) } @@ -68,16 +89,22 @@ pub fn get_public_parameters_witness( /// @returns {WitnessMap} A witness map containing the circuit's public inputs. #[wasm_bindgen(js_name = getPublicWitness)] pub fn get_public_witness( - circuit: Vec, + program: Vec, solved_witness: JsWitnessMap, ) -> Result { console_error_panic_hook::set_once(); - let circuit: Circuit = - Circuit::deserialize_circuit(&circuit).expect("Failed to deserialize circuit"); + let program: Program = + Program::deserialize_program(&program).expect("Failed to deserialize circuit"); + let circuit = match program.functions.len() { + 0 => return Ok(JsWitnessMap::from(WitnessMap::new())), + 1 => &program.functions[0], + _ => return Err(JsString::from("Program contains multiple circuits however ACVM currently only supports programs containing a single circuit")) + }; + let witness_map = WitnessMap::from(solved_witness); let public_witness = - extract_indices(&witness_map, circuit.public_inputs().0.into_iter().collect())?; + extract_indices(&witness_map, circuit.public_inputs().0.clone().into_iter().collect())?; Ok(JsWitnessMap::from(public_witness)) } diff --git a/acvm-repo/acvm_js/test/browser/black_box_solvers.test.ts b/acvm-repo/acvm_js/test/browser/black_box_solvers.test.ts index 3c54fe8e38f..695f6b89afc 100644 --- a/acvm-repo/acvm_js/test/browser/black_box_solvers.test.ts +++ b/acvm-repo/acvm_js/test/browser/black_box_solvers.test.ts @@ -4,7 +4,6 @@ import initACVM, { blake2s256, ecdsa_secp256k1_verify, ecdsa_secp256r1_verify, - initLogLevel, keccak256, sha256, xor, @@ -12,8 +11,6 @@ import initACVM, { beforeEach(async () => { await initACVM(); - - initLogLevel('INFO'); }); it('successfully calculates the bitwise AND of two fields', async () => { diff --git a/acvm-repo/acvm_js/test/browser/execute_circuit.test.ts b/acvm-repo/acvm_js/test/browser/execute_circuit.test.ts index 259c51ed1c6..cfd5523b79f 100644 --- a/acvm-repo/acvm_js/test/browser/execute_circuit.test.ts +++ b/acvm-repo/acvm_js/test/browser/execute_circuit.test.ts @@ -1,13 +1,5 @@ import { expect } from '@esm-bundle/chai'; -import initACVM, { - createBlackBoxSolver, - executeCircuit, - executeCircuitWithBlackBoxSolver, - WasmBlackBoxFunctionSolver, - WitnessMap, - initLogLevel, - ForeignCallHandler, -} from '@noir-lang/acvm_js'; +import initACVM, { executeCircuit, WitnessMap, initLogLevel, ForeignCallHandler } from '@noir-lang/acvm_js'; beforeEach(async () => { await initACVM(); @@ -93,8 +85,8 @@ it('successfully executes a Pedersen opcode', async function () { expect(solvedWitness).to.be.deep.eq(expectedWitnessMap); }); -it('successfully executes a FixedBaseScalarMul opcode', async () => { - const { bytecode, initialWitnessMap, expectedWitnessMap } = await import('../shared/fixed_base_scalar_mul'); +it('successfully executes a MultiScalarMul opcode', async () => { + const { bytecode, initialWitnessMap, expectedWitnessMap } = await import('../shared/multi_scalar_mul'); const solvedWitness: WitnessMap = await executeCircuit(bytecode, initialWitnessMap, () => { throw Error('unexpected oracle'); @@ -122,23 +114,3 @@ it('successfully executes a MemoryOp opcode', async () => { expect(solvedWitness).to.be.deep.eq(expectedWitnessMap); }); - -it('successfully executes two circuits with same backend', async function () { - // chose pedersen op here because it is the one with slow initialization - // that led to the decision to pull backend initialization into a separate - // function/wasmbind - const solver: WasmBlackBoxFunctionSolver = await createBlackBoxSolver(); - - const { bytecode, initialWitnessMap, expectedWitnessMap } = await import('../shared/pedersen'); - - const solvedWitness0: WitnessMap = await executeCircuitWithBlackBoxSolver(solver, bytecode, initialWitnessMap, () => { - throw Error('unexpected oracle'); - }); - - expect(solvedWitness0).to.be.deep.eq(expectedWitnessMap); - - const solvedWitness1: WitnessMap = await executeCircuitWithBlackBoxSolver(solver, bytecode, initialWitnessMap, () => { - throw Error('unexpected oracle'); - }); - expect(solvedWitness1).to.be.deep.eq(expectedWitnessMap); -}); diff --git a/acvm-repo/acvm_js/test/node/build_info.test.ts b/acvm-repo/acvm_js/test/node/build_info.test.ts index 23100505011..014bb6f422d 100644 --- a/acvm-repo/acvm_js/test/node/build_info.test.ts +++ b/acvm-repo/acvm_js/test/node/build_info.test.ts @@ -3,12 +3,20 @@ import { BuildInfo, buildInfo } from '@noir-lang/acvm_js'; import child_process from 'child_process'; import pkg from '../../package.json'; -it('returns the correct build into', () => { +it('returns the correct build info', () => { + let revision: string; + + try { + revision = child_process.execSync('git rev-parse HEAD').toString().trim(); + } catch (error) { + console.log('Failed to get revision, skipping test.'); + return; + } + const info: BuildInfo = buildInfo(); // TODO: enforce that `package.json` and `Cargo.toml` are consistent. expect(info.version).to.be.eq(pkg.version); - const revision = child_process.execSync('git rev-parse HEAD').toString().trim(); expect(info.gitHash).to.be.eq(revision); }); diff --git a/acvm-repo/acvm_js/test/node/execute_circuit.test.ts b/acvm-repo/acvm_js/test/node/execute_circuit.test.ts index adee3c15312..1e3517e8814 100644 --- a/acvm-repo/acvm_js/test/node/execute_circuit.test.ts +++ b/acvm-repo/acvm_js/test/node/execute_circuit.test.ts @@ -1,11 +1,11 @@ import { expect } from 'chai'; import { - createBlackBoxSolver, executeCircuit, - executeCircuitWithBlackBoxSolver, - WasmBlackBoxFunctionSolver, WitnessMap, ForeignCallHandler, + executeProgram, + WitnessStack, + StackItem, } from '@noir-lang/acvm_js'; it('successfully executes circuit and extracts return value', async () => { @@ -87,8 +87,8 @@ it('successfully executes a Pedersen opcode', async function () { expect(solvedWitness).to.be.deep.eq(expectedWitnessMap); }); -it('successfully executes a FixedBaseScalarMul opcode', async () => { - const { bytecode, initialWitnessMap, expectedWitnessMap } = await import('../shared/fixed_base_scalar_mul'); +it('successfully executes a MultiScalarMul opcode', async () => { + const { bytecode, initialWitnessMap, expectedWitnessMap } = await import('../shared/multi_scalar_mul'); const solvedWitness: WitnessMap = await executeCircuit(bytecode, initialWitnessMap, () => { throw Error('unexpected oracle'); @@ -117,43 +117,55 @@ it('successfully executes a MemoryOp opcode', async () => { expect(solvedWitness).to.be.deep.eq(expectedWitnessMap); }); -it('successfully executes two circuits with same backend', async function () { - this.timeout(10000); +it('successfully executes 500 pedersen circuits', async function () { + this.timeout(100000); - // chose pedersen op here because it is the one with slow initialization - // that led to the decision to pull backend initialization into a separate - // function/wasmbind - const solver: WasmBlackBoxFunctionSolver = await createBlackBoxSolver(); + // Pedersen opcodes used to have a large upfront cost due to generator calculation + // so we'd need to pass around the blackbox solver in JS to avoid redoing this work. + // + // This test now shows that we don't need to do this anymore without a performance regression. const { bytecode, initialWitnessMap, expectedWitnessMap } = await import('../shared/pedersen'); - const solvedWitness0 = await executeCircuitWithBlackBoxSolver(solver, bytecode, initialWitnessMap, () => { - throw Error('unexpected oracle'); - }); + for (let i = 0; i < 500; i++) { + const solvedWitness = await executeCircuit(bytecode, initialWitnessMap, () => { + throw Error('unexpected oracle'); + }); - const solvedWitness1 = await executeCircuitWithBlackBoxSolver(solver, bytecode, initialWitnessMap, () => { + expect(solvedWitness).to.be.deep.eq(expectedWitnessMap); + } +}); + +/** + * Below are all the same tests as above but using `executeProgram` + * TODO: also add a couple tests for executing multiple circuits + */ +it('executeProgram: successfully executes program and extracts return value', async () => { + const { bytecode, initialWitnessMap, resultWitness, expectedResult } = await import('../shared/addition'); + + const witnessStack: WitnessStack = await executeProgram(bytecode, initialWitnessMap, () => { throw Error('unexpected oracle'); }); - expect(solvedWitness0).to.be.deep.eq(expectedWitnessMap); - expect(solvedWitness1).to.be.deep.eq(expectedWitnessMap); -}); + const solvedStackItem: StackItem = witnessStack[0]; + expect(solvedStackItem.index).to.be.eq(0); + const solvedWitnessMap: WitnessMap = solvedStackItem.witness; -it('successfully executes 500 circuits with same backend', async function () { - this.timeout(100000); + // Witness stack should be consistent with initial witness + initialWitnessMap.forEach((value, key) => { + expect(solvedWitnessMap.get(key) as string).to.be.eq(value); + }); - // chose pedersen op here because it is the one with slow initialization - // that led to the decision to pull backend initialization into a separate - // function/wasmbind - const solver: WasmBlackBoxFunctionSolver = await createBlackBoxSolver(); + // Solved witness should contain expected return value + expect(solvedWitnessMap.get(resultWitness)).to.be.eq(expectedResult); +}); - const { bytecode, initialWitnessMap, expectedWitnessMap } = await import('../shared/pedersen'); +it('executeProgram: successfully process a program of acir functions with a nested call', async () => { + const { bytecode, initialWitnessMap, expectedWitnessStack } = await import('../shared/nested_acir_call'); - for (let i = 0; i < 500; i++) { - const solvedWitness = await executeCircuitWithBlackBoxSolver(solver, bytecode, initialWitnessMap, () => { - throw Error('unexpected oracle'); - }); + const witnessStack: WitnessStack = await executeProgram(bytecode, initialWitnessMap, () => { + throw Error('unexpected oracle'); + }); - expect(solvedWitness).to.be.deep.eq(expectedWitnessMap); - } + expect(witnessStack).to.be.deep.eq(expectedWitnessStack); }); diff --git a/acvm-repo/acvm_js/test/node/witness_conversion.test.ts b/acvm-repo/acvm_js/test/node/witness_conversion.test.ts index 41291c894ea..c6dccb4c83d 100644 --- a/acvm-repo/acvm_js/test/node/witness_conversion.test.ts +++ b/acvm-repo/acvm_js/test/node/witness_conversion.test.ts @@ -1,6 +1,7 @@ import { expect } from 'chai'; -import { compressWitness, decompressWitness } from '@noir-lang/acvm_js'; +import { compressWitness, decompressWitness, compressWitnessStack, decompressWitnessStack } from '@noir-lang/acvm_js'; import { expectedCompressedWitnessMap, expectedWitnessMap } from '../shared/witness_compression'; +import { expectedCompressedWitnessStack, expectedWitnessStack } from '../shared/nested_acir_call'; it('successfully compresses the witness', () => { const compressedWitnessMap = compressWitness(expectedWitnessMap); @@ -13,3 +14,15 @@ it('successfully decompresses the witness', () => { expect(witnessMap).to.be.deep.eq(expectedWitnessMap); }); + +it('successfully compresses the witness stack', () => { + const compressedWitnessStack = compressWitnessStack(expectedWitnessStack); + + expect(compressedWitnessStack).to.be.deep.eq(expectedCompressedWitnessStack); +}); + +it('successfully decompresses the witness stack', () => { + const witnessStack = decompressWitnessStack(expectedCompressedWitnessStack); + + expect(witnessStack).to.be.deep.eq(expectedWitnessStack); +}); diff --git a/acvm-repo/acvm_js/test/shared/addition.ts b/acvm-repo/acvm_js/test/shared/addition.ts index 217902bdea6..820a415acf3 100644 --- a/acvm-repo/acvm_js/test/shared/addition.ts +++ b/acvm-repo/acvm_js/test/shared/addition.ts @@ -2,11 +2,11 @@ import { WitnessMap } from '@noir-lang/acvm_js'; // See `addition_circuit` integration test in `acir/tests/test_program_serialization.rs`. export const bytecode = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 208, 49, 14, 192, 32, 8, 5, 80, 212, 30, 8, 4, 20, 182, 94, 165, 166, 122, - 255, 35, 52, 77, 28, 76, 58, 214, 191, 124, 166, 23, 242, 15, 0, 8, 240, 77, 154, 125, 206, 198, 127, 161, 176, 209, - 138, 139, 197, 88, 68, 122, 205, 157, 152, 46, 204, 222, 76, 81, 180, 21, 35, 35, 53, 189, 179, 49, 119, 19, 171, 222, - 188, 162, 147, 112, 167, 161, 206, 99, 98, 105, 223, 95, 248, 26, 113, 90, 97, 185, 97, 217, 56, 173, 35, 63, 243, 81, - 87, 163, 125, 1, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 144, 65, 14, 128, 32, 12, 4, 65, 124, 80, 75, 91, 104, 111, 126, 69, 34, 252, + 255, 9, 106, 228, 64, 162, 55, 153, 164, 217, 158, 38, 155, 245, 238, 97, 189, 206, 187, 55, 161, 231, 214, 19, 254, + 129, 126, 162, 107, 25, 92, 4, 137, 185, 230, 88, 145, 112, 135, 104, 69, 5, 88, 74, 82, 84, 20, 149, 35, 42, 81, 85, + 214, 108, 197, 50, 24, 50, 85, 108, 98, 212, 186, 44, 204, 235, 5, 183, 99, 233, 46, 63, 252, 110, 216, 56, 184, 15, + 78, 146, 74, 173, 20, 141, 1, 0, 0, ]); export const initialWitnessMap: WitnessMap = new Map([ diff --git a/acvm-repo/acvm_js/test/shared/complex_foreign_call.ts b/acvm-repo/acvm_js/test/shared/complex_foreign_call.ts index 27abd72305f..8ec2ddd1cb2 100644 --- a/acvm-repo/acvm_js/test/shared/complex_foreign_call.ts +++ b/acvm-repo/acvm_js/test/shared/complex_foreign_call.ts @@ -2,13 +2,13 @@ import { WitnessMap } from '@noir-lang/acvm_js'; // See `complex_brillig_foreign_call` integration test in `acir/tests/test_program_serialization.rs`. export const bytecode = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 84, 75, 10, 132, 48, 12, 125, 177, 163, 35, 179, 154, 35, 8, 51, 7, 232, 204, - 9, 188, 139, 184, 83, 116, 233, 241, 173, 152, 98, 12, 213, 141, 21, 244, 65, 232, 39, 175, 233, 35, 73, 155, 3, 32, - 204, 48, 206, 18, 158, 19, 175, 37, 60, 175, 228, 209, 30, 195, 143, 226, 197, 178, 103, 105, 76, 110, 160, 209, 156, - 160, 209, 247, 195, 69, 235, 29, 179, 46, 81, 243, 103, 2, 239, 231, 225, 44, 117, 150, 241, 250, 201, 99, 206, 251, - 96, 95, 161, 242, 14, 193, 243, 40, 162, 105, 253, 219, 12, 75, 47, 146, 186, 251, 37, 116, 86, 93, 219, 55, 245, 96, - 20, 85, 75, 253, 136, 249, 87, 249, 105, 231, 220, 4, 249, 237, 132, 56, 20, 224, 109, 113, 223, 88, 82, 153, 34, 64, - 34, 14, 164, 69, 172, 48, 2, 23, 243, 6, 31, 25, 5, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 84, 75, 10, 131, 64, 12, 77, 102, 90, 43, 221, 245, 6, 133, 246, 0, 211, 158, + 192, 187, 136, 59, 69, 151, 158, 94, 116, 48, 131, 241, 233, 70, 28, 65, 3, 195, 155, 79, 62, 47, 9, 25, 166, 81, 210, + 97, 177, 236, 239, 130, 70, 208, 223, 91, 154, 75, 208, 205, 4, 221, 62, 249, 113, 60, 95, 238, 40, 142, 230, 2, 28, + 237, 1, 28, 73, 245, 255, 132, 253, 142, 217, 151, 168, 245, 179, 43, 243, 115, 163, 113, 190, 18, 57, 63, 4, 83, 44, + 180, 55, 50, 180, 28, 188, 153, 224, 196, 122, 175, 111, 112, 68, 24, 65, 116, 178, 40, 89, 254, 93, 162, 120, 48, + 196, 126, 170, 12, 243, 186, 106, 202, 162, 181, 160, 138, 84, 63, 106, 255, 133, 119, 6, 187, 14, 108, 59, 133, 250, + 243, 90, 139, 19, 238, 205, 6, 223, 47, 154, 202, 27, 74, 222, 3, 234, 73, 242, 82, 65, 5, 0, 0, ]); export const initialWitnessMap: WitnessMap = new Map([ [1, '0x0000000000000000000000000000000000000000000000000000000000000001'], diff --git a/acvm-repo/acvm_js/test/shared/fixed_base_scalar_mul.ts b/acvm-repo/acvm_js/test/shared/fixed_base_scalar_mul.ts deleted file mode 100644 index c0859f50135..00000000000 --- a/acvm-repo/acvm_js/test/shared/fixed_base_scalar_mul.ts +++ /dev/null @@ -1,17 +0,0 @@ -// See `fixed_base_scalar_mul_circuit` integration test in `acir/tests/test_program_serialization.rs`. -export const bytecode = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 77, 138, 91, 10, 0, 32, 16, 2, 109, 171, 175, 46, 221, 209, 247, 229, 130, 130, - 140, 200, 92, 0, 11, 157, 228, 35, 127, 212, 200, 29, 61, 116, 76, 220, 217, 250, 171, 91, 113, 160, 66, 104, 242, 97, - 0, 0, 0, -]); -export const initialWitnessMap = new Map([ - [1, '0x0000000000000000000000000000000000000000000000000000000000000001'], - [2, '0x0000000000000000000000000000000000000000000000000000000000000000'], -]); - -export const expectedWitnessMap = new Map([ - [1, '0x0000000000000000000000000000000000000000000000000000000000000001'], - [2, '0x0000000000000000000000000000000000000000000000000000000000000000'], - [3, '0x0000000000000000000000000000000000000000000000000000000000000001'], - [4, '0x0000000000000002cf135e7506a45d632d270d45f1181294833fc48d823f272c'], -]); diff --git a/acvm-repo/acvm_js/test/shared/foreign_call.ts b/acvm-repo/acvm_js/test/shared/foreign_call.ts index 0be8937b57d..3c66ba18629 100644 --- a/acvm-repo/acvm_js/test/shared/foreign_call.ts +++ b/acvm-repo/acvm_js/test/shared/foreign_call.ts @@ -2,10 +2,10 @@ import { WitnessMap } from '@noir-lang/acvm_js'; // See `simple_brillig_foreign_call` integration test in `acir/tests/test_program_serialization.rs`. export const bytecode = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 143, 177, 10, 192, 32, 16, 67, 227, 21, 74, 233, 212, 79, 177, 127, 208, 159, - 233, 224, 226, 32, 226, 247, 139, 168, 16, 68, 93, 244, 45, 119, 228, 142, 144, 92, 0, 20, 50, 7, 237, 76, 213, 190, - 50, 245, 26, 175, 218, 231, 165, 57, 175, 148, 14, 137, 179, 147, 191, 114, 211, 221, 216, 240, 59, 63, 107, 221, 115, - 104, 181, 103, 244, 43, 36, 10, 38, 68, 108, 25, 253, 238, 136, 1, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 144, 193, 10, 192, 32, 8, 134, 117, 99, 99, 236, 182, 55, 105, 111, 176, 151, + 217, 161, 75, 135, 136, 30, 63, 42, 82, 144, 8, 47, 245, 65, 252, 230, 47, 162, 34, 52, 174, 242, 144, 226, 131, 148, + 255, 18, 206, 125, 164, 102, 142, 23, 215, 245, 50, 114, 222, 173, 15, 80, 38, 65, 217, 108, 39, 61, 7, 30, 115, 11, + 223, 186, 248, 251, 160, 221, 170, 146, 64, 191, 39, 215, 60, 3, 47, 3, 99, 171, 188, 84, 164, 1, 0, 0, ]); export const initialWitnessMap: WitnessMap = new Map([ [1, '0x0000000000000000000000000000000000000000000000000000000000000005'], diff --git a/acvm-repo/acvm_js/test/shared/memory_op.ts b/acvm-repo/acvm_js/test/shared/memory_op.ts index b5ab64b3447..f7443c2258b 100644 --- a/acvm-repo/acvm_js/test/shared/memory_op.ts +++ b/acvm-repo/acvm_js/test/shared/memory_op.ts @@ -1,9 +1,9 @@ // See `memory_op_circuit` integration test in `acir/tests/test_program_serialization.rs`. export const bytecode = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 145, 187, 17, 0, 32, 8, 67, 195, 111, 31, 220, 192, 253, 167, 178, 144, 2, - 239, 236, 132, 194, 52, 129, 230, 93, 8, 6, 64, 176, 101, 225, 28, 78, 49, 43, 238, 154, 225, 254, 166, 209, 205, 165, - 98, 174, 212, 177, 188, 187, 92, 255, 173, 92, 173, 190, 93, 82, 80, 78, 123, 14, 127, 60, 97, 1, 210, 144, 46, 242, - 19, 3, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 82, 65, 10, 0, 32, 8, 211, 180, 255, 216, 15, 250, 255, 171, 10, 82, 176, 232, + 150, 30, 26, 200, 118, 144, 49, 135, 8, 11, 117, 14, 169, 102, 229, 162, 140, 78, 219, 206, 137, 174, 44, 111, 104, + 217, 190, 24, 236, 75, 113, 94, 146, 93, 174, 252, 86, 46, 71, 223, 78, 46, 104, 129, 253, 155, 45, 60, 195, 5, 3, 89, + 11, 161, 73, 39, 3, 0, 0, ]); export const initialWitnessMap = new Map([ diff --git a/acvm-repo/acvm_js/test/shared/multi_scalar_mul.ts b/acvm-repo/acvm_js/test/shared/multi_scalar_mul.ts new file mode 100644 index 00000000000..5401da76974 --- /dev/null +++ b/acvm-repo/acvm_js/test/shared/multi_scalar_mul.ts @@ -0,0 +1,24 @@ +// See `multi_scalar_mul_circuit` integration test in `acir/tests/test_program_serialization.rs`. +export const bytecode = Uint8Array.from([ + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 93, 141, 219, 10, 0, 32, 8, 67, 243, 214, 5, 250, 232, 62, 189, 69, 123, 176, 132, + 195, 116, 50, 149, 114, 107, 0, 97, 127, 116, 2, 75, 243, 2, 74, 53, 122, 202, 189, 211, 15, 106, 5, 13, 116, 238, 35, + 221, 81, 230, 61, 249, 37, 253, 250, 179, 79, 109, 218, 22, 67, 227, 173, 0, 0, 0, +]); +export const initialWitnessMap = new Map([ + [1, '0x0000000000000000000000000000000000000000000000000000000000000001'], + [2, '0x0000000000000002cf135e7506a45d632d270d45f1181294833fc48d823f272c'], + [3, '0x0000000000000000000000000000000000000000000000000000000000000000'], + [4, '0x0000000000000000000000000000000000000000000000000000000000000001'], + [5, '0x0000000000000000000000000000000000000000000000000000000000000000'], +]); + +export const expectedWitnessMap = new Map([ + [1, '0x0000000000000000000000000000000000000000000000000000000000000001'], + [2, '0x0000000000000002cf135e7506a45d632d270d45f1181294833fc48d823f272c'], + [3, '0x0000000000000000000000000000000000000000000000000000000000000000'], + [4, '0x0000000000000000000000000000000000000000000000000000000000000001'], + [5, '0x0000000000000000000000000000000000000000000000000000000000000000'], + [6, '0x0000000000000000000000000000000000000000000000000000000000000001'], + [7, '0x0000000000000002cf135e7506a45d632d270d45f1181294833fc48d823f272c'], + [8, '0x0000000000000000000000000000000000000000000000000000000000000000'], +]); diff --git a/acvm-repo/acvm_js/test/shared/nested_acir_call.ts b/acvm-repo/acvm_js/test/shared/nested_acir_call.ts new file mode 100644 index 00000000000..64051dff93f --- /dev/null +++ b/acvm-repo/acvm_js/test/shared/nested_acir_call.ts @@ -0,0 +1,59 @@ +import { WitnessMap, StackItem, WitnessStack } from '@noir-lang/acvm_js'; + +// See `nested_acir_call_circuit` integration test in `acir/tests/test_program_serialization.rs`. +export const bytecode = Uint8Array.from([ + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 205, 146, 97, 10, 195, 32, 12, 133, 163, 66, 207, 147, 24, 173, 241, 223, 174, 50, + 153, 189, 255, 17, 214, 177, 148, 57, 17, 250, 99, 14, 250, 224, 97, 144, 16, 146, 143, 231, 224, 45, 167, 126, 105, + 217, 109, 118, 91, 248, 200, 168, 225, 248, 63, 107, 114, 208, 233, 104, 188, 233, 139, 191, 137, 108, 51, 139, 113, + 13, 161, 38, 95, 137, 233, 142, 62, 23, 137, 24, 98, 89, 133, 132, 162, 196, 135, 23, 230, 42, 65, 82, 46, 57, 97, + 166, 192, 149, 182, 152, 121, 211, 97, 110, 222, 94, 8, 13, 132, 182, 54, 48, 144, 235, 8, 254, 11, 22, 76, 132, 101, + 231, 237, 229, 23, 189, 213, 54, 119, 15, 83, 212, 199, 172, 175, 191, 226, 102, 96, 140, 251, 202, 84, 13, 204, 141, + 224, 25, 176, 161, 158, 53, 121, 144, 73, 14, 4, 0, 0, +]); + +export const initialWitnessMap: WitnessMap = new Map([ + [0, '0x0000000000000000000000000000000000000000000000000000000000000008'], + [1, '0x000000000000000000000000000000000000000000000000000000000000000a'], +]); + +const inner_call_witness: StackItem = { + index: 2, + witness: new Map([ + [0, '0x000000000000000000000000000000000000000000000000000000000000000a'], + [1, '0x000000000000000000000000000000000000000000000000000000000000000a'], + ]), +}; + +const nested_call_witness: StackItem = { + index: 1, + witness: new Map([ + [0, '0x0000000000000000000000000000000000000000000000000000000000000008'], + [1, '0x000000000000000000000000000000000000000000000000000000000000000a'], + [2, '0x000000000000000000000000000000000000000000000000000000000000000a'], + [3, '0x000000000000000000000000000000000000000000000000000000000000000a'], + ]), +}; + +const main_witness: StackItem = { + index: 0, + witness: new Map([ + [0, '0x0000000000000000000000000000000000000000000000000000000000000008'], + [1, '0x000000000000000000000000000000000000000000000000000000000000000a'], + [2, '0x000000000000000000000000000000000000000000000000000000000000000a'], + [3, '0x000000000000000000000000000000000000000000000000000000000000000a'], + ]), +}; + +export const expectedWitnessStack: WitnessStack = [ + inner_call_witness, + nested_call_witness, + inner_call_witness, + nested_call_witness, + main_witness, +]; + +export const expectedCompressedWitnessStack = Uint8Array.from([ + 31, 139, 8, 0, 0, 0, 0, 0, 2, 255, 237, 145, 177, 13, 0, 32, 8, 4, 17, 117, 31, 75, 75, 87, 113, 255, 37, 44, 196, 5, + 228, 42, 194, 39, 132, 238, 114, 249, 239, 114, 163, 118, 47, 203, 254, 240, 101, 23, 152, 213, 120, 199, 73, 58, 42, + 200, 170, 176, 87, 238, 27, 119, 95, 201, 238, 190, 89, 7, 37, 195, 196, 176, 4, 5, 0, 0, +]); diff --git a/acvm-repo/acvm_js/test/shared/pedersen.ts b/acvm-repo/acvm_js/test/shared/pedersen.ts index 5150d24131c..6e3ec403d65 100644 --- a/acvm-repo/acvm_js/test/shared/pedersen.ts +++ b/acvm-repo/acvm_js/test/shared/pedersen.ts @@ -1,7 +1,7 @@ // See `pedersen_circuit` integration test in `acir/tests/test_program_serialization.rs`. export const bytecode = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 93, 74, 135, 9, 0, 48, 8, 75, 171, 224, 255, 15, 139, 27, 196, 64, 200, 100, 0, 15, - 133, 80, 57, 89, 219, 127, 39, 173, 126, 235, 236, 247, 151, 48, 224, 71, 90, 33, 97, 0, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 93, 74, 73, 10, 0, 0, 4, 180, 29, 252, 255, 193, 66, 40, 76, 77, 179, 34, 20, 36, + 136, 237, 83, 245, 101, 107, 79, 65, 94, 253, 214, 217, 255, 239, 192, 1, 43, 124, 181, 238, 113, 0, 0, 0, ]); export const initialWitnessMap = new Map([[1, '0x0000000000000000000000000000000000000000000000000000000000000001']]); diff --git a/acvm-repo/acvm_js/test/shared/schnorr_verify.ts b/acvm-repo/acvm_js/test/shared/schnorr_verify.ts index 2127de66f69..05fcc47e3aa 100644 --- a/acvm-repo/acvm_js/test/shared/schnorr_verify.ts +++ b/acvm-repo/acvm_js/test/shared/schnorr_verify.ts @@ -1,17 +1,17 @@ // See `schnorr_verify_circuit` integration test in `acir/tests/test_program_serialization.rs`. export const bytecode = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 77, 210, 7, 74, 3, 1, 20, 69, 209, 177, 247, 222, 123, 239, 189, 119, 141, 93, 99, - 220, 133, 251, 95, 130, 152, 103, 78, 32, 3, 195, 33, 4, 66, 248, 239, 254, 20, 69, 209, 84, 212, 158, 216, 206, 223, - 234, 219, 204, 146, 239, 91, 170, 111, 103, 245, 109, 101, 27, 219, 217, 193, 250, 219, 197, 110, 246, 176, 151, 125, - 236, 231, 0, 7, 57, 196, 97, 142, 112, 148, 99, 28, 231, 4, 39, 57, 197, 105, 206, 112, 150, 115, 156, 231, 2, 23, - 185, 196, 101, 174, 112, 149, 107, 92, 231, 6, 55, 185, 197, 109, 238, 112, 151, 123, 220, 231, 1, 15, 121, 196, 99, - 158, 240, 148, 103, 60, 231, 5, 47, 121, 197, 107, 222, 240, 150, 119, 188, 231, 3, 75, 124, 228, 83, 195, 142, 121, - 158, 125, 126, 225, 43, 223, 248, 206, 15, 126, 178, 204, 47, 86, 248, 237, 119, 43, 76, 127, 105, 47, 189, 165, 181, - 116, 150, 198, 234, 125, 117, 249, 47, 233, 41, 45, 165, 163, 52, 148, 126, 210, 78, 186, 73, 51, 233, 37, 173, 164, - 147, 52, 146, 62, 210, 70, 186, 72, 19, 233, 33, 45, 164, 131, 52, 144, 253, 23, 139, 218, 238, 217, 60, 123, 103, - 235, 236, 156, 141, 179, 239, 166, 93, 183, 237, 185, 107, 199, 125, 251, 29, 218, 237, 216, 94, 167, 118, 58, 183, - 207, 165, 93, 174, 237, 113, 107, 135, 123, 247, 47, 185, 251, 147, 59, 191, 184, 239, 155, 187, 126, 184, 103, 217, - 29, 235, 55, 171, 223, 173, 104, 184, 231, 255, 243, 7, 236, 52, 239, 128, 225, 3, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 85, 210, 85, 78, 67, 81, 24, 133, 209, 226, 238, 238, 238, 238, 238, 165, 148, 82, + 102, 193, 252, 135, 64, 232, 78, 87, 147, 114, 147, 147, 5, 47, 132, 252, 251, 107, 41, 212, 191, 159, 218, 107, 241, + 115, 236, 226, 111, 237, 181, 178, 173, 246, 186, 107, 175, 157, 29, 236, 100, 23, 27, 175, 135, 189, 236, 99, 63, 7, + 56, 200, 33, 14, 115, 132, 163, 28, 227, 56, 39, 56, 201, 41, 78, 115, 134, 179, 156, 227, 60, 23, 184, 200, 37, 46, + 115, 133, 171, 92, 227, 58, 55, 184, 201, 45, 110, 115, 135, 187, 220, 227, 62, 15, 120, 200, 35, 30, 243, 132, 167, + 60, 227, 57, 47, 120, 201, 43, 94, 243, 134, 183, 188, 227, 61, 31, 248, 200, 39, 62, 243, 133, 175, 77, 59, 230, 123, + 243, 123, 145, 239, 44, 241, 131, 101, 126, 178, 194, 47, 86, 249, 237, 239, 86, 153, 238, 210, 92, 122, 75, 107, 233, + 44, 141, 53, 250, 234, 241, 191, 164, 167, 180, 148, 142, 210, 80, 250, 73, 59, 233, 38, 205, 164, 151, 180, 146, 78, + 210, 72, 250, 72, 27, 233, 34, 77, 164, 135, 180, 144, 14, 210, 64, 246, 95, 46, 212, 119, 207, 230, 217, 59, 91, 103, + 231, 108, 156, 125, 183, 237, 186, 107, 207, 125, 59, 30, 218, 239, 216, 110, 167, 246, 58, 183, 211, 165, 125, 174, + 237, 114, 107, 143, 123, 59, 60, 186, 255, 179, 187, 191, 186, 115, 209, 125, 75, 238, 90, 118, 207, 138, 59, 54, 110, + 214, 184, 91, 161, 233, 158, 255, 190, 63, 71, 59, 68, 130, 233, 3, 0, 0, ]); export const initialWitnessMap = new Map([ diff --git a/acvm-repo/acvm_js/test/shared/witness_compression.ts b/acvm-repo/acvm_js/test/shared/witness_compression.ts index 36b9a0284af..d2326c1b11b 100644 --- a/acvm-repo/acvm_js/test/shared/witness_compression.ts +++ b/acvm-repo/acvm_js/test/shared/witness_compression.ts @@ -4,19 +4,21 @@ // assert(x != y); // x + y // } +// +// Regenerate this byte array by going to the Noir integration tests and running `/test_programs/execution_success/witness_compression` +// after recompiling Noir to print the witness byte array to be written to file after execution export const expectedCompressedWitnessMap = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 2, 255, 173, 208, 187, 13, 128, 48, 12, 4, 80, 190, 153, 199, 142, 237, 196, 238, 88, 133, - 8, 103, 255, 17, 64, 34, 5, 61, 62, 233, 164, 171, 94, 113, 105, 122, 51, 63, 61, 198, 134, 127, 193, 37, 206, 202, - 235, 199, 34, 40, 204, 94, 179, 35, 225, 9, 217, 154, 10, 176, 180, 162, 168, 40, 42, 87, 86, 34, 87, 214, 106, 205, - 42, 24, 50, 57, 118, 49, 234, 3, 219, 2, 173, 61, 240, 175, 20, 103, 209, 13, 151, 252, 77, 33, 208, 1, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 2, 255, 173, 206, 185, 13, 0, 48, 8, 67, 209, 144, 107, 30, 146, 44, 144, 253, 167, 162, + 65, 130, 158, 239, 198, 174, 158, 44, 45, 178, 211, 254, 222, 90, 203, 17, 206, 186, 29, 252, 53, 64, 107, 114, 150, + 46, 206, 122, 6, 24, 73, 44, 193, 220, 1, 0, 0, ]); export const expectedWitnessMap = new Map([ - [1, '0x0000000000000000000000000000000000000000000000000000000000000001'], - [2, '0x0000000000000000000000000000000000000000000000000000000000000002'], - [3, '0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000'], - [4, '0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000'], - [5, '0x0000000000000000000000000000000000000000000000000000000000000001'], - [6, '0x0000000000000000000000000000000000000000000000000000000000000003'], + [0, '0x0000000000000000000000000000000000000000000000000000000000000001'], + [1, '0x0000000000000000000000000000000000000000000000000000000000000002'], + [2, '0x0000000000000000000000000000000000000000000000000000000000000001'], + [3, '0x0000000000000000000000000000000000000000000000000000000000000001'], + [4, '0x0000000000000000000000000000000000000000000000000000000000000000'], + [5, '0x0000000000000000000000000000000000000000000000000000000000000003'], ]); diff --git a/acvm-repo/blackbox_solver/Cargo.toml b/acvm-repo/blackbox_solver/Cargo.toml index 0794b2dbe7e..00c87bbca74 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.40.0" +version = "0.46.0" # x-release-please-end authors.workspace = true edition.workspace = true @@ -15,6 +15,7 @@ repository.workspace = true [dependencies] acir.workspace = true thiserror.workspace = true +num-bigint = "0.4" blake2 = "0.10.6" blake3 = "1.5.0" @@ -36,8 +37,8 @@ p256 = { version = "0.11.0", features = [ "arithmetic", ] } +libaes = "0.7.0" [features] -default = ["bn254"] bn254 = ["acir/bn254"] bls12_381 = ["acir/bls12_381"] diff --git a/acvm-repo/blackbox_solver/src/aes128.rs b/acvm-repo/blackbox_solver/src/aes128.rs new file mode 100644 index 00000000000..a4c6a228744 --- /dev/null +++ b/acvm-repo/blackbox_solver/src/aes128.rs @@ -0,0 +1,12 @@ +use crate::BlackBoxResolutionError; +use libaes::Cipher; + +pub fn aes128_encrypt( + inputs: &[u8], + iv: [u8; 16], + key: [u8; 16], +) -> Result, BlackBoxResolutionError> { + let cipher = Cipher::new_128(&key); + let encrypted = cipher.cbc_encrypt(&iv, inputs); + Ok(encrypted) +} diff --git a/acvm-repo/blackbox_solver/src/bigint.rs b/acvm-repo/blackbox_solver/src/bigint.rs new file mode 100644 index 00000000000..5b19f03a238 --- /dev/null +++ b/acvm-repo/blackbox_solver/src/bigint.rs @@ -0,0 +1,99 @@ +use std::collections::HashMap; + +use acir::BlackBoxFunc; + +use num_bigint::BigUint; + +use crate::BlackBoxResolutionError; + +/// Resolve BigInt opcodes by storing BigInt values (and their moduli) by their ID in a HashMap: +/// - When it encounters a bigint operation opcode, it performs the operation on the stored values +/// and store the result using the provided ID. +/// - When it gets a to_bytes opcode, it simply looks up the value and resolves the output witness accordingly. +#[derive(Default, Debug, Clone, PartialEq, Eq)] + +pub struct BigIntSolver { + bigint_id_to_value: HashMap, + bigint_id_to_modulus: HashMap, +} + +impl BigIntSolver { + pub(crate) fn get_bigint( + &self, + id: u32, + func: BlackBoxFunc, + ) -> Result { + self.bigint_id_to_value + .get(&id) + .ok_or(BlackBoxResolutionError::Failed( + func, + format!("could not find bigint of id {id}"), + )) + .cloned() + } + + pub(crate) fn get_modulus( + &self, + id: u32, + func: BlackBoxFunc, + ) -> Result { + self.bigint_id_to_modulus + .get(&id) + .ok_or(BlackBoxResolutionError::Failed( + func, + format!("could not find bigint of id {id}"), + )) + .cloned() + } + pub fn bigint_from_bytes( + &mut self, + inputs: &[u8], + modulus: &[u8], + output: u32, + ) -> Result<(), BlackBoxResolutionError> { + let bigint = BigUint::from_bytes_le(inputs); + self.bigint_id_to_value.insert(output, bigint); + let modulus = BigUint::from_bytes_le(modulus); + self.bigint_id_to_modulus.insert(output, modulus); + Ok(()) + } + + pub fn bigint_to_bytes(&self, input: u32) -> Result, BlackBoxResolutionError> { + let bigint = self.get_bigint(input, BlackBoxFunc::BigIntToLeBytes)?; + Ok(bigint.to_bytes_le()) + } + + pub fn bigint_op( + &mut self, + lhs: u32, + rhs: u32, + output: u32, + func: BlackBoxFunc, + ) -> Result<(), BlackBoxResolutionError> { + let modulus = self.get_modulus(lhs, func)?; + let lhs = self.get_bigint(lhs, func)?; + let rhs = self.get_bigint(rhs, func)?; + let mut result = match func { + BlackBoxFunc::BigIntAdd => lhs + rhs, + BlackBoxFunc::BigIntSub => { + if lhs >= rhs { + &lhs - &rhs + } else { + &lhs + &modulus - &rhs + } + } + BlackBoxFunc::BigIntMul => lhs * rhs, + BlackBoxFunc::BigIntDiv => { + lhs * rhs.modpow(&(&modulus - BigUint::from(2_u32)), &modulus) + } //TODO ensure that modulus is prime + _ => unreachable!("ICE - bigint_op must be called for an operation"), + }; + if result > modulus { + let q = &result / &modulus; + result -= q * &modulus; + } + self.bigint_id_to_value.insert(output, result); + self.bigint_id_to_modulus.insert(output, modulus); + Ok(()) + } +} diff --git a/acvm-repo/blackbox_solver/src/curve_specific_solver.rs b/acvm-repo/blackbox_solver/src/curve_specific_solver.rs index f0ab4561229..0ee3a252840 100644 --- a/acvm-repo/blackbox_solver/src/curve_specific_solver.rs +++ b/acvm-repo/blackbox_solver/src/curve_specific_solver.rs @@ -1,4 +1,4 @@ -use acir::{BlackBoxFunc, FieldElement}; +use acir::BlackBoxFunc; use crate::BlackBoxResolutionError; @@ -6,41 +6,44 @@ use crate::BlackBoxResolutionError; /// doesn't have a canonical Rust implementation. /// /// Returns an [`BlackBoxResolutionError`] if the backend does not support the given [`acir::BlackBoxFunc`]. -pub trait BlackBoxFunctionSolver { +pub trait BlackBoxFunctionSolver { fn schnorr_verify( &self, - public_key_x: &FieldElement, - public_key_y: &FieldElement, - signature: &[u8], + public_key_x: &F, + public_key_y: &F, + signature: &[u8; 64], message: &[u8], ) -> Result; fn pedersen_commitment( &self, - inputs: &[FieldElement], + inputs: &[F], domain_separator: u32, - ) -> Result<(FieldElement, FieldElement), BlackBoxResolutionError>; + ) -> Result<(F, F), BlackBoxResolutionError>; fn pedersen_hash( &self, - inputs: &[FieldElement], + inputs: &[F], domain_separator: u32, - ) -> Result; - fn fixed_base_scalar_mul( + ) -> Result; + fn multi_scalar_mul( &self, - low: &FieldElement, - high: &FieldElement, - ) -> Result<(FieldElement, FieldElement), BlackBoxResolutionError>; + points: &[F], + scalars_lo: &[F], + scalars_hi: &[F], + ) -> Result<(F, F, F), BlackBoxResolutionError>; fn ec_add( &self, - input1_x: &FieldElement, - input1_y: &FieldElement, - input2_x: &FieldElement, - input2_y: &FieldElement, - ) -> Result<(FieldElement, FieldElement), BlackBoxResolutionError>; + input1_x: &F, + input1_y: &F, + input1_infinite: &F, + input2_x: &F, + input2_y: &F, + input2_infinite: &F, + ) -> Result<(F, F, F), BlackBoxResolutionError>; fn poseidon2_permutation( &self, - _inputs: &[FieldElement], + _inputs: &[F], _len: u32, - ) -> Result, BlackBoxResolutionError>; + ) -> Result, BlackBoxResolutionError>; } pub struct StubbedBlackBoxSolver; @@ -54,51 +57,54 @@ impl StubbedBlackBoxSolver { } } -impl BlackBoxFunctionSolver for StubbedBlackBoxSolver { +impl BlackBoxFunctionSolver for StubbedBlackBoxSolver { fn schnorr_verify( &self, - _public_key_x: &FieldElement, - _public_key_y: &FieldElement, - _signature: &[u8], + _public_key_x: &F, + _public_key_y: &F, + _signature: &[u8; 64], _message: &[u8], ) -> Result { Err(Self::fail(BlackBoxFunc::SchnorrVerify)) } fn pedersen_commitment( &self, - _inputs: &[FieldElement], + _inputs: &[F], _domain_separator: u32, - ) -> Result<(FieldElement, FieldElement), BlackBoxResolutionError> { + ) -> Result<(F, F), BlackBoxResolutionError> { Err(Self::fail(BlackBoxFunc::PedersenCommitment)) } fn pedersen_hash( &self, - _inputs: &[FieldElement], + _inputs: &[F], _domain_separator: u32, - ) -> Result { + ) -> Result { Err(Self::fail(BlackBoxFunc::PedersenHash)) } - fn fixed_base_scalar_mul( + fn multi_scalar_mul( &self, - _low: &FieldElement, - _high: &FieldElement, - ) -> Result<(FieldElement, FieldElement), BlackBoxResolutionError> { - Err(Self::fail(BlackBoxFunc::FixedBaseScalarMul)) + _points: &[F], + _scalars_lo: &[F], + _scalars_hi: &[F], + ) -> Result<(F, F, F), BlackBoxResolutionError> { + Err(Self::fail(BlackBoxFunc::MultiScalarMul)) } fn ec_add( &self, - _input1_x: &FieldElement, - _input1_y: &FieldElement, - _input2_x: &FieldElement, - _input2_y: &FieldElement, - ) -> Result<(FieldElement, FieldElement), BlackBoxResolutionError> { + _input1_x: &F, + _input1_y: &F, + _input1_infinite: &F, + _input2_x: &F, + _input2_y: &F, + _input2_infinite: &F, + ) -> Result<(F, F, F), BlackBoxResolutionError> { Err(Self::fail(BlackBoxFunc::EmbeddedCurveAdd)) } fn poseidon2_permutation( &self, - _inputs: &[FieldElement], + _inputs: &[F], _len: u32, - ) -> Result, BlackBoxResolutionError> { + ) -> Result, BlackBoxResolutionError> { Err(Self::fail(BlackBoxFunc::Poseidon2Permutation)) } } diff --git a/acvm-repo/blackbox_solver/src/ecdsa/mod.rs b/acvm-repo/blackbox_solver/src/ecdsa/mod.rs new file mode 100644 index 00000000000..cb3134bf0ab --- /dev/null +++ b/acvm-repo/blackbox_solver/src/ecdsa/mod.rs @@ -0,0 +1,22 @@ +use crate::BlackBoxResolutionError; + +mod secp256k1; +mod secp256r1; + +pub fn ecdsa_secp256k1_verify( + hashed_msg: &[u8], + public_key_x: &[u8; 32], + public_key_y: &[u8; 32], + signature: &[u8; 64], +) -> Result { + Ok(secp256k1::verify_signature(hashed_msg, public_key_x, public_key_y, signature)) +} + +pub fn ecdsa_secp256r1_verify( + hashed_msg: &[u8], + public_key_x: &[u8; 32], + public_key_y: &[u8; 32], + signature: &[u8; 64], +) -> Result { + Ok(secp256r1::verify_signature(hashed_msg, public_key_x, public_key_y, signature)) +} diff --git a/acvm-repo/blackbox_solver/src/ecdsa/secp256k1.rs b/acvm-repo/blackbox_solver/src/ecdsa/secp256k1.rs new file mode 100644 index 00000000000..17c51353f7f --- /dev/null +++ b/acvm-repo/blackbox_solver/src/ecdsa/secp256k1.rs @@ -0,0 +1,137 @@ +use k256::elliptic_curve::sec1::FromEncodedPoint; +use k256::elliptic_curve::PrimeField; + +use blake2::digest::generic_array::GenericArray; +use k256::{ecdsa::Signature, Scalar}; +use k256::{ + elliptic_curve::{ + sec1::{Coordinates, ToEncodedPoint}, + IsHigh, + }, + AffinePoint, EncodedPoint, ProjectivePoint, PublicKey, +}; + +pub(super) fn verify_signature( + hashed_msg: &[u8], + public_key_x_bytes: &[u8; 32], + public_key_y_bytes: &[u8; 32], + signature: &[u8; 64], +) -> bool { + // Convert the inputs into k256 data structures + let Ok(signature) = Signature::try_from(signature.as_slice()) else { + // Signature `r` and `s` are forbidden from being zero. + return false; + }; + + let point = EncodedPoint::from_affine_coordinates( + public_key_x_bytes.into(), + public_key_y_bytes.into(), + true, + ); + + let pubkey = PublicKey::from_encoded_point(&point); + let pubkey = if pubkey.is_some().into() { + pubkey.unwrap() + } else { + // Public key must sit on the Secp256k1 curve. + return false; + }; + + // Note: This is incorrect as it will panic if `hashed_msg >= k256::Secp256k1::ORDER`. + // In this scenario we should just take the leftmost bits from `hashed_msg` up to the group order length. + let z = Scalar::from_repr(*GenericArray::from_slice(hashed_msg)).unwrap(); + + // Finished converting bytes into data structures + + let r = signature.r(); + let s = signature.s(); + + // Ensure signature is "low S" normalized ala BIP 0062 + if s.is_high().into() { + return false; + } + + let s_inv = s.invert().unwrap(); + let u1 = z * s_inv; + let u2 = *r * s_inv; + + #[allow(non_snake_case)] + let R: AffinePoint = ((ProjectivePoint::GENERATOR * u1) + + (ProjectivePoint::from(*pubkey.as_affine()) * u2)) + .to_affine(); + + match R.to_encoded_point(false).coordinates() { + Coordinates::Uncompressed { x, y: _ } => Scalar::from_repr(*x).unwrap().eq(&r), + _ => unreachable!("Point is uncompressed"), + } +} + +#[cfg(test)] +mod secp256k1_tests { + use super::verify_signature; + + // 0x3a73f4123a5cd2121f21cd7e8d358835476949d035d9c2da6806b4633ac8c1e2, + const HASHED_MESSAGE: [u8; 32] = [ + 0x3a, 0x73, 0xf4, 0x12, 0x3a, 0x5c, 0xd2, 0x12, 0x1f, 0x21, 0xcd, 0x7e, 0x8d, 0x35, 0x88, + 0x35, 0x47, 0x69, 0x49, 0xd0, 0x35, 0xd9, 0xc2, 0xda, 0x68, 0x06, 0xb4, 0x63, 0x3a, 0xc8, + 0xc1, 0xe2, + ]; + // 0xa0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7 + const PUB_KEY_X: [u8; 32] = [ + 0xa0, 0x43, 0x4d, 0x9e, 0x47, 0xf3, 0xc8, 0x62, 0x35, 0x47, 0x7c, 0x7b, 0x1a, 0xe6, 0xae, + 0x5d, 0x34, 0x42, 0xd4, 0x9b, 0x19, 0x43, 0xc2, 0xb7, 0x52, 0xa6, 0x8e, 0x2a, 0x47, 0xe2, + 0x47, 0xc7, + ]; + // 0x893aba425419bc27a3b6c7e693a24c696f794c2ed877a1593cbee53b037368d7 + const PUB_KEY_Y: [u8; 32] = [ + 0x89, 0x3a, 0xba, 0x42, 0x54, 0x19, 0xbc, 0x27, 0xa3, 0xb6, 0xc7, 0xe6, 0x93, 0xa2, 0x4c, + 0x69, 0x6f, 0x79, 0x4c, 0x2e, 0xd8, 0x77, 0xa1, 0x59, 0x3c, 0xbe, 0xe5, 0x3b, 0x03, 0x73, + 0x68, 0xd7, + ]; + // 0xe5081c80ab427dc370346f4a0e31aa2bad8d9798c38061db9ae55a4e8df454fd28119894344e71b78770cc931d61f480ecbb0b89d6eb69690161e49a715fcd55 + const SIGNATURE: [u8; 64] = [ + 0xe5, 0x08, 0x1c, 0x80, 0xab, 0x42, 0x7d, 0xc3, 0x70, 0x34, 0x6f, 0x4a, 0x0e, 0x31, 0xaa, + 0x2b, 0xad, 0x8d, 0x97, 0x98, 0xc3, 0x80, 0x61, 0xdb, 0x9a, 0xe5, 0x5a, 0x4e, 0x8d, 0xf4, + 0x54, 0xfd, 0x28, 0x11, 0x98, 0x94, 0x34, 0x4e, 0x71, 0xb7, 0x87, 0x70, 0xcc, 0x93, 0x1d, + 0x61, 0xf4, 0x80, 0xec, 0xbb, 0x0b, 0x89, 0xd6, 0xeb, 0x69, 0x69, 0x01, 0x61, 0xe4, 0x9a, + 0x71, 0x5f, 0xcd, 0x55, + ]; + + #[test] + fn verifies_valid_signature_with_low_s_value() { + let valid = verify_signature(&HASHED_MESSAGE, &PUB_KEY_X, &PUB_KEY_Y, &SIGNATURE); + + assert!(valid); + } + + #[test] + fn rejects_invalid_signature() { + // This signature is invalid as ECDSA specifies that `r` and `s` must be non-zero. + let invalid_signature: [u8; 64] = [0x00; 64]; + + let valid = verify_signature(&HASHED_MESSAGE, &PUB_KEY_X, &PUB_KEY_Y, &invalid_signature); + assert!(!valid); + } + + #[test] + fn rejects_invalid_public_key() { + let invalid_pub_key_x: [u8; 32] = [0xff; 32]; + let invalid_pub_key_y: [u8; 32] = [0xff; 32]; + + let valid = + verify_signature(&HASHED_MESSAGE, &invalid_pub_key_x, &invalid_pub_key_y, &SIGNATURE); + + assert!(!valid); + } + + #[test] + #[ignore = "ECDSA verification does not currently handle long hashes correctly"] + fn trims_overly_long_hashes_to_correct_length() { + let mut long_hashed_message = HASHED_MESSAGE.to_vec(); + long_hashed_message.push(0xff); + + let valid = verify_signature(&long_hashed_message, &PUB_KEY_X, &PUB_KEY_Y, &SIGNATURE); + + assert!(valid); + } +} diff --git a/acvm-repo/blackbox_solver/src/ecdsa/secp256r1.rs b/acvm-repo/blackbox_solver/src/ecdsa/secp256r1.rs new file mode 100644 index 00000000000..54559d7c774 --- /dev/null +++ b/acvm-repo/blackbox_solver/src/ecdsa/secp256r1.rs @@ -0,0 +1,133 @@ +use p256::elliptic_curve::sec1::FromEncodedPoint; +use p256::elliptic_curve::PrimeField; + +use blake2::digest::generic_array::GenericArray; +use p256::{ecdsa::Signature, Scalar}; +use p256::{ + elliptic_curve::{ + sec1::{Coordinates, ToEncodedPoint}, + IsHigh, + }, + AffinePoint, EncodedPoint, ProjectivePoint, PublicKey, +}; + +pub(super) fn verify_signature( + hashed_msg: &[u8], + public_key_x_bytes: &[u8; 32], + public_key_y_bytes: &[u8; 32], + signature: &[u8; 64], +) -> bool { + // Convert the inputs into k256 data structures + let Ok(signature) = Signature::try_from(signature.as_slice()) else { + // Signature `r` and `s` are forbidden from being zero. + return false; + }; + + let point = EncodedPoint::from_affine_coordinates( + public_key_x_bytes.into(), + public_key_y_bytes.into(), + true, + ); + + let pubkey = PublicKey::from_encoded_point(&point); + let pubkey = if pubkey.is_some().into() { + pubkey.unwrap() + } else { + // Public key must sit on the Secp256r1 curve. + return false; + }; + + // Note: This is incorrect as it will panic if `hashed_msg >= p256::NistP256::ORDER`. + // In this scenario we should just take the leftmost bits from `hashed_msg` up to the group order length. + let z = Scalar::from_repr(*GenericArray::from_slice(hashed_msg)).unwrap(); + + // Finished converting bytes into data structures + + let r = signature.r(); + let s = signature.s(); + + // Ensure signature is "low S" normalized ala BIP 0062 + if s.is_high().into() { + return false; + } + + let s_inv = s.invert().unwrap(); + let u1 = z * s_inv; + let u2 = *r * s_inv; + + #[allow(non_snake_case)] + let R: AffinePoint = ((ProjectivePoint::GENERATOR * u1) + + (ProjectivePoint::from(*pubkey.as_affine()) * u2)) + .to_affine(); + + match R.to_encoded_point(false).coordinates() { + Coordinates::Uncompressed { x, y: _ } => Scalar::from_repr(*x).unwrap().eq(&r), + _ => unreachable!("Point is uncompressed"), + } +} + +#[cfg(test)] +mod secp256r1_tests { + use super::verify_signature; + + // 0x54705ba3baafdbdfba8c5f9a70f7a89bee98d906b53e31074da7baecdc0da9ad + const HASHED_MESSAGE: [u8; 32] = [ + 84, 112, 91, 163, 186, 175, 219, 223, 186, 140, 95, 154, 112, 247, 168, 155, 238, 152, 217, + 6, 181, 62, 49, 7, 77, 167, 186, 236, 220, 13, 169, 173, + ]; + // 0x550f471003f3df97c3df506ac797f6721fb1a1fb7b8f6f83d224498a65c88e24 + const PUB_KEY_X: [u8; 32] = [ + 85, 15, 71, 16, 3, 243, 223, 151, 195, 223, 80, 106, 199, 151, 246, 114, 31, 177, 161, 251, + 123, 143, 111, 131, 210, 36, 73, 138, 101, 200, 142, 36, + ]; + // 0x136093d7012e509a73715cbd0b00a3cc0ff4b5c01b3ffa196ab1fb327036b8e6 + const PUB_KEY_Y: [u8; 32] = [ + 19, 96, 147, 215, 1, 46, 80, 154, 115, 113, 92, 189, 11, 0, 163, 204, 15, 244, 181, 192, + 27, 63, 250, 25, 106, 177, 251, 50, 112, 54, 184, 230, + ]; + // 0x2c70a8d084b62bfc5ce03641caf9f72ad4da8c81bfe6ec9487bb5e1bef62a13218ad9ee29eaf351fdc50f1520c425e9b908a07278b43b0ec7b872778c14e0784 + const SIGNATURE: [u8; 64] = [ + 44, 112, 168, 208, 132, 182, 43, 252, 92, 224, 54, 65, 202, 249, 247, 42, 212, 218, 140, + 129, 191, 230, 236, 148, 135, 187, 94, 27, 239, 98, 161, 50, 24, 173, 158, 226, 158, 175, + 53, 31, 220, 80, 241, 82, 12, 66, 94, 155, 144, 138, 7, 39, 139, 67, 176, 236, 123, 135, + 39, 120, 193, 78, 7, 132, + ]; + + #[test] + fn verifies_valid_signature_with_low_s_value() { + let valid = verify_signature(&HASHED_MESSAGE, &PUB_KEY_X, &PUB_KEY_Y, &SIGNATURE); + + assert!(valid); + } + + #[test] + fn rejects_invalid_signature() { + // This signature is invalid as ECDSA specifies that `r` and `s` must be non-zero. + let invalid_signature: [u8; 64] = [0x00; 64]; + + let valid = verify_signature(&HASHED_MESSAGE, &PUB_KEY_X, &PUB_KEY_Y, &invalid_signature); + assert!(!valid); + } + + #[test] + fn rejects_invalid_public_key() { + let invalid_pub_key_x: [u8; 32] = [0xff; 32]; + let invalid_pub_key_y: [u8; 32] = [0xff; 32]; + + let valid = + verify_signature(&HASHED_MESSAGE, &invalid_pub_key_x, &invalid_pub_key_y, &SIGNATURE); + + assert!(!valid); + } + + #[test] + #[ignore = "ECDSA verification does not currently handle long hashes correctly"] + fn trims_overly_long_hashes_to_correct_length() { + let mut long_hashed_message = HASHED_MESSAGE.to_vec(); + long_hashed_message.push(0xff); + + let valid = verify_signature(&long_hashed_message, &PUB_KEY_X, &PUB_KEY_Y, &SIGNATURE); + + assert!(valid); + } +} diff --git a/acvm-repo/blackbox_solver/src/hash.rs b/acvm-repo/blackbox_solver/src/hash.rs new file mode 100644 index 00000000000..ac56029b436 --- /dev/null +++ b/acvm-repo/blackbox_solver/src/hash.rs @@ -0,0 +1,126 @@ +use acir::BlackBoxFunc; +use blake2::digest::generic_array::GenericArray; +use blake2::{Blake2s256, Digest}; +use sha2::Sha256; +use sha3::Keccak256; + +use crate::BlackBoxResolutionError; + +/// Does a generic hash of the inputs returning the resulting 32 bytes separately. +fn generic_hash_256(message: &[u8]) -> Result<[u8; 32], String> { + let output_bytes: [u8; 32] = + D::digest(message).as_slice().try_into().map_err(|_| "digest should be 256 bits")?; + + Ok(output_bytes) +} + +pub fn sha256(inputs: &[u8]) -> Result<[u8; 32], BlackBoxResolutionError> { + generic_hash_256::(inputs) + .map_err(|err| BlackBoxResolutionError::Failed(BlackBoxFunc::SHA256, err)) +} + +pub fn blake2s(inputs: &[u8]) -> Result<[u8; 32], BlackBoxResolutionError> { + generic_hash_256::(inputs) + .map_err(|err| BlackBoxResolutionError::Failed(BlackBoxFunc::Blake2s, err)) +} + +pub fn blake3(inputs: &[u8]) -> Result<[u8; 32], BlackBoxResolutionError> { + Ok(blake3::hash(inputs).into()) +} + +pub fn keccak256(inputs: &[u8]) -> Result<[u8; 32], BlackBoxResolutionError> { + generic_hash_256::(inputs) + .map_err(|err| BlackBoxResolutionError::Failed(BlackBoxFunc::Keccak256, err)) +} + +pub fn sha256compression(state: &mut [u32; 8], msg_blocks: &[u32; 16]) { + let mut blocks = [0_u8; 64]; + for (i, block) in msg_blocks.iter().enumerate() { + let bytes = block.to_be_bytes(); + blocks[i * 4..i * 4 + 4].copy_from_slice(&bytes); + } + let blocks: GenericArray = blocks.into(); + sha2::compress256(state, &[blocks]); +} + +const KECCAK_LANES: usize = 25; + +pub fn keccakf1600( + mut state: [u64; KECCAK_LANES], +) -> Result<[u64; KECCAK_LANES], BlackBoxResolutionError> { + keccak::f1600(&mut state); + Ok(state) +} + +#[cfg(test)] +mod keccakf1600_tests { + use super::keccakf1600; + + #[test] + fn sanity_check() { + // Test vectors are copied from XKCP (eXtended Keccak Code Package) + // https://github.com/XKCP/XKCP/blob/master/tests/TestVectors/KeccakF-1600-IntermediateValues.txt + let zero_state = [0u64; 25]; + + let expected_state_first = [ + 0xF1258F7940E1DDE7, + 0x84D5CCF933C0478A, + 0xD598261EA65AA9EE, + 0xBD1547306F80494D, + 0x8B284E056253D057, + 0xFF97A42D7F8E6FD4, + 0x90FEE5A0A44647C4, + 0x8C5BDA0CD6192E76, + 0xAD30A6F71B19059C, + 0x30935AB7D08FFC64, + 0xEB5AA93F2317D635, + 0xA9A6E6260D712103, + 0x81A57C16DBCF555F, + 0x43B831CD0347C826, + 0x01F22F1A11A5569F, + 0x05E5635A21D9AE61, + 0x64BEFEF28CC970F2, + 0x613670957BC46611, + 0xB87C5A554FD00ECB, + 0x8C3EE88A1CCF32C8, + 0x940C7922AE3A2614, + 0x1841F924A2C509E4, + 0x16F53526E70465C2, + 0x75F644E97F30A13B, + 0xEAF1FF7B5CECA249, + ]; + let expected_state_second = [ + 0x2D5C954DF96ECB3C, + 0x6A332CD07057B56D, + 0x093D8D1270D76B6C, + 0x8A20D9B25569D094, + 0x4F9C4F99E5E7F156, + 0xF957B9A2DA65FB38, + 0x85773DAE1275AF0D, + 0xFAF4F247C3D810F7, + 0x1F1B9EE6F79A8759, + 0xE4FECC0FEE98B425, + 0x68CE61B6B9CE68A1, + 0xDEEA66C4BA8F974F, + 0x33C43D836EAFB1F5, + 0xE00654042719DBD9, + 0x7CF8A9F009831265, + 0xFD5449A6BF174743, + 0x97DDAD33D8994B40, + 0x48EAD5FC5D0BE774, + 0xE3B8C8EE55B7B03C, + 0x91A0226E649E42E9, + 0x900E3129E7BADD7B, + 0x202A9EC5FAA3CCE8, + 0x5B3402464E1C3DB6, + 0x609F4E62A44C1059, + 0x20D06CD26A8FBF5C, + ]; + + let state_first = keccakf1600(zero_state).unwrap(); + let state_second = keccakf1600(state_first).unwrap(); + + assert_eq!(state_first, expected_state_first); + assert_eq!(state_second, expected_state_second); + } +} diff --git a/acvm-repo/blackbox_solver/src/lib.rs b/acvm-repo/blackbox_solver/src/lib.rs index e033344fefa..a68b52a2a62 100644 --- a/acvm-repo/blackbox_solver/src/lib.rs +++ b/acvm-repo/blackbox_solver/src/lib.rs @@ -8,456 +8,22 @@ //! For functions that have a reference implementation, such as [keccak256], this crate exports the reference implementation directly. use acir::BlackBoxFunc; -use blake2::digest::generic_array::GenericArray; -use blake2::{Blake2s256, Digest}; -use sha2::Sha256; -use sha3::Keccak256; use thiserror::Error; +mod aes128; +mod bigint; mod curve_specific_solver; +mod ecdsa; +mod hash; +pub use aes128::aes128_encrypt; +pub use bigint::BigIntSolver; pub use curve_specific_solver::{BlackBoxFunctionSolver, StubbedBlackBoxSolver}; +pub use ecdsa::{ecdsa_secp256k1_verify, ecdsa_secp256r1_verify}; +pub use hash::{blake2s, blake3, keccak256, keccakf1600, sha256, sha256compression}; #[derive(Clone, PartialEq, Eq, Debug, Error)] pub enum BlackBoxResolutionError { #[error("failed to solve blackbox function: {0}, reason: {1}")] Failed(BlackBoxFunc, String), } - -pub fn sha256(inputs: &[u8]) -> Result<[u8; 32], BlackBoxResolutionError> { - generic_hash_256::(inputs) - .map_err(|err| BlackBoxResolutionError::Failed(BlackBoxFunc::SHA256, err)) -} - -pub fn blake2s(inputs: &[u8]) -> Result<[u8; 32], BlackBoxResolutionError> { - generic_hash_256::(inputs) - .map_err(|err| BlackBoxResolutionError::Failed(BlackBoxFunc::Blake2s, err)) -} - -pub fn blake3(inputs: &[u8]) -> Result<[u8; 32], BlackBoxResolutionError> { - Ok(blake3::hash(inputs).into()) -} - -pub fn keccak256(inputs: &[u8]) -> Result<[u8; 32], BlackBoxResolutionError> { - generic_hash_256::(inputs) - .map_err(|err| BlackBoxResolutionError::Failed(BlackBoxFunc::Keccak256, err)) -} - -pub fn sha256compression(state: &mut [u32; 8], msg_blocks: &[u32; 16]) { - let mut blocks = [0_u8; 64]; - for (i, block) in msg_blocks.iter().enumerate() { - let bytes = block.to_be_bytes(); - blocks[i * 4..i * 4 + 4].copy_from_slice(&bytes); - } - let blocks: GenericArray = blocks.into(); - sha2::compress256(state, &[blocks]); -} - -const KECCAK_LANES: usize = 25; - -pub fn keccakf1600( - mut state: [u64; KECCAK_LANES], -) -> Result<[u64; KECCAK_LANES], BlackBoxResolutionError> { - keccak::f1600(&mut state); - Ok(state) -} - -pub fn ecdsa_secp256k1_verify( - hashed_msg: &[u8], - public_key_x: &[u8; 32], - public_key_y: &[u8; 32], - signature: &[u8; 64], -) -> Result { - Ok(verify_secp256k1_ecdsa_signature(hashed_msg, public_key_x, public_key_y, signature)) -} - -pub fn ecdsa_secp256r1_verify( - hashed_msg: &[u8], - public_key_x: &[u8; 32], - public_key_y: &[u8; 32], - signature: &[u8; 64], -) -> Result { - Ok(verify_secp256r1_ecdsa_signature(hashed_msg, public_key_x, public_key_y, signature)) -} - -/// Does a generic hash of the inputs returning the resulting 32 bytes separately. -fn generic_hash_256(message: &[u8]) -> Result<[u8; 32], String> { - let output_bytes: [u8; 32] = - D::digest(message).as_slice().try_into().map_err(|_| "digest should be 256 bits")?; - - Ok(output_bytes) -} - -fn verify_secp256k1_ecdsa_signature( - hashed_msg: &[u8], - public_key_x_bytes: &[u8; 32], - public_key_y_bytes: &[u8; 32], - signature: &[u8; 64], -) -> bool { - use k256::elliptic_curve::sec1::FromEncodedPoint; - use k256::elliptic_curve::PrimeField; - - use k256::{ecdsa::Signature, Scalar}; - use k256::{ - elliptic_curve::{ - sec1::{Coordinates, ToEncodedPoint}, - IsHigh, - }, - AffinePoint, EncodedPoint, ProjectivePoint, PublicKey, - }; - // Convert the inputs into k256 data structures - - let Ok(signature) = Signature::try_from(signature.as_slice()) else { - // Signature `r` and `s` are forbidden from being zero. - return false; - }; - - let point = EncodedPoint::from_affine_coordinates( - public_key_x_bytes.into(), - public_key_y_bytes.into(), - true, - ); - - let pubkey = PublicKey::from_encoded_point(&point); - let pubkey = if pubkey.is_some().into() { - pubkey.unwrap() - } else { - // Public key must sit on the Secp256k1 curve. - return false; - }; - - // Note: This is incorrect as it will panic if `hashed_msg >= k256::Secp256k1::ORDER`. - // In this scenario we should just take the leftmost bits from `hashed_msg` up to the group order length. - let z = Scalar::from_repr(*GenericArray::from_slice(hashed_msg)).unwrap(); - - // Finished converting bytes into data structures - - let r = signature.r(); - let s = signature.s(); - - // Ensure signature is "low S" normalized ala BIP 0062 - if s.is_high().into() { - return false; - } - - let s_inv = s.invert().unwrap(); - let u1 = z * s_inv; - let u2 = *r * s_inv; - - #[allow(non_snake_case)] - let R: AffinePoint = ((ProjectivePoint::GENERATOR * u1) - + (ProjectivePoint::from(*pubkey.as_affine()) * u2)) - .to_affine(); - - match R.to_encoded_point(false).coordinates() { - Coordinates::Uncompressed { x, y: _ } => Scalar::from_repr(*x).unwrap().eq(&r), - _ => unreachable!("Point is uncompressed"), - } -} - -fn verify_secp256r1_ecdsa_signature( - hashed_msg: &[u8], - public_key_x_bytes: &[u8; 32], - public_key_y_bytes: &[u8; 32], - signature: &[u8; 64], -) -> bool { - use p256::elliptic_curve::sec1::FromEncodedPoint; - use p256::elliptic_curve::PrimeField; - - use p256::{ecdsa::Signature, Scalar}; - use p256::{ - elliptic_curve::{ - sec1::{Coordinates, ToEncodedPoint}, - IsHigh, - }, - AffinePoint, EncodedPoint, ProjectivePoint, PublicKey, - }; - - // Convert the inputs into k256 data structures - - let Ok(signature) = Signature::try_from(signature.as_slice()) else { - // Signature `r` and `s` are forbidden from being zero. - return false; - }; - - let point = EncodedPoint::from_affine_coordinates( - public_key_x_bytes.into(), - public_key_y_bytes.into(), - true, - ); - - let pubkey = PublicKey::from_encoded_point(&point); - let pubkey = if pubkey.is_some().into() { - pubkey.unwrap() - } else { - // Public key must sit on the Secp256r1 curve. - return false; - }; - - // Note: This is incorrect as it will panic if `hashed_msg >= p256::NistP256::ORDER`. - // In this scenario we should just take the leftmost bits from `hashed_msg` up to the group order length. - let z = Scalar::from_repr(*GenericArray::from_slice(hashed_msg)).unwrap(); - - // Finished converting bytes into data structures - - let r = signature.r(); - let s = signature.s(); - - // Ensure signature is "low S" normalized ala BIP 0062 - if s.is_high().into() { - return false; - } - - let s_inv = s.invert().unwrap(); - let u1 = z * s_inv; - let u2 = *r * s_inv; - - #[allow(non_snake_case)] - let R: AffinePoint = ((ProjectivePoint::GENERATOR * u1) - + (ProjectivePoint::from(*pubkey.as_affine()) * u2)) - .to_affine(); - - match R.to_encoded_point(false).coordinates() { - Coordinates::Uncompressed { x, y: _ } => Scalar::from_repr(*x).unwrap().eq(&r), - _ => unreachable!("Point is uncompressed"), - } -} - -#[cfg(test)] -mod keccakf1600_tests { - use crate::keccakf1600; - - #[test] - fn sanity_check() { - // Test vectors are copied from XKCP (eXtended Keccak Code Package) - // https://github.com/XKCP/XKCP/blob/master/tests/TestVectors/KeccakF-1600-IntermediateValues.txt - let zero_state = [0u64; 25]; - - let expected_state_first = [ - 0xF1258F7940E1DDE7, - 0x84D5CCF933C0478A, - 0xD598261EA65AA9EE, - 0xBD1547306F80494D, - 0x8B284E056253D057, - 0xFF97A42D7F8E6FD4, - 0x90FEE5A0A44647C4, - 0x8C5BDA0CD6192E76, - 0xAD30A6F71B19059C, - 0x30935AB7D08FFC64, - 0xEB5AA93F2317D635, - 0xA9A6E6260D712103, - 0x81A57C16DBCF555F, - 0x43B831CD0347C826, - 0x01F22F1A11A5569F, - 0x05E5635A21D9AE61, - 0x64BEFEF28CC970F2, - 0x613670957BC46611, - 0xB87C5A554FD00ECB, - 0x8C3EE88A1CCF32C8, - 0x940C7922AE3A2614, - 0x1841F924A2C509E4, - 0x16F53526E70465C2, - 0x75F644E97F30A13B, - 0xEAF1FF7B5CECA249, - ]; - let expected_state_second = [ - 0x2D5C954DF96ECB3C, - 0x6A332CD07057B56D, - 0x093D8D1270D76B6C, - 0x8A20D9B25569D094, - 0x4F9C4F99E5E7F156, - 0xF957B9A2DA65FB38, - 0x85773DAE1275AF0D, - 0xFAF4F247C3D810F7, - 0x1F1B9EE6F79A8759, - 0xE4FECC0FEE98B425, - 0x68CE61B6B9CE68A1, - 0xDEEA66C4BA8F974F, - 0x33C43D836EAFB1F5, - 0xE00654042719DBD9, - 0x7CF8A9F009831265, - 0xFD5449A6BF174743, - 0x97DDAD33D8994B40, - 0x48EAD5FC5D0BE774, - 0xE3B8C8EE55B7B03C, - 0x91A0226E649E42E9, - 0x900E3129E7BADD7B, - 0x202A9EC5FAA3CCE8, - 0x5B3402464E1C3DB6, - 0x609F4E62A44C1059, - 0x20D06CD26A8FBF5C, - ]; - - let state_first = keccakf1600(zero_state).unwrap(); - let state_second = keccakf1600(state_first).unwrap(); - - assert_eq!(state_first, expected_state_first); - assert_eq!(state_second, expected_state_second); - } -} - -#[cfg(test)] -mod secp256k1_tests { - use super::verify_secp256k1_ecdsa_signature; - - // 0x3a73f4123a5cd2121f21cd7e8d358835476949d035d9c2da6806b4633ac8c1e2, - const HASHED_MESSAGE: [u8; 32] = [ - 0x3a, 0x73, 0xf4, 0x12, 0x3a, 0x5c, 0xd2, 0x12, 0x1f, 0x21, 0xcd, 0x7e, 0x8d, 0x35, 0x88, - 0x35, 0x47, 0x69, 0x49, 0xd0, 0x35, 0xd9, 0xc2, 0xda, 0x68, 0x06, 0xb4, 0x63, 0x3a, 0xc8, - 0xc1, 0xe2, - ]; - // 0xa0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7 - const PUB_KEY_X: [u8; 32] = [ - 0xa0, 0x43, 0x4d, 0x9e, 0x47, 0xf3, 0xc8, 0x62, 0x35, 0x47, 0x7c, 0x7b, 0x1a, 0xe6, 0xae, - 0x5d, 0x34, 0x42, 0xd4, 0x9b, 0x19, 0x43, 0xc2, 0xb7, 0x52, 0xa6, 0x8e, 0x2a, 0x47, 0xe2, - 0x47, 0xc7, - ]; - // 0x893aba425419bc27a3b6c7e693a24c696f794c2ed877a1593cbee53b037368d7 - const PUB_KEY_Y: [u8; 32] = [ - 0x89, 0x3a, 0xba, 0x42, 0x54, 0x19, 0xbc, 0x27, 0xa3, 0xb6, 0xc7, 0xe6, 0x93, 0xa2, 0x4c, - 0x69, 0x6f, 0x79, 0x4c, 0x2e, 0xd8, 0x77, 0xa1, 0x59, 0x3c, 0xbe, 0xe5, 0x3b, 0x03, 0x73, - 0x68, 0xd7, - ]; - // 0xe5081c80ab427dc370346f4a0e31aa2bad8d9798c38061db9ae55a4e8df454fd28119894344e71b78770cc931d61f480ecbb0b89d6eb69690161e49a715fcd55 - const SIGNATURE: [u8; 64] = [ - 0xe5, 0x08, 0x1c, 0x80, 0xab, 0x42, 0x7d, 0xc3, 0x70, 0x34, 0x6f, 0x4a, 0x0e, 0x31, 0xaa, - 0x2b, 0xad, 0x8d, 0x97, 0x98, 0xc3, 0x80, 0x61, 0xdb, 0x9a, 0xe5, 0x5a, 0x4e, 0x8d, 0xf4, - 0x54, 0xfd, 0x28, 0x11, 0x98, 0x94, 0x34, 0x4e, 0x71, 0xb7, 0x87, 0x70, 0xcc, 0x93, 0x1d, - 0x61, 0xf4, 0x80, 0xec, 0xbb, 0x0b, 0x89, 0xd6, 0xeb, 0x69, 0x69, 0x01, 0x61, 0xe4, 0x9a, - 0x71, 0x5f, 0xcd, 0x55, - ]; - - #[test] - fn verifies_valid_signature_with_low_s_value() { - let valid = - verify_secp256k1_ecdsa_signature(&HASHED_MESSAGE, &PUB_KEY_X, &PUB_KEY_Y, &SIGNATURE); - - assert!(valid); - } - - #[test] - fn rejects_invalid_signature() { - // This signature is invalid as ECDSA specifies that `r` and `s` must be non-zero. - let invalid_signature: [u8; 64] = [0x00; 64]; - - let valid = verify_secp256k1_ecdsa_signature( - &HASHED_MESSAGE, - &PUB_KEY_X, - &PUB_KEY_Y, - &invalid_signature, - ); - assert!(!valid); - } - - #[test] - fn rejects_invalid_public_key() { - let invalid_pub_key_x: [u8; 32] = [0xff; 32]; - let invalid_pub_key_y: [u8; 32] = [0xff; 32]; - - let valid = verify_secp256k1_ecdsa_signature( - &HASHED_MESSAGE, - &invalid_pub_key_x, - &invalid_pub_key_y, - &SIGNATURE, - ); - - assert!(!valid); - } - - #[test] - #[ignore = "ECDSA verification does not currently handle long hashes correctly"] - fn trims_overly_long_hashes_to_correct_length() { - let mut long_hashed_message = HASHED_MESSAGE.to_vec(); - long_hashed_message.push(0xff); - - let valid = verify_secp256k1_ecdsa_signature( - &long_hashed_message, - &PUB_KEY_X, - &PUB_KEY_Y, - &SIGNATURE, - ); - - assert!(valid); - } -} - -#[cfg(test)] -mod secp256r1_tests { - use super::verify_secp256r1_ecdsa_signature; - - // 0x54705ba3baafdbdfba8c5f9a70f7a89bee98d906b53e31074da7baecdc0da9ad - const HASHED_MESSAGE: [u8; 32] = [ - 84, 112, 91, 163, 186, 175, 219, 223, 186, 140, 95, 154, 112, 247, 168, 155, 238, 152, 217, - 6, 181, 62, 49, 7, 77, 167, 186, 236, 220, 13, 169, 173, - ]; - // 0x550f471003f3df97c3df506ac797f6721fb1a1fb7b8f6f83d224498a65c88e24 - const PUB_KEY_X: [u8; 32] = [ - 85, 15, 71, 16, 3, 243, 223, 151, 195, 223, 80, 106, 199, 151, 246, 114, 31, 177, 161, 251, - 123, 143, 111, 131, 210, 36, 73, 138, 101, 200, 142, 36, - ]; - // 0x136093d7012e509a73715cbd0b00a3cc0ff4b5c01b3ffa196ab1fb327036b8e6 - const PUB_KEY_Y: [u8; 32] = [ - 19, 96, 147, 215, 1, 46, 80, 154, 115, 113, 92, 189, 11, 0, 163, 204, 15, 244, 181, 192, - 27, 63, 250, 25, 106, 177, 251, 50, 112, 54, 184, 230, - ]; - // 0x2c70a8d084b62bfc5ce03641caf9f72ad4da8c81bfe6ec9487bb5e1bef62a13218ad9ee29eaf351fdc50f1520c425e9b908a07278b43b0ec7b872778c14e0784 - const SIGNATURE: [u8; 64] = [ - 44, 112, 168, 208, 132, 182, 43, 252, 92, 224, 54, 65, 202, 249, 247, 42, 212, 218, 140, - 129, 191, 230, 236, 148, 135, 187, 94, 27, 239, 98, 161, 50, 24, 173, 158, 226, 158, 175, - 53, 31, 220, 80, 241, 82, 12, 66, 94, 155, 144, 138, 7, 39, 139, 67, 176, 236, 123, 135, - 39, 120, 193, 78, 7, 132, - ]; - - #[test] - fn verifies_valid_signature_with_low_s_value() { - let valid = - verify_secp256r1_ecdsa_signature(&HASHED_MESSAGE, &PUB_KEY_X, &PUB_KEY_Y, &SIGNATURE); - - assert!(valid); - } - - #[test] - fn rejects_invalid_signature() { - // This signature is invalid as ECDSA specifies that `r` and `s` must be non-zero. - let invalid_signature: [u8; 64] = [0x00; 64]; - - let valid = verify_secp256r1_ecdsa_signature( - &HASHED_MESSAGE, - &PUB_KEY_X, - &PUB_KEY_Y, - &invalid_signature, - ); - assert!(!valid); - } - - #[test] - fn rejects_invalid_public_key() { - let invalid_pub_key_x: [u8; 32] = [0xff; 32]; - let invalid_pub_key_y: [u8; 32] = [0xff; 32]; - - let valid = verify_secp256r1_ecdsa_signature( - &HASHED_MESSAGE, - &invalid_pub_key_x, - &invalid_pub_key_y, - &SIGNATURE, - ); - - assert!(!valid); - } - - #[test] - #[ignore = "ECDSA verification does not currently handle long hashes correctly"] - fn trims_overly_long_hashes_to_correct_length() { - let mut long_hashed_message = HASHED_MESSAGE.to_vec(); - long_hashed_message.push(0xff); - - let valid = verify_secp256r1_ecdsa_signature( - &long_hashed_message, - &PUB_KEY_X, - &PUB_KEY_Y, - &SIGNATURE, - ); - - assert!(valid); - } -} diff --git a/acvm-repo/bn254_blackbox_solver/Cargo.toml b/acvm-repo/bn254_blackbox_solver/Cargo.toml index ea601a6b80f..132dddd50e5 100644 --- a/acvm-repo/bn254_blackbox_solver/Cargo.toml +++ b/acvm-repo/bn254_blackbox_solver/Cargo.toml @@ -2,7 +2,7 @@ name = "bn254_blackbox_solver" description = "Solvers for black box functions which are specific for the bn254 curve" # x-release-please-start-version -version = "0.39.0" +version = "0.46.0" # x-release-please-end authors.workspace = true edition.workspace = true @@ -15,43 +15,27 @@ repository.workspace = true [dependencies] acir.workspace = true acvm_blackbox_solver.workspace = true -thiserror.workspace = true -num-traits.workspace = true +hex.workspace = true +lazy_static = "1.4" -rust-embed = { version = "6.6.0", features = [ - "debug-embed", - "interpolate-folder-path", - "include-exclude", -] } - -grumpkin = { version = "0.1.0", package = "noir_grumpkin", features = [ - "std", -] } # BN254 fixed base scalar multiplication solver +# BN254 fixed base scalar multiplication solver +grumpkin = { version = "0.1.0", package = "noir_grumpkin", features = ["std"] } ark-ec = { version = "^0.4.0", default-features = false } ark-ff = { version = "^0.4.0", default-features = false } num-bigint.workspace = true -[target.'cfg(target_arch = "wasm32")'.dependencies] -wasmer = { version = "4.2.3", default-features = false, features = [ - "js-default", +[dev-dependencies] +ark-std = { version = "^0.4.0", default-features = false } +criterion = "0.5.0" +pprof = { version = "0.12", features = [ + "flamegraph", + "frame-pointer", + "criterion", ] } -getrandom = { workspace = true, features = ["js"] } -wasm-bindgen-futures.workspace = true -js-sys.workspace = true - -[target.'cfg(not(target_arch = "wasm32"))'.dependencies] -getrandom.workspace = true -wasmer = "4.2.3" - -[build-dependencies] -pkg-config = "0.3" -tar = "~0.4.15" -flate2 = "~1.0.1" -reqwest = { version = "0.11.20", default-features = false, features = [ - "rustls-tls", - "blocking", -] } +[[bench]] +name = "criterion" +harness = false [features] default = ["bn254"] diff --git a/acvm-repo/bn254_blackbox_solver/benches/criterion.rs b/acvm-repo/bn254_blackbox_solver/benches/criterion.rs new file mode 100644 index 00000000000..cbcb75a3291 --- /dev/null +++ b/acvm-repo/bn254_blackbox_solver/benches/criterion.rs @@ -0,0 +1,68 @@ +use criterion::{criterion_group, criterion_main, Criterion}; +use std::{hint::black_box, time::Duration}; + +use acir::{AcirField, FieldElement}; +use acvm_blackbox_solver::BlackBoxFunctionSolver; +use bn254_blackbox_solver::{poseidon2_permutation, Bn254BlackBoxSolver}; + +use pprof::criterion::{Output, PProfProfiler}; + +fn bench_poseidon2(c: &mut Criterion) { + let inputs = [FieldElement::zero(); 4]; + + c.bench_function("poseidon2", |b| b.iter(|| poseidon2_permutation(black_box(&inputs), 4))); +} + +fn bench_pedersen_commitment(c: &mut Criterion) { + let inputs = [FieldElement::one(); 2]; + + c.bench_function("pedersen_commitment", |b| { + b.iter(|| Bn254BlackBoxSolver.pedersen_commitment(black_box(&inputs), 0)) + }); +} + +fn bench_pedersen_hash(c: &mut Criterion) { + let inputs = [FieldElement::one(); 2]; + + c.bench_function("pedersen_hash", |b| { + b.iter(|| Bn254BlackBoxSolver.pedersen_hash(black_box(&inputs), 0)) + }); +} + +fn bench_schnorr_verify(c: &mut Criterion) { + let pub_key_x = FieldElement::from_hex( + "0x04b260954662e97f00cab9adb773a259097f7a274b83b113532bce27fa3fb96a", + ) + .unwrap(); + let pub_key_y = FieldElement::from_hex( + "0x2fd51571db6c08666b0edfbfbc57d432068bccd0110a39b166ab243da0037197", + ) + .unwrap(); + let sig_bytes: [u8; 64] = [ + 1, 13, 119, 112, 212, 39, 233, 41, 84, 235, 255, 93, 245, 172, 186, 83, 157, 253, 76, 77, + 33, 128, 178, 15, 214, 67, 105, 107, 177, 234, 77, 48, 27, 237, 155, 84, 39, 84, 247, 27, + 22, 8, 176, 230, 24, 115, 145, 220, 254, 122, 135, 179, 171, 4, 214, 202, 64, 199, 19, 84, + 239, 138, 124, 12, + ]; + + let message: &[u8] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; + + c.bench_function("schnorr_verify", |b| { + b.iter(|| { + Bn254BlackBoxSolver.schnorr_verify( + black_box(&pub_key_x), + black_box(&pub_key_y), + black_box(&sig_bytes), + black_box(message), + ) + }) + }); +} + +criterion_group!( + name = benches; + config = Criterion::default().sample_size(40).measurement_time(Duration::from_secs(20)).with_profiler(PProfProfiler::new(100, Output::Flamegraph(None))); + targets = bench_poseidon2, bench_pedersen_commitment, bench_pedersen_hash, bench_schnorr_verify +); + +criterion_main!(benches); diff --git a/acvm-repo/bn254_blackbox_solver/build.rs b/acvm-repo/bn254_blackbox_solver/build.rs deleted file mode 100644 index 4269c86aba0..00000000000 --- a/acvm-repo/bn254_blackbox_solver/build.rs +++ /dev/null @@ -1,14 +0,0 @@ -use std::path::PathBuf; - -const BARRETENBERG_BIN_DIR: &str = "BARRETENBERG_BIN_DIR"; - -fn main() -> Result<(), String> { - let out_dir = std::env::var("OUT_DIR").unwrap(); - - let dest_path = PathBuf::from(out_dir.clone()).join("acvm_backend.wasm"); - - println!("cargo:rustc-env={BARRETENBERG_BIN_DIR}={out_dir}"); - std::fs::copy("./src/acvm_backend.wasm", dest_path).unwrap(); - - Ok(()) -} diff --git a/acvm-repo/bn254_blackbox_solver/src/acvm_backend.wasm b/acvm-repo/bn254_blackbox_solver/src/acvm_backend.wasm deleted file mode 100755 index bcf3bbf27ee..00000000000 Binary files a/acvm-repo/bn254_blackbox_solver/src/acvm_backend.wasm and /dev/null differ diff --git a/acvm-repo/bn254_blackbox_solver/src/embedded_curve_ops.rs b/acvm-repo/bn254_blackbox_solver/src/embedded_curve_ops.rs new file mode 100644 index 00000000000..148accd8b23 --- /dev/null +++ b/acvm-repo/bn254_blackbox_solver/src/embedded_curve_ops.rs @@ -0,0 +1,270 @@ +// TODO(https://github.com/noir-lang/noir/issues/4932): rename this file to something more generic +use ark_ec::AffineRepr; +use ark_ff::MontConfig; +use num_bigint::BigUint; + +use acir::BlackBoxFunc; +use acir::{AcirField, FieldElement}; + +use crate::BlackBoxResolutionError; + +/// Performs multi scalar multiplication of points with scalars. +pub fn multi_scalar_mul( + points: &[FieldElement], + scalars_lo: &[FieldElement], + scalars_hi: &[FieldElement], +) -> Result<(FieldElement, FieldElement, FieldElement), BlackBoxResolutionError> { + if points.len() != 3 * scalars_lo.len() || scalars_lo.len() != scalars_hi.len() { + dbg!(&points.len(), &scalars_lo.len(), &scalars_hi.len()); + return Err(BlackBoxResolutionError::Failed( + BlackBoxFunc::MultiScalarMul, + "Points and scalars must have the same length".to_string(), + )); + } + + let mut output_point = grumpkin::SWAffine::zero(); + + for i in (0..points.len()).step_by(3) { + let point = + create_point(points[i], points[i + 1], points[i + 2] == FieldElement::from(1_u128)) + .map_err(|e| BlackBoxResolutionError::Failed(BlackBoxFunc::MultiScalarMul, e))?; + + let scalar_low: u128 = scalars_lo[i / 3].try_into_u128().ok_or_else(|| { + BlackBoxResolutionError::Failed( + BlackBoxFunc::MultiScalarMul, + format!("Limb {} is not less than 2^128", scalars_lo[i].to_hex()), + ) + })?; + + let scalar_high: u128 = scalars_hi[i / 3].try_into_u128().ok_or_else(|| { + BlackBoxResolutionError::Failed( + BlackBoxFunc::MultiScalarMul, + format!("Limb {} is not less than 2^128", scalars_hi[i].to_hex()), + ) + })?; + + let mut bytes = scalar_high.to_be_bytes().to_vec(); + bytes.extend_from_slice(&scalar_low.to_be_bytes()); + + // Check if this is smaller than the grumpkin modulus + let grumpkin_integer = BigUint::from_bytes_be(&bytes); + + if grumpkin_integer >= grumpkin::FrConfig::MODULUS.into() { + return Err(BlackBoxResolutionError::Failed( + BlackBoxFunc::MultiScalarMul, + format!("{} is not a valid grumpkin scalar", grumpkin_integer.to_str_radix(16)), + )); + } + + let iteration_output_point = + grumpkin::SWAffine::from(point.mul_bigint(grumpkin_integer.to_u64_digits())); + + output_point = grumpkin::SWAffine::from(output_point + iteration_output_point); + } + + if let Some((out_x, out_y)) = output_point.xy() { + Ok(( + FieldElement::from_repr(*out_x), + FieldElement::from_repr(*out_y), + FieldElement::from(output_point.is_zero() as u128), + )) + } else { + Ok((FieldElement::from(0_u128), FieldElement::from(0_u128), FieldElement::from(1_u128))) + } +} + +pub fn embedded_curve_add( + input1: [FieldElement; 3], + input2: [FieldElement; 3], +) -> Result<(FieldElement, FieldElement, FieldElement), BlackBoxResolutionError> { + let point1 = create_point(input1[0], input1[1], input1[2] == FieldElement::one()) + .map_err(|e| BlackBoxResolutionError::Failed(BlackBoxFunc::EmbeddedCurveAdd, e))?; + let point2 = create_point(input2[0], input2[1], input2[2] == FieldElement::one()) + .map_err(|e| BlackBoxResolutionError::Failed(BlackBoxFunc::EmbeddedCurveAdd, e))?; + let res = grumpkin::SWAffine::from(point1 + point2); + if let Some((res_x, res_y)) = res.xy() { + Ok(( + FieldElement::from_repr(*res_x), + FieldElement::from_repr(*res_y), + FieldElement::from(res.is_zero() as u128), + )) + } else if res.is_zero() { + Ok((FieldElement::from(0_u128), FieldElement::from(0_u128), FieldElement::from(1_u128))) + } else { + Err(BlackBoxResolutionError::Failed( + BlackBoxFunc::EmbeddedCurveAdd, + "Point is not on curve".to_string(), + )) + } +} + +fn create_point( + x: FieldElement, + y: FieldElement, + is_infinite: bool, +) -> Result { + if is_infinite { + return Ok(grumpkin::SWAffine::zero()); + } + let point = grumpkin::SWAffine::new_unchecked(x.into_repr(), y.into_repr()); + if !point.is_on_curve() { + return Err(format!("Point ({}, {}) is not on curve", x.to_hex(), y.to_hex())); + }; + if !point.is_in_correct_subgroup_assuming_on_curve() { + return Err(format!("Point ({}, {}) is not in correct subgroup", x.to_hex(), y.to_hex())); + }; + Ok(point) +} + +#[cfg(test)] +mod tests { + use super::*; + + use ark_ff::BigInteger; + + fn get_generator() -> [FieldElement; 3] { + let generator = grumpkin::SWAffine::generator(); + let generator_x = FieldElement::from_repr(*generator.x().unwrap()); + let generator_y = FieldElement::from_repr(*generator.y().unwrap()); + [generator_x, generator_y, FieldElement::zero()] + } + + #[test] + fn smoke_test() -> Result<(), BlackBoxResolutionError> { + // We check that multiplying 1 by generator results in the generator + let generator = get_generator(); + + let res = multi_scalar_mul(&generator, &[FieldElement::one()], &[FieldElement::zero()])?; + + assert_eq!(generator[0], res.0); + assert_eq!(generator[1], res.1); + Ok(()) + } + + #[test] + fn low_high_smoke_test() -> Result<(), BlackBoxResolutionError> { + let points = get_generator(); + let scalars_lo = [FieldElement::one()]; + let scalars_hi = [FieldElement::from(2u128)]; + + let res = multi_scalar_mul(&points, &scalars_lo, &scalars_hi)?; + let x = "0702ab9c7038eeecc179b4f209991bcb68c7cb05bf4c532d804ccac36199c9a9"; + let y = "23f10e9e43a3ae8d75d24154e796aae12ae7af546716e8f81a2564f1b5814130"; + + assert_eq!(x, res.0.to_hex()); + assert_eq!(y, res.1.to_hex()); + Ok(()) + } + + #[test] + fn rejects_invalid_scalar_limbs() { + let points = get_generator(); + + let max_limb = FieldElement::from(u128::MAX); + let invalid_limb = max_limb + FieldElement::one(); + + let expected_error = Err(BlackBoxResolutionError::Failed( + BlackBoxFunc::MultiScalarMul, + "Limb 0000000000000000000000000000000100000000000000000000000000000000 is not less than 2^128".into(), + )); + + let res = multi_scalar_mul(&points, &[FieldElement::one()], &[invalid_limb]); + assert_eq!(res, expected_error); + + let res = multi_scalar_mul(&points, &[invalid_limb], &[FieldElement::one()]); + assert_eq!(res, expected_error); + } + + #[test] + fn rejects_grumpkin_modulus() { + let x = grumpkin::FrConfig::MODULUS.to_bytes_be(); + + let low = FieldElement::from_be_bytes_reduce(&x[16..32]); + let high = FieldElement::from_be_bytes_reduce(&x[0..16]); + + let res = multi_scalar_mul(&get_generator(), &[low], &[high]); + + assert_eq!( + res, + Err(BlackBoxResolutionError::Failed( + BlackBoxFunc::MultiScalarMul, + "30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 is not a valid grumpkin scalar".into(), + )) + ); + } + + #[test] + fn rejects_invalid_point() { + let invalid_point_x = FieldElement::one(); + let invalid_point_y = FieldElement::one(); + let valid_scalar_low = FieldElement::zero(); + let valid_scalar_high = FieldElement::zero(); + + let res = multi_scalar_mul( + &[invalid_point_x, invalid_point_y, FieldElement::zero()], + &[valid_scalar_low], + &[valid_scalar_high], + ); + + assert_eq!( + res, + Err(BlackBoxResolutionError::Failed( + BlackBoxFunc::MultiScalarMul, + "Point (0000000000000000000000000000000000000000000000000000000000000001, 0000000000000000000000000000000000000000000000000000000000000001) is not on curve".into(), + )) + ); + } + + #[test] + fn throws_on_args_length_mismatch() { + let points = get_generator(); + let scalars_lo = [FieldElement::from(2u128)]; + let scalars_hi = []; + + let res = multi_scalar_mul(&points, &scalars_lo, &scalars_hi); + + assert_eq!( + res, + Err(BlackBoxResolutionError::Failed( + BlackBoxFunc::MultiScalarMul, + "Points and scalars must have the same length".into(), + )) + ); + } + + #[test] + fn rejects_addition_of_points_not_in_curve() { + let x = FieldElement::from(1u128); + let y = FieldElement::from(2u128); + + let res = embedded_curve_add( + [x, y, FieldElement::from(0u128)], + [x, y, FieldElement::from(0u128)], + ); + + assert_eq!( + res, + Err(BlackBoxResolutionError::Failed( + BlackBoxFunc::EmbeddedCurveAdd, + "Point (0000000000000000000000000000000000000000000000000000000000000001, 0000000000000000000000000000000000000000000000000000000000000002) is not on curve".into(), + )) + ); + } + + #[test] + fn output_of_msm_matches_add() -> Result<(), BlackBoxResolutionError> { + let points = get_generator(); + let scalars_lo = [FieldElement::from(2u128)]; + let scalars_hi = [FieldElement::zero()]; + + let msm_res = multi_scalar_mul(&points, &scalars_lo, &scalars_hi)?; + let add_res = embedded_curve_add( + [points[0], points[1], FieldElement::from(0u128)], + [points[0], points[1], FieldElement::from(0u128)], + )?; + + assert_eq!(msm_res.0, add_res.0); + assert_eq!(msm_res.1, add_res.1); + Ok(()) + } +} diff --git a/acvm-repo/bn254_blackbox_solver/src/fixed_base_scalar_mul.rs b/acvm-repo/bn254_blackbox_solver/src/fixed_base_scalar_mul.rs deleted file mode 100644 index 5e68c7d4030..00000000000 --- a/acvm-repo/bn254_blackbox_solver/src/fixed_base_scalar_mul.rs +++ /dev/null @@ -1,135 +0,0 @@ -use ark_ec::AffineRepr; -use ark_ff::MontConfig; -use num_bigint::BigUint; - -use acir::{BlackBoxFunc, FieldElement}; - -use crate::BlackBoxResolutionError; - -pub fn fixed_base_scalar_mul( - low: &FieldElement, - high: &FieldElement, -) -> Result<(FieldElement, FieldElement), BlackBoxResolutionError> { - let low: u128 = low.try_into_u128().ok_or_else(|| { - BlackBoxResolutionError::Failed( - BlackBoxFunc::FixedBaseScalarMul, - format!("Limb {} is not less than 2^128", low.to_hex()), - ) - })?; - - let high: u128 = high.try_into_u128().ok_or_else(|| { - BlackBoxResolutionError::Failed( - BlackBoxFunc::FixedBaseScalarMul, - format!("Limb {} is not less than 2^128", high.to_hex()), - ) - })?; - - let mut bytes = high.to_be_bytes().to_vec(); - bytes.extend_from_slice(&low.to_be_bytes()); - - // Check if this is smaller than the grumpkin modulus - let grumpkin_integer = BigUint::from_bytes_be(&bytes); - - if grumpkin_integer >= grumpkin::FrConfig::MODULUS.into() { - return Err(BlackBoxResolutionError::Failed( - BlackBoxFunc::FixedBaseScalarMul, - format!("{} is not a valid grumpkin scalar", grumpkin_integer.to_str_radix(16)), - )); - } - - let result = grumpkin::SWAffine::from( - grumpkin::SWAffine::generator().mul_bigint(grumpkin_integer.to_u64_digits()), - ); - if let Some((res_x, res_y)) = result.xy() { - Ok((FieldElement::from_repr(*res_x), FieldElement::from_repr(*res_y))) - } else { - Ok((FieldElement::zero(), FieldElement::zero())) - } -} - -pub fn embedded_curve_add( - input1_x: FieldElement, - input1_y: FieldElement, - input2_x: FieldElement, - input2_y: FieldElement, -) -> Result<(FieldElement, FieldElement), BlackBoxResolutionError> { - let mut point1 = grumpkin::SWAffine::new(input1_x.into_repr(), input1_y.into_repr()); - let point2 = grumpkin::SWAffine::new(input2_x.into_repr(), input2_y.into_repr()); - let res = point1 + point2; - point1 = res.into(); - if let Some((res_x, res_y)) = point1.xy() { - Ok((FieldElement::from_repr(*res_x), FieldElement::from_repr(*res_y))) - } else { - Err(BlackBoxResolutionError::Failed( - BlackBoxFunc::EmbeddedCurveAdd, - "Point is not on curve".to_string(), - )) - } -} - -#[cfg(test)] -mod grumpkin_fixed_base_scalar_mul { - use ark_ff::BigInteger; - - use super::*; - #[test] - fn smoke_test() -> Result<(), BlackBoxResolutionError> { - let input = FieldElement::one(); - - let res = fixed_base_scalar_mul(&input, &FieldElement::zero())?; - let x = "0000000000000000000000000000000000000000000000000000000000000001"; - let y = "0000000000000002cf135e7506a45d632d270d45f1181294833fc48d823f272c"; - - assert_eq!(x, res.0.to_hex()); - assert_eq!(y, res.1.to_hex()); - Ok(()) - } - #[test] - fn low_high_smoke_test() -> Result<(), BlackBoxResolutionError> { - let low = FieldElement::one(); - let high = FieldElement::from(2u128); - - let res = fixed_base_scalar_mul(&low, &high)?; - let x = "0702ab9c7038eeecc179b4f209991bcb68c7cb05bf4c532d804ccac36199c9a9"; - let y = "23f10e9e43a3ae8d75d24154e796aae12ae7af546716e8f81a2564f1b5814130"; - - assert_eq!(x, res.0.to_hex()); - assert_eq!(y, res.1.to_hex()); - Ok(()) - } - - #[test] - fn rejects_invalid_limbs() { - let max_limb = FieldElement::from(u128::MAX); - let invalid_limb = max_limb + FieldElement::one(); - - let expected_error = Err(BlackBoxResolutionError::Failed( - BlackBoxFunc::FixedBaseScalarMul, - "Limb 0000000000000000000000000000000100000000000000000000000000000000 is not less than 2^128".into() - )); - - let res = fixed_base_scalar_mul(&invalid_limb, &FieldElement::zero()); - assert_eq!(res, expected_error); - - let res = fixed_base_scalar_mul(&FieldElement::zero(), &invalid_limb); - assert_eq!(res, expected_error); - } - - #[test] - fn rejects_grumpkin_modulus() { - let x = grumpkin::FrConfig::MODULUS.to_bytes_be(); - - let high = FieldElement::from_be_bytes_reduce(&x[0..16]); - let low = FieldElement::from_be_bytes_reduce(&x[16..32]); - - let res = fixed_base_scalar_mul(&low, &high); - - assert_eq!( - res, - Err(BlackBoxResolutionError::Failed( - BlackBoxFunc::FixedBaseScalarMul, - "30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 is not a valid grumpkin scalar".into() - )) - ); - } -} diff --git a/acvm-repo/bn254_blackbox_solver/src/generator/generators.rs b/acvm-repo/bn254_blackbox_solver/src/generator/generators.rs new file mode 100644 index 00000000000..f89d582d167 --- /dev/null +++ b/acvm-repo/bn254_blackbox_solver/src/generator/generators.rs @@ -0,0 +1,184 @@ +// Adapted from https://github.com/laudiacay/barustenberg/blob/df6bc6f095fe7f288bf6a12e7317fd8eb33d68ae/barustenberg/src/ecc/groups/affine_element.rshttps://github.com/laudiacay/barustenberg/blob/df6bc6f095fe7f288bf6a12e7317fd8eb33d68ae/barustenberg/src/ecc/groups/group.rs +//! +//! Code is used under the MIT license + +use std::sync::OnceLock; + +use ark_ec::short_weierstrass::Affine; + +use acvm_blackbox_solver::blake3; +use grumpkin::GrumpkinParameters; + +use super::hash_to_curve::hash_to_curve; + +pub(crate) const DEFAULT_DOMAIN_SEPARATOR: &[u8] = "DEFAULT_DOMAIN_SEPARATOR".as_bytes(); +const NUM_DEFAULT_GENERATORS: usize = 8; + +fn default_generators() -> &'static [Affine; NUM_DEFAULT_GENERATORS] { + static INSTANCE: OnceLock<[Affine; NUM_DEFAULT_GENERATORS]> = + OnceLock::new(); + INSTANCE.get_or_init(|| { + _derive_generators(DEFAULT_DOMAIN_SEPARATOR, NUM_DEFAULT_GENERATORS as u32, 0) + .try_into() + .expect("Should generate `NUM_DEFAULT_GENERATORS`") + }) +} + +/// Derives generator points via [hash-to-curve][hash_to_curve]. +/// +/// # ALGORITHM DESCRIPTION +/// +/// 1. Each generator has an associated "generator index" described by its location in the vector +/// 2. a 64-byte preimage buffer is generated with the following structure: +/// - bytes 0-31: BLAKE3 hash of domain_separator +/// - bytes 32-63: generator index in big-endian form +/// 3. The [hash-to-curve algorithm][hash_to_curve] is used to hash the above into a curve point. +/// +/// NOTE: The domain separator is included to ensure that it is possible to derive independent sets of +/// index-addressable generators. +/// +/// [hash_to_curve]: super::hash_to_curve::hash_to_curve +pub(crate) fn derive_generators( + domain_separator_bytes: &[u8], + num_generators: u32, + starting_index: u32, +) -> Vec> { + // We cache a small number of the default generators so we can reuse them without needing to repeatedly recalculate them. + if domain_separator_bytes == DEFAULT_DOMAIN_SEPARATOR + && starting_index + num_generators <= NUM_DEFAULT_GENERATORS as u32 + { + let start_index = starting_index as usize; + let end_index = (starting_index + num_generators) as usize; + default_generators()[start_index..end_index].to_vec() + } else { + _derive_generators(domain_separator_bytes, num_generators, starting_index) + } +} + +fn _derive_generators( + domain_separator_bytes: &[u8], + num_generators: u32, + starting_index: u32, +) -> Vec> { + let mut generator_preimage = [0u8; 64]; + let domain_hash = blake3(domain_separator_bytes).expect("hash should succeed"); + //1st 32 bytes are blake3 domain_hash + generator_preimage[..32].copy_from_slice(&domain_hash); + + // Convert generator index in big-endian form + let mut res = Vec::with_capacity(num_generators as usize); + for i in starting_index..(starting_index + num_generators) { + let generator_be_bytes: [u8; 4] = i.to_be_bytes(); + generator_preimage[32] = generator_be_bytes[0]; + generator_preimage[33] = generator_be_bytes[1]; + generator_preimage[34] = generator_be_bytes[2]; + generator_preimage[35] = generator_be_bytes[3]; + let generator = hash_to_curve(&generator_preimage, 0); + res.push(generator); + } + res +} + +#[cfg(test)] +mod test { + + use ark_ec::AffineRepr; + use ark_ff::{BigInteger, PrimeField}; + + use super::*; + + #[test] + fn test_derive_generators() { + let res = derive_generators("test domain".as_bytes(), 128, 0); + + let is_unique = |y: Affine, j: usize| -> bool { + for (i, res) in res.iter().enumerate() { + if i != j && *res == y { + return false; + } + } + true + }; + + for (i, res) in res.iter().enumerate() { + assert!(is_unique(*res, i)); + assert!(res.is_on_curve()); + } + } + + #[test] + fn derive_length_generator() { + let domain_separator = "pedersen_hash_length"; + let length_generator = derive_generators(domain_separator.as_bytes(), 1, 0)[0]; + + let expected_generator = ( + "2df8b940e5890e4e1377e05373fae69a1d754f6935e6a780b666947431f2cdcd", + "2ecd88d15967bc53b885912e0d16866154acb6aac2d3f85e27ca7eefb2c19083", + ); + assert_eq!( + hex::encode(length_generator.x().unwrap().into_bigint().to_bytes_be()), + expected_generator.0, + "Failed on x component" + ); + assert_eq!( + hex::encode(length_generator.y().unwrap().into_bigint().to_bytes_be()), + expected_generator.1, + "Failed on y component" + ); + } + + #[test] + fn derives_default_generators() { + const DEFAULT_GENERATORS: &[[&str; 2]] = &[ + [ + "083e7911d835097629f0067531fc15cafd79a89beecb39903f69572c636f4a5a", + "1a7f5efaad7f315c25a918f30cc8d7333fccab7ad7c90f14de81bcc528f9935d", + ], + [ + "054aa86a73cb8a34525e5bbed6e43ba1198e860f5f3950268f71df4591bde402", + "209dcfbf2cfb57f9f6046f44d71ac6faf87254afc7407c04eb621a6287cac126", + ], + [ + "1c44f2a5207c81c28a8321a5815ce8b1311024bbed131819bbdaf5a2ada84748", + "03aaee36e6422a1d0191632ac6599ae9eba5ac2c17a8c920aa3caf8b89c5f8a8", + ], + [ + "26d8b1160c6821a30c65f6cb47124afe01c29f4338f44d4a12c9fccf22fb6fb2", + "05c70c3b9c0d25a4c100e3a27bf3cc375f8af8cdd9498ec4089a823d7464caff", + ], + [ + "20ed9c6a1d27271c4498bfce0578d59db1adbeaa8734f7facc097b9b994fcf6e", + "29cd7d370938b358c62c4a00f73a0d10aba7e5aaa04704a0713f891ebeb92371", + ], + [ + "0224a8abc6c8b8d50373d64cd2a1ab1567bf372b3b1f7b861d7f01257052d383", + "2358629b90eafb299d6650a311e79914b0215eb0a790810b26da5a826726d711", + ], + [ + "0f106f6d46bc904a5290542490b2f238775ff3c445b2f8f704c466655f460a2a", + "29ab84d472f1d33f42fe09c47b8f7710f01920d6155250126731e486877bcf27", + ], + [ + "0298f2e42249f0519c8a8abd91567ebe016e480f219b8c19461d6a595cc33696", + "035bec4b8520a4ece27bd5aafabee3dfe1390d7439c419a8c55aceb207aac83b", + ], + ]; + + let generated_generators = + derive_generators(DEFAULT_DOMAIN_SEPARATOR, DEFAULT_GENERATORS.len() as u32, 0); + for (i, (generator, expected_generator)) in + generated_generators.iter().zip(DEFAULT_GENERATORS).enumerate() + { + assert_eq!( + hex::encode(generator.x().unwrap().into_bigint().to_bytes_be()), + expected_generator[0], + "Failed on x component of generator {i}" + ); + assert_eq!( + hex::encode(generator.y().unwrap().into_bigint().to_bytes_be()), + expected_generator[1], + "Failed on y component of generator {i}" + ); + } + } +} diff --git a/acvm-repo/bn254_blackbox_solver/src/generator/hash_to_curve.rs b/acvm-repo/bn254_blackbox_solver/src/generator/hash_to_curve.rs new file mode 100644 index 00000000000..c0197883442 --- /dev/null +++ b/acvm-repo/bn254_blackbox_solver/src/generator/hash_to_curve.rs @@ -0,0 +1,135 @@ +// Adapted from https://github.com/laudiacay/barustenberg/blob/df6bc6f095fe7f288bf6a12e7317fd8eb33d68ae/barustenberg/src/ecc/groups/affine_element.rs +//! +//! Code is used under the MIT license + +use acvm_blackbox_solver::blake3; + +use ark_ec::{short_weierstrass::Affine, AffineRepr, CurveConfig}; +use ark_ff::Field; +use ark_ff::{BigInteger, PrimeField}; +use grumpkin::GrumpkinParameters; + +/// Hash a seed buffer into a point +/// +/// # ALGORITHM DESCRIPTION +/// +/// 1. Initialize unsigned integer `attempt_count = 0` +/// 2. Copy seed into a buffer whose size is 2 bytes greater than `seed` (initialized to `0`) +/// 3. Interpret `attempt_count` as a byte and write into buffer at `[buffer.size() - 2]` +/// 4. Compute Blake3 hash of buffer +/// 5. Set the end byte of the buffer to `1` +/// 6. Compute Blake3 hash of buffer +/// 7. Interpret the two hash outputs as the high / low 256 bits of a 512-bit integer (big-endian) +/// 8. Derive x-coordinate of point by reducing the 512-bit integer modulo the curve's field modulus (Fq) +/// 9. Compute `y^2` from the curve formula `y^2 = x^3 + ax + b` (`a`, `b` are curve params. for BN254, `a = 0`, `b = 3`) +/// 10. IF `y^2` IS NOT A QUADRATIC RESIDUE: +/// +/// a. increment `attempt_count` by 1 and go to step 2 +/// +/// 11. IF `y^2` IS A QUADRATIC RESIDUE: +/// +/// a. derive y coordinate via `y = sqrt(y)` +/// +/// b. Interpret most significant bit of 512-bit integer as a 'parity' bit +/// +/// c. If parity bit is set AND `y`'s most significant bit is not set, invert `y` +/// +/// d. If parity bit is not set AND `y`'s most significant bit is set, invert `y` +/// +/// e. return (x, y) +/// +/// N.B. steps c. and e. are because the `sqrt()` algorithm can return 2 values, +/// we need to a way to canonically distinguish between these 2 values and select a "preferred" one +pub(crate) fn hash_to_curve(seed: &[u8], attempt_count: u8) -> Affine { + let seed_size = seed.len(); + // expand by 2 bytes to cover incremental hash attempts + let mut target_seed = seed.to_vec(); + target_seed.extend_from_slice(&[0u8; 2]); + + target_seed[seed_size] = attempt_count; + target_seed[seed_size + 1] = 0; + let hash_hi = blake3(&target_seed).expect("hash should succeed"); + target_seed[seed_size + 1] = 1; + let hash_lo = blake3(&target_seed).expect("hash should succeed"); + + let mut hash = hash_hi.to_vec(); + hash.extend_from_slice(&hash_lo); + + // Here we reduce the 512 bit number modulo the base field modulus to calculate `x` + let x = <::BaseField as Field>::BasePrimeField::from_be_bytes_mod_order(&hash); + let x = ::BaseField::from_base_prime_field(x); + + if let Some(point) = Affine::::get_point_from_x_unchecked(x, false) { + let parity_bit = hash_hi[0] > 127; + let y_bit_set = point.y().unwrap().into_bigint().get_bit(0); + if (parity_bit && !y_bit_set) || (!parity_bit && y_bit_set) { + -point + } else { + point + } + } else { + hash_to_curve(seed, attempt_count + 1) + } +} + +#[cfg(test)] +mod test { + + use ark_ec::AffineRepr; + use ark_ff::{BigInteger, PrimeField}; + + use super::hash_to_curve; + + #[test] + fn smoke_test() { + let test_cases: [(&[u8], u8, (&str, &str)); 4] = [ + ( + &[], + 0, + ( + "24c4cb9c1206ab5470592f237f1698abe684dadf0ab4d7a132c32b2134e2c12e", + "0668b8d61a317fb34ccad55c930b3554f1828a0e5530479ecab4defe6bbc0b2e", + ), + ), + ( + &[], + 1, + ( + "24c4cb9c1206ab5470592f237f1698abe684dadf0ab4d7a132c32b2134e2c12e", + "0668b8d61a317fb34ccad55c930b3554f1828a0e5530479ecab4defe6bbc0b2e", + ), + ), + ( + &[1], + 0, + ( + "107f1b633c6113f3222f39f6256f0546b41a4880918c86864b06471afb410454", + "050cd3823d0c01590b6a50adcc85d2ee4098668fd28805578aa05a423ea938c6", + ), + ), + ( + &[0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64], + 0, + ( + "037c5c229ae495f6e8d1b4bf7723fafb2b198b51e27602feb8a4d1053d685093", + "10cf9596c5b2515692d930efa2cf3817607e4796856a79f6af40c949b066969f", + ), + ), + ]; + + for (seed, attempt_count, expected_point) in test_cases { + let point = hash_to_curve(seed, attempt_count); + assert!(point.is_on_curve()); + assert_eq!( + hex::encode(point.x().unwrap().into_bigint().to_bytes_be()), + expected_point.0, + "Failed on x component with seed {seed:?}, attempt_count {attempt_count}" + ); + assert_eq!( + hex::encode(point.y().unwrap().into_bigint().to_bytes_be()), + expected_point.1, + "Failed on y component with seed {seed:?}, attempt_count {attempt_count}" + ); + } + } +} diff --git a/acvm-repo/bn254_blackbox_solver/src/generator/mod.rs b/acvm-repo/bn254_blackbox_solver/src/generator/mod.rs new file mode 100644 index 00000000000..0f62642516a --- /dev/null +++ b/acvm-repo/bn254_blackbox_solver/src/generator/mod.rs @@ -0,0 +1,8 @@ +//! This module is adapted from the [Barustenberg][barustenberg] Rust implementation of the Barretenberg library. +//! +//! Code is used under the MIT license +//! +//! [barustenberg]: https://github.com/laudiacay/barustenberg/blob/df6bc6f095fe7f288bf6a12e7317fd8eb33d68ae/ + +pub(crate) mod generators; +mod hash_to_curve; diff --git a/acvm-repo/bn254_blackbox_solver/src/lib.rs b/acvm-repo/bn254_blackbox_solver/src/lib.rs index be0e60ada96..e3cea1153be 100644 --- a/acvm-repo/bn254_blackbox_solver/src/lib.rs +++ b/acvm-repo/bn254_blackbox_solver/src/lib.rs @@ -2,62 +2,39 @@ #![warn(clippy::semicolon_if_nothing_returned)] #![cfg_attr(not(test), warn(unused_crate_dependencies, unused_extern_crates))] -use acir::{BlackBoxFunc, FieldElement}; +use acir::FieldElement; use acvm_blackbox_solver::{BlackBoxFunctionSolver, BlackBoxResolutionError}; -mod fixed_base_scalar_mul; +mod embedded_curve_ops; +mod generator; +mod pedersen; mod poseidon2; -mod wasm; +mod schnorr; -pub use fixed_base_scalar_mul::{embedded_curve_add, fixed_base_scalar_mul}; -use poseidon2::Poseidon2; -use wasm::Barretenberg; +use ark_ec::AffineRepr; +pub use embedded_curve_ops::{embedded_curve_add, multi_scalar_mul}; +pub use poseidon2::poseidon2_permutation; -use self::wasm::{Pedersen, SchnorrSig}; +#[derive(Default)] +pub struct Bn254BlackBoxSolver; -pub struct Bn254BlackBoxSolver { - blackbox_vendor: Barretenberg, -} - -impl Bn254BlackBoxSolver { - #[cfg(target_arch = "wasm32")] - pub async fn initialize() -> Bn254BlackBoxSolver { - let blackbox_vendor = Barretenberg::initialize().await; - Bn254BlackBoxSolver { blackbox_vendor } - } - - #[cfg(not(target_arch = "wasm32"))] - pub fn new() -> Bn254BlackBoxSolver { - let blackbox_vendor = Barretenberg::new(); - Bn254BlackBoxSolver { blackbox_vendor } - } -} - -#[cfg(not(target_arch = "wasm32"))] -impl Default for Bn254BlackBoxSolver { - fn default() -> Self { - Self::new() - } -} - -impl BlackBoxFunctionSolver for Bn254BlackBoxSolver { +impl BlackBoxFunctionSolver for Bn254BlackBoxSolver { fn schnorr_verify( &self, public_key_x: &FieldElement, public_key_y: &FieldElement, - signature: &[u8], + signature: &[u8; 64], message: &[u8], ) -> Result { - let pub_key_bytes: Vec = - public_key_x.to_be_bytes().iter().copied().chain(public_key_y.to_be_bytes()).collect(); - - let pub_key: [u8; 64] = pub_key_bytes.try_into().unwrap(); let sig_s: [u8; 32] = signature[0..32].try_into().unwrap(); let sig_e: [u8; 32] = signature[32..64].try_into().unwrap(); - - self.blackbox_vendor.verify_signature(pub_key, sig_s, sig_e, message).map_err(|err| { - BlackBoxResolutionError::Failed(BlackBoxFunc::SchnorrVerify, err.to_string()) - }) + Ok(schnorr::verify_signature( + public_key_x.into_repr(), + public_key_y.into_repr(), + sig_s, + sig_e, + message, + )) } fn pedersen_commitment( @@ -65,10 +42,13 @@ impl BlackBoxFunctionSolver for Bn254BlackBoxSolver { inputs: &[FieldElement], domain_separator: u32, ) -> Result<(FieldElement, FieldElement), BlackBoxResolutionError> { - #[allow(deprecated)] - self.blackbox_vendor.encrypt(inputs.to_vec(), domain_separator).map_err(|err| { - BlackBoxResolutionError::Failed(BlackBoxFunc::PedersenCommitment, err.to_string()) - }) + let inputs: Vec = inputs.iter().map(|input| input.into_repr()).collect(); + let result = pedersen::commitment::commit_native_with_index(&inputs, domain_separator); + let res_x = + FieldElement::from_repr(*result.x().expect("should not commit to point at infinity")); + let res_y = + FieldElement::from_repr(*result.y().expect("should not commit to point at infinity")); + Ok((res_x, res_y)) } fn pedersen_hash( @@ -76,28 +56,34 @@ impl BlackBoxFunctionSolver for Bn254BlackBoxSolver { inputs: &[FieldElement], domain_separator: u32, ) -> Result { - #[allow(deprecated)] - self.blackbox_vendor.hash(inputs.to_vec(), domain_separator).map_err(|err| { - BlackBoxResolutionError::Failed(BlackBoxFunc::PedersenCommitment, err.to_string()) - }) + let inputs: Vec = inputs.iter().map(|input| input.into_repr()).collect(); + let result = pedersen::hash::hash_with_index(&inputs, domain_separator); + let result = FieldElement::from_repr(result); + Ok(result) } - fn fixed_base_scalar_mul( + fn multi_scalar_mul( &self, - low: &FieldElement, - high: &FieldElement, - ) -> Result<(FieldElement, FieldElement), BlackBoxResolutionError> { - fixed_base_scalar_mul(low, high) + points: &[FieldElement], + scalars_lo: &[FieldElement], + scalars_hi: &[FieldElement], + ) -> Result<(FieldElement, FieldElement, FieldElement), BlackBoxResolutionError> { + multi_scalar_mul(points, scalars_lo, scalars_hi) } fn ec_add( &self, input1_x: &FieldElement, input1_y: &FieldElement, + input1_infinite: &FieldElement, input2_x: &FieldElement, input2_y: &FieldElement, - ) -> Result<(FieldElement, FieldElement), BlackBoxResolutionError> { - embedded_curve_add(*input1_x, *input1_y, *input2_x, *input2_y) + input2_infinite: &FieldElement, + ) -> Result<(FieldElement, FieldElement, FieldElement), BlackBoxResolutionError> { + embedded_curve_add( + [*input1_x, *input1_y, *input1_infinite], + [*input2_x, *input2_y, *input2_infinite], + ) } fn poseidon2_permutation( @@ -105,7 +91,6 @@ impl BlackBoxFunctionSolver for Bn254BlackBoxSolver { inputs: &[FieldElement], len: u32, ) -> Result, BlackBoxResolutionError> { - let poseidon = Poseidon2::new(); - poseidon.permutation(inputs, len) + poseidon2_permutation(inputs, len) } } diff --git a/acvm-repo/bn254_blackbox_solver/src/pedersen/commitment.rs b/acvm-repo/bn254_blackbox_solver/src/pedersen/commitment.rs new file mode 100644 index 00000000000..5ff2c269d8c --- /dev/null +++ b/acvm-repo/bn254_blackbox_solver/src/pedersen/commitment.rs @@ -0,0 +1,76 @@ +// Taken from: https://github.com/laudiacay/barustenberg/blob/df6bc6f095fe7f288bf6a12e7317fd8eb33d68ae/barustenberg/src/crypto/pedersen/pederson.rs + +use ark_ec::{short_weierstrass::Affine, AffineRepr, CurveGroup}; +use ark_ff::{MontConfig, PrimeField}; +use grumpkin::{Fq, FqConfig, Fr, FrConfig, GrumpkinParameters}; + +use crate::generator::generators::{derive_generators, DEFAULT_DOMAIN_SEPARATOR}; + +/// Given a vector of fields, generate a pedersen commitment using the indexed generators. +pub(crate) fn commit_native_with_index( + inputs: &[Fq], + starting_index: u32, +) -> Affine { + let generators = + derive_generators(DEFAULT_DOMAIN_SEPARATOR, inputs.len() as u32, starting_index); + + // As |F_r| > |F_q|, we can safely convert any `F_q` into an `F_r` uniquely. + assert!(FrConfig::MODULUS > FqConfig::MODULUS); + + inputs.iter().enumerate().fold(Affine::zero(), |mut acc, (i, input)| { + acc = (acc + (generators[i] * Fr::from_bigint(input.into_bigint()).unwrap()).into_affine()) + .into_affine(); + acc + }) +} + +#[cfg(test)] +mod test { + + use acir::{AcirField, FieldElement}; + use ark_ec::short_weierstrass::Affine; + use ark_std::{One, Zero}; + use grumpkin::Fq; + + use crate::pedersen::commitment::commit_native_with_index; + + #[test] + fn commitment() { + // https://github.com/AztecProtocol/aztec-packages/blob/72931bdb8202c34042cdfb8cee2ef44b75939879/barretenberg/cpp/src/barretenberg/crypto/pedersen_commitment/pedersen.test.cpp#L10-L18 + let res = commit_native_with_index(&[Fq::one(), Fq::one()], 0); + let expected = Affine::new( + FieldElement::from_hex( + "0x2f7a8f9a6c96926682205fb73ee43215bf13523c19d7afe36f12760266cdfe15", + ) + .unwrap() + .into_repr(), + FieldElement::from_hex( + "0x01916b316adbbf0e10e39b18c1d24b33ec84b46daddf72f43878bcc92b6057e6", + ) + .unwrap() + .into_repr(), + ); + + assert_eq!(res, expected); + } + + #[test] + fn commitment_with_zero() { + // https://github.com/AztecProtocol/aztec-packages/blob/72931bdb8202c34042cdfb8cee2ef44b75939879/barretenberg/cpp/src/barretenberg/crypto/pedersen_commitment/pedersen.test.cpp#L20-L29 + let res = commit_native_with_index(&[Fq::zero(), Fq::one()], 0); + let expected = Affine::new( + FieldElement::from_hex( + "0x054aa86a73cb8a34525e5bbed6e43ba1198e860f5f3950268f71df4591bde402", + ) + .unwrap() + .into_repr(), + FieldElement::from_hex( + "0x209dcfbf2cfb57f9f6046f44d71ac6faf87254afc7407c04eb621a6287cac126", + ) + .unwrap() + .into_repr(), + ); + + assert_eq!(res, expected); + } +} diff --git a/acvm-repo/bn254_blackbox_solver/src/pedersen/hash.rs b/acvm-repo/bn254_blackbox_solver/src/pedersen/hash.rs new file mode 100644 index 00000000000..5c637207491 --- /dev/null +++ b/acvm-repo/bn254_blackbox_solver/src/pedersen/hash.rs @@ -0,0 +1,68 @@ +// Taken from: https://github.com/laudiacay/barustenberg/blob/df6bc6f095fe7f288bf6a12e7317fd8eb33d68ae/barustenberg/src/crypto/pedersen/pederson_hash.rs + +use std::sync::OnceLock; + +use ark_ec::{short_weierstrass::Affine, CurveConfig, CurveGroup}; +use grumpkin::GrumpkinParameters; + +use crate::generator::generators::derive_generators; + +use super::commitment::commit_native_with_index; + +/// Given a vector of fields, generate a pedersen hash using the indexed generators. +pub(crate) fn hash_with_index( + inputs: &[grumpkin::Fq], + starting_index: u32, +) -> ::BaseField { + let length_as_scalar: ::ScalarField = + (inputs.len() as u64).into(); + let length_prefix = *length_generator() * length_as_scalar; + let result = length_prefix + commit_native_with_index(inputs, starting_index); + result.into_affine().x +} + +fn length_generator() -> &'static Affine { + static INSTANCE: OnceLock> = OnceLock::new(); + INSTANCE.get_or_init(|| derive_generators("pedersen_hash_length".as_bytes(), 1, 0)[0]) +} + +#[cfg(test)] +pub(crate) mod test { + + use super::*; + + use acir::{AcirField, FieldElement}; + use ark_std::One; + use grumpkin::Fq; + + //reference: https://github.com/AztecProtocol/barretenberg/blob/master/cpp/src/barretenberg/crypto/pedersen_hash/pedersen.test.cpp + #[test] + fn hash_one() { + // https://github.com/AztecProtocol/aztec-packages/blob/72931bdb8202c34042cdfb8cee2ef44b75939879/barretenberg/cpp/src/barretenberg/crypto/pedersen_hash/pedersen.test.cpp#L21-L26 + let res = hash_with_index(&[Fq::one(), Fq::one()], 0); + + assert_eq!( + res, + FieldElement::from_hex( + "0x07ebfbf4df29888c6cd6dca13d4bb9d1a923013ddbbcbdc3378ab8845463297b", + ) + .unwrap() + .into_repr(), + ); + } + + #[test] + fn test_hash_with_index() { + // https://github.com/AztecProtocol/aztec-packages/blob/72931bdb8202c34042cdfb8cee2ef44b75939879/barretenberg/cpp/src/barretenberg/crypto/pedersen_hash/pedersen.test.cpp#L28-L33 + let res = hash_with_index(&[Fq::one(), Fq::one()], 5); + + assert_eq!( + res, + FieldElement::from_hex( + "0x1c446df60816b897cda124524e6b03f36df0cec333fad87617aab70d7861daa6", + ) + .unwrap() + .into_repr(), + ); + } +} diff --git a/acvm-repo/bn254_blackbox_solver/src/pedersen/mod.rs b/acvm-repo/bn254_blackbox_solver/src/pedersen/mod.rs new file mode 100644 index 00000000000..c3c4ed56450 --- /dev/null +++ b/acvm-repo/bn254_blackbox_solver/src/pedersen/mod.rs @@ -0,0 +1,2 @@ +pub(crate) mod commitment; +pub(crate) mod hash; diff --git a/acvm-repo/bn254_blackbox_solver/src/poseidon2.rs b/acvm-repo/bn254_blackbox_solver/src/poseidon2.rs index e0ed5bcd053..95c620aab0d 100644 --- a/acvm-repo/bn254_blackbox_solver/src/poseidon2.rs +++ b/acvm-repo/bn254_blackbox_solver/src/poseidon2.rs @@ -1,9 +1,20 @@ -use acir::FieldElement; +use acir::{AcirField, FieldElement}; use acvm_blackbox_solver::BlackBoxResolutionError; -use num_bigint::BigUint; -use num_traits::Num; +use lazy_static::lazy_static; -pub(crate) struct Poseidon2 { +pub fn poseidon2_permutation( + inputs: &[FieldElement], + len: u32, +) -> Result, BlackBoxResolutionError> { + let poseidon = Poseidon2::new(); + poseidon.permutation(inputs, len) +} + +pub(crate) struct Poseidon2<'a> { + config: &'a Poseidon2Config, +} + +struct Poseidon2Config { t: u32, rounds_f: u32, rounds_p: u32, @@ -11,929 +22,415 @@ pub(crate) struct Poseidon2 { round_constant: [[FieldElement; 4]; 64], } -impl Poseidon2 { +fn field_from_hex(hex: &str) -> FieldElement { + FieldElement::from_be_bytes_reduce(&hex::decode(hex).expect("Should be passed only valid hex")) +} + +lazy_static! { + static ref INTERNAL_MATRIX_DIAGONAL: [FieldElement; 4] = [ + field_from_hex("10dc6e9c006ea38b04b1e03b4bd9490c0d03f98929ca1d7fb56821fd19d3b6e7"), + field_from_hex("0c28145b6a44df3e0149b3d0a30b3bb599df9756d4dd9b84a86b38cfb45a740b"), + field_from_hex("00544b8338791518b2c7645a50392798b21f75bb60e3596170067d00141cac15"), + field_from_hex("222c01175718386f2e2e82eb122789e352e105a3b8fa852613bc534433ee428b"), + ]; + static ref ROUND_CONSTANT: [[FieldElement; 4]; 64] = [ + [ + field_from_hex("19b849f69450b06848da1d39bd5e4a4302bb86744edc26238b0878e269ed23e5"), + field_from_hex("265ddfe127dd51bd7239347b758f0a1320eb2cc7450acc1dad47f80c8dcf34d6"), + field_from_hex("199750ec472f1809e0f66a545e1e51624108ac845015c2aa3dfc36bab497d8aa"), + field_from_hex("157ff3fe65ac7208110f06a5f74302b14d743ea25067f0ffd032f787c7f1cdf8"), + ], + [ + field_from_hex("2e49c43c4569dd9c5fd35ac45fca33f10b15c590692f8beefe18f4896ac94902"), + field_from_hex("0e35fb89981890520d4aef2b6d6506c3cb2f0b6973c24fa82731345ffa2d1f1e"), + field_from_hex("251ad47cb15c4f1105f109ae5e944f1ba9d9e7806d667ffec6fe723002e0b996"), + field_from_hex("13da07dc64d428369873e97160234641f8beb56fdd05e5f3563fa39d9c22df4e"), + ], + [ + field_from_hex("0c009b84e650e6d23dc00c7dccef7483a553939689d350cd46e7b89055fd4738"), + field_from_hex("011f16b1c63a854f01992e3956f42d8b04eb650c6d535eb0203dec74befdca06"), + field_from_hex("0ed69e5e383a688f209d9a561daa79612f3f78d0467ad45485df07093f367549"), + field_from_hex("04dba94a7b0ce9e221acad41472b6bbe3aec507f5eb3d33f463672264c9f789b"), + ], + [ + field_from_hex("0a3f2637d840f3a16eb094271c9d237b6036757d4bb50bf7ce732ff1d4fa28e8"), + field_from_hex("259a666f129eea198f8a1c502fdb38fa39b1f075569564b6e54a485d1182323f"), + field_from_hex("28bf7459c9b2f4c6d8e7d06a4ee3a47f7745d4271038e5157a32fdf7ede0d6a1"), + field_from_hex("0a1ca941f057037526ea200f489be8d4c37c85bbcce6a2aeec91bd6941432447"), + ], + [ + field_from_hex("0c6f8f958be0e93053d7fd4fc54512855535ed1539f051dcb43a26fd926361cf"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("123106a93cd17578d426e8128ac9d90aa9e8a00708e296e084dd57e69caaf811"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("26e1ba52ad9285d97dd3ab52f8e840085e8fa83ff1e8f1877b074867cd2dee75"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("1cb55cad7bd133de18a64c5c47b9c97cbe4d8b7bf9e095864471537e6a4ae2c5"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("1dcd73e46acd8f8e0e2c7ce04bde7f6d2a53043d5060a41c7143f08e6e9055d0"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("011003e32f6d9c66f5852f05474a4def0cda294a0eb4e9b9b12b9bb4512e5574"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("2b1e809ac1d10ab29ad5f20d03a57dfebadfe5903f58bafed7c508dd2287ae8c"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("2539de1785b735999fb4dac35ee17ed0ef995d05ab2fc5faeaa69ae87bcec0a5"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("0c246c5a2ef8ee0126497f222b3e0a0ef4e1c3d41c86d46e43982cb11d77951d"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("192089c4974f68e95408148f7c0632edbb09e6a6ad1a1c2f3f0305f5d03b527b"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("1eae0ad8ab68b2f06a0ee36eeb0d0c058529097d91096b756d8fdc2fb5a60d85"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("179190e5d0e22179e46f8282872abc88db6e2fdc0dee99e69768bd98c5d06bfb"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("29bb9e2c9076732576e9a81c7ac4b83214528f7db00f31bf6cafe794a9b3cd1c"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("225d394e42207599403efd0c2464a90d52652645882aac35b10e590e6e691e08"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("064760623c25c8cf753d238055b444532be13557451c087de09efd454b23fd59"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("10ba3a0e01df92e87f301c4b716d8a394d67f4bf42a75c10922910a78f6b5b87"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("0e070bf53f8451b24f9c6e96b0c2a801cb511bc0c242eb9d361b77693f21471c"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("1b94cd61b051b04dd39755ff93821a73ccd6cb11d2491d8aa7f921014de252fb"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("1d7cb39bafb8c744e148787a2e70230f9d4e917d5713bb050487b5aa7d74070b"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("2ec93189bd1ab4f69117d0fe980c80ff8785c2961829f701bb74ac1f303b17db"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("2db366bfdd36d277a692bb825b86275beac404a19ae07a9082ea46bd83517926"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("062100eb485db06269655cf186a68532985275428450359adc99cec6960711b8"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("0761d33c66614aaa570e7f1e8244ca1120243f92fa59e4f900c567bf41f5a59b"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("20fc411a114d13992c2705aa034e3f315d78608a0f7de4ccf7a72e494855ad0d"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("25b5c004a4bdfcb5add9ec4e9ab219ba102c67e8b3effb5fc3a30f317250bc5a"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("23b1822d278ed632a494e58f6df6f5ed038b186d8474155ad87e7dff62b37f4b"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("22734b4c5c3f9493606c4ba9012499bf0f14d13bfcfcccaa16102a29cc2f69e0"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("26c0c8fe09eb30b7e27a74dc33492347e5bdff409aa3610254413d3fad795ce5"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("070dd0ccb6bd7bbae88eac03fa1fbb26196be3083a809829bbd626df348ccad9"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("12b6595bdb329b6fb043ba78bb28c3bec2c0a6de46d8c5ad6067c4ebfd4250da"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("248d97d7f76283d63bec30e7a5876c11c06fca9b275c671c5e33d95bb7e8d729"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("1a306d439d463b0816fc6fd64cc939318b45eb759ddde4aa106d15d9bd9baaaa"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("28a8f8372e3c38daced7c00421cb4621f4f1b54ddc27821b0d62d3d6ec7c56cf"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("0094975717f9a8a8bb35152f24d43294071ce320c829f388bc852183e1e2ce7e"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("04d5ee4c3aa78f7d80fde60d716480d3593f74d4f653ae83f4103246db2e8d65"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("2a6cf5e9aa03d4336349ad6fb8ed2269c7bef54b8822cc76d08495c12efde187"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("2304d31eaab960ba9274da43e19ddeb7f792180808fd6e43baae48d7efcba3f3"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("03fd9ac865a4b2a6d5e7009785817249bff08a7e0726fcb4e1c11d39d199f0b0"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("00b7258ded52bbda2248404d55ee5044798afc3a209193073f7954d4d63b0b64"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("159f81ada0771799ec38fca2d4bf65ebb13d3a74f3298db36272c5ca65e92d9a"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("1ef90e67437fbc8550237a75bc28e3bb9000130ea25f0c5471e144cf4264431f"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("1e65f838515e5ff0196b49aa41a2d2568df739bc176b08ec95a79ed82932e30d"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("2b1b045def3a166cec6ce768d079ba74b18c844e570e1f826575c1068c94c33f"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("0832e5753ceb0ff6402543b1109229c165dc2d73bef715e3f1c6e07c168bb173"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("02f614e9cedfb3dc6b762ae0a37d41bab1b841c2e8b6451bc5a8e3c390b6ad16"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("0e2427d38bd46a60dd640b8e362cad967370ebb777bedff40f6a0be27e7ed705"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("0493630b7c670b6deb7c84d414e7ce79049f0ec098c3c7c50768bbe29214a53a"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("22ead100e8e482674decdab17066c5a26bb1515355d5461a3dc06cc85327cea9"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("25b3e56e655b42cdaae2626ed2554d48583f1ae35626d04de5084e0b6d2a6f16"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("1e32752ada8836ef5837a6cde8ff13dbb599c336349e4c584b4fdc0a0cf6f9d0"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("2fa2a871c15a387cc50f68f6f3c3455b23c00995f05078f672a9864074d412e5"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("2f569b8a9a4424c9278e1db7311e889f54ccbf10661bab7fcd18e7c7a7d83505"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("044cb455110a8fdd531ade530234c518a7df93f7332ffd2144165374b246b43d"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("227808de93906d5d420246157f2e42b191fe8c90adfe118178ddc723a5319025"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("02fcca2934e046bc623adead873579865d03781ae090ad4a8579d2e7a6800355"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("0ef915f0ac120b876abccceb344a1d36bad3f3c5ab91a8ddcbec2e060d8befac"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("1797130f4b7a3e1777eb757bc6f287f6ab0fb85f6be63b09f3b16ef2b1405d38"), + field_from_hex("0a76225dc04170ae3306c85abab59e608c7f497c20156d4d36c668555decc6e5"), + field_from_hex("1fffb9ec1992d66ba1e77a7b93209af6f8fa76d48acb664796174b5326a31a5c"), + field_from_hex("25721c4fc15a3f2853b57c338fa538d85f8fbba6c6b9c6090611889b797b9c5f"), + ], + [ + field_from_hex("0c817fd42d5f7a41215e3d07ba197216adb4c3790705da95eb63b982bfcaf75a"), + field_from_hex("13abe3f5239915d39f7e13c2c24970b6df8cf86ce00a22002bc15866e52b5a96"), + field_from_hex("2106feea546224ea12ef7f39987a46c85c1bc3dc29bdbd7a92cd60acb4d391ce"), + field_from_hex("21ca859468a746b6aaa79474a37dab49f1ca5a28c748bc7157e1b3345bb0f959"), + ], + [ + field_from_hex("05ccd6255c1e6f0c5cf1f0df934194c62911d14d0321662a8f1a48999e34185b"), + field_from_hex("0f0e34a64b70a626e464d846674c4c8816c4fb267fe44fe6ea28678cb09490a4"), + field_from_hex("0558531a4e25470c6157794ca36d0e9647dbfcfe350d64838f5b1a8a2de0d4bf"), + field_from_hex("09d3dca9173ed2faceea125157683d18924cadad3f655a60b72f5864961f1455"), + ], + [ + field_from_hex("0328cbd54e8c0913493f866ed03d218bf23f92d68aaec48617d4c722e5bd4335"), + field_from_hex("2bf07216e2aff0a223a487b1a7094e07e79e7bcc9798c648ee3347dd5329d34b"), + field_from_hex("1daf345a58006b736499c583cb76c316d6f78ed6a6dffc82111e11a63fe412df"), + field_from_hex("176563472456aaa746b694c60e1823611ef39039b2edc7ff391e6f2293d2c404"), + ], + ]; + static ref POSEIDON2_CONFIG: Poseidon2Config = Poseidon2Config { + t: 4, + rounds_f: 8, + rounds_p: 56, + internal_matrix_diagonal: *INTERNAL_MATRIX_DIAGONAL, + round_constant: *ROUND_CONSTANT, + }; +} + +impl<'a> Poseidon2<'a> { pub(crate) fn new() -> Self { - Poseidon2 { - t: 4, - rounds_f: 8, - rounds_p: 56, - internal_matrix_diagonal: [ - Poseidon2::field_from_hex( - "0x10dc6e9c006ea38b04b1e03b4bd9490c0d03f98929ca1d7fb56821fd19d3b6e7", - ), - Poseidon2::field_from_hex( - "0x0c28145b6a44df3e0149b3d0a30b3bb599df9756d4dd9b84a86b38cfb45a740b", - ), - Poseidon2::field_from_hex( - "0x00544b8338791518b2c7645a50392798b21f75bb60e3596170067d00141cac15", - ), - Poseidon2::field_from_hex( - "0x222c01175718386f2e2e82eb122789e352e105a3b8fa852613bc534433ee428b", - ), - ], - round_constant: [ - [ - Poseidon2::field_from_hex( - "0x19b849f69450b06848da1d39bd5e4a4302bb86744edc26238b0878e269ed23e5", - ), - Poseidon2::field_from_hex( - "0x265ddfe127dd51bd7239347b758f0a1320eb2cc7450acc1dad47f80c8dcf34d6", - ), - Poseidon2::field_from_hex( - "0x199750ec472f1809e0f66a545e1e51624108ac845015c2aa3dfc36bab497d8aa", - ), - Poseidon2::field_from_hex( - "0x157ff3fe65ac7208110f06a5f74302b14d743ea25067f0ffd032f787c7f1cdf8", - ), - ], - [ - Poseidon2::field_from_hex( - "0x2e49c43c4569dd9c5fd35ac45fca33f10b15c590692f8beefe18f4896ac94902", - ), - Poseidon2::field_from_hex( - "0x0e35fb89981890520d4aef2b6d6506c3cb2f0b6973c24fa82731345ffa2d1f1e", - ), - Poseidon2::field_from_hex( - "0x251ad47cb15c4f1105f109ae5e944f1ba9d9e7806d667ffec6fe723002e0b996", - ), - Poseidon2::field_from_hex( - "0x13da07dc64d428369873e97160234641f8beb56fdd05e5f3563fa39d9c22df4e", - ), - ], - [ - Poseidon2::field_from_hex( - "0x0c009b84e650e6d23dc00c7dccef7483a553939689d350cd46e7b89055fd4738", - ), - Poseidon2::field_from_hex( - "0x011f16b1c63a854f01992e3956f42d8b04eb650c6d535eb0203dec74befdca06", - ), - Poseidon2::field_from_hex( - "0x0ed69e5e383a688f209d9a561daa79612f3f78d0467ad45485df07093f367549", - ), - Poseidon2::field_from_hex( - "0x04dba94a7b0ce9e221acad41472b6bbe3aec507f5eb3d33f463672264c9f789b", - ), - ], - [ - Poseidon2::field_from_hex( - "0x0a3f2637d840f3a16eb094271c9d237b6036757d4bb50bf7ce732ff1d4fa28e8", - ), - Poseidon2::field_from_hex( - "0x259a666f129eea198f8a1c502fdb38fa39b1f075569564b6e54a485d1182323f", - ), - Poseidon2::field_from_hex( - "0x28bf7459c9b2f4c6d8e7d06a4ee3a47f7745d4271038e5157a32fdf7ede0d6a1", - ), - Poseidon2::field_from_hex( - "0x0a1ca941f057037526ea200f489be8d4c37c85bbcce6a2aeec91bd6941432447", - ), - ], - [ - Poseidon2::field_from_hex( - "0x0c6f8f958be0e93053d7fd4fc54512855535ed1539f051dcb43a26fd926361cf", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x123106a93cd17578d426e8128ac9d90aa9e8a00708e296e084dd57e69caaf811", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x26e1ba52ad9285d97dd3ab52f8e840085e8fa83ff1e8f1877b074867cd2dee75", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x1cb55cad7bd133de18a64c5c47b9c97cbe4d8b7bf9e095864471537e6a4ae2c5", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x1dcd73e46acd8f8e0e2c7ce04bde7f6d2a53043d5060a41c7143f08e6e9055d0", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x011003e32f6d9c66f5852f05474a4def0cda294a0eb4e9b9b12b9bb4512e5574", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x2b1e809ac1d10ab29ad5f20d03a57dfebadfe5903f58bafed7c508dd2287ae8c", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x2539de1785b735999fb4dac35ee17ed0ef995d05ab2fc5faeaa69ae87bcec0a5", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x0c246c5a2ef8ee0126497f222b3e0a0ef4e1c3d41c86d46e43982cb11d77951d", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x192089c4974f68e95408148f7c0632edbb09e6a6ad1a1c2f3f0305f5d03b527b", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x1eae0ad8ab68b2f06a0ee36eeb0d0c058529097d91096b756d8fdc2fb5a60d85", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x179190e5d0e22179e46f8282872abc88db6e2fdc0dee99e69768bd98c5d06bfb", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x29bb9e2c9076732576e9a81c7ac4b83214528f7db00f31bf6cafe794a9b3cd1c", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x225d394e42207599403efd0c2464a90d52652645882aac35b10e590e6e691e08", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x064760623c25c8cf753d238055b444532be13557451c087de09efd454b23fd59", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x10ba3a0e01df92e87f301c4b716d8a394d67f4bf42a75c10922910a78f6b5b87", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x0e070bf53f8451b24f9c6e96b0c2a801cb511bc0c242eb9d361b77693f21471c", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x1b94cd61b051b04dd39755ff93821a73ccd6cb11d2491d8aa7f921014de252fb", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x1d7cb39bafb8c744e148787a2e70230f9d4e917d5713bb050487b5aa7d74070b", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x2ec93189bd1ab4f69117d0fe980c80ff8785c2961829f701bb74ac1f303b17db", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x2db366bfdd36d277a692bb825b86275beac404a19ae07a9082ea46bd83517926", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x062100eb485db06269655cf186a68532985275428450359adc99cec6960711b8", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x0761d33c66614aaa570e7f1e8244ca1120243f92fa59e4f900c567bf41f5a59b", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x20fc411a114d13992c2705aa034e3f315d78608a0f7de4ccf7a72e494855ad0d", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x25b5c004a4bdfcb5add9ec4e9ab219ba102c67e8b3effb5fc3a30f317250bc5a", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x23b1822d278ed632a494e58f6df6f5ed038b186d8474155ad87e7dff62b37f4b", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x22734b4c5c3f9493606c4ba9012499bf0f14d13bfcfcccaa16102a29cc2f69e0", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x26c0c8fe09eb30b7e27a74dc33492347e5bdff409aa3610254413d3fad795ce5", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x070dd0ccb6bd7bbae88eac03fa1fbb26196be3083a809829bbd626df348ccad9", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x12b6595bdb329b6fb043ba78bb28c3bec2c0a6de46d8c5ad6067c4ebfd4250da", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x248d97d7f76283d63bec30e7a5876c11c06fca9b275c671c5e33d95bb7e8d729", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x1a306d439d463b0816fc6fd64cc939318b45eb759ddde4aa106d15d9bd9baaaa", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x28a8f8372e3c38daced7c00421cb4621f4f1b54ddc27821b0d62d3d6ec7c56cf", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x0094975717f9a8a8bb35152f24d43294071ce320c829f388bc852183e1e2ce7e", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x04d5ee4c3aa78f7d80fde60d716480d3593f74d4f653ae83f4103246db2e8d65", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x2a6cf5e9aa03d4336349ad6fb8ed2269c7bef54b8822cc76d08495c12efde187", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x2304d31eaab960ba9274da43e19ddeb7f792180808fd6e43baae48d7efcba3f3", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x03fd9ac865a4b2a6d5e7009785817249bff08a7e0726fcb4e1c11d39d199f0b0", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x00b7258ded52bbda2248404d55ee5044798afc3a209193073f7954d4d63b0b64", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x159f81ada0771799ec38fca2d4bf65ebb13d3a74f3298db36272c5ca65e92d9a", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x1ef90e67437fbc8550237a75bc28e3bb9000130ea25f0c5471e144cf4264431f", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x1e65f838515e5ff0196b49aa41a2d2568df739bc176b08ec95a79ed82932e30d", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x2b1b045def3a166cec6ce768d079ba74b18c844e570e1f826575c1068c94c33f", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x0832e5753ceb0ff6402543b1109229c165dc2d73bef715e3f1c6e07c168bb173", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x02f614e9cedfb3dc6b762ae0a37d41bab1b841c2e8b6451bc5a8e3c390b6ad16", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x0e2427d38bd46a60dd640b8e362cad967370ebb777bedff40f6a0be27e7ed705", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x0493630b7c670b6deb7c84d414e7ce79049f0ec098c3c7c50768bbe29214a53a", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x22ead100e8e482674decdab17066c5a26bb1515355d5461a3dc06cc85327cea9", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x25b3e56e655b42cdaae2626ed2554d48583f1ae35626d04de5084e0b6d2a6f16", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x1e32752ada8836ef5837a6cde8ff13dbb599c336349e4c584b4fdc0a0cf6f9d0", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x2fa2a871c15a387cc50f68f6f3c3455b23c00995f05078f672a9864074d412e5", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x2f569b8a9a4424c9278e1db7311e889f54ccbf10661bab7fcd18e7c7a7d83505", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x044cb455110a8fdd531ade530234c518a7df93f7332ffd2144165374b246b43d", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x227808de93906d5d420246157f2e42b191fe8c90adfe118178ddc723a5319025", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x02fcca2934e046bc623adead873579865d03781ae090ad4a8579d2e7a6800355", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x0ef915f0ac120b876abccceb344a1d36bad3f3c5ab91a8ddcbec2e060d8befac", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x1797130f4b7a3e1777eb757bc6f287f6ab0fb85f6be63b09f3b16ef2b1405d38", - ), - Poseidon2::field_from_hex( - "0x0a76225dc04170ae3306c85abab59e608c7f497c20156d4d36c668555decc6e5", - ), - Poseidon2::field_from_hex( - "0x1fffb9ec1992d66ba1e77a7b93209af6f8fa76d48acb664796174b5326a31a5c", - ), - Poseidon2::field_from_hex( - "0x25721c4fc15a3f2853b57c338fa538d85f8fbba6c6b9c6090611889b797b9c5f", - ), - ], - [ - Poseidon2::field_from_hex( - "0x0c817fd42d5f7a41215e3d07ba197216adb4c3790705da95eb63b982bfcaf75a", - ), - Poseidon2::field_from_hex( - "0x13abe3f5239915d39f7e13c2c24970b6df8cf86ce00a22002bc15866e52b5a96", - ), - Poseidon2::field_from_hex( - "0x2106feea546224ea12ef7f39987a46c85c1bc3dc29bdbd7a92cd60acb4d391ce", - ), - Poseidon2::field_from_hex( - "0x21ca859468a746b6aaa79474a37dab49f1ca5a28c748bc7157e1b3345bb0f959", - ), - ], - [ - Poseidon2::field_from_hex( - "0x05ccd6255c1e6f0c5cf1f0df934194c62911d14d0321662a8f1a48999e34185b", - ), - Poseidon2::field_from_hex( - "0x0f0e34a64b70a626e464d846674c4c8816c4fb267fe44fe6ea28678cb09490a4", - ), - Poseidon2::field_from_hex( - "0x0558531a4e25470c6157794ca36d0e9647dbfcfe350d64838f5b1a8a2de0d4bf", - ), - Poseidon2::field_from_hex( - "0x09d3dca9173ed2faceea125157683d18924cadad3f655a60b72f5864961f1455", - ), - ], - [ - Poseidon2::field_from_hex( - "0x0328cbd54e8c0913493f866ed03d218bf23f92d68aaec48617d4c722e5bd4335", - ), - Poseidon2::field_from_hex( - "0x2bf07216e2aff0a223a487b1a7094e07e79e7bcc9798c648ee3347dd5329d34b", - ), - Poseidon2::field_from_hex( - "0x1daf345a58006b736499c583cb76c316d6f78ed6a6dffc82111e11a63fe412df", - ), - Poseidon2::field_from_hex( - "0x176563472456aaa746b694c60e1823611ef39039b2edc7ff391e6f2293d2c404", - ), - ], - ], - } - } - fn field_from_hex(hex: &str) -> FieldElement { - let bigint = BigUint::from_str_radix(hex.strip_prefix("0x").unwrap(), 16).unwrap(); - FieldElement::from_be_bytes_reduce(&bigint.to_bytes_be()) + Poseidon2 { config: &POSEIDON2_CONFIG } } fn single_box(x: FieldElement) -> FieldElement { @@ -948,7 +445,9 @@ impl Poseidon2 { } fn add_round_constants(&self, state: &mut [FieldElement], round: usize) { - for (state_element, constant_element) in state.iter_mut().zip(self.round_constant[round]) { + for (state_element, constant_element) in + state.iter_mut().zip(self.config.round_constant[round]) + { *state_element += constant_element; } } @@ -982,7 +481,7 @@ impl Poseidon2 { sum += *i; } for (index, i) in input.iter_mut().enumerate() { - *i = *i * self.internal_matrix_diagonal[index]; + *i = *i * self.config.internal_matrix_diagonal[index]; *i += sum; } } @@ -1002,10 +501,10 @@ impl Poseidon2 { ), )); } - if len != self.t { + if len != self.config.t { return Err(BlackBoxResolutionError::Failed( acir::BlackBoxFunc::Poseidon2Permutation, - format!("Expected {} values but encountered {}", self.t, len), + format!("Expected {} values but encountered {}", self.config.t, len), )); } // Read witness assignments @@ -1017,22 +516,22 @@ impl Poseidon2 { Self::matrix_multiplication_4x4(&mut state); // First set of external rounds - let rf_first = self.rounds_f / 2; + let rf_first = self.config.rounds_f / 2; for r in 0..rf_first { self.add_round_constants(&mut state, r as usize); Self::s_box(&mut state); Self::matrix_multiplication_4x4(&mut state); } // Internal rounds - let p_end = rf_first + self.rounds_p; + let p_end = rf_first + self.config.rounds_p; for r in rf_first..p_end { - state[0] += self.round_constant[r as usize][0]; + state[0] += self.config.round_constant[r as usize][0]; state[0] = Self::single_box(state[0]); self.internal_m_multiplication(&mut state); } // Remaining external rounds - let num_rounds = self.rounds_f + self.rounds_p; + let num_rounds = self.config.rounds_f + self.config.rounds_p; for i in p_end..num_rounds { self.add_round_constants(&mut state, i as usize); Self::s_box(&mut state); @@ -1041,3 +540,24 @@ impl Poseidon2 { Ok(state.into()) } } + +#[cfg(test)] +mod test { + use acir::{AcirField, FieldElement}; + + use super::{field_from_hex, poseidon2_permutation}; + + #[test] + fn smoke_test() { + let inputs = [FieldElement::zero(); 4]; + let result = poseidon2_permutation(&inputs, 4).expect("should successfully permute"); + + let expected_result = [ + field_from_hex("18DFB8DC9B82229CFF974EFEFC8DF78B1CE96D9D844236B496785C698BC6732E"), + field_from_hex("095C230D1D37A246E8D2D5A63B165FE0FADE040D442F61E25F0590E5FB76F839"), + field_from_hex("0BB9545846E1AFA4FA3C97414A60A20FC4949F537A68CCECA34C5CE71E28AA59"), + field_from_hex("18A4F34C9C6F99335FF7638B82AEED9018026618358873C982BBDDE265B2ED6D"), + ]; + assert_eq!(result, expected_result); + } +} diff --git a/acvm-repo/bn254_blackbox_solver/src/schnorr/mod.rs b/acvm-repo/bn254_blackbox_solver/src/schnorr/mod.rs new file mode 100644 index 00000000000..62e515a0792 --- /dev/null +++ b/acvm-repo/bn254_blackbox_solver/src/schnorr/mod.rs @@ -0,0 +1,146 @@ +use acvm_blackbox_solver::blake2s; +use ark_ec::{ + short_weierstrass::{Affine, SWCurveConfig}, + AffineRepr, CurveConfig, CurveGroup, +}; +use ark_ff::{BigInteger, PrimeField, Zero}; +use grumpkin::{Fq, GrumpkinParameters}; + +pub(crate) fn verify_signature( + pub_key_x: Fq, + pub_key_y: Fq, + sig_s_bytes: [u8; 32], + sig_e_bytes: [u8; 32], + message: &[u8], +) -> bool { + let pub_key = Affine::::new_unchecked(pub_key_x, pub_key_y); + + if !pub_key.is_on_curve() + || !pub_key.is_in_correct_subgroup_assuming_on_curve() + || pub_key.is_zero() + { + return false; + } + + let sig_s = + ::ScalarField::from_be_bytes_mod_order(&sig_s_bytes); + let sig_e = + ::ScalarField::from_be_bytes_mod_order(&sig_e_bytes); + + if sig_s.is_zero() || sig_e.is_zero() { + return false; + } + + // R = g^{sig.s} • pub^{sig.e} + let r = GrumpkinParameters::GENERATOR * sig_s + pub_key * sig_e; + if r.is_zero() { + // this result implies k == 0, which would be catastrophic for the prover. + // it is a cheap check that ensures this doesn't happen. + return false; + } + + // compare the _hashes_ rather than field elements modulo r + // e = H(pedersen(r, pk.x, pk.y), m), where r = R.x + let target_e_bytes = schnorr_generate_challenge(message, pub_key_x, pub_key_y, r.into_affine()); + + sig_e_bytes == target_e_bytes +} + +fn schnorr_generate_challenge( + message: &[u8], + pub_key_x: Fq, + pub_key_y: Fq, + r: Affine, +) -> [u8; 32] { + // create challenge message pedersen_commitment(R.x, pubkey) + + let r_x = *r.x().expect("r has been checked to be non-zero"); + let pedersen_hash = crate::pedersen::hash::hash_with_index(&[r_x, pub_key_x, pub_key_y], 0); + + let mut hash_input: Vec = pedersen_hash.into_bigint().to_bytes_be(); + hash_input.extend(message); + + blake2s(&hash_input).unwrap() +} + +#[cfg(test)] +mod schnorr_tests { + use acir::{AcirField, FieldElement}; + + use super::verify_signature; + + #[test] + fn verifies_valid_signature() { + let pub_key_x: grumpkin::Fq = FieldElement::from_hex( + "0x04b260954662e97f00cab9adb773a259097f7a274b83b113532bce27fa3fb96a", + ) + .unwrap() + .into_repr(); + let pub_key_y: grumpkin::Fq = FieldElement::from_hex( + "0x2fd51571db6c08666b0edfbfbc57d432068bccd0110a39b166ab243da0037197", + ) + .unwrap() + .into_repr(); + let sig_s_bytes: [u8; 32] = [ + 1, 13, 119, 112, 212, 39, 233, 41, 84, 235, 255, 93, 245, 172, 186, 83, 157, 253, 76, + 77, 33, 128, 178, 15, 214, 67, 105, 107, 177, 234, 77, 48, + ]; + let sig_e_bytes: [u8; 32] = [ + 27, 237, 155, 84, 39, 84, 247, 27, 22, 8, 176, 230, 24, 115, 145, 220, 254, 122, 135, + 179, 171, 4, 214, 202, 64, 199, 19, 84, 239, 138, 124, 12, + ]; + let message: &[u8] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; + + assert!(verify_signature(pub_key_x, pub_key_y, sig_s_bytes, sig_e_bytes, message)); + } + + #[test] + fn rejects_zero_e() { + let pub_key_x: grumpkin::Fq = FieldElement::from_hex( + "0x04b260954662e97f00cab9adb773a259097f7a274b83b113532bce27fa3fb96a", + ) + .unwrap() + .into_repr(); + let pub_key_y: grumpkin::Fq = FieldElement::from_hex( + "0x2fd51571db6c08666b0edfbfbc57d432068bccd0110a39b166ab243da0037197", + ) + .unwrap() + .into_repr(); + let sig_s_bytes: [u8; 32] = [ + 1, 13, 119, 112, 212, 39, 233, 41, 84, 235, 255, 93, 245, 172, 186, 83, 157, 253, 76, + 77, 33, 128, 178, 15, 214, 67, 105, 107, 177, 234, 77, 48, + ]; + let sig_e_bytes: [u8; 32] = [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, + ]; + let message: &[u8] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; + + assert!(!verify_signature(pub_key_x, pub_key_y, sig_s_bytes, sig_e_bytes, message)); + } + + #[test] + fn rejects_zero_s() { + let pub_key_x: grumpkin::Fq = FieldElement::from_hex( + "0x04b260954662e97f00cab9adb773a259097f7a274b83b113532bce27fa3fb96a", + ) + .unwrap() + .into_repr(); + let pub_key_y: grumpkin::Fq = FieldElement::from_hex( + "0x2fd51571db6c08666b0edfbfbc57d432068bccd0110a39b166ab243da0037197", + ) + .unwrap() + .into_repr(); + let sig_s_bytes: [u8; 32] = [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, + ]; + let sig_e_bytes: [u8; 32] = [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, + ]; + let message: &[u8] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; + + assert!(!verify_signature(pub_key_x, pub_key_y, sig_s_bytes, sig_e_bytes, message)); + } +} diff --git a/acvm-repo/bn254_blackbox_solver/src/wasm/barretenberg_structures.rs b/acvm-repo/bn254_blackbox_solver/src/wasm/barretenberg_structures.rs deleted file mode 100644 index 302ffa8af9b..00000000000 --- a/acvm-repo/bn254_blackbox_solver/src/wasm/barretenberg_structures.rs +++ /dev/null @@ -1,25 +0,0 @@ -use acir::FieldElement; - -#[derive(Debug, Default)] -pub(crate) struct Assignments(Vec); - -impl Assignments { - pub(crate) fn to_bytes(&self) -> Vec { - let mut buffer = Vec::new(); - - let witness_len = self.0.len() as u32; - buffer.extend_from_slice(&witness_len.to_be_bytes()); - - for assignment in self.0.iter() { - buffer.extend_from_slice(&assignment.to_be_bytes()); - } - - buffer - } -} - -impl From> for Assignments { - fn from(w: Vec) -> Assignments { - Assignments(w) - } -} diff --git a/acvm-repo/bn254_blackbox_solver/src/wasm/mod.rs b/acvm-repo/bn254_blackbox_solver/src/wasm/mod.rs deleted file mode 100644 index 10b1ab22a8d..00000000000 --- a/acvm-repo/bn254_blackbox_solver/src/wasm/mod.rs +++ /dev/null @@ -1,357 +0,0 @@ -//! ACVM execution is independent of the proving backend against which the ACIR code is being proven. -//! However there are currently a few opcodes for which there is currently no rust implementation so we must -//! use the C++ implementations included in Aztec Lab's Barretenberg library. -//! -//! As [`acvm`] includes rust implementations for these opcodes, this module can be removed. - -mod barretenberg_structures; -mod pedersen; -mod schnorr; - -use barretenberg_structures::Assignments; - -pub(crate) use pedersen::Pedersen; -pub(crate) use schnorr::SchnorrSig; - -/// The number of bytes necessary to store a `FieldElement`. -const FIELD_BYTES: usize = 32; - -#[derive(Debug, thiserror::Error)] -pub(crate) enum Error { - #[error(transparent)] - FromFeature(#[from] FeatureError), -} - -#[derive(Debug, thiserror::Error)] -pub(crate) enum FeatureError { - #[error("Trying to call {name} resulted in an error")] - FunctionCallFailed { name: String, source: wasmer::RuntimeError }, - #[error("Could not find function export named {name}")] - InvalidExport { name: String, source: wasmer::ExportError }, - #[error("No value available when value was expected")] - NoValue, - #[error("Value expected to be i32")] - InvalidI32, - #[error("Could not convert value {value} from i32 to u32")] - InvalidU32 { value: i32, source: std::num::TryFromIntError }, - #[error("Could not convert value {value} from i32 to usize")] - InvalidUsize { value: i32, source: std::num::TryFromIntError }, - #[error("Value expected to be 0 or 1 representing a boolean")] - InvalidBool, -} -#[derive(Debug, thiserror::Error)] -#[error(transparent)] -pub(crate) struct BackendError(#[from] Error); - -impl From for BackendError { - fn from(value: FeatureError) -> Self { - value.into() - } -} - -#[derive(Debug)] -pub(crate) struct Barretenberg { - store: std::cell::RefCell, - memory: wasmer::Memory, - instance: wasmer::Instance, -} - -use std::cell::RefCell; - -use wasmer::{ - imports, Function, FunctionEnv, FunctionEnvMut, Imports, Instance, Memory, MemoryType, Store, - Value, WasmPtr, -}; - -/// The number of bytes necessary to represent a pointer to memory inside the wasm. -// pub(super) const POINTER_BYTES: usize = 4; - -/// The Barretenberg WASM gives us 1024 bytes of scratch space which we can use without -/// needing to allocate/free it ourselves. This can be useful for when we need to pass in several small variables -/// when calling functions on the wasm, however it's important to not overrun this scratch space as otherwise -/// the written data will begin to corrupt the stack. -/// -/// Using this scratch space isn't particularly safe if we have multiple threads interacting with the wasm however, -/// each thread could write to the same pointer address simultaneously. -pub(super) const WASM_SCRATCH_BYTES: usize = 1024; - -/// Embed the Barretenberg WASM file -#[derive(rust_embed::RustEmbed)] -#[folder = "$BARRETENBERG_BIN_DIR"] -#[include = "acvm_backend.wasm"] -struct Wasm; - -impl Barretenberg { - #[cfg(not(target_arch = "wasm32"))] - pub(crate) fn new() -> Barretenberg { - let (instance, memory, store) = instance_load(); - let barretenberg = Barretenberg { memory, instance, store: RefCell::new(store) }; - barretenberg.call_wasi_initialize(); - barretenberg - } - - #[cfg(target_arch = "wasm32")] - pub(crate) async fn initialize() -> Barretenberg { - let (instance, memory, store) = instance_load().await; - let barretenberg = Barretenberg { memory, instance, store: RefCell::new(store) }; - barretenberg.call_wasi_initialize(); - barretenberg - } - /// Call initialization function for WASI, to initialize all of the appropriate - /// globals. - fn call_wasi_initialize(&self) { - self.call_multiple("_initialize", vec![]) - .expect("expected call to WASI initialization function to not fail"); - } -} - -/// A wrapper around the arguments or return value from a WASM call. -/// Notice, `Option` is used because not every call returns a value, -/// some calls are simply made to free a pointer or manipulate the heap. -#[derive(Debug, Clone)] -pub(crate) struct WASMValue(Option); - -impl From for WASMValue { - fn from(value: usize) -> Self { - WASMValue(Some(Value::I32(value as i32))) - } -} - -impl From for WASMValue { - fn from(value: u32) -> Self { - WASMValue(Some(Value::I32(value as i32))) - } -} - -impl From for WASMValue { - fn from(value: i32) -> Self { - WASMValue(Some(Value::I32(value))) - } -} - -impl From for WASMValue { - fn from(value: Value) -> Self { - WASMValue(Some(value)) - } -} - -impl TryFrom for bool { - type Error = FeatureError; - - fn try_from(value: WASMValue) -> Result { - match value.try_into()? { - 0 => Ok(false), - 1 => Ok(true), - _ => Err(FeatureError::InvalidBool), - } - } -} - -impl TryFrom for usize { - type Error = FeatureError; - - fn try_from(value: WASMValue) -> Result { - let value: i32 = value.try_into()?; - value.try_into().map_err(|source| FeatureError::InvalidUsize { value, source }) - } -} - -impl TryFrom for u32 { - type Error = FeatureError; - - fn try_from(value: WASMValue) -> Result { - let value = value.try_into()?; - u32::try_from(value).map_err(|source| FeatureError::InvalidU32 { value, source }) - } -} - -impl TryFrom for i32 { - type Error = FeatureError; - - fn try_from(value: WASMValue) -> Result { - value.0.map_or(Err(FeatureError::NoValue), |val| val.i32().ok_or(FeatureError::InvalidI32)) - } -} - -impl TryFrom for Value { - type Error = FeatureError; - - fn try_from(value: WASMValue) -> Result { - value.0.ok_or(FeatureError::NoValue) - } -} - -impl Barretenberg { - /// Transfer bytes to WASM heap - // TODO: Consider making this Result-returning - pub(crate) fn transfer_to_heap(&self, data: &[u8], offset: usize) { - let memory = &self.memory; - let store = self.store.borrow(); - let memory_view = memory.view(&store); - - memory_view.write(offset as u64, data).unwrap(); - } - - // TODO: Consider making this Result-returning - pub(crate) fn read_memory(&self, start: usize) -> [u8; SIZE] { - self.read_memory_variable_length(start, SIZE) - .try_into() - .expect("Read memory should be of the specified length") - } - - // TODO: Consider making this Result-returning - pub(crate) fn read_memory_variable_length(&self, offset: usize, length: usize) -> Vec { - let memory = &self.memory; - let store = &self.store.borrow(); - let memory_view = memory.view(&store); - - let mut buf = vec![0; length]; - - memory_view.read(offset as u64, &mut buf).unwrap(); - buf - } - - pub(crate) fn call(&self, name: &str, param: &WASMValue) -> Result { - self.call_multiple(name, vec![param]) - } - - pub(crate) fn call_multiple( - &self, - name: &str, - params: Vec<&WASMValue>, - ) -> Result { - // We take in a reference to values, since they do not implement Copy. - // We then clone them inside of this function, so that the API does not have a bunch of Clones everywhere - - let mut args: Vec = vec![]; - for param in params.into_iter().cloned() { - args.push(param.try_into()?); - } - let func = self - .instance - .exports - .get_function(name) - .map_err(|source| FeatureError::InvalidExport { name: name.to_string(), source })?; - let boxed_value = func.call(&mut self.store.borrow_mut(), &args).map_err(|source| { - FeatureError::FunctionCallFailed { name: name.to_string(), source } - })?; - let option_value = boxed_value.first().cloned(); - - Ok(WASMValue(option_value)) - } - - /// Creates a pointer and allocates the bytes that the pointer references to, to the heap - pub(crate) fn allocate(&self, bytes: &[u8]) -> Result { - let ptr: i32 = self.call("bbmalloc", &bytes.len().into())?.try_into()?; - - let i32_bytes = ptr.to_be_bytes(); - let u32_bytes = u32::from_be_bytes(i32_bytes); - - self.transfer_to_heap(bytes, u32_bytes as usize); - Ok(ptr.into()) - } -} - -fn init_memory_and_state() -> (Memory, Store, Imports) { - let mut store = Store::default(); - - let mem_type = MemoryType::new(18, Some(65536), false); - let memory = Memory::new(&mut store, mem_type).unwrap(); - - let function_env = FunctionEnv::new(&mut store, memory.clone()); - let custom_imports = imports! { - "env" => { - "logstr" => Function::new_typed_with_env( - &mut store, - &function_env, - logstr, - ), - "memory" => memory.clone(), - }, - "wasi_snapshot_preview1" => { - "proc_exit" => Function::new_typed(&mut store, proc_exit), - "random_get" => Function::new_typed_with_env( - &mut store, - &function_env, - random_get - ), - }, - }; - - (memory, store, custom_imports) -} - -#[cfg(not(target_arch = "wasm32"))] -fn instance_load() -> (Instance, Memory, Store) { - use wasmer::Module; - - let (memory, mut store, custom_imports) = init_memory_and_state(); - - let module = Module::new(&store, Wasm::get("acvm_backend.wasm").unwrap().data).unwrap(); - - (Instance::new(&mut store, &module, &custom_imports).unwrap(), memory, store) -} - -#[cfg(target_arch = "wasm32")] -async fn instance_load() -> (Instance, Memory, Store) { - use js_sys::WebAssembly::{self}; - use wasmer::AsJs; - - let (memory, mut store, custom_imports) = init_memory_and_state(); - - let wasm_binary = Wasm::get("acvm_backend.wasm").unwrap().data; - - let js_bytes = unsafe { js_sys::Uint8Array::view(&wasm_binary) }; - let js_module_promise = WebAssembly::compile(&js_bytes); - let js_module: js_sys::WebAssembly::Module = - wasm_bindgen_futures::JsFuture::from(js_module_promise).await.unwrap().into(); - - let js_instance_promise = - WebAssembly::instantiate_module(&js_module, &custom_imports.as_jsvalue(&store).into()); - let js_instance = wasm_bindgen_futures::JsFuture::from(js_instance_promise).await.unwrap(); - let module: wasmer::Module = (js_module, wasm_binary).into(); - let instance: wasmer::Instance = Instance::from_jsvalue(&mut store, &module, &js_instance) - .map_err(|_| "Error while creating BlackBox Functions vendor instance") - .unwrap(); - - (instance, memory, store) -} - -fn logstr(mut env: FunctionEnvMut, ptr: i32) { - let (memory, store) = env.data_and_store_mut(); - let memory_view = memory.view(&store); - - let log_str_wasm_ptr: WasmPtr = WasmPtr::new(ptr as u32); - - match log_str_wasm_ptr.read_utf8_string_with_nul(&memory_view) { - Ok(log_string) => println!("{log_string}"), - Err(err) => println!("Error while reading log string from memory: {err}"), - }; -} - -// Based on https://github.com/wasmerio/wasmer/blob/2.3.0/lib/wasi/src/syscalls/mod.rs#L2537 -fn random_get(mut env: FunctionEnvMut, buf_ptr: i32, buf_len: i32) -> i32 { - let mut u8_buffer = vec![0; buf_len as usize]; - let res = getrandom::getrandom(&mut u8_buffer); - match res { - Ok(()) => { - let (memory, store) = env.data_and_store_mut(); - let memory_view = memory.view(&store); - match memory_view.write(buf_ptr as u64, u8_buffer.as_mut_slice()) { - Ok(_) => { - 0_i32 // __WASI_ESUCCESS - } - Err(_) => { - 29_i32 // __WASI_EIO - } - } - } - Err(_) => { - 29_i32 // __WASI_EIO - } - } -} - -fn proc_exit(_: i32) { - unimplemented!("proc_exit is not implemented") -} diff --git a/acvm-repo/bn254_blackbox_solver/src/wasm/pedersen.rs b/acvm-repo/bn254_blackbox_solver/src/wasm/pedersen.rs deleted file mode 100644 index c816e5b4d1b..00000000000 --- a/acvm-repo/bn254_blackbox_solver/src/wasm/pedersen.rs +++ /dev/null @@ -1,73 +0,0 @@ -use acir::FieldElement; - -use super::{Assignments, Barretenberg, Error, FIELD_BYTES}; - -pub(crate) trait Pedersen { - fn encrypt( - &self, - inputs: Vec, - hash_index: u32, - ) -> Result<(FieldElement, FieldElement), Error>; - - fn hash(&self, inputs: Vec, hash_index: u32) -> Result; -} - -impl Pedersen for Barretenberg { - fn encrypt( - &self, - inputs: Vec, - hash_index: u32, - ) -> Result<(FieldElement, FieldElement), Error> { - let input_buf = Assignments::from(inputs).to_bytes(); - let input_ptr = self.allocate(&input_buf)?; - let result_ptr: usize = 0; - - self.call_multiple( - "pedersen_plookup_commit_with_hash_index", - vec![&input_ptr, &result_ptr.into(), &hash_index.into()], - )?; - - let result_bytes: [u8; 2 * FIELD_BYTES] = self.read_memory(result_ptr); - let (point_x_bytes, point_y_bytes) = result_bytes.split_at(FIELD_BYTES); - - let point_x = FieldElement::from_be_bytes_reduce(point_x_bytes); - let point_y = FieldElement::from_be_bytes_reduce(point_y_bytes); - - Ok((point_x, point_y)) - } - - fn hash(&self, inputs: Vec, hash_index: u32) -> Result { - let input_buf = Assignments::from(inputs).to_bytes(); - let input_ptr = self.allocate(&input_buf)?; - let result_ptr: usize = 0; - - self.call_multiple( - "pedersen_plookup_compress_with_hash_index", - vec![&input_ptr, &result_ptr.into(), &hash_index.into()], - )?; - - let result_bytes: [u8; FIELD_BYTES] = self.read_memory(result_ptr); - - let hash = FieldElement::from_be_bytes_reduce(&result_bytes); - - Ok(hash) - } -} - -#[test] -fn pedersen_hash_to_point() -> Result<(), Error> { - let barretenberg = Barretenberg::new(); - let (x, y) = barretenberg.encrypt(vec![FieldElement::one(), FieldElement::one()], 1)?; - let expected_x = FieldElement::from_hex( - "0x12afb43195f5c621d1d2cabb5f629707095c5307fd4185a663d4e80bb083e878", - ) - .unwrap(); - let expected_y = FieldElement::from_hex( - "0x25793f5b5e62beb92fd18a66050293a9fd554a2ff13bceba0339cae1a038d7c1", - ) - .unwrap(); - - assert_eq!(expected_x.to_hex(), x.to_hex()); - assert_eq!(expected_y.to_hex(), y.to_hex()); - Ok(()) -} diff --git a/acvm-repo/bn254_blackbox_solver/src/wasm/schnorr.rs b/acvm-repo/bn254_blackbox_solver/src/wasm/schnorr.rs deleted file mode 100644 index 18c4f04ef64..00000000000 --- a/acvm-repo/bn254_blackbox_solver/src/wasm/schnorr.rs +++ /dev/null @@ -1,104 +0,0 @@ -use super::{Barretenberg, Error, FIELD_BYTES, WASM_SCRATCH_BYTES}; - -pub(crate) trait SchnorrSig { - fn construct_signature( - &self, - message: &[u8], - private_key: [u8; 32], - ) -> Result<([u8; 32], [u8; 32]), Error>; - fn construct_public_key(&self, private_key: [u8; 32]) -> Result<[u8; 64], Error>; - fn verify_signature( - &self, - pub_key: [u8; 64], - sig_s: [u8; 32], - sig_e: [u8; 32], - message: &[u8], - ) -> Result; -} - -impl SchnorrSig for Barretenberg { - fn construct_signature( - &self, - message: &[u8], - private_key: [u8; 32], - ) -> Result<([u8; 32], [u8; 32]), Error> { - let sig_s_ptr: usize = 0; - let sig_e_ptr: usize = sig_s_ptr + FIELD_BYTES; - let private_key_ptr: usize = sig_e_ptr + FIELD_BYTES; - let message_ptr: usize = private_key_ptr + private_key.len(); - assert!( - message_ptr + message.len() < WASM_SCRATCH_BYTES, - "Message overran wasm scratch space" - ); - - self.transfer_to_heap(&private_key, private_key_ptr); - self.transfer_to_heap(message, message_ptr); - self.call_multiple( - "construct_signature", - vec![ - &message_ptr.into(), - &message.len().into(), - &private_key_ptr.into(), - &sig_s_ptr.into(), - &sig_e_ptr.into(), - ], - )?; - - let sig_s: [u8; FIELD_BYTES] = self.read_memory(sig_s_ptr); - let sig_e: [u8; FIELD_BYTES] = self.read_memory(sig_e_ptr); - - Ok((sig_s, sig_e)) - } - - #[allow(dead_code)] - fn construct_public_key(&self, private_key: [u8; 32]) -> Result<[u8; 64], Error> { - let private_key_ptr: usize = 0; - let result_ptr: usize = private_key_ptr + FIELD_BYTES; - - self.transfer_to_heap(&private_key, private_key_ptr); - - self.call_multiple( - "compute_public_key", - vec![&private_key_ptr.into(), &result_ptr.into()], - )?; - - Ok(self.read_memory(result_ptr)) - } - - fn verify_signature( - &self, - pub_key: [u8; 64], - sig_s: [u8; 32], - sig_e: [u8; 32], - message: &[u8], - ) -> Result { - let public_key_ptr: usize = 0; - let sig_s_ptr: usize = public_key_ptr + pub_key.len(); - let sig_e_ptr: usize = sig_s_ptr + sig_s.len(); - let message_ptr: usize = sig_e_ptr + sig_e.len(); - assert!( - message_ptr + message.len() < WASM_SCRATCH_BYTES, - "Message overran wasm scratch space" - ); - - self.transfer_to_heap(&pub_key, public_key_ptr); - self.transfer_to_heap(&sig_s, sig_s_ptr); - self.transfer_to_heap(&sig_e, sig_e_ptr); - self.transfer_to_heap(message, message_ptr); - - let verified = self.call_multiple( - "verify_signature", - vec![ - &message_ptr.into(), - &message.len().into(), - &public_key_ptr.into(), - &sig_s_ptr.into(), - &sig_e_ptr.into(), - ], - )?; - - // Note, currently for Barretenberg plonk, if the signature fails - // then the whole circuit fails. - Ok(verified.try_into()?) - } -} diff --git a/acvm-repo/brillig/Cargo.toml b/acvm-repo/brillig/Cargo.toml index 8d91d19e117..245767dcecd 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.40.0" +version = "0.46.0" # x-release-please-end authors.workspace = true edition.workspace = true @@ -17,6 +17,5 @@ acir_field.workspace = true serde.workspace = true [features] -default = ["bn254"] bn254 = ["acir_field/bn254"] bls12_381 = ["acir_field/bls12_381"] diff --git a/acvm-repo/brillig/src/black_box.rs b/acvm-repo/brillig/src/black_box.rs index 29861d0fd84..3887092a8c2 100644 --- a/acvm-repo/brillig/src/black_box.rs +++ b/acvm-repo/brillig/src/black_box.rs @@ -5,6 +5,13 @@ use serde::{Deserialize, Serialize}; /// They are implemented as native functions in the VM. #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] pub enum BlackBoxOp { + /// Encrypts a message using AES128. + AES128Encrypt { + inputs: HeapVector, + iv: HeapArray, + key: HeapArray, + outputs: HeapVector, + }, /// Calculates the SHA256 hash of the inputs. Sha256 { message: HeapVector, @@ -66,18 +73,20 @@ pub enum BlackBoxOp { domain_separator: MemoryAddress, output: MemoryAddress, }, - /// Performs scalar multiplication over the embedded curve. - FixedBaseScalarMul { - low: MemoryAddress, - high: MemoryAddress, - result: HeapArray, + /// Performs multi scalar multiplication over the embedded curve. + MultiScalarMul { + points: HeapVector, + scalars: HeapVector, + outputs: HeapArray, }, /// Performs addition over the embedded curve. EmbeddedCurveAdd { input1_x: MemoryAddress, input1_y: MemoryAddress, + input1_infinite: MemoryAddress, input2_x: MemoryAddress, input2_y: MemoryAddress, + input2_infinite: MemoryAddress, result: HeapArray, }, BigIntAdd { @@ -119,4 +128,9 @@ pub enum BlackBoxOp { hash_values: HeapVector, output: HeapArray, }, + ToRadix { + input: MemoryAddress, + radix: u32, + output: HeapArray, + }, } diff --git a/acvm-repo/brillig/src/foreign_call.rs b/acvm-repo/brillig/src/foreign_call.rs index 3f124a9a0a7..a439d5c3202 100644 --- a/acvm-repo/brillig/src/foreign_call.rs +++ b/acvm-repo/brillig/src/foreign_call.rs @@ -1,34 +1,34 @@ -use crate::value::Value; +use acir_field::AcirField; use serde::{Deserialize, Serialize}; /// Single output of a [foreign call][crate::Opcode::ForeignCall]. #[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Clone)] -pub enum ForeignCallParam { - Single(Value), - Array(Vec), +pub enum ForeignCallParam { + Single(F), + Array(Vec), } -impl From for ForeignCallParam { - fn from(value: Value) -> Self { +impl From for ForeignCallParam { + fn from(value: F) -> Self { ForeignCallParam::Single(value) } } -impl From> for ForeignCallParam { - fn from(values: Vec) -> Self { +impl From> for ForeignCallParam { + fn from(values: Vec) -> Self { ForeignCallParam::Array(values) } } -impl ForeignCallParam { - pub fn values(&self) -> Vec { +impl ForeignCallParam { + pub fn fields(&self) -> Vec { match self { ForeignCallParam::Single(value) => vec![*value], - ForeignCallParam::Array(values) => values.clone(), + ForeignCallParam::Array(values) => values.to_vec(), } } - pub fn unwrap_value(&self) -> Value { + pub fn unwrap_field(&self) -> F { match self { ForeignCallParam::Single(value) => *value, ForeignCallParam::Array(_) => panic!("Expected single value, found array"), @@ -38,25 +38,25 @@ impl ForeignCallParam { /// Represents the full output of a [foreign call][crate::Opcode::ForeignCall]. #[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Clone, Default)] -pub struct ForeignCallResult { +pub struct ForeignCallResult { /// Resolved output values of the foreign call. - pub values: Vec, + pub values: Vec>, } -impl From for ForeignCallResult { - fn from(value: Value) -> Self { +impl From for ForeignCallResult { + fn from(value: F) -> Self { ForeignCallResult { values: vec![value.into()] } } } -impl From> for ForeignCallResult { - fn from(values: Vec) -> Self { +impl From> for ForeignCallResult { + fn from(values: Vec) -> Self { ForeignCallResult { values: vec![values.into()] } } } -impl From> for ForeignCallResult { - fn from(values: Vec) -> Self { +impl From>> for ForeignCallResult { + fn from(values: Vec>) -> Self { ForeignCallResult { values } } } diff --git a/acvm-repo/brillig/src/lib.rs b/acvm-repo/brillig/src/lib.rs index 0661e794360..40f2e15acfe 100644 --- a/acvm-repo/brillig/src/lib.rs +++ b/acvm-repo/brillig/src/lib.rs @@ -13,7 +13,6 @@ mod black_box; mod foreign_call; mod opcodes; -mod value; pub use black_box::BlackBoxOp; pub use foreign_call::{ForeignCallParam, ForeignCallResult}; @@ -21,5 +20,3 @@ pub use opcodes::{ BinaryFieldOp, BinaryIntOp, HeapArray, HeapValueType, HeapVector, MemoryAddress, ValueOrArray, }; pub use opcodes::{BrilligOpcode as Opcode, Label}; -pub use value::Typ; -pub use value::Value; diff --git a/acvm-repo/brillig/src/opcodes.rs b/acvm-repo/brillig/src/opcodes.rs index 51df1f90941..78c6ba8097c 100644 --- a/acvm-repo/brillig/src/opcodes.rs +++ b/acvm-repo/brillig/src/opcodes.rs @@ -1,4 +1,5 @@ -use crate::{black_box::BlackBoxOp, Value}; +use crate::black_box::BlackBoxOp; +use acir_field::{AcirField, FieldElement}; use serde::{Deserialize, Serialize}; pub type Label = usize; @@ -22,8 +23,8 @@ impl From for MemoryAddress { /// Describes the memory layout for an array/vector element #[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)] pub enum HeapValueType { - // A single field element is enough to represent the value - Simple, + // A single field element is enough to represent the value with a given bit size + Simple(u32), // The value read should be interpreted as a pointer to a heap array, which // consists of a pointer to a slice of memory of size elements, and a // reference count @@ -36,7 +37,11 @@ pub enum HeapValueType { impl HeapValueType { pub fn all_simple(types: &[HeapValueType]) -> bool { - types.iter().all(|typ| matches!(typ, HeapValueType::Simple)) + types.iter().all(|typ| matches!(typ, HeapValueType::Simple(_))) + } + + pub fn field() -> HeapValueType { + HeapValueType::Simple(FieldElement::max_num_bits()) } } @@ -47,6 +52,12 @@ pub struct HeapArray { pub size: usize, } +impl Default for HeapArray { + fn default() -> Self { + Self { pointer: MemoryAddress(0), size: 0 } + } +} + /// A memory-sized vector passed starting from a Brillig memory location and with a memory-held size #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Copy)] pub struct HeapVector { @@ -78,7 +89,7 @@ pub enum ValueOrArray { } #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -pub enum BrilligOpcode { +pub enum BrilligOpcode { /// Takes the fields in addresses `lhs` and `rhs` /// Performs the specified binary operation /// and stores the value in the `result` address. @@ -131,7 +142,7 @@ pub enum BrilligOpcode { Const { destination: MemoryAddress, bit_size: u32, - value: Value, + value: F, }, Return, /// Used to get data from an outside source. @@ -156,6 +167,13 @@ pub enum BrilligOpcode { destination: MemoryAddress, source: MemoryAddress, }, + /// destination = condition > 0 ? source_a : source_b + ConditionalMov { + destination: MemoryAddress, + source_a: MemoryAddress, + source_b: MemoryAddress, + condition: MemoryAddress, + }, Load { destination: MemoryAddress, source_pointer: MemoryAddress, @@ -165,8 +183,10 @@ pub enum BrilligOpcode { source: MemoryAddress, }, BlackBox(BlackBoxOp), - /// Used to denote execution failure - Trap, + /// Used to denote execution failure, returning data after the offset + Trap { + revert_data: HeapArray, + }, /// Stop execution, returning data after the offset Stop { return_data_offset: usize, @@ -180,9 +200,16 @@ pub enum BinaryFieldOp { Add, Sub, Mul, + /// Field division Div, + /// Integer division + IntegerDiv, /// (==) equal Equals, + /// (<) Field less than + LessThan, + /// (<=) field less or equal + LessThanEquals, } /// Binary fixed-length integer expressions @@ -191,8 +218,7 @@ pub enum BinaryIntOp { Add, Sub, Mul, - SignedDiv, - UnsignedDiv, + Div, /// (==) equal Equals, /// (<) Field less than diff --git a/acvm-repo/brillig/src/value.rs b/acvm-repo/brillig/src/value.rs deleted file mode 100644 index 5a532cbc1a7..00000000000 --- a/acvm-repo/brillig/src/value.rs +++ /dev/null @@ -1,103 +0,0 @@ -use acir_field::FieldElement; -use serde::{Deserialize, Serialize}; -use std::ops::{Add, Div, Mul, Neg, Sub}; - -/// Types of values allowed in the VM -#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, PartialOrd, Ord)] -pub enum Typ { - Field, - Unsigned { bit_size: u32 }, - Signed { bit_size: u32 }, -} - -/// `Value` represents the base descriptor for a value in the VM. -#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] -pub struct Value { - inner: FieldElement, -} - -impl Value { - /// Returns `true` if the `Value` represents `zero` - pub fn is_zero(&self) -> bool { - self.inner.is_zero() - } - - /// Converts `Value` into a `FieldElement`. - pub fn to_field(&self) -> FieldElement { - self.inner - } - - /// Converts `Value` into a `u128`. - // TODO: Check what happens if `Value` cannot fit into a u128 - pub fn to_u128(&self) -> u128 { - self.to_field().to_u128() - } - - /// Converts `Value` into a u64 and then casts it into a usize. - /// Panics: If `Value` cannot fit into a u64 or `Value` does - //// not fit into a usize. - pub fn to_usize(&self) -> usize { - usize::try_from(self.inner.try_to_u64().expect("value does not fit into u64")) - .expect("value does not fit into usize") - } -} - -impl From for Value { - fn from(value: usize) -> Self { - Value { inner: FieldElement::from(value as u128) } - } -} - -impl From for Value { - fn from(value: u128) -> Self { - Value { inner: FieldElement::from(value) } - } -} - -impl From for Value { - fn from(value: FieldElement) -> Self { - Value { inner: value } - } -} - -impl From for Value { - fn from(value: bool) -> Self { - Value { inner: FieldElement::from(value) } - } -} - -impl Add for Value { - type Output = Value; - - fn add(self, rhs: Self) -> Self::Output { - Value { inner: self.inner + rhs.inner } - } -} -impl Sub for Value { - type Output = Value; - - fn sub(self, rhs: Self) -> Self::Output { - Value { inner: self.inner - rhs.inner } - } -} -impl Mul for Value { - type Output = Value; - - fn mul(self, rhs: Self) -> Self::Output { - Value { inner: self.inner * rhs.inner } - } -} -impl Div for Value { - type Output = Value; - - fn div(self, rhs: Self) -> Self::Output { - Value { inner: self.inner / rhs.inner } - } -} -impl Neg for Value { - type Output = Value; - - fn neg(self) -> Self::Output { - Value { inner: -self.inner } - } -} diff --git a/acvm-repo/brillig_vm/Cargo.toml b/acvm-repo/brillig_vm/Cargo.toml index 272e8389413..4735514c9a7 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.40.0" +version = "0.46.0" # x-release-please-end authors.workspace = true edition.workspace = true @@ -17,8 +17,8 @@ acir.workspace = true acvm_blackbox_solver.workspace = true num-bigint.workspace = true num-traits.workspace = true +thiserror.workspace = true [features] -default = ["bn254"] bn254 = ["acir/bn254"] bls12_381 = ["acir/bls12_381"] diff --git a/acvm-repo/brillig_vm/src/arithmetic.rs b/acvm-repo/brillig_vm/src/arithmetic.rs index 9d7b6fe8f02..c88e06e2b94 100644 --- a/acvm-repo/brillig_vm/src/arithmetic.rs +++ b/acvm-repo/brillig_vm/src/arithmetic.rs @@ -1,59 +1,108 @@ use acir::brillig::{BinaryFieldOp, BinaryIntOp}; -use acir::FieldElement; -use num_bigint::{BigInt, BigUint}; -use num_traits::{One, ToPrimitive, Zero}; +use acir::AcirField; +use num_bigint::BigUint; +use num_traits::ToPrimitive; +use num_traits::{One, Zero}; -/// Evaluate a binary operation on two FieldElements and return the result as a FieldElement. -pub(crate) fn evaluate_binary_field_op( +use crate::memory::{MemoryTypeError, MemoryValue}; + +#[derive(Debug, thiserror::Error)] +pub(crate) enum BrilligArithmeticError { + #[error("Bit size for lhs {lhs_bit_size} does not match op bit size {op_bit_size}")] + MismatchedLhsBitSize { lhs_bit_size: u32, op_bit_size: u32 }, + #[error("Bit size for rhs {rhs_bit_size} does not match op bit size {op_bit_size}")] + MismatchedRhsBitSize { rhs_bit_size: u32, op_bit_size: u32 }, + #[error("Integer operation BinaryIntOp::{op:?} is not supported on FieldElement")] + IntegerOperationOnField { op: BinaryIntOp }, + #[error("Shift with bit size {op_bit_size} is invalid")] + InvalidShift { op_bit_size: u32 }, +} + +/// Evaluate a binary operation on two FieldElement memory values. +pub(crate) fn evaluate_binary_field_op( op: &BinaryFieldOp, - a: FieldElement, - b: FieldElement, -) -> FieldElement { - match op { + lhs: MemoryValue, + rhs: MemoryValue, +) -> Result, BrilligArithmeticError> { + let MemoryValue::Field(a) = lhs else { + return Err(BrilligArithmeticError::MismatchedLhsBitSize { + lhs_bit_size: lhs.bit_size(), + op_bit_size: F::max_num_bits(), + }); + }; + let MemoryValue::Field(b) = rhs else { + return Err(BrilligArithmeticError::MismatchedLhsBitSize { + lhs_bit_size: rhs.bit_size(), + op_bit_size: F::max_num_bits(), + }); + }; + + Ok(match op { // Perform addition, subtraction, multiplication, and division based on the BinaryOp variant. - BinaryFieldOp::Add => a + b, - BinaryFieldOp::Sub => a - b, - BinaryFieldOp::Mul => a * b, - BinaryFieldOp::Div => a / b, + BinaryFieldOp::Add => MemoryValue::new_field(a + b), + BinaryFieldOp::Sub => MemoryValue::new_field(a - b), + BinaryFieldOp::Mul => MemoryValue::new_field(a * b), + BinaryFieldOp::Div => MemoryValue::new_field(a / b), + BinaryFieldOp::IntegerDiv => { + let a_big = BigUint::from_bytes_be(&a.to_be_bytes()); + let b_big = BigUint::from_bytes_be(&b.to_be_bytes()); + + let result = a_big / b_big; + MemoryValue::new_field(F::from_be_bytes_reduce(&result.to_bytes_be())) + } BinaryFieldOp::Equals => (a == b).into(), - } + BinaryFieldOp::LessThan => (a < b).into(), + BinaryFieldOp::LessThanEquals => (a <= b).into(), + }) } -/// Evaluate a binary operation on two unsigned big integers with a given bit size and return the result as a big integer. -pub(crate) fn evaluate_binary_bigint_op( +/// Evaluate a binary operation on two unsigned big integers with a given bit size. +pub(crate) fn evaluate_binary_int_op( op: &BinaryIntOp, - a: BigUint, - b: BigUint, + lhs: MemoryValue, + rhs: MemoryValue, bit_size: u32, -) -> Result { +) -> Result, BrilligArithmeticError> { + let lhs = lhs.expect_integer_with_bit_size(bit_size).map_err(|err| match err { + MemoryTypeError::MismatchedBitSize { value_bit_size, expected_bit_size } => { + BrilligArithmeticError::MismatchedLhsBitSize { + lhs_bit_size: value_bit_size, + op_bit_size: expected_bit_size, + } + } + })?; + let rhs_bit_size = + if op == &BinaryIntOp::Shl || op == &BinaryIntOp::Shr { 8 } else { bit_size }; + let rhs = rhs.expect_integer_with_bit_size(rhs_bit_size).map_err(|err| match err { + MemoryTypeError::MismatchedBitSize { value_bit_size, expected_bit_size } => { + BrilligArithmeticError::MismatchedRhsBitSize { + rhs_bit_size: value_bit_size, + op_bit_size: expected_bit_size, + } + } + })?; + + if bit_size == F::max_num_bits() { + return Err(BrilligArithmeticError::IntegerOperationOnField { op: *op }); + } + let bit_modulo = &(BigUint::one() << bit_size); let result = match op { // Perform addition, subtraction, and multiplication, applying a modulo operation to keep the result within the bit size. - BinaryIntOp::Add => (a + b) % bit_modulo, - BinaryIntOp::Sub => (bit_modulo + a - b) % bit_modulo, - BinaryIntOp::Mul => (a * b) % bit_modulo, + BinaryIntOp::Add => (lhs + rhs) % bit_modulo, + BinaryIntOp::Sub => (bit_modulo + lhs - rhs) % bit_modulo, + BinaryIntOp::Mul => (lhs * rhs) % bit_modulo, // Perform unsigned division using the modulo operation on a and b. - BinaryIntOp::UnsignedDiv => { - let b_mod = b % bit_modulo; - if b_mod.is_zero() { + BinaryIntOp::Div => { + if rhs.is_zero() { BigUint::zero() } else { - (a % bit_modulo) / b_mod - } - } - // Perform signed division by first converting a and b to signed integers and then back to unsigned after the operation. - BinaryIntOp::SignedDiv => { - let b_signed = to_big_signed(b, bit_size); - if b_signed.is_zero() { - BigUint::zero() - } else { - let signed_div = to_big_signed(a, bit_size) / b_signed; - to_big_unsigned(signed_div, bit_size) + lhs / rhs } } // Perform a == operation, returning 0 or 1 BinaryIntOp::Equals => { - if (a % bit_modulo) == (b % bit_modulo) { + if lhs == rhs { BigUint::one() } else { BigUint::zero() @@ -61,7 +110,7 @@ pub(crate) fn evaluate_binary_bigint_op( } // Perform a < operation, returning 0 or 1 BinaryIntOp::LessThan => { - if (a % bit_modulo) < (b % bit_modulo) { + if lhs < rhs { BigUint::one() } else { BigUint::zero() @@ -69,51 +118,44 @@ pub(crate) fn evaluate_binary_bigint_op( } // Perform a <= operation, returning 0 or 1 BinaryIntOp::LessThanEquals => { - if (a % bit_modulo) <= (b % bit_modulo) { + if lhs <= rhs { BigUint::one() } else { BigUint::zero() } } // Perform bitwise AND, OR, XOR, left shift, and right shift operations, applying a modulo operation to keep the result within the bit size. - BinaryIntOp::And => (a & b) % bit_modulo, - BinaryIntOp::Or => (a | b) % bit_modulo, - BinaryIntOp::Xor => (a ^ b) % bit_modulo, + BinaryIntOp::And => lhs & rhs, + BinaryIntOp::Or => lhs | rhs, + BinaryIntOp::Xor => lhs ^ rhs, BinaryIntOp::Shl => { - assert!(bit_size <= 128, "unsupported bit size for right shift"); - let b = b.to_u128().unwrap(); - (a << b) % bit_modulo + if bit_size > 128 { + return Err(BrilligArithmeticError::InvalidShift { op_bit_size: bit_size }); + } + let rhs = rhs.to_u128().unwrap(); + (lhs << rhs) % bit_modulo } BinaryIntOp::Shr => { - assert!(bit_size <= 128, "unsupported bit size for right shift"); - let b = b.to_u128().unwrap(); - (a >> b) % bit_modulo + if bit_size > 128 { + return Err(BrilligArithmeticError::InvalidShift { op_bit_size: bit_size }); + } + let rhs = rhs.to_u128().unwrap(); + lhs >> rhs } }; - Ok(result) -} - -fn to_big_signed(a: BigUint, bit_size: u32) -> BigInt { - let pow_2 = BigUint::from(2_u32).pow(bit_size - 1); - if a < pow_2 { - BigInt::from(a) - } else { - BigInt::from(a) - 2 * BigInt::from(pow_2) - } -} - -fn to_big_unsigned(a: BigInt, bit_size: u32) -> BigUint { - if a >= BigInt::zero() { - BigUint::from_bytes_le(&a.to_bytes_le().1) - } else { - BigUint::from(2_u32).pow(bit_size) - BigUint::from_bytes_le(&a.to_bytes_le().1) - } + Ok(match op { + BinaryIntOp::Equals | BinaryIntOp::LessThan | BinaryIntOp::LessThanEquals => { + MemoryValue::new_integer(result, 1) + } + _ => MemoryValue::new_integer(result, bit_size), + }) } #[cfg(test)] mod tests { use super::*; + use acir::{AcirField, FieldElement}; struct TestParams { a: u128, @@ -122,30 +164,15 @@ mod tests { } fn evaluate_u128(op: &BinaryIntOp, a: u128, b: u128, bit_size: u32) -> u128 { - // Convert to big integers - let lhs_big = BigUint::from(a); - let rhs_big = BigUint::from(b); - let result_value = evaluate_binary_bigint_op(op, lhs_big, rhs_big, bit_size).unwrap(); + let result_value: MemoryValue = evaluate_binary_int_op( + op, + MemoryValue::new_integer(a.into(), bit_size), + MemoryValue::new_integer(b.into(), bit_size), + bit_size, + ) + .unwrap(); // Convert back to u128 - result_value.to_u128().unwrap() - } - - fn to_signed(a: u128, bit_size: u32) -> i128 { - assert!(bit_size < 128); - let pow_2 = 2_u128.pow(bit_size - 1); - if a < pow_2 { - a as i128 - } else { - (a.wrapping_sub(2 * pow_2)) as i128 - } - } - - fn to_unsigned(a: i128, bit_size: u32) -> u128 { - if a >= 0 { - a as u128 - } else { - (a + 2_i128.pow(bit_size)) as u128 - } + result_value.to_field().to_u128() } fn to_negative(a: u128, bit_size: u32) -> u128 { @@ -224,26 +251,6 @@ mod tests { let test_ops = vec![TestParams { a: 5, b: 3, result: 1 }, TestParams { a: 5, b: 10, result: 0 }]; - evaluate_int_ops(test_ops, BinaryIntOp::UnsignedDiv, bit_size); - } - - #[test] - fn to_signed_roundtrip() { - let bit_size = 32; - let minus_one = 2_u128.pow(bit_size) - 1; - assert_eq!(to_unsigned(to_signed(minus_one, bit_size), bit_size), minus_one); - } - - #[test] - fn signed_div_test() { - let bit_size = 32; - - let test_ops = vec![ - TestParams { a: 5, b: to_negative(10, bit_size), result: 0 }, - TestParams { a: 5, b: to_negative(1, bit_size), result: to_negative(5, bit_size) }, - TestParams { a: to_negative(5, bit_size), b: to_negative(1, bit_size), result: 5 }, - ]; - - evaluate_int_ops(test_ops, BinaryIntOp::SignedDiv, bit_size); + evaluate_int_ops(test_ops, BinaryIntOp::Div, bit_size); } } diff --git a/acvm-repo/brillig_vm/src/black_box.rs b/acvm-repo/brillig_vm/src/black_box.rs index 73b57b907f3..2053f4e7c86 100644 --- a/acvm-repo/brillig_vm/src/black_box.rs +++ b/acvm-repo/brillig_vm/src/black_box.rs @@ -1,41 +1,69 @@ -use acir::brillig::{BlackBoxOp, HeapArray, HeapVector, Value}; -use acir::{BlackBoxFunc, FieldElement}; +use acir::brillig::{BlackBoxOp, HeapArray, HeapVector}; +use acir::{AcirField, BlackBoxFunc}; +use acvm_blackbox_solver::BigIntSolver; use acvm_blackbox_solver::{ - blake2s, blake3, ecdsa_secp256k1_verify, ecdsa_secp256r1_verify, keccak256, keccakf1600, - sha256, sha256compression, BlackBoxFunctionSolver, BlackBoxResolutionError, + aes128_encrypt, blake2s, blake3, ecdsa_secp256k1_verify, ecdsa_secp256r1_verify, keccak256, + keccakf1600, sha256, sha256compression, BlackBoxFunctionSolver, BlackBoxResolutionError, }; +use num_bigint::BigUint; +use crate::memory::MemoryValue; use crate::Memory; -fn read_heap_vector<'a>(memory: &'a Memory, vector: &HeapVector) -> &'a [Value] { - memory.read_slice(memory.read_ref(vector.pointer), memory.read(vector.size).to_usize()) +fn read_heap_vector<'a, F: AcirField>( + memory: &'a Memory, + vector: &HeapVector, +) -> &'a [MemoryValue] { + let size = memory.read(vector.size); + memory.read_slice(memory.read_ref(vector.pointer), size.to_usize()) } -fn read_heap_array<'a>(memory: &'a Memory, array: &HeapArray) -> &'a [Value] { +fn read_heap_array<'a, F: AcirField>( + memory: &'a Memory, + array: &HeapArray, +) -> &'a [MemoryValue] { memory.read_slice(memory.read_ref(array.pointer), array.size) } /// Extracts the last byte of every value -fn to_u8_vec(inputs: &[Value]) -> Vec { +fn to_u8_vec(inputs: &[MemoryValue]) -> Vec { let mut result = Vec::with_capacity(inputs.len()); for input in inputs { - let field_bytes = input.to_field().to_be_bytes(); - let byte = field_bytes.last().unwrap(); - result.push(*byte); + result.push(input.try_into().unwrap()); } result } -fn to_value_vec(input: &[u8]) -> Vec { - input.iter().map(|x| Value::from(*x as usize)).collect() +fn to_value_vec(input: &[u8]) -> Vec> { + input.iter().map(|&x| x.into()).collect() } -pub(crate) fn evaluate_black_box( +pub(crate) fn evaluate_black_box>( op: &BlackBoxOp, solver: &Solver, - memory: &mut Memory, + memory: &mut Memory, + bigint_solver: &mut BigIntSolver, ) -> Result<(), BlackBoxResolutionError> { match op { + BlackBoxOp::AES128Encrypt { inputs, iv, key, outputs } => { + let bb_func = black_box_function_from_op(op); + + let inputs = to_u8_vec(read_heap_vector(memory, inputs)); + + let iv: [u8; 16] = to_u8_vec(read_heap_array(memory, iv)).try_into().map_err(|_| { + BlackBoxResolutionError::Failed(bb_func, "Invalid iv length".to_string()) + })?; + let key: [u8; 16] = + to_u8_vec(read_heap_array(memory, key)).try_into().map_err(|_| { + BlackBoxResolutionError::Failed(bb_func, "Invalid ley length".to_string()) + })?; + let ciphertext = aes128_encrypt(&inputs, iv, key)?; + + memory.write(outputs.size, ciphertext.len().into()); + memory.write_slice(memory.read_ref(outputs.pointer), &to_value_vec(&ciphertext)); + + Ok(()) + } BlackBoxOp::Sha256 { message, output } => { let message = to_u8_vec(read_heap_vector(memory, message)); let bytes = sha256(message.as_slice())?; @@ -63,14 +91,13 @@ pub(crate) fn evaluate_black_box( BlackBoxOp::Keccakf1600 { message, output } => { let state_vec: Vec = read_heap_vector(memory, message) .iter() - .map(|value| value.to_field().try_to_u64().unwrap()) + .map(|memory_value| memory_value.try_into().unwrap()) .collect(); let state: [u64; 25] = state_vec.try_into().unwrap(); let new_state = keccakf1600(state)?; - let new_state: Vec = - new_state.into_iter().map(|x| Value::from(x as usize)).collect(); + let new_state: Vec> = new_state.into_iter().map(|x| x.into()).collect(); memory.write_slice(memory.read_ref(output.pointer), &new_state); Ok(()) } @@ -125,73 +152,180 @@ pub(crate) fn evaluate_black_box( Ok(()) } BlackBoxOp::SchnorrVerify { public_key_x, public_key_y, message, signature, result } => { - let public_key_x = memory.read(*public_key_x).to_field(); - let public_key_y = memory.read(*public_key_y).to_field(); + let public_key_x = *memory.read(*public_key_x).extract_field().unwrap(); + let public_key_y = *memory.read(*public_key_y).extract_field().unwrap(); let message: Vec = to_u8_vec(read_heap_vector(memory, message)); - let signature: Vec = to_u8_vec(read_heap_vector(memory, signature)); + let signature: [u8; 64] = + to_u8_vec(read_heap_vector(memory, signature)).try_into().unwrap(); let verified = solver.schnorr_verify(&public_key_x, &public_key_y, &signature, &message)?; memory.write(*result, verified.into()); Ok(()) } - BlackBoxOp::FixedBaseScalarMul { low, high, result } => { - let low = memory.read(*low).to_field(); - let high = memory.read(*high).to_field(); - let (x, y) = solver.fixed_base_scalar_mul(&low, &high)?; - memory.write_slice(memory.read_ref(result.pointer), &[x.into(), y.into()]); + BlackBoxOp::MultiScalarMul { points, scalars, outputs: result } => { + let points: Vec = read_heap_vector(memory, points) + .iter() + .enumerate() + .map(|(i, x)| { + if i % 3 == 2 { + let is_infinite: bool = x.try_into().unwrap(); + F::from(is_infinite as u128) + } else { + *x.extract_field().unwrap() + } + }) + .collect(); + let scalars: Vec = read_heap_vector(memory, scalars) + .iter() + .map(|x| *x.extract_field().unwrap()) + .collect(); + let mut scalars_lo = Vec::with_capacity(scalars.len() / 2); + let mut scalars_hi = Vec::with_capacity(scalars.len() / 2); + for (i, scalar) in scalars.iter().enumerate() { + if i % 2 == 0 { + scalars_lo.push(*scalar); + } else { + scalars_hi.push(*scalar); + } + } + let (x, y, is_infinite) = solver.multi_scalar_mul(&points, &scalars_lo, &scalars_hi)?; + memory.write_slice( + memory.read_ref(result.pointer), + &[ + MemoryValue::new_field(x), + MemoryValue::new_field(y), + MemoryValue::new_field(is_infinite), + ], + ); Ok(()) } - BlackBoxOp::EmbeddedCurveAdd { input1_x, input1_y, input2_x, input2_y, result } => { - let input1_x = memory.read(*input1_x).to_field(); - let input1_y = memory.read(*input1_y).to_field(); - let input2_x = memory.read(*input2_x).to_field(); - let input2_y = memory.read(*input2_y).to_field(); - let (x, y) = solver.ec_add(&input1_x, &input1_y, &input2_x, &input2_y)?; - memory.write_slice(memory.read_ref(result.pointer), &[x.into(), y.into()]); + BlackBoxOp::EmbeddedCurveAdd { + input1_x, + input1_y, + input2_x, + input2_y, + result, + input1_infinite, + input2_infinite, + } => { + let input1_x = *memory.read(*input1_x).extract_field().unwrap(); + let input1_y = *memory.read(*input1_y).extract_field().unwrap(); + let input1_infinite: bool = memory.read(*input1_infinite).try_into().unwrap(); + let input2_x = *memory.read(*input2_x).extract_field().unwrap(); + let input2_y = *memory.read(*input2_y).extract_field().unwrap(); + let input2_infinite: bool = memory.read(*input2_infinite).try_into().unwrap(); + let (x, y, infinite) = solver.ec_add( + &input1_x, + &input1_y, + &input1_infinite.into(), + &input2_x, + &input2_y, + &input2_infinite.into(), + )?; + memory.write_slice( + memory.read_ref(result.pointer), + &[ + MemoryValue::new_field(x), + MemoryValue::new_field(y), + MemoryValue::new_field(infinite), + ], + ); Ok(()) } BlackBoxOp::PedersenCommitment { inputs, domain_separator, output } => { - let inputs: Vec = - read_heap_vector(memory, inputs).iter().map(|x| x.to_field()).collect(); + let inputs: Vec = read_heap_vector(memory, inputs) + .iter() + .map(|x| *x.extract_field().unwrap()) + .collect(); let domain_separator: u32 = - memory.read(*domain_separator).to_u128().try_into().map_err(|_| { + memory.read(*domain_separator).try_into().map_err(|_| { BlackBoxResolutionError::Failed( BlackBoxFunc::PedersenCommitment, "Invalid signature length".to_string(), ) })?; let (x, y) = solver.pedersen_commitment(&inputs, domain_separator)?; - memory.write_slice(memory.read_ref(output.pointer), &[x.into(), y.into()]); + memory.write_slice( + memory.read_ref(output.pointer), + &[MemoryValue::new_field(x), MemoryValue::new_field(y)], + ); Ok(()) } BlackBoxOp::PedersenHash { inputs, domain_separator, output } => { - let inputs: Vec = - read_heap_vector(memory, inputs).iter().map(|x| x.to_field()).collect(); + let inputs: Vec = read_heap_vector(memory, inputs) + .iter() + .map(|x| *x.extract_field().unwrap()) + .collect(); let domain_separator: u32 = - memory.read(*domain_separator).to_u128().try_into().map_err(|_| { + memory.read(*domain_separator).try_into().map_err(|_| { BlackBoxResolutionError::Failed( BlackBoxFunc::PedersenCommitment, "Invalid signature length".to_string(), ) })?; let hash = solver.pedersen_hash(&inputs, domain_separator)?; - memory.write(*output, hash.into()); + memory.write(*output, MemoryValue::new_field(hash)); + Ok(()) + } + BlackBoxOp::BigIntAdd { lhs, rhs, output } => { + let lhs = memory.read(*lhs).try_into().unwrap(); + let rhs = memory.read(*rhs).try_into().unwrap(); + let output = memory.read(*output).try_into().unwrap(); + bigint_solver.bigint_op(lhs, rhs, output, BlackBoxFunc::BigIntAdd)?; + Ok(()) + } + BlackBoxOp::BigIntSub { lhs, rhs, output } => { + let lhs = memory.read(*lhs).try_into().unwrap(); + let rhs = memory.read(*rhs).try_into().unwrap(); + let output = memory.read(*output).try_into().unwrap(); + bigint_solver.bigint_op(lhs, rhs, output, BlackBoxFunc::BigIntSub)?; + Ok(()) + } + BlackBoxOp::BigIntMul { lhs, rhs, output } => { + let lhs = memory.read(*lhs).try_into().unwrap(); + let rhs = memory.read(*rhs).try_into().unwrap(); + let output = memory.read(*output).try_into().unwrap(); + bigint_solver.bigint_op(lhs, rhs, output, BlackBoxFunc::BigIntMul)?; + Ok(()) + } + BlackBoxOp::BigIntDiv { lhs, rhs, output } => { + let lhs = memory.read(*lhs).try_into().unwrap(); + let rhs = memory.read(*rhs).try_into().unwrap(); + let output = memory.read(*output).try_into().unwrap(); + bigint_solver.bigint_op(lhs, rhs, output, BlackBoxFunc::BigIntDiv)?; + Ok(()) + } + BlackBoxOp::BigIntFromLeBytes { inputs, modulus, output } => { + let input = read_heap_vector(memory, inputs); + let input: Vec = input.iter().map(|x| x.try_into().unwrap()).collect(); + let modulus = read_heap_vector(memory, modulus); + let modulus: Vec = modulus.iter().map(|x| x.try_into().unwrap()).collect(); + let output = memory.read(*output).try_into().unwrap(); + bigint_solver.bigint_from_bytes(&input, &modulus, output)?; + Ok(()) + } + BlackBoxOp::BigIntToLeBytes { input, output } => { + let input: u32 = memory.read(*input).try_into().unwrap(); + let bytes = bigint_solver.bigint_to_bytes(input)?; + let mut values = Vec::new(); + for i in 0..32 { + if i < bytes.len() { + values.push(bytes[i].into()); + } else { + values.push(0_u8.into()); + } + } + memory.write_slice(memory.read_ref(output.pointer), &values); Ok(()) } - BlackBoxOp::BigIntAdd { .. } => todo!(), - BlackBoxOp::BigIntSub { .. } => todo!(), - BlackBoxOp::BigIntMul { .. } => todo!(), - BlackBoxOp::BigIntDiv { .. } => todo!(), - BlackBoxOp::BigIntFromLeBytes { .. } => todo!(), - BlackBoxOp::BigIntToLeBytes { .. } => todo!(), BlackBoxOp::Poseidon2Permutation { message, output, len } => { let input = read_heap_vector(memory, message); - let input: Vec = input.iter().map(|x| x.to_field()).collect(); - let len = memory.read(*len).to_u128() as u32; + let input: Vec = input.iter().map(|x| *x.extract_field().unwrap()).collect(); + let len = memory.read(*len).try_into().unwrap(); let result = solver.poseidon2_permutation(&input, len)?; let mut values = Vec::new(); for i in result { - values.push(Value::from(i)); + values.push(MemoryValue::new_field(i)); } memory.write_slice(memory.read_ref(output.pointer), &values); Ok(()) @@ -206,7 +340,7 @@ pub(crate) fn evaluate_black_box( )); } for (i, input) in inputs.iter().enumerate() { - message[i] = input.to_u128() as u32; + message[i] = input.try_into().unwrap(); } let mut state = [0; 8]; let values = read_heap_vector(memory, hash_values); @@ -217,20 +351,39 @@ pub(crate) fn evaluate_black_box( )); } for (i, value) in values.iter().enumerate() { - state[i] = value.to_u128() as u32; + state[i] = value.try_into().unwrap(); } sha256compression(&mut state, &message); - let state = state.map(|x| Value::from(x as u128)); + let state = state.map(|x| x.into()); memory.write_slice(memory.read_ref(output.pointer), &state); Ok(()) } + BlackBoxOp::ToRadix { input, radix, output } => { + let input: F = *memory.read(*input).extract_field().expect("ToRadix input not a field"); + + let mut input = BigUint::from_bytes_be(&input.to_be_bytes()); + let radix = BigUint::from(*radix); + + let mut limbs: Vec> = Vec::with_capacity(output.size); + + for _ in 0..output.size { + let limb = &input % &radix; + limbs.push(MemoryValue::new_field(F::from_be_bytes_reduce(&limb.to_bytes_be()))); + input /= &radix; + } + + memory.write_slice(memory.read_ref(output.pointer), &limbs); + + Ok(()) + } } } fn black_box_function_from_op(op: &BlackBoxOp) -> BlackBoxFunc { match op { + BlackBoxOp::AES128Encrypt { .. } => BlackBoxFunc::AES128Encrypt, BlackBoxOp::Sha256 { .. } => BlackBoxFunc::SHA256, BlackBoxOp::Blake2s { .. } => BlackBoxFunc::Blake2s, BlackBoxOp::Blake3 { .. } => BlackBoxFunc::Blake3, @@ -241,7 +394,7 @@ fn black_box_function_from_op(op: &BlackBoxOp) -> BlackBoxFunc { BlackBoxOp::SchnorrVerify { .. } => BlackBoxFunc::SchnorrVerify, BlackBoxOp::PedersenCommitment { .. } => BlackBoxFunc::PedersenCommitment, BlackBoxOp::PedersenHash { .. } => BlackBoxFunc::PedersenHash, - BlackBoxOp::FixedBaseScalarMul { .. } => BlackBoxFunc::FixedBaseScalarMul, + BlackBoxOp::MultiScalarMul { .. } => BlackBoxFunc::MultiScalarMul, BlackBoxOp::EmbeddedCurveAdd { .. } => BlackBoxFunc::EmbeddedCurveAdd, BlackBoxOp::BigIntAdd { .. } => BlackBoxFunc::BigIntAdd, BlackBoxOp::BigIntSub { .. } => BlackBoxFunc::BigIntSub, @@ -251,16 +404,21 @@ fn black_box_function_from_op(op: &BlackBoxOp) -> BlackBoxFunc { BlackBoxOp::BigIntToLeBytes { .. } => BlackBoxFunc::BigIntToLeBytes, BlackBoxOp::Poseidon2Permutation { .. } => BlackBoxFunc::Poseidon2Permutation, BlackBoxOp::Sha256Compression { .. } => BlackBoxFunc::Sha256Compression, + BlackBoxOp::ToRadix { .. } => unreachable!("ToRadix is not an ACIR BlackBoxFunc"), } } #[cfg(test)] mod test { - use acir::brillig::{BlackBoxOp, MemoryAddress}; + use acir::{ + brillig::{BlackBoxOp, MemoryAddress}, + FieldElement, + }; + use acvm_blackbox_solver::{BigIntSolver, StubbedBlackBoxSolver}; use crate::{ black_box::{evaluate_black_box, to_u8_vec, to_value_vec}, - DummyBlackBoxSolver, HeapArray, HeapVector, Memory, + HeapArray, HeapVector, Memory, }; #[test] @@ -268,7 +426,7 @@ mod test { let message: Vec = b"hello world".to_vec(); let message_length = message.len(); - let mut memory = Memory::default(); + let mut memory: Memory = Memory::default(); let message_pointer = 3; let result_pointer = message_pointer + message_length; memory.write(MemoryAddress(0), message_pointer.into()); @@ -281,7 +439,8 @@ mod test { output: HeapArray { pointer: 2.into(), size: 32 }, }; - evaluate_black_box(&op, &DummyBlackBoxSolver, &mut memory).unwrap(); + evaluate_black_box(&op, &StubbedBlackBoxSolver, &mut memory, &mut BigIntSolver::default()) + .unwrap(); let result = memory.read_slice(MemoryAddress(result_pointer), 32); diff --git a/acvm-repo/brillig_vm/src/lib.rs b/acvm-repo/brillig_vm/src/lib.rs index c7bf014f068..da9a34f1044 100644 --- a/acvm-repo/brillig_vm/src/lib.rs +++ b/acvm-repo/brillig_vm/src/lib.rs @@ -13,35 +13,40 @@ use acir::brillig::{ BinaryFieldOp, BinaryIntOp, ForeignCallParam, ForeignCallResult, HeapArray, HeapValueType, - HeapVector, MemoryAddress, Opcode, Value, ValueOrArray, + HeapVector, MemoryAddress, Opcode, ValueOrArray, }; -use acir::FieldElement; +use acir::AcirField; +use acvm_blackbox_solver::{BigIntSolver, BlackBoxFunctionSolver}; +use arithmetic::{evaluate_binary_field_op, evaluate_binary_int_op, BrilligArithmeticError}; +use black_box::evaluate_black_box; +use num_bigint::BigUint; + // Re-export `brillig`. pub use acir::brillig; +pub use memory::{Memory, MemoryValue, MEMORY_ADDRESSING_BIT_SIZE}; mod arithmetic; mod black_box; mod memory; -use acvm_blackbox_solver::{BlackBoxFunctionSolver, BlackBoxResolutionError}; -use arithmetic::{evaluate_binary_bigint_op, evaluate_binary_field_op}; -use black_box::evaluate_black_box; - -pub use memory::Memory; -use num_bigint::BigUint; - /// The error call stack contains the opcode indexes of the call stack at the time of failure, plus the index of the opcode that failed. pub type ErrorCallStack = Vec; #[derive(Debug, PartialEq, Eq, Clone)] -pub enum VMStatus { +pub enum FailureReason { + Trap { revert_data_offset: usize, revert_data_size: usize }, + RuntimeError { message: String }, +} + +#[derive(Debug, PartialEq, Eq, Clone)] +pub enum VMStatus { Finished { return_data_offset: usize, return_data_size: usize, }, InProgress, Failure { - message: String, + reason: FailureReason, call_stack: ErrorCallStack, }, /// The VM process is not solvable as a [foreign call][Opcode::ForeignCall] has been @@ -55,15 +60,15 @@ pub enum VMStatus { function: String, /// Input values /// Each input is a list of values as an input can be either a single value or a memory pointer - inputs: Vec, + inputs: Vec>, }, } #[derive(Debug, PartialEq, Eq, Clone)] /// VM encapsulates the state of the Brillig VM during execution. -pub struct VM<'a, B: BlackBoxFunctionSolver> { +pub struct VM<'a, F, B: BlackBoxFunctionSolver> { /// Calldata to the brillig function - calldata: Vec, + calldata: Vec, /// Instruction pointer program_counter: usize, /// A counter maintained throughout a Brillig process that determines @@ -71,25 +76,27 @@ pub struct VM<'a, B: BlackBoxFunctionSolver> { foreign_call_counter: usize, /// Represents the outputs of all foreign calls during a Brillig process /// List is appended onto by the caller upon reaching a [VMStatus::ForeignCallWait] - foreign_call_results: Vec, + foreign_call_results: Vec>, /// Executable opcodes - bytecode: &'a [Opcode], + bytecode: &'a [Opcode], /// Status of the VM - status: VMStatus, + status: VMStatus, /// Memory of the VM - memory: Memory, + memory: Memory, /// Call stack - call_stack: Vec, + call_stack: Vec, /// The solver for blackbox functions black_box_solver: &'a B, + // The solver for big integers + bigint_solver: BigIntSolver, } -impl<'a, B: BlackBoxFunctionSolver> VM<'a, B> { +impl<'a, F: AcirField, B: BlackBoxFunctionSolver> VM<'a, F, B> { /// Constructs a new VM instance pub fn new( - calldata: Vec, - bytecode: &'a [Opcode], - foreign_call_results: Vec, + calldata: Vec, + bytecode: &'a [Opcode], + foreign_call_results: Vec>, black_box_solver: &'a B, ) -> Self { Self { @@ -102,22 +109,23 @@ impl<'a, B: BlackBoxFunctionSolver> VM<'a, B> { memory: Memory::default(), call_stack: Vec::new(), black_box_solver, + bigint_solver: Default::default(), } } /// Updates the current status of the VM. /// Returns the given status. - fn status(&mut self, status: VMStatus) -> VMStatus { + fn status(&mut self, status: VMStatus) -> VMStatus { self.status = status.clone(); status } - pub fn get_status(&self) -> VMStatus { + pub fn get_status(&self) -> VMStatus { self.status.clone() } /// Sets the current status of the VM to Finished (completed execution). - fn finish(&mut self, return_data_offset: usize, return_data_size: usize) -> VMStatus { + fn finish(&mut self, return_data_offset: usize, return_data_size: usize) -> VMStatus { self.status(VMStatus::Finished { return_data_offset, return_data_size }) } @@ -126,12 +134,12 @@ impl<'a, B: BlackBoxFunctionSolver> VM<'a, B> { fn wait_for_foreign_call( &mut self, function: String, - inputs: Vec, - ) -> VMStatus { + inputs: Vec>, + ) -> VMStatus { self.status(VMStatus::ForeignCallWait { function, inputs }) } - pub fn resolve_foreign_call(&mut self, foreign_call_result: ForeignCallResult) { + pub fn resolve_foreign_call(&mut self, foreign_call_result: ForeignCallResult) { if self.foreign_call_counter < self.foreign_call_results.len() { panic!("No unresolved foreign calls"); } @@ -139,19 +147,33 @@ impl<'a, B: BlackBoxFunctionSolver> VM<'a, B> { self.status(VMStatus::InProgress); } + fn get_error_stack(&self) -> Vec { + let mut error_stack: Vec<_> = self.call_stack.clone(); + error_stack.push(self.program_counter); + error_stack + } + /// Sets the current status of the VM to `fail`. /// Indicating that the VM encountered a `Trap` Opcode /// or an invalid state. - fn fail(&mut self, message: String) -> VMStatus { - let mut error_stack: Vec<_> = - self.call_stack.iter().map(|value| value.to_usize()).collect(); - error_stack.push(self.program_counter); - self.status(VMStatus::Failure { call_stack: error_stack, message }); + fn trap(&mut self, revert_data_offset: usize, revert_data_size: usize) -> VMStatus { + self.status(VMStatus::Failure { + call_stack: self.get_error_stack(), + reason: FailureReason::Trap { revert_data_offset, revert_data_size }, + }); + self.status.clone() + } + + fn fail(&mut self, message: String) -> VMStatus { + self.status(VMStatus::Failure { + call_stack: self.get_error_stack(), + reason: FailureReason::RuntimeError { message }, + }); self.status.clone() } /// Loop over the bytecode and update the program counter - pub fn process_opcodes(&mut self) -> VMStatus { + pub fn process_opcodes(&mut self) -> VMStatus { while !matches!( self.process_opcode(), VMStatus::Finished { .. } | VMStatus::Failure { .. } | VMStatus::ForeignCallWait { .. } @@ -159,36 +181,35 @@ impl<'a, B: BlackBoxFunctionSolver> VM<'a, B> { self.status.clone() } - pub fn get_memory(&self) -> &[Value] { + pub fn get_memory(&self) -> &[MemoryValue] { self.memory.values() } - pub fn write_memory_at(&mut self, ptr: usize, value: Value) { + pub fn write_memory_at(&mut self, ptr: usize, value: MemoryValue) { self.memory.write(MemoryAddress(ptr), value); } /// Returns the VM's current call stack, including the actual program /// counter in the last position of the returned vector. pub fn get_call_stack(&self) -> Vec { - self.call_stack - .iter() - .map(|program_counter| program_counter.to_usize()) - .chain(std::iter::once(self.program_counter)) - .collect() + self.call_stack.iter().copied().chain(std::iter::once(self.program_counter)).collect() } /// Process a single opcode and modify the program counter. - pub fn process_opcode(&mut self) -> VMStatus { + pub fn process_opcode(&mut self) -> VMStatus { let opcode = &self.bytecode[self.program_counter]; match opcode { Opcode::BinaryFieldOp { op, lhs, rhs, destination: result } => { - self.process_binary_field_op(*op, *lhs, *rhs, *result); - self.increment_program_counter() + if let Err(error) = self.process_binary_field_op(*op, *lhs, *rhs, *result) { + self.fail(error.to_string()) + } else { + self.increment_program_counter() + } } Opcode::BinaryIntOp { op, bit_size, lhs, rhs, destination: result } => { if let Err(error) = self.process_binary_int_op(*op, *bit_size, *lhs, *rhs, *result) { - self.fail(error) + self.fail(error.to_string()) } else { self.increment_program_counter() } @@ -204,26 +225,29 @@ impl<'a, B: BlackBoxFunctionSolver> VM<'a, B> { // Check if condition is true // We use 0 to mean false and any other value to mean true let condition_value = self.memory.read(*condition); - if !condition_value.is_zero() { + if condition_value.try_into().expect("condition value is not a boolean") { return self.set_program_counter(*destination); } self.increment_program_counter() } Opcode::JumpIfNot { condition, location: destination } => { let condition_value = self.memory.read(*condition); - if condition_value.is_zero() { - return self.set_program_counter(*destination); + if condition_value.try_into().expect("condition value is not a boolean") { + return self.increment_program_counter(); } - self.increment_program_counter() + self.set_program_counter(*destination) } Opcode::CalldataCopy { destination_address, size, offset } => { - let values = &self.calldata[*offset..(*offset + size)]; - self.memory.write_slice(*destination_address, values); + let values: Vec<_> = self.calldata[*offset..(*offset + size)] + .iter() + .map(|value| MemoryValue::new_field(*value)) + .collect(); + self.memory.write_slice(*destination_address, &values); self.increment_program_counter() } Opcode::Return => { if let Some(return_location) = self.call_stack.pop() { - self.set_program_counter(return_location.to_usize() + 1) + self.set_program_counter(return_location + 1) } else { self.fail("return opcode hit, but callstack already empty".to_string()) } @@ -254,81 +278,14 @@ impl<'a, B: BlackBoxFunctionSolver> VM<'a, B> { return self.wait_for_foreign_call(function.clone(), resolved_inputs); } - let values = &self.foreign_call_results[self.foreign_call_counter].values; + let write_result = self.write_foreign_call_result( + destinations, + destination_value_types, + self.foreign_call_counter, + ); - let mut invalid_foreign_call_result = false; - for ((destination, value_type), output) in - destinations.iter().zip(destination_value_types).zip(values) - { - match (destination, value_type) { - (ValueOrArray::MemoryAddress(value_index), HeapValueType::Simple) => { - match output { - ForeignCallParam::Single(value) => { - self.memory.write(*value_index, *value); - } - _ => unreachable!( - "Function result size does not match brillig bytecode. Expected 1 result but got {output:?}" - ), - } - } - ( - ValueOrArray::HeapArray(HeapArray { pointer: pointer_index, size }), - HeapValueType::Array { value_types, size: type_size }, - ) if size == type_size => { - if HeapValueType::all_simple(value_types) { - match output { - ForeignCallParam::Array(values) => { - if values.len() != *size { - invalid_foreign_call_result = true; - break; - } - // Convert the destination pointer to a usize - let destination = self.memory.read_ref(*pointer_index); - // Write to our destination memory - self.memory.write_slice(destination, values); - } - _ => { - unreachable!("Function result size does not match brillig bytecode size") - } - } - } else { - unimplemented!("deflattening heap arrays from foreign calls"); - } - } - ( - ValueOrArray::HeapVector(HeapVector {pointer: pointer_index, size: size_index }), - HeapValueType::Vector { value_types }, - ) => { - if HeapValueType::all_simple(value_types) { - match output { - ForeignCallParam::Array(values) => { - // Set our size in the size address - self.memory.write(*size_index, Value::from(values.len())); - // Convert the destination pointer to a usize - let destination = self.memory.read_ref(*pointer_index); - // Write to our destination memory - self.memory.write_slice(destination, values); - } - _ => { - unreachable!("Function result size does not match brillig bytecode size") - } - } - } else { - unimplemented!("deflattening heap vectors from foreign calls"); - } - } - _ => { - unreachable!("Unexpected value type {value_type:?} for destination {destination:?}"); - } - } - } - - // These checks must come after resolving the foreign call outputs as `fail` uses a mutable reference - if destinations.len() != values.len() { - self.fail(format!("{} output values were provided as a foreign call result for {} destination slots", values.len(), destinations.len())); - } - if invalid_foreign_call_result { - self.fail("Function result size does not match brillig bytecode".to_owned()); + if let Err(e) = write_result { + return self.fail(e); } self.foreign_call_counter += 1; @@ -339,7 +296,22 @@ impl<'a, B: BlackBoxFunctionSolver> VM<'a, B> { self.memory.write(*destination_address, source_value); self.increment_program_counter() } - Opcode::Trap => self.fail("explicit trap hit in brillig".to_string()), + Opcode::ConditionalMov { destination, source_a, source_b, condition } => { + let condition_value = self.memory.read(*condition); + if condition_value.try_into().expect("condition value is not a boolean") { + self.memory.write(*destination, self.memory.read(*source_a)); + } else { + self.memory.write(*destination, self.memory.read(*source_b)); + } + self.increment_program_counter() + } + Opcode::Trap { revert_data } => { + if revert_data.size > 0 { + self.trap(self.memory.read_ref(revert_data.pointer).0, revert_data.size) + } else { + self.trap(0, 0) + } + } Opcode::Stop { return_data_offset, return_data_size } => { self.finish(*return_data_offset, *return_data_size) } @@ -347,8 +319,8 @@ impl<'a, B: BlackBoxFunctionSolver> VM<'a, B> { // Convert our source_pointer to an address let source = self.memory.read_ref(*source_pointer); // Use our usize source index to lookup the value in memory - let value = &self.memory.read(source); - self.memory.write(*destination_address, *value); + let value = self.memory.read(source); + self.memory.write(*destination_address, value); self.increment_program_counter() } Opcode::Store { destination_pointer, source: source_address } => { @@ -360,15 +332,21 @@ impl<'a, B: BlackBoxFunctionSolver> VM<'a, B> { } Opcode::Call { location } => { // Push a return location - self.call_stack.push(Value::from(self.program_counter)); + self.call_stack.push(self.program_counter); self.set_program_counter(*location) } - Opcode::Const { destination, value, bit_size: _ } => { - self.memory.write(*destination, *value); + Opcode::Const { destination, value, bit_size } => { + // Consts are not checked in runtime to fit in the bit size, since they can safely be checked statically. + self.memory.write(*destination, MemoryValue::new_from_field(*value, *bit_size)); self.increment_program_counter() } Opcode::BlackBox(black_box_op) => { - match evaluate_black_box(black_box_op, self.black_box_solver, &mut self.memory) { + match evaluate_black_box( + black_box_op, + self.black_box_solver, + &mut self.memory, + &mut self.bigint_solver, + ) { Ok(()) => self.increment_program_counter(), Err(e) => self.fail(e.to_string()), } @@ -382,14 +360,14 @@ impl<'a, B: BlackBoxFunctionSolver> VM<'a, B> { } /// Increments the program counter by 1. - fn increment_program_counter(&mut self) -> VMStatus { + fn increment_program_counter(&mut self) -> VMStatus { self.set_program_counter(self.program_counter + 1) } /// Increments the program counter by `value`. /// If the program counter no longer points to an opcode /// in the bytecode, then the VMStatus reports halted. - fn set_program_counter(&mut self, value: usize) -> VMStatus { + fn set_program_counter(&mut self, value: usize) -> VMStatus { assert!(self.program_counter < self.bytecode.len()); self.program_counter = value; if self.program_counter >= self.bytecode.len() { @@ -402,17 +380,21 @@ impl<'a, B: BlackBoxFunctionSolver> VM<'a, B> { &self, input: ValueOrArray, value_type: &HeapValueType, - ) -> ForeignCallParam { + ) -> ForeignCallParam { match (input, value_type) { - (ValueOrArray::MemoryAddress(value_index), HeapValueType::Simple) => { - self.memory.read(value_index).into() + (ValueOrArray::MemoryAddress(value_index), HeapValueType::Simple(_)) => { + ForeignCallParam::Single(self.memory.read(value_index).to_field()) } ( ValueOrArray::HeapArray(HeapArray { pointer: pointer_index, size }), HeapValueType::Array { value_types, size: type_size }, ) if *type_size == size => { let start = self.memory.read_ref(pointer_index); - self.read_slice_of_values_from_memory(start, size, value_types).into() + self.read_slice_of_values_from_memory(start, size, value_types) + .into_iter() + .map(|mem_value| mem_value.to_field()) + .collect::>() + .into() } ( ValueOrArray::HeapVector(HeapVector { pointer: pointer_index, size: size_index }), @@ -420,7 +402,11 @@ impl<'a, B: BlackBoxFunctionSolver> VM<'a, B> { ) => { let start = self.memory.read_ref(pointer_index); let size = self.memory.read(size_index).to_usize(); - self.read_slice_of_values_from_memory(start, size, value_types).into() + self.read_slice_of_values_from_memory(start, size, value_types) + .into_iter() + .map(|mem_value| mem_value.to_field()) + .collect::>() + .into() } _ => { unreachable!("Unexpected value type {value_type:?} for input {input:?}"); @@ -435,7 +421,7 @@ impl<'a, B: BlackBoxFunctionSolver> VM<'a, B> { start: MemoryAddress, size: usize, value_types: &[HeapValueType], - ) -> Vec { + ) -> Vec> { if HeapValueType::all_simple(value_types) { self.memory.read_slice(start, size).to_vec() } else { @@ -450,9 +436,8 @@ impl<'a, B: BlackBoxFunctionSolver> VM<'a, B> { .flat_map(|(i, value_type)| { let value_address: MemoryAddress = (start.to_usize() + i).into(); match value_type { - HeapValueType::Simple => { - let value = self.memory.read(value_address); - vec![value] + HeapValueType::Simple(_) => { + vec![self.memory.read(value_address)] } HeapValueType::Array { value_types, size } => { let array_address = self.memory.read_ref(value_address); @@ -477,6 +462,140 @@ impl<'a, B: BlackBoxFunctionSolver> VM<'a, B> { } } + fn write_foreign_call_result( + &mut self, + destinations: &[ValueOrArray], + destination_value_types: &[HeapValueType], + foreign_call_index: usize, + ) -> Result<(), String> { + let values = std::mem::take(&mut self.foreign_call_results[foreign_call_index].values); + + if destinations.len() != values.len() { + return Err(format!( + "{} output values were provided as a foreign call result for {} destination slots", + values.len(), + destinations.len() + )); + } + + for ((destination, value_type), output) in + destinations.iter().zip(destination_value_types).zip(&values) + { + match (destination, value_type) { + (ValueOrArray::MemoryAddress(value_index), HeapValueType::Simple(bit_size)) => { + match output { + ForeignCallParam::Single(value) => { + self.write_value_to_memory(*value_index, value, *bit_size)?; + } + _ => return Err(format!( + "Function result size does not match brillig bytecode. Expected 1 result but got {output:?}") + ), + } + } + ( + ValueOrArray::HeapArray(HeapArray { pointer: pointer_index, size }), + HeapValueType::Array { value_types, size: type_size }, + ) if size == type_size => { + if HeapValueType::all_simple(value_types) { + match output { + ForeignCallParam::Array(values) => { + if values.len() != *size { + return Err("Foreign call result array doesn't match expected size".to_string()); + } + self.write_values_to_memory_slice(*pointer_index, values, value_types)?; + } + _ => { + return Err("Function result size does not match brillig bytecode size".to_string()); + } + } + } else { + unimplemented!("deflattening heap arrays from foreign calls"); + } + } + ( + ValueOrArray::HeapVector(HeapVector {pointer: pointer_index, size: size_index }), + HeapValueType::Vector { value_types }, + ) => { + if HeapValueType::all_simple(value_types) { + match output { + ForeignCallParam::Array(values) => { + // Set our size in the size address + self.memory.write(*size_index, values.len().into()); + + self.write_values_to_memory_slice(*pointer_index, values, value_types)?; + } + _ => { + return Err("Function result size does not match brillig bytecode size".to_string()); + } + } + } else { + unimplemented!("deflattening heap vectors from foreign calls"); + } + } + _ => { + return Err(format!("Unexpected value type {value_type:?} for destination {destination:?}")); + } + } + } + + let _ = + std::mem::replace(&mut self.foreign_call_results[foreign_call_index].values, values); + + Ok(()) + } + + fn write_value_to_memory( + &mut self, + destination: MemoryAddress, + value: &F, + value_bit_size: u32, + ) -> Result<(), String> { + let memory_value = MemoryValue::new_checked(*value, value_bit_size); + + if let Some(memory_value) = memory_value { + self.memory.write(destination, memory_value); + } else { + return Err(format!( + "Foreign call result value {} does not fit in bit size {}", + value, value_bit_size + )); + } + Ok(()) + } + + fn write_values_to_memory_slice( + &mut self, + pointer_index: MemoryAddress, + values: &[F], + value_types: &[HeapValueType], + ) -> Result<(), String> { + let bit_sizes_iterator = value_types + .iter() + .map(|typ| match typ { + HeapValueType::Simple(bit_size) => *bit_size, + _ => unreachable!("Expected simple value type"), + }) + .cycle(); + + // Convert the destination pointer to a usize + let destination = self.memory.read_ref(pointer_index); + // Write to our destination memory + let memory_values: Option> = values + .iter() + .zip(bit_sizes_iterator) + .map(|(value, bit_size)| MemoryValue::new_checked(*value, bit_size)) + .collect(); + if let Some(memory_values) = memory_values { + self.memory.write_slice(destination, &memory_values); + } else { + return Err(format!( + "Foreign call result values {:?} do not match expected bit sizes", + values, + )); + } + Ok(()) + } + /// Process a binary operation. /// This method will not modify the program counter. fn process_binary_field_op( @@ -485,14 +604,15 @@ impl<'a, B: BlackBoxFunctionSolver> VM<'a, B> { lhs: MemoryAddress, rhs: MemoryAddress, result: MemoryAddress, - ) { + ) -> Result<(), BrilligArithmeticError> { let lhs_value = self.memory.read(lhs); let rhs_value = self.memory.read(rhs); - let result_value = - evaluate_binary_field_op(&op, lhs_value.to_field(), rhs_value.to_field()); + let result_value = evaluate_binary_field_op(&op, lhs_value, rhs_value)?; - self.memory.write(result, result_value.into()); + self.memory.write(result, result_value); + + Ok(()) } /// Process a binary operation. @@ -504,86 +624,34 @@ impl<'a, B: BlackBoxFunctionSolver> VM<'a, B> { lhs: MemoryAddress, rhs: MemoryAddress, result: MemoryAddress, - ) -> Result<(), String> { + ) -> Result<(), BrilligArithmeticError> { let lhs_value = self.memory.read(lhs); let rhs_value = self.memory.read(rhs); - // Convert to big integers - let lhs_big = BigUint::from_bytes_be(&lhs_value.to_field().to_be_bytes()); - let rhs_big = BigUint::from_bytes_be(&rhs_value.to_field().to_be_bytes()); - let result_value = evaluate_binary_bigint_op(&op, lhs_big, rhs_big, bit_size)?; - // Convert back to field element - self.memory - .write(result, FieldElement::from_be_bytes_reduce(&result_value.to_bytes_be()).into()); + let result_value = evaluate_binary_int_op(&op, lhs_value, rhs_value, bit_size)?; + self.memory.write(result, result_value); Ok(()) } /// Casts a value to a different bit size. - fn cast(&self, bit_size: u32, value: Value) -> Value { - let lhs_big = BigUint::from_bytes_be(&value.to_field().to_be_bytes()); + fn cast(&self, bit_size: u32, source_value: MemoryValue) -> MemoryValue { + let lhs_big = source_value.to_integer(); let mask = BigUint::from(2_u32).pow(bit_size) - 1_u32; - FieldElement::from_be_bytes_reduce(&(lhs_big & mask).to_bytes_be()).into() - } -} - -pub(crate) struct DummyBlackBoxSolver; - -impl BlackBoxFunctionSolver for DummyBlackBoxSolver { - fn schnorr_verify( - &self, - _public_key_x: &FieldElement, - _public_key_y: &FieldElement, - _signature: &[u8], - _message: &[u8], - ) -> Result { - Ok(true) - } - fn pedersen_commitment( - &self, - _inputs: &[FieldElement], - _domain_separator: u32, - ) -> Result<(FieldElement, FieldElement), BlackBoxResolutionError> { - Ok((2_u128.into(), 3_u128.into())) - } - fn pedersen_hash( - &self, - _inputs: &[FieldElement], - _domain_separator: u32, - ) -> Result { - Ok(6_u128.into()) - } - fn fixed_base_scalar_mul( - &self, - _low: &FieldElement, - _high: &FieldElement, - ) -> Result<(FieldElement, FieldElement), BlackBoxResolutionError> { - Ok((4_u128.into(), 5_u128.into())) - } - fn ec_add( - &self, - _input1_x: &FieldElement, - _input1_y: &FieldElement, - _input2_x: &FieldElement, - _input2_y: &FieldElement, - ) -> Result<(FieldElement, FieldElement), BlackBoxResolutionError> { - Ok((5_u128.into(), 6_u128.into())) - } - fn poseidon2_permutation( - &self, - _input: &[FieldElement], - len: u32, - ) -> Result, BlackBoxResolutionError> { - Ok(vec![0_u128.into(); len as usize]) + MemoryValue::new_from_integer(lhs_big & mask, bit_size) } } #[cfg(test)] mod tests { + use acir::{AcirField, FieldElement}; + use acvm_blackbox_solver::StubbedBlackBoxSolver; + const BRILLIG_MEMORY_ADDRESSING_BIT_SIZE: u32 = 32; + use super::*; #[test] fn add_single_step_smoke() { - let calldata = vec![Value::from(27u128)]; + let calldata = vec![FieldElement::from(27u128)]; // Add opcode to add the value in address `0` and `1` // and place the output in address `2` @@ -595,7 +663,7 @@ mod tests { // Start VM let opcodes = [calldata_copy]; - let mut vm = VM::new(calldata, &opcodes, vec![], &DummyBlackBoxSolver); + let mut vm = VM::new(calldata, &opcodes, vec![], &StubbedBlackBoxSolver); // Process a single VM opcode // @@ -609,21 +677,21 @@ mod tests { let VM { memory, .. } = vm; let output_value = memory.read(MemoryAddress::from(0)); - assert_eq!(output_value, Value::from(27u128)); + assert_eq!(output_value.to_field(), FieldElement::from(27u128)); } #[test] fn jmpif_opcode() { - let mut calldata = vec![]; + let mut calldata: Vec = vec![]; let mut opcodes = vec![]; let lhs = { - calldata.push(Value::from(2u128)); + calldata.push(2u128.into()); MemoryAddress::from(calldata.len() - 1) }; let rhs = { - calldata.push(Value::from(2u128)); + calldata.push(2u128.into()); MemoryAddress::from(calldata.len() - 1) }; @@ -634,13 +702,12 @@ mod tests { size: 2, offset: 0, }); - let equal_cmp_opcode = - Opcode::BinaryIntOp { op: BinaryIntOp::Equals, bit_size: 1, lhs, rhs, destination }; - opcodes.push(equal_cmp_opcode); + + opcodes.push(Opcode::BinaryFieldOp { destination, op: BinaryFieldOp::Equals, lhs, rhs }); opcodes.push(Opcode::Jump { location: 3 }); - opcodes.push(Opcode::JumpIf { condition: MemoryAddress::from(2), location: 4 }); + opcodes.push(Opcode::JumpIf { condition: destination, location: 4 }); - let mut vm = VM::new(calldata, &opcodes, vec![], &DummyBlackBoxSolver); + let mut vm = VM::new(calldata, &opcodes, vec![], &StubbedBlackBoxSolver); let status = vm.process_opcode(); assert_eq!(status, VMStatus::InProgress); @@ -648,8 +715,8 @@ mod tests { let status = vm.process_opcode(); assert_eq!(status, VMStatus::InProgress); - let output_cmp_value = vm.memory.read(MemoryAddress::from(2)); - assert_eq!(output_cmp_value, Value::from(true)); + let output_cmp_value = vm.memory.read(destination); + assert_eq!(output_cmp_value.to_field(), true.into()); let status = vm.process_opcode(); assert_eq!(status, VMStatus::InProgress); @@ -660,7 +727,7 @@ mod tests { #[test] fn jmpifnot_opcode() { - let calldata = vec![Value::from(1u128), Value::from(2u128)]; + let calldata: Vec = vec![1u128.into(), 2u128.into()]; let calldata_copy = Opcode::CalldataCopy { destination_address: MemoryAddress::from(0), @@ -670,7 +737,7 @@ mod tests { let jump_opcode = Opcode::Jump { location: 3 }; - let trap_opcode = Opcode::Trap; + let trap_opcode = Opcode::Trap { revert_data: HeapArray::default() }; let not_equal_cmp_opcode = Opcode::BinaryFieldOp { op: BinaryFieldOp::Equals, @@ -697,7 +764,7 @@ mod tests { jump_if_not_opcode, add_opcode, ]; - let mut vm = VM::new(calldata, &opcodes, vec![], &DummyBlackBoxSolver); + let mut vm = VM::new(calldata, &opcodes, vec![], &StubbedBlackBoxSolver); let status = vm.process_opcode(); assert_eq!(status, VMStatus::InProgress); @@ -708,7 +775,7 @@ mod tests { assert_eq!(status, VMStatus::InProgress); let output_cmp_value = vm.memory.read(MemoryAddress::from(2)); - assert_eq!(output_cmp_value, Value::from(false)); + assert_eq!(output_cmp_value.to_field(), false.into()); let status = vm.process_opcode(); assert_eq!(status, VMStatus::InProgress); @@ -717,7 +784,7 @@ mod tests { assert_eq!( status, VMStatus::Failure { - message: "explicit trap hit in brillig".to_string(), + reason: FailureReason::Trap { revert_data_offset: 0, revert_data_size: 0 }, call_stack: vec![2] } ); @@ -725,12 +792,12 @@ mod tests { // The address at index `2` should have not changed as we jumped over the add opcode let VM { memory, .. } = vm; let output_value = memory.read(MemoryAddress::from(2)); - assert_eq!(output_value, Value::from(false)); + assert_eq!(output_value.to_field(), false.into()); } #[test] fn cast_opcode() { - let calldata = vec![Value::from((2_u128.pow(32)) - 1)]; + let calldata: Vec = vec![((2_u128.pow(32)) - 1).into()]; let opcodes = &[ Opcode::CalldataCopy { @@ -745,7 +812,7 @@ mod tests { }, Opcode::Stop { return_data_offset: 1, return_data_size: 1 }, ]; - let mut vm = VM::new(calldata, opcodes, vec![], &DummyBlackBoxSolver); + let mut vm = VM::new(calldata, opcodes, vec![], &StubbedBlackBoxSolver); let status = vm.process_opcode(); assert_eq!(status, VMStatus::InProgress); @@ -759,12 +826,12 @@ mod tests { let VM { memory, .. } = vm; let casted_value = memory.read(MemoryAddress::from(1)); - assert_eq!(casted_value, Value::from(2_u128.pow(8) - 1)); + assert_eq!(casted_value.to_field(), (2_u128.pow(8) - 1).into()); } #[test] fn mov_opcode() { - let calldata = vec![Value::from(1u128), Value::from(2u128), Value::from(3u128)]; + let calldata: Vec = vec![(1u128).into(), (2u128).into(), (3u128).into()]; let calldata_copy = Opcode::CalldataCopy { destination_address: MemoryAddress::from(0), @@ -776,7 +843,7 @@ mod tests { Opcode::Mov { destination: MemoryAddress::from(2), source: MemoryAddress::from(0) }; let opcodes = &[calldata_copy, mov_opcode]; - let mut vm = VM::new(calldata, opcodes, vec![], &DummyBlackBoxSolver); + let mut vm = VM::new(calldata, opcodes, vec![], &StubbedBlackBoxSolver); let status = vm.process_opcode(); assert_eq!(status, VMStatus::InProgress); @@ -787,22 +854,84 @@ mod tests { let VM { memory, .. } = vm; let destination_value = memory.read(MemoryAddress::from(2)); - assert_eq!(destination_value, Value::from(1u128)); + assert_eq!(destination_value.to_field(), (1u128).into()); let source_value = memory.read(MemoryAddress::from(0)); - assert_eq!(source_value, Value::from(1u128)); + assert_eq!(source_value.to_field(), (1u128).into()); } #[test] - fn cmp_binary_ops() { - let bit_size = 32; - let calldata = vec![ - Value::from(2u128), - Value::from(2u128), - Value::from(0u128), - Value::from(5u128), - Value::from(6u128), + fn cmov_opcode() { + let calldata: Vec = + vec![(0u128).into(), (1u128).into(), (2u128).into(), (3u128).into()]; + + let calldata_copy = Opcode::CalldataCopy { + destination_address: MemoryAddress::from(0), + size: 4, + offset: 0, + }; + + let cast_zero = Opcode::Cast { + destination: MemoryAddress::from(0), + source: MemoryAddress::from(0), + bit_size: 1, + }; + + let cast_one = Opcode::Cast { + destination: MemoryAddress::from(1), + source: MemoryAddress::from(1), + bit_size: 1, + }; + + let opcodes = &[ + calldata_copy, + cast_zero, + cast_one, + Opcode::ConditionalMov { + destination: MemoryAddress(4), // Sets 3_u128 to memory address 4 + source_a: MemoryAddress(2), + source_b: MemoryAddress(3), + condition: MemoryAddress(0), + }, + Opcode::ConditionalMov { + destination: MemoryAddress(5), // Sets 2_u128 to memory address 5 + source_a: MemoryAddress(2), + source_b: MemoryAddress(3), + condition: MemoryAddress(1), + }, ]; + let mut vm = VM::new(calldata, opcodes, vec![], &StubbedBlackBoxSolver); + + let status = vm.process_opcode(); + assert_eq!(status, VMStatus::InProgress); + + let status = vm.process_opcode(); + assert_eq!(status, VMStatus::InProgress); + + let status = vm.process_opcode(); + assert_eq!(status, VMStatus::InProgress); + + let status = vm.process_opcode(); + assert_eq!(status, VMStatus::InProgress); + + let status = vm.process_opcode(); + assert_eq!(status, VMStatus::Finished { return_data_offset: 0, return_data_size: 0 }); + + let VM { memory, .. } = vm; + + let destination_value = memory.read(MemoryAddress::from(4)); + assert_eq!(destination_value.to_field(), (3_u128).into()); + + let source_value = memory.read(MemoryAddress::from(5)); + assert_eq!(source_value.to_field(), (2_u128).into()); + } + + #[test] + fn cmp_binary_ops() { + let bit_size = BRILLIG_MEMORY_ADDRESSING_BIT_SIZE; + let calldata: Vec = + vec![(2u128).into(), (2u128).into(), (0u128).into(), (5u128).into(), (6u128).into()]; + let calldata_size = calldata.len(); let calldata_copy = Opcode::CalldataCopy { destination_address: MemoryAddress::from(0), @@ -810,6 +939,14 @@ mod tests { offset: 0, }; + let cast_opcodes: Vec<_> = (0..calldata_size) + .map(|index| Opcode::Cast { + destination: MemoryAddress::from(index), + source: MemoryAddress::from(index), + bit_size, + }) + .collect(); + let equal_opcode = Opcode::BinaryIntOp { bit_size, op: BinaryIntOp::Equals, @@ -842,42 +979,47 @@ mod tests { destination: MemoryAddress::from(2), }; - let opcodes = [ - calldata_copy, - equal_opcode, - not_equal_opcode, - less_than_opcode, - less_than_equal_opcode, - ]; - let mut vm = VM::new(calldata, &opcodes, vec![], &DummyBlackBoxSolver); + let opcodes: Vec<_> = std::iter::once(calldata_copy) + .chain(cast_opcodes) + .chain([equal_opcode, not_equal_opcode, less_than_opcode, less_than_equal_opcode]) + .collect(); + let mut vm = VM::new(calldata, &opcodes, vec![], &StubbedBlackBoxSolver); + // Calldata copy let status = vm.process_opcode(); assert_eq!(status, VMStatus::InProgress); + for _ in 0..calldata_size { + let status = vm.process_opcode(); + assert_eq!(status, VMStatus::InProgress); + } + + // Equals let status = vm.process_opcode(); assert_eq!(status, VMStatus::InProgress); let output_eq_value = vm.memory.read(MemoryAddress::from(2)); - assert_eq!(output_eq_value, Value::from(true)); + assert_eq!(output_eq_value, true.into()); let status = vm.process_opcode(); assert_eq!(status, VMStatus::InProgress); let output_neq_value = vm.memory.read(MemoryAddress::from(2)); - assert_eq!(output_neq_value, Value::from(false)); + assert_eq!(output_neq_value, false.into()); let status = vm.process_opcode(); assert_eq!(status, VMStatus::InProgress); let lt_value = vm.memory.read(MemoryAddress::from(2)); - assert_eq!(lt_value, Value::from(true)); + assert_eq!(lt_value, true.into()); let status = vm.process_opcode(); assert_eq!(status, VMStatus::Finished { return_data_offset: 0, return_data_size: 0 }); let lte_value = vm.memory.read(MemoryAddress::from(2)); - assert_eq!(lte_value, Value::from(true)); + assert_eq!(lte_value, true.into()); } + #[test] fn store_opcode() { /// Brillig code for the following: @@ -887,30 +1029,26 @@ mod tests { /// memory[i] = i as Value; /// i += 1; /// } - fn brillig_write_memory(item_count: usize) -> Vec { - let bit_size = 32; + fn brillig_write_memory(item_count: usize) -> Vec> { + let bit_size = BRILLIG_MEMORY_ADDRESSING_BIT_SIZE; let r_i = MemoryAddress::from(0); let r_len = MemoryAddress::from(1); let r_tmp = MemoryAddress::from(2); let r_pointer = MemoryAddress::from(3); - let start = [ + let start: [Opcode; 3] = [ // i = 0 - Opcode::Const { destination: r_i, value: 0u128.into(), bit_size: 32 }, + Opcode::Const { destination: r_i, value: 0u128.into(), bit_size }, // len = memory.len() (approximation) - Opcode::Const { - destination: r_len, - value: Value::from(item_count as u128), - bit_size: 32, - }, + Opcode::Const { destination: r_len, value: item_count.into(), bit_size }, // pointer = free_memory_ptr - Opcode::Const { destination: r_pointer, value: 4u128.into(), bit_size: 32 }, + Opcode::Const { destination: r_pointer, value: 4u128.into(), bit_size }, ]; let loop_body = [ // *i = i Opcode::Store { destination_pointer: r_pointer, source: r_i }, // tmp = 1 - Opcode::Const { destination: r_tmp, value: 1u128.into(), bit_size: 32 }, + Opcode::Const { destination: r_tmp, value: 1u128.into(), bit_size }, // i = i + 1 (tmp) Opcode::BinaryIntOp { destination: r_i, @@ -945,17 +1083,12 @@ mod tests { } let memory = brillig_write_memory(5); - let expected = vec![ - Value::from(0u128), - Value::from(1u128), - Value::from(2u128), - Value::from(3u128), - Value::from(4u128), - ]; + let expected = + vec![(0u32).into(), (1u32).into(), (2u32).into(), (3u32).into(), (4u32).into()]; assert_eq!(memory, expected); let memory = brillig_write_memory(1024); - let expected: Vec = (0..1024).map(|i| Value::from(i as u128)).collect(); + let expected: Vec<_> = (0..1024).map(|i: u32| i.into()).collect(); assert_eq!(memory, expected); } @@ -969,7 +1102,7 @@ mod tests { /// sum += memory[i]; /// i += 1; /// } - fn brillig_sum_memory(memory: Vec) -> Value { + fn brillig_sum_memory(memory: Vec) -> FieldElement { let bit_size = 32; let r_i = MemoryAddress::from(0); let r_len = MemoryAddress::from(1); @@ -977,19 +1110,19 @@ mod tests { let r_tmp = MemoryAddress::from(3); let r_pointer = MemoryAddress::from(4); - let start = [ + let start: [Opcode; 5] = [ // sum = 0 - Opcode::Const { destination: r_sum, value: 0u128.into(), bit_size: 32 }, - // i = 0 - Opcode::Const { destination: r_i, value: 0u128.into(), bit_size: 32 }, - // len = array.len() (approximation) Opcode::Const { - destination: r_len, - value: Value::from(memory.len() as u128), - bit_size: 32, + destination: r_sum, + value: 0u128.into(), + bit_size: FieldElement::max_num_bits(), }, + // i = 0 + Opcode::Const { destination: r_i, value: 0u128.into(), bit_size }, + // len = array.len() (approximation) + Opcode::Const { destination: r_len, value: memory.len().into(), bit_size }, // pointer = array_ptr - Opcode::Const { destination: r_pointer, value: 5u128.into(), bit_size: 32 }, + Opcode::Const { destination: r_pointer, value: 5u128.into(), bit_size }, Opcode::CalldataCopy { destination_address: MemoryAddress(5), size: memory.len(), @@ -1000,15 +1133,14 @@ mod tests { // tmp = *i Opcode::Load { destination: r_tmp, source_pointer: r_pointer }, // sum = sum + tmp - Opcode::BinaryIntOp { + Opcode::BinaryFieldOp { destination: r_sum, lhs: r_sum, - op: BinaryIntOp::Add, + op: BinaryFieldOp::Add, rhs: r_tmp, - bit_size, }, // tmp = 1 - Opcode::Const { destination: r_tmp, value: 1u128.into(), bit_size: 32 }, + Opcode::Const { destination: r_tmp, value: 1u128.into(), bit_size }, // i = i + 1 (tmp) Opcode::BinaryIntOp { destination: r_i, @@ -1039,20 +1171,20 @@ mod tests { let opcodes = [&start[..], &loop_body[..]].concat(); let vm = brillig_execute_and_get_vm(memory, &opcodes); - vm.memory.read(r_sum) + vm.memory.read(r_sum).to_field() } assert_eq!( brillig_sum_memory(vec![ - Value::from(1u128), - Value::from(2u128), - Value::from(3u128), - Value::from(4u128), - Value::from(5u128), + (1u128).into(), + (2u128).into(), + (3u128).into(), + (4u128).into(), + (5u128).into(), ]), - Value::from(15u128) + (15u128).into() ); - assert_eq!(brillig_sum_memory(vec![Value::from(1u128); 1024]), Value::from(1024u128)); + assert_eq!(brillig_sum_memory(vec![(1u128).into(); 1024]), (1024u128).into()); } #[test] @@ -1066,24 +1198,24 @@ mod tests { /// recursive_write(memory, i + 1, len); /// } /// Note we represent a 100% in-stack optimized form in brillig - fn brillig_recursive_write_memory(size: usize) -> Vec { - let bit_size = 32; + fn brillig_recursive_write_memory(size: usize) -> Vec> { + let bit_size = BRILLIG_MEMORY_ADDRESSING_BIT_SIZE; let r_i = MemoryAddress::from(0); let r_len = MemoryAddress::from(1); let r_tmp = MemoryAddress::from(2); let r_pointer = MemoryAddress::from(3); - let start = [ + let start: [Opcode; 5] = [ // i = 0 - Opcode::Const { destination: r_i, value: 0u128.into(), bit_size: 32 }, + Opcode::Const { destination: r_i, value: 0u128.into(), bit_size }, // len = size - Opcode::Const { destination: r_len, value: size.into(), bit_size: 32 }, + Opcode::Const { destination: r_len, value: (size as u128).into(), bit_size }, // pointer = free_memory_ptr - Opcode::Const { destination: r_pointer, value: 4u128.into(), bit_size: 32 }, + Opcode::Const { destination: r_pointer, value: 4u128.into(), bit_size }, // call recursive_fn Opcode::Call { - location: 5, // Call after 'start' - }, + location: 5, // Call after 'start' + }, // end program by jumping to end Opcode::Jump { location: 100 }, ]; @@ -1105,7 +1237,7 @@ mod tests { // *i = i Opcode::Store { destination_pointer: r_pointer, source: r_i }, // tmp = 1 - Opcode::Const { destination: r_tmp, value: 1u128.into(), bit_size: 32 }, + Opcode::Const { destination: r_tmp, value: 1u128.into(), bit_size }, // i = i + 1 (tmp) Opcode::BinaryIntOp { destination: r_i, @@ -1132,33 +1264,28 @@ mod tests { vm.get_memory()[4..].to_vec() } - let memory = brillig_recursive_write_memory(5); - let expected = vec![ - Value::from(0u128), - Value::from(1u128), - Value::from(2u128), - Value::from(3u128), - Value::from(4u128), - ]; + let memory = brillig_recursive_write_memory::(5); + let expected = + vec![(0u32).into(), (1u32).into(), (2u32).into(), (3u32).into(), (4u32).into()]; assert_eq!(memory, expected); - let memory = brillig_recursive_write_memory(1024); - let expected: Vec = (0..1024).map(|i| Value::from(i as u128)).collect(); + let memory = brillig_recursive_write_memory::(1024); + let expected: Vec<_> = (0..1024).map(|i: u32| i.into()).collect(); assert_eq!(memory, expected); } /// Helper to execute brillig code - fn brillig_execute_and_get_vm( - calldata: Vec, - opcodes: &[Opcode], - ) -> VM<'_, DummyBlackBoxSolver> { - let mut vm = VM::new(calldata, opcodes, vec![], &DummyBlackBoxSolver); + fn brillig_execute_and_get_vm( + calldata: Vec, + opcodes: &[Opcode], + ) -> VM<'_, F, StubbedBlackBoxSolver> { + let mut vm = VM::new(calldata, opcodes, vec![], &StubbedBlackBoxSolver); brillig_execute(&mut vm); assert_eq!(vm.call_stack, vec![]); vm } - fn brillig_execute(vm: &mut VM) { + fn brillig_execute(vm: &mut VM) { loop { let status = vm.process_opcode(); if matches!(status, VMStatus::Finished { .. } | VMStatus::ForeignCallWait { .. }) { @@ -1175,14 +1302,18 @@ mod tests { let double_program = vec![ // Load input address with value 5 - Opcode::Const { destination: r_input, value: Value::from(5u128), bit_size: 32 }, + Opcode::Const { + destination: r_input, + value: (5u128).into(), + bit_size: BRILLIG_MEMORY_ADDRESSING_BIT_SIZE, + }, // Call foreign function "double" with the input address Opcode::ForeignCall { function: "double".into(), destinations: vec![ValueOrArray::MemoryAddress(r_result)], - destination_value_types: vec![HeapValueType::Simple], + destination_value_types: vec![HeapValueType::Simple(32)], inputs: vec![ValueOrArray::MemoryAddress(r_input)], - input_value_types: vec![HeapValueType::Simple], + input_value_types: vec![HeapValueType::Simple(32)], }, ]; @@ -1193,13 +1324,13 @@ mod tests { vm.status, VMStatus::ForeignCallWait { function: "double".into(), - inputs: vec![Value::from(5u128).into()] + inputs: vec![FieldElement::from(5usize).into()] } ); // Push result we're waiting for vm.resolve_foreign_call( - Value::from(10u128).into(), // Result of doubling 5u128 + FieldElement::from(10u128).into(), // Result of doubling 5u128 ); // Resume VM @@ -1210,7 +1341,7 @@ mod tests { // Check result address let result_value = vm.memory.read(r_result); - assert_eq!(result_value, Value::from(10u128)); + assert_eq!(result_value, (10u32).into()); // Ensure the foreign call counter has been incremented assert_eq!(vm.foreign_call_counter, 1); @@ -1222,12 +1353,12 @@ mod tests { let r_output = MemoryAddress::from(1); // Define a simple 2x2 matrix in memory - let initial_matrix = - vec![Value::from(1u128), Value::from(2u128), Value::from(3u128), Value::from(4u128)]; + let initial_matrix: Vec = + vec![(1u128).into(), (2u128).into(), (3u128).into(), (4u128).into()]; // Transpose of the matrix (but arbitrary for this test, the 'correct value') - let expected_result = - vec![Value::from(1u128), Value::from(3u128), Value::from(2u128), Value::from(4u128)]; + let expected_result: Vec = + vec![(1u128).into(), (3u128).into(), (2u128).into(), (4u128).into()]; let invert_program = vec![ Opcode::CalldataCopy { @@ -1236,9 +1367,17 @@ mod tests { offset: 0, }, // input = 0 - Opcode::Const { destination: r_input, value: 2_usize.into(), bit_size: 32 }, + Opcode::Const { + destination: r_input, + value: 2_usize.into(), + bit_size: BRILLIG_MEMORY_ADDRESSING_BIT_SIZE, + }, // output = 0 - Opcode::Const { destination: r_output, value: 2_usize.into(), bit_size: 32 }, + Opcode::Const { + destination: r_output, + value: 2_usize.into(), + bit_size: BRILLIG_MEMORY_ADDRESSING_BIT_SIZE, + }, // *output = matrix_2x2_transpose(*input) Opcode::ForeignCall { function: "matrix_2x2_transpose".into(), @@ -1248,14 +1387,14 @@ mod tests { })], destination_value_types: vec![HeapValueType::Array { size: initial_matrix.len(), - value_types: vec![HeapValueType::Simple], + value_types: vec![HeapValueType::field()], }], inputs: vec![ValueOrArray::HeapArray(HeapArray { pointer: r_input, size: initial_matrix.len(), })], input_value_types: vec![HeapValueType::Array { - value_types: vec![HeapValueType::Simple], + value_types: vec![HeapValueType::field()], size: initial_matrix.len(), }], }, @@ -1283,7 +1422,10 @@ mod tests { // Check result in memory let result_values = vm.memory.read_slice(MemoryAddress(2), 4).to_vec(); - assert_eq!(result_values, expected_result); + assert_eq!( + result_values.into_iter().map(|mem_value| mem_value.to_field()).collect::>(), + expected_result + ); // Ensure the foreign call counter has been incremented assert_eq!(vm.foreign_call_counter, 1); @@ -1299,10 +1441,10 @@ mod tests { let r_output_size = MemoryAddress::from(3); // Our first string to use the identity function with - let input_string = - vec![Value::from(1u128), Value::from(2u128), Value::from(3u128), Value::from(4u128)]; + let input_string: Vec = + vec![(1u128).into(), (2u128).into(), (3u128).into(), (4u128).into()]; // Double the string (concatenate it with itself) - let mut output_string: Vec = + let mut output_string: Vec<_> = input_string.iter().cloned().chain(input_string.clone()).collect(); // Reverse the concatenated string output_string.reverse(); @@ -1315,24 +1457,28 @@ mod tests { offset: 0, }, // input_pointer = 4 - Opcode::Const { destination: r_input_pointer, value: Value::from(4u128), bit_size: 32 }, + Opcode::Const { + destination: r_input_pointer, + value: (4u128).into(), + bit_size: BRILLIG_MEMORY_ADDRESSING_BIT_SIZE, + }, // input_size = input_string.len() (constant here) Opcode::Const { destination: r_input_size, - value: Value::from(input_string.len()), - bit_size: 32, + value: input_string.len().into(), + bit_size: BRILLIG_MEMORY_ADDRESSING_BIT_SIZE, }, // output_pointer = 4 + input_size Opcode::Const { destination: r_output_pointer, - value: Value::from(4 + input_string.len()), - bit_size: 32, + value: (4 + input_string.len()).into(), + bit_size: BRILLIG_MEMORY_ADDRESSING_BIT_SIZE, }, // output_size = input_size * 2 Opcode::Const { destination: r_output_size, - value: Value::from(input_string.len() * 2), - bit_size: 32, + value: (input_string.len() * 2).into(), + bit_size: BRILLIG_MEMORY_ADDRESSING_BIT_SIZE, }, // output_pointer[0..output_size] = string_double(input_pointer[0...input_size]) Opcode::ForeignCall { @@ -1342,14 +1488,14 @@ mod tests { size: r_output_size, })], destination_value_types: vec![HeapValueType::Vector { - value_types: vec![HeapValueType::Simple], + value_types: vec![HeapValueType::field()], }], inputs: vec![ValueOrArray::HeapVector(HeapVector { pointer: r_input_pointer, size: r_input_size, })], input_value_types: vec![HeapValueType::Vector { - value_types: vec![HeapValueType::Simple], + value_types: vec![HeapValueType::field()], }], }, ]; @@ -1377,10 +1523,12 @@ mod tests { assert_eq!(vm.status, VMStatus::Finished { return_data_offset: 0, return_data_size: 0 }); // Check result in memory - let result_values = vm + let result_values: Vec<_> = vm .memory .read_slice(MemoryAddress(4 + input_string.len()), output_string.len()) - .to_vec(); + .iter() + .map(|mem_val| mem_val.clone().to_field()) + .collect(); assert_eq!(result_values, output_string); // Ensure the foreign call counter has been incremented @@ -1393,12 +1541,12 @@ mod tests { let r_output = MemoryAddress::from(1); // Define a simple 2x2 matrix in memory - let initial_matrix = - vec![Value::from(1u128), Value::from(2u128), Value::from(3u128), Value::from(4u128)]; + let initial_matrix: Vec = + vec![(1u128).into(), (2u128).into(), (3u128).into(), (4u128).into()]; // Transpose of the matrix (but arbitrary for this test, the 'correct value') - let expected_result = - vec![Value::from(1u128), Value::from(3u128), Value::from(2u128), Value::from(4u128)]; + let expected_result: Vec = + vec![(1u128).into(), (3u128).into(), (2u128).into(), (4u128).into()]; let invert_program = vec![ Opcode::CalldataCopy { @@ -1407,9 +1555,17 @@ mod tests { offset: 0, }, // input = 0 - Opcode::Const { destination: r_input, value: Value::from(2u128), bit_size: 32 }, + Opcode::Const { + destination: r_input, + value: (2u128).into(), + bit_size: BRILLIG_MEMORY_ADDRESSING_BIT_SIZE, + }, // output = 0 - Opcode::Const { destination: r_output, value: Value::from(6u128), bit_size: 32 }, + Opcode::Const { + destination: r_output, + value: (6u128).into(), + bit_size: BRILLIG_MEMORY_ADDRESSING_BIT_SIZE, + }, // *output = matrix_2x2_transpose(*input) Opcode::ForeignCall { function: "matrix_2x2_transpose".into(), @@ -1419,7 +1575,7 @@ mod tests { })], destination_value_types: vec![HeapValueType::Array { size: initial_matrix.len(), - value_types: vec![HeapValueType::Simple], + value_types: vec![HeapValueType::field()], }], inputs: vec![ValueOrArray::HeapArray(HeapArray { pointer: r_input, @@ -1427,7 +1583,7 @@ mod tests { })], input_value_types: vec![HeapValueType::Array { size: initial_matrix.len(), - value_types: vec![HeapValueType::Simple], + value_types: vec![HeapValueType::field()], }], }, ]; @@ -1453,11 +1609,21 @@ mod tests { assert_eq!(vm.status, VMStatus::Finished { return_data_offset: 0, return_data_size: 0 }); // Check initial memory still in place - let initial_values = vm.memory.read_slice(MemoryAddress(2), 4).to_vec(); + let initial_values: Vec<_> = vm + .memory + .read_slice(MemoryAddress(2), 4) + .iter() + .map(|mem_val| mem_val.clone().to_field()) + .collect(); assert_eq!(initial_values, initial_matrix); // Check result in memory - let result_values = vm.memory.read_slice(MemoryAddress(6), 4).to_vec(); + let result_values: Vec<_> = vm + .memory + .read_slice(MemoryAddress(6), 4) + .iter() + .map(|mem_val| mem_val.clone().to_field()) + .collect(); assert_eq!(result_values, expected_result); // Ensure the foreign call counter has been incremented @@ -1471,23 +1637,15 @@ mod tests { let r_output = MemoryAddress::from(2); // Define a simple 2x2 matrix in memory - let matrix_a = - vec![Value::from(1u128), Value::from(2u128), Value::from(3u128), Value::from(4u128)]; - - let matrix_b = vec![ - Value::from(10u128), - Value::from(11u128), - Value::from(12u128), - Value::from(13u128), - ]; + let matrix_a: Vec = + vec![(1u128).into(), (2u128).into(), (3u128).into(), (4u128).into()]; + + let matrix_b: Vec = + vec![(10u128).into(), (11u128).into(), (12u128).into(), (13u128).into()]; // Transpose of the matrix (but arbitrary for this test, the 'correct value') - let expected_result = vec![ - Value::from(34u128), - Value::from(37u128), - Value::from(78u128), - Value::from(85u128), - ]; + let expected_result: Vec = + vec![(34u128).into(), (37u128).into(), (78u128).into(), (85u128).into()]; let matrix_mul_program = vec![ Opcode::CalldataCopy { @@ -1496,11 +1654,23 @@ mod tests { offset: 0, }, // input = 3 - Opcode::Const { destination: r_input_a, value: Value::from(3u128), bit_size: 32 }, + Opcode::Const { + destination: r_input_a, + value: (3u128).into(), + bit_size: BRILLIG_MEMORY_ADDRESSING_BIT_SIZE, + }, // input = 7 - Opcode::Const { destination: r_input_b, value: Value::from(7u128), bit_size: 32 }, + Opcode::Const { + destination: r_input_b, + value: (7u128).into(), + bit_size: BRILLIG_MEMORY_ADDRESSING_BIT_SIZE, + }, // output = 0 - Opcode::Const { destination: r_output, value: Value::from(0u128), bit_size: 32 }, + Opcode::Const { + destination: r_output, + value: (0u128).into(), + bit_size: BRILLIG_MEMORY_ADDRESSING_BIT_SIZE, + }, // *output = matrix_2x2_transpose(*input) Opcode::ForeignCall { function: "matrix_2x2_transpose".into(), @@ -1510,7 +1680,7 @@ mod tests { })], destination_value_types: vec![HeapValueType::Array { size: matrix_a.len(), - value_types: vec![HeapValueType::Simple], + value_types: vec![HeapValueType::field()], }], inputs: vec![ ValueOrArray::HeapArray(HeapArray { pointer: r_input_a, size: matrix_a.len() }), @@ -1519,11 +1689,11 @@ mod tests { input_value_types: vec![ HeapValueType::Array { size: matrix_a.len(), - value_types: vec![HeapValueType::Simple], + value_types: vec![HeapValueType::field()], }, HeapValueType::Array { size: matrix_b.len(), - value_types: vec![HeapValueType::Simple], + value_types: vec![HeapValueType::field()], }, ], }, @@ -1551,7 +1721,12 @@ mod tests { assert_eq!(vm.status, VMStatus::Finished { return_data_offset: 0, return_data_size: 0 }); // Check result in memory - let result_values = vm.memory.read_slice(MemoryAddress(0), 4).to_vec(); + let result_values: Vec<_> = vm + .memory + .read_slice(MemoryAddress(0), 4) + .iter() + .map(|mem_val| mem_val.clone().to_field()) + .collect(); assert_eq!(result_values, expected_result); // Ensure the foreign call counter has been incremented @@ -1562,47 +1737,56 @@ mod tests { fn foreign_call_opcode_nested_arrays_and_slices_input() { // [(1, <2,3>, [4]), (5, <6,7,8>, [9])] - let v2 = vec![Value::from(2u128), Value::from(3u128)]; - let a4 = vec![Value::from(4u128)]; - let v6 = vec![Value::from(6u128), Value::from(7u128), Value::from(8u128)]; - let a9 = vec![Value::from(9u128)]; + let v2: Vec> = vec![ + MemoryValue::new_field(FieldElement::from(2u128)), + MemoryValue::new_field(FieldElement::from(3u128)), + ]; + let a4: Vec> = + vec![MemoryValue::new_field(FieldElement::from(4u128))]; + let v6: Vec> = vec![ + MemoryValue::new_field(FieldElement::from(6u128)), + MemoryValue::new_field(FieldElement::from(7u128)), + MemoryValue::new_field(FieldElement::from(8u128)), + ]; + let a9: Vec> = + vec![MemoryValue::new_field(FieldElement::from(9u128))]; // construct memory by declaring all inner arrays/vectors first - let v2_ptr = 0u128; + let v2_ptr: usize = 0usize; let mut memory = v2.clone(); let v2_start = memory.len(); - memory.extend(vec![Value::from(v2_ptr), Value::from(v2.len()), Value::from(1u128)]); + memory.extend(vec![MemoryValue::from(v2_ptr), v2.len().into(), MemoryValue::from(1_u32)]); let a4_ptr = memory.len(); memory.extend(a4.clone()); let a4_start = memory.len(); - memory.extend(vec![Value::from(a4_ptr), Value::from(1u128)]); + memory.extend(vec![MemoryValue::from(a4_ptr), MemoryValue::from(1_u32)]); let v6_ptr = memory.len(); memory.extend(v6.clone()); let v6_start = memory.len(); - memory.extend(vec![Value::from(v6_ptr), Value::from(v6.len()), Value::from(1u128)]); + memory.extend(vec![MemoryValue::from(v6_ptr), v6.len().into(), MemoryValue::from(1_u32)]); let a9_ptr = memory.len(); memory.extend(a9.clone()); let a9_start = memory.len(); - memory.extend(vec![Value::from(a9_ptr), Value::from(1u128)]); + memory.extend(vec![MemoryValue::from(a9_ptr), MemoryValue::from(1_u32)]); // finally we add the contents of the outer array let outer_ptr = memory.len(); let outer_array = vec![ - Value::from(1u128), - Value::from(v2.len()), - Value::from(v2_start), - Value::from(a4_start), - Value::from(5u128), - Value::from(v6.len()), - Value::from(v6_start), - Value::from(a9_start), + MemoryValue::new_field(FieldElement::from(1u128)), + MemoryValue::from(v2.len() as u32), + MemoryValue::from(v2_start), + MemoryValue::from(a4_start), + MemoryValue::new_field(FieldElement::from(5u128)), + MemoryValue::from(v6.len() as u32), + MemoryValue::from(v6_start), + MemoryValue::from(a9_start), ]; memory.extend(outer_array.clone()); - let input_array_value_types = vec![ - HeapValueType::Simple, - HeapValueType::Simple, // size of following vector - HeapValueType::Vector { value_types: vec![HeapValueType::Simple] }, - HeapValueType::Array { value_types: vec![HeapValueType::Simple], size: 1 }, + let input_array_value_types: Vec = vec![ + HeapValueType::field(), + HeapValueType::Simple(64), // size of following vector + HeapValueType::Vector { value_types: vec![HeapValueType::field()] }, + HeapValueType::Array { value_types: vec![HeapValueType::field()], size: 1 }, ]; // memory address of the end of the above data structures @@ -1611,19 +1795,24 @@ mod tests { let r_input = MemoryAddress::from(r_ptr); let r_output = MemoryAddress::from(r_ptr + 1); - let program = vec![ - Opcode::CalldataCopy { - destination_address: MemoryAddress::from(0), - size: memory.len(), - offset: 0, - }, + let program: Vec<_> = std::iter::once(Opcode::CalldataCopy { + destination_address: MemoryAddress::from(0), + size: memory.len(), + offset: 0, + }) + .chain(memory.iter().enumerate().map(|(index, mem_value)| Opcode::Cast { + destination: MemoryAddress(index), + source: MemoryAddress(index), + bit_size: mem_value.bit_size(), + })) + .chain(vec![ // input = 0 - Opcode::Const { destination: r_input, value: Value::from(outer_ptr), bit_size: 32 }, + Opcode::Const { destination: r_input, value: (outer_ptr).into(), bit_size: 32 }, // some_function(input) Opcode::ForeignCall { function: "flat_sum".into(), destinations: vec![ValueOrArray::MemoryAddress(r_output)], - destination_value_types: vec![HeapValueType::Simple], + destination_value_types: vec![HeapValueType::field()], inputs: vec![ValueOrArray::HeapArray(HeapArray { pointer: r_input, size: outer_array.len(), @@ -1633,9 +1822,13 @@ mod tests { size: outer_array.len(), }], }, - ]; + ]) + .collect(); - let mut vm = brillig_execute_and_get_vm(memory, &program); + let mut vm = brillig_execute_and_get_vm( + memory.into_iter().map(|mem_value| mem_value.to_field()).collect(), + &program, + ); // Check that VM is waiting assert_eq!( @@ -1643,23 +1836,23 @@ mod tests { VMStatus::ForeignCallWait { function: "flat_sum".into(), inputs: vec![ForeignCallParam::Array(vec![ - Value::from(1u128), - Value::from(2u128), // size of following vector - Value::from(2u128), - Value::from(3u128), - Value::from(4u128), - Value::from(5u128), - Value::from(3u128), // size of following vector - Value::from(6u128), - Value::from(7u128), - Value::from(8u128), - Value::from(9u128), + (1u128).into(), + (2u128).into(), // size of following vector + (2u128).into(), + (3u128).into(), + (4u128).into(), + (5u128).into(), + (3u128).into(), // size of following vector + (6u128).into(), + (7u128).into(), + (8u128).into(), + (9u128).into(), ])], } ); // Push result we're waiting for - vm.resolve_foreign_call(Value::from(45u128).into()); + vm.resolve_foreign_call(FieldElement::from(45u128).into()); // Resume VM brillig_execute(&mut vm); @@ -1669,7 +1862,7 @@ mod tests { // Check result let result_value = vm.memory.read(r_output); - assert_eq!(result_value, Value::from(45u128)); + assert_eq!(result_value, MemoryValue::new_field(FieldElement::from(45u128))); // Ensure the foreign call counter has been incremented assert_eq!(vm.foreign_call_counter, 1); diff --git a/acvm-repo/brillig_vm/src/memory.rs b/acvm-repo/brillig_vm/src/memory.rs index d1c81447170..95e28f7d863 100644 --- a/acvm-repo/brillig_vm/src/memory.rs +++ b/acvm-repo/brillig_vm/src/memory.rs @@ -1,30 +1,312 @@ -use acir::{brillig::MemoryAddress, FieldElement}; +use acir::{brillig::MemoryAddress, AcirField}; +use num_bigint::BigUint; +use num_traits::{One, Zero}; -use crate::Value; +pub const MEMORY_ADDRESSING_BIT_SIZE: u32 = 32; + +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] +pub enum MemoryValue { + Field(F), + Integer(BigUint, u32), +} + +#[derive(Debug, thiserror::Error)] +pub enum MemoryTypeError { + #[error("Bit size for value {value_bit_size} does not match the expected bit size {expected_bit_size}")] + MismatchedBitSize { value_bit_size: u32, expected_bit_size: u32 }, +} + +impl MemoryValue { + /// Builds a field-typed memory value. + pub fn new_field(value: F) -> Self { + MemoryValue::Field(value) + } + + /// Extracts the field element from the memory value, if it is typed as field element. + pub fn extract_field(&self) -> Option<&F> { + match self { + MemoryValue::Field(value) => Some(value), + _ => None, + } + } + + /// Extracts the integer from the memory value, if it is typed as integer. + pub fn extract_integer(&self) -> Option<(&BigUint, u32)> { + match self { + MemoryValue::Integer(value, bit_size) => Some((value, *bit_size)), + _ => None, + } + } +} + +impl MemoryValue { + /// Builds a memory value from a field element. + pub fn new_from_field(value: F, bit_size: u32) -> Self { + if bit_size == F::max_num_bits() { + MemoryValue::new_field(value) + } else { + MemoryValue::new_integer(BigUint::from_bytes_be(&value.to_be_bytes()), bit_size) + } + } + + /// Builds a memory value from an integer + pub fn new_from_integer(value: BigUint, bit_size: u32) -> Self { + if bit_size == F::max_num_bits() { + MemoryValue::new_field(F::from_be_bytes_reduce(&value.to_bytes_be())) + } else { + MemoryValue::new_integer(value, bit_size) + } + } + + /// Builds a memory value from a field element, checking that the value is within the bit size. + pub fn new_checked(value: F, bit_size: u32) -> Option { + if bit_size < F::max_num_bits() && value.num_bits() > bit_size { + return None; + } + + Some(MemoryValue::new_from_field(value, bit_size)) + } + + /// Builds an integer-typed memory value. + pub fn new_integer(value: BigUint, bit_size: u32) -> Self { + assert!( + bit_size != F::max_num_bits(), + "Tried to build a field memory value via new_integer" + ); + MemoryValue::Integer(value, bit_size) + } + + /// Converts the memory value to a field element, independent of its type. + pub fn to_field(&self) -> F { + match self { + MemoryValue::Field(value) => *value, + MemoryValue::Integer(value, _) => F::from_be_bytes_reduce(&value.to_bytes_be()), + } + } + + /// Converts the memory value to an integer, independent of its type. + pub fn to_integer(self) -> BigUint { + match self { + MemoryValue::Field(value) => BigUint::from_bytes_be(&value.to_be_bytes()), + MemoryValue::Integer(value, _) => value, + } + } + + pub fn bit_size(&self) -> u32 { + match self { + MemoryValue::Field(_) => F::max_num_bits(), + MemoryValue::Integer(_, bit_size) => *bit_size, + } + } + + pub fn to_usize(&self) -> usize { + assert!( + self.bit_size() == MEMORY_ADDRESSING_BIT_SIZE, + "value is not typed as brillig usize" + ); + self.extract_integer().unwrap().0.try_into().unwrap() + } + + pub fn expect_field(&self) -> Result<&F, MemoryTypeError> { + match self { + MemoryValue::Integer(_, bit_size) => Err(MemoryTypeError::MismatchedBitSize { + value_bit_size: *bit_size, + expected_bit_size: F::max_num_bits(), + }), + MemoryValue::Field(field) => Ok(field), + } + } + + pub fn expect_integer_with_bit_size( + &self, + expected_bit_size: u32, + ) -> Result<&BigUint, MemoryTypeError> { + match self { + MemoryValue::Integer(value, bit_size) => { + if *bit_size != expected_bit_size { + return Err(MemoryTypeError::MismatchedBitSize { + value_bit_size: *bit_size, + expected_bit_size, + }); + } + Ok(value) + } + MemoryValue::Field(_) => Err(MemoryTypeError::MismatchedBitSize { + value_bit_size: F::max_num_bits(), + expected_bit_size, + }), + } + } +} + +impl std::fmt::Display for MemoryValue { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { + match self { + MemoryValue::Field(value) => write!(f, "{}: field", value), + MemoryValue::Integer(value, bit_size) => { + let typ = match bit_size { + 0 => "null".to_string(), + 1 => "bool".to_string(), + _ => format!("u{}", bit_size), + }; + write!(f, "{}: {}", value, typ) + } + } + } +} + +impl Default for MemoryValue { + fn default() -> Self { + MemoryValue::new_integer(BigUint::zero(), 0) + } +} + +impl From for MemoryValue { + fn from(value: usize) -> Self { + MemoryValue::new_integer(value.into(), MEMORY_ADDRESSING_BIT_SIZE) + } +} + +impl From for MemoryValue { + fn from(value: u32) -> Self { + MemoryValue::new_integer(value.into(), 32) + } +} + +impl From for MemoryValue { + fn from(value: u64) -> Self { + MemoryValue::new_integer(value.into(), 64) + } +} + +impl From for MemoryValue { + fn from(value: u8) -> Self { + MemoryValue::new_integer(value.into(), 8) + } +} + +impl From for MemoryValue { + fn from(value: bool) -> Self { + let value = if value { BigUint::one() } else { BigUint::zero() }; + MemoryValue::new_integer(value, 1) + } +} + +impl TryFrom> for u64 { + type Error = MemoryTypeError; + + fn try_from(memory_value: MemoryValue) -> Result { + memory_value.expect_integer_with_bit_size(64).map(|value| value.try_into().unwrap()) + } +} + +impl TryFrom> for u32 { + type Error = MemoryTypeError; + + fn try_from(memory_value: MemoryValue) -> Result { + memory_value.expect_integer_with_bit_size(32).map(|value| value.try_into().unwrap()) + } +} + +impl TryFrom> for u8 { + type Error = MemoryTypeError; + + fn try_from(memory_value: MemoryValue) -> Result { + memory_value.expect_integer_with_bit_size(8).map(|value| value.try_into().unwrap()) + } +} + +impl TryFrom> for bool { + type Error = MemoryTypeError; + + fn try_from(memory_value: MemoryValue) -> Result { + let as_integer = memory_value.expect_integer_with_bit_size(1)?; + + if as_integer.is_zero() { + Ok(false) + } else if as_integer.is_one() { + Ok(true) + } else { + unreachable!("value typed as bool is greater than one") + } + } +} + +impl TryFrom<&MemoryValue> for u64 { + type Error = MemoryTypeError; + + fn try_from(memory_value: &MemoryValue) -> Result { + memory_value.expect_integer_with_bit_size(64).map(|value| { + value.try_into().expect("memory_value has been asserted to contain a 64 bit integer") + }) + } +} + +impl TryFrom<&MemoryValue> for u32 { + type Error = MemoryTypeError; + + fn try_from(memory_value: &MemoryValue) -> Result { + memory_value.expect_integer_with_bit_size(32).map(|value| { + value.try_into().expect("memory_value has been asserted to contain a 32 bit integer") + }) + } +} + +impl TryFrom<&MemoryValue> for u8 { + type Error = MemoryTypeError; + + fn try_from(memory_value: &MemoryValue) -> Result { + memory_value.expect_integer_with_bit_size(8).map(|value| { + value.try_into().expect("memory_value has been asserted to contain an 8 bit integer") + }) + } +} + +impl TryFrom<&MemoryValue> for bool { + type Error = MemoryTypeError; + + fn try_from(memory_value: &MemoryValue) -> Result { + let as_integer = memory_value.expect_integer_with_bit_size(1)?; + + if as_integer.is_zero() { + Ok(false) + } else if as_integer.is_one() { + Ok(true) + } else { + unreachable!("value typed as bool is greater than one") + } + } +} #[derive(Debug, Clone, Default, PartialEq, Eq)] -pub struct Memory { +pub struct Memory { // Memory is a vector of values. // We grow the memory when values past the end are set, extending with 0s. - inner: Vec, + inner: Vec>, } -impl Memory { +impl Memory { /// Gets the value at pointer - pub fn read(&self, ptr: MemoryAddress) -> Value { - self.inner.get(ptr.to_usize()).copied().unwrap_or(0_u128.into()) + pub fn read(&self, ptr: MemoryAddress) -> MemoryValue { + self.inner.get(ptr.to_usize()).cloned().unwrap_or_default() } pub fn read_ref(&self, ptr: MemoryAddress) -> MemoryAddress { MemoryAddress(self.read(ptr).to_usize()) } - pub fn read_slice(&self, addr: MemoryAddress, len: usize) -> &[Value] { + pub fn read_slice(&self, addr: MemoryAddress, len: usize) -> &[MemoryValue] { + // Allows to read a slice of uninitialized memory if the length is zero. + // Ideally we'd be able to read uninitialized memory in general (as read does) + // but that's not possible if we want to return a slice instead of owned data. + if len == 0 { + return &[]; + } &self.inner[addr.to_usize()..(addr.to_usize() + len)] } /// Sets the value at pointer `ptr` to `value` - pub fn write(&mut self, ptr: MemoryAddress, value: Value) { + pub fn write(&mut self, ptr: MemoryAddress, value: MemoryValue) { self.resize_to_fit(ptr.to_usize() + 1); self.inner[ptr.to_usize()] = value; } @@ -33,17 +315,17 @@ impl Memory { // Calculate new memory size let new_size = std::cmp::max(self.inner.len(), size); // Expand memory to new size with default values if needed - self.inner.resize(new_size, Value::from(FieldElement::zero())); + self.inner.resize(new_size, MemoryValue::default()); } /// Sets the values after pointer `ptr` to `values` - pub fn write_slice(&mut self, ptr: MemoryAddress, values: &[Value]) { + pub fn write_slice(&mut self, ptr: MemoryAddress, values: &[MemoryValue]) { self.resize_to_fit(ptr.to_usize() + values.len()); - self.inner[ptr.to_usize()..(ptr.to_usize() + values.len())].copy_from_slice(values); + self.inner[ptr.to_usize()..(ptr.to_usize() + values.len())].clone_from_slice(values); } /// Returns the values of the memory - pub fn values(&self) -> &[Value] { + pub fn values(&self) -> &[MemoryValue] { &self.inner } } diff --git a/aztec_macros/Cargo.toml b/aztec_macros/Cargo.toml index ed9821fabcf..ed70066af22 100644 --- a/aztec_macros/Cargo.toml +++ b/aztec_macros/Cargo.toml @@ -10,7 +10,10 @@ repository.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +acvm.workspace = true noirc_frontend.workspace = true noirc_errors.workspace = true iter-extended.workspace = true convert_case = "0.6.0" +regex = "1.10" + diff --git a/aztec_macros/src/lib.rs b/aztec_macros/src/lib.rs index ba577d293ff..2daf86dc643 100644 --- a/aztec_macros/src/lib.rs +++ b/aztec_macros/src/lib.rs @@ -1,27 +1,33 @@ -use std::borrow::{Borrow, BorrowMut}; -use std::vec; +mod transforms; +mod utils; -use convert_case::{Case, Casing}; -use iter_extended::vecmap; use noirc_errors::Location; -use noirc_frontend::hir::def_collector::dc_crate::{UnresolvedFunctions, UnresolvedTraitImpl}; -use noirc_frontend::hir::def_map::{LocalModuleId, ModuleId}; -use noirc_frontend::macros_api::parse_program; -use noirc_frontend::macros_api::FieldElement; +use transforms::{ + compute_note_hash_and_nullifier::inject_compute_note_hash_and_nullifier, + contract_interface::{ + generate_contract_interface, stub_function, update_fn_signatures_in_contract_interface, + }, + events::{generate_selector_impl, transform_events}, + functions::{ + check_for_public_args, export_fn_abi, transform_function, transform_unconstrained, + }, + note_interface::{generate_note_interface_impl, inject_note_exports}, + storage::{ + assign_storage_slots, check_for_storage_definition, check_for_storage_implementation, + generate_storage_implementation, generate_storage_layout, inject_context_in_storage, + }, +}; + use noirc_frontend::macros_api::{ - BlockExpression, CallExpression, CastExpression, Distinctness, Expression, ExpressionKind, - ForLoopStatement, ForRange, FunctionDefinition, FunctionReturnType, FunctionVisibility, - HirContext, HirExpression, HirLiteral, HirStatement, Ident, ImportStatement, IndexExpression, - LetStatement, Literal, MemberAccessExpression, MethodCallExpression, NoirFunction, NoirStruct, - Param, Path, PathKind, Pattern, PrefixExpression, SecondaryAttribute, Signedness, Span, - Statement, StatementKind, StructType, Type, TypeImpl, UnaryOp, UnresolvedType, - UnresolvedTypeData, Visibility, + CrateId, FileId, HirContext, MacroError, MacroProcessor, SortedModule, Span, +}; + +use utils::{ + ast_utils::is_custom_attribute, + checks::{check_for_aztec_dependency, has_aztec_dependency}, + constants::MAX_CONTRACT_PRIVATE_FUNCTIONS, + errors::AztecMacroError, }; -use noirc_frontend::macros_api::{CrateId, FileId}; -use noirc_frontend::macros_api::{MacroError, MacroProcessor}; -use noirc_frontend::macros_api::{ModuleDefId, NodeInterner, SortedModule, StructId}; -use noirc_frontend::node_interner::{FuncId, TraitId, TraitImplId, TraitImplKind}; -use noirc_frontend::Lambda; pub struct AztecMacro; impl MacroProcessor for AztecMacro { @@ -29,28 +35,10 @@ impl MacroProcessor for AztecMacro { &self, ast: SortedModule, crate_id: &CrateId, + file_id: FileId, context: &HirContext, ) -> Result { - transform(ast, crate_id, context) - } - - fn process_unresolved_traits_impls( - &self, - crate_id: &CrateId, - context: &mut HirContext, - unresolved_traits_impls: &[UnresolvedTraitImpl], - collected_functions: &mut Vec, - ) -> Result<(), (MacroError, FileId)> { - if has_aztec_dependency(crate_id, context) { - inject_compute_note_hash_and_nullifier( - crate_id, - context, - unresolved_traits_impls, - collected_functions, - ) - } else { - Ok(()) - } + transform(ast, crate_id, file_id, context) } fn process_typed_ast( @@ -62,215 +50,6 @@ impl MacroProcessor for AztecMacro { } } -const FUNCTION_TREE_HEIGHT: u32 = 5; -const MAX_CONTRACT_PRIVATE_FUNCTIONS: usize = 2_usize.pow(FUNCTION_TREE_HEIGHT); - -#[derive(Debug, Clone)] -pub enum AztecMacroError { - AztecDepNotFound, - ContractHasTooManyPrivateFunctions { span: Span }, - ContractConstructorMissing { span: Span }, - UnsupportedFunctionArgumentType { span: Span, typ: UnresolvedTypeData }, - UnsupportedStorageType { span: Option, typ: UnresolvedTypeData }, - CouldNotAssignStorageSlots { secondary_message: Option }, - EventError { span: Span, message: String }, -} - -impl From for MacroError { - fn from(err: AztecMacroError) -> Self { - match err { - AztecMacroError::AztecDepNotFound {} => MacroError { - primary_message: "Aztec dependency not found. Please add aztec as a dependency in your Cargo.toml. For more information go to https://docs.aztec.network/developers/debugging/aztecnr-errors#aztec-dependency-not-found-please-add-aztec-as-a-dependency-in-your-nargotoml".to_owned(), - secondary_message: None, - span: None, - }, - AztecMacroError::ContractHasTooManyPrivateFunctions { span } => MacroError { - primary_message: format!("Contract can only have a maximum of {} private functions", MAX_CONTRACT_PRIVATE_FUNCTIONS), - secondary_message: None, - span: Some(span), - }, - AztecMacroError::ContractConstructorMissing { span } => MacroError { - primary_message: "Contract must have a constructor function".to_owned(), - secondary_message: None, - span: Some(span), - }, - AztecMacroError::UnsupportedFunctionArgumentType { span, typ } => MacroError { - primary_message: format!("Provided parameter type `{typ:?}` is not supported in Aztec contract interface"), - secondary_message: None, - span: Some(span), - }, - AztecMacroError::UnsupportedStorageType { span, typ } => MacroError { - primary_message: format!("Provided storage type `{typ:?}` is not directly supported in Aztec. Please provide a custom storage implementation"), - secondary_message: None, - span, - }, - AztecMacroError::CouldNotAssignStorageSlots { secondary_message } => MacroError { - primary_message: "Could not assign storage slots, please provide a custom storage implementation".to_string(), - secondary_message, - span: None, - }, - AztecMacroError::EventError { span, message } => MacroError { - primary_message: message, - secondary_message: None, - span: Some(span), - }, - } - } -} - -// -// Helper macros for creating noir ast nodes -// -fn ident(name: &str) -> Ident { - Ident::new(name.to_string(), Span::default()) -} - -fn ident_path(name: &str) -> Path { - Path::from_ident(ident(name)) -} - -fn path(ident: Ident) -> Path { - Path::from_ident(ident) -} - -fn expression(kind: ExpressionKind) -> Expression { - Expression::new(kind, Span::default()) -} - -fn variable(name: &str) -> Expression { - expression(ExpressionKind::Variable(ident_path(name))) -} - -fn variable_ident(identifier: Ident) -> Expression { - expression(ExpressionKind::Variable(path(identifier))) -} - -fn variable_path(path: Path) -> Expression { - expression(ExpressionKind::Variable(path)) -} - -fn method_call(object: Expression, method_name: &str, arguments: Vec) -> Expression { - expression(ExpressionKind::MethodCall(Box::new(MethodCallExpression { - object, - method_name: ident(method_name), - arguments, - }))) -} - -fn call(func: Expression, arguments: Vec) -> Expression { - expression(ExpressionKind::Call(Box::new(CallExpression { func: Box::new(func), arguments }))) -} - -fn pattern(name: &str) -> Pattern { - Pattern::Identifier(ident(name)) -} - -fn mutable(name: &str) -> Pattern { - Pattern::Mutable(Box::new(pattern(name)), Span::default(), true) -} - -fn mutable_assignment(name: &str, assigned_to: Expression) -> Statement { - make_statement(StatementKind::Let(LetStatement { - pattern: mutable(name), - r#type: make_type(UnresolvedTypeData::Unspecified), - expression: assigned_to, - })) -} - -fn mutable_reference(variable_name: &str) -> Expression { - expression(ExpressionKind::Prefix(Box::new(PrefixExpression { - operator: UnaryOp::MutableReference, - rhs: variable(variable_name), - }))) -} - -fn assignment(name: &str, assigned_to: Expression) -> Statement { - make_statement(StatementKind::Let(LetStatement { - pattern: pattern(name), - r#type: make_type(UnresolvedTypeData::Unspecified), - expression: assigned_to, - })) -} - -fn member_access(lhs: &str, rhs: &str) -> Expression { - expression(ExpressionKind::MemberAccess(Box::new(MemberAccessExpression { - lhs: variable(lhs), - rhs: ident(rhs), - }))) -} - -fn return_type(path: Path) -> FunctionReturnType { - let ty = make_type(UnresolvedTypeData::Named(path, vec![], true)); - FunctionReturnType::Ty(ty) -} - -fn lambda(parameters: Vec<(Pattern, UnresolvedType)>, body: Expression) -> Expression { - expression(ExpressionKind::Lambda(Box::new(Lambda { - parameters, - return_type: UnresolvedType { - typ: UnresolvedTypeData::Unspecified, - span: Some(Span::default()), - }, - body, - }))) -} - -macro_rules! chained_path { - ( $base:expr ) => { - { - ident_path($base) - } - }; - ( $base:expr $(, $tail:expr)* ) => { - { - let mut base_path = ident_path($base); - $( - base_path.segments.push(ident($tail)); - )* - base_path - } - } -} - -macro_rules! chained_dep { - ( $base:expr $(, $tail:expr)* ) => { - { - let mut base_path = ident_path($base); - base_path.kind = PathKind::Dep; - $( - base_path.segments.push(ident($tail)); - )* - base_path - } - } -} - -fn cast(lhs: Expression, ty: UnresolvedTypeData) -> Expression { - expression(ExpressionKind::Cast(Box::new(CastExpression { lhs, r#type: make_type(ty) }))) -} - -fn make_type(typ: UnresolvedTypeData) -> UnresolvedType { - UnresolvedType { typ, span: Some(Span::default()) } -} - -fn index_array(array: Ident, index: &str) -> Expression { - expression(ExpressionKind::Index(Box::new(IndexExpression { - collection: variable_path(path(array)), - index: variable(index), - }))) -} - -fn index_array_variable(array: Expression, index: &str) -> Expression { - expression(ExpressionKind::Index(Box::new(IndexExpression { - collection: array, - index: variable(index), - }))) -} - -fn import(path: Path) -> ImportStatement { - ImportStatement { path, alias: None } -} - // // Create AST Nodes for Aztec // @@ -280,175 +59,123 @@ fn import(path: Path) -> ImportStatement { fn transform( mut ast: SortedModule, crate_id: &CrateId, + file_id: FileId, context: &HirContext, ) -> Result { // Usage -> mut ast -> aztec_library::transform(&mut ast) - // Covers all functions in the ast for submodule in ast.submodules.iter_mut().filter(|submodule| submodule.is_contract) { - if transform_module(&mut submodule.contents, crate_id, context) - .map_err(|(err, file_id)| (err.into(), file_id))? + if transform_module( + crate_id, + &file_id, + context, + &mut submodule.contents, + submodule.name.0.contents.as_str(), + ) + .map_err(|err| (err.into(), file_id))? { check_for_aztec_dependency(crate_id, context)?; - include_relevant_imports(&mut submodule.contents); } } - Ok(ast) -} - -// -// Transform Hir Nodes for Aztec -// - -/// Completes the Hir with data gathered from type resolution -fn transform_hir( - crate_id: &CrateId, - context: &mut HirContext, -) -> Result<(), (AztecMacroError, FileId)> { - transform_events(crate_id, context)?; - assign_storage_slots(crate_id, context) -} -/// Includes an import to the aztec library if it has not been included yet -fn include_relevant_imports(ast: &mut SortedModule) { - // Create the aztec import path using the assumed chained_dep! macro - let aztec_import_path = import(chained_dep!("aztec")); + generate_note_interface_impl(&mut ast).map_err(|err| (err.into(), file_id))?; - // Check if the aztec import already exists - let is_aztec_imported = - ast.imports.iter().any(|existing_import| existing_import.path == aztec_import_path.path); - - // If aztec is not imported, add the import at the beginning - if !is_aztec_imported { - ast.imports.insert(0, aztec_import_path); - } -} - -/// Creates an error alerting the user that they have not downloaded the Aztec-noir library -fn check_for_aztec_dependency( - crate_id: &CrateId, - context: &HirContext, -) -> Result<(), (MacroError, FileId)> { - if has_aztec_dependency(crate_id, context) { - Ok(()) - } else { - Err((AztecMacroError::AztecDepNotFound.into(), context.crate_graph[crate_id].root_file_id)) - } -} - -fn has_aztec_dependency(crate_id: &CrateId, context: &HirContext) -> bool { - context.crate_graph[crate_id].dependencies.iter().any(|dep| dep.as_name() == "aztec") -} - -// Check to see if the user has defined a storage struct -fn check_for_storage_definition(module: &SortedModule) -> bool { - module.types.iter().any(|r#struct| r#struct.name.0.contents == "Storage") -} - -// Check to see if the user has defined a storage struct -fn check_for_storage_implementation(module: &SortedModule) -> bool { - module.impls.iter().any(|r#impl| match &r#impl.object_type.typ { - UnresolvedTypeData::Named(path, _, _) => { - path.segments.last().is_some_and(|segment| segment.0.contents == "Storage") - } - _ => false, - }) -} - -// Check if "compute_note_hash_and_nullifier(AztecAddress,Field,Field,Field,[Field; N]) -> [Field; 4]" is defined -fn check_for_compute_note_hash_and_nullifier_definition( - functions_data: &[(LocalModuleId, FuncId, NoirFunction)], - module_id: LocalModuleId, -) -> bool { - functions_data.iter().filter(|func_data| func_data.0 == module_id).any(|func_data| { - func_data.2.def.name.0.contents == "compute_note_hash_and_nullifier" - && func_data.2.def.parameters.len() == 5 - && match &func_data.2.def.parameters[0].typ.typ { - UnresolvedTypeData::Named(path, _, _) => path.segments.last().unwrap().0.contents == "AztecAddress", - _ => false, - } - && func_data.2.def.parameters[1].typ.typ == UnresolvedTypeData::FieldElement - && func_data.2.def.parameters[2].typ.typ == UnresolvedTypeData::FieldElement - && func_data.2.def.parameters[3].typ.typ == UnresolvedTypeData::FieldElement - // checks if the 5th parameter is an array and the Box in - // Array(Option, Box) contains only fields - && match &func_data.2.def.parameters[4].typ.typ { - UnresolvedTypeData::Array(_, inner_type) => { - matches!(inner_type.typ, UnresolvedTypeData::FieldElement) - }, - _ => false, - } - // We check the return type the same way as we did the 5th parameter - && match &func_data.2.def.return_type { - FunctionReturnType::Default(_) => false, - FunctionReturnType::Ty(unresolved_type) => { - match &unresolved_type.typ { - UnresolvedTypeData::Array(_, inner_type) => { - matches!(inner_type.typ, UnresolvedTypeData::FieldElement) - }, - _ => false, - } - } - } - }) -} - -/// Checks if an attribute is a custom attribute with a specific name -fn is_custom_attribute(attr: &SecondaryAttribute, attribute_name: &str) -> bool { - if let SecondaryAttribute::Custom(custom_attr) = attr { - custom_attr.as_str() == attribute_name - } else { - false - } + Ok(ast) } /// Determines if ast nodes are annotated with aztec attributes. /// For annotated functions it calls the `transform` function which will perform the required transformations. /// Returns true if an annotated node is found, false otherwise fn transform_module( - module: &mut SortedModule, crate_id: &CrateId, + file_id: &FileId, context: &HirContext, -) -> Result { + module: &mut SortedModule, + module_name: &str, +) -> Result { let mut has_transformed_module = false; // Check for a user defined storage struct - let storage_defined = check_for_storage_definition(module); - let storage_implemented = check_for_storage_implementation(module); - let crate_graph = &context.crate_graph[crate_id]; + let maybe_storage_struct_name = check_for_storage_definition(module)?; - if storage_defined && !storage_implemented { - generate_storage_implementation(module).map_err(|err| (err, crate_graph.root_file_id))?; + let storage_defined = maybe_storage_struct_name.is_some(); + + if let Some(ref storage_struct_name) = maybe_storage_struct_name { + inject_context_in_storage(module)?; + if !check_for_storage_implementation(module, storage_struct_name) { + generate_storage_implementation(module, storage_struct_name)?; + } + // Make sure we're only generating the storage layout for the root crate + // In case we got a contract importing other contracts for their interface, we + // don't want to generate the storage layout for them + if crate_id == context.root_crate_id() { + generate_storage_layout(module, storage_struct_name.clone())?; + } } - for structure in module.types.iter() { - if structure.attributes.iter().any(|attr| matches!(attr, SecondaryAttribute::Event)) { + for structure in module.types.iter_mut() { + if structure.attributes.iter().any(|attr| is_custom_attribute(attr, "aztec(event)")) { module.impls.push(generate_selector_impl(structure)); has_transformed_module = true; } } + let has_initializer = module.functions.iter().any(|func| { + func.def + .attributes + .secondary + .iter() + .any(|attr| is_custom_attribute(attr, "aztec(initializer)")) + }); + + let mut stubs: Vec<_> = vec![]; + for func in module.functions.iter_mut() { + let mut is_private = false; + let mut is_public = false; + let mut is_initializer = false; + let mut is_internal = false; + let mut insert_init_check = has_initializer; + let mut is_static = false; + for secondary_attribute in func.def.attributes.secondary.clone() { - let crate_graph = &context.crate_graph[crate_id]; if is_custom_attribute(&secondary_attribute, "aztec(private)") { - transform_function("Private", func, storage_defined) - .map_err(|err| (err, crate_graph.root_file_id))?; - has_transformed_module = true; + is_private = true; + } else if is_custom_attribute(&secondary_attribute, "aztec(initializer)") { + is_initializer = true; + insert_init_check = false; + } else if is_custom_attribute(&secondary_attribute, "aztec(noinitcheck)") { + insert_init_check = false; + } else if is_custom_attribute(&secondary_attribute, "aztec(internal)") { + is_internal = true; } else if is_custom_attribute(&secondary_attribute, "aztec(public)") { - transform_function("Public", func, storage_defined) - .map_err(|err| (err, crate_graph.root_file_id))?; - has_transformed_module = true; - } else if is_custom_attribute(&secondary_attribute, "aztec(public-vm)") { - transform_vm_function(func, storage_defined) - .map_err(|err| (err, crate_graph.root_file_id))?; - has_transformed_module = true; + is_public = true; + } + if is_custom_attribute(&secondary_attribute, "aztec(view)") { + is_static = true; } } - // Add the storage struct to the beginning of the function if it is unconstrained in an aztec contract - if storage_defined && func.def.is_unconstrained { - transform_unconstrained(func); + + // Apply transformations to the function based on collected attributes + if is_private || is_public { + let fn_type = if is_private { "Private" } else { "Public" }; + let stub_src = stub_function(fn_type, func, is_static); + stubs.push((stub_src, Location { file: *file_id, span: func.name_ident().span() })); + + export_fn_abi(&mut module.types, func)?; + transform_function( + fn_type, + func, + maybe_storage_struct_name.clone(), + is_initializer, + insert_init_check, + is_internal, + is_static, + )?; + has_transformed_module = true; + } else if storage_defined && func.def.is_unconstrained { + transform_unconstrained(func, maybe_storage_struct_name.clone().unwrap()); has_transformed_module = true; } } @@ -456,7 +183,7 @@ fn transform_module( if has_transformed_module { // We only want to run these checks if the macro processor has found the module to be an Aztec contract. - let private_functions_count = module + let private_functions: Vec<_> = module .functions .iter() .filter(|func| { @@ -466,1365 +193,54 @@ fn transform_module( .iter() .any(|attr| is_custom_attribute(attr, "aztec(private)")) }) - .count(); - - if private_functions_count > MAX_CONTRACT_PRIVATE_FUNCTIONS { - let crate_graph = &context.crate_graph[crate_id]; - return Err(( - AztecMacroError::ContractHasTooManyPrivateFunctions { span: Span::default() }, - crate_graph.root_file_id, - )); - } - - let constructor_defined = module.functions.iter().any(|func| func.name() == "constructor"); - if !constructor_defined { - let crate_graph = &context.crate_graph[crate_id]; - return Err(( - AztecMacroError::ContractConstructorMissing { span: Span::default() }, - crate_graph.root_file_id, - )); - } - } - - Ok(has_transformed_module) -} - -/// Auxiliary function to generate the storage constructor for a given field, using -/// the Storage definition as a reference. Supports nesting. -fn generate_storage_field_constructor( - (type_ident, unresolved_type): &(Ident, UnresolvedType), - slot: Expression, -) -> Result { - let typ = &unresolved_type.typ; - match typ { - UnresolvedTypeData::Named(path, generics, _) => { - let mut new_path = path.clone().to_owned(); - new_path.segments.push(ident("new")); - match path.segments.last().unwrap().0.contents.as_str() { - "Map" => Ok(call( - variable_path(new_path), - vec![ - variable("context"), - slot, - lambda( - vec![ - ( - pattern("context"), - make_type(UnresolvedTypeData::Named( - chained_path!("aztec", "context", "Context"), - vec![], - true, - )), - ), - ( - Pattern::Identifier(ident("slot")), - make_type(UnresolvedTypeData::FieldElement), - ), - ], - generate_storage_field_constructor( - &(type_ident.clone(), generics.iter().last().unwrap().clone()), - variable("slot"), - )?, - ), - ], - )), - _ => Ok(call(variable_path(new_path), vec![variable("context"), slot])), - } - } - _ => Err(AztecMacroError::UnsupportedStorageType { - typ: typ.clone(), - span: Some(type_ident.span()), - }), - } -} - -// Generates the Storage implementation block from the Storage struct definition if it does not exist -/// From: -/// -/// struct Storage { -/// a_map: Map>, -/// a_nested_map: Map>>, -/// a_field: SomeStoragePrimitive, -/// } -/// -/// To: -/// -/// impl Storage { -/// fn init(context: Context) -> Self { -/// Storage { -/// a_map: Map::new(context, 0, |context, slot| { -/// SomeStoragePrimitive::new(context, slot) -/// }), -/// a_nested_map: Map::new(context, 0, |context, slot| { -/// Map::new(context, slot, |context, slot| { -/// SomeStoragePrimitive::new(context, slot) -/// }) -/// }), -/// a_field: SomeStoragePrimitive::new(context, 0), -/// } -/// } -/// } -/// -/// Storage slots are generated as 0 and will be populated using the information from the HIR -/// at a later stage. -fn generate_storage_implementation(module: &mut SortedModule) -> Result<(), AztecMacroError> { - let definition = - module.types.iter().find(|r#struct| r#struct.name.0.contents == "Storage").unwrap(); - - let slot_zero = expression(ExpressionKind::Literal(Literal::Integer( - FieldElement::from(i128::from(0)), - false, - ))); - - let field_constructors = definition - .fields - .iter() - .flat_map(|field| { - generate_storage_field_constructor(field, slot_zero.clone()) - .map(|expression| (field.0.clone(), expression)) - }) - .collect(); - - let storage_constructor_statement = make_statement(StatementKind::Expression(expression( - ExpressionKind::constructor((chained_path!("Storage"), field_constructors)), - ))); - - let init = NoirFunction::normal(FunctionDefinition::normal( - &ident("init"), - &vec![], - &[( - ident("context"), - make_type(UnresolvedTypeData::Named( - chained_path!("aztec", "context", "Context"), - vec![], - true, - )), - )], - &BlockExpression { is_unsafe: false, statements: vec![storage_constructor_statement] }, - &[], - &return_type(chained_path!("Self")), - )); - - let storage_impl = TypeImpl { - object_type: UnresolvedType { - typ: UnresolvedTypeData::Named(chained_path!("Storage"), vec![], true), - span: Some(Span::default()), - }, - type_span: Span::default(), - generics: vec![], - methods: vec![(init, Span::default())], - }; - module.impls.push(storage_impl); - - Ok(()) -} - -/// If it does, it will insert the following things: -/// - A new Input that is provided for a kernel app circuit, named: {Public/Private}ContextInputs -/// - Hashes all of the function input variables -/// - This instantiates a helper function -fn transform_function( - ty: &str, - func: &mut NoirFunction, - storage_defined: bool, -) -> Result<(), AztecMacroError> { - let context_name = format!("{}Context", ty); - let inputs_name = format!("{}ContextInputs", ty); - let return_type_name = format!("{}CircuitPublicInputs", ty); - - // Add access to the storage struct - if storage_defined { - let storage_def = abstract_storage(&ty.to_lowercase(), false); - func.def.body.statements.insert(0, storage_def); - } - - // Insert the context creation as the first action - let create_context = create_context(&context_name, &func.def.parameters)?; - func.def.body.statements.splice(0..0, (create_context).iter().cloned()); - - // Add the inputs to the params - let input = create_inputs(&inputs_name); - func.def.parameters.insert(0, input); - - // Abstract return types such that they get added to the kernel's return_values - if let Some(return_values) = abstract_return_values(func) { - // In case we are pushing return values to the context, we remove the statement that originated it - // This avoids running duplicate code, since blocks like if/else can be value returning statements - func.def.body.statements.pop(); - // Add the new return statement - func.def.body.statements.push(return_values); - } - - // Push the finish method call to the end of the function - let finish_def = create_context_finish(); - func.def.body.statements.push(finish_def); - - let return_type = create_return_type(&return_type_name); - func.def.return_type = return_type; - func.def.return_visibility = Visibility::Public; - - // Distinct return types are only required for private functions - // Public functions should have open auto-inferred - match ty { - "Private" => func.def.return_distinctness = Distinctness::Distinct, - "Public" => func.def.is_open = true, - _ => (), - } - - Ok(()) -} - -/// Transform a function to work with AVM bytecode -fn transform_vm_function( - func: &mut NoirFunction, - _storage_defined: bool, -) -> Result<(), AztecMacroError> { - // Push Avm context creation to the beginning of the function - let create_context = create_avm_context()?; - func.def.body.statements.insert(0, create_context); - - // We want the function to be seen as a public function - func.def.is_open = true; - - // NOTE: the line below is a temporary hack to trigger external transpilation tools - // It will be removed once the transpiler is integrated into the Noir compiler - func.def.name.0.contents = format!("avm_{}", func.def.name.0.contents); - Ok(()) -} - -/// Transform Unconstrained -/// -/// Inserts the following code at the beginning of an unconstrained function -/// ```noir -/// let storage = Storage::init(Context::none()); -/// ``` -/// -/// This will allow developers to access their contract' storage struct in unconstrained functions -fn transform_unconstrained(func: &mut NoirFunction) { - func.def.body.statements.insert(0, abstract_storage("Unconstrained", true)); -} - -fn collect_crate_structs(crate_id: &CrateId, context: &HirContext) -> Vec { - context - .def_map(crate_id) - .expect("ICE: Missing crate in def_map") - .modules() - .iter() - .flat_map(|(_, module)| { - module.type_definitions().filter_map(|typ| { - if let ModuleDefId::TypeId(struct_id) = typ { - Some(struct_id) - } else { - None - } - }) - }) - .collect() -} + .collect(); -fn collect_traits(context: &HirContext) -> Vec { - let crates = context.crates(); - crates - .flat_map(|crate_id| context.def_map(&crate_id).map(|def_map| def_map.modules())) - .flatten() - .flat_map(|module| { - module.type_definitions().filter_map(|typ| { - if let ModuleDefId::TraitId(struct_id) = typ { - Some(struct_id) - } else { - None - } + let public_functions: Vec<_> = module + .functions + .iter() + .filter(|func| { + func.def + .attributes + .secondary + .iter() + .any(|attr| is_custom_attribute(attr, "aztec(public)")) }) - }) - .collect() -} + .collect(); -/// Substitutes the signature literal that was introduced in the selector method previously with the actual signature. -fn transform_event( - struct_id: StructId, - interner: &mut NodeInterner, -) -> Result<(), (AztecMacroError, FileId)> { - let struct_type = interner.get_struct(struct_id); - let selector_id = interner - .lookup_method(&Type::Struct(struct_type.clone(), vec![]), struct_id, "selector", false) - .ok_or_else(|| { - let error = AztecMacroError::EventError { - span: struct_type.borrow().location.span, - message: "Selector method not found".to_owned(), - }; - (error, struct_type.borrow().location.file) - })?; - let selector_function = interner.function(&selector_id); + let private_function_count = private_functions.len(); - let compute_selector_statement = interner.statement( - selector_function.block(interner).statements().first().ok_or_else(|| { - let error = AztecMacroError::EventError { - span: struct_type.borrow().location.span, - message: "Compute selector statement not found".to_owned(), - }; - (error, struct_type.borrow().location.file) - })?, - ); + check_for_public_args(&private_functions)?; - let compute_selector_expression = match compute_selector_statement { - HirStatement::Expression(expression_id) => match interner.expression(&expression_id) { - HirExpression::Call(hir_call_expression) => Some(hir_call_expression), - _ => None, - }, - _ => None, - } - .ok_or_else(|| { - let error = AztecMacroError::EventError { - span: struct_type.borrow().location.span, - message: "Compute selector statement is not a call expression".to_owned(), - }; - (error, struct_type.borrow().location.file) - })?; + check_for_public_args(&public_functions)?; - let first_arg_id = compute_selector_expression.arguments.first().ok_or_else(|| { - let error = AztecMacroError::EventError { - span: struct_type.borrow().location.span, - message: "Compute selector statement is not a call expression".to_owned(), - }; - (error, struct_type.borrow().location.file) - })?; - - match interner.expression(first_arg_id) { - HirExpression::Literal(HirLiteral::Str(signature)) - if signature == SIGNATURE_PLACEHOLDER => - { - let selector_literal_id = *first_arg_id; - - let structure = interner.get_struct(struct_id); - let signature = event_signature(&structure.borrow()); - interner.update_expression(selector_literal_id, |expr| { - *expr = HirExpression::Literal(HirLiteral::Str(signature.clone())); + if private_function_count > MAX_CONTRACT_PRIVATE_FUNCTIONS { + return Err(AztecMacroError::ContractHasTooManyPrivateFunctions { + span: Span::default(), }); - - // Also update the type! It might have a different length now than the placeholder. - interner.push_expr_type( - selector_literal_id, - Type::String(Box::new(Type::Constant(signature.len() as u64))), - ); - Ok(()) - } - _ => Err(( - AztecMacroError::EventError { - span: struct_type.borrow().location.span, - message: "Signature placeholder literal does not match".to_owned(), - }, - struct_type.borrow().location.file, - )), - } -} - -fn transform_events( - crate_id: &CrateId, - context: &mut HirContext, -) -> Result<(), (AztecMacroError, FileId)> { - for struct_id in collect_crate_structs(crate_id, context) { - let attributes = context.def_interner.struct_attributes(&struct_id); - if attributes.iter().any(|attr| matches!(attr, SecondaryAttribute::Event)) { - transform_event(struct_id, &mut context.def_interner)?; - } - } - Ok(()) -} - -/// Obtains the serialized length of a type that implements the Serialize trait. -fn get_serialized_length( - traits: &[TraitId], - typ: &Type, - interner: &NodeInterner, -) -> Result { - let (struct_name, maybe_stored_in_state) = match typ { - Type::Struct(struct_type, generics) => { - Ok((struct_type.borrow().name.0.contents.clone(), generics.first())) - } - _ => Err(AztecMacroError::CouldNotAssignStorageSlots { - secondary_message: Some("State storage variable must be a struct".to_string()), - }), - }?; - let stored_in_state = - maybe_stored_in_state.ok_or(AztecMacroError::CouldNotAssignStorageSlots { - secondary_message: Some("State storage variable must be generic".to_string()), - })?; - - let is_note = traits.iter().any(|&trait_id| { - let r#trait = interner.get_trait(trait_id); - r#trait.name.0.contents == "NoteInterface" - && !interner.lookup_all_trait_implementations(stored_in_state, trait_id).is_empty() - }); - - // Maps and (private) Notes always occupy a single slot. Someone could store a Note in PublicMutable for whatever reason though. - if struct_name == "Map" || (is_note && struct_name != "PublicMutable") { - return Ok(1); - } - - let serialized_trait_impl_kind = traits - .iter() - .find_map(|&trait_id| { - let r#trait = interner.get_trait(trait_id); - if r#trait.borrow().name.0.contents == "Serialize" - && r#trait.borrow().generics.len() == 1 - { - interner - .lookup_all_trait_implementations(stored_in_state, trait_id) - .into_iter() - .next() - } else { - None - } - }) - .ok_or(AztecMacroError::CouldNotAssignStorageSlots { - secondary_message: Some("Stored data must implement Serialize trait".to_string()), - })?; - - let serialized_trait_impl_id = match serialized_trait_impl_kind { - TraitImplKind::Normal(trait_impl_id) => Ok(trait_impl_id), - _ => Err(AztecMacroError::CouldNotAssignStorageSlots { secondary_message: None }), - }?; - - let serialized_trait_impl_shared = interner.get_trait_implementation(*serialized_trait_impl_id); - let serialized_trait_impl = serialized_trait_impl_shared.borrow(); - - match serialized_trait_impl.trait_generics.first().unwrap() { - Type::Constant(value) => Ok(*value), - _ => Err(AztecMacroError::CouldNotAssignStorageSlots { secondary_message: None }), - } -} - -/// Assigns storage slots to the storage struct fields based on the serialized length of the types. This automatic assignment -/// will only trigger if the assigned storage slot is invalid (0 as generated by generate_storage_implementation) -fn assign_storage_slots( - crate_id: &CrateId, - context: &mut HirContext, -) -> Result<(), (AztecMacroError, FileId)> { - let traits: Vec<_> = collect_traits(context); - for struct_id in collect_crate_structs(crate_id, context) { - let interner: &mut NodeInterner = context.def_interner.borrow_mut(); - let r#struct = interner.get_struct(struct_id); - let file_id = r#struct.borrow().location.file; - if r#struct.borrow().name.0.contents == "Storage" && r#struct.borrow().id.krate().is_root() - { - let init_id = interner - .lookup_method( - &Type::Struct(interner.get_struct(struct_id), vec![]), - struct_id, - "init", - false, - ) - .ok_or(( - AztecMacroError::CouldNotAssignStorageSlots { - secondary_message: Some( - "Storage struct must have an init function".to_string(), - ), - }, - file_id, - ))?; - let init_function = interner.function(&init_id).block(interner); - let init_function_statement_id = init_function.statements().first().ok_or(( - AztecMacroError::CouldNotAssignStorageSlots { - secondary_message: Some("Init storage statement not found".to_string()), - }, - file_id, - ))?; - let storage_constructor_statement = interner.statement(init_function_statement_id); - - let storage_constructor_expression = match storage_constructor_statement { - HirStatement::Expression(expression_id) => { - match interner.expression(&expression_id) { - HirExpression::Constructor(hir_constructor_expression) => { - Ok(hir_constructor_expression) - } - _ => Err((AztecMacroError::CouldNotAssignStorageSlots { - secondary_message: Some( - "Storage constructor statement must be a constructor expression" - .to_string(), - ), - }, file_id)) - } - } - _ => Err(( - AztecMacroError::CouldNotAssignStorageSlots { - secondary_message: Some( - "Storage constructor statement must be an expression".to_string(), - ), - }, - file_id, - )), - }?; - - let mut storage_slot: u64 = 1; - for (index, (_, expr_id)) in storage_constructor_expression.fields.iter().enumerate() { - let fields = r#struct.borrow().get_fields(&[]); - let (_, field_type) = fields.get(index).unwrap(); - let new_call_expression = match interner.expression(expr_id) { - HirExpression::Call(hir_call_expression) => Ok(hir_call_expression), - _ => Err(( - AztecMacroError::CouldNotAssignStorageSlots { - secondary_message: Some( - "Storage field initialization expression is not a call expression" - .to_string(), - ), - }, - file_id, - )), - }?; - - let slot_arg_expression = interner.expression(&new_call_expression.arguments[1]); - - let current_storage_slot = match slot_arg_expression { - HirExpression::Literal(HirLiteral::Integer(slot, _)) => Ok(slot.to_u128()), - _ => Err(( - AztecMacroError::CouldNotAssignStorageSlots { - secondary_message: Some( - "Storage slot argument expression must be a literal integer" - .to_string(), - ), - }, - file_id, - )), - }?; - - if current_storage_slot != 0 { - continue; - } - - let type_serialized_len = get_serialized_length(&traits, field_type, interner) - .map_err(|err| (err, file_id))?; - interner.update_expression(new_call_expression.arguments[1], |expr| { - *expr = HirExpression::Literal(HirLiteral::Integer( - FieldElement::from(u128::from(storage_slot)), - false, - )); - }); - - storage_slot += type_serialized_len; - } - } - } - Ok(()) -} - -const SIGNATURE_PLACEHOLDER: &str = "SIGNATURE_PLACEHOLDER"; - -/// Generates the impl for an event selector -/// -/// Inserts the following code: -/// ```noir -/// impl SomeStruct { -/// fn selector() -> FunctionSelector { -/// aztec::protocol_types::abis::function_selector::FunctionSelector::from_signature("SIGNATURE_PLACEHOLDER") -/// } -/// } -/// ``` -/// -/// This allows developers to emit events without having to write the signature of the event every time they emit it. -/// The signature cannot be known at this point since types are not resolved yet, so we use a signature placeholder. -/// It'll get resolved after by transforming the HIR. -fn generate_selector_impl(structure: &NoirStruct) -> TypeImpl { - let struct_type = - make_type(UnresolvedTypeData::Named(path(structure.name.clone()), vec![], true)); - - let selector_path = - chained_path!("aztec", "protocol_types", "abis", "function_selector", "FunctionSelector"); - let mut from_signature_path = selector_path.clone(); - from_signature_path.segments.push(ident("from_signature")); - - let selector_fun_body = BlockExpression { - is_unsafe: false, - statements: vec![make_statement(StatementKind::Expression(call( - variable_path(from_signature_path), - vec![expression(ExpressionKind::Literal(Literal::Str( - SIGNATURE_PLACEHOLDER.to_string(), - )))], - )))], - }; - - // Define `FunctionSelector` return type - let return_type = - FunctionReturnType::Ty(make_type(UnresolvedTypeData::Named(selector_path, vec![], true))); - - let mut selector_fn_def = FunctionDefinition::normal( - &ident("selector"), - &vec![], - &[], - &selector_fun_body, - &[], - &return_type, - ); - - selector_fn_def.visibility = FunctionVisibility::Public; - - // Seems to be necessary on contract modules - selector_fn_def.return_visibility = Visibility::Public; - - TypeImpl { - object_type: struct_type, - type_span: structure.span, - generics: vec![], - methods: vec![(NoirFunction::normal(selector_fn_def), Span::default())], - } -} - -/// Helper function that returns what the private context would look like in the ast -/// This should make it available to be consumed within aztec private annotated functions. -/// -/// The replaced code: -/// ```noir -/// /// Before -/// fn foo(inputs: PrivateContextInputs) { -/// // ... -/// } -/// -/// /// After -/// #[aztec(private)] -/// fn foo() { -/// // ... -/// } -fn create_inputs(ty: &str) -> Param { - let context_ident = ident("inputs"); - let context_pattern = Pattern::Identifier(context_ident); - - let path_snippet = ty.to_case(Case::Snake); // e.g. private_context_inputs - let type_path = chained_path!("aztec", "context", "inputs", &path_snippet, ty); - - let context_type = make_type(UnresolvedTypeData::Named(type_path, vec![], true)); - let visibility = Visibility::Private; - - Param { pattern: context_pattern, typ: context_type, visibility, span: Span::default() } -} - -/// Creates the private context object to be accessed within the function, the parameters need to be extracted to be -/// appended into the args hash object. -/// -/// The replaced code: -/// ```noir -/// #[aztec(private)] -/// fn foo(structInput: SomeStruct, arrayInput: [u8; 10], fieldInput: Field) -> Field { -/// // Create the hasher object -/// let mut hasher = Hasher::new(); -/// -/// // struct inputs call serialize on them to add an array of fields -/// hasher.add_multiple(structInput.serialize()); -/// -/// // Array inputs are iterated over and each element is added to the hasher (as a field) -/// for i in 0..arrayInput.len() { -/// hasher.add(arrayInput[i] as Field); -/// } -/// // Field inputs are added to the hasher -/// hasher.add({ident}); -/// -/// // Create the context -/// // The inputs (injected by this `create_inputs`) and completed hash object are passed to the context -/// let mut context = PrivateContext::new(inputs, hasher.hash()); -/// } -/// ``` -fn create_context(ty: &str, params: &[Param]) -> Result, AztecMacroError> { - let mut injected_expressions: Vec = vec![]; - - // `let mut hasher = Hasher::new();` - let let_hasher = mutable_assignment( - "hasher", // Assigned to - call( - variable_path(chained_path!("aztec", "hasher", "Hasher", "new")), // Path - vec![], // args - ), - ); - - // Completes: `let mut hasher = Hasher::new();` - injected_expressions.push(let_hasher); - - // Iterate over each of the function parameters, adding to them to the hasher - for Param { pattern, typ, span, .. } in params { - match pattern { - Pattern::Identifier(identifier) => { - // Match the type to determine the padding to do - let unresolved_type = &typ.typ; - let expression = match unresolved_type { - // `hasher.add_multiple({ident}.serialize())` - UnresolvedTypeData::Named(..) => add_struct_to_hasher(identifier), - UnresolvedTypeData::Array(_, arr_type) => { - add_array_to_hasher(identifier, arr_type) - } - // `hasher.add({ident})` - UnresolvedTypeData::FieldElement => add_field_to_hasher(identifier), - // Add the integer to the hasher, casted to a field - // `hasher.add({ident} as Field)` - UnresolvedTypeData::Integer(..) | UnresolvedTypeData::Bool => { - add_cast_to_hasher(identifier) - } - UnresolvedTypeData::String(..) => { - let (var_bytes, id) = str_to_bytes(identifier); - injected_expressions.push(var_bytes); - add_array_to_hasher( - &id, - &UnresolvedType { - typ: UnresolvedTypeData::Integer( - Signedness::Unsigned, - noirc_frontend::IntegerBitSize::ThirtyTwo, - ), - span: None, - }, - ) - } - _ => { - return Err(AztecMacroError::UnsupportedFunctionArgumentType { - typ: unresolved_type.clone(), - span: *span, - }) - } - }; - injected_expressions.push(expression); - } - _ => todo!(), // Maybe unreachable? } - } - - // Create the inputs to the context - let inputs_expression = variable("inputs"); - // `hasher.hash()` - let hash_call = method_call( - variable("hasher"), // variable - "hash", // method name - vec![], // args - ); - - let path_snippet = ty.to_case(Case::Snake); // e.g. private_context - - // let mut context = {ty}::new(inputs, hash); - let let_context = mutable_assignment( - "context", // Assigned to - call( - variable_path(chained_path!("aztec", "context", &path_snippet, ty, "new")), // Path - vec![inputs_expression, hash_call], // args - ), - ); - injected_expressions.push(let_context); - // Return all expressions that will be injected by the hasher - Ok(injected_expressions) -} - -/// Creates an mutable avm context -/// -/// ```noir -/// /// Before -/// #[aztec(public-vm)] -/// fn foo() -> Field { -/// let mut context = aztec::context::AVMContext::new(); -/// let timestamp = context.timestamp(); -/// // ... -/// } -/// -/// /// After -/// #[aztec(private)] -/// fn foo() -> Field { -/// let mut timestamp = context.timestamp(); -/// // ... -/// } -fn create_avm_context() -> Result { - let let_context = mutable_assignment( - "context", // Assigned to - call( - variable_path(chained_path!("aztec", "context", "AVMContext", "new")), // Path - vec![], // args - ), - ); - - Ok(let_context) -} - -/// Abstract Return Type -/// -/// This function intercepts the function's current return type and replaces it with pushes -/// To the kernel -/// -/// The replaced code: -/// ```noir -/// /// Before -/// #[aztec(private)] -/// fn foo() -> protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs { -/// // ... -/// let my_return_value: Field = 10; -/// context.return_values.push(my_return_value); -/// } -/// -/// /// After -/// #[aztec(private)] -/// fn foo() -> Field { -/// // ... -/// let my_return_value: Field = 10; -/// my_return_value -/// } -/// ``` -/// Similarly; Structs will be pushed to the context, after serialize() is called on them. -/// Arrays will be iterated over and each element will be pushed to the context. -/// Any primitive type that can be cast will be casted to a field and pushed to the context. -fn abstract_return_values(func: &NoirFunction) -> Option { - let current_return_type = func.return_type().typ; - let last_statement = func.def.body.statements.last()?; - - // TODO: (length, type) => We can limit the size of the array returned to be limited by kernel size - // Doesn't need done until we have settled on a kernel size - // TODO: support tuples here and in inputs -> convert into an issue - // Check if the return type is an expression, if it is, we can handle it - match last_statement { - Statement { kind: StatementKind::Expression(expression), .. } => { - match current_return_type { - // Call serialize on structs, push the whole array, calling push_array - UnresolvedTypeData::Named(..) => Some(make_struct_return_type(expression.clone())), - UnresolvedTypeData::Array(..) => Some(make_array_return_type(expression.clone())), - // Cast these types to a field before pushing - UnresolvedTypeData::Bool | UnresolvedTypeData::Integer(..) => { - Some(make_castable_return_type(expression.clone())) - } - UnresolvedTypeData::FieldElement => Some(make_return_push(expression.clone())), - _ => None, - } - } - _ => None, + generate_contract_interface(module, module_name, &stubs)?; } -} - -/// Abstract storage -/// -/// For private functions: -/// ```noir -/// #[aztec(private)] -/// fn lol() { -/// let storage = Storage::init(Context::private(context)); -/// } -/// ``` -/// -/// For public functions: -/// ```noir -/// #[aztec(public)] -/// fn lol() { -/// let storage = Storage::init(Context::public(context)); -/// } -/// ``` -/// -/// For unconstrained functions: -/// ```noir -/// unconstrained fn lol() { -/// let storage = Storage::init(Context::none()); -/// } -fn abstract_storage(typ: &str, unconstrained: bool) -> Statement { - let init_context_call = if unconstrained { - call( - variable_path(chained_path!("aztec", "context", "Context", "none")), // Path - vec![], // args - ) - } else { - call( - variable_path(chained_path!("aztec", "context", "Context", typ)), // Path - vec![mutable_reference("context")], // args - ) - }; - - assignment( - "storage", // Assigned to - call( - variable_path(chained_path!("Storage", "init")), // Path - vec![init_context_call], // args - ), - ) -} - -/// Context Return Values -/// -/// Creates an instance to the context return values -/// ```noir -/// `context.return_values` -/// ``` -fn context_return_values() -> Expression { - member_access("context", "return_values") -} - -fn make_statement(kind: StatementKind) -> Statement { - Statement { span: Span::default(), kind } -} - -/// Make return Push -/// -/// Translates to: -/// `context.return_values.push({push_value})` -fn make_return_push(push_value: Expression) -> Statement { - make_statement(StatementKind::Semi(method_call( - context_return_values(), - "push", - vec![push_value], - ))) -} - -/// Make Return push array -/// -/// Translates to: -/// `context.return_values.extend_from_array({push_value})` -fn make_return_extend_from_array(push_value: Expression) -> Statement { - make_statement(StatementKind::Semi(method_call( - context_return_values(), - "extend_from_array", - vec![push_value], - ))) -} - -/// Make struct return type -/// -/// Translates to: -/// ```noir -/// `context.return_values.extend_from_array({push_value}.serialize())` -fn make_struct_return_type(expression: Expression) -> Statement { - let serialized_call = method_call( - expression, // variable - "serialize", // method name - vec![], // args - ); - make_return_extend_from_array(serialized_call) -} - -/// Make array return type -/// -/// Translates to: -/// ```noir -/// for i in 0..{ident}.len() { -/// context.return_values.push({ident}[i] as Field) -/// } -/// ``` -fn make_array_return_type(expression: Expression) -> Statement { - let inner_cast_expression = - cast(index_array_variable(expression.clone(), "i"), UnresolvedTypeData::FieldElement); - let assignment = make_statement(StatementKind::Semi(method_call( - context_return_values(), // variable - "push", // method name - vec![inner_cast_expression], - ))); - - create_loop_over(expression, vec![assignment]) -} -/// Castable return type -/// -/// Translates to: -/// ```noir -/// context.return_values.push({ident} as Field) -/// ``` -fn make_castable_return_type(expression: Expression) -> Statement { - // Cast these types to a field before pushing - let cast_expression = cast(expression, UnresolvedTypeData::FieldElement); - make_return_push(cast_expression) -} - -/// Create Return Type -/// -/// Public functions return protocol_types::abis::public_circuit_public_inputs::PublicCircuitPublicInputs while -/// private functions return protocol_types::abis::private_circuit_public_inputs::::PrivateCircuitPublicInputs -/// -/// This call constructs an ast token referencing the above types -/// The name is set in the function above `transform`, hence the -/// whole token name is passed in -/// -/// The replaced code: -/// ```noir -/// -/// /// Before -/// fn foo() -> protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs { -/// // ... -/// } -/// -/// /// After -/// #[aztec(private)] -/// fn foo() { -/// // ... -/// } -fn create_return_type(ty: &str) -> FunctionReturnType { - let path_snippet = ty.to_case(Case::Snake); // e.g. private_circuit_public_inputs or public_circuit_public_inputs - let return_path = chained_path!("aztec", "protocol_types", "abis", &path_snippet, ty); - return_type(return_path) -} - -/// Create Context Finish -/// -/// Each aztec function calls `context.finish()` at the end of a function -/// to return values required by the kernel. -/// -/// The replaced code: -/// ```noir -/// /// Before -/// fn foo() -> protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs { -/// // ... -/// context.finish() -/// } -/// -/// /// After -/// #[aztec(private)] -/// fn foo() { -/// // ... -/// } -fn create_context_finish() -> Statement { - let method_call = method_call( - variable("context"), // variable - "finish", // method name - vec![], // args - ); - make_statement(StatementKind::Expression(method_call)) + Ok(has_transformed_module) } // -// Methods to create hasher inputs +// Transform Hir Nodes for Aztec // -fn add_struct_to_hasher(identifier: &Ident) -> Statement { - // If this is a struct, we call serialize and add the array to the hasher - let serialized_call = method_call( - variable_path(path(identifier.clone())), // variable - "serialize", // method name - vec![], // args - ); - - make_statement(StatementKind::Semi(method_call( - variable("hasher"), // variable - "add_multiple", // method name - vec![serialized_call], // args - ))) -} - -fn str_to_bytes(identifier: &Ident) -> (Statement, Ident) { - // let identifier_as_bytes = identifier.as_bytes(); - let var = variable_ident(identifier.clone()); - let contents = if let ExpressionKind::Variable(p) = &var.kind { - p.segments.first().cloned().unwrap_or_else(|| panic!("No segments")).0.contents - } else { - panic!("Unexpected identifier type") - }; - let bytes_name = format!("{}_bytes", contents); - let var_bytes = assignment(&bytes_name, method_call(var, "as_bytes", vec![])); - let id = Ident::new(bytes_name, Span::default()); - - (var_bytes, id) -} - -fn create_loop_over(var: Expression, loop_body: Vec) -> Statement { - // If this is an array of primitive types (integers / fields) we can add them each to the hasher - // casted to a field - let span = var.span; - - // `array.len()` - let end_range_expression = method_call( - var, // variable - "len", // method name - vec![], // args - ); - - // What will be looped over - // - `hasher.add({ident}[i] as Field)` - let for_loop_block = expression(ExpressionKind::Block(BlockExpression { - is_unsafe: false, - statements: loop_body, - })); - - // `for i in 0..{ident}.len()` - make_statement(StatementKind::For(ForLoopStatement { - range: ForRange::Range( - expression(ExpressionKind::Literal(Literal::Integer( - FieldElement::from(i128::from(0)), - false, - ))), - end_range_expression, - ), - identifier: ident("i"), - block: for_loop_block, - span, - })) -} - -fn add_array_to_hasher(identifier: &Ident, arr_type: &UnresolvedType) -> Statement { - // If this is an array of primitive types (integers / fields) we can add them each to the hasher - // casted to a field - - // Wrap in the semi thing - does that mean ended with semi colon? - // `hasher.add({ident}[i] as Field)` - - let arr_index = index_array(identifier.clone(), "i"); - let (add_expression, hasher_method_name) = match arr_type.typ { - UnresolvedTypeData::Named(..) => { - let hasher_method_name = "add_multiple".to_owned(); - let call = method_call( - // All serialize on each element - arr_index, // variable - "serialize", // method name - vec![], // args - ); - (call, hasher_method_name) - } - _ => { - let hasher_method_name = "add".to_owned(); - let call = cast( - arr_index, // lhs - `ident[i]` - UnresolvedTypeData::FieldElement, // cast to - `as Field` - ); - (call, hasher_method_name) - } - }; - - let block_statement = make_statement(StatementKind::Semi(method_call( - variable("hasher"), // variable - &hasher_method_name, // method name - vec![add_expression], - ))); - - create_loop_over(variable_ident(identifier.clone()), vec![block_statement]) -} - -fn add_field_to_hasher(identifier: &Ident) -> Statement { - // `hasher.add({ident})` - let ident = variable_path(path(identifier.clone())); - make_statement(StatementKind::Semi(method_call( - variable("hasher"), // variable - "add", // method name - vec![ident], // args - ))) -} - -fn add_cast_to_hasher(identifier: &Ident) -> Statement { - // `hasher.add({ident} as Field)` - // `{ident} as Field` - let cast_operation = cast( - variable_path(path(identifier.clone())), // lhs - UnresolvedTypeData::FieldElement, // rhs - ); - - // `hasher.add({ident} as Field)` - make_statement(StatementKind::Semi(method_call( - variable("hasher"), // variable - "add", // method name - vec![cast_operation], // args - ))) -} - -/// Computes the aztec signature for a resolved type. -fn signature_of_type(typ: &Type) -> String { - match typ { - Type::Integer(Signedness::Signed, bit_size) => format!("i{}", bit_size), - Type::Integer(Signedness::Unsigned, bit_size) => format!("u{}", bit_size), - Type::FieldElement => "Field".to_owned(), - Type::Bool => "bool".to_owned(), - Type::Array(len, typ) => { - if let Type::Constant(len) = **len { - format!("[{};{len}]", signature_of_type(typ)) - } else { - unimplemented!("Cannot generate signature for array with length type {:?}", typ) - } - } - Type::Struct(def, args) => { - let fields = def.borrow().get_fields(args); - let fields = vecmap(fields, |(_, typ)| signature_of_type(&typ)); - format!("({})", fields.join(",")) - } - Type::Tuple(types) => { - let fields = vecmap(types, signature_of_type); - format!("({})", fields.join(",")) - } - _ => unimplemented!("Cannot generate signature for type {:?}", typ), - } -} - -/// Computes the signature for a resolved event type. -/// It has the form 'EventName(Field,(Field),[u8;2])' -fn event_signature(event: &StructType) -> String { - let fields = vecmap(event.get_fields(&[]), |(_, typ)| signature_of_type(&typ)); - format!("{}({})", event.name.0.contents, fields.join(",")) -} - -fn inject_compute_note_hash_and_nullifier( +/// Completes the Hir with data gathered from type resolution +fn transform_hir( crate_id: &CrateId, context: &mut HirContext, - unresolved_traits_impls: &[UnresolvedTraitImpl], - collected_functions: &mut [UnresolvedFunctions], -) -> Result<(), (MacroError, FileId)> { - // We first fetch modules in this crate which correspond to contracts, along with their file id. - let contract_module_file_ids: Vec<(LocalModuleId, FileId)> = context - .def_map(crate_id) - .expect("ICE: Missing crate in def_map") - .modules() - .iter() - .filter(|(_, module)| module.is_contract) - .map(|(idx, module)| (LocalModuleId(idx), module.location.file)) - .collect(); - - // If the current crate does not contain a contract module we simply skip it. - if contract_module_file_ids.is_empty() { - return Ok(()); - } else if contract_module_file_ids.len() != 1 { - panic!("Found multiple contracts in the same crate"); - } - - let (module_id, file_id) = contract_module_file_ids[0]; - - // If compute_note_hash_and_nullifier is already defined by the user, we skip auto-generation in order to provide an - // escape hatch for this mechanism. - // TODO(#4647): improve this diagnosis and error messaging. - if collected_functions.iter().any(|coll_funcs_data| { - check_for_compute_note_hash_and_nullifier_definition(&coll_funcs_data.functions, module_id) - }) { - return Ok(()); - } - - // In order to implement compute_note_hash_and_nullifier, we need to know all of the different note types the - // contract might use. These are the types that implement the NoteInterface trait, which provides the - // get_note_type_id function. - let note_types = fetch_struct_trait_impls(context, unresolved_traits_impls, "NoteInterface"); - - // We can now generate a version of compute_note_hash_and_nullifier tailored for the contract in this crate. - let func = generate_compute_note_hash_and_nullifier(¬e_types); - - // And inject the newly created function into the contract. - - // TODO(#4373): We don't have a reasonable location for the source code of this autogenerated function, so we simply - // pass an empty span. This function should not produce errors anyway so this should not matter. - let location = Location::new(Span::empty(0), file_id); - - // These are the same things the ModCollector does when collecting functions: we push the function to the - // NodeInterner, declare it in the module (which checks for duplicate definitions), and finally add it to the list - // on collected but unresolved functions. - - let func_id = context.def_interner.push_empty_fn(); - context.def_interner.push_function( - func_id, - &func.def, - ModuleId { krate: *crate_id, local_id: module_id }, - location, - ); - - context.def_map_mut(crate_id).unwrap() - .modules_mut()[module_id.0] - .declare_function( - func.name_ident().clone(), func_id - ).expect( - "Failed to declare the autogenerated compute_note_hash_and_nullifier function, likely due to a duplicate definition. See https://github.com/AztecProtocol/aztec-packages/issues/4647." - ); - - collected_functions - .iter_mut() - .find(|fns| fns.file_id == file_id) - .expect("ICE: no functions found in contract file") - .push_fn(module_id, func_id, func.clone()); - - Ok(()) -} - -// Fetches the name of all structs that implement trait_name, both in the current crate and all of its dependencies. -fn fetch_struct_trait_impls( - context: &mut HirContext, - unresolved_traits_impls: &[UnresolvedTraitImpl], - trait_name: &str, -) -> Vec { - let mut struct_typenames: Vec = Vec::new(); - - // These structs can be declared in either external crates or the current one. External crates that contain - // dependencies have already been processed and resolved, but are available here via the NodeInterner. Note that - // crates on which the current crate does not depend on may not have been processed, and will be ignored. - for trait_impl_id in 0..context.def_interner.next_trait_impl_id().0 { - let trait_impl = &context.def_interner.get_trait_implementation(TraitImplId(trait_impl_id)); - - if trait_impl.borrow().ident.0.contents == *trait_name { - if let Type::Struct(s, _) = &trait_impl.borrow().typ { - struct_typenames.push(s.borrow().name.0.contents.clone()); - } else { - panic!("Found impl for {} on non-Struct", trait_name); - } - } - } - - // This crate's traits and impls have not yet been resolved, so we look for impls in unresolved_trait_impls. - struct_typenames.extend( - unresolved_traits_impls - .iter() - .filter(|trait_impl| { - trait_impl - .trait_path - .segments - .last() - .expect("ICE: empty trait_impl path") - .0 - .contents - == *trait_name - }) - .filter_map(|trait_impl| match &trait_impl.object_type.typ { - UnresolvedTypeData::Named(path, _, _) => { - Some(path.segments.last().unwrap().0.contents.clone()) - } - _ => None, - }), - ); - - struct_typenames -} - -fn generate_compute_note_hash_and_nullifier(note_types: &Vec) -> NoirFunction { - let function_source = generate_compute_note_hash_and_nullifier_source(note_types); - - let (function_ast, errors) = parse_program(&function_source); - if !errors.is_empty() { - dbg!(errors.clone()); - } - assert_eq!(errors.len(), 0, "Failed to parse Noir macro code. This is either a bug in the compiler or the Noir macro code"); - - let mut function_ast = function_ast.into_sorted(); - function_ast.functions.remove(0) -} - -fn generate_compute_note_hash_and_nullifier_source(note_types: &Vec) -> String { - // TODO(#4649): The serialized_note parameter is a fixed-size array, but we don't know what length it should have. - // For now we hardcode it to 20, which is the same as MAX_NOTE_FIELDS_LENGTH. - - if note_types.is_empty() { - // TODO(#4520): Even if the contract does not include any notes, other parts of the stack expect for this - // function to exist, so we include a dummy version. We likely should error out here instead. - " - unconstrained fn compute_note_hash_and_nullifier( - contract_address: AztecAddress, - nonce: Field, - storage_slot: Field, - note_type_id: Field, - serialized_note: [Field; 20] - ) -> pub [Field; 4] { - [0, 0, 0, 0] - }" - .to_string() +) -> Result<(), (AztecMacroError, FileId)> { + if has_aztec_dependency(crate_id, context) { + transform_events(crate_id, context)?; + inject_compute_note_hash_and_nullifier(crate_id, context)?; + assign_storage_slots(crate_id, context)?; + inject_note_exports(crate_id, context)?; + update_fn_signatures_in_contract_interface(crate_id, context) } else { - // For contracts that include notes we do a simple if-else chain comparing note_type_id with the different - // get_note_type_id of each of the note types. - - let if_statements: Vec = note_types.iter().map(|note_type| format!( - "if (note_type_id == {0}::get_note_type_id()) {{ - note_utils::compute_note_hash_and_nullifier({0}::deserialize_content, note_header, serialized_note) - }}" - , note_type)).collect(); - - // TODO(#4520): error out on the else instead of returning a zero array - let full_if_statement = if_statements.join(" else ") - + " - else { - [0, 0, 0, 0] - }"; - - format!( - " - unconstrained fn compute_note_hash_and_nullifier( - contract_address: AztecAddress, - nonce: Field, - storage_slot: Field, - note_type_id: Field, - serialized_note: [Field; 20] - ) -> pub [Field; 4] {{ - let note_header = NoteHeader::new(contract_address, nonce, storage_slot); - - {} - }}", - full_if_statement - ) + Ok(()) } } diff --git a/aztec_macros/src/transforms/compute_note_hash_and_nullifier.rs b/aztec_macros/src/transforms/compute_note_hash_and_nullifier.rs new file mode 100644 index 00000000000..f624cde9969 --- /dev/null +++ b/aztec_macros/src/transforms/compute_note_hash_and_nullifier.rs @@ -0,0 +1,222 @@ +use noirc_errors::{Location, Span}; +use noirc_frontend::ast::{FunctionReturnType, NoirFunction, UnresolvedTypeData}; +use noirc_frontend::{ + graph::CrateId, + macros_api::{FileId, HirContext}, + parse_program, Type, +}; + +use crate::utils::{ + errors::AztecMacroError, + hir_utils::{ + collect_crate_functions, collect_traits, fetch_notes, get_contract_module_data, + get_global_numberic_const, get_serialized_length, inject_fn, + }, +}; + +// Check if "compute_note_hash_and_nullifier(AztecAddress,Field,Field,Field,[Field; N]) -> [Field; 4]" is defined +fn check_for_compute_note_hash_and_nullifier_definition( + crate_id: &CrateId, + context: &HirContext, +) -> bool { + collect_crate_functions(crate_id, context).iter().any(|funct_id| { + let func_data = context.def_interner.function_meta(funct_id); + let func_name = context.def_interner.function_name(funct_id); + func_name == "compute_note_hash_and_nullifier" + && func_data.parameters.len() == 5 + && func_data.parameters.0.first().is_some_and(| (_, typ, _) | match typ { + Type::Struct(struct_typ, _) => struct_typ.borrow().name.0.contents == "AztecAddress", + _ => false + }) + && func_data.parameters.0.get(1).is_some_and(|(_, typ, _)| typ.is_field()) + && func_data.parameters.0.get(2).is_some_and(|(_, typ, _)| typ.is_field()) + && func_data.parameters.0.get(3).is_some_and(|(_, typ, _)| typ.is_field()) + // checks if the 5th parameter is an array and contains only fields + && func_data.parameters.0.get(4).is_some_and(|(_, typ, _)| match typ { + Type::Array(_, inner_type) => inner_type.to_owned().is_field(), + _ => false + }) + // We check the return type the same way as we did the 5th parameter + && match &func_data.return_type { + FunctionReturnType::Default(_) => false, + FunctionReturnType::Ty(unresolved_type) => { + match &unresolved_type.typ { + UnresolvedTypeData::Array(_, inner_type) => matches!(inner_type.typ, UnresolvedTypeData::FieldElement), + _ => false, + } + } + } + }) +} + +pub fn inject_compute_note_hash_and_nullifier( + crate_id: &CrateId, + context: &mut HirContext, +) -> Result<(), (AztecMacroError, FileId)> { + if let Some((_, module_id, file_id)) = get_contract_module_data(context, crate_id) { + // If compute_note_hash_and_nullifier is already defined by the user, we skip auto-generation in order to provide an + // escape hatch for this mechanism. + // TODO(#4647): improve this diagnosis and error messaging. + if context.crate_graph.root_crate_id() != crate_id + || check_for_compute_note_hash_and_nullifier_definition(crate_id, context) + { + return Ok(()); + } + + let traits: Vec<_> = collect_traits(context); + + // Get MAX_NOTE_FIELDS_LENGTH global to check if the notes in our contract are too long. + let max_note_length_const = get_global_numberic_const(context, "MAX_NOTE_FIELDS_LENGTH") + .map_err(|err| { + ( + AztecMacroError::CouldNotImplementComputeNoteHashAndNullifier { + secondary_message: Some(err.primary_message), + }, + file_id, + ) + })?; + + // In order to implement compute_note_hash_and_nullifier, we need to know all of the different note types the + // contract might use and their serialized lengths. These are the types that are marked as #[aztec(note)]. + let mut notes_and_lengths = vec![]; + + for (path, typ) in fetch_notes(context) { + let serialized_len: u128 = get_serialized_length( + &traits, + "NoteInterface", + &Type::Struct(typ.clone(), vec![]), + &context.def_interner, + ) + .map_err(|_err| { + ( + AztecMacroError::CouldNotImplementComputeNoteHashAndNullifier { + secondary_message: Some(format!( + "Failed to get serialized length for note type {}", + path + )), + }, + file_id, + ) + })? + .into(); + + if serialized_len > max_note_length_const { + return Err(( + AztecMacroError::CouldNotImplementComputeNoteHashAndNullifier { + secondary_message: Some(format!( + "Note type {} as {} fields, which is more than the maximum allowed length of {}.", + path, + serialized_len, + max_note_length_const + )), + }, + file_id, + )); + } + + notes_and_lengths.push((path.to_string(), serialized_len)); + } + + let max_note_length: u128 = + *notes_and_lengths.iter().map(|(_, serialized_len)| serialized_len).max().unwrap_or(&0); + + let note_types = + notes_and_lengths.iter().map(|(note_type, _)| note_type.clone()).collect::>(); + + // We can now generate a version of compute_note_hash_and_nullifier tailored for the contract in this crate. + let func = generate_compute_note_hash_and_nullifier(¬e_types, max_note_length); + + // And inject the newly created function into the contract. + + // TODO(#4373): We don't have a reasonable location for the source code of this autogenerated function, so we simply + // pass an empty span. This function should not produce errors anyway so this should not matter. + let location = Location::new(Span::empty(0), file_id); + + inject_fn(crate_id, context, func, location, module_id, file_id).map_err(|err| { + ( + AztecMacroError::CouldNotImplementComputeNoteHashAndNullifier { + secondary_message: err.secondary_message, + }, + file_id, + ) + })?; + } + Ok(()) +} + +fn generate_compute_note_hash_and_nullifier( + note_types: &[String], + max_note_length: u128, +) -> NoirFunction { + let function_source = + generate_compute_note_hash_and_nullifier_source(note_types, max_note_length); + + let (function_ast, errors) = parse_program(&function_source); + if !errors.is_empty() { + dbg!(errors.clone()); + } + assert_eq!(errors.len(), 0, "Failed to parse Noir macro code. This is either a bug in the compiler or the Noir macro code"); + + let mut function_ast = function_ast.into_sorted(); + function_ast.functions.remove(0) +} + +fn generate_compute_note_hash_and_nullifier_source( + note_types: &[String], + max_note_length: u128, +) -> String { + // TODO(#4649): The serialized_note parameter is a fixed-size array, but we don't know what length it should have. + // For now we hardcode it to 20, which is the same as MAX_NOTE_FIELDS_LENGTH. + + if note_types.is_empty() { + // Even if the contract does not include any notes, other parts of the stack expect for this function to exist, + // so we include a dummy version. + format!( + " + unconstrained fn compute_note_hash_and_nullifier( + contract_address: dep::aztec::protocol_types::address::AztecAddress, + nonce: Field, + storage_slot: Field, + note_type_id: Field, + serialized_note: [Field; {}] + ) -> pub [Field; 4] {{ + assert(false, \"This contract does not use private notes\"); + [0, 0, 0, 0] + }}", + max_note_length + ) + } else { + // For contracts that include notes we do a simple if-else chain comparing note_type_id with the different + // get_note_type_id of each of the note types. + + let if_statements: Vec = note_types.iter().map(|note_type| format!( + "if (note_type_id == {0}::get_note_type_id()) {{ + dep::aztec::note::utils::compute_note_hash_and_nullifier({0}::deserialize_content, note_header, serialized_note) + }}" + , note_type)).collect(); + + let full_if_statement = if_statements.join(" else ") + + " + else { + assert(false, \"Unknown note type ID\"); + [0, 0, 0, 0] + }"; + + format!( + " + unconstrained fn compute_note_hash_and_nullifier( + contract_address: dep::aztec::protocol_types::address::AztecAddress, + nonce: Field, + storage_slot: Field, + note_type_id: Field, + serialized_note: [Field; {}] + ) -> pub [Field; 4] {{ + let note_header = dep::aztec::prelude::NoteHeader::new(contract_address, nonce, storage_slot); + + {} + }}", + max_note_length, + full_if_statement + ) + } +} diff --git a/aztec_macros/src/transforms/contract_interface.rs b/aztec_macros/src/transforms/contract_interface.rs new file mode 100644 index 00000000000..90f9ce6164a --- /dev/null +++ b/aztec_macros/src/transforms/contract_interface.rs @@ -0,0 +1,350 @@ +use noirc_errors::Location; +use noirc_frontend::ast::{Ident, NoirFunction, UnresolvedTypeData}; +use noirc_frontend::{ + graph::CrateId, + macros_api::{FileId, HirContext, HirExpression, HirLiteral, HirStatement}, + parse_program, + parser::SortedModule, + Type, +}; + +use crate::utils::{ + constants::SELECTOR_PLACEHOLDER, + errors::AztecMacroError, + hir_utils::{collect_crate_structs, get_contract_module_data, signature_of_type}, +}; + +// Generates the stubs for contract functions as low level calls using CallInterface, turning +// #[aztec(public)] // also private +// fn a_function(first_arg: Field, second_arg: Struct, third_arg: [Field; 4]) -> Field { +// ... +// } +// +// into +// +// pub fn a_function(self, first_arg: Field, second_arg: Struct, third_arg: [Field; 4]) -> PublicCallInterface { +// let mut args_acc: [Field] = &[]; +// args_acc = args_acc.append(first_arg.serialize().as_slice()); +// args_acc = args_acc.append(second_arg.serialize().as_slice()); +// let hash_third_arg = third_arg.map(|x: Field| x.serialize()); +// for i in 0..third_arg.len() { +// args_acc = args_acc.append(third_arg[i].serialize().as_slice()); +// } +// let args_hash = dep::aztec::hash::hash_args(args_acc); +// assert(args_hash == dep::aztec::oracle::arguments::pack_arguments(args_acc)); +// PublicCallInterface { +// target_contract: self.target_contract, +// selector: FunctionSelector::from_signature("SELECTOR_PLACEHOLDER"), +// args_hash +// } +// } +// +// The selector placeholder has to be replaced with the actual function signature after type checking in the next macro pass +pub fn stub_function(aztec_visibility: &str, func: &NoirFunction, is_static_call: bool) -> String { + let fn_name = func.name().to_string(); + let fn_parameters = func + .parameters() + .iter() + .map(|param| { + format!( + "{}: {}", + param.pattern.name_ident().0.contents, + param.typ.to_string().replace("plain::", "") + ) + }) + .collect::>() + .join(", "); + let fn_return_type: noirc_frontend::ast::UnresolvedType = func.return_type(); + + let fn_selector = format!("dep::aztec::protocol_types::abis::function_selector::FunctionSelector::from_signature(\"{}\")", SELECTOR_PLACEHOLDER); + + let parameters = func.parameters(); + let is_void = if matches!(fn_return_type.typ, UnresolvedTypeData::Unit) { "Void" } else { "" }; + let is_static = if is_static_call { "Static" } else { "" }; + let return_type_hint = if is_void == "Void" { + "".to_string() + } else { + format!("<{}>", fn_return_type.typ.to_string().replace("plain::", "")) + }; + let call_args = parameters + .iter() + .map(|arg| { + let param_name = arg.pattern.name_ident().0.contents.clone(); + match &arg.typ.typ { + UnresolvedTypeData::Array(_, typ) => { + format!( + "let hash_{0} = {0}.map(|x: {1}| x.serialize()); + for i in 0..{0}.len() {{ + args_acc = args_acc.append(hash_{0}[i].as_slice()); + }}\n", + param_name, + typ.typ.to_string().replace("plain::", "") + ) + } + _ => { + format!("args_acc = args_acc.append({}.serialize().as_slice());\n", param_name) + } + } + }) + .collect::>() + .join(""); + if aztec_visibility != "Public" { + let args_hash = if !parameters.is_empty() { + format!( + "let mut args_acc: [Field] = &[]; + {} + let args_hash = dep::aztec::hash::hash_args(args_acc); + assert(args_hash == dep::aztec::oracle::arguments::pack_arguments(args_acc));", + call_args + ) + } else { + "let args_hash = 0;".to_string() + }; + + let fn_body = format!( + "{} + dep::aztec::context::{}{}{}CallInterface {{ + target_contract: self.target_contract, + selector: {}, + args_hash, + }}", + args_hash, aztec_visibility, is_static, is_void, fn_selector, + ); + format!( + "pub fn {}(self, {}) -> dep::aztec::context::{}{}{}CallInterface{} {{ + {} + }}", + fn_name, fn_parameters, aztec_visibility, is_static, is_void, return_type_hint, fn_body + ) + } else { + let args = format!( + "let mut args_acc: [Field] = &[]; + {} + ", + call_args + ); + let fn_body = format!( + "{} + dep::aztec::context::Public{}{}CallInterface {{ + target_contract: self.target_contract, + selector: {}, + args: args_acc, + gas_opts: dep::aztec::context::gas::GasOpts::default(), + }}", + args, is_static, is_void, fn_selector, + ); + format!( + "pub fn {}(self, {}) -> dep::aztec::context::Public{}{}CallInterface{} {{ + {} + }}", + fn_name, fn_parameters, is_static, is_void, return_type_hint, fn_body + ) + } +} + +// Generates the contract interface as a struct with an `at` function that holds the stubbed functions and provides +// them with a target contract address. The struct has the same name as the contract (which is technically a module) +// so imports look nice. The `at` function is also exposed as a contract library method for external use. +pub fn generate_contract_interface( + module: &mut SortedModule, + module_name: &str, + stubs: &[(String, Location)], +) -> Result<(), AztecMacroError> { + let contract_interface = format!( + " + struct {0} {{ + target_contract: dep::aztec::protocol_types::address::AztecAddress + }} + + impl {0} {{ + {1} + + pub fn at( + target_contract: dep::aztec::protocol_types::address::AztecAddress + ) -> Self {{ + Self {{ target_contract }} + }} + }} + + #[contract_library_method] + pub fn at( + target_contract: dep::aztec::protocol_types::address::AztecAddress + ) -> {0} {{ + {0} {{ target_contract }} + }} + ", + module_name, + stubs.iter().map(|(src, _)| src.to_owned()).collect::>().join("\n"), + ); + + let (contract_interface_ast, errors) = parse_program(&contract_interface); + if !errors.is_empty() { + dbg!(errors); + return Err(AztecMacroError::CouldNotGenerateContractInterface { secondary_message: Some("Failed to parse Noir macro code during contract interface generation. This is either a bug in the compiler or the Noir macro code".to_string()), }); + } + + let mut contract_interface_ast = contract_interface_ast.into_sorted(); + let mut impl_with_locations = contract_interface_ast.impls.pop().unwrap(); + + impl_with_locations.methods = impl_with_locations + .methods + .iter() + .enumerate() + .map(|(i, (method, orig_span))| { + if method.name() == "at" { + (method.clone(), *orig_span) + } else { + let (_, new_location) = stubs[i]; + let mut modified_method = method.clone(); + modified_method.def.name = + Ident::new(modified_method.name().to_string(), new_location.span); + (modified_method, *orig_span) + } + }) + .collect(); + + module.types.push(contract_interface_ast.types.pop().unwrap()); + module.impls.push(impl_with_locations); + module.functions.push(contract_interface_ast.functions.pop().unwrap()); + + Ok(()) +} + +fn compute_fn_signature(fn_name: &str, parameters: &[Type]) -> String { + format!( + "{}({})", + fn_name, + parameters.iter().map(signature_of_type).collect::>().join(",") + ) +} + +// Updates the function signatures in the contract interface with the actual ones, replacing the placeholder. +// This is done by locating the contract interface struct, its functions (stubs) and assuming the last statement of each +// is the constructor for a CallInterface. This constructor has a selector field that holds a +// FunctionSelector::from_signature function that receives the signature as a string literal. +pub fn update_fn_signatures_in_contract_interface( + crate_id: &CrateId, + context: &mut HirContext, +) -> Result<(), (AztecMacroError, FileId)> { + if let Some((name, _, file_id)) = get_contract_module_data(context, crate_id) { + let maybe_interface_struct = + collect_crate_structs(crate_id, context).iter().find_map(|struct_id| { + let r#struct = context.def_interner.get_struct(*struct_id); + if r#struct.borrow().name.0.contents == name { + Some(r#struct) + } else { + None + } + }); + + if let Some(interface_struct) = maybe_interface_struct { + let methods = context.def_interner.get_struct_methods(interface_struct.borrow().id); + + for func_id in methods.iter().flat_map(|methods| methods.direct.iter()) { + let name = context.def_interner.function_name(func_id); + let fn_parameters = &context.def_interner.function_meta(func_id).parameters.clone(); + + if name == "at" { + continue; + } + + let fn_signature = compute_fn_signature( + name, + &fn_parameters + .iter() + .skip(1) + .map(|(_, typ, _)| typ.clone()) + .collect::>(), + ); + let hir_func = context.def_interner.function(func_id).block(&context.def_interner); + let call_interface_constructor_statement = context.def_interner.statement( + hir_func + .statements() + .last() + .ok_or((AztecMacroError::AztecDepNotFound, file_id))?, + ); + let call_interface_constructor_expression = + match call_interface_constructor_statement { + HirStatement::Expression(expression_id) => { + match context.def_interner.expression(&expression_id) { + HirExpression::Constructor(hir_constructor_expression) => { + Ok(hir_constructor_expression) + } + _ => Err(( + AztecMacroError::CouldNotGenerateContractInterface { + secondary_message: Some( + "CallInterface constructor statement must be a constructor expression" + .to_string(), + ), + }, + file_id, + )), + } + } + _ => Err(( + AztecMacroError::CouldNotGenerateContractInterface { + secondary_message: Some( + "CallInterface constructor statement must be an expression" + .to_string(), + ), + }, + file_id, + )), + }?; + let (_, function_selector_expression_id) = + call_interface_constructor_expression.fields[1]; + let function_selector_expression = + context.def_interner.expression(&function_selector_expression_id); + + let current_fn_signature_expression_id = match function_selector_expression { + HirExpression::Call(call_expr) => Ok(call_expr.arguments[0]), + _ => Err(( + AztecMacroError::CouldNotGenerateContractInterface { + secondary_message: Some( + "Function selector argument expression must be call expression" + .to_string(), + ), + }, + file_id, + )), + }?; + + let current_fn_signature_expression = + context.def_interner.expression(¤t_fn_signature_expression_id); + + match current_fn_signature_expression { + HirExpression::Literal(HirLiteral::Str(signature)) => { + if signature != SELECTOR_PLACEHOLDER { + Err(( + AztecMacroError::CouldNotGenerateContractInterface { + secondary_message: Some(format!( + "Function signature argument must be a placeholder: {}", + SELECTOR_PLACEHOLDER + )), + }, + file_id, + )) + } else { + Ok(()) + } + } + _ => Err(( + AztecMacroError::CouldNotAssignStorageSlots { + secondary_message: Some( + "Function signature argument must be a literal string".to_string(), + ), + }, + file_id, + )), + }?; + + context + .def_interner + .update_expression(current_fn_signature_expression_id, |expr| { + *expr = HirExpression::Literal(HirLiteral::Str(fn_signature)) + }); + } + } + } + Ok(()) +} diff --git a/aztec_macros/src/transforms/events.rs b/aztec_macros/src/transforms/events.rs new file mode 100644 index 00000000000..233e6090dfd --- /dev/null +++ b/aztec_macros/src/transforms/events.rs @@ -0,0 +1,187 @@ +use iter_extended::vecmap; +use noirc_errors::Span; +use noirc_frontend::ast::{ + ExpressionKind, FunctionDefinition, FunctionReturnType, ItemVisibility, Literal, NoirFunction, + Visibility, +}; +use noirc_frontend::{ + graph::CrateId, + macros_api::{ + BlockExpression, FileId, HirContext, HirExpression, HirLiteral, HirStatement, NodeInterner, + NoirStruct, PathKind, StatementKind, StructId, StructType, Type, TypeImpl, + UnresolvedTypeData, + }, + token::SecondaryAttribute, +}; + +use crate::{ + chained_dep, + utils::{ + ast_utils::{ + call, expression, ident, ident_path, is_custom_attribute, make_statement, make_type, + path, variable_path, + }, + constants::SIGNATURE_PLACEHOLDER, + errors::AztecMacroError, + hir_utils::{collect_crate_structs, signature_of_type}, + }, +}; + +/// Generates the impl for an event selector +/// +/// Inserts the following code: +/// ```noir +/// impl SomeStruct { +/// fn selector() -> FunctionSelector { +/// aztec::protocol_types::abis::function_selector::FunctionSelector::from_signature("SIGNATURE_PLACEHOLDER") +/// } +/// } +/// ``` +/// +/// This allows developers to emit events without having to write the signature of the event every time they emit it. +/// The signature cannot be known at this point since types are not resolved yet, so we use a signature placeholder. +/// It'll get resolved after by transforming the HIR. +pub fn generate_selector_impl(structure: &mut NoirStruct) -> TypeImpl { + structure.attributes.push(SecondaryAttribute::Abi("events".to_string())); + let struct_type = + make_type(UnresolvedTypeData::Named(path(structure.name.clone()), vec![], true)); + + let selector_path = + chained_dep!("aztec", "protocol_types", "abis", "function_selector", "FunctionSelector"); + let mut from_signature_path = selector_path.clone(); + from_signature_path.segments.push(ident("from_signature")); + + let selector_fun_body = BlockExpression { + is_unsafe: false, + statements: vec![make_statement(StatementKind::Expression(call( + variable_path(from_signature_path), + vec![expression(ExpressionKind::Literal(Literal::Str( + SIGNATURE_PLACEHOLDER.to_string(), + )))], + )))], + }; + + // Define `FunctionSelector` return type + let return_type = + FunctionReturnType::Ty(make_type(UnresolvedTypeData::Named(selector_path, vec![], true))); + + let mut selector_fn_def = FunctionDefinition::normal( + &ident("selector"), + &vec![], + &[], + &selector_fun_body, + &[], + &return_type, + ); + + selector_fn_def.visibility = ItemVisibility::Public; + + // Seems to be necessary on contract modules + selector_fn_def.return_visibility = Visibility::Public; + + TypeImpl { + object_type: struct_type, + type_span: structure.span, + generics: vec![], + methods: vec![(NoirFunction::normal(selector_fn_def), Span::default())], + } +} + +/// Computes the signature for a resolved event type. +/// It has the form 'EventName(Field,(Field),[u8;2])' +fn event_signature(event: &StructType) -> String { + let fields = vecmap(event.get_fields(&[]), |(_, typ)| signature_of_type(&typ)); + format!("{}({})", event.name.0.contents, fields.join(",")) +} + +/// Substitutes the signature literal that was introduced in the selector method previously with the actual signature. +fn transform_event( + struct_id: StructId, + interner: &mut NodeInterner, +) -> Result<(), (AztecMacroError, FileId)> { + let struct_type = interner.get_struct(struct_id); + let selector_id = interner + .lookup_method(&Type::Struct(struct_type.clone(), vec![]), struct_id, "selector", false) + .ok_or_else(|| { + let error = AztecMacroError::EventError { + span: struct_type.borrow().location.span, + message: "Selector method not found".to_owned(), + }; + (error, struct_type.borrow().location.file) + })?; + let selector_function = interner.function(&selector_id); + + let compute_selector_statement = interner.statement( + selector_function.block(interner).statements().first().ok_or_else(|| { + let error = AztecMacroError::EventError { + span: struct_type.borrow().location.span, + message: "Compute selector statement not found".to_owned(), + }; + (error, struct_type.borrow().location.file) + })?, + ); + + let compute_selector_expression = match compute_selector_statement { + HirStatement::Expression(expression_id) => match interner.expression(&expression_id) { + HirExpression::Call(hir_call_expression) => Some(hir_call_expression), + _ => None, + }, + _ => None, + } + .ok_or_else(|| { + let error = AztecMacroError::EventError { + span: struct_type.borrow().location.span, + message: "Compute selector statement is not a call expression".to_owned(), + }; + (error, struct_type.borrow().location.file) + })?; + + let first_arg_id = compute_selector_expression.arguments.first().ok_or_else(|| { + let error = AztecMacroError::EventError { + span: struct_type.borrow().location.span, + message: "Compute selector statement is not a call expression".to_owned(), + }; + (error, struct_type.borrow().location.file) + })?; + + match interner.expression(first_arg_id) { + HirExpression::Literal(HirLiteral::Str(signature)) + if signature == SIGNATURE_PLACEHOLDER => + { + let selector_literal_id = *first_arg_id; + + let structure = interner.get_struct(struct_id); + let signature = event_signature(&structure.borrow()); + interner.update_expression(selector_literal_id, |expr| { + *expr = HirExpression::Literal(HirLiteral::Str(signature.clone())); + }); + + // Also update the type! It might have a different length now than the placeholder. + interner.push_expr_type( + selector_literal_id, + Type::String(Box::new(Type::Constant(signature.len() as u32))), + ); + Ok(()) + } + _ => Err(( + AztecMacroError::EventError { + span: struct_type.borrow().location.span, + message: "Signature placeholder literal does not match".to_owned(), + }, + struct_type.borrow().location.file, + )), + } +} + +pub fn transform_events( + crate_id: &CrateId, + context: &mut HirContext, +) -> Result<(), (AztecMacroError, FileId)> { + for struct_id in collect_crate_structs(crate_id, context) { + let attributes = context.def_interner.struct_attributes(&struct_id); + if attributes.iter().any(|attr| is_custom_attribute(attr, "aztec(event)")) { + transform_event(struct_id, &mut context.def_interner)?; + } + } + Ok(()) +} diff --git a/aztec_macros/src/transforms/functions.rs b/aztec_macros/src/transforms/functions.rs new file mode 100644 index 00000000000..4ddf8cf580b --- /dev/null +++ b/aztec_macros/src/transforms/functions.rs @@ -0,0 +1,837 @@ +use convert_case::{Case, Casing}; +use noirc_errors::Span; +use noirc_frontend::ast::{self, FunctionKind}; +use noirc_frontend::ast::{ + BlockExpression, ConstrainKind, ConstrainStatement, Expression, ExpressionKind, + ForLoopStatement, ForRange, FunctionReturnType, Ident, Literal, NoirFunction, NoirStruct, + Param, PathKind, Pattern, Signedness, Statement, StatementKind, UnresolvedType, + UnresolvedTypeData, Visibility, +}; + +use noirc_frontend::{macros_api::FieldElement, parse_program}; + +use crate::utils::ast_utils::member_access; +use crate::{ + chained_dep, chained_path, + utils::{ + ast_utils::{ + assignment, assignment_with_type, call, cast, expression, ident, ident_path, + index_array, make_eq, make_statement, make_type, method_call, mutable_assignment, + mutable_reference, path, return_type, variable, variable_ident, variable_path, + }, + errors::AztecMacroError, + }, +}; + +// If it does, it will insert the following things: +/// - A new Input that is provided for a kernel app circuit, named: {Public/Private}ContextInputs +/// - Hashes all of the function input variables +/// - This instantiates a helper function +pub fn transform_function( + ty: &str, + func: &mut NoirFunction, + storage_struct_name: Option, + is_initializer: bool, + insert_init_check: bool, + is_internal: bool, + is_static: bool, +) -> Result<(), AztecMacroError> { + assert!(matches!(ty, "Private" | "Public")); + let context_name = format!("{}Context", ty); + let inputs_name = format!("{}ContextInputs", ty); + let return_type_name = format!("{}CircuitPublicInputs", ty); + let is_private = ty == "Private"; + + // Force a static context if the function is static + if is_static { + let is_static_check = create_static_check(func.name(), is_private); + func.def.body.statements.insert(0, is_static_check); + } + + // Add check that msg sender equals this address and flag function as internal + if is_internal { + let is_internal_check = create_internal_check(func.name()); + func.def.body.statements.insert(0, is_internal_check); + } + + // Add initialization check + if insert_init_check { + let init_check = create_init_check(ty); + func.def.body.statements.insert(0, init_check); + } + + // Add assertion for initialization arguments and sender + if is_initializer { + func.def.body.statements.insert(0, create_assert_initializer(ty)); + } + + // Add access to the storage struct + if let Some(storage_struct_name) = storage_struct_name { + let storage_def = abstract_storage(storage_struct_name, false); + func.def.body.statements.insert(0, storage_def); + } + + // Insert the context creation as the first action + let create_context = if is_private { + create_context_private(&context_name, &func.def.parameters)? + } else { + create_context_public()? + }; + func.def.body.statements.splice(0..0, (create_context).iter().cloned()); + + // Add the inputs to the params + let input = create_inputs(&inputs_name); + func.def.parameters.insert(0, input); + + // Abstract return types such that they get added to the kernel's return_values + if is_private { + if let Some(return_values_statements) = abstract_return_values(func)? { + // In case we are pushing return values to the context, we remove the statement that originated it + // This avoids running duplicate code, since blocks like if/else can be value returning statements + func.def.body.statements.pop(); + // Add the new return statement + func.def.body.statements.extend(return_values_statements); + } + } + + // Before returning mark the contract as initialized + if is_initializer { + let mark_initialized = create_mark_as_initialized(ty); + func.def.body.statements.push(mark_initialized); + } + + // Push the finish method call to the end of the function + if is_private { + let finish_def = create_context_finish(); + func.def.body.statements.push(finish_def); + } + + // The AVM doesn't need a return type yet. + if is_private { + let return_type = create_return_type(&return_type_name); + func.def.return_type = return_type; + func.def.return_visibility = Visibility::Public; + } else { + func.def.return_visibility = Visibility::Public; + } + + // Public functions should have unconstrained auto-inferred + func.def.is_unconstrained = !is_private; + + // Private functions need to be recursive + if is_private { + func.kind = FunctionKind::Recursive; + } + + Ok(()) +} + +// Generates a global struct containing the original (before transform_function gets executed) function abi that gets exported +// in the contract artifact after compilation. The abi will be later used to decode the function return values in the simulator. +pub fn export_fn_abi( + types: &mut Vec, + func: &NoirFunction, +) -> Result<(), AztecMacroError> { + let mut parameters_struct_source: Option<&str> = None; + + let struct_source = format!( + " + struct {}_parameters {{ + {} + }} + ", + func.name(), + func.parameters() + .iter() + .map(|param| { + let param_name = match param.pattern.clone() { + Pattern::Identifier(ident) => Ok(ident.0.contents), + _ => Err(AztecMacroError::CouldNotExportFunctionAbi { + span: Some(param.span), + secondary_message: Some( + "Only identifier patterns are supported".to_owned(), + ), + }), + }; + + format!( + "{}: {}", + param_name.unwrap(), + param.typ.typ.to_string().replace("plain::", "") + ) + }) + .collect::>() + .join(",\n"), + ); + + if !func.parameters().is_empty() { + parameters_struct_source = Some(&struct_source); + } + + let mut program = String::new(); + + let parameters = if let Some(parameters_struct_source) = parameters_struct_source { + program.push_str(parameters_struct_source); + format!("parameters: {}_parameters,\n", func.name()) + } else { + "".to_string() + }; + + let return_type_str = func.return_type().typ.to_string().replace("plain::", ""); + let return_type = if return_type_str != "()" { + format!("return_type: {},\n", return_type_str) + } else { + "".to_string() + }; + + let export_struct_source = format!( + " + #[abi(functions)] + struct {}_abi {{ + {}{} + }}", + func.name(), + parameters, + return_type + ); + + program.push_str(&export_struct_source); + + let (ast, errors) = parse_program(&program); + if !errors.is_empty() { + return Err(AztecMacroError::CouldNotExportFunctionAbi { + span: None, + secondary_message: Some( + format!("Failed to parse Noir macro code (struct {}_abi). This is either a bug in the compiler or the Noir macro code", func.name()) + ) + }); + } + + let sorted_ast = ast.into_sorted(); + types.extend(sorted_ast.types); + Ok(()) +} + +/// Transform Unconstrained +/// +/// Inserts the following code at the beginning of an unconstrained function +/// ```noir +/// let storage = Storage::init(Context::none()); +/// ``` +/// +/// This will allow developers to access their contract' storage struct in unconstrained functions +pub fn transform_unconstrained(func: &mut NoirFunction, storage_struct_name: String) { + func.def.body.statements.insert(0, abstract_storage(storage_struct_name, true)); +} + +/// Helper function that returns what the private context would look like in the ast +/// This should make it available to be consumed within aztec private annotated functions. +/// +/// The replaced code: +/// ```noir +/// /// Before +/// fn foo(inputs: PrivateContextInputs) { +/// // ... +/// } +/// +/// /// After +/// #[aztec(private)] +/// fn foo() { +/// // ... +/// } +fn create_inputs(ty: &str) -> Param { + let context_ident = ident("inputs"); + let context_pattern = Pattern::Identifier(context_ident); + + let path_snippet = ty.to_case(Case::Snake); // e.g. private_context_inputs + let type_path = chained_dep!("aztec", "context", "inputs", &path_snippet, ty); + + let context_type = make_type(UnresolvedTypeData::Named(type_path, vec![], true)); + let visibility = Visibility::Private; + + Param { pattern: context_pattern, typ: context_type, visibility, span: Span::default() } +} + +/// Creates an initialization check to ensure that the contract has been initialized, meant to +/// be injected as the first statement of any function after the context has been created. +/// +/// ```noir +/// assert_is_initialized(&mut context); +/// ``` +fn create_init_check(ty: &str) -> Statement { + let fname = format!("assert_is_initialized_{}", ty.to_case(Case::Snake)); + make_statement(StatementKind::Expression(call( + variable_path(chained_dep!("aztec", "initializer", &fname)), + vec![mutable_reference("context")], + ))) +} + +/// Creates a call to mark_as_initialized which emits the initialization nullifier, meant to +/// be injected as the last statement before returning in a constructor. +/// +/// ```noir +/// mark_as_initialized(&mut context); +/// ``` +fn create_mark_as_initialized(ty: &str) -> Statement { + let fname = format!("mark_as_initialized_{}", ty.to_case(Case::Snake)); + make_statement(StatementKind::Expression(call( + variable_path(chained_dep!("aztec", "initializer", &fname)), + vec![mutable_reference("context")], + ))) +} + +/// Forces a static context for a function, ensuring that no state modifications are allowed +/// +/// ```noir +/// assert(context.inputs.call_context.is_static_call == true, "Function can only be called statically") +/// ``` +fn create_static_check(fname: &str, is_private: bool) -> Statement { + let is_static_call_expr = if is_private { + ["inputs", "call_context", "is_static_call"] + .iter() + .fold(variable("context"), |acc, member| member_access(acc, member)) + } else { + ["inputs", "is_static_call"] + .iter() + .fold(variable("context"), |acc, member| member_access(acc, member)) + }; + make_statement(StatementKind::Constrain(ConstrainStatement( + make_eq(is_static_call_expr, expression(ExpressionKind::Literal(Literal::Bool(true)))), + Some(expression(ExpressionKind::Literal(Literal::Str(format!( + "Function {} can only be called statically", + fname + ))))), + ConstrainKind::Assert, + ))) +} + +/// Creates a check for internal functions ensuring that the caller is self. +/// +/// ```noir +/// assert(context.msg_sender() == context.this_address(), "Function can only be called internally"); +/// ``` +fn create_internal_check(fname: &str) -> Statement { + make_statement(StatementKind::Constrain(ConstrainStatement( + make_eq( + method_call(variable("context"), "msg_sender", vec![]), + method_call(variable("context"), "this_address", vec![]), + ), + Some(expression(ExpressionKind::Literal(Literal::Str(format!( + "Function {} can only be called internally", + fname + ))))), + ConstrainKind::Assert, + ))) +} + +/// Creates a call to assert_initialization_matches_address_preimage to be inserted +/// in the initializer. Checks that the args and sender to the initializer match the +/// commitments from the address preimage. +/// +/// ```noir +/// assert_initialization_matches_address_preimage(context); +/// ``` +fn create_assert_initializer(ty: &str) -> Statement { + let fname = + format!("assert_initialization_matches_address_preimage_{}", ty.to_case(Case::Snake)); + make_statement(StatementKind::Expression(call( + variable_path(chained_dep!("aztec", "initializer", &fname)), + vec![variable("context")], + ))) +} + +fn serialize_to_hasher( + identifier: &Ident, + typ: &UnresolvedTypeData, + hasher_name: &str, +) -> Option> { + let mut statements = Vec::new(); + + // Match the type to determine the padding to do + match typ { + // `{hasher_name}.extend_from_array({ident}.serialize())` + UnresolvedTypeData::Named(..) => { + statements.push(add_struct_to_hasher(identifier, hasher_name)); + } + UnresolvedTypeData::Array(_, arr_type) => { + statements.push(add_array_to_hasher(identifier, arr_type, hasher_name)); + } + // `{hasher_name}.push({ident})` + UnresolvedTypeData::FieldElement => { + statements.push(add_field_to_hasher(identifier, hasher_name)); + } + // Add the integer to the bounded vec, casted to a field + // `{hasher_name}.push({ident} as Field)` + UnresolvedTypeData::Integer(..) | UnresolvedTypeData::Bool => { + statements.push(add_cast_to_hasher(identifier, hasher_name)); + } + UnresolvedTypeData::String(..) => { + let (var_bytes, id) = str_to_bytes(identifier); + statements.push(var_bytes); + statements.push(add_array_to_hasher( + &id, + &UnresolvedType { + typ: UnresolvedTypeData::Integer( + Signedness::Unsigned, + ast::IntegerBitSize::ThirtyTwo, + ), + span: None, + }, + hasher_name, + )) + } + _ => return None, + }; + Some(statements) +} + +/// Creates the private context object to be accessed within the function, the parameters need to be extracted to be +/// appended into the args hash object. +/// +/// The replaced code: +/// ```noir +/// #[aztec(private)] +/// fn foo(structInput: SomeStruct, arrayInput: [u8; 10], fieldInput: Field) -> Field { +/// // Create the hasher object +/// let mut hasher = Hasher::new(); +/// +/// // struct inputs call serialize on them to add an array of fields +/// hasher.add_multiple(structInput.serialize()); +/// +/// // Array inputs are iterated over and each element is added to the hasher (as a field) +/// for i in 0..arrayInput.len() { +/// hasher.add(arrayInput[i] as Field); +/// } +/// // Field inputs are added to the hasher +/// hasher.add({ident}); +/// +/// // Create the context +/// // The inputs (injected by this `create_inputs`) and completed hash object are passed to the context +/// let mut context = PrivateContext::new(inputs, hasher.hash()); +/// } +/// ``` +fn create_context_private(ty: &str, params: &[Param]) -> Result, AztecMacroError> { + let mut injected_statements: Vec = vec![]; + + let hasher_name = "args_hasher"; + + // `let mut args_hasher = Hasher::new();` + let let_hasher = mutable_assignment( + hasher_name, // Assigned to + call( + variable_path(chained_dep!("aztec", "hash", "ArgsHasher", "new")), // Path + vec![], // args + ), + ); + + // Completes: `let mut args_hasher = Hasher::new();` + injected_statements.push(let_hasher); + + // Iterate over each of the function parameters, adding to them to the hasher + for Param { pattern, typ, span, .. } in params { + match pattern { + Pattern::Identifier(identifier) => { + // Match the type to determine the padding to do + let unresolved_type = &typ.typ; + injected_statements.extend( + serialize_to_hasher(identifier, unresolved_type, hasher_name).ok_or_else( + || AztecMacroError::UnsupportedFunctionArgumentType { + typ: unresolved_type.clone(), + span: *span, + }, + )?, + ); + } + _ => todo!(), // Maybe unreachable? + } + } + + // Create the inputs to the context + let inputs_expression = variable("inputs"); + // `args_hasher.hash()` + let hash_call = method_call( + variable(hasher_name), // variable + "hash", // method name + vec![], // args + ); + + let path_snippet = ty.to_case(Case::Snake); // e.g. private_context + + // let mut context = {ty}::new(inputs, hash); + let let_context = mutable_assignment( + "context", // Assigned to + call( + variable_path(chained_dep!("aztec", "context", &path_snippet, ty, "new")), // Path + vec![inputs_expression, hash_call], // args + ), + ); + injected_statements.push(let_context); + + // Return all expressions that will be injected by the hasher + Ok(injected_statements) +} + +/// Creates the public context object to be accessed within the function. +/// +/// The replaced code: +/// ```noir +/// #[aztec(public)] +/// fn foo(inputs: PublicContextInputs, ...) -> Field { +/// let mut context = PublicContext::new(inputs); +/// } +/// ``` +fn create_context_public() -> Result, AztecMacroError> { + let mut injected_expressions: Vec = vec![]; + + // Create the inputs to the context + let inputs_expression = variable("inputs"); + + // let mut context = {ty}::new(inputs, hash); + let let_context = mutable_assignment( + "context", // Assigned to + call( + variable_path(chained_dep!( + "aztec", + "context", + "public_context", + "PublicContext", + "new" + )), // Path + vec![inputs_expression], // args + ), + ); + injected_expressions.push(let_context); + + // Return all expressions that will be injected by the hasher + Ok(injected_expressions) +} + +/// Abstract Return Type +/// +/// This function intercepts the function's current return type and replaces it with pushes to a hasher +/// that will be used to generate the returns hash for the kernel. +/// +/// The replaced code: +/// ```noir +/// /// Before +/// #[aztec(private)] +/// fn foo() -> Field { +/// // ... +/// let my_return_value: Field = 10; +/// my_return_value +/// } +/// +/// /// After +/// #[aztec(private)] +/// fn foo() -> protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs { +/// // ... +/// let my_return_value: Field = 10; +/// let macro__returned__values = my_return_value; +/// let mut returns_hasher = ArgsHasher::new(); +/// returns_hasher.add(macro__returned__values); +/// context.set_return_hash(returns_hasher); +/// } +/// ``` +/// Similarly; Structs will be pushed to the hasher, after serialize() is called on them. +/// Arrays will be iterated over and each element will be pushed to the hasher. +/// Any primitive type that can be cast will be casted to a field and pushed to the hasher. +fn abstract_return_values(func: &NoirFunction) -> Result>, AztecMacroError> { + let current_return_type = func.return_type().typ; + + // Short circuit if the function doesn't return anything + match current_return_type { + UnresolvedTypeData::Unit | UnresolvedTypeData::Unspecified => return Ok(None), + _ => (), + } + + let Some(last_statement) = func.def.body.statements.last() else { + return Ok(None); + }; + + // TODO: support tuples here and in inputs -> convert into an issue + // Check if the return type is an expression, if it is, we can handle it + match last_statement { + Statement { kind: StatementKind::Expression(expression), .. } => { + let return_value_name = "macro__returned__values"; + let hasher_name = "returns_hasher"; + + let mut replacement_statements = vec![ + assignment_with_type( + return_value_name, // Assigned to + current_return_type.clone(), + expression.clone(), + ), + mutable_assignment( + hasher_name, // Assigned to + call( + variable_path(chained_dep!("aztec", "hash", "ArgsHasher", "new")), // Path + vec![], // args + ), + ), + ]; + + let serialization_statements = + serialize_to_hasher(&ident(return_value_name), ¤t_return_type, hasher_name) + .ok_or_else(|| AztecMacroError::UnsupportedFunctionReturnType { + typ: current_return_type.clone(), + span: func.return_type().span.unwrap_or_default(), + })?; + + replacement_statements.extend(serialization_statements); + + replacement_statements.push(make_statement(StatementKind::Semi(method_call( + variable("context"), + "set_return_hash", + vec![variable(hasher_name)], + )))); + + Ok(Some(replacement_statements)) + } + _ => Ok(None), + } +} + +/// Abstract storage +/// +/// For private functions: +/// ```noir +/// #[aztec(private)] +/// fn lol() { +/// let storage = Storage::init(context); +/// } +/// ``` +/// +/// For public functions: +/// ```noir +/// #[aztec(public)] +/// fn lol() { +/// let storage = Storage::init(context); +/// } +/// ``` +/// +/// For unconstrained functions: +/// ```noir +/// unconstrained fn lol() { +/// let storage = Storage::init(()); +/// } +fn abstract_storage(storage_struct_name: String, unconstrained: bool) -> Statement { + let context_expr = if unconstrained { + // Note that the literal unit type (i.e. '()') is not the same as a tuple with zero elements + expression(ExpressionKind::Literal(Literal::Unit)) + } else { + mutable_reference("context") + }; + + assignment( + "storage", // Assigned to + call( + variable_path(chained_path!(storage_struct_name.as_str(), "init")), // Path + vec![context_expr], // args + ), + ) +} + +/// Create Return Type +/// +/// Public functions return protocol_types::abis::public_circuit_public_inputs::PublicCircuitPublicInputs while +/// private functions return protocol_types::abis::private_circuit_public_inputs::::PrivateCircuitPublicInputs +/// +/// This call constructs an ast token referencing the above types +/// The name is set in the function above `transform`, hence the +/// whole token name is passed in +/// +/// The replaced code: +/// ```noir +/// +/// /// Before +/// fn foo() -> protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs { +/// // ... +/// } +/// +/// /// After +/// #[aztec(private)] +/// fn foo() { +/// // ... +/// } +fn create_return_type(ty: &str) -> FunctionReturnType { + let path_snippet = ty.to_case(Case::Snake); // e.g. private_circuit_public_inputs or public_circuit_public_inputs + let return_path = chained_dep!("aztec", "protocol_types", "abis", &path_snippet, ty); + return_type(return_path) +} + +/// Create Context Finish +/// +/// Each aztec function calls `context.finish()` at the end of a function +/// to return values required by the kernel. +/// +/// The replaced code: +/// ```noir +/// /// Before +/// fn foo() -> protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs { +/// // ... +/// context.finish() +/// } +/// +/// /// After +/// #[aztec(private)] +/// fn foo() { +/// // ... +/// } +fn create_context_finish() -> Statement { + let method_call = method_call( + variable("context"), // variable + "finish", // method name + vec![], // args + ); + make_statement(StatementKind::Expression(method_call)) +} + +// +// Methods to create hasher inputs +// + +fn add_struct_to_hasher(identifier: &Ident, hasher_name: &str) -> Statement { + // If this is a struct, we call serialize and add the array to the hasher + let serialized_call = method_call( + variable_path(path(identifier.clone())), // variable + "serialize", // method name + vec![], // args + ); + + make_statement(StatementKind::Semi(method_call( + variable(hasher_name), // variable + "add_multiple", // method name + vec![serialized_call], // args + ))) +} + +fn str_to_bytes(identifier: &Ident) -> (Statement, Ident) { + // let identifier_as_bytes = identifier.as_bytes(); + let var = variable_ident(identifier.clone()); + let contents = if let ExpressionKind::Variable(p, _) = &var.kind { + p.segments.first().cloned().unwrap_or_else(|| panic!("No segments")).0.contents + } else { + panic!("Unexpected identifier type") + }; + let bytes_name = format!("{}_bytes", contents); + let var_bytes = assignment(&bytes_name, method_call(var, "as_bytes", vec![])); + let id = Ident::new(bytes_name, Span::default()); + + (var_bytes, id) +} + +fn create_loop_over(var: Expression, loop_body: Vec) -> Statement { + // If this is an array of primitive types (integers / fields) we can add them each to the hasher + // casted to a field + let span = var.span; + + // `array.len()` + let end_range_expression = method_call( + var, // variable + "len", // method name + vec![], // args + ); + + // What will be looped over + + // - `hasher.add({ident}[i] as Field)` + let for_loop_block = + expression(ExpressionKind::Block(BlockExpression { is_unsafe: false,statements: loop_body })); + + // `for i in 0..{ident}.len()` + make_statement(StatementKind::For(ForLoopStatement { + range: ForRange::Range( + expression(ExpressionKind::Literal(Literal::Integer( + FieldElement::from(i128::from(0)), + false, + ))), + end_range_expression, + ), + identifier: ident("i"), + block: for_loop_block, + span, + })) +} + +fn add_array_to_hasher( + identifier: &Ident, + arr_type: &UnresolvedType, + hasher_name: &str, +) -> Statement { + // If this is an array of primitive types (integers / fields) we can add them each to the hasher + // casted to a field + + // Wrap in the semi thing - does that mean ended with semi colon? + // `hasher.add({ident}[i] as Field)` + + let arr_index = index_array(identifier.clone(), "i"); + let (add_expression, hasher_method_name) = match arr_type.typ { + UnresolvedTypeData::Named(..) => { + let hasher_method_name = "add_multiple".to_owned(); + let call = method_call( + // All serialize 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_name), // variable + &hasher_method_name, // method name + vec![add_expression], + ))); + + create_loop_over(variable_ident(identifier.clone()), vec![block_statement]) +} + +fn add_field_to_hasher(identifier: &Ident, hasher_name: &str) -> Statement { + // `hasher.add({ident})` + let ident = variable_path(path(identifier.clone())); + make_statement(StatementKind::Semi(method_call( + variable(hasher_name), // variable + "add", // method name + vec![ident], // args + ))) +} + +fn add_cast_to_hasher(identifier: &Ident, hasher_name: &str) -> Statement { + // `hasher.add({ident} as Field)` + // `{ident} as Field` + let cast_operation = cast( + variable_path(path(identifier.clone())), // lhs + UnresolvedTypeData::FieldElement, // rhs + ); + + // `hasher.add({ident} as Field)` + make_statement(StatementKind::Semi(method_call( + variable(hasher_name), // variable + "add", // method name + vec![cast_operation], // args + ))) +} + +/** + * Takes a vector of functions and checks for the presence of arguments with Public visibility + * Returns AztecMAcroError::PublicArgsDisallowed if found + */ +pub fn check_for_public_args(functions: &[&NoirFunction]) -> Result<(), AztecMacroError> { + for func in functions { + for param in &func.def.parameters { + if param.visibility == Visibility::Public { + return Err(AztecMacroError::PublicArgsDisallowed { span: func.span() }); + } + } + } + Ok(()) +} diff --git a/aztec_macros/src/transforms/mod.rs b/aztec_macros/src/transforms/mod.rs new file mode 100644 index 00000000000..2a6fef7647f --- /dev/null +++ b/aztec_macros/src/transforms/mod.rs @@ -0,0 +1,6 @@ +pub mod compute_note_hash_and_nullifier; +pub mod contract_interface; +pub mod events; +pub mod functions; +pub mod note_interface; +pub mod storage; diff --git a/aztec_macros/src/transforms/note_interface.rs b/aztec_macros/src/transforms/note_interface.rs new file mode 100644 index 00000000000..fdce8b81db2 --- /dev/null +++ b/aztec_macros/src/transforms/note_interface.rs @@ -0,0 +1,768 @@ +use noirc_errors::Span; +use noirc_frontend::ast::{ + ItemVisibility, LetStatement, NoirFunction, NoirStruct, PathKind, TraitImplItem, TypeImpl, + UnresolvedTypeData, UnresolvedTypeExpression, +}; +use noirc_frontend::{ + graph::CrateId, + macros_api::{FileId, HirContext, HirExpression, HirLiteral, HirStatement}, + parse_program, + parser::SortedModule, + Type, +}; + +use regex::Regex; + +use crate::{ + chained_dep, + utils::{ + ast_utils::{ + check_trait_method_implemented, ident, ident_path, is_custom_attribute, make_type, + }, + errors::AztecMacroError, + hir_utils::{fetch_notes, get_contract_module_data, inject_global}, + }, +}; + +// Automatic implementation of most of the methods in the NoteInterface trait, guiding the user with meaningful error messages in case some +// methods must be implemented manually. +pub fn generate_note_interface_impl(module: &mut SortedModule) -> Result<(), AztecMacroError> { + // Find structs annotated with #[aztec(note)] + let annotated_note_structs = module + .types + .iter_mut() + .filter(|typ| typ.attributes.iter().any(|attr| is_custom_attribute(attr, "aztec(note)"))); + + let mut structs_to_inject = vec![]; + + for note_struct in annotated_note_structs { + // Look for the NoteInterface trait implementation for the note + let trait_impl = module + .trait_impls + .iter_mut() + .find(|trait_impl| { + if let UnresolvedTypeData::Named(struct_path, _, _) = &trait_impl.object_type.typ { + struct_path.last_segment() == note_struct.name + && trait_impl.trait_name.last_segment().0.contents == "NoteInterface" + } else { + false + } + }) + .ok_or(AztecMacroError::CouldNotImplementNoteInterface { + span: Some(note_struct.name.span()), + secondary_message: Some(format!( + "Could not find NoteInterface trait implementation for note: {}", + note_struct.name.0.contents + )), + })?; + let note_interface_impl_span: Option = trait_impl.object_type.span; + // Look for the note struct implementation, generate a default one if it doesn't exist (in order to append methods to it) + let existing_impl = module.impls.iter_mut().find(|r#impl| match &r#impl.object_type.typ { + UnresolvedTypeData::Named(path, _, _) => path.last_segment().eq(¬e_struct.name), + _ => false, + }); + let note_impl = if let Some(note_impl) = existing_impl { + note_impl + } else { + let default_impl = TypeImpl { + object_type: trait_impl.object_type.clone(), + type_span: note_struct.name.span(), + generics: vec![], + methods: vec![], + }; + module.impls.push(default_impl.clone()); + module.impls.last_mut().unwrap() + }; + // Identify the note type (struct name), its fields and its serialized length (generic param of NoteInterface trait impl) + let note_type = note_struct.name.0.contents.to_string(); + let mut note_fields = vec![]; + let note_interface_generics = trait_impl + .trait_generics + .iter() + .map(|gen| match gen.typ.clone() { + UnresolvedTypeData::Named(path, _, _) => { + Ok(path.last_segment().0.contents.to_string()) + } + UnresolvedTypeData::Expression(UnresolvedTypeExpression::Constant(val, _)) => { + Ok(val.to_string()) + } + _ => Err(AztecMacroError::CouldNotImplementNoteInterface { + span: trait_impl.object_type.span, + secondary_message: Some(format!( + "NoteInterface must be generic over NOTE_LEN and NOTE_BYTES_LEN: {}", + note_type + )), + }), + }) + .collect::, _>>()?; + let [note_serialized_len, note_bytes_len]: [_; 2] = + note_interface_generics.try_into().unwrap(); + let note_type_id = note_type_id(¬e_type); + + // Automatically inject the header field if it's not present + let (header_field_name, _) = if let Some(existing_header) = + note_struct.fields.iter().find(|(_, field_type)| match &field_type.typ { + UnresolvedTypeData::Named(path, _, _) => { + path.last_segment().0.contents == "NoteHeader" + } + _ => false, + }) { + existing_header.clone() + } else { + let generated_header = ( + ident("header"), + make_type(UnresolvedTypeData::Named( + chained_dep!("aztec", "note", "note_header", "NoteHeader"), + vec![], + false, + )), + ); + note_struct.fields.push(generated_header.clone()); + generated_header + }; + + for (field_ident, field_type) in note_struct.fields.iter() { + note_fields.push(( + field_ident.0.contents.to_string(), + field_type.typ.to_string().replace("plain::", ""), + )); + } + + if !check_trait_method_implemented(trait_impl, "serialize_content") + && !check_trait_method_implemented(trait_impl, "deserialize_content") + && !note_impl.methods.iter().any(|(func, _)| func.def.name.0.contents == "properties") + { + let note_serialize_content_fn = generate_note_serialize_content( + ¬e_type, + ¬e_fields, + ¬e_serialized_len, + &header_field_name.0.contents, + note_interface_impl_span, + )?; + trait_impl.items.push(TraitImplItem::Function(note_serialize_content_fn)); + + let note_deserialize_content_fn = generate_note_deserialize_content( + ¬e_type, + ¬e_fields, + ¬e_serialized_len, + &header_field_name.0.contents, + note_interface_impl_span, + )?; + trait_impl.items.push(TraitImplItem::Function(note_deserialize_content_fn)); + + let note_properties_struct = generate_note_properties_struct( + ¬e_type, + ¬e_fields, + &header_field_name.0.contents, + note_interface_impl_span, + )?; + structs_to_inject.push(note_properties_struct); + let note_properties_fn = generate_note_properties_fn( + ¬e_type, + ¬e_fields, + &header_field_name.0.contents, + note_interface_impl_span, + )?; + note_impl.methods.push((note_properties_fn, note_impl.type_span)); + } + + if !check_trait_method_implemented(trait_impl, "get_header") { + let get_header_fn = generate_note_get_header( + ¬e_type, + &header_field_name.0.contents, + note_interface_impl_span, + )?; + trait_impl.items.push(TraitImplItem::Function(get_header_fn)); + } + if !check_trait_method_implemented(trait_impl, "set_header") { + let set_header_fn = generate_note_set_header( + ¬e_type, + &header_field_name.0.contents, + note_interface_impl_span, + )?; + trait_impl.items.push(TraitImplItem::Function(set_header_fn)); + } + + if !check_trait_method_implemented(trait_impl, "get_note_type_id") { + let get_note_type_id_fn = + generate_note_get_type_id(¬e_type_id, note_interface_impl_span)?; + trait_impl.items.push(TraitImplItem::Function(get_note_type_id_fn)); + } + + if !check_trait_method_implemented(trait_impl, "compute_note_content_hash") { + let get_header_fn = + generate_compute_note_content_hash(¬e_type, note_interface_impl_span)?; + trait_impl.items.push(TraitImplItem::Function(get_header_fn)); + } + + if !check_trait_method_implemented(trait_impl, "to_be_bytes") { + let get_header_fn = generate_note_to_be_bytes( + ¬e_type, + note_bytes_len.as_str(), + note_serialized_len.as_str(), + note_interface_impl_span, + )?; + trait_impl.items.push(TraitImplItem::Function(get_header_fn)); + } + } + + module.types.extend(structs_to_inject); + Ok(()) +} + +fn generate_note_to_be_bytes( + note_type: &String, + byte_length: &str, + serialized_length: &str, + impl_span: Option, +) -> Result { + let function_source = format!( + " + fn to_be_bytes(self: {1}, storage_slot: Field) -> [u8; {0}] {{ + assert({0} == {2} * 32 + 64, \"Note byte length must be equal to (serialized_length * 32) + 64 bytes\"); + let serialized_note = self.serialize_content(); + + let mut buffer: [u8; {0}] = [0; {0}]; + + let storage_slot_bytes = storage_slot.to_be_bytes(32); + let note_type_id_bytes = {1}::get_note_type_id().to_be_bytes(32); + + for i in 0..32 {{ + buffer[i] = storage_slot_bytes[i]; + buffer[32 + i] = note_type_id_bytes[i]; + }} + + for i in 0..serialized_note.len() {{ + let bytes = serialized_note[i].to_be_bytes(32); + for j in 0..32 {{ + buffer[64 + i * 32 + j] = bytes[j]; + }} + }} + buffer + }} + ", + byte_length, note_type, serialized_length + ) + .to_string(); + + let (function_ast, errors) = parse_program(&function_source); + if !errors.is_empty() { + dbg!(errors); + return Err(AztecMacroError::CouldNotImplementNoteInterface { + secondary_message: Some("Failed to parse Noir macro code (fn to_be_bytes). This is either a bug in the compiler or the Noir macro code".to_string()), + span: impl_span + }); + } + + let mut function_ast = function_ast.into_sorted(); + let mut noir_fn = function_ast.functions.remove(0); + noir_fn.def.span = impl_span.unwrap(); + noir_fn.def.visibility = ItemVisibility::Public; + Ok(noir_fn) +} + +fn generate_note_get_header( + note_type: &String, + note_header_field_name: &String, + impl_span: Option, +) -> Result { + let function_source = format!( + " + fn get_header(note: {}) -> dep::aztec::note::note_header::NoteHeader {{ + note.{} + }} + ", + note_type, note_header_field_name + ) + .to_string(); + + let (function_ast, errors) = parse_program(&function_source); + if !errors.is_empty() { + dbg!(errors); + return Err(AztecMacroError::CouldNotImplementNoteInterface { + secondary_message: Some("Failed to parse Noir macro code (fn get_header). This is either a bug in the compiler or the Noir macro code".to_string()), + span: impl_span + }); + } + + let mut function_ast = function_ast.into_sorted(); + let mut noir_fn = function_ast.functions.remove(0); + noir_fn.def.span = impl_span.unwrap(); + noir_fn.def.visibility = ItemVisibility::Public; + Ok(noir_fn) +} + +fn generate_note_set_header( + note_type: &String, + note_header_field_name: &String, + impl_span: Option, +) -> Result { + let function_source = format!( + " + fn set_header(self: &mut {}, header: dep::aztec::note::note_header::NoteHeader) {{ + self.{} = header; + }} + ", + note_type, note_header_field_name + ); + + let (function_ast, errors) = parse_program(&function_source); + if !errors.is_empty() { + dbg!(errors); + return Err(AztecMacroError::CouldNotImplementNoteInterface { + secondary_message: Some("Failed to parse Noir macro code (fn set_header). This is either a bug in the compiler or the Noir macro code".to_string()), + span: impl_span + }); + } + + let mut function_ast = function_ast.into_sorted(); + let mut noir_fn = function_ast.functions.remove(0); + noir_fn.def.span = impl_span.unwrap(); + noir_fn.def.visibility = ItemVisibility::Public; + Ok(noir_fn) +} + +// Automatically generate the note type id getter method. The id itself its calculated as the concatenation +// of the conversion of the characters in the note's struct name to unsigned integers. +fn generate_note_get_type_id( + note_type_id: &str, + impl_span: Option, +) -> Result { + let function_source = format!( + " + fn get_note_type_id() -> Field {{ + {} + }} + ", + note_type_id + ) + .to_string(); + + let (function_ast, errors) = parse_program(&function_source); + if !errors.is_empty() { + dbg!(errors); + return Err(AztecMacroError::CouldNotImplementNoteInterface { + secondary_message: Some("Failed to parse Noir macro code (fn get_note_type_id). This is either a bug in the compiler or the Noir macro code".to_string()), + span: impl_span + }); + } + + let mut function_ast = function_ast.into_sorted(); + let mut noir_fn = function_ast.functions.remove(0); + noir_fn.def.span = impl_span.unwrap(); + noir_fn.def.visibility = ItemVisibility::Public; + Ok(noir_fn) +} + +// Automatically generate a struct that represents the note's serialization metadata, as +// +// NoteTypeFields { +// field1: PropertySelector { index: 0, offset: 0, length: 32 }, +// field2: PropertySelector { index: 1, offset: 0, length: 32 }, +// ... +// } +// +// It assumes each field occupies an entire field and its serialized in definition order +fn generate_note_properties_struct( + note_type: &str, + note_fields: &[(String, String)], + note_header_field_name: &String, + impl_span: Option, +) -> Result { + let struct_source = + generate_note_properties_struct_source(note_type, note_fields, note_header_field_name); + + let (struct_ast, errors) = parse_program(&struct_source); + if !errors.is_empty() { + dbg!(errors); + return Err(AztecMacroError::CouldNotImplementNoteInterface { + secondary_message: Some(format!("Failed to parse Noir macro code (struct {}Properties). This is either a bug in the compiler or the Noir macro code", note_type)), + span: impl_span + }); + } + + let mut struct_ast = struct_ast.into_sorted(); + Ok(struct_ast.types.remove(0)) +} + +// Generate the deserialize_content method as +// +// fn deserialize_content(serialized_note: [Field; NOTE_SERILIZED_LEN]) -> Self { +// NoteType { +// note_field1: serialized_note[0] as Field, +// note_field2: NoteFieldType2::from_field(serialized_note[1])... +// } +// } +// It assumes every note field is stored in an individual serialized field, +// and can be converted to the original type via the from_field() trait (structs) or cast as Field (integers) +fn generate_note_deserialize_content( + note_type: &str, + note_fields: &[(String, String)], + note_serialize_len: &String, + note_header_field_name: &String, + impl_span: Option, +) -> Result { + let function_source = generate_note_deserialize_content_source( + note_type, + note_fields, + note_serialize_len, + note_header_field_name, + ); + + let (function_ast, errors) = parse_program(&function_source); + if !errors.is_empty() { + dbg!(errors); + return Err(AztecMacroError::CouldNotImplementNoteInterface { + secondary_message: Some("Failed to parse Noir macro code (fn deserialize_content). This is either a bug in the compiler or the Noir macro code".to_string()), + span: impl_span + }); + } + + let mut function_ast = function_ast.into_sorted(); + let mut noir_fn = function_ast.functions.remove(0); + noir_fn.def.span = impl_span.unwrap(); + noir_fn.def.visibility = ItemVisibility::Public; + Ok(noir_fn) +} + +// Generate the serialize_content method as +// +// fn serialize_content(self: {}) -> [Field; NOTE_SERIALIZED_LEN] { +// [self.note_field1 as Field, self.note_field2.to_field()...] +// } +// +// It assumes every struct field can be converted either via the to_field() trait (structs) or cast as Field (integers) +fn generate_note_serialize_content( + note_type: &str, + note_fields: &[(String, String)], + note_serialize_len: &String, + note_header_field_name: &String, + impl_span: Option, +) -> Result { + let function_source = generate_note_serialize_content_source( + note_type, + note_fields, + note_serialize_len, + note_header_field_name, + ); + + let (function_ast, errors) = parse_program(&function_source); + if !errors.is_empty() { + dbg!(errors); + return Err(AztecMacroError::CouldNotImplementNoteInterface { + secondary_message: Some("Failed to parse Noir macro code (fn serialize_content). This is either a bug in the compiler or the Noir macro code".to_string()), + span: impl_span + }); + } + + let mut function_ast = function_ast.into_sorted(); + let mut noir_fn = function_ast.functions.remove(0); + noir_fn.def.span = impl_span.unwrap(); + noir_fn.def.visibility = ItemVisibility::Public; + Ok(noir_fn) +} + +// Automatically generate a function in the Note's impl that returns the note's fields metadata +fn generate_note_properties_fn( + note_type: &str, + note_fields: &[(String, String)], + note_header_field_name: &String, + impl_span: Option, +) -> Result { + let function_source = + generate_note_properties_fn_source(note_type, note_fields, note_header_field_name); + let (function_ast, errors) = parse_program(&function_source); + if !errors.is_empty() { + dbg!(errors); + return Err(AztecMacroError::CouldNotImplementNoteInterface { + secondary_message: Some("Failed to parse Noir macro code (fn properties). This is either a bug in the compiler or the Noir macro code".to_string()), + span: impl_span + }); + } + let mut function_ast = function_ast.into_sorted(); + let mut noir_fn = function_ast.functions.remove(0); + noir_fn.def.span = impl_span.unwrap(); + noir_fn.def.visibility = ItemVisibility::Public; + Ok(noir_fn) +} + +// Automatically generate the method to compute the note's content hash as: +// fn compute_note_content_hash(self: NoteType) -> Field { +// dep::aztec::hash::pedersen_hash(self.serialize_content(), dep::aztec::protocol_types::constants::GENERATOR_INDEX__NOTE_CONTENT_HASH) +// } +// +fn generate_compute_note_content_hash( + note_type: &String, + impl_span: Option, +) -> Result { + let function_source = format!( + " + fn compute_note_content_hash(self: {}) -> Field {{ + dep::aztec::hash::pedersen_hash(self.serialize_content(), dep::aztec::protocol_types::constants::GENERATOR_INDEX__NOTE_CONTENT_HASH) + }} + ", + note_type + ); + let (function_ast, errors) = parse_program(&function_source); + if !errors.is_empty() { + dbg!(errors); + return Err(AztecMacroError::CouldNotImplementNoteInterface { + secondary_message: Some("Failed to parse Noir macro code (fn compute_note_content_hash). This is either a bug in the compiler or the Noir macro code".to_string()), + span: impl_span + }); + } + let mut function_ast = function_ast.into_sorted(); + let mut noir_fn = function_ast.functions.remove(0); + noir_fn.def.span = impl_span.unwrap(); + noir_fn.def.visibility = ItemVisibility::Public; + Ok(noir_fn) +} + +fn generate_note_exports_global( + note_type: &str, + note_type_id: &str, +) -> Result { + let struct_source = format!( + " + #[abi(notes)] + global {0}_EXPORTS: (Field, str<{1}>) = ({2},\"{0}\"); + ", + note_type, + note_type_id.len(), + note_type_id + ) + .to_string(); + + let (global_ast, errors) = parse_program(&struct_source); + if !errors.is_empty() { + dbg!(errors); + return Err(AztecMacroError::CouldNotImplementNoteInterface { + secondary_message: Some(format!("Failed to parse Noir macro code (struct {}Exports). This is either a bug in the compiler or the Noir macro code", note_type)), + span: None + }); + } + + let mut global_ast = global_ast.into_sorted(); + Ok(global_ast.globals.pop().unwrap()) +} + +// Source code generator functions. These utility methods produce Noir code as strings, that are then parsed and added to the AST. + +fn generate_note_properties_struct_source( + note_type: &str, + note_fields: &[(String, String)], + note_header_field_name: &String, +) -> String { + let note_property_selectors = note_fields + .iter() + .filter_map(|(field_name, _)| { + if field_name != note_header_field_name { + Some(format!( + "{}: dep::aztec::note::note_getter_options::PropertySelector", + field_name + )) + } else { + None + } + }) + .collect::>() + .join(",\n"); + format!( + " + struct {}Properties {{ + {} + }}", + note_type, note_property_selectors + ) + .to_string() +} + +fn generate_note_properties_fn_source( + note_type: &str, + note_fields: &[(String, String)], + note_header_field_name: &String, +) -> String { + let note_property_selectors = note_fields + .iter() + .enumerate() + .filter_map(|(index, (field_name, _))| { + if field_name != note_header_field_name { + Some(format!( + "{}: dep::aztec::note::note_getter_options::PropertySelector {{ index: {}, offset: 0, length: 32 }}", + field_name, + index + )) + } else { + None + } + }) + .collect::>() + .join(", "); + format!( + " + pub fn properties() -> {0}Properties {{ + {0}Properties {{ + {1} + }} + }}", + note_type, note_property_selectors + ) + .to_string() +} + +fn generate_note_serialize_content_source( + note_type: &str, + note_fields: &[(String, String)], + note_serialize_len: &String, + note_header_field_name: &String, +) -> String { + let note_fields = note_fields + .iter() + .filter_map(|(field_name, field_type)| { + if field_name != note_header_field_name { + if field_type == "Field" { + Some(format!("self.{}", field_name)) + } else { + Some(format!("self.{}.to_field()", field_name)) + } + } else { + None + } + }) + .collect::>() + .join(", "); + format!( + " + fn serialize_content(self: {}) -> [Field; {}] {{ + [{}] + }}", + note_type, note_serialize_len, note_fields + ) + .to_string() +} + +fn generate_note_deserialize_content_source( + note_type: &str, + note_fields: &[(String, String)], + note_serialize_len: &String, + note_header_field_name: &String, +) -> String { + let note_fields = note_fields + .iter() + .enumerate() + .map(|(index, (field_name, field_type))| { + if field_name != note_header_field_name { + // TODO: Simplify this when https://github.com/noir-lang/noir/issues/4463 is fixed + if field_type.eq("Field") + || Regex::new(r"u[0-9]+").unwrap().is_match(field_type) + || field_type.eq("bool") + { + format!("{}: serialized_note[{}] as {},", field_name, index, field_type) + } else { + format!( + "{}: {}::from_field(serialized_note[{}]),", + field_name, field_type, index + ) + } + } else { + format!( + "{}: dep::aztec::note::note_header::NoteHeader::empty()", + note_header_field_name + ) + } + }) + .collect::>() + .join("\n"); + format!( + " + fn deserialize_content(serialized_note: [Field; {}]) -> Self {{ + {} {{ + {} + }} + }}", + note_serialize_len, note_type, note_fields + ) + .to_string() +} + +// Utility function to generate the note type id as a Field +fn note_type_id(note_type: &str) -> String { + // TODO(#4519) Improve automatic note id generation and assignment + note_type.chars().map(|c| (c as u32).to_string()).collect::>().join("") +} + +pub fn inject_note_exports( + crate_id: &CrateId, + context: &mut HirContext, +) -> Result<(), (AztecMacroError, FileId)> { + if let Some((_, module_id, file_id)) = get_contract_module_data(context, crate_id) { + let notes = fetch_notes(context); + + for (_, note) in notes { + let func_id = context + .def_interner + .lookup_method( + &Type::Struct(context.def_interner.get_struct(note.borrow().id), vec![]), + note.borrow().id, + "get_note_type_id", + false, + ) + .ok_or(( + AztecMacroError::CouldNotExportStorageLayout { + span: None, + secondary_message: Some(format!( + "Could not retrieve get_note_type_id function for note {}", + note.borrow().name.0.contents + )), + }, + file_id, + ))?; + let init_function = + context.def_interner.function(&func_id).block(&context.def_interner); + let init_function_statement_id = init_function.statements().first().ok_or(( + AztecMacroError::CouldNotExportStorageLayout { + span: None, + secondary_message: Some(format!( + "Could not retrieve note id statement from function for note {}", + note.borrow().name.0.contents + )), + }, + file_id, + ))?; + let note_id_statement = context.def_interner.statement(init_function_statement_id); + + let note_id_value = match note_id_statement { + HirStatement::Expression(expression_id) => { + match context.def_interner.expression(&expression_id) { + HirExpression::Literal(HirLiteral::Integer(value, _)) => Ok(value), + _ => Err(( + AztecMacroError::CouldNotExportStorageLayout { + span: None, + secondary_message: Some( + "note_id statement must be a literal expression".to_string(), + ), + }, + file_id, + )), + } + } + _ => Err(( + AztecMacroError::CouldNotAssignStorageSlots { + secondary_message: Some( + "note_id statement must be an expression".to_string(), + ), + }, + file_id, + )), + }?; + let global = generate_note_exports_global( + ¬e.borrow().name.0.contents, + ¬e_id_value.to_string(), + ) + .map_err(|err| (err, file_id))?; + + inject_global(crate_id, context, global, module_id, file_id); + } + } + Ok(()) +} diff --git a/aztec_macros/src/transforms/storage.rs b/aztec_macros/src/transforms/storage.rs new file mode 100644 index 00000000000..f3d615f15dd --- /dev/null +++ b/aztec_macros/src/transforms/storage.rs @@ -0,0 +1,551 @@ +use acvm::acir::AcirField; +use noirc_errors::Span; +use noirc_frontend::ast::{ + BlockExpression, Expression, ExpressionKind, FunctionDefinition, Ident, Literal, NoirFunction, + NoirStruct, Pattern, StatementKind, TypeImpl, UnresolvedType, UnresolvedTypeData, +}; +use noirc_frontend::{ + graph::CrateId, + macros_api::{ + FieldElement, FileId, HirContext, HirExpression, HirLiteral, HirStatement, NodeInterner, + }, + node_interner::TraitId, + parse_program, + parser::SortedModule, + token::SecondaryAttribute, + Type, +}; + +use crate::{ + chained_path, + utils::{ + ast_utils::{ + call, expression, ident, ident_path, is_custom_attribute, lambda, make_statement, + make_type, pattern, return_type, variable, variable_path, + }, + errors::AztecMacroError, + hir_utils::{ + collect_crate_structs, collect_traits, get_contract_module_data, get_serialized_length, + }, + }, +}; + +// Check to see if the user has defined a storage struct +pub fn check_for_storage_definition( + module: &SortedModule, +) -> Result, AztecMacroError> { + let result: Vec<&NoirStruct> = module + .types + .iter() + .filter(|r#struct| { + r#struct.attributes.iter().any(|attr| is_custom_attribute(attr, "aztec(storage)")) + }) + .collect(); + if result.len() > 1 { + return Err(AztecMacroError::MultipleStorageDefinitions { + span: result.first().map(|res| res.name.span()), + }); + } + Ok(result.iter().map(|&r#struct| r#struct.name.0.contents.clone()).next()) +} + +// Injects the Context generic in each of the Storage struct fields to avoid boilerplate, +// taking maps into account (including nested maps) +fn inject_context_in_storage_field(field: &mut UnresolvedType) -> Result<(), AztecMacroError> { + match &mut field.typ { + UnresolvedTypeData::Named(path, generics, _) => { + generics.push(make_type(UnresolvedTypeData::Named( + ident_path("Context"), + vec![], + false, + ))); + match path.segments.last().unwrap().0.contents.as_str() { + "Map" => inject_context_in_storage_field(&mut generics[1]), + _ => Ok(()), + } + } + _ => Err(AztecMacroError::CouldNotInjectContextGenericInStorage { + secondary_message: Some(format!("Unsupported type: {:?}", field.typ)), + }), + } +} + +// Injects the Context generic in the storage struct to avoid boilerplate +// Transforms this: +// struct Storage { +// a_var: SomeStoragePrimitive, +// a_map: Map>, +// } +// +// Into this: +// +// struct Storage { +// a_var: SomeStoragePrimitive, +// a_map: Map, Context>, +// } +pub fn inject_context_in_storage(module: &mut SortedModule) -> Result<(), AztecMacroError> { + let storage_struct = module + .types + .iter_mut() + .find(|r#struct| { + r#struct.attributes.iter().any(|attr| is_custom_attribute(attr, "aztec(storage)")) + }) + .unwrap(); + storage_struct.generics.push(ident("Context")); + storage_struct + .fields + .iter_mut() + .map(|(_, field)| inject_context_in_storage_field(field)) + .collect::, _>>()?; + Ok(()) +} + +// Check to see if the user has defined an impl for the storage struct +pub fn check_for_storage_implementation( + module: &SortedModule, + storage_struct_name: &String, +) -> bool { + module.impls.iter().any(|r#impl| match &r#impl.object_type.typ { + UnresolvedTypeData::Named(path, _, _) => { + path.segments.last().is_some_and(|segment| segment.0.contents == *storage_struct_name) + } + _ => false, + }) +} + +/// Auxiliary function to generate the storage constructor for a given field, using +/// the Storage definition as a reference. Supports nesting. +pub fn generate_storage_field_constructor( + (type_ident, unresolved_type): &(Ident, UnresolvedType), + slot: Expression, +) -> Result { + let typ = &unresolved_type.typ; + match typ { + UnresolvedTypeData::Named(path, generics, _) => { + let mut new_path = path.clone().to_owned(); + new_path.segments.push(ident("new")); + match path.segments.last().unwrap().0.contents.as_str() { + "Map" => Ok(call( + variable_path(new_path), + vec![ + variable("context"), + slot, + lambda( + // This lambda will be equivalent to the following + // | context, slot | { T::new(context, slot) } + // Since the `new` function has type bindings for its arguments, we don't specify the types + // of either context nor slot, and avoid that way having to deal with the generic context + // type. + vec![ + (pattern("context"), make_type(UnresolvedTypeData::Unspecified)), + ( + Pattern::Identifier(ident("slot")), + make_type(UnresolvedTypeData::Unspecified), + ), + ], + generate_storage_field_constructor( + // Map is expected to have three generic parameters: key, value and context (i.e. + // Map. Here `get(1)` fetches the value type. + &(type_ident.clone(), generics.get(1).unwrap().clone()), + variable("slot"), + )?, + ), + ], + )), + _ => Ok(call(variable_path(new_path), vec![variable("context"), slot])), + } + } + _ => Err(AztecMacroError::UnsupportedStorageType { + typ: typ.clone(), + span: Some(type_ident.span()), + }), + } +} + +// Generates the Storage implementation block from the Storage struct definition if it does not exist +/// From: +/// +/// struct Storage { +/// a_map: Map, Context>, +/// a_nested_map: Map, Context>, Context>, +/// a_field: SomeStoragePrimitive, +/// } +/// +/// To: +/// +/// impl Storage { +/// fn init(context: Context) -> Self { +/// Storage { +/// a_map: Map::new(context, 0, |context, slot| { +/// SomeStoragePrimitive::new(context, slot) +/// }), +/// a_nested_map: Map::new(context, 0, |context, slot| { +/// Map::new(context, slot, |context, slot| { +/// SomeStoragePrimitive::new(context, slot) +/// }) +/// }), +/// a_field: SomeStoragePrimitive::new(context, 0), +/// } +/// } +/// } +/// +/// Storage slots are generated as 0 and will be populated using the information from the HIR +/// at a later stage. +pub fn generate_storage_implementation( + module: &mut SortedModule, + storage_struct_name: &String, +) -> Result<(), AztecMacroError> { + let definition = module + .types + .iter() + .find(|r#struct| r#struct.name.0.contents == *storage_struct_name) + .unwrap(); + + let slot_zero = expression(ExpressionKind::Literal(Literal::Integer( + FieldElement::from(i128::from(0)), + false, + ))); + + let field_constructors = definition + .fields + .iter() + .flat_map(|field| { + generate_storage_field_constructor(field, slot_zero.clone()) + .map(|expression| (field.0.clone(), expression)) + }) + .collect(); + + let storage_constructor_statement = make_statement(StatementKind::Expression(expression( + ExpressionKind::constructor((chained_path!(storage_struct_name), field_constructors)), + ))); + + // This is the type over which the impl is generic. + let generic_context_ident = ident("Context"); + let generic_context_type = + make_type(UnresolvedTypeData::Named(ident_path("Context"), vec![], true)); + + let init = NoirFunction::normal(FunctionDefinition::normal( + &ident("init"), + &vec![], + &[(ident("context"), generic_context_type.clone())], + &BlockExpression { is_unsafe: false, statements: vec![storage_constructor_statement] }, + &[], + &return_type(chained_path!("Self")), + )); + + let storage_impl = TypeImpl { + object_type: UnresolvedType { + typ: UnresolvedTypeData::Named( + chained_path!(storage_struct_name), + vec![generic_context_type.clone()], + true, + ), + span: Some(Span::default()), + }, + type_span: Span::default(), + generics: vec![generic_context_ident], + + methods: vec![(init, Span::default())], + }; + module.impls.push(storage_impl); + + Ok(()) +} + +/// Obtains the serialized length of a type that implements the Serialize trait. +pub fn get_storage_serialized_length( + traits: &[TraitId], + typ: &Type, + interner: &NodeInterner, +) -> Result { + let (struct_name, maybe_stored_in_state) = match typ { + Type::Struct(struct_type, generics) => { + Ok((struct_type.borrow().name.0.contents.clone(), generics.first())) + } + _ => Err(AztecMacroError::CouldNotAssignStorageSlots { + secondary_message: Some("State storage variable must be a struct".to_string()), + }), + }?; + let stored_in_state = + maybe_stored_in_state.ok_or(AztecMacroError::CouldNotAssignStorageSlots { + secondary_message: Some("State storage variable must be generic".to_string()), + })?; + + let is_note = match stored_in_state { + Type::Struct(typ, _) => interner + .struct_attributes(&typ.borrow().id) + .iter() + .any(|attr| is_custom_attribute(attr, "aztec(note)")), + _ => false, + }; + + // Maps and (private) Notes always occupy a single slot. Someone could store a Note in PublicMutable for whatever reason though. + if struct_name == "Map" || (is_note && struct_name != "PublicMutable") { + return Ok(1); + } + + get_serialized_length(traits, "Serialize", stored_in_state, interner).map_err(|err| { + AztecMacroError::CouldNotAssignStorageSlots { secondary_message: Some(err.primary_message) } + }) +} + +/// Assigns storage slots to the storage struct fields based on the serialized length of the types. This automatic assignment +/// will only trigger if the assigned storage slot is invalid (0 as generated by generate_storage_implementation) +pub fn assign_storage_slots( + crate_id: &CrateId, + context: &mut HirContext, +) -> Result<(), (AztecMacroError, FileId)> { + let traits: Vec<_> = collect_traits(context); + if let Some((_, _, file_id)) = get_contract_module_data(context, crate_id) { + let maybe_storage_struct = + collect_crate_structs(crate_id, context).iter().find_map(|struct_id| { + let r#struct = context.def_interner.get_struct(*struct_id); + let attributes = context.def_interner.struct_attributes(struct_id); + if attributes.iter().any(|attr| is_custom_attribute(attr, "aztec(storage)")) + && r#struct.borrow().id.krate() == *crate_id + { + Some(r#struct) + } else { + None + } + }); + + let maybe_storage_layout = + context.def_interner.get_all_globals().iter().find_map(|global_info| { + let statement = context.def_interner.get_global_let_statement(global_info.id); + if statement.clone().is_some_and(|stmt| { + stmt.attributes + .iter() + .any(|attr| *attr == SecondaryAttribute::Abi("storage".to_string())) + }) { + let expr = context.def_interner.expression(&statement.unwrap().expression); + match expr { + HirExpression::Constructor(hir_constructor_expression) => { + if hir_constructor_expression.r#type.borrow().id.krate() == *crate_id { + Some(hir_constructor_expression) + } else { + None + } + } + _ => None, + } + } else { + None + } + }); + + if let (Some(storage_struct), Some(storage_layout)) = + (maybe_storage_struct, maybe_storage_layout) + { + let init_id = context + .def_interner + .lookup_method( + &Type::Struct( + context.def_interner.get_struct(storage_struct.borrow().id), + vec![], + ), + storage_struct.borrow().id, + "init", + false, + ) + .ok_or(( + AztecMacroError::CouldNotAssignStorageSlots { + secondary_message: Some( + "Storage struct must have an init function".to_string(), + ), + }, + file_id, + ))?; + let init_function = + context.def_interner.function(&init_id).block(&context.def_interner); + let init_function_statement_id = init_function.statements().first().ok_or(( + AztecMacroError::CouldNotAssignStorageSlots { + secondary_message: Some("Init storage statement not found".to_string()), + }, + file_id, + ))?; + let storage_constructor_statement = + context.def_interner.statement(init_function_statement_id); + + let storage_constructor_expression = match storage_constructor_statement { + HirStatement::Expression(expression_id) => { + match context.def_interner.expression(&expression_id) { + HirExpression::Constructor(hir_constructor_expression) => { + Ok(hir_constructor_expression) + } + _ => Err(( + AztecMacroError::CouldNotAssignStorageSlots { + secondary_message: Some( + "Storage constructor statement must be a constructor expression" + .to_string(), + ), + }, + file_id, + )), + } + } + _ => Err(( + AztecMacroError::CouldNotAssignStorageSlots { + secondary_message: Some( + "Storage constructor statement must be an expression".to_string(), + ), + }, + file_id, + )), + }?; + + let mut storage_slot: u32 = 1; + for (index, (_, expr_id)) in storage_constructor_expression.fields.iter().enumerate() { + let fields = storage_struct + .borrow() + .get_fields(&storage_constructor_expression.struct_generics); + let (field_name, field_type) = fields.get(index).unwrap(); + let new_call_expression = match context.def_interner.expression(expr_id) { + HirExpression::Call(hir_call_expression) => Ok(hir_call_expression), + _ => Err(( + AztecMacroError::CouldNotAssignStorageSlots { + secondary_message: Some( + "Storage field initialization expression is not a call expression" + .to_string(), + ), + }, + file_id, + )), + }?; + + let slot_arg_expression = + context.def_interner.expression(&new_call_expression.arguments[1]); + + let current_storage_slot = match slot_arg_expression { + HirExpression::Literal(HirLiteral::Integer(slot, _)) => Ok(slot.to_u128()), + _ => Err(( + AztecMacroError::CouldNotAssignStorageSlots { + secondary_message: Some( + "Storage slot argument expression must be a literal integer" + .to_string(), + ), + }, + file_id, + )), + }?; + + let storage_layout_field = + storage_layout.fields.iter().find(|field| field.0 .0.contents == *field_name); + + let storage_layout_slot_expr_id = + if let Some((_, expr_id)) = storage_layout_field { + let expr = context.def_interner.expression(expr_id); + if let HirExpression::Constructor(storage_layout_field_storable_expr) = expr + { + storage_layout_field_storable_expr.fields.iter().find_map( + |(field, expr_id)| { + if field.0.contents == "slot" { + Some(*expr_id) + } else { + None + } + }, + ) + } else { + None + } + } else { + None + } + .ok_or(( + AztecMacroError::CouldNotAssignStorageSlots { + secondary_message: Some(format!( + "Storage layout field ({}) not found or has an incorrect type", + field_name + )), + }, + file_id, + ))?; + + let new_storage_slot = if current_storage_slot == 0 { + u128::from(storage_slot) + } else { + current_storage_slot + }; + + let type_serialized_len = + get_storage_serialized_length(&traits, field_type, &context.def_interner) + .map_err(|err| (err, file_id))?; + + context.def_interner.update_expression(new_call_expression.arguments[1], |expr| { + *expr = HirExpression::Literal(HirLiteral::Integer( + FieldElement::from(new_storage_slot), + false, + )) + }); + + context.def_interner.update_expression(storage_layout_slot_expr_id, |expr| { + *expr = HirExpression::Literal(HirLiteral::Integer( + FieldElement::from(new_storage_slot), + false, + )) + }); + + storage_slot += type_serialized_len; + } + } + } + + Ok(()) +} + +pub fn generate_storage_layout( + module: &mut SortedModule, + storage_struct_name: String, +) -> Result<(), AztecMacroError> { + let definition = module + .types + .iter() + .find(|r#struct| r#struct.name.0.contents == *storage_struct_name) + .unwrap(); + + let mut generic_args = vec![]; + let mut storable_fields = vec![]; + let mut storable_fields_impl = vec![]; + + definition.fields.iter().enumerate().for_each(|(index, (field_ident, field_type))| { + storable_fields.push(format!("{}: dep::aztec::prelude::Storable", field_ident, index)); + generic_args.push(format!("N{}", index)); + storable_fields_impl.push(format!( + "{}: dep::aztec::prelude::Storable {{ slot: 0, typ: \"{}\" }}", + field_ident, + field_type.to_string().replace("plain::", "") + )); + }); + + let storage_fields_source = format!( + " + struct StorageLayout<{}> {{ + {} + }} + + #[abi(storage)] + global STORAGE_LAYOUT = StorageLayout {{ + {} + }}; + ", + generic_args.join(", "), + storable_fields.join(",\n"), + storable_fields_impl.join(",\n") + ); + + let (struct_ast, errors) = parse_program(&storage_fields_source); + if !errors.is_empty() { + dbg!(errors); + return Err(AztecMacroError::CouldNotExportStorageLayout { + secondary_message: Some("Failed to parse Noir macro code (struct StorageLayout). This is either a bug in the compiler or the Noir macro code".to_string()), + span: None + }); + } + + let mut struct_ast = struct_ast.into_sorted(); + module.types.push(struct_ast.types.pop().unwrap()); + module.globals.push(struct_ast.globals.pop().unwrap()); + + Ok(()) +} diff --git a/aztec_macros/src/utils/ast_utils.rs b/aztec_macros/src/utils/ast_utils.rs new file mode 100644 index 00000000000..4706be2df25 --- /dev/null +++ b/aztec_macros/src/utils/ast_utils.rs @@ -0,0 +1,197 @@ +use noirc_errors::{Span, Spanned}; +use noirc_frontend::ast::{ + BinaryOpKind, CallExpression, CastExpression, Expression, ExpressionKind, FunctionReturnType, + Ident, IndexExpression, InfixExpression, Lambda, LetStatement, MemberAccessExpression, + MethodCallExpression, NoirTraitImpl, Path, Pattern, PrefixExpression, Statement, StatementKind, + TraitImplItem, UnaryOp, UnresolvedType, UnresolvedTypeData, +}; +use noirc_frontend::token::SecondaryAttribute; + +// +// Helper macros for creating noir ast nodes +// +pub fn ident(name: &str) -> Ident { + Ident::new(name.to_string(), Span::default()) +} + +pub fn ident_path(name: &str) -> Path { + Path::from_ident(ident(name)) +} + +pub fn path(ident: Ident) -> Path { + Path::from_ident(ident) +} + +pub fn expression(kind: ExpressionKind) -> Expression { + Expression::new(kind, Span::default()) +} + +pub fn variable(name: &str) -> Expression { + expression(ExpressionKind::Variable(ident_path(name), None)) +} + +pub fn variable_ident(identifier: Ident) -> Expression { + expression(ExpressionKind::Variable(path(identifier), None)) +} + +pub fn variable_path(path: Path) -> Expression { + expression(ExpressionKind::Variable(path, None)) +} + +pub fn method_call( + object: Expression, + method_name: &str, + arguments: Vec, +) -> Expression { + expression(ExpressionKind::MethodCall(Box::new(MethodCallExpression { + object, + method_name: ident(method_name), + arguments, + generics: None, + }))) +} + +pub fn call(func: Expression, arguments: Vec) -> Expression { + expression(ExpressionKind::Call(Box::new(CallExpression { func: Box::new(func), arguments }))) +} + +pub fn pattern(name: &str) -> Pattern { + Pattern::Identifier(ident(name)) +} + +pub fn mutable(name: &str) -> Pattern { + Pattern::Mutable(Box::new(pattern(name)), Span::default(), true) +} + +pub fn mutable_assignment(name: &str, assigned_to: Expression) -> Statement { + make_statement(StatementKind::Let(LetStatement { + pattern: mutable(name), + r#type: make_type(UnresolvedTypeData::Unspecified), + expression: assigned_to, + comptime: false, + attributes: vec![], + })) +} + +pub fn mutable_reference(variable_name: &str) -> Expression { + expression(ExpressionKind::Prefix(Box::new(PrefixExpression { + operator: UnaryOp::MutableReference, + rhs: variable(variable_name), + }))) +} + +pub fn assignment(name: &str, assigned_to: Expression) -> Statement { + assignment_with_type(name, UnresolvedTypeData::Unspecified, assigned_to) +} + +pub fn assignment_with_type( + name: &str, + typ: UnresolvedTypeData, + assigned_to: Expression, +) -> Statement { + make_statement(StatementKind::Let(LetStatement { + pattern: pattern(name), + r#type: make_type(typ), + expression: assigned_to, + comptime: false, + attributes: vec![], + })) +} + +pub fn return_type(path: Path) -> FunctionReturnType { + let ty = make_type(UnresolvedTypeData::Named(path, vec![], true)); + FunctionReturnType::Ty(ty) +} + +pub fn lambda(parameters: Vec<(Pattern, UnresolvedType)>, body: Expression) -> Expression { + expression(ExpressionKind::Lambda(Box::new(Lambda { + parameters, + return_type: UnresolvedType { + typ: UnresolvedTypeData::Unspecified, + span: Some(Span::default()), + }, + body, + }))) +} + +pub fn make_eq(lhs: Expression, rhs: Expression) -> Expression { + expression(ExpressionKind::Infix(Box::new(InfixExpression { + lhs, + rhs, + operator: Spanned::from(Span::default(), BinaryOpKind::Equal), + }))) +} + +pub fn make_statement(kind: StatementKind) -> Statement { + Statement { span: Span::default(), kind } +} + +pub fn member_access(lhs: Expression, member: &str) -> Expression { + expression(ExpressionKind::MemberAccess(Box::new(MemberAccessExpression { + lhs, + rhs: ident(member), + }))) +} + +#[macro_export] +macro_rules! chained_path { + ( $base:expr ) => { + { + ident_path($base) + } + }; + ( $base:expr $(, $tail:expr)* ) => { + { + let mut base_path = ident_path($base); + $( + base_path.segments.push(ident($tail)); + )* + base_path + } + } +} + +#[macro_export] +macro_rules! chained_dep { + ( $base:expr $(, $tail:expr)* ) => { + { + let mut base_path = ident_path($base); + base_path.kind = PathKind::Dep; + $( + base_path.segments.push(ident($tail)); + )* + base_path + } + } +} + +pub fn cast(lhs: Expression, ty: UnresolvedTypeData) -> Expression { + expression(ExpressionKind::Cast(Box::new(CastExpression { lhs, r#type: make_type(ty) }))) +} + +pub fn make_type(typ: UnresolvedTypeData) -> UnresolvedType { + UnresolvedType { typ, span: Some(Span::default()) } +} + +pub fn index_array(array: Ident, index: &str) -> Expression { + expression(ExpressionKind::Index(Box::new(IndexExpression { + collection: variable_path(path(array)), + index: variable(index), + }))) +} + +pub fn check_trait_method_implemented(trait_impl: &NoirTraitImpl, method_name: &str) -> bool { + trait_impl.items.iter().any(|item| match item { + TraitImplItem::Function(func) => func.def.name.0.contents == method_name, + _ => false, + }) +} + +/// Checks if an attribute is a custom attribute with a specific name +pub fn is_custom_attribute(attr: &SecondaryAttribute, attribute_name: &str) -> bool { + if let SecondaryAttribute::Custom(custom_attr) = attr { + custom_attr.as_str() == attribute_name + } else { + false + } +} diff --git a/aztec_macros/src/utils/checks.rs b/aztec_macros/src/utils/checks.rs new file mode 100644 index 00000000000..5232f67ae87 --- /dev/null +++ b/aztec_macros/src/utils/checks.rs @@ -0,0 +1,22 @@ +use noirc_frontend::{ + graph::CrateId, + macros_api::{FileId, HirContext, MacroError}, +}; + +use super::errors::AztecMacroError; + +/// Creates an error alerting the user that they have not downloaded the Aztec-noir library +pub fn check_for_aztec_dependency( + crate_id: &CrateId, + context: &HirContext, +) -> Result<(), (MacroError, FileId)> { + if has_aztec_dependency(crate_id, context) { + Ok(()) + } else { + Err((AztecMacroError::AztecDepNotFound.into(), context.crate_graph[crate_id].root_file_id)) + } +} + +pub fn has_aztec_dependency(crate_id: &CrateId, context: &HirContext) -> bool { + context.crate_graph[crate_id].dependencies.iter().any(|dep| dep.as_name() == "aztec") +} diff --git a/aztec_macros/src/utils/constants.rs b/aztec_macros/src/utils/constants.rs new file mode 100644 index 00000000000..848cca0477d --- /dev/null +++ b/aztec_macros/src/utils/constants.rs @@ -0,0 +1,4 @@ +pub const FUNCTION_TREE_HEIGHT: u32 = 5; +pub const MAX_CONTRACT_PRIVATE_FUNCTIONS: usize = 2_usize.pow(FUNCTION_TREE_HEIGHT); +pub const SIGNATURE_PLACEHOLDER: &str = "SIGNATURE_PLACEHOLDER"; +pub const SELECTOR_PLACEHOLDER: &str = "SELECTOR_PLACEHOLDER"; diff --git a/aztec_macros/src/utils/errors.rs b/aztec_macros/src/utils/errors.rs new file mode 100644 index 00000000000..51aea3d052f --- /dev/null +++ b/aztec_macros/src/utils/errors.rs @@ -0,0 +1,112 @@ +use noirc_errors::Span; +use noirc_frontend::ast; +use noirc_frontend::macros_api::MacroError; + +use super::constants::MAX_CONTRACT_PRIVATE_FUNCTIONS; + +#[derive(Debug, Clone)] +pub enum AztecMacroError { + AztecDepNotFound, + ContractHasTooManyPrivateFunctions { span: Span }, + UnsupportedFunctionArgumentType { span: Span, typ: ast::UnresolvedTypeData }, + UnsupportedFunctionReturnType { span: Span, typ: ast::UnresolvedTypeData }, + UnsupportedStorageType { span: Option, typ: ast::UnresolvedTypeData }, + CouldNotAssignStorageSlots { secondary_message: Option }, + CouldNotImplementComputeNoteHashAndNullifier { secondary_message: Option }, + CouldNotImplementNoteInterface { span: Option, secondary_message: Option }, + MultipleStorageDefinitions { span: Option }, + CouldNotExportStorageLayout { span: Option, secondary_message: Option }, + CouldNotInjectContextGenericInStorage { secondary_message: Option }, + CouldNotExportFunctionAbi { span: Option, secondary_message: Option }, + CouldNotGenerateContractInterface { secondary_message: Option }, + EventError { span: Span, message: String }, + UnsupportedAttributes { span: Span, secondary_message: Option }, + PublicArgsDisallowed { span: Span }, +} + +impl From for MacroError { + fn from(err: AztecMacroError) -> Self { + match err { + AztecMacroError::AztecDepNotFound {} => MacroError { + primary_message: "Aztec dependency not found. Please add aztec as a dependency in your Nargo.toml. For more information go to https://docs.aztec.network/developers/debugging/aztecnr-errors#aztec-dependency-not-found-please-add-aztec-as-a-dependency-in-your-nargotoml".to_owned(), + secondary_message: None, + span: None, + }, + AztecMacroError::ContractHasTooManyPrivateFunctions { span } => MacroError { + primary_message: format!("Contract can only have a maximum of {} private functions", MAX_CONTRACT_PRIVATE_FUNCTIONS), + secondary_message: None, + span: Some(span), + }, + AztecMacroError::UnsupportedFunctionArgumentType { span, typ } => MacroError { + primary_message: format!("Provided parameter type `{typ:?}` is not supported in Aztec contract interface"), + secondary_message: None, + span: Some(span), + }, + AztecMacroError::UnsupportedFunctionReturnType { span, typ } => MacroError { + primary_message: format!("Provided return type `{typ:?}` is not supported in Aztec contract interface"), + secondary_message: None, + span: Some(span), + }, + AztecMacroError::UnsupportedStorageType { span, typ } => MacroError { + primary_message: format!("Provided storage type `{typ:?}` is not directly supported in Aztec. Please provide a custom storage implementation"), + secondary_message: None, + span, + }, + AztecMacroError::CouldNotAssignStorageSlots { secondary_message } => MacroError { + primary_message: "Could not assign storage slots, please provide a custom storage implementation".to_string(), + secondary_message, + span: None, + }, + AztecMacroError::CouldNotImplementComputeNoteHashAndNullifier { secondary_message } => MacroError { + primary_message: "Could not implement compute_note_hash_and_nullifier automatically, please provide an implementation".to_string(), + secondary_message, + span: None, + }, + AztecMacroError::CouldNotImplementNoteInterface { span, secondary_message } => MacroError { + primary_message: "Could not implement automatic methods for note, please provide an implementation of the NoteInterface trait".to_string(), + secondary_message, + span + }, + AztecMacroError::MultipleStorageDefinitions { span } => MacroError { + primary_message: "Only one struct can be tagged as #[aztec(storage)]".to_string(), + secondary_message: None, + span, + }, + AztecMacroError::CouldNotExportStorageLayout { secondary_message, span } => MacroError { + primary_message: "Could not generate and export storage layout".to_string(), + secondary_message, + span, + }, + AztecMacroError::CouldNotInjectContextGenericInStorage { secondary_message } => MacroError { + primary_message: "Could not inject context generic in storage".to_string(), + secondary_message, + span: None + }, + AztecMacroError::CouldNotExportFunctionAbi { secondary_message, span } => MacroError { + primary_message: "Could not generate and export function abi".to_string(), + secondary_message, + span, + }, + AztecMacroError::CouldNotGenerateContractInterface { secondary_message } => MacroError { + primary_message: "Could not generate contract interface".to_string(), + secondary_message, + span: None + }, + AztecMacroError::EventError { span, message } => MacroError { + primary_message: message, + secondary_message: None, + span: Some(span), + }, + AztecMacroError::UnsupportedAttributes { span, secondary_message } => MacroError { + primary_message: "Unsupported attributes in contract function".to_string(), + secondary_message, + span: Some(span), + }, + AztecMacroError::PublicArgsDisallowed { span } => MacroError { + primary_message: "Aztec functions can't have public arguments".to_string(), + secondary_message: None, + span: Some(span), + }, + } + } +} diff --git a/aztec_macros/src/utils/hir_utils.rs b/aztec_macros/src/utils/hir_utils.rs new file mode 100644 index 00000000000..d4b55e1311f --- /dev/null +++ b/aztec_macros/src/utils/hir_utils.rs @@ -0,0 +1,393 @@ +use acvm::acir::AcirField; +use iter_extended::vecmap; +use noirc_errors::Location; +use noirc_frontend::ast; +use noirc_frontend::macros_api::{HirExpression, HirLiteral}; +use noirc_frontend::node_interner::{NodeInterner, TraitImplKind}; +use noirc_frontend::{ + graph::CrateId, + hir::{ + def_map::{LocalModuleId, ModuleId}, + resolution::{path_resolver::StandardPathResolver, resolver::Resolver}, + type_check::type_check_func, + }, + macros_api::{FileId, HirContext, MacroError, ModuleDefId, StructId}, + node_interner::{FuncId, TraitId}, + Shared, StructType, Type, +}; + +use super::ast_utils::is_custom_attribute; + +pub fn collect_crate_structs(crate_id: &CrateId, context: &HirContext) -> Vec { + context + .def_map(crate_id) + .map(|def_map| { + def_map + .modules() + .iter() + .flat_map(|(_, module)| { + module.type_definitions().filter_map(move |typ| { + if let ModuleDefId::TypeId(struct_id) = typ { + Some(struct_id) + } else { + None + } + }) + }) + .collect() + }) + .unwrap_or_default() +} + +pub fn collect_crate_functions(crate_id: &CrateId, context: &HirContext) -> Vec { + context + .def_map(crate_id) + .expect("ICE: Missing crate in def_map") + .modules() + .iter() + .flat_map(|(_, module)| module.value_definitions().filter_map(|id| id.as_function())) + .collect() +} + +pub fn collect_traits(context: &HirContext) -> Vec { + let crates = context.crates(); + crates + .flat_map(|crate_id| context.def_map(&crate_id).map(|def_map| def_map.modules())) + .flatten() + .flat_map(|module| { + module.type_definitions().filter_map(|typ| { + if let ModuleDefId::TraitId(trait_id) = typ { + Some(trait_id) + } else { + None + } + }) + }) + .collect() +} + +/// Computes the aztec signature for a resolved type. +pub fn signature_of_type(typ: &Type) -> String { + match typ { + Type::Integer(ast::Signedness::Signed, bit_size) => format!("i{}", bit_size), + Type::Integer(ast::Signedness::Unsigned, bit_size) => format!("u{}", bit_size), + Type::FieldElement => "Field".to_owned(), + Type::Bool => "bool".to_owned(), + Type::Array(len, typ) => { + if let Type::Constant(len) = **len { + format!("[{};{len}]", signature_of_type(typ)) + } else { + unimplemented!("Cannot generate signature for array with length type {:?}", typ) + } + } + Type::Struct(def, args) => { + let fields = def.borrow().get_fields(args); + let fields = vecmap(fields, |(_, typ)| signature_of_type(&typ)); + format!("({})", fields.join(",")) + } + Type::Tuple(types) => { + let fields = vecmap(types, signature_of_type); + format!("({})", fields.join(",")) + } + Type::String(len_typ) => { + if let Type::Constant(len) = **len_typ { + format!("str<{len}>") + } else { + unimplemented!( + "Cannot generate signature for string with length type {:?}", + len_typ + ) + } + } + Type::MutableReference(typ) => signature_of_type(typ), + _ => unimplemented!("Cannot generate signature for type {:?}", typ), + } +} + +// Fetches the name of all structs tagged as #[aztec(note)] in a given crate, avoiding +// contract dependencies that are just there for their interfaces. +pub fn fetch_crate_notes( + context: &HirContext, + crate_id: &CrateId, +) -> Vec<(String, Shared)> { + collect_crate_structs(crate_id, context) + .iter() + .filter_map(|struct_id| { + let r#struct = context.def_interner.get_struct(*struct_id); + let attributes = context.def_interner.struct_attributes(struct_id); + if attributes.iter().any(|attr| is_custom_attribute(attr, "aztec(note)")) { + let module_id = struct_id.module_id(); + + fully_qualified_note_path(context, *struct_id).map(|path| { + let path = if path.contains("::") { + let prefix = if &module_id.krate == context.root_crate_id() { + "crate" + } else { + "dep" + }; + format!("{}::{}", prefix, path) + } else { + path + }; + (path.clone(), r#struct) + }) + } else { + None + } + }) + .collect() +} + +// Fetches the name of all structs tagged as #[aztec(note)], both in the current crate and all of its dependencies. +pub fn fetch_notes(context: &HirContext) -> Vec<(String, Shared)> { + context.crates().flat_map(|crate_id| fetch_crate_notes(context, &crate_id)).collect() +} + +pub fn get_contract_module_data( + context: &mut HirContext, + crate_id: &CrateId, +) -> Option<(String, LocalModuleId, FileId)> { + let def_map = context.def_map(crate_id).expect("ICE: Missing crate in def_map"); + // We first fetch modules in this crate which correspond to contracts, along with their file id. + let contract_module_file_ids: Vec<(String, LocalModuleId, FileId)> = def_map + .modules() + .iter() + .filter(|(_, module)| module.is_contract) + .map(|(idx, module)| { + (def_map.get_module_path(idx, module.parent), LocalModuleId(idx), module.location.file) + }) + .collect(); + + // If the current crate does not contain a contract module we simply skip it. + if contract_module_file_ids.is_empty() { + return None; + } + + Some(contract_module_file_ids[0].clone()) +} + +pub fn inject_fn( + crate_id: &CrateId, + context: &mut HirContext, + func: ast::NoirFunction, + location: Location, + module_id: LocalModuleId, + file_id: FileId, +) -> Result<(), MacroError> { + let func_id = context.def_interner.push_empty_fn(); + context.def_interner.push_function( + func_id, + &func.def, + ModuleId { krate: *crate_id, local_id: module_id }, + location, + ); + + context.def_map_mut(crate_id).unwrap().modules_mut()[module_id.0] + .declare_function(func.name_ident().clone(), ast::ItemVisibility::Public, func_id) + .map_err(|err| MacroError { + primary_message: format!("Failed to declare autogenerated {} function", func.name()), + secondary_message: Some(format!("Duplicate definition found {}", err.0)), + span: None, + })?; + + let def_maps = &mut context.def_maps; + + let path_resolver = + StandardPathResolver::new(ModuleId { local_id: module_id, krate: *crate_id }); + + let resolver = Resolver::new(&mut context.def_interner, &path_resolver, def_maps, file_id); + + let (hir_func, meta, _) = resolver.resolve_function(func, func_id); + + context.def_interner.push_fn_meta(meta, func_id); + context.def_interner.update_fn(func_id, hir_func); + + let errors = type_check_func(&mut context.def_interner, func_id); + + if !errors.is_empty() { + return Err(MacroError { + primary_message: "Failed to type check autogenerated function".to_owned(), + secondary_message: Some(errors.iter().map(|err| err.to_string()).collect::()), + span: None, + }); + } + + Ok(()) +} + +pub fn inject_global( + crate_id: &CrateId, + context: &mut HirContext, + global: ast::LetStatement, + module_id: LocalModuleId, + file_id: FileId, +) { + let name = global.pattern.name_ident().clone(); + + let global_id = context.def_interner.push_empty_global( + name.clone(), + module_id, + file_id, + global.attributes.clone(), + false, + ); + + // Add the statement to the scope so its path can be looked up later + context.def_map_mut(crate_id).unwrap().modules_mut()[module_id.0] + .declare_global(name, global_id) + .unwrap_or_else(|(name, _)| { + panic!( + "Failed to declare autogenerated {} global, likely due to a duplicate definition", + name + ) + }); + + let def_maps = &mut context.def_maps; + + let path_resolver = + StandardPathResolver::new(ModuleId { local_id: module_id, krate: *crate_id }); + + let mut resolver = Resolver::new(&mut context.def_interner, &path_resolver, def_maps, file_id); + + let hir_stmt = resolver.resolve_global_let(global, global_id); + + let statement_id = context.def_interner.get_global(global_id).let_statement; + context.def_interner.replace_statement(statement_id, hir_stmt); +} + +pub fn fully_qualified_note_path(context: &HirContext, note_id: StructId) -> Option { + let module_id = note_id.module_id(); + let child_id = module_id.local_id.0; + let def_map = + context.def_map(&module_id.krate).expect("The local crate should be analyzed already"); + + let module = context.module(module_id); + + let module_path = def_map.get_module_path_with_separator(child_id, module.parent, "::"); + + if &module_id.krate == context.root_crate_id() { + Some(module_path) + } else { + find_non_contract_dependencies_bfs(context, context.root_crate_id(), &module_id.krate) + .map(|crates| crates.join("::") + "::" + &module_path) + } +} + +fn filter_contract_modules(context: &HirContext, crate_id: &CrateId) -> bool { + if let Some(def_map) = context.def_map(crate_id) { + !def_map.modules().iter().any(|(_, module)| module.is_contract) + } else { + true + } +} + +fn find_non_contract_dependencies_bfs( + context: &HirContext, + crate_id: &CrateId, + target_crate_id: &CrateId, +) -> Option> { + context.crate_graph[crate_id] + .dependencies + .iter() + .filter(|dep| filter_contract_modules(context, &dep.crate_id)) + .find_map(|dep| { + if &dep.crate_id == target_crate_id { + Some(vec![dep.name.to_string()]) + } else { + None + } + }) + .or_else(|| { + context.crate_graph[crate_id] + .dependencies + .iter() + .filter(|dep| filter_contract_modules(context, &dep.crate_id)) + .find_map(|dep| { + if let Some(mut path) = + find_non_contract_dependencies_bfs(context, &dep.crate_id, target_crate_id) + { + path.insert(0, dep.name.to_string()); + Some(path) + } else { + None + } + }) + }) +} + +pub fn get_serialized_length( + traits: &[TraitId], + trait_name: &str, + typ: &Type, + interner: &NodeInterner, +) -> Result { + let serialized_trait_impl_kind = traits + .iter() + .find_map(|&trait_id| { + let r#trait = interner.get_trait(trait_id); + if r#trait.name.0.contents == trait_name { + interner.lookup_all_trait_implementations(typ, trait_id).into_iter().next() + } else { + None + } + }) + .ok_or(MacroError { + primary_message: format!("Type {} must implement {} trait", typ, trait_name), + secondary_message: None, + span: None, + })?; + + let serialized_trait_impl_id = match serialized_trait_impl_kind { + TraitImplKind::Normal(trait_impl_id) => Ok(trait_impl_id), + _ => Err(MacroError { + primary_message: format!("{} trait impl for {} must not be assumed", trait_name, typ), + secondary_message: None, + span: None, + }), + }?; + + let serialized_trait_impl_shared = interner.get_trait_implementation(*serialized_trait_impl_id); + let serialized_trait_impl = serialized_trait_impl_shared.borrow(); + + match serialized_trait_impl.trait_generics.first().unwrap() { + Type::Constant(value) => Ok(*value), + _ => Err(MacroError { + primary_message: format!("{} length for {} must be a constant", trait_name, typ), + secondary_message: None, + span: None, + }), + } +} + +pub fn get_global_numberic_const( + context: &HirContext, + const_name: &str, +) -> Result { + context + .def_interner + .get_all_globals() + .iter() + .find_map(|global_info| { + if global_info.ident.0.contents == const_name { + let stmt = context.def_interner.get_global_let_statement(global_info.id); + if let Some(let_stmt) = stmt { + let expression = context.def_interner.expression(&let_stmt.expression); + match expression { + HirExpression::Literal(HirLiteral::Integer(value, _)) => { + Some(value.to_u128()) + } + _ => None, + } + } else { + None + } + } else { + None + } + }) + .ok_or(MacroError { + primary_message: format!("Could not find {} global constant", const_name), + secondary_message: None, + span: None, + }) +} diff --git a/aztec_macros/src/utils/mod.rs b/aztec_macros/src/utils/mod.rs new file mode 100644 index 00000000000..c8914f83025 --- /dev/null +++ b/aztec_macros/src/utils/mod.rs @@ -0,0 +1,5 @@ +pub mod ast_utils; +pub mod checks; +pub mod constants; +pub mod errors; +pub mod hir_utils; diff --git a/bootstrap.sh b/bootstrap.sh deleted file mode 100755 index 54129c3d61a..00000000000 --- a/bootstrap.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env bash -set -eu - -cd $(dirname "$0") - -CMD=${1:-} - -if [ -n "$CMD" ]; then - if [ "$CMD" = "clean" ]; then - git clean -fdx - exit 0 - else - echo "Unknown command: $CMD" - exit 1 - fi -fi - -# Attempt to just pull artefacts from CI and exit on success. -[ -n "${USE_CACHE:-}" ] && ./bootstrap_cache.sh && exit - -./scripts/bootstrap_native.sh -./scripts/bootstrap_packages.sh diff --git a/bootstrap_cache.sh b/bootstrap_cache.sh deleted file mode 100755 index 1cec6c81d8e..00000000000 --- a/bootstrap_cache.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env bash -set -eu - -cd "$(dirname "$0")" -source ../build-system/scripts/setup_env '' '' mainframe_$USER > /dev/null - -echo -e "\033[1mRetrieving noir packages from remote cache...\033[0m" -extract_repo noir-packages /usr/src/noir/packages ./ -echo -e "\033[1mRetrieving nargo from remote cache...\033[0m" -extract_repo noir /usr/src/noir/target/release ./target/ - -remove_old_images noir-packages -remove_old_images noir diff --git a/compiler/fm/Cargo.toml b/compiler/fm/Cargo.toml index 42e4b0c25d7..f556f305c78 100644 --- a/compiler/fm/Cargo.toml +++ b/compiler/fm/Cargo.toml @@ -3,6 +3,7 @@ name = "fm" version.workspace = true authors.workspace = true edition.workspace = true +rust-version.workspace = true license.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/test_programs/execution_success/brillig_to_bits/Nargo.toml b/compiler/integration-tests/circuits/assert_lt/Nargo.toml similarity index 67% rename from test_programs/execution_success/brillig_to_bits/Nargo.toml rename to compiler/integration-tests/circuits/assert_lt/Nargo.toml index a18b769550d..f32ec18cae7 100644 --- a/test_programs/execution_success/brillig_to_bits/Nargo.toml +++ b/compiler/integration-tests/circuits/assert_lt/Nargo.toml @@ -1,5 +1,5 @@ [package] -name = "brillig_to_bits" +name = "assert_lt" type = "bin" authors = [""] [dependencies] diff --git a/compiler/integration-tests/circuits/assert_lt/src/main.nr b/compiler/integration-tests/circuits/assert_lt/src/main.nr new file mode 100644 index 00000000000..b8e255ca492 --- /dev/null +++ b/compiler/integration-tests/circuits/assert_lt/src/main.nr @@ -0,0 +1,10 @@ +use dep::std; + +fn main(x: u64, y: pub u64) -> pub u64 { + // We include a println statement to show that noirJS will ignore this and continue execution + std::println("foo"); + + + assert(x < y); + x + y +} diff --git a/compiler/integration-tests/circuits/fold_fibonacci/Nargo.toml b/compiler/integration-tests/circuits/fold_fibonacci/Nargo.toml new file mode 100644 index 00000000000..6d8214689b0 --- /dev/null +++ b/compiler/integration-tests/circuits/fold_fibonacci/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "fold_fibonacci" +type = "bin" +authors = [""] +compiler_version = ">=0.28.0" + +[dependencies] \ No newline at end of file diff --git a/compiler/integration-tests/circuits/fold_fibonacci/src/main.nr b/compiler/integration-tests/circuits/fold_fibonacci/src/main.nr new file mode 100644 index 00000000000..e150a586086 --- /dev/null +++ b/compiler/integration-tests/circuits/fold_fibonacci/src/main.nr @@ -0,0 +1,12 @@ +fn main(x: u32) { + assert(fibonacci(x) == 55); +} + +#[fold] +fn fibonacci(x: u32) -> u32 { + if x <= 1 { + x + } else { + fibonacci(x - 1) + fibonacci(x - 2) + } +} diff --git a/compiler/integration-tests/package.json b/compiler/integration-tests/package.json index 2e75ebc201e..b789f1f05ce 100644 --- a/compiler/integration-tests/package.json +++ b/compiler/integration-tests/package.json @@ -6,7 +6,7 @@ "scripts": { "build": "echo Integration Test build step", "test": "yarn test:browser && yarn test:node", - "test:node": "bash ./scripts/codegen-verifiers.sh && hardhat test test/node/**/*", + "test:node": "bash ./scripts/setup.sh && hardhat test test/node/**/*", "test:browser": "web-test-runner", "test:integration:browser": "web-test-runner test/browser/**/*.test.ts", "test:integration:browser:watch": "web-test-runner test/browser/**/*.test.ts --watch", @@ -19,13 +19,14 @@ "@nomicfoundation/hardhat-chai-matchers": "^2.0.0", "@nomicfoundation/hardhat-ethers": "^3.0.0", "@web/dev-server-esbuild": "^0.3.6", - "@web/test-runner": "^0.15.3", + "@web/dev-server-import-maps": "^0.2.0", + "@web/test-runner": "^0.18.1", "@web/test-runner-playwright": "^0.10.0", - "eslint": "^8.56.0", - "eslint-plugin-prettier": "^5.0.0", + "eslint": "^8.57.0", + "eslint-plugin-prettier": "^5.1.3", "ethers": "^6.7.1", "hardhat": "^2.17.4", - "prettier": "3.0.3", + "prettier": "3.2.5", "smol-toml": "^1.1.2", "toml": "^3.0.0", "tslog": "^4.9.2" diff --git a/compiler/integration-tests/scripts/codegen-verifiers.sh b/compiler/integration-tests/scripts/codegen-verifiers.sh old mode 100644 new mode 100755 index e377a3ee3f8..bec59eb6889 --- a/compiler/integration-tests/scripts/codegen-verifiers.sh +++ b/compiler/integration-tests/scripts/codegen-verifiers.sh @@ -1,26 +1,35 @@ #!/usr/bin/env bash +set -e + +NARGO_BACKEND_PATH=${NARGO_BACKEND_PATH:-bb} self_path=$(dirname "$(readlink -f "$0")") repo_root=$self_path/../../.. -# Run codegen-verifier for 1_mul +# We want to move all the contracts to the root of compiler/integration-tests +contracts_dir=$self_path/../contracts +rm -rf $contracts_dir +mkdir $contracts_dir + +KEYS=$(mktemp -d) + +# Codegen verifier contract for 1_mul mul_dir=$repo_root/test_programs/execution_success/1_mul -nargo --program-dir $mul_dir codegen-verifier +nargo --program-dir $mul_dir compile +$NARGO_BACKEND_PATH write_vk -b $mul_dir/target/1_mul.json -o $KEYS/1_mul +$NARGO_BACKEND_PATH contract -k $KEYS/1_mul -o $contracts_dir/1_mul.sol -# Run codegen-verifier for assert_statement +# Codegen verifier contract for assert_statement assert_statement_dir=$repo_root/test_programs/execution_success/assert_statement -nargo --program-dir $assert_statement_dir codegen-verifier +nargo --program-dir $assert_statement_dir compile +$NARGO_BACKEND_PATH write_vk -b $assert_statement_dir/target/assert_statement.json -o $KEYS/assert_statement +$NARGO_BACKEND_PATH contract -k $KEYS/assert_statement -o $contracts_dir/assert_statement.sol -# Run codegen-verifier for recursion +# Codegen verifier contract for recursion recursion_dir=$repo_root/compiler/integration-tests/circuits/recursion -nargo --program-dir $recursion_dir codegen-verifier - -# Copy compiled contracts from the root of compiler/integration-tests -contracts_dir=$self_path/../contracts -rm -rf $contracts_dir -mkdir $contracts_dir +nargo --program-dir $recursion_dir compile +$NARGO_BACKEND_PATH write_vk -b $recursion_dir/target/recursion.json -o $KEYS/recursion +$NARGO_BACKEND_PATH contract -k $KEYS/recursion ./ -o $contracts_dir/recursion.sol -cp $mul_dir/contract/1_mul/plonk_vk.sol $contracts_dir/1_mul.sol -cp $assert_statement_dir/contract/assert_statement/plonk_vk.sol $contracts_dir/assert_statement.sol -cp $recursion_dir/contract/recursion/plonk_vk.sol $contracts_dir/recursion.sol +rm -rf $KEYS \ No newline at end of file diff --git a/compiler/integration-tests/scripts/compile-programs.sh b/compiler/integration-tests/scripts/compile-programs.sh new file mode 100755 index 00000000000..a7071acc401 --- /dev/null +++ b/compiler/integration-tests/scripts/compile-programs.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +set -e + +self_path=$(dirname "$(readlink -f "$0")") + +package_root=$self_path/../ + +assert_lt_dir=$package_root/circuits/assert_lt/ +nargo --program-dir $assert_lt_dir compile + +fold_fibonacci_dir=$package_root/circuits/fold_fibonacci/ +nargo --program-dir $fold_fibonacci_dir compile diff --git a/compiler/integration-tests/scripts/setup.sh b/compiler/integration-tests/scripts/setup.sh new file mode 100755 index 00000000000..37db38474c0 --- /dev/null +++ b/compiler/integration-tests/scripts/setup.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +set -e + +self_path=$(dirname "$(readlink -f "$0")") + + +$self_path/compile-programs.sh +$self_path/codegen-verifiers.sh \ No newline at end of file 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 dba51895bb8..f18ceb85276 100644 --- a/compiler/integration-tests/test/browser/compile_prove_verify.test.ts +++ b/compiler/integration-tests/test/browser/compile_prove_verify.test.ts @@ -51,19 +51,20 @@ test_cases.forEach((testInfo) => { throw e; } - const backend = new BarretenbergBackend(noir_program); - const program = new Noir(noir_program, backend); - const prover_toml = await new Response(await getFile(`${base_relative_path}/${test_case}/Prover.toml`)).text(); const inputs: InputMap = TOML.parse(prover_toml) as InputMap; // JS Proving - const proofWithPublicInputs = await program.generateProof(inputs); + const program = new Noir(noir_program); + const { witness } = await program.execute(inputs); + + const backend = new BarretenbergBackend(noir_program); + const proof = await backend.generateProof(witness); // JS verification - const verified = await program.verifyProof(proofWithPublicInputs); + const verified = await backend.verifyProof(proof); expect(verified, 'Proof fails verification in JS').to.be.true; }); diff --git a/compiler/integration-tests/test/browser/recursion.test.ts b/compiler/integration-tests/test/browser/recursion.test.ts index a8927aa6a75..abbee7b96ad 100644 --- a/compiler/integration-tests/test/browser/recursion.test.ts +++ b/compiler/integration-tests/test/browser/recursion.test.ts @@ -40,7 +40,8 @@ describe('It compiles noir program code, receiving circuit bytes and abi object. circuit_main_toml = await new Response(await getFile(`${base_relative_path}/${circuit_main}/Prover.toml`)).text(); }); - it('Should generate valid inner proof for correct input, then verify proof within a proof', async () => { + // TODO(https://github.com/noir-lang/noir/issues/5106): Reinstate this test. + it.skip('Should generate valid inner proof for correct input, then verify proof within a proof', async () => { const main_program = await getCircuit(`${base_relative_path}/${circuit_main}`); const main_inputs: InputMap = TOML.parse(circuit_main_toml) as InputMap; diff --git a/compiler/integration-tests/test/mocks/os.js b/compiler/integration-tests/test/mocks/os.js new file mode 100644 index 00000000000..32333568316 --- /dev/null +++ b/compiler/integration-tests/test/mocks/os.js @@ -0,0 +1 @@ +export const os = { cpus: () => new Array(4) }; diff --git a/compiler/integration-tests/test/node/onchain_recursive_verification.test.ts b/compiler/integration-tests/test/node/onchain_recursive_verification.test.ts index 6147f770f16..f4647c478f1 100644 --- a/compiler/integration-tests/test/node/onchain_recursive_verification.test.ts +++ b/compiler/integration-tests/test/node/onchain_recursive_verification.test.ts @@ -11,7 +11,8 @@ import { Field, InputMap } from '@noir-lang/noirc_abi'; import { compile, createFileManager } from '@noir-lang/noir_wasm'; -it(`smart contract can verify a recursive proof`, async () => { +// TODO(https://github.com/AztecProtocol/aztec-packages/issues/6672): Reinstate this test. +it.skip(`smart contract can verify a recursive proof`, async () => { const basePath = resolve(join(__dirname, '../../../../')); const fm = createFileManager(basePath); const innerCompilationResult = await compile( @@ -55,8 +56,7 @@ it(`smart contract can verify a recursive proof`, async () => { // Final proof - const recursion_backend = new BarretenbergBackend(recursionProgram); - const recursion = new Noir(recursionProgram, recursion_backend); + const recursion = new Noir(recursionProgram); const recursion_inputs: InputMap = { verification_key: vkAsFields, @@ -65,8 +65,11 @@ it(`smart contract can verify a recursive proof`, async () => { key_hash: vkHash, }; - const recursion_proof = await recursion.generateProof(recursion_inputs); - expect(await recursion.verifyProof(recursion_proof)).to.be.true; + const { witness: recursionWitness } = await recursion.execute(recursion_inputs); + + const recursion_backend = new BarretenbergBackend(recursionProgram); + const recursion_proof = await recursion_backend.generateProof(recursionWitness); + expect(await recursion_backend.verifyProof(recursion_proof)).to.be.true; // Smart contract verification diff --git a/tooling/noir_js/test/node/e2e.test.ts b/compiler/integration-tests/test/node/prove_and_verify.test.ts similarity index 70% rename from tooling/noir_js/test/node/e2e.test.ts rename to compiler/integration-tests/test/node/prove_and_verify.test.ts index 8921314e8ea..1cfe36f31e9 100644 --- a/tooling/noir_js/test/node/e2e.test.ts +++ b/compiler/integration-tests/test/node/prove_and_verify.test.ts @@ -1,10 +1,12 @@ import { expect } from 'chai'; -import assert_lt_json from '../noir_compiled_examples/assert_lt/target/assert_lt.json' assert { type: 'json' }; +import assert_lt_json from '../../circuits/assert_lt/target/assert_lt.json' assert { type: 'json' }; +import fold_fibonacci_json from '../../circuits/fold_fibonacci/target/fold_fibonacci.json' assert { type: 'json' }; import { Noir } from '@noir-lang/noir_js'; -import { BarretenbergBackend as Backend } from '@noir-lang/backend_barretenberg'; +import { BarretenbergBackend as Backend, BarretenbergVerifier as Verifier } from '@noir-lang/backend_barretenberg'; import { CompiledCircuit } from '@noir-lang/types'; const assert_lt_program = assert_lt_json as CompiledCircuit; +const fold_fibonacci_program = fold_fibonacci_json as CompiledCircuit; it('end-to-end proof creation and verification (outer)', async () => { // Noir.Js part @@ -28,22 +30,26 @@ it('end-to-end proof creation and verification (outer)', async () => { expect(isValid).to.be.true; }); -it('end-to-end proof creation and verification (outer) -- Program API', async () => { +it('end-to-end proof creation and verification (outer) -- Verifier API', async () => { // Noir.Js part const inputs = { x: '2', y: '3', }; - // Initialize backend - const backend = new Backend(assert_lt_program); - // Initialize program - const program = new Noir(assert_lt_program, backend); + // Execute program + const program = new Noir(assert_lt_program); + const { witness } = await program.execute(inputs); + // Generate proof - const proof = await program.generateProof(inputs); + const backend = new Backend(assert_lt_program); + const proof = await backend.generateProof(witness); + + const verificationKey = await backend.getVerificationKey(); // Proof verification - const isValid = await program.verifyProof(proof); + const verifier = new Verifier(); + const isValid = await verifier.verifyProof(proof, verificationKey); expect(isValid).to.be.true; }); @@ -127,3 +133,24 @@ it('[BUG] -- bb.js null function or function signature mismatch (outer-inner) ', const isValidInner = await prover.verifyProof(_proofInner); expect(isValidInner).to.be.true; }); + +it('end-to-end proof creation and verification for multiple ACIR circuits (inner)', async () => { + // Noir.Js part + const inputs = { + x: '10', + }; + + const program = new Noir(fold_fibonacci_program); + + const { witness } = await program.execute(inputs); + + // bb.js part + // + // Proof creation + const backend = new Backend(fold_fibonacci_program); + const proof = await backend.generateProof(witness); + + // Proof verification + const isValid = await backend.verifyProof(proof); + expect(isValid).to.be.true; +}); diff --git a/compiler/integration-tests/test/node/smart_contract_verifier.test.ts b/compiler/integration-tests/test/node/smart_contract_verifier.test.ts index 79a0520da32..e109cbcab6a 100644 --- a/compiler/integration-tests/test/node/smart_contract_verifier.test.ts +++ b/compiler/integration-tests/test/node/smart_contract_verifier.test.ts @@ -38,19 +38,20 @@ test_cases.forEach((testInfo) => { const noir_program = compileResult.program; - const backend = new BarretenbergBackend(noir_program); - const program = new Noir(noir_program, backend); + const program = new Noir(noir_program); // JS Proving const prover_toml = readFileSync(resolve(`${base_relative_path}/${test_case}/Prover.toml`)).toString(); const inputs = toml.parse(prover_toml); + const { witness } = await program.execute(inputs); - const proofData = await program.generateProof(inputs); + const backend = new BarretenbergBackend(noir_program); + const proofData = await backend.generateProof(witness); // JS verification - const verified = await program.verifyProof(proofData); + const verified = await backend.verifyProof(proofData); expect(verified, 'Proof fails verification in JS').to.be.true; // Smart contract verification diff --git a/compiler/integration-tests/web-test-runner.config.mjs b/compiler/integration-tests/web-test-runner.config.mjs index 665ea262f99..4dfc96dd0a6 100644 --- a/compiler/integration-tests/web-test-runner.config.mjs +++ b/compiler/integration-tests/web-test-runner.config.mjs @@ -2,7 +2,8 @@ import { defaultReporter } from '@web/test-runner'; import { summaryReporter } from '@web/test-runner'; import { fileURLToPath } from 'url'; import { esbuildPlugin } from '@web/dev-server-esbuild'; -import { playwrightLauncher } from "@web/test-runner-playwright"; +import { playwrightLauncher } from '@web/test-runner-playwright'; +import { importMapsPlugin } from '@web/dev-server-import-maps'; let reporter = summaryReporter(); const debugPlugins = []; @@ -21,7 +22,7 @@ if (process.env.CI !== 'true' || process.env.RUNNER_DEBUG === '1') { export default { browsers: [ - playwrightLauncher({ product: "chromium" }), + playwrightLauncher({ product: 'chromium' }), // playwrightLauncher({ product: "webkit" }), // playwrightLauncher({ product: "firefox" }), ], @@ -29,6 +30,16 @@ export default { esbuildPlugin({ ts: true, }), + importMapsPlugin({ + inject: { + importMap: { + imports: { + // mock os module + os: '/test/mocks/os.js', + }, + }, + }, + }), ...debugPlugins, ], files: ['test/browser/**/*.test.ts'], diff --git a/compiler/utils/arena/Cargo.toml b/compiler/noirc_arena/Cargo.toml similarity index 68% rename from compiler/utils/arena/Cargo.toml rename to compiler/noirc_arena/Cargo.toml index 41c6ebc9a8b..b94f997b7b9 100644 --- a/compiler/utils/arena/Cargo.toml +++ b/compiler/noirc_arena/Cargo.toml @@ -1,6 +1,7 @@ [package] -name = "arena" +name = "noirc_arena" version.workspace = true authors.workspace = true edition.workspace = true +rust-version.workspace = true license.workspace = true diff --git a/compiler/utils/arena/src/lib.rs b/compiler/noirc_arena/src/lib.rs similarity index 94% rename from compiler/utils/arena/src/lib.rs rename to compiler/noirc_arena/src/lib.rs index 2d117304e16..9a25299d6c8 100644 --- a/compiler/utils/arena/src/lib.rs +++ b/compiler/noirc_arena/src/lib.rs @@ -3,6 +3,8 @@ #![warn(unreachable_pub)] #![warn(clippy::semicolon_if_nothing_returned)] +use std::fmt; + #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Hash)] pub struct Index(usize); @@ -25,6 +27,12 @@ impl Index { } } +impl fmt::Display for Index { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.0.fmt(f) + } +} + #[derive(Clone, Debug)] pub struct Arena { pub vec: Vec, diff --git a/compiler/noirc_driver/Cargo.toml b/compiler/noirc_driver/Cargo.toml index 681976735f3..a9949f5093a 100644 --- a/compiler/noirc_driver/Cargo.toml +++ b/compiler/noirc_driver/Cargo.toml @@ -3,6 +3,7 @@ name = "noirc_driver" version.workspace = true authors.workspace = true edition.workspace = true +rust-version.workspace = true license.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -23,7 +24,5 @@ serde.workspace = true fxhash.workspace = true rust-embed.workspace = true tracing.workspace = true -thiserror.workspace = true aztec_macros = { path = "../../aztec_macros" } -noirc_macros = { path = "../../noirc_macros" } diff --git a/compiler/noirc_driver/build.rs b/compiler/noirc_driver/build.rs index 73a56142075..2ed109398a4 100644 --- a/compiler/noirc_driver/build.rs +++ b/compiler/noirc_driver/build.rs @@ -2,8 +2,7 @@ const GIT_COMMIT: &&str = &"GIT_COMMIT"; use std::path::Path; fn main() { - // Only use build_data if the environment variable isn't set - // The environment variable is always set when working via Nix + // Only use build_data if the environment variable isn't set. if std::env::var(GIT_COMMIT).is_err() { build_data::set_GIT_COMMIT(); build_data::set_GIT_DIRTY(); diff --git a/compiler/noirc_driver/src/abi_gen.rs b/compiler/noirc_driver/src/abi_gen.rs index 7fafa719186..609c88b92c2 100644 --- a/compiler/noirc_driver/src/abi_gen.rs +++ b/compiler/noirc_driver/src/abi_gen.rs @@ -1,13 +1,15 @@ use std::collections::BTreeMap; +use acvm::acir::circuit::ErrorSelector; use acvm::acir::native_types::Witness; use iter_extended::{btree_map, vecmap}; -use noirc_abi::{Abi, AbiParameter, AbiReturnType, AbiType}; +use noirc_abi::{Abi, AbiErrorType, AbiParameter, AbiReturnType, AbiType, AbiValue}; +use noirc_frontend::ast::Visibility; use noirc_frontend::{ hir::Context, - hir_def::{function::Param, stmt::HirPattern}, + hir_def::{expr::HirArrayLiteral, function::Param, stmt::HirPattern, types::Type}, + macros_api::{HirExpression, HirLiteral}, node_interner::{FuncId, NodeInterner}, - Visibility, }; use std::ops::Range; @@ -19,12 +21,17 @@ pub(super) fn gen_abi( input_witnesses: Vec, return_witnesses: Vec, return_visibility: Visibility, + error_types: BTreeMap, ) -> Abi { let (parameters, return_type) = compute_function_abi(context, func_id); let param_witnesses = param_witnesses_from_abi_param(¶meters, input_witnesses); let return_type = return_type .map(|typ| AbiReturnType { abi_type: typ, visibility: return_visibility.into() }); - Abi { parameters, return_type, param_witnesses, return_witnesses } + let error_types = error_types + .into_iter() + .map(|(selector, typ)| (selector, AbiErrorType::from_type(context, &typ))) + .collect(); + Abi { parameters, return_type, param_witnesses, return_witnesses, error_types } } pub(super) fn compute_function_abi( @@ -109,6 +116,60 @@ fn collapse_ranges(witnesses: &[Witness]) -> Vec> { wit } +pub(super) fn value_from_hir_expression(context: &Context, expression: HirExpression) -> AbiValue { + match expression { + HirExpression::Tuple(expr_ids) => { + let fields = expr_ids + .iter() + .map(|expr_id| { + value_from_hir_expression(context, context.def_interner.expression(expr_id)) + }) + .collect(); + AbiValue::Tuple { fields } + } + HirExpression::Constructor(constructor) => { + let fields = constructor + .fields + .iter() + .map(|(ident, expr_id)| { + ( + ident.0.contents.to_string(), + value_from_hir_expression( + context, + context.def_interner.expression(expr_id), + ), + ) + }) + .collect(); + AbiValue::Struct { fields } + } + HirExpression::Literal(literal) => match literal { + HirLiteral::Array(hir_array) => match hir_array { + HirArrayLiteral::Standard(expr_ids) => { + let value = expr_ids + .iter() + .map(|expr_id| { + value_from_hir_expression( + context, + context.def_interner.expression(expr_id), + ) + }) + .collect(); + AbiValue::Array { value } + } + _ => unreachable!("Repeated arrays cannot be used in the abi"), + }, + HirLiteral::Bool(value) => AbiValue::Boolean { value }, + HirLiteral::Str(value) => AbiValue::String { value }, + HirLiteral::Integer(field, sign) => { + AbiValue::Integer { value: field.to_string(), sign } + } + _ => unreachable!("Literal cannot be used in the abi"), + }, + _ => unreachable!("Type cannot be used in the abi {:?}", expression), + } +} + #[cfg(test)] mod test { use std::ops::Range; diff --git a/compiler/noirc_driver/src/contract.rs b/compiler/noirc_driver/src/contract.rs index 5f4b66e7dd2..11fc1bb637a 100644 --- a/compiler/noirc_driver/src/contract.rs +++ b/compiler/noirc_driver/src/contract.rs @@ -1,29 +1,18 @@ use serde::{Deserialize, Serialize}; -use std::collections::BTreeMap; +use std::collections::{BTreeMap, HashMap}; -use acvm::acir::circuit::Circuit; +use acvm::{acir::circuit::Program, FieldElement}; use fm::FileId; -use noirc_abi::{Abi, ContractEvent}; +use noirc_abi::{Abi, AbiType, AbiValue}; use noirc_errors::debug_info::DebugInfo; use noirc_evaluator::errors::SsaReport; use super::debug::DebugFile; -/// Describes the types of smart contract functions that are allowed. -/// Unlike the similar enum in noirc_frontend, 'open' and 'unconstrained' -/// are mutually exclusive here. In the case a function is both, 'unconstrained' -/// takes precedence. -#[derive(Serialize, Deserialize, Debug, Copy, Clone, PartialEq, Eq)] -pub enum ContractFunctionType { - /// This function will be executed in a private - /// context. - Secret, - /// This function will be executed in a public - /// context. - Open, - /// This function cannot constrain any values and can use nondeterministic features - /// like arrays of a dynamic size. - Unconstrained, +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct CompiledContractOutputs { + pub structs: HashMap>, + pub globals: HashMap>, } #[derive(Clone, Debug, Serialize, Deserialize)] @@ -36,10 +25,7 @@ pub struct CompiledContract { /// stored in this `Vector`. pub functions: Vec, - /// All the events defined inside the contract scope. - /// An event is a struct value that can be emitted via oracles - /// by any contract function during execution. - pub events: Vec, + pub outputs: CompiledContractOutputs, pub file_map: BTreeMap, pub warnings: Vec, @@ -55,27 +41,20 @@ pub struct CompiledContract { pub struct ContractFunction { pub name: String, - pub function_type: ContractFunctionType, + pub is_unconstrained: bool, - pub is_internal: bool, + pub custom_attributes: Vec, pub abi: Abi, #[serde( - serialize_with = "Circuit::serialize_circuit_base64", - deserialize_with = "Circuit::deserialize_circuit_base64" + serialize_with = "Program::serialize_program_base64", + deserialize_with = "Program::deserialize_program_base64" )] - pub bytecode: Circuit, + pub bytecode: Program, - pub debug: DebugInfo, -} + pub debug: Vec, -impl ContractFunctionType { - pub(super) fn new(kind: noirc_frontend::ContractFunctionType, is_unconstrained: bool) -> Self { - match (kind, is_unconstrained) { - (_, true) => Self::Unconstrained, - (noirc_frontend::ContractFunctionType::Secret, false) => Self::Secret, - (noirc_frontend::ContractFunctionType::Open, false) => Self::Open, - } - } + /// Names of the functions in the program. These are used for more informative debugging and benchmarking. + pub names: Vec, } diff --git a/compiler/noirc_driver/src/lib.rs b/compiler/noirc_driver/src/lib.rs index 11f53cdb749..848d9987ca3 100644 --- a/compiler/noirc_driver/src/lib.rs +++ b/compiler/noirc_driver/src/lib.rs @@ -3,23 +3,27 @@ #![warn(unreachable_pub)] #![warn(clippy::semicolon_if_nothing_returned)] +use abi_gen::value_from_hir_expression; use acvm::acir::circuit::ExpressionWidth; use clap::Args; use fm::{FileId, FileManager}; use iter_extended::vecmap; -use noirc_abi::{AbiParameter, AbiType, ContractEvent}; +use noirc_abi::{AbiParameter, AbiType, AbiValue}; use noirc_errors::{CustomDiagnostic, FileDiagnostic}; -use noirc_evaluator::create_circuit; +use noirc_evaluator::create_program; use noirc_evaluator::errors::RuntimeError; +use noirc_evaluator::ssa::SsaProgramArtifact; use noirc_frontend::debug::build_debug_crate_file; use noirc_frontend::graph::{CrateId, CrateName}; use noirc_frontend::hir::def_map::{Contract, CrateDefMap}; use noirc_frontend::hir::Context; use noirc_frontend::macros_api::MacroProcessor; -use noirc_frontend::monomorphization::{monomorphize, monomorphize_debug, MonomorphizationError}; +use noirc_frontend::monomorphization::{ + errors::MonomorphizationError, monomorphize, monomorphize_debug, +}; use noirc_frontend::node_interner::FuncId; +use noirc_frontend::token::SecondaryAttribute; use std::path::Path; -use thiserror::Error; use tracing::info; mod abi_gen; @@ -30,7 +34,7 @@ mod stdlib; use debug::filter_relevant_files; -pub use contract::{CompiledContract, ContractFunction, ContractFunctionType}; +pub use contract::{CompiledContract, CompiledContractOutputs, ContractFunction}; pub use debug::DebugFile; pub use program::CompiledProgram; @@ -49,8 +53,8 @@ pub const NOIR_ARTIFACT_VERSION_STRING: &str = #[derive(Args, Clone, Debug, Default)] pub struct CompileOptions { /// Override the expression width requested by the backend. - #[arg(long, value_parser = parse_expression_width)] - pub expression_width: Option, + #[arg(long, value_parser = parse_expression_width, default_value = "4")] + pub expression_width: ExpressionWidth, /// Force a full recompilation. #[arg(long = "force")] @@ -67,6 +71,10 @@ pub struct CompileOptions { #[arg(long)] pub print_acir: bool, + /// Pretty print benchmark times of each code generation pass + #[arg(long, hide = true)] + pub benchmark_codegen: bool, + /// Treat all warnings as errors #[arg(long, conflicts_with = "silence_warnings")] pub deny_warnings: bool, @@ -75,10 +83,6 @@ pub struct CompileOptions { #[arg(long, conflicts_with = "deny_warnings")] pub silence_warnings: bool, - /// Output ACIR gzipped bytecode instead of the JSON artefact - #[arg(long, hide = true)] - pub only_acir: bool, - /// Disables the builtin Aztec macros being used in the compiler #[arg(long, hide = true)] pub disable_macros: bool, @@ -94,6 +98,10 @@ pub struct CompileOptions { /// Force Brillig output (for step debugging) #[arg(long, hide = true)] pub force_brillig: bool, + + /// Enable the experimental elaborator pass + #[arg(long, hide = true)] + pub use_elaborator: bool, } fn parse_expression_width(input: &str) -> Result { @@ -108,13 +116,22 @@ fn parse_expression_width(input: &str) -> Result for CompileError { + fn from(error: MonomorphizationError) -> Self { + Self::MonomorphizationError(error) + } +} - #[error(transparent)] - RuntimeError(#[from] RuntimeError), +impl From for CompileError { + fn from(error: RuntimeError) -> Self { + Self::RuntimeError(error) + } } impl From for FileDiagnostic { @@ -236,20 +253,15 @@ pub fn check_crate( crate_id: CrateId, deny_warnings: bool, disable_macros: bool, + use_elaborator: bool, ) -> CompilationResult<()> { - let macros: Vec<&dyn MacroProcessor> = if disable_macros { - vec![&noirc_macros::AssertMessageMacro as &dyn MacroProcessor] - } else { - vec![ - &aztec_macros::AztecMacro as &dyn MacroProcessor, - &noirc_macros::AssertMessageMacro as &dyn MacroProcessor, - ] - }; + let macros: &[&dyn MacroProcessor] = + if disable_macros { &[] } else { &[&aztec_macros::AztecMacro as &dyn MacroProcessor] }; let mut errors = vec![]; - let diagnostics = CrateDefMap::collect_defs(crate_id, context, macros); + let diagnostics = CrateDefMap::collect_defs(crate_id, context, use_elaborator, macros); errors.extend(diagnostics.into_iter().map(|(error, file_id)| { - let diagnostic: CustomDiagnostic = error.into(); + let diagnostic = CustomDiagnostic::from(&error); diagnostic.in_file(file_id) })); @@ -279,8 +291,13 @@ pub fn compile_main( options: &CompileOptions, cached_program: Option, ) -> CompilationResult { - let (_, mut warnings) = - check_crate(context, crate_id, options.deny_warnings, options.disable_macros)?; + let (_, mut warnings) = check_crate( + context, + crate_id, + options.deny_warnings, + options.disable_macros, + options.use_elaborator, + )?; let main = context.get_main_function(&crate_id).ok_or_else(|| { // TODO(#2155): This error might be a better to exist in Nargo @@ -303,7 +320,7 @@ pub fn compile_main( if options.print_acir { println!("Compiled ACIR for main (unoptimized):"); - println!("{}", compiled_program.circuit); + println!("{}", compiled_program.program); } Ok((compiled_program, warnings)) @@ -315,8 +332,13 @@ pub fn compile_contract( crate_id: CrateId, options: &CompileOptions, ) -> CompilationResult { - let (_, warnings) = - check_crate(context, crate_id, options.deny_warnings, options.disable_macros)?; + let (_, warnings) = check_crate( + context, + crate_id, + options.deny_warnings, + options.disable_macros, + options.use_elaborator, + )?; // TODO: We probably want to error if contracts is empty let contracts = context.get_all_contracts(&crate_id); @@ -404,38 +426,78 @@ fn compile_contract_inner( }; warnings.extend(function.warnings); let modifiers = context.def_interner.function_modifiers(&function_id); - let func_type = modifiers - .contract_function_type - .expect("Expected contract function to have a contract visibility"); - let function_type = ContractFunctionType::new(func_type, modifiers.is_unconstrained); + let custom_attributes = modifiers + .attributes + .secondary + .iter() + .filter_map( + |attr| if let SecondaryAttribute::Custom(tag) = attr { Some(tag) } else { None }, + ) + .cloned() + .collect(); functions.push(ContractFunction { name, - function_type, - is_internal: modifiers.is_internal.unwrap_or(false), + custom_attributes, abi: function.abi, - bytecode: function.circuit, + bytecode: function.program, debug: function.debug, + is_unconstrained: modifiers.is_unconstrained, + names: function.names, }); } if errors.is_empty() { - let debug_infos: Vec<_> = functions.iter().map(|function| function.debug.clone()).collect(); + let debug_infos: Vec<_> = + functions.iter().flat_map(|function| function.debug.clone()).collect(); let file_map = filter_relevant_files(&debug_infos, &context.file_manager); + let out_structs = contract + .outputs + .structs + .into_iter() + .map(|(tag, structs)| { + let structs = structs + .into_iter() + .map(|struct_id| { + let typ = context.def_interner.get_struct(struct_id); + let typ = typ.borrow(); + let fields = vecmap(typ.get_fields(&[]), |(name, typ)| { + (name, AbiType::from_type(context, &typ)) + }); + let path = + context.fully_qualified_struct_path(context.root_crate_id(), typ.id); + AbiType::Struct { path, fields } + }) + .collect(); + (tag.to_string(), structs) + }) + .collect(); + + let out_globals = contract + .outputs + .globals + .iter() + .map(|(tag, globals)| { + let globals: Vec = globals + .iter() + .map(|global_id| { + let let_statement = + context.def_interner.get_global_let_statement(*global_id).unwrap(); + let hir_expression = + context.def_interner.expression(&let_statement.expression); + value_from_hir_expression(context, hir_expression) + }) + .collect(); + (tag.to_string(), globals) + }) + .collect(); + Ok(CompiledContract { name: contract.name, - events: contract - .events - .iter() - .map(|event_id| { - let typ = context.def_interner.get_struct(*event_id); - let typ = typ.borrow(); - ContractEvent::from_struct_type(context, &typ) - }) - .collect(), functions, + outputs: CompiledContractOutputs { structs: out_structs, globals: out_globals }, file_map, noir_version: NOIR_ARTIFACT_VERSION_STRING.to_string(), warnings, @@ -478,20 +540,41 @@ pub fn compile_no_check( return Ok(cached_program.expect("cache must exist for hashes to match")); } let visibility = program.return_visibility; - let (circuit, debug, input_witnesses, return_witnesses, warnings) = - create_circuit(program, options.show_ssa, options.show_brillig, options.force_brillig)?; - let abi = - abi_gen::gen_abi(context, &main_function, input_witnesses, return_witnesses, visibility); - let file_map = filter_relevant_files(&[debug.clone()], &context.file_manager); + let SsaProgramArtifact { + program, + debug, + warnings, + main_input_witnesses, + main_return_witnesses, + names, + error_types, + } = create_program( + program, + options.show_ssa, + options.show_brillig, + options.force_brillig, + options.benchmark_codegen, + )?; + + let abi = abi_gen::gen_abi( + context, + &main_function, + main_input_witnesses, + main_return_witnesses, + visibility, + error_types, + ); + let file_map = filter_relevant_files(&debug, &context.file_manager); Ok(CompiledProgram { hash, - circuit, + program, debug, abi, file_map, noir_version: NOIR_ARTIFACT_VERSION_STRING.to_string(), warnings, + names, }) } diff --git a/compiler/noirc_driver/src/program.rs b/compiler/noirc_driver/src/program.rs index 8d509d3bf68..8e02de0b8b3 100644 --- a/compiler/noirc_driver/src/program.rs +++ b/compiler/noirc_driver/src/program.rs @@ -1,6 +1,6 @@ use std::collections::BTreeMap; -use acvm::acir::circuit::Circuit; +use acvm::{acir::circuit::Program, FieldElement}; use fm::FileId; use noirc_errors::debug_info::DebugInfo; @@ -19,12 +19,14 @@ pub struct CompiledProgram { pub hash: u64, #[serde( - serialize_with = "Circuit::serialize_circuit_base64", - deserialize_with = "Circuit::deserialize_circuit_base64" + serialize_with = "Program::serialize_program_base64", + deserialize_with = "Program::deserialize_program_base64" )] - pub circuit: Circuit, + pub program: Program, pub abi: noirc_abi::Abi, - pub debug: DebugInfo, + pub debug: Vec, pub file_map: BTreeMap, pub warnings: Vec, + /// Names of the functions in the program. These are used for more informative debugging and benchmarking. + pub names: Vec, } diff --git a/compiler/noirc_driver/tests/stdlib_warnings.rs b/compiler/noirc_driver/tests/stdlib_warnings.rs index 6f437621123..327c8daad06 100644 --- a/compiler/noirc_driver/tests/stdlib_warnings.rs +++ b/compiler/noirc_driver/tests/stdlib_warnings.rs @@ -24,7 +24,8 @@ fn stdlib_does_not_produce_constant_warnings() -> Result<(), ErrorsAndWarnings> let mut context = Context::new(file_manager, parsed_files); let root_crate_id = prepare_crate(&mut context, file_name); - let ((), warnings) = noirc_driver::check_crate(&mut context, root_crate_id, false, false)?; + let ((), warnings) = + noirc_driver::check_crate(&mut context, root_crate_id, false, false, false)?; assert_eq!(warnings, Vec::new(), "stdlib is producing warnings"); diff --git a/compiler/noirc_errors/Cargo.toml b/compiler/noirc_errors/Cargo.toml index da18399971e..41b1cd0ff58 100644 --- a/compiler/noirc_errors/Cargo.toml +++ b/compiler/noirc_errors/Cargo.toml @@ -3,6 +3,7 @@ name = "noirc_errors" version.workspace = true authors.workspace = true edition.workspace = true +rust-version.workspace = true license.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -19,4 +20,4 @@ serde_with = "3.2.0" tracing.workspace = true flate2.workspace = true serde_json.workspace = true -base64.workspace = true \ No newline at end of file +base64.workspace = true diff --git a/compiler/noirc_errors/src/debug_info.rs b/compiler/noirc_errors/src/debug_info.rs index 67ec851d46d..54e2521e413 100644 --- a/compiler/noirc_errors/src/debug_info.rs +++ b/compiler/noirc_errors/src/debug_info.rs @@ -24,6 +24,9 @@ use serde::{ #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, Deserialize, Serialize)] pub struct DebugVarId(pub u32); +#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, Deserialize, Serialize)] +pub struct DebugFnId(pub u32); + #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, Deserialize, Serialize)] pub struct DebugTypeId(pub u32); @@ -33,9 +36,59 @@ pub struct DebugVariable { pub debug_type_id: DebugTypeId, } +#[derive(Debug, Clone, Hash, Deserialize, Serialize)] +pub struct DebugFunction { + pub name: String, + pub arg_names: Vec, +} + pub type DebugVariables = BTreeMap; +pub type DebugFunctions = BTreeMap; pub type DebugTypes = BTreeMap; +#[derive(Default, Debug, Clone, Deserialize, Serialize)] +pub struct ProgramDebugInfo { + pub debug_infos: Vec, +} + +impl ProgramDebugInfo { + pub fn serialize_compressed_base64_json( + debug_info: &ProgramDebugInfo, + s: S, + ) -> Result + where + S: Serializer, + { + let json_str = serde_json::to_string(debug_info).map_err(S::Error::custom)?; + + let mut encoder = DeflateEncoder::new(Vec::new(), Compression::default()); + encoder.write_all(json_str.as_bytes()).map_err(S::Error::custom)?; + let compressed_data = encoder.finish().map_err(S::Error::custom)?; + + let encoded_b64 = base64::prelude::BASE64_STANDARD.encode(compressed_data); + s.serialize_str(&encoded_b64) + } + + pub fn deserialize_compressed_base64_json<'de, D>( + deserializer: D, + ) -> Result + where + D: Deserializer<'de>, + { + let encoded_b64: String = Deserialize::deserialize(deserializer)?; + + let compressed_data = + base64::prelude::BASE64_STANDARD.decode(encoded_b64).map_err(D::Error::custom)?; + + let mut decoder = DeflateDecoder::new(&compressed_data[..]); + let mut decompressed_data = Vec::new(); + decoder.read_to_end(&mut decompressed_data).map_err(D::Error::custom)?; + + let json_str = String::from_utf8(decompressed_data).map_err(D::Error::custom)?; + serde_json::from_str(&json_str).map_err(D::Error::custom) + } +} + #[serde_as] #[derive(Default, Debug, Clone, Deserialize, Serialize)] pub struct DebugInfo { @@ -45,6 +98,7 @@ pub struct DebugInfo { #[serde_as(as = "BTreeMap")] pub locations: BTreeMap>, pub variables: DebugVariables, + pub functions: DebugFunctions, pub types: DebugTypes, } @@ -60,9 +114,10 @@ impl DebugInfo { pub fn new( locations: BTreeMap>, variables: DebugVariables, + functions: DebugFunctions, types: DebugTypes, ) -> Self { - Self { locations, variables, types } + Self { locations, variables, functions, types } } /// Updates the locations map when the [`Circuit`][acvm::acir::circuit::Circuit] is modified. @@ -118,40 +173,4 @@ impl DebugInfo { counted_opcodes } - - pub fn serialize_compressed_base64_json( - debug_info: &DebugInfo, - s: S, - ) -> Result - where - S: Serializer, - { - let json_str = serde_json::to_string(debug_info).map_err(S::Error::custom)?; - - let mut encoder = DeflateEncoder::new(Vec::new(), Compression::default()); - encoder.write_all(json_str.as_bytes()).map_err(S::Error::custom)?; - let compressed_data = encoder.finish().map_err(S::Error::custom)?; - - let encoded_b64 = base64::prelude::BASE64_STANDARD.encode(compressed_data); - s.serialize_str(&encoded_b64) - } - - pub fn deserialize_compressed_base64_json<'de, D>( - deserializer: D, - ) -> Result - where - D: Deserializer<'de>, - { - let encoded_b64: String = Deserialize::deserialize(deserializer)?; - - let compressed_data = - base64::prelude::BASE64_STANDARD.decode(encoded_b64).map_err(D::Error::custom)?; - - let mut decoder = DeflateDecoder::new(&compressed_data[..]); - let mut decompressed_data = Vec::new(); - decoder.read_to_end(&mut decompressed_data).map_err(D::Error::custom)?; - - let json_str = String::from_utf8(decompressed_data).map_err(D::Error::custom)?; - serde_json::from_str(&json_str).map_err(D::Error::custom) - } } diff --git a/compiler/noirc_evaluator/Cargo.toml b/compiler/noirc_evaluator/Cargo.toml index a8f0e8d83a9..aa30eef9156 100644 --- a/compiler/noirc_evaluator/Cargo.toml +++ b/compiler/noirc_evaluator/Cargo.toml @@ -3,6 +3,7 @@ name = "noirc_evaluator" version.workspace = true authors.workspace = true edition.workspace = true +rust-version.workspace = true license.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -15,6 +16,7 @@ fxhash.workspace = true iter-extended.workspace = true thiserror.workspace = true num-bigint = "0.4" -im = { version = "15.1", features = ["serde"] } +im.workspace = true serde.workspace = true -tracing.workspace = true \ No newline at end of file +tracing.workspace = true +chrono = "0.4.37" diff --git a/compiler/noirc_evaluator/src/brillig/brillig_gen.rs b/compiler/noirc_evaluator/src/brillig/brillig_gen.rs index 22814a22889..5576d673f1d 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_gen.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_gen.rs @@ -14,7 +14,7 @@ use crate::ssa::ir::function::Function; pub(crate) fn convert_ssa_function(func: &Function, enable_debug_trace: bool) -> BrilligArtifact { let mut brillig_context = BrilligContext::new(enable_debug_trace); - let mut function_context = FunctionContext::new(func, &mut brillig_context); + let mut function_context = FunctionContext::new(func); brillig_context.enter_context(FunctionContext::function_id_to_function_label(func.id())); diff --git a/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_black_box.rs b/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_black_box.rs index d542240a40c..f56c5daf315 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_black_box.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_black_box.rs @@ -1,8 +1,11 @@ -use acvm::acir::{brillig::BlackBoxOp, BlackBoxFunc}; +use acvm::{ + acir::{brillig::BlackBoxOp, BlackBoxFunc}, + FieldElement, +}; use crate::brillig::brillig_ir::{ - brillig_variable::{BrilligVariable, BrilligVector}, - BrilligContext, + brillig_variable::{BrilligVariable, BrilligVector, SingleAddrVariable}, + BrilligBinaryOp, BrilligContext, }; /// Transforms SSA's black box function calls into the corresponding brillig instructions @@ -56,17 +59,23 @@ pub(crate) fn convert_black_box_call( } BlackBoxFunc::Keccak256 => { if let ( - [message, BrilligVariable::SingleAddr(array_size)], + [message, BrilligVariable::SingleAddr(message_size)], [BrilligVariable::BrilligArray(result_array)], ) = (function_arguments, function_results) { let mut message_vector = convert_array_or_vector(brillig_context, message, bb_func); - message_vector.size = array_size.address; + let message_size_as_usize = + SingleAddrVariable::new_usize(brillig_context.allocate_register()); + // Message_size is not usize + brillig_context.cast_instruction(message_size_as_usize, *message_size); + + message_vector.size = message_size_as_usize.address; brillig_context.black_box_op_instruction(BlackBoxOp::Keccak256 { message: message_vector.to_heap_vector(), output: result_array.to_heap_array(), }); + brillig_context.deallocate_single_addr(message_size_as_usize); } else { unreachable!("ICE: Keccak256 expects message, message size and result array") } @@ -167,7 +176,7 @@ pub(crate) fn convert_black_box_call( ) = (function_arguments, function_results) { let message_hash = convert_array_or_vector(brillig_context, message, bb_func); - let signature = brillig_context.array_to_vector(signature); + let signature = brillig_context.array_to_vector_instruction(signature); brillig_context.black_box_op_instruction(BlackBoxOp::SchnorrVerify { public_key_x: public_key_x.address, public_key_y: public_key_y.address, @@ -179,34 +188,36 @@ pub(crate) fn convert_black_box_call( unreachable!("ICE: Schnorr verify expects two registers for the public key, an array for signature, an array for the message hash and one result register") } } - BlackBoxFunc::FixedBaseScalarMul => { - if let ( - [BrilligVariable::SingleAddr(low), BrilligVariable::SingleAddr(high)], - [BrilligVariable::BrilligArray(result_array)], - ) = (function_arguments, function_results) + BlackBoxFunc::MultiScalarMul => { + if let ([points, scalars], [BrilligVariable::BrilligArray(outputs)]) = + (function_arguments, function_results) { - brillig_context.black_box_op_instruction(BlackBoxOp::FixedBaseScalarMul { - low: low.address, - high: high.address, - result: result_array.to_heap_array(), + let points = convert_array_or_vector(brillig_context, points, bb_func); + let scalars = convert_array_or_vector(brillig_context, scalars, bb_func); + brillig_context.black_box_op_instruction(BlackBoxOp::MultiScalarMul { + points: points.to_heap_vector(), + scalars: scalars.to_heap_vector(), + outputs: outputs.to_heap_array(), }); } else { unreachable!( - "ICE: FixedBaseScalarMul expects one register argument and one array result" + "ICE: MultiScalarMul expects two register arguments and one array result" ) } } BlackBoxFunc::EmbeddedCurveAdd => { if let ( - [BrilligVariable::SingleAddr(input1_x), BrilligVariable::SingleAddr(input1_y), BrilligVariable::SingleAddr(input2_x), BrilligVariable::SingleAddr(input2_y)], + [BrilligVariable::SingleAddr(input1_x), BrilligVariable::SingleAddr(input1_y), BrilligVariable::SingleAddr(input1_infinite), BrilligVariable::SingleAddr(input2_x), BrilligVariable::SingleAddr(input2_y), BrilligVariable::SingleAddr(input2_infinite)], [BrilligVariable::BrilligArray(result_array)], ) = (function_arguments, function_results) { brillig_context.black_box_op_instruction(BlackBoxOp::EmbeddedCurveAdd { input1_x: input1_x.address, input1_y: input1_y.address, + input1_infinite: input1_infinite.address, input2_x: input2_x.address, input2_y: input2_y.address, + input2_infinite: input2_infinite.address, result: result_array.to_heap_array(), }); } else { @@ -224,15 +235,20 @@ pub(crate) fn convert_black_box_call( BlackBoxFunc::RANGE => unreachable!( "ICE: `BlackBoxFunc::RANGE` calls should be transformed into a `Instruction::Cast`" ), - BlackBoxFunc::RecursiveAggregation => unimplemented!( - "ICE: `BlackBoxFunc::RecursiveAggregation` is not implemented by the Brillig VM" - ), + BlackBoxFunc::RecursiveAggregation => {} BlackBoxFunc::BigIntAdd => { if let ( - [BrilligVariable::SingleAddr(lhs), BrilligVariable::SingleAddr(rhs)], - [BrilligVariable::SingleAddr(output)], + [BrilligVariable::SingleAddr(lhs), BrilligVariable::SingleAddr(lhs_modulus), BrilligVariable::SingleAddr(rhs), BrilligVariable::SingleAddr(rhs_modulus)], + [BrilligVariable::SingleAddr(output), BrilligVariable::SingleAddr(modulus_id)], ) = (function_arguments, function_results) { + prepare_bigint_output( + brillig_context, + lhs_modulus, + rhs_modulus, + output, + modulus_id, + ); brillig_context.black_box_op_instruction(BlackBoxOp::BigIntAdd { lhs: lhs.address, rhs: rhs.address, @@ -240,16 +256,23 @@ pub(crate) fn convert_black_box_call( }); } else { unreachable!( - "ICE: EmbeddedCurveAdd expects two register arguments and one array result" + "ICE: BigIntAdd expects four register arguments and two result registers" ) } } BlackBoxFunc::BigIntSub => { if let ( - [BrilligVariable::SingleAddr(lhs), BrilligVariable::SingleAddr(rhs)], - [BrilligVariable::SingleAddr(output)], + [BrilligVariable::SingleAddr(lhs), BrilligVariable::SingleAddr(lhs_modulus), BrilligVariable::SingleAddr(rhs), BrilligVariable::SingleAddr(rhs_modulus)], + [BrilligVariable::SingleAddr(output), BrilligVariable::SingleAddr(modulus_id)], ) = (function_arguments, function_results) { + prepare_bigint_output( + brillig_context, + lhs_modulus, + rhs_modulus, + output, + modulus_id, + ); brillig_context.black_box_op_instruction(BlackBoxOp::BigIntSub { lhs: lhs.address, rhs: rhs.address, @@ -257,16 +280,23 @@ pub(crate) fn convert_black_box_call( }); } else { unreachable!( - "ICE: EmbeddedCurveAdd expects two register arguments and one array result" + "ICE: BigIntSub expects four register arguments and two result registers" ) } } BlackBoxFunc::BigIntMul => { if let ( - [BrilligVariable::SingleAddr(lhs), BrilligVariable::SingleAddr(rhs)], - [BrilligVariable::SingleAddr(output)], + [BrilligVariable::SingleAddr(lhs), BrilligVariable::SingleAddr(lhs_modulus), BrilligVariable::SingleAddr(rhs), BrilligVariable::SingleAddr(rhs_modulus)], + [BrilligVariable::SingleAddr(output), BrilligVariable::SingleAddr(modulus_id)], ) = (function_arguments, function_results) { + prepare_bigint_output( + brillig_context, + lhs_modulus, + rhs_modulus, + output, + modulus_id, + ); brillig_context.black_box_op_instruction(BlackBoxOp::BigIntMul { lhs: lhs.address, rhs: rhs.address, @@ -274,16 +304,23 @@ pub(crate) fn convert_black_box_call( }); } else { unreachable!( - "ICE: EmbeddedCurveAdd expects two register arguments and one array result" + "ICE: BigIntMul expects four register arguments and two result registers" ) } } BlackBoxFunc::BigIntDiv => { if let ( - [BrilligVariable::SingleAddr(lhs), BrilligVariable::SingleAddr(rhs)], - [BrilligVariable::SingleAddr(output)], + [BrilligVariable::SingleAddr(lhs), BrilligVariable::SingleAddr(lhs_modulus), BrilligVariable::SingleAddr(rhs), BrilligVariable::SingleAddr(rhs_modulus)], + [BrilligVariable::SingleAddr(output), BrilligVariable::SingleAddr(modulus_id)], ) = (function_arguments, function_results) { + prepare_bigint_output( + brillig_context, + lhs_modulus, + rhs_modulus, + output, + modulus_id, + ); brillig_context.black_box_op_instruction(BlackBoxOp::BigIntDiv { lhs: lhs.address, rhs: rhs.address, @@ -291,16 +328,20 @@ pub(crate) fn convert_black_box_call( }); } else { unreachable!( - "ICE: EmbeddedCurveAdd expects two register arguments and one array result" + "ICE: BigIntDiv expects four register arguments and two result registers" ) } } BlackBoxFunc::BigIntFromLeBytes => { - if let ([inputs, modulus], [BrilligVariable::SingleAddr(output)]) = - (function_arguments, function_results) + if let ( + [inputs, modulus], + [BrilligVariable::SingleAddr(output), BrilligVariable::SingleAddr(_modulus_id)], + ) = (function_arguments, function_results) { let inputs_vector = convert_array_or_vector(brillig_context, inputs, bb_func); let modulus_vector = convert_array_or_vector(brillig_context, modulus, bb_func); + let output_id = brillig_context.get_new_bigint_id(); + brillig_context.const_instruction(*output, FieldElement::from(output_id as u128)); brillig_context.black_box_op_instruction(BlackBoxOp::BigIntFromLeBytes { inputs: inputs_vector.to_heap_vector(), modulus: modulus_vector.to_heap_vector(), @@ -308,23 +349,24 @@ pub(crate) fn convert_black_box_call( }); } else { unreachable!( - "ICE: EmbeddedCurveAdd expects two register arguments and one array result" + "ICE: BigIntFromLeBytes expects a register and an array as arguments and two result registers" ) } } BlackBoxFunc::BigIntToLeBytes => { if let ( - [BrilligVariable::SingleAddr(input)], - [BrilligVariable::BrilligVector(result_vector)], + [BrilligVariable::SingleAddr(input), BrilligVariable::SingleAddr(_modulus)], + [result_array], ) = (function_arguments, function_results) { + let output = convert_array_or_vector(brillig_context, result_array, bb_func); brillig_context.black_box_op_instruction(BlackBoxOp::BigIntToLeBytes { input: input.address, - output: result_vector.to_heap_vector(), + output: output.to_heap_vector(), }); } else { unreachable!( - "ICE: EmbeddedCurveAdd expects two register arguments and one array result" + "ICE: BigIntToLeBytes expects two register arguments and one array result" ) } } @@ -359,6 +401,28 @@ pub(crate) fn convert_black_box_call( unreachable!("ICE: Sha256Compression expects two array argument, one array result") } } + BlackBoxFunc::AES128Encrypt => { + if let ( + [inputs, BrilligVariable::BrilligArray(iv), BrilligVariable::BrilligArray(key)], + [BrilligVariable::SingleAddr(out_len), outputs], + ) = (function_arguments, function_results) + { + let inputs = convert_array_or_vector(brillig_context, inputs, bb_func); + let outputs = convert_array_or_vector(brillig_context, outputs, bb_func); + let output_vec = outputs.to_heap_vector(); + brillig_context.black_box_op_instruction(BlackBoxOp::AES128Encrypt { + inputs: inputs.to_heap_vector(), + iv: iv.to_heap_array(), + key: key.to_heap_array(), + outputs: output_vec, + }); + brillig_context.mov_instruction(out_len.address, output_vec.size); + // Returns slice, so we need to allocate memory for it after the fact + brillig_context.increase_free_memory_pointer_instruction(output_vec.size); + } else { + unreachable!("ICE: AES128Encrypt expects three array arguments, one array result") + } + } } } @@ -368,7 +432,7 @@ fn convert_array_or_vector( bb_func: &BlackBoxFunc, ) -> BrilligVector { match array_or_vector { - BrilligVariable::BrilligArray(array) => brillig_context.array_to_vector(array), + BrilligVariable::BrilligArray(array) => brillig_context.array_to_vector_instruction(array), BrilligVariable::BrilligVector(vector) => *vector, _ => unreachable!( "ICE: {} expected an array or a vector, but got {:?}", @@ -377,3 +441,30 @@ fn convert_array_or_vector( ), } } + +fn prepare_bigint_output( + brillig_context: &mut BrilligContext, + lhs_modulus: &SingleAddrVariable, + rhs_modulus: &SingleAddrVariable, + output: &SingleAddrVariable, + modulus_id: &SingleAddrVariable, +) { + // Check moduli + let condition = brillig_context.allocate_register(); + let condition_adr = SingleAddrVariable { address: condition, bit_size: 1 }; + brillig_context.binary_instruction( + *lhs_modulus, + *rhs_modulus, + condition_adr, + BrilligBinaryOp::Equals, + ); + brillig_context.codegen_constrain( + condition_adr, + Some("moduli should be identical in BigInt operation".to_string()), + ); + brillig_context.deallocate_register(condition); + // Set output id + let output_id = brillig_context.get_new_bigint_id(); + brillig_context.const_instruction(*output, FieldElement::from(output_id as u128)); + brillig_context.mov_instruction(modulus_id.address, lhs_modulus.address); +} 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 f01f60252f6..1fa4f41b29c 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs @@ -2,12 +2,12 @@ use crate::brillig::brillig_ir::brillig_variable::{ type_to_heap_value_type, BrilligArray, BrilligVariable, BrilligVector, SingleAddrVariable, }; use crate::brillig::brillig_ir::{ - BrilligBinaryOp, BrilligContext, BRILLIG_INTEGER_ARITHMETIC_BIT_SIZE, + BrilligBinaryOp, BrilligContext, BRILLIG_MEMORY_ADDRESSING_BIT_SIZE, }; use crate::ssa::ir::dfg::CallStack; use crate::ssa::ir::instruction::ConstrainError; use crate::ssa::ir::{ - basic_block::{BasicBlock, BasicBlockId}, + basic_block::BasicBlockId, dfg::DataFlowGraph, function::FunctionId, instruction::{ @@ -16,16 +16,16 @@ use crate::ssa::ir::{ types::{NumericType, Type}, value::{Value, ValueId}, }; -use acvm::acir::brillig::{BinaryFieldOp, BinaryIntOp, MemoryAddress, ValueOrArray}; +use acvm::acir::brillig::{MemoryAddress, ValueOrArray}; use acvm::brillig_vm::brillig::HeapVector; -use acvm::FieldElement; +use acvm::{acir::AcirField, 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; -use super::brillig_fn::{get_bit_size_from_ssa_type, FunctionContext}; +use super::brillig_fn::FunctionContext; /// Generate the compilation artifacts for compiling a function into brillig bytecode. pub(crate) struct BrilligBlock<'block> { @@ -49,8 +49,7 @@ impl<'block> BrilligBlock<'block> { dfg: &DataFlowGraph, ) { let live_in = function_context.liveness.get_live_in(&block_id); - let variables = - BlockVariables::new(live_in.clone(), function_context.all_block_parameters()); + let variables = BlockVariables::new(live_in.clone()); brillig_context.set_allocated_registers( variables @@ -72,9 +71,9 @@ impl<'block> BrilligBlock<'block> { let block_label = self.create_block_label_for_current_function(self.block_id); self.brillig_context.enter_context(block_label); - // Convert the block parameters + self.convert_block_params(dfg); + let block = &dfg[self.block_id]; - self.convert_block_params(block, dfg); // Convert all of the instructions into the block for instruction_id in block.instructions() { @@ -134,12 +133,8 @@ impl<'block> BrilligBlock<'block> { let target_block = &dfg[*destination_block]; for (src, dest) in arguments.iter().zip(target_block.parameters()) { // Destinations are block parameters so they should have been allocated previously. - let destination = self.variables.get_block_param( - self.function_context, - *destination_block, - *dest, - dfg, - ); + let destination = + self.variables.get_allocation(self.function_context, *dest, dfg); let source = self.convert_ssa_value(*src, dfg); self.pass_variable(source, destination); } @@ -155,7 +150,7 @@ impl<'block> BrilligBlock<'block> { return_variable.extract_registers() }) .collect(); - self.brillig_context.return_instruction(&return_registers); + self.brillig_context.codegen_return(&return_registers); } } } @@ -206,10 +201,14 @@ impl<'block> BrilligBlock<'block> { } } - /// Converts SSA Block parameters into Brillig Registers. - fn convert_block_params(&mut self, block: &BasicBlock, dfg: &DataFlowGraph) { - for param_id in block.parameters() { - let value = &dfg[*param_id]; + /// Allocates the block parameters that the given block is defining + fn convert_block_params(&mut self, dfg: &DataFlowGraph) { + // We don't allocate the block parameters here, we allocate the parameters the block is defining. + // Since predecessors to a block have to know where the parameters of the block are allocated to pass data to it, + // the block parameters need to be defined/allocated before the given block. Variable liveness provides when the block parameters are defined. + // For the entry block, the defined block params will be the params of the function + any extra params of blocks it's the immediate dominator of. + for param_id in self.function_context.liveness.defined_block_params(&self.block_id) { + let value = &dfg[param_id]; let param_type = match value { Value::Param { typ, .. } => typ, _ => unreachable!("ICE: Only Param type values should appear in block parameters"), @@ -220,16 +219,14 @@ impl<'block> BrilligBlock<'block> { // Be a valid pointer to the array. // For slices, two registers are passed, the pointer to the data and a register holding the size of the slice. Type::Numeric(_) | Type::Array(..) | Type::Slice(..) | Type::Reference(_) => { - self.variables.get_block_param( + self.variables.define_variable( self.function_context, - self.block_id, - *param_id, + self.brillig_context, + param_id, dfg, ); } - _ => { - todo!("ICE: Param type not supported") - } + Type::Function => todo!("ICE: Type::Function Param not supported"), } } } @@ -260,32 +257,29 @@ impl<'block> BrilligBlock<'block> { dfg, condition, ); - - let assert_message = if let Some(error) = assert_message { - match error.as_ref() { - ConstrainError::Static(string) => Some(string.clone()), - ConstrainError::Dynamic(call_instruction) => { - let Instruction::Call { func, arguments } = call_instruction else { - unreachable!("expected a call instruction") - }; - - let Value::Function(func_id) = &dfg[*func] else { - unreachable!("expected a function value") - }; - - self.convert_ssa_function_call(*func_id, arguments, dfg, &[]); - - // Dynamic assert messages are handled in the generated function call. - // We then don't need to attach one to the constrain instruction. - None - } + match assert_message { + Some(ConstrainError::UserDefined(selector, values)) => { + let payload_values = + vecmap(values, |value| self.convert_ssa_value(*value, dfg)); + let payload_as_params = vecmap(values, |value| { + let value_type = dfg.type_of_value(*value); + FunctionContext::ssa_type_to_parameter(&value_type) + }); + self.brillig_context.codegen_constrain_with_revert_data( + condition, + payload_values, + payload_as_params, + selector.as_u64(), + ); } - } else { - None - }; - - self.brillig_context.constrain_instruction(condition.address, assert_message); - self.brillig_context.deallocate_register(condition.address); + Some(ConstrainError::Intrinsic(message)) => { + self.brillig_context.codegen_constrain(condition, Some(message.clone())); + } + None => { + self.brillig_context.codegen_constrain(condition, None); + } + } + self.brillig_context.deallocate_single_addr(condition); } Instruction::Allocate => { let result_value = dfg.instruction_results(instruction_id)[0]; @@ -299,16 +293,15 @@ impl<'block> BrilligBlock<'block> { Type::Reference(element) => match *element { Type::Array(..) => { self.brillig_context - .allocate_array_reference_instruction(address_register.address); + .codegen_allocate_array_reference(address_register.address); } Type::Slice(..) => { self.brillig_context - .allocate_vector_reference_instruction(address_register.address); + .codegen_allocate_vector_reference(address_register.address); } _ => { - self.brillig_context.allocate_single_addr_reference_instruction( - address_register.address, - ); + self.brillig_context + .codegen_allocate_single_addr_reference(address_register.address); } }, _ => { @@ -320,8 +313,7 @@ impl<'block> BrilligBlock<'block> { let address_var = self.convert_ssa_single_addr_value(*address, dfg); let source_variable = self.convert_ssa_value(*value, dfg); - self.brillig_context - .store_variable_instruction(address_var.address, source_variable); + self.brillig_context.codegen_store_variable(address_var.address, source_variable); } Instruction::Load { address } => { let target_variable = self.variables.define_variable( @@ -334,7 +326,7 @@ impl<'block> BrilligBlock<'block> { let address_variable = self.convert_ssa_single_addr_value(*address, dfg); self.brillig_context - .load_variable_instruction(target_variable, address_variable.address); + .codegen_load_variable(target_variable, address_variable.address); } Instruction::Not(value) => { let condition_register = self.convert_ssa_single_addr_value(*value, dfg); @@ -376,16 +368,16 @@ impl<'block> BrilligBlock<'block> { if let ValueOrArray::HeapVector(HeapVector { size, .. }) = output_register { // Update the stack pointer so that we do not overwrite // dynamic memory returned from other external calls - self.brillig_context.update_stack_pointer(*size); + self.brillig_context.increase_free_memory_pointer_instruction(*size); // Update the dynamic slice length maintained in SSA if let ValueOrArray::MemoryAddress(len_index) = output_registers[i - 1] { let element_size = dfg[result_ids[i]].get_type().element_size(); self.brillig_context.mov_instruction(len_index, *size); - self.brillig_context.usize_op_in_place( + self.brillig_context.codegen_usize_op_in_place( len_index, - BinaryIntOp::UnsignedDiv, + BrilligBinaryOp::UnsignedDiv, element_size, ); } else { @@ -455,6 +447,29 @@ impl<'block> BrilligBlock<'block> { self.convert_ssa_array_len(arguments[0], result_variable.address, dfg); } } + Value::Intrinsic(Intrinsic::AsSlice) => { + let source_variable = self.convert_ssa_value(arguments[0], dfg); + let result_ids = dfg.instruction_results(instruction_id); + let destination_len_variable = self.variables.define_single_addr_variable( + self.function_context, + self.brillig_context, + result_ids[0], + dfg, + ); + let destination_variable = self.variables.define_variable( + self.function_context, + self.brillig_context, + result_ids[1], + dfg, + ); + let source_size_as_register = + self.convert_ssa_array_set(source_variable, destination_variable, None); + + // we need to explicitly set the destination_len_variable + self.brillig_context + .mov_instruction(destination_len_variable.address, source_size_as_register); + self.brillig_context.deallocate_register(source_size_as_register); + } Value::Intrinsic( Intrinsic::SlicePushBack | Intrinsic::SlicePopBack @@ -472,8 +487,22 @@ impl<'block> BrilligBlock<'block> { } Value::Intrinsic(Intrinsic::ToRadix(endianness)) => { let source = self.convert_ssa_single_addr_value(arguments[0], dfg); - let radix = self.convert_ssa_single_addr_value(arguments[1], dfg); - let limb_count = self.convert_ssa_single_addr_value(arguments[2], dfg); + + let radix: u32 = dfg + .get_numeric_constant(arguments[1]) + .expect("Radix should be known") + .try_to_u64() + .expect("Radix should fit in u64") + .try_into() + .expect("Radix should be u32"); + + let limb_count: usize = dfg + .get_numeric_constant(arguments[2]) + .expect("Limb count should be known") + .try_to_u64() + .expect("Limb count should fit in u64") + .try_into() + .expect("Limb count should fit in usize"); let results = dfg.instruction_results(instruction_id); @@ -495,19 +524,27 @@ impl<'block> BrilligBlock<'block> { .extract_vector(); // Update the user-facing slice length - self.brillig_context.mov_instruction(target_len.address, limb_count.address); + self.brillig_context + .usize_const_instruction(target_len.address, limb_count.into()); - self.brillig_context.radix_instruction( - source.address, + self.brillig_context.codegen_to_radix( + source, target_vector, - radix.address, - limb_count.address, + radix, + limb_count, matches!(endianness, Endian::Big), + 8, ); } Value::Intrinsic(Intrinsic::ToBits(endianness)) => { let source = self.convert_ssa_single_addr_value(arguments[0], dfg); - let limb_count = self.convert_ssa_single_addr_value(arguments[1], dfg); + let limb_count: usize = dfg + .get_numeric_constant(arguments[1]) + .expect("Limb count should be known") + .try_to_u64() + .expect("Limb count should fit in u64") + .try_into() + .expect("Limb count should fit in usize"); let results = dfg.instruction_results(instruction_id); @@ -526,28 +563,24 @@ impl<'block> BrilligBlock<'block> { dfg, ) { BrilligVariable::BrilligArray(array) => { - self.brillig_context.array_to_vector(&array) + self.brillig_context.array_to_vector_instruction(&array) } BrilligVariable::BrilligVector(vector) => vector, BrilligVariable::SingleAddr(..) => unreachable!("ICE: ToBits on non-array"), }; - let radix = self - .brillig_context - .make_constant(2_usize.into(), FieldElement::max_num_bits()); - // Update the user-facing slice length - self.brillig_context.mov_instruction(target_len.address, limb_count.address); + self.brillig_context + .usize_const_instruction(target_len.address, limb_count.into()); - self.brillig_context.radix_instruction( - source.address, + self.brillig_context.codegen_to_radix( + source, target_vector, - radix, - limb_count.address, + 2, + limb_count, matches!(endianness, Endian::Big), + 1, ); - - self.brillig_context.deallocate_register(radix); } _ => { unreachable!("unsupported function call type {:?}", dfg[*func]) @@ -562,7 +595,7 @@ impl<'block> BrilligBlock<'block> { dfg, ); let source_register = self.convert_ssa_single_addr_value(*value, dfg); - self.brillig_context.truncate_instruction( + self.brillig_context.codegen_truncate( destination_register, source_register, *bit_size, @@ -599,11 +632,11 @@ impl<'block> BrilligBlock<'block> { self.validate_array_index(array_variable, index_variable); self.retrieve_variable_from_array( array_pointer, - index_variable.address, + index_variable, destination_variable, ); } - Instruction::ArraySet { array, index, value, .. } => { + Instruction::ArraySet { array, index, value, mutable: _ } => { let source_variable = self.convert_ssa_value(*array, dfg); let index_register = self.convert_ssa_single_addr_value(*index, dfg); let value_variable = self.convert_ssa_value(*value, dfg); @@ -616,57 +649,77 @@ impl<'block> BrilligBlock<'block> { dfg, ); self.validate_array_index(source_variable, index_register); - - self.convert_ssa_array_set( + let source_size_as_register = self.convert_ssa_array_set( source_variable, destination_variable, - index_register.address, - value_variable, + Some((index_register.address, value_variable)), ); + self.brillig_context.deallocate_register(source_size_as_register); } Instruction::RangeCheck { value, max_bit_size, assert_message } => { let value = self.convert_ssa_single_addr_value(*value, dfg); - // Cast original value to field - let left = SingleAddrVariable { - address: self.brillig_context.allocate_register(), - bit_size: FieldElement::max_num_bits(), - }; - self.convert_cast(left, value); + // SSA generates redundant range checks. A range check with a max bit size >= value.bit_size will always pass. + if value.bit_size > *max_bit_size { + // Cast original value to field + let left = SingleAddrVariable { + address: self.brillig_context.allocate_register(), + bit_size: FieldElement::max_num_bits(), + }; + self.convert_cast(left, value); - // Create a field constant with the max - let max = BigUint::from(2_u128).pow(*max_bit_size) - BigUint::from(1_u128); - let right = self.brillig_context.make_constant( - FieldElement::from_be_bytes_reduce(&max.to_bytes_be()).into(), - FieldElement::max_num_bits(), - ); + // Create a field constant with the max + let max = BigUint::from(2_u128).pow(*max_bit_size) - BigUint::from(1_u128); + let right = self.brillig_context.make_constant_instruction( + FieldElement::from_be_bytes_reduce(&max.to_bytes_be()), + FieldElement::max_num_bits(), + ); - // Check if lte max - let brillig_binary_op = BrilligBinaryOp::Integer { - op: BinaryIntOp::LessThanEquals, - bit_size: FieldElement::max_num_bits(), - }; - let condition = self.brillig_context.allocate_register(); - self.brillig_context.binary_instruction( - left.address, - right, - condition, - brillig_binary_op, - ); + // Check if lte max + let condition = + SingleAddrVariable::new(self.brillig_context.allocate_register(), 1); + self.brillig_context.binary_instruction( + left, + right, + condition, + BrilligBinaryOp::LessThanEquals, + ); - self.brillig_context.constrain_instruction(condition, assert_message.clone()); - self.brillig_context.deallocate_register(condition); - self.brillig_context.deallocate_register(left.address); - self.brillig_context.deallocate_register(right); + self.brillig_context.codegen_constrain(condition, assert_message.clone()); + self.brillig_context.deallocate_single_addr(condition); + self.brillig_context.deallocate_single_addr(left); + self.brillig_context.deallocate_single_addr(right); + } } Instruction::IncrementRc { value } => { let rc_register = match self.convert_ssa_value(*value, dfg) { BrilligVariable::BrilligArray(BrilligArray { rc, .. }) | BrilligVariable::BrilligVector(BrilligVector { rc, .. }) => rc, - _ => unreachable!("ICE: increment rc on non-array"), + other => unreachable!("ICE: increment rc on non-array: {other:?}"), }; - self.brillig_context.usize_op_in_place(rc_register, BinaryIntOp::Add, 1); + self.brillig_context.codegen_usize_op_in_place( + rc_register, + BrilligBinaryOp::Add, + 1, + ); + } + Instruction::DecrementRc { value } => { + let rc_register = match self.convert_ssa_value(*value, dfg) { + BrilligVariable::BrilligArray(BrilligArray { rc, .. }) + | BrilligVariable::BrilligVector(BrilligVector { rc, .. }) => rc, + other => unreachable!("ICE: decrement rc on non-array: {other:?}"), + }; + self.brillig_context.codegen_usize_op_in_place( + rc_register, + BrilligBinaryOp::Sub, + 1, + ); + } + Instruction::EnableSideEffects { .. } => { + todo!("enable_side_effects not supported by brillig") + } + Instruction::IfElse { .. } => { + unreachable!("IfElse instructions should not be possible in brillig") } - _ => todo!("ICE: Instruction not supported {instruction:?}"), }; let dead_variables = self @@ -704,7 +757,7 @@ impl<'block> BrilligBlock<'block> { let saved_registers = self .brillig_context - .pre_call_save_registers_prep_args(&argument_registers, &variables_to_save); + .codegen_pre_call_save_registers_prep_args(&argument_registers, &variables_to_save); // We don't save and restore constants, so we dump them before a external call since the callee might use the registers where they are allocated. self.variables.dump_constants(); @@ -738,7 +791,7 @@ impl<'block> BrilligBlock<'block> { // puts the returns into the returned_registers and restores saved_registers self.brillig_context - .post_call_prep_returns_load_registers(&returned_registers, &saved_registers); + .codegen_post_call_prep_returns_load_registers(&returned_registers, &saved_registers); } fn validate_array_index( @@ -748,48 +801,50 @@ impl<'block> BrilligBlock<'block> { ) { let (size_as_register, should_deallocate_size) = match array_variable { BrilligVariable::BrilligArray(BrilligArray { size, .. }) => { - (self.brillig_context.make_usize_constant(size.into()), true) + (self.brillig_context.make_usize_constant_instruction(size.into()), true) + } + BrilligVariable::BrilligVector(BrilligVector { size, .. }) => { + (SingleAddrVariable::new_usize(size), false) } - BrilligVariable::BrilligVector(BrilligVector { size, .. }) => (size, false), _ => unreachable!("ICE: validate array index on non-array"), }; - let condition = self.brillig_context.allocate_register(); + let condition = SingleAddrVariable::new(self.brillig_context.allocate_register(), 1); - self.brillig_context.memory_op( + self.brillig_context.memory_op_instruction( index_register.address, - size_as_register, - condition, - BinaryIntOp::LessThan, + size_as_register.address, + condition.address, + BrilligBinaryOp::LessThan, ); self.brillig_context - .constrain_instruction(condition, Some("Array index out of bounds".to_owned())); + .codegen_constrain(condition, Some("Array index out of bounds".to_owned())); if should_deallocate_size { - self.brillig_context.deallocate_register(size_as_register); + self.brillig_context.deallocate_single_addr(size_as_register); } - self.brillig_context.deallocate_register(condition); + self.brillig_context.deallocate_single_addr(condition); } pub(crate) fn retrieve_variable_from_array( &mut self, array_pointer: MemoryAddress, - index_register: MemoryAddress, + index_var: SingleAddrVariable, destination_variable: BrilligVariable, ) { match destination_variable { BrilligVariable::SingleAddr(destination_register) => { - self.brillig_context.array_get( + self.brillig_context.codegen_array_get( array_pointer, - index_register, + index_var, destination_register.address, ); } BrilligVariable::BrilligArray(..) | BrilligVariable::BrilligVector(..) => { let reference = self.brillig_context.allocate_register(); - self.brillig_context.array_get(array_pointer, index_register, reference); - self.brillig_context.load_variable_instruction(destination_variable, reference); + self.brillig_context.codegen_array_get(array_pointer, index_var, reference); + self.brillig_context.codegen_load_variable(destination_variable, reference); self.brillig_context.deallocate_register(reference); } } @@ -797,29 +852,31 @@ impl<'block> BrilligBlock<'block> { /// Array set operation in SSA returns a new array or slice that is a copy of the parameter array or slice /// With a specific value changed. + /// + /// Returns `source_size_as_register`, which is expected to be deallocated with: + /// `self.brillig_context.deallocate_register(source_size_as_register)` fn convert_ssa_array_set( &mut self, source_variable: BrilligVariable, destination_variable: BrilligVariable, - index_register: MemoryAddress, - value_variable: BrilligVariable, - ) { + opt_index_and_value: Option<(MemoryAddress, BrilligVariable)>, + ) -> MemoryAddress { let destination_pointer = match destination_variable { BrilligVariable::BrilligArray(BrilligArray { pointer, .. }) => pointer, BrilligVariable::BrilligVector(BrilligVector { pointer, .. }) => pointer, - _ => unreachable!("ICE: array set returns non-array"), + _ => unreachable!("ICE: array_set SSA returns non-array"), }; let reference_count = match source_variable { BrilligVariable::BrilligArray(BrilligArray { rc, .. }) | BrilligVariable::BrilligVector(BrilligVector { rc, .. }) => rc, - _ => unreachable!("ICE: array set on non-array"), + _ => unreachable!("ICE: array_set SSA on non-array"), }; let (source_pointer, source_size_as_register) = match source_variable { BrilligVariable::BrilligArray(BrilligArray { size, pointer, rc: _ }) => { let source_size_register = self.brillig_context.allocate_register(); - self.brillig_context.usize_const(source_size_register, size.into()); + self.brillig_context.usize_const_instruction(source_size_register, size.into()); (pointer, source_size_register) } BrilligVariable::BrilligVector(BrilligVector { size, pointer, rc: _ }) => { @@ -827,38 +884,40 @@ impl<'block> BrilligBlock<'block> { self.brillig_context.mov_instruction(source_size_register, size); (pointer, source_size_register) } - _ => unreachable!("ICE: array set on non-array"), + _ => unreachable!("ICE: array_set SSA on non-array"), }; - let one = self.brillig_context.make_usize_constant(1_usize.into()); + // Here we want to compare the reference count against 1. + let one = self.brillig_context.make_usize_constant_instruction(1_usize.into()); let condition = self.brillig_context.allocate_register(); - - self.brillig_context.binary_instruction( + self.brillig_context.memory_op_instruction( reference_count, - one, + one.address, condition, - BrilligBinaryOp::Field { op: BinaryFieldOp::Equals }, + BrilligBinaryOp::Equals, ); - - self.brillig_context.branch_instruction(condition, |ctx, cond| { + self.brillig_context.codegen_branch(condition, |ctx, cond| { if cond { // Reference count is 1, we can mutate the array directly ctx.mov_instruction(destination_pointer, source_pointer); } else { // First issue a array copy to the destination - ctx.allocate_array_instruction(destination_pointer, source_size_as_register); + ctx.codegen_allocate_array(destination_pointer, source_size_as_register); - ctx.copy_array_instruction( + ctx.codegen_copy_array( source_pointer, destination_pointer, - source_size_as_register, + SingleAddrVariable::new( + source_size_as_register, + BRILLIG_MEMORY_ADDRESSING_BIT_SIZE, + ), ); } }); match destination_variable { BrilligVariable::BrilligArray(BrilligArray { rc: target_rc, .. }) => { - self.brillig_context.usize_const(target_rc, 1_usize.into()); + self.brillig_context.usize_const_instruction(target_rc, 1_usize.into()); } BrilligVariable::BrilligVector(BrilligVector { size: target_size, @@ -866,41 +925,46 @@ impl<'block> BrilligBlock<'block> { .. }) => { self.brillig_context.mov_instruction(target_size, source_size_as_register); - self.brillig_context.usize_const(target_rc, 1_usize.into()); + self.brillig_context.usize_const_instruction(target_rc, 1_usize.into()); } - _ => unreachable!("ICE: array set on non-array"), + _ => unreachable!("ICE: array_set SSA on non-array"), } - // Then set the value in the newly created array - self.store_variable_in_array(destination_pointer, index_register, value_variable); + if let Some((index_register, value_variable)) = opt_index_and_value { + // Then set the value in the newly created array + self.store_variable_in_array( + destination_pointer, + SingleAddrVariable::new_usize(index_register), + value_variable, + ); + } - self.brillig_context.deallocate_register(source_size_as_register); - self.brillig_context.deallocate_register(one); self.brillig_context.deallocate_register(condition); + source_size_as_register } pub(crate) fn store_variable_in_array_with_ctx( ctx: &mut BrilligContext, destination_pointer: MemoryAddress, - index_register: MemoryAddress, + index_register: SingleAddrVariable, value_variable: BrilligVariable, ) { match value_variable { BrilligVariable::SingleAddr(value_variable) => { - ctx.array_set(destination_pointer, index_register, value_variable.address); + ctx.codegen_array_set(destination_pointer, index_register, value_variable.address); } BrilligVariable::BrilligArray(_) => { let reference: MemoryAddress = ctx.allocate_register(); - ctx.allocate_array_reference_instruction(reference); - ctx.store_variable_instruction(reference, value_variable); - ctx.array_set(destination_pointer, index_register, reference); + ctx.codegen_allocate_array_reference(reference); + ctx.codegen_store_variable(reference, value_variable); + ctx.codegen_array_set(destination_pointer, index_register, reference); ctx.deallocate_register(reference); } BrilligVariable::BrilligVector(_) => { let reference = ctx.allocate_register(); - ctx.allocate_vector_reference_instruction(reference); - ctx.store_variable_instruction(reference, value_variable); - ctx.array_set(destination_pointer, index_register, reference); + ctx.codegen_allocate_vector_reference(reference); + ctx.codegen_store_variable(reference, value_variable); + ctx.codegen_array_set(destination_pointer, index_register, reference); ctx.deallocate_register(reference); } } @@ -909,13 +973,13 @@ impl<'block> BrilligBlock<'block> { pub(crate) fn store_variable_in_array( &mut self, destination_pointer: MemoryAddress, - index_register: MemoryAddress, + index_variable: SingleAddrVariable, value_variable: BrilligVariable, ) { Self::store_variable_in_array_with_ctx( self.brillig_context, destination_pointer, - index_register, + index_variable, value_variable, ); } @@ -958,7 +1022,12 @@ impl<'block> BrilligBlock<'block> { self.convert_ssa_value(*arg, dfg) }); - self.update_slice_length(target_len.address, arguments[0], dfg, BinaryIntOp::Add); + self.update_slice_length( + target_len.address, + arguments[0], + dfg, + BrilligBinaryOp::Add, + ); self.slice_push_back_operation(target_vector, source_vector, &item_values); } @@ -984,7 +1053,12 @@ impl<'block> BrilligBlock<'block> { self.convert_ssa_value(*arg, dfg) }); - self.update_slice_length(target_len.address, arguments[0], dfg, BinaryIntOp::Add); + self.update_slice_length( + target_len.address, + arguments[0], + dfg, + BrilligBinaryOp::Add, + ); self.slice_push_front_operation(target_vector, source_vector, &item_values); } @@ -1017,7 +1091,12 @@ impl<'block> BrilligBlock<'block> { ) }); - self.update_slice_length(target_len.address, arguments[0], dfg, BinaryIntOp::Sub); + self.update_slice_length( + target_len.address, + arguments[0], + dfg, + BrilligBinaryOp::Sub, + ); self.slice_pop_back_operation(target_vector, source_vector, &pop_variables); } @@ -1049,7 +1128,12 @@ impl<'block> BrilligBlock<'block> { ); let target_vector = target_variable.extract_vector(); - self.update_slice_length(target_len.address, arguments[0], dfg, BinaryIntOp::Sub); + self.update_slice_length( + target_len.address, + arguments[0], + dfg, + BrilligBinaryOp::Sub, + ); self.slice_pop_front_operation(target_vector, source_vector, &pop_variables); } @@ -1078,23 +1162,29 @@ impl<'block> BrilligBlock<'block> { // https://github.com/noir-lang/noir/issues/1889#issuecomment-1668048587 let user_index = self.convert_ssa_single_addr_value(arguments[2], dfg); - let converted_index = self.brillig_context.make_usize_constant(element_size.into()); + let converted_index = + self.brillig_context.make_usize_constant_instruction(element_size.into()); - self.brillig_context.memory_op( - converted_index, + self.brillig_context.memory_op_instruction( + converted_index.address, user_index.address, - converted_index, - BinaryIntOp::Mul, + converted_index.address, + BrilligBinaryOp::Mul, ); let items = vecmap(&arguments[3..element_size + 3], |arg| { self.convert_ssa_value(*arg, dfg) }); - self.update_slice_length(target_len.address, arguments[0], dfg, BinaryIntOp::Add); + self.update_slice_length( + target_len.address, + arguments[0], + dfg, + BrilligBinaryOp::Add, + ); self.slice_insert_operation(target_vector, source_vector, converted_index, &items); - self.brillig_context.deallocate_register(converted_index); + self.brillig_context.deallocate_single_addr(converted_index); } Value::Intrinsic(Intrinsic::SliceRemove) => { let target_len = match self.variables.define_variable( @@ -1121,12 +1211,13 @@ impl<'block> BrilligBlock<'block> { // https://github.com/noir-lang/noir/issues/1889#issuecomment-1668048587 let user_index = self.convert_ssa_single_addr_value(arguments[2], dfg); - let converted_index = self.brillig_context.make_usize_constant(element_size.into()); - self.brillig_context.memory_op( - converted_index, + let converted_index = + self.brillig_context.make_usize_constant_instruction(element_size.into()); + self.brillig_context.memory_op_instruction( + converted_index.address, user_index.address, - converted_index, - BinaryIntOp::Mul, + converted_index.address, + BrilligBinaryOp::Mul, ); let removed_items = vecmap(&results[2..element_size + 2], |result| { @@ -1138,7 +1229,12 @@ impl<'block> BrilligBlock<'block> { ) }); - self.update_slice_length(target_len.address, arguments[0], dfg, BinaryIntOp::Sub); + self.update_slice_length( + target_len.address, + arguments[0], + dfg, + BrilligBinaryOp::Sub, + ); self.slice_remove_operation( target_vector, @@ -1147,7 +1243,7 @@ impl<'block> BrilligBlock<'block> { &removed_items, ); - self.brillig_context.deallocate_register(converted_index); + self.brillig_context.deallocate_single_addr(converted_index); } _ => unreachable!("ICE: Slice operation not supported"), } @@ -1167,12 +1263,12 @@ impl<'block> BrilligBlock<'block> { target_len: MemoryAddress, source_value: ValueId, dfg: &DataFlowGraph, - binary_op: BinaryIntOp, + binary_op: BrilligBinaryOp, ) { let source_len_variable = self.convert_ssa_value(source_value, dfg); let source_len = source_len_variable.extract_single_addr(); - self.brillig_context.usize_op(source_len.address, target_len, binary_op, 1); + self.brillig_context.codegen_usize_op(source_len.address, target_len, binary_op, 1); } /// Converts an SSA cast to a sequence of Brillig opcodes. @@ -1191,21 +1287,320 @@ impl<'block> BrilligBlock<'block> { dfg: &DataFlowGraph, result_variable: SingleAddrVariable, ) { - let binary_type = - type_of_binary_operation(dfg[binary.lhs].get_type(), dfg[binary.rhs].get_type()); + let binary_type = type_of_binary_operation( + dfg[binary.lhs].get_type(), + dfg[binary.rhs].get_type(), + binary.operator, + ); let left = self.convert_ssa_single_addr_value(binary.lhs, dfg); let right = self.convert_ssa_single_addr_value(binary.rhs, dfg); - let brillig_binary_op = - convert_ssa_binary_op_to_brillig_binary_op(binary.operator, &binary_type); + let (is_field, is_signed) = match binary_type { + Type::Numeric(numeric_type) => match numeric_type { + NumericType::Signed { .. } => (false, true), + NumericType::Unsigned { .. } => (false, false), + NumericType::NativeField => (true, false), + }, + _ => unreachable!("only numeric types are allowed in binary operations. References are handled separately"), + }; - self.brillig_context.binary_instruction( - left.address, - right.address, - result_variable.address, + let brillig_binary_op = match binary.operator { + BinaryOp::Div => { + if is_signed { + self.convert_signed_division(left, right, result_variable); + return; + } else if is_field { + BrilligBinaryOp::FieldDiv + } else { + BrilligBinaryOp::UnsignedDiv + } + } + BinaryOp::Mod => { + if is_signed { + self.convert_signed_modulo(left, right, result_variable); + return; + } else { + BrilligBinaryOp::Modulo + } + } + BinaryOp::Add => BrilligBinaryOp::Add, + BinaryOp::Sub => BrilligBinaryOp::Sub, + BinaryOp::Mul => BrilligBinaryOp::Mul, + BinaryOp::Eq => BrilligBinaryOp::Equals, + BinaryOp::Lt => { + if is_signed { + self.convert_signed_less_than(left, right, result_variable); + return; + } else { + BrilligBinaryOp::LessThan + } + } + BinaryOp::And => BrilligBinaryOp::And, + BinaryOp::Or => BrilligBinaryOp::Or, + BinaryOp::Xor => BrilligBinaryOp::Xor, + BinaryOp::Shl => BrilligBinaryOp::Shl, + BinaryOp::Shr => BrilligBinaryOp::Shr, + }; + + self.brillig_context.binary_instruction(left, right, result_variable, brillig_binary_op); + + self.add_overflow_check( brillig_binary_op, + left, + right, + result_variable, + binary, + dfg, + is_signed, + ); + } + + /// Splits a two's complement signed integer in the sign bit and the absolute value. + /// For example, -6 i8 (11111010) is split to 00000110 (6, absolute value) and 1 (is_negative). + fn absolute_value( + &mut self, + num: SingleAddrVariable, + absolute_value: SingleAddrVariable, + result_is_negative: SingleAddrVariable, + ) { + let max_positive = self + .brillig_context + .make_constant_instruction(((1_u128 << (num.bit_size - 1)) - 1).into(), num.bit_size); + + // Compute if num is negative + self.brillig_context.binary_instruction( + max_positive, + num, + result_is_negative, + BrilligBinaryOp::LessThan, ); + + // Two's complement of num + let zero = self.brillig_context.make_constant_instruction(0_usize.into(), num.bit_size); + let twos_complement = + SingleAddrVariable::new(self.brillig_context.allocate_register(), num.bit_size); + self.brillig_context.binary_instruction(zero, num, twos_complement, BrilligBinaryOp::Sub); + + // absolute_value = result_is_negative ? twos_complement : num + self.brillig_context.conditional_mov_instruction( + absolute_value.address, + result_is_negative.address, + twos_complement.address, + num.address, + ); + + self.brillig_context.deallocate_single_addr(zero); + self.brillig_context.deallocate_single_addr(max_positive); + self.brillig_context.deallocate_single_addr(twos_complement); + } + + fn convert_signed_division( + &mut self, + left: SingleAddrVariable, + right: SingleAddrVariable, + result: SingleAddrVariable, + ) { + let left_is_negative = SingleAddrVariable::new(self.brillig_context.allocate_register(), 1); + let left_abs_value = + SingleAddrVariable::new(self.brillig_context.allocate_register(), left.bit_size); + + let right_is_negative = + SingleAddrVariable::new(self.brillig_context.allocate_register(), 1); + let right_abs_value = + SingleAddrVariable::new(self.brillig_context.allocate_register(), right.bit_size); + + let result_is_negative = + SingleAddrVariable::new(self.brillig_context.allocate_register(), 1); + + // Compute both absolute values + self.absolute_value(left, left_abs_value, left_is_negative); + self.absolute_value(right, right_abs_value, right_is_negative); + + // Perform the division on the absolute values + self.brillig_context.binary_instruction( + left_abs_value, + right_abs_value, + result, + BrilligBinaryOp::UnsignedDiv, + ); + + // Compute result sign + self.brillig_context.binary_instruction( + left_is_negative, + right_is_negative, + result_is_negative, + BrilligBinaryOp::Xor, + ); + + // If result has to be negative, perform two's complement + self.brillig_context.codegen_if(result_is_negative.address, |ctx| { + let zero = ctx.make_constant_instruction(0_usize.into(), result.bit_size); + ctx.binary_instruction(zero, result, result, BrilligBinaryOp::Sub); + ctx.deallocate_single_addr(zero); + }); + + self.brillig_context.deallocate_single_addr(left_is_negative); + self.brillig_context.deallocate_single_addr(left_abs_value); + self.brillig_context.deallocate_single_addr(right_is_negative); + self.brillig_context.deallocate_single_addr(right_abs_value); + self.brillig_context.deallocate_single_addr(result_is_negative); + } + + fn convert_signed_modulo( + &mut self, + left: SingleAddrVariable, + right: SingleAddrVariable, + result: SingleAddrVariable, + ) { + let scratch_var_i = + SingleAddrVariable::new(self.brillig_context.allocate_register(), left.bit_size); + let scratch_var_j = + SingleAddrVariable::new(self.brillig_context.allocate_register(), left.bit_size); + + // i = left / right + self.convert_signed_division(left, right, scratch_var_i); + + // j = i * right + self.brillig_context.binary_instruction( + scratch_var_i, + right, + scratch_var_j, + BrilligBinaryOp::Mul, + ); + + // result_register = left - j + self.brillig_context.binary_instruction(left, scratch_var_j, result, BrilligBinaryOp::Sub); + // Free scratch registers + self.brillig_context.deallocate_single_addr(scratch_var_i); + self.brillig_context.deallocate_single_addr(scratch_var_j); + } + + fn convert_signed_less_than( + &mut self, + left: SingleAddrVariable, + right: SingleAddrVariable, + result: SingleAddrVariable, + ) { + let biased_left = + SingleAddrVariable::new(self.brillig_context.allocate_register(), left.bit_size); + let biased_right = + SingleAddrVariable::new(self.brillig_context.allocate_register(), right.bit_size); + + let bias = self + .brillig_context + .make_constant_instruction((1_u128 << (left.bit_size - 1)).into(), left.bit_size); + + self.brillig_context.binary_instruction(left, bias, biased_left, BrilligBinaryOp::Add); + self.brillig_context.binary_instruction(right, bias, biased_right, BrilligBinaryOp::Add); + + self.brillig_context.binary_instruction( + biased_left, + biased_right, + result, + BrilligBinaryOp::LessThan, + ); + + self.brillig_context.deallocate_single_addr(biased_left); + self.brillig_context.deallocate_single_addr(biased_right); + self.brillig_context.deallocate_single_addr(bias); + } + + #[allow(clippy::too_many_arguments)] + fn add_overflow_check( + &mut self, + binary_operation: BrilligBinaryOp, + left: SingleAddrVariable, + right: SingleAddrVariable, + result: SingleAddrVariable, + binary: &Binary, + dfg: &DataFlowGraph, + is_signed: bool, + ) { + let bit_size = left.bit_size; + let max_lhs_bits = dfg.get_value_max_num_bits(binary.lhs); + let max_rhs_bits = dfg.get_value_max_num_bits(binary.rhs); + + if bit_size == FieldElement::max_num_bits() { + return; + } + + match (binary_operation, is_signed) { + (BrilligBinaryOp::Add, false) => { + if std::cmp::max(max_lhs_bits, max_rhs_bits) < bit_size { + // `left` and `right` have both been casted up from smaller types and so cannot overflow. + return; + } + + let condition = + SingleAddrVariable::new(self.brillig_context.allocate_register(), 1); + // Check that lhs <= result + self.brillig_context.binary_instruction( + left, + result, + condition, + BrilligBinaryOp::LessThanEquals, + ); + self.brillig_context + .codegen_constrain(condition, Some("attempt to add with overflow".to_string())); + self.brillig_context.deallocate_single_addr(condition); + } + (BrilligBinaryOp::Sub, false) => { + if dfg.is_constant(binary.lhs) && max_lhs_bits > max_rhs_bits { + // `left` is a fixed constant and `right` is restricted such that `left - right > 0` + // Note strict inequality as `right > left` while `max_lhs_bits == max_rhs_bits` is possible. + return; + } + + let condition = + SingleAddrVariable::new(self.brillig_context.allocate_register(), 1); + // Check that rhs <= lhs + self.brillig_context.binary_instruction( + right, + left, + condition, + BrilligBinaryOp::LessThanEquals, + ); + self.brillig_context.codegen_constrain( + condition, + Some("attempt to subtract with overflow".to_string()), + ); + self.brillig_context.deallocate_single_addr(condition); + } + (BrilligBinaryOp::Mul, false) => { + if bit_size == 1 || max_lhs_bits + max_rhs_bits <= bit_size { + // Either performing boolean multiplication (which cannot overflow), + // or `left` and `right` have both been casted up from smaller types and so cannot overflow. + return; + } + + let is_right_zero = + SingleAddrVariable::new(self.brillig_context.allocate_register(), 1); + let zero = self.brillig_context.make_constant_instruction(0_usize.into(), bit_size); + self.brillig_context.binary_instruction( + zero, + right, + is_right_zero, + BrilligBinaryOp::Equals, + ); + self.brillig_context.codegen_if_not(is_right_zero.address, |ctx| { + let condition = SingleAddrVariable::new(ctx.allocate_register(), 1); + let division = SingleAddrVariable::new(ctx.allocate_register(), bit_size); + // Check that result / rhs == lhs + ctx.binary_instruction(result, right, division, BrilligBinaryOp::UnsignedDiv); + ctx.binary_instruction(division, left, condition, BrilligBinaryOp::Equals); + ctx.codegen_constrain( + condition, + Some("attempt to multiply with overflow".to_string()), + ); + ctx.deallocate_single_addr(condition); + ctx.deallocate_single_addr(division); + }); + self.brillig_context.deallocate_single_addr(is_right_zero); + self.brillig_context.deallocate_single_addr(zero); + } + _ => {} + } } /// Converts an SSA `ValueId` into a `RegisterOrMemory`. Initializes if necessary. @@ -1217,9 +1612,10 @@ impl<'block> BrilligBlock<'block> { Value::Param { .. } | Value::Instruction { .. } => { // All block parameters and instruction results should have already been // converted to registers so we fetch from the cache. + self.variables.get_allocation(self.function_context, value_id, dfg) } - Value::NumericConstant { constant, typ } => { + Value::NumericConstant { constant, .. } => { // Constants might have been converted previously or not, so we get or create and // (re)initialize the value inside. if let Some(variable) = self.variables.get_constant(value_id, dfg) { @@ -1227,13 +1623,9 @@ impl<'block> BrilligBlock<'block> { } else { let new_variable = self.variables.allocate_constant(self.brillig_context, value_id, dfg); - let register_index = new_variable.extract_single_addr(); - self.brillig_context.const_instruction( - register_index.address, - (*constant).into(), - get_bit_size_from_ssa_type(typ), - ); + self.brillig_context + .const_instruction(new_variable.extract_single_addr(), *constant); new_variable } } @@ -1247,17 +1639,21 @@ impl<'block> BrilligBlock<'block> { // Initialize the variable let pointer = match new_variable { BrilligVariable::BrilligArray(brillig_array) => { + self.brillig_context.codegen_allocate_fixed_length_array( + brillig_array.pointer, + array.len(), + ); self.brillig_context - .allocate_fixed_length_array(brillig_array.pointer, array.len()); - self.brillig_context.usize_const(brillig_array.rc, 1_usize.into()); + .usize_const_instruction(brillig_array.rc, 1_usize.into()); brillig_array.pointer } BrilligVariable::BrilligVector(vector) => { - self.brillig_context.usize_const(vector.size, array.len().into()); self.brillig_context - .allocate_array_instruction(vector.pointer, vector.size); - self.brillig_context.usize_const(vector.rc, 1_usize.into()); + .usize_const_instruction(vector.size, array.len().into()); + self.brillig_context + .codegen_allocate_array(vector.pointer, vector.size); + self.brillig_context.usize_const_instruction(vector.rc, 1_usize.into()); vector.pointer } @@ -1270,21 +1666,21 @@ impl<'block> BrilligBlock<'block> { // Allocate a register for the iterator let iterator_register = - self.brillig_context.make_usize_constant(0_usize.into()); + self.brillig_context.make_usize_constant_instruction(0_usize.into()); for element_id in array.iter() { let element_variable = self.convert_ssa_value(*element_id, dfg); // Store the item in memory self.store_variable_in_array(pointer, iterator_register, element_variable); // Increment the iterator - self.brillig_context.usize_op_in_place( - iterator_register, - BinaryIntOp::Add, + self.brillig_context.codegen_usize_op_in_place( + iterator_register.address, + BrilligBinaryOp::Add, 1, ); } - self.brillig_context.deallocate_register(iterator_register); + self.brillig_context.deallocate_single_addr(iterator_register); new_variable } @@ -1296,12 +1692,10 @@ impl<'block> BrilligBlock<'block> { // value. let new_variable = self.variables.allocate_constant(self.brillig_context, value_id, dfg); - let register_index = new_variable.extract_single_addr(); self.brillig_context.const_instruction( - register_index.address, + new_variable.extract_single_addr(), value_id.to_usize().into(), - 32, ); new_variable } @@ -1343,8 +1737,8 @@ impl<'block> BrilligBlock<'block> { dfg, ); let array = variable.extract_array(); - self.brillig_context.allocate_fixed_length_array(array.pointer, array.size); - self.brillig_context.usize_const(array.rc, 1_usize.into()); + self.brillig_context.codegen_allocate_fixed_length_array(array.pointer, array.size); + self.brillig_context.usize_const_instruction(array.rc, 1_usize.into()); variable } @@ -1360,8 +1754,8 @@ impl<'block> BrilligBlock<'block> { // Set the pointer to the current stack frame // The stack pointer will then be updated by the caller of this method // once the external call is resolved and the array size is known - self.brillig_context.set_array_pointer(vector.pointer); - self.brillig_context.usize_const(vector.rc, 1_usize.into()); + self.brillig_context.load_free_memory_pointer_instruction(vector.pointer); + self.brillig_context.usize_const_instruction(vector.rc, 1_usize.into()); variable } @@ -1385,13 +1779,14 @@ impl<'block> BrilligBlock<'block> { match array_variable { BrilligVariable::BrilligArray(BrilligArray { size, .. }) => { - self.brillig_context.usize_const(result_register, (size / element_size).into()); + self.brillig_context + .usize_const_instruction(result_register, (size / element_size).into()); } BrilligVariable::BrilligVector(BrilligVector { size, .. }) => { - self.brillig_context.usize_op( + self.brillig_context.codegen_usize_op( size, result_register, - BinaryIntOp::UnsignedDiv, + BrilligBinaryOp::UnsignedDiv, element_size, ); } @@ -1403,9 +1798,7 @@ impl<'block> BrilligBlock<'block> { } /// Returns the type of the operation considering the types of the operands -/// TODO: SSA issues binary operations between fields and integers. -/// This probably should be explicitly casted in SSA to avoid having to coerce at this level. -pub(crate) fn type_of_binary_operation(lhs_type: &Type, rhs_type: &Type) -> Type { +pub(crate) fn type_of_binary_operation(lhs_type: &Type, rhs_type: &Type, op: BinaryOp) -> Type { match (lhs_type, rhs_type) { (_, Type::Function) | (Type::Function, _) => { unreachable!("Functions are invalid in binary operations") @@ -1419,88 +1812,17 @@ pub(crate) fn type_of_binary_operation(lhs_type: &Type, rhs_type: &Type) -> Type (_, Type::Slice(..)) | (Type::Slice(..), _) => { unreachable!("Arrays are invalid in binary operations") } - // If either side is a Field constant then, we coerce into the type - // of the other operand - (Type::Numeric(NumericType::NativeField), typ) - | (typ, Type::Numeric(NumericType::NativeField)) => typ.clone(), // If both sides are numeric type, then we expect their types to be // the same. - (Type::Numeric(lhs_type), Type::Numeric(rhs_type)) => { + (Type::Numeric(lhs_type), Type::Numeric(rhs_type)) + if op != BinaryOp::Shl && op != BinaryOp::Shr => + { assert_eq!( lhs_type, rhs_type, - "lhs and rhs types in a binary operation are always the same" + "lhs and rhs types in a binary operation are always the same but got {lhs_type} and {rhs_type}" ); Type::Numeric(*lhs_type) } - } -} - -/// Convert an SSA binary operation into: -/// - Brillig Binary Integer Op, if it is a integer type -/// - Brillig Binary Field Op, if it is a field type -pub(crate) fn convert_ssa_binary_op_to_brillig_binary_op( - ssa_op: BinaryOp, - typ: &Type, -) -> BrilligBinaryOp { - // First get the bit size and whether its a signed integer, if it is a numeric type - // if it is not,then we return None, indicating that - // it is a Field. - let bit_size_signedness = match typ { - Type::Numeric(numeric_type) => match numeric_type { - NumericType::Signed { bit_size } => Some((bit_size, true)), - NumericType::Unsigned { bit_size } => Some((bit_size, false)), - NumericType::NativeField => None, - }, - _ => unreachable!("only numeric types are allowed in binary operations. References are handled separately"), - }; - - fn binary_op_to_field_op(op: BinaryOp) -> BrilligBinaryOp { - match op { - BinaryOp::Add => BrilligBinaryOp::Field { op: BinaryFieldOp::Add }, - BinaryOp::Sub => BrilligBinaryOp::Field { op: BinaryFieldOp::Sub }, - BinaryOp::Mul => BrilligBinaryOp::Field { op: BinaryFieldOp::Mul }, - BinaryOp::Div => BrilligBinaryOp::Field { op: BinaryFieldOp::Div }, - BinaryOp::Eq => BrilligBinaryOp::Field { op: BinaryFieldOp::Equals }, - BinaryOp::Lt => BrilligBinaryOp::Integer { - op: BinaryIntOp::LessThan, - bit_size: BRILLIG_INTEGER_ARITHMETIC_BIT_SIZE, - }, - _ => unreachable!( - "Field type cannot be used with {op}. This should have been caught by the frontend" - ), - } - } - - fn binary_op_to_int_op(op: BinaryOp, bit_size: u32, is_signed: bool) -> BrilligBinaryOp { - let operation = match op { - BinaryOp::Add => BinaryIntOp::Add, - BinaryOp::Sub => BinaryIntOp::Sub, - BinaryOp::Mul => BinaryIntOp::Mul, - BinaryOp::Div => { - if is_signed { - BinaryIntOp::SignedDiv - } else { - BinaryIntOp::UnsignedDiv - } - } - BinaryOp::Mod => { - return BrilligBinaryOp::Modulo { is_signed_integer: is_signed, bit_size } - } - BinaryOp::Eq => BinaryIntOp::Equals, - BinaryOp::Lt => BinaryIntOp::LessThan, - BinaryOp::And => BinaryIntOp::And, - BinaryOp::Or => BinaryIntOp::Or, - BinaryOp::Xor => BinaryIntOp::Xor, - BinaryOp::Shl => BinaryIntOp::Shl, - BinaryOp::Shr => BinaryIntOp::Shr, - }; - - BrilligBinaryOp::Integer { op: operation, bit_size } - } - - // If bit size is available then it is a binary integer operation - match bit_size_signedness { - Some((bit_size, is_signed)) => binary_op_to_int_op(ssa_op, *bit_size, is_signed), - None => binary_op_to_field_op(ssa_op), + _ => lhs_type.clone(), } } diff --git a/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block_variables.rs b/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block_variables.rs index f463bd4de4d..fb9a8577d94 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block_variables.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block_variables.rs @@ -2,11 +2,13 @@ use fxhash::{FxHashMap as HashMap, FxHashSet as HashSet}; use crate::{ brillig::brillig_ir::{ - brillig_variable::{BrilligArray, BrilligVariable, BrilligVector, SingleAddrVariable}, - BrilligContext, BRILLIG_MEMORY_ADDRESSING_BIT_SIZE, + brillig_variable::{ + get_bit_size_from_ssa_type, BrilligArray, BrilligVariable, BrilligVector, + SingleAddrVariable, + }, + BrilligContext, }, ssa::ir::{ - basic_block::BasicBlockId, dfg::DataFlowGraph, types::{CompositeType, Type}, value::ValueId, @@ -18,18 +20,13 @@ use super::brillig_fn::FunctionContext; #[derive(Debug, Default)] pub(crate) struct BlockVariables { available_variables: HashSet, - block_parameters: HashSet, available_constants: HashMap, } impl BlockVariables { /// Creates a BlockVariables instance. It uses the variables that are live in to the block and the global available variables (block parameters) - pub(crate) fn new(live_in: HashSet, all_block_parameters: HashSet) -> Self { - BlockVariables { - available_variables: live_in.into_iter().chain(all_block_parameters.clone()).collect(), - block_parameters: all_block_parameters, - ..Default::default() - } + pub(crate) fn new(live_in: HashSet) -> Self { + BlockVariables { available_variables: live_in, ..Default::default() } } /// Returns all non-constant variables that have not been removed at this point. @@ -89,16 +86,13 @@ impl BlockVariables { brillig_context: &mut BrilligContext, ) { assert!(self.available_variables.remove(value_id), "ICE: Variable is not available"); - // Block parameters should not be deallocated - if !self.block_parameters.contains(value_id) { - let variable = function_context - .ssa_value_allocations - .get(value_id) - .expect("ICE: Variable allocation not found"); - variable.extract_registers().iter().for_each(|register| { - brillig_context.deallocate_register(*register); - }); - } + let variable = function_context + .ssa_value_allocations + .get(value_id) + .expect("ICE: Variable allocation not found"); + variable.extract_registers().iter().for_each(|register| { + brillig_context.deallocate_register(*register); + }); } /// For a given SSA value id, return the corresponding cached allocation. @@ -152,27 +146,6 @@ impl BlockVariables { pub(crate) fn dump_constants(&mut self) { self.available_constants.clear(); } - - /// For a given block parameter, return the allocation that was done globally to the function. - pub(crate) fn get_block_param( - &mut self, - function_context: &FunctionContext, - block_id: BasicBlockId, - value_id: ValueId, - dfg: &DataFlowGraph, - ) -> BrilligVariable { - let value_id = dfg.resolve(value_id); - assert!( - function_context - .block_parameters - .get(&block_id) - .expect("Block not found") - .contains(&value_id), - "Value is not a block parameter" - ); - - *function_context.ssa_value_allocations.get(&value_id).expect("Block param not found") - } } /// Computes the length of an array. This will match with the indexes that SSA will issue @@ -189,21 +162,10 @@ pub(crate) fn allocate_value( let typ = dfg.type_of_value(value_id); match typ { - Type::Numeric(numeric_type) => BrilligVariable::SingleAddr(SingleAddrVariable { - address: brillig_context.allocate_register(), - bit_size: numeric_type.bit_size(), - }), - Type::Reference(_) => BrilligVariable::SingleAddr(SingleAddrVariable { - address: brillig_context.allocate_register(), - bit_size: BRILLIG_MEMORY_ADDRESSING_BIT_SIZE, - }), - Type::Function => { - // NB. function references are converted to a constant when - // translating from SSA to Brillig (to allow for debugger - // instrumentation to work properly) + Type::Numeric(_) | Type::Reference(_) | Type::Function => { BrilligVariable::SingleAddr(SingleAddrVariable { address: brillig_context.allocate_register(), - bit_size: 32, + bit_size: get_bit_size_from_ssa_type(&typ), }) } Type::Array(item_typ, elem_count) => { diff --git a/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_directive.rs b/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_directive.rs index 93c4b1a5042..74319595795 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_directive.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_directive.rs @@ -1,5 +1,6 @@ use acvm::{ - acir::brillig::{BinaryFieldOp, BinaryIntOp, MemoryAddress, Opcode as BrilligOpcode, Value}, + acir::brillig::{BinaryFieldOp, BinaryIntOp, MemoryAddress, Opcode as BrilligOpcode}, + acir::AcirField, FieldElement, }; @@ -16,18 +17,32 @@ pub(crate) fn directive_invert() -> GeneratedBrillig { // We store the result in this register too. let input = MemoryAddress::from(0); let one_const = MemoryAddress::from(1); + let zero_const = MemoryAddress::from(2); + let input_is_zero = MemoryAddress::from(3); // Location of the stop opcode - let stop_location = 3; + let stop_location = 6; GeneratedBrillig { byte_code: vec![ BrilligOpcode::CalldataCopy { destination_address: input, size: 1, offset: 0 }, + // Put value zero in register (2) + BrilligOpcode::Const { + destination: zero_const, + value: FieldElement::from(0_usize), + bit_size: FieldElement::max_num_bits(), + }, + BrilligOpcode::BinaryFieldOp { + op: BinaryFieldOp::Equals, + lhs: input, + rhs: zero_const, + destination: input_is_zero, + }, // If the input is zero, then we jump to the stop opcode - BrilligOpcode::JumpIfNot { condition: input, location: stop_location }, + BrilligOpcode::JumpIf { condition: input_is_zero, location: stop_location }, // Put value one in register (1) BrilligOpcode::Const { destination: one_const, - value: Value::from(1_usize), + value: FieldElement::from(1_usize), bit_size: FieldElement::max_num_bits(), }, // Divide 1 by the input, and set the result of the division into register (0) @@ -56,45 +71,102 @@ pub(crate) fn directive_invert() -> GeneratedBrillig { pub(crate) fn directive_quotient(bit_size: u32) -> GeneratedBrillig { // `a` is (0) (i.e register index 0) // `b` is (1) - GeneratedBrillig { - byte_code: vec![ - BrilligOpcode::CalldataCopy { - destination_address: MemoryAddress::from(0), - size: 2, - offset: 0, - }, - //q = a/b is set into register (2) - BrilligOpcode::BinaryIntOp { - op: BinaryIntOp::UnsignedDiv, - lhs: MemoryAddress::from(0), - rhs: MemoryAddress::from(1), - destination: MemoryAddress::from(2), - bit_size, - }, - //(1)= q*b - BrilligOpcode::BinaryIntOp { - op: BinaryIntOp::Mul, - lhs: MemoryAddress::from(2), - rhs: MemoryAddress::from(1), - destination: MemoryAddress::from(1), - bit_size, - }, - //(1) = a-q*b - BrilligOpcode::BinaryIntOp { - op: BinaryIntOp::Sub, - lhs: MemoryAddress::from(0), - rhs: MemoryAddress::from(1), - destination: MemoryAddress::from(1), - bit_size, - }, - //(0) = q - BrilligOpcode::Mov { - destination: MemoryAddress::from(0), - source: MemoryAddress::from(2), - }, - BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 2 }, - ], - assert_messages: Default::default(), - locations: Default::default(), + + // TODO: The only difference between these implementations is the integer version will truncate the input to the `bit_size` via cast. + // Once we deduplicate brillig functions then we can modify this so that fields and integers share the same quotient function. + if bit_size >= FieldElement::max_num_bits() { + // Field version + GeneratedBrillig { + byte_code: vec![ + BrilligOpcode::CalldataCopy { + destination_address: MemoryAddress::from(0), + size: 2, + offset: 0, + }, + // No cast, since calldata is typed as field by default + //q = a/b is set into register (2) + BrilligOpcode::BinaryFieldOp { + op: BinaryFieldOp::IntegerDiv, // We want integer division, not field division! + lhs: MemoryAddress::from(0), + rhs: MemoryAddress::from(1), + destination: MemoryAddress::from(2), + }, + //(1)= q*b + BrilligOpcode::BinaryFieldOp { + op: BinaryFieldOp::Mul, + lhs: MemoryAddress::from(2), + rhs: MemoryAddress::from(1), + destination: MemoryAddress::from(1), + }, + //(1) = a-q*b + BrilligOpcode::BinaryFieldOp { + op: BinaryFieldOp::Sub, + lhs: MemoryAddress::from(0), + rhs: MemoryAddress::from(1), + destination: MemoryAddress::from(1), + }, + //(0) = q + BrilligOpcode::Mov { + destination: MemoryAddress::from(0), + source: MemoryAddress::from(2), + }, + BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 2 }, + ], + assert_messages: Default::default(), + locations: Default::default(), + } + } else { + // Integer version + GeneratedBrillig { + byte_code: vec![ + BrilligOpcode::CalldataCopy { + destination_address: MemoryAddress::from(0), + size: 2, + offset: 0, + }, + BrilligOpcode::Cast { + destination: MemoryAddress(0), + source: MemoryAddress(0), + bit_size, + }, + BrilligOpcode::Cast { + destination: MemoryAddress(1), + source: MemoryAddress(1), + bit_size, + }, + //q = a/b is set into register (2) + BrilligOpcode::BinaryIntOp { + op: BinaryIntOp::Div, + lhs: MemoryAddress::from(0), + rhs: MemoryAddress::from(1), + destination: MemoryAddress::from(2), + bit_size, + }, + //(1)= q*b + BrilligOpcode::BinaryIntOp { + op: BinaryIntOp::Mul, + lhs: MemoryAddress::from(2), + rhs: MemoryAddress::from(1), + destination: MemoryAddress::from(1), + bit_size, + }, + //(1) = a-q*b + BrilligOpcode::BinaryIntOp { + op: BinaryIntOp::Sub, + lhs: MemoryAddress::from(0), + rhs: MemoryAddress::from(1), + destination: MemoryAddress::from(1), + bit_size, + }, + //(0) = q + BrilligOpcode::Mov { + destination: MemoryAddress::from(0), + source: MemoryAddress::from(2), + }, + BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 2 }, + ], + assert_messages: Default::default(), + locations: Default::default(), + } } } diff --git a/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_fn.rs b/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_fn.rs index b5da8296ba5..000d1230ece 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_fn.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_fn.rs @@ -1,30 +1,26 @@ -use acvm::FieldElement; use iter_extended::vecmap; use crate::{ brillig::brillig_ir::{ artifact::{BrilligParameter, Label}, - brillig_variable::BrilligVariable, - BrilligContext, BRILLIG_MEMORY_ADDRESSING_BIT_SIZE, + brillig_variable::{get_bit_size_from_ssa_type, BrilligVariable}, }, ssa::ir::{ basic_block::BasicBlockId, function::{Function, FunctionId}, post_order::PostOrder, - types::{NumericType, Type}, + types::Type, value::ValueId, }, }; -use fxhash::{FxHashMap as HashMap, FxHashSet as HashSet}; +use fxhash::FxHashMap as HashMap; -use super::{brillig_block_variables::allocate_value, variable_liveness::VariableLiveness}; +use super::variable_liveness::VariableLiveness; pub(crate) struct FunctionContext { pub(crate) function_id: FunctionId, /// Map from SSA values its allocation. Since values can be only defined once in SSA form, we insert them here on when we allocate them at their definition. pub(crate) ssa_value_allocations: HashMap, - /// Block parameters are pre allocated at the function level. - pub(crate) block_parameters: HashMap>, /// The block ids of the function in reverse post order. pub(crate) blocks: Vec, /// Liveness information for each variable in the function. @@ -32,46 +28,28 @@ pub(crate) struct FunctionContext { } impl FunctionContext { - /// Creates a new function context. It will allocate parameters for all blocks and compute the liveness of every variable. - pub(crate) fn new(function: &Function, brillig_context: &mut BrilligContext) -> Self { + /// Creates a new function context. It will compute the liveness of every variable. + pub(crate) fn new(function: &Function) -> Self { let id = function.id(); let mut reverse_post_order = Vec::new(); reverse_post_order.extend_from_slice(PostOrder::with_function(function).as_slice()); reverse_post_order.reverse(); - let mut block_parameters = HashMap::default(); - let mut ssa_variable_to_register_or_memory = HashMap::default(); - - for &block_id in &reverse_post_order { - let block = &function.dfg[block_id]; - let parameters = block.parameters().to_vec(); - parameters.iter().for_each(|&value_id| { - let variable = allocate_value(value_id, brillig_context, &function.dfg); - ssa_variable_to_register_or_memory.insert(value_id, variable); - }); - block_parameters.insert(block_id, parameters); - } - Self { function_id: id, - ssa_value_allocations: ssa_variable_to_register_or_memory, - block_parameters, + ssa_value_allocations: HashMap::default(), blocks: reverse_post_order, liveness: VariableLiveness::from_function(function), } } - pub(crate) fn all_block_parameters(&self) -> HashSet { - self.block_parameters.values().flat_map(|parameters| parameters.iter()).cloned().collect() - } - /// Creates a function label from a given SSA function id. pub(crate) fn function_id_to_function_label(function_id: FunctionId) -> Label { function_id.to_string() } - fn ssa_type_to_parameter(typ: &Type) -> BrilligParameter { + pub(crate) fn ssa_type_to_parameter(typ: &Type) -> BrilligParameter { match typ { Type::Numeric(_) | Type::Reference(_) => { BrilligParameter::SingleAddr(get_bit_size_from_ssa_type(typ)) @@ -82,26 +60,13 @@ impl FunctionContext { }), *size, ), - Type::Slice(item_type) => { - BrilligParameter::Slice(vecmap(item_type.iter(), |item_typ| { - FunctionContext::ssa_type_to_parameter(item_typ) - })) + Type::Slice(_) => { + panic!("ICE: Slice parameters cannot be derived from type information") } _ => unimplemented!("Unsupported function parameter/return type {typ:?}"), } } - /// Collects the parameters of a given function - pub(crate) fn parameters(func: &Function) -> Vec { - func.parameters() - .iter() - .map(|&value_id| { - let typ = func.dfg.type_of_value(value_id); - FunctionContext::ssa_type_to_parameter(&typ) - }) - .collect() - } - /// Collects the return values of a given function pub(crate) fn return_values(func: &Function) -> Vec { func.returns() @@ -113,14 +78,3 @@ impl FunctionContext { .collect() } } - -pub(crate) fn get_bit_size_from_ssa_type(typ: &Type) -> u32 { - match typ { - Type::Numeric(num_type) => match num_type { - NumericType::Signed { bit_size } | NumericType::Unsigned { bit_size } => *bit_size, - NumericType::NativeField => FieldElement::max_num_bits(), - }, - Type::Reference(_) => BRILLIG_MEMORY_ADDRESSING_BIT_SIZE, - _ => unreachable!("ICE bitwise not on a non numeric type"), - } -} diff --git a/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_slice_ops.rs b/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_slice_ops.rs index 3fc0e981165..491086e8c0f 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_slice_ops.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_slice_ops.rs @@ -1,6 +1,7 @@ -use acvm::brillig_vm::brillig::{BinaryIntOp, MemoryAddress}; - -use crate::brillig::brillig_ir::brillig_variable::{BrilligVariable, BrilligVector}; +use crate::brillig::brillig_ir::{ + brillig_variable::{BrilligVariable, BrilligVector, SingleAddrVariable}, + BrilligBinaryOp, +}; use super::brillig_block::BrilligBlock; @@ -12,33 +13,33 @@ impl<'block> BrilligBlock<'block> { variables_to_insert: &[BrilligVariable], ) { // First we need to allocate the target vector incrementing the size by variables_to_insert.len() - self.brillig_context.usize_op( + self.brillig_context.codegen_usize_op( source_vector.size, target_vector.size, - BinaryIntOp::Add, + BrilligBinaryOp::Add, variables_to_insert.len(), ); - self.brillig_context.allocate_array_instruction(target_vector.pointer, target_vector.size); + self.brillig_context.codegen_allocate_array(target_vector.pointer, target_vector.size); // We initialize the RC of the target vector to 1 - self.brillig_context.usize_const(target_vector.rc, 1_usize.into()); + self.brillig_context.usize_const_instruction(target_vector.rc, 1_usize.into()); // Now we copy the source vector into the target vector - self.brillig_context.copy_array_instruction( + self.brillig_context.codegen_copy_array( source_vector.pointer, target_vector.pointer, - source_vector.size, + SingleAddrVariable::new_usize(source_vector.size), ); for (index, variable) in variables_to_insert.iter().enumerate() { - let target_index = self.brillig_context.make_usize_constant(index.into()); - self.brillig_context.memory_op( - target_index, + let target_index = self.brillig_context.make_usize_constant_instruction(index.into()); + self.brillig_context.memory_op_instruction( + target_index.address, source_vector.size, - target_index, - BinaryIntOp::Add, + target_index.address, + BrilligBinaryOp::Add, ); self.store_variable_in_array(target_vector.pointer, target_index, *variable); - self.brillig_context.deallocate_register(target_index); + self.brillig_context.deallocate_single_addr(target_index); } } @@ -49,37 +50,37 @@ impl<'block> BrilligBlock<'block> { variables_to_insert: &[BrilligVariable], ) { // First we need to allocate the target vector incrementing the size by variables_to_insert.len() - self.brillig_context.usize_op( + self.brillig_context.codegen_usize_op( source_vector.size, target_vector.size, - BinaryIntOp::Add, + BrilligBinaryOp::Add, variables_to_insert.len(), ); - self.brillig_context.allocate_array_instruction(target_vector.pointer, target_vector.size); + self.brillig_context.codegen_allocate_array(target_vector.pointer, target_vector.size); // We initialize the RC of the target vector to 1 - self.brillig_context.usize_const(target_vector.rc, 1_usize.into()); + self.brillig_context.usize_const_instruction(target_vector.rc, 1_usize.into()); // Now we offset the target pointer by variables_to_insert.len() let destination_copy_pointer = self.brillig_context.allocate_register(); - self.brillig_context.usize_op( + self.brillig_context.codegen_usize_op( target_vector.pointer, destination_copy_pointer, - BinaryIntOp::Add, + BrilligBinaryOp::Add, variables_to_insert.len(), ); // Now we copy the source vector into the target vector starting at index variables_to_insert.len() - self.brillig_context.copy_array_instruction( + self.brillig_context.codegen_copy_array( source_vector.pointer, destination_copy_pointer, - source_vector.size, + SingleAddrVariable::new_usize(source_vector.size), ); // Then we write the items to insert at the start for (index, variable) in variables_to_insert.iter().enumerate() { - let target_index = self.brillig_context.make_usize_constant(index.into()); + let target_index = self.brillig_context.make_usize_constant_instruction(index.into()); self.store_variable_in_array(target_vector.pointer, target_index, *variable); - self.brillig_context.deallocate_register(target_index); + self.brillig_context.deallocate_single_addr(target_index); } self.brillig_context.deallocate_register(destination_copy_pointer); @@ -92,36 +93,36 @@ impl<'block> BrilligBlock<'block> { removed_items: &[BrilligVariable], ) { // First we need to allocate the target vector decrementing the size by removed_items.len() - self.brillig_context.usize_op( + self.brillig_context.codegen_usize_op( source_vector.size, target_vector.size, - BinaryIntOp::Sub, + BrilligBinaryOp::Sub, removed_items.len(), ); - self.brillig_context.allocate_array_instruction(target_vector.pointer, target_vector.size); + self.brillig_context.codegen_allocate_array(target_vector.pointer, target_vector.size); // We initialize the RC of the target vector to 1 - self.brillig_context.usize_const(target_vector.rc, 1_usize.into()); + self.brillig_context.usize_const_instruction(target_vector.rc, 1_usize.into()); // Now we offset the source pointer by removed_items.len() let source_copy_pointer = self.brillig_context.allocate_register(); - self.brillig_context.usize_op( + self.brillig_context.codegen_usize_op( source_vector.pointer, source_copy_pointer, - BinaryIntOp::Add, + BrilligBinaryOp::Add, removed_items.len(), ); // Now we copy the source vector starting at index removed_items.len() into the target vector - self.brillig_context.copy_array_instruction( + self.brillig_context.codegen_copy_array( source_copy_pointer, target_vector.pointer, - target_vector.size, + SingleAddrVariable::new_usize(target_vector.size), ); for (index, variable) in removed_items.iter().enumerate() { - let target_index = self.brillig_context.make_usize_constant(index.into()); + let target_index = self.brillig_context.make_usize_constant_instruction(index.into()); self.retrieve_variable_from_array(source_vector.pointer, target_index, *variable); - self.brillig_context.deallocate_register(target_index); + self.brillig_context.deallocate_single_addr(target_index); } self.brillig_context.deallocate_register(source_copy_pointer); @@ -134,33 +135,33 @@ impl<'block> BrilligBlock<'block> { removed_items: &[BrilligVariable], ) { // First we need to allocate the target vector decrementing the size by removed_items.len() - self.brillig_context.usize_op( + self.brillig_context.codegen_usize_op( source_vector.size, target_vector.size, - BinaryIntOp::Sub, + BrilligBinaryOp::Sub, removed_items.len(), ); - self.brillig_context.allocate_array_instruction(target_vector.pointer, target_vector.size); + self.brillig_context.codegen_allocate_array(target_vector.pointer, target_vector.size); // We initialize the RC of the target vector to 1 - self.brillig_context.usize_const(target_vector.rc, 1_usize.into()); + self.brillig_context.usize_const_instruction(target_vector.rc, 1_usize.into()); // Now we copy all elements except the last items into the target vector - self.brillig_context.copy_array_instruction( + self.brillig_context.codegen_copy_array( source_vector.pointer, target_vector.pointer, - target_vector.size, + SingleAddrVariable::new_usize(target_vector.size), ); for (index, variable) in removed_items.iter().enumerate() { - let target_index = self.brillig_context.make_usize_constant(index.into()); - self.brillig_context.memory_op( - target_index, + let target_index = self.brillig_context.make_usize_constant_instruction(index.into()); + self.brillig_context.memory_op_instruction( + target_index.address, target_vector.size, - target_index, - BinaryIntOp::Add, + target_index.address, + BrilligBinaryOp::Add, ); self.retrieve_variable_from_array(source_vector.pointer, target_index, *variable); - self.brillig_context.deallocate_register(target_index); + self.brillig_context.deallocate_single_addr(target_index); } } @@ -168,22 +169,22 @@ impl<'block> BrilligBlock<'block> { &mut self, target_vector: BrilligVector, source_vector: BrilligVector, - index: MemoryAddress, + index: SingleAddrVariable, items: &[BrilligVariable], ) { // First we need to allocate the target vector incrementing the size by items.len() - self.brillig_context.usize_op( + self.brillig_context.codegen_usize_op( source_vector.size, target_vector.size, - BinaryIntOp::Add, + BrilligBinaryOp::Add, items.len(), ); - self.brillig_context.allocate_array_instruction(target_vector.pointer, target_vector.size); + self.brillig_context.codegen_allocate_array(target_vector.pointer, target_vector.size); // We initialize the RC of the target vector to 1 - self.brillig_context.usize_const(target_vector.rc, 1_usize.into()); + self.brillig_context.usize_const_instruction(target_vector.rc, 1_usize.into()); // Copy the elements to the left of the index - self.brillig_context.copy_array_instruction( + self.brillig_context.codegen_copy_array( source_vector.pointer, target_vector.pointer, index, @@ -191,44 +192,55 @@ impl<'block> BrilligBlock<'block> { // Compute the source pointer just at the index let source_pointer_at_index = self.brillig_context.allocate_register(); - self.brillig_context.memory_op( + self.brillig_context.memory_op_instruction( source_vector.pointer, - index, + index.address, source_pointer_at_index, - BinaryIntOp::Add, + BrilligBinaryOp::Add, ); // Compute the target pointer after the inserted elements let target_pointer_after_index = self.brillig_context.allocate_register(); - self.brillig_context.memory_op( + self.brillig_context.memory_op_instruction( target_vector.pointer, - index, + index.address, target_pointer_after_index, - BinaryIntOp::Add, + BrilligBinaryOp::Add, ); - self.brillig_context.usize_op_in_place( + self.brillig_context.codegen_usize_op_in_place( target_pointer_after_index, - BinaryIntOp::Add, + BrilligBinaryOp::Add, items.len(), ); // Compute the number of elements to the right of the index let item_count = self.brillig_context.allocate_register(); - self.brillig_context.memory_op(source_vector.size, index, item_count, BinaryIntOp::Sub); + self.brillig_context.memory_op_instruction( + source_vector.size, + index.address, + item_count, + BrilligBinaryOp::Sub, + ); // Copy the elements to the right of the index - self.brillig_context.copy_array_instruction( + self.brillig_context.codegen_copy_array( source_pointer_at_index, target_pointer_after_index, - item_count, + SingleAddrVariable::new_usize(item_count), ); // Write the items to insert starting at the index for (subitem_index, variable) in items.iter().enumerate() { - let target_index = self.brillig_context.make_usize_constant(subitem_index.into()); - self.brillig_context.memory_op(target_index, index, target_index, BinaryIntOp::Add); + let target_index = + self.brillig_context.make_usize_constant_instruction(subitem_index.into()); + self.brillig_context.memory_op_instruction( + target_index.address, + index.address, + target_index.address, + BrilligBinaryOp::Add, + ); self.store_variable_in_array(target_vector.pointer, target_index, *variable); - self.brillig_context.deallocate_register(target_index); + self.brillig_context.deallocate_single_addr(target_index); } self.brillig_context.deallocate_register(source_pointer_at_index); @@ -240,22 +252,22 @@ impl<'block> BrilligBlock<'block> { &mut self, target_vector: BrilligVector, source_vector: BrilligVector, - index: MemoryAddress, + index: SingleAddrVariable, removed_items: &[BrilligVariable], ) { // First we need to allocate the target vector decrementing the size by removed_items.len() - self.brillig_context.usize_op( + self.brillig_context.codegen_usize_op( source_vector.size, target_vector.size, - BinaryIntOp::Sub, + BrilligBinaryOp::Sub, removed_items.len(), ); - self.brillig_context.allocate_array_instruction(target_vector.pointer, target_vector.size); + self.brillig_context.codegen_allocate_array(target_vector.pointer, target_vector.size); // We initialize the RC of the target vector to 1 - self.brillig_context.usize_const(target_vector.rc, 1_usize.into()); + self.brillig_context.usize_const_instruction(target_vector.rc, 1_usize.into()); // Copy the elements to the left of the index - self.brillig_context.copy_array_instruction( + self.brillig_context.codegen_copy_array( source_vector.pointer, target_vector.pointer, index, @@ -263,45 +275,60 @@ impl<'block> BrilligBlock<'block> { // Compute the source pointer after the removed items let source_pointer_after_index = self.brillig_context.allocate_register(); - self.brillig_context.memory_op( + self.brillig_context.memory_op_instruction( source_vector.pointer, - index, + index.address, source_pointer_after_index, - BinaryIntOp::Add, + BrilligBinaryOp::Add, ); - self.brillig_context.usize_op_in_place( + self.brillig_context.codegen_usize_op_in_place( source_pointer_after_index, - BinaryIntOp::Add, + BrilligBinaryOp::Add, removed_items.len(), ); // Compute the target pointer at the index let target_pointer_at_index = self.brillig_context.allocate_register(); - self.brillig_context.memory_op( + self.brillig_context.memory_op_instruction( target_vector.pointer, - index, + index.address, target_pointer_at_index, - BinaryIntOp::Add, + BrilligBinaryOp::Add, ); // Compute the number of elements to the right of the index let item_count = self.brillig_context.allocate_register(); - self.brillig_context.memory_op(source_vector.size, index, item_count, BinaryIntOp::Sub); - self.brillig_context.usize_op_in_place(item_count, BinaryIntOp::Sub, removed_items.len()); + self.brillig_context.memory_op_instruction( + source_vector.size, + index.address, + item_count, + BrilligBinaryOp::Sub, + ); + self.brillig_context.codegen_usize_op_in_place( + item_count, + BrilligBinaryOp::Sub, + removed_items.len(), + ); // Copy the elements to the right of the index - self.brillig_context.copy_array_instruction( + self.brillig_context.codegen_copy_array( source_pointer_after_index, target_pointer_at_index, - item_count, + SingleAddrVariable::new_usize(item_count), ); // Get the removed items for (subitem_index, variable) in removed_items.iter().enumerate() { - let target_index = self.brillig_context.make_usize_constant(subitem_index.into()); - self.brillig_context.memory_op(target_index, index, target_index, BinaryIntOp::Add); + let target_index = + self.brillig_context.make_usize_constant_instruction(subitem_index.into()); + self.brillig_context.memory_op_instruction( + target_index.address, + index.address, + target_index.address, + BrilligBinaryOp::Add, + ); self.retrieve_variable_from_array(source_vector.pointer, target_index, *variable); - self.brillig_context.deallocate_register(target_index); + self.brillig_context.deallocate_single_addr(target_index); } self.brillig_context.deallocate_register(source_pointer_after_index); @@ -316,7 +343,7 @@ impl<'block> BrilligBlock<'block> { match source_variable { BrilligVariable::BrilligVector(source_vector) => source_vector, BrilligVariable::BrilligArray(source_array) => { - self.brillig_context.array_to_vector(&source_array) + self.brillig_context.array_to_vector_instruction(&source_array) } _ => unreachable!("ICE: unsupported slice push back source {:?}", source_variable), } @@ -327,7 +354,7 @@ impl<'block> BrilligBlock<'block> { mod tests { use std::vec; - use acvm::acir::brillig::Value; + use acvm::FieldElement; use crate::brillig::brillig_gen::brillig_block::BrilligBlock; use crate::brillig::brillig_gen::brillig_block_variables::BlockVariables; @@ -346,12 +373,13 @@ mod tests { use crate::ssa::ssa_gen::Ssa; fn create_test_environment() -> (Ssa, FunctionContext, BrilligContext) { - let builder = - FunctionBuilder::new("main".to_string(), Id::test_new(0), RuntimeType::Brillig); + let mut builder = FunctionBuilder::new("main".to_string(), Id::test_new(0)); + builder.set_runtime(RuntimeType::Brillig); + let ssa = builder.finish(); - let mut brillig_context = create_context(); + let brillig_context = create_context(); - let function_context = FunctionContext::new(ssa.main(), &mut brillig_context); + let function_context = FunctionContext::new(ssa.main()); (ssa, function_context, brillig_context) } @@ -373,9 +401,9 @@ mod tests { fn test_slice_push_operation() { fn test_case_push( push_back: bool, - array: Vec, - item_to_push: Value, - expected_return: Vec, + array: Vec, + item_to_push: FieldElement, + expected_return: Vec, ) { let arguments = vec![ BrilligParameter::Array( @@ -403,7 +431,7 @@ mod tests { }; // Cast the source array to a vector - let source_vector = context.array_to_vector(&array_variable); + let source_vector = context.array_to_vector_instruction(&array_variable); // Allocate the results let target_vector = BrilligVector { @@ -428,51 +456,72 @@ mod tests { ); } - context.return_instruction(&[target_vector.pointer, target_vector.rc]); + context.codegen_return(&[target_vector.pointer, target_vector.rc]); let bytecode = create_entry_point_bytecode(context, arguments, returns).byte_code; let (vm, return_data_offset, return_data_size) = create_and_run_vm(array.into_iter().chain(vec![item_to_push]).collect(), &bytecode); assert_eq!(return_data_size, expected_return.len()); assert_eq!( - vm.get_memory()[return_data_offset..(return_data_offset + expected_return.len())], + vm.get_memory()[return_data_offset..(return_data_offset + expected_return.len())] + .iter() + .map(|mem_val| mem_val.to_field()) + .collect::>(), expected_return ); } test_case_push( true, - vec![Value::from(1_usize), Value::from(2_usize), Value::from(3_usize)], - Value::from(27_usize), vec![ - Value::from(1_usize), - Value::from(2_usize), - Value::from(3_usize), - Value::from(27_usize), + FieldElement::from(1_usize), + FieldElement::from(2_usize), + FieldElement::from(3_usize), + ], + FieldElement::from(27_usize), + vec![ + FieldElement::from(1_usize), + FieldElement::from(2_usize), + FieldElement::from(3_usize), + FieldElement::from(27_usize), ], ); - test_case_push(true, vec![], Value::from(27_usize), vec![Value::from(27_usize)]); + test_case_push( + true, + vec![], + FieldElement::from(27_usize), + vec![FieldElement::from(27_usize)], + ); test_case_push( false, - vec![Value::from(1_usize), Value::from(2_usize), Value::from(3_usize)], - Value::from(27_usize), vec![ - Value::from(27_usize), - Value::from(1_usize), - Value::from(2_usize), - Value::from(3_usize), + FieldElement::from(1_usize), + FieldElement::from(2_usize), + FieldElement::from(3_usize), + ], + FieldElement::from(27_usize), + vec![ + FieldElement::from(27_usize), + FieldElement::from(1_usize), + FieldElement::from(2_usize), + FieldElement::from(3_usize), ], ); - test_case_push(false, vec![], Value::from(27_usize), vec![Value::from(27_usize)]); + test_case_push( + false, + vec![], + FieldElement::from(27_usize), + vec![FieldElement::from(27_usize)], + ); } #[test] fn test_slice_pop_back_operation() { fn test_case_pop( pop_back: bool, - array: Vec, - expected_return_array: Vec, - expected_return_item: Value, + array: Vec, + expected_return_array: Vec, + expected_return_item: FieldElement, ) { let arguments = vec![BrilligParameter::Array( vec![BrilligParameter::SingleAddr(BRILLIG_MEMORY_ADDRESSING_BIT_SIZE)], @@ -496,7 +545,7 @@ mod tests { }; // Cast the source array to a vector - let source_vector = context.array_to_vector(&array_variable); + let source_vector = context.array_to_vector_instruction(&array_variable); // Allocate the results let target_vector = BrilligVector { @@ -525,7 +574,7 @@ mod tests { ); } - context.return_instruction(&[ + context.codegen_return(&[ target_vector.pointer, target_vector.rc, removed_item.address, @@ -539,33 +588,44 @@ mod tests { assert_eq!(return_data_size, expected_return.len()); assert_eq!( - vm.get_memory()[return_data_offset..(return_data_offset + expected_return.len())], + vm.get_memory()[return_data_offset..(return_data_offset + expected_return.len())] + .iter() + .map(|mem_val| mem_val.to_field()) + .collect::>(), expected_return ); } test_case_pop( true, - vec![Value::from(1_usize), Value::from(2_usize), Value::from(3_usize)], - vec![Value::from(1_usize), Value::from(2_usize)], - Value::from(3_usize), + vec![ + FieldElement::from(1_usize), + FieldElement::from(2_usize), + FieldElement::from(3_usize), + ], + vec![FieldElement::from(1_usize), FieldElement::from(2_usize)], + FieldElement::from(3_usize), ); - test_case_pop(true, vec![Value::from(1_usize)], vec![], Value::from(1_usize)); + test_case_pop(true, vec![FieldElement::from(1_usize)], vec![], FieldElement::from(1_usize)); test_case_pop( false, - vec![Value::from(1_usize), Value::from(2_usize), Value::from(3_usize)], - vec![Value::from(2_usize), Value::from(3_usize)], - Value::from(1_usize), + vec![ + FieldElement::from(1_usize), + FieldElement::from(2_usize), + FieldElement::from(3_usize), + ], + vec![FieldElement::from(2_usize), FieldElement::from(3_usize)], + FieldElement::from(1_usize), ); } #[test] fn test_slice_insert_operation() { fn test_case_insert( - array: Vec, - item: Value, - index: Value, - expected_return: Vec, + array: Vec, + item: FieldElement, + index: FieldElement, + expected_return: Vec, ) { let arguments = vec![ BrilligParameter::Array( @@ -592,10 +652,13 @@ mod tests { address: context.allocate_register(), bit_size: BRILLIG_MEMORY_ADDRESSING_BIT_SIZE, }; - let index_to_insert = context.allocate_register(); + let index_to_insert = SingleAddrVariable::new( + context.allocate_register(), + BRILLIG_MEMORY_ADDRESSING_BIT_SIZE, + ); // Cast the source array to a vector - let source_vector = context.array_to_vector(&array_variable); + let source_vector = context.array_to_vector_instruction(&array_variable); // Allocate the results let target_vector = BrilligVector { @@ -613,7 +676,7 @@ mod tests { &[BrilligVariable::SingleAddr(item_to_insert)], ); - context.return_instruction(&[target_vector.pointer, target_vector.rc]); + context.codegen_return(&[target_vector.pointer, target_vector.rc]); let calldata = array.into_iter().chain(vec![item]).chain(vec![index]).collect(); let bytecode = create_entry_point_bytecode(context, arguments, returns).byte_code; @@ -621,71 +684,90 @@ mod tests { assert_eq!(return_data_size, expected_return.len()); assert_eq!( - vm.get_memory()[return_data_offset..(return_data_offset + expected_return.len())], + vm.get_memory()[return_data_offset..(return_data_offset + expected_return.len())] + .iter() + .map(|mem_val| mem_val.to_field()) + .collect::>(), expected_return ); } test_case_insert( - vec![Value::from(1_usize), Value::from(2_usize), Value::from(3_usize)], - Value::from(27_usize), - Value::from(1_usize), vec![ - Value::from(1_usize), - Value::from(27_usize), - Value::from(2_usize), - Value::from(3_usize), + FieldElement::from(1_usize), + FieldElement::from(2_usize), + FieldElement::from(3_usize), + ], + FieldElement::from(27_usize), + FieldElement::from(1_usize), + vec![ + FieldElement::from(1_usize), + FieldElement::from(27_usize), + FieldElement::from(2_usize), + FieldElement::from(3_usize), ], ); test_case_insert( - vec![Value::from(1_usize), Value::from(2_usize), Value::from(3_usize)], - Value::from(27_usize), - Value::from(0_usize), vec![ - Value::from(27_usize), - Value::from(1_usize), - Value::from(2_usize), - Value::from(3_usize), + FieldElement::from(1_usize), + FieldElement::from(2_usize), + FieldElement::from(3_usize), + ], + FieldElement::from(27_usize), + FieldElement::from(0_usize), + vec![ + FieldElement::from(27_usize), + FieldElement::from(1_usize), + FieldElement::from(2_usize), + FieldElement::from(3_usize), ], ); test_case_insert( - vec![Value::from(1_usize), Value::from(2_usize), Value::from(3_usize)], - Value::from(27_usize), - Value::from(2_usize), vec![ - Value::from(1_usize), - Value::from(2_usize), - Value::from(27_usize), - Value::from(3_usize), + FieldElement::from(1_usize), + FieldElement::from(2_usize), + FieldElement::from(3_usize), + ], + FieldElement::from(27_usize), + FieldElement::from(2_usize), + vec![ + FieldElement::from(1_usize), + FieldElement::from(2_usize), + FieldElement::from(27_usize), + FieldElement::from(3_usize), ], ); test_case_insert( - vec![Value::from(1_usize), Value::from(2_usize), Value::from(3_usize)], - Value::from(27_usize), - Value::from(3_usize), vec![ - Value::from(1_usize), - Value::from(2_usize), - Value::from(3_usize), - Value::from(27_usize), + FieldElement::from(1_usize), + FieldElement::from(2_usize), + FieldElement::from(3_usize), + ], + FieldElement::from(27_usize), + FieldElement::from(3_usize), + vec![ + FieldElement::from(1_usize), + FieldElement::from(2_usize), + FieldElement::from(3_usize), + FieldElement::from(27_usize), ], ); test_case_insert( vec![], - Value::from(27_usize), - Value::from(0_usize), - vec![Value::from(27_usize)], + FieldElement::from(27_usize), + FieldElement::from(0_usize), + vec![FieldElement::from(27_usize)], ); } #[test] fn test_slice_remove_operation() { fn test_case_remove( - array: Vec, - index: Value, - expected_array: Vec, - expected_removed_item: Value, + array: Vec, + index: FieldElement, + expected_array: Vec, + expected_removed_item: FieldElement, ) { let arguments = vec![ BrilligParameter::Array( @@ -710,10 +792,13 @@ mod tests { size: array.len(), rc: context.allocate_register(), }; - let index_to_insert = context.allocate_register(); + let index_to_insert = SingleAddrVariable::new( + context.allocate_register(), + BRILLIG_MEMORY_ADDRESSING_BIT_SIZE, + ); // Cast the source array to a vector - let source_vector = context.array_to_vector(&array_variable); + let source_vector = context.array_to_vector_instruction(&array_variable); // Allocate the results let target_vector = BrilligVector { @@ -735,7 +820,7 @@ mod tests { &[BrilligVariable::SingleAddr(removed_item)], ); - context.return_instruction(&[ + context.codegen_return(&[ target_vector.pointer, target_vector.size, removed_item.address, @@ -751,36 +836,51 @@ mod tests { assert_eq!(return_data_size, expected_return.len()); assert_eq!( - vm.get_memory()[return_data_offset..(return_data_offset + expected_return.len())], + vm.get_memory()[return_data_offset..(return_data_offset + expected_return.len())] + .iter() + .map(|mem_val| mem_val.to_field()) + .collect::>(), expected_return ); } test_case_remove( - vec![Value::from(1_usize), Value::from(2_usize), Value::from(3_usize)], - Value::from(0_usize), - vec![Value::from(2_usize), Value::from(3_usize)], - Value::from(1_usize), + vec![ + FieldElement::from(1_usize), + FieldElement::from(2_usize), + FieldElement::from(3_usize), + ], + FieldElement::from(0_usize), + vec![FieldElement::from(2_usize), FieldElement::from(3_usize)], + FieldElement::from(1_usize), ); test_case_remove( - vec![Value::from(1_usize), Value::from(2_usize), Value::from(3_usize)], - Value::from(1_usize), - vec![Value::from(1_usize), Value::from(3_usize)], - Value::from(2_usize), + vec![ + FieldElement::from(1_usize), + FieldElement::from(2_usize), + FieldElement::from(3_usize), + ], + FieldElement::from(1_usize), + vec![FieldElement::from(1_usize), FieldElement::from(3_usize)], + FieldElement::from(2_usize), ); test_case_remove( - vec![Value::from(1_usize), Value::from(2_usize), Value::from(3_usize)], - Value::from(2_usize), - vec![Value::from(1_usize), Value::from(2_usize)], - Value::from(3_usize), + vec![ + FieldElement::from(1_usize), + FieldElement::from(2_usize), + FieldElement::from(3_usize), + ], + FieldElement::from(2_usize), + vec![FieldElement::from(1_usize), FieldElement::from(2_usize)], + FieldElement::from(3_usize), ); test_case_remove( - vec![Value::from(1_usize)], - Value::from(0_usize), + vec![FieldElement::from(1_usize)], + FieldElement::from(0_usize), vec![], - Value::from(1_usize), + FieldElement::from(1_usize), ); } } diff --git a/compiler/noirc_evaluator/src/brillig/brillig_gen/variable_liveness.rs b/compiler/noirc_evaluator/src/brillig/brillig_gen/variable_liveness.rs index 05978c2c6ab..52eded81919 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_gen/variable_liveness.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_gen/variable_liveness.rs @@ -93,6 +93,9 @@ fn variables_used_in_block(block: &BasicBlock, dfg: &DataFlowGraph) -> Vec Vec; -fn compute_defined_variables(block: &BasicBlock, dfg: &DataFlowGraph) -> Variables { - let mut defined_vars = HashSet::default(); - - for parameter in block.parameters() { - defined_vars.insert(dfg.resolve(*parameter)); - } - - for instruction_id in block.instructions() { - let result_values = dfg.instruction_results(*instruction_id); - for result_value in result_values { - defined_vars.insert(dfg.resolve(*result_value)); - } - } - - defined_vars -} - fn compute_used_before_def( block: &BasicBlock, dfg: &DataFlowGraph, @@ -142,6 +128,8 @@ pub(crate) struct VariableLiveness { live_in: HashMap, /// The variables that stop being alive after each specific instruction last_uses: HashMap, + /// The list of block params the given block is defining. The order matters for the entry block, so it's a vec. + param_definitions: HashMap>, } impl VariableLiveness { @@ -150,8 +138,15 @@ impl VariableLiveness { let cfg = ControlFlowGraph::with_function(func); let post_order = PostOrder::with_function(func); - let mut instance = - Self { cfg, post_order, live_in: HashMap::default(), last_uses: HashMap::default() }; + let mut instance = Self { + cfg, + post_order, + live_in: HashMap::default(), + last_uses: HashMap::default(), + param_definitions: HashMap::default(), + }; + + instance.compute_block_param_definitions(func); instance.compute_live_in_of_blocks(func); @@ -179,6 +174,30 @@ impl VariableLiveness { self.last_uses.get(block_id).expect("Last uses should have been calculated") } + /// Retrieves the list of block params the given block is defining. + /// Block params are defined before the block that owns them (since they are used by the predecessor blocks). They must be defined in the immediate dominator. + /// This is the last point where the block param can be allocated without it being allocated in different places in different branches. + pub(crate) fn defined_block_params(&self, block_id: &BasicBlockId) -> Vec { + self.param_definitions.get(block_id).cloned().unwrap_or_default() + } + + fn compute_block_param_definitions(&mut self, func: &Function) { + let tree = DominatorTree::with_cfg_and_post_order(&self.cfg, &self.post_order); + + // Going in reverse post order to process the entry block first + let mut reverse_post_order = Vec::new(); + reverse_post_order.extend_from_slice(self.post_order.as_slice()); + reverse_post_order.reverse(); + for block in reverse_post_order { + let params = func.dfg[block].parameters(); + // If it has no dominator, it's the entry block + let dominator_block = tree.immediate_dominator(block).unwrap_or(func.entry_block()); + let definitions_for_the_dominator = + self.param_definitions.entry(dominator_block).or_default(); + definitions_for_the_dominator.extend(params.iter()); + } + } + fn compute_live_in_of_blocks(&mut self, func: &Function) { let back_edges = find_back_edges(func, &self.cfg, &self.post_order); @@ -197,9 +216,10 @@ impl VariableLiveness { block_id: BasicBlockId, back_edges: &HashSet, ) { - let block = &func.dfg[block_id]; + let defined = self.compute_defined_variables(block_id, &func.dfg); + + let block: &BasicBlock = &func.dfg[block_id]; - let defined = compute_defined_variables(block, &func.dfg); let used_before_def = compute_used_before_def(block, &func.dfg, &defined); let mut live_out = HashSet::default(); @@ -222,6 +242,24 @@ impl VariableLiveness { self.live_in.insert(block_id, used_before_def.union(&passthrough_vars).cloned().collect()); } + fn compute_defined_variables(&self, block_id: BasicBlockId, dfg: &DataFlowGraph) -> Variables { + let block: &BasicBlock = &dfg[block_id]; + let mut defined_vars = HashSet::default(); + + for parameter in self.defined_block_params(&block_id) { + defined_vars.insert(dfg.resolve(parameter)); + } + + for instruction_id in block.instructions() { + let result_values = dfg.instruction_results(*instruction_id); + for result_value in result_values { + defined_vars.insert(dfg.resolve(*result_value)); + } + } + + defined_vars + } + fn update_live_ins_within_loop(&mut self, back_edge: BackEdge) { let header_live_ins = self .live_in @@ -323,7 +361,8 @@ mod test { // } let main_id = Id::test_new(1); - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Brillig); + let mut builder = FunctionBuilder::new("main".into(), main_id); + builder.set_runtime(RuntimeType::Brillig); let b1 = builder.insert_block(); let b2 = builder.insert_block(); @@ -425,7 +464,8 @@ mod test { // } let main_id = Id::test_new(1); - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Brillig); + let mut builder = FunctionBuilder::new("main".into(), main_id); + builder.set_runtime(RuntimeType::Brillig); let b1 = builder.insert_block(); let b2 = builder.insert_block(); @@ -511,12 +551,12 @@ mod test { let liveness = VariableLiveness::from_function(func); assert!(liveness.get_live_in(&func.entry_block()).is_empty()); - assert_eq!(liveness.get_live_in(&b1), &FxHashSet::from_iter([v0, v1, v3].into_iter())); + assert_eq!(liveness.get_live_in(&b1), &FxHashSet::from_iter([v0, v1, v3, v4].into_iter())); assert_eq!(liveness.get_live_in(&b3), &FxHashSet::from_iter([v3].into_iter())); assert_eq!(liveness.get_live_in(&b2), &FxHashSet::from_iter([v0, v1, v3, v4].into_iter())); assert_eq!( liveness.get_live_in(&b4), - &FxHashSet::from_iter([v0, v1, v3, v4, v6].into_iter()) + &FxHashSet::from_iter([v0, v1, v3, v4, v6, v7].into_iter()) ); assert_eq!(liveness.get_live_in(&b6), &FxHashSet::from_iter([v0, v1, v3, v4].into_iter())); assert_eq!( @@ -538,4 +578,58 @@ mod test { Some(&FxHashSet::from_iter([v3].into_iter())) ); } + + #[test] + fn block_params() { + // brillig fn main f0 { + // b0(v0: u1): + // jmpif v0 then: b1, else: b2 + // b1(): + // jmp b3(Field 27, Field 29) + // b3(v1: Field, v2: Field): + // return v1 + // b2(): + // jmp b3(Field 28, Field 40) + // } + + let main_id = Id::test_new(1); + let mut builder = FunctionBuilder::new("main".into(), main_id); + builder.set_runtime(RuntimeType::Brillig); + + let v0 = builder.add_parameter(Type::bool()); + + let b1 = builder.insert_block(); + let b2 = builder.insert_block(); + let b3 = builder.insert_block(); + + builder.terminate_with_jmpif(v0, b1, b2); + + builder.switch_to_block(b1); + let twenty_seven = builder.field_constant(27_u128); + let twenty_nine = builder.field_constant(29_u128); + builder.terminate_with_jmp(b3, vec![twenty_seven, twenty_nine]); + + builder.switch_to_block(b3); + let v1 = builder.add_block_parameter(b3, Type::field()); + let v2 = builder.add_block_parameter(b3, Type::field()); + builder.terminate_with_return(vec![v1]); + + builder.switch_to_block(b2); + let twenty_eight = builder.field_constant(28_u128); + let forty = builder.field_constant(40_u128); + builder.terminate_with_jmp(b3, vec![twenty_eight, forty]); + + let ssa = builder.finish(); + let func = ssa.main(); + let liveness = VariableLiveness::from_function(func); + + // Entry point defines its own params and also b3's params. + assert_eq!(liveness.defined_block_params(&func.entry_block()), vec![v0, v1, v2]); + assert_eq!(liveness.defined_block_params(&b1), vec![]); + assert_eq!(liveness.defined_block_params(&b2), vec![]); + assert_eq!(liveness.defined_block_params(&b3), vec![]); + + assert_eq!(liveness.get_live_in(&b1), &FxHashSet::from_iter([v1, v2].into_iter())); + assert_eq!(liveness.get_live_in(&b2), &FxHashSet::from_iter([v1, v2].into_iter())); + } } diff --git a/compiler/noirc_evaluator/src/brillig/brillig_ir.rs b/compiler/noirc_evaluator/src/brillig/brillig_ir.rs index 90608974f98..ebccf7a0bf1 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_ir.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_ir.rs @@ -4,51 +4,44 @@ //! `brillig_gen` is therefore the module which combines both //! ssa types and types in this module. //! A similar paradigm can be seen with the `acir_ir` module. +//! +//! The brillig ir provides instructions and codegens. +//! The instructions are low level operations that are printed via debug_show. +//! They should emit few opcodes. Codegens on the other hand orchestrate the +//! low level instructions to emit the desired high level operation. pub(crate) mod artifact; pub(crate) mod brillig_variable; pub(crate) mod debug_show; pub(crate) mod registers; +mod codegen_binary; +mod codegen_calls; +mod codegen_control_flow; +mod codegen_intrinsic; +mod codegen_memory; +mod codegen_stack; mod entry_point; +mod instructions; -use crate::ssa::ir::dfg::CallStack; +pub(crate) use instructions::BrilligBinaryOp; -use self::{ - artifact::{BrilligArtifact, UnresolvedJumpLocation}, - brillig_variable::{BrilligArray, BrilligVariable, BrilligVector, SingleAddrVariable}, - registers::BrilligRegistersContext, -}; +use self::{artifact::BrilligArtifact, registers::BrilligRegistersContext}; +use crate::ssa::ir::dfg::CallStack; use acvm::{ - acir::brillig::{ - BinaryFieldOp, BinaryIntOp, BlackBoxOp, MemoryAddress, Opcode as BrilligOpcode, Value, - ValueOrArray, - }, - brillig_vm::brillig::HeapValueType, + acir::brillig::{MemoryAddress, Opcode as BrilligOpcode}, FieldElement, }; use debug_show::DebugShow; -use num_bigint::BigUint; -/// Integer arithmetic in Brillig is limited to 127 bit -/// integers. -/// -/// We could lift this in the future and have Brillig -/// do big integer arithmetic when it exceeds the field size -/// or we could have users re-implement big integer arithmetic -/// in Brillig. -/// Since constrained functions do not have this property, it -/// would mean that unconstrained functions will differ from -/// constrained functions in terms of syntax compatibility. -pub(crate) const BRILLIG_INTEGER_ARITHMETIC_BIT_SIZE: u32 = 127; /// The Brillig VM does not apply a limit to the memory address space, -/// As a convention, we take use 64 bits. This means that we assume that -/// memory has 2^64 memory slots. +/// As a convention, we take use 32 bits. This means that we assume that +/// memory has 2^32 memory slots. pub(crate) const BRILLIG_MEMORY_ADDRESSING_BIT_SIZE: u32 = 32; // Registers reserved in runtime for special purposes. pub(crate) enum ReservedRegisters { - /// This register stores the stack pointer. Allocations must be done after this pointer. - StackPointer = 0, + /// This register stores the free memory pointer. Allocations must be done after this pointer. + FreeMemoryPointer = 0, /// This register stores the previous stack pointer. The registers of the caller are stored here. PreviousStackPointer = 1, } @@ -65,9 +58,9 @@ impl ReservedRegisters { Self::NUM_RESERVED_REGISTERS } - /// Returns the stack pointer register. This will get used to allocate memory in runtime. - pub(crate) fn stack_pointer() -> MemoryAddress { - MemoryAddress::from(ReservedRegisters::StackPointer as usize) + /// Returns the free memory pointer register. This will get used to allocate memory in runtime. + pub(crate) fn free_memory_pointer() -> MemoryAddress { + MemoryAddress::from(ReservedRegisters::FreeMemoryPointer as usize) } /// Returns the previous stack pointer register. This will be used to restore the registers after a fn call. @@ -96,6 +89,8 @@ pub(crate) struct BrilligContext { next_section: usize, /// IR printer debug_show: DebugShow, + /// Counter for generating bigint ids in unconstrained functions + bigint_new_id: u32, } impl BrilligContext { @@ -108,15 +103,17 @@ impl BrilligContext { section_label: 0, next_section: 1, debug_show: DebugShow::new(enable_debug_trace), + bigint_new_id: 0, } } - pub(crate) fn set_allocated_registers(&mut self, allocated_registers: Vec) { - self.registers = BrilligRegistersContext::from_preallocated_registers(allocated_registers); + pub(crate) fn get_new_bigint_id(&mut self) -> u32 { + let result = self.bigint_new_id; + self.bigint_new_id += 1; + result } - /// Adds a brillig instruction to the brillig byte code - pub(crate) fn push_opcode(&mut self, opcode: BrilligOpcode) { + fn push_opcode(&mut self, opcode: BrilligOpcode) { self.obj.push_opcode(opcode); } @@ -125,997 +122,36 @@ impl BrilligContext { self.obj } - /// Allocates an array of size `size` and stores the pointer to the array - /// in `pointer_register` - pub(crate) fn allocate_fixed_length_array( - &mut self, - pointer_register: MemoryAddress, - size: usize, - ) { - // debug_show handled by allocate_array_instruction - let size_register = self.make_usize_constant(size.into()); - self.allocate_array_instruction(pointer_register, size_register); - self.deallocate_register(size_register); - } - - /// Allocates an array of size contained in size_register and stores the - /// pointer to the array in `pointer_register` - pub(crate) fn allocate_array_instruction( - &mut self, - pointer_register: MemoryAddress, - size_register: MemoryAddress, - ) { - self.debug_show.allocate_array_instruction(pointer_register, size_register); - self.set_array_pointer(pointer_register); - self.update_stack_pointer(size_register); - } - - pub(crate) fn set_array_pointer(&mut self, pointer_register: MemoryAddress) { - self.debug_show.mov_instruction(pointer_register, ReservedRegisters::stack_pointer()); - self.push_opcode(BrilligOpcode::Mov { - destination: pointer_register, - source: ReservedRegisters::stack_pointer(), - }); - } - - pub(crate) fn update_stack_pointer(&mut self, size_register: MemoryAddress) { - self.memory_op( - ReservedRegisters::stack_pointer(), - size_register, - ReservedRegisters::stack_pointer(), - BinaryIntOp::Add, - ); - } - - /// Allocates a variable in memory and stores the - /// pointer to the array in `pointer_register` - fn allocate_variable_reference_instruction( - &mut self, - pointer_register: MemoryAddress, - size: usize, - ) { - self.debug_show.allocate_instruction(pointer_register); - // A variable can be stored in up to three values, so we reserve three values for that. - let size_register = self.make_usize_constant(size.into()); - self.push_opcode(BrilligOpcode::Mov { - destination: pointer_register, - source: ReservedRegisters::stack_pointer(), - }); - self.memory_op( - ReservedRegisters::stack_pointer(), - size_register, - ReservedRegisters::stack_pointer(), - BinaryIntOp::Add, - ); - self.deallocate_register(size_register); - } - - pub(crate) fn allocate_single_addr_reference_instruction( - &mut self, - pointer_register: MemoryAddress, - ) { - self.allocate_variable_reference_instruction(pointer_register, 1); - } - - pub(crate) fn allocate_array_reference_instruction(&mut self, pointer_register: MemoryAddress) { - self.allocate_variable_reference_instruction( - pointer_register, - BrilligArray::registers_count(), - ); - } - - pub(crate) fn allocate_vector_reference_instruction( - &mut self, - pointer_register: MemoryAddress, - ) { - self.allocate_variable_reference_instruction( - pointer_register, - BrilligVector::registers_count(), - ); - } - - /// Gets the value in the array at index `index` and stores it in `result` - pub(crate) fn array_get( - &mut self, - array_ptr: MemoryAddress, - index: MemoryAddress, - result: MemoryAddress, - ) { - self.debug_show.array_get(array_ptr, index, result); - // Computes array_ptr + index, ie array[index] - let index_of_element_in_memory = self.allocate_register(); - self.binary_instruction( - array_ptr, - index, - index_of_element_in_memory, - BrilligBinaryOp::Field { op: BinaryFieldOp::Add }, - ); - - self.load_instruction(result, index_of_element_in_memory); - // Free up temporary register - self.deallocate_register(index_of_element_in_memory); - } - - /// Sets the item in the array at index `index` to `value` - pub(crate) fn array_set( - &mut self, - array_ptr: MemoryAddress, - index: MemoryAddress, - value: MemoryAddress, - ) { - self.debug_show.array_set(array_ptr, index, value); - // Computes array_ptr + index, ie array[index] - let index_of_element_in_memory = self.allocate_register(); - self.binary_instruction( - array_ptr, - index, - index_of_element_in_memory, - BrilligBinaryOp::Field { op: BinaryFieldOp::Add }, - ); - - self.store_instruction(index_of_element_in_memory, value); - // Free up temporary register - self.deallocate_register(index_of_element_in_memory); - } - - /// Copies the values of an array pointed by source with length stored in `num_elements_register` - /// Into the array pointed by destination - pub(crate) fn copy_array_instruction( - &mut self, - source_pointer: MemoryAddress, - destination_pointer: MemoryAddress, - num_elements_register: MemoryAddress, - ) { - self.debug_show.copy_array_instruction( - source_pointer, - destination_pointer, - num_elements_register, - ); - - let value_register = self.allocate_register(); - - self.loop_instruction(num_elements_register, |ctx, iterator| { - ctx.array_get(source_pointer, iterator, value_register); - ctx.array_set(destination_pointer, iterator, value_register); - }); - - self.deallocate_register(value_register); - } - - /// This instruction will issue a loop that will iterate iteration_count times - /// The body of the loop should be issued by the caller in the on_iteration closure. - pub(crate) fn loop_instruction(&mut self, iteration_count: MemoryAddress, on_iteration: F) - where - F: FnOnce(&mut BrilligContext, MemoryAddress), - { - let iterator_register = self.make_usize_constant(0_u128.into()); - - let (loop_section, loop_label) = self.reserve_next_section_label(); - self.enter_section(loop_section); - - // Loop body - - // Check if iterator < iteration_count - let iterator_less_than_iterations = - SingleAddrVariable { address: self.allocate_register(), bit_size: 1 }; - - self.memory_op( - iterator_register, - iteration_count, - iterator_less_than_iterations.address, - BinaryIntOp::LessThan, - ); - - let (exit_loop_section, exit_loop_label) = self.reserve_next_section_label(); - - self.not_instruction(iterator_less_than_iterations, iterator_less_than_iterations); - - self.jump_if_instruction(iterator_less_than_iterations.address, exit_loop_label); - - // Call the on iteration function - on_iteration(self, iterator_register); - - // Increment the iterator register - self.usize_op_in_place(iterator_register, BinaryIntOp::Add, 1); - - self.jump_instruction(loop_label); - - // Exit the loop - self.enter_section(exit_loop_section); - - // Deallocate our temporary registers - self.deallocate_register(iterator_less_than_iterations.address); - self.deallocate_register(iterator_register); - } - - /// This instruction will issue an if-then branch that will check if the condition is true - /// and if so, perform the instructions given in `f(self, true)` and otherwise perform the - /// instructions given in `f(self, false)`. A boolean is passed instead of two separate - /// functions to allow the given function to mutably alias its environment. - pub(crate) fn branch_instruction( - &mut self, - condition: MemoryAddress, - mut f: impl FnMut(&mut BrilligContext, bool), - ) { - // Reserve 3 sections - let (then_section, then_label) = self.reserve_next_section_label(); - let (otherwise_section, otherwise_label) = self.reserve_next_section_label(); - let (end_section, end_label) = self.reserve_next_section_label(); - - self.jump_if_instruction(condition, then_label.clone()); - self.jump_instruction(otherwise_label.clone()); - - self.enter_section(then_section); - f(self, true); - self.jump_instruction(end_label.clone()); - - self.enter_section(otherwise_section); - f(self, false); - self.jump_instruction(end_label.clone()); - - self.enter_section(end_section); - } - - /// Adds a label to the next opcode - pub(crate) fn enter_context(&mut self, label: T) { - self.debug_show.enter_context(label.to_string()); - self.context_label = label.to_string(); - self.section_label = 0; - // Add a context label to the next opcode - self.obj.add_label_at_position(label.to_string(), self.obj.index_of_next_opcode()); - // Add a section label to the next opcode - self.obj - .add_label_at_position(self.current_section_label(), self.obj.index_of_next_opcode()); - } - - /// Enter the given section - fn enter_section(&mut self, section: usize) { - self.section_label = section; - self.obj - .add_label_at_position(self.current_section_label(), self.obj.index_of_next_opcode()); - } - - /// Create, reserve, and return a new section label. - fn reserve_next_section_label(&mut self) -> (usize, String) { - let section = self.next_section; - self.next_section += 1; - (section, self.compute_section_label(section)) - } - - /// Internal function used to compute the section labels - fn compute_section_label(&self, section: usize) -> String { - format!("{}-{}", self.context_label, section) - } - - /// Returns the current section label - fn current_section_label(&self) -> String { - self.compute_section_label(self.section_label) - } - - /// Adds a unresolved `Jump` instruction to the bytecode. - pub(crate) fn jump_instruction(&mut self, target_label: T) { - self.debug_show.jump_instruction(target_label.to_string()); - self.add_unresolved_jump(BrilligOpcode::Jump { location: 0 }, target_label.to_string()); - } - - /// Adds a unresolved `JumpIf` instruction to the bytecode. - pub(crate) fn jump_if_instruction( - &mut self, - condition: MemoryAddress, - target_label: T, - ) { - self.debug_show.jump_if_instruction(condition, target_label.to_string()); - self.add_unresolved_jump( - BrilligOpcode::JumpIf { condition, location: 0 }, - target_label.to_string(), - ); - } - - /// Adds a unresolved `Jump` instruction to the bytecode. - fn add_unresolved_jump( - &mut self, - jmp_instruction: BrilligOpcode, - destination: UnresolvedJumpLocation, - ) { - self.obj.add_unresolved_jump(jmp_instruction, destination); - } - - /// Allocates an unused register. - pub(crate) fn allocate_register(&mut self) -> MemoryAddress { - self.registers.allocate_register() - } - - /// Push a register to the deallocation list, ready for reuse. - /// TODO(AD): currently, register deallocation is only done with immediate values. - /// TODO(AD): See https://github.com/noir-lang/noir/issues/1720 - pub(crate) fn deallocate_register(&mut self, register_index: MemoryAddress) { - self.registers.deallocate_register(register_index); - } -} - -impl BrilligContext { - /// Emits brillig bytecode to jump to a trap condition if `condition` - /// is false. - pub(crate) fn constrain_instruction( - &mut self, - condition: MemoryAddress, - assert_message: Option, - ) { - self.debug_show.constrain_instruction(condition); - let (next_section, next_label) = self.reserve_next_section_label(); - self.add_unresolved_jump(BrilligOpcode::JumpIf { condition, location: 0 }, next_label); - self.push_opcode(BrilligOpcode::Trap); - if let Some(assert_message) = assert_message { - self.obj.add_assert_message_to_last_opcode(assert_message); - } - self.enter_section(next_section); - } - - /// Processes a return instruction. - /// - /// For Brillig, the return is implicit, since there is no explicit return instruction. - /// The caller will take `N` values from the Register starting at register index 0. - /// `N` indicates the number of return values expected. - /// - /// Brillig does not have an explicit return instruction, so this - /// method will move all register values to the first `N` values in - /// the VM. - pub(crate) fn return_instruction(&mut self, return_registers: &[MemoryAddress]) { - self.debug_show.return_instruction(return_registers); - let mut sources = Vec::with_capacity(return_registers.len()); - let mut destinations = Vec::with_capacity(return_registers.len()); - - for (destination_index, return_register) in return_registers.iter().enumerate() { - // In case we have fewer return registers than indices to write to, ensure we've allocated this register - let destination_register = ReservedRegisters::user_register_index(destination_index); - self.registers.ensure_register_is_allocated(destination_register); - sources.push(*return_register); - destinations.push(destination_register); - } - destinations - .iter() - .for_each(|destination| self.registers.ensure_register_is_allocated(*destination)); - self.mov_registers_to_registers_instruction(sources, destinations); - self.stop_instruction(); - } - - /// This function moves values from a set of registers to another set of registers. - /// It first moves all sources to new allocated registers to avoid overwriting. - pub(crate) fn mov_registers_to_registers_instruction( - &mut self, - sources: Vec, - destinations: Vec, - ) { - let new_sources: Vec<_> = sources - .iter() - .map(|source| { - let new_source = self.allocate_register(); - self.mov_instruction(new_source, *source); - new_source - }) - .collect(); - for (new_source, destination) in new_sources.iter().zip(destinations.iter()) { - self.mov_instruction(*destination, *new_source); - self.deallocate_register(*new_source); - } - } - - /// Emits a `mov` instruction. - /// - /// Copies the value at `source` into `destination` - pub(crate) fn mov_instruction(&mut self, destination: MemoryAddress, source: MemoryAddress) { - self.debug_show.mov_instruction(destination, source); - self.push_opcode(BrilligOpcode::Mov { destination, source }); - } - - /// Cast truncates the value to the given bit size and converts the type of the value in memory to that bit size. - pub(crate) fn cast_instruction( - &mut self, - destination: SingleAddrVariable, - source: SingleAddrVariable, - ) { - self.debug_show.cast_instruction(destination.address, source.address, destination.bit_size); - self.push_opcode(BrilligOpcode::Cast { - destination: destination.address, - source: source.address, - bit_size: destination.bit_size, - }); - } - - /// Processes a binary instruction according `operation`. - /// - /// This method will compute lhs rhs - /// and store the result in the `result` register. - pub(crate) fn binary_instruction( - &mut self, - lhs: MemoryAddress, - rhs: MemoryAddress, - result: MemoryAddress, - operation: BrilligBinaryOp, - ) { - self.debug_show.binary_instruction(lhs, rhs, result, operation.clone()); - match operation { - BrilligBinaryOp::Field { op } => { - let opcode = BrilligOpcode::BinaryFieldOp { op, destination: result, lhs, rhs }; - self.push_opcode(opcode); - } - BrilligBinaryOp::Integer { op, bit_size } => { - let opcode = - BrilligOpcode::BinaryIntOp { op, destination: result, bit_size, lhs, rhs }; - self.push_opcode(opcode); - } - BrilligBinaryOp::Modulo { is_signed_integer, bit_size } => { - self.modulo_instruction(result, lhs, rhs, bit_size, is_signed_integer); - } - } - } - - /// Stores the value of `constant` in the `result` register - pub(crate) fn const_instruction( - &mut self, - result: MemoryAddress, - constant: Value, - bit_size: u32, - ) { - self.debug_show.const_instruction(result, constant); - self.push_opcode(BrilligOpcode::Const { destination: result, value: constant, bit_size }); - } - - pub(crate) fn usize_const(&mut self, result: MemoryAddress, constant: Value) { - self.const_instruction(result, constant, BRILLIG_MEMORY_ADDRESSING_BIT_SIZE); - } - - /// Processes a not instruction. - /// - /// Not is computed using a subtraction operation as there is no native not instruction - /// in Brillig. - pub(crate) fn not_instruction( - &mut self, - input: SingleAddrVariable, - result: SingleAddrVariable, - ) { - self.debug_show.not_instruction(input.address, input.bit_size, result.address); - // Compile !x as ((-1) - x) - let u_max = FieldElement::from(2_i128).pow(&FieldElement::from(input.bit_size as i128)) - - FieldElement::one(); - let max = self.make_constant(Value::from(u_max), input.bit_size); - let opcode = BrilligOpcode::BinaryIntOp { - destination: result.address, - op: BinaryIntOp::Sub, - bit_size: input.bit_size, - lhs: max, - rhs: input.address, - }; - self.push_opcode(opcode); - self.deallocate_register(max); - } - - /// Processes a foreign call instruction. - /// - /// Note: the function being called is external and will - /// not be linked during brillig generation. - pub(crate) fn foreign_call_instruction( - &mut self, - func_name: String, - inputs: &[ValueOrArray], - input_value_types: &[HeapValueType], - outputs: &[ValueOrArray], - output_value_types: &[HeapValueType], - ) { - assert!(inputs.len() == input_value_types.len()); - assert!(outputs.len() == output_value_types.len()); - self.debug_show.foreign_call_instruction(func_name.clone(), inputs, outputs); - let opcode = BrilligOpcode::ForeignCall { - function: func_name, - destinations: outputs.to_vec(), - destination_value_types: output_value_types.to_vec(), - inputs: inputs.to_vec(), - input_value_types: input_value_types.to_vec(), - }; - self.push_opcode(opcode); - } - - /// Emits a load instruction - pub(crate) fn load_instruction( - &mut self, - destination: MemoryAddress, - source_pointer: MemoryAddress, - ) { - self.debug_show.load_instruction(destination, source_pointer); - self.push_opcode(BrilligOpcode::Load { destination, source_pointer }); - } - - /// Loads a variable stored previously - pub(crate) fn load_variable_instruction( - &mut self, - destination: BrilligVariable, - variable_pointer: MemoryAddress, - ) { - match destination { - BrilligVariable::SingleAddr(single_addr) => { - self.load_instruction(single_addr.address, variable_pointer); - } - BrilligVariable::BrilligArray(BrilligArray { pointer, size: _, rc }) => { - self.load_instruction(pointer, variable_pointer); - - let rc_pointer = self.allocate_register(); - self.mov_instruction(rc_pointer, variable_pointer); - self.usize_op_in_place(rc_pointer, BinaryIntOp::Add, 1_usize); - - self.load_instruction(rc, rc_pointer); - self.deallocate_register(rc_pointer); - } - BrilligVariable::BrilligVector(BrilligVector { pointer, size, rc }) => { - self.load_instruction(pointer, variable_pointer); - - let size_pointer = self.allocate_register(); - self.mov_instruction(size_pointer, variable_pointer); - self.usize_op_in_place(size_pointer, BinaryIntOp::Add, 1_usize); - - self.load_instruction(size, size_pointer); - self.deallocate_register(size_pointer); - - let rc_pointer = self.allocate_register(); - self.mov_instruction(rc_pointer, variable_pointer); - self.usize_op_in_place(rc_pointer, BinaryIntOp::Add, 2_usize); - - self.load_instruction(rc, rc_pointer); - self.deallocate_register(rc_pointer); - } - } - } - - /// Emits a store instruction - pub(crate) fn store_instruction( - &mut self, - destination_pointer: MemoryAddress, - source: MemoryAddress, - ) { - self.debug_show.store_instruction(destination_pointer, source); - self.push_opcode(BrilligOpcode::Store { destination_pointer, source }); - } - - /// Stores a variable by saving its registers to memory - pub(crate) fn store_variable_instruction( - &mut self, - variable_pointer: MemoryAddress, - source: BrilligVariable, - ) { - match source { - BrilligVariable::SingleAddr(single_addr) => { - self.store_instruction(variable_pointer, single_addr.address); - } - BrilligVariable::BrilligArray(BrilligArray { pointer, size: _, rc }) => { - self.store_instruction(variable_pointer, pointer); - - let rc_pointer: MemoryAddress = self.allocate_register(); - self.mov_instruction(rc_pointer, variable_pointer); - self.usize_op_in_place(rc_pointer, BinaryIntOp::Add, 1_usize); - self.store_instruction(rc_pointer, rc); - self.deallocate_register(rc_pointer); - } - BrilligVariable::BrilligVector(BrilligVector { pointer, size, rc }) => { - self.store_instruction(variable_pointer, pointer); - - let size_pointer = self.allocate_register(); - self.mov_instruction(size_pointer, variable_pointer); - self.usize_op_in_place(size_pointer, BinaryIntOp::Add, 1_usize); - self.store_instruction(size_pointer, size); - - let rc_pointer: MemoryAddress = self.allocate_register(); - self.mov_instruction(rc_pointer, variable_pointer); - self.usize_op_in_place(rc_pointer, BinaryIntOp::Add, 2_usize); - self.store_instruction(rc_pointer, rc); - - self.deallocate_register(size_pointer); - self.deallocate_register(rc_pointer); - } - } - } - - /// Emits a truncate instruction. - /// - /// Note: Truncation is used as an optimization in the SSA IR - /// for the ACIR generation pass; ACIR gen does not overflow - /// on every integer operation since it would be in-efficient. - /// Instead truncation instructions are emitted as to when a - /// truncation should be done. - /// For Brillig, all integer operations will overflow as its cheap. - pub(crate) fn truncate_instruction( - &mut self, - destination_of_truncated_value: SingleAddrVariable, - value_to_truncate: SingleAddrVariable, - bit_size: u32, - ) { - self.debug_show.truncate_instruction( - destination_of_truncated_value.address, - value_to_truncate.address, - bit_size, - ); - assert!( - bit_size <= value_to_truncate.bit_size, - "tried to truncate to a bit size {} greater than the variable size {}", - bit_size, - value_to_truncate.bit_size - ); - - let mask = BigUint::from(2_u32).pow(bit_size) - BigUint::from(1_u32); - let mask_constant = self.make_constant( - FieldElement::from_be_bytes_reduce(&mask.to_bytes_be()).into(), - value_to_truncate.bit_size, - ); - - self.binary_instruction( - value_to_truncate.address, - mask_constant, - destination_of_truncated_value.address, - BrilligBinaryOp::Integer { op: BinaryIntOp::And, bit_size: value_to_truncate.bit_size }, - ); - - self.deallocate_register(mask_constant); - } - - /// Emits a stop instruction - pub(crate) fn stop_instruction(&mut self) { - self.debug_show.stop_instruction(); - self.push_opcode(BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 0 }); - } - - /// Returns a register which holds the value of a constant - pub(crate) fn make_constant(&mut self, constant: Value, bit_size: u32) -> MemoryAddress { - let register = self.allocate_register(); - self.const_instruction(register, constant, bit_size); - register - } - - /// Returns a register which holds the value of an usize constant - pub(crate) fn make_usize_constant(&mut self, constant: Value) -> MemoryAddress { - let register = self.allocate_register(); - self.usize_const(register, constant); - register - } - - /// Computes left % right by emitting the necessary Brillig opcodes. - /// - /// This is done by using the following formula: - /// - /// a % b = a - (b * (a / b)) - /// - /// Brillig does not have an explicit modulo operation, - /// so we must emit multiple opcodes and process it differently - /// to other binary instructions. - pub(crate) fn modulo_instruction( - &mut self, - result_register: MemoryAddress, - left: MemoryAddress, - right: MemoryAddress, - bit_size: u32, - signed: bool, - ) { - // no debug_show, shown in binary instruction - let scratch_register_i = self.allocate_register(); - let scratch_register_j = self.allocate_register(); - - // i = left / right - self.push_opcode(BrilligOpcode::BinaryIntOp { - op: match signed { - true => BinaryIntOp::SignedDiv, - false => BinaryIntOp::UnsignedDiv, - }, - destination: scratch_register_i, - bit_size, - lhs: left, - rhs: right, - }); - - // j = i * right - self.push_opcode(BrilligOpcode::BinaryIntOp { - op: BinaryIntOp::Mul, - destination: scratch_register_j, - bit_size, - lhs: scratch_register_i, - rhs: right, - }); - - // result_register = left - j - self.push_opcode(BrilligOpcode::BinaryIntOp { - op: BinaryIntOp::Sub, - destination: result_register, - bit_size, - lhs: left, - rhs: scratch_register_j, - }); - // Free scratch registers - self.deallocate_register(scratch_register_i); - self.deallocate_register(scratch_register_j); - } - - /// Adds a unresolved external `Call` instruction to the bytecode. - /// This calls into another function compiled into this brillig artifact. - pub(crate) fn add_external_call_instruction(&mut self, func_label: T) { - self.debug_show.add_external_call_instruction(func_label.to_string()); - self.obj.add_unresolved_external_call( - BrilligOpcode::Call { location: 0 }, - func_label.to_string(), - ); - } - - /// Returns the i'th register after the reserved ones - pub(crate) fn register(&self, i: usize) -> MemoryAddress { - MemoryAddress::from(ReservedRegisters::NUM_RESERVED_REGISTERS + i) - } - - /// Saves all of the registers that have been used up until this point. - fn save_registers_of_vars(&mut self, vars: &[BrilligVariable]) -> Vec { - // Save all of the used registers at this point in memory - // because the function call will/may overwrite them. - // - // Note that here it is important that the stack pointer register is at register 0, - // as after the first register save we add to the pointer. - let mut used_registers: Vec<_> = - vars.iter().flat_map(|var| var.extract_registers()).collect(); - - // Also dump the previous stack pointer - used_registers.push(ReservedRegisters::previous_stack_pointer()); - for register in used_registers.iter() { - self.store_instruction(ReservedRegisters::stack_pointer(), *register); - // Add one to our stack pointer - self.usize_op_in_place(ReservedRegisters::stack_pointer(), BinaryIntOp::Add, 1); - } - - // Store the location of our registers in the previous stack pointer - self.mov_instruction( - ReservedRegisters::previous_stack_pointer(), - ReservedRegisters::stack_pointer(), - ); - used_registers - } - - /// Loads all of the registers that have been save by save_all_used_registers. - fn load_all_saved_registers(&mut self, used_registers: &[MemoryAddress]) { - // Load all of the used registers that we saved. - // We do all the reverse operations of save_all_used_registers. - // Iterate our registers in reverse - let iterator_register = self.allocate_register(); - self.mov_instruction(iterator_register, ReservedRegisters::previous_stack_pointer()); - - for register in used_registers.iter().rev() { - // Subtract one from our stack pointer - self.usize_op_in_place(iterator_register, BinaryIntOp::Sub, 1); - self.load_instruction(*register, iterator_register); - } - } - - /// Utility method to perform a binary instruction with a constant value in place - pub(crate) fn usize_op_in_place( - &mut self, - destination: MemoryAddress, - op: BinaryIntOp, - constant: usize, - ) { - self.usize_op(destination, destination, op, constant); - } - - /// Utility method to perform a binary instruction with a constant value - pub(crate) fn usize_op( - &mut self, - operand: MemoryAddress, - destination: MemoryAddress, - op: BinaryIntOp, - constant: usize, - ) { - let const_register = self.make_usize_constant(Value::from(constant)); - self.memory_op(operand, const_register, destination, op); - // Mark as no longer used for this purpose, frees for reuse - self.deallocate_register(const_register); - } - - /// Utility method to perform a binary instruction with a memory address - pub(crate) fn memory_op( - &mut self, - lhs: MemoryAddress, - rhs: MemoryAddress, - destination: MemoryAddress, - op: BinaryIntOp, - ) { - self.binary_instruction( - lhs, - rhs, - destination, - BrilligBinaryOp::Integer { op, bit_size: BRILLIG_MEMORY_ADDRESSING_BIT_SIZE }, - ); - } - - // Used before a call instruction. - // Save all the registers we have used to the stack. - // Move argument values to the front of the register indices. - pub(crate) fn pre_call_save_registers_prep_args( - &mut self, - arguments: &[MemoryAddress], - variables_to_save: &[BrilligVariable], - ) -> Vec { - // Save all the registers we have used to the stack. - let saved_registers = self.save_registers_of_vars(variables_to_save); - - // Move argument values to the front of the registers - // - // This means that the arguments will be in the first `n` registers after - // the number of reserved registers. - let (sources, destinations): (Vec<_>, Vec<_>) = - arguments.iter().enumerate().map(|(i, argument)| (*argument, self.register(i))).unzip(); - destinations - .iter() - .for_each(|destination| self.registers.ensure_register_is_allocated(*destination)); - self.mov_registers_to_registers_instruction(sources, destinations); - saved_registers - } - - // Used after a call instruction. - // Move return values to the front of the register indices. - // Load all the registers we have previous saved in save_registers_prep_args. - pub(crate) fn post_call_prep_returns_load_registers( - &mut self, - result_registers: &[MemoryAddress], - saved_registers: &[MemoryAddress], - ) { - // Allocate our result registers and write into them - // We assume the return values of our call are held in 0..num results register indices - let (sources, destinations): (Vec<_>, Vec<_>) = result_registers - .iter() - .enumerate() - .map(|(i, result_register)| (self.register(i), *result_register)) - .unzip(); - sources.iter().for_each(|source| self.registers.ensure_register_is_allocated(*source)); - self.mov_registers_to_registers_instruction(sources, destinations); - - // Restore all the same registers we have, in exact reverse order. - // Note that we have allocated some registers above, which we will not be handling here, - // only restoring registers that were used prior to the call finishing. - // After the call instruction, the stack frame pointer should be back to where we left off, - // so we do our instructions in reverse order. - self.load_all_saved_registers(saved_registers); - } - - /// Utility method to transform a HeapArray to a HeapVector by making a runtime constant with the size. - pub(crate) fn array_to_vector(&mut self, array: &BrilligArray) -> BrilligVector { - let size_register = self.make_usize_constant(array.size.into()); - BrilligVector { size: size_register, pointer: array.pointer, rc: array.rc } - } - - /// Issues a blackbox operation. - pub(crate) fn black_box_op_instruction(&mut self, op: BlackBoxOp) { - self.debug_show.black_box_op_instruction(&op); - self.push_opcode(BrilligOpcode::BlackBox(op)); - } - - /// Issues a to_radix instruction. This instruction will write the modulus of the source register - /// And the radix register limb_count times to the target vector. - pub(crate) fn radix_instruction( - &mut self, - source: MemoryAddress, - target_vector: BrilligVector, - radix: MemoryAddress, - limb_count: MemoryAddress, - big_endian: bool, - ) { - self.mov_instruction(target_vector.size, limb_count); - self.usize_const(target_vector.rc, 1_usize.into()); - self.allocate_array_instruction(target_vector.pointer, target_vector.size); - - let shifted_register = self.allocate_register(); - self.mov_instruction(shifted_register, source); - - let modulus_register: MemoryAddress = self.allocate_register(); - - self.loop_instruction(target_vector.size, |ctx, iterator_register| { - // Compute the modulus - ctx.modulo_instruction( - modulus_register, - shifted_register, - radix, - FieldElement::max_num_bits(), - false, - ); - // Write it - ctx.array_set(target_vector.pointer, iterator_register, modulus_register); - // Integer div the field - ctx.binary_instruction( - shifted_register, - radix, - shifted_register, - BrilligBinaryOp::Integer { - op: BinaryIntOp::UnsignedDiv, - bit_size: FieldElement::max_num_bits(), - }, - ); - }); - - // Deallocate our temporary registers - self.deallocate_register(shifted_register); - self.deallocate_register(modulus_register); - - if big_endian { - self.reverse_vector_in_place_instruction(target_vector); - } - } - - /// This instruction will reverse the order of the elements in a vector. - pub(crate) fn reverse_vector_in_place_instruction(&mut self, vector: BrilligVector) { - let iteration_count = self.allocate_register(); - self.usize_op(vector.size, iteration_count, BinaryIntOp::UnsignedDiv, 2); - - let start_value_register = self.allocate_register(); - let index_at_end_of_array = self.allocate_register(); - let end_value_register = self.allocate_register(); - - self.loop_instruction(iteration_count, |ctx, iterator_register| { - // Load both values - ctx.array_get(vector.pointer, iterator_register, start_value_register); - - // The index at the end of array is size - 1 - iterator - ctx.mov_instruction(index_at_end_of_array, vector.size); - ctx.usize_op_in_place(index_at_end_of_array, BinaryIntOp::Sub, 1); - ctx.memory_op( - index_at_end_of_array, - iterator_register, - index_at_end_of_array, - BinaryIntOp::Sub, - ); - - ctx.array_get(vector.pointer, index_at_end_of_array, end_value_register); - - // Write both values - ctx.array_set(vector.pointer, iterator_register, end_value_register); - ctx.array_set(vector.pointer, index_at_end_of_array, start_value_register); - }); - - self.deallocate_register(iteration_count); - self.deallocate_register(start_value_register); - self.deallocate_register(end_value_register); - self.deallocate_register(index_at_end_of_array); - } - /// Sets a current call stack that the next pushed opcodes will be associated with. pub(crate) fn set_call_stack(&mut self, call_stack: CallStack) { self.obj.set_call_stack(call_stack); } } -/// Type to encapsulate the binary operation types in Brillig -#[derive(Clone)] -pub(crate) enum BrilligBinaryOp { - Field { op: BinaryFieldOp }, - Integer { op: BinaryIntOp, bit_size: u32 }, - // Modulo operation requires more than one opcode - // Brillig. - Modulo { is_signed_integer: bool, bit_size: u32 }, -} - #[cfg(test)] pub(crate) mod tests { use std::vec; use acvm::acir::brillig::{ - BinaryIntOp, ForeignCallParam, ForeignCallResult, HeapVector, MemoryAddress, Value, - ValueOrArray, + ForeignCallParam, ForeignCallResult, HeapArray, HeapVector, MemoryAddress, ValueOrArray, }; use acvm::brillig_vm::brillig::HeapValueType; use acvm::brillig_vm::{VMStatus, VM}; use acvm::{BlackBoxFunctionSolver, BlackBoxResolutionError, FieldElement}; - use crate::brillig::brillig_ir::BrilligContext; + use crate::brillig::brillig_ir::{BrilligBinaryOp, BrilligContext}; use super::artifact::{BrilligParameter, GeneratedBrillig}; use super::{BrilligOpcode, ReservedRegisters}; pub(crate) struct DummyBlackBoxSolver; - impl BlackBoxFunctionSolver for DummyBlackBoxSolver { + impl BlackBoxFunctionSolver for DummyBlackBoxSolver { fn schnorr_verify( &self, _public_key_x: &FieldElement, _public_key_y: &FieldElement, - _signature: &[u8], + _signature: &[u8; 64], _message: &[u8], ) -> Result { Ok(true) @@ -1134,21 +170,24 @@ pub(crate) mod tests { ) -> Result { Ok(6_u128.into()) } - fn fixed_base_scalar_mul( + fn multi_scalar_mul( &self, - _low: &FieldElement, - _high: &FieldElement, - ) -> Result<(FieldElement, FieldElement), BlackBoxResolutionError> { - Ok((4_u128.into(), 5_u128.into())) + _points: &[FieldElement], + _scalars_lo: &[FieldElement], + _scalars_hi: &[FieldElement], + ) -> Result<(FieldElement, FieldElement, FieldElement), BlackBoxResolutionError> { + Ok((4_u128.into(), 5_u128.into(), 0_u128.into())) } fn ec_add( &self, _input1_x: &FieldElement, _input1_y: &FieldElement, + _input1_infinite: &FieldElement, _input2_x: &FieldElement, _input2_y: &FieldElement, - ) -> Result<(FieldElement, FieldElement), BlackBoxResolutionError> { + _input2_infinite: &FieldElement, + ) -> Result<(FieldElement, FieldElement, FieldElement), BlackBoxResolutionError> { panic!("Path not trodden by this test") } @@ -1180,9 +219,9 @@ pub(crate) mod tests { } pub(crate) fn create_and_run_vm( - calldata: Vec, - bytecode: &[BrilligOpcode], - ) -> (VM<'_, DummyBlackBoxSolver>, usize, usize) { + calldata: Vec, + bytecode: &[BrilligOpcode], + ) -> (VM<'_, FieldElement, DummyBlackBoxSolver>, usize, usize) { let mut vm = VM::new(calldata, bytecode, vec![], &DummyBlackBoxSolver); let status = vm.process_opcodes(); @@ -1207,37 +246,43 @@ pub(crate) mod tests { // assert(the_sequence.len() == 12); // } let mut context = BrilligContext::new(true); - let r_stack = ReservedRegisters::stack_pointer(); + let r_stack = ReservedRegisters::free_memory_pointer(); // Start stack pointer at 0 - context.usize_const(r_stack, Value::from(ReservedRegisters::len() + 3)); + context.usize_const_instruction(r_stack, FieldElement::from(ReservedRegisters::len() + 3)); let r_input_size = MemoryAddress::from(ReservedRegisters::len()); let r_array_ptr = MemoryAddress::from(ReservedRegisters::len() + 1); let r_output_size = MemoryAddress::from(ReservedRegisters::len() + 2); let r_equality = MemoryAddress::from(ReservedRegisters::len() + 3); - context.usize_const(r_input_size, Value::from(12_usize)); + context.usize_const_instruction(r_input_size, FieldElement::from(12_usize)); // copy our stack frame to r_array_ptr context.mov_instruction(r_array_ptr, r_stack); context.foreign_call_instruction( "make_number_sequence".into(), &[ValueOrArray::MemoryAddress(r_input_size)], - &[HeapValueType::Simple], + &[HeapValueType::Simple(32)], &[ValueOrArray::HeapVector(HeapVector { pointer: r_stack, size: r_output_size })], - &[HeapValueType::Vector { value_types: vec![HeapValueType::Simple] }], + &[HeapValueType::Vector { value_types: vec![HeapValueType::Simple(32)] }], ); // push stack frame by r_returned_size - context.memory_op(r_stack, r_output_size, r_stack, BinaryIntOp::Add); + context.memory_op_instruction(r_stack, r_output_size, r_stack, BrilligBinaryOp::Add); // check r_input_size == r_output_size - context.memory_op(r_input_size, r_output_size, r_equality, BinaryIntOp::Equals); + context.memory_op_instruction( + r_input_size, + r_output_size, + r_equality, + BrilligBinaryOp::Equals, + ); // We push a JumpIf and Trap opcode directly as the constrain instruction // uses unresolved jumps which requires a block to be constructed in SSA and // we don't need this for Brillig IR tests context.push_opcode(BrilligOpcode::JumpIf { condition: r_equality, location: 8 }); - context.push_opcode(BrilligOpcode::Trap); + context.push_opcode(BrilligOpcode::Trap { revert_data: HeapArray::default() }); context.stop_instruction(); - let bytecode = context.artifact().finish().byte_code; - let number_sequence: Vec = (0_usize..12_usize).map(Value::from).collect(); + let bytecode: Vec> = context.artifact().finish().byte_code; + let number_sequence: Vec = + (0_usize..12_usize).map(FieldElement::from).collect(); let mut vm = VM::new( vec![], &bytecode, diff --git a/compiler/noirc_evaluator/src/brillig/brillig_ir/artifact.rs b/compiler/noirc_evaluator/src/brillig/brillig_ir/artifact.rs index d10dcf13d9f..99e922c1580 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_ir/artifact.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_ir/artifact.rs @@ -1,24 +1,25 @@ -use acvm::acir::brillig::Opcode as BrilligOpcode; +use acvm::{acir::brillig::Opcode as BrilligOpcode, FieldElement}; use std::collections::{BTreeMap, HashMap}; use crate::ssa::ir::dfg::CallStack; -/// Represents a parameter or a return value of a function. -#[derive(Debug, Clone)] +/// Represents a parameter or a return value of an entry point function. +#[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)] pub(crate) enum BrilligParameter { /// A single address parameter or return value. Holds the bit size of the parameter. SingleAddr(u32), /// An array parameter or return value. Holds the type of an array item and its size. Array(Vec, usize), /// A slice parameter or return value. Holds the type of a slice item. - Slice(Vec), + /// Only known-length slices can be passed to brillig entry points, so the size is available as well. + Slice(Vec, usize), } /// The result of compiling and linking brillig artifacts. /// This is ready to run bytecode with attached metadata. -#[derive(Debug)] +#[derive(Debug, Default)] pub(crate) struct GeneratedBrillig { - pub(crate) byte_code: Vec, + pub(crate) byte_code: Vec>, pub(crate) locations: BTreeMap, pub(crate) assert_messages: BTreeMap, } @@ -27,8 +28,10 @@ pub(crate) struct GeneratedBrillig { /// Artifacts resulting from the compilation of a function into brillig byte code. /// It includes the bytecode of the function and all the metadata that allows linking with other functions. pub(crate) struct BrilligArtifact { - pub(crate) byte_code: Vec, - /// A map of bytecode positions to assertion messages + pub(crate) byte_code: Vec>, + /// A map of bytecode positions to assertion messages. + /// Some error messages (compiler intrinsics) are not emitted via revert data, + /// instead, they are handled externally so they don't add size to user programs. pub(crate) assert_messages: BTreeMap, /// The set of jumps that need to have their locations /// resolved. @@ -108,7 +111,7 @@ impl BrilligArtifact { self.byte_code.append(&mut byte_code); // Remove all resolved external calls and transform them to jumps - let is_resolved = |label: &Label| self.labels.get(label).is_some(); + let is_resolved = |label: &Label| self.labels.contains_key(label); let resolved_external_calls = self .unresolved_external_call_labels @@ -151,7 +154,7 @@ impl BrilligArtifact { } /// Adds a brillig instruction to the brillig byte code - pub(crate) fn push_opcode(&mut self, opcode: BrilligOpcode) { + pub(crate) fn push_opcode(&mut self, opcode: BrilligOpcode) { if !self.call_stack.is_empty() { self.locations.insert(self.index_of_next_opcode(), self.call_stack.clone()); } @@ -161,7 +164,7 @@ impl BrilligArtifact { /// Adds a unresolved jump to be fixed at the end of bytecode processing. pub(crate) fn add_unresolved_jump( &mut self, - jmp_instruction: BrilligOpcode, + jmp_instruction: BrilligOpcode, destination: UnresolvedJumpLocation, ) { assert!( @@ -175,7 +178,7 @@ impl BrilligArtifact { /// Adds a unresolved external call that will be fixed once linking has been done. pub(crate) fn add_unresolved_external_call( &mut self, - call_instruction: BrilligOpcode, + call_instruction: BrilligOpcode, destination: UnresolvedJumpLocation, ) { // TODO: Add a check to ensure that the opcode is a call instruction @@ -185,7 +188,7 @@ impl BrilligArtifact { } /// Returns true if the opcode is a jump instruction - fn is_jmp_instruction(instruction: &BrilligOpcode) -> bool { + fn is_jmp_instruction(instruction: &BrilligOpcode) -> bool { matches!( instruction, BrilligOpcode::JumpIfNot { .. } diff --git a/compiler/noirc_evaluator/src/brillig/brillig_ir/brillig_variable.rs b/compiler/noirc_evaluator/src/brillig/brillig_ir/brillig_variable.rs index 48ad3c5bae4..cf1fd555191 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_ir/brillig_variable.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_ir/brillig_variable.rs @@ -1,16 +1,34 @@ -use acvm::brillig_vm::brillig::{ - HeapArray, HeapValueType, HeapVector, MemoryAddress, ValueOrArray, +use acvm::{ + acir::AcirField, + brillig_vm::brillig::{HeapArray, HeapValueType, HeapVector, MemoryAddress, ValueOrArray}, + FieldElement, }; use serde::{Deserialize, Serialize}; use crate::ssa::ir::types::Type; +use super::BRILLIG_MEMORY_ADDRESSING_BIT_SIZE; + #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Copy)] pub(crate) struct SingleAddrVariable { pub(crate) address: MemoryAddress, pub(crate) bit_size: u32, } +impl SingleAddrVariable { + pub(crate) fn new(address: MemoryAddress, bit_size: u32) -> Self { + SingleAddrVariable { address, bit_size } + } + + pub(crate) fn new_usize(address: MemoryAddress) -> Self { + SingleAddrVariable { address, bit_size: BRILLIG_MEMORY_ADDRESSING_BIT_SIZE } + } + + pub(crate) fn new_field(address: MemoryAddress) -> Self { + SingleAddrVariable { address, bit_size: FieldElement::max_num_bits() } + } +} + /// The representation of a noir array in the Brillig IR #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Copy)] pub(crate) struct BrilligArray { @@ -108,7 +126,9 @@ impl BrilligVariable { pub(crate) fn type_to_heap_value_type(typ: &Type) -> HeapValueType { match typ { - Type::Numeric(_) | Type::Reference(_) | Type::Function => HeapValueType::Simple, + Type::Numeric(_) | Type::Reference(_) | Type::Function => { + HeapValueType::Simple(get_bit_size_from_ssa_type(typ)) + } Type::Array(elem_type, size) => HeapValueType::Array { value_types: elem_type.as_ref().iter().map(type_to_heap_value_type).collect(), size: typ.element_size() * size, @@ -118,3 +138,14 @@ pub(crate) fn type_to_heap_value_type(typ: &Type) -> HeapValueType { }, } } + +pub(crate) fn get_bit_size_from_ssa_type(typ: &Type) -> u32 { + match typ { + Type::Reference(_) => BRILLIG_MEMORY_ADDRESSING_BIT_SIZE, + // NB. function references are converted to a constant when + // translating from SSA to Brillig (to allow for debugger + // instrumentation to work properly) + Type::Function => 32, + typ => typ.bit_size(), + } +} diff --git a/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_binary.rs b/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_binary.rs new file mode 100644 index 00000000000..4ef279bd532 --- /dev/null +++ b/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_binary.rs @@ -0,0 +1,29 @@ +use acvm::{acir::brillig::MemoryAddress, FieldElement}; + +use super::{instructions::BrilligBinaryOp, BrilligContext}; + +impl BrilligContext { + /// Utility method to perform a binary instruction with a constant value in place + pub(crate) fn codegen_usize_op_in_place( + &mut self, + destination: MemoryAddress, + op: BrilligBinaryOp, + constant: usize, + ) { + self.codegen_usize_op(destination, destination, op, constant); + } + + /// Utility method to perform a binary instruction with a constant value + pub(crate) fn codegen_usize_op( + &mut self, + operand: MemoryAddress, + destination: MemoryAddress, + op: BrilligBinaryOp, + constant: usize, + ) { + let const_register = self.make_usize_constant_instruction(FieldElement::from(constant)); + self.memory_op_instruction(operand, const_register.address, destination, op); + // Mark as no longer used for this purpose, frees for reuse + self.deallocate_single_addr(const_register); + } +} diff --git a/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_calls.rs b/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_calls.rs new file mode 100644 index 00000000000..db65849a6b8 --- /dev/null +++ b/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_calls.rs @@ -0,0 +1,102 @@ +use acvm::acir::brillig::MemoryAddress; + +use super::{ + brillig_variable::BrilligVariable, BrilligBinaryOp, BrilligContext, ReservedRegisters, +}; + +impl BrilligContext { + /// Saves all of the registers that have been used up until this point. + fn codegen_save_registers_of_vars(&mut self, vars: &[BrilligVariable]) -> Vec { + // Save all of the used registers at this point in memory + // because the function call will/may overwrite them. + // + // Note that here it is important that the stack pointer register is at register 0, + // as after the first register save we add to the pointer. + let mut used_registers: Vec<_> = + vars.iter().flat_map(|var| var.extract_registers()).collect(); + + // Also dump the previous stack pointer + used_registers.push(ReservedRegisters::previous_stack_pointer()); + for register in used_registers.iter() { + self.store_instruction(ReservedRegisters::free_memory_pointer(), *register); + // Add one to our stack pointer + self.codegen_usize_op_in_place( + ReservedRegisters::free_memory_pointer(), + BrilligBinaryOp::Add, + 1, + ); + } + + // Store the location of our registers in the previous stack pointer + self.mov_instruction( + ReservedRegisters::previous_stack_pointer(), + ReservedRegisters::free_memory_pointer(), + ); + used_registers + } + + /// Loads all of the registers that have been save by save_all_used_registers. + fn codegen_load_all_saved_registers(&mut self, used_registers: &[MemoryAddress]) { + // Load all of the used registers that we saved. + // We do all the reverse operations of save_all_used_registers. + // Iterate our registers in reverse + let iterator_register = self.allocate_register(); + self.mov_instruction(iterator_register, ReservedRegisters::previous_stack_pointer()); + + for register in used_registers.iter().rev() { + // Subtract one from our stack pointer + self.codegen_usize_op_in_place(iterator_register, BrilligBinaryOp::Sub, 1); + self.load_instruction(*register, iterator_register); + } + } + + // Used before a call instruction. + // Save all the registers we have used to the stack. + // Move argument values to the front of the register indices. + pub(crate) fn codegen_pre_call_save_registers_prep_args( + &mut self, + arguments: &[MemoryAddress], + variables_to_save: &[BrilligVariable], + ) -> Vec { + // Save all the registers we have used to the stack. + let saved_registers = self.codegen_save_registers_of_vars(variables_to_save); + + // Move argument values to the front of the registers + // + // This means that the arguments will be in the first `n` registers after + // the number of reserved registers. + let (sources, destinations): (Vec<_>, Vec<_>) = + arguments.iter().enumerate().map(|(i, argument)| (*argument, self.register(i))).unzip(); + destinations + .iter() + .for_each(|destination| self.registers.ensure_register_is_allocated(*destination)); + self.codegen_mov_registers_to_registers(sources, destinations); + saved_registers + } + + // Used after a call instruction. + // Move return values to the front of the register indices. + // Load all the registers we have previous saved in save_registers_prep_args. + pub(crate) fn codegen_post_call_prep_returns_load_registers( + &mut self, + result_registers: &[MemoryAddress], + saved_registers: &[MemoryAddress], + ) { + // Allocate our result registers and write into them + // We assume the return values of our call are held in 0..num results register indices + let (sources, destinations): (Vec<_>, Vec<_>) = result_registers + .iter() + .enumerate() + .map(|(i, result_register)| (self.register(i), *result_register)) + .unzip(); + sources.iter().for_each(|source| self.registers.ensure_register_is_allocated(*source)); + self.codegen_mov_registers_to_registers(sources, destinations); + + // Restore all the same registers we have, in exact reverse order. + // Note that we have allocated some registers above, which we will not be handling here, + // only restoring registers that were used prior to the call finishing. + // After the call instruction, the stack frame pointer should be back to where we left off, + // so we do our instructions in reverse order. + self.codegen_load_all_saved_registers(saved_registers); + } +} diff --git a/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_control_flow.rs b/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_control_flow.rs new file mode 100644 index 00000000000..fee3a450119 --- /dev/null +++ b/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_control_flow.rs @@ -0,0 +1,223 @@ +use acvm::acir::brillig::{HeapArray, MemoryAddress}; + +use super::{ + artifact::BrilligParameter, + brillig_variable::{BrilligVariable, SingleAddrVariable}, + BrilligBinaryOp, BrilligContext, ReservedRegisters, +}; + +impl BrilligContext { + /// Codegens a return from the current function. + /// + /// For Brillig, the return is implicit, since there is no explicit return instruction. + /// The caller will take `N` values from the Register starting at register index 0. + /// `N` indicates the number of return values expected. + /// + /// Brillig does not have an explicit return instruction, so this + /// method will move all register values to the first `N` values in + /// the VM. + pub(crate) fn codegen_return(&mut self, return_registers: &[MemoryAddress]) { + let mut sources = Vec::with_capacity(return_registers.len()); + let mut destinations = Vec::with_capacity(return_registers.len()); + + for (destination_index, return_register) in return_registers.iter().enumerate() { + // In case we have fewer return registers than indices to write to, ensure we've allocated this register + let destination_register = ReservedRegisters::user_register_index(destination_index); + self.registers.ensure_register_is_allocated(destination_register); + sources.push(*return_register); + destinations.push(destination_register); + } + destinations + .iter() + .for_each(|destination| self.registers.ensure_register_is_allocated(*destination)); + self.codegen_mov_registers_to_registers(sources, destinations); + self.stop_instruction(); + } + + /// This codegen will issue a loop that will iterate iteration_count times + /// The body of the loop should be issued by the caller in the on_iteration closure. + pub(crate) fn codegen_loop(&mut self, iteration_count: MemoryAddress, on_iteration: F) + where + F: FnOnce(&mut BrilligContext, SingleAddrVariable), + { + let iterator_register = self.make_usize_constant_instruction(0_u128.into()); + + let (loop_section, loop_label) = self.reserve_next_section_label(); + self.enter_section(loop_section); + + // Loop body + + // Check if iterator < iteration_count + let iterator_less_than_iterations = + SingleAddrVariable { address: self.allocate_register(), bit_size: 1 }; + + self.memory_op_instruction( + iterator_register.address, + iteration_count, + iterator_less_than_iterations.address, + BrilligBinaryOp::LessThan, + ); + + let (exit_loop_section, exit_loop_label) = self.reserve_next_section_label(); + + self.not_instruction(iterator_less_than_iterations, iterator_less_than_iterations); + + self.jump_if_instruction(iterator_less_than_iterations.address, exit_loop_label); + + // Call the on iteration function + on_iteration(self, iterator_register); + + // Increment the iterator register + self.codegen_usize_op_in_place(iterator_register.address, BrilligBinaryOp::Add, 1); + + self.jump_instruction(loop_label); + + // Exit the loop + self.enter_section(exit_loop_section); + + // Deallocate our temporary registers + self.deallocate_single_addr(iterator_less_than_iterations); + self.deallocate_single_addr(iterator_register); + } + + /// This codegen will issue an if-then branch that will check if the condition is true + /// and if so, perform the instructions given in `f(self, true)` and otherwise perform the + /// instructions given in `f(self, false)`. A boolean is passed instead of two separate + /// functions to allow the given function to mutably alias its environment. + pub(crate) fn codegen_branch( + &mut self, + condition: MemoryAddress, + mut f: impl FnMut(&mut BrilligContext, bool), + ) { + // Reserve 3 sections + let (then_section, then_label) = self.reserve_next_section_label(); + let (otherwise_section, otherwise_label) = self.reserve_next_section_label(); + let (end_section, end_label) = self.reserve_next_section_label(); + + self.jump_if_instruction(condition, then_label.clone()); + self.jump_instruction(otherwise_label.clone()); + + self.enter_section(then_section); + f(self, true); + self.jump_instruction(end_label.clone()); + + self.enter_section(otherwise_section); + f(self, false); + self.jump_instruction(end_label.clone()); + + self.enter_section(end_section); + } + + /// This codegen issues a branch that jumps over the code generated by the given function if the condition is false + pub(crate) fn codegen_if( + &mut self, + condition: MemoryAddress, + f: impl FnOnce(&mut BrilligContext), + ) { + let (end_section, end_label) = self.reserve_next_section_label(); + let (then_section, then_label) = self.reserve_next_section_label(); + + self.jump_if_instruction(condition, then_label.clone()); + self.jump_instruction(end_label.clone()); + + self.enter_section(then_section); + f(self); + + self.enter_section(end_section); + } + + /// This codegen issues a branch that jumps over the code generated by the given function if the condition is truthy + pub(crate) fn codegen_if_not( + &mut self, + condition: MemoryAddress, + f: impl FnOnce(&mut BrilligContext), + ) { + let (end_section, end_label) = self.reserve_next_section_label(); + + self.jump_if_instruction(condition, end_label.clone()); + + f(self); + + self.enter_section(end_section); + } + + /// Emits brillig bytecode to jump to a trap condition if `condition` + /// is false. The trap will include the given message as revert data. + pub(crate) fn codegen_constrain_with_revert_data( + &mut self, + condition: SingleAddrVariable, + revert_data_items: Vec, + revert_data_types: Vec, + error_selector: u64, + ) { + assert!(condition.bit_size == 1); + + self.codegen_if_not(condition.address, |ctx| { + let revert_data = HeapArray { + pointer: ctx.allocate_register(), + // + 1 due to the revert data id being the first item returned + size: BrilligContext::flattened_tuple_size(&revert_data_types) + 1, + }; + ctx.codegen_allocate_fixed_length_array(revert_data.pointer, revert_data.size); + + let current_revert_data_pointer = ctx.allocate_register(); + ctx.mov_instruction(current_revert_data_pointer, revert_data.pointer); + let revert_data_id = ctx.make_constant_instruction((error_selector as u128).into(), 64); + ctx.store_instruction(current_revert_data_pointer, revert_data_id.address); + + ctx.codegen_usize_op_in_place(current_revert_data_pointer, BrilligBinaryOp::Add, 1); + for (revert_variable, revert_param) in + revert_data_items.into_iter().zip(revert_data_types.into_iter()) + { + let flattened_size = BrilligContext::flattened_size(&revert_param); + match revert_param { + BrilligParameter::SingleAddr(_) => { + ctx.store_instruction( + current_revert_data_pointer, + revert_variable.extract_single_addr().address, + ); + } + BrilligParameter::Array(item_type, item_count) => { + let variable_pointer = revert_variable.extract_array().pointer; + + ctx.flatten_array( + &item_type, + item_count, + current_revert_data_pointer, + variable_pointer, + ); + } + BrilligParameter::Slice(_, _) => { + unimplemented!("Slices are not supported as revert data") + } + } + ctx.codegen_usize_op_in_place( + current_revert_data_pointer, + BrilligBinaryOp::Add, + flattened_size, + ); + } + ctx.trap_instruction(revert_data); + ctx.deallocate_register(revert_data.pointer); + ctx.deallocate_register(current_revert_data_pointer); + ctx.deallocate_single_addr(revert_data_id); + }); + } + + /// Emits brillig bytecode to jump to a trap condition if `condition` + /// is false. + pub(crate) fn codegen_constrain( + &mut self, + condition: SingleAddrVariable, + assert_message: Option, + ) { + assert!(condition.bit_size == 1); + + self.codegen_if_not(condition.address, |ctx| { + ctx.trap_instruction(HeapArray::default()); + if let Some(assert_message) = assert_message { + ctx.obj.add_assert_message_to_last_opcode(assert_message); + } + }); + } +} diff --git a/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_intrinsic.rs b/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_intrinsic.rs new file mode 100644 index 00000000000..42f3b34aea0 --- /dev/null +++ b/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_intrinsic.rs @@ -0,0 +1,86 @@ +use acvm::{ + acir::brillig::{BlackBoxOp, HeapArray}, + acir::AcirField, + FieldElement, +}; + +use super::{ + brillig_variable::{BrilligVector, SingleAddrVariable}, + BrilligContext, +}; + +impl BrilligContext { + /// Codegens a truncation of a value to the given bit size + pub(crate) fn codegen_truncate( + &mut self, + destination_of_truncated_value: SingleAddrVariable, + value_to_truncate: SingleAddrVariable, + bit_size: u32, + ) { + assert!( + bit_size <= value_to_truncate.bit_size, + "tried to truncate to a bit size {} greater than the variable size {}", + bit_size, + value_to_truncate.bit_size + ); + + // We cast back and forth to ensure that the value is truncated. + let intermediate_register = + SingleAddrVariable { address: self.allocate_register(), bit_size }; + self.cast_instruction(intermediate_register, value_to_truncate); + self.cast_instruction(destination_of_truncated_value, intermediate_register); + self.deallocate_single_addr(intermediate_register); + } + + /// Issues a to_radix instruction. This instruction will write the modulus of the source register + /// And the radix register limb_count times to the target vector. + pub(crate) fn codegen_to_radix( + &mut self, + source_field: SingleAddrVariable, + target_vector: BrilligVector, + radix: u32, + limb_count: usize, + big_endian: bool, + limb_bit_size: u32, + ) { + assert!(source_field.bit_size == FieldElement::max_num_bits()); + + self.usize_const_instruction(target_vector.size, limb_count.into()); + self.usize_const_instruction(target_vector.rc, 1_usize.into()); + self.codegen_allocate_array(target_vector.pointer, target_vector.size); + + self.black_box_op_instruction(BlackBoxOp::ToRadix { + input: source_field.address, + radix, + output: HeapArray { pointer: target_vector.pointer, size: limb_count }, + }); + + let limb_field = + SingleAddrVariable::new(self.allocate_register(), FieldElement::max_num_bits()); + + let limb_casted = SingleAddrVariable::new(self.allocate_register(), limb_bit_size); + + if limb_bit_size != FieldElement::max_num_bits() { + self.codegen_loop(target_vector.size, |ctx, iterator_register| { + // Read the limb + ctx.codegen_array_get(target_vector.pointer, iterator_register, limb_field.address); + // Cast it + ctx.cast_instruction(limb_casted, limb_field); + // Write it + ctx.codegen_array_set( + target_vector.pointer, + iterator_register, + limb_casted.address, + ); + }); + } + + // Deallocate our temporary registers + self.deallocate_single_addr(limb_field); + self.deallocate_single_addr(limb_casted); + + if big_endian { + self.codegen_reverse_vector_in_place(target_vector); + } + } +} diff --git a/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_memory.rs b/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_memory.rs new file mode 100644 index 00000000000..15761113f51 --- /dev/null +++ b/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_memory.rs @@ -0,0 +1,255 @@ +use acvm::acir::brillig::MemoryAddress; + +use crate::brillig::brillig_ir::BrilligBinaryOp; + +use super::{ + brillig_variable::{BrilligArray, BrilligVariable, BrilligVector, SingleAddrVariable}, + BrilligContext, ReservedRegisters, BRILLIG_MEMORY_ADDRESSING_BIT_SIZE, +}; + +impl BrilligContext { + /// Allocates an array of size `size` and stores the pointer to the array + /// in `pointer_register` + pub(crate) fn codegen_allocate_fixed_length_array( + &mut self, + pointer_register: MemoryAddress, + size: usize, + ) { + let size_register = self.make_usize_constant_instruction(size.into()); + self.codegen_allocate_array(pointer_register, size_register.address); + self.deallocate_single_addr(size_register); + } + + /// Allocates an array of size contained in size_register and stores the + /// pointer to the array in `pointer_register` + pub(crate) fn codegen_allocate_array( + &mut self, + pointer_register: MemoryAddress, + size_register: MemoryAddress, + ) { + self.load_free_memory_pointer_instruction(pointer_register); + self.increase_free_memory_pointer_instruction(size_register); + } + + /// Allocates a variable in memory and stores the + /// pointer to the array in `pointer_register` + fn codegen_allocate_variable_reference( + &mut self, + pointer_register: MemoryAddress, + size: usize, + ) { + // A variable can be stored in up to three values, so we reserve three values for that. + let size_register = self.make_usize_constant_instruction(size.into()); + self.mov_instruction(pointer_register, ReservedRegisters::free_memory_pointer()); + self.memory_op_instruction( + ReservedRegisters::free_memory_pointer(), + size_register.address, + ReservedRegisters::free_memory_pointer(), + BrilligBinaryOp::Add, + ); + self.deallocate_single_addr(size_register); + } + + pub(crate) fn codegen_allocate_single_addr_reference( + &mut self, + pointer_register: MemoryAddress, + ) { + self.codegen_allocate_variable_reference(pointer_register, 1); + } + + pub(crate) fn codegen_allocate_array_reference(&mut self, pointer_register: MemoryAddress) { + self.codegen_allocate_variable_reference(pointer_register, BrilligArray::registers_count()); + } + + pub(crate) fn codegen_allocate_vector_reference(&mut self, pointer_register: MemoryAddress) { + self.codegen_allocate_variable_reference( + pointer_register, + BrilligVector::registers_count(), + ); + } + + /// Gets the value in the array at index `index` and stores it in `result` + pub(crate) fn codegen_array_get( + &mut self, + array_ptr: MemoryAddress, + index: SingleAddrVariable, + result: MemoryAddress, + ) { + assert!(index.bit_size == BRILLIG_MEMORY_ADDRESSING_BIT_SIZE); + // Computes array_ptr + index, ie array[index] + let index_of_element_in_memory = self.allocate_register(); + self.memory_op_instruction( + array_ptr, + index.address, + index_of_element_in_memory, + BrilligBinaryOp::Add, + ); + self.load_instruction(result, index_of_element_in_memory); + // Free up temporary register + self.deallocate_register(index_of_element_in_memory); + } + + /// Sets the item in the array at index `index` to `value` + pub(crate) fn codegen_array_set( + &mut self, + array_ptr: MemoryAddress, + index: SingleAddrVariable, + value: MemoryAddress, + ) { + assert!(index.bit_size == BRILLIG_MEMORY_ADDRESSING_BIT_SIZE); + // Computes array_ptr + index, ie array[index] + let index_of_element_in_memory = self.allocate_register(); + self.binary_instruction( + SingleAddrVariable::new_usize(array_ptr), + index, + SingleAddrVariable::new_usize(index_of_element_in_memory), + BrilligBinaryOp::Add, + ); + + self.store_instruction(index_of_element_in_memory, value); + // Free up temporary register + self.deallocate_register(index_of_element_in_memory); + } + + /// Copies the values of an array pointed by source with length stored in `num_elements_register` + /// Into the array pointed by destination + pub(crate) fn codegen_copy_array( + &mut self, + source_pointer: MemoryAddress, + destination_pointer: MemoryAddress, + num_elements_variable: SingleAddrVariable, + ) { + assert!(num_elements_variable.bit_size == BRILLIG_MEMORY_ADDRESSING_BIT_SIZE); + + let value_register = self.allocate_register(); + + self.codegen_loop(num_elements_variable.address, |ctx, iterator| { + ctx.codegen_array_get(source_pointer, iterator, value_register); + ctx.codegen_array_set(destination_pointer, iterator, value_register); + }); + + self.deallocate_register(value_register); + } + + /// Loads a variable stored previously + pub(crate) fn codegen_load_variable( + &mut self, + destination: BrilligVariable, + variable_pointer: MemoryAddress, + ) { + match destination { + BrilligVariable::SingleAddr(single_addr) => { + self.load_instruction(single_addr.address, variable_pointer); + } + BrilligVariable::BrilligArray(BrilligArray { pointer, size: _, rc }) => { + self.load_instruction(pointer, variable_pointer); + + let rc_pointer = self.allocate_register(); + self.mov_instruction(rc_pointer, variable_pointer); + self.codegen_usize_op_in_place(rc_pointer, BrilligBinaryOp::Add, 1_usize); + + self.load_instruction(rc, rc_pointer); + self.deallocate_register(rc_pointer); + } + BrilligVariable::BrilligVector(BrilligVector { pointer, size, rc }) => { + self.load_instruction(pointer, variable_pointer); + + let size_pointer = self.allocate_register(); + self.mov_instruction(size_pointer, variable_pointer); + self.codegen_usize_op_in_place(size_pointer, BrilligBinaryOp::Add, 1_usize); + + self.load_instruction(size, size_pointer); + self.deallocate_register(size_pointer); + + let rc_pointer = self.allocate_register(); + self.mov_instruction(rc_pointer, variable_pointer); + self.codegen_usize_op_in_place(rc_pointer, BrilligBinaryOp::Add, 2_usize); + + self.load_instruction(rc, rc_pointer); + self.deallocate_register(rc_pointer); + } + } + } + + /// Stores a variable by saving its registers to memory + pub(crate) fn codegen_store_variable( + &mut self, + variable_pointer: MemoryAddress, + source: BrilligVariable, + ) { + match source { + BrilligVariable::SingleAddr(single_addr) => { + self.store_instruction(variable_pointer, single_addr.address); + } + BrilligVariable::BrilligArray(BrilligArray { pointer, size: _, rc }) => { + self.store_instruction(variable_pointer, pointer); + + let rc_pointer: MemoryAddress = self.allocate_register(); + self.mov_instruction(rc_pointer, variable_pointer); + self.codegen_usize_op_in_place(rc_pointer, BrilligBinaryOp::Add, 1_usize); + self.store_instruction(rc_pointer, rc); + self.deallocate_register(rc_pointer); + } + BrilligVariable::BrilligVector(BrilligVector { pointer, size, rc }) => { + self.store_instruction(variable_pointer, pointer); + + let size_pointer = self.allocate_register(); + self.mov_instruction(size_pointer, variable_pointer); + self.codegen_usize_op_in_place(size_pointer, BrilligBinaryOp::Add, 1_usize); + self.store_instruction(size_pointer, size); + + let rc_pointer: MemoryAddress = self.allocate_register(); + self.mov_instruction(rc_pointer, variable_pointer); + self.codegen_usize_op_in_place(rc_pointer, BrilligBinaryOp::Add, 2_usize); + self.store_instruction(rc_pointer, rc); + + self.deallocate_register(size_pointer); + self.deallocate_register(rc_pointer); + } + } + } + + /// This instruction will reverse the order of the elements in a vector. + pub(crate) fn codegen_reverse_vector_in_place(&mut self, vector: BrilligVector) { + let iteration_count = self.allocate_register(); + self.codegen_usize_op(vector.size, iteration_count, BrilligBinaryOp::UnsignedDiv, 2); + + let start_value_register = self.allocate_register(); + let index_at_end_of_array = self.allocate_register(); + let end_value_register = self.allocate_register(); + + self.codegen_loop(iteration_count, |ctx, iterator_register| { + // Load both values + ctx.codegen_array_get(vector.pointer, iterator_register, start_value_register); + + // The index at the end of array is size - 1 - iterator + ctx.mov_instruction(index_at_end_of_array, vector.size); + ctx.codegen_usize_op_in_place(index_at_end_of_array, BrilligBinaryOp::Sub, 1); + ctx.memory_op_instruction( + index_at_end_of_array, + iterator_register.address, + index_at_end_of_array, + BrilligBinaryOp::Sub, + ); + + ctx.codegen_array_get( + vector.pointer, + SingleAddrVariable::new_usize(index_at_end_of_array), + end_value_register, + ); + + // Write both values + ctx.codegen_array_set(vector.pointer, iterator_register, end_value_register); + ctx.codegen_array_set( + vector.pointer, + SingleAddrVariable::new_usize(index_at_end_of_array), + start_value_register, + ); + }); + + self.deallocate_register(iteration_count); + self.deallocate_register(start_value_register); + self.deallocate_register(end_value_register); + self.deallocate_register(index_at_end_of_array); + } +} diff --git a/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_stack.rs b/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_stack.rs new file mode 100644 index 00000000000..1c30f0f848f --- /dev/null +++ b/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_stack.rs @@ -0,0 +1,26 @@ +use acvm::acir::brillig::MemoryAddress; + +use super::BrilligContext; + +impl BrilligContext { + /// This function moves values from a set of registers to another set of registers. + /// It first moves all sources to new allocated registers to avoid overwriting. + pub(crate) fn codegen_mov_registers_to_registers( + &mut self, + sources: Vec, + destinations: Vec, + ) { + let new_sources: Vec<_> = sources + .iter() + .map(|source| { + let new_source = self.allocate_register(); + self.mov_instruction(new_source, *source); + new_source + }) + .collect(); + for (new_source, destination) in new_sources.iter().zip(destinations.iter()) { + self.mov_instruction(*destination, *new_source); + self.deallocate_register(*new_source); + } + } +} diff --git a/compiler/noirc_evaluator/src/brillig/brillig_ir/debug_show.rs b/compiler/noirc_evaluator/src/brillig/brillig_ir/debug_show.rs index dd57f0c4426..def91f82bfd 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_ir/debug_show.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_ir/debug_show.rs @@ -1,10 +1,10 @@ //! This module contains functions for producing a higher level view disassembler of Brillig. use super::BrilligBinaryOp; -use crate::brillig::brillig_ir::{ReservedRegisters, BRILLIG_MEMORY_ADDRESSING_BIT_SIZE}; -use acvm::acir::brillig::{ - BinaryFieldOp, BinaryIntOp, BlackBoxOp, HeapArray, HeapVector, MemoryAddress, Value, - ValueOrArray, +use crate::brillig::brillig_ir::ReservedRegisters; +use acvm::{ + acir::brillig::{BlackBoxOp, HeapArray, HeapVector, MemoryAddress, ValueOrArray}, + FieldElement, }; /// Trait for converting values into debug-friendly strings. @@ -26,8 +26,8 @@ default_to_string_impl! { str usize u32 } impl DebugToString for MemoryAddress { fn debug_to_string(&self) -> String { - if *self == ReservedRegisters::stack_pointer() { - "Stack".into() + if *self == ReservedRegisters::free_memory_pointer() { + "FreeMem".into() } else if *self == ReservedRegisters::previous_stack_pointer() { "PrevStack".into() } else { @@ -48,66 +48,30 @@ impl DebugToString for HeapVector { } } -impl DebugToString for BinaryFieldOp { - fn debug_to_string(&self) -> String { - match self { - BinaryFieldOp::Add => "f+".into(), - BinaryFieldOp::Sub => "f-".into(), - BinaryFieldOp::Mul => "f*".into(), - BinaryFieldOp::Div => "f/".into(), - BinaryFieldOp::Equals => "f==".into(), - } - } -} - -impl DebugToString for BinaryIntOp { - fn debug_to_string(&self) -> String { - match self { - BinaryIntOp::Add => "+".into(), - BinaryIntOp::Sub => "-".into(), - BinaryIntOp::Mul => "*".into(), - BinaryIntOp::Equals => "==".into(), - BinaryIntOp::SignedDiv => "/".into(), - BinaryIntOp::UnsignedDiv => "//".into(), - BinaryIntOp::LessThan => "<".into(), - BinaryIntOp::LessThanEquals => "<=".into(), - BinaryIntOp::And => "&&".into(), - BinaryIntOp::Or => "||".into(), - BinaryIntOp::Xor => "^".into(), - BinaryIntOp::Shl => "<<".into(), - BinaryIntOp::Shr => ">>".into(), - } - } -} - impl DebugToString for BrilligBinaryOp { fn debug_to_string(&self) -> String { match self { - BrilligBinaryOp::Field { op } => op.debug_to_string(), - BrilligBinaryOp::Integer { op, bit_size } => { - // rationale: if there's >= 64 bits, we should not bother with this detail - if *bit_size >= BRILLIG_MEMORY_ADDRESSING_BIT_SIZE { - op.debug_to_string() - } else { - format!("i{}::{}", bit_size, op.debug_to_string()) - } - } - BrilligBinaryOp::Modulo { is_signed_integer, bit_size } => { - let op = if *is_signed_integer { "%" } else { "%%" }; - // rationale: if there's >= 64 bits, we should not bother with this detail - if *bit_size >= BRILLIG_MEMORY_ADDRESSING_BIT_SIZE { - op.into() - } else { - format!("{op}:{bit_size}") - } - } + BrilligBinaryOp::Add => "+".into(), + BrilligBinaryOp::Sub => "-".into(), + BrilligBinaryOp::Mul => "*".into(), + BrilligBinaryOp::Equals => "==".into(), + BrilligBinaryOp::FieldDiv => "f/".into(), + BrilligBinaryOp::UnsignedDiv => "/".into(), + BrilligBinaryOp::LessThan => "<".into(), + BrilligBinaryOp::LessThanEquals => "<=".into(), + BrilligBinaryOp::And => "&&".into(), + BrilligBinaryOp::Or => "||".into(), + BrilligBinaryOp::Xor => "^".into(), + BrilligBinaryOp::Shl => "<<".into(), + BrilligBinaryOp::Shr => ">>".into(), + BrilligBinaryOp::Modulo => "%".into(), } } } -impl DebugToString for Value { +impl DebugToString for FieldElement { fn debug_to_string(&self) -> String { - self.to_usize().to_string() + self.to_string() } } @@ -149,21 +113,9 @@ impl DebugShow { DebugShow { enable_debug_trace } } - /// Emits brillig bytecode to jump to a trap condition if `condition` - /// is false. - pub(crate) fn constrain_instruction(&self, condition: MemoryAddress) { - debug_println!(self.enable_debug_trace, " ASSERT {} != 0", condition); - } - - /// Processes a return instruction. - pub(crate) fn return_instruction(&self, return_registers: &[MemoryAddress]) { - let registers_string = return_registers - .iter() - .map(MemoryAddress::debug_to_string) - .collect::>() - .join(", "); - - debug_println!(self.enable_debug_trace, " // return {};", registers_string); + /// Emits a `trap` instruction. + pub(crate) fn trap_instruction(&self, revert_data: HeapArray) { + debug_println!(self.enable_debug_trace, " TRAP {}", revert_data); } /// Emits a `mov` instruction. @@ -171,6 +123,24 @@ impl DebugShow { debug_println!(self.enable_debug_trace, " MOV {}, {}", destination, source); } + /// Emits a conditional `mov` instruction. + pub(crate) fn conditional_mov_instruction( + &self, + destination: MemoryAddress, + condition: MemoryAddress, + source_a: MemoryAddress, + source_b: MemoryAddress, + ) { + debug_println!( + self.enable_debug_trace, + " CMOV {} = {}? {} : {}", + destination, + condition, + source_a, + source_b + ); + } + /// Emits a `cast` instruction. pub(crate) fn cast_instruction( &self, @@ -199,7 +169,7 @@ impl DebugShow { } /// Stores the value of `constant` in the `result` register - pub(crate) fn const_instruction(&self, result: MemoryAddress, constant: Value) { + pub(crate) fn const_instruction(&self, result: MemoryAddress, constant: FieldElement) { debug_println!(self.enable_debug_trace, " CONST {} = {}", result, constant); } @@ -252,64 +222,17 @@ impl DebugShow { debug_println!(self.enable_debug_trace, " STOP"); } - /// Debug function for allocate_array_instruction - pub(crate) fn allocate_array_instruction( - &self, - pointer_register: MemoryAddress, - size_register: MemoryAddress, - ) { - debug_println!( - self.enable_debug_trace, - " ALLOCATE_ARRAY {} SIZE {}", - pointer_register, - size_register - ); - } - - /// Debug function for allocate_instruction - pub(crate) fn allocate_instruction(&self, pointer_register: MemoryAddress) { - debug_println!(self.enable_debug_trace, " ALLOCATE {} ", pointer_register); - } - - /// Debug function for array_get - pub(crate) fn array_get( + /// Emits a external stop instruction (returns data) + pub(crate) fn external_stop_instruction( &self, - array_ptr: MemoryAddress, - index: MemoryAddress, - result: MemoryAddress, + return_data_offset: usize, + return_data_size: usize, ) { debug_println!( self.enable_debug_trace, - " ARRAY_GET {}[{}] -> {}", - array_ptr, - index, - result - ); - } - - /// Debug function for array_set - pub(crate) fn array_set( - &self, - array_ptr: MemoryAddress, - index: MemoryAddress, - value: MemoryAddress, - ) { - debug_println!(self.enable_debug_trace, " ARRAY_SET {}[{}] = {}", array_ptr, index, value); - } - - /// Debug function for copy_array_instruction - pub(crate) fn copy_array_instruction( - &self, - source: MemoryAddress, - destination: MemoryAddress, - num_elements_register: MemoryAddress, - ) { - debug_println!( - self.enable_debug_trace, - " COPY_ARRAY {} -> {} ({} ELEMENTS)", - source, - destination, - num_elements_register + " EXT_STOP {}..{}", + return_data_offset, + return_data_offset + return_data_size ); } @@ -340,25 +263,19 @@ impl DebugShow { ); } - /// Debug function for cast_instruction - pub(crate) fn truncate_instruction( - &self, - destination: MemoryAddress, - source: MemoryAddress, - target_bit_size: u32, - ) { - debug_println!( - self.enable_debug_trace, - " TRUNCATE {} FROM {} TO {} BITS", - destination, - source, - target_bit_size - ); - } - /// Debug function for black_box_op pub(crate) fn black_box_op_instruction(&self, op: &BlackBoxOp) { match op { + BlackBoxOp::AES128Encrypt { inputs, iv, key, outputs } => { + debug_println!( + self.enable_debug_trace, + " AES128 ENCRYPT {} {} {} -> {}", + inputs, + iv, + key, + outputs + ); + } BlackBoxOp::Sha256 { message, output } => { debug_println!(self.enable_debug_trace, " SHA256 {} -> {}", message, output); } @@ -408,16 +325,18 @@ impl DebugShow { result ); } - BlackBoxOp::FixedBaseScalarMul { low, high, result } => { + BlackBoxOp::MultiScalarMul { points, scalars, outputs } => { debug_println!( self.enable_debug_trace, - " FIXED_BASE_SCALAR_MUL {} {} -> {}", - low, - high, - result + " MULTI_SCALAR_MUL {} {} -> {}", + points, + scalars, + outputs ); } - BlackBoxOp::EmbeddedCurveAdd { input1_x, input1_y, input2_x, input2_y, result } => { + BlackBoxOp::EmbeddedCurveAdd { + input1_x, input1_y, input2_x, input2_y, result, .. + } => { debug_println!( self.enable_debug_trace, " EMBEDDED_CURVE_ADD ({} {}) ({} {}) -> {}", @@ -534,6 +453,15 @@ impl DebugShow { output ); } + BlackBoxOp::ToRadix { input, radix, output } => { + debug_println!( + self.enable_debug_trace, + " TO_RADIX {} {} -> {}", + input, + radix, + output + ); + } } } @@ -541,4 +469,20 @@ impl DebugShow { pub(crate) fn add_external_call_instruction(&self, func_label: String) { debug_println!(self.enable_debug_trace, " CALL {}", func_label); } + + /// Debug function for calldata_copy + pub(crate) fn calldata_copy_instruction( + &self, + destination: MemoryAddress, + calldata_size: usize, + offset: usize, + ) { + debug_println!( + self.enable_debug_trace, + " CALLDATA_COPY {} {}..{}", + destination, + offset, + offset + calldata_size + ); + } } diff --git a/compiler/noirc_evaluator/src/brillig/brillig_ir/entry_point.rs b/compiler/noirc_evaluator/src/brillig/brillig_ir/entry_point.rs index 9d186f9bc60..9023183eb36 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_ir/entry_point.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_ir/entry_point.rs @@ -1,16 +1,13 @@ use super::{ artifact::{BrilligArtifact, BrilligParameter}, - brillig_variable::{BrilligArray, BrilligVariable, SingleAddrVariable}, + brillig_variable::{BrilligArray, BrilligVariable, BrilligVector, SingleAddrVariable}, debug_show::DebugShow, registers::BrilligRegistersContext, - BrilligContext, ReservedRegisters, BRILLIG_MEMORY_ADDRESSING_BIT_SIZE, -}; -use acvm::{ - acir::brillig::{MemoryAddress, Opcode as BrilligOpcode}, - FieldElement, + BrilligBinaryOp, BrilligContext, ReservedRegisters, }; +use acvm::{acir::brillig::MemoryAddress, acir::AcirField, FieldElement}; -pub(crate) const MAX_STACK_SIZE: usize = 1024; +pub(crate) const MAX_STACK_SIZE: usize = 2048; impl BrilligContext { /// Creates an entry point artifact that will jump to the function label provided. @@ -26,20 +23,21 @@ impl BrilligContext { section_label: 0, next_section: 1, debug_show: DebugShow::new(false), + bigint_new_id: 0, }; - context.entry_point_instruction(&arguments, &return_parameters); + context.codegen_entry_point(&arguments, &return_parameters); context.add_external_call_instruction(target_function); - context.exit_point_instruction(&arguments, &return_parameters); + context.codegen_exit_point(&arguments, &return_parameters); context.artifact() } /// Adds the instructions needed to handle entry point parameters /// The runtime will leave the parameters in calldata. /// Arrays will be passed flattened. - fn entry_point_instruction( + fn codegen_entry_point( &mut self, arguments: &[BrilligParameter], return_parameters: &[BrilligParameter], @@ -48,11 +46,10 @@ impl BrilligContext { let return_data_size = BrilligContext::flattened_tuple_size(return_parameters); // Set initial value of stack pointer: MAX_STACK_SIZE + calldata_size + return_data_size - self.push_opcode(BrilligOpcode::Const { - destination: ReservedRegisters::stack_pointer(), - value: (MAX_STACK_SIZE + calldata_size + return_data_size).into(), - bit_size: BRILLIG_MEMORY_ADDRESSING_BIT_SIZE, - }); + self.const_instruction( + SingleAddrVariable::new_usize(ReservedRegisters::free_memory_pointer()), + (MAX_STACK_SIZE + calldata_size + return_data_size).into(), + ); // Copy calldata self.copy_and_cast_calldata(arguments); @@ -75,86 +72,111 @@ impl BrilligContext { } BrilligParameter::Array(_, _) => { let pointer_to_the_array_in_calldata = - self.make_usize_constant(current_calldata_pointer.into()); - let rc_register = self.make_usize_constant(1_usize.into()); + self.make_usize_constant_instruction(current_calldata_pointer.into()); + let rc_register = self.make_usize_constant_instruction(1_usize.into()); let flattened_size = BrilligContext::flattened_size(argument); let var = BrilligVariable::BrilligArray(BrilligArray { - pointer: pointer_to_the_array_in_calldata, + pointer: pointer_to_the_array_in_calldata.address, size: flattened_size, - rc: rc_register, + rc: rc_register.address, + }); + + current_calldata_pointer += flattened_size; + var + } + BrilligParameter::Slice(_, _) => { + let pointer_to_the_array_in_calldata = + self.make_usize_constant_instruction(current_calldata_pointer.into()); + + let flattened_size = BrilligContext::flattened_size(argument); + let size_register = self.make_usize_constant_instruction(flattened_size.into()); + let rc_register = self.make_usize_constant_instruction(1_usize.into()); + + let var = BrilligVariable::BrilligVector(BrilligVector { + pointer: pointer_to_the_array_in_calldata.address, + size: size_register.address, + rc: rc_register.address, }); current_calldata_pointer += flattened_size; var } - BrilligParameter::Slice(_) => unimplemented!("Unsupported slices as parameter"), }) .collect(); // Deflatten arrays for (argument_variable, argument) in argument_variables.iter_mut().zip(arguments) { - if let ( - BrilligVariable::BrilligArray(array), - BrilligParameter::Array(item_type, item_count), - ) = (argument_variable, argument) - { - if BrilligContext::has_nested_arrays(item_type) { + match (argument_variable, argument) { + ( + BrilligVariable::BrilligArray(array), + BrilligParameter::Array(item_type, item_count), + ) => { let deflattened_address = self.deflatten_array(item_type, array.size, array.pointer); self.mov_instruction(array.pointer, deflattened_address); array.size = item_type.len() * item_count; self.deallocate_register(deflattened_address); } + ( + BrilligVariable::BrilligVector(vector), + BrilligParameter::Slice(item_type, item_count), + ) => { + let flattened_size = BrilligContext::flattened_size(argument); + + let deflattened_address = + self.deflatten_array(item_type, flattened_size, vector.pointer); + self.mov_instruction(vector.pointer, deflattened_address); + self.usize_const_instruction( + vector.size, + (item_type.len() * item_count).into(), + ); + + self.deallocate_register(deflattened_address); + } + _ => {} } } } fn copy_and_cast_calldata(&mut self, arguments: &[BrilligParameter]) { let calldata_size = BrilligContext::flattened_tuple_size(arguments); - self.push_opcode(BrilligOpcode::CalldataCopy { - destination_address: MemoryAddress(MAX_STACK_SIZE), - size: calldata_size, - offset: 0, - }); + self.calldata_copy_instruction(MemoryAddress(MAX_STACK_SIZE), calldata_size, 0); fn flat_bit_sizes(param: &BrilligParameter) -> Box + '_> { match param { BrilligParameter::SingleAddr(bit_size) => Box::new(std::iter::once(*bit_size)), - BrilligParameter::Array(item_types, item_count) => Box::new( + BrilligParameter::Array(item_types, item_count) + | BrilligParameter::Slice(item_types, item_count) => Box::new( (0..*item_count).flat_map(move |_| item_types.iter().flat_map(flat_bit_sizes)), ), - BrilligParameter::Slice(..) => unimplemented!("Unsupported slices as parameter"), } } for (i, bit_size) in arguments.iter().flat_map(flat_bit_sizes).enumerate() { // Calldatacopy tags everything with field type, so when downcast when necessary if bit_size < FieldElement::max_num_bits() { - self.push_opcode(BrilligOpcode::Cast { - destination: MemoryAddress(MAX_STACK_SIZE + i), - source: MemoryAddress(MAX_STACK_SIZE + i), - bit_size, - }); + self.cast_instruction( + SingleAddrVariable::new(MemoryAddress(MAX_STACK_SIZE + i), bit_size), + SingleAddrVariable::new_field(MemoryAddress(MAX_STACK_SIZE + i)), + ); } } } /// Computes the size of a parameter if it was flattened - fn flattened_size(param: &BrilligParameter) -> usize { + pub(super) fn flattened_size(param: &BrilligParameter) -> usize { match param { BrilligParameter::SingleAddr(_) => 1, - BrilligParameter::Array(item_types, item_count) => { + BrilligParameter::Array(item_types, item_count) + | BrilligParameter::Slice(item_types, item_count) => { let item_size: usize = item_types.iter().map(BrilligContext::flattened_size).sum(); item_count * item_size } - BrilligParameter::Slice(_) => { - unreachable!("ICE: Slices cannot be passed as entry point arguments") - } } } /// Computes the size of a parameter if it was flattened - fn flattened_tuple_size(tuple: &[BrilligParameter]) -> usize { + pub(super) fn flattened_tuple_size(tuple: &[BrilligParameter]) -> usize { tuple.iter().map(BrilligContext::flattened_size).sum() } @@ -178,7 +200,7 @@ impl BrilligContext { let target_item_size = item_type.len(); let source_item_size = BrilligContext::flattened_tuple_size(item_type); - self.allocate_fixed_length_array( + self.codegen_allocate_fixed_length_array( deflattened_array_pointer, item_count * target_item_size, ); @@ -190,20 +212,22 @@ impl BrilligContext { let mut source_offset = 0; for (subitem_index, subitem) in item_type.iter().enumerate() { - let source_index = - self.make_usize_constant((source_item_base_index + source_offset).into()); + let source_index = self.make_usize_constant_instruction( + (source_item_base_index + source_offset).into(), + ); - let target_index = - self.make_usize_constant((target_item_base_index + subitem_index).into()); + let target_index = self.make_usize_constant_instruction( + (target_item_base_index + subitem_index).into(), + ); match subitem { BrilligParameter::SingleAddr(_) => { - self.array_get( + self.codegen_array_get( flattened_array_pointer, source_index, movement_register, ); - self.array_set( + self.codegen_array_set( deflattened_array_pointer, target_index, movement_register, @@ -216,11 +240,11 @@ impl BrilligContext { ) => { let nested_array_pointer = self.allocate_register(); self.mov_instruction(nested_array_pointer, flattened_array_pointer); - self.memory_op( + self.memory_op_instruction( nested_array_pointer, - source_index, + source_index.address, nested_array_pointer, - acvm::brillig_vm::brillig::BinaryIntOp::Add, + BrilligBinaryOp::Add, ); let deflattened_nested_array_pointer = self.deflatten_array( nested_array_item_type, @@ -229,17 +253,21 @@ impl BrilligContext { ); let reference = self.allocate_register(); let rc = self.allocate_register(); - self.usize_const(rc, 1_usize.into()); + self.usize_const_instruction(rc, 1_usize.into()); - self.allocate_array_reference_instruction(reference); + self.codegen_allocate_array_reference(reference); let array_variable = BrilligVariable::BrilligArray(BrilligArray { pointer: deflattened_nested_array_pointer, size: nested_array_item_type.len() * nested_array_item_count, rc, }); - self.store_variable_instruction(reference, array_variable); + self.codegen_store_variable(reference, array_variable); - self.array_set(deflattened_array_pointer, target_index, reference); + self.codegen_array_set( + deflattened_array_pointer, + target_index, + reference, + ); self.deallocate_register(nested_array_pointer); self.deallocate_register(reference); @@ -253,8 +281,8 @@ impl BrilligContext { BrilligParameter::Slice(..) => unreachable!("ICE: Cannot deflatten slices"), } - self.deallocate_register(source_index); - self.deallocate_register(target_index); + self.deallocate_single_addr(source_index); + self.deallocate_single_addr(target_index); } } @@ -272,7 +300,7 @@ impl BrilligContext { /// The runtime expects the results in a contiguous memory region. /// Arrays are expected to be returned with all the nested arrays flattened. /// However, the function called returns variables (that have extra data) and the returned arrays are deflattened. - fn exit_point_instruction( + fn codegen_exit_point( &mut self, arguments: &[BrilligParameter], return_parameters: &[BrilligParameter], @@ -318,16 +346,17 @@ impl BrilligContext { } BrilligParameter::Array(item_type, item_count) => { let returned_pointer = returned_variable.extract_array().pointer; - let pointer_to_return_data = self.make_usize_constant(return_data_index.into()); + let pointer_to_return_data = + self.make_usize_constant_instruction(return_data_index.into()); self.flatten_array( item_type, *item_count, - pointer_to_return_data, + pointer_to_return_data.address, returned_pointer, ); - self.deallocate_register(pointer_to_return_data); + self.deallocate_single_addr(pointer_to_return_data); return_data_index += BrilligContext::flattened_size(return_param); } BrilligParameter::Slice(..) => { @@ -336,11 +365,11 @@ impl BrilligContext { } } - self.push_opcode(BrilligOpcode::Stop { return_data_offset, return_data_size }); + self.external_stop_instruction(return_data_offset, return_data_size); } // Flattens an array by recursively copying nested arrays and regular items. - fn flatten_array( + pub(super) fn flatten_array( &mut self, item_type: &[BrilligParameter], item_count: usize, @@ -361,19 +390,21 @@ impl BrilligContext { let mut target_offset = 0; for (subitem_index, subitem) in item_type.iter().enumerate() { - let source_index = - self.make_usize_constant((source_item_base_index + subitem_index).into()); - let target_index = - self.make_usize_constant((target_item_base_index + target_offset).into()); + let source_index = self.make_usize_constant_instruction( + (source_item_base_index + subitem_index).into(), + ); + let target_index = self.make_usize_constant_instruction( + (target_item_base_index + target_offset).into(), + ); match subitem { BrilligParameter::SingleAddr(_) => { - self.array_get( + self.codegen_array_get( deflattened_array_pointer, source_index, movement_register, ); - self.array_set( + self.codegen_array_set( flattened_array_pointer, target_index, movement_register, @@ -385,7 +416,7 @@ impl BrilligContext { nested_array_item_count, ) => { let nested_array_reference = self.allocate_register(); - self.array_get( + self.codegen_array_get( deflattened_array_pointer, source_index, nested_array_reference, @@ -398,7 +429,7 @@ impl BrilligContext { rc: self.allocate_register(), }); - self.load_variable_instruction( + self.codegen_load_variable( nested_array_variable, nested_array_reference, ); @@ -410,11 +441,11 @@ impl BrilligContext { flattened_array_pointer, ); - self.memory_op( + self.memory_op_instruction( flattened_nested_array_pointer, - target_index, + target_index.address, flattened_nested_array_pointer, - acvm::brillig_vm::brillig::BinaryIntOp::Add, + BrilligBinaryOp::Add, ); self.flatten_array( @@ -436,43 +467,41 @@ impl BrilligContext { BrilligParameter::Slice(..) => unreachable!("ICE: Cannot flatten slices"), } - self.deallocate_register(source_index); - self.deallocate_register(target_index); + self.deallocate_single_addr(source_index); + self.deallocate_single_addr(target_index); } } self.deallocate_register(movement_register); } else { - let item_count = self.make_usize_constant((item_count * item_type.len()).into()); - self.copy_array_instruction( - deflattened_array_pointer, - flattened_array_pointer, - item_count, - ); - self.deallocate_register(item_count); + let item_count = + self.make_usize_constant_instruction((item_count * item_type.len()).into()); + self.codegen_copy_array(deflattened_array_pointer, flattened_array_pointer, item_count); + self.deallocate_single_addr(item_count); } } } #[cfg(test)] mod tests { - use acvm::brillig_vm::brillig::Value; + + use acvm::FieldElement; use crate::brillig::brillig_ir::{ - artifact::BrilligParameter, brillig_variable::BrilligArray, + entry_point::BrilligParameter, tests::{create_and_run_vm, create_context, create_entry_point_bytecode}, }; #[test] fn entry_point_with_nested_array_parameter() { let calldata = vec![ - Value::from(1_usize), - Value::from(2_usize), - Value::from(3_usize), - Value::from(4_usize), - Value::from(5_usize), - Value::from(6_usize), + FieldElement::from(1_usize), + FieldElement::from(2_usize), + FieldElement::from(3_usize), + FieldElement::from(4_usize), + FieldElement::from(5_usize), + FieldElement::from(6_usize), ]; let arguments = vec![BrilligParameter::Array( vec![ @@ -493,24 +522,24 @@ mod tests { context.load_instruction(array_pointer, array_pointer); context.load_instruction(array_value, array_pointer); - context.return_instruction(&[array_value]); + context.codegen_return(&[array_value]); let bytecode = create_entry_point_bytecode(context, arguments, returns).byte_code; let (vm, return_data_offset, return_data_size) = create_and_run_vm(calldata.clone(), &bytecode); assert_eq!(return_data_size, 1, "Return data size is incorrect"); - assert_eq!(vm.get_memory()[return_data_offset], Value::from(1_usize)); + assert_eq!(vm.get_memory()[return_data_offset].to_field(), FieldElement::from(1_usize)); } #[test] fn entry_point_with_nested_array_return() { let flattened_array = vec![ - Value::from(1_usize), - Value::from(2_usize), - Value::from(3_usize), - Value::from(4_usize), - Value::from(5_usize), - Value::from(6_usize), + FieldElement::from(1_usize), + FieldElement::from(2_usize), + FieldElement::from(3_usize), + FieldElement::from(4_usize), + FieldElement::from(5_usize), + FieldElement::from(6_usize), ]; let array_param = BrilligParameter::Array( vec![ @@ -531,7 +560,7 @@ mod tests { rc: context.allocate_register(), }; - context.return_instruction(&brillig_array.extract_registers()); + context.codegen_return(&brillig_array.extract_registers()); let bytecode = create_entry_point_bytecode(context, arguments, returns).byte_code; let (vm, return_data_pointer, return_data_size) = @@ -539,7 +568,10 @@ mod tests { let memory = vm.get_memory(); assert_eq!( - memory[return_data_pointer..(return_data_pointer + flattened_array.len())], + memory[return_data_pointer..(return_data_pointer + flattened_array.len())] + .iter() + .map(|mem_val| mem_val.to_field()) + .collect::>(), flattened_array ); assert_eq!(return_data_size, flattened_array.len()); diff --git a/compiler/noirc_evaluator/src/brillig/brillig_ir/instructions.rs b/compiler/noirc_evaluator/src/brillig/brillig_ir/instructions.rs new file mode 100644 index 00000000000..03a9216b73a --- /dev/null +++ b/compiler/noirc_evaluator/src/brillig/brillig_ir/instructions.rs @@ -0,0 +1,525 @@ +use acvm::{ + acir::brillig::{ + BinaryFieldOp, BinaryIntOp, BlackBoxOp, HeapArray, HeapValueType, MemoryAddress, + Opcode as BrilligOpcode, ValueOrArray, + }, + acir::AcirField, + FieldElement, +}; + +use super::{ + artifact::UnresolvedJumpLocation, + brillig_variable::{BrilligArray, BrilligVector, SingleAddrVariable}, + BrilligContext, ReservedRegisters, BRILLIG_MEMORY_ADDRESSING_BIT_SIZE, +}; + +/// Low level instructions of the brillig IR, used by the brillig ir codegens and brillig_gen +/// Printed using debug_slow +impl BrilligContext { + /// Processes a binary instruction according `operation`. + /// + /// This method will compute lhs rhs + /// and store the result in the `result` register. + pub(crate) fn binary_instruction( + &mut self, + lhs: SingleAddrVariable, + rhs: SingleAddrVariable, + result: SingleAddrVariable, + operation: BrilligBinaryOp, + ) { + self.debug_show.binary_instruction(lhs.address, rhs.address, result.address, operation); + self.binary(lhs, rhs, result, operation); + } + + /// Processes a not instruction. + /// + /// Not is computed using a subtraction operation as there is no native not instruction + /// in Brillig. + pub(crate) fn not_instruction( + &mut self, + input: SingleAddrVariable, + result: SingleAddrVariable, + ) { + self.debug_show.not_instruction(input.address, input.bit_size, result.address); + // Compile !x as ((-1) - x) + let u_max = FieldElement::from(2_i128).pow(&FieldElement::from(input.bit_size as i128)) + - FieldElement::one(); + let max = self.make_constant(u_max, input.bit_size); + + self.binary(max, input, result, BrilligBinaryOp::Sub); + self.deallocate_single_addr(max); + } + + /// Utility method to perform a binary instruction with a memory address + pub(crate) fn memory_op_instruction( + &mut self, + lhs: MemoryAddress, + rhs: MemoryAddress, + destination: MemoryAddress, + op: BrilligBinaryOp, + ) { + self.binary_instruction( + SingleAddrVariable::new_usize(lhs), + SingleAddrVariable::new_usize(rhs), + SingleAddrVariable::new( + destination, + BrilligContext::binary_result_bit_size(op, BRILLIG_MEMORY_ADDRESSING_BIT_SIZE), + ), + op, + ); + } + + fn binary( + &mut self, + lhs: SingleAddrVariable, + rhs: SingleAddrVariable, + result: SingleAddrVariable, + operation: BrilligBinaryOp, + ) { + let is_field_op = lhs.bit_size == FieldElement::max_num_bits(); + let expected_result_bit_size = + BrilligContext::binary_result_bit_size(operation, lhs.bit_size); + assert!( + result.bit_size == expected_result_bit_size, + "Expected result bit size to be {}, got {} for operation {:?}", + expected_result_bit_size, + result.bit_size, + operation + ); + + if let BrilligBinaryOp::Modulo = operation { + self.modulo(result, lhs, rhs); + } else if is_field_op { + self.push_opcode(BrilligOpcode::BinaryFieldOp { + op: operation.into(), + destination: result.address, + lhs: lhs.address, + rhs: rhs.address, + }); + } else { + self.push_opcode(BrilligOpcode::BinaryIntOp { + op: operation.into(), + destination: result.address, + bit_size: lhs.bit_size, + lhs: lhs.address, + rhs: rhs.address, + }); + } + } + + /// Computes left % right by emitting the necessary Brillig opcodes. + /// + /// This is done by using the following formula: + /// + /// a % b = a - (b * (a / b)) + /// + /// Brillig does not have an explicit modulo operation, + /// so we must emit multiple opcodes and process it differently + /// to other binary instructions. + fn modulo( + &mut self, + result: SingleAddrVariable, + left: SingleAddrVariable, + right: SingleAddrVariable, + ) { + assert!( + left.bit_size == right.bit_size, + "Not equal bitsize: lhs {}, rhs {}", + left.bit_size, + right.bit_size + ); + let bit_size = left.bit_size; + + let scratch_var_i = SingleAddrVariable::new(self.allocate_register(), bit_size); + let scratch_var_j = SingleAddrVariable::new(self.allocate_register(), bit_size); + + // i = left / right + self.binary(left, right, scratch_var_i, BrilligBinaryOp::UnsignedDiv); + + // j = i * right + self.binary(scratch_var_i, right, scratch_var_j, BrilligBinaryOp::Mul); + + // result_register = left - j + self.binary(left, scratch_var_j, result, BrilligBinaryOp::Sub); + // Free scratch registers + self.deallocate_single_addr(scratch_var_i); + self.deallocate_single_addr(scratch_var_j); + } + + fn binary_result_bit_size(operation: BrilligBinaryOp, arguments_bit_size: u32) -> u32 { + match operation { + BrilligBinaryOp::Equals + | BrilligBinaryOp::LessThan + | BrilligBinaryOp::LessThanEquals => 1, + _ => arguments_bit_size, + } + } + + /// Processes a foreign call instruction. + /// + /// Note: the function being called is external and will + /// not be linked during brillig generation. + pub(crate) fn foreign_call_instruction( + &mut self, + func_name: String, + inputs: &[ValueOrArray], + input_value_types: &[HeapValueType], + outputs: &[ValueOrArray], + output_value_types: &[HeapValueType], + ) { + self.debug_show.foreign_call_instruction(func_name.clone(), inputs, outputs); + + assert!(inputs.len() == input_value_types.len()); + assert!(outputs.len() == output_value_types.len()); + + self.push_opcode(BrilligOpcode::ForeignCall { + function: func_name, + destinations: outputs.to_vec(), + destination_value_types: output_value_types.to_vec(), + inputs: inputs.to_vec(), + input_value_types: input_value_types.to_vec(), + }); + } + + /// Adds a unresolved external `Call` instruction to the bytecode. + /// This calls into another function compiled into this brillig artifact. + pub(crate) fn add_external_call_instruction(&mut self, func_label: T) { + self.debug_show.add_external_call_instruction(func_label.to_string()); + self.obj.add_unresolved_external_call( + BrilligOpcode::Call { location: 0 }, + func_label.to_string(), + ); + } + + /// Adds a unresolved `Jump` instruction to the bytecode. + pub(crate) fn jump_instruction(&mut self, target_label: T) { + self.debug_show.jump_instruction(target_label.to_string()); + self.add_unresolved_jump(BrilligOpcode::Jump { location: 0 }, target_label.to_string()); + } + + /// Adds a unresolved `JumpIf` instruction to the bytecode. + pub(crate) fn jump_if_instruction( + &mut self, + condition: MemoryAddress, + target_label: T, + ) { + self.debug_show.jump_if_instruction(condition, target_label.to_string()); + self.add_unresolved_jump( + BrilligOpcode::JumpIf { condition, location: 0 }, + target_label.to_string(), + ); + } + + /// Adds a unresolved `Jump` to the bytecode. + fn add_unresolved_jump( + &mut self, + jmp_instruction: BrilligOpcode, + destination: UnresolvedJumpLocation, + ) { + self.obj.add_unresolved_jump(jmp_instruction, destination); + } + + /// Adds a label to the next opcode + pub(crate) fn enter_context(&mut self, label: T) { + self.debug_show.enter_context(label.to_string()); + self.context_label = label.to_string(); + self.section_label = 0; + // Add a context label to the next opcode + self.obj.add_label_at_position(label.to_string(), self.obj.index_of_next_opcode()); + // Add a section label to the next opcode + self.obj + .add_label_at_position(self.current_section_label(), self.obj.index_of_next_opcode()); + } + + /// Enter the given section + pub(super) fn enter_section(&mut self, section: usize) { + self.section_label = section; + self.obj + .add_label_at_position(self.current_section_label(), self.obj.index_of_next_opcode()); + } + + /// Create, reserve, and return a new section label. + pub(super) fn reserve_next_section_label(&mut self) -> (usize, String) { + let section = self.next_section; + self.next_section += 1; + (section, self.compute_section_label(section)) + } + + /// Internal function used to compute the section labels + fn compute_section_label(&self, section: usize) -> String { + format!("{}-{}", self.context_label, section) + } + + /// Returns the current section label + fn current_section_label(&self) -> String { + self.compute_section_label(self.section_label) + } + + /// Emits a stop instruction + pub(crate) fn stop_instruction(&mut self) { + self.debug_show.stop_instruction(); + self.push_opcode(BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 0 }); + } + + /// Emits a external stop instruction (returns data) + pub(crate) fn external_stop_instruction( + &mut self, + return_data_offset: usize, + return_data_size: usize, + ) { + self.debug_show.external_stop_instruction(return_data_offset, return_data_size); + self.push_opcode(BrilligOpcode::Stop { return_data_offset, return_data_size }); + } + + /// Issues a blackbox operation. + pub(crate) fn black_box_op_instruction(&mut self, op: BlackBoxOp) { + self.debug_show.black_box_op_instruction(&op); + self.push_opcode(BrilligOpcode::BlackBox(op)); + } + + pub(crate) fn load_free_memory_pointer_instruction(&mut self, pointer_register: MemoryAddress) { + self.debug_show.mov_instruction(pointer_register, ReservedRegisters::free_memory_pointer()); + self.push_opcode(BrilligOpcode::Mov { + destination: pointer_register, + source: ReservedRegisters::free_memory_pointer(), + }); + } + + pub(crate) fn increase_free_memory_pointer_instruction( + &mut self, + size_register: MemoryAddress, + ) { + self.memory_op_instruction( + ReservedRegisters::free_memory_pointer(), + size_register, + ReservedRegisters::free_memory_pointer(), + BrilligBinaryOp::Add, + ); + } + + /// Emits a store instruction + pub(crate) fn store_instruction( + &mut self, + destination_pointer: MemoryAddress, + source: MemoryAddress, + ) { + self.debug_show.store_instruction(destination_pointer, source); + self.push_opcode(BrilligOpcode::Store { destination_pointer, source }); + } + + /// Utility method to transform a HeapArray to a HeapVector by making a runtime constant with the size. + pub(crate) fn array_to_vector_instruction(&mut self, array: &BrilligArray) -> BrilligVector { + let size_register = self.make_usize_constant_instruction(array.size.into()); + BrilligVector { size: size_register.address, pointer: array.pointer, rc: array.rc } + } + + /// Emits a load instruction + pub(crate) fn load_instruction( + &mut self, + destination: MemoryAddress, + source_pointer: MemoryAddress, + ) { + self.debug_show.load_instruction(destination, source_pointer); + self.push_opcode(BrilligOpcode::Load { destination, source_pointer }); + } + + /// Emits a `mov` instruction. + /// + /// Copies the value at `source` into `destination` + pub(crate) fn mov_instruction(&mut self, destination: MemoryAddress, source: MemoryAddress) { + self.debug_show.mov_instruction(destination, source); + self.push_opcode(BrilligOpcode::Mov { destination, source }); + } + + /// Emits a conditional `mov` instruction. + /// + /// Copies the value at `source` into `destination` + pub(crate) fn conditional_mov_instruction( + &mut self, + destination: MemoryAddress, + condition: MemoryAddress, + source_a: MemoryAddress, + source_b: MemoryAddress, + ) { + self.debug_show.conditional_mov_instruction(destination, condition, source_a, source_b); + self.push_opcode(BrilligOpcode::ConditionalMov { + destination, + source_a, + source_b, + condition, + }); + } + + /// Cast truncates the value to the given bit size and converts the type of the value in memory to that bit size. + pub(crate) fn cast_instruction( + &mut self, + destination: SingleAddrVariable, + source: SingleAddrVariable, + ) { + self.debug_show.cast_instruction(destination.address, source.address, destination.bit_size); + self.cast(destination, source); + } + + pub(crate) fn cast(&mut self, destination: SingleAddrVariable, source: SingleAddrVariable) { + self.push_opcode(BrilligOpcode::Cast { + destination: destination.address, + source: source.address, + bit_size: destination.bit_size, + }); + } + + /// Stores the value of `constant` in the `result` register + pub(crate) fn const_instruction(&mut self, result: SingleAddrVariable, constant: FieldElement) { + self.debug_show.const_instruction(result.address, constant); + self.constant(result, constant); + } + + fn constant(&mut self, result: SingleAddrVariable, constant: FieldElement) { + assert!( + result.bit_size >= constant.num_bits(), + "Constant {} does not fit in bit size {}", + constant, + result.bit_size + ); + if result.bit_size > 128 && constant.num_bits() > 128 { + let high = FieldElement::from_be_bytes_reduce( + constant.to_be_bytes().get(0..16).expect("FieldElement::to_be_bytes() too short!"), + ); + let low = FieldElement::from(constant.to_u128()); + let high_register = SingleAddrVariable::new(self.allocate_register(), 254); + let low_register = SingleAddrVariable::new(self.allocate_register(), 254); + let intermediate_register = SingleAddrVariable::new(self.allocate_register(), 254); + self.constant(high_register, high); + self.constant(low_register, low); + // I want to multiply high by 2^128, but I can't get that big constant in. + // So I'll multiply by 2^64 twice. + self.constant(intermediate_register, FieldElement::from(1_u128 << 64)); + self.binary(high_register, intermediate_register, high_register, BrilligBinaryOp::Mul); + self.binary(high_register, intermediate_register, high_register, BrilligBinaryOp::Mul); + // Now we can add. + self.binary(high_register, low_register, intermediate_register, BrilligBinaryOp::Add); + self.cast(result, intermediate_register); + self.deallocate_single_addr(high_register); + self.deallocate_single_addr(low_register); + self.deallocate_single_addr(intermediate_register); + } else { + self.push_opcode(BrilligOpcode::Const { + destination: result.address, + value: constant, + bit_size: result.bit_size, + }); + } + } + + pub(crate) fn usize_const_instruction( + &mut self, + result: MemoryAddress, + constant: FieldElement, + ) { + self.const_instruction(SingleAddrVariable::new_usize(result), constant); + } + + /// Returns a register which holds the value of a constant + pub(crate) fn make_constant_instruction( + &mut self, + constant: FieldElement, + bit_size: u32, + ) -> SingleAddrVariable { + let var = SingleAddrVariable::new(self.allocate_register(), bit_size); + self.const_instruction(var, constant); + var + } + + fn make_constant(&mut self, constant: FieldElement, bit_size: u32) -> SingleAddrVariable { + let var = SingleAddrVariable::new(self.allocate_register(), bit_size); + self.constant(var, constant); + var + } + + /// Returns a register which holds the value of an usize constant + pub(crate) fn make_usize_constant_instruction( + &mut self, + constant: FieldElement, + ) -> SingleAddrVariable { + let register = self.allocate_register(); + self.usize_const_instruction(register, constant); + SingleAddrVariable::new_usize(register) + } + + pub(super) fn calldata_copy_instruction( + &mut self, + destination: MemoryAddress, + calldata_size: usize, + offset: usize, + ) { + self.debug_show.calldata_copy_instruction(destination, calldata_size, offset); + + self.push_opcode(BrilligOpcode::CalldataCopy { + destination_address: destination, + size: calldata_size, + offset, + }); + } + + pub(super) fn trap_instruction(&mut self, revert_data: HeapArray) { + self.debug_show.trap_instruction(revert_data); + + self.push_opcode(BrilligOpcode::Trap { revert_data }); + } +} + +/// Type to encapsulate the binary operation types in Brillig +#[derive(Clone, Copy, Debug)] +pub(crate) enum BrilligBinaryOp { + Add, + Sub, + Mul, + FieldDiv, + UnsignedDiv, + Equals, + LessThan, + LessThanEquals, + And, + Or, + Xor, + Shl, + Shr, + // Modulo operation requires more than one brillig opcode + Modulo, +} + +impl From for BinaryFieldOp { + fn from(operation: BrilligBinaryOp) -> BinaryFieldOp { + match operation { + BrilligBinaryOp::Add => BinaryFieldOp::Add, + BrilligBinaryOp::Sub => BinaryFieldOp::Sub, + BrilligBinaryOp::Mul => BinaryFieldOp::Mul, + BrilligBinaryOp::FieldDiv => BinaryFieldOp::Div, + BrilligBinaryOp::UnsignedDiv => BinaryFieldOp::IntegerDiv, + BrilligBinaryOp::Equals => BinaryFieldOp::Equals, + BrilligBinaryOp::LessThan => BinaryFieldOp::LessThan, + BrilligBinaryOp::LessThanEquals => BinaryFieldOp::LessThanEquals, + _ => panic!("Unsupported operation: {:?} on a field", operation), + } + } +} + +impl From for BinaryIntOp { + fn from(operation: BrilligBinaryOp) -> BinaryIntOp { + match operation { + BrilligBinaryOp::Add => BinaryIntOp::Add, + BrilligBinaryOp::Sub => BinaryIntOp::Sub, + BrilligBinaryOp::Mul => BinaryIntOp::Mul, + BrilligBinaryOp::UnsignedDiv => BinaryIntOp::Div, + BrilligBinaryOp::Equals => BinaryIntOp::Equals, + BrilligBinaryOp::LessThan => BinaryIntOp::LessThan, + BrilligBinaryOp::LessThanEquals => BinaryIntOp::LessThanEquals, + BrilligBinaryOp::And => BinaryIntOp::And, + BrilligBinaryOp::Or => BinaryIntOp::Or, + BrilligBinaryOp::Xor => BinaryIntOp::Xor, + BrilligBinaryOp::Shl => BinaryIntOp::Shl, + BrilligBinaryOp::Shr => BinaryIntOp::Shr, + _ => panic!("Unsupported operation: {:?} on an integer", operation), + } + } +} diff --git a/compiler/noirc_evaluator/src/brillig/brillig_ir/registers.rs b/compiler/noirc_evaluator/src/brillig/brillig_ir/registers.rs index 8c0e36215a9..f756f06aa69 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_ir/registers.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_ir/registers.rs @@ -2,7 +2,7 @@ use acvm::acir::brillig::MemoryAddress; use crate::brillig::brillig_ir::entry_point::MAX_STACK_SIZE; -use super::ReservedRegisters; +use super::{brillig_variable::SingleAddrVariable, BrilligContext, ReservedRegisters}; /// Every brillig stack frame/call context has its own view of register space. /// This is maintained by copying these registers to the stack during calls and reading them back. @@ -81,3 +81,29 @@ impl BrilligRegistersContext { self.deallocated_registers.push(register_index); } } + +impl BrilligContext { + /// Returns the i'th register after the reserved ones + pub(crate) fn register(&self, i: usize) -> MemoryAddress { + MemoryAddress::from(ReservedRegisters::NUM_RESERVED_REGISTERS + i) + } + + /// Allocates an unused register. + pub(crate) fn allocate_register(&mut self) -> MemoryAddress { + self.registers.allocate_register() + } + + pub(crate) fn set_allocated_registers(&mut self, allocated_registers: Vec) { + self.registers = BrilligRegistersContext::from_preallocated_registers(allocated_registers); + } + + /// Push a register to the deallocation list, ready for reuse. + pub(crate) fn deallocate_register(&mut self, register_index: MemoryAddress) { + self.registers.deallocate_register(register_index); + } + + /// Deallocates the address where the single address variable is stored + pub(crate) fn deallocate_single_addr(&mut self, var: SingleAddrVariable) { + self.deallocate_register(var.address); + } +} diff --git a/compiler/noirc_evaluator/src/errors.rs b/compiler/noirc_evaluator/src/errors.rs index 40f4336e0b5..1e922060100 100644 --- a/compiler/noirc_evaluator/src/errors.rs +++ b/compiler/noirc_evaluator/src/errors.rs @@ -7,7 +7,7 @@ //! An Error of the former is a user Error //! //! An Error of the latter is an error in the implementation of the compiler -use acvm::{acir::native_types::Expression, FieldElement}; +use acvm::FieldElement; use iter_extended::vecmap; use noirc_errors::{CustomDiagnostic as Diagnostic, FileDiagnostic}; use thiserror::Error; @@ -17,13 +17,6 @@ use serde::{Deserialize, Serialize}; #[derive(Debug, PartialEq, Eq, Clone, Error)] pub enum RuntimeError { - #[error("{}", format_failed_constraint(.assert_message))] - FailedConstraint { - lhs: Box, - rhs: Box, - call_stack: CallStack, - assert_message: Option, - }, #[error(transparent)] InternalError(#[from] InternalError), #[error("Index out of bounds, array has size {array_size}, but index was {index}")] @@ -48,16 +41,8 @@ pub enum RuntimeError { BigIntModulus { call_stack: CallStack }, #[error("Slices cannot be returned from an unconstrained runtime to a constrained runtime")] UnconstrainedSliceReturnToConstrained { call_stack: CallStack }, -} - -// We avoid showing the actual lhs and rhs since most of the time they are just 0 -// and 1 respectively. This would confuse users if a constraint such as -// assert(foo < bar) fails with "failed constraint: 0 = 1." -fn format_failed_constraint(message: &Option) -> String { - match message { - Some(message) => format!("Failed constraint: '{message}'"), - None => "Failed constraint".to_owned(), - } + #[error("All `oracle` methods should be wrapped in an unconstrained fn")] + UnconstrainedOracleReturnToConstrained { call_stack: CallStack }, } #[derive(Debug, Clone, Serialize, Deserialize)] @@ -127,7 +112,6 @@ impl RuntimeError { | InternalError::UndeclaredAcirVar { call_stack } | InternalError::Unexpected { call_stack, .. }, ) - | RuntimeError::FailedConstraint { call_stack, .. } | RuntimeError::IndexOutOfBounds { call_stack, .. } | RuntimeError::InvalidRangeConstraint { call_stack, .. } | RuntimeError::TypeConversion { call_stack, .. } @@ -138,7 +122,8 @@ impl RuntimeError { | RuntimeError::UnsupportedIntegerSize { call_stack, .. } | RuntimeError::NestedSlice { call_stack, .. } | RuntimeError::BigIntModulus { call_stack, .. } - | RuntimeError::UnconstrainedSliceReturnToConstrained { call_stack } => call_stack, + | RuntimeError::UnconstrainedSliceReturnToConstrained { call_stack } + | RuntimeError::UnconstrainedOracleReturnToConstrained { call_stack } => call_stack, } } } diff --git a/compiler/noirc_evaluator/src/lib.rs b/compiler/noirc_evaluator/src/lib.rs index 70751d3e541..54376963338 100644 --- a/compiler/noirc_evaluator/src/lib.rs +++ b/compiler/noirc_evaluator/src/lib.rs @@ -11,4 +11,4 @@ pub mod ssa; pub mod brillig; -pub use ssa::create_circuit; +pub use ssa::create_program; diff --git a/compiler/noirc_evaluator/src/ssa.rs b/compiler/noirc_evaluator/src/ssa.rs index 0bb81efe977..80a63f223e7 100644 --- a/compiler/noirc_evaluator/src/ssa.rs +++ b/compiler/noirc_evaluator/src/ssa.rs @@ -7,25 +7,33 @@ //! This module heavily borrows from Cranelift #![allow(dead_code)] -use std::collections::BTreeSet; +use std::collections::{BTreeMap, BTreeSet}; -use crate::{ - brillig::Brillig, - errors::{RuntimeError, SsaReport}, -}; -use acvm::acir::{ - circuit::{Circuit, ExpressionWidth, PublicInputs}, - native_types::Witness, +use crate::errors::{RuntimeError, SsaReport}; +use acvm::{ + acir::{ + circuit::{ + brillig::BrilligBytecode, Circuit, ErrorSelector, ExpressionWidth, + Program as AcirProgram, PublicInputs, + }, + native_types::Witness, + }, + FieldElement, }; -use noirc_errors::debug_info::DebugInfo; +use noirc_errors::debug_info::{DebugFunctions, DebugInfo, DebugTypes, DebugVariables}; +use noirc_frontend::ast::Visibility; use noirc_frontend::{ - hir_def::function::FunctionSignature, monomorphization::ast::Program, Visibility, + hir_def::{function::FunctionSignature, types::Type as HirType}, + monomorphization::ast::Program, }; use tracing::{span, Level}; -use self::{acir_gen::GeneratedAcir, ssa_gen::Ssa}; +use self::{ + acir_gen::{Artifacts, GeneratedAcir}, + ssa_gen::Ssa, +}; mod acir_gen; pub(super) mod function_builder; @@ -35,75 +43,185 @@ pub mod ssa_gen; /// Optimize the given program by converting it into SSA /// form and performing optimizations there. When finished, -/// convert the final SSA into ACIR and return it. +/// convert the final SSA into an ACIR program and return it. +/// An ACIR program is made up of both ACIR functions +/// and Brillig functions for unconstrained execution. pub(crate) fn optimize_into_acir( program: Program, - print_ssa_passes: bool, + print_passes: bool, print_brillig_trace: bool, force_brillig_output: bool, -) -> Result { - let abi_distinctness = program.return_distinctness; - + print_timings: bool, +) -> Result { let ssa_gen_span = span!(Level::TRACE, "ssa_generation"); let ssa_gen_span_guard = ssa_gen_span.enter(); - let ssa = SsaBuilder::new(program, print_ssa_passes, force_brillig_output)? + let ssa = SsaBuilder::new(program, print_passes, force_brillig_output, print_timings)? .run_pass(Ssa::defunctionalize, "After Defunctionalization:") + .run_pass(Ssa::remove_paired_rc, "After Removing Paired rc_inc & rc_decs:") + .run_pass(Ssa::separate_runtime, "After Runtime Separation:") + .run_pass(Ssa::resolve_is_unconstrained, "After Resolving IsUnconstrained:") .run_pass(Ssa::inline_functions, "After Inlining:") // Run mem2reg with the CFG separated into blocks .run_pass(Ssa::mem2reg, "After Mem2Reg:") + .run_pass(Ssa::as_slice_optimization, "After `as_slice` optimization") .try_run_pass(Ssa::evaluate_assert_constant, "After Assert Constant:")? - .try_run_pass(Ssa::unroll_loops, "After Unrolling:")? + .try_run_pass(Ssa::unroll_loops_iteratively, "After Unrolling:")? .run_pass(Ssa::simplify_cfg, "After Simplifying:") .run_pass(Ssa::flatten_cfg, "After Flattening:") .run_pass(Ssa::remove_bit_shifts, "After Removing Bit Shifts:") // Run mem2reg once more with the flattened CFG to catch any remaining loads/stores .run_pass(Ssa::mem2reg, "After Mem2Reg:") + // Run the inlining pass again to handle functions with `InlineType::NoPredicates`. + // Before flattening is run, we treat functions marked with the `InlineType::NoPredicates` as an entry point. + // This pass must come immediately following `mem2reg` as the succeeding passes + // may create an SSA which inlining fails to handle. + .run_pass(Ssa::inline_functions_with_no_predicates, "After Inlining:") + .run_pass(Ssa::remove_if_else, "After Remove IfElse:") .run_pass(Ssa::fold_constants, "After Constant Folding:") - .run_pass( - Ssa::fold_constants_using_constraints, - "After Constant Folding With Constraint Info:", - ) + .run_pass(Ssa::remove_enable_side_effects, "After EnableSideEffects removal:") + .run_pass(Ssa::fold_constants_using_constraints, "After Constraint Folding:") .run_pass(Ssa::dead_instruction_elimination, "After Dead Instruction Elimination:") + .run_pass(Ssa::array_set_optimization, "After Array Set Optimizations:") .finish(); - let brillig = ssa.to_brillig(print_brillig_trace); + let brillig = time("SSA to Brillig", print_timings, || ssa.to_brillig(print_brillig_trace)); drop(ssa_gen_span_guard); - let last_array_uses = ssa.find_last_array_uses(); + time("SSA to ACIR", print_timings, || ssa.into_acir(&brillig)) +} - ssa.into_acir(brillig, abi_distinctness, &last_array_uses) +// Helper to time SSA passes +fn time(name: &str, print_timings: bool, f: impl FnOnce() -> T) -> T { + let start_time = chrono::Utc::now().time(); + let result = f(); + + if print_timings { + let end_time = chrono::Utc::now().time(); + println!("{name}: {} ms", (end_time - start_time).num_milliseconds()); + } + + result } -/// Compiles the [`Program`] into [`ACIR`][acvm::acir::circuit::Circuit]. +#[derive(Default)] +pub struct SsaProgramArtifact { + pub program: AcirProgram, + pub debug: Vec, + pub warnings: Vec, + pub main_input_witnesses: Vec, + pub main_return_witnesses: Vec, + pub names: Vec, + pub error_types: BTreeMap, +} + +impl SsaProgramArtifact { + fn new( + unconstrained_functions: Vec>, + error_types: BTreeMap, + ) -> Self { + let program = AcirProgram { functions: Vec::default(), unconstrained_functions }; + Self { + program, + debug: Vec::default(), + warnings: Vec::default(), + main_input_witnesses: Vec::default(), + main_return_witnesses: Vec::default(), + names: Vec::default(), + error_types, + } + } + + fn add_circuit(&mut self, mut circuit_artifact: SsaCircuitArtifact, is_main: bool) { + self.program.functions.push(circuit_artifact.circuit); + self.debug.push(circuit_artifact.debug_info); + self.warnings.append(&mut circuit_artifact.warnings); + if is_main { + self.main_input_witnesses = circuit_artifact.input_witnesses; + self.main_return_witnesses = circuit_artifact.return_witnesses; + } + self.names.push(circuit_artifact.name); + } +} + +/// Compiles the [`Program`] into [`ACIR``][acvm::acir::circuit::Program]. /// /// The output ACIR is is backend-agnostic and so must go through a transformation pass before usage in proof generation. #[allow(clippy::type_complexity)] #[tracing::instrument(level = "trace", skip_all)] -pub fn create_circuit( +pub fn create_program( program: Program, enable_ssa_logging: bool, enable_brillig_logging: bool, force_brillig_output: bool, -) -> Result<(Circuit, DebugInfo, Vec, Vec, Vec), RuntimeError> { + print_codegen_timings: bool, +) -> Result { let debug_variables = program.debug_variables.clone(); let debug_types = program.debug_types.clone(); - let func_sig = program.main_function_signature.clone(); + let debug_functions = program.debug_functions.clone(); + + let func_sigs = program.function_signatures.clone(); + let recursive = program.recursive; - let mut generated_acir = optimize_into_acir( + let (generated_acirs, generated_brillig, error_types) = optimize_into_acir( program, enable_ssa_logging, enable_brillig_logging, force_brillig_output, + print_codegen_timings, )?; + assert_eq!( + generated_acirs.len(), + func_sigs.len(), + "The generated ACIRs should match the supplied function signatures" + ); + + let mut program_artifact = SsaProgramArtifact::new(generated_brillig, error_types); + // For setting up the ABI we need separately specify main's input and return witnesses + let mut is_main = true; + for (acir, func_sig) in generated_acirs.into_iter().zip(func_sigs) { + let circuit_artifact = convert_generated_acir_into_circuit( + acir, + func_sig, + recursive, + // TODO: get rid of these clones + debug_variables.clone(), + debug_functions.clone(), + debug_types.clone(), + ); + program_artifact.add_circuit(circuit_artifact, is_main); + is_main = false; + } + + Ok(program_artifact) +} + +pub struct SsaCircuitArtifact { + name: String, + circuit: Circuit, + debug_info: DebugInfo, + warnings: Vec, + input_witnesses: Vec, + return_witnesses: Vec, +} + +fn convert_generated_acir_into_circuit( + mut generated_acir: GeneratedAcir, + func_sig: FunctionSignature, + recursive: bool, + debug_variables: DebugVariables, + debug_functions: DebugFunctions, + debug_types: DebugTypes, +) -> SsaCircuitArtifact { let opcodes = generated_acir.take_opcodes(); let current_witness_index = generated_acir.current_witness_index().0; let GeneratedAcir { return_witnesses, locations, input_witnesses, - assert_messages, + assertion_payloads: assert_messages, warnings, + name, .. } = generated_acir; @@ -130,13 +248,20 @@ pub fn create_circuit( .map(|(index, locations)| (index, locations.into_iter().collect())) .collect(); - let mut debug_info = DebugInfo::new(locations, debug_variables, debug_types); + let mut debug_info = DebugInfo::new(locations, debug_variables, debug_functions, debug_types); // Perform any ACIR-level optimizations let (optimized_circuit, transformation_map) = acvm::compiler::optimize(circuit); debug_info.update_acir(transformation_map); - Ok((optimized_circuit, debug_info, input_witnesses, return_witnesses, warnings)) + SsaCircuitArtifact { + name, + circuit: optimized_circuit, + debug_info, + warnings, + input_witnesses, + return_witnesses, + } } // Takes each function argument and partitions the circuit's inputs witnesses according to its visibility. @@ -177,6 +302,7 @@ fn split_public_and_private_inputs( struct SsaBuilder { ssa: Ssa, print_ssa_passes: bool, + print_codegen_timings: bool, } impl SsaBuilder { @@ -184,9 +310,10 @@ impl SsaBuilder { program: Program, print_ssa_passes: bool, force_brillig_runtime: bool, + print_codegen_timings: bool, ) -> Result { let ssa = ssa_gen::generate_ssa(program, force_brillig_runtime)?; - Ok(SsaBuilder { print_ssa_passes, ssa }.print("Initial SSA:")) + Ok(SsaBuilder { print_ssa_passes, print_codegen_timings, ssa }.print("Initial SSA:")) } fn finish(self) -> Ssa { @@ -195,7 +322,7 @@ impl SsaBuilder { /// Runs the given SSA pass and prints the SSA afterward if `print_ssa_passes` is true. fn run_pass(mut self, pass: fn(Ssa) -> Ssa, msg: &str) -> Self { - self.ssa = pass(self.ssa); + self.ssa = time(msg, self.print_codegen_timings, || pass(self.ssa)); self.print(msg) } @@ -205,14 +332,10 @@ impl SsaBuilder { pass: fn(Ssa) -> Result, msg: &str, ) -> Result { - self.ssa = pass(self.ssa)?; + self.ssa = time(msg, self.print_codegen_timings, || pass(self.ssa))?; 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/acir_gen/acir_ir/acir_variable.rs b/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs index fb11bae556c..ac7f2c09687 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,5 +1,5 @@ use super::big_int::BigIntContext; -use super::generated_acir::GeneratedAcir; +use super::generated_acir::{BrilligStdlibFunc, GeneratedAcir, PLACEHOLDER_BRILLIG_INDEX}; use crate::brillig::brillig_gen::brillig_directive; use crate::brillig::brillig_ir::artifact::GeneratedBrillig; use crate::errors::{InternalError, RuntimeError, SsaReport}; @@ -8,11 +8,12 @@ use crate::ssa::ir::dfg::CallStack; use crate::ssa::ir::types::Type as SsaType; use crate::ssa::ir::{instruction::Endian, types::NumericType}; use acvm::acir::circuit::brillig::{BrilligInputs, BrilligOutputs}; -use acvm::acir::circuit::opcodes::{BlockId, MemOp}; -use acvm::acir::circuit::Opcode; +use acvm::acir::circuit::opcodes::{BlockId, BlockType, MemOp}; +use acvm::acir::circuit::{AssertionPayload, ExpressionOrMemory, Opcode}; use acvm::blackbox_solver; -use acvm::brillig_vm::{brillig::Value, VMStatus, VM}; +use acvm::brillig_vm::{MemoryValue, VMStatus, VM}; use acvm::{ + acir::AcirField, acir::{ brillig::Opcode as BrilligOpcode, circuit::opcodes::FunctionInput, @@ -236,7 +237,10 @@ impl AcirContext { self.acir_ir.call_stack = call_stack; } - fn get_or_create_witness_var(&mut self, var: AcirVar) -> Result { + pub(crate) fn get_or_create_witness_var( + &mut self, + var: AcirVar, + ) -> Result { if self.var_to_expression(var)?.to_witness().is_some() { // If called with a variable which is already a witness then return the same variable. return Ok(var); @@ -251,13 +255,13 @@ impl AcirContext { } /// Converts an [`AcirVar`] to a [`Witness`] - fn var_to_witness(&mut self, var: AcirVar) -> Result { + pub(crate) fn var_to_witness(&mut self, var: AcirVar) -> Result { let expression = self.var_to_expression(var)?; let witness = if let Some(constant) = expression.to_const() { // Check if a witness has been assigned this value already, if so reuse it. *self .constant_witnesses - .entry(constant) + .entry(*constant) .or_insert_with(|| self.acir_ir.get_or_create_witness(&expression)) } else { self.acir_ir.get_or_create_witness(&expression) @@ -266,7 +270,10 @@ impl AcirContext { } /// Converts an [`AcirVar`] to an [`Expression`] - pub(crate) fn var_to_expression(&self, var: AcirVar) -> Result { + pub(crate) fn var_to_expression( + &self, + var: AcirVar, + ) -> Result, InternalError> { let var_data = match self.vars.get(&var) { Some(var_data) => var_data, None => { @@ -326,13 +333,15 @@ impl AcirContext { // Compute the inverse with brillig code let inverse_code = brillig_directive::directive_invert(); - let results = self.brillig( + let results = self.brillig_call( predicate, - inverse_code, + &inverse_code, vec![AcirValue::Var(var, AcirType::field())], vec![AcirType::field()], true, false, + PLACEHOLDER_BRILLIG_INDEX, + Some(BrilligStdlibFunc::Inverse), )?; let inverted_var = Self::expect_one_var(results); @@ -493,7 +502,7 @@ impl AcirContext { &mut self, lhs: AcirVar, rhs: AcirVar, - assert_message: Option, + assert_message: Option>, ) -> Result<(), RuntimeError> { let lhs_expr = self.var_to_expression(lhs)?; let rhs_expr = self.var_to_expression(rhs)?; @@ -509,14 +518,38 @@ impl AcirContext { } self.acir_ir.assert_is_zero(diff_expr); - if let Some(message) = assert_message { - self.acir_ir.assert_messages.insert(self.acir_ir.last_acir_opcode_location(), message); + if let Some(payload) = assert_message { + self.acir_ir + .assertion_payloads + .insert(self.acir_ir.last_acir_opcode_location(), payload); } self.mark_variables_equivalent(lhs, rhs)?; Ok(()) } + pub(crate) fn vars_to_expressions_or_memory( + &self, + values: &[AcirValue], + ) -> Result>, RuntimeError> { + let mut result = Vec::with_capacity(values.len()); + for value in values { + match value { + AcirValue::Var(var, _) => { + result.push(ExpressionOrMemory::Expression(self.var_to_expression(*var)?)); + } + AcirValue::Array(vars) => { + let vars_as_vec: Vec<_> = vars.iter().cloned().collect(); + result.extend(self.vars_to_expressions_or_memory(&vars_as_vec)?); + } + AcirValue::DynamicArray(AcirDynamicArray { block_id, .. }) => { + result.push(ExpressionOrMemory::Memory(*block_id)); + } + } + } + Ok(result) + } + /// Adds a new Variable to context whose value will /// be constrained to be the division of `lhs` and `rhs` pub(crate) fn div_var( @@ -585,13 +618,44 @@ impl AcirContext { expr.push_multiplication_term(FieldElement::one(), lhs_witness, rhs_witness); self.add_data(AcirVarData::Expr(expr)) } - ( - AcirVarData::Expr(_) | AcirVarData::Witness(_), - AcirVarData::Expr(_) | AcirVarData::Witness(_), - ) => { + (AcirVarData::Expr(expression), AcirVarData::Witness(witness)) + | (AcirVarData::Witness(witness), AcirVarData::Expr(expression)) + if expression.is_linear() => + { + let mut expr = Expression::default(); + for term in expression.linear_combinations.iter() { + expr.push_multiplication_term(term.0, term.1, witness); + } + expr.push_addition_term(expression.q_c, witness); + self.add_data(AcirVarData::Expr(expr)) + } + (AcirVarData::Expr(lhs_expr), AcirVarData::Expr(rhs_expr)) => { + let degree_one = if lhs_expr.is_linear() && rhs_expr.is_degree_one_univariate() { + Some((lhs_expr, rhs_expr)) + } else if rhs_expr.is_linear() && lhs_expr.is_degree_one_univariate() { + Some((rhs_expr, lhs_expr)) + } else { + None + }; + if let Some((lin, univariate)) = degree_one { + let mut expr = Expression::default(); + let rhs_term = univariate.linear_combinations[0]; + for term in lin.linear_combinations.iter() { + expr.push_multiplication_term(term.0 * rhs_term.0, term.1, rhs_term.1); + } + expr.push_addition_term(lin.q_c * rhs_term.0, rhs_term.1); + expr.sort(); + expr = expr.add_mul(univariate.q_c, &lin); + self.add_data(AcirVarData::Expr(expr)) + } else { + let lhs = self.get_or_create_witness_var(lhs)?; + let rhs = self.get_or_create_witness_var(rhs)?; + self.mul_var(lhs, rhs)? + } + } + _ => { let lhs = self.get_or_create_witness_var(lhs)?; let rhs = self.get_or_create_witness_var(rhs)?; - self.mul_var(lhs, rhs)? } }; @@ -660,7 +724,7 @@ impl AcirContext { // If `lhs` and `rhs` are known constants then we can calculate the result at compile time. // `rhs` must be non-zero. - (Some(lhs_const), Some(rhs_const), _) if rhs_const != FieldElement::zero() => { + (Some(lhs_const), Some(rhs_const), _) if !rhs_const.is_zero() => { let quotient = lhs_const.to_u128() / rhs_const.to_u128(); let remainder = lhs_const.to_u128() - quotient * rhs_const.to_u128(); @@ -670,7 +734,7 @@ impl AcirContext { } // If `rhs` is one then the division is a noop. - (_, Some(rhs_const), _) if rhs_const == FieldElement::one() => { + (_, Some(rhs_const), _) if rhs_const.is_one() => { return Ok((lhs, zero)); } @@ -711,9 +775,9 @@ impl AcirContext { } let [q_value, r_value]: [AcirValue; 2] = self - .brillig( + .brillig_call( predicate, - brillig_directive::directive_quotient(bit_size + 1), + &brillig_directive::directive_quotient(bit_size + 1), vec![ AcirValue::Var(lhs, AcirType::unsigned(bit_size)), AcirValue::Var(rhs, AcirType::unsigned(bit_size)), @@ -721,6 +785,8 @@ impl AcirContext { vec![AcirType::unsigned(max_q_bits), AcirType::unsigned(max_rhs_bits)], true, false, + PLACEHOLDER_BRILLIG_INDEX, + Some(BrilligStdlibFunc::Quotient(bit_size + 1)), )? .try_into() .expect("quotient only returns two values"); @@ -839,7 +905,7 @@ impl AcirContext { // Optimization when rhs is const and fits within a u128 let rhs_expr = self.var_to_expression(rhs)?; - if rhs_expr.is_const() && rhs_expr.q_c.fits_in_u128() { + if rhs_expr.is_const() && rhs_expr.q_c.num_bits() <= 128 { // We try to move the offset to rhs let rhs_offset = if self.is_constant_one(&offset) && rhs_expr.q_c.to_u128() >= 1 { lhs_offset = lhs; @@ -913,6 +979,7 @@ impl AcirContext { let max_power_of_two = self.add_constant( FieldElement::from(2_i128).pow(&FieldElement::from(bit_size as i128 - 1)), ); + let zero = self.add_constant(FieldElement::zero()); let one = self.add_constant(FieldElement::one()); // Get the sign bit of rhs by computing rhs / max_power_of_two @@ -932,10 +999,19 @@ impl AcirContext { // Unsigned to signed: derive q and r from q1,r1 and the signs of lhs and rhs // Quotient sign is lhs sign * rhs sign, whose resulting sign bit is the XOR of the sign bits let q_sign = self.xor_var(lhs_leading, rhs_leading, AcirType::unsigned(1))?; - let quotient = self.two_complement(q1, q_sign, bit_size)?; let remainder = self.two_complement(r1, lhs_leading, bit_size)?; + // Issue #5129 - When q1 is zero and quotient sign is -1, we compute -0=2^{bit_size}, + // which is not valid because we do not wrap integer operations + // Similar case can happen with the remainder. + let q_is_0 = self.eq_var(q1, zero)?; + let q_is_not_0 = self.not_var(q_is_0, AcirType::unsigned(1))?; + let quotient = self.mul_var(quotient, q_is_not_0)?; + let r_is_0 = self.eq_var(r1, zero)?; + let r_is_not_0 = self.not_var(r_is_0, AcirType::unsigned(1))?; + let remainder = self.mul_var(remainder, r_is_not_0)?; + Ok((quotient, remainder)) } @@ -951,15 +1027,6 @@ impl AcirContext { Ok(remainder) } - /// Converts the `AcirVar` to a `Witness` if it hasn't been already, and appends it to the - /// `GeneratedAcir`'s return witnesses. - pub(crate) fn return_var(&mut self, acir_var: AcirVar) -> Result<(), InternalError> { - let return_var = self.get_or_create_witness_var(acir_var)?; - let witness = self.var_to_witness(return_var)?; - self.acir_ir.push_return_witness(witness); - Ok(()) - } - /// Constrains the `AcirVar` variable to be of type `NumericType`. pub(crate) fn range_constrain_var( &mut self, @@ -981,9 +1048,10 @@ impl AcirContext { let witness = self.var_to_witness(witness_var)?; self.acir_ir.range_constraint(witness, *bit_size)?; if let Some(message) = message { - self.acir_ir - .assert_messages - .insert(self.acir_ir.last_acir_opcode_location(), message); + self.acir_ir.assertion_payloads.insert( + self.acir_ir.last_acir_opcode_location(), + AssertionPayload::StaticString(message.clone()), + ); } } NumericType::NativeField => { @@ -1261,7 +1329,8 @@ impl AcirContext { let modulus = self.big_int_ctx.modulus(bigint.modulus_id()); let bytes_len = ((modulus - BigUint::from(1_u32)).bits() - 1) / 8 + 1; output_count = bytes_len as usize; - (field_inputs, vec![FieldElement::from(bytes_len as u128)]) + assert!(bytes_len == 32); + (field_inputs, vec![]) } BlackBoxFunc::BigIntFromLeBytes => { let invalid_input = "ICE - bigint operation requires 2 inputs"; @@ -1294,6 +1363,21 @@ impl AcirContext { self.big_int_ctx.new_big_int(FieldElement::from(modulus_id as u128)); (modulus, vec![result_id.bigint_id(), result_id.modulus_id()]) } + BlackBoxFunc::AES128Encrypt => { + let invalid_input = "aes128_encrypt - operation requires a plaintext to encrypt"; + let input_size = match inputs.first().expect(invalid_input) { + AcirValue::Array(values) => Ok::(values.len()), + AcirValue::DynamicArray(dyn_array) => Ok::(dyn_array.len), + _ => { + return Err(RuntimeError::InternalError(InternalError::General { + message: "aes128_encrypt requires an array of inputs".to_string(), + call_stack: self.get_call_stack(), + })); + } + }?; + output_count = input_size + (16 - input_size % 16); + (vec![], vec![FieldElement::from(output_count as u128)]) + } _ => (vec![], vec![]), }; @@ -1445,9 +1529,11 @@ impl AcirContext { pub(crate) fn finish( mut self, inputs: Vec, + return_values: Vec, warnings: Vec, ) -> GeneratedAcir { self.acir_ir.input_witnesses = inputs; + self.acir_ir.return_witnesses = return_values; self.acir_ir.warnings = warnings; self.acir_ir } @@ -1463,30 +1549,36 @@ impl AcirContext { id } - pub(crate) fn brillig( + #[allow(clippy::too_many_arguments)] + pub(crate) fn brillig_call( &mut self, predicate: AcirVar, - generated_brillig: GeneratedBrillig, + generated_brillig: &GeneratedBrillig, inputs: Vec, outputs: Vec, attempt_execution: bool, unsafe_return_values: bool, + brillig_function_index: u32, + brillig_stdlib_func: Option, ) -> Result, RuntimeError> { - let b_inputs = try_vecmap(inputs, |i| -> Result<_, InternalError> { - match i { - AcirValue::Var(var, _) => Ok(BrilligInputs::Single(self.var_to_expression(var)?)), - AcirValue::Array(vars) => { - let mut var_expressions: Vec = Vec::new(); - for var in vars { - self.brillig_array_input(&mut var_expressions, var)?; + let brillig_inputs: Vec> = + try_vecmap(inputs, |i| -> Result<_, InternalError> { + match i { + AcirValue::Var(var, _) => { + Ok(BrilligInputs::Single(self.var_to_expression(var)?)) + } + AcirValue::Array(vars) => { + let mut var_expressions: Vec> = Vec::new(); + for var in vars { + self.brillig_array_input(&mut var_expressions, var)?; + } + Ok(BrilligInputs::Array(var_expressions)) + } + AcirValue::DynamicArray(AcirDynamicArray { block_id, .. }) => { + Ok(BrilligInputs::MemoryArray(block_id)) } - Ok(BrilligInputs::Array(var_expressions)) - } - AcirValue::DynamicArray(AcirDynamicArray { block_id, .. }) => { - Ok(BrilligInputs::MemoryArray(block_id)) } - } - })?; + })?; // Optimistically try executing the brillig now, if we can complete execution they just return the results. // This is a temporary measure pending SSA optimizations being applied to Brillig which would remove constant-input opcodes (See #2066) @@ -1495,29 +1587,37 @@ impl AcirContext { // the entire program will be replaced with witness constraints to its outputs. if attempt_execution { if let Some(brillig_outputs) = - self.execute_brillig(&generated_brillig.byte_code, &b_inputs, &outputs) + self.execute_brillig(&generated_brillig.byte_code, &brillig_inputs, &outputs) { return Ok(brillig_outputs); } } // Otherwise we must generate ACIR for it and execute at runtime. - let mut b_outputs = Vec::new(); + let mut brillig_outputs = Vec::new(); let outputs_var = vecmap(outputs, |output| match output { AcirType::NumericType(_) => { let witness_index = self.acir_ir.next_witness_index(); - b_outputs.push(BrilligOutputs::Simple(witness_index)); + brillig_outputs.push(BrilligOutputs::Simple(witness_index)); let var = self.add_data(AcirVarData::Witness(witness_index)); AcirValue::Var(var, output.clone()) } AcirType::Array(element_types, size) => { let (acir_value, witnesses) = self.brillig_array_output(&element_types, size); - b_outputs.push(BrilligOutputs::Array(witnesses)); + brillig_outputs.push(BrilligOutputs::Array(witnesses)); acir_value } }); let predicate = self.var_to_expression(predicate)?; - self.acir_ir.brillig(Some(predicate), generated_brillig, b_inputs, b_outputs); + + self.acir_ir.brillig_call( + Some(predicate), + generated_brillig, + brillig_inputs, + brillig_outputs, + brillig_function_index, + brillig_stdlib_func, + ); fn range_constraint_value( context: &mut AcirContext, @@ -1555,7 +1655,7 @@ impl AcirContext { fn brillig_array_input( &mut self, - var_expressions: &mut Vec, + var_expressions: &mut Vec>, input: AcirValue, ) -> Result<(), InternalError> { match input { @@ -1614,8 +1714,8 @@ impl AcirContext { fn execute_brillig( &mut self, - code: &[BrilligOpcode], - inputs: &[BrilligInputs], + code: &[BrilligOpcode], + inputs: &[BrilligInputs], outputs_types: &[AcirType], ) -> Option> { let mut memory = (execute_brillig(code, inputs)?).into_iter(); @@ -1640,7 +1740,7 @@ impl AcirContext { &mut self, element_types: &[AcirType], size: usize, - memory_iter: &mut impl Iterator, + memory_iter: &mut impl Iterator>, ) -> AcirValue { let mut array_values = im::Vector::new(); for _ in 0..size { @@ -1717,6 +1817,7 @@ impl AcirContext { block_id: BlockId, len: usize, optional_value: Option, + databus: BlockType, ) -> Result<(), InternalError> { let initialized_values = match optional_value { None => { @@ -1731,7 +1832,11 @@ impl AcirContext { } }; - self.acir_ir.push_opcode(Opcode::MemoryInit { block_id, init: initialized_values }); + self.acir_ir.push_opcode(Opcode::MemoryInit { + block_id, + init: initialized_values, + block_type: databus, + }); Ok(()) } @@ -1757,6 +1862,32 @@ impl AcirContext { } Ok(()) } + + pub(crate) fn call_acir_function( + &mut self, + id: u32, + inputs: Vec, + output_count: usize, + predicate: AcirVar, + ) -> Result, RuntimeError> { + let inputs = self.prepare_inputs_for_black_box_func_call(inputs)?; + let inputs = inputs + .iter() + .flat_map(|input| vecmap(input, |input| input.witness)) + .collect::>(); + let outputs = vecmap(0..output_count, |_| self.acir_ir.next_witness_index()); + + // Convert `Witness` values which are now constrained to be the output of the + // ACIR function call into `AcirVar`s. + // Similar to black box functions, we do not apply range information on the output of the function. + // See issue https://github.com/noir-lang/noir/issues/1439 + let results = + vecmap(&outputs, |witness_index| self.add_data(AcirVarData::Witness(*witness_index))); + + let predicate = Some(self.var_to_expression(predicate)?); + self.acir_ir.push_opcode(Opcode::Call { id, inputs, outputs, predicate }); + Ok(results) + } } /// Enum representing the possible values that a @@ -1764,7 +1895,7 @@ impl AcirContext { #[derive(Debug, Eq, Clone)] enum AcirVarData { Witness(Witness), - Expr(Expression), + Expr(Expression), Const(FieldElement), } @@ -1796,7 +1927,7 @@ impl AcirVarData { None } /// Converts all enum variants to an Expression. - pub(crate) fn to_expression(&self) -> Cow { + pub(crate) fn to_expression(&self) -> Cow> { match self { AcirVarData::Witness(witness) => Cow::Owned(Expression::from(*witness)), AcirVarData::Expr(expr) => Cow::Borrowed(expr), @@ -1817,11 +1948,11 @@ impl From for AcirVarData { } } -impl From for AcirVarData { - fn from(expr: Expression) -> Self { +impl From> for AcirVarData { + fn from(expr: Expression) -> Self { // Prefer simpler variants if possible. if let Some(constant) = expr.to_const() { - AcirVarData::from(constant) + AcirVarData::from(*constant) } else if let Some(witness) = expr.to_witness() { AcirVarData::from(witness) } else { @@ -1839,21 +1970,24 @@ pub(crate) struct AcirVar(usize); /// Returns the finished state of the Brillig VM if execution can complete. /// /// Returns `None` if complete execution of the Brillig bytecode is not possible. -fn execute_brillig(code: &[BrilligOpcode], inputs: &[BrilligInputs]) -> Option> { +fn execute_brillig( + code: &[BrilligOpcode], + inputs: &[BrilligInputs], +) -> Option>> { // Set input values - let mut calldata: Vec = Vec::new(); + let mut calldata: Vec = Vec::new(); // Each input represents a constant or array of constants. // Iterate over each input and push it into registers and/or memory. for input in inputs { match input { BrilligInputs::Single(expr) => { - calldata.push(expr.to_const()?.into()); + calldata.push(*expr.to_const()?); } BrilligInputs::Array(expr_arr) => { // Attempt to fetch all array input values for expr in expr_arr.iter() { - calldata.push(expr.to_const()?.into()); + calldata.push(*expr.to_const()?); } } BrilligInputs::MemoryArray(_) => { diff --git a/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/big_int.rs b/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/big_int.rs index c21188a8dbc..b9c596d80c7 100644 --- a/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/big_int.rs +++ b/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/big_int.rs @@ -1,4 +1,4 @@ -use acvm::FieldElement; +use acvm::{acir::AcirField, FieldElement}; use num_bigint::BigUint; /// Represents a bigint value in the form (id, modulus) where 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 1d05e998b13..9a09e7c06ee 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 @@ -7,25 +7,31 @@ use crate::{ errors::{InternalError, RuntimeError, SsaReport}, ssa::ir::dfg::CallStack, }; - use acvm::acir::{ circuit::{ - brillig::{Brillig as AcvmBrillig, BrilligInputs, BrilligOutputs}, + brillig::{BrilligInputs, BrilligOutputs}, opcodes::{BlackBoxFuncCall, FunctionInput, Opcode as AcirOpcode}, - OpcodeLocation, + AssertionPayload, OpcodeLocation, }, native_types::Witness, BlackBoxFunc, }; use acvm::{ + acir::AcirField, acir::{circuit::directives::Directive, native_types::Expression}, FieldElement, }; use iter_extended::vecmap; use num_bigint::BigUint; +/// Brillig calls such as for the Brillig std lib are resolved only after code generation is finished. +/// This index should be used when adding a Brillig call during code generation. +/// Code generation should then keep track of that unresolved call opcode which will be resolved with the +/// correct function index after code generation. +pub(crate) const PLACEHOLDER_BRILLIG_INDEX: u32 = 0; + #[derive(Debug, Default)] -/// The output of the Acir-gen pass +/// The output of the Acir-gen pass, which should only be produced for entry point Acir functions pub(crate) struct GeneratedAcir { /// The next witness index that may be declared. /// If witness index is `None` then we have not yet created a witness @@ -36,12 +42,9 @@ pub(crate) struct GeneratedAcir { current_witness_index: Option, /// The opcodes of which the compiled ACIR will comprise. - opcodes: Vec, + opcodes: Vec>, /// All witness indices that comprise the final return value of the program - /// - /// Note: This may contain repeated indices, which is necessary for later mapping into the - /// abi's return type. pub(crate) return_witnesses: Vec, /// All witness indices which are inputs to the main function @@ -55,9 +58,36 @@ pub(crate) struct GeneratedAcir { pub(crate) call_stack: CallStack, /// Correspondence between an opcode index and the error message associated with it. - pub(crate) assert_messages: BTreeMap, + pub(crate) assertion_payloads: BTreeMap>, pub(crate) warnings: Vec, + + /// Name for the corresponding entry point represented by this Acir-gen output. + /// Only used for debugging and benchmarking purposes + pub(crate) name: String, + + /// Maps the opcode index to a Brillig std library function call. + /// As to avoid passing the ACIR gen shared context into each individual ACIR + /// we can instead keep this map and resolve the Brillig calls at the end of code generation. + pub(crate) brillig_stdlib_func_locations: BTreeMap, +} + +#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)] +pub(crate) enum BrilligStdlibFunc { + Inverse, + // The Brillig quotient code is different depending upon the bit size. + Quotient(u32), +} + +impl BrilligStdlibFunc { + pub(crate) fn get_generated_brillig(&self) -> GeneratedBrillig { + match self { + BrilligStdlibFunc::Inverse => brillig_directive::directive_invert(), + BrilligStdlibFunc::Quotient(bit_size) => { + brillig_directive::directive_quotient(*bit_size) + } + } + } } impl GeneratedAcir { @@ -67,18 +97,18 @@ impl GeneratedAcir { } /// Adds a new opcode into ACIR. - pub(crate) fn push_opcode(&mut self, opcode: AcirOpcode) { + pub(crate) fn push_opcode(&mut self, opcode: AcirOpcode) { self.opcodes.push(opcode); if !self.call_stack.is_empty() { self.locations.insert(self.last_acir_opcode_location(), self.call_stack.clone()); } } - pub(crate) fn opcodes(&self) -> &[AcirOpcode] { + pub(crate) fn opcodes(&self) -> &[AcirOpcode] { &self.opcodes } - pub(crate) fn take_opcodes(&mut self) -> Vec { + pub(crate) fn take_opcodes(&mut self) -> Vec> { std::mem::take(&mut self.opcodes) } @@ -97,7 +127,7 @@ impl GeneratedAcir { /// /// If `expr` can be represented as a `Witness` then this function will return it, /// else a new opcode will be added to create a `Witness` that is equal to `expr`. - pub(crate) fn get_or_create_witness(&mut self, expr: &Expression) -> Witness { + pub(crate) fn get_or_create_witness(&mut self, expr: &Expression) -> Witness { match expr.to_witness() { Some(witness) => witness, None => self.create_witness_for_expression(expr), @@ -110,7 +140,10 @@ impl GeneratedAcir { /// This means you cannot multiply an infinite amount of `Expression`s together. /// Once the `Expression` goes over degree-2, then it needs to be reduced to a `Witness` /// which has degree-1 in order to be able to continue the multiplication chain. - pub(crate) fn create_witness_for_expression(&mut self, expression: &Expression) -> Witness { + pub(crate) fn create_witness_for_expression( + &mut self, + expression: &Expression, + ) -> Witness { let fresh_witness = self.next_witness_index(); // Create a constraint that sets them to be equal to each other @@ -128,11 +161,6 @@ impl GeneratedAcir { fresh_witness } - - /// Adds a witness index to the program's return witnesses. - pub(crate) fn push_return_witness(&mut self, witness: Witness) { - self.return_witnesses.push(witness); - } } impl GeneratedAcir { @@ -156,6 +184,18 @@ impl GeneratedAcir { let outputs_clone = outputs.clone(); let black_box_func_call = match func_name { + BlackBoxFunc::AES128Encrypt => BlackBoxFuncCall::AES128Encrypt { + inputs: inputs[0].clone(), + iv: inputs[1] + .clone() + .try_into() + .expect("Compiler should generate correct size inputs"), + key: inputs[2] + .clone() + .try_into() + .expect("Compiler should generate correct size inputs"), + outputs, + }, BlackBoxFunc::AND => { BlackBoxFuncCall::AND { lhs: inputs[0][0], rhs: inputs[1][0], output: outputs[0] } } @@ -163,17 +203,27 @@ impl GeneratedAcir { BlackBoxFuncCall::XOR { lhs: inputs[0][0], rhs: inputs[1][0], output: outputs[0] } } BlackBoxFunc::RANGE => BlackBoxFuncCall::RANGE { input: inputs[0][0] }, - BlackBoxFunc::SHA256 => BlackBoxFuncCall::SHA256 { inputs: inputs[0].clone(), outputs }, - BlackBoxFunc::Blake2s => { - BlackBoxFuncCall::Blake2s { inputs: inputs[0].clone(), outputs } - } - BlackBoxFunc::Blake3 => BlackBoxFuncCall::Blake3 { inputs: inputs[0].clone(), outputs }, + BlackBoxFunc::SHA256 => BlackBoxFuncCall::SHA256 { + inputs: inputs[0].clone(), + outputs: outputs.try_into().expect("Compiler should generate correct size outputs"), + }, + BlackBoxFunc::Blake2s => BlackBoxFuncCall::Blake2s { + inputs: inputs[0].clone(), + outputs: outputs.try_into().expect("Compiler should generate correct size outputs"), + }, + BlackBoxFunc::Blake3 => BlackBoxFuncCall::Blake3 { + inputs: inputs[0].clone(), + outputs: outputs.try_into().expect("Compiler should generate correct size outputs"), + }, BlackBoxFunc::SchnorrVerify => { BlackBoxFuncCall::SchnorrVerify { public_key_x: inputs[0][0], public_key_y: inputs[1][0], // Schnorr signature is an r & s, 32 bytes each - signature: inputs[2].clone(), + signature: inputs[2] + .clone() + .try_into() + .expect("Compiler should generate correct size inputs"), message: inputs[3].clone(), output: outputs[0], } @@ -191,38 +241,61 @@ impl GeneratedAcir { BlackBoxFunc::EcdsaSecp256k1 => { BlackBoxFuncCall::EcdsaSecp256k1 { // 32 bytes for each public key co-ordinate - public_key_x: inputs[0].clone(), - public_key_y: inputs[1].clone(), + public_key_x: inputs[0] + .clone() + .try_into() + .expect("Compiler should generate correct size inputs"), + public_key_y: inputs[1] + .clone() + .try_into() + .expect("Compiler should generate correct size inputs"), // (r,s) are both 32 bytes each, so signature // takes up 64 bytes - signature: inputs[2].clone(), - hashed_message: inputs[3].clone(), + signature: inputs[2] + .clone() + .try_into() + .expect("Compiler should generate correct size inputs"), + hashed_message: inputs[3] + .clone() + .try_into() + .expect("Compiler should generate correct size inputs"), output: outputs[0], } } BlackBoxFunc::EcdsaSecp256r1 => { BlackBoxFuncCall::EcdsaSecp256r1 { // 32 bytes for each public key co-ordinate - public_key_x: inputs[0].clone(), - public_key_y: inputs[1].clone(), + public_key_x: inputs[0] + .clone() + .try_into() + .expect("Compiler should generate correct size inputs"), + public_key_y: inputs[1] + .clone() + .try_into() + .expect("Compiler should generate correct size inputs"), // (r,s) are both 32 bytes each, so signature // takes up 64 bytes - signature: inputs[2].clone(), - hashed_message: inputs[3].clone(), + signature: inputs[2] + .clone() + .try_into() + .expect("Compiler should generate correct size inputs"), + hashed_message: inputs[3] + .clone() + .try_into() + .expect("Compiler should generate correct size inputs"), output: outputs[0], } } - BlackBoxFunc::FixedBaseScalarMul => BlackBoxFuncCall::FixedBaseScalarMul { - low: inputs[0][0], - high: inputs[1][0], - outputs: (outputs[0], outputs[1]), + BlackBoxFunc::MultiScalarMul => BlackBoxFuncCall::MultiScalarMul { + points: inputs[0].clone(), + scalars: inputs[1].clone(), + outputs: (outputs[0], outputs[1], outputs[2]), }, + BlackBoxFunc::EmbeddedCurveAdd => BlackBoxFuncCall::EmbeddedCurveAdd { - input1_x: inputs[0][0], - input1_y: inputs[1][0], - input2_x: inputs[2][0], - input2_y: inputs[3][0], - outputs: (outputs[0], outputs[1]), + input1: Box::new([inputs[0][0], inputs[1][0], inputs[2][0]]), + input2: Box::new([inputs[3][0], inputs[4][0], inputs[5][0]]), + outputs: (outputs[0], outputs[1], outputs[2]), }, BlackBoxFunc::Keccak256 => { let var_message_size = match inputs.to_vec().pop() { @@ -236,15 +309,21 @@ impl GeneratedAcir { } }; - BlackBoxFuncCall::Keccak256VariableLength { + BlackBoxFuncCall::Keccak256 { inputs: inputs[0].clone(), var_message_size, - outputs, + outputs: outputs + .try_into() + .expect("Compiler should generate correct size outputs"), } } - BlackBoxFunc::Keccakf1600 => { - BlackBoxFuncCall::Keccakf1600 { inputs: inputs[0].clone(), outputs } - } + BlackBoxFunc::Keccakf1600 => BlackBoxFuncCall::Keccakf1600 { + inputs: inputs[0] + .clone() + .try_into() + .expect("Compiler should generate correct size inputs"), + outputs: outputs.try_into().expect("Compiler should generate correct size outputs"), + }, BlackBoxFunc::RecursiveAggregation => BlackBoxFuncCall::RecursiveAggregation { verification_key: inputs[0].clone(), proof: inputs[1].clone(), @@ -286,9 +365,15 @@ impl GeneratedAcir { len: constant_inputs[0].to_u128() as u32, }, BlackBoxFunc::Sha256Compression => BlackBoxFuncCall::Sha256Compression { - inputs: inputs[0].clone(), - hash_values: inputs[1].clone(), - outputs, + inputs: inputs[0] + .clone() + .try_into() + .expect("Compiler should generate correct size inputs"), + hash_values: inputs[1] + .clone() + .try_into() + .expect("Compiler should generate correct size inputs"), + outputs: outputs.try_into().expect("Compiler should generate correct size outputs"), }, }; @@ -303,7 +388,7 @@ impl GeneratedAcir { /// Only radix that are a power of two are supported pub(crate) fn radix_le_decompose( &mut self, - input_expr: &Expression, + input_expr: &Expression, radix: u32, limb_count: u32, bit_size: u32, @@ -341,55 +426,6 @@ impl GeneratedAcir { Ok(limb_witnesses) } - /// Returns an expression which represents `lhs * rhs` - /// - /// If one has multiplicative term and the other is of degree one or more, - /// the function creates [intermediate variables][`Witness`] accordingly. - /// There are two cases where we can optimize the multiplication between two expressions: - /// 1. If the sum of the degrees of both expressions is at most 2, then we can just multiply them - /// as each term in the result will be degree-2. - /// 2. If one expression is a constant, then we can just multiply the constant with the other expression - /// - /// (1) is because an [`Expression`] can hold at most a degree-2 univariate polynomial - /// which is what you get when you multiply two degree-1 univariate polynomials. - pub(crate) fn mul_with_witness(&mut self, lhs: &Expression, rhs: &Expression) -> Expression { - use std::borrow::Cow; - let lhs_is_linear = lhs.is_linear(); - let rhs_is_linear = rhs.is_linear(); - - // Case 1: The sum of the degrees of both expressions is at most 2. - // - // If one of the expressions is constant then it does not increase the degree when multiplying by another expression. - // If both of the expressions are linear (degree <=1) then the product will be at most degree 2. - let both_are_linear = lhs_is_linear && rhs_is_linear; - let either_is_const = lhs.is_const() || rhs.is_const(); - if both_are_linear || either_is_const { - return (lhs * rhs).expect("Both expressions are degree <= 1"); - } - - // Case 2: One or both of the sides needs to be reduced to a degree-1 univariate polynomial - let lhs_reduced = if lhs_is_linear { - Cow::Borrowed(lhs) - } else { - Cow::Owned(self.get_or_create_witness(lhs).into()) - }; - - // If the lhs and rhs are the same, then we do not need to reduce - // rhs, we only need to square the lhs. - if lhs == rhs { - return (&*lhs_reduced * &*lhs_reduced) - .expect("Both expressions are reduced to be degree <= 1"); - }; - - let rhs_reduced = if rhs_is_linear { - Cow::Borrowed(rhs) - } else { - Cow::Owned(self.get_or_create_witness(rhs).into()) - }; - - (&*lhs_reduced * &*rhs_reduced).expect("Both expressions are reduced to be degree <= 1") - } - /// Adds an inversion brillig opcode. /// /// This code will invert `expr` without applying constraints @@ -398,7 +434,7 @@ impl GeneratedAcir { /// /// Safety: It is the callers responsibility to ensure that the /// resulting `Witness` is constrained to be the inverse. - pub(crate) fn brillig_inverse(&mut self, expr: Expression) -> Witness { + pub(crate) fn brillig_inverse(&mut self, expr: Expression) -> Witness { // Create the witness for the result let inverted_witness = self.next_witness_index(); @@ -406,7 +442,14 @@ impl GeneratedAcir { let inverse_code = brillig_directive::directive_invert(); let inputs = vec![BrilligInputs::Single(expr)]; let outputs = vec![BrilligOutputs::Simple(inverted_witness)]; - self.brillig(Some(Expression::one()), inverse_code, inputs, outputs); + self.brillig_call( + Some(Expression::one()), + &inverse_code, + inputs, + outputs, + PLACEHOLDER_BRILLIG_INDEX, + Some(BrilligStdlibFunc::Inverse), + ); inverted_witness } @@ -415,14 +458,18 @@ impl GeneratedAcir { /// /// If `expr` is not zero, then the constraint system will /// fail upon verification. - pub(crate) fn assert_is_zero(&mut self, expr: Expression) { + pub(crate) fn assert_is_zero(&mut self, expr: Expression) { self.push_opcode(AcirOpcode::AssertZero(expr)); } /// Returns a `Witness` that is constrained to be: /// - `1` if `lhs == rhs` /// - `0` otherwise - pub(crate) fn is_equal(&mut self, lhs: &Expression, rhs: &Expression) -> Witness { + pub(crate) fn is_equal( + &mut self, + lhs: &Expression, + rhs: &Expression, + ) -> Witness { let t = lhs - rhs; self.is_zero(&t) @@ -480,7 +527,7 @@ impl GeneratedAcir { /// By setting `z` to be `0`, we can make `y` equal to `1`. /// This is easily observed: `y = 1 - t * 0` /// Now since `y` is one, this means that `t` needs to be zero, or else `y * t == 0` will fail. - fn is_zero(&mut self, t_expr: &Expression) -> Witness { + fn is_zero(&mut self, t_expr: &Expression) -> Witness { // We're checking for equality with zero so we can negate the expression without changing the result. // This is useful as it will sometimes allow us to simplify an expression down to a witness. let t_witness = if let Some(witness) = t_expr.to_witness() { @@ -539,34 +586,59 @@ impl GeneratedAcir { Ok(()) } - pub(crate) fn brillig( + pub(crate) fn brillig_call( &mut self, - predicate: Option, - generated_brillig: GeneratedBrillig, - inputs: Vec, + predicate: Option>, + generated_brillig: &GeneratedBrillig, + inputs: Vec>, outputs: Vec, + brillig_function_index: u32, + stdlib_func: Option, ) { - let opcode = AcirOpcode::Brillig(AcvmBrillig { - inputs, - outputs, - bytecode: generated_brillig.byte_code, - predicate, - }); + let opcode = + AcirOpcode::BrilligCall { id: brillig_function_index, inputs, outputs, predicate }; self.push_opcode(opcode); - for (brillig_index, call_stack) in generated_brillig.locations { + if let Some(stdlib_func) = stdlib_func { + self.brillig_stdlib_func_locations + .insert(self.last_acir_opcode_location(), stdlib_func); + } + + for (brillig_index, call_stack) in generated_brillig.locations.iter() { self.locations.insert( - OpcodeLocation::Brillig { acir_index: self.opcodes.len() - 1, brillig_index }, - call_stack, + OpcodeLocation::Brillig { + acir_index: self.opcodes.len() - 1, + brillig_index: *brillig_index, + }, + call_stack.clone(), ); } - for (brillig_index, message) in generated_brillig.assert_messages { - self.assert_messages.insert( - OpcodeLocation::Brillig { acir_index: self.opcodes.len() - 1, brillig_index }, - message, + for (brillig_index, message) in generated_brillig.assert_messages.iter() { + self.assertion_payloads.insert( + OpcodeLocation::Brillig { + acir_index: self.opcodes.len() - 1, + brillig_index: *brillig_index, + }, + AssertionPayload::StaticString(message.clone()), ); } } + // We can only resolve the Brillig stdlib after having processed the entire ACIR + pub(crate) fn resolve_brillig_stdlib_call( + &mut self, + opcode_location: OpcodeLocation, + brillig_function_index: u32, + ) { + let acir_index = match opcode_location { + OpcodeLocation::Acir(index) => index, + _ => panic!("should not have brillig index"), + }; + match &mut self.opcodes[acir_index] { + AcirOpcode::BrilligCall { id, .. } => *id = brillig_function_index, + _ => panic!("expected brillig call opcode"), + } + } + pub(crate) fn last_acir_opcode_location(&self) -> OpcodeLocation { OpcodeLocation::Acir(self.opcodes.len() - 1) } @@ -581,7 +653,8 @@ fn black_box_func_expected_input_size(name: BlackBoxFunc) -> Option { // All of the hash/cipher methods will take in a // variable number of inputs. - BlackBoxFunc::Keccak256 + BlackBoxFunc::AES128Encrypt + | BlackBoxFunc::Keccak256 | BlackBoxFunc::SHA256 | BlackBoxFunc::Blake2s | BlackBoxFunc::Blake3 @@ -604,15 +677,14 @@ fn black_box_func_expected_input_size(name: BlackBoxFunc) -> Option { | BlackBoxFunc::EcdsaSecp256k1 | BlackBoxFunc::EcdsaSecp256r1 => None, - // Inputs for fixed based scalar multiplication - // is the low and high limbs of the scalar - BlackBoxFunc::FixedBaseScalarMul => Some(2), + // Inputs for multi scalar multiplication is an arbitrary number of [point, scalar] pairs. + BlackBoxFunc::MultiScalarMul => None, // Recursive aggregation has a variable number of inputs BlackBoxFunc::RecursiveAggregation => None, - // Addition over the embedded curve: input are coordinates (x1,y1) and (x2,y2) of the Grumpkin points - BlackBoxFunc::EmbeddedCurveAdd => Some(4), + // Addition over the embedded curve: input are coordinates (x1,y1,infinite1) and (x2,y2,infinite2) of the Grumpkin points + BlackBoxFunc::EmbeddedCurveAdd => Some(6), // Big integer operations take in 0 inputs. They use constants for their inputs. BlackBoxFunc::BigIntAdd @@ -662,7 +734,7 @@ fn black_box_expected_output_size(name: BlackBoxFunc) -> Option { // Output of operations over the embedded curve // will be 2 field elements representing the point. - BlackBoxFunc::FixedBaseScalarMul | BlackBoxFunc::EmbeddedCurveAdd => Some(2), + BlackBoxFunc::MultiScalarMul | BlackBoxFunc::EmbeddedCurveAdd => Some(3), // Big integer operations return a big integer BlackBoxFunc::BigIntAdd @@ -676,6 +748,9 @@ fn black_box_expected_output_size(name: BlackBoxFunc) -> Option { // Recursive aggregation has a variable number of outputs BlackBoxFunc::RecursiveAggregation => None, + + // AES encryption returns a variable number of outputs + BlackBoxFunc::AES128Encrypt => None, } } diff --git a/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs b/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs index 8d4d0668534..2aac083d727 100644 --- a/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs +++ b/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs @@ -1,13 +1,16 @@ //! This file holds the pass to convert from Noir's SSA IR to ACIR. mod acir_ir; -use std::collections::HashSet; +use std::collections::{BTreeMap, HashSet}; use std::fmt::Debug; use self::acir_ir::acir_variable::{AcirContext, AcirType, AcirVar}; +use self::acir_ir::generated_acir::BrilligStdlibFunc; use super::function_builder::data_bus::DataBus; use super::ir::dfg::CallStack; -use super::ir::instruction::ConstrainError; +use super::ir::function::FunctionId; +use super::ir::instruction::{ConstrainError, ErrorType}; +use super::ir::printer::try_to_extract_string_from_error_payload; use super::{ ir::{ dfg::DataFlowGraph, @@ -21,26 +24,120 @@ use super::{ }, ssa_gen::Ssa, }; -use crate::brillig::brillig_ir::artifact::GeneratedBrillig; +use crate::brillig::brillig_ir::artifact::{BrilligParameter, GeneratedBrillig}; use crate::brillig::brillig_ir::BrilligContext; use crate::brillig::{brillig_gen::brillig_fn::FunctionContext as BrilligFunctionContext, Brillig}; use crate::errors::{InternalError, InternalWarning, RuntimeError, SsaReport}; pub(crate) use acir_ir::generated_acir::GeneratedAcir; +use acvm::acir::circuit::opcodes::BlockType; +use noirc_frontend::monomorphization::ast::InlineType; +use acvm::acir::circuit::brillig::BrilligBytecode; +use acvm::acir::circuit::{AssertionPayload, ErrorSelector, OpcodeLocation}; use acvm::acir::native_types::Witness; use acvm::acir::BlackBoxFunc; -use acvm::{ - acir::{circuit::opcodes::BlockId, native_types::Expression}, - FieldElement, -}; +use acvm::{acir::circuit::opcodes::BlockId, acir::AcirField, FieldElement}; use fxhash::FxHashMap as HashMap; use im::Vector; use iter_extended::{try_vecmap, vecmap}; -use noirc_frontend::Distinctness; + +#[derive(Default)] +struct SharedContext { + /// Final list of Brillig functions which will be part of the final program + /// This is shared across `Context` structs as we want one list of Brillig + /// functions across all ACIR artifacts + generated_brillig: Vec, + + /// Maps SSA function index -> Final generated Brillig artifact index. + /// There can be Brillig functions specified in SSA which do not act as + /// entry points in ACIR (e.g. only called by other Brillig functions) + /// This mapping is necessary to use the correct function pointer for a Brillig call. + /// This uses the brillig parameters in the map since using slices with different lengths + /// needs to create different brillig entrypoints + brillig_generated_func_pointers: BTreeMap<(FunctionId, Vec), u32>, + + /// Maps a Brillig std lib function (a handwritten primitive such as for inversion) -> Final generated Brillig artifact index. + /// A separate mapping from normal Brillig calls is necessary as these methods do not have an associated function id from SSA. + brillig_stdlib_func_pointer: HashMap, + + /// Keeps track of Brillig std lib calls per function that need to still be resolved + /// with the correct function pointer from the `brillig_stdlib_func_pointer` map. + brillig_stdlib_calls_to_resolve: HashMap>, +} + +impl SharedContext { + fn generated_brillig_pointer( + &self, + func_id: FunctionId, + arguments: Vec, + ) -> Option<&u32> { + self.brillig_generated_func_pointers.get(&(func_id, arguments)) + } + + fn generated_brillig(&self, func_pointer: usize) -> &GeneratedBrillig { + &self.generated_brillig[func_pointer] + } + + fn insert_generated_brillig( + &mut self, + func_id: FunctionId, + arguments: Vec, + generated_pointer: u32, + code: GeneratedBrillig, + ) { + self.brillig_generated_func_pointers.insert((func_id, arguments), generated_pointer); + self.generated_brillig.push(code); + } + + fn new_generated_pointer(&self) -> u32 { + self.generated_brillig.len() as u32 + } + + fn generate_brillig_calls_to_resolve( + &mut self, + brillig_stdlib_func: &BrilligStdlibFunc, + func_id: FunctionId, + opcode_location: OpcodeLocation, + ) { + if let Some(generated_pointer) = + self.brillig_stdlib_func_pointer.get(brillig_stdlib_func).copied() + { + self.add_call_to_resolve(func_id, (opcode_location, generated_pointer)); + } else { + let code = brillig_stdlib_func.get_generated_brillig(); + let generated_pointer = self.new_generated_pointer(); + self.insert_generated_brillig_stdlib( + *brillig_stdlib_func, + generated_pointer, + func_id, + opcode_location, + code, + ); + } + } + + /// Insert a newly generated Brillig stdlib function + fn insert_generated_brillig_stdlib( + &mut self, + brillig_stdlib_func: BrilligStdlibFunc, + generated_pointer: u32, + func_id: FunctionId, + opcode_location: OpcodeLocation, + code: GeneratedBrillig, + ) { + self.brillig_stdlib_func_pointer.insert(brillig_stdlib_func, generated_pointer); + self.add_call_to_resolve(func_id, (opcode_location, generated_pointer)); + self.generated_brillig.push(code); + } + + fn add_call_to_resolve(&mut self, func_id: FunctionId, call_to_resolve: (OpcodeLocation, u32)) { + self.brillig_stdlib_calls_to_resolve.entry(func_id).or_default().push(call_to_resolve); + } +} /// Context struct for the acir generation pass. /// May be similar to the Evaluator struct in the current SSA IR. -struct Context { +struct Context<'a> { /// Maps SSA values to `AcirVar`. /// /// This is needed so that we only create a single @@ -90,6 +187,9 @@ struct Context { max_block_id: u32, data_bus: DataBus, + + /// Contains state that is generated and also used across ACIR functions + shared_context: &'a mut SharedContext, } #[derive(Clone)] @@ -174,41 +274,64 @@ impl AcirValue { } } +pub(crate) type Artifacts = + (Vec, Vec>, BTreeMap); + impl Ssa { #[tracing::instrument(level = "trace", skip_all)] - pub(crate) fn into_acir( - self, - brillig: Brillig, - abi_distinctness: Distinctness, - last_array_uses: &HashMap, - ) -> Result { - let context = Context::new(); - let mut generated_acir = context.convert_ssa(self, brillig, last_array_uses)?; - - match abi_distinctness { - Distinctness::Distinct => { - // Create a witness for each return witness we have - // to guarantee that the return witnesses are distinct - let distinct_return_witness: Vec<_> = generated_acir - .return_witnesses - .clone() - .into_iter() - .map(|return_witness| { - generated_acir - .create_witness_for_expression(&Expression::from(return_witness)) - }) - .collect(); + pub(crate) fn into_acir(self, brillig: &Brillig) -> Result { + let mut acirs = Vec::new(); + // TODO: can we parallelise this? + let mut shared_context = SharedContext::default(); + for function in self.functions.values() { + let context = Context::new(&mut shared_context); + if let Some(mut generated_acir) = + context.convert_ssa_function(&self, function, brillig)? + { + // We want to be able to insert Brillig stdlib functions anywhere during the ACIR generation process (e.g. such as on the `GeneratedAcir`). + // As we don't want a reference to the `SharedContext` on the generated ACIR itself, + // we instead store the opcode location at which a Brillig call to a std lib function occurred. + // We then defer resolving the function IDs of those Brillig functions to when we have generated Brillig + // for all normal Brillig calls. + for (opcode_location, brillig_stdlib_func) in + &generated_acir.brillig_stdlib_func_locations + { + shared_context.generate_brillig_calls_to_resolve( + brillig_stdlib_func, + function.id(), + *opcode_location, + ); + } + + // Fetch the Brillig stdlib calls to resolve for this function + if let Some(calls_to_resolve) = + shared_context.brillig_stdlib_calls_to_resolve.get(&function.id()) + { + // Resolve the Brillig stdlib calls + // We have to do a separate loop as the generated ACIR cannot be borrowed as mutable after an immutable borrow + for (opcode_location, brillig_function_pointer) in calls_to_resolve { + generated_acir.resolve_brillig_stdlib_call( + *opcode_location, + *brillig_function_pointer, + ); + } + } - generated_acir.return_witnesses = distinct_return_witness; - Ok(generated_acir) + generated_acir.name = function.name().to_owned(); + acirs.push(generated_acir); } - Distinctness::DuplicationAllowed => Ok(generated_acir), } + + let brillig = vecmap(shared_context.generated_brillig, |brillig| BrilligBytecode { + bytecode: brillig.byte_code, + }); + + Ok((acirs, brillig, self.error_selector_to_type)) } } -impl Context { - fn new() -> Context { +impl<'a> Context<'a> { + fn new(shared_context: &'a mut SharedContext) -> Context<'a> { let mut acir_context = AcirContext::default(); let current_side_effects_enabled_var = acir_context.add_constant(FieldElement::one()); @@ -222,20 +345,39 @@ impl Context { internal_mem_block_lengths: HashMap::default(), max_block_id: 0, data_bus: DataBus::default(), + shared_context, } } - /// Converts SSA into ACIR - fn convert_ssa( + fn convert_ssa_function( self, - ssa: Ssa, - brillig: Brillig, - last_array_uses: &HashMap, - ) -> Result { - let main_func = ssa.main(); - match main_func.runtime() { - RuntimeType::Acir => self.convert_acir_main(main_func, &ssa, brillig, last_array_uses), - RuntimeType::Brillig => self.convert_brillig_main(main_func, brillig), + ssa: &Ssa, + function: &Function, + brillig: &Brillig, + ) -> Result, RuntimeError> { + match function.runtime() { + RuntimeType::Acir(inline_type) => { + match inline_type { + InlineType::Inline => { + if function.id() != ssa.main_id { + panic!("ACIR function should have been inlined earlier if not marked otherwise"); + } + } + InlineType::NoPredicates => { + panic!("All ACIR functions marked with #[no_predicates] should be inlined before ACIR gen. This is an SSA exclusive codegen attribute"); + } + InlineType::Fold => {} + } + // We only want to convert entry point functions. This being `main` and those marked with `InlineType::Fold` + Ok(Some(self.convert_acir_main(function, ssa, brillig)?)) + } + RuntimeType::Brillig => { + if function.id() == ssa.main_id { + Ok(Some(self.convert_brillig_main(function, brillig)?)) + } else { + Ok(None) + } + } } } @@ -243,33 +385,56 @@ impl Context { mut self, main_func: &Function, ssa: &Ssa, - brillig: Brillig, - last_array_uses: &HashMap, + brillig: &Brillig, ) -> Result { 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 num_return_witnesses = + self.get_num_return_witnesses(entry_block.unwrap_terminator(), dfg); + + // Create a witness for each return witness we have to guarantee that the return witnesses match the standard + // layout for serializing those types as if they were being passed as inputs. + // + // This is required for recursion as otherwise in situations where we cannot make use of the program's ABI + // (e.g. for `std::verify_proof` or the solidity verifier), we need extra knowledge about the program we're + // working with rather than following the standard ABI encoding rules. + // + // We allocate these witnesses now before performing ACIR gen for the rest of the program as the location of + // the function's return values can then be determined through knowledge of its ABI alone. + let return_witness_vars = + vecmap(0..num_return_witnesses, |_| self.acir_context.add_variable()); + + let return_witnesses = vecmap(&return_witness_vars, |return_var| { + let expr = self.acir_context.var_to_expression(*return_var).unwrap(); + expr.to_witness().expect("return vars should be witnesses") + }); self.data_bus = dfg.data_bus.to_owned(); let mut warnings = Vec::new(); for instruction_id in entry_block.instructions() { - warnings.extend(self.convert_ssa_instruction( - *instruction_id, - dfg, - ssa, - &brillig, - last_array_uses, - )?); + warnings.extend(self.convert_ssa_instruction(*instruction_id, dfg, ssa, brillig)?); + } + + let (return_vars, return_warnings) = + self.convert_ssa_return(entry_block.unwrap_terminator(), dfg)?; + + // TODO: This is a naive method of assigning the return values to their witnesses as + // we're likely to get a number of constraints which are asserting one witness to be equal to another. + // + // We should search through the program and relabel these witnesses so we can remove this constraint. + for (witness_var, return_var) in return_witness_vars.iter().zip(return_vars) { + self.acir_context.assert_eq_var(*witness_var, return_var, None)?; } - warnings.extend(self.convert_ssa_return(entry_block.unwrap_terminator(), dfg)?); - Ok(self.acir_context.finish(input_witness, warnings)) + warnings.extend(return_warnings); + Ok(self.acir_context.finish(input_witness, return_witnesses, warnings)) } fn convert_brillig_main( mut self, main_func: &Function, - brillig: Brillig, + brillig: &Brillig, ) -> Result { let dfg = &main_func.dfg; @@ -277,34 +442,37 @@ impl Context { let typ = dfg.type_of_value(*param_id); self.create_value_from_type(&typ, &mut |this, _| Ok(this.acir_context.add_variable())) })?; + let arguments = self.gen_brillig_parameters(dfg[main_func.entry_block()].parameters(), dfg); + let witness_inputs = self.acir_context.extract_witness(&inputs); let outputs: Vec = vecmap(main_func.returns(), |result_id| dfg.type_of_value(*result_id).into()); - let code = self.gen_brillig_for(main_func, &brillig)?; + let code = self.gen_brillig_for(main_func, arguments.clone(), brillig)?; // We specifically do not attempt execution of the brillig code being generated as this can result in it being // replaced with constraints on witnesses to the program outputs. - let output_values = self.acir_context.brillig( + let output_values = self.acir_context.brillig_call( self.current_side_effects_enabled_var, - code, + &code, inputs, outputs, false, true, + // We are guaranteed to have a Brillig function pointer of `0` as main itself is marked as unconstrained + 0, + None, )?; - let output_vars: Vec<_> = output_values + self.shared_context.insert_generated_brillig(main_func.id(), arguments, 0, code); + + let return_witnesses: Vec = output_values .iter() .flat_map(|value| value.clone().flatten()) - .map(|value| value.0) - .collect(); - - for acir_var in output_vars { - self.acir_context.return_var(acir_var)?; - } + .map(|(value, _)| self.acir_context.var_to_witness(value)) + .collect::>()?; - let generated_acir = self.acir_context.finish(witness_inputs, Vec::new()); + let generated_acir = self.acir_context.finish(witness_inputs, return_witnesses, Vec::new()); assert_eq!( generated_acir.opcodes().len(), @@ -432,7 +600,6 @@ impl Context { dfg: &DataFlowGraph, ssa: &Ssa, brillig: &Brillig, - last_array_uses: &HashMap, ) -> Result, RuntimeError> { let instruction = &dfg[instruction_id]; self.acir_context.set_call_stack(dfg.get_call_stack(instruction_id)); @@ -446,19 +613,39 @@ impl Context { let lhs = self.convert_numeric_value(*lhs, dfg)?; let rhs = self.convert_numeric_value(*rhs, dfg)?; - let assert_message = if let Some(error) = assert_message { - match error.as_ref() { - ConstrainError::Static(string) => Some(string.clone()), - ConstrainError::Dynamic(call_instruction) => { - self.convert_ssa_call(call_instruction, dfg, ssa, brillig, &[])?; - None + let assert_payload = if let Some(error) = assert_message { + match error { + ConstrainError::Intrinsic(string) => { + Some(AssertionPayload::StaticString(string.clone())) + } + ConstrainError::UserDefined(error_selector, values) => { + if let Some(constant_string) = try_to_extract_string_from_error_payload( + *error_selector, + values, + dfg, + ) { + Some(AssertionPayload::StaticString(constant_string)) + } else { + let acir_vars: Vec<_> = values + .iter() + .map(|value| self.convert_value(*value, dfg)) + .collect(); + + let expressions_or_memory = + self.acir_context.vars_to_expressions_or_memory(&acir_vars)?; + + Some(AssertionPayload::Dynamic( + error_selector.as_u64(), + expressions_or_memory, + )) + } } } } else { None }; - self.acir_context.assert_eq_var(lhs, rhs, assert_message)?; + self.acir_context.assert_eq_var(lhs, rhs, assert_payload)?; } Instruction::Cast(value_id, _) => { let acir_var = self.convert_numeric_value(*value_id, dfg)?; @@ -492,7 +679,7 @@ impl Context { self.current_side_effects_enabled_var = acir_var; } Instruction::ArrayGet { .. } | Instruction::ArraySet { .. } => { - self.handle_array_operation(instruction_id, dfg, last_array_uses)?; + self.handle_array_operation(instruction_id, dfg)?; } Instruction::Allocate => { unreachable!("Expected all allocate instructions to be removed before acir_gen") @@ -503,7 +690,7 @@ impl Context { Instruction::Load { .. } => { unreachable!("Expected all load instructions to be removed before acir_gen") } - Instruction::IncrementRc { .. } => { + Instruction::IncrementRc { .. } | Instruction::DecrementRc { .. } => { // Do nothing. Only Brillig needs to worry about reference counted arrays } Instruction::RangeCheck { value, max_bit_size, assert_message } => { @@ -514,6 +701,9 @@ impl Context { assert_message.clone(), )?; } + Instruction::IfElse { .. } => { + unreachable!("IfElse instruction remaining in acir-gen") + } } self.acir_context.set_call_stack(CallStack::new()); @@ -537,38 +727,97 @@ impl Context { Value::Function(id) => { let func = &ssa.functions[id]; match func.runtime() { - RuntimeType::Acir => unimplemented!( - "expected an intrinsic/brillig call, but found {func:?}. All ACIR methods should be inlined" - ), + RuntimeType::Acir(inline_type) => { + assert!(!matches!(inline_type, InlineType::Inline), "ICE: Got an ACIR function named {} that should have already been inlined", func.name()); + + let inputs = vecmap(arguments, |arg| self.convert_value(*arg, dfg)); + let output_count = result_ids + .iter() + .map(|result_id| dfg.type_of_value(*result_id).flattened_size()) + .sum(); + + let acir_function_id = ssa + .entry_point_to_generated_index + .get(id) + .expect("ICE: should have an associated final index"); + let output_vars = self.acir_context.call_acir_function( + *acir_function_id, + inputs, + output_count, + self.current_side_effects_enabled_var, + )?; + + let output_values = + self.convert_vars_to_values(output_vars, dfg, result_ids); + + self.handle_ssa_call_outputs(result_ids, output_values, dfg)?; + } RuntimeType::Brillig => { - // Check that we are not attempting to return a slice from + // Check that we are not attempting to return a slice from // an unconstrained runtime to a constrained runtime for result_id in result_ids { if dfg.type_of_value(*result_id).contains_slice_element() { - return Err(RuntimeError::UnconstrainedSliceReturnToConstrained { call_stack: self.acir_context.get_call_stack() }) + return Err( + RuntimeError::UnconstrainedSliceReturnToConstrained { + call_stack: self.acir_context.get_call_stack(), + }, + ); } } - let inputs = vecmap(arguments, |arg| self.convert_value(*arg, dfg)); - - let code = self.gen_brillig_for(func, brillig)?; - - let outputs: Vec = vecmap(result_ids, |result_id| dfg.type_of_value(*result_id).into()); - - let output_values = self.acir_context.brillig(self.current_side_effects_enabled_var, code, inputs, outputs, true, false)?; + let arguments = self.gen_brillig_parameters(arguments, dfg); + + let outputs: Vec = vecmap(result_ids, |result_id| { + dfg.type_of_value(*result_id).into() + }); + + // Check whether we have already generated Brillig for this function + // If we have, re-use the generated code to set-up the Brillig call. + let output_values = if let Some(generated_pointer) = self + .shared_context + .generated_brillig_pointer(*id, arguments.clone()) + { + let code = self + .shared_context + .generated_brillig(*generated_pointer as usize); + self.acir_context.brillig_call( + self.current_side_effects_enabled_var, + code, + inputs, + outputs, + true, + false, + *generated_pointer, + None, + )? + } else { + let code = + self.gen_brillig_for(func, arguments.clone(), brillig)?; + let generated_pointer = + self.shared_context.new_generated_pointer(); + let output_values = self.acir_context.brillig_call( + self.current_side_effects_enabled_var, + &code, + inputs, + outputs, + true, + false, + generated_pointer, + None, + )?; + self.shared_context.insert_generated_brillig( + *id, + arguments, + generated_pointer, + code, + ); + output_values + }; // Compiler sanity check assert_eq!(result_ids.len(), output_values.len(), "ICE: The number of Brillig output values should match the result ids in SSA"); - for result in result_ids.iter().zip(output_values) { - if let AcirValue::Array(_) = &result.1 { - let array_id = dfg.resolve(*result.0); - let block_id = self.block_id(&array_id); - let array_typ = dfg.type_of_value(array_id); - self.initialize_array(block_id, array_typ.flattened_size(), Some(result.1.clone()))?; - } - self.ssa_values.insert(*result.0, result.1); - } + self.handle_ssa_call_outputs(result_ids, output_values, dfg)?; } } } @@ -587,34 +836,14 @@ impl Context { // Issue #1438 causes this check to fail with intrinsics that return 0 // results but the ssa form instead creates 1 unit result value. // assert_eq!(result_ids.len(), outputs.len()); - - for (result, output) in result_ids.iter().zip(outputs) { - match &output { - // We need to make sure we initialize arrays returned from intrinsic calls - // or else they will fail if accessed with a dynamic index - AcirValue::Array(_) => { - let block_id = self.block_id(result); - let array_typ = dfg.type_of_value(*result); - let len = if matches!(array_typ, Type::Array(_, _)) { - array_typ.flattened_size() - } else { - Self::flattened_value_size(&output) - }; - self.initialize_array(block_id, len, Some(output.clone()))?; - } - AcirValue::DynamicArray(_) => { - // Do nothing as a dynamic array returned from a slice intrinsic should already be initialized - } - AcirValue::Var(_, _) => { - // Do nothing - } - } - self.ssa_values.insert(*result, output); - } + self.handle_ssa_call_outputs(result_ids, outputs, dfg)?; + } + Value::ForeignFunction(_) => { + // TODO: Remove this once elaborator is default frontend. This is now caught by a lint inside the frontend. + return Err(RuntimeError::UnconstrainedOracleReturnToConstrained { + call_stack: self.acir_context.get_call_stack(), + }); } - Value::ForeignFunction(_) => unreachable!( - "All `oracle` methods should be wrapped in an unconstrained fn" - ), _ => unreachable!("expected calling a function but got {function_value:?}"), } } @@ -623,14 +852,75 @@ impl Context { Ok(warnings) } + fn handle_ssa_call_outputs( + &mut self, + result_ids: &[ValueId], + output_values: Vec, + dfg: &DataFlowGraph, + ) -> Result<(), RuntimeError> { + for (result_id, output) in result_ids.iter().zip(output_values) { + if let AcirValue::Array(_) = &output { + let array_id = dfg.resolve(*result_id); + let block_id = self.block_id(&array_id); + let array_typ = dfg.type_of_value(array_id); + let len = if matches!(array_typ, Type::Array(_, _)) { + array_typ.flattened_size() + } else { + Self::flattened_value_size(&output) + }; + self.initialize_array(block_id, len, Some(output.clone()))?; + } + // Do nothing for AcirValue::DynamicArray and AcirValue::Var + // A dynamic array returned from a function call should already be initialized + // and a single variable does not require any extra initialization. + self.ssa_values.insert(*result_id, output); + } + Ok(()) + } + + fn gen_brillig_parameters( + &self, + values: &[ValueId], + dfg: &DataFlowGraph, + ) -> Vec { + values + .iter() + .map(|&value_id| { + let typ = dfg.type_of_value(value_id); + if let Type::Slice(item_types) = typ { + let len = match self + .ssa_values + .get(&value_id) + .expect("ICE: Unknown slice input to brillig") + { + AcirValue::DynamicArray(AcirDynamicArray { len, .. }) => *len, + AcirValue::Array(array) => array.len(), + _ => unreachable!("ICE: Slice value is not an array"), + }; + + BrilligParameter::Slice( + item_types + .iter() + .map(BrilligFunctionContext::ssa_type_to_parameter) + .collect(), + len / item_types.len(), + ) + } else { + BrilligFunctionContext::ssa_type_to_parameter(&typ) + } + }) + .collect() + } + fn gen_brillig_for( &self, func: &Function, + arguments: Vec, brillig: &Brillig, ) -> Result { // Create the entry point artifact let mut entry_point = BrilligContext::new_entry_point_artifact( - BrilligFunctionContext::parameters(func), + arguments, BrilligFunctionContext::return_values(func), BrilligFunctionContext::function_id_to_function_label(func.id()), ); @@ -659,12 +949,16 @@ impl Context { &mut self, instruction: InstructionId, dfg: &DataFlowGraph, - last_array_uses: &HashMap, ) -> Result<(), RuntimeError> { + let mut mutable_array_set = false; + // Pass the instruction between array methods rather than the internal fields themselves let (array, index, store_value) = match dfg[instruction] { Instruction::ArrayGet { array, index } => (array, index, None), - Instruction::ArraySet { array, index, value, .. } => (array, index, Some(value)), + Instruction::ArraySet { array, index, value, mutable } => { + mutable_array_set = mutable; + (array, index, Some(value)) + } _ => { return Err(InternalError::Unexpected { expected: "Instruction should be an ArrayGet or ArraySet".to_owned(), @@ -679,16 +973,39 @@ impl Context { return Ok(()); } - let (new_index, new_value) = - self.convert_array_operation_inputs(array, dfg, index, store_value)?; - - let resolved_array = dfg.resolve(array); - let map_array = last_array_uses.get(&resolved_array) == Some(&instruction); + // Get an offset such that the type of the array at the offset is the same as the type at the 'index' + // If we find one, we will use it when computing the index under the enable_side_effect predicate + // If not, array_get(..) will use a fallback costing one multiplication in the worst case. + // cf. https://github.com/noir-lang/noir/pull/4971 + let array_id = dfg.resolve(array); + let array_typ = dfg.type_of_value(array_id); + // For simplicity we compute the offset only for simple arrays + let is_simple_array = dfg.instruction_results(instruction).len() == 1 + && can_omit_element_sizes_array(&array_typ); + let offset = if is_simple_array { + let result_type = dfg.type_of_value(dfg.instruction_results(instruction)[0]); + match array_typ { + Type::Array(item_type, _) | Type::Slice(item_type) => item_type + .iter() + .enumerate() + .find_map(|(index, typ)| (result_type == *typ).then_some(index)), + _ => None, + } + } else { + None + }; + let (new_index, new_value) = self.convert_array_operation_inputs( + array, + dfg, + index, + store_value, + offset.unwrap_or_default(), + )?; if let Some(new_value) = new_value { - self.array_set(instruction, new_index, new_value, dfg, map_array)?; + self.array_set(instruction, new_index, new_value, dfg, mutable_array_set)?; } else { - self.array_get(instruction, array, new_index, dfg)?; + self.array_get(instruction, array, new_index, dfg, offset.is_none())?; } Ok(()) @@ -737,6 +1054,7 @@ impl Context { }); } }; + 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 { @@ -777,7 +1095,7 @@ impl Context { /// - new_index is the index of the array. ACIR memory operations work with a flat memory, so we fully flattened the specified index /// in case we have a nested array. The index for SSA array operations only represents the flattened index of the current array. /// Thus internal array element type sizes need to be computed to accurately transform the index. - /// - predicate_index is 0, or the index if the predicate is true + /// - predicate_index is offset, or the index if the predicate is true /// - new_value is the optional value when the operation is an array_set /// When there is a predicate, it is predicate*value + (1-predicate)*dummy, where dummy is the value of the array at the requested index. /// It is a dummy value because in the case of a false predicate, the value stored at the requested index will be itself. @@ -787,14 +1105,18 @@ impl Context { dfg: &DataFlowGraph, index: ValueId, store_value: Option, + offset: usize, ) -> Result<(AcirVar, Option), RuntimeError> { let (array_id, array_typ, block_id) = self.check_array_is_initialized(array, dfg)?; let index_var = self.convert_numeric_value(index, dfg)?; let index_var = self.get_flattened_index(&array_typ, array_id, index_var, dfg)?; - let predicate_index = - self.acir_context.mul_var(index_var, self.current_side_effects_enabled_var)?; + // predicate_index = index*predicate + (1-predicate)*offset + let offset = self.acir_context.add_constant(offset); + let sub = self.acir_context.sub_var(index_var, offset)?; + let pred = self.acir_context.mul_var(sub, self.current_side_effects_enabled_var)?; + let predicate_index = self.acir_context.add_var(pred, offset)?; let new_value = if let Some(store) = store_value { let store_value = self.convert_value(store, dfg); @@ -895,12 +1217,14 @@ impl Context { } /// Generates a read opcode for the array + /// `index_side_effect == false` means that we ensured `var_index` will have a type matching the value in the array fn array_get( &mut self, instruction: InstructionId, array: ValueId, mut var_index: AcirVar, dfg: &DataFlowGraph, + mut index_side_effect: bool, ) -> Result { let (array_id, _, block_id) = self.check_array_is_initialized(array, dfg)?; let results = dfg.instruction_results(instruction); @@ -919,7 +1243,7 @@ impl Context { self.data_bus.call_data_map[&array_id] as i128, )); let new_index = self.acir_context.add_var(offset, bus_index)?; - return self.array_get(instruction, call_data, new_index, dfg); + return self.array_get(instruction, call_data, new_index, dfg, index_side_effect); } } @@ -928,7 +1252,28 @@ impl Context { !res_typ.contains_slice_element(), "ICE: Nested slice result found during ACIR generation" ); - let value = self.array_get_value(&res_typ, block_id, &mut var_index)?; + let mut value = self.array_get_value(&res_typ, block_id, &mut var_index)?; + + if let AcirValue::Var(value_var, typ) = &value { + let array_id = dfg.resolve(array_id); + let array_typ = dfg.type_of_value(array_id); + if let (Type::Numeric(numeric_type), AcirType::NumericType(num)) = + (array_typ.first(), typ) + { + if numeric_type.bit_size() <= num.bit_size() { + // first element is compatible + index_side_effect = false; + } + } + // Fallback to multiplication if the index side_effects have not already been handled + if index_side_effect { + // Set the value to 0 if current_side_effects is 0, to ensure it fits in any value type + value = AcirValue::Var( + self.acir_context.mul_var(*value_var, self.current_side_effects_enabled_var)?, + typ.clone(), + ); + } + } self.define_result(dfg, instruction, value.clone()); @@ -966,16 +1311,18 @@ impl Context { } } - /// Copy the array and generates a write opcode on the new array - /// - /// Note: Copying the array is inefficient and is not the way we want to do it in the end. + /// If `mutate_array` is: + /// - true: Mutate the array directly + /// - false: Copy the array and generates a write opcode on the new array. This is + /// generally very inefficient and should be avoided if possible. Currently + /// this is controlled by SSA's array set optimization pass. fn array_set( &mut self, instruction: InstructionId, mut var_index: AcirVar, store_value: AcirValue, dfg: &DataFlowGraph, - map_array: bool, + mutate_array: bool, ) -> Result<(), RuntimeError> { // Pass the instruction between array methods rather than the internal fields themselves let array = match dfg[instruction] { @@ -1013,7 +1360,7 @@ impl Context { .first() .expect("Array set does not have one result"); let result_block_id; - if map_array { + if mutate_array { self.memory_blocks.insert(*result_id, block_id); result_block_id = block_id; } else { @@ -1025,7 +1372,13 @@ impl Context { self.array_set_value(&store_value, result_block_id, &mut var_index)?; let element_type_sizes = if !can_omit_element_sizes_array(&array_typ) { - Some(self.init_element_type_sizes_array(&array_typ, array_id, None, dfg)?) + let acir_value = self.convert_value(array_id, dfg); + Some(self.init_element_type_sizes_array( + &array_typ, + array_id, + Some(&acir_value), + dfg, + )?) } else { None }; @@ -1246,7 +1599,8 @@ impl Context { let read = self.acir_context.read_from_memory(source, &index_var)?; Ok::(AcirValue::Var(read, AcirType::field())) })?; - self.initialize_array(destination, array_len, Some(AcirValue::Array(init_values.into())))?; + let array: im::Vector = init_values.into(); + self.initialize_array(destination, array_len, Some(AcirValue::Array(array)))?; Ok(()) } @@ -1326,7 +1680,18 @@ impl Context { len: usize, value: Option, ) -> Result<(), InternalError> { - self.acir_context.initialize_array(array, len, value)?; + let databus = if self.data_bus.call_data.is_some() + && self.block_id(&self.data_bus.call_data.unwrap()) == array + { + BlockType::CallData + } else if self.data_bus.return_data.is_some() + && self.block_id(&self.data_bus.return_data.unwrap()) == array + { + BlockType::ReturnData + } else { + BlockType::Memory + }; + self.acir_context.initialize_array(array, len, value, databus)?; self.initialized_arrays.insert(array); Ok(()) } @@ -1354,32 +1719,81 @@ impl Context { self.define_result(dfg, instruction, AcirValue::Var(result, typ)); } + /// Converts an SSA terminator's return values into their ACIR representations + fn get_num_return_witnesses( + &mut self, + terminator: &TerminatorInstruction, + dfg: &DataFlowGraph, + ) -> usize { + let return_values = match terminator { + TerminatorInstruction::Return { return_values, .. } => return_values, + // TODO(https://github.com/noir-lang/noir/issues/4616): Enable recursion on foldable/non-inlined ACIR functions + _ => unreachable!("ICE: Program must have a singular return"), + }; + + return_values.iter().fold(0, |acc, value_id| { + let is_databus = self + .data_bus + .return_data + .map_or(false, |return_databus| dfg[*value_id] == dfg[return_databus]); + + if is_databus { + // We do not return value for the data bus. + acc + } else { + acc + dfg.type_of_value(*value_id).flattened_size() + } + }) + } + /// Converts an SSA terminator's return values into their ACIR representations fn convert_ssa_return( &mut self, terminator: &TerminatorInstruction, dfg: &DataFlowGraph, - ) -> Result, InternalError> { + ) -> Result<(Vec, Vec), RuntimeError> { let (return_values, call_stack) = match terminator { TerminatorInstruction::Return { return_values, call_stack } => { - (return_values, call_stack) + (return_values, call_stack.clone()) } + // TODO(https://github.com/noir-lang/noir/issues/4616): Enable recursion on foldable/non-inlined ACIR functions _ => unreachable!("ICE: Program must have a singular return"), }; - // 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 { - if self.acir_context.is_constant(&acir_var) { - warnings.push(SsaReport::Warning(InternalWarning::ReturnConstant { - call_stack: call_stack.clone(), - })); + let mut has_constant_return = false; + let mut return_vars: Vec = Vec::new(); + for value_id in return_values { + let is_databus = self + .data_bus + .return_data + .map_or(false, |return_databus| dfg[*value_id] == dfg[return_databus]); + let value = self.convert_value(*value_id, dfg); + + // `value` may or may not be an array reference. Calling `flatten` will expand the array if there is one. + let acir_vars = self.acir_context.flatten(value)?; + for (acir_var, _) in acir_vars { + has_constant_return |= self.acir_context.is_constant(&acir_var); + if is_databus { + // We do not return value for the data bus. + self.check_array_is_initialized( + self.data_bus.return_data.expect( + "`is_databus == true` implies `data_bus.return_data` is `Some`", + ), + dfg, + )?; + } else { + return_vars.push(acir_var); + } } - self.acir_context.return_var(acir_var)?; } - Ok(warnings) + + let warnings = if has_constant_return { + vec![SsaReport::Warning(InternalWarning::ReturnConstant { call_stack })] + } else { + Vec::new() + }; + + Ok((return_vars, warnings)) } /// Gets the cached `AcirVar` that was converted from the corresponding `ValueId`. If it does @@ -1479,15 +1893,15 @@ impl Context { let binary_type = AcirType::from(binary_type); let bit_count = binary_type.bit_size(); - - match binary.operator { + let num_type = binary_type.to_numeric_type(); + let result = match binary.operator { BinaryOp::Add => self.acir_context.add_var(lhs, rhs), BinaryOp::Sub => self.acir_context.sub_var(lhs, rhs), BinaryOp::Mul => self.acir_context.mul_var(lhs, rhs), BinaryOp::Div => self.acir_context.div_var( lhs, rhs, - binary_type, + binary_type.clone(), self.current_side_effects_enabled_var, ), // Note: that this produces unnecessary constraints when @@ -1511,7 +1925,71 @@ impl Context { BinaryOp::Shl | BinaryOp::Shr => unreachable!( "ICE - bit shift operators do not exist in ACIR and should have been replaced" ), + }?; + + if let NumericType::Unsigned { bit_size } = &num_type { + // Check for integer overflow + self.check_unsigned_overflow( + result, + *bit_size, + binary.lhs, + binary.rhs, + dfg, + binary.operator, + )?; } + + Ok(result) + } + + /// Adds a range check against the bit size of the result of addition, subtraction or multiplication + fn check_unsigned_overflow( + &mut self, + result: AcirVar, + bit_size: u32, + lhs: ValueId, + rhs: ValueId, + dfg: &DataFlowGraph, + op: BinaryOp, + ) -> Result<(), RuntimeError> { + // We try to optimize away operations that are guaranteed not to overflow + let max_lhs_bits = dfg.get_value_max_num_bits(lhs); + let max_rhs_bits = dfg.get_value_max_num_bits(rhs); + + let msg = match op { + BinaryOp::Add => { + if std::cmp::max(max_lhs_bits, max_rhs_bits) < bit_size { + // `lhs` and `rhs` have both been casted up from smaller types and so cannot overflow. + return Ok(()); + } + "attempt to add with overflow".to_string() + } + BinaryOp::Sub => { + if dfg.is_constant(lhs) && max_lhs_bits > max_rhs_bits { + // `lhs` is a fixed constant and `rhs` is restricted such that `lhs - rhs > 0` + // Note strict inequality as `rhs > lhs` while `max_lhs_bits == max_rhs_bits` is possible. + return Ok(()); + } + "attempt to subtract with overflow".to_string() + } + BinaryOp::Mul => { + if bit_size == 1 || max_lhs_bits + max_rhs_bits <= bit_size { + // Either performing boolean multiplication (which cannot overflow), + // or `lhs` and `rhs` have both been casted up from smaller types and so cannot overflow. + return Ok(()); + } + "attempt to multiply with overflow".to_string() + } + _ => return Ok(()), + }; + + let with_pred = self.acir_context.mul_var(result, self.current_side_effects_enabled_var)?; + self.acir_context.range_constrain_var( + with_pred, + &NumericType::Unsigned { bit_size }, + Some(msg), + )?; + Ok(()) } /// Operands in a binary operation are checked to have the same type. @@ -1663,6 +2141,49 @@ impl Context { }; Ok(vec![AcirValue::Var(self.acir_context.add_constant(len), AcirType::field())]) } + Intrinsic::AsSlice => { + let (slice_contents, slice_typ, block_id) = + self.check_array_is_initialized(arguments[0], dfg)?; + assert!(!slice_typ.is_nested_slice(), "ICE: Nested slice used in ACIR generation"); + + let result_block_id = self.block_id(&result_ids[1]); + let acir_value = self.convert_value(slice_contents, dfg); + + let array_len = if !slice_typ.contains_slice_element() { + slice_typ.flattened_size() + } else { + self.flattened_slice_size(slice_contents, dfg) + }; + let slice_length = self.acir_context.add_constant(array_len); + self.copy_dynamic_array(block_id, result_block_id, array_len)?; + + let element_type_sizes = if !can_omit_element_sizes_array(&slice_typ) { + Some(self.init_element_type_sizes_array( + &slice_typ, + slice_contents, + Some(&acir_value), + dfg, + )?) + } else { + None + }; + + let value_types = self.convert_value(slice_contents, dfg).flat_numeric_types(); + assert!( + array_len == value_types.len(), + "AsSlice: unexpected length difference: {:?} != {:?}", + array_len, + value_types.len() + ); + + let result = AcirValue::DynamicArray(AcirDynamicArray { + block_id: result_block_id, + len: value_types.len(), + value_types, + element_type_sizes, + }); + Ok(vec![AcirValue::Var(slice_length, AcirType::field()), result]) + } Intrinsic::SlicePushBack => { // arguments = [slice_length, slice_contents, ...elements_to_push] let slice_length = self.convert_value(arguments[0], dfg).into_var()?; @@ -2137,6 +2658,15 @@ impl Context { Ok(result) } + + Intrinsic::AsWitness => { + let arg = arguments[0]; + let input = self.convert_value(arg, dfg).into_var()?; + Ok(self + .acir_context + .get_or_create_witness_var(input) + .map(|val| self.convert_vars_to_values(vec![val], dfg, result_ids))?) + } _ => todo!("expected a black box function"), } } @@ -2187,24 +2717,6 @@ impl Context { } } - /// Maps an ssa value list, for which some values may be references to arrays, by inlining - /// the `AcirVar`s corresponding to the contents of each array into the list of `AcirVar`s - /// that correspond to other values. - fn flatten_value_list( - &mut self, - arguments: &[ValueId], - dfg: &DataFlowGraph, - ) -> Result, InternalError> { - let mut acir_vars = Vec::with_capacity(arguments.len()); - for value_id in arguments { - let value = self.convert_value(*value_id, dfg); - acir_vars.append( - &mut self.acir_context.flatten(value)?.iter().map(|(var, _)| *var).collect(), - ); - } - Ok(acir_vars) - } - /// Convert a Vec into a Vec using the given result ids. /// If the type of a result id is an array, several acir vars are collected into /// a single AcirValue::Array of the same length. @@ -2268,12 +2780,722 @@ impl Context { // We can omit the element size array for arrays which don't contain arrays or slices. fn can_omit_element_sizes_array(array_typ: &Type) -> bool { - if array_typ.contains_slice_element() { - return false; - } - let Type::Array(types, _) = array_typ else { - panic!("ICE: expected array type"); + let types = match array_typ { + Type::Array(types, _) | Type::Slice(types) => types, + _ => panic!("ICE: expected array or slice type"), }; !types.iter().any(|typ| typ.contains_an_array()) } + +#[cfg(test)] +mod test { + use std::collections::BTreeMap; + + use acvm::{ + acir::{ + circuit::{Opcode, OpcodeLocation}, + native_types::Witness, + }, + FieldElement, + }; + use noirc_frontend::monomorphization::ast::InlineType; + + use crate::{ + brillig::Brillig, + ssa::{ + acir_gen::acir_ir::generated_acir::BrilligStdlibFunc, + function_builder::FunctionBuilder, + ir::{function::FunctionId, instruction::BinaryOp, map::Id, types::Type}, + }, + }; + + fn build_basic_foo_with_return( + builder: &mut FunctionBuilder, + foo_id: FunctionId, + // `InlineType` can only exist on ACIR functions, so if the option is `None` we should generate a Brillig function + inline_type: Option, + ) { + // fn foo f1 { + // b0(v0: Field, v1: Field): + // v2 = eq v0, v1 + // constrain v2 == u1 0 + // return v0 + // } + if let Some(inline_type) = inline_type { + builder.new_function("foo".into(), foo_id, inline_type); + } else { + builder.new_brillig_function("foo".into(), foo_id); + } + let foo_v0 = builder.add_parameter(Type::field()); + let foo_v1 = builder.add_parameter(Type::field()); + + let foo_equality_check = builder.insert_binary(foo_v0, BinaryOp::Eq, foo_v1); + let zero = builder.numeric_constant(0u128, Type::unsigned(1)); + builder.insert_constrain(foo_equality_check, zero, None); + builder.terminate_with_return(vec![foo_v0]); + } + + /// Check that each `InlineType` which prevents inlining functions generates code in the same manner + #[test] + fn basic_calls_fold() { + basic_call_with_outputs_assert(InlineType::Fold); + call_output_as_next_call_input(InlineType::Fold); + basic_nested_call(InlineType::Fold); + } + + #[test] + #[should_panic] + fn basic_calls_no_predicates() { + basic_call_with_outputs_assert(InlineType::NoPredicates); + call_output_as_next_call_input(InlineType::NoPredicates); + basic_nested_call(InlineType::NoPredicates); + } + + #[test] + #[should_panic] + fn call_without_inline_attribute() { + basic_call_with_outputs_assert(InlineType::Inline); + } + + fn basic_call_with_outputs_assert(inline_type: InlineType) { + // acir(inline) fn main f0 { + // b0(v0: Field, v1: Field): + // v2 = call f1(v0, v1) + // v3 = call f1(v0, v1) + // constrain v2 == v3 + // return + // } + // acir(fold) fn foo f1 { + // b0(v0: Field, v1: Field): + // v2 = eq v0, v1 + // constrain v2 == u1 0 + // return v0 + // } + let foo_id = Id::test_new(0); + let mut builder = FunctionBuilder::new("main".into(), foo_id); + let main_v0 = builder.add_parameter(Type::field()); + let main_v1 = builder.add_parameter(Type::field()); + + let foo_id = Id::test_new(1); + let foo = builder.import_function(foo_id); + let main_call1_results = + builder.insert_call(foo, vec![main_v0, main_v1], vec![Type::field()]).to_vec(); + let main_call2_results = + builder.insert_call(foo, vec![main_v0, main_v1], vec![Type::field()]).to_vec(); + builder.insert_constrain(main_call1_results[0], main_call2_results[0], None); + builder.terminate_with_return(vec![]); + + build_basic_foo_with_return(&mut builder, foo_id, Some(inline_type)); + + let ssa = builder.finish(); + + let (acir_functions, _, _) = ssa + .into_acir(&Brillig::default()) + .expect("Should compile manually written SSA into ACIR"); + // Expected result: + // main f0 + // GeneratedAcir { + // ... + // opcodes: [ + // CALL func 1: inputs: [Witness(0), Witness(1)], outputs: [Witness(2)], + // CALL func 1: inputs: [Witness(0), Witness(1)], outputs: [Witness(3)], + // EXPR [ (1, _2) (-1, _3) 0 ], + // ], + // return_witnesses: [], + // input_witnesses: [ + // Witness( + // 0, + // ), + // Witness( + // 1, + // ), + // ], + // ... + // } + // foo f1 + // GeneratedAcir { + // ... + // opcodes: [ + // Same as opcodes as the expected result of `basic_call_codegen` + // ], + // return_witnesses: [ + // Witness( + // 0, + // ), + // ], + // input_witnesses: [ + // Witness( + // 0, + // ), + // Witness( + // 1, + // ), + // ], + // ... + // }, + + let main_acir = &acir_functions[0]; + let main_opcodes = main_acir.opcodes(); + assert_eq!(main_opcodes.len(), 3, "Should have two calls to `foo`"); + + check_call_opcode(&main_opcodes[0], 1, vec![Witness(0), Witness(1)], vec![Witness(2)]); + check_call_opcode(&main_opcodes[1], 1, vec![Witness(0), Witness(1)], vec![Witness(3)]); + + if let Opcode::AssertZero(expr) = &main_opcodes[2] { + assert_eq!(expr.linear_combinations[0].0, FieldElement::from(1u128)); + assert_eq!(expr.linear_combinations[0].1, Witness(2)); + + assert_eq!(expr.linear_combinations[1].0, FieldElement::from(-1i128)); + assert_eq!(expr.linear_combinations[1].1, Witness(3)); + assert_eq!(expr.q_c, FieldElement::from(0u128)); + } + } + + fn call_output_as_next_call_input(inline_type: InlineType) { + // acir(inline) fn main f0 { + // b0(v0: Field, v1: Field): + // v3 = call f1(v0, v1) + // v4 = call f1(v3, v1) + // constrain v3 == v4 + // return + // } + // acir(fold) fn foo f1 { + // b0(v0: Field, v1: Field): + // v2 = eq v0, v1 + // constrain v2 == u1 0 + // return v0 + // } + let foo_id = Id::test_new(0); + let mut builder = FunctionBuilder::new("main".into(), foo_id); + let main_v0 = builder.add_parameter(Type::field()); + let main_v1 = builder.add_parameter(Type::field()); + + let foo_id = Id::test_new(1); + let foo = builder.import_function(foo_id); + let main_call1_results = + builder.insert_call(foo, vec![main_v0, main_v1], vec![Type::field()]).to_vec(); + let main_call2_results = builder + .insert_call(foo, vec![main_call1_results[0], main_v1], vec![Type::field()]) + .to_vec(); + builder.insert_constrain(main_call1_results[0], main_call2_results[0], None); + builder.terminate_with_return(vec![]); + + build_basic_foo_with_return(&mut builder, foo_id, Some(inline_type)); + + let ssa = builder.finish(); + + let (acir_functions, _, _) = ssa + .into_acir(&Brillig::default()) + .expect("Should compile manually written SSA into ACIR"); + // The expected result should look very similar to the above test expect that the input witnesses of the `Call` + // opcodes will be different. The changes can discerned from the checks below. + + let main_acir = &acir_functions[0]; + let main_opcodes = main_acir.opcodes(); + assert_eq!(main_opcodes.len(), 3, "Should have two calls to `foo` and an assert"); + + check_call_opcode(&main_opcodes[0], 1, vec![Witness(0), Witness(1)], vec![Witness(2)]); + // The output of the first call should be the input of the second call + check_call_opcode(&main_opcodes[1], 1, vec![Witness(2), Witness(1)], vec![Witness(3)]); + } + + fn basic_nested_call(inline_type: InlineType) { + // SSA for the following Noir program: + // fn main(x: Field, y: pub Field) { + // let z = func_with_nested_foo_call(x, y); + // let z2 = func_with_nested_foo_call(x, y); + // assert(z == z2); + // } + // #[fold] + // fn func_with_nested_foo_call(x: Field, y: Field) -> Field { + // nested_call(x + 2, y) + // } + // #[fold] + // fn foo(x: Field, y: Field) -> Field { + // assert(x != y); + // x + // } + // + // SSA: + // acir(inline) fn main f0 { + // b0(v0: Field, v1: Field): + // v3 = call f1(v0, v1) + // v4 = call f1(v0, v1) + // constrain v3 == v4 + // return + // } + // acir(fold) fn func_with_nested_foo_call f1 { + // b0(v0: Field, v1: Field): + // v3 = add v0, Field 2 + // v5 = call f2(v3, v1) + // return v5 + // } + // acir(fold) fn foo f2 { + // b0(v0: Field, v1: Field): + // v2 = eq v0, v1 + // constrain v2 == Field 0 + // return v0 + // } + let foo_id = Id::test_new(0); + let mut builder = FunctionBuilder::new("main".into(), foo_id); + let main_v0 = builder.add_parameter(Type::field()); + let main_v1 = builder.add_parameter(Type::field()); + + let func_with_nested_foo_call_id = Id::test_new(1); + let func_with_nested_foo_call = builder.import_function(func_with_nested_foo_call_id); + let main_call1_results = builder + .insert_call(func_with_nested_foo_call, vec![main_v0, main_v1], vec![Type::field()]) + .to_vec(); + let main_call2_results = builder + .insert_call(func_with_nested_foo_call, vec![main_v0, main_v1], vec![Type::field()]) + .to_vec(); + builder.insert_constrain(main_call1_results[0], main_call2_results[0], None); + builder.terminate_with_return(vec![]); + + builder.new_function( + "func_with_nested_foo_call".into(), + func_with_nested_foo_call_id, + inline_type, + ); + let func_with_nested_call_v0 = builder.add_parameter(Type::field()); + let func_with_nested_call_v1 = builder.add_parameter(Type::field()); + + let two = builder.field_constant(2u128); + let v0_plus_two = builder.insert_binary(func_with_nested_call_v0, BinaryOp::Add, two); + + let foo_id = Id::test_new(2); + let foo_call = builder.import_function(foo_id); + let foo_call = builder + .insert_call(foo_call, vec![v0_plus_two, func_with_nested_call_v1], vec![Type::field()]) + .to_vec(); + builder.terminate_with_return(vec![foo_call[0]]); + + build_basic_foo_with_return(&mut builder, foo_id, Some(inline_type)); + + let ssa = builder.finish(); + + let (acir_functions, _, _) = ssa + .into_acir(&Brillig::default()) + .expect("Should compile manually written SSA into ACIR"); + + assert_eq!(acir_functions.len(), 3, "Should have three ACIR functions"); + + let main_acir = &acir_functions[0]; + let main_opcodes = main_acir.opcodes(); + assert_eq!(main_opcodes.len(), 3, "Should have two calls to `foo` and an assert"); + + // Both of these should call func_with_nested_foo_call f1 + check_call_opcode(&main_opcodes[0], 1, vec![Witness(0), Witness(1)], vec![Witness(2)]); + // The output of the first call should be the input of the second call + check_call_opcode(&main_opcodes[1], 1, vec![Witness(0), Witness(1)], vec![Witness(3)]); + + let func_with_nested_call_acir = &acir_functions[1]; + let func_with_nested_call_opcodes = func_with_nested_call_acir.opcodes(); + + assert_eq!( + func_with_nested_call_opcodes.len(), + 3, + "Should have an expression and a call to a nested `foo`" + ); + // Should call foo f2 + check_call_opcode( + &func_with_nested_call_opcodes[1], + 2, + vec![Witness(3), Witness(1)], + vec![Witness(4)], + ); + } + + fn check_call_opcode( + opcode: &Opcode, + expected_id: u32, + expected_inputs: Vec, + expected_outputs: Vec, + ) { + match opcode { + Opcode::Call { id, inputs, outputs, .. } => { + assert_eq!( + *id, expected_id, + "Main was expected to call {expected_id} but got {}", + *id + ); + for (expected_input, input) in expected_inputs.iter().zip(inputs) { + assert_eq!( + expected_input, input, + "Expected input witness {expected_input:?} but got {input:?}" + ); + } + for (expected_output, output) in expected_outputs.iter().zip(outputs) { + assert_eq!( + expected_output, output, + "Expected output witness {expected_output:?} but got {output:?}" + ); + } + } + _ => panic!("Expected only Call opcode"), + } + } + + // Test that given multiple calls to the same brillig function we generate only one bytecode + // and the appropriate Brillig call opcodes are generated + #[test] + fn multiple_brillig_calls_one_bytecode() { + // acir(inline) fn main f0 { + // b0(v0: Field, v1: Field): + // v4 = call f1(v0, v1) + // v5 = call f1(v0, v1) + // v6 = call f1(v0, v1) + // v7 = call f2(v0, v1) + // v8 = call f1(v0, v1) + // v9 = call f2(v0, v1) + // return + // } + // brillig fn foo f1 { + // b0(v0: Field, v1: Field): + // v2 = eq v0, v1 + // constrain v2 == u1 0 + // return v0 + // } + // brillig fn foo f2 { + // b0(v0: Field, v1: Field): + // v2 = eq v0, v1 + // constrain v2 == u1 0 + // return v0 + // } + let foo_id = Id::test_new(0); + let mut builder = FunctionBuilder::new("main".into(), foo_id); + let main_v0 = builder.add_parameter(Type::field()); + let main_v1 = builder.add_parameter(Type::field()); + + let foo_id = Id::test_new(1); + let foo = builder.import_function(foo_id); + let bar_id = Id::test_new(2); + let bar = builder.import_function(bar_id); + + // Insert multiple calls to the same Brillig function + builder.insert_call(foo, vec![main_v0, main_v1], vec![Type::field()]).to_vec(); + builder.insert_call(foo, vec![main_v0, main_v1], vec![Type::field()]).to_vec(); + builder.insert_call(foo, vec![main_v0, main_v1], vec![Type::field()]).to_vec(); + // Interleave a call to a separate Brillig function to make sure that we can call multiple separate Brillig functions + builder.insert_call(bar, vec![main_v0, main_v1], vec![Type::field()]).to_vec(); + builder.insert_call(foo, vec![main_v0, main_v1], vec![Type::field()]).to_vec(); + builder.insert_call(bar, vec![main_v0, main_v1], vec![Type::field()]).to_vec(); + builder.terminate_with_return(vec![]); + + build_basic_foo_with_return(&mut builder, foo_id, None); + build_basic_foo_with_return(&mut builder, bar_id, None); + + let ssa = builder.finish(); + let brillig = ssa.to_brillig(false); + + let (acir_functions, brillig_functions, _) = + ssa.into_acir(&brillig).expect("Should compile manually written SSA into ACIR"); + + assert_eq!(acir_functions.len(), 1, "Should only have a `main` ACIR function"); + assert_eq!(brillig_functions.len(), 2, "Should only have generated two Brillig functions"); + + let main_acir = &acir_functions[0]; + let main_opcodes = main_acir.opcodes(); + assert_eq!(main_opcodes.len(), 6, "Should have four calls to f1 and two calls to f2"); + + // We should only have `BrilligCall` opcodes in `main` + for (i, opcode) in main_opcodes.iter().enumerate() { + match opcode { + Opcode::BrilligCall { id, .. } => { + let expected_id = if i == 3 || i == 5 { 1 } else { 0 }; + assert_eq!(*id, expected_id, "Expected an id of {expected_id} but got {id}"); + } + _ => panic!("Expected only Brillig call opcode"), + } + } + } + + // Test that given multiple primitive operations that are represented by Brillig directives (e.g. invert/quotient), + // we will only generate one bytecode and the appropriate Brillig call opcodes are generated. + #[test] + fn multiple_brillig_stdlib_calls() { + // acir(inline) fn main f0 { + // b0(v0: u32, v1: u32, v2: u32): + // v3 = div v0, v1 + // constrain v3 == v2 + // v4 = div v1, v2 + // constrain v4 == u32 1 + // return + // } + let foo_id = Id::test_new(0); + let mut builder = FunctionBuilder::new("main".into(), foo_id); + let main_v0 = builder.add_parameter(Type::unsigned(32)); + let main_v1 = builder.add_parameter(Type::unsigned(32)); + let main_v2 = builder.add_parameter(Type::unsigned(32)); + + // Call a primitive operation that uses Brillig + let v0_div_v1 = builder.insert_binary(main_v0, BinaryOp::Div, main_v1); + builder.insert_constrain(v0_div_v1, main_v2, None); + + // Call the same primitive operation again + let v1_div_v2 = builder.insert_binary(main_v1, BinaryOp::Div, main_v2); + let one = builder.numeric_constant(1u128, Type::unsigned(32)); + builder.insert_constrain(v1_div_v2, one, None); + + builder.terminate_with_return(vec![]); + + let ssa = builder.finish(); + println!("{}", ssa); + + // The Brillig bytecode we insert for the stdlib is hardcoded so we do not need to provide any + // Brillig artifacts to the ACIR gen pass. + let (acir_functions, brillig_functions, _) = ssa + .into_acir(&Brillig::default()) + .expect("Should compile manually written SSA into ACIR"); + + assert_eq!(acir_functions.len(), 1, "Should only have a `main` ACIR function"); + // We expect two brillig functions: + // - Quotient (shared between both divisions) + // - Inversion, caused by division-by-zero check (shared between both divisions) + assert_eq!(brillig_functions.len(), 2, "Should only have generated two Brillig functions"); + + let main_acir = &acir_functions[0]; + let main_opcodes = main_acir.opcodes(); + check_brillig_calls( + &acir_functions[0].brillig_stdlib_func_locations, + main_opcodes, + 0, + 4, + 0, + ); + } + + // Test that given both hardcoded Brillig directives and calls to normal Brillig functions, + // we generate a single bytecode for the directives and a single bytecode for the normal Brillig calls. + #[test] + fn brillig_stdlib_calls_with_regular_brillig_call() { + // acir(inline) fn main f0 { + // b0(v0: u32, v1: u32, v2: u32): + // v4 = div v0, v1 + // constrain v4 == v2 + // v5 = call f1(v0, v1) + // v6 = call f1(v0, v1) + // v7 = div v1, v2 + // constrain v7 == u32 1 + // return + // } + // brillig fn foo f1 { + // b0(v0: Field, v1: Field): + // v2 = eq v0, v1 + // constrain v2 == u1 0 + // return v0 + // } + let foo_id = Id::test_new(0); + let mut builder = FunctionBuilder::new("main".into(), foo_id); + let main_v0 = builder.add_parameter(Type::unsigned(32)); + let main_v1 = builder.add_parameter(Type::unsigned(32)); + let main_v2 = builder.add_parameter(Type::unsigned(32)); + + let foo_id = Id::test_new(1); + let foo = builder.import_function(foo_id); + + // Call a primitive operation that uses Brillig + let v0_div_v1 = builder.insert_binary(main_v0, BinaryOp::Div, main_v1); + builder.insert_constrain(v0_div_v1, main_v2, None); + + // Insert multiple calls to the same Brillig function + builder.insert_call(foo, vec![main_v0, main_v1], vec![Type::field()]).to_vec(); + builder.insert_call(foo, vec![main_v0, main_v1], vec![Type::field()]).to_vec(); + + // Call the same primitive operation again + let v1_div_v2 = builder.insert_binary(main_v1, BinaryOp::Div, main_v2); + let one = builder.numeric_constant(1u128, Type::unsigned(32)); + builder.insert_constrain(v1_div_v2, one, None); + + builder.terminate_with_return(vec![]); + + build_basic_foo_with_return(&mut builder, foo_id, None); + + let ssa = builder.finish(); + // We need to generate Brillig artifacts for the regular Brillig function and pass them to the ACIR generation pass. + let brillig = ssa.to_brillig(false); + println!("{}", ssa); + + let (acir_functions, brillig_functions, _) = + ssa.into_acir(&brillig).expect("Should compile manually written SSA into ACIR"); + + assert_eq!(acir_functions.len(), 1, "Should only have a `main` ACIR function"); + // We expect 3 brillig functions: + // - Quotient (shared between both divisions) + // - Inversion, caused by division-by-zero check (shared between both divisions) + // - Custom brillig function `foo` + assert_eq!( + brillig_functions.len(), + 3, + "Should only have generated three Brillig functions" + ); + + let main_acir = &acir_functions[0]; + let main_opcodes = main_acir.opcodes(); + check_brillig_calls( + &acir_functions[0].brillig_stdlib_func_locations, + main_opcodes, + 1, + 4, + 2, + ); + } + + // Test that given both normal Brillig calls, Brillig stdlib calls, and non-inlined ACIR calls, that we accurately generate ACIR. + #[test] + fn brillig_stdlib_calls_with_multiple_acir_calls() { + // acir(inline) fn main f0 { + // b0(v0: u32, v1: u32, v2: u32): + // v4 = div v0, v1 + // constrain v4 == v2 + // v5 = call f1(v0, v1) + // v6 = call f2(v0, v1) + // v7 = div v1, v2 + // constrain v7 == u32 1 + // return + // } + // brillig fn foo f1 { + // b0(v0: Field, v1: Field): + // v2 = eq v0, v1 + // constrain v2 == u1 0 + // return v0 + // } + // acir(fold) fn foo f2 { + // b0(v0: Field, v1: Field): + // v2 = eq v0, v1 + // constrain v2 == u1 0 + // return v0 + // } + // } + let foo_id = Id::test_new(0); + let mut builder = FunctionBuilder::new("main".into(), foo_id); + let main_v0 = builder.add_parameter(Type::unsigned(32)); + let main_v1 = builder.add_parameter(Type::unsigned(32)); + let main_v2 = builder.add_parameter(Type::unsigned(32)); + + let foo_id = Id::test_new(1); + let foo = builder.import_function(foo_id); + let bar_id = Id::test_new(2); + let bar = builder.import_function(bar_id); + + // Call a primitive operation that uses Brillig + let v0_div_v1 = builder.insert_binary(main_v0, BinaryOp::Div, main_v1); + builder.insert_constrain(v0_div_v1, main_v2, None); + + // Insert multiple calls to the same Brillig function + builder.insert_call(foo, vec![main_v0, main_v1], vec![Type::field()]).to_vec(); + builder.insert_call(foo, vec![main_v0, main_v1], vec![Type::field()]).to_vec(); + builder.insert_call(bar, vec![main_v0, main_v1], vec![Type::field()]).to_vec(); + + // Call the same primitive operation again + let v1_div_v2 = builder.insert_binary(main_v1, BinaryOp::Div, main_v2); + let one = builder.numeric_constant(1u128, Type::unsigned(32)); + builder.insert_constrain(v1_div_v2, one, None); + + builder.terminate_with_return(vec![]); + + // Build a Brillig function + build_basic_foo_with_return(&mut builder, foo_id, None); + // Build an ACIR function which has the same logic as the Brillig function above + build_basic_foo_with_return(&mut builder, bar_id, Some(InlineType::Fold)); + + let ssa = builder.finish(); + // We need to generate Brillig artifacts for the regular Brillig function and pass them to the ACIR generation pass. + let brillig = ssa.to_brillig(false); + println!("{}", ssa); + + let (acir_functions, brillig_functions, _) = + ssa.into_acir(&brillig).expect("Should compile manually written SSA into ACIR"); + + assert_eq!(acir_functions.len(), 2, "Should only have two ACIR functions"); + // We expect 3 brillig functions: + // - Quotient (shared between both divisions) + // - Inversion, caused by division-by-zero check (shared between both divisions) + // - Custom brillig function `foo` + assert_eq!( + brillig_functions.len(), + 3, + "Should only have generated three Brillig functions" + ); + + let main_acir = &acir_functions[0]; + let main_opcodes = main_acir.opcodes(); + check_brillig_calls( + &acir_functions[0].brillig_stdlib_func_locations, + main_opcodes, + 1, + 4, + 2, + ); + + let foo_acir = &acir_functions[1]; + let foo_opcodes = foo_acir.opcodes(); + check_brillig_calls(&acir_functions[1].brillig_stdlib_func_locations, foo_opcodes, 1, 1, 0); + } + + fn check_brillig_calls( + brillig_stdlib_function_locations: &BTreeMap, + opcodes: &[Opcode], + num_normal_brillig_functions: u32, + expected_num_stdlib_calls: u32, + expected_num_normal_calls: u32, + ) { + // First we check calls to the Brillig stdlib + let mut num_brillig_stdlib_calls = 0; + for (i, (opcode_location, brillig_stdlib_func)) in + brillig_stdlib_function_locations.iter().enumerate() + { + // We can take just modulo 2 to determine the expected ID as we only code generated two Brillig stdlib function + let stdlib_func_index = (i % 2) as u32; + if stdlib_func_index == 0 { + assert!(matches!(brillig_stdlib_func, BrilligStdlibFunc::Inverse)); + } else { + assert!(matches!(brillig_stdlib_func, BrilligStdlibFunc::Quotient(_))); + } + + match opcode_location { + OpcodeLocation::Acir(acir_index) => { + match opcodes[*acir_index] { + Opcode::BrilligCall { id, .. } => { + // Brillig stdlib function calls are only resolved at the end of ACIR generation so their + // IDs are expected to always reference Brillig bytecode at the end of the Brillig functions list. + // We have one normal Brillig call so we add one here to the std lib function's index within the std lib. + let expected_id = stdlib_func_index + num_normal_brillig_functions; + assert_eq!(id, expected_id, "Expected {expected_id} but got {id}"); + num_brillig_stdlib_calls += 1; + } + _ => panic!("Expected BrilligCall opcode"), + } + } + _ => panic!("Expected OpcodeLocation::Acir"), + } + } + + assert_eq!( + num_brillig_stdlib_calls, expected_num_stdlib_calls, + "Should have {expected_num_stdlib_calls} BrilligCall opcodes to stdlib functions but got {num_brillig_stdlib_calls}" + ); + + // Check the normal Brillig calls + // This check right now expects to only call one Brillig function. + let mut num_normal_brillig_calls = 0; + for (i, opcode) in opcodes.iter().enumerate() { + if let Opcode::BrilligCall { id, .. } = opcode { + if brillig_stdlib_function_locations.get(&OpcodeLocation::Acir(i)).is_some() { + // We should have already checked Brillig stdlib functions and only want to check normal Brillig calls here + continue; + } + // We only generate one normal Brillig call so we should expect a function ID of `0` + let expected_id = 0u32; + assert_eq!(*id, expected_id, "Expected an id of {expected_id} but got {id}"); + num_normal_brillig_calls += 1; + } + } + + assert_eq!( + num_normal_brillig_calls, expected_num_normal_calls, + "Should have {expected_num_normal_calls} BrilligCall opcodes to normal Brillig functions but got {num_normal_brillig_calls}" + ); + } +} diff --git a/compiler/noirc_evaluator/src/ssa/function_builder/data_bus.rs b/compiler/noirc_evaluator/src/ssa/function_builder/data_bus.rs index cbaeb2477d6..5f0660f5a79 100644 --- a/compiler/noirc_evaluator/src/ssa/function_builder/data_bus.rs +++ b/compiler/noirc_evaluator/src/ssa/function_builder/data_bus.rs @@ -3,6 +3,7 @@ use std::rc::Rc; use crate::ssa::ir::{types::Type, value::ValueId}; use acvm::FieldElement; use fxhash::FxHashMap as HashMap; +use noirc_frontend::ast; use noirc_frontend::hir_def::function::FunctionSignature; use super::FunctionBuilder; @@ -33,8 +34,8 @@ impl DataBusBuilder { for param in &main_signature.0 { let is_databus = match param.2 { - noirc_frontend::Visibility::Public | noirc_frontend::Visibility::Private => false, - noirc_frontend::Visibility::DataBus => true, + ast::Visibility::Public | ast::Visibility::Private => false, + ast::Visibility::DataBus => true, }; let len = param.1.field_count() as usize; params_is_databus.extend(vec![is_databus; len]); @@ -92,7 +93,7 @@ impl FunctionBuilder { let index = self .current_function .dfg - .make_constant(FieldElement::from(i as i128), Type::field()); + .make_constant(FieldElement::from(i as i128), Type::length_type()); let element = self.insert_array_get(value, index, typ[0].clone()); self.add_to_data_bus(element, databus); } diff --git a/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs b/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs index 9d27554dcaa..b24c5632b24 100644 --- a/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs +++ b/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs @@ -1,9 +1,10 @@ pub(crate) mod data_bus; -use std::{borrow::Cow, rc::Rc}; +use std::{borrow::Cow, collections::BTreeMap, rc::Rc}; -use acvm::FieldElement; +use acvm::{acir::circuit::ErrorSelector, FieldElement}; use noirc_errors::Location; +use noirc_frontend::monomorphization::ast::InlineType; use crate::ssa::ir::{ basic_block::BasicBlockId, @@ -18,7 +19,7 @@ use super::{ basic_block::BasicBlock, dfg::{CallStack, InsertInstructionResult}, function::RuntimeType, - instruction::{ConstrainError, InstructionId, Intrinsic}, + instruction::{ConstrainError, ErrorType, InstructionId, Intrinsic}, }, ssa_gen::Ssa, }; @@ -35,6 +36,7 @@ pub(crate) struct FunctionBuilder { current_block: BasicBlockId, finished_functions: Vec, call_stack: CallStack, + error_types: BTreeMap, } impl FunctionBuilder { @@ -42,23 +44,27 @@ impl FunctionBuilder { /// /// This creates the new function internally so there is no need to call .new_function() /// right after constructing a new FunctionBuilder. - pub(crate) fn new( - function_name: String, - function_id: FunctionId, - runtime: RuntimeType, - ) -> Self { - let mut new_function = Function::new(function_name, function_id); - new_function.set_runtime(runtime); - let current_block = new_function.entry_block(); + pub(crate) fn new(function_name: String, function_id: FunctionId) -> Self { + let new_function = Function::new(function_name, function_id); Self { + current_block: new_function.entry_block(), current_function: new_function, - current_block, finished_functions: Vec::new(), call_stack: CallStack::new(), + error_types: BTreeMap::default(), } } + /// Set the runtime of the initial function that is created internally after constructing + /// the FunctionBuilder. A function's default runtime type is `RuntimeType::Acir(InlineType::Inline)`. + /// This should only be used immediately following construction of a FunctionBuilder + /// and will panic if there are any already finished functions. + pub(crate) fn set_runtime(&mut self, runtime: RuntimeType) { + assert_eq!(self.finished_functions.len(), 0, "Attempted to set runtime on a FunctionBuilder with finished functions. A FunctionBuilder's runtime should only be set on its initial function"); + self.current_function.set_runtime(runtime); + } + /// Finish the current function and create a new function. /// /// A FunctionBuilder can always only work on one function at a time, so care @@ -79,8 +85,13 @@ impl FunctionBuilder { } /// Finish the current function and create a new ACIR function. - pub(crate) fn new_function(&mut self, name: String, function_id: FunctionId) { - self.new_function_with_type(name, function_id, RuntimeType::Acir); + pub(crate) fn new_function( + &mut self, + name: String, + function_id: FunctionId, + inline_type: InlineType, + ) { + self.new_function_with_type(name, function_id, RuntimeType::Acir(inline_type)); } /// Finish the current function and create a new unconstrained function. @@ -91,7 +102,7 @@ impl FunctionBuilder { /// Consume the FunctionBuilder returning all the functions it has generated. pub(crate) fn finish(mut self) -> Ssa { self.finished_functions.push(self.current_function); - Ssa::new(self.finished_functions) + Ssa::new(self.finished_functions, self.error_types) } /// Add a parameter to the current function with the given parameter type. @@ -153,9 +164,10 @@ impl FunctionBuilder { instruction: Instruction, ctrl_typevars: Option>, ) -> InsertInstructionResult { + let block = self.current_block(); self.current_function.dfg.insert_instruction_and_results( instruction, - self.current_block, + block, ctrl_typevars, self.call_stack.clone(), ) @@ -195,12 +207,9 @@ impl FunctionBuilder { self.call_stack.clone() } - /// Insert a Load instruction at the end of the current block, loading from the given offset - /// of the given address which should point to a previous Allocate instruction. Note that - /// this is limited to loading a single value. Loading multiple values (such as a tuple) - /// will require multiple loads. - /// 'offset' is in units of FieldElements here. So loading the fourth FieldElement stored in - /// an array will have an offset of 3. + /// Insert a Load instruction at the end of the current block, loading from the given address + /// which should point to a previous Allocate instruction. Note that this is limited to loading + /// a single value. Loading multiple values (such as a tuple) will require multiple loads. /// Returns the element that was loaded. pub(crate) fn insert_load(&mut self, address: ValueId, type_to_load: Type) -> ValueId { self.insert_instruction(Instruction::Load { address }, Some(vec![type_to_load])).first() @@ -221,11 +230,14 @@ impl FunctionBuilder { operator: BinaryOp, rhs: ValueId, ) -> ValueId { - assert_eq!( - self.type_of_value(lhs), - self.type_of_value(rhs), - "ICE - Binary instruction operands must have the same type" - ); + let lhs_type = self.type_of_value(lhs); + let rhs_type = self.type_of_value(rhs); + if operator != BinaryOp::Shl && operator != BinaryOp::Shr { + assert_eq!( + lhs_type, rhs_type, + "ICE - Binary instruction operands must have the same type" + ); + } let instruction = Instruction::Binary(Binary { lhs, rhs, operator }); self.insert_instruction(instruction, None).first() } @@ -259,7 +271,7 @@ impl FunctionBuilder { &mut self, lhs: ValueId, rhs: ValueId, - assert_message: Option>, + assert_message: Option, ) { self.insert_instruction(Instruction::Constrain(lhs, rhs, assert_message), None); } @@ -306,12 +318,34 @@ impl FunctionBuilder { index: ValueId, value: ValueId, ) -> ValueId { - self.insert_instruction(Instruction::ArraySet { array, index, value }, None).first() + self.insert_instruction(Instruction::ArraySet { array, index, value, mutable: false }, None) + .first() + } + + /// Insert an instruction to increment an array's reference count. This only has an effect + /// in unconstrained code where arrays are reference counted and copy on write. + pub(crate) fn insert_inc_rc(&mut self, value: ValueId) { + self.insert_instruction(Instruction::IncrementRc { value }, None); + } + + /// Insert an instruction to decrement an array's reference count. This only has an effect + /// in unconstrained code where arrays are reference counted and copy on write. + pub(crate) fn insert_dec_rc(&mut self, value: ValueId) { + self.insert_instruction(Instruction::DecrementRc { value }, None); + } + + /// Insert an enable_side_effects_if instruction. These are normally only automatically + /// inserted during the flattening pass when branching is removed. + pub(crate) fn insert_enable_side_effects_if(&mut self, condition: ValueId) { + self.insert_instruction(Instruction::EnableSideEffects { condition }, None); } /// Terminates the current block with the given terminator instruction + /// if the current block does not already have a terminator instruction. fn terminate_block_with(&mut self, terminator: TerminatorInstruction) { - self.current_function.dfg.set_block_terminator(self.current_block, terminator); + if self.current_function.dfg[self.current_block].terminator().is_none() { + self.current_function.dfg.set_block_terminator(self.current_block, terminator); + } } /// Terminate the current block with a jmp instruction to jmp to the given @@ -384,22 +418,74 @@ impl FunctionBuilder { /// within the given value. If the given value is not an array and does not contain /// any arrays, this does nothing. pub(crate) fn increment_array_reference_count(&mut self, value: ValueId) { + self.update_array_reference_count(value, true, None); + } + + /// Insert instructions to decrement the reference count of any array(s) stored + /// within the given value. If the given value is not an array and does not contain + /// any arrays, this does nothing. + pub(crate) fn decrement_array_reference_count(&mut self, value: ValueId) { + self.update_array_reference_count(value, false, None); + } + + /// Increment or decrement the given value's reference count if it is an array. + /// If it is not an array, this does nothing. Note that inc_rc and dec_rc instructions + /// are ignored outside of unconstrained code. + fn update_array_reference_count( + &mut self, + value: ValueId, + increment: bool, + load_address: Option, + ) { match self.type_of_value(value) { Type::Numeric(_) => (), Type::Function => (), Type::Reference(element) => { if element.contains_an_array() { - let value = self.insert_load(value, element.as_ref().clone()); - self.increment_array_reference_count(value); + let reference = value; + let value = self.insert_load(reference, element.as_ref().clone()); + self.update_array_reference_count(value, increment, Some(reference)); } } - Type::Array(..) | Type::Slice(..) => { - self.insert_instruction(Instruction::IncrementRc { value }, None); + typ @ Type::Array(..) | typ @ Type::Slice(..) => { // If there are nested arrays or slices, we wait until ArrayGet // is issued to increment the count of that array. + let update_rc = |this: &mut Self, value| { + if increment { + this.insert_inc_rc(value); + } else { + this.insert_dec_rc(value); + } + }; + + update_rc(self, value); + let dfg = &self.current_function.dfg; + + // This is a bit odd, but in brillig the inc_rc instruction operates on + // a copy of the array's metadata, so we need to re-store a loaded array + // even if there have been no other changes to it. + if let Some(address) = load_address { + // If we already have a load from the Type::Reference case, avoid inserting + // another load and rc update. + self.insert_store(address, value); + } else if let Value::Instruction { instruction, .. } = &dfg[value] { + let instruction = &dfg[*instruction]; + if let Instruction::Load { address } = instruction { + // We can't re-use `value` in case the original address was stored + // to again in the meantime. So introduce another load. + let address = *address; + let new_load = self.insert_load(address, typ); + update_rc(self, new_load); + self.insert_store(address, new_load); + } + } } } } + + pub(crate) fn record_error_type(&mut self, selector: ErrorSelector, typ: ErrorType) { + self.error_types.insert(selector, typ); + } } impl std::ops::Index for FunctionBuilder { @@ -430,10 +516,9 @@ impl std::ops::Index for FunctionBuilder { mod tests { use std::rc::Rc; - use acvm::FieldElement; + use acvm::{acir::AcirField, FieldElement}; use crate::ssa::ir::{ - function::RuntimeType, instruction::{Endian, Intrinsic}, map::Id, types::Type, @@ -448,7 +533,7 @@ mod tests { // let x = 7; // let bits = x.to_le_bits(8); let func_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("func".into(), func_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("func".into(), func_id); let one = builder.numeric_constant(FieldElement::one(), Type::bool()); let zero = builder.numeric_constant(FieldElement::zero(), Type::bool()); diff --git a/compiler/noirc_evaluator/src/ssa/ir/cfg.rs b/compiler/noirc_evaluator/src/ssa/ir/cfg.rs index ebfbf003ec4..5a3f07cd673 100644 --- a/compiler/noirc_evaluator/src/ssa/ir/cfg.rs +++ b/compiler/noirc_evaluator/src/ssa/ir/cfg.rs @@ -95,10 +95,6 @@ impl ControlFlowGraph { ); predecessor_node.successors.insert(to); let successor_node = self.data.entry(to).or_default(); - assert!( - successor_node.predecessors.len() < 2, - "ICE: A cfg node cannot have more than two predecessors" - ); successor_node.predecessors.insert(from); } diff --git a/compiler/noirc_evaluator/src/ssa/ir/dfg.rs b/compiler/noirc_evaluator/src/ssa/ir/dfg.rs index 870b5e602f1..f763ae52d50 100644 --- a/compiler/noirc_evaluator/src/ssa/ir/dfg.rs +++ b/compiler/noirc_evaluator/src/ssa/ir/dfg.rs @@ -13,7 +13,7 @@ use super::{ value::{Value, ValueId}, }; -use acvm::FieldElement; +use acvm::{acir::AcirField, FieldElement}; use fxhash::FxHashMap as HashMap; use iter_extended::vecmap; use noirc_errors::Location; @@ -22,7 +22,7 @@ use noirc_errors::Location; /// its blocks, instructions, and values. This struct is largely responsible for /// owning most data in a function and handing out Ids to this data that can be /// shared without worrying about ownership. -#[derive(Debug, Default)] +#[derive(Debug, Default, Clone)] pub(crate) struct DataFlowGraph { /// All of the instructions in a function instructions: DenseMap, @@ -284,7 +284,7 @@ impl DataFlowGraph { intrinsic_value_id } - pub(crate) fn get_intrinsic(&mut self, intrinsic: Intrinsic) -> Option<&ValueId> { + pub(crate) fn get_intrinsic(&self, intrinsic: Intrinsic) -> Option<&ValueId> { self.intrinsics.get(&intrinsic) } @@ -378,6 +378,30 @@ impl DataFlowGraph { value_id } + /// Replaces an instruction result with a fresh id. + pub(crate) fn replace_result( + &mut self, + instruction_id: InstructionId, + prev_value_id: ValueId, + ) -> ValueId { + let typ = self.type_of_value(prev_value_id); + let results = self.results.get_mut(&instruction_id).unwrap(); + let res_position = results + .iter() + .position(|&id| id == prev_value_id) + .expect("Result id not found while replacing"); + + let value_id = self.values.insert(Value::Instruction { + typ, + position: res_position, + instruction: instruction_id, + }); + + // Replace the value in list of results for this instruction + results[res_position] = value_id; + value_id + } + /// Returns the number of instructions /// inserted into functions. pub(crate) fn num_instructions(&self) -> usize { @@ -530,7 +554,10 @@ impl<'dfg> InsertInstructionResult<'dfg> { match self { InsertInstructionResult::SimplifiedTo(value) => *value, InsertInstructionResult::SimplifiedToMultiple(values) => values[0], - InsertInstructionResult::Results(_, results) => results[0], + InsertInstructionResult::Results(_, results) => { + assert_eq!(results.len(), 1); + results[0] + } InsertInstructionResult::InstructionRemoved => { panic!("Instruction was removed, no results") } @@ -559,6 +586,24 @@ impl<'dfg> InsertInstructionResult<'dfg> { } } +impl<'dfg> std::ops::Index for InsertInstructionResult<'dfg> { + type Output = ValueId; + + fn index(&self, index: usize) -> &Self::Output { + match self { + InsertInstructionResult::Results(_, results) => &results[index], + InsertInstructionResult::SimplifiedTo(result) => { + assert_eq!(index, 0); + result + } + InsertInstructionResult::SimplifiedToMultiple(results) => &results[index], + InsertInstructionResult::InstructionRemoved => { + panic!("Cannot index into InsertInstructionResult::InstructionRemoved") + } + } + } +} + #[cfg(test)] mod tests { use super::DataFlowGraph; diff --git a/compiler/noirc_evaluator/src/ssa/ir/dom.rs b/compiler/noirc_evaluator/src/ssa/ir/dom.rs index c1df0428c64..15fa3bad38d 100644 --- a/compiler/noirc_evaluator/src/ssa/ir/dom.rs +++ b/compiler/noirc_evaluator/src/ssa/ir/dom.rs @@ -249,13 +249,8 @@ mod tests { use crate::ssa::{ function_builder::FunctionBuilder, ir::{ - basic_block::BasicBlockId, - dfg::CallStack, - dom::DominatorTree, - function::{Function, RuntimeType}, - instruction::TerminatorInstruction, - map::Id, - types::Type, + basic_block::BasicBlockId, dfg::CallStack, dom::DominatorTree, function::Function, + instruction::TerminatorInstruction, map::Id, types::Type, }, }; @@ -286,7 +281,7 @@ mod tests { // return () // } let func_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("func".into(), func_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("func".into(), func_id); let cond = builder.add_parameter(Type::unsigned(1)); let block1_id = builder.insert_block(); @@ -395,7 +390,7 @@ mod tests { // jump block1() // } let func_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("func".into(), func_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("func".into(), func_id); let block1_id = builder.insert_block(); let block2_id = builder.insert_block(); diff --git a/compiler/noirc_evaluator/src/ssa/ir/function.rs b/compiler/noirc_evaluator/src/ssa/ir/function.rs index 360f5710113..c44824b464b 100644 --- a/compiler/noirc_evaluator/src/ssa/ir/function.rs +++ b/compiler/noirc_evaluator/src/ssa/ir/function.rs @@ -1,6 +1,7 @@ use std::collections::BTreeSet; use iter_extended::vecmap; +use noirc_frontend::monomorphization::ast::InlineType; use super::basic_block::BasicBlockId; use super::dfg::DataFlowGraph; @@ -12,11 +13,24 @@ use super::value::ValueId; #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] pub(crate) enum RuntimeType { // A noir function, to be compiled in ACIR and executed by ACVM - Acir, + Acir(InlineType), // Unconstrained function, to be compiled to brillig and executed by the Brillig VM Brillig, } +impl RuntimeType { + /// Returns whether the runtime type represents an entry point. + /// We return `false` for InlineType::Inline on default, which is true + /// in all cases except for main. `main` should be supported with special + /// handling in any places where this function determines logic. + pub(crate) fn is_entry_point(&self) -> bool { + match self { + RuntimeType::Acir(inline_type) => inline_type.is_entry_point(), + RuntimeType::Brillig => true, + } + } +} + /// A function holds a list of instructions. /// These instructions are further grouped into Basic blocks /// @@ -47,7 +61,14 @@ impl Function { pub(crate) fn new(name: String, id: FunctionId) -> Self { let mut dfg = DataFlowGraph::default(); let entry_block = dfg.make_block(); - Self { name, id, entry_block, dfg, runtime: RuntimeType::Acir } + Self { name, id, entry_block, dfg, runtime: RuntimeType::Acir(InlineType::default()) } + } + + /// Creates a new function as a clone of the one passed in with the passed in id. + pub(crate) fn clone_with_id(id: FunctionId, another: &Function) -> Self { + let dfg = another.dfg.clone(); + let entry_block = another.entry_block; + Self { name: another.name.clone(), id, entry_block, dfg, runtime: another.runtime } } /// The name of the function. @@ -71,6 +92,13 @@ impl Function { self.runtime = runtime; } + pub(crate) fn is_no_predicates(&self) -> bool { + match self.runtime() { + RuntimeType::Acir(inline_type) => matches!(inline_type, InlineType::NoPredicates), + RuntimeType::Brillig => false, + } + } + /// Retrieves the entry block of a function. /// /// A function's entry block contains the instructions @@ -129,7 +157,7 @@ impl Function { impl std::fmt::Display for RuntimeType { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - RuntimeType::Acir => write!(f, "acir"), + RuntimeType::Acir(inline_type) => write!(f, "acir({inline_type})"), RuntimeType::Brillig => write!(f, "brillig"), } } diff --git a/compiler/noirc_evaluator/src/ssa/ir/instruction.rs b/compiler/noirc_evaluator/src/ssa/ir/instruction.rs index 0b6c7074e45..e21deb9ef79 100644 --- a/compiler/noirc_evaluator/src/ssa/ir/instruction.rs +++ b/compiler/noirc_evaluator/src/ssa/ir/instruction.rs @@ -1,5 +1,18 @@ -use acvm::{acir::BlackBoxFunc, FieldElement}; +use std::hash::{Hash, Hasher}; + +use acvm::{ + acir::AcirField, + acir::{ + circuit::{ErrorSelector, STRING_ERROR_SELECTOR}, + BlackBoxFunc, + }, + FieldElement, +}; +use fxhash::FxHasher; use iter_extended::vecmap; +use noirc_frontend::hir_def::types::Type as HirType; + +use crate::ssa::opt::flatten_cfg::value_merger::ValueMerger; use super::{ basic_block::BasicBlockId, @@ -37,6 +50,7 @@ pub(crate) type InstructionId = Id; #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub(crate) enum Intrinsic { ArrayLen, + AsSlice, AssertConstant, SlicePushBack, SlicePushFront, @@ -51,12 +65,15 @@ pub(crate) enum Intrinsic { BlackBox(BlackBoxFunc), FromField, AsField, + AsWitness, + IsUnconstrained, } impl std::fmt::Display for Intrinsic { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Intrinsic::ArrayLen => write!(f, "array_len"), + Intrinsic::AsSlice => write!(f, "as_slice"), Intrinsic::AssertConstant => write!(f, "assert_constant"), Intrinsic::SlicePushBack => write!(f, "slice_push_back"), Intrinsic::SlicePushFront => write!(f, "slice_push_front"), @@ -73,6 +90,8 @@ 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::AsWitness => write!(f, "as_witness"), + Intrinsic::IsUnconstrained => write!(f, "is_unconstrained"), } } } @@ -83,12 +102,15 @@ impl Intrinsic { /// If there are no side effects then the `Intrinsic` can be removed if the result is unused. pub(crate) fn has_side_effects(&self) -> bool { match self { - Intrinsic::AssertConstant | Intrinsic::ApplyRangeConstraint => true, + Intrinsic::AssertConstant | Intrinsic::ApplyRangeConstraint | Intrinsic::AsWitness => { + true + } // These apply a constraint that the input must fit into a specified number of limbs. Intrinsic::ToBits(_) | Intrinsic::ToRadix(_) => true, Intrinsic::ArrayLen + | Intrinsic::AsSlice | Intrinsic::SlicePushBack | Intrinsic::SlicePushFront | Intrinsic::SlicePopBack @@ -97,10 +119,16 @@ impl Intrinsic { | Intrinsic::SliceRemove | Intrinsic::StrAsBytes | Intrinsic::FromField - | Intrinsic::AsField => false, + | Intrinsic::AsField + | Intrinsic::IsUnconstrained => false, // Some black box functions have side-effects - Intrinsic::BlackBox(func) => matches!(func, BlackBoxFunc::RecursiveAggregation), + Intrinsic::BlackBox(func) => matches!( + func, + BlackBoxFunc::RecursiveAggregation + | BlackBoxFunc::MultiScalarMul + | BlackBoxFunc::EmbeddedCurveAdd + ), } } @@ -109,6 +137,7 @@ impl Intrinsic { pub(crate) fn lookup(name: &str) -> Option { match name { "array_len" => Some(Intrinsic::ArrayLen), + "as_slice" => Some(Intrinsic::AsSlice), "assert_constant" => Some(Intrinsic::AssertConstant), "apply_range_constraint" => Some(Intrinsic::ApplyRangeConstraint), "slice_push_back" => Some(Intrinsic::SlicePushBack), @@ -124,6 +153,8 @@ impl Intrinsic { "to_be_bits" => Some(Intrinsic::ToBits(Endian::Big)), "from_field" => Some(Intrinsic::FromField), "as_field" => Some(Intrinsic::AsField), + "as_witness" => Some(Intrinsic::AsWitness), + "is_unconstrained" => Some(Intrinsic::IsUnconstrained), other => BlackBoxFunc::lookup(other).map(Intrinsic::BlackBox), } } @@ -153,7 +184,7 @@ pub(crate) enum Instruction { Truncate { value: ValueId, bit_size: u32, max_bit_size: u32 }, /// Constrains two values to be equal to one another. - Constrain(ValueId, ValueId, Option>), + Constrain(ValueId, ValueId, Option), /// Range constrain `value` to `max_bit_size` RangeCheck { value: ValueId, max_bit_size: u32, assert_message: Option }, @@ -185,8 +216,9 @@ pub(crate) enum Instruction { ArrayGet { array: ValueId, index: ValueId }, /// Creates a new array with the new value at the given index. All other elements are identical - /// to those in the given array. This will not modify the original array. - ArraySet { array: ValueId, index: ValueId, value: ValueId }, + /// to those in the given array. This will not modify the original array unless `mutable` is + /// set. This flag is off by default and only enabled when optimizations determine it is safe. + ArraySet { array: ValueId, index: ValueId, value: ValueId, mutable: bool }, /// An instruction to increment the reference count of a value. /// @@ -194,6 +226,21 @@ pub(crate) enum Instruction { /// implemented via reference counting. In ACIR code this is done with im::Vector and these /// IncrementRc instructions are ignored. IncrementRc { value: ValueId }, + + /// An instruction to decrement the reference count of a value. + /// + /// This currently only has an effect in Brillig code where array sharing and copy on write is + /// implemented via reference counting. In ACIR code this is done with im::Vector and these + /// DecrementRc instructions are ignored. + DecrementRc { value: ValueId }, + + /// Merge two values returned from opposite branches of a conditional into one. + IfElse { + then_condition: ValueId, + then_value: ValueId, + else_condition: ValueId, + else_value: ValueId, + }, } impl Instruction { @@ -207,13 +254,16 @@ impl Instruction { match self { Instruction::Binary(binary) => binary.result_type(), Instruction::Cast(_, typ) => InstructionResultType::Known(typ.clone()), - Instruction::Not(value) | Instruction::Truncate { value, .. } => { + Instruction::Not(value) + | Instruction::Truncate { value, .. } + | Instruction::ArraySet { array: value, .. } + | Instruction::IfElse { then_value: value, .. } => { InstructionResultType::Operand(*value) } - Instruction::ArraySet { array, .. } => InstructionResultType::Operand(*array), Instruction::Constrain(..) | Instruction::Store { .. } | Instruction::IncrementRc { .. } + | Instruction::DecrementRc { .. } | Instruction::RangeCheck { .. } | Instruction::EnableSideEffects { .. } => InstructionResultType::None, Instruction::Allocate { .. } @@ -229,20 +279,11 @@ impl Instruction { matches!(self.result_type(), InstructionResultType::Unknown) } - /// Pure `Instructions` are instructions which have no side-effects and results are a function of the inputs only, - /// i.e. there are no interactions with memory. - /// - /// Pure instructions can be replaced with the results of another pure instruction with the same inputs. - pub(crate) fn is_pure(&self, dfg: &DataFlowGraph) -> bool { + /// Indicates if the instruction can be safely replaced with the results of another instruction with the same inputs. + pub(crate) fn can_be_deduplicated(&self, dfg: &DataFlowGraph) -> bool { use Instruction::*; match self { - Binary(bin) => { - // In ACIR, a division with a false predicate outputs (0,0), so it cannot replace another instruction unless they have the same predicate - bin.operator != BinaryOp::Div - } - Cast(_, _) | Truncate { .. } | Not(_) | ArrayGet { .. } | ArraySet { .. } => true, - // These either have side-effects or interact with memory Constrain(..) | EnableSideEffects { .. } @@ -250,27 +291,40 @@ impl Instruction { | Load { .. } | Store { .. } | IncrementRc { .. } + | DecrementRc { .. } | RangeCheck { .. } => false, Call { func, .. } => match dfg[*func] { Value::Intrinsic(intrinsic) => !intrinsic.has_side_effects(), _ => false, }, + + // These can have different behavior depending on the EnableSideEffectsIf context. + // Replacing them with a similar instruction potentially enables replacing an instruction + // with one that was disabled. See + // https://github.com/noir-lang/noir/pull/4716#issuecomment-2047846328. + Binary(_) + | Cast(_, _) + | Not(_) + | Truncate { .. } + | IfElse { .. } + | ArrayGet { .. } + | ArraySet { .. } => !self.requires_acir_gen_predicate(dfg), } } - pub(crate) fn has_side_effects(&self, dfg: &DataFlowGraph) -> bool { + pub(crate) fn can_eliminate_if_unused(&self, dfg: &DataFlowGraph) -> bool { use Instruction::*; match self { Binary(binary) => { if matches!(binary.operator, BinaryOp::Div | BinaryOp::Mod) { if let Some(rhs) = dfg.get_numeric_constant(binary.rhs) { - rhs == FieldElement::zero() + rhs != FieldElement::zero() } else { - true + false } } else { - false + true } } Cast(_, _) @@ -279,28 +333,67 @@ impl Instruction { | Allocate | Load { .. } | ArrayGet { .. } - | ArraySet { .. } => false, + | IfElse { .. } + | ArraySet { .. } => true, Constrain(..) | Store { .. } | EnableSideEffects { .. } | IncrementRc { .. } - | RangeCheck { .. } => true, + | DecrementRc { .. } + | RangeCheck { .. } => false, // Some `Intrinsic`s have side effects so we must check what kind of `Call` this is. Call { func, .. } => match dfg[*func] { - Value::Intrinsic(intrinsic) => intrinsic.has_side_effects(), + // Explicitly allows removal of unused ec operations, even if they can fail + Value::Intrinsic(Intrinsic::BlackBox(BlackBoxFunc::MultiScalarMul)) + | Value::Intrinsic(Intrinsic::BlackBox(BlackBoxFunc::EmbeddedCurveAdd)) => true, + Value::Intrinsic(intrinsic) => !intrinsic.has_side_effects(), // All foreign functions are treated as having side effects. // This is because they can be used to pass information // from the ACVM to the external world during execution. - Value::ForeignFunction(_) => true, + Value::ForeignFunction(_) => false, // We must assume that functions contain a side effect as we cannot inspect more deeply. - Value::Function(_) => true, + Value::Function(_) => false, + + _ => false, + }, + } + } + /// If true the instruction will depends on enable_side_effects context during acir-gen + fn requires_acir_gen_predicate(&self, dfg: &DataFlowGraph) -> bool { + match self { + Instruction::Binary(binary) + if matches!(binary.operator, BinaryOp::Div | BinaryOp::Mod) => + { + true + } + Instruction::EnableSideEffects { .. } + | Instruction::ArrayGet { .. } + | Instruction::ArraySet { .. } => true, + + Instruction::Call { func, .. } => match dfg[*func] { + Value::Function(_) => true, + Value::Intrinsic(intrinsic) => { + matches!(intrinsic, Intrinsic::SliceInsert | Intrinsic::SliceRemove) + } _ => false, }, + Instruction::Cast(_, _) + | Instruction::Binary(_) + | Instruction::Not(_) + | Instruction::Truncate { .. } + | Instruction::Constrain(_, _, _) + | Instruction::RangeCheck { .. } + | Instruction::Allocate + | Instruction::Load { .. } + | Instruction::Store { .. } + | Instruction::IfElse { .. } + | Instruction::IncrementRc { .. } + | Instruction::DecrementRc { .. } => false, } } @@ -325,10 +418,12 @@ impl Instruction { // Must map the `lhs` and `rhs` first as the value `f` is moved with the closure let lhs = f(*lhs); let rhs = f(*rhs); - let assert_message = assert_message.as_ref().map(|error| match error.as_ref() { - ConstrainError::Dynamic(call_instr) => { - let new_instr = call_instr.map_values(f); - Box::new(ConstrainError::Dynamic(new_instr)) + let assert_message = assert_message.as_ref().map(|error| match error { + ConstrainError::UserDefined(selector, payload_values) => { + ConstrainError::UserDefined( + *selector, + payload_values.iter().map(|&value| f(value)).collect(), + ) } _ => error.clone(), }); @@ -349,10 +444,14 @@ impl Instruction { Instruction::ArrayGet { array, index } => { Instruction::ArrayGet { array: f(*array), index: f(*index) } } - Instruction::ArraySet { array, index, value } => { - Instruction::ArraySet { array: f(*array), index: f(*index), value: f(*value) } - } + Instruction::ArraySet { array, index, value, mutable } => Instruction::ArraySet { + array: f(*array), + index: f(*index), + value: f(*value), + mutable: *mutable, + }, Instruction::IncrementRc { value } => Instruction::IncrementRc { value: f(*value) }, + Instruction::DecrementRc { value } => Instruction::DecrementRc { value: f(*value) }, Instruction::RangeCheck { value, max_bit_size, assert_message } => { Instruction::RangeCheck { value: f(*value), @@ -360,6 +459,14 @@ impl Instruction { assert_message: assert_message.clone(), } } + Instruction::IfElse { then_condition, then_value, else_condition, else_value } => { + Instruction::IfElse { + then_condition: f(*then_condition), + then_value: f(*then_value), + else_condition: f(*else_condition), + else_value: f(*else_value), + } + } } } @@ -385,10 +492,10 @@ impl Instruction { Instruction::Constrain(lhs, rhs, assert_error) => { f(*lhs); f(*rhs); - if let Some(error) = assert_error.as_ref() { - if let ConstrainError::Dynamic(call_instr) = error.as_ref() { - call_instr.for_each_value(f); - } + if let Some(ConstrainError::UserDefined(_, values)) = assert_error.as_ref() { + values.iter().for_each(|&val| { + f(val); + }); } } @@ -401,7 +508,7 @@ impl Instruction { f(*array); f(*index); } - Instruction::ArraySet { array, index, value } => { + Instruction::ArraySet { array, index, value, mutable: _ } => { f(*array); f(*index); f(*value); @@ -409,9 +516,17 @@ impl Instruction { Instruction::EnableSideEffects { condition } => { f(*condition); } - Instruction::IncrementRc { value } | Instruction::RangeCheck { value, .. } => { + Instruction::IncrementRc { value } + | Instruction::DecrementRc { value } + | Instruction::RangeCheck { value, .. } => { f(*value); } + Instruction::IfElse { then_condition, then_value, else_condition, else_value } => { + f(*then_condition); + f(*then_value); + f(*else_condition); + f(*else_value); + } } } @@ -465,7 +580,7 @@ impl Instruction { let index = dfg.get_numeric_constant(*index); if let (Some((array, _)), Some(index)) = (array, index) { let index = - index.try_to_u64().expect("Expected array index to fit in u64") as usize; + index.try_to_u32().expect("Expected array index to fit in u32") as usize; if index < array.len() { return SimplifiedTo(array[index]); } @@ -477,7 +592,7 @@ impl Instruction { let index = dfg.get_numeric_constant(*index); if let (Some((array, element_type)), Some(index)) = (array, index) { let index = - index.try_to_u64().expect("Expected array index to fit in u64") as usize; + index.try_to_u32().expect("Expected array index to fit in u32") as usize; if index < array.len() { let new_array = dfg.make_array(array.update(index, *value), element_type); @@ -554,31 +669,75 @@ impl Instruction { Instruction::Load { .. } => None, Instruction::Store { .. } => None, Instruction::IncrementRc { .. } => None, + Instruction::DecrementRc { .. } => 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; + let max_potential_bits = dfg.get_value_max_num_bits(*value); + if max_potential_bits < *max_bit_size { + Remove + } else { + None + } + } + Instruction::IfElse { then_condition, then_value, else_condition, else_value } => { + let typ = dfg.type_of_value(*then_value); + + if let Some(constant) = dfg.get_numeric_constant(*then_condition) { + if constant.is_one() { + return SimplifiedTo(*then_value); + } else if constant.is_zero() { + return SimplifiedTo(*else_value); } } - None + + if matches!(&typ, Type::Numeric(_)) { + let then_condition = *then_condition; + let then_value = *then_value; + let else_condition = *else_condition; + let else_value = *else_value; + + let result = ValueMerger::merge_numeric_values( + dfg, + block, + then_condition, + else_condition, + then_value, + else_value, + ); + SimplifiedTo(result) + } else { + None + } } } } } +pub(crate) type ErrorType = HirType; + +pub(crate) fn error_selector_from_type(typ: &ErrorType) -> ErrorSelector { + match typ { + ErrorType::String(_) => STRING_ERROR_SELECTOR, + _ => { + let mut hasher = FxHasher::default(); + typ.hash(&mut hasher); + let hash = hasher.finish(); + assert!(hash != 0, "ICE: Error type {} collides with the string error type", typ); + ErrorSelector::new(hash) + } + } +} + #[derive(Debug, PartialEq, Eq, Hash, Clone)] pub(crate) enum ConstrainError { // These are errors which have been hardcoded during SSA gen - Static(String), - // These are errors which come from runtime expressions specified by a Noir program - // We store an `Instruction` as we want this Instruction to be atomic in SSA with - // a constrain instruction, and leave codegen of this instruction to lower level passes. - Dynamic(Instruction), + Intrinsic(String), + // These are errors issued by the user + UserDefined(ErrorSelector, Vec), } impl From for ConstrainError { fn from(value: String) -> Self { - ConstrainError::Static(value) + ConstrainError::Intrinsic(value) } } diff --git a/compiler/noirc_evaluator/src/ssa/ir/instruction/binary.rs b/compiler/noirc_evaluator/src/ssa/ir/instruction/binary.rs index 36f3ae8620b..dbb717b0a10 100644 --- a/compiler/noirc_evaluator/src/ssa/ir/instruction/binary.rs +++ b/compiler/noirc_evaluator/src/ssa/ir/instruction/binary.rs @@ -1,4 +1,4 @@ -use acvm::FieldElement; +use acvm::{acir::AcirField, FieldElement}; use super::{ DataFlowGraph, Instruction, InstructionResultType, NumericType, SimplifyResult, Type, ValueId, @@ -130,6 +130,12 @@ impl Binary { let zero = dfg.make_constant(FieldElement::zero(), operand_type); return SimplifyResult::SimplifiedTo(zero); } + if dfg.resolve(self.lhs) == dfg.resolve(self.rhs) + && dfg.get_value_max_num_bits(self.lhs) == 1 + { + // Squaring a boolean value is a noop. + return SimplifyResult::SimplifiedTo(self.lhs); + } } BinaryOp::Div => { if rhs_is_one { @@ -164,6 +170,7 @@ impl Binary { let one = dfg.make_constant(FieldElement::one(), Type::bool()); return SimplifyResult::SimplifiedTo(one); } + if operand_type == Type::bool() { // Simplify forms of `(boolean == true)` into `boolean` if lhs_is_one { diff --git a/compiler/noirc_evaluator/src/ssa/ir/instruction/call.rs b/compiler/noirc_evaluator/src/ssa/ir/instruction/call.rs index 9349d58c4d9..74e5653c7ba 100644 --- a/compiler/noirc_evaluator/src/ssa/ir/instruction/call.rs +++ b/compiler/noirc_evaluator/src/ssa/ir/instruction/call.rs @@ -1,7 +1,7 @@ use fxhash::FxHashMap as HashMap; use std::{collections::VecDeque, rc::Rc}; -use acvm::{acir::BlackBoxFunc, BlackBoxResolutionError, FieldElement}; +use acvm::{acir::AcirField, acir::BlackBoxFunc, BlackBoxResolutionError, FieldElement}; use iter_extended::vecmap; use num_bigint::BigUint; @@ -84,6 +84,27 @@ pub(super) fn simplify_call( SimplifyResult::None } } + Intrinsic::AsSlice => { + let array = dfg.get_array_constant(arguments[0]); + if let Some((array, array_type)) = array { + // Compute the resulting slice length by dividing the flattened + // array length by the size of each array element + let elements_size = array_type.element_size(); + let inner_element_types = array_type.element_types(); + assert_eq!( + 0, + array.len() % elements_size, + "expected array length to be multiple of its elements size" + ); + let slice_length_value = array.len() / elements_size; + let slice_length = + dfg.make_constant(slice_length_value.into(), Type::length_type()); + let new_slice = dfg.make_array(array, Type::Slice(inner_element_types)); + SimplifyResult::SimplifiedToMultiple(vec![slice_length, new_slice]) + } else { + SimplifyResult::None + } + } Intrinsic::SlicePushBack => { let slice = dfg.get_array_constant(arguments[1]); if let Some((mut slice, element_type)) = slice { @@ -229,11 +250,16 @@ pub(super) fn simplify_call( let max_bit_size = dfg.get_numeric_constant(arguments[1]); if let Some(max_bit_size) = max_bit_size { let max_bit_size = max_bit_size.to_u128() as u32; - SimplifyResult::SimplifiedToInstruction(Instruction::RangeCheck { - value, - max_bit_size, - assert_message: Some("call to assert_max_bit_size".to_owned()), - }) + let max_potential_bits = dfg.get_value_max_num_bits(value); + if max_potential_bits < max_bit_size { + SimplifyResult::Remove + } else { + SimplifyResult::SimplifiedToInstruction(Instruction::RangeCheck { + value, + max_bit_size, + assert_message: Some("call to assert_max_bit_size".to_owned()), + }) + } } else { SimplifyResult::None } @@ -267,6 +293,8 @@ pub(super) fn simplify_call( let instruction = Instruction::Cast(truncated_value, target_type); SimplifyResult::SimplifiedToInstruction(instruction) } + Intrinsic::AsWitness => SimplifyResult::None, + Intrinsic::IsUnconstrained => SimplifyResult::None, } } @@ -323,8 +351,13 @@ fn simplify_slice_push_back( let element_size = element_type.element_size(); let new_slice = dfg.make_array(slice, element_type); - let set_last_slice_value_instr = - Instruction::ArraySet { array: new_slice, index: arguments[0], value: arguments[2] }; + let set_last_slice_value_instr = Instruction::ArraySet { + array: new_slice, + index: arguments[0], + value: arguments[2], + mutable: false, + }; + let set_last_slice_value = dfg .insert_instruction_and_results(set_last_slice_value_instr, block, None, call_stack) .first(); @@ -333,7 +366,9 @@ fn simplify_slice_push_back( slice_sizes.insert(set_last_slice_value, slice_size / element_size); slice_sizes.insert(new_slice, slice_size / element_size); - let mut value_merger = ValueMerger::new(dfg, block, &mut slice_sizes); + let unknown = &mut HashMap::default(); + let mut value_merger = ValueMerger::new(dfg, block, &mut slice_sizes, unknown, None); + let new_slice = value_merger.merge_values( len_not_equals_capacity, len_equals_capacity, @@ -431,7 +466,7 @@ fn simplify_black_box_func( simplify_signature(dfg, arguments, acvm::blackbox_solver::ecdsa_secp256r1_verify) } - BlackBoxFunc::FixedBaseScalarMul + BlackBoxFunc::MultiScalarMul | BlackBoxFunc::SchnorrVerify | BlackBoxFunc::PedersenCommitment | BlackBoxFunc::PedersenHash @@ -459,6 +494,7 @@ fn simplify_black_box_func( ) } BlackBoxFunc::Sha256Compression => SimplifyResult::None, //TODO(Guillaume) + BlackBoxFunc::AES128Encrypt => SimplifyResult::None, } } diff --git a/compiler/noirc_evaluator/src/ssa/ir/instruction/cast.rs b/compiler/noirc_evaluator/src/ssa/ir/instruction/cast.rs index 671820e801d..d0ed5a1fa9c 100644 --- a/compiler/noirc_evaluator/src/ssa/ir/instruction/cast.rs +++ b/compiler/noirc_evaluator/src/ssa/ir/instruction/cast.rs @@ -1,4 +1,4 @@ -use acvm::FieldElement; +use acvm::{acir::AcirField, FieldElement}; use num_bigint::BigUint; use super::{DataFlowGraph, Instruction, NumericType, SimplifyResult, Type, Value, ValueId}; diff --git a/compiler/noirc_evaluator/src/ssa/ir/instruction/constrain.rs b/compiler/noirc_evaluator/src/ssa/ir/instruction/constrain.rs index b4198e2cfec..66f50440d64 100644 --- a/compiler/noirc_evaluator/src/ssa/ir/instruction/constrain.rs +++ b/compiler/noirc_evaluator/src/ssa/ir/instruction/constrain.rs @@ -1,4 +1,4 @@ -use acvm::FieldElement; +use acvm::{acir::AcirField, FieldElement}; use super::{Binary, BinaryOp, ConstrainError, DataFlowGraph, Instruction, Type, Value, ValueId}; @@ -7,7 +7,7 @@ use super::{Binary, BinaryOp, ConstrainError, DataFlowGraph, Instruction, Type, pub(super) fn decompose_constrain( lhs: ValueId, rhs: ValueId, - msg: &Option>, + msg: &Option, dfg: &mut DataFlowGraph, ) -> Vec { let lhs = dfg.resolve(lhs); diff --git a/compiler/noirc_evaluator/src/ssa/ir/map.rs b/compiler/noirc_evaluator/src/ssa/ir/map.rs index b6055973f1c..3c3feabc390 100644 --- a/compiler/noirc_evaluator/src/ssa/ir/map.rs +++ b/compiler/noirc_evaluator/src/ssa/ir/map.rs @@ -115,7 +115,7 @@ impl std::fmt::Display for Id { /// access to indices is provided. Since IDs must be stable and correspond /// to indices in the internal Vec, operations that would change element /// ordering like pop, remove, swap_remove, etc, are not possible. -#[derive(Debug)] +#[derive(Debug, Clone)] pub(crate) struct DenseMap { storage: Vec, } diff --git a/compiler/noirc_evaluator/src/ssa/ir/post_order.rs b/compiler/noirc_evaluator/src/ssa/ir/post_order.rs index 3cae86829ed..94ff96ba1d7 100644 --- a/compiler/noirc_evaluator/src/ssa/ir/post_order.rs +++ b/compiler/noirc_evaluator/src/ssa/ir/post_order.rs @@ -51,7 +51,7 @@ impl PostOrder { // stack, we push the item that's due for a visit first to the top. for successor_id in func.dfg[block_id].successors().rev() { if !visited.contains(&successor_id) { - // This not visited check would also be cover by the the next + // This not visited check would also be cover by the next // iteration, but checking here two saves an iteration per successor. stack.push((Visit::First, successor_id)); } @@ -73,12 +73,7 @@ impl PostOrder { mod tests { use crate::ssa::{ function_builder::FunctionBuilder, - ir::{ - function::{Function, RuntimeType}, - map::Id, - post_order::PostOrder, - types::Type, - }, + ir::{function::Function, map::Id, post_order::PostOrder, types::Type}, }; #[test] @@ -112,7 +107,7 @@ mod tests { // D, F, E, B, A, (C dropped as unreachable) let func_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("func".into(), func_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("func".into(), func_id); let block_b_id = builder.insert_block(); let block_c_id = builder.insert_block(); let block_d_id = builder.insert_block(); diff --git a/compiler/noirc_evaluator/src/ssa/ir/printer.rs b/compiler/noirc_evaluator/src/ssa/ir/printer.rs index 9bd43fab1ff..f7ffe2406ec 100644 --- a/compiler/noirc_evaluator/src/ssa/ir/printer.rs +++ b/compiler/noirc_evaluator/src/ssa/ir/printer.rs @@ -4,13 +4,16 @@ use std::{ fmt::{Formatter, Result}, }; +use acvm::acir::circuit::{ErrorSelector, STRING_ERROR_SELECTOR}; +use acvm::acir::AcirField; use iter_extended::vecmap; use super::{ basic_block::BasicBlockId, + dfg::DataFlowGraph, function::Function, instruction::{ConstrainError, Instruction, InstructionId, TerminatorInstruction}, - value::ValueId, + value::{Value, ValueId}, }; /// Helper function for Function's Display impl to pretty-print the function with the given formatter. @@ -60,7 +63,6 @@ pub(crate) fn display_block( /// Specialize displaying value ids so that if they refer to a numeric /// constant or a function we print those directly. fn value(function: &Function, id: ValueId) -> String { - use super::value::Value; let id = function.dfg.resolve(id); match &function.dfg[id] { Value::NumericConstant { constant, typ } => { @@ -156,7 +158,6 @@ fn display_instruction_inner( Instruction::Constrain(lhs, rhs, error) => { write!(f, "constrain {} == {}", show(*lhs), show(*rhs))?; if let Some(error) = error { - write!(f, " ")?; display_constrain_error(function, error, f) } else { writeln!(f) @@ -176,35 +177,80 @@ fn display_instruction_inner( Instruction::ArrayGet { array, index } => { writeln!(f, "array_get {}, index {}", show(*array), show(*index)) } - Instruction::ArraySet { array, index, value } => { - writeln!( - f, - "array_set {}, index {}, value {}", - show(*array), - show(*index), - show(*value) - ) + Instruction::ArraySet { array, index, value, mutable } => { + let array = show(*array); + let index = show(*index); + let value = show(*value); + let mutable = if *mutable { " mut" } else { "" }; + writeln!(f, "array_set{mutable} {array}, index {index}, value {value}") } Instruction::IncrementRc { value } => { writeln!(f, "inc_rc {}", show(*value)) } + Instruction::DecrementRc { value } => { + writeln!(f, "dec_rc {}", show(*value)) + } Instruction::RangeCheck { value, max_bit_size, .. } => { writeln!(f, "range_check {} to {} bits", show(*value), *max_bit_size,) } + Instruction::IfElse { then_condition, then_value, else_condition, else_value } => { + let then_condition = show(*then_condition); + let then_value = show(*then_value); + let else_condition = show(*else_condition); + let else_value = show(*else_value); + writeln!( + f, + "if {then_condition} then {then_value} else if {else_condition} then {else_value}" + ) + } } } +/// Tries to extract a constant string from an error payload. +pub(crate) fn try_to_extract_string_from_error_payload( + error_selector: ErrorSelector, + values: &[ValueId], + dfg: &DataFlowGraph, +) -> Option { + ((error_selector == STRING_ERROR_SELECTOR) && (values.len() == 1)) + .then_some(()) + .and_then(|()| { + let Value::Array { array: values, .. } = &dfg[values[0]] else { + return None; + }; + let fields: Option> = + values.iter().map(|value_id| dfg.get_numeric_constant(*value_id)).collect(); + + fields + }) + .map(|fields| { + fields + .iter() + .map(|field| { + let as_u8 = field.try_to_u64().unwrap_or_default() as u8; + as_u8 as char + }) + .collect() + }) +} + fn display_constrain_error( function: &Function, error: &ConstrainError, f: &mut Formatter, ) -> Result { match error { - ConstrainError::Static(assert_message_string) => { - writeln!(f, "{assert_message_string:?}") + ConstrainError::Intrinsic(assert_message_string) => { + writeln!(f, " '{assert_message_string:?}'") } - ConstrainError::Dynamic(assert_message_call) => { - display_instruction_inner(function, assert_message_call, f) + ConstrainError::UserDefined(selector, values) => { + if let Some(constant_string) = + try_to_extract_string_from_error_payload(*selector, values, &function.dfg) + { + writeln!(f, " '{}'", constant_string) + } else { + writeln!(f, ", data {}", value_list(function, values)) + } } } } diff --git a/compiler/noirc_evaluator/src/ssa/ir/types.rs b/compiler/noirc_evaluator/src/ssa/ir/types.rs index ea3f5393245..76b5bc43384 100644 --- a/compiler/noirc_evaluator/src/ssa/ir/types.rs +++ b/compiler/noirc_evaluator/src/ssa/ir/types.rs @@ -1,8 +1,10 @@ use std::rc::Rc; -use acvm::FieldElement; +use acvm::{acir::AcirField, FieldElement}; use iter_extended::vecmap; +use crate::ssa::ssa_gen::SSA_WORD_SIZE; + /// A numeric type in the Intermediate representation /// Note: we class NativeField as a numeric type /// though we also apply limitations to it, such as not @@ -92,7 +94,7 @@ impl Type { /// Creates the type of an array's length. pub(crate) fn length_type() -> Type { - Type::unsigned(64) + Type::unsigned(SSA_WORD_SIZE) } /// Returns the bit size of the provided numeric type. @@ -159,6 +161,21 @@ impl Type { Type::Reference(element) => element.contains_an_array(), } } + + pub(crate) fn element_types(self) -> Rc> { + match self { + Type::Array(element_types, _) | Type::Slice(element_types) => element_types, + other => panic!("element_types: Expected array or slice, found {other}"), + } + } + + pub(crate) fn first(&self) -> Type { + match self { + Type::Numeric(_) | Type::Function => self.clone(), + Type::Reference(typ) => typ.first(), + Type::Slice(element_types) | Type::Array(element_types, _) => element_types[0].first(), + } + } } /// Composite Types are essentially flattened struct or tuple types. diff --git a/compiler/noirc_evaluator/src/ssa/opt/array_set.rs b/compiler/noirc_evaluator/src/ssa/opt/array_set.rs new file mode 100644 index 00000000000..cf61d7fd73f --- /dev/null +++ b/compiler/noirc_evaluator/src/ssa/opt/array_set.rs @@ -0,0 +1,104 @@ +use crate::ssa::{ + ir::{ + basic_block::BasicBlockId, + dfg::DataFlowGraph, + instruction::{Instruction, InstructionId}, + types::Type::{Array, Slice}, + }, + ssa_gen::Ssa, +}; +use fxhash::{FxHashMap as HashMap, FxHashSet}; + +impl Ssa { + /// Map arrays with the last instruction that uses it + /// For this we simply process all the instructions in execution order + /// and update the map whenever there is a match + #[tracing::instrument(level = "trace", skip(self))] + pub(crate) fn array_set_optimization(mut self) -> Self { + for func in self.functions.values_mut() { + if !func.runtime().is_entry_point() { + let mut reachable_blocks = func.reachable_blocks(); + assert_eq!(reachable_blocks.len(), 1, "Expected there to be 1 block remaining in Acir function for array_set optimization"); + + let block = reachable_blocks.pop_first().unwrap(); + let instructions_to_update = analyze_last_uses(&func.dfg, block); + make_mutable(&mut func.dfg, block, instructions_to_update); + } + } + self + } +} + +/// Returns the set of ArraySet instructions that can be made mutable +/// because their input value is unused elsewhere afterward. +fn analyze_last_uses(dfg: &DataFlowGraph, block_id: BasicBlockId) -> FxHashSet { + let block = &dfg[block_id]; + let mut array_to_last_use = HashMap::default(); + let mut instructions_that_can_be_made_mutable = FxHashSet::default(); + + for instruction_id in block.instructions() { + match &dfg[*instruction_id] { + Instruction::ArrayGet { array, .. } => { + let array = dfg.resolve(*array); + + if let Some(existing) = array_to_last_use.insert(array, *instruction_id) { + instructions_that_can_be_made_mutable.remove(&existing); + } + } + Instruction::ArraySet { array, .. } => { + let array = dfg.resolve(*array); + + if let Some(existing) = array_to_last_use.insert(array, *instruction_id) { + instructions_that_can_be_made_mutable.remove(&existing); + } + instructions_that_can_be_made_mutable.insert(*instruction_id); + } + Instruction::Call { arguments, .. } => { + for argument in arguments { + if matches!(dfg.type_of_value(*argument), Array { .. } | Slice { .. }) { + let argument = dfg.resolve(*argument); + + if let Some(existing) = array_to_last_use.insert(argument, *instruction_id) + { + instructions_that_can_be_made_mutable.remove(&existing); + } + } + } + } + _ => (), + } + } + + instructions_that_can_be_made_mutable +} + +/// Make each ArraySet instruction in `instructions_to_update` mutable. +fn make_mutable( + dfg: &mut DataFlowGraph, + block_id: BasicBlockId, + instructions_to_update: FxHashSet, +) { + if instructions_to_update.is_empty() { + return; + } + + // Take the instructions temporarily so we can mutate the DFG while we iterate through them + let block = &mut dfg[block_id]; + let instructions = block.take_instructions(); + + for instruction in &instructions { + if instructions_to_update.contains(instruction) { + let instruction = &mut dfg[*instruction]; + + if let Instruction::ArraySet { mutable, .. } = instruction { + *mutable = true; + } else { + unreachable!( + "Non-ArraySet instruction in instructions_to_update!\n{instruction:?}" + ); + } + } + } + + *dfg[block_id].instructions_mut() = instructions; +} diff --git a/compiler/noirc_evaluator/src/ssa/opt/array_use.rs b/compiler/noirc_evaluator/src/ssa/opt/array_use.rs deleted file mode 100644 index 0bb8b0112b6..00000000000 --- a/compiler/noirc_evaluator/src/ssa/opt/array_use.rs +++ /dev/null @@ -1,57 +0,0 @@ -use crate::ssa::{ - ir::{ - basic_block::BasicBlockId, - dfg::DataFlowGraph, - instruction::{Instruction, InstructionId}, - post_order::PostOrder, - value::{Value, ValueId}, - }, - ssa_gen::Ssa, -}; -use fxhash::FxHashMap as HashMap; - -impl Ssa { - /// Map arrays with the last instruction that uses it - /// For this we simply process all the instructions in execution order - /// and update the map whenever there is a match - #[tracing::instrument(level = "trace", skip(self))] - pub(crate) fn find_last_array_uses(&self) -> HashMap { - let mut array_use = HashMap::default(); - for func in self.functions.values() { - let mut reverse_post_order = PostOrder::with_function(func).into_vec(); - reverse_post_order.reverse(); - for block in reverse_post_order { - last_use(block, &func.dfg, &mut array_use); - } - } - array_use - } -} - -/// Updates the array_def map when an instructions is using an array -fn last_use( - block_id: BasicBlockId, - dfg: &DataFlowGraph, - array_def: &mut HashMap, -) { - let block = &dfg[block_id]; - for instruction_id in block.instructions() { - match &dfg[*instruction_id] { - Instruction::ArrayGet { array, .. } | Instruction::ArraySet { array, .. } => { - let array = dfg.resolve(*array); - array_def.insert(array, *instruction_id); - } - Instruction::Call { arguments, .. } => { - for argument in arguments { - let resolved_arg = dfg.resolve(*argument); - if matches!(dfg[resolved_arg], Value::Array { .. }) { - array_def.insert(resolved_arg, *instruction_id); - } - } - } - _ => { - // Nothing to do - } - } - } -} diff --git a/compiler/noirc_evaluator/src/ssa/opt/as_slice_length.rs b/compiler/noirc_evaluator/src/ssa/opt/as_slice_length.rs new file mode 100644 index 00000000000..69eab1da0ed --- /dev/null +++ b/compiler/noirc_evaluator/src/ssa/opt/as_slice_length.rs @@ -0,0 +1,71 @@ +use crate::ssa::{ + ir::{ + function::Function, + instruction::{Instruction, InstructionId, Intrinsic}, + types::Type, + value::Value, + }, + ssa_gen::Ssa, +}; +use fxhash::FxHashMap as HashMap; + +impl Ssa { + /// A simple SSA pass to find any calls to `Intrinsic::AsSlice` and replacing any references to the length of the + /// resulting slice with the length of the array from which it was generated. + /// + /// This allows the length of a slice generated from an array to be used in locations where a constant value is + /// necessary when the value of the array is unknown. + /// + /// Note that this pass must be placed before loop unrolling to be useful. + #[tracing::instrument(level = "trace", skip(self))] + pub(crate) fn as_slice_optimization(mut self) -> Self { + for func in self.functions.values_mut() { + let known_slice_lengths = known_slice_lengths(func); + replace_known_slice_lengths(func, known_slice_lengths); + } + self + } +} + +fn known_slice_lengths(func: &Function) -> HashMap { + let mut known_slice_lengths = HashMap::default(); + for block_id in func.reachable_blocks() { + let block = &func.dfg[block_id]; + for instruction_id in block.instructions() { + let (target_func, arguments) = match &func.dfg[*instruction_id] { + Instruction::Call { func, arguments } => (func, arguments), + _ => continue, + }; + + match &func.dfg[*target_func] { + Value::Intrinsic(Intrinsic::AsSlice) => { + let array_typ = func.dfg.type_of_value(arguments[0]); + if let Type::Array(_, length) = array_typ { + known_slice_lengths.insert(*instruction_id, length); + } else { + unreachable!("AsSlice called with non-array {}", array_typ); + } + } + _ => continue, + }; + } + } + known_slice_lengths +} + +fn replace_known_slice_lengths( + func: &mut Function, + known_slice_lengths: HashMap, +) { + known_slice_lengths.into_iter().for_each(|(instruction_id, known_length)| { + let call_returns = func.dfg.instruction_results(instruction_id); + let original_slice_length = call_returns[0]; + + // We won't use the new id for the original unknown length. + // This isn't strictly necessary as a new result will be defined the next time for which the instruction + // is reinserted but this avoids leaving the program in an invalid state. + func.dfg.replace_result(instruction_id, original_slice_length); + let known_length = func.dfg.make_constant(known_length.into(), Type::length_type()); + func.dfg.set_value_from_id(original_slice_length, known_length); + }); +} diff --git a/compiler/noirc_evaluator/src/ssa/opt/bubble_up_constrains.rs b/compiler/noirc_evaluator/src/ssa/opt/bubble_up_constrains.rs index b737c51d145..0409f0e6a49 100644 --- a/compiler/noirc_evaluator/src/ssa/opt/bubble_up_constrains.rs +++ b/compiler/noirc_evaluator/src/ssa/opt/bubble_up_constrains.rs @@ -77,7 +77,6 @@ mod test { use crate::ssa::{ function_builder::FunctionBuilder, ir::{ - function::RuntimeType, instruction::{Binary, BinaryOp, Instruction}, map::Id, types::Type, @@ -100,7 +99,7 @@ mod test { let main_id = Id::test_new(0); // Compiling main - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("main".into(), main_id); let v0 = builder.add_parameter(Type::field()); let one = builder.field_constant(1u128); diff --git a/compiler/noirc_evaluator/src/ssa/opt/constant_folding.rs b/compiler/noirc_evaluator/src/ssa/opt/constant_folding.rs index 06ae4bf5202..48bd70ff139 100644 --- a/compiler/noirc_evaluator/src/ssa/opt/constant_folding.rs +++ b/compiler/noirc_evaluator/src/ssa/opt/constant_folding.rs @@ -6,9 +6,8 @@ //! by the [`DataFlowGraph`] automatically as new instructions are pushed. //! - Check whether any input values have been constrained to be equal to a value of a simpler form //! by a [constrain instruction][Instruction::Constrain]. If so, replace the input value with the simpler form. -//! - Check whether the instruction is [pure][Instruction::is_pure()] -//! and there exists a duplicate instruction earlier in the same block. -//! If so, the instruction can be replaced with the results of this previous instruction. +//! - Check whether the instruction [can_be_replaced][Instruction::can_be_replaced()] +//! by duplicate instruction earlier in the same block. //! //! These operations are done in parallel so that they can each benefit from each other //! without the need for multiple passes. @@ -22,7 +21,7 @@ //! different blocks are merged, i.e. after the [`flatten_cfg`][super::flatten_cfg] pass. use std::collections::HashSet; -use acvm::FieldElement; +use acvm::{acir::AcirField, FieldElement}; use iter_extended::vecmap; use crate::ssa::{ @@ -257,9 +256,9 @@ impl Context { } } - // If the instruction doesn't have side-effects, cache the results so we can reuse them if - // the same instruction appears again later in the block. - if instruction.is_pure(dfg) { + // If the instruction doesn't have side-effects and if it won't interact with enable_side_effects during acir_gen, + // we cache the results so we can reuse them if the same instruction appears again later in the block. + if instruction.can_be_deduplicated(dfg) { instruction_result_cache.insert(instruction, instruction_results); } } @@ -283,13 +282,13 @@ mod test { use crate::ssa::{ function_builder::FunctionBuilder, ir::{ - function::RuntimeType, instruction::{Binary, BinaryOp, Instruction, TerminatorInstruction}, map::Id, types::Type, value::{Value, ValueId}, }, }; + use acvm::acir::AcirField; #[test] fn simple_constant_fold() { @@ -305,7 +304,7 @@ mod test { let main_id = Id::test_new(0); // Compiling main - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("main".into(), main_id); let v0 = builder.add_parameter(Type::field()); let one = builder.field_constant(1u128); @@ -361,7 +360,7 @@ mod test { let main_id = Id::test_new(0); // Compiling main - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("main".into(), main_id); let v0 = builder.add_parameter(Type::unsigned(16)); let v1 = builder.add_parameter(Type::unsigned(16)); @@ -415,7 +414,7 @@ mod test { let main_id = Id::test_new(0); // Compiling main - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("main".into(), main_id); let v0 = builder.add_parameter(Type::unsigned(16)); let v1 = builder.add_parameter(Type::unsigned(16)); @@ -471,7 +470,7 @@ mod test { let main_id = Id::test_new(0); // Compiling main - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("main".into(), main_id); let v0 = builder.add_parameter(Type::field()); let one = builder.field_constant(1u128); let v1 = builder.insert_binary(v0, BinaryOp::Add, one); @@ -518,7 +517,7 @@ mod test { let main_id = Id::test_new(0); // Compiling main - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("main".into(), main_id); let v0 = builder.add_parameter(Type::unsigned(16)); let v1 = builder.insert_cast(v0, Type::unsigned(32)); @@ -562,7 +561,7 @@ mod test { let main_id = Id::test_new(0); // Compiling main - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("main".into(), main_id); let v0 = builder.add_parameter(Type::bool()); let v1 = builder.add_parameter(Type::bool()); let v2 = builder.add_parameter(Type::bool()); @@ -608,4 +607,55 @@ mod test { assert_eq!(main.dfg[instructions[4]], Instruction::Constrain(v1, v_true, None)); assert_eq!(main.dfg[instructions[5]], Instruction::Constrain(v2, v_false, None)); } + + // Regression for #4600 + #[test] + fn array_get_regression() { + // fn main f0 { + // b0(v0: u1, v1: u64): + // enable_side_effects_if v0 + // v2 = array_get [Field 0, Field 1], index v1 + // v3 = not v0 + // enable_side_effects_if v3 + // v4 = array_get [Field 0, Field 1], index v1 + // } + // + // We want to make sure after constant folding both array_gets remain since they are + // under different enable_side_effects_if contexts and thus one may be disabled while + // the other is not. If one is removed, it is possible e.g. v4 is replaced with v2 which + // is disabled (only gets from index 0) and thus returns the wrong result. + let main_id = Id::test_new(0); + + // Compiling main + let mut builder = FunctionBuilder::new("main".into(), main_id); + let v0 = builder.add_parameter(Type::bool()); + let v1 = builder.add_parameter(Type::unsigned(64)); + + builder.insert_enable_side_effects_if(v0); + + let zero = builder.field_constant(0u128); + let one = builder.field_constant(1u128); + + let typ = Type::Array(Rc::new(vec![Type::field()]), 2); + let array = builder.array_constant(vec![zero, one].into(), typ); + + let _v2 = builder.insert_array_get(array, v1, Type::field()); + let v3 = builder.insert_not(v0); + + builder.insert_enable_side_effects_if(v3); + let _v4 = builder.insert_array_get(array, v1, Type::field()); + + // Expected output is unchanged + let ssa = builder.finish(); + let main = ssa.main(); + let instructions = main.dfg[main.entry_block()].instructions(); + let starting_instruction_count = instructions.len(); + assert_eq!(starting_instruction_count, 5); + + let ssa = ssa.fold_constants(); + let main = ssa.main(); + let instructions = main.dfg[main.entry_block()].instructions(); + let ending_instruction_count = instructions.len(); + assert_eq!(starting_instruction_count, ending_instruction_count); + } } diff --git a/compiler/noirc_evaluator/src/ssa/opt/defunctionalize.rs b/compiler/noirc_evaluator/src/ssa/opt/defunctionalize.rs index 1f09a132132..cfeb8751f25 100644 --- a/compiler/noirc_evaluator/src/ssa/opt/defunctionalize.rs +++ b/compiler/noirc_evaluator/src/ssa/opt/defunctionalize.rs @@ -13,8 +13,8 @@ use crate::ssa::{ function_builder::FunctionBuilder, ir::{ basic_block::BasicBlockId, - function::{Function, FunctionId, RuntimeType, Signature}, - instruction::{BinaryOp, ConstrainError, Instruction}, + function::{Function, FunctionId, Signature}, + instruction::{BinaryOp, Instruction}, types::{NumericType, Type}, value::{Value, ValueId}, }, @@ -90,19 +90,6 @@ impl DefunctionalizationContext { Instruction::Call { func: target_func_id, arguments } => { (*target_func_id, arguments) } - // Constrain instruction potentially hold a call instruction themselves - // thus we need to account for them. - Instruction::Constrain(_, _, Some(constrain_error)) => { - if let ConstrainError::Dynamic(Instruction::Call { - func: target_func_id, - arguments, - }) = constrain_error.as_ref() - { - (*target_func_id, arguments) - } else { - continue; - } - } _ => continue, }; @@ -134,20 +121,7 @@ impl DefunctionalizationContext { } _ => {} } - if let Some(mut new_instruction) = replacement_instruction { - if let Instruction::Constrain(lhs, rhs, constrain_error_call) = instruction { - let new_error_call = if let Some(error) = constrain_error_call { - match error.as_ref() { - ConstrainError::Dynamic(_) => { - Some(Box::new(ConstrainError::Dynamic(new_instruction))) - } - _ => None, - } - } else { - None - }; - new_instruction = Instruction::Constrain(lhs, rhs, new_error_call); - } + if let Some(new_instruction) = replacement_instruction { func.dfg[instruction_id] = new_instruction; } } @@ -304,7 +278,7 @@ fn create_apply_function( ) -> FunctionId { assert!(!function_ids.is_empty()); ssa.add_fn(|id| { - let mut function_builder = FunctionBuilder::new("apply".to_string(), id, RuntimeType::Acir); + let mut function_builder = FunctionBuilder::new("apply".to_string(), id); let target_id = function_builder.add_parameter(Type::field()); let params_ids = vecmap(signature.params, |typ| function_builder.add_parameter(typ)); diff --git a/compiler/noirc_evaluator/src/ssa/opt/die.rs b/compiler/noirc_evaluator/src/ssa/opt/die.rs index f7d8adb5275..42383680f44 100644 --- a/compiler/noirc_evaluator/src/ssa/opt/die.rs +++ b/compiler/noirc_evaluator/src/ssa/opt/die.rs @@ -7,7 +7,7 @@ use crate::ssa::{ basic_block::{BasicBlock, BasicBlockId}, dfg::DataFlowGraph, function::Function, - instruction::{Instruction, InstructionId}, + instruction::{Instruction, InstructionId, Intrinsic}, post_order::PostOrder, value::{Value, ValueId}, }, @@ -44,7 +44,7 @@ fn dead_instruction_elimination(function: &mut Function) { context.remove_unused_instructions_in_block(function, *block); } - context.remove_increment_rc_instructions(&mut function.dfg); + context.remove_rc_instructions(&mut function.dfg); } /// Per function context for tracking unused values and which instructions to remove. @@ -53,10 +53,10 @@ struct Context { used_values: HashSet, instructions_to_remove: HashSet, - /// IncrementRc instructions must be revisited after the main DIE pass since + /// IncrementRc & DecrementRc instructions must be revisited after the main DIE pass since /// they technically contain side-effects but we still want to remove them if their /// `value` parameter is not used elsewhere. - increment_rc_instructions: Vec<(InstructionId, BasicBlockId)>, + rc_instructions: Vec<(InstructionId, BasicBlockId)>, } impl Context { @@ -85,8 +85,9 @@ impl Context { } else { let instruction = &function.dfg[*instruction_id]; - if let Instruction::IncrementRc { .. } = instruction { - self.increment_rc_instructions.push((*instruction_id, block_id)); + use Instruction::*; + if matches!(instruction, IncrementRc { .. } | DecrementRc { .. }) { + self.rc_instructions.push((*instruction_id, block_id)); } else { instruction.for_each_value(|value| { self.mark_used_instruction_results(&function.dfg, value); @@ -107,12 +108,16 @@ impl Context { fn is_unused(&self, instruction_id: InstructionId, function: &Function) -> bool { let instruction = &function.dfg[instruction_id]; - if instruction.has_side_effects(&function.dfg) { - // If the instruction has side effects we should never remove it. - false - } else { + if instruction.can_eliminate_if_unused(&function.dfg) { let results = function.dfg.instruction_results(instruction_id); results.iter().all(|result| !self.used_values.contains(result)) + } else if let Instruction::Call { func, arguments } = instruction { + // TODO: make this more general for instructions which don't have results but have side effects "sometimes" like `Intrinsic::AsWitness` + let as_witness_id = function.dfg.get_intrinsic(Intrinsic::AsWitness); + as_witness_id == Some(func) && !self.used_values.contains(&arguments[0]) + } else { + // If the instruction has side effects we should never remove it. + false } } @@ -145,16 +150,19 @@ impl Context { } } - fn remove_increment_rc_instructions(self, dfg: &mut DataFlowGraph) { - for (increment_rc, block) in self.increment_rc_instructions { - let value = match &dfg[increment_rc] { + fn remove_rc_instructions(self, dfg: &mut DataFlowGraph) { + for (rc, block) in self.rc_instructions { + let value = match &dfg[rc] { Instruction::IncrementRc { value } => *value, - other => unreachable!("Expected IncrementRc instruction, found {other:?}"), + Instruction::DecrementRc { value } => *value, + other => { + unreachable!("Expected IncrementRc or DecrementRc instruction, found {other:?}") + } }; - // This could be more efficient if we have to remove multiple IncrementRcs in a single block + // This could be more efficient if we have to remove multiple instructions in a single block if !self.used_values.contains(&value) { - dfg[block].instructions_mut().retain(|instruction| *instruction != increment_rc); + dfg[block].instructions_mut().retain(|instruction| *instruction != rc); } } } @@ -165,7 +173,6 @@ mod test { use crate::ssa::{ function_builder::FunctionBuilder, ir::{ - function::RuntimeType, instruction::{BinaryOp, Intrinsic}, map::Id, types::Type, @@ -195,7 +202,7 @@ mod test { let main_id = Id::test_new(0); // Compiling main - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("main".into(), main_id); let v0 = builder.add_parameter(Type::field()); let b1 = builder.insert_block(); @@ -253,4 +260,47 @@ mod test { assert_eq!(main.dfg[main.entry_block()].instructions().len(), 1); assert_eq!(main.dfg[b1].instructions().len(), 6); } + + #[test] + fn as_witness_die() { + // fn main f0 { + // b0(v0: Field): + // v1 = add v0, Field 1 + // v2 = add v0, Field 2 + // call as_witness(v2) + // return v1 + // } + let main_id = Id::test_new(0); + + // Compiling main + let mut builder = FunctionBuilder::new("main".into(), main_id); + let v0 = builder.add_parameter(Type::field()); + + let one = builder.field_constant(1u128); + let two = builder.field_constant(2u128); + + let v1 = builder.insert_binary(v0, BinaryOp::Add, one); + let v2 = builder.insert_binary(v0, BinaryOp::Add, two); + let as_witness = builder.import_intrinsic("as_witness").unwrap(); + builder.insert_call(as_witness, vec![v2], Vec::new()); + builder.terminate_with_return(vec![v1]); + + let ssa = builder.finish(); + let main = ssa.main(); + + // The instruction count never includes the terminator instruction + assert_eq!(main.dfg[main.entry_block()].instructions().len(), 3); + + // Expected output: + // + // acir(inline) fn main f0 { + // b0(v0: Field): + // v3 = add v0, Field 1 + // return v3 + // } + let ssa = ssa.dead_instruction_elimination(); + let main = ssa.main(); + + assert_eq!(main.dfg[main.entry_block()].instructions().len(), 1); + } } diff --git a/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs b/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs index 943a57c1bc0..e07f947db8d 100644 --- a/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs +++ b/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs @@ -134,7 +134,7 @@ use fxhash::FxHashMap as HashMap; use std::collections::{BTreeMap, HashSet}; -use acvm::FieldElement; +use acvm::{acir::AcirField, acir::BlackBoxFunc, FieldElement}; use iter_extended::vecmap; use crate::ssa::{ @@ -155,9 +155,6 @@ mod branch_analysis; mod capacity_tracker; pub(crate) mod value_merger; -use capacity_tracker::SliceCapacityTracker; -use value_merger::ValueMerger; - impl Ssa { /// Flattens the control flow graph of main such that the function is left with a /// single block containing all instructions and no more control-flow. @@ -167,7 +164,9 @@ impl Ssa { /// For more information, see the module-level comment at the top of this file. #[tracing::instrument(level = "trace", skip(self))] pub(crate) fn flatten_cfg(mut self) -> Ssa { - flatten_function_cfg(self.main_mut()); + for function in self.functions.values_mut() { + flatten_function_cfg(function); + } self } } @@ -199,22 +198,47 @@ struct Context<'f> { /// found, the top of this conditions stack is popped since we are no longer under that /// condition. If we are under multiple conditions (a nested if), the topmost condition is /// the most recent condition combined with all previous conditions via `And` instructions. - conditions: Vec<(BasicBlockId, ValueId)>, + condition_stack: Vec, /// Maps SSA array values with a slice type to their size. /// This is maintained by appropriate calls to the `SliceCapacityTracker` and is used by the `ValueMerger`. slice_sizes: HashMap, + + /// Stack of block arguments + /// When processing a block, we pop this stack to get its arguments + /// and at the end we push the arguments for his successor + arguments_stack: Vec>, } +#[derive(Clone)] pub(crate) struct Store { old_value: ValueId, new_value: ValueId, } -struct Branch { - condition: ValueId, +#[derive(Clone)] +struct ConditionalBranch { + // Contains the last processed block during the processing of the branch. last_block: BasicBlockId, + // The unresolved condition of the branch + old_condition: ValueId, + // The condition of the branch + condition: ValueId, + // The store values accumulated when processing the branch store_values: HashMap, + // The allocations accumulated when processing the branch + local_allocations: HashSet, +} + +struct ConditionalContext { + // Condition from the conditional statement + condition: ValueId, + // Block containing the conditional statement + entry_block: BasicBlockId, + // First block of the then branch + then_branch: ConditionalBranch, + // First block of the else branch + else_branch: Option, } fn flatten_function_cfg(function: &mut Function) { @@ -233,90 +257,98 @@ fn flatten_function_cfg(function: &mut Function) { store_values: HashMap::default(), local_allocations: HashSet::new(), branch_ends, - conditions: Vec::new(), slice_sizes: HashMap::default(), + condition_stack: Vec::new(), + arguments_stack: Vec::new(), }; context.flatten(); } impl<'f> Context<'f> { fn flatten(&mut self) { - // Start with following the terminator of the entry block since we don't - // need to flatten the entry block into itself. - self.handle_terminator(self.inserter.function.entry_block()); + // Flatten the CFG by inlining all instructions from the queued blocks + // until all blocks have been flattened. + // We follow the terminator of each block to determine which blocks to + // process next + let mut queue = vec![self.inserter.function.entry_block()]; + while let Some(block) = queue.pop() { + self.inline_block(block); + let to_process = self.handle_terminator(block, &queue); + for incoming_block in to_process { + if !queue.contains(&incoming_block) { + queue.push(incoming_block); + } + } + } } - /// Check the terminator of the given block and recursively inline any blocks reachable from - /// it. Since each block from a jmpif terminator is inlined successively, we must handle - /// instructions with side effects like constrain and store specially to preserve correctness. - /// For these instructions we must keep track of what the current condition is and modify - /// the instructions according to the module-level comment at the top of this file. Note that - /// the current condition is all the jmpif conditions required to reach the current block, - /// combined via `And` instructions. - /// - /// Returns the last block to be inlined. This is either the return block of the function or, - /// if self.conditions is not empty, the end block of the most recent condition. - fn handle_terminator(&mut self, block: BasicBlockId) -> BasicBlockId { - // As we recursively flatten inner blocks, we need to track the slice information - // for the outer block before we start recursively inlining - let outer_block_instructions = self.inserter.function.dfg[block].instructions(); - let mut capacity_tracker = SliceCapacityTracker::new(&self.inserter.function.dfg); - for instruction in outer_block_instructions { - let results = self.inserter.function.dfg.instruction_results(*instruction); - let instruction = &self.inserter.function.dfg[*instruction]; - capacity_tracker.collect_slice_information( - instruction, - &mut self.slice_sizes, - results.to_vec(), - ); + /// Returns the updated condition so that + /// it is 'AND-ed' with the previous condition (if any) + fn link_condition(&mut self, condition: ValueId) -> ValueId { + // Retrieve the previous condition + if let Some(context) = self.condition_stack.last() { + let previous_branch = context.else_branch.as_ref().unwrap_or(&context.then_branch); + let and = Instruction::binary(BinaryOp::And, previous_branch.condition, condition); + self.insert_instruction(and, CallStack::new()) + } else { + condition + } + } + + /// Returns the current condition + fn get_last_condition(&self) -> Option { + self.condition_stack.last().map(|context| match &context.else_branch { + Some(else_branch) => else_branch.condition, + None => context.then_branch.condition, + }) + } + + // Inline all instructions from the given block into the entry block, and track slice capacities + fn inline_block(&mut self, block: BasicBlockId) { + if self.inserter.function.entry_block() == block { + // we do not inline the entry block into itself + // for the outer block before we start inlining + return; + } + + let arguments = self.arguments_stack.pop().unwrap(); + self.inserter.remember_block_params(block, &arguments); + + // If this is not a separate variable, clippy gets confused and says the to_vec is + // unnecessary, when removing it actually causes an aliasing/mutability error. + let instructions = self.inserter.function.dfg[block].instructions().to_vec(); + for instruction in instructions.iter() { + self.push_instruction(*instruction); } + } - match self.inserter.function.dfg[block].unwrap_terminator() { + /// Returns the list of blocks that need to be processed after the given block + /// For a normal block, it would be its successor + /// For blocks related to a conditional statement, we ensure to process + /// the 'then-branch', then the 'else-branch' (if it exists), and finally the end block + fn handle_terminator( + &mut self, + block: BasicBlockId, + work_list: &[BasicBlockId], + ) -> Vec { + let terminator = self.inserter.function.dfg[block].unwrap_terminator().clone(); + match &terminator { TerminatorInstruction::JmpIf { condition, then_destination, else_destination } => { - let old_condition = *condition; - let then_block = *then_destination; - let else_block = *else_destination; - let then_condition = self.inserter.resolve(old_condition); - - let one = FieldElement::one(); - let then_branch = - self.inline_branch(block, then_block, old_condition, then_condition, one); - - let else_condition = - self.insert_instruction(Instruction::Not(then_condition), CallStack::new()); - let zero = FieldElement::zero(); - - // Make sure the else branch sees the previous values of each store - // rather than any values created in the 'then' branch. - self.undo_stores_in_then_branch(&then_branch); - - let else_branch = - self.inline_branch(block, else_block, old_condition, else_condition, zero); - - // We must remember to reset whether side effects are enabled when both branches - // end, in addition to resetting the value of old_condition since it is set to - // known to be true/false within the then/else branch respectively. - self.insert_current_side_effects_enabled(); - - // We must map back to `then_condition` here. Mapping `old_condition` to itself would - // lose any previous mappings. - self.inserter.map_value(old_condition, then_condition); - - // While there is a condition on the stack we don't compile outside the condition - // until it is popped. This ensures we inline the full then and else branches - // before continuing from the end of the conditional here where they can be merged properly. - let end = self.branch_ends[&block]; - self.inline_branch_end(end, then_branch, else_branch) + self.arguments_stack.push(vec![]); + self.if_start(condition, then_destination, else_destination, &block) } TerminatorInstruction::Jmp { destination, arguments, call_stack: _ } => { - if let Some((end_block, _)) = self.conditions.last() { - if destination == end_block { - return block; + let arguments = vecmap(arguments.clone(), |value| self.inserter.resolve(value)); + self.arguments_stack.push(arguments); + if work_list.contains(destination) { + if work_list.last() == Some(destination) { + self.else_stop(&block) + } else { + self.then_stop(&block) } + } else { + vec![*destination] } - let destination = *destination; - let arguments = vecmap(arguments.clone(), |value| self.inserter.resolve(value)); - self.inline_block(destination, &arguments) } TerminatorInstruction::Return { return_values, call_stack } => { let call_stack = call_stack.clone(); @@ -326,27 +358,189 @@ impl<'f> Context<'f> { let entry = self.inserter.function.entry_block(); self.inserter.function.dfg.set_block_terminator(entry, new_return); - block + vec![] } } } - /// Push a condition to the stack of conditions. + /// Process a conditional statement + fn if_start( + &mut self, + condition: &ValueId, + then_destination: &BasicBlockId, + else_destination: &BasicBlockId, + if_entry: &BasicBlockId, + ) -> Vec { + // manage conditions + let old_condition = *condition; + let then_condition = self.inserter.resolve(old_condition); + + let one = FieldElement::one(); + let old_stores = std::mem::take(&mut self.store_values); + let old_allocations = std::mem::take(&mut self.local_allocations); + let branch = ConditionalBranch { + old_condition, + condition: self.link_condition(then_condition), + store_values: old_stores, + local_allocations: old_allocations, + last_block: *then_destination, + }; + let cond_context = ConditionalContext { + condition: then_condition, + entry_block: *if_entry, + then_branch: branch, + else_branch: None, + }; + self.condition_stack.push(cond_context); + self.insert_current_side_effects_enabled(); + // Optimization: within the then branch we know the condition to be true, so replace + // any references of it within this branch with true. Likewise, do the same with false + // with the else branch. We must be careful not to replace the condition if it is a + // known constant, otherwise we can end up setting 1 = 0 or vice-versa. + if self.inserter.function.dfg.get_numeric_constant(old_condition).is_none() { + let known_value = self.inserter.function.dfg.make_constant(one, Type::bool()); + + self.inserter.map_value(old_condition, known_value); + } + vec![self.branch_ends[if_entry], *else_destination, *then_destination] + } + + /// Switch context to the 'else-branch' + fn then_stop(&mut self, block: &BasicBlockId) -> Vec { + let mut cond_context = self.condition_stack.pop().unwrap(); + cond_context.then_branch.last_block = *block; + + let else_condition = + self.insert_instruction(Instruction::Not(cond_context.condition), CallStack::new()); + let else_condition = self.link_condition(else_condition); + + let zero = FieldElement::zero(); + // Make sure the else branch sees the previous values of each store + // rather than any values created in the 'then' branch. + let old_stores = std::mem::take(&mut cond_context.then_branch.store_values); + cond_context.then_branch.store_values = std::mem::take(&mut self.store_values); + self.undo_stores_in_then_branch(&cond_context.then_branch.store_values); + + let old_allocations = std::mem::take(&mut self.local_allocations); + let else_branch = ConditionalBranch { + old_condition: cond_context.then_branch.old_condition, + condition: else_condition, + store_values: old_stores, + local_allocations: old_allocations, + last_block: *block, + }; + let old_condition = else_branch.old_condition; + cond_context.then_branch.local_allocations.clear(); + cond_context.else_branch = Some(else_branch); + self.condition_stack.push(cond_context); + + self.insert_current_side_effects_enabled(); + // Optimization: within the then branch we know the condition to be true, so replace + // any references of it within this branch with true. Likewise, do the same with false + // with the else branch. We must be careful not to replace the condition if it is a + // known constant, otherwise we can end up setting 1 = 0 or vice-versa. + if self.inserter.function.dfg.get_numeric_constant(old_condition).is_none() { + let known_value = self.inserter.function.dfg.make_constant(zero, Type::bool()); + + self.inserter.map_value(old_condition, known_value); + } + assert_eq!(self.cfg.successors(*block).len(), 1); + vec![self.cfg.successors(*block).next().unwrap()] + } + + /// Process the 'exit' block of a conditional statement + fn else_stop(&mut self, block: &BasicBlockId) -> Vec { + let mut cond_context = self.condition_stack.pop().unwrap(); + if cond_context.else_branch.is_none() { + // then_stop() has not been called, this means that the conditional statement has no else branch + // so we simply do the then_stop() now + self.condition_stack.push(cond_context); + self.then_stop(block); + cond_context = self.condition_stack.pop().unwrap(); + } + + let mut else_branch = cond_context.else_branch.unwrap(); + let stores_in_branch = std::mem::replace(&mut self.store_values, else_branch.store_values); + self.local_allocations = std::mem::take(&mut else_branch.local_allocations); + else_branch.last_block = *block; + else_branch.store_values = stores_in_branch; + cond_context.else_branch = Some(else_branch); + + // We must remember to reset whether side effects are enabled when both branches + // end, in addition to resetting the value of old_condition since it is set to + // known to be true/false within the then/else branch respectively. + self.insert_current_side_effects_enabled(); + + // We must map back to `then_condition` here. Mapping `old_condition` to itself would + // lose any previous mappings. + self.inserter + .map_value(cond_context.then_branch.old_condition, cond_context.then_branch.condition); + + // While there is a condition on the stack we don't compile outside the condition + // until it is popped. This ensures we inline the full then and else branches + // before continuing from the end of the conditional here where they can be merged properly. + let end = self.branch_ends[&cond_context.entry_block]; + + // Merge arguments and stores from the else/end branches + self.inline_branch_end(end, cond_context); + + vec![self.cfg.successors(*block).next().unwrap()] + } + + /// Inline the ending block of a branch, the point where all blocks from a jmpif instruction + /// join back together. In particular this function must handle merging block arguments from + /// all of the join point's predecessors, and it must handle any differing side effects from + /// each branch. /// - /// This condition should be present while we're inlining each block reachable from the 'then' - /// branch of a jmpif instruction, until the branches eventually join back together. Likewise, - /// !condition should be present while we're inlining each block reachable from the 'else' - /// branch of a jmpif instruction until the join block. - fn push_condition(&mut self, start_block: BasicBlockId, condition: ValueId) { - let end_block = self.branch_ends[&start_block]; - - if let Some((_, previous_condition)) = self.conditions.last() { - let and = Instruction::binary(BinaryOp::And, *previous_condition, condition); - let new_condition = self.insert_instruction(and, CallStack::new()); - self.conditions.push((end_block, new_condition)); - } else { - self.conditions.push((end_block, condition)); + /// Afterwards, continues inlining recursively until it finds the next end block or finds the + /// end of the function. + /// + /// Returns the final block that was inlined. + fn inline_branch_end( + &mut self, + destination: BasicBlockId, + cond_context: ConditionalContext, + ) -> BasicBlockId { + assert_eq!(self.cfg.predecessors(destination).len(), 2); + let last_then = cond_context.then_branch.last_block; + let mut else_args = Vec::new(); + if cond_context.else_branch.is_some() { + let last_else = cond_context.else_branch.clone().unwrap().last_block; + else_args = self.inserter.function.dfg[last_else].terminator_arguments().to_vec(); } + + let then_args = self.inserter.function.dfg[last_then].terminator_arguments().to_vec(); + + let params = self.inserter.function.dfg.block_parameters(destination); + assert_eq!(params.len(), then_args.len()); + assert_eq!(params.len(), else_args.len()); + + let args = vecmap(then_args.iter().zip(else_args), |(then_arg, else_arg)| { + (self.inserter.resolve(*then_arg), self.inserter.resolve(else_arg)) + }); + + let block = self.inserter.function.entry_block(); + + // Cannot include this in the previous vecmap since it requires exclusive access to self + let args = vecmap(args, |(then_arg, else_arg)| { + let instruction = Instruction::IfElse { + then_condition: cond_context.then_branch.condition, + then_value: then_arg, + else_condition: cond_context.else_branch.as_ref().unwrap().condition, + else_value: else_arg, + }; + self.inserter + .function + .dfg + .insert_instruction_and_results(instruction, block, None, CallStack::new()) + .first() + }); + + self.merge_stores(cond_context.then_branch, cond_context.else_branch); + self.arguments_stack.pop(); + self.arguments_stack.pop(); + self.arguments_stack.push(args); + destination } /// Insert a new instruction into the function's entry block. @@ -385,8 +579,8 @@ impl<'f> Context<'f> { /// If the stack is empty, a "true" u1 constant is taken to be the active condition. This is /// necessary for re-enabling side-effects when re-emerging to a branch depth of 0. fn insert_current_side_effects_enabled(&mut self) { - let condition = match self.conditions.last() { - Some((_, cond)) => *cond, + let condition = match self.get_last_condition() { + Some(cond) => cond, None => { self.inserter.function.dfg.make_constant(FieldElement::one(), Type::unsigned(1)) } @@ -395,130 +589,16 @@ impl<'f> Context<'f> { self.insert_instruction_with_typevars(enable_side_effects, None); } - /// Inline one branch of a jmpif instruction. - /// - /// This will continue inlining recursively until the next end block is reached where each branch - /// of the jmpif instruction is joined back into a single block. - /// - /// Within a branch of a jmpif instruction, we can assume the condition of the jmpif to be - /// always true or false, depending on which branch we're in. - /// - /// Returns the ending block / join block of this branch. - fn inline_branch( - &mut self, - jmpif_block: BasicBlockId, - destination: BasicBlockId, - old_condition: ValueId, - new_condition: ValueId, - condition_value: FieldElement, - ) -> Branch { - if destination == self.branch_ends[&jmpif_block] { - // If the branch destination is the same as the end of the branch, this must be the - // 'else' case of an if with no else - so there is no else branch. - Branch { - condition: new_condition, - // The last block here is somewhat arbitrary. It only matters that it has no Jmp - // args that will be merged by inline_branch_end. Since jmpifs don't have - // block arguments, it is safe to use the jmpif block here. - last_block: jmpif_block, - store_values: HashMap::default(), - } - } else { - self.push_condition(jmpif_block, new_condition); - self.insert_current_side_effects_enabled(); - let old_stores = std::mem::take(&mut self.store_values); - let old_allocations = std::mem::take(&mut self.local_allocations); - - // Optimization: within the then branch we know the condition to be true, so replace - // any references of it within this branch with true. Likewise, do the same with false - // with the else branch. We must be careful not to replace the condition if it is a - // known constant, otherwise we can end up setting 1 = 0 or vice-versa. - if self.inserter.function.dfg.get_numeric_constant(old_condition).is_none() { - let known_value = - self.inserter.function.dfg.make_constant(condition_value, Type::bool()); - - self.inserter.map_value(old_condition, known_value); - } - - let final_block = self.inline_block(destination, &[]); - - self.conditions.pop(); - - let stores_in_branch = std::mem::replace(&mut self.store_values, old_stores); - self.local_allocations = old_allocations; - - Branch { - condition: new_condition, - last_block: final_block, - store_values: stores_in_branch, - } - } - } - - /// Inline the ending block of a branch, the point where all blocks from a jmpif instruction - /// join back together. In particular this function must handle merging block arguments from - /// all of the join point's predecessors, and it must handle any differing side effects from - /// each branch. - /// - /// Afterwards, continues inlining recursively until it finds the next end block or finds the - /// end of the function. - /// - /// Returns the final block that was inlined. - fn inline_branch_end( - &mut self, - destination: BasicBlockId, - then_branch: Branch, - else_branch: Branch, - ) -> BasicBlockId { - assert_eq!(self.cfg.predecessors(destination).len(), 2); - - let then_args = - self.inserter.function.dfg[then_branch.last_block].terminator_arguments().to_vec(); - let else_args = - self.inserter.function.dfg[else_branch.last_block].terminator_arguments().to_vec(); - - let params = self.inserter.function.dfg.block_parameters(destination); - assert_eq!(params.len(), then_args.len()); - assert_eq!(params.len(), else_args.len()); - - let args = vecmap(then_args.iter().zip(else_args), |(then_arg, else_arg)| { - (self.inserter.resolve(*then_arg), self.inserter.resolve(else_arg)) - }); - - let block = self.inserter.function.entry_block(); - - // Make sure we have tracked the slice capacities of any block arguments - let capacity_tracker = SliceCapacityTracker::new(&self.inserter.function.dfg); - for (then_arg, else_arg) in args.iter() { - capacity_tracker.compute_slice_capacity(*then_arg, &mut self.slice_sizes); - capacity_tracker.compute_slice_capacity(*else_arg, &mut self.slice_sizes); - } - - let mut value_merger = - ValueMerger::new(&mut self.inserter.function.dfg, block, &mut self.slice_sizes); - - // Cannot include this in the previous vecmap since it requires exclusive access to self - let args = vecmap(args, |(then_arg, else_arg)| { - value_merger.merge_values( - then_branch.condition, - else_branch.condition, - then_arg, - else_arg, - ) - }); - - self.merge_stores(then_branch, else_branch); - - // insert merge instruction - self.inline_block(destination, &args) - } - /// Merge any store instructions found in each branch. /// /// This function relies on the 'then' branch being merged before the 'else' branch of a jmpif /// instruction. If this ordering is changed, the ordering that store values are merged within /// this function also needs to be changed to reflect that. - fn merge_stores(&mut self, then_branch: Branch, else_branch: Branch) { + fn merge_stores( + &mut self, + then_branch: ConditionalBranch, + else_branch: Option, + ) { // Address -> (then_value, else_value, value_before_the_if) let mut new_map = BTreeMap::new(); @@ -526,35 +606,40 @@ impl<'f> Context<'f> { new_map.insert(address, (store.new_value, store.old_value, store.old_value)); } - for (address, store) in else_branch.store_values { - if let Some(entry) = new_map.get_mut(&address) { - entry.1 = store.new_value; - } else { - new_map.insert(address, (store.old_value, store.new_value, store.old_value)); + if else_branch.is_some() { + for (address, store) in else_branch.clone().unwrap().store_values { + if let Some(entry) = new_map.get_mut(&address) { + entry.1 = store.new_value; + } else { + new_map.insert(address, (store.old_value, store.new_value, store.old_value)); + } } } - // Most slice information is collected when instructions are inlined. - // We need to collect information on slice values here as we may possibly merge stores - // before any inlining occurs. - let capacity_tracker = SliceCapacityTracker::new(&self.inserter.function.dfg); - for (then_case, else_case, _) in new_map.values() { - capacity_tracker.compute_slice_capacity(*then_case, &mut self.slice_sizes); - capacity_tracker.compute_slice_capacity(*else_case, &mut self.slice_sizes); - } - let then_condition = then_branch.condition; - let else_condition = else_branch.condition; - + let else_condition = if let Some(branch) = else_branch { + branch.condition + } else { + self.inserter.function.dfg.make_constant(FieldElement::zero(), Type::bool()) + }; let block = self.inserter.function.entry_block(); - let mut value_merger = - ValueMerger::new(&mut self.inserter.function.dfg, block, &mut self.slice_sizes); // Merging must occur in a separate loop as we cannot borrow `self` as mutable while `value_merger` does let mut new_values = HashMap::default(); for (address, (then_case, else_case, _)) in &new_map { - let value = - value_merger.merge_values(then_condition, else_condition, *then_case, *else_case); + let instruction = Instruction::IfElse { + then_condition, + then_value: *then_case, + else_condition, + else_value: *else_case, + }; + let value = self + .inserter + .function + .dfg + .insert_instruction_and_results(instruction, block, None, CallStack::new()) + .first(); + new_values.insert(address, value); } @@ -571,16 +656,6 @@ impl<'f> Context<'f> { .insert(address, Store { old_value: *old_value, new_value: value }); } } - - // Collect any potential slice information on the stores we are merging - for (address, (_, _, _)) in &new_map { - let value = new_values[address]; - let address = *address; - let instruction = Instruction::Store { address, value }; - - let mut capacity_tracker = SliceCapacityTracker::new(&self.inserter.function.dfg); - capacity_tracker.collect_slice_information(&instruction, &mut self.slice_sizes, vec![]); - } } fn remember_store(&mut self, address: ValueId, new_value: ValueId) { @@ -594,48 +669,11 @@ impl<'f> Context<'f> { let old_value = self.insert_instruction_with_typevars(load.clone(), load_type).first(); - // Need this or else we will be missing a the previous value of a slice that we wish to merge - let mut capacity_tracker = SliceCapacityTracker::new(&self.inserter.function.dfg); - capacity_tracker.collect_slice_information( - &load, - &mut self.slice_sizes, - vec![old_value], - ); - self.store_values.insert(address, Store { old_value, new_value }); } } } - /// Inline all instructions from the given destination block into the entry block. - /// Afterwards, check the block's terminator and continue inlining recursively. - /// - /// Returns the final block that was inlined. - /// - /// Expects that the `arguments` given are already translated via self.inserter.resolve. - /// If they are not, it is possible some values which no longer exist, such as block - /// parameters, will be kept in the program. - fn inline_block(&mut self, destination: BasicBlockId, arguments: &[ValueId]) -> BasicBlockId { - self.inserter.remember_block_params(destination, arguments); - - // If this is not a separate variable, clippy gets confused and says the to_vec is - // unnecessary, when removing it actually causes an aliasing/mutability error. - let instructions = self.inserter.function.dfg[destination].instructions().to_vec(); - - for instruction in instructions.iter() { - let results = self.push_instruction(*instruction); - let (instruction, _) = self.inserter.map_instruction(*instruction); - let mut capacity_tracker = SliceCapacityTracker::new(&self.inserter.function.dfg); - capacity_tracker.collect_slice_information( - &instruction, - &mut self.slice_sizes, - results, - ); - } - - self.handle_terminator(destination) - } - /// Push the given instruction to the end of the entry block of the current function. /// /// Note that each ValueId of the instruction will be mapped via self.inserter.resolve. @@ -666,7 +704,7 @@ impl<'f> Context<'f> { instruction: Instruction, call_stack: CallStack, ) -> Instruction { - if let Some((_, condition)) = self.conditions.last().copied() { + if let Some(condition) = self.get_last_condition() { match instruction { Instruction::Constrain(lhs, rhs, message) => { // Replace constraint `lhs == rhs` with `condition * lhs == condition * rhs`. @@ -731,7 +769,38 @@ impl<'f> Context<'f> { Instruction::Call { func, arguments } } + //Issue #5045: We set curve points to infinity if condition is false + Value::Intrinsic(Intrinsic::BlackBox(BlackBoxFunc::EmbeddedCurveAdd)) => { + arguments[2] = self.var_or_one(arguments[2], condition, call_stack.clone()); + arguments[5] = self.var_or_one(arguments[5], condition, call_stack.clone()); + Instruction::Call { func, arguments } + } + Value::Intrinsic(Intrinsic::BlackBox(BlackBoxFunc::MultiScalarMul)) => { + let mut array_with_predicate = im::Vector::new(); + let array_typ; + if let Value::Array { array, typ } = + &self.inserter.function.dfg[arguments[0]] + { + array_typ = typ.clone(); + for (i, value) in array.clone().iter().enumerate() { + if i % 3 == 2 { + array_with_predicate.push_back(self.var_or_one( + *value, + condition, + call_stack.clone(), + )); + } else { + array_with_predicate.push_back(*value); + } + } + } else { + unreachable!(); + } + arguments[0] = + self.inserter.function.dfg.make_array(array_with_predicate, array_typ); + Instruction::Call { func, arguments } + } _ => Instruction::Call { func, arguments }, }, other => other, @@ -741,8 +810,22 @@ impl<'f> Context<'f> { } } - fn undo_stores_in_then_branch(&mut self, then_branch: &Branch) { - for (address, store) in &then_branch.store_values { + // Computes: if condition { var } else { 1 } + fn var_or_one(&mut self, var: ValueId, condition: ValueId, call_stack: CallStack) -> ValueId { + let field = self.insert_instruction( + Instruction::binary(BinaryOp::Mul, var, condition), + call_stack.clone(), + ); + let not_condition = + self.insert_instruction(Instruction::Not(condition), call_stack.clone()); + self.insert_instruction( + Instruction::binary(BinaryOp::Add, field, not_condition), + call_stack, + ) + } + + fn undo_stores_in_then_branch(&mut self, store_values: &HashMap) { + for (address, store) in store_values { let address = *address; let value = store.old_value; self.insert_instruction_with_typevars(Instruction::Store { address, value }, None); @@ -754,11 +837,13 @@ impl<'f> Context<'f> { mod test { use std::rc::Rc; + use acvm::acir::AcirField; + use crate::ssa::{ function_builder::FunctionBuilder, ir::{ dfg::DataFlowGraph, - function::{Function, RuntimeType}, + function::Function, instruction::{BinaryOp, Instruction, Intrinsic, TerminatorInstruction}, map::Id, types::Type, @@ -779,7 +864,7 @@ mod test { // return v1 // } let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("main".into(), main_id); let b1 = builder.insert_block(); let b2 = builder.insert_block(); @@ -833,7 +918,7 @@ mod test { // return // } let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("main".into(), main_id); let b1 = builder.insert_block(); let b2 = builder.insert_block(); @@ -882,7 +967,7 @@ mod test { // return // } let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("main".into(), main_id); let b1 = builder.insert_block(); let b2 = builder.insert_block(); @@ -943,7 +1028,7 @@ mod test { // return // } let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("main".into(), main_id); let b1 = builder.insert_block(); let b2 = builder.insert_block(); @@ -1033,7 +1118,7 @@ mod test { // ↘ ↙ // b9 let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("main".into(), main_id); let b1 = builder.insert_block(); let b2 = builder.insert_block(); @@ -1190,7 +1275,7 @@ mod test { // before the first store to allocate, which loaded an uninitialized value. // In this test we assert the ordering is strictly Allocate then Store then Load. let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("main".into(), main_id); let b1 = builder.insert_block(); let b2 = builder.insert_block(); @@ -1289,7 +1374,7 @@ mod test { // return // } let main_id = Id::test_new(1); - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("main".into(), main_id); builder.insert_block(); // entry @@ -1342,7 +1427,7 @@ mod test { // jmp b3() // } let main_id = Id::test_new(1); - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("main".into(), main_id); builder.insert_block(); // b0 let b1 = builder.insert_block(); @@ -1452,7 +1537,7 @@ mod test { // jmp b5() // } let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("main".into(), main_id); let b1 = builder.insert_block(); let b2 = builder.insert_block(); diff --git a/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg/branch_analysis.rs b/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg/branch_analysis.rs index 59bee00936a..ce54bb533f7 100644 --- a/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg/branch_analysis.rs +++ b/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg/branch_analysis.rs @@ -114,7 +114,7 @@ mod test { use crate::ssa::{ function_builder::FunctionBuilder, - ir::{cfg::ControlFlowGraph, function::RuntimeType, map::Id, types::Type}, + ir::{cfg::ControlFlowGraph, map::Id, types::Type}, opt::flatten_cfg::branch_analysis::find_branch_ends, }; @@ -134,7 +134,7 @@ mod test { // ↘ ↙ // b9 let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("main".into(), main_id); let b1 = builder.insert_block(); let b2 = builder.insert_block(); @@ -195,7 +195,7 @@ mod test { // ↘ ↙ // b15 let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("main".into(), main_id); let b1 = builder.insert_block(); let b2 = builder.insert_block(); diff --git a/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg/capacity_tracker.rs b/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg/capacity_tracker.rs index 7cd0fe3084e..f0760f29006 100644 --- a/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg/capacity_tracker.rs +++ b/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg/capacity_tracker.rs @@ -5,6 +5,7 @@ use crate::ssa::ir::{ value::{Value, ValueId}, }; +use acvm::{acir::AcirField, FieldElement}; use fxhash::FxHashMap as HashMap; pub(crate) struct SliceCapacityTracker<'a> { @@ -18,10 +19,10 @@ impl<'a> SliceCapacityTracker<'a> { /// Determine how the slice sizes map needs to be updated according to the provided instruction. pub(crate) fn collect_slice_information( - &mut self, + &self, instruction: &Instruction, slice_sizes: &mut HashMap, - results: Vec, + results: &[ValueId], ) { match instruction { Instruction::ArrayGet { array, .. } => { @@ -62,43 +63,72 @@ impl<'a> SliceCapacityTracker<'a> { | Intrinsic::SlicePushFront | Intrinsic::SlicePopBack | Intrinsic::SliceInsert - | Intrinsic::SliceRemove => (1, 1), + | Intrinsic::SliceRemove => (Some(1), 1), // `pop_front` returns the popped element, and then the respective slice. // This means in the case of a slice with structs, the result index of the popped slice // will change depending on the number of elements in the struct. // For example, a slice with four elements will look as such in SSA: // v3, v4, v5, v6, v7, v8 = call slice_pop_front(v1, v2) // where v7 is the slice length and v8 is the popped slice itself. - Intrinsic::SlicePopFront => (1, results.len() - 1), + Intrinsic::SlicePopFront => (Some(1), results.len() - 1), + // The slice capacity of these intrinsics is not determined by the arguments of the function. + Intrinsic::ToBits(_) | Intrinsic::ToRadix(_) => (None, 1), + Intrinsic::AsSlice => (Some(0), 1), _ => return, }; - let slice_contents = arguments[argument_index]; + let result_slice = results[result_index]; match intrinsic { Intrinsic::SlicePushBack | Intrinsic::SlicePushFront | Intrinsic::SliceInsert => { + let argument_index = argument_index + .expect("ICE: Should have an argument index for slice intrinsics"); + let slice_contents = arguments[argument_index]; + for arg in &arguments[(argument_index + 1)..] { let element_typ = self.dfg.type_of_value(*arg); if element_typ.contains_slice_element() { self.compute_slice_capacity(*arg, slice_sizes); } } + if let Some(contents_capacity) = slice_sizes.get(&slice_contents) { let new_capacity = *contents_capacity + 1; - slice_sizes.insert(results[result_index], new_capacity); + slice_sizes.insert(result_slice, new_capacity); } } Intrinsic::SlicePopBack | Intrinsic::SliceRemove | Intrinsic::SlicePopFront => { - // We do not decrement the size on intrinsics that could remove values from a slice. - // This is because we could potentially go back to the smaller slice and not fill in dummies. - // This pass should be tracking the potential max that a slice ***could be*** + let argument_index = argument_index + .expect("ICE: Should have an argument index for slice intrinsics"); + let slice_contents = arguments[argument_index]; + if let Some(contents_capacity) = slice_sizes.get(&slice_contents) { let new_capacity = *contents_capacity - 1; - slice_sizes.insert(results[result_index], new_capacity); + slice_sizes.insert(result_slice, new_capacity); } } + Intrinsic::ToBits(_) => { + // Compiler sanity check + assert!(matches!(self.dfg.type_of_value(result_slice), Type::Slice(_))); + slice_sizes.insert(result_slice, FieldElement::max_num_bits() as usize); + } + Intrinsic::ToRadix(_) => { + // Compiler sanity check + assert!(matches!(self.dfg.type_of_value(result_slice), Type::Slice(_))); + slice_sizes + .insert(result_slice, FieldElement::max_num_bytes() as usize); + } + Intrinsic::AsSlice => { + let argument_index = argument_index + .expect("ICE: Should have an argument index for AsSlice builtin"); + let array_size = self + .dfg + .try_get_array_length(arguments[argument_index]) + .expect("ICE: Should be have an array length for AsSlice input"); + slice_sizes.insert(result_slice, array_size); + } _ => {} } } 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 6b923a2e42d..c59134e4ecc 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 @@ -1,20 +1,25 @@ -use acvm::FieldElement; -use fxhash::FxHashMap as HashMap; +use acvm::{acir::AcirField, FieldElement}; +use fxhash::{FxHashMap as HashMap, FxHashSet}; use crate::ssa::ir::{ basic_block::BasicBlockId, - dfg::{CallStack, DataFlowGraph}, + dfg::{CallStack, DataFlowGraph, InsertInstructionResult}, instruction::{BinaryOp, Instruction}, types::Type, - value::ValueId, + value::{Value, ValueId}, }; pub(crate) struct ValueMerger<'a> { dfg: &'a mut DataFlowGraph, block: BasicBlockId, + + current_condition: Option, + // Maps SSA array values with a slice type to their size. // This must be computed before merging values. slice_sizes: &'a mut HashMap, + + array_set_conditionals: &'a mut HashMap, } impl<'a> ValueMerger<'a> { @@ -22,8 +27,10 @@ impl<'a> ValueMerger<'a> { dfg: &'a mut DataFlowGraph, block: BasicBlockId, slice_sizes: &'a mut HashMap, + array_set_conditionals: &'a mut HashMap, + current_condition: Option, ) -> Self { - ValueMerger { dfg, block, slice_sizes } + ValueMerger { dfg, block, slice_sizes, array_set_conditionals, current_condition } } /// Merge two values a and b from separate basic blocks to a single value. @@ -42,9 +49,14 @@ impl<'a> ValueMerger<'a> { else_value: ValueId, ) -> ValueId { match self.dfg.type_of_value(then_value) { - Type::Numeric(_) => { - self.merge_numeric_values(then_condition, else_condition, then_value, else_value) - } + Type::Numeric(_) => Self::merge_numeric_values( + self.dfg, + self.block, + then_condition, + else_condition, + then_value, + else_value, + ), typ @ Type::Array(_, _) => { self.merge_array_values(typ, then_condition, else_condition, then_value, else_value) } @@ -59,58 +71,57 @@ impl<'a> ValueMerger<'a> { /// Merge two numeric values a and b from separate basic blocks to a single value. This /// function would return the result of `if c { a } else { b }` as `c*a + (!c)*b`. pub(crate) fn merge_numeric_values( - &mut self, + dfg: &mut DataFlowGraph, + block: BasicBlockId, then_condition: ValueId, else_condition: ValueId, then_value: ValueId, else_value: ValueId, ) -> ValueId { - let then_type = self.dfg.type_of_value(then_value); - let else_type = self.dfg.type_of_value(else_value); + let then_type = dfg.type_of_value(then_value); + let else_type = dfg.type_of_value(else_value); assert_eq!( then_type, else_type, "Expected values merged to be of the same type but found {then_type} and {else_type}" ); - let then_call_stack = self.dfg.get_value_call_stack(then_value); - let else_call_stack = self.dfg.get_value_call_stack(else_value); + if then_value == else_value { + return then_value; + } + + let then_call_stack = dfg.get_value_call_stack(then_value); + let else_call_stack = dfg.get_value_call_stack(else_value); let call_stack = if then_call_stack.is_empty() { else_call_stack } else { then_call_stack }; // We must cast the bool conditions to the actual numeric type used by each value. - let then_condition = self - .dfg + let then_condition = dfg .insert_instruction_and_results( Instruction::Cast(then_condition, then_type), - self.block, + block, None, call_stack.clone(), ) .first(); - let else_condition = self - .dfg + let else_condition = dfg .insert_instruction_and_results( Instruction::Cast(else_condition, else_type), - self.block, + block, None, call_stack.clone(), ) .first(); let mul = Instruction::binary(BinaryOp::Mul, then_condition, then_value); - let then_value = self - .dfg - .insert_instruction_and_results(mul, self.block, None, call_stack.clone()) - .first(); + let then_value = + dfg.insert_instruction_and_results(mul, block, None, call_stack.clone()).first(); let mul = Instruction::binary(BinaryOp::Mul, else_condition, else_value); - let else_value = self - .dfg - .insert_instruction_and_results(mul, self.block, None, call_stack.clone()) - .first(); + let else_value = + dfg.insert_instruction_and_results(mul, block, None, call_stack.clone()).first(); let add = Instruction::binary(BinaryOp::Add, then_value, else_value); - self.dfg.insert_instruction_and_results(add, self.block, None, call_stack).first() + dfg.insert_instruction_and_results(add, block, None, call_stack).first() } /// Given an if expression that returns an array: `if c { array1 } else { array2 }`, @@ -131,6 +142,18 @@ impl<'a> ValueMerger<'a> { _ => panic!("Expected array type"), }; + let actual_length = len * element_types.len(); + + if let Some(result) = self.try_merge_only_changed_indices( + then_condition, + else_condition, + then_value, + else_value, + actual_length, + ) { + return result; + } + for i in 0..len { for (element_index, element_type) in element_types.iter().enumerate() { let index = ((i * element_types.len() + element_index) as u128).into(); @@ -175,12 +198,18 @@ impl<'a> ValueMerger<'a> { _ => panic!("Expected slice type"), }; - let then_len = *self.slice_sizes.get(&then_value_id).unwrap_or_else(|| { - panic!("ICE: Merging values during flattening encountered slice {then_value_id} without a preset size"); + let then_len = self.slice_sizes.get(&then_value_id).copied().unwrap_or_else(|| { + let (slice, typ) = self.dfg.get_array_constant(then_value_id).unwrap_or_else(|| { + panic!("ICE: Merging values during flattening encountered slice {then_value_id} without a preset size"); + }); + slice.len() / typ.element_types().len() }); - let else_len = *self.slice_sizes.get(&else_value_id).unwrap_or_else(|| { - panic!("ICE: Merging values during flattening encountered slice {else_value_id} without a preset size"); + let else_len = self.slice_sizes.get(&else_value_id).copied().unwrap_or_else(|| { + let (slice, typ) = self.dfg.get_array_constant(else_value_id).unwrap_or_else(|| { + panic!("ICE: Merging values during flattening encountered slice {else_value_id} without a preset size"); + }); + slice.len() / typ.element_types().len() }); let len = then_len.max(else_len); @@ -234,9 +263,9 @@ impl<'a> ValueMerger<'a> { /// such as with dynamic indexing of non-homogenous slices. fn make_slice_dummy_data(&mut self, typ: &Type) -> ValueId { match typ { - Type::Numeric(_) => { + Type::Numeric(numeric_type) => { let zero = FieldElement::zero(); - self.dfg.make_constant(zero, Type::field()) + self.dfg.make_constant(zero, Type::Numeric(*numeric_type)) } Type::Array(element_types, len) => { let mut array = im::Vector::new(); @@ -260,4 +289,157 @@ impl<'a> ValueMerger<'a> { } } } + + fn try_merge_only_changed_indices( + &mut self, + then_condition: ValueId, + else_condition: ValueId, + then_value: ValueId, + else_value: ValueId, + array_length: usize, + ) -> Option { + let mut found = false; + let current_condition = self.current_condition?; + + let mut current_then = then_value; + let mut current_else = else_value; + + // Arbitrarily limit this to looking at at most 10 past ArraySet operations. + // If there are more than that, we assume 2 completely separate arrays are being merged. + let max_iters = 2; + let mut seen_then = Vec::with_capacity(max_iters); + let mut seen_else = Vec::with_capacity(max_iters); + + // We essentially have a tree of ArraySets and want to find a common + // ancestor if it exists, alone with the path to it from each starting node. + // This path will be the indices that were changed to create each result array. + for _ in 0..max_iters { + if current_then == else_value { + seen_else.clear(); + found = true; + break; + } + + if current_else == then_value { + seen_then.clear(); + found = true; + break; + } + + if let Some(index) = seen_then.iter().position(|(elem, _, _, _)| *elem == current_else) + { + seen_else.truncate(index); + found = true; + break; + } + + if let Some(index) = seen_else.iter().position(|(elem, _, _, _)| *elem == current_then) + { + seen_then.truncate(index); + found = true; + break; + } + + current_then = self.find_previous_array_set(current_then, &mut seen_then); + current_else = self.find_previous_array_set(current_else, &mut seen_else); + } + + let changed_indices: FxHashSet<_> = seen_then + .into_iter() + .map(|(_, index, typ, condition)| (index, typ, condition)) + .chain(seen_else.into_iter().map(|(_, index, typ, condition)| (index, typ, condition))) + .collect(); + + if !found || changed_indices.len() >= array_length { + return None; + } + + let mut array = then_value; + + for (index, element_type, condition) in changed_indices { + let typevars = Some(vec![element_type.clone()]); + + let instruction = Instruction::EnableSideEffects { condition }; + self.insert_instruction(instruction); + + let mut get_element = |array, typevars| { + let get = Instruction::ArrayGet { array, index }; + self.dfg + .insert_instruction_and_results(get, self.block, typevars, CallStack::new()) + .first() + }; + + let then_element = get_element(then_value, typevars.clone()); + let else_element = get_element(else_value, typevars); + + let value = + self.merge_values(then_condition, else_condition, then_element, else_element); + + array = self.insert_array_set(array, index, value, Some(condition)).first(); + } + + let instruction = Instruction::EnableSideEffects { condition: current_condition }; + self.insert_instruction(instruction); + Some(array) + } + + fn insert_instruction(&mut self, instruction: Instruction) -> InsertInstructionResult { + self.dfg.insert_instruction_and_results(instruction, self.block, None, CallStack::new()) + } + + fn insert_array_set( + &mut self, + array: ValueId, + index: ValueId, + value: ValueId, + condition: Option, + ) -> InsertInstructionResult { + let instruction = Instruction::ArraySet { array, index, value, mutable: false }; + let result = self.dfg.insert_instruction_and_results( + instruction, + self.block, + None, + CallStack::new(), + ); + + if let Some(condition) = condition { + let result_index = if result.len() == 1 { + 0 + } else { + // Slices return (length, slice) + assert_eq!(result.len(), 2); + 1 + }; + + let result_value = result[result_index]; + self.array_set_conditionals.insert(result_value, condition); + } + + result + } + + fn find_previous_array_set( + &self, + result: ValueId, + changed_indices: &mut Vec<(ValueId, ValueId, Type, ValueId)>, + ) -> ValueId { + match &self.dfg[result] { + Value::Instruction { instruction, .. } => match &self.dfg[*instruction] { + Instruction::ArraySet { array, index, value, .. } => { + let condition = + *self.array_set_conditionals.get(&result).unwrap_or_else(|| { + panic!( + "Expected to have conditional for array set {result}\n{:?}", + self.array_set_conditionals + ) + }); + let element_type = self.dfg.type_of_value(*value); + changed_indices.push((result, *index, element_type, condition)); + *array + } + _ => result, + }, + _ => result, + } + } } diff --git a/compiler/noirc_evaluator/src/ssa/opt/inlining.rs b/compiler/noirc_evaluator/src/ssa/opt/inlining.rs index 776f22b2877..e2a7f51d0a0 100644 --- a/compiler/noirc_evaluator/src/ssa/opt/inlining.rs +++ b/compiler/noirc_evaluator/src/ssa/opt/inlining.rs @@ -4,6 +4,7 @@ //! be a single function remaining when the pass finishes. use std::collections::{BTreeSet, HashSet}; +use acvm::acir::AcirField; use iter_extended::{btree_map, vecmap}; use crate::ssa::{ @@ -26,7 +27,7 @@ const RECURSION_LIMIT: u32 = 1000; impl Ssa { /// Inline all functions within the IR. /// - /// In the case of recursive functions, this will attempt + /// In the case of recursive Acir functions, this will attempt /// to recursively inline until the RECURSION_LIMIT is reached. /// /// Functions are recursively inlined into main until either we finish @@ -36,13 +37,37 @@ impl Ssa { /// changes. This is because if the function's id later becomes known by a later /// pass, we would need to re-run all of inlining anyway to inline it, so we might /// as well save the work for later instead of performing it twice. + /// + /// There are some attributes that allow inlining a function at a different step of codegen. + /// Currently this is just `InlineType::NoPredicates` for which we have a flag indicating + /// whether treating that inline functions. The default is to treat these functions as entry points. + /// + /// This step should run after runtime separation, since it relies on the runtime of the called functions being final. #[tracing::instrument(level = "trace", skip(self))] - pub(crate) fn inline_functions(mut self) -> Ssa { - self.functions = btree_map(get_entry_point_functions(&self), |entry_point| { - let new_function = InlineContext::new(&self, entry_point).inline_all(&self); - (entry_point, new_function) - }); + pub(crate) fn inline_functions(self) -> Ssa { + Self::inline_functions_inner(self, true) + } + // Run the inlining pass where functions marked with `InlineType::NoPredicates` as not entry points + pub(crate) fn inline_functions_with_no_predicates(self) -> Ssa { + Self::inline_functions_inner(self, false) + } + + fn inline_functions_inner(mut self, no_predicates_is_entry_point: bool) -> Ssa { + let recursive_functions = find_all_recursive_functions(&self); + self.functions = btree_map( + get_functions_to_inline_into(&self, no_predicates_is_entry_point), + |entry_point| { + let new_function = InlineContext::new( + &self, + entry_point, + no_predicates_is_entry_point, + recursive_functions.clone(), + ) + .inline_all(&self); + (entry_point, new_function) + }, + ); self } } @@ -60,6 +85,10 @@ struct InlineContext { // The FunctionId of the entry point function we're inlining into in the old, unmodified Ssa. entry_point: FunctionId, + + no_predicates_is_entry_point: bool, + // We keep track of the recursive functions in the SSA to avoid inlining them in a brillig context. + recursive_functions: BTreeSet, } /// The per-function inlining context contains information that is only valid for one function. @@ -93,18 +122,101 @@ struct PerFunctionContext<'function> { inlining_entry: bool, } -/// The entry point functions are each function we should inline into - and each function that -/// should be left in the final program. This is usually just `main` but also includes any -/// brillig functions used. -fn get_entry_point_functions(ssa: &Ssa) -> BTreeSet { - let functions = ssa.functions.iter(); - let mut entry_points = functions - .filter(|(_, function)| function.runtime() == RuntimeType::Brillig) - .map(|(id, _)| *id) - .collect::>(); - - entry_points.insert(ssa.main_id); - entry_points +/// Utility function to find out the direct calls of a function. +fn called_functions(func: &Function) -> BTreeSet { + let mut called_function_ids = BTreeSet::default(); + for block_id in func.reachable_blocks() { + for instruction_id in func.dfg[block_id].instructions() { + let Instruction::Call { func: called_value_id, .. } = &func.dfg[*instruction_id] else { + continue; + }; + + if let Value::Function(function_id) = func.dfg[*called_value_id] { + called_function_ids.insert(function_id); + } + } + } + + called_function_ids +} + +// Recursively explore the SSA to find the functions that end up calling themselves +fn find_recursive_functions( + ssa: &Ssa, + current_function: FunctionId, + mut explored_functions: im::HashSet, + recursive_functions: &mut BTreeSet, +) { + if explored_functions.contains(¤t_function) { + recursive_functions.insert(current_function); + return; + } + + let called_functions = called_functions(&ssa.functions[¤t_function]); + + explored_functions.insert(current_function); + + for called_function in called_functions { + find_recursive_functions( + ssa, + called_function, + explored_functions.clone(), + recursive_functions, + ); + } +} + +fn find_all_recursive_functions(ssa: &Ssa) -> BTreeSet { + let mut recursive_functions = BTreeSet::default(); + find_recursive_functions(ssa, ssa.main_id, im::HashSet::default(), &mut recursive_functions); + recursive_functions +} + +/// The functions we should inline into (and that should be left in the final program) are: +/// - main +/// - Any Brillig function called from Acir +/// - Any Brillig recursive function (Acir recursive functions will be inlined into the main function) +/// - Any Acir functions with a [fold inline type][InlineType::Fold], +fn get_functions_to_inline_into( + ssa: &Ssa, + no_predicates_is_entry_point: bool, +) -> BTreeSet { + let mut brillig_entry_points = BTreeSet::default(); + let mut acir_entry_points = BTreeSet::default(); + + for (func_id, function) in ssa.functions.iter() { + if function.runtime() == RuntimeType::Brillig { + continue; + } + + // If we have not already finished the flattening pass, functions marked + // to not have predicates should be marked as entry points. + let no_predicates_is_entry_point = + no_predicates_is_entry_point && function.is_no_predicates(); + if function.runtime().is_entry_point() || no_predicates_is_entry_point { + acir_entry_points.insert(*func_id); + } + + for called_function_id in called_functions(function) { + if ssa.functions[&called_function_id].runtime() == RuntimeType::Brillig { + brillig_entry_points.insert(called_function_id); + } + } + } + + let brillig_recursive_functions: BTreeSet<_> = find_all_recursive_functions(ssa) + .into_iter() + .filter(|recursive_function_id| { + let function = &ssa.functions[&recursive_function_id]; + function.runtime() == RuntimeType::Brillig + }) + .collect(); + + std::iter::once(ssa.main_id) + .chain(acir_entry_points) + .chain(brillig_entry_points) + .chain(brillig_recursive_functions) + .collect() } impl InlineContext { @@ -113,10 +225,23 @@ impl InlineContext { /// The function being inlined into will always be the main function, although it is /// actually a copy that is created in case the original main is still needed from a function /// that could not be inlined calling it. - fn new(ssa: &Ssa, entry_point: FunctionId) -> InlineContext { + fn new( + ssa: &Ssa, + entry_point: FunctionId, + no_predicates_is_entry_point: bool, + recursive_functions: BTreeSet, + ) -> InlineContext { let source = &ssa.functions[&entry_point]; - let builder = FunctionBuilder::new(source.name().to_owned(), entry_point, source.runtime()); - Self { builder, recursion_level: 0, entry_point, call_stack: CallStack::new() } + let mut builder = FunctionBuilder::new(source.name().to_owned(), entry_point); + builder.set_runtime(source.runtime()); + Self { + builder, + recursion_level: 0, + entry_point, + call_stack: CallStack::new(), + no_predicates_is_entry_point, + recursive_functions, + } } /// Start inlining the entry point function and all functions reachable from it. @@ -349,10 +474,13 @@ impl<'function> PerFunctionContext<'function> { for id in block.instructions() { match &self.source_function.dfg[*id] { Instruction::Call { func, arguments } => match self.get_function(*func) { - Some(function) => match ssa.functions[&function].runtime() { - RuntimeType::Acir => self.inline_function(ssa, *id, function, arguments), - RuntimeType::Brillig => self.push_instruction(*id), - }, + Some(func_id) => { + if self.should_inline_call(ssa, func_id) { + self.inline_function(ssa, *id, func_id, arguments); + } else { + self.push_instruction(*id); + } + } None => self.push_instruction(*id), }, _ => self.push_instruction(*id), @@ -360,6 +488,24 @@ impl<'function> PerFunctionContext<'function> { } } + fn should_inline_call(&self, ssa: &Ssa, called_func_id: FunctionId) -> bool { + let function = &ssa.functions[&called_func_id]; + + if let RuntimeType::Acir(inline_type) = function.runtime() { + // If the called function is acir, we inline if it's not an entry point + + // If we have not already finished the flattening pass, functions marked + // to not have predicates should be marked as entry points. + let no_predicates_is_entry_point = + self.context.no_predicates_is_entry_point && function.is_no_predicates(); + !inline_type.is_entry_point() && !no_predicates_is_entry_point + } else { + // If the called function is brillig, we inline only if it's into brillig and the function is not recursive + ssa.functions[&self.context.entry_point].runtime() == RuntimeType::Brillig + && !self.context.recursive_functions.contains(&called_func_id) + } + } + /// Inline a function call and remember the inlined return values in the values map fn inline_function( &mut self, @@ -487,6 +633,13 @@ impl<'function> PerFunctionContext<'function> { } TerminatorInstruction::Return { return_values, call_stack } => { let return_values = vecmap(return_values, |value| self.translate_value(*value)); + + // Note that `translate_block` would take us back to the point at which the + // inlining of this source block began. Since additional blocks may have been + // inlined since, we are interested in the block representing the current program + // point, obtained via `current_block`. + let block_id = self.context.builder.current_block(); + if self.inlining_entry { let mut new_call_stack = self.context.call_stack.clone(); new_call_stack.append(call_stack.clone()); @@ -495,11 +648,7 @@ impl<'function> PerFunctionContext<'function> { .set_call_stack(new_call_stack) .terminate_with_return(return_values.clone()); } - // Note that `translate_block` would take us back to the point at which the - // inlining of this source block began. Since additional blocks may have been - // inlined since, we are interested in the block representing the current program - // point, obtained via `current_block`. - let block_id = self.context.builder.current_block(); + Some((block_id, return_values)) } } @@ -508,13 +657,13 @@ impl<'function> PerFunctionContext<'function> { #[cfg(test)] mod test { - use acvm::FieldElement; + use acvm::{acir::AcirField, FieldElement}; + use noirc_frontend::monomorphization::ast::InlineType; use crate::ssa::{ function_builder::FunctionBuilder, ir::{ basic_block::BasicBlockId, - function::RuntimeType, instruction::{BinaryOp, Intrinsic, TerminatorInstruction}, map::Id, types::Type, @@ -533,14 +682,14 @@ mod test { // return 72 // } let foo_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("foo".into(), foo_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("foo".into(), foo_id); let bar_id = Id::test_new(1); let bar = builder.import_function(bar_id); let results = builder.insert_call(bar, Vec::new(), vec![Type::field()]).to_vec(); builder.terminate_with_return(results); - builder.new_function("bar".into(), bar_id); + builder.new_function("bar".into(), bar_id, InlineType::default()); let expected_return = 72u128; let seventy_two = builder.field_constant(expected_return); builder.terminate_with_return(vec![seventy_two]); @@ -582,7 +731,7 @@ mod test { let id2_id = Id::test_new(3); // Compiling main - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("main".into(), main_id); let main_v0 = builder.add_parameter(Type::field()); let main_f1 = builder.import_function(square_id); @@ -595,18 +744,18 @@ mod test { builder.terminate_with_return(vec![main_v16]); // Compiling square f1 - builder.new_function("square".into(), square_id); + builder.new_function("square".into(), square_id, InlineType::default()); let square_v0 = builder.add_parameter(Type::field()); let square_v2 = builder.insert_binary(square_v0, BinaryOp::Mul, square_v0); builder.terminate_with_return(vec![square_v2]); // Compiling id1 f2 - builder.new_function("id1".into(), id1_id); + builder.new_function("id1".into(), id1_id, InlineType::default()); let id1_v0 = builder.add_parameter(Type::Function); builder.terminate_with_return(vec![id1_v0]); // Compiling id2 f3 - builder.new_function("id2".into(), id2_id); + builder.new_function("id2".into(), id2_id, InlineType::default()); let id2_v0 = builder.add_parameter(Type::Function); builder.terminate_with_return(vec![id2_v0]); @@ -638,7 +787,7 @@ mod test { // return v4 // } let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("main".into(), main_id); let factorial_id = Id::test_new(1); let factorial = builder.import_function(factorial_id); @@ -647,7 +796,7 @@ mod test { let results = builder.insert_call(factorial, vec![five], vec![Type::field()]).to_vec(); builder.terminate_with_return(results); - builder.new_function("factorial".into(), factorial_id); + builder.new_function("factorial".into(), factorial_id, InlineType::default()); let b1 = builder.insert_block(); let b2 = builder.insert_block(); @@ -738,7 +887,7 @@ mod test { // jmp b3(Field 2) // } let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("main".into(), main_id); let main_cond = builder.add_parameter(Type::bool()); let inner1_id = Id::test_new(1); @@ -748,14 +897,14 @@ mod test { builder.insert_call(assert_constant, vec![main_v2], vec![]); builder.terminate_with_return(vec![]); - builder.new_function("inner1".into(), inner1_id); + builder.new_function("inner1".into(), inner1_id, InlineType::default()); let inner1_cond = builder.add_parameter(Type::bool()); let inner2_id = Id::test_new(2); let inner2 = builder.import_function(inner2_id); let inner1_v2 = builder.insert_call(inner2, vec![inner1_cond], vec![Type::field()])[0]; builder.terminate_with_return(vec![inner1_v2]); - builder.new_function("inner2".into(), inner2_id); + builder.new_function("inner2".into(), inner2_id, InlineType::default()); let inner2_cond = builder.add_parameter(Type::bool()); let then_block = builder.insert_block(); let else_block = builder.insert_block(); diff --git a/compiler/noirc_evaluator/src/ssa/opt/mem2reg.rs b/compiler/noirc_evaluator/src/ssa/opt/mem2reg.rs index 0a49ca4ecca..5b1139e5b9c 100644 --- a/compiler/noirc_evaluator/src/ssa/opt/mem2reg.rs +++ b/compiler/noirc_evaluator/src/ssa/opt/mem2reg.rs @@ -406,7 +406,7 @@ impl<'f> PerFunctionContext<'f> { mod tests { use std::rc::Rc; - use acvm::FieldElement; + use acvm::{acir::AcirField, FieldElement}; use im::vector; use crate::ssa::{ @@ -414,7 +414,6 @@ mod tests { ir::{ basic_block::BasicBlockId, dfg::DataFlowGraph, - function::RuntimeType, instruction::{BinaryOp, Instruction, Intrinsic, TerminatorInstruction}, map::Id, types::Type, @@ -433,7 +432,7 @@ mod tests { // } let func_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("func".into(), func_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("func".into(), func_id); let v0 = builder.insert_allocate(Type::Array(Rc::new(vec![Type::field()]), 2)); let one = builder.field_constant(FieldElement::one()); let two = builder.field_constant(FieldElement::one()); @@ -474,7 +473,7 @@ mod tests { // } let func_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("func".into(), func_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("func".into(), func_id); let v0 = builder.insert_allocate(Type::field()); let one = builder.field_constant(FieldElement::one()); builder.insert_store(v0, one); @@ -508,7 +507,7 @@ mod tests { // } let func_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("func".into(), func_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("func".into(), func_id); let v0 = builder.insert_allocate(Type::field()); let const_one = builder.field_constant(FieldElement::one()); builder.insert_store(v0, const_one); @@ -567,7 +566,7 @@ mod tests { // return v2, v3, v4 // } let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("main".into(), main_id); let v0 = builder.insert_allocate(Type::field()); @@ -647,7 +646,7 @@ mod tests { // return // } let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("main".into(), main_id); let v0 = builder.insert_allocate(Type::field()); diff --git a/compiler/noirc_evaluator/src/ssa/opt/mod.rs b/compiler/noirc_evaluator/src/ssa/opt/mod.rs index a315695f7db..4e5fa262696 100644 --- a/compiler/noirc_evaluator/src/ssa/opt/mod.rs +++ b/compiler/noirc_evaluator/src/ssa/opt/mod.rs @@ -3,7 +3,8 @@ //! Each pass is generally expected to mutate the SSA IR into a gradually //! simpler form until the IR only has a single function remaining with 1 block within it. //! Generally, these passes are also expected to minimize the final amount of instructions. -mod array_use; +mod array_set; +mod as_slice_length; mod assert_constant; mod bubble_up_constrains; mod constant_folding; @@ -12,6 +13,11 @@ mod die; pub(crate) mod flatten_cfg; mod inlining; mod mem2reg; +mod rc; mod remove_bit_shifts; +mod remove_enable_side_effects; +mod remove_if_else; +mod resolve_is_unconstrained; +mod runtime_separation; mod simplify_cfg; mod unrolling; diff --git a/compiler/noirc_evaluator/src/ssa/opt/rc.rs b/compiler/noirc_evaluator/src/ssa/opt/rc.rs new file mode 100644 index 00000000000..1561547e32e --- /dev/null +++ b/compiler/noirc_evaluator/src/ssa/opt/rc.rs @@ -0,0 +1,328 @@ +use std::collections::{HashMap, HashSet}; + +use crate::ssa::{ + ir::{ + basic_block::BasicBlockId, + function::Function, + instruction::{Instruction, InstructionId, TerminatorInstruction}, + types::Type, + value::ValueId, + }, + ssa_gen::Ssa, +}; + +impl Ssa { + /// This pass removes `inc_rc` and `dec_rc` instructions + /// as long as there are no `array_set` instructions to an array + /// of the same type in between. + /// + /// Note that this pass is very conservative since the array_set + /// instruction does not need to be to the same array. This is because + /// the given array may alias another array (e.g. function parameters or + /// a `load`ed array from a reference). + #[tracing::instrument(level = "trace", skip(self))] + pub(crate) fn remove_paired_rc(mut self) -> Ssa { + for function in self.functions.values_mut() { + remove_paired_rc(function); + } + self + } +} + +#[derive(Default)] +struct Context { + // All inc_rc instructions encountered without a corresponding dec_rc. + // These are only searched for in the first block of a function. + // + // The type of the array being operated on is recorded. + // If an array_set to that array type is encountered, that is also recorded. + inc_rcs: HashMap>, +} + +struct IncRc { + id: InstructionId, + array: ValueId, + possibly_mutated: bool, +} + +/// This function is very simplistic for now. It takes advantage of the fact that dec_rc +/// instructions are currently issued only at the end of a function for parameters and will +/// only check the first and last block for inc & dec rc instructions to be removed. The rest +/// of the function is still checked for array_set instructions. +/// +/// This restriction lets this function largely ignore merging intermediate results from other +/// blocks and handling loops. +fn remove_paired_rc(function: &mut Function) { + // `dec_rc` is only issued for parameters currently so we can speed things + // up a bit by skipping any functions without them. + if !contains_array_parameter(function) { + return; + } + + let mut context = Context::default(); + + context.find_rcs_in_entry_block(function); + context.scan_for_array_sets(function); + let to_remove = context.find_rcs_to_remove(function); + remove_instructions(to_remove, function); +} + +fn contains_array_parameter(function: &mut Function) -> bool { + let mut parameters = function.parameters().iter(); + parameters.any(|parameter| function.dfg.type_of_value(*parameter).contains_an_array()) +} + +impl Context { + fn find_rcs_in_entry_block(&mut self, function: &Function) { + let entry = function.entry_block(); + + for instruction in function.dfg[entry].instructions() { + if let Instruction::IncrementRc { value } = &function.dfg[*instruction] { + let typ = function.dfg.type_of_value(*value); + + // We assume arrays aren't mutated until we find an array_set + let inc_rc = IncRc { id: *instruction, array: *value, possibly_mutated: false }; + self.inc_rcs.entry(typ).or_default().push(inc_rc); + } + } + } + + /// Find each array_set instruction in the function and mark any arrays used + /// by the inc_rc instructions as possibly mutated if they're the same type. + fn scan_for_array_sets(&mut self, function: &Function) { + for block in function.reachable_blocks() { + for instruction in function.dfg[block].instructions() { + if let Instruction::ArraySet { array, .. } = function.dfg[*instruction] { + let typ = function.dfg.type_of_value(array); + if let Some(inc_rcs) = self.inc_rcs.get_mut(&typ) { + for inc_rc in inc_rcs { + inc_rc.possibly_mutated = true; + } + } + } + } + } + } + + /// Find each dec_rc instruction and if the most recent inc_rc instruction for the same value + /// is not possibly mutated, then we can remove them both. Returns each such pair. + fn find_rcs_to_remove(&mut self, function: &Function) -> HashSet { + let last_block = Self::find_last_block(function); + let mut to_remove = HashSet::new(); + + for instruction in function.dfg[last_block].instructions() { + if let Instruction::DecrementRc { value } = &function.dfg[*instruction] { + if let Some(inc_rc) = self.pop_rc_for(*value, function) { + if !inc_rc.possibly_mutated { + to_remove.insert(inc_rc.id); + to_remove.insert(*instruction); + } + } + } + } + + to_remove + } + + /// Finds the block of the function with the Return instruction + fn find_last_block(function: &Function) -> BasicBlockId { + for block in function.reachable_blocks() { + if matches!( + function.dfg[block].terminator(), + Some(TerminatorInstruction::Return { .. }) + ) { + return block; + } + } + + unreachable!("SSA Function {} has no reachable return instruction!", function.id()) + } + + /// Finds and pops the IncRc for the given array value if possible. + fn pop_rc_for(&mut self, value: ValueId, function: &Function) -> Option { + let typ = function.dfg.type_of_value(value); + + let rcs = self.inc_rcs.get_mut(&typ)?; + let position = rcs.iter().position(|inc_rc| inc_rc.array == value)?; + + Some(rcs.remove(position)) + } +} + +fn remove_instructions(to_remove: HashSet, function: &mut Function) { + if !to_remove.is_empty() { + for block in function.reachable_blocks() { + function.dfg[block] + .instructions_mut() + .retain(|instruction| !to_remove.contains(instruction)); + } + } +} + +#[cfg(test)] +mod test { + use std::rc::Rc; + + use crate::ssa::{ + function_builder::FunctionBuilder, + ir::{ + basic_block::BasicBlockId, dfg::DataFlowGraph, function::RuntimeType, + instruction::Instruction, map::Id, types::Type, + }, + }; + + fn count_inc_rcs(block: BasicBlockId, dfg: &DataFlowGraph) -> usize { + dfg[block] + .instructions() + .iter() + .filter(|instruction_id| { + matches!(dfg[**instruction_id], Instruction::IncrementRc { .. }) + }) + .count() + } + + fn count_dec_rcs(block: BasicBlockId, dfg: &DataFlowGraph) -> usize { + dfg[block] + .instructions() + .iter() + .filter(|instruction_id| { + matches!(dfg[**instruction_id], Instruction::DecrementRc { .. }) + }) + .count() + } + + #[test] + fn single_block_fn_return_array() { + // This is the output for the program with a function: + // unconstrained fn foo(x: [Field; 2]) -> [[Field; 2]; 1] { + // [array] + // } + // + // fn foo { + // b0(v0: [Field; 2]): + // inc_rc v0 + // inc_rc v0 + // dec_rc v0 + // return [v0] + // } + let main_id = Id::test_new(0); + let mut builder = FunctionBuilder::new("foo".into(), main_id); + builder.set_runtime(RuntimeType::Brillig); + + let inner_array_type = Type::Array(Rc::new(vec![Type::field()]), 2); + let v0 = builder.add_parameter(inner_array_type.clone()); + + builder.insert_inc_rc(v0); + builder.insert_inc_rc(v0); + builder.insert_dec_rc(v0); + + let outer_array_type = Type::Array(Rc::new(vec![inner_array_type]), 1); + let array = builder.array_constant(vec![v0].into(), outer_array_type); + builder.terminate_with_return(vec![array]); + + let ssa = builder.finish().remove_paired_rc(); + let main = ssa.main(); + let entry = main.entry_block(); + + assert_eq!(count_inc_rcs(entry, &main.dfg), 1); + assert_eq!(count_dec_rcs(entry, &main.dfg), 0); + } + + #[test] + fn single_block_mutation() { + // fn mutator(mut array: [Field; 2]) { + // array[0] = 5; + // } + // + // fn mutator { + // b0(v0: [Field; 2]): + // v1 = allocate + // store v0 at v1 + // inc_rc v0 + // v2 = load v1 + // v7 = array_set v2, index u64 0, value Field 5 + // store v7 at v1 + // dec_rc v0 + // return + // } + let main_id = Id::test_new(0); + let mut builder = FunctionBuilder::new("mutator".into(), main_id); + + let array_type = Type::Array(Rc::new(vec![Type::field()]), 2); + let v0 = builder.add_parameter(array_type.clone()); + + let v1 = builder.insert_allocate(array_type.clone()); + builder.insert_store(v1, v0); + builder.insert_inc_rc(v0); + let v2 = builder.insert_load(v1, array_type); + + let zero = builder.numeric_constant(0u128, Type::unsigned(64)); + let five = builder.field_constant(5u128); + let v7 = builder.insert_array_set(v2, zero, five); + + builder.insert_store(v1, v7); + builder.insert_dec_rc(v0); + builder.terminate_with_return(vec![]); + + let ssa = builder.finish().remove_paired_rc(); + let main = ssa.main(); + let entry = main.entry_block(); + + // No changes, the array is possibly mutated + assert_eq!(count_inc_rcs(entry, &main.dfg), 1); + assert_eq!(count_dec_rcs(entry, &main.dfg), 1); + } + + // Similar to single_block_mutation but for a function which + // uses a mutable reference parameter. + #[test] + fn single_block_mutation_through_reference() { + // fn mutator2(array: &mut [Field; 2]) { + // array[0] = 5; + // } + // + // fn mutator2 { + // b0(v0: &mut [Field; 2]): + // v1 = load v0 + // inc_rc v1 + // store v1 at v0 + // v2 = load v0 + // v7 = array_set v2, index u64 0, value Field 5 + // store v7 at v0 + // v8 = load v0 + // dec_rc v8 + // store v8 at v0 + // return + // } + let main_id = Id::test_new(0); + let mut builder = FunctionBuilder::new("mutator2".into(), main_id); + + let array_type = Type::Array(Rc::new(vec![Type::field()]), 2); + let reference_type = Type::Reference(Rc::new(array_type.clone())); + + let v0 = builder.add_parameter(reference_type); + + let v1 = builder.insert_load(v0, array_type.clone()); + builder.insert_inc_rc(v1); + builder.insert_store(v0, v1); + + let v2 = builder.insert_load(v1, array_type.clone()); + let zero = builder.numeric_constant(0u128, Type::unsigned(64)); + let five = builder.field_constant(5u128); + let v7 = builder.insert_array_set(v2, zero, five); + + builder.insert_store(v0, v7); + let v8 = builder.insert_load(v0, array_type); + builder.insert_dec_rc(v8); + builder.insert_store(v0, v8); + builder.terminate_with_return(vec![]); + + let ssa = builder.finish().remove_paired_rc(); + let main = ssa.main(); + let entry = main.entry_block(); + + // No changes, the array is possibly mutated + assert_eq!(count_inc_rcs(entry, &main.dfg), 1); + assert_eq!(count_dec_rcs(entry, &main.dfg), 1); + } +} diff --git a/compiler/noirc_evaluator/src/ssa/opt/remove_bit_shifts.rs b/compiler/noirc_evaluator/src/ssa/opt/remove_bit_shifts.rs index a71a42d5757..628e1bd7410 100644 --- a/compiler/noirc_evaluator/src/ssa/opt/remove_bit_shifts.rs +++ b/compiler/noirc_evaluator/src/ssa/opt/remove_bit_shifts.rs @@ -1,6 +1,6 @@ use std::{borrow::Cow, rc::Rc}; -use acvm::FieldElement; +use acvm::{acir::AcirField, FieldElement}; use crate::ssa::{ ir::{ @@ -20,7 +20,9 @@ impl Ssa { /// See [`constant_folding`][self] module for more information. #[tracing::instrument(level = "trace", skip(self))] pub(crate) fn remove_bit_shifts(mut self) -> Ssa { - remove_bit_shifts(self.main_mut()); + for function in self.functions.values_mut() { + remove_bit_shifts(function); + } self } } @@ -95,7 +97,7 @@ impl Context<'_> { let typ = self.function.dfg.type_of_value(lhs); let (max_bit, pow) = if let Some(rhs_constant) = self.function.dfg.get_numeric_constant(rhs) { - // Happy case is that we know precisely by how many bits the the integer will + // Happy case is that we know precisely by how many bits the integer will // increase: lhs_bit_size + rhs let bit_shift_size = rhs_constant.to_u128() as u32; @@ -107,7 +109,7 @@ impl Context<'_> { return InsertInstructionResult::SimplifiedTo(zero).first(); } } - let pow = self.numeric_constant(FieldElement::from(rhs_bit_size_pow_2), typ); + let pow = self.numeric_constant(FieldElement::from(rhs_bit_size_pow_2), typ.clone()); let max_lhs_bits = self.function.dfg.get_value_max_num_bits(lhs); @@ -115,21 +117,24 @@ impl Context<'_> { } 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()); + self.numeric_constant(FieldElement::from(bit_size as u128), Type::unsigned(8)); let overflow = self.insert_binary(rhs, BinaryOp::Lt, bit_size_var); let predicate = self.insert_cast(overflow, typ.clone()); // we can safely cast to unsigned because overflow_checks prevent bit-shift with a negative value let rhs_unsigned = self.insert_cast(rhs, Type::unsigned(bit_size)); let pow = self.pow(base, rhs_unsigned); - let pow = self.insert_cast(pow, typ); + let pow = self.insert_cast(pow, typ.clone()); (FieldElement::max_num_bits(), self.insert_binary(predicate, BinaryOp::Mul, pow)) }; if max_bit <= bit_size { self.insert_binary(lhs, BinaryOp::Mul, pow) } else { - let result = self.insert_binary(lhs, BinaryOp::Mul, pow); - self.insert_truncate(result, bit_size, max_bit) + let lhs_field = self.insert_cast(lhs, Type::field()); + let pow_field = self.insert_cast(pow, Type::field()); + let result = self.insert_binary(lhs_field, BinaryOp::Mul, pow_field); + let result = self.insert_truncate(result, bit_size, max_bit); + self.insert_cast(result, typ) } } diff --git a/compiler/noirc_evaluator/src/ssa/opt/remove_enable_side_effects.rs b/compiler/noirc_evaluator/src/ssa/opt/remove_enable_side_effects.rs new file mode 100644 index 00000000000..6db76996747 --- /dev/null +++ b/compiler/noirc_evaluator/src/ssa/opt/remove_enable_side_effects.rs @@ -0,0 +1,172 @@ +//! The goal of the "remove enable side effects" optimization pass is to delay any [Instruction::EnableSideEffects] +//! instructions such that they cover the minimum number of instructions possible. +//! +//! The pass works as follows: +//! - Insert instructions until an [Instruction::EnableSideEffects] is encountered, save this [InstructionId]. +//! - Continue inserting instructions until either +//! - Another [Instruction::EnableSideEffects] is encountered, if so then drop the previous [InstructionId] in favour +//! of this one. +//! - An [Instruction] with side-effects is encountered, if so then insert the currently saved [Instruction::EnableSideEffects] +//! before the [Instruction]. Continue inserting instructions until the next [Instruction::EnableSideEffects] is encountered. +use std::collections::HashSet; + +use acvm::{acir::AcirField, FieldElement}; + +use crate::ssa::{ + ir::{ + basic_block::BasicBlockId, + dfg::DataFlowGraph, + function::Function, + instruction::{BinaryOp, Instruction, Intrinsic}, + value::Value, + }, + ssa_gen::Ssa, +}; + +impl Ssa { + /// See [`remove_enable_side_effects`][self] module for more information. + #[tracing::instrument(level = "trace", skip(self))] + pub(crate) fn remove_enable_side_effects(mut self) -> Ssa { + for function in self.functions.values_mut() { + remove_enable_side_effects(function); + } + self + } +} + +fn remove_enable_side_effects(function: &mut Function) { + let mut context = Context::default(); + context.block_queue.push(function.entry_block()); + + while let Some(block) = context.block_queue.pop() { + if context.visited_blocks.contains(&block) { + continue; + } + + context.visited_blocks.insert(block); + context.remove_enable_side_effects_in_block(function, block); + } +} + +#[derive(Default)] +struct Context { + visited_blocks: HashSet, + block_queue: Vec, +} + +impl Context { + fn remove_enable_side_effects_in_block( + &mut self, + function: &mut Function, + block: BasicBlockId, + ) { + let instructions = function.dfg[block].take_instructions(); + + let mut last_side_effects_enabled_instruction = None; + + let mut new_instructions = Vec::with_capacity(instructions.len()); + for instruction_id in instructions { + let instruction = &function.dfg[instruction_id]; + + // If we run into another `Instruction::EnableSideEffects` before encountering any + // instructions with side effects then we can drop the instruction we're holding and + // continue with the new `Instruction::EnableSideEffects`. + if let Instruction::EnableSideEffects { condition } = instruction { + // If we're seeing an `enable_side_effects u1 1` then we want to insert it immediately. + // This is because we want to maximize the effect it will have. + if function + .dfg + .get_numeric_constant(*condition) + .map_or(false, |condition| condition.is_one()) + { + new_instructions.push(instruction_id); + last_side_effects_enabled_instruction = None; + continue; + } + + last_side_effects_enabled_instruction = Some(instruction_id); + continue; + } + + // If we hit an instruction which is affected by the side effects var then we must insert the + // `Instruction::EnableSideEffects` before we insert this new instruction. + if Self::responds_to_side_effects_var(&function.dfg, instruction) { + if let Some(enable_side_effects_instruction_id) = + last_side_effects_enabled_instruction.take() + { + new_instructions.push(enable_side_effects_instruction_id); + } + } + new_instructions.push(instruction_id); + } + + *function.dfg[block].instructions_mut() = new_instructions; + + self.block_queue.extend(function.dfg[block].successors()); + } + + fn responds_to_side_effects_var(dfg: &DataFlowGraph, instruction: &Instruction) -> bool { + use Instruction::*; + match instruction { + Binary(binary) => match binary.operator { + BinaryOp::Add | BinaryOp::Sub | BinaryOp::Mul => { + dfg.type_of_value(binary.lhs).is_unsigned() + } + BinaryOp::Div | BinaryOp::Mod => { + if let Some(rhs) = dfg.get_numeric_constant(binary.rhs) { + rhs == FieldElement::zero() + } else { + true + } + } + _ => false, + }, + + Cast(_, _) + | Not(_) + | Truncate { .. } + | Constrain(..) + | RangeCheck { .. } + | IfElse { .. } + | IncrementRc { .. } + | DecrementRc { .. } => false, + + EnableSideEffects { .. } + | ArrayGet { .. } + | ArraySet { .. } + | Allocate + | Store { .. } + | Load { .. } => true, + + // Some `Intrinsic`s have side effects so we must check what kind of `Call` this is. + Call { func, .. } => match dfg[*func] { + Value::Intrinsic(intrinsic) => match intrinsic { + Intrinsic::SlicePushBack + | Intrinsic::SlicePushFront + | Intrinsic::SlicePopBack + | Intrinsic::SlicePopFront + | Intrinsic::SliceInsert + | Intrinsic::SliceRemove => true, + + Intrinsic::ArrayLen + | Intrinsic::AssertConstant + | Intrinsic::ApplyRangeConstraint + | Intrinsic::StrAsBytes + | Intrinsic::ToBits(_) + | Intrinsic::ToRadix(_) + | Intrinsic::BlackBox(_) + | Intrinsic::FromField + | Intrinsic::AsField + | Intrinsic::AsSlice + | Intrinsic::AsWitness + | Intrinsic::IsUnconstrained => false, + }, + + // We must assume that functions contain a side effect as we cannot inspect more deeply. + Value::Function(_) => true, + + _ => false, + }, + } + } +} diff --git a/compiler/noirc_evaluator/src/ssa/opt/remove_if_else.rs b/compiler/noirc_evaluator/src/ssa/opt/remove_if_else.rs new file mode 100644 index 00000000000..6ca7eb74e9d --- /dev/null +++ b/compiler/noirc_evaluator/src/ssa/opt/remove_if_else.rs @@ -0,0 +1,238 @@ +use std::collections::hash_map::Entry; + +use acvm::{acir::AcirField, FieldElement}; +use fxhash::FxHashMap as HashMap; + +use crate::ssa::ir::value::ValueId; +use crate::ssa::{ + ir::{ + dfg::DataFlowGraph, + function::Function, + instruction::{Instruction, Intrinsic}, + types::Type, + value::Value, + }, + opt::flatten_cfg::value_merger::ValueMerger, + Ssa, +}; + +impl Ssa { + /// This pass removes `inc_rc` and `dec_rc` instructions + /// as long as there are no `array_set` instructions to an array + /// of the same type in between. + /// + /// Note that this pass is very conservative since the array_set + /// instruction does not need to be to the same array. This is because + /// the given array may alias another array (e.g. function parameters or + /// a `load`ed array from a reference). + #[tracing::instrument(level = "trace", skip(self))] + pub(crate) fn remove_if_else(mut self) -> Ssa { + for function in self.functions.values_mut() { + // This should match the check in flatten_cfg + if let crate::ssa::ir::function::RuntimeType::Brillig = function.runtime() { + continue; + } + + Context::default().remove_if_else(function); + } + self + } +} + +#[derive(Default)] +struct Context { + slice_sizes: HashMap, + + // Maps array_set result -> element that was overwritten by that instruction. + // Used to undo array_sets while merging values + prev_array_set_elem_values: HashMap, + + // Maps array_set result -> enable_side_effects_if value which was active during it. + array_set_conditionals: HashMap, +} + +impl Context { + fn remove_if_else(&mut self, function: &mut Function) { + let block = function.entry_block(); + let instructions = function.dfg[block].take_instructions(); + let mut current_conditional = function.dfg.make_constant(FieldElement::one(), Type::bool()); + + for instruction in instructions { + match &function.dfg[instruction] { + Instruction::IfElse { then_condition, then_value, else_condition, else_value } => { + let then_condition = *then_condition; + let then_value = *then_value; + let else_condition = *else_condition; + let else_value = *else_value; + + let typ = function.dfg.type_of_value(then_value); + assert!(!matches!(typ, Type::Numeric(_))); + + let mut value_merger = ValueMerger::new( + &mut function.dfg, + block, + &mut self.slice_sizes, + &mut self.array_set_conditionals, + Some(current_conditional), + ); + + let value = value_merger.merge_values( + then_condition, + else_condition, + then_value, + else_value, + ); + + let _typ = function.dfg.type_of_value(value); + let results = function.dfg.instruction_results(instruction); + let result = results[0]; + // let result = match typ { + // Type::Array(..) => results[0], + // Type::Slice(..) => results[1], + // other => unreachable!("IfElse instructions should only have arrays or slices at this point. Found {other:?}"), + // }; + + function.dfg.set_value_from_id(result, value); + self.array_set_conditionals.insert(result, current_conditional); + } + Instruction::Call { func, arguments } => { + if let Value::Intrinsic(intrinsic) = function.dfg[*func] { + let results = function.dfg.instruction_results(instruction); + + match slice_capacity_change(&function.dfg, intrinsic, arguments, results) { + SizeChange::None => (), + SizeChange::SetTo(value, new_capacity) => { + self.slice_sizes.insert(value, new_capacity); + } + SizeChange::Inc { old, new } => { + let old_capacity = self.get_or_find_capacity(&function.dfg, old); + self.slice_sizes.insert(new, old_capacity + 1); + } + SizeChange::Dec { old, new } => { + let old_capacity = self.get_or_find_capacity(&function.dfg, old); + self.slice_sizes.insert(new, old_capacity - 1); + } + } + } + function.dfg[block].instructions_mut().push(instruction); + } + Instruction::ArraySet { array, .. } => { + let results = function.dfg.instruction_results(instruction); + let result = if results.len() == 2 { results[1] } else { results[0] }; + + self.array_set_conditionals.insert(result, current_conditional); + + let old_capacity = self.get_or_find_capacity(&function.dfg, *array); + self.slice_sizes.insert(result, old_capacity); + function.dfg[block].instructions_mut().push(instruction); + } + Instruction::EnableSideEffects { condition } => { + current_conditional = *condition; + function.dfg[block].instructions_mut().push(instruction); + } + _ => { + function.dfg[block].instructions_mut().push(instruction); + } + } + } + } + + fn get_or_find_capacity(&mut self, dfg: &DataFlowGraph, value: ValueId) -> usize { + match self.slice_sizes.entry(value) { + Entry::Occupied(entry) => return *entry.get(), + Entry::Vacant(entry) => { + if let Some((array, typ)) = dfg.get_array_constant(value) { + let length = array.len() / typ.element_types().len(); + return *entry.insert(length); + } + + if let Type::Array(_, length) = dfg.type_of_value(value) { + return *entry.insert(length); + } + } + } + + let dbg_value = &dfg[value]; + unreachable!("No size for slice {value} = {dbg_value:?}") + } +} + +enum SizeChange { + None, + SetTo(ValueId, usize), + + // These two variants store the old and new slice ids + // not their lengths which should be old_len = new_len +/- 1 + Inc { old: ValueId, new: ValueId }, + Dec { old: ValueId, new: ValueId }, +} + +/// Find the change to a slice's capacity an instruction would have +fn slice_capacity_change( + dfg: &DataFlowGraph, + intrinsic: Intrinsic, + arguments: &[ValueId], + results: &[ValueId], +) -> SizeChange { + match intrinsic { + Intrinsic::SlicePushBack | Intrinsic::SlicePushFront | Intrinsic::SliceInsert => { + // Expecting: len, slice = ... + assert_eq!(results.len(), 2); + let old = arguments[1]; + let new = results[1]; + assert!(matches!(dfg.type_of_value(old), Type::Slice(_))); + assert!(matches!(dfg.type_of_value(new), Type::Slice(_))); + SizeChange::Inc { old, new } + } + + Intrinsic::SlicePopBack | Intrinsic::SliceRemove => { + let old = arguments[1]; + let new = results[1]; + assert!(matches!(dfg.type_of_value(old), Type::Slice(_))); + assert!(matches!(dfg.type_of_value(new), Type::Slice(_))); + SizeChange::Dec { old, new } + } + + Intrinsic::SlicePopFront => { + let old = arguments[1]; + let new = results[results.len() - 1]; + assert!(matches!(dfg.type_of_value(old), Type::Slice(_))); + assert!(matches!(dfg.type_of_value(new), Type::Slice(_))); + SizeChange::Dec { old, new } + } + + Intrinsic::ToBits(_) => { + assert_eq!(results.len(), 2); + // Some tests fail this check, returning an array instead somehow: + // assert!(matches!(dfg.type_of_value(results[1]), Type::Slice(_))); + SizeChange::SetTo(results[1], FieldElement::max_num_bits() as usize) + } + // ToRadix seems to assume it is to bytes + Intrinsic::ToRadix(_) => { + assert_eq!(results.len(), 2); + assert!(matches!(dfg.type_of_value(results[1]), Type::Slice(_))); + SizeChange::SetTo(results[1], FieldElement::max_num_bytes() as usize) + } + Intrinsic::AsSlice => { + assert_eq!(arguments.len(), 1); + assert_eq!(results.len(), 2); + let length = match dfg.type_of_value(arguments[0]) { + Type::Array(_, length) => length, + other => unreachable!("slice_capacity_change expected array, found {other:?}"), + }; + assert!(matches!(dfg.type_of_value(results[1]), Type::Slice(_))); + SizeChange::SetTo(results[1], length) + } + + // These cases don't affect slice capacities + Intrinsic::AssertConstant + | Intrinsic::ApplyRangeConstraint + | Intrinsic::ArrayLen + | Intrinsic::StrAsBytes + | Intrinsic::BlackBox(_) + | Intrinsic::FromField + | Intrinsic::AsField + | Intrinsic::AsWitness + | Intrinsic::IsUnconstrained => SizeChange::None, + } +} diff --git a/compiler/noirc_evaluator/src/ssa/opt/resolve_is_unconstrained.rs b/compiler/noirc_evaluator/src/ssa/opt/resolve_is_unconstrained.rs new file mode 100644 index 00000000000..2c9e33ae528 --- /dev/null +++ b/compiler/noirc_evaluator/src/ssa/opt/resolve_is_unconstrained.rs @@ -0,0 +1,56 @@ +use crate::ssa::{ + ir::{ + function::{Function, RuntimeType}, + instruction::{Instruction, Intrinsic}, + types::Type, + value::Value, + }, + ssa_gen::Ssa, +}; +use acvm::FieldElement; +use fxhash::FxHashSet as HashSet; + +impl Ssa { + /// An SSA pass to find any calls to `Intrinsic::IsUnconstrained` and replacing any uses of the result of the intrinsic + /// with the resolved boolean value. + /// Note that this pass must run after the pass that does runtime separation, since in SSA generation an ACIR function can end up targeting brillig. + #[tracing::instrument(level = "trace", skip(self))] + pub(crate) fn resolve_is_unconstrained(mut self) -> Self { + for func in self.functions.values_mut() { + replace_is_unconstrained_result(func); + } + self + } +} + +fn replace_is_unconstrained_result(func: &mut Function) { + let mut is_unconstrained_calls = HashSet::default(); + // Collect all calls to is_unconstrained + for block_id in func.reachable_blocks() { + for &instruction_id in func.dfg[block_id].instructions() { + let target_func = match &func.dfg[instruction_id] { + Instruction::Call { func, .. } => *func, + _ => continue, + }; + + if let Value::Intrinsic(Intrinsic::IsUnconstrained) = &func.dfg[target_func] { + is_unconstrained_calls.insert(instruction_id); + } + } + } + + for instruction_id in is_unconstrained_calls { + let call_returns = func.dfg.instruction_results(instruction_id); + let original_return_id = call_returns[0]; + + // We replace the result with a fresh id. This will be unused, so the DIE pass will remove the leftover intrinsic call. + func.dfg.replace_result(instruction_id, original_return_id); + + let is_within_unconstrained = func.dfg.make_constant( + FieldElement::from(matches!(func.runtime(), RuntimeType::Brillig)), + Type::bool(), + ); + // Replace all uses of the original return value with the constant + func.dfg.set_value_from_id(original_return_id, is_within_unconstrained); + } +} diff --git a/compiler/noirc_evaluator/src/ssa/opt/runtime_separation.rs b/compiler/noirc_evaluator/src/ssa/opt/runtime_separation.rs new file mode 100644 index 00000000000..c0c9c0a1372 --- /dev/null +++ b/compiler/noirc_evaluator/src/ssa/opt/runtime_separation.rs @@ -0,0 +1,348 @@ +use std::collections::BTreeSet; + +use fxhash::{FxHashMap as HashMap, FxHashSet as HashSet}; + +use crate::ssa::{ + ir::{ + function::{Function, FunctionId, RuntimeType}, + instruction::Instruction, + value::{Value, ValueId}, + }, + ssa_gen::Ssa, +}; + +impl Ssa { + /// This optimization step separates the runtime of the functions in the SSA. + /// After this step, all functions with runtime `Acir` will be converted to Acir and + /// the functions with runtime `Brillig` will be converted to Brillig. + /// It does so by cloning all ACIR functions called from a Brillig context + /// and changing the runtime of the cloned functions to Brillig. + /// This pass needs to run after functions as values have been resolved (defunctionalization). + #[tracing::instrument(level = "trace", skip(self))] + pub(crate) fn separate_runtime(mut self) -> Self { + RuntimeSeparatorContext::separate_runtime(&mut self); + self + } +} + +#[derive(Debug, Default)] +struct RuntimeSeparatorContext { + // Original functions to clone to brillig + acir_functions_called_from_brillig: BTreeSet, + // Tracks the original => cloned version + mapped_functions: HashMap, +} + +impl RuntimeSeparatorContext { + pub(crate) fn separate_runtime(ssa: &mut Ssa) { + let mut runtime_separator = RuntimeSeparatorContext::default(); + + // We first collect all the acir functions called from a brillig context by exploring the SSA recursively + let mut processed_functions = HashSet::default(); + runtime_separator.collect_acir_functions_called_from_brillig( + ssa, + ssa.main_id, + false, + &mut processed_functions, + ); + + // Now we clone the relevant acir functions and change their runtime to brillig + runtime_separator.convert_acir_functions_called_from_brillig_to_brillig(ssa); + + // Now we update any calls within a brillig context to the mapped functions + runtime_separator.replace_calls_to_mapped_functions(ssa); + + // Some functions might be unreachable now (for example an acir function only called from brillig) + prune_unreachable_functions(ssa); + } + + fn collect_acir_functions_called_from_brillig( + &mut self, + ssa: &Ssa, + current_func_id: FunctionId, + mut within_brillig: bool, + processed_functions: &mut HashSet<(/* within_brillig */ bool, FunctionId)>, + ) { + // Processed functions needs the within brillig flag, since it is possible to call the same function from both brillig and acir + if processed_functions.contains(&(within_brillig, current_func_id)) { + return; + } + processed_functions.insert((within_brillig, current_func_id)); + + let func = &ssa.functions[¤t_func_id]; + if func.runtime() == RuntimeType::Brillig { + within_brillig = true; + } + + let called_functions = called_functions(func); + + if within_brillig { + for called_func_id in called_functions.iter() { + let called_func = &ssa.functions[&called_func_id]; + if matches!(called_func.runtime(), RuntimeType::Acir(_)) { + self.acir_functions_called_from_brillig.insert(*called_func_id); + } + } + } + + for called_func_id in called_functions.into_iter() { + self.collect_acir_functions_called_from_brillig( + ssa, + called_func_id, + within_brillig, + processed_functions, + ); + } + } + + fn convert_acir_functions_called_from_brillig_to_brillig(&mut self, ssa: &mut Ssa) { + for acir_func_id in self.acir_functions_called_from_brillig.iter() { + let cloned_id = ssa.clone_fn(*acir_func_id); + let new_func = + ssa.functions.get_mut(&cloned_id).expect("Cloned function should exist in SSA"); + new_func.set_runtime(RuntimeType::Brillig); + self.mapped_functions.insert(*acir_func_id, cloned_id); + } + } + + fn replace_calls_to_mapped_functions(&self, ssa: &mut Ssa) { + for (_function_id, func) in ssa.functions.iter_mut() { + if func.runtime() == RuntimeType::Brillig { + for called_func_value_id in called_functions_values(func).iter() { + let Value::Function(called_func_id) = &func.dfg[*called_func_value_id] else { + unreachable!("Value should be a function") + }; + if let Some(mapped_func_id) = self.mapped_functions.get(called_func_id) { + let mapped_value_id = func.dfg.import_function(*mapped_func_id); + func.dfg.set_value_from_id(*called_func_value_id, mapped_value_id); + } + } + } + } + } +} + +// We only consider direct calls to functions since functions as values should have been resolved +fn called_functions_values(func: &Function) -> BTreeSet { + let mut called_function_ids = BTreeSet::default(); + for block_id in func.reachable_blocks() { + for instruction_id in func.dfg[block_id].instructions() { + let Instruction::Call { func: called_value_id, .. } = &func.dfg[*instruction_id] else { + continue; + }; + + if let Value::Function(_) = func.dfg[*called_value_id] { + called_function_ids.insert(*called_value_id); + } + } + } + + called_function_ids +} + +fn called_functions(func: &Function) -> BTreeSet { + called_functions_values(func) + .into_iter() + .map(|value_id| { + let Value::Function(func_id) = func.dfg[value_id] else { + unreachable!("Value should be a function") + }; + func_id + }) + .collect() +} + +fn collect_reachable_functions( + ssa: &Ssa, + current_func_id: FunctionId, + reachable_functions: &mut HashSet, +) { + if reachable_functions.contains(¤t_func_id) { + return; + } + reachable_functions.insert(current_func_id); + + let func = &ssa.functions[¤t_func_id]; + let called_functions = called_functions(func); + + for called_func_id in called_functions.iter() { + collect_reachable_functions(ssa, *called_func_id, reachable_functions); + } +} + +fn prune_unreachable_functions(ssa: &mut Ssa) { + let mut reachable_functions = HashSet::default(); + collect_reachable_functions(ssa, ssa.main_id, &mut reachable_functions); + + ssa.functions.retain(|id, _value| reachable_functions.contains(id)); +} + +#[cfg(test)] +mod test { + use std::collections::BTreeSet; + + use noirc_frontend::monomorphization::ast::InlineType; + + use crate::ssa::{ + function_builder::FunctionBuilder, + ir::{ + function::{Function, FunctionId, RuntimeType}, + map::Id, + types::Type, + }, + opt::runtime_separation::called_functions, + ssa_gen::Ssa, + }; + + #[test] + fn basic_runtime_separation() { + // brillig fn foo { + // b0(): + // v0 = call bar() + // return v0 + // } + // acir fn bar { + // b0(): + // return 72 + // } + let foo_id = Id::test_new(0); + let mut builder = FunctionBuilder::new("foo".into(), foo_id); + builder.current_function.set_runtime(RuntimeType::Brillig); + + let bar_id = Id::test_new(1); + let bar = builder.import_function(bar_id); + let results = builder.insert_call(bar, Vec::new(), vec![Type::field()]).to_vec(); + builder.terminate_with_return(results); + + builder.new_function("bar".into(), bar_id, InlineType::default()); + let expected_return = 72u128; + let seventy_two = builder.field_constant(expected_return); + builder.terminate_with_return(vec![seventy_two]); + + let ssa = builder.finish(); + assert_eq!(ssa.functions.len(), 2); + + // Expected result + // brillig fn foo { + // b0(): + // v0 = call bar() + // return v0 + // } + // brillig fn bar { + // b0(): + // return 72 + // } + let separated = ssa.separate_runtime(); + + // The original bar function must have been pruned + assert_eq!(separated.functions.len(), 2); + + // All functions should be brillig now + for func in separated.functions.values() { + assert_eq!(func.runtime(), RuntimeType::Brillig); + } + } + + fn find_func_by_name<'ssa>( + ssa: &'ssa Ssa, + funcs: &BTreeSet, + name: &str, + ) -> &'ssa Function { + funcs + .iter() + .find_map(|id| { + let func = ssa.functions.get(id).unwrap(); + if func.name() == name { + Some(func) + } else { + None + } + }) + .unwrap() + } + + #[test] + fn same_function_shared_acir_brillig() { + // acir fn foo { + // b0(): + // v0 = call bar() + // v1 = call baz() + // return v0, v1 + // } + // brillig fn bar { + // b0(): + // v0 = call baz() + // return v0 + // } + // acir fn baz { + // b0(): + // return 72 + // } + let foo_id = Id::test_new(0); + let mut builder = FunctionBuilder::new("foo".into(), foo_id); + + let bar_id = Id::test_new(1); + let baz_id = Id::test_new(2); + let bar = builder.import_function(bar_id); + let baz = builder.import_function(baz_id); + let v0 = builder.insert_call(bar, Vec::new(), vec![Type::field()]).to_vec(); + let v1 = builder.insert_call(baz, Vec::new(), vec![Type::field()]).to_vec(); + builder.terminate_with_return(vec![v0[0], v1[0]]); + + builder.new_brillig_function("bar".into(), bar_id); + let baz = builder.import_function(baz_id); + let v0 = builder.insert_call(baz, Vec::new(), vec![Type::field()]).to_vec(); + builder.terminate_with_return(v0); + + builder.new_function("baz".into(), baz_id, InlineType::default()); + let expected_return = 72u128; + let seventy_two = builder.field_constant(expected_return); + builder.terminate_with_return(vec![seventy_two]); + + let ssa = builder.finish(); + assert_eq!(ssa.functions.len(), 3); + + // Expected result + // acir fn foo { + // b0(): + // v0 = call bar() + // v1 = call baz() <- baz_acir + // return v0, v1 + // } + // brillig fn bar { + // b0(): + // v0 = call baz() <- baz_brillig + // return v0 + // } + // acir fn baz { + // b0(): + // return 72 + // } + // brillig fn baz { + // b0(): + // return 72 + // } + let separated = ssa.separate_runtime(); + + // The original baz function must have been duplicated + assert_eq!(separated.functions.len(), 4); + + let main_function = separated.functions.get(&separated.main_id).unwrap(); + assert_eq!(main_function.runtime(), RuntimeType::Acir(InlineType::Inline)); + + let main_calls = called_functions(main_function); + assert_eq!(main_calls.len(), 2); + + let bar = find_func_by_name(&separated, &main_calls, "bar"); + let baz_acir = find_func_by_name(&separated, &main_calls, "baz"); + + assert_eq!(baz_acir.runtime(), RuntimeType::Acir(InlineType::Inline)); + assert_eq!(bar.runtime(), RuntimeType::Brillig); + + let bar_calls = called_functions(bar); + assert_eq!(bar_calls.len(), 1); + + let baz_brillig = find_func_by_name(&separated, &bar_calls, "baz"); + assert_eq!(baz_brillig.runtime(), RuntimeType::Brillig); + } +} diff --git a/compiler/noirc_evaluator/src/ssa/opt/simplify_cfg.rs b/compiler/noirc_evaluator/src/ssa/opt/simplify_cfg.rs index a31def8fd98..9d5d7879dcb 100644 --- a/compiler/noirc_evaluator/src/ssa/opt/simplify_cfg.rs +++ b/compiler/noirc_evaluator/src/ssa/opt/simplify_cfg.rs @@ -11,6 +11,8 @@ //! Currently, 1 and 4 are unimplemented. use std::collections::HashSet; +use acvm::acir::AcirField; + use crate::ssa::{ ir::{ basic_block::BasicBlockId, cfg::ControlFlowGraph, dfg::CallStack, function::Function, @@ -154,12 +156,12 @@ mod test { use crate::ssa::{ function_builder::FunctionBuilder, ir::{ - function::RuntimeType, instruction::{BinaryOp, TerminatorInstruction}, map::Id, types::Type, }, }; + use acvm::acir::AcirField; #[test] fn inline_blocks() { @@ -172,7 +174,7 @@ mod test { // return v1 // } let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("main".into(), main_id); let b1 = builder.insert_block(); let b2 = builder.insert_block(); @@ -228,7 +230,7 @@ mod test { // return Field 2 // } let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("main".into(), main_id); let v0 = builder.add_parameter(Type::bool()); let b1 = builder.insert_block(); diff --git a/compiler/noirc_evaluator/src/ssa/opt/unrolling.rs b/compiler/noirc_evaluator/src/ssa/opt/unrolling.rs index 645adb6b350..5f58be41422 100644 --- a/compiler/noirc_evaluator/src/ssa/opt/unrolling.rs +++ b/compiler/noirc_evaluator/src/ssa/opt/unrolling.rs @@ -12,8 +12,12 @@ //! //! Note that this pass also often creates superfluous jmp instructions in the //! program that will need to be removed by a later simplify cfg pass. +//! Note also that unrolling is skipped for Brillig runtime and as a result +//! we remove reference count instructions because they are only used by Brillig bytecode use std::collections::HashSet; +use acvm::acir::AcirField; + use crate::{ errors::RuntimeError, ssa::{ @@ -24,7 +28,7 @@ use crate::{ dom::DominatorTree, function::{Function, RuntimeType}, function_inserter::FunctionInserter, - instruction::TerminatorInstruction, + instruction::{Instruction, TerminatorInstruction}, post_order::PostOrder, value::ValueId, }, @@ -34,10 +38,41 @@ use crate::{ use fxhash::FxHashMap as HashMap; impl Ssa { - /// Unroll all loops in each SSA function. + /// Loop unrolling can return errors, since ACIR functions need to be fully unrolled. + /// This meta-pass will keep trying to unroll loops and simplifying the SSA until no more errors are found. + pub(crate) fn unroll_loops_iteratively(mut ssa: Ssa) -> Result { + // Try to unroll loops first: + let mut unroll_errors; + (ssa, unroll_errors) = ssa.try_to_unroll_loops(); + + // Keep unrolling until no more errors are found + while !unroll_errors.is_empty() { + let prev_unroll_err_count = unroll_errors.len(); + + // Simplify the SSA before retrying + + // Do a mem2reg after the last unroll to aid simplify_cfg + ssa = ssa.mem2reg(); + ssa = ssa.simplify_cfg(); + // Do another mem2reg after simplify_cfg to aid the next unroll + ssa = ssa.mem2reg(); + + // Unroll again + (ssa, unroll_errors) = ssa.try_to_unroll_loops(); + // If we didn't manage to unroll any more loops, exit + if unroll_errors.len() >= prev_unroll_err_count { + return Err(unroll_errors.swap_remove(0)); + } + } + Ok(ssa) + } + + /// Tries to unroll all loops in each SSA function. /// If any loop cannot be unrolled, it is left as-is or in a partially unrolled state. + /// Returns the ssa along with all unrolling errors encountered #[tracing::instrument(level = "trace", skip(self))] - pub(crate) fn unroll_loops(mut self) -> Result { + pub(crate) fn try_to_unroll_loops(mut self) -> (Ssa, Vec) { + let mut errors = vec![]; for function in self.functions.values_mut() { // Loop unrolling in brillig can lead to a code explosion currently. This can // also be true for ACIR, but we have no alternative to unrolling in ACIR. @@ -46,12 +81,9 @@ impl Ssa { continue; } - // This check is always true with the addition of the above guard, but I'm - // keeping it in case the guard on brillig functions is ever removed. - let abort_on_error = function.runtime() == RuntimeType::Acir; - find_all_loops(function).unroll_each_loop(function, abort_on_error)?; + errors.extend(find_all_loops(function).unroll_each_loop(function)); } - Ok(self) + (self, errors) } } @@ -115,34 +147,32 @@ fn find_all_loops(function: &Function) -> Loops { impl Loops { /// Unroll all loops within a given function. /// Any loops which fail to be unrolled (due to using non-constant indices) will be unmodified. - fn unroll_each_loop( - mut self, - function: &mut Function, - abort_on_error: bool, - ) -> Result<(), RuntimeError> { + fn unroll_each_loop(mut self, function: &mut Function) -> Vec { + let mut unroll_errors = vec![]; while let Some(next_loop) = self.yet_to_unroll.pop() { // If we've previously modified a block in this loop we need to refresh the context. // This happens any time we have nested loops. if next_loop.blocks.iter().any(|block| self.modified_blocks.contains(block)) { let mut new_context = find_all_loops(function); new_context.failed_to_unroll = self.failed_to_unroll; - return new_context.unroll_each_loop(function, abort_on_error); + return unroll_errors + .into_iter() + .chain(new_context.unroll_each_loop(function)) + .collect(); } // Don't try to unroll the loop again if it is known to fail if !self.failed_to_unroll.contains(&next_loop.header) { match unroll_loop(function, &self.cfg, &next_loop) { Ok(_) => self.modified_blocks.extend(next_loop.blocks), - Err(call_stack) if abort_on_error => { - return Err(RuntimeError::UnknownLoopBound { call_stack }); - } - Err(_) => { + Err(call_stack) => { self.failed_to_unroll.insert(next_loop.header); + unroll_errors.push(RuntimeError::UnknownLoopBound { call_stack }); } } } } - Ok(()) + unroll_errors } } @@ -439,9 +469,14 @@ impl<'f> LoopIteration<'f> { // instances of the induction variable or any values that were changed as a result // of the new induction variable value. for instruction in instructions { - self.inserter.push_instruction(instruction, self.insert_block); + // Skip reference count instructions since they are only used for brillig, and brillig code is not unrolled + if !matches!( + self.dfg()[instruction], + Instruction::IncrementRc { .. } | Instruction::DecrementRc { .. } + ) { + self.inserter.push_instruction(instruction, self.insert_block); + } } - let mut terminator = self.dfg()[self.source_block] .unwrap_terminator() .clone() @@ -464,7 +499,7 @@ impl<'f> LoopIteration<'f> { mod tests { use crate::ssa::{ function_builder::FunctionBuilder, - ir::{function::RuntimeType, instruction::BinaryOp, map::Id, types::Type}, + ir::{instruction::BinaryOp, map::Id, types::Type}, }; #[test] @@ -503,7 +538,7 @@ mod tests { let main_id = Id::test_new(0); // Compiling main - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("main".into(), main_id); let b1 = builder.insert_block(); let b2 = builder.insert_block(); @@ -585,7 +620,8 @@ mod tests { // } // The final block count is not 1 because unrolling creates some unnecessary jmps. // If a simplify cfg pass is ran afterward, the expected block count will be 1. - let ssa = ssa.unroll_loops().expect("All loops should be unrolled"); + let (ssa, errors) = ssa.try_to_unroll_loops(); + assert_eq!(errors.len(), 0, "All loops should be unrolled"); assert_eq!(ssa.main().reachable_blocks().len(), 5); } @@ -605,7 +641,7 @@ mod tests { // return Field 0 // } let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("main".into(), main_id); let b1 = builder.insert_block(); let b2 = builder.insert_block(); @@ -634,6 +670,7 @@ mod tests { assert_eq!(ssa.main().reachable_blocks().len(), 4); // Expected that we failed to unroll the loop - assert!(ssa.unroll_loops().is_err()); + let (_, errors) = ssa.try_to_unroll_loops(); + assert_eq!(errors.len(), 1, "Expected to fail to unroll loop"); } } diff --git a/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs b/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs index 9c760c013a9..a16e0f93c61 100644 --- a/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs +++ b/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs @@ -1,16 +1,16 @@ use std::rc::Rc; use std::sync::{Mutex, RwLock}; -use acvm::FieldElement; +use acvm::{acir::AcirField, FieldElement}; use iter_extended::vecmap; use noirc_errors::Location; +use noirc_frontend::ast::{BinaryOpKind, Signedness}; use noirc_frontend::monomorphization::ast::{self, LocalId, Parameters}; use noirc_frontend::monomorphization::ast::{FuncId, Program}; -use noirc_frontend::{BinaryOpKind, Signedness}; use crate::errors::RuntimeError; use crate::ssa::function_builder::FunctionBuilder; -use crate::ssa::ir::dfg::DataFlowGraph; +use crate::ssa::ir::basic_block::BasicBlockId; use crate::ssa::ir::function::FunctionId as IrFunctionId; use crate::ssa::ir::function::{Function, RuntimeType}; use crate::ssa::ir::instruction::BinaryOp; @@ -20,6 +20,7 @@ use crate::ssa::ir::types::{NumericType, Type}; use crate::ssa::ir::value::ValueId; use super::value::{Tree, Value, Values}; +use super::SSA_WORD_SIZE; use fxhash::FxHashMap as HashMap; /// The FunctionContext is the main context object for translating a @@ -38,6 +39,11 @@ pub(super) struct FunctionContext<'a> { pub(super) builder: FunctionBuilder, shared_context: &'a SharedContext, + + /// Contains any loops we're currently in the middle of translating. + /// These are ordered such that an inner loop is at the end of the vector and + /// outer loops are at the beginning. When a loop is finished, it is popped. + loops: Vec, } /// Shared context for all functions during ssa codegen. This is the only @@ -71,6 +77,13 @@ pub(super) struct SharedContext { pub(super) program: Program, } +#[derive(Copy, Clone)] +pub(super) struct Loop { + pub(super) loop_entry: BasicBlockId, + pub(super) loop_index: ValueId, + pub(super) loop_end: BasicBlockId, +} + /// The queue of functions remaining to compile type FunctionQueue = Vec<(ast::FuncId, IrFunctionId)>; @@ -95,8 +108,10 @@ impl<'a> FunctionContext<'a> { .expect("No function in queue for the FunctionContext to compile") .1; - let builder = FunctionBuilder::new(function_name, function_id, runtime); - let mut this = Self { definitions: HashMap::default(), builder, shared_context }; + let mut builder = FunctionBuilder::new(function_name, function_id); + builder.set_runtime(runtime); + let definitions = HashMap::default(); + let mut this = Self { definitions, builder, shared_context, loops: Vec::new() }; this.add_parameters_to_scope(parameters); this } @@ -111,7 +126,7 @@ impl<'a> FunctionContext<'a> { if func.unconstrained { self.builder.new_brillig_function(func.name.clone(), id); } else { - self.builder.new_function(func.name.clone(), id); + self.builder.new_function(func.name.clone(), id, func.inline_type); } self.add_parameters_to_scope(&func.parameters); } @@ -290,7 +305,7 @@ impl<'a> FunctionContext<'a> { /// 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 unsigned, overflow will be checked during acir-gen (cf. issue #4456), except for bit-shifts, because we will convert them to field multiplication /// /// If the result is signed, we just prepare it for check_signed_overflow() by casting it to /// an unsigned value representing the signed integer. @@ -330,58 +345,19 @@ impl<'a> FunctionContext<'a> { self.insert_safe_cast(result, result_type, location) } BinaryOpKind::ShiftLeft | BinaryOpKind::ShiftRight => { - self.check_shift_overflow(result, rhs, bit_size, location, true) + self.check_shift_overflow(result, rhs, bit_size, location) } _ => unreachable!("operator {} should not overflow", operator), } } Type::Numeric(NumericType::Unsigned { bit_size }) => { let dfg = &self.builder.current_function.dfg; - - let max_lhs_bits = self.builder.current_function.dfg.get_value_max_num_bits(lhs); - let max_rhs_bits = self.builder.current_function.dfg.get_value_max_num_bits(rhs); + let max_lhs_bits = dfg.get_value_max_num_bits(lhs); match operator { - BinaryOpKind::Add => { - if std::cmp::max(max_lhs_bits, max_rhs_bits) < bit_size { - // `lhs` and `rhs` have both been casted up from smaller types and so cannot overflow. - return result; - } - - let message = "attempt to add with overflow".to_string(); - self.builder.set_location(location).insert_range_check( - result, - bit_size, - Some(message), - ); - } - BinaryOpKind::Subtract => { - if dfg.is_constant(lhs) && max_lhs_bits > max_rhs_bits { - // `lhs` is a fixed constant and `rhs` is restricted such that `lhs - rhs > 0` - // Note strict inequality as `rhs > lhs` while `max_lhs_bits == max_rhs_bits` is possible. - return result; - } - - let message = "attempt to subtract with overflow".to_string(); - self.builder.set_location(location).insert_range_check( - result, - bit_size, - Some(message), - ); - } - BinaryOpKind::Multiply => { - if bit_size == 1 || max_lhs_bits + max_rhs_bits <= bit_size { - // Either performing boolean multiplication (which cannot overflow), - // or `lhs` and `rhs` have both been casted up from smaller types and so cannot overflow. - return result; - } - - let message = "attempt to multiply with overflow".to_string(); - self.builder.set_location(location).insert_range_check( - result, - bit_size, - Some(message), - ); + BinaryOpKind::Add | BinaryOpKind::Subtract | BinaryOpKind::Multiply => { + // Overflow check is deferred to acir-gen + return result; } BinaryOpKind::ShiftLeft => { if let Some(rhs_const) = dfg.get_numeric_constant(rhs) { @@ -394,7 +370,7 @@ impl<'a> FunctionContext<'a> { } } - self.check_shift_overflow(result, rhs, bit_size, location, false); + self.check_shift_overflow(result, rhs, bit_size, location); } _ => unreachable!("operator {} should not overflow", operator), @@ -416,32 +392,12 @@ impl<'a> FunctionContext<'a> { rhs: ValueId, bit_size: u32, location: Location, - is_signed: bool, ) -> ValueId { let one = self.builder.numeric_constant(FieldElement::one(), Type::bool()); - let rhs = if is_signed { - self.insert_safe_cast(rhs, Type::unsigned(bit_size), location) - } else { - rhs - }; - // Bit-shift with a negative number is an overflow - if is_signed { - // We compute the sign of rhs. - let half_width = self.builder.numeric_constant( - FieldElement::from(2_i128.pow(bit_size - 1)), - Type::unsigned(bit_size), - ); - let sign = self.builder.insert_binary(rhs, BinaryOp::Lt, half_width); - self.builder.set_location(location).insert_constrain( - sign, - one, - Some("attempt to bit-shift with overflow".to_owned().into()), - ); - } + assert!(self.builder.current_function.dfg.type_of_value(rhs) == Type::unsigned(8)); - let max = self - .builder - .numeric_constant(FieldElement::from(bit_size as i128), Type::unsigned(bit_size)); + let max = + self.builder.numeric_constant(FieldElement::from(bit_size as i128), Type::unsigned(8)); let overflow = self.builder.insert_binary(rhs, BinaryOp::Lt, max); self.builder.set_location(location).insert_constrain( overflow, @@ -546,26 +502,16 @@ impl<'a> FunctionContext<'a> { pub(super) fn insert_binary( &mut self, mut lhs: ValueId, - operator: noirc_frontend::BinaryOpKind, + operator: BinaryOpKind, mut rhs: ValueId, location: Location, ) -> Values { - let result_type = self.builder.type_of_value(lhs); - let mut result = match operator { - BinaryOpKind::Equal | BinaryOpKind::NotEqual - if matches!(result_type, Type::Array(..)) => - { - return self.insert_array_equality(lhs, operator, rhs, location) - } - _ => { - let op = convert_operator(operator); - if operator_requires_swapped_operands(operator) { - std::mem::swap(&mut lhs, &mut rhs); - } + let op = convert_operator(operator); + if operator_requires_swapped_operands(operator) { + std::mem::swap(&mut lhs, &mut rhs); + } - self.builder.set_location(location).insert_binary(lhs, op, rhs) - } - }; + let mut result = self.builder.set_location(location).insert_binary(lhs, op, rhs); // Check for integer overflow if matches!( @@ -584,94 +530,6 @@ impl<'a> FunctionContext<'a> { result.into() } - /// The frontend claims to support equality (==) on arrays, so we must support it in SSA here. - /// The actual BinaryOp::Eq in SSA is meant only for primitive numeric types so we encode an - /// entire equality loop on each array element. The generated IR is as follows: - /// - /// ... - /// result_alloc = allocate - /// store u1 1 in result_alloc - /// jmp loop_start(0) - /// loop_start(i: Field): - /// v0 = lt i, array_len - /// jmpif v0, then: loop_body, else: loop_end - /// loop_body(): - /// v1 = array_get lhs, index i - /// v2 = array_get rhs, index i - /// v3 = eq v1, v2 - /// v4 = load result_alloc - /// v5 = and v4, v3 - /// store v5 in result_alloc - /// v6 = add i, Field 1 - /// jmp loop_start(v6) - /// loop_end(): - /// result = load result_alloc - fn insert_array_equality( - &mut self, - lhs: ValueId, - operator: noirc_frontend::BinaryOpKind, - rhs: ValueId, - location: Location, - ) -> Values { - let lhs_type = self.builder.type_of_value(lhs); - let rhs_type = self.builder.type_of_value(rhs); - - let (array_length, element_type) = match (lhs_type, rhs_type) { - ( - Type::Array(lhs_composite_type, lhs_length), - Type::Array(rhs_composite_type, rhs_length), - ) => { - assert!( - lhs_composite_type.len() == 1 && rhs_composite_type.len() == 1, - "== is unimplemented for arrays of structs" - ); - assert_eq!(lhs_composite_type[0], rhs_composite_type[0]); - assert_eq!(lhs_length, rhs_length, "Expected two arrays of equal length"); - (lhs_length, lhs_composite_type[0].clone()) - } - _ => unreachable!("Expected two array values"), - }; - - let loop_start = self.builder.insert_block(); - let loop_body = self.builder.insert_block(); - let loop_end = self.builder.insert_block(); - - // pre-loop - let result_alloc = self.builder.set_location(location).insert_allocate(Type::bool()); - let true_value = self.builder.numeric_constant(1u128, Type::bool()); - self.builder.insert_store(result_alloc, true_value); - let zero = self.builder.length_constant(0u128); - self.builder.terminate_with_jmp(loop_start, vec![zero]); - - // loop_start - self.builder.switch_to_block(loop_start); - let i = self.builder.add_block_parameter(loop_start, Type::length_type()); - let array_length = self.builder.length_constant(array_length as u128); - let v0 = self.builder.insert_binary(i, BinaryOp::Lt, array_length); - self.builder.terminate_with_jmpif(v0, loop_body, loop_end); - - // loop body - self.builder.switch_to_block(loop_body); - let v1 = self.builder.insert_array_get(lhs, i, element_type.clone()); - let v2 = self.builder.insert_array_get(rhs, i, element_type); - let v3 = self.builder.insert_binary(v1, BinaryOp::Eq, v2); - let v4 = self.builder.insert_load(result_alloc, Type::bool()); - let v5 = self.builder.insert_binary(v4, BinaryOp::And, v3); - self.builder.insert_store(result_alloc, v5); - let one = self.builder.length_constant(1u128); - let v6 = self.builder.insert_binary(i, BinaryOp::Add, one); - self.builder.terminate_with_jmp(loop_start, vec![v6]); - - // loop end - self.builder.switch_to_block(loop_end); - let mut result = self.builder.insert_load(result_alloc, Type::bool()); - - if operator_requires_not(operator) { - result = self.builder.insert_not(result); - } - result.into() - } - /// Inserts a call instruction at the end of the current block and returns the results /// of the call. /// @@ -730,9 +588,9 @@ impl<'a> FunctionContext<'a> { address } - /// Array indexes are u64s. This function casts values used as indexes to u64. + /// Array indexes are u32. This function casts values used as indexes to u32. pub(super) fn make_array_index(&mut self, index: ValueId) -> ValueId { - self.builder.insert_cast(index, Type::unsigned(64)) + self.builder.insert_cast(index, Type::unsigned(SSA_WORD_SIZE)) } /// Define a local variable to be some Values that can later be retrieved @@ -980,12 +838,12 @@ impl<'a> FunctionContext<'a> { ) -> ValueId { let index = self.make_array_index(index); let element_size = - self.builder.numeric_constant(self.element_size(array), Type::unsigned(64)); + self.builder.numeric_constant(self.element_size(array), Type::unsigned(SSA_WORD_SIZE)); // The actual base index is the user's index * the array element type's size let mut index = self.builder.set_location(location).insert_binary(index, BinaryOp::Mul, element_size); - let one = self.builder.numeric_constant(FieldElement::one(), Type::unsigned(64)); + let one = self.builder.numeric_constant(FieldElement::one(), Type::unsigned(SSA_WORD_SIZE)); new_value.for_each(|value| { let value = value.eval(self); @@ -1022,94 +880,76 @@ impl<'a> FunctionContext<'a> { } } } + + /// Increments the reference count of all parameters. Returns the entry block of the function. + /// + /// This is done on parameters rather than call arguments so that we can optimize out + /// paired inc/dec instructions within brillig functions more easily. + pub(crate) fn increment_parameter_rcs(&mut self) -> BasicBlockId { + let entry = self.builder.current_function.entry_block(); + let parameters = self.builder.current_function.dfg.block_parameters(entry).to_vec(); + + for parameter in parameters { + self.builder.increment_array_reference_count(parameter); + } + + entry + } + + /// Ends a local scope of a function. + /// This will issue DecrementRc instructions for any arrays in the given starting scope + /// block's parameters. Arrays that are also used in terminator instructions for the scope are + /// ignored. + pub(crate) fn end_scope(&mut self, scope: BasicBlockId, terminator_args: &[ValueId]) { + let mut dropped_parameters = + self.builder.current_function.dfg.block_parameters(scope).to_vec(); + + dropped_parameters.retain(|parameter| !terminator_args.contains(parameter)); + + for parameter in dropped_parameters { + self.builder.decrement_array_reference_count(parameter); + } + } + + pub(crate) fn enter_loop( + &mut self, + loop_entry: BasicBlockId, + loop_index: ValueId, + loop_end: BasicBlockId, + ) { + self.loops.push(Loop { loop_entry, loop_index, loop_end }); + } + + pub(crate) fn exit_loop(&mut self) { + self.loops.pop(); + } + + pub(crate) fn current_loop(&self) -> Loop { + // The frontend should ensure break/continue are never used outside a loop + *self.loops.last().expect("current_loop: not in a loop!") + } } /// True if the given operator cannot be encoded directly and needs /// to be represented as !(some other operator) -fn operator_requires_not(op: noirc_frontend::BinaryOpKind) -> bool { - use noirc_frontend::BinaryOpKind::*; +fn operator_requires_not(op: BinaryOpKind) -> bool { + use BinaryOpKind::*; matches!(op, NotEqual | LessEqual | GreaterEqual) } /// True if the given operator cannot be encoded directly and needs /// to have its lhs and rhs swapped to be represented with another operator. /// Example: (a > b) needs to be represented as (b < a) -fn operator_requires_swapped_operands(op: noirc_frontend::BinaryOpKind) -> bool { - use noirc_frontend::BinaryOpKind::*; +fn operator_requires_swapped_operands(op: BinaryOpKind) -> bool { + use BinaryOpKind::*; matches!(op, Greater | LessEqual) } -/// If the operation requires its result to be truncated because it is an integer, the maximum -/// number of bits that result may occupy is returned. -fn operator_result_max_bit_size_to_truncate( - op: noirc_frontend::BinaryOpKind, - lhs: ValueId, - rhs: ValueId, - dfg: &DataFlowGraph, -) -> Option { - let lhs_type = dfg.type_of_value(lhs); - let rhs_type = dfg.type_of_value(rhs); - - let get_bit_size = |typ| match typ { - Type::Numeric(NumericType::Signed { bit_size } | NumericType::Unsigned { bit_size }) => { - Some(bit_size) - } - _ => None, - }; - - let lhs_bit_size = get_bit_size(lhs_type)?; - let rhs_bit_size = get_bit_size(rhs_type)?; - use noirc_frontend::BinaryOpKind::*; - match op { - Add => Some(std::cmp::max(lhs_bit_size, rhs_bit_size) + 1), - Subtract => Some(std::cmp::max(lhs_bit_size, rhs_bit_size) + 1), - Multiply => { - if lhs_bit_size == 1 || rhs_bit_size == 1 { - // Truncation is unnecessary as multiplication by a boolean value cannot cause an overflow. - None - } else { - Some(lhs_bit_size + rhs_bit_size) - } - } - - ShiftLeft => { - if let Some(rhs_constant) = 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 - return Some(lhs_bit_size + (rhs_constant.to_u128() as u32)); - } - // Unhappy case is that we don't yet know the rhs value, (even though it will - // eventually have to resolve to a constant). The best we can is assume the value of - // rhs to be the maximum value of it's numeric type. If that turns out to be larger - // than the native field's bit size, we full back to using that. - - // The formula for calculating the max bit size of a left shift is: - // lhs_bit_size + 2^{rhs_bit_size} - 1 - // Inferring the max bit size of left shift from its operands can result in huge - // number, that might not only be larger than the native field's max bit size, but - // furthermore might not be representable as a u32. Hence we use overflow checks and - // fallback to the native field's max bits. - let field_max_bits = FieldElement::max_num_bits(); - let (rhs_bit_size_pow_2, overflows) = 2_u32.overflowing_pow(rhs_bit_size); - if overflows { - return Some(field_max_bits); - } - let (max_bits_plus_1, overflows) = rhs_bit_size_pow_2.overflowing_add(lhs_bit_size); - if overflows { - return Some(field_max_bits); - } - let max_bit_size = std::cmp::min(max_bits_plus_1 - 1, field_max_bits); - Some(max_bit_size) - } - _ => None, - } -} - /// Converts the given operator to the appropriate BinaryOp. /// Take care when using this to insert a binary instruction: this requires /// checking operator_requires_not and operator_requires_swapped_operands /// to represent the full operation correctly. -fn convert_operator(op: noirc_frontend::BinaryOpKind) -> BinaryOp { +fn convert_operator(op: BinaryOpKind) -> BinaryOp { match op { BinaryOpKind::Add => BinaryOp::Add, BinaryOpKind::Subtract => BinaryOp::Sub, diff --git a/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs b/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs index d95295ae3c9..254e907fb0e 100644 --- a/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs +++ b/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs @@ -7,13 +7,12 @@ pub(crate) use program::Ssa; use context::SharedContext; use iter_extended::{try_vecmap, vecmap}; use noirc_errors::Location; -use noirc_frontend::{ - monomorphization::ast::{self, Expression, Program}, - Visibility, -}; +use noirc_frontend::ast::{UnaryOp, Visibility}; +use noirc_frontend::hir_def::types::Type as HirType; +use noirc_frontend::monomorphization::ast::{self, Expression, Program}; use crate::{ - errors::{InternalError, RuntimeError}, + errors::RuntimeError, ssa::{function_builder::data_bus::DataBusBuilder, ir::instruction::Intrinsic}, }; @@ -22,16 +21,19 @@ use self::{ value::{Tree, Values}, }; +use super::ir::instruction::error_selector_from_type; use super::{ function_builder::data_bus::DataBus, ir::{ function::RuntimeType, - instruction::{BinaryOp, ConstrainError, Instruction, TerminatorInstruction}, + instruction::{BinaryOp, ConstrainError, TerminatorInstruction}, types::Type, value::ValueId, }, }; +pub(crate) const SSA_WORD_SIZE: u32 = 32; + /// Generates SSA for the given monomorphized program. /// /// This function will generate the SSA but does not perform any optimizations on it. @@ -52,14 +54,13 @@ pub(crate) fn generate_ssa( // Queue the main function for compilation context.get_or_queue_function(main_id); - let mut function_context = FunctionContext::new( main.name.clone(), &main.parameters, if force_brillig_runtime || main.unconstrained { RuntimeType::Brillig } else { - RuntimeType::Acir + RuntimeType::Acir(main.inline_type) }, &context, ); @@ -121,8 +122,11 @@ impl<'a> FunctionContext<'a> { /// Codegen a function's body and set its return value to that of its last parameter. /// For functions returning nothing, this will be an empty list. fn codegen_function_body(&mut self, body: &Expression) -> Result<(), RuntimeError> { + let entry_block = self.increment_parameter_rcs(); let return_value = self.codegen_expression(body)?; let results = return_value.into_value_list(self); + self.end_scope(entry_block, &results); + self.builder.terminate_with_return(results); Ok(()) } @@ -144,11 +148,13 @@ impl<'a> FunctionContext<'a> { } Expression::Call(call) => self.codegen_call(call), Expression::Let(let_expr) => self.codegen_let(let_expr), - Expression::Constrain(expr, location, assert_message) => { - self.codegen_constrain(expr, *location, assert_message) + Expression::Constrain(expr, location, assert_payload) => { + self.codegen_constrain(expr, *location, assert_payload) } Expression::Assign(assign) => self.codegen_assign(assign), Expression::Semi(semi) => self.codegen_semi(semi), + Expression::Break => Ok(self.codegen_break()), + Expression::Continue => Ok(self.codegen_continue()), } } @@ -194,6 +200,15 @@ impl<'a> FunctionContext<'a> { ast::Type::Array(_, _) => { self.codegen_array_checked(elements, typ[0].clone())? } + _ => unreachable!("ICE: unexpected array literal type, got {}", array.typ), + }) + } + ast::Literal::Slice(array) => { + let elements = + try_vecmap(&array.contents, |element| self.codegen_expression(element))?; + + let typ = Self::convert_type(&array.typ).flatten(); + Ok(match array.typ { ast::Type::Slice(_) => { let slice_length = self.builder.length_constant(array.contents.len() as u128); @@ -201,10 +216,7 @@ impl<'a> FunctionContext<'a> { self.codegen_array_checked(elements, typ[1].clone())?; Tree::Branch(vec![slice_length.into(), slice_contents]) } - _ => unreachable!( - "ICE: array literal type must be an array or a slice, but got {}", - array.typ - ), + _ => unreachable!("ICE: unexpected slice literal type, got {}", array.typ), }) } ast::Literal::Integer(value, typ, location) => { @@ -226,6 +238,7 @@ impl<'a> FunctionContext<'a> { Ok(Tree::Branch(vec![string, field_count.into(), fields])) } + ast::Literal::Unit => Ok(Self::unit_value()), } } @@ -233,7 +246,7 @@ impl<'a> FunctionContext<'a> { let elements = vecmap(string.as_bytes(), |byte| { self.builder.numeric_constant(*byte as u128, Type::unsigned(8)).into() }); - let typ = Self::convert_non_tuple_type(&ast::Type::String(elements.len() as u64)); + let typ = Self::convert_non_tuple_type(&ast::Type::String(elements.len() as u32)); self.codegen_array(elements, typ) } @@ -288,24 +301,24 @@ impl<'a> FunctionContext<'a> { fn codegen_unary(&mut self, unary: &ast::Unary) -> Result { match unary.operator { - noirc_frontend::UnaryOp::Not => { + UnaryOp::Not => { let rhs = self.codegen_expression(&unary.rhs)?; let rhs = rhs.into_leaf().eval(self); Ok(self.builder.insert_not(rhs).into()) } - noirc_frontend::UnaryOp::Minus => { + UnaryOp::Minus => { let rhs = self.codegen_expression(&unary.rhs)?; let rhs = rhs.into_leaf().eval(self); let typ = self.builder.type_of_value(rhs); let zero = self.builder.numeric_constant(0u128, typ); Ok(self.insert_binary( zero, - noirc_frontend::BinaryOpKind::Subtract, + noirc_frontend::ast::BinaryOpKind::Subtract, rhs, unary.location, )) } - noirc_frontend::UnaryOp::MutableReference => { + UnaryOp::MutableReference => { Ok(self.codegen_reference(&unary.rhs)?.map(|rhs| { match rhs { value::Value::Normal(value) => { @@ -320,7 +333,7 @@ impl<'a> FunctionContext<'a> { } })) } - noirc_frontend::UnaryOp::Dereference { .. } => { + UnaryOp::Dereference { .. } => { let rhs = self.codegen_expression(&unary.rhs)?; Ok(self.dereference(&rhs, &unary.result_type)) } @@ -389,7 +402,8 @@ impl<'a> FunctionContext<'a> { // base_index = index * type_size let index = self.make_array_index(index); let type_size = Self::convert_type(element_type).size_of_type(); - let type_size = self.builder.numeric_constant(type_size as u128, Type::unsigned(64)); + let type_size = + self.builder.numeric_constant(type_size as u128, Type::unsigned(SSA_WORD_SIZE)); let base_index = self.builder.set_location(location).insert_binary(index, BinaryOp::Mul, type_size); @@ -437,7 +451,7 @@ impl<'a> FunctionContext<'a> { self.builder.insert_constrain( is_offset_out_of_bounds, true_const, - Some(Box::new("Index out of bounds".to_owned().into())), + Some("Index out of bounds".to_owned().into()), ); } @@ -474,6 +488,10 @@ impl<'a> FunctionContext<'a> { let index_type = Self::convert_non_tuple_type(&for_expr.index_type); let loop_index = self.builder.add_block_parameter(loop_entry, index_type); + // Remember the blocks and variable used in case there are break/continue instructions + // within the loop which need to jump to them. + self.enter_loop(loop_entry, loop_index, loop_end); + self.builder.set_location(for_expr.start_range_location); let start_index = self.codegen_non_tuple_expression(&for_expr.start_range)?; @@ -504,6 +522,7 @@ impl<'a> FunctionContext<'a> { // Finish by switching back to the end of the loop self.builder.switch_to_block(loop_end); + self.exit_loop(); Ok(Self::unit_value()) } @@ -595,10 +614,8 @@ impl<'a> FunctionContext<'a> { arguments.append(&mut values); } - // If an array is passed as an argument we increase its reference count - for argument in &arguments { - self.builder.increment_array_reference_count(*argument); - } + // Don't need to increment array reference counts when passed in as arguments + // since it is done within the function to each parameter already. self.codegen_intrinsic_call_checks(function, &arguments, call.location); Ok(self.insert_call(function, arguments, &call.return_type, call.location)) @@ -661,7 +678,7 @@ impl<'a> FunctionContext<'a> { &mut self, expr: &Expression, location: Location, - assert_message: &Option>, + assert_payload: &Option>, ) -> Result { let expr = self.codegen_non_tuple_expression(expr)?; let true_literal = self.builder.numeric_constant(true, Type::bool()); @@ -669,9 +686,9 @@ impl<'a> FunctionContext<'a> { // Set the location here for any errors that may occur when we codegen the assert message self.builder.set_location(location); - let assert_message = self.codegen_constrain_error(assert_message)?; + let assert_payload = self.codegen_constrain_error(assert_payload)?; - self.builder.insert_constrain(expr, true_literal, assert_message); + self.builder.insert_constrain(expr, true_literal, assert_payload); Ok(Self::unit_value()) } @@ -682,46 +699,33 @@ impl<'a> FunctionContext<'a> { // inserted to the SSA as we want that instruction to be atomic in SSA with a constrain instruction. fn codegen_constrain_error( &mut self, - assert_message: &Option>, - ) -> Result>, RuntimeError> { - let Some(assert_message_expr) = assert_message else { return Ok(None) }; - - if let ast::Expression::Literal(ast::Literal::Str(assert_message)) = - assert_message_expr.as_ref() - { - return Ok(Some(Box::new(ConstrainError::Static(assert_message.to_string())))); - } - - let ast::Expression::Call(call) = assert_message_expr.as_ref() else { - return Err(InternalError::Unexpected { - expected: "Expected a call expression".to_owned(), - found: "Instead found {expr:?}".to_owned(), - call_stack: self.builder.get_call_stack(), + assert_message: &Option>, + ) -> Result, RuntimeError> { + let Some(assert_message_payload) = assert_message else { return Ok(None) }; + let (assert_message_expression, assert_message_typ) = assert_message_payload.as_ref(); + + let values = self.codegen_expression(assert_message_expression)?.into_value_list(self); + + let error_type_id = error_selector_from_type(assert_message_typ); + // Do not record string errors in the ABI + match assert_message_typ { + HirType::String(_) => {} + _ => { + self.builder.record_error_type(error_type_id, assert_message_typ.clone()); } - .into()); }; - - let func = self.codegen_non_tuple_expression(&call.func)?; - let mut arguments = Vec::with_capacity(call.arguments.len()); - - for argument in &call.arguments { - let mut values = self.codegen_expression(argument)?.into_value_list(self); - arguments.append(&mut values); - } - - // If an array is passed as an argument we increase its reference count - for argument in &arguments { - self.builder.increment_array_reference_count(*argument); - } - - let instr = Instruction::Call { func, arguments }; - Ok(Some(Box::new(ConstrainError::Dynamic(instr)))) + Ok(Some(ConstrainError::UserDefined(error_type_id, values))) } fn codegen_assign(&mut self, assign: &ast::Assign) -> Result { let lhs = self.extract_current_value(&assign.lvalue)?; let rhs = self.codegen_expression(&assign.expression)?; + rhs.clone().for_each(|value| { + let value = value.eval(self); + self.builder.increment_array_reference_count(value); + }); + self.assign_new_value(lhs, rhs); Ok(Self::unit_value()) } @@ -730,4 +734,19 @@ impl<'a> FunctionContext<'a> { self.codegen_expression(expr)?; Ok(Self::unit_value()) } + + fn codegen_break(&mut self) -> Values { + let loop_end = self.current_loop().loop_end; + self.builder.terminate_with_jmp(loop_end, Vec::new()); + Self::unit_value() + } + + fn codegen_continue(&mut self) -> Values { + let loop_ = self.current_loop(); + + // Must remember to increment i before jumping + let new_loop_index = self.make_offset(loop_.loop_index, 1); + self.builder.terminate_with_jmp(loop_.loop_entry, vec![new_loop_index]); + Self::unit_value() + } } diff --git a/compiler/noirc_evaluator/src/ssa/ssa_gen/program.rs b/compiler/noirc_evaluator/src/ssa/ssa_gen/program.rs index 509f778f3b0..7a77aa76101 100644 --- a/compiler/noirc_evaluator/src/ssa/ssa_gen/program.rs +++ b/compiler/noirc_evaluator/src/ssa/ssa_gen/program.rs @@ -1,23 +1,34 @@ use std::{collections::BTreeMap, fmt::Display}; +use acvm::acir::circuit::ErrorSelector; use iter_extended::btree_map; use crate::ssa::ir::{ - function::{Function, FunctionId}, + function::{Function, FunctionId, RuntimeType}, map::AtomicCounter, }; +use noirc_frontend::hir_def::types::Type as HirType; /// Contains the entire SSA representation of the program. pub(crate) struct Ssa { pub(crate) functions: BTreeMap, pub(crate) main_id: FunctionId, pub(crate) next_id: AtomicCounter, + /// Maps SSA entry point function ID -> Final generated ACIR artifact index. + /// There can be functions specified in SSA which do not act as ACIR entry points. + /// This mapping is necessary to use the correct function pointer for an ACIR call, + /// as the final program artifact will be a list of only entry point functions. + pub(crate) entry_point_to_generated_index: BTreeMap, + pub(crate) error_selector_to_type: BTreeMap, } impl Ssa { /// Create a new Ssa object from the given SSA functions. /// The first function in this vector is expected to be the main function. - pub(crate) fn new(functions: Vec) -> Self { + pub(crate) fn new( + functions: Vec, + error_types: BTreeMap, + ) -> Self { let main_id = functions.first().expect("Expected at least 1 SSA function").id(); let mut max_id = main_id; @@ -26,7 +37,27 @@ impl Ssa { (f.id(), f) }); - Self { functions, main_id, next_id: AtomicCounter::starting_after(max_id) } + let entry_point_to_generated_index = btree_map( + functions + .iter() + .filter(|(_, func)| { + let runtime = func.runtime(); + match func.runtime() { + RuntimeType::Acir(_) => runtime.is_entry_point() || func.id() == main_id, + RuntimeType::Brillig => false, + } + }) + .enumerate(), + |(i, (id, _))| (*id, i as u32), + ); + + Self { + functions, + main_id, + next_id: AtomicCounter::starting_after(max_id), + entry_point_to_generated_index, + error_selector_to_type: error_types, + } } /// Returns the entry-point function of the program @@ -49,6 +80,14 @@ impl Ssa { self.functions.insert(new_id, function); new_id } + + /// Clones an already existing function with a fresh id + pub(crate) fn clone_fn(&mut self, existing_function_id: FunctionId) -> FunctionId { + let new_id = self.next_id.next(); + let function = Function::clone_with_id(new_id, &self.functions[&existing_function_id]); + self.functions.insert(new_id, function); + new_id + } } impl Display for Ssa { diff --git a/compiler/noirc_frontend/Cargo.toml b/compiler/noirc_frontend/Cargo.toml index a3a8d460572..381eb4a9bb9 100644 --- a/compiler/noirc_frontend/Cargo.toml +++ b/compiler/noirc_frontend/Cargo.toml @@ -3,29 +3,45 @@ name = "noirc_frontend" version.workspace = true authors.workspace = true edition.workspace = true +rust-version.workspace = true license.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] acvm.workspace = true +noirc_arena.workspace = true noirc_errors.workspace = true noirc_printable_type.workspace = true fm.workspace = true -arena.workspace = true iter-extended.workspace = true chumsky.workspace = true thiserror.workspace = true smol_str.workspace = true +im.workspace = true serde_json.workspace = true serde.workspace = true +num-bigint.workspace = true +num-traits.workspace = true rustc-hash = "1.1.0" small-ord-set = "0.1.3" regex = "1.9.1" +cfg-if = "1.0.0" tracing.workspace = true petgraph = "0.6" +lalrpop-util = { version = "0.20.2", features = ["lexer"] } + [dev-dependencies] +base64.workspace = true strum = "0.24" strum_macros = "0.24" tempfile.workspace = true + +[build-dependencies] +lalrpop = "0.20.2" + +[features] +experimental_parser = [] +bn254 = [] +bls12_381 = [] diff --git a/compiler/noirc_frontend/build.rs b/compiler/noirc_frontend/build.rs new file mode 100644 index 00000000000..eb896a377ae --- /dev/null +++ b/compiler/noirc_frontend/build.rs @@ -0,0 +1,28 @@ +use std::fs::{read_to_string, File}; +use std::io::Write; + +fn main() { + lalrpop::Configuration::new() + .emit_rerun_directives(true) + .use_cargo_dir_conventions() + .process() + .unwrap(); + + // here, we get a lint error from "extern crate core" so patching that until lalrpop does + // (adding cfg directives appears to be unsupported by lalrpop) + let out_dir = std::env::var("OUT_DIR").unwrap(); + let parser_path = std::path::Path::new(&out_dir).join("noir_parser.rs"); + let content_str = read_to_string(parser_path.clone()).unwrap(); + let mut parser_file = File::create(parser_path).unwrap(); + for line in content_str.lines() { + if line.contains("extern crate core") { + parser_file + .write_all( + format!("{}\n", line.replace("extern crate core", "use core")).as_bytes(), + ) + .unwrap(); + } else { + parser_file.write_all(format!("{}\n", line).as_bytes()).unwrap(); + } + } +} diff --git a/compiler/noirc_frontend/src/ast/expression.rs b/compiler/noirc_frontend/src/ast/expression.rs index dd4eca24784..3e6727c848f 100644 --- a/compiler/noirc_frontend/src/ast/expression.rs +++ b/compiler/noirc_frontend/src/ast/expression.rs @@ -1,15 +1,19 @@ use std::borrow::Cow; use std::fmt::Display; -use crate::token::{Attributes, Token}; -use crate::{ - Distinctness, FunctionVisibility, Ident, Path, Pattern, Recoverable, Statement, StatementKind, +use crate::ast::{ + Ident, ItemVisibility, Path, Pattern, Recoverable, Statement, StatementKind, UnresolvedTraitConstraint, UnresolvedType, UnresolvedTypeData, Visibility, }; -use acvm::FieldElement; +use crate::macros_api::StructId; +use crate::node_interner::ExprId; +use crate::token::{Attributes, Token}; +use acvm::{acir::AcirField, FieldElement}; use iter_extended::vecmap; use noirc_errors::{Span, Spanned}; +use super::UnaryRhsMemberAccess; + #[derive(Debug, PartialEq, Eq, Clone)] pub enum ExpressionKind { Literal(Literal), @@ -23,10 +27,19 @@ pub enum ExpressionKind { Cast(Box), Infix(Box), If(Box), - Variable(Path), + // The optional vec here is the optional list of generics + // provided by the turbofish operator, if used + Variable(Path, Option>), Tuple(Vec), Lambda(Box), Parenthesized(Box), + Quote(BlockExpression), + Comptime(BlockExpression), + + // This variant is only emitted when inlining the result of comptime + // code. It is used to translate function values back into the AST while + // guaranteeing they have the same instantiated type and definition id without resolving again. + Resolved(ExprId), Error, } @@ -37,7 +50,7 @@ pub type UnresolvedGenerics = Vec; impl ExpressionKind { pub fn into_path(self) -> Option { match self { - ExpressionKind::Variable(path) => Some(path), + ExpressionKind::Variable(path, _) => Some(path), _ => None, } } @@ -70,6 +83,17 @@ impl ExpressionKind { })) } + pub fn slice(contents: Vec) -> ExpressionKind { + ExpressionKind::Literal(Literal::Slice(ArrayLiteral::Standard(contents))) + } + + pub fn repeated_slice(repeated_element: Expression, length: Expression) -> ExpressionKind { + ExpressionKind::Literal(Literal::Slice(ArrayLiteral::Repeated { + repeated_element: Box::new(repeated_element), + length: Box::new(length), + })) + } + pub fn integer(contents: FieldElement) -> ExpressionKind { ExpressionKind::Literal(Literal::Integer(contents, false)) } @@ -91,7 +115,11 @@ impl ExpressionKind { } pub fn constructor((type_name, fields): (Path, Vec<(Ident, Expression)>)) -> ExpressionKind { - ExpressionKind::Constructor(Box::new(ConstructorExpression { type_name, fields })) + ExpressionKind::Constructor(Box::new(ConstructorExpression { + type_name, + fields, + struct_type: None, + })) } /// Returns true if the expression is a literal integer @@ -151,16 +179,19 @@ impl Expression { pub fn member_access_or_method_call( lhs: Expression, - (rhs, args): (Ident, Option>), + (rhs, args): UnaryRhsMemberAccess, span: Span, ) -> Expression { let kind = match args { None => ExpressionKind::MemberAccess(Box::new(MemberAccessExpression { lhs, rhs })), - Some(arguments) => ExpressionKind::MethodCall(Box::new(MethodCallExpression { - object: lhs, - method_name: rhs, - arguments, - })), + Some((generics, arguments)) => { + ExpressionKind::MethodCall(Box::new(MethodCallExpression { + object: lhs, + method_name: rhs, + generics, + arguments, + })) + } }; Expression::new(kind, span) } @@ -322,6 +353,7 @@ impl UnaryOp { #[derive(Debug, PartialEq, Eq, Clone)] pub enum Literal { Array(ArrayLiteral), + Slice(ArrayLiteral), Bool(bool), Integer(FieldElement, /*sign*/ bool), // false for positive integer and true for negative Str(String), @@ -372,16 +404,14 @@ pub struct FunctionDefinition { // and `secondary` attributes (ones that do not change the function kind) pub attributes: Attributes, - /// True if this function was defined with the 'open' keyword - pub is_open: bool, - - pub is_internal: bool, - /// True if this function was defined with the 'unconstrained' keyword pub is_unconstrained: bool, + /// True if this function was defined with the 'comptime' keyword + pub is_comptime: bool, + /// Indicate if this function was defined with the 'pub' keyword - pub visibility: FunctionVisibility, + pub visibility: ItemVisibility, pub generics: UnresolvedGenerics, pub parameters: Vec, @@ -390,7 +420,6 @@ pub struct FunctionDefinition { pub where_clause: Vec, pub return_type: FunctionReturnType, pub return_visibility: Visibility, - pub return_distinctness: Distinctness, } #[derive(Debug, PartialEq, Eq, Clone)] @@ -409,18 +438,6 @@ pub enum FunctionReturnType { Ty(UnresolvedType), } -/// Describes the types of smart contract functions that are allowed. -/// - All Noir programs in the non-contract context can be seen as `Secret`. -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub enum ContractFunctionType { - /// This function will be executed in a private - /// context. - Secret, - /// This function will be executed in a public - /// context. - Open, -} - #[derive(Debug, PartialEq, Eq, Clone)] pub enum ArrayLiteral { Standard(Vec), @@ -437,6 +454,8 @@ pub struct CallExpression { pub struct MethodCallExpression { pub object: Expression, pub method_name: Ident, + /// Method calls have an optional list of generics if the turbofish operator was used + pub generics: Option>, pub arguments: Vec, } @@ -444,6 +463,11 @@ pub struct MethodCallExpression { pub struct ConstructorExpression { pub type_name: Path, pub fields: Vec<(Ident, Expression)>, + + /// This may be filled out during macro expansion + /// so that we can skip re-resolving the type name since it + /// would be lost at that point. + pub struct_type: Option, } #[derive(Debug, PartialEq, Eq, Clone)] @@ -497,7 +521,14 @@ impl Display for ExpressionKind { Cast(cast) => cast.fmt(f), Infix(infix) => infix.fmt(f), If(if_expr) => if_expr.fmt(f), - Variable(path) => path.fmt(f), + Variable(path, generics) => { + if let Some(generics) = generics { + let generics = vecmap(generics, ToString::to_string); + write!(f, "{path}::<{}>", generics.join(", ")) + } else { + path.fmt(f) + } + } Constructor(constructor) => constructor.fmt(f), MemberAccess(access) => access.fmt(f), Tuple(elements) => { @@ -506,7 +537,10 @@ impl Display for ExpressionKind { } Lambda(lambda) => lambda.fmt(f), Parenthesized(sub_expr) => write!(f, "({sub_expr})"), + Quote(block) => write!(f, "quote {block}"), + Comptime(block) => write!(f, "comptime {block}"), Error => write!(f, "Error"), + Resolved(_) => write!(f, "?Resolved"), } } } @@ -521,6 +555,13 @@ impl Display for Literal { Literal::Array(ArrayLiteral::Repeated { repeated_element, length }) => { write!(f, "[{repeated_element}; {length}]") } + Literal::Slice(ArrayLiteral::Standard(elements)) => { + let contents = vecmap(elements, ToString::to_string); + write!(f, "&[{}]", contents.join(", ")) + } + Literal::Slice(ArrayLiteral::Repeated { repeated_element, length }) => { + write!(f, "&[{repeated_element}; {length}]") + } Literal::Bool(boolean) => write!(f, "{}", if *boolean { "true" } else { "false" }), Literal::Integer(integer, sign) => { if *sign { @@ -678,13 +719,13 @@ impl FunctionDefinition { span: ident.span().merge(unresolved_type.span.unwrap()), }) .collect(); + FunctionDefinition { name: name.clone(), attributes: Attributes::empty(), - is_open: false, - is_internal: false, is_unconstrained: false, - visibility: FunctionVisibility::Private, + is_comptime: false, + visibility: ItemVisibility::Private, generics: generics.clone(), parameters: p, body: body.clone(), @@ -692,7 +733,6 @@ impl FunctionDefinition { where_clause: where_clause.to_vec(), return_type: return_type.clone(), return_visibility: Visibility::Private, - return_distinctness: Distinctness::DuplicationAllowed, } } } diff --git a/compiler/noirc_frontend/src/ast/function.rs b/compiler/noirc_frontend/src/ast/function.rs index 3e8b78c1312..8acc068d86a 100644 --- a/compiler/noirc_frontend/src/ast/function.rs +++ b/compiler/noirc_frontend/src/ast/function.rs @@ -3,8 +3,8 @@ use std::fmt::Display; use noirc_errors::Span; use crate::{ + ast::{FunctionReturnType, Ident, Param, Visibility}, token::{Attributes, FunctionAttribute, SecondaryAttribute}, - FunctionReturnType, Ident, Param, Visibility, }; use super::{FunctionDefinition, UnresolvedType, UnresolvedTypeData}; @@ -32,6 +32,15 @@ pub enum FunctionKind { Recursive, } +impl FunctionKind { + pub fn can_ignore_return_type(self) -> bool { + match self { + FunctionKind::LowLevel | FunctionKind::Builtin | FunctionKind::Oracle => true, + FunctionKind::Normal | FunctionKind::Recursive => false, + } + } +} + impl NoirFunction { pub fn normal(def: FunctionDefinition) -> NoirFunction { NoirFunction { kind: FunctionKind::Normal, def } @@ -108,6 +117,8 @@ impl From for NoirFunction { Some(FunctionAttribute::Test { .. }) => FunctionKind::Normal, Some(FunctionAttribute::Oracle(_)) => FunctionKind::Oracle, Some(FunctionAttribute::Recursive) => FunctionKind::Recursive, + Some(FunctionAttribute::Fold) => FunctionKind::Normal, + Some(FunctionAttribute::NoPredicates) => FunctionKind::Normal, None => FunctionKind::Normal, }; diff --git a/compiler/noirc_frontend/src/ast/mod.rs b/compiler/noirc_frontend/src/ast/mod.rs index 29edbaca594..39b23228967 100644 --- a/compiler/noirc_frontend/src/ast/mod.rs +++ b/compiler/noirc_frontend/src/ast/mod.rs @@ -26,12 +26,14 @@ use crate::{ token::IntType, BinaryTypeOperator, }; +use acvm::acir::AcirField; use iter_extended::vecmap; #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, Ord, PartialOrd)] pub enum IntegerBitSize { One, Eight, + Sixteen, ThirtyTwo, SixtyFour, } @@ -48,6 +50,7 @@ impl From for u32 { match size { One => 1, Eight => 8, + Sixteen => 16, ThirtyTwo => 32, SixtyFour => 64, } @@ -64,6 +67,7 @@ impl TryFrom for IntegerBitSize { match value { 1 => Ok(One), 8 => Ok(Eight), + 16 => Ok(Sixteen), 32 => Ok(ThirtyTwo), 64 => Ok(SixtyFour), _ => Err(InvalidIntegerBitSizeError(value)), @@ -83,11 +87,12 @@ impl core::fmt::Display for IntegerBitSize { #[derive(Debug, PartialEq, Eq, Clone, Hash)] pub enum UnresolvedTypeData { FieldElement, - Array(Option, Box), // [4]Witness = Array(4, Witness) + Array(UnresolvedTypeExpression, Box), // [Field; 4] = Array(4, Field) + Slice(Box), Integer(Signedness, IntegerBitSize), // u32 = Integer(unsigned, ThirtyTwo) Bool, Expression(UnresolvedTypeExpression), - String(Option), + String(UnresolvedTypeExpression), FormatString(UnresolvedTypeExpression, Box), Unit, @@ -111,6 +116,9 @@ pub enum UnresolvedTypeData { /*env:*/ Box, ), + // The type of quoted code for metaprogramming + Code, + Unspecified, // This is for when the user declares a variable without specifying it's type Error, } @@ -125,13 +133,17 @@ pub struct UnresolvedType { pub span: Option, } +/// Type wrapper for a member access +pub(crate) type UnaryRhsMemberAccess = + (Ident, Option<(Option>, Vec)>); + /// The precursor to TypeExpression, this is the type that the parser allows /// to be used in the length position of an array type. Only constants, variables, /// and numeric binary operators are allowed here. #[derive(Debug, PartialEq, Eq, Clone, Hash)] pub enum UnresolvedTypeExpression { Variable(Path), - Constant(u64, Span), + Constant(u32, Span), BinaryOperation( Box, BinaryTypeOperator, @@ -151,10 +163,8 @@ impl std::fmt::Display for UnresolvedTypeData { use UnresolvedTypeData::*; match self { FieldElement => write!(f, "Field"), - Array(len, typ) => match len { - None => write!(f, "[{typ}]"), - Some(len) => write!(f, "[{typ}; {len}]"), - }, + Array(len, typ) => write!(f, "[{typ}; {len}]"), + Slice(typ) => write!(f, "[{typ}]"), Integer(sign, num_bits) => match sign { Signedness::Signed => write!(f, "i{num_bits}"), Signedness::Unsigned => write!(f, "u{num_bits}"), @@ -181,10 +191,7 @@ impl std::fmt::Display for UnresolvedTypeData { } Expression(expression) => expression.fmt(f), Bool => write!(f, "bool"), - String(len) => match len { - None => write!(f, "str<_>"), - Some(len) => write!(f, "str<{len}>"), - }, + String(len) => write!(f, "str<{len}>"), FormatString(len, elements) => write!(f, "fmt<{len}, {elements}"), Function(args, ret, env) => { let args = vecmap(args, ToString::to_string).join(", "); @@ -201,6 +208,7 @@ impl std::fmt::Display for UnresolvedTypeData { } } MutableReference(element) => write!(f, "&mut {element}"), + Code => write!(f, "Code"), Unit => write!(f, "()"), Error => write!(f, "error"), Unspecified => write!(f, "unspecified"), @@ -299,12 +307,12 @@ impl UnresolvedTypeExpression { match expr.kind { ExpressionKind::Literal(Literal::Integer(int, sign)) => { assert!(!sign, "Negative literal is not allowed here"); - match int.try_to_u64() { + match int.try_to_u32() { Some(int) => Ok(UnresolvedTypeExpression::Constant(int, expr.span)), None => Err(expr), } } - ExpressionKind::Variable(path) => Ok(UnresolvedTypeExpression::Variable(path)), + ExpressionKind::Variable(path, _) => Ok(UnresolvedTypeExpression::Variable(path)), ExpressionKind::Prefix(prefix) if prefix.operator == UnaryOp::Minus => { let lhs = Box::new(UnresolvedTypeExpression::Constant(0, expr.span)); let rhs = Box::new(UnresolvedTypeExpression::from_expr_helper(prefix.rhs)?); @@ -354,8 +362,8 @@ impl UnresolvedTypeExpression { } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] -/// Represents whether the function can be called outside its module/crate -pub enum FunctionVisibility { +/// Represents whether the definition can be referenced outside its module/crate +pub enum ItemVisibility { Public, Private, PublicCrate, diff --git a/compiler/noirc_frontend/src/ast/statement.rs b/compiler/noirc_frontend/src/ast/statement.rs index 654554fe0e8..100746e4644 100644 --- a/compiler/noirc_frontend/src/ast/statement.rs +++ b/compiler/noirc_frontend/src/ast/statement.rs @@ -1,17 +1,20 @@ 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::{ - BlockExpression, Expression, ExpressionKind, IndexExpression, MemberAccessExpression, - MethodCallExpression, UnresolvedType, -}; +use acvm::acir::AcirField; use acvm::FieldElement; use iter_extended::vecmap; use noirc_errors::{Span, Spanned}; +use super::{ + BlockExpression, Expression, ExpressionKind, IndexExpression, MemberAccessExpression, + MethodCallExpression, UnresolvedType, +}; +use crate::lexer::token::SpannedToken; +use crate::macros_api::SecondaryAttribute; +use crate::parser::{ParserError, ParserErrorReason}; +use crate::token::Token; + /// This is used when an identifier fails to parse in the parser. /// Instead of failing the parse, we can often recover using this /// as the default value instead. Further passes like name resolution @@ -35,6 +38,10 @@ pub enum StatementKind { Expression(Expression), Assign(AssignStatement), For(ForLoopStatement), + Break, + Continue, + /// This statement should be executed at compile-time + Comptime(Box), // This is an expression with a trailing semi-colon Semi(Expression), // This statement is the result of a recovered parse error. @@ -44,6 +51,19 @@ pub enum StatementKind { } impl Statement { + pub fn add_semicolon( + mut self, + semi: Option, + span: Span, + last_statement_in_block: bool, + emit_error: &mut dyn FnMut(ParserError), + ) -> Self { + self.kind = self.kind.add_semicolon(semi, span, last_statement_in_block, emit_error); + self + } +} + +impl StatementKind { pub fn add_semicolon( self, semi: Option, @@ -54,20 +74,27 @@ impl Statement { let missing_semicolon = ParserError::with_reason(ParserErrorReason::MissingSeparatingSemi, span); - let kind = match self.kind { + match self { StatementKind::Let(_) | StatementKind::Constrain(_) | StatementKind::Assign(_) | StatementKind::Semi(_) + | StatementKind::Break + | StatementKind::Continue | StatementKind::Error => { // To match rust, statements always require a semicolon, even at the end of a block if semi.is_none() { emit_error(missing_semicolon); } - self.kind + self + } + StatementKind::Comptime(mut statement) => { + *statement = + statement.add_semicolon(semi, span, last_statement_in_block, emit_error); + StatementKind::Comptime(statement) } // A semicolon on a for loop is optional and does nothing - StatementKind::For(_) => self.kind, + StatementKind::For(_) => self, StatementKind::Expression(expr) => { match (&expr.kind, semi, last_statement_in_block) { @@ -87,9 +114,7 @@ impl Statement { (_, None, true) => StatementKind::Expression(expr), } } - }; - - Statement { kind, span: self.span } + } } } @@ -103,7 +128,13 @@ impl StatementKind { pub fn new_let( ((pattern, r#type), expression): ((Pattern, UnresolvedType), Expression), ) -> StatementKind { - StatementKind::Let(LetStatement { pattern, r#type, expression }) + StatementKind::Let(LetStatement { + pattern, + r#type, + expression, + comptime: false, + attributes: vec![], + }) } /// Create a Statement::Assign value, desugaring any combined operators like += if needed. @@ -116,10 +147,10 @@ impl StatementKind { // Desugar `a = b` to `a = a b`. This relies on the evaluation of `a` having no side effects, // which is currently enforced by the restricted syntax of LValues. if operator != Token::Assign { - let lvalue_expr = lvalue.as_expression(span); + let lvalue_expr = lvalue.as_expression(); let error_msg = "Token passed to Statement::assign is not a binary operator"; - let infix = crate::InfixExpression { + let infix = crate::ast::InfixExpression { lhs: lvalue_expr, operator: operator.try_into_binary_op(span).expect(error_msg), rhs: expression, @@ -198,11 +229,10 @@ impl From for Expression { fn from(i: Ident) -> Expression { Expression { span: i.0.span(), - kind: ExpressionKind::Variable(Path { - span: i.span(), - segments: vec![i], - kind: PathKind::Plain, - }), + kind: ExpressionKind::Variable( + Path { span: i.span(), segments: vec![i], kind: PathKind::Plain }, + None, + ), } } } @@ -240,6 +270,17 @@ pub trait Recoverable { fn error(span: Span) -> Self; } +#[derive(Debug, PartialEq, Eq, Clone)] +pub struct ModuleDeclaration { + pub ident: Ident, +} + +impl std::fmt::Display for ModuleDeclaration { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "mod {}", self.ident) + } +} + #[derive(Debug, PartialEq, Eq, Clone)] pub struct ImportStatement { pub path: Path, @@ -390,14 +431,10 @@ pub struct LetStatement { pub pattern: Pattern, pub r#type: UnresolvedType, pub expression: Expression, -} + pub attributes: Vec, -impl LetStatement { - pub fn new_let( - ((pattern, r#type), expression): ((Pattern, UnresolvedType), Expression), - ) -> LetStatement { - LetStatement { pattern, r#type, expression } - } + // True if this should only be run during compile-time + pub comptime: bool, } #[derive(Debug, PartialEq, Eq, Clone)] @@ -410,9 +447,9 @@ pub struct AssignStatement { #[derive(Debug, PartialEq, Eq, Clone)] pub enum LValue { Ident(Ident), - MemberAccess { object: Box, field_name: Ident }, - Index { array: Box, index: Expression }, - Dereference(Box), + MemberAccess { object: Box, field_name: Ident, span: Span }, + Index { array: Box, index: Expression, span: Span }, + Dereference(Box, Span), } #[derive(Debug, PartialEq, Eq, Clone)] @@ -449,7 +486,8 @@ impl Pattern { pub fn name_ident(&self) -> &Ident { match self { Pattern::Identifier(name_ident) => name_ident, - _ => panic!("only the identifier pattern can return a name"), + Pattern::Mutable(pattern, ..) => pattern.name_ident(), + _ => panic!("Only the Identifier or Mutable patterns can return a name"), } } @@ -469,28 +507,40 @@ impl Recoverable for Pattern { } impl LValue { - fn as_expression(&self, span: Span) -> Expression { + fn as_expression(&self) -> Expression { let kind = match self { - LValue::Ident(ident) => ExpressionKind::Variable(Path::from_ident(ident.clone())), - LValue::MemberAccess { object, field_name } => { + LValue::Ident(ident) => ExpressionKind::Variable(Path::from_ident(ident.clone()), None), + LValue::MemberAccess { object, field_name, span: _ } => { ExpressionKind::MemberAccess(Box::new(MemberAccessExpression { - lhs: object.as_expression(span), + lhs: object.as_expression(), rhs: field_name.clone(), })) } - LValue::Index { array, index } => ExpressionKind::Index(Box::new(IndexExpression { - collection: array.as_expression(span), - index: index.clone(), - })), - LValue::Dereference(lvalue) => { - ExpressionKind::Prefix(Box::new(crate::PrefixExpression { - operator: crate::UnaryOp::Dereference { implicitly_added: false }, - rhs: lvalue.as_expression(span), + LValue::Index { array, index, span: _ } => { + ExpressionKind::Index(Box::new(IndexExpression { + collection: array.as_expression(), + index: index.clone(), + })) + } + LValue::Dereference(lvalue, _span) => { + ExpressionKind::Prefix(Box::new(crate::ast::PrefixExpression { + operator: crate::ast::UnaryOp::Dereference { implicitly_added: false }, + rhs: lvalue.as_expression(), })) } }; + let span = self.span(); Expression::new(kind, span) } + + pub fn span(&self) -> Span { + match self { + LValue::Ident(ident) => ident.span(), + LValue::MemberAccess { span, .. } + | LValue::Index { span, .. } + | LValue::Dereference(_, span) => *span, + } + } } #[derive(Debug, PartialEq, Eq, Clone)] @@ -515,7 +565,7 @@ impl ForRange { identifier: Ident, block: Expression, for_loop_span: Span, - ) -> StatementKind { + ) -> Statement { /// 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. @@ -541,21 +591,23 @@ impl ForRange { pattern: Pattern::Identifier(array_ident.clone()), r#type: UnresolvedType::unspecified(), expression: array, + comptime: false, + attributes: vec![], }), span: array_span, }; // array.len() let segments = vec![array_ident]; - let array_ident = ExpressionKind::Variable(Path { - segments, - kind: PathKind::Plain, - span: array_span, - }); + let array_ident = ExpressionKind::Variable( + Path { segments, kind: PathKind::Plain, span: array_span }, + None, + ); 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), + generics: None, arguments: vec![], })); let end_range = Expression::new(end_range, array_span); @@ -566,11 +618,10 @@ impl ForRange { // array[i] let segments = vec![Ident::new(index_name, array_span)]; - let index_ident = ExpressionKind::Variable(Path { - segments, - kind: PathKind::Plain, - span: array_span, - }); + let index_ident = ExpressionKind::Variable( + Path { segments, kind: PathKind::Plain, span: array_span }, + None, + ); let loop_element = ExpressionKind::Index(Box::new(IndexExpression { collection: Expression::new(array_ident, array_span), @@ -583,6 +634,8 @@ impl ForRange { pattern: Pattern::Identifier(identifier), r#type: UnresolvedType::unspecified(), expression: Expression::new(loop_element, array_span), + comptime: false, + attributes: vec![], }), span: array_span, }; @@ -610,7 +663,10 @@ impl ForRange { is_unsafe: false, statements: vec![let_array, for_loop], }); - StatementKind::Expression(Expression::new(block, for_loop_span)) + Statement { + kind: StatementKind::Expression(Expression::new(block, for_loop_span)), + span: for_loop_span + } } } } @@ -632,6 +688,9 @@ impl Display for StatementKind { StatementKind::Expression(expression) => expression.fmt(f), StatementKind::Assign(assign) => assign.fmt(f), StatementKind::For(for_loop) => for_loop.fmt(f), + StatementKind::Break => write!(f, "break"), + StatementKind::Continue => write!(f, "continue"), + StatementKind::Comptime(statement) => write!(f, "comptime {}", statement.kind), StatementKind::Semi(semi) => write!(f, "{semi};"), StatementKind::Error => write!(f, "Error"), } @@ -660,9 +719,11 @@ impl Display for LValue { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { LValue::Ident(ident) => ident.fmt(f), - LValue::MemberAccess { object, field_name } => write!(f, "{object}.{field_name}"), - LValue::Index { array, index } => write!(f, "{array}[{index}]"), - LValue::Dereference(lvalue) => write!(f, "*{lvalue}"), + LValue::MemberAccess { object, field_name, span: _ } => { + write!(f, "{object}.{field_name}") + } + LValue::Index { array, index, span: _ } => write!(f, "{array}[{index}]"), + LValue::Dereference(lvalue, _span) => write!(f, "*{lvalue}"), } } } diff --git a/compiler/noirc_frontend/src/ast/structure.rs b/compiler/noirc_frontend/src/ast/structure.rs index 6a32fa717f3..bda6b8c0b11 100644 --- a/compiler/noirc_frontend/src/ast/structure.rs +++ b/compiler/noirc_frontend/src/ast/structure.rs @@ -1,6 +1,8 @@ use std::fmt::Display; -use crate::{token::SecondaryAttribute, Ident, UnresolvedGenerics, UnresolvedType}; +use crate::ast::{Ident, UnresolvedGenerics, UnresolvedType}; +use crate::token::SecondaryAttribute; + use iter_extended::vecmap; use noirc_errors::Span; diff --git a/compiler/noirc_frontend/src/ast/traits.rs b/compiler/noirc_frontend/src/ast/traits.rs index 775f0a5f2b4..772675723b5 100644 --- a/compiler/noirc_frontend/src/ast/traits.rs +++ b/compiler/noirc_frontend/src/ast/traits.rs @@ -3,10 +3,11 @@ use std::fmt::Display; use iter_extended::vecmap; use noirc_errors::Span; -use crate::{ - node_interner::TraitId, BlockExpression, Expression, FunctionReturnType, Ident, NoirFunction, - Path, UnresolvedGenerics, UnresolvedType, +use crate::ast::{ + BlockExpression, Expression, FunctionReturnType, Ident, NoirFunction, Path, UnresolvedGenerics, + UnresolvedType, }; +use crate::node_interner::TraitId; /// AST node for trait definitions: /// `trait name { ... items ... }` diff --git a/compiler/noirc_frontend/src/ast/type_alias.rs b/compiler/noirc_frontend/src/ast/type_alias.rs index 76a1e5a7e30..3228765170e 100644 --- a/compiler/noirc_frontend/src/ast/type_alias.rs +++ b/compiler/noirc_frontend/src/ast/type_alias.rs @@ -1,4 +1,4 @@ -use crate::{Ident, UnresolvedGenerics, UnresolvedType}; +use super::{Ident, UnresolvedGenerics, UnresolvedType}; use iter_extended::vecmap; use noirc_errors::Span; use std::fmt::Display; diff --git a/compiler/noirc_frontend/src/debug/mod.rs b/compiler/noirc_frontend/src/debug/mod.rs index 983ec1ccc81..ad9c34da354 100644 --- a/compiler/noirc_frontend/src/debug/mod.rs +++ b/compiler/noirc_frontend/src/debug/mod.rs @@ -4,9 +4,11 @@ use crate::{ ast::{Path, PathKind}, parser::{Item, ItemKind}, }; +use noirc_errors::debug_info::{DebugFnId, DebugFunction}; use noirc_errors::{Span, Spanned}; use std::collections::HashMap; use std::collections::VecDeque; +use std::mem::take; const MAX_MEMBER_ASSIGN_DEPTH: usize = 8; @@ -26,8 +28,12 @@ pub struct DebugInstrumenter { // all field names referenced when assigning to a member of a variable pub field_names: HashMap, + // all collected function metadata (name + argument names) + pub functions: HashMap, + next_var_id: u32, next_field_name_id: u32, + next_fn_id: u32, // last seen variable names and their IDs grouped by scope scope: Vec>, @@ -38,9 +44,11 @@ impl Default for DebugInstrumenter { Self { variables: HashMap::default(), field_names: HashMap::default(), + functions: HashMap::default(), scope: vec![], next_var_id: 0, next_field_name_id: 1, + next_fn_id: 0, } } } @@ -76,10 +84,22 @@ impl DebugInstrumenter { field_name_id } + fn insert_function(&mut self, fn_name: String, arguments: Vec) -> DebugFnId { + let fn_id = DebugFnId(self.next_fn_id); + self.next_fn_id += 1; + self.functions.insert(fn_id, DebugFunction { name: fn_name, arg_names: arguments }); + fn_id + } + fn walk_fn(&mut self, func: &mut ast::FunctionDefinition) { + let func_name = func.name.0.contents.clone(); + let func_args = + func.parameters.iter().map(|param| pattern_to_string(¶m.pattern)).collect(); + let fn_id = self.insert_function(func_name, func_args); + let enter_stmt = build_debug_call_stmt("enter", fn_id, func.span); self.scope.push(HashMap::default()); - let set_fn_params = func + let set_fn_params: Vec<_> = func .parameters .iter() .flat_map(|param| { @@ -93,10 +113,21 @@ impl DebugInstrumenter { }) .collect(); - self.walk_scope(&mut func.body.statements, func.span); + let func_body = &mut func.body.statements; + let mut statements = take(func_body); - // prepend fn params: - func.body.statements = [set_fn_params, func.body.statements.clone()].concat(); + self.walk_scope(&mut statements, func.span); + + // walk_scope ensures that the last statement is the return value of the function + let last_stmt = statements.pop().expect("at least one statement after walk_scope"); + let exit_stmt = build_debug_call_stmt("exit", fn_id, last_stmt.span); + + // rebuild function body + func_body.push(enter_stmt); + func_body.extend(set_fn_params); + func_body.extend(statements); + func_body.push(exit_stmt); + func_body.push(last_stmt); } // Modify a vector of statements in-place, adding instrumentation for sets and drops. @@ -114,6 +145,8 @@ impl DebugInstrumenter { pattern: ast::Pattern::Identifier(ident("__debug_expr", ret_expr.span)), r#type: ast::UnresolvedType::unspecified(), expression: ret_expr.clone(), + comptime: false, + attributes: vec![], }), span: ret_expr.span, }; @@ -138,11 +171,14 @@ impl DebugInstrumenter { let last_stmt = if has_ret_expr { ast::Statement { kind: ast::StatementKind::Expression(ast::Expression { - kind: ast::ExpressionKind::Variable(ast::Path { - segments: vec![ident("__debug_expr", span)], - kind: PathKind::Plain, - span, - }), + kind: ast::ExpressionKind::Variable( + ast::Path { + segments: vec![ident("__debug_expr", span)], + kind: PathKind::Plain, + span, + }, + None, + ), span, }), span, @@ -211,6 +247,7 @@ impl DebugInstrumenter { kind: ast::StatementKind::Let(ast::LetStatement { pattern: ast::Pattern::Tuple(vars_pattern, let_stmt.pattern.span()), r#type: ast::UnresolvedType::unspecified(), + comptime: false, expression: ast::Expression { kind: ast::ExpressionKind::Block(ast::BlockExpression { is_unsafe: true, @@ -218,6 +255,7 @@ impl DebugInstrumenter { }), span: let_stmt.expression.span, }, + attributes: vec![], }), span: *span, } @@ -243,6 +281,8 @@ impl DebugInstrumenter { pattern: ast::Pattern::Identifier(ident("__debug_expr", assign_stmt.expression.span)), r#type: ast::UnresolvedType::unspecified(), expression: assign_stmt.expression.clone(), + comptime: false, + attributes: vec![], }); let expression_span = assign_stmt.expression.span; let new_assign_stmt = match &assign_stmt.lvalue { @@ -252,7 +292,7 @@ impl DebugInstrumenter { .unwrap_or_else(|| panic!("var lookup failed for var_name={}", &id.0.contents)); build_assign_var_stmt(var_id, id_expr(&ident("__debug_expr", id.span()))) } - ast::LValue::Dereference(_lv) => { + ast::LValue::Dereference(_lv, span) => { // TODO: this is a dummy statement for now, but we should // somehow track the derefence and update the pointed to // variable @@ -273,16 +313,16 @@ impl DebugInstrumenter { }); break; } - ast::LValue::MemberAccess { object, field_name } => { + ast::LValue::MemberAccess { object, field_name, span } => { cursor = object; let field_name_id = self.insert_field_name(&field_name.0.contents); - indexes.push(sint_expr(-(field_name_id.0 as i128), expression_span)); + indexes.push(sint_expr(-(field_name_id.0 as i128), *span)); } - ast::LValue::Index { index, array } => { + ast::LValue::Index { index, array, span: _ } => { cursor = array; indexes.push(index.clone()); } - ast::LValue::Dereference(_ref) => { + ast::LValue::Dereference(_ref, _span) => { unimplemented![] } } @@ -436,6 +476,8 @@ impl DebugInstrumenter { use dep::__debug::{{ __debug_var_assign, __debug_var_drop, + __debug_fn_enter, + __debug_fn_exit, __debug_dereference_assign, {member_assigns}, }};"# @@ -462,16 +504,38 @@ pub fn build_debug_crate_file() -> String { } #[oracle(__debug_var_drop)] - unconstrained fn __debug_var_drop_oracle(_var_id: u32) {} - unconstrained fn __debug_var_drop_inner(var_id: u32) { + unconstrained fn __debug_var_drop_oracle(_var_id: u32) {} + unconstrained fn __debug_var_drop_inner(var_id: u32) { __debug_var_drop_oracle(var_id); } - pub fn __debug_var_drop(var_id: u32) { + pub fn __debug_var_drop(var_id: u32) { unsafe {{ __debug_var_drop_inner(var_id); }} } + #[oracle(__debug_fn_enter)] + unconstrained fn __debug_fn_enter_oracle(_fn_id: u32) {} + unconstrained fn __debug_fn_enter_inner(fn_id: u32) { + __debug_fn_enter_oracle(fn_id); + } + pub fn __debug_fn_enter(fn_id: u32) { + unsafe {{ + __debug_fn_enter_inner(fn_id); + }} + } + + #[oracle(__debug_fn_exit)] + unconstrained fn __debug_fn_exit_oracle(_fn_id: u32) {} + unconstrained fn __debug_fn_exit_inner(fn_id: u32) { + __debug_fn_exit_oracle(fn_id); + } + pub fn __debug_fn_exit(fn_id: u32) { + unsafe {{ + __debug_fn_exit_inner(fn_id); + }} + } + #[oracle(__debug_dereference_assign)] unconstrained fn __debug_dereference_assign_oracle(_var_id: u32, _value: T) {} unconstrained fn __debug_dereference_assign_inner(var_id: u32, value: T) { @@ -522,11 +586,14 @@ fn build_assign_var_stmt(var_id: SourceVarId, expr: ast::Expression) -> ast::Sta let span = expr.span; let kind = ast::ExpressionKind::Call(Box::new(ast::CallExpression { func: Box::new(ast::Expression { - kind: ast::ExpressionKind::Variable(ast::Path { - segments: vec![ident("__debug_var_assign", span)], - kind: PathKind::Plain, - span, - }), + kind: ast::ExpressionKind::Variable( + ast::Path { + segments: vec![ident("__debug_var_assign", span)], + kind: PathKind::Plain, + span, + }, + None, + ), span, }), arguments: vec![uint_expr(var_id.0 as u128, span), expr], @@ -537,11 +604,14 @@ fn build_assign_var_stmt(var_id: SourceVarId, expr: ast::Expression) -> ast::Sta fn build_drop_var_stmt(var_id: SourceVarId, span: Span) -> ast::Statement { let kind = ast::ExpressionKind::Call(Box::new(ast::CallExpression { func: Box::new(ast::Expression { - kind: ast::ExpressionKind::Variable(ast::Path { - segments: vec![ident("__debug_var_drop", span)], - kind: PathKind::Plain, - span, - }), + kind: ast::ExpressionKind::Variable( + ast::Path { + segments: vec![ident("__debug_var_drop", span)], + kind: PathKind::Plain, + span, + }, + None, + ), span, }), arguments: vec![uint_expr(var_id.0 as u128, span)], @@ -561,11 +631,14 @@ fn build_assign_member_stmt( let span = expr.span; let kind = ast::ExpressionKind::Call(Box::new(ast::CallExpression { func: Box::new(ast::Expression { - kind: ast::ExpressionKind::Variable(ast::Path { - segments: vec![ident(&format!["__debug_member_assign_{arity}"], span)], - kind: PathKind::Plain, - span, - }), + kind: ast::ExpressionKind::Variable( + ast::Path { + segments: vec![ident(&format!["__debug_member_assign_{arity}"], span)], + kind: PathKind::Plain, + span, + }, + None, + ), span, }), arguments: [ @@ -578,6 +651,24 @@ fn build_assign_member_stmt( ast::Statement { kind: ast::StatementKind::Semi(ast::Expression { kind, span }), span } } +fn build_debug_call_stmt(fname: &str, fn_id: DebugFnId, span: Span) -> ast::Statement { + let kind = ast::ExpressionKind::Call(Box::new(ast::CallExpression { + func: Box::new(ast::Expression { + kind: ast::ExpressionKind::Variable( + ast::Path { + segments: vec![ident(&format!["__debug_fn_{fname}"], span)], + kind: PathKind::Plain, + span, + }, + None, + ), + span, + }), + arguments: vec![uint_expr(fn_id.0 as u128, span)], + })); + ast::Statement { kind: ast::StatementKind::Semi(ast::Expression { kind, span }), span } +} + fn pattern_vars(pattern: &ast::Pattern) -> Vec<(ast::Ident, bool)> { let mut vars = vec![]; let mut stack = VecDeque::from([(pattern, false)]); @@ -602,17 +693,40 @@ fn pattern_vars(pattern: &ast::Pattern) -> Vec<(ast::Ident, bool)> { vars } +fn pattern_to_string(pattern: &ast::Pattern) -> String { + match pattern { + ast::Pattern::Identifier(id) => id.0.contents.clone(), + ast::Pattern::Mutable(mpat, _, _) => format!("mut {}", pattern_to_string(mpat.as_ref())), + ast::Pattern::Tuple(elements, _) => format!( + "({})", + elements.iter().map(pattern_to_string).collect::>().join(", ") + ), + ast::Pattern::Struct(name, fields, _) => { + format!( + "{} {{ {} }}", + name, + fields + .iter() + .map(|(field_ident, field_pattern)| { + format!("{}: {}", &field_ident.0.contents, pattern_to_string(field_pattern)) + }) + .collect::>() + .join(", "), + ) + } + } +} + fn ident(s: &str, span: Span) -> ast::Ident { ast::Ident(Spanned::from(span, s.to_string())) } fn id_expr(id: &ast::Ident) -> ast::Expression { ast::Expression { - kind: ast::ExpressionKind::Variable(Path { - segments: vec![id.clone()], - kind: PathKind::Plain, - span: id.span(), - }), + kind: ast::ExpressionKind::Variable( + Path { segments: vec![id.clone()], kind: PathKind::Plain, span: id.span() }, + None, + ), span: id.span(), } } diff --git a/compiler/noirc_frontend/src/elaborator/expressions.rs b/compiler/noirc_frontend/src/elaborator/expressions.rs new file mode 100644 index 00000000000..ed0b050b7a5 --- /dev/null +++ b/compiler/noirc_frontend/src/elaborator/expressions.rs @@ -0,0 +1,664 @@ +use iter_extended::vecmap; +use noirc_errors::{Location, Span}; +use regex::Regex; +use rustc_hash::FxHashSet as HashSet; + +use crate::{ + ast::{ + ArrayLiteral, ConstructorExpression, IfExpression, InfixExpression, Lambda, + UnresolvedTypeExpression, + }, + hir::{ + comptime::{self, Interpreter, InterpreterError}, + resolution::{errors::ResolverError, resolver::LambdaContext}, + type_check::TypeCheckError, + }, + hir_def::{ + expr::{ + HirArrayLiteral, HirBinaryOp, HirBlockExpression, HirCallExpression, HirCastExpression, + HirConstructorExpression, HirIfExpression, HirIndexExpression, HirInfixExpression, + HirLambda, HirMemberAccess, HirMethodCallExpression, HirMethodReference, + HirPrefixExpression, + }, + traits::TraitConstraint, + }, + macros_api::{ + BlockExpression, CallExpression, CastExpression, Expression, ExpressionKind, HirExpression, + HirLiteral, HirStatement, Ident, IndexExpression, Literal, MemberAccessExpression, + MethodCallExpression, PrefixExpression, + }, + node_interner::{DefinitionKind, ExprId, FuncId}, + Shared, StructType, Type, +}; + +use super::Elaborator; + +impl<'context> Elaborator<'context> { + pub(super) fn elaborate_expression(&mut self, expr: Expression) -> (ExprId, Type) { + let (hir_expr, typ) = match expr.kind { + ExpressionKind::Literal(literal) => self.elaborate_literal(literal, expr.span), + ExpressionKind::Block(block) => self.elaborate_block(block), + ExpressionKind::Prefix(prefix) => self.elaborate_prefix(*prefix), + ExpressionKind::Index(index) => self.elaborate_index(*index), + ExpressionKind::Call(call) => self.elaborate_call(*call, expr.span), + ExpressionKind::MethodCall(call) => self.elaborate_method_call(*call, expr.span), + ExpressionKind::Constructor(constructor) => self.elaborate_constructor(*constructor), + ExpressionKind::MemberAccess(access) => { + return self.elaborate_member_access(*access, expr.span) + } + ExpressionKind::Cast(cast) => self.elaborate_cast(*cast, expr.span), + ExpressionKind::Infix(infix) => return self.elaborate_infix(*infix, expr.span), + ExpressionKind::If(if_) => self.elaborate_if(*if_), + ExpressionKind::Variable(variable, generics) => { + let generics = generics.map(|option_inner| { + option_inner.into_iter().map(|generic| self.resolve_type(generic)).collect() + }); + return self.elaborate_variable(variable, generics); + } + ExpressionKind::Tuple(tuple) => self.elaborate_tuple(tuple), + ExpressionKind::Lambda(lambda) => self.elaborate_lambda(*lambda), + ExpressionKind::Parenthesized(expr) => return self.elaborate_expression(*expr), + ExpressionKind::Quote(quote) => self.elaborate_quote(quote), + ExpressionKind::Comptime(comptime) => { + return self.elaborate_comptime_block(comptime, expr.span) + } + ExpressionKind::Resolved(id) => return (id, self.interner.id_type(id)), + ExpressionKind::Error => (HirExpression::Error, Type::Error), + }; + let id = self.interner.push_expr(hir_expr); + self.interner.push_expr_location(id, expr.span, self.file); + self.interner.push_expr_type(id, typ.clone()); + (id, typ) + } + + pub(super) fn elaborate_block(&mut self, block: BlockExpression) -> (HirExpression, Type) { + let (block, typ) = self.elaborate_block_expression(block); + (HirExpression::Block(block), typ) + } + + fn elaborate_block_expression(&mut self, block: BlockExpression) -> (HirBlockExpression, Type) { + self.push_scope(); + let mut block_type = Type::Unit; + let mut statements = Vec::with_capacity(block.statements.len()); + + for (i, statement) in block.statements.into_iter().enumerate() { + let (id, stmt_type) = self.elaborate_statement(statement); + statements.push(id); + + if let HirStatement::Semi(expr) = self.interner.statement(&id) { + let inner_expr_type = self.interner.id_type(expr); + let span = self.interner.expr_span(&expr); + + self.unify(&inner_expr_type, &Type::Unit, || TypeCheckError::UnusedResultError { + expr_type: inner_expr_type.clone(), + expr_span: span, + }); + } + + if i + 1 == statements.len() { + block_type = stmt_type; + } + } + + self.pop_scope(); + (HirBlockExpression { is_unsafe: false, statements }, block_type) + } + + fn elaborate_literal(&mut self, literal: Literal, span: Span) -> (HirExpression, Type) { + use HirExpression::Literal as Lit; + match literal { + Literal::Unit => (Lit(HirLiteral::Unit), Type::Unit), + Literal::Bool(b) => (Lit(HirLiteral::Bool(b)), Type::Bool), + Literal::Integer(integer, sign) => { + let int = HirLiteral::Integer(integer, sign); + (Lit(int), self.polymorphic_integer_or_field()) + } + Literal::Str(str) | Literal::RawStr(str, _) => { + let len = Type::Constant(str.len() as u32); + (Lit(HirLiteral::Str(str)), Type::String(Box::new(len))) + } + Literal::FmtStr(str) => self.elaborate_fmt_string(str, span), + Literal::Array(array_literal) => { + self.elaborate_array_literal(array_literal, span, true) + } + Literal::Slice(array_literal) => { + self.elaborate_array_literal(array_literal, span, false) + } + } + } + + fn elaborate_array_literal( + &mut self, + array_literal: ArrayLiteral, + span: Span, + is_array: bool, + ) -> (HirExpression, Type) { + let (expr, elem_type, length) = match array_literal { + ArrayLiteral::Standard(elements) => { + let first_elem_type = self.interner.next_type_variable(); + let first_span = elements.first().map(|elem| elem.span).unwrap_or(span); + + let elements = vecmap(elements.into_iter().enumerate(), |(i, elem)| { + let span = elem.span; + let (elem_id, elem_type) = self.elaborate_expression(elem); + + self.unify(&elem_type, &first_elem_type, || { + TypeCheckError::NonHomogeneousArray { + first_span, + first_type: first_elem_type.to_string(), + first_index: 0, + second_span: span, + second_type: elem_type.to_string(), + second_index: i, + } + .add_context("elements in an array must have the same type") + }); + elem_id + }); + + let length = Type::Constant(elements.len() as u32); + (HirArrayLiteral::Standard(elements), first_elem_type, length) + } + ArrayLiteral::Repeated { repeated_element, length } => { + let span = length.span; + let length = + UnresolvedTypeExpression::from_expr(*length, span).unwrap_or_else(|error| { + self.push_err(ResolverError::ParserError(Box::new(error))); + UnresolvedTypeExpression::Constant(0, span) + }); + + let length = self.convert_expression_type(length); + let (repeated_element, elem_type) = self.elaborate_expression(*repeated_element); + + let length_clone = length.clone(); + (HirArrayLiteral::Repeated { repeated_element, length }, elem_type, length_clone) + } + }; + let constructor = if is_array { HirLiteral::Array } else { HirLiteral::Slice }; + let elem_type = Box::new(elem_type); + let typ = if is_array { + Type::Array(Box::new(length), elem_type) + } else { + Type::Slice(elem_type) + }; + (HirExpression::Literal(constructor(expr)), typ) + } + + fn elaborate_fmt_string(&mut self, str: String, call_expr_span: Span) -> (HirExpression, Type) { + let re = Regex::new(r"\{([a-zA-Z0-9_]+)\}") + .expect("ICE: an invalid regex pattern was used for checking format strings"); + + let mut fmt_str_idents = Vec::new(); + let mut capture_types = Vec::new(); + + for field in re.find_iter(&str) { + let matched_str = field.as_str(); + let ident_name = &matched_str[1..(matched_str.len() - 1)]; + + let scope_tree = self.scopes.current_scope_tree(); + let variable = scope_tree.find(ident_name); + if let Some((old_value, _)) = variable { + old_value.num_times_used += 1; + let ident = HirExpression::Ident(old_value.ident.clone(), None); + let expr_id = self.interner.push_expr(ident); + self.interner.push_expr_location(expr_id, call_expr_span, self.file); + let ident = old_value.ident.clone(); + let typ = self.type_check_variable(ident, expr_id, None); + self.interner.push_expr_type(expr_id, typ.clone()); + capture_types.push(typ); + fmt_str_idents.push(expr_id); + } else if ident_name.parse::().is_ok() { + self.push_err(ResolverError::NumericConstantInFormatString { + name: ident_name.to_owned(), + span: call_expr_span, + }); + } else { + self.push_err(ResolverError::VariableNotDeclared { + name: ident_name.to_owned(), + span: call_expr_span, + }); + } + } + + let len = Type::Constant(str.len() as u32); + let typ = Type::FmtString(Box::new(len), Box::new(Type::Tuple(capture_types))); + (HirExpression::Literal(HirLiteral::FmtStr(str, fmt_str_idents)), typ) + } + + fn elaborate_prefix(&mut self, prefix: PrefixExpression) -> (HirExpression, Type) { + let span = prefix.rhs.span; + let (rhs, rhs_type) = self.elaborate_expression(prefix.rhs); + let ret_type = self.type_check_prefix_operand(&prefix.operator, &rhs_type, span); + (HirExpression::Prefix(HirPrefixExpression { operator: prefix.operator, rhs }), ret_type) + } + + fn elaborate_index(&mut self, index_expr: IndexExpression) -> (HirExpression, Type) { + let span = index_expr.index.span; + let (index, index_type) = self.elaborate_expression(index_expr.index); + + let expected = self.polymorphic_integer_or_field(); + self.unify(&index_type, &expected, || TypeCheckError::TypeMismatch { + expected_typ: "an integer".to_owned(), + expr_typ: index_type.to_string(), + expr_span: span, + }); + + // When writing `a[i]`, if `a : &mut ...` then automatically dereference `a` as many + // times as needed to get the underlying array. + let lhs_span = index_expr.collection.span; + let (lhs, lhs_type) = self.elaborate_expression(index_expr.collection); + let (collection, lhs_type) = self.insert_auto_dereferences(lhs, lhs_type); + + let typ = match lhs_type.follow_bindings() { + // XXX: We can check the array bounds here also, but it may be better to constant fold first + // and have ConstId instead of ExprId for constants + Type::Array(_, base_type) => *base_type, + Type::Slice(base_type) => *base_type, + Type::Error => Type::Error, + typ => { + self.push_err(TypeCheckError::TypeMismatch { + expected_typ: "Array".to_owned(), + expr_typ: typ.to_string(), + expr_span: lhs_span, + }); + Type::Error + } + }; + + let expr = HirExpression::Index(HirIndexExpression { collection, index }); + (expr, typ) + } + + fn elaborate_call(&mut self, call: CallExpression, span: Span) -> (HirExpression, Type) { + let (func, func_type) = self.elaborate_expression(*call.func); + + let mut arguments = Vec::with_capacity(call.arguments.len()); + let args = vecmap(call.arguments, |arg| { + let span = arg.span; + let (arg, typ) = self.elaborate_expression(arg); + arguments.push(arg); + (typ, arg, span) + }); + + let location = Location::new(span, self.file); + let call = HirCallExpression { func, arguments, location }; + let typ = self.type_check_call(&call, func_type, args, span); + (HirExpression::Call(call), typ) + } + + fn elaborate_method_call( + &mut self, + method_call: MethodCallExpression, + span: Span, + ) -> (HirExpression, Type) { + let object_span = method_call.object.span; + let (mut object, mut object_type) = self.elaborate_expression(method_call.object); + object_type = object_type.follow_bindings(); + + let method_name = method_call.method_name.0.contents.as_str(); + match self.lookup_method(&object_type, method_name, span) { + Some(method_ref) => { + // Automatically add `&mut` if the method expects a mutable reference and + // the object is not already one. + let func_id = match &method_ref { + HirMethodReference::FuncId(func_id) => *func_id, + HirMethodReference::TraitMethodId(method_id, _) => { + let id = self.interner.trait_method_id(*method_id); + let definition = self.interner.definition(id); + let DefinitionKind::Function(func_id) = definition.kind else { + unreachable!("Expected trait function to be a DefinitionKind::Function") + }; + func_id + } + }; + + if func_id != FuncId::dummy_id() { + let function_type = self.interner.function_meta(&func_id).typ.clone(); + self.try_add_mutable_reference_to_object( + &function_type, + &mut object_type, + &mut object, + ); + } + + // These arguments will be given to the desugared function call. + // Compared to the method arguments, they also contain the object. + let mut function_args = Vec::with_capacity(method_call.arguments.len() + 1); + let mut arguments = Vec::with_capacity(method_call.arguments.len()); + + function_args.push((object_type.clone(), object, object_span)); + + for arg in method_call.arguments { + let span = arg.span; + let (arg, typ) = self.elaborate_expression(arg); + arguments.push(arg); + function_args.push((typ, arg, span)); + } + + let location = Location::new(span, self.file); + let method = method_call.method_name; + let generics = method_call.generics.map(|option_inner| { + option_inner.into_iter().map(|generic| self.resolve_type(generic)).collect() + }); + let turbofish_generics = generics.clone(); + let method_call = + HirMethodCallExpression { method, object, arguments, location, generics }; + + // Desugar the method call into a normal, resolved function call + // so that the backend doesn't need to worry about methods + // TODO: update object_type here? + let ((function_id, function_name), function_call) = method_call.into_function_call( + &method_ref, + object_type, + location, + self.interner, + ); + + let func_type = + self.type_check_variable(function_name, function_id, turbofish_generics); + + self.interner.push_expr_type(function_id, func_type.clone()); + + // Type check the new call now that it has been changed from a method call + // to a function call. This way we avoid duplicating code. + let typ = self.type_check_call(&function_call, func_type, function_args, span); + (HirExpression::Call(function_call), typ) + } + None => (HirExpression::Error, Type::Error), + } + } + + fn elaborate_constructor( + &mut self, + constructor: ConstructorExpression, + ) -> (HirExpression, Type) { + let span = constructor.type_name.span(); + + let (r#type, struct_generics) = if let Some(struct_id) = constructor.struct_type { + let typ = self.interner.get_struct(struct_id); + let generics = typ.borrow().instantiate(self.interner); + (typ, generics) + } else { + match self.lookup_type_or_error(constructor.type_name) { + Some(Type::Struct(r#type, struct_generics)) => (r#type, struct_generics), + Some(typ) => { + self.push_err(ResolverError::NonStructUsedInConstructor { typ, span }); + return (HirExpression::Error, Type::Error); + } + None => return (HirExpression::Error, Type::Error), + } + }; + + let struct_type = r#type.clone(); + let generics = struct_generics.clone(); + + let fields = constructor.fields; + let field_types = r#type.borrow().get_fields(&struct_generics); + let fields = + self.resolve_constructor_expr_fields(struct_type.clone(), field_types, fields, span); + let expr = HirExpression::Constructor(HirConstructorExpression { + fields, + r#type, + struct_generics, + }); + (expr, Type::Struct(struct_type, generics)) + } + + /// Resolve all the fields of a struct constructor expression. + /// Ensures all fields are present, none are repeated, and all + /// are part of the struct. + fn resolve_constructor_expr_fields( + &mut self, + struct_type: Shared, + field_types: Vec<(String, Type)>, + fields: Vec<(Ident, Expression)>, + span: Span, + ) -> Vec<(Ident, ExprId)> { + let mut ret = Vec::with_capacity(fields.len()); + let mut seen_fields = HashSet::default(); + let mut unseen_fields = struct_type.borrow().field_names(); + + for (field_name, field) in fields { + let expected_type = field_types.iter().find(|(name, _)| name == &field_name.0.contents); + let expected_type = expected_type.map(|(_, typ)| typ).unwrap_or(&Type::Error); + + let field_span = field.span; + let (resolved, field_type) = self.elaborate_expression(field); + + if unseen_fields.contains(&field_name) { + unseen_fields.remove(&field_name); + seen_fields.insert(field_name.clone()); + + self.unify_with_coercions(&field_type, expected_type, resolved, || { + TypeCheckError::TypeMismatch { + expected_typ: expected_type.to_string(), + expr_typ: field_type.to_string(), + expr_span: field_span, + } + }); + } else if seen_fields.contains(&field_name) { + // duplicate field + self.push_err(ResolverError::DuplicateField { field: field_name.clone() }); + } else { + // field not required by struct + self.push_err(ResolverError::NoSuchField { + field: field_name.clone(), + struct_definition: struct_type.borrow().name.clone(), + }); + } + + ret.push((field_name, resolved)); + } + + if !unseen_fields.is_empty() { + self.push_err(ResolverError::MissingFields { + span, + missing_fields: unseen_fields.into_iter().map(|field| field.to_string()).collect(), + struct_definition: struct_type.borrow().name.clone(), + }); + } + + ret + } + + fn elaborate_member_access( + &mut self, + access: MemberAccessExpression, + span: Span, + ) -> (ExprId, Type) { + let (lhs, lhs_type) = self.elaborate_expression(access.lhs); + let rhs = access.rhs; + // `is_offset` is only used when lhs is a reference and we want to return a reference to rhs + let access = HirMemberAccess { lhs, rhs, is_offset: false }; + let expr_id = self.intern_expr(HirExpression::MemberAccess(access.clone()), span); + let typ = self.type_check_member_access(access, expr_id, lhs_type, span); + self.interner.push_expr_type(expr_id, typ.clone()); + (expr_id, typ) + } + + pub fn intern_expr(&mut self, expr: HirExpression, span: Span) -> ExprId { + let id = self.interner.push_expr(expr); + self.interner.push_expr_location(id, span, self.file); + id + } + + fn elaborate_cast(&mut self, cast: CastExpression, span: Span) -> (HirExpression, Type) { + let (lhs, lhs_type) = self.elaborate_expression(cast.lhs); + let r#type = self.resolve_type(cast.r#type); + let result = self.check_cast(lhs_type, &r#type, span); + let expr = HirExpression::Cast(HirCastExpression { lhs, r#type }); + (expr, result) + } + + fn elaborate_infix(&mut self, infix: InfixExpression, span: Span) -> (ExprId, Type) { + let (lhs, lhs_type) = self.elaborate_expression(infix.lhs); + let (rhs, rhs_type) = self.elaborate_expression(infix.rhs); + let trait_id = self.interner.get_operator_trait_method(infix.operator.contents); + + let operator = HirBinaryOp::new(infix.operator, self.file); + let expr = HirExpression::Infix(HirInfixExpression { + lhs, + operator, + trait_method_id: trait_id, + rhs, + }); + + let expr_id = self.interner.push_expr(expr); + self.interner.push_expr_location(expr_id, span, self.file); + + let typ = match self.infix_operand_type_rules(&lhs_type, &operator, &rhs_type, span) { + Ok((typ, use_impl)) => { + if use_impl { + // Delay checking the trait constraint until the end of the function. + // Checking it now could bind an unbound type variable to any type + // that implements the trait. + let constraint = TraitConstraint { + typ: lhs_type.clone(), + trait_id: trait_id.trait_id, + trait_generics: Vec::new(), + }; + self.trait_constraints.push((constraint, expr_id)); + self.type_check_operator_method(expr_id, trait_id, &lhs_type, span); + } + typ + } + Err(error) => { + self.push_err(error); + Type::Error + } + }; + + self.interner.push_expr_type(expr_id, typ.clone()); + (expr_id, typ) + } + + fn elaborate_if(&mut self, if_expr: IfExpression) -> (HirExpression, Type) { + let expr_span = if_expr.condition.span; + let (condition, cond_type) = self.elaborate_expression(if_expr.condition); + let (consequence, mut ret_type) = self.elaborate_expression(if_expr.consequence); + + self.unify(&cond_type, &Type::Bool, || TypeCheckError::TypeMismatch { + expected_typ: Type::Bool.to_string(), + expr_typ: cond_type.to_string(), + expr_span, + }); + + let alternative = if_expr.alternative.map(|alternative| { + let expr_span = alternative.span; + let (else_, else_type) = self.elaborate_expression(alternative); + + self.unify(&ret_type, &else_type, || { + let err = TypeCheckError::TypeMismatch { + expected_typ: ret_type.to_string(), + expr_typ: else_type.to_string(), + expr_span, + }; + + let context = if ret_type == Type::Unit { + "Are you missing a semicolon at the end of your 'else' branch?" + } else if else_type == Type::Unit { + "Are you missing a semicolon at the end of the first block of this 'if'?" + } else { + "Expected the types of both if branches to be equal" + }; + + err.add_context(context) + }); + else_ + }); + + if alternative.is_none() { + ret_type = Type::Unit; + } + + let if_expr = HirIfExpression { condition, consequence, alternative }; + (HirExpression::If(if_expr), ret_type) + } + + fn elaborate_tuple(&mut self, tuple: Vec) -> (HirExpression, Type) { + let mut element_ids = Vec::with_capacity(tuple.len()); + let mut element_types = Vec::with_capacity(tuple.len()); + + for element in tuple { + let (id, typ) = self.elaborate_expression(element); + element_ids.push(id); + element_types.push(typ); + } + + (HirExpression::Tuple(element_ids), Type::Tuple(element_types)) + } + + fn elaborate_lambda(&mut self, lambda: Lambda) -> (HirExpression, Type) { + self.push_scope(); + let scope_index = self.scopes.current_scope_index(); + + self.lambda_stack.push(LambdaContext { captures: Vec::new(), scope_index }); + + let mut arg_types = Vec::with_capacity(lambda.parameters.len()); + let parameters = vecmap(lambda.parameters, |(pattern, typ)| { + let parameter = DefinitionKind::Local(None); + let typ = self.resolve_inferred_type(typ); + arg_types.push(typ.clone()); + (self.elaborate_pattern(pattern, typ.clone(), parameter), typ) + }); + + let return_type = self.resolve_inferred_type(lambda.return_type); + let body_span = lambda.body.span; + let (body, body_type) = self.elaborate_expression(lambda.body); + + let lambda_context = self.lambda_stack.pop().unwrap(); + self.pop_scope(); + + self.unify(&body_type, &return_type, || TypeCheckError::TypeMismatch { + expected_typ: return_type.to_string(), + expr_typ: body_type.to_string(), + expr_span: body_span, + }); + + let captured_vars = vecmap(&lambda_context.captures, |capture| { + self.interner.definition_type(capture.ident.id) + }); + + let env_type = + if captured_vars.is_empty() { Type::Unit } else { Type::Tuple(captured_vars) }; + + let captures = lambda_context.captures; + let expr = HirExpression::Lambda(HirLambda { parameters, return_type, body, captures }); + (expr, Type::Function(arg_types, Box::new(body_type), Box::new(env_type))) + } + + fn elaborate_quote(&mut self, block: BlockExpression) -> (HirExpression, Type) { + (HirExpression::Quote(block), Type::Code) + } + + fn elaborate_comptime_block(&mut self, block: BlockExpression, span: Span) -> (ExprId, Type) { + let (block, _typ) = self.elaborate_block_expression(block); + let mut interpreter = Interpreter::new(self.interner, &mut self.comptime_scopes); + let value = interpreter.evaluate_block(block); + self.inline_comptime_value(value, span) + } + + pub(super) fn inline_comptime_value( + &mut self, + value: Result, + span: Span, + ) -> (ExprId, Type) { + let make_error = |this: &mut Self, error: InterpreterError| { + this.errors.push(error.into_compilation_error_pair()); + let error = this.interner.push_expr(HirExpression::Error); + this.interner.push_expr_location(error, span, this.file); + (error, Type::Error) + }; + + let value = match value { + Ok(value) => value, + Err(error) => return make_error(self, error), + }; + + let location = Location::new(span, self.file); + match value.into_expression(self.interner, location) { + Ok(new_expr) => self.elaborate_expression(new_expr), + Err(error) => make_error(self, error), + } + } +} diff --git a/compiler/noirc_frontend/src/elaborator/lints.rs b/compiler/noirc_frontend/src/elaborator/lints.rs new file mode 100644 index 00000000000..4859ac5f97c --- /dev/null +++ b/compiler/noirc_frontend/src/elaborator/lints.rs @@ -0,0 +1,255 @@ +use crate::{ + ast::FunctionKind, + graph::CrateId, + hir::{ + resolution::errors::{PubPosition, ResolverError}, + type_check::TypeCheckError, + }, + hir_def::expr::HirIdent, + macros_api::{ + HirExpression, HirLiteral, NodeInterner, NoirFunction, UnaryOp, UnresolvedTypeData, + Visibility, + }, + node_interner::{DefinitionKind, ExprId, FuncId}, + Type, +}; +use acvm::AcirField; + +use noirc_errors::Span; + +pub(super) fn deprecated_function(interner: &NodeInterner, expr: ExprId) -> Option { + let HirExpression::Ident(HirIdent { location, id, impl_kind: _ }, _) = + interner.expression(&expr) + else { + return None; + }; + + let Some(DefinitionKind::Function(func_id)) = interner.try_definition(id).map(|def| &def.kind) + else { + return None; + }; + + let attributes = interner.function_attributes(func_id); + attributes.get_deprecated_note().map(|note| TypeCheckError::CallDeprecated { + name: interner.definition_name(id).to_string(), + note, + span: location.span, + }) +} + +/// Inline attributes are only relevant for constrained functions +/// as all unconstrained functions are not inlined and so +/// associated attributes are disallowed. +pub(super) fn inlining_attributes(func: &NoirFunction) -> Option { + if func.def.is_unconstrained { + let attributes = func.attributes().clone(); + + if attributes.is_no_predicates() { + Some(ResolverError::NoPredicatesAttributeOnUnconstrained { + ident: func.name_ident().clone(), + }) + } else if attributes.is_foldable() { + Some(ResolverError::FoldAttributeOnUnconstrained { ident: func.name_ident().clone() }) + } else { + None + } + } else { + None + } +} + +/// Attempting to define new low level (`#[builtin]` or `#[foreign]`) functions outside of the stdlib is disallowed. +pub(super) fn low_level_function_outside_stdlib( + func: &NoirFunction, + crate_id: CrateId, +) -> Option { + let is_low_level_function = + func.attributes().function.as_ref().map_or(false, |func| func.is_low_level()); + if !crate_id.is_stdlib() && is_low_level_function { + Some(ResolverError::LowLevelFunctionOutsideOfStdlib { ident: func.name_ident().clone() }) + } else { + None + } +} + +/// Oracle definitions (functions with the `#[oracle]` attribute) must be marked as unconstrained. +pub(super) fn oracle_not_marked_unconstrained(func: &NoirFunction) -> Option { + let is_oracle_function = + func.attributes().function.as_ref().map_or(false, |func| func.is_oracle()); + if is_oracle_function && !func.def.is_unconstrained { + Some(ResolverError::OracleMarkedAsConstrained { ident: func.name_ident().clone() }) + } else { + None + } +} + +/// Oracle functions may not be called by constrained functions directly. +/// +/// In order for a constrained function to call an oracle it must first call through an unconstrained function. +pub(super) fn oracle_called_from_constrained_function( + interner: &NodeInterner, + called_func: &FuncId, + calling_from_constrained_runtime: bool, + span: Span, +) -> Option { + if !calling_from_constrained_runtime { + return None; + } + + let function_attributes = interner.function_attributes(called_func); + let is_oracle_call = + function_attributes.function.as_ref().map_or(false, |func| func.is_oracle()); + if is_oracle_call { + Some(ResolverError::UnconstrainedOracleReturnToConstrained { span }) + } else { + None + } +} + +/// `pub` is required on return types for entry point functions +pub(super) fn missing_pub(func: &NoirFunction, is_entry_point: bool) -> Option { + if is_entry_point + && func.return_type().typ != UnresolvedTypeData::Unit + && func.def.return_visibility == Visibility::Private + { + Some(ResolverError::NecessaryPub { ident: func.name_ident().clone() }) + } else { + None + } +} + +/// `#[recursive]` attribute is only allowed for entry point functions +pub(super) fn recursive_non_entrypoint_function( + func: &NoirFunction, + is_entry_point: bool, +) -> Option { + if !is_entry_point && func.kind == FunctionKind::Recursive { + Some(ResolverError::MisplacedRecursiveAttribute { ident: func.name_ident().clone() }) + } else { + None + } +} + +/// Test functions cannot have arguments in order to be executable. +pub(super) fn test_function_with_args(func: &NoirFunction) -> Option { + if func.attributes().is_test_function() && !func.parameters().is_empty() { + Some(ResolverError::TestFunctionHasParameters { span: func.name_ident().span() }) + } else { + None + } +} + +/// Check that we are not passing a mutable reference from a constrained runtime to an unconstrained runtime. +pub(super) fn unconstrained_function_args( + function_args: &[(Type, ExprId, Span)], +) -> Vec { + function_args + .iter() + .filter_map(|(typ, _, span)| { + if type_contains_mutable_reference(typ) { + Some(TypeCheckError::ConstrainedReferenceToUnconstrained { span: *span }) + } else { + None + } + }) + .collect() +} + +/// Check that we are not passing a slice from an unconstrained runtime to a constrained runtime. +pub(super) fn unconstrained_function_return( + return_type: &Type, + span: Span, +) -> Option { + if return_type.contains_slice() { + Some(TypeCheckError::UnconstrainedSliceReturnToConstrained { span }) + } else if type_contains_mutable_reference(return_type) { + Some(TypeCheckError::UnconstrainedReferenceToConstrained { span }) + } else { + None + } +} + +fn type_contains_mutable_reference(typ: &Type) -> bool { + matches!(&typ.follow_bindings(), Type::MutableReference(_)) +} + +/// Only entrypoint functions require a `pub` visibility modifier applied to their return types. +/// +/// Application of `pub` to other functions is not meaningful and is a mistake. +pub(super) fn unnecessary_pub_return( + func: &NoirFunction, + is_entry_point: bool, +) -> Option { + if !is_entry_point && func.def.return_visibility == Visibility::Public { + Some(ResolverError::UnnecessaryPub { + ident: func.name_ident().clone(), + position: PubPosition::ReturnType, + }) + } else { + None + } +} + +/// Only arguments to entrypoint functions may have a non-private visibility modifier applied to them. +/// +/// Other functions are disallowed from declaring the visibility of their arguments. +pub(super) fn unnecessary_pub_argument( + func: &NoirFunction, + arg_visibility: Visibility, + is_entry_point: bool, +) -> Option { + if arg_visibility == Visibility::Public && !is_entry_point { + Some(ResolverError::UnnecessaryPub { + ident: func.name_ident().clone(), + position: PubPosition::Parameter, + }) + } else { + None + } +} + +/// Check if an assignment is overflowing with respect to `annotated_type` +/// in a declaration statement where `annotated_type` is an unsigned integer +pub(crate) fn overflowing_uint( + interner: &NodeInterner, + rhs_expr: &ExprId, + annotated_type: &Type, +) -> Vec { + let expr = interner.expression(rhs_expr); + let span = interner.expr_span(rhs_expr); + + let mut errors = Vec::with_capacity(2); + match expr { + HirExpression::Literal(HirLiteral::Integer(value, false)) => { + let v = value.to_u128(); + if let Type::Integer(_, bit_count) = annotated_type { + let bit_count: u32 = (*bit_count).into(); + let max = 1 << bit_count; + if v >= max { + errors.push(TypeCheckError::OverflowingAssignment { + expr: value, + ty: annotated_type.clone(), + range: format!("0..={}", max - 1), + span, + }); + }; + }; + } + HirExpression::Prefix(expr) => { + overflowing_uint(interner, &expr.rhs, annotated_type); + if expr.operator == UnaryOp::Minus { + errors.push(TypeCheckError::InvalidUnaryOp { + kind: "annotated_type".to_string(), + span, + }); + } + } + HirExpression::Infix(expr) => { + errors.extend(overflowing_uint(interner, &expr.lhs, annotated_type)); + errors.extend(overflowing_uint(interner, &expr.rhs, annotated_type)); + } + _ => {} + } + + errors +} diff --git a/compiler/noirc_frontend/src/elaborator/mod.rs b/compiler/noirc_frontend/src/elaborator/mod.rs new file mode 100644 index 00000000000..f703127231f --- /dev/null +++ b/compiler/noirc_frontend/src/elaborator/mod.rs @@ -0,0 +1,1236 @@ +use std::{ + collections::{BTreeMap, BTreeSet}, + rc::Rc, +}; + +use crate::{ + ast::{FunctionKind, UnresolvedTraitConstraint}, + hir::{ + comptime::{self, Interpreter}, + def_collector::{ + dc_crate::{ + filter_literal_globals, CompilationError, ImplMap, UnresolvedGlobal, + UnresolvedStruct, UnresolvedTypeAlias, + }, + errors::DuplicateType, + }, + resolution::{errors::ResolverError, path_resolver::PathResolver, resolver::LambdaContext}, + scope::ScopeForest as GenericScopeForest, + type_check::{check_trait_impl_method_matches_declaration, TypeCheckError}, + }, + hir_def::{ + expr::HirIdent, + function::{FunctionBody, Parameters}, + traits::TraitConstraint, + }, + macros_api::{ + BlockExpression, Ident, NodeInterner, NoirFunction, NoirStruct, Pattern, + SecondaryAttribute, StructId, + }, + node_interner::{ + DefinitionId, DefinitionKind, DependencyId, ExprId, FuncId, GlobalId, TraitId, TypeAliasId, + }, + Shared, Type, TypeVariable, +}; +use crate::{ + ast::{TraitBound, UnresolvedGenerics}, + graph::CrateId, + hir::{ + def_collector::{dc_crate::CollectedItems, errors::DefCollectorErrorKind}, + def_map::{LocalModuleId, ModuleDefId, ModuleId, MAIN_FUNCTION}, + resolution::{import::PathResolution, path_resolver::StandardPathResolver}, + Context, + }, + hir_def::function::{FuncMeta, HirFunction}, + macros_api::{Param, Path, UnresolvedType, UnresolvedTypeData}, + node_interner::TraitImplId, + Generics, +}; +use crate::{ + hir::{ + def_collector::dc_crate::{UnresolvedFunctions, UnresolvedTraitImpl}, + def_map::{CrateDefMap, ModuleData}, + }, + hir_def::traits::TraitImpl, + macros_api::ItemVisibility, +}; + +mod expressions; +mod lints; +mod patterns; +mod scope; +mod statements; +mod traits; +mod types; + +use fm::FileId; +use iter_extended::vecmap; +use noirc_errors::{Location, Span}; +use rustc_hash::{FxHashMap as HashMap, FxHashSet as HashSet}; + +/// ResolverMetas are tagged onto each definition to track how many times they are used +#[derive(Debug, PartialEq, Eq)] +pub struct ResolverMeta { + num_times_used: usize, + ident: HirIdent, + warn_if_unused: bool, +} + +type ScopeForest = GenericScopeForest; + +pub struct Elaborator<'context> { + scopes: ScopeForest, + + errors: Vec<(CompilationError, FileId)>, + + interner: &'context mut NodeInterner, + + def_maps: &'context mut BTreeMap, + + file: FileId, + + in_unconstrained_fn: bool, + nested_loops: usize, + + /// True if the current module is a contract. + /// This is usually determined by self.path_resolver.module_id(), but it can + /// be overridden for impls. Impls are an odd case since the methods within resolve + /// as if they're in the parent module, but should be placed in a child module. + /// Since they should be within a child module, in_contract is manually set to false + /// for these so we can still resolve them in the parent module without them being in a contract. + in_contract: bool, + + /// Contains a mapping of the current struct or functions's generics to + /// unique type variables if we're resolving a struct. Empty otherwise. + /// This is a Vec rather than a map to preserve the order a functions generics + /// were declared in. + generics: Vec<(Rc, TypeVariable, Span)>, + + /// When resolving lambda expressions, we need to keep track of the variables + /// that are captured. We do this in order to create the hidden environment + /// parameter for the lambda function. + lambda_stack: Vec, + + /// Set to the current type if we're resolving an impl + self_type: Option, + + /// The current dependency item we're resolving. + /// Used to link items to their dependencies in the dependency graph + current_item: 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, + + trait_id: Option, + + /// In-resolution names + /// + /// This needs to be a set because we can have multiple in-resolution + /// names when resolving structs that are declared in reverse order of their + /// dependencies, such as in the following case: + /// + /// ``` + /// struct Wrapper { + /// value: Wrapped + /// } + /// struct Wrapped { + /// } + /// ``` + resolving_ids: BTreeSet, + + /// Each constraint in the `where` clause of the function currently being resolved. + trait_bounds: Vec, + + current_function: Option, + + /// All type variables created in the current function. + /// This map is used to default any integer type variables at the end of + /// a function (before checking trait constraints) if a type wasn't already chosen. + type_variables: Vec, + + /// 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)>, + + /// The current module this elaborator is in. + /// Initially empty, it is set whenever a new top-level item is resolved. + local_module: LocalModuleId, + + crate_id: CrateId, + + /// Each value currently in scope in the comptime interpreter. + /// Each element of the Vec represents a scope with every scope together making + /// up all currently visible definitions. The first scope is always the global scope. + comptime_scopes: Vec>, + + /// These are the globals that have yet to be elaborated. + /// This map is used to lazily evaluate these globals if they're encountered before + /// they are elaborated (e.g. in a function's type or another global's RHS). + unresolved_globals: BTreeMap, +} + +impl<'context> Elaborator<'context> { + pub fn new(context: &'context mut Context, crate_id: CrateId) -> Self { + Self { + scopes: ScopeForest::default(), + errors: Vec::new(), + interner: &mut context.def_interner, + def_maps: &mut context.def_maps, + file: FileId::dummy(), + in_unconstrained_fn: false, + nested_loops: 0, + in_contract: false, + generics: Vec::new(), + lambda_stack: Vec::new(), + self_type: None, + current_item: None, + trait_id: None, + local_module: LocalModuleId::dummy_id(), + crate_id, + resolving_ids: BTreeSet::new(), + trait_bounds: Vec::new(), + current_function: None, + type_variables: Vec::new(), + trait_constraints: Vec::new(), + current_trait_impl: None, + comptime_scopes: vec![HashMap::default()], + unresolved_globals: BTreeMap::new(), + } + } + + pub fn elaborate( + context: &'context mut Context, + crate_id: CrateId, + mut items: CollectedItems, + ) -> Vec<(CompilationError, FileId)> { + let mut this = Self::new(context, crate_id); + + // We must first resolve and intern the globals before we can resolve any stmts inside each function. + // Each function uses its own resolver with a newly created ScopeForest, and must be resolved again to be within a function's scope + // + // Additionally, we must resolve integer globals before structs since structs may refer to + // the values of integer globals as numeric generics. + let (literal_globals, non_literal_globals) = filter_literal_globals(items.globals); + for global in non_literal_globals { + this.unresolved_globals.insert(global.global_id, global); + } + + for global in literal_globals { + this.elaborate_global(global); + } + + for (alias_id, alias) in items.type_aliases { + this.define_type_alias(alias_id, alias); + } + + this.define_function_metas(&mut items.functions, &mut items.impls, &mut items.trait_impls); + this.collect_traits(items.traits); + + // Must resolve structs before we resolve globals. + this.collect_struct_definitions(items.types); + + // Bind trait impls to their trait. Collect trait functions, that have a + // default implementation, which hasn't been overridden. + for trait_impl in &mut items.trait_impls { + this.collect_trait_impl(trait_impl); + } + + // 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 during def collection 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. + for ((_self_type, module), impls) in &mut items.impls { + this.collect_impls(*module, impls); + } + + // We must wait to resolve non-literal globals until after we resolve structs since struct + // globals will need to reference the struct type they're initialized to to ensure they are valid. + while let Some((_, global)) = this.unresolved_globals.pop_first() { + this.elaborate_global(global); + } + + for functions in items.functions { + this.elaborate_functions(functions); + } + + for impls in items.impls.into_values() { + this.elaborate_impls(impls); + } + + for trait_impl in items.trait_impls { + this.elaborate_trait_impl(trait_impl); + } + + let cycle_errors = this.interner.check_for_dependency_cycles(); + this.errors.extend(cycle_errors); + this.errors + } + + /// Runs `f` and if it modifies `self.generics`, `self.generics` is truncated + /// back to the previous length. + fn recover_generics(&mut self, f: impl FnOnce(&mut Self) -> T) -> T { + let generics_count = self.generics.len(); + let ret = f(self); + self.generics.truncate(generics_count); + ret + } + + fn elaborate_functions(&mut self, functions: UnresolvedFunctions) { + self.file = functions.file_id; + self.trait_id = functions.trait_id; // TODO: Resolve? + self.self_type = functions.self_type; + + for (local_module, id, _) in functions.functions { + self.local_module = local_module; + self.recover_generics(|this| this.elaborate_function(id)); + } + + self.self_type = None; + self.trait_id = None; + } + + fn elaborate_function(&mut self, id: FuncId) { + let func_meta = self.interner.func_meta.get_mut(&id); + let func_meta = + func_meta.expect("FuncMetas should be declared before a function is elaborated"); + + let (kind, body, body_span) = match func_meta.take_body() { + FunctionBody::Unresolved(kind, body, span) => (kind, body, span), + FunctionBody::Resolved => return, + // Do not error for the still-resolving case. If there is a dependency cycle, + // the dependency cycle check will find it later on. + FunctionBody::Resolving => return, + }; + + let old_function = std::mem::replace(&mut self.current_function, Some(id)); + + // Without this, impl methods can accidentally be placed in contracts. See #3254 + if self.self_type.is_some() { + self.in_contract = false; + } + + self.scopes.start_function(); + let old_item = std::mem::replace(&mut self.current_item, Some(DependencyId::Function(id))); + + let func_meta = func_meta.clone(); + + self.trait_bounds = func_meta.trait_constraints.clone(); + + if self.interner.function_modifiers(&id).is_unconstrained { + self.in_unconstrained_fn = true; + } + + // The DefinitionIds for each parameter were already created in define_function_meta + // so we need to reintroduce the same IDs into scope here. + for parameter in &func_meta.parameter_idents { + let name = self.interner.definition_name(parameter.id).to_owned(); + self.add_existing_variable_to_scope(name, parameter.clone()); + } + + self.generics = func_meta.all_generics.clone(); + self.declare_numeric_generics(&func_meta.parameters, func_meta.return_type()); + self.add_trait_constraints_to_scope(&func_meta); + + let (hir_func, body_type) = match kind { + FunctionKind::Builtin | FunctionKind::LowLevel | FunctionKind::Oracle => { + (HirFunction::empty(), Type::Error) + } + FunctionKind::Normal | FunctionKind::Recursive => { + let (block, body_type) = self.elaborate_block(body); + let expr_id = self.intern_expr(block, body_span); + self.interner.push_expr_type(expr_id, body_type.clone()); + (HirFunction::unchecked_from_expr(expr_id), body_type) + } + }; + + // Don't verify the return type for builtin functions & trait function declarations + if !func_meta.is_stub() { + self.type_check_function_body(body_type, &func_meta, hir_func.as_expr()); + } + + // Default any type variables that still need defaulting. + // This is done before trait impl search since leaving them bindable can lead to errors + // when multiple impls are available. Instead we default first to choose the Field or u64 impl. + for typ in &self.type_variables { + if let Type::TypeVariable(variable, kind) = typ.follow_bindings() { + let msg = "TypeChecker should only track defaultable type vars"; + variable.bind(kind.default_type().expect(msg)); + } + } + + // Verify any remaining trait constraints arising from the function body + for (mut constraint, expr_id) in std::mem::take(&mut self.trait_constraints) { + let span = self.interner.expr_span(&expr_id); + + if matches!(&constraint.typ, Type::MutableReference(_)) { + let (_, dereferenced_typ) = + self.insert_auto_dereferences(expr_id, constraint.typ.clone()); + constraint.typ = dereferenced_typ; + } + + self.verify_trait_constraint( + &constraint.typ, + constraint.trait_id, + &constraint.trait_generics, + expr_id, + span, + ); + } + + // Now remove all the `where` clause constraints we added + for constraint in &func_meta.trait_constraints { + self.interner.remove_assumed_trait_implementations_for_trait(constraint.trait_id); + } + + let func_scope_tree = self.scopes.end_function(); + + // The arguments to low-level and oracle functions are always unused so we do not produce warnings for them. + if !func_meta.is_stub() { + self.check_for_unused_variables_in_scope_tree(func_scope_tree); + } + + let meta = self + .interner + .func_meta + .get_mut(&id) + .expect("FuncMetas should be declared before a function is elaborated"); + + meta.function_body = FunctionBody::Resolved; + + self.trait_bounds.clear(); + self.in_unconstrained_fn = false; + self.interner.update_fn(id, hir_func); + self.current_function = old_function; + self.current_item = old_item; + } + + /// This turns function parameters of the form: + /// `fn foo(x: impl Bar)` + /// + /// into + /// `fn foo(x: T0_impl_Bar) where T0_impl_Bar: Bar` + /// although the fresh type variable is not named internally. + fn desugar_impl_trait_arg( + &mut self, + trait_path: Path, + trait_generics: Vec, + generics: &mut Vec, + trait_constraints: &mut Vec, + ) -> Type { + let new_generic_id = self.interner.next_type_variable_id(); + let new_generic = TypeVariable::unbound(new_generic_id); + generics.push(new_generic.clone()); + + let name = format!("impl {trait_path}"); + let generic_type = Type::NamedGeneric(new_generic, Rc::new(name)); + let trait_bound = TraitBound { trait_path, trait_id: None, trait_generics }; + + if let Some(new_constraint) = self.resolve_trait_bound(&trait_bound, generic_type.clone()) { + trait_constraints.push(new_constraint); + } + + generic_type + } + + /// Add the given generics to scope. + /// Each generic will have a fresh Shared associated with it. + pub fn add_generics(&mut self, generics: &UnresolvedGenerics) -> Generics { + vecmap(generics, |generic| { + // Map the generic to a fresh type variable + let id = self.interner.next_type_variable_id(); + let typevar = TypeVariable::unbound(id); + let span = generic.0.span(); + + // Check for name collisions of this generic + let name = Rc::new(generic.0.contents.clone()); + + if let Some((_, _, first_span)) = self.find_generic(&name) { + self.push_err(ResolverError::DuplicateDefinition { + name: generic.0.contents.clone(), + first_span: *first_span, + second_span: span, + }); + } else { + self.generics.push((name, typevar.clone(), span)); + } + + typevar + }) + } + + fn push_err(&mut self, error: impl Into) { + self.errors.push((error.into(), self.file)); + } + + fn run_lint(&mut self, lint: impl Fn(&Elaborator) -> Option) { + if let Some(error) = lint(self) { + self.push_err(error); + } + } + + fn resolve_trait_by_path(&mut self, path: Path) -> Option { + let path_resolver = StandardPathResolver::new(self.module_id()); + + let error = match path_resolver.resolve(self.def_maps, path.clone()) { + Ok(PathResolution { module_def_id: ModuleDefId::TraitId(trait_id), error }) => { + if let Some(error) = error { + self.push_err(error); + } + return Some(trait_id); + } + Ok(_) => DefCollectorErrorKind::NotATrait { not_a_trait_name: path }, + Err(_) => DefCollectorErrorKind::TraitNotFound { trait_path: path }, + }; + self.push_err(error); + None + } + + /// TODO: This is currently only respected for generic free functions + /// there's a bunch of other places where trait constraints can pop up + fn resolve_trait_constraints( + &mut self, + where_clause: &[UnresolvedTraitConstraint], + ) -> Vec { + where_clause + .iter() + .filter_map(|constraint| self.resolve_trait_constraint(constraint)) + .collect() + } + + pub fn resolve_trait_constraint( + &mut self, + constraint: &UnresolvedTraitConstraint, + ) -> Option { + let typ = self.resolve_type(constraint.typ.clone()); + self.resolve_trait_bound(&constraint.trait_bound, typ) + } + + fn resolve_trait_bound(&mut self, bound: &TraitBound, typ: Type) -> Option { + let trait_generics = vecmap(&bound.trait_generics, |typ| self.resolve_type(typ.clone())); + + let span = bound.trait_path.span(); + let the_trait = self.lookup_trait_or_error(bound.trait_path.clone())?; + let trait_id = the_trait.id; + + let expected_generics = the_trait.generics.len(); + let actual_generics = trait_generics.len(); + + if actual_generics != expected_generics { + let item_name = the_trait.name.to_string(); + self.push_err(ResolverError::IncorrectGenericCount { + span, + item_name, + actual: actual_generics, + expected: expected_generics, + }); + } + + Some(TraitConstraint { typ, trait_id, trait_generics }) + } + + /// Extract metadata from a NoirFunction + /// to be used in analysis and intern the function parameters + /// Prerequisite: any implicit generics, including any generics from the impl, + /// have already been added to scope via `self.add_generics`. + fn define_function_meta( + &mut self, + func: &mut NoirFunction, + func_id: FuncId, + is_trait_function: bool, + ) { + self.current_function = Some(func_id); + + // Without this, impl methods can accidentally be placed in contracts. See #3254 + if self.self_type.is_some() { + self.in_contract = false; + } + + self.scopes.start_function(); + self.current_item = Some(DependencyId::Function(func_id)); + + let location = Location::new(func.name_ident().span(), self.file); + let id = self.interner.function_definition_id(func_id); + let name_ident = HirIdent::non_trait_method(id, location); + + let is_entry_point = self.is_entry_point_function(func); + + self.run_lint(|_| lints::inlining_attributes(func).map(Into::into)); + self.run_lint(|_| lints::missing_pub(func, is_entry_point).map(Into::into)); + self.run_lint(|elaborator| { + lints::unnecessary_pub_return(func, elaborator.pub_allowed(func)).map(Into::into) + }); + self.run_lint(|_| lints::oracle_not_marked_unconstrained(func).map(Into::into)); + self.run_lint(|elaborator| { + lints::low_level_function_outside_stdlib(func, elaborator.crate_id).map(Into::into) + }); + self.run_lint(|_| lints::test_function_with_args(func).map(Into::into)); + self.run_lint(|_| { + lints::recursive_non_entrypoint_function(func, is_entry_point).map(Into::into) + }); + + // Both the #[fold] and #[no_predicates] alter a function's inline type and code generation in similar ways. + // In certain cases such as type checking (for which the following flag will be used) both attributes + // indicate we should code generate in the same way. Thus, we unify the attributes into one flag here. + let has_no_predicates_attribute = func.attributes().is_no_predicates(); + let should_fold = func.attributes().is_foldable(); + let has_inline_attribute = has_no_predicates_attribute || should_fold; + let is_pub_allowed = self.pub_allowed(func); + self.add_generics(&func.def.generics); + + let mut trait_constraints = self.resolve_trait_constraints(&func.def.where_clause); + + let mut generics = vecmap(&self.generics, |(_, typevar, _)| typevar.clone()); + let mut parameters = Vec::new(); + let mut parameter_types = Vec::new(); + let mut parameter_idents = Vec::new(); + + for Param { visibility, pattern, typ, span: _ } in func.parameters().iter().cloned() { + self.run_lint(|_| { + lints::unnecessary_pub_argument(func, visibility, is_pub_allowed).map(Into::into) + }); + + let type_span = typ.span.unwrap_or_else(|| pattern.span()); + + let typ = match typ.typ { + UnresolvedTypeData::TraitAsType(path, args) => { + self.desugar_impl_trait_arg(path, args, &mut generics, &mut trait_constraints) + } + _ => self.resolve_type_inner(typ), + }; + + self.check_if_type_is_valid_for_program_input( + &typ, + is_entry_point, + has_inline_attribute, + type_span, + ); + let pattern = self.elaborate_pattern_and_store_ids( + pattern, + typ.clone(), + DefinitionKind::Local(None), + &mut parameter_idents, + None, + ); + + parameters.push((pattern, typ.clone(), visibility)); + parameter_types.push(typ); + } + + let return_type = Box::new(self.resolve_type(func.return_type())); + + let mut typ = Type::Function(parameter_types, return_type, Box::new(Type::Unit)); + + if !generics.is_empty() { + typ = Type::Forall(generics, Box::new(typ)); + } + + self.interner.push_definition_type(name_ident.id, typ.clone()); + + let direct_generics = func.def.generics.iter(); + let direct_generics = direct_generics + .filter_map(|generic| self.find_generic(&generic.0.contents)) + .map(|(name, typevar, _span)| (name.clone(), typevar.clone())) + .collect(); + + let statements = std::mem::take(&mut func.def.body.statements); + let body = BlockExpression { is_unsafe: false, statements }; + + let meta = FuncMeta { + name: name_ident, + kind: func.kind, + location, + typ, + direct_generics, + all_generics: self.generics.clone(), + trait_impl: self.current_trait_impl, + parameters: parameters.into(), + parameter_idents, + return_type: func.def.return_type.clone(), + return_visibility: func.def.return_visibility, + has_body: !func.def.body.is_empty(), + trait_constraints, + is_entry_point, + is_trait_function, + has_inline_attribute, + function_body: FunctionBody::Unresolved(func.kind, body, func.def.span), + }; + + self.interner.push_fn_meta(meta, func_id); + self.current_function = None; + self.scopes.end_function(); + self.current_item = None; + } + + /// Only sized types are valid to be used as main's parameters or the parameters to a contract + /// function. If the given type is not sized (e.g. contains a slice or NamedGeneric type), an + /// error is issued. + fn check_if_type_is_valid_for_program_input( + &mut self, + typ: &Type, + is_entry_point: bool, + has_inline_attribute: bool, + span: Span, + ) { + if (is_entry_point && !typ.is_valid_for_program_input()) + || (has_inline_attribute && !typ.is_valid_non_inlined_function_input()) + { + self.push_err(TypeCheckError::InvalidTypeForEntryPoint { span }); + } + } + + /// True if the `pub` keyword is allowed on parameters in this function + /// `pub` on function parameters is only allowed for entry point functions + fn pub_allowed(&self, func: &NoirFunction) -> bool { + self.is_entry_point_function(func) || func.attributes().is_foldable() + } + + fn is_entry_point_function(&self, func: &NoirFunction) -> bool { + if self.in_contract { + func.attributes().is_contract_entry_point() + } else { + func.name() == MAIN_FUNCTION + } + } + + fn declare_numeric_generics(&mut self, params: &Parameters, return_type: &Type) { + if self.generics.is_empty() { + return; + } + + for (name_to_find, type_variable) in Self::find_numeric_generics(params, return_type) { + // Declare any generics to let users use numeric generics in scope. + // Don't issue a warning if these are unused + // + // We can fail to find the generic in self.generics if it is an implicit one created + // by the compiler. This can happen when, e.g. eliding array lengths using the slice + // syntax [T]. + if let Some((name, _, span)) = + self.generics.iter().find(|(name, _, _)| name.as_ref() == &name_to_find) + { + let ident = Ident::new(name.to_string(), *span); + let definition = DefinitionKind::GenericType(type_variable); + self.add_variable_decl_inner(ident, false, false, false, definition); + } + } + } + + fn add_trait_constraints_to_scope(&mut self, func_meta: &FuncMeta) { + for constraint in &func_meta.trait_constraints { + let object = constraint.typ.clone(); + let trait_id = constraint.trait_id; + let generics = constraint.trait_generics.clone(); + + if !self.interner.add_assumed_trait_implementation(object, trait_id, generics) { + if let Some(the_trait) = self.interner.try_get_trait(trait_id) { + let trait_name = the_trait.name.to_string(); + let typ = constraint.typ.clone(); + let span = func_meta.location.span; + self.push_err(TypeCheckError::UnneededTraitConstraint { + trait_name, + typ, + span, + }); + } + } + } + } + + fn elaborate_impls(&mut self, impls: Vec<(Vec, Span, UnresolvedFunctions)>) { + for (_, _, functions) in impls { + self.file = functions.file_id; + self.recover_generics(|this| this.elaborate_functions(functions)); + } + } + + fn elaborate_trait_impl(&mut self, trait_impl: UnresolvedTraitImpl) { + self.file = trait_impl.file_id; + self.local_module = trait_impl.module_id; + + self.generics = trait_impl.resolved_generics; + self.current_trait_impl = trait_impl.impl_id; + + for (module, function, _) in &trait_impl.methods.functions { + self.local_module = *module; + let errors = check_trait_impl_method_matches_declaration(self.interner, *function); + self.errors.extend(errors.into_iter().map(|error| (error.into(), self.file))); + } + + self.elaborate_functions(trait_impl.methods); + + self.self_type = None; + self.current_trait_impl = None; + self.generics.clear(); + } + + fn collect_impls( + &mut self, + module: LocalModuleId, + impls: &mut [(Vec, Span, UnresolvedFunctions)], + ) { + self.local_module = module; + + for (generics, span, unresolved) in impls { + self.file = unresolved.file_id; + let old_generic_count = self.generics.len(); + self.add_generics(generics); + self.declare_methods_on_struct(false, unresolved, *span); + self.generics.truncate(old_generic_count); + } + } + + fn collect_trait_impl(&mut self, trait_impl: &mut UnresolvedTraitImpl) { + self.local_module = trait_impl.module_id; + self.file = trait_impl.file_id; + self.current_trait_impl = trait_impl.impl_id; + trait_impl.trait_id = self.resolve_trait_by_path(trait_impl.trait_path.clone()); + + let self_type = trait_impl.methods.self_type.clone(); + let self_type = + self_type.expect("Expected struct type to be set before collect_trait_impl"); + + self.self_type = Some(self_type.clone()); + let self_type_span = trait_impl.object_type.span; + + if matches!(self_type, Type::MutableReference(_)) { + let span = self_type_span.unwrap_or_else(|| trait_impl.trait_path.span()); + self.push_err(DefCollectorErrorKind::MutableReferenceInTraitImpl { span }); + } + + if let Some(trait_id) = trait_impl.trait_id { + self.generics = trait_impl.resolved_generics.clone(); + self.collect_trait_impl_methods(trait_id, trait_impl); + + let span = trait_impl.object_type.span.expect("All trait self types should have spans"); + self.declare_methods_on_struct(true, &mut trait_impl.methods, span); + + let methods = trait_impl.methods.function_ids(); + for func_id in &methods { + self.interner.set_function_trait(*func_id, self_type.clone(), trait_id); + } + + let where_clause = trait_impl + .where_clause + .iter() + .flat_map(|item| self.resolve_trait_constraint(item)) + .collect(); + + let trait_generics = trait_impl.resolved_trait_generics.clone(); + + let resolved_trait_impl = Shared::new(TraitImpl { + ident: trait_impl.trait_path.last_segment().clone(), + typ: self_type.clone(), + trait_id, + trait_generics: trait_generics.clone(), + file: trait_impl.file_id, + where_clause, + methods, + }); + + let generics = vecmap(&self.generics, |(_, type_variable, _)| type_variable.clone()); + + if let Err((prev_span, prev_file)) = self.interner.add_trait_implementation( + self_type.clone(), + trait_id, + trait_generics, + trait_impl.impl_id.expect("impl_id should be set in define_function_metas"), + generics, + resolved_trait_impl, + ) { + self.push_err(DefCollectorErrorKind::OverlappingImpl { + typ: self_type.clone(), + span: self_type_span.unwrap_or_else(|| trait_impl.trait_path.span()), + }); + + // 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. + self.file = prev_file; + self.push_err(DefCollectorErrorKind::OverlappingImplNote { span: prev_span }); + self.file = trait_impl.file_id; + } + } + + self.generics.clear(); + self.current_trait_impl = None; + self.self_type = None; + } + + fn get_module_mut(&mut self, module: ModuleId) -> &mut ModuleData { + let message = "A crate should always be present for a given crate id"; + &mut self.def_maps.get_mut(&module.krate).expect(message).modules[module.local_id.0] + } + + fn declare_methods_on_struct( + &mut self, + is_trait_impl: bool, + functions: &mut UnresolvedFunctions, + span: Span, + ) { + let self_type = functions.self_type.as_ref(); + let self_type = + self_type.expect("Expected struct type to be set before declare_methods_on_struct"); + + let function_ids = functions.function_ids(); + + if let Type::Struct(struct_type, _) = &self_type { + let struct_ref = struct_type.borrow(); + + // `impl`s are only allowed on types defined within the current crate + if !is_trait_impl && struct_ref.id.krate() != self.crate_id { + let type_name = struct_ref.name.to_string(); + self.push_err(DefCollectorErrorKind::ForeignImpl { span, type_name }); + return; + } + + // 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 = self.get_module_mut(struct_ref.id.module_id()); + + for (_, method_id, method) in &functions.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. + let name = method.name_ident().clone(); + if module.declare_function(name, ItemVisibility::Public, *method_id).is_err() { + module.remove_function(method.name_ident()); + } + } + + self.declare_struct_methods(self_type, &function_ids); + // We can define methods on primitive types only if we're in the stdlib + } else if !is_trait_impl && *self_type != Type::Error { + if self.crate_id.is_stdlib() { + self.declare_struct_methods(self_type, &function_ids); + } else { + self.push_err(DefCollectorErrorKind::NonStructTypeInImpl { span }); + } + } + } + + fn declare_struct_methods(&mut self, self_type: &Type, function_ids: &[FuncId]) { + for method_id in function_ids { + let method_name = self.interner.function_name(method_id).to_owned(); + + if let Some(first_fn) = + self.interner.add_method(self_type, method_name.clone(), *method_id, false) + { + let error = ResolverError::DuplicateDefinition { + name: method_name, + first_span: self.interner.function_ident(&first_fn).span(), + second_span: self.interner.function_ident(method_id).span(), + }; + self.push_err(error); + } + } + } + + fn collect_trait_impl_methods( + &mut self, + trait_id: TraitId, + trait_impl: &mut UnresolvedTraitImpl, + ) { + self.local_module = trait_impl.module_id; + self.file = trait_impl.file_id; + + // In this Vec methods[i] corresponds to trait.methods[i]. If the impl has no implementation + // for a particular method, the default implementation will be added at that slot. + let mut ordered_methods = Vec::new(); + + // check whether the trait implementation is in the same crate as either the trait or the type + self.check_trait_impl_crate_coherence(trait_id, trait_impl); + + // set of function ids that have a corresponding method in the trait + let mut func_ids_in_trait = HashSet::default(); + + // Temporarily take ownership of the trait's methods so we can iterate over them + // while also mutating the interner + let the_trait = self.interner.get_trait_mut(trait_id); + let methods = std::mem::take(&mut the_trait.methods); + + for method in &methods { + let overrides: Vec<_> = trait_impl + .methods + .functions + .iter() + .filter(|(_, _, f)| f.name() == method.name.0.contents) + .collect(); + + if overrides.is_empty() { + if let Some(default_impl) = &method.default_impl { + // copy 'where' clause from unresolved trait impl + let mut default_impl_clone = default_impl.clone(); + default_impl_clone.def.where_clause.extend(trait_impl.where_clause.clone()); + + let func_id = self.interner.push_empty_fn(); + let module = self.module_id(); + let location = Location::new(default_impl.def.span, trait_impl.file_id); + self.interner.push_function(func_id, &default_impl.def, module, location); + self.define_function_meta(&mut default_impl_clone, func_id, false); + func_ids_in_trait.insert(func_id); + ordered_methods.push(( + method.default_impl_module_id, + func_id, + *default_impl_clone, + )); + } else { + self.push_err(DefCollectorErrorKind::TraitMissingMethod { + trait_name: self.interner.get_trait(trait_id).name.clone(), + method_name: method.name.clone(), + trait_impl_span: trait_impl + .object_type + .span + .expect("type must have a span"), + }); + } + } else { + for (_, func_id, _) in &overrides { + func_ids_in_trait.insert(*func_id); + } + + if overrides.len() > 1 { + self.push_err(DefCollectorErrorKind::Duplicate { + typ: DuplicateType::TraitAssociatedFunction, + first_def: overrides[0].2.name_ident().clone(), + second_def: overrides[1].2.name_ident().clone(), + }); + } + + ordered_methods.push(overrides[0].clone()); + } + } + + // Restore the methods that were taken before the for loop + let the_trait = self.interner.get_trait_mut(trait_id); + the_trait.set_methods(methods); + + // Emit MethodNotInTrait error for methods in the impl block that + // don't have a corresponding method signature defined in the trait + for (_, func_id, func) in &trait_impl.methods.functions { + if !func_ids_in_trait.contains(func_id) { + let trait_name = the_trait.name.clone(); + let impl_method = func.name_ident().clone(); + let error = DefCollectorErrorKind::MethodNotInTrait { trait_name, impl_method }; + self.errors.push((error.into(), self.file)); + } + } + + trait_impl.methods.functions = ordered_methods; + trait_impl.methods.trait_id = Some(trait_id); + } + + fn check_trait_impl_crate_coherence( + &mut self, + trait_id: TraitId, + trait_impl: &UnresolvedTraitImpl, + ) { + self.local_module = trait_impl.module_id; + self.file = trait_impl.file_id; + + let object_crate = match &trait_impl.resolved_object_type { + Some(Type::Struct(struct_type, _)) => struct_type.borrow().id.krate(), + _ => CrateId::Dummy, + }; + + let the_trait = self.interner.get_trait(trait_id); + if self.crate_id != the_trait.crate_id && self.crate_id != object_crate { + self.push_err(DefCollectorErrorKind::TraitImplOrphaned { + span: trait_impl.object_type.span.expect("object type must have a span"), + }); + } + } + + fn define_type_alias(&mut self, alias_id: TypeAliasId, alias: UnresolvedTypeAlias) { + self.file = alias.file_id; + self.local_module = alias.module_id; + + let generics = self.add_generics(&alias.type_alias_def.generics); + self.current_item = Some(DependencyId::Alias(alias_id)); + let typ = self.resolve_type(alias.type_alias_def.typ); + self.interner.set_type_alias(alias_id, typ, generics); + self.generics.clear(); + } + + fn collect_struct_definitions(&mut self, structs: BTreeMap) { + // This is necessary to avoid cloning the entire struct map + // when adding checks after each struct field is resolved. + let struct_ids = structs.keys().copied().collect::>(); + + // Resolve each field in each struct. + // Each struct should already be present in the NodeInterner after def collection. + for (type_id, typ) in structs { + self.file = typ.file_id; + self.local_module = typ.module_id; + let (generics, fields) = self.resolve_struct_fields(typ.struct_def, type_id); + + self.interner.update_struct(type_id, |struct_def| { + struct_def.set_fields(fields); + struct_def.generics = generics; + }); + } + + // Check whether the struct fields have nested slices + // We need to check after all structs are resolved to + // make sure every struct's fields is accurately set. + for id in struct_ids { + let struct_type = self.interner.get_struct(id); + // Only handle structs without generics as any generics args will be checked + // after monomorphization when performing SSA codegen + if struct_type.borrow().generics.is_empty() { + let fields = struct_type.borrow().get_fields(&[]); + for (_, field_type) in fields.iter() { + if field_type.is_nested_slice() { + let location = struct_type.borrow().location; + self.file = location.file; + self.push_err(ResolverError::NestedSlices { span: location.span }); + } + } + } + } + } + + pub fn resolve_struct_fields( + &mut self, + unresolved: NoirStruct, + struct_id: StructId, + ) -> (Generics, Vec<(Ident, Type)>) { + self.recover_generics(|this| { + let generics = this.add_generics(&unresolved.generics); + + this.current_item = Some(DependencyId::Struct(struct_id)); + + this.resolving_ids.insert(struct_id); + let fields = vecmap(unresolved.fields, |(ident, typ)| (ident, this.resolve_type(typ))); + this.resolving_ids.remove(&struct_id); + + (generics, fields) + }) + } + + fn elaborate_global(&mut self, global: UnresolvedGlobal) { + self.local_module = global.module_id; + self.file = global.file_id; + + let global_id = global.global_id; + self.current_item = Some(DependencyId::Global(global_id)); + let let_stmt = global.stmt_def; + + if !self.in_contract + && let_stmt.attributes.iter().any(|attr| matches!(attr, SecondaryAttribute::Abi(_))) + { + let span = let_stmt.pattern.span(); + self.push_err(ResolverError::AbiAttributeOutsideContract { span }); + } + + if !let_stmt.comptime && matches!(let_stmt.pattern, Pattern::Mutable(..)) { + let span = let_stmt.pattern.span(); + self.push_err(ResolverError::MutableGlobal { span }); + } + + let comptime = let_stmt.comptime; + + let (let_statement, _typ) = self.elaborate_let(let_stmt, Some(global_id)); + let statement_id = self.interner.get_global(global_id).let_statement; + self.interner.replace_statement(statement_id, let_statement); + + if comptime { + self.elaborate_comptime_global(global_id); + } + + // Avoid defaulting the types of globals here since they may be used in any function. + // Otherwise we may prematurely default to a Field inside the next function if this + // global was unused there, even if it is consistently used as a u8 everywhere else. + self.type_variables.clear(); + } + + fn elaborate_comptime_global(&mut self, global_id: GlobalId) { + let let_statement = self + .interner + .get_global_let_statement(global_id) + .expect("Let statement of global should be set by elaborate_global_let"); + + let global = self.interner.get_global(global_id); + let definition_id = global.definition_id; + let location = global.location; + + let mut interpreter = Interpreter::new(self.interner, &mut self.comptime_scopes); + + if let Err(error) = interpreter.evaluate_let(let_statement) { + self.errors.push(error.into_compilation_error_pair()); + } else { + let value = interpreter + .lookup_id(definition_id, location) + .expect("The global should be defined since evaluate_let did not error"); + + self.interner.get_global_mut(global_id).value = Some(value); + } + } + + fn define_function_metas( + &mut self, + functions: &mut [UnresolvedFunctions], + impls: &mut ImplMap, + trait_impls: &mut [UnresolvedTraitImpl], + ) { + for function_set in functions { + self.define_function_metas_for_functions(function_set); + } + + for ((self_type, local_module), function_sets) in impls { + self.local_module = *local_module; + + for (generics, _, function_set) in function_sets { + self.add_generics(generics); + let self_type = self.resolve_type(self_type.clone()); + function_set.self_type = Some(self_type.clone()); + self.self_type = Some(self_type); + self.define_function_metas_for_functions(function_set); + self.generics.clear(); + } + } + + for trait_impl in trait_impls { + self.file = trait_impl.file_id; + self.local_module = trait_impl.module_id; + + let unresolved_type = &trait_impl.object_type; + self.add_generics(&trait_impl.generics); + trait_impl.resolved_generics = self.generics.clone(); + + let trait_generics = + vecmap(&trait_impl.trait_generics, |generic| self.resolve_type(generic.clone())); + trait_impl.resolved_trait_generics = trait_generics; + + let self_type = self.resolve_type(unresolved_type.clone()); + + self.self_type = Some(self_type.clone()); + trait_impl.methods.self_type = Some(self_type); + + let impl_id = self.interner.next_trait_impl_id(); + self.current_trait_impl = Some(impl_id); + + self.define_function_metas_for_functions(&mut trait_impl.methods); + + trait_impl.resolved_object_type = self.self_type.take(); + trait_impl.impl_id = self.current_trait_impl.take(); + self.generics.clear(); + } + } + + fn define_function_metas_for_functions(&mut self, function_set: &mut UnresolvedFunctions) { + self.file = function_set.file_id; + + for (local_module, id, func) in &mut function_set.functions { + self.local_module = *local_module; + self.recover_generics(|this| { + this.define_function_meta(func, *id, false); + }); + } + } +} diff --git a/compiler/noirc_frontend/src/elaborator/patterns.rs b/compiler/noirc_frontend/src/elaborator/patterns.rs new file mode 100644 index 00000000000..e337726b579 --- /dev/null +++ b/compiler/noirc_frontend/src/elaborator/patterns.rs @@ -0,0 +1,601 @@ +use iter_extended::vecmap; +use noirc_errors::{Location, Span}; +use rustc_hash::FxHashSet as HashSet; + +use crate::{ + ast::ERROR_IDENT, + hir::{ + def_collector::dc_crate::CompilationError, + resolution::errors::ResolverError, + type_check::{Source, TypeCheckError}, + }, + hir_def::{ + expr::{HirIdent, ImplKind}, + function::FunctionBody, + stmt::HirPattern, + }, + macros_api::{HirExpression, Ident, Path, Pattern}, + node_interner::{DefinitionId, DefinitionKind, DependencyId, ExprId, GlobalId, TraitImplKind}, + Shared, StructType, Type, TypeBindings, +}; + +use super::{Elaborator, ResolverMeta}; + +impl<'context> Elaborator<'context> { + pub(super) fn elaborate_pattern( + &mut self, + pattern: Pattern, + expected_type: Type, + definition_kind: DefinitionKind, + ) -> HirPattern { + self.elaborate_pattern_mut( + pattern, + expected_type, + definition_kind, + None, + &mut Vec::new(), + None, + ) + } + + /// Equivalent to `elaborate_pattern`, this version just also + /// adds any new DefinitionIds that were created to the given Vec. + pub(super) fn elaborate_pattern_and_store_ids( + &mut self, + pattern: Pattern, + expected_type: Type, + definition_kind: DefinitionKind, + created_ids: &mut Vec, + global_id: Option, + ) -> HirPattern { + self.elaborate_pattern_mut( + pattern, + expected_type, + definition_kind, + None, + created_ids, + global_id, + ) + } + + fn elaborate_pattern_mut( + &mut self, + pattern: Pattern, + expected_type: Type, + definition: DefinitionKind, + mutable: Option, + new_definitions: &mut Vec, + global_id: Option, + ) -> HirPattern { + match pattern { + Pattern::Identifier(name) => { + // If this definition is mutable, do not store the rhs because it will + // not always refer to the correct value of the variable + let definition = match (mutable, definition) { + (Some(_), DefinitionKind::Local(_)) => DefinitionKind::Local(None), + (_, other) => other, + }; + let ident = if let Some(global_id) = global_id { + // Globals don't need to be added to scope, they're already in the def_maps + let id = self.interner.get_global(global_id).definition_id; + let location = Location::new(name.span(), self.file); + HirIdent::non_trait_method(id, location) + } else { + self.add_variable_decl(name, mutable.is_some(), true, definition) + }; + self.interner.push_definition_type(ident.id, expected_type); + new_definitions.push(ident.clone()); + HirPattern::Identifier(ident) + } + Pattern::Mutable(pattern, span, _) => { + if let Some(first_mut) = mutable { + self.push_err(ResolverError::UnnecessaryMut { first_mut, second_mut: span }); + } + + let pattern = self.elaborate_pattern_mut( + *pattern, + expected_type, + definition, + Some(span), + new_definitions, + global_id, + ); + let location = Location::new(span, self.file); + HirPattern::Mutable(Box::new(pattern), location) + } + Pattern::Tuple(fields, span) => { + let field_types = match expected_type.follow_bindings() { + Type::Tuple(fields) => fields, + Type::Error => Vec::new(), + expected_type => { + let tuple = + Type::Tuple(vecmap(&fields, |_| self.interner.next_type_variable())); + + self.push_err(TypeCheckError::TypeMismatchWithSource { + expected: expected_type, + actual: tuple, + span, + source: Source::Assignment, + }); + Vec::new() + } + }; + + let fields = vecmap(fields.into_iter().enumerate(), |(i, field)| { + let field_type = field_types.get(i).cloned().unwrap_or(Type::Error); + self.elaborate_pattern_mut( + field, + field_type, + definition.clone(), + mutable, + new_definitions, + global_id, + ) + }); + let location = Location::new(span, self.file); + HirPattern::Tuple(fields, location) + } + Pattern::Struct(name, fields, span) => self.elaborate_struct_pattern( + name, + fields, + span, + expected_type, + definition, + mutable, + new_definitions, + ), + } + } + + #[allow(clippy::too_many_arguments)] + fn elaborate_struct_pattern( + &mut self, + name: Path, + fields: Vec<(Ident, Pattern)>, + span: Span, + expected_type: Type, + definition: DefinitionKind, + mutable: Option, + new_definitions: &mut Vec, + ) -> HirPattern { + let error_identifier = |this: &mut Self| { + // Must create a name here to return a HirPattern::Identifier. Allowing + // shadowing here lets us avoid further errors if we define ERROR_IDENT + // multiple times. + let name = ERROR_IDENT.into(); + let identifier = this.add_variable_decl(name, false, true, definition.clone()); + HirPattern::Identifier(identifier) + }; + + let (struct_type, generics) = match self.lookup_type_or_error(name) { + Some(Type::Struct(struct_type, generics)) => (struct_type, generics), + None => return error_identifier(self), + Some(typ) => { + self.push_err(ResolverError::NonStructUsedInConstructor { typ, span }); + return error_identifier(self); + } + }; + + let actual_type = Type::Struct(struct_type.clone(), generics); + let location = Location::new(span, self.file); + + self.unify(&actual_type, &expected_type, || TypeCheckError::TypeMismatchWithSource { + expected: expected_type.clone(), + actual: actual_type.clone(), + span: location.span, + source: Source::Assignment, + }); + + let typ = struct_type.clone(); + let fields = self.resolve_constructor_pattern_fields( + typ, + fields, + span, + expected_type.clone(), + definition, + mutable, + new_definitions, + ); + + HirPattern::Struct(expected_type, fields, location) + } + + /// Resolve all the fields of a struct constructor expression. + /// Ensures all fields are present, none are repeated, and all + /// are part of the struct. + #[allow(clippy::too_many_arguments)] + fn resolve_constructor_pattern_fields( + &mut self, + struct_type: Shared, + fields: Vec<(Ident, Pattern)>, + span: Span, + expected_type: Type, + definition: DefinitionKind, + mutable: Option, + new_definitions: &mut Vec, + ) -> Vec<(Ident, HirPattern)> { + let mut ret = Vec::with_capacity(fields.len()); + let mut seen_fields = HashSet::default(); + let mut unseen_fields = struct_type.borrow().field_names(); + + for (field, pattern) in fields { + let field_type = expected_type.get_field_type(&field.0.contents).unwrap_or(Type::Error); + let resolved = self.elaborate_pattern_mut( + pattern, + field_type, + definition.clone(), + mutable, + new_definitions, + None, + ); + + if unseen_fields.contains(&field) { + unseen_fields.remove(&field); + seen_fields.insert(field.clone()); + } else if seen_fields.contains(&field) { + // duplicate field + self.push_err(ResolverError::DuplicateField { field: field.clone() }); + } else { + // field not required by struct + self.push_err(ResolverError::NoSuchField { + field: field.clone(), + struct_definition: struct_type.borrow().name.clone(), + }); + } + + ret.push((field, resolved)); + } + + if !unseen_fields.is_empty() { + self.push_err(ResolverError::MissingFields { + span, + missing_fields: unseen_fields.into_iter().map(|field| field.to_string()).collect(), + struct_definition: struct_type.borrow().name.clone(), + }); + } + + ret + } + + pub(super) fn add_variable_decl( + &mut self, + name: Ident, + mutable: bool, + allow_shadowing: bool, + definition: DefinitionKind, + ) -> HirIdent { + self.add_variable_decl_inner(name, mutable, allow_shadowing, true, definition) + } + + pub fn add_variable_decl_inner( + &mut self, + name: Ident, + mutable: bool, + allow_shadowing: bool, + warn_if_unused: bool, + definition: DefinitionKind, + ) -> HirIdent { + if definition.is_global() { + return self.add_global_variable_decl(name, definition); + } + + let location = Location::new(name.span(), self.file); + let id = + self.interner.push_definition(name.0.contents.clone(), mutable, definition, location); + let ident = HirIdent::non_trait_method(id, location); + let resolver_meta = + ResolverMeta { num_times_used: 0, ident: ident.clone(), warn_if_unused }; + + let scope = self.scopes.get_mut_scope(); + let old_value = scope.add_key_value(name.0.contents.clone(), resolver_meta); + + if !allow_shadowing { + if let Some(old_value) = old_value { + self.push_err(ResolverError::DuplicateDefinition { + name: name.0.contents, + first_span: old_value.ident.location.span, + second_span: location.span, + }); + } + } + + ident + } + + pub fn add_existing_variable_to_scope(&mut self, name: String, ident: HirIdent) { + let second_span = ident.location.span; + let resolver_meta = ResolverMeta { num_times_used: 0, ident, warn_if_unused: true }; + + let old_value = self.scopes.get_mut_scope().add_key_value(name.clone(), resolver_meta); + + if let Some(old_value) = old_value { + let first_span = old_value.ident.location.span; + self.push_err(ResolverError::DuplicateDefinition { name, first_span, second_span }); + } + } + + pub fn add_global_variable_decl( + &mut self, + name: Ident, + definition: DefinitionKind, + ) -> HirIdent { + let scope = self.scopes.get_mut_scope(); + + // This check is necessary to maintain the same definition ids in the interner. Currently, each function uses a new resolver that has its own ScopeForest and thus global scope. + // We must first check whether an existing definition ID has been inserted as otherwise there will be multiple definitions for the same global statement. + // This leads to an error in evaluation where the wrong definition ID is selected when evaluating a statement using the global. The check below prevents this error. + let mut global_id = None; + let global = self.interner.get_all_globals(); + for global_info in global { + if global_info.local_id == self.local_module && global_info.ident == name { + global_id = Some(global_info.id); + } + } + + let (ident, resolver_meta) = if let Some(id) = global_id { + let global = self.interner.get_global(id); + let hir_ident = HirIdent::non_trait_method(global.definition_id, global.location); + let ident = hir_ident.clone(); + let resolver_meta = ResolverMeta { num_times_used: 0, ident, warn_if_unused: true }; + (hir_ident, resolver_meta) + } else { + let location = Location::new(name.span(), self.file); + let id = + self.interner.push_definition(name.0.contents.clone(), false, definition, location); + let ident = HirIdent::non_trait_method(id, location); + let resolver_meta = + ResolverMeta { num_times_used: 0, ident: ident.clone(), warn_if_unused: true }; + (ident, resolver_meta) + }; + + let old_global_value = scope.add_key_value(name.0.contents.clone(), resolver_meta); + if let Some(old_global_value) = old_global_value { + self.push_err(ResolverError::DuplicateDefinition { + name: name.0.contents.clone(), + first_span: old_global_value.ident.location.span, + second_span: name.span(), + }); + } + ident + } + + /// Lookup and use the specified variable. + /// This will increment its use counter by one and return the variable if found. + /// If the variable is not found, an error is returned. + pub(super) fn use_variable( + &mut self, + name: &Ident, + ) -> Result<(HirIdent, usize), ResolverError> { + // Find the definition for this Ident + let scope_tree = self.scopes.current_scope_tree(); + let variable = scope_tree.find(&name.0.contents); + + let location = Location::new(name.span(), self.file); + if let Some((variable_found, scope)) = variable { + variable_found.num_times_used += 1; + let id = variable_found.ident.id; + Ok((HirIdent::non_trait_method(id, location), scope)) + } else { + Err(ResolverError::VariableNotDeclared { + name: name.0.contents.clone(), + span: name.0.span(), + }) + } + } + + pub(super) fn elaborate_variable( + &mut self, + variable: Path, + generics: Option>, + ) -> (ExprId, Type) { + let span = variable.span; + let expr = self.resolve_variable(variable); + let id = self.interner.push_expr(HirExpression::Ident(expr.clone(), generics.clone())); + self.interner.push_expr_location(id, span, self.file); + let typ = self.type_check_variable(expr, id, generics); + self.interner.push_expr_type(id, typ.clone()); + (id, typ) + } + + fn resolve_variable(&mut self, path: Path) -> HirIdent { + if let Some((method, constraint, assumed)) = self.resolve_trait_generic_path(&path) { + HirIdent { + location: Location::new(path.span, self.file), + id: self.interner.trait_method_id(method), + impl_kind: ImplKind::TraitMethod(method, constraint, assumed), + } + } 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 + // This lookup allows support of such statements: let x = foo::bar::SOME_GLOBAL + 10; + // If the expression is a singular indent, we search the resolver's current scope as normal. + let (hir_ident, var_scope_index) = self.get_ident_from_path(path); + + if hir_ident.id != DefinitionId::dummy_id() { + match self.interner.definition(hir_ident.id).kind { + DefinitionKind::Function(id) => { + if let Some(current_item) = self.current_item { + // Lazily evaluate functions found within globals if necessary. + // Otherwise if we later attempt to evaluate the global it will + // see an empty function body. + if matches!(current_item, DependencyId::Global(_)) { + let meta = self.interner.function_meta(&id); + + if matches!(&meta.function_body, FunctionBody::Unresolved(..)) { + self.elaborate_function(id); + } + } + self.interner.add_function_dependency(current_item, id); + } + } + DefinitionKind::Global(global_id) => { + if let Some(global) = self.unresolved_globals.remove(&global_id) { + self.elaborate_global(global); + } + if let Some(current_item) = self.current_item { + self.interner.add_global_dependency(current_item, global_id); + } + } + DefinitionKind::GenericType(_) => { + // Initialize numeric generics to a polymorphic integer type in case + // they're used in expressions. We must do this here since type_check_variable + // does not check definition kinds and otherwise expects parameters to + // already be typed. + if self.interner.definition_type(hir_ident.id) == Type::Error { + let typ = Type::polymorphic_integer_or_field(self.interner); + self.interner.push_definition_type(hir_ident.id, typ); + } + } + DefinitionKind::Local(_) => { + // only local variables can be captured by closures. + self.resolve_local_variable(hir_ident.clone(), var_scope_index); + } + } + } + + hir_ident + } + } + + pub(super) fn type_check_variable( + &mut self, + ident: HirIdent, + expr_id: ExprId, + generics: Option>, + ) -> Type { + let mut bindings = TypeBindings::new(); + + // Add type bindings from any constraints that were used. + // We need to do this first since otherwise instantiating the type below + // will replace each trait generic with a fresh type variable, rather than + // the type used in the trait constraint (if it exists). See #4088. + if let ImplKind::TraitMethod(_, constraint, assumed) = &ident.impl_kind { + let the_trait = self.interner.get_trait(constraint.trait_id); + assert_eq!(the_trait.generics.len(), constraint.trait_generics.len()); + + for (param, arg) in the_trait.generics.iter().zip(&constraint.trait_generics) { + // Avoid binding t = t + if !arg.occurs(param.id()) { + bindings.insert(param.id(), (param.clone(), arg.clone())); + } + } + + // If the trait impl is already assumed to exist we should add any type bindings for `Self`. + // Otherwise `self` will be replaced with a fresh type variable, which will require the user + // to specify a redundant type annotation. + if *assumed { + bindings.insert( + the_trait.self_type_typevar_id, + (the_trait.self_type_typevar.clone(), constraint.typ.clone()), + ); + } + } + + // An identifiers type may be forall-quantified in the case of generic functions. + // E.g. `fn foo(t: T, field: Field) -> T` has type `forall T. fn(T, Field) -> T`. + // We must instantiate identifiers at every call site to replace this T with a new type + // variable to handle generic functions. + let t = self.interner.id_type_substitute_trait_as_type(ident.id); + + let definition = self.interner.try_definition(ident.id); + let function_generic_count = definition.map_or(0, |definition| match &definition.kind { + DefinitionKind::Function(function) => { + self.interner.function_modifiers(function).generic_count + } + _ => 0, + }); + + let span = self.interner.expr_span(&expr_id); + let location = self.interner.expr_location(&expr_id); + // This instantiates a trait's generics as well which need to be set + // when the constraint below is later solved for when the function is + // finished. How to link the two? + let (typ, bindings) = + self.instantiate(t, bindings, generics, function_generic_count, span, location); + + // 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.apply_bindings(&bindings); + self.trait_constraints.push((constraint, expr_id)); + } + } + } + + if let ImplKind::TraitMethod(_, mut constraint, assumed) = ident.impl_kind { + constraint.apply_bindings(&bindings); + if assumed { + let trait_impl = TraitImplKind::Assumed { + object_type: constraint.typ, + trait_generics: constraint.trait_generics, + }; + self.interner.select_impl_for_expression(expr_id, trait_impl); + } else { + // Currently only one impl can be selected per expr_id, so this + // constraint needs to be pushed after any other constraints so + // that monomorphization can resolve this trait method to the correct impl. + self.trait_constraints.push((constraint, expr_id)); + } + } + + self.interner.store_instantiation_bindings(expr_id, bindings); + typ + } + + fn instantiate( + &mut self, + typ: Type, + bindings: TypeBindings, + turbofish_generics: Option>, + function_generic_count: usize, + span: Span, + location: Location, + ) -> (Type, TypeBindings) { + match turbofish_generics { + Some(turbofish_generics) => { + if turbofish_generics.len() != function_generic_count { + let type_check_err = TypeCheckError::IncorrectTurbofishGenericCount { + expected_count: function_generic_count, + actual_count: turbofish_generics.len(), + span, + }; + self.errors.push((CompilationError::TypeError(type_check_err), location.file)); + typ.instantiate_with_bindings(bindings, self.interner) + } else { + // Fetch the count of any implicit generics on the function, such as + // for a method within a generic impl. + let implicit_generic_count = match &typ { + Type::Forall(generics, _) => generics.len() - function_generic_count, + _ => 0, + }; + typ.instantiate_with(turbofish_generics, self.interner, implicit_generic_count) + } + } + None => typ.instantiate_with_bindings(bindings, self.interner), + } + } + + pub fn get_ident_from_path(&mut self, path: Path) -> (HirIdent, usize) { + let location = Location::new(path.span(), self.file); + + let error = match path.as_ident().map(|ident| self.use_variable(ident)) { + Some(Ok(found)) => return found, + // Try to look it up as a global, but still issue the first error if we fail + Some(Err(error)) => match self.lookup_global(path) { + Ok(id) => return (HirIdent::non_trait_method(id, location), 0), + Err(_) => error, + }, + None => match self.lookup_global(path) { + Ok(id) => return (HirIdent::non_trait_method(id, location), 0), + Err(error) => error, + }, + }; + self.push_err(error); + let id = DefinitionId::dummy_id(); + (HirIdent::non_trait_method(id, location), 0) + } +} diff --git a/compiler/noirc_frontend/src/elaborator/scope.rs b/compiler/noirc_frontend/src/elaborator/scope.rs new file mode 100644 index 00000000000..9fd3be0a354 --- /dev/null +++ b/compiler/noirc_frontend/src/elaborator/scope.rs @@ -0,0 +1,200 @@ +use noirc_errors::Spanned; + +use crate::ast::ERROR_IDENT; +use crate::hir::def_map::{LocalModuleId, ModuleId}; +use crate::hir::resolution::path_resolver::{PathResolver, StandardPathResolver}; +use crate::hir::resolution::resolver::SELF_TYPE_NAME; +use crate::hir::scope::{Scope as GenericScope, ScopeTree as GenericScopeTree}; +use crate::macros_api::Ident; +use crate::{ + hir::{ + def_map::{ModuleDefId, TryFromModuleDefId}, + resolution::errors::ResolverError, + }, + hir_def::{ + expr::{HirCapturedVar, HirIdent}, + traits::Trait, + }, + macros_api::{Path, StructId}, + node_interner::{DefinitionId, TraitId}, + Shared, StructType, +}; +use crate::{Type, TypeAlias}; + +use super::{Elaborator, ResolverMeta}; + +type Scope = GenericScope; +type ScopeTree = GenericScopeTree; + +impl<'context> Elaborator<'context> { + pub(super) fn lookup(&mut self, path: Path) -> Result { + let span = path.span(); + let id = self.resolve_path(path)?; + T::try_from(id).ok_or_else(|| ResolverError::Expected { + expected: T::description(), + got: id.as_str().to_owned(), + span, + }) + } + + pub(super) fn module_id(&self) -> ModuleId { + assert_ne!(self.local_module, LocalModuleId::dummy_id(), "local_module is unset"); + ModuleId { krate: self.crate_id, local_id: self.local_module } + } + + pub(super) fn resolve_path(&mut self, path: Path) -> Result { + let resolver = StandardPathResolver::new(self.module_id()); + let path_resolution = resolver.resolve(self.def_maps, path)?; + + if let Some(error) = path_resolution.error { + self.push_err(error); + } + + Ok(path_resolution.module_def_id) + } + + pub(super) fn get_struct(&self, type_id: StructId) -> Shared { + self.interner.get_struct(type_id) + } + + pub(super) fn get_trait_mut(&mut self, trait_id: TraitId) -> &mut Trait { + self.interner.get_trait_mut(trait_id) + } + + pub(super) fn resolve_local_variable(&mut self, hir_ident: HirIdent, var_scope_index: usize) { + let mut transitive_capture_index: Option = None; + + for lambda_index in 0..self.lambda_stack.len() { + if self.lambda_stack[lambda_index].scope_index > var_scope_index { + // Beware: the same variable may be captured multiple times, so we check + // for its presence before adding the capture below. + let position = self.lambda_stack[lambda_index] + .captures + .iter() + .position(|capture| capture.ident.id == hir_ident.id); + + if position.is_none() { + self.lambda_stack[lambda_index].captures.push(HirCapturedVar { + ident: hir_ident.clone(), + transitive_capture_index, + }); + } + + if lambda_index + 1 < self.lambda_stack.len() { + // There is more than one closure between the current scope and + // the scope of the variable, so this is a propagated capture. + // We need to track the transitive capture index as we go up in + // the closure stack. + transitive_capture_index = Some(position.unwrap_or( + // If this was a fresh capture, we added it to the end of + // the captures vector: + self.lambda_stack[lambda_index].captures.len() - 1, + )); + } + } + } + } + + pub(super) fn lookup_global(&mut self, path: Path) -> Result { + let span = path.span(); + let id = self.resolve_path(path)?; + + if let Some(function) = TryFromModuleDefId::try_from(id) { + return Ok(self.interner.function_definition_id(function)); + } + + if let Some(global) = TryFromModuleDefId::try_from(id) { + let global = self.interner.get_global(global); + return Ok(global.definition_id); + } + + let expected = "global variable".into(); + let got = "local variable".into(); + Err(ResolverError::Expected { span, expected, got }) + } + + pub fn push_scope(&mut self) { + self.scopes.start_scope(); + self.comptime_scopes.push(Default::default()); + } + + pub fn pop_scope(&mut self) { + let scope = self.scopes.end_scope(); + self.comptime_scopes.pop(); + self.check_for_unused_variables_in_scope_tree(scope.into()); + } + + pub fn check_for_unused_variables_in_scope_tree(&mut self, scope_decls: ScopeTree) { + let mut unused_vars = Vec::new(); + for scope in scope_decls.0.into_iter() { + Self::check_for_unused_variables_in_local_scope(scope, &mut unused_vars); + } + + for unused_var in unused_vars.iter() { + if let Some(definition_info) = self.interner.try_definition(unused_var.id) { + let name = &definition_info.name; + if name != ERROR_IDENT && !definition_info.is_global() { + let ident = Ident(Spanned::from(unused_var.location.span, name.to_owned())); + self.push_err(ResolverError::UnusedVariable { ident }); + } + } + } + } + + fn check_for_unused_variables_in_local_scope(decl_map: Scope, unused_vars: &mut Vec) { + let unused_variables = decl_map.filter(|(variable_name, metadata)| { + let has_underscore_prefix = variable_name.starts_with('_'); // XXX: This is used for development mode, and will be removed + metadata.warn_if_unused && metadata.num_times_used == 0 && !has_underscore_prefix + }); + unused_vars.extend(unused_variables.map(|(_, meta)| meta.ident.clone())); + } + + /// Lookup a given trait by name/path. + pub fn lookup_trait_or_error(&mut self, path: Path) -> Option<&mut Trait> { + match self.lookup(path) { + Ok(trait_id) => Some(self.get_trait_mut(trait_id)), + Err(error) => { + self.push_err(error); + None + } + } + } + + /// Lookup a given struct type by name. + pub fn lookup_struct_or_error(&mut self, path: Path) -> Option> { + match self.lookup(path) { + Ok(struct_id) => Some(self.get_struct(struct_id)), + Err(error) => { + self.push_err(error); + None + } + } + } + + /// Looks up a given type by name. + /// This will also instantiate any struct types found. + pub(super) fn lookup_type_or_error(&mut self, path: Path) -> Option { + let ident = path.as_ident(); + if ident.map_or(false, |i| i == SELF_TYPE_NAME) { + if let Some(typ) = &self.self_type { + return Some(typ.clone()); + } + } + + match self.lookup(path) { + Ok(struct_id) => { + let struct_type = self.get_struct(struct_id); + let generics = struct_type.borrow().instantiate(self.interner); + Some(Type::Struct(struct_type, generics)) + } + Err(error) => { + self.push_err(error); + None + } + } + } + + pub fn lookup_type_alias(&mut self, path: Path) -> Option> { + self.lookup(path).ok().map(|id| self.interner.get_type_alias(id)) + } +} diff --git a/compiler/noirc_frontend/src/elaborator/statements.rs b/compiler/noirc_frontend/src/elaborator/statements.rs new file mode 100644 index 00000000000..dd3e2778726 --- /dev/null +++ b/compiler/noirc_frontend/src/elaborator/statements.rs @@ -0,0 +1,440 @@ +use noirc_errors::{Location, Span}; + +use crate::{ + ast::{AssignStatement, ConstrainStatement, LValue}, + hir::{ + comptime::Interpreter, + resolution::errors::ResolverError, + type_check::{Source, TypeCheckError}, + }, + hir_def::{ + expr::HirIdent, + stmt::{ + HirAssignStatement, HirConstrainStatement, HirForStatement, HirLValue, HirLetStatement, + }, + }, + macros_api::{ + ForLoopStatement, ForRange, HirStatement, LetStatement, Path, Statement, StatementKind, + }, + node_interner::{DefinitionId, DefinitionKind, GlobalId, StmtId}, + Type, +}; + +use super::{lints, Elaborator}; + +impl<'context> Elaborator<'context> { + fn elaborate_statement_value(&mut self, statement: Statement) -> (HirStatement, Type) { + match statement.kind { + StatementKind::Let(let_stmt) => self.elaborate_local_let(let_stmt), + StatementKind::Constrain(constrain) => self.elaborate_constrain(constrain), + StatementKind::Assign(assign) => self.elaborate_assign(assign), + StatementKind::For(for_stmt) => self.elaborate_for(for_stmt), + StatementKind::Break => self.elaborate_jump(true, statement.span), + StatementKind::Continue => self.elaborate_jump(false, statement.span), + StatementKind::Comptime(statement) => self.elaborate_comptime_statement(*statement), + StatementKind::Expression(expr) => { + let (expr, typ) = self.elaborate_expression(expr); + (HirStatement::Expression(expr), typ) + } + StatementKind::Semi(expr) => { + let (expr, _typ) = self.elaborate_expression(expr); + (HirStatement::Semi(expr), Type::Unit) + } + StatementKind::Error => (HirStatement::Error, Type::Error), + } + } + + pub(super) fn elaborate_statement(&mut self, statement: Statement) -> (StmtId, Type) { + let span = statement.span; + let (hir_statement, typ) = self.elaborate_statement_value(statement); + let id = self.interner.push_stmt(hir_statement); + self.interner.push_stmt_location(id, span, self.file); + (id, typ) + } + + pub(super) fn elaborate_local_let(&mut self, let_stmt: LetStatement) -> (HirStatement, Type) { + self.elaborate_let(let_stmt, None) + } + + /// Elaborate a local or global let statement. + /// If this is a global let, the DefinitionId of the global is specified so that + /// elaborate_pattern can create a Global definition kind with the correct ID + /// instead of a local one with a fresh ID. + pub(super) fn elaborate_let( + &mut self, + let_stmt: LetStatement, + global_id: Option, + ) -> (HirStatement, Type) { + let expr_span = let_stmt.expression.span; + let (expression, expr_type) = self.elaborate_expression(let_stmt.expression); + let annotated_type = self.resolve_type(let_stmt.r#type); + + let definition = match global_id { + None => DefinitionKind::Local(Some(expression)), + Some(id) => DefinitionKind::Global(id), + }; + + // First check if the LHS is unspecified + // If so, then we give it the same type as the expression + let r#type = if annotated_type != Type::Error { + // Now check if LHS is the same type as the RHS + // Importantly, we do not coerce any types implicitly + self.unify_with_coercions(&expr_type, &annotated_type, expression, || { + TypeCheckError::TypeMismatch { + expected_typ: annotated_type.to_string(), + expr_typ: expr_type.to_string(), + expr_span, + } + }); + if annotated_type.is_unsigned() { + let errors = lints::overflowing_uint(self.interner, &expression, &annotated_type); + for error in errors { + self.push_err(error); + } + } + annotated_type + } else { + expr_type + }; + + let pattern = self.elaborate_pattern_and_store_ids( + let_stmt.pattern, + r#type.clone(), + definition, + &mut Vec::new(), + global_id, + ); + + let attributes = let_stmt.attributes; + let comptime = let_stmt.comptime; + let let_ = HirLetStatement { pattern, r#type, expression, attributes, comptime }; + (HirStatement::Let(let_), Type::Unit) + } + + pub(super) fn elaborate_constrain(&mut self, stmt: ConstrainStatement) -> (HirStatement, Type) { + let expr_span = stmt.0.span; + let (expr_id, expr_type) = self.elaborate_expression(stmt.0); + + // Must type check the assertion message expression so that we instantiate bindings + let msg = stmt.1.map(|assert_msg_expr| self.elaborate_expression(assert_msg_expr).0); + + self.unify(&expr_type, &Type::Bool, || TypeCheckError::TypeMismatch { + expr_typ: expr_type.to_string(), + expected_typ: Type::Bool.to_string(), + expr_span, + }); + + (HirStatement::Constrain(HirConstrainStatement(expr_id, self.file, msg)), Type::Unit) + } + + pub(super) fn elaborate_assign(&mut self, assign: AssignStatement) -> (HirStatement, Type) { + let span = assign.expression.span; + let (expression, expr_type) = self.elaborate_expression(assign.expression); + let (lvalue, lvalue_type, mutable) = self.elaborate_lvalue(assign.lvalue, span); + + if !mutable { + let (name, span) = self.get_lvalue_name_and_span(&lvalue); + self.push_err(TypeCheckError::VariableMustBeMutable { name, span }); + } + + self.unify_with_coercions(&expr_type, &lvalue_type, expression, || { + TypeCheckError::TypeMismatchWithSource { + actual: expr_type.clone(), + expected: lvalue_type.clone(), + span, + source: Source::Assignment, + } + }); + + let stmt = HirAssignStatement { lvalue, expression }; + (HirStatement::Assign(stmt), Type::Unit) + } + + pub(super) fn elaborate_for(&mut self, for_loop: ForLoopStatement) -> (HirStatement, Type) { + let (start, end) = match for_loop.range { + ForRange::Range(start, end) => (start, end), + ForRange::Array(_) => { + let for_stmt = + for_loop.range.into_for(for_loop.identifier, for_loop.block, for_loop.span); + + return self.elaborate_statement_value(for_stmt); + } + }; + + let start_span = start.span; + let end_span = end.span; + + let (start_range, start_range_type) = self.elaborate_expression(start); + let (end_range, end_range_type) = self.elaborate_expression(end); + let (identifier, block) = (for_loop.identifier, for_loop.block); + + self.nested_loops += 1; + self.push_scope(); + + // TODO: For loop variables are currently mutable by default since we haven't + // yet implemented syntax for them to be optionally mutable. + let kind = DefinitionKind::Local(None); + let identifier = self.add_variable_decl(identifier, false, true, kind); + + // Check that start range and end range have the same types + let range_span = start_span.merge(end_span); + self.unify(&start_range_type, &end_range_type, || TypeCheckError::TypeMismatch { + expected_typ: start_range_type.to_string(), + expr_typ: end_range_type.to_string(), + expr_span: range_span, + }); + + let expected_type = self.polymorphic_integer(); + + self.unify(&start_range_type, &expected_type, || TypeCheckError::TypeCannotBeUsed { + typ: start_range_type.clone(), + place: "for loop", + span: range_span, + }); + + self.interner.push_definition_type(identifier.id, start_range_type); + + let (block, _block_type) = self.elaborate_expression(block); + + self.pop_scope(); + self.nested_loops -= 1; + + let statement = + HirStatement::For(HirForStatement { start_range, end_range, block, identifier }); + + (statement, Type::Unit) + } + + fn elaborate_jump(&mut self, is_break: bool, span: noirc_errors::Span) -> (HirStatement, Type) { + if !self.in_unconstrained_fn { + self.push_err(ResolverError::JumpInConstrainedFn { is_break, span }); + } + if self.nested_loops == 0 { + self.push_err(ResolverError::JumpOutsideLoop { is_break, span }); + } + + let expr = if is_break { HirStatement::Break } else { HirStatement::Continue }; + (expr, self.interner.next_type_variable()) + } + + fn get_lvalue_name_and_span(&self, lvalue: &HirLValue) -> (String, Span) { + match lvalue { + HirLValue::Ident(name, _) => { + let span = name.location.span; + + if let Some(definition) = self.interner.try_definition(name.id) { + (definition.name.clone(), span) + } else { + ("(undeclared variable)".into(), span) + } + } + HirLValue::MemberAccess { object, .. } => self.get_lvalue_name_and_span(object), + HirLValue::Index { array, .. } => self.get_lvalue_name_and_span(array), + HirLValue::Dereference { lvalue, .. } => self.get_lvalue_name_and_span(lvalue), + } + } + + fn elaborate_lvalue(&mut self, lvalue: LValue, assign_span: Span) -> (HirLValue, Type, bool) { + match lvalue { + LValue::Ident(ident) => { + let mut mutable = true; + let span = ident.span(); + let path = Path::from_single(ident.0.contents, span); + let (ident, scope_index) = self.get_ident_from_path(path); + self.resolve_local_variable(ident.clone(), scope_index); + + let typ = if ident.id == DefinitionId::dummy_id() { + Type::Error + } else { + if let Some(definition) = self.interner.try_definition(ident.id) { + mutable = definition.mutable; + } + + let typ = self.interner.definition_type(ident.id).instantiate(self.interner).0; + typ.follow_bindings() + }; + + (HirLValue::Ident(ident.clone(), typ.clone()), typ, mutable) + } + LValue::MemberAccess { object, field_name, span } => { + let (object, lhs_type, mut mutable) = self.elaborate_lvalue(*object, assign_span); + let mut object = Box::new(object); + let field_name = field_name.clone(); + + let object_ref = &mut object; + let mutable_ref = &mut mutable; + let location = Location::new(span, self.file); + + let dereference_lhs = move |_: &mut Self, _, element_type| { + // We must create a temporary value first to move out of object_ref before + // we eventually reassign to it. + let id = DefinitionId::dummy_id(); + let ident = HirIdent::non_trait_method(id, location); + let tmp_value = HirLValue::Ident(ident, Type::Error); + + let lvalue = std::mem::replace(object_ref, Box::new(tmp_value)); + *object_ref = + Box::new(HirLValue::Dereference { lvalue, element_type, location }); + *mutable_ref = true; + }; + + let name = &field_name.0.contents; + let (object_type, field_index) = self + .check_field_access(&lhs_type, name, field_name.span(), Some(dereference_lhs)) + .unwrap_or((Type::Error, 0)); + + let field_index = Some(field_index); + let typ = object_type.clone(); + let lvalue = + HirLValue::MemberAccess { object, field_name, field_index, typ, location }; + (lvalue, object_type, mutable) + } + LValue::Index { array, index, span } => { + let expr_span = index.span; + let (index, index_type) = self.elaborate_expression(index); + let location = Location::new(span, self.file); + + let expected = self.polymorphic_integer_or_field(); + self.unify(&index_type, &expected, || TypeCheckError::TypeMismatch { + expected_typ: "an integer".to_owned(), + expr_typ: index_type.to_string(), + expr_span, + }); + + let (mut lvalue, mut lvalue_type, mut mutable) = + self.elaborate_lvalue(*array, assign_span); + + // Before we check that the lvalue is an array, try to dereference it as many times + // as needed to unwrap any &mut wrappers. + while let Type::MutableReference(element) = lvalue_type.follow_bindings() { + let element_type = element.as_ref().clone(); + lvalue = + HirLValue::Dereference { lvalue: Box::new(lvalue), element_type, location }; + lvalue_type = *element; + // We know this value to be mutable now since we found an `&mut` + mutable = true; + } + + let typ = match lvalue_type.follow_bindings() { + Type::Array(_, elem_type) => *elem_type, + Type::Slice(elem_type) => *elem_type, + Type::Error => Type::Error, + Type::String(_) => { + let (_lvalue_name, lvalue_span) = self.get_lvalue_name_and_span(&lvalue); + self.push_err(TypeCheckError::StringIndexAssign { span: lvalue_span }); + Type::Error + } + other => { + // TODO: Need a better span here + self.push_err(TypeCheckError::TypeMismatch { + expected_typ: "array".to_string(), + expr_typ: other.to_string(), + expr_span: assign_span, + }); + Type::Error + } + }; + + let array = Box::new(lvalue); + let array_type = typ.clone(); + (HirLValue::Index { array, index, typ, location }, array_type, mutable) + } + LValue::Dereference(lvalue, span) => { + let (lvalue, reference_type, _) = self.elaborate_lvalue(*lvalue, assign_span); + let lvalue = Box::new(lvalue); + let location = Location::new(span, self.file); + + let element_type = Type::type_variable(self.interner.next_type_variable_id()); + let expected_type = Type::MutableReference(Box::new(element_type.clone())); + + self.unify(&reference_type, &expected_type, || TypeCheckError::TypeMismatch { + expected_typ: expected_type.to_string(), + expr_typ: reference_type.to_string(), + expr_span: assign_span, + }); + + // Dereferences are always mutable since we already type checked against a &mut T + let typ = element_type.clone(); + let lvalue = HirLValue::Dereference { lvalue, element_type, location }; + (lvalue, typ, true) + } + } + } + + /// Type checks a field access, adding dereference operators as necessary + pub(super) fn check_field_access( + &mut self, + lhs_type: &Type, + field_name: &str, + span: Span, + dereference_lhs: Option, + ) -> Option<(Type, usize)> { + let lhs_type = lhs_type.follow_bindings(); + + match &lhs_type { + Type::Struct(s, args) => { + let s = s.borrow(); + if let Some((field, index)) = s.get_field(field_name, args) { + return Some((field, index)); + } + } + Type::Tuple(elements) => { + if let Ok(index) = field_name.parse::() { + let length = elements.len(); + if index < length { + return Some((elements[index].clone(), index)); + } else { + self.push_err(TypeCheckError::TupleIndexOutOfBounds { + index, + lhs_type, + length, + span, + }); + return None; + } + } + } + // If the lhs is a mutable reference we automatically transform + // lhs.field into (*lhs).field + Type::MutableReference(element) => { + if let Some(mut dereference_lhs) = dereference_lhs { + dereference_lhs(self, lhs_type.clone(), element.as_ref().clone()); + return self.check_field_access( + element, + field_name, + span, + Some(dereference_lhs), + ); + } else { + let (element, index) = + self.check_field_access(element, field_name, span, dereference_lhs)?; + return Some((Type::MutableReference(Box::new(element)), index)); + } + } + _ => (), + } + + // If we get here the type has no field named 'access.rhs'. + // Now we specialize the error message based on whether we know the object type in question yet. + if let Type::TypeVariable(..) = &lhs_type { + self.push_err(TypeCheckError::TypeAnnotationsNeeded { span }); + } else if lhs_type != Type::Error { + self.push_err(TypeCheckError::AccessUnknownMember { + lhs_type, + field_name: field_name.to_string(), + span, + }); + } + + None + } + + fn elaborate_comptime_statement(&mut self, statement: Statement) -> (HirStatement, Type) { + let span = statement.span; + let (hir_statement, _typ) = self.elaborate_statement(statement); + let mut interpreter = Interpreter::new(self.interner, &mut self.comptime_scopes); + let value = interpreter.evaluate_statement(hir_statement); + let (expr, typ) = self.inline_comptime_value(value, span); + (HirStatement::Expression(expr), typ) + } +} diff --git a/compiler/noirc_frontend/src/elaborator/traits.rs b/compiler/noirc_frontend/src/elaborator/traits.rs new file mode 100644 index 00000000000..6183c6e950d --- /dev/null +++ b/compiler/noirc_frontend/src/elaborator/traits.rs @@ -0,0 +1,180 @@ +use std::collections::BTreeMap; + +use iter_extended::vecmap; +use noirc_errors::Location; + +use crate::{ + ast::{FunctionKind, TraitItem, UnresolvedGenerics, UnresolvedTraitConstraint}, + hir::def_collector::dc_crate::UnresolvedTrait, + hir_def::traits::{TraitConstant, TraitFunction, TraitType}, + macros_api::{ + BlockExpression, FunctionDefinition, FunctionReturnType, Ident, ItemVisibility, + NoirFunction, Param, Pattern, UnresolvedType, Visibility, + }, + node_interner::{FuncId, TraitId}, + token::Attributes, + Type, TypeVariableKind, +}; + +use super::Elaborator; + +impl<'context> Elaborator<'context> { + pub fn collect_traits(&mut self, traits: BTreeMap) { + for (trait_id, unresolved_trait) in traits { + self.recover_generics(|this| { + this.add_generics(&unresolved_trait.trait_def.generics); + + // Resolve order + // 1. Trait Types ( Trait constants can have a trait type, therefore types before constants) + let _ = this.resolve_trait_types(&unresolved_trait); + // 2. Trait Constants ( Trait's methods can use trait types & constants, therefore they should be after) + let _ = this.resolve_trait_constants(&unresolved_trait); + // 3. Trait Methods + let methods = this.resolve_trait_methods(trait_id, &unresolved_trait); + + this.interner.update_trait(trait_id, |trait_def| { + trait_def.set_methods(methods); + trait_def.generics = vecmap(&this.generics, |(_, generic, _)| generic.clone()); + }); + }); + + // This check needs to be after the trait's methods are set since + // the interner may set `interner.ordering_type` based on the result type + // of the Cmp trait, if this is it. + if self.crate_id.is_stdlib() { + self.interner.try_add_operator_trait(trait_id); + } + } + } + + fn resolve_trait_types(&mut self, _unresolved_trait: &UnresolvedTrait) -> Vec { + // TODO + vec![] + } + + fn resolve_trait_constants( + &mut self, + _unresolved_trait: &UnresolvedTrait, + ) -> Vec { + // TODO + vec![] + } + + fn resolve_trait_methods( + &mut self, + trait_id: TraitId, + unresolved_trait: &UnresolvedTrait, + ) -> Vec { + self.local_module = unresolved_trait.module_id; + self.file = self.def_maps[&self.crate_id].file_id(unresolved_trait.module_id); + + let mut functions = vec![]; + + for item in &unresolved_trait.trait_def.items { + if let TraitItem::Function { + name, + generics, + parameters, + return_type, + where_clause, + body: _, + } = item + { + self.recover_generics(|this| { + let the_trait = this.interner.get_trait(trait_id); + let self_typevar = the_trait.self_type_typevar.clone(); + let self_type = + Type::TypeVariable(self_typevar.clone(), TypeVariableKind::Normal); + let name_span = the_trait.name.span(); + + this.add_existing_generic("Self", name_span, self_typevar); + this.self_type = Some(self_type.clone()); + + let func_id = unresolved_trait.method_ids[&name.0.contents]; + this.resolve_trait_function( + name, + generics, + parameters, + return_type, + where_clause, + func_id, + ); + + let func_meta = this.interner.function_meta(&func_id); + + let arguments = vecmap(&func_meta.parameters.0, |(_, typ, _)| typ.clone()); + let return_type = func_meta.return_type().clone(); + + let generics = vecmap(&this.generics, |(_, type_var, _)| type_var.clone()); + + let default_impl_list: Vec<_> = unresolved_trait + .fns_with_default_impl + .functions + .iter() + .filter(|(_, _, q)| q.name() == name.0.contents) + .collect(); + + let default_impl = if default_impl_list.len() == 1 { + Some(Box::new(default_impl_list[0].2.clone())) + } else { + None + }; + + let no_environment = Box::new(Type::Unit); + let function_type = + Type::Function(arguments, Box::new(return_type), no_environment); + + functions.push(TraitFunction { + name: name.clone(), + typ: Type::Forall(generics, Box::new(function_type)), + location: Location::new(name.span(), unresolved_trait.file_id), + default_impl, + default_impl_module_id: unresolved_trait.module_id, + }); + }); + } + } + functions + } + + pub fn resolve_trait_function( + &mut self, + name: &Ident, + generics: &UnresolvedGenerics, + parameters: &[(Ident, UnresolvedType)], + return_type: &FunctionReturnType, + where_clause: &[UnresolvedTraitConstraint], + func_id: FuncId, + ) { + let old_generic_count = self.generics.len(); + self.scopes.start_function(); + + let kind = FunctionKind::Normal; + let def = FunctionDefinition { + name: name.clone(), + attributes: Attributes::empty(), + is_unconstrained: false, + is_comptime: false, + visibility: ItemVisibility::Public, // Trait functions are always public + generics: generics.clone(), + parameters: vecmap(parameters, |(name, typ)| Param { + visibility: Visibility::Private, + pattern: Pattern::Identifier(name.clone()), + typ: typ.clone(), + span: name.span(), + }), + body: BlockExpression { is_unsafe: false, statements: Vec::new() }, + span: name.span(), + where_clause: where_clause.to_vec(), + return_type: return_type.clone(), + return_visibility: Visibility::Private, + }; + + let mut function = NoirFunction { kind, def }; + self.define_function_meta(&mut function, func_id, true); + self.elaborate_function(func_id); + let _ = self.scopes.end_function(); + // Don't check the scope tree for unused variables, they can't be used in a declaration anyway. + self.generics.truncate(old_generic_count); + } +} diff --git a/compiler/noirc_frontend/src/elaborator/types.rs b/compiler/noirc_frontend/src/elaborator/types.rs new file mode 100644 index 00000000000..3baa7054fc5 --- /dev/null +++ b/compiler/noirc_frontend/src/elaborator/types.rs @@ -0,0 +1,1468 @@ +use std::{collections::BTreeMap, rc::Rc}; + +use acvm::acir::AcirField; +use iter_extended::vecmap; +use noirc_errors::{Location, Span}; + +use crate::{ + ast::{BinaryOpKind, IntegerBitSize, UnresolvedGenerics, UnresolvedTypeExpression}, + hir::{ + comptime::{Interpreter, Value}, + def_map::ModuleDefId, + resolution::{ + errors::ResolverError, + resolver::{verify_mutable_reference, SELF_TYPE_NAME}, + }, + type_check::{Source, TypeCheckError}, + }, + hir_def::{ + expr::{ + HirBinaryOp, HirCallExpression, HirMemberAccess, HirMethodReference, + HirPrefixExpression, + }, + function::{FuncMeta, Parameters}, + traits::TraitConstraint, + }, + macros_api::{ + HirExpression, HirLiteral, HirStatement, Path, PathKind, SecondaryAttribute, Signedness, + UnaryOp, UnresolvedType, UnresolvedTypeData, + }, + node_interner::{DefinitionKind, ExprId, GlobalId, TraitId, TraitImplKind, TraitMethodId}, + Generics, Type, TypeBinding, TypeVariable, TypeVariableKind, +}; + +use super::{lints, Elaborator}; + +impl<'context> Elaborator<'context> { + /// Translates an UnresolvedType to a Type + pub(super) fn resolve_type(&mut self, typ: UnresolvedType) -> Type { + let span = typ.span; + let resolved_type = self.resolve_type_inner(typ); + if resolved_type.is_nested_slice() { + self.push_err(ResolverError::NestedSlices { span: span.unwrap() }); + } + resolved_type + } + + /// Translates an UnresolvedType into a Type and appends any + /// freshly created TypeVariables created to new_variables. + pub fn resolve_type_inner(&mut self, typ: UnresolvedType) -> Type { + use crate::ast::UnresolvedTypeData::*; + + let resolved_type = match typ.typ { + FieldElement => Type::FieldElement, + Array(size, elem) => { + let elem = Box::new(self.resolve_type_inner(*elem)); + let size = self.convert_expression_type(size); + Type::Array(Box::new(size), elem) + } + Slice(elem) => { + let elem = Box::new(self.resolve_type_inner(*elem)); + Type::Slice(elem) + } + Expression(expr) => self.convert_expression_type(expr), + Integer(sign, bits) => Type::Integer(sign, bits), + Bool => Type::Bool, + String(size) => { + let resolved_size = self.convert_expression_type(size); + Type::String(Box::new(resolved_size)) + } + FormatString(size, fields) => { + let resolved_size = self.convert_expression_type(size); + let fields = self.resolve_type_inner(*fields); + Type::FmtString(Box::new(resolved_size), Box::new(fields)) + } + Code => Type::Code, + Unit => Type::Unit, + Unspecified => Type::Error, + Error => Type::Error, + Named(path, args, _) => self.resolve_named_type(path, args), + TraitAsType(path, args) => self.resolve_trait_as_type(path, args), + + Tuple(fields) => Type::Tuple(vecmap(fields, |field| self.resolve_type_inner(field))), + Function(args, ret, env) => { + let args = vecmap(args, |arg| self.resolve_type_inner(arg)); + let ret = Box::new(self.resolve_type_inner(*ret)); + + // expect() here is valid, because the only places we don't have a span are omitted types + // e.g. a function without return type implicitly has a spanless UnresolvedType::Unit return type + // To get an invalid env type, the user must explicitly specify the type, which will have a span + let env_span = + env.span.expect("Unexpected missing span for closure environment type"); + + let env = Box::new(self.resolve_type_inner(*env)); + + match *env { + Type::Unit | Type::Tuple(_) | Type::NamedGeneric(_, _) => { + Type::Function(args, ret, env) + } + _ => { + self.push_err(ResolverError::InvalidClosureEnvironment { + typ: *env, + span: env_span, + }); + Type::Error + } + } + } + MutableReference(element) => { + Type::MutableReference(Box::new(self.resolve_type_inner(*element))) + } + Parenthesized(typ) => self.resolve_type_inner(*typ), + }; + + if let Type::Struct(_, _) = resolved_type { + if let Some(unresolved_span) = typ.span { + // Record the location of the type reference + self.interner.push_type_ref_location( + resolved_type.clone(), + Location::new(unresolved_span, self.file), + ); + } + } + resolved_type + } + + pub fn find_generic(&self, target_name: &str) -> Option<&(Rc, TypeVariable, Span)> { + self.generics.iter().find(|(name, _, _)| name.as_ref() == target_name) + } + + fn resolve_named_type(&mut self, path: Path, args: Vec) -> Type { + if args.is_empty() { + if let Some(typ) = self.lookup_generic_or_global_type(&path) { + return typ; + } + } + + // Check if the path is a type variable first. We currently disallow generics on type + // variables since we do not support higher-kinded types. + if path.segments.len() == 1 { + let name = &path.last_segment().0.contents; + + if name == SELF_TYPE_NAME { + if let Some(self_type) = self.self_type.clone() { + if !args.is_empty() { + self.push_err(ResolverError::GenericsOnSelfType { span: path.span() }); + } + return self_type; + } + } + } + + let span = path.span(); + let mut args = vecmap(args, |arg| self.resolve_type_inner(arg)); + + if let Some(type_alias) = self.lookup_type_alias(path.clone()) { + let type_alias = type_alias.borrow(); + let expected_generic_count = type_alias.generics.len(); + let type_alias_string = type_alias.to_string(); + let id = type_alias.id; + + self.verify_generics_count(expected_generic_count, &mut args, span, || { + type_alias_string + }); + + if let Some(item) = self.current_item { + self.interner.add_type_alias_dependency(item, id); + } + + // Collecting Type Alias references [Location]s to be used by LSP in order + // to resolve the definition of the type alias + self.interner.add_type_alias_ref(id, Location::new(span, self.file)); + + // Because there is no ordering to when type aliases (and other globals) are resolved, + // it is possible for one to refer to an Error type and issue no error if it is set + // equal to another type alias. Fixing this fully requires an analysis to create a DFG + // of definition ordering, but for now we have an explicit check here so that we at + // least issue an error that the type was not found instead of silently passing. + let alias = self.interner.get_type_alias(id); + return Type::Alias(alias, args); + } + + match self.lookup_struct_or_error(path) { + Some(struct_type) => { + if self.resolving_ids.contains(&struct_type.borrow().id) { + self.push_err(ResolverError::SelfReferentialStruct { + span: struct_type.borrow().name.span(), + }); + + return Type::Error; + } + + let expected_generic_count = struct_type.borrow().generics.len(); + if !self.in_contract + && self + .interner + .struct_attributes(&struct_type.borrow().id) + .iter() + .any(|attr| matches!(attr, SecondaryAttribute::Abi(_))) + { + self.push_err(ResolverError::AbiAttributeOutsideContract { + span: struct_type.borrow().name.span(), + }); + } + self.verify_generics_count(expected_generic_count, &mut args, span, || { + struct_type.borrow().to_string() + }); + + if let Some(current_item) = self.current_item { + let dependency_id = struct_type.borrow().id; + self.interner.add_type_dependency(current_item, dependency_id); + } + + Type::Struct(struct_type, args) + } + None => Type::Error, + } + } + + fn resolve_trait_as_type(&mut self, path: Path, args: Vec) -> Type { + let args = vecmap(args, |arg| self.resolve_type_inner(arg)); + + if let Some(t) = self.lookup_trait_or_error(path) { + Type::TraitAsType(t.id, Rc::new(t.name.to_string()), args) + } else { + Type::Error + } + } + + fn verify_generics_count( + &mut self, + expected_count: usize, + args: &mut Vec, + span: Span, + type_name: impl FnOnce() -> String, + ) { + if args.len() != expected_count { + self.push_err(ResolverError::IncorrectGenericCount { + span, + item_name: type_name(), + actual: args.len(), + expected: expected_count, + }); + + // Fix the generic count so we can continue typechecking + args.resize_with(expected_count, || Type::Error); + } + } + + pub fn lookup_generic_or_global_type(&mut self, path: &Path) -> Option { + if path.segments.len() == 1 { + let name = &path.last_segment().0.contents; + if let Some((name, var, _)) = self.find_generic(name) { + return Some(Type::NamedGeneric(var.clone(), name.clone())); + } + } + + // If we cannot find a local generic of the same name, try to look up a global + match self.resolve_path(path.clone()) { + Ok(ModuleDefId::GlobalId(id)) => { + if let Some(current_item) = self.current_item { + self.interner.add_global_dependency(current_item, id); + } + + Some(Type::Constant(self.eval_global_as_array_length(id, path))) + } + _ => None, + } + } + + pub(super) fn convert_expression_type(&mut self, length: UnresolvedTypeExpression) -> Type { + match length { + UnresolvedTypeExpression::Variable(path) => { + self.lookup_generic_or_global_type(&path).unwrap_or_else(|| { + self.push_err(ResolverError::NoSuchNumericTypeVariable { path }); + Type::Constant(0) + }) + } + UnresolvedTypeExpression::Constant(int, _) => Type::Constant(int), + UnresolvedTypeExpression::BinaryOperation(lhs, op, rhs, _) => { + let (lhs_span, rhs_span) = (lhs.span(), rhs.span()); + let lhs = self.convert_expression_type(*lhs); + let rhs = self.convert_expression_type(*rhs); + + match (lhs, rhs) { + (Type::Constant(lhs), Type::Constant(rhs)) => { + Type::Constant(op.function()(lhs, rhs)) + } + (lhs, _) => { + let span = + if !matches!(lhs, Type::Constant(_)) { lhs_span } else { rhs_span }; + self.push_err(ResolverError::InvalidArrayLengthExpr { span }); + Type::Constant(0) + } + } + } + } + } + + // this resolves Self::some_static_method, inside an impl block (where we don't have a concrete self_type) + // + // Returns the trait method, trait constraint, and whether the impl is assumed to exist by a where clause or not + // E.g. `t.method()` with `where T: Foo` in scope will return `(Foo::method, T, vec![Bar])` + fn resolve_trait_static_method_by_self( + &mut self, + path: &Path, + ) -> Option<(TraitMethodId, TraitConstraint, bool)> { + let trait_id = self.trait_id?; + + if path.kind == PathKind::Plain && path.segments.len() == 2 { + let name = &path.segments[0].0.contents; + let method = &path.segments[1]; + + if name == SELF_TYPE_NAME { + let the_trait = self.interner.get_trait(trait_id); + let method = the_trait.find_method(method.0.contents.as_str())?; + + let constraint = TraitConstraint { + typ: self.self_type.clone()?, + trait_generics: Type::from_generics(&the_trait.generics), + trait_id, + }; + return Some((method, constraint, false)); + } + } + None + } + + // this resolves TraitName::some_static_method + // + // Returns the trait method, trait constraint, and whether the impl is assumed to exist by a where clause or not + // E.g. `t.method()` with `where T: Foo` in scope will return `(Foo::method, T, vec![Bar])` + fn resolve_trait_static_method( + &mut self, + path: &Path, + ) -> Option<(TraitMethodId, TraitConstraint, bool)> { + if path.kind == PathKind::Plain && path.segments.len() == 2 { + let method = &path.segments[1]; + + let mut trait_path = path.clone(); + trait_path.pop(); + let trait_id = self.lookup(trait_path).ok()?; + let the_trait = self.interner.get_trait(trait_id); + + let method = the_trait.find_method(method.0.contents.as_str())?; + let constraint = TraitConstraint { + typ: Type::TypeVariable( + the_trait.self_type_typevar.clone(), + TypeVariableKind::Normal, + ), + trait_generics: Type::from_generics(&the_trait.generics), + trait_id, + }; + return Some((method, constraint, false)); + } + None + } + + // This resolves a static trait method T::trait_method by iterating over the where clause + // + // Returns the trait method, trait constraint, and whether the impl is assumed from a where + // clause. This is always true since this helper searches where clauses for a generic constraint. + // E.g. `t.method()` with `where T: Foo` in scope will return `(Foo::method, T, vec![Bar])` + fn resolve_trait_method_by_named_generic( + &mut self, + path: &Path, + ) -> Option<(TraitMethodId, TraitConstraint, bool)> { + if path.segments.len() != 2 { + return None; + } + + for constraint in self.trait_bounds.clone() { + if let Type::NamedGeneric(_, name) = &constraint.typ { + // if `path` is `T::method_name`, we're looking for constraint of the form `T: SomeTrait` + if path.segments[0].0.contents != name.as_str() { + continue; + } + + let the_trait = self.interner.get_trait(constraint.trait_id); + if let Some(method) = + the_trait.find_method(path.segments.last().unwrap().0.contents.as_str()) + { + return Some((method, constraint, true)); + } + } + } + None + } + + // Try to resolve the given trait method path. + // + // Returns the trait method, trait constraint, and whether the impl is assumed to exist by a where clause or not + // E.g. `t.method()` with `where T: Foo` in scope will return `(Foo::method, T, vec![Bar])` + pub(super) fn resolve_trait_generic_path( + &mut self, + path: &Path, + ) -> Option<(TraitMethodId, TraitConstraint, bool)> { + self.resolve_trait_static_method_by_self(path) + .or_else(|| self.resolve_trait_static_method(path)) + .or_else(|| self.resolve_trait_method_by_named_generic(path)) + } + + fn eval_global_as_array_length(&mut self, global_id: GlobalId, path: &Path) -> u32 { + let Some(stmt) = self.interner.get_global_let_statement(global_id) else { + if let Some(global) = self.unresolved_globals.remove(&global_id) { + self.elaborate_global(global); + return self.eval_global_as_array_length(global_id, path); + } else { + let path = path.clone(); + self.push_err(ResolverError::NoSuchNumericTypeVariable { path }); + return 0; + } + }; + + let length = stmt.expression; + let span = self.interner.expr_span(&length); + let result = self.try_eval_array_length_id(length, span); + + match result.map(|length| length.try_into()) { + Ok(Ok(length_value)) => return length_value, + Ok(Err(_cast_err)) => self.push_err(ResolverError::IntegerTooLarge { span }), + Err(Some(error)) => self.push_err(error), + Err(None) => (), + } + 0 + } + + fn try_eval_array_length_id( + &self, + rhs: ExprId, + span: Span, + ) -> Result> { + // Arbitrary amount of recursive calls to try before giving up + let fuel = 100; + self.try_eval_array_length_id_with_fuel(rhs, span, fuel) + } + + fn try_eval_array_length_id_with_fuel( + &self, + rhs: ExprId, + span: Span, + fuel: u32, + ) -> Result> { + if fuel == 0 { + // If we reach here, it is likely from evaluating cyclic globals. We expect an error to + // be issued for them after name resolution so issue no error now. + return Err(None); + } + + match self.interner.expression(&rhs) { + HirExpression::Literal(HirLiteral::Integer(int, false)) => { + int.try_into_u128().ok_or(Some(ResolverError::IntegerTooLarge { span })) + } + HirExpression::Ident(ident, _) => { + let definition = self.interner.definition(ident.id); + match definition.kind { + DefinitionKind::Global(global_id) => { + let let_statement = self.interner.get_global_let_statement(global_id); + if let Some(let_statement) = let_statement { + let expression = let_statement.expression; + self.try_eval_array_length_id_with_fuel(expression, span, fuel - 1) + } else { + Err(Some(ResolverError::InvalidArrayLengthExpr { span })) + } + } + _ => Err(Some(ResolverError::InvalidArrayLengthExpr { span })), + } + } + HirExpression::Infix(infix) => { + let lhs = self.try_eval_array_length_id_with_fuel(infix.lhs, span, fuel - 1)?; + let rhs = self.try_eval_array_length_id_with_fuel(infix.rhs, span, fuel - 1)?; + + match infix.operator.kind { + BinaryOpKind::Add => Ok(lhs + rhs), + BinaryOpKind::Subtract => Ok(lhs - rhs), + BinaryOpKind::Multiply => Ok(lhs * rhs), + BinaryOpKind::Divide => Ok(lhs / rhs), + BinaryOpKind::Equal => Ok((lhs == rhs) as u128), + BinaryOpKind::NotEqual => Ok((lhs != rhs) as u128), + BinaryOpKind::Less => Ok((lhs < rhs) as u128), + BinaryOpKind::LessEqual => Ok((lhs <= rhs) as u128), + BinaryOpKind::Greater => Ok((lhs > rhs) as u128), + BinaryOpKind::GreaterEqual => Ok((lhs >= rhs) as u128), + BinaryOpKind::And => Ok(lhs & rhs), + BinaryOpKind::Or => Ok(lhs | rhs), + BinaryOpKind::Xor => Ok(lhs ^ rhs), + BinaryOpKind::ShiftRight => Ok(lhs >> rhs), + BinaryOpKind::ShiftLeft => Ok(lhs << rhs), + BinaryOpKind::Modulo => Ok(lhs % rhs), + } + } + HirExpression::Cast(cast) => { + let lhs = self.try_eval_array_length_id_with_fuel(cast.lhs, span, fuel - 1)?; + let lhs_value = Value::Field(lhs.into()); + let evaluated_value = + Interpreter::evaluate_cast_one_step(&cast, rhs, lhs_value, self.interner) + .map_err(|error| Some(ResolverError::ArrayLengthInterpreter { error }))?; + + evaluated_value + .to_u128() + .ok_or_else(|| Some(ResolverError::InvalidArrayLengthExpr { span })) + } + _other => Err(Some(ResolverError::InvalidArrayLengthExpr { span })), + } + } + + pub(super) fn unify( + &mut self, + actual: &Type, + expected: &Type, + make_error: impl FnOnce() -> TypeCheckError, + ) { + let mut errors = Vec::new(); + actual.unify(expected, &mut errors, make_error); + self.errors.extend(errors.into_iter().map(|error| (error.into(), self.file))); + } + + /// Wrapper of Type::unify_with_coercions using self.errors + pub(super) fn unify_with_coercions( + &mut self, + actual: &Type, + expected: &Type, + expression: ExprId, + make_error: impl FnOnce() -> TypeCheckError, + ) { + let mut errors = Vec::new(); + actual.unify_with_coercions(expected, expression, self.interner, &mut errors, make_error); + self.errors.extend(errors.into_iter().map(|error| (error.into(), self.file))); + } + + /// Return a fresh integer or field type variable and log it + /// in self.type_variables to default it later. + pub(super) fn polymorphic_integer_or_field(&mut self) -> Type { + let typ = Type::polymorphic_integer_or_field(self.interner); + self.type_variables.push(typ.clone()); + typ + } + + /// Return a fresh integer type variable and log it + /// in self.type_variables to default it later. + pub(super) fn polymorphic_integer(&mut self) -> Type { + let typ = Type::polymorphic_integer(self.interner); + self.type_variables.push(typ.clone()); + typ + } + + /// Translates a (possibly Unspecified) UnresolvedType to a Type. + /// Any UnresolvedType::Unspecified encountered are replaced with fresh type variables. + pub(super) fn resolve_inferred_type(&mut self, typ: UnresolvedType) -> Type { + match &typ.typ { + UnresolvedTypeData::Unspecified => self.interner.next_type_variable(), + _ => self.resolve_type(typ), + } + } + + pub(super) fn type_check_prefix_operand( + &mut self, + op: &crate::ast::UnaryOp, + rhs_type: &Type, + span: Span, + ) -> Type { + let unify = |this: &mut Self, expected| { + this.unify(rhs_type, &expected, || TypeCheckError::TypeMismatch { + expr_typ: rhs_type.to_string(), + expected_typ: expected.to_string(), + expr_span: span, + }); + expected + }; + + match op { + crate::ast::UnaryOp::Minus => { + if rhs_type.is_unsigned() { + self.push_err(TypeCheckError::InvalidUnaryOp { + kind: rhs_type.to_string(), + span, + }); + } + let expected = self.polymorphic_integer_or_field(); + self.unify(rhs_type, &expected, || TypeCheckError::InvalidUnaryOp { + kind: rhs_type.to_string(), + span, + }); + expected + } + crate::ast::UnaryOp::Not => { + let rhs_type = rhs_type.follow_bindings(); + + // `!` can work on booleans or integers + if matches!(rhs_type, Type::Integer(..)) { + return rhs_type; + } + + unify(self, Type::Bool) + } + crate::ast::UnaryOp::MutableReference => { + Type::MutableReference(Box::new(rhs_type.follow_bindings())) + } + crate::ast::UnaryOp::Dereference { implicitly_added: _ } => { + let element_type = self.interner.next_type_variable(); + unify(self, Type::MutableReference(Box::new(element_type.clone()))); + element_type + } + } + } + + /// Insert as many dereference operations as necessary to automatically dereference a method + /// call object to its base value type T. + pub(super) fn insert_auto_dereferences(&mut self, object: ExprId, typ: Type) -> (ExprId, Type) { + if let Type::MutableReference(element) = typ { + let location = self.interner.id_location(object); + + let object = self.interner.push_expr(HirExpression::Prefix(HirPrefixExpression { + operator: UnaryOp::Dereference { implicitly_added: true }, + rhs: object, + })); + self.interner.push_expr_type(object, element.as_ref().clone()); + self.interner.push_expr_location(object, location.span, location.file); + + // Recursively dereference to allow for converting &mut &mut T to T + self.insert_auto_dereferences(object, *element) + } else { + (object, typ) + } + } + + /// Given a method object: `(*foo).bar` of a method call `(*foo).bar.baz()`, remove the + /// implicitly added dereference operator if one is found. + /// + /// Returns Some(new_expr_id) if a dereference was removed and None otherwise. + fn try_remove_implicit_dereference(&mut self, object: ExprId) -> Option { + match self.interner.expression(&object) { + HirExpression::MemberAccess(mut access) => { + let new_lhs = self.try_remove_implicit_dereference(access.lhs)?; + access.lhs = new_lhs; + access.is_offset = true; + + // `object` will have a different type now, which will be filled in + // later when type checking the method call as a function call. + self.interner.replace_expr(&object, HirExpression::MemberAccess(access)); + Some(object) + } + HirExpression::Prefix(prefix) => match prefix.operator { + // Found a dereference we can remove. Now just replace it with its rhs to remove it. + UnaryOp::Dereference { implicitly_added: true } => Some(prefix.rhs), + _ => None, + }, + _ => None, + } + } + + fn bind_function_type_impl( + &mut self, + fn_params: &[Type], + fn_ret: &Type, + callsite_args: &[(Type, ExprId, Span)], + span: Span, + ) -> Type { + if fn_params.len() != callsite_args.len() { + self.push_err(TypeCheckError::ParameterCountMismatch { + expected: fn_params.len(), + found: callsite_args.len(), + span, + }); + return Type::Error; + } + + for (param, (arg, _, arg_span)) in fn_params.iter().zip(callsite_args) { + self.unify(arg, param, || TypeCheckError::TypeMismatch { + expected_typ: param.to_string(), + expr_typ: arg.to_string(), + expr_span: *arg_span, + }); + } + + fn_ret.clone() + } + + pub(super) fn bind_function_type( + &mut self, + function: Type, + args: Vec<(Type, ExprId, Span)>, + span: Span, + ) -> Type { + // Could do a single unification for the entire function type, but matching beforehand + // lets us issue a more precise error on the individual argument that fails to type check. + match function { + Type::TypeVariable(binding, TypeVariableKind::Normal) => { + if let TypeBinding::Bound(typ) = &*binding.borrow() { + return self.bind_function_type(typ.clone(), args, span); + } + + let ret = self.interner.next_type_variable(); + let args = vecmap(args, |(arg, _, _)| arg); + let env_type = self.interner.next_type_variable(); + let expected = Type::Function(args, Box::new(ret.clone()), Box::new(env_type)); + + if let Err(error) = binding.try_bind(expected, span) { + self.push_err(error); + } + ret + } + // The closure env is ignored on purpose: call arguments never place + // constraints on closure environments. + Type::Function(parameters, ret, _env) => { + self.bind_function_type_impl(¶meters, &ret, &args, span) + } + Type::Error => Type::Error, + found => { + self.push_err(TypeCheckError::ExpectedFunction { found, span }); + Type::Error + } + } + } + + pub(super) fn check_cast(&mut self, from: Type, to: &Type, span: Span) -> Type { + match from.follow_bindings() { + Type::Integer(..) + | Type::FieldElement + | Type::TypeVariable(_, TypeVariableKind::IntegerOrField) + | Type::TypeVariable(_, TypeVariableKind::Integer) + | Type::Bool => (), + + Type::TypeVariable(_, _) => { + self.push_err(TypeCheckError::TypeAnnotationsNeeded { span }); + return Type::Error; + } + Type::Error => return Type::Error, + from => { + self.push_err(TypeCheckError::InvalidCast { from, span }); + return Type::Error; + } + } + + match to { + Type::Integer(sign, bits) => Type::Integer(*sign, *bits), + Type::FieldElement => Type::FieldElement, + Type::Bool => Type::Bool, + Type::Error => Type::Error, + _ => { + self.push_err(TypeCheckError::UnsupportedCast { span }); + Type::Error + } + } + } + + // Given a binary comparison operator and another type. This method will produce the output type + // and a boolean indicating whether to use the trait impl corresponding to the operator + // or not. A value of false indicates the caller to use a primitive operation for this + // operator, while a true value indicates a user-provided trait impl is required. + fn comparator_operand_type_rules( + &mut self, + lhs_type: &Type, + rhs_type: &Type, + op: &HirBinaryOp, + span: Span, + ) -> Result<(Type, bool), TypeCheckError> { + use Type::*; + + match (lhs_type, rhs_type) { + // Avoid reporting errors multiple times + (Error, _) | (_, Error) => Ok((Bool, false)), + (Alias(alias, args), other) | (other, Alias(alias, args)) => { + let alias = alias.borrow().get_type(args); + self.comparator_operand_type_rules(&alias, other, op, span) + } + + // Matches on TypeVariable must be first to follow any type + // bindings. + (TypeVariable(var, _), other) | (other, TypeVariable(var, _)) => { + if let TypeBinding::Bound(binding) = &*var.borrow() { + return self.comparator_operand_type_rules(other, binding, op, span); + } + + let use_impl = self.bind_type_variables_for_infix(lhs_type, op, rhs_type, span); + Ok((Bool, use_impl)) + } + (Integer(sign_x, bit_width_x), Integer(sign_y, bit_width_y)) => { + if sign_x != sign_y { + return Err(TypeCheckError::IntegerSignedness { + sign_x: *sign_x, + sign_y: *sign_y, + span, + }); + } + if bit_width_x != bit_width_y { + return Err(TypeCheckError::IntegerBitWidth { + bit_width_x: *bit_width_x, + bit_width_y: *bit_width_y, + span, + }); + } + Ok((Bool, false)) + } + (FieldElement, FieldElement) => { + if op.kind.is_valid_for_field_type() { + Ok((Bool, false)) + } else { + Err(TypeCheckError::FieldComparison { span }) + } + } + + // <= and friends are technically valid for booleans, just not very useful + (Bool, Bool) => Ok((Bool, false)), + + (lhs, rhs) => { + self.unify(lhs, rhs, || TypeCheckError::TypeMismatchWithSource { + expected: lhs.clone(), + actual: rhs.clone(), + span: op.location.span, + source: Source::Binary, + }); + Ok((Bool, true)) + } + } + } + + /// Handles the TypeVariable case for checking binary operators. + /// Returns true if we should use the impl for the operator instead of the primitive + /// version of it. + fn bind_type_variables_for_infix( + &mut self, + lhs_type: &Type, + op: &HirBinaryOp, + rhs_type: &Type, + span: Span, + ) -> bool { + self.unify(lhs_type, rhs_type, || TypeCheckError::TypeMismatchWithSource { + expected: lhs_type.clone(), + actual: rhs_type.clone(), + source: Source::Binary, + span, + }); + + let use_impl = !lhs_type.is_numeric(); + + // If this operator isn't valid for fields we have to possibly narrow + // TypeVariableKind::IntegerOrField to TypeVariableKind::Integer. + // Doing so also ensures a type error if Field is used. + // The is_numeric check is to allow impls for custom types to bypass this. + if !op.kind.is_valid_for_field_type() && lhs_type.is_numeric() { + let target = Type::polymorphic_integer(self.interner); + + use crate::ast::BinaryOpKind::*; + use TypeCheckError::*; + self.unify(lhs_type, &target, || match op.kind { + Less | LessEqual | Greater | GreaterEqual => FieldComparison { span }, + And | Or | Xor | ShiftRight | ShiftLeft => FieldBitwiseOp { span }, + Modulo => FieldModulo { span }, + other => unreachable!("Operator {other:?} should be valid for Field"), + }); + } + + use_impl + } + + // Given a binary operator and another type. This method will produce the output type + // and a boolean indicating whether to use the trait impl corresponding to the operator + // or not. A value of false indicates the caller to use a primitive operation for this + // operator, while a true value indicates a user-provided trait impl is required. + pub(super) fn infix_operand_type_rules( + &mut self, + lhs_type: &Type, + op: &HirBinaryOp, + rhs_type: &Type, + span: Span, + ) -> Result<(Type, bool), TypeCheckError> { + if op.kind.is_comparator() { + return self.comparator_operand_type_rules(lhs_type, rhs_type, op, span); + } + + use Type::*; + match (lhs_type, rhs_type) { + // An error type on either side will always return an error + (Error, _) | (_, Error) => Ok((Error, false)), + (Alias(alias, args), other) | (other, Alias(alias, args)) => { + let alias = alias.borrow().get_type(args); + self.infix_operand_type_rules(&alias, op, other, span) + } + + // Matches on TypeVariable must be first so that we follow any type + // bindings. + (TypeVariable(int, _), other) | (other, TypeVariable(int, _)) => { + if let TypeBinding::Bound(binding) = &*int.borrow() { + return self.infix_operand_type_rules(binding, op, other, span); + } + if op.kind == BinaryOpKind::ShiftLeft || op.kind == BinaryOpKind::ShiftRight { + self.unify( + rhs_type, + &Type::Integer(Signedness::Unsigned, IntegerBitSize::Eight), + || TypeCheckError::InvalidShiftSize { span }, + ); + let use_impl = if lhs_type.is_numeric() { + let integer_type = Type::polymorphic_integer(self.interner); + self.bind_type_variables_for_infix(lhs_type, op, &integer_type, span) + } else { + true + }; + return Ok((lhs_type.clone(), use_impl)); + } + let use_impl = self.bind_type_variables_for_infix(lhs_type, op, rhs_type, span); + Ok((other.clone(), use_impl)) + } + (Integer(sign_x, bit_width_x), Integer(sign_y, bit_width_y)) => { + if op.kind == BinaryOpKind::ShiftLeft || op.kind == BinaryOpKind::ShiftRight { + if *sign_y != Signedness::Unsigned || *bit_width_y != IntegerBitSize::Eight { + return Err(TypeCheckError::InvalidShiftSize { span }); + } + return Ok((Integer(*sign_x, *bit_width_x), false)); + } + if sign_x != sign_y { + return Err(TypeCheckError::IntegerSignedness { + sign_x: *sign_x, + sign_y: *sign_y, + span, + }); + } + if bit_width_x != bit_width_y { + return Err(TypeCheckError::IntegerBitWidth { + bit_width_x: *bit_width_x, + bit_width_y: *bit_width_y, + span, + }); + } + Ok((Integer(*sign_x, *bit_width_x), false)) + } + // The result of two Fields is always a witness + (FieldElement, FieldElement) => { + if !op.kind.is_valid_for_field_type() { + if op.kind == BinaryOpKind::Modulo { + return Err(TypeCheckError::FieldModulo { span }); + } else { + return Err(TypeCheckError::FieldBitwiseOp { span }); + } + } + Ok((FieldElement, false)) + } + + (Bool, Bool) => Ok((Bool, false)), + + (lhs, rhs) => { + if op.kind == BinaryOpKind::ShiftLeft || op.kind == BinaryOpKind::ShiftRight { + if rhs == &Type::Integer(Signedness::Unsigned, IntegerBitSize::Eight) { + return Ok((lhs.clone(), true)); + } + return Err(TypeCheckError::InvalidShiftSize { span }); + } + self.unify(lhs, rhs, || TypeCheckError::TypeMismatchWithSource { + expected: lhs.clone(), + actual: rhs.clone(), + span: op.location.span, + source: Source::Binary, + }); + Ok((lhs.clone(), true)) + } + } + } + + /// Prerequisite: verify_trait_constraint of the operator's trait constraint. + /// + /// Although by this point the operator is expected to already have a trait impl, + /// we still need to match the operator's type against the method's instantiated type + /// to ensure the instantiation bindings are correct and the monomorphizer can + /// re-apply the needed bindings. + pub(super) fn type_check_operator_method( + &mut self, + expr_id: ExprId, + trait_method_id: TraitMethodId, + object_type: &Type, + span: Span, + ) { + let the_trait = self.interner.get_trait(trait_method_id.trait_id); + + let method = &the_trait.methods[trait_method_id.method_index]; + let (method_type, mut bindings) = method.typ.clone().instantiate(self.interner); + + match method_type { + Type::Function(args, _, _) => { + // We can cheat a bit and match against only the object type here since no operator + // overload uses other generic parameters or return types aside from the object type. + let expected_object_type = &args[0]; + self.unify(object_type, expected_object_type, || TypeCheckError::TypeMismatch { + expected_typ: expected_object_type.to_string(), + expr_typ: object_type.to_string(), + expr_span: span, + }); + } + other => { + unreachable!("Expected operator method to have a function type, but found {other}") + } + } + + // We must also remember to apply these substitutions to the object_type + // referenced by the selected trait impl, if one has yet to be selected. + let impl_kind = self.interner.get_selected_impl_for_expression(expr_id); + if let Some(TraitImplKind::Assumed { object_type, trait_generics }) = impl_kind { + let the_trait = self.interner.get_trait(trait_method_id.trait_id); + let object_type = object_type.substitute(&bindings); + bindings.insert( + the_trait.self_type_typevar_id, + (the_trait.self_type_typevar.clone(), object_type.clone()), + ); + self.interner.select_impl_for_expression( + expr_id, + TraitImplKind::Assumed { object_type, trait_generics }, + ); + } + + self.interner.store_instantiation_bindings(expr_id, bindings); + } + + pub(super) fn type_check_member_access( + &mut self, + mut access: HirMemberAccess, + expr_id: ExprId, + lhs_type: Type, + span: Span, + ) -> Type { + let access_lhs = &mut access.lhs; + + let dereference_lhs = |this: &mut Self, lhs_type, element| { + let old_lhs = *access_lhs; + *access_lhs = this.interner.push_expr(HirExpression::Prefix(HirPrefixExpression { + operator: crate::ast::UnaryOp::Dereference { implicitly_added: true }, + rhs: old_lhs, + })); + this.interner.push_expr_type(old_lhs, lhs_type); + this.interner.push_expr_type(*access_lhs, element); + + let old_location = this.interner.id_location(old_lhs); + this.interner.push_expr_location(*access_lhs, span, old_location.file); + }; + + // If this access is just a field offset, we want to avoid dereferencing + let dereference_lhs = (!access.is_offset).then_some(dereference_lhs); + + match self.check_field_access(&lhs_type, &access.rhs.0.contents, span, dereference_lhs) { + Some((element_type, index)) => { + self.interner.set_field_index(expr_id, index); + // We must update `access` in case we added any dereferences to it + self.interner.replace_expr(&expr_id, HirExpression::MemberAccess(access)); + element_type + } + None => Type::Error, + } + } + + pub(super) fn lookup_method( + &mut self, + object_type: &Type, + method_name: &str, + span: Span, + ) -> Option { + 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) { + Some(method_id) => Some(HirMethodReference::FuncId(method_id)), + None => { + self.push_err(TypeCheckError::UnresolvedMethodCall { + method_name: method_name.to_string(), + object_type: object_type.clone(), + span, + }); + None + } + } + } + // TODO: We should allow method calls on `impl Trait`s eventually. + // For now it is fine since they are only allowed on return types. + Type::TraitAsType(..) => { + self.push_err(TypeCheckError::UnresolvedMethodCall { + method_name: method_name.to_string(), + object_type: object_type.clone(), + span, + }); + None + } + Type::NamedGeneric(_, _) => { + let func_meta = self.interner.function_meta( + &self.current_function.expect("unexpected method outside a function"), + ); + + for constraint in &func_meta.trait_constraints { + if *object_type == constraint.typ { + 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, + constraint.trait_generics.clone(), + )); + } + } + } + } + } + + self.push_err(TypeCheckError::UnresolvedMethodCall { + method_name: method_name.to_string(), + object_type: object_type.clone(), + span, + }); + None + } + // Mutable references to another type should resolve to methods of their element type. + // This may be a struct or a primitive type. + Type::MutableReference(element) => self + .interner + .lookup_primitive_trait_method_mut(element.as_ref(), method_name) + .map(HirMethodReference::FuncId) + .or_else(|| self.lookup_method(&element, method_name, span)), + + // 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, + + // The type variable must be unbound at this point since follow_bindings was called + Type::TypeVariable(_, TypeVariableKind::Normal) => { + self.push_err(TypeCheckError::TypeAnnotationsNeeded { span }); + None + } + + other => match self.interner.lookup_primitive_method(&other, method_name) { + Some(method_id) => Some(HirMethodReference::FuncId(method_id)), + None => { + self.push_err(TypeCheckError::UnresolvedMethodCall { + method_name: method_name.to_string(), + object_type: object_type.clone(), + span, + }); + None + } + }, + } + } + + pub(super) fn type_check_call( + &mut self, + call: &HirCallExpression, + func_type: Type, + args: Vec<(Type, ExprId, Span)>, + span: Span, + ) -> Type { + self.run_lint(|elaborator| { + lints::deprecated_function(elaborator.interner, call.func).map(Into::into) + }); + + let func_mod = self.current_function.map(|func| self.interner.function_modifiers(&func)); + let is_current_func_constrained = + func_mod.map_or(true, |func_mod| !func_mod.is_unconstrained); + let is_unconstrained_call = self.is_unconstrained_call(call.func); + let crossing_runtime_boundary = is_current_func_constrained && is_unconstrained_call; + if crossing_runtime_boundary { + let called_func_id = self + .interner + .lookup_function_from_expr(&call.func) + .expect("Called function should exist"); + self.run_lint(|elaborator| { + lints::oracle_called_from_constrained_function( + elaborator.interner, + &called_func_id, + is_current_func_constrained, + span, + ) + .map(Into::into) + }); + let errors = lints::unconstrained_function_args(&args); + for error in errors { + self.push_err(error); + } + } + + let return_type = self.bind_function_type(func_type, args, span); + + if crossing_runtime_boundary { + self.run_lint(|_| { + lints::unconstrained_function_return(&return_type, span).map(Into::into) + }); + } + + return_type + } + + fn is_unconstrained_call(&self, expr: ExprId) -> bool { + if let Some(func_id) = self.interner.lookup_function_from_expr(&expr) { + let modifiers = self.interner.function_modifiers(&func_id); + modifiers.is_unconstrained + } else { + false + } + } + + /// 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 + /// call: `bar(&mut foo)`. + /// + /// A notable corner case of this function is where it interacts with auto-deref of `.`. + /// If a field is being mutated e.g. `foo.bar.mutate_bar()` where `foo: &mut Foo`, the compiler + /// will insert a dereference before bar `(*foo).bar.mutate_bar()` which would cause us to + /// mutate a copy of bar rather than a reference to it. We must check for this corner case here + /// and remove the implicitly added dereference operator if we find one. + pub(super) fn try_add_mutable_reference_to_object( + &mut self, + function_type: &Type, + object_type: &mut Type, + object: &mut ExprId, + ) { + let expected_object_type = match function_type { + Type::Function(args, _, _) => args.first(), + Type::Forall(_, typ) => match typ.as_ref() { + Type::Function(args, _, _) => args.first(), + typ => unreachable!("Unexpected type for function: {typ}"), + }, + typ => unreachable!("Unexpected type for function: {typ}"), + }; + + if let Some(expected_object_type) = expected_object_type { + let actual_type = object_type.follow_bindings(); + + if matches!(expected_object_type.follow_bindings(), Type::MutableReference(_)) { + if !matches!(actual_type, Type::MutableReference(_)) { + if let Err(error) = verify_mutable_reference(self.interner, *object) { + self.push_err(TypeCheckError::ResolverError(error)); + } + + let new_type = Type::MutableReference(Box::new(actual_type)); + *object_type = new_type.clone(); + + // First try to remove a dereference operator that may have been implicitly + // inserted by a field access expression `foo.bar` on a mutable reference `foo`. + let new_object = self.try_remove_implicit_dereference(*object); + + // If that didn't work, then wrap the whole expression in an `&mut` + *object = new_object.unwrap_or_else(|| { + let location = self.interner.id_location(*object); + + let new_object = + self.interner.push_expr(HirExpression::Prefix(HirPrefixExpression { + operator: UnaryOp::MutableReference, + rhs: *object, + })); + self.interner.push_expr_type(new_object, new_type); + self.interner.push_expr_location(new_object, location.span, location.file); + new_object + }); + } + // Otherwise if the object type is a mutable reference and the method is not, insert as + // many dereferences as needed. + } else if matches!(actual_type, Type::MutableReference(_)) { + let (new_object, new_type) = self.insert_auto_dereferences(*object, actual_type); + *object_type = new_type; + *object = new_object; + } + } + } + + pub fn type_check_function_body(&mut self, body_type: Type, meta: &FuncMeta, body_id: ExprId) { + let (expr_span, empty_function) = self.function_info(body_id); + let declared_return_type = meta.return_type(); + + let func_span = self.interner.expr_span(&body_id); // XXX: We could be more specific and return the span of the last stmt, however stmts do not have spans yet + if let Type::TraitAsType(trait_id, _, generics) = declared_return_type { + if self.interner.lookup_trait_implementation(&body_type, *trait_id, generics).is_err() { + self.push_err(TypeCheckError::TypeMismatchWithSource { + expected: declared_return_type.clone(), + actual: body_type, + span: func_span, + source: Source::Return(meta.return_type.clone(), expr_span), + }); + } + } else { + self.unify_with_coercions(&body_type, declared_return_type, body_id, || { + let mut error = TypeCheckError::TypeMismatchWithSource { + expected: declared_return_type.clone(), + actual: body_type.clone(), + span: func_span, + source: Source::Return(meta.return_type.clone(), expr_span), + }; + + if empty_function { + error = error.add_context( + "implicitly returns `()` as its body has no tail or `return` expression", + ); + } + error + }); + } + } + + fn function_info(&self, function_body_id: ExprId) -> (noirc_errors::Span, bool) { + let (expr_span, empty_function) = + if let HirExpression::Block(block) = self.interner.expression(&function_body_id) { + let last_stmt = block.statements().last(); + let mut span = self.interner.expr_span(&function_body_id); + + if let Some(last_stmt) = last_stmt { + if let HirStatement::Expression(expr) = self.interner.statement(last_stmt) { + span = self.interner.expr_span(&expr); + } + } + + (span, last_stmt.is_none()) + } else { + (self.interner.expr_span(&function_body_id), false) + }; + (expr_span, empty_function) + } + + pub fn verify_trait_constraint( + &mut self, + object_type: &Type, + trait_id: TraitId, + trait_generics: &[Type], + function_ident_id: ExprId, + span: Span, + ) { + match self.interner.lookup_trait_implementation(object_type, trait_id, trait_generics) { + Ok(impl_kind) => { + self.interner.select_impl_for_expression(function_ident_id, impl_kind); + } + Err(erroring_constraints) => { + if erroring_constraints.is_empty() { + self.push_err(TypeCheckError::TypeAnnotationsNeeded { span }); + } else { + // 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)?; + let mut name = r#trait.name.to_string(); + if !constraint.trait_generics.is_empty() { + let generics = + vecmap(&constraint.trait_generics, ToString::to_string); + name += &format!("<{}>", generics.join(", ")); + } + Some((constraint.typ, name)) + }) + .collect::>>(); + + if let Some(constraints) = constraints { + self.push_err(TypeCheckError::NoMatchingImplFound { constraints, span }); + } + } + } + } + } + + pub fn add_existing_generics(&mut self, names: &UnresolvedGenerics, generics: &Generics) { + assert_eq!(names.len(), generics.len()); + + for (name, typevar) in names.iter().zip(generics) { + self.add_existing_generic(&name.0.contents, name.0.span(), typevar.clone()); + } + } + + pub fn add_existing_generic(&mut self, name: &str, span: Span, typevar: TypeVariable) { + // Check for name collisions of this generic + let rc_name = Rc::new(name.to_owned()); + + if let Some((_, _, first_span)) = self.find_generic(&rc_name) { + self.push_err(ResolverError::DuplicateDefinition { + name: name.to_owned(), + first_span: *first_span, + second_span: span, + }); + } else { + self.generics.push((rc_name, typevar, span)); + } + } + + pub fn find_numeric_generics( + parameters: &Parameters, + return_type: &Type, + ) -> Vec<(String, TypeVariable)> { + let mut found = BTreeMap::new(); + for (_, parameter, _) in ¶meters.0 { + Self::find_numeric_generics_in_type(parameter, &mut found); + } + Self::find_numeric_generics_in_type(return_type, &mut found); + found.into_iter().collect() + } + + fn find_numeric_generics_in_type(typ: &Type, found: &mut BTreeMap) { + match typ { + Type::FieldElement + | Type::Integer(_, _) + | Type::Bool + | Type::Unit + | Type::Error + | Type::TypeVariable(_, _) + | Type::Constant(_) + | Type::NamedGeneric(_, _) + | Type::Code + | Type::Forall(_, _) => (), + + Type::TraitAsType(_, _, args) => { + for arg in args { + Self::find_numeric_generics_in_type(arg, found); + } + } + + Type::Array(length, element_type) => { + if let Type::NamedGeneric(type_variable, name) = length.as_ref() { + found.insert(name.to_string(), type_variable.clone()); + } + Self::find_numeric_generics_in_type(element_type, found); + } + + Type::Slice(element_type) => { + Self::find_numeric_generics_in_type(element_type, found); + } + + Type::Tuple(fields) => { + for field in fields { + Self::find_numeric_generics_in_type(field, found); + } + } + + Type::Function(parameters, return_type, _env) => { + for parameter in parameters { + Self::find_numeric_generics_in_type(parameter, found); + } + Self::find_numeric_generics_in_type(return_type, found); + } + + Type::Struct(struct_type, generics) => { + for (i, generic) in generics.iter().enumerate() { + if let Type::NamedGeneric(type_variable, name) = generic { + if struct_type.borrow().generic_is_numeric(i) { + found.insert(name.to_string(), type_variable.clone()); + } + } else { + Self::find_numeric_generics_in_type(generic, found); + } + } + } + Type::Alias(alias, generics) => { + for (i, generic) in generics.iter().enumerate() { + if let Type::NamedGeneric(type_variable, name) = generic { + if alias.borrow().generic_is_numeric(i) { + found.insert(name.to_string(), type_variable.clone()); + } + } else { + Self::find_numeric_generics_in_type(generic, found); + } + } + } + Type::MutableReference(element) => Self::find_numeric_generics_in_type(element, found), + Type::String(length) => { + if let Type::NamedGeneric(type_variable, name) = length.as_ref() { + found.insert(name.to_string(), type_variable.clone()); + } + } + Type::FmtString(length, fields) => { + if let Type::NamedGeneric(type_variable, name) = length.as_ref() { + found.insert(name.to_string(), type_variable.clone()); + } + Self::find_numeric_generics_in_type(fields, found); + } + } + } +} diff --git a/compiler/noirc_frontend/src/hir/comptime/errors.rs b/compiler/noirc_frontend/src/hir/comptime/errors.rs new file mode 100644 index 00000000000..df4bc941f66 --- /dev/null +++ b/compiler/noirc_frontend/src/hir/comptime/errors.rs @@ -0,0 +1,277 @@ +use crate::{hir::def_collector::dc_crate::CompilationError, Type}; +use acvm::{acir::AcirField, FieldElement}; +use noirc_errors::{CustomDiagnostic, Location}; + +use super::value::Value; + +/// The possible errors that can halt the interpreter. +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum InterpreterError { + ArgumentCountMismatch { expected: usize, actual: usize, location: Location }, + TypeMismatch { expected: Type, value: Value, location: Location }, + NonComptimeVarReferenced { name: String, location: Location }, + IntegerOutOfRangeForType { value: FieldElement, typ: Type, location: Location }, + ErrorNodeEncountered { location: Location }, + NonFunctionCalled { value: Value, location: Location }, + NonBoolUsedInIf { value: Value, location: Location }, + NonBoolUsedInConstrain { value: Value, location: Location }, + FailingConstraint { message: Option, location: Location }, + NoMethodFound { name: String, typ: Type, location: Location }, + NonIntegerUsedInLoop { value: Value, location: Location }, + NonPointerDereferenced { value: Value, location: Location }, + NonTupleOrStructInMemberAccess { value: Value, location: Location }, + NonArrayIndexed { value: Value, location: Location }, + NonIntegerUsedAsIndex { value: Value, location: Location }, + NonIntegerIntegerLiteral { typ: Type, location: Location }, + NonIntegerArrayLength { typ: Type, location: Location }, + NonNumericCasted { value: Value, location: Location }, + IndexOutOfBounds { index: usize, length: usize, location: Location }, + ExpectedStructToHaveField { value: Value, field_name: String, location: Location }, + TypeUnsupported { typ: Type, location: Location }, + InvalidValueForUnary { value: Value, operator: &'static str, location: Location }, + InvalidValuesForBinary { lhs: Value, rhs: Value, operator: &'static str, location: Location }, + CastToNonNumericType { typ: Type, location: Location }, + QuoteInRuntimeCode { location: Location }, + NonStructInConstructor { typ: Type, location: Location }, + CannotInlineMacro { value: Value, location: Location }, + UnquoteFoundDuringEvaluation { location: Location }, + + Unimplemented { item: &'static str, location: Location }, + + // Perhaps this should be unreachable! due to type checking also preventing this error? + // Currently it and the Continue variant are the only interpreter errors without a Location field + BreakNotInLoop { location: Location }, + ContinueNotInLoop { location: Location }, + + // These cases are not errors, they are just used to prevent us from running more code + // until the loop can be resumed properly. These cases will never be displayed to users. + Break, + Continue, +} + +#[allow(unused)] +pub(super) type IResult = std::result::Result; + +impl From for CompilationError { + fn from(error: InterpreterError) -> Self { + CompilationError::InterpreterError(error) + } +} + +impl InterpreterError { + pub fn into_compilation_error_pair(self) -> (CompilationError, fm::FileId) { + let location = self.get_location(); + (CompilationError::InterpreterError(self), location.file) + } + + pub fn get_location(&self) -> Location { + match self { + InterpreterError::ArgumentCountMismatch { location, .. } + | InterpreterError::TypeMismatch { location, .. } + | InterpreterError::NonComptimeVarReferenced { location, .. } + | InterpreterError::IntegerOutOfRangeForType { location, .. } + | InterpreterError::ErrorNodeEncountered { location, .. } + | InterpreterError::NonFunctionCalled { location, .. } + | InterpreterError::NonBoolUsedInIf { location, .. } + | InterpreterError::NonBoolUsedInConstrain { location, .. } + | InterpreterError::FailingConstraint { location, .. } + | InterpreterError::NoMethodFound { location, .. } + | InterpreterError::NonIntegerUsedInLoop { location, .. } + | InterpreterError::NonPointerDereferenced { location, .. } + | InterpreterError::NonTupleOrStructInMemberAccess { location, .. } + | InterpreterError::NonArrayIndexed { location, .. } + | InterpreterError::NonIntegerUsedAsIndex { location, .. } + | InterpreterError::NonIntegerIntegerLiteral { location, .. } + | InterpreterError::NonIntegerArrayLength { location, .. } + | InterpreterError::NonNumericCasted { location, .. } + | InterpreterError::IndexOutOfBounds { location, .. } + | InterpreterError::ExpectedStructToHaveField { location, .. } + | InterpreterError::TypeUnsupported { location, .. } + | InterpreterError::InvalidValueForUnary { location, .. } + | InterpreterError::InvalidValuesForBinary { location, .. } + | InterpreterError::CastToNonNumericType { location, .. } + | InterpreterError::QuoteInRuntimeCode { location, .. } + | InterpreterError::NonStructInConstructor { location, .. } + | InterpreterError::CannotInlineMacro { location, .. } + | InterpreterError::UnquoteFoundDuringEvaluation { location, .. } + | InterpreterError::Unimplemented { location, .. } + | InterpreterError::BreakNotInLoop { location, .. } + | InterpreterError::ContinueNotInLoop { location, .. } => *location, + InterpreterError::Break | InterpreterError::Continue => { + panic!("Tried to get the location of Break/Continue error!") + } + } + } +} + +impl<'a> From<&'a InterpreterError> for CustomDiagnostic { + fn from(error: &'a InterpreterError) -> Self { + match error { + InterpreterError::ArgumentCountMismatch { expected, actual, location } => { + let only = if expected > actual { "only " } else { "" }; + let plural = if *expected == 1 { "" } else { "s" }; + let was_were = if *actual == 1 { "was" } else { "were" }; + let msg = format!( + "Expected {expected} argument{plural}, but {only}{actual} {was_were} provided" + ); + + let few_many = if actual < expected { "few" } else { "many" }; + let secondary = format!("Too {few_many} arguments"); + CustomDiagnostic::simple_error(msg, secondary, location.span) + } + InterpreterError::TypeMismatch { expected, value, location } => { + let typ = value.get_type(); + let msg = format!("Expected `{expected}` but a value of type `{typ}` was given"); + CustomDiagnostic::simple_error(msg, String::new(), location.span) + } + InterpreterError::NonComptimeVarReferenced { name, location } => { + let msg = format!("Non-comptime variable `{name}` referenced in comptime code"); + let secondary = "Non-comptime variables can't be used in comptime code".to_string(); + CustomDiagnostic::simple_error(msg, secondary, location.span) + } + InterpreterError::IntegerOutOfRangeForType { value, typ, location } => { + let int = match value.try_into_u128() { + Some(int) => int.to_string(), + None => value.to_string(), + }; + let msg = format!("{int} is outside the range of the {typ} type"); + CustomDiagnostic::simple_error(msg, String::new(), location.span) + } + InterpreterError::ErrorNodeEncountered { location } => { + let msg = "Internal Compiler Error: Error node encountered".to_string(); + let secondary = "This is a bug, please report this if found!".to_string(); + CustomDiagnostic::simple_error(msg, secondary, location.span) + } + InterpreterError::NonFunctionCalled { value, location } => { + let msg = "Only functions may be called".to_string(); + let secondary = format!("Expression has type {}", value.get_type()); + CustomDiagnostic::simple_error(msg, secondary, location.span) + } + InterpreterError::NonBoolUsedInIf { value, location } => { + let msg = format!("Expected a `bool` but found `{}`", value.get_type()); + let secondary = "If conditions must be a boolean value".to_string(); + CustomDiagnostic::simple_error(msg, secondary, location.span) + } + InterpreterError::NonBoolUsedInConstrain { value, location } => { + let msg = format!("Expected a `bool` but found `{}`", value.get_type()); + CustomDiagnostic::simple_error(msg, String::new(), location.span) + } + InterpreterError::FailingConstraint { message, location } => { + let (primary, secondary) = match message { + Some(msg) => (format!("{msg:?}"), "Assertion failed".into()), + None => ("Assertion failed".into(), String::new()), + }; + CustomDiagnostic::simple_error(primary, secondary, location.span) + } + InterpreterError::NoMethodFound { name, typ, location } => { + let msg = format!("No method named `{name}` found for type `{typ}`"); + CustomDiagnostic::simple_error(msg, String::new(), location.span) + } + InterpreterError::NonIntegerUsedInLoop { value, location } => { + let typ = value.get_type(); + let msg = format!("Non-integer type `{typ}` used in for loop"); + let secondary = if matches!(typ.as_ref(), &Type::FieldElement) { + "`field` is not an integer type, try `u32` instead".to_string() + } else { + String::new() + }; + CustomDiagnostic::simple_error(msg, secondary, location.span) + } + InterpreterError::NonPointerDereferenced { value, location } => { + let typ = value.get_type(); + let msg = format!("Only references may be dereferenced, but found `{typ}`"); + CustomDiagnostic::simple_error(msg, String::new(), location.span) + } + InterpreterError::NonTupleOrStructInMemberAccess { value, location } => { + let msg = format!("The type `{}` has no fields to access", value.get_type()); + CustomDiagnostic::simple_error(msg, String::new(), location.span) + } + InterpreterError::NonArrayIndexed { value, location } => { + let msg = format!("Expected an array or slice but found a(n) {}", value.get_type()); + let secondary = "Only arrays or slices may be indexed".into(); + CustomDiagnostic::simple_error(msg, secondary, location.span) + } + InterpreterError::NonIntegerUsedAsIndex { value, location } => { + let msg = format!("Expected an integer but found a(n) {}", value.get_type()); + let secondary = + "Only integers may be indexed. Note that this excludes `field`s".into(); + CustomDiagnostic::simple_error(msg, secondary, location.span) + } + InterpreterError::NonIntegerIntegerLiteral { typ, location } => { + let msg = format!("This integer literal somehow has the type `{typ}`"); + let secondary = "This is likely a bug".into(); + CustomDiagnostic::simple_error(msg, secondary, location.span) + } + InterpreterError::NonIntegerArrayLength { typ, location } => { + let msg = format!("Non-integer array length: `{typ}`"); + let secondary = "Array lengths must be integers".into(); + CustomDiagnostic::simple_error(msg, secondary, location.span) + } + InterpreterError::NonNumericCasted { value, location } => { + let msg = "Only numeric types may be casted".into(); + let secondary = format!("`{}` is non-numeric", value.get_type()); + CustomDiagnostic::simple_error(msg, secondary, location.span) + } + InterpreterError::IndexOutOfBounds { index, length, location } => { + let msg = format!("{index} is out of bounds for the array of length {length}"); + CustomDiagnostic::simple_error(msg, String::new(), location.span) + } + InterpreterError::ExpectedStructToHaveField { value, field_name, location } => { + let typ = value.get_type(); + let msg = format!("The type `{typ}` has no field named `{field_name}`"); + CustomDiagnostic::simple_error(msg, String::new(), location.span) + } + InterpreterError::TypeUnsupported { typ, location } => { + let msg = + format!("The type `{typ}` is currently unsupported in comptime expressions"); + CustomDiagnostic::simple_error(msg, String::new(), location.span) + } + InterpreterError::InvalidValueForUnary { value, operator, location } => { + let msg = format!("`{}` cannot be used with unary {operator}", value.get_type()); + CustomDiagnostic::simple_error(msg, String::new(), location.span) + } + InterpreterError::InvalidValuesForBinary { lhs, rhs, operator, location } => { + let lhs = lhs.get_type(); + let rhs = rhs.get_type(); + let msg = format!("No implementation for `{lhs}` {operator} `{rhs}`",); + CustomDiagnostic::simple_error(msg, String::new(), location.span) + } + InterpreterError::CastToNonNumericType { typ, location } => { + let msg = format!("Cannot cast to non-numeric type `{typ}`"); + CustomDiagnostic::simple_error(msg, String::new(), location.span) + } + InterpreterError::QuoteInRuntimeCode { location } => { + let msg = "`quote` may only be used in comptime code".into(); + CustomDiagnostic::simple_error(msg, String::new(), location.span) + } + InterpreterError::NonStructInConstructor { typ, location } => { + let msg = format!("`{typ}` is not a struct type"); + CustomDiagnostic::simple_error(msg, String::new(), location.span) + } + InterpreterError::CannotInlineMacro { value, location } => { + let msg = "Cannot inline value into runtime code if it contains references".into(); + let secondary = format!("Cannot inline value {value:?}"); + CustomDiagnostic::simple_error(msg, secondary, location.span) + } + InterpreterError::UnquoteFoundDuringEvaluation { location } => { + let msg = "Unquote found during comptime evaluation".into(); + let secondary = "This is a bug".into(); + CustomDiagnostic::simple_error(msg, secondary, location.span) + } + InterpreterError::Unimplemented { item, location } => { + let msg = format!("{item} is currently unimplemented"); + CustomDiagnostic::simple_error(msg, String::new(), location.span) + } + InterpreterError::BreakNotInLoop { location } => { + let msg = "There is no loop to break out of!".into(); + CustomDiagnostic::simple_error(msg, String::new(), location.span) + } + InterpreterError::ContinueNotInLoop { location } => { + let msg = "There is no loop to continue!".into(); + CustomDiagnostic::simple_error(msg, String::new(), location.span) + } + InterpreterError::Break => unreachable!("Uncaught InterpreterError::Break"), + InterpreterError::Continue => unreachable!("Uncaught InterpreterError::Continue"), + } + } +} diff --git a/compiler/noirc_frontend/src/hir/comptime/interpreter.rs b/compiler/noirc_frontend/src/hir/comptime/interpreter.rs new file mode 100644 index 00000000000..e1e19ad653c --- /dev/null +++ b/compiler/noirc_frontend/src/hir/comptime/interpreter.rs @@ -0,0 +1,1272 @@ +use std::{collections::hash_map::Entry, rc::Rc}; + +use acvm::{acir::AcirField, FieldElement}; +use im::Vector; +use iter_extended::try_vecmap; +use noirc_errors::Location; +use rustc_hash::FxHashMap as HashMap; + +use crate::ast::{BinaryOpKind, FunctionKind, IntegerBitSize, Signedness}; +use crate::{ + hir_def::{ + expr::{ + HirArrayLiteral, HirBlockExpression, HirCallExpression, HirCastExpression, + HirConstructorExpression, HirIdent, HirIfExpression, HirIndexExpression, + HirInfixExpression, HirLambda, HirMemberAccess, HirMethodCallExpression, + HirPrefixExpression, + }, + stmt::{ + HirAssignStatement, HirConstrainStatement, HirForStatement, HirLValue, HirLetStatement, + HirPattern, + }, + }, + macros_api::{HirExpression, HirLiteral, HirStatement, NodeInterner}, + node_interner::{DefinitionId, DefinitionKind, ExprId, FuncId, StmtId}, + Shared, Type, TypeBinding, TypeBindings, TypeVariableKind, +}; + +use super::errors::{IResult, InterpreterError}; +use super::value::Value; + +#[allow(unused)] +pub struct Interpreter<'interner> { + /// To expand macros the Interpreter may mutate hir nodes within the NodeInterner + pub(super) interner: &'interner mut NodeInterner, + + /// Each value currently in scope in the interpreter. + /// Each element of the Vec represents a scope with every scope together making + /// up all currently visible definitions. + scopes: &'interner mut Vec>, + + in_loop: bool, +} + +#[allow(unused)] +impl<'a> Interpreter<'a> { + pub(crate) fn new( + interner: &'a mut NodeInterner, + scopes: &'a mut Vec>, + ) -> Self { + Self { interner, scopes, in_loop: false } + } + + pub(crate) fn call_function( + &mut self, + function: FuncId, + arguments: Vec<(Value, Location)>, + location: Location, + ) -> IResult { + let previous_state = self.enter_function(); + + let meta = self.interner.function_meta(&function); + if meta.kind != FunctionKind::Normal { + let item = "Evaluation for builtin functions"; + return Err(InterpreterError::Unimplemented { item, location }); + } + + if meta.parameters.len() != arguments.len() { + return Err(InterpreterError::ArgumentCountMismatch { + expected: meta.parameters.len(), + actual: arguments.len(), + location, + }); + } + + let parameters = meta.parameters.0.clone(); + for ((parameter, typ, _), (argument, arg_location)) in parameters.iter().zip(arguments) { + self.define_pattern(parameter, typ, argument, arg_location)?; + } + + let function_body = self.interner.function(&function).as_expr(); + let result = self.evaluate(function_body)?; + + self.exit_function(previous_state); + Ok(result) + } + + fn call_closure( + &mut self, + closure: HirLambda, + // TODO: How to define environment here? + _environment: Vec, + arguments: Vec<(Value, Location)>, + call_location: Location, + ) -> IResult { + let previous_state = self.enter_function(); + + if closure.parameters.len() != arguments.len() { + return Err(InterpreterError::ArgumentCountMismatch { + expected: closure.parameters.len(), + actual: arguments.len(), + location: call_location, + }); + } + + let parameters = closure.parameters.iter().zip(arguments); + for ((parameter, typ), (argument, arg_location)) in parameters { + self.define_pattern(parameter, typ, argument, arg_location)?; + } + + let result = self.evaluate(closure.body)?; + + self.exit_function(previous_state); + Ok(result) + } + + /// Enters a function, pushing a new scope and resetting any required state. + /// Returns the previous values of the internal state, to be reset when + /// `exit_function` is called. + pub(super) fn enter_function(&mut self) -> (bool, Vec>) { + // Drain every scope except the global scope + let mut scope = Vec::new(); + if self.scopes.len() > 1 { + scope = self.scopes.drain(1..).collect(); + self.push_scope(); + } + (std::mem::take(&mut self.in_loop), scope) + } + + pub(super) fn exit_function(&mut self, mut state: (bool, Vec>)) { + self.in_loop = state.0; + + // Keep only the global scope + self.scopes.truncate(1); + self.scopes.append(&mut state.1); + } + + pub(super) fn push_scope(&mut self) { + self.scopes.push(HashMap::default()); + } + + pub(super) fn pop_scope(&mut self) { + self.scopes.pop(); + } + + fn current_scope_mut(&mut self) -> &mut HashMap { + // the global scope is always at index zero, so this is always Some + self.scopes.last_mut().unwrap() + } + + pub(super) fn define_pattern( + &mut self, + pattern: &HirPattern, + typ: &Type, + argument: Value, + location: Location, + ) -> IResult<()> { + match pattern { + HirPattern::Identifier(identifier) => { + self.define(identifier.id, typ, argument, location) + } + HirPattern::Mutable(pattern, _) => { + self.define_pattern(pattern, typ, argument, location) + } + HirPattern::Tuple(pattern_fields, _) => match (argument, typ) { + (Value::Tuple(fields), Type::Tuple(type_fields)) + if fields.len() == pattern_fields.len() => + { + for ((pattern, typ), argument) in + pattern_fields.iter().zip(type_fields).zip(fields) + { + self.define_pattern(pattern, typ, argument, location)?; + } + Ok(()) + } + (value, _) => { + Err(InterpreterError::TypeMismatch { expected: typ.clone(), value, location }) + } + }, + HirPattern::Struct(struct_type, pattern_fields, _) => { + self.type_check(typ, &argument, location)?; + self.type_check(struct_type, &argument, location)?; + + match argument { + Value::Struct(fields, struct_type) if fields.len() == pattern_fields.len() => { + for (field_name, field_pattern) in pattern_fields { + let field = fields.get(&field_name.0.contents).ok_or_else(|| { + InterpreterError::ExpectedStructToHaveField { + value: Value::Struct(fields.clone(), struct_type.clone()), + field_name: field_name.0.contents.clone(), + location, + } + })?; + + let field_type = field.get_type().into_owned(); + self.define_pattern( + field_pattern, + &field_type, + field.clone(), + location, + )?; + } + Ok(()) + } + value => Err(InterpreterError::TypeMismatch { + expected: typ.clone(), + value, + location, + }), + } + } + } + } + + /// Define a new variable in the current scope + fn define( + &mut self, + id: DefinitionId, + typ: &Type, + argument: Value, + location: Location, + ) -> IResult<()> { + self.type_check(typ, &argument, location)?; + self.current_scope_mut().insert(id, argument); + Ok(()) + } + + /// Mutate an existing variable, potentially from a prior scope. + /// Also type checks the value being assigned + fn checked_mutate( + &mut self, + id: DefinitionId, + typ: &Type, + argument: Value, + location: Location, + ) -> IResult<()> { + self.type_check(typ, &argument, location)?; + self.mutate(id, argument, location) + } + + /// Mutate an existing variable, potentially from a prior scope + fn mutate(&mut self, id: DefinitionId, argument: Value, location: Location) -> IResult<()> { + // If the id is a dummy, assume the error was already issued elsewhere + if id == DefinitionId::dummy_id() { + return Ok(()); + } + + for scope in self.scopes.iter_mut().rev() { + if let Entry::Occupied(mut entry) = scope.entry(id) { + entry.insert(argument); + return Ok(()); + } + } + let name = self.interner.definition(id).name.clone(); + Err(InterpreterError::NonComptimeVarReferenced { name, location }) + } + + pub(super) fn lookup(&self, ident: &HirIdent) -> IResult { + self.lookup_id(ident.id, ident.location) + } + + pub fn lookup_id(&self, id: DefinitionId, location: Location) -> IResult { + for scope in self.scopes.iter().rev() { + if let Some(value) = scope.get(&id) { + return Ok(value.clone()); + } + } + + // Justification for `NonComptimeVarReferenced`: + // If we have an id to lookup at all that means name resolution successfully + // found another variable in scope for this name. If the name is in scope + // but unknown by the interpreter it must be because it was not a comptime variable. + let name = self.interner.definition(id).name.clone(); + Err(InterpreterError::NonComptimeVarReferenced { name, location }) + } + + fn type_check(&self, typ: &Type, value: &Value, location: Location) -> IResult<()> { + let typ = typ.follow_bindings(); + let value_type = value.get_type(); + + typ.try_unify(&value_type, &mut TypeBindings::new()).map_err(|_| { + InterpreterError::TypeMismatch { expected: typ, value: value.clone(), location } + }) + } + + /// Evaluate an expression and return the result + pub(super) fn evaluate(&mut self, id: ExprId) -> IResult { + match self.interner.expression(&id) { + HirExpression::Ident(ident, _) => self.evaluate_ident(ident, id), + HirExpression::Literal(literal) => self.evaluate_literal(literal, id), + HirExpression::Block(block) => self.evaluate_block(block), + HirExpression::Prefix(prefix) => self.evaluate_prefix(prefix, id), + HirExpression::Infix(infix) => self.evaluate_infix(infix, id), + HirExpression::Index(index) => self.evaluate_index(index, id), + HirExpression::Constructor(constructor) => self.evaluate_constructor(constructor, id), + HirExpression::MemberAccess(access) => self.evaluate_access(access, id), + HirExpression::Call(call) => self.evaluate_call(call, id), + HirExpression::MethodCall(call) => self.evaluate_method_call(call, id), + HirExpression::Cast(cast) => self.evaluate_cast(&cast, id), + HirExpression::If(if_) => self.evaluate_if(if_, id), + HirExpression::Tuple(tuple) => self.evaluate_tuple(tuple), + HirExpression::Lambda(lambda) => self.evaluate_lambda(lambda, id), + HirExpression::Quote(block) => Ok(Value::Code(Rc::new(block))), + HirExpression::Comptime(block) => self.evaluate_block(block), + HirExpression::Unquote(block) => { + // An Unquote expression being found is indicative of a macro being + // expanded within another comptime fn which we don't currently support. + let location = self.interner.expr_location(&id); + Err(InterpreterError::UnquoteFoundDuringEvaluation { location }) + } + HirExpression::Error => { + let location = self.interner.expr_location(&id); + Err(InterpreterError::ErrorNodeEncountered { location }) + } + } + } + + pub(super) fn evaluate_ident(&mut self, ident: HirIdent, id: ExprId) -> IResult { + let definition = self.interner.definition(ident.id); + + match &definition.kind { + DefinitionKind::Function(function_id) => { + let typ = self.interner.id_type(id); + Ok(Value::Function(*function_id, typ)) + } + DefinitionKind::Local(_) => self.lookup(&ident), + DefinitionKind::Global(global_id) => { + // Don't need to check let_.comptime, we can evaluate non-comptime globals too. + // Avoid resetting the value if it is already known + if let Ok(value) = self.lookup(&ident) { + Ok(value) + } else { + let let_ = self.interner.get_global_let_statement(*global_id).unwrap(); + self.evaluate_let(let_)?; + self.lookup(&ident) + } + } + DefinitionKind::GenericType(type_variable) => { + let value = match &*type_variable.borrow() { + TypeBinding::Unbound(_) => None, + TypeBinding::Bound(binding) => binding.evaluate_to_u32(), + }; + + if let Some(value) = value { + let typ = self.interner.id_type(id); + self.evaluate_integer((value as u128).into(), false, id) + } else { + let location = self.interner.expr_location(&id); + let typ = Type::TypeVariable(type_variable.clone(), TypeVariableKind::Normal); + Err(InterpreterError::NonIntegerArrayLength { typ, location }) + } + } + } + } + + fn evaluate_literal(&mut self, literal: HirLiteral, id: ExprId) -> IResult { + match literal { + HirLiteral::Unit => Ok(Value::Unit), + HirLiteral::Bool(value) => Ok(Value::Bool(value)), + HirLiteral::Integer(value, is_negative) => { + self.evaluate_integer(value, is_negative, id) + } + HirLiteral::Str(string) => Ok(Value::String(Rc::new(string))), + HirLiteral::FmtStr(_, _) => todo!("Evaluate format strings"), + HirLiteral::Array(array) => self.evaluate_array(array, id), + HirLiteral::Slice(array) => self.evaluate_slice(array, id), + } + } + + fn evaluate_integer( + &self, + value: FieldElement, + is_negative: bool, + id: ExprId, + ) -> IResult { + let typ = self.interner.id_type(id).follow_bindings(); + let location = self.interner.expr_location(&id); + + if let Type::FieldElement = &typ { + Ok(Value::Field(value)) + } else if let Type::Integer(sign, bit_size) = &typ { + match (sign, bit_size) { + (Signedness::Unsigned, IntegerBitSize::One) => { + return Err(InterpreterError::TypeUnsupported { typ, location }); + } + (Signedness::Unsigned, IntegerBitSize::Eight) => { + let value: u8 = + value.try_to_u64().and_then(|value| value.try_into().ok()).ok_or( + InterpreterError::IntegerOutOfRangeForType { value, typ, location }, + )?; + let value = if is_negative { 0u8.wrapping_sub(value) } else { value }; + Ok(Value::U8(value)) + } + (Signedness::Unsigned, IntegerBitSize::Sixteen) => { + let value: u16 = + value.try_to_u64().and_then(|value| value.try_into().ok()).ok_or( + InterpreterError::IntegerOutOfRangeForType { value, typ, location }, + )?; + let value = if is_negative { 0u16.wrapping_sub(value) } else { value }; + Ok(Value::U16(value)) + } + (Signedness::Unsigned, IntegerBitSize::ThirtyTwo) => { + let value: u32 = + value.try_to_u32().ok_or(InterpreterError::IntegerOutOfRangeForType { + value, + typ, + location, + })?; + let value = if is_negative { 0u32.wrapping_sub(value) } else { value }; + Ok(Value::U32(value)) + } + (Signedness::Unsigned, IntegerBitSize::SixtyFour) => { + let value: u64 = + value.try_to_u64().ok_or(InterpreterError::IntegerOutOfRangeForType { + value, + typ, + location, + })?; + let value = if is_negative { 0u64.wrapping_sub(value) } else { value }; + Ok(Value::U64(value)) + } + (Signedness::Signed, IntegerBitSize::One) => { + return Err(InterpreterError::TypeUnsupported { typ, location }); + } + (Signedness::Signed, IntegerBitSize::Eight) => { + let value: i8 = + value.try_to_u64().and_then(|value| value.try_into().ok()).ok_or( + InterpreterError::IntegerOutOfRangeForType { value, typ, location }, + )?; + let value = if is_negative { -value } else { value }; + Ok(Value::I8(value)) + } + (Signedness::Signed, IntegerBitSize::Sixteen) => { + let value: i16 = + value.try_to_u64().and_then(|value| value.try_into().ok()).ok_or( + InterpreterError::IntegerOutOfRangeForType { value, typ, location }, + )?; + let value = if is_negative { -value } else { value }; + Ok(Value::I16(value)) + } + (Signedness::Signed, IntegerBitSize::ThirtyTwo) => { + let value: i32 = + value.try_to_u64().and_then(|value| value.try_into().ok()).ok_or( + InterpreterError::IntegerOutOfRangeForType { value, typ, location }, + )?; + let value = if is_negative { -value } else { value }; + Ok(Value::I32(value)) + } + (Signedness::Signed, IntegerBitSize::SixtyFour) => { + let value: i64 = + value.try_to_u64().and_then(|value| value.try_into().ok()).ok_or( + InterpreterError::IntegerOutOfRangeForType { value, typ, location }, + )?; + let value = if is_negative { -value } else { value }; + Ok(Value::I64(value)) + } + } + } else { + Err(InterpreterError::NonIntegerIntegerLiteral { typ, location }) + } + } + + pub fn evaluate_block(&mut self, mut block: HirBlockExpression) -> IResult { + let last_statement = block.statements.pop(); + self.push_scope(); + + for statement in block.statements { + self.evaluate_statement(statement)?; + } + + let result = if let Some(statement) = last_statement { + self.evaluate_statement(statement) + } else { + Ok(Value::Unit) + }; + + self.pop_scope(); + result + } + + fn evaluate_array(&mut self, array: HirArrayLiteral, id: ExprId) -> IResult { + let typ = self.interner.id_type(id); + + match array { + HirArrayLiteral::Standard(elements) => { + let elements = elements + .into_iter() + .map(|id| self.evaluate(id)) + .collect::>>()?; + + Ok(Value::Array(elements, typ)) + } + HirArrayLiteral::Repeated { repeated_element, length } => { + let element = self.evaluate(repeated_element)?; + + if let Some(length) = length.evaluate_to_u32() { + let elements = (0..length).map(|_| element.clone()).collect(); + Ok(Value::Array(elements, typ)) + } else { + let location = self.interner.expr_location(&id); + Err(InterpreterError::NonIntegerArrayLength { typ: length, location }) + } + } + } + } + + fn evaluate_slice(&mut self, array: HirArrayLiteral, id: ExprId) -> IResult { + self.evaluate_array(array, id).map(|value| match value { + Value::Array(array, typ) => Value::Slice(array, typ), + other => unreachable!("Non-array value returned from evaluate array: {other:?}"), + }) + } + + fn evaluate_prefix(&mut self, prefix: HirPrefixExpression, id: ExprId) -> IResult { + let rhs = self.evaluate(prefix.rhs)?; + match prefix.operator { + crate::ast::UnaryOp::Minus => match rhs { + Value::Field(value) => Ok(Value::Field(FieldElement::zero() - value)), + Value::I8(value) => Ok(Value::I8(-value)), + Value::I16(value) => Ok(Value::I16(-value)), + Value::I32(value) => Ok(Value::I32(-value)), + Value::I64(value) => Ok(Value::I64(-value)), + Value::U8(value) => Ok(Value::U8(0 - value)), + Value::U16(value) => Ok(Value::U16(0 - value)), + Value::U32(value) => Ok(Value::U32(0 - value)), + Value::U64(value) => Ok(Value::U64(0 - value)), + value => { + let location = self.interner.expr_location(&id); + let operator = "minus"; + Err(InterpreterError::InvalidValueForUnary { value, location, operator }) + } + }, + crate::ast::UnaryOp::Not => match rhs { + Value::Bool(value) => Ok(Value::Bool(!value)), + Value::I8(value) => Ok(Value::I8(!value)), + Value::I16(value) => Ok(Value::I16(!value)), + Value::I32(value) => Ok(Value::I32(!value)), + Value::I64(value) => Ok(Value::I64(!value)), + Value::U8(value) => Ok(Value::U8(!value)), + Value::U16(value) => Ok(Value::U16(!value)), + Value::U32(value) => Ok(Value::U32(!value)), + Value::U64(value) => Ok(Value::U64(!value)), + value => { + let location = self.interner.expr_location(&id); + Err(InterpreterError::InvalidValueForUnary { value, location, operator: "not" }) + } + }, + crate::ast::UnaryOp::MutableReference => Ok(Value::Pointer(Shared::new(rhs))), + crate::ast::UnaryOp::Dereference { implicitly_added: _ } => match rhs { + Value::Pointer(element) => Ok(element.borrow().clone()), + value => { + let location = self.interner.expr_location(&id); + Err(InterpreterError::NonPointerDereferenced { value, location }) + } + }, + } + } + + fn evaluate_infix(&mut self, infix: HirInfixExpression, id: ExprId) -> IResult { + let lhs = self.evaluate(infix.lhs)?; + let rhs = self.evaluate(infix.rhs)?; + + // TODO: Need to account for operator overloading + assert!( + self.interner.get_selected_impl_for_expression(id).is_none(), + "Operator overloading is unimplemented in the interpreter" + ); + + use InterpreterError::InvalidValuesForBinary; + match infix.operator.kind { + BinaryOpKind::Add => match (lhs, rhs) { + (Value::Field(lhs), Value::Field(rhs)) => Ok(Value::Field(lhs + rhs)), + (Value::I8(lhs), Value::I8(rhs)) => Ok(Value::I8(lhs + rhs)), + (Value::I16(lhs), Value::I16(rhs)) => Ok(Value::I16(lhs + rhs)), + (Value::I32(lhs), Value::I32(rhs)) => Ok(Value::I32(lhs + rhs)), + (Value::I64(lhs), Value::I64(rhs)) => Ok(Value::I64(lhs + rhs)), + (Value::U8(lhs), Value::U8(rhs)) => Ok(Value::U8(lhs + rhs)), + (Value::U16(lhs), Value::U16(rhs)) => Ok(Value::U16(lhs + rhs)), + (Value::U32(lhs), Value::U32(rhs)) => Ok(Value::U32(lhs + rhs)), + (Value::U64(lhs), Value::U64(rhs)) => Ok(Value::U64(lhs + rhs)), + (lhs, rhs) => { + let location = self.interner.expr_location(&id); + Err(InvalidValuesForBinary { lhs, rhs, location, operator: "+" }) + } + }, + BinaryOpKind::Subtract => match (lhs, rhs) { + (Value::Field(lhs), Value::Field(rhs)) => Ok(Value::Field(lhs - rhs)), + (Value::I8(lhs), Value::I8(rhs)) => Ok(Value::I8(lhs - rhs)), + (Value::I16(lhs), Value::I16(rhs)) => Ok(Value::I16(lhs - rhs)), + (Value::I32(lhs), Value::I32(rhs)) => Ok(Value::I32(lhs - rhs)), + (Value::I64(lhs), Value::I64(rhs)) => Ok(Value::I64(lhs - rhs)), + (Value::U8(lhs), Value::U8(rhs)) => Ok(Value::U8(lhs - rhs)), + (Value::U16(lhs), Value::U16(rhs)) => Ok(Value::U16(lhs - rhs)), + (Value::U32(lhs), Value::U32(rhs)) => Ok(Value::U32(lhs - rhs)), + (Value::U64(lhs), Value::U64(rhs)) => Ok(Value::U64(lhs - rhs)), + (lhs, rhs) => { + let location = self.interner.expr_location(&id); + Err(InvalidValuesForBinary { lhs, rhs, location, operator: "-" }) + } + }, + BinaryOpKind::Multiply => match (lhs, rhs) { + (Value::Field(lhs), Value::Field(rhs)) => Ok(Value::Field(lhs * rhs)), + (Value::I8(lhs), Value::I8(rhs)) => Ok(Value::I8(lhs * rhs)), + (Value::I16(lhs), Value::I16(rhs)) => Ok(Value::I16(lhs * rhs)), + (Value::I32(lhs), Value::I32(rhs)) => Ok(Value::I32(lhs * rhs)), + (Value::I64(lhs), Value::I64(rhs)) => Ok(Value::I64(lhs * rhs)), + (Value::U8(lhs), Value::U8(rhs)) => Ok(Value::U8(lhs * rhs)), + (Value::U16(lhs), Value::U16(rhs)) => Ok(Value::U16(lhs * rhs)), + (Value::U32(lhs), Value::U32(rhs)) => Ok(Value::U32(lhs * rhs)), + (Value::U64(lhs), Value::U64(rhs)) => Ok(Value::U64(lhs * rhs)), + (lhs, rhs) => { + let location = self.interner.expr_location(&id); + Err(InvalidValuesForBinary { lhs, rhs, location, operator: "*" }) + } + }, + BinaryOpKind::Divide => match (lhs, rhs) { + (Value::Field(lhs), Value::Field(rhs)) => Ok(Value::Field(lhs / rhs)), + (Value::I8(lhs), Value::I8(rhs)) => Ok(Value::I8(lhs / rhs)), + (Value::I16(lhs), Value::I16(rhs)) => Ok(Value::I16(lhs / rhs)), + (Value::I32(lhs), Value::I32(rhs)) => Ok(Value::I32(lhs / rhs)), + (Value::I64(lhs), Value::I64(rhs)) => Ok(Value::I64(lhs / rhs)), + (Value::U8(lhs), Value::U8(rhs)) => Ok(Value::U8(lhs / rhs)), + (Value::U16(lhs), Value::U16(rhs)) => Ok(Value::U16(lhs / rhs)), + (Value::U32(lhs), Value::U32(rhs)) => Ok(Value::U32(lhs / rhs)), + (Value::U64(lhs), Value::U64(rhs)) => Ok(Value::U64(lhs / rhs)), + (lhs, rhs) => { + let location = self.interner.expr_location(&id); + Err(InvalidValuesForBinary { lhs, rhs, location, operator: "/" }) + } + }, + BinaryOpKind::Equal => match (lhs, rhs) { + (Value::Field(lhs), Value::Field(rhs)) => Ok(Value::Bool(lhs == rhs)), + (Value::I8(lhs), Value::I8(rhs)) => Ok(Value::Bool(lhs == rhs)), + (Value::I16(lhs), Value::I16(rhs)) => Ok(Value::Bool(lhs == rhs)), + (Value::I32(lhs), Value::I32(rhs)) => Ok(Value::Bool(lhs == rhs)), + (Value::I64(lhs), Value::I64(rhs)) => Ok(Value::Bool(lhs == rhs)), + (Value::U8(lhs), Value::U8(rhs)) => Ok(Value::Bool(lhs == rhs)), + (Value::U16(lhs), Value::U16(rhs)) => Ok(Value::Bool(lhs == rhs)), + (Value::U32(lhs), Value::U32(rhs)) => Ok(Value::Bool(lhs == rhs)), + (Value::U64(lhs), Value::U64(rhs)) => Ok(Value::Bool(lhs == rhs)), + (lhs, rhs) => { + let location = self.interner.expr_location(&id); + Err(InvalidValuesForBinary { lhs, rhs, location, operator: "==" }) + } + }, + BinaryOpKind::NotEqual => match (lhs, rhs) { + (Value::Field(lhs), Value::Field(rhs)) => Ok(Value::Bool(lhs != rhs)), + (Value::I8(lhs), Value::I8(rhs)) => Ok(Value::Bool(lhs != rhs)), + (Value::I16(lhs), Value::I16(rhs)) => Ok(Value::Bool(lhs != rhs)), + (Value::I32(lhs), Value::I32(rhs)) => Ok(Value::Bool(lhs != rhs)), + (Value::I64(lhs), Value::I64(rhs)) => Ok(Value::Bool(lhs != rhs)), + (Value::U8(lhs), Value::U8(rhs)) => Ok(Value::Bool(lhs != rhs)), + (Value::U16(lhs), Value::U16(rhs)) => Ok(Value::Bool(lhs != rhs)), + (Value::U32(lhs), Value::U32(rhs)) => Ok(Value::Bool(lhs != rhs)), + (Value::U64(lhs), Value::U64(rhs)) => Ok(Value::Bool(lhs != rhs)), + (lhs, rhs) => { + let location = self.interner.expr_location(&id); + Err(InvalidValuesForBinary { lhs, rhs, location, operator: "!=" }) + } + }, + BinaryOpKind::Less => match (lhs, rhs) { + (Value::Field(lhs), Value::Field(rhs)) => Ok(Value::Bool(lhs < rhs)), + (Value::I8(lhs), Value::I8(rhs)) => Ok(Value::Bool(lhs < rhs)), + (Value::I16(lhs), Value::I16(rhs)) => Ok(Value::Bool(lhs < rhs)), + (Value::I32(lhs), Value::I32(rhs)) => Ok(Value::Bool(lhs < rhs)), + (Value::I64(lhs), Value::I64(rhs)) => Ok(Value::Bool(lhs < rhs)), + (Value::U8(lhs), Value::U8(rhs)) => Ok(Value::Bool(lhs < rhs)), + (Value::U16(lhs), Value::U16(rhs)) => Ok(Value::Bool(lhs < rhs)), + (Value::U32(lhs), Value::U32(rhs)) => Ok(Value::Bool(lhs < rhs)), + (Value::U64(lhs), Value::U64(rhs)) => Ok(Value::Bool(lhs < rhs)), + (lhs, rhs) => { + let location = self.interner.expr_location(&id); + Err(InvalidValuesForBinary { lhs, rhs, location, operator: "<" }) + } + }, + BinaryOpKind::LessEqual => match (lhs, rhs) { + (Value::Field(lhs), Value::Field(rhs)) => Ok(Value::Bool(lhs <= rhs)), + (Value::I8(lhs), Value::I8(rhs)) => Ok(Value::Bool(lhs <= rhs)), + (Value::I16(lhs), Value::I16(rhs)) => Ok(Value::Bool(lhs <= rhs)), + (Value::I32(lhs), Value::I32(rhs)) => Ok(Value::Bool(lhs <= rhs)), + (Value::I64(lhs), Value::I64(rhs)) => Ok(Value::Bool(lhs <= rhs)), + (Value::U8(lhs), Value::U8(rhs)) => Ok(Value::Bool(lhs <= rhs)), + (Value::U16(lhs), Value::U16(rhs)) => Ok(Value::Bool(lhs <= rhs)), + (Value::U32(lhs), Value::U32(rhs)) => Ok(Value::Bool(lhs <= rhs)), + (Value::U64(lhs), Value::U64(rhs)) => Ok(Value::Bool(lhs <= rhs)), + (lhs, rhs) => { + let location = self.interner.expr_location(&id); + Err(InvalidValuesForBinary { lhs, rhs, location, operator: "<=" }) + } + }, + BinaryOpKind::Greater => match (lhs, rhs) { + (Value::Field(lhs), Value::Field(rhs)) => Ok(Value::Bool(lhs > rhs)), + (Value::I8(lhs), Value::I8(rhs)) => Ok(Value::Bool(lhs > rhs)), + (Value::I16(lhs), Value::I16(rhs)) => Ok(Value::Bool(lhs > rhs)), + (Value::I32(lhs), Value::I32(rhs)) => Ok(Value::Bool(lhs > rhs)), + (Value::I64(lhs), Value::I64(rhs)) => Ok(Value::Bool(lhs > rhs)), + (Value::U8(lhs), Value::U8(rhs)) => Ok(Value::Bool(lhs > rhs)), + (Value::U16(lhs), Value::U16(rhs)) => Ok(Value::Bool(lhs > rhs)), + (Value::U32(lhs), Value::U32(rhs)) => Ok(Value::Bool(lhs > rhs)), + (Value::U64(lhs), Value::U64(rhs)) => Ok(Value::Bool(lhs > rhs)), + (lhs, rhs) => { + let location = self.interner.expr_location(&id); + Err(InvalidValuesForBinary { lhs, rhs, location, operator: ">" }) + } + }, + BinaryOpKind::GreaterEqual => match (lhs, rhs) { + (Value::Field(lhs), Value::Field(rhs)) => Ok(Value::Bool(lhs >= rhs)), + (Value::I8(lhs), Value::I8(rhs)) => Ok(Value::Bool(lhs >= rhs)), + (Value::I16(lhs), Value::I16(rhs)) => Ok(Value::Bool(lhs >= rhs)), + (Value::I32(lhs), Value::I32(rhs)) => Ok(Value::Bool(lhs >= rhs)), + (Value::I64(lhs), Value::I64(rhs)) => Ok(Value::Bool(lhs >= rhs)), + (Value::U8(lhs), Value::U8(rhs)) => Ok(Value::Bool(lhs >= rhs)), + (Value::U16(lhs), Value::U16(rhs)) => Ok(Value::Bool(lhs >= rhs)), + (Value::U32(lhs), Value::U32(rhs)) => Ok(Value::Bool(lhs >= rhs)), + (Value::U64(lhs), Value::U64(rhs)) => Ok(Value::Bool(lhs >= rhs)), + (lhs, rhs) => { + let location = self.interner.expr_location(&id); + Err(InvalidValuesForBinary { lhs, rhs, location, operator: ">=" }) + } + }, + BinaryOpKind::And => match (lhs, rhs) { + (Value::Bool(lhs), Value::Bool(rhs)) => Ok(Value::Bool(lhs & rhs)), + (Value::I8(lhs), Value::I8(rhs)) => Ok(Value::I8(lhs & rhs)), + (Value::I16(lhs), Value::I16(rhs)) => Ok(Value::I16(lhs & rhs)), + (Value::I32(lhs), Value::I32(rhs)) => Ok(Value::I32(lhs & rhs)), + (Value::I64(lhs), Value::I64(rhs)) => Ok(Value::I64(lhs & rhs)), + (Value::U8(lhs), Value::U8(rhs)) => Ok(Value::U8(lhs & rhs)), + (Value::U16(lhs), Value::U16(rhs)) => Ok(Value::U16(lhs & rhs)), + (Value::U32(lhs), Value::U32(rhs)) => Ok(Value::U32(lhs & rhs)), + (Value::U64(lhs), Value::U64(rhs)) => Ok(Value::U64(lhs & rhs)), + (lhs, rhs) => { + let location = self.interner.expr_location(&id); + Err(InvalidValuesForBinary { lhs, rhs, location, operator: "&" }) + } + }, + BinaryOpKind::Or => match (lhs, rhs) { + (Value::Bool(lhs), Value::Bool(rhs)) => Ok(Value::Bool(lhs | rhs)), + (Value::I8(lhs), Value::I8(rhs)) => Ok(Value::I8(lhs | rhs)), + (Value::I16(lhs), Value::I16(rhs)) => Ok(Value::I16(lhs | rhs)), + (Value::I32(lhs), Value::I32(rhs)) => Ok(Value::I32(lhs | rhs)), + (Value::I64(lhs), Value::I64(rhs)) => Ok(Value::I64(lhs | rhs)), + (Value::U8(lhs), Value::U8(rhs)) => Ok(Value::U8(lhs | rhs)), + (Value::U16(lhs), Value::U16(rhs)) => Ok(Value::U16(lhs | rhs)), + (Value::U32(lhs), Value::U32(rhs)) => Ok(Value::U32(lhs | rhs)), + (Value::U64(lhs), Value::U64(rhs)) => Ok(Value::U64(lhs | rhs)), + (lhs, rhs) => { + let location = self.interner.expr_location(&id); + Err(InvalidValuesForBinary { lhs, rhs, location, operator: "|" }) + } + }, + BinaryOpKind::Xor => match (lhs, rhs) { + (Value::Bool(lhs), Value::Bool(rhs)) => Ok(Value::Bool(lhs ^ rhs)), + (Value::I8(lhs), Value::I8(rhs)) => Ok(Value::I8(lhs ^ rhs)), + (Value::I16(lhs), Value::I16(rhs)) => Ok(Value::I16(lhs ^ rhs)), + (Value::I32(lhs), Value::I32(rhs)) => Ok(Value::I32(lhs ^ rhs)), + (Value::I64(lhs), Value::I64(rhs)) => Ok(Value::I64(lhs ^ rhs)), + (Value::U8(lhs), Value::U8(rhs)) => Ok(Value::U8(lhs ^ rhs)), + (Value::U16(lhs), Value::U16(rhs)) => Ok(Value::U16(lhs ^ rhs)), + (Value::U32(lhs), Value::U32(rhs)) => Ok(Value::U32(lhs ^ rhs)), + (Value::U64(lhs), Value::U64(rhs)) => Ok(Value::U64(lhs ^ rhs)), + (lhs, rhs) => { + let location = self.interner.expr_location(&id); + Err(InvalidValuesForBinary { lhs, rhs, location, operator: "^" }) + } + }, + BinaryOpKind::ShiftRight => match (lhs, rhs) { + (Value::I8(lhs), Value::I8(rhs)) => Ok(Value::I8(lhs >> rhs)), + (Value::I16(lhs), Value::I16(rhs)) => Ok(Value::I16(lhs >> rhs)), + (Value::I32(lhs), Value::I32(rhs)) => Ok(Value::I32(lhs >> rhs)), + (Value::I64(lhs), Value::I64(rhs)) => Ok(Value::I64(lhs >> rhs)), + (Value::U8(lhs), Value::U8(rhs)) => Ok(Value::U8(lhs >> rhs)), + (Value::U16(lhs), Value::U16(rhs)) => Ok(Value::U16(lhs >> rhs)), + (Value::U32(lhs), Value::U32(rhs)) => Ok(Value::U32(lhs >> rhs)), + (Value::U64(lhs), Value::U64(rhs)) => Ok(Value::U64(lhs >> rhs)), + (lhs, rhs) => { + let location = self.interner.expr_location(&id); + Err(InvalidValuesForBinary { lhs, rhs, location, operator: ">>" }) + } + }, + BinaryOpKind::ShiftLeft => match (lhs, rhs) { + (Value::I8(lhs), Value::I8(rhs)) => Ok(Value::I8(lhs << rhs)), + (Value::I16(lhs), Value::I16(rhs)) => Ok(Value::I16(lhs << rhs)), + (Value::I32(lhs), Value::I32(rhs)) => Ok(Value::I32(lhs << rhs)), + (Value::I64(lhs), Value::I64(rhs)) => Ok(Value::I64(lhs << rhs)), + (Value::U8(lhs), Value::U8(rhs)) => Ok(Value::U8(lhs << rhs)), + (Value::U16(lhs), Value::U16(rhs)) => Ok(Value::U16(lhs << rhs)), + (Value::U32(lhs), Value::U32(rhs)) => Ok(Value::U32(lhs << rhs)), + (Value::U64(lhs), Value::U64(rhs)) => Ok(Value::U64(lhs << rhs)), + (lhs, rhs) => { + let location = self.interner.expr_location(&id); + Err(InvalidValuesForBinary { lhs, rhs, location, operator: "<<" }) + } + }, + BinaryOpKind::Modulo => match (lhs, rhs) { + (Value::I8(lhs), Value::I8(rhs)) => Ok(Value::I8(lhs % rhs)), + (Value::I16(lhs), Value::I16(rhs)) => Ok(Value::I16(lhs % rhs)), + (Value::I32(lhs), Value::I32(rhs)) => Ok(Value::I32(lhs % rhs)), + (Value::I64(lhs), Value::I64(rhs)) => Ok(Value::I64(lhs % rhs)), + (Value::U8(lhs), Value::U8(rhs)) => Ok(Value::U8(lhs % rhs)), + (Value::U16(lhs), Value::U16(rhs)) => Ok(Value::U16(lhs % rhs)), + (Value::U32(lhs), Value::U32(rhs)) => Ok(Value::U32(lhs % rhs)), + (Value::U64(lhs), Value::U64(rhs)) => Ok(Value::U64(lhs % rhs)), + (lhs, rhs) => { + let location = self.interner.expr_location(&id); + Err(InvalidValuesForBinary { lhs, rhs, location, operator: "%" }) + } + }, + } + } + + fn evaluate_index(&mut self, index: HirIndexExpression, id: ExprId) -> IResult { + let array = self.evaluate(index.collection)?; + let index = self.evaluate(index.index)?; + + let location = self.interner.expr_location(&id); + let (array, index) = self.bounds_check(array, index, location)?; + + Ok(array[index].clone()) + } + + /// Bounds check the given array and index pair. + /// This will also ensure the given arguments are in fact an array and integer. + fn bounds_check( + &self, + array: Value, + index: Value, + location: Location, + ) -> IResult<(Vector, usize)> { + let collection = match array { + Value::Array(array, _) => array, + Value::Slice(array, _) => array, + value => { + return Err(InterpreterError::NonArrayIndexed { value, location }); + } + }; + + let index = match index { + Value::Field(value) => { + value.try_to_u64().expect("index could not fit into u64") as usize + } + Value::I8(value) => value as usize, + Value::I16(value) => value as usize, + Value::I32(value) => value as usize, + Value::I64(value) => value as usize, + Value::U8(value) => value as usize, + Value::U16(value) => value as usize, + Value::U32(value) => value as usize, + Value::U64(value) => value as usize, + value => { + return Err(InterpreterError::NonIntegerUsedAsIndex { value, location }); + } + }; + + if index >= collection.len() { + use InterpreterError::IndexOutOfBounds; + return Err(IndexOutOfBounds { index, location, length: collection.len() }); + } + + Ok((collection, index)) + } + + fn evaluate_constructor( + &mut self, + constructor: HirConstructorExpression, + id: ExprId, + ) -> IResult { + let fields = constructor + .fields + .into_iter() + .map(|(name, expr)| { + let field_value = self.evaluate(expr)?; + Ok((Rc::new(name.0.contents), field_value)) + }) + .collect::>()?; + + let typ = self.interner.id_type(id); + Ok(Value::Struct(fields, typ)) + } + + fn evaluate_access(&mut self, access: HirMemberAccess, id: ExprId) -> IResult { + let (fields, struct_type) = match self.evaluate(access.lhs)? { + Value::Struct(fields, typ) => (fields, typ), + value => { + let location = self.interner.expr_location(&id); + return Err(InterpreterError::NonTupleOrStructInMemberAccess { value, location }); + } + }; + + fields.get(&access.rhs.0.contents).cloned().ok_or_else(|| { + let location = self.interner.expr_location(&id); + let value = Value::Struct(fields, struct_type); + let field_name = access.rhs.0.contents; + InterpreterError::ExpectedStructToHaveField { value, field_name, location } + }) + } + + fn evaluate_call(&mut self, call: HirCallExpression, id: ExprId) -> IResult { + let function = self.evaluate(call.func)?; + let arguments = try_vecmap(call.arguments, |arg| { + Ok((self.evaluate(arg)?, self.interner.expr_location(&arg))) + })?; + let location = self.interner.expr_location(&id); + + match function { + Value::Function(function_id, _) => self.call_function(function_id, arguments, location), + Value::Closure(closure, env, _) => self.call_closure(closure, env, arguments, location), + value => Err(InterpreterError::NonFunctionCalled { value, location }), + } + } + + fn evaluate_method_call( + &mut self, + call: HirMethodCallExpression, + id: ExprId, + ) -> IResult { + let object = self.evaluate(call.object)?; + let arguments = try_vecmap(call.arguments, |arg| { + Ok((self.evaluate(arg)?, self.interner.expr_location(&arg))) + })?; + let location = self.interner.expr_location(&id); + + let typ = object.get_type().follow_bindings(); + let method_name = &call.method.0.contents; + + // TODO: Traits + let method = match &typ { + Type::Struct(struct_def, _) => { + self.interner.lookup_method(&typ, struct_def.borrow().id, method_name, false) + } + _ => self.interner.lookup_primitive_method(&typ, method_name), + }; + + if let Some(method) = method { + self.call_function(method, arguments, location) + } else { + Err(InterpreterError::NoMethodFound { name: method_name.clone(), typ, location }) + } + } + + fn evaluate_cast(&mut self, cast: &HirCastExpression, id: ExprId) -> IResult { + let evaluated_lhs = self.evaluate(cast.lhs)?; + Self::evaluate_cast_one_step(cast, id, evaluated_lhs, self.interner) + } + + /// evaluate_cast without recursion + pub fn evaluate_cast_one_step( + cast: &HirCastExpression, + id: ExprId, + evaluated_lhs: Value, + interner: &NodeInterner, + ) -> IResult { + macro_rules! signed_int_to_field { + ($x:expr) => {{ + // Need to convert the signed integer to an i128 before + // we negate it to preserve the MIN value. + let mut value = $x as i128; + let is_negative = value < 0; + if is_negative { + value = -value; + } + ((value as u128).into(), is_negative) + }}; + } + + let (mut lhs, lhs_is_negative) = match evaluated_lhs { + Value::Field(value) => (value, false), + Value::U8(value) => ((value as u128).into(), false), + Value::U16(value) => ((value as u128).into(), false), + Value::U32(value) => ((value as u128).into(), false), + Value::U64(value) => ((value as u128).into(), false), + Value::I8(value) => signed_int_to_field!(value), + Value::I16(value) => signed_int_to_field!(value), + Value::I32(value) => signed_int_to_field!(value), + Value::I64(value) => signed_int_to_field!(value), + Value::Bool(value) => { + (if value { FieldElement::one() } else { FieldElement::zero() }, false) + } + value => { + let location = interner.expr_location(&id); + return Err(InterpreterError::NonNumericCasted { value, location }); + } + }; + + macro_rules! cast_to_int { + ($x:expr, $method:ident, $typ:ty, $f:ident) => {{ + let mut value = $x.$method() as $typ; + if lhs_is_negative { + value = 0 - value; + } + Ok(Value::$f(value)) + }}; + } + + // Now actually cast the lhs, bit casting and wrapping as necessary + match cast.r#type.follow_bindings() { + Type::FieldElement => { + if lhs_is_negative { + lhs = FieldElement::zero() - lhs; + } + Ok(Value::Field(lhs)) + } + Type::Integer(sign, bit_size) => match (sign, bit_size) { + (Signedness::Unsigned, IntegerBitSize::One) => { + let location = interner.expr_location(&id); + Err(InterpreterError::TypeUnsupported { typ: cast.r#type.clone(), location }) + } + (Signedness::Unsigned, IntegerBitSize::Eight) => cast_to_int!(lhs, to_u128, u8, U8), + (Signedness::Unsigned, IntegerBitSize::Sixteen) => { + cast_to_int!(lhs, to_u128, u16, U16) + } + (Signedness::Unsigned, IntegerBitSize::ThirtyTwo) => { + cast_to_int!(lhs, to_u128, u32, U32) + } + (Signedness::Unsigned, IntegerBitSize::SixtyFour) => { + cast_to_int!(lhs, to_u128, u64, U64) + } + (Signedness::Signed, IntegerBitSize::One) => { + let location = interner.expr_location(&id); + Err(InterpreterError::TypeUnsupported { typ: cast.r#type.clone(), location }) + } + (Signedness::Signed, IntegerBitSize::Eight) => cast_to_int!(lhs, to_i128, i8, I8), + (Signedness::Signed, IntegerBitSize::Sixteen) => { + cast_to_int!(lhs, to_i128, i16, I16) + } + (Signedness::Signed, IntegerBitSize::ThirtyTwo) => { + cast_to_int!(lhs, to_i128, i32, I32) + } + (Signedness::Signed, IntegerBitSize::SixtyFour) => { + cast_to_int!(lhs, to_i128, i64, I64) + } + }, + Type::Bool => Ok(Value::Bool(!lhs.is_zero() || lhs_is_negative)), + typ => { + let location = interner.expr_location(&id); + Err(InterpreterError::CastToNonNumericType { typ, location }) + } + } + } + + fn evaluate_if(&mut self, if_: HirIfExpression, id: ExprId) -> IResult { + let condition = match self.evaluate(if_.condition)? { + Value::Bool(value) => value, + value => { + let location = self.interner.expr_location(&id); + return Err(InterpreterError::NonBoolUsedInIf { value, location }); + } + }; + + self.push_scope(); + + let result = if condition { + if if_.alternative.is_some() { + self.evaluate(if_.consequence) + } else { + self.evaluate(if_.consequence)?; + Ok(Value::Unit) + } + } else { + match if_.alternative { + Some(alternative) => self.evaluate(alternative), + None => Ok(Value::Unit), + } + }; + + self.pop_scope(); + result + } + + fn evaluate_tuple(&mut self, tuple: Vec) -> IResult { + let fields = try_vecmap(tuple, |field| self.evaluate(field))?; + Ok(Value::Tuple(fields)) + } + + fn evaluate_lambda(&mut self, lambda: HirLambda, id: ExprId) -> IResult { + let location = self.interner.expr_location(&id); + let environment = + try_vecmap(&lambda.captures, |capture| self.lookup_id(capture.ident.id, location))?; + + let typ = self.interner.id_type(id); + Ok(Value::Closure(lambda, environment, typ)) + } + + pub fn evaluate_statement(&mut self, statement: StmtId) -> IResult { + match self.interner.statement(&statement) { + HirStatement::Let(let_) => self.evaluate_let(let_), + HirStatement::Constrain(constrain) => self.evaluate_constrain(constrain), + HirStatement::Assign(assign) => self.evaluate_assign(assign), + HirStatement::For(for_) => self.evaluate_for(for_), + HirStatement::Break => self.evaluate_break(statement), + HirStatement::Continue => self.evaluate_continue(statement), + HirStatement::Expression(expression) => self.evaluate(expression), + HirStatement::Comptime(statement) => self.evaluate_comptime(statement), + HirStatement::Semi(expression) => { + self.evaluate(expression)?; + Ok(Value::Unit) + } + HirStatement::Error => { + let location = self.interner.id_location(statement); + Err(InterpreterError::ErrorNodeEncountered { location }) + } + } + } + + pub fn evaluate_let(&mut self, let_: HirLetStatement) -> IResult { + let rhs = self.evaluate(let_.expression)?; + let location = self.interner.expr_location(&let_.expression); + self.define_pattern(&let_.pattern, &let_.r#type, rhs, location)?; + Ok(Value::Unit) + } + + fn evaluate_constrain(&mut self, constrain: HirConstrainStatement) -> IResult { + match self.evaluate(constrain.0)? { + Value::Bool(true) => Ok(Value::Unit), + Value::Bool(false) => { + let location = self.interner.expr_location(&constrain.0); + let message = constrain.2.and_then(|expr| self.evaluate(expr).ok()); + Err(InterpreterError::FailingConstraint { location, message }) + } + value => { + let location = self.interner.expr_location(&constrain.0); + Err(InterpreterError::NonBoolUsedInConstrain { value, location }) + } + } + } + + fn evaluate_assign(&mut self, assign: HirAssignStatement) -> IResult { + let rhs = self.evaluate(assign.expression)?; + self.store_lvalue(assign.lvalue, rhs)?; + Ok(Value::Unit) + } + + fn store_lvalue(&mut self, lvalue: HirLValue, rhs: Value) -> IResult<()> { + match lvalue { + HirLValue::Ident(ident, typ) => { + self.checked_mutate(ident.id, &typ, rhs, ident.location) + } + HirLValue::Dereference { lvalue, element_type: _, location } => { + match self.evaluate_lvalue(&lvalue)? { + Value::Pointer(value) => { + *value.borrow_mut() = rhs; + Ok(()) + } + value => Err(InterpreterError::NonPointerDereferenced { value, location }), + } + } + HirLValue::MemberAccess { object, field_name, field_index, typ: _, location } => { + let index = field_index.expect("The field index should be set after type checking"); + match self.evaluate_lvalue(&object)? { + Value::Tuple(mut fields) => { + fields[index] = rhs; + self.store_lvalue(*object, Value::Tuple(fields)) + } + Value::Struct(mut fields, typ) => { + fields.insert(Rc::new(field_name.0.contents), rhs); + self.store_lvalue(*object, Value::Struct(fields, typ)) + } + value => { + Err(InterpreterError::NonTupleOrStructInMemberAccess { value, location }) + } + } + } + HirLValue::Index { array, index, typ: _, location } => { + let array_value = self.evaluate_lvalue(&array)?; + let index = self.evaluate(index)?; + + let constructor = match &array_value { + Value::Array(..) => Value::Array, + _ => Value::Slice, + }; + + let typ = array_value.get_type().into_owned(); + let (elements, index) = self.bounds_check(array_value, index, location)?; + + let new_array = constructor(elements.update(index, rhs), typ); + self.store_lvalue(*array, new_array) + } + } + } + + fn evaluate_lvalue(&mut self, lvalue: &HirLValue) -> IResult { + match lvalue { + HirLValue::Ident(ident, _) => self.lookup(ident), + HirLValue::Dereference { lvalue, element_type: _, location } => { + match self.evaluate_lvalue(lvalue)? { + Value::Pointer(value) => Ok(value.borrow().clone()), + value => { + Err(InterpreterError::NonPointerDereferenced { value, location: *location }) + } + } + } + HirLValue::MemberAccess { object, field_name, field_index, typ: _, location } => { + let index = field_index.expect("The field index should be set after type checking"); + + match self.evaluate_lvalue(object)? { + Value::Tuple(mut values) => Ok(values.swap_remove(index)), + Value::Struct(fields, _) => Ok(fields[&field_name.0.contents].clone()), + value => Err(InterpreterError::NonTupleOrStructInMemberAccess { + value, + location: *location, + }), + } + } + HirLValue::Index { array, index, typ: _, location } => { + let array = self.evaluate_lvalue(array)?; + let index = self.evaluate(*index)?; + let (elements, index) = self.bounds_check(array, index, *location)?; + Ok(elements[index].clone()) + } + } + } + + fn evaluate_for(&mut self, for_: HirForStatement) -> IResult { + // i128 can store all values from i8 - u64 + let get_index = |this: &mut Self, expr| -> IResult<(_, fn(_) -> _)> { + match this.evaluate(expr)? { + Value::I8(value) => Ok((value as i128, |i| Value::I8(i as i8))), + Value::I16(value) => Ok((value as i128, |i| Value::I16(i as i16))), + Value::I32(value) => Ok((value as i128, |i| Value::I32(i as i32))), + Value::I64(value) => Ok((value as i128, |i| Value::I64(i as i64))), + Value::U8(value) => Ok((value as i128, |i| Value::U8(i as u8))), + Value::U16(value) => Ok((value as i128, |i| Value::U16(i as u16))), + Value::U32(value) => Ok((value as i128, |i| Value::U32(i as u32))), + Value::U64(value) => Ok((value as i128, |i| Value::U64(i as u64))), + value => { + let location = this.interner.expr_location(&expr); + Err(InterpreterError::NonIntegerUsedInLoop { value, location }) + } + } + }; + + let (start, make_value) = get_index(self, for_.start_range)?; + let (end, _) = get_index(self, for_.end_range)?; + let was_in_loop = std::mem::replace(&mut self.in_loop, true); + + for i in start..end { + self.push_scope(); + self.current_scope_mut().insert(for_.identifier.id, make_value(i)); + + match self.evaluate(for_.block) { + Ok(_) => (), + Err(InterpreterError::Break) => break, + Err(InterpreterError::Continue) => continue, + Err(other) => return Err(other), + } + self.pop_scope(); + } + + self.in_loop = was_in_loop; + Ok(Value::Unit) + } + + fn evaluate_break(&mut self, id: StmtId) -> IResult { + if self.in_loop { + Err(InterpreterError::Break) + } else { + let location = self.interner.statement_location(id); + Err(InterpreterError::BreakNotInLoop { location }) + } + } + + fn evaluate_continue(&mut self, id: StmtId) -> IResult { + if self.in_loop { + Err(InterpreterError::Continue) + } else { + let location = self.interner.statement_location(id); + Err(InterpreterError::ContinueNotInLoop { location }) + } + } + + pub(super) fn evaluate_comptime(&mut self, statement: StmtId) -> IResult { + self.evaluate_statement(statement) + } +} diff --git a/compiler/noirc_frontend/src/hir/comptime/mod.rs b/compiler/noirc_frontend/src/hir/comptime/mod.rs new file mode 100644 index 00000000000..ab984d2f2be --- /dev/null +++ b/compiler/noirc_frontend/src/hir/comptime/mod.rs @@ -0,0 +1,9 @@ +mod errors; +mod interpreter; +mod scan; +mod tests; +mod value; + +pub use errors::InterpreterError; +pub use interpreter::Interpreter; +pub use value::Value; diff --git a/compiler/noirc_frontend/src/hir/comptime/scan.rs b/compiler/noirc_frontend/src/hir/comptime/scan.rs new file mode 100644 index 00000000000..02010b6886d --- /dev/null +++ b/compiler/noirc_frontend/src/hir/comptime/scan.rs @@ -0,0 +1,258 @@ +//! This module is for the scanning of the Hir by the interpreter. +//! In this initial step, the Hir is scanned for `Comptime` nodes +//! without actually executing anything until such a node is found. +//! Once such a node is found, the interpreter will call the relevant +//! evaluate method on that node type, insert the result into the Ast, +//! and continue scanning the rest of the program. +//! +//! Since it mostly just needs to recur on the Hir looking for Comptime +//! nodes, this pass is fairly simple. The only thing it really needs to +//! ensure to do is to push and pop scopes on the interpreter as needed +//! so that any variables defined within e.g. an `if` statement containing +//! a `Comptime` block aren't accessible outside of the `if`. +use crate::{ + hir_def::{ + expr::{ + HirArrayLiteral, HirBlockExpression, HirCallExpression, HirConstructorExpression, + HirIdent, HirIfExpression, HirIndexExpression, HirInfixExpression, HirLambda, + HirMethodCallExpression, + }, + stmt::HirForStatement, + }, + macros_api::{HirExpression, HirLiteral, HirStatement}, + node_interner::{DefinitionKind, ExprId, FuncId, GlobalId, StmtId}, +}; + +use super::{ + errors::{IResult, InterpreterError}, + interpreter::Interpreter, + Value, +}; + +#[allow(dead_code)] +impl<'interner> Interpreter<'interner> { + /// Scan through a function, evaluating any Comptime nodes found. + /// These nodes will be modified in place, replaced with the + /// result of their evaluation. + pub fn scan_function(&mut self, function: FuncId) -> IResult<()> { + // Don't scan through functions that are already comptime. They may use comptime-only + // features (most likely HirExpression::Quote) that we'd otherwise error for. + if self.interner.function_modifiers(&function).is_comptime { + return Ok(()); + } + + let function = self.interner.function(&function); + + let state = self.enter_function(); + self.scan_expression(function.as_expr())?; + self.exit_function(state); + Ok(()) + } + + /// Evaluate this global if it is a comptime global. + /// Otherwise, scan through its expression for any comptime blocks to evaluate. + pub fn scan_global(&mut self, global: GlobalId) -> IResult<()> { + if let Some(let_) = self.interner.get_global_let_statement(global) { + if let_.comptime { + self.evaluate_let(let_)?; + } else { + self.scan_expression(let_.expression)?; + } + } + + Ok(()) + } + + fn scan_expression(&mut self, expr: ExprId) -> IResult<()> { + match self.interner.expression(&expr) { + HirExpression::Ident(ident, _) => self.scan_ident(ident, expr), + HirExpression::Literal(literal) => self.scan_literal(literal), + HirExpression::Block(block) => self.scan_block(block), + HirExpression::Prefix(prefix) => self.scan_expression(prefix.rhs), + HirExpression::Infix(infix) => self.scan_infix(infix), + HirExpression::Index(index) => self.scan_index(index), + HirExpression::Constructor(constructor) => self.scan_constructor(constructor), + HirExpression::MemberAccess(member_access) => self.scan_expression(member_access.lhs), + HirExpression::Call(call) => self.scan_call(call), + HirExpression::MethodCall(method_call) => self.scan_method_call(method_call), + HirExpression::Cast(cast) => self.scan_expression(cast.lhs), + HirExpression::If(if_) => self.scan_if(if_), + HirExpression::Tuple(tuple) => self.scan_tuple(tuple), + HirExpression::Lambda(lambda) => self.scan_lambda(lambda), + HirExpression::Comptime(block) => { + let location = self.interner.expr_location(&expr); + let new_expr = + self.evaluate_block(block)?.into_hir_expression(self.interner, location)?; + let new_expr = self.interner.expression(&new_expr); + self.interner.replace_expr(&expr, new_expr); + Ok(()) + } + HirExpression::Quote(_) => { + // This error could be detected much earlier in the compiler pipeline but + // it just makes sense for the comptime code to handle comptime things. + let location = self.interner.expr_location(&expr); + Err(InterpreterError::QuoteInRuntimeCode { location }) + } + HirExpression::Error => Ok(()), + + // Unquote should only be inserted by the comptime interpreter while expanding macros + // and is removed by the Hir -> Ast conversion pass which converts it into a normal block. + // If we find one now during scanning it most likely means the Hir -> Ast conversion + // missed it somehow. In the future we may allow users to manually write unquote + // expressions in their code but for now this is unreachable. + HirExpression::Unquote(block) => { + unreachable!("Found unquote block while scanning: {block}") + } + } + } + + // Identifiers have no code to execute but we may need to inline any values + // of comptime variables into runtime code. + fn scan_ident(&mut self, ident: HirIdent, id: ExprId) -> IResult<()> { + let definition = self.interner.definition(ident.id); + + match &definition.kind { + DefinitionKind::Function(_) => Ok(()), + _ => { + // Opportunistically evaluate this identifier to see if it is compile-time known. + // If so, inline its value. + if let Ok(value) = self.evaluate_ident(ident, id) { + // TODO(#4922): Inlining closures is currently unimplemented + if !matches!(value, Value::Closure(..)) { + self.inline_expression(value, id)?; + } + } + Ok(()) + } + } + } + + fn scan_literal(&mut self, literal: HirLiteral) -> IResult<()> { + match literal { + HirLiteral::Array(elements) | HirLiteral::Slice(elements) => match elements { + HirArrayLiteral::Standard(elements) => { + for element in elements { + self.scan_expression(element)?; + } + Ok(()) + } + HirArrayLiteral::Repeated { repeated_element, length: _ } => { + self.scan_expression(repeated_element) + } + }, + HirLiteral::Bool(_) + | HirLiteral::Integer(_, _) + | HirLiteral::Str(_) + | HirLiteral::FmtStr(_, _) + | HirLiteral::Unit => Ok(()), + } + } + + fn scan_block(&mut self, block: HirBlockExpression) -> IResult<()> { + self.push_scope(); + for statement in &block.statements { + self.scan_statement(*statement)?; + } + self.pop_scope(); + Ok(()) + } + + fn scan_infix(&mut self, infix: HirInfixExpression) -> IResult<()> { + self.scan_expression(infix.lhs)?; + self.scan_expression(infix.rhs) + } + + fn scan_index(&mut self, index: HirIndexExpression) -> IResult<()> { + self.scan_expression(index.collection)?; + self.scan_expression(index.index) + } + + fn scan_constructor(&mut self, constructor: HirConstructorExpression) -> IResult<()> { + for (_, field) in constructor.fields { + self.scan_expression(field)?; + } + Ok(()) + } + + fn scan_call(&mut self, call: HirCallExpression) -> IResult<()> { + self.scan_expression(call.func)?; + for arg in call.arguments { + self.scan_expression(arg)?; + } + Ok(()) + } + + fn scan_method_call(&mut self, method_call: HirMethodCallExpression) -> IResult<()> { + self.scan_expression(method_call.object)?; + for arg in method_call.arguments { + self.scan_expression(arg)?; + } + Ok(()) + } + + fn scan_if(&mut self, if_: HirIfExpression) -> IResult<()> { + self.scan_expression(if_.condition)?; + + self.push_scope(); + self.scan_expression(if_.consequence)?; + self.pop_scope(); + + if let Some(alternative) = if_.alternative { + self.push_scope(); + self.scan_expression(alternative)?; + self.pop_scope(); + } + Ok(()) + } + + fn scan_tuple(&mut self, tuple: Vec) -> IResult<()> { + for field in tuple { + self.scan_expression(field)?; + } + Ok(()) + } + + fn scan_lambda(&mut self, lambda: HirLambda) -> IResult<()> { + self.scan_expression(lambda.body) + } + + fn scan_statement(&mut self, statement: StmtId) -> IResult<()> { + match self.interner.statement(&statement) { + HirStatement::Let(let_) => self.scan_expression(let_.expression), + HirStatement::Constrain(constrain) => self.scan_expression(constrain.0), + HirStatement::Assign(assign) => self.scan_expression(assign.expression), + HirStatement::For(for_) => self.scan_for(for_), + HirStatement::Break => Ok(()), + HirStatement::Continue => Ok(()), + HirStatement::Expression(expression) => self.scan_expression(expression), + HirStatement::Semi(semi) => self.scan_expression(semi), + HirStatement::Error => Ok(()), + HirStatement::Comptime(comptime) => { + let location = self.interner.statement_location(comptime); + let new_expr = self + .evaluate_comptime(comptime)? + .into_hir_expression(self.interner, location)?; + self.interner.replace_statement(statement, HirStatement::Expression(new_expr)); + Ok(()) + } + } + } + + fn scan_for(&mut self, for_: HirForStatement) -> IResult<()> { + // We don't need to set self.in_loop since we're not actually evaluating this loop. + // We just need to push a scope so that if there's a `comptime { .. }` expr inside this + // loop, any variables it defines aren't accessible outside of it. + self.push_scope(); + self.scan_expression(for_.block)?; + self.pop_scope(); + Ok(()) + } + + fn inline_expression(&mut self, value: Value, expr: ExprId) -> IResult<()> { + let location = self.interner.expr_location(&expr); + let new_expr = value.into_hir_expression(self.interner, location)?; + let new_expr = self.interner.expression(&new_expr); + self.interner.replace_expr(&expr, new_expr); + Ok(()) + } +} diff --git a/compiler/noirc_frontend/src/hir/comptime/tests.rs b/compiler/noirc_frontend/src/hir/comptime/tests.rs new file mode 100644 index 00000000000..43f6e21905b --- /dev/null +++ b/compiler/noirc_frontend/src/hir/comptime/tests.rs @@ -0,0 +1,198 @@ +#![cfg(test)] + +use std::collections::HashMap; + +use noirc_errors::Location; + +use super::errors::InterpreterError; +use super::interpreter::Interpreter; +use super::value::Value; +use crate::hir::type_check::test::type_check_src_code; + +fn interpret_helper(src: &str, func_namespace: Vec) -> Result { + let (mut interner, main_id) = type_check_src_code(src, func_namespace); + let mut scopes = vec![HashMap::default()]; + let mut interpreter = Interpreter::new(&mut interner, &mut scopes); + + let no_location = Location::dummy(); + interpreter.call_function(main_id, Vec::new(), no_location) +} + +fn interpret(src: &str, func_namespace: Vec) -> Value { + interpret_helper(src, func_namespace).unwrap_or_else(|error| { + panic!("Expected interpreter to exit successfully, but found {error:?}") + }) +} + +fn interpret_expect_error(src: &str, func_namespace: Vec) -> InterpreterError { + interpret_helper(src, func_namespace).expect_err("Expected interpreter to error") +} + +#[test] +fn interpreter_works() { + let program = "fn main() -> pub Field { 3 }"; + let result = interpret(program, vec!["main".into()]); + assert_eq!(result, Value::Field(3u128.into())); +} + +#[test] +fn mutation_works() { + let program = "fn main() -> pub i8 { + let mut x = 3; + x = 4; + x + }"; + let result = interpret(program, vec!["main".into()]); + assert_eq!(result, Value::I8(4)); +} + +#[test] +fn mutating_references() { + let program = "fn main() -> pub i32 { + let x = &mut 3; + *x = 4; + *x + }"; + let result = interpret(program, vec!["main".into()]); + assert_eq!(result, Value::I32(4)); +} + +#[test] +fn mutating_mutable_references() { + let program = "fn main() -> pub i64 { + let mut x = &mut 3; + *x = 4; + *x + }"; + let result = interpret(program, vec!["main".into()]); + assert_eq!(result, Value::I64(4)); +} + +#[test] +fn mutating_arrays() { + let program = "fn main() -> pub u8 { + let mut a1 = [1, 2, 3, 4]; + a1[1] = 22; + a1[1] + }"; + let result = interpret(program, vec!["main".into()]); + assert_eq!(result, Value::U8(22)); +} + +#[test] +fn mutate_in_new_scope() { + let program = "fn main() -> pub u8 { + let mut x = 0; + x += 1; + { + x += 1; + } + x + }"; + let result = interpret(program, vec!["main".into()]); + assert_eq!(result, Value::U8(2)); +} + +#[test] +fn for_loop() { + let program = "fn main() -> pub u8 { + let mut x = 0; + for i in 0 .. 6 { + x += i; + } + x + }"; + let result = interpret(program, vec!["main".into()]); + assert_eq!(result, Value::U8(15)); +} + +#[test] +fn for_loop_u16() { + let program = "fn main() -> pub u16 { + let mut x = 0; + for i in 0 .. 6 { + x += i; + } + x + }"; + let result = interpret(program, vec!["main".into()]); + assert_eq!(result, Value::U16(15)); +} + +#[test] +fn for_loop_with_break() { + let program = "unconstrained fn main() -> pub u32 { + let mut x = 0; + for i in 0 .. 6 { + if i == 4 { + break; + } + x += i; + } + x + }"; + let result = interpret(program, vec!["main".into()]); + assert_eq!(result, Value::U32(6)); +} + +#[test] +fn for_loop_with_continue() { + let program = "unconstrained fn main() -> pub u64 { + let mut x = 0; + for i in 0 .. 6 { + if i == 4 { + continue; + } + x += i; + } + x + }"; + let result = interpret(program, vec!["main".into()]); + assert_eq!(result, Value::U64(11)); +} + +#[test] +fn assert() { + let program = "fn main() { + assert(1 == 1); + }"; + let result = interpret(program, vec!["main".into()]); + assert_eq!(result, Value::Unit); +} + +#[test] +fn assert_fail() { + let program = "fn main() { + assert(1 == 2); + }"; + let result = interpret_expect_error(program, vec!["main".into()]); + assert!(matches!(result, InterpreterError::FailingConstraint { .. })); +} + +#[test] +fn lambda() { + let program = "fn main() -> pub u8 { + let f = |x: u8| x + 1; + f(1) + }"; + let result = interpret(program, vec!["main".into()]); + assert!(matches!(result, Value::U8(2))); +} + +#[test] +fn non_deterministic_recursion() { + let program = " + fn main() -> pub u64 { + fib(10) + } + + fn fib(x: u64) -> u64 { + if x <= 1 { + x + } else { + fib(x - 1) + fib(x - 2) + } + }"; + let result = interpret(program, vec!["main".into(), "fib".into()]); + assert_eq!(result, Value::U64(55)); +} diff --git a/compiler/noirc_frontend/src/hir/comptime/value.rs b/compiler/noirc_frontend/src/hir/comptime/value.rs new file mode 100644 index 00000000000..43d461ad043 --- /dev/null +++ b/compiler/noirc_frontend/src/hir/comptime/value.rs @@ -0,0 +1,308 @@ +use std::{borrow::Cow, rc::Rc}; + +use acvm::{AcirField, FieldElement}; +use im::Vector; +use iter_extended::{try_vecmap, vecmap}; +use noirc_errors::Location; + +use crate::{ + ast::{ + ArrayLiteral, BlockExpression, ConstructorExpression, Ident, IntegerBitSize, Signedness, + }, + hir_def::expr::{HirArrayLiteral, HirConstructorExpression, HirIdent, HirLambda, ImplKind}, + macros_api::{ + Expression, ExpressionKind, HirExpression, HirLiteral, Literal, NodeInterner, Path, + }, + node_interner::{ExprId, FuncId}, + Shared, Type, +}; +use rustc_hash::FxHashMap as HashMap; + +use super::errors::{IResult, InterpreterError}; + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum Value { + Unit, + Bool(bool), + Field(FieldElement), + I8(i8), + I16(i16), + I32(i32), + I64(i64), + U8(u8), + U16(u16), + U32(u32), + U64(u64), + String(Rc), + Function(FuncId, Type), + Closure(HirLambda, Vec, Type), + Tuple(Vec), + Struct(HashMap, Value>, Type), + Pointer(Shared), + Array(Vector, Type), + Slice(Vector, Type), + Code(Rc), +} + +impl Value { + pub(crate) fn get_type(&self) -> Cow { + Cow::Owned(match self { + Value::Unit => Type::Unit, + Value::Bool(_) => Type::Bool, + Value::Field(_) => Type::FieldElement, + Value::I8(_) => Type::Integer(Signedness::Signed, IntegerBitSize::Eight), + Value::I16(_) => Type::Integer(Signedness::Signed, IntegerBitSize::Sixteen), + Value::I32(_) => Type::Integer(Signedness::Signed, IntegerBitSize::ThirtyTwo), + Value::I64(_) => Type::Integer(Signedness::Signed, IntegerBitSize::SixtyFour), + Value::U8(_) => Type::Integer(Signedness::Unsigned, IntegerBitSize::Eight), + Value::U16(_) => Type::Integer(Signedness::Unsigned, IntegerBitSize::Sixteen), + Value::U32(_) => Type::Integer(Signedness::Unsigned, IntegerBitSize::ThirtyTwo), + Value::U64(_) => Type::Integer(Signedness::Unsigned, IntegerBitSize::SixtyFour), + Value::String(value) => { + let length = Type::Constant(value.len() as u32); + Type::String(Box::new(length)) + } + Value::Function(_, typ) => return Cow::Borrowed(typ), + Value::Closure(_, _, typ) => return Cow::Borrowed(typ), + Value::Tuple(fields) => { + Type::Tuple(vecmap(fields, |field| field.get_type().into_owned())) + } + Value::Struct(_, typ) => return Cow::Borrowed(typ), + Value::Array(_, typ) => return Cow::Borrowed(typ), + Value::Slice(_, typ) => return Cow::Borrowed(typ), + Value::Code(_) => Type::Code, + Value::Pointer(element) => { + let element = element.borrow().get_type().into_owned(); + Type::MutableReference(Box::new(element)) + } + }) + } + + pub(crate) fn into_expression( + self, + interner: &mut NodeInterner, + location: Location, + ) -> IResult { + let kind = match self { + Value::Unit => ExpressionKind::Literal(Literal::Unit), + Value::Bool(value) => ExpressionKind::Literal(Literal::Bool(value)), + Value::Field(value) => ExpressionKind::Literal(Literal::Integer(value, false)), + Value::I8(value) => { + let negative = value < 0; + let value = value.abs(); + let value = (value as u128).into(); + ExpressionKind::Literal(Literal::Integer(value, negative)) + } + Value::I16(value) => { + let negative = value < 0; + let value = value.abs(); + let value = (value as u128).into(); + ExpressionKind::Literal(Literal::Integer(value, negative)) + } + Value::I32(value) => { + let negative = value < 0; + let value = value.abs(); + let value = (value as u128).into(); + ExpressionKind::Literal(Literal::Integer(value, negative)) + } + Value::I64(value) => { + let negative = value < 0; + let value = value.abs(); + let value = (value as u128).into(); + ExpressionKind::Literal(Literal::Integer(value, negative)) + } + Value::U8(value) => { + ExpressionKind::Literal(Literal::Integer((value as u128).into(), false)) + } + Value::U16(value) => { + ExpressionKind::Literal(Literal::Integer((value as u128).into(), false)) + } + Value::U32(value) => { + ExpressionKind::Literal(Literal::Integer((value as u128).into(), false)) + } + Value::U64(value) => { + ExpressionKind::Literal(Literal::Integer((value as u128).into(), false)) + } + Value::String(value) => ExpressionKind::Literal(Literal::Str(unwrap_rc(value))), + Value::Function(id, typ) => { + let id = interner.function_definition_id(id); + let impl_kind = ImplKind::NotATraitMethod; + let ident = HirIdent { location, id, impl_kind }; + let expr_id = interner.push_expr(HirExpression::Ident(ident, None)); + interner.push_expr_location(expr_id, location.span, location.file); + interner.push_expr_type(expr_id, typ); + ExpressionKind::Resolved(expr_id) + } + Value::Closure(_lambda, _env, _typ) => { + // TODO: How should a closure's environment be inlined? + let item = "Returning closures from a comptime fn"; + return Err(InterpreterError::Unimplemented { item, location }); + } + Value::Tuple(fields) => { + let fields = try_vecmap(fields, |field| field.into_expression(interner, location))?; + ExpressionKind::Tuple(fields) + } + Value::Struct(fields, typ) => { + let fields = try_vecmap(fields, |(name, field)| { + let field = field.into_expression(interner, location)?; + Ok((Ident::new(unwrap_rc(name), location.span), field)) + })?; + + let struct_type = match typ.follow_bindings() { + Type::Struct(def, _) => Some(def.borrow().id), + _ => return Err(InterpreterError::NonStructInConstructor { typ, location }), + }; + + // Since we've provided the struct_type, the path should be ignored. + let type_name = Path::from_single(String::new(), location.span); + ExpressionKind::Constructor(Box::new(ConstructorExpression { + type_name, + fields, + struct_type, + })) + } + Value::Array(elements, _) => { + let elements = + try_vecmap(elements, |element| element.into_expression(interner, location))?; + ExpressionKind::Literal(Literal::Array(ArrayLiteral::Standard(elements))) + } + Value::Slice(elements, _) => { + let elements = + try_vecmap(elements, |element| element.into_expression(interner, location))?; + ExpressionKind::Literal(Literal::Slice(ArrayLiteral::Standard(elements))) + } + Value::Code(block) => ExpressionKind::Block(unwrap_rc(block)), + Value::Pointer(_) => { + return Err(InterpreterError::CannotInlineMacro { value: self, location }) + } + }; + + Ok(Expression::new(kind, location.span)) + } + + pub(crate) fn into_hir_expression( + self, + interner: &mut NodeInterner, + location: Location, + ) -> IResult { + let typ = self.get_type().into_owned(); + + let expression = match self { + Value::Unit => HirExpression::Literal(HirLiteral::Unit), + Value::Bool(value) => HirExpression::Literal(HirLiteral::Bool(value)), + Value::Field(value) => HirExpression::Literal(HirLiteral::Integer(value, false)), + Value::I8(value) => { + let negative = value < 0; + let value = value.abs(); + let value = (value as u128).into(); + HirExpression::Literal(HirLiteral::Integer(value, negative)) + } + Value::I16(value) => { + let negative = value < 0; + let value = value.abs(); + let value = (value as u128).into(); + HirExpression::Literal(HirLiteral::Integer(value, negative)) + } + Value::I32(value) => { + let negative = value < 0; + let value = value.abs(); + let value = (value as u128).into(); + HirExpression::Literal(HirLiteral::Integer(value, negative)) + } + Value::I64(value) => { + let negative = value < 0; + let value = value.abs(); + let value = (value as u128).into(); + HirExpression::Literal(HirLiteral::Integer(value, negative)) + } + Value::U8(value) => { + HirExpression::Literal(HirLiteral::Integer((value as u128).into(), false)) + } + Value::U16(value) => { + HirExpression::Literal(HirLiteral::Integer((value as u128).into(), false)) + } + Value::U32(value) => { + HirExpression::Literal(HirLiteral::Integer((value as u128).into(), false)) + } + Value::U64(value) => { + HirExpression::Literal(HirLiteral::Integer((value as u128).into(), false)) + } + Value::String(value) => HirExpression::Literal(HirLiteral::Str(unwrap_rc(value))), + Value::Function(id, _typ) => { + let id = interner.function_definition_id(id); + let impl_kind = ImplKind::NotATraitMethod; + HirExpression::Ident(HirIdent { location, id, impl_kind }, None) + } + Value::Closure(_lambda, _env, _typ) => { + // TODO: How should a closure's environment be inlined? + let item = "Returning closures from a comptime fn"; + return Err(InterpreterError::Unimplemented { item, location }); + } + Value::Tuple(fields) => { + let fields = + try_vecmap(fields, |field| field.into_hir_expression(interner, location))?; + HirExpression::Tuple(fields) + } + Value::Struct(fields, typ) => { + let fields = try_vecmap(fields, |(name, field)| { + let field = field.into_hir_expression(interner, location)?; + Ok((Ident::new(unwrap_rc(name), location.span), field)) + })?; + + let (r#type, struct_generics) = match typ.follow_bindings() { + Type::Struct(def, generics) => (def, generics), + _ => return Err(InterpreterError::NonStructInConstructor { typ, location }), + }; + + HirExpression::Constructor(HirConstructorExpression { + r#type, + struct_generics, + fields, + }) + } + Value::Array(elements, _) => { + let elements = try_vecmap(elements, |element| { + element.into_hir_expression(interner, location) + })?; + HirExpression::Literal(HirLiteral::Array(HirArrayLiteral::Standard(elements))) + } + Value::Slice(elements, _) => { + let elements = try_vecmap(elements, |element| { + element.into_hir_expression(interner, location) + })?; + HirExpression::Literal(HirLiteral::Slice(HirArrayLiteral::Standard(elements))) + } + Value::Code(block) => HirExpression::Unquote(unwrap_rc(block)), + Value::Pointer(_) => { + return Err(InterpreterError::CannotInlineMacro { value: self, location }) + } + }; + + let id = interner.push_expr(expression); + interner.push_expr_location(id, location.span, location.file); + interner.push_expr_type(id, typ); + Ok(id) + } + + /// Converts any unsigned `Value` into a `u128`. + /// Returns `None` for negative integers. + pub(crate) fn to_u128(&self) -> Option { + match self { + Self::Field(value) => Some(value.to_u128()), + Self::I8(value) => (*value >= 0).then_some(*value as u128), + Self::I16(value) => (*value >= 0).then_some(*value as u128), + Self::I32(value) => (*value >= 0).then_some(*value as u128), + Self::I64(value) => (*value >= 0).then_some(*value as u128), + Self::U8(value) => Some(*value as u128), + Self::U16(value) => Some(*value as u128), + Self::U32(value) => Some(*value as u128), + Self::U64(value) => Some(*value as u128), + _ => None, + } + } +} + +/// Unwraps an Rc value without cloning the inner value if the reference count is 1. Clones otherwise. +fn unwrap_rc(rc: Rc) -> T { + Rc::try_unwrap(rc).unwrap_or_else(|rc| (*rc).clone()) +} 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 7f36af5b30e..9b47a104a40 100644 --- a/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs +++ b/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs @@ -1,41 +1,59 @@ use super::dc_mod::collect_defs; use super::errors::{DefCollectorErrorKind, DuplicateType}; +use crate::elaborator::Elaborator; use crate::graph::CrateId; +use crate::hir::comptime::{Interpreter, InterpreterError}; use crate::hir::def_map::{CrateDefMap, LocalModuleId, ModuleId}; use crate::hir::resolution::errors::ResolverError; +use crate::{Type, TypeVariable}; -use crate::hir::resolution::import::{resolve_import, ImportDirective}; -use crate::hir::resolution::resolver::Resolver; +use crate::hir::resolution::import::{resolve_import, ImportDirective, PathResolution}; use crate::hir::resolution::{ collect_impls, collect_trait_impls, path_resolver, resolve_free_functions, resolve_globals, resolve_impls, resolve_structs, resolve_trait_by_path, resolve_trait_impls, resolve_traits, resolve_type_aliases, }; -use crate::hir::type_check::{type_check_func, TypeCheckError, TypeChecker}; +use crate::hir::type_check::{ + check_trait_impl_method_matches_declaration, type_check_func, TypeCheckError, TypeChecker, +}; use crate::hir::Context; use crate::macros_api::{MacroError, MacroProcessor}; -use crate::node_interner::{FuncId, GlobalId, NodeInterner, StructId, TraitId, TypeAliasId}; +use crate::node_interner::{ + FuncId, GlobalId, NodeInterner, StructId, TraitId, TraitImplId, TypeAliasId, +}; -use crate::parser::{ParserError, SortedModule}; -use crate::{ +use crate::ast::{ ExpressionKind, Ident, LetStatement, Literal, NoirFunction, NoirStruct, NoirTrait, - NoirTypeAlias, Path, PathKind, Type, TypeBindings, UnresolvedGenerics, - UnresolvedTraitConstraint, UnresolvedType, + NoirTypeAlias, Path, PathKind, UnresolvedGenerics, UnresolvedTraitConstraint, UnresolvedType, }; +use crate::parser::{ParserError, SortedModule}; use fm::FileId; use iter_extended::vecmap; use noirc_errors::{CustomDiagnostic, Span}; use std::collections::{BTreeMap, HashMap}; +use std::rc::Rc; use std::vec; +#[derive(Default)] +pub struct ResolvedModule { + pub globals: Vec<(FileId, GlobalId)>, + pub functions: Vec<(FileId, FuncId)>, + pub trait_impl_functions: Vec<(FileId, FuncId)>, + + pub errors: Vec<(CompilationError, FileId)>, +} + /// Stores all of the unresolved functions in a particular file/mod #[derive(Clone)] pub struct UnresolvedFunctions { pub file_id: FileId, pub functions: Vec<(LocalModuleId, FuncId, NoirFunction)>, pub trait_id: Option, + + // The object type this set of functions was declared on, if there is one. + pub self_type: Option, } impl UnresolvedFunctions { @@ -43,6 +61,10 @@ impl UnresolvedFunctions { self.functions.push((mod_id, func_id, func)); } + pub fn function_ids(&self) -> Vec { + vecmap(&self.functions, |(_, id, _)| *id) + } + pub fn resolve_trait_bounds_trait_ids( &mut self, def_maps: &BTreeMap, @@ -56,8 +78,11 @@ impl UnresolvedFunctions { for bound in &mut func.def.where_clause { match resolve_trait_by_path(def_maps, module, bound.trait_bound.trait_path.clone()) { - Ok(trait_id) => { + Ok((trait_id, warning)) => { bound.trait_bound.trait_id = Some(trait_id); + if let Some(warning) = warning { + errors.push(DefCollectorErrorKind::PathResolutionError(warning)); + } } Err(err) => { errors.push(err); @@ -89,13 +114,22 @@ pub struct UnresolvedTrait { pub struct UnresolvedTraitImpl { pub file_id: FileId, pub module_id: LocalModuleId, - pub trait_id: Option, pub trait_generics: Vec, pub trait_path: Path, pub object_type: UnresolvedType, pub methods: UnresolvedFunctions, pub generics: UnresolvedGenerics, pub where_clause: Vec, + + // Every field after this line is filled in later in the elaborator + pub trait_id: Option, + pub impl_id: Option, + pub resolved_object_type: Option, + pub resolved_generics: Vec<(Rc, TypeVariable, Span)>, + + // The resolved generic on the trait itself. E.g. it is the `` in + // `impl Foo for Bar { ... }` + pub resolved_trait_generics: Vec, } #[derive(Clone)] @@ -105,7 +139,7 @@ pub struct UnresolvedTypeAlias { pub type_alias_def: NoirTypeAlias, } -#[derive(Clone)] +#[derive(Debug, Clone)] pub struct UnresolvedGlobal { pub file_id: FileId, pub module_id: LocalModuleId, @@ -116,14 +150,18 @@ pub struct UnresolvedGlobal { /// Given a Crate root, collect all definitions in that crate pub struct DefCollector { pub(crate) def_map: CrateDefMap, - pub(crate) collected_imports: Vec, - pub(crate) collected_functions: Vec, - pub(crate) collected_types: BTreeMap, - pub(crate) collected_type_aliases: BTreeMap, - pub(crate) collected_traits: BTreeMap, - pub(crate) collected_globals: Vec, - pub(crate) collected_impls: ImplMap, - pub(crate) collected_traits_impls: Vec, + pub(crate) imports: Vec, + pub(crate) items: CollectedItems, +} + +pub struct CollectedItems { + pub(crate) functions: Vec, + pub(crate) types: BTreeMap, + pub(crate) type_aliases: BTreeMap, + pub(crate) traits: BTreeMap, + pub(crate) globals: Vec, + pub(crate) impls: ImplMap, + pub(crate) trait_impls: Vec, } /// Maps the type and the module id in which the impl is defined to the functions contained in that @@ -142,15 +180,24 @@ pub enum CompilationError { DefinitionError(DefCollectorErrorKind), ResolverError(ResolverError), TypeError(TypeCheckError), + InterpreterError(InterpreterError), } -impl From for CustomDiagnostic { - fn from(value: CompilationError) -> Self { +impl CompilationError { + fn is_error(&self) -> bool { + let diagnostic = CustomDiagnostic::from(self); + diagnostic.is_error() + } +} + +impl<'a> From<&'a CompilationError> for CustomDiagnostic { + fn from(value: &'a CompilationError) -> Self { match value { CompilationError::ParseError(error) => error.into(), CompilationError::DefinitionError(error) => error.into(), CompilationError::ResolverError(error) => error.into(), CompilationError::TypeError(error) => error.into(), + CompilationError::InterpreterError(error) => error.into(), } } } @@ -188,14 +235,16 @@ impl DefCollector { fn new(def_map: CrateDefMap) -> DefCollector { DefCollector { def_map, - collected_imports: vec![], - collected_functions: vec![], - collected_types: BTreeMap::new(), - collected_type_aliases: BTreeMap::new(), - collected_traits: BTreeMap::new(), - collected_impls: HashMap::new(), - collected_globals: vec![], - collected_traits_impls: vec![], + imports: vec![], + items: CollectedItems { + functions: vec![], + types: BTreeMap::new(), + type_aliases: BTreeMap::new(), + traits: BTreeMap::new(), + impls: HashMap::new(), + globals: vec![], + trait_impls: vec![], + }, } } @@ -207,7 +256,8 @@ impl DefCollector { context: &mut Context, ast: SortedModule, root_file_id: FileId, - macro_processors: Vec<&dyn MacroProcessor>, + use_elaborator: bool, + macro_processors: &[&dyn MacroProcessor], ) -> Vec<(CompilationError, FileId)> { let mut errors: Vec<(CompilationError, FileId)> = vec![]; let crate_id = def_map.krate; @@ -223,7 +273,8 @@ impl DefCollector { errors.extend(CrateDefMap::collect_defs( dep.crate_id, context, - macro_processors.clone(), + use_elaborator, + macro_processors, )); let dep_def_root = @@ -250,40 +301,29 @@ impl DefCollector { crate_root, crate_id, context, + macro_processors, )); let submodules = vecmap(def_collector.def_map.modules().iter(), |(index, _)| index); // Add the current crate to the collection of DefMaps context.def_maps.insert(crate_id, def_collector.def_map); - // TODO(#4653): generalize this function - for macro_processor in ¯o_processors { - macro_processor - .process_unresolved_traits_impls( - &crate_id, - context, - &def_collector.collected_traits_impls, - &mut def_collector.collected_functions, - ) - .unwrap_or_else(|(macro_err, file_id)| { - errors.push((macro_err.into(), file_id)); - }); - } - - inject_prelude(crate_id, context, crate_root, &mut def_collector.collected_imports); + inject_prelude(crate_id, context, crate_root, &mut def_collector.imports); for submodule in submodules { - inject_prelude( - crate_id, - context, - LocalModuleId(submodule), - &mut def_collector.collected_imports, - ); + inject_prelude(crate_id, context, LocalModuleId(submodule), &mut def_collector.imports); } // Resolve unresolved imports collected from the crate, one by one. - for collected_import in def_collector.collected_imports { - match resolve_import(crate_id, collected_import, &context.def_maps) { + for collected_import in std::mem::take(&mut def_collector.imports) { + match resolve_import(crate_id, &collected_import, &context.def_maps) { Ok(resolved_import) => { + if let Some(error) = resolved_import.error { + errors.push(( + DefCollectorErrorKind::PathResolutionError(error).into(), + root_file_id, + )); + } + // Populate module namespaces according to the imports used let current_def_map = context.def_maps.get_mut(&crate_id).unwrap(); @@ -302,46 +342,56 @@ impl DefCollector { } } } - Err((error, module_id)) => { + Err(error) => { let current_def_map = context.def_maps.get(&crate_id).unwrap(); - let file_id = current_def_map.file_id(module_id); + let file_id = current_def_map.file_id(collected_import.module_id); let error = DefCollectorErrorKind::PathResolutionError(error); errors.push((error.into(), file_id)); } } } + if use_elaborator { + let mut more_errors = Elaborator::elaborate(context, crate_id, def_collector.items); + errors.append(&mut more_errors); + return errors; + } + + let mut resolved_module = ResolvedModule { errors, ..Default::default() }; + // We must first resolve and intern the globals before we can resolve any stmts inside each function. // Each function uses its own resolver with a newly created ScopeForest, and must be resolved again to be within a function's scope // // Additionally, we must resolve integer globals before structs since structs may refer to // the values of integer globals as numeric generics. - let (literal_globals, other_globals) = - filter_literal_globals(def_collector.collected_globals); + let (literal_globals, other_globals) = filter_literal_globals(def_collector.items.globals); - let mut resolved_globals = resolve_globals(context, literal_globals, crate_id); + resolved_module.resolve_globals(context, literal_globals, crate_id); - errors.extend(resolve_type_aliases( + resolved_module.errors.extend(resolve_type_aliases( context, - def_collector.collected_type_aliases, + def_collector.items.type_aliases, crate_id, )); - errors.extend(resolve_traits(context, def_collector.collected_traits, crate_id)); + resolved_module.errors.extend(resolve_traits( + context, + def_collector.items.traits, + crate_id, + )); // Must resolve structs before we resolve globals. - errors.extend(resolve_structs(context, def_collector.collected_types, crate_id)); - - // We must wait to resolve non-integer globals until after we resolve structs since struct - // 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)); - errors.extend(resolved_globals.errors); + resolved_module.errors.extend(resolve_structs( + context, + def_collector.items.types, + crate_id, + )); // Bind trait impls to their trait. Collect trait functions, that have a // default implementation, which hasn't been overridden. - errors.extend(collect_trait_impls( + resolved_module.errors.extend(collect_trait_impls( context, crate_id, - &mut def_collector.collected_traits_impls, + &mut def_collector.items.trait_impls, )); // Before we resolve any function symbols we must go through our impls and @@ -351,47 +401,56 @@ impl DefCollector { // // 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)); + resolved_module.errors.extend(collect_impls(context, crate_id, &def_collector.items.impls)); + + // We must wait to resolve non-integer globals until after we resolve structs since struct + // globals will need to reference the struct type they're initialized to to ensure they are valid. + resolved_module.resolve_globals(context, other_globals, crate_id); // Resolve each function in the crate. This is now possible since imports have been resolved - let mut functions = Vec::new(); - functions.extend(resolve_free_functions( + resolved_module.functions = resolve_free_functions( &mut context.def_interner, crate_id, &context.def_maps, - def_collector.collected_functions, + def_collector.items.functions, None, - &mut errors, - )); + &mut resolved_module.errors, + ); - functions.extend(resolve_impls( + resolved_module.functions.extend(resolve_impls( &mut context.def_interner, crate_id, &context.def_maps, - def_collector.collected_impls, - &mut errors, + def_collector.items.impls, + &mut resolved_module.errors, )); - functions.extend(resolve_trait_impls( + resolved_module.trait_impl_functions = resolve_trait_impls( context, - def_collector.collected_traits_impls, + def_collector.items.trait_impls, crate_id, - &mut errors, - )); + &mut resolved_module.errors, + ); for macro_processor in macro_processors { macro_processor.process_typed_ast(&crate_id, context).unwrap_or_else( |(macro_err, file_id)| { - errors.push((macro_err.into(), file_id)); + resolved_module.errors.push((macro_err.into(), file_id)); }, ); } - errors.extend(context.def_interner.check_for_dependency_cycles()); + let cycle_errors = context.def_interner.check_for_dependency_cycles(); + let cycles_present = !cycle_errors.is_empty(); + resolved_module.errors.extend(cycle_errors); - errors.extend(type_check_globals(&mut context.def_interner, resolved_globals.globals)); - errors.extend(type_check_functions(&mut context.def_interner, functions)); - errors + resolved_module.type_check(context); + + if !cycles_present { + resolved_module.evaluate_comptime(&mut context.def_interner); + } + + resolved_module.errors } } @@ -401,21 +460,25 @@ fn inject_prelude( crate_root: LocalModuleId, collected_imports: &mut Vec, ) { - let segments: Vec<_> = "std::prelude" - .split("::") - .map(|segment| crate::Ident::new(segment.into(), Span::default())) - .collect(); - - let path = - Path { segments: segments.clone(), kind: crate::PathKind::Dep, span: Span::default() }; - if !crate_id.is_stdlib() { - if let Ok(module_def) = path_resolver::resolve_path( + let segments: Vec<_> = "std::prelude" + .split("::") + .map(|segment| crate::ast::Ident::new(segment.into(), Span::default())) + .collect(); + + let path = Path { + segments: segments.clone(), + kind: crate::ast::PathKind::Dep, + span: Span::default(), + }; + + if let Ok(PathResolution { module_def_id, error }) = path_resolver::resolve_path( &context.def_maps, ModuleId { krate: crate_id, local_id: crate_root }, path, ) { - let module_id = module_def.as_module().expect("std::prelude should be a module"); + assert!(error.is_none(), "Tried to add private item to prelude"); + let module_id = module_def_id.as_module().expect("std::prelude should be a module"); let prelude = context.module(module_id).scope().names(); for path in prelude { @@ -439,7 +502,7 @@ fn inject_prelude( /// Separate the globals Vec into two. The first element in the tuple will be the /// literal globals, except for arrays, and the second will be all other globals. /// We exclude array literals as they can contain complex types -fn filter_literal_globals( +pub fn filter_literal_globals( globals: Vec, ) -> (Vec, Vec) { globals.into_iter().partition(|global| match &global.stmt_def.expression.kind { @@ -448,182 +511,75 @@ fn filter_literal_globals( }) } -fn type_check_globals( - interner: &mut NodeInterner, - global_ids: Vec<(FileId, GlobalId)>, -) -> Vec<(CompilationError, fm::FileId)> { - global_ids - .into_iter() - .flat_map(|(file_id, global_id)| { - TypeChecker::check_global(global_id, interner) - .iter() - .cloned() - .map(|e| (e.into(), file_id)) - .collect::>() - }) - .collect() -} - -fn type_check_functions( - interner: &mut NodeInterner, - file_func_ids: Vec<(FileId, FuncId)>, -) -> Vec<(CompilationError, fm::FileId)> { - file_func_ids - .into_iter() - .flat_map(|(file, func)| { - type_check_func(interner, func) - .iter() - .cloned() - .map(|e| (e.into(), file)) - .collect::>() - }) - .collect() -} - -// TODO(vitkov): Move this out of here and into type_check -#[allow(clippy::too_many_arguments)] -pub(crate) fn check_methods_signatures( - resolver: &mut Resolver, - impl_methods: &[(FileId, FuncId)], - trait_id: TraitId, - trait_name_span: Span, - // These are the generics on the trait itself from the impl. - // E.g. in `impl Foo for Bar`, this is `vec![A, B]`. - trait_generics: Vec, - trait_impl_generic_count: usize, - file_id: FileId, - errors: &mut Vec<(CompilationError, FileId)>, -) { - let self_type = resolver.get_self_type().expect("trait impl must have a Self type").clone(); - let trait_generics = vecmap(trait_generics, |typ| resolver.resolve_type(typ)); - - // Temporarily bind the trait's Self type to self_type so we can type check - let the_trait = resolver.interner.get_trait_mut(trait_id); - the_trait.self_type_typevar.bind(self_type); - - if trait_generics.len() != the_trait.generics.len() { - let error = DefCollectorErrorKind::MismatchGenericCount { - actual_generic_count: trait_generics.len(), - expected_generic_count: the_trait.generics.len(), - // Preferring to use 'here' over a more precise term like 'this reference' - // to try to make the error easier to understand for newer users. - location: "here it", - origin: the_trait.name.to_string(), - span: trait_name_span, - }; - errors.push((error.into(), file_id)); +impl ResolvedModule { + fn type_check(&mut self, context: &mut Context) { + self.type_check_globals(&mut context.def_interner); + self.type_check_functions(&mut context.def_interner); + self.type_check_trait_impl_function(&mut context.def_interner); } - // We also need to bind the traits generics to the trait's generics on the impl - for (generic, binding) in the_trait.generics.iter().zip(trait_generics) { - generic.bind(binding); + fn type_check_globals(&mut self, interner: &mut NodeInterner) { + for (file_id, global_id) in self.globals.iter() { + for error in TypeChecker::check_global(*global_id, interner) { + self.errors.push((error.into(), *file_id)); + } + } } - // Temporarily take the trait's methods so we can use both them and a mutable reference - // to the interner within the loop. - let trait_methods = std::mem::take(&mut the_trait.methods); - - for (file_id, func_id) in impl_methods { - let func_name = resolver.interner.function_name(func_id).to_owned(); - - // 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(trait_method) = - trait_methods.iter().find(|method| method.name.0.contents == func_name) - { - let impl_method = resolver.interner.function_meta(func_id); - - let impl_method_generic_count = - impl_method.typ.generic_count() - trait_impl_generic_count; - - // We subtract 1 here to account for the implicit generic `Self` type that is on all - // traits (and thus trait methods) but is not required (or allowed) for users to specify. - let the_trait = resolver.interner.get_trait(trait_id); - let trait_method_generic_count = - trait_method.generics().len() - 1 - the_trait.generics.len(); - - if impl_method_generic_count != trait_method_generic_count { - let trait_name = resolver.interner.get_trait(trait_id).name.clone(); - - let error = DefCollectorErrorKind::MismatchGenericCount { - actual_generic_count: impl_method_generic_count, - expected_generic_count: trait_method_generic_count, - origin: format!("{}::{}", trait_name, func_name), - location: "this method", - span: impl_method.location.span, - }; - errors.push((error.into(), *file_id)); + fn type_check_functions(&mut self, interner: &mut NodeInterner) { + for (file, func) in self.functions.iter() { + for error in type_check_func(interner, *func) { + self.errors.push((error.into(), *file)); } + } + } - // This instantiation is technically not needed. We could bind each generic in the - // trait function to the impl's corresponding generic but to do so we'd have to rely - // on the trait function's generics being first in the generic list, since the same - // list also contains the generic `Self` variable, and any generics on the trait itself. - // - // Instantiating the impl method's generics here instead is a bit less precise but - // doesn't rely on any orderings that may be changed. - let impl_function_type = impl_method.typ.instantiate(resolver.interner).0; - - let mut bindings = TypeBindings::new(); - let mut typecheck_errors = Vec::new(); - - if let Type::Function(impl_params, impl_return, _) = impl_function_type.as_monotype() { - if trait_method.arguments().len() != impl_params.len() { - let error = DefCollectorErrorKind::MismatchTraitImplementationNumParameters { - actual_num_parameters: impl_method.parameters.0.len(), - expected_num_parameters: trait_method.arguments().len(), - trait_name: resolver.interner.get_trait(trait_id).name.to_string(), - method_name: func_name.to_string(), - span: impl_method.location.span, - }; - errors.push((error.into(), *file_id)); - } + fn type_check_trait_impl_function(&mut self, interner: &mut NodeInterner) { + for (file, func) in self.trait_impl_functions.iter() { + for error in check_trait_impl_method_matches_declaration(interner, *func) { + self.errors.push((error.into(), *file)); + } + for error in type_check_func(interner, *func) { + self.errors.push((error.into(), *file)); + } + } + } - // 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); + /// Evaluate all `comptime` expressions in this module + fn evaluate_comptime(&mut self, interner: &mut NodeInterner) { + if self.count_errors() == 0 { + let mut scopes = vec![HashMap::default()]; + let mut interpreter = Interpreter::new(interner, &mut scopes); - for (parameter_index, ((expected, actual), (hir_pattern, _, _))) in - args_and_params.enumerate() - { - if expected.try_unify(actual, &mut bindings).is_err() { - typecheck_errors.push(TypeCheckError::TraitMethodParameterTypeMismatch { - method_name: func_name.to_string(), - expected_typ: expected.to_string(), - actual_typ: actual.to_string(), - parameter_span: hir_pattern.span(), - parameter_index: parameter_index + 1, - }); - } + for (_file, global) in &self.globals { + if let Err(error) = interpreter.scan_global(*global) { + self.errors.push(error.into_compilation_error_pair()); } + } - if trait_method.return_type().try_unify(impl_return, &mut bindings).is_err() { - let impl_method = resolver.interner.function_meta(func_id); - let ret_type_span = impl_method.return_type.get_type().span; - let expr_span = ret_type_span.expect("return type must always have a span"); - - let expected_typ = trait_method.return_type().to_string(); - let expr_typ = impl_method.return_type().to_string(); - let error = TypeCheckError::TypeMismatch { expr_typ, expected_typ, expr_span }; - typecheck_errors.push(error); + for (_file, function) in &self.functions { + // The file returned by the error may be different than the file the + // function is in so only use the error's file id. + if let Err(error) = interpreter.scan_function(*function) { + self.errors.push(error.into_compilation_error_pair()); } - } else { - unreachable!( - "impl_function_type is not a function type, it is: {impl_function_type}" - ); } - - errors.extend(typecheck_errors.iter().cloned().map(|e| (e.into(), *file_id))); } } - // Now unbind `Self` and the trait's generics - let the_trait = resolver.interner.get_trait_mut(trait_id); - the_trait.set_methods(trait_methods); - the_trait.self_type_typevar.unbind(the_trait.self_type_typevar_id); + fn resolve_globals( + &mut self, + context: &mut Context, + literal_globals: Vec, + crate_id: CrateId, + ) { + let globals = resolve_globals(context, literal_globals, crate_id); + self.globals.extend(globals.globals); + self.errors.extend(globals.errors); + } - for generic in &the_trait.generics { - generic.unbind(generic.id()); + /// Counts the number of errors (minus warnings) this program currently has + fn count_errors(&self) -> usize { + self.errors.iter().filter(|(error, _)| error.is_error()).count() } } 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 77224cc311c..5c196324b7d 100644 --- a/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs +++ b/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs @@ -1,16 +1,22 @@ use std::{collections::HashMap, path::Path, vec}; -use acvm::acir::acir_field::FieldOptions; +use acvm::{AcirField, FieldElement}; use fm::{FileId, FileManager, FILE_EXTENSION}; use noirc_errors::Location; +use num_bigint::BigUint; +use num_traits::Num; +use crate::ast::{ + FunctionDefinition, Ident, ItemVisibility, LetStatement, ModuleDeclaration, NoirFunction, + NoirStruct, NoirTrait, NoirTraitImpl, NoirTypeAlias, Pattern, TraitImplItem, TraitItem, + TypeImpl, +}; use crate::{ graph::CrateId, hir::def_collector::dc_crate::{UnresolvedStruct, UnresolvedTrait}, + macros_api::MacroProcessor, node_interner::{FunctionModifiers, TraitId, TypeAliasId}, parser::{SortedModule, SortedSubModule}, - FunctionDefinition, Ident, LetStatement, NoirFunction, NoirStruct, NoirTrait, NoirTraitImpl, - NoirTypeAlias, TraitImplItem, TraitItem, TypeImpl, }; use super::{ @@ -41,20 +47,32 @@ pub fn collect_defs( module_id: LocalModuleId, crate_id: CrateId, context: &mut Context, + macro_processors: &[&dyn MacroProcessor], ) -> Vec<(CompilationError, FileId)> { let mut collector = ModCollector { def_collector, file_id, module_id }; let mut errors: Vec<(CompilationError, FileId)> = vec![]; // First resolve the module declarations for decl in ast.module_decls { - errors.extend(collector.parse_module_declaration(context, &decl, crate_id)); + errors.extend(collector.parse_module_declaration( + context, + &decl, + crate_id, + macro_processors, + )); } - errors.extend(collector.collect_submodules(context, crate_id, ast.submodules, file_id)); + errors.extend(collector.collect_submodules( + context, + crate_id, + ast.submodules, + file_id, + macro_processors, + )); // Then add the imports to defCollector to resolve once all modules in the hierarchy have been resolved for import in ast.imports { - collector.def_collector.collected_imports.push(ImportDirective { + collector.def_collector.imports.push(ImportDirective { module_id: collector.module_id, path: import.path, alias: import.alias, @@ -89,8 +107,13 @@ impl<'a> ModCollector<'a> { for global in globals { let name = global.pattern.name_ident().clone(); - let global_id = - context.def_interner.push_empty_global(name.clone(), self.module_id, self.file_id); + let global_id = context.def_interner.push_empty_global( + name.clone(), + self.module_id, + self.file_id, + global.attributes.clone(), + matches!(global.pattern, Pattern::Mutable { .. }), + ); // Add the statement to the scope so its path can be looked up later let result = self.def_collector.def_map.modules[self.module_id.0] @@ -105,7 +128,7 @@ impl<'a> ModCollector<'a> { errors.push((err.into(), self.file_id)); } - self.def_collector.collected_globals.push(UnresolvedGlobal { + self.def_collector.items.globals.push(UnresolvedGlobal { file_id: self.file_id, module_id: self.module_id, global_id, @@ -123,6 +146,7 @@ impl<'a> ModCollector<'a> { file_id: self.file_id, functions: Vec::new(), trait_id: None, + self_type: None, }; for (method, _) in r#impl.methods { @@ -133,7 +157,7 @@ impl<'a> ModCollector<'a> { } let key = (r#impl.object_type, self.module_id); - let methods = self.def_collector.collected_impls.entry(key).or_default(); + let methods = self.def_collector.items.impls.entry(key).or_default(); methods.push((r#impl.generics, r#impl.type_span, unresolved_functions)); } } @@ -166,11 +190,17 @@ impl<'a> ModCollector<'a> { object_type: trait_impl.object_type, generics: trait_impl.impl_generics, where_clause: trait_impl.where_clause, - trait_id: None, // will be filled later trait_generics: trait_impl.trait_generics, + + // These last fields are filled later on + trait_id: None, + impl_id: None, + resolved_object_type: None, + resolved_generics: Vec::new(), + resolved_trait_generics: Vec::new(), }; - self.def_collector.collected_traits_impls.push(unresolved_trait_impl); + self.def_collector.items.trait_impls.push(unresolved_trait_impl); } } @@ -180,8 +210,12 @@ impl<'a> ModCollector<'a> { trait_impl: &NoirTraitImpl, krate: CrateId, ) -> UnresolvedFunctions { - let mut unresolved_functions = - UnresolvedFunctions { file_id: self.file_id, functions: Vec::new(), trait_id: None }; + let mut unresolved_functions = UnresolvedFunctions { + file_id: self.file_id, + functions: Vec::new(), + trait_id: None, + self_type: None, + }; let module = ModuleId { krate, local_id: self.module_id }; @@ -203,8 +237,12 @@ impl<'a> ModCollector<'a> { functions: Vec, krate: CrateId, ) -> Vec<(CompilationError, FileId)> { - let mut unresolved_functions = - UnresolvedFunctions { file_id: self.file_id, functions: Vec::new(), trait_id: None }; + let mut unresolved_functions = UnresolvedFunctions { + file_id: self.file_id, + functions: Vec::new(), + trait_id: None, + self_type: None, + }; let mut errors = vec![]; let module = ModuleId { krate, local_id: self.module_id }; @@ -212,13 +250,14 @@ impl<'a> ModCollector<'a> { for function in functions { // check if optional field attribute is compatible with native field if let Some(field) = function.attributes().get_field_attribute() { - if !FieldOptions::is_native_field(&field) { + if !is_native_field(&field) { continue; } } let name = function.name_ident().clone(); let func_id = context.def_interner.push_empty_fn(); + let visibility = function.def.visibility; // First create dummy function in the DefInterner // So that we can get a FuncId @@ -235,7 +274,7 @@ impl<'a> ModCollector<'a> { // Add function to scope/ns of the module let result = self.def_collector.def_map.modules[self.module_id.0] - .declare_function(name, func_id); + .declare_function(name, visibility, func_id); if let Err((first_def, second_def)) = result { let error = DefCollectorErrorKind::Duplicate { @@ -247,7 +286,7 @@ impl<'a> ModCollector<'a> { } } - self.def_collector.collected_functions.push(unresolved_functions); + self.def_collector.items.functions.push(unresolved_functions); errors } @@ -294,7 +333,7 @@ impl<'a> ModCollector<'a> { } // And store the TypeId -> StructType mapping somewhere it is reachable - self.def_collector.collected_types.insert(id, unresolved); + self.def_collector.items.types.insert(id, unresolved); } definition_errors } @@ -332,7 +371,7 @@ impl<'a> ModCollector<'a> { errors.push((err.into(), self.file_id)); } - self.def_collector.collected_type_aliases.insert(type_alias_id, unresolved); + self.def_collector.items.type_aliases.insert(type_alias_id, unresolved); } errors } @@ -376,6 +415,7 @@ impl<'a> ModCollector<'a> { file_id: self.file_id, functions: Vec::new(), trait_id: None, + self_type: None, }; let mut method_ids = HashMap::new(); @@ -394,12 +434,12 @@ impl<'a> ModCollector<'a> { let modifiers = FunctionModifiers { name: name.to_string(), - visibility: crate::FunctionVisibility::Public, + visibility: ItemVisibility::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, + generic_count: generics.len(), + is_comptime: false, }; let location = Location::new(name.span(), self.file_id); @@ -408,7 +448,7 @@ impl<'a> ModCollector<'a> { .push_function_definition(func_id, modifiers, trait_id.0, location); match self.def_collector.def_map.modules[trait_id.0.local_id.0] - .declare_function(name.clone(), func_id) + .declare_function(name.clone(), ItemVisibility::Public, func_id) { Ok(()) => { if let Some(body) = body { @@ -443,6 +483,8 @@ impl<'a> ModCollector<'a> { name.clone(), trait_id.0.local_id, self.file_id, + vec![], + false, ); if let Err((first_def, second_def)) = self.def_collector.def_map.modules @@ -483,7 +525,8 @@ impl<'a> ModCollector<'a> { method_ids, fns_with_default_impl: unresolved_functions, }; - self.def_collector.collected_traits.insert(trait_id, unresolved); + context.def_interner.push_empty_trait(trait_id, &unresolved); + self.def_collector.items.traits.insert(trait_id, unresolved); } errors } @@ -494,6 +537,7 @@ impl<'a> ModCollector<'a> { crate_id: CrateId, submodules: Vec, file_id: FileId, + macro_processors: &[&dyn MacroProcessor], ) -> Vec<(CompilationError, FileId)> { let mut errors: Vec<(CompilationError, FileId)> = vec![]; for submodule in submodules { @@ -506,6 +550,7 @@ impl<'a> ModCollector<'a> { child, crate_id, context, + macro_processors, )); } Err(error) => { @@ -522,15 +567,16 @@ impl<'a> ModCollector<'a> { fn parse_module_declaration( &mut self, context: &mut Context, - mod_name: &Ident, + mod_decl: &ModuleDeclaration, crate_id: CrateId, + macro_processors: &[&dyn MacroProcessor], ) -> Vec<(CompilationError, FileId)> { let mut errors: Vec<(CompilationError, FileId)> = vec![]; let child_file_id = - match find_module(&context.file_manager, self.file_id, &mod_name.0.contents) { + match find_module(&context.file_manager, self.file_id, &mod_decl.ident.0.contents) { Ok(child_file_id) => child_file_id, Err(expected_path) => { - let mod_name = mod_name.clone(); + let mod_name = mod_decl.ident.clone(); let err = DefCollectorErrorKind::UnresolvedModuleDecl { mod_name, expected_path }; errors.push((err.into(), self.file_id)); @@ -538,17 +584,17 @@ impl<'a> ModCollector<'a> { } }; - let location = Location { file: self.file_id, span: mod_name.span() }; + let location = Location { file: self.file_id, span: mod_decl.ident.span() }; if let Some(old_location) = context.visited_files.get(&child_file_id) { let error = DefCollectorErrorKind::ModuleAlreadyPartOfCrate { - mod_name: mod_name.clone(), + mod_name: mod_decl.ident.clone(), span: location.span, }; errors.push((error.into(), location.file)); let error = DefCollectorErrorKind::ModuleOriginallyDefined { - mod_name: mod_name.clone(), + mod_name: mod_decl.ident.clone(), span: old_location.span, }; errors.push((error.into(), old_location.file)); @@ -559,14 +605,31 @@ impl<'a> ModCollector<'a> { // Parse the AST for the module we just found and then recursively look for it's defs let (ast, parsing_errors) = context.parsed_file_results(child_file_id); - let ast = ast.into_sorted(); + let mut ast = ast.into_sorted(); + + for macro_processor in macro_processors { + match macro_processor.process_untyped_ast( + ast.clone(), + &crate_id, + child_file_id, + context, + ) { + Ok(processed_ast) => { + ast = processed_ast; + } + Err((error, file_id)) => { + let def_error = DefCollectorErrorKind::MacroError(error); + errors.push((def_error.into(), file_id)); + } + } + } errors.extend( parsing_errors.iter().map(|e| (e.clone().into(), child_file_id)).collect::>(), ); // Add module into def collector and get a ModuleId - match self.push_child_module(mod_name, child_file_id, true, false) { + match self.push_child_module(&mod_decl.ident, child_file_id, true, false) { Ok(child_mod_id) => { errors.extend(collect_defs( self.def_collector, @@ -575,6 +638,7 @@ impl<'a> ModCollector<'a> { child_mod_id, crate_id, context, + macro_processors, )); } Err(error) => { @@ -676,6 +740,27 @@ fn should_check_siblings_for_module(module_path: &Path, parent_path: &Path) -> b } } +cfg_if::cfg_if! { + if #[cfg(feature = "bls12_381")] { + pub const CHOSEN_FIELD: &str = "bls12_381"; + } else { + pub const CHOSEN_FIELD: &str = "bn254"; + } +} + +fn is_native_field(str: &str) -> bool { + let big_num = if let Some(hex) = str.strip_prefix("0x") { + BigUint::from_str_radix(hex, 16) + } else { + BigUint::from_str_radix(str, 10) + }; + if let Ok(big_num) = big_num { + big_num == FieldElement::modulus() + } else { + CHOSEN_FIELD == str + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/compiler/noirc_frontend/src/hir/def_collector/errors.rs b/compiler/noirc_frontend/src/hir/def_collector/errors.rs index de45be48c4e..edeb463e10d 100644 --- a/compiler/noirc_frontend/src/hir/def_collector/errors.rs +++ b/compiler/noirc_frontend/src/hir/def_collector/errors.rs @@ -1,6 +1,5 @@ +use crate::ast::{Ident, Path}; use crate::hir::resolution::import::PathResolutionError; -use crate::Ident; -use crate::Path; use noirc_errors::CustomDiagnostic as Diagnostic; use noirc_errors::FileDiagnostic; @@ -41,14 +40,6 @@ pub enum DefCollectorErrorKind { OverlappingImplNote { span: Span }, #[error("Cannot `impl` a type defined outside the current crate")] ForeignImpl { span: Span, type_name: String }, - #[error("Mismatched number of parameters in trait implementation")] - MismatchTraitImplementationNumParameters { - actual_num_parameters: usize, - expected_num_parameters: usize, - trait_name: String, - method_name: String, - span: Span, - }, #[error("Mismatched number of generics in {location}")] MismatchGenericCount { actual_generic_count: usize, @@ -86,7 +77,7 @@ pub struct MacroError { } impl DefCollectorErrorKind { - pub fn into_file_diagnostic(self, file: fm::FileId) -> FileDiagnostic { + pub fn into_file_diagnostic(&self, file: fm::FileId) -> FileDiagnostic { Diagnostic::from(self).in_file(file) } } @@ -108,8 +99,8 @@ impl fmt::Display for DuplicateType { } } -impl From for Diagnostic { - fn from(error: DefCollectorErrorKind) -> Diagnostic { +impl<'a> From<&'a DefCollectorErrorKind> for Diagnostic { + fn from(error: &'a DefCollectorErrorKind) -> Diagnostic { match error { DefCollectorErrorKind::Duplicate { typ, first_def, second_def } => { let primary_message = format!( @@ -142,18 +133,18 @@ impl From for Diagnostic { DefCollectorErrorKind::NonStructTypeInImpl { span } => Diagnostic::simple_error( "Non-struct type used in impl".into(), "Only struct types may have implementation methods".into(), - span, + *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, + *span, ), DefCollectorErrorKind::OverlappingImpl { span, typ } => { Diagnostic::simple_error( format!("Impl for type `{typ}` overlaps with existing impl"), "Overlapping impl".into(), - span, + *span, ) } DefCollectorErrorKind::OverlappingImplNote { span } => { @@ -163,31 +154,19 @@ impl From for Diagnostic { Diagnostic::simple_error( "Previous impl defined here".into(), "Previous impl defined here".into(), - span, + *span, ) } DefCollectorErrorKind::ForeignImpl { span, type_name } => Diagnostic::simple_error( "Cannot `impl` a type that was defined outside the current crate".into(), format!("{type_name} was defined outside the current crate"), - span, + *span, ), DefCollectorErrorKind::TraitNotFound { trait_path } => Diagnostic::simple_error( format!("Trait {trait_path} not found"), "".to_string(), trait_path.span(), ), - DefCollectorErrorKind::MismatchTraitImplementationNumParameters { - expected_num_parameters, - actual_num_parameters, - trait_name, - method_name, - span, - } => { - let plural = if expected_num_parameters == 1 { "" } else { "s" }; - let primary_message = format!( - "`{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::MismatchGenericCount { actual_generic_count, expected_generic_count, @@ -195,15 +174,15 @@ impl From for Diagnostic { origin, span, } => { - let plural = if expected_generic_count == 1 { "" } else { "s" }; + let plural = if *expected_generic_count == 1 { "" } else { "s" }; let primary_message = format!( "`{origin}` expects {expected_generic_count} generic{plural}, but {location} has {actual_generic_count}"); - Diagnostic::simple_error(primary_message, "".to_string(), span) + Diagnostic::simple_error(primary_message, "".to_string(), *span) } DefCollectorErrorKind::MethodNotInTrait { trait_name, impl_method } => { - let trait_name = trait_name.0.contents; + let trait_name = &trait_name.0.contents; let impl_method_span = impl_method.span(); - let impl_method_name = impl_method.0.contents; + let impl_method_name = &impl_method.0.contents; let primary_message = format!("Method with name `{impl_method_name}` is not part of trait `{trait_name}`, therefore it can't be implemented"); Diagnostic::simple_error(primary_message, "".to_owned(), impl_method_span) } @@ -212,15 +191,15 @@ impl From for Diagnostic { method_name, trait_impl_span, } => { - let trait_name = trait_name.0.contents; - let impl_method_name = method_name.0.contents; + let trait_name = &trait_name.0.contents; + let impl_method_name = &method_name.0.contents; let primary_message = format!( "Method `{impl_method_name}` from trait `{trait_name}` is not implemented" ); Diagnostic::simple_error( primary_message, format!("Please implement {impl_method_name} here"), - trait_impl_span, + *trait_impl_span, ) } DefCollectorErrorKind::NotATrait { not_a_trait_name } => { @@ -234,20 +213,20 @@ impl From for Diagnostic { DefCollectorErrorKind::ModuleAlreadyPartOfCrate { mod_name, span } => { let message = format!("Module '{mod_name}' is already part of the crate"); let secondary = String::new(); - Diagnostic::simple_error(message, secondary, span) + Diagnostic::simple_error(message, secondary, *span) } DefCollectorErrorKind::ModuleOriginallyDefined { mod_name, span } => { let message = format!("Note: {mod_name} was originally declared here"); let secondary = String::new(); - Diagnostic::simple_error(message, secondary, span) + Diagnostic::simple_error(message, secondary, *span) } 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, + *span, ), DefCollectorErrorKind::MacroError(macro_error) => { - Diagnostic::simple_error(macro_error.primary_message, macro_error.secondary_message.unwrap_or_default(), macro_error.span.unwrap_or_default()) + Diagnostic::simple_error(macro_error.primary_message.clone(), macro_error.secondary_message.clone().unwrap_or_default(), macro_error.span.unwrap_or_default()) }, } } diff --git a/compiler/noirc_frontend/src/hir/def_map/item_scope.rs b/compiler/noirc_frontend/src/hir/def_map/item_scope.rs index 523def89518..3ca89e56bbc 100644 --- a/compiler/noirc_frontend/src/hir/def_map/item_scope.rs +++ b/compiler/noirc_frontend/src/hir/def_map/item_scope.rs @@ -1,16 +1,10 @@ use super::{namespace::PerNs, ModuleDefId, ModuleId}; -use crate::{ - node_interner::{FuncId, TraitId}, - Ident, -}; -use std::collections::{hash_map::Entry, HashMap}; +use crate::ast::{Ident, ItemVisibility}; +use crate::node_interner::{FuncId, TraitId}; -type Scope = HashMap, (ModuleDefId, Visibility, bool /*is_prelude*/)>; +use std::collections::{hash_map::Entry, HashMap}; -#[derive(Debug, PartialEq, Eq, Copy, Clone)] -pub enum Visibility { - Public, -} +type Scope = HashMap, (ModuleDefId, ItemVisibility, bool /*is_prelude*/)>; #[derive(Default, Debug, PartialEq, Eq)] pub struct ItemScope { @@ -24,10 +18,11 @@ impl ItemScope { pub fn add_definition( &mut self, name: Ident, + visibility: ItemVisibility, mod_def: ModuleDefId, trait_id: Option, ) -> Result<(), (Ident, Ident)> { - self.add_item_to_namespace(name, mod_def, trait_id, false)?; + self.add_item_to_namespace(name, visibility, mod_def, trait_id, false)?; self.defs.push(mod_def); Ok(()) } @@ -38,6 +33,7 @@ impl ItemScope { pub fn add_item_to_namespace( &mut self, name: Ident, + visibility: ItemVisibility, mod_def: ModuleDefId, trait_id: Option, is_prelude: bool, @@ -46,6 +42,11 @@ impl ItemScope { if let Entry::Occupied(mut o) = map.entry(name.clone()) { let trait_hashmap = o.get_mut(); if let Entry::Occupied(mut n) = trait_hashmap.entry(trait_id) { + // Generally we want to reject having two of the same ident in the same namespace. + // The exception to this is when we're explicitly importing something + // which exists in the Noir stdlib prelude. + // + // In this case we ignore the prelude and favour the explicit import. let is_prelude = std::mem::replace(&mut n.get_mut().2, is_prelude); let old_ident = o.key(); @@ -55,12 +56,12 @@ impl ItemScope { Err((old_ident.clone(), name)) } } else { - trait_hashmap.insert(trait_id, (mod_def, Visibility::Public, is_prelude)); + trait_hashmap.insert(trait_id, (mod_def, visibility, is_prelude)); Ok(()) } } else { let mut trait_hashmap = HashMap::new(); - trait_hashmap.insert(trait_id, (mod_def, Visibility::Public, is_prelude)); + trait_hashmap.insert(trait_id, (mod_def, visibility, is_prelude)); map.insert(name, trait_hashmap); Ok(()) } diff --git a/compiler/noirc_frontend/src/hir/def_map/mod.rs b/compiler/noirc_frontend/src/hir/def_map/mod.rs index 8721bdb6c3c..19e06387d43 100644 --- a/compiler/noirc_frontend/src/hir/def_map/mod.rs +++ b/compiler/noirc_frontend/src/hir/def_map/mod.rs @@ -2,13 +2,13 @@ use crate::graph::CrateId; use crate::hir::def_collector::dc_crate::{CompilationError, DefCollector}; use crate::hir::Context; use crate::macros_api::MacroProcessor; -use crate::node_interner::{FuncId, NodeInterner, StructId}; +use crate::node_interner::{FuncId, GlobalId, NodeInterner, StructId}; use crate::parser::{parse_program, ParsedModule, ParserError}; use crate::token::{FunctionAttribute, SecondaryAttribute, TestScope}; -use arena::{Arena, Index}; use fm::{FileId, FileManager}; +use noirc_arena::{Arena, Index}; use noirc_errors::Location; -use std::collections::BTreeMap; +use std::collections::{BTreeMap, HashMap}; mod module_def; pub use module_def::*; mod item_scope; @@ -73,7 +73,8 @@ impl CrateDefMap { pub fn collect_defs( crate_id: CrateId, context: &mut Context, - macro_processors: Vec<&dyn MacroProcessor>, + use_elaborator: bool, + macro_processors: &[&dyn MacroProcessor], ) -> Vec<(CompilationError, FileId)> { // Check if this Crate has already been compiled // XXX: There is probably a better alternative for this. @@ -90,8 +91,9 @@ impl CrateDefMap { let (ast, parsing_errors) = context.parsed_file_results(root_file_id); let mut ast = ast.into_sorted(); - for macro_processor in ¯o_processors { - match macro_processor.process_untyped_ast(ast.clone(), &crate_id, context) { + for macro_processor in macro_processors { + match macro_processor.process_untyped_ast(ast.clone(), &crate_id, root_file_id, context) + { Ok(processed_ast) => { ast = processed_ast; } @@ -120,7 +122,8 @@ impl CrateDefMap { context, ast, root_file_id, - macro_processors.clone(), + use_elaborator, + macro_processors, )); errors.extend( @@ -222,20 +225,37 @@ impl CrateDefMap { }) .collect(); - let events = module - .type_definitions() - .filter_map(|id| { - id.as_type().filter(|struct_id| { - interner - .struct_attributes(struct_id) - .iter() - .any(|attr| attr == &SecondaryAttribute::Event) - }) - }) - .collect(); + let mut outputs = + ContractOutputs { structs: HashMap::new(), globals: HashMap::new() }; + + interner.get_all_globals().iter().for_each(|global_info| { + interner.global_attributes(&global_info.id).iter().for_each(|attr| { + if let SecondaryAttribute::Abi(tag) = attr { + if let Some(tagged) = outputs.globals.get_mut(tag) { + tagged.push(global_info.id); + } else { + outputs.globals.insert(tag.to_string(), vec![global_info.id]); + } + } + }); + }); + + module.type_definitions().for_each(|id| { + if let ModuleDefId::TypeId(struct_id) = id { + interner.struct_attributes(&struct_id).iter().for_each(|attr| { + if let SecondaryAttribute::Abi(tag) = attr { + if let Some(tagged) = outputs.structs.get_mut(tag) { + tagged.push(struct_id); + } else { + outputs.structs.insert(tag.to_string(), vec![struct_id]); + } + } + }); + } + }); let name = self.get_module_path(id, module.parent); - Some(Contract { name, location: module.location, functions, events }) + Some(Contract { name, location: module.location, functions, outputs }) } else { None } @@ -288,6 +308,11 @@ pub struct ContractFunctionMeta { pub is_entry_point: bool, } +pub struct ContractOutputs { + pub structs: HashMap>, + pub globals: HashMap>, +} + /// A 'contract' in Noir source code with a given name, functions and events. /// This is not an AST node, it is just a convenient form to return for CrateDefMap::get_all_contracts. pub struct Contract { @@ -295,7 +320,7 @@ pub struct Contract { pub name: String, pub location: Location, pub functions: Vec, - pub events: Vec, + pub outputs: ContractOutputs, } /// Given a FileId, fetch the File, from the FileManager and parse it's content diff --git a/compiler/noirc_frontend/src/hir/def_map/module_data.rs b/compiler/noirc_frontend/src/hir/def_map/module_data.rs index 309618dd011..488ccc476d7 100644 --- a/compiler/noirc_frontend/src/hir/def_map/module_data.rs +++ b/compiler/noirc_frontend/src/hir/def_map/module_data.rs @@ -2,12 +2,9 @@ use std::collections::HashMap; use noirc_errors::Location; -use crate::{ - node_interner::{FuncId, GlobalId, StructId, TraitId, TypeAliasId}, - Ident, -}; - use super::{ItemScope, LocalModuleId, ModuleDefId, ModuleId, PerNs}; +use crate::ast::{Ident, ItemVisibility}; +use crate::node_interner::{FuncId, GlobalId, StructId, TraitId, TypeAliasId}; /// Contains the actual contents of a module: its parent (if one exists), /// children, and scope with all definitions defined within the scope. @@ -48,18 +45,24 @@ impl ModuleData { fn declare( &mut self, name: Ident, + visibility: ItemVisibility, item_id: ModuleDefId, trait_id: Option, ) -> Result<(), (Ident, Ident)> { - self.scope.add_definition(name.clone(), item_id, trait_id)?; + self.scope.add_definition(name.clone(), visibility, item_id, trait_id)?; // definitions is a subset of self.scope so it is expected if self.scope.define_func_def // returns without error, so will self.definitions.define_func_def. - self.definitions.add_definition(name, item_id, trait_id) + self.definitions.add_definition(name, visibility, item_id, trait_id) } - pub fn declare_function(&mut self, name: Ident, id: FuncId) -> Result<(), (Ident, Ident)> { - self.declare(name, id.into(), None) + pub fn declare_function( + &mut self, + name: Ident, + visibility: ItemVisibility, + id: FuncId, + ) -> Result<(), (Ident, Ident)> { + self.declare(name, visibility, id.into(), None) } pub fn declare_trait_function( @@ -68,7 +71,7 @@ impl ModuleData { id: FuncId, trait_id: TraitId, ) -> Result<(), (Ident, Ident)> { - self.declare(name, id.into(), Some(trait_id)) + self.declare(name, ItemVisibility::Public, id.into(), Some(trait_id)) } pub fn remove_function(&mut self, name: &Ident) { @@ -77,11 +80,11 @@ impl ModuleData { } pub fn declare_global(&mut self, name: Ident, id: GlobalId) -> Result<(), (Ident, Ident)> { - self.declare(name, id.into(), None) + self.declare(name, ItemVisibility::Public, id.into(), None) } pub fn declare_struct(&mut self, name: Ident, id: StructId) -> Result<(), (Ident, Ident)> { - self.declare(name, ModuleDefId::TypeId(id), None) + self.declare(name, ItemVisibility::Public, ModuleDefId::TypeId(id), None) } pub fn declare_type_alias( @@ -89,11 +92,11 @@ impl ModuleData { name: Ident, id: TypeAliasId, ) -> Result<(), (Ident, Ident)> { - self.declare(name, id.into(), None) + self.declare(name, ItemVisibility::Public, id.into(), None) } pub fn declare_trait(&mut self, name: Ident, id: TraitId) -> Result<(), (Ident, Ident)> { - self.declare(name, ModuleDefId::TraitId(id), None) + self.declare(name, ItemVisibility::Public, ModuleDefId::TraitId(id), None) } pub fn declare_child_module( @@ -101,7 +104,7 @@ impl ModuleData { name: Ident, child_id: ModuleId, ) -> Result<(), (Ident, Ident)> { - self.declare(name, child_id.into(), None) + self.declare(name, ItemVisibility::Public, child_id.into(), None) } pub fn find_func_with_name(&self, name: &Ident) -> Option { @@ -114,7 +117,7 @@ impl ModuleData { id: ModuleDefId, is_prelude: bool, ) -> Result<(), (Ident, Ident)> { - self.scope.add_item_to_namespace(name, id, None, is_prelude) + self.scope.add_item_to_namespace(name, ItemVisibility::Public, id, None, is_prelude) } pub fn find_name(&self, name: &Ident) -> PerNs { diff --git a/compiler/noirc_frontend/src/hir/def_map/namespace.rs b/compiler/noirc_frontend/src/hir/def_map/namespace.rs index ca14d9f8617..6fac6d2b991 100644 --- a/compiler/noirc_frontend/src/hir/def_map/namespace.rs +++ b/compiler/noirc_frontend/src/hir/def_map/namespace.rs @@ -1,15 +1,16 @@ -use super::{item_scope::Visibility, ModuleDefId}; +use super::ModuleDefId; +use crate::ast::ItemVisibility; // This works exactly the same as in r-a, just simplified #[derive(Debug, PartialEq, Eq, Copy, Clone)] pub struct PerNs { - pub types: Option<(ModuleDefId, Visibility, bool)>, - pub values: Option<(ModuleDefId, Visibility, bool)>, + pub types: Option<(ModuleDefId, ItemVisibility, bool)>, + pub values: Option<(ModuleDefId, ItemVisibility, bool)>, } impl PerNs { pub fn types(t: ModuleDefId) -> PerNs { - PerNs { types: Some((t, Visibility::Public, false)), values: None } + PerNs { types: Some((t, ItemVisibility::Public, false)), values: None } } pub fn take_types(self) -> Option { @@ -24,7 +25,7 @@ impl PerNs { self.types.map(|it| it.0).into_iter().chain(self.values.map(|it| it.0)) } - pub fn iter_items(self) -> impl Iterator { + pub fn iter_items(self) -> impl Iterator { self.types.into_iter().chain(self.values) } diff --git a/compiler/noirc_frontend/src/hir/mod.rs b/compiler/noirc_frontend/src/hir/mod.rs index 00bcb0cdebf..55dc22d6c5d 100644 --- a/compiler/noirc_frontend/src/hir/mod.rs +++ b/compiler/noirc_frontend/src/hir/mod.rs @@ -1,3 +1,4 @@ +pub mod comptime; pub mod def_collector; pub mod def_map; pub mod resolution; @@ -26,7 +27,7 @@ pub type ParsedFiles = HashMap)>; pub struct Context<'file_manager, 'parsed_files> { pub def_interner: NodeInterner, pub crate_graph: CrateGraph, - pub(crate) def_maps: BTreeMap, + pub def_maps: BTreeMap, // In the WASM context, we take ownership of the file manager, // which is why this needs to be a Cow. In all use-cases, the file manager // is read-only however, once it has been passed to the Context. @@ -157,7 +158,8 @@ impl Context<'_, '_> { } } - /// Recursively walks down the crate dependency graph from crate_id until we reach requested crate + /// Tries to find the requested crate in the current one's dependencies, + /// otherwise walks down the crate dependency graph from crate_id until we reach it. /// 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. @@ -167,16 +169,26 @@ impl Context<'_, '_> { 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 + self.crate_graph[crate_id] + .dependencies + .iter() + .find_map(|dep| { + if &dep.crate_id == target_crate_id { + Some(vec![dep.name.to_string()]) + } else { + None + } + }) + .or_else(|| { + self.crate_graph[crate_id].dependencies.iter().find_map(|dep| { + if let Some(mut path) = self.find_dependencies(&dep.crate_id, target_crate_id) { + path.insert(0, dep.name.to_string()); + Some(path) + } else { + None + } + }) + }) } pub fn function_meta(&self, func_id: &FuncId) -> &FuncMeta { @@ -241,7 +253,7 @@ impl Context<'_, '_> { .get_all_contracts(&self.def_interner) } - fn module(&self, module_id: def_map::ModuleId) -> &def_map::ModuleData { + pub fn module(&self, module_id: def_map::ModuleId) -> &def_map::ModuleData { module_id.module(&self.def_maps) } } diff --git a/compiler/noirc_frontend/src/hir/resolution/errors.rs b/compiler/noirc_frontend/src/hir/resolution/errors.rs index d2fe67da38c..d6dd1c2cd54 100644 --- a/compiler/noirc_frontend/src/hir/resolution/errors.rs +++ b/compiler/noirc_frontend/src/hir/resolution/errors.rs @@ -2,7 +2,7 @@ pub use noirc_errors::Span; use noirc_errors::{CustomDiagnostic as Diagnostic, FileDiagnostic}; use thiserror::Error; -use crate::{parser::ParserError, Ident, Type}; +use crate::{ast::Ident, hir::comptime::InterpreterError, parser::ParserError, Type}; use super::import::PathResolutionError; @@ -25,7 +25,7 @@ pub enum ResolverError { #[error("path is not an identifier")] PathIsNotIdent { span: Span }, #[error("could not resolve path")] - PathResolutionError(PathResolutionError), + PathResolutionError(#[from] PathResolutionError), #[error("Expected")] Expected { span: Span, expected: String, got: String }, #[error("Duplicate field in constructor")] @@ -49,7 +49,7 @@ pub enum ResolverError { #[error("Integer too large to be evaluated in an array length context")] IntegerTooLarge { span: Span }, #[error("No global or generic type parameter found with the given name")] - NoSuchNumericTypeVariable { path: crate::Path }, + NoSuchNumericTypeVariable { path: crate::ast::Path }, #[error("Closures cannot capture mutable variables")] CapturedMutableVariable { span: Span }, #[error("Test functions are not allowed to have any parameters")] @@ -64,53 +64,65 @@ pub enum ResolverError { IncorrectGenericCount { span: Span, item_name: String, actual: usize, expected: usize }, #[error("{0}")] ParserError(Box), - #[error("Function is not defined in a contract yet sets its contract visibility")] - ContractFunctionTypeInNormalFunction { span: Span }, #[error("Cannot create a mutable reference to {variable}, it was declared to be immutable")] MutableReferenceToImmutableVariable { variable: String, span: Span }, #[error("Mutable references to array indices are unsupported")] MutableReferenceToArrayElement { span: Span }, - #[error("Function is not defined in a contract yet sets is_internal")] - ContractFunctionInternalInNormalFunction { span: Span }, #[error("Numeric constants should be printed without formatting braces")] NumericConstantInFormatString { name: String, span: Span }, #[error("Closure environment must be a tuple or unit type")] InvalidClosureEnvironment { typ: Type, span: Span }, - #[error("{name} is private and not visible from the current module")] - PrivateFunctionCalled { name: String, span: Span }, - #[error("{name} is not visible from the current crate")] - NonCrateFunctionCalled { name: String, span: Span }, - #[error("Only sized types may be used in the entry point to a program")] - InvalidTypeForEntryPoint { span: Span }, #[error("Nested slices are not supported")] NestedSlices { span: Span }, #[error("#[recursive] attribute is only allowed on entry points to a program")] MisplacedRecursiveAttribute { ident: Ident }, + #[error("#[abi(tag)] attribute is only allowed in contracts")] + AbiAttributeOutsideContract { span: Span }, #[error("Usage of the `#[foreign]` or `#[builtin]` function attributes are not allowed outside of the Noir standard library")] LowLevelFunctionOutsideOfStdlib { ident: Ident }, + #[error( + "Usage of the `#[oracle]` function attribute is only valid on unconstrained functions" + )] + OracleMarkedAsConstrained { ident: Ident }, + #[error("Oracle functions cannot be called directly from constrained functions")] + UnconstrainedOracleReturnToConstrained { span: Span }, #[error("Dependency cycle found, '{item}' recursively depends on itself: {cycle} ")] DependencyCycle { span: Span, item: String, cycle: String }, + #[error("break/continue are only allowed in unconstrained functions")] + JumpInConstrainedFn { is_break: bool, span: Span }, + #[error("break/continue are only allowed within loops")] + JumpOutsideLoop { is_break: bool, span: Span }, + #[error("Only `comptime` globals can be mutable")] + MutableGlobal { span: Span }, + #[error("Self-referential structs are not supported")] + SelfReferentialStruct { span: Span }, + #[error("#[no_predicates] attribute is only allowed on constrained functions")] + NoPredicatesAttributeOnUnconstrained { ident: Ident }, + #[error("#[fold] attribute is only allowed on constrained functions")] + FoldAttributeOnUnconstrained { ident: Ident }, + #[error("Invalid array length construction")] + ArrayLengthInterpreter { error: InterpreterError }, } impl ResolverError { - pub fn into_file_diagnostic(self, file: fm::FileId) -> FileDiagnostic { + pub fn into_file_diagnostic(&self, file: fm::FileId) -> FileDiagnostic { Diagnostic::from(self).in_file(file) } } -impl From for Diagnostic { +impl<'a> From<&'a ResolverError> for Diagnostic { /// Only user errors can be transformed into a Diagnostic /// ICEs will make the compiler panic, as they could affect the /// soundness of the generated program - fn from(error: ResolverError) -> Diagnostic { + fn from(error: &'a ResolverError) -> Diagnostic { match error { ResolverError::DuplicateDefinition { name, first_span, second_span } => { let mut diag = Diagnostic::simple_error( format!("duplicate definitions of {name} found"), "first definition found here".to_string(), - first_span, + *first_span, ); - diag.add_secondary("second definition found here".to_string(), second_span); + diag.add_secondary("second definition found here".to_string(), *second_span); diag } ResolverError::UnusedVariable { ident } => { @@ -125,18 +137,18 @@ impl From for Diagnostic { ResolverError::VariableNotDeclared { name, span } => Diagnostic::simple_error( format!("cannot find `{name}` in this scope "), "not found in this scope".to_string(), - span, + *span, ), ResolverError::PathIsNotIdent { span } => Diagnostic::simple_error( "cannot use path as an identifier".to_string(), String::new(), - span, + *span, ), ResolverError::PathResolutionError(error) => error.into(), ResolverError::Expected { span, expected, got } => Diagnostic::simple_error( format!("expected {expected} got {got}"), String::new(), - span, + *span, ), ResolverError::DuplicateField { field } => Diagnostic::simple_error( format!("duplicate field {field}"), @@ -150,7 +162,7 @@ impl From for Diagnostic { field.span(), ) } - ResolverError::MissingFields { span, mut missing_fields, struct_definition } => { + ResolverError::MissingFields { span, missing_fields, struct_definition } => { let plural = if missing_fields.len() != 1 { "s" } else { "" }; let remaining_fields_names = match &missing_fields[..] { [field1] => field1.clone(), @@ -161,7 +173,7 @@ impl From for Diagnostic { let len_plural = if len != 1 {"s"} else {""}; let truncated_fields = format!(" and {len} other field{len_plural}"); - missing_fields.truncate(3); + let missing_fields = &missing_fields[0..3]; format!("{}{truncated_fields}", missing_fields.join(", ")) } }; @@ -169,18 +181,18 @@ impl From for Diagnostic { Diagnostic::simple_error( format!("missing field{plural} {remaining_fields_names} in struct {struct_definition}"), String::new(), - span, + *span, ) } ResolverError::UnnecessaryMut { first_mut, second_mut } => { let mut error = Diagnostic::simple_error( "'mut' here is not necessary".to_owned(), "".to_owned(), - second_mut, + *second_mut, ); error.add_secondary( "Pattern was already made mutable from this 'mut'".to_owned(), - first_mut, + *first_mut, ); error } @@ -225,17 +237,17 @@ impl From for Diagnostic { "no expression specifying the value stored by the constant variable {name}" ), "expected expression to be stored for let statement".to_string(), - span, + *span, ), ResolverError::InvalidArrayLengthExpr { span } => Diagnostic::simple_error( "Expression invalid in an array-length context".into(), "Array-length expressions can only have simple integer operations and any variables used must be global constants".into(), - span, + *span, ), ResolverError::IntegerTooLarge { span } => Diagnostic::simple_error( "Integer too large to be evaluated to an array-length".into(), "Array-lengths may be a maximum size of usize::MAX, including intermediate calculations".into(), - span, + *span, ), ResolverError::NoSuchNumericTypeVariable { path } => Diagnostic::simple_error( format!("Cannot find a global or generic type parameter named `{path}`"), @@ -245,77 +257,57 @@ impl From for Diagnostic { ResolverError::CapturedMutableVariable { span } => Diagnostic::simple_error( "Closures cannot capture mutable variables".into(), "Mutable variable".into(), - span, + *span, ), ResolverError::TestFunctionHasParameters { span } => Diagnostic::simple_error( "Test functions cannot have any parameters".into(), "Try removing the parameters or moving the test into a wrapper function".into(), - span, + *span, ), ResolverError::NonStructUsedInConstructor { typ, span } => Diagnostic::simple_error( "Only struct types can be used in constructor expressions".into(), format!("{typ} has no fields to construct it with"), - span, + *span, ), ResolverError::NonStructWithGenerics { span } => Diagnostic::simple_error( "Only struct types can have generic arguments".into(), "Try removing the generic arguments".into(), - span, + *span, ), ResolverError::GenericsOnSelfType { span } => Diagnostic::simple_error( "Cannot apply generics to Self type".into(), "Use an explicit type name or apply the generics at the start of the impl instead".into(), - span, + *span, ), ResolverError::IncorrectGenericCount { span, item_name, actual, expected } => { - let expected_plural = if expected == 1 { "" } else { "s" }; - let actual_plural = if actual == 1 { "is" } else { "are" }; + let expected_plural = if *expected == 1 { "" } else { "s" }; + let actual_plural = if *actual == 1 { "is" } else { "are" }; Diagnostic::simple_error( format!("`{item_name}` has {expected} generic argument{expected_plural} but {actual} {actual_plural} given here"), "Incorrect number of generic arguments".into(), - span, + *span, ) } - ResolverError::ParserError(error) => (*error).into(), - ResolverError::ContractFunctionTypeInNormalFunction { span } => Diagnostic::simple_error( - "Only functions defined within contracts can set their contract function type".into(), - "Non-contract functions cannot be 'open'".into(), - span, - ), + ResolverError::ParserError(error) => error.as_ref().into(), ResolverError::MutableReferenceToImmutableVariable { variable, span } => { - Diagnostic::simple_error(format!("Cannot mutably reference the immutable variable {variable}"), format!("{variable} is immutable"), span) + Diagnostic::simple_error(format!("Cannot mutably reference the immutable variable {variable}"), format!("{variable} is immutable"), *span) }, ResolverError::MutableReferenceToArrayElement { span } => { - Diagnostic::simple_error("Mutable references to array elements are currently unsupported".into(), "Try storing the element in a fresh variable first".into(), span) + Diagnostic::simple_error("Mutable references to array elements are currently unsupported".into(), "Try storing the element in a fresh variable first".into(), *span) }, - ResolverError::ContractFunctionInternalInNormalFunction { span } => Diagnostic::simple_error( - "Only functions defined within contracts can set their functions to be internal".into(), - "Non-contract functions cannot be 'internal'".into(), - span, - ), ResolverError::NumericConstantInFormatString { name, span } => Diagnostic::simple_error( format!("cannot find `{name}` in this scope "), "Numeric constants should be printed without formatting braces".to_string(), - span, + *span, ), ResolverError::InvalidClosureEnvironment { span, typ } => Diagnostic::simple_error( format!("{typ} is not a valid closure environment type"), - "Closure environment must be a tuple or unit type".to_string(), span), - // This will be upgraded to an error in future versions - ResolverError::PrivateFunctionCalled { span, name } => Diagnostic::simple_warning( - format!("{name} is private and not visible from the current module"), - format!("{name} is private"), span), - ResolverError::NonCrateFunctionCalled { span, name } => Diagnostic::simple_warning( - format!("{name} is not visible from the current crate"), - format!("{name} is only visible within its crate"), span), - ResolverError::InvalidTypeForEntryPoint { span } => Diagnostic::simple_error( - "Only sized types may be used in the entry point to a program".to_string(), - "Slices, references, or any type containing them may not be used in main or a contract function".to_string(), span), + "Closure environment must be a tuple or unit type".to_string(), *span), ResolverError::NestedSlices { span } => Diagnostic::simple_error( "Nested slices are not supported".into(), "Try to use a constant sized array instead".into(), - span, + *span, ), ResolverError::MisplacedRecursiveAttribute { ident } => { let name = &ident.0.contents; @@ -329,18 +321,90 @@ impl From for Diagnostic { diag.add_note("The `#[recursive]` attribute specifies to the backend whether it should use a prover which generates proofs that are friendly for recursive verification in another circuit".to_owned()); diag } + ResolverError::AbiAttributeOutsideContract { span } => { + Diagnostic::simple_error( + "#[abi(tag)] attributes can only be used in contracts".to_string(), + "misplaced #[abi(tag)] attribute".to_string(), + *span, + ) + }, ResolverError::LowLevelFunctionOutsideOfStdlib { ident } => Diagnostic::simple_error( "Definition of low-level function outside of standard library".into(), "Usage of the `#[foreign]` or `#[builtin]` function attributes are not allowed outside of the Noir standard library".into(), ident.span(), ), + ResolverError::OracleMarkedAsConstrained { ident } => Diagnostic::simple_error( + error.to_string(), + "Oracle functions must have the `unconstrained` keyword applied".into(), + ident.span(), + ), + ResolverError::UnconstrainedOracleReturnToConstrained { span } => Diagnostic::simple_error( + error.to_string(), + "This oracle call must be wrapped in a call to another unconstrained function before being returned to a constrained runtime".into(), + *span, + ), ResolverError::DependencyCycle { span, item, cycle } => { Diagnostic::simple_error( "Dependency cycle found".into(), format!("'{item}' recursively depends on itself: {cycle}"), - span, + *span, ) }, + ResolverError::JumpInConstrainedFn { is_break, span } => { + let item = if *is_break { "break" } else { "continue" }; + Diagnostic::simple_error( + format!("{item} is only allowed in unconstrained functions"), + "Constrained code must always have a known number of loop iterations".into(), + *span, + ) + }, + ResolverError::JumpOutsideLoop { is_break, span } => { + let item = if *is_break { "break" } else { "continue" }; + Diagnostic::simple_error( + format!("{item} is only allowed within loops"), + "".into(), + *span, + ) + }, + ResolverError::MutableGlobal { span } => { + Diagnostic::simple_error( + "Only `comptime` globals may be mutable".into(), + String::new(), + *span, + ) + }, + ResolverError::SelfReferentialStruct { span } => { + Diagnostic::simple_error( + "Self-referential structs are not supported".into(), + "".into(), + *span, + ) + }, + ResolverError::NoPredicatesAttributeOnUnconstrained { ident } => { + let name = &ident.0.contents; + + let mut diag = Diagnostic::simple_error( + format!("misplaced #[no_predicates] attribute on unconstrained function {name}. Only allowed on constrained functions"), + "misplaced #[no_predicates] attribute".to_string(), + ident.0.span(), + ); + + diag.add_note("The `#[no_predicates]` attribute specifies to the compiler whether it should diverge from auto-inlining constrained functions".to_owned()); + diag + } + ResolverError::FoldAttributeOnUnconstrained { ident } => { + let name = &ident.0.contents; + + let mut diag = Diagnostic::simple_error( + format!("misplaced #[fold] attribute on unconstrained function {name}. Only allowed on constrained functions"), + "misplaced #[fold] attribute".to_string(), + ident.0.span(), + ); + + diag.add_note("The `#[fold]` attribute specifies whether a constrained function should be treated as a separate circuit rather than inlined into the program entry point".to_owned()); + diag + } + ResolverError::ArrayLengthInterpreter { error } => Diagnostic::from(error), } } } diff --git a/compiler/noirc_frontend/src/hir/resolution/globals.rs b/compiler/noirc_frontend/src/hir/resolution/globals.rs index 9fb31271727..bcda4e75d3d 100644 --- a/compiler/noirc_frontend/src/hir/resolution/globals.rs +++ b/compiler/noirc_frontend/src/hir/resolution/globals.rs @@ -11,18 +11,12 @@ use crate::{ use fm::FileId; use iter_extended::vecmap; +#[derive(Default)] pub(crate) struct ResolvedGlobals { pub(crate) globals: Vec<(FileId, GlobalId)>, pub(crate) errors: Vec<(CompilationError, FileId)>, } -impl ResolvedGlobals { - pub(crate) fn extend(&mut self, oth: Self) { - self.globals.extend(oth.globals); - self.errors.extend(oth.errors); - } -} - pub(crate) fn resolve_globals( context: &mut Context, globals: Vec, diff --git a/compiler/noirc_frontend/src/hir/resolution/impls.rs b/compiler/noirc_frontend/src/hir/resolution/impls.rs index 4aa70f00cfc..7efd1eed86e 100644 --- a/compiler/noirc_frontend/src/hir/resolution/impls.rs +++ b/compiler/noirc_frontend/src/hir/resolution/impls.rs @@ -2,6 +2,7 @@ use std::collections::BTreeMap; use fm::FileId; +use crate::ast::ItemVisibility; use crate::{ graph::CrateId, hir::{ @@ -67,7 +68,14 @@ pub(crate) fn collect_impls( // 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() { + if module + .declare_function( + method.name_ident().clone(), + ItemVisibility::Public, + *method_id, + ) + .is_err() + { module.remove_function(method.name_ident()); } } diff --git a/compiler/noirc_frontend/src/hir/resolution/import.rs b/compiler/noirc_frontend/src/hir/resolution/import.rs index e6ac33053a0..343113836ed 100644 --- a/compiler/noirc_frontend/src/hir/resolution/import.rs +++ b/compiler/noirc_frontend/src/hir/resolution/import.rs @@ -1,10 +1,14 @@ use noirc_errors::{CustomDiagnostic, Span}; +use thiserror::Error; use crate::graph::CrateId; +use crate::hir::def_collector::dc_crate::CompilationError; use std::collections::BTreeMap; +use crate::ast::{Ident, ItemVisibility, Path, PathKind}; use crate::hir::def_map::{CrateDefMap, LocalModuleId, ModuleDefId, ModuleId, PerNs}; -use crate::{Ident, Path, PathKind}; + +use super::errors::ResolverError; #[derive(Debug, Clone)] pub struct ImportDirective { @@ -14,12 +18,30 @@ pub struct ImportDirective { pub is_prelude: bool, } -pub type PathResolution = Result; +struct NamespaceResolution { + module_id: ModuleId, + namespace: PerNs, + error: Option, +} + +type NamespaceResolutionResult = Result; + +pub struct PathResolution { + pub module_def_id: ModuleDefId, + + pub error: Option, +} + +pub(crate) type PathResolutionResult = Result; -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, Error)] pub enum PathResolutionError { + #[error("Could not resolve '{0}' in path")] Unresolved(Ident), + #[error("Contract variable '{0}' referenced from outside the contract")] ExternalContractUsed(Ident), + #[error("{0} is private and not visible from the current module")] + Private(Ident), } #[derive(Debug)] @@ -31,50 +53,83 @@ pub struct ResolvedImport { // The module which we must add the resolved namespace to pub module_scope: LocalModuleId, pub is_prelude: bool, + pub error: Option, } -impl From for CustomDiagnostic { +impl From for CompilationError { fn from(error: PathResolutionError) -> Self { - match error { - PathResolutionError::Unresolved(ident) => CustomDiagnostic::simple_error( - format!("Could not resolve '{ident}' in path"), - String::new(), - ident.span(), - ), + Self::ResolverError(ResolverError::PathResolutionError(error)) + } +} + +impl<'a> From<&'a PathResolutionError> for CustomDiagnostic { + fn from(error: &'a PathResolutionError) -> Self { + match &error { + PathResolutionError::Unresolved(ident) => { + CustomDiagnostic::simple_error(error.to_string(), String::new(), ident.span()) + } PathResolutionError::ExternalContractUsed(ident) => CustomDiagnostic::simple_error( - format!("Contract variable '{ident}' referenced from outside the contract"), + error.to_string(), "Contracts may only be referenced from within a contract".to_string(), ident.span(), ), + // This will be upgraded to an error in future versions + PathResolutionError::Private(ident) => CustomDiagnostic::simple_warning( + error.to_string(), + format!("{ident} is private"), + ident.span(), + ), } } } pub fn resolve_import( crate_id: CrateId, - import_directive: ImportDirective, + import_directive: &ImportDirective, def_maps: &BTreeMap, -) -> Result { - let def_map = &def_maps[&crate_id]; - +) -> Result { let allow_contracts = allow_referencing_contracts(def_maps, crate_id, import_directive.module_id); let module_scope = import_directive.module_id; - let resolved_namespace = - resolve_path_to_ns(&import_directive, def_map, def_maps, allow_contracts) - .map_err(|error| (error, module_scope))?; + let NamespaceResolution { + module_id: resolved_module, + namespace: resolved_namespace, + mut error, + } = resolve_path_to_ns(import_directive, crate_id, crate_id, def_maps, allow_contracts)?; + + let name = resolve_path_name(import_directive); + + let visibility = resolved_namespace + .values + .or(resolved_namespace.types) + .map(|(_, visibility, _)| visibility) + .expect("Found empty namespace"); + + error = error.or_else(|| { + if can_reference_module_id( + def_maps, + crate_id, + import_directive.module_id, + resolved_module, + visibility, + ) { + None + } else { + Some(PathResolutionError::Private(name.clone())) + } + }); - let name = resolve_path_name(&import_directive); Ok(ResolvedImport { name, resolved_namespace, module_scope, is_prelude: import_directive.is_prelude, + error, }) } -pub(super) fn allow_referencing_contracts( +fn allow_referencing_contracts( def_maps: &BTreeMap, krate: CrateId, local_id: LocalModuleId, @@ -82,27 +137,40 @@ pub(super) fn allow_referencing_contracts( ModuleId { krate, local_id }.module(def_maps).is_contract } -pub fn resolve_path_to_ns( +fn resolve_path_to_ns( import_directive: &ImportDirective, - def_map: &CrateDefMap, + crate_id: CrateId, + importing_crate: CrateId, def_maps: &BTreeMap, allow_contracts: bool, -) -> PathResolution { +) -> NamespaceResolutionResult { let import_path = &import_directive.path.segments; + let def_map = &def_maps[&crate_id]; match import_directive.path.kind { crate::ast::PathKind::Crate => { // Resolve from the root of the crate - resolve_path_from_crate_root(def_map, import_path, def_maps, allow_contracts) - } - crate::ast::PathKind::Dep => { - resolve_external_dep(def_map, import_directive, def_maps, allow_contracts) + resolve_path_from_crate_root( + crate_id, + importing_crate, + import_path, + def_maps, + allow_contracts, + ) } + crate::ast::PathKind::Dep => resolve_external_dep( + def_map, + import_directive, + def_maps, + allow_contracts, + importing_crate, + ), crate::ast::PathKind::Plain => { // Plain paths are only used to import children modules. It's possible to allow import of external deps, but maybe this distinction is better? // In Rust they can also point to external Dependencies, if no children can be found with the specified name resolve_name_in_module( - def_map, + crate_id, + importing_crate, import_path, import_directive.module_id, def_maps, @@ -113,45 +181,60 @@ pub fn resolve_path_to_ns( } fn resolve_path_from_crate_root( - def_map: &CrateDefMap, + crate_id: CrateId, + importing_crate: CrateId, + import_path: &[Ident], def_maps: &BTreeMap, allow_contracts: bool, -) -> PathResolution { - resolve_name_in_module(def_map, import_path, def_map.root, def_maps, allow_contracts) +) -> NamespaceResolutionResult { + resolve_name_in_module( + crate_id, + importing_crate, + import_path, + def_maps[&crate_id].root, + def_maps, + allow_contracts, + ) } fn resolve_name_in_module( - def_map: &CrateDefMap, + krate: CrateId, + importing_crate: CrateId, import_path: &[Ident], starting_mod: LocalModuleId, def_maps: &BTreeMap, allow_contracts: bool, -) -> PathResolution { - let mut current_mod = &def_map.modules[starting_mod.0]; +) -> NamespaceResolutionResult { + let def_map = &def_maps[&krate]; + let mut current_mod_id = ModuleId { krate, local_id: starting_mod }; + let mut current_mod = &def_map.modules[current_mod_id.local_id.0]; // There is a possibility that the import path is empty // In that case, early return if import_path.is_empty() { - let mod_id = ModuleId { krate: def_map.krate, local_id: starting_mod }; - return Ok(PerNs::types(mod_id.into())); + return Ok(NamespaceResolution { + module_id: current_mod_id, + namespace: PerNs::types(current_mod_id.into()), + error: None, + }); } - let mut import_path = import_path.iter(); - let first_segment = import_path.next().expect("ice: could not fetch first segment"); + let first_segment = import_path.first().expect("ice: could not fetch first segment"); let mut current_ns = current_mod.find_name(first_segment); if current_ns.is_none() { return Err(PathResolutionError::Unresolved(first_segment.clone())); } - for segment in import_path { - let typ = match current_ns.take_types() { - None => return Err(PathResolutionError::Unresolved(segment.clone())), - Some(typ) => typ, + let mut warning: Option = None; + for (last_segment, current_segment) in import_path.iter().zip(import_path.iter().skip(1)) { + let (typ, visibility) = match current_ns.types { + None => return Err(PathResolutionError::Unresolved(last_segment.clone())), + Some((typ, visibility, _)) => (typ, visibility), }; // In the type namespace, only Mod can be used in a path. - let new_module_id = match typ { + current_mod_id = match typ { ModuleDefId::ModuleId(id) => id, ModuleDefId::FunctionId(_) => panic!("functions cannot be in the type namespace"), // TODO: If impls are ever implemented, types can be used in a path @@ -161,22 +244,37 @@ fn resolve_name_in_module( ModuleDefId::GlobalId(_) => panic!("globals cannot be in the type namespace"), }; - current_mod = &def_maps[&new_module_id.krate].modules[new_module_id.local_id.0]; + warning = warning.or_else(|| { + if can_reference_module_id( + def_maps, + importing_crate, + starting_mod, + current_mod_id, + visibility, + ) { + None + } else { + Some(PathResolutionError::Private(last_segment.clone())) + } + }); + + current_mod = &def_maps[¤t_mod_id.krate].modules[current_mod_id.local_id.0]; // Check if namespace - let found_ns = current_mod.find_name(segment); + let found_ns = current_mod.find_name(current_segment); if found_ns.is_none() { - return Err(PathResolutionError::Unresolved(segment.clone())); + return Err(PathResolutionError::Unresolved(current_segment.clone())); } + // Check if it is a contract and we're calling from a non-contract context if current_mod.is_contract && !allow_contracts { - return Err(PathResolutionError::ExternalContractUsed(segment.clone())); + return Err(PathResolutionError::ExternalContractUsed(current_segment.clone())); } current_ns = found_ns; } - Ok(current_ns) + Ok(NamespaceResolution { module_id: current_mod_id, namespace: current_ns, error: warning }) } fn resolve_path_name(import_directive: &ImportDirective) -> Ident { @@ -191,11 +289,11 @@ fn resolve_external_dep( directive: &ImportDirective, def_maps: &BTreeMap, allow_contracts: bool, -) -> PathResolution { + importing_crate: CrateId, +) -> NamespaceResolutionResult { // Use extern_prelude to get the dep - // let path = &directive.path.segments; - // + // Fetch the root module from the prelude let crate_name = path.first().unwrap(); let dep_module = current_def_map @@ -218,7 +316,49 @@ fn resolve_external_dep( is_prelude: false, }; - let dep_def_map = def_maps.get(&dep_module.krate).unwrap(); + resolve_path_to_ns(&dep_directive, dep_module.krate, importing_crate, def_maps, allow_contracts) +} + +// Issue an error if the given private function is being called from a non-child module, or +// if the given pub(crate) function is being called from another crate +fn can_reference_module_id( + def_maps: &BTreeMap, + importing_crate: CrateId, + current_module: LocalModuleId, + target_module: ModuleId, + visibility: ItemVisibility, +) -> bool { + // Note that if the target module is in a different crate from the current module then we will either + // return true as the target module is public or return false as it is private without looking at the `CrateDefMap` in either case. + let same_crate = target_module.krate == importing_crate; + let target_crate_def_map = &def_maps[&target_module.krate]; + + match visibility { + ItemVisibility::Public => true, + ItemVisibility::PublicCrate => same_crate, + ItemVisibility::Private => { + same_crate + && module_descendent_of_target( + target_crate_def_map, + target_module.local_id, + current_module, + ) + } + } +} + +// Returns true if `current` is a (potentially nested) child module of `target`. +// This is also true if `current == target`. +fn module_descendent_of_target( + def_map: &CrateDefMap, + target: LocalModuleId, + current: LocalModuleId, +) -> bool { + if current == target { + return true; + } - resolve_path_to_ns(&dep_directive, dep_def_map, def_maps, allow_contracts) + def_map.modules[current.0] + .parent + .map_or(false, |parent| module_descendent_of_target(def_map, target, parent)) } diff --git a/compiler/noirc_frontend/src/hir/resolution/path_resolver.rs b/compiler/noirc_frontend/src/hir/resolution/path_resolver.rs index 4c5fa3bceef..e423e10b712 100644 --- a/compiler/noirc_frontend/src/hir/resolution/path_resolver.rs +++ b/compiler/noirc_frontend/src/hir/resolution/path_resolver.rs @@ -1,11 +1,9 @@ -use super::import::{ - allow_referencing_contracts, resolve_path_to_ns, ImportDirective, PathResolutionError, -}; -use crate::Path; +use super::import::{resolve_import, ImportDirective, PathResolution, PathResolutionResult}; +use crate::ast::Path; use std::collections::BTreeMap; use crate::graph::CrateId; -use crate::hir::def_map::{CrateDefMap, LocalModuleId, ModuleDefId, ModuleId}; +use crate::hir::def_map::{CrateDefMap, LocalModuleId, ModuleId}; pub trait PathResolver { /// Resolve the given path returning the resolved ModuleDefId. @@ -13,7 +11,7 @@ pub trait PathResolver { &self, def_maps: &BTreeMap, path: Path, - ) -> Result; + ) -> PathResolutionResult; fn local_module_id(&self) -> LocalModuleId; @@ -36,7 +34,7 @@ impl PathResolver for StandardPathResolver { &self, def_maps: &BTreeMap, path: Path, - ) -> Result { + ) -> PathResolutionResult { resolve_path(def_maps, self.module_id, path) } @@ -55,17 +53,15 @@ pub fn resolve_path( def_maps: &BTreeMap, module_id: ModuleId, path: Path, -) -> Result { +) -> PathResolutionResult { // lets package up the path into an ImportDirective and resolve it using that let import = ImportDirective { module_id: module_id.local_id, path, alias: None, is_prelude: false }; - let allow_referencing_contracts = - allow_referencing_contracts(def_maps, module_id.krate, module_id.local_id); + let resolved_import = resolve_import(module_id.krate, &import, def_maps)?; - let def_map = &def_maps[&module_id.krate]; - let ns = resolve_path_to_ns(&import, def_map, def_maps, allow_referencing_contracts)?; + let namespace = resolved_import.resolved_namespace; + let id = + namespace.values.or(namespace.types).map(|(id, _, _)| id).expect("Found empty namespace"); - let function = ns.values.map(|(id, _, _)| id); - let id = function.or_else(|| ns.types.map(|(id, _, _)| id)); - Ok(id.expect("Found empty namespace")) + Ok(PathResolution { module_def_id: id, error: resolved_import.error }) } diff --git a/compiler/noirc_frontend/src/hir/resolution/resolver.rs b/compiler/noirc_frontend/src/hir/resolution/resolver.rs index ad469f8146d..619250ccf68 100644 --- a/compiler/noirc_frontend/src/hir/resolution/resolver.rs +++ b/compiler/noirc_frontend/src/hir/resolution/resolver.rs @@ -11,6 +11,8 @@ // XXX: Change mentions of intern to resolve. In regards to the above comment // // XXX: Resolver does not check for unused functions +use acvm::acir::AcirField; + use crate::hir_def::expr::{ HirArrayLiteral, HirBinaryOp, HirBlockExpression, HirCallExpression, HirCapturedVar, HirCastExpression, HirConstructorExpression, HirExpression, HirIdent, HirIfExpression, @@ -18,31 +20,34 @@ use crate::hir_def::expr::{ HirMethodCallExpression, HirPrefixExpression, ImplKind, }; +use crate::hir_def::function::FunctionBody; use crate::hir_def::traits::{Trait, TraitConstraint}; +use crate::macros_api::SecondaryAttribute; use crate::token::{Attributes, FunctionAttribute}; use regex::Regex; -use std::collections::{BTreeMap, HashSet}; +use std::collections::{BTreeMap, BTreeSet, HashSet}; use std::rc::Rc; +use crate::ast::{ + ArrayLiteral, BinaryOpKind, BlockExpression, Expression, ExpressionKind, ForRange, + FunctionDefinition, FunctionKind, FunctionReturnType, Ident, ItemVisibility, LValue, + LetStatement, Literal, NoirFunction, NoirStruct, NoirTypeAlias, Param, Path, PathKind, Pattern, + Statement, StatementKind, TraitBound, UnaryOp, UnresolvedGenerics, UnresolvedTraitConstraint, + UnresolvedType, UnresolvedTypeData, UnresolvedTypeExpression, Visibility, ERROR_IDENT, +}; use crate::graph::CrateId; -use crate::hir::def_map::{LocalModuleId, ModuleDefId, TryFromModuleDefId, MAIN_FUNCTION}; +use crate::hir::def_map::{ModuleDefId, TryFromModuleDefId, MAIN_FUNCTION}; +use crate::hir::{ + comptime::{Interpreter, Value}, + def_map::CrateDefMap, + resolution::path_resolver::PathResolver, +}; use crate::hir_def::stmt::{HirAssignStatement, HirForStatement, HirLValue, HirPattern}; use crate::node_interner::{ DefinitionId, DefinitionKind, DependencyId, ExprId, FuncId, GlobalId, NodeInterner, StmtId, StructId, TraitId, TraitImplId, TraitMethodId, TypeAliasId, }; -use crate::{ - hir::{def_map::CrateDefMap, resolution::path_resolver::PathResolver}, - BlockExpression, Expression, ExpressionKind, FunctionKind, Ident, Literal, NoirFunction, - StatementKind, -}; -use crate::{ - ArrayLiteral, ContractFunctionType, Distinctness, ForRange, FunctionDefinition, - FunctionReturnType, FunctionVisibility, Generics, LValue, NoirStruct, NoirTypeAlias, Param, - Path, PathKind, Pattern, Shared, StructType, Type, TypeAlias, TypeVariable, TypeVariableKind, - UnaryOp, UnresolvedGenerics, UnresolvedTraitConstraint, UnresolvedType, UnresolvedTypeData, - UnresolvedTypeExpression, Visibility, ERROR_IDENT, -}; +use crate::{Generics, Shared, StructType, Type, TypeAlias, TypeVariable, TypeVariableKind}; use fm::FileId; use iter_extended::vecmap; use noirc_errors::{Location, Span, Spanned}; @@ -56,18 +61,19 @@ use crate::hir_def::{ }; use super::errors::{PubPosition, ResolverError}; +use super::import::PathResolution; -const SELF_TYPE_NAME: &str = "Self"; +pub const SELF_TYPE_NAME: &str = "Self"; type Scope = GenericScope; type ScopeTree = GenericScopeTree; type ScopeForest = GenericScopeForest; pub struct LambdaContext { - captures: Vec, + pub captures: Vec, /// the index in the scope tree /// (sometimes being filled by ScopeTree's find method) - scope_index: usize, + pub scope_index: usize, } /// The primary jobs of the Resolver are to validate that every variable found refers to exactly 1 @@ -97,6 +103,21 @@ pub struct Resolver<'a> { /// Used to link items to their dependencies in the dependency graph current_item: Option, + /// In-resolution names + /// + /// This needs to be a set because we can have multiple in-resolution + /// names when resolving structs that are declared in reverse order of their + /// dependencies, such as in the following case: + /// + /// ``` + /// struct Wrapper { + /// value: Wrapped + /// } + /// struct Wrapped { + /// } + /// ``` + resolving_ids: BTreeSet, + /// True if the current module is a contract. /// This is usually determined by self.path_resolver.module_id(), but it can /// be overridden for impls. Impls are an odd case since the methods within resolve @@ -115,6 +136,13 @@ pub struct Resolver<'a> { /// that are captured. We do this in order to create the hidden environment /// parameter for the lambda function. lambda_stack: Vec, + + /// True if we're currently resolving an unconstrained function + in_unconstrained_fn: bool, + + /// How many loops we're currently within. + /// This increases by 1 at the start of a loop, and decreases by 1 when it ends. + nested_loops: u32, } /// ResolverMetas are tagged onto each definition to track how many times they are used @@ -153,8 +181,11 @@ impl<'a> Resolver<'a> { lambda_stack: Vec::new(), current_trait_impl: None, current_item: None, + resolving_ids: BTreeSet::new(), file, in_contract, + in_unconstrained_fn: false, + nested_loops: 0, } } @@ -178,6 +209,52 @@ impl<'a> Resolver<'a> { self.errors.push(err); } + /// This turns function parameters of the form: + /// fn foo(x: impl Bar) + /// + /// into + /// fn foo(x: T0_impl_Bar) where T0_impl_Bar: Bar + fn desugar_impl_trait_args(&mut self, func: &mut NoirFunction, func_id: FuncId) { + let mut impl_trait_generics = HashSet::new(); + let mut counter: usize = 0; + for parameter in func.def.parameters.iter_mut() { + if let UnresolvedTypeData::TraitAsType(path, args) = ¶meter.typ.typ { + let mut new_generic_ident: Ident = + format!("T{}_impl_{}", func_id, path.as_string()).into(); + let mut new_generic_path = Path::from_ident(new_generic_ident.clone()); + while impl_trait_generics.contains(&new_generic_ident) + || self.lookup_generic_or_global_type(&new_generic_path).is_some() + { + new_generic_ident = + format!("T{}_impl_{}_{}", func_id, path.as_string(), counter).into(); + new_generic_path = Path::from_ident(new_generic_ident.clone()); + counter += 1; + } + impl_trait_generics.insert(new_generic_ident.clone()); + + let is_synthesized = true; + let new_generic_type_data = + UnresolvedTypeData::Named(new_generic_path, vec![], is_synthesized); + let new_generic_type = + UnresolvedType { typ: new_generic_type_data.clone(), span: None }; + let new_trait_bound = TraitBound { + trait_path: path.clone(), + trait_id: None, + trait_generics: args.to_vec(), + }; + let new_trait_constraint = UnresolvedTraitConstraint { + typ: new_generic_type, + trait_bound: new_trait_bound, + }; + + parameter.typ.typ = new_generic_type_data; + func.def.generics.push(new_generic_ident); + func.def.where_clause.push(new_trait_constraint); + } + } + self.add_generics(&impl_trait_generics.into_iter().collect()); + } + /// Resolving a function involves interning the metadata /// interning any statements inside of the function /// and interning the function itself @@ -185,7 +262,7 @@ impl<'a> Resolver<'a> { /// Since lowering would require scope data, unless we add an extra resolution field to the AST pub fn resolve_function( mut self, - func: NoirFunction, + mut func: NoirFunction, func_id: FuncId, ) -> (HirFunction, FuncMeta, Vec) { self.scopes.start_function(); @@ -193,8 +270,9 @@ impl<'a> Resolver<'a> { // Check whether the function has globals in the local module and add them to the scope self.resolve_local_globals(); - self.add_generics(&func.def.generics); + + self.desugar_impl_trait_args(&mut func, func_id); self.trait_bounds = func.def.where_clause.clone(); let is_low_level_or_oracle = func @@ -217,6 +295,7 @@ impl<'a> Resolver<'a> { pub fn resolve_trait_function( &mut self, name: &Ident, + generics: &UnresolvedGenerics, parameters: &[(Ident, UnresolvedType)], return_type: &FunctionReturnType, where_clause: &[UnresolvedTraitConstraint], @@ -233,11 +312,10 @@ impl<'a> Resolver<'a> { let def = FunctionDefinition { name: name.clone(), attributes: Attributes::empty(), - is_open: false, - is_internal: false, is_unconstrained: false, - visibility: FunctionVisibility::Public, // Trait functions are always public - generics: Vec::new(), // self.generics should already be set + is_comptime: false, + visibility: ItemVisibility::Public, // Trait functions are always public + generics: generics.clone(), parameters: vecmap(parameters, |(name, typ)| Param { visibility: Visibility::Private, pattern: Pattern::Identifier(name.clone()), @@ -249,7 +327,6 @@ impl<'a> Resolver<'a> { where_clause: where_clause.to_vec(), return_type: return_type.clone(), return_visibility: Visibility::Private, - return_distinctness: Distinctness::DuplicationAllowed, }; let (hir_func, func_meta) = self.intern_function(NoirFunction { kind, def }, func_id); @@ -417,6 +494,11 @@ impl<'a> Resolver<'a> { fn intern_function(&mut self, func: NoirFunction, id: FuncId) -> (HirFunction, FuncMeta) { let func_meta = self.extract_meta(&func, id); + + if func.def.is_unconstrained { + self.in_unconstrained_fn = true; + } + let hir_func = match func.kind { FunctionKind::Builtin | FunctionKind::LowLevel | FunctionKind::Oracle => { HirFunction::empty() @@ -461,44 +543,43 @@ impl<'a> Resolver<'a> { /// 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 { - use UnresolvedTypeData::*; + fn resolve_type_inner(&mut self, typ: UnresolvedType) -> Type { + use crate::ast::UnresolvedTypeData::*; let resolved_type = match typ.typ { FieldElement => Type::FieldElement, Array(size, elem) => { - let elem = Box::new(self.resolve_type_inner(*elem, new_variables)); - let size = if size.is_none() { - Type::NotConstant - } else { - self.resolve_array_size(size, new_variables) - }; + let elem = Box::new(self.resolve_type_inner(*elem)); + let size = self.convert_expression_type(size); Type::Array(Box::new(size), elem) } + Slice(elem) => { + let elem = Box::new(self.resolve_type_inner(*elem)); + Type::Slice(elem) + } Expression(expr) => self.convert_expression_type(expr), Integer(sign, bits) => Type::Integer(sign, bits), Bool => Type::Bool, String(size) => { - let resolved_size = self.resolve_array_size(size, new_variables); + let resolved_size = self.convert_expression_type(size); Type::String(Box::new(resolved_size)) } FormatString(size, fields) => { let resolved_size = self.convert_expression_type(size); - let fields = self.resolve_type_inner(*fields, new_variables); + let fields = self.resolve_type_inner(*fields); Type::FmtString(Box::new(resolved_size), Box::new(fields)) } + Code => Type::Code, Unit => Type::Unit, Unspecified => Type::Error, Error => Type::Error, - Named(path, args, _) => self.resolve_named_type(path, args, new_variables), - TraitAsType(path, args) => self.resolve_trait_as_type(path, args, new_variables), + Named(path, args, _) => self.resolve_named_type(path, args), + TraitAsType(path, args) => self.resolve_trait_as_type(path, args), - Tuple(fields) => { - Type::Tuple(vecmap(fields, |field| self.resolve_type_inner(field, new_variables))) - } + Tuple(fields) => Type::Tuple(vecmap(fields, |field| self.resolve_type_inner(field))), Function(args, ret, env) => { - let args = vecmap(args, |arg| self.resolve_type_inner(arg, new_variables)); - let ret = Box::new(self.resolve_type_inner(*ret, new_variables)); + let args = vecmap(args, |arg| self.resolve_type_inner(arg)); + let ret = Box::new(self.resolve_type_inner(*ret)); // expect() here is valid, because the only places we don't have a span are omitted types // e.g. a function without return type implicitly has a spanless UnresolvedType::Unit return type @@ -506,7 +587,7 @@ impl<'a> Resolver<'a> { let env_span = env.span.expect("Unexpected missing span for closure environment type"); - let env = Box::new(self.resolve_type_inner(*env, new_variables)); + let env = Box::new(self.resolve_type_inner(*env)); match *env { Type::Unit | Type::Tuple(_) | Type::NamedGeneric(_, _) => { @@ -522,9 +603,9 @@ impl<'a> Resolver<'a> { } } MutableReference(element) => { - Type::MutableReference(Box::new(self.resolve_type_inner(*element, new_variables))) + Type::MutableReference(Box::new(self.resolve_type_inner(*element))) } - Parenthesized(typ) => self.resolve_type_inner(*typ, new_variables), + Parenthesized(typ) => self.resolve_type_inner(*typ), }; if let Type::Struct(_, _) = resolved_type { @@ -543,12 +624,7 @@ impl<'a> Resolver<'a> { self.generics.iter().find(|(name, _, _)| name.as_ref() == target_name) } - fn resolve_named_type( - &mut self, - path: Path, - args: Vec, - new_variables: &mut Generics, - ) -> Type { + fn resolve_named_type(&mut self, path: Path, args: Vec) -> Type { if args.is_empty() { if let Some(typ) = self.lookup_generic_or_global_type(&path) { return typ; @@ -571,7 +647,7 @@ impl<'a> Resolver<'a> { } let span = path.span(); - let mut args = vecmap(args, |arg| self.resolve_type_inner(arg, new_variables)); + let mut args = vecmap(args, |arg| self.resolve_type_inner(arg)); if let Some(type_alias) = self.lookup_type_alias(path.clone()) { let type_alias = type_alias.borrow(); @@ -602,8 +678,26 @@ impl<'a> Resolver<'a> { match self.lookup_struct_or_error(path) { Some(struct_type) => { - let expected_generic_count = struct_type.borrow().generics.len(); + if self.resolving_ids.contains(&struct_type.borrow().id) { + self.push_err(ResolverError::SelfReferentialStruct { + span: struct_type.borrow().name.span(), + }); + + return Type::Error; + } + let expected_generic_count = struct_type.borrow().generics.len(); + if !self.in_contract + && self + .interner + .struct_attributes(&struct_type.borrow().id) + .iter() + .any(|attr| matches!(attr, SecondaryAttribute::Abi(_))) + { + self.push_err(ResolverError::AbiAttributeOutsideContract { + span: struct_type.borrow().name.span(), + }); + } self.verify_generics_count(expected_generic_count, &mut args, span, || { struct_type.borrow().to_string() }); @@ -619,13 +713,8 @@ impl<'a> Resolver<'a> { } } - fn resolve_trait_as_type( - &mut self, - path: Path, - args: Vec, - new_variables: &mut Generics, - ) -> Type { - let args = vecmap(args, |arg| self.resolve_type_inner(arg, new_variables)); + fn resolve_trait_as_type(&mut self, path: Path, args: Vec) -> Type { + let args = vecmap(args, |arg| self.resolve_type_inner(arg)); if let Some(t) = self.lookup_trait_or_error(path) { Type::TraitAsType(t.id, Rc::new(t.name.to_string()), args) @@ -664,36 +753,20 @@ impl<'a> Resolver<'a> { // If we cannot find a local generic of the same name, try to look up a global match self.path_resolver.resolve(self.def_maps, path.clone()) { - Ok(ModuleDefId::GlobalId(id)) => { + Ok(PathResolution { module_def_id: ModuleDefId::GlobalId(id), error }) => { if let Some(current_item) = self.current_item { self.interner.add_global_dependency(current_item, id); } + + if let Some(error) = error { + self.push_err(error.into()); + } Some(Type::Constant(self.eval_global_as_array_length(id, path))) } _ => None, } } - fn resolve_array_size( - &mut self, - length: Option, - new_variables: &mut Generics, - ) -> Type { - match length { - None => { - let id = self.interner.next_type_variable_id(); - let typevar = TypeVariable::unbound(id); - new_variables.push(typevar.clone()); - - // 'Named'Generic is a bit of a misnomer here, we want a type variable that - // wont be bound over but this one has no name since we do not currently - // require users to explicitly be generic over array lengths. - Type::NamedGeneric(typevar, Rc::new("".into())) - } - Some(length) => self.convert_expression_type(length), - } - } - fn convert_expression_type(&mut self, length: UnresolvedTypeExpression) -> Type { match length { UnresolvedTypeExpression::Variable(path) => { @@ -746,11 +819,10 @@ impl<'a> Resolver<'a> { /// Translates an UnresolvedType to a Type pub fn resolve_type(&mut self, typ: UnresolvedType) -> Type { let span = typ.span; - let resolved_type = self.resolve_type_inner(typ, &mut vec![]); + let resolved_type = self.resolve_type_inner(typ); if resolved_type.is_nested_slice() { self.errors.push(ResolverError::NestedSlices { span: span.unwrap() }); } - resolved_type } @@ -791,7 +863,7 @@ impl<'a> Resolver<'a> { fn resolve_inferred_type(&mut self, typ: UnresolvedType) -> Type { match &typ.typ { UnresolvedTypeData::Unspecified => self.interner.next_type_variable(), - _ => self.resolve_type_inner(typ, &mut vec![]), + _ => self.resolve_type(typ), } } @@ -858,7 +930,10 @@ impl<'a> Resolver<'a> { self.resolve_local_globals(); self.current_item = Some(DependencyId::Struct(struct_id)); + + self.resolving_ids.insert(struct_id); let fields = vecmap(unresolved.fields, |(ident, typ)| (ident, self.resolve_type(typ))); + self.resolving_ids.remove(&struct_id); (generics, fields, self.errors) } @@ -898,8 +973,25 @@ impl<'a> Resolver<'a> { let name_ident = HirIdent::non_trait_method(id, location); let attributes = func.attributes().clone(); + let has_no_predicates_attribute = attributes.is_no_predicates(); + let should_fold = attributes.is_foldable(); + if !self.inline_attribute_allowed(func) { + if has_no_predicates_attribute { + self.push_err(ResolverError::NoPredicatesAttributeOnUnconstrained { + ident: func.name_ident().clone(), + }); + } else if should_fold { + self.push_err(ResolverError::FoldAttributeOnUnconstrained { + ident: func.name_ident().clone(), + }); + } + } + // Both the #[fold] and #[no_predicates] alter a function's inline type and code generation in similar ways. + // In certain cases such as type checking (for which the following flag will be used) both attributes + // indicate we should code generate in the same way. Thus, we unify the attributes into one flag here. + let has_inline_attribute = has_no_predicates_attribute || should_fold; - let mut generics = vecmap(&self.generics, |(_, typevar, _)| typevar.clone()); + let generics = vecmap(&self.generics, |(_, typevar, _)| typevar.clone()); let mut parameters = vec![]; let mut parameter_types = vec![]; @@ -911,12 +1003,8 @@ impl<'a> Resolver<'a> { }); } - if self.is_entry_point_function(func) { - self.verify_type_valid_for_program_input(&typ); - } - let pattern = self.resolve_pattern(pattern, DefinitionKind::Local(None)); - let typ = self.resolve_type_inner(typ, &mut generics); + let typ = self.resolve_type_inner(typ); parameters.push((pattern, typ.clone(), visibility)); parameter_types.push(typ); @@ -933,7 +1021,7 @@ impl<'a> Resolver<'a> { }); } let is_low_level_function = - func.attributes().function.as_ref().map_or(false, |func| func.is_low_level()); + attributes.function.as_ref().map_or(false, |func| func.is_low_level()); if !self.path_resolver.module_id().krate.is_stdlib() && is_low_level_function { let error = ResolverError::LowLevelFunctionOutsideOfStdlib { ident: func.name_ident().clone() }; @@ -954,12 +1042,6 @@ impl<'a> Resolver<'a> { }); } - if !self.distinct_allowed(func) - && func.def.return_distinctness != Distinctness::DuplicationAllowed - { - self.push_err(ResolverError::DistinctNotAllowed { ident: func.name_ident().clone() }); - } - if matches!(attributes.function, Some(FunctionAttribute::Test { .. })) && !parameters.is_empty() { @@ -976,21 +1058,32 @@ impl<'a> Resolver<'a> { self.interner.push_definition_type(name_ident.id, typ.clone()); - self.handle_function_type(&func_id); - self.handle_is_function_internal(&func_id); + let direct_generics = func.def.generics.iter(); + let direct_generics = direct_generics + .filter_map(|generic| self.find_generic(&generic.0.contents)) + .map(|(name, typevar, _span)| (name.clone(), typevar.clone())) + .collect(); FuncMeta { name: name_ident, kind: func.kind, location, typ, + direct_generics, trait_impl: self.current_trait_impl, parameters: parameters.into(), return_type: func.def.return_type.clone(), return_visibility: func.def.return_visibility, - return_distinctness: func.def.return_distinctness, has_body: !func.def.body.is_empty(), trait_constraints: self.resolve_trait_constraints(&func.def.where_clause), + is_entry_point: self.is_entry_point_function(func), + has_inline_attribute, + + // These fields are only used by the elaborator + all_generics: Vec::new(), + is_trait_function: false, + parameter_idents: Vec::new(), + function_body: FunctionBody::Resolved, } } @@ -1004,7 +1097,7 @@ impl<'a> Resolver<'a> { /// True if the 'pub' keyword is allowed on parameters in this function /// 'pub' on function parameters is only allowed for entry point functions fn pub_allowed(&self, func: &NoirFunction) -> bool { - self.is_entry_point_function(func) + self.is_entry_point_function(func) || func.attributes().is_foldable() } fn is_entry_point_function(&self, func: &NoirFunction) -> bool { @@ -1015,35 +1108,10 @@ impl<'a> Resolver<'a> { } } - /// True if the `distinct` keyword is allowed on a function's return type - fn distinct_allowed(&self, func: &NoirFunction) -> bool { - if self.in_contract { - // "open" and "unconstrained" functions are compiled to brillig and thus duplication of - // witness indices in their abis is not a concern. - !func.def.is_unconstrained && !func.def.is_open - } else { - func.name() == MAIN_FUNCTION - } - } - - fn handle_function_type(&mut self, function: &FuncId) { - let function_type = self.interner.function_modifiers(function).contract_function_type; - - if !self.in_contract && function_type == Some(ContractFunctionType::Open) { - let span = self.interner.function_ident(function).span(); - self.errors.push(ResolverError::ContractFunctionTypeInNormalFunction { span }); - self.interner.function_modifiers_mut(function).contract_function_type = None; - } - } - - fn handle_is_function_internal(&mut self, function: &FuncId) { - if !self.in_contract { - if self.interner.function_modifiers(function).is_internal == Some(true) { - let span = self.interner.function_ident(function).span(); - self.push_err(ResolverError::ContractFunctionInternalInNormalFunction { span }); - } - self.interner.function_modifiers_mut(function).is_internal = None; - } + fn inline_attribute_allowed(&self, func: &NoirFunction) -> bool { + // Inline attributes are only relevant for constrained functions + // as all unconstrained functions are not inlined + !func.def.is_unconstrained } fn declare_numeric_generics(&mut self, params: &[Type], return_type: &Type) { @@ -1090,10 +1158,15 @@ impl<'a> Resolver<'a> { | Type::TypeVariable(_, _) | Type::Constant(_) | Type::NamedGeneric(_, _) - | Type::NotConstant - | Type::TraitAsType(..) + | Type::Code | Type::Forall(_, _) => (), + Type::TraitAsType(_, _, args) => { + for arg in args { + Self::find_numeric_generics_in_type(arg, found); + } + } + Type::Array(length, element_type) => { if let Type::NamedGeneric(type_variable, name) = length.as_ref() { found.insert(name.to_string(), type_variable.clone()); @@ -1101,6 +1174,10 @@ impl<'a> Resolver<'a> { Self::find_numeric_generics_in_type(element_type, found); } + Type::Slice(element_type) => { + Self::find_numeric_generics_in_type(element_type, found); + } + Type::Tuple(fields) => { for field in fields { Self::find_numeric_generics_in_type(field, found); @@ -1153,22 +1230,35 @@ impl<'a> Resolver<'a> { pub fn resolve_global_let( &mut self, - let_stmt: crate::LetStatement, + let_stmt: LetStatement, global_id: GlobalId, ) -> HirStatement { self.current_item = Some(DependencyId::Global(global_id)); let expression = self.resolve_expression(let_stmt.expression); - let global_id = self.interner.next_global_id(); let definition = DefinitionKind::Global(global_id); + if !self.in_contract + && let_stmt.attributes.iter().any(|attr| matches!(attr, SecondaryAttribute::Abi(_))) + { + let span = let_stmt.pattern.span(); + self.push_err(ResolverError::AbiAttributeOutsideContract { span }); + } + + if !let_stmt.comptime && matches!(let_stmt.pattern, Pattern::Mutable(..)) { + let span = let_stmt.pattern.span(); + self.push_err(ResolverError::MutableGlobal { span }); + } + HirStatement::Let(HirLetStatement { pattern: self.resolve_pattern(let_stmt.pattern, definition), r#type: self.resolve_type(let_stmt.r#type), expression, + attributes: let_stmt.attributes, + comptime: let_stmt.comptime, }) } - pub fn resolve_stmt(&mut self, stmt: StatementKind) -> HirStatement { + pub fn resolve_stmt(&mut self, stmt: StatementKind, span: Span) -> HirStatement { match stmt { StatementKind::Let(let_stmt) => { let expression = self.resolve_expression(let_stmt.expression); @@ -1177,18 +1267,19 @@ impl<'a> Resolver<'a> { pattern: self.resolve_pattern(let_stmt.pattern, definition), r#type: self.resolve_type(let_stmt.r#type), expression, + attributes: let_stmt.attributes, + comptime: let_stmt.comptime, }) } StatementKind::Constrain(constrain_stmt) => { - let span = constrain_stmt.0.span; - let assert_msg_call_expr_id = - self.resolve_assert_message(constrain_stmt.1, span, constrain_stmt.0.clone()); let expr_id = self.resolve_expression(constrain_stmt.0); + let assert_message_expr_id = + constrain_stmt.1.map(|assert_expr_id| self.resolve_expression(assert_expr_id)); HirStatement::Constrain(HirConstrainStatement( expr_id, self.file, - assert_msg_call_expr_id, + assert_message_expr_id, )) } StatementKind::Expression(expr) => { @@ -1208,6 +1299,8 @@ impl<'a> Resolver<'a> { let end_range = self.resolve_expression(end_range); let (identifier, block) = (for_loop.identifier, for_loop.block); + self.nested_loops += 1; + // 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| { @@ -1220,6 +1313,8 @@ impl<'a> Resolver<'a> { (decl, this.resolve_expression(block)) }); + self.nested_loops -= 1; + HirStatement::For(HirForStatement { start_range, end_range, @@ -1230,55 +1325,33 @@ impl<'a> Resolver<'a> { range @ ForRange::Array(_) => { let for_stmt = range.into_for(for_loop.identifier, for_loop.block, for_loop.span); - self.resolve_stmt(for_stmt) + self.resolve_stmt(for_stmt.kind, for_loop.span) } } } + StatementKind::Break => { + self.check_break_continue(true, span); + HirStatement::Break + } + StatementKind::Continue => { + self.check_break_continue(false, span); + HirStatement::Continue + } StatementKind::Error => HirStatement::Error, + StatementKind::Comptime(statement) => { + let hir_statement = self.resolve_stmt(statement.kind, statement.span); + let statement_id = self.interner.push_stmt(hir_statement); + self.interner.push_stmt_location(statement_id, statement.span, self.file); + HirStatement::Comptime(statement_id) + } } } - fn resolve_assert_message( - &mut self, - assert_message_expr: Option, - span: Span, - condition: Expression, - ) -> Option { - let assert_message_expr = assert_message_expr?; - - if matches!( - assert_message_expr, - Expression { kind: ExpressionKind::Literal(Literal::Str(..)), .. } - ) { - return Some(self.resolve_expression(assert_message_expr)); - } - - let is_in_stdlib = self.path_resolver.module_id().krate.is_stdlib(); - let assert_msg_call_path = if is_in_stdlib { - ExpressionKind::Variable(Path { - segments: vec![Ident::from("resolve_assert_message")], - kind: PathKind::Crate, - span, - }) - } else { - ExpressionKind::Variable(Path { - segments: vec![Ident::from("std"), Ident::from("resolve_assert_message")], - kind: PathKind::Dep, - span, - }) - }; - let assert_msg_call_args = vec![assert_message_expr.clone(), condition]; - let assert_msg_call_expr = Expression::call( - Expression { kind: assert_msg_call_path, span }, - assert_msg_call_args, - span, - ); - Some(self.resolve_expression(assert_msg_call_expr)) - } - - pub fn intern_stmt(&mut self, stmt: StatementKind) -> StmtId { - let hir_stmt = self.resolve_stmt(stmt); - self.interner.push_stmt(hir_stmt) + pub fn intern_stmt(&mut self, stmt: Statement) -> StmtId { + let hir_stmt = self.resolve_stmt(stmt.kind, stmt.span); + let id = self.interner.push_stmt(hir_stmt); + self.interner.push_stmt_location(id, stmt.span, self.file); + id } fn resolve_lvalue(&mut self, lvalue: LValue) -> HirLValue { @@ -1289,75 +1362,27 @@ impl<'a> Resolver<'a> { HirLValue::Ident(ident.0, Type::Error) } - LValue::MemberAccess { object, field_name } => { - let object = Box::new(self.resolve_lvalue(*object)); - HirLValue::MemberAccess { object, field_name, field_index: None, typ: Type::Error } - } - LValue::Index { array, index } => { + LValue::MemberAccess { object, field_name, span } => HirLValue::MemberAccess { + object: Box::new(self.resolve_lvalue(*object)), + field_name, + location: Location::new(span, self.file), + field_index: None, + typ: Type::Error, + }, + LValue::Index { array, index, span } => { let array = Box::new(self.resolve_lvalue(*array)); let index = self.resolve_expression(index); - HirLValue::Index { array, index, typ: Type::Error } + let location = Location::new(span, self.file); + HirLValue::Index { array, index, location, typ: Type::Error } } - LValue::Dereference(lvalue) => { + LValue::Dereference(lvalue, span) => { let lvalue = Box::new(self.resolve_lvalue(*lvalue)); - HirLValue::Dereference { lvalue, element_type: Type::Error } - } - } - } - - // Issue an error if the given private function is being called from a non-child module, or - // if the given pub(crate) function is being called from another crate - fn check_can_reference_function( - &mut self, - func: FuncId, - span: Span, - visibility: FunctionVisibility, - ) { - let function_module = self.interner.function_module(func); - let current_module = self.path_resolver.module_id(); - - let same_crate = function_module.krate == current_module.krate; - let krate = function_module.krate; - let current_module = current_module.local_id; - let name = self.interner.function_name(&func).to_string(); - match visibility { - FunctionVisibility::Public => (), - FunctionVisibility::Private => { - if !same_crate - || !self.module_descendent_of_target( - krate, - function_module.local_id, - current_module, - ) - { - self.errors.push(ResolverError::PrivateFunctionCalled { span, name }); - } - } - FunctionVisibility::PublicCrate => { - if !same_crate { - self.errors.push(ResolverError::NonCrateFunctionCalled { span, name }); - } + let location = Location::new(span, self.file); + HirLValue::Dereference { lvalue, location, element_type: Type::Error } } } } - // Returns true if `current` is a (potentially nested) child module of `target`. - // This is also true if `current == target`. - fn module_descendent_of_target( - &self, - krate: CrateId, - target: LocalModuleId, - current: LocalModuleId, - ) -> bool { - if current == target { - return true; - } - - self.def_maps[&krate].modules[current.0] - .parent - .map_or(false, |parent| self.module_descendent_of_target(krate, target, parent)) - } - fn resolve_local_variable(&mut self, hir_ident: HirIdent, var_scope_index: usize) { let mut transitive_capture_index: Option = None; @@ -1392,27 +1417,37 @@ impl<'a> Resolver<'a> { } } + fn resolve_array_literal(&mut self, array_literal: ArrayLiteral) -> HirArrayLiteral { + match array_literal { + ArrayLiteral::Standard(elements) => { + let elements = vecmap(elements, |elem| self.resolve_expression(elem)); + HirArrayLiteral::Standard(elements) + } + ArrayLiteral::Repeated { repeated_element, length } => { + let span = length.span; + let length = + UnresolvedTypeExpression::from_expr(*length, span).unwrap_or_else(|error| { + self.errors.push(ResolverError::ParserError(Box::new(error))); + UnresolvedTypeExpression::Constant(0, span) + }); + + let length = self.convert_expression_type(length); + let repeated_element = self.resolve_expression(*repeated_element); + + HirArrayLiteral::Repeated { repeated_element, length } + } + } + } + pub fn resolve_expression(&mut self, expr: Expression) -> ExprId { let hir_expr = match expr.kind { ExpressionKind::Literal(literal) => HirExpression::Literal(match literal { Literal::Bool(b) => HirLiteral::Bool(b), - Literal::Array(ArrayLiteral::Standard(elements)) => { - let elements = vecmap(elements, |elem| self.resolve_expression(elem)); - HirLiteral::Array(HirArrayLiteral::Standard(elements)) + Literal::Array(array_literal) => { + HirLiteral::Array(self.resolve_array_literal(array_literal)) } - Literal::Array(ArrayLiteral::Repeated { repeated_element, length }) => { - let span = length.span; - let length = UnresolvedTypeExpression::from_expr(*length, span).unwrap_or_else( - |error| { - self.errors.push(ResolverError::ParserError(Box::new(error))); - UnresolvedTypeExpression::Constant(0, span) - }, - ); - - let length = self.convert_expression_type(length); - let repeated_element = self.resolve_expression(*repeated_element); - - HirLiteral::Array(HirArrayLiteral::Repeated { repeated_element, length }) + Literal::Slice(array_literal) => { + HirLiteral::Slice(self.resolve_array_literal(array_literal)) } Literal::Integer(integer, sign) => HirLiteral::Integer(integer, sign), Literal::Str(str) => HirLiteral::Str(str), @@ -1420,14 +1455,20 @@ impl<'a> Resolver<'a> { Literal::FmtStr(str) => self.resolve_fmt_str_literal(str, expr.span), Literal::Unit => HirLiteral::Unit, }), - ExpressionKind::Variable(path) => { + ExpressionKind::Variable(path, generics) => { + let generics = + generics.map(|generics| vecmap(generics, |typ| self.resolve_type(typ))); + if let Some((method, constraint, assumed)) = self.resolve_trait_generic_path(&path) { - HirExpression::Ident(HirIdent { - location: Location::new(expr.span, self.file), - id: self.interner.trait_method_id(method), - impl_kind: ImplKind::TraitMethod(method, constraint, assumed), - }) + HirExpression::Ident( + HirIdent { + location: Location::new(expr.span, self.file), + id: self.interner.trait_method_id(method), + impl_kind: ImplKind::TraitMethod(method, constraint, assumed), + }, + generics, + ) } 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 @@ -1441,17 +1482,6 @@ impl<'a> Resolver<'a> { if let Some(current_item) = self.current_item { self.interner.add_function_dependency(current_item, id); } - - if self.interner.function_visibility(id) - != FunctionVisibility::Public - { - let span = hir_ident.location.span; - self.check_can_reference_function( - id, - span, - self.interner.function_visibility(id), - ); - } } DefinitionKind::Global(global_id) => { if let Some(current_item) = self.current_item { @@ -1475,7 +1505,7 @@ impl<'a> Resolver<'a> { } } - HirExpression::Ident(hir_ident) + HirExpression::Ident(hir_ident, generics) } } ExpressionKind::Prefix(prefix) => { @@ -1513,12 +1543,20 @@ impl<'a> Resolver<'a> { ExpressionKind::MethodCall(call_expr) => { let method = call_expr.method_name; let object = self.resolve_expression(call_expr.object); + + // Cannot verify the generic count here equals the expected count since we don't + // know which definition `method` refers to until it is resolved during type checking. + let generics = call_expr + .generics + .map(|generics| vecmap(generics, |typ| self.resolve_type(typ))); + let arguments = vecmap(call_expr.arguments, |arg| self.resolve_expression(arg)); let location = Location::new(expr.span, self.file); HirExpression::MethodCall(HirMethodCallExpression { - arguments, method, object, + generics, + arguments, location, }) } @@ -1535,7 +1573,9 @@ impl<'a> Resolver<'a> { collection: self.resolve_expression(indexed_expr.collection), index: self.resolve_expression(indexed_expr.index), }), - ExpressionKind::Block(block_expr) => self.resolve_block(block_expr), + ExpressionKind::Block(block_expr) => { + HirExpression::Block(self.resolve_block(block_expr)) + } ExpressionKind::Constructor(constructor) => { let span = constructor.type_name.span(); @@ -1599,6 +1639,13 @@ impl<'a> Resolver<'a> { }) }), ExpressionKind::Parenthesized(sub_expr) => return self.resolve_expression(*sub_expr), + + // The quoted expression isn't resolved since we don't want errors if variables aren't defined + ExpressionKind::Quote(block) => HirExpression::Quote(block), + ExpressionKind::Comptime(block) => HirExpression::Comptime(self.resolve_block(block)), + ExpressionKind::Resolved(_) => unreachable!( + "ExpressionKind::Resolved should only be emitted by the comptime interpreter" + ), }; // If these lines are ever changed, make sure to change the early return @@ -1887,7 +1934,7 @@ impl<'a> Resolver<'a> { } if let Ok(ModuleDefId::TraitId(trait_id)) = - self.path_resolver.resolve(self.def_maps, trait_bound.trait_path.clone()) + self.resolve_path(trait_bound.trait_path.clone()) { let the_trait = self.interner.get_trait(trait_id); if let Some(method) = @@ -1922,21 +1969,27 @@ impl<'a> Resolver<'a> { } fn resolve_path(&mut self, path: Path) -> Result { - self.path_resolver.resolve(self.def_maps, path).map_err(ResolverError::PathResolutionError) + let path_resolution = self.path_resolver.resolve(self.def_maps, path)?; + + if let Some(error) = path_resolution.error { + self.push_err(error.into()); + } + + Ok(path_resolution.module_def_id) } - fn resolve_block(&mut self, block_expr: BlockExpression) -> HirExpression { + fn resolve_block(&mut self, block_expr: BlockExpression) -> HirBlockExpression { let statements = self - .in_new_scope(|this| vecmap(block_expr.statements, |stmt| this.intern_stmt(stmt.kind))); - HirExpression::Block(HirBlockExpression { is_unsafe: block_expr.is_unsafe, statements }) + .in_new_scope(|this| vecmap(block_expr.statements, |stmt| this.intern_stmt(stmt))); + HirBlockExpression { is_unsafe: block_expr.is_unsafe, statements } } pub fn intern_block(&mut self, block: BlockExpression) -> ExprId { - let hir_block = self.resolve_block(block); + let hir_block = HirExpression::Block(self.resolve_block(block)); self.interner.push_expr(hir_block) } - fn eval_global_as_array_length(&mut self, global: GlobalId, path: &Path) -> u64 { + fn eval_global_as_array_length(&mut self, global: GlobalId, path: &Path) -> u32 { let Some(stmt) = self.interner.get_global_let_statement(global) else { let path = path.clone(); self.push_err(ResolverError::NoSuchNumericTypeVariable { path }); @@ -1961,10 +2014,76 @@ impl<'a> Resolver<'a> { rhs: ExprId, span: Span, ) -> Result> { + // Arbitrary amount of recursive calls to try before giving up + let fuel = 100; + self.try_eval_array_length_id_with_fuel(rhs, span, fuel) + } + + fn try_eval_array_length_id_with_fuel( + &self, + rhs: ExprId, + span: Span, + fuel: u32, + ) -> Result> { + if fuel == 0 { + // If we reach here, it is likely from evaluating cyclic globals. We expect an error to + // be issued for them after name resolution so issue no error now. + return Err(None); + } + match self.interner.expression(&rhs) { HirExpression::Literal(HirLiteral::Integer(int, false)) => { int.try_into_u128().ok_or(Some(ResolverError::IntegerTooLarge { span })) } + HirExpression::Ident(ident, _) => { + let definition = self.interner.definition(ident.id); + match definition.kind { + DefinitionKind::Global(global_id) => { + let let_statement = self.interner.get_global_let_statement(global_id); + if let Some(let_statement) = let_statement { + let expression = let_statement.expression; + self.try_eval_array_length_id_with_fuel(expression, span, fuel - 1) + } else { + Err(Some(ResolverError::InvalidArrayLengthExpr { span })) + } + } + _ => Err(Some(ResolverError::InvalidArrayLengthExpr { span })), + } + } + HirExpression::Infix(infix) => { + let lhs = self.try_eval_array_length_id_with_fuel(infix.lhs, span, fuel - 1)?; + let rhs = self.try_eval_array_length_id_with_fuel(infix.rhs, span, fuel - 1)?; + + match infix.operator.kind { + BinaryOpKind::Add => Ok(lhs + rhs), + BinaryOpKind::Subtract => Ok(lhs - rhs), + BinaryOpKind::Multiply => Ok(lhs * rhs), + BinaryOpKind::Divide => Ok(lhs / rhs), + BinaryOpKind::Equal => Ok((lhs == rhs) as u128), + BinaryOpKind::NotEqual => Ok((lhs != rhs) as u128), + BinaryOpKind::Less => Ok((lhs < rhs) as u128), + BinaryOpKind::LessEqual => Ok((lhs <= rhs) as u128), + BinaryOpKind::Greater => Ok((lhs > rhs) as u128), + BinaryOpKind::GreaterEqual => Ok((lhs >= rhs) as u128), + BinaryOpKind::And => Ok(lhs & rhs), + BinaryOpKind::Or => Ok(lhs | rhs), + BinaryOpKind::Xor => Ok(lhs ^ rhs), + BinaryOpKind::ShiftRight => Ok(lhs >> rhs), + BinaryOpKind::ShiftLeft => Ok(lhs << rhs), + BinaryOpKind::Modulo => Ok(lhs % rhs), + } + } + HirExpression::Cast(cast) => { + let lhs = self.try_eval_array_length_id_with_fuel(cast.lhs, span, fuel - 1)?; + let lhs_value = Value::Field(lhs.into()); + let evaluated_value = + Interpreter::evaluate_cast_one_step(&cast, rhs, lhs_value, self.interner) + .map_err(|error| Some(ResolverError::ArrayLengthInterpreter { error }))?; + + evaluated_value + .to_u128() + .ok_or_else(|| Some(ResolverError::InvalidArrayLengthExpr { span })) + } _other => Err(Some(ResolverError::InvalidArrayLengthExpr { span })), } } @@ -1981,7 +2100,7 @@ impl<'a> Resolver<'a> { let variable = scope_tree.find(ident_name); if let Some((old_value, _)) = variable { old_value.num_times_used += 1; - let ident = HirExpression::Ident(old_value.ident.clone()); + let ident = HirExpression::Ident(old_value.ident.clone(), None); let expr_id = self.interner.push_expr(ident); self.interner.push_expr_location(expr_id, call_expr_span, self.file); fmt_str_idents.push(expr_id); @@ -2000,86 +2119,12 @@ impl<'a> Resolver<'a> { HirLiteral::FmtStr(str, fmt_str_idents) } - /// Only sized types are valid to be used as main's parameters or the parameters to a contract - /// function. If the given type is not sized (e.g. contains a slice or NamedGeneric type), an - /// error is issued. - fn verify_type_valid_for_program_input(&mut self, typ: &UnresolvedType) { - match &typ.typ { - UnresolvedTypeData::FieldElement - | UnresolvedTypeData::Integer(_, _) - | UnresolvedTypeData::Bool - | UnresolvedTypeData::Unit - | UnresolvedTypeData::Error => (), - - UnresolvedTypeData::MutableReference(_) - | UnresolvedTypeData::Function(_, _, _) - | UnresolvedTypeData::FormatString(_, _) - | UnresolvedTypeData::TraitAsType(..) - | UnresolvedTypeData::Unspecified => { - let span = typ.span.expect("Function parameters should always have spans"); - self.push_err(ResolverError::InvalidTypeForEntryPoint { span }); - } - - UnresolvedTypeData::Array(length, element) => { - if let Some(length) = length { - self.verify_type_expression_valid_for_program_input(length); - } else { - let span = typ.span.expect("Function parameters should always have spans"); - self.push_err(ResolverError::InvalidTypeForEntryPoint { span }); - } - self.verify_type_valid_for_program_input(element); - } - UnresolvedTypeData::Expression(expression) => { - self.verify_type_expression_valid_for_program_input(expression); - } - UnresolvedTypeData::String(length) => { - if let Some(length) = length { - self.verify_type_expression_valid_for_program_input(length); - } else { - let span = typ.span.expect("Function parameters should always have spans"); - self.push_err(ResolverError::InvalidTypeForEntryPoint { span }); - } - } - UnresolvedTypeData::Named(path, generics, _) => { - // Since the type is named, we need to resolve it to see what it actually refers to - // in order to check whether it is valid. Since resolving it may lead to a - // resolution error, we have to truncate our error count to the previous count just - // in case. This is to ensure resolution errors are not issued twice when this type - // is later resolved properly. - let error_count = self.errors.len(); - let resolved = self.resolve_named_type(path.clone(), generics.clone(), &mut vec![]); - self.errors.truncate(error_count); - - if !resolved.is_valid_for_program_input() { - let span = typ.span.expect("Function parameters should always have spans"); - self.push_err(ResolverError::InvalidTypeForEntryPoint { span }); - } - } - UnresolvedTypeData::Tuple(elements) => { - for element in elements { - self.verify_type_valid_for_program_input(element); - } - } - UnresolvedTypeData::Parenthesized(typ) => self.verify_type_valid_for_program_input(typ), + fn check_break_continue(&mut self, is_break: bool, span: Span) { + if !self.in_unconstrained_fn { + self.push_err(ResolverError::JumpInConstrainedFn { is_break, span }); } - } - - fn verify_type_expression_valid_for_program_input(&mut self, expr: &UnresolvedTypeExpression) { - match expr { - UnresolvedTypeExpression::Constant(_, _) => (), - UnresolvedTypeExpression::Variable(path) => { - let error_count = self.errors.len(); - let resolved = self.resolve_named_type(path.clone(), vec![], &mut vec![]); - self.errors.truncate(error_count); - - if !resolved.is_valid_for_program_input() { - self.push_err(ResolverError::InvalidTypeForEntryPoint { span: path.span() }); - } - } - UnresolvedTypeExpression::BinaryOperation(lhs, _, rhs, _) => { - self.verify_type_expression_valid_for_program_input(lhs); - self.verify_type_expression_valid_for_program_input(rhs); - } + if self.nested_loops == 0 { + self.push_err(ResolverError::JumpOutsideLoop { is_break, span }); } } } @@ -2095,7 +2140,7 @@ pub fn verify_mutable_reference(interner: &NodeInterner, rhs: ExprId) -> Result< let span = interner.expr_span(&rhs); Err(ResolverError::MutableReferenceToArrayElement { span }) } - HirExpression::Ident(ident) => { + HirExpression::Ident(ident, _) => { if let Some(definition) = interner.try_definition(ident.id) { if !definition.mutable { return Err(ResolverError::MutableReferenceToImmutableVariable { diff --git a/compiler/noirc_frontend/src/hir/resolution/structs.rs b/compiler/noirc_frontend/src/hir/resolution/structs.rs index ed7aa86e718..f62e5589d74 100644 --- a/compiler/noirc_frontend/src/hir/resolution/structs.rs +++ b/compiler/noirc_frontend/src/hir/resolution/structs.rs @@ -3,6 +3,7 @@ use std::collections::BTreeMap; use fm::FileId; use iter_extended::vecmap; +use crate::ast::Ident; use crate::{ graph::CrateId, hir::{ @@ -11,7 +12,7 @@ use crate::{ Context, }, node_interner::StructId, - Generics, Ident, Type, + Generics, Type, }; use super::{errors::ResolverError, path_resolver::StandardPathResolver, resolver::Resolver}; diff --git a/compiler/noirc_frontend/src/hir/resolution/traits.rs b/compiler/noirc_frontend/src/hir/resolution/traits.rs index 8f966be312b..3d355fd4447 100644 --- a/compiler/noirc_frontend/src/hir/resolution/traits.rs +++ b/compiler/noirc_frontend/src/hir/resolution/traits.rs @@ -4,13 +4,12 @@ use fm::FileId; use iter_extended::vecmap; use noirc_errors::Location; +use crate::ast::{ItemVisibility, Path, TraitItem}; use crate::{ graph::CrateId, hir::{ def_collector::{ - dc_crate::{ - check_methods_signatures, CompilationError, UnresolvedTrait, UnresolvedTraitImpl, - }, + dc_crate::{CompilationError, UnresolvedTrait, UnresolvedTraitImpl}, errors::{DefCollectorErrorKind, DuplicateType}, }, def_map::{CrateDefMap, ModuleDefId, ModuleId}, @@ -18,11 +17,12 @@ use crate::{ }, hir_def::traits::{TraitConstant, TraitFunction, TraitImpl, TraitType}, node_interner::{FuncId, NodeInterner, TraitId}, - Generics, Path, Shared, TraitItem, Type, TypeVariable, TypeVariableKind, + Generics, Shared, Type, TypeVariable, TypeVariableKind, }; use super::{ functions, get_module_mut, get_struct_type, + import::{PathResolution, PathResolutionError}, path_resolver::{PathResolver, StandardPathResolver}, resolver::Resolver, take_errors, @@ -124,6 +124,7 @@ fn resolve_trait_methods( let mut resolver = Resolver::new(interner, &path_resolver, def_maps, file); resolver.add_generics(generics); + resolver.add_existing_generics(&unresolved_trait.trait_def.generics, trait_generics); resolver.add_existing_generic("Self", name_span, self_typevar); resolver.set_self_type(Some(self_type.clone())); @@ -131,6 +132,7 @@ fn resolve_trait_methods( let func_id = unresolved_trait.method_ids[&name.0.contents]; let (_, func_meta) = resolver.resolve_trait_function( name, + generics, parameters, return_type, where_clause, @@ -206,16 +208,16 @@ fn collect_trait_impl_methods( if overrides.is_empty() { if let Some(default_impl) = &method.default_impl { + // copy 'where' clause from unresolved trait impl + let mut default_impl_clone = default_impl.clone(); + default_impl_clone.def.where_clause.extend(trait_impl.where_clause.clone()); + let func_id = interner.push_empty_fn(); let module = ModuleId { local_id: trait_impl.module_id, krate: crate_id }; let location = Location::new(default_impl.def.span, trait_impl.file_id); interner.push_function(func_id, &default_impl.def, module, location); func_ids_in_trait.insert(func_id); - ordered_methods.push(( - method.default_impl_module_id, - func_id, - *default_impl.clone(), - )); + ordered_methods.push((method.default_impl_module_id, func_id, *default_impl_clone)); } else { let error = DefCollectorErrorKind::TraitMissingMethod { trait_name: interner.get_trait(trait_id).name.clone(), @@ -275,7 +277,15 @@ fn collect_trait_impl( let module = ModuleId { local_id: trait_impl.module_id, krate: crate_id }; trait_impl.trait_id = match resolve_trait_by_path(def_maps, module, trait_impl.trait_path.clone()) { - Ok(trait_id) => Some(trait_id), + Ok((trait_id, warning)) => { + if let Some(warning) = warning { + errors.push(( + DefCollectorErrorKind::PathResolutionError(warning).into(), + trait_impl.file_id, + )); + } + Some(trait_id) + } Err(error) => { errors.push((error.into(), trait_impl.file_id)); None @@ -302,7 +312,14 @@ fn collect_trait_impl( // 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() { + if module + .declare_function( + method.name_ident().clone(), + ItemVisibility::Public, + *method_id, + ) + .is_err() + { module.remove_function(method.name_ident()); } } @@ -356,15 +373,18 @@ pub(crate) fn resolve_trait_by_path( def_maps: &BTreeMap, module: ModuleId, path: Path, -) -> Result { +) -> Result<(TraitId, Option), DefCollectorErrorKind> { let path_resolver = StandardPathResolver::new(module); match path_resolver.resolve(def_maps, path.clone()) { - Ok(ModuleDefId::TraitId(trait_id)) => Ok(trait_id), + Ok(PathResolution { module_def_id: ModuleDefId::TraitId(trait_id), error }) => { + Ok((trait_id, error)) + } Ok(_) => Err(DefCollectorErrorKind::NotATrait { not_a_trait_name: path }), Err(_) => Err(DefCollectorErrorKind::TraitNotFound { trait_path: path }), } } + pub(crate) fn resolve_trait_impls( context: &mut Context, traits: Vec, @@ -424,17 +444,6 @@ pub(crate) fn resolve_trait_impls( new_resolver.set_self_type(Some(self_type.clone())); if let Some(trait_id) = maybe_trait_id { - check_methods_signatures( - &mut new_resolver, - &impl_methods, - trait_id, - trait_impl.trait_path.span(), - trait_impl.trait_generics, - trait_impl.generics.len(), - trait_impl.file_id, - errors, - ); - let where_clause = trait_impl .where_clause .into_iter() diff --git a/compiler/noirc_frontend/src/hir/type_check/errors.rs b/compiler/noirc_frontend/src/hir/type_check/errors.rs index ff2a4977e72..d4b2be8c944 100644 --- a/compiler/noirc_frontend/src/hir/type_check/errors.rs +++ b/compiler/noirc_frontend/src/hir/type_check/errors.rs @@ -3,13 +3,10 @@ use noirc_errors::CustomDiagnostic as Diagnostic; use noirc_errors::Span; use thiserror::Error; +use crate::ast::{BinaryOpKind, FunctionReturnType, IntegerBitSize, Signedness}; use crate::hir::resolution::errors::ResolverError; use crate::hir_def::expr::HirBinaryOp; use crate::hir_def::types::Type; -use crate::BinaryOpKind; -use crate::FunctionReturnType; -use crate::IntegerBitSize; -use crate::Signedness; #[derive(Error, Debug, Clone, PartialEq, Eq)] pub enum Source { @@ -31,7 +28,7 @@ pub enum Source { Return(FunctionReturnType, Span), } -#[derive(Error, Debug, Clone, PartialEq, Eq)] +#[derive(Error, Debug, Clone)] pub enum TypeCheckError { #[error("Operator {op:?} cannot be used in a {place:?}")] OpCannotBeUsed { op: HirBinaryOp, place: &'static str, span: Span }, @@ -44,7 +41,7 @@ pub enum TypeCheckError { #[error("Expected type {expected} is not the same as {actual}")] TypeMismatchWithSource { expected: Type, actual: Type, span: Span, source: Source }, #[error("Expected {expected:?} found {found:?}")] - ArityMisMatch { expected: u16, found: u16, span: Span }, + ArityMisMatch { expected: usize, found: usize, span: Span }, #[error("Return type in a function cannot be public")] PublicReturnType { typ: Type, span: Span }, #[error("Cannot cast type {from}, 'as' is only for primitive field or integer types")] @@ -53,8 +50,10 @@ pub enum TypeCheckError { ExpectedFunction { found: Type, span: Span }, #[error("Type {lhs_type} has no member named {field_name}")] AccessUnknownMember { lhs_type: Type, field_name: String, span: Span }, - #[error("Function expects {expected} parameters but {found} given")] + #[error("Function expects {expected} parameters but {found} were given")] ParameterCountMismatch { expected: usize, found: usize, span: Span }, + #[error("{item} expects {expected} generics but {found} were given")] + GenericCountMismatch { item: String, expected: usize, found: usize, span: Span }, #[error("Only integer and Field types may be casted to")] UnsupportedCast { span: Span }, #[error("Index {index} is out of bounds for this tuple {lhs_type} of length {length}")] @@ -63,8 +62,6 @@ pub enum TypeCheckError { VariableMustBeMutable { name: String, span: Span }, #[error("No method named '{method_name}' found for type '{object_type}'")] UnresolvedMethodCall { method_name: String, object_type: Type, span: Span }, - #[error("Comparisons are invalid on Field types. Try casting the operands to a sized integer type first")] - InvalidComparisonOnField { span: Span }, #[error("Integers must have the same signedness LHS is {sign_x:?}, RHS is {sign_y:?}")] IntegerSignedness { sign_x: Signedness, sign_y: Signedness, span: Span }, #[error("Integers must have the same bit width LHS is {bit_width_x}, RHS is {bit_width_y}")] @@ -74,7 +71,7 @@ pub enum TypeCheckError { #[error("{kind} cannot be used in a unary operation")] InvalidUnaryOp { kind: String, span: Span }, #[error("Bitwise operations are invalid on Field types. Try casting the operands to a sized integer type first.")] - InvalidBitwiseOperationOnField { span: Span }, + FieldBitwiseOp { span: Span }, #[error("Integer cannot be used with type {typ}")] IntegerTypeMismatch { typ: Type, span: Span }, #[error("Cannot use an integer and a Field in a binary operation, try converting the Field into an integer first")] @@ -83,6 +80,8 @@ pub enum TypeCheckError { FieldModulo { span: Span }, #[error("Fields cannot be compared, try casting to an integer first")] FieldComparison { span: Span }, + #[error("The bit count in a bit-shift operation must fit in a u8, try casting the right hand side into a u8 first")] + InvalidShiftSize { span: Span }, #[error("The number of bits to use for this bitwise operation is ambiguous. Either the operand's type or return type should be specified")] AmbiguousBitWidth { span: Span }, #[error("Error with additional context")] @@ -116,14 +115,36 @@ pub enum TypeCheckError { 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 }, + #[error( + "Expected {expected_count} generic(s) from this function, but {actual_count} were provided" + )] + IncorrectTurbofishGenericCount { expected_count: usize, actual_count: usize, span: Span }, #[error( "Cannot pass a mutable reference from a constrained runtime to an unconstrained runtime" )] ConstrainedReferenceToUnconstrained { span: Span }, + #[error( + "Cannot pass a mutable reference from a unconstrained runtime to an constrained runtime" + )] + UnconstrainedReferenceToConstrained { span: Span }, #[error("Slices cannot be returned from an unconstrained runtime to a constrained runtime")] UnconstrainedSliceReturnToConstrained { span: Span }, #[error("unsafe")] Unsafe { span: Span }, + #[error("Slices must have constant length")] + NonConstantSliceLength { span: Span }, + #[error("Only sized types may be used in the entry point to a program")] + InvalidTypeForEntryPoint { span: Span }, + #[error("Mismatched number of parameters in trait implementation")] + MismatchTraitImplNumParameters { + actual_num_parameters: usize, + expected_num_parameters: usize, + trait_name: String, + method_name: String, + span: Span, + }, + #[error("Strings do not support indexed assignment")] + StringIndexAssign { span: Span }, } impl TypeCheckError { @@ -132,36 +153,36 @@ impl TypeCheckError { } } -impl From for Diagnostic { - fn from(error: TypeCheckError) -> Diagnostic { +impl<'a> From<&'a TypeCheckError> for Diagnostic { + fn from(error: &'a TypeCheckError) -> Diagnostic { match error { TypeCheckError::TypeCannotBeUsed { typ, place, span } => Diagnostic::simple_error( format!("The type {} cannot be used in a {}", &typ, place), String::new(), - span, + *span, ), TypeCheckError::Context { err, ctx } => { - let mut diag = Diagnostic::from(*err); - diag.add_note(ctx.to_owned()); + let mut diag = Diagnostic::from(err.as_ref()); + diag.add_note(ctx.to_string()); diag } TypeCheckError::OpCannotBeUsed { op, place, span } => Diagnostic::simple_error( format!("The operator {op:?} cannot be used in a {place}"), String::new(), - span, + *span, ), TypeCheckError::TypeMismatch { expected_typ, expr_typ, expr_span } => { Diagnostic::simple_error( format!("Expected type {expected_typ}, found type {expr_typ}"), String::new(), - expr_span, + *expr_span, ) } TypeCheckError::TraitMethodParameterTypeMismatch { method_name, expected_typ, actual_typ, parameter_index, parameter_span } => { Diagnostic::simple_error( format!("Parameter #{parameter_index} of method `{method_name}` must be of type {expected_typ}, not {actual_typ}"), String::new(), - parameter_span, + *parameter_span, ) } TypeCheckError::NonHomogeneousArray { @@ -177,21 +198,27 @@ impl From for Diagnostic { "Non homogeneous array, different element types found at indices ({first_index},{second_index})" ), format!("Found type {first_type}"), - first_span, + *first_span, ); - diag.add_secondary(format!("but then found type {second_type}"), second_span); + diag.add_secondary(format!("but then found type {second_type}"), *second_span); diag } TypeCheckError::ArityMisMatch { expected, found, span } => { - let plural = if expected == 1 { "" } else { "s" }; + let plural = if *expected == 1 { "" } else { "s" }; let msg = format!("Expected {expected} argument{plural}, but found {found}"); - Diagnostic::simple_error(msg, String::new(), span) + Diagnostic::simple_error(msg, String::new(), *span) } TypeCheckError::ParameterCountMismatch { expected, found, span } => { - let empty_or_s = if expected == 1 { "" } else { "s" }; - let was_or_were = if found == 1 { "was" } else { "were" }; + let empty_or_s = if *expected == 1 { "" } else { "s" }; + let was_or_were = if *found == 1 { "was" } else { "were" }; let msg = format!("Function expects {expected} parameter{empty_or_s} but {found} {was_or_were} given"); - Diagnostic::simple_error(msg, String::new(), span) + Diagnostic::simple_error(msg, String::new(), *span) + } + TypeCheckError::GenericCountMismatch { item, expected, found, span } => { + let empty_or_s = if *expected == 1 { "" } else { "s" }; + let was_or_were = if *found == 1 { "was" } else { "were" }; + let msg = format!("{item} expects {expected} generic{empty_or_s} but {found} {was_or_were} given"); + Diagnostic::simple_error(msg, String::new(), *span) } TypeCheckError::InvalidCast { span, .. } | TypeCheckError::ExpectedFunction { span, .. } @@ -200,12 +227,11 @@ impl From for Diagnostic { | TypeCheckError::TupleIndexOutOfBounds { span, .. } | TypeCheckError::VariableMustBeMutable { span, .. } | TypeCheckError::UnresolvedMethodCall { span, .. } - | TypeCheckError::InvalidComparisonOnField { span } | TypeCheckError::IntegerSignedness { span, .. } | TypeCheckError::IntegerBitWidth { span, .. } | TypeCheckError::InvalidInfixOp { span, .. } | TypeCheckError::InvalidUnaryOp { span, .. } - | TypeCheckError::InvalidBitwiseOperationOnField { span, .. } + | TypeCheckError::FieldBitwiseOp { span, .. } | TypeCheckError::IntegerTypeMismatch { span, .. } | TypeCheckError::FieldComparison { span, .. } | TypeCheckError::AmbiguousBitWidth { span, .. } @@ -213,18 +239,22 @@ impl From for Diagnostic { | TypeCheckError::OverflowingAssignment { span, .. } | TypeCheckError::FieldModulo { span } | TypeCheckError::ConstrainedReferenceToUnconstrained { span } - | TypeCheckError::UnconstrainedSliceReturnToConstrained { span } | TypeCheckError::Unsafe { span } => { - Diagnostic::simple_error(error.to_string(), String::new(), span) + | TypeCheckError::UnconstrainedReferenceToConstrained { span } + | TypeCheckError::UnconstrainedSliceReturnToConstrained { span } | TypeCheckError::Unsafe { span } + | TypeCheckError::NonConstantSliceLength { span } + | TypeCheckError::StringIndexAssign { span } + | TypeCheckError::InvalidShiftSize { span } => { + Diagnostic::simple_error(error.to_string(), String::new(), *span) } TypeCheckError::PublicReturnType { typ, span } => Diagnostic::simple_error( "Functions cannot declare a public return type".to_string(), format!("return type is {typ}"), - span, + *span, ), TypeCheckError::TypeAnnotationsNeeded { span } => Diagnostic::simple_error( "Expression type is ambiguous".to_string(), "Type must be known at this point".to_string(), - span, + *span, ), TypeCheckError::ResolverError(error) => error.into(), TypeCheckError::TypeMismatchWithSource { expected, actual, span, source } => { @@ -250,30 +280,30 @@ impl From for Diagnostic { diagnostic.add_note(format!("help: try adding a return type: `-> {actual}`")); } - diagnostic.add_secondary(format!("{actual} returned here"), expr_span); + diagnostic.add_secondary(format!("{actual} returned here"), *expr_span); return diagnostic }, }; - Diagnostic::simple_error(message, String::new(), span) + Diagnostic::simple_error(message, String::new(), *span) } TypeCheckError::CallDeprecated { span, ref note, .. } => { let primary_message = error.to_string(); let secondary_message = note.clone().unwrap_or_default(); - Diagnostic::simple_warning(primary_message, secondary_message, span) + Diagnostic::simple_warning(primary_message, secondary_message, *span) } TypeCheckError::UnusedResultError { expr_type, expr_span } => { let msg = format!("Unused expression result of type {expr_type}"); - Diagnostic::simple_warning(msg, String::new(), expr_span) + 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); + 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..] { @@ -284,8 +314,29 @@ impl From for 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) + Diagnostic::simple_warning(msg, "Unnecessary trait constraint in where clause".into(), *span) + } + TypeCheckError::InvalidTypeForEntryPoint { span } => Diagnostic::simple_error( + "Only sized types may be used in the entry point to a program".to_string(), + "Slices, references, or any type containing them may not be used in main, contract functions, or foldable functions".to_string(), *span), + TypeCheckError::MismatchTraitImplNumParameters { + expected_num_parameters, + actual_num_parameters, + trait_name, + method_name, + span, + } => { + let plural = if *expected_num_parameters == 1 { "" } else { "s" }; + let primary_message = format!( + "`{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) } + TypeCheckError::IncorrectTurbofishGenericCount { expected_count, actual_count, span } => { + let expected_plural = if *expected_count == 1 { "" } else { "s" }; + let actual_plural = if *actual_count == 1 { "was" } else { "were" }; + let msg = format!("Expected {expected_count} generic{expected_plural} from this function, but {actual_count} {actual_plural} provided"); + Diagnostic::simple_error(msg, "".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 c073f90a14f..d6618e73d0d 100644 --- a/compiler/noirc_frontend/src/hir/type_check/expr.rs +++ b/compiler/noirc_frontend/src/hir/type_check/expr.rs @@ -1,24 +1,27 @@ use iter_extended::vecmap; use noirc_errors::Span; +use crate::ast::{BinaryOpKind, IntegerBitSize, UnaryOp}; +use crate::hir_def::expr::HirCallExpression; +use crate::macros_api::Signedness; use crate::{ hir::{resolution::resolver::verify_mutable_reference, type_check::errors::Source}, hir_def::{ expr::{ - self, HirArrayLiteral, HirBinaryOp, HirExpression, HirIdent, HirLiteral, - HirMethodCallExpression, HirMethodReference, HirPrefixExpression, ImplKind, + self, HirArrayLiteral, HirBinaryOp, HirBlockExpression, HirExpression, HirIdent, + HirLiteral, HirMethodCallExpression, HirMethodReference, HirPrefixExpression, ImplKind, }, types::Type, }, node_interner::{DefinitionKind, ExprId, FuncId, TraitId, TraitImplKind, TraitMethodId}, - BinaryOpKind, TypeBinding, TypeBindings, TypeVariableKind, UnaryOp, + TypeBinding, TypeBindings, TypeVariableKind, }; use super::{errors::TypeCheckError, TypeChecker}; impl<'interner> TypeChecker<'interner> { fn check_if_deprecated(&mut self, expr: &ExprId) { - if let HirExpression::Ident(expr::HirIdent { location, id, impl_kind: _ }) = + if let HirExpression::Ident(expr::HirIdent { location, id, impl_kind: _ }, _) = self.interner.expression(expr) { if let Some(DefinitionKind::Function(func_id)) = @@ -37,7 +40,7 @@ impl<'interner> TypeChecker<'interner> { } fn is_unconstrained_call(&self, expr: &ExprId) -> bool { - if let HirExpression::Ident(expr::HirIdent { id, .. }) = self.interner.expression(expr) { + if let HirExpression::Ident(expr::HirIdent { id, .. }, _) = self.interner.expression(expr) { if let Some(DefinitionKind::Function(func_id)) = self.interner.try_definition(id).map(|def| &def.kind) { @@ -48,6 +51,49 @@ impl<'interner> TypeChecker<'interner> { false } + fn check_hir_array_literal( + &mut self, + hir_array_literal: HirArrayLiteral, + ) -> (Result>, Box) { + match hir_array_literal { + HirArrayLiteral::Standard(arr) => { + let elem_types = vecmap(&arr, |arg| self.check_expression(arg)); + + let first_elem_type = elem_types + .first() + .cloned() + .unwrap_or_else(|| self.interner.next_type_variable()); + + // Check if the array is homogeneous + for (index, elem_type) in elem_types.iter().enumerate().skip(1) { + let location = self.interner.expr_location(&arr[index]); + + elem_type.unify(&first_elem_type, &mut self.errors, || { + TypeCheckError::NonHomogeneousArray { + first_span: self.interner.expr_location(&arr[0]).span, + first_type: first_elem_type.to_string(), + first_index: index, + second_span: location.span, + second_type: elem_type.to_string(), + second_index: index + 1, + } + .add_context("elements in an array must have the same type") + }); + } + + (Ok(arr.len() as u32), Box::new(first_elem_type.clone())) + } + HirArrayLiteral::Repeated { repeated_element, length } => { + let elem_type = self.check_expression(&repeated_element); + let length = match length { + Type::Constant(length) => Ok(length), + other => Err(Box::new(other)), + }; + (length, Box::new(elem_type)) + } + } + } + /// Infers a type for a given expression, and return this type. /// As a side-effect, this function will also remember this type in the NodeInterner /// for the given expr_id key. @@ -58,65 +104,43 @@ impl<'interner> TypeChecker<'interner> { /// function `foo` to refer to. pub(crate) fn check_expression(&mut self, expr_id: &ExprId) -> Type { let typ = match self.interner.expression(expr_id) { - HirExpression::Ident(ident) => self.check_ident(ident, expr_id), - HirExpression::Literal(literal) => { - match literal { - HirLiteral::Array(HirArrayLiteral::Standard(arr)) => { - let elem_types = vecmap(&arr, |arg| self.check_expression(arg)); - - let first_elem_type = elem_types - .first() - .cloned() - .unwrap_or_else(|| self.interner.next_type_variable()); - - let arr_type = Type::Array( - Box::new(Type::constant_variable(arr.len() as u64, self.interner)), - Box::new(first_elem_type.clone()), - ); - - // Check if the array is homogeneous - for (index, elem_type) in elem_types.iter().enumerate().skip(1) { - let location = self.interner.expr_location(&arr[index]); - - elem_type.unify(&first_elem_type, &mut self.errors, || { - TypeCheckError::NonHomogeneousArray { - first_span: self.interner.expr_location(&arr[0]).span, - first_type: first_elem_type.to_string(), - first_index: index, - second_span: location.span, - second_type: elem_type.to_string(), - second_index: index + 1, - } - .add_context("elements in an array must have the same type") + HirExpression::Ident(ident, generics) => self.check_ident(ident, expr_id, generics), + HirExpression::Literal(literal) => match literal { + HirLiteral::Array(hir_array_literal) => { + let (length, elem_type) = self.check_hir_array_literal(hir_array_literal); + Type::Array( + length.map_or_else( + |typ| typ, + |constant| Box::new(Type::constant_variable(constant, self.interner)), + ), + elem_type, + ) + } + HirLiteral::Slice(hir_array_literal) => { + let (length_type, elem_type) = self.check_hir_array_literal(hir_array_literal); + match length_type { + Ok(_length) => Type::Slice(elem_type), + Err(_non_constant) => { + self.errors.push(TypeCheckError::NonConstantSliceLength { + span: self.interner.expr_span(expr_id), }); + Type::Error } - - arr_type } - HirLiteral::Array(HirArrayLiteral::Repeated { repeated_element, length }) => { - let elem_type = self.check_expression(&repeated_element); - let length = match length { - Type::Constant(length) => { - Type::constant_variable(length, self.interner) - } - other => other, - }; - Type::Array(Box::new(length), Box::new(elem_type)) - } - HirLiteral::Bool(_) => Type::Bool, - HirLiteral::Integer(_, _) => Type::polymorphic_integer_or_field(self.interner), - HirLiteral::Str(string) => { - let len = Type::Constant(string.len() as u64); - Type::String(Box::new(len)) - } - HirLiteral::FmtStr(string, idents) => { - let len = Type::Constant(string.len() as u64); - let types = vecmap(&idents, |elem| self.check_expression(elem)); - Type::FmtString(Box::new(len), Box::new(Type::Tuple(types))) - } - HirLiteral::Unit => Type::Unit, } - } + HirLiteral::Bool(_) => Type::Bool, + HirLiteral::Integer(_, _) => self.polymorphic_integer_or_field(), + HirLiteral::Str(string) => { + let len = Type::Constant(string.len() as u32); + Type::String(Box::new(len)) + } + HirLiteral::FmtStr(string, idents) => { + let len = Type::Constant(string.len() as u32); + let types = vecmap(&idents, |elem| self.check_expression(elem)); + Type::FmtString(Box::new(len), Box::new(Type::Tuple(types))) + } + HirLiteral::Unit => Type::Unit, + }, HirExpression::Infix(infix_expr) => { // The type of the infix expression must be looked up from a type table let lhs_type = self.check_expression(&infix_expr.lhs); @@ -131,14 +155,16 @@ impl<'interner> TypeChecker<'interner> { Ok((typ, use_impl)) => { if use_impl { let id = infix_expr.trait_method_id; - // Assume operators have no trait generics - self.verify_trait_constraint( - &lhs_type, - id.trait_id, - &[], - *expr_id, - span, - ); + + // Delay checking the trait constraint until the end of the function. + // Checking it now could bind an unbound type variable to any type + // that implements the trait. + let constraint = crate::hir_def::traits::TraitConstraint { + typ: lhs_type.clone(), + trait_id: id.trait_id, + trait_generics: Vec::new(), + }; + self.trait_constraints.push((constraint, *expr_id)); self.typecheck_operator_method(*expr_id, id, &lhs_type, span); } typ @@ -151,16 +177,6 @@ impl<'interner> TypeChecker<'interner> { } HirExpression::Index(index_expr) => self.check_index_expression(expr_id, index_expr), HirExpression::Call(call_expr) => { - // Need to setup these flags here as `self` is borrowed mutably to type check the rest of the call expression - // These flags are later used to type check calls to unconstrained functions from constrained functions - let current_func = self.current_function; - let func_mod = current_func.map(|func| self.interner.function_modifiers(&func)); - let is_current_func_constrained = - func_mod.map_or(true, |func_mod| !func_mod.is_unconstrained); - let is_unconstrained_call = self.is_unconstrained_call(&call_expr.func); - - self.check_if_deprecated(&call_expr.func); - let function = self.check_expression(&call_expr.func); let args = vecmap(&call_expr.arguments, |arg| { @@ -168,42 +184,13 @@ impl<'interner> TypeChecker<'interner> { (typ, *arg, self.interner.expr_span(arg)) }); - if is_current_func_constrained && is_unconstrained_call { - if !self.allow_unsafe { - self.errors.push(TypeCheckError::Unsafe { - span: self.interner.expr_span(expr_id), - }); - return Type::Error; - } - - // Check that we are not passing a mutable reference from a constrained runtime to an unconstrained runtime - for (typ, _, _) in args.iter() { - if matches!(&typ.follow_bindings(), Type::MutableReference(_)) { - self.errors.push(TypeCheckError::ConstrainedReferenceToUnconstrained { - span: self.interner.expr_span(expr_id), - }); - return Type::Error; - } - } - } - let span = self.interner.expr_span(expr_id); - let return_type = self.bind_function_type(function, args, span); - - // Check that we are not passing a slice from an unconstrained runtime to a constrained runtime - if is_current_func_constrained - && is_unconstrained_call - && return_type.contains_slice() - { - self.errors.push(TypeCheckError::UnconstrainedSliceReturnToConstrained { - span: self.interner.expr_span(expr_id), - }); - return Type::Error; - } - - return_type + self.check_call(&call_expr, function, args, span) } HirExpression::MethodCall(mut method_call) => { + let method_call_span = self.interner.expr_span(expr_id); + let object = method_call.object; + let object_span = self.interner.expr_span(&method_call.object); let mut object_type = self.check_expression(&method_call.object).follow_bindings(); let method_name = method_call.method.0.contents.as_str(); match self.lookup_method(&object_type, method_name, expr_id) { @@ -214,32 +201,65 @@ impl<'interner> TypeChecker<'interner> { // Automatically add `&mut` if the method expects a mutable reference and // the object is not already one. - if let HirMethodReference::FuncId(func_id) = &method_ref { - if *func_id != FuncId::dummy_id() { - let function_type = - self.interner.function_meta(func_id).typ.clone(); - - self.try_add_mutable_reference_to_object( - &mut method_call, - &function_type, - &mut object_type, - ); + let func_id = match &method_ref { + HirMethodReference::FuncId(func_id) => *func_id, + HirMethodReference::TraitMethodId(method_id, _) => { + let id = self.interner.trait_method_id(*method_id); + let definition = self.interner.definition(id); + let DefinitionKind::Function(func_id) = definition.kind else { + unreachable!( + "Expected trait function to be a DefinitionKind::Function" + ) + }; + func_id } + }; + + if func_id != FuncId::dummy_id() { + let function_type = self.interner.function_meta(&func_id).typ.clone(); + self.try_add_mutable_reference_to_object( + &mut method_call, + &function_type, + &mut object_type, + ); + } + + // These arguments will be given to the desugared function call. + // Compared to the method arguments, they also contain the object. + let mut function_args = Vec::with_capacity(method_call.arguments.len() + 1); + + function_args.push((object_type.clone(), object, object_span)); + + for arg in method_call.arguments.iter() { + let span = self.interner.expr_span(arg); + let typ = self.check_expression(arg); + function_args.push((typ, *arg, span)); } // TODO: update object_type here? - let function_call = method_call.into_function_call( + let ((function_id, _), function_call) = method_call.into_function_call( &method_ref, object_type, location, self.interner, ); - self.interner.replace_expr(expr_id, function_call); + let func_type = self.check_expression(&function_id); // Type check the new call now that it has been changed from a method call // to a function call. This way we avoid duplicating code. - self.check_expression(expr_id) + // We call `check_call` rather than `check_expression` directly as we want to avoid + // resolving the object type again once it is part of the arguments. + let typ = self.check_call( + &function_call, + func_type, + function_args, + method_call_span, + ); + + self.interner.replace_expr(expr_id, HirExpression::Call(function_call)); + + typ } None => Type::Error, } @@ -250,44 +270,7 @@ impl<'interner> TypeChecker<'interner> { let span = self.interner.expr_span(expr_id); self.check_cast(lhs_type, cast_expr.r#type, span) } - HirExpression::Block(block_expr) => { - let mut block_type = Type::Unit; - - // Before entering the block we cache the old value of `allow_unsafe` so it can be restored. - let old_allow_unsafe = self.allow_unsafe; - - // If we're already in an unsafe block then entering a new block should preserve this even if - // the inner block isn't marked as unsafe. - self.allow_unsafe |= block_expr.is_unsafe; - - let statements = block_expr.statements(); - for (i, stmt) in statements.iter().enumerate() { - let expr_type = self.check_statement(stmt); - - if let crate::hir_def::stmt::HirStatement::Semi(expr) = - self.interner.statement(stmt) - { - let inner_expr_type = self.interner.id_type(expr); - let span = self.interner.expr_span(&expr); - - self.unify(&inner_expr_type, &Type::Unit, || { - TypeCheckError::UnusedResultError { - expr_type: inner_expr_type.clone(), - expr_span: span, - } - }); - } - - if i + 1 == statements.len() { - block_type = expr_type; - } - } - - // Finally, we restore the original value of `self.allow_unsafe`. - self.allow_unsafe = old_allow_unsafe; - - block_type - } + HirExpression::Block(block_expr) => self.check_block(block_expr), HirExpression::Prefix(prefix_expr) => { let rhs_type = self.check_expression(&prefix_expr.rhs); let span = self.interner.expr_span(&prefix_expr.rhs); @@ -324,26 +307,130 @@ impl<'interner> TypeChecker<'interner> { Type::Function(params, Box::new(lambda.return_type), Box::new(env_type)) } + HirExpression::Quote(_) => Type::Code, + HirExpression::Comptime(block) => self.check_block(block), + + // Unquote should be inserted & removed by the comptime interpreter. + // Even if we allowed it here, we wouldn't know what type to give to the result. + HirExpression::Unquote(block) => { + unreachable!("Unquote remaining during type checking {block}") + } }; self.interner.push_expr_type(*expr_id, typ.clone()); typ } + fn check_call( + &mut self, + call: &HirCallExpression, + func_type: Type, + args: Vec<(Type, ExprId, Span)>, + span: Span, + ) -> Type { + // Need to setup these flags here as `self` is borrowed mutably to type check the rest of the call expression + // These flags are later used to type check calls to unconstrained functions from constrained functions + let func_mod = self.current_function.map(|func| self.interner.function_modifiers(&func)); + let is_current_func_constrained = + func_mod.map_or(true, |func_mod| !func_mod.is_unconstrained); + + let is_unconstrained_call = self.is_unconstrained_call(&call.func); + self.check_if_deprecated(&call.func); + + // Check that we are not passing a mutable reference from a constrained runtime to an unconstrained runtime + if is_current_func_constrained && is_unconstrained_call { + if !self.allow_unsafe { + self.errors.push(TypeCheckError::Unsafe {span}); + return Type::Error; + } + for (typ, _, _) in args.iter() { + if matches!(&typ.follow_bindings(), Type::MutableReference(_)) { + self.errors.push(TypeCheckError::ConstrainedReferenceToUnconstrained { span }); + } + } + } + + let return_type = self.bind_function_type(func_type, args, span); + + // Check that we are not passing a slice from an unconstrained runtime to a constrained runtime + if is_current_func_constrained && is_unconstrained_call { + if return_type.contains_slice() { + self.errors.push(TypeCheckError::UnconstrainedSliceReturnToConstrained { span }); + } else if matches!(&return_type.follow_bindings(), Type::MutableReference(_)) { + self.errors.push(TypeCheckError::UnconstrainedReferenceToConstrained { span }); + } + }; + + return_type + } + + fn check_block(&mut self, block: HirBlockExpression) -> Type { + let mut block_type = Type::Unit; + + // Before entering the block we cache the old value of `allow_unsafe` so it can be restored. + let old_allow_unsafe = self.allow_unsafe; + + // If we're already in an unsafe block then entering a new block should preserve this even if + // the inner block isn't marked as unsafe. + self.allow_unsafe |= block.is_unsafe; + + let statements = block.statements(); + for (i, stmt) in statements.iter().enumerate() { + let expr_type = self.check_statement(stmt); + + if let crate::hir_def::stmt::HirStatement::Semi(expr) = self.interner.statement(stmt) { + let inner_expr_type = self.interner.id_type(expr); + let span = self.interner.expr_span(&expr); + + self.unify(&inner_expr_type, &Type::Unit, || TypeCheckError::UnusedResultError { + expr_type: inner_expr_type.clone(), + expr_span: span, + }); + } + + if i + 1 == statements.len() { + block_type = expr_type; + } + } + + // Finally, we restore the original value of `self.allow_unsafe`. + self.allow_unsafe = old_allow_unsafe; + + block_type + } + /// Returns the type of the given identifier - fn check_ident(&mut self, ident: HirIdent, expr_id: &ExprId) -> Type { + fn check_ident( + &mut self, + ident: HirIdent, + expr_id: &ExprId, + generics: Option>, + ) -> Type { let mut bindings = TypeBindings::new(); // Add type bindings from any constraints that were used. // We need to do this first since otherwise instantiating the type below // will replace each trait generic with a fresh type variable, rather than // the type used in the trait constraint (if it exists). See #4088. - if let ImplKind::TraitMethod(_, constraint, _) = &ident.impl_kind { + if let ImplKind::TraitMethod(_, constraint, assumed) = &ident.impl_kind { let the_trait = self.interner.get_trait(constraint.trait_id); assert_eq!(the_trait.generics.len(), constraint.trait_generics.len()); for (param, arg) in the_trait.generics.iter().zip(&constraint.trait_generics) { - bindings.insert(param.id(), (param.clone(), arg.clone())); + // Avoid binding t = t + if !arg.occurs(param.id()) { + bindings.insert(param.id(), (param.clone(), arg.clone())); + } + } + + // If the trait impl is already assumed to exist we should add any type bindings for `Self`. + // Otherwise `self` will be replaced with a fresh type variable, which will require the user + // to specify a redundant type annotation. + if *assumed { + bindings.insert( + the_trait.self_type_typevar_id, + (the_trait.self_type_typevar.clone(), constraint.typ.clone()), + ); } } @@ -353,17 +440,25 @@ impl<'interner> TypeChecker<'interner> { // variable to handle generic functions. let t = self.interner.id_type_substitute_trait_as_type(ident.id); + let definition = self.interner.try_definition(ident.id); + let function_generic_count = definition.map_or(0, |definition| match &definition.kind { + DefinitionKind::Function(function) => { + self.interner.function_modifiers(function).generic_count + } + _ => 0, + }); + + let span = self.interner.expr_span(expr_id); // This instantiates a trait's generics as well which need to be set // when the constraint below is later solved for when the function is // finished. How to link the two? - let (typ, bindings) = t.instantiate_with_bindings(bindings, self.interner); + let (typ, bindings) = self.instantiate(t, bindings, generics, function_generic_count, span); // 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); - + if let DefinitionKind::Function(func_id) = definition.kind { + let function = self.interner.function_meta(&func_id); for mut constraint in function.trait_constraints.clone() { constraint.apply_bindings(&bindings); self.trait_constraints.push((constraint, *expr_id)); @@ -391,6 +486,37 @@ impl<'interner> TypeChecker<'interner> { typ } + fn instantiate( + &mut self, + typ: Type, + bindings: TypeBindings, + turbofish_generics: Option>, + function_generic_count: usize, + span: Span, + ) -> (Type, TypeBindings) { + match turbofish_generics { + Some(turbofish_generics) => { + if turbofish_generics.len() != function_generic_count { + self.errors.push(TypeCheckError::IncorrectTurbofishGenericCount { + expected_count: function_generic_count, + actual_count: turbofish_generics.len(), + span, + }); + typ.instantiate_with_bindings(bindings, self.interner) + } else { + // Fetch the count of any implicit generics on the function, such as + // for a method within a generic impl. + let implicit_generic_count = match &typ { + Type::Forall(generics, _) => generics.len() - function_generic_count, + _ => 0, + }; + typ.instantiate_with(turbofish_generics, self.interner, implicit_generic_count) + } + } + None => typ.instantiate_with_bindings(bindings, self.interner), + } + } + pub fn verify_trait_constraint( &mut self, object_type: &Type, @@ -404,23 +530,28 @@ impl<'interner> TypeChecker<'interner> { self.interner.select_impl_for_expression(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)?; - let mut name = r#trait.name.to_string(); - if !constraint.trait_generics.is_empty() { - let generics = vecmap(&constraint.trait_generics, ToString::to_string); - name += &format!("<{}>", generics.join(", ")); - } - Some((constraint.typ, name)) - }) - .collect::>>(); + if erroring_constraints.is_empty() { + self.errors.push(TypeCheckError::TypeAnnotationsNeeded { span }); + } else { + // 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)?; + let mut name = r#trait.name.to_string(); + if !constraint.trait_generics.is_empty() { + let generics = + vecmap(&constraint.trait_generics, ToString::to_string); + name += &format!("<{}>", generics.join(", ")); + } + Some((constraint.typ, name)) + }) + .collect::>>(); - if let Some(constraints) = constraints { - self.errors.push(TypeCheckError::NoMatchingImplFound { constraints, span }); + if let Some(constraints) = constraints { + self.errors.push(TypeCheckError::NoMatchingImplFound { constraints, span }); + } } } } @@ -495,7 +626,7 @@ impl<'interner> TypeChecker<'interner> { /// Insert as many dereference operations as necessary to automatically dereference a method /// call object to its base value type T. - fn insert_auto_dereferences(&mut self, object: ExprId, typ: Type) -> (ExprId, Type) { + pub(crate) fn insert_auto_dereferences(&mut self, object: ExprId, typ: Type) -> (ExprId, Type) { if let Type::MutableReference(element) = typ { let location = self.interner.id_location(object); @@ -546,15 +677,13 @@ impl<'interner> TypeChecker<'interner> { let index_type = self.check_expression(&index_expr.index); let span = self.interner.expr_span(&index_expr.index); - index_type.unify( - &Type::polymorphic_integer_or_field(self.interner), - &mut self.errors, - || TypeCheckError::TypeMismatch { + index_type.unify(&self.polymorphic_integer_or_field(), &mut self.errors, || { + TypeCheckError::TypeMismatch { expected_typ: "an integer".to_owned(), expr_typ: index_type.to_string(), expr_span: span, - }, - ); + } + }); // When writing `a[i]`, if `a : &mut ...` then automatically dereference `a` as many // times as needed to get the underlying array. @@ -567,6 +696,7 @@ impl<'interner> TypeChecker<'interner> { // XXX: We can check the array bounds here also, but it may be better to constant fold first // and have ConstId instead of ExprId for constants Type::Array(_, base_type) => *base_type, + Type::Slice(base_type) => *base_type, Type::Error => Type::Error, typ => { let span = self.interner.expr_span(&new_lhs); @@ -699,7 +829,7 @@ impl<'interner> TypeChecker<'interner> { let dereference_lhs = |this: &mut Self, lhs_type, element| { let old_lhs = *access_lhs; *access_lhs = this.interner.push_expr(HirExpression::Prefix(HirPrefixExpression { - operator: crate::UnaryOp::Dereference { implicitly_added: true }, + operator: crate::ast::UnaryOp::Dereference { implicitly_added: true }, rhs: old_lhs, })); this.interner.push_expr_type(old_lhs, lhs_type); @@ -823,6 +953,10 @@ impl<'interner> TypeChecker<'interner> { match (lhs_type, rhs_type) { // Avoid reporting errors multiple times (Error, _) | (_, Error) => Ok((Bool, false)), + (Alias(alias, args), other) | (other, Alias(alias, args)) => { + let alias = alias.borrow().get_type(args); + self.comparator_operand_type_rules(&alias, other, op, span) + } // Matches on TypeVariable must be first to follow any type // bindings. @@ -831,12 +965,8 @@ impl<'interner> TypeChecker<'interner> { return self.comparator_operand_type_rules(other, binding, op, span); } - self.bind_type_variables_for_infix(lhs_type, op, rhs_type, span); - Ok((Bool, false)) - } - (Alias(alias, args), other) | (other, Alias(alias, args)) => { - let alias = alias.borrow().get_type(args); - self.comparator_operand_type_rules(&alias, other, op, span) + let use_impl = self.bind_type_variables_for_infix(lhs_type, op, rhs_type, span); + Ok((Bool, use_impl)) } (Integer(sign_x, bit_width_x), Integer(sign_y, bit_width_y)) => { if sign_x != sign_y { @@ -866,30 +996,6 @@ impl<'interner> TypeChecker<'interner> { // <= and friends are technically valid for booleans, just not very useful (Bool, Bool) => Ok((Bool, false)), - // Special-case == and != for arrays - (Array(x_size, x_type), Array(y_size, y_type)) - if matches!(op.kind, BinaryOpKind::Equal | BinaryOpKind::NotEqual) => - { - self.unify(x_size, y_size, || TypeCheckError::TypeMismatchWithSource { - expected: lhs_type.clone(), - actual: rhs_type.clone(), - source: Source::ArrayLen, - span: op.location.span, - }); - - self.comparator_operand_type_rules(x_type, y_type, op, span) - } - - (String(x_size), String(y_size)) => { - self.unify(x_size, y_size, || TypeCheckError::TypeMismatchWithSource { - expected: *x_size.clone(), - actual: *y_size.clone(), - span: op.location.span, - source: Source::StringLen, - }); - - Ok((Bool, false)) - } (lhs, rhs) => { self.unify(lhs, rhs, || TypeCheckError::TypeMismatchWithSource { expected: lhs.clone(), @@ -1048,9 +1154,9 @@ impl<'interner> TypeChecker<'interner> { } ret } + // ignoring env for subtype on purpose Type::Function(parameters, ret, _env) => { - // ignoring env for subtype on purpose - self.bind_function_type_impl(parameters.as_ref(), ret.as_ref(), args.as_ref(), span) + self.bind_function_type_impl(¶meters, &ret, &args, span) } Type::Error => Type::Error, found => { @@ -1060,13 +1166,16 @@ impl<'interner> TypeChecker<'interner> { } } + /// Handles the TypeVariable case for checking binary operators. + /// Returns true if we should use the impl for the operator instead of the primitive + /// version of it. fn bind_type_variables_for_infix( &mut self, lhs_type: &Type, op: &HirBinaryOp, rhs_type: &Type, span: Span, - ) { + ) -> bool { self.unify(lhs_type, rhs_type, || TypeCheckError::TypeMismatchWithSource { expected: lhs_type.clone(), actual: rhs_type.clone(), @@ -1074,22 +1183,26 @@ impl<'interner> TypeChecker<'interner> { span, }); - // In addition to unifying both types, we also have to bind either - // the lhs or rhs to an integer type variable. This ensures if both lhs - // and rhs are type variables, that they will have the correct integer - // type variable kind instead of TypeVariableKind::Normal. - let target = if op.kind.is_valid_for_field_type() { - Type::polymorphic_integer_or_field(self.interner) - } else { - Type::polymorphic_integer(self.interner) - }; + let use_impl = !lhs_type.is_numeric(); + + // If this operator isn't valid for fields we have to possibly narrow + // TypeVariableKind::IntegerOrField to TypeVariableKind::Integer. + // Doing so also ensures a type error if Field is used. + // The is_numeric check is to allow impls for custom types to bypass this. + if !op.kind.is_valid_for_field_type() && lhs_type.is_numeric() { + let target = Type::polymorphic_integer(self.interner); + + use crate::ast::BinaryOpKind::*; + use TypeCheckError::*; + self.unify(lhs_type, &target, || match op.kind { + Less | LessEqual | Greater | GreaterEqual => FieldComparison { span }, + And | Or | Xor | ShiftRight | ShiftLeft => FieldBitwiseOp { span }, + Modulo => FieldModulo { span }, + other => unreachable!("Operator {other:?} should be valid for Field"), + }); + } - self.unify(lhs_type, &target, || TypeCheckError::TypeMismatchWithSource { - expected: lhs_type.clone(), - actual: rhs_type.clone(), - source: Source::Binary, - span, - }); + use_impl } // Given a binary operator and another type. This method will produce the output type @@ -1111,6 +1224,10 @@ impl<'interner> TypeChecker<'interner> { match (lhs_type, rhs_type) { // An error type on either side will always return an error (Error, _) | (_, Error) => Ok((Error, false)), + (Alias(alias, args), other) | (other, Alias(alias, args)) => { + let alias = alias.borrow().get_type(args); + self.infix_operand_type_rules(&alias, op, other, span) + } // Matches on TypeVariable must be first so that we follow any type // bindings. @@ -1118,17 +1235,30 @@ impl<'interner> TypeChecker<'interner> { if let TypeBinding::Bound(binding) = &*int.borrow() { return self.infix_operand_type_rules(binding, op, other, span); } - - self.bind_type_variables_for_infix(lhs_type, op, rhs_type, span); - - // Both types are unified so the choice of which to return is arbitrary - Ok((other.clone(), false)) - } - (Alias(alias, args), other) | (other, Alias(alias, args)) => { - let alias = alias.borrow().get_type(args); - self.infix_operand_type_rules(&alias, op, other, span) + if op.kind == BinaryOpKind::ShiftLeft || op.kind == BinaryOpKind::ShiftRight { + self.unify( + rhs_type, + &Type::Integer(Signedness::Unsigned, IntegerBitSize::Eight), + || TypeCheckError::InvalidShiftSize { span }, + ); + let use_impl = if lhs_type.is_numeric() { + let integer_type = Type::polymorphic_integer(self.interner); + self.bind_type_variables_for_infix(lhs_type, op, &integer_type, span) + } else { + true + }; + return Ok((lhs_type.clone(), use_impl)); + } + let use_impl = self.bind_type_variables_for_infix(lhs_type, op, rhs_type, span); + Ok((other.clone(), use_impl)) } (Integer(sign_x, bit_width_x), Integer(sign_y, bit_width_y)) => { + if op.kind == BinaryOpKind::ShiftLeft || op.kind == BinaryOpKind::ShiftRight { + if *sign_y != Signedness::Unsigned || *bit_width_y != IntegerBitSize::Eight { + return Err(TypeCheckError::InvalidShiftSize { span }); + } + return Ok((Integer(*sign_x, *bit_width_x), false)); + } if sign_x != sign_y { return Err(TypeCheckError::IntegerSignedness { sign_x: *sign_x, @@ -1151,7 +1281,7 @@ impl<'interner> TypeChecker<'interner> { if op.kind == BinaryOpKind::Modulo { return Err(TypeCheckError::FieldModulo { span }); } else { - return Err(TypeCheckError::InvalidBitwiseOperationOnField { span }); + return Err(TypeCheckError::FieldBitwiseOp { span }); } } Ok((FieldElement, false)) @@ -1160,6 +1290,12 @@ impl<'interner> TypeChecker<'interner> { (Bool, Bool) => Ok((Bool, false)), (lhs, rhs) => { + if op.kind == BinaryOpKind::ShiftLeft || op.kind == BinaryOpKind::ShiftRight { + if rhs == &Type::Integer(Signedness::Unsigned, IntegerBitSize::Eight) { + return Ok((lhs.clone(), true)); + } + return Err(TypeCheckError::InvalidShiftSize { span }); + } self.unify(lhs, rhs, || TypeCheckError::TypeMismatchWithSource { expected: lhs.clone(), actual: rhs.clone(), @@ -1173,7 +1309,7 @@ impl<'interner> TypeChecker<'interner> { fn type_check_prefix_operand( &mut self, - op: &crate::UnaryOp, + op: &crate::ast::UnaryOp, rhs_type: &Type, span: Span, ) -> Type { @@ -1187,19 +1323,19 @@ impl<'interner> TypeChecker<'interner> { }; match op { - crate::UnaryOp::Minus => { + crate::ast::UnaryOp::Minus => { if rhs_type.is_unsigned() { self.errors .push(TypeCheckError::InvalidUnaryOp { kind: rhs_type.to_string(), span }); } - let expected = Type::polymorphic_integer_or_field(self.interner); + let expected = self.polymorphic_integer_or_field(); rhs_type.unify(&expected, &mut self.errors, || TypeCheckError::InvalidUnaryOp { kind: rhs_type.to_string(), span, }); expected } - crate::UnaryOp::Not => { + crate::ast::UnaryOp::Not => { let rhs_type = rhs_type.follow_bindings(); // `!` can work on booleans or integers @@ -1209,10 +1345,10 @@ impl<'interner> TypeChecker<'interner> { unify(Type::Bool) } - crate::UnaryOp::MutableReference => { + crate::ast::UnaryOp::MutableReference => { Type::MutableReference(Box::new(rhs_type.follow_bindings())) } - crate::UnaryOp::Dereference { implicitly_added: _ } => { + crate::ast::UnaryOp::Dereference { implicitly_added: _ } => { let element_type = self.interner.next_type_variable(); unify(Type::MutableReference(Box::new(element_type.clone()))); element_type diff --git a/compiler/noirc_frontend/src/hir/type_check/mod.rs b/compiler/noirc_frontend/src/hir/type_check/mod.rs index b24f5df69bf..286bfa76abc 100644 --- a/compiler/noirc_frontend/src/hir/type_check/mod.rs +++ b/compiler/noirc_frontend/src/hir/type_check/mod.rs @@ -12,14 +12,20 @@ mod expr; mod stmt; pub use errors::TypeCheckError; +use noirc_errors::Span; use crate::{ - hir_def::{expr::HirExpression, stmt::HirStatement, traits::TraitConstraint}, + hir_def::{ + expr::HirExpression, + function::{Param, Parameters}, + stmt::HirStatement, + traits::TraitConstraint, + }, node_interner::{ExprId, FuncId, GlobalId, NodeInterner}, - Type, + Type, TypeBindings, }; -use self::errors::Source; +pub use self::errors::Source; pub struct TypeChecker<'interner> { interner: &'interner mut NodeInterner, @@ -36,6 +42,11 @@ pub struct TypeChecker<'interner> { /// 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)>, + + /// All type variables created in the current function. + /// This map is used to default any integer type variables at the end of + /// a function (before checking trait constraints) if a type wasn't already chosen. + type_variables: Vec, } /// Type checks a function and assigns the @@ -43,10 +54,9 @@ pub struct TypeChecker<'interner> { pub fn type_check_func(interner: &mut NodeInterner, func_id: FuncId) -> Vec { let meta = interner.function_meta(&func_id); let declared_return_type = meta.return_type().clone(); - let can_ignore_ret = meta.can_ignore_return_type(); + let can_ignore_ret = meta.is_stub(); - let function_body = interner.function(&func_id); - let function_body_id = function_body.as_expr(); + let function_body_id = &interner.function(&func_id).as_expr(); let mut type_checker = TypeChecker::new(interner); type_checker.current_function = Some(func_id); @@ -79,36 +89,18 @@ pub fn type_check_func(interner: &mut NodeInterner, func_id: FuncId) -> Vec Vec Vec Vec, + func_id: FuncId, + param: &Param, + errors: &mut Vec, +) { + let meta = type_checker.interner.function_meta(&func_id); + if (meta.is_entry_point && !param.1.is_valid_for_program_input()) + || (meta.has_inline_attribute && !param.1.is_valid_non_inlined_function_input()) + { + let span = param.0.span(); + errors.push(TypeCheckError::InvalidTypeForEntryPoint { span }); + } +} + fn function_info(interner: &NodeInterner, function_body_id: &ExprId) -> (noirc_errors::Span, bool) { let (expr_span, empty_function) = if let HirExpression::Block(block) = interner.expression(function_body_id) { @@ -167,6 +210,160 @@ fn function_info(interner: &NodeInterner, function_body_id: &ExprId) -> (noirc_e (expr_span, empty_function) } +/// Checks that the type of a function in a trait impl matches the type +/// of the corresponding function declaration in the trait itself. +/// +/// To do this, given a trait such as: +/// `trait Foo
{ fn foo(...); }` +/// +/// And an impl such as: +/// `impl Foo for Bar { fn foo(...); } ` +/// +/// We have to substitute: +/// - Self for Bar +/// - A for D +/// - B for F +/// +/// Before we can type check. Finally, we must also check that the unification +/// result does not introduce any new bindings. This can happen if the impl +/// function's type is more general than that of the trait function. E.g. +/// `fn baz(a: A, b: B)` when the impl required `fn baz(a: A, b: A)`. +/// +/// This does not type check the body of the impl function. +pub(crate) fn check_trait_impl_method_matches_declaration( + interner: &mut NodeInterner, + function: FuncId, +) -> Vec { + let meta = interner.function_meta(&function); + let method_name = interner.function_name(&function); + let mut errors = Vec::new(); + + let definition_type = meta.typ.as_monotype(); + + let impl_ = + meta.trait_impl.expect("Trait impl function should have a corresponding trait impl"); + + // If the trait implementation is not defined in the interner then there was a previous + // error in resolving the trait path and there is likely no trait for this impl. + let Some(impl_) = interner.try_get_trait_implementation(impl_) else { + return errors; + }; + + let impl_ = impl_.borrow(); + let trait_info = interner.get_trait(impl_.trait_id); + + let mut bindings = TypeBindings::new(); + bindings.insert( + trait_info.self_type_typevar_id, + (trait_info.self_type_typevar.clone(), impl_.typ.clone()), + ); + + if trait_info.generics.len() != impl_.trait_generics.len() { + let expected = trait_info.generics.len(); + let found = impl_.trait_generics.len(); + let span = impl_.ident.span(); + let item = trait_info.name.to_string(); + errors.push(TypeCheckError::GenericCountMismatch { item, expected, found, span }); + } + + // Substitute each generic on the trait with the corresponding generic on the impl + for (generic, arg) in trait_info.generics.iter().zip(&impl_.trait_generics) { + bindings.insert(generic.id(), (generic.clone(), arg.clone())); + } + + // If this is None, the trait does not have the corresponding function. + // This error should have been caught in name resolution already so we don't + // issue an error for it here. + if let Some(trait_fn_id) = trait_info.method_ids.get(method_name) { + let trait_fn_meta = interner.function_meta(trait_fn_id); + + if trait_fn_meta.direct_generics.len() != meta.direct_generics.len() { + let expected = trait_fn_meta.direct_generics.len(); + let found = meta.direct_generics.len(); + let span = meta.name.location.span; + let item = method_name.to_string(); + errors.push(TypeCheckError::GenericCountMismatch { item, expected, found, span }); + } + + // Substitute each generic on the trait function with the corresponding generic on the impl function + for ((_, trait_fn_generic), (name, impl_fn_generic)) in + trait_fn_meta.direct_generics.iter().zip(&meta.direct_generics) + { + let arg = Type::NamedGeneric(impl_fn_generic.clone(), name.clone()); + bindings.insert(trait_fn_generic.id(), (trait_fn_generic.clone(), arg)); + } + + let (declaration_type, _) = trait_fn_meta.typ.instantiate_with_bindings(bindings, interner); + + check_function_type_matches_expected_type( + &declaration_type, + definition_type, + method_name, + &meta.parameters, + meta.name.location.span, + &trait_info.name.0.contents, + &mut errors, + ); + } + + errors +} + +fn check_function_type_matches_expected_type( + expected: &Type, + actual: &Type, + method_name: &str, + actual_parameters: &Parameters, + span: Span, + trait_name: &str, + errors: &mut Vec, +) { + let mut bindings = TypeBindings::new(); + // Shouldn't need to unify envs, they should always be equal since they're both free functions + if let (Type::Function(params_a, ret_a, _env_a), Type::Function(params_b, ret_b, _env_b)) = + (expected, actual) + { + if params_a.len() == params_b.len() { + for (i, (a, b)) in params_a.iter().zip(params_b.iter()).enumerate() { + if a.try_unify(b, &mut bindings).is_err() { + errors.push(TypeCheckError::TraitMethodParameterTypeMismatch { + method_name: method_name.to_string(), + expected_typ: a.to_string(), + actual_typ: b.to_string(), + parameter_span: actual_parameters.0[i].0.span(), + parameter_index: i + 1, + }); + } + } + + if ret_b.try_unify(ret_a, &mut bindings).is_err() { + errors.push(TypeCheckError::TypeMismatch { + expected_typ: ret_a.to_string(), + expr_typ: ret_b.to_string(), + expr_span: span, + }); + } + } else { + errors.push(TypeCheckError::MismatchTraitImplNumParameters { + actual_num_parameters: params_b.len(), + expected_num_parameters: params_a.len(), + trait_name: trait_name.to_string(), + method_name: method_name.to_string(), + span, + }); + } + } + + // If result bindings is not empty, a type variable was bound which means the two + // signatures were not a perfect match. Note that this relies on us already binding + // all the expected generics to each other prior to this check. + if !bindings.is_empty() { + let expected_typ = expected.to_string(); + let expr_typ = actual.to_string(); + errors.push(TypeCheckError::TypeMismatch { expected_typ, expr_typ, expr_span: span }); + } +} + impl<'interner> TypeChecker<'interner> { fn new(interner: &'interner mut NodeInterner) -> Self { Self { @@ -174,6 +371,7 @@ impl<'interner> TypeChecker<'interner> { errors: Vec::new(), allow_unsafe: false, trait_constraints: Vec::new(), + type_variables: Vec::new(), current_function: None, } } @@ -191,6 +389,7 @@ impl<'interner> TypeChecker<'interner> { errors: Vec::new(), allow_unsafe: false, trait_constraints: Vec::new(), + type_variables: Vec::new(), current_function: None, }; let statement = this.interner.get_global(id).let_statement; @@ -224,23 +423,43 @@ impl<'interner> TypeChecker<'interner> { make_error, ); } + + /// Return a fresh integer or field type variable and log it + /// in self.type_variables to default it later. + fn polymorphic_integer_or_field(&mut self) -> Type { + let typ = Type::polymorphic_integer_or_field(self.interner); + self.type_variables.push(typ.clone()); + typ + } + + /// Return a fresh integer type variable and log it + /// in self.type_variables to default it later. + fn polymorphic_integer(&mut self) -> Type { + let typ = Type::polymorphic_integer(self.interner); + self.type_variables.push(typ.clone()); + typ + } } // XXX: These tests are all manual currently. /// We can either build a test apparatus or pass raw code through the resolver #[cfg(test)] -mod test { +pub mod test { use std::collections::{BTreeMap, HashMap}; use std::vec; use fm::FileId; - use iter_extended::vecmap; + use iter_extended::btree_map; use noirc_errors::{Location, Span}; + use crate::ast::{BinaryOpKind, FunctionKind, FunctionReturnType, Path, Visibility}; use crate::graph::CrateId; use crate::hir::def_map::{ModuleData, ModuleId}; - use crate::hir::resolution::import::PathResolutionError; + use crate::hir::resolution::import::{ + PathResolution, PathResolutionError, PathResolutionResult, + }; use crate::hir_def::expr::HirIdent; + use crate::hir_def::function::FunctionBody; use crate::hir_def::stmt::HirLetStatement; use crate::hir_def::stmt::HirPattern::Identifier; use crate::hir_def::types::Type; @@ -255,9 +474,8 @@ mod test { def_map::{CrateDefMap, LocalModuleId, ModuleDefId}, resolution::{path_resolver::PathResolver, resolver::Resolver}, }, - parse_program, FunctionKind, Path, + parse_program, }; - use crate::{BinaryOpKind, Distinctness, FunctionReturnType, Visibility}; #[test] fn basic_let() { @@ -288,8 +506,8 @@ mod test { let z = HirIdent::non_trait_method(z_id, location); // Push x and y as expressions - let x_expr_id = interner.push_expr(HirExpression::Ident(x.clone())); - let y_expr_id = interner.push_expr(HirExpression::Ident(y.clone())); + let x_expr_id = interner.push_expr(HirExpression::Ident(x.clone(), None)); + let y_expr_id = interner.push_expr(HirExpression::Ident(y.clone(), None)); // Create Infix let operator = HirBinaryOp { location, kind: BinaryOpKind::Add }; @@ -307,6 +525,8 @@ mod test { pattern: Identifier(z), r#type: Type::FieldElement, expression: expr_id, + attributes: vec![], + comptime: false, }; let stmt_id = interner.push_stmt(HirStatement::Let(let_stmt)); let expr_id = interner.push_expr(HirExpression::Block(HirBlockExpression { @@ -339,11 +559,17 @@ mod test { ] .into(), return_visibility: Visibility::Private, - return_distinctness: Distinctness::DuplicationAllowed, has_body: true, trait_impl: None, return_type: FunctionReturnType::Default(Span::default()), trait_constraints: Vec::new(), + direct_generics: Vec::new(), + is_entry_point: true, + is_trait_function: false, + has_inline_attribute: false, + all_generics: Vec::new(), + parameter_idents: Vec::new(), + function_body: FunctionBody::Resolved, }; interner.push_fn_meta(func_meta, func_id); @@ -402,12 +628,7 @@ mod test { "#; - let expected_num_errors = 0; - type_check_src_code_errors_expected( - src, - expected_num_errors, - vec![String::from("main"), String::from("foo")], - ); + type_check_src_code(src, vec![String::from("main")]); } #[test] fn basic_closure() { @@ -418,7 +639,7 @@ mod test { } "#; - type_check_src_code(src, vec![String::from("main"), String::from("foo")]); + type_check_src_code(src, vec![String::from("main")]); } #[test] @@ -432,6 +653,30 @@ mod test { type_check_src_code(src, vec![String::from("main")]); } + + #[test] + fn fold_entry_point() { + let src = r#" + #[fold] + fn fold(x: &mut Field) -> Field { + *x + } + "#; + + type_check_src_code_errors_expected(src, vec![String::from("fold")], 1); + } + + #[test] + fn fold_numeric_generic() { + let src = r#" + #[fold] + fn fold(x: T) -> T { + x + } + "#; + + type_check_src_code(src, vec![String::from("fold")]); + } // This is the same Stub that is in the resolver, maybe we can pull this out into a test module and re-use? struct TestPathResolver(HashMap); @@ -440,17 +685,18 @@ mod test { &self, _def_maps: &BTreeMap, path: Path, - ) -> Result { + ) -> PathResolutionResult { // Not here that foo::bar and hello::foo::bar would fetch the same thing let name = path.segments.last().unwrap(); self.0 .get(&name.0.contents) .cloned() + .map(|module_def_id| PathResolution { module_def_id, error: None }) .ok_or_else(move || PathResolutionError::Unresolved(name.clone())) } fn local_module_id(&self) -> LocalModuleId { - LocalModuleId(arena::Index::unsafe_zeroed()) + LocalModuleId(noirc_arena::Index::unsafe_zeroed()) } fn module_id(&self) -> ModuleId { @@ -464,44 +710,45 @@ mod test { } } - fn type_check_src_code(src: &str, func_namespace: Vec) { - type_check_src_code_errors_expected(src, 0, func_namespace); + pub fn type_check_src_code(src: &str, func_namespace: Vec) -> (NodeInterner, FuncId) { + type_check_src_code_errors_expected(src, func_namespace, 0) } // This function assumes that there is only one function and this is the // func id that is returned fn type_check_src_code_errors_expected( src: &str, - expected_number_errors: usize, func_namespace: Vec, - ) { + expected_num_type_check_errs: usize, + ) -> (NodeInterner, FuncId) { let (program, errors) = parse_program(src); let mut interner = NodeInterner::default(); interner.populate_dummy_operator_traits(); assert_eq!( errors.len(), - expected_number_errors, - "expected {} errors, but got {}, errors: {:?}", - expected_number_errors, + 0, + "expected 0 parser errors, but got {}, errors: {:?}", errors.len(), errors ); - let main_id = interner.push_test_function_definition("main".into()); + let func_ids = btree_map(&func_namespace, |name| { + (name.to_string(), interner.push_test_function_definition(name.into())) + }); - let func_ids = - vecmap(&func_namespace, |name| interner.push_test_function_definition(name.into())); + let main_id = + *func_ids.get("main").unwrap_or_else(|| func_ids.first_key_value().unwrap().1); let mut path_resolver = TestPathResolver(HashMap::new()); - for (name, id) in func_namespace.into_iter().zip(func_ids.clone()) { - path_resolver.insert_func(name.to_owned(), id); + for (name, id) in func_ids.iter() { + path_resolver.insert_func(name.to_owned(), *id); } let mut def_maps = BTreeMap::new(); let file = FileId::default(); - let mut modules = arena::Arena::default(); + let mut modules = noirc_arena::Arena::default(); let location = Location::new(Default::default(), file); modules.insert(ModuleData::new(None, location, false)); @@ -515,20 +762,33 @@ mod test { }, ); - let func_meta = vecmap(program.into_sorted().functions, |nf| { + for nf in program.into_sorted().functions { let resolver = Resolver::new(&mut interner, &path_resolver, &def_maps, file); - let (hir_func, func_meta, resolver_errors) = resolver.resolve_function(nf, main_id); - assert_eq!(resolver_errors, vec![]); - (hir_func, func_meta) - }); - for ((hir_func, meta), func_id) in func_meta.into_iter().zip(func_ids.clone()) { - interner.update_fn(func_id, hir_func); - interner.push_fn_meta(meta, func_id); + let function_id = *func_ids.get(nf.name()).unwrap(); + let (hir_func, func_meta, resolver_errors) = resolver.resolve_function(nf, function_id); + + interner.push_fn_meta(func_meta, function_id); + interner.update_fn(function_id, hir_func); + assert_eq!(resolver_errors, vec![]); } // Type check section - let errors = super::type_check_func(&mut interner, func_ids.first().cloned().unwrap()); - assert_eq!(errors, vec![]); + let mut errors = Vec::new(); + + for function in func_ids.values() { + errors.extend(super::type_check_func(&mut interner, *function)); + } + + assert_eq!( + errors.len(), + expected_num_type_check_errs, + "expected {} type check errors, but got {}, errors: {:?}", + expected_num_type_check_errs, + errors.len(), + errors + ); + + (interner, main_id) } } diff --git a/compiler/noirc_frontend/src/hir/type_check/stmt.rs b/compiler/noirc_frontend/src/hir/type_check/stmt.rs index cf80ce7fcb5..1828d34d4c2 100644 --- a/compiler/noirc_frontend/src/hir/type_check/stmt.rs +++ b/compiler/noirc_frontend/src/hir/type_check/stmt.rs @@ -1,6 +1,8 @@ +use acvm::acir::AcirField; use iter_extended::vecmap; -use noirc_errors::{Location, Span}; +use noirc_errors::Span; +use crate::ast::UnaryOp; use crate::hir_def::expr::{HirExpression, HirIdent, HirLiteral}; use crate::hir_def::stmt::{ HirAssignStatement, HirConstrainStatement, HirForStatement, HirLValue, HirLetStatement, @@ -8,7 +10,6 @@ use crate::hir_def::stmt::{ }; use crate::hir_def::types::Type; use crate::node_interner::{DefinitionId, ExprId, StmtId}; -use crate::UnaryOp; use super::errors::{Source, TypeCheckError}; use super::TypeChecker; @@ -55,7 +56,8 @@ impl<'interner> TypeChecker<'interner> { self.check_assign_stmt(assign_stmt, stmt_id); } HirStatement::For(for_loop) => self.check_for_loop(for_loop), - HirStatement::Error => (), + HirStatement::Comptime(statement) => return self.check_statement(&statement), + HirStatement::Break | HirStatement::Continue | HirStatement::Error => (), } Type::Unit } @@ -75,7 +77,7 @@ impl<'interner> TypeChecker<'interner> { expr_span: range_span, }); - let expected_type = Type::polymorphic_integer(self.interner); + let expected_type = self.polymorphic_integer(); self.unify(&start_range_type, &expected_type, || TypeCheckError::TypeCannotBeUsed { typ: start_range_type.clone(), @@ -199,51 +201,51 @@ impl<'interner> TypeChecker<'interner> { (typ.clone(), HirLValue::Ident(ident.clone(), typ), mutable) } - HirLValue::MemberAccess { object, field_name, .. } => { + HirLValue::MemberAccess { object, field_name, location, .. } => { let (lhs_type, object, mut mutable) = self.check_lvalue(object, assign_span); let mut object = Box::new(object); - let span = field_name.span(); let field_name = field_name.clone(); let object_ref = &mut object; let mutable_ref = &mut mutable; + let location = *location; let dereference_lhs = move |_: &mut Self, _, element_type| { // We must create a temporary value first to move out of object_ref before // we eventually reassign to it. let id = DefinitionId::dummy_id(); - let location = Location::new(span, fm::FileId::dummy()); let ident = HirIdent::non_trait_method(id, location); let tmp_value = HirLValue::Ident(ident, Type::Error); let lvalue = std::mem::replace(object_ref, Box::new(tmp_value)); - *object_ref = Box::new(HirLValue::Dereference { lvalue, element_type }); + *object_ref = + Box::new(HirLValue::Dereference { lvalue, element_type, location }); *mutable_ref = true; }; let name = &field_name.0.contents; let (object_type, field_index) = self - .check_field_access(&lhs_type, name, span, Some(dereference_lhs)) + .check_field_access(&lhs_type, name, field_name.span(), Some(dereference_lhs)) .unwrap_or((Type::Error, 0)); let field_index = Some(field_index); let typ = object_type.clone(); - let lvalue = HirLValue::MemberAccess { object, field_name, field_index, typ }; + let lvalue = + HirLValue::MemberAccess { object, field_name, field_index, typ, location }; (object_type, lvalue, mutable) } - HirLValue::Index { array, index, .. } => { + HirLValue::Index { array, index, location, .. } => { let index_type = self.check_expression(index); let expr_span = self.interner.expr_span(index); + let location = *location; - index_type.unify( - &Type::polymorphic_integer_or_field(self.interner), - &mut self.errors, - || TypeCheckError::TypeMismatch { + index_type.unify(&self.polymorphic_integer_or_field(), &mut self.errors, || { + TypeCheckError::TypeMismatch { expected_typ: "an integer".to_owned(), expr_typ: index_type.to_string(), expr_span, - }, - ); + } + }); let (mut lvalue_type, mut lvalue, mut mutable) = self.check_lvalue(array, assign_span); @@ -252,7 +254,8 @@ impl<'interner> TypeChecker<'interner> { // as needed to unwrap any &mut wrappers. while let Type::MutableReference(element) = lvalue_type.follow_bindings() { let element_type = element.as_ref().clone(); - lvalue = HirLValue::Dereference { lvalue: Box::new(lvalue), element_type }; + lvalue = + HirLValue::Dereference { lvalue: Box::new(lvalue), element_type, location }; lvalue_type = *element; // We know this value to be mutable now since we found an `&mut` mutable = true; @@ -260,7 +263,13 @@ impl<'interner> TypeChecker<'interner> { let typ = match lvalue_type.follow_bindings() { Type::Array(_, elem_type) => *elem_type, + Type::Slice(elem_type) => *elem_type, Type::Error => Type::Error, + Type::String(_) => { + let (_lvalue_name, lvalue_span) = self.get_lvalue_name_and_span(&lvalue); + self.errors.push(TypeCheckError::StringIndexAssign { span: lvalue_span }); + Type::Error + } other => { // TODO: Need a better span here self.errors.push(TypeCheckError::TypeMismatch { @@ -273,11 +282,12 @@ impl<'interner> TypeChecker<'interner> { }; let array = Box::new(lvalue); - (typ.clone(), HirLValue::Index { array, index: *index, typ }, mutable) + (typ.clone(), HirLValue::Index { array, index: *index, typ, location }, mutable) } - HirLValue::Dereference { lvalue, element_type: _ } => { + HirLValue::Dereference { lvalue, element_type: _, location } => { let (reference_type, lvalue, _) = self.check_lvalue(lvalue, assign_span); let lvalue = Box::new(lvalue); + let location = *location; let element_type = Type::type_variable(self.interner.next_type_variable_id()); let expected_type = Type::MutableReference(Box::new(element_type.clone())); @@ -289,7 +299,11 @@ impl<'interner> TypeChecker<'interner> { }); // Dereferences are always mutable since we already type checked against a &mut T - (element_type.clone(), HirLValue::Dereference { lvalue, element_type }, true) + ( + element_type.clone(), + HirLValue::Dereference { lvalue, element_type, location }, + true, + ) } } } @@ -346,8 +360,10 @@ impl<'interner> TypeChecker<'interner> { if annotated_type.is_unsigned() { self.lint_overflowing_uint(&rhs_expr, &annotated_type); } + annotated_type + } else { + expr_type } - expr_type } /// Check if an assignment is overflowing with respect to `annotated_type` diff --git a/compiler/noirc_frontend/src/hir_def/expr.rs b/compiler/noirc_frontend/src/hir_def/expr.rs index f094e1058dd..3d50e07b348 100644 --- a/compiler/noirc_frontend/src/hir_def/expr.rs +++ b/compiler/noirc_frontend/src/hir_def/expr.rs @@ -2,8 +2,9 @@ use acvm::FieldElement; use fm::FileId; use noirc_errors::Location; +use crate::ast::{BinaryOp, BinaryOpKind, Ident, UnaryOp}; use crate::node_interner::{DefinitionId, ExprId, FuncId, NodeInterner, StmtId, TraitMethodId}; -use crate::{BinaryOp, BinaryOpKind, Ident, Shared, UnaryOp}; +use crate::Shared; use super::stmt::HirPattern; use super::traits::TraitConstraint; @@ -16,7 +17,9 @@ use super::types::{StructType, Type}; /// from the definition that refers to them so there is no ambiguity with names. #[derive(Debug, Clone)] pub enum HirExpression { - Ident(HirIdent), + // The optional vec here is the optional list of generics + // provided by the turbofish operator, if it was used + Ident(HirIdent, Option>), Literal(HirLiteral), Block(HirBlockExpression), Prefix(HirPrefixExpression), @@ -30,6 +33,9 @@ pub enum HirExpression { If(HirIfExpression), Tuple(Vec), Lambda(HirLambda), + Quote(crate::ast::BlockExpression), + Unquote(crate::ast::BlockExpression), + Comptime(HirBlockExpression), Error, } @@ -99,6 +105,7 @@ impl HirBinaryOp { #[derive(Debug, Clone)] pub enum HirLiteral { Array(HirArrayLiteral), + Slice(HirArrayLiteral), Bool(bool), Integer(FieldElement, bool), //true for negative integer and false for positive Str(String), @@ -176,6 +183,8 @@ pub struct HirCallExpression { pub struct HirMethodCallExpression { pub method: Ident, pub object: ExprId, + /// Method calls have an optional list of generics provided by the turbofish operator + pub generics: Option>, pub arguments: Vec, pub location: Location, } @@ -195,13 +204,15 @@ pub enum HirMethodReference { impl HirMethodCallExpression { /// Converts a method call into a function call + /// + /// Returns ((func_var_id, func_var), call_expr) pub fn into_function_call( mut self, method: &HirMethodReference, object_type: Type, location: Location, interner: &mut NodeInterner, - ) -> HirExpression { + ) -> ((ExprId, HirIdent), HirCallExpression) { let mut arguments = vec![self.object]; arguments.append(&mut self.arguments); @@ -219,10 +230,11 @@ impl HirMethodCallExpression { (id, ImplKind::TraitMethod(*method_id, constraint, false)) } }; - let func = HirExpression::Ident(HirIdent { location, id, impl_kind }); - let func = interner.push_expr(func); + let func_var = HirIdent { location, id, impl_kind }; + let func = interner.push_expr(HirExpression::Ident(func_var.clone(), self.generics)); interner.push_expr_location(func, location.span, location.file); - HirExpression::Call(HirCallExpression { func, arguments, location }) + let expr = HirCallExpression { func, arguments, location }; + ((func, func_var), expr) } } @@ -259,7 +271,7 @@ impl HirBlockExpression { } /// A variable captured inside a closure -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq, Eq)] pub struct HirCapturedVar { pub ident: HirIdent, @@ -273,7 +285,7 @@ pub struct HirCapturedVar { pub transitive_capture_index: Option, } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq, Eq)] pub struct HirLambda { pub parameters: Vec<(HirPattern, Type)>, pub return_type: Type, diff --git a/compiler/noirc_frontend/src/hir_def/function.rs b/compiler/noirc_frontend/src/hir_def/function.rs index d3ab2a9393b..b338e9f8caa 100644 --- a/compiler/noirc_frontend/src/hir_def/function.rs +++ b/compiler/noirc_frontend/src/hir_def/function.rs @@ -1,12 +1,15 @@ use iter_extended::vecmap; use noirc_errors::{Location, Span}; +use std::rc::Rc; + use super::expr::{HirBlockExpression, HirExpression, HirIdent}; use super::stmt::HirPattern; use super::traits::TraitConstraint; +use crate::ast::{FunctionKind, FunctionReturnType, Visibility}; +use crate::macros_api::BlockExpression; use crate::node_interner::{ExprId, NodeInterner, TraitImplId}; -use crate::FunctionKind; -use crate::{Distinctness, FunctionReturnType, Type, Visibility}; +use crate::{Type, TypeVariable}; /// A Hir function is a block expression /// with a list of statements @@ -22,8 +25,8 @@ impl HirFunction { HirFunction(expr_id) } - pub const fn as_expr(&self) -> &ExprId { - &self.0 + pub const fn as_expr(&self) -> ExprId { + self.0 } pub fn block(&self, interner: &NodeInterner) -> HirBlockExpression { @@ -93,16 +96,30 @@ pub struct FuncMeta { pub parameters: Parameters, + /// The HirIdent of each identifier within the parameter list. + /// Note that this includes separate entries for each identifier in e.g. tuple patterns. + pub parameter_idents: Vec, + pub return_type: FunctionReturnType, pub return_visibility: Visibility, - pub return_distinctness: Distinctness, - /// The type of this function. Either a Type::Function /// or a Type::Forall for generic functions. pub typ: Type, + /// The set of generics that are declared directly on this function in the source code. + /// This does not include generics from an outer scope, like those introduced by + /// an `impl` block. This also does not include implicit generics added by the compiler + /// such as a trait's `Self` type variable. + pub direct_generics: Vec<(Rc, TypeVariable)>, + + /// All the generics used by this function, which includes any implicit generics or generics + /// from outer scopes, such as those introduced by an impl. + /// This is stored when the FuncMeta is first created to later be used to set the current + /// generics when the function's body is later resolved. + pub all_generics: Vec<(Rc, TypeVariable, Span)>, + pub location: Location, // This flag is needed for the attribute check pass @@ -112,18 +129,39 @@ pub struct FuncMeta { /// The trait impl this function belongs to, if any pub trait_impl: Option, + + /// True if this function is an entry point to the program. + /// For non-contracts, this means the function is `main`. + pub is_entry_point: bool, + + /// True if this function was defined within a trait (not a trait impl!). + /// Trait functions are just stubs and shouldn't have their return type checked + /// against their body type, nor should unused variables be checked. + pub is_trait_function: bool, + + /// True if this function is marked with an attribute + /// that indicates it should be inlined differently than the default (inline everything). + /// For example, such as `fold` (never inlined) or `no_predicates` (inlined after flattening) + pub has_inline_attribute: bool, + + pub function_body: FunctionBody, +} + +#[derive(Debug, Clone)] +pub enum FunctionBody { + Unresolved(FunctionKind, BlockExpression, Span), + Resolving, + Resolved, } impl FuncMeta { - /// Builtin, LowLevel and Oracle functions usually have the return type - /// declared, however their function bodies will be empty - /// So this method tells the type checker to ignore the return - /// of the empty function, which is unit - pub fn can_ignore_return_type(&self) -> bool { - match self.kind { - FunctionKind::LowLevel | FunctionKind::Builtin | FunctionKind::Oracle => true, - FunctionKind::Normal | FunctionKind::Recursive => false, - } + /// A stub function does not have a body. This includes Builtin, LowLevel, + /// and Oracle functions in addition to method declarations within a trait. + /// + /// We don't check the return type of these functions since it will always have + /// an empty body, and we don't check for unused parameters. + pub fn is_stub(&self) -> bool { + self.kind.can_ignore_return_type() || self.is_trait_function } pub fn function_signature(&self) -> FunctionSignature { @@ -145,4 +183,24 @@ impl FuncMeta { _ => unreachable!(), } } + + /// Take this function body, returning an owned version while avoiding + /// cloning any large Expressions inside by replacing a Unresolved with a Resolving variant. + pub fn take_body(&mut self) -> FunctionBody { + match &mut self.function_body { + FunctionBody::Unresolved(kind, block, span) => { + let statements = std::mem::take(&mut block.statements); + let is_unsafe = block.is_unsafe; + let (kind, span) = (*kind, *span); + self.function_body = FunctionBody::Resolving; + FunctionBody::Unresolved( + kind, + BlockExpression { is_unsafe, statements }, + span, + ) + } + FunctionBody::Resolving => FunctionBody::Resolving, + FunctionBody::Resolved => FunctionBody::Resolved, + } + } } diff --git a/compiler/noirc_frontend/src/hir_def/stmt.rs b/compiler/noirc_frontend/src/hir_def/stmt.rs index b910be1fdda..0b4dbeb3006 100644 --- a/compiler/noirc_frontend/src/hir_def/stmt.rs +++ b/compiler/noirc_frontend/src/hir_def/stmt.rs @@ -1,6 +1,8 @@ use super::expr::HirIdent; -use crate::node_interner::ExprId; -use crate::{Ident, Type}; +use crate::ast::Ident; +use crate::macros_api::SecondaryAttribute; +use crate::node_interner::{ExprId, StmtId}; +use crate::Type; use fm::FileId; use noirc_errors::{Location, Span}; @@ -14,8 +16,11 @@ pub enum HirStatement { Constrain(HirConstrainStatement), Assign(HirAssignStatement), For(HirForStatement), + Break, + Continue, Expression(ExprId), Semi(ExprId), + Comptime(StmtId), Error, } @@ -24,6 +29,8 @@ pub struct HirLetStatement { pub pattern: HirPattern, pub r#type: Type, pub expression: ExprId, + pub attributes: Vec, + pub comptime: bool, } impl HirLetStatement { @@ -57,7 +64,7 @@ pub struct HirAssignStatement { #[derive(Debug, Clone)] pub struct HirConstrainStatement(pub ExprId, pub FileId, pub Option); -#[derive(Debug, Clone, Hash)] +#[derive(Debug, Clone, Hash, PartialEq, Eq)] pub enum HirPattern { Identifier(HirIdent), Mutable(Box, Location), @@ -97,6 +104,15 @@ impl HirPattern { | HirPattern::Struct(_, _, location) => location.span, } } + + pub(crate) fn location(&self) -> Location { + match self { + HirPattern::Identifier(ident) => ident.location, + HirPattern::Mutable(_, location) + | HirPattern::Tuple(_, location) + | HirPattern::Struct(_, _, location) => *location, + } + } } /// Represents an Ast form that can be assigned to. These @@ -109,14 +125,17 @@ pub enum HirLValue { field_name: Ident, field_index: Option, typ: Type, + location: Location, }, Index { array: Box, index: ExprId, typ: Type, + location: Location, }, Dereference { lvalue: Box, element_type: Type, + location: Location, }, } diff --git a/compiler/noirc_frontend/src/hir_def/traits.rs b/compiler/noirc_frontend/src/hir_def/traits.rs index 16b9899039f..e4959cb3dd9 100644 --- a/compiler/noirc_frontend/src/hir_def/traits.rs +++ b/compiler/noirc_frontend/src/hir_def/traits.rs @@ -1,9 +1,10 @@ use std::collections::HashMap; +use crate::ast::{Ident, NoirFunction}; use crate::{ graph::CrateId, node_interner::{FuncId, TraitId, TraitMethodId}, - Generics, Ident, NoirFunction, Type, TypeBindings, TypeVariable, TypeVariableId, + Generics, Type, TypeBindings, TypeVariable, TypeVariableId, }; use fm::FileId; use noirc_errors::{Location, Span}; diff --git a/compiler/noirc_frontend/src/hir_def/types.rs b/compiler/noirc_frontend/src/hir_def/types.rs index e105da1ccf0..ff8b11f3916 100644 --- a/compiler/noirc_frontend/src/hir_def/types.rs +++ b/compiler/noirc_frontend/src/hir_def/types.rs @@ -6,15 +6,18 @@ use std::{ }; use crate::{ + ast::IntegerBitSize, hir::type_check::TypeCheckError, node_interner::{ExprId, NodeInterner, TraitId, TypeAliasId}, - IntegerBitSize, }; use iter_extended::vecmap; use noirc_errors::{Location, Span}; use noirc_printable_type::PrintableType; -use crate::{node_interner::StructId, Ident, Signedness}; +use crate::{ + ast::{Ident, Signedness}, + node_interner::StructId, +}; use super::expr::{HirCallExpression, HirExpression, HirIdent}; @@ -27,6 +30,9 @@ pub enum Type { /// is either a type variable of some kind or a Type::Constant. Array(Box, Box), + /// Slice(E) is a slice of elements of type E. + Slice(Box), + /// A primitive integer type with the given sign and bit count. /// E.g. `u32` would be `Integer(Unsigned, ThirtyTwo)` Integer(Signedness, IntegerBitSize), @@ -96,12 +102,10 @@ pub enum Type { /// A type-level integer. Included to let an Array's size type variable /// bind to an integer without special checks to bind it to a non-type. - Constant(u64), + Constant(u32), - /// The type of a slice is an array of size NotConstant. - /// The size of an array literal is resolved to this if it ever uses operations - /// involving slices. - NotConstant, + /// The type of quoted code in macros. This is always a comptime-only type + Code, /// The result of some type error. Remembering type errors as their own type variant lets /// us avoid issuing repeat type errors for the same item. For example, a lambda with @@ -117,30 +121,23 @@ impl Type { Type::FieldElement | Type::Integer { .. } | Type::Bool => 1, Type::Array(size, typ) => { let length = size - .evaluate_to_u64() + .evaluate_to_u32() .expect("Cannot have variable sized arrays as a parameter to main"); let typ = typ.as_ref(); - (length as u32) * typ.field_count() + length * typ.field_count() } Type::Struct(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::Alias(def, _) => { - // It is safe to access `typ` without instantiating generics here since generics - // cannot change the number of fields in `typ`. - def.borrow().typ.field_count() - } + Type::Alias(def, generics) => def.borrow().get_type(generics).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::String(size) => size + .evaluate_to_u32() + .expect("Cannot have variable sized strings as a parameter to main"), Type::FmtString(_, _) | Type::Unit | Type::TypeVariable(_, _) @@ -150,27 +147,24 @@ impl Type { | Type::MutableReference(_) | Type::Forall(_, _) | Type::Constant(_) - | Type::NotConstant + | Type::Code + | Type::Slice(_) | Type::Error => unreachable!("This type cannot exist as a parameter to main"), } } pub(crate) fn is_nested_slice(&self) -> bool { match self { - Type::Array(size, elem) => { - if let Type::NotConstant = size.as_ref() { - elem.as_ref().contains_slice() - } else { - false - } - } + Type::Slice(elem) => elem.as_ref().contains_slice(), + Type::Array(_, elem) => elem.as_ref().contains_slice(), + Type::Alias(alias, generics) => alias.borrow().get_type(generics).is_nested_slice(), _ => false, } } pub(crate) fn contains_slice(&self) -> bool { match self { - Type::Array(size, _) => matches!(size.as_ref(), Type::NotConstant), + Type::Slice(_) => true, Type::Struct(struct_typ, generics) => { let fields = struct_typ.borrow().get_fields(generics); for field in fields.iter() { @@ -457,10 +451,10 @@ pub enum TypeVariableKind { /// that can only be bound to Type::Integer, or other polymorphic integers. Integer, - /// A potentially constant array size. This will only bind to itself, Type::NotConstant, or + /// A potentially constant array size. This will only bind to itself or /// Type::Constant(n) with a matching size. This defaults to Type::Constant(n) if still unbound /// during monomorphization. - Constant(u64), + Constant(u32), } /// A TypeVariable is a mutable reference that is either @@ -549,12 +543,12 @@ impl TypeBinding { pub struct TypeVariableId(pub usize); impl Type { - pub fn default_int_type() -> Type { + pub fn default_int_or_field_type() -> Type { Type::FieldElement } - pub fn default_range_loop_type() -> Type { - Type::Integer(Signedness::Unsigned, IntegerBitSize::SixtyFour) + pub fn default_int_type() -> Type { + Type::Integer(Signedness::Unsigned, IntegerBitSize::ThirtyTwo) } pub fn type_variable(id: TypeVariableId) -> Type { @@ -564,7 +558,7 @@ impl Type { /// Returns a TypeVariable(_, TypeVariableKind::Constant(length)) to bind to /// a constant integer for e.g. an array length. - pub fn constant_variable(length: u64, interner: &mut NodeInterner) -> Type { + pub fn constant_variable(length: u32, interner: &mut NodeInterner) -> Type { let id = interner.next_type_variable_id(); let kind = TypeVariableKind::Constant(length); let var = TypeVariable::unbound(id); @@ -595,6 +589,7 @@ impl Type { TypeBinding::Bound(binding) => binding.is_bindable(), TypeBinding::Unbound(_) => true, }, + Type::Alias(alias, args) => alias.borrow().get_type(args).is_bindable(), _ => false, } } @@ -611,6 +606,15 @@ impl Type { matches!(self.follow_bindings(), Type::Integer(Signedness::Unsigned, _)) } + pub fn is_numeric(&self) -> bool { + use Type::*; + use TypeVariableKind as K; + matches!( + self.follow_bindings(), + FieldElement | Integer(..) | Bool | TypeVariable(_, K::Integer | K::IntegerOrField) + ) + } + fn contains_numeric_typevar(&self, target_id: TypeVariableId) -> bool { // True if the given type is a NamedGeneric with the target_id let named_generic_id_matches_target = |typ: &Type| { @@ -635,14 +639,16 @@ impl Type { | Type::TypeVariable(_, _) | Type::Constant(_) | Type::NamedGeneric(_, _) - | Type::NotConstant | Type::Forall(_, _) - | Type::TraitAsType(..) => false, + | Type::Code => false, + Type::TraitAsType(_, _, args) => { + args.iter().any(|generic| generic.contains_numeric_typevar(target_id)) + } Type::Array(length, elem) => { elem.contains_numeric_typevar(target_id) || named_generic_id_matches_target(length) } - + Type::Slice(elem) => elem.contains_numeric_typevar(target_id), Type::Tuple(fields) => { fields.iter().any(|field| field.contains_numeric_typevar(target_id)) } @@ -700,13 +706,14 @@ impl Type { | Type::Function(_, _, _) | Type::MutableReference(_) | Type::Forall(_, _) - | Type::TraitAsType(..) - | Type::NotConstant => false, + | Type::Code + | Type::Slice(_) + | Type::TraitAsType(..) => false, - // This function is called during name resolution before we've verified aliases - // are not cyclic. As a result, it wouldn't be safe to check this alias' definition - // to see if the aliased type is valid. - Type::Alias(..) => false, + Type::Alias(alias, generics) => { + let alias = alias.borrow(); + alias.get_type(generics).is_valid_for_program_input() + } Type::Array(length, element) => { length.is_valid_for_program_input() && element.is_valid_for_program_input() @@ -721,6 +728,54 @@ impl Type { } } + /// True if this type can be used as a parameter to an ACIR function that is not `main` or a contract function. + /// This encapsulates functions for which we may not want to inline during compilation. + /// + /// The inputs allowed for a function entry point differ from those allowed as input to a program as there are + /// certain types which through compilation we know what their size should be. + /// This includes types such as numeric generics. + pub(crate) fn is_valid_non_inlined_function_input(&self) -> bool { + match self { + // Type::Error is allowed as usual since it indicates an error was already issued and + // we don't need to issue further errors about this likely unresolved type + Type::FieldElement + | Type::Integer(_, _) + | Type::Bool + | Type::Unit + | Type::Constant(_) + | Type::TypeVariable(_, _) + | Type::NamedGeneric(_, _) + | Type::Error => true, + + Type::FmtString(_, _) + // To enable this we would need to determine the size of the closure outputs at compile-time. + // This is possible as long as the output size is not dependent upon a witness condition. + | Type::Function(_, _, _) + | Type::Slice(_) + | Type::MutableReference(_) + | Type::Forall(_, _) + // TODO: probably can allow code as it is all compile time + | Type::Code + | Type::TraitAsType(..) => false, + + Type::Alias(alias, generics) => { + let alias = alias.borrow(); + alias.get_type(generics).is_valid_non_inlined_function_input() + } + + Type::Array(length, element) => { + length.is_valid_non_inlined_function_input() && element.is_valid_non_inlined_function_input() + } + Type::String(length) => length.is_valid_non_inlined_function_input(), + Type::Tuple(elements) => elements.iter().all(|elem| elem.is_valid_non_inlined_function_input()), + Type::Struct(definition, generics) => definition + .borrow() + .get_fields(generics) + .into_iter() + .all(|(_, field)| field.is_valid_non_inlined_function_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 { @@ -770,11 +825,10 @@ impl std::fmt::Display for Type { write!(f, "Field") } Type::Array(len, typ) => { - if matches!(len.follow_bindings(), Type::NotConstant) { - write!(f, "[{typ}]") - } else { - write!(f, "[{typ}; {len}]") - } + write!(f, "[{typ}; {len}]") + } + Type::Slice(typ) => { + write!(f, "[{typ}]") } Type::Integer(sign, num_bits) => match sign { Signedness::Signed => write!(f, "i{num_bits}"), @@ -783,7 +837,7 @@ impl std::fmt::Display for Type { Type::TypeVariable(var, TypeVariableKind::Normal) => write!(f, "{}", var.borrow()), Type::TypeVariable(binding, TypeVariableKind::Integer) => { if let TypeBinding::Unbound(_) = &*binding.borrow() { - write!(f, "{}", TypeVariableKind::Integer.default_type()) + write!(f, "{}", Type::default_int_type()) } else { write!(f, "{}", binding.borrow()) } @@ -864,7 +918,7 @@ impl std::fmt::Display for Type { Type::MutableReference(element) => { write!(f, "&mut {element}") } - Type::NotConstant => write!(f, "_"), + Type::Code => write!(f, "Code"), } } } @@ -905,7 +959,7 @@ impl Type { fn try_bind_to_maybe_constant( &self, var: &TypeVariable, - target_length: u64, + target_length: u32, bindings: &mut TypeBindings, ) -> Result<(), UnificationError> { let target_id = match &*var.borrow() { @@ -920,10 +974,6 @@ impl Type { bindings.insert(target_id, (var.clone(), this)); Ok(()) } - Type::NotConstant => { - bindings.insert(target_id, (var.clone(), Type::NotConstant)); - Ok(()) - } // A TypeVariable is less specific than a MaybeConstant, so we bind // to the other type variable instead. Type::TypeVariable(new_var, kind) => { @@ -951,14 +1001,8 @@ impl Type { bindings.insert(*new_target_id, (new_var.clone(), clone)); Ok(()) } - // The lengths don't match, but neither are set in stone so we can - // just set them both to NotConstant. See issue 2370 - TypeVariableKind::Constant(_) => { - // *length != target_length - bindings.insert(target_id, (var.clone(), Type::NotConstant)); - bindings.insert(*new_target_id, (new_var.clone(), Type::NotConstant)); - Ok(()) - } + // *length != target_length + TypeVariableKind::Constant(_) => Err(UnificationError), TypeVariableKind::IntegerOrField => Err(UnificationError), TypeVariableKind::Integer => Err(UnificationError), }, @@ -1168,6 +1212,8 @@ impl Type { elem_a.try_unify(elem_b, bindings) } + (Slice(elem_a), Slice(elem_b)) => elem_a.try_unify(elem_b, bindings), + (String(len_a), String(len_b)) => len_a.try_unify(len_b, bindings), (FmtString(len_a, elements_a), FmtString(len_b, elements_b)) => { @@ -1312,20 +1358,14 @@ impl Type { let this = self.follow_bindings(); let target = target.follow_bindings(); - if let (Type::Array(size1, element1), Type::Array(size2, element2)) = (&this, &target) { - let size1 = size1.follow_bindings(); - let size2 = size2.follow_bindings(); - - // If we have an array and our target is a slice - if matches!(size1, Type::Constant(_)) && matches!(size2, Type::NotConstant) { - // Still have to ensure the element types match. - // Don't need to issue an error here if not, it will be done in unify_with_coercions - let mut bindings = TypeBindings::new(); - if element1.try_unify(element2, &mut bindings).is_ok() { - convert_array_expression_to_slice(expression, this, target, interner); - Self::apply_type_bindings(bindings); - return true; - } + if let (Type::Array(_size, element1), Type::Slice(element2)) = (&this, &target) { + // Still have to ensure the element types match. + // Don't need to issue an error here if not, it will be done in unify_with_coercions + let mut bindings = TypeBindings::new(); + if element1.try_unify(element2, &mut bindings).is_ok() { + convert_array_expression_to_slice(expression, this, target, interner); + Self::apply_type_bindings(bindings); + return true; } } false @@ -1340,17 +1380,17 @@ impl Type { } /// If this type is a Type::Constant (used in array lengths), or is bound - /// to a Type::Constant, return the constant as a u64. - pub fn evaluate_to_u64(&self) -> Option { + /// to a Type::Constant, return the constant as a u32. + pub fn evaluate_to_u32(&self) -> Option { if let Some(binding) = self.get_inner_type_variable() { if let TypeBinding::Bound(binding) = &*binding.borrow() { - return binding.evaluate_to_u64(); + return binding.evaluate_to_u32(); } } match self { Type::TypeVariable(_, TypeVariableKind::Constant(size)) => Some(*size), - Type::Array(len, _elem) => len.evaluate_to_u64(), + Type::Array(len, _elem) => len.evaluate_to_u32(), Type::Constant(x) => Some(*x), _ => None, } @@ -1380,14 +1420,14 @@ impl Type { /// Retrieves the type of the given field name /// Panics if the type is not a struct or tuple. - pub fn get_field_type(&self, field_name: &str) -> Type { + pub fn get_field_type(&self, field_name: &str) -> Option { match self { - Type::Struct(def, args) => def.borrow().get_field(field_name, args).unwrap().0, + Type::Struct(def, args) => def.borrow().get_field(field_name, args).map(|(typ, _)| typ), Type::Tuple(fields) => { let mut fields = fields.iter().enumerate(); - fields.find(|(i, _)| i.to_string() == *field_name).unwrap().1.clone() + fields.find(|(i, _)| i.to_string() == *field_name).map(|(_, typ)| typ).cloned() } - other => panic!("Tried to iterate over the fields of '{other}', which has none"), + _ => None, } } @@ -1435,6 +1475,43 @@ impl Type { } } + /// Instantiates a type with the given types. + /// This differs from substitute in that only the quantified type variables + /// are matched against the type list and are eligible for substitution - similar + /// to normal instantiation. This function is used when the turbofish operator + /// is used and generic substitutions are provided manually by users. + /// + /// Expects the given type vector to be the same length as the Forall type variables. + pub fn instantiate_with( + &self, + types: Vec, + interner: &NodeInterner, + implicit_generic_count: usize, + ) -> (Type, TypeBindings) { + match self { + Type::Forall(typevars, typ) => { + assert_eq!(types.len() + implicit_generic_count, typevars.len(), "Turbofish operator used with incorrect generic count which was not caught by name resolution"); + + let replacements = typevars + .iter() + .enumerate() + .map(|(i, var)| { + let binding = if i < implicit_generic_count { + interner.next_type_variable() + } else { + types[i - implicit_generic_count].clone() + }; + (var.id(), (var.clone(), binding)) + }) + .collect(); + + let instantiated = typ.substitute(&replacements); + (instantiated, replacements) + } + other => (other.clone(), HashMap::new()), + } + } + /// 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. @@ -1493,6 +1570,10 @@ impl Type { let element = element.substitute_helper(type_bindings, substitute_bound_typevars); Type::Array(Box::new(size), Box::new(element)) } + Type::Slice(element) => { + let element = element.substitute_helper(type_bindings, substitute_bound_typevars); + Type::Slice(Box::new(element)) + } Type::String(size) => { let size = size.substitute_helper(type_bindings, substitute_bound_typevars); Type::String(Box::new(size)) @@ -1546,28 +1627,37 @@ impl Type { element.substitute_helper(type_bindings, substitute_bound_typevars), )), + Type::TraitAsType(s, name, args) => { + let args = vecmap(args, |arg| { + arg.substitute_helper(type_bindings, substitute_bound_typevars) + }); + Type::TraitAsType(*s, name.clone(), args) + } + Type::FieldElement | Type::Integer(_, _) | Type::Bool | Type::Constant(_) - | Type::TraitAsType(..) | Type::Error - | Type::NotConstant + | Type::Code | Type::Unit => self.clone(), } } /// True if the given TypeVariableId is free anywhere within self - fn occurs(&self, target_id: TypeVariableId) -> bool { + pub fn occurs(&self, target_id: TypeVariableId) -> bool { match self { Type::Array(len, elem) => len.occurs(target_id) || elem.occurs(target_id), + Type::Slice(elem) => elem.occurs(target_id), Type::String(len) => len.occurs(target_id), Type::FmtString(len, fields) => { let len_occurs = len.occurs(target_id); let field_occurs = fields.occurs(target_id); len_occurs || field_occurs } - Type::Struct(_, generic_args) | Type::Alias(_, generic_args) => { + Type::Struct(_, generic_args) + | Type::Alias(_, generic_args) + | Type::TraitAsType(_, _, generic_args) => { generic_args.iter().any(|arg| arg.occurs(target_id)) } Type::Tuple(fields) => fields.iter().any(|field| field.occurs(target_id)), @@ -1591,9 +1681,8 @@ impl Type { | Type::Integer(_, _) | Type::Bool | Type::Constant(_) - | Type::TraitAsType(..) | Type::Error - | Type::NotConstant + | Type::Code | Type::Unit => false, } } @@ -1610,6 +1699,7 @@ impl Type { Array(size, elem) => { Array(Box::new(size.follow_bindings()), Box::new(elem.follow_bindings())) } + Slice(elem) => Slice(Box::new(elem.follow_bindings())), String(size) => String(Box::new(size.follow_bindings())), FmtString(size, args) => { let size = Box::new(size.follow_bindings()); @@ -1642,16 +1732,14 @@ impl Type { MutableReference(element) => MutableReference(Box::new(element.follow_bindings())), + TraitAsType(s, name, args) => { + let args = vecmap(args, |arg| arg.follow_bindings()); + TraitAsType(*s, name.clone(), args) + } + // Expect that this function should only be called on instantiated types Forall(..) => unreachable!(), - TraitAsType(..) - | FieldElement - | Integer(_, _) - | Bool - | Constant(_) - | Unit - | Error - | NotConstant => self.clone(), + FieldElement | Integer(_, _) | Bool | Constant(_) | Unit | Code | Error => self.clone(), } } @@ -1673,17 +1761,22 @@ fn convert_array_expression_to_slice( let as_slice_id = interner.function_definition_id(as_slice_method); let location = interner.expr_location(&expression); - let as_slice = HirExpression::Ident(HirIdent::non_trait_method(as_slice_id, location)); + let as_slice = HirExpression::Ident(HirIdent::non_trait_method(as_slice_id, location), None); let func = interner.push_expr(as_slice); - let arguments = vec![expression]; + // Copy the expression and give it a new ExprId. The old one + // will be mutated in place into a Call expression. + let argument = interner.expression(&expression); + let argument = interner.push_expr(argument); + interner.push_expr_type(argument, array_type.clone()); + interner.push_expr_location(argument, location.span, location.file); + + let arguments = vec![argument]; let call = HirExpression::Call(HirCallExpression { func, arguments, location }); - let call = interner.push_expr(call); + interner.replace_expr(&expression, call); - interner.push_expr_location(call, location.span, location.file); interner.push_expr_location(func, location.span, location.file); - - interner.push_expr_type(call, target_type.clone()); + interner.push_expr_type(expression, target_type.clone()); let func_type = Type::Function(vec![array_type], Box::new(target_type), Box::new(Type::Unit)); interner.push_expr_type(func, func_type); @@ -1691,7 +1784,7 @@ fn convert_array_expression_to_slice( impl BinaryTypeOperator { /// Return the actual rust numeric function associated with this operator - pub fn function(self) -> fn(u64, u64) -> u64 { + pub fn function(self) -> fn(u32, u32) -> u32 { match self { BinaryTypeOperator::Addition => |a, b| a.wrapping_add(b), BinaryTypeOperator::Subtraction => |a, b| a.wrapping_sub(b), @@ -1705,11 +1798,12 @@ impl BinaryTypeOperator { impl TypeVariableKind { /// Returns the default type this type variable should be bound to if it is still unbound /// during monomorphization. - pub(crate) fn default_type(&self) -> Type { + pub(crate) fn default_type(&self) -> Option { match self { - TypeVariableKind::IntegerOrField | TypeVariableKind::Normal => Type::default_int_type(), - TypeVariableKind::Integer => Type::default_range_loop_type(), - TypeVariableKind::Constant(length) => Type::Constant(*length), + TypeVariableKind::IntegerOrField => Some(Type::default_int_or_field_type()), + TypeVariableKind::Integer => Some(Type::default_int_type()), + TypeVariableKind::Constant(length) => Some(Type::Constant(*length)), + TypeVariableKind::Normal => None, } } } @@ -1727,10 +1821,14 @@ impl From<&Type> for PrintableType { match value { Type::FieldElement => PrintableType::Field, Type::Array(size, typ) => { - let length = size.evaluate_to_u64(); + let length = size.evaluate_to_u32().expect("Cannot print variable sized arrays"); let typ = typ.as_ref(); PrintableType::Array { length, typ: Box::new(typ.into()) } } + Type::Slice(typ) => { + let typ = typ.as_ref(); + PrintableType::Slice { typ: Box::new(typ.into()) } + } Type::Integer(sign, bit_width) => match sign { Signedness::Unsigned => { PrintableType::UnsignedInteger { width: (*bit_width).into() } @@ -1739,17 +1837,17 @@ impl From<&Type> for PrintableType { }, Type::TypeVariable(binding, TypeVariableKind::Integer) => match &*binding.borrow() { TypeBinding::Bound(typ) => typ.into(), - TypeBinding::Unbound(_) => Type::default_range_loop_type().into(), + TypeBinding::Unbound(_) => Type::default_int_type().into(), }, Type::TypeVariable(binding, TypeVariableKind::IntegerOrField) => { match &*binding.borrow() { TypeBinding::Bound(typ) => typ.into(), - TypeBinding::Unbound(_) => Type::default_int_type().into(), + TypeBinding::Unbound(_) => Type::default_int_or_field_type().into(), } } Type::Bool => PrintableType::Boolean, Type::String(size) => { - let size = size.evaluate_to_u64().expect("Cannot print variable sized strings"); + let size = size.evaluate_to_u32().expect("Cannot print variable sized strings"); PrintableType::String { length: size } } Type::FmtString(_, _) => unreachable!("format strings cannot be printed"), @@ -1768,13 +1866,15 @@ impl From<&Type> for PrintableType { Type::TypeVariable(_, _) => unreachable!(), Type::NamedGeneric(..) => unreachable!(), Type::Forall(..) => unreachable!(), - Type::Function(_, _, env) => { - PrintableType::Function { env: Box::new(env.as_ref().into()) } - } + Type::Function(arguments, return_type, env) => PrintableType::Function { + arguments: arguments.iter().map(|arg| arg.into()).collect(), + return_type: Box::new(return_type.as_ref().into()), + env: Box::new(env.as_ref().into()), + }, Type::MutableReference(typ) => { PrintableType::MutableReference { typ: Box::new(typ.as_ref().into()) } } - Type::NotConstant => unreachable!(), + Type::Code => unreachable!(), } } } @@ -1786,11 +1886,10 @@ impl std::fmt::Debug for Type { write!(f, "Field") } Type::Array(len, typ) => { - if matches!(len.follow_bindings(), Type::NotConstant) { - write!(f, "[{typ:?}]") - } else { - write!(f, "[{typ:?}; {len:?}]") - } + write!(f, "[{typ:?}; {len:?}]") + } + Type::Slice(typ) => { + write!(f, "[{typ:?}]") } Type::Integer(sign, num_bits) => match sign { Signedness::Signed => write!(f, "i{num_bits}"), @@ -1860,7 +1959,7 @@ impl std::fmt::Debug for Type { Type::MutableReference(element) => { write!(f, "&mut {element:?}") } - Type::NotConstant => write!(f, "NotConstant"), + Type::Code => write!(f, "Code"), } } } diff --git a/compiler/noirc_frontend/src/lexer/blns/LICENSE b/compiler/noirc_frontend/src/lexer/blns/LICENSE new file mode 100644 index 00000000000..4ab5bbd793b --- /dev/null +++ b/compiler/noirc_frontend/src/lexer/blns/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015-2020 Max Woolf + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/compiler/noirc_frontend/src/lexer/blns/README.md b/compiler/noirc_frontend/src/lexer/blns/README.md new file mode 100644 index 00000000000..201ed68aef0 --- /dev/null +++ b/compiler/noirc_frontend/src/lexer/blns/README.md @@ -0,0 +1,9 @@ +# BLNS + +[Big List of Naughty Strings](https://github.com/minimaxir/big-list-of-naughty-strings) + +## Updating + +```bash +wget -O blns.base64.json "https://raw.githubusercontent.com/minimaxir/big-list-of-naughty-strings/master/blns.base64.json" +``` diff --git a/compiler/noirc_frontend/src/lexer/blns/blns.base64.json b/compiler/noirc_frontend/src/lexer/blns/blns.base64.json new file mode 100644 index 00000000000..18e61c0d2c4 --- /dev/null +++ b/compiler/noirc_frontend/src/lexer/blns/blns.base64.json @@ -0,0 +1,679 @@ +[ + "", + "dW5kZWZpbmVk", + "dW5kZWY=", + "bnVsbA==", + "TlVMTA==", + "KG51bGwp", + "bmls", + "TklM", + "dHJ1ZQ==", + "ZmFsc2U=", + "VHJ1ZQ==", + "RmFsc2U=", + "VFJVRQ==", + "RkFMU0U=", + "Tm9uZQ==", + "aGFzT3duUHJvcGVydHk=", + "XA==", + "MA==", + "MQ==", + "MS4wMA==", + "JDEuMDA=", + "MS8y", + "MUUy", + "MUUwMg==", + "MUUrMDI=", + "LTE=", + "LTEuMDA=", + "LSQxLjAw", + "LTEvMg==", + "LTFFMg==", + "LTFFMDI=", + "LTFFKzAy", + "MS8w", + "MC8w", + "LTIxNDc0ODM2NDgvLTE=", + "LTkyMjMzNzIwMzY4NTQ3NzU4MDgvLTE=", + "LTA=", + "LTAuMA==", + "KzA=", + "KzAuMA==", + "MC4wMA==", + "MC4uMA==", + "Lg==", + "MC4wLjA=", + "MCwwMA==", + "MCwsMA==", + "LA==", + "MCwwLDA=", + "MC4wLzA=", + "MS4wLzAuMA==", + "MC4wLzAuMA==", + "MSwwLzAsMA==", + "MCwwLzAsMA==", + "LS0x", + "LQ==", + "LS4=", + "LSw=", + "OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5", + "OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5", + "TmFO", + "SW5maW5pdHk=", + "LUluZmluaXR5", + "SU5G", + "MSNJTkY=", + "LTEjSU5E", + "MSNRTkFO", + "MSNTTkFO", + "MSNJTkQ=", + "MHgw", + "MHhmZmZmZmZmZg==", + "MHhmZmZmZmZmZmZmZmZmZmZm", + "MHhhYmFkMWRlYQ==", + "MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5", + "MSwwMDAuMDA=", + "MSAwMDAuMDA=", + "MScwMDAuMDA=", + "MSwwMDAsMDAwLjAw", + "MSAwMDAgMDAwLjAw", + "MScwMDAnMDAwLjAw", + "MS4wMDAsMDA=", + "MSAwMDAsMDA=", + "MScwMDAsMDA=", + "MS4wMDAuMDAwLDAw", + "MSAwMDAgMDAwLDAw", + "MScwMDAnMDAwLDAw", + "MDEwMDA=", + "MDg=", + "MDk=", + "Mi4yMjUwNzM4NTg1MDcyMDExZS0zMDg=", + "LC4vOydbXS09", + "PD4/OiJ7fXxfKw==", + "IUAjJCVeJiooKWB+", + "AQIDBAUGBwgODxAREhMUFRYXGBkaGxwdHh9/", + "woDCgcKCwoPChMKGwofCiMKJworCi8KMwo3CjsKPwpDCkcKSwpPClMKVwpbCl8KYwpnCmsKbwpzC", + "ncKewp8=", + "CwwgwoXCoOGagOKAgOKAgeKAguKAg+KAhOKAheKAhuKAh+KAiOKAieKAiuKAi+KAqOKAqeKAr+KB", + "n+OAgA==", + "wq3YgNiB2ILYg9iE2IXYnNud3I/hoI7igIvigIzigI3igI7igI/igKrigKvigKzigK3igK7igaDi", + "gaHigaLigaPigaTigabigafigajiganigarigavigaziga3iga7iga/vu7/vv7nvv7rvv7vwkYK9", + "8JuyoPCbsqHwm7Ki8Juyo/CdhbPwnYW08J2FtfCdhbbwnYW38J2FuPCdhbnwnYW686CAgfOggKDz", + "oICh86CAovOggKPzoICk86CApfOggKbzoICn86CAqPOggKnzoICq86CAq/OggKzzoICt86CArvOg", + "gK/zoICw86CAsfOggLLzoICz86CAtPOggLXzoIC286CAt/OggLjzoIC586CAuvOggLvzoIC886CA", + "vfOggL7zoIC/86CBgPOggYHzoIGC86CBg/OggYTzoIGF86CBhvOggYfzoIGI86CBifOggYrzoIGL", + "86CBjPOggY3zoIGO86CBj/OggZDzoIGR86CBkvOggZPzoIGU86CBlfOggZbzoIGX86CBmPOggZnz", + "oIGa86CBm/OggZzzoIGd86CBnvOggZ/zoIGg86CBofOggaLzoIGj86CBpPOggaXzoIGm86CBp/Og", + "gajzoIGp86CBqvOggavzoIGs86CBrfOgga7zoIGv86CBsPOggbHzoIGy86CBs/OggbTzoIG186CB", + "tvOggbfzoIG486CBufOggbrzoIG786CBvPOggb3zoIG+86CBvw==", + "77u/", + "77++", + "zqniiYjDp+KImuKIq8ucwrXiiaTiiaXDtw==", + "w6XDn+KIgsaSwqnLmeKIhsuawqzigKbDpg==", + "xZPiiJHCtMKu4oCgwqXCqMuGw7jPgOKAnOKAmA==", + "wqHihKLCo8Ki4oiewqfCtuKAosKqwrrigJPiiaA=", + "wrjLm8OH4peKxLHLnMOCwq/LmMK/", + "w4XDjcOOw4/LncOTw5Tvo7/DksOaw4bimIM=", + "xZLigJ7CtOKAsMuHw4HCqMuGw5jiiI/igJ3igJk=", + "YOKBhOKCrOKAueKAuu+sge+sguKAocKwwrfigJrigJTCsQ==", + "4oWb4oWc4oWd4oWe", + "0IHQgtCD0ITQhdCG0IfQiNCJ0IrQi9CM0I3QjtCP0JDQkdCS0JPQlNCV0JbQl9CY0JnQmtCb0JzQ", + "ndCe0J/QoNCh0KLQo9Ck0KXQptCn0KjQqdCq0KvQrNCt0K7Qr9Cw0LHQstCz0LTQtdC20LfQuNC5", + "0LrQu9C80L3QvtC/0YDRgdGC0YPRhNGF0YbRh9GI0YnRitGL0YzRjdGO0Y8=", + "2aDZodmi2aPZpNml2abZp9mo2ak=", + "4oGw4oG04oG1", + "4oKA4oKB4oKC", + "4oGw4oG04oG14oKA4oKB4oKC", + "4LiU4LmJ4LmJ4LmJ4LmJ4LmJ4LmH4LmH4LmH4LmH4LmH4LmJ4LmJ4LmJ4LmJ4LmJ4LmH4LmH4LmH", + "4LmH4LmH4LmJ4LmJ4LmJ4LmJ4LmJ4LmJ4LmJ4LmJ4LmH4LmH4LmH4LmH4LmH4LmJ4LmJ4LmJ4LmJ", + "4LmJ4LmH4LmH4LmH4LmH4LmH4LmJ4LmJ4LmJ4LmJ4LmJ4LmJ4LmJ4LmJ4LmH4LmH4LmH4LmH4LmH", + "4LmJ4LmJ4LmJ4LmJ4LmJ4LmH4LmH4LmH4LmH4LmH4LmJ4LmJ4LmJ4LmJ4LmJ4LmJ4LmJ4LmJ4LmH", + "4LmH4LmH4LmH4LmH4LmJ4LmJ4LmJ4LmJ4LmJ4LmH4LmH4LmH4LmHIOC4lOC5ieC5ieC5ieC5ieC5", + "ieC5h+C5h+C5h+C5h+C5h+C5ieC5ieC5ieC5ieC5ieC5h+C5h+C5h+C5h+C5h+C5ieC5ieC5ieC5", + "ieC5ieC5ieC5ieC5ieC5h+C5h+C5h+C5h+C5h+C5ieC5ieC5ieC5ieC5ieC5h+C5h+C5h+C5h+C5", + "h+C5ieC5ieC5ieC5ieC5ieC5ieC5ieC5ieC5h+C5h+C5h+C5h+C5h+C5ieC5ieC5ieC5ieC5ieC5", + "h+C5h+C5h+C5h+C5h+C5ieC5ieC5ieC5ieC5ieC5ieC5ieC5ieC5h+C5h+C5h+C5h+C5h+C5ieC5", + "ieC5ieC5ieC5ieC5h+C5h+C5h+C5hyDguJTguYnguYnguYnguYnguYnguYfguYfguYfguYfguYfg", + "uYnguYnguYnguYnguYnguYfguYfguYfguYfguYfguYnguYnguYnguYnguYnguYnguYnguYnguYfg", + "uYfguYfguYfguYfguYnguYnguYnguYnguYnguYfguYfguYfguYfguYfguYnguYnguYnguYnguYng", + "uYnguYnguYnguYfguYfguYfguYfguYfguYnguYnguYnguYnguYnguYfguYfguYfguYfguYfguYng", + "uYnguYnguYnguYnguYnguYnguYnguYfguYfguYfguYfguYfguYnguYnguYnguYnguYnguYfguYfg", + "uYfguYc=", + "Jw==", + "Ig==", + "Jyc=", + "IiI=", + "JyIn", + "IicnJyciJyI=", + "IiciJyInJycnIg==", + "PGZvbyB2YWw94oCcYmFy4oCdIC8+", + "PGZvbyB2YWw94oCcYmFy4oCdIC8+", + "PGZvbyB2YWw94oCdYmFy4oCcIC8+", + "PGZvbyB2YWw9YGJhcicgLz4=", + "55Sw5Lit44GV44KT44Gr44GC44GS44Gm5LiL44GV44GE", + "44OR44O844OG44Kj44O844G46KGM44GL44Gq44GE44GL", + "5ZKM6KO95ryi6Kqe", + "6YOo6JC95qC8", + "7IKs7ZqM6rO87ZWZ7JuQIOyWtO2VmeyXsOq1rOyGjA==", + "7LCm7LCo66W8IO2DgOqzoCDsmKgg7Y6y7Iuc66eo6rO8IOyRm+uLpOumrCDrmKDrsKnqsIHtlZg=", + "56S+5pyD56eR5a246Zmi6Kqe5a2456CU56m25omA", + "7Jq4656A67CU7Yag66W0", + "8KCcjvCgnLHwoJ258KCxk/CgsbjwoLKW8KCzjw==", + "6KGo44Od44GCQem3l8WSw6nvvKLpgI3DnMOfwqrEhcOx5LiC45CA8KCAgA==", + "44O94Ly84LqI2YTNnOC6iOC8ve++iSDjg73gvLzguojZhM2c4LqI4Ly9776J", + "KO+9oeKXlSDiiIAg4peV772hKQ==", + "772A772oKMK04oiA772A4oip", + "X1/vvpsoLF8sKik=", + "44O7KO+/o+KIgO+/oynjg7s6Kjo=", + "776f772l4py/44O+4pWyKO+9oeKXleKAv+KXle+9oSnilbHinL/vvaXvvp8=", + "LOOAguODuzoqOuODu+OCnOKAmSgg4pi7IM+JIOKYuyAp44CC44O7Oio644O744Kc4oCZ", + "KOKVr8Kw4pahwrDvvInila/vuLUg4pS74pSB4pS7KQ==", + "KO++ieCypeebiuCype+8ie++ie+7vyDilLvilIHilLs=", + "4pSs4pSA4pSs44OOKCDCuiBfIMK644OOKQ==", + "KCDNocKwIM2cypYgzaHCsCk=", + "8J+YjQ==", + "8J+RqfCfj70=", + "8J+RqOKAjfCfprAg8J+RqPCfj7/igI3wn6awIPCfkajigI3wn6axIPCfkajwn4+/4oCN8J+msSDwn6a58J+Pv+KAjeKZgu+4jw==", + "8J+RviDwn5mHIPCfkoEg8J+ZhSDwn5mGIPCfmYsg8J+ZjiDwn5mN", + "8J+QtSDwn5mIIPCfmYkg8J+Zig==", + "4p2k77iPIPCfkpQg8J+SjCDwn5KVIPCfkp4g8J+SkyDwn5KXIPCfkpYg8J+SmCDwn5KdIPCfkp8g", + "8J+SnCDwn5KbIPCfkpog8J+SmQ==", + "4pyL8J+PvyDwn5Kq8J+PvyDwn5GQ8J+PvyDwn5mM8J+PvyDwn5GP8J+PvyDwn5mP8J+Pvw==", + "8J+aviDwn4aSIPCfhpMg8J+GlSDwn4aWIPCfhpcg8J+GmSDwn4+n", + "MO+4j+KDoyAx77iP4oOjIDLvuI/ig6MgM++4j+KDoyA077iP4oOjIDXvuI/ig6MgNu+4j+KDoyA3", + "77iP4oOjIDjvuI/ig6MgOe+4j+KDoyDwn5Sf", + "8J+HuvCfh7jwn4e38J+HuvCfh7gg8J+HpvCfh6vwn4em8J+HsvCfh7g=", + "8J+HuvCfh7jwn4e38J+HuvCfh7jwn4em8J+Hq/Cfh6bwn4ey", + "8J+HuvCfh7jwn4e38J+HuvCfh7jwn4em", + "77yR77yS77yT", + "2aHZotmj", + "2KvZhSDZhtmB2LMg2LPZgti32Kog2YjYqNin2YTYqtit2K/Zitiv2IwsINis2LLZitix2KrZiiDY", + "qNin2LPYqtiu2K/Yp9mFINij2YYg2K/ZhtmILiDYpdiwINmH2YbYp9ifINin2YTYs9iq2KfYsSDZ", + "iNiq2YbYtdmK2Kgg2YPYp9mGLiDYo9mH2ZHZhCDYp9mK2LfYp9mE2YrYp9iMINio2LHZiti32KfZ", + "htmK2Kct2YHYsdmG2LPYpyDZgtivINij2K7YsC4g2LPZhNmK2YXYp9mG2Iwg2KXYqtmB2KfZgtmK", + "2Kkg2KjZitmGINmF2KcsINmK2LDZg9ixINin2YTYrdiv2YjYryDYo9mKINio2LnYrywg2YXYudin", + "2YXZhNipINio2YjZhNmG2K/Yp9iMINin2YTYpdi32YTYp9mCINi52YQg2KXZitmILg==", + "15HWsNa816jWtdeQ16nWtNeB15nXqiwg15HWuNa816jWuNeQINeQ1rHXnNa515TWtNeZ150sINeQ", + "1rXXqiDXlNa316nWuNa814HXnta315nWtNedLCDXldaw15DWtdeqINeU1rjXkNa416jWttel", + "15TWuNeZ1rDXqta415R0ZXN02KfZhNi12YHYrdin2Kog2KfZhNiq2ZHYrdmI2YQ=", + "77e9", + "77e6", + "2YXZj9mG2Y7Yp9mC2Y7YtNmO2KnZjyDYs9mP2KjZj9mE2ZAg2KfZkNiz2ZLYqtmQ2K7Zktiv2Y7Y", + "p9mF2ZAg2KfZhNmE2ZHZj9i62Y7YqdmQINmB2ZDZiiDYp9mE2YbZkdmP2LjZj9mF2ZAg2KfZhNmS", + "2YLZjtin2KbZkNmF2Y7YqdmQINmI2Y7ZgdmQ2YrZhSDZitmO2K7Zj9i12ZHZjiDYp9mE2KrZkdmO", + "2LfZktio2ZDZitmC2Y7Yp9iq2Y8g2KfZhNmS2K3Yp9iz2Y/ZiNio2ZDZitmR2Y7YqdmP2Iw=", + "4Zqb4ZqE4ZqT4ZqQ4ZqL4ZqS4ZqE4ZqA4ZqR4ZqE4ZqC4ZqR4ZqP4ZqF4Zqc", + "4Zqb4ZqA4ZqA4ZqA4ZqA4ZqA4ZqA4ZqA4ZqA4ZqA4ZqA4ZqA4ZqA4ZqA4ZqA4ZqA4ZqA4ZqA4ZqcCg==", + "4oCq4oCqdGVzdOKAqg==", + "4oCrdGVzdOKAqw==", + "4oCpdGVzdOKAqQ==", + "dGVzdOKBoHRlc3TigKs=", + "4oGmdGVzdOKBpw==", + "4bmwzLrMusyVb82eIMy3acyyzKzNh8yqzZluzJ3Ml82VdsyfzJzMmMymzZ9vzLbMmcywzKBrw6jN", + "msyuzLrMqsy5zLHMpCDMlnTMnc2VzLPMo8y7zKrNnmjMvM2TzLLMpsyzzJjMsmXNh8yjzLDMpsys", + "zY4gzKLMvMy7zLHMmGjNms2OzZnMnMyjzLLNhWnMpsyyzKPMsMykdsy7zY1lzLrMrcyzzKrMsC1t", + "zKJpzYVuzJbMusyezLLMr8ywZMy1zLzMn82ZzKnMvMyYzLMgzJ7MpcyxzLPMrXLMm8yXzJhlzZlw", + "zaByzLzMnsy7zK3Ml2XMusygzKPNn3PMmM2HzLPNjcydzYllzYnMpcyvzJ7Mss2azKzNnMe5zKzN", + "js2OzJ/Mls2HzKR0zY3MrMykzZPMvMytzZjNhWnMqsyxbs2gZ8y0zYkgzY/Nic2FY8yszJ9ozaFh", + "zKvMu8yvzZhvzKvMn8yWzY3MmcydzYlzzJfMpsyyLsyozLnNiMyj", + "zKHNk8yezYVJzJfMmMymzZ1uzYfNh82ZdsyuzKtva8yyzKvMmc2IacyWzZnMrcy5zKDMnm7Mocy7", + "zK7Mo8y6Z8yyzYjNmcytzZnMrM2OIMywdM2UzKZozJ7MsmXMosykIM2NzKzMss2WZsy0zJjNlcyj", + "w6jNluG6ucylzKlszZbNlM2aac2TzZrMps2gbs2WzY3Ml82TzLPMrmfNjSDMqG/NmsyqzaFmzJjM", + "o8ysIMyWzJjNlsyfzZnMrmPSic2UzKvNls2TzYfNls2FaMy1zKTMo82azZTDocyXzLzNlc2Fb8y8", + "zKPMpXPMsc2IzLrMlsymzLvNoi7Mm8yWzJ7MoMyrzLA=", + "zJfMus2WzLnMr82T4bmuzKTNjcylzYfNiGjMssyBZc2PzZPMvMyXzJnMvMyjzZQgzYfMnMyxzKDN", + "k82NzYVOzZXNoGXMl8yxesyYzJ3MnMy6zZlwzKTMusy5zY3Mr82aZcygzLvMoM2ccsyozKTNjcy6", + "zJbNlMyWzJZkzKDMn8ytzKzMnc2facymzZbMqc2TzZTMpGHMoMyXzKzNicyZbs2azZwgzLvMnsyw", + "zZrNhWjMtc2JacyzzJ52zKLNh+G4mc2OzZ8t0onMrcypzLzNlG3MpMytzKtpzZXNh8ydzKZuzJfN", + "meG4jcyfIMyvzLLNlc2ex6vMn8yvzLDMss2ZzLvMnWYgzKrMsMywzJfMlsytzJjNmGPMps2NzLLM", + "ns2NzKnMmeG4pc2aYcyuzY7Mn8yZzZzGocypzLnNjnPMpC7MncydINKJWsyhzJbMnM2WzLDMo82J", + "zJxhzZbMsM2ZzKzNoWzMssyrzLPNjcypZ8yhzJ/MvMyxzZrMnsyszYVvzJfNnC7Mnw==", + "zKZIzKzMpMyXzKTNnWXNnCDMnMylzJ3Mu82NzJ/MgXfMlWjMlsyvzZNvzJ3NmcyWzY7MscyuINKJ", + "zLrMmcyezJ/NiFfMt8y8zK1hzLrMqs2NxK/NiM2VzK3NmcyvzJx0zLbMvMyuc8yYzZnNlsyVIMyg", + "zKvMoELMu82NzZnNicyzzYVlzLVozLXMrM2HzKvNmWnMuc2TzLPMs8yuzY7Mq8yVbs2fZMy0zKrM", + "nMyWIMywzYnMqc2HzZnMss2ezYVUzZbMvM2TzKrNomjNj82TzK7Mu2XMrMydzJ/NhSDMpMy5zJ1X", + "zZnMnsydzZTNh82dzYVhzY/Nk82UzLnMvMyjbMy0zZTMsMykzJ/NlOG4vcyrLs2V", + "WsyuzJ7MoM2ZzZTNheG4gMyXzJ7NiMy7zJfhuLbNmc2OzK/MucyezZNHzLtPzK3Ml8yu", + "y5nJkG5i4bSJbMmQIMmQdcaDyZDJryDHncm5b2xvcCDKh8edIMedyblvccmQbCDKh24gyod1bnDh", + "tIlw4bSJyZR14bSJIMm5b2TJr8edyocgcG/Jr3Nu4bSJx50gb3AgcMedcyAnyofhtIlsx50gxoN1", + "4bSJyZRz4bSJZOG0iXDJkCDJuW7Kh8edyofJlMedc3VvyZQgJ8qHx53Jr8mQIMqH4bSJcyDJuW9s", + "b3Agya9uc2ThtIkgya/Hncm5b8ul", + "MDDLmcaWJC0=", + "77y0772I772FIO+9ke+9le+9ie+9g++9iyDvvYLvvZLvvY/vvZfvvY4g772G772P772YIO+9iu+9", + "le+9je+9kO+9kyDvvY/vvZbvvYXvvZIg772U772I772FIO+9jO+9ge+9mu+9mSDvvYTvvY/vvYc=", + "8J2Qk/CdkKHwnZCeIPCdkKrwnZCu8J2QovCdkJzwnZCkIPCdkJvwnZCr8J2QqPCdkLDwnZCnIPCd", + "kJ/wnZCo8J2QsSDwnZCj8J2QrvCdkKbwnZCp8J2QrCDwnZCo8J2Qr/CdkJ7wnZCrIPCdkK3wnZCh", + "8J2QniDwnZCl8J2QmvCdkLPwnZCyIPCdkJ3wnZCo8J2QoA==", + "8J2Vv/Cdlo3wnZaKIPCdlpbwnZaa8J2WjvCdlojwnZaQIPCdlofwnZaX8J2WlPCdlpzwnZaTIPCd", + "lovwnZaU8J2WnSDwnZaP8J2WmvCdlpLwnZaV8J2WmCDwnZaU8J2Wm/CdlorwnZaXIPCdlpnwnZaN", + "8J2WiiDwnZaR8J2WhvCdlp/wnZaeIPCdlonwnZaU8J2WjA==", + "8J2Ru/CdkonwnZKGIPCdkpLwnZKW8J2SivCdkoTwnZKMIPCdkoPwnZKT8J2SkPCdkpjwnZKPIPCd", + "kofwnZKQ8J2SmSDwnZKL8J2SlvCdko7wnZKR8J2SlCDwnZKQ8J2Sl/CdkobwnZKTIPCdkpXwnZKJ", + "8J2ShiDwnZKN8J2SgvCdkpvwnZKaIPCdkoXwnZKQ8J2SiA==", + "8J2To/Cdk7HwnZOuIPCdk7rwnZO+8J2TsvCdk6zwnZO0IPCdk6vwnZO78J2TuPCdlIDwnZO3IPCd", + "k6/wnZO48J2UgSDwnZOz8J2TvvCdk7bwnZO58J2TvCDwnZO48J2Tv/Cdk67wnZO7IPCdk73wnZOx", + "8J2TriDwnZO18J2TqvCdlIPwnZSCIPCdk63wnZO48J2TsA==", + "8J2Vi/CdlZnwnZWWIPCdlaLwnZWm8J2VmvCdlZTwnZWcIPCdlZPwnZWj8J2VoPCdlajwnZWfIPCd", + "lZfwnZWg8J2VqSDwnZWb8J2VpvCdlZ7wnZWh8J2VpCDwnZWg8J2Vp/CdlZbwnZWjIPCdlaXwnZWZ", + "8J2VliDwnZWd8J2VkvCdlavwnZWqIPCdlZXwnZWg8J2VmA==", + "8J2ag/CdmpHwnZqOIPCdmprwnZqe8J2akvCdmozwnZqUIPCdmovwnZqb8J2amPCdmqDwnZqXIPCd", + "mo/wnZqY8J2aoSDwnZqT8J2anvCdmpbwnZqZ8J2anCDwnZqY8J2an/Cdmo7wnZqbIPCdmp3wnZqR", + "8J2ajiDwnZqV8J2aivCdmqPwnZqiIPCdmo3wnZqY8J2akA==", + "4pKv4pKj4pKgIOKSrOKSsOKSpOKSnuKSpiDikp3ikq3ikqrikrLikqkg4pKh4pKq4pKzIOKSpeKS", + "sOKSqOKSq+KSriDikqrikrHikqDikq0g4pKv4pKj4pKgIOKSp+KSnOKSteKStCDikp/ikqrikqI=", + "PHNjcmlwdD5hbGVydCgxMjMpPC9zY3JpcHQ+", + "Jmx0O3NjcmlwdCZndDthbGVydCgmIzM5OzEyMyYjMzk7KTsmbHQ7L3NjcmlwdCZndDs=", + "PGltZyBzcmM9eCBvbmVycm9yPWFsZXJ0KDEyMykgLz4=", + "PHN2Zz48c2NyaXB0PjEyMzwxPmFsZXJ0KDEyMyk8L3NjcmlwdD4=", + "Ij48c2NyaXB0PmFsZXJ0KDEyMyk8L3NjcmlwdD4=", + "Jz48c2NyaXB0PmFsZXJ0KDEyMyk8L3NjcmlwdD4=", + "PjxzY3JpcHQ+YWxlcnQoMTIzKTwvc2NyaXB0Pg==", + "PC9zY3JpcHQ+PHNjcmlwdD5hbGVydCgxMjMpPC9zY3JpcHQ+", + "PCAvIHNjcmlwdCA+PCBzY3JpcHQgPmFsZXJ0KDEyMyk8IC8gc2NyaXB0ID4=", + "b25mb2N1cz1KYVZhU0NyaXB0OmFsZXJ0KDEyMykgYXV0b2ZvY3Vz", + "IiBvbmZvY3VzPUphVmFTQ3JpcHQ6YWxlcnQoMTIzKSBhdXRvZm9jdXM=", + "JyBvbmZvY3VzPUphVmFTQ3JpcHQ6YWxlcnQoMTIzKSBhdXRvZm9jdXM=", + "77ycc2NyaXB077yeYWxlcnQoMTIzKe+8nC9zY3JpcHTvvJ4=", + "PHNjPHNjcmlwdD5yaXB0PmFsZXJ0KDEyMyk8L3NjPC9zY3JpcHQ+cmlwdD4=", + "LS0+PHNjcmlwdD5hbGVydCgxMjMpPC9zY3JpcHQ+", + "IjthbGVydCgxMjMpO3Q9Ig==", + "JzthbGVydCgxMjMpO3Q9Jw==", + "SmF2YVNDcmlwdDphbGVydCgxMjMp", + "O2FsZXJ0KDEyMyk7", + "c3JjPUphVmFTQ3JpcHQ6cHJvbXB0KDEzMik=", + "Ij48c2NyaXB0PmFsZXJ0KDEyMyk7PC9zY3JpcHQgeD0i", + "Jz48c2NyaXB0PmFsZXJ0KDEyMyk7PC9zY3JpcHQgeD0n", + "PjxzY3JpcHQ+YWxlcnQoMTIzKTs8L3NjcmlwdCB4PQ==", + "IiBhdXRvZm9jdXMgb25rZXl1cD0iamF2YXNjcmlwdDphbGVydCgxMjMp", + "JyBhdXRvZm9jdXMgb25rZXl1cD0namF2YXNjcmlwdDphbGVydCgxMjMp", + "PHNjcmlwdHgyMHR5cGU9InRleHQvamF2YXNjcmlwdCI+amF2YXNjcmlwdDphbGVydCgxKTs8L3Nj", + "cmlwdD4=", + "PHNjcmlwdHgzRXR5cGU9InRleHQvamF2YXNjcmlwdCI+amF2YXNjcmlwdDphbGVydCgxKTs8L3Nj", + "cmlwdD4=", + "PHNjcmlwdHgwRHR5cGU9InRleHQvamF2YXNjcmlwdCI+amF2YXNjcmlwdDphbGVydCgxKTs8L3Nj", + "cmlwdD4=", + "PHNjcmlwdHgwOXR5cGU9InRleHQvamF2YXNjcmlwdCI+amF2YXNjcmlwdDphbGVydCgxKTs8L3Nj", + "cmlwdD4=", + "PHNjcmlwdHgwQ3R5cGU9InRleHQvamF2YXNjcmlwdCI+amF2YXNjcmlwdDphbGVydCgxKTs8L3Nj", + "cmlwdD4=", + "PHNjcmlwdHgyRnR5cGU9InRleHQvamF2YXNjcmlwdCI+amF2YXNjcmlwdDphbGVydCgxKTs8L3Nj", + "cmlwdD4=", + "PHNjcmlwdHgwQXR5cGU9InRleHQvamF2YXNjcmlwdCI+amF2YXNjcmlwdDphbGVydCgxKTs8L3Nj", + "cmlwdD4=", + "J2AiPjx4M0NzY3JpcHQ+amF2YXNjcmlwdDphbGVydCgxKTwvc2NyaXB0Pg==", + "J2AiPjx4MDBzY3JpcHQ+amF2YXNjcmlwdDphbGVydCgxKTwvc2NyaXB0Pg==", + "QUJDPGRpdiBzdHlsZT0ieHgzQWV4cHJlc3Npb24oamF2YXNjcmlwdDphbGVydCgxKSI+REVG", + "QUJDPGRpdiBzdHlsZT0ieDpleHByZXNzaW9ueDVDKGphdmFzY3JpcHQ6YWxlcnQoMSkiPkRFRg==", + "QUJDPGRpdiBzdHlsZT0ieDpleHByZXNzaW9ueDAwKGphdmFzY3JpcHQ6YWxlcnQoMSkiPkRFRg==", + "QUJDPGRpdiBzdHlsZT0ieDpleHB4MDByZXNzaW9uKGphdmFzY3JpcHQ6YWxlcnQoMSkiPkRFRg==", + "QUJDPGRpdiBzdHlsZT0ieDpleHB4NUNyZXNzaW9uKGphdmFzY3JpcHQ6YWxlcnQoMSkiPkRFRg==", + "QUJDPGRpdiBzdHlsZT0ieDp4MEFleHByZXNzaW9uKGphdmFzY3JpcHQ6YWxlcnQoMSkiPkRFRg==", + "QUJDPGRpdiBzdHlsZT0ieDp4MDlleHByZXNzaW9uKGphdmFzY3JpcHQ6YWxlcnQoMSkiPkRFRg==", + "QUJDPGRpdiBzdHlsZT0ieDp4RTN4ODB4ODBleHByZXNzaW9uKGphdmFzY3JpcHQ6YWxlcnQoMSki", + "PkRFRg==", + "QUJDPGRpdiBzdHlsZT0ieDp4RTJ4ODB4ODRleHByZXNzaW9uKGphdmFzY3JpcHQ6YWxlcnQoMSki", + "PkRFRg==", + "QUJDPGRpdiBzdHlsZT0ieDp4QzJ4QTBleHByZXNzaW9uKGphdmFzY3JpcHQ6YWxlcnQoMSkiPkRF", + "Rg==", + "QUJDPGRpdiBzdHlsZT0ieDp4RTJ4ODB4ODBleHByZXNzaW9uKGphdmFzY3JpcHQ6YWxlcnQoMSki", + "PkRFRg==", + "QUJDPGRpdiBzdHlsZT0ieDp4RTJ4ODB4OEFleHByZXNzaW9uKGphdmFzY3JpcHQ6YWxlcnQoMSki", + "PkRFRg==", + "QUJDPGRpdiBzdHlsZT0ieDp4MERleHByZXNzaW9uKGphdmFzY3JpcHQ6YWxlcnQoMSkiPkRFRg==", + "QUJDPGRpdiBzdHlsZT0ieDp4MENleHByZXNzaW9uKGphdmFzY3JpcHQ6YWxlcnQoMSkiPkRFRg==", + "QUJDPGRpdiBzdHlsZT0ieDp4RTJ4ODB4ODdleHByZXNzaW9uKGphdmFzY3JpcHQ6YWxlcnQoMSki", + "PkRFRg==", + "QUJDPGRpdiBzdHlsZT0ieDp4RUZ4QkJ4QkZleHByZXNzaW9uKGphdmFzY3JpcHQ6YWxlcnQoMSki", + "PkRFRg==", + "QUJDPGRpdiBzdHlsZT0ieDp4MjBleHByZXNzaW9uKGphdmFzY3JpcHQ6YWxlcnQoMSkiPkRFRg==", + "QUJDPGRpdiBzdHlsZT0ieDp4RTJ4ODB4ODhleHByZXNzaW9uKGphdmFzY3JpcHQ6YWxlcnQoMSki", + "PkRFRg==", + "QUJDPGRpdiBzdHlsZT0ieDp4MDBleHByZXNzaW9uKGphdmFzY3JpcHQ6YWxlcnQoMSkiPkRFRg==", + "QUJDPGRpdiBzdHlsZT0ieDp4RTJ4ODB4OEJleHByZXNzaW9uKGphdmFzY3JpcHQ6YWxlcnQoMSki", + "PkRFRg==", + "QUJDPGRpdiBzdHlsZT0ieDp4RTJ4ODB4ODZleHByZXNzaW9uKGphdmFzY3JpcHQ6YWxlcnQoMSki", + "PkRFRg==", + "QUJDPGRpdiBzdHlsZT0ieDp4RTJ4ODB4ODVleHByZXNzaW9uKGphdmFzY3JpcHQ6YWxlcnQoMSki", + "PkRFRg==", + "QUJDPGRpdiBzdHlsZT0ieDp4RTJ4ODB4ODJleHByZXNzaW9uKGphdmFzY3JpcHQ6YWxlcnQoMSki", + "PkRFRg==", + "QUJDPGRpdiBzdHlsZT0ieDp4MEJleHByZXNzaW9uKGphdmFzY3JpcHQ6YWxlcnQoMSkiPkRFRg==", + "QUJDPGRpdiBzdHlsZT0ieDp4RTJ4ODB4ODFleHByZXNzaW9uKGphdmFzY3JpcHQ6YWxlcnQoMSki", + "PkRFRg==", + "QUJDPGRpdiBzdHlsZT0ieDp4RTJ4ODB4ODNleHByZXNzaW9uKGphdmFzY3JpcHQ6YWxlcnQoMSki", + "PkRFRg==", + "QUJDPGRpdiBzdHlsZT0ieDp4RTJ4ODB4ODlleHByZXNzaW9uKGphdmFzY3JpcHQ6YWxlcnQoMSki", + "PkRFRg==", + "PGEgaHJlZj0ieDBCamF2YXNjcmlwdDpqYXZhc2NyaXB0OmFsZXJ0KDEpIiBpZD0iZnV6emVsZW1l", + "bnQxIj50ZXN0PC9hPg==", + "PGEgaHJlZj0ieDBGamF2YXNjcmlwdDpqYXZhc2NyaXB0OmFsZXJ0KDEpIiBpZD0iZnV6emVsZW1l", + "bnQxIj50ZXN0PC9hPg==", + "PGEgaHJlZj0ieEMyeEEwamF2YXNjcmlwdDpqYXZhc2NyaXB0OmFsZXJ0KDEpIiBpZD0iZnV6emVs", + "ZW1lbnQxIj50ZXN0PC9hPg==", + "PGEgaHJlZj0ieDA1amF2YXNjcmlwdDpqYXZhc2NyaXB0OmFsZXJ0KDEpIiBpZD0iZnV6emVsZW1l", + "bnQxIj50ZXN0PC9hPg==", + "PGEgaHJlZj0ieEUxeEEweDhFamF2YXNjcmlwdDpqYXZhc2NyaXB0OmFsZXJ0KDEpIiBpZD0iZnV6", + "emVsZW1lbnQxIj50ZXN0PC9hPg==", + "PGEgaHJlZj0ieDE4amF2YXNjcmlwdDpqYXZhc2NyaXB0OmFsZXJ0KDEpIiBpZD0iZnV6emVsZW1l", + "bnQxIj50ZXN0PC9hPg==", + "PGEgaHJlZj0ieDExamF2YXNjcmlwdDpqYXZhc2NyaXB0OmFsZXJ0KDEpIiBpZD0iZnV6emVsZW1l", + "bnQxIj50ZXN0PC9hPg==", + "PGEgaHJlZj0ieEUyeDgweDg4amF2YXNjcmlwdDpqYXZhc2NyaXB0OmFsZXJ0KDEpIiBpZD0iZnV6", + "emVsZW1lbnQxIj50ZXN0PC9hPg==", + "PGEgaHJlZj0ieEUyeDgweDg5amF2YXNjcmlwdDpqYXZhc2NyaXB0OmFsZXJ0KDEpIiBpZD0iZnV6", + "emVsZW1lbnQxIj50ZXN0PC9hPg==", + "PGEgaHJlZj0ieEUyeDgweDgwamF2YXNjcmlwdDpqYXZhc2NyaXB0OmFsZXJ0KDEpIiBpZD0iZnV6", + "emVsZW1lbnQxIj50ZXN0PC9hPg==", + "PGEgaHJlZj0ieDE3amF2YXNjcmlwdDpqYXZhc2NyaXB0OmFsZXJ0KDEpIiBpZD0iZnV6emVsZW1l", + "bnQxIj50ZXN0PC9hPg==", + "PGEgaHJlZj0ieDAzamF2YXNjcmlwdDpqYXZhc2NyaXB0OmFsZXJ0KDEpIiBpZD0iZnV6emVsZW1l", + "bnQxIj50ZXN0PC9hPg==", + "PGEgaHJlZj0ieDBFamF2YXNjcmlwdDpqYXZhc2NyaXB0OmFsZXJ0KDEpIiBpZD0iZnV6emVsZW1l", + "bnQxIj50ZXN0PC9hPg==", + "PGEgaHJlZj0ieDFBamF2YXNjcmlwdDpqYXZhc2NyaXB0OmFsZXJ0KDEpIiBpZD0iZnV6emVsZW1l", + "bnQxIj50ZXN0PC9hPg==", + "PGEgaHJlZj0ieDAwamF2YXNjcmlwdDpqYXZhc2NyaXB0OmFsZXJ0KDEpIiBpZD0iZnV6emVsZW1l", + "bnQxIj50ZXN0PC9hPg==", + "PGEgaHJlZj0ieDEwamF2YXNjcmlwdDpqYXZhc2NyaXB0OmFsZXJ0KDEpIiBpZD0iZnV6emVsZW1l", + "bnQxIj50ZXN0PC9hPg==", + "PGEgaHJlZj0ieEUyeDgweDgyamF2YXNjcmlwdDpqYXZhc2NyaXB0OmFsZXJ0KDEpIiBpZD0iZnV6", + "emVsZW1lbnQxIj50ZXN0PC9hPg==", + "PGEgaHJlZj0ieDIwamF2YXNjcmlwdDpqYXZhc2NyaXB0OmFsZXJ0KDEpIiBpZD0iZnV6emVsZW1l", + "bnQxIj50ZXN0PC9hPg==", + "PGEgaHJlZj0ieDEzamF2YXNjcmlwdDpqYXZhc2NyaXB0OmFsZXJ0KDEpIiBpZD0iZnV6emVsZW1l", + "bnQxIj50ZXN0PC9hPg==", + "PGEgaHJlZj0ieDA5amF2YXNjcmlwdDpqYXZhc2NyaXB0OmFsZXJ0KDEpIiBpZD0iZnV6emVsZW1l", + "bnQxIj50ZXN0PC9hPg==", + "PGEgaHJlZj0ieEUyeDgweDhBamF2YXNjcmlwdDpqYXZhc2NyaXB0OmFsZXJ0KDEpIiBpZD0iZnV6", + "emVsZW1lbnQxIj50ZXN0PC9hPg==", + "PGEgaHJlZj0ieDE0amF2YXNjcmlwdDpqYXZhc2NyaXB0OmFsZXJ0KDEpIiBpZD0iZnV6emVsZW1l", + "bnQxIj50ZXN0PC9hPg==", + "PGEgaHJlZj0ieDE5amF2YXNjcmlwdDpqYXZhc2NyaXB0OmFsZXJ0KDEpIiBpZD0iZnV6emVsZW1l", + "bnQxIj50ZXN0PC9hPg==", + "PGEgaHJlZj0ieEUyeDgweEFGamF2YXNjcmlwdDpqYXZhc2NyaXB0OmFsZXJ0KDEpIiBpZD0iZnV6", + "emVsZW1lbnQxIj50ZXN0PC9hPg==", + "PGEgaHJlZj0ieDFGamF2YXNjcmlwdDpqYXZhc2NyaXB0OmFsZXJ0KDEpIiBpZD0iZnV6emVsZW1l", + "bnQxIj50ZXN0PC9hPg==", + "PGEgaHJlZj0ieEUyeDgweDgxamF2YXNjcmlwdDpqYXZhc2NyaXB0OmFsZXJ0KDEpIiBpZD0iZnV6", + "emVsZW1lbnQxIj50ZXN0PC9hPg==", + "PGEgaHJlZj0ieDFEamF2YXNjcmlwdDpqYXZhc2NyaXB0OmFsZXJ0KDEpIiBpZD0iZnV6emVsZW1l", + "bnQxIj50ZXN0PC9hPg==", + "PGEgaHJlZj0ieEUyeDgweDg3amF2YXNjcmlwdDpqYXZhc2NyaXB0OmFsZXJ0KDEpIiBpZD0iZnV6", + "emVsZW1lbnQxIj50ZXN0PC9hPg==", + "PGEgaHJlZj0ieDA3amF2YXNjcmlwdDpqYXZhc2NyaXB0OmFsZXJ0KDEpIiBpZD0iZnV6emVsZW1l", + "bnQxIj50ZXN0PC9hPg==", + "PGEgaHJlZj0ieEUxeDlBeDgwamF2YXNjcmlwdDpqYXZhc2NyaXB0OmFsZXJ0KDEpIiBpZD0iZnV6", + "emVsZW1lbnQxIj50ZXN0PC9hPg==", + "PGEgaHJlZj0ieEUyeDgweDgzamF2YXNjcmlwdDpqYXZhc2NyaXB0OmFsZXJ0KDEpIiBpZD0iZnV6", + "emVsZW1lbnQxIj50ZXN0PC9hPg==", + "PGEgaHJlZj0ieDA0amF2YXNjcmlwdDpqYXZhc2NyaXB0OmFsZXJ0KDEpIiBpZD0iZnV6emVsZW1l", + "bnQxIj50ZXN0PC9hPg==", + "PGEgaHJlZj0ieDAxamF2YXNjcmlwdDpqYXZhc2NyaXB0OmFsZXJ0KDEpIiBpZD0iZnV6emVsZW1l", + "bnQxIj50ZXN0PC9hPg==", + "PGEgaHJlZj0ieDA4amF2YXNjcmlwdDpqYXZhc2NyaXB0OmFsZXJ0KDEpIiBpZD0iZnV6emVsZW1l", + "bnQxIj50ZXN0PC9hPg==", + "PGEgaHJlZj0ieEUyeDgweDg0amF2YXNjcmlwdDpqYXZhc2NyaXB0OmFsZXJ0KDEpIiBpZD0iZnV6", + "emVsZW1lbnQxIj50ZXN0PC9hPg==", + "PGEgaHJlZj0ieEUyeDgweDg2amF2YXNjcmlwdDpqYXZhc2NyaXB0OmFsZXJ0KDEpIiBpZD0iZnV6", + "emVsZW1lbnQxIj50ZXN0PC9hPg==", + "PGEgaHJlZj0ieEUzeDgweDgwamF2YXNjcmlwdDpqYXZhc2NyaXB0OmFsZXJ0KDEpIiBpZD0iZnV6", + "emVsZW1lbnQxIj50ZXN0PC9hPg==", + "PGEgaHJlZj0ieDEyamF2YXNjcmlwdDpqYXZhc2NyaXB0OmFsZXJ0KDEpIiBpZD0iZnV6emVsZW1l", + "bnQxIj50ZXN0PC9hPg==", + "PGEgaHJlZj0ieDBEamF2YXNjcmlwdDpqYXZhc2NyaXB0OmFsZXJ0KDEpIiBpZD0iZnV6emVsZW1l", + "bnQxIj50ZXN0PC9hPg==", + "PGEgaHJlZj0ieDBBamF2YXNjcmlwdDpqYXZhc2NyaXB0OmFsZXJ0KDEpIiBpZD0iZnV6emVsZW1l", + "bnQxIj50ZXN0PC9hPg==", + "PGEgaHJlZj0ieDBDamF2YXNjcmlwdDpqYXZhc2NyaXB0OmFsZXJ0KDEpIiBpZD0iZnV6emVsZW1l", + "bnQxIj50ZXN0PC9hPg==", + "PGEgaHJlZj0ieDE1amF2YXNjcmlwdDpqYXZhc2NyaXB0OmFsZXJ0KDEpIiBpZD0iZnV6emVsZW1l", + "bnQxIj50ZXN0PC9hPg==", + "PGEgaHJlZj0ieEUyeDgweEE4amF2YXNjcmlwdDpqYXZhc2NyaXB0OmFsZXJ0KDEpIiBpZD0iZnV6", + "emVsZW1lbnQxIj50ZXN0PC9hPg==", + "PGEgaHJlZj0ieDE2amF2YXNjcmlwdDpqYXZhc2NyaXB0OmFsZXJ0KDEpIiBpZD0iZnV6emVsZW1l", + "bnQxIj50ZXN0PC9hPg==", + "PGEgaHJlZj0ieDAyamF2YXNjcmlwdDpqYXZhc2NyaXB0OmFsZXJ0KDEpIiBpZD0iZnV6emVsZW1l", + "bnQxIj50ZXN0PC9hPg==", + "PGEgaHJlZj0ieDFCamF2YXNjcmlwdDpqYXZhc2NyaXB0OmFsZXJ0KDEpIiBpZD0iZnV6emVsZW1l", + "bnQxIj50ZXN0PC9hPg==", + "PGEgaHJlZj0ieDA2amF2YXNjcmlwdDpqYXZhc2NyaXB0OmFsZXJ0KDEpIiBpZD0iZnV6emVsZW1l", + "bnQxIj50ZXN0PC9hPg==", + "PGEgaHJlZj0ieEUyeDgweEE5amF2YXNjcmlwdDpqYXZhc2NyaXB0OmFsZXJ0KDEpIiBpZD0iZnV6", + "emVsZW1lbnQxIj50ZXN0PC9hPg==", + "PGEgaHJlZj0ieEUyeDgweDg1amF2YXNjcmlwdDpqYXZhc2NyaXB0OmFsZXJ0KDEpIiBpZD0iZnV6", + "emVsZW1lbnQxIj50ZXN0PC9hPg==", + "PGEgaHJlZj0ieDFFamF2YXNjcmlwdDpqYXZhc2NyaXB0OmFsZXJ0KDEpIiBpZD0iZnV6emVsZW1l", + "bnQxIj50ZXN0PC9hPg==", + "PGEgaHJlZj0ieEUyeDgxeDlGamF2YXNjcmlwdDpqYXZhc2NyaXB0OmFsZXJ0KDEpIiBpZD0iZnV6", + "emVsZW1lbnQxIj50ZXN0PC9hPg==", + "PGEgaHJlZj0ieDFDamF2YXNjcmlwdDpqYXZhc2NyaXB0OmFsZXJ0KDEpIiBpZD0iZnV6emVsZW1l", + "bnQxIj50ZXN0PC9hPg==", + "PGEgaHJlZj0iamF2YXNjcmlwdHgwMDpqYXZhc2NyaXB0OmFsZXJ0KDEpIiBpZD0iZnV6emVsZW1l", + "bnQxIj50ZXN0PC9hPg==", + "PGEgaHJlZj0iamF2YXNjcmlwdHgzQTpqYXZhc2NyaXB0OmFsZXJ0KDEpIiBpZD0iZnV6emVsZW1l", + "bnQxIj50ZXN0PC9hPg==", + "PGEgaHJlZj0iamF2YXNjcmlwdHgwOTpqYXZhc2NyaXB0OmFsZXJ0KDEpIiBpZD0iZnV6emVsZW1l", + "bnQxIj50ZXN0PC9hPg==", + "PGEgaHJlZj0iamF2YXNjcmlwdHgwRDpqYXZhc2NyaXB0OmFsZXJ0KDEpIiBpZD0iZnV6emVsZW1l", + "bnQxIj50ZXN0PC9hPg==", + "PGEgaHJlZj0iamF2YXNjcmlwdHgwQTpqYXZhc2NyaXB0OmFsZXJ0KDEpIiBpZD0iZnV6emVsZW1l", + "bnQxIj50ZXN0PC9hPg==", + "YCInPjxpbWcgc3JjPXh4eDp4IHgwQW9uZXJyb3I9amF2YXNjcmlwdDphbGVydCgxKT4=", + "YCInPjxpbWcgc3JjPXh4eDp4IHgyMm9uZXJyb3I9amF2YXNjcmlwdDphbGVydCgxKT4=", + "YCInPjxpbWcgc3JjPXh4eDp4IHgwQm9uZXJyb3I9amF2YXNjcmlwdDphbGVydCgxKT4=", + "YCInPjxpbWcgc3JjPXh4eDp4IHgwRG9uZXJyb3I9amF2YXNjcmlwdDphbGVydCgxKT4=", + "YCInPjxpbWcgc3JjPXh4eDp4IHgyRm9uZXJyb3I9amF2YXNjcmlwdDphbGVydCgxKT4=", + "YCInPjxpbWcgc3JjPXh4eDp4IHgwOW9uZXJyb3I9amF2YXNjcmlwdDphbGVydCgxKT4=", + "YCInPjxpbWcgc3JjPXh4eDp4IHgwQ29uZXJyb3I9amF2YXNjcmlwdDphbGVydCgxKT4=", + "YCInPjxpbWcgc3JjPXh4eDp4IHgwMG9uZXJyb3I9amF2YXNjcmlwdDphbGVydCgxKT4=", + "YCInPjxpbWcgc3JjPXh4eDp4IHgyN29uZXJyb3I9amF2YXNjcmlwdDphbGVydCgxKT4=", + "YCInPjxpbWcgc3JjPXh4eDp4IHgyMG9uZXJyb3I9amF2YXNjcmlwdDphbGVydCgxKT4=", + "ImAnPjxzY3JpcHQ+eDNCamF2YXNjcmlwdDphbGVydCgxKTwvc2NyaXB0Pg==", + "ImAnPjxzY3JpcHQ+eDBEamF2YXNjcmlwdDphbGVydCgxKTwvc2NyaXB0Pg==", + "ImAnPjxzY3JpcHQ+eEVGeEJCeEJGamF2YXNjcmlwdDphbGVydCgxKTwvc2NyaXB0Pg==", + "ImAnPjxzY3JpcHQ+eEUyeDgweDgxamF2YXNjcmlwdDphbGVydCgxKTwvc2NyaXB0Pg==", + "ImAnPjxzY3JpcHQ+eEUyeDgweDg0amF2YXNjcmlwdDphbGVydCgxKTwvc2NyaXB0Pg==", + "ImAnPjxzY3JpcHQ+eEUzeDgweDgwamF2YXNjcmlwdDphbGVydCgxKTwvc2NyaXB0Pg==", + "ImAnPjxzY3JpcHQ+eDA5amF2YXNjcmlwdDphbGVydCgxKTwvc2NyaXB0Pg==", + "ImAnPjxzY3JpcHQ+eEUyeDgweDg5amF2YXNjcmlwdDphbGVydCgxKTwvc2NyaXB0Pg==", + "ImAnPjxzY3JpcHQ+eEUyeDgweDg1amF2YXNjcmlwdDphbGVydCgxKTwvc2NyaXB0Pg==", + "ImAnPjxzY3JpcHQ+eEUyeDgweDg4amF2YXNjcmlwdDphbGVydCgxKTwvc2NyaXB0Pg==", + "ImAnPjxzY3JpcHQ+eDAwamF2YXNjcmlwdDphbGVydCgxKTwvc2NyaXB0Pg==", + "ImAnPjxzY3JpcHQ+eEUyeDgweEE4amF2YXNjcmlwdDphbGVydCgxKTwvc2NyaXB0Pg==", + "ImAnPjxzY3JpcHQ+eEUyeDgweDhBamF2YXNjcmlwdDphbGVydCgxKTwvc2NyaXB0Pg==", + "ImAnPjxzY3JpcHQ+eEUxeDlBeDgwamF2YXNjcmlwdDphbGVydCgxKTwvc2NyaXB0Pg==", + "ImAnPjxzY3JpcHQ+eDBDamF2YXNjcmlwdDphbGVydCgxKTwvc2NyaXB0Pg==", + "ImAnPjxzY3JpcHQ+eDJCamF2YXNjcmlwdDphbGVydCgxKTwvc2NyaXB0Pg==", + "ImAnPjxzY3JpcHQ+eEYweDkweDk2eDlBamF2YXNjcmlwdDphbGVydCgxKTwvc2NyaXB0Pg==", + "ImAnPjxzY3JpcHQ+LWphdmFzY3JpcHQ6YWxlcnQoMSk8L3NjcmlwdD4=", + "ImAnPjxzY3JpcHQ+eDBBamF2YXNjcmlwdDphbGVydCgxKTwvc2NyaXB0Pg==", + "ImAnPjxzY3JpcHQ+eEUyeDgweEFGamF2YXNjcmlwdDphbGVydCgxKTwvc2NyaXB0Pg==", + "ImAnPjxzY3JpcHQ+eDdFamF2YXNjcmlwdDphbGVydCgxKTwvc2NyaXB0Pg==", + "ImAnPjxzY3JpcHQ+eEUyeDgweDg3amF2YXNjcmlwdDphbGVydCgxKTwvc2NyaXB0Pg==", + "ImAnPjxzY3JpcHQ+eEUyeDgxeDlGamF2YXNjcmlwdDphbGVydCgxKTwvc2NyaXB0Pg==", + "ImAnPjxzY3JpcHQ+eEUyeDgweEE5amF2YXNjcmlwdDphbGVydCgxKTwvc2NyaXB0Pg==", + "ImAnPjxzY3JpcHQ+eEMyeDg1amF2YXNjcmlwdDphbGVydCgxKTwvc2NyaXB0Pg==", + "ImAnPjxzY3JpcHQ+eEVGeEJGeEFFamF2YXNjcmlwdDphbGVydCgxKTwvc2NyaXB0Pg==", + "ImAnPjxzY3JpcHQ+eEUyeDgweDgzamF2YXNjcmlwdDphbGVydCgxKTwvc2NyaXB0Pg==", + "ImAnPjxzY3JpcHQ+eEUyeDgweDhCamF2YXNjcmlwdDphbGVydCgxKTwvc2NyaXB0Pg==", + "ImAnPjxzY3JpcHQ+eEVGeEJGeEJFamF2YXNjcmlwdDphbGVydCgxKTwvc2NyaXB0Pg==", + "ImAnPjxzY3JpcHQ+eEUyeDgweDgwamF2YXNjcmlwdDphbGVydCgxKTwvc2NyaXB0Pg==", + "ImAnPjxzY3JpcHQ+eDIxamF2YXNjcmlwdDphbGVydCgxKTwvc2NyaXB0Pg==", + "ImAnPjxzY3JpcHQ+eEUyeDgweDgyamF2YXNjcmlwdDphbGVydCgxKTwvc2NyaXB0Pg==", + "ImAnPjxzY3JpcHQ+eEUyeDgweDg2amF2YXNjcmlwdDphbGVydCgxKTwvc2NyaXB0Pg==", + "ImAnPjxzY3JpcHQ+eEUxeEEweDhFamF2YXNjcmlwdDphbGVydCgxKTwvc2NyaXB0Pg==", + "ImAnPjxzY3JpcHQ+eDBCamF2YXNjcmlwdDphbGVydCgxKTwvc2NyaXB0Pg==", + "ImAnPjxzY3JpcHQ+eDIwamF2YXNjcmlwdDphbGVydCgxKTwvc2NyaXB0Pg==", + "ImAnPjxzY3JpcHQ+eEMyeEEwamF2YXNjcmlwdDphbGVydCgxKTwvc2NyaXB0Pg==", + "PGltZyB4MDBzcmM9eCBvbmVycm9yPSJhbGVydCgxKSI+", + "PGltZyB4NDdzcmM9eCBvbmVycm9yPSJqYXZhc2NyaXB0OmFsZXJ0KDEpIj4=", + "PGltZyB4MTFzcmM9eCBvbmVycm9yPSJqYXZhc2NyaXB0OmFsZXJ0KDEpIj4=", + "PGltZyB4MTJzcmM9eCBvbmVycm9yPSJqYXZhc2NyaXB0OmFsZXJ0KDEpIj4=", + "PGltZ3g0N3NyYz14IG9uZXJyb3I9ImphdmFzY3JpcHQ6YWxlcnQoMSkiPg==", + "PGltZ3gxMHNyYz14IG9uZXJyb3I9ImphdmFzY3JpcHQ6YWxlcnQoMSkiPg==", + "PGltZ3gxM3NyYz14IG9uZXJyb3I9ImphdmFzY3JpcHQ6YWxlcnQoMSkiPg==", + "PGltZ3gzMnNyYz14IG9uZXJyb3I9ImphdmFzY3JpcHQ6YWxlcnQoMSkiPg==", + "PGltZ3g0N3NyYz14IG9uZXJyb3I9ImphdmFzY3JpcHQ6YWxlcnQoMSkiPg==", + "PGltZ3gxMXNyYz14IG9uZXJyb3I9ImphdmFzY3JpcHQ6YWxlcnQoMSkiPg==", + "PGltZyB4NDdzcmM9eCBvbmVycm9yPSJqYXZhc2NyaXB0OmFsZXJ0KDEpIj4=", + "PGltZyB4MzRzcmM9eCBvbmVycm9yPSJqYXZhc2NyaXB0OmFsZXJ0KDEpIj4=", + "PGltZyB4MzlzcmM9eCBvbmVycm9yPSJqYXZhc2NyaXB0OmFsZXJ0KDEpIj4=", + "PGltZyB4MDBzcmM9eCBvbmVycm9yPSJqYXZhc2NyaXB0OmFsZXJ0KDEpIj4=", + "PGltZyBzcmN4MDk9eCBvbmVycm9yPSJqYXZhc2NyaXB0OmFsZXJ0KDEpIj4=", + "PGltZyBzcmN4MTA9eCBvbmVycm9yPSJqYXZhc2NyaXB0OmFsZXJ0KDEpIj4=", + "PGltZyBzcmN4MTM9eCBvbmVycm9yPSJqYXZhc2NyaXB0OmFsZXJ0KDEpIj4=", + "PGltZyBzcmN4MzI9eCBvbmVycm9yPSJqYXZhc2NyaXB0OmFsZXJ0KDEpIj4=", + "PGltZyBzcmN4MTI9eCBvbmVycm9yPSJqYXZhc2NyaXB0OmFsZXJ0KDEpIj4=", + "PGltZyBzcmN4MTE9eCBvbmVycm9yPSJqYXZhc2NyaXB0OmFsZXJ0KDEpIj4=", + "PGltZyBzcmN4MDA9eCBvbmVycm9yPSJqYXZhc2NyaXB0OmFsZXJ0KDEpIj4=", + "PGltZyBzcmN4NDc9eCBvbmVycm9yPSJqYXZhc2NyaXB0OmFsZXJ0KDEpIj4=", + "PGltZyBzcmM9eHgwOW9uZXJyb3I9ImphdmFzY3JpcHQ6YWxlcnQoMSkiPg==", + "PGltZyBzcmM9eHgxMG9uZXJyb3I9ImphdmFzY3JpcHQ6YWxlcnQoMSkiPg==", + "PGltZyBzcmM9eHgxMW9uZXJyb3I9ImphdmFzY3JpcHQ6YWxlcnQoMSkiPg==", + "PGltZyBzcmM9eHgxMm9uZXJyb3I9ImphdmFzY3JpcHQ6YWxlcnQoMSkiPg==", + "PGltZyBzcmM9eHgxM29uZXJyb3I9ImphdmFzY3JpcHQ6YWxlcnQoMSkiPg==", + "PGltZ1thXVtiXVtjXXNyY1tkXT14W2Vdb25lcnJvcj1bZl0iYWxlcnQoMSkiPg==", + "PGltZyBzcmM9eCBvbmVycm9yPXgwOSJqYXZhc2NyaXB0OmFsZXJ0KDEpIj4=", + "PGltZyBzcmM9eCBvbmVycm9yPXgxMCJqYXZhc2NyaXB0OmFsZXJ0KDEpIj4=", + "PGltZyBzcmM9eCBvbmVycm9yPXgxMSJqYXZhc2NyaXB0OmFsZXJ0KDEpIj4=", + "PGltZyBzcmM9eCBvbmVycm9yPXgxMiJqYXZhc2NyaXB0OmFsZXJ0KDEpIj4=", + "PGltZyBzcmM9eCBvbmVycm9yPXgzMiJqYXZhc2NyaXB0OmFsZXJ0KDEpIj4=", + "PGltZyBzcmM9eCBvbmVycm9yPXgwMCJqYXZhc2NyaXB0OmFsZXJ0KDEpIj4=", + "PGEgaHJlZj1qYXZhJiMxJiMyJiMzJiM0JiM1JiM2JiM3JiM4JiMxMSYjMTJzY3JpcHQ6amF2YXNj", + "cmlwdDphbGVydCgxKT5YWFg8L2E+", + "PGltZyBzcmM9InhgIGA8c2NyaXB0PmphdmFzY3JpcHQ6YWxlcnQoMSk8L3NjcmlwdD4iYCBgPg==", + "PGltZyBzcmMgb25lcnJvciAvIiAnIj0gYWx0PWphdmFzY3JpcHQ6YWxlcnQoMSkvLyI+", + "PHRpdGxlIG9ucHJvcGVydHljaGFuZ2U9amF2YXNjcmlwdDphbGVydCgxKT48L3RpdGxlPjx0aXRs", + "ZSB0aXRsZT0+", + "PGEgaHJlZj1odHRwOi8vZm9vLmJhci8jeD1geT48L2E+PGltZyBhbHQ9ImA+PGltZyBzcmM9eDp4", + "IG9uZXJyb3I9amF2YXNjcmlwdDphbGVydCgxKT48L2E+Ij4=", + "PCEtLVtpZl0+PHNjcmlwdD5qYXZhc2NyaXB0OmFsZXJ0KDEpPC9zY3JpcHQgLS0+", + "PCEtLVtpZjxpbWcgc3JjPXggb25lcnJvcj1qYXZhc2NyaXB0OmFsZXJ0KDEpLy9dPiAtLT4=", + "PHNjcmlwdCBzcmM9Ii8lKGpzY3JpcHQpcyI+PC9zY3JpcHQ+", + "PHNjcmlwdCBzcmM9IlwlKGpzY3JpcHQpcyI+PC9zY3JpcHQ+", + "PElNRyAiIiI+PFNDUklQVD5hbGVydCgiWFNTIik8L1NDUklQVD4iPg==", + "PElNRyBTUkM9amF2YXNjcmlwdDphbGVydChTdHJpbmcuZnJvbUNoYXJDb2RlKDg4LDgzLDgzKSk+", + "PElNRyBTUkM9IyBvbm1vdXNlb3Zlcj0iYWxlcnQoJ3h4cycpIj4=", + "PElNRyBTUkM9IG9ubW91c2VvdmVyPSJhbGVydCgneHhzJykiPg==", + "PElNRyBvbm1vdXNlb3Zlcj0iYWxlcnQoJ3h4cycpIj4=", + "PElNRyBTUkM9JiMxMDY7JiM5NzsmIzExODsmIzk3OyYjMTE1OyYjOTk7JiMxMTQ7JiMxMDU7JiMx", + "MTI7JiMxMTY7JiM1ODsmIzk3OyYjMTA4OyYjMTAxOyYjMTE0OyYjMTE2OyYjNDA7JiMzOTsmIzg4", + "OyYjODM7JiM4MzsmIzM5OyYjNDE7Pg==", + "PElNRyBTUkM9JiMwMDAwMTA2JiMwMDAwMDk3JiMwMDAwMTE4JiMwMDAwMDk3JiMwMDAwMTE1JiMw", + "MDAwMDk5JiMwMDAwMTE0JiMwMDAwMTA1JiMwMDAwMTEyJiMwMDAwMTE2JiMwMDAwMDU4JiMwMDAw", + "MDk3JiMwMDAwMTA4JiMwMDAwMTAxJiMwMDAwMTE0JiMwMDAwMTE2JiMwMDAwMDQwJiMwMDAwMDM5", + "JiMwMDAwMDg4JiMwMDAwMDgzJiMwMDAwMDgzJiMwMDAwMDM5JiMwMDAwMDQxPg==", + "PElNRyBTUkM9JiN4NkEmI3g2MSYjeDc2JiN4NjEmI3g3MyYjeDYzJiN4NzImI3g2OSYjeDcwJiN4", + "NzQmI3gzQSYjeDYxJiN4NkMmI3g2NSYjeDcyJiN4NzQmI3gyOCYjeDI3JiN4NTgmI3g1MyYjeDUz", + "JiN4MjcmI3gyOT4=", + "PElNRyBTUkM9ImphdiBhc2NyaXB0OmFsZXJ0KCdYU1MnKTsiPg==", + "PElNRyBTUkM9ImphdiYjeDA5O2FzY3JpcHQ6YWxlcnQoJ1hTUycpOyI+", + "PElNRyBTUkM9ImphdiYjeDBBO2FzY3JpcHQ6YWxlcnQoJ1hTUycpOyI+", + "PElNRyBTUkM9ImphdiYjeDBEO2FzY3JpcHQ6YWxlcnQoJ1hTUycpOyI+", + "cGVybCAtZSAncHJpbnQgIjxJTUcgU1JDPWphdmEwc2NyaXB0OmFsZXJ0KCJYU1MiKT4iOycgPiBv", + "dXQ=", + "PElNRyBTUkM9IiAmIzE0OyBqYXZhc2NyaXB0OmFsZXJ0KCdYU1MnKTsiPg==", + "PFNDUklQVC9YU1MgU1JDPSJodHRwOi8vaGEuY2tlcnMub3JnL3hzcy5qcyI+PC9TQ1JJUFQ+", + "PEJPRFkgb25sb2FkISMkJSYoKSp+Ky1fLiw6Oz9AWy98XV5gPWFsZXJ0KCJYU1MiKT4=", + "PFNDUklQVC9TUkM9Imh0dHA6Ly9oYS5ja2Vycy5vcmcveHNzLmpzIj48L1NDUklQVD4=", + "PDxTQ1JJUFQ+YWxlcnQoIlhTUyIpOy8vPDwvU0NSSVBUPg==", + "PFNDUklQVCBTUkM9aHR0cDovL2hhLmNrZXJzLm9yZy94c3MuanM/PCBCID4=", + "PFNDUklQVCBTUkM9Ly9oYS5ja2Vycy5vcmcvLmo+", + "PElNRyBTUkM9ImphdmFzY3JpcHQ6YWxlcnQoJ1hTUycpIg==", + "PGlmcmFtZSBzcmM9aHR0cDovL2hhLmNrZXJzLm9yZy9zY3JpcHRsZXQuaHRtbCA8", + "IjthbGVydCgnWFNTJyk7Ly8=", + "PHUgb25jb3B5PWFsZXJ0KCk+IENvcHkgbWU8L3U+", + "PGkgb253aGVlbD1hbGVydCgxKT4gU2Nyb2xsIG92ZXIgbWUgPC9pPg==", + "PHBsYWludGV4dD4=", + "aHR0cDovL2EvJSUzMCUzMA==", + "PC90ZXh0YXJlYT48c2NyaXB0PmFsZXJ0KDEyMyk8L3NjcmlwdD4=", + "MTtEUk9QIFRBQkxFIHVzZXJz", + "MSc7IERST1AgVEFCTEUgdXNlcnMtLSAx", + "JyBPUiAxPTEgLS0gMQ==", + "JyBPUiAnMSc9JzE=", + "JQ==", + "Xw==", + "LQ==", + "LS0=", + "LS12ZXJzaW9u", + "LS1oZWxw", + "JFVTRVI=", + "L2Rldi9udWxsOyB0b3VjaCAvdG1wL2JsbnMuZmFpbCA7IGVjaG8=", + "YHRvdWNoIC90bXAvYmxucy5mYWlsYA==", + "JCh0b3VjaCAvdG1wL2JsbnMuZmFpbCk=", + "QHtbc3lzdGVtICJ0b3VjaCAvdG1wL2JsbnMuZmFpbCJdfQ==", + "ZXZhbCgicHV0cyAnaGVsbG8gd29ybGQnIik=", + "U3lzdGVtKCJscyAtYWwgLyIp", + "YGxzIC1hbCAvYA==", + "S2VybmVsLmV4ZWMoImxzIC1hbCAvIik=", + "S2VybmVsLmV4aXQoMSk=", + "JXgoJ2xzIC1hbCAvJyk=", + "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iSVNPLTg4NTktMSI/PjwhRE9DVFlQRSBmb28g", + "WyA8IUVMRU1FTlQgZm9vIEFOWSA+PCFFTlRJVFkgeHhlIFNZU1RFTSAiZmlsZTovLy9ldGMvcGFz", + "c3dkIiA+XT48Zm9vPiZ4eGU7PC9mb28+", + "JEhPTUU=", + "JEVOVnsnSE9NRSd9", + "JWQ=", + "JXM=", + "ezB9", + "JSouKnM=", + "Li4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vZXRjL3Bhc3N3ZCUwMA==", + "Li4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vZXRjL2hvc3Rz", + "KCkgeyAwOyB9OyB0b3VjaCAvdG1wL2JsbnMuc2hlbGxzaG9jazEuZmFpbDs=", + "KCkgeyBfOyB9ID5fWyQoJCgpKV0geyB0b3VjaCAvdG1wL2JsbnMuc2hlbGxzaG9jazIuZmFpbDsg", + "fQ==", + "PDw8ICVzKHVuPSclcycpID0gJXU=", + "KysrQVRIMA==", + "Q09O", + "UFJO", + "QVVY", + "Q0xPQ0sk", + "TlVM", + "QTo=", + "Wlo6", + "Q09NMQ==", + "TFBUMQ==", + "TFBUMg==", + "TFBUMw==", + "Q09NMg==", + "Q09NMw==", + "Q09NNA==", + "RENDIFNFTkQgU1RBUlRLRVlMT0dHRVIgMCAwIDA=", + "U2N1bnRob3JwZSBHZW5lcmFsIEhvc3BpdGFs", + "UGVuaXN0b25lIENvbW11bml0eSBDaHVyY2g=", + "TGlnaHR3YXRlciBDb3VudHJ5IFBhcms=", + "SmltbXkgQ2xpdGhlcm9l", + "SG9ybmltYW4gTXVzZXVt", + "c2hpdGFrZSBtdXNocm9vbXM=", + "Um9tYW5zSW5TdXNzZXguY28udWs=", + "aHR0cDovL3d3dy5jdW0ucWMuY2Ev", + "Q3JhaWcgQ29ja2J1cm4sIFNvZnR3YXJlIFNwZWNpYWxpc3Q=", + "TGluZGEgQ2FsbGFoYW4=", + "RHIuIEhlcm1hbiBJLiBMaWJzaGl0eg==", + "bWFnbmEgY3VtIGxhdWRl", + "U3VwZXIgQm93bCBYWFg=", + "bWVkaWV2YWwgZXJlY3Rpb24gb2YgcGFyYXBldHM=", + "ZXZhbHVhdGU=", + "bW9jaGE=", + "ZXhwcmVzc2lvbg==", + "QXJzZW5hbCBjYW5hbA==", + "Y2xhc3NpYw==", + "VHlzb24gR2F5", + "RGljayBWYW4gRHlrZQ==", + "YmFzZW1lbnQ=", + "SWYgeW91J3JlIHJlYWRpbmcgdGhpcywgeW91J3ZlIGJlZW4gaW4gYSBjb21hIGZvciBhbG1vc3Qg", + "MjAgeWVhcnMgbm93LiBXZSdyZSB0cnlpbmcgYSBuZXcgdGVjaG5pcXVlLiBXZSBkb24ndCBrbm93", + "IHdoZXJlIHRoaXMgbWVzc2FnZSB3aWxsIGVuZCB1cCBpbiB5b3VyIGRyZWFtLCBidXQgd2UgaG9w", + "ZSBpdCB3b3Jrcy4gUGxlYXNlIHdha2UgdXAsIHdlIG1pc3MgeW91Lg==", + "Um9zZXMgYXJlIBtbMDszMW1yZWQbWzBtLCB2aW9sZXRzIGFyZSAbWzA7MzRtYmx1ZS4gSG9wZSB5", + "b3UgZW5qb3kgdGVybWluYWwgaHVl", + "QnV0IG5vdy4uLhtbMjBDZm9yIG15IGdyZWF0ZXN0IHRyaWNrLi4uG1s4bQ==", + "VGhlIHF1aWMICAgICAhrIGJyb3duIGZvBwcHBwcHBwcHBwd4Li4uIFtCZWVlZXBd", + "UG93ZXLZhNmP2YTZj9i12ZHYqNmP2YTZj9mE2LXZkdio2Y/Ysdix2Ysg4KWjIOClo2gg4KWjIOCl", + "o+WGlw==", + "2q/ahtm+2pg=", + "eyUgcHJpbnQgJ3gnICogNjQgKiAxMDI0KiozICV9", + "e3sgIiIuX19jbGFzc19fLl9fbXJvX19bMl0uX19zdWJjbGFzc2VzX18oKVs0MF0oIi9ldGMvcGFz", + "c3dkIikucmVhZCgpIH19" +] + diff --git a/compiler/noirc_frontend/src/lexer/errors.rs b/compiler/noirc_frontend/src/lexer/errors.rs index 35a07c11e0a..73c75af4cd7 100644 --- a/compiler/noirc_frontend/src/lexer/errors.rs +++ b/compiler/noirc_frontend/src/lexer/errors.rs @@ -96,8 +96,8 @@ impl LexerErrorKind { } } -impl From for Diagnostic { - fn from(error: LexerErrorKind) -> Diagnostic { +impl<'a> From<&'a LexerErrorKind> for Diagnostic { + fn from(error: &'a LexerErrorKind) -> Diagnostic { let (primary, secondary, span) = error.parts(); Diagnostic::simple_error(primary, secondary, span) } diff --git a/compiler/noirc_frontend/src/lexer/lexer.rs b/compiler/noirc_frontend/src/lexer/lexer.rs index cf66ece0c30..2d1ebf530e3 100644 --- a/compiler/noirc_frontend/src/lexer/lexer.rs +++ b/compiler/noirc_frontend/src/lexer/lexer.rs @@ -2,7 +2,9 @@ use crate::token::{Attribute, DocStyle}; use super::{ errors::LexerErrorKind, - token::{IntType, Keyword, SpannedToken, Token, Tokens}, + token::{ + token_to_borrowed_token, BorrowedToken, IntType, Keyword, SpannedToken, Token, Tokens, + }, }; use acvm::FieldElement; use noirc_errors::{Position, Span}; @@ -21,6 +23,21 @@ pub struct Lexer<'a> { pub type SpannedTokenResult = Result; +pub(crate) fn from_spanned_token_result( + token_result: &SpannedTokenResult, +) -> Result<(usize, BorrowedToken<'_>, usize), LexerErrorKind> { + token_result + .as_ref() + .map(|spanned_token| { + ( + spanned_token.to_span().start() as usize, + token_to_borrowed_token(spanned_token.into()), + spanned_token.to_span().end() as usize, + ) + }) + .map_err(Clone::clone) +} + impl<'a> Lexer<'a> { /// Given a source file of noir code, return all the tokens in the file /// in order, along with any lexing errors that occurred. @@ -94,7 +111,7 @@ impl<'a> Lexer<'a> { fn next_token(&mut self) -> SpannedTokenResult { match self.next_char() { - Some(x) if x.is_whitespace() => { + Some(x) if Self::is_code_whitespace(x) => { let spanned = self.eat_whitespace(x); if self.skip_whitespaces { self.next_token() @@ -560,16 +577,21 @@ impl<'a> Lexer<'a> { } } + fn is_code_whitespace(c: char) -> bool { + c == '\t' || c == '\n' || c == '\r' || c == ' ' + } + /// Skips white space. They are not significant in the source language 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()); + let whitespace = self.eat_while(initial_char.into(), Self::is_code_whitespace); SpannedToken::new(Token::Whitespace(whitespace), Span::inclusive(start, self.position)) } } impl<'a> Iterator for Lexer<'a> { type Item = SpannedTokenResult; + fn next(&mut self) -> Option { if self.done { None @@ -578,10 +600,12 @@ impl<'a> Iterator for Lexer<'a> { } } } + #[cfg(test)] mod tests { use super::*; use crate::token::{FunctionAttribute, SecondaryAttribute, TestScope}; + #[test] fn test_single_double_char() { let input = "! != + ( ) { } [ ] | , ; : :: < <= > >= & - -> . .. % / * = == << >>"; @@ -726,6 +750,16 @@ mod tests { ); } + #[test] + fn fold_attribute() { + let input = r#"#[fold]"#; + + let mut lexer = Lexer::new(input); + let token = lexer.next_token().unwrap(); + + assert_eq!(token.token(), &Token::Attribute(Attribute::Function(FunctionAttribute::Fold))); + } + #[test] fn contract_library_method_attribute() { let input = r#"#[contract_library_method]"#; @@ -1087,4 +1121,114 @@ mod tests { assert_eq!(got, token); } } + + // returns a vector of: + // (expected_token_discriminator, strings_to_lex) + // expected_token_discriminator matches a given token when + // std::mem::discriminant returns the same discriminant for both. + fn blns_base64_to_statements(base64_str: String) -> Vec<(Option, Vec)> { + use base64::engine::general_purpose; + use std::borrow::Cow; + use std::io::Cursor; + use std::io::Read; + + let mut wrapped_reader = Cursor::new(base64_str); + let mut decoder = + base64::read::DecoderReader::new(&mut wrapped_reader, &general_purpose::STANDARD); + let mut base64_decoded = Vec::new(); + decoder.read_to_end(&mut base64_decoded).unwrap(); + + // NOTE: when successful, this is the same conversion method as used in + // noirc_driver::stdlib::stdlib_paths_with_source, viz. + // + // let source = std::str::from_utf8(..).unwrap().to_string(); + let s: Cow<'_, str> = match std::str::from_utf8(&base64_decoded) { + Ok(s) => std::borrow::Cow::Borrowed(s), + Err(_err) => { + // recover as much of the string as possible + // when str::from_utf8 fails + String::from_utf8_lossy(&base64_decoded) + } + }; + + vec![ + // Token::Ident(_) + (None, vec![format!("let \"{s}\" = ();")]), + (Some(Token::Str("".to_string())), vec![format!("let s = \"{s}\";")]), + ( + Some(Token::RawStr("".to_string(), 0)), + vec![ + // let s = r"Hello world"; + format!("let s = r\"{s}\";"), + // let s = r#"Simon says "hello world""#; + format!("let s = r#\"{s}\"#;"), + // // Any number of hashes may be used (>= 1) as long as the string also terminates with the same number of hashes + // let s = r#####"One "#, Two "##, Three "###, Four "####, Five will end the string."#####; + format!("let s = r##\"{s}\"##;"), + format!("let s = r###\"{s}\"###;"), + format!("let s = r####\"{s}\"####; "), + format!("let s = r#####\"{s}\"#####;"), + ], + ), + (Some(Token::FmtStr("".to_string())), vec![format!("assert(x == y, f\"{s}\");")]), + // expected token not found + // (Some(Token::LineComment("".to_string(), None)), vec![ + (None, vec![format!("//{s}"), format!("// {s}")]), + // expected token not found + // (Some(Token::BlockComment("".to_string(), None)), vec![ + (None, vec![format!("/*{s}*/"), format!("/* {s} */"), format!("/*\n{s}\n*/")]), + ] + } + + #[test] + fn test_big_list_of_naughty_strings() { + use std::mem::discriminant; + + let blns_contents = include_str!("./blns/blns.base64.json"); + let blns_base64: Vec = + serde_json::from_str(blns_contents).expect("BLNS json invalid"); + for blns_base64_str in blns_base64 { + let statements = blns_base64_to_statements(blns_base64_str); + for (token_discriminator_opt, blns_program_strs) in statements { + for blns_program_str in blns_program_strs { + let mut expected_token_found = false; + let mut lexer = Lexer::new(&blns_program_str); + let mut result_tokens = Vec::new(); + loop { + match lexer.next_token() { + Ok(next_token) => { + result_tokens.push(next_token.clone()); + expected_token_found |= token_discriminator_opt + .as_ref() + .map(|token_discriminator| { + discriminant(token_discriminator) + == discriminant(next_token.token()) + }) + .unwrap_or(true); + + if next_token == Token::EOF { + assert!(lexer.done, "lexer not done when EOF emitted!"); + break; + } + } + + Err(LexerErrorKind::InvalidIntegerLiteral { .. }) + | Err(LexerErrorKind::UnexpectedCharacter { .. }) + | Err(LexerErrorKind::UnterminatedBlockComment { .. }) => { + expected_token_found = true; + } + Err(err) => { + panic!("Unexpected lexer error found: {:?}", err) + } + } + } + + assert!( + expected_token_found, + "expected token not found: {token_discriminator_opt:?}\noutput:\n{result_tokens:?}", + ); + } + } + } + } } diff --git a/compiler/noirc_frontend/src/lexer/token.rs b/compiler/noirc_frontend/src/lexer/token.rs index 1594b521e49..f5d6792b37f 100644 --- a/compiler/noirc_frontend/src/lexer/token.rs +++ b/compiler/noirc_frontend/src/lexer/token.rs @@ -1,4 +1,4 @@ -use acvm::FieldElement; +use acvm::{acir::AcirField, FieldElement}; use noirc_errors::{Position, Span, Spanned}; use std::{fmt, iter::Map, vec::IntoIter}; @@ -9,12 +9,105 @@ use crate::lexer::errors::LexerErrorKind; /// smallest unit of grammar. A parser may (will) decide to parse /// items differently depending on the Tokens present but will /// never parse the same ordering of identical tokens differently. +#[derive(PartialEq, Eq, Hash, Debug, Clone, PartialOrd, Ord)] +pub enum BorrowedToken<'input> { + Ident(&'input str), + Int(FieldElement), + Bool(bool), + Str(&'input str), + /// the u8 is the number of hashes, i.e. r###.. + RawStr(&'input str, u8), + FmtStr(&'input str), + Keyword(Keyword), + IntType(IntType), + Attribute(Attribute), + LineComment(&'input str, Option), + BlockComment(&'input str, Option), + /// < + Less, + /// <= + LessEqual, + /// > + Greater, + /// >= + GreaterEqual, + /// == + Equal, + /// != + NotEqual, + /// + + Plus, + /// - + Minus, + /// * + Star, + /// / + Slash, + /// % + Percent, + /// & + Ampersand, + /// ^ + Caret, + /// << + ShiftLeft, + /// >> + ShiftRight, + /// . + Dot, + /// .. + DoubleDot, + /// ( + LeftParen, + /// ) + RightParen, + /// { + LeftBrace, + /// } + RightBrace, + /// [ + LeftBracket, + /// ] + RightBracket, + /// -> + Arrow, + /// | + Pipe, + /// # + Pound, + /// , + Comma, + /// : + Colon, + /// :: + DoubleColon, + /// ; + Semicolon, + /// ! + Bang, + /// = + Assign, + #[allow(clippy::upper_case_acronyms)] + EOF, + + Whitespace(&'input str), + + /// 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 + /// avoid reporting the error twice (once while lexing, again when it is encountered + /// during parsing). Reporting during lexing then removing these from the token stream + /// would not be equivalent as it would change the resulting parse. + Invalid(char), +} + #[derive(PartialEq, Eq, Hash, Debug, Clone, PartialOrd, Ord)] pub enum Token { Ident(String), Int(FieldElement), Bool(bool), Str(String), + /// the u8 is the number of hashes, i.e. r###.. RawStr(String, u8), FmtStr(String), Keyword(Keyword), @@ -100,6 +193,57 @@ pub enum Token { Invalid(char), } +pub fn token_to_borrowed_token(token: &Token) -> BorrowedToken<'_> { + match token { + Token::Ident(ref s) => BorrowedToken::Ident(s), + Token::Int(n) => BorrowedToken::Int(*n), + Token::Bool(b) => BorrowedToken::Bool(*b), + Token::Str(ref b) => BorrowedToken::Str(b), + Token::FmtStr(ref b) => BorrowedToken::FmtStr(b), + Token::RawStr(ref b, hashes) => BorrowedToken::RawStr(b, *hashes), + Token::Keyword(k) => BorrowedToken::Keyword(*k), + Token::Attribute(ref a) => BorrowedToken::Attribute(a.clone()), + Token::LineComment(ref s, _style) => BorrowedToken::LineComment(s, *_style), + Token::BlockComment(ref s, _style) => BorrowedToken::BlockComment(s, *_style), + Token::IntType(ref i) => BorrowedToken::IntType(i.clone()), + Token::Less => BorrowedToken::Less, + Token::LessEqual => BorrowedToken::LessEqual, + Token::Greater => BorrowedToken::Greater, + Token::GreaterEqual => BorrowedToken::GreaterEqual, + Token::Equal => BorrowedToken::Equal, + Token::NotEqual => BorrowedToken::NotEqual, + Token::Plus => BorrowedToken::Plus, + Token::Minus => BorrowedToken::Minus, + Token::Star => BorrowedToken::Star, + Token::Slash => BorrowedToken::Slash, + Token::Percent => BorrowedToken::Percent, + Token::Ampersand => BorrowedToken::Ampersand, + Token::Caret => BorrowedToken::Caret, + Token::ShiftLeft => BorrowedToken::ShiftLeft, + Token::ShiftRight => BorrowedToken::ShiftRight, + Token::Dot => BorrowedToken::Dot, + Token::DoubleDot => BorrowedToken::DoubleDot, + Token::LeftParen => BorrowedToken::LeftParen, + Token::RightParen => BorrowedToken::RightParen, + Token::LeftBrace => BorrowedToken::LeftBrace, + Token::RightBrace => BorrowedToken::RightBrace, + Token::LeftBracket => BorrowedToken::LeftBracket, + Token::RightBracket => BorrowedToken::RightBracket, + Token::Arrow => BorrowedToken::Arrow, + Token::Pipe => BorrowedToken::Pipe, + Token::Pound => BorrowedToken::Pound, + Token::Comma => BorrowedToken::Comma, + Token::Colon => BorrowedToken::Colon, + Token::DoubleColon => BorrowedToken::DoubleColon, + Token::Semicolon => BorrowedToken::Semicolon, + Token::Assign => BorrowedToken::Assign, + Token::Bang => BorrowedToken::Bang, + Token::EOF => BorrowedToken::EOF, + Token::Invalid(c) => BorrowedToken::Invalid(*c), + Token::Whitespace(ref s) => BorrowedToken::Whitespace(s), + } +} + #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)] pub enum DocStyle { Outer, @@ -126,6 +270,12 @@ impl From for Token { } } +impl<'a> From<&'a SpannedToken> for &'a Token { + fn from(spt: &'a SpannedToken) -> Self { + &spt.0.contents + } +} + impl SpannedToken { pub fn new(token: Token, span: Span) -> SpannedToken { SpannedToken(Spanned::from(span, token)) @@ -262,8 +412,8 @@ impl Token { [Plus, Minus, Star, Slash, Percent, Ampersand, Caret, ShiftLeft, ShiftRight, Pipe] } - pub fn try_into_binary_op(self, span: Span) -> Option> { - use crate::BinaryOpKind::*; + pub fn try_into_binary_op(self, span: Span) -> Option> { + use crate::ast::BinaryOpKind::*; let binary_op = match self { Token::Plus => Add, Token::Ampersand => And, @@ -427,6 +577,14 @@ impl Attributes { } None } + + pub fn is_foldable(&self) -> bool { + self.function.as_ref().map_or(false, |func_attribute| func_attribute.is_foldable()) + } + + pub fn is_no_predicates(&self) -> bool { + self.function.as_ref().map_or(false, |func_attribute| func_attribute.is_no_predicates()) + } } /// An Attribute can be either a Primary Attribute or a Secondary Attribute @@ -486,6 +644,8 @@ impl Attribute { } ["test"] => Attribute::Function(FunctionAttribute::Test(TestScope::None)), ["recursive"] => Attribute::Function(FunctionAttribute::Recursive), + ["fold"] => Attribute::Function(FunctionAttribute::Fold), + ["no_predicates"] => Attribute::Function(FunctionAttribute::NoPredicates), ["test", name] => { validate(name)?; let malformed_scope = @@ -504,7 +664,7 @@ impl Attribute { ["contract_library_method"] => { Attribute::Secondary(SecondaryAttribute::ContractLibraryMethod) } - ["event"] => Attribute::Secondary(SecondaryAttribute::Event), + ["abi", tag] => Attribute::Secondary(SecondaryAttribute::Abi(tag.to_string())), ["export"] => Attribute::Secondary(SecondaryAttribute::Export), ["deprecated", name] => { if !name.starts_with('"') && !name.ends_with('"') { @@ -537,6 +697,8 @@ pub enum FunctionAttribute { Oracle(String), Test(TestScope), Recursive, + Fold, + NoPredicates, } impl FunctionAttribute { @@ -565,6 +727,17 @@ impl FunctionAttribute { pub fn is_low_level(&self) -> bool { matches!(self, FunctionAttribute::Foreign(_) | FunctionAttribute::Builtin(_)) } + + pub fn is_foldable(&self) -> bool { + matches!(self, FunctionAttribute::Fold) + } + + /// Check whether we have an `inline` attribute + /// Although we also do not want to inline foldable functions, + /// we keep the two attributes distinct for clarity. + pub fn is_no_predicates(&self) -> bool { + matches!(self, FunctionAttribute::NoPredicates) + } } impl fmt::Display for FunctionAttribute { @@ -575,6 +748,8 @@ impl fmt::Display for FunctionAttribute { FunctionAttribute::Builtin(ref k) => write!(f, "#[builtin({k})]"), FunctionAttribute::Oracle(ref k) => write!(f, "#[oracle({k})]"), FunctionAttribute::Recursive => write!(f, "#[recursive]"), + FunctionAttribute::Fold => write!(f, "#[fold]"), + FunctionAttribute::NoPredicates => write!(f, "#[no_predicates]"), } } } @@ -589,10 +764,10 @@ pub enum SecondaryAttribute { // is a helper method for a contract and should not be seen as // the entry point. ContractLibraryMethod, - Event, Export, Field(String), Custom(String), + Abi(String), } impl fmt::Display for SecondaryAttribute { @@ -604,9 +779,9 @@ impl fmt::Display for SecondaryAttribute { } SecondaryAttribute::Custom(ref k) => write!(f, "#[{k}]"), SecondaryAttribute::ContractLibraryMethod => write!(f, "#[contract_library_method]"), - SecondaryAttribute::Event => write!(f, "#[event]"), SecondaryAttribute::Export => write!(f, "#[export]"), SecondaryAttribute::Field(ref k) => write!(f, "#[field({k})]"), + SecondaryAttribute::Abi(ref k) => write!(f, "#[abi({k})]"), } } } @@ -619,6 +794,8 @@ impl AsRef for FunctionAttribute { FunctionAttribute::Oracle(string) => string, FunctionAttribute::Test { .. } => "", FunctionAttribute::Recursive => "", + FunctionAttribute::Fold => "", + FunctionAttribute::NoPredicates => "", } } } @@ -628,9 +805,11 @@ impl AsRef for SecondaryAttribute { match self { SecondaryAttribute::Deprecated(Some(string)) => string, SecondaryAttribute::Deprecated(None) => "", - SecondaryAttribute::Custom(string) | SecondaryAttribute::Field(string) => string, + SecondaryAttribute::Custom(string) + | SecondaryAttribute::Field(string) + | SecondaryAttribute::Abi(string) => string, SecondaryAttribute::ContractLibraryMethod => "", - SecondaryAttribute::Event | SecondaryAttribute::Export => "", + SecondaryAttribute::Export => "", } } } @@ -644,10 +823,12 @@ pub enum Keyword { Assert, AssertEq, Bool, + Break, CallData, Char, - CompTime, + Comptime, Constrain, + Continue, Contract, Crate, Dep, @@ -661,16 +842,16 @@ pub enum Keyword { If, Impl, In, - Internal, Let, Mod, Mut, - Open, Pub, + Quote, Return, ReturnData, String, Struct, + Super, Trait, Type, Unchecked, @@ -688,10 +869,12 @@ impl fmt::Display for Keyword { Keyword::Assert => write!(f, "assert"), Keyword::AssertEq => write!(f, "assert_eq"), Keyword::Bool => write!(f, "bool"), + Keyword::Break => write!(f, "break"), Keyword::Char => write!(f, "char"), Keyword::CallData => write!(f, "call_data"), - Keyword::CompTime => write!(f, "comptime"), + Keyword::Comptime => write!(f, "comptime"), Keyword::Constrain => write!(f, "constrain"), + Keyword::Continue => write!(f, "continue"), Keyword::Contract => write!(f, "contract"), Keyword::Crate => write!(f, "crate"), Keyword::Dep => write!(f, "dep"), @@ -705,16 +888,16 @@ impl fmt::Display for Keyword { Keyword::If => write!(f, "if"), Keyword::Impl => write!(f, "impl"), Keyword::In => write!(f, "in"), - Keyword::Internal => write!(f, "internal"), Keyword::Let => write!(f, "let"), Keyword::Mod => write!(f, "mod"), Keyword::Mut => write!(f, "mut"), - Keyword::Open => write!(f, "open"), Keyword::Pub => write!(f, "pub"), + Keyword::Quote => write!(f, "quote"), Keyword::Return => write!(f, "return"), Keyword::ReturnData => write!(f, "return_data"), Keyword::String => write!(f, "str"), Keyword::Struct => write!(f, "struct"), + Keyword::Super => write!(f, "super"), Keyword::Trait => write!(f, "trait"), Keyword::Type => write!(f, "type"), Keyword::Unchecked => write!(f, "unchecked"), @@ -735,10 +918,12 @@ impl Keyword { "assert" => Keyword::Assert, "assert_eq" => Keyword::AssertEq, "bool" => Keyword::Bool, + "break" => Keyword::Break, "call_data" => Keyword::CallData, "char" => Keyword::Char, - "comptime" => Keyword::CompTime, + "comptime" => Keyword::Comptime, "constrain" => Keyword::Constrain, + "continue" => Keyword::Continue, "contract" => Keyword::Contract, "crate" => Keyword::Crate, "dep" => Keyword::Dep, @@ -752,16 +937,16 @@ impl Keyword { "if" => Keyword::If, "impl" => Keyword::Impl, "in" => Keyword::In, - "internal" => Keyword::Internal, "let" => Keyword::Let, "mod" => Keyword::Mod, "mut" => Keyword::Mut, - "open" => Keyword::Open, "pub" => Keyword::Pub, + "quote" => Keyword::Quote, "return" => Keyword::Return, "return_data" => Keyword::ReturnData, "str" => Keyword::String, "struct" => Keyword::Struct, + "super" => Keyword::Super, "trait" => Keyword::Trait, "type" => Keyword::Type, "unchecked" => Keyword::Unchecked, diff --git a/compiler/noirc_frontend/src/lib.rs b/compiler/noirc_frontend/src/lib.rs index be007929fc4..b05c635f436 100644 --- a/compiler/noirc_frontend/src/lib.rs +++ b/compiler/noirc_frontend/src/lib.rs @@ -12,6 +12,7 @@ pub mod ast; pub mod debug; +pub mod elaborator; pub mod graph; pub mod lexer; pub mod monomorphization; @@ -28,9 +29,6 @@ pub use lexer::token; // Parser API pub use parser::{parse_program, ParsedModule}; -// AST API -pub use ast::*; - // Type API pub use hir_def::types::*; @@ -45,7 +43,6 @@ pub mod macros_api { pub use noirc_errors::Span; pub use crate::graph::CrateId; - use crate::hir::def_collector::dc_crate::{UnresolvedFunctions, UnresolvedTraitImpl}; pub use crate::hir::def_collector::errors::MacroError; pub use crate::hir_def::expr::{HirExpression, HirLiteral}; pub use crate::hir_def::stmt::HirStatement; @@ -53,18 +50,18 @@ pub mod macros_api { pub use crate::parser::{parse_program, SortedModule}; pub use crate::token::SecondaryAttribute; - pub use crate::hir::def_map::ModuleDefId; - pub use crate::{ - hir::Context as HirContext, BlockExpression, CallExpression, CastExpression, Distinctness, - Expression, ExpressionKind, FunctionReturnType, Ident, IndexExpression, LetStatement, - Literal, MemberAccessExpression, MethodCallExpression, NoirFunction, Path, PathKind, - Pattern, Statement, UnresolvedType, UnresolvedTypeData, Visibility, + pub use crate::ast::{ + BlockExpression, CallExpression, CastExpression, Expression, ExpressionKind, + FunctionReturnType, Ident, IndexExpression, ItemVisibility, LetStatement, Literal, + MemberAccessExpression, MethodCallExpression, NoirFunction, Path, PathKind, Pattern, + Statement, UnresolvedType, UnresolvedTypeData, Visibility, }; - pub use crate::{ - ForLoopStatement, ForRange, FunctionDefinition, FunctionVisibility, ImportStatement, - NoirStruct, Param, PrefixExpression, Signedness, StatementKind, StructType, Type, TypeImpl, - UnaryOp, + pub use crate::ast::{ + ForLoopStatement, ForRange, FunctionDefinition, ImportStatement, NoirStruct, Param, + PrefixExpression, Signedness, StatementKind, TypeImpl, UnaryOp, }; + pub use crate::hir::{def_map::ModuleDefId, Context as HirContext}; + pub use crate::{StructType, Type}; /// Methods to process the AST before and after type checking pub trait MacroProcessor { @@ -73,18 +70,10 @@ pub mod macros_api { &self, ast: SortedModule, crate_id: &CrateId, + file_id: FileId, context: &HirContext, ) -> Result; - // TODO(#4653): generalize this function - fn process_unresolved_traits_impls( - &self, - _crate_id: &CrateId, - _context: &mut HirContext, - _unresolved_traits_impls: &[UnresolvedTraitImpl], - _collected_functions: &mut Vec, - ) -> Result<(), (MacroError, FileId)>; - /// Function to manipulate the AST after type checking has been completed. /// The AST after type checking has been done is called the HIR. fn process_typed_ast( diff --git a/compiler/noirc_frontend/src/monomorphization/ast.rs b/compiler/noirc_frontend/src/monomorphization/ast.rs index e4e619d5d92..99ac08ddfc2 100644 --- a/compiler/noirc_frontend/src/monomorphization/ast.rs +++ b/compiler/noirc_frontend/src/monomorphization/ast.rs @@ -1,15 +1,18 @@ use acvm::FieldElement; use iter_extended::vecmap; use noirc_errors::{ - debug_info::{DebugTypes, DebugVariables}, + debug_info::{DebugFunctions, DebugTypes, DebugVariables}, Location, }; +use crate::hir_def::function::FunctionSignature; use crate::{ - hir_def::function::FunctionSignature, BinaryOpKind, Distinctness, IntegerBitSize, Signedness, - Visibility, + ast::{BinaryOpKind, IntegerBitSize, Signedness, Visibility}, + token::{Attributes, FunctionAttribute}, }; +use super::HirType; + /// The monomorphized AST is expression-based, all statements are also /// folded into this expression enum. Compared to the HIR, the monomorphized /// AST has several differences: @@ -35,9 +38,11 @@ pub enum Expression { ExtractTupleField(Box, usize), Call(Call), Let(Let), - Constrain(Box, Location, Option>), + Constrain(Box, Location, Option>), Assign(Assign), Semi(Box), + Break, + Continue, } /// A definition is either a local (variable), function, or is a built-in @@ -87,15 +92,17 @@ pub struct For { #[derive(Debug, Clone, Hash)] pub enum Literal { Array(ArrayLiteral), + Slice(ArrayLiteral), Integer(FieldElement, Type, Location), Bool(bool), + Unit, Str(String), FmtStr(String, u64, Box), } #[derive(Debug, Clone, Hash)] pub struct Unary { - pub operator: crate::UnaryOp, + pub operator: crate::ast::UnaryOp, pub rhs: Box, pub result_type: Type, pub location: Location, @@ -198,6 +205,57 @@ pub enum LValue { pub type Parameters = Vec<(LocalId, /*mutable:*/ bool, /*name:*/ String, Type)>; +/// Represents how an Acir function should be inlined. +/// This type is only relevant for ACIR functions as we do not inline any Brillig functions +#[derive(Default, Clone, Copy, PartialEq, Eq, Debug, Hash)] +pub enum InlineType { + /// The most basic entry point can expect all its functions to be inlined. + /// All function calls are expected to be inlined into a single ACIR. + #[default] + Inline, + /// Functions marked as foldable will not be inlined and compiled separately into ACIR + Fold, + /// Functions marked to have no predicates will not be inlined in the default inlining pass + /// and will be separately inlined after the flattening pass. + /// They are different from `Fold` as they are expected to be inlined into the program + /// entry point before being used in the backend. + /// This attribute is unsafe and can cause a function whose logic relies on predicates from + /// the flattening pass to fail. + NoPredicates, +} + +impl From<&Attributes> for InlineType { + fn from(attributes: &Attributes) -> Self { + attributes.function.as_ref().map_or(InlineType::default(), |func_attribute| { + match func_attribute { + FunctionAttribute::Fold => InlineType::Fold, + FunctionAttribute::NoPredicates => InlineType::NoPredicates, + _ => InlineType::default(), + } + }) + } +} + +impl InlineType { + pub fn is_entry_point(&self) -> bool { + match self { + InlineType::Inline => false, + InlineType::Fold => true, + InlineType::NoPredicates => false, + } + } +} + +impl std::fmt::Display for InlineType { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + InlineType::Inline => write!(f, "inline"), + InlineType::Fold => write!(f, "fold"), + InlineType::NoPredicates => write!(f, "no_predicates"), + } + } +} + #[derive(Debug, Clone, Hash)] pub struct Function { pub id: FuncId, @@ -208,6 +266,8 @@ pub struct Function { pub return_type: Type, pub unconstrained: bool, + pub inline_type: InlineType, + pub func_sig: FunctionSignature, } /// Compared to hir_def::types::Type, this monomorphized Type has: @@ -218,11 +278,11 @@ pub struct Function { #[derive(Debug, PartialEq, Eq, Clone, Hash)] pub enum Type { Field, - Array(/*len:*/ u64, Box), // Array(4, Field) = [Field; 4] + Array(/*len:*/ u32, Box), // Array(4, Field) = [Field; 4] Integer(Signedness, /*bits:*/ IntegerBitSize), // u32 = Integer(unsigned, ThirtyTwo) Bool, - String(/*len:*/ u64), // String(4) = str[4] - FmtString(/*len:*/ u64, Box), + String(/*len:*/ u32), // String(4) = str[4] + FmtString(/*len:*/ u32, Box), Unit, Tuple(Vec), Slice(Box), @@ -242,17 +302,14 @@ impl Type { #[derive(Debug, Clone, Hash)] pub struct Program { pub functions: Vec, + pub function_signatures: Vec, pub main_function_signature: FunctionSignature, - /// Indicates whether witness indices are allowed to reoccur in the ABI of the resulting ACIR. - /// - /// Note: this has no impact on monomorphization, and is simply attached here for ease of - /// forwarding to the next phase. - pub return_distinctness: Distinctness, pub return_location: Option, pub return_visibility: Visibility, /// Indicates to a backend whether a SNARK-friendly prover should be used. pub recursive: bool, pub debug_variables: DebugVariables, + pub debug_functions: DebugFunctions, pub debug_types: DebugTypes, } @@ -260,22 +317,24 @@ impl Program { #[allow(clippy::too_many_arguments)] pub fn new( functions: Vec, + function_signatures: Vec, main_function_signature: FunctionSignature, - return_distinctness: Distinctness, return_location: Option, return_visibility: Visibility, recursive: bool, debug_variables: DebugVariables, + debug_functions: DebugFunctions, debug_types: DebugTypes, ) -> Program { Program { functions, + function_signatures, main_function_signature, - return_distinctness, return_location, return_visibility, recursive, debug_variables, + debug_functions, debug_types, } } diff --git a/compiler/noirc_frontend/src/monomorphization/debug.rs b/compiler/noirc_frontend/src/monomorphization/debug.rs index a8ff4399f99..3b399c75706 100644 --- a/compiler/noirc_frontend/src/monomorphization/debug.rs +++ b/compiler/noirc_frontend/src/monomorphization/debug.rs @@ -1,3 +1,4 @@ +use acvm::acir::AcirField; use iter_extended::vecmap; use noirc_errors::debug_info::DebugVarId; use noirc_errors::Location; @@ -76,7 +77,7 @@ impl<'interner> Monomorphizer<'interner> { let var_type = self.interner.id_type(call.arguments[DEBUG_VALUE_ARG_SLOT]); let source_var_id = source_var_id.to_u128().into(); // then update the ID used for tracking at runtime - let var_id = self.debug_type_tracker.insert_var(source_var_id, var_type); + let var_id = self.debug_type_tracker.insert_var(source_var_id, &var_type); let interned_var_id = self.intern_var_id(var_id, &call.location); arguments[DEBUG_VAR_ID_ARG_SLOT] = self.expr(interned_var_id)?; Ok(()) @@ -192,11 +193,12 @@ impl<'interner> Monomorphizer<'interner> { fn element_type_at_index(ptype: &PrintableType, i: usize) -> &PrintableType { match ptype { PrintableType::Array { length: _length, typ } => typ.as_ref(), + PrintableType::Slice { typ } => typ.as_ref(), PrintableType::Tuple { types } => &types[i], PrintableType::Struct { name: _name, fields } => &fields[i].1, PrintableType::String { length: _length } => &PrintableType::UnsignedInteger { width: 8 }, - _ => { - panic!["expected type with sub-fields, found terminal type"] + other => { + panic!["expected type with sub-fields, found terminal type: {other:?}"] } } } diff --git a/compiler/noirc_frontend/src/monomorphization/debug_types.rs b/compiler/noirc_frontend/src/monomorphization/debug_types.rs index fea073d394f..16b82d1e7b9 100644 --- a/compiler/noirc_frontend/src/monomorphization/debug_types.rs +++ b/compiler/noirc_frontend/src/monomorphization/debug_types.rs @@ -3,7 +3,8 @@ use crate::{ hir_def::types::Type, }; use noirc_errors::debug_info::{ - DebugTypeId, DebugTypes, DebugVarId, DebugVariable, DebugVariables, + DebugFnId, DebugFunction, DebugFunctions, DebugTypeId, DebugTypes, DebugVarId, DebugVariable, + DebugVariables, }; use noirc_printable_type::PrintableType; use std::collections::HashMap; @@ -30,7 +31,10 @@ pub struct DebugTypeTracker { // All instances of tracked variables variables: HashMap, - // Types of tracked variables + // Function metadata collected during instrumentation injection + functions: HashMap, + + // Types of tracked variables and functions types: HashMap, types_reverse: HashMap, @@ -43,34 +47,29 @@ impl DebugTypeTracker { DebugTypeTracker { source_variables: instrumenter.variables.clone(), source_field_names: instrumenter.field_names.clone(), + functions: instrumenter.functions.clone(), ..DebugTypeTracker::default() } } - pub fn extract_vars_and_types(&self) -> (DebugVariables, DebugTypes) { + pub fn extract_vars_and_types(&self) -> (DebugVariables, DebugFunctions, DebugTypes) { let debug_variables = self .variables .clone() .into_iter() .map(|(var_id, (source_var_id, type_id))| { - ( - var_id, - DebugVariable { - name: self.source_variables.get(&source_var_id).cloned().unwrap_or_else( - || { - unreachable!( - "failed to retrieve variable name for {source_var_id:?}" - ); - }, - ), - debug_type_id: type_id, - }, - ) + let var_name = + self.source_variables.get(&source_var_id).cloned().unwrap_or_else(|| { + unreachable!("failed to retrieve variable name for {source_var_id:?}"); + }); + (var_id, DebugVariable { name: var_name, debug_type_id: type_id }) }) .collect(); + + let debug_functions = self.functions.clone().into_iter().collect(); let debug_types = self.types.clone().into_iter().collect(); - (debug_variables, debug_types) + (debug_variables, debug_functions, debug_types) } pub fn resolve_field_index( @@ -83,19 +82,24 @@ impl DebugTypeTracker { .and_then(|field_name| get_field(cursor_type, field_name)) } - pub fn insert_var(&mut self, source_var_id: SourceVarId, var_type: Type) -> DebugVarId { - if !self.source_variables.contains_key(&source_var_id) { - unreachable!("cannot find source debug variable {source_var_id:?}"); - } - - let ptype: PrintableType = var_type.follow_bindings().into(); - let type_id = self.types_reverse.get(&ptype).copied().unwrap_or_else(|| { + fn insert_type(&mut self, the_type: &Type) -> DebugTypeId { + let ptype: PrintableType = the_type.follow_bindings().into(); + self.types_reverse.get(&ptype).copied().unwrap_or_else(|| { let type_id = DebugTypeId(self.next_type_id); self.next_type_id += 1; self.types_reverse.insert(ptype.clone(), type_id); self.types.insert(type_id, ptype); type_id - }); + }) + } + + pub fn insert_var(&mut self, source_var_id: SourceVarId, var_type: &Type) -> DebugVarId { + if !self.source_variables.contains_key(&source_var_id) { + unreachable!("cannot find source debug variable {source_var_id:?}"); + } + + let type_id = self.insert_type(var_type); + // check if we need to instantiate the var with a new type let existing_var_id = self.source_to_debug_vars.get(&source_var_id).and_then(|var_id| { let (_, existing_type_id) = self.variables.get(var_id).unwrap(); diff --git a/compiler/noirc_frontend/src/monomorphization/errors.rs b/compiler/noirc_frontend/src/monomorphization/errors.rs new file mode 100644 index 00000000000..2db570540d6 --- /dev/null +++ b/compiler/noirc_frontend/src/monomorphization/errors.rs @@ -0,0 +1,44 @@ +use noirc_errors::{CustomDiagnostic, FileDiagnostic, Location}; + +use crate::hir::comptime::InterpreterError; + +#[derive(Debug)] +pub enum MonomorphizationError { + UnknownArrayLength { location: Location }, + TypeAnnotationsNeeded { location: Location }, + InterpreterError(InterpreterError), +} + +impl MonomorphizationError { + fn location(&self) -> Location { + match self { + MonomorphizationError::UnknownArrayLength { location } + | MonomorphizationError::TypeAnnotationsNeeded { location } => *location, + MonomorphizationError::InterpreterError(error) => error.get_location(), + } + } +} + +impl From for FileDiagnostic { + fn from(error: MonomorphizationError) -> FileDiagnostic { + let location = error.location(); + let call_stack = vec![location]; + let diagnostic = error.into_diagnostic(); + diagnostic.in_file(location.file).with_call_stack(call_stack) + } +} + +impl MonomorphizationError { + fn into_diagnostic(self) -> CustomDiagnostic { + let message = match self { + MonomorphizationError::UnknownArrayLength { .. } => { + "Length of generic array could not be determined." + } + MonomorphizationError::TypeAnnotationsNeeded { .. } => "Type annotations needed", + MonomorphizationError::InterpreterError(error) => return (&error).into(), + }; + + let location = self.location(); + CustomDiagnostic::simple_error(message.into(), String::new(), location.span) + } +} diff --git a/compiler/noirc_frontend/src/monomorphization/mod.rs b/compiler/noirc_frontend/src/monomorphization/mod.rs index adba8187aa0..a25d6488c83 100644 --- a/compiler/noirc_frontend/src/monomorphization/mod.rs +++ b/compiler/noirc_frontend/src/monomorphization/mod.rs @@ -8,16 +8,7 @@ //! //! The entry point to this pass is the `monomorphize` function which, starting from a given //! function, will monomorphize the entire reachable program. -use acvm::FieldElement; -use iter_extended::{btree_map, try_vecmap, vecmap}; -use noirc_errors::{CustomDiagnostic, FileDiagnostic, Location}; -use noirc_printable_type::PrintableType; -use std::{ - collections::{BTreeMap, HashMap, VecDeque}, - unreachable, -}; -use thiserror::Error; - +use crate::ast::{FunctionKind, IntegerBitSize, Signedness, UnaryOp, Visibility}; use crate::{ debug::DebugInstrumenter, hir_def::{ @@ -28,16 +19,28 @@ use crate::{ }, node_interner::{self, DefinitionKind, NodeInterner, StmtId, TraitImplKind, TraitMethodId}, token::FunctionAttribute, - ContractFunctionType, FunctionKind, IntegerBitSize, Signedness, Type, TypeBinding, - TypeBindings, TypeVariable, TypeVariableKind, UnaryOp, Visibility, + Type, TypeBinding, TypeBindings, TypeVariable, TypeVariableKind, +}; +use acvm::{acir::AcirField, FieldElement}; +use iter_extended::{btree_map, try_vecmap, vecmap}; +use noirc_errors::Location; +use noirc_printable_type::PrintableType; +use std::{ + collections::{BTreeMap, HashMap, VecDeque}, + unreachable, }; -use self::ast::{Definition, FuncId, Function, LocalId, Program}; +use self::ast::InlineType; use self::debug_types::DebugTypeTracker; +use self::{ + ast::{Definition, FuncId, Function, LocalId, Program}, + errors::MonomorphizationError, +}; pub mod ast; mod debug; pub mod debug_types; +pub mod errors; pub mod printer; struct LambdaContext { @@ -50,14 +53,16 @@ struct LambdaContext { /// This struct holds the FIFO queue of functions to monomorphize, which is added to /// whenever a new (function, type) combination is encountered. struct Monomorphizer<'interner> { - /// Globals are keyed by their unique ID and expected type so that we can monomorphize - /// a new version of the global for each type. Note that 'global' here means 'globally - /// visible' and thus includes both functions and global variables. + /// Functions are keyed by their unique ID and expected type so that we can monomorphize + /// a new version of the function for each type. + /// We also key by any turbofish generics that are specified. + /// This is necessary for a case where we may have a trait generic that can be instantiated + /// outside of a function parameter or return value. /// /// Using nested HashMaps here lets us avoid cloning HirTypes when calling .get() - globals: HashMap>, + functions: HashMap), FuncId>>, - /// Unlike globals, locals are only keyed by their unique ID because they are never + /// Unlike functions, locals are only keyed by their unique ID because they are never /// duplicated during monomorphization. Doing so would allow them to be used polymorphically /// but would also cause them to be re-evaluated which is a performance trap that would /// confuse users. @@ -88,40 +93,6 @@ struct Monomorphizer<'interner> { type HirType = crate::Type; -#[derive(Debug, Error)] -pub enum MonomorphizationError { - #[error("Length of generic array could not be determined.")] - UnknownArrayLength { location: Location }, -} - -impl MonomorphizationError { - fn call_stack(&self) -> Vec { - match self { - MonomorphizationError::UnknownArrayLength { location } => vec![*location], - } - } -} - -impl From for FileDiagnostic { - fn from(error: MonomorphizationError) -> FileDiagnostic { - let call_stack = error.call_stack(); - let file_id = call_stack.last().map(|location| location.file).unwrap_or_default(); - let diagnostic = error.into_diagnostic(); - diagnostic.in_file(file_id).with_call_stack(call_stack) - } -} - -impl MonomorphizationError { - fn into_diagnostic(self) -> CustomDiagnostic { - CustomDiagnostic::simple_error( - "Internal Consistency Evaluators Errors: \n - This is likely a bug. Consider opening an issue at https://github.com/noir-lang/noir/issues".to_owned(), - self.to_string(), - noirc_errors::Span::inclusive(0, 0) - ) - } -} - /// Starting from the given `main` function, monomorphize the entire program, /// replacing all references to type variables and NamedGenerics with concrete /// types, duplicating definitions as necessary to do so. @@ -161,19 +132,32 @@ pub fn monomorphize_debug( undo_instantiation_bindings(bindings); } + let func_sigs = monomorphizer + .finished_functions + .iter() + .flat_map(|(_, f)| { + if f.inline_type.is_entry_point() || f.id == Program::main_id() { + Some(f.func_sig.clone()) + } else { + None + } + }) + .collect(); + let functions = vecmap(monomorphizer.finished_functions, |(_, f)| f); - let FuncMeta { return_distinctness, return_visibility, kind, .. } = - monomorphizer.interner.function_meta(&main); + let FuncMeta { return_visibility, kind, .. } = monomorphizer.interner.function_meta(&main); - let (debug_variables, debug_types) = monomorphizer.debug_type_tracker.extract_vars_and_types(); + let (debug_variables, debug_functions, debug_types) = + monomorphizer.debug_type_tracker.extract_vars_and_types(); let program = Program::new( functions, + func_sigs, function_sig, - *return_distinctness, monomorphizer.return_location, *return_visibility, *kind == FunctionKind::Recursive, debug_variables, + debug_functions, debug_types, ); Ok(program) @@ -182,7 +166,7 @@ pub fn monomorphize_debug( impl<'interner> Monomorphizer<'interner> { fn new(interner: &'interner mut NodeInterner, debug_type_tracker: DebugTypeTracker) -> Self { Monomorphizer { - globals: HashMap::new(), + functions: HashMap::new(), locals: HashMap::new(), queue: VecDeque::new(), finished_functions: BTreeMap::new(), @@ -217,10 +201,15 @@ impl<'interner> Monomorphizer<'interner> { id: node_interner::FuncId, expr_id: node_interner::ExprId, typ: &HirType, + turbofish_generics: Vec, trait_method: Option, ) -> Definition { let typ = typ.follow_bindings(); - match self.globals.get(&id).and_then(|inner_map| inner_map.get(&typ)) { + match self + .functions + .get(&id) + .and_then(|inner_map| inner_map.get(&(typ.clone(), turbofish_generics.clone()))) + { Some(id) => Definition::Function(*id), None => { // Function has not been monomorphized yet @@ -241,7 +230,8 @@ impl<'interner> Monomorphizer<'interner> { Definition::Builtin(opcode) } FunctionKind::Normal => { - let id = self.queue_function(id, expr_id, typ, trait_method); + let id = + self.queue_function(id, expr_id, typ, turbofish_generics, trait_method); Definition::Function(id) } FunctionKind::Oracle => { @@ -268,8 +258,14 @@ impl<'interner> Monomorphizer<'interner> { } /// Prerequisite: typ = typ.follow_bindings() - fn define_global(&mut self, id: node_interner::FuncId, typ: HirType, new_id: FuncId) { - self.globals.entry(id).or_default().insert(typ, new_id); + fn define_function( + &mut self, + id: node_interner::FuncId, + typ: HirType, + turbofish_generics: Vec, + new_id: FuncId, + ) { + self.functions.entry(id).or_default().insert((typ, turbofish_generics), new_id); } fn compile_main( @@ -301,21 +297,42 @@ impl<'interner> Monomorphizer<'interner> { } let meta = self.interner.function_meta(&f).clone(); + let mut func_sig = meta.function_signature(); + // Follow the bindings of the function signature for entry points + // which are not `main` such as foldable functions. + for param in func_sig.0.iter_mut() { + param.1 = param.1.follow_bindings(); + } + func_sig.1 = func_sig.1.map(|return_type| return_type.follow_bindings()); + let modifiers = self.interner.function_modifiers(&f); let name = self.interner.function_name(&f).to_owned(); - let body_expr_id = *self.interner.function(&f).as_expr(); + let body_expr_id = self.interner.function(&f).as_expr(); let body_return_type = self.interner.id_type(body_expr_id); - let return_type = self.convert_type(match meta.return_type() { + let return_type = match meta.return_type() { Type::TraitAsType(..) => &body_return_type, - _ => meta.return_type(), - }); - let unconstrained = modifiers.is_unconstrained - || matches!(modifiers.contract_function_type, Some(ContractFunctionType::Open)); + other => other, + }; + + let return_type = Self::convert_type(return_type, meta.location)?; + let unconstrained = modifiers.is_unconstrained; - let parameters = self.parameters(&meta.parameters); + let attributes = self.interner.function_attributes(&f); + let inline_type = InlineType::from(attributes); + + let parameters = self.parameters(&meta.parameters)?; let body = self.expr(body_expr_id)?; - let function = ast::Function { id, name, parameters, body, return_type, unconstrained }; + let function = ast::Function { + id, + name, + parameters, + body, + return_type, + unconstrained, + inline_type, + func_sig, + }; self.push_function(id, function); Ok(()) @@ -328,12 +345,15 @@ impl<'interner> Monomorphizer<'interner> { /// Monomorphize each parameter, expanding tuple/struct patterns into multiple parameters /// and binding any generic types found. - fn parameters(&mut self, params: &Parameters) -> Vec<(ast::LocalId, bool, String, ast::Type)> { + fn parameters( + &mut self, + params: &Parameters, + ) -> Result, MonomorphizationError> { let mut new_params = Vec::with_capacity(params.len()); for (parameter, typ, _) in ¶ms.0 { - self.parameter(parameter, typ, &mut new_params); + self.parameter(parameter, typ, &mut new_params)?; } - new_params + Ok(new_params) } fn parameter( @@ -341,21 +361,22 @@ impl<'interner> Monomorphizer<'interner> { param: &HirPattern, typ: &HirType, new_params: &mut Vec<(ast::LocalId, bool, String, ast::Type)>, - ) { + ) -> Result<(), MonomorphizationError> { match param { HirPattern::Identifier(ident) => { let new_id = self.next_local_id(); let definition = self.interner.definition(ident.id); let name = definition.name.clone(); - new_params.push((new_id, definition.mutable, name, self.convert_type(typ))); + let typ = Self::convert_type(typ, ident.location)?; + new_params.push((new_id, definition.mutable, name, typ)); self.define_local(ident.id, new_id); } - HirPattern::Mutable(pattern, _) => self.parameter(pattern, typ, new_params), + HirPattern::Mutable(pattern, _) => self.parameter(pattern, typ, new_params)?, HirPattern::Tuple(fields, _) => { let tuple_field_types = unwrap_tuple_type(typ); for (field, typ) in fields.iter().zip(tuple_field_types) { - self.parameter(field, &typ, new_params); + self.parameter(field, &typ, new_params)?; } } HirPattern::Struct(_, fields, _) => { @@ -372,10 +393,11 @@ impl<'interner> Monomorphizer<'interner> { unreachable!("Expected a field named '{field_name}' in the struct pattern") }); - self.parameter(field, &field_type, new_params); + self.parameter(field, &field_type, new_params)?; } } } + Ok(()) } fn expr( @@ -386,7 +408,7 @@ impl<'interner> Monomorphizer<'interner> { use ast::Literal::*; let expr = match self.interner.expression(&expr) { - HirExpression::Ident(ident) => self.ident(ident, expr)?, + HirExpression::Ident(ident, generics) => self.ident(ident, expr, generics)?, HirExpression::Literal(HirLiteral::Str(contents)) => Literal(Str(contents)), HirExpression::Literal(HirLiteral::FmtStr(contents, idents)) => { let fields = try_vecmap(idents, |ident| self.expr(ident))?; @@ -398,9 +420,10 @@ impl<'interner> Monomorphizer<'interner> { } HirExpression::Literal(HirLiteral::Bool(value)) => Literal(Bool(value)), HirExpression::Literal(HirLiteral::Integer(value, sign)) => { + let location = self.interner.id_location(expr); + let typ = Self::convert_type(&self.interner.id_type(expr), location)?; + if sign { - let typ = self.convert_type(&self.interner.id_type(expr)); - let location = self.interner.id_location(expr); match typ { ast::Type::Field => Literal(Integer(-value, typ, location)), ast::Type::Integer(_, bit_size) => { @@ -411,15 +434,19 @@ impl<'interner> Monomorphizer<'interner> { _ => unreachable!("Integer literal must be numeric"), } } else { - let typ = self.convert_type(&self.interner.id_type(expr)); - let location = self.interner.id_location(expr); Literal(Integer(value, typ, location)) } } HirExpression::Literal(HirLiteral::Array(array)) => match array { - HirArrayLiteral::Standard(array) => self.standard_array(expr, array)?, + HirArrayLiteral::Standard(array) => self.standard_array(expr, array, false)?, + HirArrayLiteral::Repeated { repeated_element, length } => { + self.repeated_array(expr, repeated_element, length, false)? + } + }, + HirExpression::Literal(HirLiteral::Slice(array)) => match array { + HirArrayLiteral::Standard(array) => self.standard_array(expr, array, true)?, HirArrayLiteral::Repeated { repeated_element, length } => { - self.repeated_array(expr, repeated_element, length)? + self.repeated_array(expr, repeated_element, length, true)? } }, HirExpression::Literal(HirLiteral::Unit) => ast::Expression::Block(vec![]), @@ -430,7 +457,7 @@ impl<'interner> Monomorphizer<'interner> { ast::Expression::Unary(ast::Unary { operator: prefix.operator, rhs: Box::new(self.expr(prefix.rhs)?), - result_type: self.convert_type(&self.interner.id_type(expr)), + result_type: Self::convert_type(&self.interner.id_type(expr), location)?, location, }) } @@ -448,7 +475,7 @@ impl<'interner> Monomorphizer<'interner> { // If this is a comparison operator, the result is a boolean but // the actual method call returns an Ordering - use crate::BinaryOpKind::*; + use crate::ast::BinaryOpKind::*; let ret = if matches!(operator, Less | LessEqual | Greater | GreaterEqual) { self.interner.ordering_type() } else { @@ -459,8 +486,8 @@ impl<'interner> Monomorphizer<'interner> { let function_type = Type::Function(args, Box::new(ret.clone()), env); let method = infix.trait_method_id; - let func = self.resolve_trait_method_reference(expr, function_type, method); - self.create_operator_impl_call(func, lhs, infix.operator, rhs, ret, location) + let func = self.resolve_trait_method_reference(expr, function_type, method)?; + self.create_operator_impl_call(func, lhs, infix.operator, rhs, ret, location)? } else { let lhs = Box::new(lhs); let rhs = Box::new(rhs); @@ -478,23 +505,22 @@ impl<'interner> Monomorphizer<'interner> { HirExpression::Call(call) => self.function_call(call, expr)?, - HirExpression::Cast(cast) => ast::Expression::Cast(ast::Cast { - lhs: Box::new(self.expr(cast.lhs)?), - r#type: self.convert_type(&cast.r#type), - location: self.interner.expr_location(&expr), - }), + HirExpression::Cast(cast) => { + let location = self.interner.expr_location(&expr); + let typ = Self::convert_type(&cast.r#type, location)?; + let lhs = Box::new(self.expr(cast.lhs)?); + ast::Expression::Cast(ast::Cast { lhs, r#type: typ, location }) + } HirExpression::If(if_expr) => { - let cond = self.expr(if_expr.condition)?; - let then = self.expr(if_expr.consequence)?; + let condition = Box::new(self.expr(if_expr.condition)?); + let consequence = Box::new(self.expr(if_expr.consequence)?); let else_ = if_expr.alternative.map(|alt| self.expr(alt)).transpose()?.map(Box::new); - ast::Expression::If(ast::If { - condition: Box::new(cond), - consequence: Box::new(then), - alternative: else_, - typ: self.convert_type(&self.interner.id_type(expr)), - }) + + let location = self.interner.expr_location(&expr); + let typ = Self::convert_type(&self.interner.id_type(expr), location)?; + ast::Expression::If(ast::If { condition, consequence, alternative: else_, typ }) } HirExpression::Tuple(fields) => { @@ -509,6 +535,13 @@ impl<'interner> Monomorphizer<'interner> { unreachable!("Encountered HirExpression::MethodCall during monomorphization {hir_method_call:?}") } HirExpression::Error => unreachable!("Encountered Error node during monomorphization"), + HirExpression::Quote(_) => unreachable!("quote expression remaining in runtime code"), + HirExpression::Unquote(_) => { + unreachable!("unquote expression remaining in runtime code") + } + HirExpression::Comptime(_) => { + unreachable!("comptime expression remaining in runtime code") + } }; Ok(expr) @@ -518,10 +551,16 @@ impl<'interner> Monomorphizer<'interner> { &mut self, array: node_interner::ExprId, array_elements: Vec, + is_slice: bool, ) -> Result { - let typ = self.convert_type(&self.interner.id_type(array)); + let location = self.interner.expr_location(&array); + let typ = Self::convert_type(&self.interner.id_type(array), location)?; let contents = try_vecmap(array_elements, |id| self.expr(id))?; - Ok(ast::Expression::Literal(ast::Literal::Array(ast::ArrayLiteral { contents, typ }))) + if is_slice { + Ok(ast::Expression::Literal(ast::Literal::Slice(ast::ArrayLiteral { contents, typ }))) + } else { + Ok(ast::Expression::Literal(ast::Literal::Array(ast::ArrayLiteral { contents, typ }))) + } } fn repeated_array( @@ -529,16 +568,22 @@ impl<'interner> Monomorphizer<'interner> { array: node_interner::ExprId, repeated_element: node_interner::ExprId, length: HirType, + is_slice: bool, ) -> Result { - let typ = self.convert_type(&self.interner.id_type(array)); + let location = self.interner.expr_location(&array); + let typ = Self::convert_type(&self.interner.id_type(array), location)?; - let length = length.evaluate_to_u64().ok_or_else(|| { + let length = length.evaluate_to_u32().ok_or_else(|| { let location = self.interner.expr_location(&array); MonomorphizationError::UnknownArrayLength { location } })?; let contents = try_vecmap(0..length, |_| self.expr(repeated_element))?; - Ok(ast::Expression::Literal(ast::Literal::Array(ast::ArrayLiteral { contents, typ }))) + if is_slice { + Ok(ast::Expression::Literal(ast::Literal::Slice(ast::ArrayLiteral { contents, typ }))) + } else { + Ok(ast::Expression::Literal(ast::Literal::Array(ast::ArrayLiteral { contents, typ }))) + } } fn index( @@ -546,7 +591,8 @@ impl<'interner> Monomorphizer<'interner> { id: node_interner::ExprId, index: HirIndexExpression, ) -> Result { - let element_type = self.convert_type(&self.interner.id_type(id)); + let location = self.interner.expr_location(&id); + let element_type = Self::convert_type(&self.interner.id_type(id), location)?; let collection = Box::new(self.expr(index.collection)?); let index = Box::new(self.expr(index.index)?); @@ -562,7 +608,11 @@ impl<'interner> Monomorphizer<'interner> { let location = self.interner.expr_location(&constrain.0); let assert_message = constrain .2 - .map(|assert_msg_expr| self.expr(assert_msg_expr)) + .map(|assert_msg_expr| { + self.expr(assert_msg_expr).map(|expr| { + (expr, self.interner.id_type(assert_msg_expr).follow_bindings()) + }) + }) .transpose()? .map(Box::new); Ok(ast::Expression::Constrain(Box::new(expr), location, assert_message)) @@ -577,11 +627,14 @@ impl<'interner> Monomorphizer<'interner> { self.define_local(for_loop.identifier.id, index_variable); let block = Box::new(self.expr(for_loop.block)?); + let index_location = for_loop.identifier.location; + let index_type = self.interner.id_type(for_loop.start_range); + let index_type = Self::convert_type(&index_type, index_location)?; Ok(ast::Expression::For(ast::For { index_variable, index_name: self.interner.definition_name(for_loop.identifier.id).to_owned(), - index_type: self.convert_type(&self.interner.id_type(for_loop.start_range)), + index_type, start_range: Box::new(start), end_range: Box::new(end), start_range_location: self.interner.expr_location(&for_loop.start_range), @@ -593,7 +646,12 @@ impl<'interner> Monomorphizer<'interner> { HirStatement::Semi(expr) => { self.expr(expr).map(|expr| ast::Expression::Semi(Box::new(expr))) } + HirStatement::Break => Ok(ast::Expression::Break), + HirStatement::Continue => Ok(ast::Expression::Continue), HirStatement::Error => unreachable!(), + + // All `comptime` statements & expressions should be removed before runtime. + HirStatement::Comptime(_) => unreachable!("comptime statement in runtime code"), } } @@ -603,7 +661,7 @@ impl<'interner> Monomorphizer<'interner> { ) -> Result { let expr = self.expr(let_statement.expression)?; let expected_type = self.interner.id_type(let_statement.expression); - Ok(self.unpack_pattern(let_statement.pattern, expr, &expected_type)) + self.unpack_pattern(let_statement.pattern, expr, &expected_type) } fn constructor( @@ -624,7 +682,8 @@ impl<'interner> Monomorphizer<'interner> { for (field_name, expr_id) in constructor.fields { let new_id = self.next_local_id(); let field_type = field_type_map.get(&field_name.0.contents).unwrap(); - let typ = self.convert_type(field_type); + let location = self.interner.expr_location(&expr_id); + let typ = Self::convert_type(field_type, location)?; field_vars.insert(field_name.0.contents.clone(), (new_id, typ)); let expression = Box::new(self.expr(expr_id)?); @@ -668,19 +727,19 @@ impl<'interner> Monomorphizer<'interner> { pattern: HirPattern, value: ast::Expression, typ: &HirType, - ) -> ast::Expression { + ) -> Result { match pattern { HirPattern::Identifier(ident) => { let new_id = self.next_local_id(); self.define_local(ident.id, new_id); let definition = self.interner.definition(ident.id); - ast::Expression::Let(ast::Let { + Ok(ast::Expression::Let(ast::Let { id: new_id, mutable: definition.mutable, name: definition.name.clone(), expression: Box::new(value), - }) + })) } HirPattern::Mutable(pattern, _) => self.unpack_pattern(*pattern, value, typ), HirPattern::Tuple(patterns, _) => { @@ -709,7 +768,7 @@ impl<'interner> Monomorphizer<'interner> { &mut self, value: ast::Expression, fields: impl Iterator, - ) -> ast::Expression { + ) -> Result { let fresh_id = self.next_local_id(); let mut definitions = vec![ast::Expression::Let(ast::Let { @@ -720,21 +779,22 @@ impl<'interner> Monomorphizer<'interner> { })]; for (i, (field_pattern, field_type)) in fields.into_iter().enumerate() { - let location = None; + let location = field_pattern.location(); let mutable = false; let definition = Definition::Local(fresh_id); let name = i.to_string(); - let typ = self.convert_type(&field_type); + let typ = Self::convert_type(&field_type, location)?; + let location = Some(location); let new_rhs = ast::Expression::Ident(ast::Ident { location, mutable, definition, name, typ }); let new_rhs = ast::Expression::ExtractTupleField(Box::new(new_rhs), i); - let new_expr = self.unpack_pattern(field_pattern, new_rhs, &field_type); + let new_expr = self.unpack_pattern(field_pattern, new_rhs, &field_type)?; definitions.push(new_expr); } - ast::Expression::Block(definitions) + Ok(ast::Expression::Block(definitions)) } /// Find a captured variable in the innermost closure, and construct an expression @@ -759,27 +819,33 @@ impl<'interner> Monomorphizer<'interner> { }) } - /// A local (ie non-global) ident only - fn local_ident(&mut self, ident: &HirIdent) -> Option { + /// A local (ie non-function) ident only + fn local_ident( + &mut self, + ident: &HirIdent, + ) -> Result, MonomorphizationError> { let definition = self.interner.definition(ident.id); let name = definition.name.clone(); let mutable = definition.mutable; - let definition = self.lookup_local(ident.id)?; - let typ = self.convert_type(&self.interner.definition_type(ident.id)); + let Some(definition) = self.lookup_local(ident.id) else { + return Ok(None); + }; - Some(ast::Ident { location: Some(ident.location), mutable, definition, name, typ }) + let typ = Self::convert_type(&self.interner.definition_type(ident.id), ident.location)?; + Ok(Some(ast::Ident { location: Some(ident.location), mutable, definition, name, typ })) } fn ident( &mut self, ident: HirIdent, expr_id: node_interner::ExprId, + generics: Option>, ) -> Result { let typ = self.interner.id_type(expr_id); if let ImplKind::TraitMethod(method, _, _) = ident.impl_kind { - return Ok(self.resolve_trait_method_reference(expr_id, typ, method)); + return self.resolve_trait_method_reference(expr_id, typ, method); } let definition = self.interner.definition(ident.id); @@ -788,8 +854,14 @@ impl<'interner> Monomorphizer<'interner> { let mutable = definition.mutable; let location = Some(ident.location); let name = definition.name.clone(); - let definition = self.lookup_function(*func_id, expr_id, &typ, None); - let typ = self.convert_type(&typ); + let definition = self.lookup_function( + *func_id, + expr_id, + &typ, + generics.unwrap_or_default(), + None, + ); + let typ = Self::convert_type(&typ, ident.location)?; let ident = ast::Ident { location, mutable, definition, name, typ: typ.clone() }; let ident_expression = ast::Expression::Ident(ident); if self.is_function_closure_type(&typ) { @@ -805,30 +877,40 @@ impl<'interner> Monomorphizer<'interner> { } } DefinitionKind::Global(global_id) => { - let Some(let_) = self.interner.get_global_let_statement(*global_id) else { - unreachable!( - "Globals should have a corresponding let statement by monomorphization" - ) + let global = self.interner.get_global(*global_id); + + let expr = if let Some(value) = global.value.clone() { + value + .into_hir_expression(self.interner, global.location) + .map_err(MonomorphizationError::InterpreterError)? + } else { + let let_ = self.interner.get_global_let_statement(*global_id).expect( + "Globals should have a corresponding let statement by monomorphization", + ); + let_.expression }; - self.expr(let_.expression)? + self.expr(expr)? } - DefinitionKind::Local(_) => self.lookup_captured_expr(ident.id).unwrap_or_else(|| { - let ident = self.local_ident(&ident).unwrap(); - ast::Expression::Ident(ident) - }), + DefinitionKind::Local(_) => match self.lookup_captured_expr(ident.id) { + Some(expr) => expr, + None => { + let ident = self.local_ident(&ident)?.unwrap(); + ast::Expression::Ident(ident) + } + }, DefinitionKind::GenericType(type_variable) => { let value = match &*type_variable.borrow() { TypeBinding::Unbound(_) => { unreachable!("Unbound type variable used in expression") } - TypeBinding::Bound(binding) => binding.evaluate_to_u64().unwrap_or_else(|| { + TypeBinding::Bound(binding) => binding.evaluate_to_u32().unwrap_or_else(|| { panic!("Non-numeric type variable used in expression expecting a value") }), }; let value = FieldElement::from(value as u128); let location = self.interner.id_location(expr_id); - let typ = self.convert_type(&typ); + let typ = Self::convert_type(&typ, ident.location)?; ast::Expression::Literal(ast::Literal::Integer(value, typ, location)) } }; @@ -837,81 +919,82 @@ impl<'interner> Monomorphizer<'interner> { } /// Convert a non-tuple/struct type to a monomorphized type - fn convert_type(&self, typ: &HirType) -> ast::Type { - match typ { + fn convert_type(typ: &HirType, location: Location) -> Result { + Ok(match typ { HirType::FieldElement => ast::Type::Field, HirType::Integer(sign, bits) => ast::Type::Integer(*sign, *bits), HirType::Bool => ast::Type::Bool, - HirType::String(size) => ast::Type::String(size.evaluate_to_u64().unwrap_or(0)), + HirType::String(size) => ast::Type::String(size.evaluate_to_u32().unwrap_or(0)), HirType::FmtString(size, fields) => { - let size = size.evaluate_to_u64().unwrap_or(0); - let fields = Box::new(self.convert_type(fields.as_ref())); + let size = size.evaluate_to_u32().unwrap_or(0); + let fields = Box::new(Self::convert_type(fields.as_ref(), location)?); ast::Type::FmtString(size, fields) } HirType::Unit => ast::Type::Unit, HirType::Array(length, element) => { - let element = Box::new(self.convert_type(element.as_ref())); - - if let Some(length) = length.evaluate_to_u64() { - ast::Type::Array(length, element) - } else { - ast::Type::Slice(element) - } + let element = Box::new(Self::convert_type(element.as_ref(), location)?); + let length = match length.evaluate_to_u32() { + Some(length) => length, + None => return Err(MonomorphizationError::TypeAnnotationsNeeded { location }), + }; + ast::Type::Array(length, element) + } + HirType::Slice(element) => { + let element = Box::new(Self::convert_type(element.as_ref(), location)?); + ast::Type::Slice(element) } HirType::TraitAsType(..) => { unreachable!("All TraitAsType should be replaced before calling convert_type"); } HirType::NamedGeneric(binding, _) => { if let TypeBinding::Bound(binding) = &*binding.borrow() { - return self.convert_type(binding); + return Self::convert_type(binding, location); } // Default any remaining unbound type variables. // This should only happen if the variable in question is unused // and within a larger generic type. - binding.bind(HirType::default_int_type()); + binding.bind(HirType::default_int_or_field_type()); ast::Type::Field } HirType::TypeVariable(binding, kind) => { if let TypeBinding::Bound(binding) = &*binding.borrow() { - return self.convert_type(binding); + return Self::convert_type(binding, location); } // Default any remaining unbound type variables. // This should only happen if the variable in question is unused // and within a larger generic type. - let default = if self.is_range_loop - && (matches!(kind, TypeVariableKind::IntegerOrField) - || matches!(kind, TypeVariableKind::Integer)) - { - Type::default_range_loop_type() - } else { - kind.default_type() + let default = match kind.default_type() { + Some(typ) => typ, + None => return Err(MonomorphizationError::TypeAnnotationsNeeded { location }), }; - let monomorphized_default = self.convert_type(&default); + let monomorphized_default = Self::convert_type(&default, location)?; binding.bind(default); monomorphized_default } HirType::Struct(def, args) => { let fields = def.borrow().get_fields(args); - let fields = vecmap(fields, |(_, field)| self.convert_type(&field)); + let fields = try_vecmap(fields, |(_, field)| Self::convert_type(&field, location))?; ast::Type::Tuple(fields) } - HirType::Alias(def, args) => self.convert_type(&def.borrow().get_type(args)), + HirType::Alias(def, args) => { + Self::convert_type(&def.borrow().get_type(args), location)? + } HirType::Tuple(fields) => { - let fields = vecmap(fields, |x| self.convert_type(x)); + let fields = try_vecmap(fields, |x| Self::convert_type(x, location))?; ast::Type::Tuple(fields) } HirType::Function(args, ret, env) => { - let args = vecmap(args, |x| self.convert_type(x)); - let ret = Box::new(self.convert_type(ret)); - let env = self.convert_type(env); + let args = try_vecmap(args, |x| Self::convert_type(x, location))?; + let ret = Box::new(Self::convert_type(ret, location)?); + let env = Self::convert_type(env, location)?; match &env { ast::Type::Unit => ast::Type::Function(args, ret, Box::new(env)), ast::Type::Tuple(_elements) => ast::Type::Tuple(vec![ @@ -927,17 +1010,15 @@ impl<'interner> Monomorphizer<'interner> { } HirType::MutableReference(element) => { - let element = self.convert_type(element); + let element = Self::convert_type(element, location)?; ast::Type::MutableReference(Box::new(element)) } - HirType::Forall(_, _) - | HirType::Constant(_) - | HirType::NotConstant - | HirType::Error => { + HirType::Forall(_, _) | HirType::Constant(_) | HirType::Error => { unreachable!("Unexpected type {} found", typ) } - } + HirType::Code => unreachable!("Tried to translate Code type into runtime code"), + }) } fn is_function_closure(&self, t: ast::Type) -> bool { @@ -968,7 +1049,7 @@ impl<'interner> Monomorphizer<'interner> { expr_id: node_interner::ExprId, function_type: HirType, method: TraitMethodId, - ) -> ast::Expression { + ) -> Result { let trait_impl = self .interner .get_selected_impl_for_expression(expr_id) @@ -995,7 +1076,12 @@ impl<'interner> Monomorphizer<'interner> { Err(constraints) => { let failed_constraints = vecmap(constraints, |constraint| { let id = constraint.trait_id; - let name = self.interner.get_trait(id).name.to_string(); + let mut name = self.interner.get_trait(id).name.to_string(); + if !constraint.trait_generics.is_empty() { + let types = + vecmap(&constraint.trait_generics, |t| format!("{t:?}")); + name += &format!("<{}>", types.join(", ")); + } format!(" {}: {name}", constraint.typ) }) .join("\n"); @@ -1006,19 +1092,22 @@ impl<'interner> Monomorphizer<'interner> { } }; - let func_id = match self.lookup_function(func_id, expr_id, &function_type, Some(method)) { - Definition::Function(func_id) => func_id, - _ => unreachable!(), - }; + let func_id = + match self.lookup_function(func_id, expr_id, &function_type, vec![], Some(method)) { + Definition::Function(func_id) => func_id, + _ => unreachable!(), + }; let the_trait = self.interner.get_trait(method.trait_id); - ast::Expression::Ident(ast::Ident { + let location = self.interner.expr_location(&expr_id); + + Ok(ast::Expression::Ident(ast::Ident { definition: Definition::Function(func_id), mutable: false, location: None, name: the_trait.methods[method.method_index].name.0.contents.clone(), - typ: self.convert_type(&function_type), - }) + typ: Self::convert_type(&function_type, location)?, + })) } fn function_call( @@ -1033,7 +1122,8 @@ impl<'interner> Monomorphizer<'interner> { self.patch_debug_instrumentation_call(&call, &mut arguments)?; let return_type = self.interner.id_type(id); - let return_type = self.convert_type(&return_type); + let location = self.interner.expr_location(&id); + let return_type = Self::convert_type(&return_type, location)?; let location = call.location; @@ -1044,16 +1134,13 @@ impl<'interner> Monomorphizer<'interner> { // The first argument to the `print` oracle is a bool, indicating a newline to be inserted at the end of the input // The second argument is expected to always be an ident self.append_printable_type_info(&hir_arguments[1], &mut arguments); - } else if name.as_str() == "assert_message" { - // The first argument to the `assert_message` oracle is the expression passed as a message to an `assert` or `assert_eq` statement - self.append_printable_type_info(&hir_arguments[0], &mut arguments); } } } let mut block_expressions = vec![]; let func_type = self.interner.id_type(call.func); - let func_type = self.convert_type(&func_type); + let func_type = Self::convert_type(&func_type, location)?; let is_closure = self.is_function_closure(func_type); let func = if is_closure { @@ -1075,7 +1162,7 @@ impl<'interner> Monomorphizer<'interner> { definition: Definition::Local(local_id), mutable: false, name: "tmp".to_string(), - typ: self.convert_type(&self.interner.id_type(call.func)), + typ: Self::convert_type(&self.interner.id_type(call.func), location)?, }); let env_argument = @@ -1115,7 +1202,7 @@ impl<'interner> Monomorphizer<'interner> { arguments: &mut Vec, ) { match hir_argument { - HirExpression::Ident(ident) => { + HirExpression::Ident(ident, _) => { let typ = self.interner.definition_type(ident.id); let typ: Type = typ.follow_bindings(); let is_fmt_str = match typ { @@ -1149,11 +1236,7 @@ impl<'interner> Monomorphizer<'interner> { fn append_printable_type_info_inner(typ: &Type, arguments: &mut Vec) { // Disallow printing slices and mutable references for consistency, // since they cannot be passed from ACIR into Brillig - if let HirType::Array(size, _) = typ { - if let HirType::NotConstant = **size { - unreachable!("println and format strings do not support slices. Convert the slice to an array before passing it to println"); - } - } else if matches!(typ, HirType::MutableReference(_)) { + if matches!(typ, HirType::MutableReference(_)) { unreachable!("println and format strings do not support mutable references."); } @@ -1221,13 +1304,14 @@ impl<'interner> Monomorphizer<'interner> { location: Location, ) -> ast::Expression { use ast::*; - let int_type = Type::Integer(crate::Signedness::Unsigned, arr_elem_bits); + + let int_type = Type::Integer(crate::ast::Signedness::Unsigned, arr_elem_bits); let bytes_as_expr = vecmap(bytes, |byte| { Expression::Literal(Literal::Integer((byte as u128).into(), int_type.clone(), location)) }); - let typ = Type::Array(bytes_as_expr.len() as u64, Box::new(int_type)); + let typ = Type::Array(bytes_as_expr.len() as u32, Box::new(int_type)); let arr_literal = ArrayLiteral { typ, contents: bytes_as_expr }; Expression::Literal(Literal::Array(arr_literal)) @@ -1238,10 +1322,11 @@ impl<'interner> Monomorphizer<'interner> { id: node_interner::FuncId, expr_id: node_interner::ExprId, function_type: HirType, + turbofish_generics: Vec, trait_method: Option, ) -> FuncId { let new_id = self.next_function_id(); - self.define_global(id, function_type.clone(), new_id); + self.define_function(id, function_type.clone(), turbofish_generics, new_id); let bindings = self.interner.get_instantiation_bindings(expr_id); let bindings = self.follow_bindings(bindings); @@ -1277,24 +1362,24 @@ impl<'interner> Monomorphizer<'interner> { fn lvalue(&mut self, lvalue: HirLValue) -> Result { let value = match lvalue { - HirLValue::Ident(ident, _) => self - .lookup_captured_lvalue(ident.id) - .unwrap_or_else(|| ast::LValue::Ident(self.local_ident(&ident).unwrap())), + HirLValue::Ident(ident, _) => match self.lookup_captured_lvalue(ident.id) { + Some(value) => value, + None => ast::LValue::Ident(self.local_ident(&ident)?.unwrap()), + }, HirLValue::MemberAccess { object, field_index, .. } => { let field_index = field_index.unwrap(); let object = Box::new(self.lvalue(*object)?); ast::LValue::MemberAccess { object, field_index } } - HirLValue::Index { array, index, typ } => { - let location = self.interner.expr_location(&index); + HirLValue::Index { array, index, typ, location } => { let array = Box::new(self.lvalue(*array)?); let index = Box::new(self.expr(index)?); - let element_type = self.convert_type(&typ); + let element_type = Self::convert_type(&typ, location)?; ast::LValue::Index { array, index, element_type, location } } - HirLValue::Dereference { lvalue, element_type } => { + HirLValue::Dereference { lvalue, element_type, location } => { let reference = Box::new(self.lvalue(*lvalue)?); - let element_type = self.convert_type(&element_type); + let element_type = Self::convert_type(&element_type, location)?; ast::LValue::Dereference { reference, element_type } } }; @@ -1308,7 +1393,7 @@ impl<'interner> Monomorphizer<'interner> { expr: node_interner::ExprId, ) -> Result { if lambda.captures.is_empty() { - self.lambda_no_capture(lambda) + self.lambda_no_capture(lambda, expr) } else { let (setup, closure_variable) = self.lambda_with_setup(lambda, expr)?; Ok(ast::Expression::Block(vec![setup, closure_variable])) @@ -1318,16 +1403,19 @@ impl<'interner> Monomorphizer<'interner> { fn lambda_no_capture( &mut self, lambda: HirLambda, + expr: node_interner::ExprId, ) -> Result { - let ret_type = self.convert_type(&lambda.return_type); + let location = self.interner.expr_location(&expr); + let ret_type = Self::convert_type(&lambda.return_type, location)?; let lambda_name = "lambda"; - let parameter_types = vecmap(&lambda.parameters, |(_, typ)| self.convert_type(typ)); + let parameter_types = + try_vecmap(&lambda.parameters, |(_, typ)| Self::convert_type(typ, location))?; // Manually convert to Parameters type so we can reuse the self.parameters method let parameters = vecmap(lambda.parameters, |(pattern, typ)| (pattern, typ, Visibility::Private)).into(); - let parameters = self.parameters(¶meters); + let parameters = self.parameters(¶meters)?; let body = self.expr(lambda.body)?; let id = self.next_function_id(); @@ -1335,7 +1423,16 @@ impl<'interner> Monomorphizer<'interner> { let name = lambda_name.to_owned(); let unconstrained = false; - let function = ast::Function { id, name, parameters, body, return_type, unconstrained }; + let function = ast::Function { + id, + name, + parameters, + body, + return_type, + unconstrained, + inline_type: InlineType::default(), + func_sig: FunctionSignature::default(), + }; self.push_function(id, function); let typ = @@ -1370,15 +1467,17 @@ impl<'interner> Monomorphizer<'interner> { // patterns in the resulting tree, // which seems more fragile, we directly reuse the return parameters // of this function in those cases - let ret_type = self.convert_type(&lambda.return_type); + let location = self.interner.expr_location(&expr); + let ret_type = Self::convert_type(&lambda.return_type, location)?; let lambda_name = "lambda"; - let parameter_types = vecmap(&lambda.parameters, |(_, typ)| self.convert_type(typ)); + let parameter_types = + try_vecmap(&lambda.parameters, |(_, typ)| Self::convert_type(typ, location))?; // Manually convert to Parameters type so we can reuse the self.parameters method let parameters = vecmap(lambda.parameters, |(pattern, typ)| (pattern, typ, Visibility::Private)).into(); - let mut converted_parameters = self.parameters(¶meters); + let mut converted_parameters = self.parameters(¶meters)?; let id = self.next_function_id(); let name = lambda_name.to_owned(); @@ -1386,26 +1485,27 @@ impl<'interner> Monomorphizer<'interner> { let env_local_id = self.next_local_id(); let env_name = "env"; - let env_tuple = ast::Expression::Tuple(vecmap(&lambda.captures, |capture| { - match capture.transitive_capture_index { - Some(field_index) => match self.lambda_envs_stack.last() { - Some(lambda_ctx) => ast::Expression::ExtractTupleField( - Box::new(ast::Expression::Ident(lambda_ctx.env_ident.clone())), - field_index, - ), - None => unreachable!( - "Expected to find a parent closure environment, but found none" - ), - }, - None => { - let ident = self.local_ident(&capture.ident).unwrap(); - ast::Expression::Ident(ident) + let env_tuple = + ast::Expression::Tuple(try_vecmap(&lambda.captures, |capture| { + match capture.transitive_capture_index { + Some(field_index) => { + let lambda_ctx = self.lambda_envs_stack.last().expect( + "Expected to find a parent closure environment, but found none", + ); + + let ident = Box::new(ast::Expression::Ident(lambda_ctx.env_ident.clone())); + Ok(ast::Expression::ExtractTupleField(ident, field_index)) + } + None => { + let ident = self.local_ident(&capture.ident)?.unwrap(); + Ok(ast::Expression::Ident(ident)) + } } - } - })); + })?); + let expr_type = self.interner.id_type(expr); let env_typ = if let types::Type::Function(_, _, function_env_type) = expr_type { - self.convert_type(&function_env_type) + Self::convert_type(&function_env_type, location)? } else { unreachable!("expected a Function type for a Lambda node") }; @@ -1449,7 +1549,16 @@ impl<'interner> Monomorphizer<'interner> { parameters.append(&mut converted_parameters); let unconstrained = false; - let function = ast::Function { id, name, parameters, body, return_type, unconstrained }; + let function = ast::Function { + id, + name, + parameters, + body, + return_type, + unconstrained, + inline_type: InlineType::default(), + func_sig: FunctionSignature::default(), + }; self.push_function(id, function); let lambda_value = @@ -1490,9 +1599,7 @@ impl<'interner> Monomorphizer<'interner> { ast::Expression::Literal(ast::Literal::Integer(0_u128.into(), typ, location)) } ast::Type::Bool => ast::Expression::Literal(ast::Literal::Bool(false)), - // There is no unit literal currently. Replace it with 'false' since it should be ignored - // anyway. - ast::Type::Unit => ast::Expression::Literal(ast::Literal::Bool(false)), + ast::Type::Unit => ast::Expression::Literal(ast::Literal::Unit), ast::Type::Array(length, element_type) => { let element = self.zeroed_value_of_type(element_type.as_ref(), location); ast::Expression::Literal(ast::Literal::Array(ast::ArrayLiteral { @@ -1528,7 +1635,7 @@ impl<'interner> Monomorphizer<'interner> { })) } ast::Type::MutableReference(element) => { - use crate::UnaryOp::MutableReference; + use crate::ast::UnaryOp::MutableReference; let rhs = Box::new(self.zeroed_value_of_type(element, location)); let result_type = typ.clone(); ast::Expression::Unary(ast::Unary { @@ -1567,7 +1674,16 @@ impl<'interner> Monomorphizer<'interner> { let name = lambda_name.to_owned(); let unconstrained = false; - let function = ast::Function { id, name, parameters, body, return_type, unconstrained }; + let function = ast::Function { + id, + name, + parameters, + body, + return_type, + unconstrained, + inline_type: InlineType::default(), + func_sig: FunctionSignature::default(), + }; self.push_function(id, function); ast::Expression::Ident(ast::Ident { @@ -1596,15 +1712,15 @@ impl<'interner> Monomorphizer<'interner> { rhs: ast::Expression, ret: Type, location: Location, - ) -> ast::Expression { + ) -> Result { let arguments = vec![lhs, rhs]; let func = Box::new(func); - let return_type = self.convert_type(&ret); + let return_type = Self::convert_type(&ret, location)?; let mut result = ast::Expression::Call(ast::Call { func, arguments, return_type, location }); - use crate::BinaryOpKind::*; + use crate::ast::BinaryOpKind::*; match operator.kind { // Negate the result of the == operation NotEqual => { @@ -1644,7 +1760,7 @@ impl<'interner> Monomorphizer<'interner> { _ => (), } - result + Ok(result) } /// Call sites are instantiated against the trait method, but when an impl is later selected, @@ -1689,23 +1805,15 @@ impl<'interner> Monomorphizer<'interner> { } fn unwrap_tuple_type(typ: &HirType) -> Vec { - match typ { + match typ.follow_bindings() { HirType::Tuple(fields) => fields.clone(), - HirType::TypeVariable(binding, TypeVariableKind::Normal) => match &*binding.borrow() { - TypeBinding::Bound(binding) => unwrap_tuple_type(binding), - TypeBinding::Unbound(_) => unreachable!(), - }, other => unreachable!("unwrap_tuple_type: expected tuple, found {:?}", other), } } fn unwrap_struct_type(typ: &HirType) -> Vec<(String, HirType)> { - match typ { - HirType::Struct(def, args) => def.borrow().get_fields(args), - HirType::TypeVariable(binding, TypeVariableKind::Normal) => match &*binding.borrow() { - TypeBinding::Bound(binding) => unwrap_struct_type(binding), - TypeBinding::Unbound(_) => unreachable!(), - }, + match typ.follow_bindings() { + HirType::Struct(def, args) => def.borrow().get_fields(&args), other => unreachable!("unwrap_struct_type: expected struct, found {:?}", other), } } diff --git a/compiler/noirc_frontend/src/monomorphization/printer.rs b/compiler/noirc_frontend/src/monomorphization/printer.rs index 7aec2193494..ea8f079cc2f 100644 --- a/compiler/noirc_frontend/src/monomorphization/printer.rs +++ b/compiler/noirc_frontend/src/monomorphization/printer.rs @@ -73,6 +73,8 @@ impl AstPrinter { self.print_expr(expr, f)?; write!(f, ";") } + Expression::Break => write!(f, "break"), + Expression::Continue => write!(f, "continue"), } } @@ -95,6 +97,11 @@ impl AstPrinter { self.print_comma_separated(&array.contents, f)?; write!(f, "]") } + super::ast::Literal::Slice(array) => { + write!(f, "&[")?; + self.print_comma_separated(&array.contents, f)?; + write!(f, "]") + } super::ast::Literal::Integer(x, _, _) => x.fmt(f), super::ast::Literal::Bool(x) => x.fmt(f), super::ast::Literal::Str(s) => s.fmt(f), @@ -103,6 +110,9 @@ impl AstPrinter { s.fmt(f)?; write!(f, "\"") } + super::ast::Literal::Unit => { + write!(f, "()") + } } } diff --git a/compiler/noirc_frontend/src/node_interner.rs b/compiler/noirc_frontend/src/node_interner.rs index 5de43e59254..cef49332b00 100644 --- a/compiler/noirc_frontend/src/node_interner.rs +++ b/compiler/noirc_frontend/src/node_interner.rs @@ -1,10 +1,11 @@ use std::borrow::Cow; use std::collections::HashMap; +use std::fmt; use std::ops::Deref; -use arena::{Arena, Index}; use fm::FileId; use iter_extended::vecmap; +use noirc_arena::{Arena, Index}; use noirc_errors::{Location, Span, Spanned}; use petgraph::algo::tarjan_scc; use petgraph::prelude::DiGraph; @@ -12,11 +13,14 @@ use petgraph::prelude::NodeIndex as PetGraphIndex; use crate::ast::Ident; use crate::graph::CrateId; +use crate::hir::comptime; use crate::hir::def_collector::dc_crate::CompilationError; use crate::hir::def_collector::dc_crate::{UnresolvedStruct, UnresolvedTrait, UnresolvedTypeAlias}; use crate::hir::def_map::{LocalModuleId, ModuleId}; +use crate::ast::{BinaryOpKind, FunctionDefinition, ItemVisibility}; use crate::hir::resolution::errors::ResolverError; +use crate::hir_def::expr::HirIdent; use crate::hir_def::stmt::HirLetStatement; use crate::hir_def::traits::TraitImpl; use crate::hir_def::traits::{Trait, TraitConstraint}; @@ -28,8 +32,7 @@ use crate::hir_def::{ }; use crate::token::{Attributes, SecondaryAttribute}; use crate::{ - BinaryOpKind, ContractFunctionType, FunctionDefinition, FunctionVisibility, Generics, Shared, - TypeAlias, TypeBindings, TypeVariable, TypeVariableId, TypeVariableKind, + Generics, Shared, TypeAlias, TypeBindings, TypeVariable, TypeVariableId, TypeVariableKind, }; /// An arbitrary number to limit the recursion depth when searching for trait impls. @@ -110,7 +113,9 @@ pub struct NodeInterner { // The purpose for this hashmap is to detect duplication of trait implementations ( if any ) // // Indexed by TraitImplIds - pub(crate) trait_implementations: Vec>, + pub(crate) trait_implementations: HashMap>, + + next_trait_implementation_id: usize, /// Trait implementations on each type. This is expected to always have the same length as /// `self.trait_implementations`. @@ -146,6 +151,7 @@ pub struct NodeInterner { // Maps GlobalId -> GlobalInfo // NOTE: currently only used for checking repeat globals and restricting their scope to a module globals: Vec, + global_attributes: HashMap>, next_type_variable_id: std::cell::Cell, @@ -222,10 +228,10 @@ pub enum TraitImplKind { /// /// Additionally, types can define specialized impls with methods of the same name /// as long as these specialized impls do not overlap. E.g. `impl Struct` and `impl Struct` -#[derive(Default, Debug)] +#[derive(Default, Debug, Clone)] pub struct Methods { - direct: Vec, - trait_impl_methods: Vec, + pub direct: Vec, + pub trait_impl_methods: Vec, } /// All the information from a function that is filled out during definition collection rather than @@ -236,20 +242,15 @@ pub struct FunctionModifiers { pub name: String, /// Whether the function is `pub` or not. - pub visibility: FunctionVisibility, + pub visibility: ItemVisibility, pub attributes: Attributes, pub is_unconstrained: bool, - /// This function's type in its contract. - /// If this function is not in a contract, this is always 'Secret'. - pub contract_function_type: Option, + pub generic_count: usize, - /// This function's contract visibility. - /// If this function is internal can only be called by itself. - /// Will be None if not in contract. - pub is_internal: Option, + pub is_comptime: bool, } impl FunctionModifiers { @@ -259,11 +260,11 @@ impl FunctionModifiers { pub fn new() -> Self { Self { name: String::new(), - visibility: FunctionVisibility::Public, + visibility: ItemVisibility::Public, attributes: Attributes::empty(), is_unconstrained: false, - is_internal: None, - contract_function_type: None, + generic_count: 0, + is_comptime: false, } } } @@ -279,7 +280,7 @@ impl DefinitionId { } /// An ID for a global value -#[derive(Debug, Eq, PartialEq, Hash, Clone, Copy)] +#[derive(Debug, Eq, PartialEq, Hash, Clone, Copy, PartialOrd, Ord)] pub struct GlobalId(usize); impl GlobalId { @@ -321,6 +322,12 @@ impl FuncId { } } +impl fmt::Display for FuncId { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.0.fmt(f) + } +} + #[derive(Debug, Eq, PartialEq, Hash, Copy, Clone, PartialOrd, Ord)] pub struct StructId(ModuleId); @@ -461,6 +468,7 @@ pub struct GlobalInfo { pub local_id: LocalModuleId, pub location: Location, pub let_statement: StmtId, + pub value: Option, } impl Default for NodeInterner { @@ -482,7 +490,8 @@ impl Default for NodeInterner { struct_attributes: HashMap::new(), type_aliases: Vec::new(), traits: HashMap::new(), - trait_implementations: Vec::new(), + trait_implementations: HashMap::new(), + next_trait_implementation_id: 0, trait_implementation_map: HashMap::new(), selected_trait_implementations: HashMap::new(), operator_traits: HashMap::new(), @@ -491,6 +500,7 @@ impl Default for NodeInterner { field_indices: HashMap::new(), next_type_variable_id: std::cell::Cell::new(0), globals: Vec::new(), + global_attributes: HashMap::new(), struct_methods: HashMap::new(), primitive_methods: HashMap::new(), type_alias_ref: Vec::new(), @@ -531,7 +541,7 @@ impl NodeInterner { self.id_to_type.insert(expr_id.into(), typ); } - /// Store the type for an interned expression + /// Store the type for a definition pub fn push_definition_type(&mut self, definition_id: DefinitionId, typ: Type) { self.definition_to_type.insert(definition_id, typ); } @@ -658,11 +668,15 @@ impl NodeInterner { local_id: LocalModuleId, let_statement: StmtId, file: FileId, + attributes: Vec, + mutable: bool, ) -> GlobalId { let id = GlobalId(self.globals.len()); let location = Location::new(ident.span(), file); let name = ident.to_string(); - let definition_id = self.push_definition(name, false, DefinitionKind::Global(id), location); + let definition_id = + self.push_definition(name, mutable, DefinitionKind::Global(id), location); + self.globals.push(GlobalInfo { id, definition_id, @@ -670,7 +684,9 @@ impl NodeInterner { local_id, let_statement, location, + value: None, }); + self.global_attributes.insert(id, attributes); id } @@ -684,9 +700,14 @@ impl NodeInterner { name: Ident, local_id: LocalModuleId, file: FileId, + attributes: Vec, + mutable: bool, ) -> GlobalId { let statement = self.push_stmt(HirStatement::Error); - self.push_global(name, local_id, statement, file) + let span = name.span(); + let id = self.push_global(name, local_id, statement, file, attributes, mutable); + self.push_stmt_location(statement, span, file); + id } /// Intern an empty function. @@ -759,17 +780,13 @@ impl NodeInterner { module: ModuleId, location: Location, ) -> DefinitionId { - use ContractFunctionType::*; - - // We're filling in contract_function_type and is_internal now, but these will be verified - // later during name resolution. let modifiers = FunctionModifiers { name: function.name.0.contents.clone(), visibility: function.visibility, attributes: function.attributes.clone(), is_unconstrained: function.is_unconstrained, - contract_function_type: Some(if function.is_open { Open } else { Secret }), - is_internal: Some(function.is_internal), + generic_count: function.generics.len(), + is_comptime: function.is_comptime, }; self.push_function_definition(id, modifiers, module, location) } @@ -799,7 +816,7 @@ impl NodeInterner { /// /// The underlying function_visibilities map is populated during def collection, /// so this function can be called anytime afterward. - pub fn function_visibility(&self, func: FuncId) -> FunctionVisibility { + pub fn function_visibility(&self, func: FuncId) -> ItemVisibility { self.function_modifiers[&func].visibility } @@ -808,6 +825,21 @@ impl NodeInterner { self.function_modules[&func] } + /// Returns the [`FuncId`] corresponding to the function referred to by `expr_id` + pub fn lookup_function_from_expr(&self, expr: &ExprId) -> Option { + if let HirExpression::Ident(HirIdent { id, .. }, _) = self.expression(expr) { + if let Some(DefinitionKind::Function(func_id)) = + self.try_definition(id).map(|def| &def.kind) + { + Some(*func_id) + } else { + None + } + } else { + None + } + } + /// Returns the interned HIR function corresponding to `func_id` // // Cloning HIR structures is cheap, so we return owned structures @@ -829,10 +861,10 @@ impl NodeInterner { self.func_meta.get(func_id) } - pub fn function_ident(&self, func_id: &FuncId) -> crate::Ident { + pub fn function_ident(&self, func_id: &FuncId) -> crate::ast::Ident { let name = self.function_name(func_id).to_owned(); let span = self.function_meta(func_id).name.location.span; - crate::Ident(Spanned::from(span, name)) + crate::ast::Ident(Spanned::from(span, name)) } pub fn function_name(&self, func_id: &FuncId) -> &str { @@ -855,6 +887,10 @@ impl NodeInterner { &self.struct_attributes[struct_id] } + pub fn global_attributes(&self, global_id: &GlobalId) -> &[SecondaryAttribute] { + &self.global_attributes[global_id] + } + /// Returns the interned statement corresponding to `stmt_id` pub fn statement(&self, stmt_id: &StmtId) -> HirStatement { let def = @@ -874,8 +910,9 @@ impl NodeInterner { match def { Node::Statement(hir_stmt) => match hir_stmt { HirStatement::Let(let_stmt) => Some(let_stmt.clone()), - _ => { - panic!("ice: all globals should correspond to a let statement in the interner") + HirStatement::Error => None, + other => { + panic!("ice: all globals should correspond to a let statement in the interner: {other:?}") } }, _ => panic!("ice: all globals should correspond to a statement in the interner"), @@ -902,6 +939,13 @@ impl NodeInterner { &self.definitions[id.0] } + /// Retrieves the definition where the given id was defined. + /// This will panic if given DefinitionId::dummy_id. Use try_definition for + /// any call with a possibly undefined variable. + pub fn definition_mut(&mut self, id: DefinitionId) -> &mut DefinitionInfo { + &mut self.definitions[id.0] + } + /// Tries to retrieve the given id's definition. /// This function should be used during name resolution or type checking when we cannot be sure /// all variables have corresponding definitions (in case of an error in the user's code). @@ -924,10 +968,40 @@ impl NodeInterner { self.id_location(expr_id) } + pub fn statement_span(&self, stmt_id: StmtId) -> Span { + self.id_location(stmt_id).span + } + + pub fn statement_location(&self, stmt_id: StmtId) -> Location { + self.id_location(stmt_id) + } + + pub fn push_stmt_location(&mut self, id: StmtId, span: Span, file: FileId) { + self.id_to_location.insert(id.into(), Location::new(span, file)); + } + pub fn get_struct(&self, id: StructId) -> Shared { self.structs[&id].clone() } + pub fn get_struct_methods(&self, id: StructId) -> Vec { + self.struct_methods + .keys() + .filter_map(|(key_id, name)| { + if key_id == &id { + Some( + self.struct_methods + .get(&(*key_id, name.clone())) + .expect("get_struct_methods given invalid StructId") + .clone(), + ) + } else { + None + } + }) + .collect() + } + pub fn get_trait(&self, id: TraitId) -> &Trait { &self.traits[&id] } @@ -948,11 +1022,20 @@ impl NodeInterner { &self.globals[global_id.0] } + pub fn get_global_mut(&mut self, global_id: GlobalId) -> &mut GlobalInfo { + &mut self.globals[global_id.0] + } + pub fn get_global_definition(&self, global_id: GlobalId) -> &DefinitionInfo { let global = self.get_global(global_id); self.definition(global.definition_id) } + pub fn get_global_definition_mut(&mut self, global_id: GlobalId) -> &mut DefinitionInfo { + let global = self.get_global(global_id); + self.definition_mut(global.definition_id) + } + pub fn get_all_globals(&self) -> &[GlobalInfo] { &self.globals } @@ -1086,8 +1169,12 @@ impl NodeInterner { } } + pub fn try_get_trait_implementation(&self, id: TraitImplId) -> Option> { + self.trait_implementations.get(&id).cloned() + } + pub fn get_trait_implementation(&self, id: TraitImplId) -> Shared { - self.trait_implementations[id.0].clone() + self.trait_implementations[&id].clone() } /// Given a `ObjectType: TraitId` pair, try to find an existing impl that satisfies the @@ -1096,6 +1183,7 @@ impl NodeInterner { /// 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. + /// If this list of failing constraints is empty, this means type annotations are required. pub fn lookup_trait_implementation( &self, object_type: &Type, @@ -1138,6 +1226,10 @@ impl NodeInterner { } /// Similar to `lookup_trait_implementation` but does not apply any type bindings on success. + /// On error returns either: + /// - 1+ failing trait constraints, including the original. + /// Each constraint after the first represents a `where` clause that was followed. + /// - 0 trait constraints indicating type annotations are needed to choose an impl. pub fn try_lookup_trait_implementation( &self, object_type: &Type, @@ -1155,6 +1247,11 @@ impl NodeInterner { Ok((impl_kind, bindings)) } + /// Returns the trait implementation if found. + /// On error returns either: + /// - 1+ failing trait constraints, including the original. + /// Each constraint after the first represents a `where` clause that was followed. + /// - 0 trait constraints indicating type annotations are needed to choose an impl. fn lookup_trait_implementation_helper( &self, object_type: &Type, @@ -1173,15 +1270,22 @@ impl NodeInterner { let object_type = object_type.substitute(type_bindings); + // If the object type isn't known, just return an error saying type annotations are needed. + if object_type.is_bindable() { + return Err(Vec::new()); + } + let impls = self.trait_implementation_map.get(&trait_id).ok_or_else(|| vec![make_constraint()])?; + let mut matching_impls = Vec::new(); + for (existing_object_type2, impl_kind) in impls { // Bug: We're instantiating only the object type's generics here, not all of the trait's generics like we need to let (existing_object_type, instantiation_bindings) = existing_object_type2.instantiate(self); - let mut fresh_bindings = TypeBindings::new(); + let mut fresh_bindings = type_bindings.clone(); let mut check_trait_generics = |impl_generics: &[Type]| { trait_generics.iter().zip(impl_generics).all(|(trait_generic, impl_generic2)| { @@ -1206,16 +1310,13 @@ impl NodeInterner { } if object_type.try_unify(&existing_object_type, &mut fresh_bindings).is_ok() { - // The unification was successful so we can append fresh_bindings to our bindings list - type_bindings.extend(fresh_bindings); - if 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, + &mut fresh_bindings, &instantiation_bindings, recursion_limit, ) { @@ -1224,11 +1325,20 @@ impl NodeInterner { } } - return Ok(impl_kind.clone()); + matching_impls.push((impl_kind.clone(), fresh_bindings)); } } - Err(vec![make_constraint()]) + if matching_impls.len() == 1 { + let (impl_, fresh_bindings) = matching_impls.pop().unwrap(); + *type_bindings = fresh_bindings; + Ok(impl_) + } else if matching_impls.is_empty() { + Err(vec![make_constraint()]) + } else { + // multiple matching impls, type annotations needed + Err(vec![]) + } } /// Verifies that each constraint in the given where clause is valid. @@ -1244,12 +1354,11 @@ impl NodeInterner { // Instantiation bindings are generally safe to force substitute into the same type. // This is needed here to undo any bindings done to trait methods by monomorphization. // Otherwise, an impl for (A, B) could get narrowed to only an impl for e.g. (u8, u16). - let constraint_type = constraint.typ.force_substitute(instantiation_bindings); - let constraint_type = constraint_type.substitute(type_bindings); + let constraint_type = + constraint.typ.force_substitute(instantiation_bindings).substitute(type_bindings); let trait_generics = vecmap(&constraint.trait_generics, |generic| { - let generic = generic.force_substitute(instantiation_bindings); - generic.substitute(type_bindings) + generic.force_substitute(instantiation_bindings).substitute(type_bindings) }); self.lookup_trait_implementation_helper( @@ -1258,10 +1367,11 @@ impl NodeInterner { &trait_generics, // Use a fresh set of type bindings here since the constraint_type originates from // our impl list, which we don't want to bind to. - &mut TypeBindings::new(), + type_bindings, recursion_limit - 1, )?; } + Ok(()) } @@ -1299,9 +1409,7 @@ impl NodeInterner { impl_generics: Generics, trait_impl: Shared, ) -> 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()); + self.trait_implementations.insert(impl_id, trait_impl.clone()); // Replace each generic with a fresh type variable let substitutions = impl_generics @@ -1404,10 +1512,10 @@ impl NodeInterner { } /// 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()) + pub fn next_trait_impl_id(&mut self) -> TraitImplId { + let next_id = self.next_trait_implementation_id; + self.next_trait_implementation_id += 1; + TraitImplId(next_id) } /// Removes all TraitImplKind::Assumed from the list of known impls for the given trait @@ -1681,6 +1789,7 @@ enum TypeMethodKey { /// accept only fields or integers, it is just that their names may not clash. FieldOrInt, Array, + Slice, Bool, String, FmtString, @@ -1688,6 +1797,7 @@ enum TypeMethodKey { Tuple, Function, Generic, + Code, } fn get_type_method_key(typ: &Type) -> Option { @@ -1696,6 +1806,7 @@ fn get_type_method_key(typ: &Type) -> Option { match &typ { Type::FieldElement => Some(FieldOrInt), Type::Array(_, _) => Some(Array), + Type::Slice(_) => Some(Slice), Type::Integer(_, _) => Some(FieldOrInt), Type::TypeVariable(_, TypeVariableKind::IntegerOrField) => Some(FieldOrInt), Type::TypeVariable(_, TypeVariableKind::Integer) => Some(FieldOrInt), @@ -1706,6 +1817,7 @@ fn get_type_method_key(typ: &Type) -> Option { Type::Tuple(_) => Some(Tuple), Type::Function(_, _, _) => Some(Function), Type::NamedGeneric(_, _) => Some(Generic), + Type::Code => Some(Code), Type::MutableReference(element) => get_type_method_key(element), Type::Alias(alias, _) => get_type_method_key(&alias.borrow().typ), @@ -1714,7 +1826,6 @@ fn get_type_method_key(typ: &Type) -> Option { | Type::Forall(_, _) | Type::Constant(_) | Type::Error - | Type::NotConstant | Type::Struct(_, _) | Type::TraitAsType(..) => None, } diff --git a/compiler/noirc_frontend/src/noir_parser.lalrpop b/compiler/noirc_frontend/src/noir_parser.lalrpop new file mode 100644 index 00000000000..9acb5ef8b58 --- /dev/null +++ b/compiler/noirc_frontend/src/noir_parser.lalrpop @@ -0,0 +1,164 @@ +use noirc_errors::Span; + +use crate::lexer::token::BorrowedToken; +use crate::lexer::token as noir_token; +use crate::lexer::errors::LexerErrorKind; +use crate::parser::TopLevelStatement; +use crate::ast::{Ident, Path, PathKind, UseTree, UseTreeKind}; + +use lalrpop_util::ErrorRecovery; + +grammar<'input, 'err>(input: &'input str, errors: &'err mut [ErrorRecovery, &'static str>]); + +extern { + type Location = usize; + + type Error = LexerErrorKind; + + // NOTE: each token needs a terminal defined + enum BorrowedToken<'input> { + string => BorrowedToken::Str(<&'input str>), + ident => BorrowedToken::Ident(<&'input str>), + + // symbols + "<" => BorrowedToken::Less, + "<=" => BorrowedToken::LessEqual, + ">" => BorrowedToken::Greater, + ">=" => BorrowedToken::GreaterEqual, + "==" => BorrowedToken::Equal, + "!=" => BorrowedToken::NotEqual, + "+" => BorrowedToken::Plus, + "-" => BorrowedToken::Minus, + "*" => BorrowedToken::Star, + "/" => BorrowedToken::Slash, + "%" => BorrowedToken::Percent, + "&" => BorrowedToken::Ampersand, + "^" => BorrowedToken::Caret, + "<<" => BorrowedToken::ShiftLeft, + ">>" => BorrowedToken::ShiftRight, + "." => BorrowedToken::Dot, + ".." => BorrowedToken::DoubleDot, + "(" => BorrowedToken::LeftParen, + ")" => BorrowedToken::RightParen, + "{" => BorrowedToken::LeftBrace, + "}" => BorrowedToken::RightBrace, + "[" => BorrowedToken::LeftBracket, + "]" => BorrowedToken::RightBracket, + "->" => BorrowedToken::Arrow, + "|" => BorrowedToken::Pipe, + "#" => BorrowedToken::Pound, + "," => BorrowedToken::Comma, + ":" => BorrowedToken::Colon, + "::" => BorrowedToken::DoubleColon, + ";" => BorrowedToken::Semicolon, + "!" => BorrowedToken::Bang, + "=" => BorrowedToken::Assign, + // keywords + "as" => BorrowedToken::Keyword(noir_token::Keyword::As), + "assert" => BorrowedToken::Keyword(noir_token::Keyword::Assert), + "assert_eq" => BorrowedToken::Keyword(noir_token::Keyword::AssertEq), + "bool" => BorrowedToken::Keyword(noir_token::Keyword::Bool), + "break" => BorrowedToken::Keyword(noir_token::Keyword::Break), + "call_data" => BorrowedToken::Keyword(noir_token::Keyword::CallData), + "char" => BorrowedToken::Keyword(noir_token::Keyword::Char), + "comptime" => BorrowedToken::Keyword(noir_token::Keyword::Comptime), + "constrain" => BorrowedToken::Keyword(noir_token::Keyword::Constrain), + "continue" => BorrowedToken::Keyword(noir_token::Keyword::Continue), + "contract" => BorrowedToken::Keyword(noir_token::Keyword::Contract), + "crate" => BorrowedToken::Keyword(noir_token::Keyword::Crate), + "dep" => BorrowedToken::Keyword(noir_token::Keyword::Dep), + "distinct" => BorrowedToken::Keyword(noir_token::Keyword::Distinct), + "else" => BorrowedToken::Keyword(noir_token::Keyword::Else), + "Field" => BorrowedToken::Keyword(noir_token::Keyword::Field), + "fn" => BorrowedToken::Keyword(noir_token::Keyword::Fn), + "for" => BorrowedToken::Keyword(noir_token::Keyword::For), + "fmtstr" => BorrowedToken::Keyword(noir_token::Keyword::FormatString), + "global" => BorrowedToken::Keyword(noir_token::Keyword::Global), + "if" => BorrowedToken::Keyword(noir_token::Keyword::If), + "impl" => BorrowedToken::Keyword(noir_token::Keyword::Impl), + "in" => BorrowedToken::Keyword(noir_token::Keyword::In), + "let" => BorrowedToken::Keyword(noir_token::Keyword::Let), + "mod" => BorrowedToken::Keyword(noir_token::Keyword::Mod), + "mut" => BorrowedToken::Keyword(noir_token::Keyword::Mut), + "pub" => BorrowedToken::Keyword(noir_token::Keyword::Pub), + "quote" => BorrowedToken::Keyword(noir_token::Keyword::Quote), + "return" => BorrowedToken::Keyword(noir_token::Keyword::Return), + "return_data" => BorrowedToken::Keyword(noir_token::Keyword::ReturnData), + "str" => BorrowedToken::Keyword(noir_token::Keyword::String), + "struct" => BorrowedToken::Keyword(noir_token::Keyword::Struct), + "trait" => BorrowedToken::Keyword(noir_token::Keyword::Trait), + "type" => BorrowedToken::Keyword(noir_token::Keyword::Type), + "unchecked" => BorrowedToken::Keyword(noir_token::Keyword::Unchecked), + "unconstrained" => BorrowedToken::Keyword(noir_token::Keyword::Unconstrained), + "use" => BorrowedToken::Keyword(noir_token::Keyword::Use), + "where" => BorrowedToken::Keyword(noir_token::Keyword::Where), + "while" => BorrowedToken::Keyword(noir_token::Keyword::While), + // bool + "true" => BorrowedToken::Bool(true), + "false" => BorrowedToken::Bool(false), + + r"[\t\r\n ]+" => BorrowedToken::Whitespace(_), + + EOF => BorrowedToken::EOF, + } +} + +pub(crate) TopLevelStatement: TopLevelStatement = { + "use" r"[\t\r\n ]+" ";" EOF => { + TopLevelStatement::Import(use_tree) + } +} + +UseTree: UseTree = { + // path::to::ident as SomeAlias + => { + let ident = prefix.pop(); + let kind = UseTreeKind::Path(ident, alias); + UseTree { prefix, kind } + }, +} + +pub(crate) Path: Path = { + "crate" "::" => { + let kind = PathKind::Crate; + let span = Span::from(lo as u32..hi as u32); + Path { segments, kind, span } + }, + + "dep" "::" => { + let kind = PathKind::Dep; + let span = Span::from(lo as u32..hi as u32); + Path { segments, kind, span } + }, + + => { + segments.insert(0, id); + let kind = PathKind::Plain; + let span = Span::from(lo as u32..hi as u32); + Path { segments, kind, span } + }, +} + +PathSegments: Vec = { + )*> => { + segments + } +} + +Alias: Ident = { + r"[\t\r\n ]+" "as" r"[\t\r\n ]+" => <>, +} + +Ident: Ident = { + => { + let token = noir_token::Token::Ident(i.to_string()); + let span = Span::from(lo as u32..hi as u32); + Ident::from_token(token, span) + }, +} + +Bool: BorrowedToken<'input> = { + "true" => BorrowedToken::Bool(true), + "false" => BorrowedToken::Bool(false), +}; + diff --git a/compiler/noirc_frontend/src/parser/errors.rs b/compiler/noirc_frontend/src/parser/errors.rs index 43a1f96f13f..9f9a8200954 100644 --- a/compiler/noirc_frontend/src/parser/errors.rs +++ b/compiler/noirc_frontend/src/parser/errors.rs @@ -1,7 +1,6 @@ +use crate::ast::{Expression, IntegerBitSize}; use crate::lexer::errors::LexerErrorKind; use crate::lexer::token::Token; -use crate::Expression; -use crate::IntegerBitSize; use small_ord_set::SmallOrdSet; use thiserror::Error; @@ -31,6 +30,8 @@ pub enum ParserErrorReason { TraitImplFunctionModifiers, #[error("comptime keyword is deprecated")] ComptimeDeprecated, + #[error("distinct keyword is deprecated. The `distinct` behavior is now the default.")] + DistinctDeprecated, #[error("{0} are experimental and aren't fully supported yet")] ExperimentalFeature(&'static str), #[error( @@ -110,32 +111,38 @@ impl ParserError { impl std::fmt::Display for ParserError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let reason_str: String = if self.reason.is_none() { + "".to_string() + } else { + format!("\nreason: {}", Diagnostic::from(self)) + }; let mut expected = vecmap(&self.expected_tokens, ToString::to_string); expected.append(&mut vecmap(&self.expected_labels, |label| format!("{label}"))); if expected.is_empty() { - write!(f, "Unexpected {} in input", self.found) + write!(f, "Unexpected {} in input{}", self.found, reason_str) } else if expected.len() == 1 { let first = expected.first().unwrap(); let vowel = "aeiou".contains(first.chars().next().unwrap()); write!( f, - "Expected a{} {} but found {}", + "Expected a{} {} but found {}{}", if vowel { "n" } else { "" }, first, - self.found + self.found, + reason_str ) } else { let expected = expected.iter().map(ToString::to_string).collect::>().join(", "); - write!(f, "Unexpected {}, expected one of {}", self.found, expected) + write!(f, "Unexpected {}, expected one of {}{}", self.found, expected, reason_str) } } } -impl From for Diagnostic { - fn from(error: ParserError) -> Diagnostic { - match error.reason { +impl<'a> From<&'a ParserError> for Diagnostic { + fn from(error: &'a ParserError) -> Diagnostic { + match &error.reason { Some(reason) => { match reason { ParserErrorReason::ConstrainDeprecated => Diagnostic::simple_error( diff --git a/compiler/noirc_frontend/src/parser/mod.rs b/compiler/noirc_frontend/src/parser/mod.rs index 0ff7819c00f..9e60383afee 100644 --- a/compiler/noirc_frontend/src/parser/mod.rs +++ b/compiler/noirc_frontend/src/parser/mod.rs @@ -11,12 +11,11 @@ mod labels; #[allow(clippy::module_inception)] mod parser; -use crate::token::{Keyword, Token}; -use crate::{ast::ImportStatement, Expression, NoirStruct}; -use crate::{ - Ident, LetStatement, NoirFunction, NoirTrait, NoirTraitImpl, NoirTypeAlias, Recoverable, - StatementKind, TypeImpl, UseTree, +use crate::ast::{ + Expression, Ident, ImportStatement, LetStatement, ModuleDeclaration, NoirFunction, NoirStruct, + NoirTrait, NoirTraitImpl, NoirTypeAlias, Recoverable, StatementKind, TypeImpl, UseTree, }; +use crate::token::{Keyword, Token}; use chumsky::prelude::*; use chumsky::primitive::Container; @@ -28,7 +27,7 @@ pub use parser::parse_program; #[derive(Debug, Clone)] pub(crate) enum TopLevelStatement { Function(NoirFunction), - Module(Ident), + Module(ModuleDeclaration), Import(UseTree), Struct(NoirStruct), Trait(NoirTrait), @@ -97,14 +96,14 @@ where /// Sequence the two parsers. /// Fails if the first parser fails, otherwise forces /// the second parser to succeed while logging any errors. -fn then_commit<'a, P1, P2, T1, T2: 'a>( +fn then_commit<'a, P1, P2, T1, T2>( first_parser: P1, second_parser: P2, ) -> impl NoirParser<(T1, T2)> + 'a where P1: NoirParser + 'a, P2: NoirParser + 'a, - T2: Clone + Recoverable, + T2: Clone + Recoverable + 'a, { let second_parser = skip_then_retry_until(second_parser) .map_with_span(|option, span| option.unwrap_or_else(|| Recoverable::error(span))); @@ -112,14 +111,15 @@ where first_parser.then(second_parser) } -fn then_commit_ignore<'a, P1, P2, T1: 'a, T2: 'a>( +fn then_commit_ignore<'a, P1, P2, T1, T2>( first_parser: P1, second_parser: P2, ) -> impl NoirParser + 'a where P1: NoirParser + 'a, P2: NoirParser + 'a, - T2: Clone, + T1: 'a, + T2: Clone + 'a, { let second_parser = skip_then_retry_until(second_parser); first_parser.then_ignore(second_parser) @@ -140,10 +140,10 @@ where first_parser.ignore_then(second_parser) } -fn skip_then_retry_until<'a, P, T: 'a>(parser: P) -> impl NoirParser> + 'a +fn skip_then_retry_until<'a, P, T>(parser: P) -> impl NoirParser> + 'a where P: NoirParser + 'a, - T: Clone, + T: Clone + 'a, { let terminators = [ Token::EOF, @@ -220,7 +220,7 @@ pub struct SortedModule { pub globals: Vec, /// Module declarations like `mod foo;` - pub module_decls: Vec, + pub module_decls: Vec, /// Full submodules as in `mod foo { ... definitions ... }` pub submodules: Vec, @@ -229,7 +229,7 @@ pub struct SortedModule { impl std::fmt::Display for SortedModule { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { for decl in &self.module_decls { - writeln!(f, "mod {decl};")?; + writeln!(f, "{decl};")?; } for import in &self.imports { @@ -309,7 +309,7 @@ pub enum ItemKind { Impl(TypeImpl), TypeAlias(NoirTypeAlias), Global(LetStatement), - ModuleDecl(Ident), + ModuleDecl(ModuleDeclaration), Submodules(ParsedSubModule), } @@ -380,8 +380,8 @@ impl SortedModule { self.imports.extend(import_stmt.desugar(None)); } - fn push_module_decl(&mut self, mod_name: Ident) { - self.module_decls.push(mod_name); + fn push_module_decl(&mut self, mod_decl: ModuleDeclaration) { + self.module_decls.push(mod_decl); } fn push_submodule(&mut self, submodule: SortedSubModule) { @@ -474,7 +474,7 @@ impl std::fmt::Display for TopLevelStatement { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { TopLevelStatement::Function(fun) => fun.fmt(f), - TopLevelStatement::Module(m) => write!(f, "mod {m}"), + TopLevelStatement::Module(m) => m.fmt(f), TopLevelStatement::Import(tree) => write!(f, "use {tree}"), TopLevelStatement::Trait(t) => t.fmt(f), TopLevelStatement::TraitImpl(i) => i.fmt(f), diff --git a/compiler/noirc_frontend/src/parser/parser.rs b/compiler/noirc_frontend/src/parser/parser.rs index 38146a67e7c..ddde3952868 100644 --- a/compiler/noirc_frontend/src/parser/parser.rs +++ b/compiler/noirc_frontend/src/parser/parser.rs @@ -32,21 +32,22 @@ use super::{ TopLevelStatement, }; use super::{spanned, Item, ItemKind}; +use crate::ast::{ + BinaryOp, BinaryOpKind, BlockExpression, ForLoopStatement, ForRange, Ident, IfExpression, + InfixExpression, LValue, Literal, ModuleDeclaration, NoirTypeAlias, Param, Path, Pattern, + Recoverable, Statement, TraitBound, TypeImpl, UnaryRhsMemberAccess, UnresolvedTraitConstraint, + UnresolvedTypeExpression, UseTree, UseTreeKind, Visibility, +}; use crate::ast::{ Expression, ExpressionKind, LetStatement, StatementKind, UnresolvedType, UnresolvedTypeData, }; -use crate::lexer::Lexer; +use crate::lexer::{lexer::from_spanned_token_result, Lexer}; use crate::parser::{force, ignore_then_commit, statement_recovery}; use crate::token::{Keyword, Token, TokenKind}; -use crate::{ - BinaryOp, BinaryOpKind, BlockExpression, Distinctness, ForLoopStatement, ForRange, - FunctionReturnType, Ident, IfExpression, InfixExpression, LValue, Literal, NoirTypeAlias, - Param, Path, Pattern, Recoverable, Statement, TraitBound, TypeImpl, UnresolvedTraitConstraint, - UnresolvedTypeExpression, UseTree, UseTreeKind, Visibility, -}; use chumsky::prelude::*; use iter_extended::vecmap; +use lalrpop_util::lalrpop_mod; use noirc_errors::{Span, Spanned}; mod assertion; @@ -59,6 +60,9 @@ mod primitives; mod structs; mod traits; +// synthesized by LALRPOP +lalrpop_mod!(pub noir_parser); + #[cfg(test)] mod test_helpers; @@ -77,8 +81,79 @@ pub fn parse_program(source_program: &str) -> (ParsedModule, Vec) { let (module, mut parsing_errors) = program().parse_recovery_verbose(tokens); parsing_errors.extend(lexing_errors.into_iter().map(Into::into)); + let parsed_module = module.unwrap_or(ParsedModule { items: vec![] }); + + if cfg!(feature = "experimental_parser") { + for parsed_item in &parsed_module.items { + if lalrpop_parser_supports_kind(&parsed_item.kind) { + match &parsed_item.kind { + ItemKind::Import(parsed_use_tree) => { + prototype_parse_use_tree(Some(parsed_use_tree), source_program); + } + // other kinds prevented by lalrpop_parser_supports_kind + _ => unreachable!(), + } + } + } + } + (parsed_module, parsing_errors) +} - (module.unwrap_or(ParsedModule { items: vec![] }), parsing_errors) +fn prototype_parse_use_tree(expected_use_tree_opt: Option<&UseTree>, input: &str) { + // TODO(https://github.com/noir-lang/noir/issues/4777): currently skipping + // recursive use trees, e.g. "use std::{foo, bar}" + if input.contains('{') { + return; + } + + let mut lexer = Lexer::new(input); + lexer = lexer.skip_whitespaces(false); + let mut errors = Vec::new(); + + // NOTE: this is a hack to get the references working + // => this likely means that we'll want to propagate the <'input> lifetime further into Token + let lexer_result = lexer.collect::>(); + let referenced_lexer_result = lexer_result.iter().map(from_spanned_token_result); + + let calculated = noir_parser::TopLevelStatementParser::new().parse( + input, + &mut errors, + referenced_lexer_result, + ); + + if let Some(expected_use_tree) = expected_use_tree_opt { + assert!( + calculated.is_ok(), + "calculated not Ok(_): {:?}\n\nlexer: {:?}\n\ninput: {:?}", + calculated, + lexer_result, + input + ); + + match calculated.unwrap() { + TopLevelStatement::Import(parsed_use_tree) => { + assert_eq!(expected_use_tree, &parsed_use_tree); + } + unexpected_calculated => { + panic!( + "expected a TopLevelStatement::Import, but found: {:?}", + unexpected_calculated + ) + } + } + } else { + assert!( + calculated.is_err(), + "calculated not Err(_): {:?}\n\nlexer: {:?}\n\ninput: {:?}", + calculated, + lexer_result, + input + ); + } +} + +fn lalrpop_parser_supports_kind(kind: &ItemKind) -> bool { + matches!(kind, ItemKind::Import(_)) } /// program: module EOF @@ -158,14 +233,30 @@ fn implementation() -> impl NoirParser { /// global_declaration: 'global' ident global_type_annotation '=' literal fn global_declaration() -> impl NoirParser { - let p = ignore_then_commit( - keyword(Keyword::Global).labelled(ParsingRuleLabel::Global), - ident().map(Pattern::Identifier), - ); + let p = attributes::attributes() + .then(maybe_comp_time()) + .then(spanned(keyword(Keyword::Mut)).or_not()) + .then_ignore(keyword(Keyword::Global).labelled(ParsingRuleLabel::Global)) + .then(ident().map(Pattern::Identifier)); + let p = then_commit(p, optional_type_annotation()); let p = then_commit_ignore(p, just(Token::Assign)); let p = then_commit(p, expression()); - p.map(LetStatement::new_let).map(TopLevelStatement::Global) + p.validate( + |(((((attributes, comptime), mutable), mut pattern), r#type), expression), span, emit| { + let global_attributes = + attributes::validate_secondary_attributes(attributes, span, emit); + + // Only comptime globals are allowed to be mutable, but we always parse the `mut` + // and throw the error in name resolution. + if let Some((_, mut_span)) = mutable { + let span = mut_span.merge(pattern.span()); + pattern = Pattern::Mutable(Box::new(pattern), span, false); + } + LetStatement { pattern, r#type, comptime, expression, attributes: global_attributes } + }, + ) + .map(TopLevelStatement::Global) } /// submodule: 'mod' ident '{' module '}' @@ -205,21 +296,6 @@ fn type_alias_definition() -> impl NoirParser { }) } -fn function_return_type() -> impl NoirParser<((Distinctness, Visibility), FunctionReturnType)> { - just(Token::Arrow) - .ignore_then(optional_distinctness()) - .then(optional_visibility()) - .then(spanned(parse_type())) - .or_not() - .map_with_span(|ret, span| match ret { - Some((head, (ty, _))) => (head, FunctionReturnType::Ty(ty)), - None => ( - (Distinctness::DuplicationAllowed, Visibility::Private), - FunctionReturnType::Default(span), - ), - }) -} - fn self_parameter() -> impl NoirParser { let mut_ref_pattern = just(Token::Ampersand).then_ignore(keyword(Keyword::Mut)); let mut_pattern = keyword(Keyword::Mut); @@ -354,7 +430,7 @@ fn block<'a>( |span| vec![Statement { kind: StatementKind::Error, span }], )), ) - .map(|(is_unsafe, statements)| BlockExpression { is_unsafe, statements }) + .map(|(is_unsafe, statements)|BlockExpression { is_unsafe, statements }) } fn check_statements_require_semicolon( @@ -377,7 +453,9 @@ fn optional_type_annotation<'a>() -> impl NoirParser + 'a { } fn module_declaration() -> impl NoirParser { - keyword(Keyword::Mod).ignore_then(ident()).map(TopLevelStatement::Module) + keyword(Keyword::Mod) + .ignore_then(ident()) + .map(|ident| TopLevelStatement::Module(ModuleDeclaration { ident })) } fn use_statement() -> impl NoirParser { @@ -425,8 +503,11 @@ where assertion::assertion_eq(expr_parser.clone()), declaration(expr_parser.clone()), assignment(expr_parser.clone()), - for_loop(expr_no_constructors, statement), + for_loop(expr_no_constructors.clone(), statement.clone()), + break_statement(), + continue_statement(), return_statement(expr_parser.clone()), + comptime_statement(expr_parser.clone(), expr_no_constructors, statement), expr_parser.map(StatementKind::Expression), )) }) @@ -436,6 +517,44 @@ fn fresh_statement() -> impl NoirParser { statement(expression(), expression_no_constructors(expression())) } +fn break_statement() -> impl NoirParser { + keyword(Keyword::Break).to(StatementKind::Break) +} + +fn continue_statement() -> impl NoirParser { + keyword(Keyword::Continue).to(StatementKind::Continue) +} + +fn comptime_statement<'a, P1, P2, S>( + expr: P1, + expr_no_constructors: P2, + statement: S, +) -> impl NoirParser + 'a +where + P1: ExprParser + 'a, + P2: ExprParser + 'a, + S: NoirParser + 'a, +{ + let comptime_statement = choice(( + declaration(expr), + for_loop(expr_no_constructors, statement.clone()), + block(statement).map_with_span(|block, span| { + StatementKind::Expression(Expression::new(ExpressionKind::Block(block), span)) + }), + )) + .map_with_span(|kind, span| Box::new(Statement { kind, span })); + + keyword(Keyword::Comptime).ignore_then(comptime_statement).map(StatementKind::Comptime) +} + +/// Comptime in an expression position only accepts entire blocks +fn comptime_expr<'a, S>(statement: S) -> impl NoirParser + 'a +where + S: NoirParser + 'a, +{ + keyword(Keyword::Comptime).ignore_then(block(statement)).map(ExpressionKind::Comptime) +} + fn declaration<'a, P>(expr_parser: P) -> impl NoirParser + 'a where P: ExprParser + 'a, @@ -521,8 +640,8 @@ fn assign_operator() -> impl NoirParser { } enum LValueRhs { - MemberAccess(Ident), - Index(Expression), + MemberAccess(Ident, Span), + Index(Expression, Span), } fn lvalue<'a, P>(expr_parser: P) -> impl NoirParser + 'a @@ -534,23 +653,28 @@ where let dereferences = just(Token::Star) .ignore_then(lvalue.clone()) - .map(|lvalue| LValue::Dereference(Box::new(lvalue))); + .map_with_span(|lvalue, span| LValue::Dereference(Box::new(lvalue), span)); let parenthesized = lvalue.delimited_by(just(Token::LeftParen), just(Token::RightParen)); let term = choice((parenthesized, dereferences, l_ident)); - let l_member_rhs = just(Token::Dot).ignore_then(field_name()).map(LValueRhs::MemberAccess); + let l_member_rhs = + just(Token::Dot).ignore_then(field_name()).map_with_span(LValueRhs::MemberAccess); let l_index = expr_parser .delimited_by(just(Token::LeftBracket), just(Token::RightBracket)) - .map(LValueRhs::Index); + .map_with_span(LValueRhs::Index); term.then(l_member_rhs.or(l_index).repeated()).foldl(|lvalue, rhs| match rhs { - LValueRhs::MemberAccess(field_name) => { - LValue::MemberAccess { object: Box::new(lvalue), field_name } + LValueRhs::MemberAccess(field_name, span) => { + let span = lvalue.span().merge(span); + LValue::MemberAccess { object: Box::new(lvalue), field_name, span } + } + LValueRhs::Index(index, span) => { + let span = lvalue.span().merge(span); + LValue::Index { array: Box::new(lvalue), index, span } } - LValueRhs::Index(index) => LValue::Index { array: Box::new(lvalue), index }, }) }) } @@ -559,9 +683,9 @@ fn parse_type<'a>() -> impl NoirParser + 'a { recursive(parse_type_inner) } -fn parse_type_inner( - recursive_type_parser: impl NoirParser, -) -> impl NoirParser { +fn parse_type_inner<'a>( + recursive_type_parser: impl NoirParser + 'a, +) -> impl NoirParser + 'a { choice(( field_type(), int_type(), @@ -570,6 +694,7 @@ fn parse_type_inner( format_string_type(recursive_type_parser.clone()), named_type(recursive_type_parser.clone()), named_trait(recursive_type_parser.clone()), + slice_type(recursive_type_parser.clone()), array_type(recursive_type_parser.clone()), parenthesized_type(recursive_type_parser.clone()), tuple_type(recursive_type_parser.clone()), @@ -604,44 +729,36 @@ fn optional_visibility() -> impl NoirParser { }) } -fn optional_distinctness() -> impl NoirParser { - keyword(Keyword::Distinct).or_not().map(|opt| match opt { - Some(_) => Distinctness::Distinct, - None => Distinctness::DuplicationAllowed, - }) -} - -fn maybe_comp_time() -> impl NoirParser<()> { - keyword(Keyword::CompTime).or_not().validate(|opt, span, emit| { +fn maybe_comp_time() -> impl NoirParser { + keyword(Keyword::Comptime).or_not().validate(|opt, span, emit| { if opt.is_some() { - emit(ParserError::with_reason(ParserErrorReason::ComptimeDeprecated, span)); + emit(ParserError::with_reason( + ParserErrorReason::ExperimentalFeature("Comptime values"), + span, + )); } + opt.is_some() }) } fn field_type() -> impl NoirParser { - maybe_comp_time() - .then_ignore(keyword(Keyword::Field)) + keyword(Keyword::Field) .map_with_span(|_, span| UnresolvedTypeData::FieldElement.with_span(span)) } fn bool_type() -> impl NoirParser { - maybe_comp_time() - .then_ignore(keyword(Keyword::Bool)) - .map_with_span(|_, span| UnresolvedTypeData::Bool.with_span(span)) + keyword(Keyword::Bool).map_with_span(|_, span| UnresolvedTypeData::Bool.with_span(span)) } fn string_type() -> impl NoirParser { keyword(Keyword::String) - .ignore_then( - type_expression().delimited_by(just(Token::Less), just(Token::Greater)).or_not(), - ) + .ignore_then(type_expression().delimited_by(just(Token::Less), just(Token::Greater))) .map_with_span(|expr, span| UnresolvedTypeData::String(expr).with_span(span)) } -fn format_string_type( - type_parser: impl NoirParser, -) -> impl NoirParser { +fn format_string_type<'a>( + type_parser: impl NoirParser + 'a, +) -> impl NoirParser + 'a { keyword(Keyword::FormatString) .ignore_then( type_expression() @@ -655,39 +772,43 @@ fn format_string_type( } fn int_type() -> impl NoirParser { - maybe_comp_time() - .then(filter_map(|span, token: Token| match token { - Token::IntType(int_type) => Ok(int_type), - unexpected => { - Err(ParserError::expected_label(ParsingRuleLabel::IntegerType, unexpected, span)) - } - })) - .validate(|(_, token), span, emit| { - UnresolvedTypeData::from_int_token(token) - .map(|data| data.with_span(span)) - .unwrap_or_else(|err| { - emit(ParserError::with_reason(ParserErrorReason::InvalidBitSize(err.0), span)); - UnresolvedType::error(span) - }) - }) + filter_map(|span, token: Token| match token { + Token::IntType(int_type) => Ok(int_type), + unexpected => { + Err(ParserError::expected_label(ParsingRuleLabel::IntegerType, unexpected, span)) + } + }) + .validate(|token, span, emit| { + UnresolvedTypeData::from_int_token(token).map(|data| data.with_span(span)).unwrap_or_else( + |err| { + emit(ParserError::with_reason(ParserErrorReason::InvalidBitSize(err.0), span)); + UnresolvedType::error(span) + }, + ) + }) } -fn named_type(type_parser: impl NoirParser) -> impl NoirParser { +fn named_type<'a>( + type_parser: impl NoirParser + 'a, +) -> impl NoirParser + 'a { path().then(generic_type_args(type_parser)).map_with_span(|(path, args), span| { UnresolvedTypeData::Named(path, args, false).with_span(span) }) } -fn named_trait(type_parser: impl NoirParser) -> impl NoirParser { +fn named_trait<'a>( + type_parser: impl NoirParser + 'a, +) -> impl NoirParser + 'a { keyword(Keyword::Impl).ignore_then(path()).then(generic_type_args(type_parser)).map_with_span( |(path, args), span| UnresolvedTypeData::TraitAsType(path, args).with_span(span), ) } -fn generic_type_args( - type_parser: impl NoirParser, -) -> impl NoirParser> { +fn generic_type_args<'a>( + type_parser: impl NoirParser + 'a, +) -> impl NoirParser> + 'a { type_parser + .clone() // Without checking for a terminating ',' or '>' here we may incorrectly // parse a generic `N * 2` as just the type `N` then fail when there is no // separator afterward. Failing early here ensures we try the `type_expression` @@ -703,16 +824,27 @@ fn generic_type_args( .map(Option::unwrap_or_default) } -fn array_type(type_parser: impl NoirParser) -> impl NoirParser { +fn array_type<'a>( + type_parser: impl NoirParser + 'a, +) -> impl NoirParser + 'a { just(Token::LeftBracket) .ignore_then(type_parser) - .then(just(Token::Semicolon).ignore_then(type_expression()).or_not()) + .then(just(Token::Semicolon).ignore_then(type_expression())) .then_ignore(just(Token::RightBracket)) .map_with_span(|(element_type, size), span| { UnresolvedTypeData::Array(size, Box::new(element_type)).with_span(span) }) } +fn slice_type(type_parser: impl NoirParser) -> impl NoirParser { + just(Token::LeftBracket) + .ignore_then(type_parser) + .then_ignore(just(Token::RightBracket)) + .map_with_span(|element_type, span| { + UnresolvedTypeData::Slice(Box::new(element_type)).with_span(span) + }) +} + fn type_expression() -> impl NoirParser { recursive(|expr| { expression_with_precedence( @@ -917,6 +1049,7 @@ where expr_no_constructors, statement, allow_constructors, + parse_type(), )) }) } @@ -937,6 +1070,7 @@ fn atom_or_right_unary<'a, P, P2, S>( expr_no_constructors: P2, statement: S, allow_constructors: bool, + type_parser: impl NoirParser + 'a, ) -> impl NoirParser + 'a where P: ExprParser + 'a, @@ -947,7 +1081,7 @@ where Call(Vec), ArrayIndex(Expression), Cast(UnresolvedType), - MemberAccess((Ident, Option>)), + MemberAccess(UnaryRhsMemberAccess), } // `(arg1, ..., argN)` in `my_func(arg1, ..., argN)` @@ -961,14 +1095,17 @@ where // `as Type` in `atom as Type` let cast_rhs = keyword(Keyword::As) - .ignore_then(parse_type()) + .ignore_then(type_parser.clone()) .map(UnaryRhs::Cast) .labelled(ParsingRuleLabel::Cast); + // A turbofish operator is optional in a method call to specify generic types + let turbofish = primitives::turbofish(type_parser); + // `.foo` or `.foo(args)` in `atom.foo` or `atom.foo(args)` let member_rhs = just(Token::Dot) .ignore_then(field_name()) - .then(parenthesized(expression_list(expr_parser.clone())).or_not()) + .then(turbofish.then(parenthesized(expression_list(expr_parser.clone()))).or_not()) .map(UnaryRhs::MemberAccess) .labelled(ParsingRuleLabel::FieldAccess); @@ -1077,6 +1214,36 @@ where .map(|(lhs, count)| ExpressionKind::repeated_array(lhs, count)) } +fn slice_expr

(expr_parser: P) -> impl NoirParser +where + P: ExprParser, +{ + just(Token::Ampersand) + .ignore_then(standard_slice(expr_parser.clone()).or(slice_sugar(expr_parser))) +} + +/// &[a, b, c, ...] +fn standard_slice

(expr_parser: P) -> impl NoirParser +where + P: ExprParser, +{ + expression_list(expr_parser) + .delimited_by(just(Token::LeftBracket), just(Token::RightBracket)) + .validate(|elements, _span, _emit| ExpressionKind::slice(elements)) +} + +/// &[a; N] +fn slice_sugar

(expr_parser: P) -> impl NoirParser +where + P: ExprParser, +{ + expr_parser + .clone() + .then(just(Token::Semicolon).ignore_then(expr_parser)) + .delimited_by(just(Token::LeftBracket), just(Token::RightBracket)) + .map(|(lhs, count)| ExpressionKind::repeated_slice(lhs, count)) +} + fn expression_list

(expr_parser: P) -> impl NoirParser> where P: ExprParser, @@ -1100,6 +1267,7 @@ where { choice(( if_expr(expr_no_constructors, statement.clone()), + slice_expr(expr_parser.clone()), array_expr(expr_parser.clone()), if allow_constructors { constructor(expr_parser.clone()).boxed() @@ -1107,7 +1275,9 @@ where nothing().boxed() }, lambdas::lambda(expr_parser.clone()), - block(statement).map(ExpressionKind::Block), + block(statement.clone()).map(ExpressionKind::Block), + comptime_expr(statement.clone()), + quote(statement), variable(), literal(), )) @@ -1125,13 +1295,26 @@ fn type_expression_atom<'a, P>(expr_parser: P) -> impl NoirParser + where P: ExprParser + 'a, { - variable() + primitives::variable_no_turbofish() .or(literal()) .map_with_span(Expression::new) .or(parenthesized(expr_parser)) .labelled(ParsingRuleLabel::Atom) } +fn quote<'a, P>(statement: P) -> impl NoirParser + 'a +where + P: NoirParser + 'a, +{ + keyword(Keyword::Quote).ignore_then(block(statement)).validate(|block, span, emit| { + emit(ParserError::with_reason( + ParserErrorReason::ExperimentalFeature("quoted expressions"), + span, + )); + ExpressionKind::Quote(block) + }) +} + fn tuple

(expr_parser: P) -> impl NoirParser where P: ExprParser, @@ -1178,7 +1361,7 @@ where mod test { use super::test_helpers::*; use super::*; - use crate::{ArrayLiteral, Literal}; + use crate::ast::ArrayLiteral; #[test] fn parse_infix() { @@ -1202,22 +1385,19 @@ mod test { #[test] fn parse_cast() { + let expression_nc = expression_no_constructors(expression()); parse_all( atom_or_right_unary( expression(), expression_no_constructors(expression()), fresh_statement(), true, + parse_type(), ), - vec!["x as u8", "0 as Field", "(x + 3) as [Field; 8]"], + vec!["x as u8", "x as u16", "0 as Field", "(x + 3) as [Field; 8]"], ); parse_all_failing( - atom_or_right_unary( - expression(), - expression_no_constructors(expression()), - fresh_statement(), - true, - ), + atom_or_right_unary(expression(), expression_nc, fresh_statement(), true, parse_type()), vec!["x as pub u8"], ); } @@ -1237,6 +1417,7 @@ mod test { expression_no_constructors(expression()), fresh_statement(), true, + parse_type(), ), valid, ); @@ -1291,6 +1472,50 @@ mod test { parse_all_failing(array_expr(expression()), invalid); } + fn expr_to_slice(expr: ExpressionKind) -> ArrayLiteral { + let lit = match expr { + ExpressionKind::Literal(literal) => literal, + _ => unreachable!("expected a literal"), + }; + + match lit { + Literal::Slice(arr) => arr, + _ => unreachable!("expected a slice: {:?}", lit), + } + } + + #[test] + fn parse_slice() { + let valid = vec![ + "&[0, 1, 2,3, 4]", + "&[0,1,2,3,4,]", // Trailing commas are valid syntax + "&[0;5]", + ]; + + for expr in parse_all(slice_expr(expression()), valid) { + match expr_to_slice(expr) { + ArrayLiteral::Standard(elements) => assert_eq!(elements.len(), 5), + ArrayLiteral::Repeated { length, .. } => { + assert_eq!(length.kind, ExpressionKind::integer(5i128.into())); + } + } + } + + parse_all_failing( + slice_expr(expression()), + vec!["0,1,2,3,4]", "&[[0,1,2,3,4]", "&[0,1,2,,]", "&[0,1,2,3,4"], + ); + } + + #[test] + fn parse_slice_sugar() { + let valid = vec!["&[0;7]", "&[(1, 2); 4]", "&[0;Four]", "&[2;1+3-a]"]; + parse_all(slice_expr(expression()), valid); + + let invalid = vec!["&[0;;4]", "&[1, 2; 3]"]; + parse_all_failing(slice_expr(expression()), invalid); + } + #[test] fn parse_block() { parse_with(block(fresh_statement()), "{ [0,1,2,3,4] }").unwrap(); @@ -1337,7 +1562,10 @@ mod test { // Let statements are not type checked here, so the parser will accept as // long as it is a type. Other statements such as Public are type checked // Because for now, they can only have one type - parse_all(declaration(expression()), vec!["let _ = 42", "let x = y", "let x : u8 = y"]); + parse_all( + declaration(expression()), + vec!["let _ = 42", "let x = y", "let x : u8 = y", "let x: u16 = y"], + ); } #[test] @@ -1401,33 +1629,53 @@ mod test { #[test] fn parse_use() { - parse_all( - use_statement(), - vec![ - "use std::hash", - "use std", - "use foo::bar as hello", - "use bar as bar", - "use foo::{}", - "use foo::{bar,}", - "use foo::{bar, hello}", - "use foo::{bar as bar2, hello}", - "use foo::{bar as bar2, hello::{foo}, nested::{foo, bar}}", - "use dep::{std::println, bar::baz}", - ], - ); + let valid_use_statements = [ + "use std::hash", + "use std", + "use foo::bar as hello", + "use bar as bar", + "use foo::{}", + "use foo::{bar,}", + "use foo::{bar, hello}", + "use foo::{bar as bar2, hello}", + "use foo::{bar as bar2, hello::{foo}, nested::{foo, bar}}", + "use dep::{std::println, bar::baz}", + ]; - parse_all_failing( - use_statement(), - vec![ - "use std as ;", - "use foobar as as;", - "use hello:: as foo;", - "use foo bar::baz", - "use foo bar::{baz}", - "use foo::{,}", - ], - ); + let invalid_use_statements = [ + "use std as ;", + "use foobar as as;", + "use hello:: as foo;", + "use foo bar::baz", + "use foo bar::{baz}", + "use foo::{,}", + ]; + + let use_statements = valid_use_statements + .into_iter() + .map(|valid_str| (valid_str, true)) + .chain(invalid_use_statements.into_iter().map(|invalid_str| (invalid_str, false))); + + for (use_statement_str, expect_valid) in use_statements { + let mut use_statement_str = use_statement_str.to_string(); + let expected_use_statement = if expect_valid { + let (result_opt, _diagnostics) = + parse_recover(&use_statement(), &use_statement_str); + use_statement_str.push(';'); + match result_opt.unwrap() { + TopLevelStatement::Import(expected_use_statement) => { + Some(expected_use_statement) + } + _ => unreachable!(), + } + } else { + let result = parse_with(&use_statement(), &use_statement_str); + assert!(result.is_err()); + None + }; + + prototype_parse_use_tree(expected_use_statement.as_ref(), &use_statement_str); + } } #[test] diff --git a/compiler/noirc_frontend/src/parser/parser/assertion.rs b/compiler/noirc_frontend/src/parser/parser/assertion.rs index f9c8d7aa46b..ed08a4c9922 100644 --- a/compiler/noirc_frontend/src/parser/parser/assertion.rs +++ b/compiler/noirc_frontend/src/parser/parser/assertion.rs @@ -4,8 +4,8 @@ use crate::parser::{ ParserError, ParserErrorReason, }; +use crate::ast::{BinaryOpKind, ConstrainKind, ConstrainStatement, InfixExpression, Recoverable}; use crate::token::{Keyword, Token}; -use crate::{BinaryOpKind, ConstrainKind, ConstrainStatement, InfixExpression, Recoverable}; use chumsky::prelude::*; use noirc_errors::Spanned; @@ -74,11 +74,11 @@ where mod test { use super::*; use crate::{ + ast::Literal, parser::parser::{ expression, test_helpers::{parse_all, parse_all_failing, parse_with}, }, - Literal, }; /// Deprecated constrain usage test diff --git a/compiler/noirc_frontend/src/parser/parser/attributes.rs b/compiler/noirc_frontend/src/parser/parser/attributes.rs index 4b256a95c8b..47add6f82e0 100644 --- a/compiler/noirc_frontend/src/parser/parser/attributes.rs +++ b/compiler/noirc_frontend/src/parser/parser/attributes.rs @@ -2,6 +2,7 @@ use chumsky::Parser; use noirc_errors::Span; use crate::{ + macros_api::SecondaryAttribute, parser::{NoirParser, ParserError, ParserErrorReason}, token::{Attribute, Attributes, Token, TokenKind}, }; @@ -44,3 +45,25 @@ pub(super) fn validate_attributes( Attributes { function: primary, secondary } } + +pub(super) fn validate_secondary_attributes( + attributes: Vec, + span: Span, + emit: &mut dyn FnMut(ParserError), +) -> Vec { + let mut struct_attributes = vec![]; + + for attribute in attributes { + match attribute { + Attribute::Function(..) => { + emit(ParserError::with_reason( + ParserErrorReason::NoFunctionAttributesAllowedOnStruct, + span, + )); + } + Attribute::Secondary(attr) => struct_attributes.push(attr), + } + } + + struct_attributes +} diff --git a/compiler/noirc_frontend/src/parser/parser/function.rs b/compiler/noirc_frontend/src/parser/parser/function.rs index 0d34c719061..40180a9f9ac 100644 --- a/compiler/noirc_frontend/src/parser/parser/function.rs +++ b/compiler/noirc_frontend/src/parser/parser/function.rs @@ -1,6 +1,6 @@ use super::{ attributes::{attributes, validate_attributes}, - block, fresh_statement, ident, keyword, nothing, optional_distinctness, optional_visibility, + block, fresh_statement, ident, keyword, maybe_comp_time, nothing, optional_visibility, parameter_name_recovery, parameter_recovery, parenthesized, parse_type, pattern, self_parameter, where_clause, NoirParser, }; @@ -8,8 +8,11 @@ use crate::parser::labels::ParsingRuleLabel; use crate::parser::spanned; use crate::token::{Keyword, Token}; use crate::{ - Distinctness, FunctionDefinition, FunctionReturnType, FunctionVisibility, Ident, NoirFunction, - Param, Visibility, + ast::{ + FunctionDefinition, FunctionReturnType, Ident, ItemVisibility, NoirFunction, Param, + Visibility, + }, + parser::{ParserError, ParserErrorReason}, }; use chumsky::prelude::*; @@ -36,57 +39,47 @@ pub(super) fn function_definition(allow_self: bool) -> impl NoirParser impl NoirParser { + let is_pub_crate = (keyword(Keyword::Pub) + .then_ignore(just(Token::LeftParen)) + .then_ignore(keyword(Keyword::Crate)) + .then_ignore(just(Token::RightParen))) + .map(|_| ItemVisibility::PublicCrate); + + let is_pub = keyword(Keyword::Pub).map(|_| ItemVisibility::Public); + + let is_private = empty().map(|_| ItemVisibility::Private); + + choice((is_pub_crate, is_pub, is_private)) +} + +/// function_modifiers: 'unconstrained'? (visibility)? /// -/// returns (is_unconstrained, is_pub_crate, is_open, is_internal, is_pub) for whether each keyword was present -fn function_modifiers() -> impl NoirParser<(bool, bool, bool, bool, bool)> { +/// returns (is_unconstrained, visibility) for whether each keyword was present +fn function_modifiers() -> impl NoirParser<(bool, ItemVisibility, bool)> { keyword(Keyword::Unconstrained) .or_not() - .then(is_pub_crate()) - .then(keyword(Keyword::Pub).or_not()) - .then(keyword(Keyword::Open).or_not()) - .then(keyword(Keyword::Internal).or_not()) - .map(|((((unconstrained, pub_crate), public), open), internal)| { - ( - unconstrained.is_some(), - pub_crate, - open.is_some(), - internal.is_some(), - public.is_some(), - ) + .then(visibility_modifier()) + .then(maybe_comp_time()) + .map(|((unconstrained, visibility), comptime)| { + (unconstrained.is_some(), visibility, comptime) }) } -fn is_pub_crate() -> impl NoirParser { - (keyword(Keyword::Pub) - .then_ignore(just(Token::LeftParen)) - .then_ignore(keyword(Keyword::Crate)) - .then_ignore(just(Token::RightParen))) - .or_not() - .map(|a| a.is_some()) -} - /// non_empty_ident_list: ident ',' non_empty_ident_list /// | ident /// @@ -102,18 +95,26 @@ pub(super) fn generics() -> impl NoirParser> { .map(|opt| opt.unwrap_or_default()) } -fn function_return_type() -> impl NoirParser<((Distinctness, Visibility), FunctionReturnType)> { +#[deprecated = "Distinct keyword is now deprecated. Remove this function after the 0.30.0 release"] +fn optional_distinctness() -> impl NoirParser { + keyword(Keyword::Distinct).or_not().validate(|opt, span, emit| { + if opt.is_some() { + emit(ParserError::with_reason(ParserErrorReason::DistinctDeprecated, span)); + } + opt.is_some() + }) +} + +pub(super) fn function_return_type() -> impl NoirParser<(Visibility, FunctionReturnType)> { + #[allow(deprecated)] just(Token::Arrow) .ignore_then(optional_distinctness()) - .then(optional_visibility()) + .ignore_then(optional_visibility()) .then(spanned(parse_type())) .or_not() .map_with_span(|ret, span| match ret { - Some((head, (ty, _))) => (head, FunctionReturnType::Ty(ty)), - None => ( - (Distinctness::DuplicationAllowed, Visibility::Private), - FunctionReturnType::Default(span), - ), + Some((visibility, (ty, _))) => (visibility, FunctionReturnType::Ty(ty)), + None => (Visibility::Private, FunctionReturnType::Default(span)), }) } @@ -183,9 +184,9 @@ mod test { "fn f(f: pub Field, y : Field, z : Field) -> u8 { x + a }", "fn f(f: pub Field, y : T, z : Field) -> u8 { x + a }", "fn func_name(x: [Field], y : [Field;2],y : pub [Field;2], z : pub [u8;5]) {}", - "fn main(x: pub u8, y: pub u8) -> distinct pub [u8; 2] { [x, y] }", - "fn f(f: pub Field, y : Field, z : comptime Field) -> u8 { x + a }", - "fn f(f: pub Field, y : T, z : comptime Field) -> u8 { x + a }", + "fn main(x: pub u8, y: pub u8) -> pub [u8; 2] { [x, y] }", + "fn f(f: pub Field, y : Field, z : Field) -> u8 { x + a }", + "fn f(f: pub Field, y : T, z : Field) -> u8 { x + a }", "fn func_name(f: Field, y : T) where T: SomeTrait {}", "fn func_name(f: Field, y : T) where T: SomeTrait + SomeTrait2 {}", "fn func_name(f: Field, y : T) where T: SomeTrait, T: SomeTrait2 {}", @@ -202,6 +203,11 @@ mod test { "fn func_name(f: Field, y : T) where T: SomeTrait + {}", // The following should produce compile error on later stage. From the parser's perspective it's fine "fn func_name(f: Field, y : Field, z : Field) where T: SomeTrait {}", + // TODO: this fails with known EOF != EOF error + // https://github.com/noir-lang/noir/issues/4763 + // fn func_name(x: impl Eq) {} with error Expected an end of input but found end of input + // "fn func_name(x: impl Eq) {}", + "fn func_name(x: impl Eq, y : T) where T: SomeTrait + Eq {}", ], ); @@ -218,6 +224,8 @@ mod test { // 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 + {}", + // `distinct` is deprecated + "fn main(x: pub u8, y: pub u8) -> distinct pub [u8; 2] { [x, y] }", ], ); } diff --git a/compiler/noirc_frontend/src/parser/parser/lambdas.rs b/compiler/noirc_frontend/src/parser/parser/lambdas.rs index 48ddd41ab44..2b4a1d547c0 100644 --- a/compiler/noirc_frontend/src/parser/parser/lambdas.rs +++ b/compiler/noirc_frontend/src/parser/parser/lambdas.rs @@ -1,13 +1,12 @@ use chumsky::{primitive::just, Parser}; +use super::{parse_type, pattern}; +use crate::ast::{Expression, ExpressionKind, Lambda, Pattern, UnresolvedType}; use crate::{ parser::{labels::ParsingRuleLabel, parameter_name_recovery, parameter_recovery, NoirParser}, token::Token, - Expression, ExpressionKind, Lambda, Pattern, UnresolvedType, }; -use super::{parse_type, pattern}; - pub(super) fn lambda<'a>( expr_parser: impl NoirParser + 'a, ) -> impl NoirParser + 'a { diff --git a/compiler/noirc_frontend/src/parser/parser/literals.rs b/compiler/noirc_frontend/src/parser/parser/literals.rs index 32f4f03de2e..584224fda46 100644 --- a/compiler/noirc_frontend/src/parser/parser/literals.rs +++ b/compiler/noirc_frontend/src/parser/parser/literals.rs @@ -1,9 +1,9 @@ use chumsky::Parser; use crate::{ + ast::ExpressionKind, parser::NoirParser, token::{Token, TokenKind}, - ExpressionKind, }; use super::primitives::token_kind; @@ -22,10 +22,10 @@ pub(super) fn literal() -> impl NoirParser { #[cfg(test)] mod test { use super::*; + use crate::ast::Literal; use crate::parser::parser::{ expression, expression_no_constructors, fresh_statement, term, test_helpers::*, }; - use crate::Literal; fn expr_to_lit(expr: ExpressionKind) -> Literal { match expr { @@ -105,6 +105,7 @@ mod test { Case { source: r#" r#"foo" "#, expect: "(none)", errors: 2 }, // empty string Case { source: r#"r"""#, expect: r#"r"""#, errors: 0 }, + #[allow(clippy::needless_raw_string_hashes)] Case { source: r####"r###""###"####, expect: r####"r###""###"####, errors: 0 }, // miscellaneous Case { source: r##" r#\"foo\"# "##, expect: "plain::r", errors: 2 }, diff --git a/compiler/noirc_frontend/src/parser/parser/path.rs b/compiler/noirc_frontend/src/parser/parser/path.rs index ab812c07dce..47bb11991fa 100644 --- a/compiler/noirc_frontend/src/parser/parser/path.rs +++ b/compiler/noirc_frontend/src/parser/parser/path.rs @@ -1,5 +1,5 @@ +use crate::ast::{Path, PathKind}; use crate::parser::NoirParser; -use crate::{Path, PathKind}; use crate::token::{Keyword, Token}; diff --git a/compiler/noirc_frontend/src/parser/parser/primitives.rs b/compiler/noirc_frontend/src/parser/parser/primitives.rs index 34927278038..9da19c0a185 100644 --- a/compiler/noirc_frontend/src/parser/parser/primitives.rs +++ b/compiler/noirc_frontend/src/parser/parser/primitives.rs @@ -1,9 +1,10 @@ use chumsky::prelude::*; +use crate::ast::{ExpressionKind, Ident, UnaryOp}; +use crate::macros_api::UnresolvedType; use crate::{ parser::{labels::ParsingRuleLabel, ExprParser, NoirParser, ParserError}, token::{Keyword, Token, TokenKind}, - ExpressionKind, Ident, UnaryOp, }; use super::path; @@ -77,8 +78,20 @@ where .map(|rhs| ExpressionKind::prefix(UnaryOp::Dereference { implicitly_added: false }, rhs)) } +pub(super) fn turbofish<'a>( + type_parser: impl NoirParser + 'a, +) -> impl NoirParser>> + 'a { + just(Token::DoubleColon).ignore_then(super::generic_type_args(type_parser)).or_not() +} + pub(super) fn variable() -> impl NoirParser { - path().map(ExpressionKind::Variable) + path() + .then(turbofish(super::parse_type())) + .map(|(path, generics)| ExpressionKind::Variable(path, generics)) +} + +pub(super) fn variable_no_turbofish() -> impl NoirParser { + path().map(|path| ExpressionKind::Variable(path, None)) } #[cfg(test)] diff --git a/compiler/noirc_frontend/src/parser/parser/structs.rs b/compiler/noirc_frontend/src/parser/parser/structs.rs index 0212f56783f..7da956bdfea 100644 --- a/compiler/noirc_frontend/src/parser/parser/structs.rs +++ b/compiler/noirc_frontend/src/parser/parser/structs.rs @@ -1,18 +1,16 @@ use chumsky::prelude::*; -use noirc_errors::Span; +use crate::ast::{Ident, NoirStruct, UnresolvedType}; use crate::{ - macros_api::SecondaryAttribute, parser::{ parser::{ - attributes::attributes, + attributes::{attributes, validate_secondary_attributes}, function, parse_type, primitives::{ident, keyword}, }, - NoirParser, ParserError, ParserErrorReason, TopLevelStatement, + NoirParser, TopLevelStatement, }, - token::{Attribute, Keyword, Token}, - Ident, NoirStruct, UnresolvedType, + token::{Keyword, Token}, }; pub(super) fn struct_definition() -> impl NoirParser { @@ -35,7 +33,7 @@ pub(super) fn struct_definition() -> impl NoirParser { .then(function::generics()) .then(fields) .validate(|(((raw_attributes, name), generics), fields), span, emit| { - let attributes = validate_struct_attributes(raw_attributes, span, emit); + let attributes = validate_secondary_attributes(raw_attributes, span, emit); TopLevelStatement::Struct(NoirStruct { name, attributes, generics, fields, span }) }) } @@ -48,28 +46,6 @@ fn struct_fields() -> impl NoirParser> { .allow_trailing() } -fn validate_struct_attributes( - attributes: Vec, - span: Span, - emit: &mut dyn FnMut(ParserError), -) -> Vec { - let mut struct_attributes = vec![]; - - for attribute in attributes { - match attribute { - Attribute::Function(..) => { - emit(ParserError::with_reason( - ParserErrorReason::NoFunctionAttributesAllowedOnStruct, - span, - )); - } - Attribute::Secondary(attr) => struct_attributes.push(attr), - } - } - - struct_attributes -} - #[cfg(test)] mod test { use super::*; diff --git a/compiler/noirc_frontend/src/parser/parser/test_helpers.rs b/compiler/noirc_frontend/src/parser/parser/test_helpers.rs index 6b8cb80a0a0..83c1e148f0e 100644 --- a/compiler/noirc_frontend/src/parser/parser/test_helpers.rs +++ b/compiler/noirc_frontend/src/parser/parser/test_helpers.rs @@ -15,9 +15,9 @@ where { let (tokens, lexer_errors) = Lexer::lex(program); if !lexer_errors.is_empty() { - return Err(vecmap(lexer_errors, Into::into)); + return Err(vecmap(&lexer_errors, Into::into)); } - parser.then_ignore(just(Token::EOF)).parse(tokens).map_err(|errors| vecmap(errors, Into::into)) + parser.then_ignore(just(Token::EOF)).parse(tokens).map_err(|errors| vecmap(&errors, Into::into)) } pub(crate) fn parse_recover(parser: P, program: &str) -> (Option, Vec) @@ -27,8 +27,8 @@ where let (tokens, lexer_errors) = Lexer::lex(program); let (opt, errs) = parser.then_ignore(force(just(Token::EOF))).parse_recovery(tokens); - let mut errors = vecmap(lexer_errors, Into::into); - errors.extend(errs.into_iter().map(Into::into)); + let mut errors = vecmap(&lexer_errors, Into::into); + errors.extend(errs.iter().map(Into::into)); (opt, errors) } diff --git a/compiler/noirc_frontend/src/parser/parser/traits.rs b/compiler/noirc_frontend/src/parser/parser/traits.rs index 0d72fbd5303..1aec57c8e41 100644 --- a/compiler/noirc_frontend/src/parser/parser/traits.rs +++ b/compiler/noirc_frontend/src/parser/parser/traits.rs @@ -1,18 +1,18 @@ use chumsky::prelude::*; -use super::{ - block, expression, fresh_statement, function, function_declaration_parameters, - function_return_type, -}; +use super::function::function_return_type; +use super::{block, expression, fresh_statement, function, function_declaration_parameters}; +use crate::ast::{ + Expression, ItemVisibility, NoirTrait, NoirTraitImpl, TraitBound, TraitImplItem, TraitItem, + UnresolvedTraitConstraint, UnresolvedType, +}; use crate::{ parser::{ ignore_then_commit, parenthesized, parser::primitives::keyword, NoirParser, ParserError, ParserErrorReason, TopLevelStatement, }, token::{Keyword, Token}, - Expression, FunctionVisibility, NoirTrait, NoirTraitImpl, TraitBound, TraitImplItem, TraitItem, - UnresolvedTraitConstraint, UnresolvedType, }; use super::{generic_type_args, parse_type, path, primitives::ident}; @@ -120,15 +120,11 @@ pub(super) fn trait_implementation() -> impl NoirParser { fn trait_implementation_body() -> impl NoirParser> { let function = function::function_definition(true).validate(|mut f, span, emit| { - if f.def().is_internal - || f.def().is_unconstrained - || f.def().is_open - || f.def().visibility != FunctionVisibility::Private - { + if f.def().is_unconstrained || f.def().visibility != ItemVisibility::Private { emit(ParserError::with_reason(ParserErrorReason::TraitImplFunctionModifiers, span)); } // Trait impl functions are always public - f.def_mut().visibility = FunctionVisibility::Public; + f.def_mut().visibility = ItemVisibility::Public; TraitImplItem::Function(f) }); diff --git a/compiler/noirc_frontend/src/parser/parser/types.rs b/compiler/noirc_frontend/src/parser/parser/types.rs index 572397d6527..82dd3dad681 100644 --- a/compiler/noirc_frontend/src/parser/parser/types.rs +++ b/compiler/noirc_frontend/src/parser/parser/types.rs @@ -12,7 +12,7 @@ use chumsky::prelude::*; use noirc_errors::Span; fn maybe_comp_time() -> impl NoirParser<()> { - keyword(Keyword::CompTime).or_not().validate(|opt, span, emit| { + keyword(Keyword::Comptime).or_not().validate(|opt, span, emit| { if opt.is_some() { emit(ParserError::with_reason(ParserErrorReason::ComptimeDeprecated, span)); } @@ -88,13 +88,24 @@ pub(super) fn array_type( ) -> impl NoirParser { just(Token::LeftBracket) .ignore_then(type_parser) - .then(just(Token::Semicolon).ignore_then(type_expression()).or_not()) + .then(just(Token::Semicolon).ignore_then(type_expression())) .then_ignore(just(Token::RightBracket)) .map_with_span(|(element_type, size), span| { UnresolvedTypeData::Array(size, Box::new(element_type)).with_span(span) }) } +pub(super) fn slice_type( + type_parser: impl NoirParser, +) -> impl NoirParser { + just(Token::LeftBracket) + .ignore_then(type_parser) + .then_ignore(just(Token::RightBracket)) + .map_with_span(|element_type, span| { + UnresolvedTypeData::Slice(Box::new(element_type)).with_span(span) + }) +} + pub(super) fn type_expression() -> impl NoirParser { recursive(|expr| { expression_with_precedence( diff --git a/compiler/noirc_frontend/src/resolve_locations.rs b/compiler/noirc_frontend/src/resolve_locations.rs index b5f1b1d0c64..5efe2e4a041 100644 --- a/compiler/noirc_frontend/src/resolve_locations.rs +++ b/compiler/noirc_frontend/src/resolve_locations.rs @@ -1,4 +1,4 @@ -use arena::Index; +use noirc_arena::Index; use noirc_errors::Location; use crate::hir_def::expr::HirExpression; @@ -97,7 +97,7 @@ impl NodeInterner { return_type_location_instead: bool, ) -> Option { match expression { - HirExpression::Ident(ident) => { + HirExpression::Ident(ident, _) => { let definition_info = self.definition(ident.id); match definition_info.kind { DefinitionKind::Function(func_id) => { @@ -157,11 +157,11 @@ impl NodeInterner { self.trait_implementations .iter() .find(|shared_trait_impl| { - let trait_impl = shared_trait_impl.borrow(); + let trait_impl = shared_trait_impl.1.borrow(); trait_impl.file == location.file && trait_impl.ident.span().contains(&location.span) }) .and_then(|shared_trait_impl| { - let trait_impl = shared_trait_impl.borrow(); + let trait_impl = shared_trait_impl.1.borrow(); self.traits.get(&trait_impl.trait_id).map(|trait_| trait_.location) }) } diff --git a/compiler/noirc_frontend/src/tests.rs b/compiler/noirc_frontend/src/tests.rs index c661cc92eef..99215c8f173 100644 --- a/compiler/noirc_frontend/src/tests.rs +++ b/compiler/noirc_frontend/src/tests.rs @@ -1,1150 +1,1216 @@ +#![cfg(test)] + +#[cfg(test)] +mod name_shadowing; + // XXX: These tests repeat a lot of code // what we should do is have test cases which are passed to a test harness // A test harness will allow for more expressive and readable tests -#[cfg(test)] -mod test { - - use core::panic; - use std::collections::BTreeMap; - - use fm::FileId; - - use iter_extended::vecmap; - use noirc_errors::Location; - - use crate::hir::def_collector::dc_crate::CompilationError; - use crate::hir::def_collector::errors::{DefCollectorErrorKind, DuplicateType}; - use crate::hir::def_map::ModuleData; - use crate::hir::resolution::errors::ResolverError; - use crate::hir::resolution::import::PathResolutionError; - use crate::hir::type_check::TypeCheckError; - use crate::hir::Context; - use crate::node_interner::{NodeInterner, StmtId}; - - use crate::hir::def_collector::dc_crate::DefCollector; - use crate::hir_def::expr::HirExpression; - use crate::hir_def::stmt::HirStatement; - use crate::monomorphization::monomorphize; - use crate::parser::ParserErrorReason; - use crate::ParsedModule; - use crate::{ - hir::def_map::{CrateDefMap, LocalModuleId}, - parse_program, - }; - use arena::Arena; - use fm::FileManager; +use core::panic; +use std::collections::BTreeMap; + +use fm::FileId; + +use iter_extended::vecmap; +use noirc_errors::Location; + +use crate::hir::def_collector::dc_crate::CompilationError; +use crate::hir::def_collector::errors::{DefCollectorErrorKind, DuplicateType}; +use crate::hir::def_map::ModuleData; +use crate::hir::resolution::errors::ResolverError; +use crate::hir::resolution::import::PathResolutionError; +use crate::hir::type_check::TypeCheckError; +use crate::hir::Context; +use crate::node_interner::{NodeInterner, StmtId}; + +use crate::hir::def_collector::dc_crate::DefCollector; +use crate::hir_def::expr::HirExpression; +use crate::hir_def::stmt::HirStatement; +use crate::monomorphization::monomorphize; +use crate::parser::ParserErrorReason; +use crate::ParsedModule; +use crate::{ + hir::def_map::{CrateDefMap, LocalModuleId}, + parse_program, +}; +use fm::FileManager; +use noirc_arena::Arena; + +pub(crate) fn has_parser_error(errors: &[(CompilationError, FileId)]) -> bool { + errors.iter().any(|(e, _f)| matches!(e, CompilationError::ParseError(_))) +} - pub(crate) fn has_parser_error(errors: &[(CompilationError, FileId)]) -> bool { - errors.iter().any(|(e, _f)| matches!(e, CompilationError::ParseError(_))) - } +pub(crate) fn remove_experimental_warnings(errors: &mut Vec<(CompilationError, FileId)>) { + errors.retain(|(error, _)| match error { + CompilationError::ParseError(error) => { + !matches!(error.reason(), Some(ParserErrorReason::ExperimentalFeature(..))) + } + _ => true, + }); +} - pub(crate) fn remove_experimental_warnings(errors: &mut Vec<(CompilationError, FileId)>) { - errors.retain(|(error, _)| match error { - CompilationError::ParseError(error) => { - !matches!(error.reason(), Some(ParserErrorReason::ExperimentalFeature(..))) - } - _ => true, - }); - } - - pub(crate) fn get_program( - src: &str, - ) -> (ParsedModule, Context, Vec<(CompilationError, FileId)>) { - let root = std::path::Path::new("/"); - let fm = FileManager::new(root); - - let mut context = Context::new(fm, Default::default()); - context.def_interner.populate_dummy_operator_traits(); - let root_file_id = FileId::dummy(); - let root_crate_id = context.crate_graph.add_crate_root(root_file_id); - - let (program, parser_errors) = parse_program(src); - let mut errors = vecmap(parser_errors, |e| (e.into(), root_file_id)); - remove_experimental_warnings(&mut errors); - - if !has_parser_error(&errors) { - // Allocate a default Module for the root, giving it a ModuleId - let mut modules: Arena = Arena::default(); - let location = Location::new(Default::default(), root_file_id); - let root = modules.insert(ModuleData::new(None, location, false)); - - let def_map = CrateDefMap { - root: LocalModuleId(root), - modules, - krate: root_crate_id, - extern_prelude: BTreeMap::new(), - }; +pub(crate) fn get_program(src: &str) -> (ParsedModule, Context, Vec<(CompilationError, FileId)>) { + let root = std::path::Path::new("/"); + let fm = FileManager::new(root); + + let mut context = Context::new(fm, Default::default()); + context.def_interner.populate_dummy_operator_traits(); + let root_file_id = FileId::dummy(); + let root_crate_id = context.crate_graph.add_crate_root(root_file_id); + + let (program, parser_errors) = parse_program(src); + let mut errors = vecmap(parser_errors, |e| (e.into(), root_file_id)); + remove_experimental_warnings(&mut errors); + + if !has_parser_error(&errors) { + // Allocate a default Module for the root, giving it a ModuleId + let mut modules: Arena = Arena::default(); + let location = Location::new(Default::default(), root_file_id); + let root = modules.insert(ModuleData::new(None, location, false)); + + let def_map = CrateDefMap { + root: LocalModuleId(root), + modules, + krate: root_crate_id, + extern_prelude: BTreeMap::new(), + }; - // Now we want to populate the CrateDefMap using the DefCollector - errors.extend(DefCollector::collect( - def_map, - &mut context, - program.clone().into_sorted(), - root_file_id, - Vec::new(), // No macro processors - )); - } - (program, context, errors) + // Now we want to populate the CrateDefMap using the DefCollector + errors.extend(DefCollector::collect( + def_map, + &mut context, + program.clone().into_sorted(), + root_file_id, + false, + &[], // No macro processors + )); } + (program, context, errors) +} - pub(crate) fn get_program_errors(src: &str) -> Vec<(CompilationError, FileId)> { - get_program(src).2 - } +pub(crate) fn get_program_errors(src: &str) -> Vec<(CompilationError, FileId)> { + get_program(src).2 +} - #[test] - fn check_trait_implemented_for_all_t() { - let src = " - trait Default { - fn default() -> Self; - } - - trait Eq { - fn eq(self, other: Self) -> bool; +#[test] +fn check_trait_implemented_for_all_t() { + let src = " + trait Default { + fn default() -> Self; + } + + trait Eq { + fn eq(self, other: Self) -> bool; + } + + trait IsDefault { + fn is_default(self) -> bool; + } + + impl IsDefault for T where T: Default + Eq { + fn is_default(self) -> bool { + self.eq(T::default()) } - - trait IsDefault { - fn is_default(self) -> bool; + } + + struct Foo { + a: u64, + } + + impl Eq for Foo { + fn eq(self, other: Foo) -> bool { self.a == other.a } + } + + impl Default for u64 { + fn default() -> Self { + 0 } - - impl IsDefault for T where T: Default + Eq { - fn is_default(self) -> bool { - self.eq(T::default()) - } + } + + impl Default for Foo { + fn default() -> Self { + Foo { a: Default::default() } } - - struct Foo { - a: u64, + } + + fn main(a: Foo) -> pub bool { + a.is_default() + }"; + + let errors = get_program_errors(src); + errors.iter().for_each(|err| println!("{:?}", err)); + assert!(errors.is_empty()); +} + +#[test] +fn check_trait_implementation_duplicate_method() { + let src = " + trait Default { + fn default(x: Field, y: Field) -> Field; + } + + struct Foo { + bar: Field, + array: [Field; 2], + } + + impl Default for Foo { + // Duplicate trait methods should not compile + fn default(x: Field, y: Field) -> Field { + y + 2 * x } - - impl Eq for Foo { - fn eq(self, other: Foo) -> bool { self.a == other.a } + // Duplicate trait methods should not compile + fn default(x: Field, y: Field) -> Field { + x + 2 * y } - - impl Default for u64 { - fn default() -> Self { - 0 + } + + 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::Duplicate { + typ, + first_def, + second_def, + }) => { + assert_eq!(typ, &DuplicateType::TraitAssociatedFunction); + assert_eq!(first_def, "default"); + assert_eq!(second_def, "default"); } - } - - impl Default for Foo { - fn default() -> Self { - Foo { a: Default::default() } + _ => { + panic!("No other errors are expected! Found = {:?}", err); } - } - - fn main(a: Foo) -> pub bool { - a.is_default() - }"; - - let errors = get_program_errors(src); - errors.iter().for_each(|err| println!("{:?}", err)); - assert!(errors.is_empty()); + }; } +} - #[test] - fn check_trait_implementation_duplicate_method() { - let src = " - trait Default { - fn default(x: Field, y: Field) -> Field; - } - - struct Foo { - bar: Field, - array: [Field; 2], +#[test] +fn check_trait_wrong_method_return_type() { + let src = " + trait Default { + fn default() -> Self; + } + + struct Foo { + } + + impl Default for Foo { + fn default() -> Field { + 0 } - - impl Default for Foo { - // Duplicate trait methods should not compile - fn default(x: Field, y: Field) -> Field { - y + 2 * x + } + + 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::TypeError(TypeCheckError::TypeMismatch { + expected_typ, + expr_typ, + expr_span: _, + }) => { + assert_eq!(expected_typ, "Foo"); + assert_eq!(expr_typ, "Field"); } - // Duplicate trait methods should not compile - fn default(x: Field, y: Field) -> Field { - x + 2 * y + _ => { + panic!("No other errors are expected! Found = {:?}", err); } - } - - 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::Duplicate { - typ, - first_def, - second_def, - }) => { - assert_eq!(typ, &DuplicateType::TraitAssociatedFunction); - assert_eq!(first_def, "default"); - assert_eq!(second_def, "default"); - } - _ => { - panic!("No other errors are expected! Found = {:?}", err); - } - }; - } + }; } +} - #[test] - fn check_trait_wrong_method_return_type() { - let src = " - trait Default { - fn default() -> Self; - } - - struct Foo { +#[test] +fn check_trait_wrong_method_return_type2() { + let src = " + trait Default { + fn default(x: Field, y: Field) -> Self; + } + + struct Foo { + bar: Field, + array: [Field; 2], + } + + impl Default for Foo { + fn default(x: Field, _y: Field) -> Field { + x } - - impl Default for Foo { - fn default() -> Field { - 0 + } + + 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::TypeError(TypeCheckError::TypeMismatch { + expected_typ, + expr_typ, + expr_span: _, + }) => { + assert_eq!(expected_typ, "Foo"); + assert_eq!(expr_typ, "Field"); } - } - - 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::TypeError(TypeCheckError::TypeMismatch { - expected_typ, - expr_typ, - expr_span: _, - }) => { - assert_eq!(expected_typ, "Foo"); - assert_eq!(expr_typ, "Field"); - } - _ => { - panic!("No other errors are expected! Found = {:?}", err); - } - }; - } + _ => { + panic!("No other errors are expected! Found = {:?}", err); + } + }; } +} - #[test] - fn check_trait_wrong_method_return_type2() { - let src = " - trait Default { - fn default(x: Field, y: Field) -> Self; - } - - struct Foo { - bar: Field, - array: [Field; 2], +#[test] +fn check_trait_missing_implementation() { + let src = " + trait Default { + fn default(x: Field, y: Field) -> Self; + + fn method2(x: Field) -> Field; + + } + + struct Foo { + bar: Field, + array: [Field; 2], + } + + impl Default for Foo { + fn default(x: Field, y: Field) -> Self { + Self { bar: x, array: [x,y] } } - - impl Default for Foo { - fn default(x: Field, _y: Field) -> Field { - x + } + + 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::TraitMissingMethod { + trait_name, + method_name, + trait_impl_span: _, + }) => { + assert_eq!(trait_name, "Default"); + assert_eq!(method_name, "method2"); } - } - - 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::TypeError(TypeCheckError::TypeMismatch { - expected_typ, - expr_typ, - expr_span: _, - }) => { - assert_eq!(expected_typ, "Foo"); - assert_eq!(expr_typ, "Field"); - } - _ => { - panic!("No other errors are expected! Found = {:?}", err); - } - }; - } + _ => { + panic!("No other errors are expected! Found = {:?}", err); + } + }; } +} - #[test] - fn check_trait_missing_implementation() { - let src = " - trait Default { - fn default(x: Field, y: Field) -> Self; - - fn method2(x: Field) -> Field; - - } - - struct Foo { - bar: Field, - array: [Field; 2], +#[test] +fn check_trait_not_in_scope() { + let src = " + struct Foo { + bar: Field, + array: [Field; 2], + } + + // Default trait does not exist + impl Default for Foo { + fn default(x: Field, y: Field) -> Self { + Self { bar: x, array: [x,y] } } - - impl Default for Foo { - fn default(x: Field, y: Field) -> Self { - Self { bar: x, array: [x,y] } + } + + 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::TraitNotFound { + trait_path, + }) => { + assert_eq!(trait_path.as_string(), "Default"); } - } - - 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::TraitMissingMethod { - trait_name, - method_name, - trait_impl_span: _, - }) => { - assert_eq!(trait_name, "Default"); - assert_eq!(method_name, "method2"); - } - _ => { - panic!("No other errors are expected! Found = {:?}", err); - } - }; - } + _ => { + panic!("No other errors are expected! Found = {:?}", err); + } + }; } +} - #[test] - fn check_trait_not_in_scope() { - let src = " - struct Foo { - bar: Field, - array: [Field; 2], +#[test] +fn check_trait_wrong_method_name() { + let src = " + trait Default { + } + + struct Foo { + bar: Field, + array: [Field; 2], + } + + // wrong trait name method should not compile + impl Default for Foo { + fn does_not_exist(x: Field, y: Field) -> Self { + Self { bar: x, array: [x,y] } } - - // Default trait does not exist - impl Default for Foo { - fn default(x: Field, y: Field) -> Self { - Self { bar: x, array: [x,y] } + } + + fn main() { + }"; + let compilation_errors = get_program_errors(src); + assert!(!has_parser_error(&compilation_errors)); + assert!( + compilation_errors.len() == 1, + "Expected 1 compilation error, got: {:?}", + compilation_errors + ); + + for (err, _file_id) in compilation_errors { + match &err { + CompilationError::DefinitionError(DefCollectorErrorKind::MethodNotInTrait { + trait_name, + impl_method, + }) => { + assert_eq!(trait_name, "Default"); + assert_eq!(impl_method, "does_not_exist"); } - } - - 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::TraitNotFound { - trait_path, - }) => { - assert_eq!(trait_path.as_string(), "Default"); - } - _ => { - panic!("No other errors are expected! Found = {:?}", err); - } - }; - } + _ => { + panic!("No other errors are expected! Found = {:?}", err); + } + }; } +} - #[test] - fn check_trait_wrong_method_name() { - let src = " - trait Default { - } - - struct Foo { - bar: Field, - array: [Field; 2], +#[test] +fn check_trait_wrong_parameter() { + let src = " + trait Default { + fn default(x: Field) -> Self; + } + + struct Foo { + bar: u32, + } + + impl Default for Foo { + fn default(x: u32) -> Self { + Foo {bar: x} } - - // wrong trait name method should not compile - impl Default for Foo { - fn does_not_exist(x: Field, y: Field) -> Self { - Self { bar: x, array: [x,y] } + } + + 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::TypeError(TypeCheckError::TraitMethodParameterTypeMismatch { + method_name, + expected_typ, + actual_typ, + .. + }) => { + assert_eq!(method_name, "default"); + assert_eq!(expected_typ, "Field"); + assert_eq!(actual_typ, "u32"); } - } - - fn main() { - }"; - let compilation_errors = get_program_errors(src); - assert!(!has_parser_error(&compilation_errors)); - assert!( - compilation_errors.len() == 1, - "Expected 1 compilation error, got: {:?}", - compilation_errors - ); - - for (err, _file_id) in compilation_errors { - match &err { - CompilationError::DefinitionError(DefCollectorErrorKind::MethodNotInTrait { - trait_name, - impl_method, - }) => { - assert_eq!(trait_name, "Default"); - assert_eq!(impl_method, "does_not_exist"); - } - _ => { - panic!("No other errors are expected! Found = {:?}", err); - } - }; - } + _ => { + panic!("No other errors are expected! Found = {:?}", err); + } + }; } +} - #[test] - fn check_trait_wrong_parameter() { - let src = " - trait Default { - fn default(x: Field) -> Self; - } - - struct Foo { - bar: u32, +#[test] +fn check_trait_wrong_parameter2() { + let src = " + trait Default { + fn default(x: Field, y: Field) -> Self; + } + + struct Foo { + bar: Field, + array: [Field; 2], + } + + impl Default for Foo { + fn default(x: Field, y: Foo) -> Self { + Self { bar: x, array: [x, y.bar] } } - - impl Default for Foo { - fn default(x: u32) -> Self { - Foo {bar: x} + } + + 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::TypeError(TypeCheckError::TraitMethodParameterTypeMismatch { + method_name, + expected_typ, + actual_typ, + .. + }) => { + assert_eq!(method_name, "default"); + assert_eq!(expected_typ, "Field"); + assert_eq!(actual_typ, "Foo"); } - } - - 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::TypeError(TypeCheckError::TraitMethodParameterTypeMismatch { - method_name, - expected_typ, - actual_typ, - .. - }) => { - assert_eq!(method_name, "default"); - assert_eq!(expected_typ, "Field"); - assert_eq!(actual_typ, "u32"); - } - _ => { - panic!("No other errors are expected! Found = {:?}", err); - } - }; - } + _ => { + panic!("No other errors are expected! Found = {:?}", err); + } + }; } +} - #[test] - fn check_trait_wrong_parameter2() { - let src = " - trait Default { - fn default(x: Field, y: Field) -> Self; - } - - struct Foo { - bar: Field, - array: [Field; 2], - } - - impl Default for Foo { - fn default(x: Field, y: Foo) -> Self { - Self { bar: x, array: [x, y.bar] } +#[test] +fn check_trait_wrong_parameter_type() { + let src = " + trait Default { + fn default(x: Field, y: NotAType) -> Field; + } + + fn main(x: Field, y: Field) { + assert(y == x); + }"; + let errors = get_program_errors(src); + assert!(!has_parser_error(&errors)); + + // This is a duplicate error in the name resolver & type checker. + // In the elaborator there is no duplicate and only 1 error is issued + assert!(errors.len() <= 2, "Expected 1 or 2 errors, got: {:?}", errors); + + for (err, _file_id) in errors { + match &err { + CompilationError::ResolverError(ResolverError::PathResolutionError( + PathResolutionError::Unresolved(ident), + )) => { + assert_eq!(ident, "NotAType"); } - } - - 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::TypeError(TypeCheckError::TraitMethodParameterTypeMismatch { - method_name, - expected_typ, - actual_typ, - .. - }) => { - assert_eq!(method_name, "default"); - assert_eq!(expected_typ, "Field"); - assert_eq!(actual_typ, "Foo"); - } - _ => { - panic!("No other errors are expected! Found = {:?}", err); - } - }; - } + _ => { + panic!("No other errors are expected! Found = {:?}", err); + } + }; } +} - #[test] - fn check_trait_wrong_parameter_type() { - let src = " - trait Default { - fn default(x: Field, y: NotAType) -> Field; - } - - fn main(x: Field, y: Field) { - assert(y == x); - }"; - let errors = get_program_errors(src); - assert!(!has_parser_error(&errors)); - assert!(errors.len() == 2, "Expected 2 errors, got: {:?}", errors); - - for (err, _file_id) in errors { - match &err { - CompilationError::ResolverError(ResolverError::PathResolutionError( - PathResolutionError::Unresolved(ident), - )) => { - assert_eq!(ident, "NotAType"); - } - _ => { - panic!("No other errors are expected! Found = {:?}", err); - } - }; - } +#[test] +fn check_trait_wrong_parameters_count() { + let src = " + trait Default { + fn default(x: Field, y: Field) -> Self; } - - #[test] - fn check_trait_wrong_parameters_count() { - let src = " - trait Default { - fn default(x: Field, y: Field) -> Self; - } - - struct Foo { - bar: Field, - array: [Field; 2], + + struct Foo { + bar: Field, + array: [Field; 2], + } + + impl Default for Foo { + fn default(x: Field) -> Self { + Self { bar: x, array: [x, x] } } - - impl Default for Foo { - fn default(x: Field) -> Self { - Self { bar: x, array: [x, x] } + } + + 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::TypeError(TypeCheckError::MismatchTraitImplNumParameters { + actual_num_parameters, + expected_num_parameters, + trait_name, + method_name, + .. + }) => { + assert_eq!(actual_num_parameters, &1_usize); + assert_eq!(expected_num_parameters, &2_usize); + assert_eq!(method_name, "default"); + assert_eq!(trait_name, "Default"); } - } - - 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::MismatchTraitImplementationNumParameters { - actual_num_parameters, - expected_num_parameters, - trait_name, - method_name, - .. - }, - ) => { - assert_eq!(actual_num_parameters, &1_usize); - assert_eq!(expected_num_parameters, &2_usize); - assert_eq!(method_name, "default"); - assert_eq!(trait_name, "Default"); - } - _ => { - panic!("No other errors are expected in this test case! Found = {:?}", err); - } - }; - } + _ => { + panic!("No other errors are expected in this test case! Found = {:?}", err); + } + }; } +} - #[test] - fn check_trait_impl_for_non_type() { - let src = " - trait Default { - fn default(x: Field, y: Field) -> Field; +#[test] +fn check_trait_impl_for_non_type() { + let src = " + trait Default { + fn default(x: Field, y: Field) -> Field; + } + + impl Default for main { + fn default(x: Field, y: Field) -> Field { + x + y } + } - impl Default for main { - fn default(x: Field, y: Field) -> Field { - x + y + 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::ResolverError(ResolverError::Expected { expected, got, .. }) => { + assert_eq!(expected, "type"); + assert_eq!(got, "function"); } - } + _ => { + panic!("No other errors are expected! Found = {:?}", err); + } + }; + } +} - 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::ResolverError(ResolverError::Expected { - expected, got, .. - }) => { - assert_eq!(expected, "type"); - assert_eq!(got, "function"); - } - _ => { - panic!("No other errors are expected! Found = {:?}", err); - } - }; - } +#[test] +fn check_impl_struct_not_trait() { + let src = " + struct Foo { + bar: Field, + array: [Field; 2], } - #[test] - fn check_impl_struct_not_trait() { - let src = " - struct Foo { - bar: Field, - array: [Field; 2], - } - - struct Default { - x: Field, - z: Field, + struct Default { + x: Field, + z: Field, + } + + // Default is a struct not a trait + impl Default for Foo { + fn default(x: Field, y: Field) -> Self { + Self { bar: x, array: [x,y] } } - - // Default is struct not a trait - impl Default for Foo { - fn default(x: Field, y: Field) -> Self { - Self { bar: x, array: [x,y] } + } + + 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::NotATrait { + not_a_trait_name, + }) => { + assert_eq!(not_a_trait_name.to_string(), "plain::Default"); } - } - - 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::NotATrait { - not_a_trait_name, - }) => { - assert_eq!(not_a_trait_name.to_string(), "plain::Default"); - } - _ => { - panic!("No other errors are expected! Found = {:?}", err); - } - }; - } + _ => { + panic!("No other errors are expected! Found = {:?}", err); + } + }; } +} - #[test] - fn check_trait_duplicate_declaration() { - let src = " - trait Default { - fn default(x: Field, y: Field) -> Self; - } - - struct Foo { - bar: Field, - array: [Field; 2], +#[test] +fn check_trait_duplicate_declaration() { + let src = " + trait Default { + fn default(x: Field, y: Field) -> Self; + } + + struct Foo { + bar: Field, + array: [Field; 2], + } + + impl Default for Foo { + fn default(x: Field,y: Field) -> Self { + Self { bar: x, array: [x,y] } } - - impl Default for Foo { - fn default(x: Field,y: Field) -> Self { - Self { bar: x, array: [x,y] } + } + + + trait Default { + fn default(x: Field) -> Self; + } + + 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::Duplicate { + typ, + first_def, + second_def, + }) => { + assert_eq!(typ, &DuplicateType::Trait); + assert_eq!(first_def, "Default"); + assert_eq!(second_def, "Default"); } - } - - - trait Default { - fn default(x: Field) -> Self; - } - - 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::Duplicate { - typ, - first_def, - second_def, - }) => { - assert_eq!(typ, &DuplicateType::Trait); - assert_eq!(first_def, "Default"); - assert_eq!(second_def, "Default"); - } - _ => { - panic!("No other errors are expected! Found = {:?}", err); - } - }; - } + _ => { + panic!("No other errors are expected! Found = {:?}", err); + } + }; } +} - #[test] - fn check_trait_duplicate_implementation() { - let src = " - trait Default { - } - struct Foo { - bar: Field, - } - - impl Default for Foo { - } - impl Default for Foo { - } - fn main() { - } - "; - let errors = get_program_errors(src); - assert!(!has_parser_error(&errors)); - assert!(errors.len() == 2, "Expected 2 errors, got: {:?}", errors); - for (err, _file_id) in errors { - match &err { - CompilationError::DefinitionError(DefCollectorErrorKind::OverlappingImpl { - .. - }) => (), - CompilationError::DefinitionError(DefCollectorErrorKind::OverlappingImplNote { - .. - }) => (), - _ => { - panic!("No other errors are expected! Found = {:?}", err); - } - }; - } +#[test] +fn check_trait_duplicate_implementation() { + let src = " + trait Default { + } + struct Foo { + bar: Field, + } + + impl Default for Foo { + } + impl Default for Foo { + } + fn main() { + } + "; + let errors = get_program_errors(src); + assert!(!has_parser_error(&errors)); + assert!(errors.len() == 2, "Expected 2 errors, got: {:?}", errors); + for (err, _file_id) in errors { + match &err { + CompilationError::DefinitionError(DefCollectorErrorKind::OverlappingImpl { + .. + }) => (), + CompilationError::DefinitionError(DefCollectorErrorKind::OverlappingImplNote { + .. + }) => (), + _ => { + panic!("No other errors are expected! Found = {:?}", err); + } + }; + } +} + +#[test] +fn check_trait_duplicate_implementation_with_alias() { + let src = " + trait Default { + } + + struct MyStruct { + } + + type MyType = MyStruct; + + impl Default for MyStruct { + } + + impl Default for MyType { + } + + fn main() { + } + "; + let errors = get_program_errors(src); + assert!(!has_parser_error(&errors)); + assert!(errors.len() == 2, "Expected 2 errors, got: {:?}", errors); + for (err, _file_id) in errors { + match &err { + CompilationError::DefinitionError(DefCollectorErrorKind::OverlappingImpl { + .. + }) => (), + CompilationError::DefinitionError(DefCollectorErrorKind::OverlappingImplNote { + .. + }) => (), + _ => { + panic!("No other errors are expected! Found = {:?}", err); + } + }; } +} - #[test] - fn check_trait_duplicate_implementation_with_alias() { - let src = " - trait Default { - } - - struct MyStruct { - } - - type MyType = MyStruct; - - impl Default for MyStruct { - } - - impl Default for MyType { - } - - fn main() { - } - "; - let errors = get_program_errors(src); - assert!(!has_parser_error(&errors)); - assert!(errors.len() == 2, "Expected 2 errors, got: {:?}", errors); - for (err, _file_id) in errors { - match &err { - CompilationError::DefinitionError(DefCollectorErrorKind::OverlappingImpl { - .. - }) => (), - CompilationError::DefinitionError(DefCollectorErrorKind::OverlappingImplNote { - .. - }) => (), - _ => { - panic!("No other errors are expected! Found = {:?}", err); - } - }; +#[test] +fn test_impl_self_within_default_def() { + let src = " + trait Bar { + fn ok(self) -> Self; + + fn ref_ok(self) -> Self { + self.ok() } } - fn get_program_captures(src: &str) -> Vec> { - let (program, context, _errors) = get_program(src); - let interner = context.def_interner; - let mut all_captures: Vec> = Vec::new(); - for func in program.into_sorted().functions { - let func_id = interner.find_function(func.name()).unwrap(); - let hir_func = interner.function(&func_id); - // Iterate over function statements and apply filtering function - find_lambda_captures( - hir_func.block(&interner).statements(), - &interner, - &mut all_captures, - ); + impl Bar for (T, T) where T: Bar { + fn ok(self) -> Self { + self } - all_captures - } - - fn find_lambda_captures( - stmts: &[StmtId], - interner: &NodeInterner, - result: &mut Vec>, - ) { - for stmt_id in stmts.iter() { - let hir_stmt = interner.statement(stmt_id); - let expr_id = match hir_stmt { - HirStatement::Expression(expr_id) => expr_id, - HirStatement::Let(let_stmt) => let_stmt.expression, - HirStatement::Assign(assign_stmt) => assign_stmt.expression, - HirStatement::Constrain(constr_stmt) => constr_stmt.0, - HirStatement::Semi(semi_expr) => semi_expr, - HirStatement::For(for_loop) => for_loop.block, - HirStatement::Error => panic!("Invalid HirStatement!"), - }; - let expr = interner.expression(&expr_id); + }"; + let errors = get_program_errors(src); + errors.iter().for_each(|err| println!("{:?}", err)); + assert!(errors.is_empty()); +} - get_lambda_captures(expr, interner, result); // TODO: dyn filter function as parameter - } +#[test] +fn check_trait_as_type_as_fn_parameter() { + let src = " + trait Eq { + fn eq(self, other: Self) -> bool; } - fn get_lambda_captures( - expr: HirExpression, - interner: &NodeInterner, - result: &mut Vec>, - ) { - if let HirExpression::Lambda(lambda_expr) = expr { - let mut cur_capture = Vec::new(); + struct Foo { + a: u64, + } - for capture in lambda_expr.captures.iter() { - cur_capture.push(interner.definition(capture.ident.id).name.clone()); - } - result.push(cur_capture); + impl Eq for Foo { + fn eq(self, other: Foo) -> bool { self.a == other.a } + } - // Check for other captures recursively within the lambda body - let hir_body_expr = interner.expression(&lambda_expr.body); - if let HirExpression::Block(block_expr) = hir_body_expr { - find_lambda_captures(block_expr.statements(), interner, result); - } - } + fn test_eq(x: impl Eq) -> bool { + x.eq(x) } - #[test] - fn resolve_empty_function() { - let src = " - fn main() { + fn main(a: Foo) -> pub bool { + test_eq(a) + }"; - } - "; - assert!(get_program_errors(src).is_empty()); - } - #[test] - fn resolve_basic_function() { - let src = r#" - fn main(x : Field) { - let y = x + x; - assert(y == x); - } - "#; - assert!(get_program_errors(src).is_empty()); - } - #[test] - fn resolve_unused_var() { - let src = r#" - fn main(x : Field) { - let y = x + x; - assert(x == x); - } - "#; - - let errors = get_program_errors(src); - assert!(errors.len() == 1, "Expected 1 error, got: {:?}", errors); - // It should be regarding the unused variable - match &errors[0].0 { - CompilationError::ResolverError(ResolverError::UnusedVariable { ident }) => { - assert_eq!(&ident.0.contents, "y"); - } - _ => unreachable!("we should only have an unused var error"), - } + let errors = get_program_errors(src); + errors.iter().for_each(|err| println!("{:?}", err)); + assert!(errors.is_empty()); +} + +#[test] +fn check_trait_as_type_as_two_fn_parameters() { + let src = " + trait Eq { + fn eq(self, other: Self) -> bool; } - #[test] - fn resolve_unresolved_var() { - let src = r#" - fn main(x : Field) { - let y = x + x; - assert(y == z); - } - "#; - let errors = get_program_errors(src); - 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::ResolverError(ResolverError::VariableNotDeclared { - name, - span: _, - }) => assert_eq!(name, "z"), - _ => unimplemented!("we should only have an unresolved variable"), - } + trait Test { + fn test(self) -> bool; } - #[test] - fn unresolved_path() { - let src = " - fn main(x : Field) { - let _z = some::path::to::a::func(x); - } - "; - let errors = get_program_errors(src); - assert!(errors.len() == 1, "Expected 1 error, got: {:?}", errors); - for (compilation_error, _file_id) in errors { - match compilation_error { - CompilationError::ResolverError(err) => { - match err { - ResolverError::PathResolutionError(PathResolutionError::Unresolved( - name, - )) => { - assert_eq!(name.to_string(), "some"); - } - _ => unimplemented!("we should only have an unresolved function"), - }; - } - _ => unimplemented!(), - } - } + struct Foo { + a: u64, } - #[test] - fn resolve_literal_expr() { - let src = r#" - fn main(x : Field) { - let y = 5; - assert(y == x); - } - "#; - assert!(get_program_errors(src).is_empty()); + impl Eq for Foo { + fn eq(self, other: Foo) -> bool { self.a == other.a } } - #[test] - fn multiple_resolution_errors() { - let src = r#" - fn main(x : Field) { - let y = foo::bar(x); - let z = y + a; - } - "#; - - let errors = get_program_errors(src); - assert!(errors.len() == 3, "Expected 3 errors, got: {:?}", errors); - - // Errors are: - // `a` is undeclared - // `z` is unused - // `foo::bar` does not exist - for (compilation_error, _file_id) in errors { - match compilation_error { - CompilationError::ResolverError(err) => { - match err { - ResolverError::UnusedVariable { ident } => { - assert_eq!(&ident.0.contents, "z"); - } - ResolverError::VariableNotDeclared { name, .. } => { - assert_eq!(name, "a"); - } - ResolverError::PathResolutionError(PathResolutionError::Unresolved( - name, - )) => { - assert_eq!(name.to_string(), "foo"); - } - _ => unimplemented!(), - }; - } - _ => unimplemented!(), - } - } + impl Test for u64 { + fn test(self) -> bool { self == self } } - #[test] - fn resolve_prefix_expr() { - let src = r#" - fn main(x : Field) { - let _y = -x; - } - "#; - assert!(get_program_errors(src).is_empty()); + fn test_eq(x: impl Eq, y: impl Test) -> bool { + x.eq(x) == y.test() } - #[test] - fn resolve_for_expr() { - let src = r#" - fn main(x : u64) { - for i in 1..20 { - let _z = x + i; - }; - } - "#; - assert!(get_program_errors(src).is_empty()); + fn main(a: Foo, b: u64) -> pub bool { + test_eq(a, b) + }"; + + let errors = get_program_errors(src); + errors.iter().for_each(|err| println!("{:?}", err)); + assert!(errors.is_empty()); +} + +fn get_program_captures(src: &str) -> Vec> { + let (program, context, _errors) = get_program(src); + let interner = context.def_interner; + let mut all_captures: Vec> = Vec::new(); + for func in program.into_sorted().functions { + let func_id = interner.find_function(func.name()).unwrap(); + let hir_func = interner.function(&func_id); + // Iterate over function statements and apply filtering function + find_lambda_captures(hir_func.block(&interner).statements(), &interner, &mut all_captures); } + all_captures +} - #[test] - fn resolve_call_expr() { - let src = r#" - fn main(x : Field) { - let _z = foo(x); - } +fn find_lambda_captures(stmts: &[StmtId], interner: &NodeInterner, result: &mut Vec>) { + for stmt_id in stmts.iter() { + let hir_stmt = interner.statement(stmt_id); + let expr_id = match hir_stmt { + HirStatement::Expression(expr_id) => expr_id, + HirStatement::Let(let_stmt) => let_stmt.expression, + HirStatement::Assign(assign_stmt) => assign_stmt.expression, + HirStatement::Constrain(constr_stmt) => constr_stmt.0, + HirStatement::Semi(semi_expr) => semi_expr, + HirStatement::For(for_loop) => for_loop.block, + HirStatement::Error => panic!("Invalid HirStatement!"), + HirStatement::Break => panic!("Unexpected break"), + HirStatement::Continue => panic!("Unexpected continue"), + HirStatement::Comptime(_) => panic!("Unexpected comptime"), + }; + let expr = interner.expression(&expr_id); - fn foo(x : Field) -> Field { - x - } - "#; - assert!(get_program_errors(src).is_empty()); - } - - #[test] - fn resolve_shadowing() { - let src = r#" - fn main(x : Field) { - let x = foo(x); - let x = x; - let (x, x) = (x, x); - let _ = x; - } + get_lambda_captures(expr, interner, result); // TODO: dyn filter function as parameter + } +} + +fn get_lambda_captures( + expr: HirExpression, + interner: &NodeInterner, + result: &mut Vec>, +) { + if let HirExpression::Lambda(lambda_expr) = expr { + let mut cur_capture = Vec::new(); + + for capture in lambda_expr.captures.iter() { + cur_capture.push(interner.definition(capture.ident.id).name.clone()); + } + result.push(cur_capture); + + // Check for other captures recursively within the lambda body + let hir_body_expr = interner.expression(&lambda_expr.body); + if let HirExpression::Block(block_expr) = hir_body_expr { + find_lambda_captures(block_expr.statements(), interner, result); + } + } +} + +#[test] +fn resolve_empty_function() { + let src = " + fn main() { - fn foo(x : Field) -> Field { - x + } + "; + assert!(get_program_errors(src).is_empty()); +} +#[test] +fn resolve_basic_function() { + let src = r#" + fn main(x : Field) { + let y = x + x; + assert(y == x); + } + "#; + assert!(get_program_errors(src).is_empty()); +} +#[test] +fn resolve_unused_var() { + let src = r#" + fn main(x : Field) { + let y = x + x; + assert(x == x); + } + "#; + + let errors = get_program_errors(src); + assert!(errors.len() == 1, "Expected 1 error, got: {:?}", errors); + // It should be regarding the unused variable + match &errors[0].0 { + CompilationError::ResolverError(ResolverError::UnusedVariable { ident }) => { + assert_eq!(&ident.0.contents, "y"); + } + _ => unreachable!("we should only have an unused var error"), + } +} + +#[test] +fn resolve_unresolved_var() { + let src = r#" + fn main(x : Field) { + let y = x + x; + assert(y == z); + } + "#; + let errors = get_program_errors(src); + 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::ResolverError(ResolverError::VariableNotDeclared { name, span: _ }) => { + assert_eq!(name, "z"); + } + _ => unimplemented!("we should only have an unresolved variable"), + } +} + +#[test] +fn unresolved_path() { + let src = " + fn main(x : Field) { + let _z = some::path::to::a::func(x); + } + "; + let errors = get_program_errors(src); + assert!(errors.len() == 1, "Expected 1 error, got: {:?}", errors); + for (compilation_error, _file_id) in errors { + match compilation_error { + CompilationError::ResolverError(err) => { + match err { + ResolverError::PathResolutionError(PathResolutionError::Unresolved(name)) => { + assert_eq!(name.to_string(), "some"); + } + _ => unimplemented!("we should only have an unresolved function"), + }; } - "#; - assert!(get_program_errors(src).is_empty()); + _ => unimplemented!(), + } } +} - #[test] - fn resolve_basic_closure() { - let src = r#" - fn main(x : Field) -> pub Field { - let closure = |y| y + x; - closure(x) +#[test] +fn resolve_literal_expr() { + let src = r#" + fn main(x : Field) { + let y = 5; + assert(y == x); + } + "#; + assert!(get_program_errors(src).is_empty()); +} + +#[test] +fn multiple_resolution_errors() { + let src = r#" + fn main(x : Field) { + let y = foo::bar(x); + let z = y + a; + } + "#; + + let errors = get_program_errors(src); + assert!(errors.len() == 3, "Expected 3 errors, got: {:?}", errors); + + // Errors are: + // `a` is undeclared + // `z` is unused + // `foo::bar` does not exist + for (compilation_error, _file_id) in errors { + match compilation_error { + CompilationError::ResolverError(err) => { + match err { + ResolverError::UnusedVariable { ident } => { + assert_eq!(&ident.0.contents, "z"); + } + ResolverError::VariableNotDeclared { name, .. } => { + assert_eq!(name, "a"); + } + ResolverError::PathResolutionError(PathResolutionError::Unresolved(name)) => { + assert_eq!(name.to_string(), "foo"); + } + _ => unimplemented!(), + }; } - "#; - assert!(get_program_errors(src).is_empty()); + _ => unimplemented!(), + } } +} - #[test] - fn resolve_simplified_closure() { - // based on bug https://github.com/noir-lang/noir/issues/1088 +#[test] +fn resolve_prefix_expr() { + let src = r#" + fn main(x : Field) { + let _y = -x; + } + "#; + assert!(get_program_errors(src).is_empty()); +} - let src = r#"fn do_closure(x: Field) -> Field { - let y = x; - let ret_capture = || { - y +#[test] +fn resolve_for_expr() { + let src = r#" + fn main(x : u64) { + for i in 1..20 { + let _z = x + i; }; - ret_capture() - } - - fn main(x: Field) { - assert(do_closure(x) == 100); - } - - "#; - let parsed_captures = get_program_captures(src); - let expected_captures = vec![vec!["y".to_string()]]; - assert_eq!(expected_captures, parsed_captures); - } - - #[test] - fn resolve_complex_closures() { - let src = r#" - fn main(x: Field) -> pub Field { - let closure_without_captures = |x| x + x; - let a = closure_without_captures(1); - - let closure_capturing_a_param = |y| y + x; - let b = closure_capturing_a_param(2); - - let closure_capturing_a_local_var = |y| y + b; - let c = closure_capturing_a_local_var(3); - - let closure_with_transitive_captures = |y| { - let d = 5; - let nested_closure = |z| { - let doubly_nested_closure = |w| w + x + b; - a + z + y + d + x + doubly_nested_closure(4) + x + y - }; - let res = nested_closure(5); - res + } + "#; + assert!(get_program_errors(src).is_empty()); +} + +#[test] +fn resolve_call_expr() { + let src = r#" + fn main(x : Field) { + let _z = foo(x); + } + + fn foo(x : Field) -> Field { + x + } + "#; + assert!(get_program_errors(src).is_empty()); +} + +#[test] +fn resolve_shadowing() { + let src = r#" + fn main(x : Field) { + let x = foo(x); + let x = x; + let (x, x) = (x, x); + let _ = x; + } + + fn foo(x : Field) -> Field { + x + } + "#; + assert!(get_program_errors(src).is_empty()); +} + +#[test] +fn resolve_basic_closure() { + let src = r#" + fn main(x : Field) -> pub Field { + let closure = |y| y + x; + closure(x) + } + "#; + assert!(get_program_errors(src).is_empty()); +} + +#[test] +fn resolve_simplified_closure() { + // based on bug https://github.com/noir-lang/noir/issues/1088 + + let src = r#"fn do_closure(x: Field) -> Field { + let y = x; + let ret_capture = || { + y + }; + ret_capture() + } + + fn main(x: Field) { + assert(do_closure(x) == 100); + } + + "#; + let parsed_captures = get_program_captures(src); + let expected_captures = vec![vec!["y".to_string()]]; + assert_eq!(expected_captures, parsed_captures); +} + +#[test] +fn resolve_complex_closures() { + let src = r#" + fn main(x: Field) -> pub Field { + let closure_without_captures = |x: Field| -> Field { x + x }; + let a = closure_without_captures(1); + + let closure_capturing_a_param = |y: Field| -> Field { y + x }; + let b = closure_capturing_a_param(2); + + let closure_capturing_a_local_var = |y: Field| -> Field { y + b }; + let c = closure_capturing_a_local_var(3); + + let closure_with_transitive_captures = |y: Field| -> Field { + let d = 5; + let nested_closure = |z: Field| -> Field { + let doubly_nested_closure = |w: Field| -> Field { w + x + b }; + a + z + y + d + x + doubly_nested_closure(4) + x + y }; + let res = nested_closure(5); + res + }; + + a + b + c + closure_with_transitive_captures(6) + } + "#; + assert!(get_program_errors(src).is_empty(), "there should be no errors"); + + let expected_captures = vec![ + vec![], + vec!["x".to_string()], + vec!["b".to_string()], + vec!["x".to_string(), "b".to_string(), "a".to_string()], + vec!["x".to_string(), "b".to_string(), "a".to_string(), "y".to_string(), "d".to_string()], + vec!["x".to_string(), "b".to_string()], + ]; - a + b + c + closure_with_transitive_captures(6) + let parsed_captures = get_program_captures(src); + + assert_eq!(expected_captures, parsed_captures); +} + +#[test] +fn resolve_fmt_strings() { + let src = r#" + fn main() { + let string = f"this is i: {i}"; + println(string); + + println(f"I want to print {0}"); + + let new_val = 10; + println(f"random_string{new_val}{new_val}"); + } + fn println(x : T) -> T { + x + } + "#; + + let errors = get_program_errors(src); + assert!(errors.len() == 5, "Expected 5 errors, got: {:?}", errors); + + for (err, _file_id) in errors { + match &err { + CompilationError::ResolverError(ResolverError::VariableNotDeclared { + name, .. + }) => { + assert_eq!(name, "i"); } - "#; - assert!(get_program_errors(src).is_empty(), "there should be no errors"); - - let expected_captures = vec![ - vec![], - vec!["x".to_string()], - vec!["b".to_string()], - vec!["x".to_string(), "b".to_string(), "a".to_string()], - vec![ - "x".to_string(), - "b".to_string(), - "a".to_string(), - "y".to_string(), - "d".to_string(), - ], - vec!["x".to_string(), "b".to_string()], - ]; - - let parsed_captures = get_program_captures(src); - - assert_eq!(expected_captures, parsed_captures); - } - - #[test] - fn resolve_fmt_strings() { - let src = r#" - fn main() { - let string = f"this is i: {i}"; - println(string); - - println(f"I want to print {0}"); - - let new_val = 10; - println(f"random_string{new_val}{new_val}"); + CompilationError::ResolverError(ResolverError::NumericConstantInFormatString { + name, + .. + }) => { + assert_eq!(name, "0"); } - fn println(x : T) -> T { - x + CompilationError::TypeError(TypeCheckError::UnusedResultError { + expr_type: _, + expr_span, + }) => { + let a = src.get(expr_span.start() as usize..expr_span.end() as usize).unwrap(); + assert!( + a == "println(string)" + || a == "println(f\"I want to print {0}\")" + || a == "println(f\"random_string{new_val}{new_val}\")" + ); } - "#; - - let errors = get_program_errors(src); - assert!(errors.len() == 5, "Expected 5 errors, got: {:?}", errors); - - for (err, _file_id) in errors { - match &err { - CompilationError::ResolverError(ResolverError::VariableNotDeclared { - name, - .. - }) => { - assert_eq!(name, "i"); - } - CompilationError::ResolverError(ResolverError::NumericConstantInFormatString { - name, - .. - }) => { - assert_eq!(name, "0"); - } - CompilationError::TypeError(TypeCheckError::UnusedResultError { - expr_type: _, - expr_span, - }) => { - let a = src.get(expr_span.start() as usize..expr_span.end() as usize).unwrap(); - assert!( - a == "println(string)" - || a == "println(f\"I want to print {0}\")" - || a == "println(f\"random_string{new_val}{new_val}\")" - ); - } - _ => unimplemented!(), - }; - } + _ => unimplemented!(), + }; } +} - fn check_rewrite(src: &str, expected: &str) { - let (_program, mut context, _errors) = get_program(src); - let main_func_id = context.def_interner.find_function("main").unwrap(); - let program = monomorphize(main_func_id, &mut context.def_interner).unwrap(); - assert!(format!("{}", program) == expected); - } +fn check_rewrite(src: &str, expected: &str) { + let (_program, mut context, _errors) = get_program(src); + let main_func_id = context.def_interner.find_function("main").unwrap(); + let program = monomorphize(main_func_id, &mut context.def_interner).unwrap(); + assert!(format!("{}", program) == expected); +} - #[test] - fn simple_closure_with_no_captured_variables() { - let src = r#" - fn main() -> pub Field { - let x = 1; - let closure = || x; - closure() - } - "#; +#[test] +fn simple_closure_with_no_captured_variables() { + let src = r#" + fn main() -> pub Field { + let x = 1; + let closure = || x; + closure() + } + "#; - let expected_rewrite = r#"fn main$f0() -> Field { + let expected_rewrite = r#"fn main$f0() -> Field { let x$0 = 1; let closure$3 = { let closure_variable$2 = { @@ -1162,48 +1228,219 @@ fn lambda$f1(mut env$l1: (Field)) -> Field { env$l1.0 } "#; - check_rewrite(src, expected_rewrite); - } - - #[test] - fn deny_cyclic_structs() { - let src = r#" - struct Foo { bar: Bar } - struct Bar { foo: Foo } - fn main() {} - "#; - assert_eq!(get_program_errors(src).len(), 1); - } - - #[test] - fn deny_cyclic_globals() { - let src = r#" - global A = B; - global B = A; - fn main() {} - "#; - assert_eq!(get_program_errors(src).len(), 1); - } - - #[test] - fn deny_cyclic_type_aliases() { - let src = r#" - type A = B; - type B = A; - fn main() {} - "#; - assert_eq!(get_program_errors(src).len(), 1); - } - - #[test] - fn ensure_nested_type_aliases_type_check() { - let src = r#" - type A = B; - type B = u8; - fn main() { - let _a: A = 0 as u16; + check_rewrite(src, expected_rewrite); +} + +#[test] +fn deny_cyclic_globals() { + let src = r#" + global A = B; + global B = A; + fn main() {} + "#; + assert_eq!(get_program_errors(src).len(), 1); +} + +#[test] +fn deny_cyclic_type_aliases() { + let src = r#" + type A = B; + type B = A; + fn main() {} + "#; + assert_eq!(get_program_errors(src).len(), 1); +} + +#[test] +fn ensure_nested_type_aliases_type_check() { + let src = r#" + type A = B; + type B = u8; + fn main() { + let _a: A = 0 as u16; + } + "#; + assert_eq!(get_program_errors(src).len(), 1); +} + +#[test] +fn type_aliases_in_entry_point() { + let src = r#" + type Foo = u8; + fn main(_x: Foo) {} + "#; + assert_eq!(get_program_errors(src).len(), 0); +} + +#[test] +fn operators_in_global_used_in_type() { + let src = r#" + global ONE = 1; + global COUNT = ONE + 2; + fn main() { + let _array: [Field; COUNT] = [1, 2, 3]; + } + "#; + assert_eq!(get_program_errors(src).len(), 0); +} + +#[test] +fn break_and_continue_in_constrained_fn() { + let src = r#" + fn main() { + for i in 0 .. 10 { + if i == 2 { + continue; + } + if i == 5 { + break; + } } - "#; - assert_eq!(get_program_errors(src).len(), 1); - } + } + "#; + assert_eq!(get_program_errors(src).len(), 2); +} + +#[test] +fn break_and_continue_outside_loop() { + let src = r#" + unconstrained fn main() { + continue; + break; + } + "#; + assert_eq!(get_program_errors(src).len(), 2); +} + +// Regression for #2540 +#[test] +fn for_loop_over_array() { + let src = r#" + fn hello(_array: [u1; N]) { + for _ in 0..N {} + } + + fn main() { + let array: [u1; 2] = [0, 1]; + hello(array); + } + "#; + assert_eq!(get_program_errors(src).len(), 0); +} + +// Regression for #4545 +#[test] +fn type_aliases_in_main() { + let src = r#" + type Outer = [u8; N]; + fn main(_arg: Outer<1>) {} + "#; + assert_eq!(get_program_errors(src).len(), 0); +} + +#[test] +fn ban_mutable_globals() { + // Mutable globals are only allowed in a comptime context + let src = r#" + mut global FOO: Field = 0; + fn main() {} + "#; + assert_eq!(get_program_errors(src).len(), 1); +} + +#[test] +fn deny_inline_attribute_on_unconstrained() { + let src = r#" + #[no_predicates] + unconstrained fn foo(x: Field, y: Field) { + assert(x != y); + } + "#; + let errors = get_program_errors(src); + assert_eq!(errors.len(), 1); + assert!(matches!( + errors[0].0, + CompilationError::ResolverError(ResolverError::NoPredicatesAttributeOnUnconstrained { .. }) + )); +} + +#[test] +fn deny_fold_attribute_on_unconstrained() { + let src = r#" + #[fold] + unconstrained fn foo(x: Field, y: Field) { + assert(x != y); + } + "#; + let errors = get_program_errors(src); + assert_eq!(errors.len(), 1); + assert!(matches!( + errors[0].0, + CompilationError::ResolverError(ResolverError::FoldAttributeOnUnconstrained { .. }) + )); +} + +#[test] +fn specify_function_types_with_turbofish() { + let src = r#" + trait Default { + fn default() -> Self; + } + + impl Default for Field { + fn default() -> Self { 0 } + } + + impl Default for u64 { + fn default() -> Self { 0 } + } + + // Need the above as we don't have access to the stdlib here. + // We also need to construct a concrete value of `U` without giving away its type + // as otherwise the unspecified type is ignored. + + fn generic_func() -> (T, U) where T: Default, U: Default { + (T::default(), U::default()) + } + + fn main() { + let _ = generic_func::(); + } + "#; + let errors = get_program_errors(src); + assert_eq!(errors.len(), 0); +} + +#[test] +fn specify_method_types_with_turbofish() { + let src = r#" + trait Default { + fn default() -> Self; + } + + impl Default for Field { + fn default() -> Self { 0 } + } + + // Need the above as we don't have access to the stdlib here. + // We also need to construct a concrete value of `U` without giving away its type + // as otherwise the unspecified type is ignored. + + struct Foo { + inner: T + } + + impl Foo { + fn generic_method(_self: Self) -> U where U: Default { + U::default() + } + } + + fn main() { + let foo: Foo = Foo { inner: 1 }; + let _ = foo.generic_method::(); + } + "#; + let errors = get_program_errors(src); + assert_eq!(errors.len(), 0); } diff --git a/compiler/noirc_frontend/src/tests/name_shadowing.rs b/compiler/noirc_frontend/src/tests/name_shadowing.rs new file mode 100644 index 00000000000..b0d83510039 --- /dev/null +++ b/compiler/noirc_frontend/src/tests/name_shadowing.rs @@ -0,0 +1,419 @@ +#![cfg(test)] +use super::get_program_errors; +use std::collections::HashSet; + +#[test] +fn test_name_shadowing() { + let src = " + trait Default { + fn default() -> Self; + } + + impl Default for bool { + fn default() -> bool { + false + } + } + + impl Default for Field { + fn default() -> Field { + 0 + } + } + + impl Default for [T; N] where T: Default { + fn default() -> [T; N] { + [Default::default(); N] + } + } + + impl Default for (T, U) where T: Default, U: Default { + fn default() -> (T, U) { + (Default::default(), Default::default()) + } + } + + fn drop_var(_x: T, y: U) -> U { y } + + mod local_module { + use crate::{Default, drop_var}; + + global LOCAL_GLOBAL_N: Field = 0; + + global LOCAL_GLOBAL_M: Field = 1; + + struct LocalStruct { + field1: A, + field2: B, + field3: [A; N], + field4: ([A; N], [B; M]), + field5: &mut A, + } + + impl Default for LocalStruct where A: Default, B: Default { + fn default() -> Self { + let mut mut_field = &mut Default::default(); + Self { + field1: Default::default(), + field2: Default::default(), + field3: Default::default(), + field4: Default::default(), + field5: mut_field, + } + } + } + + trait DefinedInLocalModule1 { + fn trait_fn1(self, x: A); + fn trait_fn2(self, y: B); + fn trait_fn3(&mut self, x: A, y: B); + fn trait_fn4(self, x: [A; 0], y: [B]); + fn trait_fn5(self, x: [A; N], y: [B; M]) -> [A; 0]; + fn trait_fn6(self, x: [A; N], y: [B; M]) -> [A; 0]; + fn trait_fn7(self, _x: fn([A; 0]) -> B) -> Field { + drop_var(self, N + M) + } + } + + impl DefinedInLocalModule1 for LocalStruct { + fn trait_fn1(self, _x: A) { drop_var(self, ()) } + fn trait_fn2(self, _y: B) { drop_var(self, ()) } + fn trait_fn3(&mut self, _x: A, _y: B) { drop_var(self, ()) } + fn trait_fn4(self, _x: [A; 0], _y: [B]) { drop_var(self, ()) } + fn trait_fn5(self, _x: [A; N], _y: [B; M]) -> [A; 0] { drop_var(self, []) } + fn trait_fn6(self, _x: [A; N], _y: [B; M]) -> [A; 0] { drop_var(self, []) } + } + + pub fn local_fn4(_x: (A, B), _y: [Field; N], _z: [Field; M]) -> [A; 0] { + assert(LOCAL_GLOBAL_N != LOCAL_GLOBAL_M); + let x: Field = 0; + assert(x == 0); + let x: Field = 1; + assert(x == 1); + [] + } + } + + mod library { + use crate::{Default, drop_var}; + + mod library2 { + use crate::{Default, drop_var}; + + global IMPORT_GLOBAL_N_2: Field = 4; + + global IMPORT_GLOBAL_M_2: Field = 5; + + // When we re-export this type from another library and then use it in + // main, we get a panic + struct ReExportMeFromAnotherLib1 { + x : Field, + } + + struct PubLibLocalStruct3 { + pub_field1: A, + pub_field2: B, + pub_field3: [A; N], + pub_field4: ([A; N], [B; M]), + pub_field5: &mut A, + } + + impl Default for PubLibLocalStruct3 where A: Default, B: Default { + fn default() -> Self { + let mut mut_field = &mut Default::default(); + Self { + pub_field1: Default::default(), + pub_field2: Default::default(), + pub_field3: Default::default(), + pub_field4: Default::default(), + pub_field5: mut_field, + } + } + } + + trait PubLibDefinedInLocalModule3 { + fn pub_trait_fn1(self, x: A); + fn pub_trait_fn2(self, y: B); + fn pub_trait_fn3(&mut self, x: A, y: B); + fn pub_trait_fn4(self, x: [A; 0], y: [B]); + fn pub_trait_fn5(self, x: [A; N], y: [B; M]) -> [A; 0]; + fn pub_trait_fn6(self, x: [A; N], y: [B; M]) -> [A; 0]; + fn pub_trait_fn7(self, _x: fn([A; 0]) -> B) -> Field { + drop_var(self, N + M) + } + } + + impl PubLibDefinedInLocalModule3 for PubLibLocalStruct3 { + fn pub_trait_fn1(self, _x: A) { drop_var(self, ()) } + fn pub_trait_fn2(self, _y: B) { drop_var(self, ()) } + fn pub_trait_fn3(&mut self, _x: A, _y: B) { drop_var(self, ()) } + fn pub_trait_fn4(self, _x: [A; 0], _y: [B]) { drop_var(self, ()) } + fn pub_trait_fn5(self, _x: [A; N], _y: [B; M]) -> [A; 0] { drop_var(self, []) } + fn pub_trait_fn6(self, _x: [A; N], _y: [B; M]) -> [A; 0] { drop_var(self, []) } + } + + pub fn PubLiblocal_fn3(_x: (A, B), _y: [Field; N], _z: [Field; M]) -> [A; 0] { + assert(IMPORT_GLOBAL_N_2 != IMPORT_GLOBAL_M_2); + [] + } + } + + // Re-export + use library2::ReExportMeFromAnotherLib1; + + global IMPORT_GLOBAL_N_1: Field = 2; + + global IMPORT_GLOBAL_M_1: Field = 3; + + struct LibLocalStruct1 { + lib_field1: A, + lib_field2: B, + lib_field3: [A; N], + lib_field4: ([A; N], [B; M]), + lib_field5: &mut A, + } + + impl Default for LibLocalStruct1 where A: Default, B: Default { + fn default() -> Self { + let mut mut_field = &mut Default::default(); + Self { + lib_field1: Default::default(), + lib_field2: Default::default(), + lib_field3: Default::default(), + lib_field4: Default::default(), + lib_field5: mut_field, + } + } + } + + trait LibDefinedInLocalModule1 { + fn lib_trait_fn1(self, x: A); + fn lib_trait_fn2(self, y: B); + fn lib_trait_fn3(&mut self, x: A, y: B); + fn lib_trait_fn4(self, x: [A; 0], y: [B]); + fn lib_trait_fn5(self, x: [A; N], y: [B; M]) -> [A; 0]; + fn lib_trait_fn6(self, x: [A; N], y: [B; M]) -> [A; 0]; + fn lib_trait_fn7(self, _x: fn([A; 0]) -> B) -> Field { + drop_var(self, N + M) + } + } + + impl LibDefinedInLocalModule1 for LibLocalStruct1 { + fn lib_trait_fn1(self, _x: A) { drop_var(self, ()) } + fn lib_trait_fn2(self, _y: B) { drop_var(self, ()) } + fn lib_trait_fn3(&mut self, _x: A, _y: B) { drop_var(self, ()) } + fn lib_trait_fn4(self, _x: [A; 0], _y: [B]) { drop_var(self, ()) } + fn lib_trait_fn5(self, _x: [A; N], _y: [B; M]) -> [A; 0] { drop_var(self, []) } + fn lib_trait_fn6(self, _x: [A; N], _y: [B; M]) -> [A; 0] { drop_var(self, []) } + } + + pub fn Liblocal_fn1(_x: (A, B), _y: [Field; N], _z: [Field; M]) -> [A; 0] { + assert(IMPORT_GLOBAL_N_1 != IMPORT_GLOBAL_M_1); + [] + } + } + + mod library3 { + use crate::{Default, drop_var}; + + global IMPORT_GLOBAL_N_3: Field = 6; + + global IMPORT_GLOBAL_M_3: Field = 7; + + struct ReExportMeFromAnotherLib2 { + x : Field, + } + + struct PubCrateLibLocalStruct2 { + crate_field1: A, + crate_field2: B, + crate_field3: [A; N], + crate_field4: ([A; N], [B; M]), + crate_field5: &mut A, + } + + impl Default for PubCrateLibLocalStruct2 where A: Default, B: Default { + fn default() -> Self { + let mut mut_field = &mut Default::default(); + Self { + crate_field1: Default::default(), + crate_field2: Default::default(), + crate_field3: Default::default(), + crate_field4: Default::default(), + crate_field5: mut_field, + } + } + } + + trait PubCrateLibDefinedInLocalModule2 { + fn crate_trait_fn1(self, x: A); + fn crate_trait_fn2(self, y: B); + fn crate_trait_fn3(&mut self, x: A, y: B); + fn crate_trait_fn4(self, x: [A; 0], y: [B]); + fn crate_trait_fn5(self, x: [A; N], y: [B; M]) -> [A; 0]; + fn crate_trait_fn6(self, x: [A; N], y: [B; M]) -> [A; 0]; + fn crate_trait_fn7(self, _x: fn([A; 0]) -> B) -> Field { + drop_var(self, N + M) + } + } + + impl PubCrateLibDefinedInLocalModule2 for PubCrateLibLocalStruct2 { + fn crate_trait_fn1(self, _x: A) { drop_var(self, ()) } + fn crate_trait_fn2(self, _y: B) { drop_var(self, ()) } + fn crate_trait_fn3(&mut self, _x: A, _y: B) { drop_var(self, ()) } + fn crate_trait_fn4(self, _x: [A; 0], _y: [B]) { drop_var(self, ()) } + fn crate_trait_fn5(self, _x: [A; N], _y: [B; M]) -> [A; 0] { drop_var(self, ()); [] } + fn crate_trait_fn6(self, _x: [A; N], _y: [B; M]) -> [A; 0] { drop_var(self, ()); [] } + } + + pub(crate) fn PubCrateLiblocal_fn2(_x: (A, B), _y: [Field; N], _z: [Field; M]) -> [A; 0] { + assert(IMPORT_GLOBAL_N_3 != IMPORT_GLOBAL_M_3); + [] + } + } + + + use crate::local_module::{local_fn4, LocalStruct, DefinedInLocalModule1, LOCAL_GLOBAL_N, LOCAL_GLOBAL_M}; + + use library::{ReExportMeFromAnotherLib1, LibLocalStruct1, LibDefinedInLocalModule1, Liblocal_fn1, IMPORT_GLOBAL_N_1, IMPORT_GLOBAL_M_1}; + + // overlapping + // use library::library2::ReExportMeFromAnotherLib1; + use crate::library::library2::{PubLibLocalStruct3, PubLibDefinedInLocalModule3, PubLiblocal_fn3, IMPORT_GLOBAL_N_2, IMPORT_GLOBAL_M_2}; + + use library3::{ReExportMeFromAnotherLib2, PubCrateLibLocalStruct2, PubCrateLibDefinedInLocalModule2, PubCrateLiblocal_fn2, IMPORT_GLOBAL_N_3, IMPORT_GLOBAL_M_3}; + + + fn main(_x: ReExportMeFromAnotherLib1, _y: ReExportMeFromAnotherLib2) { + assert(LOCAL_GLOBAL_N != LOCAL_GLOBAL_M); + assert(IMPORT_GLOBAL_N_1 != IMPORT_GLOBAL_M_1); + assert(IMPORT_GLOBAL_N_2 != IMPORT_GLOBAL_M_2); + assert(IMPORT_GLOBAL_N_3 != IMPORT_GLOBAL_M_3); + + let x: LocalStruct = Default::default(); + assert(drop_var(x.trait_fn5([0; LOCAL_GLOBAL_N], [false; LOCAL_GLOBAL_M]), true)); + assert(drop_var(x.trait_fn6([0; LOCAL_GLOBAL_N], [false; LOCAL_GLOBAL_M]), true)); + + let x: LibLocalStruct1 = Default::default(); + assert(drop_var(x.lib_trait_fn5([0; IMPORT_GLOBAL_N_1], [false; IMPORT_GLOBAL_M_1]), true)); + assert(drop_var(x.lib_trait_fn6([0; IMPORT_GLOBAL_N_1], [false; IMPORT_GLOBAL_M_1]), true)); + + let x: PubLibLocalStruct3 = Default::default(); + assert(drop_var(x.pub_trait_fn5([0; IMPORT_GLOBAL_N_2], [false; IMPORT_GLOBAL_M_2]), true)); + assert(drop_var(x.pub_trait_fn6([0; IMPORT_GLOBAL_N_2], [false; IMPORT_GLOBAL_M_2]), true)); + + let x: PubCrateLibLocalStruct2 = Default::default(); + assert(drop_var(x.crate_trait_fn5([0; IMPORT_GLOBAL_N_3], [false; IMPORT_GLOBAL_M_3]), true)); + assert(drop_var(x.crate_trait_fn6([0; IMPORT_GLOBAL_N_3], [false; IMPORT_GLOBAL_M_3]), true)); + + assert(drop_var(local_fn2((0, 1), [], []), true)); + assert(drop_var(Liblocal_fn1((0, 1), [], []), true)); + assert(drop_var(PubLiblocal_fn4((0, 1), [], []), true)); + assert(drop_var(PubCrateLiblocal_fn3((0, 1), [], []), true)); + }"; + + // NOTE: these names must be "replacement-unique", i.e. + // replacing one in a discinct name should do nothing + let names_to_collapse = [ + "DefinedInLocalModule1", + "IMPORT_GLOBAL_M_1", + "IMPORT_GLOBAL_M_2", + "IMPORT_GLOBAL_M_3", + "IMPORT_GLOBAL_N_1", + "IMPORT_GLOBAL_N_2", + "IMPORT_GLOBAL_N_3", + "LOCAL_GLOBAL_M", + "LOCAL_GLOBAL_N", + "LibDefinedInLocalModule1", + "LibLocalStruct1", + "Liblocal_fn1", + "LocalStruct", + "PubCrateLibDefinedInLocalModule2", + "PubCrateLibLocalStruct2", + "PubCrateLiblocal_fn2", + "PubLibDefinedInLocalModule3", + "PubLibLocalStruct3", + "PubLiblocal_fn3", + "ReExportMeFromAnotherLib1", + "ReExportMeFromAnotherLib2", + "local_fn4", + "crate_field1", + "crate_field2", + "crate_field3", + "crate_field4", + "crate_field5", + "crate_trait_fn1", + "crate_trait_fn2", + "crate_trait_fn3", + "crate_trait_fn4", + "crate_trait_fn5", + "crate_trait_fn6", + "crate_trait_fn7", + "field1", + "field2", + "field3", + "field4", + "field5", + "lib_field1", + "lib_field2", + "lib_field3", + "lib_field4", + "lib_field5", + "lib_trait_fn1", + "lib_trait_fn2", + "lib_trait_fn3", + "lib_trait_fn4", + "lib_trait_fn5", + "lib_trait_fn6", + "lib_trait_fn7", + "pub_field1", + "pub_field2", + "pub_field3", + "pub_field4", + "pub_field5", + "pub_trait_fn1", + "pub_trait_fn2", + "pub_trait_fn3", + "pub_trait_fn4", + "pub_trait_fn5", + "pub_trait_fn6", + "pub_trait_fn7", + "trait_fn1", + "trait_fn2", + "trait_fn3", + "trait_fn4", + "trait_fn5", + "trait_fn6", + "trait_fn7", + ]; + + // TODO(https://github.com/noir-lang/noir/issues/4973): + // Name resolution panic from name shadowing test + let cases_to_skip = [ + (1, 21), + (2, 11), + (2, 21), + (3, 11), + (3, 18), + (3, 21), + (4, 21), + (5, 11), + (5, 21), + (6, 11), + (6, 18), + (6, 21), + ]; + let cases_to_skip: HashSet<(usize, usize)> = cases_to_skip.into_iter().collect(); + + for (i, x) in names_to_collapse.iter().enumerate() { + for (j, y) in names_to_collapse.iter().enumerate().filter(|(j, _)| i < *j) { + if !cases_to_skip.contains(&(i, j)) { + dbg!((i, j)); + + let modified_src = src.replace(x, y); + let errors = get_program_errors(&modified_src); + assert!(!errors.is_empty(), "Expected errors, got: {:?}", errors); + } + } + } +} diff --git a/compiler/noirc_printable_type/Cargo.toml b/compiler/noirc_printable_type/Cargo.toml index fbbe778e561..5140f5a5a8c 100644 --- a/compiler/noirc_printable_type/Cargo.toml +++ b/compiler/noirc_printable_type/Cargo.toml @@ -3,6 +3,7 @@ name = "noirc_printable_type" version.workspace = true authors.workspace = true edition.workspace = true +rust-version.workspace = true license.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/compiler/noirc_printable_type/src/lib.rs b/compiler/noirc_printable_type/src/lib.rs index 24f4f275a14..d9c9c7f9731 100644 --- a/compiler/noirc_printable_type/src/lib.rs +++ b/compiler/noirc_printable_type/src/lib.rs @@ -1,6 +1,6 @@ use std::{collections::BTreeMap, str}; -use acvm::{brillig_vm::brillig::ForeignCallParam, FieldElement}; +use acvm::{acir::AcirField, brillig_vm::brillig::ForeignCallParam, FieldElement}; use iter_extended::vecmap; use regex::{Captures, Regex}; use serde::{Deserialize, Serialize}; @@ -11,7 +11,11 @@ use thiserror::Error; pub enum PrintableType { Field, Array { - length: Option, + length: u32, + #[serde(rename = "type")] + typ: Box, + }, + Slice { #[serde(rename = "type")] typ: Box, }, @@ -30,9 +34,11 @@ pub enum PrintableType { fields: Vec<(String, PrintableType)>, }, String { - length: u64, + length: u32, }, Function { + arguments: Vec, + return_type: Box, env: Box, }, MutableReference { @@ -48,7 +54,7 @@ pub enum PrintableType { pub enum PrintableValue { Field(FieldElement), String(String), - Vec(Vec), + Vec { array_elements: Vec, is_slice: bool }, Struct(BTreeMap), Other, } @@ -75,14 +81,16 @@ pub enum ForeignCallError { ResolvedAssertMessage(String), } -impl TryFrom<&[ForeignCallParam]> for PrintableValueDisplay { +impl TryFrom<&[ForeignCallParam]> for PrintableValueDisplay { type Error = ForeignCallError; - fn try_from(foreign_call_inputs: &[ForeignCallParam]) -> Result { + fn try_from( + foreign_call_inputs: &[ForeignCallParam], + ) -> Result { let (is_fmt_str, foreign_call_inputs) = foreign_call_inputs.split_last().ok_or(ForeignCallError::MissingForeignCallInputs)?; - if is_fmt_str.unwrap_value().to_field().is_one() { + if is_fmt_str.unwrap_field().is_one() { convert_fmt_string_inputs(foreign_call_inputs) } else { convert_string_inputs(foreign_call_inputs) @@ -91,7 +99,7 @@ impl TryFrom<&[ForeignCallParam]> for PrintableValueDisplay { } fn convert_string_inputs( - foreign_call_inputs: &[ForeignCallParam], + foreign_call_inputs: &[ForeignCallParam], ) -> Result { // Fetch the PrintableType from the foreign call input // The remaining input values should hold what is to be printed @@ -100,8 +108,7 @@ fn convert_string_inputs( let printable_type = fetch_printable_type(printable_type_as_values)?; // We must use a flat map here as each value in a struct will be in a separate input value - let mut input_values_as_fields = - input_values.iter().flat_map(|param| vecmap(param.values(), |value| value.to_field())); + let mut input_values_as_fields = input_values.iter().flat_map(|param| param.fields()); let value = decode_value(&mut input_values_as_fields, &printable_type); @@ -109,12 +116,12 @@ fn convert_string_inputs( } fn convert_fmt_string_inputs( - foreign_call_inputs: &[ForeignCallParam], + foreign_call_inputs: &[ForeignCallParam], ) -> Result { let (message, input_and_printable_types) = foreign_call_inputs.split_first().ok_or(ForeignCallError::MissingForeignCallInputs)?; - let message_as_fields = vecmap(message.values(), |value| value.to_field()); + let message_as_fields = message.fields(); let message_as_string = decode_string_value(&message_as_fields); let (num_values, input_and_printable_types) = input_and_printable_types @@ -122,12 +129,11 @@ fn convert_fmt_string_inputs( .ok_or(ForeignCallError::MissingForeignCallInputs)?; let mut output = Vec::new(); - let num_values = num_values.unwrap_value().to_field().to_u128() as usize; + let num_values = num_values.unwrap_field().to_u128() as usize; let types_start_at = input_and_printable_types.len() - num_values; - let mut input_iter = input_and_printable_types[0..types_start_at] - .iter() - .flat_map(|param| vecmap(param.values(), |value| value.to_field())); + let mut input_iter = + input_and_printable_types[0..types_start_at].iter().flat_map(|param| param.fields()); for printable_type in input_and_printable_types.iter().skip(types_start_at) { let printable_type = fetch_printable_type(printable_type)?; let value = decode_value(&mut input_iter, &printable_type); @@ -139,9 +145,9 @@ fn convert_fmt_string_inputs( } fn fetch_printable_type( - printable_type: &ForeignCallParam, + printable_type: &ForeignCallParam, ) -> Result { - let printable_type_as_fields = vecmap(printable_type.values(), |value| value.to_field()); + let printable_type_as_fields = printable_type.fields(); let printable_type_as_string = decode_string_value(&printable_type_as_fields); let printable_type: PrintableType = serde_json::from_str(&printable_type_as_string)?; @@ -176,15 +182,19 @@ fn to_string(value: &PrintableValue, typ: &PrintableType) -> Option { output.push_str("false"); } } - (PrintableValue::Field(_), PrintableType::Function { .. }) => { - output.push_str("<>"); + (PrintableValue::Field(_), PrintableType::Function { arguments, return_type, .. }) => { + output.push_str(&format!("< {:?}>>", arguments, return_type,)); } (_, PrintableType::MutableReference { .. }) => { output.push_str("<>"); } - (PrintableValue::Vec(vector), PrintableType::Array { typ, .. }) => { + (PrintableValue::Vec { array_elements, is_slice }, PrintableType::Array { typ, .. }) + | (PrintableValue::Vec { array_elements, is_slice }, PrintableType::Slice { typ }) => { + if *is_slice { + output.push('&') + } output.push('['); - let mut values = vector.iter().peekable(); + let mut values = array_elements.iter().peekable(); while let Some(value) = values.next() { output.push_str(&format!( "{}", @@ -219,9 +229,9 @@ fn to_string(value: &PrintableValue, typ: &PrintableType) -> Option { output.push_str(" }"); } - (PrintableValue::Vec(values), PrintableType::Tuple { types }) => { + (PrintableValue::Vec { array_elements, .. }, PrintableType::Tuple { types }) => { output.push('('); - let mut elems = values.iter().zip(types).peekable(); + let mut elems = array_elements.iter().zip(types).peekable(); while let Some((value, typ)) = elems.next() { output.push_str( &PrintableValueDisplay::Plain(value.clone(), typ.clone()).to_string(), @@ -310,30 +320,31 @@ pub fn decode_value( PrintableValue::Field(field_element) } - PrintableType::Array { length: None, typ } => { - let length = field_iterator - .next() - .expect("not enough data to decode variable array length") - .to_u128() as usize; + PrintableType::Array { length, typ } => { + let length = *length as usize; let mut array_elements = Vec::with_capacity(length); for _ in 0..length { array_elements.push(decode_value(field_iterator, typ)); } - PrintableValue::Vec(array_elements) + PrintableValue::Vec { array_elements, is_slice: false } } - PrintableType::Array { length: Some(length), typ } => { - let length = *length as usize; + PrintableType::Slice { typ } => { + let length = field_iterator + .next() + .expect("not enough data to decode variable array length") + .to_u128() as usize; let mut array_elements = Vec::with_capacity(length); for _ in 0..length { array_elements.push(decode_value(field_iterator, typ)); } - PrintableValue::Vec(array_elements) - } - PrintableType::Tuple { types } => { - PrintableValue::Vec(vecmap(types, |typ| decode_value(field_iterator, typ))) + PrintableValue::Vec { array_elements, is_slice: true } } + PrintableType::Tuple { types } => PrintableValue::Vec { + array_elements: vecmap(types, |typ| decode_value(field_iterator, typ)), + is_slice: false, + }, PrintableType::String { length } => { let field_elements: Vec = field_iterator.take(*length as usize).collect(); @@ -350,7 +361,7 @@ pub fn decode_value( PrintableValue::Struct(struct_map) } - PrintableType::Function { env } => { + PrintableType::Function { env, .. } => { let field_element = field_iterator.next().unwrap(); let func_ref = PrintableValue::Field(field_element); // we want to consume the fields from the environment, but for now they are not actually printed diff --git a/compiler/wasm/Cargo.toml b/compiler/wasm/Cargo.toml index a20efeeed8a..03e59b3e269 100644 --- a/compiler/wasm/Cargo.toml +++ b/compiler/wasm/Cargo.toml @@ -3,6 +3,7 @@ name = "noir_wasm" version.workspace = true authors.workspace = true edition.workspace = true +rust-version.workspace = true license.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -12,11 +13,11 @@ license.workspace = true crate-type = ["cdylib"] [dependencies] -acvm.workspace = true +acvm = { workspace = true, features = ["bn254"] } fm.workspace = true nargo.workspace = true noirc_driver.workspace = true -noirc_frontend.workspace = true +noirc_frontend = { workspace = true, features = ["bn254"] } noirc_errors.workspace = true noirc_evaluator.workspace = true wasm-bindgen.workspace = true diff --git a/compiler/wasm/README.md b/compiler/wasm/README.md index 52f7e83e19e..fd534722622 100644 --- a/compiler/wasm/README.md +++ b/compiler/wasm/README.md @@ -26,17 +26,3 @@ for (const path of files) { } const myCompiledCode = await compile(fm); ``` - -## Building from source - -Outside of the [noir repo](https://github.com/noir-lang/noir), this package can be built using the command below: - -```bash -nix build -L github:noir-lang/noir/master#noir_wasm -``` - -If you are within the noir repo and would like to build local changes, you can use: - -```bash -nix build -L #noir_wasm -``` diff --git a/compiler/wasm/package.json b/compiler/wasm/package.json index 67584a2def1..0bb9b803ee0 100644 --- a/compiler/wasm/package.json +++ b/compiler/wasm/package.json @@ -3,7 +3,7 @@ "contributors": [ "The Noir Team " ], - "version": "0.24.0", + "version": "0.30.0", "license": "(MIT OR Apache-2.0)", "main": "dist/main.js", "types": "./dist/types/src/index.d.cts", @@ -55,27 +55,27 @@ "@types/sinon": "^17", "@wasm-tool/wasm-pack-plugin": "^1.7.0", "@web/dev-server-esbuild": "^0.3.6", - "@web/test-runner": "^0.18.0", + "@web/test-runner": "^0.18.1", "@web/test-runner-playwright": "^0.11.0", "adm-zip": "^0.5.0", "assert": "^2.1.0", "browserify-fs": "^1.0.0", - "chai": "^4.3.10", + "chai": "^4.4.1", "copy-webpack-plugin": "^12.0.2", - "eslint": "^8.56.0", - "eslint-plugin-prettier": "^5.0.0", + "eslint": "^8.57.0", + "eslint-plugin-prettier": "^5.1.3", "html-webpack-plugin": "^5.6.0", "memfs": "^4.6.0", "mocha": "^10.2.0", "mocha-each": "^2.0.1", "path-browserify": "^1.0.1", - "prettier": "3.0.3", + "prettier": "3.2.5", "process": "^0.11.10", "readable-stream": "^4.4.2", "sinon": "^17.0.1", "ts-loader": "^9.5.1", "ts-node": "^10.9.1", - "typescript": "~5.2.2", + "typescript": "^5.4.2", "unzipit": "^1.4.3", "url": "^0.11.3", "webpack": "^5.90.1", diff --git a/compiler/wasm/scripts/build-fixtures.sh b/compiler/wasm/scripts/build-fixtures.sh index 3a2330d4726..4c0505ef519 100755 --- a/compiler/wasm/scripts/build-fixtures.sh +++ b/compiler/wasm/scripts/build-fixtures.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash nargo compile --program-dir ./test/fixtures/simple -nargo compile --program-dir ./test/fixtures/with-deps +nargo compile --program-dir ./test/fixtures/with-deps nargo compile --program-dir ./test/fixtures/noir-contract \ No newline at end of file diff --git a/compiler/wasm/src/compile.rs b/compiler/wasm/src/compile.rs index 9e6fca1126e..f1495e0b438 100644 --- a/compiler/wasm/src/compile.rs +++ b/compiler/wasm/src/compile.rs @@ -1,16 +1,13 @@ +use acvm::acir::circuit::ExpressionWidth; use fm::FileManager; use gloo_utils::format::JsValueSerdeExt; use js_sys::{JsString, Object}; use nargo::{ - artifacts::{ - contract::{ContractArtifact, ContractFunctionArtifact}, - program::ProgramArtifact, - }, + artifacts::{contract::ContractArtifact, program::ProgramArtifact}, parse_all, }; use noirc_driver::{ add_dep, file_manager_with_stdlib, prepare_crate, prepare_dependency, CompileOptions, - NOIR_ARTIFACT_VERSION_STRING, }; use noirc_evaluator::errors::SsaReport; use noirc_frontend::{ @@ -30,11 +27,16 @@ export type DependencyGraph = { library_dependencies: Readonly>; } +export type ContractOutputsArtifact = { + structs: Record>; + globals: Record>; +} + export type ContractArtifact = { noir_version: string; name: string; functions: Array; - events: Array; + outputs: ContractOutputsArtifact; file_map: Record; }; @@ -164,9 +166,10 @@ pub fn compile_program( console_error_panic_hook::set_once(); let (crate_id, mut context) = prepare_context(entry_point, dependency_graph, file_source_map)?; - let compile_options = CompileOptions::default(); - // For now we default to a bounded width of 3, though we can add it as a parameter - let expression_width = acvm::acir::circuit::ExpressionWidth::Bounded { width: 3 }; + let compile_options = CompileOptions { + expression_width: ExpressionWidth::Bounded { width: 4 }, + ..CompileOptions::default() + }; let compiled_program = noirc_driver::compile_main(&mut context, crate_id, &compile_options, None) @@ -179,7 +182,8 @@ pub fn compile_program( })? .0; - let optimized_program = nargo::ops::transform_program(compiled_program, expression_width); + let optimized_program = + nargo::ops::transform_program(compiled_program, compile_options.expression_width); let warnings = optimized_program.warnings.clone(); Ok(JsCompileProgramResult::new(optimized_program.into(), warnings)) @@ -194,9 +198,10 @@ pub fn compile_contract( console_error_panic_hook::set_once(); let (crate_id, mut context) = prepare_context(entry_point, dependency_graph, file_source_map)?; - let compile_options = CompileOptions::default(); - // For now we default to a bounded width of 3, though we can add it as a parameter - let expression_width = acvm::acir::circuit::ExpressionWidth::Bounded { width: 3 }; + let compile_options = CompileOptions { + expression_width: ExpressionWidth::Bounded { width: 4 }, + ..CompileOptions::default() + }; let compiled_contract = noirc_driver::compile_contract(&mut context, crate_id, &compile_options) @@ -209,20 +214,11 @@ pub fn compile_contract( })? .0; - let optimized_contract = nargo::ops::transform_contract(compiled_contract, expression_width); - - let functions = - optimized_contract.functions.into_iter().map(ContractFunctionArtifact::from).collect(); - - let contract_artifact = ContractArtifact { - noir_version: String::from(NOIR_ARTIFACT_VERSION_STRING), - name: optimized_contract.name, - functions, - events: optimized_contract.events, - file_map: optimized_contract.file_map, - }; + let optimized_contract = + nargo::ops::transform_contract(compiled_contract, compile_options.expression_width); + let warnings = optimized_contract.warnings.clone(); - Ok(JsCompileContractResult::new(contract_artifact, optimized_contract.warnings)) + Ok(JsCompileContractResult::new(optimized_contract.into(), warnings)) } fn prepare_context( diff --git a/compiler/wasm/src/compile_new.rs b/compiler/wasm/src/compile_new.rs index d6b382f669f..d5f02833521 100644 --- a/compiler/wasm/src/compile_new.rs +++ b/compiler/wasm/src/compile_new.rs @@ -3,11 +3,10 @@ use crate::compile::{ PathToFileSourceMap, }; use crate::errors::{CompileError, JsCompileError}; -use nargo::artifacts::contract::{ContractArtifact, ContractFunctionArtifact}; +use acvm::acir::circuit::ExpressionWidth; use nargo::parse_all; use noirc_driver::{ add_dep, compile_contract, compile_main, prepare_crate, prepare_dependency, CompileOptions, - NOIR_ARTIFACT_VERSION_STRING, }; use noirc_frontend::{ graph::{CrateId, CrateName}, @@ -96,11 +95,14 @@ impl CompilerContext { mut self, program_width: usize, ) -> Result { - let compile_options = CompileOptions::default(); - let np_language = acvm::acir::circuit::ExpressionWidth::Bounded { width: program_width }; + let expression_width = if program_width == 0 { + ExpressionWidth::Unbounded + } else { + ExpressionWidth::Bounded { width: 4 } + }; + let compile_options = CompileOptions { expression_width, ..CompileOptions::default() }; let root_crate_id = *self.context.root_crate_id(); - let compiled_program = compile_main(&mut self.context, root_crate_id, &compile_options, None) .map_err(|errs| { @@ -112,7 +114,8 @@ impl CompilerContext { })? .0; - let optimized_program = nargo::ops::transform_program(compiled_program, np_language); + let optimized_program = + nargo::ops::transform_program(compiled_program, compile_options.expression_width); let warnings = optimized_program.warnings.clone(); Ok(JsCompileProgramResult::new(optimized_program.into(), warnings)) @@ -122,10 +125,14 @@ impl CompilerContext { mut self, program_width: usize, ) -> Result { - let compile_options = CompileOptions::default(); - let np_language = acvm::acir::circuit::ExpressionWidth::Bounded { width: program_width }; - let root_crate_id = *self.context.root_crate_id(); + let expression_width = if program_width == 0 { + ExpressionWidth::Unbounded + } else { + ExpressionWidth::Bounded { width: 4 } + }; + let compile_options = CompileOptions { expression_width, ..CompileOptions::default() }; + let root_crate_id = *self.context.root_crate_id(); let compiled_contract = compile_contract(&mut self.context, root_crate_id, &compile_options) .map_err(|errs| { @@ -137,20 +144,11 @@ impl CompilerContext { })? .0; - let optimized_contract = nargo::ops::transform_contract(compiled_contract, np_language); - - let functions = - optimized_contract.functions.into_iter().map(ContractFunctionArtifact::from).collect(); - - let contract_artifact = ContractArtifact { - noir_version: String::from(NOIR_ARTIFACT_VERSION_STRING), - name: optimized_contract.name, - functions, - events: optimized_contract.events, - file_map: optimized_contract.file_map, - }; + let optimized_contract = + nargo::ops::transform_contract(compiled_contract, compile_options.expression_width); + let warnings = optimized_contract.warnings.clone(); - Ok(JsCompileContractResult::new(contract_artifact, optimized_contract.warnings)) + Ok(JsCompileContractResult::new(optimized_contract.into(), warnings)) } } @@ -166,7 +164,7 @@ pub fn compile_program_( let compiler_context = prepare_compiler_context(entry_point, dependency_graph, file_source_map)?; - let program_width = 3; + let program_width = 4; compiler_context.compile_program(program_width) } @@ -183,7 +181,7 @@ pub fn compile_contract_( let compiler_context = prepare_compiler_context(entry_point, dependency_graph, file_source_map)?; - let program_width = 3; + let program_width = 4; compiler_context.compile_contract(program_width) } diff --git a/compiler/wasm/src/noir/dependencies/github-dependency-resolver.ts b/compiler/wasm/src/noir/dependencies/github-dependency-resolver.ts index 8b08b6f0dd8..39ad0d802fb 100644 --- a/compiler/wasm/src/noir/dependencies/github-dependency-resolver.ts +++ b/compiler/wasm/src/noir/dependencies/github-dependency-resolver.ts @@ -12,10 +12,12 @@ import { LogData } from '../../utils'; */ export class GithubDependencyResolver implements DependencyResolver { #fm: FileManager; + #fetch: typeof fetch; #log; - constructor(fm: FileManager) { + constructor(fm: FileManager, fetcher: typeof fetch) { this.#fm = fm; + this.#fetch = fetcher; this.#log = (msg: string, _data?: LogData) => { console.log(msg); }; @@ -56,7 +58,7 @@ export class GithubDependencyResolver implements DependencyResolver { return localArchivePath; } - const response = await fetch(url, { + const response = await this.#fetch(url, { method: 'GET', }); diff --git a/compiler/wasm/src/noir/noir-wasm-compiler.ts b/compiler/wasm/src/noir/noir-wasm-compiler.ts index 1ec3af1fd65..1fe3c79eae7 100644 --- a/compiler/wasm/src/noir/noir-wasm-compiler.ts +++ b/compiler/wasm/src/noir/noir-wasm-compiler.ts @@ -72,7 +72,8 @@ export class NoirWasmCompiler { const dependencyManager = new DependencyManager( [ new LocalDependencyResolver(fileManager), - new GithubCodeArchiveDependencyResolver(fileManager), + // use node's global fetch + new GithubCodeArchiveDependencyResolver(fileManager, fetch), // TODO support actual Git repositories ], noirPackage, diff --git a/compiler/wasm/src/noir/package.ts b/compiler/wasm/src/noir/package.ts index 81178e6ae96..2856798273a 100644 --- a/compiler/wasm/src/noir/package.ts +++ b/compiler/wasm/src/noir/package.ts @@ -105,7 +105,12 @@ export class Package { handles .filter((handle) => SOURCE_EXTENSIONS.find((ext) => handle.endsWith(ext))) .map(async (file) => { - const suffix = file.replace(this.#srcPath, ''); + // Github deps are directly added to the file manager, which causes them to be missing the absolute path to the source file + // and only include the extraction directory relative to the fm root directory + // This regexp ensures we remove the "real" source path for all dependencies, providing the compiler with what it expects for each source file: + // -> for bin/contract packages + // -> for libs + const suffix = file.replace(new RegExp(`.*${this.#srcPath}`), ''); return { path: this.getType() === 'lib' ? `${alias ? alias : this.#config.package.name}${suffix}` : file, source: (await fm.readFile(file, 'utf-8')).toString(), diff --git a/compiler/wasm/src/types/noir_artifact.ts b/compiler/wasm/src/types/noir_artifact.ts index 832a6ed9bf9..6ecc3ccd56f 100644 --- a/compiler/wasm/src/types/noir_artifact.ts +++ b/compiler/wasm/src/types/noir_artifact.ts @@ -1,50 +1,67 @@ import { Abi, AbiType } from '@noir-lang/types'; /** - * A named type. + * A basic value. */ -export interface ABIVariable { - /** - * The name of the variable. - */ - name: string; +export interface BasicValue { /** - * The type of the variable. + * The kind of the value. */ - type: AbiType; + kind: T; + value: V; +} + +/** + * An exported value. + */ +export type AbiValue = + | BasicValue<'boolean', boolean> + | BasicValue<'string', string> + | BasicValue<'array', AbiValue[]> + | TupleValue + | IntegerValue + | StructValue; + +export type TypedStructFieldValue = { name: string; value: T }; + +export interface StructValue { + kind: 'struct'; + fields: TypedStructFieldValue[]; +} + +export interface TupleValue { + kind: 'tuple'; + fields: AbiValue[]; +} + +export interface IntegerValue extends BasicValue<'integer', string> { + sign: boolean; } /** - * A contract event. + * A named type. */ -export interface EventAbi { +export interface ABIVariable { /** - * The event name. + * The name of the variable. */ name: string; /** - * Fully qualified name of the event. - */ - path: string; - /** - * The fields of the event. + * The type of the variable. */ - fields: ABIVariable[]; + type: AbiType; } -/** The Noir function types. */ -export type NoirFunctionType = 'Open' | 'Secret' | 'Unconstrained'; - /** * The compilation result of an Noir function. */ export interface NoirFunctionEntry { /** The name of the function. */ name: string; - /** The type of the function. */ - function_type: NoirFunctionType; - /** Whether the function is internal. */ - is_internal: boolean; + /** Whether the function is unconstrained. */ + is_unconstrained: boolean; + /** The custom attributes applied to the function. */ + custom_attributes: string[]; /** The ABI of the function. */ abi: Abi; /** The bytecode of the function in base64. */ @@ -63,8 +80,11 @@ export interface ContractArtifact { noir_version: string; /** The functions of the contract. */ functions: NoirFunctionEntry[]; - /** The events of the contract */ - events: EventAbi[]; + + outputs: { + structs: Record; + globals: Record; + }; /** The map of file ID to the source code and path of the file. */ file_map: DebugFileMap; } @@ -131,6 +151,16 @@ export interface DebugInfo { locations: Record; } +/** + * The debug information for a given program. + */ +export interface ProgramDebugInfo { + /** + * An array that maps to each function of a program. + */ + debug_infos: Array; +} + /** * Maps a file ID to its metadata for debugging purposes. */ diff --git a/compiler/wasm/test/compiler/shared/compile.test.ts b/compiler/wasm/test/compiler/shared/compile.test.ts index 52cef14968b..f9e37530cbc 100644 --- a/compiler/wasm/test/compiler/shared/compile.test.ts +++ b/compiler/wasm/test/compiler/shared/compile.test.ts @@ -5,6 +5,7 @@ import { ContractCompilationArtifacts, DebugFileMap, DebugInfo, + ProgramDebugInfo, NoirFunctionEntry, ProgramArtifact, ProgramCompilationArtifacts, @@ -15,7 +16,7 @@ export function shouldCompileProgramIdentically( expect: typeof Expect, timeout = 5000, ) { - it('both nargo and noir_wasm should compile identically', async () => { + it('both nargo and noir_wasm should compile program identically', async () => { // Compile! const { nargoArtifact, noirWasmArtifact } = await compileFn(); @@ -51,7 +52,7 @@ export function shouldCompileContractIdentically( expect: typeof Expect, timeout = 5000, ) { - it('both nargo and noir_wasm should compile identically', async () => { + it('both nargo and noir_wasm should compile contract identically', async () => { // Compile! const { nargoArtifact, noirWasmArtifact } = await compileFn(); @@ -90,7 +91,7 @@ function extractDebugInfos(fns: NoirFunctionEntry[]) { return fns.map((fn) => { const debugSymbols = inflateDebugSymbols(fn.debug_symbols); delete (fn as Partial).debug_symbols; - clearFileIdentifiers(debugSymbols); + clearFileIdentifiersProgram(debugSymbols); return debugSymbols; }); } @@ -113,6 +114,12 @@ function deleteContractDebugMetadata(contract: ContractArtifact) { return [extractDebugInfos(contract.functions), fileMap]; } +function clearFileIdentifiersProgram(debugSymbols: ProgramDebugInfo) { + debugSymbols.debug_infos.map((debug_info) => { + clearFileIdentifiers(debug_info); + }); +} + /** Clears file identifiers from a set of debug symbols. */ function clearFileIdentifiers(debugSymbols: DebugInfo) { for (const loc of Object.values(debugSymbols.locations)) { diff --git a/compiler/wasm/test/dependencies/github-dependency-resolver.test.ts b/compiler/wasm/test/dependencies/github-dependency-resolver.test.ts index e7fae8afe8e..505b2269cd2 100644 --- a/compiler/wasm/test/dependencies/github-dependency-resolver.test.ts +++ b/compiler/wasm/test/dependencies/github-dependency-resolver.test.ts @@ -31,7 +31,7 @@ describe('GithubDependencyResolver', () => { let fetchStub: SinonStub | undefined; beforeEach(() => { - fetchStub = Sinon.stub(globalThis, 'fetch'); + fetchStub = Sinon.stub(); fm = createMemFSFileManager(createFsFromVolume(new Volume()), '/'); libDependency = { @@ -50,16 +50,12 @@ describe('GithubDependencyResolver', () => { }, }); - resolver = new GithubDependencyResolver(fm); + resolver = new GithubDependencyResolver(fm, fetchStub); // cut off outside access fetchStub.onCall(0).throws(new Error()); }); - afterEach(() => { - fetchStub?.restore(); - }); - it("returns null if it can't resolve a dependency", async () => { const dep = await resolver.resolveDependency(pkg, { path: '/lib-c', diff --git a/compiler/wasm/test/fixtures/deps/lib-c/src/lib.nr b/compiler/wasm/test/fixtures/deps/lib-c/src/lib.nr index 5c0b5a621e0..144bcec0532 100644 --- a/compiler/wasm/test/fixtures/deps/lib-c/src/lib.nr +++ b/compiler/wasm/test/fixtures/deps/lib-c/src/lib.nr @@ -1 +1 @@ -mod module; \ No newline at end of file +mod module; diff --git a/compiler/wasm/test/fixtures/deps/lib-c/src/module.nr b/compiler/wasm/test/fixtures/deps/lib-c/src/module.nr index 2746c97edf0..f4ad3bff5c9 100644 --- a/compiler/wasm/test/fixtures/deps/lib-c/src/module.nr +++ b/compiler/wasm/test/fixtures/deps/lib-c/src/module.nr @@ -1 +1 @@ -mod foo; \ No newline at end of file +mod foo; diff --git a/compiler/wasm/test/fixtures/deps/lib-c/src/module/foo.nr b/compiler/wasm/test/fixtures/deps/lib-c/src/module/foo.nr index e0c82fb1960..0376cd4cb87 100644 --- a/compiler/wasm/test/fixtures/deps/lib-c/src/module/foo.nr +++ b/compiler/wasm/test/fixtures/deps/lib-c/src/module/foo.nr @@ -1,3 +1,3 @@ pub fn bar(param: Field) -> Field { - dep::std::hash::pedersen_hash([param]) + dep::std::hash::pedersen_hash([param]) } diff --git a/compiler/wasm/test/fixtures/noir-contract/src/main.nr b/compiler/wasm/test/fixtures/noir-contract/src/main.nr index b980af369cf..fc1dc8a5a17 100644 --- a/compiler/wasm/test/fixtures/noir-contract/src/main.nr +++ b/compiler/wasm/test/fixtures/noir-contract/src/main.nr @@ -5,8 +5,7 @@ contract TestContract { [foo::bar(param), param + pub_param] } - open fn openFunction() -> pub Field { + fn someFunction() -> pub Field { 42 } - } diff --git a/cspell.json b/cspell.json index 23659b39c68..cea0dd7ed38 100644 --- a/cspell.json +++ b/cspell.json @@ -6,6 +6,7 @@ "words": [ "aarch", "acir", + "acirs", "acvm", "aeiou", "appender", @@ -13,8 +14,12 @@ "arithmetization", "arity", "arkworks", + "backpropagate", + "Backpropagation", "barebones", "barretenberg", + "barustenberg", + "bbup", "bincode", "bindgen", "bitand", @@ -34,6 +39,7 @@ "castable", "catmcgee", "Celo", + "chrono", "chumsky", "codegen", "codegenned", @@ -50,6 +56,8 @@ "csat", "curvegroup", "databus", + "debouncer", + "defaultable", "deflater", "deflatten", "deflattened", @@ -57,6 +65,12 @@ "defunctionalization", "defunctionalize", "defunctionalized", + "demonomorphization", + "demonomorphize", + "demonomorphized", + "demonomorphizer", + "demonomorphizes", + "demonomorphizing", "deque", "desugared", "devcontainer", @@ -84,6 +98,7 @@ "hexdigit", "higher-kinded", "Hindley-Milner", + "homomorphic", "idents", "ilog", "impls", @@ -108,6 +123,7 @@ "Maddiaa", "mathbb", "memfs", + "memset", "merkle", "metas", "minreq", @@ -137,6 +153,7 @@ "plonkc", "PLONKish", "pprof", + "preimage", "preprocess", "prettytable", "printstd", @@ -152,6 +169,8 @@ "sdiv", "secp256k1", "secp256r1", + "Secpk", + "Secpr", "signedness", "signorecello", "smol", @@ -170,6 +189,7 @@ "termcolor", "thiserror", "tslog", + "turbofish", "typecheck", "typechecked", "typevar", diff --git a/default.nix b/default.nix deleted file mode 100644 index 9e230590a61..00000000000 --- a/default.nix +++ /dev/null @@ -1,13 +0,0 @@ -let - lock = builtins.fromJSON (builtins.readFile ./flake.lock); - flakeCompatRev = lock.nodes.flake-compat.locked.rev; - flakeCompatHash = lock.nodes.flake-compat.locked.narHash; - flakeCompat = fetchTarball { - url = "https://github.com/edolstra/flake-compat/archive/${flakeCompatRev}.tar.gz"; - sha256 = flakeCompatHash; - }; - compat = import flakeCompat { - src = ./.; - }; -in -compat.defaultNix diff --git a/deny.toml b/deny.toml index 72150f08a3c..db7e53cad24 100644 --- a/deny.toml +++ b/deny.toml @@ -2,11 +2,13 @@ # More documentation for the advisories section can be found here: # https://embarkstudios.github.io/cargo-deny/checks/advisories/cfg.html [advisories] -vulnerability = "deny" -unmaintained = "warn" -unsound = "warn" +version = 2 yanked = "warn" -notice = "warn" + +ignore = [ + "RUSTSEC-2020-0168", # mach unmaintained + "RUSTSEC-2020-0016" # net2 unmaintained +] # This section is considered when running `cargo deny check bans`. # More documentation about the 'bans' section can be found here: @@ -32,9 +34,8 @@ skip = [] skip-tree = [] [licenses] -unlicensed = "deny" +version = 2 confidence-threshold = 0.9 -# copyleft = "deny" # List of explicitly allowed licenses # See https://spdx.org/licenses/ for list of possible licenses @@ -57,7 +58,7 @@ allow = [ # bitmaps 2.1.0, im 15.1.0 "MPL-2.0", # Boost Software License - "BSL-1.0", + "BSL-1.0" ] # Allow 1 or more licenses on a per-crate basis, so that particular licenses @@ -68,6 +69,8 @@ exceptions = [ # https://tldrlegal.com/license/creative-commons-cc0-1.0-universal { allow = ["CC0-1.0"], name = "more-asserts" }, { allow = ["CC0-1.0"], name = "jsonrpc" }, + { allow = ["CC0-1.0"], name = "notify" }, + { allow = ["CC0-1.0"], name = "tiny-keccak" }, { allow = ["MPL-2.0"], name = "sized-chunks" }, { allow = ["MPL-2.0"], name = "webpki-roots" }, diff --git a/docs/.markdownlint.json b/docs/.markdownlint.json new file mode 100644 index 00000000000..40896b4542f --- /dev/null +++ b/docs/.markdownlint.json @@ -0,0 +1,3 @@ +{ + "no-missing-space-atx": false +} diff --git a/docs/docs/getting_started/barretenberg/_category_.json b/docs/docs/getting_started/barretenberg/_category_.json new file mode 100644 index 00000000000..27a8e89228d --- /dev/null +++ b/docs/docs/getting_started/barretenberg/_category_.json @@ -0,0 +1,6 @@ +{ + "position": 1, + "label": "Install Barretenberg", + "collapsible": true, + "collapsed": true +} diff --git a/docs/docs/getting_started/barretenberg/index.md b/docs/docs/getting_started/barretenberg/index.md new file mode 100644 index 00000000000..0102c86770b --- /dev/null +++ b/docs/docs/getting_started/barretenberg/index.md @@ -0,0 +1,47 @@ +--- +title: Barretenberg Installation +description: bb is a command line tool for interacting with Aztec's proving backend Barretenberg. This page is a quick guide on how to install `bb` +keywords: [ + Barretenberg + bb + Installation + Terminal Commands + Version Check + Nightlies + Specific Versions + Branches +] +pagination_next: getting_started/hello_noir/index +--- + +`bb` is the CLI tool for generating and verifying proofs for Noir programs using the Barretenberg proving library. It also allows generating solidity verifier contracts for which you can verify contracts which were constructed using `bb`. + +## Installing `bb` + +Open a terminal on your machine, and write: + +##### macOS (Apple Silicon) + +```bash +curl -L https://raw.githubusercontent.com/AztecProtocol/aztec-packages/master/barretenberg/cpp/installation/install | bash +source ~/.zshrc +bbup -v 0.41.0 +``` + +##### macOS (Intel) + +```bash +curl -L https://raw.githubusercontent.com/AztecProtocol/aztec-packages/master/barretenberg/cpp/installation/install | bash +source ~/.zshrc +bbup -v 0.41.0 +``` + +##### Linux (Bash) + +```bash +curl -L https://raw.githubusercontent.com/AztecProtocol/aztec-packages/master/barretenberg/cpp/installation/install | bash +source ~/.bashrc +bbup -v 0.41.0 +``` + +Now we're ready to start working on [our first Noir program!](../hello_noir/index.md) diff --git a/docs/docs/getting_started/hello_noir/_category_.json b/docs/docs/getting_started/hello_noir/_category_.json index 23b560f610b..976a2325de0 100644 --- a/docs/docs/getting_started/hello_noir/_category_.json +++ b/docs/docs/getting_started/hello_noir/_category_.json @@ -1,5 +1,5 @@ { - "position": 1, + "position": 2, "collapsible": true, "collapsed": true } diff --git a/docs/docs/getting_started/hello_noir/index.md b/docs/docs/getting_started/hello_noir/index.md index 743c4d8d634..1ade3f09ae3 100644 --- a/docs/docs/getting_started/hello_noir/index.md +++ b/docs/docs/getting_started/hello_noir/index.md @@ -90,13 +90,11 @@ cd hello_world nargo check ``` -Two additional files would be generated in your project directory: +A _Prover.toml_ file will be generated in your project directory, to allow specifying input values to the program. -_Prover.toml_ houses input values, and _Verifier.toml_ houses public values. +## Execute Our Noir Program -## Prove Our Noir Program - -Now that the project is set up, we can create a proof of correct execution of our Noir program. +Now that the project is set up, we can execute our Noir program. Fill in input values for execution in the _Prover.toml_ file. For example: @@ -105,37 +103,42 @@ x = "1" y = "2" ``` -Prove the valid execution of your Noir program: +Execute your Noir program: ```sh -nargo prove +nargo execute witness-name ``` -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 witness corresponding to this execution will then be written to the file `./target/witness-name.gz`. -The _Verifier.toml_ file would also be updated with the public values computed from program -execution (in this case the value of `y`): +## Prove Our Noir Program -```toml -y = "0x0000000000000000000000000000000000000000000000000000000000000002" +:::info + +Nargo no longer handles communicating with backends in order to generate proofs. In order to prove/verify your Noir programs, you'll need an installation of [bb](../barretenberg/index.md). + +::: + +Prove the valid execution of your Noir program using `bb`: + +```sh +bb prove -b ./target/hello_world.json -w ./target/witness-name.gz -o ./proof ``` -> **Note:** Values in _Verifier.toml_ are computed as 32-byte hex values. +A new file called `proof` will be generated in your project directory, containing the generated proof for your program. ## Verify Our Noir Program -Once a proof is generated, we can verify correct execution of our Noir program by verifying the -proof file. +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 +bb write_vk -b ./target/hello_world.json -o ./target/vk +bb verify -k ./target/vk -p ./proof ``` -The verification will complete in silence if it is successful. If it fails, it will log the -corresponding error instead. +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! diff --git a/docs/docs/getting_started/hello_noir/project_breakdown.md b/docs/docs/getting_started/hello_noir/project_breakdown.md index 6160a102c6c..29688df148f 100644 --- a/docs/docs/getting_started/hello_noir/project_breakdown.md +++ b/docs/docs/getting_started/hello_noir/project_breakdown.md @@ -1,10 +1,10 @@ --- 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. + Learn about the anatomy of a Nargo project, including the purpose of the Prover TOML + file, and how to prove and verify your program. keywords: - [Nargo, Nargo project, Prover.toml, Verifier.toml, proof verification, private asset transfer] + [Nargo, Nargo project, Prover.toml, proof verification, private asset transfer] sidebar_position: 2 --- @@ -18,7 +18,6 @@ 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_ @@ -28,10 +27,6 @@ file will be generated within it. _Prover.toml_ is used for specifying the input values for executing and proving the program. You can specify `toml` files with different names by using the `--prover-name` or `-p` flags, see the [Prover](#provertoml) section below. Optionally you may specify expected output values for prove-time checking as well. -### Verifier.toml - -_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. @@ -92,20 +87,15 @@ fn main(x : Field, y : Field) { } ``` -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 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 that the condition to be satisfied (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). +As for the program body, `assert` ensures that the condition to be satisfied (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). +The _Prover.toml_ file is a file which the prover uses to supply the inputs to the Noir program (both private and public). In our hello world program the _Prover.toml_ file looks like this: @@ -114,12 +104,9 @@ 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 inequality constraint is due to the line `assert(x != y)`. +When the command `nargo execute` is executed, nargo will execute the Noir program using the inputs specified in `Prover.toml`, aborting if it finds that these do not satisfy the constraints defined by `main`. In this example, `x` and `y` must satisfy the inequality constraint `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. +If an output name is specified such as `nargo execute foo`, the witness generated by this execution will be written to `./target/foo.gz`. This can then be used to generate a proof of the execution. #### Arrays of Structs @@ -155,45 +142,18 @@ 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. +You can specify a `toml` file with a different name to use for execution 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`: +This command looks for proof inputs in the default **Prover.toml** and generates the witness and saves it at `./target/foo.gz`: ```bash -nargo prove +nargo execute foo ``` -This command looks for proof inputs in the custom **OtherProver.toml** and generates proof and saves it at `./proofs/.proof`: +This command looks for proof inputs in the custom **OtherProver.toml** and generates the witness and saves it at `./target/bar.gz`: ```bash -nargo prove -p OtherProver +nargo execute -p OtherProver bar ``` -## 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, usually from external sources, and -verify the validity of the proof against it. - -Take a private asset transfer as an example: - -A person using a browser as the prover would retrieve private inputs locally (e.g. the user's private key) and -public inputs (e.g. the user's encrypted balance on-chain), compute the transfer, generate a proof -and submit it to the verifier smart contract. - -The verifier contract would then draw the user's encrypted balance directly from the blockchain and -verify the proof submitted against it. If the verification passes, additional functions in the -verifier contract could trigger (e.g. approve the asset transfer). - Now that you understand the concepts, you'll probably want some editor feedback while you are writing more complex code. diff --git a/docs/docs/getting_started/installation/other_install_methods.md b/docs/docs/getting_started/installation/other_install_methods.md index a35e34aaf9c..3634723562b 100644 --- a/docs/docs/getting_started/installation/other_install_methods.md +++ b/docs/docs/getting_started/installation/other_install_methods.md @@ -1,6 +1,6 @@ --- -title: Alternative Install Methods -description: There are different ways to install Nargo, the one-stop shop and command-line tool for developing Noir programs. This guide explains other methods that don't rely on noirup, such as compiling from source, installing from binaries, and using WSL for windows +title: Alternative Installations +description: There are different ways to install Nargo, the one-stop shop and command-line tool for developing Noir programs. This guide explains how to specify which version to install when using noirup, and using WSL for windows. keywords: [ Installation Nargo @@ -12,10 +12,7 @@ keywords: [ Linux Nix Direnv - Shell & editor experience - Building and testing Uninstalling Nargo - Noir vs code extension, ] sidebar_position: 1 --- @@ -86,146 +83,7 @@ With `noirup`, you can easily switch between different Nargo versions, including noirup --path ./path/to/local/source ``` -## Alternate Installation Methods (No Longer Recommended) - -While the following methods are available, they are no longer recommended. We advise using noirup for a more efficient and flexible installation experience. - -However, there are other methods for installing Nargo: - -- [Binaries](#option-1-installing-from-binaries) -- [Compiling from Source](#option-2-compile-from-source) -- [WSL for Windows](#option-3-wsl-for-windows) - -### Option 1: Installing from 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.24.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.24.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.24.0/nargo-x86_64-unknown-linux-gnu.tar.gz && \ -tar -xvf $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -C $HOME/.nargo/bin/ && \ -echo -e '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.bashrc && \ -source ~/.bashrc -``` - -#### Step 2 - -Check if the installation was successful by running `nargo --version`. You should get a version number. - -> **macOS:** If you are prompted with an OS alert, right-click and open the _nargo_ executable from -> Finder. Close the new terminal popped up and `nargo` should now be accessible. - -### Option 2: 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 issues 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 clears 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.73.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 3: WSL (for Windows) +## Installation on Windows The default backend for Noir (Barretenberg) doesn't provide Windows binaries at this time. For that reason, Noir cannot be installed natively. However, it is available by using Windows Subsystem for Linux (WSL). @@ -235,20 +93,10 @@ step 2: Follow the [Noirup instructions](#encouraged-installation-method-noirup) ## Uninstalling Nargo -### Noirup - -If you installed Nargo with `noirup` or through directly downloading binaries, you can uninstall Nargo by removing the files in `~/.nargo`, `~/nargo`, and `~/noir_cache`. This ensures that all installed binaries, configurations, and cache related to Nargo are fully removed from your system. +If you installed Nargo with `noirup`, you can uninstall Nargo by removing the files in `~/.nargo`, `~/nargo`, and `~/noir_cache`. This ensures that all installed binaries, configurations, and cache related to Nargo are fully removed from your system. ```bash rm -r ~/.nargo rm -r ~/nargo rm -r ~/noir_cache ``` - -### Nix - -If you installed Nargo with Nix or compiled it from source, you can remove the binary located at `~/.nix-profile/bin/nargo`. - -```bash -rm ~/.nix-profile/bin/nargo -``` diff --git a/docs/docs/getting_started/tooling/noir_codegen.md b/docs/docs/getting_started/tooling/noir_codegen.md new file mode 100644 index 00000000000..1c040585340 --- /dev/null +++ b/docs/docs/getting_started/tooling/noir_codegen.md @@ -0,0 +1,113 @@ +--- +title: Noir Codegen for TypeScript +description: Learn how to use Noir codegen to generate TypeScript bindings +keywords: [Nargo, Noir, compile, TypeScript] +sidebar_position: 3 +--- + +When using TypeScript, it is extra work to interpret Noir program outputs in a type-safe way. Third party libraries may exist for popular Noir programs, but they are either hard to find or unmaintained. + +Now you can generate TypeScript bindings for your Noir programs in two steps: +1. Exporting Noir functions using `nargo export` +2. Using the TypeScript module `noir_codegen` to generate TypeScript binding + +**Note:** you can only export functions from a Noir *library* (not binary or contract program types). + +## Installation + +### Your TypeScript project + +If you don't already have a TypeScript project you can add the module with `yarn` (or `npm`), then initialize it: + +```bash +yarn add typescript -D +npx tsc --init +``` + +### Add TypeScript module - `noir_codegen` + +The following command will add the module to your project's devDependencies: + +```bash +yarn add @noir-lang/noir_codegen -D +``` + +### Nargo library +Make sure you have Nargo, v0.25.0 or greater, installed. If you don't, follow the [installation guide](../installation/index.md). + +If you're in a new project, make a `circuits` folder and create a new Noir library: + +```bash +mkdir circuits && cd circuits +nargo new --lib myNoirLib +``` + +## Usage + +### Export ABI of specified functions + +First go to the `.nr` files in your Noir library, and add the `#[export]` macro to each function that you want to use in TypeScript. + +```rust +#[export] +fn your_function(... +``` + +From your Noir library (where `Nargo.toml` is), run the following command: + +```bash +nargo export +``` + +You will now have an `export` directory with a .json file per exported function. + +You can also specify the directory of Noir programs using `--program-dir`, for example: + +```bash +nargo export --program-dir=./circuits/myNoirLib +``` + +### Generate TypeScript bindings from exported functions + +To use the `noir-codegen` package we added to the TypeScript project: + +```bash +yarn noir-codegen ./export/your_function.json +``` + +This creates an `exports` directory with an `index.ts` file containing all exported functions. + +**Note:** adding `--out-dir` allows you to specify an output dir for your TypeScript bindings to go. Eg: + +```bash +yarn noir-codegen ./export/*.json --out-dir ./path/to/output/dir +``` + +## Example .nr function to .ts output + +Consider a Noir library with this function: + +```rust +#[export] +fn not_equal(x: Field, y: Field) -> bool { + x != y +} +``` + +After the export and codegen steps, you should have an `index.ts` like: + +```typescript +export type Field = string; + + +export const is_equal_circuit: CompiledCircuit = {"abi":{"parameters":[{"name":"x","type":{"kind":"field"},"visibility":"private"},{"name":"y","type":{"kind":"field"},"visibility":"private"}],"param_witnesses":{"x":[{"start":0,"end":1}],"y":[{"start":1,"end":2}]},"return_type":{"abi_type":{"kind":"boolean"},"visibility":"private"},"return_witnesses":[4]},"bytecode":"H4sIAAAAAAAA/7WUMQ7DIAxFQ0Krrr2JjSGYLVcpKrn/CaqqDQN12WK+hPBgmWd/wEyHbF1SS923uhOs3pfoChI+wKXMAXzIKyNj4PB0TFTYc0w5RUjoqeAeEu1wqK0F54RGkWvW44LPzExnlkbMEs4JNZmN8PxS42uHv82T8a3Jeyn2Ks+VLPcO558HmyLMCDOXAXXtpPt4R/Rt9T36ss6dS9HGPx/eG17nGegKBQAA"}; + +export async function is_equal(x: Field, y: Field, foreignCallHandler?: ForeignCallHandler): Promise { + const program = new Noir(is_equal_circuit); + const args: InputMap = { x, y }; + const { returnValue } = await program.execute(args, foreignCallHandler); + return returnValue as boolean; +} +``` + +Now the `is_equal()` function and relevant types are readily available for use in TypeScript. diff --git a/docs/docs/how_to/debugger/_category_.json b/docs/docs/how_to/debugger/_category_.json new file mode 100644 index 00000000000..cc2cbb1c253 --- /dev/null +++ b/docs/docs/how_to/debugger/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Debugging", + "position": 5, + "collapsible": true, + "collapsed": true +} diff --git a/docs/docs/how_to/debugger/debugging_with_the_repl.md b/docs/docs/how_to/debugger/debugging_with_the_repl.md new file mode 100644 index 00000000000..09e5bae68ad --- /dev/null +++ b/docs/docs/how_to/debugger/debugging_with_the_repl.md @@ -0,0 +1,164 @@ +--- +title: Using the REPL Debugger +description: + Step by step guide on how to debug your Noir circuits with the REPL Debugger. +keywords: + [ + Nargo, + Noir CLI, + Noir Debugger, + REPL, + ] +sidebar_position: 1 +--- + +#### Pre-requisites + +In order to use the REPL debugger, first you need to install recent enough versions of Nargo and vscode-noir. + +## Debugging a simple circuit + +Let's debug a simple circuit: + +```rust +fn main(x : Field, y : pub Field) { + assert(x != y); +} +``` + +To start the REPL debugger, using a terminal, go to a Noir circuit's home directory. Then: + +`$ nargo debug` + +You should be seeing this in your terminal: + +``` +[main] Starting debugger +At ~/noir-examples/recursion/circuits/main/src/main.nr:1:9 + 1 -> fn main(x : Field, y : pub Field) { + 2 assert(x != y); + 3 } +> +``` + +The debugger displays the current Noir code location, and it is now waiting for us to drive it. + +Let's first take a look at the available commands. For that we'll use the `help` command. + +``` +> help +Available commands: + + opcodes display ACIR opcodes + into step into to the next opcode + next step until a new source location is reached + out step until a new source location is reached + and the current stack frame is finished + break LOCATION:OpcodeLocation add a breakpoint at an opcode location + over step until a new source location is reached + without diving into function calls + restart restart the debugging session + delete LOCATION:OpcodeLocation delete breakpoint at an opcode location + witness show witness map + witness index:u32 display a single witness from the witness map + witness index:u32 value:String update a witness with the given value + memset index:usize value:String update a memory cell with the given + value + continue continue execution until the end of the + program + vars show variable values available at this point + in execution + stacktrace display the current stack trace + memory show memory (valid when executing unconstrained code) + step step to the next ACIR opcode + +Other commands: + + help Show this help message + quit Quit repl + +``` + +Some commands operate only for unconstrained functions, such as `memory` and `memset`. If you try to use them while execution is paused at an ACIR opcode, the debugger will simply inform you that you are not executing unconstrained code: + +``` +> memory +Unconstrained VM memory not available +> +``` + +Before continuing, we can take a look at the initial witness map: + +``` +> witness +_0 = 1 +_1 = 2 +> +``` + +Cool, since `x==1`, `y==2`, and we want to check that `x != y`, our circuit should succeed. At this point we could intervene and use the witness setter command to change one of the witnesses. Let's set `y=3`, then back to 2, so we don't affect the expected result: + +``` +> witness +_0 = 1 +_1 = 2 +> witness 1 3 +_1 = 3 +> witness +_0 = 1 +_1 = 3 +> witness 1 2 +_1 = 2 +> witness +_0 = 1 +_1 = 2 +> +``` + +Now we can inspect the current state of local variables. For that we use the `vars` command. + +``` +> vars +> +``` + +We currently have no vars in context, since we are at the entry point of the program. Let's use `next` to execute until the next point in the program. + +``` +> vars +> next +At ~/noir-examples/recursion/circuits/main/src/main.nr:1:20 + 1 -> fn main(x : Field, y : pub Field) { + 2 assert(x != y); + 3 } +> vars +x:Field = 0x01 +``` + +As a result of stepping, the variable `x`, whose initial value comes from the witness map, is now in context and returned by `vars`. + +``` +> next + 1 fn main(x : Field, y : pub Field) { + 2 -> assert(x != y); + 3 } +> vars +y:Field = 0x02 +x:Field = 0x01 +``` + +Stepping again we can finally see both variables and their values. And now we can see that the next assertion should succeed. + +Let's continue to the end: + +``` +> continue +(Continuing execution...) +Finished execution +> q +[main] Circuit witness successfully solved +``` + +Upon quitting the debugger after a solved circuit, the resulting circuit witness gets saved, equivalent to what would happen if we had run the same circuit with `nargo execute`. + +We just went through the basics of debugging using Noir REPL debugger. For a comprehensive reference, check out [the reference page](../../reference/debugger/debugger_repl.md). diff --git a/docs/docs/how_to/debugger/debugging_with_vs_code.md b/docs/docs/how_to/debugger/debugging_with_vs_code.md new file mode 100644 index 00000000000..a5858c1a5eb --- /dev/null +++ b/docs/docs/how_to/debugger/debugging_with_vs_code.md @@ -0,0 +1,68 @@ +--- +title: Using the VS Code Debugger +description: + Step by step guide on how to debug your Noir circuits with the VS Code Debugger configuration and features. +keywords: + [ + Nargo, + Noir CLI, + Noir Debugger, + VS Code, + IDE, + ] +sidebar_position: 0 +--- + +This guide will show you how to use VS Code with the vscode-noir extension to debug a Noir project. + +#### Pre-requisites + +- Nargo +- vscode-noir +- A Noir project with a `Nargo.toml`, `Prover.toml` and at least one Noir (`.nr`) containing an entry point function (typically `main`). + +## Running the debugger + +The easiest way to start debugging is to open the file you want to debug, and press `F5`. This will cause the debugger to launch, using your `Prover.toml` file as input. + +You should see something like this: + +![Debugger launched](@site/static/img/debugger/1-started.png) + +Let's inspect the state of the program. For that, we open VS Code's _Debug pane_. Look for this icon: + +![Debug pane icon](@site/static/img/debugger/2-icon.png) + +You will now see two categories of variables: Locals and Witness Map. + +![Debug pane expanded](@site/static/img/debugger/3-debug-pane.png) + +1. **Locals**: variables of your program. At this point in execution this section is empty, but as we step through the code it will get populated by `x`, `result`, `digest`, etc. + +2. **Witness map**: these are initially populated from your project's `Prover.toml` file. In this example, they will be used to populate `x` and `result` at the beginning of the `main` function. + +Most of the time you will probably be focusing mostly on locals, as they represent the high level state of your program. + +You might be interested in inspecting the witness map in case you are trying to solve a really low level issue in the compiler or runtime itself, so this concerns mostly advanced or niche users. + +Let's step through the program, by using the debugger buttons or their corresponding keyboard shortcuts. + +![Debugger buttons](@site/static/img/debugger/4-debugger-buttons.png) + +Now we can see in the variables pane that there's values for `digest`, `result` and `x`. + +![Inspecting locals](@site/static/img/debugger/5-assert.png) + +We can also inspect the values of variables by directly hovering on them on the code. + +![Hover locals](@site/static/img/debugger/6-hover.png) + +Let's set a break point at the `keccak256` function, so we can continue execution up to the point when it's first invoked without having to go one step at a time. + +We just need to click the to the right of the line number 18. Once the breakpoint appears, we can click the `continue` button or use its corresponding keyboard shortcut (`F5` by default). + +![Breakpoint](@site/static/img/debugger/7-break.png) + +Now we are debugging the `keccak256` function, notice the _Call Stack pane_ at the lower right. This lets us inspect the current call stack of our process. + +That covers most of the current debugger functionalities. Check out [the reference](../../reference/debugger/debugger_vscode.md) for more details on how to configure the debugger. \ No newline at end of file diff --git a/docs/docs/how_to/how-to-oracles.md b/docs/docs/how_to/how-to-oracles.md index 0d84d992320..2811968c634 100644 --- a/docs/docs/how_to/how-to-oracles.md +++ b/docs/docs/how_to/how-to-oracles.md @@ -138,8 +138,8 @@ Now, we will add our `getSqrt` method, as expected by the `#[oracle(getSqrt)]` d ```js server.addMethod("getSqrt", async (params) => { - const values = params[0].Array.map(({ inner }) => { - return { inner: `${Math.sqrt(parseInt(inner, 16))}` }; + const values = params[0].Array.map((field) => { + return `${Math.sqrt(parseInt(field, 16))}`; }); return { values: [{ Array: values }] }; }); @@ -147,27 +147,23 @@ server.addMethod("getSqrt", async (params) => { :::tip -Brillig expects an object with an array of values. Each value is an object declaring to be `Single` or `Array` and returning a `inner` property *as a string*. For example: +Brillig expects an object with an array of values. Each value is an object declaring to be `Single` or `Array` and returning a field element *as a string*. For example: ```json -{ "values": [{ "Array": [{ "inner": "1" }, { "inner": "2"}]}]} -{ "values": [{ "Single": { "inner": "1" }}]} -{ "values": [{ "Single": { "inner": "1" }}, { "Array": [{ "inner": "1", { "inner": "2" }}]}]} +{ "values": [{ "Array": ["1", "2"] }]} +{ "values": [{ "Single": "1" }]} +{ "values": [{ "Single": "1" }, { "Array": ["1", "2"] }]} ``` If you're using Typescript, the following types may be helpful in understanding the expected return value and making sure they're easy to follow: ```js -interface Value { - inner: string, -} - interface SingleForeignCallParam { - Single: Value, + Single: string, } interface ArrayForeignCallParam { - Array: Value[], + Array: string[], } type ForeignCallParam = SingleForeignCallParam | ArrayForeignCallParam; @@ -181,7 +177,7 @@ interface ForeignCallResult { ## Step 3 - Usage with Nargo -Using the [`nargo` CLI tool](../getting_started/installation/index.md), you can use oracles in the `nargo test`, `nargo execute` and `nargo prove` commands by passing a value to `--oracle-resolver`. For example: +Using the [`nargo` CLI tool](../getting_started/installation/index.md), you can use oracles in the `nargo test` and `nargo execute` commands by passing a value to `--oracle-resolver`. For example: ```bash nargo test --oracle-resolver http://localhost:5555 @@ -198,7 +194,7 @@ For example, if your Noir program expects the host machine to provide CPU pseudo ```js const foreignCallHandler = (name, inputs) => crypto.randomBytes(16) // etc -await noir.generateFinalProof(inputs, foreignCallHandler) +await noir.execute(inputs, foreignCallHandler) ``` As one can see, in NoirJS, the [`foreignCallHandler`](../reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md) function simply means "a callback function that returns a value of type [`ForeignCallOutput`](../reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md). It doesn't have to be an RPC call like in the case for Nargo. @@ -207,7 +203,7 @@ As one can see, in NoirJS, the [`foreignCallHandler`](../reference/NoirJS/noir_j Does this mean you don't have to write an RPC server like in [Step #2](#step-2---write-an-rpc-server)? -You don't technically have to, but then how would you run `nargo test` or `nargo prove`? To use both `Nargo` and `NoirJS` in your development flow, you will have to write a JSON RPC server. +You don't technically have to, but then how would you run `nargo test`? To use both `Nargo` and `NoirJS` in your development flow, you will have to write a JSON RPC server. ::: @@ -243,9 +239,9 @@ const foreignCallHandler = async (name, input) => { // notice that the "inputs" parameter contains *all* the inputs // in this case we to make the RPC request with the first parameter "numbers", which would be input[0] const oracleReturn = await client.request(name, [ - { Array: input[0].map((i) => ({ inner: i.toString("hex") })) }, + { Array: input[0].map((i) => i.toString("hex")) }, ]); - return [oracleReturn.values[0].Array.map((x) => x.inner)]; + return [oracleReturn.values[0].Array]; }; // the rest of your NoirJS code diff --git a/docs/docs/how_to/how-to-recursion.md b/docs/docs/how_to/how-to-recursion.md index 4c45bb87ae2..aac84e29fac 100644 --- a/docs/docs/how_to/how-to-recursion.md +++ b/docs/docs/how_to/how-to-recursion.md @@ -70,7 +70,7 @@ You can use the [`os.cpus()`](https://nodejs.org/api/os.html#oscpus) object in ` After instantiating the backend, you should also instantiate `noir_js`. We will use it to execute the circuit and get the witness. ```js -const noir = new Noir(circuit, backend) +const noir = new Noir(circuit) const { witness } = noir.execute(input) ``` @@ -155,8 +155,8 @@ const backends = { recursive: new BarretenbergBackend(circuits.recursive) } const noir_programs = { - main: new Noir(circuits.main, backends.main), - recursive: new Noir(circuits.recursive, backends.recursive) + main: new Noir(circuits.main), + recursive: new Noir(circuits.recursive) } ``` @@ -173,7 +173,8 @@ const { proofAsFields, vkAsFields, vkHash } = await backends.main.generateRecurs proof, numPublicInputs, ); -const recursiveProof = await noir_programs.recursive.generateProof(recursiveInputs) +const { witness: recursiveWitness } = await noir_programs.recursive.execute(recursiveInputs) +const recursiveProof = await backends.recursive.generateProof(recursiveWitness); ``` ::: diff --git a/docs/docs/how_to/how-to-solidity-verifier.md b/docs/docs/how_to/how-to-solidity-verifier.md index e3c7c1065da..e6ed9abaec6 100644 --- a/docs/docs/how_to/how-to-solidity-verifier.md +++ b/docs/docs/how_to/how-to-solidity-verifier.md @@ -43,11 +43,19 @@ Generating a Solidity Verifier contract is actually a one-command process. Howev This is by far the most straight-forward step. Just run: ```sh -nargo codegen-verifier +nargo compile ``` -A new `contract` folder would then be generated in your project directory, containing the Solidity -file `plonk_vk.sol`. It can be deployed to any EVM blockchain acting as a verifier smart contract. +This will compile your source code into a Noir build artifact to be stored in the `./target` directory, you can then generate the smart contract using the commands: + +```sh +# Here we pass the path to the newly generated Noir artifact. +bb write_vk -b ./target/.json +bb contract +``` + +replacing `` with the name of your Noir project. A new `contract` folder would then be generated in your project directory, containing the Solidity +file `contract.sol`. It can be deployed to any EVM blockchain acting as a verifier smart contract. :::info @@ -123,11 +131,25 @@ To verify a proof using the Solidity verifier contract, we call the `verify` fun function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool) ``` -When using the default example in the [Hello Noir](../getting_started/hello_noir/index.md) guide, the easiest way to confirm that the verifier contract is doing its job is by calling the `verify` function via remix with the required parameters. For `_proof`, run `nargo prove` and use the string in `proof/.proof` (adding the hex `0x` prefix). We can also copy the public input from `Verifier.toml`, as it will be properly formatted as 32-byte strings: +When using the default example in the [Hello Noir](../getting_started/hello_noir/index.md) guide, the easiest way to confirm that the verifier contract is doing its job is by calling the `verify` function via remix with the required parameters. Note that the public inputs must be passed in separately to the rest of the proof so we must split the proof as returned from `bb`. +First generate a proof with `bb` at the location `./proof` using the steps in [get started](../getting_started/hello_noir/index.md), this proof is in a binary format but we want to convert it into a hex string to pass into Remix, this can be done with the + +```bash +# This value must be changed to match the number of public inputs (including return values!) in your program. +NUM_PUBLIC_INPUTS=1 +PUBLIC_INPUT_BYTES=32*NUM_PUBLIC_INPUTS +HEX_PUBLIC_INPUTS=$(head -c $PUBLIC_INPUT_BYTES ./proof | od -An -v -t x1 | tr -d $' \n') +HEX_PROOF=$(tail -c +$(($PUBLIC_INPUT_BYTES + 1)) ./proof | od -An -v -t x1 | tr -d $' \n') + +echo "Public inputs:" +echo $HEX_PUBLIC_INPUTS + +echo "Proof:" +echo "0x$HEX_PROOF" ``` -0x...... , [0x0000.....02] -``` + +Remix expects that the public inputs will be split into an array of `bytes32` values so `HEX_PUBLIC_INPUTS` needs to be split up into 32 byte chunks which are prefixed with `0x` accordingly. A programmatic example of how the `verify` function is called can be seen in the example zk voting application [here](https://github.com/noir-lang/noir-examples/blob/33e598c257e2402ea3a6b68dd4c5ad492bce1b0a/foundry-voting/src/zkVote.sol#L35): @@ -144,11 +166,9 @@ function castVote(bytes calldata proof, uint proposalId, uint vote, bytes32 null :::info[Return Values] -A circuit doesn't have the concept of a return value. Return values are just syntactic sugar in -Noir. +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. +Under the hood, the return value is passed as an input to the circuit and is checked at the end of the circuit program. For example, if you have Noir program like this: @@ -162,11 +182,11 @@ fn main( ) -> pub Field ``` -the `verify` function will expect the public inputs array (second function parameter) to be of length 3, the two inputs and the return value. Like before, these values are populated in Verifier.toml after running `nargo prove`. +the `verify` function will expect the public inputs array (second function parameter) to be of length 3, the two inputs and the return value. Passing only two inputs will result in an error such as `PUBLIC_INPUT_COUNT_INVALID(3, 2)`. -In this case, the inputs parameter to `verify` would be an array ordered as `[pubkey_x, pubkey_y, return]`. +In this case, the inputs parameter to `verify` would be an array ordered as `[pubkey_x, pubkey_y, return`. ::: @@ -210,7 +230,7 @@ It would be incorrect to say that a Noir proof verification costs any gas at all ## A Note on EVM chains -ZK-SNARK verification depends on some precompiled cryptographic primitives such as Elliptic Curve Pairings (if you like complex math, you can read about EC Pairings [here](https://medium.com/@VitalikButerin/exploring-elliptic-curve-pairings-c73c1864e627)). Not all EVM chains support EC Pairings, notably some of the ZK-EVMs. This means that you won't be able to use the verifier contract in all of them. +Noir proof verification requires the ecMul, ecAdd and ecPairing precompiles. Not all EVM chains support EC Pairings, notably some of the ZK-EVMs. This means that you won't be able to use the verifier contract in all of them. You can find an incomplete list of which EVM chains support these precompiles [here](https://www.evmdiff.com/features?feature=precompiles). For example, chains like `zkSync ERA` and `Polygon zkEVM` do not currently support these precompiles, so proof verification via Solidity verifier contracts won't work. Here's a quick list of EVM chains that have been tested and are known to work: diff --git a/docs/docs/how_to/merkle-proof.mdx b/docs/docs/how_to/merkle-proof.mdx index 34074659ac1..16c425bed76 100644 --- a/docs/docs/how_to/merkle-proof.mdx +++ b/docs/docs/how_to/merkle-proof.mdx @@ -5,6 +5,7 @@ description: merkle tree with a specified root, at a given index. keywords: [merkle proof, merkle membership proof, Noir, rust, hash function, Pedersen, sha256, merkle tree] +sidebar_position: 4 --- Let's walk through an example of a merkle membership proof in Noir that proves that a given leaf is @@ -14,7 +15,7 @@ in a merkle tree. use dep::std; fn main(message : [Field; 62], index : Field, hashpath : [Field; 40], root : Field) { - let leaf = std::hash::hash_to_field(message); + let leaf = std::hash::hash_to_field(message.as_slice()); let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); assert(merkle_root == root); } @@ -27,7 +28,7 @@ random oracle. If only collision resistance is needed, then one can call `std::h instead. ```rust -let leaf = std::hash::hash_to_field(message); +let leaf = std::hash::hash_to_field(message.as_slice()); ``` 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. diff --git a/docs/docs/noir/concepts/control_flow.md b/docs/docs/noir/concepts/control_flow.md index 4ce65236db3..045d3c3a5f5 100644 --- a/docs/docs/noir/concepts/control_flow.md +++ b/docs/docs/noir/concepts/control_flow.md @@ -7,21 +7,6 @@ keywords: [Noir programming language, loops, for loop, if-else statements, Rust sidebar_position: 2 --- -## Loops - -Noir has one kind of loop: the `for` loop. `for` loops allow you to repeat a block of code multiple -times. - -The following block of code between the braces is run 10 times. - -```rust -for i in 0..10 { - // do something -}; -``` - -The index for loops is of type `u64`. - ## If Expressions Noir supports `if-else` statements. The syntax is most similar to Rust's where it is not required @@ -43,3 +28,50 @@ if a == 0 { } assert(x == 2); ``` + +## Loops + +Noir has one kind of loop: the `for` loop. `for` loops allow you to repeat a block of code multiple +times. + +The following block of code between the braces is run 10 times. + +```rust +for i in 0..10 { + // do something +} +``` + +The index for loops is of type `u64`. + +### Break and Continue + +In unconstrained code, `break` and `continue` are also allowed in `for` loops. These are only allowed +in unconstrained code since normal constrained code requires that Noir knows exactly how many iterations +a loop may have. `break` and `continue` can be used like so: + +```rust +for i in 0 .. 10 { + println("Iteration start") + + if i == 2 { + continue; + } + + if i == 5 { + break; + } + + println(i); +} +println("Loop end") +``` + +When used, `break` will end the current loop early and jump to the statement after the for loop. In the example +above, the `break` will stop the loop and jump to the `println("Loop end")`. + +`continue` will stop the current iteration of the loop, and jump to the start of the next iteration. In the example +above, `continue` will jump to `println("Iteration start")` when used. Note that the loop continues as normal after this. +The iteration variable `i` is still increased by one as normal when `continue` is used. + +`break` and `continue` cannot currently be used to jump out of more than a single loop at a time. diff --git a/docs/docs/noir/concepts/data_types/arrays.md b/docs/docs/noir/concepts/data_types/arrays.md index a8bd338e736..efce3e95d32 100644 --- a/docs/docs/noir/concepts/data_types/arrays.md +++ b/docs/docs/noir/concepts/data_types/arrays.md @@ -72,7 +72,7 @@ let element = array[0][0]; ``` However, multidimensional slices are not supported. For example, the following code will error at compile time: ```rust -let slice : [[Field]] = []; +let slice : [[Field]] = &[]; ``` ## Types diff --git a/docs/docs/noir/concepts/data_types/booleans.md b/docs/docs/noir/concepts/data_types/booleans.md index 69826fcd724..3dcfa836814 100644 --- a/docs/docs/noir/concepts/data_types/booleans.md +++ b/docs/docs/noir/concepts/data_types/booleans.md @@ -23,9 +23,6 @@ fn main() { } ``` -> **Note:** When returning a boolean value, it will show up as a value of 1 for `true` and 0 for -> `false` in _Verifier.toml_. - The boolean type is most commonly used in conditionals like `if` expressions and `assert` statements. More about conditionals is covered in the [Control Flow](../control_flow) and [Assert Function](../assert) sections. diff --git a/docs/docs/noir/concepts/data_types/fields.md b/docs/docs/noir/concepts/data_types/fields.md index 99b4aa63549..a10a4810788 100644 --- a/docs/docs/noir/concepts/data_types/fields.md +++ b/docs/docs/noir/concepts/data_types/fields.md @@ -42,7 +42,7 @@ After declaring a Field, you can use these common methods on it: Transforms the field into an array of bits, Little Endian. ```rust -fn to_le_bits(_x : Field, _bit_size: u32) -> [u1; N] +fn to_le_bits(_x : Field, _bit_size: u32) -> [u1] ``` example: @@ -59,7 +59,7 @@ fn main() { Transforms the field into an array of bits, Big Endian. ```rust -fn to_be_bits(_x : Field, _bit_size: u32) -> [u1; N] +fn to_be_bits(_x : Field, _bit_size: u32) -> [u1] ``` example: diff --git a/docs/docs/noir/concepts/data_types/index.md b/docs/docs/noir/concepts/data_types/index.md index 97b3b2cb094..357813c147a 100644 --- a/docs/docs/noir/concepts/data_types/index.md +++ b/docs/docs/noir/concepts/data_types/index.md @@ -79,7 +79,7 @@ fn main() { } ``` -Type aliases can also be used with [generics](@site/docs/noir/concepts/generics.md): +Type aliases can also be used with [generics](../generics.md): ```rust type Id = Size; diff --git a/docs/docs/noir/concepts/data_types/integers.md b/docs/docs/noir/concepts/data_types/integers.md index 4d58d96fed5..c14fffa7174 100644 --- a/docs/docs/noir/concepts/data_types/integers.md +++ b/docs/docs/noir/concepts/data_types/integers.md @@ -5,7 +5,9 @@ keywords: [noir, integer types, methods, examples, arithmetic] sidebar_position: 1 --- -An integer type is a range constrained field type. The Noir frontend supports both unsigned and signed integer types. The allowed sizes are 1, 8, 32 and 64 bits. +An integer type is a range constrained field type. +The Noir frontend supports both unsigned and signed integer types. +The allowed sizes are 1, 8, 16, 32 and 64 bits. :::info @@ -51,7 +53,7 @@ The built-in structure `U128` allows you to use 128-bit unsigned integers almost - You cannot cast between a native integer and `U128` - There is a higher performance cost when using `U128`, compared to a native type. -Conversion between unsigned integer types and U128 are done through the use of `from_integer` and `to_integer` functions. +Conversion between unsigned integer types and U128 are done through the use of `from_integer` and `to_integer` functions. `from_integer` also accepts the `Field` type as input. ```rust fn main() { @@ -113,7 +115,7 @@ y = "1" Would result in: ``` -$ nargo prove +$ nargo execute error: Assertion failed: 'attempt to add with overflow' ┌─ ~/src/main.nr:9:13 │ diff --git a/docs/docs/noir/concepts/data_types/slices.mdx b/docs/docs/noir/concepts/data_types/slices.mdx index 4a6ee816aa2..4eccc677b80 100644 --- a/docs/docs/noir/concepts/data_types/slices.mdx +++ b/docs/docs/noir/concepts/data_types/slices.mdx @@ -15,13 +15,19 @@ A slice is a dynamically-sized view into a sequence of elements. They can be res use dep::std::slice; fn main() -> pub Field { - let mut slice: [Field] = [0; 2]; + let mut slice: [Field] = &[0; 2]; let mut new_slice = slice.push_back(6); new_slice.len() } ``` +To write a slice literal, use a preceeding ampersand as in: `&[0; 2]` or +`&[1, 2, 3]`. + +It is important to note that slices are not references to arrays. In Noir, +`&[..]` is more similar to an immutable, growable vector. + 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 @@ -42,7 +48,7 @@ example: ```rust fn main() -> pub Field { - let mut slice: [Field] = [0; 2]; + let mut slice: [Field] = &[0; 2]; let mut new_slice = slice.push_back(6); new_slice.len() @@ -62,7 +68,7 @@ fn push_front(_self: Self, _elem: T) -> Self Example: ```rust -let mut new_slice: [Field] = []; +let mut new_slice: [Field] = &[]; new_slice = new_slice.push_front(20); assert(new_slice[0] == 20); // returns true ``` @@ -112,7 +118,7 @@ fn append(mut self, other: Self) -> Self Example: ```rust -let append = [1, 2].append([3, 4, 5]); +let append = &[1, 2].append(&[3, 4, 5]); ``` ### insert @@ -145,3 +151,45 @@ Example: ```rust let (remove_slice, removed_elem) = slice.remove(3); ``` + +### len + +Returns the length of a slice + +```rust +fn len(self) -> Field +``` + +Example: + +```rust +fn main() { + let slice = &[42, 42]; + assert(slice.len() == 2); +} +``` + +### as_array + +Converts this slice into an array. + +Make sure to specify the size of the resulting array. +Panics if the resulting array length is different than the slice's length. + +```rust +fn as_array(self) -> [T; N] +``` + +Example: + +```rust +fn main() { + let slice = &[5, 6]; + + // Always specify the length of the resulting array! + let array: [Field; 2] = slice.as_array(); + + assert(array[0] == slice[0]); + assert(array[1] == slice[1]); +} +``` diff --git a/docs/docs/noir/concepts/functions.md b/docs/docs/noir/concepts/functions.md index 48aba9cd058..f656cdfd97a 100644 --- a/docs/docs/noir/concepts/functions.md +++ b/docs/docs/noir/concepts/functions.md @@ -62,7 +62,7 @@ fn main(x : [Field]) // can't compile, has variable size fn main(....// i think you got it by now ``` -Keep in mind [tests](../../getting_started/tooling/testing.md) don't differentiate between `main` and any other function. The following snippet passes tests, but won't compile or prove: +Keep in mind [tests](../../tooling/testing.md) don't differentiate between `main` and any other function. The following snippet passes tests, but won't compile or prove: ```rust fn main(x : [Field]) { @@ -71,7 +71,7 @@ fn main(x : [Field]) { #[test] fn test_one() { - main([1, 2]); + main(&[1, 2]); } ``` @@ -190,7 +190,7 @@ Supported attributes include: - **deprecated**: mark the function as _deprecated_. Calling the function will generate a warning: `warning: use of deprecated function` - **field**: Used to enable conditional compilation of code depending on the field size. See below for more details - **oracle**: mark the function as _oracle_; meaning it is an external unconstrained function, implemented in noir_js. See [Unconstrained](./unconstrained.md) and [NoirJS](../../reference/NoirJS/noir_js/index.md) for more details. -- **test**: mark the function as unit tests. See [Tests](../../getting_started/tooling/testing.md) for more details +- **test**: mark the function as unit tests. See [Tests](../../tooling/testing.md) for more details ### Field Attribute diff --git a/docs/docs/noir/concepts/ops.md b/docs/docs/noir/concepts/ops.md index 60425cb8994..c35c36c38a9 100644 --- a/docs/docs/noir/concepts/ops.md +++ b/docs/docs/noir/concepts/ops.md @@ -30,8 +30,8 @@ sidebar_position: 3 | ^ | 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 | +| \<\< | Left shift an integer by another integer amount | Types must be integer, shift must be u8 | +| >> | Right shift an integer by another integer amount | Types must be integer, shift must be u8 | | ! | 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 | diff --git a/docs/docs/noir/concepts/oracles.md b/docs/docs/noir/concepts/oracles.md index 2e6a6818d48..aa380b5f7b8 100644 --- a/docs/docs/noir/concepts/oracles.md +++ b/docs/docs/noir/concepts/oracles.md @@ -11,6 +11,12 @@ keywords: sidebar_position: 6 --- +:::note + +This is an experimental feature that is not fully documented. If you notice any outdated information or potential improvements to this page, pull request contributions are very welcome: https://github.com/noir-lang/noir + +::: + Noir has support for Oracles via RPC calls. This means Noir will make an RPC call and use the return value for proof generation. Since Oracles are not resolved by Noir, they are [`unconstrained` functions](./unconstrained.md) @@ -21,3 +27,5 @@ You can declare an Oracle through the `#[oracle()]` flag. Example: #[oracle(get_number_sequence)] unconstrained fn get_number_sequence(_size: Field) -> [Field] {} ``` + +The timeout for when using an external RPC oracle resolver can be set with the `NARGO_FOREIGN_CALL_TIMEOUT` environment variable. This timeout is in units of milliseconds. diff --git a/docs/docs/noir/concepts/unconstrained.md b/docs/docs/noir/concepts/unconstrained.md index 89d12c1c971..b8e71fe65f0 100644 --- a/docs/docs/noir/concepts/unconstrained.md +++ b/docs/docs/noir/concepts/unconstrained.md @@ -93,3 +93,7 @@ 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. + +## Break and Continue + +In addition to loops over runtime bounds, `break` and `continue` are also available in unconstrained code. See [break and continue](../concepts/control_flow/#break-and-continue) diff --git a/docs/docs/noir/modules_packages_crates/workspaces.md b/docs/docs/noir/modules_packages_crates/workspaces.md index 67a1dafa372..513497f12bf 100644 --- a/docs/docs/noir/modules_packages_crates/workspaces.md +++ b/docs/docs/noir/modules_packages_crates/workspaces.md @@ -11,16 +11,18 @@ 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 +│ ├── a +│ │ ├── Nargo.toml +│ │ └── Prover.toml +│ │ └── src +│ │ └── main.nr +│ └── b +│ ├── Nargo.toml +│ └── Prover.toml +│ └── src +│ └── main.nr +│ +└── Nargo.toml ``` You can define a workspace in Nargo.toml like so: diff --git a/docs/docs/noir/standard_library/bigint.md b/docs/docs/noir/standard_library/bigint.md new file mode 100644 index 00000000000..54d791b82d3 --- /dev/null +++ b/docs/docs/noir/standard_library/bigint.md @@ -0,0 +1,105 @@ +--- +title: Big Integers +description: How to use big integers from Noir standard library +keywords: + [ + Big Integer, + Noir programming language, + Noir libraries, + ] +--- + +The BigInt module in the standard library exposes some class of integers which do not fit (well) into a Noir native field. It implements modulo arithmetic, modulo a 'big' prime number. + +:::note + +The module can currently be considered as `Field`s with fixed modulo sizes used by a set of elliptic curves, in addition to just the native curve. [More work](https://github.com/noir-lang/noir/issues/510) is needed to achieve arbitrarily sized big integers. + +::: + +Currently 6 classes of integers (i.e 'big' prime numbers) are available in the module, namely: + +- BN254 Fq: Bn254Fq +- BN254 Fr: Bn254Fr +- Secp256k1 Fq: Secpk1Fq +- Secp256k1 Fr: Secpk1Fr +- Secp256r1 Fr: Secpr1Fr +- Secp256r1 Fq: Secpr1Fq + +Where XXX Fq and XXX Fr denote respectively the order of the base and scalar field of the (usual) elliptic curve XXX. +For instance the big integer 'Secpk1Fq' in the standard library refers to integers modulo $2^{256}-2^{32}-977$. + +Feel free to explore the source code for the other primes: + +#include_code big_int_definition noir_stdlib/src/bigint.nr rust + +## Example usage + +A common use-case is when constructing a big integer from its bytes representation, and performing arithmetic operations on it: + +#include_code big_int_example test_programs/execution_success/bigint/src/main.nr rust + +## Methods + +The available operations for each big integer are: + +### from_le_bytes + +Construct a big integer from its little-endian bytes representation. Example: + +```rust + // Construct a big integer from a slice of bytes + let a = Secpk1Fq::from_le_bytes(&[x, y, 0, 45, 2]); + // Construct a big integer from an array of 32 bytes + let a = Secpk1Fq::from_le_bytes_32([1;32]); + ``` + +Sure, here's the formatted version of the remaining methods: + +### to_le_bytes + +Return the little-endian bytes representation of a big integer. Example: + +```rust +let bytes = a.to_le_bytes(); +``` + +### add + +Add two big integers. Example: + +```rust +let sum = a + b; +``` + +### sub + +Subtract two big integers. Example: + +```rust +let difference = a - b; +``` + +### mul + +Multiply two big integers. Example: + +```rust +let product = a * b; +``` + +### div + +Divide two big integers. Note that division is field division and not euclidean division. Example: + +```rust +let quotient = a / b; +``` + +### eq + +Compare two big integers. Example: + +```rust +let are_equal = a == b; +``` diff --git a/docs/docs/noir/standard_library/black_box_fns.md b/docs/docs/noir/standard_library/black_box_fns.md index eae8744abf0..eeead580969 100644 --- a/docs/docs/noir/standard_library/black_box_fns.md +++ b/docs/docs/noir/standard_library/black_box_fns.md @@ -12,18 +12,19 @@ The ACVM spec defines a set of blackbox functions which backends will be expecte Here is a list of the current black box functions: -- [SHA256](./cryptographic_primitives/hashes#sha256) -- [Schnorr signature verification](./cryptographic_primitives/schnorr) -- [Blake2s](./cryptographic_primitives/hashes#blake2s) -- [Blake3](./cryptographic_primitives/hashes#blake3) -- [Pedersen Hash](./cryptographic_primitives/hashes#pedersen_hash) -- [Pedersen Commitment](./cryptographic_primitives/hashes#pedersen_commitment) -- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification) -- [Fixed base scalar multiplication](./cryptographic_primitives/scalar) +- [AES128](./cryptographic_primitives/ciphers.mdx#aes128) +- [SHA256](./cryptographic_primitives/hashes.mdx#sha256) +- [Schnorr signature verification](./cryptographic_primitives/schnorr.mdx) +- [Blake2s](./cryptographic_primitives/hashes.mdx#blake2s) +- [Blake3](./cryptographic_primitives/hashes.mdx#blake3) +- [Pedersen Hash](./cryptographic_primitives/hashes.mdx#pedersen_hash) +- [Pedersen Commitment](./cryptographic_primitives/hashes.mdx#pedersen_commitment) +- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification.mdx) +- [Embedded curve operations (MSM, addition, ...)](./cryptographic_primitives/embedded_curve_ops.mdx) - AND - XOR - RANGE -- [Keccak256](./cryptographic_primitives/hashes#keccak256) +- [Keccak256](./cryptographic_primitives/hashes.mdx#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. diff --git a/docs/docs/noir/standard_library/containers/boundedvec.md b/docs/docs/noir/standard_library/containers/boundedvec.md new file mode 100644 index 00000000000..ccce62562f8 --- /dev/null +++ b/docs/docs/noir/standard_library/containers/boundedvec.md @@ -0,0 +1,224 @@ +--- +title: Bounded Vectors +keywords: [noir, vector, bounded vector, slice] +sidebar_position: 1 +--- + +A `BoundedVec` is a growable storage similar to a `Vec` except that it +is bounded with a maximum possible length. Unlike `Vec`, `BoundedVec` is not implemented +via slices and thus is not subject to the same restrictions slices are (notably, nested +slices - and thus nested vectors as well - are disallowed). + +Since a BoundedVec is backed by a normal array under the hood, growing the BoundedVec by +pushing an additional element is also more efficient - the length only needs to be increased +by one. + +For these reasons `BoundedVec` should generally be preferred over `Vec` when there +is a reasonable maximum bound that can be placed on the vector. + +Example: + +```rust +let mut vector: BoundedVec = BoundedVec::new(); +for i in 0..5 { + vector.push(i); +} +assert(vector.len() == 5); +assert(vector.max_len() == 10); +``` + +## Methods + +### new + +```rust +pub fn new() -> Self +``` + +Creates a new, empty vector of length zero. + +Since this container is backed by an array internally, it still needs an initial value +to give each element. To resolve this, each element is zeroed internally. This value +is guaranteed to be inaccessible unless `get_unchecked` is used. + +Example: + +```rust +let empty_vector: BoundedVec = BoundedVec::new(); +assert(empty_vector.len() == 0); +``` + +Note that whenever calling `new` the maximum length of the vector should always be specified +via a type signature: + +#include_code new_example test_programs/noir_test_success/bounded_vec/src/main.nr rust + +This defaulting of `MaxLen` (and numeric generics in general) to zero may change in future noir versions +but for now make sure to use type annotations when using bounded vectors. Otherwise, you will receive a constraint failure at runtime when the vec is pushed to. + +### get + +```rust +pub fn get(mut self: Self, index: u64) -> T { +``` + +Retrieves an element from the vector at the given index, starting from zero. + +If the given index is equal to or greater than the length of the vector, this +will issue a constraint failure. + +Example: + +```rust +fn foo(v: BoundedVec) { + let first = v.get(0); + let last = v.get(v.len() - 1); + assert(first != last); +} +``` + +### get_unchecked + +```rust +pub fn get_unchecked(mut self: Self, index: u64) -> T { +``` + +Retrieves an element from the vector at the given index, starting from zero, without +performing a bounds check. + +Since this function does not perform a bounds check on length before accessing the element, +it is unsafe! Use at your own risk! + +Example: + +#include_code get_unchecked_example test_programs/noir_test_success/bounded_vec/src/main.nr rust + + +### push + +```rust +pub fn push(&mut self, elem: T) { +``` + +Pushes an element to the end of the vector. This increases the length +of the vector by one. + +Panics if the new length of the vector will be greater than the max length. + +Example: + +#include_code bounded-vec-push-example test_programs/noir_test_success/bounded_vec/src/main.nr rust + +### pop + +```rust +pub fn pop(&mut self) -> T +``` + +Pops the element at the end of the vector. This will decrease the length +of the vector by one. + +Panics if the vector is empty. + +Example: + +#include_code bounded-vec-pop-example test_programs/noir_test_success/bounded_vec/src/main.nr rust + +### len + +```rust +pub fn len(self) -> u64 { +``` + +Returns the current length of this vector + +Example: + +#include_code bounded-vec-len-example test_programs/noir_test_success/bounded_vec/src/main.nr rust + +### max_len + +```rust +pub fn max_len(_self: BoundedVec) -> u64 { +``` + +Returns the maximum length of this vector. This is always +equal to the `MaxLen` parameter this vector was initialized with. + +Example: + +#include_code bounded-vec-max-len-example test_programs/noir_test_success/bounded_vec/src/main.nr rust + +### storage + +```rust +pub fn storage(self) -> [T; MaxLen] { +``` + +Returns the internal array within this vector. +Since arrays in Noir are immutable, mutating the returned storage array will not mutate +the storage held internally by this vector. + +Note that uninitialized elements may be zeroed out! + +Example: + +#include_code bounded-vec-storage-example test_programs/noir_test_success/bounded_vec/src/main.nr rust + +### extend_from_array + +```rust +pub fn extend_from_array(&mut self, array: [T; Len]) +``` + +Pushes each element from the given array to this vector. + +Panics if pushing each element would cause the length of this vector +to exceed the maximum length. + +Example: + +#include_code bounded-vec-extend-from-array-example test_programs/noir_test_success/bounded_vec/src/main.nr rust + +### extend_from_bounded_vec + +```rust +pub fn extend_from_bounded_vec(&mut self, vec: BoundedVec) +``` + +Pushes each element from the other vector to this vector. The length of +the other vector is left unchanged. + +Panics if pushing each element would cause the length of this vector +to exceed the maximum length. + +Example: + +#include_code bounded-vec-extend-from-bounded-vec-example test_programs/noir_test_success/bounded_vec/src/main.nr rust + +### from_array + +```rust +pub fn from_array(array: [T; Len]) -> Self +``` + +Creates a new vector, populating it with values derived from an array input. +The maximum length of the vector is determined based on the type signature. + +Example: +```rust +let bounded_vec: BoundedVec = BoundedVec::from_array([1, 2, 3]) +``` + +### any + +```rust +pub fn any(self, predicate: fn[Env](T) -> bool) -> bool +``` + +Returns true if the given predicate returns true for any element +in this vector. + +Example: + +#include_code bounded-vec-any-example test_programs/noir_test_success/bounded_vec/src/main.nr rust diff --git a/docs/docs/noir/standard_library/containers/hashmap.md b/docs/docs/noir/standard_library/containers/hashmap.md new file mode 100644 index 00000000000..2b9f4895722 --- /dev/null +++ b/docs/docs/noir/standard_library/containers/hashmap.md @@ -0,0 +1,271 @@ +--- +title: HashMap +keywords: [noir, map, hash, hashmap] +sidebar_position: 1 +--- + +`HashMap` is used to efficiently store and look up key-value pairs. + +`HashMap` is a bounded type which can store anywhere from zero to `MaxLen` total elements. +Note that due to hash collisions, the actual maximum number of elements stored by any particular +hashmap is likely lower than `MaxLen`. This is true even with cryptographic hash functions since +every hash value will be performed modulo `MaxLen`. + +When creating `HashMap`s, the `MaxLen` generic should always be specified if it is not already +known. Otherwise, the compiler may infer a different value for `MaxLen` (such as zero), which +will likely change the result of the program. This behavior is set to become an error in future +versions instead. + +Example: + +```rust +// Create a mapping from Fields to u32s with a maximum length of 12 +// using a poseidon2 hasher +use dep::std::hash::poseidon2::Poseidon2Hasher; +let mut map: HashMap> = HashMap::default(); + +map.insert(1, 2); +map.insert(3, 4); + +let two = map.get(1).unwrap(); +``` + +## Methods + +### default + +#include_code default noir_stdlib/src/collections/map.nr rust + +Creates a fresh, empty HashMap. + +When using this function, always make sure to specify the maximum size of the hash map. + +This is the same `default` from the `Default` implementation given further below. It is +repeated here for convenience since it is the recommended way to create a hashmap. + +Example: + +#include_code default_example test_programs/execution_success/hashmap/src/main.nr rust + +Because `HashMap` has so many generic arguments that are likely to be the same throughout +your program, it may be helpful to create a type alias: + +#include_code type_alias test_programs/execution_success/hashmap/src/main.nr rust + +### with_hasher + +#include_code with_hasher noir_stdlib/src/collections/map.nr rust + +Creates a hashmap with an existing `BuildHasher`. This can be used to ensure multiple +hashmaps are created with the same hasher instance. + +Example: + +#include_code with_hasher_example test_programs/execution_success/hashmap/src/main.nr rust + +### get + +#include_code get noir_stdlib/src/collections/map.nr rust + +Retrieves a value from the hashmap, returning `Option::none()` if it was not found. + +Example: + +#include_code get_example test_programs/execution_success/hashmap/src/main.nr rust + +### insert + +#include_code insert noir_stdlib/src/collections/map.nr rust + +Inserts a new key-value pair into the map. If the key was already in the map, its +previous value will be overridden with the newly provided one. + +Example: + +#include_code insert_example test_programs/execution_success/hashmap/src/main.nr rust + +### remove + +#include_code remove noir_stdlib/src/collections/map.nr rust + +Removes the given key-value pair from the map. If the key was not already present +in the map, this does nothing. + +Example: + +#include_code remove_example test_programs/execution_success/hashmap/src/main.nr rust + +### is_empty + +#include_code is_empty noir_stdlib/src/collections/map.nr rust + +True if the length of the hash map is empty. + +Example: + +#include_code is_empty_example test_programs/execution_success/hashmap/src/main.nr rust + +### len + +#include_code len noir_stdlib/src/collections/map.nr rust + +Returns the current length of this hash map. + +Example: + +#include_code len_example test_programs/execution_success/hashmap/src/main.nr rust + +### capacity + +#include_code capacity noir_stdlib/src/collections/map.nr rust + +Returns the maximum capacity of this hashmap. This is always equal to the capacity +specified in the hashmap's type. + +Unlike hashmaps in general purpose programming languages, hashmaps in Noir have a +static capacity that does not increase as the map grows larger. Thus, this capacity +is also the maximum possible element count that can be inserted into the hashmap. +Due to hash collisions (modulo the hashmap length), it is likely the actual maximum +element count will be lower than the full capacity. + +Example: + +#include_code capacity_example test_programs/execution_success/hashmap/src/main.nr rust + +### clear + +#include_code clear noir_stdlib/src/collections/map.nr rust + +Clears the hashmap, removing all key-value pairs from it. + +Example: + +#include_code clear_example test_programs/execution_success/hashmap/src/main.nr rust + +### contains_key + +#include_code contains_key noir_stdlib/src/collections/map.nr rust + +True if the hashmap contains the given key. Unlike `get`, this will not also return +the value associated with the key. + +Example: + +#include_code contains_key_example test_programs/execution_success/hashmap/src/main.nr rust + +### entries + +#include_code entries noir_stdlib/src/collections/map.nr rust + +Returns a vector of each key-value pair present in the hashmap. + +The length of the returned vector is always equal to the length of the hashmap. + +Example: + +#include_code entries_example test_programs/execution_success/hashmap/src/main.nr rust + +### keys + +#include_code keys noir_stdlib/src/collections/map.nr rust + +Returns a vector of each key present in the hashmap. + +The length of the returned vector is always equal to the length of the hashmap. + +Example: + +#include_code keys_example test_programs/execution_success/hashmap/src/main.nr rust + +### values + +#include_code values noir_stdlib/src/collections/map.nr rust + +Returns a vector of each value present in the hashmap. + +The length of the returned vector is always equal to the length of the hashmap. + +Example: + +#include_code values_example test_programs/execution_success/hashmap/src/main.nr rust + +### iter_mut + +#include_code iter_mut noir_stdlib/src/collections/map.nr rust + +Iterates through each key-value pair of the HashMap, setting each key-value pair to the +result returned from the given function. + +Note that since keys can be mutated, the HashMap needs to be rebuilt as it is iterated +through. If this is not desired, use `iter_values_mut` if only values need to be mutated, +or `entries` if neither keys nor values need to be mutated. + +The iteration order is left unspecified. As a result, if two keys are mutated to become +equal, which of the two values that will be present for the key in the resulting map is also unspecified. + +Example: + +#include_code iter_mut_example test_programs/execution_success/hashmap/src/main.nr rust + +### iter_keys_mut + +#include_code iter_keys_mut noir_stdlib/src/collections/map.nr rust + +Iterates through the HashMap, mutating each key to the result returned from +the given function. + +Note that since keys can be mutated, the HashMap needs to be rebuilt as it is iterated +through. If only iteration is desired and the keys are not intended to be mutated, +prefer using `entries` instead. + +The iteration order is left unspecified. As a result, if two keys are mutated to become +equal, which of the two values that will be present for the key in the resulting map is also unspecified. + +Example: + +#include_code iter_keys_mut_example test_programs/execution_success/hashmap/src/main.nr rust + +### iter_values_mut + +#include_code iter_values_mut noir_stdlib/src/collections/map.nr rust + +Iterates through the HashMap, applying the given function to each value and mutating the +value to equal the result. This function is more efficient than `iter_mut` and `iter_keys_mut` +because the keys are untouched and the underlying hashmap thus does not need to be reordered. + +Example: + +#include_code iter_values_mut_example test_programs/execution_success/hashmap/src/main.nr rust + +### retain + +#include_code retain noir_stdlib/src/collections/map.nr rust + +Retains only the key-value pairs for which the given function returns true. +Any key-value pairs for which the function returns false will be removed from the map. + +Example: + +#include_code retain_example test_programs/execution_success/hashmap/src/main.nr rust + +## Trait Implementations + +### default + +#include_code default noir_stdlib/src/collections/map.nr rust + +Constructs an empty HashMap. + +Example: + +#include_code default_example test_programs/execution_success/hashmap/src/main.nr rust + +### eq + +#include_code eq noir_stdlib/src/collections/map.nr rust + +Checks if two HashMaps are equal. + +Example: + +#include_code eq_example test_programs/execution_success/hashmap/src/main.nr rust diff --git a/docs/docs/noir/standard_library/containers/index.md b/docs/docs/noir/standard_library/containers/index.md new file mode 100644 index 00000000000..ea84c6d5c21 --- /dev/null +++ b/docs/docs/noir/standard_library/containers/index.md @@ -0,0 +1,5 @@ +--- +title: Containers +description: Container types provided by Noir's standard library for storing and retrieving data +keywords: [containers, data types, vec, hashmap] +--- diff --git a/docs/docs/noir/standard_library/containers/vec.mdx b/docs/docs/noir/standard_library/containers/vec.mdx index 1954f05bc76..fcfd7e07aa0 100644 --- a/docs/docs/noir/standard_library/containers/vec.mdx +++ b/docs/docs/noir/standard_library/containers/vec.mdx @@ -49,8 +49,8 @@ pub fn from_slice(slice: [T]) -> Self Example: ```rust -let arr: [Field] = [1, 2, 3]; -let vector_from_slice = Vec::from_slice(arr); +let slice: [Field] = &[1, 2, 3]; +let vector_from_slice = Vec::from_slice(slice); assert(vector_from_slice.len() == 3); ``` @@ -80,7 +80,7 @@ pub fn get(self, index: Field) -> T Example: ```rust -let vector: Vec = Vec::from_slice([10, 20, 30]); +let vector: Vec = Vec::from_slice(&[10, 20, 30]); assert(vector.get(1) == 20); ``` @@ -111,7 +111,7 @@ pub fn pop(&mut self) -> T Example: ```rust -let mut vector = Vec::from_slice([10, 20]); +let mut vector = Vec::from_slice(&[10, 20]); let popped_elem = vector.pop(); assert(popped_elem == 20); assert(vector.len() == 1); @@ -128,7 +128,7 @@ pub fn insert(&mut self, index: Field, elem: T) Example: ```rust -let mut vector = Vec::from_slice([10, 30]); +let mut vector = Vec::from_slice(&[10, 30]); vector.insert(1, 20); assert(vector.get(1) == 20); ``` @@ -144,7 +144,7 @@ pub fn remove(&mut self, index: Field) -> T Example: ```rust -let mut vector = Vec::from_slice([10, 20, 30]); +let mut vector = Vec::from_slice(&[10, 20, 30]); let removed_elem = vector.remove(1); assert(removed_elem == 20); assert(vector.len() == 2); diff --git a/docs/docs/noir/standard_library/cryptographic_primitives/ciphers.mdx b/docs/docs/noir/standard_library/cryptographic_primitives/ciphers.mdx new file mode 100644 index 00000000000..0103791d2e4 --- /dev/null +++ b/docs/docs/noir/standard_library/cryptographic_primitives/ciphers.mdx @@ -0,0 +1,28 @@ +--- +title: Ciphers +description: + Learn about the implemented ciphers ready to use for any Noir project +keywords: + [ciphers, Noir project, aes128, encrypt] +sidebar_position: 0 +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +## aes128 + +Given a plaintext as an array of bytes, returns the corresponding aes128 ciphertext (CBC mode). Input padding is automatically performed using PKCS#7, so that the output length is `input.len() + (16 - input.len() % 16)`. + +#include_code aes128 noir_stdlib/src/aes128.nr rust + +```rust +fn main() { + let input: [u8; 4] = [0, 12, 3, 15] // Random bytes, will be padded to 16 bytes. + let iv: [u8; 16] = [0; 16]; // Initialisation vector + let key: [u8; 16] = [0; 16] // AES key + let ciphertext = std::aes128::aes128_encrypt(inputs.as_bytes(), iv.as_bytes(), key.as_bytes()); // In this case, the output length will be 16 bytes. +} +``` + + + \ No newline at end of file diff --git a/docs/docs/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx b/docs/docs/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx index d67a1ac94df..6787c9f46a1 100644 --- a/docs/docs/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx +++ b/docs/docs/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx @@ -11,7 +11,8 @@ Noir supports ECDSA signatures verification over the secp256k1 and secp256r1 cur ## ecdsa_secp256k1::verify_signature -Verifier for ECDSA Secp256k1 signatures +Verifier for ECDSA Secp256k1 signatures. +See ecdsa_secp256k1::verify_signature_slice for a version that accepts slices directly. #include_code ecdsa_secp256k1 noir_stdlib/src/ecdsa_secp256k1.nr rust @@ -24,9 +25,20 @@ fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], sign } ``` + + +## ecdsa_secp256k1::verify_signature_slice + +Verifier for ECDSA Secp256k1 signatures where the message is a slice. + +#include_code ecdsa_secp256k1_slice noir_stdlib/src/ecdsa_secp256k1.nr rust + + + ## ecdsa_secp256r1::verify_signature -Verifier for ECDSA Secp256r1 signatures +Verifier for ECDSA Secp256r1 signatures. +See ecdsa_secp256r1::verify_signature_slice for a version that accepts slices directly. #include_code ecdsa_secp256r1 noir_stdlib/src/ecdsa_secp256r1.nr rust @@ -40,3 +52,11 @@ fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], sign ``` + +## ecdsa_secp256r1::verify_signature + +Verifier for ECDSA Secp256r1 signatures where the message is a slice. + +#include_code ecdsa_secp256r1_slice noir_stdlib/src/ecdsa_secp256r1.nr rust + + diff --git a/docs/docs/noir/standard_library/cryptographic_primitives/eddsa.mdx b/docs/docs/noir/standard_library/cryptographic_primitives/eddsa.mdx index a9c10da6c06..789d26ce426 100644 --- a/docs/docs/noir/standard_library/cryptographic_primitives/eddsa.mdx +++ b/docs/docs/noir/standard_library/cryptographic_primitives/eddsa.mdx @@ -15,4 +15,23 @@ Verifier for EdDSA signatures 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 ``` +It is also possible to specify the hash algorithm used for the signature by using the `eddsa_verify` function by passing a type implementing the Hasher trait with the turbofish operator. +For instance, if you want to use Poseidon2 instead, you can do the following: +```rust +use dep::std::hash::poseidon2::Poseidon2Hasher; + +eddsa_verify::(pub_key_a.x, pub_key_a.y, s_a, r8_a.x, r8_a.y, msg); +``` + + +## eddsa::eddsa_to_pub + +Private to public key conversion. + +Returns `(pub_key_x, pub_key_y)` + +```rust +fn eddsa_to_pub(secret : Field) -> (Field, Field) +``` + diff --git a/docs/docs/noir/standard_library/cryptographic_primitives/embedded_curve_ops.mdx b/docs/docs/noir/standard_library/cryptographic_primitives/embedded_curve_ops.mdx new file mode 100644 index 00000000000..f1122fc37d5 --- /dev/null +++ b/docs/docs/noir/standard_library/cryptographic_primitives/embedded_curve_ops.mdx @@ -0,0 +1,77 @@ +--- +title: Scalar multiplication +description: See how you can perform scalar multiplication in Noir +keywords: [cryptographic primitives, Noir project, scalar multiplication] +sidebar_position: 1 +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +The following functions perform operations over the embedded curve whose coordinates are defined by the configured noir field. +For the BN254 scalar field, this is BabyJubJub or Grumpkin. + +:::note +Suffixes `_low` and `_high` denote low and high limbs of a scalar. +::: + +## embedded_curve_ops::multi_scalar_mul + +Performs multi scalar multiplication over the embedded curve. +The function accepts arbitrary amount of point-scalar pairs on the input, it multiplies the individual pairs over +the curve and returns a sum of the resulting points. + +Points represented as x and y coordinates [x1, y1, x2, y2, ...], scalars as low and high limbs [low1, high1, low2, high2, ...]. + +#include_code multi_scalar_mul noir_stdlib/src/embedded_curve_ops.nr rust + +example + +```rust +fn main(point_x: Field, point_y: Field, scalar_low: Field, scalar_high: Field) { + let point = std::embedded_curve_ops::multi_scalar_mul([point_x, point_y], [scalar_low, scalar_high]); + println(point); +} +``` + +## embedded_curve_ops::fixed_base_scalar_mul + +Performs fixed base scalar multiplication over the embedded curve (multiplies input scalar with a generator point). +The function accepts a single scalar on the input represented as 2 fields. + +#include_code fixed_base_scalar_mul noir_stdlib/src/embedded_curve_ops.nr rust + +example + +```rust +fn main(scalar_low: Field, scalar_high: Field) { + let point = std::embedded_curve_ops::fixed_base_scalar_mul(scalar_low, scalar_high); + println(point); +} +``` + +## embedded_curve_ops::embedded_curve_add + +Adds two points on the embedded curve. +This function takes two `EmbeddedCurvePoint` structures as parameters, representing points on the curve, and returns a new `EmbeddedCurvePoint` structure that represents their sum. + +### Parameters: +- `point1` (`EmbeddedCurvePoint`): The first point to add. +- `point2` (`EmbeddedCurvePoint`): The second point to add. + +### Returns: +- `EmbeddedCurvePoint`: The resulting point after the addition of `point1` and `point2`. + +#include_code embedded_curve_add noir_stdlib/src/embedded_curve_ops.nr rust + +example + +```rust +fn main() { + let point1 = EmbeddedCurvePoint { x: 1, y: 2 }; + let point2 = EmbeddedCurvePoint { x: 3, y: 4 }; + let result = std::embedded_curve_ops::embedded_curve_add(point1, point2); + println!("Resulting Point: ({}, {})", result.x, result.y); +} +``` + + diff --git a/docs/docs/noir/standard_library/cryptographic_primitives/hashes.mdx b/docs/docs/noir/standard_library/cryptographic_primitives/hashes.mdx index b9239f822e8..efa52b2c3f2 100644 --- a/docs/docs/noir/standard_library/cryptographic_primitives/hashes.mdx +++ b/docs/docs/noir/standard_library/cryptographic_primitives/hashes.mdx @@ -13,18 +13,21 @@ import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; ## sha256 Given an array of bytes, returns the resulting sha256 hash. +Specify a message_size to hash only the first `message_size` bytes of the input. #include_code sha256 noir_stdlib/src/hash.nr rust example: +#include_code sha256_var test_programs/execution_success/sha256/src/main.nr rust ```rust fn main() { let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::sha256(x); + let hash = std::sha256::sha256_var(x, 4); } ``` + ## blake2s @@ -73,7 +76,6 @@ example: - ## pedersen_commitment Given an array of Fields, returns the Pedersen commitment. @@ -88,9 +90,9 @@ example: ## 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. +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. #include_code keccak256 noir_stdlib/src/hash.nr rust @@ -156,7 +158,7 @@ fn main() { ## hash_to_field ```rust -fn hash_to_field(_input : [Field; N]) -> Field {} +fn hash_to_field(_input : [Field]) -> Field {} ``` Calculates the `blake2s` hash of the inputs and returns the hash modulo the field modulus to return diff --git a/docs/docs/noir/standard_library/cryptographic_primitives/schnorr.mdx b/docs/docs/noir/standard_library/cryptographic_primitives/schnorr.mdx index 0e0c358c6e1..2c9eb18cd34 100644 --- a/docs/docs/noir/standard_library/cryptographic_primitives/schnorr.mdx +++ b/docs/docs/noir/standard_library/cryptographic_primitives/schnorr.mdx @@ -10,6 +10,7 @@ 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). +See schnorr::verify_signature_slice for a version that works directly on slices. #include_code schnorr_verify noir_stdlib/src/schnorr.nr rust @@ -34,3 +35,12 @@ const signature = Array.from( ``` + +## schnorr::verify_signature_slice + +Verifier for Schnorr signatures over the embedded curve (for BN254 it is Grumpkin) +where the message is a slice. + +#include_code schnorr_verify_slice noir_stdlib/src/schnorr.nr rust + + diff --git a/docs/docs/noir/standard_library/is_unconstrained.md b/docs/docs/noir/standard_library/is_unconstrained.md new file mode 100644 index 00000000000..bb157e719dc --- /dev/null +++ b/docs/docs/noir/standard_library/is_unconstrained.md @@ -0,0 +1,59 @@ +--- +title: Is Unconstrained Function +description: + The is_unconstrained function returns wether the context at that point of the program is unconstrained or not. +keywords: + [ + unconstrained + ] +--- + +It's very common for functions in circuits to take unconstrained hints of an expensive computation and then verify it. This is done by running the hint in an unconstrained context and then verifying the result in a constrained context. + +When a function is marked as unconstrained, any subsequent functions that it calls will also be run in an unconstrained context. However, if we are implementing a library function, other users might call it within an unconstrained context or a constrained one. Generally, in an unconstrained context we prefer just computing the result instead of taking a hint of it and verifying it, since that'd mean doing the same computation twice: + +```rust + +fn my_expensive_computation(){ + ... +} + +unconstrained fn my_expensive_computation_hint(){ + my_expensive_computation() +} + +pub fn external_interface(){ + my_expensive_computation_hint(); + // verify my_expensive_computation: If external_interface is called from unconstrained, this is redundant + ... +} + +``` + +In order to improve the performance in an unconstrained context you can use the function at `std::runtime::is_unconstrained() -> bool`: + + +```rust +use dep::std::runtime::is_unconstrained; + +fn my_expensive_computation(){ + ... +} + +unconstrained fn my_expensive_computation_hint(){ + my_expensive_computation() +} + +pub fn external_interface(){ + if is_unconstrained() { + my_expensive_computation(); + } else { + my_expensive_computation_hint(); + // verify my_expensive_computation + ... + } +} + +``` + +The is_unconstrained result is resolved at compile time, so in unconstrained contexts the compiler removes the else branch, and in constrained contexts the compiler removes the if branch, reducing the amount of compute necessary to run external_interface. \ No newline at end of file diff --git a/docs/docs/noir/standard_library/merkle_trees.md b/docs/docs/noir/standard_library/merkle_trees.md index fa488677884..6a9ebf72ada 100644 --- a/docs/docs/noir/standard_library/merkle_trees.md +++ b/docs/docs/noir/standard_library/merkle_trees.md @@ -42,9 +42,9 @@ 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 note_commitment = std::hash::pedersen(&[pubkey_x, pubkey_y, secret]); - let root = std::merkle::compute_merkle_root(note_commitment[0], index, note_hash_path); + let root = std::merkle::compute_merkle_root(note_commitment[0], index, note_hash_path.as_slice()); println(root); } ``` diff --git a/docs/docs/noir/standard_library/recursion.md b/docs/docs/noir/standard_library/recursion.md index 9337499dac8..a93894043dc 100644 --- a/docs/docs/noir/standard_library/recursion.md +++ b/docs/docs/noir/standard_library/recursion.md @@ -29,8 +29,8 @@ By incorporating this attribute directly in the circuit's definition, tooling li ## Verifying Recursive Proofs ```rust -#[foreign(verify_proof)] -fn verify_proof(_verification_key : [Field], _proof : [Field], _public_input : Field, _key_hash : Field) {} +#[foreign(recursive_aggregation)] +pub fn verify_proof(verification_key: [Field], proof: [Field], public_inputs: [Field], key_hash: Field) {} ``` :::info diff --git a/docs/docs/noir/standard_library/traits.md b/docs/docs/noir/standard_library/traits.md index fb6d5ae1c48..96a7b8e2f22 100644 --- a/docs/docs/noir/standard_library/traits.md +++ b/docs/docs/noir/standard_library/traits.md @@ -32,6 +32,8 @@ impl Default for bool { .. } impl Default for [T; N] where T: Default { .. } +impl Default for [T] { .. } + impl Default for (A, B) where A: Default, B: Default { .. } @@ -46,7 +48,8 @@ impl Default for (A, B, C, D, E) ``` For primitive integer types, the return value of `default` is `0`. Container -types such as arrays are filled with default values of their element type. +types such as arrays are filled with default values of their element type, +except slices whose length is unknown and thus defaulted to zero. ## `std::convert` @@ -112,6 +115,9 @@ impl Eq for bool { .. } impl Eq for [T; N] where T: Eq { .. } +impl Eq for [T] + where T: Eq { .. } + impl Eq for (A, B) where A: Eq, B: Eq { .. } @@ -134,6 +140,8 @@ impl Eq for (A, B, C, D, E) Implementing this trait on a type allows `<`, `<=`, `>`, and `>=` to be used on values of the type. +`std::cmp` also provides `max` and `min` functions for any type which implements the `Ord` trait. + Implementations: ```rust @@ -154,6 +162,9 @@ impl Ord for bool { .. } impl Ord for [T; N] where T: Ord { .. } +impl Ord for [T] + where T: Ord { .. } + impl Ord for (A, B) where A: Ord, B: Ord { .. } @@ -175,10 +186,10 @@ These traits abstract over addition, subtraction, multiplication, and division r Implementing these traits for a given type will also allow that type to be used with the corresponding operator for that trait (`+` for Add, etc) in addition to the normal method names. -#include_code add-trait noir_stdlib/src/ops.nr rust -#include_code sub-trait noir_stdlib/src/ops.nr rust -#include_code mul-trait noir_stdlib/src/ops.nr rust -#include_code div-trait noir_stdlib/src/ops.nr rust +#include_code add-trait noir_stdlib/src/ops/arith.nr rust +#include_code sub-trait noir_stdlib/src/ops/arith.nr rust +#include_code mul-trait noir_stdlib/src/ops/arith.nr rust +#include_code div-trait noir_stdlib/src/ops/arith.nr rust The implementations block below is given for the `Add` trait, but the same types that implement `Add` also implement `Sub`, `Mul`, and `Div`. @@ -200,7 +211,7 @@ impl Add for u64 { .. } ### `std::ops::Rem` -#include_code rem-trait noir_stdlib/src/ops.nr rust +#include_code rem-trait noir_stdlib/src/ops/arith.nr rust `Rem::rem(a, b)` is the remainder function returning the result of what is left after dividing `a` and `b`. Implementing `Rem` allows the `%` operator @@ -221,11 +232,29 @@ impl Rem for i32 { fn rem(self, other: i32) -> i32 { self % other } } impl Rem for i64 { fn rem(self, other: i64) -> i64 { self % other } } ``` +### `std::ops::Neg` + +#include_code neg-trait noir_stdlib/src/ops/arith.nr rust + +`Neg::neg` is equivalent to the unary negation operator `-`. + +Implementations: +#include_code neg-trait-impls noir_stdlib/src/ops/arith.nr rust + +### `std::ops::Not` + +#include_code not-trait noir_stdlib/src/ops/bit.nr rust + +`Not::not` is equivalent to the unary bitwise NOT operator `!`. + +Implementations: +#include_code not-trait-impls noir_stdlib/src/ops/bit.nr rust + ### `std::ops::{ BitOr, BitAnd, BitXor }` -#include_code bitor-trait noir_stdlib/src/ops.nr rust -#include_code bitand-trait noir_stdlib/src/ops.nr rust -#include_code bitxor-trait noir_stdlib/src/ops.nr rust +#include_code bitor-trait noir_stdlib/src/ops/bit.nr rust +#include_code bitand-trait noir_stdlib/src/ops/bit.nr rust +#include_code bitxor-trait noir_stdlib/src/ops/bit.nr rust Traits for the bitwise operations `|`, `&`, and `^`. @@ -252,8 +281,8 @@ impl BitOr for i64 { fn bitor(self, other: i64) -> i64 { self | other } } ### `std::ops::{ Shl, Shr }` -#include_code shl-trait noir_stdlib/src/ops.nr rust -#include_code shr-trait noir_stdlib/src/ops.nr rust +#include_code shl-trait noir_stdlib/src/ops/bit.nr rust +#include_code shr-trait noir_stdlib/src/ops/bit.nr rust Traits for a bit shift left and bit shift right. diff --git a/docs/docs/noir/standard_library/zeroed.md b/docs/docs/noir/standard_library/zeroed.md index 97dab02dac2..f450fecdd36 100644 --- a/docs/docs/noir/standard_library/zeroed.md +++ b/docs/docs/noir/standard_library/zeroed.md @@ -18,6 +18,7 @@ This function currently supports the following types: - Bool - Uint - Array +- Slice - String - Tuple - Function diff --git a/docs/docs/reference/debugger/_category_.json b/docs/docs/reference/debugger/_category_.json new file mode 100644 index 00000000000..27869205ad3 --- /dev/null +++ b/docs/docs/reference/debugger/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Debugger", + "position": 1, + "collapsible": true, + "collapsed": true +} diff --git a/docs/docs/reference/debugger/debugger_known_limitations.md b/docs/docs/reference/debugger/debugger_known_limitations.md new file mode 100644 index 00000000000..936d416ac4b --- /dev/null +++ b/docs/docs/reference/debugger/debugger_known_limitations.md @@ -0,0 +1,59 @@ +--- +title: Known limitations +description: + An overview of known limitations of the current version of the Noir debugger +keywords: + [ + Nargo, + Noir Debugger, + VS Code, + ] +sidebar_position: 2 +--- + +# Debugger Known Limitations + +There are currently some limits to what the debugger can observe. + +## Mutable references + +The debugger is currently blind to any state mutated via a mutable reference. For example, in: + +``` +let mut x = 1; +let y = &mut x; +*y = 2; +``` + +The update on `x` will not be observed by the debugger. That means, when running `vars` from the debugger REPL, or inspecting the _local variables_ pane in the VS Code debugger, `x` will appear with value 1 despite having executed `*y = 2;`. + +## Variables of type function or mutable references are opaque + +When inspecting variables, any variable of type `Function` or `MutableReference` will render its value as `<>` or `<>`. + +## Debugger instrumentation affects resulting ACIR + +In order to make the state of local variables observable, the debugger compiles Noir circuits interleaving foreign calls that track any mutations to them. While this works (except in the cases described above) and doesn't introduce any behavior changes, it does as a side effect produce bigger bytecode. In particular, when running the command `opcodes` on the REPL debugger, you will notice Unconstrained VM blocks that look like this: + +``` +... +5 BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [], q_c: 2 }), Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(2))], q_c: 0 })] + | outputs=[] + 5.0 | Mov { destination: RegisterIndex(2), source: RegisterIndex(0) } + 5.1 | Mov { destination: RegisterIndex(3), source: RegisterIndex(1) } + 5.2 | Const { destination: RegisterIndex(0), value: Value { inner: 0 } } + 5.3 | Const { destination: RegisterIndex(1), value: Value { inner: 0 } } + 5.4 | Mov { destination: RegisterIndex(2), source: RegisterIndex(2) } + 5.5 | Mov { destination: RegisterIndex(3), source: RegisterIndex(3) } + 5.6 | Call { location: 8 } + 5.7 | Stop + 5.8 | ForeignCall { function: "__debug_var_assign", destinations: [], inputs: [RegisterIndex(RegisterIndex(2)), RegisterIndex(RegisterIndex(3))] } +... +``` + +If you are interested in debugging/inspecting compiled ACIR without these synthetic changes, you can invoke the REPL debugger with the `--skip-instrumentation` flag or launch the VS Code debugger with the `skipConfiguration` property set to true in its launch configuration. You can find more details about those in the [Debugger REPL reference](debugger_repl.md) and the [VS Code Debugger reference](debugger_vscode.md). + +:::note +Skipping debugger instrumentation means you won't be able to inspect values of local variables. +::: + diff --git a/docs/docs/reference/debugger/debugger_repl.md b/docs/docs/reference/debugger/debugger_repl.md new file mode 100644 index 00000000000..46e2011304e --- /dev/null +++ b/docs/docs/reference/debugger/debugger_repl.md @@ -0,0 +1,360 @@ +--- +title: REPL Debugger +description: + Noir Debugger REPL options and commands. +keywords: + [ + Nargo, + Noir CLI, + Noir Debugger, + REPL, + ] +sidebar_position: 1 +--- + +## Running the REPL debugger + +`nargo debug [OPTIONS] [WITNESS_NAME]` + +Runs the Noir REPL debugger. If a `WITNESS_NAME` is provided the debugger writes the resulting execution witness to a `WITNESS_NAME` 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 debug | +| `--print-acir` | Display the ACIR for compiled circuit | +| `--deny-warnings` | Treat all warnings as errors | +| `--silence-warnings` | Suppress warnings | +| `-h, --help` | Print help | + +None of these options are required. + +:::note +Since the debugger starts by compiling the target package, all Noir compiler options are also available. Check out the [compiler reference](../nargo_commands.md#nargo-compile) to learn more about the compiler options. +::: + +## REPL commands + +Once the debugger is running, it accepts the following commands. + +#### `help` (h) + +Displays the menu of available commands. + +``` +> help +Available commands: + + opcodes display ACIR opcodes + into step into to the next opcode + next step until a new source location is reached + out step until a new source location is reached + and the current stack frame is finished + break LOCATION:OpcodeLocation add a breakpoint at an opcode location + over step until a new source location is reached + without diving into function calls + restart restart the debugging session + delete LOCATION:OpcodeLocation delete breakpoint at an opcode location + witness show witness map + witness index:u32 display a single witness from the witness map + witness index:u32 value:String update a witness with the given value + memset index:usize value:String update a memory cell with the given + value + continue continue execution until the end of the + program + vars show variable values available at this point + in execution + stacktrace display the current stack trace + memory show memory (valid when executing unconstrained code) value + step step to the next ACIR opcode + +Other commands: + + help Show this help message + quit Quit repl + +``` + +### Stepping through programs + +#### `next` (n) + +Step until the next Noir source code location. While other commands, such as [`into`](#into-i) and [`step`](#step-s), allow for finer grained control of the program's execution at the opcode level, `next` is source code centric. For example: + +``` +3 ... +4 fn main(x: u32) { +5 assert(entry_point(x) == 2); +6 swap_entry_point(x, x + 1); +7 -> assert(deep_entry_point(x) == 4); +8 multiple_values_entry_point(x); +9 } +``` + + +Using `next` here would cause the debugger to jump to the definition of `deep_entry_point` (if available). + +If you want to step over `deep_entry_point` and go straight to line 8, use [the `over` command](#over) instead. + +#### `over` + +Step until the next source code location, without diving into function calls. For example: + +``` +3 ... +4 fn main(x: u32) { +5 assert(entry_point(x) == 2); +6 swap_entry_point(x, x + 1); +7 -> assert(deep_entry_point(x) == 4); +8 multiple_values_entry_point(x); +9 } +``` + + +Using `over` here would cause the debugger to execute until line 8 (`multiple_values_entry_point(x);`). + +If you want to step into `deep_entry_point` instead, use [the `next` command](#next-n). + +#### `out` + +Step until the end of the current function call. For example: + +``` + 3 ... + 4 fn main(x: u32) { + 5 assert(entry_point(x) == 2); + 6 swap_entry_point(x, x + 1); + 7 -> assert(deep_entry_point(x) == 4); + 8 multiple_values_entry_point(x); + 9 } + 10 + 11 unconstrained fn returns_multiple_values(x: u32) -> (u32, u32, u32, u32) { + 12 ... + ... + 55 + 56 unconstrained fn deep_entry_point(x: u32) -> u32 { + 57 -> level_1(x + 1) + 58 } + +``` + +Running `out` here will resume execution until line 8. + +#### `step` (s) + +Skips to the next ACIR code. A compiled Noir program is a sequence of ACIR opcodes. However, an unconstrained VM opcode denotes the start of an unconstrained code block, to be executed by the unconstrained VM. For example (redacted for brevity): + +``` +0 BLACKBOX::RANGE [(_0, num_bits: 32)] [ ] +1 -> BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(0))], q_c: 0 })] outputs=[Simple(Witness(1))] + 1.0 | Mov { destination: RegisterIndex(2), source: RegisterIndex(0) } + 1.1 | Const { destination: RegisterIndex(0), value: Value { inner: 0 } } + 1.2 | Const { destination: RegisterIndex(1), value: Value { inner: 0 } } + 1.3 | Mov { destination: RegisterIndex(2), source: RegisterIndex(2) } + 1.4 | Call { location: 7 } + ... + 1.43 | Return +2 EXPR [ (1, _1) -2 ] +``` + +The `->` here shows the debugger paused at an ACIR opcode: `BRILLIG`, at index 1, which denotes an unconstrained code block is about to start. + +Using the `step` command at this point would result in the debugger stopping at ACIR opcode 2, `EXPR`, skipping unconstrained computation steps. + +Use [the `into` command](#into-i) instead if you want to follow unconstrained computation step by step. + +#### `into` (i) + +Steps into the next opcode. A compiled Noir program is a sequence of ACIR opcodes. However, a BRILLIG opcode denotes the start of an unconstrained code block, to be executed by the unconstrained VM. For example (redacted for brevity): + +``` +0 BLACKBOX::RANGE [(_0, num_bits: 32)] [ ] +1 -> BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(0))], q_c: 0 })] outputs=[Simple(Witness(1))] + 1.0 | Mov { destination: RegisterIndex(2), source: RegisterIndex(0) } + 1.1 | Const { destination: RegisterIndex(0), value: Value { inner: 0 } } + 1.2 | Const { destination: RegisterIndex(1), value: Value { inner: 0 } } + 1.3 | Mov { destination: RegisterIndex(2), source: RegisterIndex(2) } + 1.4 | Call { location: 7 } + ... + 1.43 | Return +2 EXPR [ (1, _1) -2 ] +``` + +The `->` here shows the debugger paused at an ACIR opcode: `BRILLIG`, at index 1, which denotes an unconstrained code block is about to start. + +Using the `into` command at this point would result in the debugger stopping at opcode 1.0, `Mov ...`, allowing the debugger user to follow unconstrained computation step by step. + +Use [the `step` command](#step-s) instead if you want to skip to the next ACIR code directly. + +#### `continue` (c) + +Continues execution until the next breakpoint, or the end of the program. + +#### `restart` (res) + +Interrupts execution, and restarts a new debugging session from scratch. + +#### `opcodes` (o) + +Display the program's ACIR opcode sequence. For example: + +``` +0 BLACKBOX::RANGE [(_0, num_bits: 32)] [ ] +1 -> BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(0))], q_c: 0 })] outputs=[Simple(Witness(1))] + 1.0 | Mov { destination: RegisterIndex(2), source: RegisterIndex(0) } + 1.1 | Const { destination: RegisterIndex(0), value: Value { inner: 0 } } + 1.2 | Const { destination: RegisterIndex(1), value: Value { inner: 0 } } + 1.3 | Mov { destination: RegisterIndex(2), source: RegisterIndex(2) } + 1.4 | Call { location: 7 } + ... + 1.43 | Return +2 EXPR [ (1, _1) -2 ] +``` + +### Breakpoints + +#### `break [Opcode]` (or shorthand `b [Opcode]`) + +Sets a breakpoint on the specified opcode index. To get a list of the program opcode numbers, see [the `opcode` command](#opcodes-o). For example: + +``` +0 BLACKBOX::RANGE [(_0, num_bits: 32)] [ ] +1 -> BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(0))], q_c: 0 })] outputs=[Simple(Witness(1))] + 1.0 | Mov { destination: RegisterIndex(2), source: RegisterIndex(0) } + 1.1 | Const { destination: RegisterIndex(0), value: Value { inner: 0 } } + 1.2 | Const { destination: RegisterIndex(1), value: Value { inner: 0 } } + 1.3 | Mov { destination: RegisterIndex(2), source: RegisterIndex(2) } + 1.4 | Call { location: 7 } + ... + 1.43 | Return +2 EXPR [ (1, _1) -2 ] +``` + +In this example, issuing a `break 1.2` command adds break on opcode 1.2, as denoted by the `*` character: + +``` +0 BLACKBOX::RANGE [(_0, num_bits: 32)] [ ] +1 -> BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(0))], q_c: 0 })] outputs=[Simple(Witness(1))] + 1.0 | Mov { destination: RegisterIndex(2), source: RegisterIndex(0) } + 1.1 | Const { destination: RegisterIndex(0), value: Value { inner: 0 } } + 1.2 | * Const { destination: RegisterIndex(1), value: Value { inner: 0 } } + 1.3 | Mov { destination: RegisterIndex(2), source: RegisterIndex(2) } + 1.4 | Call { location: 7 } + ... + 1.43 | Return +2 EXPR [ (1, _1) -2 ] +``` + +Running [the `continue` command](#continue-c) at this point would cause the debugger to execute the program until opcode 1.2. + +#### `delete [Opcode]` (or shorthand `d [Opcode]`) + +Deletes a breakpoint at an opcode location. Usage is analogous to [the `break` command](#). + +### Variable inspection + +#### vars + +Show variable values available at this point in execution. + +:::note +The ability to inspect variable values from the debugger depends on compilation to be run in a special debug instrumentation mode. This instrumentation weaves variable tracing code with the original source code. + +So variable value inspection comes at the expense of making the resulting ACIR bytecode bigger and harder to understand and optimize. + +If you find this compromise unacceptable, you can run the debugger with the flag `--skip-debug-instrumentation`. This will compile your circuit without any additional debug information, so the resulting ACIR bytecode will be identical to the one produced by standard Noir compilation. However, if you opt for this, the `vars` command will not be available while debugging. +::: + + +### Stacktrace + +#### `stacktrace` + +Displays the current stack trace. + + +### Witness map + +#### `witness` (w) + +Show witness map. For example: + +``` +_0 = 0 +_1 = 2 +_2 = 1 +``` + +#### `witness [Witness Index]` + +Display a single witness from the witness map. For example: + +``` +> witness 1 +_1 = 2 +``` + +#### `witness [Witness Index] [New value]` + +Overwrite the given index with a new value. For example: + +``` +> witness 1 3 +_1 = 3 +``` + + +### Unconstrained VM memory + +#### `memory` + +Show unconstrained VM memory state. For example: + +``` +> memory +At opcode 1.13: Store { destination_pointer: RegisterIndex(0), source: RegisterIndex(3) } +... +> registers +0 = 0 +1 = 10 +2 = 0 +3 = 1 +4 = 1 +5 = 2³² +6 = 1 +> into +At opcode 1.14: Const { destination: RegisterIndex(5), value: Value { inner: 1 } } +... +> memory +0 = 1 +> +``` + +In the example above: we start with clean memory, then step through a `Store` opcode which stores the value of register 3 (1) into the memory address stored in register 0 (0). Thus now `memory` shows memory address 0 contains value 1. + +:::note +This command is only functional while the debugger is executing unconstrained code. +::: + +#### `memset [Memory address] [New value]` + +Update a memory cell with the given value. For example: + +``` +> memory +0 = 1 +> memset 0 2 +> memory +0 = 2 +> memset 1 4 +> memory +0 = 2 +1 = 4 +> +``` + +:::note +This command is only functional while the debugger is executing unconstrained code. +::: \ No newline at end of file diff --git a/docs/docs/reference/debugger/debugger_vscode.md b/docs/docs/reference/debugger/debugger_vscode.md new file mode 100644 index 00000000000..c027332b3b0 --- /dev/null +++ b/docs/docs/reference/debugger/debugger_vscode.md @@ -0,0 +1,82 @@ +--- +title: VS Code Debugger +description: + VS Code Debugger configuration and features. +keywords: + [ + Nargo, + Noir CLI, + Noir Debugger, + VS Code, + IDE, + ] +sidebar_position: 0 +--- + +# VS Code Noir Debugger Reference + +The Noir debugger enabled by the vscode-noir extension ships with default settings such that the most common scenario should run without any additional configuration steps. + +These defaults can nevertheless be overridden by defining a launch configuration file. This page provides a reference for the properties you can override via a launch configuration file, as well as documenting the Nargo `dap` command, which is a dependency of the VS Code Noir debugger. + + +## Creating and editing launch configuration files + +To create a launch configuration file from VS Code, open the _debug pane_, and click on _create a launch.json file_. + +![Creating a launch configuration file](@site/static/img/debugger/ref1-create-launch.png) + +A `launch.json` file will be created, populated with basic defaults. + +### Noir Debugger launch.json properties + +#### projectFolder + +_String, optional._ + +Absolute path to the Nargo project to debug. By default, it is dynamically determined by looking for the nearest `Nargo.toml` file to the active file at the moment of launching the debugger. + +#### proverName + +_String, optional._ + +Name of the prover input to use. Defaults to `Prover`, which looks for a file named `Prover.toml` at the `projectFolder`. + +#### generateAcir + +_Boolean, optional._ + +If true, generate ACIR opcodes instead of unconstrained opcodes which will be closer to release binaries but less convenient for debugging. Defaults to `false`. + +#### skipInstrumentation + +_Boolean, optional._ + +Skips variables debugging instrumentation of code, making debugging less convenient but the resulting binary smaller and closer to production. Defaults to `false`. + +:::note +Skipping instrumentation causes the debugger to be unable to inspect local variables. +::: + +## `nargo dap [OPTIONS]` + +When run without any option flags, it starts the Nargo Debug Adapter Protocol server, which acts as the debugging backend for the VS Code Noir Debugger. + +All option flags are related to preflight checks. The Debug Adapter Protocol specifies how errors are to be informed from a running DAP server, but it doesn't specify mechanisms to communicate server initialization errors between the DAP server and its client IDE. + +Thus `nargo dap` ships with a _preflight check_ mode. If flag `--preflight-check` and the rest of the `--preflight-*` flags are provided, Nargo will run the same initialization routine except it will not start the DAP server. + +`vscode-noir` will then run `nargo dap` in preflight check mode first before a debugging session starts. If the preflight check ends in error, vscode-noir will present stderr and stdout output from this process through its own Output pane in VS Code. This makes it possible for users to diagnose what pieces of configuration might be wrong or missing in case of initialization errors. + +If the preflight check succeeds, `vscode-noir` proceeds to start the DAP server normally but running `nargo dap` without any additional flags. + +### Options + +| Option | Description | +| --------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- | +| `--preflight-check` | If present, dap runs in preflight check mode. | +| `--preflight-project-folder ` | Absolute path to the project to debug for preflight check. | +| `--preflight-prover-name ` | Name of prover file to use for preflight check | +| `--preflight-generate-acir` | Optional. If present, compile in ACIR mode while running preflight check. | +| `--preflight-skip-instrumentation` | Optional. If present, compile without introducing debug instrumentation while running preflight check. | +| `-h, --help` | Print help. | diff --git a/docs/docs/tooling/debugger.md b/docs/docs/tooling/debugger.md new file mode 100644 index 00000000000..184c436068f --- /dev/null +++ b/docs/docs/tooling/debugger.md @@ -0,0 +1,27 @@ +--- +title: Debugger +description: Learn about the Noir Debugger, in its REPL or VS Code versions. +keywords: [Nargo, VSCode, Visual Studio Code, REPL, Debugger] +sidebar_position: 2 +--- + +# Noir Debugger + +There are currently two ways of debugging Noir programs: + +1. From VS 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). +2. Via the REPL debugger, which ships with Nargo. + +In order to use either version of the debugger, you will need to install recent enough versions of Noir, [Nargo](../getting_started/installation) and vscode-noir: + +- Noir 0.xx +- Nargo 0.xx +- vscode-noir 0.xx + +:::info +At the moment, the debugger supports debugging binary projects, but not contracts. +::: + +We cover the VS Code Noir debugger more in depth in [its VS Code debugger how-to guide](../how_to/debugger/debugging_with_vs_code.md) and [the reference](../reference/debugger/debugger_vscode.md). + +The REPL debugger is discussed at length in [the REPL debugger how-to guide](../how_to/debugger/debugging_with_the_repl.md) and [the reference](../reference/debugger/debugger_repl.md). diff --git a/docs/docs/getting_started/tooling/language_server.md b/docs/docs/tooling/language_server.md similarity index 100% rename from docs/docs/getting_started/tooling/language_server.md rename to docs/docs/tooling/language_server.md diff --git a/docs/docs/getting_started/tooling/testing.md b/docs/docs/tooling/testing.md similarity index 100% rename from docs/docs/getting_started/tooling/testing.md rename to docs/docs/tooling/testing.md diff --git a/docs/docs/tutorials/noirjs_app.md b/docs/docs/tutorials/noirjs_app.md index ad76dd255cc..cbb1938a5c6 100644 --- a/docs/docs/tutorials/noirjs_app.md +++ b/docs/docs/tutorials/noirjs_app.md @@ -14,9 +14,9 @@ You can find the complete app code for this guide [here](https://github.com/noir :::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.19.x matches `noir_js@0.19.x`, etc. +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.27.x matches `noir_js@0.27.x`, etc. -In this guide, we will be pinned to 0.19.4. +In this guide, we will be pinned to 0.27.0. ::: @@ -24,7 +24,7 @@ Before we start, we want to make sure we have Node and Nargo installed. We start by opening a terminal and executing `node --version`. If we don't get an output like `v20.10.0`, that means node is not installed. Let's do that by following the handy [nvm guide](https://github.com/nvm-sh/nvm?tab=readme-ov-file#install--update-script). -As for `Nargo`, we can follow the the [Nargo guide](../getting_started/installation/index.md) to install it. If you're lazy, just paste this on a terminal and run `noirup`: +As for `Nargo`, we can follow the [Nargo guide](../getting_started/installation/index.md) to install it. If you're lazy, just paste this on a terminal and run `noirup`: ```sh curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash @@ -34,7 +34,7 @@ Easy enough. Onwards! ## Our project -ZK is a powerful technology. An app that doesn't reveal one of the inputs to *anyone* is almost unbelievable, yet Noir makes it as easy as a single line of code. +ZK is a powerful technology. An app that doesn't reveal one of the inputs to _anyone_ is almost unbelievable, yet Noir makes it as easy as a single line of code. In fact, it's so simple that it comes nicely packaged in `nargo`. Let's do that! @@ -42,13 +42,13 @@ In fact, it's so simple that it comes nicely packaged in `nargo`. Let's do that! Run: -```nargo new circuit``` +`nargo new circuit` And... That's about it. Your program is ready to be compiled and run. To compile, let's `cd` into the `circuit` folder to enter our project, and call: -```nargo compile``` +`nargo compile` This compiles our circuit into `json` format and add it to a new `target` folder. @@ -77,10 +77,55 @@ Vite is a powerful tool to generate static websites. While it provides all kinds To do this this, go back to the previous folder (`cd ..`) and create a new vite project by running `npm create vite` and choosing "Vanilla" and "Javascript". -You should see `vite-project` appear in your root folder. This seems like a good time to `cd` into it and install our NoirJS packages: +A wild `vite-project` directory should now appear in your root folder! Let's not waste any time and dive right in: ```bash -npm i @noir-lang/backend_barretenberg@0.19.4 @noir-lang/noir_js@0.19.4 +cd vite-project +``` + +### Setting Up Vite and Configuring the Project + +Before we proceed with any coding, let's get our environment tailored for Noir. We'll start by laying down the foundations with a `vite.config.js` file. This little piece of configuration is our secret sauce for making sure everything meshes well with the NoirJS libraries and other special setups we might need, like handling WebAssembly modules. Here’s how you get that going: + +#### Creating the vite.config.js + +In your freshly minted `vite-project` folder, create a new file named `vite.config.js` and open it in your code editor. Paste the following to set the stage: + +```javascript +import { defineConfig } from "vite"; +import copy from "rollup-plugin-copy"; + +export default defineConfig({ + esbuild: { + target: "esnext", + }, + optimizeDeps: { + esbuildOptions: { + target: "esnext", + }, + }, + plugins: [ + copy({ + targets: [ + { src: "node_modules/**/*.wasm", dest: "node_modules/.vite/dist" }, + ], + copySync: true, + hook: "buildStart", + }), + ], + server: { + port: 3000, + }, +}); +``` + +#### Install Dependencies + +Now that our stage is set, install the necessary NoirJS packages along with our other dependencies: + +```bash +npm install && npm install @noir-lang/backend_barretenberg@0.27.0 @noir-lang/noir_js@0.27.0 +npm install rollup-plugin-copy --save-dev ``` :::info @@ -99,7 +144,7 @@ At this point in the tutorial, your folder structure should look like this: #### Some cleanup -`npx create vite` is amazing but it creates a bunch of files we don't really need for our simple example. Actually, let's just delete everything except for `index.html`, `main.js` and `package.json`. I feel lighter already. +`npx create vite` is amazing but it creates a bunch of files we don't really need for our simple example. Actually, let's just delete everything except for `vite.config.js`, `index.html`, `main.js` and `package.json`. I feel lighter already. ![my heart is ready for you, noir.js](@site/static/img/memes/titanic.jpeg) @@ -139,7 +184,7 @@ Our app won't run like this, of course. We need some working HTML, at least. Let ``` -It *could* be a beautiful UI... Depending on which universe you live in. +It _could_ be a beautiful UI... Depending on which universe you live in. ## Some good old vanilla Javascript @@ -150,14 +195,14 @@ Start by pasting in this boilerplate code: ```js const setup = async () => { await Promise.all([ - import("@noir-lang/noirc_abi").then(module => - module.default(new URL("@noir-lang/noirc_abi/web/noirc_abi_wasm_bg.wasm", import.meta.url).toString()) + import('@noir-lang/noirc_abi').then((module) => + module.default(new URL('@noir-lang/noirc_abi/web/noirc_abi_wasm_bg.wasm', import.meta.url).toString()), + ), + import('@noir-lang/acvm_js').then((module) => + module.default(new URL('@noir-lang/acvm_js/web/acvm_js_bg.wasm', import.meta.url).toString()), ), - import("@noir-lang/acvm_js").then(module => - module.default(new URL("@noir-lang/acvm_js/web/acvm_js_bg.wasm", import.meta.url).toString()) - ) ]); -} +}; function display(container, msg) { const c = document.getElementById(container); @@ -169,11 +214,10 @@ function display(container, msg) { document.getElementById('submitGuess').addEventListener('click', async () => { try { // here's where love happens - } catch(err) { - display("logs", "Oh 💔 Wrong guess") + } catch (err) { + display('logs', 'Oh 💔 Wrong guess'); } }); - ``` The display function doesn't do much. We're simply manipulating our website to see stuff happening. For example, if the proof fails, it will simply log a broken heart 😢 @@ -189,6 +233,7 @@ At this point in the tutorial, your folder structure should look like this: └── circuit └── ...same as above └── vite-project + ├── vite.config.js ├── main.js ├── package.json └── index.html @@ -209,7 +254,7 @@ import circuit from '../circuit/target/circuit.json'; [Noir is backend-agnostic](../index.mdx#whats-new-about-noir). We write Noir, but we also need a proving backend. That's why we need to import and instantiate the two dependencies we installed above: `BarretenbergBackend` and `Noir`. Let's import them right below: ```js -import { BarretenbergBackend } from '@noir-lang/backend_barretenberg'; +import { BarretenbergBackend, BarretenbergVerifier as Verifier } from '@noir-lang/backend_barretenberg'; import { Noir } from '@noir-lang/noir_js'; ``` @@ -218,7 +263,7 @@ And instantiate them inside our try-catch block: ```ts // try { const backend = new BarretenbergBackend(circuit); -const noir = new Noir(circuit, backend); +const noir = new Noir(circuit); // } ``` @@ -243,7 +288,8 @@ Now we're ready to prove stuff! Let's feed some inputs to our circuit and calcul await setup(); // let's squeeze our wasm inits here display('logs', 'Generating proof... ⌛'); -const proof = await noir.generateFinalProof(input); +const { witness } = await noir.execute(input); +const proof = await backend.generateProof(witness); display('logs', 'Generating proof... ✅'); display('results', proof.proof); ``` @@ -264,8 +310,10 @@ Time to celebrate, yes! But we shouldn't trust machines so blindly. Let's add th ```js display('logs', 'Verifying proof... ⌛'); -const verification = await noir.verifyFinalProof(proof); -if (verification) display('logs', 'Verifying proof... ✅'); +const verificationKey = await backend.getVerificationKey(); +const verifier = new Verifier(); +const isValid = await verifier.verifyProof(proof, verificationKey); +if (isValid) display('logs', 'Verifying proof... ✅'); ``` You have successfully generated a client-side Noir web app! diff --git a/docs/docusaurus.config.ts b/docs/docusaurus.config.ts index 49566c5c380..2d5b8941f55 100644 --- a/docs/docusaurus.config.ts +++ b/docs/docusaurus.config.ts @@ -47,7 +47,9 @@ export default { }, ], ], - + customFields: { + MATOMO_ENV: process.env.MATOMO_ENV, + }, themeConfig: { colorMode: { respectPrefersColorScheme: true, diff --git a/docs/package.json b/docs/package.json index 146c2a9800c..c81d0b7b24f 100644 --- a/docs/package.json +++ b/docs/package.json @@ -3,12 +3,14 @@ "version": "0.0.0", "private": true, "scripts": { - "preprocess": "./scripts/codegen_nargo_reference.sh && yarn node ./scripts/preprocess/index.js", - "start": "yarn preprocess && docusaurus start", - "build": "yarn preprocess && yarn version::stables && docusaurus build", + "preprocess": "yarn workspace @noir-lang/acvm_js build && ./scripts/codegen_nargo_reference.sh && yarn node ./scripts/preprocess/index.js", + "start": "yarn preprocess && MATOMO_ENV=dev docusaurus start", + "build": "yarn preprocess && docusaurus build", + "clean": "rm -rf ./processed-docs ./processed-docs ./build", "version::stables": "ts-node ./scripts/setStable.ts", "serve": "serve build", - "version": "yarn preprocess && docusaurus docs:version" + "swizzle": "docusaurus swizzle", + "version": "yarn version::stables && ./scripts/cut_version.sh" }, "dependencies": { "@docusaurus/core": "^3.0.1", @@ -34,15 +36,15 @@ "@docusaurus/types": "^3.0.1", "@types/prettier": "^3", "docusaurus-plugin-typedoc": "1.0.0-next.18", - "eslint-plugin-prettier": "^5.0.0", - "prettier": "3.0.3", + "eslint-plugin-prettier": "^5.1.3", + "prettier": "3.2.5", "serve": "^14.2.1", "ts-node": "^10.9.1", "typedoc": "^0.25.0", "typedoc-plugin-frontmatter": "^0.0.2", "typedoc-plugin-markdown": "4.0.0-next.25", "typedoc-plugin-merge-modules": "^5.1.0", - "typescript": "~5.2.2" + "typescript": "^5.4.2" }, "browserslist": { "production": [ diff --git a/docs/scripts/codegen_nargo_reference.sh b/docs/scripts/codegen_nargo_reference.sh index 4ff7d43d142..6a9fda9420b 100755 --- a/docs/scripts/codegen_nargo_reference.sh +++ b/docs/scripts/codegen_nargo_reference.sh @@ -30,4 +30,4 @@ sidebar_position: 0 --- " > $NARGO_REFERENCE -cargo run -F codegen-docs -- info >> $NARGO_REFERENCE +cargo run --bin nargo -F codegen-docs -- info >> $NARGO_REFERENCE diff --git a/docs/scripts/cut_version.sh b/docs/scripts/cut_version.sh new file mode 100755 index 00000000000..4000707328c --- /dev/null +++ b/docs/scripts/cut_version.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash +set -eu + +cd $(dirname "$0")/.. + +VERSION=$1 + +# We assume that the new release tag has been made on github, so setStable.ts will add this to `versions.json`. +# We don't have a version of the docs for this release however (that's what we're doing right now!) so we need to remove it. +jq 'map(select(. != "'"$VERSION"'"))' versions.json > tmp.json && mv tmp.json versions.json + +# We need to build the docs in order to perform all necessary preprocessing. +yarn build + +# Finally cut the actual new docs version. +yarn docusaurus docs:version $VERSION diff --git a/docs/sidebars.js b/docs/sidebars.js index f1e79ba9ebc..cf7e852fed5 100644 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -65,6 +65,11 @@ export default { label: 'Reference', items: [{ type: 'autogenerated', dirName: 'reference' }], }, + { + type: 'category', + label: 'Tooling', + items: [{ type: 'autogenerated', dirName: 'tooling' }], + }, { type: 'html', value: '

', diff --git a/docs/src/components/Matomo/matomo.jsx b/docs/src/components/Matomo/matomo.jsx new file mode 100644 index 00000000000..7ee34fc8e51 --- /dev/null +++ b/docs/src/components/Matomo/matomo.jsx @@ -0,0 +1,133 @@ +import { useEffect, useState } from 'react'; +import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; +import Link from '@docusaurus/Link'; + +function getSiteId(env) { + if (env == 'dev') { + return '3'; + } else if (env == 'staging') { + return '2'; + } else { + return '1'; + } +} +function pushInstruction(name, ...args) { + return window._paq.push([name, ...args]); +} + +export default function useMatomo() { + const { siteConfig } = useDocusaurusContext(); + const [showBanner, setShowBanner] = useState(false); + + const env = siteConfig.customFields.MATOMO_ENV; + const urlBase = 'https://noirlang.matomo.cloud/'; + const trackerUrl = `${urlBase}matomo.php`; + const srcUrl = `${urlBase}matomo.js`; + + window._paq = window._paq || []; + + useEffect(() => { + const storedConsent = localStorage.getItem('matomoConsent'); + if (storedConsent === null) { + setShowBanner(true); + } + }, []); + + useEffect(() => { + pushInstruction('setTrackerUrl', trackerUrl); + pushInstruction('setSiteId', getSiteId(env)); + if (env !== 'prod') { + pushInstruction('setSecureCookie', false); + } + + const doc = document; + const scriptElement = doc.createElement('script'); + const scripts = doc.getElementsByTagName('script')[0]; + + scriptElement.type = 'text/javascript'; + scriptElement.async = true; + scriptElement.defer = true; + scriptElement.src = srcUrl; + + if (scripts && scripts.parentNode) { + scripts.parentNode.insertBefore(scriptElement, scripts); + } + }, []); + + useEffect(() => { + pushInstruction('trackPageView'); + }, [window.location.href]); + + const optIn = () => { + pushInstruction('rememberConsentGiven'); + localStorage.setItem('matomoConsent', true); + setShowBanner(false); + }; + + const optOut = () => { + pushInstruction('forgetConsentGiven'); + localStorage.setItem('matomoConsent', false); + setShowBanner(false); + }; + + const debug = () => { + pushInstruction(function () { + console.log(this.getRememberedConsent()); + console.log(localStorage.getItem('matomoConsent')); + }); + }; + + const reset = () => { + pushInstruction('forgetConsentGiven'); + localStorage.clear('matomoConsent'); + }; + + if (!showBanner && env === 'dev') { + return ( +
+
+

Debugging analytics

+
+ + +
+
+
+ ); + } else if (!showBanner) { + return null; + } + + return ( +
+
+

+ We value your privacy and we only collect statistics and essential cookies. If you'd like to help us improve + our websites, you can allow cookies for tracking page views, time on site, and other analytics. +
+
+ + Find out how we use cookies and how you can change your settings. + +

+
+ + + {env === 'dev' && ( + + )} +
+
+
+ ); +} diff --git a/docs/src/css/custom.css b/docs/src/css/custom.css index b08766fbc3b..fb6be87b519 100644 --- a/docs/src/css/custom.css +++ b/docs/src/css/custom.css @@ -214,3 +214,31 @@ input#docsearch-input { background-color: transparent; } + +#optout-form { + position: sticky; + bottom: 10px; + flex-direction: column; + display: flex; + max-width: 800px; + margin: 0 auto; + background-color: var(--ifm-breadcrumb-color-active); +} + + + +.homepage_footer { + text-align: center; + margin-bottom: 1rem; + padding: 1.5rem 2rem; + display: flex; + flex-direction: column; + border: 1px solid #BEC2C3; + border-radius: 12px; +} + +.homepage_cta_footer_container { + display: flex; + justify-content: center; +} + diff --git a/docs/src/pages/index.jsx b/docs/src/pages/index.jsx index b372871e7b4..c7de44b300d 100644 --- a/docs/src/pages/index.jsx +++ b/docs/src/pages/index.jsx @@ -1,9 +1,8 @@ -import React, { lazy, Suspense } from 'react'; +import React from 'react'; import Layout from '@theme/Layout'; import Link from '@docusaurus/Link'; import headerPic from '@site/static/img/homepage_header_pic.png'; -import { BeatLoader } from 'react-spinners'; export default function Landing() { return ( diff --git a/docs/src/theme/Root.js b/docs/src/theme/Root.js new file mode 100644 index 00000000000..68c1e529db3 --- /dev/null +++ b/docs/src/theme/Root.js @@ -0,0 +1,22 @@ +import React from 'react'; +import useMatomo from '@site/src/components/Matomo/matomo'; +import BrowserOnly from '@docusaurus/BrowserOnly'; +import useIsBrowser from '@docusaurus/useIsBrowser'; + +function OptOutForm() { + const banner = useMatomo(); + + return <>{banner}; +} + +export default function Root({ children }) { + const useIsBrowserValue = useIsBrowser(); + if (!useIsBrowserValue) return <>{children}; + + return ( + <> + {children} + {() => } + + ); +} diff --git a/docs/static/img/debugger/1-started.png b/docs/static/img/debugger/1-started.png new file mode 100644 index 00000000000..6f764d4e601 Binary files /dev/null and b/docs/static/img/debugger/1-started.png differ diff --git a/docs/static/img/debugger/2-icon.png b/docs/static/img/debugger/2-icon.png new file mode 100644 index 00000000000..31706670ccb Binary files /dev/null and b/docs/static/img/debugger/2-icon.png differ diff --git a/docs/static/img/debugger/3-debug-pane.png b/docs/static/img/debugger/3-debug-pane.png new file mode 100644 index 00000000000..24c112da96f Binary files /dev/null and b/docs/static/img/debugger/3-debug-pane.png differ diff --git a/docs/static/img/debugger/4-debugger-buttons.png b/docs/static/img/debugger/4-debugger-buttons.png new file mode 100644 index 00000000000..64c1e05be8a Binary files /dev/null and b/docs/static/img/debugger/4-debugger-buttons.png differ diff --git a/docs/static/img/debugger/5-assert.png b/docs/static/img/debugger/5-assert.png new file mode 100644 index 00000000000..0bfed6562af Binary files /dev/null and b/docs/static/img/debugger/5-assert.png differ diff --git a/docs/static/img/debugger/6-hover.png b/docs/static/img/debugger/6-hover.png new file mode 100644 index 00000000000..20579ec461e Binary files /dev/null and b/docs/static/img/debugger/6-hover.png differ diff --git a/docs/static/img/debugger/7-break.png b/docs/static/img/debugger/7-break.png new file mode 100644 index 00000000000..aca5121d722 Binary files /dev/null and b/docs/static/img/debugger/7-break.png differ diff --git a/docs/static/img/debugger/debugger-intro.gif b/docs/static/img/debugger/debugger-intro.gif new file mode 100644 index 00000000000..06e3b853555 Binary files /dev/null and b/docs/static/img/debugger/debugger-intro.gif differ diff --git a/docs/static/img/debugger/ref1-create-launch.png b/docs/static/img/debugger/ref1-create-launch.png new file mode 100644 index 00000000000..0b6cb8b3ec6 Binary files /dev/null and b/docs/static/img/debugger/ref1-create-launch.png differ 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 index 744de72bb2c..23f60855c30 100644 --- 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 @@ -23,7 +23,7 @@ _Library crates_ don't have a `main` function and they don't compile down to ACI #### 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/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/noir-projects/noir-contracts/contracts). ### Crate Root 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 index d9ac92667c9..8168793fc80 100644 --- 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 @@ -10,16 +10,18 @@ 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 +│ ├── a +│ │ ├── Nargo.toml +│ │ └── Prover.toml +│ │ └── src +│ │ └── main.nr +│ └── b +│ ├── Nargo.toml +│ └── Prover.toml +│ └── src +│ └── main.nr +│ +└── Nargo.toml ``` You can define a workspace in Nargo.toml like so: 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 index 142cd02b94c..b3f1d6df747 100644 --- 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 @@ -18,7 +18,7 @@ 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: +First of all, follow 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 diff --git a/docs/versioned_docs/version-v0.19.0/language_concepts/06_generics.md b/docs/versioned_docs/version-v0.19.0/language_concepts/06_generics.md index b700bd5bc5b..a932d7b47c2 100644 --- a/docs/versioned_docs/version-v0.19.0/language_concepts/06_generics.md +++ b/docs/versioned_docs/version-v0.19.0/language_concepts/06_generics.md @@ -107,7 +107,3 @@ fn main() { let array = [MyStruct::new(), MyStruct::new()]; assert(array_eq(array, array, MyStruct::eq)); } -``` - -You can see an example of generics in the tests -[here](https://github.com/noir-lang/noir/blob/master/crates/nargo_cli/tests/test_data/generics/src/main.nr). diff --git a/docs/versioned_docs/version-v0.19.0/modules_packages_crates/crates_and_packages.md b/docs/versioned_docs/version-v0.19.0/modules_packages_crates/crates_and_packages.md index 744de72bb2c..23f60855c30 100644 --- a/docs/versioned_docs/version-v0.19.0/modules_packages_crates/crates_and_packages.md +++ b/docs/versioned_docs/version-v0.19.0/modules_packages_crates/crates_and_packages.md @@ -23,7 +23,7 @@ _Library crates_ don't have a `main` function and they don't compile down to ACI #### 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/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/noir-projects/noir-contracts/contracts). ### Crate Root diff --git a/docs/versioned_docs/version-v0.19.0/modules_packages_crates/workspaces.md b/docs/versioned_docs/version-v0.19.0/modules_packages_crates/workspaces.md index d9ac92667c9..8168793fc80 100644 --- a/docs/versioned_docs/version-v0.19.0/modules_packages_crates/workspaces.md +++ b/docs/versioned_docs/version-v0.19.0/modules_packages_crates/workspaces.md @@ -10,16 +10,18 @@ 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 +│ ├── a +│ │ ├── Nargo.toml +│ │ └── Prover.toml +│ │ └── src +│ │ └── main.nr +│ └── b +│ ├── Nargo.toml +│ └── Prover.toml +│ └── src +│ └── main.nr +│ +└── Nargo.toml ``` You can define a workspace in Nargo.toml like so: diff --git a/docs/versioned_docs/version-v0.19.0/noir_js/getting_started/01_tiny_noir_app.md b/docs/versioned_docs/version-v0.19.0/noir_js/getting_started/01_tiny_noir_app.md index 795baa59d59..64ba4a2c44a 100644 --- a/docs/versioned_docs/version-v0.19.0/noir_js/getting_started/01_tiny_noir_app.md +++ b/docs/versioned_docs/version-v0.19.0/noir_js/getting_started/01_tiny_noir_app.md @@ -20,7 +20,7 @@ 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: +First of all, follow 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 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 index 744de72bb2c..23f60855c30 100644 --- 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 @@ -23,7 +23,7 @@ _Library crates_ don't have a `main` function and they don't compile down to ACI #### 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/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/noir-projects/noir-contracts/contracts). ### Crate Root 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 index d9ac92667c9..8168793fc80 100644 --- 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 @@ -10,16 +10,18 @@ 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 +│ ├── a +│ │ ├── Nargo.toml +│ │ └── Prover.toml +│ │ └── src +│ │ └── main.nr +│ └── b +│ ├── Nargo.toml +│ └── Prover.toml +│ └── src +│ └── main.nr +│ +└── Nargo.toml ``` You can define a workspace in Nargo.toml like so: 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 index 795baa59d59..64ba4a2c44a 100644 --- 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 @@ -20,7 +20,7 @@ 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: +First of all, follow 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 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 index 744de72bb2c..23f60855c30 100644 --- 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 @@ -23,7 +23,7 @@ _Library crates_ don't have a `main` function and they don't compile down to ACI #### 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/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/noir-projects/noir-contracts/contracts). ### Crate Root 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 index d9ac92667c9..8168793fc80 100644 --- 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 @@ -10,16 +10,18 @@ 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 +│ ├── a +│ │ ├── Nargo.toml +│ │ └── Prover.toml +│ │ └── src +│ │ └── main.nr +│ └── b +│ ├── Nargo.toml +│ └── Prover.toml +│ └── src +│ └── main.nr +│ +└── Nargo.toml ``` You can define a workspace in Nargo.toml like so: 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 index 795baa59d59..64ba4a2c44a 100644 --- 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 @@ -20,7 +20,7 @@ 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: +First of all, follow 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 diff --git a/docs/versioned_docs/version-v0.19.3/modules_packages_crates/crates_and_packages.md b/docs/versioned_docs/version-v0.19.3/modules_packages_crates/crates_and_packages.md index 744de72bb2c..23f60855c30 100644 --- a/docs/versioned_docs/version-v0.19.3/modules_packages_crates/crates_and_packages.md +++ b/docs/versioned_docs/version-v0.19.3/modules_packages_crates/crates_and_packages.md @@ -23,7 +23,7 @@ _Library crates_ don't have a `main` function and they don't compile down to ACI #### 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/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/noir-projects/noir-contracts/contracts). ### Crate Root diff --git a/docs/versioned_docs/version-v0.19.3/modules_packages_crates/workspaces.md b/docs/versioned_docs/version-v0.19.3/modules_packages_crates/workspaces.md index a979ef9f0a5..8168793fc80 100644 --- a/docs/versioned_docs/version-v0.19.3/modules_packages_crates/workspaces.md +++ b/docs/versioned_docs/version-v0.19.3/modules_packages_crates/workspaces.md @@ -10,16 +10,18 @@ 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 +│ ├── a +│ │ ├── Nargo.toml +│ │ └── Prover.toml +│ │ └── src +│ │ └── main.nr +│ └── b +│ ├── Nargo.toml +│ └── Prover.toml +│ └── src +│ └── main.nr +│ +└── Nargo.toml ``` You can define a workspace in Nargo.toml like so: @@ -36,4 +38,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. \ No newline at end of file +Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/docs/versioned_docs/version-v0.19.3/noir_js/getting_started/01_tiny_noir_app.md b/docs/versioned_docs/version-v0.19.3/noir_js/getting_started/01_tiny_noir_app.md index 795baa59d59..64ba4a2c44a 100644 --- a/docs/versioned_docs/version-v0.19.3/noir_js/getting_started/01_tiny_noir_app.md +++ b/docs/versioned_docs/version-v0.19.3/noir_js/getting_started/01_tiny_noir_app.md @@ -20,7 +20,7 @@ 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: +First of all, follow 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 diff --git a/docs/versioned_docs/version-v0.19.4/modules_packages_crates/crates_and_packages.md b/docs/versioned_docs/version-v0.19.4/modules_packages_crates/crates_and_packages.md index 744de72bb2c..23f60855c30 100644 --- a/docs/versioned_docs/version-v0.19.4/modules_packages_crates/crates_and_packages.md +++ b/docs/versioned_docs/version-v0.19.4/modules_packages_crates/crates_and_packages.md @@ -23,7 +23,7 @@ _Library crates_ don't have a `main` function and they don't compile down to ACI #### 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/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/noir-projects/noir-contracts/contracts). ### Crate Root diff --git a/docs/versioned_docs/version-v0.19.4/modules_packages_crates/workspaces.md b/docs/versioned_docs/version-v0.19.4/modules_packages_crates/workspaces.md index a979ef9f0a5..8168793fc80 100644 --- a/docs/versioned_docs/version-v0.19.4/modules_packages_crates/workspaces.md +++ b/docs/versioned_docs/version-v0.19.4/modules_packages_crates/workspaces.md @@ -10,16 +10,18 @@ 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 +│ ├── a +│ │ ├── Nargo.toml +│ │ └── Prover.toml +│ │ └── src +│ │ └── main.nr +│ └── b +│ ├── Nargo.toml +│ └── Prover.toml +│ └── src +│ └── main.nr +│ +└── Nargo.toml ``` You can define a workspace in Nargo.toml like so: @@ -36,4 +38,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. \ No newline at end of file +Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/docs/versioned_docs/version-v0.19.4/noir_js/getting_started/01_tiny_noir_app.md b/docs/versioned_docs/version-v0.19.4/noir_js/getting_started/01_tiny_noir_app.md index 795baa59d59..64ba4a2c44a 100644 --- a/docs/versioned_docs/version-v0.19.4/noir_js/getting_started/01_tiny_noir_app.md +++ b/docs/versioned_docs/version-v0.19.4/noir_js/getting_started/01_tiny_noir_app.md @@ -20,7 +20,7 @@ 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: +First of all, follow 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 diff --git a/docs/versioned_docs/version-v0.22.0/getting_started/tooling/index.md b/docs/versioned_docs/version-v0.22.0/getting_started/tooling/index.md index 55df833005a..16f5f3ca45e 100644 --- a/docs/versioned_docs/version-v0.22.0/getting_started/tooling/index.md +++ b/docs/versioned_docs/version-v0.22.0/getting_started/tooling/index.md @@ -1,15 +1,11 @@ --- title: Tooling -Description: This section provides information about the various tools and utilities available for Noir development. It covers the Noir playground, IDE tools, Codespaces, and community projects. +Description: This section provides information about the various tools and utilities available for Noir development. It covers IDE tools, Codespaces, and community projects. Keywords: [Noir, Development, Playground, IDE Tools, Language Service Provider, VS Code Extension, Codespaces, noir-starter, Community Projects, Awesome Noir Repository, Developer Tooling] --- Noir is meant to be easy to develop with. For that reason, a number of utilities have been put together to ease the development process as much as feasible in the zero-knowledge world. -## Playground - -The Noir playground is an easy way to test small ideas, share snippets, and integrate in other websites. You can access it at [play.noir-lang.org](https://play.noir-lang.org). - ## IDE tools When you install Nargo, you're also installing a Language Service Provider (LSP), which can be used by IDEs to provide syntax highlighting, codelens, warnings, and more. diff --git a/docs/versioned_docs/version-v0.22.0/noir/modules_packages_crates/crates_and_packages.md b/docs/versioned_docs/version-v0.22.0/noir/modules_packages_crates/crates_and_packages.md index 760a463094c..95ee9f52ab2 100644 --- a/docs/versioned_docs/version-v0.22.0/noir/modules_packages_crates/crates_and_packages.md +++ b/docs/versioned_docs/version-v0.22.0/noir/modules_packages_crates/crates_and_packages.md @@ -24,7 +24,7 @@ _Library crates_ don't have a `main` function and they don't compile down to ACI #### 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/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/noir-projects/noir-contracts/contracts). ### Crate Root diff --git a/docs/versioned_docs/version-v0.22.0/noir/modules_packages_crates/workspaces.md b/docs/versioned_docs/version-v0.22.0/noir/modules_packages_crates/workspaces.md index 67a1dafa372..513497f12bf 100644 --- a/docs/versioned_docs/version-v0.22.0/noir/modules_packages_crates/workspaces.md +++ b/docs/versioned_docs/version-v0.22.0/noir/modules_packages_crates/workspaces.md @@ -11,16 +11,18 @@ 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 +│ ├── a +│ │ ├── Nargo.toml +│ │ └── Prover.toml +│ │ └── src +│ │ └── main.nr +│ └── b +│ ├── Nargo.toml +│ └── Prover.toml +│ └── src +│ └── main.nr +│ +└── Nargo.toml ``` You can define a workspace in Nargo.toml like so: diff --git a/docs/versioned_docs/version-v0.22.0/tutorials/noirjs_app.md b/docs/versioned_docs/version-v0.22.0/tutorials/noirjs_app.md index 0763b6224c9..516e07c89fd 100644 --- a/docs/versioned_docs/version-v0.22.0/tutorials/noirjs_app.md +++ b/docs/versioned_docs/version-v0.22.0/tutorials/noirjs_app.md @@ -21,7 +21,7 @@ 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/installation/index.md) to install nargo version 0.17.0 and create a new project with `nargo new circuit`. Once there, `cd` into the `circuit` folder. You should then be able to compile your circuit into `json` format and see it inside the `target` folder: +First of all, follow the [Nargo guide](../getting_started/installation/index.md) to install nargo version 0.17.0 and create a new project with `nargo new circuit`. Once there, `cd` into the `circuit` folder. You should then be able to compile your circuit into `json` format and see it inside the `target` folder: ```bash nargo compile diff --git a/docs/versioned_docs/version-v0.23.0/getting_started/tooling/index.mdx b/docs/versioned_docs/version-v0.23.0/getting_started/tooling/index.mdx index ac480f3c9f5..ec9ccea4115 100644 --- a/docs/versioned_docs/version-v0.23.0/getting_started/tooling/index.mdx +++ b/docs/versioned_docs/version-v0.23.0/getting_started/tooling/index.mdx @@ -1,15 +1,11 @@ --- title: Tooling -Description: This section provides information about the various tools and utilities available for Noir development. It covers the Noir playground, IDE tools, Codespaces, and community projects. +Description: This section provides information about the various tools and utilities available for Noir development. It covers IDE tools, Codespaces, and community projects. Keywords: [Noir, Development, Playground, IDE Tools, Language Service Provider, VS Code Extension, Codespaces, noir-starter, Community Projects, Awesome Noir Repository, Developer Tooling] --- Noir is meant to be easy to develop with. For that reason, a number of utilities have been put together to ease the development process as much as feasible in the zero-knowledge world. -## Playground - -The Noir playground is an easy way to test small ideas, share snippets, and integrate in other websites. You can access it at [play.noir-lang.org](https://play.noir-lang.org). - ## IDE tools When you install Nargo, you're also installing a Language Service Provider (LSP), which can be used by IDEs to provide syntax highlighting, codelens, warnings, and more. diff --git a/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/index.md b/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/index.md index 3c9cd4c2437..f09bca0ee04 100644 --- a/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/index.md +++ b/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/index.md @@ -79,7 +79,7 @@ fn main() { } ``` -Type aliases can also be used with [generics](@site/docs/noir/concepts/generics.md): +Type aliases can also be used with [generics](../generics.md): ```rust type Id = Size; diff --git a/docs/versioned_docs/version-v0.23.0/noir/modules_packages_crates/crates_and_packages.md b/docs/versioned_docs/version-v0.23.0/noir/modules_packages_crates/crates_and_packages.md index 760a463094c..95ee9f52ab2 100644 --- a/docs/versioned_docs/version-v0.23.0/noir/modules_packages_crates/crates_and_packages.md +++ b/docs/versioned_docs/version-v0.23.0/noir/modules_packages_crates/crates_and_packages.md @@ -24,7 +24,7 @@ _Library crates_ don't have a `main` function and they don't compile down to ACI #### 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/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/noir-projects/noir-contracts/contracts). ### Crate Root diff --git a/docs/versioned_docs/version-v0.23.0/noir/modules_packages_crates/workspaces.md b/docs/versioned_docs/version-v0.23.0/noir/modules_packages_crates/workspaces.md index 67a1dafa372..513497f12bf 100644 --- a/docs/versioned_docs/version-v0.23.0/noir/modules_packages_crates/workspaces.md +++ b/docs/versioned_docs/version-v0.23.0/noir/modules_packages_crates/workspaces.md @@ -11,16 +11,18 @@ 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 +│ ├── a +│ │ ├── Nargo.toml +│ │ └── Prover.toml +│ │ └── src +│ │ └── main.nr +│ └── b +│ ├── Nargo.toml +│ └── Prover.toml +│ └── src +│ └── main.nr +│ +└── Nargo.toml ``` You can define a workspace in Nargo.toml like so: diff --git a/docs/versioned_docs/version-v0.23.0/tutorials/noirjs_app.md b/docs/versioned_docs/version-v0.23.0/tutorials/noirjs_app.md index 82899217e61..e3bc8c58b24 100644 --- a/docs/versioned_docs/version-v0.23.0/tutorials/noirjs_app.md +++ b/docs/versioned_docs/version-v0.23.0/tutorials/noirjs_app.md @@ -24,7 +24,7 @@ Before we start, we want to make sure we have Node and Nargo installed. We start by opening a terminal and executing `node --version`. If we don't get an output like `v20.10.0`, that means node is not installed. Let's do that by following the handy [nvm guide](https://github.com/nvm-sh/nvm?tab=readme-ov-file#install--update-script). -As for `Nargo`, we can follow the the [Nargo guide](../getting_started/installation/index.md) to install it. If you're lazy, just paste this on a terminal and run `noirup`: +As for `Nargo`, we can follow the [Nargo guide](../getting_started/installation/index.md) to install it. If you're lazy, just paste this on a terminal and run `noirup`: ```sh curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash diff --git a/docs/versioned_docs/version-v0.24.0/getting_started/tooling/index.mdx b/docs/versioned_docs/version-v0.24.0/getting_started/tooling/index.mdx index ac480f3c9f5..ec9ccea4115 100644 --- a/docs/versioned_docs/version-v0.24.0/getting_started/tooling/index.mdx +++ b/docs/versioned_docs/version-v0.24.0/getting_started/tooling/index.mdx @@ -1,15 +1,11 @@ --- title: Tooling -Description: This section provides information about the various tools and utilities available for Noir development. It covers the Noir playground, IDE tools, Codespaces, and community projects. +Description: This section provides information about the various tools and utilities available for Noir development. It covers IDE tools, Codespaces, and community projects. Keywords: [Noir, Development, Playground, IDE Tools, Language Service Provider, VS Code Extension, Codespaces, noir-starter, Community Projects, Awesome Noir Repository, Developer Tooling] --- Noir is meant to be easy to develop with. For that reason, a number of utilities have been put together to ease the development process as much as feasible in the zero-knowledge world. -## Playground - -The Noir playground is an easy way to test small ideas, share snippets, and integrate in other websites. You can access it at [play.noir-lang.org](https://play.noir-lang.org). - ## IDE tools When you install Nargo, you're also installing a Language Service Provider (LSP), which can be used by IDEs to provide syntax highlighting, codelens, warnings, and more. diff --git a/docs/versioned_docs/version-v0.24.0/how_to/how-to-oracles.md b/docs/versioned_docs/version-v0.24.0/how_to/how-to-oracles.md index 0d84d992320..ab225b9421f 100644 --- a/docs/versioned_docs/version-v0.24.0/how_to/how-to-oracles.md +++ b/docs/versioned_docs/version-v0.24.0/how_to/how-to-oracles.md @@ -198,7 +198,7 @@ For example, if your Noir program expects the host machine to provide CPU pseudo ```js const foreignCallHandler = (name, inputs) => crypto.randomBytes(16) // etc -await noir.generateFinalProof(inputs, foreignCallHandler) +await noir.generateProof(inputs, foreignCallHandler) ``` As one can see, in NoirJS, the [`foreignCallHandler`](../reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md) function simply means "a callback function that returns a value of type [`ForeignCallOutput`](../reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md). It doesn't have to be an RPC call like in the case for Nargo. diff --git a/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/index.md b/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/index.md index 3c9cd4c2437..f09bca0ee04 100644 --- a/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/index.md +++ b/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/index.md @@ -79,7 +79,7 @@ fn main() { } ``` -Type aliases can also be used with [generics](@site/docs/noir/concepts/generics.md): +Type aliases can also be used with [generics](../generics.md): ```rust type Id = Size; diff --git a/docs/versioned_docs/version-v0.24.0/noir/modules_packages_crates/crates_and_packages.md b/docs/versioned_docs/version-v0.24.0/noir/modules_packages_crates/crates_and_packages.md index 760a463094c..95ee9f52ab2 100644 --- a/docs/versioned_docs/version-v0.24.0/noir/modules_packages_crates/crates_and_packages.md +++ b/docs/versioned_docs/version-v0.24.0/noir/modules_packages_crates/crates_and_packages.md @@ -24,7 +24,7 @@ _Library crates_ don't have a `main` function and they don't compile down to ACI #### 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/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/noir-projects/noir-contracts/contracts). ### Crate Root diff --git a/docs/versioned_docs/version-v0.24.0/noir/modules_packages_crates/workspaces.md b/docs/versioned_docs/version-v0.24.0/noir/modules_packages_crates/workspaces.md index 67a1dafa372..513497f12bf 100644 --- a/docs/versioned_docs/version-v0.24.0/noir/modules_packages_crates/workspaces.md +++ b/docs/versioned_docs/version-v0.24.0/noir/modules_packages_crates/workspaces.md @@ -11,16 +11,18 @@ 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 +│ ├── a +│ │ ├── Nargo.toml +│ │ └── Prover.toml +│ │ └── src +│ │ └── main.nr +│ └── b +│ ├── Nargo.toml +│ └── Prover.toml +│ └── src +│ └── main.nr +│ +└── Nargo.toml ``` You can define a workspace in Nargo.toml like so: diff --git a/docs/versioned_docs/version-v0.24.0/noir/standard_library/black_box_fns.md b/docs/versioned_docs/version-v0.24.0/noir/standard_library/black_box_fns.md index eae8744abf0..be8c65679c3 100644 --- a/docs/versioned_docs/version-v0.24.0/noir/standard_library/black_box_fns.md +++ b/docs/versioned_docs/version-v0.24.0/noir/standard_library/black_box_fns.md @@ -12,18 +12,18 @@ The ACVM spec defines a set of blackbox functions which backends will be expecte Here is a list of the current black box functions: -- [SHA256](./cryptographic_primitives/hashes#sha256) -- [Schnorr signature verification](./cryptographic_primitives/schnorr) -- [Blake2s](./cryptographic_primitives/hashes#blake2s) -- [Blake3](./cryptographic_primitives/hashes#blake3) -- [Pedersen Hash](./cryptographic_primitives/hashes#pedersen_hash) -- [Pedersen Commitment](./cryptographic_primitives/hashes#pedersen_commitment) -- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification) -- [Fixed base scalar multiplication](./cryptographic_primitives/scalar) +- [SHA256](./cryptographic_primitives/hashes.mdx#sha256) +- [Schnorr signature verification](./cryptographic_primitives/schnorr.mdx) +- [Blake2s](./cryptographic_primitives/hashes.mdx#blake2s) +- [Blake3](./cryptographic_primitives/hashes.mdx#blake3) +- [Pedersen Hash](./cryptographic_primitives/hashes.mdx#pedersen_hash) +- [Pedersen Commitment](./cryptographic_primitives/hashes.mdx#pedersen_commitment) +- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification.mdx) +- [Fixed base scalar multiplication](./cryptographic_primitives/scalar.mdx) - AND - XOR - RANGE -- [Keccak256](./cryptographic_primitives/hashes#keccak256) +- [Keccak256](./cryptographic_primitives/hashes.mdx#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. diff --git a/docs/versioned_docs/version-v0.24.0/tutorials/noirjs_app.md b/docs/versioned_docs/version-v0.24.0/tutorials/noirjs_app.md index ad76dd255cc..0d75e2e8045 100644 --- a/docs/versioned_docs/version-v0.24.0/tutorials/noirjs_app.md +++ b/docs/versioned_docs/version-v0.24.0/tutorials/noirjs_app.md @@ -24,7 +24,7 @@ Before we start, we want to make sure we have Node and Nargo installed. We start by opening a terminal and executing `node --version`. If we don't get an output like `v20.10.0`, that means node is not installed. Let's do that by following the handy [nvm guide](https://github.com/nvm-sh/nvm?tab=readme-ov-file#install--update-script). -As for `Nargo`, we can follow the the [Nargo guide](../getting_started/installation/index.md) to install it. If you're lazy, just paste this on a terminal and run `noirup`: +As for `Nargo`, we can follow the [Nargo guide](../getting_started/installation/index.md) to install it. If you're lazy, just paste this on a terminal and run `noirup`: ```sh curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash @@ -243,7 +243,7 @@ Now we're ready to prove stuff! Let's feed some inputs to our circuit and calcul await setup(); // let's squeeze our wasm inits here display('logs', 'Generating proof... ⌛'); -const proof = await noir.generateFinalProof(input); +const proof = await noir.generateProof(input); display('logs', 'Generating proof... ✅'); display('results', proof.proof); ``` @@ -264,7 +264,7 @@ Time to celebrate, yes! But we shouldn't trust machines so blindly. Let's add th ```js display('logs', 'Verifying proof... ⌛'); -const verification = await noir.verifyFinalProof(proof); +const verification = await noir.verifyProof(proof); if (verification) display('logs', 'Verifying proof... ✅'); ``` diff --git a/docs/versioned_docs/version-v0.25.0/explainers/explainer-oracle.md b/docs/versioned_docs/version-v0.25.0/explainers/explainer-oracle.md new file mode 100644 index 00000000000..b84ca5dd986 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/explainers/explainer-oracle.md @@ -0,0 +1,57 @@ +--- +title: Oracles +description: This guide provides an in-depth understanding of how Oracles work in Noir programming. Learn how to use outside calculations in your programs, constrain oracles, and understand their uses and limitations. +keywords: + - Noir Programming + - Oracles + - JSON-RPC + - Foreign Call Handlers + - Constrained Functions + - Blockchain Programming +sidebar_position: 1 +--- + +If you've seen "The Matrix" you may recall "The Oracle" as Gloria Foster smoking cigarettes and baking cookies. While she appears to "know things", she is actually providing a calculation of a pre-determined future. Noir Oracles are similar, in a way. They don't calculate the future (yet), but they allow you to use outside calculations in your programs. + +![matrix oracle prediction](@site/static/img/memes/matrix_oracle.jpeg) + +A Noir program is usually self-contained. You can pass certain inputs to it, and it will generate a deterministic output for those inputs. But what if you wanted to defer some calculation to an outside process or source? + +Oracles are functions that provide this feature. + +## Use cases + +An example usage for Oracles is proving something on-chain. For example, proving that the ETH-USDC quote was below a certain target at a certain block time. Or even making more complex proofs like proving the ownership of an NFT as an anonymous login method. + +Another interesting use case is to defer expensive calculations to be made outside of the Noir program, and then constraining the result; similar to the use of [unconstrained functions](../noir/concepts//unconstrained.md). + +In short, anything that can be constrained in a Noir program but needs to be fetched from an external source is a great candidate to be used in oracles. + +## Constraining oracles + +Just like in The Matrix, Oracles are powerful. But with great power, comes great responsibility. Just because you're using them in a Noir program doesn't mean they're true. Noir has no superpowers. If you want to prove that Portugal won the Euro Cup 2016, you're still relying on potentially untrusted information. + +To give a concrete example, Alice wants to login to the [NounsDAO](https://nouns.wtf/) forum with her username "noir_nouner" by proving she owns a noun without revealing her ethereum address. Her Noir program could have a oracle call like this: + +```rust +#[oracle(getNoun)] +unconstrained fn get_noun(address: Field) -> Field +``` + +This oracle could naively resolve with the number of Nouns she possesses. However, it is useless as a trusted source, as the oracle could resolve to anything Alice wants. In order to make this oracle call actually useful, Alice would need to constrain the response from the oracle, by proving her address and the noun count belongs to the state tree of the contract. + +In short, **Oracles don't prove anything. Your Noir program does.** + +:::danger + +If you don't constrain the return of your oracle, you could be clearly opening an attack vector on your Noir program. Make double-triple sure that the return of an oracle call is constrained! + +::: + +## How to use Oracles + +On CLI, Nargo resolves oracles by making JSON RPC calls, which means it would require an RPC node to be running. + +In JavaScript, NoirJS accepts and resolves arbitrary call handlers (that is, not limited to JSON) as long as they matches the expected types the developer defines. Refer to [Foreign Call Handler](../reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md) to learn more about NoirJS's call handling. + +If you want to build using oracles, follow through to the [oracle guide](../how_to/how-to-oracles.md) for a simple example on how to do that. diff --git a/docs/versioned_docs/version-v0.25.0/explainers/explainer-recursion.md b/docs/versioned_docs/version-v0.25.0/explainers/explainer-recursion.md new file mode 100644 index 00000000000..18846176ca7 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/explainers/explainer-recursion.md @@ -0,0 +1,176 @@ +--- +title: Recursive proofs +description: Explore the concept of recursive proofs in Zero-Knowledge programming. Understand how recursion works in Noir, a language for writing smart contracts on the EVM blockchain. Learn through practical examples like Alice and Bob's guessing game, Charlie's recursive merkle tree, and Daniel's reusable components. Discover how to use recursive proofs to optimize computational resources and improve efficiency. + +keywords: + [ + "Recursive Proofs", + "Zero-Knowledge Programming", + "Noir", + "EVM Blockchain", + "Smart Contracts", + "Recursion in Noir", + "Alice and Bob Guessing Game", + "Recursive Merkle Tree", + "Reusable Components", + "Optimizing Computational Resources", + "Improving Efficiency", + "Verification Key", + "Aggregation", + "Recursive zkSNARK schemes", + "PLONK", + "Proving and Verification Keys" + ] +sidebar_position: 1 +pagination_next: how_to/how-to-recursion +--- + +In programming, we tend to think of recursion as something calling itself. A classic example would be the calculation of the factorial of a number: + +```js +function factorial(n) { + if (n === 0 || n === 1) { + return 1; + } else { + return n * factorial(n - 1); + } +} +``` + +In this case, while `n` is not `1`, this function will keep calling itself until it hits the base case, bubbling up the result on the call stack: + +```md + Is `n` 1? <--------- + /\ / + / \ n = n -1 + / \ / + Yes No -------- +``` + +In Zero-Knowledge, recursion has some similarities. + +It is not a Noir function calling itself, but a proof being used as an input to another circuit. In short, you verify one proof *inside* another proof, returning the proof that both proofs are valid. + +This means that, given enough computational resources, you can prove the correctness of any arbitrary number of proofs in a single proof. This could be useful to design state channels (for which a common example would be [Bitcoin's Lightning Network](https://en.wikipedia.org/wiki/Lightning_Network)), to save on gas costs by settling one proof on-chain, or simply to make business logic less dependent on a consensus mechanism. + +## Examples + +Let us look at some of these examples + +### Alice and Bob - Guessing game + +Alice and Bob are friends, and they like guessing games. They want to play a guessing game online, but for that, they need a trusted third-party that knows both of their secrets and finishes the game once someone wins. + +So, they use zero-knowledge proofs. Alice tries to guess Bob's number, and Bob will generate a ZK proof stating whether she succeeded or failed. + +This ZK proof can go on a smart contract, revealing the winner and even giving prizes. However, this means every turn needs to be verified on-chain. This incurs some cost and waiting time that may simply make the game too expensive or time-consuming to be worth it. + +As a solution, Alice proposes the following: "what if Bob generates his proof, and instead of sending it on-chain, I verify it *within* my own proof before playing my own turn?". + +She can then generate a proof that she verified his proof, and so on. + +```md + Did you fail? <-------------------------- + / \ / + / \ n = n -1 + / \ / + Yes No / + | | / + | | / + | You win / + | / + | / +Generate proof of that / + + / + my own guess ---------------- +``` + +### Charlie - Recursive merkle tree + +Charlie is a concerned citizen, and wants to be sure his vote in an election is accounted for. He votes with a ZK proof, but he has no way of knowing that his ZK proof was included in the total vote count! + +If the vote collector puts all of the votes into a [Merkle tree](https://en.wikipedia.org/wiki/Merkle_tree), everyone can prove the verification of two proofs within one proof, as such: + +```md + abcd + __________|______________ + | | + ab cd + _____|_____ ______|______ + | | | | + alice bob charlie daniel +``` + +Doing this recursively allows us to arrive on a final proof `abcd` which if true, verifies the correctness of all the votes. + +### Daniel - Reusable components + +Daniel has a big circuit and a big headache. A part of his circuit is a setup phase that finishes with some assertions that need to be made. But that section alone takes most of the proving time, and is largely independent of the rest of the circuit. + +He might find it more efficient to generate a proof for that setup phase separately, and verify that proof recursively in the actual business logic section of his circuit. This will allow for parallelization of both proofs, which results in a considerable speedup. + +## What params do I need + +As you can see in the [recursion reference](noir/standard_library/recursion.md), a simple recursive proof requires: + +- The proof to verify +- The Verification Key of the circuit that generated the proof +- A hash of this verification key, as it's needed for some backends +- The public inputs for the proof + +:::info + +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. + +So, taking the example of Alice and Bob and their guessing game: + +- Alice makes her guess. Her proof is *not* recursive: it doesn't verify any proof within it! It's just a standard `assert(x != y)` circuit +- Bob verifies Alice's proof and makes his own guess. In this circuit, he doesn't exactly *prove* the verification of Alice's proof. Instead, he *aggregates* his proof to Alice's proof. The actual verification is done when the full proof is verified, for example when using `nargo verify` or through the verifier smart contract. + +We can imagine recursive proofs a [relay race](https://en.wikipedia.org/wiki/Relay_race). The first runner doesn't have to receive the baton from anyone else, as he/she already starts with it. But when his/her turn is over, the next runner needs to receive it, run a bit more, and pass it along. Even though every runner could theoretically verify the baton mid-run (why not? 🏃🔍), only at the end of the race does the referee verify that the whole race is valid. + +::: + +## Some architecture + +As with everything in computer science, there's no one-size-fits all. But there are some patterns that could help understanding and implementing them. To give three examples: + +### Adding some logic to a proof verification + +This would be an approach for something like our guessing game, where proofs are sent back and forth and are verified by each opponent. This circuit would be divided in two sections: + +- A `recursive verification` section, which would be just the call to `std::verify_proof`, and that would be skipped on the first move (since there's no proof to verify) +- A `guessing` section, which is basically the logic part where the actual guessing happens + +In such a situation, and assuming Alice is first, she would skip the first part and try to guess Bob's number. Bob would then verify her proof on the first section of his run, and try to guess Alice's number on the second part, and so on. + +### Aggregating proofs + +In some one-way interaction situations, recursion would allow for aggregation of simple proofs that don't need to be immediately verified on-chain or elsewhere. + +To give a practical example, a barman wouldn't need to verify a "proof-of-age" on-chain every time he serves alcohol to a customer. Instead, the architecture would comprise two circuits: + +- A `main`, non-recursive circuit with some logic +- A `recursive` circuit meant to verify two proofs in one proof + +The customer's proofs would be intermediate, and made on their phones, and the barman could just verify them locally. He would then aggregate them into a final proof sent on-chain (or elsewhere) at the end of the day. + +### Recursively verifying different circuits + +Nothing prevents you from verifying different circuits in a recursive proof, for example: + +- A `circuit1` circuit +- A `circuit2` circuit +- A `recursive` circuit + +In this example, a regulator could verify that taxes were paid for a specific purchase by aggregating both a `payer` circuit (proving that a purchase was made and taxes were paid), and a `receipt` circuit (proving that the payment was received) + +## How fast is it + +At the time of writing, verifying recursive proofs is surprisingly fast. This is because most of the time is spent on generating the verification key that will be used to generate the next proof. So you are able to cache the verification key and reuse it later. + +Currently, Noir JS packages don't expose the functionality of loading proving and verification keys, but that feature exists in the underlying `bb.js` package. + +## How can I try it + +Learn more about using recursion in Nargo and NoirJS in the [how-to guide](../how_to/how-to-recursion.md) and see a full example in [noir-examples](https://github.com/noir-lang/noir-examples). diff --git a/docs/versioned_docs/version-v0.25.0/getting_started/_category_.json b/docs/versioned_docs/version-v0.25.0/getting_started/_category_.json new file mode 100644 index 00000000000..5d694210bbf --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/getting_started/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 0, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.25.0/getting_started/hello_noir/_category_.json b/docs/versioned_docs/version-v0.25.0/getting_started/hello_noir/_category_.json new file mode 100644 index 00000000000..23b560f610b --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/getting_started/hello_noir/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 1, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.25.0/getting_started/hello_noir/index.md b/docs/versioned_docs/version-v0.25.0/getting_started/hello_noir/index.md new file mode 100644 index 00000000000..743c4d8d634 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/getting_started/hello_noir/index.md @@ -0,0 +1,142 @@ +--- +title: Creating a Project +description: + Learn how to create and verify your first Noir program using Nargo, a programming language for + zero-knowledge proofs. +keywords: + [ + Nargo, + Noir, + zero-knowledge proofs, + programming language, + create Noir program, + verify Noir program, + step-by-step guide, + ] +sidebar_position: 1 + +--- + +Now that we have installed Nargo, it is time to make our first hello world program! + +## Create a Project Directory + +Noir code can live anywhere on your computer. Let us create a _projects_ folder in the home +directory to house our Noir programs. + +For Linux, macOS, and Windows PowerShell, create the directory and change directory into it by +running: + +```sh +mkdir ~/projects +cd ~/projects +``` + +## Create Our First Nargo Project + +Now that we are in the projects directory, create a new Nargo project by running: + +```sh +nargo new hello_world +``` + +> **Note:** `hello_world` can be any arbitrary project name, we are simply using `hello_world` for +> demonstration. +> +> In production, the common practice is to name the project folder as `circuits` for better +> identifiability when sitting alongside other folders in the codebase (e.g. `contracts`, `scripts`, +> `test`). + +A `hello_world` folder would be created. Similar to Rust, the folder houses _src/main.nr_ and +_Nargo.toml_ which contain 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](../../noir/concepts/data_types/index.md) section. + +The next line of the program specifies its body: + +```rust +assert(x != y); +``` + +The Noir syntax `assert` can be interpreted as something similar to constraints in other zk-contract languages. + +For more Noir syntax, check the [Language Concepts](../../noir/concepts/comments.md) chapter. + +## Build In/Output Files + +Change directory into _hello_world_ and build in/output files for your Noir program by running: + +```sh +cd hello_world +nargo check +``` + +Two additional files would be generated in your project directory: + +_Prover.toml_ houses input values, and _Verifier.toml_ houses public values. + +## Prove Our Noir Program + +Now that the project is set up, we can create a proof of correct execution of 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](./project_breakdown.md), we will go into more detail on each step performed. diff --git a/docs/versioned_docs/version-v0.25.0/getting_started/hello_noir/project_breakdown.md b/docs/versioned_docs/version-v0.25.0/getting_started/hello_noir/project_breakdown.md new file mode 100644 index 00000000000..6160a102c6c --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/getting_started/hello_noir/project_breakdown.md @@ -0,0 +1,199 @@ +--- +title: Project Breakdown +description: + Learn about the anatomy of a Nargo project, including the purpose of the Prover and Verifier TOML + files, and how to prove and verify your program. +keywords: + [Nargo, Nargo project, Prover.toml, Verifier.toml, proof verification, private asset transfer] +sidebar_position: 2 +--- + +This section breaks down our hello world program from the previous section. We elaborate on the project +structure and what the `prove` and `verify` commands did. + +## 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 = "noir_starter" +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](../../noir/modules_packages_crates/workspaces.md) will look a bit different. For example: + +```toml +[workspace] +members = ["crates/a", "crates/b"] +default-member = "crates/a" +``` + +#### Package section + +The package section defines 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](../../noir/modules_packages_crates/dependencies.md) for more info. + +`./proofs/` and `./contract/` directories will not be immediately visible until you create a proof or +verifier contract respectively. + +### main.nr + +The _main.nr_ file contains a `main` method, this method is the entry point into your Noir program. + +In our sample program, _main.nr_ looks like this: + +```rust +fn main(x : Field, y : Field) { + assert(x != y); +} +``` + +The parameters `x` and `y` can be seen as the API for the program and must be supplied by the +prover. Since neither `x` nor `y` is marked as public, the verifier does not supply any inputs, when +verifying the proof. + +The prover supplies the values for `x` and `y` in the _Prover.toml_ file. + +As for the program body, `assert` ensures that the condition to be satisfied (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 inequality 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, usually from external sources, and +verify the validity of the proof against it. + +Take a private asset transfer as an example: + +A person using a browser as the prover would retrieve private inputs locally (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.25.0/getting_started/installation/_category_.json b/docs/versioned_docs/version-v0.25.0/getting_started/installation/_category_.json new file mode 100644 index 00000000000..0c02fb5d4d7 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/getting_started/installation/_category_.json @@ -0,0 +1,6 @@ +{ + "position": 0, + "label": "Install Nargo", + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.25.0/getting_started/installation/index.md b/docs/versioned_docs/version-v0.25.0/getting_started/installation/index.md new file mode 100644 index 00000000000..4ef86aa5914 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/getting_started/installation/index.md @@ -0,0 +1,48 @@ +--- +title: Nargo Installation +description: + nargo is a command line tool for interacting with Noir programs. This page is a quick guide on how to install Nargo through the most common and easy method, noirup +keywords: [ + Nargo + Noir + Rust + Cargo + Noirup + Installation + Terminal Commands + Version Check + Nightlies + Specific Versions + Branches + Noirup Repository +] +pagination_next: getting_started/hello_noir/index +--- + +`nargo` is the one-stop-shop for almost everything related with Noir. The name comes from our love for Rust and its package manager `cargo`. + +With `nargo`, you can start new projects, compile, execute, prove, verify, test, generate solidity contracts, and do pretty much all that is available in Noir. + +Similarly to `rustup`, we also maintain an easy installation method that covers most machines: `noirup`. + +## Installing Noirup + +Open a terminal on your machine, and write: + +```bash +curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash +``` + +Close the terminal, open another one, and run + +```bash +noirup +``` + +Done. That's it. You should have the latest version working. You can check with `nargo --version`. + +You can also install nightlies, specific versions +or branches. Check out the [noirup repository](https://github.com/noir-lang/noirup) for more +information. + +Now we're ready to start working on [our first Noir program!](../hello_noir/index.md) diff --git a/docs/versioned_docs/version-v0.25.0/getting_started/installation/other_install_methods.md b/docs/versioned_docs/version-v0.25.0/getting_started/installation/other_install_methods.md new file mode 100644 index 00000000000..a35e34aaf9c --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/getting_started/installation/other_install_methods.md @@ -0,0 +1,254 @@ +--- +title: Alternative Install Methods +description: There are different ways to install Nargo, the one-stop shop and command-line tool for developing Noir programs. This guide explains other methods that don't rely on noirup, such as compiling from source, installing from binaries, and using WSL for windows +keywords: [ + Installation + Nargo + Noirup + Binaries + Compiling from Source + WSL for Windows + macOS + Linux + Nix + Direnv + Shell & editor experience + Building and testing + Uninstalling Nargo + Noir vs code extension, + ] +sidebar_position: 1 +--- + +## Encouraged Installation Method: Noirup + +Noirup is the endorsed method for installing Nargo, streamlining the process of fetching binaries or compiling from source. It supports a range of options to cater to your specific needs, from nightly builds and specific versions to compiling from various sources. + +### Installing Noirup + +First, ensure you have `noirup` installed: + +```sh +curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash +``` + +### Fetching Binaries + +With `noirup`, you can easily switch between different Nargo versions, including nightly builds: + +- **Nightly Version**: Install the latest nightly build. + + ```sh + noirup --version nightly + ``` + +- **Specific Version**: Install a specific version of Nargo. + ```sh + noirup --version + ``` + +### Compiling from Source + +`noirup` also enables compiling Nargo from various sources: + +- **From a Specific Branch**: Install from the latest commit on a branch. + + ```sh + noirup --branch + ``` + +- **From a Fork**: Install from the main branch of a fork. + + ```sh + noirup --repo + ``` + +- **From a Specific Branch in a Fork**: Install from a specific branch in a fork. + + ```sh + noirup --repo --branch + ``` + +- **From a Specific Pull Request**: Install from a specific PR. + + ```sh + noirup --pr + ``` + +- **From a Specific Commit**: Install from a specific commit. + + ```sh + noirup -C + ``` + +- **From Local Source**: Compile and install from a local directory. + ```sh + noirup --path ./path/to/local/source + ``` + +## Alternate Installation Methods (No Longer Recommended) + +While the following methods are available, they are no longer recommended. We advise using noirup for a more efficient and flexible installation experience. + +However, there are other methods for installing Nargo: + +- [Binaries](#option-1-installing-from-binaries) +- [Compiling from Source](#option-2-compile-from-source) +- [WSL for Windows](#option-3-wsl-for-windows) + +### Option 1: Installing from 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.24.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.24.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.24.0/nargo-x86_64-unknown-linux-gnu.tar.gz && \ +tar -xvf $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -C $HOME/.nargo/bin/ && \ +echo -e '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.bashrc && \ +source ~/.bashrc +``` + +#### Step 2 + +Check if the installation was successful by running `nargo --version`. You should get a version number. + +> **macOS:** If you are prompted with an OS alert, right-click and open the _nargo_ executable from +> Finder. Close the new terminal popped up and `nargo` should now be accessible. + +### Option 2: 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 issues 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 clears 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.73.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 3: WSL (for Windows) + +The default backend for Noir (Barretenberg) doesn't provide Windows binaries at this time. For that reason, Noir cannot be installed natively. 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](#encouraged-installation-method-noirup). + +## Uninstalling Nargo + +### Noirup + +If you installed Nargo with `noirup` or through directly downloading binaries, you can uninstall Nargo by removing the files in `~/.nargo`, `~/nargo`, and `~/noir_cache`. This ensures that all installed binaries, configurations, and cache related to Nargo are fully removed from your system. + +```bash +rm -r ~/.nargo +rm -r ~/nargo +rm -r ~/noir_cache +``` + +### Nix + +If you installed Nargo with Nix or compiled it from source, you can remove the binary located at `~/.nix-profile/bin/nargo`. + +```bash +rm ~/.nix-profile/bin/nargo +``` diff --git a/docs/docs/getting_started/tooling/_category_.json b/docs/versioned_docs/version-v0.25.0/getting_started/tooling/_category_.json similarity index 100% rename from docs/docs/getting_started/tooling/_category_.json rename to docs/versioned_docs/version-v0.25.0/getting_started/tooling/_category_.json diff --git a/docs/docs/getting_started/tooling/index.mdx b/docs/versioned_docs/version-v0.25.0/getting_started/tooling/index.mdx similarity index 84% rename from docs/docs/getting_started/tooling/index.mdx rename to docs/versioned_docs/version-v0.25.0/getting_started/tooling/index.mdx index ac480f3c9f5..ec9ccea4115 100644 --- a/docs/docs/getting_started/tooling/index.mdx +++ b/docs/versioned_docs/version-v0.25.0/getting_started/tooling/index.mdx @@ -1,15 +1,11 @@ --- title: Tooling -Description: This section provides information about the various tools and utilities available for Noir development. It covers the Noir playground, IDE tools, Codespaces, and community projects. +Description: This section provides information about the various tools and utilities available for Noir development. It covers IDE tools, Codespaces, and community projects. Keywords: [Noir, Development, Playground, IDE Tools, Language Service Provider, VS Code Extension, Codespaces, noir-starter, Community Projects, Awesome Noir Repository, Developer Tooling] --- Noir is meant to be easy to develop with. For that reason, a number of utilities have been put together to ease the development process as much as feasible in the zero-knowledge world. -## Playground - -The Noir playground is an easy way to test small ideas, share snippets, and integrate in other websites. You can access it at [play.noir-lang.org](https://play.noir-lang.org). - ## IDE tools When you install Nargo, you're also installing a Language Service Provider (LSP), which can be used by IDEs to provide syntax highlighting, codelens, warnings, and more. diff --git a/docs/versioned_docs/version-v0.25.0/getting_started/tooling/language_server.md b/docs/versioned_docs/version-v0.25.0/getting_started/tooling/language_server.md new file mode 100644 index 00000000000..81e0356ef8a --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/getting_started/tooling/language_server.md @@ -0,0 +1,43 @@ +--- +title: Language Server +description: Learn about the Noir Language Server, how to install the components, and configuration that may be required. +keywords: [Nargo, Language Server, LSP, VSCode, Visual Studio Code] +sidebar_position: 0 +--- + +This section helps you install and configure the Noir Language Server. + +The Language Server Protocol (LSP) has two components, the [Server](#language-server) and the [Client](#language-client). Below we describe each in the context of Noir. + +## Language Server + +The Server component is provided by the Nargo command line tool that you installed at the beginning of this guide. +As long as Nargo is installed and you've used it to run other commands in this guide, it should be good to go! + +If you'd like to verify that the `nargo lsp` command is available, you can run `nargo --help` and look for `lsp` in the list of commands. If you see it, you're using a version of Noir with LSP support. + +## Language Client + +The Client component is usually an editor plugin that launches the Server. It communicates LSP messages between the editor and the Server. For example, when you save a file, the Client will alert the Server, so it can try to compile the project and report any errors. + +Currently, Noir provides a Language Client for Visual Studio Code via the [vscode-noir](https://github.com/noir-lang/vscode-noir) extension. You can install it via the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir). + +> **Note:** Noir's Language Server Protocol support currently assumes users' VSCode workspace root to be the same as users' Noir project root (i.e. where Nargo.toml lies). +> +> If LSP features seem to be missing / malfunctioning, make sure you are opening your Noir project directly (instead of as a sub-folder) in your VSCode instance. + +When your language server is running correctly and the VSCode plugin is installed, you should see handy codelens buttons for compilation, measuring circuit size, execution, and tests: + +![Compile and Execute](@site/static/img/codelens_compile_execute.png) +![Run test](@site/static/img/codelens_run_test.png) + +You should also see your tests in the `testing` panel: + +![Testing panel](@site/static/img/codelens_testing_panel.png) + +### Configuration + +- **Noir: Enable LSP** - If checked, the extension will launch the Language Server via `nargo lsp` and communicate with it. +- **Noir: Nargo Flags** - Additional flags may be specified if you require them to be added when the extension calls `nargo lsp`. +- **Noir: Nargo Path** - An absolute path to a Nargo binary with the `lsp` command. This may be useful if Nargo is not within the `PATH` of your editor. +- **Noir > Trace: Server** - Setting this to `"messages"` or `"verbose"` will log LSP messages between the Client and Server. Useful for debugging. diff --git a/docs/versioned_docs/version-v0.25.0/getting_started/tooling/testing.md b/docs/versioned_docs/version-v0.25.0/getting_started/tooling/testing.md new file mode 100644 index 00000000000..d3e0c522473 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/getting_started/tooling/testing.md @@ -0,0 +1,62 @@ +--- +title: Testing in Noir +description: Learn how to use Nargo to test your Noir program in a quick and easy way +keywords: [Nargo, testing, Noir, compile, test] +sidebar_position: 1 +--- + +You can test your Noir programs using Noir circuits. + +Nargo will automatically compile and run any functions which have the decorator `#[test]` on them if +you run `nargo test`. + +For example if you have a program like: + +```rust +fn add(x: u64, y: u64) -> u64 { + x + y +} +#[test] +fn test_add() { + assert(add(2,2) == 4); + assert(add(0,1) == 1); + assert(add(1,0) == 1); +} +``` + +Running `nargo test` will test that the `test_add` function can be executed while satisfying all +the constraints 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.25.0/how_to/_category_.json b/docs/versioned_docs/version-v0.25.0/how_to/_category_.json new file mode 100644 index 00000000000..23b560f610b --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/how_to/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 1, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.25.0/how_to/how-to-oracles.md b/docs/versioned_docs/version-v0.25.0/how_to/how-to-oracles.md new file mode 100644 index 00000000000..ab225b9421f --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/how_to/how-to-oracles.md @@ -0,0 +1,280 @@ +--- +title: How to use Oracles +description: Learn how to use oracles in your Noir program with examples in both Nargo and NoirJS. This guide also covers writing a JSON RPC server and providing custom foreign call handlers for NoirJS. +keywords: + - Noir Programming + - Oracles + - Nargo + - NoirJS + - JSON RPC Server + - Foreign Call Handlers +sidebar_position: 1 +--- + +This guide shows you how to use oracles in your Noir program. For the sake of clarity, it assumes that: + +- You have read the [explainer on Oracles](../explainers/explainer-oracle.md) and are comfortable with the concept. +- You have a Noir program to add oracles to. You can create one using the [vite-hardhat starter](https://github.com/noir-lang/noir-starter/tree/main/vite-hardhat) as a boilerplate. +- You understand the concept of a JSON-RPC server. Visit the [JSON-RPC website](https://www.jsonrpc.org/) if you need a refresher. +- You are comfortable with server-side JavaScript (e.g. Node.js, managing packages, etc.). + +For reference, you can find the snippets used in this tutorial on the [Aztec DevRel Repository](https://github.com/AztecProtocol/dev-rel/tree/main/code-snippets/how-to-oracles). + +## Rundown + +This guide has 3 major steps: + +1. How to modify our Noir program to make use of oracle calls as unconstrained functions +2. How to write a JSON RPC Server to resolve these oracle calls with Nargo +3. How to use them in Nargo and how to provide a custom resolver in NoirJS + +## Step 1 - Modify your Noir program + +An oracle is defined in a Noir program by defining two methods: + +- An unconstrained method - This tells the compiler that it is executing an [unconstrained functions](../noir/concepts//unconstrained.md). +- A decorated oracle method - This tells the compiler that this method is an RPC call. + +An example of an oracle that returns a `Field` would be: + +```rust +#[oracle(getSqrt)] +unconstrained fn sqrt(number: Field) -> Field { } + +unconstrained fn get_sqrt(number: Field) -> Field { + sqrt(number) +} +``` + +In this example, we're wrapping our oracle function in a unconstrained method, and decorating it with `oracle(getSqrt)`. We can then call the unconstrained function as we would call any other function: + +```rust +fn main(input: Field) { + let sqrt = get_sqrt(input); +} +``` + +In the next section, we will make this `getSqrt` (defined on the `sqrt` decorator) be a method of the RPC server Noir will use. + +:::danger + +As explained in the [Oracle Explainer](../explainers/explainer-oracle.md), this `main` function is unsafe unless you constrain its return value. For example: + +```rust +fn main(input: Field) { + let sqrt = get_sqrt(input); + assert(sqrt.pow_32(2) as u64 == input as u64); // <---- constrain the return of an oracle! +} +``` + +::: + +:::info + +Currently, oracles only work with single params or array params. For example: + +```rust +#[oracle(getSqrt)] +unconstrained fn sqrt([Field; 2]) -> [Field; 2] { } +``` + +::: + +## Step 2 - Write an RPC server + +Brillig will call *one* RPC server. Most likely you will have to write your own, and you can do it in whatever language you prefer. In this guide, we will do it in Javascript. + +Let's use the above example of an oracle that consumes an array with two `Field` and returns their square roots: + +```rust +#[oracle(getSqrt)] +unconstrained fn sqrt(input: [Field; 2]) -> [Field; 2] { } + +unconstrained fn get_sqrt(input: [Field; 2]) -> [Field; 2] { + sqrt(input) +} + +fn main(input: [Field; 2]) { + let sqrt = get_sqrt(input); + assert(sqrt[0].pow_32(2) as u64 == input[0] as u64); + assert(sqrt[1].pow_32(2) as u64 == input[1] as u64); +} +``` + +:::info + +Why square root? + +In general, computing square roots is computationally more expensive than multiplications, which takes a toll when speaking about ZK applications. In this case, instead of calculating the square root in Noir, we are using our oracle to offload that computation to be made in plain. In our circuit we can simply multiply the two values. + +::: + +Now, we should write the correspondent RPC server, starting with the [default JSON-RPC 2.0 boilerplate](https://www.npmjs.com/package/json-rpc-2.0#example): + +```js +import { JSONRPCServer } from "json-rpc-2.0"; +import express from "express"; +import bodyParser from "body-parser"; + +const app = express(); +app.use(bodyParser.json()); + +const server = new JSONRPCServer(); +app.post("/", (req, res) => { + const jsonRPCRequest = req.body; + server.receive(jsonRPCRequest).then((jsonRPCResponse) => { + if (jsonRPCResponse) { + res.json(jsonRPCResponse); + } else { + res.sendStatus(204); + } + }); +}); + +app.listen(5555); +``` + +Now, we will add our `getSqrt` method, as expected by the `#[oracle(getSqrt)]` decorator in our Noir code. It maps through the params array and returns their square roots: + +```js +server.addMethod("getSqrt", async (params) => { + const values = params[0].Array.map(({ inner }) => { + return { inner: `${Math.sqrt(parseInt(inner, 16))}` }; + }); + return { values: [{ Array: values }] }; +}); +``` + +:::tip + +Brillig expects an object with an array of values. Each value is an object declaring to be `Single` or `Array` and returning a `inner` property *as a string*. For example: + +```json +{ "values": [{ "Array": [{ "inner": "1" }, { "inner": "2"}]}]} +{ "values": [{ "Single": { "inner": "1" }}]} +{ "values": [{ "Single": { "inner": "1" }}, { "Array": [{ "inner": "1", { "inner": "2" }}]}]} +``` + +If you're using Typescript, the following types may be helpful in understanding the expected return value and making sure they're easy to follow: + +```js +interface Value { + inner: string, +} + +interface SingleForeignCallParam { + Single: Value, +} + +interface ArrayForeignCallParam { + Array: Value[], +} + +type ForeignCallParam = SingleForeignCallParam | ArrayForeignCallParam; + +interface ForeignCallResult { + values: ForeignCallParam[], +} +``` + +::: + +## Step 3 - Usage with Nargo + +Using the [`nargo` CLI tool](../getting_started/installation/index.md), you can use oracles in the `nargo test`, `nargo execute` and `nargo prove` commands by passing a value to `--oracle-resolver`. For example: + +```bash +nargo test --oracle-resolver http://localhost:5555 +``` + +This tells `nargo` to use your RPC Server URL whenever it finds an oracle decorator. + +## Step 4 - Usage with NoirJS + +In a JS environment, an RPC server is not strictly necessary, as you may want to resolve your oracles without needing any JSON call at all. NoirJS simply expects that you pass a callback function when you generate proofs, and that callback function can be anything. + +For example, if your Noir program expects the host machine to provide CPU pseudo-randomness, you could simply pass it as the `foreignCallHandler`. You don't strictly need to create an RPC server to serve pseudo-randomness, as you may as well get it directly in your app: + +```js +const foreignCallHandler = (name, inputs) => crypto.randomBytes(16) // etc + +await noir.generateProof(inputs, foreignCallHandler) +``` + +As one can see, in NoirJS, the [`foreignCallHandler`](../reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md) function simply means "a callback function that returns a value of type [`ForeignCallOutput`](../reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md). It doesn't have to be an RPC call like in the case for Nargo. + +:::tip + +Does this mean you don't have to write an RPC server like in [Step #2](#step-2---write-an-rpc-server)? + +You don't technically have to, but then how would you run `nargo test` or `nargo prove`? To use both `Nargo` and `NoirJS` in your development flow, you will have to write a JSON RPC server. + +::: + +In this case, let's make `foreignCallHandler` call the JSON RPC Server we created in [Step #2](#step-2---write-an-rpc-server), by making it a JSON RPC Client. + +For example, using the same `getSqrt` program in [Step #1](#step-1---modify-your-noir-program) (comments in the code): + +```js +import { JSONRPCClient } from "json-rpc-2.0"; + +// declaring the JSONRPCClient +const client = new JSONRPCClient((jsonRPCRequest) => { +// hitting the same JSON RPC Server we coded above + return fetch("http://localhost:5555", { + method: "POST", + headers: { + "content-type": "application/json", + }, + body: JSON.stringify(jsonRPCRequest), + }).then((response) => { + if (response.status === 200) { + return response + .json() + .then((jsonRPCResponse) => client.receive(jsonRPCResponse)); + } else if (jsonRPCRequest.id !== undefined) { + return Promise.reject(new Error(response.statusText)); + } + }); +}); + +// declaring a function that takes the name of the foreign call (getSqrt) and the inputs +const foreignCallHandler = async (name, input) => { + // notice that the "inputs" parameter contains *all* the inputs + // in this case we to make the RPC request with the first parameter "numbers", which would be input[0] + const oracleReturn = await client.request(name, [ + { Array: input[0].map((i) => ({ inner: i.toString("hex") })) }, + ]); + return [oracleReturn.values[0].Array.map((x) => x.inner)]; +}; + +// the rest of your NoirJS code +const input = { input: [4, 16] }; +const { witness } = await noir.execute(numbers, foreignCallHandler); +``` + +:::tip + +If you're in a NoirJS environment running your RPC server together with a frontend app, you'll probably hit a familiar problem in full-stack development: requests being blocked by [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) policy. For development only, you can simply install and use the [`cors` npm package](https://www.npmjs.com/package/cors) to get around the problem: + +```bash +yarn add cors +``` + +and use it as a middleware: + +```js +import cors from "cors"; + +const app = express(); +app.use(cors()) +``` + +::: + +## Conclusion + +Hopefully by the end of this guide, you should be able to: + +- Write your own logic around Oracles and how to write a JSON RPC server to make them work with your Nargo commands. +- Provide custom foreign call handlers for NoirJS. diff --git a/docs/versioned_docs/version-v0.25.0/how_to/how-to-recursion.md b/docs/versioned_docs/version-v0.25.0/how_to/how-to-recursion.md new file mode 100644 index 00000000000..4c45bb87ae2 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/how_to/how-to-recursion.md @@ -0,0 +1,179 @@ +--- +title: How to use recursion on NoirJS +description: Learn how to implement recursion with NoirJS, a powerful tool for creating smart contracts on the EVM blockchain. This guide assumes familiarity with NoirJS, solidity verifiers, and the Barretenberg proving backend. Discover how to generate both final and intermediate proofs using `noir_js` and `backend_barretenberg`. +keywords: + [ + "NoirJS", + "EVM blockchain", + "smart contracts", + "recursion", + "solidity verifiers", + "Barretenberg backend", + "noir_js", + "backend_barretenberg", + "intermediate proofs", + "final proofs", + "nargo compile", + "json import", + "recursive circuit", + "recursive app" + ] +sidebar_position: 1 +--- + +This guide shows you how to use recursive proofs in your NoirJS app. For the sake of clarity, it is assumed that: + +- You already have a NoirJS app. If you don't, please visit the [NoirJS tutorial](../tutorials/noirjs_app.md) and the [reference](../reference/NoirJS/noir_js/index.md). +- You are familiar with what are recursive proofs and you have read the [recursion explainer](../explainers/explainer-recursion.md) +- You already built a recursive circuit following [the reference](../noir/standard_library/recursion.md), and understand how it works. + +It is also assumed that you're not using `noir_wasm` for compilation, and instead you've used [`nargo compile`](../reference/nargo_commands.md) to generate the `json` you're now importing into your project. However, the guide should work just the same if you're using `noir_wasm`. + +:::info + +As you've read in the [explainer](../explainers/explainer-recursion.md), a recursive proof is an intermediate proof. This means that it doesn't necessarily generate the final step that makes it verifiable in a smart contract. However, it is easy to verify within another circuit. + +While "standard" usage of NoirJS packages abstracts final proofs, it currently lacks the necessary interface to abstract away intermediate proofs. This means that these proofs need to be created by using the backend directly. + +In short: + +- `noir_js` generates *only* final proofs +- `backend_barretenberg` generates both types of proofs + +::: + +In a standard recursive app, you're also dealing with at least two circuits. For the purpose of this guide, we will assume the following: + +- `main`: a circuit of type `assert(x != y)`, where `main` is marked with a `#[recursive]` attribute. This attribute states that the backend should generate proofs that are friendly for verification within another circuit. +- `recursive`: a circuit that verifies `main` + +For a full example on how recursive proofs work, please refer to the [noir-examples](https://github.com/noir-lang/noir-examples) repository. We will *not* be using it as a reference for this guide. + +## Step 1: Setup + +In a common NoirJS app, you need to instantiate a backend with something like `const backend = new Backend(circuit)`. Then you feed it to the `noir_js` interface. + +For recursion, this doesn't happen, and the only need for `noir_js` is only to `execute` a circuit and get its witness and return value. Everything else is not interfaced, so it needs to happen on the `backend` object. + +It is also recommended that you instantiate the backend with as many threads as possible, to allow for maximum concurrency: + +```js +const backend = new Backend(circuit, { threads: 8 }) +``` + +:::tip +You can use the [`os.cpus()`](https://nodejs.org/api/os.html#oscpus) object in `nodejs` or [`navigator.hardwareConcurrency`](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/hardwareConcurrency) on the browser to make the most out of those glorious cpu cores +::: + +## Step 2: Generating the witness and the proof for `main` + +After instantiating the backend, you should also instantiate `noir_js`. We will use it to execute the circuit and get the witness. + +```js +const noir = new Noir(circuit, backend) +const { witness } = noir.execute(input) +``` + +With this witness, you are now able to generate the intermediate proof for the main circuit: + +```js +const { proof, publicInputs } = await backend.generateProof(witness) +``` + +:::warning + +Always keep in mind what is actually happening on your development process, otherwise you'll quickly become confused about what circuit we are actually running and why! + +In this case, you can imagine that Alice (running the `main` circuit) is proving something to Bob (running the `recursive` circuit), and Bob is verifying her proof within his proof. + +With this in mind, it becomes clear that our intermediate proof is the one *meant to be verified within another circuit*, so it must be Alice's. Actually, the only final proof in this theoretical scenario would be the last one, sent on-chain. + +::: + +## Step 3 - Verification and proof artifacts + +Optionally, you are able to verify the intermediate proof: + +```js +const verified = await backend.verifyProof({ proof, publicInputs }) +``` + +This can be useful to make sure our intermediate proof was correctly generated. But the real goal is to do it within another circuit. For that, we need to generate recursive proof artifacts that will be passed to the circuit that is verifying the proof we just generated. Instead of passing the proof and verification key as a byte array, we pass them as fields which makes it cheaper to verify in a circuit: + +```js +const { proofAsFields, vkAsFields, vkHash } = await backend.generateRecursiveProofArtifacts( { publicInputs, proof }, publicInputsCount) +``` + +This call takes the public inputs and the proof, but also the public inputs count. While this is easily retrievable by simply counting the `publicInputs` length, the backend interface doesn't currently abstract it away. + +:::info + +The `proofAsFields` has a constant size `[Field; 93]` and verification keys in Barretenberg are always `[Field; 114]`. + +::: + +:::warning + +One common mistake is to forget *who* makes this call. + +In a situation where Alice is generating the `main` proof, if she generates the proof artifacts and sends them to Bob, which gladly takes them as true, this would mean Alice could prove anything! + +Instead, Bob needs to make sure *he* extracts the proof artifacts, using his own instance of the `main` circuit backend. This way, Alice has to provide a valid proof for the correct `main` circuit. + +::: + +## Step 4 - Recursive proof generation + +With the artifacts, generating a recursive proof is no different from a normal proof. You simply use the `backend` (with the recursive circuit) to generate it: + +```js +const recursiveInputs = { + verification_key: vkAsFields, // array of length 114 + proof: proofAsFields, // array of length 93 + size of public inputs + publicInputs: [mainInput.y], // using the example above, where `y` is the only public input + key_hash: vkHash, +} + +const { witness, returnValue } = noir.execute(recursiveInputs) // we're executing the recursive circuit now! +const { proof, publicInputs } = backend.generateProof(witness) +const verified = backend.verifyProof({ proof, publicInputs }) +``` + +You can obviously chain this proof into another proof. In fact, if you're using recursive proofs, you're probably interested of using them this way! + +:::tip + +Managing circuits and "who does what" can be confusing. To make sure your naming is consistent, you can keep them in an object. For example: + +```js +const circuits = { + main: mainJSON, + recursive: recursiveJSON +} +const backends = { + main: new BarretenbergBackend(circuits.main), + recursive: new BarretenbergBackend(circuits.recursive) +} +const noir_programs = { + main: new Noir(circuits.main, backends.main), + recursive: new Noir(circuits.recursive, backends.recursive) +} +``` + +This allows you to neatly call exactly the method you want without conflicting names: + +```js +// Alice runs this 👇 +const { witness: mainWitness } = await noir_programs.main.execute(input) +const proof = await backends.main.generateProof(mainWitness) + +// Bob runs this 👇 +const verified = await backends.main.verifyProof(proof) +const { proofAsFields, vkAsFields, vkHash } = await backends.main.generateRecursiveProofArtifacts( + proof, + numPublicInputs, +); +const recursiveProof = await noir_programs.recursive.generateProof(recursiveInputs) +``` + +::: diff --git a/docs/versioned_docs/version-v0.25.0/how_to/how-to-solidity-verifier.md b/docs/versioned_docs/version-v0.25.0/how_to/how-to-solidity-verifier.md new file mode 100644 index 00000000000..e3c7c1065da --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/how_to/how-to-solidity-verifier.md @@ -0,0 +1,231 @@ +--- +title: Generate a Solidity Verifier +description: + Learn how to run the verifier as a smart contract on the blockchain. Compile a Solidity verifier + contract for your Noir program and deploy it on any EVM blockchain acting as a verifier smart + contract. Read more to find out +keywords: + [ + solidity verifier, + smart contract, + blockchain, + compiler, + plonk_vk.sol, + EVM blockchain, + verifying Noir programs, + proving backend, + Barretenberg, + ] +sidebar_position: 0 +pagination_next: tutorials/noirjs_app +--- + +Noir has the ability to generate a verifier contract in Solidity, which can be deployed in many EVM-compatible blockchains such as Ethereum. + +This allows for a powerful feature set, as one can make use of the conciseness and the privacy provided by Noir in an immutable ledger. Applications can range from simple P2P guessing games, to complex private DeFi interactions. + +This guide shows you how to generate a Solidity Verifier and deploy it on the [Remix IDE](https://remix.ethereum.org/). It is assumed that: + +- You are comfortable with the Solidity programming language and understand how contracts are deployed on the Ethereum network +- You have Noir installed and you have a Noir program. If you don't, [get started](../getting_started/installation/index.md) with Nargo and the example Hello Noir circuit +- You are comfortable navigating RemixIDE. If you aren't or you need a refresher, you can find some video tutorials [here](https://www.youtube.com/channel/UCjTUPyFEr2xDGN6Cg8nKDaA) that could help you. + +## Rundown + +Generating a Solidity Verifier contract is actually a one-command process. However, compiling it and deploying it can have some caveats. Here's the rundown of this guide: + +1. How to generate a solidity smart contract +2. How to compile the smart contract in the RemixIDE +3. How to deploy it to a testnet + +## Step 1 - Generate a contract + +This is by far the most straight-forward step. Just run: + +```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 to any EVM blockchain acting as a verifier smart contract. + +:::info + +It is possible to generate 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 generation of verifier contracts, for the time being these are only in Solidity. +::: + +## Step 2 - Compiling + +We will mostly skip the details of RemixIDE, as the UI can change from version to version. For now, we can just open +
Remix and create a blank workspace. + +![Create Workspace](@site/static/img/how-tos/solidity_verifier_1.png) + +We will create a new file to contain the contract Nargo generated, and copy-paste its content. + +:::warning + +You'll likely see a warning advising you to not trust pasted code. While it is an important warning, it is irrelevant in the context of this guide and can be ignored. We will not be deploying anywhere near a mainnet. + +::: + +To compile our the verifier, we can navigate to the compilation tab: + +![Compilation Tab](@site/static/img/how-tos/solidity_verifier_2.png) + +Remix should automatically match a suitable compiler version. However, hitting the "Compile" button will most likely generate a "Stack too deep" error: + +![Stack too deep](@site/static/img/how-tos/solidity_verifier_3.png) + +This is due to the verify function needing to put many variables on the stack, but enabling the optimizer resolves the issue. To do this, let's open the "Advanced Configurations" tab and enable optimization. The default 200 runs will suffice. + +:::info + +This time we will see a warning about an unused function parameter. This is expected, as the `verify` function doesn't use the `_proof` parameter inside a solidity block, it is loaded from calldata and used in assembly. + +::: + +![Compilation success](@site/static/img/how-tos/solidity_verifier_4.png) + +## Step 3 - Deploying + +At this point we should have a compiled contract read to deploy. If we navigate to the deploy section in Remix, we will see many different environments we can deploy to. The steps to deploy on each environment would be out-of-scope for this guide, so we will just use the default Remix VM. + +Looking closely, we will notice that our "Solidity Verifier" is actually three contracts working together: + +- An `UltraVerificationKey` library which simply stores the verification key for our circuit. +- An abstract contract `BaseUltraVerifier` containing most of the verifying logic. +- A main `UltraVerifier` contract that inherits from the Base and uses the Key contract. + +Remix will take care of the dependencies for us so we can simply deploy the UltraVerifier contract by selecting it and hitting "deploy": + +![Deploying UltraVerifier](@site/static/img/how-tos/solidity_verifier_5.png) + +A contract will show up in the "Deployed Contracts" section, where we can retrieve the Verification Key Hash. This is particularly useful for double-checking the deployer contract is the correct one. + +:::note + +Why "UltraVerifier"? + +To be precise, the Noir compiler (`nargo`) doesn't generate the verifier contract directly. It compiles the Noir code into an intermediate language (ACIR), which is then executed by the backend. So it is the backend that returns the verifier smart contract, not Noir. + +In this case, the Barretenberg Backend uses the UltraPlonk proving system, hence the "UltraVerifier" name. + +::: + +## Step 4 - Verifying + +To verify a proof using the Solidity verifier contract, we call the `verify` function in this extended contract: + +```solidity +function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool) +``` + +When using the default example in the [Hello Noir](../getting_started/hello_noir/index.md) guide, the easiest way to confirm that the verifier contract is doing its job is by calling the `verify` function via remix with the required parameters. For `_proof`, run `nargo prove` and use the string in `proof/.proof` (adding the hex `0x` prefix). We can also copy the public input from `Verifier.toml`, as it will be properly formatted as 32-byte strings: + +``` +0x...... , [0x0000.....02] +``` + +A programmatic example of how the `verify` function is called can be seen 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"); +``` + +:::info[Return Values] + +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. + +For example, if you have Noir program like this: + +```rust +fn main( + // Public inputs + pubkey_x: pub Field, + pubkey_y: pub Field, + // Private inputs + priv_key: Field, +) -> pub Field +``` + +the `verify` function will expect the public inputs array (second function parameter) to be of length 3, the two inputs and the return value. Like before, these values are populated in Verifier.toml after running `nargo prove`. + +Passing only two inputs will result in an error such as `PUBLIC_INPUT_COUNT_INVALID(3, 2)`. + +In this case, the inputs parameter to `verify` would be an array ordered as `[pubkey_x, pubkey_y, return]`. + +::: + +:::tip[Structs] + +You can pass structs to the verifier contract. They will be flattened so that the array of inputs is 1-dimensional array. + +For example, 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) { + //... +} +``` + +The order of these inputs would be flattened to: `[x, nested.t1.val1, nested.t1.val2, nested.is_true, y]` + +::: + +The other function you can call is our entrypoint `verify` function, as defined above. + +:::tip + +It's worth noticing that the `verify` function is actually a `view` function. A `view` function does not alter the blockchain state, so it doesn't need to be distributed (i.e. it will run only on the executing node), and therefore doesn't cost any gas. + +This can be particularly useful in some situations. If Alice generated a proof and wants Bob to verify its correctness, Bob doesn't need to run Nargo, NoirJS, or any Noir specific infrastructure. He can simply make a call to the blockchain with the proof and verify it is correct without paying any gas. + +It would be incorrect to say that a Noir proof verification costs any gas at all. However, most of the time the result of `verify` is used to modify state (for example, to update a balance, a game state, etc). In that case the whole network needs to execute it, which does incur gas costs (calldata and execution, but not storage). + +::: + +## A Note on EVM chains + +ZK-SNARK verification depends on some precompiled cryptographic primitives such as Elliptic Curve Pairings (if you like complex math, you can read about EC Pairings [here](https://medium.com/@VitalikButerin/exploring-elliptic-curve-pairings-c73c1864e627)). Not all EVM chains support EC Pairings, notably some of the ZK-EVMs. This means that you won't be able to use the verifier contract in all of them. + +For example, chains like `zkSync ERA` and `Polygon zkEVM` do not currently support these precompiles, so proof verification via Solidity verifier contracts won't work. Here's a quick list of EVM chains that have been tested and are known to work: + +- Optimism +- Arbitrum +- Polygon PoS +- Scroll +- Celo + +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. + +## What's next + +Now that you know how to call a Noir Solidity Verifier on a smart contract using Remix, you should be comfortable with using it with some programmatic frameworks, such as [hardhat](https://github.com/noir-lang/noir-starter/tree/main/vite-hardhat) and [foundry](https://github.com/noir-lang/noir-starter/tree/main/with-foundry). + +You can find other tools, examples, boilerplates and libraries in the [awesome-noir](https://github.com/noir-lang/awesome-noir) repository. + +You should also be ready to write and deploy your first NoirJS app and start generating proofs on websites, phones, and NodeJS environments! Head on to the [NoirJS tutorial](../tutorials/noirjs_app.md) to learn how to do that. diff --git a/docs/versioned_docs/version-v0.25.0/how_to/merkle-proof.mdx b/docs/versioned_docs/version-v0.25.0/how_to/merkle-proof.mdx new file mode 100644 index 00000000000..34074659ac1 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/how_to/merkle-proof.mdx @@ -0,0 +1,48 @@ +--- +title: Prove Merkle Tree Membership +description: + Learn how to use merkle membership proof in Noir to prove that a given leaf is a member of a + merkle tree with a specified root, at a given index. +keywords: + [merkle proof, merkle membership proof, Noir, rust, hash function, Pedersen, sha256, merkle tree] +--- + +Let's walk through an example of a merkle membership proof in Noir that proves that a given leaf is +in a merkle tree. + +```rust +use dep::std; + +fn main(message : [Field; 62], index : Field, hashpath : [Field; 40], root : Field) { + let leaf = std::hash::hash_to_field(message); + let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); + assert(merkle_root == root); +} + +``` + +The message is hashed using `hash_to_field`. The specific hash function that is being used is chosen +by the backend. The only requirement is that this hash function can heuristically be used as a +random oracle. If only collision resistance is needed, then one can call `std::hash::pedersen_hash` +instead. + +```rust +let leaf = std::hash::hash_to_field(message); +``` + +The leaf is then passed to a compute_merkle_root function with the root, index and hashpath. The returned root can then be asserted to be the same as the provided root. + +```rust +let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); +assert (merkle_root == root); +``` + +> **Note:** It is possible to re-implement the merkle tree implementation without standard library. +> However, for most usecases, it is enough. In general, the standard library will always opt to be +> as conservative as possible, while striking a balance with efficiency. + +An example, the merkle membership proof, only requires a hash function that has collision +resistance, hence a hash function like Pedersen is allowed, which in most cases is more efficient +than the even more conservative sha256. + +[View an example on the starter repo](https://github.com/noir-lang/noir-examples/blob/3ea09545cabfa464124ec2f3ea8e60c608abe6df/stealthdrop/circuits/src/main.nr#L20) diff --git a/docs/versioned_docs/version-v0.25.0/how_to/using-devcontainers.mdx b/docs/versioned_docs/version-v0.25.0/how_to/using-devcontainers.mdx new file mode 100644 index 00000000000..727ec6ca667 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/how_to/using-devcontainers.mdx @@ -0,0 +1,110 @@ +--- +title: Developer Containers and Codespaces +description: "Learn how to set up a devcontainer in your GitHub repository for a seamless coding experience with Codespaces. Follow our easy 8-step guide to create your own Noir environment without installing Nargo locally." +keywords: ["Devcontainer", "Codespaces", "GitHub", "Noir Environment", "Docker Image", "Development Environment", "Remote Coding", "GitHub Codespaces", "Noir Programming", "Nargo", "VSCode Extensions", "Noirup"] +sidebar_position: 1 +--- + +Adding a developer container configuration file to your Noir project is one of the easiest way to unlock coding in browser. + +## What's a devcontainer after all? + +A [Developer Container](https://containers.dev/) (devcontainer for short) is a Docker image that comes preloaded with tools, extensions, and other tools you need to quickly get started or continue a project, without having to install Nargo locally. Think of it as a development environment in a box. + +There are many advantages to this: + +- It's platform and architecture agnostic +- You don't need to have an IDE installed, or Nargo, or use a terminal at all +- It's safer for using on a public machine or public network + +One of the best ways of using devcontainers is... not using your machine at all, for maximum control, performance, and ease of use. +Enter Codespaces. + +## Codespaces + +If a devcontainer is just a Docker image, then what stops you from provisioning a `p3dn.24xlarge` AWS EC2 instance with 92 vCPUs and 768 GiB RAM and using it to prove your 10-gate SNARK proof? + +Nothing! Except perhaps the 30-40$ per hour it will cost you. + +The problem is that provisioning takes time, and I bet you don't want to see the AWS console every time you want to code something real quick. + +Fortunately, there's an easy and free way to get a decent remote machine ready and loaded in less than 2 minutes: Codespaces. [Codespaces is a Github feature](https://github.com/features/codespaces) that allows you to code in a remote machine by using devcontainers, and it's pretty cool: + +- You can start coding Noir in less than a minute +- It uses the resources of a remote machine, so you can code on your grandma's phone if needed be +- It makes it easy to share work with your frens +- It's fully reusable, you can stop and restart whenever you need to + +:::info + +Don't take out your wallet just yet. Free GitHub accounts get about [15-60 hours of coding](https://github.com/features/codespaces) for free per month, depending on the size of your provisioned machine. + +::: + +## Tell me it's _actually_ easy + +It is! + +Github comes with a default codespace and you can use it to code your own devcontainer. That's exactly what we will be doing in this guide. + + + +8 simple steps: + +#### 1. Create a new repository on GitHub. + +#### 2. Click "Start coding with Codespaces". This will use the default image. + +#### 3. Create a folder called `.devcontainer` in the root of your repository. + +#### 4. Create a Dockerfile in that folder, and paste the following code: + +```docker +FROM --platform=linux/amd64 node:lts-bookworm-slim +SHELL ["/bin/bash", "-c"] +RUN apt update && apt install -y curl bash git tar gzip libc++-dev +RUN curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash +ENV PATH="/root/.nargo/bin:$PATH" +RUN noirup +ENTRYPOINT ["nargo"] +``` +#### 5. Create a file called `devcontainer.json` in the same folder, and paste the following code: + +```json +{ + "name": "Noir on Codespaces", + "build": { + "context": ".", + "dockerfile": "Dockerfile" + }, + "customizations": { + "vscode": { + "extensions": ["noir-lang.vscode-noir"] + } + } +} +``` +#### 6. Commit and push your changes + +This will pull the new image and build it, so it could take a minute or so + +#### 8. Done! +Just wait for the build to finish, and there's your easy Noir environment. + + +Refer to [noir-starter](https://github.com/noir-lang/noir-starter/) as an example of how devcontainers can be used together with codespaces. + + + +## How do I use it? + +Using the codespace is obviously much easier than setting it up. +Just navigate to your repository and click "Code" -> "Open with Codespaces". It should take a few seconds to load, and you're ready to go. + +:::info + +If you really like the experience, you can add a badge to your readme, links to existing codespaces, and more. +Check out the [official docs](https://docs.github.com/en/codespaces/setting-up-your-project-for-codespaces/setting-up-your-repository/facilitating-quick-creation-and-resumption-of-codespaces) for more info. diff --git a/docs/versioned_docs/version-v0.25.0/index.mdx b/docs/versioned_docs/version-v0.25.0/index.mdx new file mode 100644 index 00000000000..75086ddcdde --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/index.mdx @@ -0,0 +1,67 @@ +--- +title: Noir Lang +hide_title: true +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] +sidebar_position: 0 +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +Noir Logo + +Noir is a Domain-Specific Language for SNARK proving systems developed by [Aztec Labs](https://aztec.network/). It allows you to generate complex Zero-Knowledge Programs (ZKP) by using simple and flexible syntax, requiring no previous knowledge on the underlying mathematics or cryptography. + +ZK programs are programs that can generate short proofs of a certain statement without revealing some details about it. You can read more about ZKPs [here](https://dev.to/spalladino/a-beginners-intro-to-coding-zero-knowledge-proofs-c56). + +## What's new about Noir? + +Noir works differently from most ZK languages by taking a two-pronged path. First, it compiles the program to an adaptable intermediate language known as ACIR. From there, depending on a given project's needs, ACIR can be further compiled into an arithmetic circuit for integration with the proving backend. + +:::info + +Noir is backend agnostic, which means it makes no assumptions on which proving backend powers the ZK proof. Being the language that powers [Aztec Contracts](https://docs.aztec.network/developers/contracts/main), it defaults to Aztec's Barretenberg proving backend. + +However, the ACIR output can be transformed to be compatible with other PLONK-based backends, or into a [rank-1 constraint system](https://www.rareskills.io/post/rank-1-constraint-system) suitable for backends such as Arkwork's Marlin. + +::: + +## Who is Noir for? + +Noir can be used both in complex cloud-based backends and in user's smartphones, requiring no knowledge on the underlying math or cryptography. From authorization systems that keep a password in the user's device, to complex on-chain verification of recursive proofs, Noir is designed to abstract away complexity without any significant overhead. Here are some examples of situations where Noir can be used: + + + + Noir Logo + + Aztec Contracts leverage Noir to allow for the storage and execution of private information. Writing an Aztec Contract is as easy as writing Noir, and Aztec developers can easily interact with the network storage and execution through the [Aztec.nr](https://docs.aztec.network/developers/contracts/main) library. + + + Soliditry Verifier Example + Noir can auto-generate Solidity verifier contracts that verify Noir proofs. This allows for non-interactive verification of proofs containing private information in an immutable system. This feature powers a multitude of use-case scenarios, from P2P chess tournaments, to [Aztec Layer-2 Blockchain](https://docs.aztec.network/) + + + Aztec Labs developed NoirJS, an easy interface to generate and verify Noir proofs in a Javascript environment. This allows for Noir to be used in webpages, mobile apps, games, and any other environment supporting JS execution in a standalone manner. + + + + +## Libraries + +Noir is meant to be easy to extend by simply importing Noir libraries just like in Rust. +The [awesome-noir repo](https://github.com/noir-lang/awesome-noir#libraries) is a collection of libraries developed by the Noir community. +Writing a new library is easy and makes code be composable and easy to reuse. See the section on [dependencies](noir/modules_packages_crates/dependencies.md) for more information. diff --git a/docs/versioned_docs/version-v0.25.0/migration_notes.md b/docs/versioned_docs/version-v0.25.0/migration_notes.md new file mode 100644 index 00000000000..6bd740024e5 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/migration_notes.md @@ -0,0 +1,105 @@ +--- +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. + +### `backend encountered an error: libc++.so.1` + +Depending on your OS, you may encounter the following error when running `nargo prove` for the first time: + +```text +The backend encountered an error: "/home/codespace/.nargo/backends/acvm-backend-barretenberg/backend_binary: error while loading shared libraries: libc++.so.1: cannot open shared object file: No such file or directory\n" +``` + +Install the `libc++-dev` library with: + +```bash +sudo apt install libc++-dev +``` + +## ≥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](noir/concepts/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 your 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 file is running [this bash script](https://github.com/noir-lang/barretenberg-js-binary/blob/master/run-bb-js.sh), where we need to gzip it as the Nargo currently expect the backend to be zipped up. + +Then run: + +``` +DESIRED_BINARY_VERSION=0.8.1 nargo info +``` + +This overrides the bb native binary with a bb.js node application instead, which should be compatible with most if not all hardware. This does come with the drawback of being generally slower than native binary. + +0.8.1 indicates bb.js version 0.8.1, so if you change that it will update to a different version or the default version in the script if none was supplied. diff --git a/docs/versioned_docs/version-v0.25.0/noir/concepts/_category_.json b/docs/versioned_docs/version-v0.25.0/noir/concepts/_category_.json new file mode 100644 index 00000000000..7da08f8a8c5 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/noir/concepts/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Concepts", + "position": 0, + "collapsible": true, + "collapsed": true +} \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.25.0/noir/concepts/assert.md b/docs/versioned_docs/version-v0.25.0/noir/concepts/assert.md new file mode 100644 index 00000000000..bcff613a695 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/noir/concepts/assert.md @@ -0,0 +1,45 @@ +--- +title: Assert Function +description: + Learn about the assert function in Noir, which can be used to explicitly constrain the predicate or + comparison expression that follows to be true, and what happens if the expression is false at + runtime. +keywords: [Noir programming language, assert statement, predicate expression, comparison expression] +sidebar_position: 4 +--- + +Noir includes a special `assert` function which will explicitly constrain the predicate/comparison +expression that follows to be true. If this expression is false at runtime, the program will fail to +be proven. Example: + +```rust +fn main(x : Field, y : Field) { + assert(x == y); +} +``` + +> 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`. + +You can optionally provide a message to be logged when the assertion fails: + +```rust +assert(x == y, "x and y are not equal"); +``` + +Aside string literals, the optional message can be a format string or any other type supported as input for Noir's [print](../standard_library/logging.md) functions. This feature lets you incorporate runtime variables into your failed assertion logs: + +```rust +assert(x == y, f"Expected x == y, but got {x} == {y}"); +``` + +Using a variable as an assertion message directly: + +```rust +struct myStruct { + myField: Field +} + +let s = myStruct { myField: y }; +assert(s.myField == x, s); +``` + diff --git a/docs/versioned_docs/version-v0.25.0/noir/concepts/comments.md b/docs/versioned_docs/version-v0.25.0/noir/concepts/comments.md new file mode 100644 index 00000000000..b51a85f5c94 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/noir/concepts/comments.md @@ -0,0 +1,33 @@ +--- +title: Comments +description: + Learn how to write comments in Noir programming language. A comment is a line of code that is + ignored by the compiler, but it can be read by programmers. Single-line and multi-line comments + are supported in Noir. +keywords: [Noir programming language, comments, single-line comments, multi-line comments] +sidebar_position: 10 +--- + +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.25.0/noir/concepts/control_flow.md b/docs/versioned_docs/version-v0.25.0/noir/concepts/control_flow.md new file mode 100644 index 00000000000..4ce65236db3 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/noir/concepts/control_flow.md @@ -0,0 +1,45 @@ +--- +title: Control Flow +description: + Learn how to use loops and if expressions in the Noir programming language. Discover the syntax + and examples for for loops and if-else statements. +keywords: [Noir programming language, loops, for loop, if-else statements, Rust syntax] +sidebar_position: 2 +--- + +## Loops + +Noir has one kind of loop: the `for` loop. `for` loops allow you to repeat a block of code multiple +times. + +The following block of code between the braces is run 10 times. + +```rust +for i in 0..10 { + // do something +}; +``` + +The index for loops is of type `u64`. + +## If Expressions + +Noir supports `if-else` statements. The syntax is most similar to Rust's where it is not required +for the statement's conditional to be surrounded by parentheses. + +```rust +let a = 0; +let mut x: u32 = 0; + +if a == 0 { + if a != 0 { + x = 6; + } else { + x = 2; + } +} else { + x = 5; + assert(x == 5); +} +assert(x == 2); +``` diff --git a/docs/versioned_docs/version-v0.25.0/noir/concepts/data_bus.md b/docs/versioned_docs/version-v0.25.0/noir/concepts/data_bus.md new file mode 100644 index 00000000000..e54fc861257 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/noir/concepts/data_bus.md @@ -0,0 +1,21 @@ +--- +title: Data Bus +sidebar_position: 13 +--- +**Disclaimer** this feature is experimental, do not use it! + +The data bus is an optimization that the backend can use to make recursion more efficient. +In order to use it, you must define some inputs of the program entry points (usually the `main()` +function) with the `call_data` modifier, and the return values with the `return_data` modifier. +These modifiers are incompatible with `pub` and `mut` modifiers. + +## Example + +```rust +fn main(mut x: u32, y: call_data u32, z: call_data [u32;4] ) -> return_data u32 { + let a = z[x]; + a+y +} +``` + +As a result, both call_data and return_data will be treated as private inputs and encapsulated into a read-only array each, for the backend to process. diff --git a/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/_category_.json b/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/_category_.json new file mode 100644 index 00000000000..5d694210bbf --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 0, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/arrays.md b/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/arrays.md new file mode 100644 index 00000000000..a8bd338e736 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/arrays.md @@ -0,0 +1,251 @@ +--- +title: Arrays +description: + Dive into the Array data type in Noir. Grasp its methods, practical examples, and best practices for efficiently using Arrays in your Noir code. +keywords: + [ + noir, + array type, + methods, + examples, + indexing, + ] +sidebar_position: 4 +--- + +An array is one way of grouping together values into one compound type. Array types can be inferred +or explicitly specified via the syntax `[; ]`: + +```rust +fn main(x : Field, y : Field) { + let my_arr = [x, y]; + let your_arr: [Field; 2] = [x, y]; +} +``` + +Here, both `my_arr` and `your_arr` are instantiated as an array containing two `Field` elements. + +Array elements can be accessed using indexing: + +```rust +fn main() { + let a = [1, 2, 3, 4, 5]; + + let first = a[0]; + let second = a[1]; +} +``` + +All elements in an array must be of the same type (i.e. homogeneous). That is, an array cannot group +a `Field` value and a `u8` value together for example. + +You can write mutable arrays, like: + +```rust +fn main() { + let mut arr = [1, 2, 3, 4, 5]; + assert(arr[0] == 1); + + arr[0] = 42; + assert(arr[0] == 42); +} +``` + +You can instantiate a new array of a fixed size with the same value repeated for each element. The following example instantiates an array of length 32 where each element is of type Field and has the value 0. + +```rust +let array: [Field; 32] = [0; 32]; +``` + +Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices), you can just call `as_slice` on your array: + +```rust +let array: [Field; 32] = [0; 32]; +let sl = array.as_slice() +``` + +You can define multidimensional arrays: + +```rust +let array : [[Field; 2]; 2]; +let element = array[0][0]; +``` +However, multidimensional slices are not supported. For example, the following code will error at compile time: +```rust +let slice : [[Field]] = []; +``` + +## 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. +Each of these functions are located within the generic impl `impl [T; N] {`. +So anywhere `self` appears, it refers to the variable `self: [T; N]`. + +### len + +Returns the length of an array + +```rust +fn len(self) -> 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(self) -> [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(self, 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(self, 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(self, 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(self, 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(self, 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(self, 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.25.0/noir/concepts/data_types/booleans.md b/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/booleans.md new file mode 100644 index 00000000000..69826fcd724 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/booleans.md @@ -0,0 +1,31 @@ +--- +title: Booleans +description: + Delve into the Boolean data type in Noir. Understand its methods, practical examples, and best practices for using Booleans in your Noir programs. +keywords: + [ + noir, + boolean type, + methods, + examples, + logical operations, + ] +sidebar_position: 2 +--- + + +The `bool` type in Noir has two possible values: `true` and `false`: + +```rust +fn main() { + let t = true; + let f: bool = false; +} +``` + +> **Note:** When returning a boolean value, it will show up as a value of 1 for `true` and 0 for +> `false` in _Verifier.toml_. + +The boolean type is most commonly used in conditionals like `if` expressions and `assert` +statements. More about conditionals is covered in the [Control Flow](../control_flow) and +[Assert Function](../assert) sections. diff --git a/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/fields.md b/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/fields.md new file mode 100644 index 00000000000..99b4aa63549 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/fields.md @@ -0,0 +1,192 @@ +--- +title: Fields +description: + Dive deep into the Field data type in Noir. Understand its methods, practical examples, and best practices to effectively use Fields in your Noir programs. +keywords: + [ + noir, + field type, + methods, + examples, + best practices, + ] +sidebar_position: 0 +--- + +The field type corresponds to the native field type of the proving backend. + +The size of a Noir field depends on the elliptic curve's finite field for the proving backend +adopted. For example, a field would be a 254-bit integer when paired with the default backend that +spans the Grumpkin curve. + +Fields support integer arithmetic and are often used as the default numeric type in Noir: + +```rust +fn main(x : Field, y : Field) { + let z = x + y; +} +``` + +`x`, `y` and `z` are all private fields in this example. Using the `let` keyword we defined a new +private value `z` constrained to be equal to `x + y`. + +If proving efficiency is of priority, fields should be used as a default for solving problems. +Smaller integer types (e.g. `u64`) incur extra range constraints. + +## Methods + +After declaring a Field, you can use these common methods on it: + +### to_le_bits + +Transforms the field into an array of bits, Little Endian. + +```rust +fn to_le_bits(_x : Field, _bit_size: u32) -> [u1; N] +``` + +example: + +```rust +fn main() { + let field = 2; + let bits = field.to_le_bits(32); +} +``` + +### to_be_bits + +Transforms the field into an array of bits, Big Endian. + +```rust +fn to_be_bits(_x : Field, _bit_size: u32) -> [u1; N] +``` + +example: + +```rust +fn main() { + let field = 2; + let bits = field.to_be_bits(32); +} +``` + +### to_le_bytes + +Transforms into an array of bytes, Little Endian + +```rust +fn to_le_bytes(_x : Field, byte_size: u32) -> [u8] +``` + +example: + +```rust +fn main() { + let field = 2; + let bytes = field.to_le_bytes(4); +} +``` + +### to_be_bytes + +Transforms into an array of bytes, Big Endian + +```rust +fn to_be_bytes(_x : Field, byte_size: u32) -> [u8] +``` + +example: + +```rust +fn main() { + let field = 2; + let bytes = field.to_be_bytes(4); +} +``` + +### to_le_radix + +Decomposes into a vector over the specified base, Little Endian + +```rust +fn to_le_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] +``` + +example: + +```rust +fn main() { + let field = 2; + let radix = field.to_le_radix(256, 4); +} +``` + +### to_be_radix + +Decomposes into a vector over the specified base, Big Endian + +```rust +fn to_be_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] +``` + +example: + +```rust +fn main() { + let field = 2; + let radix = field.to_be_radix(256, 4); +} +``` + +### pow_32 + +Returns the value to the power of the specified exponent + +```rust +fn pow_32(self, exponent: Field) -> Field +``` + +example: + +```rust +fn main() { + let field = 2 + let pow = field.pow_32(4); + assert(pow == 16); +} +``` + +### assert_max_bit_size + +Adds a constraint to specify that the field can be represented with `bit_size` number of bits + +```rust +fn assert_max_bit_size(self, bit_size: u32) +``` + +example: + +```rust +fn main() { + let field = 2 + field.assert_max_bit_size(32); +} +``` + +### 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 +``` + + +### lt + +Returns true if the field is less than the other field + +```rust +pub fn lt(self, another: Field) -> bool +``` diff --git a/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/function_types.md b/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/function_types.md new file mode 100644 index 00000000000..f6121af17e2 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/function_types.md @@ -0,0 +1,26 @@ +--- +title: Function types +sidebar_position: 10 +--- + +Noir supports higher-order functions. The syntax for a function type is as follows: + +```rust +fn(arg1_type, arg2_type, ...) -> return_type +``` + +Example: + +```rust +fn assert_returns_100(f: fn() -> Field) { // f takes no args and returns a Field + assert(f() == 100); +} + +fn main() { + assert_returns_100(|| 100); // ok + assert_returns_100(|| 150); // fails +} +``` + +A function type also has an optional capture environment - this is necessary to support closures. +See [Lambdas](../lambdas.md) for more details. diff --git a/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/index.md b/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/index.md new file mode 100644 index 00000000000..357813c147a --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/index.md @@ -0,0 +1,110 @@ +--- +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](../generics.md): + +```rust +type Id = Size; + +fn main() { + let id: Id = 1; + let zero: u32 = 0; + assert(zero + 1 == id); +} +``` + +Type aliases can even refer to other aliases. An error will be issued if they form a cycle: + +```rust +// Ok! +type A = B; +type B = Field; + +type Bad1 = Bad2; + +// error: Dependency cycle found +type Bad2 = Bad1; +// ^^^^^^^^^^^ 'Bad2' recursively depends on itself: Bad2 -> Bad1 -> Bad2 +``` + +### BigInt + +You can achieve BigInt functionality using the [Noir BigInt](https://github.com/shuklaayush/noir-bigint) library. diff --git a/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/integers.md b/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/integers.md new file mode 100644 index 00000000000..4d58d96fed5 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/integers.md @@ -0,0 +1,155 @@ +--- +title: Integers +description: Explore the Integer data type in Noir. Learn about its methods, see real-world examples, and grasp how to efficiently use Integers in your Noir code. +keywords: [noir, integer types, methods, examples, arithmetic] +sidebar_position: 1 +--- + +An integer type is a range constrained field type. The Noir frontend supports both unsigned and signed integer types. The allowed sizes are 1, 8, 32 and 64 bits. + +:::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\\$). + +## 128 bits Unsigned Integers + +The built-in structure `U128` allows you to use 128-bit unsigned integers almost like a native integer type. However, there are some differences to keep in mind: +- You cannot cast between a native integer and `U128` +- There is a higher performance cost when using `U128`, compared to a native type. + +Conversion between unsigned integer types and U128 are done through the use of `from_integer` and `to_integer` functions. + +```rust +fn main() { + let x = U128::from_integer(23); + let y = U128::from_hex("0x7"); + let z = x + y; + assert(z.to_integer() == 30); +} +``` + +`U128` is implemented with two 64 bits limbs, representing the low and high bits, which explains the performance cost. You should expect `U128` to be twice more costly for addition and four times more costly for multiplication. +You can construct a U128 from its limbs: +```rust +fn main(x: u64, y: u64) { + let x = U128::from_u64s_be(x,y); + assert(z.hi == x as Field); + assert(z.lo == y as Field); +} +``` + +Note that the limbs are stored as Field elements in order to avoid unnecessary conversions. +Apart from this, most operations will work as usual: + +```rust +fn main(x: U128, y: U128) { + // multiplication + let c = x * y; + // addition and subtraction + let c = c - x + y; + // division + let c = x / y; + // bit operation; + let c = x & y | y; + // bit shift + let c = x << y; + // comparisons; + let c = x < y; + let c = x == y; +} +``` + +## 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.25.0/noir/concepts/data_types/references.md b/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/references.md new file mode 100644 index 00000000000..a5293d11cfb --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/references.md @@ -0,0 +1,23 @@ +--- +title: References +sidebar_position: 9 +--- + +Noir supports first-class references. References are a bit like pointers: they point to a specific address that can be followed to access the data stored at that address. You can use Rust-like syntax to use pointers in Noir: the `&` operator references the variable, the `*` operator dereferences it. + +Example: + +```rust +fn main() { + let mut x = 2; + + // you can reference x as &mut and pass it to multiplyBy2 + multiplyBy2(&mut x); +} + +// you can access &mut here +fn multiplyBy2(x: &mut Field) { + // and dereference it with * + *x = *x * 2; +} +``` diff --git a/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/slices.mdx b/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/slices.mdx new file mode 100644 index 00000000000..4a6ee816aa2 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/slices.mdx @@ -0,0 +1,147 @@ +--- +title: Slices +description: Explore the Slice data type in Noir. Understand its methods, see real-world examples, and learn how to effectively use Slices in your Noir programs. +keywords: [noir, slice type, methods, examples, subarrays] +sidebar_position: 5 +--- + +import Experimental from '@site/src/components/Notes/_experimental.mdx'; + + + +A slice is a dynamically-sized view into a sequence of elements. They can be resized at runtime, but because they don't own the data, they cannot be returned from a circuit. You can treat slices as arrays without a constrained size. + +```rust +use dep::std::slice; + +fn main() -> pub Field { + let mut slice: [Field] = [0; 2]; + + let mut new_slice = slice.push_back(6); + new_slice.len() +} +``` + +View the corresponding test file [here][test-file]. + +[test-file]: https://github.com/noir-lang/noir/blob/f387ec1475129732f72ba294877efdf6857135ac/crates/nargo_cli/tests/test_data_ssa_refactor/slices/src/main.nr + +## Methods + +For convenience, the STD provides some ready-to-use, common methods for slices: + +### push_back + +Pushes a new element to the end of the slice, returning a new slice with a length one greater than the original unmodified slice. + +```rust +fn push_back(_self: [T], _elem: T) -> [T] +``` + +example: + +```rust +fn main() -> pub Field { + let mut slice: [Field] = [0; 2]; + + let mut new_slice = slice.push_back(6); + new_slice.len() +} +``` + +View the corresponding test file [here][test-file]. + +### push_front + +Returns a new array with the specified element inserted at index 0. The existing elements indexes are incremented by 1. + +```rust +fn push_front(_self: Self, _elem: T) -> Self +``` + +Example: + +```rust +let mut new_slice: [Field] = []; +new_slice = new_slice.push_front(20); +assert(new_slice[0] == 20); // returns true +``` + +View the corresponding test file [here][test-file]. + +### pop_front + +Returns a tuple of two items, the first element of the array and the rest of the array. + +```rust +fn pop_front(_self: Self) -> (T, Self) +``` + +Example: + +```rust +let (first_elem, rest_of_slice) = slice.pop_front(); +``` + +View the corresponding test file [here][test-file]. + +### pop_back + +Returns a tuple of two items, the beginning of the array with the last element omitted and the last element. + +```rust +fn pop_back(_self: Self) -> (Self, T) +``` + +Example: + +```rust +let (popped_slice, last_elem) = slice.pop_back(); +``` + +View the corresponding test file [here][test-file]. + +### append + +Loops over a slice and adds it to the end of another. + +```rust +fn append(mut self, other: Self) -> Self +``` + +Example: + +```rust +let append = [1, 2].append([3, 4, 5]); +``` + +### insert + +Inserts an element at a specified index and shifts all following elements by 1. + +```rust +fn insert(_self: Self, _index: Field, _elem: T) -> Self +``` + +Example: + +```rust +new_slice = rest_of_slice.insert(2, 100); +assert(new_slice[2] == 100); +``` + +View the corresponding test file [here][test-file]. + +### remove + +Remove an element at a specified index, shifting all elements after it to the left, returning the altered slice and the removed element. + +```rust +fn remove(_self: Self, _index: Field) -> (Self, T) +``` + +Example: + +```rust +let (remove_slice, removed_elem) = slice.remove(3); +``` diff --git a/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/strings.md b/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/strings.md new file mode 100644 index 00000000000..311dfd64416 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/strings.md @@ -0,0 +1,80 @@ +--- +title: Strings +description: + Discover the String data type in Noir. Learn about its methods, see real-world examples, and understand how to effectively manipulate and use Strings in Noir. +keywords: + [ + noir, + string type, + methods, + examples, + concatenation, + ] +sidebar_position: 3 +--- + + +The string type is a fixed length value defined with `str`. + +You can use strings in `assert()` functions or print them with +`println()`. See more about [Logging](../../standard_library/logging). + +```rust +use dep::std; + +fn main(message : pub str<11>, hex_as_string : str<4>) { + println(message); + assert(message == "hello world"); + assert(hex_as_string == "0x41"); +} +``` + +You can convert a `str` to a byte array by calling `as_bytes()` +or a vector by calling `as_bytes_vec()`. + +```rust +fn main() { + let message = "hello world"; + let message_bytes = message.as_bytes(); + let mut message_vec = message.as_bytes_vec(); + assert(message_bytes.len() == 11); + assert(message_bytes[0] == 104); + assert(message_bytes[0] == message_vec.get(0)); +} +``` + +## Escape characters + +You can use escape characters for your strings: + +| Escape Sequence | Description | +|-----------------|-----------------| +| `\r` | Carriage Return | +| `\n` | Newline | +| `\t` | Tab | +| `\0` | Null Character | +| `\"` | Double Quote | +| `\\` | Backslash | + +Example: + +```rust +let s = "Hello \"world" // prints "Hello "world" +let s = "hey \tyou"; // prints "hey you" +``` + +## Raw strings + +A raw string begins with the letter `r` and is optionally delimited by a number of hashes `#`. + +Escape characters are *not* processed within raw strings. All contents are interpreted literally. + +Example: + +```rust +let s = r"Hello world"; +let s = r#"Simon says "hello world""#; + +// Any number of hashes may be used (>= 1) as long as the string also terminates with the same number of hashes +let s = r#####"One "#, Two "##, Three "###, Four "####, Five will end the string."#####; +``` diff --git a/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/structs.md b/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/structs.md new file mode 100644 index 00000000000..dbf68c99813 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/structs.md @@ -0,0 +1,70 @@ +--- +title: Structs +description: + Explore the Struct data type in Noir. Learn about its methods, see real-world examples, and grasp how to effectively define and use Structs in your Noir programs. +keywords: + [ + noir, + struct type, + methods, + examples, + data structures, + ] +sidebar_position: 8 +--- + +A struct also allows for grouping multiple values of different types. Unlike tuples, we can also +name each field. + +> **Note:** The usage of _field_ here refers to each element of the struct and is unrelated to the +> field type of Noir. + +Defining a struct requires giving it a name and listing each field within as `: ` pairs: + +```rust +struct Animal { + hands: Field, + legs: Field, + eyes: u8, +} +``` + +An instance of a struct can then be created with actual values in `: ` pairs in any +order. Struct fields are accessible using their given names: + +```rust +fn main() { + let legs = 4; + + let dog = Animal { + eyes: 2, + hands: 0, + legs, + }; + + let zero = dog.hands; +} +``` + +Structs can also be destructured in a pattern, binding each field to a new variable: + +```rust +fn main() { + let Animal { hands, legs: feet, eyes } = get_octopus(); + + let ten = hands + feet + eyes as u8; +} + +fn get_octopus() -> Animal { + let octopus = Animal { + hands: 0, + legs: 8, + eyes: 2, + }; + + octopus +} +``` + +The new variables can be bound with names different from the original struct field names, as +showcased in the `legs --> feet` binding in the example above. diff --git a/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/tuples.md b/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/tuples.md new file mode 100644 index 00000000000..2ec5c9c4113 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/tuples.md @@ -0,0 +1,48 @@ +--- +title: Tuples +description: + Dive into the Tuple data type in Noir. Understand its methods, practical examples, and best practices for efficiently using Tuples in your Noir code. +keywords: + [ + noir, + tuple type, + methods, + examples, + multi-value containers, + ] +sidebar_position: 7 +--- + +A tuple collects multiple values like an array, but with the added ability to collect values of +different types: + +```rust +fn main() { + let tup: (u8, u64, Field) = (255, 500, 1000); +} +``` + +One way to access tuple elements is via destructuring using pattern matching: + +```rust +fn main() { + let tup = (1, 2); + + let (one, two) = tup; + + let three = one + two; +} +``` + +Another way to access tuple elements is via direct member access, using a period (`.`) followed by +the index of the element we want to access. Index `0` corresponds to the first tuple element, `1` to +the second and so on: + +```rust +fn main() { + let tup = (5, 6, 7, 8); + + let five = tup.0; + let eight = tup.3; +} +``` diff --git a/docs/docs/noir/concepts/distinct.md b/docs/versioned_docs/version-v0.25.0/noir/concepts/distinct.md similarity index 100% rename from docs/docs/noir/concepts/distinct.md rename to docs/versioned_docs/version-v0.25.0/noir/concepts/distinct.md diff --git a/docs/versioned_docs/version-v0.25.0/noir/concepts/functions.md b/docs/versioned_docs/version-v0.25.0/noir/concepts/functions.md new file mode 100644 index 00000000000..48aba9cd058 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/noir/concepts/functions.md @@ -0,0 +1,226 @@ +--- +title: Functions +description: + Learn how to declare functions and methods in Noir, a programming language with Rust semantics. + This guide covers parameter declaration, return types, call expressions, and more. +keywords: [Noir, Rust, functions, methods, parameter declaration, return types, call expressions] +sidebar_position: 1 +--- + +Functions in Noir follow the same semantics of Rust, though Noir does not support early returns. + +To declare a function the `fn` keyword is used. + +```rust +fn foo() {} +``` + +By default, functions are visible only within the package they are defined. To make them visible outside of that package (for example, as part of a [library](../modules_packages_crates/crates_and_packages.md#libraries)), you should mark them as `pub`: + +```rust +pub fn foo() {} +``` + +You can also restrict the visibility of the function to only the crate it was defined in, by specifying `pub(crate)`: + +```rust +pub(crate) fn foo() {} //foo can only be called within its crate +``` + +All parameters in a function must have a type and all types are known at compile time. The parameter +is pre-pended with a colon and the parameter type. Multiple parameters are separated using a comma. + +```rust +fn foo(x : Field, y : Field){} +``` + +The return type of a function can be stated by using the `->` arrow notation. The function below +states that the foo function must return a `Field`. If the function returns no value, then the arrow +is omitted. + +```rust +fn foo(x : Field, y : Field) -> Field { + x + y +} +``` + +Note that a `return` keyword is unneeded in this case - the last expression in a function's body is +returned. + +## Main function + +If you're writing a binary, the `main` function is the starting point of your program. You can pass all types of expressions to it, as long as they have a fixed size at compile time: + +```rust +fn main(x : Field) // this is fine: passing a Field +fn main(x : [Field; 2]) // this is also fine: passing a Field with known size at compile-time +fn main(x : (Field, bool)) // 👌: passing a (Field, bool) tuple means size 2 +fn main(x : str<5>) // this is fine, as long as you pass a string of size 5 + +fn main(x : Vec) // can't compile, has variable size +fn main(x : [Field]) // can't compile, has variable size +fn main(....// i think you got it by now +``` + +Keep in mind [tests](../../getting_started/tooling/testing.md) don't differentiate between `main` and any other function. The following snippet passes tests, but won't compile or prove: + +```rust +fn main(x : [Field]) { + assert(x[0] == 1); +} + +#[test] +fn test_one() { + main([1, 2]); +} +``` + +```bash +$ nargo test +[testing] Running 1 test functions +[testing] Testing test_one... ok +[testing] All tests passed + +$ nargo check +The application panicked (crashed). +Message: Cannot have variable sized arrays as a parameter to main +``` + +## Call Expressions + +Calling a function in Noir is executed by using the function name and passing in the necessary +arguments. + +Below we show how to call the `foo` function from the `main` function using a call expression: + +```rust +fn main(x : Field, y : Field) { + let z = foo(x); +} + +fn foo(x : Field) -> Field { + x + x +} +``` + +## Methods + +You can define methods in Noir on any struct type in scope. + +```rust +struct MyStruct { + foo: Field, + bar: Field, +} + +impl MyStruct { + fn new(foo: Field) -> MyStruct { + MyStruct { + foo, + bar: 2, + } + } + + fn sum(self) -> Field { + self.foo + self.bar + } +} + +fn main() { + let s = MyStruct::new(40); + assert(s.sum() == 42); +} +``` + +Methods are just syntactic sugar for functions, so if we wanted to we could also call `sum` as +follows: + +```rust +assert(MyStruct::sum(s) == 42); +``` + +It is also possible to specialize which method is chosen depending on the [generic](./generics.md) type that is used. In this example, the `foo` function returns different values depending on its type: + +```rust +struct Foo {} + +impl Foo { + fn foo(self) -> Field { 1 } +} + +impl Foo { + fn foo(self) -> Field { 2 } +} + +fn main() { + let f1: Foo = Foo{}; + let f2: Foo = Foo{}; + assert(f1.foo() + f2.foo() == 3); +} +``` + +Also note that impls with the same method name defined in them cannot overlap. For example, if we already have `foo` defined for `Foo` and `Foo` like we do above, we cannot also define `foo` in an `impl Foo` since it would be ambiguous which version of `foo` to choose. + +```rust +// Including this impl in the same project as the above snippet would +// cause an overlapping impls error +impl Foo { + fn foo(self) -> Field { 3 } +} +``` + +## Lambdas + +Lambdas are anonymous functions. They follow the syntax of Rust - `|arg1, arg2, ..., argN| return_expression`. + +```rust +let add_50 = |val| val + 50; +assert(add_50(100) == 150); +``` + +See [Lambdas](./lambdas.md) for more details. + +## Attributes + +Attributes are metadata that can be applied to a function, using the following syntax: `#[attribute(value)]`. + +Supported attributes include: + +- **builtin**: the function is implemented by the compiler, for efficiency purposes. +- **deprecated**: mark the function as _deprecated_. Calling the function will generate a warning: `warning: use of deprecated function` +- **field**: Used to enable conditional compilation of code depending on the field size. See below for more details +- **oracle**: mark the function as _oracle_; meaning it is an external unconstrained function, implemented in noir_js. See [Unconstrained](./unconstrained.md) and [NoirJS](../../reference/NoirJS/noir_js/index.md) for more details. +- **test**: mark the function as unit tests. See [Tests](../../getting_started/tooling/testing.md) for more details + +### Field Attribute + +The field attribute defines which field the function is compatible for. The function is conditionally compiled, under the condition that the field attribute matches the Noir native field. +The field can be defined implicitly, by using the name of the elliptic curve usually associated to it - for instance bn254, bls12_381 - or explicitly by using the field (prime) order, in decimal or hexadecimal form. +As a result, it is possible to define multiple versions of a function with each version specialized for a different field attribute. This can be useful when a function requires different parameters depending on the underlying elliptic curve. + +Example: we define the function `foo()` three times below. Once for the default Noir bn254 curve, once for the field $\mathbb F_{23}$, which will normally never be used by Noir, and once again for the bls12_381 curve. + +```rust +#[field(bn254)] +fn foo() -> u32 { + 1 +} + +#[field(23)] +fn foo() -> u32 { + 2 +} + +// This commented code would not compile as foo would be defined twice because it is the same field as bn254 +// #[field(21888242871839275222246405745257275088548364400416034343698204186575808495617)] +// fn foo() -> u32 { +// 2 +// } + +#[field(bls12_381)] +fn foo() -> u32 { + 3 +} +``` + +If the field name is not known to Noir, it will discard the function. Field names are case insensitive. diff --git a/docs/versioned_docs/version-v0.25.0/noir/concepts/generics.md b/docs/versioned_docs/version-v0.25.0/noir/concepts/generics.md new file mode 100644 index 00000000000..ddd42bf1f9b --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/noir/concepts/generics.md @@ -0,0 +1,106 @@ +--- +title: Generics +description: Learn how to use Generics in Noir +keywords: [Noir, Rust, generics, functions, structs] +sidebar_position: 7 +--- + +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 print(self) { + for _i in 0 .. self.count { + println(self.value); + } + } +} + +fn main() { + let repeated = RepeatedValue { value: "Hello!", count: 2 }; + 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 + +Since a generic type `T` can represent any type, how can we call functions on the underlying type? +In other words, how can we go from "any type `T`" to "any type `T` that has certain methods available?" + +This is what [traits](../concepts/traits) are for in Noir. Here's an example of a function generic over +any type `T` that implements the `Eq` trait for equality: + +```rust +fn first_element_is_equal(array1: [T; N], array2: [T; N]) -> bool + where T: Eq +{ + if (array1.len() == 0) | (array2.len() == 0) { + true + } else { + array1[0] == array2[0] + } +} + +fn main() { + assert(first_element_is_equal([1, 2, 3], [1, 5, 6])); + + // We can use first_element_is_equal for arrays of any type + // as long as we have an Eq impl for the types we pass in + let array = [MyStruct::new(), MyStruct::new()]; + assert(array_eq(array, array, MyStruct::eq)); +} + +impl Eq for MyStruct { + fn eq(self, other: MyStruct) -> bool { + self.foo == other.foo + } +} +``` + +You can find more details on traits and trait implementations on the [traits page](../concepts/traits). diff --git a/docs/versioned_docs/version-v0.25.0/noir/concepts/globals.md b/docs/versioned_docs/version-v0.25.0/noir/concepts/globals.md new file mode 100644 index 00000000000..063a3d89248 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/noir/concepts/globals.md @@ -0,0 +1,72 @@ +--- +title: Global Variables +description: + Learn about global variables in Noir. Discover how + to declare, modify, and use them in your programs. +keywords: [noir programming language, globals, global variables, constants] +sidebar_position: 8 +--- + +## Globals + + +Noir supports global variables. The global's type can be inferred by the compiler entirely: + +```rust +global N = 5; // Same as `global N: Field = 5` + +global TUPLE = (3, 2); + +fn main() { + assert(N == 5); + assert(N == TUPLE.0 + TUPLE.1); +} +``` + +:::info + +Globals can be defined as any expression, so long as they don't depend on themselves - otherwise there would be a dependency cycle! For example: + +```rust +global T = foo(T); // dependency error +``` + +::: + + +If they are initialized to a literal integer, globals can be used to specify an array's length: + +```rust +global N: Field = 2; + +fn main(y : [Field; N]) { + assert(y[0] == y[1]) +} +``` + +A global from another module can be imported or referenced externally like any other name: + +```rust +global N = 20; + +fn main() { + assert(my_submodule::N != N); +} + +mod my_submodule { + global N: Field = 10; +} +``` + +When a global is used, Noir replaces the name with its definition on each occurrence. +This means globals defined using function calls will repeat the call each time they're used: + +```rust +global RESULT = foo(); + +fn foo() -> [Field; 100] { ... } +``` + +This is usually fine since Noir will generally optimize any function call that does not +refer to a program input into a constant. It should be kept in mind however, if the called +function performs side-effects like `println`, as these will still occur on each use. diff --git a/docs/versioned_docs/version-v0.25.0/noir/concepts/lambdas.md b/docs/versioned_docs/version-v0.25.0/noir/concepts/lambdas.md new file mode 100644 index 00000000000..be3c7e0b5ca --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/noir/concepts/lambdas.md @@ -0,0 +1,81 @@ +--- +title: Lambdas +description: Learn how to use anonymous functions in Noir programming language. +keywords: [Noir programming language, lambda, closure, function, anonymous function] +sidebar_position: 9 +--- + +## 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.25.0/noir/concepts/mutability.md b/docs/versioned_docs/version-v0.25.0/noir/concepts/mutability.md new file mode 100644 index 00000000000..fdeef6a87c5 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/noir/concepts/mutability.md @@ -0,0 +1,121 @@ +--- +title: Mutability +description: + Learn about mutable variables in Noir. Discover how + to declare, modify, and use them in your programs. +keywords: [noir programming language, mutability in noir, mutable variables] +sidebar_position: 8 +--- + +Variables in noir can be declared mutable via the `mut` keyword. Mutable variables can be reassigned +to via an assignment expression. + +```rust +let x = 2; +x = 3; // error: x must be mutable to be assigned to + +let mut y = 3; +let y = 4; // OK +``` + +The `mut` modifier can also apply to patterns: + +```rust +let (a, mut b) = (1, 2); +a = 11; // error: a must be mutable to be assigned to +b = 12; // OK + +let mut (c, d) = (3, 4); +c = 13; // OK +d = 14; // OK + +// etc. +let MyStruct { x: mut y } = MyStruct { x: a }; +// y is now in scope +``` + +Note that mutability in noir is local and everything is passed by value, so if a called function +mutates its parameters then the parent function will keep the old value of the parameters. + +```rust +fn main() -> pub Field { + let x = 3; + helper(x); + x // x is still 3 +} + +fn helper(mut x: i32) { + x = 4; +} +``` + +## Non-local mutability + +Non-local mutability can be achieved through the mutable reference type `&mut T`: + +```rust +fn set_to_zero(x: &mut Field) { + *x = 0; +} + +fn main() { + let mut y = 42; + set_to_zero(&mut y); + assert(*y == 0); +} +``` + +When creating a mutable reference, the original variable being referred to (`y` in this +example) must also be mutable. Since mutable references are a reference type, they must +be explicitly dereferenced via `*` to retrieve the underlying value. Note that this yields +a copy of the value, so mutating this copy will not change the original value behind the +reference: + +```rust +fn main() { + let mut x = 1; + let x_ref = &mut x; + + let mut y = *x_ref; + let y_ref = &mut y; + + x = 2; + *x_ref = 3; + + y = 4; + *y_ref = 5; + + assert(x == 3); + assert(*x_ref == 3); + assert(y == 5); + assert(*y_ref == 5); +} +``` + +Note that types in Noir are actually deeply immutable so the copy that occurs when +dereferencing is only a conceptual copy - no additional constraints will occur. + +Mutable references can also be stored within structs. Note that there is also +no lifetime parameter on these unlike rust. This is because the allocated memory +always lasts the entire program - as if it were an array of one element. + +```rust +struct Foo { + x: &mut Field +} + +impl Foo { + fn incr(mut self) { + *self.x += 1; + } +} + +fn main() { + let foo = Foo { x: &mut 0 }; + foo.incr(); + assert(*foo.x == 1); +} +``` + +In general, you should avoid non-local & shared mutability unless it is needed. Sticking +to only local mutability will improve readability and potentially improve compiler optimizations as well. diff --git a/docs/versioned_docs/version-v0.25.0/noir/concepts/ops.md b/docs/versioned_docs/version-v0.25.0/noir/concepts/ops.md new file mode 100644 index 00000000000..60425cb8994 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/noir/concepts/ops.md @@ -0,0 +1,98 @@ +--- +title: Logical Operations +description: + Learn about the supported arithmetic and logical operations in the Noir programming language. + Discover how to perform operations on private input types, integers, and booleans. +keywords: + [ + Noir programming language, + supported operations, + arithmetic operations, + logical operations, + predicate operators, + bitwise operations, + short-circuiting, + backend, + ] +sidebar_position: 3 +--- + +# Operations + +## Table of Supported Operations + +| Operation | Description | Requirements | +| :-------- | :------------------------------------------------------------: | -------------------------------------: | +| + | Adds two private input types together | Types must be private input | +| - | Subtracts two private input types together | Types must be private input | +| \* | Multiplies two private input types together | Types must be private input | +| / | Divides two private input types together | Types must be private input | +| ^ | XOR two private input types together | Types must be integer | +| & | AND two private input types together | Types must be integer | +| \| | OR two private input types together | Types must be integer | +| \<\< | Left shift an integer by another integer amount | Types must be integer | +| >> | Right shift an integer by another integer amount | Types must be integer | +| ! | Bitwise not of a value | Type must be integer or boolean | +| \< | returns a bool if one value is less than the other | Upper bound must have a known bit size | +| \<= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | +| > | returns a bool if one value is more than the other | Upper bound must have a known bit size | +| >= | returns a bool if one value is more than or equal to the other | Upper bound must have a known bit size | +| == | returns a bool if one value is equal to the other | Both types must not be constants | +| != | returns a bool if one value is not equal to the other | Both types must not be constants | + +### Predicate Operators + +`<,<=, !=, == , >, >=` are known as predicate/comparison operations because they compare two values. +This differs from the operations such as `+` where the operands are used in _computation_. + +### Bitwise Operations Example + +```rust +fn main(x : Field) { + let y = x as u32; + let z = y & y; +} +``` + +`z` is implicitly constrained to be the result of `y & y`. The `&` operand is used to denote bitwise +`&`. + +> `x & x` would not compile as `x` is a `Field` and not an integer type. + +### Logical Operators + +Noir has no support for the logical operators `||` and `&&`. This is because encoding the +short-circuiting that these operators require can be inefficient for Noir's backend. Instead you can +use the bitwise operators `|` and `&` which operate identically 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.25.0/noir/concepts/oracles.md b/docs/versioned_docs/version-v0.25.0/noir/concepts/oracles.md new file mode 100644 index 00000000000..2e6a6818d48 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/noir/concepts/oracles.md @@ -0,0 +1,23 @@ +--- +title: Oracles +description: Dive into how Noir supports Oracles via RPC calls, and learn how to declare an Oracle in Noir with our comprehensive guide. +keywords: + - Noir + - Oracles + - RPC Calls + - Unconstrained Functions + - Programming + - Blockchain +sidebar_position: 6 +--- + +Noir has support for Oracles via RPC calls. This means Noir will make an RPC call and use the return value for proof generation. + +Since Oracles are not resolved by Noir, they are [`unconstrained` functions](./unconstrained.md) + +You can declare an Oracle through the `#[oracle()]` flag. Example: + +```rust +#[oracle(get_number_sequence)] +unconstrained fn get_number_sequence(_size: Field) -> [Field] {} +``` diff --git a/docs/versioned_docs/version-v0.25.0/noir/concepts/shadowing.md b/docs/versioned_docs/version-v0.25.0/noir/concepts/shadowing.md new file mode 100644 index 00000000000..5ce6130d201 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/noir/concepts/shadowing.md @@ -0,0 +1,44 @@ +--- +title: Shadowing +sidebar_position: 12 +--- + +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.25.0/noir/concepts/traits.md b/docs/versioned_docs/version-v0.25.0/noir/concepts/traits.md new file mode 100644 index 00000000000..ef1445a5907 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/noir/concepts/traits.md @@ -0,0 +1,389 @@ +--- +title: Traits +description: + Traits in Noir can be used to abstract out a common interface for functions across + several data types. +keywords: [noir programming language, traits, interfaces, generic, protocol] +sidebar_position: 14 +--- + +## Overview + +Traits in Noir are a useful abstraction similar to interfaces or protocols in other languages. Each trait defines +the interface of several methods contained within the trait. Types can then implement this trait by providing +implementations for these methods. For example in the program: + +```rust +struct Rectangle { + width: Field, + height: Field, +} + +impl Rectangle { + fn area(self) -> Field { + self.width * self.height + } +} + +fn log_area(r: Rectangle) { + println(r.area()); +} +``` + +We have a function `log_area` to log the area of a `Rectangle`. Now how should we change the program if we want this +function to work on `Triangle`s as well?: + +```rust +struct Triangle { + width: Field, + height: Field, +} + +impl Triangle { + fn area(self) -> Field { + self.width * self.height / 2 + } +} +``` + +Making `log_area` generic over all types `T` would be invalid since not all types have an `area` method. Instead, we can +introduce a new `Area` trait and make `log_area` generic over all types `T` that implement `Area`: + +```rust +trait Area { + fn area(self) -> Field; +} + +fn log_area(shape: T) where T: Area { + println(shape.area()); +} +``` + +We also need to explicitly implement `Area` for `Rectangle` and `Triangle`. We can do that by changing their existing +impls slightly. Note that the parameter types and return type of each of our `area` methods must match those defined +by the `Area` trait. + +```rust +impl Area for Rectangle { + fn area(self) -> Field { + self.width * self.height + } +} + +impl Area for Triangle { + fn area(self) -> Field { + self.width * self.height / 2 + } +} +``` + +Now we have a working program that is generic over any type of Shape that is used! Others can even use this program +as a library with their own types - such as `Circle` - as long as they also implement `Area` for these types. + +## Where Clauses + +As seen in `log_area` above, when we want to create a function or method that is generic over any type that implements +a trait, we can add a where clause to the generic function. + +```rust +fn log_area(shape: T) where T: Area { + println(shape.area()); +} +``` + +It is also possible to apply multiple trait constraints on the same variable at once by combining traits with the `+` +operator. Similarly, we can have multiple trait constraints by separating each with a comma: + +```rust +fn foo(elements: [T], thing: U) where + T: Default + Add + Eq, + U: Bar, +{ + let mut sum = T::default(); + + for element in elements { + sum += element; + } + + if sum == T::default() { + thing.bar(); + } +} +``` + +## Generic Implementations + +You can add generics to a trait implementation by adding the generic list after the `impl` keyword: + +```rust +trait Second { + fn second(self) -> Field; +} + +impl Second for (T, Field) { + fn second(self) -> Field { + self.1 + } +} +``` + +You can also implement a trait for every type this way: + +```rust +trait Debug { + fn debug(self); +} + +impl Debug for T { + fn debug(self) { + println(self); + } +} + +fn main() { + 1.debug(); +} +``` + +### Generic Trait Implementations With Where Clauses + +Where clauses can also be placed on trait implementations themselves to restrict generics in a similar way. +For example, while `impl Foo for T` implements the trait `Foo` for every type, `impl Foo for T where T: Bar` +will implement `Foo` only for types that also implement `Bar`. This is often used for implementing generic types. +For example, here is the implementation for array equality: + +```rust +impl Eq for [T; N] where T: Eq { + // Test if two arrays have the same elements. + // Because both arrays must have length N, we know their lengths already match. + fn eq(self, other: Self) -> bool { + let mut result = true; + + for i in 0 .. self.len() { + // The T: Eq constraint is needed to call == on the array elements here + result &= self[i] == other[i]; + } + + result + } +} +``` + +## Generic Traits + +Traits themselves can also be generic by placing the generic arguments after the trait name. These generics are in +scope of every item within the trait. + +```rust +trait Into { + // Convert `self` to type `T` + fn into(self) -> T; +} +``` + +When implementing generic traits the generic arguments of the trait must be specified. This is also true anytime +when referencing a generic trait (e.g. in a `where` clause). + +```rust +struct MyStruct { + array: [Field; 2], +} + +impl Into<[Field; 2]> for MyStruct { + fn into(self) -> [Field; 2] { + self.array + } +} + +fn as_array(x: T) -> [Field; 2] + where T: Into<[Field; 2]> +{ + x.into() +} + +fn main() { + let array = [1, 2]; + let my_struct = MyStruct { array }; + + assert_eq(as_array(my_struct), array); +} +``` + +## Trait Methods With No `self` + +A trait can contain any number of methods, each of which have access to the `Self` type which represents each type +that eventually implements the trait. Similarly, the `self` variable is available as well but is not required to be used. +For example, we can define a trait to create a default value for a type. This trait will need to return the `Self` type +but doesn't need to take any parameters: + +```rust +trait Default { + fn default() -> Self; +} +``` + +Implementing this trait can be done similarly to any other trait: + +```rust +impl Default for Field { + fn default() -> Field { + 0 + } +} + +struct MyType {} + +impl Default for MyType { + fn default() -> Field { + MyType {} + } +} +``` + +However, since there is no `self` parameter, we cannot call it via the method call syntax `object.method()`. +Instead, we'll need to refer to the function directly. This can be done either by referring to the +specific impl `MyType::default()` or referring to the trait itself `Default::default()`. In the later +case, type inference determines the impl that is selected. + +```rust +let my_struct = MyStruct::default(); + +let x: Field = Default::default(); +let result = x + Default::default(); +``` + +:::warning + +```rust +let _ = Default::default(); +``` + +If type inference cannot select which impl to use because of an ambiguous `Self` type, an impl will be +arbitrarily selected. This occurs most often when the result of a trait function call with no parameters +is unused. To avoid this, when calling a trait function with no `self` or `Self` parameters or return type, +always refer to it via the implementation type's namespace - e.g. `MyType::default()`. +This is set to change to an error in future Noir versions. + +::: + +## Default Method Implementations + +A trait can also have default implementations of its methods by giving a body to the desired functions. +Note that this body must be valid for all types that may implement the trait. As a result, the only +valid operations on `self` will be operations valid for any type or other operations on the trait itself. + +```rust +trait Numeric { + fn add(self, other: Self) -> Self; + + // Default implementation of double is (self + self) + fn double(self) -> Self { + self.add(self) + } +} +``` + +When implementing a trait with default functions, a type may choose to implement only the required functions: + +```rust +impl Numeric for Field { + fn add(self, other: Field) -> Field { + self + other + } +} +``` + +Or it may implement the optional methods as well: + +```rust +impl Numeric for u32 { + fn add(self, other: u32) -> u32 { + self + other + } + + fn double(self) -> u32 { + self * 2 + } +} +``` + +## Impl Specialization + +When implementing traits for a generic type it is possible to implement the trait for only a certain combination +of generics. This can be either as an optimization or because those specific generics are required to implement the trait. + +```rust +trait Sub { + fn sub(self, other: Self) -> Self; +} + +struct NonZero { + value: T, +} + +impl Sub for NonZero { + fn sub(self, other: Self) -> Self { + let value = self.value - other.value; + assert(value != 0); + NonZero { value } + } +} +``` + +## Overlapping Implementations + +Overlapping implementations are disallowed by Noir to ensure Noir's decision on which impl to select is never ambiguous. +This means if a trait `Foo` is already implemented +by a type `Bar` for all `T`, then we cannot also have a separate impl for `Bar` (or any other +type argument). Similarly, if there is an impl for all `T` such as `impl Debug for T`, we cannot create +any more impls to `Debug` for other types since it would be ambiguous which impl to choose for any given +method call. + +```rust +trait Trait {} + +// Previous impl defined here +impl Trait for (A, B) {} + +// error: Impl for type `(Field, Field)` overlaps with existing impl +impl Trait for (Field, Field) {} +``` + +## Trait Coherence + +Another restriction on trait implementations is coherence. This restriction ensures other crates cannot create +impls that may overlap with other impls, even if several unrelated crates are used as dependencies in the same +program. + +The coherence restriction is: to implement a trait, either the trait itself or the object type must be declared +in the crate the impl is in. + +In practice this often comes up when using types provided by libraries. If a library provides a type `Foo` that does +not implement a trait in the standard library such as `Default`, you may not `impl Default for Foo` in your own crate. +While restrictive, this prevents later issues or silent changes in the program if the `Foo` library later added its +own impl for `Default`. If you are a user of the `Foo` library in this scenario and need a trait not implemented by the +library your choices are to either submit a patch to the library or use the newtype pattern. + +### The Newtype Pattern + +The newtype pattern gets around the coherence restriction by creating a new wrapper type around the library type +that we cannot create `impl`s for. Since the new wrapper type is defined in our current crate, we can create +impls for any trait we need on it. + +```rust +struct Wrapper { + foo: dep::some_library::Foo, +} + +impl Default for Wrapper { + fn default() -> Wrapper { + Wrapper { + foo: dep::some_library::Foo::new(), + } + } +} +``` + +Since we have an impl for our own type, the behavior of this code will not change even if `some_library` is updated +to provide its own `impl Default for Foo`. The downside of this pattern is that it requires extra wrapping and +unwrapping of values when converting to and from the `Wrapper` and `Foo` types. diff --git a/docs/versioned_docs/version-v0.25.0/noir/concepts/unconstrained.md b/docs/versioned_docs/version-v0.25.0/noir/concepts/unconstrained.md new file mode 100644 index 00000000000..89d12c1c971 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/noir/concepts/unconstrained.md @@ -0,0 +1,95 @@ +--- +title: Unconstrained Functions +description: "Learn about what unconstrained functions in Noir are, how to use them and when you'd want to." + +keywords: [Noir programming language, unconstrained, open] +sidebar_position: 5 +--- + +Unconstrained functions are functions which do not constrain any of the included computation and allow for non-deterministic 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 AND 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.25.0/noir/modules_packages_crates/_category_.json b/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/_category_.json new file mode 100644 index 00000000000..1debcfe7675 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Modules, Packages and Crates", + "position": 2, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/crates_and_packages.md b/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/crates_and_packages.md new file mode 100644 index 00000000000..95ee9f52ab2 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/crates_and_packages.md @@ -0,0 +1,43 @@ +--- +title: Crates and Packages +description: Learn how to use Crates and Packages in your Noir project +keywords: [Nargo, dependencies, package management, crates, package] +sidebar_position: 0 +--- + +## Crates + +A crate is the smallest amount of code that the Noir compiler considers at a time. +Crates can contain modules, and the modules may be defined in other files that get compiled with the crate, as we’ll see in the coming sections. + +### Crate Types + +A Noir crate can come in several forms: binaries, libraries or contracts. + +#### Binaries + +_Binary crates_ are programs which you can compile to an ACIR circuit which you can then create proofs against. Each must have a function called `main` that defines the ACIR circuit which is to be proved. + +#### Libraries + +_Library crates_ don't have a `main` function and they don't compile down to ACIR. Instead they define functionality intended to be shared with multiple projects, and eventually included in a binary crate. + +#### Contracts + +Contract crates are similar to binary crates in that they compile to ACIR which you can create proofs against. They are different in that they do not have a single `main` function, but are a collection of functions to be deployed to the [Aztec network](https://aztec.network). You can learn more about the technical details of Aztec in the [monorepo](https://github.com/AztecProtocol/aztec-packages) or contract [examples](https://github.com/AztecProtocol/aztec-packages/tree/master/noir-projects/noir-contracts/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.25.0/noir/modules_packages_crates/dependencies.md b/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/dependencies.md new file mode 100644 index 00000000000..04c1703d929 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/dependencies.md @@ -0,0 +1,124 @@ +--- +title: Dependencies +description: + Learn how to specify and manage dependencies in Nargo, allowing you to upload packages to GitHub + and use them easily in your project. +keywords: [Nargo, dependencies, GitHub, package management, versioning] +sidebar_position: 1 +--- + +Nargo allows you to upload packages to GitHub and use them as dependencies. + +## Specifying a dependency + +Specifying a dependency requires a tag to a specific commit and the git url to the url containing +the package. + +Currently, there are no requirements on the tag contents. If requirements are added, it would follow +semver 2.0 guidelines. + +> Note: Without a `tag` , there would be no versioning and dependencies would change each time you +> compile your project. + +For example, to add the [ecrecover-noir library](https://github.com/colinnielsen/ecrecover-noir) to your project, add it to `Nargo.toml`: + +```toml +# Nargo.toml + +[dependencies] +ecrecover = {tag = "v0.8.0", git = "https://github.com/colinnielsen/ecrecover-noir"} +``` + +If the module is in a subdirectory, you can define a subdirectory in your git repository, for example: + +```toml +# Nargo.toml + +[dependencies] +easy_private_token_contract = {tag ="v0.1.0-alpha62", git = "https://github.com/AztecProtocol/aztec-packages", directory = "noir-contracts/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 +└── lib_a + ├── Nargo.toml + └── src + └── lib.nr +``` + +Inside of the binary crate, you can specify: + +```toml +# Nargo.toml + +[dependencies] +lib_a = { path = "../lib_a" } +``` + +## 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 lib_a referenced above: + +```rust +use dep::ecrecover; +use dep::lib_a; +``` + +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.25.0/noir/modules_packages_crates/modules.md b/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/modules.md new file mode 100644 index 00000000000..ae822a1cff4 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/modules.md @@ -0,0 +1,105 @@ +--- +title: Modules +description: + Learn how to organize your files using modules in Noir, following the same convention as Rust's + module system. Examples included. +keywords: [Noir, Rust, modules, organizing files, sub-modules] +sidebar_position: 2 +--- + +Noir's module system follows the same convention as the _newer_ version of Rust's module system. + +## Purpose of Modules + +Modules are used to organize 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.25.0/noir/modules_packages_crates/workspaces.md b/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/workspaces.md new file mode 100644 index 00000000000..513497f12bf --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/workspaces.md @@ -0,0 +1,42 @@ +--- +title: Workspaces +sidebar_position: 3 +--- + +Workspaces are a feature of nargo that allow you to manage multiple related Noir packages in a single repository. A workspace is essentially a group of related projects that share common build output directories and configurations. + +Each Noir project (with it's own Nargo.toml file) can be thought of as a package. Each package is expected to contain exactly one "named circuit", being the "name" defined in Nargo.toml with the program logic defined in `./src/main.nr`. + +For a project with the following structure: + +```tree +├── crates +│ ├── a +│ │ ├── Nargo.toml +│ │ └── Prover.toml +│ │ └── src +│ │ └── main.nr +│ └── b +│ ├── Nargo.toml +│ └── Prover.toml +│ └── src +│ └── main.nr +│ +└── Nargo.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.25.0/noir/standard_library/_category_.json b/docs/versioned_docs/version-v0.25.0/noir/standard_library/_category_.json new file mode 100644 index 00000000000..af04c0933fd --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/noir/standard_library/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Standard Library", + "position": 1, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.25.0/noir/standard_library/black_box_fns.md b/docs/versioned_docs/version-v0.25.0/noir/standard_library/black_box_fns.md new file mode 100644 index 00000000000..be8c65679c3 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/noir/standard_library/black_box_fns.md @@ -0,0 +1,31 @@ +--- +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. + +The ACVM spec defines a set of blackbox functions which backends will be expected to implement. This allows backends to use optimized implementations of these constraints if they have them, however they may also fallback to less efficient naive implementations if not. + +## Function list + +Here is a list of the current black box functions: + +- [SHA256](./cryptographic_primitives/hashes.mdx#sha256) +- [Schnorr signature verification](./cryptographic_primitives/schnorr.mdx) +- [Blake2s](./cryptographic_primitives/hashes.mdx#blake2s) +- [Blake3](./cryptographic_primitives/hashes.mdx#blake3) +- [Pedersen Hash](./cryptographic_primitives/hashes.mdx#pedersen_hash) +- [Pedersen Commitment](./cryptographic_primitives/hashes.mdx#pedersen_commitment) +- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification.mdx) +- [Fixed base scalar multiplication](./cryptographic_primitives/scalar.mdx) +- AND +- XOR +- RANGE +- [Keccak256](./cryptographic_primitives/hashes.mdx#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. + +You can view the black box functions defined in the ACVM code [here](https://github.com/noir-lang/noir/blob/master/acvm-repo/acir/src/circuit/black_box_functions.rs). diff --git a/docs/versioned_docs/version-v0.25.0/noir/standard_library/bn254.md b/docs/versioned_docs/version-v0.25.0/noir/standard_library/bn254.md new file mode 100644 index 00000000000..3294f005dbb --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/noir/standard_library/bn254.md @@ -0,0 +1,46 @@ +--- +title: Bn254 Field Library +--- + +Noir provides a module in standard library with some optimized functions for bn254 Fr in `std::field::bn254`. + +## decompose + +```rust +fn decompose(x: Field) -> (Field, Field) {} +``` + +Decomposes a single field into two fields, low and high. The low field contains the lower 16 bytes of the input field and the high field contains the upper 16 bytes of the input field. Both field results are range checked to 128 bits. + + +## assert_gt + +```rust +fn assert_gt(a: Field, b: Field) {} +``` + +Asserts that a > b. This will generate less constraints than using `assert(gt(a, b))`. + +## assert_lt + +```rust +fn assert_lt(a: Field, b: Field) {} +``` + +Asserts that a < b. This will generate less constraints than using `assert(lt(a, b))`. + +## gt + +```rust +fn gt(a: Field, b: Field) -> bool {} +``` + +Returns true if a > b. + +## lt + +```rust +fn lt(a: Field, b: Field) -> bool {} +``` + +Returns true if a < b. \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.25.0/noir/standard_library/containers/boundedvec.md b/docs/versioned_docs/version-v0.25.0/noir/standard_library/containers/boundedvec.md new file mode 100644 index 00000000000..ce4529f6e57 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/noir/standard_library/containers/boundedvec.md @@ -0,0 +1,326 @@ +--- +title: Bounded Vectors +keywords: [noir, vector, bounded vector, slice] +sidebar_position: 1 +--- + +A `BoundedVec` is a growable storage similar to a `Vec` except that it +is bounded with a maximum possible length. Unlike `Vec`, `BoundedVec` is not implemented +via slices and thus is not subject to the same restrictions slices are (notably, nested +slices - and thus nested vectors as well - are disallowed). + +Since a BoundedVec is backed by a normal array under the hood, growing the BoundedVec by +pushing an additional element is also more efficient - the length only needs to be increased +by one. + +For these reasons `BoundedVec` should generally be preferred over `Vec` when there +is a reasonable maximum bound that can be placed on the vector. + +Example: + +```rust +let mut vector: BoundedVec = BoundedVec::new(); +for i in 0..5 { + vector.push(i); +} +assert(vector.len() == 5); +assert(vector.max_len() == 10); +``` + +## Methods + +### new + +```rust +pub fn new() -> Self +``` + +Creates a new, empty vector of length zero. + +Since this container is backed by an array internally, it still needs an initial value +to give each element. To resolve this, each element is zeroed internally. This value +is guaranteed to be inaccessible unless `get_unchecked` is used. + +Example: + +```rust +let empty_vector: BoundedVec = BoundedVec::new(); +assert(empty_vector.len() == 0); +``` + +Note that whenever calling `new` the maximum length of the vector should always be specified +via a type signature: + +```rust title="new_example" showLineNumbers +fn foo() -> BoundedVec { + // Ok! MaxLen is specified with a type annotation + let v1: BoundedVec = BoundedVec::new(); + let v2 = BoundedVec::new(); + + // Ok! MaxLen is known from the type of foo's return value + v2 +} + +fn bad() { + let mut v3 = BoundedVec::new(); + + // Not Ok! We don't know if v3's MaxLen is at least 1, and the compiler often infers 0 by default. + v3.push(5); +} +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L11-L27 + + +This defaulting of `MaxLen` (and numeric generics in general) to zero may change in future noir versions +but for now make sure to use type annotations when using bounded vectors. Otherwise, you will receive a constraint failure at runtime when the vec is pushed to. + +### get + +```rust +pub fn get(mut self: Self, index: u64) -> T { +``` + +Retrieves an element from the vector at the given index, starting from zero. + +If the given index is equal to or greater than the length of the vector, this +will issue a constraint failure. + +Example: + +```rust +fn foo(v: BoundedVec) { + let first = v.get(0); + let last = v.get(v.len() - 1); + assert(first != last); +} +``` + +### get_unchecked + +```rust +pub fn get_unchecked(mut self: Self, index: u64) -> T { +``` + +Retrieves an element from the vector at the given index, starting from zero, without +performing a bounds check. + +Since this function does not perform a bounds check on length before accessing the element, +it is unsafe! Use at your own risk! + +Example: + +```rust title="get_unchecked_example" showLineNumbers +fn sum_of_first_three(v: BoundedVec) -> u32 { + // Always ensure the length is larger than the largest + // index passed to get_unchecked + assert(v.len() > 2); + let first = v.get_unchecked(0); + let second = v.get_unchecked(1); + let third = v.get_unchecked(2); + first + second + third +} +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L54-L64 + + + +### push + +```rust +pub fn push(&mut self, elem: T) { +``` + +Pushes an element to the end of the vector. This increases the length +of the vector by one. + +Panics if the new length of the vector will be greater than the max length. + +Example: + +```rust title="bounded-vec-push-example" showLineNumbers +let mut v: BoundedVec = BoundedVec::new(); + + v.push(1); + v.push(2); + + // Panics with failed assertion "push out of bounds" + v.push(3); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L68-L76 + + +### pop + +```rust +pub fn pop(&mut self) -> T +``` + +Pops the element at the end of the vector. This will decrease the length +of the vector by one. + +Panics if the vector is empty. + +Example: + +```rust title="bounded-vec-pop-example" showLineNumbers +let mut v: BoundedVec = BoundedVec::new(); + v.push(1); + v.push(2); + + let two = v.pop(); + let one = v.pop(); + + assert(two == 2); + assert(one == 1); + // error: cannot pop from an empty vector + // let _ = v.pop(); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L81-L93 + + +### len + +```rust +pub fn len(self) -> u64 { +``` + +Returns the current length of this vector + +Example: + +```rust title="bounded-vec-len-example" showLineNumbers +let mut v: BoundedVec = BoundedVec::new(); + assert(v.len() == 0); + + v.push(100); + assert(v.len() == 1); + + v.push(200); + v.push(300); + v.push(400); + assert(v.len() == 4); + + let _ = v.pop(); + let _ = v.pop(); + assert(v.len() == 2); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L98-L113 + + +### max_len + +```rust +pub fn max_len(_self: BoundedVec) -> u64 { +``` + +Returns the maximum length of this vector. This is always +equal to the `MaxLen` parameter this vector was initialized with. + +Example: + +```rust title="bounded-vec-max-len-example" showLineNumbers +let mut v: BoundedVec = BoundedVec::new(); + + assert(v.max_len() == 5); + v.push(10); + assert(v.max_len() == 5); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L118-L124 + + +### storage + +```rust +pub fn storage(self) -> [T; MaxLen] { +``` + +Returns the internal array within this vector. +Since arrays in Noir are immutable, mutating the returned storage array will not mutate +the storage held internally by this vector. + +Note that uninitialized elements may be zeroed out! + +Example: + +```rust title="bounded-vec-storage-example" showLineNumbers +let mut v: BoundedVec = BoundedVec::new(); + + assert(v.storage() == [0, 0, 0, 0, 0]); + + v.push(57); + assert(v.storage() == [57, 0, 0, 0, 0]); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L129-L136 + + +### extend_from_array + +```rust +pub fn extend_from_array(&mut self, array: [T; Len]) +``` + +Pushes each element from the given array to this vector. + +Panics if pushing each element would cause the length of this vector +to exceed the maximum length. + +Example: + +```rust title="bounded-vec-extend-from-array-example" showLineNumbers +let mut vec: BoundedVec = BoundedVec::new(); + vec.extend_from_array([2, 4]); + + assert(vec.len == 2); + assert(vec.get(0) == 2); + assert(vec.get(1) == 4); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L141-L148 + + +### extend_from_bounded_vec + +```rust +pub fn extend_from_bounded_vec(&mut self, vec: BoundedVec) +``` + +Pushes each element from the other vector to this vector. The length of +the other vector is left unchanged. + +Panics if pushing each element would cause the length of this vector +to exceed the maximum length. + +Example: + +```rust title="bounded-vec-extend-from-bounded-vec-example" showLineNumbers +let mut v1: BoundedVec = BoundedVec::new(); + let mut v2: BoundedVec = BoundedVec::new(); + + v2.extend_from_array([1, 2, 3]); + v1.extend_from_bounded_vec(v2); + + assert(v1.storage() == [1, 2, 3, 0, 0]); + assert(v2.storage() == [1, 2, 3, 0, 0, 0, 0]); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L153-L162 + + +### any + +```rust +pub fn any(self, predicate: fn[Env](T) -> bool) -> bool +``` + +Returns true if the given predicate returns true for any element +in this vector. + +Example: + +```rust title="bounded-vec-any-example" showLineNumbers +let mut v: BoundedVec = BoundedVec::new(); + v.extend_from_array([2, 4, 6]); + + let all_even = !v.any(|elem: u32| elem % 2 != 0); + assert(all_even); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L229-L235 + diff --git a/docs/versioned_docs/version-v0.25.0/noir/standard_library/containers/hashmap.md b/docs/versioned_docs/version-v0.25.0/noir/standard_library/containers/hashmap.md new file mode 100644 index 00000000000..91604af765d --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/noir/standard_library/containers/hashmap.md @@ -0,0 +1,569 @@ +--- +title: HashMap +keywords: [noir, map, hash, hashmap] +sidebar_position: 1 +--- + +`HashMap` is used to efficiently store and look up key-value pairs. + +`HashMap` is a bounded type which can store anywhere from zero to `MaxLen` total elements. +Note that due to hash collisions, the actual maximum number of elements stored by any particular +hashmap is likely lower than `MaxLen`. This is true even with cryptographic hash functions since +every hash value will be performed modulo `MaxLen`. + +When creating `HashMap`s, the `MaxLen` generic should always be specified if it is not already +known. Otherwise, the compiler may infer a different value for `MaxLen` (such as zero), which +will likely change the result of the program. This behavior is set to become an error in future +versions instead. + +Example: + +```rust +// Create a mapping from Fields to u32s with a maximum length of 12 +// using a pedersen hash +let mut map: HashMap> = HashMap::default(); + +map.insert(1, 2); +map.insert(3, 4); + +let two = map.get(1).unwrap(); +``` + +## Methods + +### default + +```rust title="default" showLineNumbers +impl Default for HashMap +where + B: BuildHasher + Default, + H: Hasher + Default +{ + fn default() -> Self { +``` +> Source code: noir_stdlib/src/collections/map.nr#L462-L469 + + +Creates a fresh, empty HashMap. + +When using this function, always make sure to specify the maximum size of the hash map. + +This is the same `default` from the `Default` implementation given further below. It is +repeated here for convenience since it is the recommended way to create a hashmap. + +Example: + +```rust title="default_example" showLineNumbers +let hashmap: HashMap> = HashMap::default(); + assert(hashmap.is_empty()); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L202-L205 + + +Because `HashMap` has so many generic arguments that are likely to be the same throughout +your program, it may be helpful to create a type alias: + +```rust title="type_alias" showLineNumbers +type MyMap = HashMap>; +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L196-L198 + + +### with_hasher + +```rust title="with_hasher" showLineNumbers +pub fn with_hasher(_build_hasher: B) -> Self + where + B: BuildHasher { +``` +> Source code: noir_stdlib/src/collections/map.nr#L82-L86 + + +Creates a hashmap with an existing `BuildHasher`. This can be used to ensure multiple +hashmaps are created with the same hasher instance. + +Example: + +```rust title="with_hasher_example" showLineNumbers +let my_hasher: BuildHasherDefault = Default::default(); + let hashmap: HashMap> = HashMap::with_hasher(my_hasher); + assert(hashmap.is_empty()); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L207-L211 + + +### get + +```rust title="get" showLineNumbers +pub fn get( + self, + key: K + ) -> Option + where + K: Eq + Hash, + B: BuildHasher, + H: Hasher { +``` +> Source code: noir_stdlib/src/collections/map.nr#L278-L287 + + +Retrieves a value from the hashmap, returning `Option::none()` if it was not found. + +Example: + +```rust title="get_example" showLineNumbers +fn get_example(map: HashMap>) { + let x = map.get(12); + + if x.is_some() { + assert(x.unwrap() == 42); + } +} +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L299-L307 + + +### insert + +```rust title="insert" showLineNumbers +pub fn insert( + &mut self, + key: K, + value: V + ) + where + K: Eq + Hash, + B: BuildHasher, + H: Hasher { +``` +> Source code: noir_stdlib/src/collections/map.nr#L313-L323 + + +Inserts a new key-value pair into the map. If the key was already in the map, its +previous value will be overridden with the newly provided one. + +Example: + +```rust title="insert_example" showLineNumbers +let mut map: HashMap> = HashMap::default(); + map.insert(12, 42); + assert(map.len() == 1); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L213-L217 + + +### remove + +```rust title="remove" showLineNumbers +pub fn remove( + &mut self, + key: K + ) + where + K: Eq + Hash, + B: BuildHasher, + H: Hasher { +``` +> Source code: noir_stdlib/src/collections/map.nr#L356-L365 + + +Removes the given key-value pair from the map. If the key was not already present +in the map, this does nothing. + +Example: + +```rust title="remove_example" showLineNumbers +map.remove(12); + assert(map.is_empty()); + + // If a key was not present in the map, remove does nothing + map.remove(12); + assert(map.is_empty()); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L221-L228 + + +### is_empty + +```rust title="is_empty" showLineNumbers +pub fn is_empty(self) -> bool { +``` +> Source code: noir_stdlib/src/collections/map.nr#L115-L117 + + +True if the length of the hash map is empty. + +Example: + +```rust title="is_empty_example" showLineNumbers +assert(map.is_empty()); + + map.insert(1, 2); + assert(!map.is_empty()); + + map.remove(1); + assert(map.is_empty()); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L230-L238 + + +### len + +```rust title="len" showLineNumbers +pub fn len(self) -> u64 { +``` +> Source code: noir_stdlib/src/collections/map.nr#L264-L266 + + +Returns the current length of this hash map. + +Example: + +```rust title="len_example" showLineNumbers +// This is equivalent to checking map.is_empty() + assert(map.len() == 0); + + map.insert(1, 2); + map.insert(3, 4); + map.insert(5, 6); + assert(map.len() == 3); + + // 3 was already present as a key in the hash map, so the length is unchanged + map.insert(3, 7); + assert(map.len() == 3); + + map.remove(1); + assert(map.len() == 2); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L240-L255 + + +### capacity + +```rust title="capacity" showLineNumbers +pub fn capacity(_self: Self) -> u64 { +``` +> Source code: noir_stdlib/src/collections/map.nr#L271-L273 + + +Returns the maximum capacity of this hashmap. This is always equal to the capacity +specified in the hashmap's type. + +Unlike hashmaps in general purpose programming languages, hashmaps in Noir have a +static capacity that does not increase as the map grows larger. Thus, this capacity +is also the maximum possible element count that can be inserted into the hashmap. +Due to hash collisions (modulo the hashmap length), it is likely the actual maximum +element count will be lower than the full capacity. + +Example: + +```rust title="capacity_example" showLineNumbers +let empty_map: HashMap> = HashMap::default(); + assert(empty_map.len() == 0); + assert(empty_map.capacity() == 42); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L257-L261 + + +### clear + +```rust title="clear" showLineNumbers +pub fn clear(&mut self) { +``` +> Source code: noir_stdlib/src/collections/map.nr#L93-L95 + + +Clears the hashmap, removing all key-value pairs from it. + +Example: + +```rust title="clear_example" showLineNumbers +assert(!map.is_empty()); + map.clear(); + assert(map.is_empty()); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L263-L267 + + +### contains_key + +```rust title="contains_key" showLineNumbers +pub fn contains_key( + self, + key: K + ) -> bool + where + K: Hash + Eq, + B: BuildHasher, + H: Hasher { +``` +> Source code: noir_stdlib/src/collections/map.nr#L101-L110 + + +True if the hashmap contains the given key. Unlike `get`, this will not also return +the value associated with the key. + +Example: + +```rust title="contains_key_example" showLineNumbers +if map.contains_key(7) { + let value = map.get(7); + assert(value.is_some()); + } else { + println("No value for key 7!"); + } +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L269-L276 + + +### entries + +```rust title="entries" showLineNumbers +pub fn entries(self) -> BoundedVec<(K, V), N> { +``` +> Source code: noir_stdlib/src/collections/map.nr#L123-L125 + + +Returns a vector of each key-value pair present in the hashmap. + +The length of the returned vector is always equal to the length of the hashmap. + +Example: + +```rust title="entries_example" showLineNumbers +let entries = map.entries(); + + // The length of a hashmap may not be compile-time known, so we + // need to loop over its capacity instead + for i in 0..map.capacity() { + if i < entries.len() { + let (key, value) = entries.get(i); + println(f"{key} -> {value}"); + } + } +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L310-L321 + + +### keys + +```rust title="keys" showLineNumbers +pub fn keys(self) -> BoundedVec { +``` +> Source code: noir_stdlib/src/collections/map.nr#L144-L146 + + +Returns a vector of each key present in the hashmap. + +The length of the returned vector is always equal to the length of the hashmap. + +Example: + +```rust title="keys_example" showLineNumbers +let keys = map.keys(); + + for i in 0..keys.max_len() { + if i < keys.len() { + let key = keys.get_unchecked(i); + let value = map.get(key).unwrap_unchecked(); + println(f"{key} -> {value}"); + } + } +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L323-L333 + + +### values + +```rust title="values" showLineNumbers +pub fn values(self) -> BoundedVec { +``` +> Source code: noir_stdlib/src/collections/map.nr#L164-L166 + + +Returns a vector of each value present in the hashmap. + +The length of the returned vector is always equal to the length of the hashmap. + +Example: + +```rust title="values_example" showLineNumbers +let values = map.values(); + + for i in 0..values.max_len() { + if i < values.len() { + let value = values.get_unchecked(i); + println(f"Found value {value}"); + } + } +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L335-L344 + + +### iter_mut + +```rust title="iter_mut" showLineNumbers +pub fn iter_mut( + &mut self, + f: fn(K, V) -> (K, V) + ) + where + K: Eq + Hash, + B: BuildHasher, + H: Hasher { +``` +> Source code: noir_stdlib/src/collections/map.nr#L183-L192 + + +Iterates through each key-value pair of the HashMap, setting each key-value pair to the +result returned from the given function. + +Note that since keys can be mutated, the HashMap needs to be rebuilt as it is iterated +through. If this is not desired, use `iter_values_mut` if only values need to be mutated, +or `entries` if neither keys nor values need to be mutated. + +The iteration order is left unspecified. As a result, if two keys are mutated to become +equal, which of the two values that will be present for the key in the resulting map is also unspecified. + +Example: + +```rust title="iter_mut_example" showLineNumbers +// Add 1 to each key in the map, and double the value associated with that key. + map.iter_mut(|k, v| (k + 1, v * 2)); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L348-L351 + + +### iter_keys_mut + +```rust title="iter_keys_mut" showLineNumbers +pub fn iter_keys_mut( + &mut self, + f: fn(K) -> K + ) + where + K: Eq + Hash, + B: BuildHasher, + H: Hasher { +``` +> Source code: noir_stdlib/src/collections/map.nr#L208-L217 + + +Iterates through the HashMap, mutating each key to the result returned from +the given function. + +Note that since keys can be mutated, the HashMap needs to be rebuilt as it is iterated +through. If only iteration is desired and the keys are not intended to be mutated, +prefer using `entries` instead. + +The iteration order is left unspecified. As a result, if two keys are mutated to become +equal, which of the two values that will be present for the key in the resulting map is also unspecified. + +Example: + +```rust title="iter_keys_mut_example" showLineNumbers +// Double each key, leaving the value associated with that key untouched + map.iter_keys_mut(|k| k * 2); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L353-L356 + + +### iter_values_mut + +```rust title="iter_values_mut" showLineNumbers +pub fn iter_values_mut(&mut self, f: fn(V) -> V) { +``` +> Source code: noir_stdlib/src/collections/map.nr#L233-L235 + + +Iterates through the HashMap, applying the given function to each value and mutating the +value to equal the result. This function is more efficient than `iter_mut` and `iter_keys_mut` +because the keys are untouched and the underlying hashmap thus does not need to be reordered. + +Example: + +```rust title="iter_values_mut_example" showLineNumbers +// Halve each value + map.iter_values_mut(|v| v / 2); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L358-L361 + + +### retain + +```rust title="retain" showLineNumbers +pub fn retain(&mut self, f: fn(K, V) -> bool) { +``` +> Source code: noir_stdlib/src/collections/map.nr#L247-L249 + + +Retains only the key-value pairs for which the given function returns true. +Any key-value pairs for which the function returns false will be removed from the map. + +Example: + +```rust title="retain_example" showLineNumbers +map.retain(|k, v| (k != 0) & (v != 0)); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L281-L283 + + +## Trait Implementations + +### default + +```rust title="default" showLineNumbers +impl Default for HashMap +where + B: BuildHasher + Default, + H: Hasher + Default +{ + fn default() -> Self { +``` +> Source code: noir_stdlib/src/collections/map.nr#L462-L469 + + +Constructs an empty HashMap. + +Example: + +```rust title="default_example" showLineNumbers +let hashmap: HashMap> = HashMap::default(); + assert(hashmap.is_empty()); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L202-L205 + + +### eq + +```rust title="eq" showLineNumbers +impl Eq for HashMap +where + K: Eq + Hash, + V: Eq, + B: BuildHasher, + H: Hasher +{ + fn eq(self, other: HashMap) -> bool { +``` +> Source code: noir_stdlib/src/collections/map.nr#L426-L435 + + +Checks if two HashMaps are equal. + +Example: + +```rust title="eq_example" showLineNumbers +let mut map1: HashMap> = HashMap::default(); + let mut map2: HashMap> = HashMap::default(); + + map1.insert(1, 2); + map1.insert(3, 4); + + map2.insert(3, 4); + map2.insert(1, 2); + + assert(map1 == map2); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L285-L296 + diff --git a/docs/versioned_docs/version-v0.25.0/noir/standard_library/containers/index.md b/docs/versioned_docs/version-v0.25.0/noir/standard_library/containers/index.md new file mode 100644 index 00000000000..ea84c6d5c21 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/noir/standard_library/containers/index.md @@ -0,0 +1,5 @@ +--- +title: Containers +description: Container types provided by Noir's standard library for storing and retrieving data +keywords: [containers, data types, vec, hashmap] +--- diff --git a/docs/versioned_docs/version-v0.25.0/noir/standard_library/containers/vec.mdx b/docs/versioned_docs/version-v0.25.0/noir/standard_library/containers/vec.mdx new file mode 100644 index 00000000000..1954f05bc76 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/noir/standard_library/containers/vec.mdx @@ -0,0 +1,151 @@ +--- +title: Vectors +description: Delve into the Vec data type in Noir. Learn about its methods, practical examples, and best practices for using Vectors in your Noir code. +keywords: [noir, vector type, methods, examples, dynamic arrays] +sidebar_position: 6 +--- + +import Experimental from '@site/src/components/Notes/_experimental.mdx'; + + + +A vector is a collection type similar to Rust's `Vec` type. In Noir, it is a convenient way to use slices as mutable arrays. + +Example: + +```rust +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 +``` + +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 +``` + +Example: + +```rust +let arr: [Field] = [1, 2, 3]; +let vector_from_slice = Vec::from_slice(arr); +assert(vector_from_slice.len() == 3); +``` + +### len + +Returns the number of elements in the vector. + +```rust +pub fn len(self) -> Field +``` + +Example: + +```rust +let empty_vector: Vec = Vec::new(); +assert(empty_vector.len() == 0); +``` + +### 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 +``` + +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) +``` + +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 +``` + +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) +``` + +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 +``` + +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); +``` diff --git a/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/_category_.json b/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/_category_.json new file mode 100644 index 00000000000..5d694210bbf --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 0, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/ec_primitives.md b/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/ec_primitives.md new file mode 100644 index 00000000000..d2b42d67b7c --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/ec_primitives.md @@ -0,0 +1,102 @@ +--- +title: Elliptic Curve Primitives +keywords: [cryptographic primitives, Noir project] +sidebar_position: 4 +--- + +Data structures and methods on them that allow you to carry out computations involving elliptic +curves over the (mathematical) field corresponding to `Field`. For the field currently at our +disposal, applications would involve a curve embedded in BN254, e.g. the +[Baby Jubjub curve](https://eips.ethereum.org/EIPS/eip-2494). + +## Data structures + +### Elliptic curve configurations + +(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Curve`), i.e. the specific elliptic +curve you want to use, which would be specified using any one of the methods +`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::new` which take the coefficients in the +defining equation together with a generator point as parameters. You can find more detail in the +comments in +[`noir_stdlib/src/ec.nr`](https://github.com/noir-lang/noir/blob/master/noir_stdlib/src/ec.nr), but +the gist of it is that the elliptic curves of interest are usually expressed in one of the standard +forms implemented here (Twisted Edwards, Montgomery and Short Weierstraß), and in addition to that, +you could choose to use `affine` coordinates (Cartesian coordinates - the usual (x,y) - possibly +together with a point at infinity) or `curvegroup` coordinates (some form of projective coordinates +requiring more coordinates but allowing for more efficient implementations of elliptic curve +operations). Conversions between all of these forms are provided, and under the hood these +conversions are done whenever an operation is more efficient in a different representation (or a +mixed coordinate representation is employed). + +### Points + +(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Point`), i.e. points lying on the +elliptic curve. For a curve configuration `c` and a point `p`, it may be checked that `p` +does indeed lie on `c` by calling `c.contains(p1)`. + +## Methods + +(given a choice of curve representation, e.g. use `std::ec::tecurve::affine::Curve` and use +`std::ec::tecurve::affine::Point`) + +- The **zero element** is given by `Point::zero()`, and we can verify whether a point `p: Point` is + zero by calling `p.is_zero()`. +- **Equality**: Points `p1: Point` and `p2: Point` may be checked for equality by calling + `p1.eq(p2)`. +- **Addition**: For `c: Curve` and points `p1: Point` and `p2: Point` on the curve, adding these two + points is accomplished by calling `c.add(p1,p2)`. +- **Negation**: For a point `p: Point`, `p.negate()` is its negation. +- **Subtraction**: For `c` and `p1`, `p2` as above, subtracting `p2` from `p1` is accomplished by + calling `c.subtract(p1,p2)`. +- **Scalar multiplication**: For `c` as above, `p: Point` a point on the curve and `n: Field`, + scalar multiplication is given by `c.mul(n,p)`. If instead `n :: [u1; N]`, i.e. `n` is a bit + array, the `bit_mul` method may be used instead: `c.bit_mul(n,p)` +- **Multi-scalar multiplication**: For `c` as above and arrays `n: [Field; N]` and `p: [Point; N]`, + multi-scalar multiplication is given by `c.msm(n,p)`. +- **Coordinate representation conversions**: The `into_group` method converts a point or curve + configuration in the affine representation to one in the CurveGroup representation, and + `into_affine` goes in the other direction. +- **Curve representation conversions**: `tecurve` and `montcurve` curves and points are equivalent + and may be converted between one another by calling `into_montcurve` or `into_tecurve` on their + configurations or points. `swcurve` is more general and a curve c of one of the other two types + may be converted to this representation by calling `c.into_swcurve()`, whereas a point `p` lying + on the curve given by `c` may be mapped to its corresponding `swcurve` point by calling + `c.map_into_swcurve(p)`. +- **Map-to-curve methods**: The Elligator 2 method of mapping a field element `n: Field` into a + `tecurve` or `montcurve` with configuration `c` may be called as `c.elligator2_map(n)`. For all of + the curve configurations, the SWU map-to-curve method may be called as `c.swu_map(z,n)`, where + `z: Field` depends on `Field` and `c` and must be chosen by the user (the conditions it needs to + satisfy are specified in the comments + [here](https://github.com/noir-lang/noir/blob/master/noir_stdlib/src/ec.nr)). + +## Examples + +The +[ec_baby_jubjub test](https://github.com/noir-lang/noir/blob/master/test_programs/compile_success_empty/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.25.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx b/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx new file mode 100644 index 00000000000..4bf09cef178 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx @@ -0,0 +1,60 @@ +--- +title: ECDSA Signature Verification +description: Learn about the cryptographic primitives regarding ECDSA over the secp256k1 and secp256r1 curves +keywords: [cryptographic primitives, Noir project, ecdsa, secp256k1, secp256r1, signatures] +sidebar_position: 3 +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +Noir supports ECDSA signatures verification over the secp256k1 and secp256r1 curves. + +## ecdsa_secp256k1::verify_signature + +Verifier for ECDSA Secp256k1 signatures + +```rust title="ecdsa_secp256k1" showLineNumbers +pub fn verify_signature( + public_key_x: [u8; 32], + public_key_y: [u8; 32], + signature: [u8; 64], + message_hash: [u8; N] +) -> bool +``` +> Source code: noir_stdlib/src/ecdsa_secp256k1.nr#L2-L9 + + +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 title="ecdsa_secp256r1" showLineNumbers +pub fn verify_signature( + public_key_x: [u8; 32], + public_key_y: [u8; 32], + signature: [u8; 64], + message_hash: [u8; N] +) -> bool +``` +> Source code: noir_stdlib/src/ecdsa_secp256r1.nr#L2-L9 + + +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.25.0/noir/standard_library/cryptographic_primitives/eddsa.mdx b/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/eddsa.mdx new file mode 100644 index 00000000000..c2c0624dfad --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/eddsa.mdx @@ -0,0 +1,37 @@ +--- +title: EdDSA Verification +description: Learn about the cryptographic primitives regarding EdDSA +keywords: [cryptographic primitives, Noir project, eddsa, signatures] +sidebar_position: 5 +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +## eddsa::eddsa_poseidon_verify + +Verifier for EdDSA signatures + +```rust +fn eddsa_poseidon_verify(public_key_x : Field, public_key_y : Field, signature_s: Field, signature_r8_x: Field, signature_r8_y: Field, message: Field) -> bool +``` + +It is also possible to specify the hash algorithm used for the signature by using the `eddsa_verify_with_hasher` function with a parameter implementing the Hasher trait. For instance, if you want to use Poseidon2 instead, you can do the following: +```rust +use dep::std::hash::poseidon2::Poseidon2Hasher; + +let mut hasher = Poseidon2Hasher::default(); +eddsa_verify_with_hasher(pub_key_a.x, pub_key_a.y, s_a, r8_a.x, r8_a.y, msg, &mut hasher); +``` + + + +## eddsa::eddsa_to_pub + +Private to public key conversion. + +Returns `(pub_key_x, pub_key_y)` + +```rust +fn eddsa_to_pub(secret : Field) -> (Field, Field) +``` + diff --git a/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/hashes.mdx b/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/hashes.mdx new file mode 100644 index 00000000000..119d8ccc70e --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/hashes.mdx @@ -0,0 +1,251 @@ +--- +title: Hash methods +description: + Learn about the cryptographic primitives ready to use for any Noir project, including sha256, + blake2s, pedersen, mimc_bn254 and mimc +keywords: + [cryptographic primitives, Noir project, sha256, blake2s, pedersen, mimc_bn254, mimc, hash] +sidebar_position: 0 +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +## sha256 + +Given an array of bytes, returns the resulting sha256 hash. + +```rust title="sha256" showLineNumbers +pub fn sha256(input: [u8; N]) -> [u8; 32] +``` +> Source code: noir_stdlib/src/hash.nr#L9-L11 + + +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 title="blake2s" showLineNumbers +pub fn blake2s(input: [u8; N]) -> [u8; 32] +``` +> Source code: noir_stdlib/src/hash.nr#L15-L17 + + +example: + +```rust +fn main() { + let x = [163, 117, 178, 149]; // some random bytes + let hash = std::hash::blake2s(x); +} +``` + + + +## blake3 + +Given an array of bytes, returns an array with the Blake3 hash + +```rust title="blake3" showLineNumbers +pub fn blake3(input: [u8; N]) -> [u8; 32] +``` +> Source code: noir_stdlib/src/hash.nr#L21-L23 + + +example: + +```rust +fn main() { + let x = [163, 117, 178, 149]; // some random bytes + let hash = std::hash::blake3(x); +} +``` + + + +## pedersen_hash + +Given an array of Fields, returns the Pedersen hash. + +```rust title="pedersen_hash" showLineNumbers +pub fn pedersen_hash(input: [Field; N]) -> Field +``` +> Source code: noir_stdlib/src/hash.nr#L46-L48 + + +example: + +```rust title="pedersen-hash" showLineNumbers +use dep::std; + +fn main(x: Field, y: Field, expected_hash: Field) { + let hash = std::hash::pedersen_hash([x, y]); + assert_eq(hash, expected_hash); +} +``` +> Source code: test_programs/execution_success/pedersen_hash/src/main.nr#L1-L8 + + + + + +## pedersen_commitment + +Given an array of Fields, returns the Pedersen commitment. + +```rust title="pedersen_commitment" showLineNumbers +struct PedersenPoint { + x : Field, + y : Field, +} + +pub fn pedersen_commitment(input: [Field; N]) -> PedersenPoint +``` +> Source code: noir_stdlib/src/hash.nr#L26-L33 + + +example: + +```rust title="pedersen-commitment" showLineNumbers +use dep::std; + +fn main(x: Field, y: Field, expected_commitment: std::hash::PedersenPoint) { + let commitment = std::hash::pedersen_commitment([x, y]); + assert_eq(commitment.x, expected_commitment.x); + assert_eq(commitment.y, expected_commitment.y); +} +``` +> Source code: test_programs/execution_success/pedersen_commitment/src/main.nr#L1-L9 + + + + +## 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 title="keccak256" showLineNumbers +pub fn keccak256(input: [u8; N], message_size: u32) -> [u8; 32] +``` +> Source code: noir_stdlib/src/hash.nr#L71-L73 + + +example: + +```rust title="keccak256" showLineNumbers +use dep::std; + +fn main(x: Field, result: [u8; 32]) { + // We use the `as` keyword here to denote the fact that we want to take just the first byte from the x Field + // The padding is taken care of by the program + let digest = std::hash::keccak256([x as u8], 1); + assert(digest == result); + + //#1399: variable message 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); + + 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); + + assert(hash_a != hash_c); +} +``` +> Source code: test_programs/execution_success/keccak256/src/main.nr#L1-L22 + + + + +## 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 title="poseidon" showLineNumbers +use dep::std::hash::poseidon; +use dep::std::hash::poseidon2; + +fn main(x1: [Field; 2], y1: pub Field, x2: [Field; 4], y2: pub Field, x3: [Field; 4], y3: Field) { + let hash1 = poseidon::bn254::hash_2(x1); + assert(hash1 == y1); + + let hash2 = poseidon::bn254::hash_4(x2); + assert(hash2 == y2); + + let hash3 = poseidon2::Poseidon2::hash(x3, x3.len()); + assert(hash3 == y3); +} +``` +> Source code: test_programs/execution_success/poseidon_bn254_hash/src/main.nr#L1-L15 + + +## poseidon 2 + +Given an array of Fields, returns a new Field with the Poseidon2 Hash. Contrary to the Poseidon +function, there is only one hash and you can specify a message_size to hash only the first +`message_size` bytes of the input, + +```rust +// example for hashing the first three elements of the input +Poseidon2::hash(input, 3); +``` + +The above example for Poseidon also includes Poseidon2. + +## 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.25.0/noir/standard_library/cryptographic_primitives/index.md b/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/index.md new file mode 100644 index 00000000000..650f30165d5 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/index.md @@ -0,0 +1,14 @@ +--- +title: Cryptographic Primitives +description: + Learn about the cryptographic primitives ready to use for any Noir project +keywords: + [ + cryptographic primitives, + Noir project, + ] +--- + +The Noir team is progressively adding new cryptographic primitives to the standard library. Reach out for news or if you would be interested in adding more of these calculations in Noir. + +Some methods are available thanks to the Aztec backend, not being performed using Noir. When using other backends, these methods may or may not be supplied. diff --git a/docs/docs/noir/standard_library/cryptographic_primitives/scalar.mdx b/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/scalar.mdx similarity index 64% rename from docs/docs/noir/standard_library/cryptographic_primitives/scalar.mdx rename to docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/scalar.mdx index c2946b2b73b..df411ca5443 100644 --- a/docs/docs/noir/standard_library/cryptographic_primitives/scalar.mdx +++ b/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/scalar.mdx @@ -12,7 +12,14 @@ import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; 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. -#include_code fixed_base_embedded_curve noir_stdlib/src/scalar_mul.nr rust +```rust title="fixed_base_embedded_curve" showLineNumbers +pub fn fixed_base_embedded_curve( + low: Field, + high: Field +) -> [Field; 2] +``` +> Source code: noir_stdlib/src/scalar_mul.nr#L27-L32 + example diff --git a/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/schnorr.mdx b/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/schnorr.mdx new file mode 100644 index 00000000000..ae12e6c12dc --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/schnorr.mdx @@ -0,0 +1,45 @@ +--- +title: Schnorr Signatures +description: Learn how you can verify Schnorr signatures using Noir +keywords: [cryptographic primitives, Noir project, schnorr, signatures] +sidebar_position: 2 +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +## schnorr::verify_signature + +Verifier for Schnorr signatures over the embedded curve (for BN254 it is Grumpkin). + +```rust title="schnorr_verify" showLineNumbers +pub fn verify_signature( + public_key_x: Field, + public_key_y: Field, + signature: [u8; 64], + message: [u8; N] +) -> bool +``` +> Source code: noir_stdlib/src/schnorr.nr#L2-L9 + + +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.25.0/noir/standard_library/logging.md b/docs/versioned_docs/version-v0.25.0/noir/standard_library/logging.md new file mode 100644 index 00000000000..db75ef9f86f --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/noir/standard_library/logging.md @@ -0,0 +1,78 @@ +--- +title: Logging +description: + Learn how to use the println statement for debugging in Noir with this tutorial. Understand the + basics of logging in Noir and how to implement it in your code. +keywords: + [ + noir logging, + println statement, + print statement, + debugging in noir, + noir std library, + logging tutorial, + basic logging in noir, + noir logging implementation, + noir debugging techniques, + rust, + ] +--- + +The standard library provides two familiar statements you can use: `println` and `print`. Despite being a limited implementation of rust's `println!` and `print!` macros, these constructs can be useful for debugging. + +You can print the output of both statements in your Noir code by using the `nargo execute` command or the `--show-output` flag when using `nargo test` (provided there are print statements in your tests). + +It is recommended to use `nargo execute` if you want to debug failing constraints with `println` or `print` statements. This is due to every input in a test being a constant rather than a witness, so we issue an error during compilation while we only print during execution (which comes after compilation). Neither `println`, nor `print` are callable for failed constraints caught at compile time. + +Both `print` and `println` are generic functions which can work on integers, fields, strings, and even structs or expressions. Note however, that slices are currently unsupported. For example: + +```rust +struct Person { + age: Field, + height: Field, +} + +fn main(age: Field, height: Field) { + let person = Person { + age: age, + height: height, + }; + println(person); + println(age + height); + println("Hello world!"); +} +``` + +You can print different types in the same statement (including strings) with a type called `fmtstr`. It can be specified in the same way as a normal string, just prepended with an "f" character: + +```rust + let fmt_str = f"i: {i}, j: {j}"; + println(fmt_str); + + let s = myStruct { y: x, x: y }; + println(s); + + println(f"i: {i}, s: {s}"); + + println(x); + println([x, y]); + + let foo = fooStruct { my_struct: s, foo: 15 }; + println(f"s: {s}, foo: {foo}"); + + println(15); // prints 0x0f, implicit Field + println(-1 as u8); // prints 255 + println(-1 as i8); // prints -1 +``` + +Examples shown above are interchangeable between the two `print` statements: + +```rust +let person = Person { age : age, height : height }; + +println(person); +print(person); + +println("Hello world!"); // Prints with a newline at the end of the input +print("Hello world!"); // Prints the input and keeps cursor on the same line +``` diff --git a/docs/versioned_docs/version-v0.25.0/noir/standard_library/merkle_trees.md b/docs/versioned_docs/version-v0.25.0/noir/standard_library/merkle_trees.md new file mode 100644 index 00000000000..fa488677884 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/noir/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/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); + 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.25.0/noir/standard_library/options.md b/docs/versioned_docs/version-v0.25.0/noir/standard_library/options.md new file mode 100644 index 00000000000..a1bd4e1de5f --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/noir/standard_library/options.md @@ -0,0 +1,101 @@ +--- +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), +} +``` + +The `Option` type, already imported into your Noir program, can be used directly: + +```rust +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. + +### expect + +Asserts `self.is_some()` with a provided custom message and returns the contained `Some` value. The custom message is expected to be a format string. + +### 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.25.0/noir/standard_library/recursion.md b/docs/versioned_docs/version-v0.25.0/noir/standard_library/recursion.md new file mode 100644 index 00000000000..9337499dac8 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/noir/standard_library/recursion.md @@ -0,0 +1,88 @@ +--- +title: Recursive Proofs +description: Learn about how to write recursive proofs in Noir. +keywords: [recursion, recursive proofs, verification_key, 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. + +Read [the explainer on recursion](../../explainers/explainer-recursion.md) to know more about this function and the [guide on how to use it.](../../how_to/how-to-recursion.md) + +## The `#[recursive]` Attribute + +In Noir, the `#[recursive]` attribute is used to indicate that a circuit is designed for recursive proof generation. When applied, it informs the compiler and the tooling that the circuit should be compiled in a way that makes its proofs suitable for recursive verification. This attribute eliminates the need for manual flagging of recursion at the tooling level, streamlining the proof generation process for recursive circuits. + +### Example usage with `#[recursive]` + +```rust +#[recursive] +fn main(x: Field, y: pub Field) { + assert(x == y, "x and y are not equal"); +} + +// This marks the circuit as recursion-friendly and indicates that proofs generated from this circuit +// are intended for recursive verification. +``` + +By incorporating this attribute directly in the circuit's definition, tooling like Nargo and NoirJS can automatically execute recursive-specific duties for Noir programs (e.g. recursive-friendly proof artifact generation) without additional flags or configurations. + +## Verifying Recursive Proofs + +```rust +#[foreign(verify_proof)] +fn verify_proof(_verification_key : [Field], _proof : [Field], _public_input : Field, _key_hash : Field) {} +``` + +:::info + +This is a black box function. Read [this section](./black_box_fns) to learn more about black box functions in Noir. + +::: + +## Example usage + +```rust +use dep::std; + +fn main( + verification_key : [Field; 114], + proof : [Field; 93], + public_inputs : [Field; 1], + key_hash : Field, + proof_b : [Field; 93], +) { + std::verify_proof( + verification_key.as_slice(), + proof.as_slice(), + public_inputs.as_slice(), + key_hash + ); + + std::verify_proof( + verification_key.as_slice(), + proof_b.as_slice(), + public_inputs.as_slice(), + key_hash + ); +} +``` + +You can see a full example of recursive proofs in [this example recursion demo repo](https://github.com/noir-lang/noir-examples/tree/master/recursion). + +## 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. + +### `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. diff --git a/docs/versioned_docs/version-v0.25.0/noir/standard_library/traits.md b/docs/versioned_docs/version-v0.25.0/noir/standard_library/traits.md new file mode 100644 index 00000000000..ba9fa2ee841 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/noir/standard_library/traits.md @@ -0,0 +1,399 @@ +--- +title: Traits +description: Noir's stdlib provides a few commonly used traits. +keywords: [traits, trait, interface, protocol, default, add, eq] +--- + +## `std::default` + +### `std::default::Default` + +```rust title="default-trait" showLineNumbers +trait Default { + fn default() -> Self; +} +``` +> Source code: noir_stdlib/src/default.nr#L1-L5 + + +Constructs a default value of a type. + +Implementations: +```rust +impl Default for Field { .. } + +impl Default for i8 { .. } +impl Default for i16 { .. } +impl Default for i32 { .. } +impl Default for i64 { .. } + +impl Default for u8 { .. } +impl Default for u16 { .. } +impl Default for u32 { .. } +impl Default for u64 { .. } + +impl Default for () { .. } +impl Default for bool { .. } + +impl Default for [T; N] + where T: Default { .. } + +impl Default for (A, B) + where A: Default, B: Default { .. } + +impl Default for (A, B, C) + where A: Default, B: Default, C: Default { .. } + +impl Default for (A, B, C, D) + where A: Default, B: Default, C: Default, D: Default { .. } + +impl Default for (A, B, C, D, E) + where A: Default, B: Default, C: Default, D: Default, E: Default { .. } +``` + +For primitive integer types, the return value of `default` is `0`. Container +types such as arrays are filled with default values of their element type. + + +## `std::convert` + +### `std::convert::From` + +```rust title="from-trait" showLineNumbers +trait From { + fn from(input: T) -> Self; +} +``` +> Source code: noir_stdlib/src/convert.nr#L1-L5 + + +The `From` trait defines how to convert from a given type `T` to the type on which the trait is implemented. + +The Noir standard library provides a number of implementations of `From` between primitive types. +```rust title="from-impls" showLineNumbers +// Unsigned integers + +impl From for u32 { fn from(value: u8) -> u32 { value as u32 } } + +impl From for u64 { fn from(value: u8) -> u64 { value as u64 } } +impl From for u64 { fn from(value: u32) -> u64 { value as u64 } } + +impl From for Field { fn from(value: u8) -> Field { value as Field } } +impl From for Field { fn from(value: u32) -> Field { value as Field } } +impl From for Field { fn from(value: u64) -> Field { value as Field } } + +// Signed integers + +impl From for i32 { fn from(value: i8) -> i32 { value as i32 } } + +impl From for i64 { fn from(value: i8) -> i64 { value as i64 } } +impl From for i64 { fn from(value: i32) -> i64 { value as i64 } } + +// Booleans +impl From for u8 { fn from(value: bool) -> u8 { value as u8 } } +impl From for u32 { fn from(value: bool) -> u32 { value as u32 } } +impl From for u64 { fn from(value: bool) -> u64 { value as u64 } } +impl From for i8 { fn from(value: bool) -> i8 { value as i8 } } +impl From for i32 { fn from(value: bool) -> i32 { value as i32 } } +impl From for i64 { fn from(value: bool) -> i64 { value as i64 } } +impl From for Field { fn from(value: bool) -> Field { value as Field } } +``` +> Source code: noir_stdlib/src/convert.nr#L25-L52 + + +#### When to implement `From` + +As a general rule of thumb, `From` may be implemented in the [situations where it would be suitable in Rust](https://doc.rust-lang.org/std/convert/trait.From.html#when-to-implement-from): + +- The conversion is *infallible*: Noir does not provide an equivalent to Rust's `TryFrom`, if the conversion can fail then provide a named method instead. +- The conversion is *lossless*: semantically, it should not lose or discard information. For example, `u32: From` can losslessly convert any `u16` into a valid `u32` such that the original `u16` can be recovered. On the other hand, `u16: From` should not be implemented as `2**16` is a `u32` which cannot be losslessly converted into a `u16`. +- The conversion is *value-preserving*: the conceptual kind and meaning of the resulting value is the same, even though the Noir type and technical representation might be different. While it's possible to infallibly and losslessly convert a `u8` into a `str<2>` hex representation, `4u8` and `"04"` are too different for `str<2>: From` to be implemented. +- The conversion is *obvious*: it's the only reasonable conversion between the two types. If there's ambiguity on how to convert between them such that the same input could potentially map to two different values then a named method should be used. For instance rather than implementing `U128: From<[u8; 16]>`, the methods `U128::from_le_bytes` and `U128::from_be_bytes` are used as otherwise the endianness of the array would be ambiguous, resulting in two potential values of `U128` from the same byte array. + +One additional recommendation specific to Noir is: +- The conversion is *efficient*: it's relatively cheap to convert between the two types. Due to being a ZK DSL, it's more important to avoid unnecessary computation compared to Rust. If the implementation of `From` would encourage users to perform unnecessary conversion, resulting in additional proving time, then it may be preferable to expose functionality such that this conversion may be avoided. + +### `std::convert::Into` + +The `Into` trait is defined as the reciprocal of `From`. It should be easy to convince yourself that if we can convert to type `A` from type `B`, then it's possible to convert type `B` into type `A`. + +For this reason, implementing `From` on a type will automatically generate a matching `Into` implementation. One should always prefer implementing `From` over `Into` as implementing `Into` will not generate a matching `From` implementation. + +```rust title="into-trait" showLineNumbers +trait Into { + fn into(input: Self) -> T; +} + +impl Into for U where T: From { + fn into(input: U) -> T { + T::from(input) + } +} +``` +> Source code: noir_stdlib/src/convert.nr#L13-L23 + + +`Into` is most useful when passing function arguments where the types don't quite match up with what the function expects. In this case, the compiler has enough type information to perform the necessary conversion by just appending `.into()` onto the arguments in question. + + +## `std::cmp` + +### `std::cmp::Eq` + +```rust title="eq-trait" showLineNumbers +trait Eq { + fn eq(self, other: Self) -> bool; +} +``` +> Source code: noir_stdlib/src/cmp.nr#L1-L5 + + +Returns `true` if `self` is equal to `other`. Implementing this trait on a type +allows the type to be used with `==` and `!=`. + +Implementations: +```rust +impl Eq for Field { .. } + +impl Eq for i8 { .. } +impl Eq for i16 { .. } +impl Eq for i32 { .. } +impl Eq for i64 { .. } + +impl Eq for u8 { .. } +impl Eq for u16 { .. } +impl Eq for u32 { .. } +impl Eq for u64 { .. } + +impl Eq for () { .. } +impl Eq for bool { .. } + +impl Eq for [T; N] + where T: Eq { .. } + +impl Eq for (A, B) + where A: Eq, B: Eq { .. } + +impl Eq for (A, B, C) + where A: Eq, B: Eq, C: Eq { .. } + +impl Eq for (A, B, C, D) + where A: Eq, B: Eq, C: Eq, D: Eq { .. } + +impl Eq for (A, B, C, D, E) + where A: Eq, B: Eq, C: Eq, D: Eq, E: Eq { .. } +``` + +### `std::cmp::Ord` + +```rust title="ord-trait" showLineNumbers +trait Ord { + fn cmp(self, other: Self) -> Ordering; +} +``` +> Source code: noir_stdlib/src/cmp.nr#L92-L96 + + +`a.cmp(b)` compares two values returning `Ordering::less()` if `a < b`, +`Ordering::equal()` if `a == b`, or `Ordering::greater()` if `a > b`. +Implementing this trait on a type allows `<`, `<=`, `>`, and `>=` to be +used on values of the type. + +Implementations: + +```rust +impl Ord for u8 { .. } +impl Ord for u16 { .. } +impl Ord for u32 { .. } +impl Ord for u64 { .. } + +impl Ord for i8 { .. } +impl Ord for i16 { .. } +impl Ord for i32 { .. } + +impl Ord for i64 { .. } + +impl Ord for () { .. } +impl Ord for bool { .. } + +impl Ord for [T; N] + where T: Ord { .. } + +impl Ord for (A, B) + where A: Ord, B: Ord { .. } + +impl Ord for (A, B, C) + where A: Ord, B: Ord, C: Ord { .. } + +impl Ord for (A, B, C, D) + where A: Ord, B: Ord, C: Ord, D: Ord { .. } + +impl Ord for (A, B, C, D, E) + where A: Ord, B: Ord, C: Ord, D: Ord, E: Ord { .. } +``` + +## `std::ops` + +### `std::ops::Add`, `std::ops::Sub`, `std::ops::Mul`, and `std::ops::Div` + +These traits abstract over addition, subtraction, multiplication, and division respectively. +Implementing these traits for a given type will also allow that type to be used with the corresponding operator +for that trait (`+` for Add, etc) in addition to the normal method names. + +```rust title="add-trait" showLineNumbers +trait Add { + fn add(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L1-L5 + +```rust title="sub-trait" showLineNumbers +trait Sub { + fn sub(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L17-L21 + +```rust title="mul-trait" showLineNumbers +trait Mul { + fn mul(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L33-L37 + +```rust title="div-trait" showLineNumbers +trait Div { + fn div(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L49-L53 + + +The implementations block below is given for the `Add` trait, but the same types that implement +`Add` also implement `Sub`, `Mul`, and `Div`. + +Implementations: +```rust +impl Add for Field { .. } + +impl Add for i8 { .. } +impl Add for i16 { .. } +impl Add for i32 { .. } +impl Add for i64 { .. } + +impl Add for u8 { .. } +impl Add for u16 { .. } +impl Add for u32 { .. } +impl Add for u64 { .. } +``` + +### `std::ops::Rem` + +```rust title="rem-trait" showLineNumbers +trait Rem{ + fn rem(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L65-L69 + + +`Rem::rem(a, b)` is the remainder function returning the result of what is +left after dividing `a` and `b`. Implementing `Rem` allows the `%` operator +to be used with the implementation type. + +Unlike other numeric traits, `Rem` is not implemented for `Field`. + +Implementations: +```rust +impl Rem for u8 { fn rem(self, other: u8) -> u8 { self % other } } +impl Rem for u16 { fn rem(self, other: u16) -> u16 { self % other } } +impl Rem for u32 { fn rem(self, other: u32) -> u32 { self % other } } +impl Rem for u64 { fn rem(self, other: u64) -> u64 { self % other } } + +impl Rem for i8 { fn rem(self, other: i8) -> i8 { self % other } } +impl Rem for i16 { fn rem(self, other: i16) -> i16 { self % other } } +impl Rem for i32 { fn rem(self, other: i32) -> i32 { self % other } } +impl Rem for i64 { fn rem(self, other: i64) -> i64 { self % other } } +``` + +### `std::ops::{ BitOr, BitAnd, BitXor }` + +```rust title="bitor-trait" showLineNumbers +trait BitOr { + fn bitor(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L79-L83 + +```rust title="bitand-trait" showLineNumbers +trait BitAnd { + fn bitand(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L95-L99 + +```rust title="bitxor-trait" showLineNumbers +trait BitXor { + fn bitxor(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L111-L115 + + +Traits for the bitwise operations `|`, `&`, and `^`. + +Implementing `BitOr`, `BitAnd` or `BitXor` for a type allows the `|`, `&`, or `^` operator respectively +to be used with the type. + +The implementations block below is given for the `BitOr` trait, but the same types that implement +`BitOr` also implement `BitAnd` and `BitXor`. + +Implementations: +```rust +impl BitOr for bool { fn bitor(self, other: bool) -> bool { self | other } } + +impl BitOr for u8 { fn bitor(self, other: u8) -> u8 { self | other } } +impl BitOr for u16 { fn bitor(self, other: u16) -> u16 { self | other } } +impl BitOr for u32 { fn bitor(self, other: u32) -> u32 { self | other } } +impl BitOr for u64 { fn bitor(self, other: u64) -> u64 { self | other } } + +impl BitOr for i8 { fn bitor(self, other: i8) -> i8 { self | other } } +impl BitOr for i16 { fn bitor(self, other: i16) -> i16 { self | other } } +impl BitOr for i32 { fn bitor(self, other: i32) -> i32 { self | other } } +impl BitOr for i64 { fn bitor(self, other: i64) -> i64 { self | other } } +``` + +### `std::ops::{ Shl, Shr }` + +```rust title="shl-trait" showLineNumbers +trait Shl { + fn shl(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L127-L131 + +```rust title="shr-trait" showLineNumbers +trait Shr { + fn shr(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L142-L146 + + +Traits for a bit shift left and bit shift right. + +Implementing `Shl` for a type allows the left shift operator (`<<`) to be used with the implementation type. +Similarly, implementing `Shr` allows the right shift operator (`>>`) to be used with the type. + +Note that bit shifting is not currently implemented for signed types. + +The implementations block below is given for the `Shl` trait, but the same types that implement +`Shl` also implement `Shr`. + +Implementations: +```rust +impl Shl for u8 { fn shl(self, other: u8) -> u8 { self << other } } +impl Shl for u16 { fn shl(self, other: u16) -> u16 { self << other } } +impl Shl for u32 { fn shl(self, other: u32) -> u32 { self << other } } +impl Shl for u64 { fn shl(self, other: u64) -> u64 { self << other } } +``` diff --git a/docs/versioned_docs/version-v0.25.0/noir/standard_library/zeroed.md b/docs/versioned_docs/version-v0.25.0/noir/standard_library/zeroed.md new file mode 100644 index 00000000000..97dab02dac2 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/noir/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-v0.25.0/reference/NoirJS/backend_barretenberg/.nojekyll b/docs/versioned_docs/version-v0.25.0/reference/NoirJS/backend_barretenberg/.nojekyll new file mode 100644 index 00000000000..e2ac6616add --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/reference/NoirJS/backend_barretenberg/.nojekyll @@ -0,0 +1 @@ +TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.25.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md b/docs/versioned_docs/version-v0.25.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md new file mode 100644 index 00000000000..d60940df3ea --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md @@ -0,0 +1,127 @@ +# 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 + +*** + +### generateProof() + +```ts +generateProof(compressedWitness): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `compressedWitness` | `Uint8Array` | + +#### Returns + +`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> + +#### Description + +Generates a proof + +*** + +### generateRecursiveProofArtifacts() + +```ts +generateRecursiveProofArtifacts(proofData, numOfPublicInputs): Promise +``` + +Generates artifacts that will be passed to a circuit that will verify this proof. + +Instead of passing the proof and verification key as a byte array, we pass them +as fields which makes it cheaper to verify in a circuit. + +The proof that is passed here will have been created using a circuit +that has the #[recursive] attribute on its `main` method. + +The number of public inputs denotes how many public inputs are in the inner proof. + +#### Parameters + +| Parameter | Type | Default value | +| :------ | :------ | :------ | +| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | `undefined` | +| `numOfPublicInputs` | `number` | `0` | + +#### Returns + +`Promise`\<`object`\> + +#### Example + +```typescript +const artifacts = await backend.generateRecursiveProofArtifacts(proof, numOfPublicInputs); +``` + +*** + +### verifyProof() + +```ts +verifyProof(proofData): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | + +#### Returns + +`Promise`\<`boolean`\> + +#### Description + +Verifies 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.25.0/reference/NoirJS/backend_barretenberg/index.md b/docs/versioned_docs/version-v0.25.0/reference/NoirJS/backend_barretenberg/index.md new file mode 100644 index 00000000000..e32501acb71 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/reference/NoirJS/backend_barretenberg/index.md @@ -0,0 +1,46 @@ +# backend_barretenberg + +## Exports + +### Classes + +| Class | Description | +| :------ | :------ | +| [BarretenbergBackend](classes/BarretenbergBackend.md) | - | + +### Interfaces + +| Interface | Description | +| :------ | :------ | +| [Backend](interfaces/Backend.md) | - | + +### Type Aliases + +| Type alias | Description | +| :------ | :------ | +| [BackendOptions](type-aliases/BackendOptions.md) | - | +| [CompiledCircuit](type-aliases/CompiledCircuit.md) | - | +| [ProofData](type-aliases/ProofData.md) | - | + +## Functions + +### publicInputsToWitnessMap() + +```ts +publicInputsToWitnessMap(publicInputs, abi): WitnessMap +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `publicInputs` | `string`[] | +| `abi` | `Abi` | + +#### Returns + +`WitnessMap` + +*** + +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.25.0/reference/NoirJS/backend_barretenberg/interfaces/Backend.md b/docs/versioned_docs/version-v0.25.0/reference/NoirJS/backend_barretenberg/interfaces/Backend.md new file mode 100644 index 00000000000..3eb9645c8d2 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/reference/NoirJS/backend_barretenberg/interfaces/Backend.md @@ -0,0 +1,132 @@ +# Backend + +## Methods + +### destroy() + +```ts +destroy(): Promise +``` + +#### Returns + +`Promise`\<`void`\> + +#### Description + +Destroys the backend + +*** + +### generateFinalProof() + +```ts +generateFinalProof(decompressedWitness): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `decompressedWitness` | `Uint8Array` | + +#### Returns + +`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> + +#### Description + +Generates a final proof (not meant to be verified in another circuit) + +*** + +### generateIntermediateProof() + +```ts +generateIntermediateProof(decompressedWitness): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `decompressedWitness` | `Uint8Array` | + +#### Returns + +`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> + +#### Description + +Generates an intermediate proof (meant to be verified in another circuit) + +*** + +### generateIntermediateProofArtifacts() + +```ts +generateIntermediateProofArtifacts(proofData, numOfPublicInputs): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | +| `numOfPublicInputs` | `number` | + +#### Returns + +`Promise`\<`object`\> + +#### Description + +Retrieves the artifacts from a proof in the Field format + +*** + +### verifyFinalProof() + +```ts +verifyFinalProof(proofData): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | + +#### Returns + +`Promise`\<`boolean`\> + +#### Description + +Verifies a final proof + +*** + +### verifyIntermediateProof() + +```ts +verifyIntermediateProof(proofData): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | + +#### Returns + +`Promise`\<`boolean`\> + +#### Description + +Verifies an intermediate proof + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.25.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md b/docs/versioned_docs/version-v0.25.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md new file mode 100644 index 00000000000..b49a479f4f4 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md @@ -0,0 +1,21 @@ +# 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 | +| :------ | :------ | :------ | +| `memory` | `object` | - | +| `memory.maximum` | `number` | - | +| `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.25.0/reference/NoirJS/backend_barretenberg/type-aliases/CompiledCircuit.md b/docs/versioned_docs/version-v0.25.0/reference/NoirJS/backend_barretenberg/type-aliases/CompiledCircuit.md new file mode 100644 index 00000000000..34e0dd04205 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/reference/NoirJS/backend_barretenberg/type-aliases/CompiledCircuit.md @@ -0,0 +1,20 @@ +# CompiledCircuit + +```ts +type CompiledCircuit: object; +``` + +## Description + +The representation of a compiled circuit + +## Type declaration + +| Member | Type | Description | +| :------ | :------ | :------ | +| `abi` | `Abi` | **Description**

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

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

An byte array representing the proof | +| `publicInputs` | `string`[] | **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.25.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs b/docs/versioned_docs/version-v0.25.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs new file mode 100644 index 00000000000..2aaa55bccf6 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs @@ -0,0 +1,4 @@ +// @ts-check +/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ +const typedocSidebar = { items: [{"type":"category","label":"Classes","items":[{"type":"doc","id":"reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend","label":"BarretenbergBackend"}]},{"type":"category","label":"Interfaces","items":[{"type":"doc","id":"reference/NoirJS/backend_barretenberg/interfaces/Backend","label":"Backend"}]},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions","label":"BackendOptions"},{"type":"doc","id":"reference/NoirJS/backend_barretenberg/type-aliases/CompiledCircuit","label":"CompiledCircuit"},{"type":"doc","id":"reference/NoirJS/backend_barretenberg/type-aliases/ProofData","label":"ProofData"}]}]}; +module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/.nojekyll b/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/.nojekyll new file mode 100644 index 00000000000..e2ac6616add --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/.nojekyll @@ -0,0 +1 @@ +TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/classes/Noir.md b/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/classes/Noir.md new file mode 100644 index 00000000000..421d274fff8 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/classes/Noir.md @@ -0,0 +1,132 @@ +# Noir + +## Constructors + +### new Noir(circuit, backend) + +```ts +new Noir(circuit, backend?): Noir +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `circuit` | [`CompiledCircuit`](../type-aliases/CompiledCircuit.md) | +| `backend`? | `Backend` | + +#### Returns + +[`Noir`](Noir.md) + +## Methods + +### destroy() + +```ts +destroy(): Promise +``` + +#### Returns + +`Promise`\<`void`\> + +#### Description + +Destroys the underlying backend instance. + +#### Example + +```typescript +await noir.destroy(); +``` + +*** + +### execute() + +```ts +execute(inputs, foreignCallHandler?): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `inputs` | [`InputMap`](../type-aliases/InputMap.md) | +| `foreignCallHandler`? | [`ForeignCallHandler`](../type-aliases/ForeignCallHandler.md) | + +#### Returns + +`Promise`\<`object`\> + +#### Description + +Allows to execute a circuit to get its witness and return value. + +#### Example + +```typescript +async execute(inputs) +``` + +*** + +### generateProof() + +```ts +generateProof(inputs, foreignCallHandler?): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `inputs` | [`InputMap`](../type-aliases/InputMap.md) | +| `foreignCallHandler`? | [`ForeignCallHandler`](../type-aliases/ForeignCallHandler.md) | + +#### Returns + +`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> + +#### Description + +Generates a witness and a proof given an object as input. + +#### Example + +```typescript +async generateProof(input) +``` + +*** + +### verifyProof() + +```ts +verifyProof(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 verifyProof(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.25.0/reference/NoirJS/noir_js/functions/and.md b/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/functions/and.md new file mode 100644 index 00000000000..c783283e396 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/functions/and.md @@ -0,0 +1,22 @@ +# and() + +```ts +and(lhs, rhs): string +``` + +Performs a bitwise AND operation between `lhs` and `rhs` + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `lhs` | `string` | | +| `rhs` | `string` | | + +## Returns + +`string` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/functions/blake2s256.md b/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/functions/blake2s256.md new file mode 100644 index 00000000000..7882d0da8d5 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/functions/blake2s256.md @@ -0,0 +1,21 @@ +# blake2s256() + +```ts +blake2s256(inputs): Uint8Array +``` + +Calculates the Blake2s256 hash of the input bytes + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `inputs` | `Uint8Array` | | + +## Returns + +`Uint8Array` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md b/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md new file mode 100644 index 00000000000..5e3cd53e9d3 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md @@ -0,0 +1,28 @@ +# ecdsa\_secp256k1\_verify() + +```ts +ecdsa_secp256k1_verify( + hashed_msg, + public_key_x_bytes, + public_key_y_bytes, + signature): boolean +``` + +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.25.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md b/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md new file mode 100644 index 00000000000..0b20ff68957 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md @@ -0,0 +1,28 @@ +# ecdsa\_secp256r1\_verify() + +```ts +ecdsa_secp256r1_verify( + hashed_msg, + public_key_x_bytes, + public_key_y_bytes, + signature): boolean +``` + +Verifies a ECDSA signature over the secp256r1 curve. + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `hashed_msg` | `Uint8Array` | | +| `public_key_x_bytes` | `Uint8Array` | | +| `public_key_y_bytes` | `Uint8Array` | | +| `signature` | `Uint8Array` | | + +## Returns + +`boolean` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/functions/keccak256.md b/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/functions/keccak256.md new file mode 100644 index 00000000000..d10f155ce86 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/functions/keccak256.md @@ -0,0 +1,21 @@ +# keccak256() + +```ts +keccak256(inputs): Uint8Array +``` + +Calculates the Keccak256 hash of the input bytes + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `inputs` | `Uint8Array` | | + +## Returns + +`Uint8Array` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/functions/sha256.md b/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/functions/sha256.md new file mode 100644 index 00000000000..6ba4ecac022 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/functions/sha256.md @@ -0,0 +1,21 @@ +# sha256() + +```ts +sha256(inputs): Uint8Array +``` + +Calculates the SHA256 hash of the input bytes + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `inputs` | `Uint8Array` | | + +## Returns + +`Uint8Array` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/functions/xor.md b/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/functions/xor.md new file mode 100644 index 00000000000..8d762b895d3 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/functions/xor.md @@ -0,0 +1,22 @@ +# xor() + +```ts +xor(lhs, rhs): string +``` + +Performs a bitwise XOR operation between `lhs` and `rhs` + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `lhs` | `string` | | +| `rhs` | `string` | | + +## Returns + +`string` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/index.md b/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/index.md new file mode 100644 index 00000000000..d600e21b299 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/index.md @@ -0,0 +1,37 @@ +# noir_js + +## Exports + +### Classes + +| Class | Description | +| :------ | :------ | +| [Noir](classes/Noir.md) | - | + +### Type Aliases + +| Type alias | Description | +| :------ | :------ | +| [CompiledCircuit](type-aliases/CompiledCircuit.md) | - | +| [ForeignCallHandler](type-aliases/ForeignCallHandler.md) | A callback which performs an foreign call and returns the response. | +| [ForeignCallInput](type-aliases/ForeignCallInput.md) | - | +| [ForeignCallOutput](type-aliases/ForeignCallOutput.md) | - | +| [InputMap](type-aliases/InputMap.md) | - | +| [ProofData](type-aliases/ProofData.md) | - | +| [WitnessMap](type-aliases/WitnessMap.md) | - | + +### Functions + +| Function | Description | +| :------ | :------ | +| [and](functions/and.md) | Performs a bitwise AND operation between `lhs` and `rhs` | +| [blake2s256](functions/blake2s256.md) | Calculates the Blake2s256 hash of the input bytes | +| [ecdsa\_secp256k1\_verify](functions/ecdsa_secp256k1_verify.md) | Verifies a ECDSA signature over the secp256k1 curve. | +| [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.25.0/reference/NoirJS/noir_js/type-aliases/CompiledCircuit.md b/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/type-aliases/CompiledCircuit.md new file mode 100644 index 00000000000..34e0dd04205 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/type-aliases/CompiledCircuit.md @@ -0,0 +1,20 @@ +# CompiledCircuit + +```ts +type CompiledCircuit: object; +``` + +## Description + +The representation of a compiled circuit + +## Type declaration + +| Member | Type | Description | +| :------ | :------ | :------ | +| `abi` | `Abi` | **Description**

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

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

An byte array representing the proof | +| `publicInputs` | `string`[] | **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.25.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md b/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md new file mode 100644 index 00000000000..258c46f9d0c --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md @@ -0,0 +1,9 @@ +# WitnessMap + +```ts +type WitnessMap: Map; +``` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs b/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs new file mode 100644 index 00000000000..fe2629ddc9f --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs @@ -0,0 +1,4 @@ +// @ts-check +/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ +const typedocSidebar = { items: [{"type":"category","label":"Classes","items":[{"type":"doc","id":"reference/NoirJS/noir_js/classes/Noir","label":"Noir"}]},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/CompiledCircuit","label":"CompiledCircuit"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ForeignCallHandler","label":"ForeignCallHandler"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ForeignCallInput","label":"ForeignCallInput"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ForeignCallOutput","label":"ForeignCallOutput"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/InputMap","label":"InputMap"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ProofData","label":"ProofData"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/WitnessMap","label":"WitnessMap"}]},{"type":"category","label":"Functions","items":[{"type":"doc","id":"reference/NoirJS/noir_js/functions/and","label":"and"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/blake2s256","label":"blake2s256"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify","label":"ecdsa_secp256k1_verify"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify","label":"ecdsa_secp256r1_verify"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/keccak256","label":"keccak256"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/sha256","label":"sha256"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/xor","label":"xor"}]}]}; +module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_wasm/.nojekyll b/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_wasm/.nojekyll new file mode 100644 index 00000000000..e2ac6616add --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_wasm/.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.25.0/reference/NoirJS/noir_wasm/functions/compile.md b/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_wasm/functions/compile.md new file mode 100644 index 00000000000..6faf763b37f --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_wasm/functions/compile.md @@ -0,0 +1,51 @@ +# compile() + +```ts +compile( + fileManager, + projectPath?, + logFn?, +debugLogFn?): Promise +``` + +Compiles a Noir project + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `fileManager` | `FileManager` | The file manager to use | +| `projectPath`? | `string` | The path to the project inside the file manager. Defaults to the root of the file manager | +| `logFn`? | `LogFn` | A logging function. If not provided, console.log will be used | +| `debugLogFn`? | `LogFn` | A debug logging function. If not provided, logFn will be used | + +## Returns + +`Promise`\<[`ProgramCompilationArtifacts`](../index.md#programcompilationartifacts)\> + +## Example + +```typescript +// Node.js + +import { compile_program, createFileManager } from '@noir-lang/noir_wasm'; + +const fm = createFileManager(myProjectPath); +const myCompiledCode = await compile_program(fm); +``` + +```typescript +// Browser + +import { compile_program, createFileManager } from '@noir-lang/noir_wasm'; + +const fm = createFileManager('/'); +for (const path of files) { + await fm.writeFile(path, await getFileAsStream(path)); +} +const myCompiledCode = await compile_program(fm); +``` + +*** + +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.25.0/reference/NoirJS/noir_wasm/functions/compile_contract.md b/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_wasm/functions/compile_contract.md new file mode 100644 index 00000000000..7d0b39a43ef --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_wasm/functions/compile_contract.md @@ -0,0 +1,51 @@ +# compile\_contract() + +```ts +compile_contract( + fileManager, + projectPath?, + logFn?, +debugLogFn?): Promise +``` + +Compiles a Noir project + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `fileManager` | `FileManager` | The file manager to use | +| `projectPath`? | `string` | The path to the project inside the file manager. Defaults to the root of the file manager | +| `logFn`? | `LogFn` | A logging function. If not provided, console.log will be used | +| `debugLogFn`? | `LogFn` | A debug logging function. If not provided, logFn will be used | + +## Returns + +`Promise`\<[`ContractCompilationArtifacts`](../index.md#contractcompilationartifacts)\> + +## Example + +```typescript +// Node.js + +import { compile_contract, createFileManager } from '@noir-lang/noir_wasm'; + +const fm = createFileManager(myProjectPath); +const myCompiledCode = await compile_contract(fm); +``` + +```typescript +// Browser + +import { compile_contract, createFileManager } from '@noir-lang/noir_wasm'; + +const fm = createFileManager('/'); +for (const path of files) { + await fm.writeFile(path, await getFileAsStream(path)); +} +const myCompiledCode = await compile_contract(fm); +``` + +*** + +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.25.0/reference/NoirJS/noir_wasm/functions/createFileManager.md b/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_wasm/functions/createFileManager.md new file mode 100644 index 00000000000..7e65c1d69c7 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_wasm/functions/createFileManager.md @@ -0,0 +1,21 @@ +# createFileManager() + +```ts +createFileManager(dataDir): FileManager +``` + +Creates a new FileManager instance based on fs in node and memfs in the browser (via webpack alias) + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `dataDir` | `string` | root of the file system | + +## Returns + +`FileManager` + +*** + +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.25.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md b/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md new file mode 100644 index 00000000000..fcea9275341 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md @@ -0,0 +1,21 @@ +# inflateDebugSymbols() + +```ts +inflateDebugSymbols(debugSymbols): any +``` + +Decompresses and decodes the debug symbols + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `debugSymbols` | `string` | The base64 encoded debug symbols | + +## Returns + +`any` + +*** + +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.25.0/reference/NoirJS/noir_wasm/index.md b/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_wasm/index.md new file mode 100644 index 00000000000..b6e0f9d1bc0 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_wasm/index.md @@ -0,0 +1,49 @@ +# noir_wasm + +## Exports + +### Functions + +| Function | Description | +| :------ | :------ | +| [compile](functions/compile.md) | Compiles a Noir project | +| [compile\_contract](functions/compile_contract.md) | Compiles a Noir project | +| [createFileManager](functions/createFileManager.md) | Creates a new FileManager instance based on fs in node and memfs in the browser (via webpack alias) | +| [inflateDebugSymbols](functions/inflateDebugSymbols.md) | Decompresses and decodes the debug symbols | + +## References + +### compile\_program + +Renames and re-exports [compile](functions/compile.md) + +## Interfaces + +### ContractCompilationArtifacts + +The compilation artifacts of a given contract. + +#### Properties + +| Property | Type | Description | +| :------ | :------ | :------ | +| `contract` | `ContractArtifact` | The compiled contract. | +| `warnings` | `unknown`[] | Compilation warnings. | + +*** + +### ProgramCompilationArtifacts + +The compilation artifacts of a given program. + +#### Properties + +| Property | Type | Description | +| :------ | :------ | :------ | +| `name` | `string` | not part of the compilation output, injected later | +| `program` | `ProgramArtifact` | The compiled contract. | +| `warnings` | `unknown`[] | Compilation warnings. | + +*** + +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.25.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs b/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs new file mode 100644 index 00000000000..e0870710349 --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs @@ -0,0 +1,4 @@ +// @ts-check +/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ +const typedocSidebar = { items: [{"type":"doc","id":"reference/NoirJS/noir_wasm/index","label":"API"},{"type":"category","label":"Functions","items":[{"type":"doc","id":"reference/NoirJS/noir_wasm/functions/compile","label":"compile"},{"type":"doc","id":"reference/NoirJS/noir_wasm/functions/compile_contract","label":"compile_contract"},{"type":"doc","id":"reference/NoirJS/noir_wasm/functions/createFileManager","label":"createFileManager"},{"type":"doc","id":"reference/NoirJS/noir_wasm/functions/inflateDebugSymbols","label":"inflateDebugSymbols"}]}]}; +module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.25.0/reference/_category_.json b/docs/versioned_docs/version-v0.25.0/reference/_category_.json new file mode 100644 index 00000000000..5b6a20a609a --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/reference/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 4, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.25.0/reference/nargo_commands.md b/docs/versioned_docs/version-v0.25.0/reference/nargo_commands.md new file mode 100644 index 00000000000..8a309ef4e7e --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/reference/nargo_commands.md @@ -0,0 +1,380 @@ +--- +title: Nargo +description: + Noir CLI Commands for Noir Prover and Verifier to create, execute, prove and verify programs, + generate Solidity verifier smart contract and compile into JSON file containing ACIR + representation and ABI of circuit. +keywords: + [ + Nargo, + Noir CLI, + Noir Prover, + Noir Verifier, + generate Solidity verifier, + compile JSON file, + ACIR representation, + ABI of circuit, + TypeScript, + ] +sidebar_position: 0 +--- + +# Command-Line Help for `nargo` + +This document contains the help content for the `nargo` command-line program. + +**Command Overview:** + +* [`nargo`↴](#nargo) +* [`nargo backend`↴](#nargo-backend) +* [`nargo backend current`↴](#nargo-backend-current) +* [`nargo backend ls`↴](#nargo-backend-ls) +* [`nargo backend use`↴](#nargo-backend-use) +* [`nargo backend install`↴](#nargo-backend-install) +* [`nargo backend uninstall`↴](#nargo-backend-uninstall) +* [`nargo check`↴](#nargo-check) +* [`nargo fmt`↴](#nargo-fmt) +* [`nargo codegen-verifier`↴](#nargo-codegen-verifier) +* [`nargo compile`↴](#nargo-compile) +* [`nargo new`↴](#nargo-new) +* [`nargo init`↴](#nargo-init) +* [`nargo execute`↴](#nargo-execute) +* [`nargo prove`↴](#nargo-prove) +* [`nargo verify`↴](#nargo-verify) +* [`nargo test`↴](#nargo-test) +* [`nargo info`↴](#nargo-info) +* [`nargo lsp`↴](#nargo-lsp) + +## `nargo` + +Noir's package manager + +**Usage:** `nargo ` + +###### **Subcommands:** + +* `backend` — Install and select custom backends used to generate and verify proofs +* `check` — Checks the constraint system for errors +* `fmt` — Format the Noir files in a workspace +* `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 Noir project in a new directory +* `init` — Create a Noir project in the current directory +* `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 +* `info` — Provides detailed information on a circuit +* `lsp` — Starts the Noir LSP server + +###### **Options:** + + + + +## `nargo backend` + +Install and select custom backends used to generate and verify proofs + +**Usage:** `nargo backend ` + +###### **Subcommands:** + +* `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 + + + +## `nargo backend current` + +Prints the name of the currently active backend + +**Usage:** `nargo backend current` + + + +## `nargo backend ls` + +Prints the list of currently installed backends + +**Usage:** `nargo backend ls` + + + +## `nargo backend use` + +Select the backend to use + +**Usage:** `nargo backend use ` + +###### **Arguments:** + +* `` + + + +## `nargo backend install` + +Install a new backend from a URL + +**Usage:** `nargo backend install ` + +###### **Arguments:** + +* `` — The name of the backend to install +* `` — The URL from which to download the backend + + + +## `nargo backend uninstall` + +Uninstalls a backend + +**Usage:** `nargo backend uninstall ` + +###### **Arguments:** + +* `` — The name of the backend to uninstall + + + +## `nargo check` + +Checks the constraint system for errors + +**Usage:** `nargo check [OPTIONS]` + +###### **Options:** + +* `--package ` — The name of the package to check +* `--workspace` — Check all packages in the workspace +* `--expression-width ` — Override the expression width requested by the backend +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings + + + +## `nargo fmt` + +Format the Noir files in a workspace + +**Usage:** `nargo fmt [OPTIONS]` + +###### **Options:** + +* `--check` — Run noirfmt in check mode + + + +## `nargo codegen-verifier` + +Generates a Solidity verifier smart contract for the program + +**Usage:** `nargo codegen-verifier [OPTIONS]` + +###### **Options:** + +* `--package ` — The name of the package to codegen +* `--workspace` — Codegen all packages in the workspace +* `--expression-width ` — Override the expression width requested by the backend +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings + + + +## `nargo compile` + +Compile the program and its secret execution trace into ACIR format + +**Usage:** `nargo compile [OPTIONS]` + +###### **Options:** + +* `--package ` — The name of the package to compile +* `--workspace` — Compile all packages in the workspace +* `--expression-width ` — Override the expression width requested by the backend +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings + + + +## `nargo new` + +Create a Noir project in a new directory + +**Usage:** `nargo new [OPTIONS] ` + +###### **Arguments:** + +* `` — The path to save the new project + +###### **Options:** + +* `--name ` — Name of the package [default: package directory name] +* `--lib` — Use a library template +* `--bin` — Use a binary template [default] +* `--contract` — Use a contract template + + + +## `nargo init` + +Create a Noir project in the current directory + +**Usage:** `nargo init [OPTIONS]` + +###### **Options:** + +* `--name ` — Name of the package [default: current directory name] +* `--lib` — Use a library template +* `--bin` — Use a binary template [default] +* `--contract` — Use a contract template + + + +## `nargo execute` + +Executes a circuit to calculate its return value + +**Usage:** `nargo execute [OPTIONS] [WITNESS_NAME]` + +###### **Arguments:** + +* `` — Write the execution witness to named file + +###### **Options:** + +* `-p`, `--prover-name ` — The name of the toml file which contains the inputs for the prover + + Default value: `Prover` +* `--package ` — The name of the package to execute +* `--workspace` — Execute all packages in the workspace +* `--expression-width ` — Override the expression width requested by the backend +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings +* `--oracle-resolver ` — JSON RPC url to solve oracle calls + + + +## `nargo prove` + +Create proof for this program. The proof is returned as a hex encoded string + +**Usage:** `nargo prove [OPTIONS]` + +###### **Options:** + +* `-p`, `--prover-name ` — The name of the toml file which contains the inputs for the prover + + Default value: `Prover` +* `-v`, `--verifier-name ` — The name of the toml file which contains the inputs for the verifier + + Default value: `Verifier` +* `--verify` — Verify proof after proving +* `--package ` — The name of the package to prove +* `--workspace` — Prove all packages in the workspace +* `--expression-width ` — Override the expression width requested by the backend +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings +* `--oracle-resolver ` — JSON RPC url to solve oracle calls + + + +## `nargo verify` + +Given a proof and a program, verify whether the proof is valid + +**Usage:** `nargo verify [OPTIONS]` + +###### **Options:** + +* `-v`, `--verifier-name ` — The name of the toml file which contains the inputs for the verifier + + Default value: `Verifier` +* `--package ` — The name of the package verify +* `--workspace` — Verify all packages in the workspace +* `--expression-width ` — Override the expression width requested by the backend +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings + + + +## `nargo test` + +Run the tests for this program + +**Usage:** `nargo test [OPTIONS] [TEST_NAME]` + +###### **Arguments:** + +* `` — If given, only tests with names containing this string will be run + +###### **Options:** + +* `--show-output` — Display output of `println` statements +* `--exact` — Only run tests that match exactly +* `--package ` — The name of the package to test +* `--workspace` — Test all packages in the workspace +* `--expression-width ` — Override the expression width requested by the backend +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings +* `--oracle-resolver ` — JSON RPC url to solve oracle calls + + + +## `nargo info` + +Provides detailed information on a circuit + +Current information provided: 1. The number of ACIR opcodes 2. Counts the final number gates in the circuit used by a backend + +**Usage:** `nargo info [OPTIONS]` + +###### **Options:** + +* `--package ` — The name of the package to detail +* `--workspace` — Detail all packages in the workspace +* `--expression-width ` — Override the expression width requested by the backend +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings + + + +## `nargo lsp` + +Starts the Noir LSP server + +Starts an LSP server which allows IDEs such as VS Code to display diagnostics in Noir source. + +VS Code Noir Language Support: https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir + +**Usage:** `nargo lsp` + + + +
+ + + This document was generated automatically by + clap-markdown. + + diff --git a/docs/versioned_docs/version-v0.25.0/tutorials/noirjs_app.md b/docs/versioned_docs/version-v0.25.0/tutorials/noirjs_app.md new file mode 100644 index 00000000000..0cea72314ce --- /dev/null +++ b/docs/versioned_docs/version-v0.25.0/tutorials/noirjs_app.md @@ -0,0 +1,324 @@ +--- +title: Building a web app with NoirJS +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, app] +sidebar_position: 0 +pagination_next: noir/concepts/data_types/index +--- + +NoirJS is a set of packages meant to work both in a browser and a server environment. In this tutorial, we will build a simple web app using them. From here, you should get an idea on how to proceed with your own Noir projects! + +You can find the complete app code for this guide [here](https://github.com/noir-lang/tiny-noirjs-app). + +## Setup + +:::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.25.x matches `noir_js@0.25.x`, etc. + +In this guide, we will be pinned to 0.25.0. + +::: + +Before we start, we want to make sure we have Node and Nargo installed. + +We start by opening a terminal and executing `node --version`. If we don't get an output like `v20.10.0`, that means node is not installed. Let's do that by following the handy [nvm guide](https://github.com/nvm-sh/nvm?tab=readme-ov-file#install--update-script). + +As for `Nargo`, we can follow the [Nargo guide](../getting_started/installation/index.md) to install it. If you're lazy, just paste this on a terminal and run `noirup`: + +```sh +curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash +``` + +Easy enough. Onwards! + +## Our project + +ZK is a powerful technology. An app that doesn't reveal one of the inputs to _anyone_ is almost unbelievable, yet Noir makes it as easy as a single line of code. + +In fact, it's so simple that it comes nicely packaged in `nargo`. Let's do that! + +### Nargo + +Run: + +`nargo new circuit` + +And... That's about it. Your program is ready to be compiled and run. + +To compile, let's `cd` into the `circuit` folder to enter our project, and call: + +`nargo compile` + +This compiles our circuit into `json` format and add it to a new `target` folder. + +:::info + +At this point in the tutorial, your folder structure should look like this: + +```tree +. +└── circuit <---- our working directory + ├── Nargo.toml + ├── src + │ └── main.nr + └── target + └── circuit.json +``` + +::: + +### Node and Vite + +If you want to explore Nargo, feel free to go on a side-quest now and follow the steps in the +[getting started](../getting_started/hello_noir/index.md) guide. However, we want our app to run on the browser, so we need Vite. + +Vite is a powerful tool to generate static websites. While it provides all kinds of features, let's just go barebones with some good old vanilla JS. + +To do this this, go back to the previous folder (`cd ..`) and create a new vite project by running `npm create vite` and choosing "Vanilla" and "Javascript". + +A wild `vite-project` directory should now appear in your root folder! Let's not waste any time and dive right in: + +```bash +cd vite-project +``` + +### Setting Up Vite and Configuring the Project + +Before we proceed with any coding, let's get our environment tailored for Noir. We'll start by laying down the foundations with a `vite.config.js` file. This little piece of configuration is our secret sauce for making sure everything meshes well with the NoirJS libraries and other special setups we might need, like handling WebAssembly modules. Here’s how you get that going: + +#### Creating the vite.config.js + +In your freshly minted `vite-project` folder, create a new file named `vite.config.js` and open it in your code editor. Paste the following to set the stage: + +```javascript +import { defineConfig } from "vite"; +import copy from "rollup-plugin-copy"; + +export default defineConfig({ + esbuild: { + target: "esnext", + }, + optimizeDeps: { + esbuildOptions: { + target: "esnext", + }, + }, + plugins: [ + copy({ + targets: [ + { src: "node_modules/**/*.wasm", dest: "node_modules/.vite/dist" }, + ], + copySync: true, + hook: "buildStart", + }), + ], + server: { + port: 3000, + }, +}); +``` + +#### Install Dependencies + +Now that our stage is set, install the necessary NoirJS packages along with our other dependencies: + +```bash +npm install && npm install @noir-lang/backend_barretenberg@0.25.0 @noir-lang/noir_js@0.25.0 +npm install rollup-plugin-copy --save-dev +``` + +:::info + +At this point in the tutorial, your folder structure should look like this: + +```tree +. +└── circuit + └── ...etc... +└── vite-project <---- our working directory + └── ...etc... +``` + +::: + +#### Some cleanup + +`npx create vite` is amazing but it creates a bunch of files we don't really need for our simple example. Actually, let's just delete everything except for `vite.config.js`, `index.html`, `main.js` and `package.json`. I feel lighter already. + +![my heart is ready for you, noir.js](@site/static/img/memes/titanic.jpeg) + +## HTML + +Our app won't run like this, of course. We need some working HTML, at least. Let's open our broken-hearted `index.html` and replace everything with this code snippet: + +```html + + + + + + +

Noir app

+
+ + +
+
+

Logs

+

Proof

+
+ + +``` + +It _could_ be a beautiful UI... Depending on which universe you live in. + +## Some good old vanilla Javascript + +Our love for Noir needs undivided attention, so let's just open `main.js` and delete everything (this is where the romantic scenery becomes a bit creepy). + +Start by pasting in this boilerplate code: + +```js +const setup = async () => { + await Promise.all([ + import('@noir-lang/noirc_abi').then((module) => + module.default(new URL('@noir-lang/noirc_abi/web/noirc_abi_wasm_bg.wasm', import.meta.url).toString()), + ), + import('@noir-lang/acvm_js').then((module) => + module.default(new URL('@noir-lang/acvm_js/web/acvm_js_bg.wasm', import.meta.url).toString()), + ), + ]); +}; + +function display(container, msg) { + const c = document.getElementById(container); + const p = document.createElement('p'); + p.textContent = msg; + c.appendChild(p); +} + +document.getElementById('submitGuess').addEventListener('click', async () => { + try { + // here's where love happens + } catch (err) { + display('logs', 'Oh 💔 Wrong guess'); + } +}); +``` + +The display function doesn't do much. We're simply manipulating our website to see stuff happening. For example, if the proof fails, it will simply log a broken heart 😢 + +As for the `setup` function, it's just a sad reminder that dealing with `wasm` on the browser is not as easy as it should. Just copy, paste, and forget. + +:::info + +At this point in the tutorial, your folder structure should look like this: + +```tree +. +└── circuit + └── ...same as above +└── vite-project + └── vite.config.js + ├── main.js + ├── package.json + └── index.html +``` + +You'll see other files and folders showing up (like `package-lock.json`, `node_modules`) but you shouldn't have to care about those. + +::: + +## Some NoirJS + +We're starting with the good stuff now. If you've compiled the circuit as described above, you should have a `json` file we want to import at the very top of our `main.js` file: + +```ts +import circuit from '../circuit/target/circuit.json'; +``` + +[Noir is backend-agnostic](../index.mdx#whats-new-about-noir). We write Noir, but we also need a proving backend. That's why we need to import and instantiate the two dependencies we installed above: `BarretenbergBackend` and `Noir`. Let's import them right below: + +```js +import { BarretenbergBackend } from '@noir-lang/backend_barretenberg'; +import { Noir } from '@noir-lang/noir_js'; +``` + +And instantiate them inside our try-catch block: + +```ts +// try { +const backend = new BarretenbergBackend(circuit); +const noir = new Noir(circuit, backend); +// } +``` + +:::note + +For the remainder of the tutorial, everything will be happening inside the `try` block + +::: + +## Our app + +Now for the app itself. We're capturing whatever is in the input when people press the submit button. Just add this: + +```js +const x = parseInt(document.getElementById('guessInput').value); +const input = { x, y: 2 }; +``` + +Now we're ready to prove stuff! Let's feed some inputs to our circuit and calculate the proof: + +```js +await setup(); // let's squeeze our wasm inits here + +display('logs', 'Generating proof... ⌛'); +const proof = await noir.generateProof(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 run dev`. If it doesn't open a browser for you, just visit `localhost:5173`. You should now see the worst UI ever, with an ugly input. + +![Getting Started 0](@site/static/img/noir_getting_started_1.png) + +Now, our circuit says `fn main(x: Field, y: pub Field)`. This means only the `y` value is public, and it's hardcoded above: `input = { x, y: 2 }`. In other words, you won't need to send your secret`x` to the verifier! + +By inputting any number other than 2 in the input box and clicking "submit", you should get a valid proof. Otherwise the proof won't even generate correctly. By the way, if you're human, you shouldn't be able to understand anything on the "proof" box. That's OK. We like you, human ❤️. + +## Verifying + +Time to celebrate, yes! But we shouldn't trust machines so blindly. Let's add these lines to see our proof being verified: + +```js +display('logs', 'Verifying proof... ⌛'); +const verification = await noir.verifyProof(proof); +if (verification) display('logs', 'Verifying proof... ✅'); +``` + +You have successfully generated a client-side Noir web app! + +![coded app without math knowledge](@site/static/img/memes/flextape.jpeg) + +## 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/vite-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.26.0/explainers/explainer-oracle.md b/docs/versioned_docs/version-v0.26.0/explainers/explainer-oracle.md new file mode 100644 index 00000000000..b84ca5dd986 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/explainers/explainer-oracle.md @@ -0,0 +1,57 @@ +--- +title: Oracles +description: This guide provides an in-depth understanding of how Oracles work in Noir programming. Learn how to use outside calculations in your programs, constrain oracles, and understand their uses and limitations. +keywords: + - Noir Programming + - Oracles + - JSON-RPC + - Foreign Call Handlers + - Constrained Functions + - Blockchain Programming +sidebar_position: 1 +--- + +If you've seen "The Matrix" you may recall "The Oracle" as Gloria Foster smoking cigarettes and baking cookies. While she appears to "know things", she is actually providing a calculation of a pre-determined future. Noir Oracles are similar, in a way. They don't calculate the future (yet), but they allow you to use outside calculations in your programs. + +![matrix oracle prediction](@site/static/img/memes/matrix_oracle.jpeg) + +A Noir program is usually self-contained. You can pass certain inputs to it, and it will generate a deterministic output for those inputs. But what if you wanted to defer some calculation to an outside process or source? + +Oracles are functions that provide this feature. + +## Use cases + +An example usage for Oracles is proving something on-chain. For example, proving that the ETH-USDC quote was below a certain target at a certain block time. Or even making more complex proofs like proving the ownership of an NFT as an anonymous login method. + +Another interesting use case is to defer expensive calculations to be made outside of the Noir program, and then constraining the result; similar to the use of [unconstrained functions](../noir/concepts//unconstrained.md). + +In short, anything that can be constrained in a Noir program but needs to be fetched from an external source is a great candidate to be used in oracles. + +## Constraining oracles + +Just like in The Matrix, Oracles are powerful. But with great power, comes great responsibility. Just because you're using them in a Noir program doesn't mean they're true. Noir has no superpowers. If you want to prove that Portugal won the Euro Cup 2016, you're still relying on potentially untrusted information. + +To give a concrete example, Alice wants to login to the [NounsDAO](https://nouns.wtf/) forum with her username "noir_nouner" by proving she owns a noun without revealing her ethereum address. Her Noir program could have a oracle call like this: + +```rust +#[oracle(getNoun)] +unconstrained fn get_noun(address: Field) -> Field +``` + +This oracle could naively resolve with the number of Nouns she possesses. However, it is useless as a trusted source, as the oracle could resolve to anything Alice wants. In order to make this oracle call actually useful, Alice would need to constrain the response from the oracle, by proving her address and the noun count belongs to the state tree of the contract. + +In short, **Oracles don't prove anything. Your Noir program does.** + +:::danger + +If you don't constrain the return of your oracle, you could be clearly opening an attack vector on your Noir program. Make double-triple sure that the return of an oracle call is constrained! + +::: + +## How to use Oracles + +On CLI, Nargo resolves oracles by making JSON RPC calls, which means it would require an RPC node to be running. + +In JavaScript, NoirJS accepts and resolves arbitrary call handlers (that is, not limited to JSON) as long as they matches the expected types the developer defines. Refer to [Foreign Call Handler](../reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md) to learn more about NoirJS's call handling. + +If you want to build using oracles, follow through to the [oracle guide](../how_to/how-to-oracles.md) for a simple example on how to do that. diff --git a/docs/versioned_docs/version-v0.26.0/explainers/explainer-recursion.md b/docs/versioned_docs/version-v0.26.0/explainers/explainer-recursion.md new file mode 100644 index 00000000000..18846176ca7 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/explainers/explainer-recursion.md @@ -0,0 +1,176 @@ +--- +title: Recursive proofs +description: Explore the concept of recursive proofs in Zero-Knowledge programming. Understand how recursion works in Noir, a language for writing smart contracts on the EVM blockchain. Learn through practical examples like Alice and Bob's guessing game, Charlie's recursive merkle tree, and Daniel's reusable components. Discover how to use recursive proofs to optimize computational resources and improve efficiency. + +keywords: + [ + "Recursive Proofs", + "Zero-Knowledge Programming", + "Noir", + "EVM Blockchain", + "Smart Contracts", + "Recursion in Noir", + "Alice and Bob Guessing Game", + "Recursive Merkle Tree", + "Reusable Components", + "Optimizing Computational Resources", + "Improving Efficiency", + "Verification Key", + "Aggregation", + "Recursive zkSNARK schemes", + "PLONK", + "Proving and Verification Keys" + ] +sidebar_position: 1 +pagination_next: how_to/how-to-recursion +--- + +In programming, we tend to think of recursion as something calling itself. A classic example would be the calculation of the factorial of a number: + +```js +function factorial(n) { + if (n === 0 || n === 1) { + return 1; + } else { + return n * factorial(n - 1); + } +} +``` + +In this case, while `n` is not `1`, this function will keep calling itself until it hits the base case, bubbling up the result on the call stack: + +```md + Is `n` 1? <--------- + /\ / + / \ n = n -1 + / \ / + Yes No -------- +``` + +In Zero-Knowledge, recursion has some similarities. + +It is not a Noir function calling itself, but a proof being used as an input to another circuit. In short, you verify one proof *inside* another proof, returning the proof that both proofs are valid. + +This means that, given enough computational resources, you can prove the correctness of any arbitrary number of proofs in a single proof. This could be useful to design state channels (for which a common example would be [Bitcoin's Lightning Network](https://en.wikipedia.org/wiki/Lightning_Network)), to save on gas costs by settling one proof on-chain, or simply to make business logic less dependent on a consensus mechanism. + +## Examples + +Let us look at some of these examples + +### Alice and Bob - Guessing game + +Alice and Bob are friends, and they like guessing games. They want to play a guessing game online, but for that, they need a trusted third-party that knows both of their secrets and finishes the game once someone wins. + +So, they use zero-knowledge proofs. Alice tries to guess Bob's number, and Bob will generate a ZK proof stating whether she succeeded or failed. + +This ZK proof can go on a smart contract, revealing the winner and even giving prizes. However, this means every turn needs to be verified on-chain. This incurs some cost and waiting time that may simply make the game too expensive or time-consuming to be worth it. + +As a solution, Alice proposes the following: "what if Bob generates his proof, and instead of sending it on-chain, I verify it *within* my own proof before playing my own turn?". + +She can then generate a proof that she verified his proof, and so on. + +```md + Did you fail? <-------------------------- + / \ / + / \ n = n -1 + / \ / + Yes No / + | | / + | | / + | You win / + | / + | / +Generate proof of that / + + / + my own guess ---------------- +``` + +### Charlie - Recursive merkle tree + +Charlie is a concerned citizen, and wants to be sure his vote in an election is accounted for. He votes with a ZK proof, but he has no way of knowing that his ZK proof was included in the total vote count! + +If the vote collector puts all of the votes into a [Merkle tree](https://en.wikipedia.org/wiki/Merkle_tree), everyone can prove the verification of two proofs within one proof, as such: + +```md + abcd + __________|______________ + | | + ab cd + _____|_____ ______|______ + | | | | + alice bob charlie daniel +``` + +Doing this recursively allows us to arrive on a final proof `abcd` which if true, verifies the correctness of all the votes. + +### Daniel - Reusable components + +Daniel has a big circuit and a big headache. A part of his circuit is a setup phase that finishes with some assertions that need to be made. But that section alone takes most of the proving time, and is largely independent of the rest of the circuit. + +He might find it more efficient to generate a proof for that setup phase separately, and verify that proof recursively in the actual business logic section of his circuit. This will allow for parallelization of both proofs, which results in a considerable speedup. + +## What params do I need + +As you can see in the [recursion reference](noir/standard_library/recursion.md), a simple recursive proof requires: + +- The proof to verify +- The Verification Key of the circuit that generated the proof +- A hash of this verification key, as it's needed for some backends +- The public inputs for the proof + +:::info + +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. + +So, taking the example of Alice and Bob and their guessing game: + +- Alice makes her guess. Her proof is *not* recursive: it doesn't verify any proof within it! It's just a standard `assert(x != y)` circuit +- Bob verifies Alice's proof and makes his own guess. In this circuit, he doesn't exactly *prove* the verification of Alice's proof. Instead, he *aggregates* his proof to Alice's proof. The actual verification is done when the full proof is verified, for example when using `nargo verify` or through the verifier smart contract. + +We can imagine recursive proofs a [relay race](https://en.wikipedia.org/wiki/Relay_race). The first runner doesn't have to receive the baton from anyone else, as he/she already starts with it. But when his/her turn is over, the next runner needs to receive it, run a bit more, and pass it along. Even though every runner could theoretically verify the baton mid-run (why not? 🏃🔍), only at the end of the race does the referee verify that the whole race is valid. + +::: + +## Some architecture + +As with everything in computer science, there's no one-size-fits all. But there are some patterns that could help understanding and implementing them. To give three examples: + +### Adding some logic to a proof verification + +This would be an approach for something like our guessing game, where proofs are sent back and forth and are verified by each opponent. This circuit would be divided in two sections: + +- A `recursive verification` section, which would be just the call to `std::verify_proof`, and that would be skipped on the first move (since there's no proof to verify) +- A `guessing` section, which is basically the logic part where the actual guessing happens + +In such a situation, and assuming Alice is first, she would skip the first part and try to guess Bob's number. Bob would then verify her proof on the first section of his run, and try to guess Alice's number on the second part, and so on. + +### Aggregating proofs + +In some one-way interaction situations, recursion would allow for aggregation of simple proofs that don't need to be immediately verified on-chain or elsewhere. + +To give a practical example, a barman wouldn't need to verify a "proof-of-age" on-chain every time he serves alcohol to a customer. Instead, the architecture would comprise two circuits: + +- A `main`, non-recursive circuit with some logic +- A `recursive` circuit meant to verify two proofs in one proof + +The customer's proofs would be intermediate, and made on their phones, and the barman could just verify them locally. He would then aggregate them into a final proof sent on-chain (or elsewhere) at the end of the day. + +### Recursively verifying different circuits + +Nothing prevents you from verifying different circuits in a recursive proof, for example: + +- A `circuit1` circuit +- A `circuit2` circuit +- A `recursive` circuit + +In this example, a regulator could verify that taxes were paid for a specific purchase by aggregating both a `payer` circuit (proving that a purchase was made and taxes were paid), and a `receipt` circuit (proving that the payment was received) + +## How fast is it + +At the time of writing, verifying recursive proofs is surprisingly fast. This is because most of the time is spent on generating the verification key that will be used to generate the next proof. So you are able to cache the verification key and reuse it later. + +Currently, Noir JS packages don't expose the functionality of loading proving and verification keys, but that feature exists in the underlying `bb.js` package. + +## How can I try it + +Learn more about using recursion in Nargo and NoirJS in the [how-to guide](../how_to/how-to-recursion.md) and see a full example in [noir-examples](https://github.com/noir-lang/noir-examples). diff --git a/docs/versioned_docs/version-v0.26.0/getting_started/_category_.json b/docs/versioned_docs/version-v0.26.0/getting_started/_category_.json new file mode 100644 index 00000000000..5d694210bbf --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/getting_started/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 0, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.26.0/getting_started/hello_noir/_category_.json b/docs/versioned_docs/version-v0.26.0/getting_started/hello_noir/_category_.json new file mode 100644 index 00000000000..23b560f610b --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/getting_started/hello_noir/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 1, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.26.0/getting_started/hello_noir/index.md b/docs/versioned_docs/version-v0.26.0/getting_started/hello_noir/index.md new file mode 100644 index 00000000000..743c4d8d634 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/getting_started/hello_noir/index.md @@ -0,0 +1,142 @@ +--- +title: Creating a Project +description: + Learn how to create and verify your first Noir program using Nargo, a programming language for + zero-knowledge proofs. +keywords: + [ + Nargo, + Noir, + zero-knowledge proofs, + programming language, + create Noir program, + verify Noir program, + step-by-step guide, + ] +sidebar_position: 1 + +--- + +Now that we have installed Nargo, it is time to make our first hello world program! + +## Create a Project Directory + +Noir code can live anywhere on your computer. Let us create a _projects_ folder in the home +directory to house our Noir programs. + +For Linux, macOS, and Windows PowerShell, create the directory and change directory into it by +running: + +```sh +mkdir ~/projects +cd ~/projects +``` + +## Create Our First Nargo Project + +Now that we are in the projects directory, create a new Nargo project by running: + +```sh +nargo new hello_world +``` + +> **Note:** `hello_world` can be any arbitrary project name, we are simply using `hello_world` for +> demonstration. +> +> In production, the common practice is to name the project folder as `circuits` for better +> identifiability when sitting alongside other folders in the codebase (e.g. `contracts`, `scripts`, +> `test`). + +A `hello_world` folder would be created. Similar to Rust, the folder houses _src/main.nr_ and +_Nargo.toml_ which contain 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](../../noir/concepts/data_types/index.md) section. + +The next line of the program specifies its body: + +```rust +assert(x != y); +``` + +The Noir syntax `assert` can be interpreted as something similar to constraints in other zk-contract languages. + +For more Noir syntax, check the [Language Concepts](../../noir/concepts/comments.md) chapter. + +## Build In/Output Files + +Change directory into _hello_world_ and build in/output files for your Noir program by running: + +```sh +cd hello_world +nargo check +``` + +Two additional files would be generated in your project directory: + +_Prover.toml_ houses input values, and _Verifier.toml_ houses public values. + +## Prove Our Noir Program + +Now that the project is set up, we can create a proof of correct execution of 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](./project_breakdown.md), we will go into more detail on each step performed. diff --git a/docs/versioned_docs/version-v0.26.0/getting_started/hello_noir/project_breakdown.md b/docs/versioned_docs/version-v0.26.0/getting_started/hello_noir/project_breakdown.md new file mode 100644 index 00000000000..6160a102c6c --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/getting_started/hello_noir/project_breakdown.md @@ -0,0 +1,199 @@ +--- +title: Project Breakdown +description: + Learn about the anatomy of a Nargo project, including the purpose of the Prover and Verifier TOML + files, and how to prove and verify your program. +keywords: + [Nargo, Nargo project, Prover.toml, Verifier.toml, proof verification, private asset transfer] +sidebar_position: 2 +--- + +This section breaks down our hello world program from the previous section. We elaborate on the project +structure and what the `prove` and `verify` commands did. + +## 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 = "noir_starter" +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](../../noir/modules_packages_crates/workspaces.md) will look a bit different. For example: + +```toml +[workspace] +members = ["crates/a", "crates/b"] +default-member = "crates/a" +``` + +#### Package section + +The package section defines 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](../../noir/modules_packages_crates/dependencies.md) for more info. + +`./proofs/` and `./contract/` directories will not be immediately visible until you create a proof or +verifier contract respectively. + +### main.nr + +The _main.nr_ file contains a `main` method, this method is the entry point into your Noir program. + +In our sample program, _main.nr_ looks like this: + +```rust +fn main(x : Field, y : Field) { + assert(x != y); +} +``` + +The parameters `x` and `y` can be seen as the API for the program and must be supplied by the +prover. Since neither `x` nor `y` is marked as public, the verifier does not supply any inputs, when +verifying the proof. + +The prover supplies the values for `x` and `y` in the _Prover.toml_ file. + +As for the program body, `assert` ensures that the condition to be satisfied (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 inequality 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, usually from external sources, and +verify the validity of the proof against it. + +Take a private asset transfer as an example: + +A person using a browser as the prover would retrieve private inputs locally (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.26.0/getting_started/installation/_category_.json b/docs/versioned_docs/version-v0.26.0/getting_started/installation/_category_.json new file mode 100644 index 00000000000..0c02fb5d4d7 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/getting_started/installation/_category_.json @@ -0,0 +1,6 @@ +{ + "position": 0, + "label": "Install Nargo", + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.26.0/getting_started/installation/index.md b/docs/versioned_docs/version-v0.26.0/getting_started/installation/index.md new file mode 100644 index 00000000000..4ef86aa5914 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/getting_started/installation/index.md @@ -0,0 +1,48 @@ +--- +title: Nargo Installation +description: + nargo is a command line tool for interacting with Noir programs. This page is a quick guide on how to install Nargo through the most common and easy method, noirup +keywords: [ + Nargo + Noir + Rust + Cargo + Noirup + Installation + Terminal Commands + Version Check + Nightlies + Specific Versions + Branches + Noirup Repository +] +pagination_next: getting_started/hello_noir/index +--- + +`nargo` is the one-stop-shop for almost everything related with Noir. The name comes from our love for Rust and its package manager `cargo`. + +With `nargo`, you can start new projects, compile, execute, prove, verify, test, generate solidity contracts, and do pretty much all that is available in Noir. + +Similarly to `rustup`, we also maintain an easy installation method that covers most machines: `noirup`. + +## Installing Noirup + +Open a terminal on your machine, and write: + +```bash +curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash +``` + +Close the terminal, open another one, and run + +```bash +noirup +``` + +Done. That's it. You should have the latest version working. You can check with `nargo --version`. + +You can also install nightlies, specific versions +or branches. Check out the [noirup repository](https://github.com/noir-lang/noirup) for more +information. + +Now we're ready to start working on [our first Noir program!](../hello_noir/index.md) diff --git a/docs/versioned_docs/version-v0.26.0/getting_started/installation/other_install_methods.md b/docs/versioned_docs/version-v0.26.0/getting_started/installation/other_install_methods.md new file mode 100644 index 00000000000..3634723562b --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/getting_started/installation/other_install_methods.md @@ -0,0 +1,102 @@ +--- +title: Alternative Installations +description: There are different ways to install Nargo, the one-stop shop and command-line tool for developing Noir programs. This guide explains how to specify which version to install when using noirup, and using WSL for windows. +keywords: [ + Installation + Nargo + Noirup + Binaries + Compiling from Source + WSL for Windows + macOS + Linux + Nix + Direnv + Uninstalling Nargo + ] +sidebar_position: 1 +--- + +## Encouraged Installation Method: Noirup + +Noirup is the endorsed method for installing Nargo, streamlining the process of fetching binaries or compiling from source. It supports a range of options to cater to your specific needs, from nightly builds and specific versions to compiling from various sources. + +### Installing Noirup + +First, ensure you have `noirup` installed: + +```sh +curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash +``` + +### Fetching Binaries + +With `noirup`, you can easily switch between different Nargo versions, including nightly builds: + +- **Nightly Version**: Install the latest nightly build. + + ```sh + noirup --version nightly + ``` + +- **Specific Version**: Install a specific version of Nargo. + ```sh + noirup --version + ``` + +### Compiling from Source + +`noirup` also enables compiling Nargo from various sources: + +- **From a Specific Branch**: Install from the latest commit on a branch. + + ```sh + noirup --branch + ``` + +- **From a Fork**: Install from the main branch of a fork. + + ```sh + noirup --repo + ``` + +- **From a Specific Branch in a Fork**: Install from a specific branch in a fork. + + ```sh + noirup --repo --branch + ``` + +- **From a Specific Pull Request**: Install from a specific PR. + + ```sh + noirup --pr + ``` + +- **From a Specific Commit**: Install from a specific commit. + + ```sh + noirup -C + ``` + +- **From Local Source**: Compile and install from a local directory. + ```sh + noirup --path ./path/to/local/source + ``` + +## Installation on Windows + +The default backend for Noir (Barretenberg) doesn't provide Windows binaries at this time. For that reason, Noir cannot be installed natively. 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](#encouraged-installation-method-noirup). + +## Uninstalling Nargo + +If you installed Nargo with `noirup`, you can uninstall Nargo by removing the files in `~/.nargo`, `~/nargo`, and `~/noir_cache`. This ensures that all installed binaries, configurations, and cache related to Nargo are fully removed from your system. + +```bash +rm -r ~/.nargo +rm -r ~/nargo +rm -r ~/noir_cache +``` diff --git a/docs/versioned_docs/version-v0.26.0/getting_started/tooling/_category_.json b/docs/versioned_docs/version-v0.26.0/getting_started/tooling/_category_.json new file mode 100644 index 00000000000..55804c03a71 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/getting_started/tooling/_category_.json @@ -0,0 +1,6 @@ +{ + "position": 2, + "label": "Tooling", + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.26.0/getting_started/tooling/index.mdx b/docs/versioned_docs/version-v0.26.0/getting_started/tooling/index.mdx new file mode 100644 index 00000000000..ec9ccea4115 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/getting_started/tooling/index.mdx @@ -0,0 +1,34 @@ +--- +title: Tooling +Description: This section provides information about the various tools and utilities available for Noir development. It covers IDE tools, Codespaces, and community projects. +Keywords: [Noir, Development, Playground, IDE Tools, Language Service Provider, VS Code Extension, Codespaces, noir-starter, Community Projects, Awesome Noir Repository, Developer Tooling] +--- + +Noir is meant to be easy to develop with. For that reason, a number of utilities have been put together to ease the development process as much as feasible in the zero-knowledge world. + +## IDE tools + +When you install Nargo, you're also installing a Language Service Provider (LSP), which can be used by IDEs to provide syntax highlighting, codelens, warnings, and more. + +The easiest way to use these tools is by installing the [Noir VS Code extension](https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir). + +## Codespaces + +Some Noir repos have leveraged Codespaces in order to ease the development process. You can visit the [noir-starter](https://github.com/noir-lang/noir-starter) for an example. + + + +## GitHub Actions + +You can use `noirup` with GitHub Actions for CI/CD and automated testing. It is as simple as +installing `noirup` and running tests in your GitHub Action `yml` file. + +See the +[config file in the Noir repo](https://github.com/TomAFrench/noir-hashes/blob/master/.github/workflows/noir.yml) for an example usage. + +## Community projects + +As an open-source project, Noir has received many contributions over time. Some of them are related with developer tooling, and you can see some of them in [Awesome Noir repository](https://github.com/noir-lang/awesome-noir#dev-tools) diff --git a/docs/versioned_docs/version-v0.26.0/getting_started/tooling/language_server.md b/docs/versioned_docs/version-v0.26.0/getting_started/tooling/language_server.md new file mode 100644 index 00000000000..81e0356ef8a --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/getting_started/tooling/language_server.md @@ -0,0 +1,43 @@ +--- +title: Language Server +description: Learn about the Noir Language Server, how to install the components, and configuration that may be required. +keywords: [Nargo, Language Server, LSP, VSCode, Visual Studio Code] +sidebar_position: 0 +--- + +This section helps you install and configure the Noir Language Server. + +The Language Server Protocol (LSP) has two components, the [Server](#language-server) and the [Client](#language-client). Below we describe each in the context of Noir. + +## Language Server + +The Server component is provided by the Nargo command line tool that you installed at the beginning of this guide. +As long as Nargo is installed and you've used it to run other commands in this guide, it should be good to go! + +If you'd like to verify that the `nargo lsp` command is available, you can run `nargo --help` and look for `lsp` in the list of commands. If you see it, you're using a version of Noir with LSP support. + +## Language Client + +The Client component is usually an editor plugin that launches the Server. It communicates LSP messages between the editor and the Server. For example, when you save a file, the Client will alert the Server, so it can try to compile the project and report any errors. + +Currently, Noir provides a Language Client for Visual Studio Code via the [vscode-noir](https://github.com/noir-lang/vscode-noir) extension. You can install it via the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir). + +> **Note:** Noir's Language Server Protocol support currently assumes users' VSCode workspace root to be the same as users' Noir project root (i.e. where Nargo.toml lies). +> +> If LSP features seem to be missing / malfunctioning, make sure you are opening your Noir project directly (instead of as a sub-folder) in your VSCode instance. + +When your language server is running correctly and the VSCode plugin is installed, you should see handy codelens buttons for compilation, measuring circuit size, execution, and tests: + +![Compile and Execute](@site/static/img/codelens_compile_execute.png) +![Run test](@site/static/img/codelens_run_test.png) + +You should also see your tests in the `testing` panel: + +![Testing panel](@site/static/img/codelens_testing_panel.png) + +### Configuration + +- **Noir: Enable LSP** - If checked, the extension will launch the Language Server via `nargo lsp` and communicate with it. +- **Noir: Nargo Flags** - Additional flags may be specified if you require them to be added when the extension calls `nargo lsp`. +- **Noir: Nargo Path** - An absolute path to a Nargo binary with the `lsp` command. This may be useful if Nargo is not within the `PATH` of your editor. +- **Noir > Trace: Server** - Setting this to `"messages"` or `"verbose"` will log LSP messages between the Client and Server. Useful for debugging. diff --git a/docs/versioned_docs/version-v0.26.0/getting_started/tooling/noir_codegen.md b/docs/versioned_docs/version-v0.26.0/getting_started/tooling/noir_codegen.md new file mode 100644 index 00000000000..d65151da0ab --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/getting_started/tooling/noir_codegen.md @@ -0,0 +1,113 @@ +--- +title: Noir Codegen for TypeScript +description: Learn how to use Noir codegen to generate TypeScript bindings +keywords: [Nargo, Noir, compile, TypeScript] +sidebar_position: 2 +--- + +When using TypeScript, it is extra work to interpret Noir program outputs in a type-safe way. Third party libraries may exist for popular Noir programs, but they are either hard to find or unmaintained. + +Now you can generate TypeScript bindings for your Noir programs in two steps: +1. Exporting Noir functions using `nargo export` +2. Using the TypeScript module `noir_codegen` to generate TypeScript binding + +**Note:** you can only export functions from a Noir *library* (not binary or contract program types). + +## Installation + +### Your TypeScript project + +If you don't already have a TypeScript project you can add the module with `yarn` (or `npm`), then initialize it: + +```bash +yarn add typescript -D +npx tsc --init +``` + +### Add TypeScript module - `noir_codegen` + +The following command will add the module to your project's devDependencies: + +```bash +yarn add @noir-lang/noir_codegen -D +``` + +### Nargo library +Make sure you have Nargo, v0.25.0 or greater, installed. If you don't, follow the [installation guide](../installation/index.md). + +If you're in a new project, make a `circuits` folder and create a new Noir library: + +```bash +mkdir circuits && cd circuits +nargo new --lib myNoirLib +``` + +## Usage + +### Export ABI of specified functions + +First go to the `.nr` files in your Noir library, and add the `#[export]` macro to each function that you want to use in TypeScript. + +```rust +#[export] +fn your_function(... +``` + +From your Noir library (where `Nargo.toml` is), run the following command: + +```bash +nargo export +``` + +You will now have an `export` directory with a .json file per exported function. + +You can also specify the directory of Noir programs using `--program-dir`, for example: + +```bash +nargo export --program-dir=./circuits/myNoirLib +``` + +### Generate TypeScript bindings from exported functions + +To use the `noir-codegen` package we added to the TypeScript project: + +```bash +yarn noir-codegen ./export/your_function.json +``` + +This creates an `exports` directory with an `index.ts` file containing all exported functions. + +**Note:** adding `--out-dir` allows you to specify an output dir for your TypeScript bindings to go. Eg: + +```bash +yarn noir-codegen ./export/*.json --out-dir ./path/to/output/dir +``` + +## Example .nr function to .ts output + +Consider a Noir library with this function: + +```rust +#[export] +fn not_equal(x: Field, y: Field) -> bool { + x != y +} +``` + +After the export and codegen steps, you should have an `index.ts` like: + +```typescript +export type Field = string; + + +export const is_equal_circuit: CompiledCircuit = {"abi":{"parameters":[{"name":"x","type":{"kind":"field"},"visibility":"private"},{"name":"y","type":{"kind":"field"},"visibility":"private"}],"param_witnesses":{"x":[{"start":0,"end":1}],"y":[{"start":1,"end":2}]},"return_type":{"abi_type":{"kind":"boolean"},"visibility":"private"},"return_witnesses":[4]},"bytecode":"H4sIAAAAAAAA/7WUMQ7DIAxFQ0Krrr2JjSGYLVcpKrn/CaqqDQN12WK+hPBgmWd/wEyHbF1SS923uhOs3pfoChI+wKXMAXzIKyNj4PB0TFTYc0w5RUjoqeAeEu1wqK0F54RGkWvW44LPzExnlkbMEs4JNZmN8PxS42uHv82T8a3Jeyn2Ks+VLPcO558HmyLMCDOXAXXtpPt4R/Rt9T36ss6dS9HGPx/eG17nGegKBQAA"}; + +export async function is_equal(x: Field, y: Field, foreignCallHandler?: ForeignCallHandler): Promise { + const program = new Noir(is_equal_circuit); + const args: InputMap = { x, y }; + const { returnValue } = await program.execute(args, foreignCallHandler); + return returnValue as boolean; +} +``` + +Now the `is_equal()` function and relevant types are readily available for use in TypeScript. diff --git a/docs/versioned_docs/version-v0.26.0/getting_started/tooling/testing.md b/docs/versioned_docs/version-v0.26.0/getting_started/tooling/testing.md new file mode 100644 index 00000000000..d3e0c522473 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/getting_started/tooling/testing.md @@ -0,0 +1,62 @@ +--- +title: Testing in Noir +description: Learn how to use Nargo to test your Noir program in a quick and easy way +keywords: [Nargo, testing, Noir, compile, test] +sidebar_position: 1 +--- + +You can test your Noir programs using Noir circuits. + +Nargo will automatically compile and run any functions which have the decorator `#[test]` on them if +you run `nargo test`. + +For example if you have a program like: + +```rust +fn add(x: u64, y: u64) -> u64 { + x + y +} +#[test] +fn test_add() { + assert(add(2,2) == 4); + assert(add(0,1) == 1); + assert(add(1,0) == 1); +} +``` + +Running `nargo test` will test that the `test_add` function can be executed while satisfying all +the constraints 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.26.0/how_to/_category_.json b/docs/versioned_docs/version-v0.26.0/how_to/_category_.json new file mode 100644 index 00000000000..23b560f610b --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/how_to/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 1, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.26.0/how_to/how-to-oracles.md b/docs/versioned_docs/version-v0.26.0/how_to/how-to-oracles.md new file mode 100644 index 00000000000..8cf8035a5c4 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/how_to/how-to-oracles.md @@ -0,0 +1,276 @@ +--- +title: How to use Oracles +description: Learn how to use oracles in your Noir program with examples in both Nargo and NoirJS. This guide also covers writing a JSON RPC server and providing custom foreign call handlers for NoirJS. +keywords: + - Noir Programming + - Oracles + - Nargo + - NoirJS + - JSON RPC Server + - Foreign Call Handlers +sidebar_position: 1 +--- + +This guide shows you how to use oracles in your Noir program. For the sake of clarity, it assumes that: + +- You have read the [explainer on Oracles](../explainers/explainer-oracle.md) and are comfortable with the concept. +- You have a Noir program to add oracles to. You can create one using the [vite-hardhat starter](https://github.com/noir-lang/noir-starter/tree/main/vite-hardhat) as a boilerplate. +- You understand the concept of a JSON-RPC server. Visit the [JSON-RPC website](https://www.jsonrpc.org/) if you need a refresher. +- You are comfortable with server-side JavaScript (e.g. Node.js, managing packages, etc.). + +For reference, you can find the snippets used in this tutorial on the [Aztec DevRel Repository](https://github.com/AztecProtocol/dev-rel/tree/main/code-snippets/how-to-oracles). + +## Rundown + +This guide has 3 major steps: + +1. How to modify our Noir program to make use of oracle calls as unconstrained functions +2. How to write a JSON RPC Server to resolve these oracle calls with Nargo +3. How to use them in Nargo and how to provide a custom resolver in NoirJS + +## Step 1 - Modify your Noir program + +An oracle is defined in a Noir program by defining two methods: + +- An unconstrained method - This tells the compiler that it is executing an [unconstrained functions](../noir/concepts//unconstrained.md). +- A decorated oracle method - This tells the compiler that this method is an RPC call. + +An example of an oracle that returns a `Field` would be: + +```rust +#[oracle(getSqrt)] +unconstrained fn sqrt(number: Field) -> Field { } + +unconstrained fn get_sqrt(number: Field) -> Field { + sqrt(number) +} +``` + +In this example, we're wrapping our oracle function in a unconstrained method, and decorating it with `oracle(getSqrt)`. We can then call the unconstrained function as we would call any other function: + +```rust +fn main(input: Field) { + let sqrt = get_sqrt(input); +} +``` + +In the next section, we will make this `getSqrt` (defined on the `sqrt` decorator) be a method of the RPC server Noir will use. + +:::danger + +As explained in the [Oracle Explainer](../explainers/explainer-oracle.md), this `main` function is unsafe unless you constrain its return value. For example: + +```rust +fn main(input: Field) { + let sqrt = get_sqrt(input); + assert(sqrt.pow_32(2) as u64 == input as u64); // <---- constrain the return of an oracle! +} +``` + +::: + +:::info + +Currently, oracles only work with single params or array params. For example: + +```rust +#[oracle(getSqrt)] +unconstrained fn sqrt([Field; 2]) -> [Field; 2] { } +``` + +::: + +## Step 2 - Write an RPC server + +Brillig will call *one* RPC server. Most likely you will have to write your own, and you can do it in whatever language you prefer. In this guide, we will do it in Javascript. + +Let's use the above example of an oracle that consumes an array with two `Field` and returns their square roots: + +```rust +#[oracle(getSqrt)] +unconstrained fn sqrt(input: [Field; 2]) -> [Field; 2] { } + +unconstrained fn get_sqrt(input: [Field; 2]) -> [Field; 2] { + sqrt(input) +} + +fn main(input: [Field; 2]) { + let sqrt = get_sqrt(input); + assert(sqrt[0].pow_32(2) as u64 == input[0] as u64); + assert(sqrt[1].pow_32(2) as u64 == input[1] as u64); +} +``` + +:::info + +Why square root? + +In general, computing square roots is computationally more expensive than multiplications, which takes a toll when speaking about ZK applications. In this case, instead of calculating the square root in Noir, we are using our oracle to offload that computation to be made in plain. In our circuit we can simply multiply the two values. + +::: + +Now, we should write the correspondent RPC server, starting with the [default JSON-RPC 2.0 boilerplate](https://www.npmjs.com/package/json-rpc-2.0#example): + +```js +import { JSONRPCServer } from "json-rpc-2.0"; +import express from "express"; +import bodyParser from "body-parser"; + +const app = express(); +app.use(bodyParser.json()); + +const server = new JSONRPCServer(); +app.post("/", (req, res) => { + const jsonRPCRequest = req.body; + server.receive(jsonRPCRequest).then((jsonRPCResponse) => { + if (jsonRPCResponse) { + res.json(jsonRPCResponse); + } else { + res.sendStatus(204); + } + }); +}); + +app.listen(5555); +``` + +Now, we will add our `getSqrt` method, as expected by the `#[oracle(getSqrt)]` decorator in our Noir code. It maps through the params array and returns their square roots: + +```js +server.addMethod("getSqrt", async (params) => { + const values = params[0].Array.map((field) => { + return `${Math.sqrt(parseInt(field, 16))}`; + }); + return { values: [{ Array: values }] }; +}); +``` + +:::tip + +Brillig expects an object with an array of values. Each value is an object declaring to be `Single` or `Array` and returning a field element *as a string*. For example: + +```json +{ "values": [{ "Array": ["1", "2"] }]} +{ "values": [{ "Single": "1" }]} +{ "values": [{ "Single": "1" }, { "Array": ["1", "2"] }]} +``` + +If you're using Typescript, the following types may be helpful in understanding the expected return value and making sure they're easy to follow: + +```js +interface SingleForeignCallParam { + Single: string, +} + +interface ArrayForeignCallParam { + Array: string[], +} + +type ForeignCallParam = SingleForeignCallParam | ArrayForeignCallParam; + +interface ForeignCallResult { + values: ForeignCallParam[], +} +``` + +::: + +## Step 3 - Usage with Nargo + +Using the [`nargo` CLI tool](../getting_started/installation/index.md), you can use oracles in the `nargo test`, `nargo execute` and `nargo prove` commands by passing a value to `--oracle-resolver`. For example: + +```bash +nargo test --oracle-resolver http://localhost:5555 +``` + +This tells `nargo` to use your RPC Server URL whenever it finds an oracle decorator. + +## Step 4 - Usage with NoirJS + +In a JS environment, an RPC server is not strictly necessary, as you may want to resolve your oracles without needing any JSON call at all. NoirJS simply expects that you pass a callback function when you generate proofs, and that callback function can be anything. + +For example, if your Noir program expects the host machine to provide CPU pseudo-randomness, you could simply pass it as the `foreignCallHandler`. You don't strictly need to create an RPC server to serve pseudo-randomness, as you may as well get it directly in your app: + +```js +const foreignCallHandler = (name, inputs) => crypto.randomBytes(16) // etc + +await noir.generateProof(inputs, foreignCallHandler) +``` + +As one can see, in NoirJS, the [`foreignCallHandler`](../reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md) function simply means "a callback function that returns a value of type [`ForeignCallOutput`](../reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md). It doesn't have to be an RPC call like in the case for Nargo. + +:::tip + +Does this mean you don't have to write an RPC server like in [Step #2](#step-2---write-an-rpc-server)? + +You don't technically have to, but then how would you run `nargo test` or `nargo prove`? To use both `Nargo` and `NoirJS` in your development flow, you will have to write a JSON RPC server. + +::: + +In this case, let's make `foreignCallHandler` call the JSON RPC Server we created in [Step #2](#step-2---write-an-rpc-server), by making it a JSON RPC Client. + +For example, using the same `getSqrt` program in [Step #1](#step-1---modify-your-noir-program) (comments in the code): + +```js +import { JSONRPCClient } from "json-rpc-2.0"; + +// declaring the JSONRPCClient +const client = new JSONRPCClient((jsonRPCRequest) => { +// hitting the same JSON RPC Server we coded above + return fetch("http://localhost:5555", { + method: "POST", + headers: { + "content-type": "application/json", + }, + body: JSON.stringify(jsonRPCRequest), + }).then((response) => { + if (response.status === 200) { + return response + .json() + .then((jsonRPCResponse) => client.receive(jsonRPCResponse)); + } else if (jsonRPCRequest.id !== undefined) { + return Promise.reject(new Error(response.statusText)); + } + }); +}); + +// declaring a function that takes the name of the foreign call (getSqrt) and the inputs +const foreignCallHandler = async (name, input) => { + // notice that the "inputs" parameter contains *all* the inputs + // in this case we to make the RPC request with the first parameter "numbers", which would be input[0] + const oracleReturn = await client.request(name, [ + { Array: input[0].map((i) => i.toString("hex")) }, + ]); + return [oracleReturn.values[0].Array]; +}; + +// the rest of your NoirJS code +const input = { input: [4, 16] }; +const { witness } = await noir.execute(numbers, foreignCallHandler); +``` + +:::tip + +If you're in a NoirJS environment running your RPC server together with a frontend app, you'll probably hit a familiar problem in full-stack development: requests being blocked by [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) policy. For development only, you can simply install and use the [`cors` npm package](https://www.npmjs.com/package/cors) to get around the problem: + +```bash +yarn add cors +``` + +and use it as a middleware: + +```js +import cors from "cors"; + +const app = express(); +app.use(cors()) +``` + +::: + +## Conclusion + +Hopefully by the end of this guide, you should be able to: + +- Write your own logic around Oracles and how to write a JSON RPC server to make them work with your Nargo commands. +- Provide custom foreign call handlers for NoirJS. diff --git a/docs/versioned_docs/version-v0.26.0/how_to/how-to-recursion.md b/docs/versioned_docs/version-v0.26.0/how_to/how-to-recursion.md new file mode 100644 index 00000000000..4c45bb87ae2 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/how_to/how-to-recursion.md @@ -0,0 +1,179 @@ +--- +title: How to use recursion on NoirJS +description: Learn how to implement recursion with NoirJS, a powerful tool for creating smart contracts on the EVM blockchain. This guide assumes familiarity with NoirJS, solidity verifiers, and the Barretenberg proving backend. Discover how to generate both final and intermediate proofs using `noir_js` and `backend_barretenberg`. +keywords: + [ + "NoirJS", + "EVM blockchain", + "smart contracts", + "recursion", + "solidity verifiers", + "Barretenberg backend", + "noir_js", + "backend_barretenberg", + "intermediate proofs", + "final proofs", + "nargo compile", + "json import", + "recursive circuit", + "recursive app" + ] +sidebar_position: 1 +--- + +This guide shows you how to use recursive proofs in your NoirJS app. For the sake of clarity, it is assumed that: + +- You already have a NoirJS app. If you don't, please visit the [NoirJS tutorial](../tutorials/noirjs_app.md) and the [reference](../reference/NoirJS/noir_js/index.md). +- You are familiar with what are recursive proofs and you have read the [recursion explainer](../explainers/explainer-recursion.md) +- You already built a recursive circuit following [the reference](../noir/standard_library/recursion.md), and understand how it works. + +It is also assumed that you're not using `noir_wasm` for compilation, and instead you've used [`nargo compile`](../reference/nargo_commands.md) to generate the `json` you're now importing into your project. However, the guide should work just the same if you're using `noir_wasm`. + +:::info + +As you've read in the [explainer](../explainers/explainer-recursion.md), a recursive proof is an intermediate proof. This means that it doesn't necessarily generate the final step that makes it verifiable in a smart contract. However, it is easy to verify within another circuit. + +While "standard" usage of NoirJS packages abstracts final proofs, it currently lacks the necessary interface to abstract away intermediate proofs. This means that these proofs need to be created by using the backend directly. + +In short: + +- `noir_js` generates *only* final proofs +- `backend_barretenberg` generates both types of proofs + +::: + +In a standard recursive app, you're also dealing with at least two circuits. For the purpose of this guide, we will assume the following: + +- `main`: a circuit of type `assert(x != y)`, where `main` is marked with a `#[recursive]` attribute. This attribute states that the backend should generate proofs that are friendly for verification within another circuit. +- `recursive`: a circuit that verifies `main` + +For a full example on how recursive proofs work, please refer to the [noir-examples](https://github.com/noir-lang/noir-examples) repository. We will *not* be using it as a reference for this guide. + +## Step 1: Setup + +In a common NoirJS app, you need to instantiate a backend with something like `const backend = new Backend(circuit)`. Then you feed it to the `noir_js` interface. + +For recursion, this doesn't happen, and the only need for `noir_js` is only to `execute` a circuit and get its witness and return value. Everything else is not interfaced, so it needs to happen on the `backend` object. + +It is also recommended that you instantiate the backend with as many threads as possible, to allow for maximum concurrency: + +```js +const backend = new Backend(circuit, { threads: 8 }) +``` + +:::tip +You can use the [`os.cpus()`](https://nodejs.org/api/os.html#oscpus) object in `nodejs` or [`navigator.hardwareConcurrency`](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/hardwareConcurrency) on the browser to make the most out of those glorious cpu cores +::: + +## Step 2: Generating the witness and the proof for `main` + +After instantiating the backend, you should also instantiate `noir_js`. We will use it to execute the circuit and get the witness. + +```js +const noir = new Noir(circuit, backend) +const { witness } = noir.execute(input) +``` + +With this witness, you are now able to generate the intermediate proof for the main circuit: + +```js +const { proof, publicInputs } = await backend.generateProof(witness) +``` + +:::warning + +Always keep in mind what is actually happening on your development process, otherwise you'll quickly become confused about what circuit we are actually running and why! + +In this case, you can imagine that Alice (running the `main` circuit) is proving something to Bob (running the `recursive` circuit), and Bob is verifying her proof within his proof. + +With this in mind, it becomes clear that our intermediate proof is the one *meant to be verified within another circuit*, so it must be Alice's. Actually, the only final proof in this theoretical scenario would be the last one, sent on-chain. + +::: + +## Step 3 - Verification and proof artifacts + +Optionally, you are able to verify the intermediate proof: + +```js +const verified = await backend.verifyProof({ proof, publicInputs }) +``` + +This can be useful to make sure our intermediate proof was correctly generated. But the real goal is to do it within another circuit. For that, we need to generate recursive proof artifacts that will be passed to the circuit that is verifying the proof we just generated. Instead of passing the proof and verification key as a byte array, we pass them as fields which makes it cheaper to verify in a circuit: + +```js +const { proofAsFields, vkAsFields, vkHash } = await backend.generateRecursiveProofArtifacts( { publicInputs, proof }, publicInputsCount) +``` + +This call takes the public inputs and the proof, but also the public inputs count. While this is easily retrievable by simply counting the `publicInputs` length, the backend interface doesn't currently abstract it away. + +:::info + +The `proofAsFields` has a constant size `[Field; 93]` and verification keys in Barretenberg are always `[Field; 114]`. + +::: + +:::warning + +One common mistake is to forget *who* makes this call. + +In a situation where Alice is generating the `main` proof, if she generates the proof artifacts and sends them to Bob, which gladly takes them as true, this would mean Alice could prove anything! + +Instead, Bob needs to make sure *he* extracts the proof artifacts, using his own instance of the `main` circuit backend. This way, Alice has to provide a valid proof for the correct `main` circuit. + +::: + +## Step 4 - Recursive proof generation + +With the artifacts, generating a recursive proof is no different from a normal proof. You simply use the `backend` (with the recursive circuit) to generate it: + +```js +const recursiveInputs = { + verification_key: vkAsFields, // array of length 114 + proof: proofAsFields, // array of length 93 + size of public inputs + publicInputs: [mainInput.y], // using the example above, where `y` is the only public input + key_hash: vkHash, +} + +const { witness, returnValue } = noir.execute(recursiveInputs) // we're executing the recursive circuit now! +const { proof, publicInputs } = backend.generateProof(witness) +const verified = backend.verifyProof({ proof, publicInputs }) +``` + +You can obviously chain this proof into another proof. In fact, if you're using recursive proofs, you're probably interested of using them this way! + +:::tip + +Managing circuits and "who does what" can be confusing. To make sure your naming is consistent, you can keep them in an object. For example: + +```js +const circuits = { + main: mainJSON, + recursive: recursiveJSON +} +const backends = { + main: new BarretenbergBackend(circuits.main), + recursive: new BarretenbergBackend(circuits.recursive) +} +const noir_programs = { + main: new Noir(circuits.main, backends.main), + recursive: new Noir(circuits.recursive, backends.recursive) +} +``` + +This allows you to neatly call exactly the method you want without conflicting names: + +```js +// Alice runs this 👇 +const { witness: mainWitness } = await noir_programs.main.execute(input) +const proof = await backends.main.generateProof(mainWitness) + +// Bob runs this 👇 +const verified = await backends.main.verifyProof(proof) +const { proofAsFields, vkAsFields, vkHash } = await backends.main.generateRecursiveProofArtifacts( + proof, + numPublicInputs, +); +const recursiveProof = await noir_programs.recursive.generateProof(recursiveInputs) +``` + +::: diff --git a/docs/versioned_docs/version-v0.26.0/how_to/how-to-solidity-verifier.md b/docs/versioned_docs/version-v0.26.0/how_to/how-to-solidity-verifier.md new file mode 100644 index 00000000000..e3c7c1065da --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/how_to/how-to-solidity-verifier.md @@ -0,0 +1,231 @@ +--- +title: Generate a Solidity Verifier +description: + Learn how to run the verifier as a smart contract on the blockchain. Compile a Solidity verifier + contract for your Noir program and deploy it on any EVM blockchain acting as a verifier smart + contract. Read more to find out +keywords: + [ + solidity verifier, + smart contract, + blockchain, + compiler, + plonk_vk.sol, + EVM blockchain, + verifying Noir programs, + proving backend, + Barretenberg, + ] +sidebar_position: 0 +pagination_next: tutorials/noirjs_app +--- + +Noir has the ability to generate a verifier contract in Solidity, which can be deployed in many EVM-compatible blockchains such as Ethereum. + +This allows for a powerful feature set, as one can make use of the conciseness and the privacy provided by Noir in an immutable ledger. Applications can range from simple P2P guessing games, to complex private DeFi interactions. + +This guide shows you how to generate a Solidity Verifier and deploy it on the [Remix IDE](https://remix.ethereum.org/). It is assumed that: + +- You are comfortable with the Solidity programming language and understand how contracts are deployed on the Ethereum network +- You have Noir installed and you have a Noir program. If you don't, [get started](../getting_started/installation/index.md) with Nargo and the example Hello Noir circuit +- You are comfortable navigating RemixIDE. If you aren't or you need a refresher, you can find some video tutorials [here](https://www.youtube.com/channel/UCjTUPyFEr2xDGN6Cg8nKDaA) that could help you. + +## Rundown + +Generating a Solidity Verifier contract is actually a one-command process. However, compiling it and deploying it can have some caveats. Here's the rundown of this guide: + +1. How to generate a solidity smart contract +2. How to compile the smart contract in the RemixIDE +3. How to deploy it to a testnet + +## Step 1 - Generate a contract + +This is by far the most straight-forward step. Just run: + +```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 to any EVM blockchain acting as a verifier smart contract. + +:::info + +It is possible to generate 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 generation of verifier contracts, for the time being these are only in Solidity. +::: + +## Step 2 - Compiling + +We will mostly skip the details of RemixIDE, as the UI can change from version to version. For now, we can just open +Remix and create a blank workspace. + +![Create Workspace](@site/static/img/how-tos/solidity_verifier_1.png) + +We will create a new file to contain the contract Nargo generated, and copy-paste its content. + +:::warning + +You'll likely see a warning advising you to not trust pasted code. While it is an important warning, it is irrelevant in the context of this guide and can be ignored. We will not be deploying anywhere near a mainnet. + +::: + +To compile our the verifier, we can navigate to the compilation tab: + +![Compilation Tab](@site/static/img/how-tos/solidity_verifier_2.png) + +Remix should automatically match a suitable compiler version. However, hitting the "Compile" button will most likely generate a "Stack too deep" error: + +![Stack too deep](@site/static/img/how-tos/solidity_verifier_3.png) + +This is due to the verify function needing to put many variables on the stack, but enabling the optimizer resolves the issue. To do this, let's open the "Advanced Configurations" tab and enable optimization. The default 200 runs will suffice. + +:::info + +This time we will see a warning about an unused function parameter. This is expected, as the `verify` function doesn't use the `_proof` parameter inside a solidity block, it is loaded from calldata and used in assembly. + +::: + +![Compilation success](@site/static/img/how-tos/solidity_verifier_4.png) + +## Step 3 - Deploying + +At this point we should have a compiled contract read to deploy. If we navigate to the deploy section in Remix, we will see many different environments we can deploy to. The steps to deploy on each environment would be out-of-scope for this guide, so we will just use the default Remix VM. + +Looking closely, we will notice that our "Solidity Verifier" is actually three contracts working together: + +- An `UltraVerificationKey` library which simply stores the verification key for our circuit. +- An abstract contract `BaseUltraVerifier` containing most of the verifying logic. +- A main `UltraVerifier` contract that inherits from the Base and uses the Key contract. + +Remix will take care of the dependencies for us so we can simply deploy the UltraVerifier contract by selecting it and hitting "deploy": + +![Deploying UltraVerifier](@site/static/img/how-tos/solidity_verifier_5.png) + +A contract will show up in the "Deployed Contracts" section, where we can retrieve the Verification Key Hash. This is particularly useful for double-checking the deployer contract is the correct one. + +:::note + +Why "UltraVerifier"? + +To be precise, the Noir compiler (`nargo`) doesn't generate the verifier contract directly. It compiles the Noir code into an intermediate language (ACIR), which is then executed by the backend. So it is the backend that returns the verifier smart contract, not Noir. + +In this case, the Barretenberg Backend uses the UltraPlonk proving system, hence the "UltraVerifier" name. + +::: + +## Step 4 - Verifying + +To verify a proof using the Solidity verifier contract, we call the `verify` function in this extended contract: + +```solidity +function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool) +``` + +When using the default example in the [Hello Noir](../getting_started/hello_noir/index.md) guide, the easiest way to confirm that the verifier contract is doing its job is by calling the `verify` function via remix with the required parameters. For `_proof`, run `nargo prove` and use the string in `proof/.proof` (adding the hex `0x` prefix). We can also copy the public input from `Verifier.toml`, as it will be properly formatted as 32-byte strings: + +``` +0x...... , [0x0000.....02] +``` + +A programmatic example of how the `verify` function is called can be seen 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"); +``` + +:::info[Return Values] + +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. + +For example, if you have Noir program like this: + +```rust +fn main( + // Public inputs + pubkey_x: pub Field, + pubkey_y: pub Field, + // Private inputs + priv_key: Field, +) -> pub Field +``` + +the `verify` function will expect the public inputs array (second function parameter) to be of length 3, the two inputs and the return value. Like before, these values are populated in Verifier.toml after running `nargo prove`. + +Passing only two inputs will result in an error such as `PUBLIC_INPUT_COUNT_INVALID(3, 2)`. + +In this case, the inputs parameter to `verify` would be an array ordered as `[pubkey_x, pubkey_y, return]`. + +::: + +:::tip[Structs] + +You can pass structs to the verifier contract. They will be flattened so that the array of inputs is 1-dimensional array. + +For example, 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) { + //... +} +``` + +The order of these inputs would be flattened to: `[x, nested.t1.val1, nested.t1.val2, nested.is_true, y]` + +::: + +The other function you can call is our entrypoint `verify` function, as defined above. + +:::tip + +It's worth noticing that the `verify` function is actually a `view` function. A `view` function does not alter the blockchain state, so it doesn't need to be distributed (i.e. it will run only on the executing node), and therefore doesn't cost any gas. + +This can be particularly useful in some situations. If Alice generated a proof and wants Bob to verify its correctness, Bob doesn't need to run Nargo, NoirJS, or any Noir specific infrastructure. He can simply make a call to the blockchain with the proof and verify it is correct without paying any gas. + +It would be incorrect to say that a Noir proof verification costs any gas at all. However, most of the time the result of `verify` is used to modify state (for example, to update a balance, a game state, etc). In that case the whole network needs to execute it, which does incur gas costs (calldata and execution, but not storage). + +::: + +## A Note on EVM chains + +ZK-SNARK verification depends on some precompiled cryptographic primitives such as Elliptic Curve Pairings (if you like complex math, you can read about EC Pairings [here](https://medium.com/@VitalikButerin/exploring-elliptic-curve-pairings-c73c1864e627)). Not all EVM chains support EC Pairings, notably some of the ZK-EVMs. This means that you won't be able to use the verifier contract in all of them. + +For example, chains like `zkSync ERA` and `Polygon zkEVM` do not currently support these precompiles, so proof verification via Solidity verifier contracts won't work. Here's a quick list of EVM chains that have been tested and are known to work: + +- Optimism +- Arbitrum +- Polygon PoS +- Scroll +- Celo + +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. + +## What's next + +Now that you know how to call a Noir Solidity Verifier on a smart contract using Remix, you should be comfortable with using it with some programmatic frameworks, such as [hardhat](https://github.com/noir-lang/noir-starter/tree/main/vite-hardhat) and [foundry](https://github.com/noir-lang/noir-starter/tree/main/with-foundry). + +You can find other tools, examples, boilerplates and libraries in the [awesome-noir](https://github.com/noir-lang/awesome-noir) repository. + +You should also be ready to write and deploy your first NoirJS app and start generating proofs on websites, phones, and NodeJS environments! Head on to the [NoirJS tutorial](../tutorials/noirjs_app.md) to learn how to do that. diff --git a/docs/versioned_docs/version-v0.26.0/how_to/merkle-proof.mdx b/docs/versioned_docs/version-v0.26.0/how_to/merkle-proof.mdx new file mode 100644 index 00000000000..003c7019a93 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/how_to/merkle-proof.mdx @@ -0,0 +1,48 @@ +--- +title: Prove Merkle Tree Membership +description: + Learn how to use merkle membership proof in Noir to prove that a given leaf is a member of a + merkle tree with a specified root, at a given index. +keywords: + [merkle proof, merkle membership proof, Noir, rust, hash function, Pedersen, sha256, merkle tree] +--- + +Let's walk through an example of a merkle membership proof in Noir that proves that a given leaf is +in a merkle tree. + +```rust +use dep::std; + +fn main(message : [Field; 62], index : Field, hashpath : [Field; 40], root : Field) { + let leaf = std::hash::hash_to_field(message.as_slice()); + 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.as_slice()); +``` + +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.26.0/how_to/using-devcontainers.mdx b/docs/versioned_docs/version-v0.26.0/how_to/using-devcontainers.mdx new file mode 100644 index 00000000000..727ec6ca667 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/how_to/using-devcontainers.mdx @@ -0,0 +1,110 @@ +--- +title: Developer Containers and Codespaces +description: "Learn how to set up a devcontainer in your GitHub repository for a seamless coding experience with Codespaces. Follow our easy 8-step guide to create your own Noir environment without installing Nargo locally." +keywords: ["Devcontainer", "Codespaces", "GitHub", "Noir Environment", "Docker Image", "Development Environment", "Remote Coding", "GitHub Codespaces", "Noir Programming", "Nargo", "VSCode Extensions", "Noirup"] +sidebar_position: 1 +--- + +Adding a developer container configuration file to your Noir project is one of the easiest way to unlock coding in browser. + +## What's a devcontainer after all? + +A [Developer Container](https://containers.dev/) (devcontainer for short) is a Docker image that comes preloaded with tools, extensions, and other tools you need to quickly get started or continue a project, without having to install Nargo locally. Think of it as a development environment in a box. + +There are many advantages to this: + +- It's platform and architecture agnostic +- You don't need to have an IDE installed, or Nargo, or use a terminal at all +- It's safer for using on a public machine or public network + +One of the best ways of using devcontainers is... not using your machine at all, for maximum control, performance, and ease of use. +Enter Codespaces. + +## Codespaces + +If a devcontainer is just a Docker image, then what stops you from provisioning a `p3dn.24xlarge` AWS EC2 instance with 92 vCPUs and 768 GiB RAM and using it to prove your 10-gate SNARK proof? + +Nothing! Except perhaps the 30-40$ per hour it will cost you. + +The problem is that provisioning takes time, and I bet you don't want to see the AWS console every time you want to code something real quick. + +Fortunately, there's an easy and free way to get a decent remote machine ready and loaded in less than 2 minutes: Codespaces. [Codespaces is a Github feature](https://github.com/features/codespaces) that allows you to code in a remote machine by using devcontainers, and it's pretty cool: + +- You can start coding Noir in less than a minute +- It uses the resources of a remote machine, so you can code on your grandma's phone if needed be +- It makes it easy to share work with your frens +- It's fully reusable, you can stop and restart whenever you need to + +:::info + +Don't take out your wallet just yet. Free GitHub accounts get about [15-60 hours of coding](https://github.com/features/codespaces) for free per month, depending on the size of your provisioned machine. + +::: + +## Tell me it's _actually_ easy + +It is! + +Github comes with a default codespace and you can use it to code your own devcontainer. That's exactly what we will be doing in this guide. + + + +8 simple steps: + +#### 1. Create a new repository on GitHub. + +#### 2. Click "Start coding with Codespaces". This will use the default image. + +#### 3. Create a folder called `.devcontainer` in the root of your repository. + +#### 4. Create a Dockerfile in that folder, and paste the following code: + +```docker +FROM --platform=linux/amd64 node:lts-bookworm-slim +SHELL ["/bin/bash", "-c"] +RUN apt update && apt install -y curl bash git tar gzip libc++-dev +RUN curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash +ENV PATH="/root/.nargo/bin:$PATH" +RUN noirup +ENTRYPOINT ["nargo"] +``` +#### 5. Create a file called `devcontainer.json` in the same folder, and paste the following code: + +```json +{ + "name": "Noir on Codespaces", + "build": { + "context": ".", + "dockerfile": "Dockerfile" + }, + "customizations": { + "vscode": { + "extensions": ["noir-lang.vscode-noir"] + } + } +} +``` +#### 6. Commit and push your changes + +This will pull the new image and build it, so it could take a minute or so + +#### 8. Done! +Just wait for the build to finish, and there's your easy Noir environment. + + +Refer to [noir-starter](https://github.com/noir-lang/noir-starter/) as an example of how devcontainers can be used together with codespaces. + + + +## How do I use it? + +Using the codespace is obviously much easier than setting it up. +Just navigate to your repository and click "Code" -> "Open with Codespaces". It should take a few seconds to load, and you're ready to go. + +:::info + +If you really like the experience, you can add a badge to your readme, links to existing codespaces, and more. +Check out the [official docs](https://docs.github.com/en/codespaces/setting-up-your-project-for-codespaces/setting-up-your-repository/facilitating-quick-creation-and-resumption-of-codespaces) for more info. diff --git a/docs/versioned_docs/version-v0.26.0/index.mdx b/docs/versioned_docs/version-v0.26.0/index.mdx new file mode 100644 index 00000000000..75086ddcdde --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/index.mdx @@ -0,0 +1,67 @@ +--- +title: Noir Lang +hide_title: true +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] +sidebar_position: 0 +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +Noir Logo + +Noir is a Domain-Specific Language for SNARK proving systems developed by [Aztec Labs](https://aztec.network/). It allows you to generate complex Zero-Knowledge Programs (ZKP) by using simple and flexible syntax, requiring no previous knowledge on the underlying mathematics or cryptography. + +ZK programs are programs that can generate short proofs of a certain statement without revealing some details about it. You can read more about ZKPs [here](https://dev.to/spalladino/a-beginners-intro-to-coding-zero-knowledge-proofs-c56). + +## What's new about Noir? + +Noir works differently from most ZK languages by taking a two-pronged path. First, it compiles the program to an adaptable intermediate language known as ACIR. From there, depending on a given project's needs, ACIR can be further compiled into an arithmetic circuit for integration with the proving backend. + +:::info + +Noir is backend agnostic, which means it makes no assumptions on which proving backend powers the ZK proof. Being the language that powers [Aztec Contracts](https://docs.aztec.network/developers/contracts/main), it defaults to Aztec's Barretenberg proving backend. + +However, the ACIR output can be transformed to be compatible with other PLONK-based backends, or into a [rank-1 constraint system](https://www.rareskills.io/post/rank-1-constraint-system) suitable for backends such as Arkwork's Marlin. + +::: + +## Who is Noir for? + +Noir can be used both in complex cloud-based backends and in user's smartphones, requiring no knowledge on the underlying math or cryptography. From authorization systems that keep a password in the user's device, to complex on-chain verification of recursive proofs, Noir is designed to abstract away complexity without any significant overhead. Here are some examples of situations where Noir can be used: + + + + Noir Logo + + Aztec Contracts leverage Noir to allow for the storage and execution of private information. Writing an Aztec Contract is as easy as writing Noir, and Aztec developers can easily interact with the network storage and execution through the [Aztec.nr](https://docs.aztec.network/developers/contracts/main) library. + + + Soliditry Verifier Example + Noir can auto-generate Solidity verifier contracts that verify Noir proofs. This allows for non-interactive verification of proofs containing private information in an immutable system. This feature powers a multitude of use-case scenarios, from P2P chess tournaments, to [Aztec Layer-2 Blockchain](https://docs.aztec.network/) + + + Aztec Labs developed NoirJS, an easy interface to generate and verify Noir proofs in a Javascript environment. This allows for Noir to be used in webpages, mobile apps, games, and any other environment supporting JS execution in a standalone manner. + + + + +## Libraries + +Noir is meant to be easy to extend by simply importing Noir libraries just like in Rust. +The [awesome-noir repo](https://github.com/noir-lang/awesome-noir#libraries) is a collection of libraries developed by the Noir community. +Writing a new library is easy and makes code be composable and easy to reuse. See the section on [dependencies](noir/modules_packages_crates/dependencies.md) for more information. diff --git a/docs/versioned_docs/version-v0.26.0/migration_notes.md b/docs/versioned_docs/version-v0.26.0/migration_notes.md new file mode 100644 index 00000000000..6bd740024e5 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/migration_notes.md @@ -0,0 +1,105 @@ +--- +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. + +### `backend encountered an error: libc++.so.1` + +Depending on your OS, you may encounter the following error when running `nargo prove` for the first time: + +```text +The backend encountered an error: "/home/codespace/.nargo/backends/acvm-backend-barretenberg/backend_binary: error while loading shared libraries: libc++.so.1: cannot open shared object file: No such file or directory\n" +``` + +Install the `libc++-dev` library with: + +```bash +sudo apt install libc++-dev +``` + +## ≥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](noir/concepts/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 your 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 file is running [this bash script](https://github.com/noir-lang/barretenberg-js-binary/blob/master/run-bb-js.sh), where we need to gzip it as the Nargo currently expect the backend to be zipped up. + +Then run: + +``` +DESIRED_BINARY_VERSION=0.8.1 nargo info +``` + +This overrides the bb native binary with a bb.js node application instead, which should be compatible with most if not all hardware. This does come with the drawback of being generally slower than native binary. + +0.8.1 indicates bb.js version 0.8.1, so if you change that it will update to a different version or the default version in the script if none was supplied. diff --git a/docs/versioned_docs/version-v0.26.0/noir/concepts/_category_.json b/docs/versioned_docs/version-v0.26.0/noir/concepts/_category_.json new file mode 100644 index 00000000000..7da08f8a8c5 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/noir/concepts/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Concepts", + "position": 0, + "collapsible": true, + "collapsed": true +} \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.26.0/noir/concepts/assert.md b/docs/versioned_docs/version-v0.26.0/noir/concepts/assert.md new file mode 100644 index 00000000000..bcff613a695 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/noir/concepts/assert.md @@ -0,0 +1,45 @@ +--- +title: Assert Function +description: + Learn about the assert function in Noir, which can be used to explicitly constrain the predicate or + comparison expression that follows to be true, and what happens if the expression is false at + runtime. +keywords: [Noir programming language, assert statement, predicate expression, comparison expression] +sidebar_position: 4 +--- + +Noir includes a special `assert` function which will explicitly constrain the predicate/comparison +expression that follows to be true. If this expression is false at runtime, the program will fail to +be proven. Example: + +```rust +fn main(x : Field, y : Field) { + assert(x == y); +} +``` + +> 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`. + +You can optionally provide a message to be logged when the assertion fails: + +```rust +assert(x == y, "x and y are not equal"); +``` + +Aside string literals, the optional message can be a format string or any other type supported as input for Noir's [print](../standard_library/logging.md) functions. This feature lets you incorporate runtime variables into your failed assertion logs: + +```rust +assert(x == y, f"Expected x == y, but got {x} == {y}"); +``` + +Using a variable as an assertion message directly: + +```rust +struct myStruct { + myField: Field +} + +let s = myStruct { myField: y }; +assert(s.myField == x, s); +``` + diff --git a/docs/versioned_docs/version-v0.26.0/noir/concepts/comments.md b/docs/versioned_docs/version-v0.26.0/noir/concepts/comments.md new file mode 100644 index 00000000000..b51a85f5c94 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/noir/concepts/comments.md @@ -0,0 +1,33 @@ +--- +title: Comments +description: + Learn how to write comments in Noir programming language. A comment is a line of code that is + ignored by the compiler, but it can be read by programmers. Single-line and multi-line comments + are supported in Noir. +keywords: [Noir programming language, comments, single-line comments, multi-line comments] +sidebar_position: 10 +--- + +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.26.0/noir/concepts/control_flow.md b/docs/versioned_docs/version-v0.26.0/noir/concepts/control_flow.md new file mode 100644 index 00000000000..045d3c3a5f5 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/noir/concepts/control_flow.md @@ -0,0 +1,77 @@ +--- +title: Control Flow +description: + Learn how to use loops and if expressions in the Noir programming language. Discover the syntax + and examples for for loops and if-else statements. +keywords: [Noir programming language, loops, for loop, if-else statements, Rust syntax] +sidebar_position: 2 +--- + +## 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); +``` + +## 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`. + +### Break and Continue + +In unconstrained code, `break` and `continue` are also allowed in `for` loops. These are only allowed +in unconstrained code since normal constrained code requires that Noir knows exactly how many iterations +a loop may have. `break` and `continue` can be used like so: + +```rust +for i in 0 .. 10 { + println("Iteration start") + + if i == 2 { + continue; + } + + if i == 5 { + break; + } + + println(i); +} +println("Loop end") +``` + +When used, `break` will end the current loop early and jump to the statement after the for loop. In the example +above, the `break` will stop the loop and jump to the `println("Loop end")`. + +`continue` will stop the current iteration of the loop, and jump to the start of the next iteration. In the example +above, `continue` will jump to `println("Iteration start")` when used. Note that the loop continues as normal after this. +The iteration variable `i` is still increased by one as normal when `continue` is used. + +`break` and `continue` cannot currently be used to jump out of more than a single loop at a time. diff --git a/docs/versioned_docs/version-v0.26.0/noir/concepts/data_bus.md b/docs/versioned_docs/version-v0.26.0/noir/concepts/data_bus.md new file mode 100644 index 00000000000..e54fc861257 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/noir/concepts/data_bus.md @@ -0,0 +1,21 @@ +--- +title: Data Bus +sidebar_position: 13 +--- +**Disclaimer** this feature is experimental, do not use it! + +The data bus is an optimization that the backend can use to make recursion more efficient. +In order to use it, you must define some inputs of the program entry points (usually the `main()` +function) with the `call_data` modifier, and the return values with the `return_data` modifier. +These modifiers are incompatible with `pub` and `mut` modifiers. + +## Example + +```rust +fn main(mut x: u32, y: call_data u32, z: call_data [u32;4] ) -> return_data u32 { + let a = z[x]; + a+y +} +``` + +As a result, both call_data and return_data will be treated as private inputs and encapsulated into a read-only array each, for the backend to process. diff --git a/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/_category_.json b/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/_category_.json new file mode 100644 index 00000000000..5d694210bbf --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 0, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/arrays.md b/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/arrays.md new file mode 100644 index 00000000000..efce3e95d32 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/arrays.md @@ -0,0 +1,251 @@ +--- +title: Arrays +description: + Dive into the Array data type in Noir. Grasp its methods, practical examples, and best practices for efficiently using Arrays in your Noir code. +keywords: + [ + noir, + array type, + methods, + examples, + indexing, + ] +sidebar_position: 4 +--- + +An array is one way of grouping together values into one compound type. Array types can be inferred +or explicitly specified via the syntax `[; ]`: + +```rust +fn main(x : Field, y : Field) { + let my_arr = [x, y]; + let your_arr: [Field; 2] = [x, y]; +} +``` + +Here, both `my_arr` and `your_arr` are instantiated as an array containing two `Field` elements. + +Array elements can be accessed using indexing: + +```rust +fn main() { + let a = [1, 2, 3, 4, 5]; + + let first = a[0]; + let second = a[1]; +} +``` + +All elements in an array must be of the same type (i.e. homogeneous). That is, an array cannot group +a `Field` value and a `u8` value together for example. + +You can write mutable arrays, like: + +```rust +fn main() { + let mut arr = [1, 2, 3, 4, 5]; + assert(arr[0] == 1); + + arr[0] = 42; + assert(arr[0] == 42); +} +``` + +You can instantiate a new array of a fixed size with the same value repeated for each element. The following example instantiates an array of length 32 where each element is of type Field and has the value 0. + +```rust +let array: [Field; 32] = [0; 32]; +``` + +Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices), you can just call `as_slice` on your array: + +```rust +let array: [Field; 32] = [0; 32]; +let sl = array.as_slice() +``` + +You can define multidimensional arrays: + +```rust +let array : [[Field; 2]; 2]; +let element = array[0][0]; +``` +However, multidimensional slices are not supported. For example, the following code will error at compile time: +```rust +let slice : [[Field]] = &[]; +``` + +## 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. +Each of these functions are located within the generic impl `impl [T; N] {`. +So anywhere `self` appears, it refers to the variable `self: [T; N]`. + +### len + +Returns the length of an array + +```rust +fn len(self) -> 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(self) -> [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(self, 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(self, 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(self, 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(self, 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(self, 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(self, 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.26.0/noir/concepts/data_types/booleans.md b/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/booleans.md new file mode 100644 index 00000000000..69826fcd724 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/booleans.md @@ -0,0 +1,31 @@ +--- +title: Booleans +description: + Delve into the Boolean data type in Noir. Understand its methods, practical examples, and best practices for using Booleans in your Noir programs. +keywords: + [ + noir, + boolean type, + methods, + examples, + logical operations, + ] +sidebar_position: 2 +--- + + +The `bool` type in Noir has two possible values: `true` and `false`: + +```rust +fn main() { + let t = true; + let f: bool = false; +} +``` + +> **Note:** When returning a boolean value, it will show up as a value of 1 for `true` and 0 for +> `false` in _Verifier.toml_. + +The boolean type is most commonly used in conditionals like `if` expressions and `assert` +statements. More about conditionals is covered in the [Control Flow](../control_flow) and +[Assert Function](../assert) sections. diff --git a/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/fields.md b/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/fields.md new file mode 100644 index 00000000000..a10a4810788 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/fields.md @@ -0,0 +1,192 @@ +--- +title: Fields +description: + Dive deep into the Field data type in Noir. Understand its methods, practical examples, and best practices to effectively use Fields in your Noir programs. +keywords: + [ + noir, + field type, + methods, + examples, + best practices, + ] +sidebar_position: 0 +--- + +The field type corresponds to the native field type of the proving backend. + +The size of a Noir field depends on the elliptic curve's finite field for the proving backend +adopted. For example, a field would be a 254-bit integer when paired with the default backend that +spans the Grumpkin curve. + +Fields support integer arithmetic and are often used as the default numeric type in Noir: + +```rust +fn main(x : Field, y : Field) { + let z = x + y; +} +``` + +`x`, `y` and `z` are all private fields in this example. Using the `let` keyword we defined a new +private value `z` constrained to be equal to `x + y`. + +If proving efficiency is of priority, fields should be used as a default for solving problems. +Smaller integer types (e.g. `u64`) incur extra range constraints. + +## Methods + +After declaring a Field, you can use these common methods on it: + +### to_le_bits + +Transforms the field into an array of bits, Little Endian. + +```rust +fn to_le_bits(_x : Field, _bit_size: u32) -> [u1] +``` + +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] +``` + +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); +} +``` + +### assert_max_bit_size + +Adds a constraint to specify that the field can be represented with `bit_size` number of bits + +```rust +fn assert_max_bit_size(self, bit_size: u32) +``` + +example: + +```rust +fn main() { + let field = 2 + field.assert_max_bit_size(32); +} +``` + +### 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 +``` + + +### lt + +Returns true if the field is less than the other field + +```rust +pub fn lt(self, another: Field) -> bool +``` diff --git a/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/function_types.md b/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/function_types.md new file mode 100644 index 00000000000..f6121af17e2 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/function_types.md @@ -0,0 +1,26 @@ +--- +title: Function types +sidebar_position: 10 +--- + +Noir supports higher-order functions. The syntax for a function type is as follows: + +```rust +fn(arg1_type, arg2_type, ...) -> return_type +``` + +Example: + +```rust +fn assert_returns_100(f: fn() -> Field) { // f takes no args and returns a Field + assert(f() == 100); +} + +fn main() { + assert_returns_100(|| 100); // ok + assert_returns_100(|| 150); // fails +} +``` + +A function type also has an optional capture environment - this is necessary to support closures. +See [Lambdas](../lambdas.md) for more details. diff --git a/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/index.md b/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/index.md new file mode 100644 index 00000000000..357813c147a --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/index.md @@ -0,0 +1,110 @@ +--- +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](../generics.md): + +```rust +type Id = Size; + +fn main() { + let id: Id = 1; + let zero: u32 = 0; + assert(zero + 1 == id); +} +``` + +Type aliases can even refer to other aliases. An error will be issued if they form a cycle: + +```rust +// Ok! +type A = B; +type B = Field; + +type Bad1 = Bad2; + +// error: Dependency cycle found +type Bad2 = Bad1; +// ^^^^^^^^^^^ 'Bad2' recursively depends on itself: Bad2 -> Bad1 -> Bad2 +``` + +### BigInt + +You can achieve BigInt functionality using the [Noir BigInt](https://github.com/shuklaayush/noir-bigint) library. diff --git a/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/integers.md b/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/integers.md new file mode 100644 index 00000000000..1c6b375db49 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/integers.md @@ -0,0 +1,155 @@ +--- +title: Integers +description: Explore the Integer data type in Noir. Learn about its methods, see real-world examples, and grasp how to efficiently use Integers in your Noir code. +keywords: [noir, integer types, methods, examples, arithmetic] +sidebar_position: 1 +--- + +An integer type is a range constrained field type. The Noir frontend supports both unsigned and signed integer types. The allowed sizes are 1, 8, 32 and 64 bits. + +:::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\\$). + +## 128 bits Unsigned Integers + +The built-in structure `U128` allows you to use 128-bit unsigned integers almost like a native integer type. However, there are some differences to keep in mind: +- You cannot cast between a native integer and `U128` +- There is a higher performance cost when using `U128`, compared to a native type. + +Conversion between unsigned integer types and U128 are done through the use of `from_integer` and `to_integer` functions. `from_integer` also accepts the `Field` type as input. + +```rust +fn main() { + let x = U128::from_integer(23); + let y = U128::from_hex("0x7"); + let z = x + y; + assert(z.to_integer() == 30); +} +``` + +`U128` is implemented with two 64 bits limbs, representing the low and high bits, which explains the performance cost. You should expect `U128` to be twice more costly for addition and four times more costly for multiplication. +You can construct a U128 from its limbs: +```rust +fn main(x: u64, y: u64) { + let x = U128::from_u64s_be(x,y); + assert(z.hi == x as Field); + assert(z.lo == y as Field); +} +``` + +Note that the limbs are stored as Field elements in order to avoid unnecessary conversions. +Apart from this, most operations will work as usual: + +```rust +fn main(x: U128, y: U128) { + // multiplication + let c = x * y; + // addition and subtraction + let c = c - x + y; + // division + let c = x / y; + // bit operation; + let c = x & y | y; + // bit shift + let c = x << y; + // comparisons; + let c = x < y; + let c = x == y; +} +``` + +## 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.26.0/noir/concepts/data_types/references.md b/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/references.md new file mode 100644 index 00000000000..a5293d11cfb --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/references.md @@ -0,0 +1,23 @@ +--- +title: References +sidebar_position: 9 +--- + +Noir supports first-class references. References are a bit like pointers: they point to a specific address that can be followed to access the data stored at that address. You can use Rust-like syntax to use pointers in Noir: the `&` operator references the variable, the `*` operator dereferences it. + +Example: + +```rust +fn main() { + let mut x = 2; + + // you can reference x as &mut and pass it to multiplyBy2 + multiplyBy2(&mut x); +} + +// you can access &mut here +fn multiplyBy2(x: &mut Field) { + // and dereference it with * + *x = *x * 2; +} +``` diff --git a/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/slices.mdx b/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/slices.mdx new file mode 100644 index 00000000000..828faf4a8f8 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/slices.mdx @@ -0,0 +1,170 @@ +--- +title: Slices +description: Explore the Slice data type in Noir. Understand its methods, see real-world examples, and learn how to effectively use Slices in your Noir programs. +keywords: [noir, slice type, methods, examples, subarrays] +sidebar_position: 5 +--- + +import Experimental from '@site/src/components/Notes/_experimental.mdx'; + + + +A slice is a dynamically-sized view into a sequence of elements. They can be resized at runtime, but because they don't own the data, they cannot be returned from a circuit. You can treat slices as arrays without a constrained size. + +```rust +use dep::std::slice; + +fn main() -> pub Field { + let mut slice: [Field] = &[0; 2]; + + let mut new_slice = slice.push_back(6); + new_slice.len() +} +``` + +To write a slice literal, use a preceeding ampersand as in: `&[0; 2]` or +`&[1, 2, 3]`. + +It is important to note that slices are not references to arrays. In Noir, +`&[..]` is more similar to an immutable, growable vector. + +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); +``` + +### len + +Returns the length of a slice + +```rust +fn len(self) -> Field +``` + +Example: + +```rust +fn main() { + let slice = &[42, 42]; + assert(slice.len() == 2); +} +``` diff --git a/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/strings.md b/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/strings.md new file mode 100644 index 00000000000..311dfd64416 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/strings.md @@ -0,0 +1,80 @@ +--- +title: Strings +description: + Discover the String data type in Noir. Learn about its methods, see real-world examples, and understand how to effectively manipulate and use Strings in Noir. +keywords: + [ + noir, + string type, + methods, + examples, + concatenation, + ] +sidebar_position: 3 +--- + + +The string type is a fixed length value defined with `str`. + +You can use strings in `assert()` functions or print them with +`println()`. See more about [Logging](../../standard_library/logging). + +```rust +use dep::std; + +fn main(message : pub str<11>, hex_as_string : str<4>) { + println(message); + assert(message == "hello world"); + assert(hex_as_string == "0x41"); +} +``` + +You can convert a `str` to a byte array by calling `as_bytes()` +or a vector by calling `as_bytes_vec()`. + +```rust +fn main() { + let message = "hello world"; + let message_bytes = message.as_bytes(); + let mut message_vec = message.as_bytes_vec(); + assert(message_bytes.len() == 11); + assert(message_bytes[0] == 104); + assert(message_bytes[0] == message_vec.get(0)); +} +``` + +## Escape characters + +You can use escape characters for your strings: + +| Escape Sequence | Description | +|-----------------|-----------------| +| `\r` | Carriage Return | +| `\n` | Newline | +| `\t` | Tab | +| `\0` | Null Character | +| `\"` | Double Quote | +| `\\` | Backslash | + +Example: + +```rust +let s = "Hello \"world" // prints "Hello "world" +let s = "hey \tyou"; // prints "hey you" +``` + +## Raw strings + +A raw string begins with the letter `r` and is optionally delimited by a number of hashes `#`. + +Escape characters are *not* processed within raw strings. All contents are interpreted literally. + +Example: + +```rust +let s = r"Hello world"; +let s = r#"Simon says "hello world""#; + +// Any number of hashes may be used (>= 1) as long as the string also terminates with the same number of hashes +let s = r#####"One "#, Two "##, Three "###, Four "####, Five will end the string."#####; +``` diff --git a/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/structs.md b/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/structs.md new file mode 100644 index 00000000000..dbf68c99813 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/structs.md @@ -0,0 +1,70 @@ +--- +title: Structs +description: + Explore the Struct data type in Noir. Learn about its methods, see real-world examples, and grasp how to effectively define and use Structs in your Noir programs. +keywords: + [ + noir, + struct type, + methods, + examples, + data structures, + ] +sidebar_position: 8 +--- + +A struct also allows for grouping multiple values of different types. Unlike tuples, we can also +name each field. + +> **Note:** The usage of _field_ here refers to each element of the struct and is unrelated to the +> field type of Noir. + +Defining a struct requires giving it a name and listing each field within as `: ` pairs: + +```rust +struct Animal { + hands: Field, + legs: Field, + eyes: u8, +} +``` + +An instance of a struct can then be created with actual values in `: ` pairs in any +order. Struct fields are accessible using their given names: + +```rust +fn main() { + let legs = 4; + + let dog = Animal { + eyes: 2, + hands: 0, + legs, + }; + + let zero = dog.hands; +} +``` + +Structs can also be destructured in a pattern, binding each field to a new variable: + +```rust +fn main() { + let Animal { hands, legs: feet, eyes } = get_octopus(); + + let ten = hands + feet + eyes as u8; +} + +fn get_octopus() -> Animal { + let octopus = Animal { + hands: 0, + legs: 8, + eyes: 2, + }; + + octopus +} +``` + +The new variables can be bound with names different from the original struct field names, as +showcased in the `legs --> feet` binding in the example above. diff --git a/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/tuples.md b/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/tuples.md new file mode 100644 index 00000000000..2ec5c9c4113 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/tuples.md @@ -0,0 +1,48 @@ +--- +title: Tuples +description: + Dive into the Tuple data type in Noir. Understand its methods, practical examples, and best practices for efficiently using Tuples in your Noir code. +keywords: + [ + noir, + tuple type, + methods, + examples, + multi-value containers, + ] +sidebar_position: 7 +--- + +A tuple collects multiple values like an array, but with the added ability to collect values of +different types: + +```rust +fn main() { + let tup: (u8, u64, Field) = (255, 500, 1000); +} +``` + +One way to access tuple elements is via destructuring using pattern matching: + +```rust +fn main() { + let tup = (1, 2); + + let (one, two) = tup; + + let three = one + two; +} +``` + +Another way to access tuple elements is via direct member access, using a period (`.`) followed by +the index of the element we want to access. Index `0` corresponds to the first tuple element, `1` to +the second and so on: + +```rust +fn main() { + let tup = (5, 6, 7, 8); + + let five = tup.0; + let eight = tup.3; +} +``` diff --git a/docs/versioned_docs/version-v0.26.0/noir/concepts/distinct.md b/docs/versioned_docs/version-v0.26.0/noir/concepts/distinct.md new file mode 100644 index 00000000000..6c993b8b5e0 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/noir/concepts/distinct.md @@ -0,0 +1,64 @@ +--- +title: Distinct Witnesses +sidebar_position: 11 +--- + +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.26.0/noir/concepts/functions.md b/docs/versioned_docs/version-v0.26.0/noir/concepts/functions.md new file mode 100644 index 00000000000..2c9bc33fdfc --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/noir/concepts/functions.md @@ -0,0 +1,226 @@ +--- +title: Functions +description: + Learn how to declare functions and methods in Noir, a programming language with Rust semantics. + This guide covers parameter declaration, return types, call expressions, and more. +keywords: [Noir, Rust, functions, methods, parameter declaration, return types, call expressions] +sidebar_position: 1 +--- + +Functions in Noir follow the same semantics of Rust, though Noir does not support early returns. + +To declare a function the `fn` keyword is used. + +```rust +fn foo() {} +``` + +By default, functions are visible only within the package they are defined. To make them visible outside of that package (for example, as part of a [library](../modules_packages_crates/crates_and_packages.md#libraries)), you should mark them as `pub`: + +```rust +pub fn foo() {} +``` + +You can also restrict the visibility of the function to only the crate it was defined in, by specifying `pub(crate)`: + +```rust +pub(crate) fn foo() {} //foo can only be called within its crate +``` + +All parameters in a function must have a type and all types are known at compile time. The parameter +is pre-pended with a colon and the parameter type. Multiple parameters are separated using a comma. + +```rust +fn foo(x : Field, y : Field){} +``` + +The return type of a function can be stated by using the `->` arrow notation. The function below +states that the foo function must return a `Field`. If the function returns no value, then the arrow +is omitted. + +```rust +fn foo(x : Field, y : Field) -> Field { + x + y +} +``` + +Note that a `return` keyword is unneeded in this case - the last expression in a function's body is +returned. + +## Main function + +If you're writing a binary, the `main` function is the starting point of your program. You can pass all types of expressions to it, as long as they have a fixed size at compile time: + +```rust +fn main(x : Field) // this is fine: passing a Field +fn main(x : [Field; 2]) // this is also fine: passing a Field with known size at compile-time +fn main(x : (Field, bool)) // 👌: passing a (Field, bool) tuple means size 2 +fn main(x : str<5>) // this is fine, as long as you pass a string of size 5 + +fn main(x : Vec) // can't compile, has variable size +fn main(x : [Field]) // can't compile, has variable size +fn main(....// i think you got it by now +``` + +Keep in mind [tests](../../getting_started/tooling/testing.md) don't differentiate between `main` and any other function. The following snippet passes tests, but won't compile or prove: + +```rust +fn main(x : [Field]) { + assert(x[0] == 1); +} + +#[test] +fn test_one() { + main(&[1, 2]); +} +``` + +```bash +$ nargo test +[testing] Running 1 test functions +[testing] Testing test_one... ok +[testing] All tests passed + +$ nargo check +The application panicked (crashed). +Message: Cannot have variable sized arrays as a parameter to main +``` + +## Call Expressions + +Calling a function in Noir is executed by using the function name and passing in the necessary +arguments. + +Below we show how to call the `foo` function from the `main` function using a call expression: + +```rust +fn main(x : Field, y : Field) { + let z = foo(x); +} + +fn foo(x : Field) -> Field { + x + x +} +``` + +## Methods + +You can define methods in Noir on any struct type in scope. + +```rust +struct MyStruct { + foo: Field, + bar: Field, +} + +impl MyStruct { + fn new(foo: Field) -> MyStruct { + MyStruct { + foo, + bar: 2, + } + } + + fn sum(self) -> Field { + self.foo + self.bar + } +} + +fn main() { + let s = MyStruct::new(40); + assert(s.sum() == 42); +} +``` + +Methods are just syntactic sugar for functions, so if we wanted to we could also call `sum` as +follows: + +```rust +assert(MyStruct::sum(s) == 42); +``` + +It is also possible to specialize which method is chosen depending on the [generic](./generics.md) type that is used. In this example, the `foo` function returns different values depending on its type: + +```rust +struct Foo {} + +impl Foo { + fn foo(self) -> Field { 1 } +} + +impl Foo { + fn foo(self) -> Field { 2 } +} + +fn main() { + let f1: Foo = Foo{}; + let f2: Foo = Foo{}; + assert(f1.foo() + f2.foo() == 3); +} +``` + +Also note that impls with the same method name defined in them cannot overlap. For example, if we already have `foo` defined for `Foo` and `Foo` like we do above, we cannot also define `foo` in an `impl Foo` since it would be ambiguous which version of `foo` to choose. + +```rust +// Including this impl in the same project as the above snippet would +// cause an overlapping impls error +impl Foo { + fn foo(self) -> Field { 3 } +} +``` + +## Lambdas + +Lambdas are anonymous functions. They follow the syntax of Rust - `|arg1, arg2, ..., argN| return_expression`. + +```rust +let add_50 = |val| val + 50; +assert(add_50(100) == 150); +``` + +See [Lambdas](./lambdas.md) for more details. + +## Attributes + +Attributes are metadata that can be applied to a function, using the following syntax: `#[attribute(value)]`. + +Supported attributes include: + +- **builtin**: the function is implemented by the compiler, for efficiency purposes. +- **deprecated**: mark the function as _deprecated_. Calling the function will generate a warning: `warning: use of deprecated function` +- **field**: Used to enable conditional compilation of code depending on the field size. See below for more details +- **oracle**: mark the function as _oracle_; meaning it is an external unconstrained function, implemented in noir_js. See [Unconstrained](./unconstrained.md) and [NoirJS](../../reference/NoirJS/noir_js/index.md) for more details. +- **test**: mark the function as unit tests. See [Tests](../../getting_started/tooling/testing.md) for more details + +### Field Attribute + +The field attribute defines which field the function is compatible for. The function is conditionally compiled, under the condition that the field attribute matches the Noir native field. +The field can be defined implicitly, by using the name of the elliptic curve usually associated to it - for instance bn254, bls12_381 - or explicitly by using the field (prime) order, in decimal or hexadecimal form. +As a result, it is possible to define multiple versions of a function with each version specialized for a different field attribute. This can be useful when a function requires different parameters depending on the underlying elliptic curve. + +Example: we define the function `foo()` three times below. Once for the default Noir bn254 curve, once for the field $\mathbb F_{23}$, which will normally never be used by Noir, and once again for the bls12_381 curve. + +```rust +#[field(bn254)] +fn foo() -> u32 { + 1 +} + +#[field(23)] +fn foo() -> u32 { + 2 +} + +// This commented code would not compile as foo would be defined twice because it is the same field as bn254 +// #[field(21888242871839275222246405745257275088548364400416034343698204186575808495617)] +// fn foo() -> u32 { +// 2 +// } + +#[field(bls12_381)] +fn foo() -> u32 { + 3 +} +``` + +If the field name is not known to Noir, it will discard the function. Field names are case insensitive. diff --git a/docs/versioned_docs/version-v0.26.0/noir/concepts/generics.md b/docs/versioned_docs/version-v0.26.0/noir/concepts/generics.md new file mode 100644 index 00000000000..ddd42bf1f9b --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/noir/concepts/generics.md @@ -0,0 +1,106 @@ +--- +title: Generics +description: Learn how to use Generics in Noir +keywords: [Noir, Rust, generics, functions, structs] +sidebar_position: 7 +--- + +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 print(self) { + for _i in 0 .. self.count { + println(self.value); + } + } +} + +fn main() { + let repeated = RepeatedValue { value: "Hello!", count: 2 }; + 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 + +Since a generic type `T` can represent any type, how can we call functions on the underlying type? +In other words, how can we go from "any type `T`" to "any type `T` that has certain methods available?" + +This is what [traits](../concepts/traits) are for in Noir. Here's an example of a function generic over +any type `T` that implements the `Eq` trait for equality: + +```rust +fn first_element_is_equal(array1: [T; N], array2: [T; N]) -> bool + where T: Eq +{ + if (array1.len() == 0) | (array2.len() == 0) { + true + } else { + array1[0] == array2[0] + } +} + +fn main() { + assert(first_element_is_equal([1, 2, 3], [1, 5, 6])); + + // We can use first_element_is_equal for arrays of any type + // as long as we have an Eq impl for the types we pass in + let array = [MyStruct::new(), MyStruct::new()]; + assert(array_eq(array, array, MyStruct::eq)); +} + +impl Eq for MyStruct { + fn eq(self, other: MyStruct) -> bool { + self.foo == other.foo + } +} +``` + +You can find more details on traits and trait implementations on the [traits page](../concepts/traits). diff --git a/docs/versioned_docs/version-v0.26.0/noir/concepts/globals.md b/docs/versioned_docs/version-v0.26.0/noir/concepts/globals.md new file mode 100644 index 00000000000..063a3d89248 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/noir/concepts/globals.md @@ -0,0 +1,72 @@ +--- +title: Global Variables +description: + Learn about global variables in Noir. Discover how + to declare, modify, and use them in your programs. +keywords: [noir programming language, globals, global variables, constants] +sidebar_position: 8 +--- + +## Globals + + +Noir supports global variables. The global's type can be inferred by the compiler entirely: + +```rust +global N = 5; // Same as `global N: Field = 5` + +global TUPLE = (3, 2); + +fn main() { + assert(N == 5); + assert(N == TUPLE.0 + TUPLE.1); +} +``` + +:::info + +Globals can be defined as any expression, so long as they don't depend on themselves - otherwise there would be a dependency cycle! For example: + +```rust +global T = foo(T); // dependency error +``` + +::: + + +If they are initialized to a literal integer, globals can be used to specify an array's length: + +```rust +global N: Field = 2; + +fn main(y : [Field; N]) { + assert(y[0] == y[1]) +} +``` + +A global from another module can be imported or referenced externally like any other name: + +```rust +global N = 20; + +fn main() { + assert(my_submodule::N != N); +} + +mod my_submodule { + global N: Field = 10; +} +``` + +When a global is used, Noir replaces the name with its definition on each occurrence. +This means globals defined using function calls will repeat the call each time they're used: + +```rust +global RESULT = foo(); + +fn foo() -> [Field; 100] { ... } +``` + +This is usually fine since Noir will generally optimize any function call that does not +refer to a program input into a constant. It should be kept in mind however, if the called +function performs side-effects like `println`, as these will still occur on each use. diff --git a/docs/versioned_docs/version-v0.26.0/noir/concepts/lambdas.md b/docs/versioned_docs/version-v0.26.0/noir/concepts/lambdas.md new file mode 100644 index 00000000000..be3c7e0b5ca --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/noir/concepts/lambdas.md @@ -0,0 +1,81 @@ +--- +title: Lambdas +description: Learn how to use anonymous functions in Noir programming language. +keywords: [Noir programming language, lambda, closure, function, anonymous function] +sidebar_position: 9 +--- + +## 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.26.0/noir/concepts/mutability.md b/docs/versioned_docs/version-v0.26.0/noir/concepts/mutability.md new file mode 100644 index 00000000000..fdeef6a87c5 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/noir/concepts/mutability.md @@ -0,0 +1,121 @@ +--- +title: Mutability +description: + Learn about mutable variables in Noir. Discover how + to declare, modify, and use them in your programs. +keywords: [noir programming language, mutability in noir, mutable variables] +sidebar_position: 8 +--- + +Variables in noir can be declared mutable via the `mut` keyword. Mutable variables can be reassigned +to via an assignment expression. + +```rust +let x = 2; +x = 3; // error: x must be mutable to be assigned to + +let mut y = 3; +let y = 4; // OK +``` + +The `mut` modifier can also apply to patterns: + +```rust +let (a, mut b) = (1, 2); +a = 11; // error: a must be mutable to be assigned to +b = 12; // OK + +let mut (c, d) = (3, 4); +c = 13; // OK +d = 14; // OK + +// etc. +let MyStruct { x: mut y } = MyStruct { x: a }; +// y is now in scope +``` + +Note that mutability in noir is local and everything is passed by value, so if a called function +mutates its parameters then the parent function will keep the old value of the parameters. + +```rust +fn main() -> pub Field { + let x = 3; + helper(x); + x // x is still 3 +} + +fn helper(mut x: i32) { + x = 4; +} +``` + +## Non-local mutability + +Non-local mutability can be achieved through the mutable reference type `&mut T`: + +```rust +fn set_to_zero(x: &mut Field) { + *x = 0; +} + +fn main() { + let mut y = 42; + set_to_zero(&mut y); + assert(*y == 0); +} +``` + +When creating a mutable reference, the original variable being referred to (`y` in this +example) must also be mutable. Since mutable references are a reference type, they must +be explicitly dereferenced via `*` to retrieve the underlying value. Note that this yields +a copy of the value, so mutating this copy will not change the original value behind the +reference: + +```rust +fn main() { + let mut x = 1; + let x_ref = &mut x; + + let mut y = *x_ref; + let y_ref = &mut y; + + x = 2; + *x_ref = 3; + + y = 4; + *y_ref = 5; + + assert(x == 3); + assert(*x_ref == 3); + assert(y == 5); + assert(*y_ref == 5); +} +``` + +Note that types in Noir are actually deeply immutable so the copy that occurs when +dereferencing is only a conceptual copy - no additional constraints will occur. + +Mutable references can also be stored within structs. Note that there is also +no lifetime parameter on these unlike rust. This is because the allocated memory +always lasts the entire program - as if it were an array of one element. + +```rust +struct Foo { + x: &mut Field +} + +impl Foo { + fn incr(mut self) { + *self.x += 1; + } +} + +fn main() { + let foo = Foo { x: &mut 0 }; + foo.incr(); + assert(*foo.x == 1); +} +``` + +In general, you should avoid non-local & shared mutability unless it is needed. Sticking +to only local mutability will improve readability and potentially improve compiler optimizations as well. diff --git a/docs/versioned_docs/version-v0.26.0/noir/concepts/ops.md b/docs/versioned_docs/version-v0.26.0/noir/concepts/ops.md new file mode 100644 index 00000000000..60425cb8994 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/noir/concepts/ops.md @@ -0,0 +1,98 @@ +--- +title: Logical Operations +description: + Learn about the supported arithmetic and logical operations in the Noir programming language. + Discover how to perform operations on private input types, integers, and booleans. +keywords: + [ + Noir programming language, + supported operations, + arithmetic operations, + logical operations, + predicate operators, + bitwise operations, + short-circuiting, + backend, + ] +sidebar_position: 3 +--- + +# Operations + +## Table of Supported Operations + +| Operation | Description | Requirements | +| :-------- | :------------------------------------------------------------: | -------------------------------------: | +| + | Adds two private input types together | Types must be private input | +| - | Subtracts two private input types together | Types must be private input | +| \* | Multiplies two private input types together | Types must be private input | +| / | Divides two private input types together | Types must be private input | +| ^ | XOR two private input types together | Types must be integer | +| & | AND two private input types together | Types must be integer | +| \| | OR two private input types together | Types must be integer | +| \<\< | Left shift an integer by another integer amount | Types must be integer | +| >> | Right shift an integer by another integer amount | Types must be integer | +| ! | Bitwise not of a value | Type must be integer or boolean | +| \< | returns a bool if one value is less than the other | Upper bound must have a known bit size | +| \<= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | +| > | returns a bool if one value is more than the other | Upper bound must have a known bit size | +| >= | returns a bool if one value is more than or equal to the other | Upper bound must have a known bit size | +| == | returns a bool if one value is equal to the other | Both types must not be constants | +| != | returns a bool if one value is not equal to the other | Both types must not be constants | + +### Predicate Operators + +`<,<=, !=, == , >, >=` are known as predicate/comparison operations because they compare two values. +This differs from the operations such as `+` where the operands are used in _computation_. + +### Bitwise Operations Example + +```rust +fn main(x : Field) { + let y = x as u32; + let z = y & y; +} +``` + +`z` is implicitly constrained to be the result of `y & y`. The `&` operand is used to denote bitwise +`&`. + +> `x & x` would not compile as `x` is a `Field` and not an integer type. + +### Logical Operators + +Noir has no support for the logical operators `||` and `&&`. This is because encoding the +short-circuiting that these operators require can be inefficient for Noir's backend. Instead you can +use the bitwise operators `|` and `&` which operate identically 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.26.0/noir/concepts/oracles.md b/docs/versioned_docs/version-v0.26.0/noir/concepts/oracles.md new file mode 100644 index 00000000000..2e6a6818d48 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/noir/concepts/oracles.md @@ -0,0 +1,23 @@ +--- +title: Oracles +description: Dive into how Noir supports Oracles via RPC calls, and learn how to declare an Oracle in Noir with our comprehensive guide. +keywords: + - Noir + - Oracles + - RPC Calls + - Unconstrained Functions + - Programming + - Blockchain +sidebar_position: 6 +--- + +Noir has support for Oracles via RPC calls. This means Noir will make an RPC call and use the return value for proof generation. + +Since Oracles are not resolved by Noir, they are [`unconstrained` functions](./unconstrained.md) + +You can declare an Oracle through the `#[oracle()]` flag. Example: + +```rust +#[oracle(get_number_sequence)] +unconstrained fn get_number_sequence(_size: Field) -> [Field] {} +``` diff --git a/docs/versioned_docs/version-v0.26.0/noir/concepts/shadowing.md b/docs/versioned_docs/version-v0.26.0/noir/concepts/shadowing.md new file mode 100644 index 00000000000..5ce6130d201 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/noir/concepts/shadowing.md @@ -0,0 +1,44 @@ +--- +title: Shadowing +sidebar_position: 12 +--- + +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.26.0/noir/concepts/traits.md b/docs/versioned_docs/version-v0.26.0/noir/concepts/traits.md new file mode 100644 index 00000000000..ef1445a5907 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/noir/concepts/traits.md @@ -0,0 +1,389 @@ +--- +title: Traits +description: + Traits in Noir can be used to abstract out a common interface for functions across + several data types. +keywords: [noir programming language, traits, interfaces, generic, protocol] +sidebar_position: 14 +--- + +## Overview + +Traits in Noir are a useful abstraction similar to interfaces or protocols in other languages. Each trait defines +the interface of several methods contained within the trait. Types can then implement this trait by providing +implementations for these methods. For example in the program: + +```rust +struct Rectangle { + width: Field, + height: Field, +} + +impl Rectangle { + fn area(self) -> Field { + self.width * self.height + } +} + +fn log_area(r: Rectangle) { + println(r.area()); +} +``` + +We have a function `log_area` to log the area of a `Rectangle`. Now how should we change the program if we want this +function to work on `Triangle`s as well?: + +```rust +struct Triangle { + width: Field, + height: Field, +} + +impl Triangle { + fn area(self) -> Field { + self.width * self.height / 2 + } +} +``` + +Making `log_area` generic over all types `T` would be invalid since not all types have an `area` method. Instead, we can +introduce a new `Area` trait and make `log_area` generic over all types `T` that implement `Area`: + +```rust +trait Area { + fn area(self) -> Field; +} + +fn log_area(shape: T) where T: Area { + println(shape.area()); +} +``` + +We also need to explicitly implement `Area` for `Rectangle` and `Triangle`. We can do that by changing their existing +impls slightly. Note that the parameter types and return type of each of our `area` methods must match those defined +by the `Area` trait. + +```rust +impl Area for Rectangle { + fn area(self) -> Field { + self.width * self.height + } +} + +impl Area for Triangle { + fn area(self) -> Field { + self.width * self.height / 2 + } +} +``` + +Now we have a working program that is generic over any type of Shape that is used! Others can even use this program +as a library with their own types - such as `Circle` - as long as they also implement `Area` for these types. + +## Where Clauses + +As seen in `log_area` above, when we want to create a function or method that is generic over any type that implements +a trait, we can add a where clause to the generic function. + +```rust +fn log_area(shape: T) where T: Area { + println(shape.area()); +} +``` + +It is also possible to apply multiple trait constraints on the same variable at once by combining traits with the `+` +operator. Similarly, we can have multiple trait constraints by separating each with a comma: + +```rust +fn foo(elements: [T], thing: U) where + T: Default + Add + Eq, + U: Bar, +{ + let mut sum = T::default(); + + for element in elements { + sum += element; + } + + if sum == T::default() { + thing.bar(); + } +} +``` + +## Generic Implementations + +You can add generics to a trait implementation by adding the generic list after the `impl` keyword: + +```rust +trait Second { + fn second(self) -> Field; +} + +impl Second for (T, Field) { + fn second(self) -> Field { + self.1 + } +} +``` + +You can also implement a trait for every type this way: + +```rust +trait Debug { + fn debug(self); +} + +impl Debug for T { + fn debug(self) { + println(self); + } +} + +fn main() { + 1.debug(); +} +``` + +### Generic Trait Implementations With Where Clauses + +Where clauses can also be placed on trait implementations themselves to restrict generics in a similar way. +For example, while `impl Foo for T` implements the trait `Foo` for every type, `impl Foo for T where T: Bar` +will implement `Foo` only for types that also implement `Bar`. This is often used for implementing generic types. +For example, here is the implementation for array equality: + +```rust +impl Eq for [T; N] where T: Eq { + // Test if two arrays have the same elements. + // Because both arrays must have length N, we know their lengths already match. + fn eq(self, other: Self) -> bool { + let mut result = true; + + for i in 0 .. self.len() { + // The T: Eq constraint is needed to call == on the array elements here + result &= self[i] == other[i]; + } + + result + } +} +``` + +## Generic Traits + +Traits themselves can also be generic by placing the generic arguments after the trait name. These generics are in +scope of every item within the trait. + +```rust +trait Into { + // Convert `self` to type `T` + fn into(self) -> T; +} +``` + +When implementing generic traits the generic arguments of the trait must be specified. This is also true anytime +when referencing a generic trait (e.g. in a `where` clause). + +```rust +struct MyStruct { + array: [Field; 2], +} + +impl Into<[Field; 2]> for MyStruct { + fn into(self) -> [Field; 2] { + self.array + } +} + +fn as_array(x: T) -> [Field; 2] + where T: Into<[Field; 2]> +{ + x.into() +} + +fn main() { + let array = [1, 2]; + let my_struct = MyStruct { array }; + + assert_eq(as_array(my_struct), array); +} +``` + +## Trait Methods With No `self` + +A trait can contain any number of methods, each of which have access to the `Self` type which represents each type +that eventually implements the trait. Similarly, the `self` variable is available as well but is not required to be used. +For example, we can define a trait to create a default value for a type. This trait will need to return the `Self` type +but doesn't need to take any parameters: + +```rust +trait Default { + fn default() -> Self; +} +``` + +Implementing this trait can be done similarly to any other trait: + +```rust +impl Default for Field { + fn default() -> Field { + 0 + } +} + +struct MyType {} + +impl Default for MyType { + fn default() -> Field { + MyType {} + } +} +``` + +However, since there is no `self` parameter, we cannot call it via the method call syntax `object.method()`. +Instead, we'll need to refer to the function directly. This can be done either by referring to the +specific impl `MyType::default()` or referring to the trait itself `Default::default()`. In the later +case, type inference determines the impl that is selected. + +```rust +let my_struct = MyStruct::default(); + +let x: Field = Default::default(); +let result = x + Default::default(); +``` + +:::warning + +```rust +let _ = Default::default(); +``` + +If type inference cannot select which impl to use because of an ambiguous `Self` type, an impl will be +arbitrarily selected. This occurs most often when the result of a trait function call with no parameters +is unused. To avoid this, when calling a trait function with no `self` or `Self` parameters or return type, +always refer to it via the implementation type's namespace - e.g. `MyType::default()`. +This is set to change to an error in future Noir versions. + +::: + +## Default Method Implementations + +A trait can also have default implementations of its methods by giving a body to the desired functions. +Note that this body must be valid for all types that may implement the trait. As a result, the only +valid operations on `self` will be operations valid for any type or other operations on the trait itself. + +```rust +trait Numeric { + fn add(self, other: Self) -> Self; + + // Default implementation of double is (self + self) + fn double(self) -> Self { + self.add(self) + } +} +``` + +When implementing a trait with default functions, a type may choose to implement only the required functions: + +```rust +impl Numeric for Field { + fn add(self, other: Field) -> Field { + self + other + } +} +``` + +Or it may implement the optional methods as well: + +```rust +impl Numeric for u32 { + fn add(self, other: u32) -> u32 { + self + other + } + + fn double(self) -> u32 { + self * 2 + } +} +``` + +## Impl Specialization + +When implementing traits for a generic type it is possible to implement the trait for only a certain combination +of generics. This can be either as an optimization or because those specific generics are required to implement the trait. + +```rust +trait Sub { + fn sub(self, other: Self) -> Self; +} + +struct NonZero { + value: T, +} + +impl Sub for NonZero { + fn sub(self, other: Self) -> Self { + let value = self.value - other.value; + assert(value != 0); + NonZero { value } + } +} +``` + +## Overlapping Implementations + +Overlapping implementations are disallowed by Noir to ensure Noir's decision on which impl to select is never ambiguous. +This means if a trait `Foo` is already implemented +by a type `Bar` for all `T`, then we cannot also have a separate impl for `Bar` (or any other +type argument). Similarly, if there is an impl for all `T` such as `impl Debug for T`, we cannot create +any more impls to `Debug` for other types since it would be ambiguous which impl to choose for any given +method call. + +```rust +trait Trait {} + +// Previous impl defined here +impl Trait for (A, B) {} + +// error: Impl for type `(Field, Field)` overlaps with existing impl +impl Trait for (Field, Field) {} +``` + +## Trait Coherence + +Another restriction on trait implementations is coherence. This restriction ensures other crates cannot create +impls that may overlap with other impls, even if several unrelated crates are used as dependencies in the same +program. + +The coherence restriction is: to implement a trait, either the trait itself or the object type must be declared +in the crate the impl is in. + +In practice this often comes up when using types provided by libraries. If a library provides a type `Foo` that does +not implement a trait in the standard library such as `Default`, you may not `impl Default for Foo` in your own crate. +While restrictive, this prevents later issues or silent changes in the program if the `Foo` library later added its +own impl for `Default`. If you are a user of the `Foo` library in this scenario and need a trait not implemented by the +library your choices are to either submit a patch to the library or use the newtype pattern. + +### The Newtype Pattern + +The newtype pattern gets around the coherence restriction by creating a new wrapper type around the library type +that we cannot create `impl`s for. Since the new wrapper type is defined in our current crate, we can create +impls for any trait we need on it. + +```rust +struct Wrapper { + foo: dep::some_library::Foo, +} + +impl Default for Wrapper { + fn default() -> Wrapper { + Wrapper { + foo: dep::some_library::Foo::new(), + } + } +} +``` + +Since we have an impl for our own type, the behavior of this code will not change even if `some_library` is updated +to provide its own `impl Default for Foo`. The downside of this pattern is that it requires extra wrapping and +unwrapping of values when converting to and from the `Wrapper` and `Foo` types. diff --git a/docs/versioned_docs/version-v0.26.0/noir/concepts/unconstrained.md b/docs/versioned_docs/version-v0.26.0/noir/concepts/unconstrained.md new file mode 100644 index 00000000000..b8e71fe65f0 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/noir/concepts/unconstrained.md @@ -0,0 +1,99 @@ +--- +title: Unconstrained Functions +description: "Learn about what unconstrained functions in Noir are, how to use them and when you'd want to." + +keywords: [Noir programming language, unconstrained, open] +sidebar_position: 5 +--- + +Unconstrained functions are functions which do not constrain any of the included computation and allow for non-deterministic 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 AND 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. + +## Break and Continue + +In addition to loops over runtime bounds, `break` and `continue` are also available in unconstrained code. See [break and continue](../concepts/control_flow/#break-and-continue) diff --git a/docs/versioned_docs/version-v0.26.0/noir/modules_packages_crates/_category_.json b/docs/versioned_docs/version-v0.26.0/noir/modules_packages_crates/_category_.json new file mode 100644 index 00000000000..1debcfe7675 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/noir/modules_packages_crates/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Modules, Packages and Crates", + "position": 2, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.26.0/noir/modules_packages_crates/crates_and_packages.md b/docs/versioned_docs/version-v0.26.0/noir/modules_packages_crates/crates_and_packages.md new file mode 100644 index 00000000000..95ee9f52ab2 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/noir/modules_packages_crates/crates_and_packages.md @@ -0,0 +1,43 @@ +--- +title: Crates and Packages +description: Learn how to use Crates and Packages in your Noir project +keywords: [Nargo, dependencies, package management, crates, package] +sidebar_position: 0 +--- + +## Crates + +A crate is the smallest amount of code that the Noir compiler considers at a time. +Crates can contain modules, and the modules may be defined in other files that get compiled with the crate, as we’ll see in the coming sections. + +### Crate Types + +A Noir crate can come in several forms: binaries, libraries or contracts. + +#### Binaries + +_Binary crates_ are programs which you can compile to an ACIR circuit which you can then create proofs against. Each must have a function called `main` that defines the ACIR circuit which is to be proved. + +#### Libraries + +_Library crates_ don't have a `main` function and they don't compile down to ACIR. Instead they define functionality intended to be shared with multiple projects, and eventually included in a binary crate. + +#### Contracts + +Contract crates are similar to binary crates in that they compile to ACIR which you can create proofs against. They are different in that they do not have a single `main` function, but are a collection of functions to be deployed to the [Aztec network](https://aztec.network). You can learn more about the technical details of Aztec in the [monorepo](https://github.com/AztecProtocol/aztec-packages) or contract [examples](https://github.com/AztecProtocol/aztec-packages/tree/master/noir-projects/noir-contracts/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.26.0/noir/modules_packages_crates/dependencies.md b/docs/versioned_docs/version-v0.26.0/noir/modules_packages_crates/dependencies.md new file mode 100644 index 00000000000..04c1703d929 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/noir/modules_packages_crates/dependencies.md @@ -0,0 +1,124 @@ +--- +title: Dependencies +description: + Learn how to specify and manage dependencies in Nargo, allowing you to upload packages to GitHub + and use them easily in your project. +keywords: [Nargo, dependencies, GitHub, package management, versioning] +sidebar_position: 1 +--- + +Nargo allows you to upload packages to GitHub and use them as dependencies. + +## Specifying a dependency + +Specifying a dependency requires a tag to a specific commit and the git url to the url containing +the package. + +Currently, there are no requirements on the tag contents. If requirements are added, it would follow +semver 2.0 guidelines. + +> Note: Without a `tag` , there would be no versioning and dependencies would change each time you +> compile your project. + +For example, to add the [ecrecover-noir library](https://github.com/colinnielsen/ecrecover-noir) to your project, add it to `Nargo.toml`: + +```toml +# Nargo.toml + +[dependencies] +ecrecover = {tag = "v0.8.0", git = "https://github.com/colinnielsen/ecrecover-noir"} +``` + +If the module is in a subdirectory, you can define a subdirectory in your git repository, for example: + +```toml +# Nargo.toml + +[dependencies] +easy_private_token_contract = {tag ="v0.1.0-alpha62", git = "https://github.com/AztecProtocol/aztec-packages", directory = "noir-contracts/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 +└── lib_a + ├── Nargo.toml + └── src + └── lib.nr +``` + +Inside of the binary crate, you can specify: + +```toml +# Nargo.toml + +[dependencies] +lib_a = { path = "../lib_a" } +``` + +## 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 lib_a referenced above: + +```rust +use dep::ecrecover; +use dep::lib_a; +``` + +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.26.0/noir/modules_packages_crates/modules.md b/docs/versioned_docs/version-v0.26.0/noir/modules_packages_crates/modules.md new file mode 100644 index 00000000000..ae822a1cff4 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/noir/modules_packages_crates/modules.md @@ -0,0 +1,105 @@ +--- +title: Modules +description: + Learn how to organize your files using modules in Noir, following the same convention as Rust's + module system. Examples included. +keywords: [Noir, Rust, modules, organizing files, sub-modules] +sidebar_position: 2 +--- + +Noir's module system follows the same convention as the _newer_ version of Rust's module system. + +## Purpose of Modules + +Modules are used to organize 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.26.0/noir/modules_packages_crates/workspaces.md b/docs/versioned_docs/version-v0.26.0/noir/modules_packages_crates/workspaces.md new file mode 100644 index 00000000000..513497f12bf --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/noir/modules_packages_crates/workspaces.md @@ -0,0 +1,42 @@ +--- +title: Workspaces +sidebar_position: 3 +--- + +Workspaces are a feature of nargo that allow you to manage multiple related Noir packages in a single repository. A workspace is essentially a group of related projects that share common build output directories and configurations. + +Each Noir project (with it's own Nargo.toml file) can be thought of as a package. Each package is expected to contain exactly one "named circuit", being the "name" defined in Nargo.toml with the program logic defined in `./src/main.nr`. + +For a project with the following structure: + +```tree +├── crates +│ ├── a +│ │ ├── Nargo.toml +│ │ └── Prover.toml +│ │ └── src +│ │ └── main.nr +│ └── b +│ ├── Nargo.toml +│ └── Prover.toml +│ └── src +│ └── main.nr +│ +└── Nargo.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.26.0/noir/standard_library/_category_.json b/docs/versioned_docs/version-v0.26.0/noir/standard_library/_category_.json new file mode 100644 index 00000000000..af04c0933fd --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/noir/standard_library/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Standard Library", + "position": 1, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.26.0/noir/standard_library/bigint.md b/docs/versioned_docs/version-v0.26.0/noir/standard_library/bigint.md new file mode 100644 index 00000000000..da6a7cdfd81 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/noir/standard_library/bigint.md @@ -0,0 +1,119 @@ +--- +title: Big Integers +description: How to use big integers from Noir standard library +keywords: + [ + Big Integer, + Noir programming language, + Noir libraries, + ] +--- + +The BigInt module in the standard library exposes some class of integers which do not fit (well) into a Noir native field. It implements modulo arithmetic, modulo a 'big' prime number. + +:::note + +The module can currently be considered as `Field`s with fixed modulo sizes used by a set of elliptic curves, in addition to just the native curve. [More work](https://github.com/noir-lang/noir/issues/510) is needed to achieve arbitrarily sized big integers. + +::: + +Currently 6 classes of integers (i.e 'big' prime numbers) are available in the module, namely: + +- BN254 Fq: Bn254Fq +- BN254 Fr: Bn254Fr +- Secp256k1 Fq: Secpk1Fq +- Secp256k1 Fr: Secpk1Fr +- Secp256r1 Fr: Secpr1Fr +- Secp256r1 Fq: Secpr1Fq + +Where XXX Fq and XXX Fr denote respectively the order of the base and scalar field of the (usual) elliptic curve XXX. +For instance the big integer 'Secpk1Fq' in the standard library refers to integers modulo $2^{256}-2^{32}-977$. + +Feel free to explore the source code for the other primes: + +```rust title="big_int_definition" showLineNumbers +struct BigInt { + pointer: u32, + modulus: u32, +} +``` +> Source code: noir_stdlib/src/bigint.nr#L16-L21 + + +## Example usage + +A common use-case is when constructing a big integer from its bytes representation, and performing arithmetic operations on it: + +```rust title="big_int_example" showLineNumbers +fn big_int_example(x: u8, y: u8) { + let a = Secpk1Fq::from_le_bytes(&[x, y, 0, 45, 2]); + let b = Secpk1Fq::from_le_bytes(&[y, x, 9]); + let c = (a + b) * b / a; + let d = c.to_le_bytes(); + println(d[0]); +} +``` +> Source code: test_programs/execution_success/bigint/src/main.nr#L20-L28 + + +## Methods + +The available operations for each big integer are: + +### from_le_bytes + +Construct a big integer from its little-endian bytes representation. Example: + +```rust + let a = Secpk1Fq::from_le_bytes(&[x, y, 0, 45, 2]); + ``` + +Sure, here's the formatted version of the remaining methods: + +### to_le_bytes + +Return the little-endian bytes representation of a big integer. Example: + +```rust +let bytes = a.to_le_bytes(); +``` + +### add + +Add two big integers. Example: + +```rust +let sum = a + b; +``` + +### sub + +Subtract two big integers. Example: + +```rust +let difference = a - b; +``` + +### mul + +Multiply two big integers. Example: + +```rust +let product = a * b; +``` + +### div + +Divide two big integers. Note that division is field division and not euclidean division. Example: + +```rust +let quotient = a / b; +``` + +### eq + +Compare two big integers. Example: + +```rust +let are_equal = a == b; +``` diff --git a/docs/versioned_docs/version-v0.26.0/noir/standard_library/black_box_fns.md b/docs/versioned_docs/version-v0.26.0/noir/standard_library/black_box_fns.md new file mode 100644 index 00000000000..be8c65679c3 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/noir/standard_library/black_box_fns.md @@ -0,0 +1,31 @@ +--- +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. + +The ACVM spec defines a set of blackbox functions which backends will be expected to implement. This allows backends to use optimized implementations of these constraints if they have them, however they may also fallback to less efficient naive implementations if not. + +## Function list + +Here is a list of the current black box functions: + +- [SHA256](./cryptographic_primitives/hashes.mdx#sha256) +- [Schnorr signature verification](./cryptographic_primitives/schnorr.mdx) +- [Blake2s](./cryptographic_primitives/hashes.mdx#blake2s) +- [Blake3](./cryptographic_primitives/hashes.mdx#blake3) +- [Pedersen Hash](./cryptographic_primitives/hashes.mdx#pedersen_hash) +- [Pedersen Commitment](./cryptographic_primitives/hashes.mdx#pedersen_commitment) +- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification.mdx) +- [Fixed base scalar multiplication](./cryptographic_primitives/scalar.mdx) +- AND +- XOR +- RANGE +- [Keccak256](./cryptographic_primitives/hashes.mdx#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. + +You can view the black box functions defined in the ACVM code [here](https://github.com/noir-lang/noir/blob/master/acvm-repo/acir/src/circuit/black_box_functions.rs). diff --git a/docs/versioned_docs/version-v0.26.0/noir/standard_library/bn254.md b/docs/versioned_docs/version-v0.26.0/noir/standard_library/bn254.md new file mode 100644 index 00000000000..3294f005dbb --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/noir/standard_library/bn254.md @@ -0,0 +1,46 @@ +--- +title: Bn254 Field Library +--- + +Noir provides a module in standard library with some optimized functions for bn254 Fr in `std::field::bn254`. + +## decompose + +```rust +fn decompose(x: Field) -> (Field, Field) {} +``` + +Decomposes a single field into two fields, low and high. The low field contains the lower 16 bytes of the input field and the high field contains the upper 16 bytes of the input field. Both field results are range checked to 128 bits. + + +## assert_gt + +```rust +fn assert_gt(a: Field, b: Field) {} +``` + +Asserts that a > b. This will generate less constraints than using `assert(gt(a, b))`. + +## assert_lt + +```rust +fn assert_lt(a: Field, b: Field) {} +``` + +Asserts that a < b. This will generate less constraints than using `assert(lt(a, b))`. + +## gt + +```rust +fn gt(a: Field, b: Field) -> bool {} +``` + +Returns true if a > b. + +## lt + +```rust +fn lt(a: Field, b: Field) -> bool {} +``` + +Returns true if a < b. \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.26.0/noir/standard_library/containers/boundedvec.md b/docs/versioned_docs/version-v0.26.0/noir/standard_library/containers/boundedvec.md new file mode 100644 index 00000000000..ce4529f6e57 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/noir/standard_library/containers/boundedvec.md @@ -0,0 +1,326 @@ +--- +title: Bounded Vectors +keywords: [noir, vector, bounded vector, slice] +sidebar_position: 1 +--- + +A `BoundedVec` is a growable storage similar to a `Vec` except that it +is bounded with a maximum possible length. Unlike `Vec`, `BoundedVec` is not implemented +via slices and thus is not subject to the same restrictions slices are (notably, nested +slices - and thus nested vectors as well - are disallowed). + +Since a BoundedVec is backed by a normal array under the hood, growing the BoundedVec by +pushing an additional element is also more efficient - the length only needs to be increased +by one. + +For these reasons `BoundedVec` should generally be preferred over `Vec` when there +is a reasonable maximum bound that can be placed on the vector. + +Example: + +```rust +let mut vector: BoundedVec = BoundedVec::new(); +for i in 0..5 { + vector.push(i); +} +assert(vector.len() == 5); +assert(vector.max_len() == 10); +``` + +## Methods + +### new + +```rust +pub fn new() -> Self +``` + +Creates a new, empty vector of length zero. + +Since this container is backed by an array internally, it still needs an initial value +to give each element. To resolve this, each element is zeroed internally. This value +is guaranteed to be inaccessible unless `get_unchecked` is used. + +Example: + +```rust +let empty_vector: BoundedVec = BoundedVec::new(); +assert(empty_vector.len() == 0); +``` + +Note that whenever calling `new` the maximum length of the vector should always be specified +via a type signature: + +```rust title="new_example" showLineNumbers +fn foo() -> BoundedVec { + // Ok! MaxLen is specified with a type annotation + let v1: BoundedVec = BoundedVec::new(); + let v2 = BoundedVec::new(); + + // Ok! MaxLen is known from the type of foo's return value + v2 +} + +fn bad() { + let mut v3 = BoundedVec::new(); + + // Not Ok! We don't know if v3's MaxLen is at least 1, and the compiler often infers 0 by default. + v3.push(5); +} +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L11-L27 + + +This defaulting of `MaxLen` (and numeric generics in general) to zero may change in future noir versions +but for now make sure to use type annotations when using bounded vectors. Otherwise, you will receive a constraint failure at runtime when the vec is pushed to. + +### get + +```rust +pub fn get(mut self: Self, index: u64) -> T { +``` + +Retrieves an element from the vector at the given index, starting from zero. + +If the given index is equal to or greater than the length of the vector, this +will issue a constraint failure. + +Example: + +```rust +fn foo(v: BoundedVec) { + let first = v.get(0); + let last = v.get(v.len() - 1); + assert(first != last); +} +``` + +### get_unchecked + +```rust +pub fn get_unchecked(mut self: Self, index: u64) -> T { +``` + +Retrieves an element from the vector at the given index, starting from zero, without +performing a bounds check. + +Since this function does not perform a bounds check on length before accessing the element, +it is unsafe! Use at your own risk! + +Example: + +```rust title="get_unchecked_example" showLineNumbers +fn sum_of_first_three(v: BoundedVec) -> u32 { + // Always ensure the length is larger than the largest + // index passed to get_unchecked + assert(v.len() > 2); + let first = v.get_unchecked(0); + let second = v.get_unchecked(1); + let third = v.get_unchecked(2); + first + second + third +} +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L54-L64 + + + +### push + +```rust +pub fn push(&mut self, elem: T) { +``` + +Pushes an element to the end of the vector. This increases the length +of the vector by one. + +Panics if the new length of the vector will be greater than the max length. + +Example: + +```rust title="bounded-vec-push-example" showLineNumbers +let mut v: BoundedVec = BoundedVec::new(); + + v.push(1); + v.push(2); + + // Panics with failed assertion "push out of bounds" + v.push(3); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L68-L76 + + +### pop + +```rust +pub fn pop(&mut self) -> T +``` + +Pops the element at the end of the vector. This will decrease the length +of the vector by one. + +Panics if the vector is empty. + +Example: + +```rust title="bounded-vec-pop-example" showLineNumbers +let mut v: BoundedVec = BoundedVec::new(); + v.push(1); + v.push(2); + + let two = v.pop(); + let one = v.pop(); + + assert(two == 2); + assert(one == 1); + // error: cannot pop from an empty vector + // let _ = v.pop(); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L81-L93 + + +### len + +```rust +pub fn len(self) -> u64 { +``` + +Returns the current length of this vector + +Example: + +```rust title="bounded-vec-len-example" showLineNumbers +let mut v: BoundedVec = BoundedVec::new(); + assert(v.len() == 0); + + v.push(100); + assert(v.len() == 1); + + v.push(200); + v.push(300); + v.push(400); + assert(v.len() == 4); + + let _ = v.pop(); + let _ = v.pop(); + assert(v.len() == 2); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L98-L113 + + +### max_len + +```rust +pub fn max_len(_self: BoundedVec) -> u64 { +``` + +Returns the maximum length of this vector. This is always +equal to the `MaxLen` parameter this vector was initialized with. + +Example: + +```rust title="bounded-vec-max-len-example" showLineNumbers +let mut v: BoundedVec = BoundedVec::new(); + + assert(v.max_len() == 5); + v.push(10); + assert(v.max_len() == 5); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L118-L124 + + +### storage + +```rust +pub fn storage(self) -> [T; MaxLen] { +``` + +Returns the internal array within this vector. +Since arrays in Noir are immutable, mutating the returned storage array will not mutate +the storage held internally by this vector. + +Note that uninitialized elements may be zeroed out! + +Example: + +```rust title="bounded-vec-storage-example" showLineNumbers +let mut v: BoundedVec = BoundedVec::new(); + + assert(v.storage() == [0, 0, 0, 0, 0]); + + v.push(57); + assert(v.storage() == [57, 0, 0, 0, 0]); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L129-L136 + + +### extend_from_array + +```rust +pub fn extend_from_array(&mut self, array: [T; Len]) +``` + +Pushes each element from the given array to this vector. + +Panics if pushing each element would cause the length of this vector +to exceed the maximum length. + +Example: + +```rust title="bounded-vec-extend-from-array-example" showLineNumbers +let mut vec: BoundedVec = BoundedVec::new(); + vec.extend_from_array([2, 4]); + + assert(vec.len == 2); + assert(vec.get(0) == 2); + assert(vec.get(1) == 4); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L141-L148 + + +### extend_from_bounded_vec + +```rust +pub fn extend_from_bounded_vec(&mut self, vec: BoundedVec) +``` + +Pushes each element from the other vector to this vector. The length of +the other vector is left unchanged. + +Panics if pushing each element would cause the length of this vector +to exceed the maximum length. + +Example: + +```rust title="bounded-vec-extend-from-bounded-vec-example" showLineNumbers +let mut v1: BoundedVec = BoundedVec::new(); + let mut v2: BoundedVec = BoundedVec::new(); + + v2.extend_from_array([1, 2, 3]); + v1.extend_from_bounded_vec(v2); + + assert(v1.storage() == [1, 2, 3, 0, 0]); + assert(v2.storage() == [1, 2, 3, 0, 0, 0, 0]); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L153-L162 + + +### any + +```rust +pub fn any(self, predicate: fn[Env](T) -> bool) -> bool +``` + +Returns true if the given predicate returns true for any element +in this vector. + +Example: + +```rust title="bounded-vec-any-example" showLineNumbers +let mut v: BoundedVec = BoundedVec::new(); + v.extend_from_array([2, 4, 6]); + + let all_even = !v.any(|elem: u32| elem % 2 != 0); + assert(all_even); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L229-L235 + diff --git a/docs/versioned_docs/version-v0.26.0/noir/standard_library/containers/hashmap.md b/docs/versioned_docs/version-v0.26.0/noir/standard_library/containers/hashmap.md new file mode 100644 index 00000000000..91604af765d --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/noir/standard_library/containers/hashmap.md @@ -0,0 +1,569 @@ +--- +title: HashMap +keywords: [noir, map, hash, hashmap] +sidebar_position: 1 +--- + +`HashMap` is used to efficiently store and look up key-value pairs. + +`HashMap` is a bounded type which can store anywhere from zero to `MaxLen` total elements. +Note that due to hash collisions, the actual maximum number of elements stored by any particular +hashmap is likely lower than `MaxLen`. This is true even with cryptographic hash functions since +every hash value will be performed modulo `MaxLen`. + +When creating `HashMap`s, the `MaxLen` generic should always be specified if it is not already +known. Otherwise, the compiler may infer a different value for `MaxLen` (such as zero), which +will likely change the result of the program. This behavior is set to become an error in future +versions instead. + +Example: + +```rust +// Create a mapping from Fields to u32s with a maximum length of 12 +// using a pedersen hash +let mut map: HashMap> = HashMap::default(); + +map.insert(1, 2); +map.insert(3, 4); + +let two = map.get(1).unwrap(); +``` + +## Methods + +### default + +```rust title="default" showLineNumbers +impl Default for HashMap +where + B: BuildHasher + Default, + H: Hasher + Default +{ + fn default() -> Self { +``` +> Source code: noir_stdlib/src/collections/map.nr#L462-L469 + + +Creates a fresh, empty HashMap. + +When using this function, always make sure to specify the maximum size of the hash map. + +This is the same `default` from the `Default` implementation given further below. It is +repeated here for convenience since it is the recommended way to create a hashmap. + +Example: + +```rust title="default_example" showLineNumbers +let hashmap: HashMap> = HashMap::default(); + assert(hashmap.is_empty()); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L202-L205 + + +Because `HashMap` has so many generic arguments that are likely to be the same throughout +your program, it may be helpful to create a type alias: + +```rust title="type_alias" showLineNumbers +type MyMap = HashMap>; +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L196-L198 + + +### with_hasher + +```rust title="with_hasher" showLineNumbers +pub fn with_hasher(_build_hasher: B) -> Self + where + B: BuildHasher { +``` +> Source code: noir_stdlib/src/collections/map.nr#L82-L86 + + +Creates a hashmap with an existing `BuildHasher`. This can be used to ensure multiple +hashmaps are created with the same hasher instance. + +Example: + +```rust title="with_hasher_example" showLineNumbers +let my_hasher: BuildHasherDefault = Default::default(); + let hashmap: HashMap> = HashMap::with_hasher(my_hasher); + assert(hashmap.is_empty()); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L207-L211 + + +### get + +```rust title="get" showLineNumbers +pub fn get( + self, + key: K + ) -> Option + where + K: Eq + Hash, + B: BuildHasher, + H: Hasher { +``` +> Source code: noir_stdlib/src/collections/map.nr#L278-L287 + + +Retrieves a value from the hashmap, returning `Option::none()` if it was not found. + +Example: + +```rust title="get_example" showLineNumbers +fn get_example(map: HashMap>) { + let x = map.get(12); + + if x.is_some() { + assert(x.unwrap() == 42); + } +} +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L299-L307 + + +### insert + +```rust title="insert" showLineNumbers +pub fn insert( + &mut self, + key: K, + value: V + ) + where + K: Eq + Hash, + B: BuildHasher, + H: Hasher { +``` +> Source code: noir_stdlib/src/collections/map.nr#L313-L323 + + +Inserts a new key-value pair into the map. If the key was already in the map, its +previous value will be overridden with the newly provided one. + +Example: + +```rust title="insert_example" showLineNumbers +let mut map: HashMap> = HashMap::default(); + map.insert(12, 42); + assert(map.len() == 1); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L213-L217 + + +### remove + +```rust title="remove" showLineNumbers +pub fn remove( + &mut self, + key: K + ) + where + K: Eq + Hash, + B: BuildHasher, + H: Hasher { +``` +> Source code: noir_stdlib/src/collections/map.nr#L356-L365 + + +Removes the given key-value pair from the map. If the key was not already present +in the map, this does nothing. + +Example: + +```rust title="remove_example" showLineNumbers +map.remove(12); + assert(map.is_empty()); + + // If a key was not present in the map, remove does nothing + map.remove(12); + assert(map.is_empty()); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L221-L228 + + +### is_empty + +```rust title="is_empty" showLineNumbers +pub fn is_empty(self) -> bool { +``` +> Source code: noir_stdlib/src/collections/map.nr#L115-L117 + + +True if the length of the hash map is empty. + +Example: + +```rust title="is_empty_example" showLineNumbers +assert(map.is_empty()); + + map.insert(1, 2); + assert(!map.is_empty()); + + map.remove(1); + assert(map.is_empty()); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L230-L238 + + +### len + +```rust title="len" showLineNumbers +pub fn len(self) -> u64 { +``` +> Source code: noir_stdlib/src/collections/map.nr#L264-L266 + + +Returns the current length of this hash map. + +Example: + +```rust title="len_example" showLineNumbers +// This is equivalent to checking map.is_empty() + assert(map.len() == 0); + + map.insert(1, 2); + map.insert(3, 4); + map.insert(5, 6); + assert(map.len() == 3); + + // 3 was already present as a key in the hash map, so the length is unchanged + map.insert(3, 7); + assert(map.len() == 3); + + map.remove(1); + assert(map.len() == 2); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L240-L255 + + +### capacity + +```rust title="capacity" showLineNumbers +pub fn capacity(_self: Self) -> u64 { +``` +> Source code: noir_stdlib/src/collections/map.nr#L271-L273 + + +Returns the maximum capacity of this hashmap. This is always equal to the capacity +specified in the hashmap's type. + +Unlike hashmaps in general purpose programming languages, hashmaps in Noir have a +static capacity that does not increase as the map grows larger. Thus, this capacity +is also the maximum possible element count that can be inserted into the hashmap. +Due to hash collisions (modulo the hashmap length), it is likely the actual maximum +element count will be lower than the full capacity. + +Example: + +```rust title="capacity_example" showLineNumbers +let empty_map: HashMap> = HashMap::default(); + assert(empty_map.len() == 0); + assert(empty_map.capacity() == 42); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L257-L261 + + +### clear + +```rust title="clear" showLineNumbers +pub fn clear(&mut self) { +``` +> Source code: noir_stdlib/src/collections/map.nr#L93-L95 + + +Clears the hashmap, removing all key-value pairs from it. + +Example: + +```rust title="clear_example" showLineNumbers +assert(!map.is_empty()); + map.clear(); + assert(map.is_empty()); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L263-L267 + + +### contains_key + +```rust title="contains_key" showLineNumbers +pub fn contains_key( + self, + key: K + ) -> bool + where + K: Hash + Eq, + B: BuildHasher, + H: Hasher { +``` +> Source code: noir_stdlib/src/collections/map.nr#L101-L110 + + +True if the hashmap contains the given key. Unlike `get`, this will not also return +the value associated with the key. + +Example: + +```rust title="contains_key_example" showLineNumbers +if map.contains_key(7) { + let value = map.get(7); + assert(value.is_some()); + } else { + println("No value for key 7!"); + } +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L269-L276 + + +### entries + +```rust title="entries" showLineNumbers +pub fn entries(self) -> BoundedVec<(K, V), N> { +``` +> Source code: noir_stdlib/src/collections/map.nr#L123-L125 + + +Returns a vector of each key-value pair present in the hashmap. + +The length of the returned vector is always equal to the length of the hashmap. + +Example: + +```rust title="entries_example" showLineNumbers +let entries = map.entries(); + + // The length of a hashmap may not be compile-time known, so we + // need to loop over its capacity instead + for i in 0..map.capacity() { + if i < entries.len() { + let (key, value) = entries.get(i); + println(f"{key} -> {value}"); + } + } +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L310-L321 + + +### keys + +```rust title="keys" showLineNumbers +pub fn keys(self) -> BoundedVec { +``` +> Source code: noir_stdlib/src/collections/map.nr#L144-L146 + + +Returns a vector of each key present in the hashmap. + +The length of the returned vector is always equal to the length of the hashmap. + +Example: + +```rust title="keys_example" showLineNumbers +let keys = map.keys(); + + for i in 0..keys.max_len() { + if i < keys.len() { + let key = keys.get_unchecked(i); + let value = map.get(key).unwrap_unchecked(); + println(f"{key} -> {value}"); + } + } +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L323-L333 + + +### values + +```rust title="values" showLineNumbers +pub fn values(self) -> BoundedVec { +``` +> Source code: noir_stdlib/src/collections/map.nr#L164-L166 + + +Returns a vector of each value present in the hashmap. + +The length of the returned vector is always equal to the length of the hashmap. + +Example: + +```rust title="values_example" showLineNumbers +let values = map.values(); + + for i in 0..values.max_len() { + if i < values.len() { + let value = values.get_unchecked(i); + println(f"Found value {value}"); + } + } +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L335-L344 + + +### iter_mut + +```rust title="iter_mut" showLineNumbers +pub fn iter_mut( + &mut self, + f: fn(K, V) -> (K, V) + ) + where + K: Eq + Hash, + B: BuildHasher, + H: Hasher { +``` +> Source code: noir_stdlib/src/collections/map.nr#L183-L192 + + +Iterates through each key-value pair of the HashMap, setting each key-value pair to the +result returned from the given function. + +Note that since keys can be mutated, the HashMap needs to be rebuilt as it is iterated +through. If this is not desired, use `iter_values_mut` if only values need to be mutated, +or `entries` if neither keys nor values need to be mutated. + +The iteration order is left unspecified. As a result, if two keys are mutated to become +equal, which of the two values that will be present for the key in the resulting map is also unspecified. + +Example: + +```rust title="iter_mut_example" showLineNumbers +// Add 1 to each key in the map, and double the value associated with that key. + map.iter_mut(|k, v| (k + 1, v * 2)); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L348-L351 + + +### iter_keys_mut + +```rust title="iter_keys_mut" showLineNumbers +pub fn iter_keys_mut( + &mut self, + f: fn(K) -> K + ) + where + K: Eq + Hash, + B: BuildHasher, + H: Hasher { +``` +> Source code: noir_stdlib/src/collections/map.nr#L208-L217 + + +Iterates through the HashMap, mutating each key to the result returned from +the given function. + +Note that since keys can be mutated, the HashMap needs to be rebuilt as it is iterated +through. If only iteration is desired and the keys are not intended to be mutated, +prefer using `entries` instead. + +The iteration order is left unspecified. As a result, if two keys are mutated to become +equal, which of the two values that will be present for the key in the resulting map is also unspecified. + +Example: + +```rust title="iter_keys_mut_example" showLineNumbers +// Double each key, leaving the value associated with that key untouched + map.iter_keys_mut(|k| k * 2); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L353-L356 + + +### iter_values_mut + +```rust title="iter_values_mut" showLineNumbers +pub fn iter_values_mut(&mut self, f: fn(V) -> V) { +``` +> Source code: noir_stdlib/src/collections/map.nr#L233-L235 + + +Iterates through the HashMap, applying the given function to each value and mutating the +value to equal the result. This function is more efficient than `iter_mut` and `iter_keys_mut` +because the keys are untouched and the underlying hashmap thus does not need to be reordered. + +Example: + +```rust title="iter_values_mut_example" showLineNumbers +// Halve each value + map.iter_values_mut(|v| v / 2); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L358-L361 + + +### retain + +```rust title="retain" showLineNumbers +pub fn retain(&mut self, f: fn(K, V) -> bool) { +``` +> Source code: noir_stdlib/src/collections/map.nr#L247-L249 + + +Retains only the key-value pairs for which the given function returns true. +Any key-value pairs for which the function returns false will be removed from the map. + +Example: + +```rust title="retain_example" showLineNumbers +map.retain(|k, v| (k != 0) & (v != 0)); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L281-L283 + + +## Trait Implementations + +### default + +```rust title="default" showLineNumbers +impl Default for HashMap +where + B: BuildHasher + Default, + H: Hasher + Default +{ + fn default() -> Self { +``` +> Source code: noir_stdlib/src/collections/map.nr#L462-L469 + + +Constructs an empty HashMap. + +Example: + +```rust title="default_example" showLineNumbers +let hashmap: HashMap> = HashMap::default(); + assert(hashmap.is_empty()); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L202-L205 + + +### eq + +```rust title="eq" showLineNumbers +impl Eq for HashMap +where + K: Eq + Hash, + V: Eq, + B: BuildHasher, + H: Hasher +{ + fn eq(self, other: HashMap) -> bool { +``` +> Source code: noir_stdlib/src/collections/map.nr#L426-L435 + + +Checks if two HashMaps are equal. + +Example: + +```rust title="eq_example" showLineNumbers +let mut map1: HashMap> = HashMap::default(); + let mut map2: HashMap> = HashMap::default(); + + map1.insert(1, 2); + map1.insert(3, 4); + + map2.insert(3, 4); + map2.insert(1, 2); + + assert(map1 == map2); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L285-L296 + diff --git a/docs/versioned_docs/version-v0.26.0/noir/standard_library/containers/index.md b/docs/versioned_docs/version-v0.26.0/noir/standard_library/containers/index.md new file mode 100644 index 00000000000..ea84c6d5c21 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/noir/standard_library/containers/index.md @@ -0,0 +1,5 @@ +--- +title: Containers +description: Container types provided by Noir's standard library for storing and retrieving data +keywords: [containers, data types, vec, hashmap] +--- diff --git a/docs/versioned_docs/version-v0.26.0/noir/standard_library/containers/vec.mdx b/docs/versioned_docs/version-v0.26.0/noir/standard_library/containers/vec.mdx new file mode 100644 index 00000000000..fcfd7e07aa0 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/noir/standard_library/containers/vec.mdx @@ -0,0 +1,151 @@ +--- +title: Vectors +description: Delve into the Vec data type in Noir. Learn about its methods, practical examples, and best practices for using Vectors in your Noir code. +keywords: [noir, vector type, methods, examples, dynamic arrays] +sidebar_position: 6 +--- + +import Experimental from '@site/src/components/Notes/_experimental.mdx'; + + + +A vector is a collection type similar to Rust's `Vec` type. In Noir, it is a convenient way to use slices as mutable arrays. + +Example: + +```rust +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 +``` + +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 +``` + +Example: + +```rust +let slice: [Field] = &[1, 2, 3]; +let vector_from_slice = Vec::from_slice(slice); +assert(vector_from_slice.len() == 3); +``` + +### len + +Returns the number of elements in the vector. + +```rust +pub fn len(self) -> Field +``` + +Example: + +```rust +let empty_vector: Vec = Vec::new(); +assert(empty_vector.len() == 0); +``` + +### 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 +``` + +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) +``` + +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 +``` + +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) +``` + +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 +``` + +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); +``` diff --git a/docs/versioned_docs/version-v0.26.0/noir/standard_library/cryptographic_primitives/_category_.json b/docs/versioned_docs/version-v0.26.0/noir/standard_library/cryptographic_primitives/_category_.json new file mode 100644 index 00000000000..5d694210bbf --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/noir/standard_library/cryptographic_primitives/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 0, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.26.0/noir/standard_library/cryptographic_primitives/ec_primitives.md b/docs/versioned_docs/version-v0.26.0/noir/standard_library/cryptographic_primitives/ec_primitives.md new file mode 100644 index 00000000000..d2b42d67b7c --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/noir/standard_library/cryptographic_primitives/ec_primitives.md @@ -0,0 +1,102 @@ +--- +title: Elliptic Curve Primitives +keywords: [cryptographic primitives, Noir project] +sidebar_position: 4 +--- + +Data structures and methods on them that allow you to carry out computations involving elliptic +curves over the (mathematical) field corresponding to `Field`. For the field currently at our +disposal, applications would involve a curve embedded in BN254, e.g. the +[Baby Jubjub curve](https://eips.ethereum.org/EIPS/eip-2494). + +## Data structures + +### Elliptic curve configurations + +(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Curve`), i.e. the specific elliptic +curve you want to use, which would be specified using any one of the methods +`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::new` which take the coefficients in the +defining equation together with a generator point as parameters. You can find more detail in the +comments in +[`noir_stdlib/src/ec.nr`](https://github.com/noir-lang/noir/blob/master/noir_stdlib/src/ec.nr), but +the gist of it is that the elliptic curves of interest are usually expressed in one of the standard +forms implemented here (Twisted Edwards, Montgomery and Short Weierstraß), and in addition to that, +you could choose to use `affine` coordinates (Cartesian coordinates - the usual (x,y) - possibly +together with a point at infinity) or `curvegroup` coordinates (some form of projective coordinates +requiring more coordinates but allowing for more efficient implementations of elliptic curve +operations). Conversions between all of these forms are provided, and under the hood these +conversions are done whenever an operation is more efficient in a different representation (or a +mixed coordinate representation is employed). + +### Points + +(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Point`), i.e. points lying on the +elliptic curve. For a curve configuration `c` and a point `p`, it may be checked that `p` +does indeed lie on `c` by calling `c.contains(p1)`. + +## Methods + +(given a choice of curve representation, e.g. use `std::ec::tecurve::affine::Curve` and use +`std::ec::tecurve::affine::Point`) + +- The **zero element** is given by `Point::zero()`, and we can verify whether a point `p: Point` is + zero by calling `p.is_zero()`. +- **Equality**: Points `p1: Point` and `p2: Point` may be checked for equality by calling + `p1.eq(p2)`. +- **Addition**: For `c: Curve` and points `p1: Point` and `p2: Point` on the curve, adding these two + points is accomplished by calling `c.add(p1,p2)`. +- **Negation**: For a point `p: Point`, `p.negate()` is its negation. +- **Subtraction**: For `c` and `p1`, `p2` as above, subtracting `p2` from `p1` is accomplished by + calling `c.subtract(p1,p2)`. +- **Scalar multiplication**: For `c` as above, `p: Point` a point on the curve and `n: Field`, + scalar multiplication is given by `c.mul(n,p)`. If instead `n :: [u1; N]`, i.e. `n` is a bit + array, the `bit_mul` method may be used instead: `c.bit_mul(n,p)` +- **Multi-scalar multiplication**: For `c` as above and arrays `n: [Field; N]` and `p: [Point; N]`, + multi-scalar multiplication is given by `c.msm(n,p)`. +- **Coordinate representation conversions**: The `into_group` method converts a point or curve + configuration in the affine representation to one in the CurveGroup representation, and + `into_affine` goes in the other direction. +- **Curve representation conversions**: `tecurve` and `montcurve` curves and points are equivalent + and may be converted between one another by calling `into_montcurve` or `into_tecurve` on their + configurations or points. `swcurve` is more general and a curve c of one of the other two types + may be converted to this representation by calling `c.into_swcurve()`, whereas a point `p` lying + on the curve given by `c` may be mapped to its corresponding `swcurve` point by calling + `c.map_into_swcurve(p)`. +- **Map-to-curve methods**: The Elligator 2 method of mapping a field element `n: Field` into a + `tecurve` or `montcurve` with configuration `c` may be called as `c.elligator2_map(n)`. For all of + the curve configurations, the SWU map-to-curve method may be called as `c.swu_map(z,n)`, where + `z: Field` depends on `Field` and `c` and must be chosen by the user (the conditions it needs to + satisfy are specified in the comments + [here](https://github.com/noir-lang/noir/blob/master/noir_stdlib/src/ec.nr)). + +## Examples + +The +[ec_baby_jubjub test](https://github.com/noir-lang/noir/blob/master/test_programs/compile_success_empty/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.26.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx b/docs/versioned_docs/version-v0.26.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx new file mode 100644 index 00000000000..4394b48f907 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx @@ -0,0 +1,98 @@ +--- +title: ECDSA Signature Verification +description: Learn about the cryptographic primitives regarding ECDSA over the secp256k1 and secp256r1 curves +keywords: [cryptographic primitives, Noir project, ecdsa, secp256k1, secp256r1, signatures] +sidebar_position: 3 +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +Noir supports ECDSA signatures verification over the secp256k1 and secp256r1 curves. + +## ecdsa_secp256k1::verify_signature + +Verifier for ECDSA Secp256k1 signatures. +See ecdsa_secp256k1::verify_signature_slice for a version that accepts slices directly. + +```rust title="ecdsa_secp256k1" showLineNumbers +pub fn verify_signature( + public_key_x: [u8; 32], + public_key_y: [u8; 32], + signature: [u8; 64], + message_hash: [u8; N] +) -> bool +``` +> Source code: noir_stdlib/src/ecdsa_secp256k1.nr#L2-L9 + + +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_secp256k1::verify_signature_slice + +Verifier for ECDSA Secp256k1 signatures where the message is a slice. + +```rust title="ecdsa_secp256k1_slice" showLineNumbers +pub fn verify_signature_slice( + public_key_x: [u8; 32], + public_key_y: [u8; 32], + signature: [u8; 64], + message_hash: [u8] +) -> bool +``` +> Source code: noir_stdlib/src/ecdsa_secp256k1.nr#L13-L20 + + + + +## ecdsa_secp256r1::verify_signature + +Verifier for ECDSA Secp256r1 signatures. +See ecdsa_secp256r1::verify_signature_slice for a version that accepts slices directly. + +```rust title="ecdsa_secp256r1" showLineNumbers +pub fn verify_signature( + public_key_x: [u8; 32], + public_key_y: [u8; 32], + signature: [u8; 64], + message_hash: [u8; N] +) -> bool +``` +> Source code: noir_stdlib/src/ecdsa_secp256r1.nr#L2-L9 + + +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); +} +``` + + + +## ecdsa_secp256r1::verify_signature + +Verifier for ECDSA Secp256r1 signatures where the message is a slice. + +```rust title="ecdsa_secp256r1_slice" showLineNumbers +pub fn verify_signature_slice( + public_key_x: [u8; 32], + public_key_y: [u8; 32], + signature: [u8; 64], + message_hash: [u8] +) -> bool +``` +> Source code: noir_stdlib/src/ecdsa_secp256r1.nr#L13-L20 + + + diff --git a/docs/versioned_docs/version-v0.26.0/noir/standard_library/cryptographic_primitives/eddsa.mdx b/docs/versioned_docs/version-v0.26.0/noir/standard_library/cryptographic_primitives/eddsa.mdx new file mode 100644 index 00000000000..c2c0624dfad --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/noir/standard_library/cryptographic_primitives/eddsa.mdx @@ -0,0 +1,37 @@ +--- +title: EdDSA Verification +description: Learn about the cryptographic primitives regarding EdDSA +keywords: [cryptographic primitives, Noir project, eddsa, signatures] +sidebar_position: 5 +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +## eddsa::eddsa_poseidon_verify + +Verifier for EdDSA signatures + +```rust +fn eddsa_poseidon_verify(public_key_x : Field, public_key_y : Field, signature_s: Field, signature_r8_x: Field, signature_r8_y: Field, message: Field) -> bool +``` + +It is also possible to specify the hash algorithm used for the signature by using the `eddsa_verify_with_hasher` function with a parameter implementing the Hasher trait. For instance, if you want to use Poseidon2 instead, you can do the following: +```rust +use dep::std::hash::poseidon2::Poseidon2Hasher; + +let mut hasher = Poseidon2Hasher::default(); +eddsa_verify_with_hasher(pub_key_a.x, pub_key_a.y, s_a, r8_a.x, r8_a.y, msg, &mut hasher); +``` + + + +## eddsa::eddsa_to_pub + +Private to public key conversion. + +Returns `(pub_key_x, pub_key_y)` + +```rust +fn eddsa_to_pub(secret : Field) -> (Field, Field) +``` + diff --git a/docs/versioned_docs/version-v0.26.0/noir/standard_library/cryptographic_primitives/hashes.mdx b/docs/versioned_docs/version-v0.26.0/noir/standard_library/cryptographic_primitives/hashes.mdx new file mode 100644 index 00000000000..695c7d9406f --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/noir/standard_library/cryptographic_primitives/hashes.mdx @@ -0,0 +1,331 @@ +--- +title: Hash methods +description: + Learn about the cryptographic primitives ready to use for any Noir project, including sha256, + blake2s, pedersen, mimc_bn254 and mimc +keywords: + [cryptographic primitives, Noir project, sha256, blake2s, pedersen, mimc_bn254, mimc, hash] +sidebar_position: 0 +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +## sha256 + +Given an array of bytes, returns the resulting sha256 hash. +See sha256_slice for a version that works directly on slices. + +```rust title="sha256" showLineNumbers +pub fn sha256(input: [u8; N]) -> [u8; 32] +``` +> Source code: noir_stdlib/src/hash.nr#L10-L12 + + +example: + +```rust +fn main() { + let x = [163, 117, 178, 149]; // some random bytes + let hash = std::hash::sha256(x); +} +``` + + + +## sha256_slice + +A version of sha256 specialized to slices: + +```rust title="sha256_slice" showLineNumbers +pub fn sha256_slice(input: [u8]) -> [u8; 32] +``` +> Source code: noir_stdlib/src/hash.nr#L16-L18 + + + + +## blake2s + +Given an array of bytes, returns an array with the Blake2 hash +See blake2s_slice for a version that works directly on slices. + +```rust title="blake2s" showLineNumbers +pub fn blake2s(input: [u8; N]) -> [u8; 32] +``` +> Source code: noir_stdlib/src/hash.nr#L22-L24 + + +example: + +```rust +fn main() { + let x = [163, 117, 178, 149]; // some random bytes + let hash = std::hash::blake2s(x); +} +``` + + + +## blake2s_slice + +A version of blake2s specialized to slices: + +```rust title="blake2s_slice" showLineNumbers +pub fn blake2s_slice(input: [u8]) -> [u8; 32] +``` +> Source code: noir_stdlib/src/hash.nr#L28-L30 + + + + +## blake3 + +Given an array of bytes, returns an array with the Blake3 hash +See blake3_slice for a version that works directly on slices. + +```rust title="blake3" showLineNumbers +pub fn blake3(input: [u8; N]) -> [u8; 32] +``` +> Source code: noir_stdlib/src/hash.nr#L34-L36 + + +example: + +```rust +fn main() { + let x = [163, 117, 178, 149]; // some random bytes + let hash = std::hash::blake3(x); +} +``` + + + +## blake3_slice + +A version of blake3 specialized to slices: + +```rust title="blake3_slice" showLineNumbers +pub fn blake3_slice(input: [u8]) -> [u8; 32] +``` +> Source code: noir_stdlib/src/hash.nr#L40-L42 + + + + +## pedersen_hash + +Given an array of Fields, returns the Pedersen hash. +See pedersen_hash_slice for a version that works directly on slices. + +```rust title="pedersen_hash" showLineNumbers +pub fn pedersen_hash(input: [Field; N]) -> Field +``` +> Source code: noir_stdlib/src/hash.nr#L78-L80 + + +example: + +```rust title="pedersen-hash" showLineNumbers +use dep::std; + +fn main(x: Field, y: Field, expected_hash: Field) { + let hash = std::hash::pedersen_hash([x, y]); + assert_eq(hash, expected_hash); +} +``` +> Source code: test_programs/execution_success/pedersen_hash/src/main.nr#L1-L8 + + + + +## pedersen_hash_slice + +Given a slice of Fields, returns the Pedersen hash. + +```rust title="pedersen_hash_slice" showLineNumbers +pub fn pedersen_hash_slice(input: [Field]) -> Field +``` +> Source code: noir_stdlib/src/hash.nr#L85-L87 + + + + +## pedersen_commitment + +Given an array of Fields, returns the Pedersen commitment. +See pedersen_commitment_slice for a version that works directly on slices. + +```rust title="pedersen_commitment" showLineNumbers +struct PedersenPoint { + x : Field, + y : Field, +} + +pub fn pedersen_commitment(input: [Field; N]) -> PedersenPoint { +``` +> Source code: noir_stdlib/src/hash.nr#L45-L52 + + +example: + +```rust title="pedersen-commitment" showLineNumbers +use dep::std; + +fn main(x: Field, y: Field, expected_commitment: std::hash::PedersenPoint) { + let commitment = std::hash::pedersen_commitment([x, y]); + assert_eq(commitment.x, expected_commitment.x); + assert_eq(commitment.y, expected_commitment.y); +} +``` +> Source code: test_programs/execution_success/pedersen_commitment/src/main.nr#L1-L9 + + + + +## pedersen_commitment_slice + +Given a slice of Fields, returns the Pedersen commitment. + +```rust title="pedersen_commitment_slice" showLineNumbers +pub fn pedersen_commitment_slice(input: [Field]) -> PedersenPoint { + pedersen_commitment_with_separator_slice(input, 0) +} +``` +> Source code: noir_stdlib/src/hash.nr#L56-L60 + + + + +## 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. See keccak256_slice for a version that works +directly on slices. + +```rust title="keccak256" showLineNumbers +pub fn keccak256(input: [u8; N], message_size: u32) -> [u8; 32] +``` +> Source code: noir_stdlib/src/hash.nr#L113-L115 + + +example: + +```rust title="keccak256" showLineNumbers +use dep::std; + +fn main(x: Field, result: [u8; 32]) { + // We use the `as` keyword here to denote the fact that we want to take just the first byte from the x Field + // The padding is taken care of by the program + let digest = std::hash::keccak256([x as u8], 1); + assert(digest == result); + + //#1399: variable message 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); + + 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); + + assert(hash_a != hash_c); +} +``` +> Source code: test_programs/execution_success/keccak256/src/main.nr#L1-L22 + + + + +## keccak256_slice + +Given a slice of bytes (`u8`), returns the resulting keccak hash as an array of +32 bytes (`[u8; 32]`). + +```rust title="keccak256_slice" showLineNumbers +pub fn keccak256_slice(input: [u8], message_size: u32) -> [u8; 32] +``` +> Source code: noir_stdlib/src/hash.nr#L119-L121 + + + + +## 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 title="poseidon" showLineNumbers +use dep::std::hash::poseidon; +use dep::std::hash::poseidon2; + +fn main(x1: [Field; 2], y1: pub Field, x2: [Field; 4], y2: pub Field, x3: [Field; 4], y3: Field) { + let hash1 = poseidon::bn254::hash_2(x1); + assert(hash1 == y1); + + let hash2 = poseidon::bn254::hash_4(x2); + assert(hash2 == y2); + + let hash3 = poseidon2::Poseidon2::hash(x3, x3.len()); + assert(hash3 == y3); +} +``` +> Source code: test_programs/execution_success/poseidon_bn254_hash/src/main.nr#L1-L15 + + +## poseidon 2 + +Given an array of Fields, returns a new Field with the Poseidon2 Hash. Contrary to the Poseidon +function, there is only one hash and you can specify a message_size to hash only the first +`message_size` bytes of the input, + +```rust +// example for hashing the first three elements of the input +Poseidon2::hash(input, 3); +``` + +The above example for Poseidon also includes Poseidon2. + +## 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]) -> 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.26.0/noir/standard_library/cryptographic_primitives/index.md b/docs/versioned_docs/version-v0.26.0/noir/standard_library/cryptographic_primitives/index.md new file mode 100644 index 00000000000..650f30165d5 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/noir/standard_library/cryptographic_primitives/index.md @@ -0,0 +1,14 @@ +--- +title: Cryptographic Primitives +description: + Learn about the cryptographic primitives ready to use for any Noir project +keywords: + [ + cryptographic primitives, + Noir project, + ] +--- + +The Noir team is progressively adding new cryptographic primitives to the standard library. Reach out for news or if you would be interested in adding more of these calculations in Noir. + +Some methods are available thanks to the Aztec backend, not being performed using Noir. When using other backends, these methods may or may not be supplied. diff --git a/docs/versioned_docs/version-v0.26.0/noir/standard_library/cryptographic_primitives/scalar.mdx b/docs/versioned_docs/version-v0.26.0/noir/standard_library/cryptographic_primitives/scalar.mdx new file mode 100644 index 00000000000..df411ca5443 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/noir/standard_library/cryptographic_primitives/scalar.mdx @@ -0,0 +1,33 @@ +--- +title: Scalar multiplication +description: See how you can perform scalar multiplications over a fixed base in Noir +keywords: [cryptographic primitives, Noir project, scalar multiplication] +sidebar_position: 1 +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +## scalar_mul::fixed_base_embedded_curve + +Performs scalar multiplication over the embedded curve whose coordinates are defined by the +configured noir field. For the BN254 scalar field, this is BabyJubJub or Grumpkin. + +```rust title="fixed_base_embedded_curve" showLineNumbers +pub fn fixed_base_embedded_curve( + low: Field, + high: Field +) -> [Field; 2] +``` +> Source code: noir_stdlib/src/scalar_mul.nr#L27-L32 + + +example + +```rust +fn main(x : Field) { + let scal = std::scalar_mul::fixed_base_embedded_curve(x); + println(scal); +} +``` + + diff --git a/docs/versioned_docs/version-v0.26.0/noir/standard_library/cryptographic_primitives/schnorr.mdx b/docs/versioned_docs/version-v0.26.0/noir/standard_library/cryptographic_primitives/schnorr.mdx new file mode 100644 index 00000000000..b59e69c8f07 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/noir/standard_library/cryptographic_primitives/schnorr.mdx @@ -0,0 +1,64 @@ +--- +title: Schnorr Signatures +description: Learn how you can verify Schnorr signatures using Noir +keywords: [cryptographic primitives, Noir project, schnorr, signatures] +sidebar_position: 2 +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +## schnorr::verify_signature + +Verifier for Schnorr signatures over the embedded curve (for BN254 it is Grumpkin). +See schnorr::verify_signature_slice for a version that works directly on slices. + +```rust title="schnorr_verify" showLineNumbers +pub fn verify_signature( + public_key_x: Field, + public_key_y: Field, + signature: [u8; 64], + message: [u8; N] +) -> bool +``` +> Source code: noir_stdlib/src/schnorr.nr#L2-L9 + + +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() +); + +... +``` + + + +## schnorr::verify_signature_slice + +Verifier for Schnorr signatures over the embedded curve (for BN254 it is Grumpkin) +where the message is a slice. + +```rust title="schnorr_verify_slice" showLineNumbers +pub fn verify_signature_slice( + public_key_x: Field, + public_key_y: Field, + signature: [u8; 64], + message: [u8] +) -> bool +``` +> Source code: noir_stdlib/src/schnorr.nr#L13-L20 + + + diff --git a/docs/versioned_docs/version-v0.26.0/noir/standard_library/logging.md b/docs/versioned_docs/version-v0.26.0/noir/standard_library/logging.md new file mode 100644 index 00000000000..db75ef9f86f --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/noir/standard_library/logging.md @@ -0,0 +1,78 @@ +--- +title: Logging +description: + Learn how to use the println statement for debugging in Noir with this tutorial. Understand the + basics of logging in Noir and how to implement it in your code. +keywords: + [ + noir logging, + println statement, + print statement, + debugging in noir, + noir std library, + logging tutorial, + basic logging in noir, + noir logging implementation, + noir debugging techniques, + rust, + ] +--- + +The standard library provides two familiar statements you can use: `println` and `print`. Despite being a limited implementation of rust's `println!` and `print!` macros, these constructs can be useful for debugging. + +You can print the output of both statements in your Noir code by using the `nargo execute` command or the `--show-output` flag when using `nargo test` (provided there are print statements in your tests). + +It is recommended to use `nargo execute` if you want to debug failing constraints with `println` or `print` statements. This is due to every input in a test being a constant rather than a witness, so we issue an error during compilation while we only print during execution (which comes after compilation). Neither `println`, nor `print` are callable for failed constraints caught at compile time. + +Both `print` and `println` are generic functions which can work on integers, fields, strings, and even structs or expressions. Note however, that slices are currently unsupported. For example: + +```rust +struct Person { + age: Field, + height: Field, +} + +fn main(age: Field, height: Field) { + let person = Person { + age: age, + height: height, + }; + println(person); + println(age + height); + println("Hello world!"); +} +``` + +You can print different types in the same statement (including strings) with a type called `fmtstr`. It can be specified in the same way as a normal string, just prepended with an "f" character: + +```rust + let fmt_str = f"i: {i}, j: {j}"; + println(fmt_str); + + let s = myStruct { y: x, x: y }; + println(s); + + println(f"i: {i}, s: {s}"); + + println(x); + println([x, y]); + + let foo = fooStruct { my_struct: s, foo: 15 }; + println(f"s: {s}, foo: {foo}"); + + println(15); // prints 0x0f, implicit Field + println(-1 as u8); // prints 255 + println(-1 as i8); // prints -1 +``` + +Examples shown above are interchangeable between the two `print` statements: + +```rust +let person = Person { age : age, height : height }; + +println(person); +print(person); + +println("Hello world!"); // Prints with a newline at the end of the input +print("Hello world!"); // Prints the input and keeps cursor on the same line +``` diff --git a/docs/versioned_docs/version-v0.26.0/noir/standard_library/merkle_trees.md b/docs/versioned_docs/version-v0.26.0/noir/standard_library/merkle_trees.md new file mode 100644 index 00000000000..6a9ebf72ada --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/noir/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/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.as_slice()); + 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.26.0/noir/standard_library/options.md b/docs/versioned_docs/version-v0.26.0/noir/standard_library/options.md new file mode 100644 index 00000000000..a1bd4e1de5f --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/noir/standard_library/options.md @@ -0,0 +1,101 @@ +--- +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), +} +``` + +The `Option` type, already imported into your Noir program, can be used directly: + +```rust +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. + +### expect + +Asserts `self.is_some()` with a provided custom message and returns the contained `Some` value. The custom message is expected to be a format string. + +### 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.26.0/noir/standard_library/recursion.md b/docs/versioned_docs/version-v0.26.0/noir/standard_library/recursion.md new file mode 100644 index 00000000000..a93894043dc --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/noir/standard_library/recursion.md @@ -0,0 +1,88 @@ +--- +title: Recursive Proofs +description: Learn about how to write recursive proofs in Noir. +keywords: [recursion, recursive proofs, verification_key, 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. + +Read [the explainer on recursion](../../explainers/explainer-recursion.md) to know more about this function and the [guide on how to use it.](../../how_to/how-to-recursion.md) + +## The `#[recursive]` Attribute + +In Noir, the `#[recursive]` attribute is used to indicate that a circuit is designed for recursive proof generation. When applied, it informs the compiler and the tooling that the circuit should be compiled in a way that makes its proofs suitable for recursive verification. This attribute eliminates the need for manual flagging of recursion at the tooling level, streamlining the proof generation process for recursive circuits. + +### Example usage with `#[recursive]` + +```rust +#[recursive] +fn main(x: Field, y: pub Field) { + assert(x == y, "x and y are not equal"); +} + +// This marks the circuit as recursion-friendly and indicates that proofs generated from this circuit +// are intended for recursive verification. +``` + +By incorporating this attribute directly in the circuit's definition, tooling like Nargo and NoirJS can automatically execute recursive-specific duties for Noir programs (e.g. recursive-friendly proof artifact generation) without additional flags or configurations. + +## Verifying Recursive Proofs + +```rust +#[foreign(recursive_aggregation)] +pub fn verify_proof(verification_key: [Field], proof: [Field], public_inputs: [Field], key_hash: Field) {} +``` + +:::info + +This is a black box function. Read [this section](./black_box_fns) to learn more about black box functions in Noir. + +::: + +## Example usage + +```rust +use dep::std; + +fn main( + verification_key : [Field; 114], + proof : [Field; 93], + public_inputs : [Field; 1], + key_hash : Field, + proof_b : [Field; 93], +) { + std::verify_proof( + verification_key.as_slice(), + proof.as_slice(), + public_inputs.as_slice(), + key_hash + ); + + std::verify_proof( + verification_key.as_slice(), + proof_b.as_slice(), + public_inputs.as_slice(), + key_hash + ); +} +``` + +You can see a full example of recursive proofs in [this example recursion demo repo](https://github.com/noir-lang/noir-examples/tree/master/recursion). + +## 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. + +### `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. diff --git a/docs/versioned_docs/version-v0.26.0/noir/standard_library/traits.md b/docs/versioned_docs/version-v0.26.0/noir/standard_library/traits.md new file mode 100644 index 00000000000..68a9dc3d54b --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/noir/standard_library/traits.md @@ -0,0 +1,408 @@ +--- +title: Traits +description: Noir's stdlib provides a few commonly used traits. +keywords: [traits, trait, interface, protocol, default, add, eq] +--- + +## `std::default` + +### `std::default::Default` + +```rust title="default-trait" showLineNumbers +trait Default { + fn default() -> Self; +} +``` +> Source code: noir_stdlib/src/default.nr#L1-L5 + + +Constructs a default value of a type. + +Implementations: +```rust +impl Default for Field { .. } + +impl Default for i8 { .. } +impl Default for i16 { .. } +impl Default for i32 { .. } +impl Default for i64 { .. } + +impl Default for u8 { .. } +impl Default for u16 { .. } +impl Default for u32 { .. } +impl Default for u64 { .. } + +impl Default for () { .. } +impl Default for bool { .. } + +impl Default for [T; N] + where T: Default { .. } + +impl Default for [T] { .. } + +impl Default for (A, B) + where A: Default, B: Default { .. } + +impl Default for (A, B, C) + where A: Default, B: Default, C: Default { .. } + +impl Default for (A, B, C, D) + where A: Default, B: Default, C: Default, D: Default { .. } + +impl Default for (A, B, C, D, E) + where A: Default, B: Default, C: Default, D: Default, E: Default { .. } +``` + +For primitive integer types, the return value of `default` is `0`. Container +types such as arrays are filled with default values of their element type, +except slices whose length is unknown and thus defaulted to zero. + + +## `std::convert` + +### `std::convert::From` + +```rust title="from-trait" showLineNumbers +trait From { + fn from(input: T) -> Self; +} +``` +> Source code: noir_stdlib/src/convert.nr#L1-L5 + + +The `From` trait defines how to convert from a given type `T` to the type on which the trait is implemented. + +The Noir standard library provides a number of implementations of `From` between primitive types. +```rust title="from-impls" showLineNumbers +// Unsigned integers + +impl From for u32 { fn from(value: u8) -> u32 { value as u32 } } + +impl From for u64 { fn from(value: u8) -> u64 { value as u64 } } +impl From for u64 { fn from(value: u32) -> u64 { value as u64 } } + +impl From for Field { fn from(value: u8) -> Field { value as Field } } +impl From for Field { fn from(value: u32) -> Field { value as Field } } +impl From for Field { fn from(value: u64) -> Field { value as Field } } + +// Signed integers + +impl From for i32 { fn from(value: i8) -> i32 { value as i32 } } + +impl From for i64 { fn from(value: i8) -> i64 { value as i64 } } +impl From for i64 { fn from(value: i32) -> i64 { value as i64 } } + +// Booleans +impl From for u8 { fn from(value: bool) -> u8 { value as u8 } } +impl From for u32 { fn from(value: bool) -> u32 { value as u32 } } +impl From for u64 { fn from(value: bool) -> u64 { value as u64 } } +impl From for i8 { fn from(value: bool) -> i8 { value as i8 } } +impl From for i32 { fn from(value: bool) -> i32 { value as i32 } } +impl From for i64 { fn from(value: bool) -> i64 { value as i64 } } +impl From for Field { fn from(value: bool) -> Field { value as Field } } +``` +> Source code: noir_stdlib/src/convert.nr#L25-L52 + + +#### When to implement `From` + +As a general rule of thumb, `From` may be implemented in the [situations where it would be suitable in Rust](https://doc.rust-lang.org/std/convert/trait.From.html#when-to-implement-from): + +- The conversion is *infallible*: Noir does not provide an equivalent to Rust's `TryFrom`, if the conversion can fail then provide a named method instead. +- The conversion is *lossless*: semantically, it should not lose or discard information. For example, `u32: From` can losslessly convert any `u16` into a valid `u32` such that the original `u16` can be recovered. On the other hand, `u16: From` should not be implemented as `2**16` is a `u32` which cannot be losslessly converted into a `u16`. +- The conversion is *value-preserving*: the conceptual kind and meaning of the resulting value is the same, even though the Noir type and technical representation might be different. While it's possible to infallibly and losslessly convert a `u8` into a `str<2>` hex representation, `4u8` and `"04"` are too different for `str<2>: From` to be implemented. +- The conversion is *obvious*: it's the only reasonable conversion between the two types. If there's ambiguity on how to convert between them such that the same input could potentially map to two different values then a named method should be used. For instance rather than implementing `U128: From<[u8; 16]>`, the methods `U128::from_le_bytes` and `U128::from_be_bytes` are used as otherwise the endianness of the array would be ambiguous, resulting in two potential values of `U128` from the same byte array. + +One additional recommendation specific to Noir is: +- The conversion is *efficient*: it's relatively cheap to convert between the two types. Due to being a ZK DSL, it's more important to avoid unnecessary computation compared to Rust. If the implementation of `From` would encourage users to perform unnecessary conversion, resulting in additional proving time, then it may be preferable to expose functionality such that this conversion may be avoided. + +### `std::convert::Into` + +The `Into` trait is defined as the reciprocal of `From`. It should be easy to convince yourself that if we can convert to type `A` from type `B`, then it's possible to convert type `B` into type `A`. + +For this reason, implementing `From` on a type will automatically generate a matching `Into` implementation. One should always prefer implementing `From` over `Into` as implementing `Into` will not generate a matching `From` implementation. + +```rust title="into-trait" showLineNumbers +trait Into { + fn into(input: Self) -> T; +} + +impl Into for U where T: From { + fn into(input: U) -> T { + T::from(input) + } +} +``` +> Source code: noir_stdlib/src/convert.nr#L13-L23 + + +`Into` is most useful when passing function arguments where the types don't quite match up with what the function expects. In this case, the compiler has enough type information to perform the necessary conversion by just appending `.into()` onto the arguments in question. + + +## `std::cmp` + +### `std::cmp::Eq` + +```rust title="eq-trait" showLineNumbers +trait Eq { + fn eq(self, other: Self) -> bool; +} +``` +> Source code: noir_stdlib/src/cmp.nr#L1-L5 + + +Returns `true` if `self` is equal to `other`. Implementing this trait on a type +allows the type to be used with `==` and `!=`. + +Implementations: +```rust +impl Eq for Field { .. } + +impl Eq for i8 { .. } +impl Eq for i16 { .. } +impl Eq for i32 { .. } +impl Eq for i64 { .. } + +impl Eq for u8 { .. } +impl Eq for u16 { .. } +impl Eq for u32 { .. } +impl Eq for u64 { .. } + +impl Eq for () { .. } +impl Eq for bool { .. } + +impl Eq for [T; N] + where T: Eq { .. } + +impl Eq for [T] + where T: Eq { .. } + +impl Eq for (A, B) + where A: Eq, B: Eq { .. } + +impl Eq for (A, B, C) + where A: Eq, B: Eq, C: Eq { .. } + +impl Eq for (A, B, C, D) + where A: Eq, B: Eq, C: Eq, D: Eq { .. } + +impl Eq for (A, B, C, D, E) + where A: Eq, B: Eq, C: Eq, D: Eq, E: Eq { .. } +``` + +### `std::cmp::Ord` + +```rust title="ord-trait" showLineNumbers +trait Ord { + fn cmp(self, other: Self) -> Ordering; +} +``` +> Source code: noir_stdlib/src/cmp.nr#L102-L106 + + +`a.cmp(b)` compares two values returning `Ordering::less()` if `a < b`, +`Ordering::equal()` if `a == b`, or `Ordering::greater()` if `a > b`. +Implementing this trait on a type allows `<`, `<=`, `>`, and `>=` to be +used on values of the type. + +Implementations: + +```rust +impl Ord for u8 { .. } +impl Ord for u16 { .. } +impl Ord for u32 { .. } +impl Ord for u64 { .. } + +impl Ord for i8 { .. } +impl Ord for i16 { .. } +impl Ord for i32 { .. } + +impl Ord for i64 { .. } + +impl Ord for () { .. } +impl Ord for bool { .. } + +impl Ord for [T; N] + where T: Ord { .. } + +impl Ord for [T] + where T: Ord { .. } + +impl Ord for (A, B) + where A: Ord, B: Ord { .. } + +impl Ord for (A, B, C) + where A: Ord, B: Ord, C: Ord { .. } + +impl Ord for (A, B, C, D) + where A: Ord, B: Ord, C: Ord, D: Ord { .. } + +impl Ord for (A, B, C, D, E) + where A: Ord, B: Ord, C: Ord, D: Ord, E: Ord { .. } +``` + +## `std::ops` + +### `std::ops::Add`, `std::ops::Sub`, `std::ops::Mul`, and `std::ops::Div` + +These traits abstract over addition, subtraction, multiplication, and division respectively. +Implementing these traits for a given type will also allow that type to be used with the corresponding operator +for that trait (`+` for Add, etc) in addition to the normal method names. + +```rust title="add-trait" showLineNumbers +trait Add { + fn add(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L1-L5 + +```rust title="sub-trait" showLineNumbers +trait Sub { + fn sub(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L17-L21 + +```rust title="mul-trait" showLineNumbers +trait Mul { + fn mul(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L33-L37 + +```rust title="div-trait" showLineNumbers +trait Div { + fn div(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L49-L53 + + +The implementations block below is given for the `Add` trait, but the same types that implement +`Add` also implement `Sub`, `Mul`, and `Div`. + +Implementations: +```rust +impl Add for Field { .. } + +impl Add for i8 { .. } +impl Add for i16 { .. } +impl Add for i32 { .. } +impl Add for i64 { .. } + +impl Add for u8 { .. } +impl Add for u16 { .. } +impl Add for u32 { .. } +impl Add for u64 { .. } +``` + +### `std::ops::Rem` + +```rust title="rem-trait" showLineNumbers +trait Rem{ + fn rem(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L65-L69 + + +`Rem::rem(a, b)` is the remainder function returning the result of what is +left after dividing `a` and `b`. Implementing `Rem` allows the `%` operator +to be used with the implementation type. + +Unlike other numeric traits, `Rem` is not implemented for `Field`. + +Implementations: +```rust +impl Rem for u8 { fn rem(self, other: u8) -> u8 { self % other } } +impl Rem for u16 { fn rem(self, other: u16) -> u16 { self % other } } +impl Rem for u32 { fn rem(self, other: u32) -> u32 { self % other } } +impl Rem for u64 { fn rem(self, other: u64) -> u64 { self % other } } + +impl Rem for i8 { fn rem(self, other: i8) -> i8 { self % other } } +impl Rem for i16 { fn rem(self, other: i16) -> i16 { self % other } } +impl Rem for i32 { fn rem(self, other: i32) -> i32 { self % other } } +impl Rem for i64 { fn rem(self, other: i64) -> i64 { self % other } } +``` + +### `std::ops::{ BitOr, BitAnd, BitXor }` + +```rust title="bitor-trait" showLineNumbers +trait BitOr { + fn bitor(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L79-L83 + +```rust title="bitand-trait" showLineNumbers +trait BitAnd { + fn bitand(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L95-L99 + +```rust title="bitxor-trait" showLineNumbers +trait BitXor { + fn bitxor(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L111-L115 + + +Traits for the bitwise operations `|`, `&`, and `^`. + +Implementing `BitOr`, `BitAnd` or `BitXor` for a type allows the `|`, `&`, or `^` operator respectively +to be used with the type. + +The implementations block below is given for the `BitOr` trait, but the same types that implement +`BitOr` also implement `BitAnd` and `BitXor`. + +Implementations: +```rust +impl BitOr for bool { fn bitor(self, other: bool) -> bool { self | other } } + +impl BitOr for u8 { fn bitor(self, other: u8) -> u8 { self | other } } +impl BitOr for u16 { fn bitor(self, other: u16) -> u16 { self | other } } +impl BitOr for u32 { fn bitor(self, other: u32) -> u32 { self | other } } +impl BitOr for u64 { fn bitor(self, other: u64) -> u64 { self | other } } + +impl BitOr for i8 { fn bitor(self, other: i8) -> i8 { self | other } } +impl BitOr for i16 { fn bitor(self, other: i16) -> i16 { self | other } } +impl BitOr for i32 { fn bitor(self, other: i32) -> i32 { self | other } } +impl BitOr for i64 { fn bitor(self, other: i64) -> i64 { self | other } } +``` + +### `std::ops::{ Shl, Shr }` + +```rust title="shl-trait" showLineNumbers +trait Shl { + fn shl(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L127-L131 + +```rust title="shr-trait" showLineNumbers +trait Shr { + fn shr(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L142-L146 + + +Traits for a bit shift left and bit shift right. + +Implementing `Shl` for a type allows the left shift operator (`<<`) to be used with the implementation type. +Similarly, implementing `Shr` allows the right shift operator (`>>`) to be used with the type. + +Note that bit shifting is not currently implemented for signed types. + +The implementations block below is given for the `Shl` trait, but the same types that implement +`Shl` also implement `Shr`. + +Implementations: +```rust +impl Shl for u8 { fn shl(self, other: u8) -> u8 { self << other } } +impl Shl for u16 { fn shl(self, other: u16) -> u16 { self << other } } +impl Shl for u32 { fn shl(self, other: u32) -> u32 { self << other } } +impl Shl for u64 { fn shl(self, other: u64) -> u64 { self << other } } +``` diff --git a/docs/versioned_docs/version-v0.26.0/noir/standard_library/zeroed.md b/docs/versioned_docs/version-v0.26.0/noir/standard_library/zeroed.md new file mode 100644 index 00000000000..f450fecdd36 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/noir/standard_library/zeroed.md @@ -0,0 +1,26 @@ +--- +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 +- Slice +- String +- Tuple +- Function + +Using it on other types could result in unexpected behavior. diff --git a/docs/versioned_docs/version-v0.26.0/reference/NoirJS/backend_barretenberg/.nojekyll b/docs/versioned_docs/version-v0.26.0/reference/NoirJS/backend_barretenberg/.nojekyll new file mode 100644 index 00000000000..e2ac6616add --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/reference/NoirJS/backend_barretenberg/.nojekyll @@ -0,0 +1 @@ +TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.26.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md b/docs/versioned_docs/version-v0.26.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md new file mode 100644 index 00000000000..b18c1926b93 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md @@ -0,0 +1,119 @@ +# BarretenbergBackend + +## Implements + +- [`Backend`](../index.md#backend) + +## Constructors + +### new BarretenbergBackend(acirCircuit, options) + +```ts +new BarretenbergBackend(acirCircuit, options): BarretenbergBackend +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `acirCircuit` | `CompiledCircuit` | +| `options` | [`BackendOptions`](../type-aliases/BackendOptions.md) | + +#### Returns + +[`BarretenbergBackend`](BarretenbergBackend.md) + +## Methods + +### destroy() + +```ts +destroy(): Promise +``` + +#### Returns + +`Promise`\<`void`\> + +*** + +### generateProof() + +```ts +generateProof(compressedWitness): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `compressedWitness` | `Uint8Array` | + +#### Returns + +`Promise`\<`ProofData`\> + +#### Description + +Generates a proof + +*** + +### generateRecursiveProofArtifacts() + +```ts +generateRecursiveProofArtifacts(proofData, numOfPublicInputs): Promise +``` + +Generates artifacts that will be passed to a circuit that will verify this proof. + +Instead of passing the proof and verification key as a byte array, we pass them +as fields which makes it cheaper to verify in a circuit. + +The proof that is passed here will have been created using a circuit +that has the #[recursive] attribute on its `main` method. + +The number of public inputs denotes how many public inputs are in the inner proof. + +#### Parameters + +| Parameter | Type | Default value | +| :------ | :------ | :------ | +| `proofData` | `ProofData` | `undefined` | +| `numOfPublicInputs` | `number` | `0` | + +#### Returns + +`Promise`\<`object`\> + +#### Example + +```typescript +const artifacts = await backend.generateRecursiveProofArtifacts(proof, numOfPublicInputs); +``` + +*** + +### verifyProof() + +```ts +verifyProof(proofData): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `proofData` | `ProofData` | + +#### Returns + +`Promise`\<`boolean`\> + +#### Description + +Verifies 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.26.0/reference/NoirJS/backend_barretenberg/index.md b/docs/versioned_docs/version-v0.26.0/reference/NoirJS/backend_barretenberg/index.md new file mode 100644 index 00000000000..c146316a915 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/reference/NoirJS/backend_barretenberg/index.md @@ -0,0 +1,58 @@ +# backend_barretenberg + +## Exports + +### Classes + +| Class | Description | +| :------ | :------ | +| [BarretenbergBackend](classes/BarretenbergBackend.md) | - | + +### Type Aliases + +| Type alias | Description | +| :------ | :------ | +| [BackendOptions](type-aliases/BackendOptions.md) | - | + +## References + +### CompiledCircuit + +Renames and re-exports [Backend](index.md#backend) + +*** + +### ProofData + +Renames and re-exports [Backend](index.md#backend) + +## Variables + +### Backend + +```ts +Backend: any; +``` + +## Functions + +### publicInputsToWitnessMap() + +```ts +publicInputsToWitnessMap(publicInputs, abi): Backend +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `publicInputs` | `string`[] | +| `abi` | `Abi` | + +#### Returns + +[`Backend`](index.md#backend) + +*** + +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.26.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md b/docs/versioned_docs/version-v0.26.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md new file mode 100644 index 00000000000..b49a479f4f4 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md @@ -0,0 +1,21 @@ +# 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 | +| :------ | :------ | :------ | +| `memory` | `object` | - | +| `memory.maximum` | `number` | - | +| `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.26.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs b/docs/versioned_docs/version-v0.26.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs new file mode 100644 index 00000000000..339353b9862 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs @@ -0,0 +1,4 @@ +// @ts-check +/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ +const typedocSidebar = { items: [{"type":"category","label":"Classes","items":[{"type":"doc","id":"reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend","label":"BarretenbergBackend"}]},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions","label":"BackendOptions"}]}]}; +module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/.nojekyll b/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/.nojekyll new file mode 100644 index 00000000000..e2ac6616add --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/.nojekyll @@ -0,0 +1 @@ +TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/classes/Noir.md b/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/classes/Noir.md new file mode 100644 index 00000000000..45dd62ee57e --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/classes/Noir.md @@ -0,0 +1,132 @@ +# Noir + +## Constructors + +### new Noir(circuit, backend) + +```ts +new Noir(circuit, backend?): Noir +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `circuit` | `CompiledCircuit` | +| `backend`? | `any` | + +#### 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) +``` + +*** + +### generateProof() + +```ts +generateProof(inputs, foreignCallHandler?): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `inputs` | `InputMap` | +| `foreignCallHandler`? | [`ForeignCallHandler`](../type-aliases/ForeignCallHandler.md) | + +#### Returns + +`Promise`\<`ProofData`\> + +#### Description + +Generates a witness and a proof given an object as input. + +#### Example + +```typescript +async generateProof(input) +``` + +*** + +### verifyProof() + +```ts +verifyProof(proofData): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `proofData` | `ProofData` | + +#### Returns + +`Promise`\<`boolean`\> + +#### Description + +Instantiates the verification key and verifies a proof. + +#### Example + +```typescript +async verifyProof(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.26.0/reference/NoirJS/noir_js/functions/and.md b/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/functions/and.md new file mode 100644 index 00000000000..c783283e396 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/functions/and.md @@ -0,0 +1,22 @@ +# and() + +```ts +and(lhs, rhs): string +``` + +Performs a bitwise AND operation between `lhs` and `rhs` + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `lhs` | `string` | | +| `rhs` | `string` | | + +## Returns + +`string` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/functions/blake2s256.md b/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/functions/blake2s256.md new file mode 100644 index 00000000000..7882d0da8d5 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/functions/blake2s256.md @@ -0,0 +1,21 @@ +# blake2s256() + +```ts +blake2s256(inputs): Uint8Array +``` + +Calculates the Blake2s256 hash of the input bytes + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `inputs` | `Uint8Array` | | + +## Returns + +`Uint8Array` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md b/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md new file mode 100644 index 00000000000..5e3cd53e9d3 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md @@ -0,0 +1,28 @@ +# ecdsa\_secp256k1\_verify() + +```ts +ecdsa_secp256k1_verify( + hashed_msg, + public_key_x_bytes, + public_key_y_bytes, + signature): boolean +``` + +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.26.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md b/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md new file mode 100644 index 00000000000..0b20ff68957 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md @@ -0,0 +1,28 @@ +# ecdsa\_secp256r1\_verify() + +```ts +ecdsa_secp256r1_verify( + hashed_msg, + public_key_x_bytes, + public_key_y_bytes, + signature): boolean +``` + +Verifies a ECDSA signature over the secp256r1 curve. + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `hashed_msg` | `Uint8Array` | | +| `public_key_x_bytes` | `Uint8Array` | | +| `public_key_y_bytes` | `Uint8Array` | | +| `signature` | `Uint8Array` | | + +## Returns + +`boolean` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/functions/keccak256.md b/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/functions/keccak256.md new file mode 100644 index 00000000000..d10f155ce86 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/functions/keccak256.md @@ -0,0 +1,21 @@ +# keccak256() + +```ts +keccak256(inputs): Uint8Array +``` + +Calculates the Keccak256 hash of the input bytes + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `inputs` | `Uint8Array` | | + +## Returns + +`Uint8Array` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/functions/sha256.md b/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/functions/sha256.md new file mode 100644 index 00000000000..6ba4ecac022 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/functions/sha256.md @@ -0,0 +1,21 @@ +# sha256() + +```ts +sha256(inputs): Uint8Array +``` + +Calculates the SHA256 hash of the input bytes + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `inputs` | `Uint8Array` | | + +## Returns + +`Uint8Array` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/functions/xor.md b/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/functions/xor.md new file mode 100644 index 00000000000..8d762b895d3 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/functions/xor.md @@ -0,0 +1,22 @@ +# xor() + +```ts +xor(lhs, rhs): string +``` + +Performs a bitwise XOR operation between `lhs` and `rhs` + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `lhs` | `string` | | +| `rhs` | `string` | | + +## Returns + +`string` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/index.md b/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/index.md new file mode 100644 index 00000000000..cca6b3ace41 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/index.md @@ -0,0 +1,54 @@ +# noir_js + +## Exports + +### Classes + +| Class | Description | +| :------ | :------ | +| [Noir](classes/Noir.md) | - | + +### Type Aliases + +| Type alias | Description | +| :------ | :------ | +| [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) | - | +| [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) | Verifies a ECDSA signature over the secp256k1 curve. | +| [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` | + +## References + +### CompiledCircuit + +Renames and re-exports [InputMap](index.md#inputmap) + +*** + +### ProofData + +Renames and re-exports [InputMap](index.md#inputmap) + +## Variables + +### InputMap + +```ts +InputMap: any; +``` + +*** + +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.26.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md b/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md new file mode 100644 index 00000000000..812b8b16481 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md @@ -0,0 +1,24 @@ +# ForeignCallHandler + +```ts +type ForeignCallHandler: (name, inputs) => Promise; +``` + +A callback which performs an foreign call and returns the response. + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `name` | `string` | The identifier for the type of foreign call being performed. | +| `inputs` | [`ForeignCallInput`](ForeignCallInput.md)[] | An array of hex encoded inputs to the foreign call. | + +## Returns + +`Promise`\<[`ForeignCallOutput`](ForeignCallOutput.md)[]\> + +outputs - An array of hex encoded outputs containing the results of the foreign call. + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md b/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md new file mode 100644 index 00000000000..dd95809186a --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md @@ -0,0 +1,9 @@ +# ForeignCallInput + +```ts +type ForeignCallInput: string[]; +``` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md b/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md new file mode 100644 index 00000000000..b71fb78a946 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md @@ -0,0 +1,9 @@ +# ForeignCallOutput + +```ts +type ForeignCallOutput: string | string[]; +``` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md b/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md new file mode 100644 index 00000000000..258c46f9d0c --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md @@ -0,0 +1,9 @@ +# WitnessMap + +```ts +type WitnessMap: Map; +``` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs b/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs new file mode 100644 index 00000000000..c6d8125eaad --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs @@ -0,0 +1,4 @@ +// @ts-check +/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ +const typedocSidebar = { items: [{"type":"category","label":"Classes","items":[{"type":"doc","id":"reference/NoirJS/noir_js/classes/Noir","label":"Noir"}]},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ForeignCallHandler","label":"ForeignCallHandler"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ForeignCallInput","label":"ForeignCallInput"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ForeignCallOutput","label":"ForeignCallOutput"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/WitnessMap","label":"WitnessMap"}]},{"type":"category","label":"Functions","items":[{"type":"doc","id":"reference/NoirJS/noir_js/functions/and","label":"and"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/blake2s256","label":"blake2s256"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify","label":"ecdsa_secp256k1_verify"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify","label":"ecdsa_secp256r1_verify"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/keccak256","label":"keccak256"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/sha256","label":"sha256"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/xor","label":"xor"}]}]}; +module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_wasm/.nojekyll b/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_wasm/.nojekyll new file mode 100644 index 00000000000..e2ac6616add --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_wasm/.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.26.0/reference/NoirJS/noir_wasm/functions/compile.md b/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_wasm/functions/compile.md new file mode 100644 index 00000000000..6faf763b37f --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_wasm/functions/compile.md @@ -0,0 +1,51 @@ +# compile() + +```ts +compile( + fileManager, + projectPath?, + logFn?, +debugLogFn?): Promise +``` + +Compiles a Noir project + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `fileManager` | `FileManager` | The file manager to use | +| `projectPath`? | `string` | The path to the project inside the file manager. Defaults to the root of the file manager | +| `logFn`? | `LogFn` | A logging function. If not provided, console.log will be used | +| `debugLogFn`? | `LogFn` | A debug logging function. If not provided, logFn will be used | + +## Returns + +`Promise`\<[`ProgramCompilationArtifacts`](../index.md#programcompilationartifacts)\> + +## Example + +```typescript +// Node.js + +import { compile_program, createFileManager } from '@noir-lang/noir_wasm'; + +const fm = createFileManager(myProjectPath); +const myCompiledCode = await compile_program(fm); +``` + +```typescript +// Browser + +import { compile_program, createFileManager } from '@noir-lang/noir_wasm'; + +const fm = createFileManager('/'); +for (const path of files) { + await fm.writeFile(path, await getFileAsStream(path)); +} +const myCompiledCode = await compile_program(fm); +``` + +*** + +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.26.0/reference/NoirJS/noir_wasm/functions/compile_contract.md b/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_wasm/functions/compile_contract.md new file mode 100644 index 00000000000..7d0b39a43ef --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_wasm/functions/compile_contract.md @@ -0,0 +1,51 @@ +# compile\_contract() + +```ts +compile_contract( + fileManager, + projectPath?, + logFn?, +debugLogFn?): Promise +``` + +Compiles a Noir project + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `fileManager` | `FileManager` | The file manager to use | +| `projectPath`? | `string` | The path to the project inside the file manager. Defaults to the root of the file manager | +| `logFn`? | `LogFn` | A logging function. If not provided, console.log will be used | +| `debugLogFn`? | `LogFn` | A debug logging function. If not provided, logFn will be used | + +## Returns + +`Promise`\<[`ContractCompilationArtifacts`](../index.md#contractcompilationartifacts)\> + +## Example + +```typescript +// Node.js + +import { compile_contract, createFileManager } from '@noir-lang/noir_wasm'; + +const fm = createFileManager(myProjectPath); +const myCompiledCode = await compile_contract(fm); +``` + +```typescript +// Browser + +import { compile_contract, createFileManager } from '@noir-lang/noir_wasm'; + +const fm = createFileManager('/'); +for (const path of files) { + await fm.writeFile(path, await getFileAsStream(path)); +} +const myCompiledCode = await compile_contract(fm); +``` + +*** + +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.26.0/reference/NoirJS/noir_wasm/functions/createFileManager.md b/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_wasm/functions/createFileManager.md new file mode 100644 index 00000000000..7e65c1d69c7 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_wasm/functions/createFileManager.md @@ -0,0 +1,21 @@ +# createFileManager() + +```ts +createFileManager(dataDir): FileManager +``` + +Creates a new FileManager instance based on fs in node and memfs in the browser (via webpack alias) + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `dataDir` | `string` | root of the file system | + +## Returns + +`FileManager` + +*** + +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.26.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md b/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md new file mode 100644 index 00000000000..fcea9275341 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md @@ -0,0 +1,21 @@ +# inflateDebugSymbols() + +```ts +inflateDebugSymbols(debugSymbols): any +``` + +Decompresses and decodes the debug symbols + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `debugSymbols` | `string` | The base64 encoded debug symbols | + +## Returns + +`any` + +*** + +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.26.0/reference/NoirJS/noir_wasm/index.md b/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_wasm/index.md new file mode 100644 index 00000000000..b6e0f9d1bc0 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_wasm/index.md @@ -0,0 +1,49 @@ +# noir_wasm + +## Exports + +### Functions + +| Function | Description | +| :------ | :------ | +| [compile](functions/compile.md) | Compiles a Noir project | +| [compile\_contract](functions/compile_contract.md) | Compiles a Noir project | +| [createFileManager](functions/createFileManager.md) | Creates a new FileManager instance based on fs in node and memfs in the browser (via webpack alias) | +| [inflateDebugSymbols](functions/inflateDebugSymbols.md) | Decompresses and decodes the debug symbols | + +## References + +### compile\_program + +Renames and re-exports [compile](functions/compile.md) + +## Interfaces + +### ContractCompilationArtifacts + +The compilation artifacts of a given contract. + +#### Properties + +| Property | Type | Description | +| :------ | :------ | :------ | +| `contract` | `ContractArtifact` | The compiled contract. | +| `warnings` | `unknown`[] | Compilation warnings. | + +*** + +### ProgramCompilationArtifacts + +The compilation artifacts of a given program. + +#### Properties + +| Property | Type | Description | +| :------ | :------ | :------ | +| `name` | `string` | not part of the compilation output, injected later | +| `program` | `ProgramArtifact` | The compiled contract. | +| `warnings` | `unknown`[] | Compilation warnings. | + +*** + +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.26.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs b/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs new file mode 100644 index 00000000000..e0870710349 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs @@ -0,0 +1,4 @@ +// @ts-check +/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ +const typedocSidebar = { items: [{"type":"doc","id":"reference/NoirJS/noir_wasm/index","label":"API"},{"type":"category","label":"Functions","items":[{"type":"doc","id":"reference/NoirJS/noir_wasm/functions/compile","label":"compile"},{"type":"doc","id":"reference/NoirJS/noir_wasm/functions/compile_contract","label":"compile_contract"},{"type":"doc","id":"reference/NoirJS/noir_wasm/functions/createFileManager","label":"createFileManager"},{"type":"doc","id":"reference/NoirJS/noir_wasm/functions/inflateDebugSymbols","label":"inflateDebugSymbols"}]}]}; +module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.26.0/reference/_category_.json b/docs/versioned_docs/version-v0.26.0/reference/_category_.json new file mode 100644 index 00000000000..5b6a20a609a --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/reference/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 4, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.26.0/reference/nargo_commands.md b/docs/versioned_docs/version-v0.26.0/reference/nargo_commands.md new file mode 100644 index 00000000000..218fcfb0c8c --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/reference/nargo_commands.md @@ -0,0 +1,381 @@ +--- +title: Nargo +description: + Noir CLI Commands for Noir Prover and Verifier to create, execute, prove and verify programs, + generate Solidity verifier smart contract and compile into JSON file containing ACIR + representation and ABI of circuit. +keywords: + [ + Nargo, + Noir CLI, + Noir Prover, + Noir Verifier, + generate Solidity verifier, + compile JSON file, + ACIR representation, + ABI of circuit, + TypeScript, + ] +sidebar_position: 0 +--- + +# Command-Line Help for `nargo` + +This document contains the help content for the `nargo` command-line program. + +**Command Overview:** + +* [`nargo`↴](#nargo) +* [`nargo backend`↴](#nargo-backend) +* [`nargo backend current`↴](#nargo-backend-current) +* [`nargo backend ls`↴](#nargo-backend-ls) +* [`nargo backend use`↴](#nargo-backend-use) +* [`nargo backend install`↴](#nargo-backend-install) +* [`nargo backend uninstall`↴](#nargo-backend-uninstall) +* [`nargo check`↴](#nargo-check) +* [`nargo fmt`↴](#nargo-fmt) +* [`nargo codegen-verifier`↴](#nargo-codegen-verifier) +* [`nargo compile`↴](#nargo-compile) +* [`nargo new`↴](#nargo-new) +* [`nargo init`↴](#nargo-init) +* [`nargo execute`↴](#nargo-execute) +* [`nargo prove`↴](#nargo-prove) +* [`nargo verify`↴](#nargo-verify) +* [`nargo test`↴](#nargo-test) +* [`nargo info`↴](#nargo-info) +* [`nargo lsp`↴](#nargo-lsp) + +## `nargo` + +Noir's package manager + +**Usage:** `nargo ` + +###### **Subcommands:** + +* `backend` — Install and select custom backends used to generate and verify proofs +* `check` — Checks the constraint system for errors +* `fmt` — Format the Noir files in a workspace +* `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 Noir project in a new directory +* `init` — Create a Noir project in the current directory +* `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 +* `info` — Provides detailed information on each of a program's function (represented by a single circuit) +* `lsp` — Starts the Noir LSP server + +###### **Options:** + + + + +## `nargo backend` + +Install and select custom backends used to generate and verify proofs + +**Usage:** `nargo backend ` + +###### **Subcommands:** + +* `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 + + + +## `nargo backend current` + +Prints the name of the currently active backend + +**Usage:** `nargo backend current` + + + +## `nargo backend ls` + +Prints the list of currently installed backends + +**Usage:** `nargo backend ls` + + + +## `nargo backend use` + +Select the backend to use + +**Usage:** `nargo backend use ` + +###### **Arguments:** + +* `` + + + +## `nargo backend install` + +Install a new backend from a URL + +**Usage:** `nargo backend install ` + +###### **Arguments:** + +* `` — The name of the backend to install +* `` — The URL from which to download the backend + + + +## `nargo backend uninstall` + +Uninstalls a backend + +**Usage:** `nargo backend uninstall ` + +###### **Arguments:** + +* `` — The name of the backend to uninstall + + + +## `nargo check` + +Checks the constraint system for errors + +**Usage:** `nargo check [OPTIONS]` + +###### **Options:** + +* `--package ` — The name of the package to check +* `--workspace` — Check all packages in the workspace +* `--overwrite` — Force overwrite of existing files +* `--expression-width ` — Override the expression width requested by the backend +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings + + + +## `nargo fmt` + +Format the Noir files in a workspace + +**Usage:** `nargo fmt [OPTIONS]` + +###### **Options:** + +* `--check` — Run noirfmt in check mode + + + +## `nargo codegen-verifier` + +Generates a Solidity verifier smart contract for the program + +**Usage:** `nargo codegen-verifier [OPTIONS]` + +###### **Options:** + +* `--package ` — The name of the package to codegen +* `--workspace` — Codegen all packages in the workspace +* `--expression-width ` — Override the expression width requested by the backend +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings + + + +## `nargo compile` + +Compile the program and its secret execution trace into ACIR format + +**Usage:** `nargo compile [OPTIONS]` + +###### **Options:** + +* `--package ` — The name of the package to compile +* `--workspace` — Compile all packages in the workspace +* `--expression-width ` — Override the expression width requested by the backend +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings + + + +## `nargo new` + +Create a Noir project in a new directory + +**Usage:** `nargo new [OPTIONS] ` + +###### **Arguments:** + +* `` — The path to save the new project + +###### **Options:** + +* `--name ` — Name of the package [default: package directory name] +* `--lib` — Use a library template +* `--bin` — Use a binary template [default] +* `--contract` — Use a contract template + + + +## `nargo init` + +Create a Noir project in the current directory + +**Usage:** `nargo init [OPTIONS]` + +###### **Options:** + +* `--name ` — Name of the package [default: current directory name] +* `--lib` — Use a library template +* `--bin` — Use a binary template [default] +* `--contract` — Use a contract template + + + +## `nargo execute` + +Executes a circuit to calculate its return value + +**Usage:** `nargo execute [OPTIONS] [WITNESS_NAME]` + +###### **Arguments:** + +* `` — Write the execution witness to named file + +###### **Options:** + +* `-p`, `--prover-name ` — The name of the toml file which contains the inputs for the prover + + Default value: `Prover` +* `--package ` — The name of the package to execute +* `--workspace` — Execute all packages in the workspace +* `--expression-width ` — Override the expression width requested by the backend +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings +* `--oracle-resolver ` — JSON RPC url to solve oracle calls + + + +## `nargo prove` + +Create proof for this program. The proof is returned as a hex encoded string + +**Usage:** `nargo prove [OPTIONS]` + +###### **Options:** + +* `-p`, `--prover-name ` — The name of the toml file which contains the inputs for the prover + + Default value: `Prover` +* `-v`, `--verifier-name ` — The name of the toml file which contains the inputs for the verifier + + Default value: `Verifier` +* `--verify` — Verify proof after proving +* `--package ` — The name of the package to prove +* `--workspace` — Prove all packages in the workspace +* `--expression-width ` — Override the expression width requested by the backend +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings +* `--oracle-resolver ` — JSON RPC url to solve oracle calls + + + +## `nargo verify` + +Given a proof and a program, verify whether the proof is valid + +**Usage:** `nargo verify [OPTIONS]` + +###### **Options:** + +* `-v`, `--verifier-name ` — The name of the toml file which contains the inputs for the verifier + + Default value: `Verifier` +* `--package ` — The name of the package verify +* `--workspace` — Verify all packages in the workspace +* `--expression-width ` — Override the expression width requested by the backend +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings + + + +## `nargo test` + +Run the tests for this program + +**Usage:** `nargo test [OPTIONS] [TEST_NAME]` + +###### **Arguments:** + +* `` — If given, only tests with names containing this string will be run + +###### **Options:** + +* `--show-output` — Display output of `println` statements +* `--exact` — Only run tests that match exactly +* `--package ` — The name of the package to test +* `--workspace` — Test all packages in the workspace +* `--expression-width ` — Override the expression width requested by the backend +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings +* `--oracle-resolver ` — JSON RPC url to solve oracle calls + + + +## `nargo info` + +Provides detailed information on each of a program's function (represented by a single circuit) + +Current information provided per circuit: 1. The number of ACIR opcodes 2. Counts the final number gates in the circuit used by a backend + +**Usage:** `nargo info [OPTIONS]` + +###### **Options:** + +* `--package ` — The name of the package to detail +* `--workspace` — Detail all packages in the workspace +* `--expression-width ` — Override the expression width requested by the backend +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings + + + +## `nargo lsp` + +Starts the Noir LSP server + +Starts an LSP server which allows IDEs such as VS Code to display diagnostics in Noir source. + +VS Code Noir Language Support: https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir + +**Usage:** `nargo lsp` + + + +
+ + + This document was generated automatically by + clap-markdown. + + diff --git a/docs/versioned_docs/version-v0.26.0/tutorials/noirjs_app.md b/docs/versioned_docs/version-v0.26.0/tutorials/noirjs_app.md new file mode 100644 index 00000000000..a6dda7e08c3 --- /dev/null +++ b/docs/versioned_docs/version-v0.26.0/tutorials/noirjs_app.md @@ -0,0 +1,324 @@ +--- +title: Building a web app with NoirJS +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, app] +sidebar_position: 0 +pagination_next: noir/concepts/data_types/index +--- + +NoirJS is a set of packages meant to work both in a browser and a server environment. In this tutorial, we will build a simple web app using them. From here, you should get an idea on how to proceed with your own Noir projects! + +You can find the complete app code for this guide [here](https://github.com/noir-lang/tiny-noirjs-app). + +## Setup + +:::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.26.x matches `noir_js@0.26.x`, etc. + +In this guide, we will be pinned to 0.26.0. + +::: + +Before we start, we want to make sure we have Node and Nargo installed. + +We start by opening a terminal and executing `node --version`. If we don't get an output like `v20.10.0`, that means node is not installed. Let's do that by following the handy [nvm guide](https://github.com/nvm-sh/nvm?tab=readme-ov-file#install--update-script). + +As for `Nargo`, we can follow the [Nargo guide](../getting_started/installation/index.md) to install it. If you're lazy, just paste this on a terminal and run `noirup`: + +```sh +curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash +``` + +Easy enough. Onwards! + +## Our project + +ZK is a powerful technology. An app that doesn't reveal one of the inputs to _anyone_ is almost unbelievable, yet Noir makes it as easy as a single line of code. + +In fact, it's so simple that it comes nicely packaged in `nargo`. Let's do that! + +### Nargo + +Run: + +`nargo new circuit` + +And... That's about it. Your program is ready to be compiled and run. + +To compile, let's `cd` into the `circuit` folder to enter our project, and call: + +`nargo compile` + +This compiles our circuit into `json` format and add it to a new `target` folder. + +:::info + +At this point in the tutorial, your folder structure should look like this: + +```tree +. +└── circuit <---- our working directory + ├── Nargo.toml + ├── src + │ └── main.nr + └── target + └── circuit.json +``` + +::: + +### Node and Vite + +If you want to explore Nargo, feel free to go on a side-quest now and follow the steps in the +[getting started](../getting_started/hello_noir/index.md) guide. However, we want our app to run on the browser, so we need Vite. + +Vite is a powerful tool to generate static websites. While it provides all kinds of features, let's just go barebones with some good old vanilla JS. + +To do this this, go back to the previous folder (`cd ..`) and create a new vite project by running `npm create vite` and choosing "Vanilla" and "Javascript". + +A wild `vite-project` directory should now appear in your root folder! Let's not waste any time and dive right in: + +```bash +cd vite-project +``` + +### Setting Up Vite and Configuring the Project + +Before we proceed with any coding, let's get our environment tailored for Noir. We'll start by laying down the foundations with a `vite.config.js` file. This little piece of configuration is our secret sauce for making sure everything meshes well with the NoirJS libraries and other special setups we might need, like handling WebAssembly modules. Here’s how you get that going: + +#### Creating the vite.config.js + +In your freshly minted `vite-project` folder, create a new file named `vite.config.js` and open it in your code editor. Paste the following to set the stage: + +```javascript +import { defineConfig } from "vite"; +import copy from "rollup-plugin-copy"; + +export default defineConfig({ + esbuild: { + target: "esnext", + }, + optimizeDeps: { + esbuildOptions: { + target: "esnext", + }, + }, + plugins: [ + copy({ + targets: [ + { src: "node_modules/**/*.wasm", dest: "node_modules/.vite/dist" }, + ], + copySync: true, + hook: "buildStart", + }), + ], + server: { + port: 3000, + }, +}); +``` + +#### Install Dependencies + +Now that our stage is set, install the necessary NoirJS packages along with our other dependencies: + +```bash +npm install && npm install @noir-lang/backend_barretenberg@0.26.0 @noir-lang/noir_js@0.26.0 +npm install rollup-plugin-copy --save-dev +``` + +:::info + +At this point in the tutorial, your folder structure should look like this: + +```tree +. +└── circuit + └── ...etc... +└── vite-project <---- our working directory + └── ...etc... +``` + +::: + +#### Some cleanup + +`npx create vite` is amazing but it creates a bunch of files we don't really need for our simple example. Actually, let's just delete everything except for `vite.config.js`, `index.html`, `main.js` and `package.json`. I feel lighter already. + +![my heart is ready for you, noir.js](@site/static/img/memes/titanic.jpeg) + +## HTML + +Our app won't run like this, of course. We need some working HTML, at least. Let's open our broken-hearted `index.html` and replace everything with this code snippet: + +```html + + + + + + +

Noir app

+
+ + +
+
+

Logs

+

Proof

+
+ + +``` + +It _could_ be a beautiful UI... Depending on which universe you live in. + +## Some good old vanilla Javascript + +Our love for Noir needs undivided attention, so let's just open `main.js` and delete everything (this is where the romantic scenery becomes a bit creepy). + +Start by pasting in this boilerplate code: + +```js +const setup = async () => { + await Promise.all([ + import('@noir-lang/noirc_abi').then((module) => + module.default(new URL('@noir-lang/noirc_abi/web/noirc_abi_wasm_bg.wasm', import.meta.url).toString()), + ), + import('@noir-lang/acvm_js').then((module) => + module.default(new URL('@noir-lang/acvm_js/web/acvm_js_bg.wasm', import.meta.url).toString()), + ), + ]); +}; + +function display(container, msg) { + const c = document.getElementById(container); + const p = document.createElement('p'); + p.textContent = msg; + c.appendChild(p); +} + +document.getElementById('submitGuess').addEventListener('click', async () => { + try { + // here's where love happens + } catch (err) { + display('logs', 'Oh 💔 Wrong guess'); + } +}); +``` + +The display function doesn't do much. We're simply manipulating our website to see stuff happening. For example, if the proof fails, it will simply log a broken heart 😢 + +As for the `setup` function, it's just a sad reminder that dealing with `wasm` on the browser is not as easy as it should. Just copy, paste, and forget. + +:::info + +At this point in the tutorial, your folder structure should look like this: + +```tree +. +└── circuit + └── ...same as above +└── vite-project + └── vite.config.js + ├── main.js + ├── package.json + └── index.html +``` + +You'll see other files and folders showing up (like `package-lock.json`, `node_modules`) but you shouldn't have to care about those. + +::: + +## Some NoirJS + +We're starting with the good stuff now. If you've compiled the circuit as described above, you should have a `json` file we want to import at the very top of our `main.js` file: + +```ts +import circuit from '../circuit/target/circuit.json'; +``` + +[Noir is backend-agnostic](../index.mdx#whats-new-about-noir). We write Noir, but we also need a proving backend. That's why we need to import and instantiate the two dependencies we installed above: `BarretenbergBackend` and `Noir`. Let's import them right below: + +```js +import { BarretenbergBackend } from '@noir-lang/backend_barretenberg'; +import { Noir } from '@noir-lang/noir_js'; +``` + +And instantiate them inside our try-catch block: + +```ts +// try { +const backend = new BarretenbergBackend(circuit); +const noir = new Noir(circuit, backend); +// } +``` + +:::note + +For the remainder of the tutorial, everything will be happening inside the `try` block + +::: + +## Our app + +Now for the app itself. We're capturing whatever is in the input when people press the submit button. Just add this: + +```js +const x = parseInt(document.getElementById('guessInput').value); +const input = { x, y: 2 }; +``` + +Now we're ready to prove stuff! Let's feed some inputs to our circuit and calculate the proof: + +```js +await setup(); // let's squeeze our wasm inits here + +display('logs', 'Generating proof... ⌛'); +const proof = await noir.generateProof(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 run dev`. If it doesn't open a browser for you, just visit `localhost:5173`. You should now see the worst UI ever, with an ugly input. + +![Getting Started 0](@site/static/img/noir_getting_started_1.png) + +Now, our circuit says `fn main(x: Field, y: pub Field)`. This means only the `y` value is public, and it's hardcoded above: `input = { x, y: 2 }`. In other words, you won't need to send your secret`x` to the verifier! + +By inputting any number other than 2 in the input box and clicking "submit", you should get a valid proof. Otherwise the proof won't even generate correctly. By the way, if you're human, you shouldn't be able to understand anything on the "proof" box. That's OK. We like you, human ❤️. + +## Verifying + +Time to celebrate, yes! But we shouldn't trust machines so blindly. Let's add these lines to see our proof being verified: + +```js +display('logs', 'Verifying proof... ⌛'); +const verification = await noir.verifyProof(proof); +if (verification) display('logs', 'Verifying proof... ✅'); +``` + +You have successfully generated a client-side Noir web app! + +![coded app without math knowledge](@site/static/img/memes/flextape.jpeg) + +## 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/vite-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.27.0/explainers/explainer-oracle.md b/docs/versioned_docs/version-v0.27.0/explainers/explainer-oracle.md new file mode 100644 index 00000000000..b84ca5dd986 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/explainers/explainer-oracle.md @@ -0,0 +1,57 @@ +--- +title: Oracles +description: This guide provides an in-depth understanding of how Oracles work in Noir programming. Learn how to use outside calculations in your programs, constrain oracles, and understand their uses and limitations. +keywords: + - Noir Programming + - Oracles + - JSON-RPC + - Foreign Call Handlers + - Constrained Functions + - Blockchain Programming +sidebar_position: 1 +--- + +If you've seen "The Matrix" you may recall "The Oracle" as Gloria Foster smoking cigarettes and baking cookies. While she appears to "know things", she is actually providing a calculation of a pre-determined future. Noir Oracles are similar, in a way. They don't calculate the future (yet), but they allow you to use outside calculations in your programs. + +![matrix oracle prediction](@site/static/img/memes/matrix_oracle.jpeg) + +A Noir program is usually self-contained. You can pass certain inputs to it, and it will generate a deterministic output for those inputs. But what if you wanted to defer some calculation to an outside process or source? + +Oracles are functions that provide this feature. + +## Use cases + +An example usage for Oracles is proving something on-chain. For example, proving that the ETH-USDC quote was below a certain target at a certain block time. Or even making more complex proofs like proving the ownership of an NFT as an anonymous login method. + +Another interesting use case is to defer expensive calculations to be made outside of the Noir program, and then constraining the result; similar to the use of [unconstrained functions](../noir/concepts//unconstrained.md). + +In short, anything that can be constrained in a Noir program but needs to be fetched from an external source is a great candidate to be used in oracles. + +## Constraining oracles + +Just like in The Matrix, Oracles are powerful. But with great power, comes great responsibility. Just because you're using them in a Noir program doesn't mean they're true. Noir has no superpowers. If you want to prove that Portugal won the Euro Cup 2016, you're still relying on potentially untrusted information. + +To give a concrete example, Alice wants to login to the [NounsDAO](https://nouns.wtf/) forum with her username "noir_nouner" by proving she owns a noun without revealing her ethereum address. Her Noir program could have a oracle call like this: + +```rust +#[oracle(getNoun)] +unconstrained fn get_noun(address: Field) -> Field +``` + +This oracle could naively resolve with the number of Nouns she possesses. However, it is useless as a trusted source, as the oracle could resolve to anything Alice wants. In order to make this oracle call actually useful, Alice would need to constrain the response from the oracle, by proving her address and the noun count belongs to the state tree of the contract. + +In short, **Oracles don't prove anything. Your Noir program does.** + +:::danger + +If you don't constrain the return of your oracle, you could be clearly opening an attack vector on your Noir program. Make double-triple sure that the return of an oracle call is constrained! + +::: + +## How to use Oracles + +On CLI, Nargo resolves oracles by making JSON RPC calls, which means it would require an RPC node to be running. + +In JavaScript, NoirJS accepts and resolves arbitrary call handlers (that is, not limited to JSON) as long as they matches the expected types the developer defines. Refer to [Foreign Call Handler](../reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md) to learn more about NoirJS's call handling. + +If you want to build using oracles, follow through to the [oracle guide](../how_to/how-to-oracles.md) for a simple example on how to do that. diff --git a/docs/versioned_docs/version-v0.27.0/explainers/explainer-recursion.md b/docs/versioned_docs/version-v0.27.0/explainers/explainer-recursion.md new file mode 100644 index 00000000000..18846176ca7 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/explainers/explainer-recursion.md @@ -0,0 +1,176 @@ +--- +title: Recursive proofs +description: Explore the concept of recursive proofs in Zero-Knowledge programming. Understand how recursion works in Noir, a language for writing smart contracts on the EVM blockchain. Learn through practical examples like Alice and Bob's guessing game, Charlie's recursive merkle tree, and Daniel's reusable components. Discover how to use recursive proofs to optimize computational resources and improve efficiency. + +keywords: + [ + "Recursive Proofs", + "Zero-Knowledge Programming", + "Noir", + "EVM Blockchain", + "Smart Contracts", + "Recursion in Noir", + "Alice and Bob Guessing Game", + "Recursive Merkle Tree", + "Reusable Components", + "Optimizing Computational Resources", + "Improving Efficiency", + "Verification Key", + "Aggregation", + "Recursive zkSNARK schemes", + "PLONK", + "Proving and Verification Keys" + ] +sidebar_position: 1 +pagination_next: how_to/how-to-recursion +--- + +In programming, we tend to think of recursion as something calling itself. A classic example would be the calculation of the factorial of a number: + +```js +function factorial(n) { + if (n === 0 || n === 1) { + return 1; + } else { + return n * factorial(n - 1); + } +} +``` + +In this case, while `n` is not `1`, this function will keep calling itself until it hits the base case, bubbling up the result on the call stack: + +```md + Is `n` 1? <--------- + /\ / + / \ n = n -1 + / \ / + Yes No -------- +``` + +In Zero-Knowledge, recursion has some similarities. + +It is not a Noir function calling itself, but a proof being used as an input to another circuit. In short, you verify one proof *inside* another proof, returning the proof that both proofs are valid. + +This means that, given enough computational resources, you can prove the correctness of any arbitrary number of proofs in a single proof. This could be useful to design state channels (for which a common example would be [Bitcoin's Lightning Network](https://en.wikipedia.org/wiki/Lightning_Network)), to save on gas costs by settling one proof on-chain, or simply to make business logic less dependent on a consensus mechanism. + +## Examples + +Let us look at some of these examples + +### Alice and Bob - Guessing game + +Alice and Bob are friends, and they like guessing games. They want to play a guessing game online, but for that, they need a trusted third-party that knows both of their secrets and finishes the game once someone wins. + +So, they use zero-knowledge proofs. Alice tries to guess Bob's number, and Bob will generate a ZK proof stating whether she succeeded or failed. + +This ZK proof can go on a smart contract, revealing the winner and even giving prizes. However, this means every turn needs to be verified on-chain. This incurs some cost and waiting time that may simply make the game too expensive or time-consuming to be worth it. + +As a solution, Alice proposes the following: "what if Bob generates his proof, and instead of sending it on-chain, I verify it *within* my own proof before playing my own turn?". + +She can then generate a proof that she verified his proof, and so on. + +```md + Did you fail? <-------------------------- + / \ / + / \ n = n -1 + / \ / + Yes No / + | | / + | | / + | You win / + | / + | / +Generate proof of that / + + / + my own guess ---------------- +``` + +### Charlie - Recursive merkle tree + +Charlie is a concerned citizen, and wants to be sure his vote in an election is accounted for. He votes with a ZK proof, but he has no way of knowing that his ZK proof was included in the total vote count! + +If the vote collector puts all of the votes into a [Merkle tree](https://en.wikipedia.org/wiki/Merkle_tree), everyone can prove the verification of two proofs within one proof, as such: + +```md + abcd + __________|______________ + | | + ab cd + _____|_____ ______|______ + | | | | + alice bob charlie daniel +``` + +Doing this recursively allows us to arrive on a final proof `abcd` which if true, verifies the correctness of all the votes. + +### Daniel - Reusable components + +Daniel has a big circuit and a big headache. A part of his circuit is a setup phase that finishes with some assertions that need to be made. But that section alone takes most of the proving time, and is largely independent of the rest of the circuit. + +He might find it more efficient to generate a proof for that setup phase separately, and verify that proof recursively in the actual business logic section of his circuit. This will allow for parallelization of both proofs, which results in a considerable speedup. + +## What params do I need + +As you can see in the [recursion reference](noir/standard_library/recursion.md), a simple recursive proof requires: + +- The proof to verify +- The Verification Key of the circuit that generated the proof +- A hash of this verification key, as it's needed for some backends +- The public inputs for the proof + +:::info + +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. + +So, taking the example of Alice and Bob and their guessing game: + +- Alice makes her guess. Her proof is *not* recursive: it doesn't verify any proof within it! It's just a standard `assert(x != y)` circuit +- Bob verifies Alice's proof and makes his own guess. In this circuit, he doesn't exactly *prove* the verification of Alice's proof. Instead, he *aggregates* his proof to Alice's proof. The actual verification is done when the full proof is verified, for example when using `nargo verify` or through the verifier smart contract. + +We can imagine recursive proofs a [relay race](https://en.wikipedia.org/wiki/Relay_race). The first runner doesn't have to receive the baton from anyone else, as he/she already starts with it. But when his/her turn is over, the next runner needs to receive it, run a bit more, and pass it along. Even though every runner could theoretically verify the baton mid-run (why not? 🏃🔍), only at the end of the race does the referee verify that the whole race is valid. + +::: + +## Some architecture + +As with everything in computer science, there's no one-size-fits all. But there are some patterns that could help understanding and implementing them. To give three examples: + +### Adding some logic to a proof verification + +This would be an approach for something like our guessing game, where proofs are sent back and forth and are verified by each opponent. This circuit would be divided in two sections: + +- A `recursive verification` section, which would be just the call to `std::verify_proof`, and that would be skipped on the first move (since there's no proof to verify) +- A `guessing` section, which is basically the logic part where the actual guessing happens + +In such a situation, and assuming Alice is first, she would skip the first part and try to guess Bob's number. Bob would then verify her proof on the first section of his run, and try to guess Alice's number on the second part, and so on. + +### Aggregating proofs + +In some one-way interaction situations, recursion would allow for aggregation of simple proofs that don't need to be immediately verified on-chain or elsewhere. + +To give a practical example, a barman wouldn't need to verify a "proof-of-age" on-chain every time he serves alcohol to a customer. Instead, the architecture would comprise two circuits: + +- A `main`, non-recursive circuit with some logic +- A `recursive` circuit meant to verify two proofs in one proof + +The customer's proofs would be intermediate, and made on their phones, and the barman could just verify them locally. He would then aggregate them into a final proof sent on-chain (or elsewhere) at the end of the day. + +### Recursively verifying different circuits + +Nothing prevents you from verifying different circuits in a recursive proof, for example: + +- A `circuit1` circuit +- A `circuit2` circuit +- A `recursive` circuit + +In this example, a regulator could verify that taxes were paid for a specific purchase by aggregating both a `payer` circuit (proving that a purchase was made and taxes were paid), and a `receipt` circuit (proving that the payment was received) + +## How fast is it + +At the time of writing, verifying recursive proofs is surprisingly fast. This is because most of the time is spent on generating the verification key that will be used to generate the next proof. So you are able to cache the verification key and reuse it later. + +Currently, Noir JS packages don't expose the functionality of loading proving and verification keys, but that feature exists in the underlying `bb.js` package. + +## How can I try it + +Learn more about using recursion in Nargo and NoirJS in the [how-to guide](../how_to/how-to-recursion.md) and see a full example in [noir-examples](https://github.com/noir-lang/noir-examples). diff --git a/docs/versioned_docs/version-v0.27.0/getting_started/_category_.json b/docs/versioned_docs/version-v0.27.0/getting_started/_category_.json new file mode 100644 index 00000000000..5d694210bbf --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/getting_started/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 0, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.27.0/getting_started/hello_noir/_category_.json b/docs/versioned_docs/version-v0.27.0/getting_started/hello_noir/_category_.json new file mode 100644 index 00000000000..23b560f610b --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/getting_started/hello_noir/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 1, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.27.0/getting_started/hello_noir/index.md b/docs/versioned_docs/version-v0.27.0/getting_started/hello_noir/index.md new file mode 100644 index 00000000000..743c4d8d634 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/getting_started/hello_noir/index.md @@ -0,0 +1,142 @@ +--- +title: Creating a Project +description: + Learn how to create and verify your first Noir program using Nargo, a programming language for + zero-knowledge proofs. +keywords: + [ + Nargo, + Noir, + zero-knowledge proofs, + programming language, + create Noir program, + verify Noir program, + step-by-step guide, + ] +sidebar_position: 1 + +--- + +Now that we have installed Nargo, it is time to make our first hello world program! + +## Create a Project Directory + +Noir code can live anywhere on your computer. Let us create a _projects_ folder in the home +directory to house our Noir programs. + +For Linux, macOS, and Windows PowerShell, create the directory and change directory into it by +running: + +```sh +mkdir ~/projects +cd ~/projects +``` + +## Create Our First Nargo Project + +Now that we are in the projects directory, create a new Nargo project by running: + +```sh +nargo new hello_world +``` + +> **Note:** `hello_world` can be any arbitrary project name, we are simply using `hello_world` for +> demonstration. +> +> In production, the common practice is to name the project folder as `circuits` for better +> identifiability when sitting alongside other folders in the codebase (e.g. `contracts`, `scripts`, +> `test`). + +A `hello_world` folder would be created. Similar to Rust, the folder houses _src/main.nr_ and +_Nargo.toml_ which contain 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](../../noir/concepts/data_types/index.md) section. + +The next line of the program specifies its body: + +```rust +assert(x != y); +``` + +The Noir syntax `assert` can be interpreted as something similar to constraints in other zk-contract languages. + +For more Noir syntax, check the [Language Concepts](../../noir/concepts/comments.md) chapter. + +## Build In/Output Files + +Change directory into _hello_world_ and build in/output files for your Noir program by running: + +```sh +cd hello_world +nargo check +``` + +Two additional files would be generated in your project directory: + +_Prover.toml_ houses input values, and _Verifier.toml_ houses public values. + +## Prove Our Noir Program + +Now that the project is set up, we can create a proof of correct execution of 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](./project_breakdown.md), we will go into more detail on each step performed. diff --git a/docs/versioned_docs/version-v0.27.0/getting_started/hello_noir/project_breakdown.md b/docs/versioned_docs/version-v0.27.0/getting_started/hello_noir/project_breakdown.md new file mode 100644 index 00000000000..6160a102c6c --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/getting_started/hello_noir/project_breakdown.md @@ -0,0 +1,199 @@ +--- +title: Project Breakdown +description: + Learn about the anatomy of a Nargo project, including the purpose of the Prover and Verifier TOML + files, and how to prove and verify your program. +keywords: + [Nargo, Nargo project, Prover.toml, Verifier.toml, proof verification, private asset transfer] +sidebar_position: 2 +--- + +This section breaks down our hello world program from the previous section. We elaborate on the project +structure and what the `prove` and `verify` commands did. + +## 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 = "noir_starter" +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](../../noir/modules_packages_crates/workspaces.md) will look a bit different. For example: + +```toml +[workspace] +members = ["crates/a", "crates/b"] +default-member = "crates/a" +``` + +#### Package section + +The package section defines 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](../../noir/modules_packages_crates/dependencies.md) for more info. + +`./proofs/` and `./contract/` directories will not be immediately visible until you create a proof or +verifier contract respectively. + +### main.nr + +The _main.nr_ file contains a `main` method, this method is the entry point into your Noir program. + +In our sample program, _main.nr_ looks like this: + +```rust +fn main(x : Field, y : Field) { + assert(x != y); +} +``` + +The parameters `x` and `y` can be seen as the API for the program and must be supplied by the +prover. Since neither `x` nor `y` is marked as public, the verifier does not supply any inputs, when +verifying the proof. + +The prover supplies the values for `x` and `y` in the _Prover.toml_ file. + +As for the program body, `assert` ensures that the condition to be satisfied (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 inequality 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, usually from external sources, and +verify the validity of the proof against it. + +Take a private asset transfer as an example: + +A person using a browser as the prover would retrieve private inputs locally (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.27.0/getting_started/installation/_category_.json b/docs/versioned_docs/version-v0.27.0/getting_started/installation/_category_.json new file mode 100644 index 00000000000..0c02fb5d4d7 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/getting_started/installation/_category_.json @@ -0,0 +1,6 @@ +{ + "position": 0, + "label": "Install Nargo", + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.27.0/getting_started/installation/index.md b/docs/versioned_docs/version-v0.27.0/getting_started/installation/index.md new file mode 100644 index 00000000000..4ef86aa5914 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/getting_started/installation/index.md @@ -0,0 +1,48 @@ +--- +title: Nargo Installation +description: + nargo is a command line tool for interacting with Noir programs. This page is a quick guide on how to install Nargo through the most common and easy method, noirup +keywords: [ + Nargo + Noir + Rust + Cargo + Noirup + Installation + Terminal Commands + Version Check + Nightlies + Specific Versions + Branches + Noirup Repository +] +pagination_next: getting_started/hello_noir/index +--- + +`nargo` is the one-stop-shop for almost everything related with Noir. The name comes from our love for Rust and its package manager `cargo`. + +With `nargo`, you can start new projects, compile, execute, prove, verify, test, generate solidity contracts, and do pretty much all that is available in Noir. + +Similarly to `rustup`, we also maintain an easy installation method that covers most machines: `noirup`. + +## Installing Noirup + +Open a terminal on your machine, and write: + +```bash +curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash +``` + +Close the terminal, open another one, and run + +```bash +noirup +``` + +Done. That's it. You should have the latest version working. You can check with `nargo --version`. + +You can also install nightlies, specific versions +or branches. Check out the [noirup repository](https://github.com/noir-lang/noirup) for more +information. + +Now we're ready to start working on [our first Noir program!](../hello_noir/index.md) diff --git a/docs/versioned_docs/version-v0.27.0/getting_started/installation/other_install_methods.md b/docs/versioned_docs/version-v0.27.0/getting_started/installation/other_install_methods.md new file mode 100644 index 00000000000..3634723562b --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/getting_started/installation/other_install_methods.md @@ -0,0 +1,102 @@ +--- +title: Alternative Installations +description: There are different ways to install Nargo, the one-stop shop and command-line tool for developing Noir programs. This guide explains how to specify which version to install when using noirup, and using WSL for windows. +keywords: [ + Installation + Nargo + Noirup + Binaries + Compiling from Source + WSL for Windows + macOS + Linux + Nix + Direnv + Uninstalling Nargo + ] +sidebar_position: 1 +--- + +## Encouraged Installation Method: Noirup + +Noirup is the endorsed method for installing Nargo, streamlining the process of fetching binaries or compiling from source. It supports a range of options to cater to your specific needs, from nightly builds and specific versions to compiling from various sources. + +### Installing Noirup + +First, ensure you have `noirup` installed: + +```sh +curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash +``` + +### Fetching Binaries + +With `noirup`, you can easily switch between different Nargo versions, including nightly builds: + +- **Nightly Version**: Install the latest nightly build. + + ```sh + noirup --version nightly + ``` + +- **Specific Version**: Install a specific version of Nargo. + ```sh + noirup --version + ``` + +### Compiling from Source + +`noirup` also enables compiling Nargo from various sources: + +- **From a Specific Branch**: Install from the latest commit on a branch. + + ```sh + noirup --branch + ``` + +- **From a Fork**: Install from the main branch of a fork. + + ```sh + noirup --repo + ``` + +- **From a Specific Branch in a Fork**: Install from a specific branch in a fork. + + ```sh + noirup --repo --branch + ``` + +- **From a Specific Pull Request**: Install from a specific PR. + + ```sh + noirup --pr + ``` + +- **From a Specific Commit**: Install from a specific commit. + + ```sh + noirup -C + ``` + +- **From Local Source**: Compile and install from a local directory. + ```sh + noirup --path ./path/to/local/source + ``` + +## Installation on Windows + +The default backend for Noir (Barretenberg) doesn't provide Windows binaries at this time. For that reason, Noir cannot be installed natively. 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](#encouraged-installation-method-noirup). + +## Uninstalling Nargo + +If you installed Nargo with `noirup`, you can uninstall Nargo by removing the files in `~/.nargo`, `~/nargo`, and `~/noir_cache`. This ensures that all installed binaries, configurations, and cache related to Nargo are fully removed from your system. + +```bash +rm -r ~/.nargo +rm -r ~/nargo +rm -r ~/noir_cache +``` diff --git a/docs/versioned_docs/version-v0.27.0/getting_started/tooling/_category_.json b/docs/versioned_docs/version-v0.27.0/getting_started/tooling/_category_.json new file mode 100644 index 00000000000..55804c03a71 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/getting_started/tooling/_category_.json @@ -0,0 +1,6 @@ +{ + "position": 2, + "label": "Tooling", + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.27.0/getting_started/tooling/index.mdx b/docs/versioned_docs/version-v0.27.0/getting_started/tooling/index.mdx new file mode 100644 index 00000000000..ec9ccea4115 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/getting_started/tooling/index.mdx @@ -0,0 +1,34 @@ +--- +title: Tooling +Description: This section provides information about the various tools and utilities available for Noir development. It covers IDE tools, Codespaces, and community projects. +Keywords: [Noir, Development, Playground, IDE Tools, Language Service Provider, VS Code Extension, Codespaces, noir-starter, Community Projects, Awesome Noir Repository, Developer Tooling] +--- + +Noir is meant to be easy to develop with. For that reason, a number of utilities have been put together to ease the development process as much as feasible in the zero-knowledge world. + +## IDE tools + +When you install Nargo, you're also installing a Language Service Provider (LSP), which can be used by IDEs to provide syntax highlighting, codelens, warnings, and more. + +The easiest way to use these tools is by installing the [Noir VS Code extension](https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir). + +## Codespaces + +Some Noir repos have leveraged Codespaces in order to ease the development process. You can visit the [noir-starter](https://github.com/noir-lang/noir-starter) for an example. + + + +## GitHub Actions + +You can use `noirup` with GitHub Actions for CI/CD and automated testing. It is as simple as +installing `noirup` and running tests in your GitHub Action `yml` file. + +See the +[config file in the Noir repo](https://github.com/TomAFrench/noir-hashes/blob/master/.github/workflows/noir.yml) for an example usage. + +## Community projects + +As an open-source project, Noir has received many contributions over time. Some of them are related with developer tooling, and you can see some of them in [Awesome Noir repository](https://github.com/noir-lang/awesome-noir#dev-tools) diff --git a/docs/versioned_docs/version-v0.27.0/getting_started/tooling/language_server.md b/docs/versioned_docs/version-v0.27.0/getting_started/tooling/language_server.md new file mode 100644 index 00000000000..81e0356ef8a --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/getting_started/tooling/language_server.md @@ -0,0 +1,43 @@ +--- +title: Language Server +description: Learn about the Noir Language Server, how to install the components, and configuration that may be required. +keywords: [Nargo, Language Server, LSP, VSCode, Visual Studio Code] +sidebar_position: 0 +--- + +This section helps you install and configure the Noir Language Server. + +The Language Server Protocol (LSP) has two components, the [Server](#language-server) and the [Client](#language-client). Below we describe each in the context of Noir. + +## Language Server + +The Server component is provided by the Nargo command line tool that you installed at the beginning of this guide. +As long as Nargo is installed and you've used it to run other commands in this guide, it should be good to go! + +If you'd like to verify that the `nargo lsp` command is available, you can run `nargo --help` and look for `lsp` in the list of commands. If you see it, you're using a version of Noir with LSP support. + +## Language Client + +The Client component is usually an editor plugin that launches the Server. It communicates LSP messages between the editor and the Server. For example, when you save a file, the Client will alert the Server, so it can try to compile the project and report any errors. + +Currently, Noir provides a Language Client for Visual Studio Code via the [vscode-noir](https://github.com/noir-lang/vscode-noir) extension. You can install it via the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir). + +> **Note:** Noir's Language Server Protocol support currently assumes users' VSCode workspace root to be the same as users' Noir project root (i.e. where Nargo.toml lies). +> +> If LSP features seem to be missing / malfunctioning, make sure you are opening your Noir project directly (instead of as a sub-folder) in your VSCode instance. + +When your language server is running correctly and the VSCode plugin is installed, you should see handy codelens buttons for compilation, measuring circuit size, execution, and tests: + +![Compile and Execute](@site/static/img/codelens_compile_execute.png) +![Run test](@site/static/img/codelens_run_test.png) + +You should also see your tests in the `testing` panel: + +![Testing panel](@site/static/img/codelens_testing_panel.png) + +### Configuration + +- **Noir: Enable LSP** - If checked, the extension will launch the Language Server via `nargo lsp` and communicate with it. +- **Noir: Nargo Flags** - Additional flags may be specified if you require them to be added when the extension calls `nargo lsp`. +- **Noir: Nargo Path** - An absolute path to a Nargo binary with the `lsp` command. This may be useful if Nargo is not within the `PATH` of your editor. +- **Noir > Trace: Server** - Setting this to `"messages"` or `"verbose"` will log LSP messages between the Client and Server. Useful for debugging. diff --git a/docs/versioned_docs/version-v0.27.0/getting_started/tooling/noir_codegen.md b/docs/versioned_docs/version-v0.27.0/getting_started/tooling/noir_codegen.md new file mode 100644 index 00000000000..d65151da0ab --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/getting_started/tooling/noir_codegen.md @@ -0,0 +1,113 @@ +--- +title: Noir Codegen for TypeScript +description: Learn how to use Noir codegen to generate TypeScript bindings +keywords: [Nargo, Noir, compile, TypeScript] +sidebar_position: 2 +--- + +When using TypeScript, it is extra work to interpret Noir program outputs in a type-safe way. Third party libraries may exist for popular Noir programs, but they are either hard to find or unmaintained. + +Now you can generate TypeScript bindings for your Noir programs in two steps: +1. Exporting Noir functions using `nargo export` +2. Using the TypeScript module `noir_codegen` to generate TypeScript binding + +**Note:** you can only export functions from a Noir *library* (not binary or contract program types). + +## Installation + +### Your TypeScript project + +If you don't already have a TypeScript project you can add the module with `yarn` (or `npm`), then initialize it: + +```bash +yarn add typescript -D +npx tsc --init +``` + +### Add TypeScript module - `noir_codegen` + +The following command will add the module to your project's devDependencies: + +```bash +yarn add @noir-lang/noir_codegen -D +``` + +### Nargo library +Make sure you have Nargo, v0.25.0 or greater, installed. If you don't, follow the [installation guide](../installation/index.md). + +If you're in a new project, make a `circuits` folder and create a new Noir library: + +```bash +mkdir circuits && cd circuits +nargo new --lib myNoirLib +``` + +## Usage + +### Export ABI of specified functions + +First go to the `.nr` files in your Noir library, and add the `#[export]` macro to each function that you want to use in TypeScript. + +```rust +#[export] +fn your_function(... +``` + +From your Noir library (where `Nargo.toml` is), run the following command: + +```bash +nargo export +``` + +You will now have an `export` directory with a .json file per exported function. + +You can also specify the directory of Noir programs using `--program-dir`, for example: + +```bash +nargo export --program-dir=./circuits/myNoirLib +``` + +### Generate TypeScript bindings from exported functions + +To use the `noir-codegen` package we added to the TypeScript project: + +```bash +yarn noir-codegen ./export/your_function.json +``` + +This creates an `exports` directory with an `index.ts` file containing all exported functions. + +**Note:** adding `--out-dir` allows you to specify an output dir for your TypeScript bindings to go. Eg: + +```bash +yarn noir-codegen ./export/*.json --out-dir ./path/to/output/dir +``` + +## Example .nr function to .ts output + +Consider a Noir library with this function: + +```rust +#[export] +fn not_equal(x: Field, y: Field) -> bool { + x != y +} +``` + +After the export and codegen steps, you should have an `index.ts` like: + +```typescript +export type Field = string; + + +export const is_equal_circuit: CompiledCircuit = {"abi":{"parameters":[{"name":"x","type":{"kind":"field"},"visibility":"private"},{"name":"y","type":{"kind":"field"},"visibility":"private"}],"param_witnesses":{"x":[{"start":0,"end":1}],"y":[{"start":1,"end":2}]},"return_type":{"abi_type":{"kind":"boolean"},"visibility":"private"},"return_witnesses":[4]},"bytecode":"H4sIAAAAAAAA/7WUMQ7DIAxFQ0Krrr2JjSGYLVcpKrn/CaqqDQN12WK+hPBgmWd/wEyHbF1SS923uhOs3pfoChI+wKXMAXzIKyNj4PB0TFTYc0w5RUjoqeAeEu1wqK0F54RGkWvW44LPzExnlkbMEs4JNZmN8PxS42uHv82T8a3Jeyn2Ks+VLPcO558HmyLMCDOXAXXtpPt4R/Rt9T36ss6dS9HGPx/eG17nGegKBQAA"}; + +export async function is_equal(x: Field, y: Field, foreignCallHandler?: ForeignCallHandler): Promise { + const program = new Noir(is_equal_circuit); + const args: InputMap = { x, y }; + const { returnValue } = await program.execute(args, foreignCallHandler); + return returnValue as boolean; +} +``` + +Now the `is_equal()` function and relevant types are readily available for use in TypeScript. diff --git a/docs/versioned_docs/version-v0.27.0/getting_started/tooling/testing.md b/docs/versioned_docs/version-v0.27.0/getting_started/tooling/testing.md new file mode 100644 index 00000000000..d3e0c522473 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/getting_started/tooling/testing.md @@ -0,0 +1,62 @@ +--- +title: Testing in Noir +description: Learn how to use Nargo to test your Noir program in a quick and easy way +keywords: [Nargo, testing, Noir, compile, test] +sidebar_position: 1 +--- + +You can test your Noir programs using Noir circuits. + +Nargo will automatically compile and run any functions which have the decorator `#[test]` on them if +you run `nargo test`. + +For example if you have a program like: + +```rust +fn add(x: u64, y: u64) -> u64 { + x + y +} +#[test] +fn test_add() { + assert(add(2,2) == 4); + assert(add(0,1) == 1); + assert(add(1,0) == 1); +} +``` + +Running `nargo test` will test that the `test_add` function can be executed while satisfying all +the constraints 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.27.0/how_to/_category_.json b/docs/versioned_docs/version-v0.27.0/how_to/_category_.json new file mode 100644 index 00000000000..23b560f610b --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/how_to/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 1, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.27.0/how_to/how-to-oracles.md b/docs/versioned_docs/version-v0.27.0/how_to/how-to-oracles.md new file mode 100644 index 00000000000..8cf8035a5c4 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/how_to/how-to-oracles.md @@ -0,0 +1,276 @@ +--- +title: How to use Oracles +description: Learn how to use oracles in your Noir program with examples in both Nargo and NoirJS. This guide also covers writing a JSON RPC server and providing custom foreign call handlers for NoirJS. +keywords: + - Noir Programming + - Oracles + - Nargo + - NoirJS + - JSON RPC Server + - Foreign Call Handlers +sidebar_position: 1 +--- + +This guide shows you how to use oracles in your Noir program. For the sake of clarity, it assumes that: + +- You have read the [explainer on Oracles](../explainers/explainer-oracle.md) and are comfortable with the concept. +- You have a Noir program to add oracles to. You can create one using the [vite-hardhat starter](https://github.com/noir-lang/noir-starter/tree/main/vite-hardhat) as a boilerplate. +- You understand the concept of a JSON-RPC server. Visit the [JSON-RPC website](https://www.jsonrpc.org/) if you need a refresher. +- You are comfortable with server-side JavaScript (e.g. Node.js, managing packages, etc.). + +For reference, you can find the snippets used in this tutorial on the [Aztec DevRel Repository](https://github.com/AztecProtocol/dev-rel/tree/main/code-snippets/how-to-oracles). + +## Rundown + +This guide has 3 major steps: + +1. How to modify our Noir program to make use of oracle calls as unconstrained functions +2. How to write a JSON RPC Server to resolve these oracle calls with Nargo +3. How to use them in Nargo and how to provide a custom resolver in NoirJS + +## Step 1 - Modify your Noir program + +An oracle is defined in a Noir program by defining two methods: + +- An unconstrained method - This tells the compiler that it is executing an [unconstrained functions](../noir/concepts//unconstrained.md). +- A decorated oracle method - This tells the compiler that this method is an RPC call. + +An example of an oracle that returns a `Field` would be: + +```rust +#[oracle(getSqrt)] +unconstrained fn sqrt(number: Field) -> Field { } + +unconstrained fn get_sqrt(number: Field) -> Field { + sqrt(number) +} +``` + +In this example, we're wrapping our oracle function in a unconstrained method, and decorating it with `oracle(getSqrt)`. We can then call the unconstrained function as we would call any other function: + +```rust +fn main(input: Field) { + let sqrt = get_sqrt(input); +} +``` + +In the next section, we will make this `getSqrt` (defined on the `sqrt` decorator) be a method of the RPC server Noir will use. + +:::danger + +As explained in the [Oracle Explainer](../explainers/explainer-oracle.md), this `main` function is unsafe unless you constrain its return value. For example: + +```rust +fn main(input: Field) { + let sqrt = get_sqrt(input); + assert(sqrt.pow_32(2) as u64 == input as u64); // <---- constrain the return of an oracle! +} +``` + +::: + +:::info + +Currently, oracles only work with single params or array params. For example: + +```rust +#[oracle(getSqrt)] +unconstrained fn sqrt([Field; 2]) -> [Field; 2] { } +``` + +::: + +## Step 2 - Write an RPC server + +Brillig will call *one* RPC server. Most likely you will have to write your own, and you can do it in whatever language you prefer. In this guide, we will do it in Javascript. + +Let's use the above example of an oracle that consumes an array with two `Field` and returns their square roots: + +```rust +#[oracle(getSqrt)] +unconstrained fn sqrt(input: [Field; 2]) -> [Field; 2] { } + +unconstrained fn get_sqrt(input: [Field; 2]) -> [Field; 2] { + sqrt(input) +} + +fn main(input: [Field; 2]) { + let sqrt = get_sqrt(input); + assert(sqrt[0].pow_32(2) as u64 == input[0] as u64); + assert(sqrt[1].pow_32(2) as u64 == input[1] as u64); +} +``` + +:::info + +Why square root? + +In general, computing square roots is computationally more expensive than multiplications, which takes a toll when speaking about ZK applications. In this case, instead of calculating the square root in Noir, we are using our oracle to offload that computation to be made in plain. In our circuit we can simply multiply the two values. + +::: + +Now, we should write the correspondent RPC server, starting with the [default JSON-RPC 2.0 boilerplate](https://www.npmjs.com/package/json-rpc-2.0#example): + +```js +import { JSONRPCServer } from "json-rpc-2.0"; +import express from "express"; +import bodyParser from "body-parser"; + +const app = express(); +app.use(bodyParser.json()); + +const server = new JSONRPCServer(); +app.post("/", (req, res) => { + const jsonRPCRequest = req.body; + server.receive(jsonRPCRequest).then((jsonRPCResponse) => { + if (jsonRPCResponse) { + res.json(jsonRPCResponse); + } else { + res.sendStatus(204); + } + }); +}); + +app.listen(5555); +``` + +Now, we will add our `getSqrt` method, as expected by the `#[oracle(getSqrt)]` decorator in our Noir code. It maps through the params array and returns their square roots: + +```js +server.addMethod("getSqrt", async (params) => { + const values = params[0].Array.map((field) => { + return `${Math.sqrt(parseInt(field, 16))}`; + }); + return { values: [{ Array: values }] }; +}); +``` + +:::tip + +Brillig expects an object with an array of values. Each value is an object declaring to be `Single` or `Array` and returning a field element *as a string*. For example: + +```json +{ "values": [{ "Array": ["1", "2"] }]} +{ "values": [{ "Single": "1" }]} +{ "values": [{ "Single": "1" }, { "Array": ["1", "2"] }]} +``` + +If you're using Typescript, the following types may be helpful in understanding the expected return value and making sure they're easy to follow: + +```js +interface SingleForeignCallParam { + Single: string, +} + +interface ArrayForeignCallParam { + Array: string[], +} + +type ForeignCallParam = SingleForeignCallParam | ArrayForeignCallParam; + +interface ForeignCallResult { + values: ForeignCallParam[], +} +``` + +::: + +## Step 3 - Usage with Nargo + +Using the [`nargo` CLI tool](../getting_started/installation/index.md), you can use oracles in the `nargo test`, `nargo execute` and `nargo prove` commands by passing a value to `--oracle-resolver`. For example: + +```bash +nargo test --oracle-resolver http://localhost:5555 +``` + +This tells `nargo` to use your RPC Server URL whenever it finds an oracle decorator. + +## Step 4 - Usage with NoirJS + +In a JS environment, an RPC server is not strictly necessary, as you may want to resolve your oracles without needing any JSON call at all. NoirJS simply expects that you pass a callback function when you generate proofs, and that callback function can be anything. + +For example, if your Noir program expects the host machine to provide CPU pseudo-randomness, you could simply pass it as the `foreignCallHandler`. You don't strictly need to create an RPC server to serve pseudo-randomness, as you may as well get it directly in your app: + +```js +const foreignCallHandler = (name, inputs) => crypto.randomBytes(16) // etc + +await noir.generateProof(inputs, foreignCallHandler) +``` + +As one can see, in NoirJS, the [`foreignCallHandler`](../reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md) function simply means "a callback function that returns a value of type [`ForeignCallOutput`](../reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md). It doesn't have to be an RPC call like in the case for Nargo. + +:::tip + +Does this mean you don't have to write an RPC server like in [Step #2](#step-2---write-an-rpc-server)? + +You don't technically have to, but then how would you run `nargo test` or `nargo prove`? To use both `Nargo` and `NoirJS` in your development flow, you will have to write a JSON RPC server. + +::: + +In this case, let's make `foreignCallHandler` call the JSON RPC Server we created in [Step #2](#step-2---write-an-rpc-server), by making it a JSON RPC Client. + +For example, using the same `getSqrt` program in [Step #1](#step-1---modify-your-noir-program) (comments in the code): + +```js +import { JSONRPCClient } from "json-rpc-2.0"; + +// declaring the JSONRPCClient +const client = new JSONRPCClient((jsonRPCRequest) => { +// hitting the same JSON RPC Server we coded above + return fetch("http://localhost:5555", { + method: "POST", + headers: { + "content-type": "application/json", + }, + body: JSON.stringify(jsonRPCRequest), + }).then((response) => { + if (response.status === 200) { + return response + .json() + .then((jsonRPCResponse) => client.receive(jsonRPCResponse)); + } else if (jsonRPCRequest.id !== undefined) { + return Promise.reject(new Error(response.statusText)); + } + }); +}); + +// declaring a function that takes the name of the foreign call (getSqrt) and the inputs +const foreignCallHandler = async (name, input) => { + // notice that the "inputs" parameter contains *all* the inputs + // in this case we to make the RPC request with the first parameter "numbers", which would be input[0] + const oracleReturn = await client.request(name, [ + { Array: input[0].map((i) => i.toString("hex")) }, + ]); + return [oracleReturn.values[0].Array]; +}; + +// the rest of your NoirJS code +const input = { input: [4, 16] }; +const { witness } = await noir.execute(numbers, foreignCallHandler); +``` + +:::tip + +If you're in a NoirJS environment running your RPC server together with a frontend app, you'll probably hit a familiar problem in full-stack development: requests being blocked by [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) policy. For development only, you can simply install and use the [`cors` npm package](https://www.npmjs.com/package/cors) to get around the problem: + +```bash +yarn add cors +``` + +and use it as a middleware: + +```js +import cors from "cors"; + +const app = express(); +app.use(cors()) +``` + +::: + +## Conclusion + +Hopefully by the end of this guide, you should be able to: + +- Write your own logic around Oracles and how to write a JSON RPC server to make them work with your Nargo commands. +- Provide custom foreign call handlers for NoirJS. diff --git a/docs/versioned_docs/version-v0.27.0/how_to/how-to-recursion.md b/docs/versioned_docs/version-v0.27.0/how_to/how-to-recursion.md new file mode 100644 index 00000000000..4c45bb87ae2 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/how_to/how-to-recursion.md @@ -0,0 +1,179 @@ +--- +title: How to use recursion on NoirJS +description: Learn how to implement recursion with NoirJS, a powerful tool for creating smart contracts on the EVM blockchain. This guide assumes familiarity with NoirJS, solidity verifiers, and the Barretenberg proving backend. Discover how to generate both final and intermediate proofs using `noir_js` and `backend_barretenberg`. +keywords: + [ + "NoirJS", + "EVM blockchain", + "smart contracts", + "recursion", + "solidity verifiers", + "Barretenberg backend", + "noir_js", + "backend_barretenberg", + "intermediate proofs", + "final proofs", + "nargo compile", + "json import", + "recursive circuit", + "recursive app" + ] +sidebar_position: 1 +--- + +This guide shows you how to use recursive proofs in your NoirJS app. For the sake of clarity, it is assumed that: + +- You already have a NoirJS app. If you don't, please visit the [NoirJS tutorial](../tutorials/noirjs_app.md) and the [reference](../reference/NoirJS/noir_js/index.md). +- You are familiar with what are recursive proofs and you have read the [recursion explainer](../explainers/explainer-recursion.md) +- You already built a recursive circuit following [the reference](../noir/standard_library/recursion.md), and understand how it works. + +It is also assumed that you're not using `noir_wasm` for compilation, and instead you've used [`nargo compile`](../reference/nargo_commands.md) to generate the `json` you're now importing into your project. However, the guide should work just the same if you're using `noir_wasm`. + +:::info + +As you've read in the [explainer](../explainers/explainer-recursion.md), a recursive proof is an intermediate proof. This means that it doesn't necessarily generate the final step that makes it verifiable in a smart contract. However, it is easy to verify within another circuit. + +While "standard" usage of NoirJS packages abstracts final proofs, it currently lacks the necessary interface to abstract away intermediate proofs. This means that these proofs need to be created by using the backend directly. + +In short: + +- `noir_js` generates *only* final proofs +- `backend_barretenberg` generates both types of proofs + +::: + +In a standard recursive app, you're also dealing with at least two circuits. For the purpose of this guide, we will assume the following: + +- `main`: a circuit of type `assert(x != y)`, where `main` is marked with a `#[recursive]` attribute. This attribute states that the backend should generate proofs that are friendly for verification within another circuit. +- `recursive`: a circuit that verifies `main` + +For a full example on how recursive proofs work, please refer to the [noir-examples](https://github.com/noir-lang/noir-examples) repository. We will *not* be using it as a reference for this guide. + +## Step 1: Setup + +In a common NoirJS app, you need to instantiate a backend with something like `const backend = new Backend(circuit)`. Then you feed it to the `noir_js` interface. + +For recursion, this doesn't happen, and the only need for `noir_js` is only to `execute` a circuit and get its witness and return value. Everything else is not interfaced, so it needs to happen on the `backend` object. + +It is also recommended that you instantiate the backend with as many threads as possible, to allow for maximum concurrency: + +```js +const backend = new Backend(circuit, { threads: 8 }) +``` + +:::tip +You can use the [`os.cpus()`](https://nodejs.org/api/os.html#oscpus) object in `nodejs` or [`navigator.hardwareConcurrency`](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/hardwareConcurrency) on the browser to make the most out of those glorious cpu cores +::: + +## Step 2: Generating the witness and the proof for `main` + +After instantiating the backend, you should also instantiate `noir_js`. We will use it to execute the circuit and get the witness. + +```js +const noir = new Noir(circuit, backend) +const { witness } = noir.execute(input) +``` + +With this witness, you are now able to generate the intermediate proof for the main circuit: + +```js +const { proof, publicInputs } = await backend.generateProof(witness) +``` + +:::warning + +Always keep in mind what is actually happening on your development process, otherwise you'll quickly become confused about what circuit we are actually running and why! + +In this case, you can imagine that Alice (running the `main` circuit) is proving something to Bob (running the `recursive` circuit), and Bob is verifying her proof within his proof. + +With this in mind, it becomes clear that our intermediate proof is the one *meant to be verified within another circuit*, so it must be Alice's. Actually, the only final proof in this theoretical scenario would be the last one, sent on-chain. + +::: + +## Step 3 - Verification and proof artifacts + +Optionally, you are able to verify the intermediate proof: + +```js +const verified = await backend.verifyProof({ proof, publicInputs }) +``` + +This can be useful to make sure our intermediate proof was correctly generated. But the real goal is to do it within another circuit. For that, we need to generate recursive proof artifacts that will be passed to the circuit that is verifying the proof we just generated. Instead of passing the proof and verification key as a byte array, we pass them as fields which makes it cheaper to verify in a circuit: + +```js +const { proofAsFields, vkAsFields, vkHash } = await backend.generateRecursiveProofArtifacts( { publicInputs, proof }, publicInputsCount) +``` + +This call takes the public inputs and the proof, but also the public inputs count. While this is easily retrievable by simply counting the `publicInputs` length, the backend interface doesn't currently abstract it away. + +:::info + +The `proofAsFields` has a constant size `[Field; 93]` and verification keys in Barretenberg are always `[Field; 114]`. + +::: + +:::warning + +One common mistake is to forget *who* makes this call. + +In a situation where Alice is generating the `main` proof, if she generates the proof artifacts and sends them to Bob, which gladly takes them as true, this would mean Alice could prove anything! + +Instead, Bob needs to make sure *he* extracts the proof artifacts, using his own instance of the `main` circuit backend. This way, Alice has to provide a valid proof for the correct `main` circuit. + +::: + +## Step 4 - Recursive proof generation + +With the artifacts, generating a recursive proof is no different from a normal proof. You simply use the `backend` (with the recursive circuit) to generate it: + +```js +const recursiveInputs = { + verification_key: vkAsFields, // array of length 114 + proof: proofAsFields, // array of length 93 + size of public inputs + publicInputs: [mainInput.y], // using the example above, where `y` is the only public input + key_hash: vkHash, +} + +const { witness, returnValue } = noir.execute(recursiveInputs) // we're executing the recursive circuit now! +const { proof, publicInputs } = backend.generateProof(witness) +const verified = backend.verifyProof({ proof, publicInputs }) +``` + +You can obviously chain this proof into another proof. In fact, if you're using recursive proofs, you're probably interested of using them this way! + +:::tip + +Managing circuits and "who does what" can be confusing. To make sure your naming is consistent, you can keep them in an object. For example: + +```js +const circuits = { + main: mainJSON, + recursive: recursiveJSON +} +const backends = { + main: new BarretenbergBackend(circuits.main), + recursive: new BarretenbergBackend(circuits.recursive) +} +const noir_programs = { + main: new Noir(circuits.main, backends.main), + recursive: new Noir(circuits.recursive, backends.recursive) +} +``` + +This allows you to neatly call exactly the method you want without conflicting names: + +```js +// Alice runs this 👇 +const { witness: mainWitness } = await noir_programs.main.execute(input) +const proof = await backends.main.generateProof(mainWitness) + +// Bob runs this 👇 +const verified = await backends.main.verifyProof(proof) +const { proofAsFields, vkAsFields, vkHash } = await backends.main.generateRecursiveProofArtifacts( + proof, + numPublicInputs, +); +const recursiveProof = await noir_programs.recursive.generateProof(recursiveInputs) +``` + +::: diff --git a/docs/versioned_docs/version-v0.27.0/how_to/how-to-solidity-verifier.md b/docs/versioned_docs/version-v0.27.0/how_to/how-to-solidity-verifier.md new file mode 100644 index 00000000000..e3c7c1065da --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/how_to/how-to-solidity-verifier.md @@ -0,0 +1,231 @@ +--- +title: Generate a Solidity Verifier +description: + Learn how to run the verifier as a smart contract on the blockchain. Compile a Solidity verifier + contract for your Noir program and deploy it on any EVM blockchain acting as a verifier smart + contract. Read more to find out +keywords: + [ + solidity verifier, + smart contract, + blockchain, + compiler, + plonk_vk.sol, + EVM blockchain, + verifying Noir programs, + proving backend, + Barretenberg, + ] +sidebar_position: 0 +pagination_next: tutorials/noirjs_app +--- + +Noir has the ability to generate a verifier contract in Solidity, which can be deployed in many EVM-compatible blockchains such as Ethereum. + +This allows for a powerful feature set, as one can make use of the conciseness and the privacy provided by Noir in an immutable ledger. Applications can range from simple P2P guessing games, to complex private DeFi interactions. + +This guide shows you how to generate a Solidity Verifier and deploy it on the [Remix IDE](https://remix.ethereum.org/). It is assumed that: + +- You are comfortable with the Solidity programming language and understand how contracts are deployed on the Ethereum network +- You have Noir installed and you have a Noir program. If you don't, [get started](../getting_started/installation/index.md) with Nargo and the example Hello Noir circuit +- You are comfortable navigating RemixIDE. If you aren't or you need a refresher, you can find some video tutorials [here](https://www.youtube.com/channel/UCjTUPyFEr2xDGN6Cg8nKDaA) that could help you. + +## Rundown + +Generating a Solidity Verifier contract is actually a one-command process. However, compiling it and deploying it can have some caveats. Here's the rundown of this guide: + +1. How to generate a solidity smart contract +2. How to compile the smart contract in the RemixIDE +3. How to deploy it to a testnet + +## Step 1 - Generate a contract + +This is by far the most straight-forward step. Just run: + +```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 to any EVM blockchain acting as a verifier smart contract. + +:::info + +It is possible to generate 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 generation of verifier contracts, for the time being these are only in Solidity. +::: + +## Step 2 - Compiling + +We will mostly skip the details of RemixIDE, as the UI can change from version to version. For now, we can just open +Remix and create a blank workspace. + +![Create Workspace](@site/static/img/how-tos/solidity_verifier_1.png) + +We will create a new file to contain the contract Nargo generated, and copy-paste its content. + +:::warning + +You'll likely see a warning advising you to not trust pasted code. While it is an important warning, it is irrelevant in the context of this guide and can be ignored. We will not be deploying anywhere near a mainnet. + +::: + +To compile our the verifier, we can navigate to the compilation tab: + +![Compilation Tab](@site/static/img/how-tos/solidity_verifier_2.png) + +Remix should automatically match a suitable compiler version. However, hitting the "Compile" button will most likely generate a "Stack too deep" error: + +![Stack too deep](@site/static/img/how-tos/solidity_verifier_3.png) + +This is due to the verify function needing to put many variables on the stack, but enabling the optimizer resolves the issue. To do this, let's open the "Advanced Configurations" tab and enable optimization. The default 200 runs will suffice. + +:::info + +This time we will see a warning about an unused function parameter. This is expected, as the `verify` function doesn't use the `_proof` parameter inside a solidity block, it is loaded from calldata and used in assembly. + +::: + +![Compilation success](@site/static/img/how-tos/solidity_verifier_4.png) + +## Step 3 - Deploying + +At this point we should have a compiled contract read to deploy. If we navigate to the deploy section in Remix, we will see many different environments we can deploy to. The steps to deploy on each environment would be out-of-scope for this guide, so we will just use the default Remix VM. + +Looking closely, we will notice that our "Solidity Verifier" is actually three contracts working together: + +- An `UltraVerificationKey` library which simply stores the verification key for our circuit. +- An abstract contract `BaseUltraVerifier` containing most of the verifying logic. +- A main `UltraVerifier` contract that inherits from the Base and uses the Key contract. + +Remix will take care of the dependencies for us so we can simply deploy the UltraVerifier contract by selecting it and hitting "deploy": + +![Deploying UltraVerifier](@site/static/img/how-tos/solidity_verifier_5.png) + +A contract will show up in the "Deployed Contracts" section, where we can retrieve the Verification Key Hash. This is particularly useful for double-checking the deployer contract is the correct one. + +:::note + +Why "UltraVerifier"? + +To be precise, the Noir compiler (`nargo`) doesn't generate the verifier contract directly. It compiles the Noir code into an intermediate language (ACIR), which is then executed by the backend. So it is the backend that returns the verifier smart contract, not Noir. + +In this case, the Barretenberg Backend uses the UltraPlonk proving system, hence the "UltraVerifier" name. + +::: + +## Step 4 - Verifying + +To verify a proof using the Solidity verifier contract, we call the `verify` function in this extended contract: + +```solidity +function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool) +``` + +When using the default example in the [Hello Noir](../getting_started/hello_noir/index.md) guide, the easiest way to confirm that the verifier contract is doing its job is by calling the `verify` function via remix with the required parameters. For `_proof`, run `nargo prove` and use the string in `proof/.proof` (adding the hex `0x` prefix). We can also copy the public input from `Verifier.toml`, as it will be properly formatted as 32-byte strings: + +``` +0x...... , [0x0000.....02] +``` + +A programmatic example of how the `verify` function is called can be seen 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"); +``` + +:::info[Return Values] + +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. + +For example, if you have Noir program like this: + +```rust +fn main( + // Public inputs + pubkey_x: pub Field, + pubkey_y: pub Field, + // Private inputs + priv_key: Field, +) -> pub Field +``` + +the `verify` function will expect the public inputs array (second function parameter) to be of length 3, the two inputs and the return value. Like before, these values are populated in Verifier.toml after running `nargo prove`. + +Passing only two inputs will result in an error such as `PUBLIC_INPUT_COUNT_INVALID(3, 2)`. + +In this case, the inputs parameter to `verify` would be an array ordered as `[pubkey_x, pubkey_y, return]`. + +::: + +:::tip[Structs] + +You can pass structs to the verifier contract. They will be flattened so that the array of inputs is 1-dimensional array. + +For example, 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) { + //... +} +``` + +The order of these inputs would be flattened to: `[x, nested.t1.val1, nested.t1.val2, nested.is_true, y]` + +::: + +The other function you can call is our entrypoint `verify` function, as defined above. + +:::tip + +It's worth noticing that the `verify` function is actually a `view` function. A `view` function does not alter the blockchain state, so it doesn't need to be distributed (i.e. it will run only on the executing node), and therefore doesn't cost any gas. + +This can be particularly useful in some situations. If Alice generated a proof and wants Bob to verify its correctness, Bob doesn't need to run Nargo, NoirJS, or any Noir specific infrastructure. He can simply make a call to the blockchain with the proof and verify it is correct without paying any gas. + +It would be incorrect to say that a Noir proof verification costs any gas at all. However, most of the time the result of `verify` is used to modify state (for example, to update a balance, a game state, etc). In that case the whole network needs to execute it, which does incur gas costs (calldata and execution, but not storage). + +::: + +## A Note on EVM chains + +ZK-SNARK verification depends on some precompiled cryptographic primitives such as Elliptic Curve Pairings (if you like complex math, you can read about EC Pairings [here](https://medium.com/@VitalikButerin/exploring-elliptic-curve-pairings-c73c1864e627)). Not all EVM chains support EC Pairings, notably some of the ZK-EVMs. This means that you won't be able to use the verifier contract in all of them. + +For example, chains like `zkSync ERA` and `Polygon zkEVM` do not currently support these precompiles, so proof verification via Solidity verifier contracts won't work. Here's a quick list of EVM chains that have been tested and are known to work: + +- Optimism +- Arbitrum +- Polygon PoS +- Scroll +- Celo + +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. + +## What's next + +Now that you know how to call a Noir Solidity Verifier on a smart contract using Remix, you should be comfortable with using it with some programmatic frameworks, such as [hardhat](https://github.com/noir-lang/noir-starter/tree/main/vite-hardhat) and [foundry](https://github.com/noir-lang/noir-starter/tree/main/with-foundry). + +You can find other tools, examples, boilerplates and libraries in the [awesome-noir](https://github.com/noir-lang/awesome-noir) repository. + +You should also be ready to write and deploy your first NoirJS app and start generating proofs on websites, phones, and NodeJS environments! Head on to the [NoirJS tutorial](../tutorials/noirjs_app.md) to learn how to do that. diff --git a/docs/versioned_docs/version-v0.27.0/how_to/merkle-proof.mdx b/docs/versioned_docs/version-v0.27.0/how_to/merkle-proof.mdx new file mode 100644 index 00000000000..003c7019a93 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/how_to/merkle-proof.mdx @@ -0,0 +1,48 @@ +--- +title: Prove Merkle Tree Membership +description: + Learn how to use merkle membership proof in Noir to prove that a given leaf is a member of a + merkle tree with a specified root, at a given index. +keywords: + [merkle proof, merkle membership proof, Noir, rust, hash function, Pedersen, sha256, merkle tree] +--- + +Let's walk through an example of a merkle membership proof in Noir that proves that a given leaf is +in a merkle tree. + +```rust +use dep::std; + +fn main(message : [Field; 62], index : Field, hashpath : [Field; 40], root : Field) { + let leaf = std::hash::hash_to_field(message.as_slice()); + 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.as_slice()); +``` + +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.27.0/how_to/using-devcontainers.mdx b/docs/versioned_docs/version-v0.27.0/how_to/using-devcontainers.mdx new file mode 100644 index 00000000000..727ec6ca667 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/how_to/using-devcontainers.mdx @@ -0,0 +1,110 @@ +--- +title: Developer Containers and Codespaces +description: "Learn how to set up a devcontainer in your GitHub repository for a seamless coding experience with Codespaces. Follow our easy 8-step guide to create your own Noir environment without installing Nargo locally." +keywords: ["Devcontainer", "Codespaces", "GitHub", "Noir Environment", "Docker Image", "Development Environment", "Remote Coding", "GitHub Codespaces", "Noir Programming", "Nargo", "VSCode Extensions", "Noirup"] +sidebar_position: 1 +--- + +Adding a developer container configuration file to your Noir project is one of the easiest way to unlock coding in browser. + +## What's a devcontainer after all? + +A [Developer Container](https://containers.dev/) (devcontainer for short) is a Docker image that comes preloaded with tools, extensions, and other tools you need to quickly get started or continue a project, without having to install Nargo locally. Think of it as a development environment in a box. + +There are many advantages to this: + +- It's platform and architecture agnostic +- You don't need to have an IDE installed, or Nargo, or use a terminal at all +- It's safer for using on a public machine or public network + +One of the best ways of using devcontainers is... not using your machine at all, for maximum control, performance, and ease of use. +Enter Codespaces. + +## Codespaces + +If a devcontainer is just a Docker image, then what stops you from provisioning a `p3dn.24xlarge` AWS EC2 instance with 92 vCPUs and 768 GiB RAM and using it to prove your 10-gate SNARK proof? + +Nothing! Except perhaps the 30-40$ per hour it will cost you. + +The problem is that provisioning takes time, and I bet you don't want to see the AWS console every time you want to code something real quick. + +Fortunately, there's an easy and free way to get a decent remote machine ready and loaded in less than 2 minutes: Codespaces. [Codespaces is a Github feature](https://github.com/features/codespaces) that allows you to code in a remote machine by using devcontainers, and it's pretty cool: + +- You can start coding Noir in less than a minute +- It uses the resources of a remote machine, so you can code on your grandma's phone if needed be +- It makes it easy to share work with your frens +- It's fully reusable, you can stop and restart whenever you need to + +:::info + +Don't take out your wallet just yet. Free GitHub accounts get about [15-60 hours of coding](https://github.com/features/codespaces) for free per month, depending on the size of your provisioned machine. + +::: + +## Tell me it's _actually_ easy + +It is! + +Github comes with a default codespace and you can use it to code your own devcontainer. That's exactly what we will be doing in this guide. + + + +8 simple steps: + +#### 1. Create a new repository on GitHub. + +#### 2. Click "Start coding with Codespaces". This will use the default image. + +#### 3. Create a folder called `.devcontainer` in the root of your repository. + +#### 4. Create a Dockerfile in that folder, and paste the following code: + +```docker +FROM --platform=linux/amd64 node:lts-bookworm-slim +SHELL ["/bin/bash", "-c"] +RUN apt update && apt install -y curl bash git tar gzip libc++-dev +RUN curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash +ENV PATH="/root/.nargo/bin:$PATH" +RUN noirup +ENTRYPOINT ["nargo"] +``` +#### 5. Create a file called `devcontainer.json` in the same folder, and paste the following code: + +```json +{ + "name": "Noir on Codespaces", + "build": { + "context": ".", + "dockerfile": "Dockerfile" + }, + "customizations": { + "vscode": { + "extensions": ["noir-lang.vscode-noir"] + } + } +} +``` +#### 6. Commit and push your changes + +This will pull the new image and build it, so it could take a minute or so + +#### 8. Done! +Just wait for the build to finish, and there's your easy Noir environment. + + +Refer to [noir-starter](https://github.com/noir-lang/noir-starter/) as an example of how devcontainers can be used together with codespaces. + + + +## How do I use it? + +Using the codespace is obviously much easier than setting it up. +Just navigate to your repository and click "Code" -> "Open with Codespaces". It should take a few seconds to load, and you're ready to go. + +:::info + +If you really like the experience, you can add a badge to your readme, links to existing codespaces, and more. +Check out the [official docs](https://docs.github.com/en/codespaces/setting-up-your-project-for-codespaces/setting-up-your-repository/facilitating-quick-creation-and-resumption-of-codespaces) for more info. diff --git a/docs/versioned_docs/version-v0.27.0/index.mdx b/docs/versioned_docs/version-v0.27.0/index.mdx new file mode 100644 index 00000000000..75086ddcdde --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/index.mdx @@ -0,0 +1,67 @@ +--- +title: Noir Lang +hide_title: true +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] +sidebar_position: 0 +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +Noir Logo + +Noir is a Domain-Specific Language for SNARK proving systems developed by [Aztec Labs](https://aztec.network/). It allows you to generate complex Zero-Knowledge Programs (ZKP) by using simple and flexible syntax, requiring no previous knowledge on the underlying mathematics or cryptography. + +ZK programs are programs that can generate short proofs of a certain statement without revealing some details about it. You can read more about ZKPs [here](https://dev.to/spalladino/a-beginners-intro-to-coding-zero-knowledge-proofs-c56). + +## What's new about Noir? + +Noir works differently from most ZK languages by taking a two-pronged path. First, it compiles the program to an adaptable intermediate language known as ACIR. From there, depending on a given project's needs, ACIR can be further compiled into an arithmetic circuit for integration with the proving backend. + +:::info + +Noir is backend agnostic, which means it makes no assumptions on which proving backend powers the ZK proof. Being the language that powers [Aztec Contracts](https://docs.aztec.network/developers/contracts/main), it defaults to Aztec's Barretenberg proving backend. + +However, the ACIR output can be transformed to be compatible with other PLONK-based backends, or into a [rank-1 constraint system](https://www.rareskills.io/post/rank-1-constraint-system) suitable for backends such as Arkwork's Marlin. + +::: + +## Who is Noir for? + +Noir can be used both in complex cloud-based backends and in user's smartphones, requiring no knowledge on the underlying math or cryptography. From authorization systems that keep a password in the user's device, to complex on-chain verification of recursive proofs, Noir is designed to abstract away complexity without any significant overhead. Here are some examples of situations where Noir can be used: + + + + Noir Logo + + Aztec Contracts leverage Noir to allow for the storage and execution of private information. Writing an Aztec Contract is as easy as writing Noir, and Aztec developers can easily interact with the network storage and execution through the [Aztec.nr](https://docs.aztec.network/developers/contracts/main) library. + + + Soliditry Verifier Example + Noir can auto-generate Solidity verifier contracts that verify Noir proofs. This allows for non-interactive verification of proofs containing private information in an immutable system. This feature powers a multitude of use-case scenarios, from P2P chess tournaments, to [Aztec Layer-2 Blockchain](https://docs.aztec.network/) + + + Aztec Labs developed NoirJS, an easy interface to generate and verify Noir proofs in a Javascript environment. This allows for Noir to be used in webpages, mobile apps, games, and any other environment supporting JS execution in a standalone manner. + + + + +## Libraries + +Noir is meant to be easy to extend by simply importing Noir libraries just like in Rust. +The [awesome-noir repo](https://github.com/noir-lang/awesome-noir#libraries) is a collection of libraries developed by the Noir community. +Writing a new library is easy and makes code be composable and easy to reuse. See the section on [dependencies](noir/modules_packages_crates/dependencies.md) for more information. diff --git a/docs/versioned_docs/version-v0.27.0/migration_notes.md b/docs/versioned_docs/version-v0.27.0/migration_notes.md new file mode 100644 index 00000000000..6bd740024e5 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/migration_notes.md @@ -0,0 +1,105 @@ +--- +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. + +### `backend encountered an error: libc++.so.1` + +Depending on your OS, you may encounter the following error when running `nargo prove` for the first time: + +```text +The backend encountered an error: "/home/codespace/.nargo/backends/acvm-backend-barretenberg/backend_binary: error while loading shared libraries: libc++.so.1: cannot open shared object file: No such file or directory\n" +``` + +Install the `libc++-dev` library with: + +```bash +sudo apt install libc++-dev +``` + +## ≥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](noir/concepts/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 your 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 file is running [this bash script](https://github.com/noir-lang/barretenberg-js-binary/blob/master/run-bb-js.sh), where we need to gzip it as the Nargo currently expect the backend to be zipped up. + +Then run: + +``` +DESIRED_BINARY_VERSION=0.8.1 nargo info +``` + +This overrides the bb native binary with a bb.js node application instead, which should be compatible with most if not all hardware. This does come with the drawback of being generally slower than native binary. + +0.8.1 indicates bb.js version 0.8.1, so if you change that it will update to a different version or the default version in the script if none was supplied. diff --git a/docs/versioned_docs/version-v0.27.0/noir/concepts/_category_.json b/docs/versioned_docs/version-v0.27.0/noir/concepts/_category_.json new file mode 100644 index 00000000000..7da08f8a8c5 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/noir/concepts/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Concepts", + "position": 0, + "collapsible": true, + "collapsed": true +} \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.27.0/noir/concepts/assert.md b/docs/versioned_docs/version-v0.27.0/noir/concepts/assert.md new file mode 100644 index 00000000000..bcff613a695 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/noir/concepts/assert.md @@ -0,0 +1,45 @@ +--- +title: Assert Function +description: + Learn about the assert function in Noir, which can be used to explicitly constrain the predicate or + comparison expression that follows to be true, and what happens if the expression is false at + runtime. +keywords: [Noir programming language, assert statement, predicate expression, comparison expression] +sidebar_position: 4 +--- + +Noir includes a special `assert` function which will explicitly constrain the predicate/comparison +expression that follows to be true. If this expression is false at runtime, the program will fail to +be proven. Example: + +```rust +fn main(x : Field, y : Field) { + assert(x == y); +} +``` + +> 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`. + +You can optionally provide a message to be logged when the assertion fails: + +```rust +assert(x == y, "x and y are not equal"); +``` + +Aside string literals, the optional message can be a format string or any other type supported as input for Noir's [print](../standard_library/logging.md) functions. This feature lets you incorporate runtime variables into your failed assertion logs: + +```rust +assert(x == y, f"Expected x == y, but got {x} == {y}"); +``` + +Using a variable as an assertion message directly: + +```rust +struct myStruct { + myField: Field +} + +let s = myStruct { myField: y }; +assert(s.myField == x, s); +``` + diff --git a/docs/versioned_docs/version-v0.27.0/noir/concepts/comments.md b/docs/versioned_docs/version-v0.27.0/noir/concepts/comments.md new file mode 100644 index 00000000000..b51a85f5c94 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/noir/concepts/comments.md @@ -0,0 +1,33 @@ +--- +title: Comments +description: + Learn how to write comments in Noir programming language. A comment is a line of code that is + ignored by the compiler, but it can be read by programmers. Single-line and multi-line comments + are supported in Noir. +keywords: [Noir programming language, comments, single-line comments, multi-line comments] +sidebar_position: 10 +--- + +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.27.0/noir/concepts/control_flow.md b/docs/versioned_docs/version-v0.27.0/noir/concepts/control_flow.md new file mode 100644 index 00000000000..045d3c3a5f5 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/noir/concepts/control_flow.md @@ -0,0 +1,77 @@ +--- +title: Control Flow +description: + Learn how to use loops and if expressions in the Noir programming language. Discover the syntax + and examples for for loops and if-else statements. +keywords: [Noir programming language, loops, for loop, if-else statements, Rust syntax] +sidebar_position: 2 +--- + +## 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); +``` + +## 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`. + +### Break and Continue + +In unconstrained code, `break` and `continue` are also allowed in `for` loops. These are only allowed +in unconstrained code since normal constrained code requires that Noir knows exactly how many iterations +a loop may have. `break` and `continue` can be used like so: + +```rust +for i in 0 .. 10 { + println("Iteration start") + + if i == 2 { + continue; + } + + if i == 5 { + break; + } + + println(i); +} +println("Loop end") +``` + +When used, `break` will end the current loop early and jump to the statement after the for loop. In the example +above, the `break` will stop the loop and jump to the `println("Loop end")`. + +`continue` will stop the current iteration of the loop, and jump to the start of the next iteration. In the example +above, `continue` will jump to `println("Iteration start")` when used. Note that the loop continues as normal after this. +The iteration variable `i` is still increased by one as normal when `continue` is used. + +`break` and `continue` cannot currently be used to jump out of more than a single loop at a time. diff --git a/docs/versioned_docs/version-v0.27.0/noir/concepts/data_bus.md b/docs/versioned_docs/version-v0.27.0/noir/concepts/data_bus.md new file mode 100644 index 00000000000..e54fc861257 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/noir/concepts/data_bus.md @@ -0,0 +1,21 @@ +--- +title: Data Bus +sidebar_position: 13 +--- +**Disclaimer** this feature is experimental, do not use it! + +The data bus is an optimization that the backend can use to make recursion more efficient. +In order to use it, you must define some inputs of the program entry points (usually the `main()` +function) with the `call_data` modifier, and the return values with the `return_data` modifier. +These modifiers are incompatible with `pub` and `mut` modifiers. + +## Example + +```rust +fn main(mut x: u32, y: call_data u32, z: call_data [u32;4] ) -> return_data u32 { + let a = z[x]; + a+y +} +``` + +As a result, both call_data and return_data will be treated as private inputs and encapsulated into a read-only array each, for the backend to process. diff --git a/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/_category_.json b/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/_category_.json new file mode 100644 index 00000000000..5d694210bbf --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 0, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/arrays.md b/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/arrays.md new file mode 100644 index 00000000000..efce3e95d32 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/arrays.md @@ -0,0 +1,251 @@ +--- +title: Arrays +description: + Dive into the Array data type in Noir. Grasp its methods, practical examples, and best practices for efficiently using Arrays in your Noir code. +keywords: + [ + noir, + array type, + methods, + examples, + indexing, + ] +sidebar_position: 4 +--- + +An array is one way of grouping together values into one compound type. Array types can be inferred +or explicitly specified via the syntax `[; ]`: + +```rust +fn main(x : Field, y : Field) { + let my_arr = [x, y]; + let your_arr: [Field; 2] = [x, y]; +} +``` + +Here, both `my_arr` and `your_arr` are instantiated as an array containing two `Field` elements. + +Array elements can be accessed using indexing: + +```rust +fn main() { + let a = [1, 2, 3, 4, 5]; + + let first = a[0]; + let second = a[1]; +} +``` + +All elements in an array must be of the same type (i.e. homogeneous). That is, an array cannot group +a `Field` value and a `u8` value together for example. + +You can write mutable arrays, like: + +```rust +fn main() { + let mut arr = [1, 2, 3, 4, 5]; + assert(arr[0] == 1); + + arr[0] = 42; + assert(arr[0] == 42); +} +``` + +You can instantiate a new array of a fixed size with the same value repeated for each element. The following example instantiates an array of length 32 where each element is of type Field and has the value 0. + +```rust +let array: [Field; 32] = [0; 32]; +``` + +Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices), you can just call `as_slice` on your array: + +```rust +let array: [Field; 32] = [0; 32]; +let sl = array.as_slice() +``` + +You can define multidimensional arrays: + +```rust +let array : [[Field; 2]; 2]; +let element = array[0][0]; +``` +However, multidimensional slices are not supported. For example, the following code will error at compile time: +```rust +let slice : [[Field]] = &[]; +``` + +## 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. +Each of these functions are located within the generic impl `impl [T; N] {`. +So anywhere `self` appears, it refers to the variable `self: [T; N]`. + +### len + +Returns the length of an array + +```rust +fn len(self) -> 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(self) -> [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(self, 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(self, 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(self, 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(self, 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(self, 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(self, 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.27.0/noir/concepts/data_types/booleans.md b/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/booleans.md new file mode 100644 index 00000000000..69826fcd724 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/booleans.md @@ -0,0 +1,31 @@ +--- +title: Booleans +description: + Delve into the Boolean data type in Noir. Understand its methods, practical examples, and best practices for using Booleans in your Noir programs. +keywords: + [ + noir, + boolean type, + methods, + examples, + logical operations, + ] +sidebar_position: 2 +--- + + +The `bool` type in Noir has two possible values: `true` and `false`: + +```rust +fn main() { + let t = true; + let f: bool = false; +} +``` + +> **Note:** When returning a boolean value, it will show up as a value of 1 for `true` and 0 for +> `false` in _Verifier.toml_. + +The boolean type is most commonly used in conditionals like `if` expressions and `assert` +statements. More about conditionals is covered in the [Control Flow](../control_flow) and +[Assert Function](../assert) sections. diff --git a/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/fields.md b/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/fields.md new file mode 100644 index 00000000000..a10a4810788 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/fields.md @@ -0,0 +1,192 @@ +--- +title: Fields +description: + Dive deep into the Field data type in Noir. Understand its methods, practical examples, and best practices to effectively use Fields in your Noir programs. +keywords: + [ + noir, + field type, + methods, + examples, + best practices, + ] +sidebar_position: 0 +--- + +The field type corresponds to the native field type of the proving backend. + +The size of a Noir field depends on the elliptic curve's finite field for the proving backend +adopted. For example, a field would be a 254-bit integer when paired with the default backend that +spans the Grumpkin curve. + +Fields support integer arithmetic and are often used as the default numeric type in Noir: + +```rust +fn main(x : Field, y : Field) { + let z = x + y; +} +``` + +`x`, `y` and `z` are all private fields in this example. Using the `let` keyword we defined a new +private value `z` constrained to be equal to `x + y`. + +If proving efficiency is of priority, fields should be used as a default for solving problems. +Smaller integer types (e.g. `u64`) incur extra range constraints. + +## Methods + +After declaring a Field, you can use these common methods on it: + +### to_le_bits + +Transforms the field into an array of bits, Little Endian. + +```rust +fn to_le_bits(_x : Field, _bit_size: u32) -> [u1] +``` + +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] +``` + +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); +} +``` + +### assert_max_bit_size + +Adds a constraint to specify that the field can be represented with `bit_size` number of bits + +```rust +fn assert_max_bit_size(self, bit_size: u32) +``` + +example: + +```rust +fn main() { + let field = 2 + field.assert_max_bit_size(32); +} +``` + +### 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 +``` + + +### lt + +Returns true if the field is less than the other field + +```rust +pub fn lt(self, another: Field) -> bool +``` diff --git a/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/function_types.md b/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/function_types.md new file mode 100644 index 00000000000..f6121af17e2 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/function_types.md @@ -0,0 +1,26 @@ +--- +title: Function types +sidebar_position: 10 +--- + +Noir supports higher-order functions. The syntax for a function type is as follows: + +```rust +fn(arg1_type, arg2_type, ...) -> return_type +``` + +Example: + +```rust +fn assert_returns_100(f: fn() -> Field) { // f takes no args and returns a Field + assert(f() == 100); +} + +fn main() { + assert_returns_100(|| 100); // ok + assert_returns_100(|| 150); // fails +} +``` + +A function type also has an optional capture environment - this is necessary to support closures. +See [Lambdas](../lambdas.md) for more details. diff --git a/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/index.md b/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/index.md new file mode 100644 index 00000000000..357813c147a --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/index.md @@ -0,0 +1,110 @@ +--- +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](../generics.md): + +```rust +type Id = Size; + +fn main() { + let id: Id = 1; + let zero: u32 = 0; + assert(zero + 1 == id); +} +``` + +Type aliases can even refer to other aliases. An error will be issued if they form a cycle: + +```rust +// Ok! +type A = B; +type B = Field; + +type Bad1 = Bad2; + +// error: Dependency cycle found +type Bad2 = Bad1; +// ^^^^^^^^^^^ 'Bad2' recursively depends on itself: Bad2 -> Bad1 -> Bad2 +``` + +### BigInt + +You can achieve BigInt functionality using the [Noir BigInt](https://github.com/shuklaayush/noir-bigint) library. diff --git a/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/integers.md b/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/integers.md new file mode 100644 index 00000000000..1c6b375db49 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/integers.md @@ -0,0 +1,155 @@ +--- +title: Integers +description: Explore the Integer data type in Noir. Learn about its methods, see real-world examples, and grasp how to efficiently use Integers in your Noir code. +keywords: [noir, integer types, methods, examples, arithmetic] +sidebar_position: 1 +--- + +An integer type is a range constrained field type. The Noir frontend supports both unsigned and signed integer types. The allowed sizes are 1, 8, 32 and 64 bits. + +:::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\\$). + +## 128 bits Unsigned Integers + +The built-in structure `U128` allows you to use 128-bit unsigned integers almost like a native integer type. However, there are some differences to keep in mind: +- You cannot cast between a native integer and `U128` +- There is a higher performance cost when using `U128`, compared to a native type. + +Conversion between unsigned integer types and U128 are done through the use of `from_integer` and `to_integer` functions. `from_integer` also accepts the `Field` type as input. + +```rust +fn main() { + let x = U128::from_integer(23); + let y = U128::from_hex("0x7"); + let z = x + y; + assert(z.to_integer() == 30); +} +``` + +`U128` is implemented with two 64 bits limbs, representing the low and high bits, which explains the performance cost. You should expect `U128` to be twice more costly for addition and four times more costly for multiplication. +You can construct a U128 from its limbs: +```rust +fn main(x: u64, y: u64) { + let x = U128::from_u64s_be(x,y); + assert(z.hi == x as Field); + assert(z.lo == y as Field); +} +``` + +Note that the limbs are stored as Field elements in order to avoid unnecessary conversions. +Apart from this, most operations will work as usual: + +```rust +fn main(x: U128, y: U128) { + // multiplication + let c = x * y; + // addition and subtraction + let c = c - x + y; + // division + let c = x / y; + // bit operation; + let c = x & y | y; + // bit shift + let c = x << y; + // comparisons; + let c = x < y; + let c = x == y; +} +``` + +## 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.27.0/noir/concepts/data_types/references.md b/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/references.md new file mode 100644 index 00000000000..a5293d11cfb --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/references.md @@ -0,0 +1,23 @@ +--- +title: References +sidebar_position: 9 +--- + +Noir supports first-class references. References are a bit like pointers: they point to a specific address that can be followed to access the data stored at that address. You can use Rust-like syntax to use pointers in Noir: the `&` operator references the variable, the `*` operator dereferences it. + +Example: + +```rust +fn main() { + let mut x = 2; + + // you can reference x as &mut and pass it to multiplyBy2 + multiplyBy2(&mut x); +} + +// you can access &mut here +fn multiplyBy2(x: &mut Field) { + // and dereference it with * + *x = *x * 2; +} +``` diff --git a/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/slices.mdx b/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/slices.mdx new file mode 100644 index 00000000000..828faf4a8f8 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/slices.mdx @@ -0,0 +1,170 @@ +--- +title: Slices +description: Explore the Slice data type in Noir. Understand its methods, see real-world examples, and learn how to effectively use Slices in your Noir programs. +keywords: [noir, slice type, methods, examples, subarrays] +sidebar_position: 5 +--- + +import Experimental from '@site/src/components/Notes/_experimental.mdx'; + + + +A slice is a dynamically-sized view into a sequence of elements. They can be resized at runtime, but because they don't own the data, they cannot be returned from a circuit. You can treat slices as arrays without a constrained size. + +```rust +use dep::std::slice; + +fn main() -> pub Field { + let mut slice: [Field] = &[0; 2]; + + let mut new_slice = slice.push_back(6); + new_slice.len() +} +``` + +To write a slice literal, use a preceeding ampersand as in: `&[0; 2]` or +`&[1, 2, 3]`. + +It is important to note that slices are not references to arrays. In Noir, +`&[..]` is more similar to an immutable, growable vector. + +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); +``` + +### len + +Returns the length of a slice + +```rust +fn len(self) -> Field +``` + +Example: + +```rust +fn main() { + let slice = &[42, 42]; + assert(slice.len() == 2); +} +``` diff --git a/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/strings.md b/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/strings.md new file mode 100644 index 00000000000..311dfd64416 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/strings.md @@ -0,0 +1,80 @@ +--- +title: Strings +description: + Discover the String data type in Noir. Learn about its methods, see real-world examples, and understand how to effectively manipulate and use Strings in Noir. +keywords: + [ + noir, + string type, + methods, + examples, + concatenation, + ] +sidebar_position: 3 +--- + + +The string type is a fixed length value defined with `str`. + +You can use strings in `assert()` functions or print them with +`println()`. See more about [Logging](../../standard_library/logging). + +```rust +use dep::std; + +fn main(message : pub str<11>, hex_as_string : str<4>) { + println(message); + assert(message == "hello world"); + assert(hex_as_string == "0x41"); +} +``` + +You can convert a `str` to a byte array by calling `as_bytes()` +or a vector by calling `as_bytes_vec()`. + +```rust +fn main() { + let message = "hello world"; + let message_bytes = message.as_bytes(); + let mut message_vec = message.as_bytes_vec(); + assert(message_bytes.len() == 11); + assert(message_bytes[0] == 104); + assert(message_bytes[0] == message_vec.get(0)); +} +``` + +## Escape characters + +You can use escape characters for your strings: + +| Escape Sequence | Description | +|-----------------|-----------------| +| `\r` | Carriage Return | +| `\n` | Newline | +| `\t` | Tab | +| `\0` | Null Character | +| `\"` | Double Quote | +| `\\` | Backslash | + +Example: + +```rust +let s = "Hello \"world" // prints "Hello "world" +let s = "hey \tyou"; // prints "hey you" +``` + +## Raw strings + +A raw string begins with the letter `r` and is optionally delimited by a number of hashes `#`. + +Escape characters are *not* processed within raw strings. All contents are interpreted literally. + +Example: + +```rust +let s = r"Hello world"; +let s = r#"Simon says "hello world""#; + +// Any number of hashes may be used (>= 1) as long as the string also terminates with the same number of hashes +let s = r#####"One "#, Two "##, Three "###, Four "####, Five will end the string."#####; +``` diff --git a/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/structs.md b/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/structs.md new file mode 100644 index 00000000000..dbf68c99813 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/structs.md @@ -0,0 +1,70 @@ +--- +title: Structs +description: + Explore the Struct data type in Noir. Learn about its methods, see real-world examples, and grasp how to effectively define and use Structs in your Noir programs. +keywords: + [ + noir, + struct type, + methods, + examples, + data structures, + ] +sidebar_position: 8 +--- + +A struct also allows for grouping multiple values of different types. Unlike tuples, we can also +name each field. + +> **Note:** The usage of _field_ here refers to each element of the struct and is unrelated to the +> field type of Noir. + +Defining a struct requires giving it a name and listing each field within as `: ` pairs: + +```rust +struct Animal { + hands: Field, + legs: Field, + eyes: u8, +} +``` + +An instance of a struct can then be created with actual values in `: ` pairs in any +order. Struct fields are accessible using their given names: + +```rust +fn main() { + let legs = 4; + + let dog = Animal { + eyes: 2, + hands: 0, + legs, + }; + + let zero = dog.hands; +} +``` + +Structs can also be destructured in a pattern, binding each field to a new variable: + +```rust +fn main() { + let Animal { hands, legs: feet, eyes } = get_octopus(); + + let ten = hands + feet + eyes as u8; +} + +fn get_octopus() -> Animal { + let octopus = Animal { + hands: 0, + legs: 8, + eyes: 2, + }; + + octopus +} +``` + +The new variables can be bound with names different from the original struct field names, as +showcased in the `legs --> feet` binding in the example above. diff --git a/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/tuples.md b/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/tuples.md new file mode 100644 index 00000000000..2ec5c9c4113 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/tuples.md @@ -0,0 +1,48 @@ +--- +title: Tuples +description: + Dive into the Tuple data type in Noir. Understand its methods, practical examples, and best practices for efficiently using Tuples in your Noir code. +keywords: + [ + noir, + tuple type, + methods, + examples, + multi-value containers, + ] +sidebar_position: 7 +--- + +A tuple collects multiple values like an array, but with the added ability to collect values of +different types: + +```rust +fn main() { + let tup: (u8, u64, Field) = (255, 500, 1000); +} +``` + +One way to access tuple elements is via destructuring using pattern matching: + +```rust +fn main() { + let tup = (1, 2); + + let (one, two) = tup; + + let three = one + two; +} +``` + +Another way to access tuple elements is via direct member access, using a period (`.`) followed by +the index of the element we want to access. Index `0` corresponds to the first tuple element, `1` to +the second and so on: + +```rust +fn main() { + let tup = (5, 6, 7, 8); + + let five = tup.0; + let eight = tup.3; +} +``` diff --git a/docs/versioned_docs/version-v0.27.0/noir/concepts/distinct.md b/docs/versioned_docs/version-v0.27.0/noir/concepts/distinct.md new file mode 100644 index 00000000000..6c993b8b5e0 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/noir/concepts/distinct.md @@ -0,0 +1,64 @@ +--- +title: Distinct Witnesses +sidebar_position: 11 +--- + +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.27.0/noir/concepts/functions.md b/docs/versioned_docs/version-v0.27.0/noir/concepts/functions.md new file mode 100644 index 00000000000..2c9bc33fdfc --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/noir/concepts/functions.md @@ -0,0 +1,226 @@ +--- +title: Functions +description: + Learn how to declare functions and methods in Noir, a programming language with Rust semantics. + This guide covers parameter declaration, return types, call expressions, and more. +keywords: [Noir, Rust, functions, methods, parameter declaration, return types, call expressions] +sidebar_position: 1 +--- + +Functions in Noir follow the same semantics of Rust, though Noir does not support early returns. + +To declare a function the `fn` keyword is used. + +```rust +fn foo() {} +``` + +By default, functions are visible only within the package they are defined. To make them visible outside of that package (for example, as part of a [library](../modules_packages_crates/crates_and_packages.md#libraries)), you should mark them as `pub`: + +```rust +pub fn foo() {} +``` + +You can also restrict the visibility of the function to only the crate it was defined in, by specifying `pub(crate)`: + +```rust +pub(crate) fn foo() {} //foo can only be called within its crate +``` + +All parameters in a function must have a type and all types are known at compile time. The parameter +is pre-pended with a colon and the parameter type. Multiple parameters are separated using a comma. + +```rust +fn foo(x : Field, y : Field){} +``` + +The return type of a function can be stated by using the `->` arrow notation. The function below +states that the foo function must return a `Field`. If the function returns no value, then the arrow +is omitted. + +```rust +fn foo(x : Field, y : Field) -> Field { + x + y +} +``` + +Note that a `return` keyword is unneeded in this case - the last expression in a function's body is +returned. + +## Main function + +If you're writing a binary, the `main` function is the starting point of your program. You can pass all types of expressions to it, as long as they have a fixed size at compile time: + +```rust +fn main(x : Field) // this is fine: passing a Field +fn main(x : [Field; 2]) // this is also fine: passing a Field with known size at compile-time +fn main(x : (Field, bool)) // 👌: passing a (Field, bool) tuple means size 2 +fn main(x : str<5>) // this is fine, as long as you pass a string of size 5 + +fn main(x : Vec) // can't compile, has variable size +fn main(x : [Field]) // can't compile, has variable size +fn main(....// i think you got it by now +``` + +Keep in mind [tests](../../getting_started/tooling/testing.md) don't differentiate between `main` and any other function. The following snippet passes tests, but won't compile or prove: + +```rust +fn main(x : [Field]) { + assert(x[0] == 1); +} + +#[test] +fn test_one() { + main(&[1, 2]); +} +``` + +```bash +$ nargo test +[testing] Running 1 test functions +[testing] Testing test_one... ok +[testing] All tests passed + +$ nargo check +The application panicked (crashed). +Message: Cannot have variable sized arrays as a parameter to main +``` + +## Call Expressions + +Calling a function in Noir is executed by using the function name and passing in the necessary +arguments. + +Below we show how to call the `foo` function from the `main` function using a call expression: + +```rust +fn main(x : Field, y : Field) { + let z = foo(x); +} + +fn foo(x : Field) -> Field { + x + x +} +``` + +## Methods + +You can define methods in Noir on any struct type in scope. + +```rust +struct MyStruct { + foo: Field, + bar: Field, +} + +impl MyStruct { + fn new(foo: Field) -> MyStruct { + MyStruct { + foo, + bar: 2, + } + } + + fn sum(self) -> Field { + self.foo + self.bar + } +} + +fn main() { + let s = MyStruct::new(40); + assert(s.sum() == 42); +} +``` + +Methods are just syntactic sugar for functions, so if we wanted to we could also call `sum` as +follows: + +```rust +assert(MyStruct::sum(s) == 42); +``` + +It is also possible to specialize which method is chosen depending on the [generic](./generics.md) type that is used. In this example, the `foo` function returns different values depending on its type: + +```rust +struct Foo {} + +impl Foo { + fn foo(self) -> Field { 1 } +} + +impl Foo { + fn foo(self) -> Field { 2 } +} + +fn main() { + let f1: Foo = Foo{}; + let f2: Foo = Foo{}; + assert(f1.foo() + f2.foo() == 3); +} +``` + +Also note that impls with the same method name defined in them cannot overlap. For example, if we already have `foo` defined for `Foo` and `Foo` like we do above, we cannot also define `foo` in an `impl Foo` since it would be ambiguous which version of `foo` to choose. + +```rust +// Including this impl in the same project as the above snippet would +// cause an overlapping impls error +impl Foo { + fn foo(self) -> Field { 3 } +} +``` + +## Lambdas + +Lambdas are anonymous functions. They follow the syntax of Rust - `|arg1, arg2, ..., argN| return_expression`. + +```rust +let add_50 = |val| val + 50; +assert(add_50(100) == 150); +``` + +See [Lambdas](./lambdas.md) for more details. + +## Attributes + +Attributes are metadata that can be applied to a function, using the following syntax: `#[attribute(value)]`. + +Supported attributes include: + +- **builtin**: the function is implemented by the compiler, for efficiency purposes. +- **deprecated**: mark the function as _deprecated_. Calling the function will generate a warning: `warning: use of deprecated function` +- **field**: Used to enable conditional compilation of code depending on the field size. See below for more details +- **oracle**: mark the function as _oracle_; meaning it is an external unconstrained function, implemented in noir_js. See [Unconstrained](./unconstrained.md) and [NoirJS](../../reference/NoirJS/noir_js/index.md) for more details. +- **test**: mark the function as unit tests. See [Tests](../../getting_started/tooling/testing.md) for more details + +### Field Attribute + +The field attribute defines which field the function is compatible for. The function is conditionally compiled, under the condition that the field attribute matches the Noir native field. +The field can be defined implicitly, by using the name of the elliptic curve usually associated to it - for instance bn254, bls12_381 - or explicitly by using the field (prime) order, in decimal or hexadecimal form. +As a result, it is possible to define multiple versions of a function with each version specialized for a different field attribute. This can be useful when a function requires different parameters depending on the underlying elliptic curve. + +Example: we define the function `foo()` three times below. Once for the default Noir bn254 curve, once for the field $\mathbb F_{23}$, which will normally never be used by Noir, and once again for the bls12_381 curve. + +```rust +#[field(bn254)] +fn foo() -> u32 { + 1 +} + +#[field(23)] +fn foo() -> u32 { + 2 +} + +// This commented code would not compile as foo would be defined twice because it is the same field as bn254 +// #[field(21888242871839275222246405745257275088548364400416034343698204186575808495617)] +// fn foo() -> u32 { +// 2 +// } + +#[field(bls12_381)] +fn foo() -> u32 { + 3 +} +``` + +If the field name is not known to Noir, it will discard the function. Field names are case insensitive. diff --git a/docs/versioned_docs/version-v0.27.0/noir/concepts/generics.md b/docs/versioned_docs/version-v0.27.0/noir/concepts/generics.md new file mode 100644 index 00000000000..ddd42bf1f9b --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/noir/concepts/generics.md @@ -0,0 +1,106 @@ +--- +title: Generics +description: Learn how to use Generics in Noir +keywords: [Noir, Rust, generics, functions, structs] +sidebar_position: 7 +--- + +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 print(self) { + for _i in 0 .. self.count { + println(self.value); + } + } +} + +fn main() { + let repeated = RepeatedValue { value: "Hello!", count: 2 }; + 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 + +Since a generic type `T` can represent any type, how can we call functions on the underlying type? +In other words, how can we go from "any type `T`" to "any type `T` that has certain methods available?" + +This is what [traits](../concepts/traits) are for in Noir. Here's an example of a function generic over +any type `T` that implements the `Eq` trait for equality: + +```rust +fn first_element_is_equal(array1: [T; N], array2: [T; N]) -> bool + where T: Eq +{ + if (array1.len() == 0) | (array2.len() == 0) { + true + } else { + array1[0] == array2[0] + } +} + +fn main() { + assert(first_element_is_equal([1, 2, 3], [1, 5, 6])); + + // We can use first_element_is_equal for arrays of any type + // as long as we have an Eq impl for the types we pass in + let array = [MyStruct::new(), MyStruct::new()]; + assert(array_eq(array, array, MyStruct::eq)); +} + +impl Eq for MyStruct { + fn eq(self, other: MyStruct) -> bool { + self.foo == other.foo + } +} +``` + +You can find more details on traits and trait implementations on the [traits page](../concepts/traits). diff --git a/docs/versioned_docs/version-v0.27.0/noir/concepts/globals.md b/docs/versioned_docs/version-v0.27.0/noir/concepts/globals.md new file mode 100644 index 00000000000..063a3d89248 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/noir/concepts/globals.md @@ -0,0 +1,72 @@ +--- +title: Global Variables +description: + Learn about global variables in Noir. Discover how + to declare, modify, and use them in your programs. +keywords: [noir programming language, globals, global variables, constants] +sidebar_position: 8 +--- + +## Globals + + +Noir supports global variables. The global's type can be inferred by the compiler entirely: + +```rust +global N = 5; // Same as `global N: Field = 5` + +global TUPLE = (3, 2); + +fn main() { + assert(N == 5); + assert(N == TUPLE.0 + TUPLE.1); +} +``` + +:::info + +Globals can be defined as any expression, so long as they don't depend on themselves - otherwise there would be a dependency cycle! For example: + +```rust +global T = foo(T); // dependency error +``` + +::: + + +If they are initialized to a literal integer, globals can be used to specify an array's length: + +```rust +global N: Field = 2; + +fn main(y : [Field; N]) { + assert(y[0] == y[1]) +} +``` + +A global from another module can be imported or referenced externally like any other name: + +```rust +global N = 20; + +fn main() { + assert(my_submodule::N != N); +} + +mod my_submodule { + global N: Field = 10; +} +``` + +When a global is used, Noir replaces the name with its definition on each occurrence. +This means globals defined using function calls will repeat the call each time they're used: + +```rust +global RESULT = foo(); + +fn foo() -> [Field; 100] { ... } +``` + +This is usually fine since Noir will generally optimize any function call that does not +refer to a program input into a constant. It should be kept in mind however, if the called +function performs side-effects like `println`, as these will still occur on each use. diff --git a/docs/versioned_docs/version-v0.27.0/noir/concepts/lambdas.md b/docs/versioned_docs/version-v0.27.0/noir/concepts/lambdas.md new file mode 100644 index 00000000000..be3c7e0b5ca --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/noir/concepts/lambdas.md @@ -0,0 +1,81 @@ +--- +title: Lambdas +description: Learn how to use anonymous functions in Noir programming language. +keywords: [Noir programming language, lambda, closure, function, anonymous function] +sidebar_position: 9 +--- + +## 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.27.0/noir/concepts/mutability.md b/docs/versioned_docs/version-v0.27.0/noir/concepts/mutability.md new file mode 100644 index 00000000000..fdeef6a87c5 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/noir/concepts/mutability.md @@ -0,0 +1,121 @@ +--- +title: Mutability +description: + Learn about mutable variables in Noir. Discover how + to declare, modify, and use them in your programs. +keywords: [noir programming language, mutability in noir, mutable variables] +sidebar_position: 8 +--- + +Variables in noir can be declared mutable via the `mut` keyword. Mutable variables can be reassigned +to via an assignment expression. + +```rust +let x = 2; +x = 3; // error: x must be mutable to be assigned to + +let mut y = 3; +let y = 4; // OK +``` + +The `mut` modifier can also apply to patterns: + +```rust +let (a, mut b) = (1, 2); +a = 11; // error: a must be mutable to be assigned to +b = 12; // OK + +let mut (c, d) = (3, 4); +c = 13; // OK +d = 14; // OK + +// etc. +let MyStruct { x: mut y } = MyStruct { x: a }; +// y is now in scope +``` + +Note that mutability in noir is local and everything is passed by value, so if a called function +mutates its parameters then the parent function will keep the old value of the parameters. + +```rust +fn main() -> pub Field { + let x = 3; + helper(x); + x // x is still 3 +} + +fn helper(mut x: i32) { + x = 4; +} +``` + +## Non-local mutability + +Non-local mutability can be achieved through the mutable reference type `&mut T`: + +```rust +fn set_to_zero(x: &mut Field) { + *x = 0; +} + +fn main() { + let mut y = 42; + set_to_zero(&mut y); + assert(*y == 0); +} +``` + +When creating a mutable reference, the original variable being referred to (`y` in this +example) must also be mutable. Since mutable references are a reference type, they must +be explicitly dereferenced via `*` to retrieve the underlying value. Note that this yields +a copy of the value, so mutating this copy will not change the original value behind the +reference: + +```rust +fn main() { + let mut x = 1; + let x_ref = &mut x; + + let mut y = *x_ref; + let y_ref = &mut y; + + x = 2; + *x_ref = 3; + + y = 4; + *y_ref = 5; + + assert(x == 3); + assert(*x_ref == 3); + assert(y == 5); + assert(*y_ref == 5); +} +``` + +Note that types in Noir are actually deeply immutable so the copy that occurs when +dereferencing is only a conceptual copy - no additional constraints will occur. + +Mutable references can also be stored within structs. Note that there is also +no lifetime parameter on these unlike rust. This is because the allocated memory +always lasts the entire program - as if it were an array of one element. + +```rust +struct Foo { + x: &mut Field +} + +impl Foo { + fn incr(mut self) { + *self.x += 1; + } +} + +fn main() { + let foo = Foo { x: &mut 0 }; + foo.incr(); + assert(*foo.x == 1); +} +``` + +In general, you should avoid non-local & shared mutability unless it is needed. Sticking +to only local mutability will improve readability and potentially improve compiler optimizations as well. diff --git a/docs/versioned_docs/version-v0.27.0/noir/concepts/ops.md b/docs/versioned_docs/version-v0.27.0/noir/concepts/ops.md new file mode 100644 index 00000000000..60425cb8994 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/noir/concepts/ops.md @@ -0,0 +1,98 @@ +--- +title: Logical Operations +description: + Learn about the supported arithmetic and logical operations in the Noir programming language. + Discover how to perform operations on private input types, integers, and booleans. +keywords: + [ + Noir programming language, + supported operations, + arithmetic operations, + logical operations, + predicate operators, + bitwise operations, + short-circuiting, + backend, + ] +sidebar_position: 3 +--- + +# Operations + +## Table of Supported Operations + +| Operation | Description | Requirements | +| :-------- | :------------------------------------------------------------: | -------------------------------------: | +| + | Adds two private input types together | Types must be private input | +| - | Subtracts two private input types together | Types must be private input | +| \* | Multiplies two private input types together | Types must be private input | +| / | Divides two private input types together | Types must be private input | +| ^ | XOR two private input types together | Types must be integer | +| & | AND two private input types together | Types must be integer | +| \| | OR two private input types together | Types must be integer | +| \<\< | Left shift an integer by another integer amount | Types must be integer | +| >> | Right shift an integer by another integer amount | Types must be integer | +| ! | Bitwise not of a value | Type must be integer or boolean | +| \< | returns a bool if one value is less than the other | Upper bound must have a known bit size | +| \<= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | +| > | returns a bool if one value is more than the other | Upper bound must have a known bit size | +| >= | returns a bool if one value is more than or equal to the other | Upper bound must have a known bit size | +| == | returns a bool if one value is equal to the other | Both types must not be constants | +| != | returns a bool if one value is not equal to the other | Both types must not be constants | + +### Predicate Operators + +`<,<=, !=, == , >, >=` are known as predicate/comparison operations because they compare two values. +This differs from the operations such as `+` where the operands are used in _computation_. + +### Bitwise Operations Example + +```rust +fn main(x : Field) { + let y = x as u32; + let z = y & y; +} +``` + +`z` is implicitly constrained to be the result of `y & y`. The `&` operand is used to denote bitwise +`&`. + +> `x & x` would not compile as `x` is a `Field` and not an integer type. + +### Logical Operators + +Noir has no support for the logical operators `||` and `&&`. This is because encoding the +short-circuiting that these operators require can be inefficient for Noir's backend. Instead you can +use the bitwise operators `|` and `&` which operate identically 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.27.0/noir/concepts/oracles.md b/docs/versioned_docs/version-v0.27.0/noir/concepts/oracles.md new file mode 100644 index 00000000000..2e6a6818d48 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/noir/concepts/oracles.md @@ -0,0 +1,23 @@ +--- +title: Oracles +description: Dive into how Noir supports Oracles via RPC calls, and learn how to declare an Oracle in Noir with our comprehensive guide. +keywords: + - Noir + - Oracles + - RPC Calls + - Unconstrained Functions + - Programming + - Blockchain +sidebar_position: 6 +--- + +Noir has support for Oracles via RPC calls. This means Noir will make an RPC call and use the return value for proof generation. + +Since Oracles are not resolved by Noir, they are [`unconstrained` functions](./unconstrained.md) + +You can declare an Oracle through the `#[oracle()]` flag. Example: + +```rust +#[oracle(get_number_sequence)] +unconstrained fn get_number_sequence(_size: Field) -> [Field] {} +``` diff --git a/docs/versioned_docs/version-v0.27.0/noir/concepts/shadowing.md b/docs/versioned_docs/version-v0.27.0/noir/concepts/shadowing.md new file mode 100644 index 00000000000..5ce6130d201 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/noir/concepts/shadowing.md @@ -0,0 +1,44 @@ +--- +title: Shadowing +sidebar_position: 12 +--- + +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.27.0/noir/concepts/traits.md b/docs/versioned_docs/version-v0.27.0/noir/concepts/traits.md new file mode 100644 index 00000000000..ef1445a5907 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/noir/concepts/traits.md @@ -0,0 +1,389 @@ +--- +title: Traits +description: + Traits in Noir can be used to abstract out a common interface for functions across + several data types. +keywords: [noir programming language, traits, interfaces, generic, protocol] +sidebar_position: 14 +--- + +## Overview + +Traits in Noir are a useful abstraction similar to interfaces or protocols in other languages. Each trait defines +the interface of several methods contained within the trait. Types can then implement this trait by providing +implementations for these methods. For example in the program: + +```rust +struct Rectangle { + width: Field, + height: Field, +} + +impl Rectangle { + fn area(self) -> Field { + self.width * self.height + } +} + +fn log_area(r: Rectangle) { + println(r.area()); +} +``` + +We have a function `log_area` to log the area of a `Rectangle`. Now how should we change the program if we want this +function to work on `Triangle`s as well?: + +```rust +struct Triangle { + width: Field, + height: Field, +} + +impl Triangle { + fn area(self) -> Field { + self.width * self.height / 2 + } +} +``` + +Making `log_area` generic over all types `T` would be invalid since not all types have an `area` method. Instead, we can +introduce a new `Area` trait and make `log_area` generic over all types `T` that implement `Area`: + +```rust +trait Area { + fn area(self) -> Field; +} + +fn log_area(shape: T) where T: Area { + println(shape.area()); +} +``` + +We also need to explicitly implement `Area` for `Rectangle` and `Triangle`. We can do that by changing their existing +impls slightly. Note that the parameter types and return type of each of our `area` methods must match those defined +by the `Area` trait. + +```rust +impl Area for Rectangle { + fn area(self) -> Field { + self.width * self.height + } +} + +impl Area for Triangle { + fn area(self) -> Field { + self.width * self.height / 2 + } +} +``` + +Now we have a working program that is generic over any type of Shape that is used! Others can even use this program +as a library with their own types - such as `Circle` - as long as they also implement `Area` for these types. + +## Where Clauses + +As seen in `log_area` above, when we want to create a function or method that is generic over any type that implements +a trait, we can add a where clause to the generic function. + +```rust +fn log_area(shape: T) where T: Area { + println(shape.area()); +} +``` + +It is also possible to apply multiple trait constraints on the same variable at once by combining traits with the `+` +operator. Similarly, we can have multiple trait constraints by separating each with a comma: + +```rust +fn foo(elements: [T], thing: U) where + T: Default + Add + Eq, + U: Bar, +{ + let mut sum = T::default(); + + for element in elements { + sum += element; + } + + if sum == T::default() { + thing.bar(); + } +} +``` + +## Generic Implementations + +You can add generics to a trait implementation by adding the generic list after the `impl` keyword: + +```rust +trait Second { + fn second(self) -> Field; +} + +impl Second for (T, Field) { + fn second(self) -> Field { + self.1 + } +} +``` + +You can also implement a trait for every type this way: + +```rust +trait Debug { + fn debug(self); +} + +impl Debug for T { + fn debug(self) { + println(self); + } +} + +fn main() { + 1.debug(); +} +``` + +### Generic Trait Implementations With Where Clauses + +Where clauses can also be placed on trait implementations themselves to restrict generics in a similar way. +For example, while `impl Foo for T` implements the trait `Foo` for every type, `impl Foo for T where T: Bar` +will implement `Foo` only for types that also implement `Bar`. This is often used for implementing generic types. +For example, here is the implementation for array equality: + +```rust +impl Eq for [T; N] where T: Eq { + // Test if two arrays have the same elements. + // Because both arrays must have length N, we know their lengths already match. + fn eq(self, other: Self) -> bool { + let mut result = true; + + for i in 0 .. self.len() { + // The T: Eq constraint is needed to call == on the array elements here + result &= self[i] == other[i]; + } + + result + } +} +``` + +## Generic Traits + +Traits themselves can also be generic by placing the generic arguments after the trait name. These generics are in +scope of every item within the trait. + +```rust +trait Into { + // Convert `self` to type `T` + fn into(self) -> T; +} +``` + +When implementing generic traits the generic arguments of the trait must be specified. This is also true anytime +when referencing a generic trait (e.g. in a `where` clause). + +```rust +struct MyStruct { + array: [Field; 2], +} + +impl Into<[Field; 2]> for MyStruct { + fn into(self) -> [Field; 2] { + self.array + } +} + +fn as_array(x: T) -> [Field; 2] + where T: Into<[Field; 2]> +{ + x.into() +} + +fn main() { + let array = [1, 2]; + let my_struct = MyStruct { array }; + + assert_eq(as_array(my_struct), array); +} +``` + +## Trait Methods With No `self` + +A trait can contain any number of methods, each of which have access to the `Self` type which represents each type +that eventually implements the trait. Similarly, the `self` variable is available as well but is not required to be used. +For example, we can define a trait to create a default value for a type. This trait will need to return the `Self` type +but doesn't need to take any parameters: + +```rust +trait Default { + fn default() -> Self; +} +``` + +Implementing this trait can be done similarly to any other trait: + +```rust +impl Default for Field { + fn default() -> Field { + 0 + } +} + +struct MyType {} + +impl Default for MyType { + fn default() -> Field { + MyType {} + } +} +``` + +However, since there is no `self` parameter, we cannot call it via the method call syntax `object.method()`. +Instead, we'll need to refer to the function directly. This can be done either by referring to the +specific impl `MyType::default()` or referring to the trait itself `Default::default()`. In the later +case, type inference determines the impl that is selected. + +```rust +let my_struct = MyStruct::default(); + +let x: Field = Default::default(); +let result = x + Default::default(); +``` + +:::warning + +```rust +let _ = Default::default(); +``` + +If type inference cannot select which impl to use because of an ambiguous `Self` type, an impl will be +arbitrarily selected. This occurs most often when the result of a trait function call with no parameters +is unused. To avoid this, when calling a trait function with no `self` or `Self` parameters or return type, +always refer to it via the implementation type's namespace - e.g. `MyType::default()`. +This is set to change to an error in future Noir versions. + +::: + +## Default Method Implementations + +A trait can also have default implementations of its methods by giving a body to the desired functions. +Note that this body must be valid for all types that may implement the trait. As a result, the only +valid operations on `self` will be operations valid for any type or other operations on the trait itself. + +```rust +trait Numeric { + fn add(self, other: Self) -> Self; + + // Default implementation of double is (self + self) + fn double(self) -> Self { + self.add(self) + } +} +``` + +When implementing a trait with default functions, a type may choose to implement only the required functions: + +```rust +impl Numeric for Field { + fn add(self, other: Field) -> Field { + self + other + } +} +``` + +Or it may implement the optional methods as well: + +```rust +impl Numeric for u32 { + fn add(self, other: u32) -> u32 { + self + other + } + + fn double(self) -> u32 { + self * 2 + } +} +``` + +## Impl Specialization + +When implementing traits for a generic type it is possible to implement the trait for only a certain combination +of generics. This can be either as an optimization or because those specific generics are required to implement the trait. + +```rust +trait Sub { + fn sub(self, other: Self) -> Self; +} + +struct NonZero { + value: T, +} + +impl Sub for NonZero { + fn sub(self, other: Self) -> Self { + let value = self.value - other.value; + assert(value != 0); + NonZero { value } + } +} +``` + +## Overlapping Implementations + +Overlapping implementations are disallowed by Noir to ensure Noir's decision on which impl to select is never ambiguous. +This means if a trait `Foo` is already implemented +by a type `Bar` for all `T`, then we cannot also have a separate impl for `Bar` (or any other +type argument). Similarly, if there is an impl for all `T` such as `impl Debug for T`, we cannot create +any more impls to `Debug` for other types since it would be ambiguous which impl to choose for any given +method call. + +```rust +trait Trait {} + +// Previous impl defined here +impl Trait for (A, B) {} + +// error: Impl for type `(Field, Field)` overlaps with existing impl +impl Trait for (Field, Field) {} +``` + +## Trait Coherence + +Another restriction on trait implementations is coherence. This restriction ensures other crates cannot create +impls that may overlap with other impls, even if several unrelated crates are used as dependencies in the same +program. + +The coherence restriction is: to implement a trait, either the trait itself or the object type must be declared +in the crate the impl is in. + +In practice this often comes up when using types provided by libraries. If a library provides a type `Foo` that does +not implement a trait in the standard library such as `Default`, you may not `impl Default for Foo` in your own crate. +While restrictive, this prevents later issues or silent changes in the program if the `Foo` library later added its +own impl for `Default`. If you are a user of the `Foo` library in this scenario and need a trait not implemented by the +library your choices are to either submit a patch to the library or use the newtype pattern. + +### The Newtype Pattern + +The newtype pattern gets around the coherence restriction by creating a new wrapper type around the library type +that we cannot create `impl`s for. Since the new wrapper type is defined in our current crate, we can create +impls for any trait we need on it. + +```rust +struct Wrapper { + foo: dep::some_library::Foo, +} + +impl Default for Wrapper { + fn default() -> Wrapper { + Wrapper { + foo: dep::some_library::Foo::new(), + } + } +} +``` + +Since we have an impl for our own type, the behavior of this code will not change even if `some_library` is updated +to provide its own `impl Default for Foo`. The downside of this pattern is that it requires extra wrapping and +unwrapping of values when converting to and from the `Wrapper` and `Foo` types. diff --git a/docs/versioned_docs/version-v0.27.0/noir/concepts/unconstrained.md b/docs/versioned_docs/version-v0.27.0/noir/concepts/unconstrained.md new file mode 100644 index 00000000000..b8e71fe65f0 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/noir/concepts/unconstrained.md @@ -0,0 +1,99 @@ +--- +title: Unconstrained Functions +description: "Learn about what unconstrained functions in Noir are, how to use them and when you'd want to." + +keywords: [Noir programming language, unconstrained, open] +sidebar_position: 5 +--- + +Unconstrained functions are functions which do not constrain any of the included computation and allow for non-deterministic 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 AND 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. + +## Break and Continue + +In addition to loops over runtime bounds, `break` and `continue` are also available in unconstrained code. See [break and continue](../concepts/control_flow/#break-and-continue) diff --git a/docs/versioned_docs/version-v0.27.0/noir/modules_packages_crates/_category_.json b/docs/versioned_docs/version-v0.27.0/noir/modules_packages_crates/_category_.json new file mode 100644 index 00000000000..1debcfe7675 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/noir/modules_packages_crates/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Modules, Packages and Crates", + "position": 2, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.27.0/noir/modules_packages_crates/crates_and_packages.md b/docs/versioned_docs/version-v0.27.0/noir/modules_packages_crates/crates_and_packages.md new file mode 100644 index 00000000000..95ee9f52ab2 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/noir/modules_packages_crates/crates_and_packages.md @@ -0,0 +1,43 @@ +--- +title: Crates and Packages +description: Learn how to use Crates and Packages in your Noir project +keywords: [Nargo, dependencies, package management, crates, package] +sidebar_position: 0 +--- + +## Crates + +A crate is the smallest amount of code that the Noir compiler considers at a time. +Crates can contain modules, and the modules may be defined in other files that get compiled with the crate, as we’ll see in the coming sections. + +### Crate Types + +A Noir crate can come in several forms: binaries, libraries or contracts. + +#### Binaries + +_Binary crates_ are programs which you can compile to an ACIR circuit which you can then create proofs against. Each must have a function called `main` that defines the ACIR circuit which is to be proved. + +#### Libraries + +_Library crates_ don't have a `main` function and they don't compile down to ACIR. Instead they define functionality intended to be shared with multiple projects, and eventually included in a binary crate. + +#### Contracts + +Contract crates are similar to binary crates in that they compile to ACIR which you can create proofs against. They are different in that they do not have a single `main` function, but are a collection of functions to be deployed to the [Aztec network](https://aztec.network). You can learn more about the technical details of Aztec in the [monorepo](https://github.com/AztecProtocol/aztec-packages) or contract [examples](https://github.com/AztecProtocol/aztec-packages/tree/master/noir-projects/noir-contracts/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.27.0/noir/modules_packages_crates/dependencies.md b/docs/versioned_docs/version-v0.27.0/noir/modules_packages_crates/dependencies.md new file mode 100644 index 00000000000..04c1703d929 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/noir/modules_packages_crates/dependencies.md @@ -0,0 +1,124 @@ +--- +title: Dependencies +description: + Learn how to specify and manage dependencies in Nargo, allowing you to upload packages to GitHub + and use them easily in your project. +keywords: [Nargo, dependencies, GitHub, package management, versioning] +sidebar_position: 1 +--- + +Nargo allows you to upload packages to GitHub and use them as dependencies. + +## Specifying a dependency + +Specifying a dependency requires a tag to a specific commit and the git url to the url containing +the package. + +Currently, there are no requirements on the tag contents. If requirements are added, it would follow +semver 2.0 guidelines. + +> Note: Without a `tag` , there would be no versioning and dependencies would change each time you +> compile your project. + +For example, to add the [ecrecover-noir library](https://github.com/colinnielsen/ecrecover-noir) to your project, add it to `Nargo.toml`: + +```toml +# Nargo.toml + +[dependencies] +ecrecover = {tag = "v0.8.0", git = "https://github.com/colinnielsen/ecrecover-noir"} +``` + +If the module is in a subdirectory, you can define a subdirectory in your git repository, for example: + +```toml +# Nargo.toml + +[dependencies] +easy_private_token_contract = {tag ="v0.1.0-alpha62", git = "https://github.com/AztecProtocol/aztec-packages", directory = "noir-contracts/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 +└── lib_a + ├── Nargo.toml + └── src + └── lib.nr +``` + +Inside of the binary crate, you can specify: + +```toml +# Nargo.toml + +[dependencies] +lib_a = { path = "../lib_a" } +``` + +## 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 lib_a referenced above: + +```rust +use dep::ecrecover; +use dep::lib_a; +``` + +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.27.0/noir/modules_packages_crates/modules.md b/docs/versioned_docs/version-v0.27.0/noir/modules_packages_crates/modules.md new file mode 100644 index 00000000000..ae822a1cff4 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/noir/modules_packages_crates/modules.md @@ -0,0 +1,105 @@ +--- +title: Modules +description: + Learn how to organize your files using modules in Noir, following the same convention as Rust's + module system. Examples included. +keywords: [Noir, Rust, modules, organizing files, sub-modules] +sidebar_position: 2 +--- + +Noir's module system follows the same convention as the _newer_ version of Rust's module system. + +## Purpose of Modules + +Modules are used to organize 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.27.0/noir/modules_packages_crates/workspaces.md b/docs/versioned_docs/version-v0.27.0/noir/modules_packages_crates/workspaces.md new file mode 100644 index 00000000000..513497f12bf --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/noir/modules_packages_crates/workspaces.md @@ -0,0 +1,42 @@ +--- +title: Workspaces +sidebar_position: 3 +--- + +Workspaces are a feature of nargo that allow you to manage multiple related Noir packages in a single repository. A workspace is essentially a group of related projects that share common build output directories and configurations. + +Each Noir project (with it's own Nargo.toml file) can be thought of as a package. Each package is expected to contain exactly one "named circuit", being the "name" defined in Nargo.toml with the program logic defined in `./src/main.nr`. + +For a project with the following structure: + +```tree +├── crates +│ ├── a +│ │ ├── Nargo.toml +│ │ └── Prover.toml +│ │ └── src +│ │ └── main.nr +│ └── b +│ ├── Nargo.toml +│ └── Prover.toml +│ └── src +│ └── main.nr +│ +└── Nargo.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.27.0/noir/standard_library/_category_.json b/docs/versioned_docs/version-v0.27.0/noir/standard_library/_category_.json new file mode 100644 index 00000000000..af04c0933fd --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/noir/standard_library/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Standard Library", + "position": 1, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.27.0/noir/standard_library/bigint.md b/docs/versioned_docs/version-v0.27.0/noir/standard_library/bigint.md new file mode 100644 index 00000000000..da6a7cdfd81 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/noir/standard_library/bigint.md @@ -0,0 +1,119 @@ +--- +title: Big Integers +description: How to use big integers from Noir standard library +keywords: + [ + Big Integer, + Noir programming language, + Noir libraries, + ] +--- + +The BigInt module in the standard library exposes some class of integers which do not fit (well) into a Noir native field. It implements modulo arithmetic, modulo a 'big' prime number. + +:::note + +The module can currently be considered as `Field`s with fixed modulo sizes used by a set of elliptic curves, in addition to just the native curve. [More work](https://github.com/noir-lang/noir/issues/510) is needed to achieve arbitrarily sized big integers. + +::: + +Currently 6 classes of integers (i.e 'big' prime numbers) are available in the module, namely: + +- BN254 Fq: Bn254Fq +- BN254 Fr: Bn254Fr +- Secp256k1 Fq: Secpk1Fq +- Secp256k1 Fr: Secpk1Fr +- Secp256r1 Fr: Secpr1Fr +- Secp256r1 Fq: Secpr1Fq + +Where XXX Fq and XXX Fr denote respectively the order of the base and scalar field of the (usual) elliptic curve XXX. +For instance the big integer 'Secpk1Fq' in the standard library refers to integers modulo $2^{256}-2^{32}-977$. + +Feel free to explore the source code for the other primes: + +```rust title="big_int_definition" showLineNumbers +struct BigInt { + pointer: u32, + modulus: u32, +} +``` +> Source code: noir_stdlib/src/bigint.nr#L16-L21 + + +## Example usage + +A common use-case is when constructing a big integer from its bytes representation, and performing arithmetic operations on it: + +```rust title="big_int_example" showLineNumbers +fn big_int_example(x: u8, y: u8) { + let a = Secpk1Fq::from_le_bytes(&[x, y, 0, 45, 2]); + let b = Secpk1Fq::from_le_bytes(&[y, x, 9]); + let c = (a + b) * b / a; + let d = c.to_le_bytes(); + println(d[0]); +} +``` +> Source code: test_programs/execution_success/bigint/src/main.nr#L20-L28 + + +## Methods + +The available operations for each big integer are: + +### from_le_bytes + +Construct a big integer from its little-endian bytes representation. Example: + +```rust + let a = Secpk1Fq::from_le_bytes(&[x, y, 0, 45, 2]); + ``` + +Sure, here's the formatted version of the remaining methods: + +### to_le_bytes + +Return the little-endian bytes representation of a big integer. Example: + +```rust +let bytes = a.to_le_bytes(); +``` + +### add + +Add two big integers. Example: + +```rust +let sum = a + b; +``` + +### sub + +Subtract two big integers. Example: + +```rust +let difference = a - b; +``` + +### mul + +Multiply two big integers. Example: + +```rust +let product = a * b; +``` + +### div + +Divide two big integers. Note that division is field division and not euclidean division. Example: + +```rust +let quotient = a / b; +``` + +### eq + +Compare two big integers. Example: + +```rust +let are_equal = a == b; +``` diff --git a/docs/versioned_docs/version-v0.27.0/noir/standard_library/black_box_fns.md b/docs/versioned_docs/version-v0.27.0/noir/standard_library/black_box_fns.md new file mode 100644 index 00000000000..be8c65679c3 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/noir/standard_library/black_box_fns.md @@ -0,0 +1,31 @@ +--- +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. + +The ACVM spec defines a set of blackbox functions which backends will be expected to implement. This allows backends to use optimized implementations of these constraints if they have them, however they may also fallback to less efficient naive implementations if not. + +## Function list + +Here is a list of the current black box functions: + +- [SHA256](./cryptographic_primitives/hashes.mdx#sha256) +- [Schnorr signature verification](./cryptographic_primitives/schnorr.mdx) +- [Blake2s](./cryptographic_primitives/hashes.mdx#blake2s) +- [Blake3](./cryptographic_primitives/hashes.mdx#blake3) +- [Pedersen Hash](./cryptographic_primitives/hashes.mdx#pedersen_hash) +- [Pedersen Commitment](./cryptographic_primitives/hashes.mdx#pedersen_commitment) +- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification.mdx) +- [Fixed base scalar multiplication](./cryptographic_primitives/scalar.mdx) +- AND +- XOR +- RANGE +- [Keccak256](./cryptographic_primitives/hashes.mdx#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. + +You can view the black box functions defined in the ACVM code [here](https://github.com/noir-lang/noir/blob/master/acvm-repo/acir/src/circuit/black_box_functions.rs). diff --git a/docs/versioned_docs/version-v0.27.0/noir/standard_library/bn254.md b/docs/versioned_docs/version-v0.27.0/noir/standard_library/bn254.md new file mode 100644 index 00000000000..3294f005dbb --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/noir/standard_library/bn254.md @@ -0,0 +1,46 @@ +--- +title: Bn254 Field Library +--- + +Noir provides a module in standard library with some optimized functions for bn254 Fr in `std::field::bn254`. + +## decompose + +```rust +fn decompose(x: Field) -> (Field, Field) {} +``` + +Decomposes a single field into two fields, low and high. The low field contains the lower 16 bytes of the input field and the high field contains the upper 16 bytes of the input field. Both field results are range checked to 128 bits. + + +## assert_gt + +```rust +fn assert_gt(a: Field, b: Field) {} +``` + +Asserts that a > b. This will generate less constraints than using `assert(gt(a, b))`. + +## assert_lt + +```rust +fn assert_lt(a: Field, b: Field) {} +``` + +Asserts that a < b. This will generate less constraints than using `assert(lt(a, b))`. + +## gt + +```rust +fn gt(a: Field, b: Field) -> bool {} +``` + +Returns true if a > b. + +## lt + +```rust +fn lt(a: Field, b: Field) -> bool {} +``` + +Returns true if a < b. \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.27.0/noir/standard_library/containers/boundedvec.md b/docs/versioned_docs/version-v0.27.0/noir/standard_library/containers/boundedvec.md new file mode 100644 index 00000000000..ce4529f6e57 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/noir/standard_library/containers/boundedvec.md @@ -0,0 +1,326 @@ +--- +title: Bounded Vectors +keywords: [noir, vector, bounded vector, slice] +sidebar_position: 1 +--- + +A `BoundedVec` is a growable storage similar to a `Vec` except that it +is bounded with a maximum possible length. Unlike `Vec`, `BoundedVec` is not implemented +via slices and thus is not subject to the same restrictions slices are (notably, nested +slices - and thus nested vectors as well - are disallowed). + +Since a BoundedVec is backed by a normal array under the hood, growing the BoundedVec by +pushing an additional element is also more efficient - the length only needs to be increased +by one. + +For these reasons `BoundedVec` should generally be preferred over `Vec` when there +is a reasonable maximum bound that can be placed on the vector. + +Example: + +```rust +let mut vector: BoundedVec = BoundedVec::new(); +for i in 0..5 { + vector.push(i); +} +assert(vector.len() == 5); +assert(vector.max_len() == 10); +``` + +## Methods + +### new + +```rust +pub fn new() -> Self +``` + +Creates a new, empty vector of length zero. + +Since this container is backed by an array internally, it still needs an initial value +to give each element. To resolve this, each element is zeroed internally. This value +is guaranteed to be inaccessible unless `get_unchecked` is used. + +Example: + +```rust +let empty_vector: BoundedVec = BoundedVec::new(); +assert(empty_vector.len() == 0); +``` + +Note that whenever calling `new` the maximum length of the vector should always be specified +via a type signature: + +```rust title="new_example" showLineNumbers +fn foo() -> BoundedVec { + // Ok! MaxLen is specified with a type annotation + let v1: BoundedVec = BoundedVec::new(); + let v2 = BoundedVec::new(); + + // Ok! MaxLen is known from the type of foo's return value + v2 +} + +fn bad() { + let mut v3 = BoundedVec::new(); + + // Not Ok! We don't know if v3's MaxLen is at least 1, and the compiler often infers 0 by default. + v3.push(5); +} +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L11-L27 + + +This defaulting of `MaxLen` (and numeric generics in general) to zero may change in future noir versions +but for now make sure to use type annotations when using bounded vectors. Otherwise, you will receive a constraint failure at runtime when the vec is pushed to. + +### get + +```rust +pub fn get(mut self: Self, index: u64) -> T { +``` + +Retrieves an element from the vector at the given index, starting from zero. + +If the given index is equal to or greater than the length of the vector, this +will issue a constraint failure. + +Example: + +```rust +fn foo(v: BoundedVec) { + let first = v.get(0); + let last = v.get(v.len() - 1); + assert(first != last); +} +``` + +### get_unchecked + +```rust +pub fn get_unchecked(mut self: Self, index: u64) -> T { +``` + +Retrieves an element from the vector at the given index, starting from zero, without +performing a bounds check. + +Since this function does not perform a bounds check on length before accessing the element, +it is unsafe! Use at your own risk! + +Example: + +```rust title="get_unchecked_example" showLineNumbers +fn sum_of_first_three(v: BoundedVec) -> u32 { + // Always ensure the length is larger than the largest + // index passed to get_unchecked + assert(v.len() > 2); + let first = v.get_unchecked(0); + let second = v.get_unchecked(1); + let third = v.get_unchecked(2); + first + second + third +} +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L54-L64 + + + +### push + +```rust +pub fn push(&mut self, elem: T) { +``` + +Pushes an element to the end of the vector. This increases the length +of the vector by one. + +Panics if the new length of the vector will be greater than the max length. + +Example: + +```rust title="bounded-vec-push-example" showLineNumbers +let mut v: BoundedVec = BoundedVec::new(); + + v.push(1); + v.push(2); + + // Panics with failed assertion "push out of bounds" + v.push(3); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L68-L76 + + +### pop + +```rust +pub fn pop(&mut self) -> T +``` + +Pops the element at the end of the vector. This will decrease the length +of the vector by one. + +Panics if the vector is empty. + +Example: + +```rust title="bounded-vec-pop-example" showLineNumbers +let mut v: BoundedVec = BoundedVec::new(); + v.push(1); + v.push(2); + + let two = v.pop(); + let one = v.pop(); + + assert(two == 2); + assert(one == 1); + // error: cannot pop from an empty vector + // let _ = v.pop(); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L81-L93 + + +### len + +```rust +pub fn len(self) -> u64 { +``` + +Returns the current length of this vector + +Example: + +```rust title="bounded-vec-len-example" showLineNumbers +let mut v: BoundedVec = BoundedVec::new(); + assert(v.len() == 0); + + v.push(100); + assert(v.len() == 1); + + v.push(200); + v.push(300); + v.push(400); + assert(v.len() == 4); + + let _ = v.pop(); + let _ = v.pop(); + assert(v.len() == 2); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L98-L113 + + +### max_len + +```rust +pub fn max_len(_self: BoundedVec) -> u64 { +``` + +Returns the maximum length of this vector. This is always +equal to the `MaxLen` parameter this vector was initialized with. + +Example: + +```rust title="bounded-vec-max-len-example" showLineNumbers +let mut v: BoundedVec = BoundedVec::new(); + + assert(v.max_len() == 5); + v.push(10); + assert(v.max_len() == 5); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L118-L124 + + +### storage + +```rust +pub fn storage(self) -> [T; MaxLen] { +``` + +Returns the internal array within this vector. +Since arrays in Noir are immutable, mutating the returned storage array will not mutate +the storage held internally by this vector. + +Note that uninitialized elements may be zeroed out! + +Example: + +```rust title="bounded-vec-storage-example" showLineNumbers +let mut v: BoundedVec = BoundedVec::new(); + + assert(v.storage() == [0, 0, 0, 0, 0]); + + v.push(57); + assert(v.storage() == [57, 0, 0, 0, 0]); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L129-L136 + + +### extend_from_array + +```rust +pub fn extend_from_array(&mut self, array: [T; Len]) +``` + +Pushes each element from the given array to this vector. + +Panics if pushing each element would cause the length of this vector +to exceed the maximum length. + +Example: + +```rust title="bounded-vec-extend-from-array-example" showLineNumbers +let mut vec: BoundedVec = BoundedVec::new(); + vec.extend_from_array([2, 4]); + + assert(vec.len == 2); + assert(vec.get(0) == 2); + assert(vec.get(1) == 4); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L141-L148 + + +### extend_from_bounded_vec + +```rust +pub fn extend_from_bounded_vec(&mut self, vec: BoundedVec) +``` + +Pushes each element from the other vector to this vector. The length of +the other vector is left unchanged. + +Panics if pushing each element would cause the length of this vector +to exceed the maximum length. + +Example: + +```rust title="bounded-vec-extend-from-bounded-vec-example" showLineNumbers +let mut v1: BoundedVec = BoundedVec::new(); + let mut v2: BoundedVec = BoundedVec::new(); + + v2.extend_from_array([1, 2, 3]); + v1.extend_from_bounded_vec(v2); + + assert(v1.storage() == [1, 2, 3, 0, 0]); + assert(v2.storage() == [1, 2, 3, 0, 0, 0, 0]); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L153-L162 + + +### any + +```rust +pub fn any(self, predicate: fn[Env](T) -> bool) -> bool +``` + +Returns true if the given predicate returns true for any element +in this vector. + +Example: + +```rust title="bounded-vec-any-example" showLineNumbers +let mut v: BoundedVec = BoundedVec::new(); + v.extend_from_array([2, 4, 6]); + + let all_even = !v.any(|elem: u32| elem % 2 != 0); + assert(all_even); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L229-L235 + diff --git a/docs/versioned_docs/version-v0.27.0/noir/standard_library/containers/hashmap.md b/docs/versioned_docs/version-v0.27.0/noir/standard_library/containers/hashmap.md new file mode 100644 index 00000000000..91604af765d --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/noir/standard_library/containers/hashmap.md @@ -0,0 +1,569 @@ +--- +title: HashMap +keywords: [noir, map, hash, hashmap] +sidebar_position: 1 +--- + +`HashMap` is used to efficiently store and look up key-value pairs. + +`HashMap` is a bounded type which can store anywhere from zero to `MaxLen` total elements. +Note that due to hash collisions, the actual maximum number of elements stored by any particular +hashmap is likely lower than `MaxLen`. This is true even with cryptographic hash functions since +every hash value will be performed modulo `MaxLen`. + +When creating `HashMap`s, the `MaxLen` generic should always be specified if it is not already +known. Otherwise, the compiler may infer a different value for `MaxLen` (such as zero), which +will likely change the result of the program. This behavior is set to become an error in future +versions instead. + +Example: + +```rust +// Create a mapping from Fields to u32s with a maximum length of 12 +// using a pedersen hash +let mut map: HashMap> = HashMap::default(); + +map.insert(1, 2); +map.insert(3, 4); + +let two = map.get(1).unwrap(); +``` + +## Methods + +### default + +```rust title="default" showLineNumbers +impl Default for HashMap +where + B: BuildHasher + Default, + H: Hasher + Default +{ + fn default() -> Self { +``` +> Source code: noir_stdlib/src/collections/map.nr#L462-L469 + + +Creates a fresh, empty HashMap. + +When using this function, always make sure to specify the maximum size of the hash map. + +This is the same `default` from the `Default` implementation given further below. It is +repeated here for convenience since it is the recommended way to create a hashmap. + +Example: + +```rust title="default_example" showLineNumbers +let hashmap: HashMap> = HashMap::default(); + assert(hashmap.is_empty()); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L202-L205 + + +Because `HashMap` has so many generic arguments that are likely to be the same throughout +your program, it may be helpful to create a type alias: + +```rust title="type_alias" showLineNumbers +type MyMap = HashMap>; +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L196-L198 + + +### with_hasher + +```rust title="with_hasher" showLineNumbers +pub fn with_hasher(_build_hasher: B) -> Self + where + B: BuildHasher { +``` +> Source code: noir_stdlib/src/collections/map.nr#L82-L86 + + +Creates a hashmap with an existing `BuildHasher`. This can be used to ensure multiple +hashmaps are created with the same hasher instance. + +Example: + +```rust title="with_hasher_example" showLineNumbers +let my_hasher: BuildHasherDefault = Default::default(); + let hashmap: HashMap> = HashMap::with_hasher(my_hasher); + assert(hashmap.is_empty()); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L207-L211 + + +### get + +```rust title="get" showLineNumbers +pub fn get( + self, + key: K + ) -> Option + where + K: Eq + Hash, + B: BuildHasher, + H: Hasher { +``` +> Source code: noir_stdlib/src/collections/map.nr#L278-L287 + + +Retrieves a value from the hashmap, returning `Option::none()` if it was not found. + +Example: + +```rust title="get_example" showLineNumbers +fn get_example(map: HashMap>) { + let x = map.get(12); + + if x.is_some() { + assert(x.unwrap() == 42); + } +} +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L299-L307 + + +### insert + +```rust title="insert" showLineNumbers +pub fn insert( + &mut self, + key: K, + value: V + ) + where + K: Eq + Hash, + B: BuildHasher, + H: Hasher { +``` +> Source code: noir_stdlib/src/collections/map.nr#L313-L323 + + +Inserts a new key-value pair into the map. If the key was already in the map, its +previous value will be overridden with the newly provided one. + +Example: + +```rust title="insert_example" showLineNumbers +let mut map: HashMap> = HashMap::default(); + map.insert(12, 42); + assert(map.len() == 1); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L213-L217 + + +### remove + +```rust title="remove" showLineNumbers +pub fn remove( + &mut self, + key: K + ) + where + K: Eq + Hash, + B: BuildHasher, + H: Hasher { +``` +> Source code: noir_stdlib/src/collections/map.nr#L356-L365 + + +Removes the given key-value pair from the map. If the key was not already present +in the map, this does nothing. + +Example: + +```rust title="remove_example" showLineNumbers +map.remove(12); + assert(map.is_empty()); + + // If a key was not present in the map, remove does nothing + map.remove(12); + assert(map.is_empty()); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L221-L228 + + +### is_empty + +```rust title="is_empty" showLineNumbers +pub fn is_empty(self) -> bool { +``` +> Source code: noir_stdlib/src/collections/map.nr#L115-L117 + + +True if the length of the hash map is empty. + +Example: + +```rust title="is_empty_example" showLineNumbers +assert(map.is_empty()); + + map.insert(1, 2); + assert(!map.is_empty()); + + map.remove(1); + assert(map.is_empty()); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L230-L238 + + +### len + +```rust title="len" showLineNumbers +pub fn len(self) -> u64 { +``` +> Source code: noir_stdlib/src/collections/map.nr#L264-L266 + + +Returns the current length of this hash map. + +Example: + +```rust title="len_example" showLineNumbers +// This is equivalent to checking map.is_empty() + assert(map.len() == 0); + + map.insert(1, 2); + map.insert(3, 4); + map.insert(5, 6); + assert(map.len() == 3); + + // 3 was already present as a key in the hash map, so the length is unchanged + map.insert(3, 7); + assert(map.len() == 3); + + map.remove(1); + assert(map.len() == 2); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L240-L255 + + +### capacity + +```rust title="capacity" showLineNumbers +pub fn capacity(_self: Self) -> u64 { +``` +> Source code: noir_stdlib/src/collections/map.nr#L271-L273 + + +Returns the maximum capacity of this hashmap. This is always equal to the capacity +specified in the hashmap's type. + +Unlike hashmaps in general purpose programming languages, hashmaps in Noir have a +static capacity that does not increase as the map grows larger. Thus, this capacity +is also the maximum possible element count that can be inserted into the hashmap. +Due to hash collisions (modulo the hashmap length), it is likely the actual maximum +element count will be lower than the full capacity. + +Example: + +```rust title="capacity_example" showLineNumbers +let empty_map: HashMap> = HashMap::default(); + assert(empty_map.len() == 0); + assert(empty_map.capacity() == 42); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L257-L261 + + +### clear + +```rust title="clear" showLineNumbers +pub fn clear(&mut self) { +``` +> Source code: noir_stdlib/src/collections/map.nr#L93-L95 + + +Clears the hashmap, removing all key-value pairs from it. + +Example: + +```rust title="clear_example" showLineNumbers +assert(!map.is_empty()); + map.clear(); + assert(map.is_empty()); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L263-L267 + + +### contains_key + +```rust title="contains_key" showLineNumbers +pub fn contains_key( + self, + key: K + ) -> bool + where + K: Hash + Eq, + B: BuildHasher, + H: Hasher { +``` +> Source code: noir_stdlib/src/collections/map.nr#L101-L110 + + +True if the hashmap contains the given key. Unlike `get`, this will not also return +the value associated with the key. + +Example: + +```rust title="contains_key_example" showLineNumbers +if map.contains_key(7) { + let value = map.get(7); + assert(value.is_some()); + } else { + println("No value for key 7!"); + } +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L269-L276 + + +### entries + +```rust title="entries" showLineNumbers +pub fn entries(self) -> BoundedVec<(K, V), N> { +``` +> Source code: noir_stdlib/src/collections/map.nr#L123-L125 + + +Returns a vector of each key-value pair present in the hashmap. + +The length of the returned vector is always equal to the length of the hashmap. + +Example: + +```rust title="entries_example" showLineNumbers +let entries = map.entries(); + + // The length of a hashmap may not be compile-time known, so we + // need to loop over its capacity instead + for i in 0..map.capacity() { + if i < entries.len() { + let (key, value) = entries.get(i); + println(f"{key} -> {value}"); + } + } +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L310-L321 + + +### keys + +```rust title="keys" showLineNumbers +pub fn keys(self) -> BoundedVec { +``` +> Source code: noir_stdlib/src/collections/map.nr#L144-L146 + + +Returns a vector of each key present in the hashmap. + +The length of the returned vector is always equal to the length of the hashmap. + +Example: + +```rust title="keys_example" showLineNumbers +let keys = map.keys(); + + for i in 0..keys.max_len() { + if i < keys.len() { + let key = keys.get_unchecked(i); + let value = map.get(key).unwrap_unchecked(); + println(f"{key} -> {value}"); + } + } +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L323-L333 + + +### values + +```rust title="values" showLineNumbers +pub fn values(self) -> BoundedVec { +``` +> Source code: noir_stdlib/src/collections/map.nr#L164-L166 + + +Returns a vector of each value present in the hashmap. + +The length of the returned vector is always equal to the length of the hashmap. + +Example: + +```rust title="values_example" showLineNumbers +let values = map.values(); + + for i in 0..values.max_len() { + if i < values.len() { + let value = values.get_unchecked(i); + println(f"Found value {value}"); + } + } +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L335-L344 + + +### iter_mut + +```rust title="iter_mut" showLineNumbers +pub fn iter_mut( + &mut self, + f: fn(K, V) -> (K, V) + ) + where + K: Eq + Hash, + B: BuildHasher, + H: Hasher { +``` +> Source code: noir_stdlib/src/collections/map.nr#L183-L192 + + +Iterates through each key-value pair of the HashMap, setting each key-value pair to the +result returned from the given function. + +Note that since keys can be mutated, the HashMap needs to be rebuilt as it is iterated +through. If this is not desired, use `iter_values_mut` if only values need to be mutated, +or `entries` if neither keys nor values need to be mutated. + +The iteration order is left unspecified. As a result, if two keys are mutated to become +equal, which of the two values that will be present for the key in the resulting map is also unspecified. + +Example: + +```rust title="iter_mut_example" showLineNumbers +// Add 1 to each key in the map, and double the value associated with that key. + map.iter_mut(|k, v| (k + 1, v * 2)); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L348-L351 + + +### iter_keys_mut + +```rust title="iter_keys_mut" showLineNumbers +pub fn iter_keys_mut( + &mut self, + f: fn(K) -> K + ) + where + K: Eq + Hash, + B: BuildHasher, + H: Hasher { +``` +> Source code: noir_stdlib/src/collections/map.nr#L208-L217 + + +Iterates through the HashMap, mutating each key to the result returned from +the given function. + +Note that since keys can be mutated, the HashMap needs to be rebuilt as it is iterated +through. If only iteration is desired and the keys are not intended to be mutated, +prefer using `entries` instead. + +The iteration order is left unspecified. As a result, if two keys are mutated to become +equal, which of the two values that will be present for the key in the resulting map is also unspecified. + +Example: + +```rust title="iter_keys_mut_example" showLineNumbers +// Double each key, leaving the value associated with that key untouched + map.iter_keys_mut(|k| k * 2); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L353-L356 + + +### iter_values_mut + +```rust title="iter_values_mut" showLineNumbers +pub fn iter_values_mut(&mut self, f: fn(V) -> V) { +``` +> Source code: noir_stdlib/src/collections/map.nr#L233-L235 + + +Iterates through the HashMap, applying the given function to each value and mutating the +value to equal the result. This function is more efficient than `iter_mut` and `iter_keys_mut` +because the keys are untouched and the underlying hashmap thus does not need to be reordered. + +Example: + +```rust title="iter_values_mut_example" showLineNumbers +// Halve each value + map.iter_values_mut(|v| v / 2); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L358-L361 + + +### retain + +```rust title="retain" showLineNumbers +pub fn retain(&mut self, f: fn(K, V) -> bool) { +``` +> Source code: noir_stdlib/src/collections/map.nr#L247-L249 + + +Retains only the key-value pairs for which the given function returns true. +Any key-value pairs for which the function returns false will be removed from the map. + +Example: + +```rust title="retain_example" showLineNumbers +map.retain(|k, v| (k != 0) & (v != 0)); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L281-L283 + + +## Trait Implementations + +### default + +```rust title="default" showLineNumbers +impl Default for HashMap +where + B: BuildHasher + Default, + H: Hasher + Default +{ + fn default() -> Self { +``` +> Source code: noir_stdlib/src/collections/map.nr#L462-L469 + + +Constructs an empty HashMap. + +Example: + +```rust title="default_example" showLineNumbers +let hashmap: HashMap> = HashMap::default(); + assert(hashmap.is_empty()); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L202-L205 + + +### eq + +```rust title="eq" showLineNumbers +impl Eq for HashMap +where + K: Eq + Hash, + V: Eq, + B: BuildHasher, + H: Hasher +{ + fn eq(self, other: HashMap) -> bool { +``` +> Source code: noir_stdlib/src/collections/map.nr#L426-L435 + + +Checks if two HashMaps are equal. + +Example: + +```rust title="eq_example" showLineNumbers +let mut map1: HashMap> = HashMap::default(); + let mut map2: HashMap> = HashMap::default(); + + map1.insert(1, 2); + map1.insert(3, 4); + + map2.insert(3, 4); + map2.insert(1, 2); + + assert(map1 == map2); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L285-L296 + diff --git a/docs/versioned_docs/version-v0.27.0/noir/standard_library/containers/index.md b/docs/versioned_docs/version-v0.27.0/noir/standard_library/containers/index.md new file mode 100644 index 00000000000..ea84c6d5c21 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/noir/standard_library/containers/index.md @@ -0,0 +1,5 @@ +--- +title: Containers +description: Container types provided by Noir's standard library for storing and retrieving data +keywords: [containers, data types, vec, hashmap] +--- diff --git a/docs/versioned_docs/version-v0.27.0/noir/standard_library/containers/vec.mdx b/docs/versioned_docs/version-v0.27.0/noir/standard_library/containers/vec.mdx new file mode 100644 index 00000000000..fcfd7e07aa0 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/noir/standard_library/containers/vec.mdx @@ -0,0 +1,151 @@ +--- +title: Vectors +description: Delve into the Vec data type in Noir. Learn about its methods, practical examples, and best practices for using Vectors in your Noir code. +keywords: [noir, vector type, methods, examples, dynamic arrays] +sidebar_position: 6 +--- + +import Experimental from '@site/src/components/Notes/_experimental.mdx'; + + + +A vector is a collection type similar to Rust's `Vec` type. In Noir, it is a convenient way to use slices as mutable arrays. + +Example: + +```rust +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 +``` + +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 +``` + +Example: + +```rust +let slice: [Field] = &[1, 2, 3]; +let vector_from_slice = Vec::from_slice(slice); +assert(vector_from_slice.len() == 3); +``` + +### len + +Returns the number of elements in the vector. + +```rust +pub fn len(self) -> Field +``` + +Example: + +```rust +let empty_vector: Vec = Vec::new(); +assert(empty_vector.len() == 0); +``` + +### 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 +``` + +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) +``` + +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 +``` + +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) +``` + +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 +``` + +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); +``` diff --git a/docs/versioned_docs/version-v0.27.0/noir/standard_library/cryptographic_primitives/_category_.json b/docs/versioned_docs/version-v0.27.0/noir/standard_library/cryptographic_primitives/_category_.json new file mode 100644 index 00000000000..5d694210bbf --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/noir/standard_library/cryptographic_primitives/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 0, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.27.0/noir/standard_library/cryptographic_primitives/ec_primitives.md b/docs/versioned_docs/version-v0.27.0/noir/standard_library/cryptographic_primitives/ec_primitives.md new file mode 100644 index 00000000000..d2b42d67b7c --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/noir/standard_library/cryptographic_primitives/ec_primitives.md @@ -0,0 +1,102 @@ +--- +title: Elliptic Curve Primitives +keywords: [cryptographic primitives, Noir project] +sidebar_position: 4 +--- + +Data structures and methods on them that allow you to carry out computations involving elliptic +curves over the (mathematical) field corresponding to `Field`. For the field currently at our +disposal, applications would involve a curve embedded in BN254, e.g. the +[Baby Jubjub curve](https://eips.ethereum.org/EIPS/eip-2494). + +## Data structures + +### Elliptic curve configurations + +(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Curve`), i.e. the specific elliptic +curve you want to use, which would be specified using any one of the methods +`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::new` which take the coefficients in the +defining equation together with a generator point as parameters. You can find more detail in the +comments in +[`noir_stdlib/src/ec.nr`](https://github.com/noir-lang/noir/blob/master/noir_stdlib/src/ec.nr), but +the gist of it is that the elliptic curves of interest are usually expressed in one of the standard +forms implemented here (Twisted Edwards, Montgomery and Short Weierstraß), and in addition to that, +you could choose to use `affine` coordinates (Cartesian coordinates - the usual (x,y) - possibly +together with a point at infinity) or `curvegroup` coordinates (some form of projective coordinates +requiring more coordinates but allowing for more efficient implementations of elliptic curve +operations). Conversions between all of these forms are provided, and under the hood these +conversions are done whenever an operation is more efficient in a different representation (or a +mixed coordinate representation is employed). + +### Points + +(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Point`), i.e. points lying on the +elliptic curve. For a curve configuration `c` and a point `p`, it may be checked that `p` +does indeed lie on `c` by calling `c.contains(p1)`. + +## Methods + +(given a choice of curve representation, e.g. use `std::ec::tecurve::affine::Curve` and use +`std::ec::tecurve::affine::Point`) + +- The **zero element** is given by `Point::zero()`, and we can verify whether a point `p: Point` is + zero by calling `p.is_zero()`. +- **Equality**: Points `p1: Point` and `p2: Point` may be checked for equality by calling + `p1.eq(p2)`. +- **Addition**: For `c: Curve` and points `p1: Point` and `p2: Point` on the curve, adding these two + points is accomplished by calling `c.add(p1,p2)`. +- **Negation**: For a point `p: Point`, `p.negate()` is its negation. +- **Subtraction**: For `c` and `p1`, `p2` as above, subtracting `p2` from `p1` is accomplished by + calling `c.subtract(p1,p2)`. +- **Scalar multiplication**: For `c` as above, `p: Point` a point on the curve and `n: Field`, + scalar multiplication is given by `c.mul(n,p)`. If instead `n :: [u1; N]`, i.e. `n` is a bit + array, the `bit_mul` method may be used instead: `c.bit_mul(n,p)` +- **Multi-scalar multiplication**: For `c` as above and arrays `n: [Field; N]` and `p: [Point; N]`, + multi-scalar multiplication is given by `c.msm(n,p)`. +- **Coordinate representation conversions**: The `into_group` method converts a point or curve + configuration in the affine representation to one in the CurveGroup representation, and + `into_affine` goes in the other direction. +- **Curve representation conversions**: `tecurve` and `montcurve` curves and points are equivalent + and may be converted between one another by calling `into_montcurve` or `into_tecurve` on their + configurations or points. `swcurve` is more general and a curve c of one of the other two types + may be converted to this representation by calling `c.into_swcurve()`, whereas a point `p` lying + on the curve given by `c` may be mapped to its corresponding `swcurve` point by calling + `c.map_into_swcurve(p)`. +- **Map-to-curve methods**: The Elligator 2 method of mapping a field element `n: Field` into a + `tecurve` or `montcurve` with configuration `c` may be called as `c.elligator2_map(n)`. For all of + the curve configurations, the SWU map-to-curve method may be called as `c.swu_map(z,n)`, where + `z: Field` depends on `Field` and `c` and must be chosen by the user (the conditions it needs to + satisfy are specified in the comments + [here](https://github.com/noir-lang/noir/blob/master/noir_stdlib/src/ec.nr)). + +## Examples + +The +[ec_baby_jubjub test](https://github.com/noir-lang/noir/blob/master/test_programs/compile_success_empty/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.27.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx b/docs/versioned_docs/version-v0.27.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx new file mode 100644 index 00000000000..4394b48f907 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx @@ -0,0 +1,98 @@ +--- +title: ECDSA Signature Verification +description: Learn about the cryptographic primitives regarding ECDSA over the secp256k1 and secp256r1 curves +keywords: [cryptographic primitives, Noir project, ecdsa, secp256k1, secp256r1, signatures] +sidebar_position: 3 +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +Noir supports ECDSA signatures verification over the secp256k1 and secp256r1 curves. + +## ecdsa_secp256k1::verify_signature + +Verifier for ECDSA Secp256k1 signatures. +See ecdsa_secp256k1::verify_signature_slice for a version that accepts slices directly. + +```rust title="ecdsa_secp256k1" showLineNumbers +pub fn verify_signature( + public_key_x: [u8; 32], + public_key_y: [u8; 32], + signature: [u8; 64], + message_hash: [u8; N] +) -> bool +``` +> Source code: noir_stdlib/src/ecdsa_secp256k1.nr#L2-L9 + + +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_secp256k1::verify_signature_slice + +Verifier for ECDSA Secp256k1 signatures where the message is a slice. + +```rust title="ecdsa_secp256k1_slice" showLineNumbers +pub fn verify_signature_slice( + public_key_x: [u8; 32], + public_key_y: [u8; 32], + signature: [u8; 64], + message_hash: [u8] +) -> bool +``` +> Source code: noir_stdlib/src/ecdsa_secp256k1.nr#L13-L20 + + + + +## ecdsa_secp256r1::verify_signature + +Verifier for ECDSA Secp256r1 signatures. +See ecdsa_secp256r1::verify_signature_slice for a version that accepts slices directly. + +```rust title="ecdsa_secp256r1" showLineNumbers +pub fn verify_signature( + public_key_x: [u8; 32], + public_key_y: [u8; 32], + signature: [u8; 64], + message_hash: [u8; N] +) -> bool +``` +> Source code: noir_stdlib/src/ecdsa_secp256r1.nr#L2-L9 + + +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); +} +``` + + + +## ecdsa_secp256r1::verify_signature + +Verifier for ECDSA Secp256r1 signatures where the message is a slice. + +```rust title="ecdsa_secp256r1_slice" showLineNumbers +pub fn verify_signature_slice( + public_key_x: [u8; 32], + public_key_y: [u8; 32], + signature: [u8; 64], + message_hash: [u8] +) -> bool +``` +> Source code: noir_stdlib/src/ecdsa_secp256r1.nr#L13-L20 + + + diff --git a/docs/versioned_docs/version-v0.27.0/noir/standard_library/cryptographic_primitives/eddsa.mdx b/docs/versioned_docs/version-v0.27.0/noir/standard_library/cryptographic_primitives/eddsa.mdx new file mode 100644 index 00000000000..c2c0624dfad --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/noir/standard_library/cryptographic_primitives/eddsa.mdx @@ -0,0 +1,37 @@ +--- +title: EdDSA Verification +description: Learn about the cryptographic primitives regarding EdDSA +keywords: [cryptographic primitives, Noir project, eddsa, signatures] +sidebar_position: 5 +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +## eddsa::eddsa_poseidon_verify + +Verifier for EdDSA signatures + +```rust +fn eddsa_poseidon_verify(public_key_x : Field, public_key_y : Field, signature_s: Field, signature_r8_x: Field, signature_r8_y: Field, message: Field) -> bool +``` + +It is also possible to specify the hash algorithm used for the signature by using the `eddsa_verify_with_hasher` function with a parameter implementing the Hasher trait. For instance, if you want to use Poseidon2 instead, you can do the following: +```rust +use dep::std::hash::poseidon2::Poseidon2Hasher; + +let mut hasher = Poseidon2Hasher::default(); +eddsa_verify_with_hasher(pub_key_a.x, pub_key_a.y, s_a, r8_a.x, r8_a.y, msg, &mut hasher); +``` + + + +## eddsa::eddsa_to_pub + +Private to public key conversion. + +Returns `(pub_key_x, pub_key_y)` + +```rust +fn eddsa_to_pub(secret : Field) -> (Field, Field) +``` + diff --git a/docs/versioned_docs/version-v0.27.0/noir/standard_library/cryptographic_primitives/hashes.mdx b/docs/versioned_docs/version-v0.27.0/noir/standard_library/cryptographic_primitives/hashes.mdx new file mode 100644 index 00000000000..695c7d9406f --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/noir/standard_library/cryptographic_primitives/hashes.mdx @@ -0,0 +1,331 @@ +--- +title: Hash methods +description: + Learn about the cryptographic primitives ready to use for any Noir project, including sha256, + blake2s, pedersen, mimc_bn254 and mimc +keywords: + [cryptographic primitives, Noir project, sha256, blake2s, pedersen, mimc_bn254, mimc, hash] +sidebar_position: 0 +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +## sha256 + +Given an array of bytes, returns the resulting sha256 hash. +See sha256_slice for a version that works directly on slices. + +```rust title="sha256" showLineNumbers +pub fn sha256(input: [u8; N]) -> [u8; 32] +``` +> Source code: noir_stdlib/src/hash.nr#L10-L12 + + +example: + +```rust +fn main() { + let x = [163, 117, 178, 149]; // some random bytes + let hash = std::hash::sha256(x); +} +``` + + + +## sha256_slice + +A version of sha256 specialized to slices: + +```rust title="sha256_slice" showLineNumbers +pub fn sha256_slice(input: [u8]) -> [u8; 32] +``` +> Source code: noir_stdlib/src/hash.nr#L16-L18 + + + + +## blake2s + +Given an array of bytes, returns an array with the Blake2 hash +See blake2s_slice for a version that works directly on slices. + +```rust title="blake2s" showLineNumbers +pub fn blake2s(input: [u8; N]) -> [u8; 32] +``` +> Source code: noir_stdlib/src/hash.nr#L22-L24 + + +example: + +```rust +fn main() { + let x = [163, 117, 178, 149]; // some random bytes + let hash = std::hash::blake2s(x); +} +``` + + + +## blake2s_slice + +A version of blake2s specialized to slices: + +```rust title="blake2s_slice" showLineNumbers +pub fn blake2s_slice(input: [u8]) -> [u8; 32] +``` +> Source code: noir_stdlib/src/hash.nr#L28-L30 + + + + +## blake3 + +Given an array of bytes, returns an array with the Blake3 hash +See blake3_slice for a version that works directly on slices. + +```rust title="blake3" showLineNumbers +pub fn blake3(input: [u8; N]) -> [u8; 32] +``` +> Source code: noir_stdlib/src/hash.nr#L34-L36 + + +example: + +```rust +fn main() { + let x = [163, 117, 178, 149]; // some random bytes + let hash = std::hash::blake3(x); +} +``` + + + +## blake3_slice + +A version of blake3 specialized to slices: + +```rust title="blake3_slice" showLineNumbers +pub fn blake3_slice(input: [u8]) -> [u8; 32] +``` +> Source code: noir_stdlib/src/hash.nr#L40-L42 + + + + +## pedersen_hash + +Given an array of Fields, returns the Pedersen hash. +See pedersen_hash_slice for a version that works directly on slices. + +```rust title="pedersen_hash" showLineNumbers +pub fn pedersen_hash(input: [Field; N]) -> Field +``` +> Source code: noir_stdlib/src/hash.nr#L78-L80 + + +example: + +```rust title="pedersen-hash" showLineNumbers +use dep::std; + +fn main(x: Field, y: Field, expected_hash: Field) { + let hash = std::hash::pedersen_hash([x, y]); + assert_eq(hash, expected_hash); +} +``` +> Source code: test_programs/execution_success/pedersen_hash/src/main.nr#L1-L8 + + + + +## pedersen_hash_slice + +Given a slice of Fields, returns the Pedersen hash. + +```rust title="pedersen_hash_slice" showLineNumbers +pub fn pedersen_hash_slice(input: [Field]) -> Field +``` +> Source code: noir_stdlib/src/hash.nr#L85-L87 + + + + +## pedersen_commitment + +Given an array of Fields, returns the Pedersen commitment. +See pedersen_commitment_slice for a version that works directly on slices. + +```rust title="pedersen_commitment" showLineNumbers +struct PedersenPoint { + x : Field, + y : Field, +} + +pub fn pedersen_commitment(input: [Field; N]) -> PedersenPoint { +``` +> Source code: noir_stdlib/src/hash.nr#L45-L52 + + +example: + +```rust title="pedersen-commitment" showLineNumbers +use dep::std; + +fn main(x: Field, y: Field, expected_commitment: std::hash::PedersenPoint) { + let commitment = std::hash::pedersen_commitment([x, y]); + assert_eq(commitment.x, expected_commitment.x); + assert_eq(commitment.y, expected_commitment.y); +} +``` +> Source code: test_programs/execution_success/pedersen_commitment/src/main.nr#L1-L9 + + + + +## pedersen_commitment_slice + +Given a slice of Fields, returns the Pedersen commitment. + +```rust title="pedersen_commitment_slice" showLineNumbers +pub fn pedersen_commitment_slice(input: [Field]) -> PedersenPoint { + pedersen_commitment_with_separator_slice(input, 0) +} +``` +> Source code: noir_stdlib/src/hash.nr#L56-L60 + + + + +## 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. See keccak256_slice for a version that works +directly on slices. + +```rust title="keccak256" showLineNumbers +pub fn keccak256(input: [u8; N], message_size: u32) -> [u8; 32] +``` +> Source code: noir_stdlib/src/hash.nr#L113-L115 + + +example: + +```rust title="keccak256" showLineNumbers +use dep::std; + +fn main(x: Field, result: [u8; 32]) { + // We use the `as` keyword here to denote the fact that we want to take just the first byte from the x Field + // The padding is taken care of by the program + let digest = std::hash::keccak256([x as u8], 1); + assert(digest == result); + + //#1399: variable message 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); + + 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); + + assert(hash_a != hash_c); +} +``` +> Source code: test_programs/execution_success/keccak256/src/main.nr#L1-L22 + + + + +## keccak256_slice + +Given a slice of bytes (`u8`), returns the resulting keccak hash as an array of +32 bytes (`[u8; 32]`). + +```rust title="keccak256_slice" showLineNumbers +pub fn keccak256_slice(input: [u8], message_size: u32) -> [u8; 32] +``` +> Source code: noir_stdlib/src/hash.nr#L119-L121 + + + + +## 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 title="poseidon" showLineNumbers +use dep::std::hash::poseidon; +use dep::std::hash::poseidon2; + +fn main(x1: [Field; 2], y1: pub Field, x2: [Field; 4], y2: pub Field, x3: [Field; 4], y3: Field) { + let hash1 = poseidon::bn254::hash_2(x1); + assert(hash1 == y1); + + let hash2 = poseidon::bn254::hash_4(x2); + assert(hash2 == y2); + + let hash3 = poseidon2::Poseidon2::hash(x3, x3.len()); + assert(hash3 == y3); +} +``` +> Source code: test_programs/execution_success/poseidon_bn254_hash/src/main.nr#L1-L15 + + +## poseidon 2 + +Given an array of Fields, returns a new Field with the Poseidon2 Hash. Contrary to the Poseidon +function, there is only one hash and you can specify a message_size to hash only the first +`message_size` bytes of the input, + +```rust +// example for hashing the first three elements of the input +Poseidon2::hash(input, 3); +``` + +The above example for Poseidon also includes Poseidon2. + +## 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]) -> 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.27.0/noir/standard_library/cryptographic_primitives/index.md b/docs/versioned_docs/version-v0.27.0/noir/standard_library/cryptographic_primitives/index.md new file mode 100644 index 00000000000..650f30165d5 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/noir/standard_library/cryptographic_primitives/index.md @@ -0,0 +1,14 @@ +--- +title: Cryptographic Primitives +description: + Learn about the cryptographic primitives ready to use for any Noir project +keywords: + [ + cryptographic primitives, + Noir project, + ] +--- + +The Noir team is progressively adding new cryptographic primitives to the standard library. Reach out for news or if you would be interested in adding more of these calculations in Noir. + +Some methods are available thanks to the Aztec backend, not being performed using Noir. When using other backends, these methods may or may not be supplied. diff --git a/docs/versioned_docs/version-v0.27.0/noir/standard_library/cryptographic_primitives/scalar.mdx b/docs/versioned_docs/version-v0.27.0/noir/standard_library/cryptographic_primitives/scalar.mdx new file mode 100644 index 00000000000..df411ca5443 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/noir/standard_library/cryptographic_primitives/scalar.mdx @@ -0,0 +1,33 @@ +--- +title: Scalar multiplication +description: See how you can perform scalar multiplications over a fixed base in Noir +keywords: [cryptographic primitives, Noir project, scalar multiplication] +sidebar_position: 1 +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +## scalar_mul::fixed_base_embedded_curve + +Performs scalar multiplication over the embedded curve whose coordinates are defined by the +configured noir field. For the BN254 scalar field, this is BabyJubJub or Grumpkin. + +```rust title="fixed_base_embedded_curve" showLineNumbers +pub fn fixed_base_embedded_curve( + low: Field, + high: Field +) -> [Field; 2] +``` +> Source code: noir_stdlib/src/scalar_mul.nr#L27-L32 + + +example + +```rust +fn main(x : Field) { + let scal = std::scalar_mul::fixed_base_embedded_curve(x); + println(scal); +} +``` + + diff --git a/docs/versioned_docs/version-v0.27.0/noir/standard_library/cryptographic_primitives/schnorr.mdx b/docs/versioned_docs/version-v0.27.0/noir/standard_library/cryptographic_primitives/schnorr.mdx new file mode 100644 index 00000000000..b59e69c8f07 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/noir/standard_library/cryptographic_primitives/schnorr.mdx @@ -0,0 +1,64 @@ +--- +title: Schnorr Signatures +description: Learn how you can verify Schnorr signatures using Noir +keywords: [cryptographic primitives, Noir project, schnorr, signatures] +sidebar_position: 2 +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +## schnorr::verify_signature + +Verifier for Schnorr signatures over the embedded curve (for BN254 it is Grumpkin). +See schnorr::verify_signature_slice for a version that works directly on slices. + +```rust title="schnorr_verify" showLineNumbers +pub fn verify_signature( + public_key_x: Field, + public_key_y: Field, + signature: [u8; 64], + message: [u8; N] +) -> bool +``` +> Source code: noir_stdlib/src/schnorr.nr#L2-L9 + + +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() +); + +... +``` + + + +## schnorr::verify_signature_slice + +Verifier for Schnorr signatures over the embedded curve (for BN254 it is Grumpkin) +where the message is a slice. + +```rust title="schnorr_verify_slice" showLineNumbers +pub fn verify_signature_slice( + public_key_x: Field, + public_key_y: Field, + signature: [u8; 64], + message: [u8] +) -> bool +``` +> Source code: noir_stdlib/src/schnorr.nr#L13-L20 + + + diff --git a/docs/versioned_docs/version-v0.27.0/noir/standard_library/logging.md b/docs/versioned_docs/version-v0.27.0/noir/standard_library/logging.md new file mode 100644 index 00000000000..db75ef9f86f --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/noir/standard_library/logging.md @@ -0,0 +1,78 @@ +--- +title: Logging +description: + Learn how to use the println statement for debugging in Noir with this tutorial. Understand the + basics of logging in Noir and how to implement it in your code. +keywords: + [ + noir logging, + println statement, + print statement, + debugging in noir, + noir std library, + logging tutorial, + basic logging in noir, + noir logging implementation, + noir debugging techniques, + rust, + ] +--- + +The standard library provides two familiar statements you can use: `println` and `print`. Despite being a limited implementation of rust's `println!` and `print!` macros, these constructs can be useful for debugging. + +You can print the output of both statements in your Noir code by using the `nargo execute` command or the `--show-output` flag when using `nargo test` (provided there are print statements in your tests). + +It is recommended to use `nargo execute` if you want to debug failing constraints with `println` or `print` statements. This is due to every input in a test being a constant rather than a witness, so we issue an error during compilation while we only print during execution (which comes after compilation). Neither `println`, nor `print` are callable for failed constraints caught at compile time. + +Both `print` and `println` are generic functions which can work on integers, fields, strings, and even structs or expressions. Note however, that slices are currently unsupported. For example: + +```rust +struct Person { + age: Field, + height: Field, +} + +fn main(age: Field, height: Field) { + let person = Person { + age: age, + height: height, + }; + println(person); + println(age + height); + println("Hello world!"); +} +``` + +You can print different types in the same statement (including strings) with a type called `fmtstr`. It can be specified in the same way as a normal string, just prepended with an "f" character: + +```rust + let fmt_str = f"i: {i}, j: {j}"; + println(fmt_str); + + let s = myStruct { y: x, x: y }; + println(s); + + println(f"i: {i}, s: {s}"); + + println(x); + println([x, y]); + + let foo = fooStruct { my_struct: s, foo: 15 }; + println(f"s: {s}, foo: {foo}"); + + println(15); // prints 0x0f, implicit Field + println(-1 as u8); // prints 255 + println(-1 as i8); // prints -1 +``` + +Examples shown above are interchangeable between the two `print` statements: + +```rust +let person = Person { age : age, height : height }; + +println(person); +print(person); + +println("Hello world!"); // Prints with a newline at the end of the input +print("Hello world!"); // Prints the input and keeps cursor on the same line +``` diff --git a/docs/versioned_docs/version-v0.27.0/noir/standard_library/merkle_trees.md b/docs/versioned_docs/version-v0.27.0/noir/standard_library/merkle_trees.md new file mode 100644 index 00000000000..6a9ebf72ada --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/noir/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/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.as_slice()); + 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.27.0/noir/standard_library/options.md b/docs/versioned_docs/version-v0.27.0/noir/standard_library/options.md new file mode 100644 index 00000000000..a1bd4e1de5f --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/noir/standard_library/options.md @@ -0,0 +1,101 @@ +--- +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), +} +``` + +The `Option` type, already imported into your Noir program, can be used directly: + +```rust +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. + +### expect + +Asserts `self.is_some()` with a provided custom message and returns the contained `Some` value. The custom message is expected to be a format string. + +### 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.27.0/noir/standard_library/recursion.md b/docs/versioned_docs/version-v0.27.0/noir/standard_library/recursion.md new file mode 100644 index 00000000000..a93894043dc --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/noir/standard_library/recursion.md @@ -0,0 +1,88 @@ +--- +title: Recursive Proofs +description: Learn about how to write recursive proofs in Noir. +keywords: [recursion, recursive proofs, verification_key, 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. + +Read [the explainer on recursion](../../explainers/explainer-recursion.md) to know more about this function and the [guide on how to use it.](../../how_to/how-to-recursion.md) + +## The `#[recursive]` Attribute + +In Noir, the `#[recursive]` attribute is used to indicate that a circuit is designed for recursive proof generation. When applied, it informs the compiler and the tooling that the circuit should be compiled in a way that makes its proofs suitable for recursive verification. This attribute eliminates the need for manual flagging of recursion at the tooling level, streamlining the proof generation process for recursive circuits. + +### Example usage with `#[recursive]` + +```rust +#[recursive] +fn main(x: Field, y: pub Field) { + assert(x == y, "x and y are not equal"); +} + +// This marks the circuit as recursion-friendly and indicates that proofs generated from this circuit +// are intended for recursive verification. +``` + +By incorporating this attribute directly in the circuit's definition, tooling like Nargo and NoirJS can automatically execute recursive-specific duties for Noir programs (e.g. recursive-friendly proof artifact generation) without additional flags or configurations. + +## Verifying Recursive Proofs + +```rust +#[foreign(recursive_aggregation)] +pub fn verify_proof(verification_key: [Field], proof: [Field], public_inputs: [Field], key_hash: Field) {} +``` + +:::info + +This is a black box function. Read [this section](./black_box_fns) to learn more about black box functions in Noir. + +::: + +## Example usage + +```rust +use dep::std; + +fn main( + verification_key : [Field; 114], + proof : [Field; 93], + public_inputs : [Field; 1], + key_hash : Field, + proof_b : [Field; 93], +) { + std::verify_proof( + verification_key.as_slice(), + proof.as_slice(), + public_inputs.as_slice(), + key_hash + ); + + std::verify_proof( + verification_key.as_slice(), + proof_b.as_slice(), + public_inputs.as_slice(), + key_hash + ); +} +``` + +You can see a full example of recursive proofs in [this example recursion demo repo](https://github.com/noir-lang/noir-examples/tree/master/recursion). + +## 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. + +### `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. diff --git a/docs/versioned_docs/version-v0.27.0/noir/standard_library/traits.md b/docs/versioned_docs/version-v0.27.0/noir/standard_library/traits.md new file mode 100644 index 00000000000..68a9dc3d54b --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/noir/standard_library/traits.md @@ -0,0 +1,408 @@ +--- +title: Traits +description: Noir's stdlib provides a few commonly used traits. +keywords: [traits, trait, interface, protocol, default, add, eq] +--- + +## `std::default` + +### `std::default::Default` + +```rust title="default-trait" showLineNumbers +trait Default { + fn default() -> Self; +} +``` +> Source code: noir_stdlib/src/default.nr#L1-L5 + + +Constructs a default value of a type. + +Implementations: +```rust +impl Default for Field { .. } + +impl Default for i8 { .. } +impl Default for i16 { .. } +impl Default for i32 { .. } +impl Default for i64 { .. } + +impl Default for u8 { .. } +impl Default for u16 { .. } +impl Default for u32 { .. } +impl Default for u64 { .. } + +impl Default for () { .. } +impl Default for bool { .. } + +impl Default for [T; N] + where T: Default { .. } + +impl Default for [T] { .. } + +impl Default for (A, B) + where A: Default, B: Default { .. } + +impl Default for (A, B, C) + where A: Default, B: Default, C: Default { .. } + +impl Default for (A, B, C, D) + where A: Default, B: Default, C: Default, D: Default { .. } + +impl Default for (A, B, C, D, E) + where A: Default, B: Default, C: Default, D: Default, E: Default { .. } +``` + +For primitive integer types, the return value of `default` is `0`. Container +types such as arrays are filled with default values of their element type, +except slices whose length is unknown and thus defaulted to zero. + + +## `std::convert` + +### `std::convert::From` + +```rust title="from-trait" showLineNumbers +trait From { + fn from(input: T) -> Self; +} +``` +> Source code: noir_stdlib/src/convert.nr#L1-L5 + + +The `From` trait defines how to convert from a given type `T` to the type on which the trait is implemented. + +The Noir standard library provides a number of implementations of `From` between primitive types. +```rust title="from-impls" showLineNumbers +// Unsigned integers + +impl From for u32 { fn from(value: u8) -> u32 { value as u32 } } + +impl From for u64 { fn from(value: u8) -> u64 { value as u64 } } +impl From for u64 { fn from(value: u32) -> u64 { value as u64 } } + +impl From for Field { fn from(value: u8) -> Field { value as Field } } +impl From for Field { fn from(value: u32) -> Field { value as Field } } +impl From for Field { fn from(value: u64) -> Field { value as Field } } + +// Signed integers + +impl From for i32 { fn from(value: i8) -> i32 { value as i32 } } + +impl From for i64 { fn from(value: i8) -> i64 { value as i64 } } +impl From for i64 { fn from(value: i32) -> i64 { value as i64 } } + +// Booleans +impl From for u8 { fn from(value: bool) -> u8 { value as u8 } } +impl From for u32 { fn from(value: bool) -> u32 { value as u32 } } +impl From for u64 { fn from(value: bool) -> u64 { value as u64 } } +impl From for i8 { fn from(value: bool) -> i8 { value as i8 } } +impl From for i32 { fn from(value: bool) -> i32 { value as i32 } } +impl From for i64 { fn from(value: bool) -> i64 { value as i64 } } +impl From for Field { fn from(value: bool) -> Field { value as Field } } +``` +> Source code: noir_stdlib/src/convert.nr#L25-L52 + + +#### When to implement `From` + +As a general rule of thumb, `From` may be implemented in the [situations where it would be suitable in Rust](https://doc.rust-lang.org/std/convert/trait.From.html#when-to-implement-from): + +- The conversion is *infallible*: Noir does not provide an equivalent to Rust's `TryFrom`, if the conversion can fail then provide a named method instead. +- The conversion is *lossless*: semantically, it should not lose or discard information. For example, `u32: From` can losslessly convert any `u16` into a valid `u32` such that the original `u16` can be recovered. On the other hand, `u16: From` should not be implemented as `2**16` is a `u32` which cannot be losslessly converted into a `u16`. +- The conversion is *value-preserving*: the conceptual kind and meaning of the resulting value is the same, even though the Noir type and technical representation might be different. While it's possible to infallibly and losslessly convert a `u8` into a `str<2>` hex representation, `4u8` and `"04"` are too different for `str<2>: From` to be implemented. +- The conversion is *obvious*: it's the only reasonable conversion between the two types. If there's ambiguity on how to convert between them such that the same input could potentially map to two different values then a named method should be used. For instance rather than implementing `U128: From<[u8; 16]>`, the methods `U128::from_le_bytes` and `U128::from_be_bytes` are used as otherwise the endianness of the array would be ambiguous, resulting in two potential values of `U128` from the same byte array. + +One additional recommendation specific to Noir is: +- The conversion is *efficient*: it's relatively cheap to convert between the two types. Due to being a ZK DSL, it's more important to avoid unnecessary computation compared to Rust. If the implementation of `From` would encourage users to perform unnecessary conversion, resulting in additional proving time, then it may be preferable to expose functionality such that this conversion may be avoided. + +### `std::convert::Into` + +The `Into` trait is defined as the reciprocal of `From`. It should be easy to convince yourself that if we can convert to type `A` from type `B`, then it's possible to convert type `B` into type `A`. + +For this reason, implementing `From` on a type will automatically generate a matching `Into` implementation. One should always prefer implementing `From` over `Into` as implementing `Into` will not generate a matching `From` implementation. + +```rust title="into-trait" showLineNumbers +trait Into { + fn into(input: Self) -> T; +} + +impl Into for U where T: From { + fn into(input: U) -> T { + T::from(input) + } +} +``` +> Source code: noir_stdlib/src/convert.nr#L13-L23 + + +`Into` is most useful when passing function arguments where the types don't quite match up with what the function expects. In this case, the compiler has enough type information to perform the necessary conversion by just appending `.into()` onto the arguments in question. + + +## `std::cmp` + +### `std::cmp::Eq` + +```rust title="eq-trait" showLineNumbers +trait Eq { + fn eq(self, other: Self) -> bool; +} +``` +> Source code: noir_stdlib/src/cmp.nr#L1-L5 + + +Returns `true` if `self` is equal to `other`. Implementing this trait on a type +allows the type to be used with `==` and `!=`. + +Implementations: +```rust +impl Eq for Field { .. } + +impl Eq for i8 { .. } +impl Eq for i16 { .. } +impl Eq for i32 { .. } +impl Eq for i64 { .. } + +impl Eq for u8 { .. } +impl Eq for u16 { .. } +impl Eq for u32 { .. } +impl Eq for u64 { .. } + +impl Eq for () { .. } +impl Eq for bool { .. } + +impl Eq for [T; N] + where T: Eq { .. } + +impl Eq for [T] + where T: Eq { .. } + +impl Eq for (A, B) + where A: Eq, B: Eq { .. } + +impl Eq for (A, B, C) + where A: Eq, B: Eq, C: Eq { .. } + +impl Eq for (A, B, C, D) + where A: Eq, B: Eq, C: Eq, D: Eq { .. } + +impl Eq for (A, B, C, D, E) + where A: Eq, B: Eq, C: Eq, D: Eq, E: Eq { .. } +``` + +### `std::cmp::Ord` + +```rust title="ord-trait" showLineNumbers +trait Ord { + fn cmp(self, other: Self) -> Ordering; +} +``` +> Source code: noir_stdlib/src/cmp.nr#L102-L106 + + +`a.cmp(b)` compares two values returning `Ordering::less()` if `a < b`, +`Ordering::equal()` if `a == b`, or `Ordering::greater()` if `a > b`. +Implementing this trait on a type allows `<`, `<=`, `>`, and `>=` to be +used on values of the type. + +Implementations: + +```rust +impl Ord for u8 { .. } +impl Ord for u16 { .. } +impl Ord for u32 { .. } +impl Ord for u64 { .. } + +impl Ord for i8 { .. } +impl Ord for i16 { .. } +impl Ord for i32 { .. } + +impl Ord for i64 { .. } + +impl Ord for () { .. } +impl Ord for bool { .. } + +impl Ord for [T; N] + where T: Ord { .. } + +impl Ord for [T] + where T: Ord { .. } + +impl Ord for (A, B) + where A: Ord, B: Ord { .. } + +impl Ord for (A, B, C) + where A: Ord, B: Ord, C: Ord { .. } + +impl Ord for (A, B, C, D) + where A: Ord, B: Ord, C: Ord, D: Ord { .. } + +impl Ord for (A, B, C, D, E) + where A: Ord, B: Ord, C: Ord, D: Ord, E: Ord { .. } +``` + +## `std::ops` + +### `std::ops::Add`, `std::ops::Sub`, `std::ops::Mul`, and `std::ops::Div` + +These traits abstract over addition, subtraction, multiplication, and division respectively. +Implementing these traits for a given type will also allow that type to be used with the corresponding operator +for that trait (`+` for Add, etc) in addition to the normal method names. + +```rust title="add-trait" showLineNumbers +trait Add { + fn add(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L1-L5 + +```rust title="sub-trait" showLineNumbers +trait Sub { + fn sub(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L17-L21 + +```rust title="mul-trait" showLineNumbers +trait Mul { + fn mul(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L33-L37 + +```rust title="div-trait" showLineNumbers +trait Div { + fn div(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L49-L53 + + +The implementations block below is given for the `Add` trait, but the same types that implement +`Add` also implement `Sub`, `Mul`, and `Div`. + +Implementations: +```rust +impl Add for Field { .. } + +impl Add for i8 { .. } +impl Add for i16 { .. } +impl Add for i32 { .. } +impl Add for i64 { .. } + +impl Add for u8 { .. } +impl Add for u16 { .. } +impl Add for u32 { .. } +impl Add for u64 { .. } +``` + +### `std::ops::Rem` + +```rust title="rem-trait" showLineNumbers +trait Rem{ + fn rem(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L65-L69 + + +`Rem::rem(a, b)` is the remainder function returning the result of what is +left after dividing `a` and `b`. Implementing `Rem` allows the `%` operator +to be used with the implementation type. + +Unlike other numeric traits, `Rem` is not implemented for `Field`. + +Implementations: +```rust +impl Rem for u8 { fn rem(self, other: u8) -> u8 { self % other } } +impl Rem for u16 { fn rem(self, other: u16) -> u16 { self % other } } +impl Rem for u32 { fn rem(self, other: u32) -> u32 { self % other } } +impl Rem for u64 { fn rem(self, other: u64) -> u64 { self % other } } + +impl Rem for i8 { fn rem(self, other: i8) -> i8 { self % other } } +impl Rem for i16 { fn rem(self, other: i16) -> i16 { self % other } } +impl Rem for i32 { fn rem(self, other: i32) -> i32 { self % other } } +impl Rem for i64 { fn rem(self, other: i64) -> i64 { self % other } } +``` + +### `std::ops::{ BitOr, BitAnd, BitXor }` + +```rust title="bitor-trait" showLineNumbers +trait BitOr { + fn bitor(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L79-L83 + +```rust title="bitand-trait" showLineNumbers +trait BitAnd { + fn bitand(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L95-L99 + +```rust title="bitxor-trait" showLineNumbers +trait BitXor { + fn bitxor(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L111-L115 + + +Traits for the bitwise operations `|`, `&`, and `^`. + +Implementing `BitOr`, `BitAnd` or `BitXor` for a type allows the `|`, `&`, or `^` operator respectively +to be used with the type. + +The implementations block below is given for the `BitOr` trait, but the same types that implement +`BitOr` also implement `BitAnd` and `BitXor`. + +Implementations: +```rust +impl BitOr for bool { fn bitor(self, other: bool) -> bool { self | other } } + +impl BitOr for u8 { fn bitor(self, other: u8) -> u8 { self | other } } +impl BitOr for u16 { fn bitor(self, other: u16) -> u16 { self | other } } +impl BitOr for u32 { fn bitor(self, other: u32) -> u32 { self | other } } +impl BitOr for u64 { fn bitor(self, other: u64) -> u64 { self | other } } + +impl BitOr for i8 { fn bitor(self, other: i8) -> i8 { self | other } } +impl BitOr for i16 { fn bitor(self, other: i16) -> i16 { self | other } } +impl BitOr for i32 { fn bitor(self, other: i32) -> i32 { self | other } } +impl BitOr for i64 { fn bitor(self, other: i64) -> i64 { self | other } } +``` + +### `std::ops::{ Shl, Shr }` + +```rust title="shl-trait" showLineNumbers +trait Shl { + fn shl(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L127-L131 + +```rust title="shr-trait" showLineNumbers +trait Shr { + fn shr(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L142-L146 + + +Traits for a bit shift left and bit shift right. + +Implementing `Shl` for a type allows the left shift operator (`<<`) to be used with the implementation type. +Similarly, implementing `Shr` allows the right shift operator (`>>`) to be used with the type. + +Note that bit shifting is not currently implemented for signed types. + +The implementations block below is given for the `Shl` trait, but the same types that implement +`Shl` also implement `Shr`. + +Implementations: +```rust +impl Shl for u8 { fn shl(self, other: u8) -> u8 { self << other } } +impl Shl for u16 { fn shl(self, other: u16) -> u16 { self << other } } +impl Shl for u32 { fn shl(self, other: u32) -> u32 { self << other } } +impl Shl for u64 { fn shl(self, other: u64) -> u64 { self << other } } +``` diff --git a/docs/versioned_docs/version-v0.27.0/noir/standard_library/zeroed.md b/docs/versioned_docs/version-v0.27.0/noir/standard_library/zeroed.md new file mode 100644 index 00000000000..f450fecdd36 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/noir/standard_library/zeroed.md @@ -0,0 +1,26 @@ +--- +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 +- Slice +- String +- Tuple +- Function + +Using it on other types could result in unexpected behavior. diff --git a/docs/versioned_docs/version-v0.27.0/reference/NoirJS/backend_barretenberg/.nojekyll b/docs/versioned_docs/version-v0.27.0/reference/NoirJS/backend_barretenberg/.nojekyll new file mode 100644 index 00000000000..e2ac6616add --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/reference/NoirJS/backend_barretenberg/.nojekyll @@ -0,0 +1 @@ +TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.27.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md b/docs/versioned_docs/version-v0.27.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md new file mode 100644 index 00000000000..b18c1926b93 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md @@ -0,0 +1,119 @@ +# BarretenbergBackend + +## Implements + +- [`Backend`](../index.md#backend) + +## Constructors + +### new BarretenbergBackend(acirCircuit, options) + +```ts +new BarretenbergBackend(acirCircuit, options): BarretenbergBackend +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `acirCircuit` | `CompiledCircuit` | +| `options` | [`BackendOptions`](../type-aliases/BackendOptions.md) | + +#### Returns + +[`BarretenbergBackend`](BarretenbergBackend.md) + +## Methods + +### destroy() + +```ts +destroy(): Promise +``` + +#### Returns + +`Promise`\<`void`\> + +*** + +### generateProof() + +```ts +generateProof(compressedWitness): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `compressedWitness` | `Uint8Array` | + +#### Returns + +`Promise`\<`ProofData`\> + +#### Description + +Generates a proof + +*** + +### generateRecursiveProofArtifacts() + +```ts +generateRecursiveProofArtifacts(proofData, numOfPublicInputs): Promise +``` + +Generates artifacts that will be passed to a circuit that will verify this proof. + +Instead of passing the proof and verification key as a byte array, we pass them +as fields which makes it cheaper to verify in a circuit. + +The proof that is passed here will have been created using a circuit +that has the #[recursive] attribute on its `main` method. + +The number of public inputs denotes how many public inputs are in the inner proof. + +#### Parameters + +| Parameter | Type | Default value | +| :------ | :------ | :------ | +| `proofData` | `ProofData` | `undefined` | +| `numOfPublicInputs` | `number` | `0` | + +#### Returns + +`Promise`\<`object`\> + +#### Example + +```typescript +const artifacts = await backend.generateRecursiveProofArtifacts(proof, numOfPublicInputs); +``` + +*** + +### verifyProof() + +```ts +verifyProof(proofData): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `proofData` | `ProofData` | + +#### Returns + +`Promise`\<`boolean`\> + +#### Description + +Verifies 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.27.0/reference/NoirJS/backend_barretenberg/index.md b/docs/versioned_docs/version-v0.27.0/reference/NoirJS/backend_barretenberg/index.md new file mode 100644 index 00000000000..c146316a915 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/reference/NoirJS/backend_barretenberg/index.md @@ -0,0 +1,58 @@ +# backend_barretenberg + +## Exports + +### Classes + +| Class | Description | +| :------ | :------ | +| [BarretenbergBackend](classes/BarretenbergBackend.md) | - | + +### Type Aliases + +| Type alias | Description | +| :------ | :------ | +| [BackendOptions](type-aliases/BackendOptions.md) | - | + +## References + +### CompiledCircuit + +Renames and re-exports [Backend](index.md#backend) + +*** + +### ProofData + +Renames and re-exports [Backend](index.md#backend) + +## Variables + +### Backend + +```ts +Backend: any; +``` + +## Functions + +### publicInputsToWitnessMap() + +```ts +publicInputsToWitnessMap(publicInputs, abi): Backend +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `publicInputs` | `string`[] | +| `abi` | `Abi` | + +#### Returns + +[`Backend`](index.md#backend) + +*** + +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.27.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md b/docs/versioned_docs/version-v0.27.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md new file mode 100644 index 00000000000..b49a479f4f4 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md @@ -0,0 +1,21 @@ +# 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 | +| :------ | :------ | :------ | +| `memory` | `object` | - | +| `memory.maximum` | `number` | - | +| `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.27.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs b/docs/versioned_docs/version-v0.27.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs new file mode 100644 index 00000000000..339353b9862 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs @@ -0,0 +1,4 @@ +// @ts-check +/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ +const typedocSidebar = { items: [{"type":"category","label":"Classes","items":[{"type":"doc","id":"reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend","label":"BarretenbergBackend"}]},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions","label":"BackendOptions"}]}]}; +module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/.nojekyll b/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/.nojekyll new file mode 100644 index 00000000000..e2ac6616add --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/.nojekyll @@ -0,0 +1 @@ +TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/classes/Noir.md b/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/classes/Noir.md new file mode 100644 index 00000000000..45dd62ee57e --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/classes/Noir.md @@ -0,0 +1,132 @@ +# Noir + +## Constructors + +### new Noir(circuit, backend) + +```ts +new Noir(circuit, backend?): Noir +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `circuit` | `CompiledCircuit` | +| `backend`? | `any` | + +#### 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) +``` + +*** + +### generateProof() + +```ts +generateProof(inputs, foreignCallHandler?): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `inputs` | `InputMap` | +| `foreignCallHandler`? | [`ForeignCallHandler`](../type-aliases/ForeignCallHandler.md) | + +#### Returns + +`Promise`\<`ProofData`\> + +#### Description + +Generates a witness and a proof given an object as input. + +#### Example + +```typescript +async generateProof(input) +``` + +*** + +### verifyProof() + +```ts +verifyProof(proofData): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `proofData` | `ProofData` | + +#### Returns + +`Promise`\<`boolean`\> + +#### Description + +Instantiates the verification key and verifies a proof. + +#### Example + +```typescript +async verifyProof(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.27.0/reference/NoirJS/noir_js/functions/and.md b/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/functions/and.md new file mode 100644 index 00000000000..c783283e396 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/functions/and.md @@ -0,0 +1,22 @@ +# and() + +```ts +and(lhs, rhs): string +``` + +Performs a bitwise AND operation between `lhs` and `rhs` + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `lhs` | `string` | | +| `rhs` | `string` | | + +## Returns + +`string` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/functions/blake2s256.md b/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/functions/blake2s256.md new file mode 100644 index 00000000000..7882d0da8d5 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/functions/blake2s256.md @@ -0,0 +1,21 @@ +# blake2s256() + +```ts +blake2s256(inputs): Uint8Array +``` + +Calculates the Blake2s256 hash of the input bytes + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `inputs` | `Uint8Array` | | + +## Returns + +`Uint8Array` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md b/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md new file mode 100644 index 00000000000..5e3cd53e9d3 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md @@ -0,0 +1,28 @@ +# ecdsa\_secp256k1\_verify() + +```ts +ecdsa_secp256k1_verify( + hashed_msg, + public_key_x_bytes, + public_key_y_bytes, + signature): boolean +``` + +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.27.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md b/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md new file mode 100644 index 00000000000..0b20ff68957 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md @@ -0,0 +1,28 @@ +# ecdsa\_secp256r1\_verify() + +```ts +ecdsa_secp256r1_verify( + hashed_msg, + public_key_x_bytes, + public_key_y_bytes, + signature): boolean +``` + +Verifies a ECDSA signature over the secp256r1 curve. + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `hashed_msg` | `Uint8Array` | | +| `public_key_x_bytes` | `Uint8Array` | | +| `public_key_y_bytes` | `Uint8Array` | | +| `signature` | `Uint8Array` | | + +## Returns + +`boolean` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/functions/keccak256.md b/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/functions/keccak256.md new file mode 100644 index 00000000000..d10f155ce86 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/functions/keccak256.md @@ -0,0 +1,21 @@ +# keccak256() + +```ts +keccak256(inputs): Uint8Array +``` + +Calculates the Keccak256 hash of the input bytes + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `inputs` | `Uint8Array` | | + +## Returns + +`Uint8Array` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/functions/sha256.md b/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/functions/sha256.md new file mode 100644 index 00000000000..6ba4ecac022 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/functions/sha256.md @@ -0,0 +1,21 @@ +# sha256() + +```ts +sha256(inputs): Uint8Array +``` + +Calculates the SHA256 hash of the input bytes + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `inputs` | `Uint8Array` | | + +## Returns + +`Uint8Array` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/functions/xor.md b/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/functions/xor.md new file mode 100644 index 00000000000..8d762b895d3 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/functions/xor.md @@ -0,0 +1,22 @@ +# xor() + +```ts +xor(lhs, rhs): string +``` + +Performs a bitwise XOR operation between `lhs` and `rhs` + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `lhs` | `string` | | +| `rhs` | `string` | | + +## Returns + +`string` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/index.md b/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/index.md new file mode 100644 index 00000000000..cca6b3ace41 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/index.md @@ -0,0 +1,54 @@ +# noir_js + +## Exports + +### Classes + +| Class | Description | +| :------ | :------ | +| [Noir](classes/Noir.md) | - | + +### Type Aliases + +| Type alias | Description | +| :------ | :------ | +| [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) | - | +| [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) | Verifies a ECDSA signature over the secp256k1 curve. | +| [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` | + +## References + +### CompiledCircuit + +Renames and re-exports [InputMap](index.md#inputmap) + +*** + +### ProofData + +Renames and re-exports [InputMap](index.md#inputmap) + +## Variables + +### InputMap + +```ts +InputMap: any; +``` + +*** + +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.27.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md b/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md new file mode 100644 index 00000000000..812b8b16481 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md @@ -0,0 +1,24 @@ +# ForeignCallHandler + +```ts +type ForeignCallHandler: (name, inputs) => Promise; +``` + +A callback which performs an foreign call and returns the response. + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `name` | `string` | The identifier for the type of foreign call being performed. | +| `inputs` | [`ForeignCallInput`](ForeignCallInput.md)[] | An array of hex encoded inputs to the foreign call. | + +## Returns + +`Promise`\<[`ForeignCallOutput`](ForeignCallOutput.md)[]\> + +outputs - An array of hex encoded outputs containing the results of the foreign call. + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md b/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md new file mode 100644 index 00000000000..dd95809186a --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md @@ -0,0 +1,9 @@ +# ForeignCallInput + +```ts +type ForeignCallInput: string[]; +``` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md b/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md new file mode 100644 index 00000000000..b71fb78a946 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md @@ -0,0 +1,9 @@ +# ForeignCallOutput + +```ts +type ForeignCallOutput: string | string[]; +``` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md b/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md new file mode 100644 index 00000000000..258c46f9d0c --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md @@ -0,0 +1,9 @@ +# WitnessMap + +```ts +type WitnessMap: Map; +``` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs b/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs new file mode 100644 index 00000000000..c6d8125eaad --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs @@ -0,0 +1,4 @@ +// @ts-check +/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ +const typedocSidebar = { items: [{"type":"category","label":"Classes","items":[{"type":"doc","id":"reference/NoirJS/noir_js/classes/Noir","label":"Noir"}]},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ForeignCallHandler","label":"ForeignCallHandler"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ForeignCallInput","label":"ForeignCallInput"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ForeignCallOutput","label":"ForeignCallOutput"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/WitnessMap","label":"WitnessMap"}]},{"type":"category","label":"Functions","items":[{"type":"doc","id":"reference/NoirJS/noir_js/functions/and","label":"and"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/blake2s256","label":"blake2s256"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify","label":"ecdsa_secp256k1_verify"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify","label":"ecdsa_secp256r1_verify"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/keccak256","label":"keccak256"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/sha256","label":"sha256"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/xor","label":"xor"}]}]}; +module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_wasm/.nojekyll b/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_wasm/.nojekyll new file mode 100644 index 00000000000..e2ac6616add --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_wasm/.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.27.0/reference/NoirJS/noir_wasm/functions/compile.md b/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_wasm/functions/compile.md new file mode 100644 index 00000000000..6faf763b37f --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_wasm/functions/compile.md @@ -0,0 +1,51 @@ +# compile() + +```ts +compile( + fileManager, + projectPath?, + logFn?, +debugLogFn?): Promise +``` + +Compiles a Noir project + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `fileManager` | `FileManager` | The file manager to use | +| `projectPath`? | `string` | The path to the project inside the file manager. Defaults to the root of the file manager | +| `logFn`? | `LogFn` | A logging function. If not provided, console.log will be used | +| `debugLogFn`? | `LogFn` | A debug logging function. If not provided, logFn will be used | + +## Returns + +`Promise`\<[`ProgramCompilationArtifacts`](../index.md#programcompilationartifacts)\> + +## Example + +```typescript +// Node.js + +import { compile_program, createFileManager } from '@noir-lang/noir_wasm'; + +const fm = createFileManager(myProjectPath); +const myCompiledCode = await compile_program(fm); +``` + +```typescript +// Browser + +import { compile_program, createFileManager } from '@noir-lang/noir_wasm'; + +const fm = createFileManager('/'); +for (const path of files) { + await fm.writeFile(path, await getFileAsStream(path)); +} +const myCompiledCode = await compile_program(fm); +``` + +*** + +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.27.0/reference/NoirJS/noir_wasm/functions/compile_contract.md b/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_wasm/functions/compile_contract.md new file mode 100644 index 00000000000..7d0b39a43ef --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_wasm/functions/compile_contract.md @@ -0,0 +1,51 @@ +# compile\_contract() + +```ts +compile_contract( + fileManager, + projectPath?, + logFn?, +debugLogFn?): Promise +``` + +Compiles a Noir project + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `fileManager` | `FileManager` | The file manager to use | +| `projectPath`? | `string` | The path to the project inside the file manager. Defaults to the root of the file manager | +| `logFn`? | `LogFn` | A logging function. If not provided, console.log will be used | +| `debugLogFn`? | `LogFn` | A debug logging function. If not provided, logFn will be used | + +## Returns + +`Promise`\<[`ContractCompilationArtifacts`](../index.md#contractcompilationartifacts)\> + +## Example + +```typescript +// Node.js + +import { compile_contract, createFileManager } from '@noir-lang/noir_wasm'; + +const fm = createFileManager(myProjectPath); +const myCompiledCode = await compile_contract(fm); +``` + +```typescript +// Browser + +import { compile_contract, createFileManager } from '@noir-lang/noir_wasm'; + +const fm = createFileManager('/'); +for (const path of files) { + await fm.writeFile(path, await getFileAsStream(path)); +} +const myCompiledCode = await compile_contract(fm); +``` + +*** + +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.27.0/reference/NoirJS/noir_wasm/functions/createFileManager.md b/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_wasm/functions/createFileManager.md new file mode 100644 index 00000000000..7e65c1d69c7 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_wasm/functions/createFileManager.md @@ -0,0 +1,21 @@ +# createFileManager() + +```ts +createFileManager(dataDir): FileManager +``` + +Creates a new FileManager instance based on fs in node and memfs in the browser (via webpack alias) + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `dataDir` | `string` | root of the file system | + +## Returns + +`FileManager` + +*** + +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.27.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md b/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md new file mode 100644 index 00000000000..fcea9275341 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md @@ -0,0 +1,21 @@ +# inflateDebugSymbols() + +```ts +inflateDebugSymbols(debugSymbols): any +``` + +Decompresses and decodes the debug symbols + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `debugSymbols` | `string` | The base64 encoded debug symbols | + +## Returns + +`any` + +*** + +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.27.0/reference/NoirJS/noir_wasm/index.md b/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_wasm/index.md new file mode 100644 index 00000000000..b6e0f9d1bc0 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_wasm/index.md @@ -0,0 +1,49 @@ +# noir_wasm + +## Exports + +### Functions + +| Function | Description | +| :------ | :------ | +| [compile](functions/compile.md) | Compiles a Noir project | +| [compile\_contract](functions/compile_contract.md) | Compiles a Noir project | +| [createFileManager](functions/createFileManager.md) | Creates a new FileManager instance based on fs in node and memfs in the browser (via webpack alias) | +| [inflateDebugSymbols](functions/inflateDebugSymbols.md) | Decompresses and decodes the debug symbols | + +## References + +### compile\_program + +Renames and re-exports [compile](functions/compile.md) + +## Interfaces + +### ContractCompilationArtifacts + +The compilation artifacts of a given contract. + +#### Properties + +| Property | Type | Description | +| :------ | :------ | :------ | +| `contract` | `ContractArtifact` | The compiled contract. | +| `warnings` | `unknown`[] | Compilation warnings. | + +*** + +### ProgramCompilationArtifacts + +The compilation artifacts of a given program. + +#### Properties + +| Property | Type | Description | +| :------ | :------ | :------ | +| `name` | `string` | not part of the compilation output, injected later | +| `program` | `ProgramArtifact` | The compiled contract. | +| `warnings` | `unknown`[] | Compilation warnings. | + +*** + +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.27.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs b/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs new file mode 100644 index 00000000000..e0870710349 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs @@ -0,0 +1,4 @@ +// @ts-check +/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ +const typedocSidebar = { items: [{"type":"doc","id":"reference/NoirJS/noir_wasm/index","label":"API"},{"type":"category","label":"Functions","items":[{"type":"doc","id":"reference/NoirJS/noir_wasm/functions/compile","label":"compile"},{"type":"doc","id":"reference/NoirJS/noir_wasm/functions/compile_contract","label":"compile_contract"},{"type":"doc","id":"reference/NoirJS/noir_wasm/functions/createFileManager","label":"createFileManager"},{"type":"doc","id":"reference/NoirJS/noir_wasm/functions/inflateDebugSymbols","label":"inflateDebugSymbols"}]}]}; +module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.27.0/reference/_category_.json b/docs/versioned_docs/version-v0.27.0/reference/_category_.json new file mode 100644 index 00000000000..5b6a20a609a --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/reference/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 4, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.27.0/reference/nargo_commands.md b/docs/versioned_docs/version-v0.27.0/reference/nargo_commands.md new file mode 100644 index 00000000000..218fcfb0c8c --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/reference/nargo_commands.md @@ -0,0 +1,381 @@ +--- +title: Nargo +description: + Noir CLI Commands for Noir Prover and Verifier to create, execute, prove and verify programs, + generate Solidity verifier smart contract and compile into JSON file containing ACIR + representation and ABI of circuit. +keywords: + [ + Nargo, + Noir CLI, + Noir Prover, + Noir Verifier, + generate Solidity verifier, + compile JSON file, + ACIR representation, + ABI of circuit, + TypeScript, + ] +sidebar_position: 0 +--- + +# Command-Line Help for `nargo` + +This document contains the help content for the `nargo` command-line program. + +**Command Overview:** + +* [`nargo`↴](#nargo) +* [`nargo backend`↴](#nargo-backend) +* [`nargo backend current`↴](#nargo-backend-current) +* [`nargo backend ls`↴](#nargo-backend-ls) +* [`nargo backend use`↴](#nargo-backend-use) +* [`nargo backend install`↴](#nargo-backend-install) +* [`nargo backend uninstall`↴](#nargo-backend-uninstall) +* [`nargo check`↴](#nargo-check) +* [`nargo fmt`↴](#nargo-fmt) +* [`nargo codegen-verifier`↴](#nargo-codegen-verifier) +* [`nargo compile`↴](#nargo-compile) +* [`nargo new`↴](#nargo-new) +* [`nargo init`↴](#nargo-init) +* [`nargo execute`↴](#nargo-execute) +* [`nargo prove`↴](#nargo-prove) +* [`nargo verify`↴](#nargo-verify) +* [`nargo test`↴](#nargo-test) +* [`nargo info`↴](#nargo-info) +* [`nargo lsp`↴](#nargo-lsp) + +## `nargo` + +Noir's package manager + +**Usage:** `nargo ` + +###### **Subcommands:** + +* `backend` — Install and select custom backends used to generate and verify proofs +* `check` — Checks the constraint system for errors +* `fmt` — Format the Noir files in a workspace +* `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 Noir project in a new directory +* `init` — Create a Noir project in the current directory +* `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 +* `info` — Provides detailed information on each of a program's function (represented by a single circuit) +* `lsp` — Starts the Noir LSP server + +###### **Options:** + + + + +## `nargo backend` + +Install and select custom backends used to generate and verify proofs + +**Usage:** `nargo backend ` + +###### **Subcommands:** + +* `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 + + + +## `nargo backend current` + +Prints the name of the currently active backend + +**Usage:** `nargo backend current` + + + +## `nargo backend ls` + +Prints the list of currently installed backends + +**Usage:** `nargo backend ls` + + + +## `nargo backend use` + +Select the backend to use + +**Usage:** `nargo backend use ` + +###### **Arguments:** + +* `` + + + +## `nargo backend install` + +Install a new backend from a URL + +**Usage:** `nargo backend install ` + +###### **Arguments:** + +* `` — The name of the backend to install +* `` — The URL from which to download the backend + + + +## `nargo backend uninstall` + +Uninstalls a backend + +**Usage:** `nargo backend uninstall ` + +###### **Arguments:** + +* `` — The name of the backend to uninstall + + + +## `nargo check` + +Checks the constraint system for errors + +**Usage:** `nargo check [OPTIONS]` + +###### **Options:** + +* `--package ` — The name of the package to check +* `--workspace` — Check all packages in the workspace +* `--overwrite` — Force overwrite of existing files +* `--expression-width ` — Override the expression width requested by the backend +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings + + + +## `nargo fmt` + +Format the Noir files in a workspace + +**Usage:** `nargo fmt [OPTIONS]` + +###### **Options:** + +* `--check` — Run noirfmt in check mode + + + +## `nargo codegen-verifier` + +Generates a Solidity verifier smart contract for the program + +**Usage:** `nargo codegen-verifier [OPTIONS]` + +###### **Options:** + +* `--package ` — The name of the package to codegen +* `--workspace` — Codegen all packages in the workspace +* `--expression-width ` — Override the expression width requested by the backend +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings + + + +## `nargo compile` + +Compile the program and its secret execution trace into ACIR format + +**Usage:** `nargo compile [OPTIONS]` + +###### **Options:** + +* `--package ` — The name of the package to compile +* `--workspace` — Compile all packages in the workspace +* `--expression-width ` — Override the expression width requested by the backend +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings + + + +## `nargo new` + +Create a Noir project in a new directory + +**Usage:** `nargo new [OPTIONS] ` + +###### **Arguments:** + +* `` — The path to save the new project + +###### **Options:** + +* `--name ` — Name of the package [default: package directory name] +* `--lib` — Use a library template +* `--bin` — Use a binary template [default] +* `--contract` — Use a contract template + + + +## `nargo init` + +Create a Noir project in the current directory + +**Usage:** `nargo init [OPTIONS]` + +###### **Options:** + +* `--name ` — Name of the package [default: current directory name] +* `--lib` — Use a library template +* `--bin` — Use a binary template [default] +* `--contract` — Use a contract template + + + +## `nargo execute` + +Executes a circuit to calculate its return value + +**Usage:** `nargo execute [OPTIONS] [WITNESS_NAME]` + +###### **Arguments:** + +* `` — Write the execution witness to named file + +###### **Options:** + +* `-p`, `--prover-name ` — The name of the toml file which contains the inputs for the prover + + Default value: `Prover` +* `--package ` — The name of the package to execute +* `--workspace` — Execute all packages in the workspace +* `--expression-width ` — Override the expression width requested by the backend +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings +* `--oracle-resolver ` — JSON RPC url to solve oracle calls + + + +## `nargo prove` + +Create proof for this program. The proof is returned as a hex encoded string + +**Usage:** `nargo prove [OPTIONS]` + +###### **Options:** + +* `-p`, `--prover-name ` — The name of the toml file which contains the inputs for the prover + + Default value: `Prover` +* `-v`, `--verifier-name ` — The name of the toml file which contains the inputs for the verifier + + Default value: `Verifier` +* `--verify` — Verify proof after proving +* `--package ` — The name of the package to prove +* `--workspace` — Prove all packages in the workspace +* `--expression-width ` — Override the expression width requested by the backend +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings +* `--oracle-resolver ` — JSON RPC url to solve oracle calls + + + +## `nargo verify` + +Given a proof and a program, verify whether the proof is valid + +**Usage:** `nargo verify [OPTIONS]` + +###### **Options:** + +* `-v`, `--verifier-name ` — The name of the toml file which contains the inputs for the verifier + + Default value: `Verifier` +* `--package ` — The name of the package verify +* `--workspace` — Verify all packages in the workspace +* `--expression-width ` — Override the expression width requested by the backend +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings + + + +## `nargo test` + +Run the tests for this program + +**Usage:** `nargo test [OPTIONS] [TEST_NAME]` + +###### **Arguments:** + +* `` — If given, only tests with names containing this string will be run + +###### **Options:** + +* `--show-output` — Display output of `println` statements +* `--exact` — Only run tests that match exactly +* `--package ` — The name of the package to test +* `--workspace` — Test all packages in the workspace +* `--expression-width ` — Override the expression width requested by the backend +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings +* `--oracle-resolver ` — JSON RPC url to solve oracle calls + + + +## `nargo info` + +Provides detailed information on each of a program's function (represented by a single circuit) + +Current information provided per circuit: 1. The number of ACIR opcodes 2. Counts the final number gates in the circuit used by a backend + +**Usage:** `nargo info [OPTIONS]` + +###### **Options:** + +* `--package ` — The name of the package to detail +* `--workspace` — Detail all packages in the workspace +* `--expression-width ` — Override the expression width requested by the backend +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings + + + +## `nargo lsp` + +Starts the Noir LSP server + +Starts an LSP server which allows IDEs such as VS Code to display diagnostics in Noir source. + +VS Code Noir Language Support: https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir + +**Usage:** `nargo lsp` + + + +
+ + + This document was generated automatically by + clap-markdown. + + diff --git a/docs/versioned_docs/version-v0.27.0/tutorials/noirjs_app.md b/docs/versioned_docs/version-v0.27.0/tutorials/noirjs_app.md new file mode 100644 index 00000000000..0d75e2e8045 --- /dev/null +++ b/docs/versioned_docs/version-v0.27.0/tutorials/noirjs_app.md @@ -0,0 +1,279 @@ +--- +title: Building a web app with NoirJS +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, app] +sidebar_position: 0 +pagination_next: noir/concepts/data_types/index +--- + +NoirJS is a set of packages meant to work both in a browser and a server environment. In this tutorial, we will build a simple web app using them. From here, you should get an idea on how to proceed with your own Noir projects! + +You can find the complete app code for this guide [here](https://github.com/noir-lang/tiny-noirjs-app). + +## Setup + +:::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.19.x matches `noir_js@0.19.x`, etc. + +In this guide, we will be pinned to 0.19.4. + +::: + +Before we start, we want to make sure we have Node and Nargo installed. + +We start by opening a terminal and executing `node --version`. If we don't get an output like `v20.10.0`, that means node is not installed. Let's do that by following the handy [nvm guide](https://github.com/nvm-sh/nvm?tab=readme-ov-file#install--update-script). + +As for `Nargo`, we can follow the [Nargo guide](../getting_started/installation/index.md) to install it. If you're lazy, just paste this on a terminal and run `noirup`: + +```sh +curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash +``` + +Easy enough. Onwards! + +## Our project + +ZK is a powerful technology. An app that doesn't reveal one of the inputs to *anyone* is almost unbelievable, yet Noir makes it as easy as a single line of code. + +In fact, it's so simple that it comes nicely packaged in `nargo`. Let's do that! + +### Nargo + +Run: + +```nargo new circuit``` + +And... That's about it. Your program is ready to be compiled and run. + +To compile, let's `cd` into the `circuit` folder to enter our project, and call: + +```nargo compile``` + +This compiles our circuit into `json` format and add it to a new `target` folder. + +:::info + +At this point in the tutorial, your folder structure should look like this: + +```tree +. +└── circuit <---- our working directory + ├── Nargo.toml + ├── src + │ └── main.nr + └── target + └── circuit.json +``` + +::: + +### Node and Vite + +If you want to explore Nargo, feel free to go on a side-quest now and follow the steps in the +[getting started](../getting_started/hello_noir/index.md) guide. However, we want our app to run on the browser, so we need Vite. + +Vite is a powerful tool to generate static websites. While it provides all kinds of features, let's just go barebones with some good old vanilla JS. + +To do this this, go back to the previous folder (`cd ..`) and create a new vite project by running `npm create vite` and choosing "Vanilla" and "Javascript". + +You should see `vite-project` appear in your root folder. This seems like a good time to `cd` into it and install our NoirJS packages: + +```bash +npm i @noir-lang/backend_barretenberg@0.19.4 @noir-lang/noir_js@0.19.4 +``` + +:::info + +At this point in the tutorial, your folder structure should look like this: + +```tree +. +└── circuit + └── ...etc... +└── vite-project <---- our working directory + └── ...etc... +``` + +::: + +#### Some cleanup + +`npx create vite` is amazing but it creates a bunch of files we don't really need for our simple example. Actually, let's just delete everything except for `index.html`, `main.js` and `package.json`. I feel lighter already. + +![my heart is ready for you, noir.js](@site/static/img/memes/titanic.jpeg) + +## HTML + +Our app won't run like this, of course. We need some working HTML, at least. Let's open our broken-hearted `index.html` and replace everything with this code snippet: + +```html + + + + + + +

Noir app

+
+ + +
+
+

Logs

+

Proof

+
+ + +``` + +It *could* be a beautiful UI... Depending on which universe you live in. + +## Some good old vanilla Javascript + +Our love for Noir needs undivided attention, so let's just open `main.js` and delete everything (this is where the romantic scenery becomes a bit creepy). + +Start by pasting in this boilerplate code: + +```js +const setup = async () => { + await Promise.all([ + import("@noir-lang/noirc_abi").then(module => + module.default(new URL("@noir-lang/noirc_abi/web/noirc_abi_wasm_bg.wasm", import.meta.url).toString()) + ), + import("@noir-lang/acvm_js").then(module => + module.default(new URL("@noir-lang/acvm_js/web/acvm_js_bg.wasm", import.meta.url).toString()) + ) + ]); +} + +function display(container, msg) { + const c = document.getElementById(container); + const p = document.createElement('p'); + p.textContent = msg; + c.appendChild(p); +} + +document.getElementById('submitGuess').addEventListener('click', async () => { + try { + // here's where love happens + } catch(err) { + display("logs", "Oh 💔 Wrong guess") + } +}); + +``` + +The display function doesn't do much. We're simply manipulating our website to see stuff happening. For example, if the proof fails, it will simply log a broken heart 😢 + +As for the `setup` function, it's just a sad reminder that dealing with `wasm` on the browser is not as easy as it should. Just copy, paste, and forget. + +:::info + +At this point in the tutorial, your folder structure should look like this: + +```tree +. +└── circuit + └── ...same as above +└── vite-project + ├── main.js + ├── package.json + └── index.html +``` + +You'll see other files and folders showing up (like `package-lock.json`, `node_modules`) but you shouldn't have to care about those. + +::: + +## Some NoirJS + +We're starting with the good stuff now. If you've compiled the circuit as described above, you should have a `json` file we want to import at the very top of our `main.js` file: + +```ts +import circuit from '../circuit/target/circuit.json'; +``` + +[Noir is backend-agnostic](../index.mdx#whats-new-about-noir). We write Noir, but we also need a proving backend. That's why we need to import and instantiate the two dependencies we installed above: `BarretenbergBackend` and `Noir`. Let's import them right below: + +```js +import { BarretenbergBackend } from '@noir-lang/backend_barretenberg'; +import { Noir } from '@noir-lang/noir_js'; +``` + +And instantiate them inside our try-catch block: + +```ts +// try { +const backend = new BarretenbergBackend(circuit); +const noir = new Noir(circuit, backend); +// } +``` + +:::note + +For the remainder of the tutorial, everything will be happening inside the `try` block + +::: + +## Our app + +Now for the app itself. We're capturing whatever is in the input when people press the submit button. Just add this: + +```js +const x = parseInt(document.getElementById('guessInput').value); +const input = { x, y: 2 }; +``` + +Now we're ready to prove stuff! Let's feed some inputs to our circuit and calculate the proof: + +```js +await setup(); // let's squeeze our wasm inits here + +display('logs', 'Generating proof... ⌛'); +const proof = await noir.generateProof(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 run dev`. If it doesn't open a browser for you, just visit `localhost:5173`. You should now see the worst UI ever, with an ugly input. + +![Getting Started 0](@site/static/img/noir_getting_started_1.png) + +Now, our circuit says `fn main(x: Field, y: pub Field)`. This means only the `y` value is public, and it's hardcoded above: `input = { x, y: 2 }`. In other words, you won't need to send your secret`x` to the verifier! + +By inputting any number other than 2 in the input box and clicking "submit", you should get a valid proof. Otherwise the proof won't even generate correctly. By the way, if you're human, you shouldn't be able to understand anything on the "proof" box. That's OK. We like you, human ❤️. + +## Verifying + +Time to celebrate, yes! But we shouldn't trust machines so blindly. Let's add these lines to see our proof being verified: + +```js +display('logs', 'Verifying proof... ⌛'); +const verification = await noir.verifyProof(proof); +if (verification) display('logs', 'Verifying proof... ✅'); +``` + +You have successfully generated a client-side Noir web app! + +![coded app without math knowledge](@site/static/img/memes/flextape.jpeg) + +## 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/vite-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.28.0/explainers/explainer-oracle.md b/docs/versioned_docs/version-v0.28.0/explainers/explainer-oracle.md new file mode 100644 index 00000000000..b84ca5dd986 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/explainers/explainer-oracle.md @@ -0,0 +1,57 @@ +--- +title: Oracles +description: This guide provides an in-depth understanding of how Oracles work in Noir programming. Learn how to use outside calculations in your programs, constrain oracles, and understand their uses and limitations. +keywords: + - Noir Programming + - Oracles + - JSON-RPC + - Foreign Call Handlers + - Constrained Functions + - Blockchain Programming +sidebar_position: 1 +--- + +If you've seen "The Matrix" you may recall "The Oracle" as Gloria Foster smoking cigarettes and baking cookies. While she appears to "know things", she is actually providing a calculation of a pre-determined future. Noir Oracles are similar, in a way. They don't calculate the future (yet), but they allow you to use outside calculations in your programs. + +![matrix oracle prediction](@site/static/img/memes/matrix_oracle.jpeg) + +A Noir program is usually self-contained. You can pass certain inputs to it, and it will generate a deterministic output for those inputs. But what if you wanted to defer some calculation to an outside process or source? + +Oracles are functions that provide this feature. + +## Use cases + +An example usage for Oracles is proving something on-chain. For example, proving that the ETH-USDC quote was below a certain target at a certain block time. Or even making more complex proofs like proving the ownership of an NFT as an anonymous login method. + +Another interesting use case is to defer expensive calculations to be made outside of the Noir program, and then constraining the result; similar to the use of [unconstrained functions](../noir/concepts//unconstrained.md). + +In short, anything that can be constrained in a Noir program but needs to be fetched from an external source is a great candidate to be used in oracles. + +## Constraining oracles + +Just like in The Matrix, Oracles are powerful. But with great power, comes great responsibility. Just because you're using them in a Noir program doesn't mean they're true. Noir has no superpowers. If you want to prove that Portugal won the Euro Cup 2016, you're still relying on potentially untrusted information. + +To give a concrete example, Alice wants to login to the [NounsDAO](https://nouns.wtf/) forum with her username "noir_nouner" by proving she owns a noun without revealing her ethereum address. Her Noir program could have a oracle call like this: + +```rust +#[oracle(getNoun)] +unconstrained fn get_noun(address: Field) -> Field +``` + +This oracle could naively resolve with the number of Nouns she possesses. However, it is useless as a trusted source, as the oracle could resolve to anything Alice wants. In order to make this oracle call actually useful, Alice would need to constrain the response from the oracle, by proving her address and the noun count belongs to the state tree of the contract. + +In short, **Oracles don't prove anything. Your Noir program does.** + +:::danger + +If you don't constrain the return of your oracle, you could be clearly opening an attack vector on your Noir program. Make double-triple sure that the return of an oracle call is constrained! + +::: + +## How to use Oracles + +On CLI, Nargo resolves oracles by making JSON RPC calls, which means it would require an RPC node to be running. + +In JavaScript, NoirJS accepts and resolves arbitrary call handlers (that is, not limited to JSON) as long as they matches the expected types the developer defines. Refer to [Foreign Call Handler](../reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md) to learn more about NoirJS's call handling. + +If you want to build using oracles, follow through to the [oracle guide](../how_to/how-to-oracles.md) for a simple example on how to do that. diff --git a/docs/versioned_docs/version-v0.28.0/explainers/explainer-recursion.md b/docs/versioned_docs/version-v0.28.0/explainers/explainer-recursion.md new file mode 100644 index 00000000000..18846176ca7 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/explainers/explainer-recursion.md @@ -0,0 +1,176 @@ +--- +title: Recursive proofs +description: Explore the concept of recursive proofs in Zero-Knowledge programming. Understand how recursion works in Noir, a language for writing smart contracts on the EVM blockchain. Learn through practical examples like Alice and Bob's guessing game, Charlie's recursive merkle tree, and Daniel's reusable components. Discover how to use recursive proofs to optimize computational resources and improve efficiency. + +keywords: + [ + "Recursive Proofs", + "Zero-Knowledge Programming", + "Noir", + "EVM Blockchain", + "Smart Contracts", + "Recursion in Noir", + "Alice and Bob Guessing Game", + "Recursive Merkle Tree", + "Reusable Components", + "Optimizing Computational Resources", + "Improving Efficiency", + "Verification Key", + "Aggregation", + "Recursive zkSNARK schemes", + "PLONK", + "Proving and Verification Keys" + ] +sidebar_position: 1 +pagination_next: how_to/how-to-recursion +--- + +In programming, we tend to think of recursion as something calling itself. A classic example would be the calculation of the factorial of a number: + +```js +function factorial(n) { + if (n === 0 || n === 1) { + return 1; + } else { + return n * factorial(n - 1); + } +} +``` + +In this case, while `n` is not `1`, this function will keep calling itself until it hits the base case, bubbling up the result on the call stack: + +```md + Is `n` 1? <--------- + /\ / + / \ n = n -1 + / \ / + Yes No -------- +``` + +In Zero-Knowledge, recursion has some similarities. + +It is not a Noir function calling itself, but a proof being used as an input to another circuit. In short, you verify one proof *inside* another proof, returning the proof that both proofs are valid. + +This means that, given enough computational resources, you can prove the correctness of any arbitrary number of proofs in a single proof. This could be useful to design state channels (for which a common example would be [Bitcoin's Lightning Network](https://en.wikipedia.org/wiki/Lightning_Network)), to save on gas costs by settling one proof on-chain, or simply to make business logic less dependent on a consensus mechanism. + +## Examples + +Let us look at some of these examples + +### Alice and Bob - Guessing game + +Alice and Bob are friends, and they like guessing games. They want to play a guessing game online, but for that, they need a trusted third-party that knows both of their secrets and finishes the game once someone wins. + +So, they use zero-knowledge proofs. Alice tries to guess Bob's number, and Bob will generate a ZK proof stating whether she succeeded or failed. + +This ZK proof can go on a smart contract, revealing the winner and even giving prizes. However, this means every turn needs to be verified on-chain. This incurs some cost and waiting time that may simply make the game too expensive or time-consuming to be worth it. + +As a solution, Alice proposes the following: "what if Bob generates his proof, and instead of sending it on-chain, I verify it *within* my own proof before playing my own turn?". + +She can then generate a proof that she verified his proof, and so on. + +```md + Did you fail? <-------------------------- + / \ / + / \ n = n -1 + / \ / + Yes No / + | | / + | | / + | You win / + | / + | / +Generate proof of that / + + / + my own guess ---------------- +``` + +### Charlie - Recursive merkle tree + +Charlie is a concerned citizen, and wants to be sure his vote in an election is accounted for. He votes with a ZK proof, but he has no way of knowing that his ZK proof was included in the total vote count! + +If the vote collector puts all of the votes into a [Merkle tree](https://en.wikipedia.org/wiki/Merkle_tree), everyone can prove the verification of two proofs within one proof, as such: + +```md + abcd + __________|______________ + | | + ab cd + _____|_____ ______|______ + | | | | + alice bob charlie daniel +``` + +Doing this recursively allows us to arrive on a final proof `abcd` which if true, verifies the correctness of all the votes. + +### Daniel - Reusable components + +Daniel has a big circuit and a big headache. A part of his circuit is a setup phase that finishes with some assertions that need to be made. But that section alone takes most of the proving time, and is largely independent of the rest of the circuit. + +He might find it more efficient to generate a proof for that setup phase separately, and verify that proof recursively in the actual business logic section of his circuit. This will allow for parallelization of both proofs, which results in a considerable speedup. + +## What params do I need + +As you can see in the [recursion reference](noir/standard_library/recursion.md), a simple recursive proof requires: + +- The proof to verify +- The Verification Key of the circuit that generated the proof +- A hash of this verification key, as it's needed for some backends +- The public inputs for the proof + +:::info + +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. + +So, taking the example of Alice and Bob and their guessing game: + +- Alice makes her guess. Her proof is *not* recursive: it doesn't verify any proof within it! It's just a standard `assert(x != y)` circuit +- Bob verifies Alice's proof and makes his own guess. In this circuit, he doesn't exactly *prove* the verification of Alice's proof. Instead, he *aggregates* his proof to Alice's proof. The actual verification is done when the full proof is verified, for example when using `nargo verify` or through the verifier smart contract. + +We can imagine recursive proofs a [relay race](https://en.wikipedia.org/wiki/Relay_race). The first runner doesn't have to receive the baton from anyone else, as he/she already starts with it. But when his/her turn is over, the next runner needs to receive it, run a bit more, and pass it along. Even though every runner could theoretically verify the baton mid-run (why not? 🏃🔍), only at the end of the race does the referee verify that the whole race is valid. + +::: + +## Some architecture + +As with everything in computer science, there's no one-size-fits all. But there are some patterns that could help understanding and implementing them. To give three examples: + +### Adding some logic to a proof verification + +This would be an approach for something like our guessing game, where proofs are sent back and forth and are verified by each opponent. This circuit would be divided in two sections: + +- A `recursive verification` section, which would be just the call to `std::verify_proof`, and that would be skipped on the first move (since there's no proof to verify) +- A `guessing` section, which is basically the logic part where the actual guessing happens + +In such a situation, and assuming Alice is first, she would skip the first part and try to guess Bob's number. Bob would then verify her proof on the first section of his run, and try to guess Alice's number on the second part, and so on. + +### Aggregating proofs + +In some one-way interaction situations, recursion would allow for aggregation of simple proofs that don't need to be immediately verified on-chain or elsewhere. + +To give a practical example, a barman wouldn't need to verify a "proof-of-age" on-chain every time he serves alcohol to a customer. Instead, the architecture would comprise two circuits: + +- A `main`, non-recursive circuit with some logic +- A `recursive` circuit meant to verify two proofs in one proof + +The customer's proofs would be intermediate, and made on their phones, and the barman could just verify them locally. He would then aggregate them into a final proof sent on-chain (or elsewhere) at the end of the day. + +### Recursively verifying different circuits + +Nothing prevents you from verifying different circuits in a recursive proof, for example: + +- A `circuit1` circuit +- A `circuit2` circuit +- A `recursive` circuit + +In this example, a regulator could verify that taxes were paid for a specific purchase by aggregating both a `payer` circuit (proving that a purchase was made and taxes were paid), and a `receipt` circuit (proving that the payment was received) + +## How fast is it + +At the time of writing, verifying recursive proofs is surprisingly fast. This is because most of the time is spent on generating the verification key that will be used to generate the next proof. So you are able to cache the verification key and reuse it later. + +Currently, Noir JS packages don't expose the functionality of loading proving and verification keys, but that feature exists in the underlying `bb.js` package. + +## How can I try it + +Learn more about using recursion in Nargo and NoirJS in the [how-to guide](../how_to/how-to-recursion.md) and see a full example in [noir-examples](https://github.com/noir-lang/noir-examples). diff --git a/docs/versioned_docs/version-v0.28.0/getting_started/_category_.json b/docs/versioned_docs/version-v0.28.0/getting_started/_category_.json new file mode 100644 index 00000000000..5d694210bbf --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/getting_started/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 0, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.28.0/getting_started/hello_noir/_category_.json b/docs/versioned_docs/version-v0.28.0/getting_started/hello_noir/_category_.json new file mode 100644 index 00000000000..23b560f610b --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/getting_started/hello_noir/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 1, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.28.0/getting_started/hello_noir/index.md b/docs/versioned_docs/version-v0.28.0/getting_started/hello_noir/index.md new file mode 100644 index 00000000000..743c4d8d634 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/getting_started/hello_noir/index.md @@ -0,0 +1,142 @@ +--- +title: Creating a Project +description: + Learn how to create and verify your first Noir program using Nargo, a programming language for + zero-knowledge proofs. +keywords: + [ + Nargo, + Noir, + zero-knowledge proofs, + programming language, + create Noir program, + verify Noir program, + step-by-step guide, + ] +sidebar_position: 1 + +--- + +Now that we have installed Nargo, it is time to make our first hello world program! + +## Create a Project Directory + +Noir code can live anywhere on your computer. Let us create a _projects_ folder in the home +directory to house our Noir programs. + +For Linux, macOS, and Windows PowerShell, create the directory and change directory into it by +running: + +```sh +mkdir ~/projects +cd ~/projects +``` + +## Create Our First Nargo Project + +Now that we are in the projects directory, create a new Nargo project by running: + +```sh +nargo new hello_world +``` + +> **Note:** `hello_world` can be any arbitrary project name, we are simply using `hello_world` for +> demonstration. +> +> In production, the common practice is to name the project folder as `circuits` for better +> identifiability when sitting alongside other folders in the codebase (e.g. `contracts`, `scripts`, +> `test`). + +A `hello_world` folder would be created. Similar to Rust, the folder houses _src/main.nr_ and +_Nargo.toml_ which contain 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](../../noir/concepts/data_types/index.md) section. + +The next line of the program specifies its body: + +```rust +assert(x != y); +``` + +The Noir syntax `assert` can be interpreted as something similar to constraints in other zk-contract languages. + +For more Noir syntax, check the [Language Concepts](../../noir/concepts/comments.md) chapter. + +## Build In/Output Files + +Change directory into _hello_world_ and build in/output files for your Noir program by running: + +```sh +cd hello_world +nargo check +``` + +Two additional files would be generated in your project directory: + +_Prover.toml_ houses input values, and _Verifier.toml_ houses public values. + +## Prove Our Noir Program + +Now that the project is set up, we can create a proof of correct execution of 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](./project_breakdown.md), we will go into more detail on each step performed. diff --git a/docs/versioned_docs/version-v0.28.0/getting_started/hello_noir/project_breakdown.md b/docs/versioned_docs/version-v0.28.0/getting_started/hello_noir/project_breakdown.md new file mode 100644 index 00000000000..6160a102c6c --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/getting_started/hello_noir/project_breakdown.md @@ -0,0 +1,199 @@ +--- +title: Project Breakdown +description: + Learn about the anatomy of a Nargo project, including the purpose of the Prover and Verifier TOML + files, and how to prove and verify your program. +keywords: + [Nargo, Nargo project, Prover.toml, Verifier.toml, proof verification, private asset transfer] +sidebar_position: 2 +--- + +This section breaks down our hello world program from the previous section. We elaborate on the project +structure and what the `prove` and `verify` commands did. + +## 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 = "noir_starter" +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](../../noir/modules_packages_crates/workspaces.md) will look a bit different. For example: + +```toml +[workspace] +members = ["crates/a", "crates/b"] +default-member = "crates/a" +``` + +#### Package section + +The package section defines 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](../../noir/modules_packages_crates/dependencies.md) for more info. + +`./proofs/` and `./contract/` directories will not be immediately visible until you create a proof or +verifier contract respectively. + +### main.nr + +The _main.nr_ file contains a `main` method, this method is the entry point into your Noir program. + +In our sample program, _main.nr_ looks like this: + +```rust +fn main(x : Field, y : Field) { + assert(x != y); +} +``` + +The parameters `x` and `y` can be seen as the API for the program and must be supplied by the +prover. Since neither `x` nor `y` is marked as public, the verifier does not supply any inputs, when +verifying the proof. + +The prover supplies the values for `x` and `y` in the _Prover.toml_ file. + +As for the program body, `assert` ensures that the condition to be satisfied (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 inequality 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, usually from external sources, and +verify the validity of the proof against it. + +Take a private asset transfer as an example: + +A person using a browser as the prover would retrieve private inputs locally (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.28.0/getting_started/installation/_category_.json b/docs/versioned_docs/version-v0.28.0/getting_started/installation/_category_.json new file mode 100644 index 00000000000..0c02fb5d4d7 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/getting_started/installation/_category_.json @@ -0,0 +1,6 @@ +{ + "position": 0, + "label": "Install Nargo", + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.28.0/getting_started/installation/index.md b/docs/versioned_docs/version-v0.28.0/getting_started/installation/index.md new file mode 100644 index 00000000000..4ef86aa5914 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/getting_started/installation/index.md @@ -0,0 +1,48 @@ +--- +title: Nargo Installation +description: + nargo is a command line tool for interacting with Noir programs. This page is a quick guide on how to install Nargo through the most common and easy method, noirup +keywords: [ + Nargo + Noir + Rust + Cargo + Noirup + Installation + Terminal Commands + Version Check + Nightlies + Specific Versions + Branches + Noirup Repository +] +pagination_next: getting_started/hello_noir/index +--- + +`nargo` is the one-stop-shop for almost everything related with Noir. The name comes from our love for Rust and its package manager `cargo`. + +With `nargo`, you can start new projects, compile, execute, prove, verify, test, generate solidity contracts, and do pretty much all that is available in Noir. + +Similarly to `rustup`, we also maintain an easy installation method that covers most machines: `noirup`. + +## Installing Noirup + +Open a terminal on your machine, and write: + +```bash +curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash +``` + +Close the terminal, open another one, and run + +```bash +noirup +``` + +Done. That's it. You should have the latest version working. You can check with `nargo --version`. + +You can also install nightlies, specific versions +or branches. Check out the [noirup repository](https://github.com/noir-lang/noirup) for more +information. + +Now we're ready to start working on [our first Noir program!](../hello_noir/index.md) diff --git a/docs/versioned_docs/version-v0.28.0/getting_started/installation/other_install_methods.md b/docs/versioned_docs/version-v0.28.0/getting_started/installation/other_install_methods.md new file mode 100644 index 00000000000..3634723562b --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/getting_started/installation/other_install_methods.md @@ -0,0 +1,102 @@ +--- +title: Alternative Installations +description: There are different ways to install Nargo, the one-stop shop and command-line tool for developing Noir programs. This guide explains how to specify which version to install when using noirup, and using WSL for windows. +keywords: [ + Installation + Nargo + Noirup + Binaries + Compiling from Source + WSL for Windows + macOS + Linux + Nix + Direnv + Uninstalling Nargo + ] +sidebar_position: 1 +--- + +## Encouraged Installation Method: Noirup + +Noirup is the endorsed method for installing Nargo, streamlining the process of fetching binaries or compiling from source. It supports a range of options to cater to your specific needs, from nightly builds and specific versions to compiling from various sources. + +### Installing Noirup + +First, ensure you have `noirup` installed: + +```sh +curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash +``` + +### Fetching Binaries + +With `noirup`, you can easily switch between different Nargo versions, including nightly builds: + +- **Nightly Version**: Install the latest nightly build. + + ```sh + noirup --version nightly + ``` + +- **Specific Version**: Install a specific version of Nargo. + ```sh + noirup --version + ``` + +### Compiling from Source + +`noirup` also enables compiling Nargo from various sources: + +- **From a Specific Branch**: Install from the latest commit on a branch. + + ```sh + noirup --branch + ``` + +- **From a Fork**: Install from the main branch of a fork. + + ```sh + noirup --repo + ``` + +- **From a Specific Branch in a Fork**: Install from a specific branch in a fork. + + ```sh + noirup --repo --branch + ``` + +- **From a Specific Pull Request**: Install from a specific PR. + + ```sh + noirup --pr + ``` + +- **From a Specific Commit**: Install from a specific commit. + + ```sh + noirup -C + ``` + +- **From Local Source**: Compile and install from a local directory. + ```sh + noirup --path ./path/to/local/source + ``` + +## Installation on Windows + +The default backend for Noir (Barretenberg) doesn't provide Windows binaries at this time. For that reason, Noir cannot be installed natively. 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](#encouraged-installation-method-noirup). + +## Uninstalling Nargo + +If you installed Nargo with `noirup`, you can uninstall Nargo by removing the files in `~/.nargo`, `~/nargo`, and `~/noir_cache`. This ensures that all installed binaries, configurations, and cache related to Nargo are fully removed from your system. + +```bash +rm -r ~/.nargo +rm -r ~/nargo +rm -r ~/noir_cache +``` diff --git a/docs/versioned_docs/version-v0.28.0/getting_started/tooling/noir_codegen.md b/docs/versioned_docs/version-v0.28.0/getting_started/tooling/noir_codegen.md new file mode 100644 index 00000000000..d65151da0ab --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/getting_started/tooling/noir_codegen.md @@ -0,0 +1,113 @@ +--- +title: Noir Codegen for TypeScript +description: Learn how to use Noir codegen to generate TypeScript bindings +keywords: [Nargo, Noir, compile, TypeScript] +sidebar_position: 2 +--- + +When using TypeScript, it is extra work to interpret Noir program outputs in a type-safe way. Third party libraries may exist for popular Noir programs, but they are either hard to find or unmaintained. + +Now you can generate TypeScript bindings for your Noir programs in two steps: +1. Exporting Noir functions using `nargo export` +2. Using the TypeScript module `noir_codegen` to generate TypeScript binding + +**Note:** you can only export functions from a Noir *library* (not binary or contract program types). + +## Installation + +### Your TypeScript project + +If you don't already have a TypeScript project you can add the module with `yarn` (or `npm`), then initialize it: + +```bash +yarn add typescript -D +npx tsc --init +``` + +### Add TypeScript module - `noir_codegen` + +The following command will add the module to your project's devDependencies: + +```bash +yarn add @noir-lang/noir_codegen -D +``` + +### Nargo library +Make sure you have Nargo, v0.25.0 or greater, installed. If you don't, follow the [installation guide](../installation/index.md). + +If you're in a new project, make a `circuits` folder and create a new Noir library: + +```bash +mkdir circuits && cd circuits +nargo new --lib myNoirLib +``` + +## Usage + +### Export ABI of specified functions + +First go to the `.nr` files in your Noir library, and add the `#[export]` macro to each function that you want to use in TypeScript. + +```rust +#[export] +fn your_function(... +``` + +From your Noir library (where `Nargo.toml` is), run the following command: + +```bash +nargo export +``` + +You will now have an `export` directory with a .json file per exported function. + +You can also specify the directory of Noir programs using `--program-dir`, for example: + +```bash +nargo export --program-dir=./circuits/myNoirLib +``` + +### Generate TypeScript bindings from exported functions + +To use the `noir-codegen` package we added to the TypeScript project: + +```bash +yarn noir-codegen ./export/your_function.json +``` + +This creates an `exports` directory with an `index.ts` file containing all exported functions. + +**Note:** adding `--out-dir` allows you to specify an output dir for your TypeScript bindings to go. Eg: + +```bash +yarn noir-codegen ./export/*.json --out-dir ./path/to/output/dir +``` + +## Example .nr function to .ts output + +Consider a Noir library with this function: + +```rust +#[export] +fn not_equal(x: Field, y: Field) -> bool { + x != y +} +``` + +After the export and codegen steps, you should have an `index.ts` like: + +```typescript +export type Field = string; + + +export const is_equal_circuit: CompiledCircuit = {"abi":{"parameters":[{"name":"x","type":{"kind":"field"},"visibility":"private"},{"name":"y","type":{"kind":"field"},"visibility":"private"}],"param_witnesses":{"x":[{"start":0,"end":1}],"y":[{"start":1,"end":2}]},"return_type":{"abi_type":{"kind":"boolean"},"visibility":"private"},"return_witnesses":[4]},"bytecode":"H4sIAAAAAAAA/7WUMQ7DIAxFQ0Krrr2JjSGYLVcpKrn/CaqqDQN12WK+hPBgmWd/wEyHbF1SS923uhOs3pfoChI+wKXMAXzIKyNj4PB0TFTYc0w5RUjoqeAeEu1wqK0F54RGkWvW44LPzExnlkbMEs4JNZmN8PxS42uHv82T8a3Jeyn2Ks+VLPcO558HmyLMCDOXAXXtpPt4R/Rt9T36ss6dS9HGPx/eG17nGegKBQAA"}; + +export async function is_equal(x: Field, y: Field, foreignCallHandler?: ForeignCallHandler): Promise { + const program = new Noir(is_equal_circuit); + const args: InputMap = { x, y }; + const { returnValue } = await program.execute(args, foreignCallHandler); + return returnValue as boolean; +} +``` + +Now the `is_equal()` function and relevant types are readily available for use in TypeScript. diff --git a/docs/versioned_docs/version-v0.28.0/how_to/_category_.json b/docs/versioned_docs/version-v0.28.0/how_to/_category_.json new file mode 100644 index 00000000000..23b560f610b --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/how_to/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 1, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.28.0/how_to/debugger/_category_.json b/docs/versioned_docs/version-v0.28.0/how_to/debugger/_category_.json new file mode 100644 index 00000000000..cc2cbb1c253 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/how_to/debugger/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Debugging", + "position": 5, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.28.0/how_to/debugger/debugging_with_the_repl.md b/docs/versioned_docs/version-v0.28.0/how_to/debugger/debugging_with_the_repl.md new file mode 100644 index 00000000000..09e5bae68ad --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/how_to/debugger/debugging_with_the_repl.md @@ -0,0 +1,164 @@ +--- +title: Using the REPL Debugger +description: + Step by step guide on how to debug your Noir circuits with the REPL Debugger. +keywords: + [ + Nargo, + Noir CLI, + Noir Debugger, + REPL, + ] +sidebar_position: 1 +--- + +#### Pre-requisites + +In order to use the REPL debugger, first you need to install recent enough versions of Nargo and vscode-noir. + +## Debugging a simple circuit + +Let's debug a simple circuit: + +```rust +fn main(x : Field, y : pub Field) { + assert(x != y); +} +``` + +To start the REPL debugger, using a terminal, go to a Noir circuit's home directory. Then: + +`$ nargo debug` + +You should be seeing this in your terminal: + +``` +[main] Starting debugger +At ~/noir-examples/recursion/circuits/main/src/main.nr:1:9 + 1 -> fn main(x : Field, y : pub Field) { + 2 assert(x != y); + 3 } +> +``` + +The debugger displays the current Noir code location, and it is now waiting for us to drive it. + +Let's first take a look at the available commands. For that we'll use the `help` command. + +``` +> help +Available commands: + + opcodes display ACIR opcodes + into step into to the next opcode + next step until a new source location is reached + out step until a new source location is reached + and the current stack frame is finished + break LOCATION:OpcodeLocation add a breakpoint at an opcode location + over step until a new source location is reached + without diving into function calls + restart restart the debugging session + delete LOCATION:OpcodeLocation delete breakpoint at an opcode location + witness show witness map + witness index:u32 display a single witness from the witness map + witness index:u32 value:String update a witness with the given value + memset index:usize value:String update a memory cell with the given + value + continue continue execution until the end of the + program + vars show variable values available at this point + in execution + stacktrace display the current stack trace + memory show memory (valid when executing unconstrained code) + step step to the next ACIR opcode + +Other commands: + + help Show this help message + quit Quit repl + +``` + +Some commands operate only for unconstrained functions, such as `memory` and `memset`. If you try to use them while execution is paused at an ACIR opcode, the debugger will simply inform you that you are not executing unconstrained code: + +``` +> memory +Unconstrained VM memory not available +> +``` + +Before continuing, we can take a look at the initial witness map: + +``` +> witness +_0 = 1 +_1 = 2 +> +``` + +Cool, since `x==1`, `y==2`, and we want to check that `x != y`, our circuit should succeed. At this point we could intervene and use the witness setter command to change one of the witnesses. Let's set `y=3`, then back to 2, so we don't affect the expected result: + +``` +> witness +_0 = 1 +_1 = 2 +> witness 1 3 +_1 = 3 +> witness +_0 = 1 +_1 = 3 +> witness 1 2 +_1 = 2 +> witness +_0 = 1 +_1 = 2 +> +``` + +Now we can inspect the current state of local variables. For that we use the `vars` command. + +``` +> vars +> +``` + +We currently have no vars in context, since we are at the entry point of the program. Let's use `next` to execute until the next point in the program. + +``` +> vars +> next +At ~/noir-examples/recursion/circuits/main/src/main.nr:1:20 + 1 -> fn main(x : Field, y : pub Field) { + 2 assert(x != y); + 3 } +> vars +x:Field = 0x01 +``` + +As a result of stepping, the variable `x`, whose initial value comes from the witness map, is now in context and returned by `vars`. + +``` +> next + 1 fn main(x : Field, y : pub Field) { + 2 -> assert(x != y); + 3 } +> vars +y:Field = 0x02 +x:Field = 0x01 +``` + +Stepping again we can finally see both variables and their values. And now we can see that the next assertion should succeed. + +Let's continue to the end: + +``` +> continue +(Continuing execution...) +Finished execution +> q +[main] Circuit witness successfully solved +``` + +Upon quitting the debugger after a solved circuit, the resulting circuit witness gets saved, equivalent to what would happen if we had run the same circuit with `nargo execute`. + +We just went through the basics of debugging using Noir REPL debugger. For a comprehensive reference, check out [the reference page](../../reference/debugger/debugger_repl.md). diff --git a/docs/versioned_docs/version-v0.28.0/how_to/debugger/debugging_with_vs_code.md b/docs/versioned_docs/version-v0.28.0/how_to/debugger/debugging_with_vs_code.md new file mode 100644 index 00000000000..a5858c1a5eb --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/how_to/debugger/debugging_with_vs_code.md @@ -0,0 +1,68 @@ +--- +title: Using the VS Code Debugger +description: + Step by step guide on how to debug your Noir circuits with the VS Code Debugger configuration and features. +keywords: + [ + Nargo, + Noir CLI, + Noir Debugger, + VS Code, + IDE, + ] +sidebar_position: 0 +--- + +This guide will show you how to use VS Code with the vscode-noir extension to debug a Noir project. + +#### Pre-requisites + +- Nargo +- vscode-noir +- A Noir project with a `Nargo.toml`, `Prover.toml` and at least one Noir (`.nr`) containing an entry point function (typically `main`). + +## Running the debugger + +The easiest way to start debugging is to open the file you want to debug, and press `F5`. This will cause the debugger to launch, using your `Prover.toml` file as input. + +You should see something like this: + +![Debugger launched](@site/static/img/debugger/1-started.png) + +Let's inspect the state of the program. For that, we open VS Code's _Debug pane_. Look for this icon: + +![Debug pane icon](@site/static/img/debugger/2-icon.png) + +You will now see two categories of variables: Locals and Witness Map. + +![Debug pane expanded](@site/static/img/debugger/3-debug-pane.png) + +1. **Locals**: variables of your program. At this point in execution this section is empty, but as we step through the code it will get populated by `x`, `result`, `digest`, etc. + +2. **Witness map**: these are initially populated from your project's `Prover.toml` file. In this example, they will be used to populate `x` and `result` at the beginning of the `main` function. + +Most of the time you will probably be focusing mostly on locals, as they represent the high level state of your program. + +You might be interested in inspecting the witness map in case you are trying to solve a really low level issue in the compiler or runtime itself, so this concerns mostly advanced or niche users. + +Let's step through the program, by using the debugger buttons or their corresponding keyboard shortcuts. + +![Debugger buttons](@site/static/img/debugger/4-debugger-buttons.png) + +Now we can see in the variables pane that there's values for `digest`, `result` and `x`. + +![Inspecting locals](@site/static/img/debugger/5-assert.png) + +We can also inspect the values of variables by directly hovering on them on the code. + +![Hover locals](@site/static/img/debugger/6-hover.png) + +Let's set a break point at the `keccak256` function, so we can continue execution up to the point when it's first invoked without having to go one step at a time. + +We just need to click the to the right of the line number 18. Once the breakpoint appears, we can click the `continue` button or use its corresponding keyboard shortcut (`F5` by default). + +![Breakpoint](@site/static/img/debugger/7-break.png) + +Now we are debugging the `keccak256` function, notice the _Call Stack pane_ at the lower right. This lets us inspect the current call stack of our process. + +That covers most of the current debugger functionalities. Check out [the reference](../../reference/debugger/debugger_vscode.md) for more details on how to configure the debugger. \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.28.0/how_to/how-to-oracles.md b/docs/versioned_docs/version-v0.28.0/how_to/how-to-oracles.md new file mode 100644 index 00000000000..8cf8035a5c4 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/how_to/how-to-oracles.md @@ -0,0 +1,276 @@ +--- +title: How to use Oracles +description: Learn how to use oracles in your Noir program with examples in both Nargo and NoirJS. This guide also covers writing a JSON RPC server and providing custom foreign call handlers for NoirJS. +keywords: + - Noir Programming + - Oracles + - Nargo + - NoirJS + - JSON RPC Server + - Foreign Call Handlers +sidebar_position: 1 +--- + +This guide shows you how to use oracles in your Noir program. For the sake of clarity, it assumes that: + +- You have read the [explainer on Oracles](../explainers/explainer-oracle.md) and are comfortable with the concept. +- You have a Noir program to add oracles to. You can create one using the [vite-hardhat starter](https://github.com/noir-lang/noir-starter/tree/main/vite-hardhat) as a boilerplate. +- You understand the concept of a JSON-RPC server. Visit the [JSON-RPC website](https://www.jsonrpc.org/) if you need a refresher. +- You are comfortable with server-side JavaScript (e.g. Node.js, managing packages, etc.). + +For reference, you can find the snippets used in this tutorial on the [Aztec DevRel Repository](https://github.com/AztecProtocol/dev-rel/tree/main/code-snippets/how-to-oracles). + +## Rundown + +This guide has 3 major steps: + +1. How to modify our Noir program to make use of oracle calls as unconstrained functions +2. How to write a JSON RPC Server to resolve these oracle calls with Nargo +3. How to use them in Nargo and how to provide a custom resolver in NoirJS + +## Step 1 - Modify your Noir program + +An oracle is defined in a Noir program by defining two methods: + +- An unconstrained method - This tells the compiler that it is executing an [unconstrained functions](../noir/concepts//unconstrained.md). +- A decorated oracle method - This tells the compiler that this method is an RPC call. + +An example of an oracle that returns a `Field` would be: + +```rust +#[oracle(getSqrt)] +unconstrained fn sqrt(number: Field) -> Field { } + +unconstrained fn get_sqrt(number: Field) -> Field { + sqrt(number) +} +``` + +In this example, we're wrapping our oracle function in a unconstrained method, and decorating it with `oracle(getSqrt)`. We can then call the unconstrained function as we would call any other function: + +```rust +fn main(input: Field) { + let sqrt = get_sqrt(input); +} +``` + +In the next section, we will make this `getSqrt` (defined on the `sqrt` decorator) be a method of the RPC server Noir will use. + +:::danger + +As explained in the [Oracle Explainer](../explainers/explainer-oracle.md), this `main` function is unsafe unless you constrain its return value. For example: + +```rust +fn main(input: Field) { + let sqrt = get_sqrt(input); + assert(sqrt.pow_32(2) as u64 == input as u64); // <---- constrain the return of an oracle! +} +``` + +::: + +:::info + +Currently, oracles only work with single params or array params. For example: + +```rust +#[oracle(getSqrt)] +unconstrained fn sqrt([Field; 2]) -> [Field; 2] { } +``` + +::: + +## Step 2 - Write an RPC server + +Brillig will call *one* RPC server. Most likely you will have to write your own, and you can do it in whatever language you prefer. In this guide, we will do it in Javascript. + +Let's use the above example of an oracle that consumes an array with two `Field` and returns their square roots: + +```rust +#[oracle(getSqrt)] +unconstrained fn sqrt(input: [Field; 2]) -> [Field; 2] { } + +unconstrained fn get_sqrt(input: [Field; 2]) -> [Field; 2] { + sqrt(input) +} + +fn main(input: [Field; 2]) { + let sqrt = get_sqrt(input); + assert(sqrt[0].pow_32(2) as u64 == input[0] as u64); + assert(sqrt[1].pow_32(2) as u64 == input[1] as u64); +} +``` + +:::info + +Why square root? + +In general, computing square roots is computationally more expensive than multiplications, which takes a toll when speaking about ZK applications. In this case, instead of calculating the square root in Noir, we are using our oracle to offload that computation to be made in plain. In our circuit we can simply multiply the two values. + +::: + +Now, we should write the correspondent RPC server, starting with the [default JSON-RPC 2.0 boilerplate](https://www.npmjs.com/package/json-rpc-2.0#example): + +```js +import { JSONRPCServer } from "json-rpc-2.0"; +import express from "express"; +import bodyParser from "body-parser"; + +const app = express(); +app.use(bodyParser.json()); + +const server = new JSONRPCServer(); +app.post("/", (req, res) => { + const jsonRPCRequest = req.body; + server.receive(jsonRPCRequest).then((jsonRPCResponse) => { + if (jsonRPCResponse) { + res.json(jsonRPCResponse); + } else { + res.sendStatus(204); + } + }); +}); + +app.listen(5555); +``` + +Now, we will add our `getSqrt` method, as expected by the `#[oracle(getSqrt)]` decorator in our Noir code. It maps through the params array and returns their square roots: + +```js +server.addMethod("getSqrt", async (params) => { + const values = params[0].Array.map((field) => { + return `${Math.sqrt(parseInt(field, 16))}`; + }); + return { values: [{ Array: values }] }; +}); +``` + +:::tip + +Brillig expects an object with an array of values. Each value is an object declaring to be `Single` or `Array` and returning a field element *as a string*. For example: + +```json +{ "values": [{ "Array": ["1", "2"] }]} +{ "values": [{ "Single": "1" }]} +{ "values": [{ "Single": "1" }, { "Array": ["1", "2"] }]} +``` + +If you're using Typescript, the following types may be helpful in understanding the expected return value and making sure they're easy to follow: + +```js +interface SingleForeignCallParam { + Single: string, +} + +interface ArrayForeignCallParam { + Array: string[], +} + +type ForeignCallParam = SingleForeignCallParam | ArrayForeignCallParam; + +interface ForeignCallResult { + values: ForeignCallParam[], +} +``` + +::: + +## Step 3 - Usage with Nargo + +Using the [`nargo` CLI tool](../getting_started/installation/index.md), you can use oracles in the `nargo test`, `nargo execute` and `nargo prove` commands by passing a value to `--oracle-resolver`. For example: + +```bash +nargo test --oracle-resolver http://localhost:5555 +``` + +This tells `nargo` to use your RPC Server URL whenever it finds an oracle decorator. + +## Step 4 - Usage with NoirJS + +In a JS environment, an RPC server is not strictly necessary, as you may want to resolve your oracles without needing any JSON call at all. NoirJS simply expects that you pass a callback function when you generate proofs, and that callback function can be anything. + +For example, if your Noir program expects the host machine to provide CPU pseudo-randomness, you could simply pass it as the `foreignCallHandler`. You don't strictly need to create an RPC server to serve pseudo-randomness, as you may as well get it directly in your app: + +```js +const foreignCallHandler = (name, inputs) => crypto.randomBytes(16) // etc + +await noir.generateProof(inputs, foreignCallHandler) +``` + +As one can see, in NoirJS, the [`foreignCallHandler`](../reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md) function simply means "a callback function that returns a value of type [`ForeignCallOutput`](../reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md). It doesn't have to be an RPC call like in the case for Nargo. + +:::tip + +Does this mean you don't have to write an RPC server like in [Step #2](#step-2---write-an-rpc-server)? + +You don't technically have to, but then how would you run `nargo test` or `nargo prove`? To use both `Nargo` and `NoirJS` in your development flow, you will have to write a JSON RPC server. + +::: + +In this case, let's make `foreignCallHandler` call the JSON RPC Server we created in [Step #2](#step-2---write-an-rpc-server), by making it a JSON RPC Client. + +For example, using the same `getSqrt` program in [Step #1](#step-1---modify-your-noir-program) (comments in the code): + +```js +import { JSONRPCClient } from "json-rpc-2.0"; + +// declaring the JSONRPCClient +const client = new JSONRPCClient((jsonRPCRequest) => { +// hitting the same JSON RPC Server we coded above + return fetch("http://localhost:5555", { + method: "POST", + headers: { + "content-type": "application/json", + }, + body: JSON.stringify(jsonRPCRequest), + }).then((response) => { + if (response.status === 200) { + return response + .json() + .then((jsonRPCResponse) => client.receive(jsonRPCResponse)); + } else if (jsonRPCRequest.id !== undefined) { + return Promise.reject(new Error(response.statusText)); + } + }); +}); + +// declaring a function that takes the name of the foreign call (getSqrt) and the inputs +const foreignCallHandler = async (name, input) => { + // notice that the "inputs" parameter contains *all* the inputs + // in this case we to make the RPC request with the first parameter "numbers", which would be input[0] + const oracleReturn = await client.request(name, [ + { Array: input[0].map((i) => i.toString("hex")) }, + ]); + return [oracleReturn.values[0].Array]; +}; + +// the rest of your NoirJS code +const input = { input: [4, 16] }; +const { witness } = await noir.execute(numbers, foreignCallHandler); +``` + +:::tip + +If you're in a NoirJS environment running your RPC server together with a frontend app, you'll probably hit a familiar problem in full-stack development: requests being blocked by [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) policy. For development only, you can simply install and use the [`cors` npm package](https://www.npmjs.com/package/cors) to get around the problem: + +```bash +yarn add cors +``` + +and use it as a middleware: + +```js +import cors from "cors"; + +const app = express(); +app.use(cors()) +``` + +::: + +## Conclusion + +Hopefully by the end of this guide, you should be able to: + +- Write your own logic around Oracles and how to write a JSON RPC server to make them work with your Nargo commands. +- Provide custom foreign call handlers for NoirJS. diff --git a/docs/versioned_docs/version-v0.28.0/how_to/how-to-recursion.md b/docs/versioned_docs/version-v0.28.0/how_to/how-to-recursion.md new file mode 100644 index 00000000000..4c45bb87ae2 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/how_to/how-to-recursion.md @@ -0,0 +1,179 @@ +--- +title: How to use recursion on NoirJS +description: Learn how to implement recursion with NoirJS, a powerful tool for creating smart contracts on the EVM blockchain. This guide assumes familiarity with NoirJS, solidity verifiers, and the Barretenberg proving backend. Discover how to generate both final and intermediate proofs using `noir_js` and `backend_barretenberg`. +keywords: + [ + "NoirJS", + "EVM blockchain", + "smart contracts", + "recursion", + "solidity verifiers", + "Barretenberg backend", + "noir_js", + "backend_barretenberg", + "intermediate proofs", + "final proofs", + "nargo compile", + "json import", + "recursive circuit", + "recursive app" + ] +sidebar_position: 1 +--- + +This guide shows you how to use recursive proofs in your NoirJS app. For the sake of clarity, it is assumed that: + +- You already have a NoirJS app. If you don't, please visit the [NoirJS tutorial](../tutorials/noirjs_app.md) and the [reference](../reference/NoirJS/noir_js/index.md). +- You are familiar with what are recursive proofs and you have read the [recursion explainer](../explainers/explainer-recursion.md) +- You already built a recursive circuit following [the reference](../noir/standard_library/recursion.md), and understand how it works. + +It is also assumed that you're not using `noir_wasm` for compilation, and instead you've used [`nargo compile`](../reference/nargo_commands.md) to generate the `json` you're now importing into your project. However, the guide should work just the same if you're using `noir_wasm`. + +:::info + +As you've read in the [explainer](../explainers/explainer-recursion.md), a recursive proof is an intermediate proof. This means that it doesn't necessarily generate the final step that makes it verifiable in a smart contract. However, it is easy to verify within another circuit. + +While "standard" usage of NoirJS packages abstracts final proofs, it currently lacks the necessary interface to abstract away intermediate proofs. This means that these proofs need to be created by using the backend directly. + +In short: + +- `noir_js` generates *only* final proofs +- `backend_barretenberg` generates both types of proofs + +::: + +In a standard recursive app, you're also dealing with at least two circuits. For the purpose of this guide, we will assume the following: + +- `main`: a circuit of type `assert(x != y)`, where `main` is marked with a `#[recursive]` attribute. This attribute states that the backend should generate proofs that are friendly for verification within another circuit. +- `recursive`: a circuit that verifies `main` + +For a full example on how recursive proofs work, please refer to the [noir-examples](https://github.com/noir-lang/noir-examples) repository. We will *not* be using it as a reference for this guide. + +## Step 1: Setup + +In a common NoirJS app, you need to instantiate a backend with something like `const backend = new Backend(circuit)`. Then you feed it to the `noir_js` interface. + +For recursion, this doesn't happen, and the only need for `noir_js` is only to `execute` a circuit and get its witness and return value. Everything else is not interfaced, so it needs to happen on the `backend` object. + +It is also recommended that you instantiate the backend with as many threads as possible, to allow for maximum concurrency: + +```js +const backend = new Backend(circuit, { threads: 8 }) +``` + +:::tip +You can use the [`os.cpus()`](https://nodejs.org/api/os.html#oscpus) object in `nodejs` or [`navigator.hardwareConcurrency`](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/hardwareConcurrency) on the browser to make the most out of those glorious cpu cores +::: + +## Step 2: Generating the witness and the proof for `main` + +After instantiating the backend, you should also instantiate `noir_js`. We will use it to execute the circuit and get the witness. + +```js +const noir = new Noir(circuit, backend) +const { witness } = noir.execute(input) +``` + +With this witness, you are now able to generate the intermediate proof for the main circuit: + +```js +const { proof, publicInputs } = await backend.generateProof(witness) +``` + +:::warning + +Always keep in mind what is actually happening on your development process, otherwise you'll quickly become confused about what circuit we are actually running and why! + +In this case, you can imagine that Alice (running the `main` circuit) is proving something to Bob (running the `recursive` circuit), and Bob is verifying her proof within his proof. + +With this in mind, it becomes clear that our intermediate proof is the one *meant to be verified within another circuit*, so it must be Alice's. Actually, the only final proof in this theoretical scenario would be the last one, sent on-chain. + +::: + +## Step 3 - Verification and proof artifacts + +Optionally, you are able to verify the intermediate proof: + +```js +const verified = await backend.verifyProof({ proof, publicInputs }) +``` + +This can be useful to make sure our intermediate proof was correctly generated. But the real goal is to do it within another circuit. For that, we need to generate recursive proof artifacts that will be passed to the circuit that is verifying the proof we just generated. Instead of passing the proof and verification key as a byte array, we pass them as fields which makes it cheaper to verify in a circuit: + +```js +const { proofAsFields, vkAsFields, vkHash } = await backend.generateRecursiveProofArtifacts( { publicInputs, proof }, publicInputsCount) +``` + +This call takes the public inputs and the proof, but also the public inputs count. While this is easily retrievable by simply counting the `publicInputs` length, the backend interface doesn't currently abstract it away. + +:::info + +The `proofAsFields` has a constant size `[Field; 93]` and verification keys in Barretenberg are always `[Field; 114]`. + +::: + +:::warning + +One common mistake is to forget *who* makes this call. + +In a situation where Alice is generating the `main` proof, if she generates the proof artifacts and sends them to Bob, which gladly takes them as true, this would mean Alice could prove anything! + +Instead, Bob needs to make sure *he* extracts the proof artifacts, using his own instance of the `main` circuit backend. This way, Alice has to provide a valid proof for the correct `main` circuit. + +::: + +## Step 4 - Recursive proof generation + +With the artifacts, generating a recursive proof is no different from a normal proof. You simply use the `backend` (with the recursive circuit) to generate it: + +```js +const recursiveInputs = { + verification_key: vkAsFields, // array of length 114 + proof: proofAsFields, // array of length 93 + size of public inputs + publicInputs: [mainInput.y], // using the example above, where `y` is the only public input + key_hash: vkHash, +} + +const { witness, returnValue } = noir.execute(recursiveInputs) // we're executing the recursive circuit now! +const { proof, publicInputs } = backend.generateProof(witness) +const verified = backend.verifyProof({ proof, publicInputs }) +``` + +You can obviously chain this proof into another proof. In fact, if you're using recursive proofs, you're probably interested of using them this way! + +:::tip + +Managing circuits and "who does what" can be confusing. To make sure your naming is consistent, you can keep them in an object. For example: + +```js +const circuits = { + main: mainJSON, + recursive: recursiveJSON +} +const backends = { + main: new BarretenbergBackend(circuits.main), + recursive: new BarretenbergBackend(circuits.recursive) +} +const noir_programs = { + main: new Noir(circuits.main, backends.main), + recursive: new Noir(circuits.recursive, backends.recursive) +} +``` + +This allows you to neatly call exactly the method you want without conflicting names: + +```js +// Alice runs this 👇 +const { witness: mainWitness } = await noir_programs.main.execute(input) +const proof = await backends.main.generateProof(mainWitness) + +// Bob runs this 👇 +const verified = await backends.main.verifyProof(proof) +const { proofAsFields, vkAsFields, vkHash } = await backends.main.generateRecursiveProofArtifacts( + proof, + numPublicInputs, +); +const recursiveProof = await noir_programs.recursive.generateProof(recursiveInputs) +``` + +::: diff --git a/docs/versioned_docs/version-v0.28.0/how_to/how-to-solidity-verifier.md b/docs/versioned_docs/version-v0.28.0/how_to/how-to-solidity-verifier.md new file mode 100644 index 00000000000..e3c7c1065da --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/how_to/how-to-solidity-verifier.md @@ -0,0 +1,231 @@ +--- +title: Generate a Solidity Verifier +description: + Learn how to run the verifier as a smart contract on the blockchain. Compile a Solidity verifier + contract for your Noir program and deploy it on any EVM blockchain acting as a verifier smart + contract. Read more to find out +keywords: + [ + solidity verifier, + smart contract, + blockchain, + compiler, + plonk_vk.sol, + EVM blockchain, + verifying Noir programs, + proving backend, + Barretenberg, + ] +sidebar_position: 0 +pagination_next: tutorials/noirjs_app +--- + +Noir has the ability to generate a verifier contract in Solidity, which can be deployed in many EVM-compatible blockchains such as Ethereum. + +This allows for a powerful feature set, as one can make use of the conciseness and the privacy provided by Noir in an immutable ledger. Applications can range from simple P2P guessing games, to complex private DeFi interactions. + +This guide shows you how to generate a Solidity Verifier and deploy it on the [Remix IDE](https://remix.ethereum.org/). It is assumed that: + +- You are comfortable with the Solidity programming language and understand how contracts are deployed on the Ethereum network +- You have Noir installed and you have a Noir program. If you don't, [get started](../getting_started/installation/index.md) with Nargo and the example Hello Noir circuit +- You are comfortable navigating RemixIDE. If you aren't or you need a refresher, you can find some video tutorials [here](https://www.youtube.com/channel/UCjTUPyFEr2xDGN6Cg8nKDaA) that could help you. + +## Rundown + +Generating a Solidity Verifier contract is actually a one-command process. However, compiling it and deploying it can have some caveats. Here's the rundown of this guide: + +1. How to generate a solidity smart contract +2. How to compile the smart contract in the RemixIDE +3. How to deploy it to a testnet + +## Step 1 - Generate a contract + +This is by far the most straight-forward step. Just run: + +```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 to any EVM blockchain acting as a verifier smart contract. + +:::info + +It is possible to generate 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 generation of verifier contracts, for the time being these are only in Solidity. +::: + +## Step 2 - Compiling + +We will mostly skip the details of RemixIDE, as the UI can change from version to version. For now, we can just open +Remix and create a blank workspace. + +![Create Workspace](@site/static/img/how-tos/solidity_verifier_1.png) + +We will create a new file to contain the contract Nargo generated, and copy-paste its content. + +:::warning + +You'll likely see a warning advising you to not trust pasted code. While it is an important warning, it is irrelevant in the context of this guide and can be ignored. We will not be deploying anywhere near a mainnet. + +::: + +To compile our the verifier, we can navigate to the compilation tab: + +![Compilation Tab](@site/static/img/how-tos/solidity_verifier_2.png) + +Remix should automatically match a suitable compiler version. However, hitting the "Compile" button will most likely generate a "Stack too deep" error: + +![Stack too deep](@site/static/img/how-tos/solidity_verifier_3.png) + +This is due to the verify function needing to put many variables on the stack, but enabling the optimizer resolves the issue. To do this, let's open the "Advanced Configurations" tab and enable optimization. The default 200 runs will suffice. + +:::info + +This time we will see a warning about an unused function parameter. This is expected, as the `verify` function doesn't use the `_proof` parameter inside a solidity block, it is loaded from calldata and used in assembly. + +::: + +![Compilation success](@site/static/img/how-tos/solidity_verifier_4.png) + +## Step 3 - Deploying + +At this point we should have a compiled contract read to deploy. If we navigate to the deploy section in Remix, we will see many different environments we can deploy to. The steps to deploy on each environment would be out-of-scope for this guide, so we will just use the default Remix VM. + +Looking closely, we will notice that our "Solidity Verifier" is actually three contracts working together: + +- An `UltraVerificationKey` library which simply stores the verification key for our circuit. +- An abstract contract `BaseUltraVerifier` containing most of the verifying logic. +- A main `UltraVerifier` contract that inherits from the Base and uses the Key contract. + +Remix will take care of the dependencies for us so we can simply deploy the UltraVerifier contract by selecting it and hitting "deploy": + +![Deploying UltraVerifier](@site/static/img/how-tos/solidity_verifier_5.png) + +A contract will show up in the "Deployed Contracts" section, where we can retrieve the Verification Key Hash. This is particularly useful for double-checking the deployer contract is the correct one. + +:::note + +Why "UltraVerifier"? + +To be precise, the Noir compiler (`nargo`) doesn't generate the verifier contract directly. It compiles the Noir code into an intermediate language (ACIR), which is then executed by the backend. So it is the backend that returns the verifier smart contract, not Noir. + +In this case, the Barretenberg Backend uses the UltraPlonk proving system, hence the "UltraVerifier" name. + +::: + +## Step 4 - Verifying + +To verify a proof using the Solidity verifier contract, we call the `verify` function in this extended contract: + +```solidity +function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool) +``` + +When using the default example in the [Hello Noir](../getting_started/hello_noir/index.md) guide, the easiest way to confirm that the verifier contract is doing its job is by calling the `verify` function via remix with the required parameters. For `_proof`, run `nargo prove` and use the string in `proof/.proof` (adding the hex `0x` prefix). We can also copy the public input from `Verifier.toml`, as it will be properly formatted as 32-byte strings: + +``` +0x...... , [0x0000.....02] +``` + +A programmatic example of how the `verify` function is called can be seen 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"); +``` + +:::info[Return Values] + +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. + +For example, if you have Noir program like this: + +```rust +fn main( + // Public inputs + pubkey_x: pub Field, + pubkey_y: pub Field, + // Private inputs + priv_key: Field, +) -> pub Field +``` + +the `verify` function will expect the public inputs array (second function parameter) to be of length 3, the two inputs and the return value. Like before, these values are populated in Verifier.toml after running `nargo prove`. + +Passing only two inputs will result in an error such as `PUBLIC_INPUT_COUNT_INVALID(3, 2)`. + +In this case, the inputs parameter to `verify` would be an array ordered as `[pubkey_x, pubkey_y, return]`. + +::: + +:::tip[Structs] + +You can pass structs to the verifier contract. They will be flattened so that the array of inputs is 1-dimensional array. + +For example, 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) { + //... +} +``` + +The order of these inputs would be flattened to: `[x, nested.t1.val1, nested.t1.val2, nested.is_true, y]` + +::: + +The other function you can call is our entrypoint `verify` function, as defined above. + +:::tip + +It's worth noticing that the `verify` function is actually a `view` function. A `view` function does not alter the blockchain state, so it doesn't need to be distributed (i.e. it will run only on the executing node), and therefore doesn't cost any gas. + +This can be particularly useful in some situations. If Alice generated a proof and wants Bob to verify its correctness, Bob doesn't need to run Nargo, NoirJS, or any Noir specific infrastructure. He can simply make a call to the blockchain with the proof and verify it is correct without paying any gas. + +It would be incorrect to say that a Noir proof verification costs any gas at all. However, most of the time the result of `verify` is used to modify state (for example, to update a balance, a game state, etc). In that case the whole network needs to execute it, which does incur gas costs (calldata and execution, but not storage). + +::: + +## A Note on EVM chains + +ZK-SNARK verification depends on some precompiled cryptographic primitives such as Elliptic Curve Pairings (if you like complex math, you can read about EC Pairings [here](https://medium.com/@VitalikButerin/exploring-elliptic-curve-pairings-c73c1864e627)). Not all EVM chains support EC Pairings, notably some of the ZK-EVMs. This means that you won't be able to use the verifier contract in all of them. + +For example, chains like `zkSync ERA` and `Polygon zkEVM` do not currently support these precompiles, so proof verification via Solidity verifier contracts won't work. Here's a quick list of EVM chains that have been tested and are known to work: + +- Optimism +- Arbitrum +- Polygon PoS +- Scroll +- Celo + +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. + +## What's next + +Now that you know how to call a Noir Solidity Verifier on a smart contract using Remix, you should be comfortable with using it with some programmatic frameworks, such as [hardhat](https://github.com/noir-lang/noir-starter/tree/main/vite-hardhat) and [foundry](https://github.com/noir-lang/noir-starter/tree/main/with-foundry). + +You can find other tools, examples, boilerplates and libraries in the [awesome-noir](https://github.com/noir-lang/awesome-noir) repository. + +You should also be ready to write and deploy your first NoirJS app and start generating proofs on websites, phones, and NodeJS environments! Head on to the [NoirJS tutorial](../tutorials/noirjs_app.md) to learn how to do that. diff --git a/docs/versioned_docs/version-v0.28.0/how_to/merkle-proof.mdx b/docs/versioned_docs/version-v0.28.0/how_to/merkle-proof.mdx new file mode 100644 index 00000000000..16c425bed76 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/how_to/merkle-proof.mdx @@ -0,0 +1,49 @@ +--- +title: Prove Merkle Tree Membership +description: + Learn how to use merkle membership proof in Noir to prove that a given leaf is a member of a + merkle tree with a specified root, at a given index. +keywords: + [merkle proof, merkle membership proof, Noir, rust, hash function, Pedersen, sha256, merkle tree] +sidebar_position: 4 +--- + +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.as_slice()); + 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.as_slice()); +``` + +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.28.0/how_to/using-devcontainers.mdx b/docs/versioned_docs/version-v0.28.0/how_to/using-devcontainers.mdx new file mode 100644 index 00000000000..727ec6ca667 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/how_to/using-devcontainers.mdx @@ -0,0 +1,110 @@ +--- +title: Developer Containers and Codespaces +description: "Learn how to set up a devcontainer in your GitHub repository for a seamless coding experience with Codespaces. Follow our easy 8-step guide to create your own Noir environment without installing Nargo locally." +keywords: ["Devcontainer", "Codespaces", "GitHub", "Noir Environment", "Docker Image", "Development Environment", "Remote Coding", "GitHub Codespaces", "Noir Programming", "Nargo", "VSCode Extensions", "Noirup"] +sidebar_position: 1 +--- + +Adding a developer container configuration file to your Noir project is one of the easiest way to unlock coding in browser. + +## What's a devcontainer after all? + +A [Developer Container](https://containers.dev/) (devcontainer for short) is a Docker image that comes preloaded with tools, extensions, and other tools you need to quickly get started or continue a project, without having to install Nargo locally. Think of it as a development environment in a box. + +There are many advantages to this: + +- It's platform and architecture agnostic +- You don't need to have an IDE installed, or Nargo, or use a terminal at all +- It's safer for using on a public machine or public network + +One of the best ways of using devcontainers is... not using your machine at all, for maximum control, performance, and ease of use. +Enter Codespaces. + +## Codespaces + +If a devcontainer is just a Docker image, then what stops you from provisioning a `p3dn.24xlarge` AWS EC2 instance with 92 vCPUs and 768 GiB RAM and using it to prove your 10-gate SNARK proof? + +Nothing! Except perhaps the 30-40$ per hour it will cost you. + +The problem is that provisioning takes time, and I bet you don't want to see the AWS console every time you want to code something real quick. + +Fortunately, there's an easy and free way to get a decent remote machine ready and loaded in less than 2 minutes: Codespaces. [Codespaces is a Github feature](https://github.com/features/codespaces) that allows you to code in a remote machine by using devcontainers, and it's pretty cool: + +- You can start coding Noir in less than a minute +- It uses the resources of a remote machine, so you can code on your grandma's phone if needed be +- It makes it easy to share work with your frens +- It's fully reusable, you can stop and restart whenever you need to + +:::info + +Don't take out your wallet just yet. Free GitHub accounts get about [15-60 hours of coding](https://github.com/features/codespaces) for free per month, depending on the size of your provisioned machine. + +::: + +## Tell me it's _actually_ easy + +It is! + +Github comes with a default codespace and you can use it to code your own devcontainer. That's exactly what we will be doing in this guide. + + + +8 simple steps: + +#### 1. Create a new repository on GitHub. + +#### 2. Click "Start coding with Codespaces". This will use the default image. + +#### 3. Create a folder called `.devcontainer` in the root of your repository. + +#### 4. Create a Dockerfile in that folder, and paste the following code: + +```docker +FROM --platform=linux/amd64 node:lts-bookworm-slim +SHELL ["/bin/bash", "-c"] +RUN apt update && apt install -y curl bash git tar gzip libc++-dev +RUN curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash +ENV PATH="/root/.nargo/bin:$PATH" +RUN noirup +ENTRYPOINT ["nargo"] +``` +#### 5. Create a file called `devcontainer.json` in the same folder, and paste the following code: + +```json +{ + "name": "Noir on Codespaces", + "build": { + "context": ".", + "dockerfile": "Dockerfile" + }, + "customizations": { + "vscode": { + "extensions": ["noir-lang.vscode-noir"] + } + } +} +``` +#### 6. Commit and push your changes + +This will pull the new image and build it, so it could take a minute or so + +#### 8. Done! +Just wait for the build to finish, and there's your easy Noir environment. + + +Refer to [noir-starter](https://github.com/noir-lang/noir-starter/) as an example of how devcontainers can be used together with codespaces. + + + +## How do I use it? + +Using the codespace is obviously much easier than setting it up. +Just navigate to your repository and click "Code" -> "Open with Codespaces". It should take a few seconds to load, and you're ready to go. + +:::info + +If you really like the experience, you can add a badge to your readme, links to existing codespaces, and more. +Check out the [official docs](https://docs.github.com/en/codespaces/setting-up-your-project-for-codespaces/setting-up-your-repository/facilitating-quick-creation-and-resumption-of-codespaces) for more info. diff --git a/docs/versioned_docs/version-v0.28.0/index.mdx b/docs/versioned_docs/version-v0.28.0/index.mdx new file mode 100644 index 00000000000..75086ddcdde --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/index.mdx @@ -0,0 +1,67 @@ +--- +title: Noir Lang +hide_title: true +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] +sidebar_position: 0 +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +Noir Logo + +Noir is a Domain-Specific Language for SNARK proving systems developed by [Aztec Labs](https://aztec.network/). It allows you to generate complex Zero-Knowledge Programs (ZKP) by using simple and flexible syntax, requiring no previous knowledge on the underlying mathematics or cryptography. + +ZK programs are programs that can generate short proofs of a certain statement without revealing some details about it. You can read more about ZKPs [here](https://dev.to/spalladino/a-beginners-intro-to-coding-zero-knowledge-proofs-c56). + +## What's new about Noir? + +Noir works differently from most ZK languages by taking a two-pronged path. First, it compiles the program to an adaptable intermediate language known as ACIR. From there, depending on a given project's needs, ACIR can be further compiled into an arithmetic circuit for integration with the proving backend. + +:::info + +Noir is backend agnostic, which means it makes no assumptions on which proving backend powers the ZK proof. Being the language that powers [Aztec Contracts](https://docs.aztec.network/developers/contracts/main), it defaults to Aztec's Barretenberg proving backend. + +However, the ACIR output can be transformed to be compatible with other PLONK-based backends, or into a [rank-1 constraint system](https://www.rareskills.io/post/rank-1-constraint-system) suitable for backends such as Arkwork's Marlin. + +::: + +## Who is Noir for? + +Noir can be used both in complex cloud-based backends and in user's smartphones, requiring no knowledge on the underlying math or cryptography. From authorization systems that keep a password in the user's device, to complex on-chain verification of recursive proofs, Noir is designed to abstract away complexity without any significant overhead. Here are some examples of situations where Noir can be used: + + + + Noir Logo + + Aztec Contracts leverage Noir to allow for the storage and execution of private information. Writing an Aztec Contract is as easy as writing Noir, and Aztec developers can easily interact with the network storage and execution through the [Aztec.nr](https://docs.aztec.network/developers/contracts/main) library. + + + Soliditry Verifier Example + Noir can auto-generate Solidity verifier contracts that verify Noir proofs. This allows for non-interactive verification of proofs containing private information in an immutable system. This feature powers a multitude of use-case scenarios, from P2P chess tournaments, to [Aztec Layer-2 Blockchain](https://docs.aztec.network/) + + + Aztec Labs developed NoirJS, an easy interface to generate and verify Noir proofs in a Javascript environment. This allows for Noir to be used in webpages, mobile apps, games, and any other environment supporting JS execution in a standalone manner. + + + + +## Libraries + +Noir is meant to be easy to extend by simply importing Noir libraries just like in Rust. +The [awesome-noir repo](https://github.com/noir-lang/awesome-noir#libraries) is a collection of libraries developed by the Noir community. +Writing a new library is easy and makes code be composable and easy to reuse. See the section on [dependencies](noir/modules_packages_crates/dependencies.md) for more information. diff --git a/docs/versioned_docs/version-v0.28.0/migration_notes.md b/docs/versioned_docs/version-v0.28.0/migration_notes.md new file mode 100644 index 00000000000..6bd740024e5 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/migration_notes.md @@ -0,0 +1,105 @@ +--- +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. + +### `backend encountered an error: libc++.so.1` + +Depending on your OS, you may encounter the following error when running `nargo prove` for the first time: + +```text +The backend encountered an error: "/home/codespace/.nargo/backends/acvm-backend-barretenberg/backend_binary: error while loading shared libraries: libc++.so.1: cannot open shared object file: No such file or directory\n" +``` + +Install the `libc++-dev` library with: + +```bash +sudo apt install libc++-dev +``` + +## ≥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](noir/concepts/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 your 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 file is running [this bash script](https://github.com/noir-lang/barretenberg-js-binary/blob/master/run-bb-js.sh), where we need to gzip it as the Nargo currently expect the backend to be zipped up. + +Then run: + +``` +DESIRED_BINARY_VERSION=0.8.1 nargo info +``` + +This overrides the bb native binary with a bb.js node application instead, which should be compatible with most if not all hardware. This does come with the drawback of being generally slower than native binary. + +0.8.1 indicates bb.js version 0.8.1, so if you change that it will update to a different version or the default version in the script if none was supplied. diff --git a/docs/versioned_docs/version-v0.28.0/noir/concepts/_category_.json b/docs/versioned_docs/version-v0.28.0/noir/concepts/_category_.json new file mode 100644 index 00000000000..7da08f8a8c5 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/noir/concepts/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Concepts", + "position": 0, + "collapsible": true, + "collapsed": true +} \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.28.0/noir/concepts/assert.md b/docs/versioned_docs/version-v0.28.0/noir/concepts/assert.md new file mode 100644 index 00000000000..bcff613a695 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/noir/concepts/assert.md @@ -0,0 +1,45 @@ +--- +title: Assert Function +description: + Learn about the assert function in Noir, which can be used to explicitly constrain the predicate or + comparison expression that follows to be true, and what happens if the expression is false at + runtime. +keywords: [Noir programming language, assert statement, predicate expression, comparison expression] +sidebar_position: 4 +--- + +Noir includes a special `assert` function which will explicitly constrain the predicate/comparison +expression that follows to be true. If this expression is false at runtime, the program will fail to +be proven. Example: + +```rust +fn main(x : Field, y : Field) { + assert(x == y); +} +``` + +> 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`. + +You can optionally provide a message to be logged when the assertion fails: + +```rust +assert(x == y, "x and y are not equal"); +``` + +Aside string literals, the optional message can be a format string or any other type supported as input for Noir's [print](../standard_library/logging.md) functions. This feature lets you incorporate runtime variables into your failed assertion logs: + +```rust +assert(x == y, f"Expected x == y, but got {x} == {y}"); +``` + +Using a variable as an assertion message directly: + +```rust +struct myStruct { + myField: Field +} + +let s = myStruct { myField: y }; +assert(s.myField == x, s); +``` + diff --git a/docs/versioned_docs/version-v0.28.0/noir/concepts/comments.md b/docs/versioned_docs/version-v0.28.0/noir/concepts/comments.md new file mode 100644 index 00000000000..b51a85f5c94 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/noir/concepts/comments.md @@ -0,0 +1,33 @@ +--- +title: Comments +description: + Learn how to write comments in Noir programming language. A comment is a line of code that is + ignored by the compiler, but it can be read by programmers. Single-line and multi-line comments + are supported in Noir. +keywords: [Noir programming language, comments, single-line comments, multi-line comments] +sidebar_position: 10 +--- + +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.28.0/noir/concepts/control_flow.md b/docs/versioned_docs/version-v0.28.0/noir/concepts/control_flow.md new file mode 100644 index 00000000000..045d3c3a5f5 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/noir/concepts/control_flow.md @@ -0,0 +1,77 @@ +--- +title: Control Flow +description: + Learn how to use loops and if expressions in the Noir programming language. Discover the syntax + and examples for for loops and if-else statements. +keywords: [Noir programming language, loops, for loop, if-else statements, Rust syntax] +sidebar_position: 2 +--- + +## 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); +``` + +## 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`. + +### Break and Continue + +In unconstrained code, `break` and `continue` are also allowed in `for` loops. These are only allowed +in unconstrained code since normal constrained code requires that Noir knows exactly how many iterations +a loop may have. `break` and `continue` can be used like so: + +```rust +for i in 0 .. 10 { + println("Iteration start") + + if i == 2 { + continue; + } + + if i == 5 { + break; + } + + println(i); +} +println("Loop end") +``` + +When used, `break` will end the current loop early and jump to the statement after the for loop. In the example +above, the `break` will stop the loop and jump to the `println("Loop end")`. + +`continue` will stop the current iteration of the loop, and jump to the start of the next iteration. In the example +above, `continue` will jump to `println("Iteration start")` when used. Note that the loop continues as normal after this. +The iteration variable `i` is still increased by one as normal when `continue` is used. + +`break` and `continue` cannot currently be used to jump out of more than a single loop at a time. diff --git a/docs/versioned_docs/version-v0.28.0/noir/concepts/data_bus.md b/docs/versioned_docs/version-v0.28.0/noir/concepts/data_bus.md new file mode 100644 index 00000000000..e54fc861257 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/noir/concepts/data_bus.md @@ -0,0 +1,21 @@ +--- +title: Data Bus +sidebar_position: 13 +--- +**Disclaimer** this feature is experimental, do not use it! + +The data bus is an optimization that the backend can use to make recursion more efficient. +In order to use it, you must define some inputs of the program entry points (usually the `main()` +function) with the `call_data` modifier, and the return values with the `return_data` modifier. +These modifiers are incompatible with `pub` and `mut` modifiers. + +## Example + +```rust +fn main(mut x: u32, y: call_data u32, z: call_data [u32;4] ) -> return_data u32 { + let a = z[x]; + a+y +} +``` + +As a result, both call_data and return_data will be treated as private inputs and encapsulated into a read-only array each, for the backend to process. diff --git a/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/_category_.json b/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/_category_.json new file mode 100644 index 00000000000..5d694210bbf --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 0, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/arrays.md b/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/arrays.md new file mode 100644 index 00000000000..efce3e95d32 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/arrays.md @@ -0,0 +1,251 @@ +--- +title: Arrays +description: + Dive into the Array data type in Noir. Grasp its methods, practical examples, and best practices for efficiently using Arrays in your Noir code. +keywords: + [ + noir, + array type, + methods, + examples, + indexing, + ] +sidebar_position: 4 +--- + +An array is one way of grouping together values into one compound type. Array types can be inferred +or explicitly specified via the syntax `[; ]`: + +```rust +fn main(x : Field, y : Field) { + let my_arr = [x, y]; + let your_arr: [Field; 2] = [x, y]; +} +``` + +Here, both `my_arr` and `your_arr` are instantiated as an array containing two `Field` elements. + +Array elements can be accessed using indexing: + +```rust +fn main() { + let a = [1, 2, 3, 4, 5]; + + let first = a[0]; + let second = a[1]; +} +``` + +All elements in an array must be of the same type (i.e. homogeneous). That is, an array cannot group +a `Field` value and a `u8` value together for example. + +You can write mutable arrays, like: + +```rust +fn main() { + let mut arr = [1, 2, 3, 4, 5]; + assert(arr[0] == 1); + + arr[0] = 42; + assert(arr[0] == 42); +} +``` + +You can instantiate a new array of a fixed size with the same value repeated for each element. The following example instantiates an array of length 32 where each element is of type Field and has the value 0. + +```rust +let array: [Field; 32] = [0; 32]; +``` + +Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices), you can just call `as_slice` on your array: + +```rust +let array: [Field; 32] = [0; 32]; +let sl = array.as_slice() +``` + +You can define multidimensional arrays: + +```rust +let array : [[Field; 2]; 2]; +let element = array[0][0]; +``` +However, multidimensional slices are not supported. For example, the following code will error at compile time: +```rust +let slice : [[Field]] = &[]; +``` + +## 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. +Each of these functions are located within the generic impl `impl [T; N] {`. +So anywhere `self` appears, it refers to the variable `self: [T; N]`. + +### len + +Returns the length of an array + +```rust +fn len(self) -> 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(self) -> [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(self, 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(self, 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(self, 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(self, 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(self, 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(self, 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.28.0/noir/concepts/data_types/booleans.md b/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/booleans.md new file mode 100644 index 00000000000..69826fcd724 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/booleans.md @@ -0,0 +1,31 @@ +--- +title: Booleans +description: + Delve into the Boolean data type in Noir. Understand its methods, practical examples, and best practices for using Booleans in your Noir programs. +keywords: + [ + noir, + boolean type, + methods, + examples, + logical operations, + ] +sidebar_position: 2 +--- + + +The `bool` type in Noir has two possible values: `true` and `false`: + +```rust +fn main() { + let t = true; + let f: bool = false; +} +``` + +> **Note:** When returning a boolean value, it will show up as a value of 1 for `true` and 0 for +> `false` in _Verifier.toml_. + +The boolean type is most commonly used in conditionals like `if` expressions and `assert` +statements. More about conditionals is covered in the [Control Flow](../control_flow) and +[Assert Function](../assert) sections. diff --git a/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/fields.md b/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/fields.md new file mode 100644 index 00000000000..a10a4810788 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/fields.md @@ -0,0 +1,192 @@ +--- +title: Fields +description: + Dive deep into the Field data type in Noir. Understand its methods, practical examples, and best practices to effectively use Fields in your Noir programs. +keywords: + [ + noir, + field type, + methods, + examples, + best practices, + ] +sidebar_position: 0 +--- + +The field type corresponds to the native field type of the proving backend. + +The size of a Noir field depends on the elliptic curve's finite field for the proving backend +adopted. For example, a field would be a 254-bit integer when paired with the default backend that +spans the Grumpkin curve. + +Fields support integer arithmetic and are often used as the default numeric type in Noir: + +```rust +fn main(x : Field, y : Field) { + let z = x + y; +} +``` + +`x`, `y` and `z` are all private fields in this example. Using the `let` keyword we defined a new +private value `z` constrained to be equal to `x + y`. + +If proving efficiency is of priority, fields should be used as a default for solving problems. +Smaller integer types (e.g. `u64`) incur extra range constraints. + +## Methods + +After declaring a Field, you can use these common methods on it: + +### to_le_bits + +Transforms the field into an array of bits, Little Endian. + +```rust +fn to_le_bits(_x : Field, _bit_size: u32) -> [u1] +``` + +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] +``` + +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); +} +``` + +### assert_max_bit_size + +Adds a constraint to specify that the field can be represented with `bit_size` number of bits + +```rust +fn assert_max_bit_size(self, bit_size: u32) +``` + +example: + +```rust +fn main() { + let field = 2 + field.assert_max_bit_size(32); +} +``` + +### 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 +``` + + +### lt + +Returns true if the field is less than the other field + +```rust +pub fn lt(self, another: Field) -> bool +``` diff --git a/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/function_types.md b/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/function_types.md new file mode 100644 index 00000000000..f6121af17e2 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/function_types.md @@ -0,0 +1,26 @@ +--- +title: Function types +sidebar_position: 10 +--- + +Noir supports higher-order functions. The syntax for a function type is as follows: + +```rust +fn(arg1_type, arg2_type, ...) -> return_type +``` + +Example: + +```rust +fn assert_returns_100(f: fn() -> Field) { // f takes no args and returns a Field + assert(f() == 100); +} + +fn main() { + assert_returns_100(|| 100); // ok + assert_returns_100(|| 150); // fails +} +``` + +A function type also has an optional capture environment - this is necessary to support closures. +See [Lambdas](../lambdas.md) for more details. diff --git a/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/index.md b/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/index.md new file mode 100644 index 00000000000..357813c147a --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/index.md @@ -0,0 +1,110 @@ +--- +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](../generics.md): + +```rust +type Id = Size; + +fn main() { + let id: Id = 1; + let zero: u32 = 0; + assert(zero + 1 == id); +} +``` + +Type aliases can even refer to other aliases. An error will be issued if they form a cycle: + +```rust +// Ok! +type A = B; +type B = Field; + +type Bad1 = Bad2; + +// error: Dependency cycle found +type Bad2 = Bad1; +// ^^^^^^^^^^^ 'Bad2' recursively depends on itself: Bad2 -> Bad1 -> Bad2 +``` + +### BigInt + +You can achieve BigInt functionality using the [Noir BigInt](https://github.com/shuklaayush/noir-bigint) library. diff --git a/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/integers.md b/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/integers.md new file mode 100644 index 00000000000..1c6b375db49 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/integers.md @@ -0,0 +1,155 @@ +--- +title: Integers +description: Explore the Integer data type in Noir. Learn about its methods, see real-world examples, and grasp how to efficiently use Integers in your Noir code. +keywords: [noir, integer types, methods, examples, arithmetic] +sidebar_position: 1 +--- + +An integer type is a range constrained field type. The Noir frontend supports both unsigned and signed integer types. The allowed sizes are 1, 8, 32 and 64 bits. + +:::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\\$). + +## 128 bits Unsigned Integers + +The built-in structure `U128` allows you to use 128-bit unsigned integers almost like a native integer type. However, there are some differences to keep in mind: +- You cannot cast between a native integer and `U128` +- There is a higher performance cost when using `U128`, compared to a native type. + +Conversion between unsigned integer types and U128 are done through the use of `from_integer` and `to_integer` functions. `from_integer` also accepts the `Field` type as input. + +```rust +fn main() { + let x = U128::from_integer(23); + let y = U128::from_hex("0x7"); + let z = x + y; + assert(z.to_integer() == 30); +} +``` + +`U128` is implemented with two 64 bits limbs, representing the low and high bits, which explains the performance cost. You should expect `U128` to be twice more costly for addition and four times more costly for multiplication. +You can construct a U128 from its limbs: +```rust +fn main(x: u64, y: u64) { + let x = U128::from_u64s_be(x,y); + assert(z.hi == x as Field); + assert(z.lo == y as Field); +} +``` + +Note that the limbs are stored as Field elements in order to avoid unnecessary conversions. +Apart from this, most operations will work as usual: + +```rust +fn main(x: U128, y: U128) { + // multiplication + let c = x * y; + // addition and subtraction + let c = c - x + y; + // division + let c = x / y; + // bit operation; + let c = x & y | y; + // bit shift + let c = x << y; + // comparisons; + let c = x < y; + let c = x == y; +} +``` + +## 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.28.0/noir/concepts/data_types/references.md b/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/references.md new file mode 100644 index 00000000000..a5293d11cfb --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/references.md @@ -0,0 +1,23 @@ +--- +title: References +sidebar_position: 9 +--- + +Noir supports first-class references. References are a bit like pointers: they point to a specific address that can be followed to access the data stored at that address. You can use Rust-like syntax to use pointers in Noir: the `&` operator references the variable, the `*` operator dereferences it. + +Example: + +```rust +fn main() { + let mut x = 2; + + // you can reference x as &mut and pass it to multiplyBy2 + multiplyBy2(&mut x); +} + +// you can access &mut here +fn multiplyBy2(x: &mut Field) { + // and dereference it with * + *x = *x * 2; +} +``` diff --git a/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/slices.mdx b/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/slices.mdx new file mode 100644 index 00000000000..4eccc677b80 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/slices.mdx @@ -0,0 +1,195 @@ +--- +title: Slices +description: Explore the Slice data type in Noir. Understand its methods, see real-world examples, and learn how to effectively use Slices in your Noir programs. +keywords: [noir, slice type, methods, examples, subarrays] +sidebar_position: 5 +--- + +import Experimental from '@site/src/components/Notes/_experimental.mdx'; + + + +A slice is a dynamically-sized view into a sequence of elements. They can be resized at runtime, but because they don't own the data, they cannot be returned from a circuit. You can treat slices as arrays without a constrained size. + +```rust +use dep::std::slice; + +fn main() -> pub Field { + let mut slice: [Field] = &[0; 2]; + + let mut new_slice = slice.push_back(6); + new_slice.len() +} +``` + +To write a slice literal, use a preceeding ampersand as in: `&[0; 2]` or +`&[1, 2, 3]`. + +It is important to note that slices are not references to arrays. In Noir, +`&[..]` is more similar to an immutable, growable vector. + +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); +``` + +### len + +Returns the length of a slice + +```rust +fn len(self) -> Field +``` + +Example: + +```rust +fn main() { + let slice = &[42, 42]; + assert(slice.len() == 2); +} +``` + +### as_array + +Converts this slice into an array. + +Make sure to specify the size of the resulting array. +Panics if the resulting array length is different than the slice's length. + +```rust +fn as_array(self) -> [T; N] +``` + +Example: + +```rust +fn main() { + let slice = &[5, 6]; + + // Always specify the length of the resulting array! + let array: [Field; 2] = slice.as_array(); + + assert(array[0] == slice[0]); + assert(array[1] == slice[1]); +} +``` diff --git a/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/strings.md b/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/strings.md new file mode 100644 index 00000000000..311dfd64416 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/strings.md @@ -0,0 +1,80 @@ +--- +title: Strings +description: + Discover the String data type in Noir. Learn about its methods, see real-world examples, and understand how to effectively manipulate and use Strings in Noir. +keywords: + [ + noir, + string type, + methods, + examples, + concatenation, + ] +sidebar_position: 3 +--- + + +The string type is a fixed length value defined with `str`. + +You can use strings in `assert()` functions or print them with +`println()`. See more about [Logging](../../standard_library/logging). + +```rust +use dep::std; + +fn main(message : pub str<11>, hex_as_string : str<4>) { + println(message); + assert(message == "hello world"); + assert(hex_as_string == "0x41"); +} +``` + +You can convert a `str` to a byte array by calling `as_bytes()` +or a vector by calling `as_bytes_vec()`. + +```rust +fn main() { + let message = "hello world"; + let message_bytes = message.as_bytes(); + let mut message_vec = message.as_bytes_vec(); + assert(message_bytes.len() == 11); + assert(message_bytes[0] == 104); + assert(message_bytes[0] == message_vec.get(0)); +} +``` + +## Escape characters + +You can use escape characters for your strings: + +| Escape Sequence | Description | +|-----------------|-----------------| +| `\r` | Carriage Return | +| `\n` | Newline | +| `\t` | Tab | +| `\0` | Null Character | +| `\"` | Double Quote | +| `\\` | Backslash | + +Example: + +```rust +let s = "Hello \"world" // prints "Hello "world" +let s = "hey \tyou"; // prints "hey you" +``` + +## Raw strings + +A raw string begins with the letter `r` and is optionally delimited by a number of hashes `#`. + +Escape characters are *not* processed within raw strings. All contents are interpreted literally. + +Example: + +```rust +let s = r"Hello world"; +let s = r#"Simon says "hello world""#; + +// Any number of hashes may be used (>= 1) as long as the string also terminates with the same number of hashes +let s = r#####"One "#, Two "##, Three "###, Four "####, Five will end the string."#####; +``` diff --git a/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/structs.md b/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/structs.md new file mode 100644 index 00000000000..dbf68c99813 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/structs.md @@ -0,0 +1,70 @@ +--- +title: Structs +description: + Explore the Struct data type in Noir. Learn about its methods, see real-world examples, and grasp how to effectively define and use Structs in your Noir programs. +keywords: + [ + noir, + struct type, + methods, + examples, + data structures, + ] +sidebar_position: 8 +--- + +A struct also allows for grouping multiple values of different types. Unlike tuples, we can also +name each field. + +> **Note:** The usage of _field_ here refers to each element of the struct and is unrelated to the +> field type of Noir. + +Defining a struct requires giving it a name and listing each field within as `: ` pairs: + +```rust +struct Animal { + hands: Field, + legs: Field, + eyes: u8, +} +``` + +An instance of a struct can then be created with actual values in `: ` pairs in any +order. Struct fields are accessible using their given names: + +```rust +fn main() { + let legs = 4; + + let dog = Animal { + eyes: 2, + hands: 0, + legs, + }; + + let zero = dog.hands; +} +``` + +Structs can also be destructured in a pattern, binding each field to a new variable: + +```rust +fn main() { + let Animal { hands, legs: feet, eyes } = get_octopus(); + + let ten = hands + feet + eyes as u8; +} + +fn get_octopus() -> Animal { + let octopus = Animal { + hands: 0, + legs: 8, + eyes: 2, + }; + + octopus +} +``` + +The new variables can be bound with names different from the original struct field names, as +showcased in the `legs --> feet` binding in the example above. diff --git a/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/tuples.md b/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/tuples.md new file mode 100644 index 00000000000..2ec5c9c4113 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/tuples.md @@ -0,0 +1,48 @@ +--- +title: Tuples +description: + Dive into the Tuple data type in Noir. Understand its methods, practical examples, and best practices for efficiently using Tuples in your Noir code. +keywords: + [ + noir, + tuple type, + methods, + examples, + multi-value containers, + ] +sidebar_position: 7 +--- + +A tuple collects multiple values like an array, but with the added ability to collect values of +different types: + +```rust +fn main() { + let tup: (u8, u64, Field) = (255, 500, 1000); +} +``` + +One way to access tuple elements is via destructuring using pattern matching: + +```rust +fn main() { + let tup = (1, 2); + + let (one, two) = tup; + + let three = one + two; +} +``` + +Another way to access tuple elements is via direct member access, using a period (`.`) followed by +the index of the element we want to access. Index `0` corresponds to the first tuple element, `1` to +the second and so on: + +```rust +fn main() { + let tup = (5, 6, 7, 8); + + let five = tup.0; + let eight = tup.3; +} +``` diff --git a/docs/versioned_docs/version-v0.28.0/noir/concepts/distinct.md b/docs/versioned_docs/version-v0.28.0/noir/concepts/distinct.md new file mode 100644 index 00000000000..6c993b8b5e0 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/noir/concepts/distinct.md @@ -0,0 +1,64 @@ +--- +title: Distinct Witnesses +sidebar_position: 11 +--- + +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.28.0/noir/concepts/functions.md b/docs/versioned_docs/version-v0.28.0/noir/concepts/functions.md new file mode 100644 index 00000000000..f656cdfd97a --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/noir/concepts/functions.md @@ -0,0 +1,226 @@ +--- +title: Functions +description: + Learn how to declare functions and methods in Noir, a programming language with Rust semantics. + This guide covers parameter declaration, return types, call expressions, and more. +keywords: [Noir, Rust, functions, methods, parameter declaration, return types, call expressions] +sidebar_position: 1 +--- + +Functions in Noir follow the same semantics of Rust, though Noir does not support early returns. + +To declare a function the `fn` keyword is used. + +```rust +fn foo() {} +``` + +By default, functions are visible only within the package they are defined. To make them visible outside of that package (for example, as part of a [library](../modules_packages_crates/crates_and_packages.md#libraries)), you should mark them as `pub`: + +```rust +pub fn foo() {} +``` + +You can also restrict the visibility of the function to only the crate it was defined in, by specifying `pub(crate)`: + +```rust +pub(crate) fn foo() {} //foo can only be called within its crate +``` + +All parameters in a function must have a type and all types are known at compile time. The parameter +is pre-pended with a colon and the parameter type. Multiple parameters are separated using a comma. + +```rust +fn foo(x : Field, y : Field){} +``` + +The return type of a function can be stated by using the `->` arrow notation. The function below +states that the foo function must return a `Field`. If the function returns no value, then the arrow +is omitted. + +```rust +fn foo(x : Field, y : Field) -> Field { + x + y +} +``` + +Note that a `return` keyword is unneeded in this case - the last expression in a function's body is +returned. + +## Main function + +If you're writing a binary, the `main` function is the starting point of your program. You can pass all types of expressions to it, as long as they have a fixed size at compile time: + +```rust +fn main(x : Field) // this is fine: passing a Field +fn main(x : [Field; 2]) // this is also fine: passing a Field with known size at compile-time +fn main(x : (Field, bool)) // 👌: passing a (Field, bool) tuple means size 2 +fn main(x : str<5>) // this is fine, as long as you pass a string of size 5 + +fn main(x : Vec) // can't compile, has variable size +fn main(x : [Field]) // can't compile, has variable size +fn main(....// i think you got it by now +``` + +Keep in mind [tests](../../tooling/testing.md) don't differentiate between `main` and any other function. The following snippet passes tests, but won't compile or prove: + +```rust +fn main(x : [Field]) { + assert(x[0] == 1); +} + +#[test] +fn test_one() { + main(&[1, 2]); +} +``` + +```bash +$ nargo test +[testing] Running 1 test functions +[testing] Testing test_one... ok +[testing] All tests passed + +$ nargo check +The application panicked (crashed). +Message: Cannot have variable sized arrays as a parameter to main +``` + +## Call Expressions + +Calling a function in Noir is executed by using the function name and passing in the necessary +arguments. + +Below we show how to call the `foo` function from the `main` function using a call expression: + +```rust +fn main(x : Field, y : Field) { + let z = foo(x); +} + +fn foo(x : Field) -> Field { + x + x +} +``` + +## Methods + +You can define methods in Noir on any struct type in scope. + +```rust +struct MyStruct { + foo: Field, + bar: Field, +} + +impl MyStruct { + fn new(foo: Field) -> MyStruct { + MyStruct { + foo, + bar: 2, + } + } + + fn sum(self) -> Field { + self.foo + self.bar + } +} + +fn main() { + let s = MyStruct::new(40); + assert(s.sum() == 42); +} +``` + +Methods are just syntactic sugar for functions, so if we wanted to we could also call `sum` as +follows: + +```rust +assert(MyStruct::sum(s) == 42); +``` + +It is also possible to specialize which method is chosen depending on the [generic](./generics.md) type that is used. In this example, the `foo` function returns different values depending on its type: + +```rust +struct Foo {} + +impl Foo { + fn foo(self) -> Field { 1 } +} + +impl Foo { + fn foo(self) -> Field { 2 } +} + +fn main() { + let f1: Foo = Foo{}; + let f2: Foo = Foo{}; + assert(f1.foo() + f2.foo() == 3); +} +``` + +Also note that impls with the same method name defined in them cannot overlap. For example, if we already have `foo` defined for `Foo` and `Foo` like we do above, we cannot also define `foo` in an `impl Foo` since it would be ambiguous which version of `foo` to choose. + +```rust +// Including this impl in the same project as the above snippet would +// cause an overlapping impls error +impl Foo { + fn foo(self) -> Field { 3 } +} +``` + +## Lambdas + +Lambdas are anonymous functions. They follow the syntax of Rust - `|arg1, arg2, ..., argN| return_expression`. + +```rust +let add_50 = |val| val + 50; +assert(add_50(100) == 150); +``` + +See [Lambdas](./lambdas.md) for more details. + +## Attributes + +Attributes are metadata that can be applied to a function, using the following syntax: `#[attribute(value)]`. + +Supported attributes include: + +- **builtin**: the function is implemented by the compiler, for efficiency purposes. +- **deprecated**: mark the function as _deprecated_. Calling the function will generate a warning: `warning: use of deprecated function` +- **field**: Used to enable conditional compilation of code depending on the field size. See below for more details +- **oracle**: mark the function as _oracle_; meaning it is an external unconstrained function, implemented in noir_js. See [Unconstrained](./unconstrained.md) and [NoirJS](../../reference/NoirJS/noir_js/index.md) for more details. +- **test**: mark the function as unit tests. See [Tests](../../tooling/testing.md) for more details + +### Field Attribute + +The field attribute defines which field the function is compatible for. The function is conditionally compiled, under the condition that the field attribute matches the Noir native field. +The field can be defined implicitly, by using the name of the elliptic curve usually associated to it - for instance bn254, bls12_381 - or explicitly by using the field (prime) order, in decimal or hexadecimal form. +As a result, it is possible to define multiple versions of a function with each version specialized for a different field attribute. This can be useful when a function requires different parameters depending on the underlying elliptic curve. + +Example: we define the function `foo()` three times below. Once for the default Noir bn254 curve, once for the field $\mathbb F_{23}$, which will normally never be used by Noir, and once again for the bls12_381 curve. + +```rust +#[field(bn254)] +fn foo() -> u32 { + 1 +} + +#[field(23)] +fn foo() -> u32 { + 2 +} + +// This commented code would not compile as foo would be defined twice because it is the same field as bn254 +// #[field(21888242871839275222246405745257275088548364400416034343698204186575808495617)] +// fn foo() -> u32 { +// 2 +// } + +#[field(bls12_381)] +fn foo() -> u32 { + 3 +} +``` + +If the field name is not known to Noir, it will discard the function. Field names are case insensitive. diff --git a/docs/versioned_docs/version-v0.28.0/noir/concepts/generics.md b/docs/versioned_docs/version-v0.28.0/noir/concepts/generics.md new file mode 100644 index 00000000000..ddd42bf1f9b --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/noir/concepts/generics.md @@ -0,0 +1,106 @@ +--- +title: Generics +description: Learn how to use Generics in Noir +keywords: [Noir, Rust, generics, functions, structs] +sidebar_position: 7 +--- + +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 print(self) { + for _i in 0 .. self.count { + println(self.value); + } + } +} + +fn main() { + let repeated = RepeatedValue { value: "Hello!", count: 2 }; + 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 + +Since a generic type `T` can represent any type, how can we call functions on the underlying type? +In other words, how can we go from "any type `T`" to "any type `T` that has certain methods available?" + +This is what [traits](../concepts/traits) are for in Noir. Here's an example of a function generic over +any type `T` that implements the `Eq` trait for equality: + +```rust +fn first_element_is_equal(array1: [T; N], array2: [T; N]) -> bool + where T: Eq +{ + if (array1.len() == 0) | (array2.len() == 0) { + true + } else { + array1[0] == array2[0] + } +} + +fn main() { + assert(first_element_is_equal([1, 2, 3], [1, 5, 6])); + + // We can use first_element_is_equal for arrays of any type + // as long as we have an Eq impl for the types we pass in + let array = [MyStruct::new(), MyStruct::new()]; + assert(array_eq(array, array, MyStruct::eq)); +} + +impl Eq for MyStruct { + fn eq(self, other: MyStruct) -> bool { + self.foo == other.foo + } +} +``` + +You can find more details on traits and trait implementations on the [traits page](../concepts/traits). diff --git a/docs/versioned_docs/version-v0.28.0/noir/concepts/globals.md b/docs/versioned_docs/version-v0.28.0/noir/concepts/globals.md new file mode 100644 index 00000000000..063a3d89248 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/noir/concepts/globals.md @@ -0,0 +1,72 @@ +--- +title: Global Variables +description: + Learn about global variables in Noir. Discover how + to declare, modify, and use them in your programs. +keywords: [noir programming language, globals, global variables, constants] +sidebar_position: 8 +--- + +## Globals + + +Noir supports global variables. The global's type can be inferred by the compiler entirely: + +```rust +global N = 5; // Same as `global N: Field = 5` + +global TUPLE = (3, 2); + +fn main() { + assert(N == 5); + assert(N == TUPLE.0 + TUPLE.1); +} +``` + +:::info + +Globals can be defined as any expression, so long as they don't depend on themselves - otherwise there would be a dependency cycle! For example: + +```rust +global T = foo(T); // dependency error +``` + +::: + + +If they are initialized to a literal integer, globals can be used to specify an array's length: + +```rust +global N: Field = 2; + +fn main(y : [Field; N]) { + assert(y[0] == y[1]) +} +``` + +A global from another module can be imported or referenced externally like any other name: + +```rust +global N = 20; + +fn main() { + assert(my_submodule::N != N); +} + +mod my_submodule { + global N: Field = 10; +} +``` + +When a global is used, Noir replaces the name with its definition on each occurrence. +This means globals defined using function calls will repeat the call each time they're used: + +```rust +global RESULT = foo(); + +fn foo() -> [Field; 100] { ... } +``` + +This is usually fine since Noir will generally optimize any function call that does not +refer to a program input into a constant. It should be kept in mind however, if the called +function performs side-effects like `println`, as these will still occur on each use. diff --git a/docs/versioned_docs/version-v0.28.0/noir/concepts/lambdas.md b/docs/versioned_docs/version-v0.28.0/noir/concepts/lambdas.md new file mode 100644 index 00000000000..be3c7e0b5ca --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/noir/concepts/lambdas.md @@ -0,0 +1,81 @@ +--- +title: Lambdas +description: Learn how to use anonymous functions in Noir programming language. +keywords: [Noir programming language, lambda, closure, function, anonymous function] +sidebar_position: 9 +--- + +## 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.28.0/noir/concepts/mutability.md b/docs/versioned_docs/version-v0.28.0/noir/concepts/mutability.md new file mode 100644 index 00000000000..fdeef6a87c5 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/noir/concepts/mutability.md @@ -0,0 +1,121 @@ +--- +title: Mutability +description: + Learn about mutable variables in Noir. Discover how + to declare, modify, and use them in your programs. +keywords: [noir programming language, mutability in noir, mutable variables] +sidebar_position: 8 +--- + +Variables in noir can be declared mutable via the `mut` keyword. Mutable variables can be reassigned +to via an assignment expression. + +```rust +let x = 2; +x = 3; // error: x must be mutable to be assigned to + +let mut y = 3; +let y = 4; // OK +``` + +The `mut` modifier can also apply to patterns: + +```rust +let (a, mut b) = (1, 2); +a = 11; // error: a must be mutable to be assigned to +b = 12; // OK + +let mut (c, d) = (3, 4); +c = 13; // OK +d = 14; // OK + +// etc. +let MyStruct { x: mut y } = MyStruct { x: a }; +// y is now in scope +``` + +Note that mutability in noir is local and everything is passed by value, so if a called function +mutates its parameters then the parent function will keep the old value of the parameters. + +```rust +fn main() -> pub Field { + let x = 3; + helper(x); + x // x is still 3 +} + +fn helper(mut x: i32) { + x = 4; +} +``` + +## Non-local mutability + +Non-local mutability can be achieved through the mutable reference type `&mut T`: + +```rust +fn set_to_zero(x: &mut Field) { + *x = 0; +} + +fn main() { + let mut y = 42; + set_to_zero(&mut y); + assert(*y == 0); +} +``` + +When creating a mutable reference, the original variable being referred to (`y` in this +example) must also be mutable. Since mutable references are a reference type, they must +be explicitly dereferenced via `*` to retrieve the underlying value. Note that this yields +a copy of the value, so mutating this copy will not change the original value behind the +reference: + +```rust +fn main() { + let mut x = 1; + let x_ref = &mut x; + + let mut y = *x_ref; + let y_ref = &mut y; + + x = 2; + *x_ref = 3; + + y = 4; + *y_ref = 5; + + assert(x == 3); + assert(*x_ref == 3); + assert(y == 5); + assert(*y_ref == 5); +} +``` + +Note that types in Noir are actually deeply immutable so the copy that occurs when +dereferencing is only a conceptual copy - no additional constraints will occur. + +Mutable references can also be stored within structs. Note that there is also +no lifetime parameter on these unlike rust. This is because the allocated memory +always lasts the entire program - as if it were an array of one element. + +```rust +struct Foo { + x: &mut Field +} + +impl Foo { + fn incr(mut self) { + *self.x += 1; + } +} + +fn main() { + let foo = Foo { x: &mut 0 }; + foo.incr(); + assert(*foo.x == 1); +} +``` + +In general, you should avoid non-local & shared mutability unless it is needed. Sticking +to only local mutability will improve readability and potentially improve compiler optimizations as well. diff --git a/docs/versioned_docs/version-v0.28.0/noir/concepts/ops.md b/docs/versioned_docs/version-v0.28.0/noir/concepts/ops.md new file mode 100644 index 00000000000..60425cb8994 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/noir/concepts/ops.md @@ -0,0 +1,98 @@ +--- +title: Logical Operations +description: + Learn about the supported arithmetic and logical operations in the Noir programming language. + Discover how to perform operations on private input types, integers, and booleans. +keywords: + [ + Noir programming language, + supported operations, + arithmetic operations, + logical operations, + predicate operators, + bitwise operations, + short-circuiting, + backend, + ] +sidebar_position: 3 +--- + +# Operations + +## Table of Supported Operations + +| Operation | Description | Requirements | +| :-------- | :------------------------------------------------------------: | -------------------------------------: | +| + | Adds two private input types together | Types must be private input | +| - | Subtracts two private input types together | Types must be private input | +| \* | Multiplies two private input types together | Types must be private input | +| / | Divides two private input types together | Types must be private input | +| ^ | XOR two private input types together | Types must be integer | +| & | AND two private input types together | Types must be integer | +| \| | OR two private input types together | Types must be integer | +| \<\< | Left shift an integer by another integer amount | Types must be integer | +| >> | Right shift an integer by another integer amount | Types must be integer | +| ! | Bitwise not of a value | Type must be integer or boolean | +| \< | returns a bool if one value is less than the other | Upper bound must have a known bit size | +| \<= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | +| > | returns a bool if one value is more than the other | Upper bound must have a known bit size | +| >= | returns a bool if one value is more than or equal to the other | Upper bound must have a known bit size | +| == | returns a bool if one value is equal to the other | Both types must not be constants | +| != | returns a bool if one value is not equal to the other | Both types must not be constants | + +### Predicate Operators + +`<,<=, !=, == , >, >=` are known as predicate/comparison operations because they compare two values. +This differs from the operations such as `+` where the operands are used in _computation_. + +### Bitwise Operations Example + +```rust +fn main(x : Field) { + let y = x as u32; + let z = y & y; +} +``` + +`z` is implicitly constrained to be the result of `y & y`. The `&` operand is used to denote bitwise +`&`. + +> `x & x` would not compile as `x` is a `Field` and not an integer type. + +### Logical Operators + +Noir has no support for the logical operators `||` and `&&`. This is because encoding the +short-circuiting that these operators require can be inefficient for Noir's backend. Instead you can +use the bitwise operators `|` and `&` which operate identically 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.28.0/noir/concepts/oracles.md b/docs/versioned_docs/version-v0.28.0/noir/concepts/oracles.md new file mode 100644 index 00000000000..aa380b5f7b8 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/noir/concepts/oracles.md @@ -0,0 +1,31 @@ +--- +title: Oracles +description: Dive into how Noir supports Oracles via RPC calls, and learn how to declare an Oracle in Noir with our comprehensive guide. +keywords: + - Noir + - Oracles + - RPC Calls + - Unconstrained Functions + - Programming + - Blockchain +sidebar_position: 6 +--- + +:::note + +This is an experimental feature that is not fully documented. If you notice any outdated information or potential improvements to this page, pull request contributions are very welcome: https://github.com/noir-lang/noir + +::: + +Noir has support for Oracles via RPC calls. This means Noir will make an RPC call and use the return value for proof generation. + +Since Oracles are not resolved by Noir, they are [`unconstrained` functions](./unconstrained.md) + +You can declare an Oracle through the `#[oracle()]` flag. Example: + +```rust +#[oracle(get_number_sequence)] +unconstrained fn get_number_sequence(_size: Field) -> [Field] {} +``` + +The timeout for when using an external RPC oracle resolver can be set with the `NARGO_FOREIGN_CALL_TIMEOUT` environment variable. This timeout is in units of milliseconds. diff --git a/docs/versioned_docs/version-v0.28.0/noir/concepts/shadowing.md b/docs/versioned_docs/version-v0.28.0/noir/concepts/shadowing.md new file mode 100644 index 00000000000..5ce6130d201 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/noir/concepts/shadowing.md @@ -0,0 +1,44 @@ +--- +title: Shadowing +sidebar_position: 12 +--- + +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.28.0/noir/concepts/traits.md b/docs/versioned_docs/version-v0.28.0/noir/concepts/traits.md new file mode 100644 index 00000000000..ef1445a5907 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/noir/concepts/traits.md @@ -0,0 +1,389 @@ +--- +title: Traits +description: + Traits in Noir can be used to abstract out a common interface for functions across + several data types. +keywords: [noir programming language, traits, interfaces, generic, protocol] +sidebar_position: 14 +--- + +## Overview + +Traits in Noir are a useful abstraction similar to interfaces or protocols in other languages. Each trait defines +the interface of several methods contained within the trait. Types can then implement this trait by providing +implementations for these methods. For example in the program: + +```rust +struct Rectangle { + width: Field, + height: Field, +} + +impl Rectangle { + fn area(self) -> Field { + self.width * self.height + } +} + +fn log_area(r: Rectangle) { + println(r.area()); +} +``` + +We have a function `log_area` to log the area of a `Rectangle`. Now how should we change the program if we want this +function to work on `Triangle`s as well?: + +```rust +struct Triangle { + width: Field, + height: Field, +} + +impl Triangle { + fn area(self) -> Field { + self.width * self.height / 2 + } +} +``` + +Making `log_area` generic over all types `T` would be invalid since not all types have an `area` method. Instead, we can +introduce a new `Area` trait and make `log_area` generic over all types `T` that implement `Area`: + +```rust +trait Area { + fn area(self) -> Field; +} + +fn log_area(shape: T) where T: Area { + println(shape.area()); +} +``` + +We also need to explicitly implement `Area` for `Rectangle` and `Triangle`. We can do that by changing their existing +impls slightly. Note that the parameter types and return type of each of our `area` methods must match those defined +by the `Area` trait. + +```rust +impl Area for Rectangle { + fn area(self) -> Field { + self.width * self.height + } +} + +impl Area for Triangle { + fn area(self) -> Field { + self.width * self.height / 2 + } +} +``` + +Now we have a working program that is generic over any type of Shape that is used! Others can even use this program +as a library with their own types - such as `Circle` - as long as they also implement `Area` for these types. + +## Where Clauses + +As seen in `log_area` above, when we want to create a function or method that is generic over any type that implements +a trait, we can add a where clause to the generic function. + +```rust +fn log_area(shape: T) where T: Area { + println(shape.area()); +} +``` + +It is also possible to apply multiple trait constraints on the same variable at once by combining traits with the `+` +operator. Similarly, we can have multiple trait constraints by separating each with a comma: + +```rust +fn foo(elements: [T], thing: U) where + T: Default + Add + Eq, + U: Bar, +{ + let mut sum = T::default(); + + for element in elements { + sum += element; + } + + if sum == T::default() { + thing.bar(); + } +} +``` + +## Generic Implementations + +You can add generics to a trait implementation by adding the generic list after the `impl` keyword: + +```rust +trait Second { + fn second(self) -> Field; +} + +impl Second for (T, Field) { + fn second(self) -> Field { + self.1 + } +} +``` + +You can also implement a trait for every type this way: + +```rust +trait Debug { + fn debug(self); +} + +impl Debug for T { + fn debug(self) { + println(self); + } +} + +fn main() { + 1.debug(); +} +``` + +### Generic Trait Implementations With Where Clauses + +Where clauses can also be placed on trait implementations themselves to restrict generics in a similar way. +For example, while `impl Foo for T` implements the trait `Foo` for every type, `impl Foo for T where T: Bar` +will implement `Foo` only for types that also implement `Bar`. This is often used for implementing generic types. +For example, here is the implementation for array equality: + +```rust +impl Eq for [T; N] where T: Eq { + // Test if two arrays have the same elements. + // Because both arrays must have length N, we know their lengths already match. + fn eq(self, other: Self) -> bool { + let mut result = true; + + for i in 0 .. self.len() { + // The T: Eq constraint is needed to call == on the array elements here + result &= self[i] == other[i]; + } + + result + } +} +``` + +## Generic Traits + +Traits themselves can also be generic by placing the generic arguments after the trait name. These generics are in +scope of every item within the trait. + +```rust +trait Into { + // Convert `self` to type `T` + fn into(self) -> T; +} +``` + +When implementing generic traits the generic arguments of the trait must be specified. This is also true anytime +when referencing a generic trait (e.g. in a `where` clause). + +```rust +struct MyStruct { + array: [Field; 2], +} + +impl Into<[Field; 2]> for MyStruct { + fn into(self) -> [Field; 2] { + self.array + } +} + +fn as_array(x: T) -> [Field; 2] + where T: Into<[Field; 2]> +{ + x.into() +} + +fn main() { + let array = [1, 2]; + let my_struct = MyStruct { array }; + + assert_eq(as_array(my_struct), array); +} +``` + +## Trait Methods With No `self` + +A trait can contain any number of methods, each of which have access to the `Self` type which represents each type +that eventually implements the trait. Similarly, the `self` variable is available as well but is not required to be used. +For example, we can define a trait to create a default value for a type. This trait will need to return the `Self` type +but doesn't need to take any parameters: + +```rust +trait Default { + fn default() -> Self; +} +``` + +Implementing this trait can be done similarly to any other trait: + +```rust +impl Default for Field { + fn default() -> Field { + 0 + } +} + +struct MyType {} + +impl Default for MyType { + fn default() -> Field { + MyType {} + } +} +``` + +However, since there is no `self` parameter, we cannot call it via the method call syntax `object.method()`. +Instead, we'll need to refer to the function directly. This can be done either by referring to the +specific impl `MyType::default()` or referring to the trait itself `Default::default()`. In the later +case, type inference determines the impl that is selected. + +```rust +let my_struct = MyStruct::default(); + +let x: Field = Default::default(); +let result = x + Default::default(); +``` + +:::warning + +```rust +let _ = Default::default(); +``` + +If type inference cannot select which impl to use because of an ambiguous `Self` type, an impl will be +arbitrarily selected. This occurs most often when the result of a trait function call with no parameters +is unused. To avoid this, when calling a trait function with no `self` or `Self` parameters or return type, +always refer to it via the implementation type's namespace - e.g. `MyType::default()`. +This is set to change to an error in future Noir versions. + +::: + +## Default Method Implementations + +A trait can also have default implementations of its methods by giving a body to the desired functions. +Note that this body must be valid for all types that may implement the trait. As a result, the only +valid operations on `self` will be operations valid for any type or other operations on the trait itself. + +```rust +trait Numeric { + fn add(self, other: Self) -> Self; + + // Default implementation of double is (self + self) + fn double(self) -> Self { + self.add(self) + } +} +``` + +When implementing a trait with default functions, a type may choose to implement only the required functions: + +```rust +impl Numeric for Field { + fn add(self, other: Field) -> Field { + self + other + } +} +``` + +Or it may implement the optional methods as well: + +```rust +impl Numeric for u32 { + fn add(self, other: u32) -> u32 { + self + other + } + + fn double(self) -> u32 { + self * 2 + } +} +``` + +## Impl Specialization + +When implementing traits for a generic type it is possible to implement the trait for only a certain combination +of generics. This can be either as an optimization or because those specific generics are required to implement the trait. + +```rust +trait Sub { + fn sub(self, other: Self) -> Self; +} + +struct NonZero { + value: T, +} + +impl Sub for NonZero { + fn sub(self, other: Self) -> Self { + let value = self.value - other.value; + assert(value != 0); + NonZero { value } + } +} +``` + +## Overlapping Implementations + +Overlapping implementations are disallowed by Noir to ensure Noir's decision on which impl to select is never ambiguous. +This means if a trait `Foo` is already implemented +by a type `Bar` for all `T`, then we cannot also have a separate impl for `Bar` (or any other +type argument). Similarly, if there is an impl for all `T` such as `impl Debug for T`, we cannot create +any more impls to `Debug` for other types since it would be ambiguous which impl to choose for any given +method call. + +```rust +trait Trait {} + +// Previous impl defined here +impl Trait for (A, B) {} + +// error: Impl for type `(Field, Field)` overlaps with existing impl +impl Trait for (Field, Field) {} +``` + +## Trait Coherence + +Another restriction on trait implementations is coherence. This restriction ensures other crates cannot create +impls that may overlap with other impls, even if several unrelated crates are used as dependencies in the same +program. + +The coherence restriction is: to implement a trait, either the trait itself or the object type must be declared +in the crate the impl is in. + +In practice this often comes up when using types provided by libraries. If a library provides a type `Foo` that does +not implement a trait in the standard library such as `Default`, you may not `impl Default for Foo` in your own crate. +While restrictive, this prevents later issues or silent changes in the program if the `Foo` library later added its +own impl for `Default`. If you are a user of the `Foo` library in this scenario and need a trait not implemented by the +library your choices are to either submit a patch to the library or use the newtype pattern. + +### The Newtype Pattern + +The newtype pattern gets around the coherence restriction by creating a new wrapper type around the library type +that we cannot create `impl`s for. Since the new wrapper type is defined in our current crate, we can create +impls for any trait we need on it. + +```rust +struct Wrapper { + foo: dep::some_library::Foo, +} + +impl Default for Wrapper { + fn default() -> Wrapper { + Wrapper { + foo: dep::some_library::Foo::new(), + } + } +} +``` + +Since we have an impl for our own type, the behavior of this code will not change even if `some_library` is updated +to provide its own `impl Default for Foo`. The downside of this pattern is that it requires extra wrapping and +unwrapping of values when converting to and from the `Wrapper` and `Foo` types. diff --git a/docs/versioned_docs/version-v0.28.0/noir/concepts/unconstrained.md b/docs/versioned_docs/version-v0.28.0/noir/concepts/unconstrained.md new file mode 100644 index 00000000000..b8e71fe65f0 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/noir/concepts/unconstrained.md @@ -0,0 +1,99 @@ +--- +title: Unconstrained Functions +description: "Learn about what unconstrained functions in Noir are, how to use them and when you'd want to." + +keywords: [Noir programming language, unconstrained, open] +sidebar_position: 5 +--- + +Unconstrained functions are functions which do not constrain any of the included computation and allow for non-deterministic 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 AND 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. + +## Break and Continue + +In addition to loops over runtime bounds, `break` and `continue` are also available in unconstrained code. See [break and continue](../concepts/control_flow/#break-and-continue) diff --git a/docs/versioned_docs/version-v0.28.0/noir/modules_packages_crates/_category_.json b/docs/versioned_docs/version-v0.28.0/noir/modules_packages_crates/_category_.json new file mode 100644 index 00000000000..1debcfe7675 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/noir/modules_packages_crates/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Modules, Packages and Crates", + "position": 2, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.28.0/noir/modules_packages_crates/crates_and_packages.md b/docs/versioned_docs/version-v0.28.0/noir/modules_packages_crates/crates_and_packages.md new file mode 100644 index 00000000000..95ee9f52ab2 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/noir/modules_packages_crates/crates_and_packages.md @@ -0,0 +1,43 @@ +--- +title: Crates and Packages +description: Learn how to use Crates and Packages in your Noir project +keywords: [Nargo, dependencies, package management, crates, package] +sidebar_position: 0 +--- + +## Crates + +A crate is the smallest amount of code that the Noir compiler considers at a time. +Crates can contain modules, and the modules may be defined in other files that get compiled with the crate, as we’ll see in the coming sections. + +### Crate Types + +A Noir crate can come in several forms: binaries, libraries or contracts. + +#### Binaries + +_Binary crates_ are programs which you can compile to an ACIR circuit which you can then create proofs against. Each must have a function called `main` that defines the ACIR circuit which is to be proved. + +#### Libraries + +_Library crates_ don't have a `main` function and they don't compile down to ACIR. Instead they define functionality intended to be shared with multiple projects, and eventually included in a binary crate. + +#### Contracts + +Contract crates are similar to binary crates in that they compile to ACIR which you can create proofs against. They are different in that they do not have a single `main` function, but are a collection of functions to be deployed to the [Aztec network](https://aztec.network). You can learn more about the technical details of Aztec in the [monorepo](https://github.com/AztecProtocol/aztec-packages) or contract [examples](https://github.com/AztecProtocol/aztec-packages/tree/master/noir-projects/noir-contracts/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.28.0/noir/modules_packages_crates/dependencies.md b/docs/versioned_docs/version-v0.28.0/noir/modules_packages_crates/dependencies.md new file mode 100644 index 00000000000..04c1703d929 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/noir/modules_packages_crates/dependencies.md @@ -0,0 +1,124 @@ +--- +title: Dependencies +description: + Learn how to specify and manage dependencies in Nargo, allowing you to upload packages to GitHub + and use them easily in your project. +keywords: [Nargo, dependencies, GitHub, package management, versioning] +sidebar_position: 1 +--- + +Nargo allows you to upload packages to GitHub and use them as dependencies. + +## Specifying a dependency + +Specifying a dependency requires a tag to a specific commit and the git url to the url containing +the package. + +Currently, there are no requirements on the tag contents. If requirements are added, it would follow +semver 2.0 guidelines. + +> Note: Without a `tag` , there would be no versioning and dependencies would change each time you +> compile your project. + +For example, to add the [ecrecover-noir library](https://github.com/colinnielsen/ecrecover-noir) to your project, add it to `Nargo.toml`: + +```toml +# Nargo.toml + +[dependencies] +ecrecover = {tag = "v0.8.0", git = "https://github.com/colinnielsen/ecrecover-noir"} +``` + +If the module is in a subdirectory, you can define a subdirectory in your git repository, for example: + +```toml +# Nargo.toml + +[dependencies] +easy_private_token_contract = {tag ="v0.1.0-alpha62", git = "https://github.com/AztecProtocol/aztec-packages", directory = "noir-contracts/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 +└── lib_a + ├── Nargo.toml + └── src + └── lib.nr +``` + +Inside of the binary crate, you can specify: + +```toml +# Nargo.toml + +[dependencies] +lib_a = { path = "../lib_a" } +``` + +## 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 lib_a referenced above: + +```rust +use dep::ecrecover; +use dep::lib_a; +``` + +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.28.0/noir/modules_packages_crates/modules.md b/docs/versioned_docs/version-v0.28.0/noir/modules_packages_crates/modules.md new file mode 100644 index 00000000000..ae822a1cff4 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/noir/modules_packages_crates/modules.md @@ -0,0 +1,105 @@ +--- +title: Modules +description: + Learn how to organize your files using modules in Noir, following the same convention as Rust's + module system. Examples included. +keywords: [Noir, Rust, modules, organizing files, sub-modules] +sidebar_position: 2 +--- + +Noir's module system follows the same convention as the _newer_ version of Rust's module system. + +## Purpose of Modules + +Modules are used to organize 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.28.0/noir/modules_packages_crates/workspaces.md b/docs/versioned_docs/version-v0.28.0/noir/modules_packages_crates/workspaces.md new file mode 100644 index 00000000000..513497f12bf --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/noir/modules_packages_crates/workspaces.md @@ -0,0 +1,42 @@ +--- +title: Workspaces +sidebar_position: 3 +--- + +Workspaces are a feature of nargo that allow you to manage multiple related Noir packages in a single repository. A workspace is essentially a group of related projects that share common build output directories and configurations. + +Each Noir project (with it's own Nargo.toml file) can be thought of as a package. Each package is expected to contain exactly one "named circuit", being the "name" defined in Nargo.toml with the program logic defined in `./src/main.nr`. + +For a project with the following structure: + +```tree +├── crates +│ ├── a +│ │ ├── Nargo.toml +│ │ └── Prover.toml +│ │ └── src +│ │ └── main.nr +│ └── b +│ ├── Nargo.toml +│ └── Prover.toml +│ └── src +│ └── main.nr +│ +└── Nargo.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.28.0/noir/standard_library/_category_.json b/docs/versioned_docs/version-v0.28.0/noir/standard_library/_category_.json new file mode 100644 index 00000000000..af04c0933fd --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/noir/standard_library/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Standard Library", + "position": 1, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.28.0/noir/standard_library/bigint.md b/docs/versioned_docs/version-v0.28.0/noir/standard_library/bigint.md new file mode 100644 index 00000000000..2bfdeec6631 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/noir/standard_library/bigint.md @@ -0,0 +1,122 @@ +--- +title: Big Integers +description: How to use big integers from Noir standard library +keywords: + [ + Big Integer, + Noir programming language, + Noir libraries, + ] +--- + +The BigInt module in the standard library exposes some class of integers which do not fit (well) into a Noir native field. It implements modulo arithmetic, modulo a 'big' prime number. + +:::note + +The module can currently be considered as `Field`s with fixed modulo sizes used by a set of elliptic curves, in addition to just the native curve. [More work](https://github.com/noir-lang/noir/issues/510) is needed to achieve arbitrarily sized big integers. + +::: + +Currently 6 classes of integers (i.e 'big' prime numbers) are available in the module, namely: + +- BN254 Fq: Bn254Fq +- BN254 Fr: Bn254Fr +- Secp256k1 Fq: Secpk1Fq +- Secp256k1 Fr: Secpk1Fr +- Secp256r1 Fr: Secpr1Fr +- Secp256r1 Fq: Secpr1Fq + +Where XXX Fq and XXX Fr denote respectively the order of the base and scalar field of the (usual) elliptic curve XXX. +For instance the big integer 'Secpk1Fq' in the standard library refers to integers modulo $2^{256}-2^{32}-977$. + +Feel free to explore the source code for the other primes: + +```rust title="big_int_definition" showLineNumbers +struct BigInt { + pointer: u32, + modulus: u32, +} +``` +> Source code: noir_stdlib/src/bigint.nr#L14-L19 + + +## Example usage + +A common use-case is when constructing a big integer from its bytes representation, and performing arithmetic operations on it: + +```rust title="big_int_example" showLineNumbers +fn big_int_example(x: u8, y: u8) { + let a = Secpk1Fq::from_le_bytes(&[x, y, 0, 45, 2]); + let b = Secpk1Fq::from_le_bytes(&[y, x, 9]); + let c = (a + b) * b / a; + let d = c.to_le_bytes(); + println(d[0]); +} +``` +> Source code: test_programs/execution_success/bigint/src/main.nr#L70-L78 + + +## Methods + +The available operations for each big integer are: + +### from_le_bytes + +Construct a big integer from its little-endian bytes representation. Example: + +```rust + // Construct a big integer from a slice of bytes + let a = Secpk1Fq::from_le_bytes(&[x, y, 0, 45, 2]); + // Construct a big integer from an array of 32 bytes + let a = Secpk1Fq::from_le_bytes_32([1;32]); + ``` + +Sure, here's the formatted version of the remaining methods: + +### to_le_bytes + +Return the little-endian bytes representation of a big integer. Example: + +```rust +let bytes = a.to_le_bytes(); +``` + +### add + +Add two big integers. Example: + +```rust +let sum = a + b; +``` + +### sub + +Subtract two big integers. Example: + +```rust +let difference = a - b; +``` + +### mul + +Multiply two big integers. Example: + +```rust +let product = a * b; +``` + +### div + +Divide two big integers. Note that division is field division and not euclidean division. Example: + +```rust +let quotient = a / b; +``` + +### eq + +Compare two big integers. Example: + +```rust +let are_equal = a == b; +``` diff --git a/docs/versioned_docs/version-v0.28.0/noir/standard_library/black_box_fns.md b/docs/versioned_docs/version-v0.28.0/noir/standard_library/black_box_fns.md new file mode 100644 index 00000000000..be8c65679c3 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/noir/standard_library/black_box_fns.md @@ -0,0 +1,31 @@ +--- +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. + +The ACVM spec defines a set of blackbox functions which backends will be expected to implement. This allows backends to use optimized implementations of these constraints if they have them, however they may also fallback to less efficient naive implementations if not. + +## Function list + +Here is a list of the current black box functions: + +- [SHA256](./cryptographic_primitives/hashes.mdx#sha256) +- [Schnorr signature verification](./cryptographic_primitives/schnorr.mdx) +- [Blake2s](./cryptographic_primitives/hashes.mdx#blake2s) +- [Blake3](./cryptographic_primitives/hashes.mdx#blake3) +- [Pedersen Hash](./cryptographic_primitives/hashes.mdx#pedersen_hash) +- [Pedersen Commitment](./cryptographic_primitives/hashes.mdx#pedersen_commitment) +- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification.mdx) +- [Fixed base scalar multiplication](./cryptographic_primitives/scalar.mdx) +- AND +- XOR +- RANGE +- [Keccak256](./cryptographic_primitives/hashes.mdx#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. + +You can view the black box functions defined in the ACVM code [here](https://github.com/noir-lang/noir/blob/master/acvm-repo/acir/src/circuit/black_box_functions.rs). diff --git a/docs/versioned_docs/version-v0.28.0/noir/standard_library/bn254.md b/docs/versioned_docs/version-v0.28.0/noir/standard_library/bn254.md new file mode 100644 index 00000000000..3294f005dbb --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/noir/standard_library/bn254.md @@ -0,0 +1,46 @@ +--- +title: Bn254 Field Library +--- + +Noir provides a module in standard library with some optimized functions for bn254 Fr in `std::field::bn254`. + +## decompose + +```rust +fn decompose(x: Field) -> (Field, Field) {} +``` + +Decomposes a single field into two fields, low and high. The low field contains the lower 16 bytes of the input field and the high field contains the upper 16 bytes of the input field. Both field results are range checked to 128 bits. + + +## assert_gt + +```rust +fn assert_gt(a: Field, b: Field) {} +``` + +Asserts that a > b. This will generate less constraints than using `assert(gt(a, b))`. + +## assert_lt + +```rust +fn assert_lt(a: Field, b: Field) {} +``` + +Asserts that a < b. This will generate less constraints than using `assert(lt(a, b))`. + +## gt + +```rust +fn gt(a: Field, b: Field) -> bool {} +``` + +Returns true if a > b. + +## lt + +```rust +fn lt(a: Field, b: Field) -> bool {} +``` + +Returns true if a < b. \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.28.0/noir/standard_library/containers/boundedvec.md b/docs/versioned_docs/version-v0.28.0/noir/standard_library/containers/boundedvec.md new file mode 100644 index 00000000000..ce4529f6e57 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/noir/standard_library/containers/boundedvec.md @@ -0,0 +1,326 @@ +--- +title: Bounded Vectors +keywords: [noir, vector, bounded vector, slice] +sidebar_position: 1 +--- + +A `BoundedVec` is a growable storage similar to a `Vec` except that it +is bounded with a maximum possible length. Unlike `Vec`, `BoundedVec` is not implemented +via slices and thus is not subject to the same restrictions slices are (notably, nested +slices - and thus nested vectors as well - are disallowed). + +Since a BoundedVec is backed by a normal array under the hood, growing the BoundedVec by +pushing an additional element is also more efficient - the length only needs to be increased +by one. + +For these reasons `BoundedVec` should generally be preferred over `Vec` when there +is a reasonable maximum bound that can be placed on the vector. + +Example: + +```rust +let mut vector: BoundedVec = BoundedVec::new(); +for i in 0..5 { + vector.push(i); +} +assert(vector.len() == 5); +assert(vector.max_len() == 10); +``` + +## Methods + +### new + +```rust +pub fn new() -> Self +``` + +Creates a new, empty vector of length zero. + +Since this container is backed by an array internally, it still needs an initial value +to give each element. To resolve this, each element is zeroed internally. This value +is guaranteed to be inaccessible unless `get_unchecked` is used. + +Example: + +```rust +let empty_vector: BoundedVec = BoundedVec::new(); +assert(empty_vector.len() == 0); +``` + +Note that whenever calling `new` the maximum length of the vector should always be specified +via a type signature: + +```rust title="new_example" showLineNumbers +fn foo() -> BoundedVec { + // Ok! MaxLen is specified with a type annotation + let v1: BoundedVec = BoundedVec::new(); + let v2 = BoundedVec::new(); + + // Ok! MaxLen is known from the type of foo's return value + v2 +} + +fn bad() { + let mut v3 = BoundedVec::new(); + + // Not Ok! We don't know if v3's MaxLen is at least 1, and the compiler often infers 0 by default. + v3.push(5); +} +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L11-L27 + + +This defaulting of `MaxLen` (and numeric generics in general) to zero may change in future noir versions +but for now make sure to use type annotations when using bounded vectors. Otherwise, you will receive a constraint failure at runtime when the vec is pushed to. + +### get + +```rust +pub fn get(mut self: Self, index: u64) -> T { +``` + +Retrieves an element from the vector at the given index, starting from zero. + +If the given index is equal to or greater than the length of the vector, this +will issue a constraint failure. + +Example: + +```rust +fn foo(v: BoundedVec) { + let first = v.get(0); + let last = v.get(v.len() - 1); + assert(first != last); +} +``` + +### get_unchecked + +```rust +pub fn get_unchecked(mut self: Self, index: u64) -> T { +``` + +Retrieves an element from the vector at the given index, starting from zero, without +performing a bounds check. + +Since this function does not perform a bounds check on length before accessing the element, +it is unsafe! Use at your own risk! + +Example: + +```rust title="get_unchecked_example" showLineNumbers +fn sum_of_first_three(v: BoundedVec) -> u32 { + // Always ensure the length is larger than the largest + // index passed to get_unchecked + assert(v.len() > 2); + let first = v.get_unchecked(0); + let second = v.get_unchecked(1); + let third = v.get_unchecked(2); + first + second + third +} +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L54-L64 + + + +### push + +```rust +pub fn push(&mut self, elem: T) { +``` + +Pushes an element to the end of the vector. This increases the length +of the vector by one. + +Panics if the new length of the vector will be greater than the max length. + +Example: + +```rust title="bounded-vec-push-example" showLineNumbers +let mut v: BoundedVec = BoundedVec::new(); + + v.push(1); + v.push(2); + + // Panics with failed assertion "push out of bounds" + v.push(3); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L68-L76 + + +### pop + +```rust +pub fn pop(&mut self) -> T +``` + +Pops the element at the end of the vector. This will decrease the length +of the vector by one. + +Panics if the vector is empty. + +Example: + +```rust title="bounded-vec-pop-example" showLineNumbers +let mut v: BoundedVec = BoundedVec::new(); + v.push(1); + v.push(2); + + let two = v.pop(); + let one = v.pop(); + + assert(two == 2); + assert(one == 1); + // error: cannot pop from an empty vector + // let _ = v.pop(); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L81-L93 + + +### len + +```rust +pub fn len(self) -> u64 { +``` + +Returns the current length of this vector + +Example: + +```rust title="bounded-vec-len-example" showLineNumbers +let mut v: BoundedVec = BoundedVec::new(); + assert(v.len() == 0); + + v.push(100); + assert(v.len() == 1); + + v.push(200); + v.push(300); + v.push(400); + assert(v.len() == 4); + + let _ = v.pop(); + let _ = v.pop(); + assert(v.len() == 2); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L98-L113 + + +### max_len + +```rust +pub fn max_len(_self: BoundedVec) -> u64 { +``` + +Returns the maximum length of this vector. This is always +equal to the `MaxLen` parameter this vector was initialized with. + +Example: + +```rust title="bounded-vec-max-len-example" showLineNumbers +let mut v: BoundedVec = BoundedVec::new(); + + assert(v.max_len() == 5); + v.push(10); + assert(v.max_len() == 5); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L118-L124 + + +### storage + +```rust +pub fn storage(self) -> [T; MaxLen] { +``` + +Returns the internal array within this vector. +Since arrays in Noir are immutable, mutating the returned storage array will not mutate +the storage held internally by this vector. + +Note that uninitialized elements may be zeroed out! + +Example: + +```rust title="bounded-vec-storage-example" showLineNumbers +let mut v: BoundedVec = BoundedVec::new(); + + assert(v.storage() == [0, 0, 0, 0, 0]); + + v.push(57); + assert(v.storage() == [57, 0, 0, 0, 0]); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L129-L136 + + +### extend_from_array + +```rust +pub fn extend_from_array(&mut self, array: [T; Len]) +``` + +Pushes each element from the given array to this vector. + +Panics if pushing each element would cause the length of this vector +to exceed the maximum length. + +Example: + +```rust title="bounded-vec-extend-from-array-example" showLineNumbers +let mut vec: BoundedVec = BoundedVec::new(); + vec.extend_from_array([2, 4]); + + assert(vec.len == 2); + assert(vec.get(0) == 2); + assert(vec.get(1) == 4); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L141-L148 + + +### extend_from_bounded_vec + +```rust +pub fn extend_from_bounded_vec(&mut self, vec: BoundedVec) +``` + +Pushes each element from the other vector to this vector. The length of +the other vector is left unchanged. + +Panics if pushing each element would cause the length of this vector +to exceed the maximum length. + +Example: + +```rust title="bounded-vec-extend-from-bounded-vec-example" showLineNumbers +let mut v1: BoundedVec = BoundedVec::new(); + let mut v2: BoundedVec = BoundedVec::new(); + + v2.extend_from_array([1, 2, 3]); + v1.extend_from_bounded_vec(v2); + + assert(v1.storage() == [1, 2, 3, 0, 0]); + assert(v2.storage() == [1, 2, 3, 0, 0, 0, 0]); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L153-L162 + + +### any + +```rust +pub fn any(self, predicate: fn[Env](T) -> bool) -> bool +``` + +Returns true if the given predicate returns true for any element +in this vector. + +Example: + +```rust title="bounded-vec-any-example" showLineNumbers +let mut v: BoundedVec = BoundedVec::new(); + v.extend_from_array([2, 4, 6]); + + let all_even = !v.any(|elem: u32| elem % 2 != 0); + assert(all_even); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L229-L235 + diff --git a/docs/versioned_docs/version-v0.28.0/noir/standard_library/containers/hashmap.md b/docs/versioned_docs/version-v0.28.0/noir/standard_library/containers/hashmap.md new file mode 100644 index 00000000000..47faa99aba6 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/noir/standard_library/containers/hashmap.md @@ -0,0 +1,570 @@ +--- +title: HashMap +keywords: [noir, map, hash, hashmap] +sidebar_position: 1 +--- + +`HashMap` is used to efficiently store and look up key-value pairs. + +`HashMap` is a bounded type which can store anywhere from zero to `MaxLen` total elements. +Note that due to hash collisions, the actual maximum number of elements stored by any particular +hashmap is likely lower than `MaxLen`. This is true even with cryptographic hash functions since +every hash value will be performed modulo `MaxLen`. + +When creating `HashMap`s, the `MaxLen` generic should always be specified if it is not already +known. Otherwise, the compiler may infer a different value for `MaxLen` (such as zero), which +will likely change the result of the program. This behavior is set to become an error in future +versions instead. + +Example: + +```rust +// Create a mapping from Fields to u32s with a maximum length of 12 +// using a poseidon2 hasher +use dep::std::hash::poseidon2::Poseidon2Hasher; +let mut map: HashMap> = HashMap::default(); + +map.insert(1, 2); +map.insert(3, 4); + +let two = map.get(1).unwrap(); +``` + +## Methods + +### default + +```rust title="default" showLineNumbers +impl Default for HashMap +where + B: BuildHasher + Default, + H: Hasher + Default +{ + fn default() -> Self { +``` +> Source code: noir_stdlib/src/collections/map.nr#L462-L469 + + +Creates a fresh, empty HashMap. + +When using this function, always make sure to specify the maximum size of the hash map. + +This is the same `default` from the `Default` implementation given further below. It is +repeated here for convenience since it is the recommended way to create a hashmap. + +Example: + +```rust title="default_example" showLineNumbers +let hashmap: HashMap> = HashMap::default(); + assert(hashmap.is_empty()); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L202-L205 + + +Because `HashMap` has so many generic arguments that are likely to be the same throughout +your program, it may be helpful to create a type alias: + +```rust title="type_alias" showLineNumbers +type MyMap = HashMap>; +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L196-L198 + + +### with_hasher + +```rust title="with_hasher" showLineNumbers +pub fn with_hasher(_build_hasher: B) -> Self + where + B: BuildHasher { +``` +> Source code: noir_stdlib/src/collections/map.nr#L82-L86 + + +Creates a hashmap with an existing `BuildHasher`. This can be used to ensure multiple +hashmaps are created with the same hasher instance. + +Example: + +```rust title="with_hasher_example" showLineNumbers +let my_hasher: BuildHasherDefault = Default::default(); + let hashmap: HashMap> = HashMap::with_hasher(my_hasher); + assert(hashmap.is_empty()); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L207-L211 + + +### get + +```rust title="get" showLineNumbers +pub fn get( + self, + key: K + ) -> Option + where + K: Eq + Hash, + B: BuildHasher, + H: Hasher { +``` +> Source code: noir_stdlib/src/collections/map.nr#L278-L287 + + +Retrieves a value from the hashmap, returning `Option::none()` if it was not found. + +Example: + +```rust title="get_example" showLineNumbers +fn get_example(map: HashMap>) { + let x = map.get(12); + + if x.is_some() { + assert(x.unwrap() == 42); + } +} +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L299-L307 + + +### insert + +```rust title="insert" showLineNumbers +pub fn insert( + &mut self, + key: K, + value: V + ) + where + K: Eq + Hash, + B: BuildHasher, + H: Hasher { +``` +> Source code: noir_stdlib/src/collections/map.nr#L313-L323 + + +Inserts a new key-value pair into the map. If the key was already in the map, its +previous value will be overridden with the newly provided one. + +Example: + +```rust title="insert_example" showLineNumbers +let mut map: HashMap> = HashMap::default(); + map.insert(12, 42); + assert(map.len() == 1); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L213-L217 + + +### remove + +```rust title="remove" showLineNumbers +pub fn remove( + &mut self, + key: K + ) + where + K: Eq + Hash, + B: BuildHasher, + H: Hasher { +``` +> Source code: noir_stdlib/src/collections/map.nr#L356-L365 + + +Removes the given key-value pair from the map. If the key was not already present +in the map, this does nothing. + +Example: + +```rust title="remove_example" showLineNumbers +map.remove(12); + assert(map.is_empty()); + + // If a key was not present in the map, remove does nothing + map.remove(12); + assert(map.is_empty()); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L221-L228 + + +### is_empty + +```rust title="is_empty" showLineNumbers +pub fn is_empty(self) -> bool { +``` +> Source code: noir_stdlib/src/collections/map.nr#L115-L117 + + +True if the length of the hash map is empty. + +Example: + +```rust title="is_empty_example" showLineNumbers +assert(map.is_empty()); + + map.insert(1, 2); + assert(!map.is_empty()); + + map.remove(1); + assert(map.is_empty()); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L230-L238 + + +### len + +```rust title="len" showLineNumbers +pub fn len(self) -> u64 { +``` +> Source code: noir_stdlib/src/collections/map.nr#L264-L266 + + +Returns the current length of this hash map. + +Example: + +```rust title="len_example" showLineNumbers +// This is equivalent to checking map.is_empty() + assert(map.len() == 0); + + map.insert(1, 2); + map.insert(3, 4); + map.insert(5, 6); + assert(map.len() == 3); + + // 3 was already present as a key in the hash map, so the length is unchanged + map.insert(3, 7); + assert(map.len() == 3); + + map.remove(1); + assert(map.len() == 2); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L240-L255 + + +### capacity + +```rust title="capacity" showLineNumbers +pub fn capacity(_self: Self) -> u64 { +``` +> Source code: noir_stdlib/src/collections/map.nr#L271-L273 + + +Returns the maximum capacity of this hashmap. This is always equal to the capacity +specified in the hashmap's type. + +Unlike hashmaps in general purpose programming languages, hashmaps in Noir have a +static capacity that does not increase as the map grows larger. Thus, this capacity +is also the maximum possible element count that can be inserted into the hashmap. +Due to hash collisions (modulo the hashmap length), it is likely the actual maximum +element count will be lower than the full capacity. + +Example: + +```rust title="capacity_example" showLineNumbers +let empty_map: HashMap> = HashMap::default(); + assert(empty_map.len() == 0); + assert(empty_map.capacity() == 42); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L257-L261 + + +### clear + +```rust title="clear" showLineNumbers +pub fn clear(&mut self) { +``` +> Source code: noir_stdlib/src/collections/map.nr#L93-L95 + + +Clears the hashmap, removing all key-value pairs from it. + +Example: + +```rust title="clear_example" showLineNumbers +assert(!map.is_empty()); + map.clear(); + assert(map.is_empty()); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L263-L267 + + +### contains_key + +```rust title="contains_key" showLineNumbers +pub fn contains_key( + self, + key: K + ) -> bool + where + K: Hash + Eq, + B: BuildHasher, + H: Hasher { +``` +> Source code: noir_stdlib/src/collections/map.nr#L101-L110 + + +True if the hashmap contains the given key. Unlike `get`, this will not also return +the value associated with the key. + +Example: + +```rust title="contains_key_example" showLineNumbers +if map.contains_key(7) { + let value = map.get(7); + assert(value.is_some()); + } else { + println("No value for key 7!"); + } +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L269-L276 + + +### entries + +```rust title="entries" showLineNumbers +pub fn entries(self) -> BoundedVec<(K, V), N> { +``` +> Source code: noir_stdlib/src/collections/map.nr#L123-L125 + + +Returns a vector of each key-value pair present in the hashmap. + +The length of the returned vector is always equal to the length of the hashmap. + +Example: + +```rust title="entries_example" showLineNumbers +let entries = map.entries(); + + // The length of a hashmap may not be compile-time known, so we + // need to loop over its capacity instead + for i in 0..map.capacity() { + if i < entries.len() { + let (key, value) = entries.get(i); + println(f"{key} -> {value}"); + } + } +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L310-L321 + + +### keys + +```rust title="keys" showLineNumbers +pub fn keys(self) -> BoundedVec { +``` +> Source code: noir_stdlib/src/collections/map.nr#L144-L146 + + +Returns a vector of each key present in the hashmap. + +The length of the returned vector is always equal to the length of the hashmap. + +Example: + +```rust title="keys_example" showLineNumbers +let keys = map.keys(); + + for i in 0..keys.max_len() { + if i < keys.len() { + let key = keys.get_unchecked(i); + let value = map.get(key).unwrap_unchecked(); + println(f"{key} -> {value}"); + } + } +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L323-L333 + + +### values + +```rust title="values" showLineNumbers +pub fn values(self) -> BoundedVec { +``` +> Source code: noir_stdlib/src/collections/map.nr#L164-L166 + + +Returns a vector of each value present in the hashmap. + +The length of the returned vector is always equal to the length of the hashmap. + +Example: + +```rust title="values_example" showLineNumbers +let values = map.values(); + + for i in 0..values.max_len() { + if i < values.len() { + let value = values.get_unchecked(i); + println(f"Found value {value}"); + } + } +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L335-L344 + + +### iter_mut + +```rust title="iter_mut" showLineNumbers +pub fn iter_mut( + &mut self, + f: fn(K, V) -> (K, V) + ) + where + K: Eq + Hash, + B: BuildHasher, + H: Hasher { +``` +> Source code: noir_stdlib/src/collections/map.nr#L183-L192 + + +Iterates through each key-value pair of the HashMap, setting each key-value pair to the +result returned from the given function. + +Note that since keys can be mutated, the HashMap needs to be rebuilt as it is iterated +through. If this is not desired, use `iter_values_mut` if only values need to be mutated, +or `entries` if neither keys nor values need to be mutated. + +The iteration order is left unspecified. As a result, if two keys are mutated to become +equal, which of the two values that will be present for the key in the resulting map is also unspecified. + +Example: + +```rust title="iter_mut_example" showLineNumbers +// Add 1 to each key in the map, and double the value associated with that key. + map.iter_mut(|k, v| (k + 1, v * 2)); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L348-L351 + + +### iter_keys_mut + +```rust title="iter_keys_mut" showLineNumbers +pub fn iter_keys_mut( + &mut self, + f: fn(K) -> K + ) + where + K: Eq + Hash, + B: BuildHasher, + H: Hasher { +``` +> Source code: noir_stdlib/src/collections/map.nr#L208-L217 + + +Iterates through the HashMap, mutating each key to the result returned from +the given function. + +Note that since keys can be mutated, the HashMap needs to be rebuilt as it is iterated +through. If only iteration is desired and the keys are not intended to be mutated, +prefer using `entries` instead. + +The iteration order is left unspecified. As a result, if two keys are mutated to become +equal, which of the two values that will be present for the key in the resulting map is also unspecified. + +Example: + +```rust title="iter_keys_mut_example" showLineNumbers +// Double each key, leaving the value associated with that key untouched + map.iter_keys_mut(|k| k * 2); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L353-L356 + + +### iter_values_mut + +```rust title="iter_values_mut" showLineNumbers +pub fn iter_values_mut(&mut self, f: fn(V) -> V) { +``` +> Source code: noir_stdlib/src/collections/map.nr#L233-L235 + + +Iterates through the HashMap, applying the given function to each value and mutating the +value to equal the result. This function is more efficient than `iter_mut` and `iter_keys_mut` +because the keys are untouched and the underlying hashmap thus does not need to be reordered. + +Example: + +```rust title="iter_values_mut_example" showLineNumbers +// Halve each value + map.iter_values_mut(|v| v / 2); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L358-L361 + + +### retain + +```rust title="retain" showLineNumbers +pub fn retain(&mut self, f: fn(K, V) -> bool) { +``` +> Source code: noir_stdlib/src/collections/map.nr#L247-L249 + + +Retains only the key-value pairs for which the given function returns true. +Any key-value pairs for which the function returns false will be removed from the map. + +Example: + +```rust title="retain_example" showLineNumbers +map.retain(|k, v| (k != 0) & (v != 0)); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L281-L283 + + +## Trait Implementations + +### default + +```rust title="default" showLineNumbers +impl Default for HashMap +where + B: BuildHasher + Default, + H: Hasher + Default +{ + fn default() -> Self { +``` +> Source code: noir_stdlib/src/collections/map.nr#L462-L469 + + +Constructs an empty HashMap. + +Example: + +```rust title="default_example" showLineNumbers +let hashmap: HashMap> = HashMap::default(); + assert(hashmap.is_empty()); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L202-L205 + + +### eq + +```rust title="eq" showLineNumbers +impl Eq for HashMap +where + K: Eq + Hash, + V: Eq, + B: BuildHasher, + H: Hasher +{ + fn eq(self, other: HashMap) -> bool { +``` +> Source code: noir_stdlib/src/collections/map.nr#L426-L435 + + +Checks if two HashMaps are equal. + +Example: + +```rust title="eq_example" showLineNumbers +let mut map1: HashMap> = HashMap::default(); + let mut map2: HashMap> = HashMap::default(); + + map1.insert(1, 2); + map1.insert(3, 4); + + map2.insert(3, 4); + map2.insert(1, 2); + + assert(map1 == map2); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L285-L296 + diff --git a/docs/versioned_docs/version-v0.28.0/noir/standard_library/containers/index.md b/docs/versioned_docs/version-v0.28.0/noir/standard_library/containers/index.md new file mode 100644 index 00000000000..ea84c6d5c21 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/noir/standard_library/containers/index.md @@ -0,0 +1,5 @@ +--- +title: Containers +description: Container types provided by Noir's standard library for storing and retrieving data +keywords: [containers, data types, vec, hashmap] +--- diff --git a/docs/versioned_docs/version-v0.28.0/noir/standard_library/containers/vec.mdx b/docs/versioned_docs/version-v0.28.0/noir/standard_library/containers/vec.mdx new file mode 100644 index 00000000000..fcfd7e07aa0 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/noir/standard_library/containers/vec.mdx @@ -0,0 +1,151 @@ +--- +title: Vectors +description: Delve into the Vec data type in Noir. Learn about its methods, practical examples, and best practices for using Vectors in your Noir code. +keywords: [noir, vector type, methods, examples, dynamic arrays] +sidebar_position: 6 +--- + +import Experimental from '@site/src/components/Notes/_experimental.mdx'; + + + +A vector is a collection type similar to Rust's `Vec` type. In Noir, it is a convenient way to use slices as mutable arrays. + +Example: + +```rust +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 +``` + +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 +``` + +Example: + +```rust +let slice: [Field] = &[1, 2, 3]; +let vector_from_slice = Vec::from_slice(slice); +assert(vector_from_slice.len() == 3); +``` + +### len + +Returns the number of elements in the vector. + +```rust +pub fn len(self) -> Field +``` + +Example: + +```rust +let empty_vector: Vec = Vec::new(); +assert(empty_vector.len() == 0); +``` + +### 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 +``` + +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) +``` + +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 +``` + +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) +``` + +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 +``` + +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); +``` diff --git a/docs/versioned_docs/version-v0.28.0/noir/standard_library/cryptographic_primitives/_category_.json b/docs/versioned_docs/version-v0.28.0/noir/standard_library/cryptographic_primitives/_category_.json new file mode 100644 index 00000000000..5d694210bbf --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/noir/standard_library/cryptographic_primitives/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 0, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.28.0/noir/standard_library/cryptographic_primitives/ec_primitives.md b/docs/versioned_docs/version-v0.28.0/noir/standard_library/cryptographic_primitives/ec_primitives.md new file mode 100644 index 00000000000..d2b42d67b7c --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/noir/standard_library/cryptographic_primitives/ec_primitives.md @@ -0,0 +1,102 @@ +--- +title: Elliptic Curve Primitives +keywords: [cryptographic primitives, Noir project] +sidebar_position: 4 +--- + +Data structures and methods on them that allow you to carry out computations involving elliptic +curves over the (mathematical) field corresponding to `Field`. For the field currently at our +disposal, applications would involve a curve embedded in BN254, e.g. the +[Baby Jubjub curve](https://eips.ethereum.org/EIPS/eip-2494). + +## Data structures + +### Elliptic curve configurations + +(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Curve`), i.e. the specific elliptic +curve you want to use, which would be specified using any one of the methods +`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::new` which take the coefficients in the +defining equation together with a generator point as parameters. You can find more detail in the +comments in +[`noir_stdlib/src/ec.nr`](https://github.com/noir-lang/noir/blob/master/noir_stdlib/src/ec.nr), but +the gist of it is that the elliptic curves of interest are usually expressed in one of the standard +forms implemented here (Twisted Edwards, Montgomery and Short Weierstraß), and in addition to that, +you could choose to use `affine` coordinates (Cartesian coordinates - the usual (x,y) - possibly +together with a point at infinity) or `curvegroup` coordinates (some form of projective coordinates +requiring more coordinates but allowing for more efficient implementations of elliptic curve +operations). Conversions between all of these forms are provided, and under the hood these +conversions are done whenever an operation is more efficient in a different representation (or a +mixed coordinate representation is employed). + +### Points + +(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Point`), i.e. points lying on the +elliptic curve. For a curve configuration `c` and a point `p`, it may be checked that `p` +does indeed lie on `c` by calling `c.contains(p1)`. + +## Methods + +(given a choice of curve representation, e.g. use `std::ec::tecurve::affine::Curve` and use +`std::ec::tecurve::affine::Point`) + +- The **zero element** is given by `Point::zero()`, and we can verify whether a point `p: Point` is + zero by calling `p.is_zero()`. +- **Equality**: Points `p1: Point` and `p2: Point` may be checked for equality by calling + `p1.eq(p2)`. +- **Addition**: For `c: Curve` and points `p1: Point` and `p2: Point` on the curve, adding these two + points is accomplished by calling `c.add(p1,p2)`. +- **Negation**: For a point `p: Point`, `p.negate()` is its negation. +- **Subtraction**: For `c` and `p1`, `p2` as above, subtracting `p2` from `p1` is accomplished by + calling `c.subtract(p1,p2)`. +- **Scalar multiplication**: For `c` as above, `p: Point` a point on the curve and `n: Field`, + scalar multiplication is given by `c.mul(n,p)`. If instead `n :: [u1; N]`, i.e. `n` is a bit + array, the `bit_mul` method may be used instead: `c.bit_mul(n,p)` +- **Multi-scalar multiplication**: For `c` as above and arrays `n: [Field; N]` and `p: [Point; N]`, + multi-scalar multiplication is given by `c.msm(n,p)`. +- **Coordinate representation conversions**: The `into_group` method converts a point or curve + configuration in the affine representation to one in the CurveGroup representation, and + `into_affine` goes in the other direction. +- **Curve representation conversions**: `tecurve` and `montcurve` curves and points are equivalent + and may be converted between one another by calling `into_montcurve` or `into_tecurve` on their + configurations or points. `swcurve` is more general and a curve c of one of the other two types + may be converted to this representation by calling `c.into_swcurve()`, whereas a point `p` lying + on the curve given by `c` may be mapped to its corresponding `swcurve` point by calling + `c.map_into_swcurve(p)`. +- **Map-to-curve methods**: The Elligator 2 method of mapping a field element `n: Field` into a + `tecurve` or `montcurve` with configuration `c` may be called as `c.elligator2_map(n)`. For all of + the curve configurations, the SWU map-to-curve method may be called as `c.swu_map(z,n)`, where + `z: Field` depends on `Field` and `c` and must be chosen by the user (the conditions it needs to + satisfy are specified in the comments + [here](https://github.com/noir-lang/noir/blob/master/noir_stdlib/src/ec.nr)). + +## Examples + +The +[ec_baby_jubjub test](https://github.com/noir-lang/noir/blob/master/test_programs/compile_success_empty/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.28.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx b/docs/versioned_docs/version-v0.28.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx new file mode 100644 index 00000000000..4394b48f907 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx @@ -0,0 +1,98 @@ +--- +title: ECDSA Signature Verification +description: Learn about the cryptographic primitives regarding ECDSA over the secp256k1 and secp256r1 curves +keywords: [cryptographic primitives, Noir project, ecdsa, secp256k1, secp256r1, signatures] +sidebar_position: 3 +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +Noir supports ECDSA signatures verification over the secp256k1 and secp256r1 curves. + +## ecdsa_secp256k1::verify_signature + +Verifier for ECDSA Secp256k1 signatures. +See ecdsa_secp256k1::verify_signature_slice for a version that accepts slices directly. + +```rust title="ecdsa_secp256k1" showLineNumbers +pub fn verify_signature( + public_key_x: [u8; 32], + public_key_y: [u8; 32], + signature: [u8; 64], + message_hash: [u8; N] +) -> bool +``` +> Source code: noir_stdlib/src/ecdsa_secp256k1.nr#L2-L9 + + +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_secp256k1::verify_signature_slice + +Verifier for ECDSA Secp256k1 signatures where the message is a slice. + +```rust title="ecdsa_secp256k1_slice" showLineNumbers +pub fn verify_signature_slice( + public_key_x: [u8; 32], + public_key_y: [u8; 32], + signature: [u8; 64], + message_hash: [u8] +) -> bool +``` +> Source code: noir_stdlib/src/ecdsa_secp256k1.nr#L13-L20 + + + + +## ecdsa_secp256r1::verify_signature + +Verifier for ECDSA Secp256r1 signatures. +See ecdsa_secp256r1::verify_signature_slice for a version that accepts slices directly. + +```rust title="ecdsa_secp256r1" showLineNumbers +pub fn verify_signature( + public_key_x: [u8; 32], + public_key_y: [u8; 32], + signature: [u8; 64], + message_hash: [u8; N] +) -> bool +``` +> Source code: noir_stdlib/src/ecdsa_secp256r1.nr#L2-L9 + + +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); +} +``` + + + +## ecdsa_secp256r1::verify_signature + +Verifier for ECDSA Secp256r1 signatures where the message is a slice. + +```rust title="ecdsa_secp256r1_slice" showLineNumbers +pub fn verify_signature_slice( + public_key_x: [u8; 32], + public_key_y: [u8; 32], + signature: [u8; 64], + message_hash: [u8] +) -> bool +``` +> Source code: noir_stdlib/src/ecdsa_secp256r1.nr#L13-L20 + + + diff --git a/docs/versioned_docs/version-v0.28.0/noir/standard_library/cryptographic_primitives/eddsa.mdx b/docs/versioned_docs/version-v0.28.0/noir/standard_library/cryptographic_primitives/eddsa.mdx new file mode 100644 index 00000000000..c2c0624dfad --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/noir/standard_library/cryptographic_primitives/eddsa.mdx @@ -0,0 +1,37 @@ +--- +title: EdDSA Verification +description: Learn about the cryptographic primitives regarding EdDSA +keywords: [cryptographic primitives, Noir project, eddsa, signatures] +sidebar_position: 5 +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +## eddsa::eddsa_poseidon_verify + +Verifier for EdDSA signatures + +```rust +fn eddsa_poseidon_verify(public_key_x : Field, public_key_y : Field, signature_s: Field, signature_r8_x: Field, signature_r8_y: Field, message: Field) -> bool +``` + +It is also possible to specify the hash algorithm used for the signature by using the `eddsa_verify_with_hasher` function with a parameter implementing the Hasher trait. For instance, if you want to use Poseidon2 instead, you can do the following: +```rust +use dep::std::hash::poseidon2::Poseidon2Hasher; + +let mut hasher = Poseidon2Hasher::default(); +eddsa_verify_with_hasher(pub_key_a.x, pub_key_a.y, s_a, r8_a.x, r8_a.y, msg, &mut hasher); +``` + + + +## eddsa::eddsa_to_pub + +Private to public key conversion. + +Returns `(pub_key_x, pub_key_y)` + +```rust +fn eddsa_to_pub(secret : Field) -> (Field, Field) +``` + diff --git a/docs/versioned_docs/version-v0.28.0/noir/standard_library/cryptographic_primitives/hashes.mdx b/docs/versioned_docs/version-v0.28.0/noir/standard_library/cryptographic_primitives/hashes.mdx new file mode 100644 index 00000000000..87e113b96cd --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/noir/standard_library/cryptographic_primitives/hashes.mdx @@ -0,0 +1,250 @@ +--- +title: Hash methods +description: + Learn about the cryptographic primitives ready to use for any Noir project, including sha256, + blake2s, pedersen, mimc_bn254 and mimc +keywords: + [cryptographic primitives, Noir project, sha256, blake2s, pedersen, mimc_bn254, mimc, hash] +sidebar_position: 0 +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +## sha256 + +Given an array of bytes, returns the resulting sha256 hash. + +```rust title="sha256" showLineNumbers +pub fn sha256(input: [u8; N]) -> [u8; 32] +``` +> Source code: noir_stdlib/src/hash.nr#L9-L11 + + +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 title="blake2s" showLineNumbers +pub fn blake2s(input: [u8; N]) -> [u8; 32] +``` +> Source code: noir_stdlib/src/hash.nr#L15-L17 + + +example: + +```rust +fn main() { + let x = [163, 117, 178, 149]; // some random bytes + let hash = std::hash::blake2s(x); +} +``` + + + +## blake3 + +Given an array of bytes, returns an array with the Blake3 hash + +```rust title="blake3" showLineNumbers +pub fn blake3(input: [u8; N]) -> [u8; 32] +``` +> Source code: noir_stdlib/src/hash.nr#L21-L23 + + +example: + +```rust +fn main() { + let x = [163, 117, 178, 149]; // some random bytes + let hash = std::hash::blake3(x); +} +``` + + + +## pedersen_hash + +Given an array of Fields, returns the Pedersen hash. + +```rust title="pedersen_hash" showLineNumbers +pub fn pedersen_hash(input: [Field; N]) -> Field +``` +> Source code: noir_stdlib/src/hash.nr#L45-L47 + + +example: + +```rust title="pedersen-hash" showLineNumbers +use dep::std; + +fn main(x: Field, y: Field, expected_hash: Field) { + let hash = std::hash::pedersen_hash([x, y]); + assert_eq(hash, expected_hash); +} +``` +> Source code: test_programs/execution_success/pedersen_hash/src/main.nr#L1-L8 + + + + +## pedersen_commitment + +Given an array of Fields, returns the Pedersen commitment. + +```rust title="pedersen_commitment" showLineNumbers +struct PedersenPoint { + x : Field, + y : Field, +} + +pub fn pedersen_commitment(input: [Field; N]) -> PedersenPoint { +``` +> Source code: noir_stdlib/src/hash.nr#L26-L33 + + +example: + +```rust title="pedersen-commitment" showLineNumbers +use dep::std; + +fn main(x: Field, y: Field, expected_commitment: std::hash::PedersenPoint) { + let commitment = std::hash::pedersen_commitment([x, y]); + assert_eq(commitment.x, expected_commitment.x); + assert_eq(commitment.y, expected_commitment.y); +} +``` +> Source code: test_programs/execution_success/pedersen_commitment/src/main.nr#L1-L9 + + + + +## 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 title="keccak256" showLineNumbers +pub fn keccak256(input: [u8; N], message_size: u32) -> [u8; 32] +``` +> Source code: noir_stdlib/src/hash.nr#L67-L69 + + +example: + +```rust title="keccak256" showLineNumbers +use dep::std; + +fn main(x: Field, result: [u8; 32]) { + // We use the `as` keyword here to denote the fact that we want to take just the first byte from the x Field + // The padding is taken care of by the program + let digest = std::hash::keccak256([x as u8], 1); + assert(digest == result); + + //#1399: variable message 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); + + 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); + + assert(hash_a != hash_c); +} +``` +> Source code: test_programs/execution_success/keccak256/src/main.nr#L1-L22 + + + + +## 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 title="poseidon" showLineNumbers +use dep::std::hash::poseidon; +use dep::std::hash::poseidon2; + +fn main(x1: [Field; 2], y1: pub Field, x2: [Field; 4], y2: pub Field, x3: [Field; 4], y3: Field) { + let hash1 = poseidon::bn254::hash_2(x1); + assert(hash1 == y1); + + let hash2 = poseidon::bn254::hash_4(x2); + assert(hash2 == y2); + + let hash3 = poseidon2::Poseidon2::hash(x3, x3.len()); + assert(hash3 == y3); +} +``` +> Source code: test_programs/execution_success/poseidon_bn254_hash/src/main.nr#L1-L15 + + +## poseidon 2 + +Given an array of Fields, returns a new Field with the Poseidon2 Hash. Contrary to the Poseidon +function, there is only one hash and you can specify a message_size to hash only the first +`message_size` bytes of the input, + +```rust +// example for hashing the first three elements of the input +Poseidon2::hash(input, 3); +``` + +The above example for Poseidon also includes Poseidon2. + +## 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]) -> 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.28.0/noir/standard_library/cryptographic_primitives/index.md b/docs/versioned_docs/version-v0.28.0/noir/standard_library/cryptographic_primitives/index.md new file mode 100644 index 00000000000..650f30165d5 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/noir/standard_library/cryptographic_primitives/index.md @@ -0,0 +1,14 @@ +--- +title: Cryptographic Primitives +description: + Learn about the cryptographic primitives ready to use for any Noir project +keywords: + [ + cryptographic primitives, + Noir project, + ] +--- + +The Noir team is progressively adding new cryptographic primitives to the standard library. Reach out for news or if you would be interested in adding more of these calculations in Noir. + +Some methods are available thanks to the Aztec backend, not being performed using Noir. When using other backends, these methods may or may not be supplied. diff --git a/docs/versioned_docs/version-v0.28.0/noir/standard_library/cryptographic_primitives/scalar.mdx b/docs/versioned_docs/version-v0.28.0/noir/standard_library/cryptographic_primitives/scalar.mdx new file mode 100644 index 00000000000..df411ca5443 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/noir/standard_library/cryptographic_primitives/scalar.mdx @@ -0,0 +1,33 @@ +--- +title: Scalar multiplication +description: See how you can perform scalar multiplications over a fixed base in Noir +keywords: [cryptographic primitives, Noir project, scalar multiplication] +sidebar_position: 1 +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +## scalar_mul::fixed_base_embedded_curve + +Performs scalar multiplication over the embedded curve whose coordinates are defined by the +configured noir field. For the BN254 scalar field, this is BabyJubJub or Grumpkin. + +```rust title="fixed_base_embedded_curve" showLineNumbers +pub fn fixed_base_embedded_curve( + low: Field, + high: Field +) -> [Field; 2] +``` +> Source code: noir_stdlib/src/scalar_mul.nr#L27-L32 + + +example + +```rust +fn main(x : Field) { + let scal = std::scalar_mul::fixed_base_embedded_curve(x); + println(scal); +} +``` + + diff --git a/docs/versioned_docs/version-v0.28.0/noir/standard_library/cryptographic_primitives/schnorr.mdx b/docs/versioned_docs/version-v0.28.0/noir/standard_library/cryptographic_primitives/schnorr.mdx new file mode 100644 index 00000000000..b59e69c8f07 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/noir/standard_library/cryptographic_primitives/schnorr.mdx @@ -0,0 +1,64 @@ +--- +title: Schnorr Signatures +description: Learn how you can verify Schnorr signatures using Noir +keywords: [cryptographic primitives, Noir project, schnorr, signatures] +sidebar_position: 2 +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +## schnorr::verify_signature + +Verifier for Schnorr signatures over the embedded curve (for BN254 it is Grumpkin). +See schnorr::verify_signature_slice for a version that works directly on slices. + +```rust title="schnorr_verify" showLineNumbers +pub fn verify_signature( + public_key_x: Field, + public_key_y: Field, + signature: [u8; 64], + message: [u8; N] +) -> bool +``` +> Source code: noir_stdlib/src/schnorr.nr#L2-L9 + + +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() +); + +... +``` + + + +## schnorr::verify_signature_slice + +Verifier for Schnorr signatures over the embedded curve (for BN254 it is Grumpkin) +where the message is a slice. + +```rust title="schnorr_verify_slice" showLineNumbers +pub fn verify_signature_slice( + public_key_x: Field, + public_key_y: Field, + signature: [u8; 64], + message: [u8] +) -> bool +``` +> Source code: noir_stdlib/src/schnorr.nr#L13-L20 + + + diff --git a/docs/versioned_docs/version-v0.28.0/noir/standard_library/logging.md b/docs/versioned_docs/version-v0.28.0/noir/standard_library/logging.md new file mode 100644 index 00000000000..db75ef9f86f --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/noir/standard_library/logging.md @@ -0,0 +1,78 @@ +--- +title: Logging +description: + Learn how to use the println statement for debugging in Noir with this tutorial. Understand the + basics of logging in Noir and how to implement it in your code. +keywords: + [ + noir logging, + println statement, + print statement, + debugging in noir, + noir std library, + logging tutorial, + basic logging in noir, + noir logging implementation, + noir debugging techniques, + rust, + ] +--- + +The standard library provides two familiar statements you can use: `println` and `print`. Despite being a limited implementation of rust's `println!` and `print!` macros, these constructs can be useful for debugging. + +You can print the output of both statements in your Noir code by using the `nargo execute` command or the `--show-output` flag when using `nargo test` (provided there are print statements in your tests). + +It is recommended to use `nargo execute` if you want to debug failing constraints with `println` or `print` statements. This is due to every input in a test being a constant rather than a witness, so we issue an error during compilation while we only print during execution (which comes after compilation). Neither `println`, nor `print` are callable for failed constraints caught at compile time. + +Both `print` and `println` are generic functions which can work on integers, fields, strings, and even structs or expressions. Note however, that slices are currently unsupported. For example: + +```rust +struct Person { + age: Field, + height: Field, +} + +fn main(age: Field, height: Field) { + let person = Person { + age: age, + height: height, + }; + println(person); + println(age + height); + println("Hello world!"); +} +``` + +You can print different types in the same statement (including strings) with a type called `fmtstr`. It can be specified in the same way as a normal string, just prepended with an "f" character: + +```rust + let fmt_str = f"i: {i}, j: {j}"; + println(fmt_str); + + let s = myStruct { y: x, x: y }; + println(s); + + println(f"i: {i}, s: {s}"); + + println(x); + println([x, y]); + + let foo = fooStruct { my_struct: s, foo: 15 }; + println(f"s: {s}, foo: {foo}"); + + println(15); // prints 0x0f, implicit Field + println(-1 as u8); // prints 255 + println(-1 as i8); // prints -1 +``` + +Examples shown above are interchangeable between the two `print` statements: + +```rust +let person = Person { age : age, height : height }; + +println(person); +print(person); + +println("Hello world!"); // Prints with a newline at the end of the input +print("Hello world!"); // Prints the input and keeps cursor on the same line +``` diff --git a/docs/versioned_docs/version-v0.28.0/noir/standard_library/merkle_trees.md b/docs/versioned_docs/version-v0.28.0/noir/standard_library/merkle_trees.md new file mode 100644 index 00000000000..6a9ebf72ada --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/noir/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/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.as_slice()); + 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.28.0/noir/standard_library/options.md b/docs/versioned_docs/version-v0.28.0/noir/standard_library/options.md new file mode 100644 index 00000000000..a1bd4e1de5f --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/noir/standard_library/options.md @@ -0,0 +1,101 @@ +--- +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), +} +``` + +The `Option` type, already imported into your Noir program, can be used directly: + +```rust +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. + +### expect + +Asserts `self.is_some()` with a provided custom message and returns the contained `Some` value. The custom message is expected to be a format string. + +### 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.28.0/noir/standard_library/recursion.md b/docs/versioned_docs/version-v0.28.0/noir/standard_library/recursion.md new file mode 100644 index 00000000000..a93894043dc --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/noir/standard_library/recursion.md @@ -0,0 +1,88 @@ +--- +title: Recursive Proofs +description: Learn about how to write recursive proofs in Noir. +keywords: [recursion, recursive proofs, verification_key, 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. + +Read [the explainer on recursion](../../explainers/explainer-recursion.md) to know more about this function and the [guide on how to use it.](../../how_to/how-to-recursion.md) + +## The `#[recursive]` Attribute + +In Noir, the `#[recursive]` attribute is used to indicate that a circuit is designed for recursive proof generation. When applied, it informs the compiler and the tooling that the circuit should be compiled in a way that makes its proofs suitable for recursive verification. This attribute eliminates the need for manual flagging of recursion at the tooling level, streamlining the proof generation process for recursive circuits. + +### Example usage with `#[recursive]` + +```rust +#[recursive] +fn main(x: Field, y: pub Field) { + assert(x == y, "x and y are not equal"); +} + +// This marks the circuit as recursion-friendly and indicates that proofs generated from this circuit +// are intended for recursive verification. +``` + +By incorporating this attribute directly in the circuit's definition, tooling like Nargo and NoirJS can automatically execute recursive-specific duties for Noir programs (e.g. recursive-friendly proof artifact generation) without additional flags or configurations. + +## Verifying Recursive Proofs + +```rust +#[foreign(recursive_aggregation)] +pub fn verify_proof(verification_key: [Field], proof: [Field], public_inputs: [Field], key_hash: Field) {} +``` + +:::info + +This is a black box function. Read [this section](./black_box_fns) to learn more about black box functions in Noir. + +::: + +## Example usage + +```rust +use dep::std; + +fn main( + verification_key : [Field; 114], + proof : [Field; 93], + public_inputs : [Field; 1], + key_hash : Field, + proof_b : [Field; 93], +) { + std::verify_proof( + verification_key.as_slice(), + proof.as_slice(), + public_inputs.as_slice(), + key_hash + ); + + std::verify_proof( + verification_key.as_slice(), + proof_b.as_slice(), + public_inputs.as_slice(), + key_hash + ); +} +``` + +You can see a full example of recursive proofs in [this example recursion demo repo](https://github.com/noir-lang/noir-examples/tree/master/recursion). + +## 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. + +### `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. diff --git a/docs/versioned_docs/version-v0.28.0/noir/standard_library/traits.md b/docs/versioned_docs/version-v0.28.0/noir/standard_library/traits.md new file mode 100644 index 00000000000..94337e77a3e --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/noir/standard_library/traits.md @@ -0,0 +1,410 @@ +--- +title: Traits +description: Noir's stdlib provides a few commonly used traits. +keywords: [traits, trait, interface, protocol, default, add, eq] +--- + +## `std::default` + +### `std::default::Default` + +```rust title="default-trait" showLineNumbers +trait Default { + fn default() -> Self; +} +``` +> Source code: noir_stdlib/src/default.nr#L1-L5 + + +Constructs a default value of a type. + +Implementations: +```rust +impl Default for Field { .. } + +impl Default for i8 { .. } +impl Default for i16 { .. } +impl Default for i32 { .. } +impl Default for i64 { .. } + +impl Default for u8 { .. } +impl Default for u16 { .. } +impl Default for u32 { .. } +impl Default for u64 { .. } + +impl Default for () { .. } +impl Default for bool { .. } + +impl Default for [T; N] + where T: Default { .. } + +impl Default for [T] { .. } + +impl Default for (A, B) + where A: Default, B: Default { .. } + +impl Default for (A, B, C) + where A: Default, B: Default, C: Default { .. } + +impl Default for (A, B, C, D) + where A: Default, B: Default, C: Default, D: Default { .. } + +impl Default for (A, B, C, D, E) + where A: Default, B: Default, C: Default, D: Default, E: Default { .. } +``` + +For primitive integer types, the return value of `default` is `0`. Container +types such as arrays are filled with default values of their element type, +except slices whose length is unknown and thus defaulted to zero. + + +## `std::convert` + +### `std::convert::From` + +```rust title="from-trait" showLineNumbers +trait From { + fn from(input: T) -> Self; +} +``` +> Source code: noir_stdlib/src/convert.nr#L1-L5 + + +The `From` trait defines how to convert from a given type `T` to the type on which the trait is implemented. + +The Noir standard library provides a number of implementations of `From` between primitive types. +```rust title="from-impls" showLineNumbers +// Unsigned integers + +impl From for u32 { fn from(value: u8) -> u32 { value as u32 } } + +impl From for u64 { fn from(value: u8) -> u64 { value as u64 } } +impl From for u64 { fn from(value: u32) -> u64 { value as u64 } } + +impl From for Field { fn from(value: u8) -> Field { value as Field } } +impl From for Field { fn from(value: u32) -> Field { value as Field } } +impl From for Field { fn from(value: u64) -> Field { value as Field } } + +// Signed integers + +impl From for i32 { fn from(value: i8) -> i32 { value as i32 } } + +impl From for i64 { fn from(value: i8) -> i64 { value as i64 } } +impl From for i64 { fn from(value: i32) -> i64 { value as i64 } } + +// Booleans +impl From for u8 { fn from(value: bool) -> u8 { value as u8 } } +impl From for u32 { fn from(value: bool) -> u32 { value as u32 } } +impl From for u64 { fn from(value: bool) -> u64 { value as u64 } } +impl From for i8 { fn from(value: bool) -> i8 { value as i8 } } +impl From for i32 { fn from(value: bool) -> i32 { value as i32 } } +impl From for i64 { fn from(value: bool) -> i64 { value as i64 } } +impl From for Field { fn from(value: bool) -> Field { value as Field } } +``` +> Source code: noir_stdlib/src/convert.nr#L25-L52 + + +#### When to implement `From` + +As a general rule of thumb, `From` may be implemented in the [situations where it would be suitable in Rust](https://doc.rust-lang.org/std/convert/trait.From.html#when-to-implement-from): + +- The conversion is *infallible*: Noir does not provide an equivalent to Rust's `TryFrom`, if the conversion can fail then provide a named method instead. +- The conversion is *lossless*: semantically, it should not lose or discard information. For example, `u32: From` can losslessly convert any `u16` into a valid `u32` such that the original `u16` can be recovered. On the other hand, `u16: From` should not be implemented as `2**16` is a `u32` which cannot be losslessly converted into a `u16`. +- The conversion is *value-preserving*: the conceptual kind and meaning of the resulting value is the same, even though the Noir type and technical representation might be different. While it's possible to infallibly and losslessly convert a `u8` into a `str<2>` hex representation, `4u8` and `"04"` are too different for `str<2>: From` to be implemented. +- The conversion is *obvious*: it's the only reasonable conversion between the two types. If there's ambiguity on how to convert between them such that the same input could potentially map to two different values then a named method should be used. For instance rather than implementing `U128: From<[u8; 16]>`, the methods `U128::from_le_bytes` and `U128::from_be_bytes` are used as otherwise the endianness of the array would be ambiguous, resulting in two potential values of `U128` from the same byte array. + +One additional recommendation specific to Noir is: +- The conversion is *efficient*: it's relatively cheap to convert between the two types. Due to being a ZK DSL, it's more important to avoid unnecessary computation compared to Rust. If the implementation of `From` would encourage users to perform unnecessary conversion, resulting in additional proving time, then it may be preferable to expose functionality such that this conversion may be avoided. + +### `std::convert::Into` + +The `Into` trait is defined as the reciprocal of `From`. It should be easy to convince yourself that if we can convert to type `A` from type `B`, then it's possible to convert type `B` into type `A`. + +For this reason, implementing `From` on a type will automatically generate a matching `Into` implementation. One should always prefer implementing `From` over `Into` as implementing `Into` will not generate a matching `From` implementation. + +```rust title="into-trait" showLineNumbers +trait Into { + fn into(self) -> T; +} + +impl Into for U where T: From { + fn into(self) -> T { + T::from(self) + } +} +``` +> Source code: noir_stdlib/src/convert.nr#L13-L23 + + +`Into` is most useful when passing function arguments where the types don't quite match up with what the function expects. In this case, the compiler has enough type information to perform the necessary conversion by just appending `.into()` onto the arguments in question. + + +## `std::cmp` + +### `std::cmp::Eq` + +```rust title="eq-trait" showLineNumbers +trait Eq { + fn eq(self, other: Self) -> bool; +} +``` +> Source code: noir_stdlib/src/cmp.nr#L1-L5 + + +Returns `true` if `self` is equal to `other`. Implementing this trait on a type +allows the type to be used with `==` and `!=`. + +Implementations: +```rust +impl Eq for Field { .. } + +impl Eq for i8 { .. } +impl Eq for i16 { .. } +impl Eq for i32 { .. } +impl Eq for i64 { .. } + +impl Eq for u8 { .. } +impl Eq for u16 { .. } +impl Eq for u32 { .. } +impl Eq for u64 { .. } + +impl Eq for () { .. } +impl Eq for bool { .. } + +impl Eq for [T; N] + where T: Eq { .. } + +impl Eq for [T] + where T: Eq { .. } + +impl Eq for (A, B) + where A: Eq, B: Eq { .. } + +impl Eq for (A, B, C) + where A: Eq, B: Eq, C: Eq { .. } + +impl Eq for (A, B, C, D) + where A: Eq, B: Eq, C: Eq, D: Eq { .. } + +impl Eq for (A, B, C, D, E) + where A: Eq, B: Eq, C: Eq, D: Eq, E: Eq { .. } +``` + +### `std::cmp::Ord` + +```rust title="ord-trait" showLineNumbers +trait Ord { + fn cmp(self, other: Self) -> Ordering; +} +``` +> Source code: noir_stdlib/src/cmp.nr#L102-L106 + + +`a.cmp(b)` compares two values returning `Ordering::less()` if `a < b`, +`Ordering::equal()` if `a == b`, or `Ordering::greater()` if `a > b`. +Implementing this trait on a type allows `<`, `<=`, `>`, and `>=` to be +used on values of the type. + +`std::cmp` also provides `max` and `min` functions for any type which implements the `Ord` trait. + +Implementations: + +```rust +impl Ord for u8 { .. } +impl Ord for u16 { .. } +impl Ord for u32 { .. } +impl Ord for u64 { .. } + +impl Ord for i8 { .. } +impl Ord for i16 { .. } +impl Ord for i32 { .. } + +impl Ord for i64 { .. } + +impl Ord for () { .. } +impl Ord for bool { .. } + +impl Ord for [T; N] + where T: Ord { .. } + +impl Ord for [T] + where T: Ord { .. } + +impl Ord for (A, B) + where A: Ord, B: Ord { .. } + +impl Ord for (A, B, C) + where A: Ord, B: Ord, C: Ord { .. } + +impl Ord for (A, B, C, D) + where A: Ord, B: Ord, C: Ord, D: Ord { .. } + +impl Ord for (A, B, C, D, E) + where A: Ord, B: Ord, C: Ord, D: Ord, E: Ord { .. } +``` + +## `std::ops` + +### `std::ops::Add`, `std::ops::Sub`, `std::ops::Mul`, and `std::ops::Div` + +These traits abstract over addition, subtraction, multiplication, and division respectively. +Implementing these traits for a given type will also allow that type to be used with the corresponding operator +for that trait (`+` for Add, etc) in addition to the normal method names. + +```rust title="add-trait" showLineNumbers +trait Add { + fn add(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L1-L5 + +```rust title="sub-trait" showLineNumbers +trait Sub { + fn sub(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L17-L21 + +```rust title="mul-trait" showLineNumbers +trait Mul { + fn mul(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L33-L37 + +```rust title="div-trait" showLineNumbers +trait Div { + fn div(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L49-L53 + + +The implementations block below is given for the `Add` trait, but the same types that implement +`Add` also implement `Sub`, `Mul`, and `Div`. + +Implementations: +```rust +impl Add for Field { .. } + +impl Add for i8 { .. } +impl Add for i16 { .. } +impl Add for i32 { .. } +impl Add for i64 { .. } + +impl Add for u8 { .. } +impl Add for u16 { .. } +impl Add for u32 { .. } +impl Add for u64 { .. } +``` + +### `std::ops::Rem` + +```rust title="rem-trait" showLineNumbers +trait Rem{ + fn rem(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L65-L69 + + +`Rem::rem(a, b)` is the remainder function returning the result of what is +left after dividing `a` and `b`. Implementing `Rem` allows the `%` operator +to be used with the implementation type. + +Unlike other numeric traits, `Rem` is not implemented for `Field`. + +Implementations: +```rust +impl Rem for u8 { fn rem(self, other: u8) -> u8 { self % other } } +impl Rem for u16 { fn rem(self, other: u16) -> u16 { self % other } } +impl Rem for u32 { fn rem(self, other: u32) -> u32 { self % other } } +impl Rem for u64 { fn rem(self, other: u64) -> u64 { self % other } } + +impl Rem for i8 { fn rem(self, other: i8) -> i8 { self % other } } +impl Rem for i16 { fn rem(self, other: i16) -> i16 { self % other } } +impl Rem for i32 { fn rem(self, other: i32) -> i32 { self % other } } +impl Rem for i64 { fn rem(self, other: i64) -> i64 { self % other } } +``` + +### `std::ops::{ BitOr, BitAnd, BitXor }` + +```rust title="bitor-trait" showLineNumbers +trait BitOr { + fn bitor(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L79-L83 + +```rust title="bitand-trait" showLineNumbers +trait BitAnd { + fn bitand(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L95-L99 + +```rust title="bitxor-trait" showLineNumbers +trait BitXor { + fn bitxor(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L111-L115 + + +Traits for the bitwise operations `|`, `&`, and `^`. + +Implementing `BitOr`, `BitAnd` or `BitXor` for a type allows the `|`, `&`, or `^` operator respectively +to be used with the type. + +The implementations block below is given for the `BitOr` trait, but the same types that implement +`BitOr` also implement `BitAnd` and `BitXor`. + +Implementations: +```rust +impl BitOr for bool { fn bitor(self, other: bool) -> bool { self | other } } + +impl BitOr for u8 { fn bitor(self, other: u8) -> u8 { self | other } } +impl BitOr for u16 { fn bitor(self, other: u16) -> u16 { self | other } } +impl BitOr for u32 { fn bitor(self, other: u32) -> u32 { self | other } } +impl BitOr for u64 { fn bitor(self, other: u64) -> u64 { self | other } } + +impl BitOr for i8 { fn bitor(self, other: i8) -> i8 { self | other } } +impl BitOr for i16 { fn bitor(self, other: i16) -> i16 { self | other } } +impl BitOr for i32 { fn bitor(self, other: i32) -> i32 { self | other } } +impl BitOr for i64 { fn bitor(self, other: i64) -> i64 { self | other } } +``` + +### `std::ops::{ Shl, Shr }` + +```rust title="shl-trait" showLineNumbers +trait Shl { + fn shl(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L127-L131 + +```rust title="shr-trait" showLineNumbers +trait Shr { + fn shr(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L142-L146 + + +Traits for a bit shift left and bit shift right. + +Implementing `Shl` for a type allows the left shift operator (`<<`) to be used with the implementation type. +Similarly, implementing `Shr` allows the right shift operator (`>>`) to be used with the type. + +Note that bit shifting is not currently implemented for signed types. + +The implementations block below is given for the `Shl` trait, but the same types that implement +`Shl` also implement `Shr`. + +Implementations: +```rust +impl Shl for u8 { fn shl(self, other: u8) -> u8 { self << other } } +impl Shl for u16 { fn shl(self, other: u16) -> u16 { self << other } } +impl Shl for u32 { fn shl(self, other: u32) -> u32 { self << other } } +impl Shl for u64 { fn shl(self, other: u64) -> u64 { self << other } } +``` diff --git a/docs/versioned_docs/version-v0.28.0/noir/standard_library/zeroed.md b/docs/versioned_docs/version-v0.28.0/noir/standard_library/zeroed.md new file mode 100644 index 00000000000..f450fecdd36 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/noir/standard_library/zeroed.md @@ -0,0 +1,26 @@ +--- +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 +- Slice +- String +- Tuple +- Function + +Using it on other types could result in unexpected behavior. diff --git a/docs/versioned_docs/version-v0.28.0/reference/NoirJS/backend_barretenberg/.nojekyll b/docs/versioned_docs/version-v0.28.0/reference/NoirJS/backend_barretenberg/.nojekyll new file mode 100644 index 00000000000..e2ac6616add --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/reference/NoirJS/backend_barretenberg/.nojekyll @@ -0,0 +1 @@ +TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.28.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md b/docs/versioned_docs/version-v0.28.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md new file mode 100644 index 00000000000..d7249d24330 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md @@ -0,0 +1,160 @@ +# BarretenbergBackend + +## Extends + +- `BarretenbergVerifierBackend` + +## Implements + +- [`Backend`](../index.md#backend) + +## Constructors + +### new BarretenbergBackend(acirCircuit, options) + +```ts +new BarretenbergBackend(acirCircuit, options): BarretenbergBackend +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `acirCircuit` | `CompiledCircuit` | +| `options` | [`BackendOptions`](../type-aliases/BackendOptions.md) | + +#### Returns + +[`BarretenbergBackend`](BarretenbergBackend.md) + +#### Inherited from + +BarretenbergVerifierBackend.constructor + +## Properties + +| Property | Type | Description | Inheritance | +| :------ | :------ | :------ | :------ | +| `acirComposer` | `any` | - | BarretenbergVerifierBackend.acirComposer | +| `acirUncompressedBytecode` | `Uint8Array` | - | BarretenbergVerifierBackend.acirUncompressedBytecode | +| `api` | `Barretenberg` | - | BarretenbergVerifierBackend.api | +| `options` | [`BackendOptions`](../type-aliases/BackendOptions.md) | - | BarretenbergVerifierBackend.options | + +## Methods + +### destroy() + +```ts +destroy(): Promise +``` + +#### Returns + +`Promise`\<`void`\> + +#### Inherited from + +BarretenbergVerifierBackend.destroy + +*** + +### generateProof() + +```ts +generateProof(compressedWitness): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `compressedWitness` | `Uint8Array` | + +#### Returns + +`Promise`\<`ProofData`\> + +#### Description + +Generates a proof + +*** + +### generateRecursiveProofArtifacts() + +```ts +generateRecursiveProofArtifacts(proofData, numOfPublicInputs): Promise +``` + +Generates artifacts that will be passed to a circuit that will verify this proof. + +Instead of passing the proof and verification key as a byte array, we pass them +as fields which makes it cheaper to verify in a circuit. + +The proof that is passed here will have been created using a circuit +that has the #[recursive] attribute on its `main` method. + +The number of public inputs denotes how many public inputs are in the inner proof. + +#### Parameters + +| Parameter | Type | Default value | +| :------ | :------ | :------ | +| `proofData` | `ProofData` | `undefined` | +| `numOfPublicInputs` | `number` | `0` | + +#### Returns + +`Promise`\<`object`\> + +#### Example + +```typescript +const artifacts = await backend.generateRecursiveProofArtifacts(proof, numOfPublicInputs); +``` + +*** + +### getVerificationKey() + +```ts +getVerificationKey(): Promise +``` + +#### Returns + +`Promise`\<`Uint8Array`\> + +#### Inherited from + +BarretenbergVerifierBackend.getVerificationKey + +*** + +### verifyProof() + +```ts +verifyProof(proofData): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `proofData` | `ProofData` | + +#### Returns + +`Promise`\<`boolean`\> + +#### Inherited from + +BarretenbergVerifierBackend.verifyProof + +#### Description + +Verifies 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.28.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergVerifier.md b/docs/versioned_docs/version-v0.28.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergVerifier.md new file mode 100644 index 00000000000..500276ea748 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergVerifier.md @@ -0,0 +1,58 @@ +# BarretenbergVerifier + +## Constructors + +### new BarretenbergVerifier(options) + +```ts +new BarretenbergVerifier(options): BarretenbergVerifier +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `options` | [`BackendOptions`](../type-aliases/BackendOptions.md) | + +#### Returns + +[`BarretenbergVerifier`](BarretenbergVerifier.md) + +## Methods + +### destroy() + +```ts +destroy(): Promise +``` + +#### Returns + +`Promise`\<`void`\> + +*** + +### verifyProof() + +```ts +verifyProof(proofData, verificationKey): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `proofData` | `ProofData` | +| `verificationKey` | `Uint8Array` | + +#### Returns + +`Promise`\<`boolean`\> + +#### Description + +Verifies 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.28.0/reference/NoirJS/backend_barretenberg/index.md b/docs/versioned_docs/version-v0.28.0/reference/NoirJS/backend_barretenberg/index.md new file mode 100644 index 00000000000..64971973196 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/reference/NoirJS/backend_barretenberg/index.md @@ -0,0 +1,59 @@ +# backend_barretenberg + +## Exports + +### Classes + +| Class | Description | +| :------ | :------ | +| [BarretenbergBackend](classes/BarretenbergBackend.md) | - | +| [BarretenbergVerifier](classes/BarretenbergVerifier.md) | - | + +### Type Aliases + +| Type alias | Description | +| :------ | :------ | +| [BackendOptions](type-aliases/BackendOptions.md) | - | + +## References + +### CompiledCircuit + +Renames and re-exports [Backend](index.md#backend) + +*** + +### ProofData + +Renames and re-exports [Backend](index.md#backend) + +## Variables + +### Backend + +```ts +Backend: any; +``` + +## Functions + +### publicInputsToWitnessMap() + +```ts +publicInputsToWitnessMap(publicInputs, abi): Backend +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `publicInputs` | `string`[] | +| `abi` | `Abi` | + +#### Returns + +[`Backend`](index.md#backend) + +*** + +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.28.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md b/docs/versioned_docs/version-v0.28.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md new file mode 100644 index 00000000000..b49a479f4f4 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md @@ -0,0 +1,21 @@ +# 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 | +| :------ | :------ | :------ | +| `memory` | `object` | - | +| `memory.maximum` | `number` | - | +| `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.28.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs b/docs/versioned_docs/version-v0.28.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs new file mode 100644 index 00000000000..d7d5128f9e3 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs @@ -0,0 +1,4 @@ +// @ts-check +/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ +const typedocSidebar = { items: [{"type":"category","label":"Classes","items":[{"type":"doc","id":"reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend","label":"BarretenbergBackend"},{"type":"doc","id":"reference/NoirJS/backend_barretenberg/classes/BarretenbergVerifier","label":"BarretenbergVerifier"}]},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions","label":"BackendOptions"}]}]}; +module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/.nojekyll b/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/.nojekyll new file mode 100644 index 00000000000..e2ac6616add --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/.nojekyll @@ -0,0 +1 @@ +TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/classes/Noir.md b/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/classes/Noir.md new file mode 100644 index 00000000000..45dd62ee57e --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/classes/Noir.md @@ -0,0 +1,132 @@ +# Noir + +## Constructors + +### new Noir(circuit, backend) + +```ts +new Noir(circuit, backend?): Noir +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `circuit` | `CompiledCircuit` | +| `backend`? | `any` | + +#### 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) +``` + +*** + +### generateProof() + +```ts +generateProof(inputs, foreignCallHandler?): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `inputs` | `InputMap` | +| `foreignCallHandler`? | [`ForeignCallHandler`](../type-aliases/ForeignCallHandler.md) | + +#### Returns + +`Promise`\<`ProofData`\> + +#### Description + +Generates a witness and a proof given an object as input. + +#### Example + +```typescript +async generateProof(input) +``` + +*** + +### verifyProof() + +```ts +verifyProof(proofData): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `proofData` | `ProofData` | + +#### Returns + +`Promise`\<`boolean`\> + +#### Description + +Instantiates the verification key and verifies a proof. + +#### Example + +```typescript +async verifyProof(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.28.0/reference/NoirJS/noir_js/functions/and.md b/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/functions/and.md new file mode 100644 index 00000000000..c783283e396 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/functions/and.md @@ -0,0 +1,22 @@ +# and() + +```ts +and(lhs, rhs): string +``` + +Performs a bitwise AND operation between `lhs` and `rhs` + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `lhs` | `string` | | +| `rhs` | `string` | | + +## Returns + +`string` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/functions/blake2s256.md b/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/functions/blake2s256.md new file mode 100644 index 00000000000..7882d0da8d5 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/functions/blake2s256.md @@ -0,0 +1,21 @@ +# blake2s256() + +```ts +blake2s256(inputs): Uint8Array +``` + +Calculates the Blake2s256 hash of the input bytes + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `inputs` | `Uint8Array` | | + +## Returns + +`Uint8Array` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md b/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md new file mode 100644 index 00000000000..5e3cd53e9d3 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md @@ -0,0 +1,28 @@ +# ecdsa\_secp256k1\_verify() + +```ts +ecdsa_secp256k1_verify( + hashed_msg, + public_key_x_bytes, + public_key_y_bytes, + signature): boolean +``` + +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.28.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md b/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md new file mode 100644 index 00000000000..0b20ff68957 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md @@ -0,0 +1,28 @@ +# ecdsa\_secp256r1\_verify() + +```ts +ecdsa_secp256r1_verify( + hashed_msg, + public_key_x_bytes, + public_key_y_bytes, + signature): boolean +``` + +Verifies a ECDSA signature over the secp256r1 curve. + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `hashed_msg` | `Uint8Array` | | +| `public_key_x_bytes` | `Uint8Array` | | +| `public_key_y_bytes` | `Uint8Array` | | +| `signature` | `Uint8Array` | | + +## Returns + +`boolean` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/functions/keccak256.md b/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/functions/keccak256.md new file mode 100644 index 00000000000..d10f155ce86 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/functions/keccak256.md @@ -0,0 +1,21 @@ +# keccak256() + +```ts +keccak256(inputs): Uint8Array +``` + +Calculates the Keccak256 hash of the input bytes + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `inputs` | `Uint8Array` | | + +## Returns + +`Uint8Array` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/functions/sha256.md b/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/functions/sha256.md new file mode 100644 index 00000000000..6ba4ecac022 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/functions/sha256.md @@ -0,0 +1,21 @@ +# sha256() + +```ts +sha256(inputs): Uint8Array +``` + +Calculates the SHA256 hash of the input bytes + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `inputs` | `Uint8Array` | | + +## Returns + +`Uint8Array` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/functions/xor.md b/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/functions/xor.md new file mode 100644 index 00000000000..8d762b895d3 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/functions/xor.md @@ -0,0 +1,22 @@ +# xor() + +```ts +xor(lhs, rhs): string +``` + +Performs a bitwise XOR operation between `lhs` and `rhs` + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `lhs` | `string` | | +| `rhs` | `string` | | + +## Returns + +`string` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/index.md b/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/index.md new file mode 100644 index 00000000000..cca6b3ace41 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/index.md @@ -0,0 +1,54 @@ +# noir_js + +## Exports + +### Classes + +| Class | Description | +| :------ | :------ | +| [Noir](classes/Noir.md) | - | + +### Type Aliases + +| Type alias | Description | +| :------ | :------ | +| [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) | - | +| [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) | Verifies a ECDSA signature over the secp256k1 curve. | +| [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` | + +## References + +### CompiledCircuit + +Renames and re-exports [InputMap](index.md#inputmap) + +*** + +### ProofData + +Renames and re-exports [InputMap](index.md#inputmap) + +## Variables + +### InputMap + +```ts +InputMap: any; +``` + +*** + +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.28.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md b/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md new file mode 100644 index 00000000000..812b8b16481 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md @@ -0,0 +1,24 @@ +# ForeignCallHandler + +```ts +type ForeignCallHandler: (name, inputs) => Promise; +``` + +A callback which performs an foreign call and returns the response. + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `name` | `string` | The identifier for the type of foreign call being performed. | +| `inputs` | [`ForeignCallInput`](ForeignCallInput.md)[] | An array of hex encoded inputs to the foreign call. | + +## Returns + +`Promise`\<[`ForeignCallOutput`](ForeignCallOutput.md)[]\> + +outputs - An array of hex encoded outputs containing the results of the foreign call. + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md b/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md new file mode 100644 index 00000000000..dd95809186a --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md @@ -0,0 +1,9 @@ +# ForeignCallInput + +```ts +type ForeignCallInput: string[]; +``` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md b/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md new file mode 100644 index 00000000000..b71fb78a946 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md @@ -0,0 +1,9 @@ +# ForeignCallOutput + +```ts +type ForeignCallOutput: string | string[]; +``` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md b/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md new file mode 100644 index 00000000000..258c46f9d0c --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md @@ -0,0 +1,9 @@ +# WitnessMap + +```ts +type WitnessMap: Map; +``` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs b/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs new file mode 100644 index 00000000000..c6d8125eaad --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs @@ -0,0 +1,4 @@ +// @ts-check +/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ +const typedocSidebar = { items: [{"type":"category","label":"Classes","items":[{"type":"doc","id":"reference/NoirJS/noir_js/classes/Noir","label":"Noir"}]},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ForeignCallHandler","label":"ForeignCallHandler"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ForeignCallInput","label":"ForeignCallInput"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ForeignCallOutput","label":"ForeignCallOutput"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/WitnessMap","label":"WitnessMap"}]},{"type":"category","label":"Functions","items":[{"type":"doc","id":"reference/NoirJS/noir_js/functions/and","label":"and"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/blake2s256","label":"blake2s256"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify","label":"ecdsa_secp256k1_verify"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify","label":"ecdsa_secp256r1_verify"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/keccak256","label":"keccak256"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/sha256","label":"sha256"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/xor","label":"xor"}]}]}; +module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_wasm/.nojekyll b/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_wasm/.nojekyll new file mode 100644 index 00000000000..e2ac6616add --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_wasm/.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.28.0/reference/NoirJS/noir_wasm/functions/compile.md b/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_wasm/functions/compile.md new file mode 100644 index 00000000000..6faf763b37f --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_wasm/functions/compile.md @@ -0,0 +1,51 @@ +# compile() + +```ts +compile( + fileManager, + projectPath?, + logFn?, +debugLogFn?): Promise +``` + +Compiles a Noir project + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `fileManager` | `FileManager` | The file manager to use | +| `projectPath`? | `string` | The path to the project inside the file manager. Defaults to the root of the file manager | +| `logFn`? | `LogFn` | A logging function. If not provided, console.log will be used | +| `debugLogFn`? | `LogFn` | A debug logging function. If not provided, logFn will be used | + +## Returns + +`Promise`\<[`ProgramCompilationArtifacts`](../index.md#programcompilationartifacts)\> + +## Example + +```typescript +// Node.js + +import { compile_program, createFileManager } from '@noir-lang/noir_wasm'; + +const fm = createFileManager(myProjectPath); +const myCompiledCode = await compile_program(fm); +``` + +```typescript +// Browser + +import { compile_program, createFileManager } from '@noir-lang/noir_wasm'; + +const fm = createFileManager('/'); +for (const path of files) { + await fm.writeFile(path, await getFileAsStream(path)); +} +const myCompiledCode = await compile_program(fm); +``` + +*** + +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.28.0/reference/NoirJS/noir_wasm/functions/compile_contract.md b/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_wasm/functions/compile_contract.md new file mode 100644 index 00000000000..7d0b39a43ef --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_wasm/functions/compile_contract.md @@ -0,0 +1,51 @@ +# compile\_contract() + +```ts +compile_contract( + fileManager, + projectPath?, + logFn?, +debugLogFn?): Promise +``` + +Compiles a Noir project + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `fileManager` | `FileManager` | The file manager to use | +| `projectPath`? | `string` | The path to the project inside the file manager. Defaults to the root of the file manager | +| `logFn`? | `LogFn` | A logging function. If not provided, console.log will be used | +| `debugLogFn`? | `LogFn` | A debug logging function. If not provided, logFn will be used | + +## Returns + +`Promise`\<[`ContractCompilationArtifacts`](../index.md#contractcompilationartifacts)\> + +## Example + +```typescript +// Node.js + +import { compile_contract, createFileManager } from '@noir-lang/noir_wasm'; + +const fm = createFileManager(myProjectPath); +const myCompiledCode = await compile_contract(fm); +``` + +```typescript +// Browser + +import { compile_contract, createFileManager } from '@noir-lang/noir_wasm'; + +const fm = createFileManager('/'); +for (const path of files) { + await fm.writeFile(path, await getFileAsStream(path)); +} +const myCompiledCode = await compile_contract(fm); +``` + +*** + +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.28.0/reference/NoirJS/noir_wasm/functions/createFileManager.md b/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_wasm/functions/createFileManager.md new file mode 100644 index 00000000000..7e65c1d69c7 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_wasm/functions/createFileManager.md @@ -0,0 +1,21 @@ +# createFileManager() + +```ts +createFileManager(dataDir): FileManager +``` + +Creates a new FileManager instance based on fs in node and memfs in the browser (via webpack alias) + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `dataDir` | `string` | root of the file system | + +## Returns + +`FileManager` + +*** + +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.28.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md b/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md new file mode 100644 index 00000000000..fcea9275341 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md @@ -0,0 +1,21 @@ +# inflateDebugSymbols() + +```ts +inflateDebugSymbols(debugSymbols): any +``` + +Decompresses and decodes the debug symbols + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `debugSymbols` | `string` | The base64 encoded debug symbols | + +## Returns + +`any` + +*** + +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.28.0/reference/NoirJS/noir_wasm/index.md b/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_wasm/index.md new file mode 100644 index 00000000000..b6e0f9d1bc0 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_wasm/index.md @@ -0,0 +1,49 @@ +# noir_wasm + +## Exports + +### Functions + +| Function | Description | +| :------ | :------ | +| [compile](functions/compile.md) | Compiles a Noir project | +| [compile\_contract](functions/compile_contract.md) | Compiles a Noir project | +| [createFileManager](functions/createFileManager.md) | Creates a new FileManager instance based on fs in node and memfs in the browser (via webpack alias) | +| [inflateDebugSymbols](functions/inflateDebugSymbols.md) | Decompresses and decodes the debug symbols | + +## References + +### compile\_program + +Renames and re-exports [compile](functions/compile.md) + +## Interfaces + +### ContractCompilationArtifacts + +The compilation artifacts of a given contract. + +#### Properties + +| Property | Type | Description | +| :------ | :------ | :------ | +| `contract` | `ContractArtifact` | The compiled contract. | +| `warnings` | `unknown`[] | Compilation warnings. | + +*** + +### ProgramCompilationArtifacts + +The compilation artifacts of a given program. + +#### Properties + +| Property | Type | Description | +| :------ | :------ | :------ | +| `name` | `string` | not part of the compilation output, injected later | +| `program` | `ProgramArtifact` | The compiled contract. | +| `warnings` | `unknown`[] | Compilation warnings. | + +*** + +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.28.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs b/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs new file mode 100644 index 00000000000..e0870710349 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs @@ -0,0 +1,4 @@ +// @ts-check +/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ +const typedocSidebar = { items: [{"type":"doc","id":"reference/NoirJS/noir_wasm/index","label":"API"},{"type":"category","label":"Functions","items":[{"type":"doc","id":"reference/NoirJS/noir_wasm/functions/compile","label":"compile"},{"type":"doc","id":"reference/NoirJS/noir_wasm/functions/compile_contract","label":"compile_contract"},{"type":"doc","id":"reference/NoirJS/noir_wasm/functions/createFileManager","label":"createFileManager"},{"type":"doc","id":"reference/NoirJS/noir_wasm/functions/inflateDebugSymbols","label":"inflateDebugSymbols"}]}]}; +module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.28.0/reference/_category_.json b/docs/versioned_docs/version-v0.28.0/reference/_category_.json new file mode 100644 index 00000000000..5b6a20a609a --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/reference/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 4, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.28.0/reference/debugger/_category_.json b/docs/versioned_docs/version-v0.28.0/reference/debugger/_category_.json new file mode 100644 index 00000000000..27869205ad3 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/reference/debugger/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Debugger", + "position": 1, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.28.0/reference/debugger/debugger_known_limitations.md b/docs/versioned_docs/version-v0.28.0/reference/debugger/debugger_known_limitations.md new file mode 100644 index 00000000000..936d416ac4b --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/reference/debugger/debugger_known_limitations.md @@ -0,0 +1,59 @@ +--- +title: Known limitations +description: + An overview of known limitations of the current version of the Noir debugger +keywords: + [ + Nargo, + Noir Debugger, + VS Code, + ] +sidebar_position: 2 +--- + +# Debugger Known Limitations + +There are currently some limits to what the debugger can observe. + +## Mutable references + +The debugger is currently blind to any state mutated via a mutable reference. For example, in: + +``` +let mut x = 1; +let y = &mut x; +*y = 2; +``` + +The update on `x` will not be observed by the debugger. That means, when running `vars` from the debugger REPL, or inspecting the _local variables_ pane in the VS Code debugger, `x` will appear with value 1 despite having executed `*y = 2;`. + +## Variables of type function or mutable references are opaque + +When inspecting variables, any variable of type `Function` or `MutableReference` will render its value as `<>` or `<>`. + +## Debugger instrumentation affects resulting ACIR + +In order to make the state of local variables observable, the debugger compiles Noir circuits interleaving foreign calls that track any mutations to them. While this works (except in the cases described above) and doesn't introduce any behavior changes, it does as a side effect produce bigger bytecode. In particular, when running the command `opcodes` on the REPL debugger, you will notice Unconstrained VM blocks that look like this: + +``` +... +5 BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [], q_c: 2 }), Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(2))], q_c: 0 })] + | outputs=[] + 5.0 | Mov { destination: RegisterIndex(2), source: RegisterIndex(0) } + 5.1 | Mov { destination: RegisterIndex(3), source: RegisterIndex(1) } + 5.2 | Const { destination: RegisterIndex(0), value: Value { inner: 0 } } + 5.3 | Const { destination: RegisterIndex(1), value: Value { inner: 0 } } + 5.4 | Mov { destination: RegisterIndex(2), source: RegisterIndex(2) } + 5.5 | Mov { destination: RegisterIndex(3), source: RegisterIndex(3) } + 5.6 | Call { location: 8 } + 5.7 | Stop + 5.8 | ForeignCall { function: "__debug_var_assign", destinations: [], inputs: [RegisterIndex(RegisterIndex(2)), RegisterIndex(RegisterIndex(3))] } +... +``` + +If you are interested in debugging/inspecting compiled ACIR without these synthetic changes, you can invoke the REPL debugger with the `--skip-instrumentation` flag or launch the VS Code debugger with the `skipConfiguration` property set to true in its launch configuration. You can find more details about those in the [Debugger REPL reference](debugger_repl.md) and the [VS Code Debugger reference](debugger_vscode.md). + +:::note +Skipping debugger instrumentation means you won't be able to inspect values of local variables. +::: + diff --git a/docs/versioned_docs/version-v0.28.0/reference/debugger/debugger_repl.md b/docs/versioned_docs/version-v0.28.0/reference/debugger/debugger_repl.md new file mode 100644 index 00000000000..46e2011304e --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/reference/debugger/debugger_repl.md @@ -0,0 +1,360 @@ +--- +title: REPL Debugger +description: + Noir Debugger REPL options and commands. +keywords: + [ + Nargo, + Noir CLI, + Noir Debugger, + REPL, + ] +sidebar_position: 1 +--- + +## Running the REPL debugger + +`nargo debug [OPTIONS] [WITNESS_NAME]` + +Runs the Noir REPL debugger. If a `WITNESS_NAME` is provided the debugger writes the resulting execution witness to a `WITNESS_NAME` 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 debug | +| `--print-acir` | Display the ACIR for compiled circuit | +| `--deny-warnings` | Treat all warnings as errors | +| `--silence-warnings` | Suppress warnings | +| `-h, --help` | Print help | + +None of these options are required. + +:::note +Since the debugger starts by compiling the target package, all Noir compiler options are also available. Check out the [compiler reference](../nargo_commands.md#nargo-compile) to learn more about the compiler options. +::: + +## REPL commands + +Once the debugger is running, it accepts the following commands. + +#### `help` (h) + +Displays the menu of available commands. + +``` +> help +Available commands: + + opcodes display ACIR opcodes + into step into to the next opcode + next step until a new source location is reached + out step until a new source location is reached + and the current stack frame is finished + break LOCATION:OpcodeLocation add a breakpoint at an opcode location + over step until a new source location is reached + without diving into function calls + restart restart the debugging session + delete LOCATION:OpcodeLocation delete breakpoint at an opcode location + witness show witness map + witness index:u32 display a single witness from the witness map + witness index:u32 value:String update a witness with the given value + memset index:usize value:String update a memory cell with the given + value + continue continue execution until the end of the + program + vars show variable values available at this point + in execution + stacktrace display the current stack trace + memory show memory (valid when executing unconstrained code) value + step step to the next ACIR opcode + +Other commands: + + help Show this help message + quit Quit repl + +``` + +### Stepping through programs + +#### `next` (n) + +Step until the next Noir source code location. While other commands, such as [`into`](#into-i) and [`step`](#step-s), allow for finer grained control of the program's execution at the opcode level, `next` is source code centric. For example: + +``` +3 ... +4 fn main(x: u32) { +5 assert(entry_point(x) == 2); +6 swap_entry_point(x, x + 1); +7 -> assert(deep_entry_point(x) == 4); +8 multiple_values_entry_point(x); +9 } +``` + + +Using `next` here would cause the debugger to jump to the definition of `deep_entry_point` (if available). + +If you want to step over `deep_entry_point` and go straight to line 8, use [the `over` command](#over) instead. + +#### `over` + +Step until the next source code location, without diving into function calls. For example: + +``` +3 ... +4 fn main(x: u32) { +5 assert(entry_point(x) == 2); +6 swap_entry_point(x, x + 1); +7 -> assert(deep_entry_point(x) == 4); +8 multiple_values_entry_point(x); +9 } +``` + + +Using `over` here would cause the debugger to execute until line 8 (`multiple_values_entry_point(x);`). + +If you want to step into `deep_entry_point` instead, use [the `next` command](#next-n). + +#### `out` + +Step until the end of the current function call. For example: + +``` + 3 ... + 4 fn main(x: u32) { + 5 assert(entry_point(x) == 2); + 6 swap_entry_point(x, x + 1); + 7 -> assert(deep_entry_point(x) == 4); + 8 multiple_values_entry_point(x); + 9 } + 10 + 11 unconstrained fn returns_multiple_values(x: u32) -> (u32, u32, u32, u32) { + 12 ... + ... + 55 + 56 unconstrained fn deep_entry_point(x: u32) -> u32 { + 57 -> level_1(x + 1) + 58 } + +``` + +Running `out` here will resume execution until line 8. + +#### `step` (s) + +Skips to the next ACIR code. A compiled Noir program is a sequence of ACIR opcodes. However, an unconstrained VM opcode denotes the start of an unconstrained code block, to be executed by the unconstrained VM. For example (redacted for brevity): + +``` +0 BLACKBOX::RANGE [(_0, num_bits: 32)] [ ] +1 -> BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(0))], q_c: 0 })] outputs=[Simple(Witness(1))] + 1.0 | Mov { destination: RegisterIndex(2), source: RegisterIndex(0) } + 1.1 | Const { destination: RegisterIndex(0), value: Value { inner: 0 } } + 1.2 | Const { destination: RegisterIndex(1), value: Value { inner: 0 } } + 1.3 | Mov { destination: RegisterIndex(2), source: RegisterIndex(2) } + 1.4 | Call { location: 7 } + ... + 1.43 | Return +2 EXPR [ (1, _1) -2 ] +``` + +The `->` here shows the debugger paused at an ACIR opcode: `BRILLIG`, at index 1, which denotes an unconstrained code block is about to start. + +Using the `step` command at this point would result in the debugger stopping at ACIR opcode 2, `EXPR`, skipping unconstrained computation steps. + +Use [the `into` command](#into-i) instead if you want to follow unconstrained computation step by step. + +#### `into` (i) + +Steps into the next opcode. A compiled Noir program is a sequence of ACIR opcodes. However, a BRILLIG opcode denotes the start of an unconstrained code block, to be executed by the unconstrained VM. For example (redacted for brevity): + +``` +0 BLACKBOX::RANGE [(_0, num_bits: 32)] [ ] +1 -> BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(0))], q_c: 0 })] outputs=[Simple(Witness(1))] + 1.0 | Mov { destination: RegisterIndex(2), source: RegisterIndex(0) } + 1.1 | Const { destination: RegisterIndex(0), value: Value { inner: 0 } } + 1.2 | Const { destination: RegisterIndex(1), value: Value { inner: 0 } } + 1.3 | Mov { destination: RegisterIndex(2), source: RegisterIndex(2) } + 1.4 | Call { location: 7 } + ... + 1.43 | Return +2 EXPR [ (1, _1) -2 ] +``` + +The `->` here shows the debugger paused at an ACIR opcode: `BRILLIG`, at index 1, which denotes an unconstrained code block is about to start. + +Using the `into` command at this point would result in the debugger stopping at opcode 1.0, `Mov ...`, allowing the debugger user to follow unconstrained computation step by step. + +Use [the `step` command](#step-s) instead if you want to skip to the next ACIR code directly. + +#### `continue` (c) + +Continues execution until the next breakpoint, or the end of the program. + +#### `restart` (res) + +Interrupts execution, and restarts a new debugging session from scratch. + +#### `opcodes` (o) + +Display the program's ACIR opcode sequence. For example: + +``` +0 BLACKBOX::RANGE [(_0, num_bits: 32)] [ ] +1 -> BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(0))], q_c: 0 })] outputs=[Simple(Witness(1))] + 1.0 | Mov { destination: RegisterIndex(2), source: RegisterIndex(0) } + 1.1 | Const { destination: RegisterIndex(0), value: Value { inner: 0 } } + 1.2 | Const { destination: RegisterIndex(1), value: Value { inner: 0 } } + 1.3 | Mov { destination: RegisterIndex(2), source: RegisterIndex(2) } + 1.4 | Call { location: 7 } + ... + 1.43 | Return +2 EXPR [ (1, _1) -2 ] +``` + +### Breakpoints + +#### `break [Opcode]` (or shorthand `b [Opcode]`) + +Sets a breakpoint on the specified opcode index. To get a list of the program opcode numbers, see [the `opcode` command](#opcodes-o). For example: + +``` +0 BLACKBOX::RANGE [(_0, num_bits: 32)] [ ] +1 -> BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(0))], q_c: 0 })] outputs=[Simple(Witness(1))] + 1.0 | Mov { destination: RegisterIndex(2), source: RegisterIndex(0) } + 1.1 | Const { destination: RegisterIndex(0), value: Value { inner: 0 } } + 1.2 | Const { destination: RegisterIndex(1), value: Value { inner: 0 } } + 1.3 | Mov { destination: RegisterIndex(2), source: RegisterIndex(2) } + 1.4 | Call { location: 7 } + ... + 1.43 | Return +2 EXPR [ (1, _1) -2 ] +``` + +In this example, issuing a `break 1.2` command adds break on opcode 1.2, as denoted by the `*` character: + +``` +0 BLACKBOX::RANGE [(_0, num_bits: 32)] [ ] +1 -> BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(0))], q_c: 0 })] outputs=[Simple(Witness(1))] + 1.0 | Mov { destination: RegisterIndex(2), source: RegisterIndex(0) } + 1.1 | Const { destination: RegisterIndex(0), value: Value { inner: 0 } } + 1.2 | * Const { destination: RegisterIndex(1), value: Value { inner: 0 } } + 1.3 | Mov { destination: RegisterIndex(2), source: RegisterIndex(2) } + 1.4 | Call { location: 7 } + ... + 1.43 | Return +2 EXPR [ (1, _1) -2 ] +``` + +Running [the `continue` command](#continue-c) at this point would cause the debugger to execute the program until opcode 1.2. + +#### `delete [Opcode]` (or shorthand `d [Opcode]`) + +Deletes a breakpoint at an opcode location. Usage is analogous to [the `break` command](#). + +### Variable inspection + +#### vars + +Show variable values available at this point in execution. + +:::note +The ability to inspect variable values from the debugger depends on compilation to be run in a special debug instrumentation mode. This instrumentation weaves variable tracing code with the original source code. + +So variable value inspection comes at the expense of making the resulting ACIR bytecode bigger and harder to understand and optimize. + +If you find this compromise unacceptable, you can run the debugger with the flag `--skip-debug-instrumentation`. This will compile your circuit without any additional debug information, so the resulting ACIR bytecode will be identical to the one produced by standard Noir compilation. However, if you opt for this, the `vars` command will not be available while debugging. +::: + + +### Stacktrace + +#### `stacktrace` + +Displays the current stack trace. + + +### Witness map + +#### `witness` (w) + +Show witness map. For example: + +``` +_0 = 0 +_1 = 2 +_2 = 1 +``` + +#### `witness [Witness Index]` + +Display a single witness from the witness map. For example: + +``` +> witness 1 +_1 = 2 +``` + +#### `witness [Witness Index] [New value]` + +Overwrite the given index with a new value. For example: + +``` +> witness 1 3 +_1 = 3 +``` + + +### Unconstrained VM memory + +#### `memory` + +Show unconstrained VM memory state. For example: + +``` +> memory +At opcode 1.13: Store { destination_pointer: RegisterIndex(0), source: RegisterIndex(3) } +... +> registers +0 = 0 +1 = 10 +2 = 0 +3 = 1 +4 = 1 +5 = 2³² +6 = 1 +> into +At opcode 1.14: Const { destination: RegisterIndex(5), value: Value { inner: 1 } } +... +> memory +0 = 1 +> +``` + +In the example above: we start with clean memory, then step through a `Store` opcode which stores the value of register 3 (1) into the memory address stored in register 0 (0). Thus now `memory` shows memory address 0 contains value 1. + +:::note +This command is only functional while the debugger is executing unconstrained code. +::: + +#### `memset [Memory address] [New value]` + +Update a memory cell with the given value. For example: + +``` +> memory +0 = 1 +> memset 0 2 +> memory +0 = 2 +> memset 1 4 +> memory +0 = 2 +1 = 4 +> +``` + +:::note +This command is only functional while the debugger is executing unconstrained code. +::: \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.28.0/reference/debugger/debugger_vscode.md b/docs/versioned_docs/version-v0.28.0/reference/debugger/debugger_vscode.md new file mode 100644 index 00000000000..c027332b3b0 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/reference/debugger/debugger_vscode.md @@ -0,0 +1,82 @@ +--- +title: VS Code Debugger +description: + VS Code Debugger configuration and features. +keywords: + [ + Nargo, + Noir CLI, + Noir Debugger, + VS Code, + IDE, + ] +sidebar_position: 0 +--- + +# VS Code Noir Debugger Reference + +The Noir debugger enabled by the vscode-noir extension ships with default settings such that the most common scenario should run without any additional configuration steps. + +These defaults can nevertheless be overridden by defining a launch configuration file. This page provides a reference for the properties you can override via a launch configuration file, as well as documenting the Nargo `dap` command, which is a dependency of the VS Code Noir debugger. + + +## Creating and editing launch configuration files + +To create a launch configuration file from VS Code, open the _debug pane_, and click on _create a launch.json file_. + +![Creating a launch configuration file](@site/static/img/debugger/ref1-create-launch.png) + +A `launch.json` file will be created, populated with basic defaults. + +### Noir Debugger launch.json properties + +#### projectFolder + +_String, optional._ + +Absolute path to the Nargo project to debug. By default, it is dynamically determined by looking for the nearest `Nargo.toml` file to the active file at the moment of launching the debugger. + +#### proverName + +_String, optional._ + +Name of the prover input to use. Defaults to `Prover`, which looks for a file named `Prover.toml` at the `projectFolder`. + +#### generateAcir + +_Boolean, optional._ + +If true, generate ACIR opcodes instead of unconstrained opcodes which will be closer to release binaries but less convenient for debugging. Defaults to `false`. + +#### skipInstrumentation + +_Boolean, optional._ + +Skips variables debugging instrumentation of code, making debugging less convenient but the resulting binary smaller and closer to production. Defaults to `false`. + +:::note +Skipping instrumentation causes the debugger to be unable to inspect local variables. +::: + +## `nargo dap [OPTIONS]` + +When run without any option flags, it starts the Nargo Debug Adapter Protocol server, which acts as the debugging backend for the VS Code Noir Debugger. + +All option flags are related to preflight checks. The Debug Adapter Protocol specifies how errors are to be informed from a running DAP server, but it doesn't specify mechanisms to communicate server initialization errors between the DAP server and its client IDE. + +Thus `nargo dap` ships with a _preflight check_ mode. If flag `--preflight-check` and the rest of the `--preflight-*` flags are provided, Nargo will run the same initialization routine except it will not start the DAP server. + +`vscode-noir` will then run `nargo dap` in preflight check mode first before a debugging session starts. If the preflight check ends in error, vscode-noir will present stderr and stdout output from this process through its own Output pane in VS Code. This makes it possible for users to diagnose what pieces of configuration might be wrong or missing in case of initialization errors. + +If the preflight check succeeds, `vscode-noir` proceeds to start the DAP server normally but running `nargo dap` without any additional flags. + +### Options + +| Option | Description | +| --------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- | +| `--preflight-check` | If present, dap runs in preflight check mode. | +| `--preflight-project-folder ` | Absolute path to the project to debug for preflight check. | +| `--preflight-prover-name ` | Name of prover file to use for preflight check | +| `--preflight-generate-acir` | Optional. If present, compile in ACIR mode while running preflight check. | +| `--preflight-skip-instrumentation` | Optional. If present, compile without introducing debug instrumentation while running preflight check. | +| `-h, --help` | Print help. | diff --git a/docs/versioned_docs/version-v0.28.0/reference/nargo_commands.md b/docs/versioned_docs/version-v0.28.0/reference/nargo_commands.md new file mode 100644 index 00000000000..218fcfb0c8c --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/reference/nargo_commands.md @@ -0,0 +1,381 @@ +--- +title: Nargo +description: + Noir CLI Commands for Noir Prover and Verifier to create, execute, prove and verify programs, + generate Solidity verifier smart contract and compile into JSON file containing ACIR + representation and ABI of circuit. +keywords: + [ + Nargo, + Noir CLI, + Noir Prover, + Noir Verifier, + generate Solidity verifier, + compile JSON file, + ACIR representation, + ABI of circuit, + TypeScript, + ] +sidebar_position: 0 +--- + +# Command-Line Help for `nargo` + +This document contains the help content for the `nargo` command-line program. + +**Command Overview:** + +* [`nargo`↴](#nargo) +* [`nargo backend`↴](#nargo-backend) +* [`nargo backend current`↴](#nargo-backend-current) +* [`nargo backend ls`↴](#nargo-backend-ls) +* [`nargo backend use`↴](#nargo-backend-use) +* [`nargo backend install`↴](#nargo-backend-install) +* [`nargo backend uninstall`↴](#nargo-backend-uninstall) +* [`nargo check`↴](#nargo-check) +* [`nargo fmt`↴](#nargo-fmt) +* [`nargo codegen-verifier`↴](#nargo-codegen-verifier) +* [`nargo compile`↴](#nargo-compile) +* [`nargo new`↴](#nargo-new) +* [`nargo init`↴](#nargo-init) +* [`nargo execute`↴](#nargo-execute) +* [`nargo prove`↴](#nargo-prove) +* [`nargo verify`↴](#nargo-verify) +* [`nargo test`↴](#nargo-test) +* [`nargo info`↴](#nargo-info) +* [`nargo lsp`↴](#nargo-lsp) + +## `nargo` + +Noir's package manager + +**Usage:** `nargo ` + +###### **Subcommands:** + +* `backend` — Install and select custom backends used to generate and verify proofs +* `check` — Checks the constraint system for errors +* `fmt` — Format the Noir files in a workspace +* `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 Noir project in a new directory +* `init` — Create a Noir project in the current directory +* `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 +* `info` — Provides detailed information on each of a program's function (represented by a single circuit) +* `lsp` — Starts the Noir LSP server + +###### **Options:** + + + + +## `nargo backend` + +Install and select custom backends used to generate and verify proofs + +**Usage:** `nargo backend ` + +###### **Subcommands:** + +* `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 + + + +## `nargo backend current` + +Prints the name of the currently active backend + +**Usage:** `nargo backend current` + + + +## `nargo backend ls` + +Prints the list of currently installed backends + +**Usage:** `nargo backend ls` + + + +## `nargo backend use` + +Select the backend to use + +**Usage:** `nargo backend use ` + +###### **Arguments:** + +* `` + + + +## `nargo backend install` + +Install a new backend from a URL + +**Usage:** `nargo backend install ` + +###### **Arguments:** + +* `` — The name of the backend to install +* `` — The URL from which to download the backend + + + +## `nargo backend uninstall` + +Uninstalls a backend + +**Usage:** `nargo backend uninstall ` + +###### **Arguments:** + +* `` — The name of the backend to uninstall + + + +## `nargo check` + +Checks the constraint system for errors + +**Usage:** `nargo check [OPTIONS]` + +###### **Options:** + +* `--package ` — The name of the package to check +* `--workspace` — Check all packages in the workspace +* `--overwrite` — Force overwrite of existing files +* `--expression-width ` — Override the expression width requested by the backend +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings + + + +## `nargo fmt` + +Format the Noir files in a workspace + +**Usage:** `nargo fmt [OPTIONS]` + +###### **Options:** + +* `--check` — Run noirfmt in check mode + + + +## `nargo codegen-verifier` + +Generates a Solidity verifier smart contract for the program + +**Usage:** `nargo codegen-verifier [OPTIONS]` + +###### **Options:** + +* `--package ` — The name of the package to codegen +* `--workspace` — Codegen all packages in the workspace +* `--expression-width ` — Override the expression width requested by the backend +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings + + + +## `nargo compile` + +Compile the program and its secret execution trace into ACIR format + +**Usage:** `nargo compile [OPTIONS]` + +###### **Options:** + +* `--package ` — The name of the package to compile +* `--workspace` — Compile all packages in the workspace +* `--expression-width ` — Override the expression width requested by the backend +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings + + + +## `nargo new` + +Create a Noir project in a new directory + +**Usage:** `nargo new [OPTIONS] ` + +###### **Arguments:** + +* `` — The path to save the new project + +###### **Options:** + +* `--name ` — Name of the package [default: package directory name] +* `--lib` — Use a library template +* `--bin` — Use a binary template [default] +* `--contract` — Use a contract template + + + +## `nargo init` + +Create a Noir project in the current directory + +**Usage:** `nargo init [OPTIONS]` + +###### **Options:** + +* `--name ` — Name of the package [default: current directory name] +* `--lib` — Use a library template +* `--bin` — Use a binary template [default] +* `--contract` — Use a contract template + + + +## `nargo execute` + +Executes a circuit to calculate its return value + +**Usage:** `nargo execute [OPTIONS] [WITNESS_NAME]` + +###### **Arguments:** + +* `` — Write the execution witness to named file + +###### **Options:** + +* `-p`, `--prover-name ` — The name of the toml file which contains the inputs for the prover + + Default value: `Prover` +* `--package ` — The name of the package to execute +* `--workspace` — Execute all packages in the workspace +* `--expression-width ` — Override the expression width requested by the backend +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings +* `--oracle-resolver ` — JSON RPC url to solve oracle calls + + + +## `nargo prove` + +Create proof for this program. The proof is returned as a hex encoded string + +**Usage:** `nargo prove [OPTIONS]` + +###### **Options:** + +* `-p`, `--prover-name ` — The name of the toml file which contains the inputs for the prover + + Default value: `Prover` +* `-v`, `--verifier-name ` — The name of the toml file which contains the inputs for the verifier + + Default value: `Verifier` +* `--verify` — Verify proof after proving +* `--package ` — The name of the package to prove +* `--workspace` — Prove all packages in the workspace +* `--expression-width ` — Override the expression width requested by the backend +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings +* `--oracle-resolver ` — JSON RPC url to solve oracle calls + + + +## `nargo verify` + +Given a proof and a program, verify whether the proof is valid + +**Usage:** `nargo verify [OPTIONS]` + +###### **Options:** + +* `-v`, `--verifier-name ` — The name of the toml file which contains the inputs for the verifier + + Default value: `Verifier` +* `--package ` — The name of the package verify +* `--workspace` — Verify all packages in the workspace +* `--expression-width ` — Override the expression width requested by the backend +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings + + + +## `nargo test` + +Run the tests for this program + +**Usage:** `nargo test [OPTIONS] [TEST_NAME]` + +###### **Arguments:** + +* `` — If given, only tests with names containing this string will be run + +###### **Options:** + +* `--show-output` — Display output of `println` statements +* `--exact` — Only run tests that match exactly +* `--package ` — The name of the package to test +* `--workspace` — Test all packages in the workspace +* `--expression-width ` — Override the expression width requested by the backend +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings +* `--oracle-resolver ` — JSON RPC url to solve oracle calls + + + +## `nargo info` + +Provides detailed information on each of a program's function (represented by a single circuit) + +Current information provided per circuit: 1. The number of ACIR opcodes 2. Counts the final number gates in the circuit used by a backend + +**Usage:** `nargo info [OPTIONS]` + +###### **Options:** + +* `--package ` — The name of the package to detail +* `--workspace` — Detail all packages in the workspace +* `--expression-width ` — Override the expression width requested by the backend +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings + + + +## `nargo lsp` + +Starts the Noir LSP server + +Starts an LSP server which allows IDEs such as VS Code to display diagnostics in Noir source. + +VS Code Noir Language Support: https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir + +**Usage:** `nargo lsp` + + + +
+ + + This document was generated automatically by + clap-markdown. + + diff --git a/docs/versioned_docs/version-v0.28.0/tooling/debugger.md b/docs/versioned_docs/version-v0.28.0/tooling/debugger.md new file mode 100644 index 00000000000..184c436068f --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/tooling/debugger.md @@ -0,0 +1,27 @@ +--- +title: Debugger +description: Learn about the Noir Debugger, in its REPL or VS Code versions. +keywords: [Nargo, VSCode, Visual Studio Code, REPL, Debugger] +sidebar_position: 2 +--- + +# Noir Debugger + +There are currently two ways of debugging Noir programs: + +1. From VS 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). +2. Via the REPL debugger, which ships with Nargo. + +In order to use either version of the debugger, you will need to install recent enough versions of Noir, [Nargo](../getting_started/installation) and vscode-noir: + +- Noir 0.xx +- Nargo 0.xx +- vscode-noir 0.xx + +:::info +At the moment, the debugger supports debugging binary projects, but not contracts. +::: + +We cover the VS Code Noir debugger more in depth in [its VS Code debugger how-to guide](../how_to/debugger/debugging_with_vs_code.md) and [the reference](../reference/debugger/debugger_vscode.md). + +The REPL debugger is discussed at length in [the REPL debugger how-to guide](../how_to/debugger/debugging_with_the_repl.md) and [the reference](../reference/debugger/debugger_repl.md). diff --git a/docs/versioned_docs/version-v0.28.0/tooling/language_server.md b/docs/versioned_docs/version-v0.28.0/tooling/language_server.md new file mode 100644 index 00000000000..81e0356ef8a --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/tooling/language_server.md @@ -0,0 +1,43 @@ +--- +title: Language Server +description: Learn about the Noir Language Server, how to install the components, and configuration that may be required. +keywords: [Nargo, Language Server, LSP, VSCode, Visual Studio Code] +sidebar_position: 0 +--- + +This section helps you install and configure the Noir Language Server. + +The Language Server Protocol (LSP) has two components, the [Server](#language-server) and the [Client](#language-client). Below we describe each in the context of Noir. + +## Language Server + +The Server component is provided by the Nargo command line tool that you installed at the beginning of this guide. +As long as Nargo is installed and you've used it to run other commands in this guide, it should be good to go! + +If you'd like to verify that the `nargo lsp` command is available, you can run `nargo --help` and look for `lsp` in the list of commands. If you see it, you're using a version of Noir with LSP support. + +## Language Client + +The Client component is usually an editor plugin that launches the Server. It communicates LSP messages between the editor and the Server. For example, when you save a file, the Client will alert the Server, so it can try to compile the project and report any errors. + +Currently, Noir provides a Language Client for Visual Studio Code via the [vscode-noir](https://github.com/noir-lang/vscode-noir) extension. You can install it via the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir). + +> **Note:** Noir's Language Server Protocol support currently assumes users' VSCode workspace root to be the same as users' Noir project root (i.e. where Nargo.toml lies). +> +> If LSP features seem to be missing / malfunctioning, make sure you are opening your Noir project directly (instead of as a sub-folder) in your VSCode instance. + +When your language server is running correctly and the VSCode plugin is installed, you should see handy codelens buttons for compilation, measuring circuit size, execution, and tests: + +![Compile and Execute](@site/static/img/codelens_compile_execute.png) +![Run test](@site/static/img/codelens_run_test.png) + +You should also see your tests in the `testing` panel: + +![Testing panel](@site/static/img/codelens_testing_panel.png) + +### Configuration + +- **Noir: Enable LSP** - If checked, the extension will launch the Language Server via `nargo lsp` and communicate with it. +- **Noir: Nargo Flags** - Additional flags may be specified if you require them to be added when the extension calls `nargo lsp`. +- **Noir: Nargo Path** - An absolute path to a Nargo binary with the `lsp` command. This may be useful if Nargo is not within the `PATH` of your editor. +- **Noir > Trace: Server** - Setting this to `"messages"` or `"verbose"` will log LSP messages between the Client and Server. Useful for debugging. diff --git a/docs/versioned_docs/version-v0.28.0/tooling/testing.md b/docs/versioned_docs/version-v0.28.0/tooling/testing.md new file mode 100644 index 00000000000..d3e0c522473 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/tooling/testing.md @@ -0,0 +1,62 @@ +--- +title: Testing in Noir +description: Learn how to use Nargo to test your Noir program in a quick and easy way +keywords: [Nargo, testing, Noir, compile, test] +sidebar_position: 1 +--- + +You can test your Noir programs using Noir circuits. + +Nargo will automatically compile and run any functions which have the decorator `#[test]` on them if +you run `nargo test`. + +For example if you have a program like: + +```rust +fn add(x: u64, y: u64) -> u64 { + x + y +} +#[test] +fn test_add() { + assert(add(2,2) == 4); + assert(add(0,1) == 1); + assert(add(1,0) == 1); +} +``` + +Running `nargo test` will test that the `test_add` function can be executed while satisfying all +the constraints 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.28.0/tutorials/noirjs_app.md b/docs/versioned_docs/version-v0.28.0/tutorials/noirjs_app.md new file mode 100644 index 00000000000..6446e0b2a76 --- /dev/null +++ b/docs/versioned_docs/version-v0.28.0/tutorials/noirjs_app.md @@ -0,0 +1,326 @@ +--- +title: Building a web app with NoirJS +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, app] +sidebar_position: 0 +pagination_next: noir/concepts/data_types/index +--- + +NoirJS is a set of packages meant to work both in a browser and a server environment. In this tutorial, we will build a simple web app using them. From here, you should get an idea on how to proceed with your own Noir projects! + +You can find the complete app code for this guide [here](https://github.com/noir-lang/tiny-noirjs-app). + +## Setup + +:::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.27.x matches `noir_js@0.27.x`, etc. + +In this guide, we will be pinned to 0.27.0. + +::: + +Before we start, we want to make sure we have Node and Nargo installed. + +We start by opening a terminal and executing `node --version`. If we don't get an output like `v20.10.0`, that means node is not installed. Let's do that by following the handy [nvm guide](https://github.com/nvm-sh/nvm?tab=readme-ov-file#install--update-script). + +As for `Nargo`, we can follow the the [Nargo guide](../getting_started/installation/index.md) to install it. If you're lazy, just paste this on a terminal and run `noirup`: + +```sh +curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash +``` + +Easy enough. Onwards! + +## Our project + +ZK is a powerful technology. An app that doesn't reveal one of the inputs to _anyone_ is almost unbelievable, yet Noir makes it as easy as a single line of code. + +In fact, it's so simple that it comes nicely packaged in `nargo`. Let's do that! + +### Nargo + +Run: + +`nargo new circuit` + +And... That's about it. Your program is ready to be compiled and run. + +To compile, let's `cd` into the `circuit` folder to enter our project, and call: + +`nargo compile` + +This compiles our circuit into `json` format and add it to a new `target` folder. + +:::info + +At this point in the tutorial, your folder structure should look like this: + +```tree +. +└── circuit <---- our working directory + ├── Nargo.toml + ├── src + │ └── main.nr + └── target + └── circuit.json +``` + +::: + +### Node and Vite + +If you want to explore Nargo, feel free to go on a side-quest now and follow the steps in the +[getting started](../getting_started/hello_noir/index.md) guide. However, we want our app to run on the browser, so we need Vite. + +Vite is a powerful tool to generate static websites. While it provides all kinds of features, let's just go barebones with some good old vanilla JS. + +To do this this, go back to the previous folder (`cd ..`) and create a new vite project by running `npm create vite` and choosing "Vanilla" and "Javascript". + +A wild `vite-project` directory should now appear in your root folder! Let's not waste any time and dive right in: + +```bash +cd vite-project +``` + +### Setting Up Vite and Configuring the Project + +Before we proceed with any coding, let's get our environment tailored for Noir. We'll start by laying down the foundations with a `vite.config.js` file. This little piece of configuration is our secret sauce for making sure everything meshes well with the NoirJS libraries and other special setups we might need, like handling WebAssembly modules. Here’s how you get that going: + +#### Creating the vite.config.js + +In your freshly minted `vite-project` folder, create a new file named `vite.config.js` and open it in your code editor. Paste the following to set the stage: + +```javascript +import { defineConfig } from "vite"; +import copy from "rollup-plugin-copy"; + +export default defineConfig({ + esbuild: { + target: "esnext", + }, + optimizeDeps: { + esbuildOptions: { + target: "esnext", + }, + }, + plugins: [ + copy({ + targets: [ + { src: "node_modules/**/*.wasm", dest: "node_modules/.vite/dist" }, + ], + copySync: true, + hook: "buildStart", + }), + ], + server: { + port: 3000, + }, +}); +``` + +#### Install Dependencies + +Now that our stage is set, install the necessary NoirJS packages along with our other dependencies: + +```bash +npm install && npm install @noir-lang/backend_barretenberg@0.27.0 @noir-lang/noir_js@0.27.0 +npm install rollup-plugin-copy --save-dev +``` + +:::info + +At this point in the tutorial, your folder structure should look like this: + +```tree +. +└── circuit + └── ...etc... +└── vite-project <---- our working directory + └── ...etc... +``` + +::: + +#### Some cleanup + +`npx create vite` is amazing but it creates a bunch of files we don't really need for our simple example. Actually, let's just delete everything except for `vite.config.js`, `index.html`, `main.js` and `package.json`. I feel lighter already. + +![my heart is ready for you, noir.js](@site/static/img/memes/titanic.jpeg) + +## HTML + +Our app won't run like this, of course. We need some working HTML, at least. Let's open our broken-hearted `index.html` and replace everything with this code snippet: + +```html + + + + + + +

Noir app

+
+ + +
+
+

Logs

+

Proof

+
+ + +``` + +It _could_ be a beautiful UI... Depending on which universe you live in. + +## Some good old vanilla Javascript + +Our love for Noir needs undivided attention, so let's just open `main.js` and delete everything (this is where the romantic scenery becomes a bit creepy). + +Start by pasting in this boilerplate code: + +```js +const setup = async () => { + await Promise.all([ + import('@noir-lang/noirc_abi').then((module) => + module.default(new URL('@noir-lang/noirc_abi/web/noirc_abi_wasm_bg.wasm', import.meta.url).toString()), + ), + import('@noir-lang/acvm_js').then((module) => + module.default(new URL('@noir-lang/acvm_js/web/acvm_js_bg.wasm', import.meta.url).toString()), + ), + ]); +}; + +function display(container, msg) { + const c = document.getElementById(container); + const p = document.createElement('p'); + p.textContent = msg; + c.appendChild(p); +} + +document.getElementById('submitGuess').addEventListener('click', async () => { + try { + // here's where love happens + } catch (err) { + display('logs', 'Oh 💔 Wrong guess'); + } +}); +``` + +The display function doesn't do much. We're simply manipulating our website to see stuff happening. For example, if the proof fails, it will simply log a broken heart 😢 + +As for the `setup` function, it's just a sad reminder that dealing with `wasm` on the browser is not as easy as it should. Just copy, paste, and forget. + +:::info + +At this point in the tutorial, your folder structure should look like this: + +```tree +. +└── circuit + └── ...same as above +└── vite-project + ├── vite.config.js + ├── main.js + ├── package.json + └── index.html +``` + +You'll see other files and folders showing up (like `package-lock.json`, `node_modules`) but you shouldn't have to care about those. + +::: + +## Some NoirJS + +We're starting with the good stuff now. If you've compiled the circuit as described above, you should have a `json` file we want to import at the very top of our `main.js` file: + +```ts +import circuit from '../circuit/target/circuit.json'; +``` + +[Noir is backend-agnostic](../index.mdx#whats-new-about-noir). We write Noir, but we also need a proving backend. That's why we need to import and instantiate the two dependencies we installed above: `BarretenbergBackend` and `Noir`. Let's import them right below: + +```js +import { BarretenbergBackend, BarretenbergVerifier as Verifier } from '@noir-lang/backend_barretenberg'; +import { Noir } from '@noir-lang/noir_js'; +``` + +And instantiate them inside our try-catch block: + +```ts +// try { +const backend = new BarretenbergBackend(circuit); +const noir = new Noir(circuit, backend); +// } +``` + +:::note + +For the remainder of the tutorial, everything will be happening inside the `try` block + +::: + +## Our app + +Now for the app itself. We're capturing whatever is in the input when people press the submit button. Just add this: + +```js +const x = parseInt(document.getElementById('guessInput').value); +const input = { x, y: 2 }; +``` + +Now we're ready to prove stuff! Let's feed some inputs to our circuit and calculate the proof: + +```js +await setup(); // let's squeeze our wasm inits here + +display('logs', 'Generating proof... ⌛'); +const proof = await noir.generateProof(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 run dev`. If it doesn't open a browser for you, just visit `localhost:5173`. You should now see the worst UI ever, with an ugly input. + +![Getting Started 0](@site/static/img/noir_getting_started_1.png) + +Now, our circuit says `fn main(x: Field, y: pub Field)`. This means only the `y` value is public, and it's hardcoded above: `input = { x, y: 2 }`. In other words, you won't need to send your secret`x` to the verifier! + +By inputting any number other than 2 in the input box and clicking "submit", you should get a valid proof. Otherwise the proof won't even generate correctly. By the way, if you're human, you shouldn't be able to understand anything on the "proof" box. That's OK. We like you, human ❤️. + +## Verifying + +Time to celebrate, yes! But we shouldn't trust machines so blindly. Let's add these lines to see our proof being verified: + +```js +display('logs', 'Verifying proof... ⌛'); +const verificationKey = await backend.getVerificationKey(); +const verifier = new Verifier(); +const isValid = await verifier.verifyProof(proof, verificationKey); +if (isValid) display('logs', 'Verifying proof... ✅'); +``` + +You have successfully generated a client-side Noir web app! + +![coded app without math knowledge](@site/static/img/memes/flextape.jpeg) + +## 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/vite-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.29.0/explainers/explainer-oracle.md b/docs/versioned_docs/version-v0.29.0/explainers/explainer-oracle.md new file mode 100644 index 00000000000..b84ca5dd986 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/explainers/explainer-oracle.md @@ -0,0 +1,57 @@ +--- +title: Oracles +description: This guide provides an in-depth understanding of how Oracles work in Noir programming. Learn how to use outside calculations in your programs, constrain oracles, and understand their uses and limitations. +keywords: + - Noir Programming + - Oracles + - JSON-RPC + - Foreign Call Handlers + - Constrained Functions + - Blockchain Programming +sidebar_position: 1 +--- + +If you've seen "The Matrix" you may recall "The Oracle" as Gloria Foster smoking cigarettes and baking cookies. While she appears to "know things", she is actually providing a calculation of a pre-determined future. Noir Oracles are similar, in a way. They don't calculate the future (yet), but they allow you to use outside calculations in your programs. + +![matrix oracle prediction](@site/static/img/memes/matrix_oracle.jpeg) + +A Noir program is usually self-contained. You can pass certain inputs to it, and it will generate a deterministic output for those inputs. But what if you wanted to defer some calculation to an outside process or source? + +Oracles are functions that provide this feature. + +## Use cases + +An example usage for Oracles is proving something on-chain. For example, proving that the ETH-USDC quote was below a certain target at a certain block time. Or even making more complex proofs like proving the ownership of an NFT as an anonymous login method. + +Another interesting use case is to defer expensive calculations to be made outside of the Noir program, and then constraining the result; similar to the use of [unconstrained functions](../noir/concepts//unconstrained.md). + +In short, anything that can be constrained in a Noir program but needs to be fetched from an external source is a great candidate to be used in oracles. + +## Constraining oracles + +Just like in The Matrix, Oracles are powerful. But with great power, comes great responsibility. Just because you're using them in a Noir program doesn't mean they're true. Noir has no superpowers. If you want to prove that Portugal won the Euro Cup 2016, you're still relying on potentially untrusted information. + +To give a concrete example, Alice wants to login to the [NounsDAO](https://nouns.wtf/) forum with her username "noir_nouner" by proving she owns a noun without revealing her ethereum address. Her Noir program could have a oracle call like this: + +```rust +#[oracle(getNoun)] +unconstrained fn get_noun(address: Field) -> Field +``` + +This oracle could naively resolve with the number of Nouns she possesses. However, it is useless as a trusted source, as the oracle could resolve to anything Alice wants. In order to make this oracle call actually useful, Alice would need to constrain the response from the oracle, by proving her address and the noun count belongs to the state tree of the contract. + +In short, **Oracles don't prove anything. Your Noir program does.** + +:::danger + +If you don't constrain the return of your oracle, you could be clearly opening an attack vector on your Noir program. Make double-triple sure that the return of an oracle call is constrained! + +::: + +## How to use Oracles + +On CLI, Nargo resolves oracles by making JSON RPC calls, which means it would require an RPC node to be running. + +In JavaScript, NoirJS accepts and resolves arbitrary call handlers (that is, not limited to JSON) as long as they matches the expected types the developer defines. Refer to [Foreign Call Handler](../reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md) to learn more about NoirJS's call handling. + +If you want to build using oracles, follow through to the [oracle guide](../how_to/how-to-oracles.md) for a simple example on how to do that. diff --git a/docs/versioned_docs/version-v0.29.0/explainers/explainer-recursion.md b/docs/versioned_docs/version-v0.29.0/explainers/explainer-recursion.md new file mode 100644 index 00000000000..18846176ca7 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/explainers/explainer-recursion.md @@ -0,0 +1,176 @@ +--- +title: Recursive proofs +description: Explore the concept of recursive proofs in Zero-Knowledge programming. Understand how recursion works in Noir, a language for writing smart contracts on the EVM blockchain. Learn through practical examples like Alice and Bob's guessing game, Charlie's recursive merkle tree, and Daniel's reusable components. Discover how to use recursive proofs to optimize computational resources and improve efficiency. + +keywords: + [ + "Recursive Proofs", + "Zero-Knowledge Programming", + "Noir", + "EVM Blockchain", + "Smart Contracts", + "Recursion in Noir", + "Alice and Bob Guessing Game", + "Recursive Merkle Tree", + "Reusable Components", + "Optimizing Computational Resources", + "Improving Efficiency", + "Verification Key", + "Aggregation", + "Recursive zkSNARK schemes", + "PLONK", + "Proving and Verification Keys" + ] +sidebar_position: 1 +pagination_next: how_to/how-to-recursion +--- + +In programming, we tend to think of recursion as something calling itself. A classic example would be the calculation of the factorial of a number: + +```js +function factorial(n) { + if (n === 0 || n === 1) { + return 1; + } else { + return n * factorial(n - 1); + } +} +``` + +In this case, while `n` is not `1`, this function will keep calling itself until it hits the base case, bubbling up the result on the call stack: + +```md + Is `n` 1? <--------- + /\ / + / \ n = n -1 + / \ / + Yes No -------- +``` + +In Zero-Knowledge, recursion has some similarities. + +It is not a Noir function calling itself, but a proof being used as an input to another circuit. In short, you verify one proof *inside* another proof, returning the proof that both proofs are valid. + +This means that, given enough computational resources, you can prove the correctness of any arbitrary number of proofs in a single proof. This could be useful to design state channels (for which a common example would be [Bitcoin's Lightning Network](https://en.wikipedia.org/wiki/Lightning_Network)), to save on gas costs by settling one proof on-chain, or simply to make business logic less dependent on a consensus mechanism. + +## Examples + +Let us look at some of these examples + +### Alice and Bob - Guessing game + +Alice and Bob are friends, and they like guessing games. They want to play a guessing game online, but for that, they need a trusted third-party that knows both of their secrets and finishes the game once someone wins. + +So, they use zero-knowledge proofs. Alice tries to guess Bob's number, and Bob will generate a ZK proof stating whether she succeeded or failed. + +This ZK proof can go on a smart contract, revealing the winner and even giving prizes. However, this means every turn needs to be verified on-chain. This incurs some cost and waiting time that may simply make the game too expensive or time-consuming to be worth it. + +As a solution, Alice proposes the following: "what if Bob generates his proof, and instead of sending it on-chain, I verify it *within* my own proof before playing my own turn?". + +She can then generate a proof that she verified his proof, and so on. + +```md + Did you fail? <-------------------------- + / \ / + / \ n = n -1 + / \ / + Yes No / + | | / + | | / + | You win / + | / + | / +Generate proof of that / + + / + my own guess ---------------- +``` + +### Charlie - Recursive merkle tree + +Charlie is a concerned citizen, and wants to be sure his vote in an election is accounted for. He votes with a ZK proof, but he has no way of knowing that his ZK proof was included in the total vote count! + +If the vote collector puts all of the votes into a [Merkle tree](https://en.wikipedia.org/wiki/Merkle_tree), everyone can prove the verification of two proofs within one proof, as such: + +```md + abcd + __________|______________ + | | + ab cd + _____|_____ ______|______ + | | | | + alice bob charlie daniel +``` + +Doing this recursively allows us to arrive on a final proof `abcd` which if true, verifies the correctness of all the votes. + +### Daniel - Reusable components + +Daniel has a big circuit and a big headache. A part of his circuit is a setup phase that finishes with some assertions that need to be made. But that section alone takes most of the proving time, and is largely independent of the rest of the circuit. + +He might find it more efficient to generate a proof for that setup phase separately, and verify that proof recursively in the actual business logic section of his circuit. This will allow for parallelization of both proofs, which results in a considerable speedup. + +## What params do I need + +As you can see in the [recursion reference](noir/standard_library/recursion.md), a simple recursive proof requires: + +- The proof to verify +- The Verification Key of the circuit that generated the proof +- A hash of this verification key, as it's needed for some backends +- The public inputs for the proof + +:::info + +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. + +So, taking the example of Alice and Bob and their guessing game: + +- Alice makes her guess. Her proof is *not* recursive: it doesn't verify any proof within it! It's just a standard `assert(x != y)` circuit +- Bob verifies Alice's proof and makes his own guess. In this circuit, he doesn't exactly *prove* the verification of Alice's proof. Instead, he *aggregates* his proof to Alice's proof. The actual verification is done when the full proof is verified, for example when using `nargo verify` or through the verifier smart contract. + +We can imagine recursive proofs a [relay race](https://en.wikipedia.org/wiki/Relay_race). The first runner doesn't have to receive the baton from anyone else, as he/she already starts with it. But when his/her turn is over, the next runner needs to receive it, run a bit more, and pass it along. Even though every runner could theoretically verify the baton mid-run (why not? 🏃🔍), only at the end of the race does the referee verify that the whole race is valid. + +::: + +## Some architecture + +As with everything in computer science, there's no one-size-fits all. But there are some patterns that could help understanding and implementing them. To give three examples: + +### Adding some logic to a proof verification + +This would be an approach for something like our guessing game, where proofs are sent back and forth and are verified by each opponent. This circuit would be divided in two sections: + +- A `recursive verification` section, which would be just the call to `std::verify_proof`, and that would be skipped on the first move (since there's no proof to verify) +- A `guessing` section, which is basically the logic part where the actual guessing happens + +In such a situation, and assuming Alice is first, she would skip the first part and try to guess Bob's number. Bob would then verify her proof on the first section of his run, and try to guess Alice's number on the second part, and so on. + +### Aggregating proofs + +In some one-way interaction situations, recursion would allow for aggregation of simple proofs that don't need to be immediately verified on-chain or elsewhere. + +To give a practical example, a barman wouldn't need to verify a "proof-of-age" on-chain every time he serves alcohol to a customer. Instead, the architecture would comprise two circuits: + +- A `main`, non-recursive circuit with some logic +- A `recursive` circuit meant to verify two proofs in one proof + +The customer's proofs would be intermediate, and made on their phones, and the barman could just verify them locally. He would then aggregate them into a final proof sent on-chain (or elsewhere) at the end of the day. + +### Recursively verifying different circuits + +Nothing prevents you from verifying different circuits in a recursive proof, for example: + +- A `circuit1` circuit +- A `circuit2` circuit +- A `recursive` circuit + +In this example, a regulator could verify that taxes were paid for a specific purchase by aggregating both a `payer` circuit (proving that a purchase was made and taxes were paid), and a `receipt` circuit (proving that the payment was received) + +## How fast is it + +At the time of writing, verifying recursive proofs is surprisingly fast. This is because most of the time is spent on generating the verification key that will be used to generate the next proof. So you are able to cache the verification key and reuse it later. + +Currently, Noir JS packages don't expose the functionality of loading proving and verification keys, but that feature exists in the underlying `bb.js` package. + +## How can I try it + +Learn more about using recursion in Nargo and NoirJS in the [how-to guide](../how_to/how-to-recursion.md) and see a full example in [noir-examples](https://github.com/noir-lang/noir-examples). diff --git a/docs/versioned_docs/version-v0.29.0/getting_started/_category_.json b/docs/versioned_docs/version-v0.29.0/getting_started/_category_.json new file mode 100644 index 00000000000..5d694210bbf --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/getting_started/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 0, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.29.0/getting_started/hello_noir/_category_.json b/docs/versioned_docs/version-v0.29.0/getting_started/hello_noir/_category_.json new file mode 100644 index 00000000000..23b560f610b --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/getting_started/hello_noir/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 1, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.29.0/getting_started/hello_noir/index.md b/docs/versioned_docs/version-v0.29.0/getting_started/hello_noir/index.md new file mode 100644 index 00000000000..743c4d8d634 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/getting_started/hello_noir/index.md @@ -0,0 +1,142 @@ +--- +title: Creating a Project +description: + Learn how to create and verify your first Noir program using Nargo, a programming language for + zero-knowledge proofs. +keywords: + [ + Nargo, + Noir, + zero-knowledge proofs, + programming language, + create Noir program, + verify Noir program, + step-by-step guide, + ] +sidebar_position: 1 + +--- + +Now that we have installed Nargo, it is time to make our first hello world program! + +## Create a Project Directory + +Noir code can live anywhere on your computer. Let us create a _projects_ folder in the home +directory to house our Noir programs. + +For Linux, macOS, and Windows PowerShell, create the directory and change directory into it by +running: + +```sh +mkdir ~/projects +cd ~/projects +``` + +## Create Our First Nargo Project + +Now that we are in the projects directory, create a new Nargo project by running: + +```sh +nargo new hello_world +``` + +> **Note:** `hello_world` can be any arbitrary project name, we are simply using `hello_world` for +> demonstration. +> +> In production, the common practice is to name the project folder as `circuits` for better +> identifiability when sitting alongside other folders in the codebase (e.g. `contracts`, `scripts`, +> `test`). + +A `hello_world` folder would be created. Similar to Rust, the folder houses _src/main.nr_ and +_Nargo.toml_ which contain 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](../../noir/concepts/data_types/index.md) section. + +The next line of the program specifies its body: + +```rust +assert(x != y); +``` + +The Noir syntax `assert` can be interpreted as something similar to constraints in other zk-contract languages. + +For more Noir syntax, check the [Language Concepts](../../noir/concepts/comments.md) chapter. + +## Build In/Output Files + +Change directory into _hello_world_ and build in/output files for your Noir program by running: + +```sh +cd hello_world +nargo check +``` + +Two additional files would be generated in your project directory: + +_Prover.toml_ houses input values, and _Verifier.toml_ houses public values. + +## Prove Our Noir Program + +Now that the project is set up, we can create a proof of correct execution of 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](./project_breakdown.md), we will go into more detail on each step performed. diff --git a/docs/versioned_docs/version-v0.29.0/getting_started/hello_noir/project_breakdown.md b/docs/versioned_docs/version-v0.29.0/getting_started/hello_noir/project_breakdown.md new file mode 100644 index 00000000000..6160a102c6c --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/getting_started/hello_noir/project_breakdown.md @@ -0,0 +1,199 @@ +--- +title: Project Breakdown +description: + Learn about the anatomy of a Nargo project, including the purpose of the Prover and Verifier TOML + files, and how to prove and verify your program. +keywords: + [Nargo, Nargo project, Prover.toml, Verifier.toml, proof verification, private asset transfer] +sidebar_position: 2 +--- + +This section breaks down our hello world program from the previous section. We elaborate on the project +structure and what the `prove` and `verify` commands did. + +## 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 = "noir_starter" +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](../../noir/modules_packages_crates/workspaces.md) will look a bit different. For example: + +```toml +[workspace] +members = ["crates/a", "crates/b"] +default-member = "crates/a" +``` + +#### Package section + +The package section defines 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](../../noir/modules_packages_crates/dependencies.md) for more info. + +`./proofs/` and `./contract/` directories will not be immediately visible until you create a proof or +verifier contract respectively. + +### main.nr + +The _main.nr_ file contains a `main` method, this method is the entry point into your Noir program. + +In our sample program, _main.nr_ looks like this: + +```rust +fn main(x : Field, y : Field) { + assert(x != y); +} +``` + +The parameters `x` and `y` can be seen as the API for the program and must be supplied by the +prover. Since neither `x` nor `y` is marked as public, the verifier does not supply any inputs, when +verifying the proof. + +The prover supplies the values for `x` and `y` in the _Prover.toml_ file. + +As for the program body, `assert` ensures that the condition to be satisfied (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 inequality 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, usually from external sources, and +verify the validity of the proof against it. + +Take a private asset transfer as an example: + +A person using a browser as the prover would retrieve private inputs locally (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.29.0/getting_started/installation/_category_.json b/docs/versioned_docs/version-v0.29.0/getting_started/installation/_category_.json new file mode 100644 index 00000000000..0c02fb5d4d7 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/getting_started/installation/_category_.json @@ -0,0 +1,6 @@ +{ + "position": 0, + "label": "Install Nargo", + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.29.0/getting_started/installation/index.md b/docs/versioned_docs/version-v0.29.0/getting_started/installation/index.md new file mode 100644 index 00000000000..4ef86aa5914 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/getting_started/installation/index.md @@ -0,0 +1,48 @@ +--- +title: Nargo Installation +description: + nargo is a command line tool for interacting with Noir programs. This page is a quick guide on how to install Nargo through the most common and easy method, noirup +keywords: [ + Nargo + Noir + Rust + Cargo + Noirup + Installation + Terminal Commands + Version Check + Nightlies + Specific Versions + Branches + Noirup Repository +] +pagination_next: getting_started/hello_noir/index +--- + +`nargo` is the one-stop-shop for almost everything related with Noir. The name comes from our love for Rust and its package manager `cargo`. + +With `nargo`, you can start new projects, compile, execute, prove, verify, test, generate solidity contracts, and do pretty much all that is available in Noir. + +Similarly to `rustup`, we also maintain an easy installation method that covers most machines: `noirup`. + +## Installing Noirup + +Open a terminal on your machine, and write: + +```bash +curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash +``` + +Close the terminal, open another one, and run + +```bash +noirup +``` + +Done. That's it. You should have the latest version working. You can check with `nargo --version`. + +You can also install nightlies, specific versions +or branches. Check out the [noirup repository](https://github.com/noir-lang/noirup) for more +information. + +Now we're ready to start working on [our first Noir program!](../hello_noir/index.md) diff --git a/docs/versioned_docs/version-v0.29.0/getting_started/installation/other_install_methods.md b/docs/versioned_docs/version-v0.29.0/getting_started/installation/other_install_methods.md new file mode 100644 index 00000000000..3634723562b --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/getting_started/installation/other_install_methods.md @@ -0,0 +1,102 @@ +--- +title: Alternative Installations +description: There are different ways to install Nargo, the one-stop shop and command-line tool for developing Noir programs. This guide explains how to specify which version to install when using noirup, and using WSL for windows. +keywords: [ + Installation + Nargo + Noirup + Binaries + Compiling from Source + WSL for Windows + macOS + Linux + Nix + Direnv + Uninstalling Nargo + ] +sidebar_position: 1 +--- + +## Encouraged Installation Method: Noirup + +Noirup is the endorsed method for installing Nargo, streamlining the process of fetching binaries or compiling from source. It supports a range of options to cater to your specific needs, from nightly builds and specific versions to compiling from various sources. + +### Installing Noirup + +First, ensure you have `noirup` installed: + +```sh +curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash +``` + +### Fetching Binaries + +With `noirup`, you can easily switch between different Nargo versions, including nightly builds: + +- **Nightly Version**: Install the latest nightly build. + + ```sh + noirup --version nightly + ``` + +- **Specific Version**: Install a specific version of Nargo. + ```sh + noirup --version + ``` + +### Compiling from Source + +`noirup` also enables compiling Nargo from various sources: + +- **From a Specific Branch**: Install from the latest commit on a branch. + + ```sh + noirup --branch + ``` + +- **From a Fork**: Install from the main branch of a fork. + + ```sh + noirup --repo + ``` + +- **From a Specific Branch in a Fork**: Install from a specific branch in a fork. + + ```sh + noirup --repo --branch + ``` + +- **From a Specific Pull Request**: Install from a specific PR. + + ```sh + noirup --pr + ``` + +- **From a Specific Commit**: Install from a specific commit. + + ```sh + noirup -C + ``` + +- **From Local Source**: Compile and install from a local directory. + ```sh + noirup --path ./path/to/local/source + ``` + +## Installation on Windows + +The default backend for Noir (Barretenberg) doesn't provide Windows binaries at this time. For that reason, Noir cannot be installed natively. 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](#encouraged-installation-method-noirup). + +## Uninstalling Nargo + +If you installed Nargo with `noirup`, you can uninstall Nargo by removing the files in `~/.nargo`, `~/nargo`, and `~/noir_cache`. This ensures that all installed binaries, configurations, and cache related to Nargo are fully removed from your system. + +```bash +rm -r ~/.nargo +rm -r ~/nargo +rm -r ~/noir_cache +``` diff --git a/docs/versioned_docs/version-v0.29.0/getting_started/tooling/noir_codegen.md b/docs/versioned_docs/version-v0.29.0/getting_started/tooling/noir_codegen.md new file mode 100644 index 00000000000..d65151da0ab --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/getting_started/tooling/noir_codegen.md @@ -0,0 +1,113 @@ +--- +title: Noir Codegen for TypeScript +description: Learn how to use Noir codegen to generate TypeScript bindings +keywords: [Nargo, Noir, compile, TypeScript] +sidebar_position: 2 +--- + +When using TypeScript, it is extra work to interpret Noir program outputs in a type-safe way. Third party libraries may exist for popular Noir programs, but they are either hard to find or unmaintained. + +Now you can generate TypeScript bindings for your Noir programs in two steps: +1. Exporting Noir functions using `nargo export` +2. Using the TypeScript module `noir_codegen` to generate TypeScript binding + +**Note:** you can only export functions from a Noir *library* (not binary or contract program types). + +## Installation + +### Your TypeScript project + +If you don't already have a TypeScript project you can add the module with `yarn` (or `npm`), then initialize it: + +```bash +yarn add typescript -D +npx tsc --init +``` + +### Add TypeScript module - `noir_codegen` + +The following command will add the module to your project's devDependencies: + +```bash +yarn add @noir-lang/noir_codegen -D +``` + +### Nargo library +Make sure you have Nargo, v0.25.0 or greater, installed. If you don't, follow the [installation guide](../installation/index.md). + +If you're in a new project, make a `circuits` folder and create a new Noir library: + +```bash +mkdir circuits && cd circuits +nargo new --lib myNoirLib +``` + +## Usage + +### Export ABI of specified functions + +First go to the `.nr` files in your Noir library, and add the `#[export]` macro to each function that you want to use in TypeScript. + +```rust +#[export] +fn your_function(... +``` + +From your Noir library (where `Nargo.toml` is), run the following command: + +```bash +nargo export +``` + +You will now have an `export` directory with a .json file per exported function. + +You can also specify the directory of Noir programs using `--program-dir`, for example: + +```bash +nargo export --program-dir=./circuits/myNoirLib +``` + +### Generate TypeScript bindings from exported functions + +To use the `noir-codegen` package we added to the TypeScript project: + +```bash +yarn noir-codegen ./export/your_function.json +``` + +This creates an `exports` directory with an `index.ts` file containing all exported functions. + +**Note:** adding `--out-dir` allows you to specify an output dir for your TypeScript bindings to go. Eg: + +```bash +yarn noir-codegen ./export/*.json --out-dir ./path/to/output/dir +``` + +## Example .nr function to .ts output + +Consider a Noir library with this function: + +```rust +#[export] +fn not_equal(x: Field, y: Field) -> bool { + x != y +} +``` + +After the export and codegen steps, you should have an `index.ts` like: + +```typescript +export type Field = string; + + +export const is_equal_circuit: CompiledCircuit = {"abi":{"parameters":[{"name":"x","type":{"kind":"field"},"visibility":"private"},{"name":"y","type":{"kind":"field"},"visibility":"private"}],"param_witnesses":{"x":[{"start":0,"end":1}],"y":[{"start":1,"end":2}]},"return_type":{"abi_type":{"kind":"boolean"},"visibility":"private"},"return_witnesses":[4]},"bytecode":"H4sIAAAAAAAA/7WUMQ7DIAxFQ0Krrr2JjSGYLVcpKrn/CaqqDQN12WK+hPBgmWd/wEyHbF1SS923uhOs3pfoChI+wKXMAXzIKyNj4PB0TFTYc0w5RUjoqeAeEu1wqK0F54RGkWvW44LPzExnlkbMEs4JNZmN8PxS42uHv82T8a3Jeyn2Ks+VLPcO558HmyLMCDOXAXXtpPt4R/Rt9T36ss6dS9HGPx/eG17nGegKBQAA"}; + +export async function is_equal(x: Field, y: Field, foreignCallHandler?: ForeignCallHandler): Promise { + const program = new Noir(is_equal_circuit); + const args: InputMap = { x, y }; + const { returnValue } = await program.execute(args, foreignCallHandler); + return returnValue as boolean; +} +``` + +Now the `is_equal()` function and relevant types are readily available for use in TypeScript. diff --git a/docs/versioned_docs/version-v0.29.0/how_to/_category_.json b/docs/versioned_docs/version-v0.29.0/how_to/_category_.json new file mode 100644 index 00000000000..23b560f610b --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/how_to/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 1, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.29.0/how_to/debugger/_category_.json b/docs/versioned_docs/version-v0.29.0/how_to/debugger/_category_.json new file mode 100644 index 00000000000..cc2cbb1c253 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/how_to/debugger/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Debugging", + "position": 5, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.29.0/how_to/debugger/debugging_with_the_repl.md b/docs/versioned_docs/version-v0.29.0/how_to/debugger/debugging_with_the_repl.md new file mode 100644 index 00000000000..09e5bae68ad --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/how_to/debugger/debugging_with_the_repl.md @@ -0,0 +1,164 @@ +--- +title: Using the REPL Debugger +description: + Step by step guide on how to debug your Noir circuits with the REPL Debugger. +keywords: + [ + Nargo, + Noir CLI, + Noir Debugger, + REPL, + ] +sidebar_position: 1 +--- + +#### Pre-requisites + +In order to use the REPL debugger, first you need to install recent enough versions of Nargo and vscode-noir. + +## Debugging a simple circuit + +Let's debug a simple circuit: + +```rust +fn main(x : Field, y : pub Field) { + assert(x != y); +} +``` + +To start the REPL debugger, using a terminal, go to a Noir circuit's home directory. Then: + +`$ nargo debug` + +You should be seeing this in your terminal: + +``` +[main] Starting debugger +At ~/noir-examples/recursion/circuits/main/src/main.nr:1:9 + 1 -> fn main(x : Field, y : pub Field) { + 2 assert(x != y); + 3 } +> +``` + +The debugger displays the current Noir code location, and it is now waiting for us to drive it. + +Let's first take a look at the available commands. For that we'll use the `help` command. + +``` +> help +Available commands: + + opcodes display ACIR opcodes + into step into to the next opcode + next step until a new source location is reached + out step until a new source location is reached + and the current stack frame is finished + break LOCATION:OpcodeLocation add a breakpoint at an opcode location + over step until a new source location is reached + without diving into function calls + restart restart the debugging session + delete LOCATION:OpcodeLocation delete breakpoint at an opcode location + witness show witness map + witness index:u32 display a single witness from the witness map + witness index:u32 value:String update a witness with the given value + memset index:usize value:String update a memory cell with the given + value + continue continue execution until the end of the + program + vars show variable values available at this point + in execution + stacktrace display the current stack trace + memory show memory (valid when executing unconstrained code) + step step to the next ACIR opcode + +Other commands: + + help Show this help message + quit Quit repl + +``` + +Some commands operate only for unconstrained functions, such as `memory` and `memset`. If you try to use them while execution is paused at an ACIR opcode, the debugger will simply inform you that you are not executing unconstrained code: + +``` +> memory +Unconstrained VM memory not available +> +``` + +Before continuing, we can take a look at the initial witness map: + +``` +> witness +_0 = 1 +_1 = 2 +> +``` + +Cool, since `x==1`, `y==2`, and we want to check that `x != y`, our circuit should succeed. At this point we could intervene and use the witness setter command to change one of the witnesses. Let's set `y=3`, then back to 2, so we don't affect the expected result: + +``` +> witness +_0 = 1 +_1 = 2 +> witness 1 3 +_1 = 3 +> witness +_0 = 1 +_1 = 3 +> witness 1 2 +_1 = 2 +> witness +_0 = 1 +_1 = 2 +> +``` + +Now we can inspect the current state of local variables. For that we use the `vars` command. + +``` +> vars +> +``` + +We currently have no vars in context, since we are at the entry point of the program. Let's use `next` to execute until the next point in the program. + +``` +> vars +> next +At ~/noir-examples/recursion/circuits/main/src/main.nr:1:20 + 1 -> fn main(x : Field, y : pub Field) { + 2 assert(x != y); + 3 } +> vars +x:Field = 0x01 +``` + +As a result of stepping, the variable `x`, whose initial value comes from the witness map, is now in context and returned by `vars`. + +``` +> next + 1 fn main(x : Field, y : pub Field) { + 2 -> assert(x != y); + 3 } +> vars +y:Field = 0x02 +x:Field = 0x01 +``` + +Stepping again we can finally see both variables and their values. And now we can see that the next assertion should succeed. + +Let's continue to the end: + +``` +> continue +(Continuing execution...) +Finished execution +> q +[main] Circuit witness successfully solved +``` + +Upon quitting the debugger after a solved circuit, the resulting circuit witness gets saved, equivalent to what would happen if we had run the same circuit with `nargo execute`. + +We just went through the basics of debugging using Noir REPL debugger. For a comprehensive reference, check out [the reference page](../../reference/debugger/debugger_repl.md). diff --git a/docs/versioned_docs/version-v0.29.0/how_to/debugger/debugging_with_vs_code.md b/docs/versioned_docs/version-v0.29.0/how_to/debugger/debugging_with_vs_code.md new file mode 100644 index 00000000000..a5858c1a5eb --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/how_to/debugger/debugging_with_vs_code.md @@ -0,0 +1,68 @@ +--- +title: Using the VS Code Debugger +description: + Step by step guide on how to debug your Noir circuits with the VS Code Debugger configuration and features. +keywords: + [ + Nargo, + Noir CLI, + Noir Debugger, + VS Code, + IDE, + ] +sidebar_position: 0 +--- + +This guide will show you how to use VS Code with the vscode-noir extension to debug a Noir project. + +#### Pre-requisites + +- Nargo +- vscode-noir +- A Noir project with a `Nargo.toml`, `Prover.toml` and at least one Noir (`.nr`) containing an entry point function (typically `main`). + +## Running the debugger + +The easiest way to start debugging is to open the file you want to debug, and press `F5`. This will cause the debugger to launch, using your `Prover.toml` file as input. + +You should see something like this: + +![Debugger launched](@site/static/img/debugger/1-started.png) + +Let's inspect the state of the program. For that, we open VS Code's _Debug pane_. Look for this icon: + +![Debug pane icon](@site/static/img/debugger/2-icon.png) + +You will now see two categories of variables: Locals and Witness Map. + +![Debug pane expanded](@site/static/img/debugger/3-debug-pane.png) + +1. **Locals**: variables of your program. At this point in execution this section is empty, but as we step through the code it will get populated by `x`, `result`, `digest`, etc. + +2. **Witness map**: these are initially populated from your project's `Prover.toml` file. In this example, they will be used to populate `x` and `result` at the beginning of the `main` function. + +Most of the time you will probably be focusing mostly on locals, as they represent the high level state of your program. + +You might be interested in inspecting the witness map in case you are trying to solve a really low level issue in the compiler or runtime itself, so this concerns mostly advanced or niche users. + +Let's step through the program, by using the debugger buttons or their corresponding keyboard shortcuts. + +![Debugger buttons](@site/static/img/debugger/4-debugger-buttons.png) + +Now we can see in the variables pane that there's values for `digest`, `result` and `x`. + +![Inspecting locals](@site/static/img/debugger/5-assert.png) + +We can also inspect the values of variables by directly hovering on them on the code. + +![Hover locals](@site/static/img/debugger/6-hover.png) + +Let's set a break point at the `keccak256` function, so we can continue execution up to the point when it's first invoked without having to go one step at a time. + +We just need to click the to the right of the line number 18. Once the breakpoint appears, we can click the `continue` button or use its corresponding keyboard shortcut (`F5` by default). + +![Breakpoint](@site/static/img/debugger/7-break.png) + +Now we are debugging the `keccak256` function, notice the _Call Stack pane_ at the lower right. This lets us inspect the current call stack of our process. + +That covers most of the current debugger functionalities. Check out [the reference](../../reference/debugger/debugger_vscode.md) for more details on how to configure the debugger. \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.29.0/how_to/how-to-oracles.md b/docs/versioned_docs/version-v0.29.0/how_to/how-to-oracles.md new file mode 100644 index 00000000000..8cf8035a5c4 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/how_to/how-to-oracles.md @@ -0,0 +1,276 @@ +--- +title: How to use Oracles +description: Learn how to use oracles in your Noir program with examples in both Nargo and NoirJS. This guide also covers writing a JSON RPC server and providing custom foreign call handlers for NoirJS. +keywords: + - Noir Programming + - Oracles + - Nargo + - NoirJS + - JSON RPC Server + - Foreign Call Handlers +sidebar_position: 1 +--- + +This guide shows you how to use oracles in your Noir program. For the sake of clarity, it assumes that: + +- You have read the [explainer on Oracles](../explainers/explainer-oracle.md) and are comfortable with the concept. +- You have a Noir program to add oracles to. You can create one using the [vite-hardhat starter](https://github.com/noir-lang/noir-starter/tree/main/vite-hardhat) as a boilerplate. +- You understand the concept of a JSON-RPC server. Visit the [JSON-RPC website](https://www.jsonrpc.org/) if you need a refresher. +- You are comfortable with server-side JavaScript (e.g. Node.js, managing packages, etc.). + +For reference, you can find the snippets used in this tutorial on the [Aztec DevRel Repository](https://github.com/AztecProtocol/dev-rel/tree/main/code-snippets/how-to-oracles). + +## Rundown + +This guide has 3 major steps: + +1. How to modify our Noir program to make use of oracle calls as unconstrained functions +2. How to write a JSON RPC Server to resolve these oracle calls with Nargo +3. How to use them in Nargo and how to provide a custom resolver in NoirJS + +## Step 1 - Modify your Noir program + +An oracle is defined in a Noir program by defining two methods: + +- An unconstrained method - This tells the compiler that it is executing an [unconstrained functions](../noir/concepts//unconstrained.md). +- A decorated oracle method - This tells the compiler that this method is an RPC call. + +An example of an oracle that returns a `Field` would be: + +```rust +#[oracle(getSqrt)] +unconstrained fn sqrt(number: Field) -> Field { } + +unconstrained fn get_sqrt(number: Field) -> Field { + sqrt(number) +} +``` + +In this example, we're wrapping our oracle function in a unconstrained method, and decorating it with `oracle(getSqrt)`. We can then call the unconstrained function as we would call any other function: + +```rust +fn main(input: Field) { + let sqrt = get_sqrt(input); +} +``` + +In the next section, we will make this `getSqrt` (defined on the `sqrt` decorator) be a method of the RPC server Noir will use. + +:::danger + +As explained in the [Oracle Explainer](../explainers/explainer-oracle.md), this `main` function is unsafe unless you constrain its return value. For example: + +```rust +fn main(input: Field) { + let sqrt = get_sqrt(input); + assert(sqrt.pow_32(2) as u64 == input as u64); // <---- constrain the return of an oracle! +} +``` + +::: + +:::info + +Currently, oracles only work with single params or array params. For example: + +```rust +#[oracle(getSqrt)] +unconstrained fn sqrt([Field; 2]) -> [Field; 2] { } +``` + +::: + +## Step 2 - Write an RPC server + +Brillig will call *one* RPC server. Most likely you will have to write your own, and you can do it in whatever language you prefer. In this guide, we will do it in Javascript. + +Let's use the above example of an oracle that consumes an array with two `Field` and returns their square roots: + +```rust +#[oracle(getSqrt)] +unconstrained fn sqrt(input: [Field; 2]) -> [Field; 2] { } + +unconstrained fn get_sqrt(input: [Field; 2]) -> [Field; 2] { + sqrt(input) +} + +fn main(input: [Field; 2]) { + let sqrt = get_sqrt(input); + assert(sqrt[0].pow_32(2) as u64 == input[0] as u64); + assert(sqrt[1].pow_32(2) as u64 == input[1] as u64); +} +``` + +:::info + +Why square root? + +In general, computing square roots is computationally more expensive than multiplications, which takes a toll when speaking about ZK applications. In this case, instead of calculating the square root in Noir, we are using our oracle to offload that computation to be made in plain. In our circuit we can simply multiply the two values. + +::: + +Now, we should write the correspondent RPC server, starting with the [default JSON-RPC 2.0 boilerplate](https://www.npmjs.com/package/json-rpc-2.0#example): + +```js +import { JSONRPCServer } from "json-rpc-2.0"; +import express from "express"; +import bodyParser from "body-parser"; + +const app = express(); +app.use(bodyParser.json()); + +const server = new JSONRPCServer(); +app.post("/", (req, res) => { + const jsonRPCRequest = req.body; + server.receive(jsonRPCRequest).then((jsonRPCResponse) => { + if (jsonRPCResponse) { + res.json(jsonRPCResponse); + } else { + res.sendStatus(204); + } + }); +}); + +app.listen(5555); +``` + +Now, we will add our `getSqrt` method, as expected by the `#[oracle(getSqrt)]` decorator in our Noir code. It maps through the params array and returns their square roots: + +```js +server.addMethod("getSqrt", async (params) => { + const values = params[0].Array.map((field) => { + return `${Math.sqrt(parseInt(field, 16))}`; + }); + return { values: [{ Array: values }] }; +}); +``` + +:::tip + +Brillig expects an object with an array of values. Each value is an object declaring to be `Single` or `Array` and returning a field element *as a string*. For example: + +```json +{ "values": [{ "Array": ["1", "2"] }]} +{ "values": [{ "Single": "1" }]} +{ "values": [{ "Single": "1" }, { "Array": ["1", "2"] }]} +``` + +If you're using Typescript, the following types may be helpful in understanding the expected return value and making sure they're easy to follow: + +```js +interface SingleForeignCallParam { + Single: string, +} + +interface ArrayForeignCallParam { + Array: string[], +} + +type ForeignCallParam = SingleForeignCallParam | ArrayForeignCallParam; + +interface ForeignCallResult { + values: ForeignCallParam[], +} +``` + +::: + +## Step 3 - Usage with Nargo + +Using the [`nargo` CLI tool](../getting_started/installation/index.md), you can use oracles in the `nargo test`, `nargo execute` and `nargo prove` commands by passing a value to `--oracle-resolver`. For example: + +```bash +nargo test --oracle-resolver http://localhost:5555 +``` + +This tells `nargo` to use your RPC Server URL whenever it finds an oracle decorator. + +## Step 4 - Usage with NoirJS + +In a JS environment, an RPC server is not strictly necessary, as you may want to resolve your oracles without needing any JSON call at all. NoirJS simply expects that you pass a callback function when you generate proofs, and that callback function can be anything. + +For example, if your Noir program expects the host machine to provide CPU pseudo-randomness, you could simply pass it as the `foreignCallHandler`. You don't strictly need to create an RPC server to serve pseudo-randomness, as you may as well get it directly in your app: + +```js +const foreignCallHandler = (name, inputs) => crypto.randomBytes(16) // etc + +await noir.generateProof(inputs, foreignCallHandler) +``` + +As one can see, in NoirJS, the [`foreignCallHandler`](../reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md) function simply means "a callback function that returns a value of type [`ForeignCallOutput`](../reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md). It doesn't have to be an RPC call like in the case for Nargo. + +:::tip + +Does this mean you don't have to write an RPC server like in [Step #2](#step-2---write-an-rpc-server)? + +You don't technically have to, but then how would you run `nargo test` or `nargo prove`? To use both `Nargo` and `NoirJS` in your development flow, you will have to write a JSON RPC server. + +::: + +In this case, let's make `foreignCallHandler` call the JSON RPC Server we created in [Step #2](#step-2---write-an-rpc-server), by making it a JSON RPC Client. + +For example, using the same `getSqrt` program in [Step #1](#step-1---modify-your-noir-program) (comments in the code): + +```js +import { JSONRPCClient } from "json-rpc-2.0"; + +// declaring the JSONRPCClient +const client = new JSONRPCClient((jsonRPCRequest) => { +// hitting the same JSON RPC Server we coded above + return fetch("http://localhost:5555", { + method: "POST", + headers: { + "content-type": "application/json", + }, + body: JSON.stringify(jsonRPCRequest), + }).then((response) => { + if (response.status === 200) { + return response + .json() + .then((jsonRPCResponse) => client.receive(jsonRPCResponse)); + } else if (jsonRPCRequest.id !== undefined) { + return Promise.reject(new Error(response.statusText)); + } + }); +}); + +// declaring a function that takes the name of the foreign call (getSqrt) and the inputs +const foreignCallHandler = async (name, input) => { + // notice that the "inputs" parameter contains *all* the inputs + // in this case we to make the RPC request with the first parameter "numbers", which would be input[0] + const oracleReturn = await client.request(name, [ + { Array: input[0].map((i) => i.toString("hex")) }, + ]); + return [oracleReturn.values[0].Array]; +}; + +// the rest of your NoirJS code +const input = { input: [4, 16] }; +const { witness } = await noir.execute(numbers, foreignCallHandler); +``` + +:::tip + +If you're in a NoirJS environment running your RPC server together with a frontend app, you'll probably hit a familiar problem in full-stack development: requests being blocked by [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) policy. For development only, you can simply install and use the [`cors` npm package](https://www.npmjs.com/package/cors) to get around the problem: + +```bash +yarn add cors +``` + +and use it as a middleware: + +```js +import cors from "cors"; + +const app = express(); +app.use(cors()) +``` + +::: + +## Conclusion + +Hopefully by the end of this guide, you should be able to: + +- Write your own logic around Oracles and how to write a JSON RPC server to make them work with your Nargo commands. +- Provide custom foreign call handlers for NoirJS. diff --git a/docs/versioned_docs/version-v0.29.0/how_to/how-to-recursion.md b/docs/versioned_docs/version-v0.29.0/how_to/how-to-recursion.md new file mode 100644 index 00000000000..4c45bb87ae2 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/how_to/how-to-recursion.md @@ -0,0 +1,179 @@ +--- +title: How to use recursion on NoirJS +description: Learn how to implement recursion with NoirJS, a powerful tool for creating smart contracts on the EVM blockchain. This guide assumes familiarity with NoirJS, solidity verifiers, and the Barretenberg proving backend. Discover how to generate both final and intermediate proofs using `noir_js` and `backend_barretenberg`. +keywords: + [ + "NoirJS", + "EVM blockchain", + "smart contracts", + "recursion", + "solidity verifiers", + "Barretenberg backend", + "noir_js", + "backend_barretenberg", + "intermediate proofs", + "final proofs", + "nargo compile", + "json import", + "recursive circuit", + "recursive app" + ] +sidebar_position: 1 +--- + +This guide shows you how to use recursive proofs in your NoirJS app. For the sake of clarity, it is assumed that: + +- You already have a NoirJS app. If you don't, please visit the [NoirJS tutorial](../tutorials/noirjs_app.md) and the [reference](../reference/NoirJS/noir_js/index.md). +- You are familiar with what are recursive proofs and you have read the [recursion explainer](../explainers/explainer-recursion.md) +- You already built a recursive circuit following [the reference](../noir/standard_library/recursion.md), and understand how it works. + +It is also assumed that you're not using `noir_wasm` for compilation, and instead you've used [`nargo compile`](../reference/nargo_commands.md) to generate the `json` you're now importing into your project. However, the guide should work just the same if you're using `noir_wasm`. + +:::info + +As you've read in the [explainer](../explainers/explainer-recursion.md), a recursive proof is an intermediate proof. This means that it doesn't necessarily generate the final step that makes it verifiable in a smart contract. However, it is easy to verify within another circuit. + +While "standard" usage of NoirJS packages abstracts final proofs, it currently lacks the necessary interface to abstract away intermediate proofs. This means that these proofs need to be created by using the backend directly. + +In short: + +- `noir_js` generates *only* final proofs +- `backend_barretenberg` generates both types of proofs + +::: + +In a standard recursive app, you're also dealing with at least two circuits. For the purpose of this guide, we will assume the following: + +- `main`: a circuit of type `assert(x != y)`, where `main` is marked with a `#[recursive]` attribute. This attribute states that the backend should generate proofs that are friendly for verification within another circuit. +- `recursive`: a circuit that verifies `main` + +For a full example on how recursive proofs work, please refer to the [noir-examples](https://github.com/noir-lang/noir-examples) repository. We will *not* be using it as a reference for this guide. + +## Step 1: Setup + +In a common NoirJS app, you need to instantiate a backend with something like `const backend = new Backend(circuit)`. Then you feed it to the `noir_js` interface. + +For recursion, this doesn't happen, and the only need for `noir_js` is only to `execute` a circuit and get its witness and return value. Everything else is not interfaced, so it needs to happen on the `backend` object. + +It is also recommended that you instantiate the backend with as many threads as possible, to allow for maximum concurrency: + +```js +const backend = new Backend(circuit, { threads: 8 }) +``` + +:::tip +You can use the [`os.cpus()`](https://nodejs.org/api/os.html#oscpus) object in `nodejs` or [`navigator.hardwareConcurrency`](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/hardwareConcurrency) on the browser to make the most out of those glorious cpu cores +::: + +## Step 2: Generating the witness and the proof for `main` + +After instantiating the backend, you should also instantiate `noir_js`. We will use it to execute the circuit and get the witness. + +```js +const noir = new Noir(circuit, backend) +const { witness } = noir.execute(input) +``` + +With this witness, you are now able to generate the intermediate proof for the main circuit: + +```js +const { proof, publicInputs } = await backend.generateProof(witness) +``` + +:::warning + +Always keep in mind what is actually happening on your development process, otherwise you'll quickly become confused about what circuit we are actually running and why! + +In this case, you can imagine that Alice (running the `main` circuit) is proving something to Bob (running the `recursive` circuit), and Bob is verifying her proof within his proof. + +With this in mind, it becomes clear that our intermediate proof is the one *meant to be verified within another circuit*, so it must be Alice's. Actually, the only final proof in this theoretical scenario would be the last one, sent on-chain. + +::: + +## Step 3 - Verification and proof artifacts + +Optionally, you are able to verify the intermediate proof: + +```js +const verified = await backend.verifyProof({ proof, publicInputs }) +``` + +This can be useful to make sure our intermediate proof was correctly generated. But the real goal is to do it within another circuit. For that, we need to generate recursive proof artifacts that will be passed to the circuit that is verifying the proof we just generated. Instead of passing the proof and verification key as a byte array, we pass them as fields which makes it cheaper to verify in a circuit: + +```js +const { proofAsFields, vkAsFields, vkHash } = await backend.generateRecursiveProofArtifacts( { publicInputs, proof }, publicInputsCount) +``` + +This call takes the public inputs and the proof, but also the public inputs count. While this is easily retrievable by simply counting the `publicInputs` length, the backend interface doesn't currently abstract it away. + +:::info + +The `proofAsFields` has a constant size `[Field; 93]` and verification keys in Barretenberg are always `[Field; 114]`. + +::: + +:::warning + +One common mistake is to forget *who* makes this call. + +In a situation where Alice is generating the `main` proof, if she generates the proof artifacts and sends them to Bob, which gladly takes them as true, this would mean Alice could prove anything! + +Instead, Bob needs to make sure *he* extracts the proof artifacts, using his own instance of the `main` circuit backend. This way, Alice has to provide a valid proof for the correct `main` circuit. + +::: + +## Step 4 - Recursive proof generation + +With the artifacts, generating a recursive proof is no different from a normal proof. You simply use the `backend` (with the recursive circuit) to generate it: + +```js +const recursiveInputs = { + verification_key: vkAsFields, // array of length 114 + proof: proofAsFields, // array of length 93 + size of public inputs + publicInputs: [mainInput.y], // using the example above, where `y` is the only public input + key_hash: vkHash, +} + +const { witness, returnValue } = noir.execute(recursiveInputs) // we're executing the recursive circuit now! +const { proof, publicInputs } = backend.generateProof(witness) +const verified = backend.verifyProof({ proof, publicInputs }) +``` + +You can obviously chain this proof into another proof. In fact, if you're using recursive proofs, you're probably interested of using them this way! + +:::tip + +Managing circuits and "who does what" can be confusing. To make sure your naming is consistent, you can keep them in an object. For example: + +```js +const circuits = { + main: mainJSON, + recursive: recursiveJSON +} +const backends = { + main: new BarretenbergBackend(circuits.main), + recursive: new BarretenbergBackend(circuits.recursive) +} +const noir_programs = { + main: new Noir(circuits.main, backends.main), + recursive: new Noir(circuits.recursive, backends.recursive) +} +``` + +This allows you to neatly call exactly the method you want without conflicting names: + +```js +// Alice runs this 👇 +const { witness: mainWitness } = await noir_programs.main.execute(input) +const proof = await backends.main.generateProof(mainWitness) + +// Bob runs this 👇 +const verified = await backends.main.verifyProof(proof) +const { proofAsFields, vkAsFields, vkHash } = await backends.main.generateRecursiveProofArtifacts( + proof, + numPublicInputs, +); +const recursiveProof = await noir_programs.recursive.generateProof(recursiveInputs) +``` + +::: diff --git a/docs/versioned_docs/version-v0.29.0/how_to/how-to-solidity-verifier.md b/docs/versioned_docs/version-v0.29.0/how_to/how-to-solidity-verifier.md new file mode 100644 index 00000000000..e5ce3b7bc22 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/how_to/how-to-solidity-verifier.md @@ -0,0 +1,232 @@ +--- +title: Generate a Solidity Verifier +description: + Learn how to run the verifier as a smart contract on the blockchain. Compile a Solidity verifier + contract for your Noir program and deploy it on any EVM blockchain acting as a verifier smart + contract. Read more to find out +keywords: + [ + solidity verifier, + smart contract, + blockchain, + compiler, + plonk_vk.sol, + EVM blockchain, + verifying Noir programs, + proving backend, + Barretenberg, + ] +sidebar_position: 0 +pagination_next: tutorials/noirjs_app +--- + +Noir has the ability to generate a verifier contract in Solidity, which can be deployed in many EVM-compatible blockchains such as Ethereum. + +This allows for a powerful feature set, as one can make use of the conciseness and the privacy provided by Noir in an immutable ledger. Applications can range from simple P2P guessing games, to complex private DeFi interactions. + +This guide shows you how to generate a Solidity Verifier and deploy it on the [Remix IDE](https://remix.ethereum.org/). It is assumed that: + +- You are comfortable with the Solidity programming language and understand how contracts are deployed on the Ethereum network +- You have Noir installed and you have a Noir program. If you don't, [get started](../getting_started/installation/index.md) with Nargo and the example Hello Noir circuit +- You are comfortable navigating RemixIDE. If you aren't or you need a refresher, you can find some video tutorials [here](https://www.youtube.com/channel/UCjTUPyFEr2xDGN6Cg8nKDaA) that could help you. + +## Rundown + +Generating a Solidity Verifier contract is actually a one-command process. However, compiling it and deploying it can have some caveats. Here's the rundown of this guide: + +1. How to generate a solidity smart contract +2. How to compile the smart contract in the RemixIDE +3. How to deploy it to a testnet + +## Step 1 - Generate a contract + +This is by far the most straight-forward step. Just run: + +```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 to any EVM blockchain acting as a verifier smart contract. + +:::info + +It is possible to generate 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 generation of verifier contracts, for the time being these are only in Solidity. +::: + +## Step 2 - Compiling + +We will mostly skip the details of RemixIDE, as the UI can change from version to version. For now, we can just open +Remix and create a blank workspace. + +![Create Workspace](@site/static/img/how-tos/solidity_verifier_1.png) + +We will create a new file to contain the contract Nargo generated, and copy-paste its content. + +:::warning + +You'll likely see a warning advising you to not trust pasted code. While it is an important warning, it is irrelevant in the context of this guide and can be ignored. We will not be deploying anywhere near a mainnet. + +::: + +To compile our the verifier, we can navigate to the compilation tab: + +![Compilation Tab](@site/static/img/how-tos/solidity_verifier_2.png) + +Remix should automatically match a suitable compiler version. However, hitting the "Compile" button will most likely generate a "Stack too deep" error: + +![Stack too deep](@site/static/img/how-tos/solidity_verifier_3.png) + +This is due to the verify function needing to put many variables on the stack, but enabling the optimizer resolves the issue. To do this, let's open the "Advanced Configurations" tab and enable optimization. The default 200 runs will suffice. + +:::info + +This time we will see a warning about an unused function parameter. This is expected, as the `verify` function doesn't use the `_proof` parameter inside a solidity block, it is loaded from calldata and used in assembly. + +::: + +![Compilation success](@site/static/img/how-tos/solidity_verifier_4.png) + +## Step 3 - Deploying + +At this point we should have a compiled contract read to deploy. If we navigate to the deploy section in Remix, we will see many different environments we can deploy to. The steps to deploy on each environment would be out-of-scope for this guide, so we will just use the default Remix VM. + +Looking closely, we will notice that our "Solidity Verifier" is actually three contracts working together: + +- An `UltraVerificationKey` library which simply stores the verification key for our circuit. +- An abstract contract `BaseUltraVerifier` containing most of the verifying logic. +- A main `UltraVerifier` contract that inherits from the Base and uses the Key contract. + +Remix will take care of the dependencies for us so we can simply deploy the UltraVerifier contract by selecting it and hitting "deploy": + +![Deploying UltraVerifier](@site/static/img/how-tos/solidity_verifier_5.png) + +A contract will show up in the "Deployed Contracts" section, where we can retrieve the Verification Key Hash. This is particularly useful for double-checking the deployer contract is the correct one. + +:::note + +Why "UltraVerifier"? + +To be precise, the Noir compiler (`nargo`) doesn't generate the verifier contract directly. It compiles the Noir code into an intermediate language (ACIR), which is then executed by the backend. So it is the backend that returns the verifier smart contract, not Noir. + +In this case, the Barretenberg Backend uses the UltraPlonk proving system, hence the "UltraVerifier" name. + +::: + +## Step 4 - Verifying + +To verify a proof using the Solidity verifier contract, we call the `verify` function in this extended contract: + +```solidity +function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool) +``` + +When using the default example in the [Hello Noir](../getting_started/hello_noir/index.md) guide, the easiest way to confirm that the verifier contract is doing its job is by calling the `verify` function via remix with the required parameters. For `_proof`, run `nargo prove` and use the string in `proof/.proof` (adding the hex `0x` prefix). We can also copy the public input from `Verifier.toml`, as it will be properly formatted as 32-byte strings: + +``` +0x...... , [0x0000.....02] +``` + +A programmatic example of how the `verify` function is called can be seen 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"); +``` + +:::info[Return Values] + +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. + +For example, if you have Noir program like this: + +```rust +fn main( + // Public inputs + pubkey_x: pub Field, + pubkey_y: pub Field, + // Private inputs + priv_key: Field, +) -> pub Field +``` + +the `verify` function will expect the public inputs array (second function parameter) to be of length 3, the two inputs and the return value. Like before, these values are populated in Verifier.toml after running `nargo prove`. + +Passing only two inputs will result in an error such as `PUBLIC_INPUT_COUNT_INVALID(3, 2)`. + +In this case, the inputs parameter to `verify` would be an array ordered as `[pubkey_x, pubkey_y, return]`. + +::: + +:::tip[Structs] + +You can pass structs to the verifier contract. They will be flattened so that the array of inputs is 1-dimensional array. + +For example, 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) { + //... +} +``` + +The order of these inputs would be flattened to: `[x, nested.t1.val1, nested.t1.val2, nested.is_true, y]` + +::: + +The other function you can call is our entrypoint `verify` function, as defined above. + +:::tip + +It's worth noticing that the `verify` function is actually a `view` function. A `view` function does not alter the blockchain state, so it doesn't need to be distributed (i.e. it will run only on the executing node), and therefore doesn't cost any gas. + +This can be particularly useful in some situations. If Alice generated a proof and wants Bob to verify its correctness, Bob doesn't need to run Nargo, NoirJS, or any Noir specific infrastructure. He can simply make a call to the blockchain with the proof and verify it is correct without paying any gas. + +It would be incorrect to say that a Noir proof verification costs any gas at all. However, most of the time the result of `verify` is used to modify state (for example, to update a balance, a game state, etc). In that case the whole network needs to execute it, which does incur gas costs (calldata and execution, but not storage). + +::: + +## A Note on EVM chains + +ZK-SNARK verification depends on some precompiled cryptographic primitives such as Elliptic Curve Pairings (if you like complex math, you can read about EC Pairings [here](https://medium.com/@VitalikButerin/exploring-elliptic-curve-pairings-c73c1864e627)). Not all EVM chains support EC Pairings, notably some of the ZK-EVMs. This means that you won't be able to use the verifier contract in all of them. + +For example, `Polygon zkEVM` does not currently support these precompiles, so proof verification via Solidity verifier contracts won't work. Here's a quick list of EVM chains that have been tested and are known to work: + +- Optimism +- Arbitrum +- Polygon PoS +- Scroll +- Celo +- zkSync + +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. + +## What's next + +Now that you know how to call a Noir Solidity Verifier on a smart contract using Remix, you should be comfortable with using it with some programmatic frameworks, such as [hardhat](https://github.com/noir-lang/noir-starter/tree/main/vite-hardhat) and [foundry](https://github.com/noir-lang/noir-starter/tree/main/with-foundry). + +You can find other tools, examples, boilerplates and libraries in the [awesome-noir](https://github.com/noir-lang/awesome-noir) repository. + +You should also be ready to write and deploy your first NoirJS app and start generating proofs on websites, phones, and NodeJS environments! Head on to the [NoirJS tutorial](../tutorials/noirjs_app.md) to learn how to do that. diff --git a/docs/versioned_docs/version-v0.29.0/how_to/merkle-proof.mdx b/docs/versioned_docs/version-v0.29.0/how_to/merkle-proof.mdx new file mode 100644 index 00000000000..16c425bed76 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/how_to/merkle-proof.mdx @@ -0,0 +1,49 @@ +--- +title: Prove Merkle Tree Membership +description: + Learn how to use merkle membership proof in Noir to prove that a given leaf is a member of a + merkle tree with a specified root, at a given index. +keywords: + [merkle proof, merkle membership proof, Noir, rust, hash function, Pedersen, sha256, merkle tree] +sidebar_position: 4 +--- + +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.as_slice()); + 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.as_slice()); +``` + +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.29.0/how_to/using-devcontainers.mdx b/docs/versioned_docs/version-v0.29.0/how_to/using-devcontainers.mdx new file mode 100644 index 00000000000..727ec6ca667 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/how_to/using-devcontainers.mdx @@ -0,0 +1,110 @@ +--- +title: Developer Containers and Codespaces +description: "Learn how to set up a devcontainer in your GitHub repository for a seamless coding experience with Codespaces. Follow our easy 8-step guide to create your own Noir environment without installing Nargo locally." +keywords: ["Devcontainer", "Codespaces", "GitHub", "Noir Environment", "Docker Image", "Development Environment", "Remote Coding", "GitHub Codespaces", "Noir Programming", "Nargo", "VSCode Extensions", "Noirup"] +sidebar_position: 1 +--- + +Adding a developer container configuration file to your Noir project is one of the easiest way to unlock coding in browser. + +## What's a devcontainer after all? + +A [Developer Container](https://containers.dev/) (devcontainer for short) is a Docker image that comes preloaded with tools, extensions, and other tools you need to quickly get started or continue a project, without having to install Nargo locally. Think of it as a development environment in a box. + +There are many advantages to this: + +- It's platform and architecture agnostic +- You don't need to have an IDE installed, or Nargo, or use a terminal at all +- It's safer for using on a public machine or public network + +One of the best ways of using devcontainers is... not using your machine at all, for maximum control, performance, and ease of use. +Enter Codespaces. + +## Codespaces + +If a devcontainer is just a Docker image, then what stops you from provisioning a `p3dn.24xlarge` AWS EC2 instance with 92 vCPUs and 768 GiB RAM and using it to prove your 10-gate SNARK proof? + +Nothing! Except perhaps the 30-40$ per hour it will cost you. + +The problem is that provisioning takes time, and I bet you don't want to see the AWS console every time you want to code something real quick. + +Fortunately, there's an easy and free way to get a decent remote machine ready and loaded in less than 2 minutes: Codespaces. [Codespaces is a Github feature](https://github.com/features/codespaces) that allows you to code in a remote machine by using devcontainers, and it's pretty cool: + +- You can start coding Noir in less than a minute +- It uses the resources of a remote machine, so you can code on your grandma's phone if needed be +- It makes it easy to share work with your frens +- It's fully reusable, you can stop and restart whenever you need to + +:::info + +Don't take out your wallet just yet. Free GitHub accounts get about [15-60 hours of coding](https://github.com/features/codespaces) for free per month, depending on the size of your provisioned machine. + +::: + +## Tell me it's _actually_ easy + +It is! + +Github comes with a default codespace and you can use it to code your own devcontainer. That's exactly what we will be doing in this guide. + + + +8 simple steps: + +#### 1. Create a new repository on GitHub. + +#### 2. Click "Start coding with Codespaces". This will use the default image. + +#### 3. Create a folder called `.devcontainer` in the root of your repository. + +#### 4. Create a Dockerfile in that folder, and paste the following code: + +```docker +FROM --platform=linux/amd64 node:lts-bookworm-slim +SHELL ["/bin/bash", "-c"] +RUN apt update && apt install -y curl bash git tar gzip libc++-dev +RUN curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash +ENV PATH="/root/.nargo/bin:$PATH" +RUN noirup +ENTRYPOINT ["nargo"] +``` +#### 5. Create a file called `devcontainer.json` in the same folder, and paste the following code: + +```json +{ + "name": "Noir on Codespaces", + "build": { + "context": ".", + "dockerfile": "Dockerfile" + }, + "customizations": { + "vscode": { + "extensions": ["noir-lang.vscode-noir"] + } + } +} +``` +#### 6. Commit and push your changes + +This will pull the new image and build it, so it could take a minute or so + +#### 8. Done! +Just wait for the build to finish, and there's your easy Noir environment. + + +Refer to [noir-starter](https://github.com/noir-lang/noir-starter/) as an example of how devcontainers can be used together with codespaces. + + + +## How do I use it? + +Using the codespace is obviously much easier than setting it up. +Just navigate to your repository and click "Code" -> "Open with Codespaces". It should take a few seconds to load, and you're ready to go. + +:::info + +If you really like the experience, you can add a badge to your readme, links to existing codespaces, and more. +Check out the [official docs](https://docs.github.com/en/codespaces/setting-up-your-project-for-codespaces/setting-up-your-repository/facilitating-quick-creation-and-resumption-of-codespaces) for more info. diff --git a/docs/versioned_docs/version-v0.29.0/index.mdx b/docs/versioned_docs/version-v0.29.0/index.mdx new file mode 100644 index 00000000000..75086ddcdde --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/index.mdx @@ -0,0 +1,67 @@ +--- +title: Noir Lang +hide_title: true +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] +sidebar_position: 0 +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +Noir Logo + +Noir is a Domain-Specific Language for SNARK proving systems developed by [Aztec Labs](https://aztec.network/). It allows you to generate complex Zero-Knowledge Programs (ZKP) by using simple and flexible syntax, requiring no previous knowledge on the underlying mathematics or cryptography. + +ZK programs are programs that can generate short proofs of a certain statement without revealing some details about it. You can read more about ZKPs [here](https://dev.to/spalladino/a-beginners-intro-to-coding-zero-knowledge-proofs-c56). + +## What's new about Noir? + +Noir works differently from most ZK languages by taking a two-pronged path. First, it compiles the program to an adaptable intermediate language known as ACIR. From there, depending on a given project's needs, ACIR can be further compiled into an arithmetic circuit for integration with the proving backend. + +:::info + +Noir is backend agnostic, which means it makes no assumptions on which proving backend powers the ZK proof. Being the language that powers [Aztec Contracts](https://docs.aztec.network/developers/contracts/main), it defaults to Aztec's Barretenberg proving backend. + +However, the ACIR output can be transformed to be compatible with other PLONK-based backends, or into a [rank-1 constraint system](https://www.rareskills.io/post/rank-1-constraint-system) suitable for backends such as Arkwork's Marlin. + +::: + +## Who is Noir for? + +Noir can be used both in complex cloud-based backends and in user's smartphones, requiring no knowledge on the underlying math or cryptography. From authorization systems that keep a password in the user's device, to complex on-chain verification of recursive proofs, Noir is designed to abstract away complexity without any significant overhead. Here are some examples of situations where Noir can be used: + + + + Noir Logo + + Aztec Contracts leverage Noir to allow for the storage and execution of private information. Writing an Aztec Contract is as easy as writing Noir, and Aztec developers can easily interact with the network storage and execution through the [Aztec.nr](https://docs.aztec.network/developers/contracts/main) library. + + + Soliditry Verifier Example + Noir can auto-generate Solidity verifier contracts that verify Noir proofs. This allows for non-interactive verification of proofs containing private information in an immutable system. This feature powers a multitude of use-case scenarios, from P2P chess tournaments, to [Aztec Layer-2 Blockchain](https://docs.aztec.network/) + + + Aztec Labs developed NoirJS, an easy interface to generate and verify Noir proofs in a Javascript environment. This allows for Noir to be used in webpages, mobile apps, games, and any other environment supporting JS execution in a standalone manner. + + + + +## Libraries + +Noir is meant to be easy to extend by simply importing Noir libraries just like in Rust. +The [awesome-noir repo](https://github.com/noir-lang/awesome-noir#libraries) is a collection of libraries developed by the Noir community. +Writing a new library is easy and makes code be composable and easy to reuse. See the section on [dependencies](noir/modules_packages_crates/dependencies.md) for more information. diff --git a/docs/versioned_docs/version-v0.29.0/migration_notes.md b/docs/versioned_docs/version-v0.29.0/migration_notes.md new file mode 100644 index 00000000000..6bd740024e5 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/migration_notes.md @@ -0,0 +1,105 @@ +--- +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. + +### `backend encountered an error: libc++.so.1` + +Depending on your OS, you may encounter the following error when running `nargo prove` for the first time: + +```text +The backend encountered an error: "/home/codespace/.nargo/backends/acvm-backend-barretenberg/backend_binary: error while loading shared libraries: libc++.so.1: cannot open shared object file: No such file or directory\n" +``` + +Install the `libc++-dev` library with: + +```bash +sudo apt install libc++-dev +``` + +## ≥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](noir/concepts/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 your 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 file is running [this bash script](https://github.com/noir-lang/barretenberg-js-binary/blob/master/run-bb-js.sh), where we need to gzip it as the Nargo currently expect the backend to be zipped up. + +Then run: + +``` +DESIRED_BINARY_VERSION=0.8.1 nargo info +``` + +This overrides the bb native binary with a bb.js node application instead, which should be compatible with most if not all hardware. This does come with the drawback of being generally slower than native binary. + +0.8.1 indicates bb.js version 0.8.1, so if you change that it will update to a different version or the default version in the script if none was supplied. diff --git a/docs/versioned_docs/version-v0.29.0/noir/concepts/_category_.json b/docs/versioned_docs/version-v0.29.0/noir/concepts/_category_.json new file mode 100644 index 00000000000..7da08f8a8c5 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/noir/concepts/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Concepts", + "position": 0, + "collapsible": true, + "collapsed": true +} \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.29.0/noir/concepts/assert.md b/docs/versioned_docs/version-v0.29.0/noir/concepts/assert.md new file mode 100644 index 00000000000..bcff613a695 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/noir/concepts/assert.md @@ -0,0 +1,45 @@ +--- +title: Assert Function +description: + Learn about the assert function in Noir, which can be used to explicitly constrain the predicate or + comparison expression that follows to be true, and what happens if the expression is false at + runtime. +keywords: [Noir programming language, assert statement, predicate expression, comparison expression] +sidebar_position: 4 +--- + +Noir includes a special `assert` function which will explicitly constrain the predicate/comparison +expression that follows to be true. If this expression is false at runtime, the program will fail to +be proven. Example: + +```rust +fn main(x : Field, y : Field) { + assert(x == y); +} +``` + +> 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`. + +You can optionally provide a message to be logged when the assertion fails: + +```rust +assert(x == y, "x and y are not equal"); +``` + +Aside string literals, the optional message can be a format string or any other type supported as input for Noir's [print](../standard_library/logging.md) functions. This feature lets you incorporate runtime variables into your failed assertion logs: + +```rust +assert(x == y, f"Expected x == y, but got {x} == {y}"); +``` + +Using a variable as an assertion message directly: + +```rust +struct myStruct { + myField: Field +} + +let s = myStruct { myField: y }; +assert(s.myField == x, s); +``` + diff --git a/docs/versioned_docs/version-v0.29.0/noir/concepts/comments.md b/docs/versioned_docs/version-v0.29.0/noir/concepts/comments.md new file mode 100644 index 00000000000..b51a85f5c94 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/noir/concepts/comments.md @@ -0,0 +1,33 @@ +--- +title: Comments +description: + Learn how to write comments in Noir programming language. A comment is a line of code that is + ignored by the compiler, but it can be read by programmers. Single-line and multi-line comments + are supported in Noir. +keywords: [Noir programming language, comments, single-line comments, multi-line comments] +sidebar_position: 10 +--- + +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.29.0/noir/concepts/control_flow.md b/docs/versioned_docs/version-v0.29.0/noir/concepts/control_flow.md new file mode 100644 index 00000000000..045d3c3a5f5 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/noir/concepts/control_flow.md @@ -0,0 +1,77 @@ +--- +title: Control Flow +description: + Learn how to use loops and if expressions in the Noir programming language. Discover the syntax + and examples for for loops and if-else statements. +keywords: [Noir programming language, loops, for loop, if-else statements, Rust syntax] +sidebar_position: 2 +--- + +## 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); +``` + +## 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`. + +### Break and Continue + +In unconstrained code, `break` and `continue` are also allowed in `for` loops. These are only allowed +in unconstrained code since normal constrained code requires that Noir knows exactly how many iterations +a loop may have. `break` and `continue` can be used like so: + +```rust +for i in 0 .. 10 { + println("Iteration start") + + if i == 2 { + continue; + } + + if i == 5 { + break; + } + + println(i); +} +println("Loop end") +``` + +When used, `break` will end the current loop early and jump to the statement after the for loop. In the example +above, the `break` will stop the loop and jump to the `println("Loop end")`. + +`continue` will stop the current iteration of the loop, and jump to the start of the next iteration. In the example +above, `continue` will jump to `println("Iteration start")` when used. Note that the loop continues as normal after this. +The iteration variable `i` is still increased by one as normal when `continue` is used. + +`break` and `continue` cannot currently be used to jump out of more than a single loop at a time. diff --git a/docs/versioned_docs/version-v0.29.0/noir/concepts/data_bus.md b/docs/versioned_docs/version-v0.29.0/noir/concepts/data_bus.md new file mode 100644 index 00000000000..e54fc861257 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/noir/concepts/data_bus.md @@ -0,0 +1,21 @@ +--- +title: Data Bus +sidebar_position: 13 +--- +**Disclaimer** this feature is experimental, do not use it! + +The data bus is an optimization that the backend can use to make recursion more efficient. +In order to use it, you must define some inputs of the program entry points (usually the `main()` +function) with the `call_data` modifier, and the return values with the `return_data` modifier. +These modifiers are incompatible with `pub` and `mut` modifiers. + +## Example + +```rust +fn main(mut x: u32, y: call_data u32, z: call_data [u32;4] ) -> return_data u32 { + let a = z[x]; + a+y +} +``` + +As a result, both call_data and return_data will be treated as private inputs and encapsulated into a read-only array each, for the backend to process. diff --git a/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/_category_.json b/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/_category_.json new file mode 100644 index 00000000000..5d694210bbf --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 0, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/arrays.md b/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/arrays.md new file mode 100644 index 00000000000..efce3e95d32 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/arrays.md @@ -0,0 +1,251 @@ +--- +title: Arrays +description: + Dive into the Array data type in Noir. Grasp its methods, practical examples, and best practices for efficiently using Arrays in your Noir code. +keywords: + [ + noir, + array type, + methods, + examples, + indexing, + ] +sidebar_position: 4 +--- + +An array is one way of grouping together values into one compound type. Array types can be inferred +or explicitly specified via the syntax `[; ]`: + +```rust +fn main(x : Field, y : Field) { + let my_arr = [x, y]; + let your_arr: [Field; 2] = [x, y]; +} +``` + +Here, both `my_arr` and `your_arr` are instantiated as an array containing two `Field` elements. + +Array elements can be accessed using indexing: + +```rust +fn main() { + let a = [1, 2, 3, 4, 5]; + + let first = a[0]; + let second = a[1]; +} +``` + +All elements in an array must be of the same type (i.e. homogeneous). That is, an array cannot group +a `Field` value and a `u8` value together for example. + +You can write mutable arrays, like: + +```rust +fn main() { + let mut arr = [1, 2, 3, 4, 5]; + assert(arr[0] == 1); + + arr[0] = 42; + assert(arr[0] == 42); +} +``` + +You can instantiate a new array of a fixed size with the same value repeated for each element. The following example instantiates an array of length 32 where each element is of type Field and has the value 0. + +```rust +let array: [Field; 32] = [0; 32]; +``` + +Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices), you can just call `as_slice` on your array: + +```rust +let array: [Field; 32] = [0; 32]; +let sl = array.as_slice() +``` + +You can define multidimensional arrays: + +```rust +let array : [[Field; 2]; 2]; +let element = array[0][0]; +``` +However, multidimensional slices are not supported. For example, the following code will error at compile time: +```rust +let slice : [[Field]] = &[]; +``` + +## 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. +Each of these functions are located within the generic impl `impl [T; N] {`. +So anywhere `self` appears, it refers to the variable `self: [T; N]`. + +### len + +Returns the length of an array + +```rust +fn len(self) -> 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(self) -> [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(self, 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(self, 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(self, 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(self, 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(self, 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(self, 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.29.0/noir/concepts/data_types/booleans.md b/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/booleans.md new file mode 100644 index 00000000000..69826fcd724 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/booleans.md @@ -0,0 +1,31 @@ +--- +title: Booleans +description: + Delve into the Boolean data type in Noir. Understand its methods, practical examples, and best practices for using Booleans in your Noir programs. +keywords: + [ + noir, + boolean type, + methods, + examples, + logical operations, + ] +sidebar_position: 2 +--- + + +The `bool` type in Noir has two possible values: `true` and `false`: + +```rust +fn main() { + let t = true; + let f: bool = false; +} +``` + +> **Note:** When returning a boolean value, it will show up as a value of 1 for `true` and 0 for +> `false` in _Verifier.toml_. + +The boolean type is most commonly used in conditionals like `if` expressions and `assert` +statements. More about conditionals is covered in the [Control Flow](../control_flow) and +[Assert Function](../assert) sections. diff --git a/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/fields.md b/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/fields.md new file mode 100644 index 00000000000..a10a4810788 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/fields.md @@ -0,0 +1,192 @@ +--- +title: Fields +description: + Dive deep into the Field data type in Noir. Understand its methods, practical examples, and best practices to effectively use Fields in your Noir programs. +keywords: + [ + noir, + field type, + methods, + examples, + best practices, + ] +sidebar_position: 0 +--- + +The field type corresponds to the native field type of the proving backend. + +The size of a Noir field depends on the elliptic curve's finite field for the proving backend +adopted. For example, a field would be a 254-bit integer when paired with the default backend that +spans the Grumpkin curve. + +Fields support integer arithmetic and are often used as the default numeric type in Noir: + +```rust +fn main(x : Field, y : Field) { + let z = x + y; +} +``` + +`x`, `y` and `z` are all private fields in this example. Using the `let` keyword we defined a new +private value `z` constrained to be equal to `x + y`. + +If proving efficiency is of priority, fields should be used as a default for solving problems. +Smaller integer types (e.g. `u64`) incur extra range constraints. + +## Methods + +After declaring a Field, you can use these common methods on it: + +### to_le_bits + +Transforms the field into an array of bits, Little Endian. + +```rust +fn to_le_bits(_x : Field, _bit_size: u32) -> [u1] +``` + +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] +``` + +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); +} +``` + +### assert_max_bit_size + +Adds a constraint to specify that the field can be represented with `bit_size` number of bits + +```rust +fn assert_max_bit_size(self, bit_size: u32) +``` + +example: + +```rust +fn main() { + let field = 2 + field.assert_max_bit_size(32); +} +``` + +### 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 +``` + + +### lt + +Returns true if the field is less than the other field + +```rust +pub fn lt(self, another: Field) -> bool +``` diff --git a/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/function_types.md b/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/function_types.md new file mode 100644 index 00000000000..f6121af17e2 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/function_types.md @@ -0,0 +1,26 @@ +--- +title: Function types +sidebar_position: 10 +--- + +Noir supports higher-order functions. The syntax for a function type is as follows: + +```rust +fn(arg1_type, arg2_type, ...) -> return_type +``` + +Example: + +```rust +fn assert_returns_100(f: fn() -> Field) { // f takes no args and returns a Field + assert(f() == 100); +} + +fn main() { + assert_returns_100(|| 100); // ok + assert_returns_100(|| 150); // fails +} +``` + +A function type also has an optional capture environment - this is necessary to support closures. +See [Lambdas](../lambdas.md) for more details. diff --git a/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/index.md b/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/index.md new file mode 100644 index 00000000000..357813c147a --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/index.md @@ -0,0 +1,110 @@ +--- +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](../generics.md): + +```rust +type Id = Size; + +fn main() { + let id: Id = 1; + let zero: u32 = 0; + assert(zero + 1 == id); +} +``` + +Type aliases can even refer to other aliases. An error will be issued if they form a cycle: + +```rust +// Ok! +type A = B; +type B = Field; + +type Bad1 = Bad2; + +// error: Dependency cycle found +type Bad2 = Bad1; +// ^^^^^^^^^^^ 'Bad2' recursively depends on itself: Bad2 -> Bad1 -> Bad2 +``` + +### BigInt + +You can achieve BigInt functionality using the [Noir BigInt](https://github.com/shuklaayush/noir-bigint) library. diff --git a/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/integers.md b/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/integers.md new file mode 100644 index 00000000000..1c6b375db49 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/integers.md @@ -0,0 +1,155 @@ +--- +title: Integers +description: Explore the Integer data type in Noir. Learn about its methods, see real-world examples, and grasp how to efficiently use Integers in your Noir code. +keywords: [noir, integer types, methods, examples, arithmetic] +sidebar_position: 1 +--- + +An integer type is a range constrained field type. The Noir frontend supports both unsigned and signed integer types. The allowed sizes are 1, 8, 32 and 64 bits. + +:::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\\$). + +## 128 bits Unsigned Integers + +The built-in structure `U128` allows you to use 128-bit unsigned integers almost like a native integer type. However, there are some differences to keep in mind: +- You cannot cast between a native integer and `U128` +- There is a higher performance cost when using `U128`, compared to a native type. + +Conversion between unsigned integer types and U128 are done through the use of `from_integer` and `to_integer` functions. `from_integer` also accepts the `Field` type as input. + +```rust +fn main() { + let x = U128::from_integer(23); + let y = U128::from_hex("0x7"); + let z = x + y; + assert(z.to_integer() == 30); +} +``` + +`U128` is implemented with two 64 bits limbs, representing the low and high bits, which explains the performance cost. You should expect `U128` to be twice more costly for addition and four times more costly for multiplication. +You can construct a U128 from its limbs: +```rust +fn main(x: u64, y: u64) { + let x = U128::from_u64s_be(x,y); + assert(z.hi == x as Field); + assert(z.lo == y as Field); +} +``` + +Note that the limbs are stored as Field elements in order to avoid unnecessary conversions. +Apart from this, most operations will work as usual: + +```rust +fn main(x: U128, y: U128) { + // multiplication + let c = x * y; + // addition and subtraction + let c = c - x + y; + // division + let c = x / y; + // bit operation; + let c = x & y | y; + // bit shift + let c = x << y; + // comparisons; + let c = x < y; + let c = x == y; +} +``` + +## 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.29.0/noir/concepts/data_types/references.md b/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/references.md new file mode 100644 index 00000000000..a5293d11cfb --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/references.md @@ -0,0 +1,23 @@ +--- +title: References +sidebar_position: 9 +--- + +Noir supports first-class references. References are a bit like pointers: they point to a specific address that can be followed to access the data stored at that address. You can use Rust-like syntax to use pointers in Noir: the `&` operator references the variable, the `*` operator dereferences it. + +Example: + +```rust +fn main() { + let mut x = 2; + + // you can reference x as &mut and pass it to multiplyBy2 + multiplyBy2(&mut x); +} + +// you can access &mut here +fn multiplyBy2(x: &mut Field) { + // and dereference it with * + *x = *x * 2; +} +``` diff --git a/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/slices.mdx b/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/slices.mdx new file mode 100644 index 00000000000..4eccc677b80 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/slices.mdx @@ -0,0 +1,195 @@ +--- +title: Slices +description: Explore the Slice data type in Noir. Understand its methods, see real-world examples, and learn how to effectively use Slices in your Noir programs. +keywords: [noir, slice type, methods, examples, subarrays] +sidebar_position: 5 +--- + +import Experimental from '@site/src/components/Notes/_experimental.mdx'; + + + +A slice is a dynamically-sized view into a sequence of elements. They can be resized at runtime, but because they don't own the data, they cannot be returned from a circuit. You can treat slices as arrays without a constrained size. + +```rust +use dep::std::slice; + +fn main() -> pub Field { + let mut slice: [Field] = &[0; 2]; + + let mut new_slice = slice.push_back(6); + new_slice.len() +} +``` + +To write a slice literal, use a preceeding ampersand as in: `&[0; 2]` or +`&[1, 2, 3]`. + +It is important to note that slices are not references to arrays. In Noir, +`&[..]` is more similar to an immutable, growable vector. + +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); +``` + +### len + +Returns the length of a slice + +```rust +fn len(self) -> Field +``` + +Example: + +```rust +fn main() { + let slice = &[42, 42]; + assert(slice.len() == 2); +} +``` + +### as_array + +Converts this slice into an array. + +Make sure to specify the size of the resulting array. +Panics if the resulting array length is different than the slice's length. + +```rust +fn as_array(self) -> [T; N] +``` + +Example: + +```rust +fn main() { + let slice = &[5, 6]; + + // Always specify the length of the resulting array! + let array: [Field; 2] = slice.as_array(); + + assert(array[0] == slice[0]); + assert(array[1] == slice[1]); +} +``` diff --git a/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/strings.md b/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/strings.md new file mode 100644 index 00000000000..311dfd64416 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/strings.md @@ -0,0 +1,80 @@ +--- +title: Strings +description: + Discover the String data type in Noir. Learn about its methods, see real-world examples, and understand how to effectively manipulate and use Strings in Noir. +keywords: + [ + noir, + string type, + methods, + examples, + concatenation, + ] +sidebar_position: 3 +--- + + +The string type is a fixed length value defined with `str`. + +You can use strings in `assert()` functions or print them with +`println()`. See more about [Logging](../../standard_library/logging). + +```rust +use dep::std; + +fn main(message : pub str<11>, hex_as_string : str<4>) { + println(message); + assert(message == "hello world"); + assert(hex_as_string == "0x41"); +} +``` + +You can convert a `str` to a byte array by calling `as_bytes()` +or a vector by calling `as_bytes_vec()`. + +```rust +fn main() { + let message = "hello world"; + let message_bytes = message.as_bytes(); + let mut message_vec = message.as_bytes_vec(); + assert(message_bytes.len() == 11); + assert(message_bytes[0] == 104); + assert(message_bytes[0] == message_vec.get(0)); +} +``` + +## Escape characters + +You can use escape characters for your strings: + +| Escape Sequence | Description | +|-----------------|-----------------| +| `\r` | Carriage Return | +| `\n` | Newline | +| `\t` | Tab | +| `\0` | Null Character | +| `\"` | Double Quote | +| `\\` | Backslash | + +Example: + +```rust +let s = "Hello \"world" // prints "Hello "world" +let s = "hey \tyou"; // prints "hey you" +``` + +## Raw strings + +A raw string begins with the letter `r` and is optionally delimited by a number of hashes `#`. + +Escape characters are *not* processed within raw strings. All contents are interpreted literally. + +Example: + +```rust +let s = r"Hello world"; +let s = r#"Simon says "hello world""#; + +// Any number of hashes may be used (>= 1) as long as the string also terminates with the same number of hashes +let s = r#####"One "#, Two "##, Three "###, Four "####, Five will end the string."#####; +``` diff --git a/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/structs.md b/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/structs.md new file mode 100644 index 00000000000..dbf68c99813 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/structs.md @@ -0,0 +1,70 @@ +--- +title: Structs +description: + Explore the Struct data type in Noir. Learn about its methods, see real-world examples, and grasp how to effectively define and use Structs in your Noir programs. +keywords: + [ + noir, + struct type, + methods, + examples, + data structures, + ] +sidebar_position: 8 +--- + +A struct also allows for grouping multiple values of different types. Unlike tuples, we can also +name each field. + +> **Note:** The usage of _field_ here refers to each element of the struct and is unrelated to the +> field type of Noir. + +Defining a struct requires giving it a name and listing each field within as `: ` pairs: + +```rust +struct Animal { + hands: Field, + legs: Field, + eyes: u8, +} +``` + +An instance of a struct can then be created with actual values in `: ` pairs in any +order. Struct fields are accessible using their given names: + +```rust +fn main() { + let legs = 4; + + let dog = Animal { + eyes: 2, + hands: 0, + legs, + }; + + let zero = dog.hands; +} +``` + +Structs can also be destructured in a pattern, binding each field to a new variable: + +```rust +fn main() { + let Animal { hands, legs: feet, eyes } = get_octopus(); + + let ten = hands + feet + eyes as u8; +} + +fn get_octopus() -> Animal { + let octopus = Animal { + hands: 0, + legs: 8, + eyes: 2, + }; + + octopus +} +``` + +The new variables can be bound with names different from the original struct field names, as +showcased in the `legs --> feet` binding in the example above. diff --git a/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/tuples.md b/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/tuples.md new file mode 100644 index 00000000000..2ec5c9c4113 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/tuples.md @@ -0,0 +1,48 @@ +--- +title: Tuples +description: + Dive into the Tuple data type in Noir. Understand its methods, practical examples, and best practices for efficiently using Tuples in your Noir code. +keywords: + [ + noir, + tuple type, + methods, + examples, + multi-value containers, + ] +sidebar_position: 7 +--- + +A tuple collects multiple values like an array, but with the added ability to collect values of +different types: + +```rust +fn main() { + let tup: (u8, u64, Field) = (255, 500, 1000); +} +``` + +One way to access tuple elements is via destructuring using pattern matching: + +```rust +fn main() { + let tup = (1, 2); + + let (one, two) = tup; + + let three = one + two; +} +``` + +Another way to access tuple elements is via direct member access, using a period (`.`) followed by +the index of the element we want to access. Index `0` corresponds to the first tuple element, `1` to +the second and so on: + +```rust +fn main() { + let tup = (5, 6, 7, 8); + + let five = tup.0; + let eight = tup.3; +} +``` diff --git a/docs/versioned_docs/version-v0.29.0/noir/concepts/functions.md b/docs/versioned_docs/version-v0.29.0/noir/concepts/functions.md new file mode 100644 index 00000000000..f656cdfd97a --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/noir/concepts/functions.md @@ -0,0 +1,226 @@ +--- +title: Functions +description: + Learn how to declare functions and methods in Noir, a programming language with Rust semantics. + This guide covers parameter declaration, return types, call expressions, and more. +keywords: [Noir, Rust, functions, methods, parameter declaration, return types, call expressions] +sidebar_position: 1 +--- + +Functions in Noir follow the same semantics of Rust, though Noir does not support early returns. + +To declare a function the `fn` keyword is used. + +```rust +fn foo() {} +``` + +By default, functions are visible only within the package they are defined. To make them visible outside of that package (for example, as part of a [library](../modules_packages_crates/crates_and_packages.md#libraries)), you should mark them as `pub`: + +```rust +pub fn foo() {} +``` + +You can also restrict the visibility of the function to only the crate it was defined in, by specifying `pub(crate)`: + +```rust +pub(crate) fn foo() {} //foo can only be called within its crate +``` + +All parameters in a function must have a type and all types are known at compile time. The parameter +is pre-pended with a colon and the parameter type. Multiple parameters are separated using a comma. + +```rust +fn foo(x : Field, y : Field){} +``` + +The return type of a function can be stated by using the `->` arrow notation. The function below +states that the foo function must return a `Field`. If the function returns no value, then the arrow +is omitted. + +```rust +fn foo(x : Field, y : Field) -> Field { + x + y +} +``` + +Note that a `return` keyword is unneeded in this case - the last expression in a function's body is +returned. + +## Main function + +If you're writing a binary, the `main` function is the starting point of your program. You can pass all types of expressions to it, as long as they have a fixed size at compile time: + +```rust +fn main(x : Field) // this is fine: passing a Field +fn main(x : [Field; 2]) // this is also fine: passing a Field with known size at compile-time +fn main(x : (Field, bool)) // 👌: passing a (Field, bool) tuple means size 2 +fn main(x : str<5>) // this is fine, as long as you pass a string of size 5 + +fn main(x : Vec) // can't compile, has variable size +fn main(x : [Field]) // can't compile, has variable size +fn main(....// i think you got it by now +``` + +Keep in mind [tests](../../tooling/testing.md) don't differentiate between `main` and any other function. The following snippet passes tests, but won't compile or prove: + +```rust +fn main(x : [Field]) { + assert(x[0] == 1); +} + +#[test] +fn test_one() { + main(&[1, 2]); +} +``` + +```bash +$ nargo test +[testing] Running 1 test functions +[testing] Testing test_one... ok +[testing] All tests passed + +$ nargo check +The application panicked (crashed). +Message: Cannot have variable sized arrays as a parameter to main +``` + +## Call Expressions + +Calling a function in Noir is executed by using the function name and passing in the necessary +arguments. + +Below we show how to call the `foo` function from the `main` function using a call expression: + +```rust +fn main(x : Field, y : Field) { + let z = foo(x); +} + +fn foo(x : Field) -> Field { + x + x +} +``` + +## Methods + +You can define methods in Noir on any struct type in scope. + +```rust +struct MyStruct { + foo: Field, + bar: Field, +} + +impl MyStruct { + fn new(foo: Field) -> MyStruct { + MyStruct { + foo, + bar: 2, + } + } + + fn sum(self) -> Field { + self.foo + self.bar + } +} + +fn main() { + let s = MyStruct::new(40); + assert(s.sum() == 42); +} +``` + +Methods are just syntactic sugar for functions, so if we wanted to we could also call `sum` as +follows: + +```rust +assert(MyStruct::sum(s) == 42); +``` + +It is also possible to specialize which method is chosen depending on the [generic](./generics.md) type that is used. In this example, the `foo` function returns different values depending on its type: + +```rust +struct Foo {} + +impl Foo { + fn foo(self) -> Field { 1 } +} + +impl Foo { + fn foo(self) -> Field { 2 } +} + +fn main() { + let f1: Foo = Foo{}; + let f2: Foo = Foo{}; + assert(f1.foo() + f2.foo() == 3); +} +``` + +Also note that impls with the same method name defined in them cannot overlap. For example, if we already have `foo` defined for `Foo` and `Foo` like we do above, we cannot also define `foo` in an `impl Foo` since it would be ambiguous which version of `foo` to choose. + +```rust +// Including this impl in the same project as the above snippet would +// cause an overlapping impls error +impl Foo { + fn foo(self) -> Field { 3 } +} +``` + +## Lambdas + +Lambdas are anonymous functions. They follow the syntax of Rust - `|arg1, arg2, ..., argN| return_expression`. + +```rust +let add_50 = |val| val + 50; +assert(add_50(100) == 150); +``` + +See [Lambdas](./lambdas.md) for more details. + +## Attributes + +Attributes are metadata that can be applied to a function, using the following syntax: `#[attribute(value)]`. + +Supported attributes include: + +- **builtin**: the function is implemented by the compiler, for efficiency purposes. +- **deprecated**: mark the function as _deprecated_. Calling the function will generate a warning: `warning: use of deprecated function` +- **field**: Used to enable conditional compilation of code depending on the field size. See below for more details +- **oracle**: mark the function as _oracle_; meaning it is an external unconstrained function, implemented in noir_js. See [Unconstrained](./unconstrained.md) and [NoirJS](../../reference/NoirJS/noir_js/index.md) for more details. +- **test**: mark the function as unit tests. See [Tests](../../tooling/testing.md) for more details + +### Field Attribute + +The field attribute defines which field the function is compatible for. The function is conditionally compiled, under the condition that the field attribute matches the Noir native field. +The field can be defined implicitly, by using the name of the elliptic curve usually associated to it - for instance bn254, bls12_381 - or explicitly by using the field (prime) order, in decimal or hexadecimal form. +As a result, it is possible to define multiple versions of a function with each version specialized for a different field attribute. This can be useful when a function requires different parameters depending on the underlying elliptic curve. + +Example: we define the function `foo()` three times below. Once for the default Noir bn254 curve, once for the field $\mathbb F_{23}$, which will normally never be used by Noir, and once again for the bls12_381 curve. + +```rust +#[field(bn254)] +fn foo() -> u32 { + 1 +} + +#[field(23)] +fn foo() -> u32 { + 2 +} + +// This commented code would not compile as foo would be defined twice because it is the same field as bn254 +// #[field(21888242871839275222246405745257275088548364400416034343698204186575808495617)] +// fn foo() -> u32 { +// 2 +// } + +#[field(bls12_381)] +fn foo() -> u32 { + 3 +} +``` + +If the field name is not known to Noir, it will discard the function. Field names are case insensitive. diff --git a/docs/versioned_docs/version-v0.29.0/noir/concepts/generics.md b/docs/versioned_docs/version-v0.29.0/noir/concepts/generics.md new file mode 100644 index 00000000000..ddd42bf1f9b --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/noir/concepts/generics.md @@ -0,0 +1,106 @@ +--- +title: Generics +description: Learn how to use Generics in Noir +keywords: [Noir, Rust, generics, functions, structs] +sidebar_position: 7 +--- + +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 print(self) { + for _i in 0 .. self.count { + println(self.value); + } + } +} + +fn main() { + let repeated = RepeatedValue { value: "Hello!", count: 2 }; + 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 + +Since a generic type `T` can represent any type, how can we call functions on the underlying type? +In other words, how can we go from "any type `T`" to "any type `T` that has certain methods available?" + +This is what [traits](../concepts/traits) are for in Noir. Here's an example of a function generic over +any type `T` that implements the `Eq` trait for equality: + +```rust +fn first_element_is_equal(array1: [T; N], array2: [T; N]) -> bool + where T: Eq +{ + if (array1.len() == 0) | (array2.len() == 0) { + true + } else { + array1[0] == array2[0] + } +} + +fn main() { + assert(first_element_is_equal([1, 2, 3], [1, 5, 6])); + + // We can use first_element_is_equal for arrays of any type + // as long as we have an Eq impl for the types we pass in + let array = [MyStruct::new(), MyStruct::new()]; + assert(array_eq(array, array, MyStruct::eq)); +} + +impl Eq for MyStruct { + fn eq(self, other: MyStruct) -> bool { + self.foo == other.foo + } +} +``` + +You can find more details on traits and trait implementations on the [traits page](../concepts/traits). diff --git a/docs/versioned_docs/version-v0.29.0/noir/concepts/globals.md b/docs/versioned_docs/version-v0.29.0/noir/concepts/globals.md new file mode 100644 index 00000000000..063a3d89248 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/noir/concepts/globals.md @@ -0,0 +1,72 @@ +--- +title: Global Variables +description: + Learn about global variables in Noir. Discover how + to declare, modify, and use them in your programs. +keywords: [noir programming language, globals, global variables, constants] +sidebar_position: 8 +--- + +## Globals + + +Noir supports global variables. The global's type can be inferred by the compiler entirely: + +```rust +global N = 5; // Same as `global N: Field = 5` + +global TUPLE = (3, 2); + +fn main() { + assert(N == 5); + assert(N == TUPLE.0 + TUPLE.1); +} +``` + +:::info + +Globals can be defined as any expression, so long as they don't depend on themselves - otherwise there would be a dependency cycle! For example: + +```rust +global T = foo(T); // dependency error +``` + +::: + + +If they are initialized to a literal integer, globals can be used to specify an array's length: + +```rust +global N: Field = 2; + +fn main(y : [Field; N]) { + assert(y[0] == y[1]) +} +``` + +A global from another module can be imported or referenced externally like any other name: + +```rust +global N = 20; + +fn main() { + assert(my_submodule::N != N); +} + +mod my_submodule { + global N: Field = 10; +} +``` + +When a global is used, Noir replaces the name with its definition on each occurrence. +This means globals defined using function calls will repeat the call each time they're used: + +```rust +global RESULT = foo(); + +fn foo() -> [Field; 100] { ... } +``` + +This is usually fine since Noir will generally optimize any function call that does not +refer to a program input into a constant. It should be kept in mind however, if the called +function performs side-effects like `println`, as these will still occur on each use. diff --git a/docs/versioned_docs/version-v0.29.0/noir/concepts/lambdas.md b/docs/versioned_docs/version-v0.29.0/noir/concepts/lambdas.md new file mode 100644 index 00000000000..be3c7e0b5ca --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/noir/concepts/lambdas.md @@ -0,0 +1,81 @@ +--- +title: Lambdas +description: Learn how to use anonymous functions in Noir programming language. +keywords: [Noir programming language, lambda, closure, function, anonymous function] +sidebar_position: 9 +--- + +## 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.29.0/noir/concepts/mutability.md b/docs/versioned_docs/version-v0.29.0/noir/concepts/mutability.md new file mode 100644 index 00000000000..fdeef6a87c5 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/noir/concepts/mutability.md @@ -0,0 +1,121 @@ +--- +title: Mutability +description: + Learn about mutable variables in Noir. Discover how + to declare, modify, and use them in your programs. +keywords: [noir programming language, mutability in noir, mutable variables] +sidebar_position: 8 +--- + +Variables in noir can be declared mutable via the `mut` keyword. Mutable variables can be reassigned +to via an assignment expression. + +```rust +let x = 2; +x = 3; // error: x must be mutable to be assigned to + +let mut y = 3; +let y = 4; // OK +``` + +The `mut` modifier can also apply to patterns: + +```rust +let (a, mut b) = (1, 2); +a = 11; // error: a must be mutable to be assigned to +b = 12; // OK + +let mut (c, d) = (3, 4); +c = 13; // OK +d = 14; // OK + +// etc. +let MyStruct { x: mut y } = MyStruct { x: a }; +// y is now in scope +``` + +Note that mutability in noir is local and everything is passed by value, so if a called function +mutates its parameters then the parent function will keep the old value of the parameters. + +```rust +fn main() -> pub Field { + let x = 3; + helper(x); + x // x is still 3 +} + +fn helper(mut x: i32) { + x = 4; +} +``` + +## Non-local mutability + +Non-local mutability can be achieved through the mutable reference type `&mut T`: + +```rust +fn set_to_zero(x: &mut Field) { + *x = 0; +} + +fn main() { + let mut y = 42; + set_to_zero(&mut y); + assert(*y == 0); +} +``` + +When creating a mutable reference, the original variable being referred to (`y` in this +example) must also be mutable. Since mutable references are a reference type, they must +be explicitly dereferenced via `*` to retrieve the underlying value. Note that this yields +a copy of the value, so mutating this copy will not change the original value behind the +reference: + +```rust +fn main() { + let mut x = 1; + let x_ref = &mut x; + + let mut y = *x_ref; + let y_ref = &mut y; + + x = 2; + *x_ref = 3; + + y = 4; + *y_ref = 5; + + assert(x == 3); + assert(*x_ref == 3); + assert(y == 5); + assert(*y_ref == 5); +} +``` + +Note that types in Noir are actually deeply immutable so the copy that occurs when +dereferencing is only a conceptual copy - no additional constraints will occur. + +Mutable references can also be stored within structs. Note that there is also +no lifetime parameter on these unlike rust. This is because the allocated memory +always lasts the entire program - as if it were an array of one element. + +```rust +struct Foo { + x: &mut Field +} + +impl Foo { + fn incr(mut self) { + *self.x += 1; + } +} + +fn main() { + let foo = Foo { x: &mut 0 }; + foo.incr(); + assert(*foo.x == 1); +} +``` + +In general, you should avoid non-local & shared mutability unless it is needed. Sticking +to only local mutability will improve readability and potentially improve compiler optimizations as well. diff --git a/docs/versioned_docs/version-v0.29.0/noir/concepts/ops.md b/docs/versioned_docs/version-v0.29.0/noir/concepts/ops.md new file mode 100644 index 00000000000..c35c36c38a9 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/noir/concepts/ops.md @@ -0,0 +1,98 @@ +--- +title: Logical Operations +description: + Learn about the supported arithmetic and logical operations in the Noir programming language. + Discover how to perform operations on private input types, integers, and booleans. +keywords: + [ + Noir programming language, + supported operations, + arithmetic operations, + logical operations, + predicate operators, + bitwise operations, + short-circuiting, + backend, + ] +sidebar_position: 3 +--- + +# Operations + +## Table of Supported Operations + +| Operation | Description | Requirements | +| :-------- | :------------------------------------------------------------: | -------------------------------------: | +| + | Adds two private input types together | Types must be private input | +| - | Subtracts two private input types together | Types must be private input | +| \* | Multiplies two private input types together | Types must be private input | +| / | Divides two private input types together | Types must be private input | +| ^ | XOR two private input types together | Types must be integer | +| & | AND two private input types together | Types must be integer | +| \| | OR two private input types together | Types must be integer | +| \<\< | Left shift an integer by another integer amount | Types must be integer, shift must be u8 | +| >> | Right shift an integer by another integer amount | Types must be integer, shift must be u8 | +| ! | 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 identically 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.29.0/noir/concepts/oracles.md b/docs/versioned_docs/version-v0.29.0/noir/concepts/oracles.md new file mode 100644 index 00000000000..aa380b5f7b8 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/noir/concepts/oracles.md @@ -0,0 +1,31 @@ +--- +title: Oracles +description: Dive into how Noir supports Oracles via RPC calls, and learn how to declare an Oracle in Noir with our comprehensive guide. +keywords: + - Noir + - Oracles + - RPC Calls + - Unconstrained Functions + - Programming + - Blockchain +sidebar_position: 6 +--- + +:::note + +This is an experimental feature that is not fully documented. If you notice any outdated information or potential improvements to this page, pull request contributions are very welcome: https://github.com/noir-lang/noir + +::: + +Noir has support for Oracles via RPC calls. This means Noir will make an RPC call and use the return value for proof generation. + +Since Oracles are not resolved by Noir, they are [`unconstrained` functions](./unconstrained.md) + +You can declare an Oracle through the `#[oracle()]` flag. Example: + +```rust +#[oracle(get_number_sequence)] +unconstrained fn get_number_sequence(_size: Field) -> [Field] {} +``` + +The timeout for when using an external RPC oracle resolver can be set with the `NARGO_FOREIGN_CALL_TIMEOUT` environment variable. This timeout is in units of milliseconds. diff --git a/docs/versioned_docs/version-v0.29.0/noir/concepts/shadowing.md b/docs/versioned_docs/version-v0.29.0/noir/concepts/shadowing.md new file mode 100644 index 00000000000..5ce6130d201 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/noir/concepts/shadowing.md @@ -0,0 +1,44 @@ +--- +title: Shadowing +sidebar_position: 12 +--- + +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.29.0/noir/concepts/traits.md b/docs/versioned_docs/version-v0.29.0/noir/concepts/traits.md new file mode 100644 index 00000000000..ef1445a5907 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/noir/concepts/traits.md @@ -0,0 +1,389 @@ +--- +title: Traits +description: + Traits in Noir can be used to abstract out a common interface for functions across + several data types. +keywords: [noir programming language, traits, interfaces, generic, protocol] +sidebar_position: 14 +--- + +## Overview + +Traits in Noir are a useful abstraction similar to interfaces or protocols in other languages. Each trait defines +the interface of several methods contained within the trait. Types can then implement this trait by providing +implementations for these methods. For example in the program: + +```rust +struct Rectangle { + width: Field, + height: Field, +} + +impl Rectangle { + fn area(self) -> Field { + self.width * self.height + } +} + +fn log_area(r: Rectangle) { + println(r.area()); +} +``` + +We have a function `log_area` to log the area of a `Rectangle`. Now how should we change the program if we want this +function to work on `Triangle`s as well?: + +```rust +struct Triangle { + width: Field, + height: Field, +} + +impl Triangle { + fn area(self) -> Field { + self.width * self.height / 2 + } +} +``` + +Making `log_area` generic over all types `T` would be invalid since not all types have an `area` method. Instead, we can +introduce a new `Area` trait and make `log_area` generic over all types `T` that implement `Area`: + +```rust +trait Area { + fn area(self) -> Field; +} + +fn log_area(shape: T) where T: Area { + println(shape.area()); +} +``` + +We also need to explicitly implement `Area` for `Rectangle` and `Triangle`. We can do that by changing their existing +impls slightly. Note that the parameter types and return type of each of our `area` methods must match those defined +by the `Area` trait. + +```rust +impl Area for Rectangle { + fn area(self) -> Field { + self.width * self.height + } +} + +impl Area for Triangle { + fn area(self) -> Field { + self.width * self.height / 2 + } +} +``` + +Now we have a working program that is generic over any type of Shape that is used! Others can even use this program +as a library with their own types - such as `Circle` - as long as they also implement `Area` for these types. + +## Where Clauses + +As seen in `log_area` above, when we want to create a function or method that is generic over any type that implements +a trait, we can add a where clause to the generic function. + +```rust +fn log_area(shape: T) where T: Area { + println(shape.area()); +} +``` + +It is also possible to apply multiple trait constraints on the same variable at once by combining traits with the `+` +operator. Similarly, we can have multiple trait constraints by separating each with a comma: + +```rust +fn foo(elements: [T], thing: U) where + T: Default + Add + Eq, + U: Bar, +{ + let mut sum = T::default(); + + for element in elements { + sum += element; + } + + if sum == T::default() { + thing.bar(); + } +} +``` + +## Generic Implementations + +You can add generics to a trait implementation by adding the generic list after the `impl` keyword: + +```rust +trait Second { + fn second(self) -> Field; +} + +impl Second for (T, Field) { + fn second(self) -> Field { + self.1 + } +} +``` + +You can also implement a trait for every type this way: + +```rust +trait Debug { + fn debug(self); +} + +impl Debug for T { + fn debug(self) { + println(self); + } +} + +fn main() { + 1.debug(); +} +``` + +### Generic Trait Implementations With Where Clauses + +Where clauses can also be placed on trait implementations themselves to restrict generics in a similar way. +For example, while `impl Foo for T` implements the trait `Foo` for every type, `impl Foo for T where T: Bar` +will implement `Foo` only for types that also implement `Bar`. This is often used for implementing generic types. +For example, here is the implementation for array equality: + +```rust +impl Eq for [T; N] where T: Eq { + // Test if two arrays have the same elements. + // Because both arrays must have length N, we know their lengths already match. + fn eq(self, other: Self) -> bool { + let mut result = true; + + for i in 0 .. self.len() { + // The T: Eq constraint is needed to call == on the array elements here + result &= self[i] == other[i]; + } + + result + } +} +``` + +## Generic Traits + +Traits themselves can also be generic by placing the generic arguments after the trait name. These generics are in +scope of every item within the trait. + +```rust +trait Into { + // Convert `self` to type `T` + fn into(self) -> T; +} +``` + +When implementing generic traits the generic arguments of the trait must be specified. This is also true anytime +when referencing a generic trait (e.g. in a `where` clause). + +```rust +struct MyStruct { + array: [Field; 2], +} + +impl Into<[Field; 2]> for MyStruct { + fn into(self) -> [Field; 2] { + self.array + } +} + +fn as_array(x: T) -> [Field; 2] + where T: Into<[Field; 2]> +{ + x.into() +} + +fn main() { + let array = [1, 2]; + let my_struct = MyStruct { array }; + + assert_eq(as_array(my_struct), array); +} +``` + +## Trait Methods With No `self` + +A trait can contain any number of methods, each of which have access to the `Self` type which represents each type +that eventually implements the trait. Similarly, the `self` variable is available as well but is not required to be used. +For example, we can define a trait to create a default value for a type. This trait will need to return the `Self` type +but doesn't need to take any parameters: + +```rust +trait Default { + fn default() -> Self; +} +``` + +Implementing this trait can be done similarly to any other trait: + +```rust +impl Default for Field { + fn default() -> Field { + 0 + } +} + +struct MyType {} + +impl Default for MyType { + fn default() -> Field { + MyType {} + } +} +``` + +However, since there is no `self` parameter, we cannot call it via the method call syntax `object.method()`. +Instead, we'll need to refer to the function directly. This can be done either by referring to the +specific impl `MyType::default()` or referring to the trait itself `Default::default()`. In the later +case, type inference determines the impl that is selected. + +```rust +let my_struct = MyStruct::default(); + +let x: Field = Default::default(); +let result = x + Default::default(); +``` + +:::warning + +```rust +let _ = Default::default(); +``` + +If type inference cannot select which impl to use because of an ambiguous `Self` type, an impl will be +arbitrarily selected. This occurs most often when the result of a trait function call with no parameters +is unused. To avoid this, when calling a trait function with no `self` or `Self` parameters or return type, +always refer to it via the implementation type's namespace - e.g. `MyType::default()`. +This is set to change to an error in future Noir versions. + +::: + +## Default Method Implementations + +A trait can also have default implementations of its methods by giving a body to the desired functions. +Note that this body must be valid for all types that may implement the trait. As a result, the only +valid operations on `self` will be operations valid for any type or other operations on the trait itself. + +```rust +trait Numeric { + fn add(self, other: Self) -> Self; + + // Default implementation of double is (self + self) + fn double(self) -> Self { + self.add(self) + } +} +``` + +When implementing a trait with default functions, a type may choose to implement only the required functions: + +```rust +impl Numeric for Field { + fn add(self, other: Field) -> Field { + self + other + } +} +``` + +Or it may implement the optional methods as well: + +```rust +impl Numeric for u32 { + fn add(self, other: u32) -> u32 { + self + other + } + + fn double(self) -> u32 { + self * 2 + } +} +``` + +## Impl Specialization + +When implementing traits for a generic type it is possible to implement the trait for only a certain combination +of generics. This can be either as an optimization or because those specific generics are required to implement the trait. + +```rust +trait Sub { + fn sub(self, other: Self) -> Self; +} + +struct NonZero { + value: T, +} + +impl Sub for NonZero { + fn sub(self, other: Self) -> Self { + let value = self.value - other.value; + assert(value != 0); + NonZero { value } + } +} +``` + +## Overlapping Implementations + +Overlapping implementations are disallowed by Noir to ensure Noir's decision on which impl to select is never ambiguous. +This means if a trait `Foo` is already implemented +by a type `Bar` for all `T`, then we cannot also have a separate impl for `Bar` (or any other +type argument). Similarly, if there is an impl for all `T` such as `impl Debug for T`, we cannot create +any more impls to `Debug` for other types since it would be ambiguous which impl to choose for any given +method call. + +```rust +trait Trait {} + +// Previous impl defined here +impl Trait for (A, B) {} + +// error: Impl for type `(Field, Field)` overlaps with existing impl +impl Trait for (Field, Field) {} +``` + +## Trait Coherence + +Another restriction on trait implementations is coherence. This restriction ensures other crates cannot create +impls that may overlap with other impls, even if several unrelated crates are used as dependencies in the same +program. + +The coherence restriction is: to implement a trait, either the trait itself or the object type must be declared +in the crate the impl is in. + +In practice this often comes up when using types provided by libraries. If a library provides a type `Foo` that does +not implement a trait in the standard library such as `Default`, you may not `impl Default for Foo` in your own crate. +While restrictive, this prevents later issues or silent changes in the program if the `Foo` library later added its +own impl for `Default`. If you are a user of the `Foo` library in this scenario and need a trait not implemented by the +library your choices are to either submit a patch to the library or use the newtype pattern. + +### The Newtype Pattern + +The newtype pattern gets around the coherence restriction by creating a new wrapper type around the library type +that we cannot create `impl`s for. Since the new wrapper type is defined in our current crate, we can create +impls for any trait we need on it. + +```rust +struct Wrapper { + foo: dep::some_library::Foo, +} + +impl Default for Wrapper { + fn default() -> Wrapper { + Wrapper { + foo: dep::some_library::Foo::new(), + } + } +} +``` + +Since we have an impl for our own type, the behavior of this code will not change even if `some_library` is updated +to provide its own `impl Default for Foo`. The downside of this pattern is that it requires extra wrapping and +unwrapping of values when converting to and from the `Wrapper` and `Foo` types. diff --git a/docs/versioned_docs/version-v0.29.0/noir/concepts/unconstrained.md b/docs/versioned_docs/version-v0.29.0/noir/concepts/unconstrained.md new file mode 100644 index 00000000000..b8e71fe65f0 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/noir/concepts/unconstrained.md @@ -0,0 +1,99 @@ +--- +title: Unconstrained Functions +description: "Learn about what unconstrained functions in Noir are, how to use them and when you'd want to." + +keywords: [Noir programming language, unconstrained, open] +sidebar_position: 5 +--- + +Unconstrained functions are functions which do not constrain any of the included computation and allow for non-deterministic 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 AND 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. + +## Break and Continue + +In addition to loops over runtime bounds, `break` and `continue` are also available in unconstrained code. See [break and continue](../concepts/control_flow/#break-and-continue) diff --git a/docs/versioned_docs/version-v0.29.0/noir/modules_packages_crates/_category_.json b/docs/versioned_docs/version-v0.29.0/noir/modules_packages_crates/_category_.json new file mode 100644 index 00000000000..1debcfe7675 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/noir/modules_packages_crates/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Modules, Packages and Crates", + "position": 2, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.29.0/noir/modules_packages_crates/crates_and_packages.md b/docs/versioned_docs/version-v0.29.0/noir/modules_packages_crates/crates_and_packages.md new file mode 100644 index 00000000000..95ee9f52ab2 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/noir/modules_packages_crates/crates_and_packages.md @@ -0,0 +1,43 @@ +--- +title: Crates and Packages +description: Learn how to use Crates and Packages in your Noir project +keywords: [Nargo, dependencies, package management, crates, package] +sidebar_position: 0 +--- + +## Crates + +A crate is the smallest amount of code that the Noir compiler considers at a time. +Crates can contain modules, and the modules may be defined in other files that get compiled with the crate, as we’ll see in the coming sections. + +### Crate Types + +A Noir crate can come in several forms: binaries, libraries or contracts. + +#### Binaries + +_Binary crates_ are programs which you can compile to an ACIR circuit which you can then create proofs against. Each must have a function called `main` that defines the ACIR circuit which is to be proved. + +#### Libraries + +_Library crates_ don't have a `main` function and they don't compile down to ACIR. Instead they define functionality intended to be shared with multiple projects, and eventually included in a binary crate. + +#### Contracts + +Contract crates are similar to binary crates in that they compile to ACIR which you can create proofs against. They are different in that they do not have a single `main` function, but are a collection of functions to be deployed to the [Aztec network](https://aztec.network). You can learn more about the technical details of Aztec in the [monorepo](https://github.com/AztecProtocol/aztec-packages) or contract [examples](https://github.com/AztecProtocol/aztec-packages/tree/master/noir-projects/noir-contracts/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.29.0/noir/modules_packages_crates/dependencies.md b/docs/versioned_docs/version-v0.29.0/noir/modules_packages_crates/dependencies.md new file mode 100644 index 00000000000..04c1703d929 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/noir/modules_packages_crates/dependencies.md @@ -0,0 +1,124 @@ +--- +title: Dependencies +description: + Learn how to specify and manage dependencies in Nargo, allowing you to upload packages to GitHub + and use them easily in your project. +keywords: [Nargo, dependencies, GitHub, package management, versioning] +sidebar_position: 1 +--- + +Nargo allows you to upload packages to GitHub and use them as dependencies. + +## Specifying a dependency + +Specifying a dependency requires a tag to a specific commit and the git url to the url containing +the package. + +Currently, there are no requirements on the tag contents. If requirements are added, it would follow +semver 2.0 guidelines. + +> Note: Without a `tag` , there would be no versioning and dependencies would change each time you +> compile your project. + +For example, to add the [ecrecover-noir library](https://github.com/colinnielsen/ecrecover-noir) to your project, add it to `Nargo.toml`: + +```toml +# Nargo.toml + +[dependencies] +ecrecover = {tag = "v0.8.0", git = "https://github.com/colinnielsen/ecrecover-noir"} +``` + +If the module is in a subdirectory, you can define a subdirectory in your git repository, for example: + +```toml +# Nargo.toml + +[dependencies] +easy_private_token_contract = {tag ="v0.1.0-alpha62", git = "https://github.com/AztecProtocol/aztec-packages", directory = "noir-contracts/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 +└── lib_a + ├── Nargo.toml + └── src + └── lib.nr +``` + +Inside of the binary crate, you can specify: + +```toml +# Nargo.toml + +[dependencies] +lib_a = { path = "../lib_a" } +``` + +## 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 lib_a referenced above: + +```rust +use dep::ecrecover; +use dep::lib_a; +``` + +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.29.0/noir/modules_packages_crates/modules.md b/docs/versioned_docs/version-v0.29.0/noir/modules_packages_crates/modules.md new file mode 100644 index 00000000000..ae822a1cff4 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/noir/modules_packages_crates/modules.md @@ -0,0 +1,105 @@ +--- +title: Modules +description: + Learn how to organize your files using modules in Noir, following the same convention as Rust's + module system. Examples included. +keywords: [Noir, Rust, modules, organizing files, sub-modules] +sidebar_position: 2 +--- + +Noir's module system follows the same convention as the _newer_ version of Rust's module system. + +## Purpose of Modules + +Modules are used to organize 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.29.0/noir/modules_packages_crates/workspaces.md b/docs/versioned_docs/version-v0.29.0/noir/modules_packages_crates/workspaces.md new file mode 100644 index 00000000000..513497f12bf --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/noir/modules_packages_crates/workspaces.md @@ -0,0 +1,42 @@ +--- +title: Workspaces +sidebar_position: 3 +--- + +Workspaces are a feature of nargo that allow you to manage multiple related Noir packages in a single repository. A workspace is essentially a group of related projects that share common build output directories and configurations. + +Each Noir project (with it's own Nargo.toml file) can be thought of as a package. Each package is expected to contain exactly one "named circuit", being the "name" defined in Nargo.toml with the program logic defined in `./src/main.nr`. + +For a project with the following structure: + +```tree +├── crates +│ ├── a +│ │ ├── Nargo.toml +│ │ └── Prover.toml +│ │ └── src +│ │ └── main.nr +│ └── b +│ ├── Nargo.toml +│ └── Prover.toml +│ └── src +│ └── main.nr +│ +└── Nargo.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.29.0/noir/standard_library/_category_.json b/docs/versioned_docs/version-v0.29.0/noir/standard_library/_category_.json new file mode 100644 index 00000000000..af04c0933fd --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/noir/standard_library/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Standard Library", + "position": 1, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.29.0/noir/standard_library/bigint.md b/docs/versioned_docs/version-v0.29.0/noir/standard_library/bigint.md new file mode 100644 index 00000000000..2bfdeec6631 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/noir/standard_library/bigint.md @@ -0,0 +1,122 @@ +--- +title: Big Integers +description: How to use big integers from Noir standard library +keywords: + [ + Big Integer, + Noir programming language, + Noir libraries, + ] +--- + +The BigInt module in the standard library exposes some class of integers which do not fit (well) into a Noir native field. It implements modulo arithmetic, modulo a 'big' prime number. + +:::note + +The module can currently be considered as `Field`s with fixed modulo sizes used by a set of elliptic curves, in addition to just the native curve. [More work](https://github.com/noir-lang/noir/issues/510) is needed to achieve arbitrarily sized big integers. + +::: + +Currently 6 classes of integers (i.e 'big' prime numbers) are available in the module, namely: + +- BN254 Fq: Bn254Fq +- BN254 Fr: Bn254Fr +- Secp256k1 Fq: Secpk1Fq +- Secp256k1 Fr: Secpk1Fr +- Secp256r1 Fr: Secpr1Fr +- Secp256r1 Fq: Secpr1Fq + +Where XXX Fq and XXX Fr denote respectively the order of the base and scalar field of the (usual) elliptic curve XXX. +For instance the big integer 'Secpk1Fq' in the standard library refers to integers modulo $2^{256}-2^{32}-977$. + +Feel free to explore the source code for the other primes: + +```rust title="big_int_definition" showLineNumbers +struct BigInt { + pointer: u32, + modulus: u32, +} +``` +> Source code: noir_stdlib/src/bigint.nr#L14-L19 + + +## Example usage + +A common use-case is when constructing a big integer from its bytes representation, and performing arithmetic operations on it: + +```rust title="big_int_example" showLineNumbers +fn big_int_example(x: u8, y: u8) { + let a = Secpk1Fq::from_le_bytes(&[x, y, 0, 45, 2]); + let b = Secpk1Fq::from_le_bytes(&[y, x, 9]); + let c = (a + b) * b / a; + let d = c.to_le_bytes(); + println(d[0]); +} +``` +> Source code: test_programs/execution_success/bigint/src/main.nr#L70-L78 + + +## Methods + +The available operations for each big integer are: + +### from_le_bytes + +Construct a big integer from its little-endian bytes representation. Example: + +```rust + // Construct a big integer from a slice of bytes + let a = Secpk1Fq::from_le_bytes(&[x, y, 0, 45, 2]); + // Construct a big integer from an array of 32 bytes + let a = Secpk1Fq::from_le_bytes_32([1;32]); + ``` + +Sure, here's the formatted version of the remaining methods: + +### to_le_bytes + +Return the little-endian bytes representation of a big integer. Example: + +```rust +let bytes = a.to_le_bytes(); +``` + +### add + +Add two big integers. Example: + +```rust +let sum = a + b; +``` + +### sub + +Subtract two big integers. Example: + +```rust +let difference = a - b; +``` + +### mul + +Multiply two big integers. Example: + +```rust +let product = a * b; +``` + +### div + +Divide two big integers. Note that division is field division and not euclidean division. Example: + +```rust +let quotient = a / b; +``` + +### eq + +Compare two big integers. Example: + +```rust +let are_equal = a == b; +``` diff --git a/docs/versioned_docs/version-v0.29.0/noir/standard_library/black_box_fns.md b/docs/versioned_docs/version-v0.29.0/noir/standard_library/black_box_fns.md new file mode 100644 index 00000000000..be8c65679c3 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/noir/standard_library/black_box_fns.md @@ -0,0 +1,31 @@ +--- +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. + +The ACVM spec defines a set of blackbox functions which backends will be expected to implement. This allows backends to use optimized implementations of these constraints if they have them, however they may also fallback to less efficient naive implementations if not. + +## Function list + +Here is a list of the current black box functions: + +- [SHA256](./cryptographic_primitives/hashes.mdx#sha256) +- [Schnorr signature verification](./cryptographic_primitives/schnorr.mdx) +- [Blake2s](./cryptographic_primitives/hashes.mdx#blake2s) +- [Blake3](./cryptographic_primitives/hashes.mdx#blake3) +- [Pedersen Hash](./cryptographic_primitives/hashes.mdx#pedersen_hash) +- [Pedersen Commitment](./cryptographic_primitives/hashes.mdx#pedersen_commitment) +- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification.mdx) +- [Fixed base scalar multiplication](./cryptographic_primitives/scalar.mdx) +- AND +- XOR +- RANGE +- [Keccak256](./cryptographic_primitives/hashes.mdx#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. + +You can view the black box functions defined in the ACVM code [here](https://github.com/noir-lang/noir/blob/master/acvm-repo/acir/src/circuit/black_box_functions.rs). diff --git a/docs/versioned_docs/version-v0.29.0/noir/standard_library/bn254.md b/docs/versioned_docs/version-v0.29.0/noir/standard_library/bn254.md new file mode 100644 index 00000000000..3294f005dbb --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/noir/standard_library/bn254.md @@ -0,0 +1,46 @@ +--- +title: Bn254 Field Library +--- + +Noir provides a module in standard library with some optimized functions for bn254 Fr in `std::field::bn254`. + +## decompose + +```rust +fn decompose(x: Field) -> (Field, Field) {} +``` + +Decomposes a single field into two fields, low and high. The low field contains the lower 16 bytes of the input field and the high field contains the upper 16 bytes of the input field. Both field results are range checked to 128 bits. + + +## assert_gt + +```rust +fn assert_gt(a: Field, b: Field) {} +``` + +Asserts that a > b. This will generate less constraints than using `assert(gt(a, b))`. + +## assert_lt + +```rust +fn assert_lt(a: Field, b: Field) {} +``` + +Asserts that a < b. This will generate less constraints than using `assert(lt(a, b))`. + +## gt + +```rust +fn gt(a: Field, b: Field) -> bool {} +``` + +Returns true if a > b. + +## lt + +```rust +fn lt(a: Field, b: Field) -> bool {} +``` + +Returns true if a < b. \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.29.0/noir/standard_library/containers/boundedvec.md b/docs/versioned_docs/version-v0.29.0/noir/standard_library/containers/boundedvec.md new file mode 100644 index 00000000000..ce4529f6e57 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/noir/standard_library/containers/boundedvec.md @@ -0,0 +1,326 @@ +--- +title: Bounded Vectors +keywords: [noir, vector, bounded vector, slice] +sidebar_position: 1 +--- + +A `BoundedVec` is a growable storage similar to a `Vec` except that it +is bounded with a maximum possible length. Unlike `Vec`, `BoundedVec` is not implemented +via slices and thus is not subject to the same restrictions slices are (notably, nested +slices - and thus nested vectors as well - are disallowed). + +Since a BoundedVec is backed by a normal array under the hood, growing the BoundedVec by +pushing an additional element is also more efficient - the length only needs to be increased +by one. + +For these reasons `BoundedVec` should generally be preferred over `Vec` when there +is a reasonable maximum bound that can be placed on the vector. + +Example: + +```rust +let mut vector: BoundedVec = BoundedVec::new(); +for i in 0..5 { + vector.push(i); +} +assert(vector.len() == 5); +assert(vector.max_len() == 10); +``` + +## Methods + +### new + +```rust +pub fn new() -> Self +``` + +Creates a new, empty vector of length zero. + +Since this container is backed by an array internally, it still needs an initial value +to give each element. To resolve this, each element is zeroed internally. This value +is guaranteed to be inaccessible unless `get_unchecked` is used. + +Example: + +```rust +let empty_vector: BoundedVec = BoundedVec::new(); +assert(empty_vector.len() == 0); +``` + +Note that whenever calling `new` the maximum length of the vector should always be specified +via a type signature: + +```rust title="new_example" showLineNumbers +fn foo() -> BoundedVec { + // Ok! MaxLen is specified with a type annotation + let v1: BoundedVec = BoundedVec::new(); + let v2 = BoundedVec::new(); + + // Ok! MaxLen is known from the type of foo's return value + v2 +} + +fn bad() { + let mut v3 = BoundedVec::new(); + + // Not Ok! We don't know if v3's MaxLen is at least 1, and the compiler often infers 0 by default. + v3.push(5); +} +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L11-L27 + + +This defaulting of `MaxLen` (and numeric generics in general) to zero may change in future noir versions +but for now make sure to use type annotations when using bounded vectors. Otherwise, you will receive a constraint failure at runtime when the vec is pushed to. + +### get + +```rust +pub fn get(mut self: Self, index: u64) -> T { +``` + +Retrieves an element from the vector at the given index, starting from zero. + +If the given index is equal to or greater than the length of the vector, this +will issue a constraint failure. + +Example: + +```rust +fn foo(v: BoundedVec) { + let first = v.get(0); + let last = v.get(v.len() - 1); + assert(first != last); +} +``` + +### get_unchecked + +```rust +pub fn get_unchecked(mut self: Self, index: u64) -> T { +``` + +Retrieves an element from the vector at the given index, starting from zero, without +performing a bounds check. + +Since this function does not perform a bounds check on length before accessing the element, +it is unsafe! Use at your own risk! + +Example: + +```rust title="get_unchecked_example" showLineNumbers +fn sum_of_first_three(v: BoundedVec) -> u32 { + // Always ensure the length is larger than the largest + // index passed to get_unchecked + assert(v.len() > 2); + let first = v.get_unchecked(0); + let second = v.get_unchecked(1); + let third = v.get_unchecked(2); + first + second + third +} +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L54-L64 + + + +### push + +```rust +pub fn push(&mut self, elem: T) { +``` + +Pushes an element to the end of the vector. This increases the length +of the vector by one. + +Panics if the new length of the vector will be greater than the max length. + +Example: + +```rust title="bounded-vec-push-example" showLineNumbers +let mut v: BoundedVec = BoundedVec::new(); + + v.push(1); + v.push(2); + + // Panics with failed assertion "push out of bounds" + v.push(3); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L68-L76 + + +### pop + +```rust +pub fn pop(&mut self) -> T +``` + +Pops the element at the end of the vector. This will decrease the length +of the vector by one. + +Panics if the vector is empty. + +Example: + +```rust title="bounded-vec-pop-example" showLineNumbers +let mut v: BoundedVec = BoundedVec::new(); + v.push(1); + v.push(2); + + let two = v.pop(); + let one = v.pop(); + + assert(two == 2); + assert(one == 1); + // error: cannot pop from an empty vector + // let _ = v.pop(); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L81-L93 + + +### len + +```rust +pub fn len(self) -> u64 { +``` + +Returns the current length of this vector + +Example: + +```rust title="bounded-vec-len-example" showLineNumbers +let mut v: BoundedVec = BoundedVec::new(); + assert(v.len() == 0); + + v.push(100); + assert(v.len() == 1); + + v.push(200); + v.push(300); + v.push(400); + assert(v.len() == 4); + + let _ = v.pop(); + let _ = v.pop(); + assert(v.len() == 2); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L98-L113 + + +### max_len + +```rust +pub fn max_len(_self: BoundedVec) -> u64 { +``` + +Returns the maximum length of this vector. This is always +equal to the `MaxLen` parameter this vector was initialized with. + +Example: + +```rust title="bounded-vec-max-len-example" showLineNumbers +let mut v: BoundedVec = BoundedVec::new(); + + assert(v.max_len() == 5); + v.push(10); + assert(v.max_len() == 5); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L118-L124 + + +### storage + +```rust +pub fn storage(self) -> [T; MaxLen] { +``` + +Returns the internal array within this vector. +Since arrays in Noir are immutable, mutating the returned storage array will not mutate +the storage held internally by this vector. + +Note that uninitialized elements may be zeroed out! + +Example: + +```rust title="bounded-vec-storage-example" showLineNumbers +let mut v: BoundedVec = BoundedVec::new(); + + assert(v.storage() == [0, 0, 0, 0, 0]); + + v.push(57); + assert(v.storage() == [57, 0, 0, 0, 0]); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L129-L136 + + +### extend_from_array + +```rust +pub fn extend_from_array(&mut self, array: [T; Len]) +``` + +Pushes each element from the given array to this vector. + +Panics if pushing each element would cause the length of this vector +to exceed the maximum length. + +Example: + +```rust title="bounded-vec-extend-from-array-example" showLineNumbers +let mut vec: BoundedVec = BoundedVec::new(); + vec.extend_from_array([2, 4]); + + assert(vec.len == 2); + assert(vec.get(0) == 2); + assert(vec.get(1) == 4); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L141-L148 + + +### extend_from_bounded_vec + +```rust +pub fn extend_from_bounded_vec(&mut self, vec: BoundedVec) +``` + +Pushes each element from the other vector to this vector. The length of +the other vector is left unchanged. + +Panics if pushing each element would cause the length of this vector +to exceed the maximum length. + +Example: + +```rust title="bounded-vec-extend-from-bounded-vec-example" showLineNumbers +let mut v1: BoundedVec = BoundedVec::new(); + let mut v2: BoundedVec = BoundedVec::new(); + + v2.extend_from_array([1, 2, 3]); + v1.extend_from_bounded_vec(v2); + + assert(v1.storage() == [1, 2, 3, 0, 0]); + assert(v2.storage() == [1, 2, 3, 0, 0, 0, 0]); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L153-L162 + + +### any + +```rust +pub fn any(self, predicate: fn[Env](T) -> bool) -> bool +``` + +Returns true if the given predicate returns true for any element +in this vector. + +Example: + +```rust title="bounded-vec-any-example" showLineNumbers +let mut v: BoundedVec = BoundedVec::new(); + v.extend_from_array([2, 4, 6]); + + let all_even = !v.any(|elem: u32| elem % 2 != 0); + assert(all_even); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L229-L235 + diff --git a/docs/versioned_docs/version-v0.29.0/noir/standard_library/containers/hashmap.md b/docs/versioned_docs/version-v0.29.0/noir/standard_library/containers/hashmap.md new file mode 100644 index 00000000000..47faa99aba6 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/noir/standard_library/containers/hashmap.md @@ -0,0 +1,570 @@ +--- +title: HashMap +keywords: [noir, map, hash, hashmap] +sidebar_position: 1 +--- + +`HashMap` is used to efficiently store and look up key-value pairs. + +`HashMap` is a bounded type which can store anywhere from zero to `MaxLen` total elements. +Note that due to hash collisions, the actual maximum number of elements stored by any particular +hashmap is likely lower than `MaxLen`. This is true even with cryptographic hash functions since +every hash value will be performed modulo `MaxLen`. + +When creating `HashMap`s, the `MaxLen` generic should always be specified if it is not already +known. Otherwise, the compiler may infer a different value for `MaxLen` (such as zero), which +will likely change the result of the program. This behavior is set to become an error in future +versions instead. + +Example: + +```rust +// Create a mapping from Fields to u32s with a maximum length of 12 +// using a poseidon2 hasher +use dep::std::hash::poseidon2::Poseidon2Hasher; +let mut map: HashMap> = HashMap::default(); + +map.insert(1, 2); +map.insert(3, 4); + +let two = map.get(1).unwrap(); +``` + +## Methods + +### default + +```rust title="default" showLineNumbers +impl Default for HashMap +where + B: BuildHasher + Default, + H: Hasher + Default +{ + fn default() -> Self { +``` +> Source code: noir_stdlib/src/collections/map.nr#L462-L469 + + +Creates a fresh, empty HashMap. + +When using this function, always make sure to specify the maximum size of the hash map. + +This is the same `default` from the `Default` implementation given further below. It is +repeated here for convenience since it is the recommended way to create a hashmap. + +Example: + +```rust title="default_example" showLineNumbers +let hashmap: HashMap> = HashMap::default(); + assert(hashmap.is_empty()); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L202-L205 + + +Because `HashMap` has so many generic arguments that are likely to be the same throughout +your program, it may be helpful to create a type alias: + +```rust title="type_alias" showLineNumbers +type MyMap = HashMap>; +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L196-L198 + + +### with_hasher + +```rust title="with_hasher" showLineNumbers +pub fn with_hasher(_build_hasher: B) -> Self + where + B: BuildHasher { +``` +> Source code: noir_stdlib/src/collections/map.nr#L82-L86 + + +Creates a hashmap with an existing `BuildHasher`. This can be used to ensure multiple +hashmaps are created with the same hasher instance. + +Example: + +```rust title="with_hasher_example" showLineNumbers +let my_hasher: BuildHasherDefault = Default::default(); + let hashmap: HashMap> = HashMap::with_hasher(my_hasher); + assert(hashmap.is_empty()); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L207-L211 + + +### get + +```rust title="get" showLineNumbers +pub fn get( + self, + key: K + ) -> Option + where + K: Eq + Hash, + B: BuildHasher, + H: Hasher { +``` +> Source code: noir_stdlib/src/collections/map.nr#L278-L287 + + +Retrieves a value from the hashmap, returning `Option::none()` if it was not found. + +Example: + +```rust title="get_example" showLineNumbers +fn get_example(map: HashMap>) { + let x = map.get(12); + + if x.is_some() { + assert(x.unwrap() == 42); + } +} +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L299-L307 + + +### insert + +```rust title="insert" showLineNumbers +pub fn insert( + &mut self, + key: K, + value: V + ) + where + K: Eq + Hash, + B: BuildHasher, + H: Hasher { +``` +> Source code: noir_stdlib/src/collections/map.nr#L313-L323 + + +Inserts a new key-value pair into the map. If the key was already in the map, its +previous value will be overridden with the newly provided one. + +Example: + +```rust title="insert_example" showLineNumbers +let mut map: HashMap> = HashMap::default(); + map.insert(12, 42); + assert(map.len() == 1); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L213-L217 + + +### remove + +```rust title="remove" showLineNumbers +pub fn remove( + &mut self, + key: K + ) + where + K: Eq + Hash, + B: BuildHasher, + H: Hasher { +``` +> Source code: noir_stdlib/src/collections/map.nr#L356-L365 + + +Removes the given key-value pair from the map. If the key was not already present +in the map, this does nothing. + +Example: + +```rust title="remove_example" showLineNumbers +map.remove(12); + assert(map.is_empty()); + + // If a key was not present in the map, remove does nothing + map.remove(12); + assert(map.is_empty()); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L221-L228 + + +### is_empty + +```rust title="is_empty" showLineNumbers +pub fn is_empty(self) -> bool { +``` +> Source code: noir_stdlib/src/collections/map.nr#L115-L117 + + +True if the length of the hash map is empty. + +Example: + +```rust title="is_empty_example" showLineNumbers +assert(map.is_empty()); + + map.insert(1, 2); + assert(!map.is_empty()); + + map.remove(1); + assert(map.is_empty()); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L230-L238 + + +### len + +```rust title="len" showLineNumbers +pub fn len(self) -> u64 { +``` +> Source code: noir_stdlib/src/collections/map.nr#L264-L266 + + +Returns the current length of this hash map. + +Example: + +```rust title="len_example" showLineNumbers +// This is equivalent to checking map.is_empty() + assert(map.len() == 0); + + map.insert(1, 2); + map.insert(3, 4); + map.insert(5, 6); + assert(map.len() == 3); + + // 3 was already present as a key in the hash map, so the length is unchanged + map.insert(3, 7); + assert(map.len() == 3); + + map.remove(1); + assert(map.len() == 2); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L240-L255 + + +### capacity + +```rust title="capacity" showLineNumbers +pub fn capacity(_self: Self) -> u64 { +``` +> Source code: noir_stdlib/src/collections/map.nr#L271-L273 + + +Returns the maximum capacity of this hashmap. This is always equal to the capacity +specified in the hashmap's type. + +Unlike hashmaps in general purpose programming languages, hashmaps in Noir have a +static capacity that does not increase as the map grows larger. Thus, this capacity +is also the maximum possible element count that can be inserted into the hashmap. +Due to hash collisions (modulo the hashmap length), it is likely the actual maximum +element count will be lower than the full capacity. + +Example: + +```rust title="capacity_example" showLineNumbers +let empty_map: HashMap> = HashMap::default(); + assert(empty_map.len() == 0); + assert(empty_map.capacity() == 42); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L257-L261 + + +### clear + +```rust title="clear" showLineNumbers +pub fn clear(&mut self) { +``` +> Source code: noir_stdlib/src/collections/map.nr#L93-L95 + + +Clears the hashmap, removing all key-value pairs from it. + +Example: + +```rust title="clear_example" showLineNumbers +assert(!map.is_empty()); + map.clear(); + assert(map.is_empty()); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L263-L267 + + +### contains_key + +```rust title="contains_key" showLineNumbers +pub fn contains_key( + self, + key: K + ) -> bool + where + K: Hash + Eq, + B: BuildHasher, + H: Hasher { +``` +> Source code: noir_stdlib/src/collections/map.nr#L101-L110 + + +True if the hashmap contains the given key. Unlike `get`, this will not also return +the value associated with the key. + +Example: + +```rust title="contains_key_example" showLineNumbers +if map.contains_key(7) { + let value = map.get(7); + assert(value.is_some()); + } else { + println("No value for key 7!"); + } +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L269-L276 + + +### entries + +```rust title="entries" showLineNumbers +pub fn entries(self) -> BoundedVec<(K, V), N> { +``` +> Source code: noir_stdlib/src/collections/map.nr#L123-L125 + + +Returns a vector of each key-value pair present in the hashmap. + +The length of the returned vector is always equal to the length of the hashmap. + +Example: + +```rust title="entries_example" showLineNumbers +let entries = map.entries(); + + // The length of a hashmap may not be compile-time known, so we + // need to loop over its capacity instead + for i in 0..map.capacity() { + if i < entries.len() { + let (key, value) = entries.get(i); + println(f"{key} -> {value}"); + } + } +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L310-L321 + + +### keys + +```rust title="keys" showLineNumbers +pub fn keys(self) -> BoundedVec { +``` +> Source code: noir_stdlib/src/collections/map.nr#L144-L146 + + +Returns a vector of each key present in the hashmap. + +The length of the returned vector is always equal to the length of the hashmap. + +Example: + +```rust title="keys_example" showLineNumbers +let keys = map.keys(); + + for i in 0..keys.max_len() { + if i < keys.len() { + let key = keys.get_unchecked(i); + let value = map.get(key).unwrap_unchecked(); + println(f"{key} -> {value}"); + } + } +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L323-L333 + + +### values + +```rust title="values" showLineNumbers +pub fn values(self) -> BoundedVec { +``` +> Source code: noir_stdlib/src/collections/map.nr#L164-L166 + + +Returns a vector of each value present in the hashmap. + +The length of the returned vector is always equal to the length of the hashmap. + +Example: + +```rust title="values_example" showLineNumbers +let values = map.values(); + + for i in 0..values.max_len() { + if i < values.len() { + let value = values.get_unchecked(i); + println(f"Found value {value}"); + } + } +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L335-L344 + + +### iter_mut + +```rust title="iter_mut" showLineNumbers +pub fn iter_mut( + &mut self, + f: fn(K, V) -> (K, V) + ) + where + K: Eq + Hash, + B: BuildHasher, + H: Hasher { +``` +> Source code: noir_stdlib/src/collections/map.nr#L183-L192 + + +Iterates through each key-value pair of the HashMap, setting each key-value pair to the +result returned from the given function. + +Note that since keys can be mutated, the HashMap needs to be rebuilt as it is iterated +through. If this is not desired, use `iter_values_mut` if only values need to be mutated, +or `entries` if neither keys nor values need to be mutated. + +The iteration order is left unspecified. As a result, if two keys are mutated to become +equal, which of the two values that will be present for the key in the resulting map is also unspecified. + +Example: + +```rust title="iter_mut_example" showLineNumbers +// Add 1 to each key in the map, and double the value associated with that key. + map.iter_mut(|k, v| (k + 1, v * 2)); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L348-L351 + + +### iter_keys_mut + +```rust title="iter_keys_mut" showLineNumbers +pub fn iter_keys_mut( + &mut self, + f: fn(K) -> K + ) + where + K: Eq + Hash, + B: BuildHasher, + H: Hasher { +``` +> Source code: noir_stdlib/src/collections/map.nr#L208-L217 + + +Iterates through the HashMap, mutating each key to the result returned from +the given function. + +Note that since keys can be mutated, the HashMap needs to be rebuilt as it is iterated +through. If only iteration is desired and the keys are not intended to be mutated, +prefer using `entries` instead. + +The iteration order is left unspecified. As a result, if two keys are mutated to become +equal, which of the two values that will be present for the key in the resulting map is also unspecified. + +Example: + +```rust title="iter_keys_mut_example" showLineNumbers +// Double each key, leaving the value associated with that key untouched + map.iter_keys_mut(|k| k * 2); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L353-L356 + + +### iter_values_mut + +```rust title="iter_values_mut" showLineNumbers +pub fn iter_values_mut(&mut self, f: fn(V) -> V) { +``` +> Source code: noir_stdlib/src/collections/map.nr#L233-L235 + + +Iterates through the HashMap, applying the given function to each value and mutating the +value to equal the result. This function is more efficient than `iter_mut` and `iter_keys_mut` +because the keys are untouched and the underlying hashmap thus does not need to be reordered. + +Example: + +```rust title="iter_values_mut_example" showLineNumbers +// Halve each value + map.iter_values_mut(|v| v / 2); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L358-L361 + + +### retain + +```rust title="retain" showLineNumbers +pub fn retain(&mut self, f: fn(K, V) -> bool) { +``` +> Source code: noir_stdlib/src/collections/map.nr#L247-L249 + + +Retains only the key-value pairs for which the given function returns true. +Any key-value pairs for which the function returns false will be removed from the map. + +Example: + +```rust title="retain_example" showLineNumbers +map.retain(|k, v| (k != 0) & (v != 0)); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L281-L283 + + +## Trait Implementations + +### default + +```rust title="default" showLineNumbers +impl Default for HashMap +where + B: BuildHasher + Default, + H: Hasher + Default +{ + fn default() -> Self { +``` +> Source code: noir_stdlib/src/collections/map.nr#L462-L469 + + +Constructs an empty HashMap. + +Example: + +```rust title="default_example" showLineNumbers +let hashmap: HashMap> = HashMap::default(); + assert(hashmap.is_empty()); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L202-L205 + + +### eq + +```rust title="eq" showLineNumbers +impl Eq for HashMap +where + K: Eq + Hash, + V: Eq, + B: BuildHasher, + H: Hasher +{ + fn eq(self, other: HashMap) -> bool { +``` +> Source code: noir_stdlib/src/collections/map.nr#L426-L435 + + +Checks if two HashMaps are equal. + +Example: + +```rust title="eq_example" showLineNumbers +let mut map1: HashMap> = HashMap::default(); + let mut map2: HashMap> = HashMap::default(); + + map1.insert(1, 2); + map1.insert(3, 4); + + map2.insert(3, 4); + map2.insert(1, 2); + + assert(map1 == map2); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L285-L296 + diff --git a/docs/versioned_docs/version-v0.29.0/noir/standard_library/containers/index.md b/docs/versioned_docs/version-v0.29.0/noir/standard_library/containers/index.md new file mode 100644 index 00000000000..ea84c6d5c21 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/noir/standard_library/containers/index.md @@ -0,0 +1,5 @@ +--- +title: Containers +description: Container types provided by Noir's standard library for storing and retrieving data +keywords: [containers, data types, vec, hashmap] +--- diff --git a/docs/versioned_docs/version-v0.29.0/noir/standard_library/containers/vec.mdx b/docs/versioned_docs/version-v0.29.0/noir/standard_library/containers/vec.mdx new file mode 100644 index 00000000000..fcfd7e07aa0 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/noir/standard_library/containers/vec.mdx @@ -0,0 +1,151 @@ +--- +title: Vectors +description: Delve into the Vec data type in Noir. Learn about its methods, practical examples, and best practices for using Vectors in your Noir code. +keywords: [noir, vector type, methods, examples, dynamic arrays] +sidebar_position: 6 +--- + +import Experimental from '@site/src/components/Notes/_experimental.mdx'; + + + +A vector is a collection type similar to Rust's `Vec` type. In Noir, it is a convenient way to use slices as mutable arrays. + +Example: + +```rust +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 +``` + +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 +``` + +Example: + +```rust +let slice: [Field] = &[1, 2, 3]; +let vector_from_slice = Vec::from_slice(slice); +assert(vector_from_slice.len() == 3); +``` + +### len + +Returns the number of elements in the vector. + +```rust +pub fn len(self) -> Field +``` + +Example: + +```rust +let empty_vector: Vec = Vec::new(); +assert(empty_vector.len() == 0); +``` + +### 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 +``` + +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) +``` + +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 +``` + +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) +``` + +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 +``` + +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); +``` diff --git a/docs/versioned_docs/version-v0.29.0/noir/standard_library/cryptographic_primitives/_category_.json b/docs/versioned_docs/version-v0.29.0/noir/standard_library/cryptographic_primitives/_category_.json new file mode 100644 index 00000000000..5d694210bbf --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/noir/standard_library/cryptographic_primitives/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 0, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.29.0/noir/standard_library/cryptographic_primitives/ec_primitives.md b/docs/versioned_docs/version-v0.29.0/noir/standard_library/cryptographic_primitives/ec_primitives.md new file mode 100644 index 00000000000..d2b42d67b7c --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/noir/standard_library/cryptographic_primitives/ec_primitives.md @@ -0,0 +1,102 @@ +--- +title: Elliptic Curve Primitives +keywords: [cryptographic primitives, Noir project] +sidebar_position: 4 +--- + +Data structures and methods on them that allow you to carry out computations involving elliptic +curves over the (mathematical) field corresponding to `Field`. For the field currently at our +disposal, applications would involve a curve embedded in BN254, e.g. the +[Baby Jubjub curve](https://eips.ethereum.org/EIPS/eip-2494). + +## Data structures + +### Elliptic curve configurations + +(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Curve`), i.e. the specific elliptic +curve you want to use, which would be specified using any one of the methods +`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::new` which take the coefficients in the +defining equation together with a generator point as parameters. You can find more detail in the +comments in +[`noir_stdlib/src/ec.nr`](https://github.com/noir-lang/noir/blob/master/noir_stdlib/src/ec.nr), but +the gist of it is that the elliptic curves of interest are usually expressed in one of the standard +forms implemented here (Twisted Edwards, Montgomery and Short Weierstraß), and in addition to that, +you could choose to use `affine` coordinates (Cartesian coordinates - the usual (x,y) - possibly +together with a point at infinity) or `curvegroup` coordinates (some form of projective coordinates +requiring more coordinates but allowing for more efficient implementations of elliptic curve +operations). Conversions between all of these forms are provided, and under the hood these +conversions are done whenever an operation is more efficient in a different representation (or a +mixed coordinate representation is employed). + +### Points + +(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Point`), i.e. points lying on the +elliptic curve. For a curve configuration `c` and a point `p`, it may be checked that `p` +does indeed lie on `c` by calling `c.contains(p1)`. + +## Methods + +(given a choice of curve representation, e.g. use `std::ec::tecurve::affine::Curve` and use +`std::ec::tecurve::affine::Point`) + +- The **zero element** is given by `Point::zero()`, and we can verify whether a point `p: Point` is + zero by calling `p.is_zero()`. +- **Equality**: Points `p1: Point` and `p2: Point` may be checked for equality by calling + `p1.eq(p2)`. +- **Addition**: For `c: Curve` and points `p1: Point` and `p2: Point` on the curve, adding these two + points is accomplished by calling `c.add(p1,p2)`. +- **Negation**: For a point `p: Point`, `p.negate()` is its negation. +- **Subtraction**: For `c` and `p1`, `p2` as above, subtracting `p2` from `p1` is accomplished by + calling `c.subtract(p1,p2)`. +- **Scalar multiplication**: For `c` as above, `p: Point` a point on the curve and `n: Field`, + scalar multiplication is given by `c.mul(n,p)`. If instead `n :: [u1; N]`, i.e. `n` is a bit + array, the `bit_mul` method may be used instead: `c.bit_mul(n,p)` +- **Multi-scalar multiplication**: For `c` as above and arrays `n: [Field; N]` and `p: [Point; N]`, + multi-scalar multiplication is given by `c.msm(n,p)`. +- **Coordinate representation conversions**: The `into_group` method converts a point or curve + configuration in the affine representation to one in the CurveGroup representation, and + `into_affine` goes in the other direction. +- **Curve representation conversions**: `tecurve` and `montcurve` curves and points are equivalent + and may be converted between one another by calling `into_montcurve` or `into_tecurve` on their + configurations or points. `swcurve` is more general and a curve c of one of the other two types + may be converted to this representation by calling `c.into_swcurve()`, whereas a point `p` lying + on the curve given by `c` may be mapped to its corresponding `swcurve` point by calling + `c.map_into_swcurve(p)`. +- **Map-to-curve methods**: The Elligator 2 method of mapping a field element `n: Field` into a + `tecurve` or `montcurve` with configuration `c` may be called as `c.elligator2_map(n)`. For all of + the curve configurations, the SWU map-to-curve method may be called as `c.swu_map(z,n)`, where + `z: Field` depends on `Field` and `c` and must be chosen by the user (the conditions it needs to + satisfy are specified in the comments + [here](https://github.com/noir-lang/noir/blob/master/noir_stdlib/src/ec.nr)). + +## Examples + +The +[ec_baby_jubjub test](https://github.com/noir-lang/noir/blob/master/test_programs/compile_success_empty/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.29.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx b/docs/versioned_docs/version-v0.29.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx new file mode 100644 index 00000000000..4394b48f907 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx @@ -0,0 +1,98 @@ +--- +title: ECDSA Signature Verification +description: Learn about the cryptographic primitives regarding ECDSA over the secp256k1 and secp256r1 curves +keywords: [cryptographic primitives, Noir project, ecdsa, secp256k1, secp256r1, signatures] +sidebar_position: 3 +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +Noir supports ECDSA signatures verification over the secp256k1 and secp256r1 curves. + +## ecdsa_secp256k1::verify_signature + +Verifier for ECDSA Secp256k1 signatures. +See ecdsa_secp256k1::verify_signature_slice for a version that accepts slices directly. + +```rust title="ecdsa_secp256k1" showLineNumbers +pub fn verify_signature( + public_key_x: [u8; 32], + public_key_y: [u8; 32], + signature: [u8; 64], + message_hash: [u8; N] +) -> bool +``` +> Source code: noir_stdlib/src/ecdsa_secp256k1.nr#L2-L9 + + +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_secp256k1::verify_signature_slice + +Verifier for ECDSA Secp256k1 signatures where the message is a slice. + +```rust title="ecdsa_secp256k1_slice" showLineNumbers +pub fn verify_signature_slice( + public_key_x: [u8; 32], + public_key_y: [u8; 32], + signature: [u8; 64], + message_hash: [u8] +) -> bool +``` +> Source code: noir_stdlib/src/ecdsa_secp256k1.nr#L13-L20 + + + + +## ecdsa_secp256r1::verify_signature + +Verifier for ECDSA Secp256r1 signatures. +See ecdsa_secp256r1::verify_signature_slice for a version that accepts slices directly. + +```rust title="ecdsa_secp256r1" showLineNumbers +pub fn verify_signature( + public_key_x: [u8; 32], + public_key_y: [u8; 32], + signature: [u8; 64], + message_hash: [u8; N] +) -> bool +``` +> Source code: noir_stdlib/src/ecdsa_secp256r1.nr#L2-L9 + + +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); +} +``` + + + +## ecdsa_secp256r1::verify_signature + +Verifier for ECDSA Secp256r1 signatures where the message is a slice. + +```rust title="ecdsa_secp256r1_slice" showLineNumbers +pub fn verify_signature_slice( + public_key_x: [u8; 32], + public_key_y: [u8; 32], + signature: [u8; 64], + message_hash: [u8] +) -> bool +``` +> Source code: noir_stdlib/src/ecdsa_secp256r1.nr#L13-L20 + + + diff --git a/docs/versioned_docs/version-v0.29.0/noir/standard_library/cryptographic_primitives/eddsa.mdx b/docs/versioned_docs/version-v0.29.0/noir/standard_library/cryptographic_primitives/eddsa.mdx new file mode 100644 index 00000000000..c2c0624dfad --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/noir/standard_library/cryptographic_primitives/eddsa.mdx @@ -0,0 +1,37 @@ +--- +title: EdDSA Verification +description: Learn about the cryptographic primitives regarding EdDSA +keywords: [cryptographic primitives, Noir project, eddsa, signatures] +sidebar_position: 5 +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +## eddsa::eddsa_poseidon_verify + +Verifier for EdDSA signatures + +```rust +fn eddsa_poseidon_verify(public_key_x : Field, public_key_y : Field, signature_s: Field, signature_r8_x: Field, signature_r8_y: Field, message: Field) -> bool +``` + +It is also possible to specify the hash algorithm used for the signature by using the `eddsa_verify_with_hasher` function with a parameter implementing the Hasher trait. For instance, if you want to use Poseidon2 instead, you can do the following: +```rust +use dep::std::hash::poseidon2::Poseidon2Hasher; + +let mut hasher = Poseidon2Hasher::default(); +eddsa_verify_with_hasher(pub_key_a.x, pub_key_a.y, s_a, r8_a.x, r8_a.y, msg, &mut hasher); +``` + + + +## eddsa::eddsa_to_pub + +Private to public key conversion. + +Returns `(pub_key_x, pub_key_y)` + +```rust +fn eddsa_to_pub(secret : Field) -> (Field, Field) +``` + diff --git a/docs/versioned_docs/version-v0.29.0/noir/standard_library/cryptographic_primitives/hashes.mdx b/docs/versioned_docs/version-v0.29.0/noir/standard_library/cryptographic_primitives/hashes.mdx new file mode 100644 index 00000000000..3b83d9ec31a --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/noir/standard_library/cryptographic_primitives/hashes.mdx @@ -0,0 +1,257 @@ +--- +title: Hash methods +description: + Learn about the cryptographic primitives ready to use for any Noir project, including sha256, + blake2s, pedersen, mimc_bn254 and mimc +keywords: + [cryptographic primitives, Noir project, sha256, blake2s, pedersen, mimc_bn254, mimc, hash] +sidebar_position: 0 +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +## sha256 + +Given an array of bytes, returns the resulting sha256 hash. +Specify a message_size to hash only the first `message_size` bytes of the input. + +```rust title="sha256" showLineNumbers +pub fn sha256(input: [u8; N]) -> [u8; 32] +``` +> Source code: noir_stdlib/src/hash.nr#L10-L12 + + +example: +```rust title="sha256_var" showLineNumbers +let digest = std::hash::sha256_var([x as u8], 1); +``` +> Source code: test_programs/execution_success/sha256/src/main.nr#L17-L19 + + +```rust +fn main() { + let x = [163, 117, 178, 149]; // some random bytes + let hash = std::sha256::sha256_var(x, 4); +} +``` + + + + +## blake2s + +Given an array of bytes, returns an array with the Blake2 hash + +```rust title="blake2s" showLineNumbers +pub fn blake2s(input: [u8; N]) -> [u8; 32] +``` +> Source code: noir_stdlib/src/hash.nr#L16-L18 + + +example: + +```rust +fn main() { + let x = [163, 117, 178, 149]; // some random bytes + let hash = std::hash::blake2s(x); +} +``` + + + +## blake3 + +Given an array of bytes, returns an array with the Blake3 hash + +```rust title="blake3" showLineNumbers +pub fn blake3(input: [u8; N]) -> [u8; 32] +``` +> Source code: noir_stdlib/src/hash.nr#L22-L24 + + +example: + +```rust +fn main() { + let x = [163, 117, 178, 149]; // some random bytes + let hash = std::hash::blake3(x); +} +``` + + + +## pedersen_hash + +Given an array of Fields, returns the Pedersen hash. + +```rust title="pedersen_hash" showLineNumbers +pub fn pedersen_hash(input: [Field; N]) -> Field +``` +> Source code: noir_stdlib/src/hash.nr#L46-L48 + + +example: + +```rust title="pedersen-hash" showLineNumbers +use dep::std; + +fn main(x: Field, y: Field, expected_hash: Field) { + let hash = std::hash::pedersen_hash([x, y]); + assert_eq(hash, expected_hash); +} +``` +> Source code: test_programs/execution_success/pedersen_hash/src/main.nr#L1-L8 + + + + +## pedersen_commitment + +Given an array of Fields, returns the Pedersen commitment. + +```rust title="pedersen_commitment" showLineNumbers +struct PedersenPoint { + x : Field, + y : Field, +} + +pub fn pedersen_commitment(input: [Field; N]) -> PedersenPoint { +``` +> Source code: noir_stdlib/src/hash.nr#L27-L34 + + +example: + +```rust title="pedersen-commitment" showLineNumbers +use dep::std; + +fn main(x: Field, y: Field, expected_commitment: std::hash::PedersenPoint) { + let commitment = std::hash::pedersen_commitment([x, y]); + assert_eq(commitment.x, expected_commitment.x); + assert_eq(commitment.y, expected_commitment.y); +} +``` +> Source code: test_programs/execution_success/pedersen_commitment/src/main.nr#L1-L9 + + + + +## 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 title="keccak256" showLineNumbers +pub fn keccak256(input: [u8; N], message_size: u32) -> [u8; 32] +``` +> Source code: noir_stdlib/src/hash.nr#L68-L70 + + +example: + +```rust title="keccak256" showLineNumbers +use dep::std; + +fn main(x: Field, result: [u8; 32]) { + // We use the `as` keyword here to denote the fact that we want to take just the first byte from the x Field + // The padding is taken care of by the program + let digest = std::hash::keccak256([x as u8], 1); + assert(digest == result); + + //#1399: variable message 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); + + 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); + + assert(hash_a != hash_c); +} +``` +> Source code: test_programs/execution_success/keccak256/src/main.nr#L1-L22 + + + + +## 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 title="poseidon" showLineNumbers +use dep::std::hash::poseidon; +use dep::std::hash::poseidon2; + +fn main(x1: [Field; 2], y1: pub Field, x2: [Field; 4], y2: pub Field, x3: [Field; 4], y3: Field) { + let hash1 = poseidon::bn254::hash_2(x1); + assert(hash1 == y1); + + let hash2 = poseidon::bn254::hash_4(x2); + assert(hash2 == y2); + + let hash3 = poseidon2::Poseidon2::hash(x3, x3.len()); + assert(hash3 == y3); +} +``` +> Source code: test_programs/execution_success/poseidon_bn254_hash/src/main.nr#L1-L15 + + +## poseidon 2 + +Given an array of Fields, returns a new Field with the Poseidon2 Hash. Contrary to the Poseidon +function, there is only one hash and you can specify a message_size to hash only the first +`message_size` bytes of the input, + +```rust +// example for hashing the first three elements of the input +Poseidon2::hash(input, 3); +``` + +The above example for Poseidon also includes Poseidon2. + +## 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]) -> 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.29.0/noir/standard_library/cryptographic_primitives/index.md b/docs/versioned_docs/version-v0.29.0/noir/standard_library/cryptographic_primitives/index.md new file mode 100644 index 00000000000..650f30165d5 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/noir/standard_library/cryptographic_primitives/index.md @@ -0,0 +1,14 @@ +--- +title: Cryptographic Primitives +description: + Learn about the cryptographic primitives ready to use for any Noir project +keywords: + [ + cryptographic primitives, + Noir project, + ] +--- + +The Noir team is progressively adding new cryptographic primitives to the standard library. Reach out for news or if you would be interested in adding more of these calculations in Noir. + +Some methods are available thanks to the Aztec backend, not being performed using Noir. When using other backends, these methods may or may not be supplied. diff --git a/docs/versioned_docs/version-v0.29.0/noir/standard_library/cryptographic_primitives/scalar.mdx b/docs/versioned_docs/version-v0.29.0/noir/standard_library/cryptographic_primitives/scalar.mdx new file mode 100644 index 00000000000..df411ca5443 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/noir/standard_library/cryptographic_primitives/scalar.mdx @@ -0,0 +1,33 @@ +--- +title: Scalar multiplication +description: See how you can perform scalar multiplications over a fixed base in Noir +keywords: [cryptographic primitives, Noir project, scalar multiplication] +sidebar_position: 1 +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +## scalar_mul::fixed_base_embedded_curve + +Performs scalar multiplication over the embedded curve whose coordinates are defined by the +configured noir field. For the BN254 scalar field, this is BabyJubJub or Grumpkin. + +```rust title="fixed_base_embedded_curve" showLineNumbers +pub fn fixed_base_embedded_curve( + low: Field, + high: Field +) -> [Field; 2] +``` +> Source code: noir_stdlib/src/scalar_mul.nr#L27-L32 + + +example + +```rust +fn main(x : Field) { + let scal = std::scalar_mul::fixed_base_embedded_curve(x); + println(scal); +} +``` + + diff --git a/docs/versioned_docs/version-v0.29.0/noir/standard_library/cryptographic_primitives/schnorr.mdx b/docs/versioned_docs/version-v0.29.0/noir/standard_library/cryptographic_primitives/schnorr.mdx new file mode 100644 index 00000000000..b59e69c8f07 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/noir/standard_library/cryptographic_primitives/schnorr.mdx @@ -0,0 +1,64 @@ +--- +title: Schnorr Signatures +description: Learn how you can verify Schnorr signatures using Noir +keywords: [cryptographic primitives, Noir project, schnorr, signatures] +sidebar_position: 2 +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +## schnorr::verify_signature + +Verifier for Schnorr signatures over the embedded curve (for BN254 it is Grumpkin). +See schnorr::verify_signature_slice for a version that works directly on slices. + +```rust title="schnorr_verify" showLineNumbers +pub fn verify_signature( + public_key_x: Field, + public_key_y: Field, + signature: [u8; 64], + message: [u8; N] +) -> bool +``` +> Source code: noir_stdlib/src/schnorr.nr#L2-L9 + + +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() +); + +... +``` + + + +## schnorr::verify_signature_slice + +Verifier for Schnorr signatures over the embedded curve (for BN254 it is Grumpkin) +where the message is a slice. + +```rust title="schnorr_verify_slice" showLineNumbers +pub fn verify_signature_slice( + public_key_x: Field, + public_key_y: Field, + signature: [u8; 64], + message: [u8] +) -> bool +``` +> Source code: noir_stdlib/src/schnorr.nr#L13-L20 + + + diff --git a/docs/versioned_docs/version-v0.29.0/noir/standard_library/logging.md b/docs/versioned_docs/version-v0.29.0/noir/standard_library/logging.md new file mode 100644 index 00000000000..db75ef9f86f --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/noir/standard_library/logging.md @@ -0,0 +1,78 @@ +--- +title: Logging +description: + Learn how to use the println statement for debugging in Noir with this tutorial. Understand the + basics of logging in Noir and how to implement it in your code. +keywords: + [ + noir logging, + println statement, + print statement, + debugging in noir, + noir std library, + logging tutorial, + basic logging in noir, + noir logging implementation, + noir debugging techniques, + rust, + ] +--- + +The standard library provides two familiar statements you can use: `println` and `print`. Despite being a limited implementation of rust's `println!` and `print!` macros, these constructs can be useful for debugging. + +You can print the output of both statements in your Noir code by using the `nargo execute` command or the `--show-output` flag when using `nargo test` (provided there are print statements in your tests). + +It is recommended to use `nargo execute` if you want to debug failing constraints with `println` or `print` statements. This is due to every input in a test being a constant rather than a witness, so we issue an error during compilation while we only print during execution (which comes after compilation). Neither `println`, nor `print` are callable for failed constraints caught at compile time. + +Both `print` and `println` are generic functions which can work on integers, fields, strings, and even structs or expressions. Note however, that slices are currently unsupported. For example: + +```rust +struct Person { + age: Field, + height: Field, +} + +fn main(age: Field, height: Field) { + let person = Person { + age: age, + height: height, + }; + println(person); + println(age + height); + println("Hello world!"); +} +``` + +You can print different types in the same statement (including strings) with a type called `fmtstr`. It can be specified in the same way as a normal string, just prepended with an "f" character: + +```rust + let fmt_str = f"i: {i}, j: {j}"; + println(fmt_str); + + let s = myStruct { y: x, x: y }; + println(s); + + println(f"i: {i}, s: {s}"); + + println(x); + println([x, y]); + + let foo = fooStruct { my_struct: s, foo: 15 }; + println(f"s: {s}, foo: {foo}"); + + println(15); // prints 0x0f, implicit Field + println(-1 as u8); // prints 255 + println(-1 as i8); // prints -1 +``` + +Examples shown above are interchangeable between the two `print` statements: + +```rust +let person = Person { age : age, height : height }; + +println(person); +print(person); + +println("Hello world!"); // Prints with a newline at the end of the input +print("Hello world!"); // Prints the input and keeps cursor on the same line +``` diff --git a/docs/versioned_docs/version-v0.29.0/noir/standard_library/merkle_trees.md b/docs/versioned_docs/version-v0.29.0/noir/standard_library/merkle_trees.md new file mode 100644 index 00000000000..6a9ebf72ada --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/noir/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/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.as_slice()); + 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.29.0/noir/standard_library/options.md b/docs/versioned_docs/version-v0.29.0/noir/standard_library/options.md new file mode 100644 index 00000000000..a1bd4e1de5f --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/noir/standard_library/options.md @@ -0,0 +1,101 @@ +--- +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), +} +``` + +The `Option` type, already imported into your Noir program, can be used directly: + +```rust +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. + +### expect + +Asserts `self.is_some()` with a provided custom message and returns the contained `Some` value. The custom message is expected to be a format string. + +### 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.29.0/noir/standard_library/recursion.md b/docs/versioned_docs/version-v0.29.0/noir/standard_library/recursion.md new file mode 100644 index 00000000000..a93894043dc --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/noir/standard_library/recursion.md @@ -0,0 +1,88 @@ +--- +title: Recursive Proofs +description: Learn about how to write recursive proofs in Noir. +keywords: [recursion, recursive proofs, verification_key, 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. + +Read [the explainer on recursion](../../explainers/explainer-recursion.md) to know more about this function and the [guide on how to use it.](../../how_to/how-to-recursion.md) + +## The `#[recursive]` Attribute + +In Noir, the `#[recursive]` attribute is used to indicate that a circuit is designed for recursive proof generation. When applied, it informs the compiler and the tooling that the circuit should be compiled in a way that makes its proofs suitable for recursive verification. This attribute eliminates the need for manual flagging of recursion at the tooling level, streamlining the proof generation process for recursive circuits. + +### Example usage with `#[recursive]` + +```rust +#[recursive] +fn main(x: Field, y: pub Field) { + assert(x == y, "x and y are not equal"); +} + +// This marks the circuit as recursion-friendly and indicates that proofs generated from this circuit +// are intended for recursive verification. +``` + +By incorporating this attribute directly in the circuit's definition, tooling like Nargo and NoirJS can automatically execute recursive-specific duties for Noir programs (e.g. recursive-friendly proof artifact generation) without additional flags or configurations. + +## Verifying Recursive Proofs + +```rust +#[foreign(recursive_aggregation)] +pub fn verify_proof(verification_key: [Field], proof: [Field], public_inputs: [Field], key_hash: Field) {} +``` + +:::info + +This is a black box function. Read [this section](./black_box_fns) to learn more about black box functions in Noir. + +::: + +## Example usage + +```rust +use dep::std; + +fn main( + verification_key : [Field; 114], + proof : [Field; 93], + public_inputs : [Field; 1], + key_hash : Field, + proof_b : [Field; 93], +) { + std::verify_proof( + verification_key.as_slice(), + proof.as_slice(), + public_inputs.as_slice(), + key_hash + ); + + std::verify_proof( + verification_key.as_slice(), + proof_b.as_slice(), + public_inputs.as_slice(), + key_hash + ); +} +``` + +You can see a full example of recursive proofs in [this example recursion demo repo](https://github.com/noir-lang/noir-examples/tree/master/recursion). + +## 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. + +### `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. diff --git a/docs/versioned_docs/version-v0.29.0/noir/standard_library/traits.md b/docs/versioned_docs/version-v0.29.0/noir/standard_library/traits.md new file mode 100644 index 00000000000..04dc40f0dac --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/noir/standard_library/traits.md @@ -0,0 +1,410 @@ +--- +title: Traits +description: Noir's stdlib provides a few commonly used traits. +keywords: [traits, trait, interface, protocol, default, add, eq] +--- + +## `std::default` + +### `std::default::Default` + +```rust title="default-trait" showLineNumbers +trait Default { + fn default() -> Self; +} +``` +> Source code: noir_stdlib/src/default.nr#L1-L5 + + +Constructs a default value of a type. + +Implementations: +```rust +impl Default for Field { .. } + +impl Default for i8 { .. } +impl Default for i16 { .. } +impl Default for i32 { .. } +impl Default for i64 { .. } + +impl Default for u8 { .. } +impl Default for u16 { .. } +impl Default for u32 { .. } +impl Default for u64 { .. } + +impl Default for () { .. } +impl Default for bool { .. } + +impl Default for [T; N] + where T: Default { .. } + +impl Default for [T] { .. } + +impl Default for (A, B) + where A: Default, B: Default { .. } + +impl Default for (A, B, C) + where A: Default, B: Default, C: Default { .. } + +impl Default for (A, B, C, D) + where A: Default, B: Default, C: Default, D: Default { .. } + +impl Default for (A, B, C, D, E) + where A: Default, B: Default, C: Default, D: Default, E: Default { .. } +``` + +For primitive integer types, the return value of `default` is `0`. Container +types such as arrays are filled with default values of their element type, +except slices whose length is unknown and thus defaulted to zero. + + +## `std::convert` + +### `std::convert::From` + +```rust title="from-trait" showLineNumbers +trait From { + fn from(input: T) -> Self; +} +``` +> Source code: noir_stdlib/src/convert.nr#L1-L5 + + +The `From` trait defines how to convert from a given type `T` to the type on which the trait is implemented. + +The Noir standard library provides a number of implementations of `From` between primitive types. +```rust title="from-impls" showLineNumbers +// Unsigned integers + +impl From for u32 { fn from(value: u8) -> u32 { value as u32 } } + +impl From for u64 { fn from(value: u8) -> u64 { value as u64 } } +impl From for u64 { fn from(value: u32) -> u64 { value as u64 } } + +impl From for Field { fn from(value: u8) -> Field { value as Field } } +impl From for Field { fn from(value: u32) -> Field { value as Field } } +impl From for Field { fn from(value: u64) -> Field { value as Field } } + +// Signed integers + +impl From for i32 { fn from(value: i8) -> i32 { value as i32 } } + +impl From for i64 { fn from(value: i8) -> i64 { value as i64 } } +impl From for i64 { fn from(value: i32) -> i64 { value as i64 } } + +// Booleans +impl From for u8 { fn from(value: bool) -> u8 { value as u8 } } +impl From for u32 { fn from(value: bool) -> u32 { value as u32 } } +impl From for u64 { fn from(value: bool) -> u64 { value as u64 } } +impl From for i8 { fn from(value: bool) -> i8 { value as i8 } } +impl From for i32 { fn from(value: bool) -> i32 { value as i32 } } +impl From for i64 { fn from(value: bool) -> i64 { value as i64 } } +impl From for Field { fn from(value: bool) -> Field { value as Field } } +``` +> Source code: noir_stdlib/src/convert.nr#L25-L52 + + +#### When to implement `From` + +As a general rule of thumb, `From` may be implemented in the [situations where it would be suitable in Rust](https://doc.rust-lang.org/std/convert/trait.From.html#when-to-implement-from): + +- The conversion is *infallible*: Noir does not provide an equivalent to Rust's `TryFrom`, if the conversion can fail then provide a named method instead. +- The conversion is *lossless*: semantically, it should not lose or discard information. For example, `u32: From` can losslessly convert any `u16` into a valid `u32` such that the original `u16` can be recovered. On the other hand, `u16: From` should not be implemented as `2**16` is a `u32` which cannot be losslessly converted into a `u16`. +- The conversion is *value-preserving*: the conceptual kind and meaning of the resulting value is the same, even though the Noir type and technical representation might be different. While it's possible to infallibly and losslessly convert a `u8` into a `str<2>` hex representation, `4u8` and `"04"` are too different for `str<2>: From` to be implemented. +- The conversion is *obvious*: it's the only reasonable conversion between the two types. If there's ambiguity on how to convert between them such that the same input could potentially map to two different values then a named method should be used. For instance rather than implementing `U128: From<[u8; 16]>`, the methods `U128::from_le_bytes` and `U128::from_be_bytes` are used as otherwise the endianness of the array would be ambiguous, resulting in two potential values of `U128` from the same byte array. + +One additional recommendation specific to Noir is: +- The conversion is *efficient*: it's relatively cheap to convert between the two types. Due to being a ZK DSL, it's more important to avoid unnecessary computation compared to Rust. If the implementation of `From` would encourage users to perform unnecessary conversion, resulting in additional proving time, then it may be preferable to expose functionality such that this conversion may be avoided. + +### `std::convert::Into` + +The `Into` trait is defined as the reciprocal of `From`. It should be easy to convince yourself that if we can convert to type `A` from type `B`, then it's possible to convert type `B` into type `A`. + +For this reason, implementing `From` on a type will automatically generate a matching `Into` implementation. One should always prefer implementing `From` over `Into` as implementing `Into` will not generate a matching `From` implementation. + +```rust title="into-trait" showLineNumbers +trait Into { + fn into(self) -> T; +} + +impl Into for U where T: From { + fn into(self) -> T { + T::from(self) + } +} +``` +> Source code: noir_stdlib/src/convert.nr#L13-L23 + + +`Into` is most useful when passing function arguments where the types don't quite match up with what the function expects. In this case, the compiler has enough type information to perform the necessary conversion by just appending `.into()` onto the arguments in question. + + +## `std::cmp` + +### `std::cmp::Eq` + +```rust title="eq-trait" showLineNumbers +trait Eq { + fn eq(self, other: Self) -> bool; +} +``` +> Source code: noir_stdlib/src/cmp.nr#L1-L5 + + +Returns `true` if `self` is equal to `other`. Implementing this trait on a type +allows the type to be used with `==` and `!=`. + +Implementations: +```rust +impl Eq for Field { .. } + +impl Eq for i8 { .. } +impl Eq for i16 { .. } +impl Eq for i32 { .. } +impl Eq for i64 { .. } + +impl Eq for u8 { .. } +impl Eq for u16 { .. } +impl Eq for u32 { .. } +impl Eq for u64 { .. } + +impl Eq for () { .. } +impl Eq for bool { .. } + +impl Eq for [T; N] + where T: Eq { .. } + +impl Eq for [T] + where T: Eq { .. } + +impl Eq for (A, B) + where A: Eq, B: Eq { .. } + +impl Eq for (A, B, C) + where A: Eq, B: Eq, C: Eq { .. } + +impl Eq for (A, B, C, D) + where A: Eq, B: Eq, C: Eq, D: Eq { .. } + +impl Eq for (A, B, C, D, E) + where A: Eq, B: Eq, C: Eq, D: Eq, E: Eq { .. } +``` + +### `std::cmp::Ord` + +```rust title="ord-trait" showLineNumbers +trait Ord { + fn cmp(self, other: Self) -> Ordering; +} +``` +> Source code: noir_stdlib/src/cmp.nr#L102-L106 + + +`a.cmp(b)` compares two values returning `Ordering::less()` if `a < b`, +`Ordering::equal()` if `a == b`, or `Ordering::greater()` if `a > b`. +Implementing this trait on a type allows `<`, `<=`, `>`, and `>=` to be +used on values of the type. + +`std::cmp` also provides `max` and `min` functions for any type which implements the `Ord` trait. + +Implementations: + +```rust +impl Ord for u8 { .. } +impl Ord for u16 { .. } +impl Ord for u32 { .. } +impl Ord for u64 { .. } + +impl Ord for i8 { .. } +impl Ord for i16 { .. } +impl Ord for i32 { .. } + +impl Ord for i64 { .. } + +impl Ord for () { .. } +impl Ord for bool { .. } + +impl Ord for [T; N] + where T: Ord { .. } + +impl Ord for [T] + where T: Ord { .. } + +impl Ord for (A, B) + where A: Ord, B: Ord { .. } + +impl Ord for (A, B, C) + where A: Ord, B: Ord, C: Ord { .. } + +impl Ord for (A, B, C, D) + where A: Ord, B: Ord, C: Ord, D: Ord { .. } + +impl Ord for (A, B, C, D, E) + where A: Ord, B: Ord, C: Ord, D: Ord, E: Ord { .. } +``` + +## `std::ops` + +### `std::ops::Add`, `std::ops::Sub`, `std::ops::Mul`, and `std::ops::Div` + +These traits abstract over addition, subtraction, multiplication, and division respectively. +Implementing these traits for a given type will also allow that type to be used with the corresponding operator +for that trait (`+` for Add, etc) in addition to the normal method names. + +```rust title="add-trait" showLineNumbers +trait Add { + fn add(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L1-L5 + +```rust title="sub-trait" showLineNumbers +trait Sub { + fn sub(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L17-L21 + +```rust title="mul-trait" showLineNumbers +trait Mul { + fn mul(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L33-L37 + +```rust title="div-trait" showLineNumbers +trait Div { + fn div(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L49-L53 + + +The implementations block below is given for the `Add` trait, but the same types that implement +`Add` also implement `Sub`, `Mul`, and `Div`. + +Implementations: +```rust +impl Add for Field { .. } + +impl Add for i8 { .. } +impl Add for i16 { .. } +impl Add for i32 { .. } +impl Add for i64 { .. } + +impl Add for u8 { .. } +impl Add for u16 { .. } +impl Add for u32 { .. } +impl Add for u64 { .. } +``` + +### `std::ops::Rem` + +```rust title="rem-trait" showLineNumbers +trait Rem{ + fn rem(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L65-L69 + + +`Rem::rem(a, b)` is the remainder function returning the result of what is +left after dividing `a` and `b`. Implementing `Rem` allows the `%` operator +to be used with the implementation type. + +Unlike other numeric traits, `Rem` is not implemented for `Field`. + +Implementations: +```rust +impl Rem for u8 { fn rem(self, other: u8) -> u8 { self % other } } +impl Rem for u16 { fn rem(self, other: u16) -> u16 { self % other } } +impl Rem for u32 { fn rem(self, other: u32) -> u32 { self % other } } +impl Rem for u64 { fn rem(self, other: u64) -> u64 { self % other } } + +impl Rem for i8 { fn rem(self, other: i8) -> i8 { self % other } } +impl Rem for i16 { fn rem(self, other: i16) -> i16 { self % other } } +impl Rem for i32 { fn rem(self, other: i32) -> i32 { self % other } } +impl Rem for i64 { fn rem(self, other: i64) -> i64 { self % other } } +``` + +### `std::ops::{ BitOr, BitAnd, BitXor }` + +```rust title="bitor-trait" showLineNumbers +trait BitOr { + fn bitor(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L79-L83 + +```rust title="bitand-trait" showLineNumbers +trait BitAnd { + fn bitand(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L95-L99 + +```rust title="bitxor-trait" showLineNumbers +trait BitXor { + fn bitxor(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L111-L115 + + +Traits for the bitwise operations `|`, `&`, and `^`. + +Implementing `BitOr`, `BitAnd` or `BitXor` for a type allows the `|`, `&`, or `^` operator respectively +to be used with the type. + +The implementations block below is given for the `BitOr` trait, but the same types that implement +`BitOr` also implement `BitAnd` and `BitXor`. + +Implementations: +```rust +impl BitOr for bool { fn bitor(self, other: bool) -> bool { self | other } } + +impl BitOr for u8 { fn bitor(self, other: u8) -> u8 { self | other } } +impl BitOr for u16 { fn bitor(self, other: u16) -> u16 { self | other } } +impl BitOr for u32 { fn bitor(self, other: u32) -> u32 { self | other } } +impl BitOr for u64 { fn bitor(self, other: u64) -> u64 { self | other } } + +impl BitOr for i8 { fn bitor(self, other: i8) -> i8 { self | other } } +impl BitOr for i16 { fn bitor(self, other: i16) -> i16 { self | other } } +impl BitOr for i32 { fn bitor(self, other: i32) -> i32 { self | other } } +impl BitOr for i64 { fn bitor(self, other: i64) -> i64 { self | other } } +``` + +### `std::ops::{ Shl, Shr }` + +```rust title="shl-trait" showLineNumbers +trait Shl { + fn shl(self, other: u8) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L127-L131 + +```rust title="shr-trait" showLineNumbers +trait Shr { + fn shr(self, other: u8) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L142-L146 + + +Traits for a bit shift left and bit shift right. + +Implementing `Shl` for a type allows the left shift operator (`<<`) to be used with the implementation type. +Similarly, implementing `Shr` allows the right shift operator (`>>`) to be used with the type. + +Note that bit shifting is not currently implemented for signed types. + +The implementations block below is given for the `Shl` trait, but the same types that implement +`Shl` also implement `Shr`. + +Implementations: +```rust +impl Shl for u8 { fn shl(self, other: u8) -> u8 { self << other } } +impl Shl for u16 { fn shl(self, other: u16) -> u16 { self << other } } +impl Shl for u32 { fn shl(self, other: u32) -> u32 { self << other } } +impl Shl for u64 { fn shl(self, other: u64) -> u64 { self << other } } +``` diff --git a/docs/versioned_docs/version-v0.29.0/noir/standard_library/zeroed.md b/docs/versioned_docs/version-v0.29.0/noir/standard_library/zeroed.md new file mode 100644 index 00000000000..f450fecdd36 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/noir/standard_library/zeroed.md @@ -0,0 +1,26 @@ +--- +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 +- Slice +- String +- Tuple +- Function + +Using it on other types could result in unexpected behavior. diff --git a/docs/versioned_docs/version-v0.29.0/reference/NoirJS/backend_barretenberg/.nojekyll b/docs/versioned_docs/version-v0.29.0/reference/NoirJS/backend_barretenberg/.nojekyll new file mode 100644 index 00000000000..e2ac6616add --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/reference/NoirJS/backend_barretenberg/.nojekyll @@ -0,0 +1 @@ +TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.29.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md b/docs/versioned_docs/version-v0.29.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md new file mode 100644 index 00000000000..d7249d24330 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md @@ -0,0 +1,160 @@ +# BarretenbergBackend + +## Extends + +- `BarretenbergVerifierBackend` + +## Implements + +- [`Backend`](../index.md#backend) + +## Constructors + +### new BarretenbergBackend(acirCircuit, options) + +```ts +new BarretenbergBackend(acirCircuit, options): BarretenbergBackend +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `acirCircuit` | `CompiledCircuit` | +| `options` | [`BackendOptions`](../type-aliases/BackendOptions.md) | + +#### Returns + +[`BarretenbergBackend`](BarretenbergBackend.md) + +#### Inherited from + +BarretenbergVerifierBackend.constructor + +## Properties + +| Property | Type | Description | Inheritance | +| :------ | :------ | :------ | :------ | +| `acirComposer` | `any` | - | BarretenbergVerifierBackend.acirComposer | +| `acirUncompressedBytecode` | `Uint8Array` | - | BarretenbergVerifierBackend.acirUncompressedBytecode | +| `api` | `Barretenberg` | - | BarretenbergVerifierBackend.api | +| `options` | [`BackendOptions`](../type-aliases/BackendOptions.md) | - | BarretenbergVerifierBackend.options | + +## Methods + +### destroy() + +```ts +destroy(): Promise +``` + +#### Returns + +`Promise`\<`void`\> + +#### Inherited from + +BarretenbergVerifierBackend.destroy + +*** + +### generateProof() + +```ts +generateProof(compressedWitness): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `compressedWitness` | `Uint8Array` | + +#### Returns + +`Promise`\<`ProofData`\> + +#### Description + +Generates a proof + +*** + +### generateRecursiveProofArtifacts() + +```ts +generateRecursiveProofArtifacts(proofData, numOfPublicInputs): Promise +``` + +Generates artifacts that will be passed to a circuit that will verify this proof. + +Instead of passing the proof and verification key as a byte array, we pass them +as fields which makes it cheaper to verify in a circuit. + +The proof that is passed here will have been created using a circuit +that has the #[recursive] attribute on its `main` method. + +The number of public inputs denotes how many public inputs are in the inner proof. + +#### Parameters + +| Parameter | Type | Default value | +| :------ | :------ | :------ | +| `proofData` | `ProofData` | `undefined` | +| `numOfPublicInputs` | `number` | `0` | + +#### Returns + +`Promise`\<`object`\> + +#### Example + +```typescript +const artifacts = await backend.generateRecursiveProofArtifacts(proof, numOfPublicInputs); +``` + +*** + +### getVerificationKey() + +```ts +getVerificationKey(): Promise +``` + +#### Returns + +`Promise`\<`Uint8Array`\> + +#### Inherited from + +BarretenbergVerifierBackend.getVerificationKey + +*** + +### verifyProof() + +```ts +verifyProof(proofData): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `proofData` | `ProofData` | + +#### Returns + +`Promise`\<`boolean`\> + +#### Inherited from + +BarretenbergVerifierBackend.verifyProof + +#### Description + +Verifies 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.29.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergVerifier.md b/docs/versioned_docs/version-v0.29.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergVerifier.md new file mode 100644 index 00000000000..500276ea748 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergVerifier.md @@ -0,0 +1,58 @@ +# BarretenbergVerifier + +## Constructors + +### new BarretenbergVerifier(options) + +```ts +new BarretenbergVerifier(options): BarretenbergVerifier +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `options` | [`BackendOptions`](../type-aliases/BackendOptions.md) | + +#### Returns + +[`BarretenbergVerifier`](BarretenbergVerifier.md) + +## Methods + +### destroy() + +```ts +destroy(): Promise +``` + +#### Returns + +`Promise`\<`void`\> + +*** + +### verifyProof() + +```ts +verifyProof(proofData, verificationKey): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `proofData` | `ProofData` | +| `verificationKey` | `Uint8Array` | + +#### Returns + +`Promise`\<`boolean`\> + +#### Description + +Verifies 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.29.0/reference/NoirJS/backend_barretenberg/index.md b/docs/versioned_docs/version-v0.29.0/reference/NoirJS/backend_barretenberg/index.md new file mode 100644 index 00000000000..64971973196 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/reference/NoirJS/backend_barretenberg/index.md @@ -0,0 +1,59 @@ +# backend_barretenberg + +## Exports + +### Classes + +| Class | Description | +| :------ | :------ | +| [BarretenbergBackend](classes/BarretenbergBackend.md) | - | +| [BarretenbergVerifier](classes/BarretenbergVerifier.md) | - | + +### Type Aliases + +| Type alias | Description | +| :------ | :------ | +| [BackendOptions](type-aliases/BackendOptions.md) | - | + +## References + +### CompiledCircuit + +Renames and re-exports [Backend](index.md#backend) + +*** + +### ProofData + +Renames and re-exports [Backend](index.md#backend) + +## Variables + +### Backend + +```ts +Backend: any; +``` + +## Functions + +### publicInputsToWitnessMap() + +```ts +publicInputsToWitnessMap(publicInputs, abi): Backend +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `publicInputs` | `string`[] | +| `abi` | `Abi` | + +#### Returns + +[`Backend`](index.md#backend) + +*** + +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.29.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md b/docs/versioned_docs/version-v0.29.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md new file mode 100644 index 00000000000..b49a479f4f4 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md @@ -0,0 +1,21 @@ +# 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 | +| :------ | :------ | :------ | +| `memory` | `object` | - | +| `memory.maximum` | `number` | - | +| `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.29.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs b/docs/versioned_docs/version-v0.29.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs new file mode 100644 index 00000000000..d7d5128f9e3 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs @@ -0,0 +1,4 @@ +// @ts-check +/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ +const typedocSidebar = { items: [{"type":"category","label":"Classes","items":[{"type":"doc","id":"reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend","label":"BarretenbergBackend"},{"type":"doc","id":"reference/NoirJS/backend_barretenberg/classes/BarretenbergVerifier","label":"BarretenbergVerifier"}]},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions","label":"BackendOptions"}]}]}; +module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/.nojekyll b/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/.nojekyll new file mode 100644 index 00000000000..e2ac6616add --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/.nojekyll @@ -0,0 +1 @@ +TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/classes/Noir.md b/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/classes/Noir.md new file mode 100644 index 00000000000..45dd62ee57e --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/classes/Noir.md @@ -0,0 +1,132 @@ +# Noir + +## Constructors + +### new Noir(circuit, backend) + +```ts +new Noir(circuit, backend?): Noir +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `circuit` | `CompiledCircuit` | +| `backend`? | `any` | + +#### 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) +``` + +*** + +### generateProof() + +```ts +generateProof(inputs, foreignCallHandler?): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `inputs` | `InputMap` | +| `foreignCallHandler`? | [`ForeignCallHandler`](../type-aliases/ForeignCallHandler.md) | + +#### Returns + +`Promise`\<`ProofData`\> + +#### Description + +Generates a witness and a proof given an object as input. + +#### Example + +```typescript +async generateProof(input) +``` + +*** + +### verifyProof() + +```ts +verifyProof(proofData): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `proofData` | `ProofData` | + +#### Returns + +`Promise`\<`boolean`\> + +#### Description + +Instantiates the verification key and verifies a proof. + +#### Example + +```typescript +async verifyProof(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.29.0/reference/NoirJS/noir_js/functions/and.md b/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/functions/and.md new file mode 100644 index 00000000000..c783283e396 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/functions/and.md @@ -0,0 +1,22 @@ +# and() + +```ts +and(lhs, rhs): string +``` + +Performs a bitwise AND operation between `lhs` and `rhs` + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `lhs` | `string` | | +| `rhs` | `string` | | + +## Returns + +`string` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/functions/blake2s256.md b/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/functions/blake2s256.md new file mode 100644 index 00000000000..7882d0da8d5 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/functions/blake2s256.md @@ -0,0 +1,21 @@ +# blake2s256() + +```ts +blake2s256(inputs): Uint8Array +``` + +Calculates the Blake2s256 hash of the input bytes + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `inputs` | `Uint8Array` | | + +## Returns + +`Uint8Array` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md b/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md new file mode 100644 index 00000000000..5e3cd53e9d3 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md @@ -0,0 +1,28 @@ +# ecdsa\_secp256k1\_verify() + +```ts +ecdsa_secp256k1_verify( + hashed_msg, + public_key_x_bytes, + public_key_y_bytes, + signature): boolean +``` + +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.29.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md b/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md new file mode 100644 index 00000000000..0b20ff68957 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md @@ -0,0 +1,28 @@ +# ecdsa\_secp256r1\_verify() + +```ts +ecdsa_secp256r1_verify( + hashed_msg, + public_key_x_bytes, + public_key_y_bytes, + signature): boolean +``` + +Verifies a ECDSA signature over the secp256r1 curve. + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `hashed_msg` | `Uint8Array` | | +| `public_key_x_bytes` | `Uint8Array` | | +| `public_key_y_bytes` | `Uint8Array` | | +| `signature` | `Uint8Array` | | + +## Returns + +`boolean` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/functions/keccak256.md b/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/functions/keccak256.md new file mode 100644 index 00000000000..d10f155ce86 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/functions/keccak256.md @@ -0,0 +1,21 @@ +# keccak256() + +```ts +keccak256(inputs): Uint8Array +``` + +Calculates the Keccak256 hash of the input bytes + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `inputs` | `Uint8Array` | | + +## Returns + +`Uint8Array` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/functions/sha256.md b/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/functions/sha256.md new file mode 100644 index 00000000000..6ba4ecac022 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/functions/sha256.md @@ -0,0 +1,21 @@ +# sha256() + +```ts +sha256(inputs): Uint8Array +``` + +Calculates the SHA256 hash of the input bytes + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `inputs` | `Uint8Array` | | + +## Returns + +`Uint8Array` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/functions/xor.md b/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/functions/xor.md new file mode 100644 index 00000000000..8d762b895d3 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/functions/xor.md @@ -0,0 +1,22 @@ +# xor() + +```ts +xor(lhs, rhs): string +``` + +Performs a bitwise XOR operation between `lhs` and `rhs` + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `lhs` | `string` | | +| `rhs` | `string` | | + +## Returns + +`string` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/index.md b/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/index.md new file mode 100644 index 00000000000..cca6b3ace41 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/index.md @@ -0,0 +1,54 @@ +# noir_js + +## Exports + +### Classes + +| Class | Description | +| :------ | :------ | +| [Noir](classes/Noir.md) | - | + +### Type Aliases + +| Type alias | Description | +| :------ | :------ | +| [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) | - | +| [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) | Verifies a ECDSA signature over the secp256k1 curve. | +| [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` | + +## References + +### CompiledCircuit + +Renames and re-exports [InputMap](index.md#inputmap) + +*** + +### ProofData + +Renames and re-exports [InputMap](index.md#inputmap) + +## Variables + +### InputMap + +```ts +InputMap: any; +``` + +*** + +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.29.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md b/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md new file mode 100644 index 00000000000..812b8b16481 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md @@ -0,0 +1,24 @@ +# ForeignCallHandler + +```ts +type ForeignCallHandler: (name, inputs) => Promise; +``` + +A callback which performs an foreign call and returns the response. + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `name` | `string` | The identifier for the type of foreign call being performed. | +| `inputs` | [`ForeignCallInput`](ForeignCallInput.md)[] | An array of hex encoded inputs to the foreign call. | + +## Returns + +`Promise`\<[`ForeignCallOutput`](ForeignCallOutput.md)[]\> + +outputs - An array of hex encoded outputs containing the results of the foreign call. + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md b/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md new file mode 100644 index 00000000000..dd95809186a --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md @@ -0,0 +1,9 @@ +# ForeignCallInput + +```ts +type ForeignCallInput: string[]; +``` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md b/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md new file mode 100644 index 00000000000..b71fb78a946 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md @@ -0,0 +1,9 @@ +# ForeignCallOutput + +```ts +type ForeignCallOutput: string | string[]; +``` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md b/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md new file mode 100644 index 00000000000..258c46f9d0c --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md @@ -0,0 +1,9 @@ +# WitnessMap + +```ts +type WitnessMap: Map; +``` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs b/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs new file mode 100644 index 00000000000..c6d8125eaad --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs @@ -0,0 +1,4 @@ +// @ts-check +/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ +const typedocSidebar = { items: [{"type":"category","label":"Classes","items":[{"type":"doc","id":"reference/NoirJS/noir_js/classes/Noir","label":"Noir"}]},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ForeignCallHandler","label":"ForeignCallHandler"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ForeignCallInput","label":"ForeignCallInput"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ForeignCallOutput","label":"ForeignCallOutput"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/WitnessMap","label":"WitnessMap"}]},{"type":"category","label":"Functions","items":[{"type":"doc","id":"reference/NoirJS/noir_js/functions/and","label":"and"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/blake2s256","label":"blake2s256"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify","label":"ecdsa_secp256k1_verify"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify","label":"ecdsa_secp256r1_verify"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/keccak256","label":"keccak256"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/sha256","label":"sha256"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/xor","label":"xor"}]}]}; +module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_wasm/.nojekyll b/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_wasm/.nojekyll new file mode 100644 index 00000000000..e2ac6616add --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_wasm/.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.29.0/reference/NoirJS/noir_wasm/functions/compile.md b/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_wasm/functions/compile.md new file mode 100644 index 00000000000..6faf763b37f --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_wasm/functions/compile.md @@ -0,0 +1,51 @@ +# compile() + +```ts +compile( + fileManager, + projectPath?, + logFn?, +debugLogFn?): Promise +``` + +Compiles a Noir project + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `fileManager` | `FileManager` | The file manager to use | +| `projectPath`? | `string` | The path to the project inside the file manager. Defaults to the root of the file manager | +| `logFn`? | `LogFn` | A logging function. If not provided, console.log will be used | +| `debugLogFn`? | `LogFn` | A debug logging function. If not provided, logFn will be used | + +## Returns + +`Promise`\<[`ProgramCompilationArtifacts`](../index.md#programcompilationartifacts)\> + +## Example + +```typescript +// Node.js + +import { compile_program, createFileManager } from '@noir-lang/noir_wasm'; + +const fm = createFileManager(myProjectPath); +const myCompiledCode = await compile_program(fm); +``` + +```typescript +// Browser + +import { compile_program, createFileManager } from '@noir-lang/noir_wasm'; + +const fm = createFileManager('/'); +for (const path of files) { + await fm.writeFile(path, await getFileAsStream(path)); +} +const myCompiledCode = await compile_program(fm); +``` + +*** + +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.29.0/reference/NoirJS/noir_wasm/functions/compile_contract.md b/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_wasm/functions/compile_contract.md new file mode 100644 index 00000000000..7d0b39a43ef --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_wasm/functions/compile_contract.md @@ -0,0 +1,51 @@ +# compile\_contract() + +```ts +compile_contract( + fileManager, + projectPath?, + logFn?, +debugLogFn?): Promise +``` + +Compiles a Noir project + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `fileManager` | `FileManager` | The file manager to use | +| `projectPath`? | `string` | The path to the project inside the file manager. Defaults to the root of the file manager | +| `logFn`? | `LogFn` | A logging function. If not provided, console.log will be used | +| `debugLogFn`? | `LogFn` | A debug logging function. If not provided, logFn will be used | + +## Returns + +`Promise`\<[`ContractCompilationArtifacts`](../index.md#contractcompilationartifacts)\> + +## Example + +```typescript +// Node.js + +import { compile_contract, createFileManager } from '@noir-lang/noir_wasm'; + +const fm = createFileManager(myProjectPath); +const myCompiledCode = await compile_contract(fm); +``` + +```typescript +// Browser + +import { compile_contract, createFileManager } from '@noir-lang/noir_wasm'; + +const fm = createFileManager('/'); +for (const path of files) { + await fm.writeFile(path, await getFileAsStream(path)); +} +const myCompiledCode = await compile_contract(fm); +``` + +*** + +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.29.0/reference/NoirJS/noir_wasm/functions/createFileManager.md b/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_wasm/functions/createFileManager.md new file mode 100644 index 00000000000..7e65c1d69c7 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_wasm/functions/createFileManager.md @@ -0,0 +1,21 @@ +# createFileManager() + +```ts +createFileManager(dataDir): FileManager +``` + +Creates a new FileManager instance based on fs in node and memfs in the browser (via webpack alias) + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `dataDir` | `string` | root of the file system | + +## Returns + +`FileManager` + +*** + +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.29.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md b/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md new file mode 100644 index 00000000000..fcea9275341 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md @@ -0,0 +1,21 @@ +# inflateDebugSymbols() + +```ts +inflateDebugSymbols(debugSymbols): any +``` + +Decompresses and decodes the debug symbols + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `debugSymbols` | `string` | The base64 encoded debug symbols | + +## Returns + +`any` + +*** + +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.29.0/reference/NoirJS/noir_wasm/index.md b/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_wasm/index.md new file mode 100644 index 00000000000..b6e0f9d1bc0 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_wasm/index.md @@ -0,0 +1,49 @@ +# noir_wasm + +## Exports + +### Functions + +| Function | Description | +| :------ | :------ | +| [compile](functions/compile.md) | Compiles a Noir project | +| [compile\_contract](functions/compile_contract.md) | Compiles a Noir project | +| [createFileManager](functions/createFileManager.md) | Creates a new FileManager instance based on fs in node and memfs in the browser (via webpack alias) | +| [inflateDebugSymbols](functions/inflateDebugSymbols.md) | Decompresses and decodes the debug symbols | + +## References + +### compile\_program + +Renames and re-exports [compile](functions/compile.md) + +## Interfaces + +### ContractCompilationArtifacts + +The compilation artifacts of a given contract. + +#### Properties + +| Property | Type | Description | +| :------ | :------ | :------ | +| `contract` | `ContractArtifact` | The compiled contract. | +| `warnings` | `unknown`[] | Compilation warnings. | + +*** + +### ProgramCompilationArtifacts + +The compilation artifacts of a given program. + +#### Properties + +| Property | Type | Description | +| :------ | :------ | :------ | +| `name` | `string` | not part of the compilation output, injected later | +| `program` | `ProgramArtifact` | The compiled contract. | +| `warnings` | `unknown`[] | Compilation warnings. | + +*** + +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.29.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs b/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs new file mode 100644 index 00000000000..e0870710349 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs @@ -0,0 +1,4 @@ +// @ts-check +/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ +const typedocSidebar = { items: [{"type":"doc","id":"reference/NoirJS/noir_wasm/index","label":"API"},{"type":"category","label":"Functions","items":[{"type":"doc","id":"reference/NoirJS/noir_wasm/functions/compile","label":"compile"},{"type":"doc","id":"reference/NoirJS/noir_wasm/functions/compile_contract","label":"compile_contract"},{"type":"doc","id":"reference/NoirJS/noir_wasm/functions/createFileManager","label":"createFileManager"},{"type":"doc","id":"reference/NoirJS/noir_wasm/functions/inflateDebugSymbols","label":"inflateDebugSymbols"}]}]}; +module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.29.0/reference/_category_.json b/docs/versioned_docs/version-v0.29.0/reference/_category_.json new file mode 100644 index 00000000000..5b6a20a609a --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/reference/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 4, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.29.0/reference/debugger/_category_.json b/docs/versioned_docs/version-v0.29.0/reference/debugger/_category_.json new file mode 100644 index 00000000000..27869205ad3 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/reference/debugger/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Debugger", + "position": 1, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.29.0/reference/debugger/debugger_known_limitations.md b/docs/versioned_docs/version-v0.29.0/reference/debugger/debugger_known_limitations.md new file mode 100644 index 00000000000..936d416ac4b --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/reference/debugger/debugger_known_limitations.md @@ -0,0 +1,59 @@ +--- +title: Known limitations +description: + An overview of known limitations of the current version of the Noir debugger +keywords: + [ + Nargo, + Noir Debugger, + VS Code, + ] +sidebar_position: 2 +--- + +# Debugger Known Limitations + +There are currently some limits to what the debugger can observe. + +## Mutable references + +The debugger is currently blind to any state mutated via a mutable reference. For example, in: + +``` +let mut x = 1; +let y = &mut x; +*y = 2; +``` + +The update on `x` will not be observed by the debugger. That means, when running `vars` from the debugger REPL, or inspecting the _local variables_ pane in the VS Code debugger, `x` will appear with value 1 despite having executed `*y = 2;`. + +## Variables of type function or mutable references are opaque + +When inspecting variables, any variable of type `Function` or `MutableReference` will render its value as `<>` or `<>`. + +## Debugger instrumentation affects resulting ACIR + +In order to make the state of local variables observable, the debugger compiles Noir circuits interleaving foreign calls that track any mutations to them. While this works (except in the cases described above) and doesn't introduce any behavior changes, it does as a side effect produce bigger bytecode. In particular, when running the command `opcodes` on the REPL debugger, you will notice Unconstrained VM blocks that look like this: + +``` +... +5 BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [], q_c: 2 }), Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(2))], q_c: 0 })] + | outputs=[] + 5.0 | Mov { destination: RegisterIndex(2), source: RegisterIndex(0) } + 5.1 | Mov { destination: RegisterIndex(3), source: RegisterIndex(1) } + 5.2 | Const { destination: RegisterIndex(0), value: Value { inner: 0 } } + 5.3 | Const { destination: RegisterIndex(1), value: Value { inner: 0 } } + 5.4 | Mov { destination: RegisterIndex(2), source: RegisterIndex(2) } + 5.5 | Mov { destination: RegisterIndex(3), source: RegisterIndex(3) } + 5.6 | Call { location: 8 } + 5.7 | Stop + 5.8 | ForeignCall { function: "__debug_var_assign", destinations: [], inputs: [RegisterIndex(RegisterIndex(2)), RegisterIndex(RegisterIndex(3))] } +... +``` + +If you are interested in debugging/inspecting compiled ACIR without these synthetic changes, you can invoke the REPL debugger with the `--skip-instrumentation` flag or launch the VS Code debugger with the `skipConfiguration` property set to true in its launch configuration. You can find more details about those in the [Debugger REPL reference](debugger_repl.md) and the [VS Code Debugger reference](debugger_vscode.md). + +:::note +Skipping debugger instrumentation means you won't be able to inspect values of local variables. +::: + diff --git a/docs/versioned_docs/version-v0.29.0/reference/debugger/debugger_repl.md b/docs/versioned_docs/version-v0.29.0/reference/debugger/debugger_repl.md new file mode 100644 index 00000000000..46e2011304e --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/reference/debugger/debugger_repl.md @@ -0,0 +1,360 @@ +--- +title: REPL Debugger +description: + Noir Debugger REPL options and commands. +keywords: + [ + Nargo, + Noir CLI, + Noir Debugger, + REPL, + ] +sidebar_position: 1 +--- + +## Running the REPL debugger + +`nargo debug [OPTIONS] [WITNESS_NAME]` + +Runs the Noir REPL debugger. If a `WITNESS_NAME` is provided the debugger writes the resulting execution witness to a `WITNESS_NAME` 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 debug | +| `--print-acir` | Display the ACIR for compiled circuit | +| `--deny-warnings` | Treat all warnings as errors | +| `--silence-warnings` | Suppress warnings | +| `-h, --help` | Print help | + +None of these options are required. + +:::note +Since the debugger starts by compiling the target package, all Noir compiler options are also available. Check out the [compiler reference](../nargo_commands.md#nargo-compile) to learn more about the compiler options. +::: + +## REPL commands + +Once the debugger is running, it accepts the following commands. + +#### `help` (h) + +Displays the menu of available commands. + +``` +> help +Available commands: + + opcodes display ACIR opcodes + into step into to the next opcode + next step until a new source location is reached + out step until a new source location is reached + and the current stack frame is finished + break LOCATION:OpcodeLocation add a breakpoint at an opcode location + over step until a new source location is reached + without diving into function calls + restart restart the debugging session + delete LOCATION:OpcodeLocation delete breakpoint at an opcode location + witness show witness map + witness index:u32 display a single witness from the witness map + witness index:u32 value:String update a witness with the given value + memset index:usize value:String update a memory cell with the given + value + continue continue execution until the end of the + program + vars show variable values available at this point + in execution + stacktrace display the current stack trace + memory show memory (valid when executing unconstrained code) value + step step to the next ACIR opcode + +Other commands: + + help Show this help message + quit Quit repl + +``` + +### Stepping through programs + +#### `next` (n) + +Step until the next Noir source code location. While other commands, such as [`into`](#into-i) and [`step`](#step-s), allow for finer grained control of the program's execution at the opcode level, `next` is source code centric. For example: + +``` +3 ... +4 fn main(x: u32) { +5 assert(entry_point(x) == 2); +6 swap_entry_point(x, x + 1); +7 -> assert(deep_entry_point(x) == 4); +8 multiple_values_entry_point(x); +9 } +``` + + +Using `next` here would cause the debugger to jump to the definition of `deep_entry_point` (if available). + +If you want to step over `deep_entry_point` and go straight to line 8, use [the `over` command](#over) instead. + +#### `over` + +Step until the next source code location, without diving into function calls. For example: + +``` +3 ... +4 fn main(x: u32) { +5 assert(entry_point(x) == 2); +6 swap_entry_point(x, x + 1); +7 -> assert(deep_entry_point(x) == 4); +8 multiple_values_entry_point(x); +9 } +``` + + +Using `over` here would cause the debugger to execute until line 8 (`multiple_values_entry_point(x);`). + +If you want to step into `deep_entry_point` instead, use [the `next` command](#next-n). + +#### `out` + +Step until the end of the current function call. For example: + +``` + 3 ... + 4 fn main(x: u32) { + 5 assert(entry_point(x) == 2); + 6 swap_entry_point(x, x + 1); + 7 -> assert(deep_entry_point(x) == 4); + 8 multiple_values_entry_point(x); + 9 } + 10 + 11 unconstrained fn returns_multiple_values(x: u32) -> (u32, u32, u32, u32) { + 12 ... + ... + 55 + 56 unconstrained fn deep_entry_point(x: u32) -> u32 { + 57 -> level_1(x + 1) + 58 } + +``` + +Running `out` here will resume execution until line 8. + +#### `step` (s) + +Skips to the next ACIR code. A compiled Noir program is a sequence of ACIR opcodes. However, an unconstrained VM opcode denotes the start of an unconstrained code block, to be executed by the unconstrained VM. For example (redacted for brevity): + +``` +0 BLACKBOX::RANGE [(_0, num_bits: 32)] [ ] +1 -> BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(0))], q_c: 0 })] outputs=[Simple(Witness(1))] + 1.0 | Mov { destination: RegisterIndex(2), source: RegisterIndex(0) } + 1.1 | Const { destination: RegisterIndex(0), value: Value { inner: 0 } } + 1.2 | Const { destination: RegisterIndex(1), value: Value { inner: 0 } } + 1.3 | Mov { destination: RegisterIndex(2), source: RegisterIndex(2) } + 1.4 | Call { location: 7 } + ... + 1.43 | Return +2 EXPR [ (1, _1) -2 ] +``` + +The `->` here shows the debugger paused at an ACIR opcode: `BRILLIG`, at index 1, which denotes an unconstrained code block is about to start. + +Using the `step` command at this point would result in the debugger stopping at ACIR opcode 2, `EXPR`, skipping unconstrained computation steps. + +Use [the `into` command](#into-i) instead if you want to follow unconstrained computation step by step. + +#### `into` (i) + +Steps into the next opcode. A compiled Noir program is a sequence of ACIR opcodes. However, a BRILLIG opcode denotes the start of an unconstrained code block, to be executed by the unconstrained VM. For example (redacted for brevity): + +``` +0 BLACKBOX::RANGE [(_0, num_bits: 32)] [ ] +1 -> BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(0))], q_c: 0 })] outputs=[Simple(Witness(1))] + 1.0 | Mov { destination: RegisterIndex(2), source: RegisterIndex(0) } + 1.1 | Const { destination: RegisterIndex(0), value: Value { inner: 0 } } + 1.2 | Const { destination: RegisterIndex(1), value: Value { inner: 0 } } + 1.3 | Mov { destination: RegisterIndex(2), source: RegisterIndex(2) } + 1.4 | Call { location: 7 } + ... + 1.43 | Return +2 EXPR [ (1, _1) -2 ] +``` + +The `->` here shows the debugger paused at an ACIR opcode: `BRILLIG`, at index 1, which denotes an unconstrained code block is about to start. + +Using the `into` command at this point would result in the debugger stopping at opcode 1.0, `Mov ...`, allowing the debugger user to follow unconstrained computation step by step. + +Use [the `step` command](#step-s) instead if you want to skip to the next ACIR code directly. + +#### `continue` (c) + +Continues execution until the next breakpoint, or the end of the program. + +#### `restart` (res) + +Interrupts execution, and restarts a new debugging session from scratch. + +#### `opcodes` (o) + +Display the program's ACIR opcode sequence. For example: + +``` +0 BLACKBOX::RANGE [(_0, num_bits: 32)] [ ] +1 -> BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(0))], q_c: 0 })] outputs=[Simple(Witness(1))] + 1.0 | Mov { destination: RegisterIndex(2), source: RegisterIndex(0) } + 1.1 | Const { destination: RegisterIndex(0), value: Value { inner: 0 } } + 1.2 | Const { destination: RegisterIndex(1), value: Value { inner: 0 } } + 1.3 | Mov { destination: RegisterIndex(2), source: RegisterIndex(2) } + 1.4 | Call { location: 7 } + ... + 1.43 | Return +2 EXPR [ (1, _1) -2 ] +``` + +### Breakpoints + +#### `break [Opcode]` (or shorthand `b [Opcode]`) + +Sets a breakpoint on the specified opcode index. To get a list of the program opcode numbers, see [the `opcode` command](#opcodes-o). For example: + +``` +0 BLACKBOX::RANGE [(_0, num_bits: 32)] [ ] +1 -> BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(0))], q_c: 0 })] outputs=[Simple(Witness(1))] + 1.0 | Mov { destination: RegisterIndex(2), source: RegisterIndex(0) } + 1.1 | Const { destination: RegisterIndex(0), value: Value { inner: 0 } } + 1.2 | Const { destination: RegisterIndex(1), value: Value { inner: 0 } } + 1.3 | Mov { destination: RegisterIndex(2), source: RegisterIndex(2) } + 1.4 | Call { location: 7 } + ... + 1.43 | Return +2 EXPR [ (1, _1) -2 ] +``` + +In this example, issuing a `break 1.2` command adds break on opcode 1.2, as denoted by the `*` character: + +``` +0 BLACKBOX::RANGE [(_0, num_bits: 32)] [ ] +1 -> BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(0))], q_c: 0 })] outputs=[Simple(Witness(1))] + 1.0 | Mov { destination: RegisterIndex(2), source: RegisterIndex(0) } + 1.1 | Const { destination: RegisterIndex(0), value: Value { inner: 0 } } + 1.2 | * Const { destination: RegisterIndex(1), value: Value { inner: 0 } } + 1.3 | Mov { destination: RegisterIndex(2), source: RegisterIndex(2) } + 1.4 | Call { location: 7 } + ... + 1.43 | Return +2 EXPR [ (1, _1) -2 ] +``` + +Running [the `continue` command](#continue-c) at this point would cause the debugger to execute the program until opcode 1.2. + +#### `delete [Opcode]` (or shorthand `d [Opcode]`) + +Deletes a breakpoint at an opcode location. Usage is analogous to [the `break` command](#). + +### Variable inspection + +#### vars + +Show variable values available at this point in execution. + +:::note +The ability to inspect variable values from the debugger depends on compilation to be run in a special debug instrumentation mode. This instrumentation weaves variable tracing code with the original source code. + +So variable value inspection comes at the expense of making the resulting ACIR bytecode bigger and harder to understand and optimize. + +If you find this compromise unacceptable, you can run the debugger with the flag `--skip-debug-instrumentation`. This will compile your circuit without any additional debug information, so the resulting ACIR bytecode will be identical to the one produced by standard Noir compilation. However, if you opt for this, the `vars` command will not be available while debugging. +::: + + +### Stacktrace + +#### `stacktrace` + +Displays the current stack trace. + + +### Witness map + +#### `witness` (w) + +Show witness map. For example: + +``` +_0 = 0 +_1 = 2 +_2 = 1 +``` + +#### `witness [Witness Index]` + +Display a single witness from the witness map. For example: + +``` +> witness 1 +_1 = 2 +``` + +#### `witness [Witness Index] [New value]` + +Overwrite the given index with a new value. For example: + +``` +> witness 1 3 +_1 = 3 +``` + + +### Unconstrained VM memory + +#### `memory` + +Show unconstrained VM memory state. For example: + +``` +> memory +At opcode 1.13: Store { destination_pointer: RegisterIndex(0), source: RegisterIndex(3) } +... +> registers +0 = 0 +1 = 10 +2 = 0 +3 = 1 +4 = 1 +5 = 2³² +6 = 1 +> into +At opcode 1.14: Const { destination: RegisterIndex(5), value: Value { inner: 1 } } +... +> memory +0 = 1 +> +``` + +In the example above: we start with clean memory, then step through a `Store` opcode which stores the value of register 3 (1) into the memory address stored in register 0 (0). Thus now `memory` shows memory address 0 contains value 1. + +:::note +This command is only functional while the debugger is executing unconstrained code. +::: + +#### `memset [Memory address] [New value]` + +Update a memory cell with the given value. For example: + +``` +> memory +0 = 1 +> memset 0 2 +> memory +0 = 2 +> memset 1 4 +> memory +0 = 2 +1 = 4 +> +``` + +:::note +This command is only functional while the debugger is executing unconstrained code. +::: \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.29.0/reference/debugger/debugger_vscode.md b/docs/versioned_docs/version-v0.29.0/reference/debugger/debugger_vscode.md new file mode 100644 index 00000000000..c027332b3b0 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/reference/debugger/debugger_vscode.md @@ -0,0 +1,82 @@ +--- +title: VS Code Debugger +description: + VS Code Debugger configuration and features. +keywords: + [ + Nargo, + Noir CLI, + Noir Debugger, + VS Code, + IDE, + ] +sidebar_position: 0 +--- + +# VS Code Noir Debugger Reference + +The Noir debugger enabled by the vscode-noir extension ships with default settings such that the most common scenario should run without any additional configuration steps. + +These defaults can nevertheless be overridden by defining a launch configuration file. This page provides a reference for the properties you can override via a launch configuration file, as well as documenting the Nargo `dap` command, which is a dependency of the VS Code Noir debugger. + + +## Creating and editing launch configuration files + +To create a launch configuration file from VS Code, open the _debug pane_, and click on _create a launch.json file_. + +![Creating a launch configuration file](@site/static/img/debugger/ref1-create-launch.png) + +A `launch.json` file will be created, populated with basic defaults. + +### Noir Debugger launch.json properties + +#### projectFolder + +_String, optional._ + +Absolute path to the Nargo project to debug. By default, it is dynamically determined by looking for the nearest `Nargo.toml` file to the active file at the moment of launching the debugger. + +#### proverName + +_String, optional._ + +Name of the prover input to use. Defaults to `Prover`, which looks for a file named `Prover.toml` at the `projectFolder`. + +#### generateAcir + +_Boolean, optional._ + +If true, generate ACIR opcodes instead of unconstrained opcodes which will be closer to release binaries but less convenient for debugging. Defaults to `false`. + +#### skipInstrumentation + +_Boolean, optional._ + +Skips variables debugging instrumentation of code, making debugging less convenient but the resulting binary smaller and closer to production. Defaults to `false`. + +:::note +Skipping instrumentation causes the debugger to be unable to inspect local variables. +::: + +## `nargo dap [OPTIONS]` + +When run without any option flags, it starts the Nargo Debug Adapter Protocol server, which acts as the debugging backend for the VS Code Noir Debugger. + +All option flags are related to preflight checks. The Debug Adapter Protocol specifies how errors are to be informed from a running DAP server, but it doesn't specify mechanisms to communicate server initialization errors between the DAP server and its client IDE. + +Thus `nargo dap` ships with a _preflight check_ mode. If flag `--preflight-check` and the rest of the `--preflight-*` flags are provided, Nargo will run the same initialization routine except it will not start the DAP server. + +`vscode-noir` will then run `nargo dap` in preflight check mode first before a debugging session starts. If the preflight check ends in error, vscode-noir will present stderr and stdout output from this process through its own Output pane in VS Code. This makes it possible for users to diagnose what pieces of configuration might be wrong or missing in case of initialization errors. + +If the preflight check succeeds, `vscode-noir` proceeds to start the DAP server normally but running `nargo dap` without any additional flags. + +### Options + +| Option | Description | +| --------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- | +| `--preflight-check` | If present, dap runs in preflight check mode. | +| `--preflight-project-folder ` | Absolute path to the project to debug for preflight check. | +| `--preflight-prover-name ` | Name of prover file to use for preflight check | +| `--preflight-generate-acir` | Optional. If present, compile in ACIR mode while running preflight check. | +| `--preflight-skip-instrumentation` | Optional. If present, compile without introducing debug instrumentation while running preflight check. | +| `-h, --help` | Print help. | diff --git a/docs/versioned_docs/version-v0.29.0/reference/nargo_commands.md b/docs/versioned_docs/version-v0.29.0/reference/nargo_commands.md new file mode 100644 index 00000000000..218fcfb0c8c --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/reference/nargo_commands.md @@ -0,0 +1,381 @@ +--- +title: Nargo +description: + Noir CLI Commands for Noir Prover and Verifier to create, execute, prove and verify programs, + generate Solidity verifier smart contract and compile into JSON file containing ACIR + representation and ABI of circuit. +keywords: + [ + Nargo, + Noir CLI, + Noir Prover, + Noir Verifier, + generate Solidity verifier, + compile JSON file, + ACIR representation, + ABI of circuit, + TypeScript, + ] +sidebar_position: 0 +--- + +# Command-Line Help for `nargo` + +This document contains the help content for the `nargo` command-line program. + +**Command Overview:** + +* [`nargo`↴](#nargo) +* [`nargo backend`↴](#nargo-backend) +* [`nargo backend current`↴](#nargo-backend-current) +* [`nargo backend ls`↴](#nargo-backend-ls) +* [`nargo backend use`↴](#nargo-backend-use) +* [`nargo backend install`↴](#nargo-backend-install) +* [`nargo backend uninstall`↴](#nargo-backend-uninstall) +* [`nargo check`↴](#nargo-check) +* [`nargo fmt`↴](#nargo-fmt) +* [`nargo codegen-verifier`↴](#nargo-codegen-verifier) +* [`nargo compile`↴](#nargo-compile) +* [`nargo new`↴](#nargo-new) +* [`nargo init`↴](#nargo-init) +* [`nargo execute`↴](#nargo-execute) +* [`nargo prove`↴](#nargo-prove) +* [`nargo verify`↴](#nargo-verify) +* [`nargo test`↴](#nargo-test) +* [`nargo info`↴](#nargo-info) +* [`nargo lsp`↴](#nargo-lsp) + +## `nargo` + +Noir's package manager + +**Usage:** `nargo ` + +###### **Subcommands:** + +* `backend` — Install and select custom backends used to generate and verify proofs +* `check` — Checks the constraint system for errors +* `fmt` — Format the Noir files in a workspace +* `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 Noir project in a new directory +* `init` — Create a Noir project in the current directory +* `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 +* `info` — Provides detailed information on each of a program's function (represented by a single circuit) +* `lsp` — Starts the Noir LSP server + +###### **Options:** + + + + +## `nargo backend` + +Install and select custom backends used to generate and verify proofs + +**Usage:** `nargo backend ` + +###### **Subcommands:** + +* `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 + + + +## `nargo backend current` + +Prints the name of the currently active backend + +**Usage:** `nargo backend current` + + + +## `nargo backend ls` + +Prints the list of currently installed backends + +**Usage:** `nargo backend ls` + + + +## `nargo backend use` + +Select the backend to use + +**Usage:** `nargo backend use ` + +###### **Arguments:** + +* `` + + + +## `nargo backend install` + +Install a new backend from a URL + +**Usage:** `nargo backend install ` + +###### **Arguments:** + +* `` — The name of the backend to install +* `` — The URL from which to download the backend + + + +## `nargo backend uninstall` + +Uninstalls a backend + +**Usage:** `nargo backend uninstall ` + +###### **Arguments:** + +* `` — The name of the backend to uninstall + + + +## `nargo check` + +Checks the constraint system for errors + +**Usage:** `nargo check [OPTIONS]` + +###### **Options:** + +* `--package ` — The name of the package to check +* `--workspace` — Check all packages in the workspace +* `--overwrite` — Force overwrite of existing files +* `--expression-width ` — Override the expression width requested by the backend +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings + + + +## `nargo fmt` + +Format the Noir files in a workspace + +**Usage:** `nargo fmt [OPTIONS]` + +###### **Options:** + +* `--check` — Run noirfmt in check mode + + + +## `nargo codegen-verifier` + +Generates a Solidity verifier smart contract for the program + +**Usage:** `nargo codegen-verifier [OPTIONS]` + +###### **Options:** + +* `--package ` — The name of the package to codegen +* `--workspace` — Codegen all packages in the workspace +* `--expression-width ` — Override the expression width requested by the backend +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings + + + +## `nargo compile` + +Compile the program and its secret execution trace into ACIR format + +**Usage:** `nargo compile [OPTIONS]` + +###### **Options:** + +* `--package ` — The name of the package to compile +* `--workspace` — Compile all packages in the workspace +* `--expression-width ` — Override the expression width requested by the backend +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings + + + +## `nargo new` + +Create a Noir project in a new directory + +**Usage:** `nargo new [OPTIONS] ` + +###### **Arguments:** + +* `` — The path to save the new project + +###### **Options:** + +* `--name ` — Name of the package [default: package directory name] +* `--lib` — Use a library template +* `--bin` — Use a binary template [default] +* `--contract` — Use a contract template + + + +## `nargo init` + +Create a Noir project in the current directory + +**Usage:** `nargo init [OPTIONS]` + +###### **Options:** + +* `--name ` — Name of the package [default: current directory name] +* `--lib` — Use a library template +* `--bin` — Use a binary template [default] +* `--contract` — Use a contract template + + + +## `nargo execute` + +Executes a circuit to calculate its return value + +**Usage:** `nargo execute [OPTIONS] [WITNESS_NAME]` + +###### **Arguments:** + +* `` — Write the execution witness to named file + +###### **Options:** + +* `-p`, `--prover-name ` — The name of the toml file which contains the inputs for the prover + + Default value: `Prover` +* `--package ` — The name of the package to execute +* `--workspace` — Execute all packages in the workspace +* `--expression-width ` — Override the expression width requested by the backend +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings +* `--oracle-resolver ` — JSON RPC url to solve oracle calls + + + +## `nargo prove` + +Create proof for this program. The proof is returned as a hex encoded string + +**Usage:** `nargo prove [OPTIONS]` + +###### **Options:** + +* `-p`, `--prover-name ` — The name of the toml file which contains the inputs for the prover + + Default value: `Prover` +* `-v`, `--verifier-name ` — The name of the toml file which contains the inputs for the verifier + + Default value: `Verifier` +* `--verify` — Verify proof after proving +* `--package ` — The name of the package to prove +* `--workspace` — Prove all packages in the workspace +* `--expression-width ` — Override the expression width requested by the backend +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings +* `--oracle-resolver ` — JSON RPC url to solve oracle calls + + + +## `nargo verify` + +Given a proof and a program, verify whether the proof is valid + +**Usage:** `nargo verify [OPTIONS]` + +###### **Options:** + +* `-v`, `--verifier-name ` — The name of the toml file which contains the inputs for the verifier + + Default value: `Verifier` +* `--package ` — The name of the package verify +* `--workspace` — Verify all packages in the workspace +* `--expression-width ` — Override the expression width requested by the backend +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings + + + +## `nargo test` + +Run the tests for this program + +**Usage:** `nargo test [OPTIONS] [TEST_NAME]` + +###### **Arguments:** + +* `` — If given, only tests with names containing this string will be run + +###### **Options:** + +* `--show-output` — Display output of `println` statements +* `--exact` — Only run tests that match exactly +* `--package ` — The name of the package to test +* `--workspace` — Test all packages in the workspace +* `--expression-width ` — Override the expression width requested by the backend +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings +* `--oracle-resolver ` — JSON RPC url to solve oracle calls + + + +## `nargo info` + +Provides detailed information on each of a program's function (represented by a single circuit) + +Current information provided per circuit: 1. The number of ACIR opcodes 2. Counts the final number gates in the circuit used by a backend + +**Usage:** `nargo info [OPTIONS]` + +###### **Options:** + +* `--package ` — The name of the package to detail +* `--workspace` — Detail all packages in the workspace +* `--expression-width ` — Override the expression width requested by the backend +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings + + + +## `nargo lsp` + +Starts the Noir LSP server + +Starts an LSP server which allows IDEs such as VS Code to display diagnostics in Noir source. + +VS Code Noir Language Support: https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir + +**Usage:** `nargo lsp` + + + +
+ + + This document was generated automatically by + clap-markdown. + + diff --git a/docs/versioned_docs/version-v0.29.0/tooling/debugger.md b/docs/versioned_docs/version-v0.29.0/tooling/debugger.md new file mode 100644 index 00000000000..184c436068f --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/tooling/debugger.md @@ -0,0 +1,27 @@ +--- +title: Debugger +description: Learn about the Noir Debugger, in its REPL or VS Code versions. +keywords: [Nargo, VSCode, Visual Studio Code, REPL, Debugger] +sidebar_position: 2 +--- + +# Noir Debugger + +There are currently two ways of debugging Noir programs: + +1. From VS 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). +2. Via the REPL debugger, which ships with Nargo. + +In order to use either version of the debugger, you will need to install recent enough versions of Noir, [Nargo](../getting_started/installation) and vscode-noir: + +- Noir 0.xx +- Nargo 0.xx +- vscode-noir 0.xx + +:::info +At the moment, the debugger supports debugging binary projects, but not contracts. +::: + +We cover the VS Code Noir debugger more in depth in [its VS Code debugger how-to guide](../how_to/debugger/debugging_with_vs_code.md) and [the reference](../reference/debugger/debugger_vscode.md). + +The REPL debugger is discussed at length in [the REPL debugger how-to guide](../how_to/debugger/debugging_with_the_repl.md) and [the reference](../reference/debugger/debugger_repl.md). diff --git a/docs/versioned_docs/version-v0.29.0/tooling/language_server.md b/docs/versioned_docs/version-v0.29.0/tooling/language_server.md new file mode 100644 index 00000000000..81e0356ef8a --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/tooling/language_server.md @@ -0,0 +1,43 @@ +--- +title: Language Server +description: Learn about the Noir Language Server, how to install the components, and configuration that may be required. +keywords: [Nargo, Language Server, LSP, VSCode, Visual Studio Code] +sidebar_position: 0 +--- + +This section helps you install and configure the Noir Language Server. + +The Language Server Protocol (LSP) has two components, the [Server](#language-server) and the [Client](#language-client). Below we describe each in the context of Noir. + +## Language Server + +The Server component is provided by the Nargo command line tool that you installed at the beginning of this guide. +As long as Nargo is installed and you've used it to run other commands in this guide, it should be good to go! + +If you'd like to verify that the `nargo lsp` command is available, you can run `nargo --help` and look for `lsp` in the list of commands. If you see it, you're using a version of Noir with LSP support. + +## Language Client + +The Client component is usually an editor plugin that launches the Server. It communicates LSP messages between the editor and the Server. For example, when you save a file, the Client will alert the Server, so it can try to compile the project and report any errors. + +Currently, Noir provides a Language Client for Visual Studio Code via the [vscode-noir](https://github.com/noir-lang/vscode-noir) extension. You can install it via the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir). + +> **Note:** Noir's Language Server Protocol support currently assumes users' VSCode workspace root to be the same as users' Noir project root (i.e. where Nargo.toml lies). +> +> If LSP features seem to be missing / malfunctioning, make sure you are opening your Noir project directly (instead of as a sub-folder) in your VSCode instance. + +When your language server is running correctly and the VSCode plugin is installed, you should see handy codelens buttons for compilation, measuring circuit size, execution, and tests: + +![Compile and Execute](@site/static/img/codelens_compile_execute.png) +![Run test](@site/static/img/codelens_run_test.png) + +You should also see your tests in the `testing` panel: + +![Testing panel](@site/static/img/codelens_testing_panel.png) + +### Configuration + +- **Noir: Enable LSP** - If checked, the extension will launch the Language Server via `nargo lsp` and communicate with it. +- **Noir: Nargo Flags** - Additional flags may be specified if you require them to be added when the extension calls `nargo lsp`. +- **Noir: Nargo Path** - An absolute path to a Nargo binary with the `lsp` command. This may be useful if Nargo is not within the `PATH` of your editor. +- **Noir > Trace: Server** - Setting this to `"messages"` or `"verbose"` will log LSP messages between the Client and Server. Useful for debugging. diff --git a/docs/versioned_docs/version-v0.29.0/tooling/testing.md b/docs/versioned_docs/version-v0.29.0/tooling/testing.md new file mode 100644 index 00000000000..d3e0c522473 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/tooling/testing.md @@ -0,0 +1,62 @@ +--- +title: Testing in Noir +description: Learn how to use Nargo to test your Noir program in a quick and easy way +keywords: [Nargo, testing, Noir, compile, test] +sidebar_position: 1 +--- + +You can test your Noir programs using Noir circuits. + +Nargo will automatically compile and run any functions which have the decorator `#[test]` on them if +you run `nargo test`. + +For example if you have a program like: + +```rust +fn add(x: u64, y: u64) -> u64 { + x + y +} +#[test] +fn test_add() { + assert(add(2,2) == 4); + assert(add(0,1) == 1); + assert(add(1,0) == 1); +} +``` + +Running `nargo test` will test that the `test_add` function can be executed while satisfying all +the constraints 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.29.0/tutorials/noirjs_app.md b/docs/versioned_docs/version-v0.29.0/tutorials/noirjs_app.md new file mode 100644 index 00000000000..6446e0b2a76 --- /dev/null +++ b/docs/versioned_docs/version-v0.29.0/tutorials/noirjs_app.md @@ -0,0 +1,326 @@ +--- +title: Building a web app with NoirJS +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, app] +sidebar_position: 0 +pagination_next: noir/concepts/data_types/index +--- + +NoirJS is a set of packages meant to work both in a browser and a server environment. In this tutorial, we will build a simple web app using them. From here, you should get an idea on how to proceed with your own Noir projects! + +You can find the complete app code for this guide [here](https://github.com/noir-lang/tiny-noirjs-app). + +## Setup + +:::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.27.x matches `noir_js@0.27.x`, etc. + +In this guide, we will be pinned to 0.27.0. + +::: + +Before we start, we want to make sure we have Node and Nargo installed. + +We start by opening a terminal and executing `node --version`. If we don't get an output like `v20.10.0`, that means node is not installed. Let's do that by following the handy [nvm guide](https://github.com/nvm-sh/nvm?tab=readme-ov-file#install--update-script). + +As for `Nargo`, we can follow the the [Nargo guide](../getting_started/installation/index.md) to install it. If you're lazy, just paste this on a terminal and run `noirup`: + +```sh +curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash +``` + +Easy enough. Onwards! + +## Our project + +ZK is a powerful technology. An app that doesn't reveal one of the inputs to _anyone_ is almost unbelievable, yet Noir makes it as easy as a single line of code. + +In fact, it's so simple that it comes nicely packaged in `nargo`. Let's do that! + +### Nargo + +Run: + +`nargo new circuit` + +And... That's about it. Your program is ready to be compiled and run. + +To compile, let's `cd` into the `circuit` folder to enter our project, and call: + +`nargo compile` + +This compiles our circuit into `json` format and add it to a new `target` folder. + +:::info + +At this point in the tutorial, your folder structure should look like this: + +```tree +. +└── circuit <---- our working directory + ├── Nargo.toml + ├── src + │ └── main.nr + └── target + └── circuit.json +``` + +::: + +### Node and Vite + +If you want to explore Nargo, feel free to go on a side-quest now and follow the steps in the +[getting started](../getting_started/hello_noir/index.md) guide. However, we want our app to run on the browser, so we need Vite. + +Vite is a powerful tool to generate static websites. While it provides all kinds of features, let's just go barebones with some good old vanilla JS. + +To do this this, go back to the previous folder (`cd ..`) and create a new vite project by running `npm create vite` and choosing "Vanilla" and "Javascript". + +A wild `vite-project` directory should now appear in your root folder! Let's not waste any time and dive right in: + +```bash +cd vite-project +``` + +### Setting Up Vite and Configuring the Project + +Before we proceed with any coding, let's get our environment tailored for Noir. We'll start by laying down the foundations with a `vite.config.js` file. This little piece of configuration is our secret sauce for making sure everything meshes well with the NoirJS libraries and other special setups we might need, like handling WebAssembly modules. Here’s how you get that going: + +#### Creating the vite.config.js + +In your freshly minted `vite-project` folder, create a new file named `vite.config.js` and open it in your code editor. Paste the following to set the stage: + +```javascript +import { defineConfig } from "vite"; +import copy from "rollup-plugin-copy"; + +export default defineConfig({ + esbuild: { + target: "esnext", + }, + optimizeDeps: { + esbuildOptions: { + target: "esnext", + }, + }, + plugins: [ + copy({ + targets: [ + { src: "node_modules/**/*.wasm", dest: "node_modules/.vite/dist" }, + ], + copySync: true, + hook: "buildStart", + }), + ], + server: { + port: 3000, + }, +}); +``` + +#### Install Dependencies + +Now that our stage is set, install the necessary NoirJS packages along with our other dependencies: + +```bash +npm install && npm install @noir-lang/backend_barretenberg@0.27.0 @noir-lang/noir_js@0.27.0 +npm install rollup-plugin-copy --save-dev +``` + +:::info + +At this point in the tutorial, your folder structure should look like this: + +```tree +. +└── circuit + └── ...etc... +└── vite-project <---- our working directory + └── ...etc... +``` + +::: + +#### Some cleanup + +`npx create vite` is amazing but it creates a bunch of files we don't really need for our simple example. Actually, let's just delete everything except for `vite.config.js`, `index.html`, `main.js` and `package.json`. I feel lighter already. + +![my heart is ready for you, noir.js](@site/static/img/memes/titanic.jpeg) + +## HTML + +Our app won't run like this, of course. We need some working HTML, at least. Let's open our broken-hearted `index.html` and replace everything with this code snippet: + +```html + + + + + + +

Noir app

+
+ + +
+
+

Logs

+

Proof

+
+ + +``` + +It _could_ be a beautiful UI... Depending on which universe you live in. + +## Some good old vanilla Javascript + +Our love for Noir needs undivided attention, so let's just open `main.js` and delete everything (this is where the romantic scenery becomes a bit creepy). + +Start by pasting in this boilerplate code: + +```js +const setup = async () => { + await Promise.all([ + import('@noir-lang/noirc_abi').then((module) => + module.default(new URL('@noir-lang/noirc_abi/web/noirc_abi_wasm_bg.wasm', import.meta.url).toString()), + ), + import('@noir-lang/acvm_js').then((module) => + module.default(new URL('@noir-lang/acvm_js/web/acvm_js_bg.wasm', import.meta.url).toString()), + ), + ]); +}; + +function display(container, msg) { + const c = document.getElementById(container); + const p = document.createElement('p'); + p.textContent = msg; + c.appendChild(p); +} + +document.getElementById('submitGuess').addEventListener('click', async () => { + try { + // here's where love happens + } catch (err) { + display('logs', 'Oh 💔 Wrong guess'); + } +}); +``` + +The display function doesn't do much. We're simply manipulating our website to see stuff happening. For example, if the proof fails, it will simply log a broken heart 😢 + +As for the `setup` function, it's just a sad reminder that dealing with `wasm` on the browser is not as easy as it should. Just copy, paste, and forget. + +:::info + +At this point in the tutorial, your folder structure should look like this: + +```tree +. +└── circuit + └── ...same as above +└── vite-project + ├── vite.config.js + ├── main.js + ├── package.json + └── index.html +``` + +You'll see other files and folders showing up (like `package-lock.json`, `node_modules`) but you shouldn't have to care about those. + +::: + +## Some NoirJS + +We're starting with the good stuff now. If you've compiled the circuit as described above, you should have a `json` file we want to import at the very top of our `main.js` file: + +```ts +import circuit from '../circuit/target/circuit.json'; +``` + +[Noir is backend-agnostic](../index.mdx#whats-new-about-noir). We write Noir, but we also need a proving backend. That's why we need to import and instantiate the two dependencies we installed above: `BarretenbergBackend` and `Noir`. Let's import them right below: + +```js +import { BarretenbergBackend, BarretenbergVerifier as Verifier } from '@noir-lang/backend_barretenberg'; +import { Noir } from '@noir-lang/noir_js'; +``` + +And instantiate them inside our try-catch block: + +```ts +// try { +const backend = new BarretenbergBackend(circuit); +const noir = new Noir(circuit, backend); +// } +``` + +:::note + +For the remainder of the tutorial, everything will be happening inside the `try` block + +::: + +## Our app + +Now for the app itself. We're capturing whatever is in the input when people press the submit button. Just add this: + +```js +const x = parseInt(document.getElementById('guessInput').value); +const input = { x, y: 2 }; +``` + +Now we're ready to prove stuff! Let's feed some inputs to our circuit and calculate the proof: + +```js +await setup(); // let's squeeze our wasm inits here + +display('logs', 'Generating proof... ⌛'); +const proof = await noir.generateProof(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 run dev`. If it doesn't open a browser for you, just visit `localhost:5173`. You should now see the worst UI ever, with an ugly input. + +![Getting Started 0](@site/static/img/noir_getting_started_1.png) + +Now, our circuit says `fn main(x: Field, y: pub Field)`. This means only the `y` value is public, and it's hardcoded above: `input = { x, y: 2 }`. In other words, you won't need to send your secret`x` to the verifier! + +By inputting any number other than 2 in the input box and clicking "submit", you should get a valid proof. Otherwise the proof won't even generate correctly. By the way, if you're human, you shouldn't be able to understand anything on the "proof" box. That's OK. We like you, human ❤️. + +## Verifying + +Time to celebrate, yes! But we shouldn't trust machines so blindly. Let's add these lines to see our proof being verified: + +```js +display('logs', 'Verifying proof... ⌛'); +const verificationKey = await backend.getVerificationKey(); +const verifier = new Verifier(); +const isValid = await verifier.verifyProof(proof, verificationKey); +if (isValid) display('logs', 'Verifying proof... ✅'); +``` + +You have successfully generated a client-side Noir web app! + +![coded app without math knowledge](@site/static/img/memes/flextape.jpeg) + +## 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/vite-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.30.0/explainers/explainer-oracle.md b/docs/versioned_docs/version-v0.30.0/explainers/explainer-oracle.md new file mode 100644 index 00000000000..b84ca5dd986 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/explainers/explainer-oracle.md @@ -0,0 +1,57 @@ +--- +title: Oracles +description: This guide provides an in-depth understanding of how Oracles work in Noir programming. Learn how to use outside calculations in your programs, constrain oracles, and understand their uses and limitations. +keywords: + - Noir Programming + - Oracles + - JSON-RPC + - Foreign Call Handlers + - Constrained Functions + - Blockchain Programming +sidebar_position: 1 +--- + +If you've seen "The Matrix" you may recall "The Oracle" as Gloria Foster smoking cigarettes and baking cookies. While she appears to "know things", she is actually providing a calculation of a pre-determined future. Noir Oracles are similar, in a way. They don't calculate the future (yet), but they allow you to use outside calculations in your programs. + +![matrix oracle prediction](@site/static/img/memes/matrix_oracle.jpeg) + +A Noir program is usually self-contained. You can pass certain inputs to it, and it will generate a deterministic output for those inputs. But what if you wanted to defer some calculation to an outside process or source? + +Oracles are functions that provide this feature. + +## Use cases + +An example usage for Oracles is proving something on-chain. For example, proving that the ETH-USDC quote was below a certain target at a certain block time. Or even making more complex proofs like proving the ownership of an NFT as an anonymous login method. + +Another interesting use case is to defer expensive calculations to be made outside of the Noir program, and then constraining the result; similar to the use of [unconstrained functions](../noir/concepts//unconstrained.md). + +In short, anything that can be constrained in a Noir program but needs to be fetched from an external source is a great candidate to be used in oracles. + +## Constraining oracles + +Just like in The Matrix, Oracles are powerful. But with great power, comes great responsibility. Just because you're using them in a Noir program doesn't mean they're true. Noir has no superpowers. If you want to prove that Portugal won the Euro Cup 2016, you're still relying on potentially untrusted information. + +To give a concrete example, Alice wants to login to the [NounsDAO](https://nouns.wtf/) forum with her username "noir_nouner" by proving she owns a noun without revealing her ethereum address. Her Noir program could have a oracle call like this: + +```rust +#[oracle(getNoun)] +unconstrained fn get_noun(address: Field) -> Field +``` + +This oracle could naively resolve with the number of Nouns she possesses. However, it is useless as a trusted source, as the oracle could resolve to anything Alice wants. In order to make this oracle call actually useful, Alice would need to constrain the response from the oracle, by proving her address and the noun count belongs to the state tree of the contract. + +In short, **Oracles don't prove anything. Your Noir program does.** + +:::danger + +If you don't constrain the return of your oracle, you could be clearly opening an attack vector on your Noir program. Make double-triple sure that the return of an oracle call is constrained! + +::: + +## How to use Oracles + +On CLI, Nargo resolves oracles by making JSON RPC calls, which means it would require an RPC node to be running. + +In JavaScript, NoirJS accepts and resolves arbitrary call handlers (that is, not limited to JSON) as long as they matches the expected types the developer defines. Refer to [Foreign Call Handler](../reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md) to learn more about NoirJS's call handling. + +If you want to build using oracles, follow through to the [oracle guide](../how_to/how-to-oracles.md) for a simple example on how to do that. diff --git a/docs/versioned_docs/version-v0.30.0/explainers/explainer-recursion.md b/docs/versioned_docs/version-v0.30.0/explainers/explainer-recursion.md new file mode 100644 index 00000000000..18846176ca7 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/explainers/explainer-recursion.md @@ -0,0 +1,176 @@ +--- +title: Recursive proofs +description: Explore the concept of recursive proofs in Zero-Knowledge programming. Understand how recursion works in Noir, a language for writing smart contracts on the EVM blockchain. Learn through practical examples like Alice and Bob's guessing game, Charlie's recursive merkle tree, and Daniel's reusable components. Discover how to use recursive proofs to optimize computational resources and improve efficiency. + +keywords: + [ + "Recursive Proofs", + "Zero-Knowledge Programming", + "Noir", + "EVM Blockchain", + "Smart Contracts", + "Recursion in Noir", + "Alice and Bob Guessing Game", + "Recursive Merkle Tree", + "Reusable Components", + "Optimizing Computational Resources", + "Improving Efficiency", + "Verification Key", + "Aggregation", + "Recursive zkSNARK schemes", + "PLONK", + "Proving and Verification Keys" + ] +sidebar_position: 1 +pagination_next: how_to/how-to-recursion +--- + +In programming, we tend to think of recursion as something calling itself. A classic example would be the calculation of the factorial of a number: + +```js +function factorial(n) { + if (n === 0 || n === 1) { + return 1; + } else { + return n * factorial(n - 1); + } +} +``` + +In this case, while `n` is not `1`, this function will keep calling itself until it hits the base case, bubbling up the result on the call stack: + +```md + Is `n` 1? <--------- + /\ / + / \ n = n -1 + / \ / + Yes No -------- +``` + +In Zero-Knowledge, recursion has some similarities. + +It is not a Noir function calling itself, but a proof being used as an input to another circuit. In short, you verify one proof *inside* another proof, returning the proof that both proofs are valid. + +This means that, given enough computational resources, you can prove the correctness of any arbitrary number of proofs in a single proof. This could be useful to design state channels (for which a common example would be [Bitcoin's Lightning Network](https://en.wikipedia.org/wiki/Lightning_Network)), to save on gas costs by settling one proof on-chain, or simply to make business logic less dependent on a consensus mechanism. + +## Examples + +Let us look at some of these examples + +### Alice and Bob - Guessing game + +Alice and Bob are friends, and they like guessing games. They want to play a guessing game online, but for that, they need a trusted third-party that knows both of their secrets and finishes the game once someone wins. + +So, they use zero-knowledge proofs. Alice tries to guess Bob's number, and Bob will generate a ZK proof stating whether she succeeded or failed. + +This ZK proof can go on a smart contract, revealing the winner and even giving prizes. However, this means every turn needs to be verified on-chain. This incurs some cost and waiting time that may simply make the game too expensive or time-consuming to be worth it. + +As a solution, Alice proposes the following: "what if Bob generates his proof, and instead of sending it on-chain, I verify it *within* my own proof before playing my own turn?". + +She can then generate a proof that she verified his proof, and so on. + +```md + Did you fail? <-------------------------- + / \ / + / \ n = n -1 + / \ / + Yes No / + | | / + | | / + | You win / + | / + | / +Generate proof of that / + + / + my own guess ---------------- +``` + +### Charlie - Recursive merkle tree + +Charlie is a concerned citizen, and wants to be sure his vote in an election is accounted for. He votes with a ZK proof, but he has no way of knowing that his ZK proof was included in the total vote count! + +If the vote collector puts all of the votes into a [Merkle tree](https://en.wikipedia.org/wiki/Merkle_tree), everyone can prove the verification of two proofs within one proof, as such: + +```md + abcd + __________|______________ + | | + ab cd + _____|_____ ______|______ + | | | | + alice bob charlie daniel +``` + +Doing this recursively allows us to arrive on a final proof `abcd` which if true, verifies the correctness of all the votes. + +### Daniel - Reusable components + +Daniel has a big circuit and a big headache. A part of his circuit is a setup phase that finishes with some assertions that need to be made. But that section alone takes most of the proving time, and is largely independent of the rest of the circuit. + +He might find it more efficient to generate a proof for that setup phase separately, and verify that proof recursively in the actual business logic section of his circuit. This will allow for parallelization of both proofs, which results in a considerable speedup. + +## What params do I need + +As you can see in the [recursion reference](noir/standard_library/recursion.md), a simple recursive proof requires: + +- The proof to verify +- The Verification Key of the circuit that generated the proof +- A hash of this verification key, as it's needed for some backends +- The public inputs for the proof + +:::info + +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. + +So, taking the example of Alice and Bob and their guessing game: + +- Alice makes her guess. Her proof is *not* recursive: it doesn't verify any proof within it! It's just a standard `assert(x != y)` circuit +- Bob verifies Alice's proof and makes his own guess. In this circuit, he doesn't exactly *prove* the verification of Alice's proof. Instead, he *aggregates* his proof to Alice's proof. The actual verification is done when the full proof is verified, for example when using `nargo verify` or through the verifier smart contract. + +We can imagine recursive proofs a [relay race](https://en.wikipedia.org/wiki/Relay_race). The first runner doesn't have to receive the baton from anyone else, as he/she already starts with it. But when his/her turn is over, the next runner needs to receive it, run a bit more, and pass it along. Even though every runner could theoretically verify the baton mid-run (why not? 🏃🔍), only at the end of the race does the referee verify that the whole race is valid. + +::: + +## Some architecture + +As with everything in computer science, there's no one-size-fits all. But there are some patterns that could help understanding and implementing them. To give three examples: + +### Adding some logic to a proof verification + +This would be an approach for something like our guessing game, where proofs are sent back and forth and are verified by each opponent. This circuit would be divided in two sections: + +- A `recursive verification` section, which would be just the call to `std::verify_proof`, and that would be skipped on the first move (since there's no proof to verify) +- A `guessing` section, which is basically the logic part where the actual guessing happens + +In such a situation, and assuming Alice is first, she would skip the first part and try to guess Bob's number. Bob would then verify her proof on the first section of his run, and try to guess Alice's number on the second part, and so on. + +### Aggregating proofs + +In some one-way interaction situations, recursion would allow for aggregation of simple proofs that don't need to be immediately verified on-chain or elsewhere. + +To give a practical example, a barman wouldn't need to verify a "proof-of-age" on-chain every time he serves alcohol to a customer. Instead, the architecture would comprise two circuits: + +- A `main`, non-recursive circuit with some logic +- A `recursive` circuit meant to verify two proofs in one proof + +The customer's proofs would be intermediate, and made on their phones, and the barman could just verify them locally. He would then aggregate them into a final proof sent on-chain (or elsewhere) at the end of the day. + +### Recursively verifying different circuits + +Nothing prevents you from verifying different circuits in a recursive proof, for example: + +- A `circuit1` circuit +- A `circuit2` circuit +- A `recursive` circuit + +In this example, a regulator could verify that taxes were paid for a specific purchase by aggregating both a `payer` circuit (proving that a purchase was made and taxes were paid), and a `receipt` circuit (proving that the payment was received) + +## How fast is it + +At the time of writing, verifying recursive proofs is surprisingly fast. This is because most of the time is spent on generating the verification key that will be used to generate the next proof. So you are able to cache the verification key and reuse it later. + +Currently, Noir JS packages don't expose the functionality of loading proving and verification keys, but that feature exists in the underlying `bb.js` package. + +## How can I try it + +Learn more about using recursion in Nargo and NoirJS in the [how-to guide](../how_to/how-to-recursion.md) and see a full example in [noir-examples](https://github.com/noir-lang/noir-examples). diff --git a/docs/versioned_docs/version-v0.30.0/getting_started/_category_.json b/docs/versioned_docs/version-v0.30.0/getting_started/_category_.json new file mode 100644 index 00000000000..5d694210bbf --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/getting_started/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 0, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.30.0/getting_started/hello_noir/_category_.json b/docs/versioned_docs/version-v0.30.0/getting_started/hello_noir/_category_.json new file mode 100644 index 00000000000..23b560f610b --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/getting_started/hello_noir/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 1, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.30.0/getting_started/hello_noir/index.md b/docs/versioned_docs/version-v0.30.0/getting_started/hello_noir/index.md new file mode 100644 index 00000000000..743c4d8d634 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/getting_started/hello_noir/index.md @@ -0,0 +1,142 @@ +--- +title: Creating a Project +description: + Learn how to create and verify your first Noir program using Nargo, a programming language for + zero-knowledge proofs. +keywords: + [ + Nargo, + Noir, + zero-knowledge proofs, + programming language, + create Noir program, + verify Noir program, + step-by-step guide, + ] +sidebar_position: 1 + +--- + +Now that we have installed Nargo, it is time to make our first hello world program! + +## Create a Project Directory + +Noir code can live anywhere on your computer. Let us create a _projects_ folder in the home +directory to house our Noir programs. + +For Linux, macOS, and Windows PowerShell, create the directory and change directory into it by +running: + +```sh +mkdir ~/projects +cd ~/projects +``` + +## Create Our First Nargo Project + +Now that we are in the projects directory, create a new Nargo project by running: + +```sh +nargo new hello_world +``` + +> **Note:** `hello_world` can be any arbitrary project name, we are simply using `hello_world` for +> demonstration. +> +> In production, the common practice is to name the project folder as `circuits` for better +> identifiability when sitting alongside other folders in the codebase (e.g. `contracts`, `scripts`, +> `test`). + +A `hello_world` folder would be created. Similar to Rust, the folder houses _src/main.nr_ and +_Nargo.toml_ which contain 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](../../noir/concepts/data_types/index.md) section. + +The next line of the program specifies its body: + +```rust +assert(x != y); +``` + +The Noir syntax `assert` can be interpreted as something similar to constraints in other zk-contract languages. + +For more Noir syntax, check the [Language Concepts](../../noir/concepts/comments.md) chapter. + +## Build In/Output Files + +Change directory into _hello_world_ and build in/output files for your Noir program by running: + +```sh +cd hello_world +nargo check +``` + +Two additional files would be generated in your project directory: + +_Prover.toml_ houses input values, and _Verifier.toml_ houses public values. + +## Prove Our Noir Program + +Now that the project is set up, we can create a proof of correct execution of 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](./project_breakdown.md), we will go into more detail on each step performed. diff --git a/docs/versioned_docs/version-v0.30.0/getting_started/hello_noir/project_breakdown.md b/docs/versioned_docs/version-v0.30.0/getting_started/hello_noir/project_breakdown.md new file mode 100644 index 00000000000..6160a102c6c --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/getting_started/hello_noir/project_breakdown.md @@ -0,0 +1,199 @@ +--- +title: Project Breakdown +description: + Learn about the anatomy of a Nargo project, including the purpose of the Prover and Verifier TOML + files, and how to prove and verify your program. +keywords: + [Nargo, Nargo project, Prover.toml, Verifier.toml, proof verification, private asset transfer] +sidebar_position: 2 +--- + +This section breaks down our hello world program from the previous section. We elaborate on the project +structure and what the `prove` and `verify` commands did. + +## 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 = "noir_starter" +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](../../noir/modules_packages_crates/workspaces.md) will look a bit different. For example: + +```toml +[workspace] +members = ["crates/a", "crates/b"] +default-member = "crates/a" +``` + +#### Package section + +The package section defines 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](../../noir/modules_packages_crates/dependencies.md) for more info. + +`./proofs/` and `./contract/` directories will not be immediately visible until you create a proof or +verifier contract respectively. + +### main.nr + +The _main.nr_ file contains a `main` method, this method is the entry point into your Noir program. + +In our sample program, _main.nr_ looks like this: + +```rust +fn main(x : Field, y : Field) { + assert(x != y); +} +``` + +The parameters `x` and `y` can be seen as the API for the program and must be supplied by the +prover. Since neither `x` nor `y` is marked as public, the verifier does not supply any inputs, when +verifying the proof. + +The prover supplies the values for `x` and `y` in the _Prover.toml_ file. + +As for the program body, `assert` ensures that the condition to be satisfied (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 inequality 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, usually from external sources, and +verify the validity of the proof against it. + +Take a private asset transfer as an example: + +A person using a browser as the prover would retrieve private inputs locally (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.30.0/getting_started/installation/_category_.json b/docs/versioned_docs/version-v0.30.0/getting_started/installation/_category_.json new file mode 100644 index 00000000000..0c02fb5d4d7 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/getting_started/installation/_category_.json @@ -0,0 +1,6 @@ +{ + "position": 0, + "label": "Install Nargo", + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.30.0/getting_started/installation/index.md b/docs/versioned_docs/version-v0.30.0/getting_started/installation/index.md new file mode 100644 index 00000000000..4ef86aa5914 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/getting_started/installation/index.md @@ -0,0 +1,48 @@ +--- +title: Nargo Installation +description: + nargo is a command line tool for interacting with Noir programs. This page is a quick guide on how to install Nargo through the most common and easy method, noirup +keywords: [ + Nargo + Noir + Rust + Cargo + Noirup + Installation + Terminal Commands + Version Check + Nightlies + Specific Versions + Branches + Noirup Repository +] +pagination_next: getting_started/hello_noir/index +--- + +`nargo` is the one-stop-shop for almost everything related with Noir. The name comes from our love for Rust and its package manager `cargo`. + +With `nargo`, you can start new projects, compile, execute, prove, verify, test, generate solidity contracts, and do pretty much all that is available in Noir. + +Similarly to `rustup`, we also maintain an easy installation method that covers most machines: `noirup`. + +## Installing Noirup + +Open a terminal on your machine, and write: + +```bash +curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash +``` + +Close the terminal, open another one, and run + +```bash +noirup +``` + +Done. That's it. You should have the latest version working. You can check with `nargo --version`. + +You can also install nightlies, specific versions +or branches. Check out the [noirup repository](https://github.com/noir-lang/noirup) for more +information. + +Now we're ready to start working on [our first Noir program!](../hello_noir/index.md) diff --git a/docs/versioned_docs/version-v0.30.0/getting_started/installation/other_install_methods.md b/docs/versioned_docs/version-v0.30.0/getting_started/installation/other_install_methods.md new file mode 100644 index 00000000000..3634723562b --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/getting_started/installation/other_install_methods.md @@ -0,0 +1,102 @@ +--- +title: Alternative Installations +description: There are different ways to install Nargo, the one-stop shop and command-line tool for developing Noir programs. This guide explains how to specify which version to install when using noirup, and using WSL for windows. +keywords: [ + Installation + Nargo + Noirup + Binaries + Compiling from Source + WSL for Windows + macOS + Linux + Nix + Direnv + Uninstalling Nargo + ] +sidebar_position: 1 +--- + +## Encouraged Installation Method: Noirup + +Noirup is the endorsed method for installing Nargo, streamlining the process of fetching binaries or compiling from source. It supports a range of options to cater to your specific needs, from nightly builds and specific versions to compiling from various sources. + +### Installing Noirup + +First, ensure you have `noirup` installed: + +```sh +curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash +``` + +### Fetching Binaries + +With `noirup`, you can easily switch between different Nargo versions, including nightly builds: + +- **Nightly Version**: Install the latest nightly build. + + ```sh + noirup --version nightly + ``` + +- **Specific Version**: Install a specific version of Nargo. + ```sh + noirup --version + ``` + +### Compiling from Source + +`noirup` also enables compiling Nargo from various sources: + +- **From a Specific Branch**: Install from the latest commit on a branch. + + ```sh + noirup --branch + ``` + +- **From a Fork**: Install from the main branch of a fork. + + ```sh + noirup --repo + ``` + +- **From a Specific Branch in a Fork**: Install from a specific branch in a fork. + + ```sh + noirup --repo --branch + ``` + +- **From a Specific Pull Request**: Install from a specific PR. + + ```sh + noirup --pr + ``` + +- **From a Specific Commit**: Install from a specific commit. + + ```sh + noirup -C + ``` + +- **From Local Source**: Compile and install from a local directory. + ```sh + noirup --path ./path/to/local/source + ``` + +## Installation on Windows + +The default backend for Noir (Barretenberg) doesn't provide Windows binaries at this time. For that reason, Noir cannot be installed natively. 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](#encouraged-installation-method-noirup). + +## Uninstalling Nargo + +If you installed Nargo with `noirup`, you can uninstall Nargo by removing the files in `~/.nargo`, `~/nargo`, and `~/noir_cache`. This ensures that all installed binaries, configurations, and cache related to Nargo are fully removed from your system. + +```bash +rm -r ~/.nargo +rm -r ~/nargo +rm -r ~/noir_cache +``` diff --git a/docs/versioned_docs/version-v0.30.0/getting_started/tooling/noir_codegen.md b/docs/versioned_docs/version-v0.30.0/getting_started/tooling/noir_codegen.md new file mode 100644 index 00000000000..d65151da0ab --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/getting_started/tooling/noir_codegen.md @@ -0,0 +1,113 @@ +--- +title: Noir Codegen for TypeScript +description: Learn how to use Noir codegen to generate TypeScript bindings +keywords: [Nargo, Noir, compile, TypeScript] +sidebar_position: 2 +--- + +When using TypeScript, it is extra work to interpret Noir program outputs in a type-safe way. Third party libraries may exist for popular Noir programs, but they are either hard to find or unmaintained. + +Now you can generate TypeScript bindings for your Noir programs in two steps: +1. Exporting Noir functions using `nargo export` +2. Using the TypeScript module `noir_codegen` to generate TypeScript binding + +**Note:** you can only export functions from a Noir *library* (not binary or contract program types). + +## Installation + +### Your TypeScript project + +If you don't already have a TypeScript project you can add the module with `yarn` (or `npm`), then initialize it: + +```bash +yarn add typescript -D +npx tsc --init +``` + +### Add TypeScript module - `noir_codegen` + +The following command will add the module to your project's devDependencies: + +```bash +yarn add @noir-lang/noir_codegen -D +``` + +### Nargo library +Make sure you have Nargo, v0.25.0 or greater, installed. If you don't, follow the [installation guide](../installation/index.md). + +If you're in a new project, make a `circuits` folder and create a new Noir library: + +```bash +mkdir circuits && cd circuits +nargo new --lib myNoirLib +``` + +## Usage + +### Export ABI of specified functions + +First go to the `.nr` files in your Noir library, and add the `#[export]` macro to each function that you want to use in TypeScript. + +```rust +#[export] +fn your_function(... +``` + +From your Noir library (where `Nargo.toml` is), run the following command: + +```bash +nargo export +``` + +You will now have an `export` directory with a .json file per exported function. + +You can also specify the directory of Noir programs using `--program-dir`, for example: + +```bash +nargo export --program-dir=./circuits/myNoirLib +``` + +### Generate TypeScript bindings from exported functions + +To use the `noir-codegen` package we added to the TypeScript project: + +```bash +yarn noir-codegen ./export/your_function.json +``` + +This creates an `exports` directory with an `index.ts` file containing all exported functions. + +**Note:** adding `--out-dir` allows you to specify an output dir for your TypeScript bindings to go. Eg: + +```bash +yarn noir-codegen ./export/*.json --out-dir ./path/to/output/dir +``` + +## Example .nr function to .ts output + +Consider a Noir library with this function: + +```rust +#[export] +fn not_equal(x: Field, y: Field) -> bool { + x != y +} +``` + +After the export and codegen steps, you should have an `index.ts` like: + +```typescript +export type Field = string; + + +export const is_equal_circuit: CompiledCircuit = {"abi":{"parameters":[{"name":"x","type":{"kind":"field"},"visibility":"private"},{"name":"y","type":{"kind":"field"},"visibility":"private"}],"param_witnesses":{"x":[{"start":0,"end":1}],"y":[{"start":1,"end":2}]},"return_type":{"abi_type":{"kind":"boolean"},"visibility":"private"},"return_witnesses":[4]},"bytecode":"H4sIAAAAAAAA/7WUMQ7DIAxFQ0Krrr2JjSGYLVcpKrn/CaqqDQN12WK+hPBgmWd/wEyHbF1SS923uhOs3pfoChI+wKXMAXzIKyNj4PB0TFTYc0w5RUjoqeAeEu1wqK0F54RGkWvW44LPzExnlkbMEs4JNZmN8PxS42uHv82T8a3Jeyn2Ks+VLPcO558HmyLMCDOXAXXtpPt4R/Rt9T36ss6dS9HGPx/eG17nGegKBQAA"}; + +export async function is_equal(x: Field, y: Field, foreignCallHandler?: ForeignCallHandler): Promise { + const program = new Noir(is_equal_circuit); + const args: InputMap = { x, y }; + const { returnValue } = await program.execute(args, foreignCallHandler); + return returnValue as boolean; +} +``` + +Now the `is_equal()` function and relevant types are readily available for use in TypeScript. diff --git a/docs/versioned_docs/version-v0.30.0/how_to/_category_.json b/docs/versioned_docs/version-v0.30.0/how_to/_category_.json new file mode 100644 index 00000000000..23b560f610b --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/how_to/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 1, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.30.0/how_to/debugger/_category_.json b/docs/versioned_docs/version-v0.30.0/how_to/debugger/_category_.json new file mode 100644 index 00000000000..cc2cbb1c253 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/how_to/debugger/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Debugging", + "position": 5, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.30.0/how_to/debugger/debugging_with_the_repl.md b/docs/versioned_docs/version-v0.30.0/how_to/debugger/debugging_with_the_repl.md new file mode 100644 index 00000000000..09e5bae68ad --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/how_to/debugger/debugging_with_the_repl.md @@ -0,0 +1,164 @@ +--- +title: Using the REPL Debugger +description: + Step by step guide on how to debug your Noir circuits with the REPL Debugger. +keywords: + [ + Nargo, + Noir CLI, + Noir Debugger, + REPL, + ] +sidebar_position: 1 +--- + +#### Pre-requisites + +In order to use the REPL debugger, first you need to install recent enough versions of Nargo and vscode-noir. + +## Debugging a simple circuit + +Let's debug a simple circuit: + +```rust +fn main(x : Field, y : pub Field) { + assert(x != y); +} +``` + +To start the REPL debugger, using a terminal, go to a Noir circuit's home directory. Then: + +`$ nargo debug` + +You should be seeing this in your terminal: + +``` +[main] Starting debugger +At ~/noir-examples/recursion/circuits/main/src/main.nr:1:9 + 1 -> fn main(x : Field, y : pub Field) { + 2 assert(x != y); + 3 } +> +``` + +The debugger displays the current Noir code location, and it is now waiting for us to drive it. + +Let's first take a look at the available commands. For that we'll use the `help` command. + +``` +> help +Available commands: + + opcodes display ACIR opcodes + into step into to the next opcode + next step until a new source location is reached + out step until a new source location is reached + and the current stack frame is finished + break LOCATION:OpcodeLocation add a breakpoint at an opcode location + over step until a new source location is reached + without diving into function calls + restart restart the debugging session + delete LOCATION:OpcodeLocation delete breakpoint at an opcode location + witness show witness map + witness index:u32 display a single witness from the witness map + witness index:u32 value:String update a witness with the given value + memset index:usize value:String update a memory cell with the given + value + continue continue execution until the end of the + program + vars show variable values available at this point + in execution + stacktrace display the current stack trace + memory show memory (valid when executing unconstrained code) + step step to the next ACIR opcode + +Other commands: + + help Show this help message + quit Quit repl + +``` + +Some commands operate only for unconstrained functions, such as `memory` and `memset`. If you try to use them while execution is paused at an ACIR opcode, the debugger will simply inform you that you are not executing unconstrained code: + +``` +> memory +Unconstrained VM memory not available +> +``` + +Before continuing, we can take a look at the initial witness map: + +``` +> witness +_0 = 1 +_1 = 2 +> +``` + +Cool, since `x==1`, `y==2`, and we want to check that `x != y`, our circuit should succeed. At this point we could intervene and use the witness setter command to change one of the witnesses. Let's set `y=3`, then back to 2, so we don't affect the expected result: + +``` +> witness +_0 = 1 +_1 = 2 +> witness 1 3 +_1 = 3 +> witness +_0 = 1 +_1 = 3 +> witness 1 2 +_1 = 2 +> witness +_0 = 1 +_1 = 2 +> +``` + +Now we can inspect the current state of local variables. For that we use the `vars` command. + +``` +> vars +> +``` + +We currently have no vars in context, since we are at the entry point of the program. Let's use `next` to execute until the next point in the program. + +``` +> vars +> next +At ~/noir-examples/recursion/circuits/main/src/main.nr:1:20 + 1 -> fn main(x : Field, y : pub Field) { + 2 assert(x != y); + 3 } +> vars +x:Field = 0x01 +``` + +As a result of stepping, the variable `x`, whose initial value comes from the witness map, is now in context and returned by `vars`. + +``` +> next + 1 fn main(x : Field, y : pub Field) { + 2 -> assert(x != y); + 3 } +> vars +y:Field = 0x02 +x:Field = 0x01 +``` + +Stepping again we can finally see both variables and their values. And now we can see that the next assertion should succeed. + +Let's continue to the end: + +``` +> continue +(Continuing execution...) +Finished execution +> q +[main] Circuit witness successfully solved +``` + +Upon quitting the debugger after a solved circuit, the resulting circuit witness gets saved, equivalent to what would happen if we had run the same circuit with `nargo execute`. + +We just went through the basics of debugging using Noir REPL debugger. For a comprehensive reference, check out [the reference page](../../reference/debugger/debugger_repl.md). diff --git a/docs/versioned_docs/version-v0.30.0/how_to/debugger/debugging_with_vs_code.md b/docs/versioned_docs/version-v0.30.0/how_to/debugger/debugging_with_vs_code.md new file mode 100644 index 00000000000..a5858c1a5eb --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/how_to/debugger/debugging_with_vs_code.md @@ -0,0 +1,68 @@ +--- +title: Using the VS Code Debugger +description: + Step by step guide on how to debug your Noir circuits with the VS Code Debugger configuration and features. +keywords: + [ + Nargo, + Noir CLI, + Noir Debugger, + VS Code, + IDE, + ] +sidebar_position: 0 +--- + +This guide will show you how to use VS Code with the vscode-noir extension to debug a Noir project. + +#### Pre-requisites + +- Nargo +- vscode-noir +- A Noir project with a `Nargo.toml`, `Prover.toml` and at least one Noir (`.nr`) containing an entry point function (typically `main`). + +## Running the debugger + +The easiest way to start debugging is to open the file you want to debug, and press `F5`. This will cause the debugger to launch, using your `Prover.toml` file as input. + +You should see something like this: + +![Debugger launched](@site/static/img/debugger/1-started.png) + +Let's inspect the state of the program. For that, we open VS Code's _Debug pane_. Look for this icon: + +![Debug pane icon](@site/static/img/debugger/2-icon.png) + +You will now see two categories of variables: Locals and Witness Map. + +![Debug pane expanded](@site/static/img/debugger/3-debug-pane.png) + +1. **Locals**: variables of your program. At this point in execution this section is empty, but as we step through the code it will get populated by `x`, `result`, `digest`, etc. + +2. **Witness map**: these are initially populated from your project's `Prover.toml` file. In this example, they will be used to populate `x` and `result` at the beginning of the `main` function. + +Most of the time you will probably be focusing mostly on locals, as they represent the high level state of your program. + +You might be interested in inspecting the witness map in case you are trying to solve a really low level issue in the compiler or runtime itself, so this concerns mostly advanced or niche users. + +Let's step through the program, by using the debugger buttons or their corresponding keyboard shortcuts. + +![Debugger buttons](@site/static/img/debugger/4-debugger-buttons.png) + +Now we can see in the variables pane that there's values for `digest`, `result` and `x`. + +![Inspecting locals](@site/static/img/debugger/5-assert.png) + +We can also inspect the values of variables by directly hovering on them on the code. + +![Hover locals](@site/static/img/debugger/6-hover.png) + +Let's set a break point at the `keccak256` function, so we can continue execution up to the point when it's first invoked without having to go one step at a time. + +We just need to click the to the right of the line number 18. Once the breakpoint appears, we can click the `continue` button or use its corresponding keyboard shortcut (`F5` by default). + +![Breakpoint](@site/static/img/debugger/7-break.png) + +Now we are debugging the `keccak256` function, notice the _Call Stack pane_ at the lower right. This lets us inspect the current call stack of our process. + +That covers most of the current debugger functionalities. Check out [the reference](../../reference/debugger/debugger_vscode.md) for more details on how to configure the debugger. \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.30.0/how_to/how-to-oracles.md b/docs/versioned_docs/version-v0.30.0/how_to/how-to-oracles.md new file mode 100644 index 00000000000..8cf8035a5c4 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/how_to/how-to-oracles.md @@ -0,0 +1,276 @@ +--- +title: How to use Oracles +description: Learn how to use oracles in your Noir program with examples in both Nargo and NoirJS. This guide also covers writing a JSON RPC server and providing custom foreign call handlers for NoirJS. +keywords: + - Noir Programming + - Oracles + - Nargo + - NoirJS + - JSON RPC Server + - Foreign Call Handlers +sidebar_position: 1 +--- + +This guide shows you how to use oracles in your Noir program. For the sake of clarity, it assumes that: + +- You have read the [explainer on Oracles](../explainers/explainer-oracle.md) and are comfortable with the concept. +- You have a Noir program to add oracles to. You can create one using the [vite-hardhat starter](https://github.com/noir-lang/noir-starter/tree/main/vite-hardhat) as a boilerplate. +- You understand the concept of a JSON-RPC server. Visit the [JSON-RPC website](https://www.jsonrpc.org/) if you need a refresher. +- You are comfortable with server-side JavaScript (e.g. Node.js, managing packages, etc.). + +For reference, you can find the snippets used in this tutorial on the [Aztec DevRel Repository](https://github.com/AztecProtocol/dev-rel/tree/main/code-snippets/how-to-oracles). + +## Rundown + +This guide has 3 major steps: + +1. How to modify our Noir program to make use of oracle calls as unconstrained functions +2. How to write a JSON RPC Server to resolve these oracle calls with Nargo +3. How to use them in Nargo and how to provide a custom resolver in NoirJS + +## Step 1 - Modify your Noir program + +An oracle is defined in a Noir program by defining two methods: + +- An unconstrained method - This tells the compiler that it is executing an [unconstrained functions](../noir/concepts//unconstrained.md). +- A decorated oracle method - This tells the compiler that this method is an RPC call. + +An example of an oracle that returns a `Field` would be: + +```rust +#[oracle(getSqrt)] +unconstrained fn sqrt(number: Field) -> Field { } + +unconstrained fn get_sqrt(number: Field) -> Field { + sqrt(number) +} +``` + +In this example, we're wrapping our oracle function in a unconstrained method, and decorating it with `oracle(getSqrt)`. We can then call the unconstrained function as we would call any other function: + +```rust +fn main(input: Field) { + let sqrt = get_sqrt(input); +} +``` + +In the next section, we will make this `getSqrt` (defined on the `sqrt` decorator) be a method of the RPC server Noir will use. + +:::danger + +As explained in the [Oracle Explainer](../explainers/explainer-oracle.md), this `main` function is unsafe unless you constrain its return value. For example: + +```rust +fn main(input: Field) { + let sqrt = get_sqrt(input); + assert(sqrt.pow_32(2) as u64 == input as u64); // <---- constrain the return of an oracle! +} +``` + +::: + +:::info + +Currently, oracles only work with single params or array params. For example: + +```rust +#[oracle(getSqrt)] +unconstrained fn sqrt([Field; 2]) -> [Field; 2] { } +``` + +::: + +## Step 2 - Write an RPC server + +Brillig will call *one* RPC server. Most likely you will have to write your own, and you can do it in whatever language you prefer. In this guide, we will do it in Javascript. + +Let's use the above example of an oracle that consumes an array with two `Field` and returns their square roots: + +```rust +#[oracle(getSqrt)] +unconstrained fn sqrt(input: [Field; 2]) -> [Field; 2] { } + +unconstrained fn get_sqrt(input: [Field; 2]) -> [Field; 2] { + sqrt(input) +} + +fn main(input: [Field; 2]) { + let sqrt = get_sqrt(input); + assert(sqrt[0].pow_32(2) as u64 == input[0] as u64); + assert(sqrt[1].pow_32(2) as u64 == input[1] as u64); +} +``` + +:::info + +Why square root? + +In general, computing square roots is computationally more expensive than multiplications, which takes a toll when speaking about ZK applications. In this case, instead of calculating the square root in Noir, we are using our oracle to offload that computation to be made in plain. In our circuit we can simply multiply the two values. + +::: + +Now, we should write the correspondent RPC server, starting with the [default JSON-RPC 2.0 boilerplate](https://www.npmjs.com/package/json-rpc-2.0#example): + +```js +import { JSONRPCServer } from "json-rpc-2.0"; +import express from "express"; +import bodyParser from "body-parser"; + +const app = express(); +app.use(bodyParser.json()); + +const server = new JSONRPCServer(); +app.post("/", (req, res) => { + const jsonRPCRequest = req.body; + server.receive(jsonRPCRequest).then((jsonRPCResponse) => { + if (jsonRPCResponse) { + res.json(jsonRPCResponse); + } else { + res.sendStatus(204); + } + }); +}); + +app.listen(5555); +``` + +Now, we will add our `getSqrt` method, as expected by the `#[oracle(getSqrt)]` decorator in our Noir code. It maps through the params array and returns their square roots: + +```js +server.addMethod("getSqrt", async (params) => { + const values = params[0].Array.map((field) => { + return `${Math.sqrt(parseInt(field, 16))}`; + }); + return { values: [{ Array: values }] }; +}); +``` + +:::tip + +Brillig expects an object with an array of values. Each value is an object declaring to be `Single` or `Array` and returning a field element *as a string*. For example: + +```json +{ "values": [{ "Array": ["1", "2"] }]} +{ "values": [{ "Single": "1" }]} +{ "values": [{ "Single": "1" }, { "Array": ["1", "2"] }]} +``` + +If you're using Typescript, the following types may be helpful in understanding the expected return value and making sure they're easy to follow: + +```js +interface SingleForeignCallParam { + Single: string, +} + +interface ArrayForeignCallParam { + Array: string[], +} + +type ForeignCallParam = SingleForeignCallParam | ArrayForeignCallParam; + +interface ForeignCallResult { + values: ForeignCallParam[], +} +``` + +::: + +## Step 3 - Usage with Nargo + +Using the [`nargo` CLI tool](../getting_started/installation/index.md), you can use oracles in the `nargo test`, `nargo execute` and `nargo prove` commands by passing a value to `--oracle-resolver`. For example: + +```bash +nargo test --oracle-resolver http://localhost:5555 +``` + +This tells `nargo` to use your RPC Server URL whenever it finds an oracle decorator. + +## Step 4 - Usage with NoirJS + +In a JS environment, an RPC server is not strictly necessary, as you may want to resolve your oracles without needing any JSON call at all. NoirJS simply expects that you pass a callback function when you generate proofs, and that callback function can be anything. + +For example, if your Noir program expects the host machine to provide CPU pseudo-randomness, you could simply pass it as the `foreignCallHandler`. You don't strictly need to create an RPC server to serve pseudo-randomness, as you may as well get it directly in your app: + +```js +const foreignCallHandler = (name, inputs) => crypto.randomBytes(16) // etc + +await noir.generateProof(inputs, foreignCallHandler) +``` + +As one can see, in NoirJS, the [`foreignCallHandler`](../reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md) function simply means "a callback function that returns a value of type [`ForeignCallOutput`](../reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md). It doesn't have to be an RPC call like in the case for Nargo. + +:::tip + +Does this mean you don't have to write an RPC server like in [Step #2](#step-2---write-an-rpc-server)? + +You don't technically have to, but then how would you run `nargo test` or `nargo prove`? To use both `Nargo` and `NoirJS` in your development flow, you will have to write a JSON RPC server. + +::: + +In this case, let's make `foreignCallHandler` call the JSON RPC Server we created in [Step #2](#step-2---write-an-rpc-server), by making it a JSON RPC Client. + +For example, using the same `getSqrt` program in [Step #1](#step-1---modify-your-noir-program) (comments in the code): + +```js +import { JSONRPCClient } from "json-rpc-2.0"; + +// declaring the JSONRPCClient +const client = new JSONRPCClient((jsonRPCRequest) => { +// hitting the same JSON RPC Server we coded above + return fetch("http://localhost:5555", { + method: "POST", + headers: { + "content-type": "application/json", + }, + body: JSON.stringify(jsonRPCRequest), + }).then((response) => { + if (response.status === 200) { + return response + .json() + .then((jsonRPCResponse) => client.receive(jsonRPCResponse)); + } else if (jsonRPCRequest.id !== undefined) { + return Promise.reject(new Error(response.statusText)); + } + }); +}); + +// declaring a function that takes the name of the foreign call (getSqrt) and the inputs +const foreignCallHandler = async (name, input) => { + // notice that the "inputs" parameter contains *all* the inputs + // in this case we to make the RPC request with the first parameter "numbers", which would be input[0] + const oracleReturn = await client.request(name, [ + { Array: input[0].map((i) => i.toString("hex")) }, + ]); + return [oracleReturn.values[0].Array]; +}; + +// the rest of your NoirJS code +const input = { input: [4, 16] }; +const { witness } = await noir.execute(numbers, foreignCallHandler); +``` + +:::tip + +If you're in a NoirJS environment running your RPC server together with a frontend app, you'll probably hit a familiar problem in full-stack development: requests being blocked by [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) policy. For development only, you can simply install and use the [`cors` npm package](https://www.npmjs.com/package/cors) to get around the problem: + +```bash +yarn add cors +``` + +and use it as a middleware: + +```js +import cors from "cors"; + +const app = express(); +app.use(cors()) +``` + +::: + +## Conclusion + +Hopefully by the end of this guide, you should be able to: + +- Write your own logic around Oracles and how to write a JSON RPC server to make them work with your Nargo commands. +- Provide custom foreign call handlers for NoirJS. diff --git a/docs/versioned_docs/version-v0.30.0/how_to/how-to-recursion.md b/docs/versioned_docs/version-v0.30.0/how_to/how-to-recursion.md new file mode 100644 index 00000000000..4c45bb87ae2 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/how_to/how-to-recursion.md @@ -0,0 +1,179 @@ +--- +title: How to use recursion on NoirJS +description: Learn how to implement recursion with NoirJS, a powerful tool for creating smart contracts on the EVM blockchain. This guide assumes familiarity with NoirJS, solidity verifiers, and the Barretenberg proving backend. Discover how to generate both final and intermediate proofs using `noir_js` and `backend_barretenberg`. +keywords: + [ + "NoirJS", + "EVM blockchain", + "smart contracts", + "recursion", + "solidity verifiers", + "Barretenberg backend", + "noir_js", + "backend_barretenberg", + "intermediate proofs", + "final proofs", + "nargo compile", + "json import", + "recursive circuit", + "recursive app" + ] +sidebar_position: 1 +--- + +This guide shows you how to use recursive proofs in your NoirJS app. For the sake of clarity, it is assumed that: + +- You already have a NoirJS app. If you don't, please visit the [NoirJS tutorial](../tutorials/noirjs_app.md) and the [reference](../reference/NoirJS/noir_js/index.md). +- You are familiar with what are recursive proofs and you have read the [recursion explainer](../explainers/explainer-recursion.md) +- You already built a recursive circuit following [the reference](../noir/standard_library/recursion.md), and understand how it works. + +It is also assumed that you're not using `noir_wasm` for compilation, and instead you've used [`nargo compile`](../reference/nargo_commands.md) to generate the `json` you're now importing into your project. However, the guide should work just the same if you're using `noir_wasm`. + +:::info + +As you've read in the [explainer](../explainers/explainer-recursion.md), a recursive proof is an intermediate proof. This means that it doesn't necessarily generate the final step that makes it verifiable in a smart contract. However, it is easy to verify within another circuit. + +While "standard" usage of NoirJS packages abstracts final proofs, it currently lacks the necessary interface to abstract away intermediate proofs. This means that these proofs need to be created by using the backend directly. + +In short: + +- `noir_js` generates *only* final proofs +- `backend_barretenberg` generates both types of proofs + +::: + +In a standard recursive app, you're also dealing with at least two circuits. For the purpose of this guide, we will assume the following: + +- `main`: a circuit of type `assert(x != y)`, where `main` is marked with a `#[recursive]` attribute. This attribute states that the backend should generate proofs that are friendly for verification within another circuit. +- `recursive`: a circuit that verifies `main` + +For a full example on how recursive proofs work, please refer to the [noir-examples](https://github.com/noir-lang/noir-examples) repository. We will *not* be using it as a reference for this guide. + +## Step 1: Setup + +In a common NoirJS app, you need to instantiate a backend with something like `const backend = new Backend(circuit)`. Then you feed it to the `noir_js` interface. + +For recursion, this doesn't happen, and the only need for `noir_js` is only to `execute` a circuit and get its witness and return value. Everything else is not interfaced, so it needs to happen on the `backend` object. + +It is also recommended that you instantiate the backend with as many threads as possible, to allow for maximum concurrency: + +```js +const backend = new Backend(circuit, { threads: 8 }) +``` + +:::tip +You can use the [`os.cpus()`](https://nodejs.org/api/os.html#oscpus) object in `nodejs` or [`navigator.hardwareConcurrency`](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/hardwareConcurrency) on the browser to make the most out of those glorious cpu cores +::: + +## Step 2: Generating the witness and the proof for `main` + +After instantiating the backend, you should also instantiate `noir_js`. We will use it to execute the circuit and get the witness. + +```js +const noir = new Noir(circuit, backend) +const { witness } = noir.execute(input) +``` + +With this witness, you are now able to generate the intermediate proof for the main circuit: + +```js +const { proof, publicInputs } = await backend.generateProof(witness) +``` + +:::warning + +Always keep in mind what is actually happening on your development process, otherwise you'll quickly become confused about what circuit we are actually running and why! + +In this case, you can imagine that Alice (running the `main` circuit) is proving something to Bob (running the `recursive` circuit), and Bob is verifying her proof within his proof. + +With this in mind, it becomes clear that our intermediate proof is the one *meant to be verified within another circuit*, so it must be Alice's. Actually, the only final proof in this theoretical scenario would be the last one, sent on-chain. + +::: + +## Step 3 - Verification and proof artifacts + +Optionally, you are able to verify the intermediate proof: + +```js +const verified = await backend.verifyProof({ proof, publicInputs }) +``` + +This can be useful to make sure our intermediate proof was correctly generated. But the real goal is to do it within another circuit. For that, we need to generate recursive proof artifacts that will be passed to the circuit that is verifying the proof we just generated. Instead of passing the proof and verification key as a byte array, we pass them as fields which makes it cheaper to verify in a circuit: + +```js +const { proofAsFields, vkAsFields, vkHash } = await backend.generateRecursiveProofArtifacts( { publicInputs, proof }, publicInputsCount) +``` + +This call takes the public inputs and the proof, but also the public inputs count. While this is easily retrievable by simply counting the `publicInputs` length, the backend interface doesn't currently abstract it away. + +:::info + +The `proofAsFields` has a constant size `[Field; 93]` and verification keys in Barretenberg are always `[Field; 114]`. + +::: + +:::warning + +One common mistake is to forget *who* makes this call. + +In a situation where Alice is generating the `main` proof, if she generates the proof artifacts and sends them to Bob, which gladly takes them as true, this would mean Alice could prove anything! + +Instead, Bob needs to make sure *he* extracts the proof artifacts, using his own instance of the `main` circuit backend. This way, Alice has to provide a valid proof for the correct `main` circuit. + +::: + +## Step 4 - Recursive proof generation + +With the artifacts, generating a recursive proof is no different from a normal proof. You simply use the `backend` (with the recursive circuit) to generate it: + +```js +const recursiveInputs = { + verification_key: vkAsFields, // array of length 114 + proof: proofAsFields, // array of length 93 + size of public inputs + publicInputs: [mainInput.y], // using the example above, where `y` is the only public input + key_hash: vkHash, +} + +const { witness, returnValue } = noir.execute(recursiveInputs) // we're executing the recursive circuit now! +const { proof, publicInputs } = backend.generateProof(witness) +const verified = backend.verifyProof({ proof, publicInputs }) +``` + +You can obviously chain this proof into another proof. In fact, if you're using recursive proofs, you're probably interested of using them this way! + +:::tip + +Managing circuits and "who does what" can be confusing. To make sure your naming is consistent, you can keep them in an object. For example: + +```js +const circuits = { + main: mainJSON, + recursive: recursiveJSON +} +const backends = { + main: new BarretenbergBackend(circuits.main), + recursive: new BarretenbergBackend(circuits.recursive) +} +const noir_programs = { + main: new Noir(circuits.main, backends.main), + recursive: new Noir(circuits.recursive, backends.recursive) +} +``` + +This allows you to neatly call exactly the method you want without conflicting names: + +```js +// Alice runs this 👇 +const { witness: mainWitness } = await noir_programs.main.execute(input) +const proof = await backends.main.generateProof(mainWitness) + +// Bob runs this 👇 +const verified = await backends.main.verifyProof(proof) +const { proofAsFields, vkAsFields, vkHash } = await backends.main.generateRecursiveProofArtifacts( + proof, + numPublicInputs, +); +const recursiveProof = await noir_programs.recursive.generateProof(recursiveInputs) +``` + +::: diff --git a/docs/versioned_docs/version-v0.30.0/how_to/how-to-solidity-verifier.md b/docs/versioned_docs/version-v0.30.0/how_to/how-to-solidity-verifier.md new file mode 100644 index 00000000000..e3c7c1065da --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/how_to/how-to-solidity-verifier.md @@ -0,0 +1,231 @@ +--- +title: Generate a Solidity Verifier +description: + Learn how to run the verifier as a smart contract on the blockchain. Compile a Solidity verifier + contract for your Noir program and deploy it on any EVM blockchain acting as a verifier smart + contract. Read more to find out +keywords: + [ + solidity verifier, + smart contract, + blockchain, + compiler, + plonk_vk.sol, + EVM blockchain, + verifying Noir programs, + proving backend, + Barretenberg, + ] +sidebar_position: 0 +pagination_next: tutorials/noirjs_app +--- + +Noir has the ability to generate a verifier contract in Solidity, which can be deployed in many EVM-compatible blockchains such as Ethereum. + +This allows for a powerful feature set, as one can make use of the conciseness and the privacy provided by Noir in an immutable ledger. Applications can range from simple P2P guessing games, to complex private DeFi interactions. + +This guide shows you how to generate a Solidity Verifier and deploy it on the [Remix IDE](https://remix.ethereum.org/). It is assumed that: + +- You are comfortable with the Solidity programming language and understand how contracts are deployed on the Ethereum network +- You have Noir installed and you have a Noir program. If you don't, [get started](../getting_started/installation/index.md) with Nargo and the example Hello Noir circuit +- You are comfortable navigating RemixIDE. If you aren't or you need a refresher, you can find some video tutorials [here](https://www.youtube.com/channel/UCjTUPyFEr2xDGN6Cg8nKDaA) that could help you. + +## Rundown + +Generating a Solidity Verifier contract is actually a one-command process. However, compiling it and deploying it can have some caveats. Here's the rundown of this guide: + +1. How to generate a solidity smart contract +2. How to compile the smart contract in the RemixIDE +3. How to deploy it to a testnet + +## Step 1 - Generate a contract + +This is by far the most straight-forward step. Just run: + +```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 to any EVM blockchain acting as a verifier smart contract. + +:::info + +It is possible to generate 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 generation of verifier contracts, for the time being these are only in Solidity. +::: + +## Step 2 - Compiling + +We will mostly skip the details of RemixIDE, as the UI can change from version to version. For now, we can just open +Remix and create a blank workspace. + +![Create Workspace](@site/static/img/how-tos/solidity_verifier_1.png) + +We will create a new file to contain the contract Nargo generated, and copy-paste its content. + +:::warning + +You'll likely see a warning advising you to not trust pasted code. While it is an important warning, it is irrelevant in the context of this guide and can be ignored. We will not be deploying anywhere near a mainnet. + +::: + +To compile our the verifier, we can navigate to the compilation tab: + +![Compilation Tab](@site/static/img/how-tos/solidity_verifier_2.png) + +Remix should automatically match a suitable compiler version. However, hitting the "Compile" button will most likely generate a "Stack too deep" error: + +![Stack too deep](@site/static/img/how-tos/solidity_verifier_3.png) + +This is due to the verify function needing to put many variables on the stack, but enabling the optimizer resolves the issue. To do this, let's open the "Advanced Configurations" tab and enable optimization. The default 200 runs will suffice. + +:::info + +This time we will see a warning about an unused function parameter. This is expected, as the `verify` function doesn't use the `_proof` parameter inside a solidity block, it is loaded from calldata and used in assembly. + +::: + +![Compilation success](@site/static/img/how-tos/solidity_verifier_4.png) + +## Step 3 - Deploying + +At this point we should have a compiled contract read to deploy. If we navigate to the deploy section in Remix, we will see many different environments we can deploy to. The steps to deploy on each environment would be out-of-scope for this guide, so we will just use the default Remix VM. + +Looking closely, we will notice that our "Solidity Verifier" is actually three contracts working together: + +- An `UltraVerificationKey` library which simply stores the verification key for our circuit. +- An abstract contract `BaseUltraVerifier` containing most of the verifying logic. +- A main `UltraVerifier` contract that inherits from the Base and uses the Key contract. + +Remix will take care of the dependencies for us so we can simply deploy the UltraVerifier contract by selecting it and hitting "deploy": + +![Deploying UltraVerifier](@site/static/img/how-tos/solidity_verifier_5.png) + +A contract will show up in the "Deployed Contracts" section, where we can retrieve the Verification Key Hash. This is particularly useful for double-checking the deployer contract is the correct one. + +:::note + +Why "UltraVerifier"? + +To be precise, the Noir compiler (`nargo`) doesn't generate the verifier contract directly. It compiles the Noir code into an intermediate language (ACIR), which is then executed by the backend. So it is the backend that returns the verifier smart contract, not Noir. + +In this case, the Barretenberg Backend uses the UltraPlonk proving system, hence the "UltraVerifier" name. + +::: + +## Step 4 - Verifying + +To verify a proof using the Solidity verifier contract, we call the `verify` function in this extended contract: + +```solidity +function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool) +``` + +When using the default example in the [Hello Noir](../getting_started/hello_noir/index.md) guide, the easiest way to confirm that the verifier contract is doing its job is by calling the `verify` function via remix with the required parameters. For `_proof`, run `nargo prove` and use the string in `proof/.proof` (adding the hex `0x` prefix). We can also copy the public input from `Verifier.toml`, as it will be properly formatted as 32-byte strings: + +``` +0x...... , [0x0000.....02] +``` + +A programmatic example of how the `verify` function is called can be seen 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"); +``` + +:::info[Return Values] + +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. + +For example, if you have Noir program like this: + +```rust +fn main( + // Public inputs + pubkey_x: pub Field, + pubkey_y: pub Field, + // Private inputs + priv_key: Field, +) -> pub Field +``` + +the `verify` function will expect the public inputs array (second function parameter) to be of length 3, the two inputs and the return value. Like before, these values are populated in Verifier.toml after running `nargo prove`. + +Passing only two inputs will result in an error such as `PUBLIC_INPUT_COUNT_INVALID(3, 2)`. + +In this case, the inputs parameter to `verify` would be an array ordered as `[pubkey_x, pubkey_y, return]`. + +::: + +:::tip[Structs] + +You can pass structs to the verifier contract. They will be flattened so that the array of inputs is 1-dimensional array. + +For example, 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) { + //... +} +``` + +The order of these inputs would be flattened to: `[x, nested.t1.val1, nested.t1.val2, nested.is_true, y]` + +::: + +The other function you can call is our entrypoint `verify` function, as defined above. + +:::tip + +It's worth noticing that the `verify` function is actually a `view` function. A `view` function does not alter the blockchain state, so it doesn't need to be distributed (i.e. it will run only on the executing node), and therefore doesn't cost any gas. + +This can be particularly useful in some situations. If Alice generated a proof and wants Bob to verify its correctness, Bob doesn't need to run Nargo, NoirJS, or any Noir specific infrastructure. He can simply make a call to the blockchain with the proof and verify it is correct without paying any gas. + +It would be incorrect to say that a Noir proof verification costs any gas at all. However, most of the time the result of `verify` is used to modify state (for example, to update a balance, a game state, etc). In that case the whole network needs to execute it, which does incur gas costs (calldata and execution, but not storage). + +::: + +## A Note on EVM chains + +ZK-SNARK verification depends on some precompiled cryptographic primitives such as Elliptic Curve Pairings (if you like complex math, you can read about EC Pairings [here](https://medium.com/@VitalikButerin/exploring-elliptic-curve-pairings-c73c1864e627)). Not all EVM chains support EC Pairings, notably some of the ZK-EVMs. This means that you won't be able to use the verifier contract in all of them. + +For example, chains like `zkSync ERA` and `Polygon zkEVM` do not currently support these precompiles, so proof verification via Solidity verifier contracts won't work. Here's a quick list of EVM chains that have been tested and are known to work: + +- Optimism +- Arbitrum +- Polygon PoS +- Scroll +- Celo + +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. + +## What's next + +Now that you know how to call a Noir Solidity Verifier on a smart contract using Remix, you should be comfortable with using it with some programmatic frameworks, such as [hardhat](https://github.com/noir-lang/noir-starter/tree/main/vite-hardhat) and [foundry](https://github.com/noir-lang/noir-starter/tree/main/with-foundry). + +You can find other tools, examples, boilerplates and libraries in the [awesome-noir](https://github.com/noir-lang/awesome-noir) repository. + +You should also be ready to write and deploy your first NoirJS app and start generating proofs on websites, phones, and NodeJS environments! Head on to the [NoirJS tutorial](../tutorials/noirjs_app.md) to learn how to do that. diff --git a/docs/versioned_docs/version-v0.30.0/how_to/merkle-proof.mdx b/docs/versioned_docs/version-v0.30.0/how_to/merkle-proof.mdx new file mode 100644 index 00000000000..16c425bed76 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/how_to/merkle-proof.mdx @@ -0,0 +1,49 @@ +--- +title: Prove Merkle Tree Membership +description: + Learn how to use merkle membership proof in Noir to prove that a given leaf is a member of a + merkle tree with a specified root, at a given index. +keywords: + [merkle proof, merkle membership proof, Noir, rust, hash function, Pedersen, sha256, merkle tree] +sidebar_position: 4 +--- + +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.as_slice()); + 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.as_slice()); +``` + +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.30.0/how_to/using-devcontainers.mdx b/docs/versioned_docs/version-v0.30.0/how_to/using-devcontainers.mdx new file mode 100644 index 00000000000..727ec6ca667 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/how_to/using-devcontainers.mdx @@ -0,0 +1,110 @@ +--- +title: Developer Containers and Codespaces +description: "Learn how to set up a devcontainer in your GitHub repository for a seamless coding experience with Codespaces. Follow our easy 8-step guide to create your own Noir environment without installing Nargo locally." +keywords: ["Devcontainer", "Codespaces", "GitHub", "Noir Environment", "Docker Image", "Development Environment", "Remote Coding", "GitHub Codespaces", "Noir Programming", "Nargo", "VSCode Extensions", "Noirup"] +sidebar_position: 1 +--- + +Adding a developer container configuration file to your Noir project is one of the easiest way to unlock coding in browser. + +## What's a devcontainer after all? + +A [Developer Container](https://containers.dev/) (devcontainer for short) is a Docker image that comes preloaded with tools, extensions, and other tools you need to quickly get started or continue a project, without having to install Nargo locally. Think of it as a development environment in a box. + +There are many advantages to this: + +- It's platform and architecture agnostic +- You don't need to have an IDE installed, or Nargo, or use a terminal at all +- It's safer for using on a public machine or public network + +One of the best ways of using devcontainers is... not using your machine at all, for maximum control, performance, and ease of use. +Enter Codespaces. + +## Codespaces + +If a devcontainer is just a Docker image, then what stops you from provisioning a `p3dn.24xlarge` AWS EC2 instance with 92 vCPUs and 768 GiB RAM and using it to prove your 10-gate SNARK proof? + +Nothing! Except perhaps the 30-40$ per hour it will cost you. + +The problem is that provisioning takes time, and I bet you don't want to see the AWS console every time you want to code something real quick. + +Fortunately, there's an easy and free way to get a decent remote machine ready and loaded in less than 2 minutes: Codespaces. [Codespaces is a Github feature](https://github.com/features/codespaces) that allows you to code in a remote machine by using devcontainers, and it's pretty cool: + +- You can start coding Noir in less than a minute +- It uses the resources of a remote machine, so you can code on your grandma's phone if needed be +- It makes it easy to share work with your frens +- It's fully reusable, you can stop and restart whenever you need to + +:::info + +Don't take out your wallet just yet. Free GitHub accounts get about [15-60 hours of coding](https://github.com/features/codespaces) for free per month, depending on the size of your provisioned machine. + +::: + +## Tell me it's _actually_ easy + +It is! + +Github comes with a default codespace and you can use it to code your own devcontainer. That's exactly what we will be doing in this guide. + + + +8 simple steps: + +#### 1. Create a new repository on GitHub. + +#### 2. Click "Start coding with Codespaces". This will use the default image. + +#### 3. Create a folder called `.devcontainer` in the root of your repository. + +#### 4. Create a Dockerfile in that folder, and paste the following code: + +```docker +FROM --platform=linux/amd64 node:lts-bookworm-slim +SHELL ["/bin/bash", "-c"] +RUN apt update && apt install -y curl bash git tar gzip libc++-dev +RUN curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash +ENV PATH="/root/.nargo/bin:$PATH" +RUN noirup +ENTRYPOINT ["nargo"] +``` +#### 5. Create a file called `devcontainer.json` in the same folder, and paste the following code: + +```json +{ + "name": "Noir on Codespaces", + "build": { + "context": ".", + "dockerfile": "Dockerfile" + }, + "customizations": { + "vscode": { + "extensions": ["noir-lang.vscode-noir"] + } + } +} +``` +#### 6. Commit and push your changes + +This will pull the new image and build it, so it could take a minute or so + +#### 8. Done! +Just wait for the build to finish, and there's your easy Noir environment. + + +Refer to [noir-starter](https://github.com/noir-lang/noir-starter/) as an example of how devcontainers can be used together with codespaces. + + + +## How do I use it? + +Using the codespace is obviously much easier than setting it up. +Just navigate to your repository and click "Code" -> "Open with Codespaces". It should take a few seconds to load, and you're ready to go. + +:::info + +If you really like the experience, you can add a badge to your readme, links to existing codespaces, and more. +Check out the [official docs](https://docs.github.com/en/codespaces/setting-up-your-project-for-codespaces/setting-up-your-repository/facilitating-quick-creation-and-resumption-of-codespaces) for more info. diff --git a/docs/versioned_docs/version-v0.30.0/index.mdx b/docs/versioned_docs/version-v0.30.0/index.mdx new file mode 100644 index 00000000000..75086ddcdde --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/index.mdx @@ -0,0 +1,67 @@ +--- +title: Noir Lang +hide_title: true +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] +sidebar_position: 0 +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +Noir Logo + +Noir is a Domain-Specific Language for SNARK proving systems developed by [Aztec Labs](https://aztec.network/). It allows you to generate complex Zero-Knowledge Programs (ZKP) by using simple and flexible syntax, requiring no previous knowledge on the underlying mathematics or cryptography. + +ZK programs are programs that can generate short proofs of a certain statement without revealing some details about it. You can read more about ZKPs [here](https://dev.to/spalladino/a-beginners-intro-to-coding-zero-knowledge-proofs-c56). + +## What's new about Noir? + +Noir works differently from most ZK languages by taking a two-pronged path. First, it compiles the program to an adaptable intermediate language known as ACIR. From there, depending on a given project's needs, ACIR can be further compiled into an arithmetic circuit for integration with the proving backend. + +:::info + +Noir is backend agnostic, which means it makes no assumptions on which proving backend powers the ZK proof. Being the language that powers [Aztec Contracts](https://docs.aztec.network/developers/contracts/main), it defaults to Aztec's Barretenberg proving backend. + +However, the ACIR output can be transformed to be compatible with other PLONK-based backends, or into a [rank-1 constraint system](https://www.rareskills.io/post/rank-1-constraint-system) suitable for backends such as Arkwork's Marlin. + +::: + +## Who is Noir for? + +Noir can be used both in complex cloud-based backends and in user's smartphones, requiring no knowledge on the underlying math or cryptography. From authorization systems that keep a password in the user's device, to complex on-chain verification of recursive proofs, Noir is designed to abstract away complexity without any significant overhead. Here are some examples of situations where Noir can be used: + + + + Noir Logo + + Aztec Contracts leverage Noir to allow for the storage and execution of private information. Writing an Aztec Contract is as easy as writing Noir, and Aztec developers can easily interact with the network storage and execution through the [Aztec.nr](https://docs.aztec.network/developers/contracts/main) library. + + + Soliditry Verifier Example + Noir can auto-generate Solidity verifier contracts that verify Noir proofs. This allows for non-interactive verification of proofs containing private information in an immutable system. This feature powers a multitude of use-case scenarios, from P2P chess tournaments, to [Aztec Layer-2 Blockchain](https://docs.aztec.network/) + + + Aztec Labs developed NoirJS, an easy interface to generate and verify Noir proofs in a Javascript environment. This allows for Noir to be used in webpages, mobile apps, games, and any other environment supporting JS execution in a standalone manner. + + + + +## Libraries + +Noir is meant to be easy to extend by simply importing Noir libraries just like in Rust. +The [awesome-noir repo](https://github.com/noir-lang/awesome-noir#libraries) is a collection of libraries developed by the Noir community. +Writing a new library is easy and makes code be composable and easy to reuse. See the section on [dependencies](noir/modules_packages_crates/dependencies.md) for more information. diff --git a/docs/versioned_docs/version-v0.30.0/migration_notes.md b/docs/versioned_docs/version-v0.30.0/migration_notes.md new file mode 100644 index 00000000000..6bd740024e5 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/migration_notes.md @@ -0,0 +1,105 @@ +--- +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. + +### `backend encountered an error: libc++.so.1` + +Depending on your OS, you may encounter the following error when running `nargo prove` for the first time: + +```text +The backend encountered an error: "/home/codespace/.nargo/backends/acvm-backend-barretenberg/backend_binary: error while loading shared libraries: libc++.so.1: cannot open shared object file: No such file or directory\n" +``` + +Install the `libc++-dev` library with: + +```bash +sudo apt install libc++-dev +``` + +## ≥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](noir/concepts/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 your 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 file is running [this bash script](https://github.com/noir-lang/barretenberg-js-binary/blob/master/run-bb-js.sh), where we need to gzip it as the Nargo currently expect the backend to be zipped up. + +Then run: + +``` +DESIRED_BINARY_VERSION=0.8.1 nargo info +``` + +This overrides the bb native binary with a bb.js node application instead, which should be compatible with most if not all hardware. This does come with the drawback of being generally slower than native binary. + +0.8.1 indicates bb.js version 0.8.1, so if you change that it will update to a different version or the default version in the script if none was supplied. diff --git a/docs/versioned_docs/version-v0.30.0/noir/concepts/_category_.json b/docs/versioned_docs/version-v0.30.0/noir/concepts/_category_.json new file mode 100644 index 00000000000..7da08f8a8c5 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/noir/concepts/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Concepts", + "position": 0, + "collapsible": true, + "collapsed": true +} \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.30.0/noir/concepts/assert.md b/docs/versioned_docs/version-v0.30.0/noir/concepts/assert.md new file mode 100644 index 00000000000..bcff613a695 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/noir/concepts/assert.md @@ -0,0 +1,45 @@ +--- +title: Assert Function +description: + Learn about the assert function in Noir, which can be used to explicitly constrain the predicate or + comparison expression that follows to be true, and what happens if the expression is false at + runtime. +keywords: [Noir programming language, assert statement, predicate expression, comparison expression] +sidebar_position: 4 +--- + +Noir includes a special `assert` function which will explicitly constrain the predicate/comparison +expression that follows to be true. If this expression is false at runtime, the program will fail to +be proven. Example: + +```rust +fn main(x : Field, y : Field) { + assert(x == y); +} +``` + +> 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`. + +You can optionally provide a message to be logged when the assertion fails: + +```rust +assert(x == y, "x and y are not equal"); +``` + +Aside string literals, the optional message can be a format string or any other type supported as input for Noir's [print](../standard_library/logging.md) functions. This feature lets you incorporate runtime variables into your failed assertion logs: + +```rust +assert(x == y, f"Expected x == y, but got {x} == {y}"); +``` + +Using a variable as an assertion message directly: + +```rust +struct myStruct { + myField: Field +} + +let s = myStruct { myField: y }; +assert(s.myField == x, s); +``` + diff --git a/docs/versioned_docs/version-v0.30.0/noir/concepts/comments.md b/docs/versioned_docs/version-v0.30.0/noir/concepts/comments.md new file mode 100644 index 00000000000..b51a85f5c94 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/noir/concepts/comments.md @@ -0,0 +1,33 @@ +--- +title: Comments +description: + Learn how to write comments in Noir programming language. A comment is a line of code that is + ignored by the compiler, but it can be read by programmers. Single-line and multi-line comments + are supported in Noir. +keywords: [Noir programming language, comments, single-line comments, multi-line comments] +sidebar_position: 10 +--- + +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.30.0/noir/concepts/control_flow.md b/docs/versioned_docs/version-v0.30.0/noir/concepts/control_flow.md new file mode 100644 index 00000000000..045d3c3a5f5 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/noir/concepts/control_flow.md @@ -0,0 +1,77 @@ +--- +title: Control Flow +description: + Learn how to use loops and if expressions in the Noir programming language. Discover the syntax + and examples for for loops and if-else statements. +keywords: [Noir programming language, loops, for loop, if-else statements, Rust syntax] +sidebar_position: 2 +--- + +## 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); +``` + +## 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`. + +### Break and Continue + +In unconstrained code, `break` and `continue` are also allowed in `for` loops. These are only allowed +in unconstrained code since normal constrained code requires that Noir knows exactly how many iterations +a loop may have. `break` and `continue` can be used like so: + +```rust +for i in 0 .. 10 { + println("Iteration start") + + if i == 2 { + continue; + } + + if i == 5 { + break; + } + + println(i); +} +println("Loop end") +``` + +When used, `break` will end the current loop early and jump to the statement after the for loop. In the example +above, the `break` will stop the loop and jump to the `println("Loop end")`. + +`continue` will stop the current iteration of the loop, and jump to the start of the next iteration. In the example +above, `continue` will jump to `println("Iteration start")` when used. Note that the loop continues as normal after this. +The iteration variable `i` is still increased by one as normal when `continue` is used. + +`break` and `continue` cannot currently be used to jump out of more than a single loop at a time. diff --git a/docs/versioned_docs/version-v0.30.0/noir/concepts/data_bus.md b/docs/versioned_docs/version-v0.30.0/noir/concepts/data_bus.md new file mode 100644 index 00000000000..e54fc861257 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/noir/concepts/data_bus.md @@ -0,0 +1,21 @@ +--- +title: Data Bus +sidebar_position: 13 +--- +**Disclaimer** this feature is experimental, do not use it! + +The data bus is an optimization that the backend can use to make recursion more efficient. +In order to use it, you must define some inputs of the program entry points (usually the `main()` +function) with the `call_data` modifier, and the return values with the `return_data` modifier. +These modifiers are incompatible with `pub` and `mut` modifiers. + +## Example + +```rust +fn main(mut x: u32, y: call_data u32, z: call_data [u32;4] ) -> return_data u32 { + let a = z[x]; + a+y +} +``` + +As a result, both call_data and return_data will be treated as private inputs and encapsulated into a read-only array each, for the backend to process. diff --git a/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/_category_.json b/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/_category_.json new file mode 100644 index 00000000000..5d694210bbf --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 0, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/arrays.md b/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/arrays.md new file mode 100644 index 00000000000..efce3e95d32 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/arrays.md @@ -0,0 +1,251 @@ +--- +title: Arrays +description: + Dive into the Array data type in Noir. Grasp its methods, practical examples, and best practices for efficiently using Arrays in your Noir code. +keywords: + [ + noir, + array type, + methods, + examples, + indexing, + ] +sidebar_position: 4 +--- + +An array is one way of grouping together values into one compound type. Array types can be inferred +or explicitly specified via the syntax `[; ]`: + +```rust +fn main(x : Field, y : Field) { + let my_arr = [x, y]; + let your_arr: [Field; 2] = [x, y]; +} +``` + +Here, both `my_arr` and `your_arr` are instantiated as an array containing two `Field` elements. + +Array elements can be accessed using indexing: + +```rust +fn main() { + let a = [1, 2, 3, 4, 5]; + + let first = a[0]; + let second = a[1]; +} +``` + +All elements in an array must be of the same type (i.e. homogeneous). That is, an array cannot group +a `Field` value and a `u8` value together for example. + +You can write mutable arrays, like: + +```rust +fn main() { + let mut arr = [1, 2, 3, 4, 5]; + assert(arr[0] == 1); + + arr[0] = 42; + assert(arr[0] == 42); +} +``` + +You can instantiate a new array of a fixed size with the same value repeated for each element. The following example instantiates an array of length 32 where each element is of type Field and has the value 0. + +```rust +let array: [Field; 32] = [0; 32]; +``` + +Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices), you can just call `as_slice` on your array: + +```rust +let array: [Field; 32] = [0; 32]; +let sl = array.as_slice() +``` + +You can define multidimensional arrays: + +```rust +let array : [[Field; 2]; 2]; +let element = array[0][0]; +``` +However, multidimensional slices are not supported. For example, the following code will error at compile time: +```rust +let slice : [[Field]] = &[]; +``` + +## 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. +Each of these functions are located within the generic impl `impl [T; N] {`. +So anywhere `self` appears, it refers to the variable `self: [T; N]`. + +### len + +Returns the length of an array + +```rust +fn len(self) -> 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(self) -> [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(self, 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(self, 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(self, 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(self, 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(self, 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(self, 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.30.0/noir/concepts/data_types/booleans.md b/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/booleans.md new file mode 100644 index 00000000000..69826fcd724 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/booleans.md @@ -0,0 +1,31 @@ +--- +title: Booleans +description: + Delve into the Boolean data type in Noir. Understand its methods, practical examples, and best practices for using Booleans in your Noir programs. +keywords: + [ + noir, + boolean type, + methods, + examples, + logical operations, + ] +sidebar_position: 2 +--- + + +The `bool` type in Noir has two possible values: `true` and `false`: + +```rust +fn main() { + let t = true; + let f: bool = false; +} +``` + +> **Note:** When returning a boolean value, it will show up as a value of 1 for `true` and 0 for +> `false` in _Verifier.toml_. + +The boolean type is most commonly used in conditionals like `if` expressions and `assert` +statements. More about conditionals is covered in the [Control Flow](../control_flow) and +[Assert Function](../assert) sections. diff --git a/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/fields.md b/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/fields.md new file mode 100644 index 00000000000..a10a4810788 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/fields.md @@ -0,0 +1,192 @@ +--- +title: Fields +description: + Dive deep into the Field data type in Noir. Understand its methods, practical examples, and best practices to effectively use Fields in your Noir programs. +keywords: + [ + noir, + field type, + methods, + examples, + best practices, + ] +sidebar_position: 0 +--- + +The field type corresponds to the native field type of the proving backend. + +The size of a Noir field depends on the elliptic curve's finite field for the proving backend +adopted. For example, a field would be a 254-bit integer when paired with the default backend that +spans the Grumpkin curve. + +Fields support integer arithmetic and are often used as the default numeric type in Noir: + +```rust +fn main(x : Field, y : Field) { + let z = x + y; +} +``` + +`x`, `y` and `z` are all private fields in this example. Using the `let` keyword we defined a new +private value `z` constrained to be equal to `x + y`. + +If proving efficiency is of priority, fields should be used as a default for solving problems. +Smaller integer types (e.g. `u64`) incur extra range constraints. + +## Methods + +After declaring a Field, you can use these common methods on it: + +### to_le_bits + +Transforms the field into an array of bits, Little Endian. + +```rust +fn to_le_bits(_x : Field, _bit_size: u32) -> [u1] +``` + +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] +``` + +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); +} +``` + +### assert_max_bit_size + +Adds a constraint to specify that the field can be represented with `bit_size` number of bits + +```rust +fn assert_max_bit_size(self, bit_size: u32) +``` + +example: + +```rust +fn main() { + let field = 2 + field.assert_max_bit_size(32); +} +``` + +### 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 +``` + + +### lt + +Returns true if the field is less than the other field + +```rust +pub fn lt(self, another: Field) -> bool +``` diff --git a/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/function_types.md b/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/function_types.md new file mode 100644 index 00000000000..f6121af17e2 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/function_types.md @@ -0,0 +1,26 @@ +--- +title: Function types +sidebar_position: 10 +--- + +Noir supports higher-order functions. The syntax for a function type is as follows: + +```rust +fn(arg1_type, arg2_type, ...) -> return_type +``` + +Example: + +```rust +fn assert_returns_100(f: fn() -> Field) { // f takes no args and returns a Field + assert(f() == 100); +} + +fn main() { + assert_returns_100(|| 100); // ok + assert_returns_100(|| 150); // fails +} +``` + +A function type also has an optional capture environment - this is necessary to support closures. +See [Lambdas](../lambdas.md) for more details. diff --git a/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/index.md b/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/index.md new file mode 100644 index 00000000000..357813c147a --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/index.md @@ -0,0 +1,110 @@ +--- +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](../generics.md): + +```rust +type Id = Size; + +fn main() { + let id: Id = 1; + let zero: u32 = 0; + assert(zero + 1 == id); +} +``` + +Type aliases can even refer to other aliases. An error will be issued if they form a cycle: + +```rust +// Ok! +type A = B; +type B = Field; + +type Bad1 = Bad2; + +// error: Dependency cycle found +type Bad2 = Bad1; +// ^^^^^^^^^^^ 'Bad2' recursively depends on itself: Bad2 -> Bad1 -> Bad2 +``` + +### BigInt + +You can achieve BigInt functionality using the [Noir BigInt](https://github.com/shuklaayush/noir-bigint) library. diff --git a/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/integers.md b/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/integers.md new file mode 100644 index 00000000000..6b2d3773912 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/integers.md @@ -0,0 +1,157 @@ +--- +title: Integers +description: Explore the Integer data type in Noir. Learn about its methods, see real-world examples, and grasp how to efficiently use Integers in your Noir code. +keywords: [noir, integer types, methods, examples, arithmetic] +sidebar_position: 1 +--- + +An integer type is a range constrained field type. +The Noir frontend supports both unsigned and signed integer types. +The allowed sizes are 1, 8, 16, 32 and 64 bits. + +:::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\\$). + +## 128 bits Unsigned Integers + +The built-in structure `U128` allows you to use 128-bit unsigned integers almost like a native integer type. However, there are some differences to keep in mind: +- You cannot cast between a native integer and `U128` +- There is a higher performance cost when using `U128`, compared to a native type. + +Conversion between unsigned integer types and U128 are done through the use of `from_integer` and `to_integer` functions. `from_integer` also accepts the `Field` type as input. + +```rust +fn main() { + let x = U128::from_integer(23); + let y = U128::from_hex("0x7"); + let z = x + y; + assert(z.to_integer() == 30); +} +``` + +`U128` is implemented with two 64 bits limbs, representing the low and high bits, which explains the performance cost. You should expect `U128` to be twice more costly for addition and four times more costly for multiplication. +You can construct a U128 from its limbs: +```rust +fn main(x: u64, y: u64) { + let x = U128::from_u64s_be(x,y); + assert(z.hi == x as Field); + assert(z.lo == y as Field); +} +``` + +Note that the limbs are stored as Field elements in order to avoid unnecessary conversions. +Apart from this, most operations will work as usual: + +```rust +fn main(x: U128, y: U128) { + // multiplication + let c = x * y; + // addition and subtraction + let c = c - x + y; + // division + let c = x / y; + // bit operation; + let c = x & y | y; + // bit shift + let c = x << y; + // comparisons; + let c = x < y; + let c = x == y; +} +``` + +## 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.30.0/noir/concepts/data_types/references.md b/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/references.md new file mode 100644 index 00000000000..a5293d11cfb --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/references.md @@ -0,0 +1,23 @@ +--- +title: References +sidebar_position: 9 +--- + +Noir supports first-class references. References are a bit like pointers: they point to a specific address that can be followed to access the data stored at that address. You can use Rust-like syntax to use pointers in Noir: the `&` operator references the variable, the `*` operator dereferences it. + +Example: + +```rust +fn main() { + let mut x = 2; + + // you can reference x as &mut and pass it to multiplyBy2 + multiplyBy2(&mut x); +} + +// you can access &mut here +fn multiplyBy2(x: &mut Field) { + // and dereference it with * + *x = *x * 2; +} +``` diff --git a/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/slices.mdx b/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/slices.mdx new file mode 100644 index 00000000000..4eccc677b80 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/slices.mdx @@ -0,0 +1,195 @@ +--- +title: Slices +description: Explore the Slice data type in Noir. Understand its methods, see real-world examples, and learn how to effectively use Slices in your Noir programs. +keywords: [noir, slice type, methods, examples, subarrays] +sidebar_position: 5 +--- + +import Experimental from '@site/src/components/Notes/_experimental.mdx'; + + + +A slice is a dynamically-sized view into a sequence of elements. They can be resized at runtime, but because they don't own the data, they cannot be returned from a circuit. You can treat slices as arrays without a constrained size. + +```rust +use dep::std::slice; + +fn main() -> pub Field { + let mut slice: [Field] = &[0; 2]; + + let mut new_slice = slice.push_back(6); + new_slice.len() +} +``` + +To write a slice literal, use a preceeding ampersand as in: `&[0; 2]` or +`&[1, 2, 3]`. + +It is important to note that slices are not references to arrays. In Noir, +`&[..]` is more similar to an immutable, growable vector. + +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); +``` + +### len + +Returns the length of a slice + +```rust +fn len(self) -> Field +``` + +Example: + +```rust +fn main() { + let slice = &[42, 42]; + assert(slice.len() == 2); +} +``` + +### as_array + +Converts this slice into an array. + +Make sure to specify the size of the resulting array. +Panics if the resulting array length is different than the slice's length. + +```rust +fn as_array(self) -> [T; N] +``` + +Example: + +```rust +fn main() { + let slice = &[5, 6]; + + // Always specify the length of the resulting array! + let array: [Field; 2] = slice.as_array(); + + assert(array[0] == slice[0]); + assert(array[1] == slice[1]); +} +``` diff --git a/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/strings.md b/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/strings.md new file mode 100644 index 00000000000..311dfd64416 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/strings.md @@ -0,0 +1,80 @@ +--- +title: Strings +description: + Discover the String data type in Noir. Learn about its methods, see real-world examples, and understand how to effectively manipulate and use Strings in Noir. +keywords: + [ + noir, + string type, + methods, + examples, + concatenation, + ] +sidebar_position: 3 +--- + + +The string type is a fixed length value defined with `str`. + +You can use strings in `assert()` functions or print them with +`println()`. See more about [Logging](../../standard_library/logging). + +```rust +use dep::std; + +fn main(message : pub str<11>, hex_as_string : str<4>) { + println(message); + assert(message == "hello world"); + assert(hex_as_string == "0x41"); +} +``` + +You can convert a `str` to a byte array by calling `as_bytes()` +or a vector by calling `as_bytes_vec()`. + +```rust +fn main() { + let message = "hello world"; + let message_bytes = message.as_bytes(); + let mut message_vec = message.as_bytes_vec(); + assert(message_bytes.len() == 11); + assert(message_bytes[0] == 104); + assert(message_bytes[0] == message_vec.get(0)); +} +``` + +## Escape characters + +You can use escape characters for your strings: + +| Escape Sequence | Description | +|-----------------|-----------------| +| `\r` | Carriage Return | +| `\n` | Newline | +| `\t` | Tab | +| `\0` | Null Character | +| `\"` | Double Quote | +| `\\` | Backslash | + +Example: + +```rust +let s = "Hello \"world" // prints "Hello "world" +let s = "hey \tyou"; // prints "hey you" +``` + +## Raw strings + +A raw string begins with the letter `r` and is optionally delimited by a number of hashes `#`. + +Escape characters are *not* processed within raw strings. All contents are interpreted literally. + +Example: + +```rust +let s = r"Hello world"; +let s = r#"Simon says "hello world""#; + +// Any number of hashes may be used (>= 1) as long as the string also terminates with the same number of hashes +let s = r#####"One "#, Two "##, Three "###, Four "####, Five will end the string."#####; +``` diff --git a/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/structs.md b/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/structs.md new file mode 100644 index 00000000000..dbf68c99813 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/structs.md @@ -0,0 +1,70 @@ +--- +title: Structs +description: + Explore the Struct data type in Noir. Learn about its methods, see real-world examples, and grasp how to effectively define and use Structs in your Noir programs. +keywords: + [ + noir, + struct type, + methods, + examples, + data structures, + ] +sidebar_position: 8 +--- + +A struct also allows for grouping multiple values of different types. Unlike tuples, we can also +name each field. + +> **Note:** The usage of _field_ here refers to each element of the struct and is unrelated to the +> field type of Noir. + +Defining a struct requires giving it a name and listing each field within as `: ` pairs: + +```rust +struct Animal { + hands: Field, + legs: Field, + eyes: u8, +} +``` + +An instance of a struct can then be created with actual values in `: ` pairs in any +order. Struct fields are accessible using their given names: + +```rust +fn main() { + let legs = 4; + + let dog = Animal { + eyes: 2, + hands: 0, + legs, + }; + + let zero = dog.hands; +} +``` + +Structs can also be destructured in a pattern, binding each field to a new variable: + +```rust +fn main() { + let Animal { hands, legs: feet, eyes } = get_octopus(); + + let ten = hands + feet + eyes as u8; +} + +fn get_octopus() -> Animal { + let octopus = Animal { + hands: 0, + legs: 8, + eyes: 2, + }; + + octopus +} +``` + +The new variables can be bound with names different from the original struct field names, as +showcased in the `legs --> feet` binding in the example above. diff --git a/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/tuples.md b/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/tuples.md new file mode 100644 index 00000000000..2ec5c9c4113 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/tuples.md @@ -0,0 +1,48 @@ +--- +title: Tuples +description: + Dive into the Tuple data type in Noir. Understand its methods, practical examples, and best practices for efficiently using Tuples in your Noir code. +keywords: + [ + noir, + tuple type, + methods, + examples, + multi-value containers, + ] +sidebar_position: 7 +--- + +A tuple collects multiple values like an array, but with the added ability to collect values of +different types: + +```rust +fn main() { + let tup: (u8, u64, Field) = (255, 500, 1000); +} +``` + +One way to access tuple elements is via destructuring using pattern matching: + +```rust +fn main() { + let tup = (1, 2); + + let (one, two) = tup; + + let three = one + two; +} +``` + +Another way to access tuple elements is via direct member access, using a period (`.`) followed by +the index of the element we want to access. Index `0` corresponds to the first tuple element, `1` to +the second and so on: + +```rust +fn main() { + let tup = (5, 6, 7, 8); + + let five = tup.0; + let eight = tup.3; +} +``` diff --git a/docs/versioned_docs/version-v0.30.0/noir/concepts/functions.md b/docs/versioned_docs/version-v0.30.0/noir/concepts/functions.md new file mode 100644 index 00000000000..f656cdfd97a --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/noir/concepts/functions.md @@ -0,0 +1,226 @@ +--- +title: Functions +description: + Learn how to declare functions and methods in Noir, a programming language with Rust semantics. + This guide covers parameter declaration, return types, call expressions, and more. +keywords: [Noir, Rust, functions, methods, parameter declaration, return types, call expressions] +sidebar_position: 1 +--- + +Functions in Noir follow the same semantics of Rust, though Noir does not support early returns. + +To declare a function the `fn` keyword is used. + +```rust +fn foo() {} +``` + +By default, functions are visible only within the package they are defined. To make them visible outside of that package (for example, as part of a [library](../modules_packages_crates/crates_and_packages.md#libraries)), you should mark them as `pub`: + +```rust +pub fn foo() {} +``` + +You can also restrict the visibility of the function to only the crate it was defined in, by specifying `pub(crate)`: + +```rust +pub(crate) fn foo() {} //foo can only be called within its crate +``` + +All parameters in a function must have a type and all types are known at compile time. The parameter +is pre-pended with a colon and the parameter type. Multiple parameters are separated using a comma. + +```rust +fn foo(x : Field, y : Field){} +``` + +The return type of a function can be stated by using the `->` arrow notation. The function below +states that the foo function must return a `Field`. If the function returns no value, then the arrow +is omitted. + +```rust +fn foo(x : Field, y : Field) -> Field { + x + y +} +``` + +Note that a `return` keyword is unneeded in this case - the last expression in a function's body is +returned. + +## Main function + +If you're writing a binary, the `main` function is the starting point of your program. You can pass all types of expressions to it, as long as they have a fixed size at compile time: + +```rust +fn main(x : Field) // this is fine: passing a Field +fn main(x : [Field; 2]) // this is also fine: passing a Field with known size at compile-time +fn main(x : (Field, bool)) // 👌: passing a (Field, bool) tuple means size 2 +fn main(x : str<5>) // this is fine, as long as you pass a string of size 5 + +fn main(x : Vec) // can't compile, has variable size +fn main(x : [Field]) // can't compile, has variable size +fn main(....// i think you got it by now +``` + +Keep in mind [tests](../../tooling/testing.md) don't differentiate between `main` and any other function. The following snippet passes tests, but won't compile or prove: + +```rust +fn main(x : [Field]) { + assert(x[0] == 1); +} + +#[test] +fn test_one() { + main(&[1, 2]); +} +``` + +```bash +$ nargo test +[testing] Running 1 test functions +[testing] Testing test_one... ok +[testing] All tests passed + +$ nargo check +The application panicked (crashed). +Message: Cannot have variable sized arrays as a parameter to main +``` + +## Call Expressions + +Calling a function in Noir is executed by using the function name and passing in the necessary +arguments. + +Below we show how to call the `foo` function from the `main` function using a call expression: + +```rust +fn main(x : Field, y : Field) { + let z = foo(x); +} + +fn foo(x : Field) -> Field { + x + x +} +``` + +## Methods + +You can define methods in Noir on any struct type in scope. + +```rust +struct MyStruct { + foo: Field, + bar: Field, +} + +impl MyStruct { + fn new(foo: Field) -> MyStruct { + MyStruct { + foo, + bar: 2, + } + } + + fn sum(self) -> Field { + self.foo + self.bar + } +} + +fn main() { + let s = MyStruct::new(40); + assert(s.sum() == 42); +} +``` + +Methods are just syntactic sugar for functions, so if we wanted to we could also call `sum` as +follows: + +```rust +assert(MyStruct::sum(s) == 42); +``` + +It is also possible to specialize which method is chosen depending on the [generic](./generics.md) type that is used. In this example, the `foo` function returns different values depending on its type: + +```rust +struct Foo {} + +impl Foo { + fn foo(self) -> Field { 1 } +} + +impl Foo { + fn foo(self) -> Field { 2 } +} + +fn main() { + let f1: Foo = Foo{}; + let f2: Foo = Foo{}; + assert(f1.foo() + f2.foo() == 3); +} +``` + +Also note that impls with the same method name defined in them cannot overlap. For example, if we already have `foo` defined for `Foo` and `Foo` like we do above, we cannot also define `foo` in an `impl Foo` since it would be ambiguous which version of `foo` to choose. + +```rust +// Including this impl in the same project as the above snippet would +// cause an overlapping impls error +impl Foo { + fn foo(self) -> Field { 3 } +} +``` + +## Lambdas + +Lambdas are anonymous functions. They follow the syntax of Rust - `|arg1, arg2, ..., argN| return_expression`. + +```rust +let add_50 = |val| val + 50; +assert(add_50(100) == 150); +``` + +See [Lambdas](./lambdas.md) for more details. + +## Attributes + +Attributes are metadata that can be applied to a function, using the following syntax: `#[attribute(value)]`. + +Supported attributes include: + +- **builtin**: the function is implemented by the compiler, for efficiency purposes. +- **deprecated**: mark the function as _deprecated_. Calling the function will generate a warning: `warning: use of deprecated function` +- **field**: Used to enable conditional compilation of code depending on the field size. See below for more details +- **oracle**: mark the function as _oracle_; meaning it is an external unconstrained function, implemented in noir_js. See [Unconstrained](./unconstrained.md) and [NoirJS](../../reference/NoirJS/noir_js/index.md) for more details. +- **test**: mark the function as unit tests. See [Tests](../../tooling/testing.md) for more details + +### Field Attribute + +The field attribute defines which field the function is compatible for. The function is conditionally compiled, under the condition that the field attribute matches the Noir native field. +The field can be defined implicitly, by using the name of the elliptic curve usually associated to it - for instance bn254, bls12_381 - or explicitly by using the field (prime) order, in decimal or hexadecimal form. +As a result, it is possible to define multiple versions of a function with each version specialized for a different field attribute. This can be useful when a function requires different parameters depending on the underlying elliptic curve. + +Example: we define the function `foo()` three times below. Once for the default Noir bn254 curve, once for the field $\mathbb F_{23}$, which will normally never be used by Noir, and once again for the bls12_381 curve. + +```rust +#[field(bn254)] +fn foo() -> u32 { + 1 +} + +#[field(23)] +fn foo() -> u32 { + 2 +} + +// This commented code would not compile as foo would be defined twice because it is the same field as bn254 +// #[field(21888242871839275222246405745257275088548364400416034343698204186575808495617)] +// fn foo() -> u32 { +// 2 +// } + +#[field(bls12_381)] +fn foo() -> u32 { + 3 +} +``` + +If the field name is not known to Noir, it will discard the function. Field names are case insensitive. diff --git a/docs/versioned_docs/version-v0.30.0/noir/concepts/generics.md b/docs/versioned_docs/version-v0.30.0/noir/concepts/generics.md new file mode 100644 index 00000000000..ddd42bf1f9b --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/noir/concepts/generics.md @@ -0,0 +1,106 @@ +--- +title: Generics +description: Learn how to use Generics in Noir +keywords: [Noir, Rust, generics, functions, structs] +sidebar_position: 7 +--- + +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 print(self) { + for _i in 0 .. self.count { + println(self.value); + } + } +} + +fn main() { + let repeated = RepeatedValue { value: "Hello!", count: 2 }; + 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 + +Since a generic type `T` can represent any type, how can we call functions on the underlying type? +In other words, how can we go from "any type `T`" to "any type `T` that has certain methods available?" + +This is what [traits](../concepts/traits) are for in Noir. Here's an example of a function generic over +any type `T` that implements the `Eq` trait for equality: + +```rust +fn first_element_is_equal(array1: [T; N], array2: [T; N]) -> bool + where T: Eq +{ + if (array1.len() == 0) | (array2.len() == 0) { + true + } else { + array1[0] == array2[0] + } +} + +fn main() { + assert(first_element_is_equal([1, 2, 3], [1, 5, 6])); + + // We can use first_element_is_equal for arrays of any type + // as long as we have an Eq impl for the types we pass in + let array = [MyStruct::new(), MyStruct::new()]; + assert(array_eq(array, array, MyStruct::eq)); +} + +impl Eq for MyStruct { + fn eq(self, other: MyStruct) -> bool { + self.foo == other.foo + } +} +``` + +You can find more details on traits and trait implementations on the [traits page](../concepts/traits). diff --git a/docs/versioned_docs/version-v0.30.0/noir/concepts/globals.md b/docs/versioned_docs/version-v0.30.0/noir/concepts/globals.md new file mode 100644 index 00000000000..063a3d89248 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/noir/concepts/globals.md @@ -0,0 +1,72 @@ +--- +title: Global Variables +description: + Learn about global variables in Noir. Discover how + to declare, modify, and use them in your programs. +keywords: [noir programming language, globals, global variables, constants] +sidebar_position: 8 +--- + +## Globals + + +Noir supports global variables. The global's type can be inferred by the compiler entirely: + +```rust +global N = 5; // Same as `global N: Field = 5` + +global TUPLE = (3, 2); + +fn main() { + assert(N == 5); + assert(N == TUPLE.0 + TUPLE.1); +} +``` + +:::info + +Globals can be defined as any expression, so long as they don't depend on themselves - otherwise there would be a dependency cycle! For example: + +```rust +global T = foo(T); // dependency error +``` + +::: + + +If they are initialized to a literal integer, globals can be used to specify an array's length: + +```rust +global N: Field = 2; + +fn main(y : [Field; N]) { + assert(y[0] == y[1]) +} +``` + +A global from another module can be imported or referenced externally like any other name: + +```rust +global N = 20; + +fn main() { + assert(my_submodule::N != N); +} + +mod my_submodule { + global N: Field = 10; +} +``` + +When a global is used, Noir replaces the name with its definition on each occurrence. +This means globals defined using function calls will repeat the call each time they're used: + +```rust +global RESULT = foo(); + +fn foo() -> [Field; 100] { ... } +``` + +This is usually fine since Noir will generally optimize any function call that does not +refer to a program input into a constant. It should be kept in mind however, if the called +function performs side-effects like `println`, as these will still occur on each use. diff --git a/docs/versioned_docs/version-v0.30.0/noir/concepts/lambdas.md b/docs/versioned_docs/version-v0.30.0/noir/concepts/lambdas.md new file mode 100644 index 00000000000..be3c7e0b5ca --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/noir/concepts/lambdas.md @@ -0,0 +1,81 @@ +--- +title: Lambdas +description: Learn how to use anonymous functions in Noir programming language. +keywords: [Noir programming language, lambda, closure, function, anonymous function] +sidebar_position: 9 +--- + +## 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.30.0/noir/concepts/mutability.md b/docs/versioned_docs/version-v0.30.0/noir/concepts/mutability.md new file mode 100644 index 00000000000..fdeef6a87c5 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/noir/concepts/mutability.md @@ -0,0 +1,121 @@ +--- +title: Mutability +description: + Learn about mutable variables in Noir. Discover how + to declare, modify, and use them in your programs. +keywords: [noir programming language, mutability in noir, mutable variables] +sidebar_position: 8 +--- + +Variables in noir can be declared mutable via the `mut` keyword. Mutable variables can be reassigned +to via an assignment expression. + +```rust +let x = 2; +x = 3; // error: x must be mutable to be assigned to + +let mut y = 3; +let y = 4; // OK +``` + +The `mut` modifier can also apply to patterns: + +```rust +let (a, mut b) = (1, 2); +a = 11; // error: a must be mutable to be assigned to +b = 12; // OK + +let mut (c, d) = (3, 4); +c = 13; // OK +d = 14; // OK + +// etc. +let MyStruct { x: mut y } = MyStruct { x: a }; +// y is now in scope +``` + +Note that mutability in noir is local and everything is passed by value, so if a called function +mutates its parameters then the parent function will keep the old value of the parameters. + +```rust +fn main() -> pub Field { + let x = 3; + helper(x); + x // x is still 3 +} + +fn helper(mut x: i32) { + x = 4; +} +``` + +## Non-local mutability + +Non-local mutability can be achieved through the mutable reference type `&mut T`: + +```rust +fn set_to_zero(x: &mut Field) { + *x = 0; +} + +fn main() { + let mut y = 42; + set_to_zero(&mut y); + assert(*y == 0); +} +``` + +When creating a mutable reference, the original variable being referred to (`y` in this +example) must also be mutable. Since mutable references are a reference type, they must +be explicitly dereferenced via `*` to retrieve the underlying value. Note that this yields +a copy of the value, so mutating this copy will not change the original value behind the +reference: + +```rust +fn main() { + let mut x = 1; + let x_ref = &mut x; + + let mut y = *x_ref; + let y_ref = &mut y; + + x = 2; + *x_ref = 3; + + y = 4; + *y_ref = 5; + + assert(x == 3); + assert(*x_ref == 3); + assert(y == 5); + assert(*y_ref == 5); +} +``` + +Note that types in Noir are actually deeply immutable so the copy that occurs when +dereferencing is only a conceptual copy - no additional constraints will occur. + +Mutable references can also be stored within structs. Note that there is also +no lifetime parameter on these unlike rust. This is because the allocated memory +always lasts the entire program - as if it were an array of one element. + +```rust +struct Foo { + x: &mut Field +} + +impl Foo { + fn incr(mut self) { + *self.x += 1; + } +} + +fn main() { + let foo = Foo { x: &mut 0 }; + foo.incr(); + assert(*foo.x == 1); +} +``` + +In general, you should avoid non-local & shared mutability unless it is needed. Sticking +to only local mutability will improve readability and potentially improve compiler optimizations as well. diff --git a/docs/versioned_docs/version-v0.30.0/noir/concepts/ops.md b/docs/versioned_docs/version-v0.30.0/noir/concepts/ops.md new file mode 100644 index 00000000000..c35c36c38a9 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/noir/concepts/ops.md @@ -0,0 +1,98 @@ +--- +title: Logical Operations +description: + Learn about the supported arithmetic and logical operations in the Noir programming language. + Discover how to perform operations on private input types, integers, and booleans. +keywords: + [ + Noir programming language, + supported operations, + arithmetic operations, + logical operations, + predicate operators, + bitwise operations, + short-circuiting, + backend, + ] +sidebar_position: 3 +--- + +# Operations + +## Table of Supported Operations + +| Operation | Description | Requirements | +| :-------- | :------------------------------------------------------------: | -------------------------------------: | +| + | Adds two private input types together | Types must be private input | +| - | Subtracts two private input types together | Types must be private input | +| \* | Multiplies two private input types together | Types must be private input | +| / | Divides two private input types together | Types must be private input | +| ^ | XOR two private input types together | Types must be integer | +| & | AND two private input types together | Types must be integer | +| \| | OR two private input types together | Types must be integer | +| \<\< | Left shift an integer by another integer amount | Types must be integer, shift must be u8 | +| >> | Right shift an integer by another integer amount | Types must be integer, shift must be u8 | +| ! | 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 identically 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.30.0/noir/concepts/oracles.md b/docs/versioned_docs/version-v0.30.0/noir/concepts/oracles.md new file mode 100644 index 00000000000..aa380b5f7b8 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/noir/concepts/oracles.md @@ -0,0 +1,31 @@ +--- +title: Oracles +description: Dive into how Noir supports Oracles via RPC calls, and learn how to declare an Oracle in Noir with our comprehensive guide. +keywords: + - Noir + - Oracles + - RPC Calls + - Unconstrained Functions + - Programming + - Blockchain +sidebar_position: 6 +--- + +:::note + +This is an experimental feature that is not fully documented. If you notice any outdated information or potential improvements to this page, pull request contributions are very welcome: https://github.com/noir-lang/noir + +::: + +Noir has support for Oracles via RPC calls. This means Noir will make an RPC call and use the return value for proof generation. + +Since Oracles are not resolved by Noir, they are [`unconstrained` functions](./unconstrained.md) + +You can declare an Oracle through the `#[oracle()]` flag. Example: + +```rust +#[oracle(get_number_sequence)] +unconstrained fn get_number_sequence(_size: Field) -> [Field] {} +``` + +The timeout for when using an external RPC oracle resolver can be set with the `NARGO_FOREIGN_CALL_TIMEOUT` environment variable. This timeout is in units of milliseconds. diff --git a/docs/versioned_docs/version-v0.30.0/noir/concepts/shadowing.md b/docs/versioned_docs/version-v0.30.0/noir/concepts/shadowing.md new file mode 100644 index 00000000000..5ce6130d201 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/noir/concepts/shadowing.md @@ -0,0 +1,44 @@ +--- +title: Shadowing +sidebar_position: 12 +--- + +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.30.0/noir/concepts/traits.md b/docs/versioned_docs/version-v0.30.0/noir/concepts/traits.md new file mode 100644 index 00000000000..ef1445a5907 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/noir/concepts/traits.md @@ -0,0 +1,389 @@ +--- +title: Traits +description: + Traits in Noir can be used to abstract out a common interface for functions across + several data types. +keywords: [noir programming language, traits, interfaces, generic, protocol] +sidebar_position: 14 +--- + +## Overview + +Traits in Noir are a useful abstraction similar to interfaces or protocols in other languages. Each trait defines +the interface of several methods contained within the trait. Types can then implement this trait by providing +implementations for these methods. For example in the program: + +```rust +struct Rectangle { + width: Field, + height: Field, +} + +impl Rectangle { + fn area(self) -> Field { + self.width * self.height + } +} + +fn log_area(r: Rectangle) { + println(r.area()); +} +``` + +We have a function `log_area` to log the area of a `Rectangle`. Now how should we change the program if we want this +function to work on `Triangle`s as well?: + +```rust +struct Triangle { + width: Field, + height: Field, +} + +impl Triangle { + fn area(self) -> Field { + self.width * self.height / 2 + } +} +``` + +Making `log_area` generic over all types `T` would be invalid since not all types have an `area` method. Instead, we can +introduce a new `Area` trait and make `log_area` generic over all types `T` that implement `Area`: + +```rust +trait Area { + fn area(self) -> Field; +} + +fn log_area(shape: T) where T: Area { + println(shape.area()); +} +``` + +We also need to explicitly implement `Area` for `Rectangle` and `Triangle`. We can do that by changing their existing +impls slightly. Note that the parameter types and return type of each of our `area` methods must match those defined +by the `Area` trait. + +```rust +impl Area for Rectangle { + fn area(self) -> Field { + self.width * self.height + } +} + +impl Area for Triangle { + fn area(self) -> Field { + self.width * self.height / 2 + } +} +``` + +Now we have a working program that is generic over any type of Shape that is used! Others can even use this program +as a library with their own types - such as `Circle` - as long as they also implement `Area` for these types. + +## Where Clauses + +As seen in `log_area` above, when we want to create a function or method that is generic over any type that implements +a trait, we can add a where clause to the generic function. + +```rust +fn log_area(shape: T) where T: Area { + println(shape.area()); +} +``` + +It is also possible to apply multiple trait constraints on the same variable at once by combining traits with the `+` +operator. Similarly, we can have multiple trait constraints by separating each with a comma: + +```rust +fn foo(elements: [T], thing: U) where + T: Default + Add + Eq, + U: Bar, +{ + let mut sum = T::default(); + + for element in elements { + sum += element; + } + + if sum == T::default() { + thing.bar(); + } +} +``` + +## Generic Implementations + +You can add generics to a trait implementation by adding the generic list after the `impl` keyword: + +```rust +trait Second { + fn second(self) -> Field; +} + +impl Second for (T, Field) { + fn second(self) -> Field { + self.1 + } +} +``` + +You can also implement a trait for every type this way: + +```rust +trait Debug { + fn debug(self); +} + +impl Debug for T { + fn debug(self) { + println(self); + } +} + +fn main() { + 1.debug(); +} +``` + +### Generic Trait Implementations With Where Clauses + +Where clauses can also be placed on trait implementations themselves to restrict generics in a similar way. +For example, while `impl Foo for T` implements the trait `Foo` for every type, `impl Foo for T where T: Bar` +will implement `Foo` only for types that also implement `Bar`. This is often used for implementing generic types. +For example, here is the implementation for array equality: + +```rust +impl Eq for [T; N] where T: Eq { + // Test if two arrays have the same elements. + // Because both arrays must have length N, we know their lengths already match. + fn eq(self, other: Self) -> bool { + let mut result = true; + + for i in 0 .. self.len() { + // The T: Eq constraint is needed to call == on the array elements here + result &= self[i] == other[i]; + } + + result + } +} +``` + +## Generic Traits + +Traits themselves can also be generic by placing the generic arguments after the trait name. These generics are in +scope of every item within the trait. + +```rust +trait Into { + // Convert `self` to type `T` + fn into(self) -> T; +} +``` + +When implementing generic traits the generic arguments of the trait must be specified. This is also true anytime +when referencing a generic trait (e.g. in a `where` clause). + +```rust +struct MyStruct { + array: [Field; 2], +} + +impl Into<[Field; 2]> for MyStruct { + fn into(self) -> [Field; 2] { + self.array + } +} + +fn as_array(x: T) -> [Field; 2] + where T: Into<[Field; 2]> +{ + x.into() +} + +fn main() { + let array = [1, 2]; + let my_struct = MyStruct { array }; + + assert_eq(as_array(my_struct), array); +} +``` + +## Trait Methods With No `self` + +A trait can contain any number of methods, each of which have access to the `Self` type which represents each type +that eventually implements the trait. Similarly, the `self` variable is available as well but is not required to be used. +For example, we can define a trait to create a default value for a type. This trait will need to return the `Self` type +but doesn't need to take any parameters: + +```rust +trait Default { + fn default() -> Self; +} +``` + +Implementing this trait can be done similarly to any other trait: + +```rust +impl Default for Field { + fn default() -> Field { + 0 + } +} + +struct MyType {} + +impl Default for MyType { + fn default() -> Field { + MyType {} + } +} +``` + +However, since there is no `self` parameter, we cannot call it via the method call syntax `object.method()`. +Instead, we'll need to refer to the function directly. This can be done either by referring to the +specific impl `MyType::default()` or referring to the trait itself `Default::default()`. In the later +case, type inference determines the impl that is selected. + +```rust +let my_struct = MyStruct::default(); + +let x: Field = Default::default(); +let result = x + Default::default(); +``` + +:::warning + +```rust +let _ = Default::default(); +``` + +If type inference cannot select which impl to use because of an ambiguous `Self` type, an impl will be +arbitrarily selected. This occurs most often when the result of a trait function call with no parameters +is unused. To avoid this, when calling a trait function with no `self` or `Self` parameters or return type, +always refer to it via the implementation type's namespace - e.g. `MyType::default()`. +This is set to change to an error in future Noir versions. + +::: + +## Default Method Implementations + +A trait can also have default implementations of its methods by giving a body to the desired functions. +Note that this body must be valid for all types that may implement the trait. As a result, the only +valid operations on `self` will be operations valid for any type or other operations on the trait itself. + +```rust +trait Numeric { + fn add(self, other: Self) -> Self; + + // Default implementation of double is (self + self) + fn double(self) -> Self { + self.add(self) + } +} +``` + +When implementing a trait with default functions, a type may choose to implement only the required functions: + +```rust +impl Numeric for Field { + fn add(self, other: Field) -> Field { + self + other + } +} +``` + +Or it may implement the optional methods as well: + +```rust +impl Numeric for u32 { + fn add(self, other: u32) -> u32 { + self + other + } + + fn double(self) -> u32 { + self * 2 + } +} +``` + +## Impl Specialization + +When implementing traits for a generic type it is possible to implement the trait for only a certain combination +of generics. This can be either as an optimization or because those specific generics are required to implement the trait. + +```rust +trait Sub { + fn sub(self, other: Self) -> Self; +} + +struct NonZero { + value: T, +} + +impl Sub for NonZero { + fn sub(self, other: Self) -> Self { + let value = self.value - other.value; + assert(value != 0); + NonZero { value } + } +} +``` + +## Overlapping Implementations + +Overlapping implementations are disallowed by Noir to ensure Noir's decision on which impl to select is never ambiguous. +This means if a trait `Foo` is already implemented +by a type `Bar` for all `T`, then we cannot also have a separate impl for `Bar` (or any other +type argument). Similarly, if there is an impl for all `T` such as `impl Debug for T`, we cannot create +any more impls to `Debug` for other types since it would be ambiguous which impl to choose for any given +method call. + +```rust +trait Trait {} + +// Previous impl defined here +impl Trait for (A, B) {} + +// error: Impl for type `(Field, Field)` overlaps with existing impl +impl Trait for (Field, Field) {} +``` + +## Trait Coherence + +Another restriction on trait implementations is coherence. This restriction ensures other crates cannot create +impls that may overlap with other impls, even if several unrelated crates are used as dependencies in the same +program. + +The coherence restriction is: to implement a trait, either the trait itself or the object type must be declared +in the crate the impl is in. + +In practice this often comes up when using types provided by libraries. If a library provides a type `Foo` that does +not implement a trait in the standard library such as `Default`, you may not `impl Default for Foo` in your own crate. +While restrictive, this prevents later issues or silent changes in the program if the `Foo` library later added its +own impl for `Default`. If you are a user of the `Foo` library in this scenario and need a trait not implemented by the +library your choices are to either submit a patch to the library or use the newtype pattern. + +### The Newtype Pattern + +The newtype pattern gets around the coherence restriction by creating a new wrapper type around the library type +that we cannot create `impl`s for. Since the new wrapper type is defined in our current crate, we can create +impls for any trait we need on it. + +```rust +struct Wrapper { + foo: dep::some_library::Foo, +} + +impl Default for Wrapper { + fn default() -> Wrapper { + Wrapper { + foo: dep::some_library::Foo::new(), + } + } +} +``` + +Since we have an impl for our own type, the behavior of this code will not change even if `some_library` is updated +to provide its own `impl Default for Foo`. The downside of this pattern is that it requires extra wrapping and +unwrapping of values when converting to and from the `Wrapper` and `Foo` types. diff --git a/docs/versioned_docs/version-v0.30.0/noir/concepts/unconstrained.md b/docs/versioned_docs/version-v0.30.0/noir/concepts/unconstrained.md new file mode 100644 index 00000000000..b8e71fe65f0 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/noir/concepts/unconstrained.md @@ -0,0 +1,99 @@ +--- +title: Unconstrained Functions +description: "Learn about what unconstrained functions in Noir are, how to use them and when you'd want to." + +keywords: [Noir programming language, unconstrained, open] +sidebar_position: 5 +--- + +Unconstrained functions are functions which do not constrain any of the included computation and allow for non-deterministic 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 AND 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. + +## Break and Continue + +In addition to loops over runtime bounds, `break` and `continue` are also available in unconstrained code. See [break and continue](../concepts/control_flow/#break-and-continue) diff --git a/docs/versioned_docs/version-v0.30.0/noir/modules_packages_crates/_category_.json b/docs/versioned_docs/version-v0.30.0/noir/modules_packages_crates/_category_.json new file mode 100644 index 00000000000..1debcfe7675 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/noir/modules_packages_crates/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Modules, Packages and Crates", + "position": 2, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.30.0/noir/modules_packages_crates/crates_and_packages.md b/docs/versioned_docs/version-v0.30.0/noir/modules_packages_crates/crates_and_packages.md new file mode 100644 index 00000000000..95ee9f52ab2 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/noir/modules_packages_crates/crates_and_packages.md @@ -0,0 +1,43 @@ +--- +title: Crates and Packages +description: Learn how to use Crates and Packages in your Noir project +keywords: [Nargo, dependencies, package management, crates, package] +sidebar_position: 0 +--- + +## Crates + +A crate is the smallest amount of code that the Noir compiler considers at a time. +Crates can contain modules, and the modules may be defined in other files that get compiled with the crate, as we’ll see in the coming sections. + +### Crate Types + +A Noir crate can come in several forms: binaries, libraries or contracts. + +#### Binaries + +_Binary crates_ are programs which you can compile to an ACIR circuit which you can then create proofs against. Each must have a function called `main` that defines the ACIR circuit which is to be proved. + +#### Libraries + +_Library crates_ don't have a `main` function and they don't compile down to ACIR. Instead they define functionality intended to be shared with multiple projects, and eventually included in a binary crate. + +#### Contracts + +Contract crates are similar to binary crates in that they compile to ACIR which you can create proofs against. They are different in that they do not have a single `main` function, but are a collection of functions to be deployed to the [Aztec network](https://aztec.network). You can learn more about the technical details of Aztec in the [monorepo](https://github.com/AztecProtocol/aztec-packages) or contract [examples](https://github.com/AztecProtocol/aztec-packages/tree/master/noir-projects/noir-contracts/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.30.0/noir/modules_packages_crates/dependencies.md b/docs/versioned_docs/version-v0.30.0/noir/modules_packages_crates/dependencies.md new file mode 100644 index 00000000000..04c1703d929 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/noir/modules_packages_crates/dependencies.md @@ -0,0 +1,124 @@ +--- +title: Dependencies +description: + Learn how to specify and manage dependencies in Nargo, allowing you to upload packages to GitHub + and use them easily in your project. +keywords: [Nargo, dependencies, GitHub, package management, versioning] +sidebar_position: 1 +--- + +Nargo allows you to upload packages to GitHub and use them as dependencies. + +## Specifying a dependency + +Specifying a dependency requires a tag to a specific commit and the git url to the url containing +the package. + +Currently, there are no requirements on the tag contents. If requirements are added, it would follow +semver 2.0 guidelines. + +> Note: Without a `tag` , there would be no versioning and dependencies would change each time you +> compile your project. + +For example, to add the [ecrecover-noir library](https://github.com/colinnielsen/ecrecover-noir) to your project, add it to `Nargo.toml`: + +```toml +# Nargo.toml + +[dependencies] +ecrecover = {tag = "v0.8.0", git = "https://github.com/colinnielsen/ecrecover-noir"} +``` + +If the module is in a subdirectory, you can define a subdirectory in your git repository, for example: + +```toml +# Nargo.toml + +[dependencies] +easy_private_token_contract = {tag ="v0.1.0-alpha62", git = "https://github.com/AztecProtocol/aztec-packages", directory = "noir-contracts/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 +└── lib_a + ├── Nargo.toml + └── src + └── lib.nr +``` + +Inside of the binary crate, you can specify: + +```toml +# Nargo.toml + +[dependencies] +lib_a = { path = "../lib_a" } +``` + +## 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 lib_a referenced above: + +```rust +use dep::ecrecover; +use dep::lib_a; +``` + +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.30.0/noir/modules_packages_crates/modules.md b/docs/versioned_docs/version-v0.30.0/noir/modules_packages_crates/modules.md new file mode 100644 index 00000000000..ae822a1cff4 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/noir/modules_packages_crates/modules.md @@ -0,0 +1,105 @@ +--- +title: Modules +description: + Learn how to organize your files using modules in Noir, following the same convention as Rust's + module system. Examples included. +keywords: [Noir, Rust, modules, organizing files, sub-modules] +sidebar_position: 2 +--- + +Noir's module system follows the same convention as the _newer_ version of Rust's module system. + +## Purpose of Modules + +Modules are used to organize 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.30.0/noir/modules_packages_crates/workspaces.md b/docs/versioned_docs/version-v0.30.0/noir/modules_packages_crates/workspaces.md new file mode 100644 index 00000000000..513497f12bf --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/noir/modules_packages_crates/workspaces.md @@ -0,0 +1,42 @@ +--- +title: Workspaces +sidebar_position: 3 +--- + +Workspaces are a feature of nargo that allow you to manage multiple related Noir packages in a single repository. A workspace is essentially a group of related projects that share common build output directories and configurations. + +Each Noir project (with it's own Nargo.toml file) can be thought of as a package. Each package is expected to contain exactly one "named circuit", being the "name" defined in Nargo.toml with the program logic defined in `./src/main.nr`. + +For a project with the following structure: + +```tree +├── crates +│ ├── a +│ │ ├── Nargo.toml +│ │ └── Prover.toml +│ │ └── src +│ │ └── main.nr +│ └── b +│ ├── Nargo.toml +│ └── Prover.toml +│ └── src +│ └── main.nr +│ +└── Nargo.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.30.0/noir/standard_library/_category_.json b/docs/versioned_docs/version-v0.30.0/noir/standard_library/_category_.json new file mode 100644 index 00000000000..af04c0933fd --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/noir/standard_library/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Standard Library", + "position": 1, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.30.0/noir/standard_library/bigint.md b/docs/versioned_docs/version-v0.30.0/noir/standard_library/bigint.md new file mode 100644 index 00000000000..2bfdeec6631 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/noir/standard_library/bigint.md @@ -0,0 +1,122 @@ +--- +title: Big Integers +description: How to use big integers from Noir standard library +keywords: + [ + Big Integer, + Noir programming language, + Noir libraries, + ] +--- + +The BigInt module in the standard library exposes some class of integers which do not fit (well) into a Noir native field. It implements modulo arithmetic, modulo a 'big' prime number. + +:::note + +The module can currently be considered as `Field`s with fixed modulo sizes used by a set of elliptic curves, in addition to just the native curve. [More work](https://github.com/noir-lang/noir/issues/510) is needed to achieve arbitrarily sized big integers. + +::: + +Currently 6 classes of integers (i.e 'big' prime numbers) are available in the module, namely: + +- BN254 Fq: Bn254Fq +- BN254 Fr: Bn254Fr +- Secp256k1 Fq: Secpk1Fq +- Secp256k1 Fr: Secpk1Fr +- Secp256r1 Fr: Secpr1Fr +- Secp256r1 Fq: Secpr1Fq + +Where XXX Fq and XXX Fr denote respectively the order of the base and scalar field of the (usual) elliptic curve XXX. +For instance the big integer 'Secpk1Fq' in the standard library refers to integers modulo $2^{256}-2^{32}-977$. + +Feel free to explore the source code for the other primes: + +```rust title="big_int_definition" showLineNumbers +struct BigInt { + pointer: u32, + modulus: u32, +} +``` +> Source code: noir_stdlib/src/bigint.nr#L14-L19 + + +## Example usage + +A common use-case is when constructing a big integer from its bytes representation, and performing arithmetic operations on it: + +```rust title="big_int_example" showLineNumbers +fn big_int_example(x: u8, y: u8) { + let a = Secpk1Fq::from_le_bytes(&[x, y, 0, 45, 2]); + let b = Secpk1Fq::from_le_bytes(&[y, x, 9]); + let c = (a + b) * b / a; + let d = c.to_le_bytes(); + println(d[0]); +} +``` +> Source code: test_programs/execution_success/bigint/src/main.nr#L70-L78 + + +## Methods + +The available operations for each big integer are: + +### from_le_bytes + +Construct a big integer from its little-endian bytes representation. Example: + +```rust + // Construct a big integer from a slice of bytes + let a = Secpk1Fq::from_le_bytes(&[x, y, 0, 45, 2]); + // Construct a big integer from an array of 32 bytes + let a = Secpk1Fq::from_le_bytes_32([1;32]); + ``` + +Sure, here's the formatted version of the remaining methods: + +### to_le_bytes + +Return the little-endian bytes representation of a big integer. Example: + +```rust +let bytes = a.to_le_bytes(); +``` + +### add + +Add two big integers. Example: + +```rust +let sum = a + b; +``` + +### sub + +Subtract two big integers. Example: + +```rust +let difference = a - b; +``` + +### mul + +Multiply two big integers. Example: + +```rust +let product = a * b; +``` + +### div + +Divide two big integers. Note that division is field division and not euclidean division. Example: + +```rust +let quotient = a / b; +``` + +### eq + +Compare two big integers. Example: + +```rust +let are_equal = a == b; +``` diff --git a/docs/versioned_docs/version-v0.30.0/noir/standard_library/black_box_fns.md b/docs/versioned_docs/version-v0.30.0/noir/standard_library/black_box_fns.md new file mode 100644 index 00000000000..eeead580969 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/noir/standard_library/black_box_fns.md @@ -0,0 +1,32 @@ +--- +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. + +The ACVM spec defines a set of blackbox functions which backends will be expected to implement. This allows backends to use optimized implementations of these constraints if they have them, however they may also fallback to less efficient naive implementations if not. + +## Function list + +Here is a list of the current black box functions: + +- [AES128](./cryptographic_primitives/ciphers.mdx#aes128) +- [SHA256](./cryptographic_primitives/hashes.mdx#sha256) +- [Schnorr signature verification](./cryptographic_primitives/schnorr.mdx) +- [Blake2s](./cryptographic_primitives/hashes.mdx#blake2s) +- [Blake3](./cryptographic_primitives/hashes.mdx#blake3) +- [Pedersen Hash](./cryptographic_primitives/hashes.mdx#pedersen_hash) +- [Pedersen Commitment](./cryptographic_primitives/hashes.mdx#pedersen_commitment) +- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification.mdx) +- [Embedded curve operations (MSM, addition, ...)](./cryptographic_primitives/embedded_curve_ops.mdx) +- AND +- XOR +- RANGE +- [Keccak256](./cryptographic_primitives/hashes.mdx#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. + +You can view the black box functions defined in the ACVM code [here](https://github.com/noir-lang/noir/blob/master/acvm-repo/acir/src/circuit/black_box_functions.rs). diff --git a/docs/versioned_docs/version-v0.30.0/noir/standard_library/bn254.md b/docs/versioned_docs/version-v0.30.0/noir/standard_library/bn254.md new file mode 100644 index 00000000000..3294f005dbb --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/noir/standard_library/bn254.md @@ -0,0 +1,46 @@ +--- +title: Bn254 Field Library +--- + +Noir provides a module in standard library with some optimized functions for bn254 Fr in `std::field::bn254`. + +## decompose + +```rust +fn decompose(x: Field) -> (Field, Field) {} +``` + +Decomposes a single field into two fields, low and high. The low field contains the lower 16 bytes of the input field and the high field contains the upper 16 bytes of the input field. Both field results are range checked to 128 bits. + + +## assert_gt + +```rust +fn assert_gt(a: Field, b: Field) {} +``` + +Asserts that a > b. This will generate less constraints than using `assert(gt(a, b))`. + +## assert_lt + +```rust +fn assert_lt(a: Field, b: Field) {} +``` + +Asserts that a < b. This will generate less constraints than using `assert(lt(a, b))`. + +## gt + +```rust +fn gt(a: Field, b: Field) -> bool {} +``` + +Returns true if a > b. + +## lt + +```rust +fn lt(a: Field, b: Field) -> bool {} +``` + +Returns true if a < b. \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.30.0/noir/standard_library/containers/boundedvec.md b/docs/versioned_docs/version-v0.30.0/noir/standard_library/containers/boundedvec.md new file mode 100644 index 00000000000..c22fe8c5045 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/noir/standard_library/containers/boundedvec.md @@ -0,0 +1,340 @@ +--- +title: Bounded Vectors +keywords: [noir, vector, bounded vector, slice] +sidebar_position: 1 +--- + +A `BoundedVec` is a growable storage similar to a `Vec` except that it +is bounded with a maximum possible length. Unlike `Vec`, `BoundedVec` is not implemented +via slices and thus is not subject to the same restrictions slices are (notably, nested +slices - and thus nested vectors as well - are disallowed). + +Since a BoundedVec is backed by a normal array under the hood, growing the BoundedVec by +pushing an additional element is also more efficient - the length only needs to be increased +by one. + +For these reasons `BoundedVec` should generally be preferred over `Vec` when there +is a reasonable maximum bound that can be placed on the vector. + +Example: + +```rust +let mut vector: BoundedVec = BoundedVec::new(); +for i in 0..5 { + vector.push(i); +} +assert(vector.len() == 5); +assert(vector.max_len() == 10); +``` + +## Methods + +### new + +```rust +pub fn new() -> Self +``` + +Creates a new, empty vector of length zero. + +Since this container is backed by an array internally, it still needs an initial value +to give each element. To resolve this, each element is zeroed internally. This value +is guaranteed to be inaccessible unless `get_unchecked` is used. + +Example: + +```rust +let empty_vector: BoundedVec = BoundedVec::new(); +assert(empty_vector.len() == 0); +``` + +Note that whenever calling `new` the maximum length of the vector should always be specified +via a type signature: + +```rust title="new_example" showLineNumbers +fn foo() -> BoundedVec { + // Ok! MaxLen is specified with a type annotation + let v1: BoundedVec = BoundedVec::new(); + let v2 = BoundedVec::new(); + + // Ok! MaxLen is known from the type of foo's return value + v2 +} + +fn bad() { + let mut v3 = BoundedVec::new(); + + // Not Ok! We don't know if v3's MaxLen is at least 1, and the compiler often infers 0 by default. + v3.push(5); +} +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L11-L27 + + +This defaulting of `MaxLen` (and numeric generics in general) to zero may change in future noir versions +but for now make sure to use type annotations when using bounded vectors. Otherwise, you will receive a constraint failure at runtime when the vec is pushed to. + +### get + +```rust +pub fn get(mut self: Self, index: u64) -> T { +``` + +Retrieves an element from the vector at the given index, starting from zero. + +If the given index is equal to or greater than the length of the vector, this +will issue a constraint failure. + +Example: + +```rust +fn foo(v: BoundedVec) { + let first = v.get(0); + let last = v.get(v.len() - 1); + assert(first != last); +} +``` + +### get_unchecked + +```rust +pub fn get_unchecked(mut self: Self, index: u64) -> T { +``` + +Retrieves an element from the vector at the given index, starting from zero, without +performing a bounds check. + +Since this function does not perform a bounds check on length before accessing the element, +it is unsafe! Use at your own risk! + +Example: + +```rust title="get_unchecked_example" showLineNumbers +fn sum_of_first_three(v: BoundedVec) -> u32 { + // Always ensure the length is larger than the largest + // index passed to get_unchecked + assert(v.len() > 2); + let first = v.get_unchecked(0); + let second = v.get_unchecked(1); + let third = v.get_unchecked(2); + first + second + third +} +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L54-L64 + + + +### push + +```rust +pub fn push(&mut self, elem: T) { +``` + +Pushes an element to the end of the vector. This increases the length +of the vector by one. + +Panics if the new length of the vector will be greater than the max length. + +Example: + +```rust title="bounded-vec-push-example" showLineNumbers +let mut v: BoundedVec = BoundedVec::new(); + + v.push(1); + v.push(2); + + // Panics with failed assertion "push out of bounds" + v.push(3); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L68-L76 + + +### pop + +```rust +pub fn pop(&mut self) -> T +``` + +Pops the element at the end of the vector. This will decrease the length +of the vector by one. + +Panics if the vector is empty. + +Example: + +```rust title="bounded-vec-pop-example" showLineNumbers +let mut v: BoundedVec = BoundedVec::new(); + v.push(1); + v.push(2); + + let two = v.pop(); + let one = v.pop(); + + assert(two == 2); + assert(one == 1); + // error: cannot pop from an empty vector + // let _ = v.pop(); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L81-L93 + + +### len + +```rust +pub fn len(self) -> u64 { +``` + +Returns the current length of this vector + +Example: + +```rust title="bounded-vec-len-example" showLineNumbers +let mut v: BoundedVec = BoundedVec::new(); + assert(v.len() == 0); + + v.push(100); + assert(v.len() == 1); + + v.push(200); + v.push(300); + v.push(400); + assert(v.len() == 4); + + let _ = v.pop(); + let _ = v.pop(); + assert(v.len() == 2); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L98-L113 + + +### max_len + +```rust +pub fn max_len(_self: BoundedVec) -> u64 { +``` + +Returns the maximum length of this vector. This is always +equal to the `MaxLen` parameter this vector was initialized with. + +Example: + +```rust title="bounded-vec-max-len-example" showLineNumbers +let mut v: BoundedVec = BoundedVec::new(); + + assert(v.max_len() == 5); + v.push(10); + assert(v.max_len() == 5); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L118-L124 + + +### storage + +```rust +pub fn storage(self) -> [T; MaxLen] { +``` + +Returns the internal array within this vector. +Since arrays in Noir are immutable, mutating the returned storage array will not mutate +the storage held internally by this vector. + +Note that uninitialized elements may be zeroed out! + +Example: + +```rust title="bounded-vec-storage-example" showLineNumbers +let mut v: BoundedVec = BoundedVec::new(); + + assert(v.storage() == [0, 0, 0, 0, 0]); + + v.push(57); + assert(v.storage() == [57, 0, 0, 0, 0]); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L129-L136 + + +### extend_from_array + +```rust +pub fn extend_from_array(&mut self, array: [T; Len]) +``` + +Pushes each element from the given array to this vector. + +Panics if pushing each element would cause the length of this vector +to exceed the maximum length. + +Example: + +```rust title="bounded-vec-extend-from-array-example" showLineNumbers +let mut vec: BoundedVec = BoundedVec::new(); + vec.extend_from_array([2, 4]); + + assert(vec.len == 2); + assert(vec.get(0) == 2); + assert(vec.get(1) == 4); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L141-L148 + + +### extend_from_bounded_vec + +```rust +pub fn extend_from_bounded_vec(&mut self, vec: BoundedVec) +``` + +Pushes each element from the other vector to this vector. The length of +the other vector is left unchanged. + +Panics if pushing each element would cause the length of this vector +to exceed the maximum length. + +Example: + +```rust title="bounded-vec-extend-from-bounded-vec-example" showLineNumbers +let mut v1: BoundedVec = BoundedVec::new(); + let mut v2: BoundedVec = BoundedVec::new(); + + v2.extend_from_array([1, 2, 3]); + v1.extend_from_bounded_vec(v2); + + assert(v1.storage() == [1, 2, 3, 0, 0]); + assert(v2.storage() == [1, 2, 3, 0, 0, 0, 0]); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L153-L162 + + +### from_array + +```rust +pub fn from_array(array: [T; Len]) -> Self +``` + +Creates a new vector, populating it with values derived from an array input. +The maximum length of the vector is determined based on the type signature. + +Example: +```rust +let bounded_vec: BoundedVec = BoundedVec::from_array([1, 2, 3]) +``` + +### any + +```rust +pub fn any(self, predicate: fn[Env](T) -> bool) -> bool +``` + +Returns true if the given predicate returns true for any element +in this vector. + +Example: + +```rust title="bounded-vec-any-example" showLineNumbers +let mut v: BoundedVec = BoundedVec::new(); + v.extend_from_array([2, 4, 6]); + + let all_even = !v.any(|elem: u32| elem % 2 != 0); + assert(all_even); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L229-L235 + diff --git a/docs/versioned_docs/version-v0.30.0/noir/standard_library/containers/hashmap.md b/docs/versioned_docs/version-v0.30.0/noir/standard_library/containers/hashmap.md new file mode 100644 index 00000000000..47faa99aba6 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/noir/standard_library/containers/hashmap.md @@ -0,0 +1,570 @@ +--- +title: HashMap +keywords: [noir, map, hash, hashmap] +sidebar_position: 1 +--- + +`HashMap` is used to efficiently store and look up key-value pairs. + +`HashMap` is a bounded type which can store anywhere from zero to `MaxLen` total elements. +Note that due to hash collisions, the actual maximum number of elements stored by any particular +hashmap is likely lower than `MaxLen`. This is true even with cryptographic hash functions since +every hash value will be performed modulo `MaxLen`. + +When creating `HashMap`s, the `MaxLen` generic should always be specified if it is not already +known. Otherwise, the compiler may infer a different value for `MaxLen` (such as zero), which +will likely change the result of the program. This behavior is set to become an error in future +versions instead. + +Example: + +```rust +// Create a mapping from Fields to u32s with a maximum length of 12 +// using a poseidon2 hasher +use dep::std::hash::poseidon2::Poseidon2Hasher; +let mut map: HashMap> = HashMap::default(); + +map.insert(1, 2); +map.insert(3, 4); + +let two = map.get(1).unwrap(); +``` + +## Methods + +### default + +```rust title="default" showLineNumbers +impl Default for HashMap +where + B: BuildHasher + Default, + H: Hasher + Default +{ + fn default() -> Self { +``` +> Source code: noir_stdlib/src/collections/map.nr#L462-L469 + + +Creates a fresh, empty HashMap. + +When using this function, always make sure to specify the maximum size of the hash map. + +This is the same `default` from the `Default` implementation given further below. It is +repeated here for convenience since it is the recommended way to create a hashmap. + +Example: + +```rust title="default_example" showLineNumbers +let hashmap: HashMap> = HashMap::default(); + assert(hashmap.is_empty()); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L202-L205 + + +Because `HashMap` has so many generic arguments that are likely to be the same throughout +your program, it may be helpful to create a type alias: + +```rust title="type_alias" showLineNumbers +type MyMap = HashMap>; +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L196-L198 + + +### with_hasher + +```rust title="with_hasher" showLineNumbers +pub fn with_hasher(_build_hasher: B) -> Self + where + B: BuildHasher { +``` +> Source code: noir_stdlib/src/collections/map.nr#L82-L86 + + +Creates a hashmap with an existing `BuildHasher`. This can be used to ensure multiple +hashmaps are created with the same hasher instance. + +Example: + +```rust title="with_hasher_example" showLineNumbers +let my_hasher: BuildHasherDefault = Default::default(); + let hashmap: HashMap> = HashMap::with_hasher(my_hasher); + assert(hashmap.is_empty()); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L207-L211 + + +### get + +```rust title="get" showLineNumbers +pub fn get( + self, + key: K + ) -> Option + where + K: Eq + Hash, + B: BuildHasher, + H: Hasher { +``` +> Source code: noir_stdlib/src/collections/map.nr#L278-L287 + + +Retrieves a value from the hashmap, returning `Option::none()` if it was not found. + +Example: + +```rust title="get_example" showLineNumbers +fn get_example(map: HashMap>) { + let x = map.get(12); + + if x.is_some() { + assert(x.unwrap() == 42); + } +} +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L299-L307 + + +### insert + +```rust title="insert" showLineNumbers +pub fn insert( + &mut self, + key: K, + value: V + ) + where + K: Eq + Hash, + B: BuildHasher, + H: Hasher { +``` +> Source code: noir_stdlib/src/collections/map.nr#L313-L323 + + +Inserts a new key-value pair into the map. If the key was already in the map, its +previous value will be overridden with the newly provided one. + +Example: + +```rust title="insert_example" showLineNumbers +let mut map: HashMap> = HashMap::default(); + map.insert(12, 42); + assert(map.len() == 1); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L213-L217 + + +### remove + +```rust title="remove" showLineNumbers +pub fn remove( + &mut self, + key: K + ) + where + K: Eq + Hash, + B: BuildHasher, + H: Hasher { +``` +> Source code: noir_stdlib/src/collections/map.nr#L356-L365 + + +Removes the given key-value pair from the map. If the key was not already present +in the map, this does nothing. + +Example: + +```rust title="remove_example" showLineNumbers +map.remove(12); + assert(map.is_empty()); + + // If a key was not present in the map, remove does nothing + map.remove(12); + assert(map.is_empty()); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L221-L228 + + +### is_empty + +```rust title="is_empty" showLineNumbers +pub fn is_empty(self) -> bool { +``` +> Source code: noir_stdlib/src/collections/map.nr#L115-L117 + + +True if the length of the hash map is empty. + +Example: + +```rust title="is_empty_example" showLineNumbers +assert(map.is_empty()); + + map.insert(1, 2); + assert(!map.is_empty()); + + map.remove(1); + assert(map.is_empty()); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L230-L238 + + +### len + +```rust title="len" showLineNumbers +pub fn len(self) -> u64 { +``` +> Source code: noir_stdlib/src/collections/map.nr#L264-L266 + + +Returns the current length of this hash map. + +Example: + +```rust title="len_example" showLineNumbers +// This is equivalent to checking map.is_empty() + assert(map.len() == 0); + + map.insert(1, 2); + map.insert(3, 4); + map.insert(5, 6); + assert(map.len() == 3); + + // 3 was already present as a key in the hash map, so the length is unchanged + map.insert(3, 7); + assert(map.len() == 3); + + map.remove(1); + assert(map.len() == 2); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L240-L255 + + +### capacity + +```rust title="capacity" showLineNumbers +pub fn capacity(_self: Self) -> u64 { +``` +> Source code: noir_stdlib/src/collections/map.nr#L271-L273 + + +Returns the maximum capacity of this hashmap. This is always equal to the capacity +specified in the hashmap's type. + +Unlike hashmaps in general purpose programming languages, hashmaps in Noir have a +static capacity that does not increase as the map grows larger. Thus, this capacity +is also the maximum possible element count that can be inserted into the hashmap. +Due to hash collisions (modulo the hashmap length), it is likely the actual maximum +element count will be lower than the full capacity. + +Example: + +```rust title="capacity_example" showLineNumbers +let empty_map: HashMap> = HashMap::default(); + assert(empty_map.len() == 0); + assert(empty_map.capacity() == 42); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L257-L261 + + +### clear + +```rust title="clear" showLineNumbers +pub fn clear(&mut self) { +``` +> Source code: noir_stdlib/src/collections/map.nr#L93-L95 + + +Clears the hashmap, removing all key-value pairs from it. + +Example: + +```rust title="clear_example" showLineNumbers +assert(!map.is_empty()); + map.clear(); + assert(map.is_empty()); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L263-L267 + + +### contains_key + +```rust title="contains_key" showLineNumbers +pub fn contains_key( + self, + key: K + ) -> bool + where + K: Hash + Eq, + B: BuildHasher, + H: Hasher { +``` +> Source code: noir_stdlib/src/collections/map.nr#L101-L110 + + +True if the hashmap contains the given key. Unlike `get`, this will not also return +the value associated with the key. + +Example: + +```rust title="contains_key_example" showLineNumbers +if map.contains_key(7) { + let value = map.get(7); + assert(value.is_some()); + } else { + println("No value for key 7!"); + } +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L269-L276 + + +### entries + +```rust title="entries" showLineNumbers +pub fn entries(self) -> BoundedVec<(K, V), N> { +``` +> Source code: noir_stdlib/src/collections/map.nr#L123-L125 + + +Returns a vector of each key-value pair present in the hashmap. + +The length of the returned vector is always equal to the length of the hashmap. + +Example: + +```rust title="entries_example" showLineNumbers +let entries = map.entries(); + + // The length of a hashmap may not be compile-time known, so we + // need to loop over its capacity instead + for i in 0..map.capacity() { + if i < entries.len() { + let (key, value) = entries.get(i); + println(f"{key} -> {value}"); + } + } +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L310-L321 + + +### keys + +```rust title="keys" showLineNumbers +pub fn keys(self) -> BoundedVec { +``` +> Source code: noir_stdlib/src/collections/map.nr#L144-L146 + + +Returns a vector of each key present in the hashmap. + +The length of the returned vector is always equal to the length of the hashmap. + +Example: + +```rust title="keys_example" showLineNumbers +let keys = map.keys(); + + for i in 0..keys.max_len() { + if i < keys.len() { + let key = keys.get_unchecked(i); + let value = map.get(key).unwrap_unchecked(); + println(f"{key} -> {value}"); + } + } +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L323-L333 + + +### values + +```rust title="values" showLineNumbers +pub fn values(self) -> BoundedVec { +``` +> Source code: noir_stdlib/src/collections/map.nr#L164-L166 + + +Returns a vector of each value present in the hashmap. + +The length of the returned vector is always equal to the length of the hashmap. + +Example: + +```rust title="values_example" showLineNumbers +let values = map.values(); + + for i in 0..values.max_len() { + if i < values.len() { + let value = values.get_unchecked(i); + println(f"Found value {value}"); + } + } +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L335-L344 + + +### iter_mut + +```rust title="iter_mut" showLineNumbers +pub fn iter_mut( + &mut self, + f: fn(K, V) -> (K, V) + ) + where + K: Eq + Hash, + B: BuildHasher, + H: Hasher { +``` +> Source code: noir_stdlib/src/collections/map.nr#L183-L192 + + +Iterates through each key-value pair of the HashMap, setting each key-value pair to the +result returned from the given function. + +Note that since keys can be mutated, the HashMap needs to be rebuilt as it is iterated +through. If this is not desired, use `iter_values_mut` if only values need to be mutated, +or `entries` if neither keys nor values need to be mutated. + +The iteration order is left unspecified. As a result, if two keys are mutated to become +equal, which of the two values that will be present for the key in the resulting map is also unspecified. + +Example: + +```rust title="iter_mut_example" showLineNumbers +// Add 1 to each key in the map, and double the value associated with that key. + map.iter_mut(|k, v| (k + 1, v * 2)); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L348-L351 + + +### iter_keys_mut + +```rust title="iter_keys_mut" showLineNumbers +pub fn iter_keys_mut( + &mut self, + f: fn(K) -> K + ) + where + K: Eq + Hash, + B: BuildHasher, + H: Hasher { +``` +> Source code: noir_stdlib/src/collections/map.nr#L208-L217 + + +Iterates through the HashMap, mutating each key to the result returned from +the given function. + +Note that since keys can be mutated, the HashMap needs to be rebuilt as it is iterated +through. If only iteration is desired and the keys are not intended to be mutated, +prefer using `entries` instead. + +The iteration order is left unspecified. As a result, if two keys are mutated to become +equal, which of the two values that will be present for the key in the resulting map is also unspecified. + +Example: + +```rust title="iter_keys_mut_example" showLineNumbers +// Double each key, leaving the value associated with that key untouched + map.iter_keys_mut(|k| k * 2); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L353-L356 + + +### iter_values_mut + +```rust title="iter_values_mut" showLineNumbers +pub fn iter_values_mut(&mut self, f: fn(V) -> V) { +``` +> Source code: noir_stdlib/src/collections/map.nr#L233-L235 + + +Iterates through the HashMap, applying the given function to each value and mutating the +value to equal the result. This function is more efficient than `iter_mut` and `iter_keys_mut` +because the keys are untouched and the underlying hashmap thus does not need to be reordered. + +Example: + +```rust title="iter_values_mut_example" showLineNumbers +// Halve each value + map.iter_values_mut(|v| v / 2); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L358-L361 + + +### retain + +```rust title="retain" showLineNumbers +pub fn retain(&mut self, f: fn(K, V) -> bool) { +``` +> Source code: noir_stdlib/src/collections/map.nr#L247-L249 + + +Retains only the key-value pairs for which the given function returns true. +Any key-value pairs for which the function returns false will be removed from the map. + +Example: + +```rust title="retain_example" showLineNumbers +map.retain(|k, v| (k != 0) & (v != 0)); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L281-L283 + + +## Trait Implementations + +### default + +```rust title="default" showLineNumbers +impl Default for HashMap +where + B: BuildHasher + Default, + H: Hasher + Default +{ + fn default() -> Self { +``` +> Source code: noir_stdlib/src/collections/map.nr#L462-L469 + + +Constructs an empty HashMap. + +Example: + +```rust title="default_example" showLineNumbers +let hashmap: HashMap> = HashMap::default(); + assert(hashmap.is_empty()); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L202-L205 + + +### eq + +```rust title="eq" showLineNumbers +impl Eq for HashMap +where + K: Eq + Hash, + V: Eq, + B: BuildHasher, + H: Hasher +{ + fn eq(self, other: HashMap) -> bool { +``` +> Source code: noir_stdlib/src/collections/map.nr#L426-L435 + + +Checks if two HashMaps are equal. + +Example: + +```rust title="eq_example" showLineNumbers +let mut map1: HashMap> = HashMap::default(); + let mut map2: HashMap> = HashMap::default(); + + map1.insert(1, 2); + map1.insert(3, 4); + + map2.insert(3, 4); + map2.insert(1, 2); + + assert(map1 == map2); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L285-L296 + diff --git a/docs/versioned_docs/version-v0.30.0/noir/standard_library/containers/index.md b/docs/versioned_docs/version-v0.30.0/noir/standard_library/containers/index.md new file mode 100644 index 00000000000..ea84c6d5c21 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/noir/standard_library/containers/index.md @@ -0,0 +1,5 @@ +--- +title: Containers +description: Container types provided by Noir's standard library for storing and retrieving data +keywords: [containers, data types, vec, hashmap] +--- diff --git a/docs/versioned_docs/version-v0.30.0/noir/standard_library/containers/vec.mdx b/docs/versioned_docs/version-v0.30.0/noir/standard_library/containers/vec.mdx new file mode 100644 index 00000000000..fcfd7e07aa0 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/noir/standard_library/containers/vec.mdx @@ -0,0 +1,151 @@ +--- +title: Vectors +description: Delve into the Vec data type in Noir. Learn about its methods, practical examples, and best practices for using Vectors in your Noir code. +keywords: [noir, vector type, methods, examples, dynamic arrays] +sidebar_position: 6 +--- + +import Experimental from '@site/src/components/Notes/_experimental.mdx'; + + + +A vector is a collection type similar to Rust's `Vec` type. In Noir, it is a convenient way to use slices as mutable arrays. + +Example: + +```rust +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 +``` + +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 +``` + +Example: + +```rust +let slice: [Field] = &[1, 2, 3]; +let vector_from_slice = Vec::from_slice(slice); +assert(vector_from_slice.len() == 3); +``` + +### len + +Returns the number of elements in the vector. + +```rust +pub fn len(self) -> Field +``` + +Example: + +```rust +let empty_vector: Vec = Vec::new(); +assert(empty_vector.len() == 0); +``` + +### 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 +``` + +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) +``` + +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 +``` + +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) +``` + +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 +``` + +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); +``` diff --git a/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/_category_.json b/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/_category_.json new file mode 100644 index 00000000000..5d694210bbf --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 0, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/ciphers.mdx b/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/ciphers.mdx new file mode 100644 index 00000000000..e83e26efb97 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/ciphers.mdx @@ -0,0 +1,32 @@ +--- +title: Ciphers +description: + Learn about the implemented ciphers ready to use for any Noir project +keywords: + [ciphers, Noir project, aes128, encrypt] +sidebar_position: 0 +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +## aes128 + +Given a plaintext as an array of bytes, returns the corresponding aes128 ciphertext (CBC mode). Input padding is automatically performed using PKCS#7, so that the output length is `input.len() + (16 - input.len() % 16)`. + +```rust title="aes128" showLineNumbers +pub fn aes128_encrypt(input: [u8; N], iv: [u8; 16], key: [u8; 16]) -> [u8] {} +``` +> Source code: noir_stdlib/src/aes128.nr#L2-L4 + + +```rust +fn main() { + let input: [u8; 4] = [0, 12, 3, 15] // Random bytes, will be padded to 16 bytes. + let iv: [u8; 16] = [0; 16]; // Initialisation vector + let key: [u8; 16] = [0; 16] // AES key + let ciphertext = std::aes128::aes128_encrypt(inputs.as_bytes(), iv.as_bytes(), key.as_bytes()); // In this case, the output length will be 16 bytes. +} +``` + + + \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/ec_primitives.md b/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/ec_primitives.md new file mode 100644 index 00000000000..d2b42d67b7c --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/ec_primitives.md @@ -0,0 +1,102 @@ +--- +title: Elliptic Curve Primitives +keywords: [cryptographic primitives, Noir project] +sidebar_position: 4 +--- + +Data structures and methods on them that allow you to carry out computations involving elliptic +curves over the (mathematical) field corresponding to `Field`. For the field currently at our +disposal, applications would involve a curve embedded in BN254, e.g. the +[Baby Jubjub curve](https://eips.ethereum.org/EIPS/eip-2494). + +## Data structures + +### Elliptic curve configurations + +(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Curve`), i.e. the specific elliptic +curve you want to use, which would be specified using any one of the methods +`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::new` which take the coefficients in the +defining equation together with a generator point as parameters. You can find more detail in the +comments in +[`noir_stdlib/src/ec.nr`](https://github.com/noir-lang/noir/blob/master/noir_stdlib/src/ec.nr), but +the gist of it is that the elliptic curves of interest are usually expressed in one of the standard +forms implemented here (Twisted Edwards, Montgomery and Short Weierstraß), and in addition to that, +you could choose to use `affine` coordinates (Cartesian coordinates - the usual (x,y) - possibly +together with a point at infinity) or `curvegroup` coordinates (some form of projective coordinates +requiring more coordinates but allowing for more efficient implementations of elliptic curve +operations). Conversions between all of these forms are provided, and under the hood these +conversions are done whenever an operation is more efficient in a different representation (or a +mixed coordinate representation is employed). + +### Points + +(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Point`), i.e. points lying on the +elliptic curve. For a curve configuration `c` and a point `p`, it may be checked that `p` +does indeed lie on `c` by calling `c.contains(p1)`. + +## Methods + +(given a choice of curve representation, e.g. use `std::ec::tecurve::affine::Curve` and use +`std::ec::tecurve::affine::Point`) + +- The **zero element** is given by `Point::zero()`, and we can verify whether a point `p: Point` is + zero by calling `p.is_zero()`. +- **Equality**: Points `p1: Point` and `p2: Point` may be checked for equality by calling + `p1.eq(p2)`. +- **Addition**: For `c: Curve` and points `p1: Point` and `p2: Point` on the curve, adding these two + points is accomplished by calling `c.add(p1,p2)`. +- **Negation**: For a point `p: Point`, `p.negate()` is its negation. +- **Subtraction**: For `c` and `p1`, `p2` as above, subtracting `p2` from `p1` is accomplished by + calling `c.subtract(p1,p2)`. +- **Scalar multiplication**: For `c` as above, `p: Point` a point on the curve and `n: Field`, + scalar multiplication is given by `c.mul(n,p)`. If instead `n :: [u1; N]`, i.e. `n` is a bit + array, the `bit_mul` method may be used instead: `c.bit_mul(n,p)` +- **Multi-scalar multiplication**: For `c` as above and arrays `n: [Field; N]` and `p: [Point; N]`, + multi-scalar multiplication is given by `c.msm(n,p)`. +- **Coordinate representation conversions**: The `into_group` method converts a point or curve + configuration in the affine representation to one in the CurveGroup representation, and + `into_affine` goes in the other direction. +- **Curve representation conversions**: `tecurve` and `montcurve` curves and points are equivalent + and may be converted between one another by calling `into_montcurve` or `into_tecurve` on their + configurations or points. `swcurve` is more general and a curve c of one of the other two types + may be converted to this representation by calling `c.into_swcurve()`, whereas a point `p` lying + on the curve given by `c` may be mapped to its corresponding `swcurve` point by calling + `c.map_into_swcurve(p)`. +- **Map-to-curve methods**: The Elligator 2 method of mapping a field element `n: Field` into a + `tecurve` or `montcurve` with configuration `c` may be called as `c.elligator2_map(n)`. For all of + the curve configurations, the SWU map-to-curve method may be called as `c.swu_map(z,n)`, where + `z: Field` depends on `Field` and `c` and must be chosen by the user (the conditions it needs to + satisfy are specified in the comments + [here](https://github.com/noir-lang/noir/blob/master/noir_stdlib/src/ec.nr)). + +## Examples + +The +[ec_baby_jubjub test](https://github.com/noir-lang/noir/blob/master/test_programs/compile_success_empty/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.30.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx b/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx new file mode 100644 index 00000000000..4394b48f907 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx @@ -0,0 +1,98 @@ +--- +title: ECDSA Signature Verification +description: Learn about the cryptographic primitives regarding ECDSA over the secp256k1 and secp256r1 curves +keywords: [cryptographic primitives, Noir project, ecdsa, secp256k1, secp256r1, signatures] +sidebar_position: 3 +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +Noir supports ECDSA signatures verification over the secp256k1 and secp256r1 curves. + +## ecdsa_secp256k1::verify_signature + +Verifier for ECDSA Secp256k1 signatures. +See ecdsa_secp256k1::verify_signature_slice for a version that accepts slices directly. + +```rust title="ecdsa_secp256k1" showLineNumbers +pub fn verify_signature( + public_key_x: [u8; 32], + public_key_y: [u8; 32], + signature: [u8; 64], + message_hash: [u8; N] +) -> bool +``` +> Source code: noir_stdlib/src/ecdsa_secp256k1.nr#L2-L9 + + +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_secp256k1::verify_signature_slice + +Verifier for ECDSA Secp256k1 signatures where the message is a slice. + +```rust title="ecdsa_secp256k1_slice" showLineNumbers +pub fn verify_signature_slice( + public_key_x: [u8; 32], + public_key_y: [u8; 32], + signature: [u8; 64], + message_hash: [u8] +) -> bool +``` +> Source code: noir_stdlib/src/ecdsa_secp256k1.nr#L13-L20 + + + + +## ecdsa_secp256r1::verify_signature + +Verifier for ECDSA Secp256r1 signatures. +See ecdsa_secp256r1::verify_signature_slice for a version that accepts slices directly. + +```rust title="ecdsa_secp256r1" showLineNumbers +pub fn verify_signature( + public_key_x: [u8; 32], + public_key_y: [u8; 32], + signature: [u8; 64], + message_hash: [u8; N] +) -> bool +``` +> Source code: noir_stdlib/src/ecdsa_secp256r1.nr#L2-L9 + + +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); +} +``` + + + +## ecdsa_secp256r1::verify_signature + +Verifier for ECDSA Secp256r1 signatures where the message is a slice. + +```rust title="ecdsa_secp256r1_slice" showLineNumbers +pub fn verify_signature_slice( + public_key_x: [u8; 32], + public_key_y: [u8; 32], + signature: [u8; 64], + message_hash: [u8] +) -> bool +``` +> Source code: noir_stdlib/src/ecdsa_secp256r1.nr#L13-L20 + + + diff --git a/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/eddsa.mdx b/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/eddsa.mdx new file mode 100644 index 00000000000..c2c0624dfad --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/eddsa.mdx @@ -0,0 +1,37 @@ +--- +title: EdDSA Verification +description: Learn about the cryptographic primitives regarding EdDSA +keywords: [cryptographic primitives, Noir project, eddsa, signatures] +sidebar_position: 5 +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +## eddsa::eddsa_poseidon_verify + +Verifier for EdDSA signatures + +```rust +fn eddsa_poseidon_verify(public_key_x : Field, public_key_y : Field, signature_s: Field, signature_r8_x: Field, signature_r8_y: Field, message: Field) -> bool +``` + +It is also possible to specify the hash algorithm used for the signature by using the `eddsa_verify_with_hasher` function with a parameter implementing the Hasher trait. For instance, if you want to use Poseidon2 instead, you can do the following: +```rust +use dep::std::hash::poseidon2::Poseidon2Hasher; + +let mut hasher = Poseidon2Hasher::default(); +eddsa_verify_with_hasher(pub_key_a.x, pub_key_a.y, s_a, r8_a.x, r8_a.y, msg, &mut hasher); +``` + + + +## eddsa::eddsa_to_pub + +Private to public key conversion. + +Returns `(pub_key_x, pub_key_y)` + +```rust +fn eddsa_to_pub(secret : Field) -> (Field, Field) +``` + diff --git a/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/embedded_curve_ops.mdx b/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/embedded_curve_ops.mdx new file mode 100644 index 00000000000..9dab7dd1047 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/embedded_curve_ops.mdx @@ -0,0 +1,98 @@ +--- +title: Scalar multiplication +description: See how you can perform scalar multiplication in Noir +keywords: [cryptographic primitives, Noir project, scalar multiplication] +sidebar_position: 1 +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +The following functions perform operations over the embedded curve whose coordinates are defined by the configured noir field. +For the BN254 scalar field, this is BabyJubJub or Grumpkin. + +:::note +Suffixes `_low` and `_high` denote low and high limbs of a scalar. +::: + +## embedded_curve_ops::multi_scalar_mul + +Performs multi scalar multiplication over the embedded curve. +The function accepts arbitrary amount of point-scalar pairs on the input, it multiplies the individual pairs over +the curve and returns a sum of the resulting points. + +Points represented as x and y coordinates [x1, y1, x2, y2, ...], scalars as low and high limbs [low1, high1, low2, high2, ...]. + +```rust title="multi_scalar_mul" showLineNumbers +pub fn multi_scalar_mul( + points: [Field; N], // points represented as x and y coordinates [x1, y1, x2, y2, ...] + scalars: [Field; N] // scalars represented as low and high limbs [low1, high1, low2, high2, ...] +) -> [Field; 2] +``` +> Source code: noir_stdlib/src/embedded_curve_ops.nr#L43-L48 + + +example + +```rust +fn main(point_x: Field, point_y: Field, scalar_low: Field, scalar_high: Field) { + let point = std::embedded_curve_ops::multi_scalar_mul([point_x, point_y], [scalar_low, scalar_high]); + println(point); +} +``` + +## embedded_curve_ops::fixed_base_scalar_mul + +Performs fixed base scalar multiplication over the embedded curve (multiplies input scalar with a generator point). +The function accepts a single scalar on the input represented as 2 fields. + +```rust title="fixed_base_scalar_mul" showLineNumbers +pub fn fixed_base_scalar_mul( + scalar_low: Field, + scalar_high: Field +) -> [Field; 2] +``` +> Source code: noir_stdlib/src/embedded_curve_ops.nr#L51-L56 + + +example + +```rust +fn main(scalar_low: Field, scalar_high: Field) { + let point = std::embedded_curve_ops::fixed_base_scalar_mul(scalar_low, scalar_high); + println(point); +} +``` + +## embedded_curve_ops::embedded_curve_add + +Adds two points on the embedded curve. +This function takes two `EmbeddedCurvePoint` structures as parameters, representing points on the curve, and returns a new `EmbeddedCurvePoint` structure that represents their sum. + +### Parameters: +- `point1` (`EmbeddedCurvePoint`): The first point to add. +- `point2` (`EmbeddedCurvePoint`): The second point to add. + +### Returns: +- `EmbeddedCurvePoint`: The resulting point after the addition of `point1` and `point2`. + +```rust title="embedded_curve_add" showLineNumbers +fn embedded_curve_add( + point1: EmbeddedCurvePoint, + point2: EmbeddedCurvePoint +) -> EmbeddedCurvePoint +``` +> Source code: noir_stdlib/src/embedded_curve_ops.nr#L65-L70 + + +example + +```rust +fn main() { + let point1 = EmbeddedCurvePoint { x: 1, y: 2 }; + let point2 = EmbeddedCurvePoint { x: 3, y: 4 }; + let result = std::embedded_curve_ops::embedded_curve_add(point1, point2); + println!("Resulting Point: ({}, {})", result.x, result.y); +} +``` + + diff --git a/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/hashes.mdx b/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/hashes.mdx new file mode 100644 index 00000000000..3b83d9ec31a --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/hashes.mdx @@ -0,0 +1,257 @@ +--- +title: Hash methods +description: + Learn about the cryptographic primitives ready to use for any Noir project, including sha256, + blake2s, pedersen, mimc_bn254 and mimc +keywords: + [cryptographic primitives, Noir project, sha256, blake2s, pedersen, mimc_bn254, mimc, hash] +sidebar_position: 0 +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +## sha256 + +Given an array of bytes, returns the resulting sha256 hash. +Specify a message_size to hash only the first `message_size` bytes of the input. + +```rust title="sha256" showLineNumbers +pub fn sha256(input: [u8; N]) -> [u8; 32] +``` +> Source code: noir_stdlib/src/hash.nr#L10-L12 + + +example: +```rust title="sha256_var" showLineNumbers +let digest = std::hash::sha256_var([x as u8], 1); +``` +> Source code: test_programs/execution_success/sha256/src/main.nr#L17-L19 + + +```rust +fn main() { + let x = [163, 117, 178, 149]; // some random bytes + let hash = std::sha256::sha256_var(x, 4); +} +``` + + + + +## blake2s + +Given an array of bytes, returns an array with the Blake2 hash + +```rust title="blake2s" showLineNumbers +pub fn blake2s(input: [u8; N]) -> [u8; 32] +``` +> Source code: noir_stdlib/src/hash.nr#L16-L18 + + +example: + +```rust +fn main() { + let x = [163, 117, 178, 149]; // some random bytes + let hash = std::hash::blake2s(x); +} +``` + + + +## blake3 + +Given an array of bytes, returns an array with the Blake3 hash + +```rust title="blake3" showLineNumbers +pub fn blake3(input: [u8; N]) -> [u8; 32] +``` +> Source code: noir_stdlib/src/hash.nr#L22-L24 + + +example: + +```rust +fn main() { + let x = [163, 117, 178, 149]; // some random bytes + let hash = std::hash::blake3(x); +} +``` + + + +## pedersen_hash + +Given an array of Fields, returns the Pedersen hash. + +```rust title="pedersen_hash" showLineNumbers +pub fn pedersen_hash(input: [Field; N]) -> Field +``` +> Source code: noir_stdlib/src/hash.nr#L46-L48 + + +example: + +```rust title="pedersen-hash" showLineNumbers +use dep::std; + +fn main(x: Field, y: Field, expected_hash: Field) { + let hash = std::hash::pedersen_hash([x, y]); + assert_eq(hash, expected_hash); +} +``` +> Source code: test_programs/execution_success/pedersen_hash/src/main.nr#L1-L8 + + + + +## pedersen_commitment + +Given an array of Fields, returns the Pedersen commitment. + +```rust title="pedersen_commitment" showLineNumbers +struct PedersenPoint { + x : Field, + y : Field, +} + +pub fn pedersen_commitment(input: [Field; N]) -> PedersenPoint { +``` +> Source code: noir_stdlib/src/hash.nr#L27-L34 + + +example: + +```rust title="pedersen-commitment" showLineNumbers +use dep::std; + +fn main(x: Field, y: Field, expected_commitment: std::hash::PedersenPoint) { + let commitment = std::hash::pedersen_commitment([x, y]); + assert_eq(commitment.x, expected_commitment.x); + assert_eq(commitment.y, expected_commitment.y); +} +``` +> Source code: test_programs/execution_success/pedersen_commitment/src/main.nr#L1-L9 + + + + +## 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 title="keccak256" showLineNumbers +pub fn keccak256(input: [u8; N], message_size: u32) -> [u8; 32] +``` +> Source code: noir_stdlib/src/hash.nr#L68-L70 + + +example: + +```rust title="keccak256" showLineNumbers +use dep::std; + +fn main(x: Field, result: [u8; 32]) { + // We use the `as` keyword here to denote the fact that we want to take just the first byte from the x Field + // The padding is taken care of by the program + let digest = std::hash::keccak256([x as u8], 1); + assert(digest == result); + + //#1399: variable message 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); + + 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); + + assert(hash_a != hash_c); +} +``` +> Source code: test_programs/execution_success/keccak256/src/main.nr#L1-L22 + + + + +## 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 title="poseidon" showLineNumbers +use dep::std::hash::poseidon; +use dep::std::hash::poseidon2; + +fn main(x1: [Field; 2], y1: pub Field, x2: [Field; 4], y2: pub Field, x3: [Field; 4], y3: Field) { + let hash1 = poseidon::bn254::hash_2(x1); + assert(hash1 == y1); + + let hash2 = poseidon::bn254::hash_4(x2); + assert(hash2 == y2); + + let hash3 = poseidon2::Poseidon2::hash(x3, x3.len()); + assert(hash3 == y3); +} +``` +> Source code: test_programs/execution_success/poseidon_bn254_hash/src/main.nr#L1-L15 + + +## poseidon 2 + +Given an array of Fields, returns a new Field with the Poseidon2 Hash. Contrary to the Poseidon +function, there is only one hash and you can specify a message_size to hash only the first +`message_size` bytes of the input, + +```rust +// example for hashing the first three elements of the input +Poseidon2::hash(input, 3); +``` + +The above example for Poseidon also includes Poseidon2. + +## 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]) -> 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.30.0/noir/standard_library/cryptographic_primitives/index.md b/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/index.md new file mode 100644 index 00000000000..650f30165d5 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/index.md @@ -0,0 +1,14 @@ +--- +title: Cryptographic Primitives +description: + Learn about the cryptographic primitives ready to use for any Noir project +keywords: + [ + cryptographic primitives, + Noir project, + ] +--- + +The Noir team is progressively adding new cryptographic primitives to the standard library. Reach out for news or if you would be interested in adding more of these calculations in Noir. + +Some methods are available thanks to the Aztec backend, not being performed using Noir. When using other backends, these methods may or may not be supplied. diff --git a/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/schnorr.mdx b/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/schnorr.mdx new file mode 100644 index 00000000000..b59e69c8f07 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/noir/standard_library/cryptographic_primitives/schnorr.mdx @@ -0,0 +1,64 @@ +--- +title: Schnorr Signatures +description: Learn how you can verify Schnorr signatures using Noir +keywords: [cryptographic primitives, Noir project, schnorr, signatures] +sidebar_position: 2 +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +## schnorr::verify_signature + +Verifier for Schnorr signatures over the embedded curve (for BN254 it is Grumpkin). +See schnorr::verify_signature_slice for a version that works directly on slices. + +```rust title="schnorr_verify" showLineNumbers +pub fn verify_signature( + public_key_x: Field, + public_key_y: Field, + signature: [u8; 64], + message: [u8; N] +) -> bool +``` +> Source code: noir_stdlib/src/schnorr.nr#L2-L9 + + +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() +); + +... +``` + + + +## schnorr::verify_signature_slice + +Verifier for Schnorr signatures over the embedded curve (for BN254 it is Grumpkin) +where the message is a slice. + +```rust title="schnorr_verify_slice" showLineNumbers +pub fn verify_signature_slice( + public_key_x: Field, + public_key_y: Field, + signature: [u8; 64], + message: [u8] +) -> bool +``` +> Source code: noir_stdlib/src/schnorr.nr#L13-L20 + + + diff --git a/docs/versioned_docs/version-v0.30.0/noir/standard_library/logging.md b/docs/versioned_docs/version-v0.30.0/noir/standard_library/logging.md new file mode 100644 index 00000000000..db75ef9f86f --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/noir/standard_library/logging.md @@ -0,0 +1,78 @@ +--- +title: Logging +description: + Learn how to use the println statement for debugging in Noir with this tutorial. Understand the + basics of logging in Noir and how to implement it in your code. +keywords: + [ + noir logging, + println statement, + print statement, + debugging in noir, + noir std library, + logging tutorial, + basic logging in noir, + noir logging implementation, + noir debugging techniques, + rust, + ] +--- + +The standard library provides two familiar statements you can use: `println` and `print`. Despite being a limited implementation of rust's `println!` and `print!` macros, these constructs can be useful for debugging. + +You can print the output of both statements in your Noir code by using the `nargo execute` command or the `--show-output` flag when using `nargo test` (provided there are print statements in your tests). + +It is recommended to use `nargo execute` if you want to debug failing constraints with `println` or `print` statements. This is due to every input in a test being a constant rather than a witness, so we issue an error during compilation while we only print during execution (which comes after compilation). Neither `println`, nor `print` are callable for failed constraints caught at compile time. + +Both `print` and `println` are generic functions which can work on integers, fields, strings, and even structs or expressions. Note however, that slices are currently unsupported. For example: + +```rust +struct Person { + age: Field, + height: Field, +} + +fn main(age: Field, height: Field) { + let person = Person { + age: age, + height: height, + }; + println(person); + println(age + height); + println("Hello world!"); +} +``` + +You can print different types in the same statement (including strings) with a type called `fmtstr`. It can be specified in the same way as a normal string, just prepended with an "f" character: + +```rust + let fmt_str = f"i: {i}, j: {j}"; + println(fmt_str); + + let s = myStruct { y: x, x: y }; + println(s); + + println(f"i: {i}, s: {s}"); + + println(x); + println([x, y]); + + let foo = fooStruct { my_struct: s, foo: 15 }; + println(f"s: {s}, foo: {foo}"); + + println(15); // prints 0x0f, implicit Field + println(-1 as u8); // prints 255 + println(-1 as i8); // prints -1 +``` + +Examples shown above are interchangeable between the two `print` statements: + +```rust +let person = Person { age : age, height : height }; + +println(person); +print(person); + +println("Hello world!"); // Prints with a newline at the end of the input +print("Hello world!"); // Prints the input and keeps cursor on the same line +``` diff --git a/docs/versioned_docs/version-v0.30.0/noir/standard_library/merkle_trees.md b/docs/versioned_docs/version-v0.30.0/noir/standard_library/merkle_trees.md new file mode 100644 index 00000000000..6a9ebf72ada --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/noir/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/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.as_slice()); + 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.30.0/noir/standard_library/options.md b/docs/versioned_docs/version-v0.30.0/noir/standard_library/options.md new file mode 100644 index 00000000000..a1bd4e1de5f --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/noir/standard_library/options.md @@ -0,0 +1,101 @@ +--- +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), +} +``` + +The `Option` type, already imported into your Noir program, can be used directly: + +```rust +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. + +### expect + +Asserts `self.is_some()` with a provided custom message and returns the contained `Some` value. The custom message is expected to be a format string. + +### 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.30.0/noir/standard_library/recursion.md b/docs/versioned_docs/version-v0.30.0/noir/standard_library/recursion.md new file mode 100644 index 00000000000..a93894043dc --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/noir/standard_library/recursion.md @@ -0,0 +1,88 @@ +--- +title: Recursive Proofs +description: Learn about how to write recursive proofs in Noir. +keywords: [recursion, recursive proofs, verification_key, 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. + +Read [the explainer on recursion](../../explainers/explainer-recursion.md) to know more about this function and the [guide on how to use it.](../../how_to/how-to-recursion.md) + +## The `#[recursive]` Attribute + +In Noir, the `#[recursive]` attribute is used to indicate that a circuit is designed for recursive proof generation. When applied, it informs the compiler and the tooling that the circuit should be compiled in a way that makes its proofs suitable for recursive verification. This attribute eliminates the need for manual flagging of recursion at the tooling level, streamlining the proof generation process for recursive circuits. + +### Example usage with `#[recursive]` + +```rust +#[recursive] +fn main(x: Field, y: pub Field) { + assert(x == y, "x and y are not equal"); +} + +// This marks the circuit as recursion-friendly and indicates that proofs generated from this circuit +// are intended for recursive verification. +``` + +By incorporating this attribute directly in the circuit's definition, tooling like Nargo and NoirJS can automatically execute recursive-specific duties for Noir programs (e.g. recursive-friendly proof artifact generation) without additional flags or configurations. + +## Verifying Recursive Proofs + +```rust +#[foreign(recursive_aggregation)] +pub fn verify_proof(verification_key: [Field], proof: [Field], public_inputs: [Field], key_hash: Field) {} +``` + +:::info + +This is a black box function. Read [this section](./black_box_fns) to learn more about black box functions in Noir. + +::: + +## Example usage + +```rust +use dep::std; + +fn main( + verification_key : [Field; 114], + proof : [Field; 93], + public_inputs : [Field; 1], + key_hash : Field, + proof_b : [Field; 93], +) { + std::verify_proof( + verification_key.as_slice(), + proof.as_slice(), + public_inputs.as_slice(), + key_hash + ); + + std::verify_proof( + verification_key.as_slice(), + proof_b.as_slice(), + public_inputs.as_slice(), + key_hash + ); +} +``` + +You can see a full example of recursive proofs in [this example recursion demo repo](https://github.com/noir-lang/noir-examples/tree/master/recursion). + +## 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. + +### `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. diff --git a/docs/versioned_docs/version-v0.30.0/noir/standard_library/traits.md b/docs/versioned_docs/version-v0.30.0/noir/standard_library/traits.md new file mode 100644 index 00000000000..a14312d2792 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/noir/standard_library/traits.md @@ -0,0 +1,464 @@ +--- +title: Traits +description: Noir's stdlib provides a few commonly used traits. +keywords: [traits, trait, interface, protocol, default, add, eq] +--- + +## `std::default` + +### `std::default::Default` + +```rust title="default-trait" showLineNumbers +trait Default { + fn default() -> Self; +} +``` +> Source code: noir_stdlib/src/default.nr#L1-L5 + + +Constructs a default value of a type. + +Implementations: +```rust +impl Default for Field { .. } + +impl Default for i8 { .. } +impl Default for i16 { .. } +impl Default for i32 { .. } +impl Default for i64 { .. } + +impl Default for u8 { .. } +impl Default for u16 { .. } +impl Default for u32 { .. } +impl Default for u64 { .. } + +impl Default for () { .. } +impl Default for bool { .. } + +impl Default for [T; N] + where T: Default { .. } + +impl Default for [T] { .. } + +impl Default for (A, B) + where A: Default, B: Default { .. } + +impl Default for (A, B, C) + where A: Default, B: Default, C: Default { .. } + +impl Default for (A, B, C, D) + where A: Default, B: Default, C: Default, D: Default { .. } + +impl Default for (A, B, C, D, E) + where A: Default, B: Default, C: Default, D: Default, E: Default { .. } +``` + +For primitive integer types, the return value of `default` is `0`. Container +types such as arrays are filled with default values of their element type, +except slices whose length is unknown and thus defaulted to zero. + + +## `std::convert` + +### `std::convert::From` + +```rust title="from-trait" showLineNumbers +trait From { + fn from(input: T) -> Self; +} +``` +> Source code: noir_stdlib/src/convert.nr#L1-L5 + + +The `From` trait defines how to convert from a given type `T` to the type on which the trait is implemented. + +The Noir standard library provides a number of implementations of `From` between primitive types. +```rust title="from-impls" showLineNumbers +// Unsigned integers + +impl From for u32 { fn from(value: u8) -> u32 { value as u32 } } + +impl From for u64 { fn from(value: u8) -> u64 { value as u64 } } +impl From for u64 { fn from(value: u32) -> u64 { value as u64 } } + +impl From for Field { fn from(value: u8) -> Field { value as Field } } +impl From for Field { fn from(value: u32) -> Field { value as Field } } +impl From for Field { fn from(value: u64) -> Field { value as Field } } + +// Signed integers + +impl From for i32 { fn from(value: i8) -> i32 { value as i32 } } + +impl From for i64 { fn from(value: i8) -> i64 { value as i64 } } +impl From for i64 { fn from(value: i32) -> i64 { value as i64 } } + +// Booleans +impl From for u8 { fn from(value: bool) -> u8 { value as u8 } } +impl From for u32 { fn from(value: bool) -> u32 { value as u32 } } +impl From for u64 { fn from(value: bool) -> u64 { value as u64 } } +impl From for i8 { fn from(value: bool) -> i8 { value as i8 } } +impl From for i32 { fn from(value: bool) -> i32 { value as i32 } } +impl From for i64 { fn from(value: bool) -> i64 { value as i64 } } +impl From for Field { fn from(value: bool) -> Field { value as Field } } +``` +> Source code: noir_stdlib/src/convert.nr#L25-L52 + + +#### When to implement `From` + +As a general rule of thumb, `From` may be implemented in the [situations where it would be suitable in Rust](https://doc.rust-lang.org/std/convert/trait.From.html#when-to-implement-from): + +- The conversion is *infallible*: Noir does not provide an equivalent to Rust's `TryFrom`, if the conversion can fail then provide a named method instead. +- The conversion is *lossless*: semantically, it should not lose or discard information. For example, `u32: From` can losslessly convert any `u16` into a valid `u32` such that the original `u16` can be recovered. On the other hand, `u16: From` should not be implemented as `2**16` is a `u32` which cannot be losslessly converted into a `u16`. +- The conversion is *value-preserving*: the conceptual kind and meaning of the resulting value is the same, even though the Noir type and technical representation might be different. While it's possible to infallibly and losslessly convert a `u8` into a `str<2>` hex representation, `4u8` and `"04"` are too different for `str<2>: From` to be implemented. +- The conversion is *obvious*: it's the only reasonable conversion between the two types. If there's ambiguity on how to convert between them such that the same input could potentially map to two different values then a named method should be used. For instance rather than implementing `U128: From<[u8; 16]>`, the methods `U128::from_le_bytes` and `U128::from_be_bytes` are used as otherwise the endianness of the array would be ambiguous, resulting in two potential values of `U128` from the same byte array. + +One additional recommendation specific to Noir is: +- The conversion is *efficient*: it's relatively cheap to convert between the two types. Due to being a ZK DSL, it's more important to avoid unnecessary computation compared to Rust. If the implementation of `From` would encourage users to perform unnecessary conversion, resulting in additional proving time, then it may be preferable to expose functionality such that this conversion may be avoided. + +### `std::convert::Into` + +The `Into` trait is defined as the reciprocal of `From`. It should be easy to convince yourself that if we can convert to type `A` from type `B`, then it's possible to convert type `B` into type `A`. + +For this reason, implementing `From` on a type will automatically generate a matching `Into` implementation. One should always prefer implementing `From` over `Into` as implementing `Into` will not generate a matching `From` implementation. + +```rust title="into-trait" showLineNumbers +trait Into { + fn into(self) -> T; +} + +impl Into for U where T: From { + fn into(self) -> T { + T::from(self) + } +} +``` +> Source code: noir_stdlib/src/convert.nr#L13-L23 + + +`Into` is most useful when passing function arguments where the types don't quite match up with what the function expects. In this case, the compiler has enough type information to perform the necessary conversion by just appending `.into()` onto the arguments in question. + + +## `std::cmp` + +### `std::cmp::Eq` + +```rust title="eq-trait" showLineNumbers +trait Eq { + fn eq(self, other: Self) -> bool; +} +``` +> Source code: noir_stdlib/src/cmp.nr#L1-L5 + + +Returns `true` if `self` is equal to `other`. Implementing this trait on a type +allows the type to be used with `==` and `!=`. + +Implementations: +```rust +impl Eq for Field { .. } + +impl Eq for i8 { .. } +impl Eq for i16 { .. } +impl Eq for i32 { .. } +impl Eq for i64 { .. } + +impl Eq for u8 { .. } +impl Eq for u16 { .. } +impl Eq for u32 { .. } +impl Eq for u64 { .. } + +impl Eq for () { .. } +impl Eq for bool { .. } + +impl Eq for [T; N] + where T: Eq { .. } + +impl Eq for [T] + where T: Eq { .. } + +impl Eq for (A, B) + where A: Eq, B: Eq { .. } + +impl Eq for (A, B, C) + where A: Eq, B: Eq, C: Eq { .. } + +impl Eq for (A, B, C, D) + where A: Eq, B: Eq, C: Eq, D: Eq { .. } + +impl Eq for (A, B, C, D, E) + where A: Eq, B: Eq, C: Eq, D: Eq, E: Eq { .. } +``` + +### `std::cmp::Ord` + +```rust title="ord-trait" showLineNumbers +trait Ord { + fn cmp(self, other: Self) -> Ordering; +} +``` +> Source code: noir_stdlib/src/cmp.nr#L102-L106 + + +`a.cmp(b)` compares two values returning `Ordering::less()` if `a < b`, +`Ordering::equal()` if `a == b`, or `Ordering::greater()` if `a > b`. +Implementing this trait on a type allows `<`, `<=`, `>`, and `>=` to be +used on values of the type. + +`std::cmp` also provides `max` and `min` functions for any type which implements the `Ord` trait. + +Implementations: + +```rust +impl Ord for u8 { .. } +impl Ord for u16 { .. } +impl Ord for u32 { .. } +impl Ord for u64 { .. } + +impl Ord for i8 { .. } +impl Ord for i16 { .. } +impl Ord for i32 { .. } + +impl Ord for i64 { .. } + +impl Ord for () { .. } +impl Ord for bool { .. } + +impl Ord for [T; N] + where T: Ord { .. } + +impl Ord for [T] + where T: Ord { .. } + +impl Ord for (A, B) + where A: Ord, B: Ord { .. } + +impl Ord for (A, B, C) + where A: Ord, B: Ord, C: Ord { .. } + +impl Ord for (A, B, C, D) + where A: Ord, B: Ord, C: Ord, D: Ord { .. } + +impl Ord for (A, B, C, D, E) + where A: Ord, B: Ord, C: Ord, D: Ord, E: Ord { .. } +``` + +## `std::ops` + +### `std::ops::Add`, `std::ops::Sub`, `std::ops::Mul`, and `std::ops::Div` + +These traits abstract over addition, subtraction, multiplication, and division respectively. +Implementing these traits for a given type will also allow that type to be used with the corresponding operator +for that trait (`+` for Add, etc) in addition to the normal method names. + +```rust title="add-trait" showLineNumbers +trait Add { + fn add(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/arith.nr#L1-L5 + +```rust title="sub-trait" showLineNumbers +trait Sub { + fn sub(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/arith.nr#L19-L23 + +```rust title="mul-trait" showLineNumbers +trait Mul { + fn mul(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/arith.nr#L37-L41 + +```rust title="div-trait" showLineNumbers +trait Div { + fn div(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/arith.nr#L55-L59 + + +The implementations block below is given for the `Add` trait, but the same types that implement +`Add` also implement `Sub`, `Mul`, and `Div`. + +Implementations: +```rust +impl Add for Field { .. } + +impl Add for i8 { .. } +impl Add for i16 { .. } +impl Add for i32 { .. } +impl Add for i64 { .. } + +impl Add for u8 { .. } +impl Add for u16 { .. } +impl Add for u32 { .. } +impl Add for u64 { .. } +``` + +### `std::ops::Rem` + +```rust title="rem-trait" showLineNumbers +trait Rem{ + fn rem(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/arith.nr#L73-L77 + + +`Rem::rem(a, b)` is the remainder function returning the result of what is +left after dividing `a` and `b`. Implementing `Rem` allows the `%` operator +to be used with the implementation type. + +Unlike other numeric traits, `Rem` is not implemented for `Field`. + +Implementations: +```rust +impl Rem for u8 { fn rem(self, other: u8) -> u8 { self % other } } +impl Rem for u16 { fn rem(self, other: u16) -> u16 { self % other } } +impl Rem for u32 { fn rem(self, other: u32) -> u32 { self % other } } +impl Rem for u64 { fn rem(self, other: u64) -> u64 { self % other } } + +impl Rem for i8 { fn rem(self, other: i8) -> i8 { self % other } } +impl Rem for i16 { fn rem(self, other: i16) -> i16 { self % other } } +impl Rem for i32 { fn rem(self, other: i32) -> i32 { self % other } } +impl Rem for i64 { fn rem(self, other: i64) -> i64 { self % other } } +``` + +### `std::ops::Neg` + +```rust title="neg-trait" showLineNumbers +trait Neg { + fn neg(self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/arith.nr#L89-L93 + + +`Neg::neg` is equivalent to the unary negation operator `-`. + +Implementations: +```rust title="neg-trait-impls" showLineNumbers +impl Neg for Field { fn neg(self) -> Field { -self } } + +impl Neg for i8 { fn neg(self) -> i8 { -self } } +impl Neg for i16 { fn neg(self) -> i16 { -self } } +impl Neg for i32 { fn neg(self) -> i32 { -self } } +impl Neg for i64 { fn neg(self) -> i64 { -self } } +``` +> Source code: noir_stdlib/src/ops/arith.nr#L95-L102 + + +### `std::ops::Not` + +```rust title="not-trait" showLineNumbers +trait Not { + fn not(self: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/bit.nr#L1-L5 + + +`Not::not` is equivalent to the unary bitwise NOT operator `!`. + +Implementations: +```rust title="not-trait-impls" showLineNumbers +impl Not for bool { fn not(self) -> bool { !self } } + +impl Not for u64 { fn not(self) -> u64 { !self } } +impl Not for u32 { fn not(self) -> u32 { !self } } +impl Not for u16 { fn not(self) -> u16 { !self } } +impl Not for u8 { fn not(self) -> u8 { !self } } +impl Not for u1 { fn not(self) -> u1 { !self } } + +impl Not for i8 { fn not(self) -> i8 { !self } } +impl Not for i16 { fn not(self) -> i16 { !self } } +impl Not for i32 { fn not(self) -> i32 { !self } } +impl Not for i64 { fn not(self) -> i64 { !self } } +``` +> Source code: noir_stdlib/src/ops/bit.nr#L7-L20 + + +### `std::ops::{ BitOr, BitAnd, BitXor }` + +```rust title="bitor-trait" showLineNumbers +trait BitOr { + fn bitor(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/bit.nr#L22-L26 + +```rust title="bitand-trait" showLineNumbers +trait BitAnd { + fn bitand(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/bit.nr#L40-L44 + +```rust title="bitxor-trait" showLineNumbers +trait BitXor { + fn bitxor(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/bit.nr#L58-L62 + + +Traits for the bitwise operations `|`, `&`, and `^`. + +Implementing `BitOr`, `BitAnd` or `BitXor` for a type allows the `|`, `&`, or `^` operator respectively +to be used with the type. + +The implementations block below is given for the `BitOr` trait, but the same types that implement +`BitOr` also implement `BitAnd` and `BitXor`. + +Implementations: +```rust +impl BitOr for bool { fn bitor(self, other: bool) -> bool { self | other } } + +impl BitOr for u8 { fn bitor(self, other: u8) -> u8 { self | other } } +impl BitOr for u16 { fn bitor(self, other: u16) -> u16 { self | other } } +impl BitOr for u32 { fn bitor(self, other: u32) -> u32 { self | other } } +impl BitOr for u64 { fn bitor(self, other: u64) -> u64 { self | other } } + +impl BitOr for i8 { fn bitor(self, other: i8) -> i8 { self | other } } +impl BitOr for i16 { fn bitor(self, other: i16) -> i16 { self | other } } +impl BitOr for i32 { fn bitor(self, other: i32) -> i32 { self | other } } +impl BitOr for i64 { fn bitor(self, other: i64) -> i64 { self | other } } +``` + +### `std::ops::{ Shl, Shr }` + +```rust title="shl-trait" showLineNumbers +trait Shl { + fn shl(self, other: u8) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/bit.nr#L76-L80 + +```rust title="shr-trait" showLineNumbers +trait Shr { + fn shr(self, other: u8) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/bit.nr#L93-L97 + + +Traits for a bit shift left and bit shift right. + +Implementing `Shl` for a type allows the left shift operator (`<<`) to be used with the implementation type. +Similarly, implementing `Shr` allows the right shift operator (`>>`) to be used with the type. + +Note that bit shifting is not currently implemented for signed types. + +The implementations block below is given for the `Shl` trait, but the same types that implement +`Shl` also implement `Shr`. + +Implementations: +```rust +impl Shl for u8 { fn shl(self, other: u8) -> u8 { self << other } } +impl Shl for u16 { fn shl(self, other: u16) -> u16 { self << other } } +impl Shl for u32 { fn shl(self, other: u32) -> u32 { self << other } } +impl Shl for u64 { fn shl(self, other: u64) -> u64 { self << other } } +``` diff --git a/docs/versioned_docs/version-v0.30.0/noir/standard_library/zeroed.md b/docs/versioned_docs/version-v0.30.0/noir/standard_library/zeroed.md new file mode 100644 index 00000000000..f450fecdd36 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/noir/standard_library/zeroed.md @@ -0,0 +1,26 @@ +--- +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 +- Slice +- String +- Tuple +- Function + +Using it on other types could result in unexpected behavior. diff --git a/docs/versioned_docs/version-v0.30.0/reference/NoirJS/backend_barretenberg/.nojekyll b/docs/versioned_docs/version-v0.30.0/reference/NoirJS/backend_barretenberg/.nojekyll new file mode 100644 index 00000000000..e2ac6616add --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/reference/NoirJS/backend_barretenberg/.nojekyll @@ -0,0 +1 @@ +TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.30.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md b/docs/versioned_docs/version-v0.30.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md new file mode 100644 index 00000000000..d7249d24330 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md @@ -0,0 +1,160 @@ +# BarretenbergBackend + +## Extends + +- `BarretenbergVerifierBackend` + +## Implements + +- [`Backend`](../index.md#backend) + +## Constructors + +### new BarretenbergBackend(acirCircuit, options) + +```ts +new BarretenbergBackend(acirCircuit, options): BarretenbergBackend +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `acirCircuit` | `CompiledCircuit` | +| `options` | [`BackendOptions`](../type-aliases/BackendOptions.md) | + +#### Returns + +[`BarretenbergBackend`](BarretenbergBackend.md) + +#### Inherited from + +BarretenbergVerifierBackend.constructor + +## Properties + +| Property | Type | Description | Inheritance | +| :------ | :------ | :------ | :------ | +| `acirComposer` | `any` | - | BarretenbergVerifierBackend.acirComposer | +| `acirUncompressedBytecode` | `Uint8Array` | - | BarretenbergVerifierBackend.acirUncompressedBytecode | +| `api` | `Barretenberg` | - | BarretenbergVerifierBackend.api | +| `options` | [`BackendOptions`](../type-aliases/BackendOptions.md) | - | BarretenbergVerifierBackend.options | + +## Methods + +### destroy() + +```ts +destroy(): Promise +``` + +#### Returns + +`Promise`\<`void`\> + +#### Inherited from + +BarretenbergVerifierBackend.destroy + +*** + +### generateProof() + +```ts +generateProof(compressedWitness): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `compressedWitness` | `Uint8Array` | + +#### Returns + +`Promise`\<`ProofData`\> + +#### Description + +Generates a proof + +*** + +### generateRecursiveProofArtifacts() + +```ts +generateRecursiveProofArtifacts(proofData, numOfPublicInputs): Promise +``` + +Generates artifacts that will be passed to a circuit that will verify this proof. + +Instead of passing the proof and verification key as a byte array, we pass them +as fields which makes it cheaper to verify in a circuit. + +The proof that is passed here will have been created using a circuit +that has the #[recursive] attribute on its `main` method. + +The number of public inputs denotes how many public inputs are in the inner proof. + +#### Parameters + +| Parameter | Type | Default value | +| :------ | :------ | :------ | +| `proofData` | `ProofData` | `undefined` | +| `numOfPublicInputs` | `number` | `0` | + +#### Returns + +`Promise`\<`object`\> + +#### Example + +```typescript +const artifacts = await backend.generateRecursiveProofArtifacts(proof, numOfPublicInputs); +``` + +*** + +### getVerificationKey() + +```ts +getVerificationKey(): Promise +``` + +#### Returns + +`Promise`\<`Uint8Array`\> + +#### Inherited from + +BarretenbergVerifierBackend.getVerificationKey + +*** + +### verifyProof() + +```ts +verifyProof(proofData): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `proofData` | `ProofData` | + +#### Returns + +`Promise`\<`boolean`\> + +#### Inherited from + +BarretenbergVerifierBackend.verifyProof + +#### Description + +Verifies 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.30.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergVerifier.md b/docs/versioned_docs/version-v0.30.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergVerifier.md new file mode 100644 index 00000000000..500276ea748 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergVerifier.md @@ -0,0 +1,58 @@ +# BarretenbergVerifier + +## Constructors + +### new BarretenbergVerifier(options) + +```ts +new BarretenbergVerifier(options): BarretenbergVerifier +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `options` | [`BackendOptions`](../type-aliases/BackendOptions.md) | + +#### Returns + +[`BarretenbergVerifier`](BarretenbergVerifier.md) + +## Methods + +### destroy() + +```ts +destroy(): Promise +``` + +#### Returns + +`Promise`\<`void`\> + +*** + +### verifyProof() + +```ts +verifyProof(proofData, verificationKey): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `proofData` | `ProofData` | +| `verificationKey` | `Uint8Array` | + +#### Returns + +`Promise`\<`boolean`\> + +#### Description + +Verifies 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.30.0/reference/NoirJS/backend_barretenberg/index.md b/docs/versioned_docs/version-v0.30.0/reference/NoirJS/backend_barretenberg/index.md new file mode 100644 index 00000000000..64971973196 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/reference/NoirJS/backend_barretenberg/index.md @@ -0,0 +1,59 @@ +# backend_barretenberg + +## Exports + +### Classes + +| Class | Description | +| :------ | :------ | +| [BarretenbergBackend](classes/BarretenbergBackend.md) | - | +| [BarretenbergVerifier](classes/BarretenbergVerifier.md) | - | + +### Type Aliases + +| Type alias | Description | +| :------ | :------ | +| [BackendOptions](type-aliases/BackendOptions.md) | - | + +## References + +### CompiledCircuit + +Renames and re-exports [Backend](index.md#backend) + +*** + +### ProofData + +Renames and re-exports [Backend](index.md#backend) + +## Variables + +### Backend + +```ts +Backend: any; +``` + +## Functions + +### publicInputsToWitnessMap() + +```ts +publicInputsToWitnessMap(publicInputs, abi): Backend +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `publicInputs` | `string`[] | +| `abi` | `Abi` | + +#### Returns + +[`Backend`](index.md#backend) + +*** + +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.30.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md b/docs/versioned_docs/version-v0.30.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md new file mode 100644 index 00000000000..b49a479f4f4 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md @@ -0,0 +1,21 @@ +# 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 | +| :------ | :------ | :------ | +| `memory` | `object` | - | +| `memory.maximum` | `number` | - | +| `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.30.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs b/docs/versioned_docs/version-v0.30.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs new file mode 100644 index 00000000000..d7d5128f9e3 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs @@ -0,0 +1,4 @@ +// @ts-check +/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ +const typedocSidebar = { items: [{"type":"category","label":"Classes","items":[{"type":"doc","id":"reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend","label":"BarretenbergBackend"},{"type":"doc","id":"reference/NoirJS/backend_barretenberg/classes/BarretenbergVerifier","label":"BarretenbergVerifier"}]},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions","label":"BackendOptions"}]}]}; +module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/.nojekyll b/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/.nojekyll new file mode 100644 index 00000000000..e2ac6616add --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/.nojekyll @@ -0,0 +1 @@ +TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/classes/Noir.md b/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/classes/Noir.md new file mode 100644 index 00000000000..45dd62ee57e --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/classes/Noir.md @@ -0,0 +1,132 @@ +# Noir + +## Constructors + +### new Noir(circuit, backend) + +```ts +new Noir(circuit, backend?): Noir +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `circuit` | `CompiledCircuit` | +| `backend`? | `any` | + +#### 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) +``` + +*** + +### generateProof() + +```ts +generateProof(inputs, foreignCallHandler?): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `inputs` | `InputMap` | +| `foreignCallHandler`? | [`ForeignCallHandler`](../type-aliases/ForeignCallHandler.md) | + +#### Returns + +`Promise`\<`ProofData`\> + +#### Description + +Generates a witness and a proof given an object as input. + +#### Example + +```typescript +async generateProof(input) +``` + +*** + +### verifyProof() + +```ts +verifyProof(proofData): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `proofData` | `ProofData` | + +#### Returns + +`Promise`\<`boolean`\> + +#### Description + +Instantiates the verification key and verifies a proof. + +#### Example + +```typescript +async verifyProof(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.30.0/reference/NoirJS/noir_js/functions/and.md b/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/functions/and.md new file mode 100644 index 00000000000..c783283e396 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/functions/and.md @@ -0,0 +1,22 @@ +# and() + +```ts +and(lhs, rhs): string +``` + +Performs a bitwise AND operation between `lhs` and `rhs` + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `lhs` | `string` | | +| `rhs` | `string` | | + +## Returns + +`string` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/functions/blake2s256.md b/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/functions/blake2s256.md new file mode 100644 index 00000000000..7882d0da8d5 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/functions/blake2s256.md @@ -0,0 +1,21 @@ +# blake2s256() + +```ts +blake2s256(inputs): Uint8Array +``` + +Calculates the Blake2s256 hash of the input bytes + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `inputs` | `Uint8Array` | | + +## Returns + +`Uint8Array` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md b/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md new file mode 100644 index 00000000000..5e3cd53e9d3 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md @@ -0,0 +1,28 @@ +# ecdsa\_secp256k1\_verify() + +```ts +ecdsa_secp256k1_verify( + hashed_msg, + public_key_x_bytes, + public_key_y_bytes, + signature): boolean +``` + +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.30.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md b/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md new file mode 100644 index 00000000000..0b20ff68957 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md @@ -0,0 +1,28 @@ +# ecdsa\_secp256r1\_verify() + +```ts +ecdsa_secp256r1_verify( + hashed_msg, + public_key_x_bytes, + public_key_y_bytes, + signature): boolean +``` + +Verifies a ECDSA signature over the secp256r1 curve. + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `hashed_msg` | `Uint8Array` | | +| `public_key_x_bytes` | `Uint8Array` | | +| `public_key_y_bytes` | `Uint8Array` | | +| `signature` | `Uint8Array` | | + +## Returns + +`boolean` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/functions/keccak256.md b/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/functions/keccak256.md new file mode 100644 index 00000000000..d10f155ce86 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/functions/keccak256.md @@ -0,0 +1,21 @@ +# keccak256() + +```ts +keccak256(inputs): Uint8Array +``` + +Calculates the Keccak256 hash of the input bytes + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `inputs` | `Uint8Array` | | + +## Returns + +`Uint8Array` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/functions/sha256.md b/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/functions/sha256.md new file mode 100644 index 00000000000..6ba4ecac022 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/functions/sha256.md @@ -0,0 +1,21 @@ +# sha256() + +```ts +sha256(inputs): Uint8Array +``` + +Calculates the SHA256 hash of the input bytes + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `inputs` | `Uint8Array` | | + +## Returns + +`Uint8Array` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/functions/xor.md b/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/functions/xor.md new file mode 100644 index 00000000000..8d762b895d3 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/functions/xor.md @@ -0,0 +1,22 @@ +# xor() + +```ts +xor(lhs, rhs): string +``` + +Performs a bitwise XOR operation between `lhs` and `rhs` + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `lhs` | `string` | | +| `rhs` | `string` | | + +## Returns + +`string` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/index.md b/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/index.md new file mode 100644 index 00000000000..40bef8393fc --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/index.md @@ -0,0 +1,55 @@ +# noir_js + +## Exports + +### Classes + +| Class | Description | +| :------ | :------ | +| [Noir](classes/Noir.md) | - | + +### Type Aliases + +| Type alias | Description | +| :------ | :------ | +| [ErrorWithPayload](type-aliases/ErrorWithPayload.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) | - | +| [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) | Verifies a ECDSA signature over the secp256k1 curve. | +| [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` | + +## References + +### CompiledCircuit + +Renames and re-exports [InputMap](index.md#inputmap) + +*** + +### ProofData + +Renames and re-exports [InputMap](index.md#inputmap) + +## Variables + +### InputMap + +```ts +InputMap: any; +``` + +*** + +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.30.0/reference/NoirJS/noir_js/type-aliases/ErrorWithPayload.md b/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/type-aliases/ErrorWithPayload.md new file mode 100644 index 00000000000..e8c2f4aef3d --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/type-aliases/ErrorWithPayload.md @@ -0,0 +1,15 @@ +# ErrorWithPayload + +```ts +type ErrorWithPayload: ExecutionError & object; +``` + +## Type declaration + +| Member | Type | Description | +| :------ | :------ | :------ | +| `decodedAssertionPayload` | `any` | - | + +*** + +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.30.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md b/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md new file mode 100644 index 00000000000..812b8b16481 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md @@ -0,0 +1,24 @@ +# ForeignCallHandler + +```ts +type ForeignCallHandler: (name, inputs) => Promise; +``` + +A callback which performs an foreign call and returns the response. + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `name` | `string` | The identifier for the type of foreign call being performed. | +| `inputs` | [`ForeignCallInput`](ForeignCallInput.md)[] | An array of hex encoded inputs to the foreign call. | + +## Returns + +`Promise`\<[`ForeignCallOutput`](ForeignCallOutput.md)[]\> + +outputs - An array of hex encoded outputs containing the results of the foreign call. + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md b/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md new file mode 100644 index 00000000000..dd95809186a --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md @@ -0,0 +1,9 @@ +# ForeignCallInput + +```ts +type ForeignCallInput: string[]; +``` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md b/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md new file mode 100644 index 00000000000..b71fb78a946 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md @@ -0,0 +1,9 @@ +# ForeignCallOutput + +```ts +type ForeignCallOutput: string | string[]; +``` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md b/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md new file mode 100644 index 00000000000..258c46f9d0c --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md @@ -0,0 +1,9 @@ +# WitnessMap + +```ts +type WitnessMap: Map; +``` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs b/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs new file mode 100644 index 00000000000..b3156097df6 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs @@ -0,0 +1,4 @@ +// @ts-check +/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ +const typedocSidebar = { items: [{"type":"category","label":"Classes","items":[{"type":"doc","id":"reference/NoirJS/noir_js/classes/Noir","label":"Noir"}]},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ErrorWithPayload","label":"ErrorWithPayload"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ForeignCallHandler","label":"ForeignCallHandler"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ForeignCallInput","label":"ForeignCallInput"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ForeignCallOutput","label":"ForeignCallOutput"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/WitnessMap","label":"WitnessMap"}]},{"type":"category","label":"Functions","items":[{"type":"doc","id":"reference/NoirJS/noir_js/functions/and","label":"and"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/blake2s256","label":"blake2s256"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify","label":"ecdsa_secp256k1_verify"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify","label":"ecdsa_secp256r1_verify"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/keccak256","label":"keccak256"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/sha256","label":"sha256"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/xor","label":"xor"}]}]}; +module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_wasm/.nojekyll b/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_wasm/.nojekyll new file mode 100644 index 00000000000..e2ac6616add --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_wasm/.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.30.0/reference/NoirJS/noir_wasm/functions/compile.md b/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_wasm/functions/compile.md new file mode 100644 index 00000000000..6faf763b37f --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_wasm/functions/compile.md @@ -0,0 +1,51 @@ +# compile() + +```ts +compile( + fileManager, + projectPath?, + logFn?, +debugLogFn?): Promise +``` + +Compiles a Noir project + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `fileManager` | `FileManager` | The file manager to use | +| `projectPath`? | `string` | The path to the project inside the file manager. Defaults to the root of the file manager | +| `logFn`? | `LogFn` | A logging function. If not provided, console.log will be used | +| `debugLogFn`? | `LogFn` | A debug logging function. If not provided, logFn will be used | + +## Returns + +`Promise`\<[`ProgramCompilationArtifacts`](../index.md#programcompilationartifacts)\> + +## Example + +```typescript +// Node.js + +import { compile_program, createFileManager } from '@noir-lang/noir_wasm'; + +const fm = createFileManager(myProjectPath); +const myCompiledCode = await compile_program(fm); +``` + +```typescript +// Browser + +import { compile_program, createFileManager } from '@noir-lang/noir_wasm'; + +const fm = createFileManager('/'); +for (const path of files) { + await fm.writeFile(path, await getFileAsStream(path)); +} +const myCompiledCode = await compile_program(fm); +``` + +*** + +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.30.0/reference/NoirJS/noir_wasm/functions/compile_contract.md b/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_wasm/functions/compile_contract.md new file mode 100644 index 00000000000..7d0b39a43ef --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_wasm/functions/compile_contract.md @@ -0,0 +1,51 @@ +# compile\_contract() + +```ts +compile_contract( + fileManager, + projectPath?, + logFn?, +debugLogFn?): Promise +``` + +Compiles a Noir project + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `fileManager` | `FileManager` | The file manager to use | +| `projectPath`? | `string` | The path to the project inside the file manager. Defaults to the root of the file manager | +| `logFn`? | `LogFn` | A logging function. If not provided, console.log will be used | +| `debugLogFn`? | `LogFn` | A debug logging function. If not provided, logFn will be used | + +## Returns + +`Promise`\<[`ContractCompilationArtifacts`](../index.md#contractcompilationartifacts)\> + +## Example + +```typescript +// Node.js + +import { compile_contract, createFileManager } from '@noir-lang/noir_wasm'; + +const fm = createFileManager(myProjectPath); +const myCompiledCode = await compile_contract(fm); +``` + +```typescript +// Browser + +import { compile_contract, createFileManager } from '@noir-lang/noir_wasm'; + +const fm = createFileManager('/'); +for (const path of files) { + await fm.writeFile(path, await getFileAsStream(path)); +} +const myCompiledCode = await compile_contract(fm); +``` + +*** + +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.30.0/reference/NoirJS/noir_wasm/functions/createFileManager.md b/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_wasm/functions/createFileManager.md new file mode 100644 index 00000000000..7e65c1d69c7 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_wasm/functions/createFileManager.md @@ -0,0 +1,21 @@ +# createFileManager() + +```ts +createFileManager(dataDir): FileManager +``` + +Creates a new FileManager instance based on fs in node and memfs in the browser (via webpack alias) + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `dataDir` | `string` | root of the file system | + +## Returns + +`FileManager` + +*** + +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.30.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md b/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md new file mode 100644 index 00000000000..fcea9275341 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md @@ -0,0 +1,21 @@ +# inflateDebugSymbols() + +```ts +inflateDebugSymbols(debugSymbols): any +``` + +Decompresses and decodes the debug symbols + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `debugSymbols` | `string` | The base64 encoded debug symbols | + +## Returns + +`any` + +*** + +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.30.0/reference/NoirJS/noir_wasm/index.md b/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_wasm/index.md new file mode 100644 index 00000000000..b6e0f9d1bc0 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_wasm/index.md @@ -0,0 +1,49 @@ +# noir_wasm + +## Exports + +### Functions + +| Function | Description | +| :------ | :------ | +| [compile](functions/compile.md) | Compiles a Noir project | +| [compile\_contract](functions/compile_contract.md) | Compiles a Noir project | +| [createFileManager](functions/createFileManager.md) | Creates a new FileManager instance based on fs in node and memfs in the browser (via webpack alias) | +| [inflateDebugSymbols](functions/inflateDebugSymbols.md) | Decompresses and decodes the debug symbols | + +## References + +### compile\_program + +Renames and re-exports [compile](functions/compile.md) + +## Interfaces + +### ContractCompilationArtifacts + +The compilation artifacts of a given contract. + +#### Properties + +| Property | Type | Description | +| :------ | :------ | :------ | +| `contract` | `ContractArtifact` | The compiled contract. | +| `warnings` | `unknown`[] | Compilation warnings. | + +*** + +### ProgramCompilationArtifacts + +The compilation artifacts of a given program. + +#### Properties + +| Property | Type | Description | +| :------ | :------ | :------ | +| `name` | `string` | not part of the compilation output, injected later | +| `program` | `ProgramArtifact` | The compiled contract. | +| `warnings` | `unknown`[] | Compilation warnings. | + +*** + +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.30.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs b/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs new file mode 100644 index 00000000000..e0870710349 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs @@ -0,0 +1,4 @@ +// @ts-check +/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ +const typedocSidebar = { items: [{"type":"doc","id":"reference/NoirJS/noir_wasm/index","label":"API"},{"type":"category","label":"Functions","items":[{"type":"doc","id":"reference/NoirJS/noir_wasm/functions/compile","label":"compile"},{"type":"doc","id":"reference/NoirJS/noir_wasm/functions/compile_contract","label":"compile_contract"},{"type":"doc","id":"reference/NoirJS/noir_wasm/functions/createFileManager","label":"createFileManager"},{"type":"doc","id":"reference/NoirJS/noir_wasm/functions/inflateDebugSymbols","label":"inflateDebugSymbols"}]}]}; +module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.30.0/reference/_category_.json b/docs/versioned_docs/version-v0.30.0/reference/_category_.json new file mode 100644 index 00000000000..5b6a20a609a --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/reference/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 4, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.30.0/reference/debugger/_category_.json b/docs/versioned_docs/version-v0.30.0/reference/debugger/_category_.json new file mode 100644 index 00000000000..27869205ad3 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/reference/debugger/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Debugger", + "position": 1, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.30.0/reference/debugger/debugger_known_limitations.md b/docs/versioned_docs/version-v0.30.0/reference/debugger/debugger_known_limitations.md new file mode 100644 index 00000000000..936d416ac4b --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/reference/debugger/debugger_known_limitations.md @@ -0,0 +1,59 @@ +--- +title: Known limitations +description: + An overview of known limitations of the current version of the Noir debugger +keywords: + [ + Nargo, + Noir Debugger, + VS Code, + ] +sidebar_position: 2 +--- + +# Debugger Known Limitations + +There are currently some limits to what the debugger can observe. + +## Mutable references + +The debugger is currently blind to any state mutated via a mutable reference. For example, in: + +``` +let mut x = 1; +let y = &mut x; +*y = 2; +``` + +The update on `x` will not be observed by the debugger. That means, when running `vars` from the debugger REPL, or inspecting the _local variables_ pane in the VS Code debugger, `x` will appear with value 1 despite having executed `*y = 2;`. + +## Variables of type function or mutable references are opaque + +When inspecting variables, any variable of type `Function` or `MutableReference` will render its value as `<>` or `<>`. + +## Debugger instrumentation affects resulting ACIR + +In order to make the state of local variables observable, the debugger compiles Noir circuits interleaving foreign calls that track any mutations to them. While this works (except in the cases described above) and doesn't introduce any behavior changes, it does as a side effect produce bigger bytecode. In particular, when running the command `opcodes` on the REPL debugger, you will notice Unconstrained VM blocks that look like this: + +``` +... +5 BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [], q_c: 2 }), Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(2))], q_c: 0 })] + | outputs=[] + 5.0 | Mov { destination: RegisterIndex(2), source: RegisterIndex(0) } + 5.1 | Mov { destination: RegisterIndex(3), source: RegisterIndex(1) } + 5.2 | Const { destination: RegisterIndex(0), value: Value { inner: 0 } } + 5.3 | Const { destination: RegisterIndex(1), value: Value { inner: 0 } } + 5.4 | Mov { destination: RegisterIndex(2), source: RegisterIndex(2) } + 5.5 | Mov { destination: RegisterIndex(3), source: RegisterIndex(3) } + 5.6 | Call { location: 8 } + 5.7 | Stop + 5.8 | ForeignCall { function: "__debug_var_assign", destinations: [], inputs: [RegisterIndex(RegisterIndex(2)), RegisterIndex(RegisterIndex(3))] } +... +``` + +If you are interested in debugging/inspecting compiled ACIR without these synthetic changes, you can invoke the REPL debugger with the `--skip-instrumentation` flag or launch the VS Code debugger with the `skipConfiguration` property set to true in its launch configuration. You can find more details about those in the [Debugger REPL reference](debugger_repl.md) and the [VS Code Debugger reference](debugger_vscode.md). + +:::note +Skipping debugger instrumentation means you won't be able to inspect values of local variables. +::: + diff --git a/docs/versioned_docs/version-v0.30.0/reference/debugger/debugger_repl.md b/docs/versioned_docs/version-v0.30.0/reference/debugger/debugger_repl.md new file mode 100644 index 00000000000..46e2011304e --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/reference/debugger/debugger_repl.md @@ -0,0 +1,360 @@ +--- +title: REPL Debugger +description: + Noir Debugger REPL options and commands. +keywords: + [ + Nargo, + Noir CLI, + Noir Debugger, + REPL, + ] +sidebar_position: 1 +--- + +## Running the REPL debugger + +`nargo debug [OPTIONS] [WITNESS_NAME]` + +Runs the Noir REPL debugger. If a `WITNESS_NAME` is provided the debugger writes the resulting execution witness to a `WITNESS_NAME` 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 debug | +| `--print-acir` | Display the ACIR for compiled circuit | +| `--deny-warnings` | Treat all warnings as errors | +| `--silence-warnings` | Suppress warnings | +| `-h, --help` | Print help | + +None of these options are required. + +:::note +Since the debugger starts by compiling the target package, all Noir compiler options are also available. Check out the [compiler reference](../nargo_commands.md#nargo-compile) to learn more about the compiler options. +::: + +## REPL commands + +Once the debugger is running, it accepts the following commands. + +#### `help` (h) + +Displays the menu of available commands. + +``` +> help +Available commands: + + opcodes display ACIR opcodes + into step into to the next opcode + next step until a new source location is reached + out step until a new source location is reached + and the current stack frame is finished + break LOCATION:OpcodeLocation add a breakpoint at an opcode location + over step until a new source location is reached + without diving into function calls + restart restart the debugging session + delete LOCATION:OpcodeLocation delete breakpoint at an opcode location + witness show witness map + witness index:u32 display a single witness from the witness map + witness index:u32 value:String update a witness with the given value + memset index:usize value:String update a memory cell with the given + value + continue continue execution until the end of the + program + vars show variable values available at this point + in execution + stacktrace display the current stack trace + memory show memory (valid when executing unconstrained code) value + step step to the next ACIR opcode + +Other commands: + + help Show this help message + quit Quit repl + +``` + +### Stepping through programs + +#### `next` (n) + +Step until the next Noir source code location. While other commands, such as [`into`](#into-i) and [`step`](#step-s), allow for finer grained control of the program's execution at the opcode level, `next` is source code centric. For example: + +``` +3 ... +4 fn main(x: u32) { +5 assert(entry_point(x) == 2); +6 swap_entry_point(x, x + 1); +7 -> assert(deep_entry_point(x) == 4); +8 multiple_values_entry_point(x); +9 } +``` + + +Using `next` here would cause the debugger to jump to the definition of `deep_entry_point` (if available). + +If you want to step over `deep_entry_point` and go straight to line 8, use [the `over` command](#over) instead. + +#### `over` + +Step until the next source code location, without diving into function calls. For example: + +``` +3 ... +4 fn main(x: u32) { +5 assert(entry_point(x) == 2); +6 swap_entry_point(x, x + 1); +7 -> assert(deep_entry_point(x) == 4); +8 multiple_values_entry_point(x); +9 } +``` + + +Using `over` here would cause the debugger to execute until line 8 (`multiple_values_entry_point(x);`). + +If you want to step into `deep_entry_point` instead, use [the `next` command](#next-n). + +#### `out` + +Step until the end of the current function call. For example: + +``` + 3 ... + 4 fn main(x: u32) { + 5 assert(entry_point(x) == 2); + 6 swap_entry_point(x, x + 1); + 7 -> assert(deep_entry_point(x) == 4); + 8 multiple_values_entry_point(x); + 9 } + 10 + 11 unconstrained fn returns_multiple_values(x: u32) -> (u32, u32, u32, u32) { + 12 ... + ... + 55 + 56 unconstrained fn deep_entry_point(x: u32) -> u32 { + 57 -> level_1(x + 1) + 58 } + +``` + +Running `out` here will resume execution until line 8. + +#### `step` (s) + +Skips to the next ACIR code. A compiled Noir program is a sequence of ACIR opcodes. However, an unconstrained VM opcode denotes the start of an unconstrained code block, to be executed by the unconstrained VM. For example (redacted for brevity): + +``` +0 BLACKBOX::RANGE [(_0, num_bits: 32)] [ ] +1 -> BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(0))], q_c: 0 })] outputs=[Simple(Witness(1))] + 1.0 | Mov { destination: RegisterIndex(2), source: RegisterIndex(0) } + 1.1 | Const { destination: RegisterIndex(0), value: Value { inner: 0 } } + 1.2 | Const { destination: RegisterIndex(1), value: Value { inner: 0 } } + 1.3 | Mov { destination: RegisterIndex(2), source: RegisterIndex(2) } + 1.4 | Call { location: 7 } + ... + 1.43 | Return +2 EXPR [ (1, _1) -2 ] +``` + +The `->` here shows the debugger paused at an ACIR opcode: `BRILLIG`, at index 1, which denotes an unconstrained code block is about to start. + +Using the `step` command at this point would result in the debugger stopping at ACIR opcode 2, `EXPR`, skipping unconstrained computation steps. + +Use [the `into` command](#into-i) instead if you want to follow unconstrained computation step by step. + +#### `into` (i) + +Steps into the next opcode. A compiled Noir program is a sequence of ACIR opcodes. However, a BRILLIG opcode denotes the start of an unconstrained code block, to be executed by the unconstrained VM. For example (redacted for brevity): + +``` +0 BLACKBOX::RANGE [(_0, num_bits: 32)] [ ] +1 -> BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(0))], q_c: 0 })] outputs=[Simple(Witness(1))] + 1.0 | Mov { destination: RegisterIndex(2), source: RegisterIndex(0) } + 1.1 | Const { destination: RegisterIndex(0), value: Value { inner: 0 } } + 1.2 | Const { destination: RegisterIndex(1), value: Value { inner: 0 } } + 1.3 | Mov { destination: RegisterIndex(2), source: RegisterIndex(2) } + 1.4 | Call { location: 7 } + ... + 1.43 | Return +2 EXPR [ (1, _1) -2 ] +``` + +The `->` here shows the debugger paused at an ACIR opcode: `BRILLIG`, at index 1, which denotes an unconstrained code block is about to start. + +Using the `into` command at this point would result in the debugger stopping at opcode 1.0, `Mov ...`, allowing the debugger user to follow unconstrained computation step by step. + +Use [the `step` command](#step-s) instead if you want to skip to the next ACIR code directly. + +#### `continue` (c) + +Continues execution until the next breakpoint, or the end of the program. + +#### `restart` (res) + +Interrupts execution, and restarts a new debugging session from scratch. + +#### `opcodes` (o) + +Display the program's ACIR opcode sequence. For example: + +``` +0 BLACKBOX::RANGE [(_0, num_bits: 32)] [ ] +1 -> BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(0))], q_c: 0 })] outputs=[Simple(Witness(1))] + 1.0 | Mov { destination: RegisterIndex(2), source: RegisterIndex(0) } + 1.1 | Const { destination: RegisterIndex(0), value: Value { inner: 0 } } + 1.2 | Const { destination: RegisterIndex(1), value: Value { inner: 0 } } + 1.3 | Mov { destination: RegisterIndex(2), source: RegisterIndex(2) } + 1.4 | Call { location: 7 } + ... + 1.43 | Return +2 EXPR [ (1, _1) -2 ] +``` + +### Breakpoints + +#### `break [Opcode]` (or shorthand `b [Opcode]`) + +Sets a breakpoint on the specified opcode index. To get a list of the program opcode numbers, see [the `opcode` command](#opcodes-o). For example: + +``` +0 BLACKBOX::RANGE [(_0, num_bits: 32)] [ ] +1 -> BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(0))], q_c: 0 })] outputs=[Simple(Witness(1))] + 1.0 | Mov { destination: RegisterIndex(2), source: RegisterIndex(0) } + 1.1 | Const { destination: RegisterIndex(0), value: Value { inner: 0 } } + 1.2 | Const { destination: RegisterIndex(1), value: Value { inner: 0 } } + 1.3 | Mov { destination: RegisterIndex(2), source: RegisterIndex(2) } + 1.4 | Call { location: 7 } + ... + 1.43 | Return +2 EXPR [ (1, _1) -2 ] +``` + +In this example, issuing a `break 1.2` command adds break on opcode 1.2, as denoted by the `*` character: + +``` +0 BLACKBOX::RANGE [(_0, num_bits: 32)] [ ] +1 -> BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(0))], q_c: 0 })] outputs=[Simple(Witness(1))] + 1.0 | Mov { destination: RegisterIndex(2), source: RegisterIndex(0) } + 1.1 | Const { destination: RegisterIndex(0), value: Value { inner: 0 } } + 1.2 | * Const { destination: RegisterIndex(1), value: Value { inner: 0 } } + 1.3 | Mov { destination: RegisterIndex(2), source: RegisterIndex(2) } + 1.4 | Call { location: 7 } + ... + 1.43 | Return +2 EXPR [ (1, _1) -2 ] +``` + +Running [the `continue` command](#continue-c) at this point would cause the debugger to execute the program until opcode 1.2. + +#### `delete [Opcode]` (or shorthand `d [Opcode]`) + +Deletes a breakpoint at an opcode location. Usage is analogous to [the `break` command](#). + +### Variable inspection + +#### vars + +Show variable values available at this point in execution. + +:::note +The ability to inspect variable values from the debugger depends on compilation to be run in a special debug instrumentation mode. This instrumentation weaves variable tracing code with the original source code. + +So variable value inspection comes at the expense of making the resulting ACIR bytecode bigger and harder to understand and optimize. + +If you find this compromise unacceptable, you can run the debugger with the flag `--skip-debug-instrumentation`. This will compile your circuit without any additional debug information, so the resulting ACIR bytecode will be identical to the one produced by standard Noir compilation. However, if you opt for this, the `vars` command will not be available while debugging. +::: + + +### Stacktrace + +#### `stacktrace` + +Displays the current stack trace. + + +### Witness map + +#### `witness` (w) + +Show witness map. For example: + +``` +_0 = 0 +_1 = 2 +_2 = 1 +``` + +#### `witness [Witness Index]` + +Display a single witness from the witness map. For example: + +``` +> witness 1 +_1 = 2 +``` + +#### `witness [Witness Index] [New value]` + +Overwrite the given index with a new value. For example: + +``` +> witness 1 3 +_1 = 3 +``` + + +### Unconstrained VM memory + +#### `memory` + +Show unconstrained VM memory state. For example: + +``` +> memory +At opcode 1.13: Store { destination_pointer: RegisterIndex(0), source: RegisterIndex(3) } +... +> registers +0 = 0 +1 = 10 +2 = 0 +3 = 1 +4 = 1 +5 = 2³² +6 = 1 +> into +At opcode 1.14: Const { destination: RegisterIndex(5), value: Value { inner: 1 } } +... +> memory +0 = 1 +> +``` + +In the example above: we start with clean memory, then step through a `Store` opcode which stores the value of register 3 (1) into the memory address stored in register 0 (0). Thus now `memory` shows memory address 0 contains value 1. + +:::note +This command is only functional while the debugger is executing unconstrained code. +::: + +#### `memset [Memory address] [New value]` + +Update a memory cell with the given value. For example: + +``` +> memory +0 = 1 +> memset 0 2 +> memory +0 = 2 +> memset 1 4 +> memory +0 = 2 +1 = 4 +> +``` + +:::note +This command is only functional while the debugger is executing unconstrained code. +::: \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.30.0/reference/debugger/debugger_vscode.md b/docs/versioned_docs/version-v0.30.0/reference/debugger/debugger_vscode.md new file mode 100644 index 00000000000..c027332b3b0 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/reference/debugger/debugger_vscode.md @@ -0,0 +1,82 @@ +--- +title: VS Code Debugger +description: + VS Code Debugger configuration and features. +keywords: + [ + Nargo, + Noir CLI, + Noir Debugger, + VS Code, + IDE, + ] +sidebar_position: 0 +--- + +# VS Code Noir Debugger Reference + +The Noir debugger enabled by the vscode-noir extension ships with default settings such that the most common scenario should run without any additional configuration steps. + +These defaults can nevertheless be overridden by defining a launch configuration file. This page provides a reference for the properties you can override via a launch configuration file, as well as documenting the Nargo `dap` command, which is a dependency of the VS Code Noir debugger. + + +## Creating and editing launch configuration files + +To create a launch configuration file from VS Code, open the _debug pane_, and click on _create a launch.json file_. + +![Creating a launch configuration file](@site/static/img/debugger/ref1-create-launch.png) + +A `launch.json` file will be created, populated with basic defaults. + +### Noir Debugger launch.json properties + +#### projectFolder + +_String, optional._ + +Absolute path to the Nargo project to debug. By default, it is dynamically determined by looking for the nearest `Nargo.toml` file to the active file at the moment of launching the debugger. + +#### proverName + +_String, optional._ + +Name of the prover input to use. Defaults to `Prover`, which looks for a file named `Prover.toml` at the `projectFolder`. + +#### generateAcir + +_Boolean, optional._ + +If true, generate ACIR opcodes instead of unconstrained opcodes which will be closer to release binaries but less convenient for debugging. Defaults to `false`. + +#### skipInstrumentation + +_Boolean, optional._ + +Skips variables debugging instrumentation of code, making debugging less convenient but the resulting binary smaller and closer to production. Defaults to `false`. + +:::note +Skipping instrumentation causes the debugger to be unable to inspect local variables. +::: + +## `nargo dap [OPTIONS]` + +When run without any option flags, it starts the Nargo Debug Adapter Protocol server, which acts as the debugging backend for the VS Code Noir Debugger. + +All option flags are related to preflight checks. The Debug Adapter Protocol specifies how errors are to be informed from a running DAP server, but it doesn't specify mechanisms to communicate server initialization errors between the DAP server and its client IDE. + +Thus `nargo dap` ships with a _preflight check_ mode. If flag `--preflight-check` and the rest of the `--preflight-*` flags are provided, Nargo will run the same initialization routine except it will not start the DAP server. + +`vscode-noir` will then run `nargo dap` in preflight check mode first before a debugging session starts. If the preflight check ends in error, vscode-noir will present stderr and stdout output from this process through its own Output pane in VS Code. This makes it possible for users to diagnose what pieces of configuration might be wrong or missing in case of initialization errors. + +If the preflight check succeeds, `vscode-noir` proceeds to start the DAP server normally but running `nargo dap` without any additional flags. + +### Options + +| Option | Description | +| --------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- | +| `--preflight-check` | If present, dap runs in preflight check mode. | +| `--preflight-project-folder ` | Absolute path to the project to debug for preflight check. | +| `--preflight-prover-name ` | Name of prover file to use for preflight check | +| `--preflight-generate-acir` | Optional. If present, compile in ACIR mode while running preflight check. | +| `--preflight-skip-instrumentation` | Optional. If present, compile without introducing debug instrumentation while running preflight check. | +| `-h, --help` | Print help. | diff --git a/docs/versioned_docs/version-v0.30.0/reference/nargo_commands.md b/docs/versioned_docs/version-v0.30.0/reference/nargo_commands.md new file mode 100644 index 00000000000..519e3dbddc2 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/reference/nargo_commands.md @@ -0,0 +1,397 @@ +--- +title: Nargo +description: + Noir CLI Commands for Noir Prover and Verifier to create, execute, prove and verify programs, + generate Solidity verifier smart contract and compile into JSON file containing ACIR + representation and ABI of circuit. +keywords: + [ + Nargo, + Noir CLI, + Noir Prover, + Noir Verifier, + generate Solidity verifier, + compile JSON file, + ACIR representation, + ABI of circuit, + TypeScript, + ] +sidebar_position: 0 +--- + +# Command-Line Help for `nargo` + +This document contains the help content for the `nargo` command-line program. + +**Command Overview:** + +* [`nargo`↴](#nargo) +* [`nargo backend`↴](#nargo-backend) +* [`nargo backend current`↴](#nargo-backend-current) +* [`nargo backend ls`↴](#nargo-backend-ls) +* [`nargo backend use`↴](#nargo-backend-use) +* [`nargo backend install`↴](#nargo-backend-install) +* [`nargo backend uninstall`↴](#nargo-backend-uninstall) +* [`nargo check`↴](#nargo-check) +* [`nargo fmt`↴](#nargo-fmt) +* [`nargo codegen-verifier`↴](#nargo-codegen-verifier) +* [`nargo compile`↴](#nargo-compile) +* [`nargo new`↴](#nargo-new) +* [`nargo init`↴](#nargo-init) +* [`nargo execute`↴](#nargo-execute) +* [`nargo prove`↴](#nargo-prove) +* [`nargo verify`↴](#nargo-verify) +* [`nargo test`↴](#nargo-test) +* [`nargo info`↴](#nargo-info) +* [`nargo lsp`↴](#nargo-lsp) + +## `nargo` + +Noir's package manager + +**Usage:** `nargo ` + +###### **Subcommands:** + +* `backend` — Install and select custom backends used to generate and verify proofs +* `check` — Checks the constraint system for errors +* `fmt` — Format the Noir files in a workspace +* `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 Noir project in a new directory +* `init` — Create a Noir project in the current directory +* `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 +* `info` — Provides detailed information on each of a program's function (represented by a single circuit) +* `lsp` — Starts the Noir LSP server + +###### **Options:** + + + + +## `nargo backend` + +Install and select custom backends used to generate and verify proofs + +**Usage:** `nargo backend ` + +###### **Subcommands:** + +* `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 + + + +## `nargo backend current` + +Prints the name of the currently active backend + +**Usage:** `nargo backend current` + + + +## `nargo backend ls` + +Prints the list of currently installed backends + +**Usage:** `nargo backend ls` + + + +## `nargo backend use` + +Select the backend to use + +**Usage:** `nargo backend use ` + +###### **Arguments:** + +* `` + + + +## `nargo backend install` + +Install a new backend from a URL + +**Usage:** `nargo backend install ` + +###### **Arguments:** + +* `` — The name of the backend to install +* `` — The URL from which to download the backend + + + +## `nargo backend uninstall` + +Uninstalls a backend + +**Usage:** `nargo backend uninstall ` + +###### **Arguments:** + +* `` — The name of the backend to uninstall + + + +## `nargo check` + +Checks the constraint system for errors + +**Usage:** `nargo check [OPTIONS]` + +###### **Options:** + +* `--package ` — The name of the package to check +* `--workspace` — Check all packages in the workspace +* `--overwrite` — Force overwrite of existing files +* `--expression-width ` — Override the expression width requested by the backend + + Default value: `4` +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings + + + +## `nargo fmt` + +Format the Noir files in a workspace + +**Usage:** `nargo fmt [OPTIONS]` + +###### **Options:** + +* `--check` — Run noirfmt in check mode + + + +## `nargo codegen-verifier` + +Generates a Solidity verifier smart contract for the program + +**Usage:** `nargo codegen-verifier [OPTIONS]` + +###### **Options:** + +* `--package ` — The name of the package to codegen +* `--workspace` — Codegen all packages in the workspace +* `--expression-width ` — Override the expression width requested by the backend + + Default value: `4` +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings + + + +## `nargo compile` + +Compile the program and its secret execution trace into ACIR format + +**Usage:** `nargo compile [OPTIONS]` + +###### **Options:** + +* `--package ` — The name of the package to compile +* `--workspace` — Compile all packages in the workspace +* `--expression-width ` — Override the expression width requested by the backend + + Default value: `4` +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings + + + +## `nargo new` + +Create a Noir project in a new directory + +**Usage:** `nargo new [OPTIONS] ` + +###### **Arguments:** + +* `` — The path to save the new project + +###### **Options:** + +* `--name ` — Name of the package [default: package directory name] +* `--lib` — Use a library template +* `--bin` — Use a binary template [default] +* `--contract` — Use a contract template + + + +## `nargo init` + +Create a Noir project in the current directory + +**Usage:** `nargo init [OPTIONS]` + +###### **Options:** + +* `--name ` — Name of the package [default: current directory name] +* `--lib` — Use a library template +* `--bin` — Use a binary template [default] +* `--contract` — Use a contract template + + + +## `nargo execute` + +Executes a circuit to calculate its return value + +**Usage:** `nargo execute [OPTIONS] [WITNESS_NAME]` + +###### **Arguments:** + +* `` — Write the execution witness to named file + +###### **Options:** + +* `-p`, `--prover-name ` — The name of the toml file which contains the inputs for the prover + + Default value: `Prover` +* `--package ` — The name of the package to execute +* `--workspace` — Execute all packages in the workspace +* `--expression-width ` — Override the expression width requested by the backend + + Default value: `4` +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings +* `--oracle-resolver ` — JSON RPC url to solve oracle calls + + + +## `nargo prove` + +Create proof for this program. The proof is returned as a hex encoded string + +**Usage:** `nargo prove [OPTIONS]` + +###### **Options:** + +* `-p`, `--prover-name ` — The name of the toml file which contains the inputs for the prover + + Default value: `Prover` +* `-v`, `--verifier-name ` — The name of the toml file which contains the inputs for the verifier + + Default value: `Verifier` +* `--verify` — Verify proof after proving +* `--package ` — The name of the package to prove +* `--workspace` — Prove all packages in the workspace +* `--expression-width ` — Override the expression width requested by the backend + + Default value: `4` +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings +* `--oracle-resolver ` — JSON RPC url to solve oracle calls + + + +## `nargo verify` + +Given a proof and a program, verify whether the proof is valid + +**Usage:** `nargo verify [OPTIONS]` + +###### **Options:** + +* `-v`, `--verifier-name ` — The name of the toml file which contains the inputs for the verifier + + Default value: `Verifier` +* `--package ` — The name of the package verify +* `--workspace` — Verify all packages in the workspace +* `--expression-width ` — Override the expression width requested by the backend + + Default value: `4` +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings + + + +## `nargo test` + +Run the tests for this program + +**Usage:** `nargo test [OPTIONS] [TEST_NAME]` + +###### **Arguments:** + +* `` — If given, only tests with names containing this string will be run + +###### **Options:** + +* `--show-output` — Display output of `println` statements +* `--exact` — Only run tests that match exactly +* `--package ` — The name of the package to test +* `--workspace` — Test all packages in the workspace +* `--expression-width ` — Override the expression width requested by the backend + + Default value: `4` +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings +* `--oracle-resolver ` — JSON RPC url to solve oracle calls + + + +## `nargo info` + +Provides detailed information on each of a program's function (represented by a single circuit) + +Current information provided per circuit: 1. The number of ACIR opcodes 2. Counts the final number gates in the circuit used by a backend + +**Usage:** `nargo info [OPTIONS]` + +###### **Options:** + +* `--package ` — The name of the package to detail +* `--workspace` — Detail all packages in the workspace +* `--expression-width ` — Override the expression width requested by the backend + + Default value: `4` +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings + + + +## `nargo lsp` + +Starts the Noir LSP server + +Starts an LSP server which allows IDEs such as VS Code to display diagnostics in Noir source. + +VS Code Noir Language Support: https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir + +**Usage:** `nargo lsp` + + + +
+ + + This document was generated automatically by + clap-markdown. + + diff --git a/docs/versioned_docs/version-v0.30.0/tooling/debugger.md b/docs/versioned_docs/version-v0.30.0/tooling/debugger.md new file mode 100644 index 00000000000..184c436068f --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/tooling/debugger.md @@ -0,0 +1,27 @@ +--- +title: Debugger +description: Learn about the Noir Debugger, in its REPL or VS Code versions. +keywords: [Nargo, VSCode, Visual Studio Code, REPL, Debugger] +sidebar_position: 2 +--- + +# Noir Debugger + +There are currently two ways of debugging Noir programs: + +1. From VS 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). +2. Via the REPL debugger, which ships with Nargo. + +In order to use either version of the debugger, you will need to install recent enough versions of Noir, [Nargo](../getting_started/installation) and vscode-noir: + +- Noir 0.xx +- Nargo 0.xx +- vscode-noir 0.xx + +:::info +At the moment, the debugger supports debugging binary projects, but not contracts. +::: + +We cover the VS Code Noir debugger more in depth in [its VS Code debugger how-to guide](../how_to/debugger/debugging_with_vs_code.md) and [the reference](../reference/debugger/debugger_vscode.md). + +The REPL debugger is discussed at length in [the REPL debugger how-to guide](../how_to/debugger/debugging_with_the_repl.md) and [the reference](../reference/debugger/debugger_repl.md). diff --git a/docs/versioned_docs/version-v0.30.0/tooling/language_server.md b/docs/versioned_docs/version-v0.30.0/tooling/language_server.md new file mode 100644 index 00000000000..81e0356ef8a --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/tooling/language_server.md @@ -0,0 +1,43 @@ +--- +title: Language Server +description: Learn about the Noir Language Server, how to install the components, and configuration that may be required. +keywords: [Nargo, Language Server, LSP, VSCode, Visual Studio Code] +sidebar_position: 0 +--- + +This section helps you install and configure the Noir Language Server. + +The Language Server Protocol (LSP) has two components, the [Server](#language-server) and the [Client](#language-client). Below we describe each in the context of Noir. + +## Language Server + +The Server component is provided by the Nargo command line tool that you installed at the beginning of this guide. +As long as Nargo is installed and you've used it to run other commands in this guide, it should be good to go! + +If you'd like to verify that the `nargo lsp` command is available, you can run `nargo --help` and look for `lsp` in the list of commands. If you see it, you're using a version of Noir with LSP support. + +## Language Client + +The Client component is usually an editor plugin that launches the Server. It communicates LSP messages between the editor and the Server. For example, when you save a file, the Client will alert the Server, so it can try to compile the project and report any errors. + +Currently, Noir provides a Language Client for Visual Studio Code via the [vscode-noir](https://github.com/noir-lang/vscode-noir) extension. You can install it via the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir). + +> **Note:** Noir's Language Server Protocol support currently assumes users' VSCode workspace root to be the same as users' Noir project root (i.e. where Nargo.toml lies). +> +> If LSP features seem to be missing / malfunctioning, make sure you are opening your Noir project directly (instead of as a sub-folder) in your VSCode instance. + +When your language server is running correctly and the VSCode plugin is installed, you should see handy codelens buttons for compilation, measuring circuit size, execution, and tests: + +![Compile and Execute](@site/static/img/codelens_compile_execute.png) +![Run test](@site/static/img/codelens_run_test.png) + +You should also see your tests in the `testing` panel: + +![Testing panel](@site/static/img/codelens_testing_panel.png) + +### Configuration + +- **Noir: Enable LSP** - If checked, the extension will launch the Language Server via `nargo lsp` and communicate with it. +- **Noir: Nargo Flags** - Additional flags may be specified if you require them to be added when the extension calls `nargo lsp`. +- **Noir: Nargo Path** - An absolute path to a Nargo binary with the `lsp` command. This may be useful if Nargo is not within the `PATH` of your editor. +- **Noir > Trace: Server** - Setting this to `"messages"` or `"verbose"` will log LSP messages between the Client and Server. Useful for debugging. diff --git a/docs/versioned_docs/version-v0.30.0/tooling/testing.md b/docs/versioned_docs/version-v0.30.0/tooling/testing.md new file mode 100644 index 00000000000..d3e0c522473 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/tooling/testing.md @@ -0,0 +1,62 @@ +--- +title: Testing in Noir +description: Learn how to use Nargo to test your Noir program in a quick and easy way +keywords: [Nargo, testing, Noir, compile, test] +sidebar_position: 1 +--- + +You can test your Noir programs using Noir circuits. + +Nargo will automatically compile and run any functions which have the decorator `#[test]` on them if +you run `nargo test`. + +For example if you have a program like: + +```rust +fn add(x: u64, y: u64) -> u64 { + x + y +} +#[test] +fn test_add() { + assert(add(2,2) == 4); + assert(add(0,1) == 1); + assert(add(1,0) == 1); +} +``` + +Running `nargo test` will test that the `test_add` function can be executed while satisfying all +the constraints 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.30.0/tutorials/noirjs_app.md b/docs/versioned_docs/version-v0.30.0/tutorials/noirjs_app.md new file mode 100644 index 00000000000..3dd9fe7d2b0 --- /dev/null +++ b/docs/versioned_docs/version-v0.30.0/tutorials/noirjs_app.md @@ -0,0 +1,326 @@ +--- +title: Building a web app with NoirJS +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, app] +sidebar_position: 0 +pagination_next: noir/concepts/data_types/index +--- + +NoirJS is a set of packages meant to work both in a browser and a server environment. In this tutorial, we will build a simple web app using them. From here, you should get an idea on how to proceed with your own Noir projects! + +You can find the complete app code for this guide [here](https://github.com/noir-lang/tiny-noirjs-app). + +## Setup + +:::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.27.x matches `noir_js@0.27.x`, etc. + +In this guide, we will be pinned to 0.27.0. + +::: + +Before we start, we want to make sure we have Node and Nargo installed. + +We start by opening a terminal and executing `node --version`. If we don't get an output like `v20.10.0`, that means node is not installed. Let's do that by following the handy [nvm guide](https://github.com/nvm-sh/nvm?tab=readme-ov-file#install--update-script). + +As for `Nargo`, we can follow the [Nargo guide](../getting_started/installation/index.md) to install it. If you're lazy, just paste this on a terminal and run `noirup`: + +```sh +curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash +``` + +Easy enough. Onwards! + +## Our project + +ZK is a powerful technology. An app that doesn't reveal one of the inputs to _anyone_ is almost unbelievable, yet Noir makes it as easy as a single line of code. + +In fact, it's so simple that it comes nicely packaged in `nargo`. Let's do that! + +### Nargo + +Run: + +`nargo new circuit` + +And... That's about it. Your program is ready to be compiled and run. + +To compile, let's `cd` into the `circuit` folder to enter our project, and call: + +`nargo compile` + +This compiles our circuit into `json` format and add it to a new `target` folder. + +:::info + +At this point in the tutorial, your folder structure should look like this: + +```tree +. +└── circuit <---- our working directory + ├── Nargo.toml + ├── src + │ └── main.nr + └── target + └── circuit.json +``` + +::: + +### Node and Vite + +If you want to explore Nargo, feel free to go on a side-quest now and follow the steps in the +[getting started](../getting_started/hello_noir/index.md) guide. However, we want our app to run on the browser, so we need Vite. + +Vite is a powerful tool to generate static websites. While it provides all kinds of features, let's just go barebones with some good old vanilla JS. + +To do this this, go back to the previous folder (`cd ..`) and create a new vite project by running `npm create vite` and choosing "Vanilla" and "Javascript". + +A wild `vite-project` directory should now appear in your root folder! Let's not waste any time and dive right in: + +```bash +cd vite-project +``` + +### Setting Up Vite and Configuring the Project + +Before we proceed with any coding, let's get our environment tailored for Noir. We'll start by laying down the foundations with a `vite.config.js` file. This little piece of configuration is our secret sauce for making sure everything meshes well with the NoirJS libraries and other special setups we might need, like handling WebAssembly modules. Here’s how you get that going: + +#### Creating the vite.config.js + +In your freshly minted `vite-project` folder, create a new file named `vite.config.js` and open it in your code editor. Paste the following to set the stage: + +```javascript +import { defineConfig } from "vite"; +import copy from "rollup-plugin-copy"; + +export default defineConfig({ + esbuild: { + target: "esnext", + }, + optimizeDeps: { + esbuildOptions: { + target: "esnext", + }, + }, + plugins: [ + copy({ + targets: [ + { src: "node_modules/**/*.wasm", dest: "node_modules/.vite/dist" }, + ], + copySync: true, + hook: "buildStart", + }), + ], + server: { + port: 3000, + }, +}); +``` + +#### Install Dependencies + +Now that our stage is set, install the necessary NoirJS packages along with our other dependencies: + +```bash +npm install && npm install @noir-lang/backend_barretenberg@0.27.0 @noir-lang/noir_js@0.27.0 +npm install rollup-plugin-copy --save-dev +``` + +:::info + +At this point in the tutorial, your folder structure should look like this: + +```tree +. +└── circuit + └── ...etc... +└── vite-project <---- our working directory + └── ...etc... +``` + +::: + +#### Some cleanup + +`npx create vite` is amazing but it creates a bunch of files we don't really need for our simple example. Actually, let's just delete everything except for `vite.config.js`, `index.html`, `main.js` and `package.json`. I feel lighter already. + +![my heart is ready for you, noir.js](@site/static/img/memes/titanic.jpeg) + +## HTML + +Our app won't run like this, of course. We need some working HTML, at least. Let's open our broken-hearted `index.html` and replace everything with this code snippet: + +```html + + + + + + +

Noir app

+
+ + +
+
+

Logs

+

Proof

+
+ + +``` + +It _could_ be a beautiful UI... Depending on which universe you live in. + +## Some good old vanilla Javascript + +Our love for Noir needs undivided attention, so let's just open `main.js` and delete everything (this is where the romantic scenery becomes a bit creepy). + +Start by pasting in this boilerplate code: + +```js +const setup = async () => { + await Promise.all([ + import('@noir-lang/noirc_abi').then((module) => + module.default(new URL('@noir-lang/noirc_abi/web/noirc_abi_wasm_bg.wasm', import.meta.url).toString()), + ), + import('@noir-lang/acvm_js').then((module) => + module.default(new URL('@noir-lang/acvm_js/web/acvm_js_bg.wasm', import.meta.url).toString()), + ), + ]); +}; + +function display(container, msg) { + const c = document.getElementById(container); + const p = document.createElement('p'); + p.textContent = msg; + c.appendChild(p); +} + +document.getElementById('submitGuess').addEventListener('click', async () => { + try { + // here's where love happens + } catch (err) { + display('logs', 'Oh 💔 Wrong guess'); + } +}); +``` + +The display function doesn't do much. We're simply manipulating our website to see stuff happening. For example, if the proof fails, it will simply log a broken heart 😢 + +As for the `setup` function, it's just a sad reminder that dealing with `wasm` on the browser is not as easy as it should. Just copy, paste, and forget. + +:::info + +At this point in the tutorial, your folder structure should look like this: + +```tree +. +└── circuit + └── ...same as above +└── vite-project + ├── vite.config.js + ├── main.js + ├── package.json + └── index.html +``` + +You'll see other files and folders showing up (like `package-lock.json`, `node_modules`) but you shouldn't have to care about those. + +::: + +## Some NoirJS + +We're starting with the good stuff now. If you've compiled the circuit as described above, you should have a `json` file we want to import at the very top of our `main.js` file: + +```ts +import circuit from '../circuit/target/circuit.json'; +``` + +[Noir is backend-agnostic](../index.mdx#whats-new-about-noir). We write Noir, but we also need a proving backend. That's why we need to import and instantiate the two dependencies we installed above: `BarretenbergBackend` and `Noir`. Let's import them right below: + +```js +import { BarretenbergBackend, BarretenbergVerifier as Verifier } from '@noir-lang/backend_barretenberg'; +import { Noir } from '@noir-lang/noir_js'; +``` + +And instantiate them inside our try-catch block: + +```ts +// try { +const backend = new BarretenbergBackend(circuit); +const noir = new Noir(circuit, backend); +// } +``` + +:::note + +For the remainder of the tutorial, everything will be happening inside the `try` block + +::: + +## Our app + +Now for the app itself. We're capturing whatever is in the input when people press the submit button. Just add this: + +```js +const x = parseInt(document.getElementById('guessInput').value); +const input = { x, y: 2 }; +``` + +Now we're ready to prove stuff! Let's feed some inputs to our circuit and calculate the proof: + +```js +await setup(); // let's squeeze our wasm inits here + +display('logs', 'Generating proof... ⌛'); +const proof = await noir.generateProof(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 run dev`. If it doesn't open a browser for you, just visit `localhost:5173`. You should now see the worst UI ever, with an ugly input. + +![Getting Started 0](@site/static/img/noir_getting_started_1.png) + +Now, our circuit says `fn main(x: Field, y: pub Field)`. This means only the `y` value is public, and it's hardcoded above: `input = { x, y: 2 }`. In other words, you won't need to send your secret`x` to the verifier! + +By inputting any number other than 2 in the input box and clicking "submit", you should get a valid proof. Otherwise the proof won't even generate correctly. By the way, if you're human, you shouldn't be able to understand anything on the "proof" box. That's OK. We like you, human ❤️. + +## Verifying + +Time to celebrate, yes! But we shouldn't trust machines so blindly. Let's add these lines to see our proof being verified: + +```js +display('logs', 'Verifying proof... ⌛'); +const verificationKey = await backend.getVerificationKey(); +const verifier = new Verifier(); +const isValid = await verifier.verifyProof(proof, verificationKey); +if (isValid) display('logs', 'Verifying proof... ✅'); +``` + +You have successfully generated a client-side Noir web app! + +![coded app without math knowledge](@site/static/img/memes/flextape.jpeg) + +## 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/vite-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_sidebars/version-v0.25.0-sidebars.json b/docs/versioned_sidebars/version-v0.25.0-sidebars.json new file mode 100644 index 00000000000..b16f79cc176 --- /dev/null +++ b/docs/versioned_sidebars/version-v0.25.0-sidebars.json @@ -0,0 +1,83 @@ +{ + "sidebar": [ + { + "type": "doc", + "id": "index" + }, + { + "type": "category", + "label": "Getting Started", + "items": [ + { + "type": "autogenerated", + "dirName": "getting_started" + } + ] + }, + { + "type": "category", + "label": "The Noir Language", + "items": [ + { + "type": "autogenerated", + "dirName": "noir" + } + ] + }, + { + "type": "html", + "value": "
", + "defaultStyle": true + }, + { + "type": "category", + "label": "How To Guides", + "items": [ + { + "type": "autogenerated", + "dirName": "how_to" + } + ] + }, + { + "type": "category", + "label": "Explainers", + "items": [ + { + "type": "autogenerated", + "dirName": "explainers" + } + ] + }, + { + "type": "category", + "label": "Tutorials", + "items": [ + { + "type": "autogenerated", + "dirName": "tutorials" + } + ] + }, + { + "type": "category", + "label": "Reference", + "items": [ + { + "type": "autogenerated", + "dirName": "reference" + } + ] + }, + { + "type": "html", + "value": "
", + "defaultStyle": true + }, + { + "type": "doc", + "id": "migration_notes", + "label": "Migration notes" + } + ] +} diff --git a/docs/versioned_sidebars/version-v0.26.0-sidebars.json b/docs/versioned_sidebars/version-v0.26.0-sidebars.json new file mode 100644 index 00000000000..b16f79cc176 --- /dev/null +++ b/docs/versioned_sidebars/version-v0.26.0-sidebars.json @@ -0,0 +1,83 @@ +{ + "sidebar": [ + { + "type": "doc", + "id": "index" + }, + { + "type": "category", + "label": "Getting Started", + "items": [ + { + "type": "autogenerated", + "dirName": "getting_started" + } + ] + }, + { + "type": "category", + "label": "The Noir Language", + "items": [ + { + "type": "autogenerated", + "dirName": "noir" + } + ] + }, + { + "type": "html", + "value": "
", + "defaultStyle": true + }, + { + "type": "category", + "label": "How To Guides", + "items": [ + { + "type": "autogenerated", + "dirName": "how_to" + } + ] + }, + { + "type": "category", + "label": "Explainers", + "items": [ + { + "type": "autogenerated", + "dirName": "explainers" + } + ] + }, + { + "type": "category", + "label": "Tutorials", + "items": [ + { + "type": "autogenerated", + "dirName": "tutorials" + } + ] + }, + { + "type": "category", + "label": "Reference", + "items": [ + { + "type": "autogenerated", + "dirName": "reference" + } + ] + }, + { + "type": "html", + "value": "
", + "defaultStyle": true + }, + { + "type": "doc", + "id": "migration_notes", + "label": "Migration notes" + } + ] +} diff --git a/docs/versioned_sidebars/version-v0.27.0-sidebars.json b/docs/versioned_sidebars/version-v0.27.0-sidebars.json new file mode 100644 index 00000000000..b16f79cc176 --- /dev/null +++ b/docs/versioned_sidebars/version-v0.27.0-sidebars.json @@ -0,0 +1,83 @@ +{ + "sidebar": [ + { + "type": "doc", + "id": "index" + }, + { + "type": "category", + "label": "Getting Started", + "items": [ + { + "type": "autogenerated", + "dirName": "getting_started" + } + ] + }, + { + "type": "category", + "label": "The Noir Language", + "items": [ + { + "type": "autogenerated", + "dirName": "noir" + } + ] + }, + { + "type": "html", + "value": "
", + "defaultStyle": true + }, + { + "type": "category", + "label": "How To Guides", + "items": [ + { + "type": "autogenerated", + "dirName": "how_to" + } + ] + }, + { + "type": "category", + "label": "Explainers", + "items": [ + { + "type": "autogenerated", + "dirName": "explainers" + } + ] + }, + { + "type": "category", + "label": "Tutorials", + "items": [ + { + "type": "autogenerated", + "dirName": "tutorials" + } + ] + }, + { + "type": "category", + "label": "Reference", + "items": [ + { + "type": "autogenerated", + "dirName": "reference" + } + ] + }, + { + "type": "html", + "value": "
", + "defaultStyle": true + }, + { + "type": "doc", + "id": "migration_notes", + "label": "Migration notes" + } + ] +} diff --git a/docs/versioned_sidebars/version-v0.28.0-sidebars.json b/docs/versioned_sidebars/version-v0.28.0-sidebars.json new file mode 100644 index 00000000000..b9ad026f69f --- /dev/null +++ b/docs/versioned_sidebars/version-v0.28.0-sidebars.json @@ -0,0 +1,93 @@ +{ + "sidebar": [ + { + "type": "doc", + "id": "index" + }, + { + "type": "category", + "label": "Getting Started", + "items": [ + { + "type": "autogenerated", + "dirName": "getting_started" + } + ] + }, + { + "type": "category", + "label": "The Noir Language", + "items": [ + { + "type": "autogenerated", + "dirName": "noir" + } + ] + }, + { + "type": "html", + "value": "
", + "defaultStyle": true + }, + { + "type": "category", + "label": "How To Guides", + "items": [ + { + "type": "autogenerated", + "dirName": "how_to" + } + ] + }, + { + "type": "category", + "label": "Explainers", + "items": [ + { + "type": "autogenerated", + "dirName": "explainers" + } + ] + }, + { + "type": "category", + "label": "Tutorials", + "items": [ + { + "type": "autogenerated", + "dirName": "tutorials" + } + ] + }, + { + "type": "category", + "label": "Reference", + "items": [ + { + "type": "autogenerated", + "dirName": "reference" + } + ] + }, + { + "type": "category", + "label": "Tooling", + "items": [ + { + "type": "autogenerated", + "dirName": "tooling" + } + ] + }, + { + "type": "html", + "value": "
", + "defaultStyle": true + }, + { + "type": "doc", + "id": "migration_notes", + "label": "Migration notes" + } + ] +} diff --git a/docs/versioned_sidebars/version-v0.29.0-sidebars.json b/docs/versioned_sidebars/version-v0.29.0-sidebars.json new file mode 100644 index 00000000000..b9ad026f69f --- /dev/null +++ b/docs/versioned_sidebars/version-v0.29.0-sidebars.json @@ -0,0 +1,93 @@ +{ + "sidebar": [ + { + "type": "doc", + "id": "index" + }, + { + "type": "category", + "label": "Getting Started", + "items": [ + { + "type": "autogenerated", + "dirName": "getting_started" + } + ] + }, + { + "type": "category", + "label": "The Noir Language", + "items": [ + { + "type": "autogenerated", + "dirName": "noir" + } + ] + }, + { + "type": "html", + "value": "
", + "defaultStyle": true + }, + { + "type": "category", + "label": "How To Guides", + "items": [ + { + "type": "autogenerated", + "dirName": "how_to" + } + ] + }, + { + "type": "category", + "label": "Explainers", + "items": [ + { + "type": "autogenerated", + "dirName": "explainers" + } + ] + }, + { + "type": "category", + "label": "Tutorials", + "items": [ + { + "type": "autogenerated", + "dirName": "tutorials" + } + ] + }, + { + "type": "category", + "label": "Reference", + "items": [ + { + "type": "autogenerated", + "dirName": "reference" + } + ] + }, + { + "type": "category", + "label": "Tooling", + "items": [ + { + "type": "autogenerated", + "dirName": "tooling" + } + ] + }, + { + "type": "html", + "value": "
", + "defaultStyle": true + }, + { + "type": "doc", + "id": "migration_notes", + "label": "Migration notes" + } + ] +} diff --git a/docs/versioned_sidebars/version-v0.30.0-sidebars.json b/docs/versioned_sidebars/version-v0.30.0-sidebars.json new file mode 100644 index 00000000000..b9ad026f69f --- /dev/null +++ b/docs/versioned_sidebars/version-v0.30.0-sidebars.json @@ -0,0 +1,93 @@ +{ + "sidebar": [ + { + "type": "doc", + "id": "index" + }, + { + "type": "category", + "label": "Getting Started", + "items": [ + { + "type": "autogenerated", + "dirName": "getting_started" + } + ] + }, + { + "type": "category", + "label": "The Noir Language", + "items": [ + { + "type": "autogenerated", + "dirName": "noir" + } + ] + }, + { + "type": "html", + "value": "
", + "defaultStyle": true + }, + { + "type": "category", + "label": "How To Guides", + "items": [ + { + "type": "autogenerated", + "dirName": "how_to" + } + ] + }, + { + "type": "category", + "label": "Explainers", + "items": [ + { + "type": "autogenerated", + "dirName": "explainers" + } + ] + }, + { + "type": "category", + "label": "Tutorials", + "items": [ + { + "type": "autogenerated", + "dirName": "tutorials" + } + ] + }, + { + "type": "category", + "label": "Reference", + "items": [ + { + "type": "autogenerated", + "dirName": "reference" + } + ] + }, + { + "type": "category", + "label": "Tooling", + "items": [ + { + "type": "autogenerated", + "dirName": "tooling" + } + ] + }, + { + "type": "html", + "value": "
", + "defaultStyle": true + }, + { + "type": "doc", + "id": "migration_notes", + "label": "Migration notes" + } + ] +} diff --git a/examples/codegen_verifier/.gitignore b/examples/codegen_verifier/.gitignore new file mode 100644 index 00000000000..c0d62c447d3 --- /dev/null +++ b/examples/codegen_verifier/.gitignore @@ -0,0 +1,4 @@ +out +cache +target +src/contract.sol \ No newline at end of file diff --git a/examples/codegen_verifier/Nargo.toml b/examples/codegen_verifier/Nargo.toml new file mode 100644 index 00000000000..2b367f30dbc --- /dev/null +++ b/examples/codegen_verifier/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "hello_world" +type = "bin" +authors = [""] +compiler_version = ">=0.29.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/orphaned_trait_impl/Prover.toml b/examples/codegen_verifier/Prover.toml similarity index 100% rename from test_programs/compile_failure/orphaned_trait_impl/Prover.toml rename to examples/codegen_verifier/Prover.toml diff --git a/examples/codegen_verifier/codegen_verifier.sh b/examples/codegen_verifier/codegen_verifier.sh new file mode 100755 index 00000000000..fabd6235a67 --- /dev/null +++ b/examples/codegen_verifier/codegen_verifier.sh @@ -0,0 +1,38 @@ +#!/bin/bash +set -eu + +BACKEND=${BACKEND:-bb} + +nargo compile + +# TODO: backend should automatically generate vk if necessary. +$BACKEND write_vk -b ./target/hello_world.json +$BACKEND contract -o ./src/contract.sol + +# We now generate a proof and check whether the verifier contract will verify it. + +nargo execute witness + +PROOF_PATH=./target/proof +$BACKEND prove -b ./target/hello_world.json -w ./target/witness.gz -o $PROOF_PATH + +NUM_PUBLIC_INPUTS=1 +PUBLIC_INPUT_BYTES=$((32 * $NUM_PUBLIC_INPUTS)) +HEX_PUBLIC_INPUTS=$(head -c $PUBLIC_INPUT_BYTES $PROOF_PATH | od -An -v -t x1 | tr -d $' \n') +HEX_PROOF=$(tail -c +$(($PUBLIC_INPUT_BYTES + 1)) $PROOF_PATH | od -An -v -t x1 | tr -d $' \n') + +# Spin up an anvil node to deploy the contract to +anvil & + +DEPLOY_INFO=$(forge create UltraVerifier \ + --rpc-url "127.0.0.1:8545" \ + --private-key "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" \ + --json) +VERIFIER_ADDRESS=$(echo $DEPLOY_INFO | jq -r '.deployedTo') + +# Call the verifier contract with our proof. +# Note that we haven't needed to split up `HEX_PUBLIC_INPUTS` as there's only a single public input +cast call $VERIFIER_ADDRESS "verify(bytes, bytes32[])(bool)" "0x$HEX_PROOF" "[0x$HEX_PUBLIC_INPUTS]" + +# Stop anvil node again +kill %- \ No newline at end of file diff --git a/examples/codegen_verifier/foundry.toml b/examples/codegen_verifier/foundry.toml new file mode 100644 index 00000000000..25b918f9c9a --- /dev/null +++ b/examples/codegen_verifier/foundry.toml @@ -0,0 +1,6 @@ +[profile.default] +src = "src" +out = "out" +libs = ["lib"] + +# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options diff --git a/examples/codegen_verifier/src/main.nr b/examples/codegen_verifier/src/main.nr new file mode 100644 index 00000000000..baef0c3786a --- /dev/null +++ b/examples/codegen_verifier/src/main.nr @@ -0,0 +1,3 @@ +fn main(x: Field, y: pub Field) { + assert(x != y); +} \ No newline at end of file diff --git a/examples/codegen_verifier/test.sh b/examples/codegen_verifier/test.sh new file mode 100755 index 00000000000..93c2f6edf51 --- /dev/null +++ b/examples/codegen_verifier/test.sh @@ -0,0 +1,15 @@ +#!/bin/bash +set -eu + +# This file is used for Noir CI and is not required. + +BACKEND=${BACKEND:-bb} + +rm -f ./src/contract.sol + +./codegen_verifier.sh + +if ! [ -f ./src/contract.sol ]; then + printf '%s\n' "Contract not written to file" >&2 + exit 1 +fi \ No newline at end of file diff --git a/examples/prove_and_verify/Nargo.toml b/examples/prove_and_verify/Nargo.toml new file mode 100644 index 00000000000..2b367f30dbc --- /dev/null +++ b/examples/prove_and_verify/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "hello_world" +type = "bin" +authors = [""] +compiler_version = ">=0.29.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/workspace_missing_toml/crates/a/Prover.toml b/examples/prove_and_verify/Prover.toml similarity index 50% rename from test_programs/compile_failure/workspace_missing_toml/crates/a/Prover.toml rename to examples/prove_and_verify/Prover.toml index 465ef562de4..8c12ebba6cf 100644 --- a/test_programs/compile_failure/workspace_missing_toml/crates/a/Prover.toml +++ b/examples/prove_and_verify/Prover.toml @@ -1,2 +1,2 @@ x = "1" -y = "1" +y = "2" diff --git a/examples/prove_and_verify/proofs/proof b/examples/prove_and_verify/proofs/proof new file mode 100644 index 00000000000..01d5ad27686 Binary files /dev/null and b/examples/prove_and_verify/proofs/proof differ diff --git a/examples/prove_and_verify/prove_and_verify.sh b/examples/prove_and_verify/prove_and_verify.sh new file mode 100755 index 00000000000..01ee6c70738 --- /dev/null +++ b/examples/prove_and_verify/prove_and_verify.sh @@ -0,0 +1,14 @@ +#!/bin/bash +set -eu + +BACKEND=${BACKEND:-bb} + +nargo execute witness + +# TODO: `bb` should create `proofs` directory if it doesn't exist. +mkdir -p proofs +$BACKEND prove -b ./target/hello_world.json -w ./target/witness.gz + +# TODO: backend should automatically generate vk if necessary. +$BACKEND write_vk -b ./target/hello_world.json +$BACKEND verify -v ./target/vk -p ./proofs/proof \ No newline at end of file diff --git a/examples/prove_and_verify/src/main.nr b/examples/prove_and_verify/src/main.nr new file mode 100644 index 00000000000..baef0c3786a --- /dev/null +++ b/examples/prove_and_verify/src/main.nr @@ -0,0 +1,3 @@ +fn main(x: Field, y: pub Field) { + assert(x != y); +} \ No newline at end of file diff --git a/examples/prove_and_verify/test.sh b/examples/prove_and_verify/test.sh new file mode 100755 index 00000000000..a8ae3cca132 --- /dev/null +++ b/examples/prove_and_verify/test.sh @@ -0,0 +1,10 @@ +#!/bin/bash +set -eu + +# This file is used for Noir CI and is not required. + +BACKEND=${BACKEND:-bb} + +rm -rf ./target ./proofs + +./prove_and_verify.sh \ No newline at end of file diff --git a/flake.lock b/flake.lock deleted file mode 100644 index 5a9f9470a1f..00000000000 --- a/flake.lock +++ /dev/null @@ -1,170 +0,0 @@ -{ - "nodes": { - "crane": { - "inputs": { - "flake-compat": [ - "flake-compat" - ], - "flake-utils": [ - "flake-utils" - ], - "nixpkgs": [ - "nixpkgs" - ], - "rust-overlay": "rust-overlay" - }, - "locked": { - "lastModified": 1681177078, - "narHash": "sha256-ZNIjBDou2GOabcpctiQykEQVkI8BDwk7TyvlWlI4myE=", - "owner": "ipetkov", - "repo": "crane", - "rev": "0c9f468ff00576577d83f5019a66c557ede5acf6", - "type": "github" - }, - "original": { - "owner": "ipetkov", - "repo": "crane", - "type": "github" - } - }, - "fenix": { - "inputs": { - "nixpkgs": [ - "nixpkgs" - ], - "rust-analyzer-src": "rust-analyzer-src" - }, - "locked": { - "lastModified": 1694499657, - "narHash": "sha256-u/fZtLtN7VcDrMMVrdsFy93PEkaiK+tNpJT9on4SGdU=", - "owner": "nix-community", - "repo": "fenix", - "rev": "2895ff377cbb3cb6f5dd92066734b0447cb04e20", - "type": "github" - }, - "original": { - "owner": "nix-community", - "repo": "fenix", - "type": "github" - } - }, - "flake-compat": { - "flake": false, - "locked": { - "lastModified": 1673956053, - "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", - "type": "github" - }, - "original": { - "owner": "edolstra", - "repo": "flake-compat", - "type": "github" - } - }, - "flake-utils": { - "inputs": { - "systems": "systems" - }, - "locked": { - "lastModified": 1681202837, - "narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "cfacdce06f30d2b68473a46042957675eebb3401", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, - "nixpkgs": { - "locked": { - "lastModified": 1695559356, - "narHash": "sha256-kXZ1pUoImD9OEbPCwpTz4tHsNTr4CIyIfXb3ocuR8sI=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "261abe8a44a7e8392598d038d2e01f7b33cf26d0", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixos-23.05", - "repo": "nixpkgs", - "type": "github" - } - }, - "root": { - "inputs": { - "crane": "crane", - "fenix": "fenix", - "flake-compat": "flake-compat", - "flake-utils": "flake-utils", - "nixpkgs": "nixpkgs" - } - }, - "rust-analyzer-src": { - "flake": false, - "locked": { - "lastModified": 1694421477, - "narHash": "sha256-df6YZzR57VFzkOPwIohJfC0fRwgq6yUPbMJkKAtQyAE=", - "owner": "rust-lang", - "repo": "rust-analyzer", - "rev": "cc6c8209cbaf7df55013977cf5cc8488d6b7ff1c", - "type": "github" - }, - "original": { - "owner": "rust-lang", - "ref": "nightly", - "repo": "rust-analyzer", - "type": "github" - } - }, - "rust-overlay": { - "inputs": { - "flake-utils": [ - "crane", - "flake-utils" - ], - "nixpkgs": [ - "crane", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1694484610, - "narHash": "sha256-aeSDkp7fkAqtVjW3QUn7vq7BKNlFul/BiGgdv7rK+mA=", - "owner": "oxalica", - "repo": "rust-overlay", - "rev": "c5b977a7e6a295697fa1f9c42174fd6313b38df4", - "type": "github" - }, - "original": { - "owner": "oxalica", - "repo": "rust-overlay", - "type": "github" - } - }, - "systems": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } - } - }, - "root": "root", - "version": 7 -} diff --git a/flake.nix b/flake.nix deleted file mode 100644 index 4c5db8bfaae..00000000000 --- a/flake.nix +++ /dev/null @@ -1,260 +0,0 @@ -{ - description = "Build the Noir programming language"; - - # All of these inputs (a.k.a. dependencies) need to align with inputs we - # use so they use the `inputs.*.follows` syntax to reference our inputs - inputs = { - nixpkgs = { - url = "github:NixOS/nixpkgs/nixos-23.05"; - }; - - flake-utils = { - url = "github:numtide/flake-utils"; - }; - - flake-compat = { - url = "github:edolstra/flake-compat"; - flake = false; - }; - - fenix = { - url = "github:nix-community/fenix"; - inputs = { - nixpkgs.follows = "nixpkgs"; - }; - }; - - crane = { - url = "github:ipetkov/crane"; - inputs = { - nixpkgs.follows = "nixpkgs"; - flake-utils.follows = "flake-utils"; - flake-compat.follows = "flake-compat"; - }; - }; - }; - - outputs = - { self, nixpkgs, crane, flake-utils, fenix, ... }: - flake-utils.lib.eachDefaultSystem (system: - let - pkgs = import nixpkgs { - inherit system; - }; - - rustToolchain = fenix.packages.${system}.fromToolchainFile { - file = ./rust-toolchain.toml; - sha256 = "sha256-rLP8+fTxnPHoR96ZJiCa/5Ans1OojI7MLsmSqR2ip8o="; - }; - - craneLib = (crane.mkLib pkgs).overrideToolchain rustToolchain; - - # The `self.rev` property is only available when the working tree is not dirty - GIT_COMMIT = if (self ? rev) then self.rev else "unknown"; - GIT_DIRTY = if (self ? rev) then "false" else "true"; - - extraBuildInputs = [ ] ++ pkgs.lib.optionals pkgs.stdenv.isDarwin [ - # Need libiconv and apple Security on Darwin. See https://github.com/ipetkov/crane/issues/156 - pkgs.libiconv - pkgs.darwin.apple_sdk.frameworks.Security - ]; - - environment = { - # We enable backtraces on any failure for help with debugging - RUST_BACKTRACE = "1"; - - # We download the Wasm version of `acvm_backend` in the barretenberg releases for the ACVM `blackbox_solver` - BARRETENBERG_ARCHIVE = pkgs.fetchurl { - url = "https://github.com/AztecProtocol/barretenberg/releases/download/barretenberg-v0.4.5/acvm_backend.wasm.tar.gz"; - sha256 = "sha256-xONt5pTKWf/YbVnX/NXl/VNBbtKd+CP7CLkB1jf0RHw="; - }; - }; - - # Configuration shared between builds - config = { - # x-release-please-start-version - version = "0.24.0"; - # x-release-please-end - - src = pkgs.lib.cleanSourceWith { - src = craneLib.path ./.; - # Custom filter with various file extensions that we rely upon to build packages - # Currently: `.nr`, `.sol`, `.sh`, `.json`, `.md` and `.wasm` - filter = path: type: - (builtins.match ".*\.(nr|sol|sh|json|md|wasm)$" path != null) || (craneLib.filterCargoSources path type); - }; - - # TODO(#1198): It'd be nice to include these flags when running `cargo clippy` in a devShell. - cargoClippyExtraArgs = "--all-targets -- -D warnings"; - - # TODO(#1198): It'd be nice to include this flag when running `cargo test` in a devShell. - cargoTestExtraArgs = "--workspace"; - }; - - # Combine the environment and other configuration needed for Crane to build our Rust packages - nativeConfig = environment // config // { - nativeBuildInputs = [ ]; - - buildInputs = [ ] ++ extraBuildInputs; - }; - - # Combine the environmnet and other configuration needed for Crane to build our Wasm packages - wasmConfig = environment // config // { - CARGO_TARGET_DIR = "./target"; - - nativeBuildInputs = with pkgs; [ - which - git - jq - rustToolchain - wasm-bindgen-cli - binaryen - ]; - - buildInputs = [ ] ++ extraBuildInputs; - }; - - # Build *just* the cargo dependencies, so we can reuse all of that work between runs - native-cargo-artifacts = craneLib.buildDepsOnly (nativeConfig // { - pname = "nargo"; - }); - noirc-abi-wasm-cargo-artifacts = craneLib.buildDepsOnly (wasmConfig // { - pname = "noirc_abi_wasm"; - }); - acvm-js-cargo-artifacts = craneLib.buildDepsOnly (wasmConfig // { - pname = "acvm_js"; - }); - - nargo = craneLib.buildPackage (nativeConfig // { - pname = "nargo"; - - inherit GIT_COMMIT GIT_DIRTY; - - cargoArtifacts = native-cargo-artifacts; - - # We don't want to run tests because they don't work in the Nix sandbox - doCheck = false; - }); - - noirc_abi_wasm = craneLib.buildPackage (wasmConfig // rec { - pname = "noirc_abi_wasm"; - - inherit GIT_COMMIT GIT_DIRTY; - - cargoArtifacts = noirc-abi-wasm-cargo-artifacts; - - cargoExtraArgs = "--package ${pname} --target wasm32-unknown-unknown"; - - buildPhaseCargoCommand = '' - bash tooling/noirc_abi_wasm/buildPhaseCargoCommand.sh release - ''; - - installPhase = '' - bash tooling/noirc_abi_wasm/installPhase.sh - ''; - - # We don't want to run tests because they don't work in the Nix sandbox - doCheck = false; - }); - - acvm_js = craneLib.buildPackage (wasmConfig // rec { - pname = "acvm_js"; - - inherit GIT_COMMIT GIT_DIRTY; - - cargoArtifacts = acvm-js-cargo-artifacts; - - cargoExtraArgs = "--package ${pname} --target wasm32-unknown-unknown"; - - buildPhaseCargoCommand = '' - bash acvm-repo/acvm_js/buildPhaseCargoCommand.sh release - ''; - - installPhase = '' - bash acvm-repo/acvm_js/installPhase.sh - ''; - - # We don't want to run tests because they don't work in the Nix sandbox - doCheck = false; - }); - - wasm-bindgen-cli = pkgs.callPackage ./wasm-bindgen-cli.nix { - rustPlatform = pkgs.makeRustPlatform { - rustc = rustToolchain; - cargo = rustToolchain; - }; - }; - in - { - # We use `checks` to run `cargo clippy` and `cargo fmt` since we disable checks in the primary derivations - checks = { - cargo-clippy = craneLib.cargoClippy (nativeConfig // { - pname = "noir"; - - inherit GIT_COMMIT GIT_DIRTY; - - cargoArtifacts = native-cargo-artifacts; - }); - - cargo-fmt = craneLib.cargoFmt (nativeConfig // { - pname = "noir"; - - inherit GIT_COMMIT GIT_DIRTY; - - cargoArtifacts = native-cargo-artifacts; - }); - }; - - packages = { - default = nargo; - - # Nix flakes cannot build more than one derivation in one command (see https://github.com/NixOS/nix/issues/5591) - # so we use `symlinkJoin` to build everything as the "all" package. - all = pkgs.symlinkJoin { name = "all"; paths = [ nargo noirc_abi_wasm acvm_js ]; }; - all_wasm = pkgs.symlinkJoin { name = "all_wasm"; paths = [ noirc_abi_wasm acvm_js ]; }; - - # We also export individual packages to enable `nix build .#nargo -L`, etc. - inherit nargo; - inherit noirc_abi_wasm; - inherit acvm_js; - - # We expose the `*-cargo-artifacts` derivations so we can cache our cargo dependencies in CI - inherit native-cargo-artifacts; - inherit noirc-abi-wasm-cargo-artifacts; - inherit acvm-js-cargo-artifacts; - }; - - # Setup the environment to match the environment settings, the inputs from our checks derivations, - # and extra tooling via `nativeBuildInputs` - devShells.default = pkgs.mkShell (environment // { - inputsFrom = [ - nargo - noirc_abi_wasm - acvm_js - ]; - - # Additional tools that weren't included as `nativeBuildInputs` of any of the derivations in `inputsFrom` - nativeBuildInputs = with pkgs; [ - # Rust toolchain - rustToolchain - # Other tools - starship - yarn - nodejs-18_x - # Used by the `bb` binary - curl - gzip - # This ensures the right lldb is in the environment for running rust-lldb - llvmPackages.lldb - # Nix tools - nil - nixpkgs-fmt - ]; - - shellHook = '' - eval "$(starship init bash)" - ''; - }); - }); -} - diff --git a/noir-logo.png b/noir-logo.png new file mode 100644 index 00000000000..eabb163ad73 Binary files /dev/null and b/noir-logo.png differ diff --git a/noir_stdlib/src/aes128.nr b/noir_stdlib/src/aes128.nr new file mode 100644 index 00000000000..e6e2a5e4997 --- /dev/null +++ b/noir_stdlib/src/aes128.nr @@ -0,0 +1,4 @@ +#[foreign(aes128_encrypt)] +// docs:start:aes128 +pub fn aes128_encrypt(input: [u8; N], iv: [u8; 16], key: [u8; 16]) -> [u8] {} +// docs:end:aes128 diff --git a/noir_stdlib/src/array.nr b/noir_stdlib/src/array.nr index 8ddc43bbda6..f3bc9e33d1f 100644 --- a/noir_stdlib/src/array.nr +++ b/noir_stdlib/src/array.nr @@ -1,10 +1,10 @@ -use crate::cmp::{Ord}; +use crate::cmp::Ord; // TODO: Once we fully move to the new SSA pass this module can be removed and replaced // by the methods in the `slice` module impl [T; N] { #[builtin(array_len)] - pub fn len(self) -> u64 {} + pub fn len(self) -> u32 {} pub fn sort(self) -> Self where T: Ord { self.sort_via(|a: T, b: T| a <= b) @@ -13,7 +13,7 @@ impl [T; N] { pub fn sort_via(self, ordering: fn[Env](T, T) -> bool) -> Self { let sorted_index = unsafe { // Safety: This is safe we we enforce proper ordering using these indices - let sorted_index: [u64; N] = self.get_sorting_index(ordering); + let sorted_index: [u32; N] = self.get_sorting_index(ordering); // Ensure the indexes are correct for i in 0..N { @@ -38,7 +38,7 @@ impl [T; N] { } /// Returns the index of the elements in the array that would sort it, using the provided custom sorting function. - unconstrained fn get_sorting_index(self, ordering: fn[Env](T, T) -> bool) -> [u64; N] { + unconstrained fn get_sorting_index(self, ordering: fn[Env](T, T) -> bool) -> [u32; N] { let mut result = [0; N]; let mut a = self; for i in 0..N { @@ -59,14 +59,8 @@ impl [T; N] { result } - // Converts an array into a slice. - pub fn as_slice(self) -> [T] { - let mut slice = []; - for elem in self { - slice = slice.push_back(elem); - } - slice - } + #[builtin(as_slice)] + pub fn as_slice(self) -> [T] {} // Apply a function to each element of an array, returning a new array // containing the mapped elements. @@ -123,7 +117,7 @@ impl [T; N] { // helper function used to look up the position of a value in an array of Field // Note that function returns 0 if the value is not found -unconstrained fn find_index(a: [u64; N], find: u64) -> u64 { +unconstrained fn find_index(a: [u32; N], find: u32) -> u32 { let mut result = 0; for i in 0..a.len() { if a[i] == find { diff --git a/noir_stdlib/src/bigint.nr b/noir_stdlib/src/bigint.nr index 98237a54779..81dad968bf7 100644 --- a/noir_stdlib/src/bigint.nr +++ b/noir_stdlib/src/bigint.nr @@ -1,23 +1,22 @@ use crate::ops::{Add, Sub, Mul, Div}; use crate::cmp::Eq; -global bn254_fq = [0x47, 0xFD, 0x7C, 0xD8, 0x16, 0x8C, 0x20, 0x3C, 0x8d, 0xca, 0x71, 0x68, 0x91, 0x6a, 0x81, 0x97, - 0x5d, 0x58, 0x81, 0x81, 0xb6, 0x45, 0x50, 0xb8, 0x29, 0xa0, 0x31, 0xe1, 0x72, 0x4e, 0x64, 0x30]; -global bn254_fr = [0x01, 0x00, 0x00, 0x00, 0x3F, 0x59, 0x1F, 0x43, 0x09, 0x97, 0xB9, 0x79, 0x48, 0xE8, 0x33, 0x28, - 0x5D, 0x58, 0x81, 0x81, 0xB6, 0x45, 0x50, 0xB8, 0x29, 0xA0, 0x31, 0xE1, 0x72, 0x4E, 0x64, 0x30]; -global secpk1_fr = [0x41, 0x41, 0x36, 0xD0, 0x8C, 0x5E, 0xD2, 0xBF, 0x3B, 0xA0, 0x48, 0xAF, 0xE6, 0xDC, 0xAE, 0xBA, - 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]; -global secpk1_fq = [0x2F, 0xFC, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]; -global secpr1_fq = [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF]; -global secpr1_fr = [0x51, 0x25, 0x63, 0xFC, 0xC2, 0xCA, 0xB9, 0xF3, 0x84, 0x9E, 0x17, 0xA7, 0xAD, 0xFA, 0xE6, 0xBC, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,0xFF, 0xFF, 0xFF, 0xFF]; - +global bn254_fq = &[0x47, 0xFD, 0x7C, 0xD8, 0x16, 0x8C, 0x20, 0x3C, 0x8d, 0xca, 0x71, 0x68, 0x91, 0x6a, 0x81, 0x97, + 0x5d, 0x58, 0x81, 0x81, 0xb6, 0x45, 0x50, 0xb8, 0x29, 0xa0, 0x31, 0xe1, 0x72, 0x4e, 0x64, 0x30]; +global bn254_fr = &[1, 0, 0, 240, 147, 245, 225, 67, 145, 112, 185, 121, 72, 232, 51, 40, 93, 88, 129, 129, 182, 69, 80, 184, 41, 160, 49, 225, 114, 78, 100, 48]; +global secpk1_fr = &[0x41, 0x41, 0x36, 0xD0, 0x8C, 0x5E, 0xD2, 0xBF, 0x3B, 0xA0, 0x48, 0xAF, 0xE6, 0xDC, 0xAE, 0xBA, + 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]; +global secpk1_fq = &[0x2F, 0xFC, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]; +global secpr1_fq = &[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF]; +global secpr1_fr = &[81, 37, 99, 252, 194, 202, 185, 243, 132, 158, 23, 167, 173, 250, 230, 188, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255]; +// docs:start:big_int_definition struct BigInt { pointer: u32, modulus: u32, } +// docs:end:big_int_definition impl BigInt { #[builtin(bigint_add)] @@ -31,7 +30,7 @@ impl BigInt { #[builtin(bigint_from_le_bytes)] fn from_le_bytes(bytes: [u8], modulus: [u8]) -> BigInt {} #[builtin(bigint_to_le_bytes)] - fn to_le_bytes(self) -> [u8] {} + fn to_le_bytes(self) -> [u8; 32] {} fn check_32_bytes(self: Self, other: BigInt) -> bool { let bytes = self.to_le_bytes(); @@ -46,305 +45,420 @@ impl BigInt { trait BigField { fn from_le_bytes(bytes: [u8]) -> Self; + fn from_le_bytes_32(bytes: [u8; 32]) -> Self; fn to_le_bytes(self) -> [u8]; } struct Secpk1Fq { - inner: BigInt, + array: [u8;32], } impl BigField for Secpk1Fq { fn from_le_bytes(bytes: [u8]) -> Secpk1Fq { + assert(bytes.len() <= 32); + let mut array = [0;32]; + for i in 0..bytes.len() { + array[i] = bytes[i]; + } + Secpk1Fq { + array: array, + } + } + + fn from_le_bytes_32(bytes: [u8;32]) -> Secpk1Fq { Secpk1Fq { - inner: BigInt::from_le_bytes(bytes, secpk1_fq) + array: bytes, } } + fn to_le_bytes(self) -> [u8] { - self.inner.to_le_bytes() + self.array } } impl Add for Secpk1Fq { fn add(self: Self, other: Secpk1Fq) -> Secpk1Fq { + let a = BigInt::from_le_bytes(self.array.as_slice(), secpk1_fq); + let b = BigInt::from_le_bytes(other.array.as_slice(), secpk1_fq); Secpk1Fq { - inner: self.inner.bigint_add(other.inner) + array: a.bigint_add(b).to_le_bytes() } } } impl Sub for Secpk1Fq { fn sub(self: Self, other: Secpk1Fq) -> Secpk1Fq { + let a = BigInt::from_le_bytes(self.array.as_slice(), secpk1_fq); + let b = BigInt::from_le_bytes(other.array.as_slice(), secpk1_fq); Secpk1Fq { - inner: self.inner.bigint_sub(other.inner) + array: a.bigint_sub(b).to_le_bytes() } } } impl Mul for Secpk1Fq { fn mul(self: Self, other: Secpk1Fq) -> Secpk1Fq { + let a = BigInt::from_le_bytes(self.array.as_slice(), secpk1_fq); + let b = BigInt::from_le_bytes(other.array.as_slice(), secpk1_fq); Secpk1Fq { - inner: self.inner.bigint_mul(other.inner) + array: a.bigint_mul(b).to_le_bytes() } - } } impl Div for Secpk1Fq { fn div(self: Self, other: Secpk1Fq) -> Secpk1Fq { + let a = BigInt::from_le_bytes(self.array.as_slice(), secpk1_fq); + let b = BigInt::from_le_bytes(other.array.as_slice(), secpk1_fq); Secpk1Fq { - inner: self.inner.bigint_div(other.inner) + array: a.bigint_div(b).to_le_bytes() } } } impl Eq for Secpk1Fq { fn eq(self: Self, other: Secpk1Fq) -> bool { - self.inner.check_32_bytes(other.inner) + self.array == other.array } } struct Secpk1Fr { - inner: BigInt, + array: [u8;32], } impl BigField for Secpk1Fr { fn from_le_bytes(bytes: [u8]) -> Secpk1Fr { + assert(bytes.len() <= 32); + let mut array = [0;32]; + for i in 0..bytes.len() { + array[i] = bytes[i]; + } Secpk1Fr { - inner: BigInt::from_le_bytes(bytes, secpk1_fr) + array: array, } } + + fn from_le_bytes_32(bytes: [u8;32]) -> Secpk1Fr { + Secpk1Fr { + array: bytes, + } + } + fn to_le_bytes(self) -> [u8] { - self.inner.to_le_bytes() + self.array } } impl Add for Secpk1Fr { fn add(self: Self, other: Secpk1Fr) -> Secpk1Fr { + let a = BigInt::from_le_bytes(self.array.as_slice(), secpk1_fr); + let b = BigInt::from_le_bytes(other.array.as_slice(), secpk1_fr); Secpk1Fr { - inner: self.inner.bigint_add(other.inner) + array: a.bigint_add(b).to_le_bytes() } } } impl Sub for Secpk1Fr { fn sub(self: Self, other: Secpk1Fr) -> Secpk1Fr { + let a = BigInt::from_le_bytes(self.array.as_slice(), secpk1_fr); + let b = BigInt::from_le_bytes(other.array.as_slice(), secpk1_fr); Secpk1Fr { - inner: self.inner.bigint_sub(other.inner) + array: a.bigint_sub(b).to_le_bytes() } } } impl Mul for Secpk1Fr { fn mul(self: Self, other: Secpk1Fr) -> Secpk1Fr { + let a = BigInt::from_le_bytes(self.array.as_slice(), secpk1_fr); + let b = BigInt::from_le_bytes(other.array.as_slice(), secpk1_fr); Secpk1Fr { - inner: self.inner.bigint_mul(other.inner) + array: a.bigint_mul(b).to_le_bytes() } - } } impl Div for Secpk1Fr { fn div(self: Self, other: Secpk1Fr) -> Secpk1Fr { + let a = BigInt::from_le_bytes(self.array.as_slice(), secpk1_fr); + let b = BigInt::from_le_bytes(other.array.as_slice(), secpk1_fr); Secpk1Fr { - inner: self.inner.bigint_div(other.inner) + array: a.bigint_div(b).to_le_bytes() } } } impl Eq for Secpk1Fr { fn eq(self: Self, other: Secpk1Fr) -> bool { - self.inner.check_32_bytes(other.inner) + self.array == other.array } } struct Bn254Fr { - inner: BigInt, + array: [u8;32], } impl BigField for Bn254Fr { fn from_le_bytes(bytes: [u8]) -> Bn254Fr { + assert(bytes.len() <= 32); + let mut array = [0;32]; + for i in 0..bytes.len() { + array[i] = bytes[i]; + } + Bn254Fr { + array: array, + } + } + + fn from_le_bytes_32(bytes: [u8;32]) -> Bn254Fr { Bn254Fr { - inner: BigInt::from_le_bytes(bytes, bn254_fr) + array: bytes, } } + fn to_le_bytes(self) -> [u8] { - self.inner.to_le_bytes() + self.array } } impl Add for Bn254Fr { fn add(self: Self, other: Bn254Fr) -> Bn254Fr { + let a = BigInt::from_le_bytes(self.array.as_slice(), bn254_fr); + let b = BigInt::from_le_bytes(other.array.as_slice(), bn254_fr); Bn254Fr { - inner: self.inner.bigint_add(other.inner) + array: a.bigint_add(b).to_le_bytes() } } } impl Sub for Bn254Fr { fn sub(self: Self, other: Bn254Fr) -> Bn254Fr { + let a = BigInt::from_le_bytes(self.array.as_slice(), bn254_fr); + let b = BigInt::from_le_bytes(other.array.as_slice(), bn254_fr); Bn254Fr { - inner: self.inner.bigint_sub(other.inner) + array: a.bigint_sub(b).to_le_bytes() } } } impl Mul for Bn254Fr { fn mul(self: Self, other: Bn254Fr) -> Bn254Fr { + let a = BigInt::from_le_bytes(self.array.as_slice(), bn254_fr); + let b = BigInt::from_le_bytes(other.array.as_slice(), bn254_fr); Bn254Fr { - inner: self.inner.bigint_mul(other.inner) + array: a.bigint_mul(b).to_le_bytes() } - } } impl Div for Bn254Fr { fn div(self: Self, other: Bn254Fr) -> Bn254Fr { + let a = BigInt::from_le_bytes(self.array.as_slice(), bn254_fr); + let b = BigInt::from_le_bytes(other.array.as_slice(), bn254_fr); Bn254Fr { - inner: self.inner.bigint_div(other.inner) + array: a.bigint_div(b).to_le_bytes() } } } impl Eq for Bn254Fr { fn eq(self: Self, other: Bn254Fr) -> bool { - self.inner.check_32_bytes(other.inner) + self.array == other.array } } struct Bn254Fq { - inner: BigInt, + array: [u8;32], } impl BigField for Bn254Fq { fn from_le_bytes(bytes: [u8]) -> Bn254Fq { + assert(bytes.len() <= 32); + let mut array = [0;32]; + for i in 0..bytes.len() { + array[i] = bytes[i]; + } + Bn254Fq { + array: array, + } + } + + fn from_le_bytes_32(bytes: [u8;32]) -> Bn254Fq { Bn254Fq { - inner: BigInt::from_le_bytes(bytes, bn254_fq) + array: bytes, } } + fn to_le_bytes(self) -> [u8] { - self.inner.to_le_bytes() + self.array } } impl Add for Bn254Fq { fn add(self: Self, other: Bn254Fq) -> Bn254Fq { + let a = BigInt::from_le_bytes(self.array.as_slice(), bn254_fq); + let b = BigInt::from_le_bytes(other.array.as_slice(), bn254_fq); Bn254Fq { - inner: self.inner.bigint_add(other.inner) + array: a.bigint_add(b).to_le_bytes() } } } impl Sub for Bn254Fq { fn sub(self: Self, other: Bn254Fq) -> Bn254Fq { + let a = BigInt::from_le_bytes(self.array.as_slice(), bn254_fq); + let b = BigInt::from_le_bytes(other.array.as_slice(), bn254_fq); Bn254Fq { - inner: self.inner.bigint_sub(other.inner) + array: a.bigint_sub(b).to_le_bytes() } } } impl Mul for Bn254Fq { fn mul(self: Self, other: Bn254Fq) -> Bn254Fq { + let a = BigInt::from_le_bytes(self.array.as_slice(), bn254_fq); + let b = BigInt::from_le_bytes(other.array.as_slice(), bn254_fq); Bn254Fq { - inner: self.inner.bigint_mul(other.inner) + array: a.bigint_mul(b).to_le_bytes() } - } } impl Div for Bn254Fq { fn div(self: Self, other: Bn254Fq) -> Bn254Fq { + let a = BigInt::from_le_bytes(self.array.as_slice(), bn254_fq); + let b = BigInt::from_le_bytes(other.array.as_slice(), bn254_fq); Bn254Fq { - inner: self.inner.bigint_div(other.inner) + array: a.bigint_div(b).to_le_bytes() } } } impl Eq for Bn254Fq { fn eq(self: Self, other: Bn254Fq) -> bool { - self.inner.check_32_bytes(other.inner) + self.array == other.array } } struct Secpr1Fq { - inner: BigInt, + array: [u8;32], } impl BigField for Secpr1Fq { fn from_le_bytes(bytes: [u8]) -> Secpr1Fq { + assert(bytes.len() <= 32); + let mut array = [0;32]; + for i in 0..bytes.len() { + array[i] = bytes[i]; + } Secpr1Fq { - inner: BigInt::from_le_bytes(bytes, secpr1_fq) + array: array, } } + + fn from_le_bytes_32(bytes: [u8;32]) -> Secpr1Fq { + Secpr1Fq { + array: bytes, + } + } + fn to_le_bytes(self) -> [u8] { - self.inner.to_le_bytes() + self.array } } impl Add for Secpr1Fq { fn add(self: Self, other: Secpr1Fq) -> Secpr1Fq { + let a = BigInt::from_le_bytes(self.array.as_slice(), secpr1_fq); + let b = BigInt::from_le_bytes(other.array.as_slice(), secpr1_fq); Secpr1Fq { - inner: self.inner.bigint_add(other.inner) + array: a.bigint_add(b).to_le_bytes() } } } impl Sub for Secpr1Fq { fn sub(self: Self, other: Secpr1Fq) -> Secpr1Fq { + let a = BigInt::from_le_bytes(self.array.as_slice(), secpr1_fq); + let b = BigInt::from_le_bytes(other.array.as_slice(), secpr1_fq); Secpr1Fq { - inner: self.inner.bigint_sub(other.inner) + array: a.bigint_sub(b).to_le_bytes() } } } impl Mul for Secpr1Fq { fn mul(self: Self, other: Secpr1Fq) -> Secpr1Fq { + let a = BigInt::from_le_bytes(self.array.as_slice(), secpr1_fq); + let b = BigInt::from_le_bytes(other.array.as_slice(), secpr1_fq); Secpr1Fq { - inner: self.inner.bigint_mul(other.inner) + array: a.bigint_mul(b).to_le_bytes() } - } } impl Div for Secpr1Fq { fn div(self: Self, other: Secpr1Fq) -> Secpr1Fq { + let a = BigInt::from_le_bytes(self.array.as_slice(), secpr1_fq); + let b = BigInt::from_le_bytes(other.array.as_slice(), secpr1_fq); Secpr1Fq { - inner: self.inner.bigint_div(other.inner) + array: a.bigint_div(b).to_le_bytes() } } } impl Eq for Secpr1Fq { fn eq(self: Self, other: Secpr1Fq) -> bool { - self.inner.check_32_bytes(other.inner) + self.array == other.array } } struct Secpr1Fr { - inner: BigInt, + array: [u8;32], } impl BigField for Secpr1Fr { fn from_le_bytes(bytes: [u8]) -> Secpr1Fr { + assert(bytes.len() <= 32); + let mut array = [0;32]; + for i in 0..bytes.len() { + array[i] = bytes[i]; + } + Secpr1Fr { + array: array, + } + } + + fn from_le_bytes_32(bytes: [u8;32]) -> Secpr1Fr { Secpr1Fr { - inner: BigInt::from_le_bytes(bytes, secpr1_fr) + array: bytes, } } + fn to_le_bytes(self) -> [u8] { - self.inner.to_le_bytes() + self.array } } impl Add for Secpr1Fr { fn add(self: Self, other: Secpr1Fr) -> Secpr1Fr { + let a = BigInt::from_le_bytes(self.array.as_slice(), secpr1_fr); + let b = BigInt::from_le_bytes(other.array.as_slice(), secpr1_fr); Secpr1Fr { - inner: self.inner.bigint_add(other.inner) + array: a.bigint_add(b).to_le_bytes() } } } impl Sub for Secpr1Fr { fn sub(self: Self, other: Secpr1Fr) -> Secpr1Fr { + let a = BigInt::from_le_bytes(self.array.as_slice(), secpr1_fr); + let b = BigInt::from_le_bytes(other.array.as_slice(), secpr1_fr); Secpr1Fr { - inner: self.inner.bigint_sub(other.inner) + array: a.bigint_sub(b).to_le_bytes() } } } impl Mul for Secpr1Fr { fn mul(self: Self, other: Secpr1Fr) -> Secpr1Fr { + let a = BigInt::from_le_bytes(self.array.as_slice(), secpr1_fr); + let b = BigInt::from_le_bytes(other.array.as_slice(), secpr1_fr); Secpr1Fr { - inner: self.inner.bigint_mul(other.inner) + array: a.bigint_mul(b).to_le_bytes() } - } } impl Div for Secpr1Fr { fn div(self: Self, other: Secpr1Fr) -> Secpr1Fr { + let a = BigInt::from_le_bytes(self.array.as_slice(), secpr1_fr); + let b = BigInt::from_le_bytes(other.array.as_slice(), secpr1_fr); Secpr1Fr { - inner: self.inner.bigint_div(other.inner) + array: a.bigint_div(b).to_le_bytes() } } } impl Eq for Secpr1Fr { fn eq(self: Self, other: Secpr1Fr) -> bool { - self.inner.check_32_bytes(other.inner) + self.array == other.array } } diff --git a/noir_stdlib/src/cmp.nr b/noir_stdlib/src/cmp.nr index 38316e5d6a8..457b2cfa167 100644 --- a/noir_stdlib/src/cmp.nr +++ b/noir_stdlib/src/cmp.nr @@ -6,10 +6,10 @@ trait Eq { impl Eq for Field { fn eq(self, other: Field) -> bool { self == other } } -impl Eq for u1 { fn eq(self, other: u1) -> bool { self == other } } -impl Eq for u8 { fn eq(self, other: u8) -> bool { self == other } } -impl Eq for u32 { fn eq(self, other: u32) -> bool { self == other } } impl Eq for u64 { fn eq(self, other: u64) -> bool { self == other } } +impl Eq for u32 { fn eq(self, other: u32) -> bool { self == other } } +impl Eq for u8 { fn eq(self, other: u8) -> bool { self == other } } +impl Eq for u1 { fn eq(self, other: u1) -> bool { self == other } } impl Eq for i8 { fn eq(self, other: i8) -> bool { self == other } } impl Eq for i32 { fn eq(self, other: i32) -> bool { self == other } } @@ -28,6 +28,16 @@ impl Eq for [T; N] where T: Eq { } } +impl Eq for [T] where T: Eq { + fn eq(self, other: [T]) -> bool { + let mut result = self.len() == other.len(); + for i in 0 .. self.len() { + result &= self[i].eq(other[i]); + } + result + } +} + impl Eq for str { fn eq(self, other: str) -> bool { let self_bytes = self.as_bytes(); @@ -97,8 +107,8 @@ trait Ord { // Note: Field deliberately does not implement Ord -impl Ord for u8 { - fn cmp(self, other: u8) -> Ordering { +impl Ord for u64 { + fn cmp(self, other: u64) -> Ordering { if self < other { Ordering::less() } else if self > other { @@ -121,8 +131,8 @@ impl Ord for u32 { } } -impl Ord for u64 { - fn cmp(self, other: u64) -> Ordering { +impl Ord for u8 { + fn cmp(self, other: u8) -> Ordering { if self < other { Ordering::less() } else if self > other { @@ -213,6 +223,26 @@ impl Ord for [T; N] where T: Ord { } } +impl Ord for [T] where T: Ord { + // The first non-equal element of both arrays determines + // the ordering for the whole array. + fn cmp(self, other: [T]) -> Ordering { + let mut result = self.len().cmp(other.len()); + for i in 0 .. self.len() { + if result == Ordering::equal() { + let result_i = self[i].cmp(other[i]); + + if result_i == Ordering::less() { + result = result_i; + } else if result_i == Ordering::greater() { + result = result_i; + } + } + } + result + } +} + impl Ord for (A, B) where A: Ord, B: Ord { fn cmp(self, other: (A, B)) -> Ordering { let result = self.0.cmp(other.0); @@ -284,3 +314,55 @@ impl Ord for (A, B, C, D, E) where A: Ord, B: Ord, C: Ord, D: Ord result } } + +// Compares and returns the maximum of two values. +// +// Returns the second argument if the comparison determines them to be equal. +// +// # Examples +// +// ``` +// use std::cmp; +// +// assert_eq(cmp::max(1, 2), 2); +// assert_eq(cmp::max(2, 2), 2); +// ``` +pub fn max(v1: T, v2: T) -> T where T: Ord { + if v1 > v2 { v1 } else { v2 } +} + +// Compares and returns the minimum of two values. +// +// Returns the first argument if the comparison determines them to be equal. +// +// # Examples +// +// ``` +// use std::cmp; +// +// assert_eq(cmp::min(1, 2), 1); +// assert_eq(cmp::min(2, 2), 2); +// ``` +pub fn min(v1: T, v2: T) -> T where T: Ord { + if v1 > v2 { v2 } else { v1 } +} + +mod cmp_tests { + use crate::cmp::{min, max}; + + #[test] + fn sanity_check_min() { + assert_eq(min(0 as u64, 1 as u64), 0); + assert_eq(min(0 as u64, 0 as u64), 0); + assert_eq(min(1 as u64, 1 as u64), 1); + assert_eq(min(255 as u8, 0 as u8), 0); + } + + #[test] + fn sanity_check_max() { + assert_eq(max(0 as u64, 1 as u64), 1); + assert_eq(max(0 as u64, 0 as u64), 0); + assert_eq(max(1 as u64, 1 as u64), 1); + assert_eq(max(255 as u8, 0 as u8), 255); + } +} diff --git a/noir_stdlib/src/collections/bounded_vec.nr b/noir_stdlib/src/collections/bounded_vec.nr index 04201b0fa19..46da76ef718 100644 --- a/noir_stdlib/src/collections/bounded_vec.nr +++ b/noir_stdlib/src/collections/bounded_vec.nr @@ -1,6 +1,8 @@ +use crate::{cmp::Eq, convert::From}; + struct BoundedVec { storage: [T; MaxLen], - len: u64, + len: u32, } impl BoundedVec { @@ -9,27 +11,27 @@ impl BoundedVec { BoundedVec { storage: [zeroed; MaxLen], len: 0 } } - pub fn get(mut self: Self, index: u64) -> T { - assert(index as u64 < self.len); + pub fn get(mut self: Self, index: u32) -> T { + assert(index < self.len); self.storage[index] } - pub fn get_unchecked(mut self: Self, index: u64) -> T { + pub fn get_unchecked(mut self: Self, index: u32) -> T { self.storage[index] } pub fn push(&mut self, elem: T) { - assert(self.len < MaxLen as u64, "push out of bounds"); + assert(self.len < MaxLen, "push out of bounds"); self.storage[self.len] = elem; self.len += 1; } - pub fn len(self) -> u64 { + pub fn len(self) -> u32 { self.len } - pub fn max_len(_self: BoundedVec) -> u64 { + pub fn max_len(_self: BoundedVec) -> u32 { MaxLen } @@ -41,17 +43,26 @@ impl BoundedVec { pub fn extend_from_array(&mut self, array: [T; Len]) { let new_len = self.len + array.len(); - assert(new_len as u64 <= MaxLen as u64, "extend_from_array out of bounds"); + assert(new_len <= MaxLen, "extend_from_array out of bounds"); for i in 0..array.len() { self.storage[self.len + i] = array[i]; } self.len = new_len; } + pub fn extend_from_slice(&mut self, slice: [T]) { + let new_len = self.len + slice.len(); + assert(new_len <= MaxLen, "extend_from_slice out of bounds"); + for i in 0..slice.len() { + self.storage[self.len + i] = slice[i]; + } + self.len = new_len; + } + pub fn extend_from_bounded_vec(&mut self, vec: BoundedVec) { let append_len = vec.len(); let new_len = self.len + append_len; - assert(new_len as u64 <= MaxLen as u64, "extend_from_bounded_vec out of bounds"); + assert(new_len <= MaxLen, "extend_from_bounded_vec out of bounds"); let mut exceeded_len = false; for i in 0..Len { @@ -63,8 +74,15 @@ impl BoundedVec { self.len = new_len; } + pub fn from_array(array: [T; Len]) -> Self { + assert(Len <= MaxLen, "from array out of bounds"); + let mut vec: BoundedVec = BoundedVec::new(); + vec.extend_from_array(array); + vec + } + pub fn pop(&mut self) -> T { - assert(self.len as u64 > 0); + assert(self.len > 0); self.len -= 1; let elem = self.storage[self.len]; @@ -84,3 +102,99 @@ impl BoundedVec { ret } } + +impl Eq for BoundedVec where T: Eq { + fn eq(self, other: BoundedVec) -> bool { + // TODO: https://github.com/noir-lang/noir/issues/4837 + // + // We make the assumption that the user has used the proper interface for working with `BoundedVec`s + // rather than directly manipulating the internal fields as this can result in an inconsistent internal state. + + (self.len == other.len) & (self.storage == other.storage) + } +} + +impl From<[T; Len]> for BoundedVec { + fn from(array: [T; Len]) -> BoundedVec { + BoundedVec::from_array(array) + } +} + +mod bounded_vec_tests { + // TODO: Allow imports from "super" + use crate::collections::bounded_vec::BoundedVec; + + #[test] + fn empty_equality() { + let mut bounded_vec1: BoundedVec = BoundedVec::new(); + let mut bounded_vec2: BoundedVec = BoundedVec::new(); + + assert_eq(bounded_vec1, bounded_vec2); + } + + #[test] + fn inequality() { + let mut bounded_vec1: BoundedVec = BoundedVec::new(); + let mut bounded_vec2: BoundedVec = BoundedVec::new(); + bounded_vec1.push(1); + bounded_vec2.push(2); + + assert(bounded_vec1 != bounded_vec2); + } + + mod from_array { + use crate::collections::bounded_vec::BoundedVec; + + #[test] + fn empty() { + let empty_array: [Field; 0] = []; + let bounded_vec = BoundedVec::from_array([]); + + assert_eq(bounded_vec.max_len(), 0); + assert_eq(bounded_vec.len(), 0); + assert_eq(bounded_vec.storage(), empty_array); + } + + #[test] + fn equal_len() { + let array = [1, 2, 3]; + let bounded_vec = BoundedVec::from_array(array); + + assert_eq(bounded_vec.max_len(), 3); + assert_eq(bounded_vec.len(), 3); + assert_eq(bounded_vec.storage(), array); + } + + #[test] + fn max_len_greater_then_array_len() { + let array = [1, 2, 3]; + let bounded_vec: BoundedVec = BoundedVec::from_array(array); + + assert_eq(bounded_vec.max_len(), 10); + assert_eq(bounded_vec.len(), 3); + assert_eq(bounded_vec.storage()[0], 1); + assert_eq(bounded_vec.storage()[1], 2); + assert_eq(bounded_vec.storage()[2], 3); + } + + #[test(should_fail_with="from array out of bounds")] + fn max_len_lower_then_array_len() { + let _: BoundedVec = BoundedVec::from_array([0; 3]); + } + } + + mod trait_from { + use crate::collections::bounded_vec::BoundedVec; + + #[test] + fn simple() { + let array = [1, 2]; + let bounded_vec: BoundedVec = BoundedVec::from(array); + + assert_eq(bounded_vec.max_len(), 10); + assert_eq(bounded_vec.len(), 2); + assert_eq(bounded_vec.storage()[0], 1); + assert_eq(bounded_vec.storage()[1], 2); + } + } +} diff --git a/noir_stdlib/src/collections/map.nr b/noir_stdlib/src/collections/map.nr index 5f78b3047eb..6eec21d75a0 100644 --- a/noir_stdlib/src/collections/map.nr +++ b/noir_stdlib/src/collections/map.nr @@ -3,6 +3,7 @@ use crate::collections::vec::Vec; use crate::option::Option; use crate::default::Default; use crate::hash::{Hash, Hasher, BuildHasher}; +use crate::collections::bounded_vec::BoundedVec; // We use load factor α_max = 0.75. // Upon exceeding it, assert will fail in order to inform the user @@ -18,7 +19,7 @@ struct HashMap { _table: [Slot; N], // Amount of valid elements in the map. - _len: u64, + _len: u32, _build_hasher: B } @@ -78,21 +79,26 @@ impl Slot { // it is very unlikely to be after - performance will be heavily degraded. impl HashMap { // Creates a new instance of HashMap with specified BuildHasher. + // docs:start:with_hasher pub fn with_hasher(_build_hasher: B) -> Self where B: BuildHasher { + // docs:end:with_hasher let _table = [Slot::default(); N]; let _len = 0; Self { _table, _len, _build_hasher } } // Clears the map, removing all key-value entries. + // docs:start:clear pub fn clear(&mut self) { + // docs:end:clear self._table = [Slot::default(); N]; self._len = 0; } // Returns true if the map contains a value for the specified key. + // docs:start:contains_key pub fn contains_key( self, key: K @@ -101,89 +107,80 @@ impl HashMap { K: Hash + Eq, B: BuildHasher, H: Hasher { + // docs:end:contains_key self.get(key).is_some() } // Returns true if the map contains no elements. + // docs:start:is_empty pub fn is_empty(self) -> bool { + // docs:end:is_empty self._len == 0 } - // Get the Option<(K, V) array of valid entries - // with a length of map capacity. First len() elements - // are safe to unwrap_unchecked(), whilst remaining - // are guaranteed to be Option::none(). - // - // This design is reasoned by compile-time limitations and - // temporary nested slices ban. - pub fn entries(self) -> [Option<(K, V)>; N] { - let mut entries = [Option::none(); N]; - let mut valid_amount = 0; + // Returns a BoundedVec of all valid entries in this HashMap. + // The length of the returned vector will always match the length of this HashMap. + // docs:start:entries + pub fn entries(self) -> BoundedVec<(K, V), N> { + // docs:end:entries + let mut entries = BoundedVec::new(); for slot in self._table { if slot.is_valid() { - entries[valid_amount] = slot.key_value(); - valid_amount += 1; + // SAFETY: slot.is_valid() should ensure there is a valid key-value pairing here + let key_value = slot.key_value().unwrap_unchecked(); + entries.push(key_value); } } - let msg = f"Amount of valid elements should have been {self._len} times, but got {valid_amount}."; - assert(valid_amount == self._len, msg); + let msg = f"Amount of valid elements should have been {self._len} times, but got {entries.len()}."; + assert(entries.len() == self._len, msg); entries } - // Get the Option array of valid keys - // with a length of map capacity. First len() elements - // are safe to unwrap_unchecked(), whilst remaining - // are guaranteed to be Option::none(). - // - // This design is reasoned by compile-time limitations and - // temporary nested slices ban. - pub fn keys(self) -> [Option; N] { - let mut keys = [Option::none(); N]; - let mut valid_amount = 0; + // Returns a BoundedVec containing all the keys within this HashMap. + // The length of the returned vector will always match the length of this HashMap. + // docs:start:keys + pub fn keys(self) -> BoundedVec { + // docs:end:keys + let mut keys = BoundedVec::new(); for slot in self._table { if slot.is_valid() { let (key, _) = slot.key_value_unchecked(); - keys[valid_amount] = Option::some(key); - valid_amount += 1; + keys.push(key); } } - let msg = f"Amount of valid elements should have been {self._len} times, but got {valid_amount}."; - assert(valid_amount == self._len, msg); + let msg = f"Amount of valid elements should have been {self._len} times, but got {keys.len()}."; + assert(keys.len() == self._len, msg); keys } - // Get the Option array of valid values - // with a length of map capacity. First len() elements - // are safe to unwrap_unchecked(), whilst remaining - // are guaranteed to be Option::none(). - // - // This design is reasoned by compile-time limitations and - // temporary nested slices ban. - pub fn values(self) -> [Option; N] { - let mut values = [Option::none(); N]; - let mut valid_amount = 0; + // Returns a BoundedVec containing all the values within this HashMap. + // The length of the returned vector will always match the length of this HashMap. + // docs:start:values + pub fn values(self) -> BoundedVec { + // docs:end:values + let mut values = BoundedVec::new(); for slot in self._table { if slot.is_valid() { let (_, value) = unsafe {slot.key_value_unchecked()}; - values[valid_amount] = Option::some(value); - valid_amount += 1; + values.push(value); } } - let msg = f"Amount of valid elements should have been {self._len} times, but got {valid_amount}."; - assert(valid_amount == self._len, msg); + let msg = f"Amount of valid elements should have been {self._len} times, but got {values.len()}."; + assert(values.len() == self._len, msg); values } // For each key-value entry applies mutator function. + // docs:start:iter_mut pub fn iter_mut( &mut self, f: fn(K, V) -> (K, V) @@ -192,12 +189,13 @@ impl HashMap { K: Eq + Hash, B: BuildHasher, H: Hasher { + // docs:end:iter_mut let mut entries = self.entries(); let mut new_map = HashMap::with_hasher(self._build_hasher); for i in 0..N { if i < self._len { - let entry = entries[i].unwrap_unchecked(); + let entry = entries.get_unchecked(i); let (key, value) = f(entry.0, entry.1); new_map.insert(key, value); } @@ -207,6 +205,7 @@ impl HashMap { } // For each key applies mutator function. + // docs:start:iter_keys_mut pub fn iter_keys_mut( &mut self, f: fn(K) -> K @@ -215,12 +214,13 @@ impl HashMap { K: Eq + Hash, B: BuildHasher, H: Hasher { + // docs:end:iter_keys_mut let mut entries = self.entries(); let mut new_map = HashMap::with_hasher(self._build_hasher); for i in 0..N { if i < self._len { - let entry = entries[i].unwrap_unchecked(); + let entry = entries.get_unchecked(i); let (key, value) = (f(entry.0), entry.1); new_map.insert(key, value); } @@ -230,7 +230,9 @@ impl HashMap { } // For each value applies mutator function. + // docs:start:iter_values_mut pub fn iter_values_mut(&mut self, f: fn(V) -> V) { + // docs:end:iter_values_mut for i in 0..N { let mut slot = self._table[i]; if slot.is_valid() { @@ -242,7 +244,9 @@ impl HashMap { } // Retains only the elements specified by the predicate. + // docs:start:retain pub fn retain(&mut self, f: fn(K, V) -> bool) { + // docs:end:retain for index in 0..N { let mut slot = self._table[index]; if slot.is_valid() { @@ -257,16 +261,21 @@ impl HashMap { } // Amount of active key-value entries. - pub fn len(self) -> u64 { + // docs:start:len + pub fn len(self) -> u32 { + // docs:end:len self._len } // Get the compile-time map capacity. - pub fn capacity(_self: Self) -> u64 { + // docs:start:capacity + pub fn capacity(_self: Self) -> u32 { + // docs:end:capacity N } // Get the value by key. If it does not exist, returns none(). + // docs:start:get pub fn get( self, key: K @@ -275,14 +284,15 @@ impl HashMap { K: Eq + Hash, B: BuildHasher, H: Hasher { + // docs:end:get let mut result = Option::none(); let hash = self.hash(key); - let mut break = false; + let mut should_break = false; for attempt in 0..N { - if !break { - let index = self.quadratic_probe(hash, attempt as u64); + if !should_break { + let index = self.quadratic_probe(hash, attempt as u32); let slot = self._table[index]; // Not marked as deleted and has key-value. @@ -290,7 +300,7 @@ impl HashMap { let (current_key, value) = slot.key_value_unchecked(); if current_key == key { result = Option::some(value); - break = true; + should_break = true; } } } @@ -300,6 +310,7 @@ impl HashMap { } // Insert key-value entry. In case key was already present, value is overridden. + // docs:start:insert pub fn insert( &mut self, key: K, @@ -309,14 +320,15 @@ impl HashMap { K: Eq + Hash, B: BuildHasher, H: Hasher { + // docs:end:insert self.assert_load_factor(); let hash = self.hash(key); - let mut break = false; + let mut should_break = false; for attempt in 0..N { - if !break { - let index = self.quadratic_probe(hash, attempt as u64); + if !should_break { + let index = self.quadratic_probe(hash, attempt as u32); let mut slot = self._table[index]; let mut insert = false; @@ -334,13 +346,14 @@ impl HashMap { if insert { slot.set(key, value); self._table[index] = slot; - break = true; + should_break = true; } } } } - // Remove key-value entry. If key is not present, HashMap remains unchanged. + // Removes a key-value entry. If key is not present, HashMap remains unchanged. + // docs:start:remove pub fn remove( &mut self, key: K @@ -349,12 +362,13 @@ impl HashMap { K: Eq + Hash, B: BuildHasher, H: Hasher { + // docs:end:remove let hash = self.hash(key); - let mut break = false; + let mut should_break = false; for attempt in 0..N { - if !break { - let index = self.quadratic_probe(hash, attempt as u64); + if !should_break { + let index = self.quadratic_probe(hash, attempt as u32); let mut slot = self._table[index]; // Not marked as deleted and has key-value. @@ -364,7 +378,7 @@ impl HashMap { slot.mark_deleted(); self._table[index] = slot; self._len -= 1; - break = true; + should_break = true; } } } @@ -375,21 +389,21 @@ impl HashMap { fn hash( self, key: K - ) -> u64 + ) -> u32 where K: Hash, B: BuildHasher, H: Hasher { let mut hasher = self._build_hasher.build_hasher(); key.hash(&mut hasher); - hasher.finish() as u64 + hasher.finish() as u32 } // Probing scheme: quadratic function. // We use 0.5 constant near variadic attempt and attempt^2 monomials. // This ensures good uniformity of distribution for table sizes // equal to prime numbers or powers of two. - fn quadratic_probe(_self: Self, hash: u64, attempt: u64) -> u64 { + fn quadratic_probe(_self: Self, hash: u32, attempt: u32) -> u32 { (hash + (attempt + attempt * attempt) / 2) % N } @@ -409,6 +423,7 @@ impl HashMap { // Equality class on HashMap has to test that they have // equal sets of key-value entries, // thus one is a subset of the other and vice versa. +// docs:start:eq impl Eq for HashMap where K: Eq + Hash, @@ -416,7 +431,8 @@ where B: BuildHasher, H: Hasher { - fn eq(self, other: HashMap) -> bool{ + fn eq(self, other: HashMap) -> bool { +// docs:end:eq let mut equal = false; if self.len() == other.len(){ @@ -443,12 +459,14 @@ where } } +// docs:start:default impl Default for HashMap where B: BuildHasher + Default, H: Hasher + Default { - fn default() -> Self{ + fn default() -> Self { +// docs:end:default let _build_hasher = B::default(); let map: HashMap = HashMap::with_hasher(_build_hasher); map diff --git a/noir_stdlib/src/collections/vec.nr b/noir_stdlib/src/collections/vec.nr index deec98185ff..18aaa8b9b3b 100644 --- a/noir_stdlib/src/collections/vec.nr +++ b/noir_stdlib/src/collections/vec.nr @@ -5,7 +5,7 @@ struct Vec { // A separate type is technically not needed but helps differentiate which operations are mutable. impl Vec { pub fn new() -> Self { - Self { slice: [] } + Self { slice: &[] } } // Create a Vec containing each element from the given slice. @@ -17,7 +17,7 @@ impl Vec { /// Get an element from the vector at the given index. /// Panics if the given index /// points beyond the end of the vector. - pub fn get(self, index: u64) -> T { + pub fn get(self, index: u32) -> T { self.slice[index] } @@ -40,20 +40,20 @@ impl Vec { /// Insert an element at a specified index, shifting all elements /// after it to the right - pub fn insert(&mut self, index: u64, elem: T) { + pub fn insert(&mut self, index: u32, elem: T) { self.slice = self.slice.insert(index, elem); } /// Remove an element at a specified index, shifting all elements /// after it to the left, returning the removed element - pub fn remove(&mut self, index: u64) -> T { + pub fn remove(&mut self, index: u32) -> T { let (new_slice, elem) = self.slice.remove(index); self.slice = new_slice; elem } /// Returns the number of elements in the vector - pub fn len(self) -> u64 { + pub fn len(self) -> u32 { self.slice.len() } } diff --git a/noir_stdlib/src/convert.nr b/noir_stdlib/src/convert.nr index 00ac0a0fd8c..d3537df3c5e 100644 --- a/noir_stdlib/src/convert.nr +++ b/noir_stdlib/src/convert.nr @@ -12,12 +12,12 @@ impl From for T { // docs:start:into-trait trait Into { - fn into(input: Self) -> T; + fn into(self) -> T; } impl Into for U where T: From { - fn into(input: U) -> T { - T::from(input) + fn into(self) -> T { + T::from(self) } } // docs:end:into-trait diff --git a/noir_stdlib/src/default.nr b/noir_stdlib/src/default.nr index 32c4f3f3b48..bd2f1ce0cd2 100644 --- a/noir_stdlib/src/default.nr +++ b/noir_stdlib/src/default.nr @@ -23,6 +23,12 @@ impl Default for [T; N] where T: Default { } } +impl Default for [T] { + fn default() -> [T] { + &[] + } +} + impl Default for (A, B) where A: Default, B: Default { fn default() -> (A, B) { (A::default(), B::default()) diff --git a/noir_stdlib/src/ecdsa_secp256k1.nr b/noir_stdlib/src/ecdsa_secp256k1.nr index b72a1acd041..f84e2221f57 100644 --- a/noir_stdlib/src/ecdsa_secp256k1.nr +++ b/noir_stdlib/src/ecdsa_secp256k1.nr @@ -8,3 +8,15 @@ pub fn verify_signature( ) -> bool // docs:end:ecdsa_secp256k1 {} + +#[foreign(ecdsa_secp256k1)] +// docs:start:ecdsa_secp256k1_slice +pub fn verify_signature_slice( + public_key_x: [u8; 32], + public_key_y: [u8; 32], + signature: [u8; 64], + message_hash: [u8] +) -> bool +// docs:end:ecdsa_secp256k1_slice +{} + diff --git a/noir_stdlib/src/ecdsa_secp256r1.nr b/noir_stdlib/src/ecdsa_secp256r1.nr index ef92bf24ae4..76e68aeeafa 100644 --- a/noir_stdlib/src/ecdsa_secp256r1.nr +++ b/noir_stdlib/src/ecdsa_secp256r1.nr @@ -8,3 +8,14 @@ pub fn verify_signature( ) -> bool // docs:end:ecdsa_secp256r1 {} + +#[foreign(ecdsa_secp256r1)] +// docs:start:ecdsa_secp256r1_slice +pub fn verify_signature_slice( + public_key_x: [u8; 32], + public_key_y: [u8; 32], + signature: [u8; 64], + message_hash: [u8] +) -> bool +// docs:end:ecdsa_secp256r1_slice +{} diff --git a/noir_stdlib/src/eddsa.nr b/noir_stdlib/src/eddsa.nr index 657e791e9c7..337969be90e 100644 --- a/noir_stdlib/src/eddsa.nr +++ b/noir_stdlib/src/eddsa.nr @@ -1,6 +1,9 @@ use crate::hash::poseidon; use crate::ec::consts::te::baby_jubjub; use crate::ec::tecurve::affine::Point as TEPoint; +use crate::hash::{Hash, Hasher, BuildHasher, BuildHasherDefault}; +use crate::hash::poseidon::PoseidonHasher; +use crate::default::Default; // Returns true if signature is valid pub fn eddsa_poseidon_verify( @@ -11,6 +14,25 @@ pub fn eddsa_poseidon_verify( signature_r8_y: Field, message: Field ) -> bool { + eddsa_verify::( + pub_key_x, + pub_key_y, + signature_s, + signature_r8_x, + signature_r8_y, + message + ) +} + +pub fn eddsa_verify( + pub_key_x: Field, + pub_key_y: Field, + signature_s: Field, + signature_r8_x: Field, + signature_r8_y: Field, + message: Field +) -> bool +where H: Hasher + Default { // Verifies by testing: // S * B8 = R8 + H(R8, A, m) * A8 let bjj = baby_jubjub(); @@ -23,7 +45,13 @@ pub fn eddsa_poseidon_verify( // Ensure S < Subgroup Order assert(signature_s.lt(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 mut hasher = H::default(); + hasher.write(signature_r8_x); + hasher.write(signature_r8_y); + hasher.write(pub_key_x); + hasher.write(pub_key_y); + hasher.write(message); + let hash: Field = hasher.finish(); // 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); @@ -38,3 +66,10 @@ pub fn eddsa_poseidon_verify( left.eq(right) } + +// Returns the public key of the given secret key as (pub_key_x, pub_key_y) +pub fn eddsa_to_pub(secret: Field) -> (Field, Field) { + let bjj = baby_jubjub(); + let pub_key = bjj.curve.mul(secret, bjj.curve.gen); + (pub_key.x, pub_key.y) +} diff --git a/noir_stdlib/src/embedded_curve_ops.nr b/noir_stdlib/src/embedded_curve_ops.nr new file mode 100644 index 00000000000..cd8c421e136 --- /dev/null +++ b/noir_stdlib/src/embedded_curve_ops.nr @@ -0,0 +1,98 @@ +use crate::ops::arith::{Add, Sub, Neg}; +use crate::cmp::Eq; + +// TODO(https://github.com/noir-lang/noir/issues/4931) +struct EmbeddedCurvePoint { + x: Field, + y: Field, + is_infinite: bool +} + +impl EmbeddedCurvePoint { + fn double(self) -> EmbeddedCurvePoint { + embedded_curve_add(self, self) + } + + fn point_at_infinity() -> EmbeddedCurvePoint { + EmbeddedCurvePoint { x: 0, y: 0, is_infinite: true } + } +} + +impl Add for EmbeddedCurvePoint { + fn add(self, other: EmbeddedCurvePoint) -> EmbeddedCurvePoint { + embedded_curve_add(self, other) + } +} + +impl Sub for EmbeddedCurvePoint { + fn sub(self, other: EmbeddedCurvePoint) -> EmbeddedCurvePoint { + self + other.neg() + } +} + +impl Neg for EmbeddedCurvePoint { + fn neg(self) -> EmbeddedCurvePoint { + EmbeddedCurvePoint { + x: self.x, + y: -self.y, + is_infinite: self.is_infinite + } + } +} + +impl Eq for EmbeddedCurvePoint { + fn eq(self: Self, b: EmbeddedCurvePoint) -> bool { + (self.is_infinite & b.is_infinite) | ((self.is_infinite == b.is_infinite) & (self.x == b.x) & (self.y == b.y)) + } +} + +// Scalar represented as low and high limbs +struct EmbeddedCurveScalar { + lo: Field, + hi: Field, +} + +// Computes a multi scalar multiplication over the embedded curve. +// For bn254, We have Grumpkin and Baby JubJub. +// For bls12-381, we have JubJub and Bandersnatch. +// +// The embedded curve being used is decided by the +// underlying proof system. +#[foreign(multi_scalar_mul)] +// docs:start:multi_scalar_mul +pub fn multi_scalar_mul( + points: [EmbeddedCurvePoint; N], + scalars: [EmbeddedCurveScalar; N] +) -> [Field; 3] +// docs:end:multi_scalar_mul +{} + +// docs:start:fixed_base_scalar_mul +pub fn fixed_base_scalar_mul( + scalar_low: Field, + scalar_high: Field +) -> [Field; 3] +// docs:end:fixed_base_scalar_mul +{ + let g1 = EmbeddedCurvePoint { x: 1, y: 17631683881184975370165255887551781615748388533673675138860, is_infinite: false }; + let scalar = EmbeddedCurveScalar { lo: scalar_low, hi: scalar_high }; + multi_scalar_mul([g1], [scalar]) +} + +// This is a hack as returning an `EmbeddedCurvePoint` from a foreign function in brillig returns a [BrilligVariable::SingleAddr; 2] rather than BrilligVariable::BrilligArray +// as is defined in the brillig bytecode format. This is a workaround which allows us to fix this without modifying the serialization format. +// docs:start:embedded_curve_add +fn embedded_curve_add( + point1: EmbeddedCurvePoint, + point2: EmbeddedCurvePoint +) -> EmbeddedCurvePoint +// docs:end:embedded_curve_add +{ + let point_array = embedded_curve_add_array_return(point1, point2); + let x = point_array[0]; + let y = point_array[1]; + EmbeddedCurvePoint { x, y, is_infinite: point_array[2] == 1 } +} + +#[foreign(embedded_curve_add)] +fn embedded_curve_add_array_return(_point1: EmbeddedCurvePoint, _point2: EmbeddedCurvePoint) -> [Field; 3] {} diff --git a/noir_stdlib/src/field.nr b/noir_stdlib/src/field.nr index 0f4c2caffdf..b876bcc967b 100644 --- a/noir_stdlib/src/field.nr +++ b/noir_stdlib/src/field.nr @@ -97,7 +97,7 @@ 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 +// Convert a 32 byte array to a field element by modding pub fn bytes32_to_field(bytes32: [u8; 32]) -> Field { // Convert it to a field element let mut v = 1; diff --git a/noir_stdlib/src/field/bn254.nr b/noir_stdlib/src/field/bn254.nr index 0931ef3ca25..dbb6cdb7d11 100644 --- a/noir_stdlib/src/field/bn254.nr +++ b/noir_stdlib/src/field/bn254.nr @@ -1,11 +1,13 @@ +use crate::runtime::is_unconstrained; + // The low and high decomposition of the field modulus global PLO: Field = 53438638232309528389504892708671455233; global PHI: Field = 64323764613183177041862057485226039389; global TWO_POW_128: Field = 0x100000000000000000000000000000000; -/// A hint for decomposing a single field into two 16 byte fields. -unconstrained fn decompose_unsafe(x: Field) -> (Field, Field) { +// Decomposes a single field into two 16 byte fields. +fn compute_decomposition(x: Field) -> (Field, Field) { let x_bytes = x.to_le_bytes(32); let mut low: Field = 0; @@ -21,38 +23,13 @@ unconstrained fn decompose_unsafe(x: Field) -> (Field, Field) { (low, high) } -/// Decompose a single field into two 16 byte fields. -pub fn decompose(x: Field) -> (Field, Field) { - // Take hints of the decomposition - let (xlo, xhi) = unsafe { - let (xlo, xhi) = decompose_unsafe(x); - - // Range check the limbs - xlo.assert_max_bit_size(128); - xhi.assert_max_bit_size(128); - - // Check that the decomposition is correct - assert_eq(x, xlo + TWO_POW_128 * xhi); - - (xlo, xhi) - }; - - - let borrow = unsafe {lt_unsafe(PLO, xlo, 16)}; - - // Check that (xlo < plo && xhi <= phi) || (xlo >= plo && xhi < phi) - let rlo = PLO - xlo + (borrow as Field) * TWO_POW_128; - let rhi = PHI - xhi - (borrow as Field); - - rlo.assert_max_bit_size(128); - rhi.assert_max_bit_size(128); - - (xlo, xhi) +unconstrained fn decompose_hint(x: Field) -> (Field, Field) { + compute_decomposition(x) } -unconstrained fn lt_unsafe(x: Field, y: Field, num_bytes: u32) -> bool { - let x_bytes = x.__to_le_radix(256, num_bytes); - let y_bytes = y.__to_le_radix(256, num_bytes); +fn compute_lt(x: Field, y: Field, num_bytes: u32) -> bool { + let x_bytes = x.to_le_radix(256, num_bytes); + let y_bytes = y.to_le_radix(256, num_bytes); let mut x_is_lt = false; let mut done = false; for i in 0..num_bytes { @@ -69,23 +46,71 @@ unconstrained fn lt_unsafe(x: Field, y: Field, num_bytes: u32) -> bool { x_is_lt } -unconstrained fn lte_unsafe(x: Field, y: Field, num_bytes: u32) -> bool { - lt_unsafe(x, y, num_bytes) | (x == y) +fn compute_lte(x: Field, y: Field, num_bytes: u32) -> bool { + if x == y { + true + } else { + compute_lt(x, y, num_bytes) + } } -pub fn assert_gt(a: Field, b: Field) { - // Decompose a and b - let (alo, ahi) = decompose(a); - let (blo, bhi) = decompose(b); +unconstrained fn lt_32_hint(x: Field, y: Field) -> bool { + compute_lt(x, y, 32) +} - let borrow = unsafe { lte_unsafe(alo, blo, 16) }; +unconstrained fn lte_16_hint(x: Field, y: Field) -> bool { + compute_lte(x, y, 16) +} + +// Assert that (alo > blo && ahi >= bhi) || (alo <= blo && ahi > bhi) +fn assert_gt_limbs(a: (Field, Field), b: (Field, Field)) { + let (alo, ahi) = a; + let (blo, bhi) = b; + unsafe { + let borrow = lte_16_hint(alo, blo); - // Assert that (alo > blo && ahi >= bhi) || (alo <= blo && ahi > bhi) - let rlo = alo - blo - 1 + (borrow as Field) * TWO_POW_128; - let rhi = ahi - bhi - (borrow as Field); + let rlo = alo - blo - 1 + (borrow as Field) * TWO_POW_128; + let rhi = ahi - bhi - (borrow as Field); - rlo.assert_max_bit_size(128); - rhi.assert_max_bit_size(128); + rlo.assert_max_bit_size(128); + rhi.assert_max_bit_size(128); + } +} + +/// Decompose a single field into two 16 byte fields. +pub fn decompose(x: Field) -> (Field, Field) { + if is_unconstrained() { + compute_decomposition(x) + } else { + unsafe { + // Take hints of the decomposition + let (xlo, xhi) = decompose_hint(x); + + // Range check the limbs + xlo.assert_max_bit_size(128); + xhi.assert_max_bit_size(128); + + // Check that the decomposition is correct + assert_eq(x, xlo + TWO_POW_128 * xhi); + + // Assert that the decomposition of P is greater than the decomposition of x + assert_gt_limbs((PLO, PHI), (xlo, xhi)); + (xlo, xhi) + } + } +} + +pub fn assert_gt(a: Field, b: Field) { + if is_unconstrained() { + assert(compute_lt(b, a, 32)); + } else { + // Decompose a and b + let a_limbs = decompose(a); + let b_limbs = decompose(b); + + // Assert that a_limbs is greater than b_limbs + assert_gt_limbs(a_limbs, b_limbs) + } } pub fn assert_lt(a: Field, b: Field) { @@ -93,22 +118,123 @@ pub fn assert_lt(a: Field, b: Field) { } pub fn gt(a: Field, b: Field) -> bool { - if a == b { + if is_unconstrained() { + compute_lt(b, a, 32) + } else if a == b { false - } else { - let a_lt_b = unsafe {lt_unsafe(a, b, 32) }; - if a_lt_b { - assert_gt(b, a); - false - } else { - assert_gt(a, b); - true + } else { + // Take a hint of the comparison and verify it + unsafe { + if lt_32_hint(a, b) { + assert_gt(b, a); + false + } else { + assert_gt(a, b); + true + } } } - - } pub fn lt(a: Field, b: Field) -> bool { gt(b, a) } + +mod tests { + // TODO: Allow imports from "super" + use crate::field::bn254::{decompose_hint, decompose, compute_lt, assert_gt, gt, lt, TWO_POW_128, compute_lte, PLO, PHI}; + + #[test] + fn check_decompose() { + assert_eq(decompose(TWO_POW_128), (0, 1)); + assert_eq(decompose(TWO_POW_128 + 0x1234567890), (0x1234567890, 1)); + assert_eq(decompose(0x1234567890), (0x1234567890, 0)); + } + + #[test] + unconstrained fn check_decompose_unconstrained() { + assert_eq(decompose(TWO_POW_128), (0, 1)); + assert_eq(decompose(TWO_POW_128 + 0x1234567890), (0x1234567890, 1)); + assert_eq(decompose(0x1234567890), (0x1234567890, 0)); + } + + #[test] + fn check_compute_lt() { + assert(compute_lt(0, 1, 16)); + assert(compute_lt(0, 0x100, 16)); + assert(compute_lt(0x100, TWO_POW_128 - 1, 16)); + assert(!compute_lt(0, TWO_POW_128, 16)); + } + + #[test] + fn check_compute_lte() { + assert(compute_lte(0, 1, 16)); + assert(compute_lte(0, 0x100, 16)); + assert(compute_lte(0x100, TWO_POW_128 - 1, 16)); + assert(!compute_lte(0, TWO_POW_128, 16)); + + assert(compute_lte(0, 0, 16)); + assert(compute_lte(0x100, 0x100, 16)); + assert(compute_lte(TWO_POW_128 - 1, TWO_POW_128 - 1, 16)); + assert(compute_lte(TWO_POW_128, TWO_POW_128, 16)); + } + + #[test] + fn check_assert_gt() { + assert_gt(1, 0); + assert_gt(0x100, 0); + assert_gt((0 - 1), (0 - 2)); + assert_gt(TWO_POW_128, 0); + assert_gt(0 - 1, 0); + } + + #[test] + unconstrained fn check_assert_gt_unconstrained() { + assert_gt(1, 0); + assert_gt(0x100, 0); + assert_gt((0 - 1), (0 - 2)); + assert_gt(TWO_POW_128, 0); + assert_gt(0 - 1, 0); + } + + #[test] + fn check_gt() { + assert(gt(1, 0)); + assert(gt(0x100, 0)); + assert(gt((0 - 1), (0 - 2))); + assert(gt(TWO_POW_128, 0)); + assert(!gt(0, 0)); + assert(!gt(0, 0x100)); + assert(gt(0 - 1, 0 - 2)); + assert(!gt(0 - 2, 0 - 1)); + } + + #[test] + unconstrained fn check_gt_unconstrained() { + assert(gt(1, 0)); + assert(gt(0x100, 0)); + assert(gt((0 - 1), (0 - 2))); + assert(gt(TWO_POW_128, 0)); + assert(!gt(0, 0)); + assert(!gt(0, 0x100)); + assert(gt(0 - 1, 0 - 2)); + assert(!gt(0 - 2, 0 - 1)); + } + + #[test] + fn check_plo_phi() { + assert_eq(PLO + PHI * TWO_POW_128, 0); + let p_bytes = crate::field::modulus_le_bytes(); + let mut p_low: Field = 0; + let mut p_high: Field = 0; + + let mut offset = 1; + for i in 0..16 { + p_low += (p_bytes[i] as Field) * offset; + p_high += (p_bytes[i + 16] as Field) * offset; + offset *= 256; + } + assert_eq(p_low, PLO); + assert_eq(p_high, PHI); + } +} diff --git a/noir_stdlib/src/grumpkin_scalar.nr b/noir_stdlib/src/grumpkin_scalar.nr deleted file mode 100644 index d05158488f4..00000000000 --- a/noir_stdlib/src/grumpkin_scalar.nr +++ /dev/null @@ -1,21 +0,0 @@ -struct GrumpkinScalar { - low: Field, - high: Field, -} - -impl GrumpkinScalar { - pub fn new(low: Field, high: Field) -> Self { - // TODO: check that the low and high value fit within the grumpkin modulus - GrumpkinScalar { low, high } - } -} - -global GRUMPKIN_SCALAR_SERIALIZED_LEN: Field = 2; - -pub fn deserialize_grumpkin_scalar(fields: [Field; GRUMPKIN_SCALAR_SERIALIZED_LEN]) -> GrumpkinScalar { - GrumpkinScalar { low: fields[0], high: fields[1] } -} - -pub fn serialize_grumpkin_scalar(scalar: GrumpkinScalar) -> [Field; GRUMPKIN_SCALAR_SERIALIZED_LEN] { - [scalar.low, scalar.high] -} diff --git a/noir_stdlib/src/grumpkin_scalar_mul.nr b/noir_stdlib/src/grumpkin_scalar_mul.nr deleted file mode 100644 index 06d30d62332..00000000000 --- a/noir_stdlib/src/grumpkin_scalar_mul.nr +++ /dev/null @@ -1,7 +0,0 @@ -use crate::grumpkin_scalar::GrumpkinScalar; -use crate::scalar_mul::fixed_base_embedded_curve; - -pub fn grumpkin_fixed_base(scalar: GrumpkinScalar) -> [Field; 2] { - // TODO: this should use both the low and high limbs to do the scalar multiplication - fixed_base_embedded_curve(scalar.low, scalar.high) -} diff --git a/noir_stdlib/src/hash.nr b/noir_stdlib/src/hash.nr index fcf21436197..6c295d127ab 100644 --- a/noir_stdlib/src/hash.nr +++ b/noir_stdlib/src/hash.nr @@ -1,9 +1,11 @@ mod poseidon; mod mimc; mod poseidon2; -mod pedersen; use crate::default::Default; +use crate::uint128::U128; +use crate::sha256::{digest, sha256_var}; +use crate::embedded_curve_ops::EmbeddedCurvePoint; #[foreign(sha256)] // docs:start:sha256 @@ -24,23 +26,17 @@ pub fn blake3(input: [u8; N]) -> [u8; 32] {} // docs:start:pedersen_commitment -struct PedersenPoint { - x : Field, - y : Field, -} - -pub fn pedersen_commitment(input: [Field; N]) -> PedersenPoint -// docs:end:pedersen_commitment -{ +pub fn pedersen_commitment(input: [Field; N]) -> EmbeddedCurvePoint { + // docs:end:pedersen_commitment pedersen_commitment_with_separator(input, 0) } #[foreign(pedersen_commitment)] pub fn __pedersen_commitment_with_separator(input: [Field; N], separator: u32) -> [Field; 2] {} -pub fn pedersen_commitment_with_separator(input: [Field; N], separator: u32) -> PedersenPoint { +pub fn pedersen_commitment_with_separator(input: [Field; N], separator: u32) -> EmbeddedCurvePoint { let values = __pedersen_commitment_with_separator(input, separator); - PedersenPoint { x: values[0], y: values[1] } + EmbeddedCurvePoint { x: values[0], y: values[1], is_infinite: false } } // docs:start:pedersen_hash @@ -53,18 +49,15 @@ pub fn pedersen_hash(input: [Field; N]) -> Field #[foreign(pedersen_hash)] pub fn pedersen_hash_with_separator(input: [Field; N], separator: u32) -> Field {} -pub fn hash_to_field(input: [Field; N]) -> Field { - let mut inputs_as_bytes = []; +pub fn hash_to_field(inputs: [Field]) -> Field { + let mut sum = 0; - 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]); - } + for input in inputs { + let input_bytes: [u8; 32] = input.to_le_bytes(32).as_array(); + sum += crate::field::bytes32_to_field(blake2s(input_bytes)); } - let hashed_input = blake2s(inputs_as_bytes); - crate::field::bytes32_to_field(hashed_input) + sum } #[foreign(keccak256)] @@ -92,7 +85,7 @@ trait Hash{ trait Hasher{ fn finish(self) -> Field; - fn write(&mut self, input: [Field]); + fn write(&mut self, input: Field); } // BuildHasher is a factory trait, responsible for production of specific Hasher. @@ -120,10 +113,112 @@ where } } -// TODO: add implementations for the remainder of primitive types. -impl Hash for Field{ +impl Hash for Field { + fn hash(self, state: &mut H) where H: Hasher{ + H::write(state, self); + } +} + +impl Hash for u8 { + fn hash(self, state: &mut H) where H: Hasher{ + H::write(state, self as Field); + } +} + +impl Hash for u32 { + fn hash(self, state: &mut H) where H: Hasher{ + H::write(state, self as Field); + } +} + +impl Hash for u64 { + fn hash(self, state: &mut H) where H: Hasher{ + H::write(state, self as Field); + } +} + +impl Hash for i8 { + fn hash(self, state: &mut H) where H: Hasher{ + H::write(state, self as Field); + } +} + +impl Hash for i32 { + fn hash(self, state: &mut H) where H: Hasher{ + H::write(state, self as Field); + } +} + +impl Hash for i64 { + fn hash(self, state: &mut H) where H: Hasher{ + H::write(state, self as Field); + } +} + +impl Hash for bool { + fn hash(self, state: &mut H) where H: Hasher{ + H::write(state, self as Field); + } +} + +impl Hash for () { + fn hash(_self: Self, _state: &mut H) where H: Hasher {} +} + +impl Hash for U128 { + fn hash(self, state: &mut H) where H: Hasher{ + H::write(state, self.lo as Field); + H::write(state, self.hi as Field); + } +} + +impl Hash for [T; N] where T: Hash { + fn hash(self, state: &mut H) where H: Hasher{ + for elem in self { + elem.hash(state); + } + } +} + +impl Hash for [T] where T: Hash { + fn hash(self, state: &mut H) where H: Hasher{ + self.len().hash(state); + for elem in self { + elem.hash(state); + } + } +} + +impl Hash for (A, B) where A: Hash, B: Hash { + fn hash(self, state: &mut H) where H: Hasher{ + self.0.hash(state); + self.1.hash(state); + } +} + +impl Hash for (A, B, C) where A: Hash, B: Hash, C: Hash { + fn hash(self, state: &mut H) where H: Hasher{ + self.0.hash(state); + self.1.hash(state); + self.2.hash(state); + } +} + +impl Hash for (A, B, C, D) where A: Hash, B: Hash, C: Hash, D: Hash { + fn hash(self, state: &mut H) where H: Hasher{ + self.0.hash(state); + self.1.hash(state); + self.2.hash(state); + self.3.hash(state); + } +} + +impl Hash for (A, B, C, D, E) where A: Hash, B: Hash, C: Hash, D: Hash, E: Hash { fn hash(self, state: &mut H) where H: Hasher{ - let input: [Field] = [self]; - H::write(state, input); + self.0.hash(state); + self.1.hash(state); + self.2.hash(state); + self.3.hash(state); + self.4.hash(state); } } diff --git a/noir_stdlib/src/hash/mimc.nr b/noir_stdlib/src/hash/mimc.nr index 10c0a48917c..6c5502c2fbf 100644 --- a/noir_stdlib/src/hash/mimc.nr +++ b/noir_stdlib/src/hash/mimc.nr @@ -1,3 +1,6 @@ +use crate::hash::Hasher; +use crate::default::Default; + // 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 @@ -16,13 +19,8 @@ fn mimc(x: Field, k: Field, constants: [Field; N], exp: Field) -> Field { } 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] = [ +//generated from seed "mimc" using keccak256 +global MIMC_BN254_CONSTANTS: [Field; MIMC_BN254_ROUNDS] = [ 0, 20888961410941983456478427210666206549300505294776164667214940546594746570981, 15265126113435022738560151911929040668591755459209400716467504685752745317193, @@ -116,10 +114,43 @@ pub fn mimc_bn254(array: [Field; N]) -> Field { 13602139229813231349386885113156901793661719180900395818909719758150455500533 ]; +//mimc implementation with hardcoded parameters for BN254 curve. +#[field(bn254)] +pub fn mimc_bn254(array: [Field; N]) -> Field { + let exponent = 7; let mut r = 0; for elem in array { - let h = mimc(elem, r, constants, exponent); + let h = mimc(elem, r, MIMC_BN254_CONSTANTS, exponent); r = r + elem + h; } r } + +struct MimcHasher { + _state: [Field], +} + +impl Hasher for MimcHasher { + #[field(bn254)] + fn finish(self) -> Field { + let exponent = 7; + let mut r = 0; + for i in 0..self._state.len() { + let h = mimc(self._state[i], r, MIMC_BN254_CONSTANTS, exponent); + r = r + self._state[i] + h; + } + r + } + + fn write(&mut self, input: Field){ + self._state = self._state.push_back(input); + } +} + +impl Default for MimcHasher{ + fn default() -> Self{ + MimcHasher { + _state: &[], + } + } +} diff --git a/noir_stdlib/src/hash/pedersen.nr b/noir_stdlib/src/hash/pedersen.nr deleted file mode 100644 index ace6851099d..00000000000 --- a/noir_stdlib/src/hash/pedersen.nr +++ /dev/null @@ -1,24 +0,0 @@ -use crate::hash::{Hasher, pedersen_hash}; -use crate::default::Default; - -struct PedersenHasher{ - _state: [Field] -} - -impl Hasher for PedersenHasher { - fn finish(self) -> Field { - pedersen_hash(self._state) - } - - fn write(&mut self, input: [Field]){ - self._state = self._state.append(input); - } -} - -impl Default for PedersenHasher{ - fn default() -> Self{ - PedersenHasher{ - _state: [] - } - } -} diff --git a/noir_stdlib/src/hash/poseidon.nr b/noir_stdlib/src/hash/poseidon.nr index b1a7c4a2367..c4b5f0fcb6f 100644 --- a/noir_stdlib/src/hash/poseidon.nr +++ b/noir_stdlib/src/hash/poseidon.nr @@ -1,66 +1,136 @@ mod bn254; // Instantiations of Poseidon for prime field of the same order as BN254 use crate::field::modulus_num_bits; +use crate::hash::Hasher; +use crate::default::Default; -struct PoseidonConfig { - t: Field, // Width, i.e. state size - rf: u8, // Number of full rounds; should be even - rp: u8, // Number of partial rounds - alpha: Field, // S-box power; depends on the underlying field - ark: [Field; M], // Additive round keys - mds: [Field; N] // MDS Matrix in row-major order +// A config struct defining the parameters of the Poseidon instance to use. +// +// A thorough writeup of this method (along with an unoptimized method) can be found at: https://spec.filecoin.io/algorithms/crypto/poseidon/ +struct PoseidonConfig { + // State width, should be equal to `T` + t: Field, + // Number of full rounds. should be even + rf: u8, + // Number of partial rounds + rp: u8, + // S-box power; depends on the underlying field + alpha: Field, + // The round constants for the + round_constants: [Field; N], + // The MDS matrix for the Poseidon instance + mds: [[Field; T]; T], + // An MDS matrix which also applies a basis transformation which allows + // sparse matrices to be used for the partial rounds. + // + // This should be applied instead of `mds` in the final full round. + presparse_mds: [[Field; T]; T], + // A set of sparse matrices used for MDS mixing for the partial rounds. + sparse_mds: [Field; X], } -pub fn config( +pub fn config( t: Field, rf: u8, rp: u8, alpha: Field, - ark: [Field; M], - mds: [Field; N] -) -> PoseidonConfig { + round_constants: [Field; N], + mds: [[Field; T]; T], + presparse_mds: [[Field; T]; T], + sparse_mds: [Field; X] +) -> PoseidonConfig { // Input checks - let mul = crate::wrapping_mul(t as u8, (rf + rp)); - assert(mul == ark.len() as u8); - assert(t * t == mds.len() as Field); + assert_eq(rf & 1, 0); + assert_eq((t as u8) * rf + rp, N); + assert_eq(t, T); assert(alpha != 0); - PoseidonConfig { t, rf, rp, alpha, ark, mds } + PoseidonConfig { t, rf, rp, alpha, round_constants, mds, presparse_mds, sparse_mds } } -// General Poseidon permutation on elements of type Field -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() as Field); +pub fn permute(pos_conf: PoseidonConfig, mut state: [Field; T]) -> [Field; T] { + let PoseidonConfig {t, rf, rp, alpha, round_constants, mds, presparse_mds, sparse_mds } = pos_conf; - let mut count = 0; - // for r in 0..rf + rp - 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 + for i in 0..state.len() { + state[i] += round_constants[i]; + } + + for _r in 0..rf / 2 - 1 { + state = sigma(state); + for i in 0..T { + state[i] += round_constants[T * (_r + 1) as u32 + i]; + } + state = apply_matrix(mds, state); + } + + state = sigma(state); + for i in 0..T { + state[i] += round_constants[T * (rf / 2) as u32 + i]; + } + state = apply_matrix(presparse_mds, state); + + for i in 0..T { + crate::as_witness(state[i]); + } + + for _r in 0..rp { 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) { - for i in 1..state.len() { - state[i] = state[i].pow_32(alpha); + state[0] += round_constants[(rf/2 + 1) as u32 * T + _r as u32]; + crate::as_witness(state[0]); + { + let mut newState0 = 0; + for j in 0..T { + newState0 += sparse_mds[(T * 2 - 1) * _r as u32 + j as u32] * state[j]; + } + for k in 1..T { + state[k] += state[0] * sparse_mds[(t * 2 - 1) as u32 * _r as u32 + T + k - 1]; + } + state[0] = newState0; + + if (_r & 1 == 0) { + for k in 1..T { + crate::as_witness(state[k]); + } } } + } - state = apply_matrix(mds, state); // Apply MDS matrix - count = count + t as u64; + for _r in 0..rf / 2 - 1 { + state = sigma(state); + for i in 0..state.len() { + state[i] += round_constants[(rf/2+1) as u32 * T + rp as u32 + (_r as u32) * T + i]; + } + state = apply_matrix(mds, state); } + state = sigma(state); + state = apply_matrix(mds, state); + state } -// Absorption. Fully absorbs input message. -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] -) -> [Field; O] { - assert(pos_conf.t == rate + capacity); + +// Performs matrix multiplication on a vector +fn apply_matrix(matrix: [[Field; N]; N], vec: [Field; N]) -> [Field; N] { + let mut out = [0; N]; + + for i in 0..N { + for j in 0..N { + out[i] += vec[j] * matrix[j][i]; + } + } + + out +} + +// Corresponding absorption. +fn absorb( + pos_conf: PoseidonConfig, + // Initial state; usually [0; O] + mut state: [Field; T], + rate: Field, + capacity: Field, + msg: [Field; O] // Arbitrary length message +) -> [Field; T] { + assert_eq(pos_conf.t, rate + capacity); let mut i = 0; @@ -81,22 +151,118 @@ fn absorb( state } + +fn sigma(x: [Field; O]) -> [Field; O] { + let mut y = x; + for i in 0..O { + let t = y[i]; + let tt = t * t; + let tttt = tt * tt; + y[i] *= tttt; + } + y +} + // Check security of sponge instantiation fn check_security(rate: Field, width: Field, security: Field) -> bool { let n = modulus_num_bits(); ((n - 1) as Field * (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; - 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]; +struct PoseidonHasher{ + _state: [Field], +} + +impl Hasher for PoseidonHasher { + #[field(bn254)] + fn finish(self) -> Field { + let mut result = 0; + let len = self._state.len(); + assert(len < 16); + if len == 1 { + result = bn254::hash_1([self._state[0]]); + } + if len == 2 { + result = bn254::hash_2([self._state[0],self._state[1]]); + } + if len == 3 { + result = bn254::hash_3([self._state[0],self._state[1],self._state[2]]); + } + if len == 4 { + result = bn254::hash_4([self._state[0],self._state[1],self._state[2],self._state[3]]); + } + if len == 5 { + result = bn254::hash_5([self._state[0],self._state[1],self._state[2],self._state[3],self._state[4]]); + } + if len == 6 { + result = bn254::hash_6([self._state[0],self._state[1],self._state[2],self._state[3],self._state[4], self._state[5]]); + } + if len == 7 { + result = bn254::hash_7([self._state[0],self._state[1],self._state[2],self._state[3],self._state[4], self._state[5], self._state[6]]); + } + if len == 8 { + result = bn254::hash_8([self._state[0],self._state[1],self._state[2],self._state[3],self._state[4], self._state[5], self._state[6], self._state[7]]); + } + if len == 9 { + result = bn254::hash_9([self._state[0],self._state[1],self._state[2],self._state[3],self._state[4], self._state[5], self._state[6], self._state[7], self._state[8]]); + } + if len == 10 { + result = bn254::hash_10([self._state[0],self._state[1],self._state[2],self._state[3],self._state[4], self._state[5], self._state[6], self._state[7], self._state[8], self._state[9]]); + } + if len == 11 { + result = bn254::hash_11([self._state[0],self._state[1],self._state[2],self._state[3],self._state[4], self._state[5], self._state[6], self._state[7], self._state[8], self._state[9], self._state[10]]); + } + if len == 12 { + result = bn254::hash_12([self._state[0],self._state[1],self._state[2],self._state[3],self._state[4], self._state[5], self._state[6], self._state[7], self._state[8], self._state[9], self._state[10], self._state[11]]); + } + if len == 13 { + result = bn254::hash_13([self._state[0],self._state[1],self._state[2],self._state[3],self._state[4], self._state[5], self._state[6], self._state[7], self._state[8], self._state[9], self._state[10], self._state[11], self._state[12]]); } + if len == 14 { + result = bn254::hash_14([self._state[0],self._state[1],self._state[2],self._state[3],self._state[4], self._state[5], self._state[6], self._state[7], self._state[8], self._state[9], self._state[10], self._state[11], self._state[12], self._state[13]]); + } + if len == 15 { + result = bn254::hash_15([self._state[0],self._state[1],self._state[2],self._state[3],self._state[4], self._state[5], self._state[6], self._state[7], self._state[8], self._state[9], self._state[10], self._state[11], self._state[12], self._state[13], self._state[14]]); + } + + result } - y + fn write(&mut self, input: Field){ + self._state = self._state.push_back(input); + } +} + +impl Default for PoseidonHasher{ + fn default() -> Self{ + PoseidonHasher{ + _state: &[], + } + } +} + +mod poseidon_tests { + use crate::hash::poseidon; + + #[test] + fn reference_impl_test_vectors() { + // hardcoded test vectors from https://extgit.iaik.tugraz.at/krypto/hadeshash/-/blob/master/code/test_vectors.txt + { + let mut state = [0, 1, 2]; + let mut expected = [ + 0x115cc0f5e7d690413df64c6b9662e9cf2a3617f2743245519e19607a4417189a, 0x0fca49b798923ab0239de1c9e7a4a9a2210312b6a2f616d18b5a87f9b628ae29, 0x0e7ae82e40091e63cbd4f16a6d16310b3729d4b6e138fcf54110e2867045a30c + ]; + assert_eq(expected, poseidon::bn254::perm::x5_3(state), "Failed to reproduce output for [0, 1, 2]"); + } + { + let mut state = [0, 1, 2, 3, 4]; + let mut expected = [ + 0x299c867db6c1fdd79dcefa40e4510b9837e60ebb1ce0663dbaa525df65250465, 0x1148aaef609aa338b27dafd89bb98862d8bb2b429aceac47d86206154ffe053d, 0x24febb87fed7462e23f6665ff9a0111f4044c38ee1672c1ac6b0637d34f24907, 0x0eb08f6d809668a981c186beaf6110060707059576406b248e5d9cf6e78b3d3e, 0x07748bc6877c9b82c8b98666ee9d0626ec7f5be4205f79ee8528ef1c4a376fc7 + ]; + assert_eq( + expected, poseidon::bn254::perm::x5_5(state), "Failed to reproduce output for [0, 1, 2, 3, 4]" + ); + } + } } diff --git a/noir_stdlib/src/hash/poseidon/bn254.nr b/noir_stdlib/src/hash/poseidon/bn254.nr index 37b08e3c8fb..54f22884e29 100644 --- a/noir_stdlib/src/hash/poseidon/bn254.nr +++ b/noir_stdlib/src/hash/poseidon/bn254.nr @@ -2,93 +2,14 @@ mod perm; 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. -#[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: u8 = 8; - let rp: u8 = [56, 57, 56, 60, 60, 63, 64, 63, 60, 66, 60, 65, 70, 60, 64, 68][state.len() - 2]; - - assert(t == state.len() as Field); - assert(rf == config_rf); - assert(rp == config_rp); - - let mut count = 0; - // First half of full rounds - 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 as u64; - } - // 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 as u64; - } - // Second half of full rounds - 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 as u64; - } - - state -} -// Corresponding absorption. -#[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 -} +use crate::hash::poseidon::{PoseidonConfig, absorb}; + // 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] } + // Various instances of the Poseidon hash function // Consistent with Circom's implementation pub fn hash_1(input: [Field; 1]) -> Field { diff --git a/noir_stdlib/src/hash/poseidon/bn254/consts.nr b/noir_stdlib/src/hash/poseidon/bn254/consts.nr index 62b5f4b5212..81d78377ce8 100644 --- a/noir_stdlib/src/hash/poseidon/bn254/consts.nr +++ b/noir_stdlib/src/hash/poseidon/bn254/consts.nr @@ -1,9 +1,11 @@ +// Parameters are generated by a reference script https://extgit.iaik.tugraz.at/krypto/hadeshash/-/blob/master/code/generate_parameters_grain.sage +// Used like so: sage generate_parameters_grain.sage 1 0 254 2 8 56 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001 + // Constants for various Poseidon instances in the case of the prime field of the same order as BN254. // 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] @@ -12,181 +14,24958 @@ fn rp() -> [u8; 16] { fn alpha() -> Field { 5 } -// Poseidon configurations for states of size 2 to 17. + // noir-fmt:ignore -pub fn x5_2_config() -> PoseidonConfig<128, 4> { +pub fn x5_2_config() -> PoseidonConfig<2, 72, 168> { config( 2, 8, 56, alpha(), - [4417881134626180770308697923359573201005643519861877412381846989312604493735,5433650512959517612316327474713065966758808864213826738576266661723522780033,13641176377184356099764086973022553863760045607496549923679278773208775739952,17949713444224994136330421782109149544629237834775211751417461773584374506783,13765628375339178273710281891027109699578766420463125835325926111705201856003,19179513468172002314585757290678967643352171735526887944518845346318719730387,5157412437176756884543472904098424903141745259452875378101256928559722612176,535160875740282236955320458485730000677124519901643397458212725410971557409,1050793453380762984940163090920066886770841063557081906093018330633089036729,10665495010329663932664894101216428400933984666065399374198502106997623173873,19965634623406616956648724894636666805991993496469370618546874926025059150737,13007250030070838431593222885902415182312449212965120303174723305710127422213,16877538715074991604507979123743768693428157847423939051086744213162455276374,18211747749504876135588847560312685184956239426147543810126553367063157141465,18151553319826126919739798892854572062191241985315767086020821632812331245635,19957033149976712666746140949846950406660099037474791840946955175819555930825,3469514863538261843186854830917934449567467100548474599735384052339577040841,989698510043911779243192466312362856042600749099921773896924315611668507708,12568377015646290945235387813564567111330046038050864455358059568128000172201,20856104135605479600325529349246932565148587186338606236677138505306779314172,8206918720503535523121349917159924938835810381723474192155637697065780938424,1309058477013932989380617265069188723120054926187607548493110334522527703566,14076116939332667074621703729512195584105250395163383769419390236426287710606,10153498892749751942204288991871286290442690932856658983589258153608012428674,18202499207234128286137597834010475797175973146805180988367589376893530181575,12739388830157083522877690211447248168864006284243907142044329113461613743052,15123358710467780770838026754240340042441262572309759635224051333176022613949,19925004701844594370904593774447343836015483888496504201331110250494635362184,10352416606816998476681131583320899030072315953910679608943150613208329645891,10567371822366244361703342347428230537114808440249611395507235283708966113221,5635498582763880627392290206431559361272660937399944184533035305989295959602,11866432933224219174041051738704352719163271639958083608224676028593315904909,5795020705294401441272215064554385591292330721703923167136157291459784140431,9482202378699252817564375087302794636287866584767523335624368774856230692758,4245237636894546151746468406560945873445548423466753843402086544922216329298,12000500941313982757584712677991730019124834399479314697467598397927435905133,7596790274058425558167520209857956363736666939016807569082239187494363541787,2484867918246116343205467273440098378820186751202461278013576281097918148877,18312645949449997391810445935615409295369169383463185688973803378104013950190,15320686572748723004980855263301182130424010735782762814513954166519592552733,12618438900597948888520621062416758747872180395546164387827245287017031303859,17438141672027706116733201008397064011774368832458707512367404736905021019585,6374197807230665998865688675365359100400438034755781666913068586172586548950,2189398913433273865510950346186699930188746169476472274335177556702504595264,6268495580028970231803791523870131137294646402347399003576649137450213034606,17896250365994900261202920044129628104272791547990619503076839618914047059275,13692156312448722528008862371944543449350293305158722920787736248435893008873,15234446864368744483209945022439268713300180233589581910497691316744177619376,1572426502623310766593681563281600503979671244997798691029595521622402217227,80103447810215150918585162168214870083573048458555897999822831203653996617,8228820324013669567851850635126713973797711779951230446503353812192849106342,5375851433746509614045812476958526065449377558695752132494533666370449415873,12115998939203497346386774317892338270561208357481805380546938146796257365018,9764067909645821279940531410531154041386008396840887338272986634350423466622,8538708244538850542384936174629541085495830544298260335345008245230827876882,7140127896620013355910287215441004676619168261422440177712039790284719613114,14297402962228458726038826185823085337698917275385741292940049024977027409762,6667115556431351074165934212337261254608231545257434281887966406956835140819,20226761165244293291042617464655196752671169026542832236139342122602741090001,12038289506489256655759141386763477208196694421666339040483042079632134429119,19027757334170818571203982241812412991528769934917288000224335655934473717551,16272152964456553579565580463468069884359929612321610357528838696790370074720,2500392889689246014710135696485946334448570271481948765283016105301740284071,8595254970528530312401637448610398388203855633951264114100575485022581946023,11635945688914011450976408058407206367914559009113158286982919675551688078198,614739068603482619581328040478536306925147663946742687395148680260956671871,18692271780377861570175282183255720350972693125537599213951106550953176268753,4987059230784976306647166378298632695585915319042844495357753339378260807164,21851403978498723616722415377430107676258664746210815234490134600998983955497,9830635451186415300891533983087800047564037813328875992115573428596207326204,4842706106434537116860242620706030229206345167233200482994958847436425185478,6422235064906823218421386871122109085799298052314922856340127798647926126490,4564364104986856861943331689105797031330091877115997069096365671501473357846,1944043894089780613038197112872830569538541856657037469098448708685350671343,21179865974855950600518216085229498748425990426231530451599322283119880194955,14296697761894107574369608843560006996183955751502547883167824879840894933162,12274619649702218570450581712439138337725246879938860735460378251639845671898,16371396450276899401411886674029075408418848209575273031725505038938314070356,3702561221750983937578095019779188631407216522704543451228773892695044653565,19721616877735564664624984774636557499099875603996426215495516594530838681980,6383350109027696789969911008057747025018308755462287526819231672217685282429,20860583956177367265984596617324237471765572961978977333122281041544719622905,5766390934595026947545001478457407504285452477687752470140790011329357286275,4043175758319898049344746138515323336207420888499903387536875603879441092484,15579382179133608217098622223834161692266188678101563820988612253342538956534,1864640783252634743892105383926602930909039567065240010338908865509831749824,15943719865023133586707144161652035291705809358178262514871056013754142625673,2326415993032390211558498780803238091925402878871059708106213703504162832999,19995326402773833553207196590622808505547443523750970375738981396588337910289,5143583711361588952673350526320181330406047695593201009385718506918735286622,15436006486881920976813738625999473183944244531070780793506388892313517319583,16660446760173633166698660166238066533278664023818938868110282615200613695857,4966065365695755376133119391352131079892396024584848298231004326013366253934,20683781957411705574951987677641476019618457561419278856689645563561076926702,17280836839165902792086432296371645107551519324565649849400948918605456875699,17045635513701208892073056357048619435743564064921155892004135325530808465371,17055032967194400710390142791334572297458033582458169295920670679093585707295,15727174639569115300068198908071514334002742825679221638729902577962862163505,1001755657610446661315902885492677747789366510875120894840818704741370398633,18638547332826171619311285502376343504539399518545103511265465604926625041234,6751954224763196429755298529194402870632445298969935050224267844020826420799,3526747115904224771452549517614107688674036840088422555827581348280834879405,15705897908180497062880001271426561999724005008972544196300715293701537574122,574386695213920937259007343820417029802510752426579750428758189312416867750,15973040855000600860816974646787367136127946402908768408978806375685439868553,20934130413948796333037139460875996342810005558806621330680156931816867321122,6918585327145564636398173845411579411526758237572034236476079610890705810764,14158163500813182062258176233162498241310167509137716527054939926126453647182,4164602626597695668474100217150111342272610479949122406544277384862187287433,12146526846507496913615390662823936206892812880963914267275606265272996025304,10153527926900017763244212043512822363696541810586522108597162891799345289938,13564663485965299104296214940873270349072051793008946663855767889066202733588,5612449256997576125867742696783020582952387615430650198777254717398552960096,12151885480032032868507892738683067544172874895736290365318623681886999930120,380452237704664384810613424095477896605414037288009963200982915188629772177,9067557551252570188533509616805287919563636482030947363841198066124642069518,21280306817619711661335268484199763923870315733198162896599997188206277056900,5567165819557297006750252582140767993422097822227408837378089569369734876257,10411936321072105429908396649383171465939606386380071222095155850987201580137,21338390051413922944780864872652000187403217966653363270851298678606449622266,12156296560457833712186127325312904760045212412680904475497938949653569234473,4271647814574748734312113971565139132510281260328947438246615707172526380757,9061738206062369647211128232833114177054715885442782773131292534862178874950,10134551893627587797380445583959894183158393780166496661696555422178052339133,8932270237664043612366044102088319242789325050842783721780970129656616386103,3339412934966886386194449782756711637636784424032779155216609410591712750636,9704903972004596791086522314847373103670545861209569267884026709445485704400,17467570179597572575614276429760169990940929887711661192333523245667228809456], - [2910766817845651019878574839501801340070030115151021261302834310722729507541,19727366863391167538122140361473584127147630672623100827934084310230022599144,5776684794125549462448597414050232243778680302179439492664047328281728356345,8348174920934122550483593999453880006756108121341067172388445916328941978568] + [ + 0x9c46e9ec68e9bd4fe1faaba294cba38a71aa177534cdd1b6c7dc0dbd0abd7a7, + 0xc0356530896eec42a97ed937f3135cfc5142b3ae405b8343c1d83ffa604cb81, + 0x250f5116a417d76aaa422952fcc5b33329f7714fc26d56c0432507fc740a87c4, + 0x264065ad87572e016659626c33c8213f7a373b9b8225a384f458d850bb4a949f, + 0x2bb8e94ad8d8adca6ce909ff94b8750729b294e4400376da39e33fda24bd42af, + 0x19051065d05d861ec813c15291d46a328f6201b21ad5d239d4f85fbb09a5dbae, + 0x245bd0617aa449618f5bd4550aac7b8e08d4d1c017165943cdf4776cdff3434a, + 0x9fb1a1118074ff79d8acbf5b02131e048a1570155e0f2b1c36ad091d491a88f, + 0x234ab504bbae8198972741952f78b7eb018ea192f05e54c1484ab8973ff66d88, + 0x1f66e509b84c355ae3d4c3513a282fd48f9c8c6439f42a7835fbcfe0f2a324c, + 0x1b22f5d69d725e6002cf00dd9ee62d1a5af0efdc4910f54127a920ccc43f91fa, + 0x252b55edead135f852968b7f1c4f490fa659ecd5b47a78a7db91f65a6dfc23f, + 0x1773ae2e1637c92ad0677c2a047fea8eca4b53303f21871f6892a2c0487d7ff1, + 0x2d57b02906cd0ab82a79e76faeef6f87666eac093cf7715645d5ec9f7ac732f5, + 0xa16f3a62824b281e8b2ddb8fc391a498fb061317faffa03696f834596313d93, + 0x1666f525f7f4b6988d2a37834ab747eae0587757b788eb7f1e26b08e36a08591, + 0x5da44f8e0a3b8bb13231f0ca25b50b57f5c82128e1dfec3e541d912ebe17b76, + 0x9a39ba9993303ba191bac8bdb3e0144dbfb5f39624cdd9524dc7861633bc95a, + 0x6c0fb824a19202d30ee6b418c0029e100e85a6d158f9f2a828dfd2ed0920a68, + 0x387d8e056b2b176a9776b4492cb3b418adc660627e52bb3324283bf9522395d, + 0x147a1af82036ef5b28a7a37bea40d6ac3013cf1b62358396bf7156f5c2dc9684, + 0x3038d92060daeaaf1bd0482bd3f0613d88e8dff90a7a0525f9227e4cb7c6f81b, + 0x72940aa1d538a5a39a323f9e5d65616cf6c223339006f9789a97245532908f5, + 0x2d3d604949f4e14c70b8a879aedec49b3a367ba216af048f464ed6f15e2b9023, + 0x225b9e4f35c7549f80774c2b4d18309b2dcf7c7287b982e49746a176641e73c5, + 0x1ea781288fdf13b2190095a2344828e37dfe81c75a09709f0d139bbbf6c70414, + 0x8e96c3e7e8de4432b202405458468b90dc6890d4cee128b3502e5b6cb4aeeeb, + 0x5b43da7c8aa29af6dcaae57d070b49d29ce889a64a4ac183e85d55b366c805f, + 0xbec98a034e3b8af7ba4861f1ad5a48dcef7c996e7a51c7cdde724d8f610e52, + 0x2eb67ccfa29e2b422b9f84a5d0575fc435b30fcae303039480be384ee4ebe72a, + 0x102bbdc21a3f147bf04eedee5d70bd084a7105c631c86ecd2c4e8749a13915ca, + 0x274bc16c88721babfd5bbe8d8562c1bf127ae38915280fbb8e3115cad3582f79, + 0x185cece417549b25283de04511f769101c8850b409d4928ab831611351bd9938, + 0x13c73fb043f7e978bc9cfb55c7faacb4f4c823674abe17737059ac0a32c36007, + 0x24b3a1d83308742b360c9c60595673e201cdd4cef5a4145c933c4e5969481d70, + 0x18b5ae94df9ec97aaa2a8f0f42425bcccdc8266a070f866ef0f48d7a3744398b, + 0x20eb398cb958cc2ccc7cb1fac38501abbe38169b2d8522d9e5f099f2d5905cb4, + 0x1e588dd3ec8b0d252c2c7c0c78a02b22bbbad1f4dcaa2e78a8b8eef2f4e29344, + 0xf8bf3bd6c22ba3b1bf3ab2e3fb40818cd4217ffbaf294ca42331d4e3043a0a6, + 0x388c9fcf30fc2841d648f46bad01dd10bee9dc184d25eabc9f617021109cec3, + 0x2bb7f397c5941ac67befa8b232f15c8853dac263da793555441a90cec83b6454, + 0x17f389b52f9ea7a98874a4a31ef6a7beb43fb17db0e499250bb3f0181c59fb21, + 0x3a2090eacb897a31fb10561d560a9aeec24b7ad14d17b145f20c875a0b28c7c, + 0xc398534f0eb580f1fe4bf64553389e67cca4714399430e09619dcbee17ba099, + 0x7095ac9fda46afa7f181259e3635feffa7f11ee63f3ee777a5cebf4822328c4, + 0x2046f7cf1c8f13ef2b69cbc8bc0d5d809f82568abe2b33d1cd060958b1ced683, + 0x2c274136a5de2849de6e7f92f9097296501acb68d56138fbcb660c4cb0f69107, + 0x1c4d5178acb5c6b6eceef23afc6f16ec7b0383094cb6467e8d0f4507b3cf74c3, + 0x65b1447d0d64ceced116785b92c63a6a7dd9701507dcbe8b909325e28f7b8d3, + 0x2265d7e244881220c81a193d979330409c9bfa333438951340e023e7b72a1961, + 0x15b12b355af7e05637a1c76e67f9cec6fca8a6449b37669f6850502256b30aba, + 0x1a1522fecc6ae028e4d3e3029497b88f35c2b48c687af168ec2582d9075b4387, + 0x22f56e79e81b7496e472a641a053c414bcc53b0a9350e2589240803076f58f26, + 0x202ddb66d0988994e7aabad692ceac4e2324672a17ab8417d1ee278afd17fd0c, + 0x12b0701e8813c5b21a8e30208f8f1158b96cd428ae77bdea72f84510f73edfce, + 0x1e63fd20e706e1407c8838ceb26b84c9fe693fdde0eb1e1a9df7e84e53eeee7e, + 0x20a16c5a86256deffd15af174c39f9d9aa11500676ac7e570088280dd1896259, + 0x1c8f8bf8e153da55ad5aca2eaaee38da563e0435c0f2f37c27558fb9bae0a3eb, + 0xd7732687bb7bf5f3aabcfdcc4fbb67e159c1983213e416c3880124fddf187c9, + 0xcdd04475a86999a2edcbbbf8264b195e108b3b60b6475d835f6ccef9e2f6865, + 0x2fe65586cd4e754b4c63a88c2ed3f9ba0e3bfa43f547b41153560c214fe3cbcd, + 0x503cf963c8273604e659128ec29261f62399815d98c56dbf4f2837c727ad4d9, + 0x1ee48ea27839061b78379936f6d97ca9400b393ef5fdf38ef1475c8742cb334c, + 0x1a423f8d8fc892b22d7cd5bf0197c575c579e83563d04859d73b2c1c5c0413f9, + 0x69a0da50133e9952f00e61778972a7be0e8d8ab76c95616ae465636abb97ec7, + 0x1bf7879dd42f2cbb91c65a0976356f67964c2f94dfbf0e44cf2b9909165d8614, + 0x1b23dccf485822065c8fc0afe610be7164e25056267f6c4a805fffd4547a0b98, + 0x2ebe90d6f6fdca420e0c2e004ce5c5a4409e564c9c4f3671e3011f627bec7c2e, + 0x167cd6930535a816dfebe81d20c376e77687760f3a2fa0da290b2f4d6c6863f7, + 0x8865c10f4a633c54ccc8b68b79df285f19f1210374cc64e3c8a966d4f90264b, + 0x1de902fbc0bf01951ca25abb39d78894721b37e071851b03a72cc6b833b7893b, + 0xe3eca007699dd0f852eb22da642e495f67c988dd5bf0137676b16a31eab4667 + ], + [ + [ + 0x66f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, + 0xcc57cdbb08507d62bf67a4493cc262fb6c09d557013fff1f573f431221f8ff9 + ], + [ + 0x2b9d4b4110c9ae997782e1509b1d0fdb20a7c02bbd8bea7305462b9f8125b1e8, + 0x1274e649a32ed355a31a6ed69724e1adade857e86eb5c3a121bcd147943203c8 + ] + ], + [ + [ + 0x66f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, + 0x20e3e914631964e394d269ae59f17efee3fecee512cbb163d32cc760be574bd6 + ], + [ + 0x2b9d4b4110c9ae997782e1509b1d0fdb20a7c02bbd8bea7305462b9f8125b1e8, + 0x10a44ed9dd9ce568563394632833d8633690d329ae737c8c7220a9b197ee3f46 + ] + ], + [ + 0x66f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, + 0x1fd20dcb58503896fd52998d6a5be6f12ec33b3cbd590c793e45de825ff8cb5f, + 0x8c8295df0ba11861e97f0cdde8f202a7096c1e6452d33d64a11b5be4e0a1efb, + 0x66f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, + 0x2458ee6d7c526073d165d2b08b95cf8947e20e05a76bc12b401b996421e89835, + 0x18c235e6e723390aa65baf06ffa557829f78a2fe1fbfb44eef84e938209c92f9, + 0x66f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, + 0x1868e106689f8ea2e9c561b4b192899d07b52e58595c393436c37df24976a584, + 0x2d5161804f0ec6445cb8904ad3e8e9ec21153350df4075c9cbe840b7b609ca92, + 0x66f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, + 0x3510550ddf6292355c690f03b9b815aab2dc3f4914612da7ecb79ddcf7b0b90, + 0x9a2e7bb3b278a1d5f264a26345ad8365efe0058403d8a52909cf2d5f6ee6170, + 0x66f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, + 0x13dd4148c491a166b015a7a4233f4e488ae94a0e6439be66fe149b50b55759c0, + 0x1d2d3b261f5beb3fc010f42ec3825649d90150eee4ce55dc9f86ddf110295550, + 0x66f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, + 0x221b4477678dad4e2abcabb47eb5e7a4129190b3855ae4eecd8ba68643ff77e5, + 0x16b76448e9855f165f2043f5f09bedf1830a4998ff45ebc25f1d40e8e8fcd6e4, + 0x66f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, + 0x2a10b6a2cbae9578142cf66104b69e448eae6d3bd53ac8602363460e2286c92d, + 0x2db84dba4a9d96cebe94dfb1d59edfa58ccfa871b9c067c522e31949b69f2bec, + 0x66f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, + 0x1ca9bbf26402238296ad897ec1a55b4fc273cf20c1f68f03d5c149be890e7b60, + 0x283d37fa5e35d25c83d1b9d34ecb00cd03848ca730ace52f367e0d7b5fde30d6, + 0x66f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, + 0x349057941b141ceea5a063a0ff8ab221271e618a174e5d8009ab5f9c791d960, + 0x1af2e1d98c3c09908503883d3b9ed50fe8958eb1e5d6538016c344d40070efc2, + 0x66f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, + 0x5b7bddacf4522b0aa3082e2c05448962743d0023bb6402291f592e6c1da4679, + 0x1fceeccf337e8a903cf6a0c21a6445da7ff8c4a0bc78909c7e704131c8a35241, + 0x66f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, + 0x2f30a25f4d843e28afdd850f31d1920ee058dfb6d91c322fc960473e917a6768, + 0x1a55160bf49a4936bcc59162617026194574a89e5857751b68f3c08f7c07ce87, + 0x66f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, + 0x19c66ee887ab4763b17573b6ad192b7df1af24f54761998b03b342b95709041e, + 0x1a82828b7f87eba7f5f8624b31e1115506ab3e723266777b3789c9104f9c781e, + 0x66f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, + 0xf506d3199d96083de9fc4e71b250825e84a242d81ae3a81d99debc7faed3385, + 0x1cac7482d91faef657db9072a97567ff172374d99987a8b24b2c04472aab9f83, + 0x66f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, + 0x249b26b1d4e333b23f3192f0e4f52884ee63d489ee153ecc3216939a72848150, + 0x13d1aeb10b225e2a8b97131154407d1bf145972dcd3a0073339dca336180dfb1, + 0x66f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, + 0xb90f72b7fcf867eb2e0f9400787d1dd52720cbc14a7095784e4116624d16df3, + 0x25e346edd8dd55142abd2135951398230f0c8d08bc5c365c5a6cd70011a8f39, + 0x66f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, + 0x263003b8ed502577c6427b0b4589ef6ceb87b4e21b7c424e587f2630a7b868a2, + 0x2d92ef6b8bdc53dd1b6c5b1c92e5a8248eb9c12255b910ff89c09961ec12ead7, + 0x66f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, + 0x2eb36b6d0bfc593a8d6d9459a7af04f0b15bcae4181bbb123543870c11316681, + 0x1e48bb591146f461c1d2f085f3979139e37f4a5c2354952c833b2791f59034e0, + 0x66f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, + 0xe759913751418871f0351ee180ca466cf8a03f541079c1b51bb001550d8162a, + 0x1e45e194b16936c5b1f81c72eb0fe8c62e859c4661b14b7e327503cf49eca55b, + 0x66f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, + 0x28c8b58c9e4cfb830a51af4529318b6269c4f6ac1867ed1174ce4aefc57fbeb3, + 0x255b293fcb1be27d9e5aafd4cd28c26746fc3520889367eed1355c2c41b93016, + 0x66f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, + 0x1db1367a8e37c5597835365bbfa66f6ecf40da775a54c35d5c94da70415544fe, + 0xcdd97951c2f0b885edc683b9db74f08df61286578a69989a9fed7ca34c5b4ce, + 0x66f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, + 0xe4d4e42cacb9fa6745c6dd3630ec5a4cca8a912b7ec28576ab3ba29c57306c9, + 0x2141a925c279e4c4e351641744750d4702d90ef2137d1905dada0bae3c7b3af6, + 0x66f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, + 0x8f9f9b3abc79ed89c20597cfbfe49021119cc50648ce401dc50cb042a54d167, + 0x6af6c072313d868cd945c9f0eb7d4eadb24c8d4763fa042952b99353df2b236, + 0x66f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, + 0x8b43c97bf4a40b4f376d1fa0c5e6e6955cbf9ba301f878ed3eae4ac812b79d1, + 0x11e0e607ac6781ca34a714e6c5b7a4f839852377446520032420e2abe16115a7, + 0x66f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, + 0x2dd7f0e1b303f425cb7e6b1c30ca428b3bff751e7b651152eb4de008b2c00da6, + 0x107d7f92d1c6a24068b917120f993ae3ee84349aaadb71eaa4128b349812dda8, + 0x66f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, + 0x10ab9e8e4ec9ad5fdb1166c64ed2fc3223c7e16dd982f66dcd820a7861ae1463, + 0x3000d3b3ddb3fb864ccc729984468a7317397713303544a84d7de1d209d25cb1, + 0x66f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, + 0x17610359e624e7feb3eede8099a1dc45c4a0c6b2debc2dc8f200fa27a0da6ebd, + 0x2affce5b7a7d8c5aac04f6c2708794cd01a8439b65d74df5982d24ad2a944eb8, + 0x66f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, + 0x2d439fbefe8d2b65ed32658bd21fc5604408d5fb69e1f64965e5895ca61c6e09, + 0xb51cc2a1b1c329fd72a286d4938540db3cfc4320de363a3f68a7935cd193ab9, + 0x66f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, + 0x1468ea2868d31f7ebafe78af8c24656a3185963272f34c51d5e2695c43bd3247, + 0x29553949324f27f4fa7bd734920e9be7b662a0ec5797fdd4ed3fe19464879b95, + 0x66f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, + 0xd9780ee7d395f7c977fd4b86329f6cd720047a7f9d1672d18d2cfb428343afa, + 0x210a098afd451fca3997860e220106c7487f4716831dfff78036de18f17cb31d, + 0x66f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, + 0x1cedcfe2751b360e73d6ef5af88cd5b75a2b2d97c571889a0dda87a0dd90ad81, + 0x22719f26e16723c1bd45a619e91836c340a304f3648672f90de2b047880aee03, + 0x66f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, + 0xae0cec959c4c7859f670f19c7490f8eef6ad66346e04613c1350597be000be2, + 0x177560de731482bdb7316c238bc38f20a16cd03edda2e0393b1c515ec64b0727, + 0x66f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, + 0x1f19a267da0b8fc2b4850a4f458add5514edf0aad6f7a7f175aef0b98e816a40, + 0x1da77cdeff9cf822b54509031ea2888f6f398051ae1870afd3770e7724c09f31, + 0x66f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, + 0x2d1e17aaaa96743665a869970255c267ba338cfd43ec9b33ecaa764f48f17a8, + 0xc376a8ff1da39dec980316ea26ef66fae5c86877a8f82266c14670024329d12, + 0x66f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, + 0xbb856048ef43a77b39560adeb3c7a9a783db5cad8e3f422495a69c56680a79, + 0x1d81808a3c73be1bb2c99b6403f3ac4a532c88d29ad652cbb20061656006c19a, + 0x66f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, + 0x15e52ae83a9db363d24cc5900df8ff0b81e445d4409a0e2aafd3223c354add62, + 0x2aa2fc03cb5f72e237f7d88ef66f765a159be533354ffb88751abb8885203ad4, + 0x66f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, + 0x10afedad881a1da7dace5c69546d0890bc35f41992b1062a7c7789b03ac932c0, + 0x1d18193701979ad24042446e947dfedfad22a6e7d4f6bde875fe2d8c882c858a, + 0x66f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, + 0x2f0b8457690e4d9770beb0300a09fc7001cd417061e826bc450dd96d7b24f36, + 0xdc31897d61d70e16870e0b02b9776bc53b8b9848be3062f8da18ff9d981effb, + 0x66f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, + 0x203c94bb7694f9cdad3a14a7603e3cb69c141200fd46bdc9ebb0d5d73663525, + 0x2b778a231f21f8a6cdaa3c84372933e610eb985dcc81af9926fe8b09f1afc81f, + 0x66f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, + 0x2c8a0376c766055e6a9d5272a2466a28faa7e359db111e84d98b2138c8c9d5d2, + 0x2ffda33f5b85a4fde16ba590ae0cd49fce4ad01e095f94f49138fe44aaa8c778, + 0x66f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, + 0x318af53cfd822ec2a7f4d40614f72fc6cb27f44067fb58d15789bbe15444844, + 0xd24997465c5b23d4e7436a4ecef2f91ce9f8910b6fa8a4a3ba6f884bd7206cc, + 0x66f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, + 0x1ea39e4d9edebf65d648e42880b396a6becfa66b3c5e47ff9a33577a3d2a658, + 0x15e4e016c94a026fd9ede9bdcf11268f7735cf5ebdbdd4a092fda1ee8b50f2ff, + 0x66f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, + 0x2ef185c4b1cdb7072a82fd43fe4bb145c4dbd04973fb3ef76e757b00392eac9d, + 0x15cedc8a4ef6f7017d1dd3d92255beb54f1d7d1e3bb0204cb07ab81c71435902, + 0x66f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, + 0xdbf148ee8983db0c117b111270f1c2c8219565733684494eaf5ce0645e5749a, + 0x2842f44ddc05dbd5b319b1efe6b3eabced380b99ffc42dfb08805ea2b4c48aab, + 0x66f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, + 0x1aa07e7ffa4a036f1b7efb2e124e75028426fdf5f1e4fb8bb62e1ebf3298af2c, + 0x1e5a2abded8c7022a8ba97ea683b605d09f017fd43e92296656561eb96d25d32, + 0x66f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, + 0xacf3ab02c018573bc3d36b0cb73de6df11e8cc1dea223e98a2a0cfbc028d2af, + 0x1bab48ad2c31dcec5fcc6df1f02dc4164f949202122673b06105f7ff1beabb29, + 0x66f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, + 0x1a36af3ad1c61cddc06a2a4c6967dc004b589a4a8b358ded11a38cce6a7f31c, + 0x125e0e822514cf49536fa643a66e1d2fa6788cb5b4805c9cd3cb69a584e0d8d2, + 0x66f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, + 0x85be8486ecb3dbf71d63940d8d689f9b142434a14d5d4f8c93d7d0f17bfcbd3, + 0x275651360d88063b2feead8bc71ae9c002d5db9822ab63b058f11e0d506b17e3, + 0x66f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, + 0xf7eb245596d9ac5ecc21446ed94c80289db1e1f9f620c18f7815b247b228a6f, + 0x221862a04a00f406bc67f7677ab459c9d887c8bb88091513f0fc2fb103ad549c, + 0x66f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, + 0x1bd575603b7085afcf0a588a5fadf8705cda7eb1d4ab7e70137dbd47fc26e3a2, + 0x146d1d176245ff772db8575d986a82e931079de61e67184c4158a6f62db446f1, + 0x66f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, + 0x2202ec1e7fd85c4749393664f024d578d392d59cb12a42e2ef4fa728da4cd3a, + 0x1c0e72693a0e12bff0ab3e12a1203c846b5dfdb9dd5ba26a7309c6970371421, + 0x66f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, + 0x2b3d8733bb4872b6cbb0bd83378163ab14a585dbf5ad9758c07948de056071e0, + 0x185d12aa30aed1a0575b9d3dcee6332f4fa34643a429cfdd8de0fdc87a29640e, + 0x66f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, + 0x1b394227301f28bee29bd3dfc35dfcc8e1c60ec6dd944dd33593a9a77675f641, + 0x15b1cfd522bdc418f6c08a3deb114a4ff48854b4a496537d41eb3a325f2265e7, + 0x66f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, + 0xbca3aef46833e8a30a9db0a16b59abc619800d2da15da01dd5a0713ff4cbbb8, + 0x529062596e51b8ca2c2f8c7cf4adff0853150015e2e6b4ce7af212500f5e6ca, + 0x66f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, + 0x2fda517f4261325a7366a45da1e847cd150d022be2982eb6105dcfc31fdef60, + 0x1fec5a09cea4d25e5b7ff9d2fbab64d264db993e8d8629b7154a1539d12dd1cf, + 0x66f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, + 0x2d87776eef5dfabbe5605094751af17b831717fa3f8e01943b74d1a9a42eb1bb, + 0xd257a437910f3995aebd0afb9be584967afa4188c4684958f68c39f9f01ff19, + 0x66f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, + 0x98f0aa06092ed2cbcbac004f90799e6e1c32fc24a9f0b6066f8d7289716aee4, + 0xcc57cdbb08507d62bf67a4493cc262fb6c09d557013fff1f573f431221f8ff9 + ] ) - } + // noir-fmt:ignore -pub fn x5_3_config() -> PoseidonConfig<195, 9> { +pub fn x5_3_config() -> PoseidonConfig<3, 81, 285> { config( 3, 8, 57, - 5, - [6745197990210204598374042828761989596302876299545964402857411729872131034734,426281677759936592021316809065178817848084678679510574715894138690250139748,4014188762916583598888942667424965430287497824629657219807941460227372577781,21328925083209914769191926116470334003273872494252651254811226518870906634704,19525217621804205041825319248827370085205895195618474548469181956339322154226,1402547928439424661186498190603111095981986484908825517071607587179649375482,18320863691943690091503704046057443633081959680694199244583676572077409194605,17709820605501892134371743295301255810542620360751268064484461849423726103416,15970119011175710804034336110979394557344217932580634635707518729185096681010,9818625905832534778628436765635714771300533913823445439412501514317783880744,6235167673500273618358172865171408902079591030551453531218774338170981503478,12575685815457815780909564540589853169226710664203625668068862277336357031324,7381963244739421891665696965695211188125933529845348367882277882370864309593,14214782117460029685087903971105962785460806586237411939435376993762368956406,13382692957873425730537487257409819532582973556007555550953772737680185788165,2203881792421502412097043743980777162333765109810562102330023625047867378813,2916799379096386059941979057020673941967403377243798575982519638429287573544,4341714036313630002881786446132415875360643644216758539961571543427269293497,2340590164268886572738332390117165591168622939528604352383836760095320678310,5222233506067684445011741833180208249846813936652202885155168684515636170204,7963328565263035669460582454204125526132426321764384712313576357234706922961,1394121618978136816716817287892553782094854454366447781505650417569234586889,20251767894547536128245030306810919879363877532719496013176573522769484883301,141695147295366035069589946372747683366709960920818122842195372849143476473,15919677773886738212551540894030218900525794162097204800782557234189587084981,2616624285043480955310772600732442182691089413248613225596630696960447611520,4740655602437503003625476760295930165628853341577914460831224100471301981787,19201590924623513311141753466125212569043677014481753075022686585593991810752,12116486795864712158501385780203500958268173542001460756053597574143933465696,8481222075475748672358154589993007112877289817336436741649507712124418867136,5181207870440376967537721398591028675236553829547043817076573656878024336014,1576305643467537308202593927724028147293702201461402534316403041563704263752,2555752030748925341265856133642532487884589978209403118872788051695546807407,18840924862590752659304250828416640310422888056457367520753407434927494649454,14593453114436356872569019099482380600010961031449147888385564231161572479535,20826991704411880672028799007667199259549645488279985687894219600551387252871,9159011389589751902277217485643457078922343616356921337993871236707687166408,5605846325255071220412087261490782205304876403716989785167758520729893194481,1148784255964739709393622058074925404369763692117037208398835319441214134867,20945896491956417459309978192328611958993484165135279604807006821513499894540,229312996389666104692157009189660162223783309871515463857687414818018508814,21184391300727296923488439338697060571987191396173649012875080956309403646776,21853424399738097885762888601689700621597911601971608617330124755808946442758,12776298811140222029408960445729157525018582422120161448937390282915768616621,7556638921712565671493830639474905252516049452878366640087648712509680826732,19042212131548710076857572964084011858520620377048961573689299061399932349935,12871359356889933725034558434803294882039795794349132643274844130484166679697,3313271555224009399457959221795880655466141771467177849716499564904543504032,15080780006046305940429266707255063673138269243146576829483541808378091931472,21300668809180077730195066774916591829321297484129506780637389508430384679582,20480395468049323836126447690964858840772494303543046543729776750771407319822,10034492246236387932307199011778078115444704411143703430822959320969550003883,19584962776865783763416938001503258436032522042569001300175637333222729790225,20155726818439649091211122042505326538030503429443841583127932647435472711802,13313554736139368941495919643765094930693458639277286513236143495391474916777,14606609055603079181113315307204024259649959674048912770003912154260692161833,5563317320536360357019805881367133322562055054443943486481491020841431450882,10535419877021741166931390532371024954143141727751832596925779759801808223060,12025323200952647772051708095132262602424463606315130667435888188024371598063,2906495834492762782415522961458044920178260121151056598901462871824771097354,19131970618309428864375891649512521128588657129006772405220584460225143887876,8896386073442729425831367074375892129571226824899294414632856215758860965449,7748212315898910829925509969895667732958278025359537472413515465768989125274,422974903473869924285294686399247660575841594104291551918957116218939002865,6398251826151191010634405259351528880538837895394722626439957170031528482771,18978082967849498068717608127246258727629855559346799025101476822814831852169,19150742296744826773994641927898928595714611370355487304294875666791554590142,12896891575271590393203506752066427004153880610948642373943666975402674068209,9546270356416926575977159110423162512143435321217584886616658624852959369669,2159256158967802519099187112783460402410585039950369442740637803310736339200,8911064487437952102278704807713767893452045491852457406400757953039127292263,745203718271072817124702263707270113474103371777640557877379939715613501668,19313999467876585876087962875809436559985619524211587308123441305315685710594,13254105126478921521101199309550428567648131468564858698707378705299481802310,1842081783060652110083740461228060164332599013503094142244413855982571335453,9630707582521938235113899367442877106957117302212260601089037887382200262598,5066637850921463603001689152130702510691309665971848984551789224031532240292,4222575506342961001052323857466868245596202202118237252286417317084494678062,2919565560395273474653456663643621058897649501626354982855207508310069954086,6828792324689892364977311977277548750189770865063718432946006481461319858171,2245543836264212411244499299744964607957732316191654500700776604707526766099,19602444885919216544870739287153239096493385668743835386720501338355679311704,8239538512351936341605373169291864076963368674911219628966947078336484944367,15053013456316196458870481299866861595818749671771356646798978105863499965417,7173615418515925804810790963571435428017065786053377450925733428353831789901,8239211677777829016346247446855147819062679124993100113886842075069166957042,15330855478780269194281285878526984092296288422420009233557393252489043181621,10014883178425964324400942419088813432808659204697623248101862794157084619079,14014440630268834826103915635277409547403899966106389064645466381170788813506,3580284508947993352601712737893796312152276667249521401778537893620670305946,2559754020964039399020874042785294258009596917335212876725104742182177996988,14898657953331064524657146359621913343900897440154577299309964768812788279359,2094037260225570753385567402013028115218264157081728958845544426054943497065,18051086536715129874440142649831636862614413764019212222493256578581754875930,21680659279808524976004872421382255670910633119979692059689680820959727969489,13950668739013333802529221454188102772764935019081479852094403697438884885176,9703845704528288130475698300068368924202959408694460208903346143576482802458,12064310080154762977097567536495874701200266107682637369509532768346427148165,16970760937630487134309762150133050221647250855182482010338640862111040175223,9790997389841527686594908620011261506072956332346095631818178387333642218087,16314772317774781682315680698375079500119933343877658265473913556101283387175,82044870826814863425230825851780076663078706675282523830353041968943811739,21696416499108261787701615667919260888528264686979598953977501999747075085778,327771579314982889069767086599893095509690747425186236545716715062234528958,4606746338794869835346679399457321301521448510419912225455957310754258695442,64499140292086295251085369317820027058256893294990556166497635237544139149,10455028514626281809317431738697215395754892241565963900707779591201786416553,10421411526406559029881814534127830959833724368842872558146891658647152404488,18848084335930758908929996602136129516563864917028006334090900573158639401697,13844582069112758573505569452838731733665881813247931940917033313637916625267,13488838454403536473492810836925746129625931018303120152441617863324950564617,15742141787658576773362201234656079648895020623294182888893044264221895077688,6756884846734501741323584200608866954194124526254904154220230538416015199997,7860026400080412708388991924996537435137213401947704476935669541906823414404,7871040688194276447149361970364037034145427598711982334898258974993423182255,20758972836260983284101736686981180669442461217558708348216227791678564394086,21723241881201839361054939276225528403036494340235482225557493179929400043949,19428469330241922173653014973246050805326196062205770999171646238586440011910,7969200143746252148180468265998213908636952110398450526104077406933642389443,10950417916542216146808986264475443189195561844878185034086477052349738113024,18149233917533571579549129116652755182249709970669448788972210488823719849654,3729796741814967444466779622727009306670204996071028061336690366291718751463,5172504399789702452458550583224415301790558941194337190035441508103183388987,6686473297578275808822003704722284278892335730899287687997898239052863590235,19426913098142877404613120616123695099909113097119499573837343516470853338513,5120337081764243150760446206763109494847464512045895114970710519826059751800,5055737465570446530938379301905385631528718027725177854815404507095601126720,14235578612970484492268974539959119923625505766550088220840324058885914976980,653592517890187950103239281291172267359747551606210609563961204572842639923,5507360526092411682502736946959369987101940689834541471605074817375175870579,7864202866011437199771472205361912625244234597659755013419363091895334445453,21294659996736305811805196472076519801392453844037698272479731199885739891648,13767183507040326119772335839274719411331242166231012705169069242737428254651,810181532076738148308457416289197585577119693706380535394811298325092337781,14232321930654703053193240133923161848171310212544136614525040874814292190478,16796904728299128263054838299534612533844352058851230375569421467352578781209,16256310366973209550759123431979563367001604350120872788217761535379268327259,19791658638819031543640174069980007021961272701723090073894685478509001321817,7046232469803978873754056165670086532908888046886780200907660308846356865119,16001732848952745747636754668380555263330934909183814105655567108556497219752,9737276123084413897604802930591512772593843242069849260396983774140735981896,11410895086919039954381533622971292904413121053792570364694836768885182251535,19098362474249267294548762387533474746422711206129028436248281690105483603471,11013788190750472643548844759298623898218957233582881400726340624764440203586,2206958256327295151076063922661677909471794458896944583339625762978736821035,7171889270225471948987523104033632910444398328090760036609063776968837717795,2510237900514902891152324520472140114359583819338640775472608119384714834368,8825275525296082671615660088137472022727508654813239986303576303490504107418,1481125575303576470988538039195271612778457110700618040436600537924912146613,16268684562967416784133317570130804847322980788316762518215429249893668424280,4681491452239189664806745521067158092729838954919425311759965958272644506354,3131438137839074317765338377823608627360421824842227925080193892542578675835,7930402370812046914611776451748034256998580373012248216998696754202474945793,8973151117361309058790078507956716669068786070949641445408234962176963060145,10223139291409280771165469989652431067575076252562753663259473331031932716923,2232089286698717316374057160056566551249777684520809735680538268209217819725,16930089744400890347392540468934821520000065594669279286854302439710657571308,21739597952486540111798430281275997558482064077591840966152905690279247146674,7508315029150148468008716674010060103310093296969466203204862163743615534994,11418894863682894988747041469969889669847284797234703818032750410328384432224,10895338268862022698088163806301557188640023613155321294365781481663489837917,18644184384117747990653304688839904082421784959872380449968500304556054962449,7414443845282852488299349772251184564170443662081877445177167932875038836497,5391299369598751507276083947272874512197023231529277107201098701900193273851,10329906873896253554985208009869159014028187242848161393978194008068001342262,4711719500416619550464783480084256452493890461073147512131129596065578741786,11943219201565014805519989716407790139241726526989183705078747065985453201504,4298705349772984837150885571712355513879480272326239023123910904259614053334,9999044003322463509208400801275356671266978396985433172455084837770460579627,4908416131442887573991189028182614782884545304889259793974797565686968097291,11963412684806827200577486696316210731159599844307091475104710684559519773777,20129916000261129180023520480843084814481184380399868943565043864970719708502,12884788430473747619080473633364244616344003003135883061507342348586143092592,20286808211545908191036106582330883564479538831989852602050135926112143921015,16282045180030846845043407450751207026423331632332114205316676731302016331498,4332932669439410887701725251009073017227450696965904037736403407953448682093,11105712698773407689561953778861118250080830258196150686012791790342360778288,21853934471586954540926699232107176721894655187276984175226220218852955976831,9807888223112768841912392164376763820266226276821186661925633831143729724792,13411808896854134882869416756427789378942943805153730705795307450368858622668,17906847067500673080192335286161014930416613104209700445088168479205894040011,14554387648466176616800733804942239711702169161888492380425023505790070369632,4264116751358967409634966292436919795665643055548061693088119780787376143967,2401104597023440271473786738539405349187326308074330930748109868990675625380,12251645483867233248963286274239998200789646392205783056343767189806123148785,15331181254680049984374210433775713530849624954688899814297733641575188164316,13108834590369183125338853868477110922788848506677889928217413952560148766472,6843160824078397950058285123048455551935389277899379615286104657075620692224,10151103286206275742153883485231683504642432930275602063393479013696349676320,7074320081443088514060123546121507442501369977071685257650287261047855962224,11413928794424774638606755585641504971720734248726394295158115188173278890938,7312756097842145322667451519888915975561412209738441762091369106604423801080,7181677521425162567568557182629489303281861794357882492140051324529826589361,15123155547166304758320442783720138372005699143801247333941013553002921430306,13409242754315411433193860530743374419854094495153957441316635981078068351329], - [7511745149465107256748700652201246547602992235352608707588321460060273774987,10370080108974718697676803824769673834027675643658433702224577712625900127200,19705173408229649878903981084052839426532978878058043055305024233888854471533,18732019378264290557468133440468564866454307626475683536618613112504878618481,20870176810702568768751421378473869562658540583882454726129544628203806653987,7266061498423634438633389053804536045105766754026813321943009179476902321146,9131299761947733513298312097611845208338517739621853568979632113419485819303,10595341252162738537912664445405114076324478519622938027420701542910180337937,11597556804922396090267472882856054602429588299176362916247939723151043581408]) - + alpha(), + [ + 0xee9a592ba9a9518d05986d656f40c2114c4993c11bb29938d21d47304cd8e6e, + 0xf1445235f2148c5986587169fc1bcd887b08d4d00868df5696fff40956e864, + 0x8dff3487e8ac99e1f29a058d0fa80b930c728730b7ab36ce879f3890ecf73f5, + 0x84d520e4e5bb469e1f9075cb7c490efa59565eedae2d00ca8ef88ceea2b0197, + 0x2d15d982d99577fa33da56722416fd734b3e667a2f9f15d8eb3e767ae0fd811e, + 0xed2538844aba161cf1578a43cf0364e91601f6536a5996d0efbe65632c41b6d, + 0x2600c27d879fbca186e739e6363c71cf804c877d829b735dcc3e3af02955e60a, + 0x28f8bd44a583cbaa475bd15396430e7ccb99a5517440dfd970058558282bf2c5, + 0x9cd7d4c380dc5488781aad012e7eaef1ed314d7f697a5572d030c55df153221, + 0x11bb6ee1291aabb206120ecaace460d24b6713febe82234951e2bee7d0f855f5, + 0x2d74e8fa0637d9853310f3c0e3fae1d06f171580f5b8fd05349cadeecfceb230, + 0x2735e4ec9d39bdffac9bef31bacba338b1a09559a511a18be4b4d316ed889033, + 0xf03c1e9e0895db1a5da6312faa78e971106c33f826e08dcf617e24213132dfd, + 0x17094cd297bf827caf92920205b719c18741090b8f777811848a7e9ead6778c4, + 0xdb8f419c21f92461fc2b3219465798348df90d4178042c81ba7d4b4d559e2b8, + 0x243443613f64ffa417427ed5933fcfbc66809db60b9ca1724a22709ceceeece2, + 0x22af49fbfd5d7e9fcd256c25c07d3dd8ecbbae6deecd03aa04bb191fada75411, + 0x14fbd37fa8ad6e4e0c78a20d93c7230c4677f797b4327323f7f7c097c19420e0, + 0x15a9298bbb882534d4b2c9fbc6e4ef4189420c4eb3f3e1ea22faa7e18b5ae625, + 0x2f7de75f23ddaaa5221323ebceb2f2ac83eef92e854e75434c2f1d90562232bc, + 0x36a4432a868283b78a315e84c4ae5aeca216f2ff9e9b2e623584f7479cd5c27, + 0x2180d7786a8cf810e277218ab14a11e5e39f3c962f11e860ae1c5682c797de5c, + 0xa268ef870736eebd0cb55be640d73ee3778990484cc03ce53572377eefff8e4, + 0x1eefefe11c0be4664f2999031f15994829e982e8c90e09069df9bae16809a5b2, + 0x27e87f033bd1e0a89ca596e8cb77fe3a4b8fb93d9a1129946571a3c3cf244c52, + 0x1498a3e6599fe243321f57d6c5435889979c4f9d2a3e184d21451809178ee39, + 0x27c0a41f4cb9fe67e9dd4d7ce33707f74d5d6bcc235bef108dea1bbebde507aa, + 0x1f75230908b141b46637238b120fc770f4f4ae825d5004c16a7c91fe1dae280f, + 0x25f99a9198e923167bba831b15fffd2d7b97b3a089808d4eb1f0a085bee21656, + 0x101bc318e9ea5920d0f6acdc2bb526593d3d56ec8ed14c67622974228ba900c6, + 0x1a175607067d517397c1334ecb019754ebc0c852a3cf091ec1ccc43207a83c76, + 0xf02f0e6d25f9ea3deb245f3e8c381ee6b2eb380ba4af5c1c4d89770155df37b, + 0x151d757acc8237af08d8a6677203ec9692565de456ae789ff358b3163b393bc9, + 0x256cd9577cea143049e0a1fe0068dd20084980ee5b757890a79d13a3a624fad4, + 0x513abaff6195ea48833b13da50e0884476682c3fbdd195497b8ae86e1937c61, + 0x1d9570dc70a205f36f610251ee6e2e8039246e84e4ac448386d19dbac4e4a655, + 0x18f1a5194755b8c5d5d7f1bf8aaa6f56effb012dd784cf5e044eec50b29fc9d4, + 0x266b53b615ef73ac866512c091e4a4f2fa4bb0af966ef420d88163238eebbca8, + 0x2d63234c9207438aa42b8de27644c02268304dfeb8c89a1a3f4fd6e8344ae0f7, + 0x2ab30fbe51ee49bc7b3adde219a6f0b5fbb976205ef8df7e0021daee6f55c693, + 0x1aee6d4b3ebe9366dcb9cce48969d4df1dc42abcd528b270068d9207fa6a45c9, + 0x1891aeab71e34b895a79452e5864ae1d11f57646c60bb34aa211d123f6095219, + 0x24492b5f95c0b0876437e94b4101c69118e16b2657771bd3a7caab01c818aa4b, + 0x1752161b3350f7e1b3b2c8663a0d642964628213d66c10ab2fddf71bcfde68f, + 0xab676935722e2f67cfb84938e614c6c2f445b8d148de54368cfb8f90a00f3a7, + 0xb0f72472b9a2f5f45bc730117ed9ae5683fc2e6e227e3d4fe0da1f7aa348189, + 0x16aa6f9273acd5631c201d1a52fc4f8acaf2b2152c3ae6df13a78a513edcd369, + 0x2f60b987e63614eb13c324c1d8716eb0bf62d9b155d23281a45c08d52435cd60, + 0x18d24ae01dde92fd7606bb7884554e9df1cb89b042f508fd9db76b7cc1b21212, + 0x4fc3bf76fe31e2f8d776373130df79d18c3185fdf1593960715d4724cffa586, + 0xd18f6b53fc69546cfdd670b41732bdf6dee9e06b21260c6b5d26270468dbf82, + 0xba4231a918f13acec11fbafa17c5223f1f70b4cdb045036fa5d7045bd10e24, + 0x7b458b2e00cd7c6100985301663e7ec33c826da0635ff1ebedd0dd86120b4c8, + 0x1c35c2d96db90f4f6058e76f15a0c8286bba24e2ed40b16cec39e9fd7baa5799, + 0x1d12bea3d8c32a5d766568f03dd1ecdb0a4f589abbef96945e0dde688e292050, + 0xd953e20022003270525f9a73526e9889c995bb62fdea94313db405a61300286, + 0x29f053ec388795d786a40bec4c875047f06ff0b610b4040a760e33506d2671e1, + 0x4188e33735f46b14a4952a98463bc12e264d5f446e0c3f64b9679caaae44fc2, + 0x149ec28846d4f438a84f1d0529431bb9e996a408b7e97eb3bf1735cdbe96f68f, + 0xde20fae0af5188bca24b5f63630bad47aeafd98e651922d148cce1c5fdddee8, + 0x12d650e8f790b1253ea94350e722ad2f7d836c234b8660edf449fba6984c6709, + 0x22ab53aa39f34ad30ea96717ba7446aafdadbc1a8abe28d78340dfc4babb8f6c, + 0x26503e8d4849bdf5450dabea7907bc3de0de109871dd776904a129db9149166c, + 0x1d5e7a0e2965dffa00f5454f5003c5c8ec34b23d897e7fc4c8064035b0d33850, + 0xee3d8daa098bee012d96b7ec48448c6bc9a6aefa544615b9cb3c7bbd07104cb, + 0x1bf282082a04979955d30754cd4d9056fa9ef7a7175703d91dc232b5f98ead00, + 0x7ae1344abfc6c2ce3e951bc316bee49971645f16b693733a0272173ee9ad461, + 0x217e3a247827c376ec21b131d511d7dbdc98a36b7a47d97a5c8e89762ee80488, + 0x215ffe584b0eb067a003d438e2fbe28babe1e50efc2894117509b616addc30ee, + 0x1e770fc8ecbfdc8692dcedc597c4ca0fbec19b84e33da57412a92d1d3ce3ec20, + 0x2f6243cda919bf4c9f1e3a8a6d66a05742914fc19338b3c0e50e828f69ff6d1f, + 0x246efddc3117ecd39595d0046f44ab303a195d0e9cc89345d3c03ff87a11b693, + 0x53e8d9b3ea5b8ed4fe006f139cbc4e0168b1c89a918dfbe602bc62cec6adf1, + 0x1b894a2f45cb96647d910f6a710d38b7eb4f261beefff135aec04c1abe59427b, + 0xaeb1554e266693d8212652479107d5fdc077abf88651f5a42553d54ec242cc0, + 0x16a735f6f7209d24e6888680d1781c7f04ba7d71bd4b7d0e11faf9da8d9ca28e, + 0x487b8b7fab5fc8fd7c13b4df0543cd260e4bcbb615b19374ff549dcf073d41b, + 0x1e75b9d2c2006307124bea26b0772493cfb5d512068c3ad677fdf51c92388793, + 0x5120e3d0e28003c253b46d5ff77d272ae46fa1e239d1c6c961dcb02da3b388f, + 0xda5feb534576492b822e8763240119ac0900a053b171823f890f5fd55d78372, + 0x2e211b39a023031a22acc1a1f5f3bb6d8c2666a6379d9d2c40cc8f78b7bd9abe + ], + [ + [ + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0x2969f27eed31a480b9c36c764379dbca2cc8fdd1415c3dded62940bcde0bd771, + 0x143021ec686a3f330d5f9e654638065ce6cd79e28c5b3753326244ee65a1b1a7 + ], + [ + 0x16ed41e13bb9c0c66ae119424fddbcbc9314dc9fdbdeea55d6c64543dc4903e0, + 0x2e2419f9ec02ec394c9871c832963dc1b89d743c8c7b964029b2311687b1fe23, + 0x176cc029695ad02582a70eff08a6fd99d057e12e58e7d7b6b16cdfabc8ee2911 + ], + [ + 0x2b90bba00fca0589f617e7dcbfe82e0df706ab640ceb247b791a93b74e36736d, + 0x101071f0032379b697315876690f053d148d4e109f5fb065c8aacc55a0f89bfa, + 0x19a3fc0a56702bf417ba7fee3802593fa644470307043f7773279cd71d25d5e0 + ] + ], + [ + [ + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0x1e6f20a11d1e31e43f83dcedddb9a0236203f5f24ae72c925a8a79a66831f51d, + 0x1bd8c528472e57bdc722a141f8785694484f426725403ae24084e3027e782467 + ], + [ + 0x16ed41e13bb9c0c66ae119424fddbcbc9314dc9fdbdeea55d6c64543dc4903e0, + 0x2d51ba82c8073c6d6bacf1ad5e56655b7143625b0a9e9c3190527a1a5f05079a, + 0x1b07d6d51e6f7e97e0ab10fc2e51ea83ce0611f940ff0731b5f927fe8d6a77c9 + ], + [ + 0x2b90bba00fca0589f617e7dcbfe82e0df706ab640ceb247b791a93b74e36736d, + 0x11e12a40d262ae88e8376f62d19edf43093cdef1ccf34d985a3e53f0bc5765a0, + 0x221c170e4d02a2479c6f3e47b5ff55781574f980d89038308a3ef37cce8463bd + ] + ], + [ + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0x3f0815ab463f1b76ee25a9b8768b3231a89752f427f4f063ab718e707576b31, + 0x15648bf46f60d82954c7e33029b3617357012a3d3b1d34c8e008859f1dbfb317, + 0x127e00c2253de07818ca7f2eafdd7564d05ea850cf61f1daa0cfefbf7fbfba85, + 0x66365afd18a41ef9382fc0b1d265cb4d3ce470a8cbbb878f7d48051630747bd, + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0x219d14f823513140dc69a96f7fe7e086f4fa24c84e57dcf2b099715c4404aae7, + 0x3a30bfbbf2cb86d4a6a63a8050d91f9f14f4d33696d37ebaefa9ac2302132d5, + 0x2121bbcdeaa33a35b0270fb7d5c9f94edad5a84d74b06e3385104b0b41935bcc, + 0x196b544fbeb0a792cfbb82c289e579b7cd5580c2e338a389d053ef8b3d10e70e, + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0x2809c3a1547c0cee89c1db270ef479c26973ec73edb4bd4e7d907ea0202f560f, + 0x11c34446b083ef92ca157585a02b8b342a4c67175b31f4b5d40d4e96dfc5c8f1, + 0x253ea0b33a8bf3b2367c030e3289cbe0f6242ad7709d90b86d9d8026e2e39925, + 0x30467dc1930f6afe90c89d4007ad29fc4f5a19c006d1030438c16df85637bd5f, + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0x2f9d4b55495f7e377e20e6f5a3a88af7aa6a536458b38bbe13c8ebfbbba54f44, + 0x1d9e9d5c736e3151f11d36d499e7e093d8ee2353be18aad54cfd03ff0feac4b8, + 0x124b617b43e598f9ebf622f7823a3de7d1bfedb87e097c315f343de301e54841, + 0x198e7cfc66ae45774055cf073bedc945a5f9c5b19cae08d789cc5748ffe199b2, + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0x2eac25b3498dfadffd124ab3aad57789eb945ba57443099c5bb6c27ed977fe24, + 0x1ee02c175cdfe1871b378305c1bb9c904e8af1d4454ed3550b3c6ab5f4f90126, + 0x616f8c34c607266b29ea8f9d2dfa47ff6fbb1d9745c48609fa98301d0f679d5, + 0x181d68b0a188504958b9f19cbbdb972a853e51ed385e4883a43a42832803370b, + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0x2d5397ce863464a25d6b7f5b015d579181d1ce2f24cbabf6059e9327f5ba7004, + 0x15bf817491b94d71e8912940cc0b80277713e7d32da2b6591724d8dbd4bc2618, + 0x2a7cbd11460b177ab76feab28b69485ac8cc687740bc910994a3827d29c08714, + 0xf7cd5ffa4661730ab56e447fae5cc1763cb462da80a85614c237b290de9d502, + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0xe0766004b4c4176eb13273508eb6575f768137d86d305be644ce04531008100, + 0x625fa7145813481f6d148be6b9c8bb7b54ee3c1afac00104e1f763000b9924c, + 0x7c5472508b459916ee0f5461aad2e0b19cd9c7b184f515b65136318ce2c6a5, + 0x567375470d189b693ac77ab3fb7557231d53073951d43c54685879cb7a89fcb, + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0x1d0406bcbec83f8d5165f56c063e42108ad21f51ea4bfc71601174ba5c7b8bcc, + 0xc02b18eef22332d280a8aa1f86405f3375f06342f8696ee7c73b46c63272cb7, + 0x17c1fc174cd9a6ebeaa7add2f801a664823509ad4fd1b15aad053a55ad6da4cf, + 0x5f843c23024eb1dab7ebbc86709a021aaa6caf433f7ed258a08638e9584b32d, + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0x22df2420697ca28b5cc51c53165e002727b45ccd90a55c87589f792f0ad8cb37, + 0x2f1438303a7b49d473400aaedf0f48009fd3af804b76be86417588efc4d7302a, + 0x2323d5fcf2da8965c6b2b7b4fbf9a24bbaa7f4dccd35d5ca6155c5463093b23b, + 0x26c85b9dfbbe48fe83b753a5e7336b9f40f7b961e9c54f94e37700073d4d26e, + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0x31511000251ec86feb38b5ab4e335f070b271df4c20979528e41d65384c318f, + 0x18e588324a9bbaacb42fa69e5d90a0c0e27cd16b941e34a60ff5df9a26c03af1, + 0x2642b5d8e16b953b070635775c8d3c9498357d6ad9bef2e7d99f03c10ea1f95f, + 0x21fc313ba11c60e8e84ff60db906a0f031189b0b48335c4221f909aef836c133, + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0x2d3562e3d4b42bc6890b698cc6ab89f7311298bcbac6e4e9f2f4d93d06dae151, + 0xa74ef541d360e842e3e0b6ff7e5c7c77934a5f67616f01c189d886dfd2e0808, + 0x140564b53e0a812ac3983d6e3b433afa43f434087d9e754967c2c9b1b02caf8a, + 0x14709e32d98ae4cd18b400181e71ab9759c436c8e83fa6993adb6f2db6bba9d0, + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0x734b2366c59e394423f179e1266dd392372db4f2dba651f4a619a4b52bdc010, + 0x11fb2d705c94b08d5ad3e3c5fb6629abe963ed92913642c7d02d7e71088fd2d4, + 0x27d03abf5c1f290e5d715eba19371050ef6eb7f78fd84be834e4cc3618059484, + 0x13ed9e9e6b452df27fb3353cfc2cd63ebe817f212a39c6a8bb9b441ac1395861, + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0x1319c51cf37aaa10246cdaaa04a12e88795de4452604263a7c5b79ab99cbd23c, + 0xbca25588d187b7f9dad839f2c8cb526a4cf444eebbd0e715b6cea019ac3f2, + 0x1d837ea0341c5964181226874b923cd01a069b493f02f7a3c01be23cf51d593f, + 0x1b41ce9ed3634cbd42c427ce4c5c83774149e2a6dbd25f24012090db7de4e7f9, + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0x671f0e3b674ae7cddc790ecc4e946f4bca74b98b78a127c7b56bd6673f1ce1f, + 0x19fc073797a39b272e40cd30615f55fefeb682c1ac14143071d0449a5426e4e, + 0x17bee47d262a497fd1f7c5c6d5a7c70fa4209480bf5d97311c5096619e9fd13, + 0x2073cff92d3141b480763539cff2978a4c7944721cc937ba00cc8527274471e3, + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0x3bd7b3e2c1885877f43182a55a91d48f9c58d152e730fe2c7aa46b1fa663baa, + 0x226ebc9a538b5bbaff128edfb9bbf5fa0ceb100719a14c8dfed9ffbbbad9b6b7, + 0xd395f0b08b9fede0373a06e1552c0e634a49572af1d830dc6e394e8a5d3b21a, + 0x28242439b524540a30d49b68e19e31ba5284bd3bcf1e0f2f41f77d5331f99ffa, + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0x370d6fa19eaac142d2de034801ab85e0b457e129e91f929754b48c6154d4df6, + 0x9a16f573b3280f390762abf269579eaa37939bc0c753feb0a2b2e0bcbde1659, + 0x2228e360fb5b162b496ac443f98127ee3c0021a690b71b268d99981368231d97, + 0x7e42c2ca633d2c49fabf83991476d209431e34d8032b6a1b97675f3c567f944, + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0x2ce12d7269663770c3cab85a6215a32eed35fda1d8e9d753a50fe96097724a9f, + 0x3d7427704c61e2009eeb9b1b45a0125084bc4daf70973a7ba0b2231815b15de, + 0x10f8abf0764185861c1267fcf4b4b33ca096fb4ddc4626732d86921e553e69c6, + 0x17ccaf6f26f7267a025d7cb456e3aeb251a1a620aaf6568a5c95644c7c5914cc, + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0x63bb306b96310051385c3ce00ca820ad0e3651a6e55754d59de6df28cea4d51, + 0x1f761ee5553c5e86f2c304a18095ab7403242e0b65e608bc920cf993a4169974, + 0xdc5f00bbfd7c1d9a23c0e666859ba6564bcde8761b45717cd6bdfc09de4e8f2, + 0x6de511520e277b7df07c3536381c13eb44cf790a230abc391089760bfc40ef2, + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0x2a134348c8660efcf9ef54863e70528a1fd4481b50a1fe21f24a8c06e10cca03, + 0xaeb5023bbb9a64c4bd80089e99edf8ed5f6f1ffb63a7dbba1b33520bcfce37b, + 0x141a6d0810366ae225ecb5f0bfdc9995406c5960ab26155836fc51fb7cb933d1, + 0x9d2ea05ef54dadbbe776f404dca6626cc0b2539990bc0b8bfe87497f1e2c5b7, + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0x1e56d244a8e41be5d104d5f8ef70891d22d4a5432441bfe8ff1a16e91719cdde, + 0x1d4f020c57c4f14aec908b2f99b5c4fd5e09447fa85c2fd68ba4d5c5f50c7b49, + 0x763911a3a92a4f0e09f4e14cd03398d8d82a1e09db80fb0ee1e833764c18fd3, + 0x12857275be2fe6b9ba2ec68f9061643f1fc5d9a2c5e47e55684366e54b302946, + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0x2ed11ccd2e2e2376655ffe9a96c4b81adc0a60353c5d83d4d0ebf50d1bbf87c0, + 0x3e31de8958e82645b320d5e3e966ef4726d5b1c2cfbb4acd288a21543c6d594, + 0x11e880dfefdbd08858ae890046533d58da28a608d7e905366ec2ca4a36e71963, + 0x1835b275deaed2d00704a9c3cc21ab7a44a34662978d53c190dc25e969a507b2, + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0x68b75315e25ed4ace5a4a9480e1d82ce5d44f76f1324240419f372ff8d3c3f5, + 0x1b7ef7d04aec73d62b052d2ad12b92a4268fccd795c839d698ad3b22823274d1, + 0x28c0c848022a90606f6193ff5501b57216b670727f4b8efcc240d30bbaa9f03f, + 0x13bda49296cbcc51686a7bfb1c39f3f254370985a16660efd6e5d82d4f068e1b, + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0x2e7987ea8204389d11eb10b34265e378a945729f86c3e0e2fd38490d3a594141, + 0x826d4a2324ad3aa4b2b45c10a190fedef702aeffda3226ce5415fffd03935c8, + 0x2dbeee85eaeaa9fa3675ef541c9df7bb964a85435c3b59685f93b434036ded, + 0x227ee7a945edaee6919418ecb3279b11e6fa44f5f5c5abfb966a4be599cb86c7, + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0x1d0a6d1a9519877805ac90d696faf2a5ffadc23986de8c698d541471c7244220, + 0x2208aaba508ae816da4f333b7854fbbcd10eea1db284ec3e9f4de02b25f6e9d4, + 0x28a58901035b2c99e36a7d29b587a215c9e59268e2f8e01a175720971ccf04ec, + 0x112f6d8d42b0a0d123a07865ca1376df317a2a14ffc0191226f38a8adfd6238, + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0x8c6eb19c016d1833174dda182d266d5c727f97fb4d01f1daf906b6d3c6e2308, + 0x1359d2d6c8b5a116d0b38b95f9c642df75b1be9a48c8698ecfea9103f73f1879, + 0x10c5052ec67ab9b6a467c1cc1878d91aaa07aacf7725f8a5ed42b699c4af3ca7, + 0x583c4d292d54f3cdb708803e6338fc6afdb188d5d4e9f060193823684c96c75, + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0x2d94a1c55be382151a4054c5b96322e7bcd1fe2b3e076e16ee2c18bfc06f57b4, + 0x15e3402fdde8770fb997369579c1b1703ef77c671927ead80dbc64dd2211c3ec, + 0x185be98784817f22f7b21e6b867d5a71b5000bef8bb902eb302677e20a727be3, + 0x18db4321c721c03666ed8927c89890aa8aad1b00c054547b5ca14cd94de467b6, + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0x2a852b6247f5d61f0c390b3f3d799188528849bcd2cd0aff4eb2134a039b5126, + 0x2510aeed51b7f506e65fb9a18ee0124aa5276f6de1cd771b165930204da58f22, + 0xf2074a32eb8260fb5bd3a236f03a47b47b7fb54dcad1d7977d6486513bab5f2, + 0x2f4c69297866bd45a8270e19941926cec3531c9e12c4c2c84971404bfa044090, + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0x154668727d2dbadf05d083a65093c0d0e92df5fd5f3fd75e9b792c562a37473f, + 0x1e6ffc5d6a1ff5dc4fd77fc5ab5c8c4e8d3e2e375bcd1194a91e5b0f7b13cadf, + 0x2cf1a1d7c44309109d75acbc9395cb8398c8b2d428538571fafa389da29990c6, + 0x140fb39a89f26f6d87cf76cd5ce8da47aa5d8a023e24cf016ecf64cf793c9880, + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0x1289d13d58a17b5bf0712b201fb3cddfce2c16dac159990b8298a93a8589f9e8, + 0xf45cf974d2c9edb5781e8d3d207adc8370cf56bc5218749610920fe98b2db2e, + 0x11909c81a16518046b79edfd24f5abcc585a81d1b333568b8687a1c9eceb44d4, + 0x2990b23c81882f7709f3b891a0e3da4d6917672f2d5a1041fd7bbd6792330d16, + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0x609551b14716ca3cd5560e0821e7285e0a083ea9a16dc102ecf461e4aef7277, + 0xc8c1abdfab99d03fd93dced2467354b6175de1755f4f93dc0880eaa08d03f77, + 0x138bd098c4923b9fbd02f33f8bec6c730db3fed298ec09f78a7a55d08f2e0b10, + 0x2e61e4bc021630114673f0f77161ae55dcd0b45ce07d9ae3f21bb5a3190f14c0, + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0x124860913e3df8f65a9c4060ce3297c626abd1c22401c905ddb408260d8e910, + 0x13807f89c394a133ec104804d955cbe125f24c5701d98286c6ac8b7ed052ec8, + 0x2e88d1a6938f0788132aa9eeaec08d2f59aa444050c8f4c4e85578abb0fc2fe5, + 0x1f3d24f17cfc6050a0cbf64e1f1787e2257be3c3ba607c2e8fcc1f26abf3104, + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0x1fe1cb0e2ae169f83b9d4f133d41fb5b3fe6c76a82a916bfd9b62f82f0f8d0bf, + 0xef79351229409cd353329221229827e19946f3d8d1c48bf5e3377f9177071f3, + 0x18fb2e46fc1b90fe1c4893ef77a9d111507551883127860e89088608373beda9, + 0x77afe2579f42ec14c32ef0761e23a3cc0ad6263a68c5cb61916bd57120d1868, + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0x79769092daa5a752642c04ccf8a6ea54e2ac9836fdd65d248b186f1490b7b99, + 0x1d8bf229c19968f0254eb6e09c5c8bfd67eb9734606b676b663c76cf76bab4a5, + 0x2a33b7d855e7fe55f93556e49e4b37737664f14236f17256428f29f6ec1bddad, + 0x25b0331d7e2b15af4ec161c86e84ba6ab2056077e7aa7536340dc3187ccca8b2, + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0x762098f5fe26598ccbf45e4810211b0ffcf8ccbb92c16e2f4f13f22342474e2, + 0xe234d720d70b2886d0da4c007b1bda42362e144185c70716dece2b6172c2514, + 0x1d82bedccd2bc8a06e3742e720b7fec2ea72182f11c0c60d135c811152aa4b60, + 0x480064d4b3eb0ada5e9a3e7d05930b7c3397fd6b94d481314bd1c690a17c979, + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0x10a892763b3cca9ef7593fbb1140edc8c8e4580568560cf41867f7464fb0c11a, + 0xb5ec64548ea841ac921f9b2553680785978b315667ae4714dde4cd7f4de8b91, + 0x10554aca4e348e5949761bd7131dfaebd78010edd030e1a9ce3c65c9db931d46, + 0x15be66f38d86b0998b93655462b1f475b9be9de306e150d4ac648fab3db0cff6, + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0x176ad3600fd3491182d182957ffad01bf6c26e9d4ab0c23caaf308e427d3dbe8, + 0x2b6f355b3dbf65f09335001d705ac125e3beb20f4fc11bd3ce82b5cf0af2e6f2, + 0x1c85c06a6d5d40d81d7c89edefb32d1a8448c51288fa296b6de9ff788c77451, + 0x20e1e876c4746a0cbd9a51d76b2e25f82361c389e43f7d1f51a70aaac2460d79, + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0x20e46219f684186d2a024b637bc35a29ee3b08ce737701392d987dda9217fa08, + 0x2ea7279db9f2aa0f654e987907277c24480766367a8bd90e28be0f2ed6091367, + 0x136be2a7f18924c9362096d472bc75ca0969dc077c9171b1641be95091780f74, + 0x1ca2033501baa3f73067c4300fb0f51119ed5736fbc8f1f6c924baf0df5a0e9e, + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0xa82f199c2505277ecaa75e495f34e3525824f7a4a9d9fa1da810832b48a50c7, + 0xecf10485307b4bae92fefb0d7f7782a9f37a2722e7ed9eb7925a2dea580b7d5, + 0x7b642138dfd6a6dd12aa22f08a8296d68615c8478f13af16aebbbb339a3936b, + 0x1d9dda43a25593ffd2256d34921fb86ed70e760ba76d61e9cbc3b6dd0f1a2150, + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0x2f1af228520c8b751dc91136c91c6bccd5367eb08213d392958ce2fd3d7d2fce, + 0x1fecfe833ad540455c6d6c1ab3de4abae61ada625a1a2b6b18551a45a6cde123, + 0x18fc8e608c735b2b3b0d7583460227575657ff8a77abe637bdd3ad28e4a23c88, + 0x28f740bc1182e9706ebf03cb3f53aba8a43ce0b618783a5586388a7547faa815, + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0x47998cc0af5a26b94ad301e4b998d29e960a4851cfd13822bed35b7146966a4, + 0x1b5f1525b31db911dda43e415e1b9a3a9725c7b52e880ee130a14a692b777b70, + 0x275a83fa5d19b4535f65e965a90eac9bf770ae9bd1d7b1af945fa57ed5c8de6e, + 0x2e8789257ed2cbcccb430568e49bc9dc2a563359808c9897ce3e40a6f6a27aa8, + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0x927f46cfe80feefeb2721a4c09e9d17f60c34500dcd6e41e2925a39c8e2c7c1, + 0x1f868ae04832a5dbc37619bfe6ab6a97fd8fb2cfbc1ecf9e0e484bbfe7698101, + 0x9d7a11e27d2f53109b73f745b2defed65d94ba80f308fb19ce6d56c9b45eff4, + 0x282d857cfe8da3b5104e1c2823fb7c5b9a7b25924fda5995b0c351aa2b879dff, + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0x20ba8a9fcec815b13f349ff830ae663b27576e135c0744f6987fb0f6ff49c217, + 0x11b6afc91e32f1ca4589fba12e657d226d57b471ddd2ab1b66a8ae4dcbfb136e, + 0x2e666402ac9cc588316e335c7d93db344788eec2c72ddf3f908141736cebc3be, + 0x17522e0e9e64f795a202a110e283faad7057aec5c9ed9a1a74920f2794f18595, + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0x2d2ed17f7a1f3ee9e20b470cad4cc7319e6adb40e2ff24b7878cb9878edbd3b9, + 0x1a81efb19d7e1edaa96fa276e89e85d08f75e54a8136f4d73c937da16c7bf9f4, + 0x27ff57c1ca847e57210a7b44e52e5630f299c5f451c7a0d515a16bb3bd33e237, + 0x1c1a8e22230abcd13c5be96031bfa167840d117b3c6a5a0a11be26a7f5fb1a94, + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0x2a1c3f15d4927c843627a9cd533e4250d81e7774d2c32b59d5836f9c19a5657, + 0x2ddbb7239eb904d81c52499b37cb4be1af0373a10ac112e185acb219899357e4, + 0xdff198393085a754e0d6faec54be81d8edf8bc25edadab48a86fad6da0afb60, + 0x10d50c2473146bbc76275fcc589d038dec8db28728789f28b6d5f504bd1645ca, + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0x61e8328fb5593f92a53dfd40e1022e6231ba45948506282536b08b4476c1538, + 0x1b589243847198ded90b644bee31ac58067debf3f07d3c51cfa5a0dd9f6d9784, + 0x4b00c0da1f851e59863b053bd4c6087190f0bdcced99d5ce6f67a420a3bd1f7, + 0x239941a46c2b93d9126a70163009a7ac27f8a8d42e35018b3bec8cdcb5ddfd67, + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0x204f26ca7993b03ac2c35377cb0a3712bfc9bc3ec0bfecb4e87ef6814acf2ea2, + 0x85aff9c7fdadba039d832d8be165a1e5747cf7308d515e348ef117e926d721c, + 0x249042a8dc111f27c4ae9db044c0b0b3f10e57d05e093158efd375df00ea2068, + 0x6e799bcdf2b4a74542854f3029803e2f84550665203327b3e0825977413e96b, + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0x1cb3caed4bffb6aca9f4d2c002921bc3fffed333cae12085c612496183b87996, + 0xb47e9755fae480128a128bfd4faa6a3dd6ea03cab566889dcd99e84d310d51c, + 0xc7e4cea365c2061920a0c9fd2c360a6506293bc024fd1ca3f0bb730da886a4f, + 0x21da1f701bac77bcbbaa30d964d6f6f63dbe1b20d9d6988c8dcd7ba4187215df, + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0x9ae612e8ba1ca1370905fb67899d10db86b47bd19965b6edd1a9486e3c6cc55, + 0x262e1e0b56cac47fc150f284491190e6aab75445b0c99373fe1f7a0e3b95cf3d, + 0x234bf4a7dce7587c2c87c293e3bb7c9e2a7bfa5f29fd4ddeaa5d3f67491d34bd, + 0x2f6cbac694c886b02d0a527cac744fb658d2690e213d7432eee67f6cb69f70c2, + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0x22accb18b7c49b4b7bb8c9fdf78b7aded52aa1842fff818d9a3300876dec3ad9, + 0x81e2f0652f898c6d659f22d2c77be302eabd9182a0b3d3cbf623a1df7f8f2fc, + 0x12c0a25e70d006eccea3ada75d669b8c534b962890f3ffc016b3186ad675b935, + 0x10ef9c23848128cc2fd6fc869df24d7ab56efd349edd56f49f8d4f2381df3259, + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0x2161cd280772819dd4a81262b71df1bcc2c1d41b9491e0620bda347962b240f0, + 0x2cebb0ae5108318eb406590041b5248292533364f799bc41b7f4fdd12cb8d38a, + 0x2b2092f86b5979a7fe4f7c22d9561f3bf2852283a656880fb759e08709a0a62f, + 0x1566b3402d774b8c08146188425a442450cfc900cf643e7382b2d8507a065fed, + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0x11a316aa31607f268fb4c56d6c57ba01627c3635fccf8d3d1a163e601d1a0173, + 0xde7ee069c934256b782648b560e595408a5e8434644609152e353d9c2874e44, + 0x2d36f4029245704cc84df0297708c5e5845c36ae706c72e67128b8949eab1af, + 0x1b8cc326b5ee160f53198c217fb34e899bde46cd82dabdc284d7951d546f858, + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0x27625da0f73ea07110689fb2187b71694cbf9203fd4ddf8a96ece85407550ebb, + 0x1cd8338a3e5b1ad7cdc0da581a6950f6dea349c3edda06cb99ba025b94e4790d, + 0x5ea02d65b209f6da763856c94b6438c78a8aed8d3e67e877a10a84072741a56, + 0x9f7cb68d4e388f85366cfcf284a895d8b6250ced627e810817743ce03330a55, + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0x18c6230ddc0f896827b043f5e58dbd1aec13995a202e4ebcdfeb969e9d5c1212, + 0x73a6114b997285e1a91c0a0fdccdaa8452e4f07bfd2e1a10578232096db6dcd, + 0x2e78746340b2a6d222c6a1fc0838adf5fe013f39b1660ce7a3e7742b2f37be7f, + 0x7aa27e7150baddd06303ad8e5e4bf4249b7ea846553def28e675259d3e5c851, + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0xb66fdec210ea4eabf623d2712cf4d9fa90273ccb4643f680cbc98345715ead8, + 0x2fb6a29d9f394a589b633b8a4d6be51c9c0601ce0b140be641acea41c49aa5e3, + 0x29025cc66fd041c4fc845e9c1c2cd1288569fb243d049bd675a69dc889b2ce2a, + 0x150963f0aca9bcbe4126214ab9c627a6f7ed731cfa695168b85d534b17be3f48, + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0xed59780302257663f72c1bfc6656eb7b5bca2e47bec0d5798a08a32a61a8a65, + 0x7e19cb8a893369b3d30ae188c767f391c11888a3000debfc8d30c06143cc084, + 0x600c7d2b6946345e5f1eeeafb5eb8ec2b6ecfe528d2c052cd860afb4a3aa272, + 0x596083b6c972bc13022a1f33d6523b4773f2cd0a480e19ea0125119f0385705, + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0x210b5c36f27a07d97f98b9d8663d85db2e64513099a8e1ef6db21043631e24c4, + 0x13bb2764bf1475cfc7bb9f3d563c5cc201c2489874e9159326a8f4930b7883f9, + 0x202cf557d625c26080eb082862a76757287872b181e89997219e4b7576e24d30, + 0xe561c3f8bd4f76e76d49e97142d220601fbc5a03d905a4728ea1f95fd8824b2, + 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, + 0xde20097480e7555471785de07bd9809d57dd859bbe827307c33ae9ed7890597, + 0x72f2a6287fb984bb810df8c5788eebcfd2825613cb72bb80cde8edd76d2e97d, + 0x2969f27eed31a480b9c36c764379dbca2cc8fdd1415c3dded62940bcde0bd771, + 0x143021ec686a3f330d5f9e654638065ce6cd79e28c5b3753326244ee65a1b1a7 + ] + ) } + // noir-fmt:ignore -pub fn x5_4_config() -> PoseidonConfig<256, 16> { +pub fn x5_4_config() -> PoseidonConfig<4, 88, 392> { config( 4, 8, 56, alpha(), - [11633431549750490989983886834189948010834808234699737327785600195936805266405,17353750182810071758476407404624088842693631054828301270920107619055744005334,11575173631114898451293296430061690731976535592475236587664058405912382527658,9724643380371653925020965751082872123058642683375812487991079305063678725624,20936725237749945635418633443468987188819556232926135747685274666391889856770,6427758822462294912934022562310355233516927282963039741999349770315205779230,16782979953202249973699352594809882974187694538612412531558950864304931387798,8979171037234948998646722737761679613767384188475887657669871981433930833742,5428827536651017352121626533783677797977876323745420084354839999137145767736,507241738797493565802569310165979445570507129759637903167193063764556368390,6711578168107599474498163409443059675558516582274824463959700553865920673097,2197359304646916921018958991647650011119043556688567376178243393652789311643,4634703622846121403803831560584049007806112989824652272428991253572845447400,17008376818199175111793852447685303011746023680921106348278379453039148937791,18430784755956196942937899353653692286521408688385681805132578732731487278753,4573768376486344895797915946239137669624900197544620153250805961657870918727,5624865188680173294191042415227598609140934495743721047183803859030618890703,8228252753786907198149068514193371173033070694924002912950645971088002709521,17586714789554691446538331362711502394998837215506284064347036653995353304693,12985198716830497423350597750558817467658937953000235442251074063454897365701,13480076116139680784838493959937969792577589073830107110893279354229821035984,480609231761423388761863647137314056373740727639536352979673303078459561332,19503345496799249258956440299354839375920540225688429628121751361906635419276,16837818502122887883669221005435922946567532037624537243846974433811447595173,5492108497278641078569490709794391352213168666744080628008171695469579703581,11365311159988448419785032079155356000691294261495515880484003277443744617083,13876891705632851072613751905778242936713392247975808888614530203269491723653,10660388389107698747692475159023710744797290186015856503629656779989214850043,18876318870401623474401728758498150977988613254023317877612912724282285739292,15543349138237018307536452195922365893694804703361435879256942490123776892424,2839988449157209999638903652853828318645773519300826410959678570041742458201,7566039810305694135184226097163626060317478635973510706368412858136696413063,6344830340705033582410486810600848473125256338903726340728639711688240744220,12475357769019880256619207099578191648078162511547701737481203260317463892731,13337401254840718303633782478677852514218549070508887338718446132574012311307,21161869193849404954234950798647336336709035097706159414187214758702055364571,20671052961616073313397254362345395594858011165315285344464242404604146448678,2772189387845778213446441819361180378678387127454165972767013098872140927416,3339032002224218054945450150550795352855387702520990006196627537441898997147,14919705931281848425960108279746818433850049439186607267862213649460469542157,17056699976793486403099510941807022658662936611123286147276760381688934087770,16144580075268719403964467603213740327573316872987042261854346306108421013323,15582343953927413680541644067712456296539774919658221087452235772880573393376,17528510080741946423534916423363640132610906812668323263058626230135522155749,3190600034239022251529646836642735752388641846393941612827022280601486805721,8463814172152682468446984305780323150741498069701538916468821815030498611418,16533435971270903741871235576178437313873873358463959658178441562520661055273,11845696835505436397913764735273748291716405946246049903478361223369666046634,18391057370973634202531308463652130631065370546571735004701144829951670507215,262537877325812689820791215463881982531707709719292538608229687240243203710,2187234489894387585309965540987639130975753519805550941279098789852422770021,19189656350920455659006418422409390013967064310525314160026356916172976152967,15839474183930359560478122372067744245080413846070743460407578046890458719219,1805019124769763805045852541831585930225376844141668951787801647576910524592,323592203814803486950280155834638828455175703393817797003361354810251742052,9780393509796825017346015868945480913627956475147371732521398519483580624282,14009429785059642386335012561867511048847749030947687313594053997432177705759,13749550162460745037234826077137388777330401847577727796245150843898019635981,19497187499283431845443758879472819384797584633472792651343926414232528405311,3708428802547661961864524194762556064568867603968214870300574294082023305587,1339414413482882567499652761996854155383863472782829777976929310155400981782,6396261245879814100794661157306877072718690153118140891315137894471052482309,2069661495404347929962833138824526893650803079024564477269192079629046031674,15793521554502133342917616035884588152451122589545915605459159078589855944361,17053424498357819626596285492499512504457128907932827007302385782133229252374,13658536470391360399708067455536748955260723760813498481671323619545320978896,21546095668130239633971575351786704948662094117932406102037724221634677838565,21411726238386979516934941789127061362496195649331822900487557574597304399109,1944776378988765673004063363506638781964264107780425928778257145151172817981,15590719714223718537172639598316570285163081746016049278954513732528516468773,1351266421179051765004709939353170430290500926943038391678843253157009556309,6772476224477167317130064764757502335545080109882028900432703947986275397548,10670120969725161535937685539136065944959698664551200616467222887025111751992,4731853626374224678749618809759140702342195350742653173378450474772131006181,14473527495914528513885847341981310373531349450901830749157165104135412062812,16937191362061486658876740597821783333355021670608822932942683228741190786143,5656559696428674390125424316117443507583679061659043998559560535270557939546,8897648276515725841133578021896617755369443750194849587616503841335248902806,14938684446722672719637788054570691068799510611164812175626676768545923371470,15284149043690546115252102390417391226617211133644099356880071475803043461465,2623479025068612775740107497276979457946709347831661908218182874823658838107,6809791961761836061129379546794905411734858375517368211894790874813684813988,2417620338751920563196799065781703780495622795713803712576790485412779971775,4445143310792944321746901285176579692343442786777464604312772017806735512661,1429019233589939118995503267516676481141938536269008901607126781291273208629,19874283200702583165110559932895904979843482162236139561356679724680604144459,13426632171723830006915194799390005513190035492503509233177687891041405113055,10582332261829184460912611488470654685922576576939233092337240630493625631748,21233753931561918964692715735079738969202507286592442257083521969358109931739,15570526832729960536088203016939646235070527502823725736220985057263010426410,9379993197409194016084018867205217180276068758980710078281820842068357746159,20771047769547788232530761122022227554484215799917531852224053856574439035591,20468066117407230615347036860121267564735050776924839007390915936603720868039,5488458379783632930817704196671117722181776789793038046303454621235628350505,1394272944960494549436156060041871735938329188644910029274839018389507786995,5147716541319265558364686380685869814344975511061045836883803841066664401308,14583556014436264794011679557180458872925270147116325433110111823036572987256,11881598145635709076820802010238799308467020773223027240974808290357539410246,1566675577370566803714158020143436746360531503329117352692311127363508063658,212097210828847555076368799807292486212366234848453077606919035866276438405,7447795983723838393344606913699113402588250391491430720006009618589586043349,7626475329478847982857743246276194948757851985510858890691733676098590062312,148936322117705719734052984176402258788283488576388928671173547788498414614,15456385653678559339152734484033356164266089951521103188900320352052358038156,18207029603568083031075933940507782729612798852390383193518574746240484434885,2783356767974552799246444090988849933848968900471538294757665724820698962027,2721136724873145834448711197875719736776242904173494370334510875996324906822,2101139679159828164567502977338446902934095964116292264803779234163802308621,8995221857405946029753863203034191016106353727035116779995228902499254557482,502050382895618998241481591846956281507455925731652006822624065608151015665,4998642074447347292230083981705092465562944918178587362047610976950173759150,9349925422548495396957991080641322437286312278286826683803695584372829655908,11780347248050333407713097022607360765169543706092266937432199545936788840710,17875657248128792902343900636176628524337469245418171053476833541334867949063,10366707960411170224546487410133378396211437543372531210718212258701730218585,16918708725327525329474486073529093971911689155838787615544405646587858805834,18845394288827839099791436411179859406694814287249240544635770075956540806104,9838806160073701591447223014625214979004281138811495046618998465898136914308,10285680425916086863571101560978592912547567902925573205991454216988033815759,1292119286233210185026381033809498665433650491423040630240164455269575958565,2665524343601461489082054230426835550060387413710679950970616347092017688857,13502286133892103192305476866434484921895765252706158317341618311553476426306,686854655578191041672292972738875170071982317195092845673566320025160026512,9315942923163981372372434957632152754092082859001311184186702151150554806508,17166793131238158480636170455452575971861309825745828685724097210995239015581,4443784618760852757287735236046535266034706880634443644576653970979377878608,21470445782021672615018345703580059646973568891521510437236903770708690160080,6932852445473908850835611723958058203645654625170962537129706393570586565567,17078326120157725640173982185667969009350208542843294226397809921509565607842,19251873001736801921864956728611772738233338338726553113352118847732921831266,13062907978694932362695258750558734366820802962383346229947907261606619788585,16576609187793673559170206379939616900133457644695219057683704871664434872406,17140499059660867342372156843620845644831519603574612796639429147195776838516,16226688173010504218547945848523900236290532501559570164276462499487632388445,2806068123803905806401128967330263340459046260107112845068533446899070326517,17788735370835052317224182711467216134690146479710634688273650370951230404901,9840665370904113434661468973557421114403401847108482949465899631150766783733,17357287363046228581837055771327121704742940914150998420465281177406182088510,8956082469997974864521346025916496675956939495318858500685756691488425559998,10583741436561099911914917245130852199607666337956354910388730829023746895549,15241902639811607164983030447109332729761435946009172128089506810551693978973,10889882303914055687481932975789161945462141459528413507160087442461090813788,19789561133254944544821898921133697408237804586549835559829396563401674817160,20741336668287037026472434608739333171202674306575625457456116338034432647230,17864073449995977742930566850933082711031717858550870842712972350665650521079,6017691253505466300212182439349954426085752315661098358839308909771637792741,5209125836207196173669497054522582922896061838702136844305036341250990710540,8138726312837322624537330169363664364899441867118983214176695868443641051381,15491983986041746833254372934846748393213690608865689646440909282144232382678,5054332867608171303802774230688792431028169804536607979111644888500809938980,15427030776591294577308915282298854681562344215287630895931797573417982096417,21754057982677295571284116502193272661309010996970316384923307174180521790164,16265286590463120486705206231835953324076688991892805307349612983237844034032,17679791107777049796013011282788633179411040182820636236163074053597517790779,4281652562868629887097957174897458165728741859103571825874408386197225591996,9168010397863299719604788533602757515513214141450093775967322808686129400625,17584182367226175071087689123358883902969885218985589531538416263709138156515,15671512310414658663135385639435845966109237059155734764323312289873534719186,10536294659491685326297777845632759824567028904726211134518740400643540109527,13431319759608247201135260841651365578663315527795431484765940626659812285319,9584697124715190200241839387725546204368618031045071660911490086723434692561,5180327104839158483066851400960171505063442195966219343315555549982472660055,18888217223053385111625483360538133292128748730565502371803782424772027937822,19535732913737027522540340630296365525208404217634392013266346283017745945894,8577759627886344995887423695190093296190181539234301534326157005220006624466,16793670928407147476673650839110019799844249677846432113010280456483595763987,13926032620965299897272071104154310460519723329016284975305942957859374938463,4794697578055472890255676575927616606591024075768967985031137397587590174501,3529566190782060578446859853852791941913086545101307988176595267965876143250,3975008029239568933166738482470827494289192118694622729549964538823092192163,17739094873244464728483944474780943281491793683051033330476367597242349886622,7367136451127531266518046223598095299278392589059366687082785080179161005418,11175297939460631138047404082172242706491354303440776362693987984031241399771,21687543815463985355165197827968086406938428974327951792877419032069230058777,21156136641989461785420005321350884477682466566148802533375726181416623358719,17347558768803521970212188258074365309929638984714303299899732035040892048478,16293716234695956076322008955071091921491953458541407305955104663269677475740,4206144021605871396668976569508168522675546062304959729829228403361714668567,19988050626299122864942213847548542155670073758974734015174045163059179151544,747972634423324369570795147739377097591383105262743308036321386836856106229,4612470951309047869982067912468200581649949743307592869671537990797895413707,9630852913694079049153027193127278569487291430069466630362958024525616303220,17941539917430916523930519432495442476511211427972760202450248798031711471474,20332911350443969653703295317915788278109458962706923653715140186132935894113,21764801803055897327474057344100833670291402543384934706514147201527191846513,18792043166429470991157980448329308661526906138700725174612608941551872082876,12308177224490762720061048892842527800271687977085172836705858261595655154325,6234555076867437297776538521925679658360922070165740193866337972293380196151,4651047048822067434403056477377459986292934655827821636179452835839127581305,4762047093602693619418269784972874862577325737690375448572644958129932507374,12373514879531674477721132062882065826558811149582829246378921774344318418269,452512704634345955634014968317367844987135264395068376894497483188243356523,21642936370936057063268550589361090955573362743817395689260298777690935495218,16170209200627740434842090607802586195654207376087117044989637541681675086276,11682826760471401430136435257946377996085824742031456481961511737883954750045,20628055165039718158878805520495324869838279647796500565701893698896698211929,16438375313036818694140277721632185529697783132872683043559674569424388375143,4855690425141732729622202649174026736476144238882856677953515240716341676853,11680269552161854836013784579325442981497075865007420427279871128110023581360,7052688838948398479718163301866620773458411881591190572311273079833122884040,10339199500986679207942447430230758709198802637648680544816596214595887890122,16310974164366557619327768780809157500356605306298690718711623172209302167675,4572051236178600578566286373491186377601851723137133424312445102215267283375,20933392620931420860078756859763708025350478446661033451436796955762857910093,10145870387395991071594748880090507240612313913083518483680901820696866812598,11173854866888110108878560284050142518686158431744851782991510385755602063727,3895357290105797542988795070918100785105415165483657264407967118738833241858,16358886674154007883356717944805100413481233709808000948036974385803613296849,10544067501284177518983466437755150442726536257903869254459488412549270232123,10495171258604974589451578238018388630585794890815982293891430761424812600427,13820724103604550843562070971473423552484851063169471886037640613650155173554,2334954333435579600152488915208745055087482119087065911968347050969338669409,15100284614446277058846085121308897497066957549089629374506920751044105723791,8493821960754696376711287628276980042183127459347650448500304251148421115590,18612435536889941393944858783110719304584209891406420832295898519317994950798,362101794940079733974215941991047456600874474038781578925062694203564740952,11020033081956343850903875701444955317664141075326494650405276926536449284939,9396289482656518627529185765935649373549564165735162258912975312413185691167,6879055176150676925438486069371149089824290576271090206945130252868108043422,12466610601804566637227883322591924115458766539177061670432424956205788935144,6570302110526154075173287644133038486970998888099669190857256824048085590052,20997862990590350605775941983360263378441519274215787225587679916056749626824,2642485040919927233352421501444361753154137311893617974318977215281720542724,18832940311494549247524002614969382413324906834787422940144532352384742506504,18751288968473015103659806087408412890105261892140397690496125593160830694164,13938622158186434739533995447553824444480420613323252752005511269934155122652,12878982657080117316101160964182202074759312554860119090514406868768962707099,13757859113119127982418426758782225628393556023865807897214601826218702003247,11817871682869491875135867072669251115204978941736982465520516648114811792373,11336448548896065624515261709306933490181794458266726453198857687608284871020,194970717714150352477887371297168267861902418496792228400198694925721020795,4999282817977533227652305360183045040853565298259070645110453061034932285549,17094174197873140035316532568922652294881600587639905417701074492648767414173,8484251464872873032022789624790167173458682056313339863651348894878144808746,10260366716129057466862964875306868898686918428814373470382979997177852668590,549263552864476084904464374701167884060947403076520259964592729731619317724,10052714818439832487575851829190658679562445501271745818931448693381812170889,1735373362835209096342827192021124337509188507323448903608623506589963950966,7998373949540733111485892137806629484517602009122941425332571732658301689428,9035170288660659483243066011612158174896974797912618405030929911180945246244,6458619567307414386633203375143968061892762498463026121155477954682976784731,12314261817227551876673777186352972884847144237148169773300066404053441924532,19869454329688183813243851218196625862680921049019496233616575272637276975230,20326917073492686652690019138603910654692396590122884746951129061818467704300,20403270805536666081472738304916561119325397964511536801752236086414818653063,2865941730880218719188224311916978807415673142487507504983320505748719154068,20614246027521726470902405957496110178017768563127335842405314212897493119848,12060194341463088508348622863463208827312128863463014006529428845777217660299,1128906798719793375274166820235650701301189774851381709919492584451845983197,19670876372911656158743764425809421400123168087389888660308456184201759209723,5647230694522866559497222129254930524469944430191328619422533907417776118543,318629082509194371490189248876734616088516535434806492900653650176451776632,13685970881538585172319228162662520285656571966985351768743970447782846353365,8283840607829148567836919316142994745766280854211662326632930274668867638198,8968895518159422029900464138741638511289476298837958524156654785428413265371,10061801991000917366002570579819627134666386452411986168205986791283562415829], - [16023668707004248971294664614290028914393192768609916554276071736843535714477,17849615858846139011678879517964683507928512741474025695659909954675835121177,1013663139540921998616312712475594638459213772728467613870351821911056489570,13211800058103802189838759488224684841774731021206389709687693993627918500545,19204974983793400699898444372535256207646557857575315905278218870961389967884,3722304780857845144568029505892077496425786544014166938942516810831732569870,11920634922168932145084219049241528148129057802067880076377897257847125830511,6085682566123812000257211683010755099394491689511511633947011263229442977967,14672613178263529785795301930884172260797190868602674472542654261498546023746,20850178060552184587113773087797340350525370429749200838012809627359404457643,7082289538076771741936674361200789891432311337766695368327626572220036527624,1787876543469562003404632310460227730887431311758627706450615128255538398187,21407770160218607278833379114951608489910182969042472165261557405353704846967,16058955581309173858487265533260133430557379878452348481750737813742488209262,593311177550138061601452020934455734040559402531605836278498327468203888086,341662423637860635938968460722645910313598807845686354625820505885069260074] + [ + 0x19b849f69450b06848da1d39bd5e4a4302bb86744edc26238b0878e269ed23e5, + 0x265ddfe127dd51bd7239347b758f0a1320eb2cc7450acc1dad47f80c8dcf34d6, + 0x199750ec472f1809e0f66a545e1e51624108ac845015c2aa3dfc36bab497d8aa, + 0x157ff3fe65ac7208110f06a5f74302b14d743ea25067f0ffd032f787c7f1cdf8, + 0x1b0f68f0726a0514a4d05b377b58aabc45945842e70183784a4ab5a32337b8f8, + 0x1228d2565787140430569d69342d374d85509dea4245db479fdef1a425e27526, + 0x17a8784ecdcdd6e550875c36a89610f7b8c1d245d52f53ff96eeb91283585e0b, + 0x9870a8b450722a2b2d5ee7ae865aaf0aa00adcfc31520a32e0ceaa250aaebaf, + 0x1e1d6aaa902574e3e4055c6b6f03a49b2bbdb7847f940ebc78c0a6d3f9372a64, + 0x2816c4fa6b085487e1eec1eefd92ee9fef40f30190ac61009103d03266550db2, + 0x17359fd88be36ba867000e83f76ffb46660634efbad15dcf4d4d502d427ff51c, + 0xe3004cb44ba455a3f16fefbd0c026404cbac203c0f236baad879610b8661022, + 0xa55f276af1ceb6ebc6c6820f334b26f11ca4af98c833bc1b496193d6b04a7ca, + 0x1ee4b0458adcd4c4861a27adc1404a5981d320b6b8e20e51d31b9b877e8346d, + 0x14315e2753e7fb94f70199f8645d78f87c194a4054e69872b3841da1b4f482f1, + 0x2b7b63ecffd55d95c660f435ad9e2e25f266cb57e17ebd1b6b0d75e88a6a56d6, + 0xbb56fa3e9fd48ab46d4e7295bbe1204b652ebe958221860f56e38db80d83c0, + 0x50653bf5dd59edd6d15fa6071f5005057218b33a8f92a58b9c2656081249f82, + 0x2c575423e24b522655c5a976c65d069287900c8d5825514098c5b13c86f1fcdc, + 0x2ff3a2ccdee91e09a32f74232b704cdd99f72c1f78557a2ce568b07e218071d7, + 0x1144734901a81c1543b8bc6fc9d365f50469eb89949491d3693dbe9c6238d90c, + 0x1eff9a954e24bcd4af20b6ab74d89e1cd38bc694a9e75ea6da217a98db80cd22, + 0x14707de7496c5638f97fe9bd7d485c20ead6bfdbfc0599791e49fad0301cd6df, + 0x13d0de341ba819f90fe3ef1f7ce0a54d8538acdd9b3ef840a91d48ee536042b8, + 0x26520ab1d20055daded712d59b07088458c18afbd0da58aee9f151a903372ba1, + 0x68cb4827ac485fc6e7537a3c0a06d08a4c2790f5c65d9866d75296999f7495f, + 0x7d6baaa2e587c21b03dfa0eb71136e2982cb389b438c8bc282748d0e674e89e, + 0x15b92d36db02cb16b831eeab2e6ed75d126ffbc274cc3362370851526de13d27, + 0x277b9ce89133de7b7918ad5fcfab7323ef5b9c1916b588cd7e5a0d814cbc3395, + 0x2ae847b66b3c5d73b70b733040aa86c51f737092d65c3492d529000fa1802b24, + 0x2fa3e8ae1fef974cded6aba6dc25cf567e16e0af29e675706643f21bf8efd651, + 0xb1d4b9508cec4d19aa53f4efe46c57952dbd368fcbcd454a8b1087bc18a2088, + 0x2d381014d01578b888b3273270babdc393ac392e7958be0478947fafa569bb0, + 0x2e79a827c85406242523a94431007021bc865a45cabcba4368c41d4486fefec8, + 0x207c99b7d594a5c61d7e60cc2365c4c0c804cd434098af6244f0a00c259b347, + 0x119c124086ea58ebb83f14f262c693424360e97e6fb42ae8596badbe9edb2dca, + 0x104ff38cca0f00173ccd0b68bddba09fc543f074f753bd8e413f8334f887a251, + 0x2f5b5377bd156f89845811eb262436638dc038b8cb10e147a87df4c0e2384253, + 0xf70e8e02d1d23968930a8e0db69b1c20204f3e3b4cecd101f81476d0b5ea996, + 0x1ac4653a51071ae722f90a03f006d8575814db782b7f19f607dae4d56ad586b3, + 0x12b12600e3bfd8e7bdfae5ef9c4f3805fa41e74acabf7de817823017a8b23db9, + 0x11b9d19908919dacb7e0f8d0ba77286d417529a18a1d89c405ed1c30289fdd28, + 0x2c350d245f4f75864744f88dbff8fe335b00f4fb688895c1363a7484ace820d3, + 0x16a7f76fd2b2147db6ef94c22c78bff782de17ef73e52da7df82603f422b461f, + 0x1d18d8024be1e96ec25626af06a139f6093545aa504033dac7e285d1cc3db3de, + 0xc8cab1ad5998072945b9b88228f53c295466819fb94d8f6a9ed449be8f7c18c, + 0x1a68d133d703cd406ca30041913ce3423c73b13384187ab1530109b756ad4f7a, + 0x24a58b9e86ce823ff4c45342941417ff23d03c80fcdef9498ca0d860855e01a9, + 0xe6315c93fbb89d38021148b6c35320fb793c41c6a4386d6aed6acfe2f952c57, + 0x2c3806d99a69ce63299e876f5f218c7295d87224795d7568d558696e34c692f8, + 0x59c893a771e94774d49a356494568dd376856ab89705dff25db8273860fa04e, + 0x1166d9819c4faae8982243d0deb1f8977027d5cc56bf52ce260bec5e27e8b0f5, + 0x12806fab3fcb09fc2b79406c3c203c4965fc7259112af2104312e1537327e0a3, + 0x172015e0e33736058f60aa33e82d3dd73dc3ead89f98ded0dba35dcc1d8bda2c, + 0x77ba18800d852d0a34f70ae8cfd68a080296bf9d47a1b40de7e6fd6392a0d30, + 0x2094ecd768bfa8f0df0d78d0d946e1aff4a2d38e029e41479d6e3c0fe79fa8b9, + 0xccebd302afe84c20ff774d3c1f650ca7cd0bca08baa1e261da9c7441a823f89, + 0x5b9303053bb40c73671f5d55b4052e0d5549871f1b5283f01485a6b568cd05, + 0x2527289084ab492275b4cd67d38311a2b816eaa68ee6bdb2389eeefd6ba4c721, + 0x2222f9738290d8d5f2a3eacdad95f12cd4e7417ed2661b012f6448c7503877f2, + 0x226c8208f26d69e6b7e02fe26557e6bd160fcbe27ee741fd1e581161c1789354, + 0x216b208c0261f3c91faf609e15f7a9d4853e40d9204496b2441115d73c2941c5, + 0xe0d660e046a259f3bad6829729b6ae3151fbcd75de33b122fe134ca3d5a4dd6, + 0x240f039d2026b3266f39ba5c4ec48ac6ace88aadaef991498cd52daaa0ffbba8, + 0x28c8cccf7b40a2c3cfd2eee0ec4d160a876a4dfeb408ffe333e92fa5e1ee4d79, + 0xd7f81b4b46d4f247c4243f045a852cc957d2b2923d28eb2fa77b5a9844efd69, + 0x2be432f87b2c5094a82c788457651dd8cdb0200ac3b42860cbf54475996b772f, + 0x13ea39f2d63d9adae187af14dd07b533d45a63435e0ea4e5e555d35e70d4016b, + 0x29e3b1afe1973be9cd1cf4b047325abfaa65cf2b98ff3aed47870461977ec921, + 0x8db7d684e6b841b5e9692498f95a1f950a1cf1eb638bb4e48f3bc1a3c571197, + 0xf4f1041a976aa05196da1c042124e3277ea1a28fb6eeeab4bec1243bd31618b, + 0x5a9d0526d6f18c86b255f00e86ec34e7f8a26c251b51c21fe4c12bdc4c0ff1d, + 0x284b0304dd6ce669bcf650c5ab85c89d4410d472aa6eb00df1b8d17e52f2f3ff, + 0x2363e9b01a0163598962ff86907002f95902e725049294ca7ab10cc7aa3f06ba, + 0x2c2db12647c4c0461dd3290a75c5f2fd8d7f115b3e040cb05dd7e3ad260d842, + 0x2e3c42f671431f9560f3d0863ac445052422d5b993e9fda6b81486b14ffe3a74, + 0x1d38441f228c0ce22ff2882560f5d7ee3b4c0caa101371cb7782ffd97af5fff1, + 0x268141b0e49c59eab1d573ead4e2e1f379364dd133f2cec574c25ade2c794287, + 0x2209cb2e187df1522810d3f28868da6cf52af9a65dbd7b806049f472d966374a, + 0xa5eb2510e6f804d1830d7974ac1677d082034e5388bfaee91a319eca7c1ffab, + 0x1cb2864c38800736f8f3ad98669d3ad7a9d5ee52138e96b8a7015e1089e36ae0, + 0x2af8ed05bfc8f8ada547ee9bc6c7c6c5e8c15c6c0d380a3f9aa277273321b54e, + 0xf85d1593b35be03f79b222885555a252bf1f0a3911d784132c49b1a96ac0f3c, + 0x29095192ec53e0b859eba456295d95bc4567d351a6dad391b8b89707855008c5, + 0x1a92efde1f5fa56aeb02b4c4b8f51ac80831f898c7843407113fbb6011177854, + 0x2a05e8deeea15e4377c080aa70fd6a86dc73f3fdfa6b55f5610614c184b0b02e, + 0x12119f3b019cc3fc46ecc80893e86f510b1dd4030b2ce28c9dadcd1e71ad4891, + 0x42b6ffe687bc23a2bf6b73317286a543c60ed122fc225aae742c3a1c2dd3a1d + ], + [ + [ + 0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, + 0x2a75a171563b807db525be259699ab28fe9bc7fb1f70943ff049bc970e841a0c, + 0x2070679e798782ef592a52ca9cef820d497ad2eecbaa7e42f366b3e521c4ed42, + 0x2f545e578202c9732488540e41f783b68ff0613fd79375f8ba8b3d30958e7677 + ], + [ + 0x277686494f7644bbc4a9b194e10724eb967f1dc58718e59e3cedc821b2a7ae19, + 0x83abff5e10051f078e2827d092e1ae808b4dd3e15ccc3706f38ce4157b6770e, + 0x2e18c8570d20bf5df800739a53da75d906ece318cd224ab6b3a2be979e2d7eab, + 0x23810bf82877fc19bff7eefeae3faf4bb8104c32ba4cd701596a15623d01476e + ], + [ + 0x23db68784e3f0cc0b85618826a9b3505129c16479973b0a84a4529e66b09c62, + 0x1a5ad71bbbecd8a97dc49cfdbae303ad24d5c4741eab8b7568a9ff8253a1eb6f, + 0xfa86f0f27e4d3dd7f3367ce86f684f1f2e4386d3e5b9f38fa283c6aa723b608, + 0x14fcd5eb0be6d5beeafc4944034cf321c068ef930f10be2207ed58d2a34cdd6 + ], + [ + 0x1d359d245f286c12d50d663bae733f978af08cdbd63017c57b3a75646ff382c1, + 0xd745fd00dd167fb86772133640f02ce945004a7bc2c59e8790f725c5d84f0af, + 0x3f3e6fab791f16628168e4b14dbaeb657035ee3da6b2ca83f0c2491e0b403eb, + 0xc15fc3a1d5733dd835eae0823e377f8ba4a8b627627cc2bb661c25d20fb52a + ] + ], + [ +[ +0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, +0x2b257df708d2f3d6785ff39129c7f268c13aef87ee92e9096bd6bd8d2989a74, +0x224a7cc70daf93a67ba74c0f2d80c5b0aea7ec1bb1f4e17ea21ff147c58b0a1b, +0x18ce43c42faa57788e66b11b59c98363b6970c4fbe9206a0986ac7a4438b96c9 +], +[ +0x277686494f7644bbc4a9b194e10724eb967f1dc58718e59e3cedc821b2a7ae19, +0x27907df41fa277d8c74c3725e5b8be54f4b35d3d0b6e57b26ead3cde3d431897, +0x1b7e85dfcfe013c45746d870fb2114991d43131fadbf80494c01d5b105d44a5e, +0x2c1597f81dc951f0b27440567676ac64ea1b184e65eb25292cc4da61d8bf9824 +], +[ +0x23db68784e3f0cc0b85618826a9b3505129c16479973b0a84a4529e66b09c62, +0x2460a032cf84ecd1f57096c9d21f5d48d1b21abc6d70277d7a75946997aed17, +0xc7a2ae4396db1838e5cb1ee490a768c1777efac919031924ab242d19be92806, +0x8c2147f957a152ffc37eec7b1cb029c07ecfabcc84489502a6e052aa6f94288 +], +[ +0x1d359d245f286c12d50d663bae733f978af08cdbd63017c57b3a75646ff382c1, +0x2456b3c4841aabbcc4bcb4950dae4a0f8e60cf0511decb8b67afdabeca0dc590, +0x1a2e45b92aba8f36f92110d68941ce37d39fe27d02b794d53f7b961b7ed377c5, +0x182d95b63ec720b3af3a3bc6d0a6012d4885ba5754f32aa1f1d92ba130fe5745 +] +], + [ + 0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, + 0x2ca7b911ea4f6a11da0bd5e72ab3cc621c5908b59ff3d76c609ea9c2fba8fa41, + 0x2de5f3a5bbe5b20d77ba6a6f8ffe2db01ff5000901b9ce0140df133385fd9506, + 0xa150cdbffe3c60c7a52cefa903bbee4d3846d24339f926c3655cdf9f81f67fb, + 0x2026ad7e03636deef47934dd0d5dd29d87056d172e993bf5e96d6a3bb32d2e9c, + 0x232507a3d48ca163c5e1b6f5bf391141524733d9cef80d404fdf78393c90151d, + 0x1b16b96e6aec89d326a5a6c18336ec3c56e7189f8c1fe74c5c46074b865a1d83, + 0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, + 0xfdf5d15426498ac82411ff8a7a3884894f02c5242eab1dd7fdfca1cfdabd35b, + 0x97cfa1218fe00b4edf8ce61cd20b4f8875ea5c8282d90f6f7153c9463bfbd95, + 0xfd1ebd67968d1e49926c3952aaf96d3558aa856acbfe48e5a9fdb4285ad9bda, + 0x27d5dc47f678316695d548d3b4fd1b00244a11d4cb753edd917d849cfa02fb8c, + 0x2602ddd7ea3a280860321a70aa806562a57bebfa5a0f5d2770f3a169b88ae244, + 0x2fafd30b7fac7a6699776892b07366b40fa387bc4141e009ee42070337088a89, + 0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, + 0x1b2ac2c9f97eb32560cee0b8e8320f52866b17042d2c7c13178dbd963936517, + 0xc6db19118e83768bce24e1556ab9d383adb0f4f2b63c3f540d5b5e4deebb1f4, + 0xf94cafc14403845ea574997bf75caba6b2016ee5a10de57ae35923c9c6a2261, + 0x9145c337938ac3f71b78022c80fcdce4c1742f47dd2190c31c3cc5a41980f5d, + 0xa0ca462d8ae218e235b6f24f4c17747886524aded7e4f3a59631497a4f98863, + 0x1851288ccce2bdece3a7f68ff33b00cb961e6292f2af29c775cdf6ce3fe0777b, + 0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, + 0x9ad33992db79124edac791c80e82876cf3a60a043edfcd7bfb5a93ee3feab08, + 0xb320d1000c50439a989886c4c11e711bd26667e61c50afba9d347cbd4b312f3, + 0x26123488a4f037ba7b2a51391f25f91642ae52bae1435dfe32c5f47ce63f68a5, + 0xd7a4403c3407d64ff5f63275add86c161183b2f1e88dab842607a8f3fcaa270, + 0x2cad68fb4be69ca135d9b37e2d3084557efa6423a9662f1fb24150b310c71727, + 0x2e122deb202b0e2c6a25e15226c09b9564cc57a8fc0d3645be77c36f8f27d4fd, + 0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, + 0x23e090845b17c18cc12ff83ce7deb2e58cff2f37771c39cd0b68ba14f4cd65ac, + 0x8b041b40e47ef1883a30a5e631cb1e0596543f5c240701002be9d495d59a775, + 0x19d0ad6176cd87e6109b92dff1b863104182e2c85bbaac5330b2b7a4b56f9a6e, + 0x11296e1ff67a98dff758d023ea74c5fabe372a797f86a621bac4bbcdf31878bd, + 0x1b0943c04cc4c3885335624a4df555ff89e439a40e6691d5db44732aea1b36ab, + 0xc2cb45703a55a050e57ca3e51bf386b2cba4d5dadeb1749f8a6e047c5e9ac1d, + 0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, + 0x20c061a0f70692748ab2f61b7e52e5ddd5e704e51de165eb19312700eef604a9, + 0x2aeb2df6a12c099b42c03dac1557681f03947ecd76426d6cb8a749dfb9f964f0, + 0x111fa84f899677752592a75d53083c3188d97a72d8aa1be3835b681bc6813270, + 0x1aad37ed6a2102cb892b98a7783fb019752cc8c0327190be544ad76165251f90, + 0x1be6d262a580b10956cd6163ef221f3d9b0dc3e5cbc7ab04b3f8f2a0ffe86be9, + 0x19fb44907e93686f59b9f17c0266c8139f8f4d8a5d212503bec1c6ef72409fca, + 0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, + 0xccbd07f12f007d8f30c6150e395dacffde4eae8fa51bf6bea1d6a7c421a586d, + 0x9a3428b0108143dc9c78633aa3bb37807bcd9603406be211bb286e42b58cb52, + 0x2a7ab6ca90a4e66f52e863c4b0f515148798ac8f92661b2b816902e915d8227c, + 0x179239cb6d96131ef12f09a58f9535b66b23c4367bcfab687e9a7c3c880a040f, + 0x7f9eff8cd62907b5d607140bd0b0944d175f17abe2b2eed814b6463ad29b8ce, + 0x2f44cd6674099eae8cee5c6f84e9b25cfd7c801e0b457278e83fe4b511458c8e, + 0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, + 0x241d4acb53e51cee878b7d23223fd33311ff0aae81f4faa07816546eb732d8d9, + 0x13016b694f63245a8a9b2f09a84bef7c0711bb8838b3ad49e0b7838f6f644560, + 0x240a3ff47c2e7332534647a5a2fe278aff069cc479fa000d7c31a78ce2929bd1, + 0x1a510b683ed295b19be81ace3dfbf7cf1061b07a18579325f7cd001d38146c30, + 0x20c4eceba419b0575a95e295d84e71bd1a928d5ccca5d79a809059de3342c9cf, + 0xbaf9899a51723a56cda43c1aecd6c096a499b57ae1893e16a28908bc5dcff6a, + 0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, + 0x162315c3b31a4d5b766510f46974ff89071424364fd69c9bfba1b6e0bece8eac, + 0x2f6a4f9489ad4e1439c806d757799fd6ee58ca5d0560d15a8f658c6eb86f47d6, + 0xf67999a01cf660e19180113f770041cc147a335e19f545e3f31a61bb6b4efa9, + 0x9146d7f035d379789456542d3d727b593a6fc67252a631ec407053635478fa0, + 0x2e44a6eb2efede0a5768d8491e4c86bfcd63b0ee2f383b74d62af311cf91de5a, + 0x160631bd9c54749181816c9aca5fe004260ee7a56fd35fb56977ef04911d5e71, + 0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, + 0x26f7f151e37cde405da94d5b7e897e9768862af285902b590b636e12bb43c7af, + 0xeeffd18325f8754d15db8adf98d290ac816cab0e4315306b2418068e78dd02f, + 0x284277b5d2b0fd66df351ff703419da6b1aea5ee405bba09bd4a369e6eaea49a, + 0x13584c5168cf2fc77f884d111e05fa8512e7cffec60dd3a105503196d682ca12, + 0x1ebd55190bbbaae0e9dd1af991eaf3ae13af0e71fa686312224c886c97e9e2f9, + 0x13a449ace196028aea035af0cd9d5b763d29f8d292443a762d8be06b1e136dfb, + 0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, + 0x21fa424cf90bf0b715656aeb3d02acc326cb56880bcd91602efacf66164bd07b, + 0x24694b5ba9200603bca8f52d73d0f3fea26c0ee1939d2cec8a9bc5f961cd68c7, + 0x1a6d98f744fca59c910dfb19ad89d7c25f2c719332edbbafb6cc85c190e4e170, + 0xab904b12244246c2dd95c69a28ab91d2c34e641f697b5361bd91d1625c937dc, + 0xfd87c8923668cce921af698cda67103c048864129954800460374ded5b86770, + 0x2098ce0512ca13bea1141e48f14bc691b410cf81de7f597d062465e1431c4c2a, + 0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, + 0x4d94ebda7313ce25cd0dfcd1dde7992439daae630c054d7cfd6d690a85c27e9, + 0xaf2fa274dd5b1e16568fc4613e76c9ab4fa99d09d10105e98bd9b92b82ea455, + 0x19153b7441c48cd270b491762e96e470858714e9650aac65169577d2fc755af4, + 0x2a5c69d030248d78f70674af65d92a908a7c27c34f32f9fd2417450e0585254b, + 0x436d86f139382ffb61085560e2592290518eced5230894b4a8bcdebe06a88fb, + 0x23b40e7f1bd0b7fae8cf2ea0608ace9299b903ac8d9994f7448bc2e46090af99, + 0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, + 0x21427832371fd1ce0efebe904a3ffae941142d4f35ce77e064e256ab5937653a, + 0x1b527a15f36d4f03015a6ff483cfb5c18f8b331a7caf79237998fb914dd46149, + 0x13d847e25b71d35789c6cde81ad9ad9c1afa6ace79ecf363920dc233e5646338, + 0x238b13365a6b8fcd6580ff9f4bf267b01366a41d7c326c826be7dfec751bd480, + 0x2fdc1ab225df187a8fdece2e14114cb71f01ed887085eed22731ded19882966b, + 0x2fc9fa00830e2671b36e8eeec5c369a6b3fc27bd96905b5fc220fcf0458d1c3e, + 0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, + 0x101b70dd04be642aa07377610e3ee7d630bdb12e3b26295806b92e9f482151cb, + 0x1227872231f192f1c81440c79fdebe597ce8ad03894cb07ac9b3423e4db90d10, + 0x1d01d734b7090603174951fe6d338fb3cccc00c0accf2ac8d45859f45166305c, + 0xe593e9c0177976f4caa991e54fc7eeae897fb723a9fad08a811b296f3e7b10e, + 0x2fe9b7637f54d7060ff768205f9e161a4cb3bd9dcf14a8bbcb37743b6fc60c16, + 0x26ac179b67db2c393739a450573022142905e5faa7e8efdd1c717eb603a6d9c2, + 0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, + 0x2e26f19972ff8bedefb7803e3284690f4fc7828cb0bcf3b5d5697b82714a171a, + 0x7f4790a30254f654fb0a465c42217421998843693e2c2320e58cdf31a77ceea, + 0x16adbd595b9959b8b903db7df15187e66b7f6fd433fd2ed3ca0dab8d45f8d031, + 0x1341399558f697e9e3b49e50ad3889a7a6ac1b7a169ffe1575a3172a4f33c75a, + 0x2c8e714ec99e38714e1d01b984f863c0d8e05b8c3b7ff6fbca20caacfbf3bf4, + 0xaeb4122ca96285c5eb5b52fe2c26355db417406c567aa6c35dec7fc58ba6176, + 0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, + 0x24f5e61cac001b78c4664cdc75cd8d75bde602e45c6dac698f3b28ded5a75604, + 0x158dab8b85f4412fdaefdee4d4f1fecb22f433672964d2ee7730b03663361f1d, + 0x210a7fd894e483be032c8e6876957968f2152a9f1eded11c3cd26539ab12a213, + 0x27dd83e178817fe22e022c22e620afb88e02fb15346322b8f70bb26485b813ed, + 0x28b60c3bcdd4693b01f111dab969ee5dfa4a8840defdbf2bbf38604ce4e23e70, + 0x5c56f683ea2d1d507676f03c411a29c9925215ca5d8e7f28a3da73cd7b513de, + 0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, + 0x1ef913d33b18f5ca1d000c2209646780c4580869163f287c4fbe537e270c308b, + 0x2f77767437b926272dcdeecd45416aaa588551a79bfeb15fc3c76d938d12afcb, + 0x2da62c50f92d8dcc0f6fdd909051708b0c8f21f966ad57ba303370f00209ed21, + 0x118c1924b687d5268424af23862f95eb629e1c699a7c27de27c581c495ef159f, + 0x1c20f20b601f89d66abc8e1854d3f29489de9a559584b9df842fb988980133c4, + 0x19078ba50370eef76a00f6c89217183bba9da58fe15d8a07c565caa019147772, + 0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, + 0x90d697c32be00d8b71f734d1f9023cdd11a587b51581e763bac5b3c766c5043, + 0x28309a912afc86848b67f7d85be9603f34ddceac4385e702f3662b3c2bdcf9e5, + 0xb100f36ac254ea63a6b92996445318f7053603e181261d07051400f302dc3bc, + 0x1931597f6dfad68193199a2166736c0c7e874189ca4d4d2555ef9d964b06c93e, + 0xb26976995fcdb354ec5c6c50e1b29139fc3c0a64709cbfc2fa992effa833800, + 0x2dd919c2edc302e56e0ece7b8537905feaa8c6dfa6c6130f94d68f7380bca019, + 0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, + 0x278b0231cff85bdeee497f6274fda5e07cefaac1ab05ce89f863db3fce5eeb29, + 0x9ee1dcae79dc90e4cf0d0fb5e6bdee96fa6b751adde822d30e3a80b1a5bb506, + 0x1769f50fb961ba50df8b9e03a12fc37bc965265fce93f9762b274328fd04afbd, + 0x20a99da43235a2bb30b0ef58d708d07740510f517b2eedb678a94aaa4edbdeee, + 0x11b7181ec0f9a1485d84cd91c342f70e1924c7a85f48a33e7bf8b5dba2b8b7a9, + 0x23453eb1a5e44e28b31107f29dc6a7bf4818a7ce156d2c7e81dff75cc02e937a, + 0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, + 0x2abc91241e3275e2028d68130f5533d6c8e3d1ec2942632fa4b91a49fc762880, + 0x21653a887bf627cba0b5a35ebb3329f4602afd8440ada0050c31b249d962f86e, + 0x2ffee525440cb92eafc518b16135ca00df2ccd813bf1f9bc458252d7ee478def, + 0x104bce734fb0322de9a91058ffb340e35c212a8af5c5b6ce1817344d82137d5, + 0x12db34f34145195e64455a298fe597ce8b757426784cc53975ed5a439b91c12a, + 0x13a9a61ca0008c1b911748f5593bbeaf633308428e4e85378214be04aef88b1c, + 0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, + 0x14ade7cef88a7726d51eb001357d8bfce8d1d8ec79472f6f2531d94792d4707a, + 0x24baee921a2b827fe96835346b85a3e94ab75b4eb9fcab4235cb9c54d0a077a6, + 0x4dfb441b179922b9e2ca9458de6d3aa0c653beca2fa7317a5d1fc4138e8782b, + 0x2efdb84c3c6faceb0f58fefdefc09e447ea2302291d3ab11101d487f3c679ee4, + 0x24d861650389f03a0da9d720f25df6e7ab3796ab597ed63d38055431655bbba5, + 0x1f8b2609f6999f6b15577697e90e891fc7b691c30c2695278042c2d152aac2ae, + 0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, + 0x242fed5519f01070752e2e3779757e5df21033baaab86a9fbdb1a54d11cd4db6, + 0x6dff8e392f51302fd8864de5068b943a2b04fb0b239c38b679faf689d69e1a9, + 0x1ce5db5cd27794bbda0f7215bd9404f46502d2b601f74fcf2cb1a5b7fd440fbc, + 0x16aea838ec8bc6e8b8f48309cd6e783cb4a337b92728f66f701f0d5efb32a80a, + 0x1fd21a8ff13f0ef12be5a125bfbd5e952ef1e46b4f3747f3fbd8198209d4ea95, + 0x125158b21d677618076854954d977c35a6313a1f37564e36bf6d072d2500df6, + 0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, + 0x2bb8e29cb323e3e2879d93d36e9312bb3c38a922cc6bcc1689f72793f5d4a18e, + 0xd0e2ecbd08e247ae7aff1bce2bc54ad1603fc2cf0ef32822701feeebf4e826a, + 0x2e7df0f7b842490b3f39d0d87bbb35a90cf23f3cfeef3c8a4fe4716a47699470, + 0x1d9dd609a2944aa782ecb1a08acb5c0bb857c7489920644f6839c93c10b37837, + 0x11ad269471d4b36fb23aa243904a0290608c32759020f082cda8b4d538752109, + 0x2d2f546cbe60a9822e205c3f3fd187bf89f6def774c3f988de86e4eb91595bea, + 0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, + 0x28113fd3a8d3b95ebcf29f2ddb54c6d9ea034a51e3bd1198e4c1f4f1dcf068d0, + 0x114ed46d49b389b14c202ba1c069ed4d836c131dcec2472f4bb78f803b90025b, + 0x14a217bf8737fb3570e38b75cbc97b316ba21db8a3f316aca5a26ed35c0d1424, + 0x16c9e7a58ddf141978209561d930058233b8adbb9e3aec9702ff674c22b009d0, + 0x1388b78b9ec0242e402906d75be419cf92e3dbc2a5152df9797318e004632793, + 0x2a459318d3f7156d87e3c666a8f7626cfed0d30fca28ef7927513b1f7a294b07, + 0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, + 0x1f3df3ca1c4b854792a69d107bb7e6e7be2f479be397de83c94cb310e8e821cb, + 0x2869447a669cafc20f1f9017028e3098b38a82fdf3cee59d9de2c888004b41e9, + 0x25eccbdcaf0a67d5ef15c7baaef8bd2a4eaa1a6d5d70385ed777c10db4796ff7, + 0x24c26970e999f27e6351f1be0a3211c0a177cdb778ead13baea9b7b4be3534a5, + 0x731afc922ad48a9f0ce9d635e26ba013a7d4ae8d52d4fb75f0f02409d83433b, + 0x217044abaa3c9ab6c51927ad1061d0c1cedc63a90b01b7b5f1c10974e66f879d, + 0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, + 0x26cfa9ff210943f6b07c08691c2eddb1bb1d2167a417912ece724706b5c20b0e, + 0xa5509b4fa5bc8be630a2ca7c40980904713b196e36a7e9f839c4474037e049c, + 0x1c4dc788b6131f9dd132c2edffc7a46ec50b000383faff5419392f0d291c3475, + 0x150bdab59767a62d994ce37edf2c3cd5311abd0bfe541fb30968e19ee2601053, + 0x25393627a593730f4cf25a068932d447c1581f251f9a7b7d86cf9e392aca0d31, + 0x10598af7a84cfdb4c458ca7625dd8b18509491e7109db65bd8a0f80d8778a6ae, + 0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, + 0x1fd5ba5922d7109795d5dba77bfb57ba6aef1bb6aef0baec38d0f916d35ec9d0, + 0x439026e268ca0fa85b1f6ded27c854552eed2629ddb59e6a679d4efaea6f218, + 0x1d5d47eb657ce510b9f9a17e9a49d6f0040f7f360399dab7f053faba3f06286e, + 0x5cf07dcd831c1c51062ea271b402941996f46dd9df0fbb227305a550f42697, + 0x24ef1615afe18b0ff998bf9e1fc69fedf38db66b2257f4bac76adc04ce92e029, + 0xce1da26cb97828162425a7236c23e8f4b7778bda9d7d514b1b8fc9328087c2c, + 0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, + 0x1355e415b0db4001ca01503bc20232a49e67f0e816dc90ff18a4280437e9e9b8, + 0x11fc9669cbe3bf176da65f312e409d635dbee3fbf8f3d1d6b056b48473cb451, + 0x1d6c1910236789557b4c42df0191d2a46cddd2838ec6a74b7c308f023e71d4c5, + 0x1626f4d2cc7f2d46d7c9c97030c1b420d6c2d55033f7becea7d377541b19f57f, + 0x210c4bb43d712b400d4bae4bf8dde436786fc88bfcb82570b3e235ddc2982115, + 0x213fd23b04ea9e58ea915c1fdb460f3a0ac4b0041afe80f6ca1ba9e1a0e13825, + 0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, + 0x2ea430efe8ee1f2c72ac009258a1ad98b87725c00f72d27a31c445046bb9a80e, + 0x2d694e23e1b3f6b632b646584e76fb7b0d35aeda598fa5069d73c75136bd0272, + 0x2ed754f34a22fe04fbb3635776e0894d21cdbf4cc6e03b8bf33787883c1a0db0, + 0xf23e64e2b59d750be3bd037f4df62f7fbf16899400e69554b893f4afeaa41ae, + 0x1cd301878d6d778480ef82b2a3cb9bcc36362d198e44c204e490cc524a2bb2b0, + 0x276d797b67c8b3d935a71d2f8342bf7cbbd68de537e32c466f95a01a5a207f04, + 0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, + 0x16e8ab5ced34e81dfe00c24c7fbd0f4188351be2b1b26b6d63a1e02b84aea6b, + 0x1caf3b10ac5814656ec2d5852b5439f810c8dc0a4fd6ebe82d9f33134f60c7a7, + 0x225f97bdaeb6a565372c547e9d6c354c1f78fa1998cc3d92c28212ec7edb634e, + 0x2d828acba9e58e0f3adf239a3689449515a1ba244c13b0186c827d600b7a7358, + 0x1f9da4066a62e0cf290cb839bf62c9a49cf79b0ea1affe03696062ab8cb9d39b, + 0x240706e2b81b5b65343b41e59330666d2b405258c4b9b177495776c2b1b6816c, + 0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, + 0x2d0f43029750f58be22d66c5b2963ac6b15b18c6e9d009b717044859fef9618d, + 0x14237392b60352f6c8aa0f5c08024beb882ab82dbd3e790cda3898886aa3e9bb, + 0xc8f3b03657beee6e1f94c98662b6339cfb7db5cb431fb9813587ee3f194d260, + 0x18700b515de19b3256513482566afcbf490e55633dc0ba574c2fb4efad1ef118, + 0x1c3b0a6645d002a9d1e18721a96d1e8b00217bdbea74ff1340dca47e6a326e26, + 0x2979c4d21f80db612fa98aa90bbd65e2cecc1ea431849612005a904c08bfd014, + 0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, + 0x24509dfe357470309be062b07c05dd3df57d7cca62caa26001991820ce3af97f, + 0x2bedda6eaf8901b78a0e53e25dacd92c60673046c86deb333ce4798bcf9357e2, + 0x1f1d984e06825a3da53ac4066d4910067f6e0ff13ef83152cce3977ccb273404, + 0x1f592946ac103f244d168802c352a7e2dc52bd2e53d3ef2f4a7571af810609e, + 0x1a975c6688744220ac1e3d5295126f8ee0db7ca6283a176585e8dd5bce060ff9, + 0x1a78319fb62d99297737e9dfdccd57fe6ffe0329195b8ff713a2d6d33596a6f6, + 0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, + 0x2fb4c2f41520052bd4498be87f445b3c62e86ca7d872dae8fa99c67b5977d11, + 0x3162b367e9f34180f2228d505e54dbb7f2f23a3a8fee14f3084aea490fbf3fa, + 0xda5cb94995f668763e7c6ecf96dc6bc13943abf3e49c55a702d37f36f79114e, + 0x2575cdf1a61befe9fb7b83e880e8cc23d82600f35598ea2f81ad1bec1bd701b9, + 0x1f83d6c20646a7e089a8fd0ad274021af2fb24e315f400dcb3d26a99ab5a35ae, + 0x2c774cf487f79664580219c9d698781249e47b432767b0cbaf5169a5079fdb42, + 0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, + 0x203c1b59256ff5c004e70c2c5125ed51cc53e99390a8de9018e647e1be8d9888, + 0x27abfb2e0894c5b4279b39b9319fa54ccbabd1efc509b31d906a1b5f764963c1, + 0x2fea2fd0f35fffa4f84894b6525b3fec299c821a4766a78c829c2e7e69efbf0b, + 0x2451d54dc48cb608f2e96698b96fd545816fef09dcaea75c9928179373a66fba, + 0x17c5d4cbf713d33eb7c1f915dd2b0e439bebc5510cb409594adb43f94b7a0e9a, + 0x279fbf4382e4b2bc46c1a8f719063ddb4226bb09c10cd68008b37c7f32d469c, + 0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, + 0xeb7c1194600e6ced3d8dc88c8689704d4188dfe89970dd790bb9cb600652321, + 0xa0e776c12cd108cc589b14e8493dc743d85046b1c4ca97715ec501fcb166ba3, + 0x1a8a8487cb8a60bce5774f64f62d0bcee791dc32d3a6f872f7dc626e4a732948, + 0x16f103fdba708db2bce8b58c467a05bb8878939c82852921e94e5e955aa09ca0, + 0x27a57324ff8193272833550d82f749d1389b493f98c8d3473f1a98900376325b, + 0x26e4040378441fe8a60d1a5319aab70076c82cc203530d82e758844070c04860, + 0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, + 0x71846aa99eae694fa17d73eae87534f09c4539fa5c3b79ea6bc56d888dfa9c1, + 0xcf75a0326b8ca3e2ad571834bc835c083555587a928fef417730656217faa2e, + 0x1b80702e894d74821bfef8a2dae36f71d4802940f63a14fe64b3081340c4f11b, + 0x2cc49fb1ce9198b927ab098ec9f454d205342ab49677037f9ff7f08e3f07ce71, + 0x1a6e74bef4b0a5b3566facbf770a14bad98d8b6feab3e45995a328135888e924, + 0x2ef1e0f0bbff91312b2c9b4710ca04f4e978061ba53657e9bc1893bdb2e7c7c9, + 0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, + 0xbb77a79511909681081da11a13c7abf3107373ba413ecba4d47ee5a0c288fac, + 0x23d8b2e6869d7d05101d387c1b8cde6b85b7fe860e7eed2944c50d099053bfa5, + 0x3023a8bf03a803eda3830c500d1c0e061fa85c4c15b72459475e3de290616ae9, + 0x2b27c41a943be0d396ed3630098ff7018767161fc1a24d25f47969f1a44e20eb, + 0x2a73bceed9ee2a7261290c8590e2ff679582a3a6c5988254ddf6f108f1103e13, + 0x2579c47b76db59c6206ef023b59884fae08ef6a697acf7e55b6f132fd7733bc2, + 0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, + 0x2a5993c9c2a80be0f4b0a6f9c432e2c0604cf59d5bf5bf24609572d7d0acb900, + 0x10faea103aa36e7d5c7bf760b355e0fd381a393feca3c04450d7faf0f6a22804, + 0x2e98e92bc9904ca92c3e6d68fdd79e8bef6123ad5174f01d5dc04a240d8f47f1, + 0x119937bb5d5d9029f290239eb94fe86069f2db6bcedcda8a1028e0b7a434428, + 0x7c67a48f20850fc8ec8c735b73e07af2a08f52e7bc90084e9609e97f070cf2, + 0x2da7855de0bdab6e993fdc9ece5fadf00c5d39d58f6599a56438aa2663cc35ee, + 0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, + 0x1a69a3840762376c3a2aec1bd8a434f2a5e410a7e92d23dbbb20a0991aadc46b, + 0x57e27ad9218a311c3627a25345c879508fb856d68b9c0aca90276b1dfa4bf15, + 0x14307851c6b079c4f3b26689dc5f62b8ac2b69ccf33f3802e9ada26718881832, + 0x26c71cfb532662f6e681dd310fe112703b78f8ce1e3c39183d5d4889ce304271, + 0x294cb0c139a1a5a345bc094d8a53f21d90e82cf47bb87e3d5e5bbd761e6d82aa, + 0x84133bb35d1cee7f10a2f61953a4c77e09c4661a5565646654ddb7fec0be900, + 0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, + 0x1807d1d910cf5420087bc575b795cf7b77b590b7d14d3e3d2298b302c875bc1a, + 0x1df001fd3c1262358bfa1198116229dc12e112bcd91b4f3962c8136c02c57e9a, + 0x2b424b88ddb0ae2ff74d14a89099f8942df4e737c63f61f695ecea4842f9ff07, + 0x189b086bfbbb9da30885f11ff9cb213c0a353710153cadd96203c7f97203791a, + 0x1bd472ab81eb7d6c92809c07a387b1dad43a3083fe658bc88d1c3ac1672e2ec9, + 0x2bcb32de32d02f4b8f8b1d100459f537cb0e4e1f14cfe5724424107a9929bf8f, + 0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, + 0xcfc7baed4497a2252d54cdeaf8ce6f23773209abb5f341ca2ab616f0516195e, + 0x1cbfb6629ded2640c886dd504a2ec58f96b441839b79e54feab04260eb90b128, + 0xb3e19811df2edf55549ac304fb205cdae326abff1e7febd20f350af8752f2b, + 0x17e85c4c6fe808534124bb66995e5c663eb5a195ac1a26d8a096db675ca0dfcf, + 0x31cdebefacdf2b2dc708ff87cee0315f36e97308369e304e8d2654c342622dd, + 0x17c33efac12fd569e1ff7c0a0165c4cb8d23c279d442e7bbd073cadbe4f665b2, + 0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, + 0x866a0d2140ed3854d5822fba68985764126345cdafbf547ebd33c39aecb895c, + 0x2bbd1e9f3114413c347ee4037d08f914d4cb655617c0cfaab77bb09ced39950, + 0x1ad0d5f7480a78dd4e048c459479d5622ed65f87880f675cbd2c4d97e7bc7847, + 0x1b88066e99b993f70306cde87ea47cab3efa6d698c9d3b1ba355b2c9f3453b74, + 0x25fa0cd0dea157ff4ed741b0dc76e0095a51fc30c799500e80d0b821aad7b9f1, + 0x208e0d0378f2c7d87a6ce8abcbd4bdd979a4d9dc80268cb96d84ad440fd0f99a, + 0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, + 0xbcb27a9e590ba76102f8bfa6f1c64726558f57a0027e6ddbc46d564eb8b09da, + 0xce91923c51960849a75b3f8fd1bfe1d9754dc7cd48144f964a0c91a4e08dd61, + 0x1fac92c295c763fe6b1e3c0f3604f0c7d618def2133ee2f869d2a1e774b4245d, + 0x87968a25cdbb96cd471e88fc2cccbf3e5b8bd1037b4ee5332adac070a82a109, + 0xcc8d9f53ff98eedd6fdd5c5def364a45d12ace1ff5e3626f760773b5de0e624, + 0x2b95310fe6307070e985d61390a351ca5e1c4a9f5e2c539602136fcd080f4e6a, + 0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, + 0x28c0a6ccd9587d41eb73206239493c9150e52258eefa598382cf609d4559b2e8, + 0x165c6c313faa07be77275b235bcccbf30af0740ca973d6acce2cafa9462491d9, + 0xcdeb047d8e50b00253e926dff5f95b4279be0377669908d6759612cb73259e6, + 0x10140d5f85f2f329572c2c9b7535776b7695d62d6362ef27285485abbf9db018, + 0x9501340c196da04db07c8b1c3bc1461c228e926c9ee26f5e26364dd894b1468, + 0xf607855b7f42530fc19f6431d53035a74eb03f7251d71567982458698c93ac0, + 0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, + 0x255be79d8de4168c44cf8a26522391ec6b67e30f2474bf2cc7c792dd25a47046, + 0x1ecb792391cc746710b586800234267adcd4d9841c4e8f1e76dfc5dd15eaec90, + 0x292470307f3a20d0205a19091cb044a8f9e58d0156f0364b21f3b6025b65d016, + 0xc3d7b0383d1377489843e884a06ba72245f0498e71043af2acda8353a47ecee, + 0xc610cb1971aaa4ae5f87fb14ed536198648cdc876c7c6e2f531d7d5d1ad625c, + 0x1c237dcaf124be157c5897960fe7f22af44d441d2d4590028a07bb249711d7e2, + 0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, + 0x2a5e583e4003e7e747a1d39ad6027a9f347c7de946a3cfd00750a9a102c05e3b, + 0x16ccec4b4960d2331a960804ecdb0442ecb1bcddb9bab42b306c4736510675e9, + 0x2d0db3092b03a54bdb861c291c1a1f522112f9e457e3a51d731851dd59b1365f, + 0x16f1469935ef074ab1ae192294dd62af3e14ae22f1e294032222c5ae19e2adbd, + 0x67c4106d011aaf52f2539ba2f8d1fe65ce9ae081858ad629b9ebe8148cc0878, + 0x12c6eaadcc69ac3b7344b8296ea4a251facc1c96356c84e8131b662f3d5f34a3, + 0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, + 0x2ad9831069e1f113495cdaaaf18733aa4a4eae1e850d58c06665a1c787ed6049, + 0x1a6d2b5f928d9f0a9c4022b9520d707e5eca0ac9cee84927a71737a036628f6c, + 0x1d92d368ae1f42256bfe712909a03c69a46bcd207c17461986a6de00e0952945, + 0x10ad1d35f6f8f499e64daef032a28251b50c622a28429d2b2107ab377784faaf, + 0x150225afc95fcb450fa9b2b7723479ecf7c3143eda0eaa257df4f1a798cf6375, + 0x13c542f46f245c790955fd30c8cfe7125534ebcf6df7b1d9bedbe7205eddb980, + 0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, + 0x2fea3116266bd3005b05649b48c70089e572a077ed0f8f9730b63cbb9134a368, + 0x1bc4f0df44852b392b2a36846030f42fcd462c40b04d0c90e71129e621842af6, + 0x83b244ee2ab819a95d0c4bcdb9d915dabb6832b4dff9bde7ce0515827d19cfb, + 0x1fe91590b6942e9c496a9c696c067b3086fd707b01290a7711d4f398908c8917, + 0x2e97a6382c9007fb2b6ac74186070eda269b10506e8e4a74ba82274d154268c0, + 0x19d731e981d3dd374362f4b4f05c5ee9600b5396567615c3ee94e0a80c8cc4ac, + 0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, + 0x1299ec83503dcd0c6aaece92e6c2cf7871b61e43318dc82a183a5039044fd000, + 0x27059db058fd253b71b341d077246299734497dc31f2159918c64a78188b85e1, + 0xf8c2dee7cdc8dc90eb57f025076157a181973f6347318feeb0c99afeae085d0, + 0x1053d862218c7ad87cda3105ac23bcb12c92e883006c3d44fa3f9166e827cfd6, + 0x1442ee0343b9bc2ae95f8c4f59cb32bb461a4c7b40a12e89b68b6990a4b71933, + 0x2ef147fa908e6186fc2ed54fadf20555ef2a1e9b3babcb6863879adf84a3472b, + 0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, + 0x297d7f9fc303a0f583f992f7347f68b50b5bbd791acb93e2d8bc8efdc4c1ab53, + 0x2b4e8b40ce6c64abc1c906a956e5aaf5ebbdb7c98110e171adac573b81b16195, + 0x316fe041d68e38cbaa5d728d225ed818f00b2aa9ffb1ad3d9ec24bcdfccdcbc, + 0x168c57b725731fe3159d73e0d94c0ebf35171e3cf88e1267c2b556a5456ae6c1, + 0x90666d655622b3757b5ae5283432b4aeaece83148a36eb57821d241b3efbd3e, + 0x2c91164e87fcb1bd07143870286eca8a29df3678768bae50817569f48bd7bdf, + 0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, + 0x110f901d246c2e951c579bbe91467a2950e69ecf241d8b68c4a4c98f05284b26, + 0x484e7feefee9a459b2861009d6007e8b15721afb4a35f3e5c9a6f1f70334091, + 0x11300deae6b73e9e5129595f0996c10ce002506c2c207bf672676a130aba8364, + 0xec4bcec59f43f5b5653a3cb0440d71118ce31bb60c75b9c6766b6a5e0524968, + 0xefa65a66b38b03467fe38d8669207d9fbb9f38faaf70d13a67c6bf71e1e71e6, + 0x27806883684a018d11ee2ecabb971dd9f690cc5a22ffe36ce61f17c6ea5fb4a8, + 0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, + 0xf4b7f229e28a7a9e7bf019b18ce7a36280fff22f7a99e60bd84d1baa891cd12, + 0x20b53ef54ebd25d7c222d418e017b7cc5e00a9ae5221191a1ff561b1ee3177b8, + 0x14efc55a08da5f53635520e21890e2e5eaf0cc1fa1fddcacf1302dc65ee059c2, + 0x1b701800b22e5765059fc4525bb4aacfac8dedf2ed37253160baa818678ef374, + 0x118648d759ffd92fb5bcb86acfdfc4bceddadd6fb1679c317cbbcf686651c67f, + 0x2601544a6e67f78415a0c2a6e8f4665f5910909c58bb2eb03f7854519af15f0, + 0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, + 0x1bfdb6da2db944b4b79fc0ef825d6ca2acd350cbb87ff12187db30a1798d0dcf, + 0x969ce62c18f96eb6c6e3d0c5a7bc7b2b1de0cb7ae0474b47d16445f2d067cbb, + 0x13d54abe37dccf2eede120eeaabc5105b997f3647874179cfebc1c9b022b8215, + 0x27b42d0a347af048017cd6e2a577e959c0b6b6b8c2ae405cd9b05b793a2643b3, + 0x2737758ec335fcb4498d54d210c11bce1d2cf1b97b7ebb835c4bd17b1cf8d54f, + 0x1f9696df0bb5e293dc20d0579dba1866adef8f6e6d3846f42380861f5b54ca46, + 0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, + 0x2fa9dd289eab48f0424a48c9a2b4f51d2de3ae6cf2d5e23a10b0366938541d65, + 0xfc755141d556a5eebf1efccbcbbf72ead5eecb5ad93e9814b715c4d388d7709, + 0x26127072286989c57c665090b20dc85c5fa983ae80c412fb2d8ad02194843981, + 0x229663addd9b99e225513a7d0ed1b43c0b02de97a57466355e670add9ad636b3, + 0x3011613dbd895a56a9dc81ca4f61a03f4e77c18834c6c20a51be01d4ef9062d2, + 0x5598cd7707b28488e2a0d669ac14e8464804e51537d7d3baa45a7c80e489c5b, + 0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, + 0x16dc1f58a2e54f8f78d4a2bc67c5dd242744ff2db0ea9533a9fb3de2afa831e5, + 0x2a274cc1ef7dd9e160541523dd6b2c159fcb0f40191b63a8d0a877777b8dd060, + 0x1e8f3078f2fd0b0409460ab369a100d5a82cd93b3dd947644aa6bb8fc2f4f863, + 0x2ee81ae8b9bc0eb7d4417e09a83dd467ca8dcb6e8f0c8758b9cba555123dac67, + 0x367cb4b603a227e6b02ba57173fe7391e93db6078be2d56ef2e9164b6fd2721, + 0x184637a267f328df1bd119191fe0d1158eab799713ea537f01bebfa4fbb640f3, + 0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, + 0x27649a3a1db5ba83511b2f9fb3785dbdf083f1f5d4bed38b76fd379545d9ca08, + 0x8f84f219781937a7bd7ed5aecdffbcad92a1d31262fe51761c94a0f19973283, + 0x14f65d95f7359b8f9f3527527ba9722197df3e698f773cf3027c00bc4160f989, + 0x2a75a171563b807db525be259699ab28fe9bc7fb1f70943ff049bc970e841a0c, + 0x2070679e798782ef592a52ca9cef820d497ad2eecbaa7e42f366b3e521c4ed42, + 0x2f545e578202c9732488540e41f783b68ff0613fd79375f8ba8b3d30958e7677 + ] ) } + // noir-fmt:ignore -pub fn x5_5_config() -> PoseidonConfig<340, 25> { +pub fn x5_5_config() -> PoseidonConfig<5, 100, 540> { config( 5, 8, 60, alpha(), - [6652655389322448471317061533546982911992554640679550674058582942754771150993,2411464732857349694082092299330329691469354396507353145272547491824343787723,21491443688002139478732659842894153142870918973450440713149176834049574486740,20196926676989483530222124573030747187074792043523478381149800153065505592963,12986278951352369831003505493892366673723882190521699331613883287145355738793,21126146258242782643168619000295062005037298340836817770565977031890883232034,15509665795506578582538177431401381655815033647735781734613703976071034655246,6989769181472743404364681671283889685042701491627165526899522083327752110839,7062179885254277466334896166987547257487047183881628199983668518000910197987,13842521112365108087725039904948872289730786568469683976372377853164252494752,3830559505943186272618534143266118508463381443414165428900505002474439179836,17704863473432653834041116667846189591617394753001613253930974854399793083900,875580502229441633079974792778818749112423694973231971690365132230865385439,1971134273535892826573832061354985059300866001765691176219451252512658771248,4865738840363990164915013008693722144676933915103280504727326977328013515878,1148603338028060679975883868174895825055359423662532941509525326937127571764,17506086433923270253695698017062834613463718526046463655503742220257039588796,21580033018107258179208198773211859664893072138803756118939260252922297665067,15411900706973212043830142913959920716501447427702082030760032355626616412240,12219699506725448409610279620972339448030565224304464695714944121760832152291,4525719544192047521328360848269156485222470829314314216955024799558286708479,19667371373588322336224317159113441765198420040800065314868656839300028747331,18916925604689704279265158984702141998345424765142129953154245912230835240445,12789343981741773931665143789673052782408749041041266509485929045869073416222,3094428508959717445577232225505810354980663487713729230015754183012845687401,18544590634480965569098056786078005630500574069468005220462377474861119476492,20990087440247450018723844204951613913840993427110495085701200965767234569705,17552251989761134508416634118845221324472178264364440017634233349418103869223,21000797802575507763447855752602183842956182733750968489641741136166640639409,19292751508591545849778577901067988044973302547209758604667395356943370737868,18314088316445539319869442180584299715533304874169767778761887632882728399870,15003745150856597539000559910957155642193629735521291045949652201905498569732,7839443900003691950104175747634267110464104444913379977500178134209666299140,13568305490393393394812598233983935295266242465548739772708079888867621061127,6453005227995051361096639028742707098785560656441339640433794156400437698140,1420171596348195609536167209221442141824294918625468780931400849866478645240,8347329128252205996443084339884155586061343024498283583400215109265013719709,7893774494551056447960817286805128884970061671041428326788899872964096959040,8970476243368194065341537088653900235777512204874037182428362347342487241690,239049405935404678508864874854718951364753739466303321590415544572014148257,15772878921699764223771017074289335629553777447709755479885293350677783703695,5416082112919155131434995906647355834510201879607888732259087164602171650389,4384524908062410354304345761652962203632712291085564157560146286207296352050,4210984612917608245844011498198864216639269565627982123611519493203177283139,18816442907032290878644773027005263628136050677095986565400687355912498966559,21443510232279945782338486087712914668515437675585863788610958361560172084515,3234314779308300525339049581669531363375743827111579883853941968586490182859,11029499234949696730080035941750777601416171837281021031653841244636590396063,11145210633226924132308292113124660576759662647204939721872338908644906571564,4583160563963432761409369246361117506465307518522062239686649163525543782173,9813992026757562966842771727657080117609486122615087352428596024939855084450,10084171857039480706430282187972782725948479260179367780776125786119489581409,3874212709197875589640151274548083098712939093643165182881681226579903752816,21595542491397091124739711708612983479307589335640792812157875295064235960610,2068530815441314105493629066002923150651375034543842424822712297257260726954,2673459852071215292298131389250564595426361004231758522146794940265552265806,8591046256746588406353455230465605224309754008961178558834659065898923355164,1020055192431352394776887540248098706183934464205704158014904833376067287118,11085709480582865378042656141271006552092494690130782253913953070642865919312,5673844083530503489429922596812992664928167369104420134641855283771127716005,10492199162275168254265892158402955076490959375050993042712629236807564461542,2280843393156259739329331366624245275580688891778782679394848304764573859886,6807797027131305026345508953353882265754363485246407959111359919046340709440,12692191384043938397944633973317584101723715998700063415107128429315536223446,19818676957110967644349139912613239435706480354664804036688552936554140369382,18055602608192644695569077694296748842203151828348990995792087204755925787339,20934555391215769430553078793246717148484784880715746179415906355043590089450,11420705181439111353998210442417752592951340005396931802449360401461783159557,19878854521263746227125001670931867821366047088989510542865511663910116386085,8568201846715449867087132677683368912214864824182424933182820310911278496552,19198701614488576617610339232794062430644024620523684127268879880793305460015,15262122764244854433806270478871594904740306012582364033343126589996733802868,6412758421155818207287638337822550233376667015263373809976157264137577776202,17371585001641430978766734501830788427263945848682170096055857509304472649262,20262970042379497707724791203314262108784948621691331141565359315001027736581,3859750447119748295302212198327542106766447958113540005985799287718502362717,1172269945800307665458943534144481495673510885455899148864236015097947176746,8164247467959680477306326470118519335673181279975551434197731340070491876250,4513977811114181395323888111232002391599397736872779927267726121435887238972,1075250595927474080680862736233039825365918646878264905022213616210377518447,18658420120424372681792175914064174056413842231969276203770574969914576681364,17769673440848360838244654765103041739044212539359630263894092078288342647801,4319086204044362848967484441065231939136453667264715596505827197873119273506,11221173270629292820060668122527062274557317856738971635698169204652845111606,8635411372759272135249379415383299350267629947167809163276219879514948820576,926977621651476360285369760355547766944001783780761167546467658394097283069,17702143780592866375901805387463459229828093905183622296234691441436877570082,629612289140842594504574984021125242351317893847688437087866691775821981724,19990548577495092294245865870717186004301934545721835081514347926537975465539,7124830628609719908679298707909792306162298058570958688501370177898647946696,14620227791860703231425817538142948793892390269806790476396226159679984968174,18495581997440241868332244230687799183899751339442721677540757155760745277888,16922065056093401385376103551657968760602009001905886435813054626317776258714,9969610601962874779035054685661667941954971427956866645694064022029705170229,15281641269114187762159685323068136816556739502211864119670902056596295644116,12114994625438879103001132949163961965524612903017200394727056658298824651596,4840986177718281128440833017205097196672382395936939379498412745183060615212,12847307562796769659308999092658905656250954898192781948610713494470441775991,20290096217351155282642224215178246911041509999959311313223857240001143893317,16151664509646153154405691138084115125600386733136285504828908979176781265710,13848845391482751436287906247470303487958950799995701248612703022979890932133,6335716166231441585596963683321661194889815181545222079376536449814718259931,1824302750039354704619545544386637317858342555634601563660279997221547953768,11327469654081586239268713126961534952233559223228327222485848924908493444712,10077703415170135154603829433031861799853903739210136452726077323833067256620,16368073884579385814331927334821006319227867093692644942500207970751483237405,10621580796499573269115131164341885791299038227955222944695715163010783205295,2099241376651019397894434242565225315652133572870234550073686122343103853816,17104632243449417396641550271977294699471083572885397875525767745512335891599,1935453754847256492223646005402770357836971113012418013930273797463411526183,7492761611332930896292052363224494314920390056637668407353957465667515477934,16836705924460095689555600825174696605443212968244843485187771119291716736958,16995495500678141665340056658079449793587669420913589967848082091551329904176,16097379973857697753436437302681608056543122759719328497348770844548177814262,17476569537128329379528694049566216604638194592812108658767104922628767500420,17997217989870184804787026924935938133194070033518938653831611194683423549591,17573343771046232580761295935281170028624495346579002725814597714902588657750,2450087639204541254902859018960918562514681200270997307467560465282168310665,17288084325555056222618040923753050382954155896826087372317882602328092535440,21837047676579063581498107773514419735425738753079336764356909012851439336687,370061273472837873736743292149368449614309676635341873070086681342317566380,420725183996224279379885018872359102189091670793820517618337092091910692771,4966571645678139143731798992823327185758562224229132271884647901363447388530,5039558223429273757296118284876763395391635773837549121798873235133698166026,14663152729953724779401067486012084029581847325524052152795817923033297673686,7201040456590575809960214033959496417566605177095808543357813677845263237276,16872945504528960415453618286121813996587432836152082188694652370255998768595,4914824783780909279212078186433590922437371437384817332713271291839616026466,17503018483514413315464207189113334433424965178631599286655188843769810245465,4087750571011463387872022799241315348852213278729592692674275176152296405923,4006961923780091252337105595934918049936238157468198971234322013673884171131,4481908842184366902145805444001507554481032302978790080019710161108326487967,13532316826436461968093937893872910736305115143550039673102602344678825540956,11602986656925867325907196773754426955346837006705269228226729102186031417465,15306992574062791537454541745213815567999895856471097922112648012979731636068,4497571735611504561173050536899411999551839050319538712220770383407135602945,2571242673174714867278075260451133687893879636121064640779554188161591611843,7070272070524747733177730083966686149849667613589868731851816020060781720851,1308310289745495626002351437755820460104812708071634598163946330870933261232,9483468192990391193401121929514821570714432121414330663623018046165053411090,7317568349845215930675847155716598288688799068821709820024570206796617676748,1918505733423704616434273602054555051755671749253598966287072464475922854850,15158168161084905689406532256983805923258003804476527617207287404280855731962,6855540174355511438343304861678411868002455139032857270673849263857877330771,5989863238360846166935911112885654223487221280254816980802479355446167746774,20283337058688740322296928691341300752003492063748410749625272920572074851396,18957132189629332408653055312790838576277703952267542471751593810468444454136,15764518568966520670995753676429154315765754748131847346608706222194564055358,7192524197002826721654253762628934164676539329903087107420445743247046038858,142950766663597487919643890566358241353679421113406309294925836697585309311,15012262168187689680572958978610204856600235635916074406168861726626292993057,20795666834671497603181209610179324236645779324677512349797033323222380300794,12650341271833683789775531792948185319868795529390391267833516836256688318306,5597700232877580665749288204589530549415282468176625525368428476461504532052,20949303924691159143653175365242293984396858344688574262804199947001630916385,10746523145835332938672833282581864816136388045771578294905302886974358762209,4998982766221590779170630035756820066555357949247521575936385387288356143784,6936999580131731861735955554005106460473097800566952971315565150681540640020,6670695360676548472482680016233507548657051302712214051977034166870814430578,12210816592786563975173850937247594401582085430897698766795696447223454826466,14933901149105284237676334791785996160108290333321693498322435129559137152007,3848529433916624869590379003597911090976938589461403388133685310398004369431,12778805225074604003024964969486878839359935515509480774809299341511161183802,3288267180428684202786697419666969564766921974531343432588030535602163038467,1272672432174256751826350693883913844502039730140570583479554071765667798207,21130828804874452930669244946376257892693846272313548250936991077452679117587,21254559353072473881932828401787134230282801383134765683324465204971002861493,4116075860631781527931204624078712926526805345818156200756399332393348685924,17435888597009729827411190999389277840088354756277916760187756022854497211746,15837398163415665169712832984380121382150588321621493928953938599666110830812,17988638446757562417082379159769772097890681265659458369075768452342579854303,8144561030363576879343874888624208577604401139613622673042754207987577727758,20020299925602421262203305284307419339160247406220693128040712457114283033661,2945951415037890626891130390523013930737768652394758977777336357159436605764,1505954324723537402640844232704189835623922400329086438898375859826553573763,11851584491756305117491374581845512067704002072833714119284164514457248861803,14471204965036278214508938537949717553799007630471016532866101610339050785912,7163557293233604902868673807221391042191134560333950452577270522828534690707,17291625782465108601367695465389799786592304061550212130987221355832952230827,10240907112109243116543462081552827576656826251172050843989873656917271396422,20702261919346727858635106264046787321170414155594199951578791234276181642650,16678253307828004252292273162411388452019952018258857370242272543091326285541,19810917631941180098047817620026253706643400683524412974923209268916769874447,3357220165225360610202375608872621445880880830154732998557832689480921421791,4392285438534542495332422274902727975330102148971785438164412161504066619105,14642025133729666610167675086855441462580619607677226879159952689184960379911,18142623439987890999821892559271093087005885278955082040377769578204898750505,11769399023330099592616157336702104329646487200891911089287290893650532639221,7261353756299584174448625214367175510387913706095214313669922259027644778060,10406994568199070863112470594593301582798997458844791396920771226539013327304,7475277967562870216712397220016587384793504784585573136176313471517144184018,9598064630327104406929367986473441777975480987434868213697837347643980267620,21137410002545951849752865514437404724653771608225272412595423069852350320648,12345612867231779996383303763804719815752861524077922121654106906093103051400,16461750199070055335468534730937701659470268635084522644824623393184528879703,7829250842543018165409887731515254191943527926556191989558018633300783421935,19801151644322693878208767560968285812646931156576102755771403150148125880648,808770634664491371274943928223981161442027957963181999892266696287962813461,2298122748772261447929855283951027113218922003687701626762072351622993276571,17407798064458858450209051887305178872029674498718760624162479511390762310526,18585562277464562541666582720366573863334618817908062612923861658144918595030,733976598693219656339731904831283238690050114241501938501377743874139460889,11316063986696838098122262534148335669847478050407756877728672233736962269417,17614529714381496379478130066245111825610297227468263851608027100133421612826,12110694197729365219340374599835523099651939156213930558791147158357810646901,4337343008663255658976574468931581484970687989356019720784093082313510905405,1379188959674402095268172673987199124815512095460112504778179157481327937561,3116148242507754420428768481157196067508084836097458698846114802493377512591,13306507137873332434793374848948087993544118494881134631519748904811343155566,18496878480807017010077624766326681523549495609998881196570603040242554712562,3940126764022508707486095199473913866137718790062498893812401335738707507732,10030078765792498033316282784150304209584388923549357286679864120250994473810,18519871685760382462428068450331593474924737719734568498029727699878543899254,12599428893576891013523136950822667754415283296587096197120138265392279834128,16038578953099895530943034305356008247313649524436132877362941968861459073483,14319233878082524834510736727226054073026413911339853399113450188859080424272,13710161613540579690732775978855380876556751245265568031703536595040993113748,14958726446649273856607176275240008023824615720456760403465034344703779274727,20935428111942360630758629263346308597806819928838924586682307174931367773605,5826394436548487315966647466017047216786257295199620110266250301500717796281,31401797997389676486806123612280306684597605608110075525648021056710776011,10784171495708237485952707518956314344821522727746927291389338644844400581452,11604345371765580191117799693565193618158448665352599382713281103552305960442,1378145039624937931836538950217364481423707761527018494355648047365613434790,10284294167221806561993937798090888689421933711157676807977401896199778472860,8233695574758520342808807499924062869636681352769371531557726871630696672029,6570581391072134029876349038190171593169496519436674767949949730275868319732,4026501263908027819614805027945064360196399012004574117767831931274788631138,21091098569404004244061462065218203986433580687172854429523306262593782053656,20711772916118045406356429185975897495222240215931761100801599257137350834799,3165519312799351250309462589160165591299333587158531489859211268084164422251,16470663723473939739601217501478624726068461799539012562455639586886033078064,15672299304945968727435591100602007503785845873606917887638890765525875123857,21393538327627889838198844493522533627143658125568123117776524944297103649079,7688819203734248199049004650451546300187194458173935784579101984183800649342,6609663518412297884695057080546416278366560290439222127471462938252865438638,3476303650597281786976907813110835564442121684386467570637538230409080744769,20633582549754495054832414039299188930065286005370053173386561254823483851717,18067076834611402459142612082327591538480657933568191619109271502102126814407,157209609820117793892254328219308970217366919934739036156851508233236414461,1848396116513925340973398423998379465460554039715233953825786874352442451413,188642786730195655565401615804782553245486295156304142809552609651873793325,540089254487190924787439362270708251103955915909358626209177199653451469720,12796274768956950589847157187031845061404119522843128177103898080653493269942,1785666356337148874573621868025910291826158842346617719666738769156993598966,20649919247042517528354490854561347316237285929352042389729444382153378749538,9568390566108569727471722677925269460696523515877621230569682954652430518787,8590683334740232786825518158771304803451657249486419816607179533515442407283,9321198393538172042803957409292145345834077448228642847843261373640165958582,3651905214805616378360839954289447530035139753215923648216350128870943481828,1324345422558073117779462079218851558068746895262914344818945294328678893083,6666363895154434021620869731925915051086919707989020578203743660669796175288,9850757893972463103359995012900314323213006625927501272997539940766979170137,10214293226445704940138790188111862069675188797488928722469679760666574484266,16862124085118494177559484642483513597285992646267864845521573612482278871023,9172340118369291059693735314505606817316211450324955429310200429408035954801,1968992755714619414656181112336357119271845800144345284299978250769356388249,17192498940296212027365280042755701662136570107224000496521552617655679821443,10063385968535643122430064779260670089120686456635080613693015398478175344193,20101961459945738562625328882763768836449780661345042148985756598106706734632,12704305975772252539534386080950631076046431529894091327218544197389260775334,3008242816727585639441748210631464697850194693570485141354082562181236010097,7797705698071555811456747812384107102104184812467361013142453143842134807658,19323240331433203844038522035479659453946066968727795017745942269828428751105,1698137797127320576751729191866734754105401103859852376273763815257758421427,17656850887825900397821271738817912328294075224643535784810269137125067875996,20755447986835730799031196367323817361150623932048563112034040627213597261325,6221130271964372280138992636208062417325313096379273438539556580491430711297,11042709376363248213366896208587241517252100440844476816212498352999929578287,987361321094619571176752720390429919723900732295551211263814448408232028205,15077982986114392945859048373768437818569856001604485167476360943078774679228,6278894644165961404521866714059972066255652200107181684047812674333675794053,2649747800006903047073625320829560088088800522557851927539477888486006072675,2636278052351769676017824297717609512488651850924228608531372135635042762078,816232991472315395984098922575496846552245086608787214581606973359616326446,14372687274434205592004117128588852491871014819273428668840779210928924573820,7351401720390274950322621121981079413650308506660552567079785209176949174210,10275293929161727274572318228903710245677747557851999483919909420098936352013,14869686444606195206734119702227763209172799407142930791211203702643805341518,937617196362766626935279232045712623531859540210120280128165029613358941709,21331527351771920568751070369057714014285398281585036009305608379072813379081,4305436470381074948146072259605215282335211631970525440530773004228212378618,5894273721571292784412707230481346442881109207745969297947253583203466014760,6512250441044591603946512492071171861967500633638753443182294740883123881284,20863871952569294813936866452848141274047362082838805921071316386912981651979,18788566662709810970880679984141390717017951403407913908833463086244783373013,7784927597396249543149135503684024377171301321636804832597181795981969626201,13818519831569592521516488188127966399245767953522268350556654747680372036664,10515208647860053151690062640705322684876580250632027862984821874343071549235,797604926079325807488629085866693514275115789253871397971708541758696512985,8741784289526985522570446847275649913333939699807282742190607491216732972386,20966712704043418981047968701828936463778140093909973286855779694780086635828,11359697297415630167449040380538108774924967116147664240213257348125754475868,8070907838094569287067982462230761680706116783989613960066342967469297961118,1868550288036217638713133945402464194193242298015503906068429633793800456561,198709459347510170000840600179608479136663571567208109852828485236018304733,1601154135701845545733926027872374554514541574822026314034696802419388627041,4363994778006302991481199477873248350039564117453810275561422974475581105893,773054378219982710451611471050404495804413666789496412742983455527754059148,5209426340109575519362014651321132459061755868557415513439993327176584352934,16124961412020675839394907565568143713078242978522632778625312854364651991011,20812496670075231301471694692369245988519082317145989298573032859079075730004,3312489967581906638742585802390894285073229440039144559060030129184388053832,2967475373447822846542676378804990140732835322255774209561143670843223463335,19744585401442299381952694102570931935735276268739851233412754166721728873141,20026293345566344685499234599699178313754630774489046573312844763673073616936,2611303659034102517884318354550433047021831422518437228002960700934925644951,6230291832603218406134986471162106408091661326026848531605999413028246206577,9126162046556730019959291776456914453189657463686708035601186672661595109020,18827736146609035067773173111376739253733288103277133456626928961785293662143,2328703958261360872869074208611873245571971231035163763965210852182760438390,13796410059666172174899788866809560044715551934510722965495280798363043241416,1593663256684781552813616365605526150610454082601584196604084376715746899324,1565874145189898288764434737762721576951043839540107044892767693968417810945,8709849304563896945461696717753976956465219721409993781555147204068634555572,2994256803561260177499267243802460581941891553208150783951937342406846377191,10452746656507347152042187616753027475507881362159944564077673851918869542550,20130580998875572619695450234900655050996104101008767761546912649074040426200,18926933358104691474037431437316089682088433006245222723356764715400831411716,3783551594057498940671877156409957274854990650480535806320220142873170375307,7919031943604095374667473717154511882451510130166237539514111182596247372692,14518552587329209714850286012780632801030157943402419401997576700600952906519,4770764028263701271241862755569969531641408032906982530346384375773459918490,10866502826034731763529371496585294375373238783964914673031891984092997621879,4234148117462322266937279401468367908013627589417699250592523530383852950379,10747942066055887965185603234524367638106812660210378090215017248140719240336,2587411532912868255102795810490361867789634574022411742057853375399270197531,17350061113113681344498080520518808976916692173267298878258722510332360424059,16490282364669098969805528215926442920328903121380947471680517193373377657129,9274691782659584680377375192682066090127280485689527337429804211265749864190,7630965482352419767782717986075793694403609453648729580916814032587325374653,9483872310024003776681196467845329825094379763716541754956796450187787638623,12182966986735661215639970080491757244218854808156498220088212871061979325833,1853790963611367149183440339188924598268644281518961106776656221408171642714,17425077915972423995335545370701802959607559878032910147159424242864219303096,14571075346526399549826264845894977639678567831720652860528738036970272895919,5627701855249158721927849603102149698163511782011562166637339712383551336091,3620805686755372260289125555061886982808014642356719556961142525373021656729,11556995641752009899073583627136467840237831247117281278719511600076965602980,18960242154096055221658318882298412299294886669455506299567210308762501113202], - [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] + [ + 0xeb544fee2815dda7f53e29ccac98ed7d889bb4ebd47c3864f3c2bd81a6da891, + 0x554d736315b8662f02fdba7dd737fbca197aeb12ea64713ba733f28475128cb, + 0x2f83b9df259b2b68bcd748056307c37754907df0c0fb0035f5087c58d5e8c2d4, + 0x2ca70e2e8d7f39a12447ac83052451b461f15f8b41a75ef31915208f5aba9683, + 0x1cb5f9319be6a45e91b04d7222271c94994196f12ed22c5d4ec719cb83ecfea9, + 0xa9c0b1916a8e41d360d02e6e2e5d1b98c34dfcec769429c851867e46e126fa3, + 0x1dd6ba3731e49d21e8d36e9d4d1edad245ebf9bdd9ebb60a252e4804a6390f6a, + 0x24ae2a67c3d521c11a11b7112abbdee30647107b808866a980837d0d7da4e3e0, + 0xd20c9310b5c14d9ef12866af5a45eae3ca9be16d200497066c8b2ee96781d70, + 0xe047c9821fe94d55d400d763a66c4c6169993abed543c7284b4a35430019445, + 0x29474ab799b1e13948eff41d2ce79bfad335d09110157076988ac207e10c81dd, + 0x3899f139d0dc4b281be3b74ab4c70789b7f41e7aca47ea2722a20d79afbca93, + 0x1866624f761ab8dd7a91c5f37af5e47639951d5acb6b1bbf3b96ca273f71029d, + 0x13c119f36718f7d5f09ad8541325a13acf6b34db6d9ee2af7ea06061240f3009, + 0xe4a1008158077402b11f13c08890b739643cc8e93fa44487b5a1575dd867fd7, + 0xef505fd44ac10a251b670dafe14cabd9ada9e3002210ac9c3876f37de4e7ad8, + 0x1d31e4e2a5978b7491c43d367470a5a5d1445b6b8129a5b9a6fd238405720de5, + 0xa979ad5428d481cb624d9d504524a9694ca5cb4421b5d1dc6af2c030fbeac39, + 0xf7fccd2ec8bc6ed9ce3682f38aa291deea9373f4995778bf762ade36d6ab2a0, + 0x2691b924dfa123005f7c078d9bf8706defe99c2ba99bd6ee53b153e9fec7bb80, + 0x2077df6510b4860e56b913bef3a80dbc464b0e4678add60dea7a9517463220b, + 0x29ee09d8af9d24ca49350ce2e0aa47d00a3dc21bafbfac1c9ba61c58e2993e8c, + 0x8b292c661d427506b9a01916624f3cde332aaced9f1a494a733cea6f25bfaad, + 0x2583699ce536a757b22e4713edfbb050092c84abc72c90ad87393a1da9a4cf90, + 0x1e3f1b660223d65ad88999475374f6e25fd4148eb8110a0b12cffa19657b0b66, + 0x20f3ecbb37c34aec79131455461259e59b222f0ee8e02f3194cf62a9ad4c3448, + 0xdf4f5088e4444fbf87d553ba62dbda95696d8b9cf6210b1c85513b1776fbc64, + 0x2b348effd4c9cef00a1cf4dd67dd664b2ffe361a807c589a252c63bcbfc6833, + 0x1ba1e522fcb153676cd8f20e82256f0327c000fa96b1b462fc84b556f26a86c7, + 0x294c44df8e68c96144e964c37bbc5766764ed3550aff80dbe9d3fa74419fe50, + 0x313716eec6dcd8a602ca040700498dc04c77dfe2194753c59bc818c1d2636a1, + 0x287dec74696d663e2359f68225de955384d960bbafb90967429a442e19e3ec61, + 0x25e42f72c6be0942311ba097cf365683db4962c8204fec9213f0f8f72c1946be, + 0x12b6881b96654fe1768c242acd5399b08639f081a94896f5ea6da70b6b475c91, + 0xdfc2b54546fd3267d7be55c716cb243ef18118ed9498c8270449bd9418afdb5, + 0x27dd55fe0d5c0ff56ad4890fa029c27c5f36d04cdc73899ab99b2872b28eedf0, + 0xc60962711aef16e7a2ce59f587443ec8b41ef8dcfccb38188adcbddd32f173f, + 0x2edc09feb267c6b586e62fffe32bf5f16c28b585986b81116684b7e8b40d42d2, + 0xaf8386859db252ff295a19466d8d100622c90502137aa1cd4c4bcc9656d11e2, + 0x121f218392f73d4c16abe382102a459e6c080b3ca4eda51a23e651a13a680550, + 0x1ea38273f5d59e65061f8c775c571ffc75ef67d29405b5e02913cb3019d56f8e, + 0x9bd2349005699bcc0ac35b627e2f8f08bfc3b0bf30b146f37742ac1556187fe, + 0x91c505b1e92448c11aea22aaac4d44f6a7f2132f89e91b7f55f9404696c1433, + 0xb316f1c29689d4f490f7fcdd5e9f2d256d443ba14cda4bb799b0573a931a99f, + 0x2049251919a8f3f4398188b81f99d2e2d0e3f5359cfa55bdf3aa75fdadf367e7, + 0x1fe7f9eb6788101908814168e3e4cf7a899a105bf9e584af0064188a4aac55bd, + 0x158e6579b0388153b0acd630ea94de8f6d966d529c2d01b9e9b1c67c1ec1d570, + 0x1994f82f27153afb9de2aa3f4be05c4b2c487e393dcedca2566aa6b7fbc3696b, + 0x1b6250553e8629a5a8a40b568432ce7dbd83c87603eeccc8dad572ccebef6e1d, + 0x20296940a7d1eded2ae79fd78fa2ac11abb2210bf24542feabee71f0d0d7c9e, + 0x2553943f9e0ffce9c297cd31c29f1fa5f01883cc9e504fded7a905032c170c89, + 0x1c56eb362896c2f00ad18faeaf04d577f5feb4db4e077965c38f2eaf5f7be08c, + 0xed8857205e0680055de7e822b6f7d62ac0f75fef67da1ff7b7735208885cf90, + 0x118f91185a09355f9d8c3f556367a2bebe79e7d9528a8d72a592681671aac75, + 0x2a71e6a67abdb25a78010fe6fe0a20d1d84e21cba75ad55937dc1834c13af0c5, + 0x2327dbc05997ce8575680e4b8929d4e9ed25fb9204277d603061986dbee57e0, + 0xe05235e01f21cc3f2971c382d18c14e41785a5ec8d447cd93d13281792e6d6e, + 0x98afa2ea7ff065b2adfc4ab00f3b04496c1e490eab264d2370b107e5a49204e, + 0x27bddb7bf06eaa63419adae44209dd25a4e35edcb863b009bd34ccc4905d204b, + 0x2704406bc806f4ccb19085cb9d3771b12ab5ce7aabf0601e9e06a2bc98837ade, + 0x21c75c54664b9fec86756aa9027261975244f42cf91c9cc0b33c2a62b756a3ef, + 0x2be84c1d84c16038ea5f933290699daaaa8164c5ea39a02bcbddc66cf69fe8ec, + 0x2c970e41d48649cf013c676c8c688ac165563720d1d5f32628ac5b239488a96e, + 0xe1ad2660a2e958daa1f2654b3a37fee60546ca0327150733070742edc806435, + 0x2060ee7fdf775fc7e389a55376374c9e35d5c8763d597f426304e236f577b829, + 0x1e0116818c843ed86f09daee0a581af10d52deeadad77656e736eac08e6f0f17, + 0xa89c1498ef25a383d886bb58424e6940ac399e3e557e9de951a697c54a7576c, + 0x303743d6f36d925e1097483350f5bd2cb297d4ec9239209f63c516b849a67e6, + 0x8cf44446d968430232df175d462b9c9b0e2e2c37e8406764cb96c7c3446018d, + 0x2419811cbaeb3f551b0a9232eee5d53e3769fbcf5239533074375f1b00777f16, + 0x4237c622626db376b774849dbbe876809082f1b13f5824f4c58369f27fe7b6, + 0x1e5b490c72eeb607e114a5cb87a8494b178937cdee34b9e8e947342c14454558, + 0x4265333e59e1a5ff749203cb4a5d1415a72862c61380b1c242d0f32ca15b97a, + 0x189deaf74258451ac4da682532be43d24a5c683293c1ff7486de26d35d982e86, + 0x4ec516b0fd42fa53a34905cfdedaad021b36399d03d8263ae08c46af3eca76f, + 0x2ce1c8a00845a82b3aa1b6642fc988578576cef86196525e6d595c7701ad700d, + 0x247816fd0d34f9d3b396917478605c94a1c052a6ed663bdc344e7aee9686b6b4, + 0xc676dbe6c494d5609c444de622bcf60cf555091a507fce86477019daea987d, + 0x1cb395ade530fc2407aa7b2148d2dfaee30f4ddf258fc149cce3c5cde80a85d5, + 0x190e1494e3cfdada3b9e65d8fe3c1ec769540da023f9ec2e56259f6a56890b0e, + 0x18f2941b2335138336c351a792343222a845ee0a2ea5a3b9160c1d6d9b229fe2, + 0x14ea23ce8b2312e07df57e0aece1da5d2c0e01f757e6a5c86ab5e403688544dc, + 0x2818ad1005f4efb5d554361a29f85ea10940d6e71f38e8369beff3563a660bbe, + 0x23ce3a9a522915a281793977b49054c37d65f90b841e0ca90817bab49d79db4a, + 0x6c2ed2be876309a9b3b44ece37b1c42382927dd04249658a3d41e3f38d5e022, + 0x18b6740f72d77ebcf642b945ca2ed6c8a9853a3749d7fab6051e4ca36f44fc42, + 0x1feacb9eb2a6878061374d069a9dae328369ee63e75a1b99cdb06a48b0d9976a, + 0x1a44ee4565a967647300c75ed2b2543d8d45d5477fd606a356d1073bd13831d2, + 0x41f3b3b5b1050c16bf3d62d87d5d273b067da484679103231ed65a18da9fe48, + 0x1fd958cc4fe0a290bd0fbfb8b8a513acb5898d63bc0d7e585b7d081c49eb5659, + 0x175daba07c5edbf84f09c87a8c34dd73325943a48fc12cb839dca47512561d2e, + 0x9cf0a4e6e31dc24dfd5a5a27a77833e477d5b2d92cff5fc5ccad9528c43ba78, + 0x12d49465bd4120cbf78e5a3414d44c6530bc963bd701c54d4c6418a6cebe80b1, + 0x101b2f2b675804d3b26b2bd1e07c7365af0bfc2edf010916eefb39e28215d44a, + 0x114fc65faba09a59749e0b5f111930783529a0638456216232cb7e5a339736aa, + 0x1dff99b52799afc802c2bbf9b67dd044d3cb51017dc4f88358ddd67366d3a9f5, + 0x290f4496a52dd4dda59edccd7325038bbdc0554ad3a9a0be7931c91062a67027, + 0x91e8704663c516c3b96721d2033d985089fb992dca48c8ddcb97d7d15c7e188, + 0x2dce22599de04196a0169fc211d0f9c8692643aa09728eadf6d50bb534c0e323, + 0x29a7ff0720e170c0e67efde72795328fecef66daada5f0e2ca858a8c6135fd48 + ], + [ + [ + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x2a70b9f1d4bbccdbc03e17c1d1dcdb02052903dc6609ea6969f661b2eb74c839, + 0x2f69a7198e1fbcc7dea43265306a37ed55b91bff652ad69aa4fa8478970d401d, + 0xc3f050a6bf5af151981e55e3e1a29a13c3ffa4550bd2514f1afd6c5f721f830, + 0x2a20e3a4a0e57d92f97c9d6186c6c3ea7c5e55c20146259be2f78c2ccc2e3595 + ], + [ + 0x25fb50b65acf4fb047cbd3b1c17d97c7fe26ea9ca238d6e348550486e91c7765, + 0x281154651c921e746315a9934f1b8a1bba9f92ad8ef4b979115b8e2e991ccd7a, + 0x1c1edd62645b73ad931ab80e37bbb267ba312b34140e716d6a3747594d3052, + 0xdec54e6dbf75205fa75ba7992bd34f08b2efe2ecd424a73eda7784320a1a36e, + 0x1049f8210566b51faafb1e9a5d63c0ee701673aed820d9c4403b01feb727a549 + ], + [ + 0x293d617d7da72102355f39ebf62f91b06deb5325f367a4556ea1e31ed5767833, + 0x28c2be2f8264f95f0b53c732134efa338ccd8fdb9ee2b45fb86a894f7db36c37, + 0x15b98ce93e47bc64ce2f2c96c69663c439c40c603049466fa7f9a4b228bfc32b, + 0x1c482a25a729f5df20225815034b196098364a11f4d988fb7cc75cf32d8136fa, + 0x2ecac687ef5b4b568002bd9d1b96b4bef357a69e3e86b5561b9299b82d69c8e + ], + [ + 0x104d0295ab00c85e960111ac25da474366599e575a9b7edf6145f14ba6d3c1c4, + 0x21888041e6febd546d427c890b1883bb9b626d8cb4dc18dcc4ec8fa75e530a13, + 0x12c7e2adfa524e5958f65be2fbac809fcba8458b28e44d9265051de33163cf9c, + 0x2625ce48a7b39a4252732624e4ab94360812ac2fc9a14a5fb8b607ae9fd8514a, + 0x2d3a1aea2e6d44466808f88c9ba903d3bdcb6b58ba40441ed4ebcf11bbe1e37b + ], + [ + 0xaaa35e2c84baf117dea3e336cd96a39792b3813954fe9bf3ed5b90f2f69c977, + 0x14ddb5fada0171db80195b9592d8cf2be810930e3ea4574a350d65e2cbff4941, + 0x2efc2b90d688134849018222e7b8922eaf67ce79816ef468531ec2de53bbd167, + 0x7f017a7ebd56dd086f7cd4fd710c509ed7ef8e300b9a8bb9fb9f28af710251f, + 0x14074bb14c982c81c9ad171e4f35fe49b39c4a7a72dbb6d9c98d803bfed65e64 + ] + ], + [ +[ +0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, +0x12873658ecf188d299b8ccd568eb14a4d4307c5caa95633dc296f05cfc966598, +0x153cf8033d8e8a15cde2c5e6b93da4018c5954d00a9274ec5ec6d5101ea22761, +0x9f15a882446823fdca6f6ab15dd8e250d90c84470516671afbdfb0de80fb00e, +0x167c655bf6cf3e0fb64c9075773bc862b24b4ce2f69c8ec198add2758a2ce216 +], +[ +0x25fb50b65acf4fb047cbd3b1c17d97c7fe26ea9ca238d6e348550486e91c7765, +0x27f9160806de9ef57ddb4243f839e4b7e8bb293ac176fdc5b5419ed73a07999f, +0x16fceedd703bbbc2bc6f1d792e501939105b044b1b904d3b110110da983ccdc2, +0x2eaa925d06b6f5a77c0d5cb20598742791495cec84593a57ee9fc4c9115ae7ca, +0x279b324735fbc883e24f191ca7039f9986115b9e6fcf4946cf45f08ceda2dc8c +], +[ +0x293d617d7da72102355f39ebf62f91b06deb5325f367a4556ea1e31ed5767833, +0x97d71f1fd579a0d0f436a6b36165cd23a9fcab03ad25e7872cdb09b4a0ea0dc, +0x1a9fd26611128d592d594f51c251dbf4eff6dccecbcf2ebf310e34bed661337e, +0x21eb30a57e5912ab06d18573fc546b2bf3be840d5f5ede01f91dd2bbb578dcc2, +0x13abaf72889b31372b1e6f48759371ef65bc57d28ac2f60e6d227eb008b96ced +], +[ +0x104d0295ab00c85e960111ac25da474366599e575a9b7edf6145f14ba6d3c1c4, +0x19bb8abf6a012cc7b8b974039c6be6df31446a51702b39a8d90ae4be7ec33ec9, +0x11075889bc0dcc9d6f06af3012f04aadcf9049de04fc775f8fa091702e70b9bb, +0x2e4cb25599a3dbf07de338827b28d16b9c8fcab8fffe8f2a16161be6a521a358, +0xc7a700b33fb23fc642e0e8671deb84d05ded8ccbc968d15171182e158684e85 +], +[ +0xaaa35e2c84baf117dea3e336cd96a39792b3813954fe9bf3ed5b90f2f69c977, +0x2b5d28e8d648bffe0fab59e3c7d983a4099fa0a4c548df0006e6d0f4e20206c1, +0x1a96c37c461ab8a38ee15bc2784c5096d30d1482e57c2f861bab95584b90d84a, +0xdbdd3171308bfcd3cb8b8a676592858b8652e902142beb8fe4145002fba8e0f, +0x17ac4855f295a3b8fb8ceded7f4b39290647a0145af56b03b01e957808d66fa7 +] +], + [ + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x351d582486c39726623750495e297970b0e19787b49173a9388a0d5b08788ab, + 0x10e1a3beae297a472a31a3b51514c664abb12ec2d15860a29d2a9352d3ce8ba, + 0x12395fabf1c14664faf3ecc72a84623c1d5cb7b5e5744e602c886a5773e5f06d, + 0x9b91873151f00b299a173a5b736f73fbe2ce543f0b4d237565bd58758935cfd, + 0x1d53cf618f93c90852172c773264b8f49e938bf22791cff829e95ff6942299b, + 0x1a78e48450798918f254396fa7417bf2c5ff69259200c2a8d53af5f2c4d8ba1e, + 0xd3d4c1eb9828c87afeca8ea128d1d533750cf555c6b70d70a8520ccf16feb, + 0x3af062fcd1ca71ba6de0ca4436f1a5a0698a3f49abbe4ecf3daa0ea2e4dc84c, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x1ad1ba4f26d401924b25657414256b59767284a692897ba5cd53a7f5322005fc, + 0x1133694747d2cb4890f4f5982564eac6019ca5a9091b302d2c10b87297041d5f, + 0x1b46c42ff1aa475972e26f559a88164024234f7b392039fb2a2171be631bd8de, + 0x1954aa0a79f14968c817000929e2e744262871011f238d986086e7d9574936b4, + 0x7aced898db99ae9796fc7191a103b9de4c77f0e08ecea6aa593974f652ac4ba, + 0x18a5a098d914f6221726d42ada7683a1605e20217a09489c9b2d84c3cdd2c39e, + 0x13e00cf4ab3b1e028165af8d41019ca20a21aeb40926592a180f9806083eb5a0, + 0x478f72938b528ec79defe09215b46320801fb752ddc88d638a48790561b4e2b, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x8ff43b0eda2134077b96d7e4cc37a6871254910ab4c58a4bcc78c1bc6ce3937, + 0x27d7fa3ab9c438b6ad1ec5a60e8ad91aad02e4d2908ff7192e5ac0cebd91f928, + 0x1e9ac8ae7cf2b40d629999251be50d9771391326a664dfc206f2abec8efbe56f, + 0x2d6b56b4849de82b636d81f2e98476bb6c35cbc8962137b615bff86f8f261971, + 0x21e70566d2f4bb8728fdb3749da99a2143a0d90bb6c1b0d6d02125aa1fe63092, + 0x1c01c050dd9b0b8ec8e5ee1eaecac1171bf69a8f3d477eb7ec3a605b010d4ea5, + 0x282e8dde73a0dc74ee10816aacc1dba10c142109c14ad7954eb7b56ca268a16e, + 0x767cf96b16035a96d19fcc57edcd92e746d226cfe84b733454c7ff9a16d25cc, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x18974b9f253b6bb681f82ed0f2d3e6b4f70ca858468b7f1bd3ded1a581ec21d9, + 0x18153fe8966abfc450a25222a6a27f6175fe851989776dcd2111a5a2de99c2da, + 0x2da1e2e775539490c2fe2c827e65c00e382a4a5d6c49a8374381d39c627f36c, + 0x2608589b9cd3f4c12b4e832e05fc5ebdcb403cd6560a8d7ece8d17ac94e79e06, + 0x5b4b074edb1366d35bf1c1ec1451a36cff351b407a8d30d563471bde491f146, + 0x856cc5a00bc37dd0217920da66c5765dea0644555e35822d7fd464d9eb38096, + 0x2021dde3ed193bdade457c9db5ab799e6b3fca640669d2f6295b4852f54d446e, + 0x12e3785f05f36bb797b2c9f03c5a55fab52e88b0550b7155d6013b706574d41b, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x118084c76d1340b3980add4df3878df4ffc6e9fe26f0b5c4e2f9579ee6fe2c1a, + 0xb9dacae8623c514c622c85753ef7b994d9102ab46620f956c26e9c62fe53050, + 0xdaea6d18a826bb2ba972ae16dc621cb8fdf9ecd531ee3c9f9d0b4012da6769f, + 0x8f2a5df6437e253b579921fc3208b3c176e5a18dde267a4f85b7afb7f79ceed, + 0x6a91d7c75e34fd43d9aa53b7d2793e4d5d70a5fecc5fd5653b162ba2631aa68, + 0x207579e33c36af2d20d759996c313f78dc339878c0a289d5db58b6b3d6069c56, + 0x25562540cd12084b3392c8cb8cda95ffc9c2dd6f8a75054ce16acf87ba871b9f, + 0xbbf47feca60b93dd0501ee0fc294c2a82b103817b4acf0af6979183afcdc87, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x1e0814ce223453b24804a1ab4ce39815e35aed2fe9f7510e6288abb9d8b15711, + 0x18f9aa2721d95963399ae18d6d95a6f81b78b528e750554eb2613d6dabbd72a9, + 0x2ea329822ad302ab8831c559c64080e7ba6bf4c98ea0caf9cddd929bbb5875a6, + 0x29910d86bc27b38a93bca80677a3647c01cb5262ed19cd0c00872925a046a338, + 0x21c0a05ace45015ea895e01d630ce6b7423f3c211d26e8b6ef54d3dfc0660ab, + 0x25e7c463042f520ed2ff8c68be30bdddbd7ea5cdd7a91224bc6a32a3f5c0fcc, + 0xdf5b7e7663197f911e0dcd1ff4237ffdf080234e9b92201538ae7db6b6a7d21, + 0x94d0fcd9592b4771d2b9bfbc2bd78defef3b6ca923c68382650f9d63ce37c85, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x270361108967ed0391a49d4b7cd6af9bdd544e8bf048658c4fab36aa12407263, + 0x18bbf89e7cae93044c847bea654101914dbdd1656483e54e07ae332857821961, + 0x4aa47a0ede64ecdfa83507a2b8947b4b587758d75239071f6b4d3d66777bc1e, + 0x182d30ec988fca803ff7def1470c06aa6a596f56710184909fda17d354d3ce02, + 0x223c27171e456846dffc59cb1a53c761afddf85582e4c70ebafddf10eb1f8448, + 0x7d46dc97554a25edb78ea4d862c48bc5a08e9ea1eb369c5c8c2e0903114c915, + 0x1bf473a2e982e519523b486d264941d8e32cbbad362bdbf736d7ac04c4d2a964, + 0x12277b175bf54c3f2b0a57eb189e77714cf21630ace1fcf44d39397aae5b6da5, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x15c0a2cfffac7feab86a185031f489a9f83e89e3337a84b51dfe6fbb57feb15b, + 0x2b83199ec584185de52190f5a415c1fbb9efd4bb9eae4c4e2763abcf99359ccc, + 0x28601b9940a312c65b02adccb76937ef645d4e451c940ad4241b2b0f4925d7da, + 0x1a187b4875be24a2420729e016901b94ec0566c8a6936978c3f21e8d611996f7, + 0x10ed1fd44722d10bc7e44824e64978d36e68d56de2a465a0201b8e31065d5c57, + 0x2c4b6867179a949d377a9bfd3efe48456f7e70f02d859c78684a3573486dc227, + 0x15cb2c17aabecf7aa0f61655a8bb35a7afd87d0e20ac38fe21a07da7b388dfb1, + 0x4dff03c742111aab3e61f4166a733e87699c1ffa889fce179316e39f7d845ec, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x17baac874eaaa88de70cc92d5a72e00be4ec0e5e99ba7cbac2b0d98cead394a1, + 0x1dba338b4779919a2fb22ba949a050c85a73983d5ea4752cd73f664fe05f6247, + 0x1e33e7fcc41f32f90de5771d69e58f4486290c7b856becd5cd967d8e7739f719, + 0x10877ad7cf0652a2ff93977d3862e3ffb5d87d0c040f02a4f98612afafc9b604, + 0x115d3675856ff59ebcc9110defb9d6c70df6af533d4b0875d0e5eec430350595, + 0x3d74b961ba9013a874e7bcdc782f478da6097537549db7e6af4702ca749dae5, + 0x2563411e29867500a8fd18e4eba3c9a2b7992e44d263c29f7e06000f74887cdd, + 0x285501c4e0ee1b3c3e6b1b29160d6ec0f1af4dc2f36a4a1e654b7b47899738d7, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x209194489c86891b179e33103a81d969c5c75e941dc30e7228c04ed8ba68704f, + 0x2c7b2835cb79c29852926900cc168b2315aaf03a89532dd9fc162c2f7ddad845, + 0x1df181c420308c5b0bf00ee21c16f248edff686e9e835869d1022dcd4a8a635a, + 0x1ffabdffee2481d8cc1233506f708d9acabc1d758bb99c329142c866ef4c7474, + 0x8955ed55c2bec07027e4355a694a9b6ae1d9d50126563b29d8a074ea65540f5, + 0x1ab4b24a4db7c5758471846eb375163e7587791417cbc355b6ce93b64fd01da2, + 0x25a3439d2838ad459270bc633164f3a68215e11217eef1d605ecfa8b1805c609, + 0x65240d63179ae83013295a8251fbe17dd988ca5c84761ccb6a6ecb2bfbf02a6, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0xc1a91ddc1b24113bf876a2ef895c3315cd1b109cfa569b79f3155ee12b1c564, + 0x146fe8e28539ae36ae921069f4af83f675f1b68399efceb18989cab5fdd36ac9, + 0x1ba8c3cfa46425412e30790090980db139810efed7bdba7a38adf75e1a0d3641, + 0x83a58c9d889b74e66636bb8418db624726b0f1374f59eafb4d269ba1ed234d8, + 0x2b812a76ea526ce18df6032192ef033541aaf99d1c61839a0edf0336142a25f3, + 0x295f6d35fb9e57a50a5d913600538030ba8c09e021c16aa8634488cc8eeba645, + 0x1de69ba07e3b9f90c87eb67b1f64660c71befe5138061dbebb752296032542e6, + 0x24734fa363e52c64ee0162a86578ca899796e89caa1a3a3533b0965665208f59, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x2d5fb67efe93e8386fac071fe3522be1dade9dbf1d1030417a7b51e3122111f4, + 0x19522e9228feae7473e317fd7958a021a0b042a81b75da6dbf7568b857afab75, + 0x2bc3f6f0df0c7305afe83fd9ef0b708e129fbe889fce42cb695b33b290479342, + 0x783e5635eea0e623bb8c406909f0db77ad4f9302d4828b51015d6512818690e, + 0x2d61b243f02e21edaed6fd2e4969ddb95a6d0da8db17d115a9a3b0d8885bccaa, + 0x55e1a09f4bd4809a86e67f99279fc06ca89a4468df1ea25d76fe0ad36ccea12, + 0x17871eed22b0cdd2de61e55ba5c9f4e37da63ed0376420bb1ee7f077a0d7a85e, + 0x20fd0af1329bbdd70d4d835d18c915d98956c5f0a4252cfb81c1fe02fe130091, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x2e5b840ca8faeba6ec3613e22eb7b071d9633c83cef659ed96b2f6a8fcc6b262, + 0x5f5385703edf7c4a388ce585a81fe7cc92ff49e900b5601865a352c61d6b111, + 0x21e83ab5e95d369ccd30cc1c55cd5844cb1cc78ffcf0c8bc91c9c0d9937a3fab, + 0xa67b7ed9c37946306ac525597f1275b30a5d004ca50258c3d992284d90d724d, + 0x214f52f9f73a2c2d5425c9610461303d839dfe71891489c376c2ea3b5d868b27, + 0x241e0d267f7d1d899656929cdebd850f70ace216d9ac10253ab720bf40da0c7e, + 0x2229153475b7a6b282e110b10e8aed1fbc2a05a37352e954f40d85205fbd8bef, + 0xf30d0b7cd8ef10e895cdfab3faa4f4c1a61a5f4eba688634540619c84782d2d, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x265589a340c71d49e1660d3dd43d1869408176d8b9110ae8c369078de8ff7aef, + 0x1bcadf844bd1a2e7f4f464991dd651b9f15630c94977d35ebc3e85801252ac2e, + 0xc112b1c56ea288e8518cc039fe050649cf40b7ab98de8fdbc56eb7ef6bcfdde, + 0xf020b9ef75af8ddd505cd3947e11a04270be15daacbfa76fa04d9005283aa77, + 0xa426601ce9415e666acbbaf2a7cc8ef7ef7d07538d84b1a53da24c19c601688, + 0x10a1af65503614381fe2003123aee9008ab97d69739dc462e72a8be04594618e, + 0x2d792f9fe5f0ad658dddadfe3893d158012d84b3837b7415e188131595b060d2, + 0x2daa42d04e0b62fcb3869031bf382c3b9f8a98f7f5bf7421d0b63c2598f5f65e, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x144c0395157a1bfcfb5cc4187f271096784dbcdbfcb6a28c31ce8a06f908c0ac, + 0x1af8cdba0eccc83c16019622667527645e94c9ce64add4415df7f40446277a09, + 0x213c7a7ad6237e7211530c210a8d6f46a25bee433bade010591e6adf42fcd906, + 0x224f1ca24803c0119ad0e6c41a64968e064a83f5821972f2a5c9d5895da4ea42, + 0x10944d95ff5a3699efdde41ead13344937e3b1b93ba73a1531246ca4b99aad2b, + 0xcb2508b0a3395fabbeee5286ce5f1839c006ebbc09d94f475924923d8079ec2, + 0x284a14b1007ff6c5c0f8f7d8d0e4b19fe2d4a7094103912134b0f563a672acd1, + 0x2bc0bce43d55bfe1a27eed426980cf9055b0dbd42e8de516e77580b9d9a9060f, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x28e9b1884a4619b38b6f8a384368c358b7f210f3412c4481a26ae296f73c5c72, + 0x2123ca1f119a35e7d4e1b323fd2942d12ed020ccff3a7ad6b65af90457f00614, + 0x4aaffb0ba008fb9a82fc0700beaab2ce39efa895acdc280252f01e31035b8ad, + 0x1f1e16f8ec9261c82443b9b31cd908015e2c2d2314629a22639af1f37e1073d8, + 0x134928ff5ebe5e019214ef937b7f7a28248285d583613ea2bedfc66b5e2ae924, + 0x87fc99e11e63deec9d55047ac98030c57a4f09228cfa7749a3e1c7ab5f212e7, + 0x9429bcc52d6c43814df5b07fa116f8875299500a36ef791b592a64e27cca486, + 0x2267b1dfa5d26e6f0a80bc8b4c0026f0204bd4fd06c7725544d7760354e401f4, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x16fb3cdb76d21d3448c9988f428d198c8e5a640035ac2caff7aa7964b34ff1dd, + 0x80dd9d263a6698479df06bc98fc64594478028b61047ff93c425b29b092d37c, + 0x165f4f2d302a24eea5f46abeec4ab03d21e3d013865085e515bebcb2684af340, + 0xa8a3f3abf28f457c62045789fdcd302f0df1049b6ec521db2b7e72e8d9516cb, + 0x2342f103587a005c977578b12810378f9014bae831809cf7ad59ef3aed48aae9, + 0x1d1308e311e7ab846e158769c12213013eca377f396061aada6220f29eb1b7d8, + 0x2563949aeabfaa782be07dad903ebff5c913893761b75a3f8402a1e2bea5a998, + 0xcb371898d8d2e1f5bbc32dc21782704a73e415e0c9f6387157b48746bbf6ebe, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x1231d40e7c6fe5bd47010ebe4f63d186369cdb6e8823aec194093a0b4cbc6845, + 0x18943696a4da551747068255f57a0437ba0ec36ad7e5c92cbed9c49a9775b97, + 0x1fa58f378160dd4af40e3b01bfe32dfd34f2cdca527973c194a53af30bc40670, + 0xc976561eeade533c5579041bcf5e8272e4af95efe3af9e5372250fdc5ad8966, + 0xcacfeeae1a8359ae9fcf831f315a4b8c576d579eae86b1b09823656231d3bff, + 0x109b0647298eaec354e4a155308192b5facfb586bc2fe63f073cd221a2106fb4, + 0x69d4744aca289d123baa0e6754c5232202dbcdfadd0ee8d14dd19a7bea39781, + 0x156195fe27df23b8184fc58a30e1a9bafcb9cc9fa9ce071163a26dccfb7c6ad0, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x20fed35942cbdc86df51a49ca26055bb25e232a42476ef06997af8911560fc12, + 0xcf20343957a55345423dd3450c2fd74039f1a82c6c02446dd64c4569d31471e, + 0x1e177139b05dbe38a56c40f919dc1f07126bad03049fc4025d77b4bc34c25ebf, + 0x144d1944a849fdc2aba8ab2a4368d57911e9614e3956d9326ca493c83050e932, + 0x162f08d305fe4f1b0a9bb1acf1223bde3405aecbf2356508841b85f1180cbc1d, + 0x21d68868502ab599c7c5f2a54d65be40ed5caec1613a98b2a98c5f8117415d97, + 0x984adb0c5263193be4027c68c6f3a6dbf7e22cf199dc4358b52968b0a248789, + 0x2883f3a940a8c10f7f347a8011b0f0d7f6e0a4a82eff568fffc7524235d1e4f3, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0xd89a340993be3d3ba07d2fa8432d412730e8ebf2bbfacbf9378c0c4d3d1e692, + 0x105e4a12836770bdbab24c85e7a63572c77556fffafc8f55a0e3f6e7383f7b02, + 0x4b09e851bb6dbbffd0780af3f99cbb707f5e8a073810b28b1b59794c8b117a8, + 0x2c8031907c10e1df2bfdd2589dd502a012a2292202e67954091ca57d21906d41, + 0x88a360cf4c5e26faddcba291dd2553906abd82fecb0ffaff4f3f544f672d703, + 0xe9e8d8ba62712e7f95840b5651f32912e84f146bbd57c566c178084cbb155f8, + 0x38fbaea7dd737c642ec414759bdeca4250d31d6011140e7e45e86c12c6f6fe2, + 0x96dea6e0d6411dd0c18e516511b03d8506c4901c52dbc2772c3d47bdbf461ab, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x2d60fb66fb133b0507b6b41ed7fbd5278c4ba9fa0679d2889da9672d21f07037, + 0x2567f444cfdbbf4d7799d5b50c8c582e1d2038a11969b3eb2b60aebafb1efc7b, + 0x2401d941b4fafe3311bc6cd9fb0bef62ad9b59e731c1ec4e6b0ca5e2c685bb2c, + 0x28747741579283853ed4e6525da70a4312769f7040db4f098eb7d9214fc8fae6, + 0x1104899fde3f530cf99500f20c4fb9d479e512cd70a15def442a4ea92bcb9743, + 0x4ddfde1b1aacb33977d4b3020db51b834f6197a18505e3ccfb37fa8a3a8764c, + 0x2bfa6913d62c8aea04ccc3e50229220efe3b9af6a568194ece56c065e3cac8aa, + 0x5cb914ec7b72436cf25adcbd0550c2db3c9c09aac565d46f96ac156fa72a90e, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x145dcc8a89ffd8fddf4e5bbe377a3b7649ab6faaddf5eb580ced3e0421b7077c, + 0x21f1b7c169a0744e49718346cbd390dbe3287f5de3897acdaaf2e4bbc1f3e80b, + 0xeeae34b5e8e48d2ba6bd062c803ced1dd1165cce5f8f0574ff7caf4e6eaf6b4, + 0x2827170c30a7f570a12f37aa0434e01a4aed9b5d37f1815029d5de89a8ff75e2, + 0xe328161a29c0376af526c8004597fbe018328d6d0c89503eaee36f59a4cee8a, + 0xd6617ff29ac941a779f907e749603cb36778fef6644b8684fa40055c8d978c6, + 0x169506e0877092fdef32109c064d251c4d6a50257ab9c032bd79801fa23094ba, + 0x8c516740479e1a852294e8cbbcbf83b4d7095b69758aaa9f1a368004dc1742a, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x281bcec4cbcefa9e18a1aca1dfeacd7f7ec527df5deb6c002f541ee4c0f2bcda, + 0x13ea58a6a82bf43f6d4c2619b87da0ce760410b68b77f694685e3f34ff47b86c, + 0x1ed604569bf581c71e4180d59a78dd48e2103006ac045566e44162656c36080b, + 0x15d25d19f8fb93c9272f10ea525e787c758f98c5bca884e6317ed21a292abf6f, + 0x1696701143abf5794f370a122fc60dafa4f0c241e8607983222bc72d1d8d1439, + 0x1471c9bea5d880676ffb53255487c1af57a0476b77eba56204a4a3780b109b50, + 0x1ec18e953909ee6e34dcbdde64fd6ae8b99817ffef4811551a27924b714cc00d, + 0x89ad915c65eb1cc1633229dd97f098a2f86e7ea44ee6d94f3fe5f08682c807f, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x7e3bb22a5d8f517b12b42d68ab707d809ce83671dd9a933313d251889a9d55, + 0x142b4285cb7ac7249975ddf59d177aeed1a94e0412002d83861ce061e3f38621, + 0x24839c6f8fade0c2ef1e248f64c4d81e324caa4ef4052916a31c5d1da484ec43, + 0xac0879ac864dc7bf40955a3f4a19cf37846fcfa9289ae59c8f8c7c174c5a57e, + 0x44832eb1eb4ac43192406deb4a37ea61e2d110468762d3a31f01f3c6c1f8208, + 0x2b3f948fb289860a26e995d14c6f8aba2089511c7ba58a310e6cbcb533f2dca2, + 0x118bfa7e2d1386301f187c1b1eda2f48c0a03de15e370b5be0f431a0b574681e, + 0x1399fb352bfce7874d22e0fcb24553b96ab59b85364c0c3c9b0135d4970c2349, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x2f25d0089300da1d286c5efcc9cf22d095af8f615b76cbee09b9ba651d737311, + 0x84eaaf7a0b07cf4992c7d05790c42cc742a7bed021c48f614b988d99f141e3d, + 0xcbb53527ad34cbd3c4d59504fa47c87eb5be078155e58ac3f1e4b3f45dd1cec, + 0x14e8e0d80d2af6efd3cc60741cbc21f6da3a42e2429322bc209097b1d22d26b4, + 0x149dc605f3ad39d4b470a132191d2739df2ad19fb71e067f6ede3f9da3172922, + 0x1533cdda4fe346f0a3e538172b8d5636d3b4b502047cb268015b2088f12b9897, + 0x1da21ab47505b1ed4358160f3cd24a01330718bb901beedde8cca37839805c62, + 0x130eee6229e6346096e121bda6bd3892aba85c363deda16ae8c8efc6ba721b18, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x1d0669bb3cb83ad8702a76855510918ef300df2416cdf04a83061a915a6fbdeb, + 0x113f0f0db699267055417d499467b7502e23179a0c23787b7e8130967c95080d, + 0x28cd66f5e2046799405a9c14282070ef66fd409507971fcbac16032499bada61, + 0x230173d8146362d28c0cc9bc2c72a64afa7741b77653726017932821c1dc9502, + 0x4b23de911f3a1d3f32366c35a7f293837e1e7e8287b8abde423b2b3ab81c187, + 0xd4bcdd5ff441637f977dba6d523ef1f6178ba245cda76e429a91b0ca994db04, + 0x93bfbfaa8f3a8718603066321ce48219b55558f33e0f8645a93a41e6f4d3e2d, + 0x24e21e25f0b3d0e754bfd0e91e62b5fcd232e756ab34cbed6b4ab709dfca551a, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x146990fff0e10b8d70a4411f57f9e74a03d2ac0127b216400b82c8c644038303, + 0x1ddaefaba77bcd9c5ba0671b0a34a4cb37b7c689bdca187d90212f188ba4a87c, + 0xa7c37e8eab27e5edcfc3d6682b0267e3d9250fe470980956f5e3e5993ddaaaf, + 0x2d81f6984b67d7cc74b35aa9d673878f05d517085812190798dd24a510b8d6b5, + 0x7c46458e45e15ce1338bbe98ed3c0726664d8ae0c965bf0fc79ae31ad04a349, + 0x16dd83567c7289d8ea0e62df8620df74f3c987d5f162b6b0a24ab09837b5d2da, + 0x21819b9d78ef5e05c535a83e7d709f80f3ab5e8d733146139015ec4e34b29f1b, + 0x2340a29e4e4d4e920f39a6a32149b54307f918a2e179e6c7288cd02834c0e44c, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x1ced784118aac9880c9fbbee28972453b36abc3d967b20e9b0a886af86d64305, + 0x237848c6b0c87f794b30cad5a3cebfe2c6c9173f7a258f4ea139252338a3ea5a, + 0x27c636aa956756d9ee04b355abe2fad8d703b1721fcf73b17a77751813c8abb4, + 0x1b40358386698e21d43bd3950c00f81d6ae340eff9ac0821a213f8fabd142d09, + 0x695487b95b15feda7188ab9bd8072f0edfcdaea2dfbe06596f8c037bf52145b, + 0x1df336831b6745c8f22a80c252ba12b24e2bb1e7fd3615cc96145d898dbf3220, + 0x264b7a66fcd41995c19f021b71fcb1abd59986c55377a82ad92e79a1165e58f5, + 0x208defb2122d53224aacda9868250ca3b39f78b13c9d150a14d75a886a1a42bc, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x1627fe11fe92ca5b0841cd804a211151ca6c0d2706b2a17ec17a7fd224a48a13, + 0xd483b82a1ed0d6788ec73c257cacba9738eae7232e365df112b15a93459627e, + 0x24c490612a1636b43f902459851afb3cfc37d71db5e9ffd247116d5cbd34f9fc, + 0x2f2d08c8cab748b056307066141837d5cf195104459a91084768548346c8593f, + 0x42d3a4f87d782326b0c097a03de01ac1698954c8f300af708fa79a92e84790f, + 0x2b064fb3fabe9deb1593d253ecc7a12fcfae3193e8f7e16ec563876f92e4c62c, + 0x22b8060d8bd295c3a201655ef3891a481e21748554dcb7613ce6c0a532628e5a, + 0x1526148f85ce610667aa96af20059f0b02c8a9d4d463b27f0711db72a545503a, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x12d2a42d255875bd671d376e499cd79393db48c414f967d53388f60b4e180986, + 0x22d0f27c6767b64adf2eb09ed595e2f2c211a3504a8de66ac01991c81c0e2669, + 0x1fbcdf3ca6f2e0739b571248a9a994ea913375db065ed255b5eca3fde587dc91, + 0x402b7640d18feac0c700cbea0d8f527a7c3fb44a110c4d7cff21deae9a70e40, + 0x27f6c76f1b519e71c3888f1ece7cce4e0f99f231ddccc7798a31b0dee0c68206, + 0x2fe908cd208699c9d8e3b0c09f5c0fd58716d0eb50017aa7d12df08b53d963ff, + 0x1922a59ac83c1e2821afccf1610aa5fb0b3cf8eb3fe3f4957bac604c177fcffc, + 0x126fc5609db3cb254a05919034b8a7f9a0f85ec5abbde6f85068607250ea0ac0, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x28db35e17bb31e5be954d69f5bf8f6838651bb6f5c80f750b6b7017643b6c28c, + 0x26dd684288015065728c5e09454535a33e1537761d874102bd4ecd2baf40b384, + 0x1895d33a312becc17090e45df74981b4fc4b220d3aaa346c7e8485311cab159d, + 0x28bff25eb0f2a5c6d007a92a7c4d88bd9c12c5622d0ecc5a509c404048b7b5aa, + 0x130136f07c7e09acd49556f3a6bf0739c9efc0a1be738453af67b31e845c976e, + 0x259c455761e6b6420dadf3d6b64eb65493f989fb3e5698e7307a6d6075714ede, + 0x1c9ac464fb08828d02006c7529eb1e8f45eef54405ed2cfaa133bd697f618929, + 0x60abe65207efd0fda7b24719d35018f7607dd732e71c05077148f3d046dd180, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x2a41f347b5f6eebe8969667071926905a3e6e521b85a89006ec2f500ef42b000, + 0x17840fa3a180177731bce340ffeb5a3b6a68b94e3f870501e787edc5a94db63b, + 0x161ec94c3f624f928eadb0e2f2cf6b16430fba680a5a50590d89005a688d9b18, + 0x22d8be171b4571fb5b773c3a548fbb286b06e2701ce99b7630866e1bca6e2cc5, + 0x52464c9c7ad14525380aaea9b06e76f03db8edd220f90b03a9feef2fecfb978, + 0xbdee83b20d91ff9a0404d8b0593879c90f7be5a95a22c8e1b157d92c3cf4746, + 0x2d84235b4f4e04262d8f246123b8e631ad51a4e1051f41f1c89cc42b61717302, + 0x3d6b62f816bc4b464e2971cc6a7c1a585e519266c4627b1367ce7963cf93d86, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x16caff6fcc165168b3ed958d3aac8d09f98f670bdbb847ec0e9083a022d27692, + 0x2cd4beaac59c5306bf76ef7e06c81adff6de4bee730cd4676e966db45fc067d4, + 0x1b11abd8ee736830ffeda3782fc7a82623ecc5afa92c0ec9eeec58177ce8608b, + 0x2c80d3430e64bf850c9e10a22f6b781fd513af20d4705435bc870ec8cbe93cee, + 0x2d2f20d2ec0e52eec9fc2d0e49fef7a2454aa77a5055ebfc4d4449e8f83bd015, + 0x1e51c55a8d7a04be4edae4f7dfe6137e96370ee2a4ed459ec524b19de646e0b0, + 0x13d4327afa809e26c8f97e36ebb5be1d3992ec72d459760bbd25659790738f43, + 0x176222f47d8c0ff9e8a967920376793dbdb9dcc3a79b44fd25e1f43a755e6b81, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x5193cbcb59713c78012ede93db828e69336a197fdd30c6b7d03b1cfcdd6adfc, + 0x2bbe660fd34f6ac3f2545cba9f717d2eae9f8c60242851657f8661504a457c69, + 0x1fe59c3d2724f4158483406e6cd62aafa121c451f13e48ab3c857b2293333c3b, + 0x249c893f9de208601de45c9769ebad071eb864524003add0bde31fef7f4f91a7, + 0xc20c4a12bbd772e0dbb929b69b24751da26b0fa8639005ff786a25ac1a5fe96, + 0x1a0750fb1d27bcb326ceb3a3065a487cf7d513d8954f31dfb174fc5ed95ce55b, + 0x16d40c0ba7a7aa232eea997d45ec4f0567fb6814677b262aadfaefc91d409cad, + 0x25ccf860fc7237cc8721aaf1c717190db40ccd65bf65d108b16f851cebca736, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x1a25b1a6b81926e968ffffa63979c900c1e82452c986ae599ef991ba214e6f67, + 0x2b344bbb50400ea76151bd0b68c3139955f101c701d32befddcfec1ca72df25e, + 0x1044e69af594eca5f9ca7ee28cc38d161d01037fe223412e2f10838bb9ffd1e5, + 0x1145f6f783af7d1e0ee3388f107ccc27609bb8314bce27b03dbf8d02843ab2c7, + 0x20ed7009a6093b160020318b0bbfbc9a9d14de64a3aa25936ddff0ffe3a3bc4b, + 0x24cc5ed4ff9d84fce95c1508e1c7852fe60a6def592f423bb79c229327be7627, + 0x1fc31b0e67cdf9efa9c0c312afe54b5158ada1511719c76953587b772f1c830c, + 0x1faf997032cbbadc0c6d30fc804d068faeccbdf7cc90155395b739e017081259, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x1197c402e5f0a49c8f9b9a41af6fbcd013cf9adfe864613c1bdecb6201d9651e, + 0x3025d698462f4cf23c7d4d8a3eec4aa8e1a2184a43020122db653afc6d0deb4, + 0xecd1d402fafa3602052ab586f804ec15f1910542f35c608eb7a247d5a960cc9, + 0x30021619d0c0b402b429d4e962cc3c2a2d00c62c131144f7b3d7f8acae6975b8, + 0x2bcd05e889bf0fcd9dc4f5faf21c506cde15c316aaca47724e71bad0cf34b27d, + 0x1b890b4097a781900b40d9c1ffa06a5e8cd05ae8fe52e040db0e7085ca46b460, + 0x8081b53a974ee264310b279468093218cd5e5edec1b7da6b21ab35622242e48, + 0xe6632e8ec976cefca5b164e6c07ab40ac611fc723e8d8a14899a4cf4be3b2a, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x63a3f8dea9d024a6f6a851ecdb21bffbfe259ac17f6793c91e73823a82f4f76, + 0x23b2c6ec9af5d0188e75baab9990f663f8e929bcdac96cc09c4c0626274692a0, + 0x9a41c06730fe53d395c602113f1607fbe01425190d50d56e9f215658ad128cc, + 0x16571048fa92024a9345a0ffecc159e76602455a71bc7e9c9c01dc50d8aa1d6c, + 0x2a5a7e76dc76ad78878b3d3b4c74995e2ce77bc126e4d17db507161b049eadf6, + 0xa23738e129c11b285d81c1c01e3f87989c87600727e7593af45607f98fb18eb, + 0x2ce8d6eeaf4d6c7ca0922c4738e81dfba227e98fc3ed24e7696ebe9c2732a1ff, + 0x22e3bfb13d10368cee5175f5e2a2cc205d28021caf5fb2898de2389123178a5, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x66c43e71903c5b74ee8e90ec30a1d8cbff7d8c85d3c7b995a976036eef8c4b7, + 0x2fe5dfcdc9335f0c0dd3d08f4e783a5ff6c2e6fb7e2928840821e6da8d91570a, + 0x9accce03257f967a24c11ce718f21167d9d71a1cb60a4f50d0228418428300, + 0x224e2a85316b67bf2dc64549c505721a7858438a00e793fe76b961bfbfb67291, + 0x29f1447b45128f5c1cdb12a334509e0a991c0d2c9360a5cfc28af420c2ffffe0, + 0x1301ae5665bd3e87cb647f566ebcf2f2eb5bec4b257a77061a15dcc7b8b34abf, + 0xfc6599ea957e02f69b1ca585c7135425a6825867d0cdd2b06019f3c9398ba4f, + 0x22e91a30a945b960bd87d7b0d8290dcd5f5b1caa339c41aef323be1ba9c724e, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x1c7c359c26eab655aa469e0f9a8cc3d8c7a8149ba9e9baeca9233b7edddd1d24, + 0x1ddf651a5d396b680828eaea1f252625db1988504765eb4aeae3274a19cef175, + 0xab486e3e737f40898d3fdd6bab09213c0056c2e090a90acc754574739159385, + 0xd0b817b8995913e3ddd08b576951bd47b45f536739fc9cc782e769fd17e0028, + 0x13471abd3a25160947928376fcd79dd5aa58672f8382745e3a040c2acb464974, + 0x7bff672e50ff1f20296b1838e5270229a7477110d9a7fb56580371ee4ba38c4, + 0x23f91ef1b8182e80c8a0f54c3a35ad51cb9a3bb61b07b3e34386f16f7f4b32bd, + 0x16c390b3fdf09c6c42e50b66557532cc5998cb5a8c15446d31813e7b70607ec5, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x1976d21aee74f79c60d44e46029a5b04fc03ebfb9bdb09a0b5dbb89f677cd296, + 0x56e7cdc08bff8d8bc12dc72af3c84858dde68919cd991bdf513656eb0a0cfb2, + 0x22b7992d7c0ed349aab7531de2f12da4fdcf961215ba06f2b7577f5d42bfa85e, + 0x10f97fcc757a0d6d0d4e2d585ea5968b3faba9d6458d16bd366d081ab65ae95a, + 0x21bc046c3d727baf6e65b568653a398aeed8c95b73567feca3884a051ac001a2, + 0xe757fd0b77219a771723e071c9896062eedbb3da05cda25d39ead3cdf738491, + 0x1ed536c497ff36f612f326f3d03e97d30abf91605ba686af36ea04c19cce4f4a, + 0x2491340ecfed3f98ed6fd566034240e64a08e5a39a468c78b31e4734a679bd67, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x144b73c6f361a4c232674a08616b36c33f7bd667dcaeec35530a2e8fcb66103f, + 0xb244143540a248840ba5fa161cbfb2fb2dab97332073042cbf8a932144d27b, + 0xb5bedd8122560caf5a9dbd69f82f7439543bbad397d7cfb4ef7782f64ea4e12, + 0x1386c7e88c5c0bf880b28eb2735e221c2a88e7f871ca5d720c99b4287c528a67, + 0x277164cdc5187613b0a6d6450b56cabfc828f20dd7d07611edccbfc3d381c9ba, + 0x16bc97ee1ac4b1cea8f96e731dfa610212aec4a193015b94b0f2a1657d41f13, + 0xb341e4361f31734af9951c20a6aace08a3dc80f57379add9693b56b047b3480, + 0x263a060ba49fe4862df997994261e665c0406642c669c32dee4ae7a153fe1dbf, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0xdf811b70cab32c0ad0aacb576fd95b23424d3686d79e36feeff21d1aa047eb8, + 0xafae979e41c0cf7d662b4cf09e93dca70c0945c6759c4f8d2c935a6084eced, + 0x21ae12f1dbb152c33213efe9cdb6044574b3df8236be92341131435152115e5f, + 0x272fd8955a7524a09f77c28ce89d58caf7d883f9e4503ad6a37c0eab6bcbe468, + 0x3712cabfab0f6f3d23ac7beb815226883f409d60d798242c6d5e9dae8178fa6, + 0x15bc41d746b14885ba93dc7d00594ea2f174b3b3dbc1acd774335405c18b154f, + 0x9dded6d75c33754be1c1ebd2dbed077c1f1cb80938f0798bb2e25b054a52962, + 0x1d9fd7f273e141e48d7ae825a6d7758e351d80c4ed50139a659d52edff60d227, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0xca2cbfed626671d6e0f2e3d1b6b2ebb5e9048c2f1273223c34fe599429e1f2, + 0x1e9bb2efac004014858166710da5d764ab36b80e4e97500d784fe5cc2326fca1, + 0x23f8af81b77d2f06d566eb0d9096c4b267f498f92bac69d622dbed85bc8a8ada, + 0x11546811642965c71b3865d830809b7f402e02d1980c3219c4bbe48e8bd37811, + 0x2b872c434320ac521ac1e14867c05d88692de6ee063f402c28cba02adeaf9c51, + 0x1f80e8d09a04ffb20613cd83ea35fc1593f9a5d8db6c846d80dca53cd4ba5a94, + 0x117c4e17071565b51a2b97908f375ca0194dd595e9e873e8c0a158b59684ac70, + 0x14da94b9be3adb3c5f7cd04dd5c58f63e74245d5a1e6fce5de3d093d476f08a4, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x2ac96264771dd5b1762078d5132db23febb0d2edb19c7b24848d4b654e9ce670, + 0x5a23e8be5fe8e01b11d0c7a1dc85c909602604b15d620c7a51e2b017dd63830, + 0x172623676d3d38b2c68ba2b30c12c5818d874d83a98478cbec0b1d27f5dd7ece, + 0xb632ee1e8730d509691580805b890371ca2d51bce083faed1615a845481de7b, + 0x2a220ef566e4d54373e1a095231c10905a2f5e72edd2b6259b46ea45749203ce, + 0x2ebf4340ee05460d8298d52260b4ebae389357bd857cb638c41b2708cc333dc8, + 0x27e873b1750916366d2e7906ffe4f42e6dd7545bf534adc73a02b7410f7f8275, + 0x1ee70cb51ad6da4513ce42ff200e46dfa39992a90447f1004765711f3f5ad52e, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x1021282efc84669e4a98956e30ad0043c6c19dfeb98d6d14bf027bcfa555f8af, + 0x1f1c2e424bdeadd277162d70faeb398d661225414a975a59be613e47274b73c3, + 0x1a71e415abc5ccd5bf268130070e89b1e61981cd54f6e5864b8cc4e1d50bb21b, + 0x29799820e28bb9c0a7bd0a2c6d6105e5c91f8f88b2823da7c57825067214dbb6, + 0x17377cb0195b95b473606c81a6bd5c807b22870afa6cb230a1048e9515e31db, + 0x2f73cf9f22e0431d5e7bbd907ebeb8553b4117ff1fc50d09fc7b75935ef41251, + 0x19cd57e77a99328260bd31fb993e7bb3fd27fdc21b2187fe3a4bac0ad664719c, + 0xd5ff1b6b5f33d6d568d9197d0df40d07abede20ae3a94a0292c01c304012713, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x26c7615e04be2355af0773fc0e025f86baab5f59d834ba005e099d95331d61b0, + 0x170ea6732c6d1b2ce3279f2d4990926fb8d279e4864d966ce6ee6c319739c2f5, + 0x2f870269a506f351fb0b9a9d677bad1bbc5e6ab40ff0afc1772f02ba395fdc8c, + 0x11986790a1cc239c92bd4b8d8a1b9baa76e1e49f847f16ede5f6398aa83e97c2, + 0x2510c2e5a39cd6c243ff590621941b221d2a2c5a79ed6e5bb90eb1008219239f, + 0x1ba5c05a828609b93a7e151338699af0b8b0aa96d3d5cc9e7d3785333fa03dcd, + 0x8648c03bd03b5f4dc3868ac1c47363d90010b9cb19933554fc7586b97b5fbda, + 0x69d0c72c5880618f66ad58d65f09e5fc488697c71d92135be291f55d496cb7, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x91acb34aa0d03afd0ea47c1d56965a9051b05eebff9af71e07c4554184f462a, + 0x2b3f75e8ca7118776d9676fe058565eb99b6e99bd23505a8fefc927e17cf5336, + 0x16d9ae82c0073fe1dcf35384c0dce87494b2400f9027ce1e64ee440a439fcbaa, + 0x2a11becd9333eb48f3027ad8f3c24fa1a0ea671a1020278ad84c863c322e8057, + 0xd569be295d5e44ccffd9d3ba84aaf6a0c178e8639689aa6c57214f00a6a9d90, + 0xa66025e45040fd45eb136eccc63e2d7fd237aae9b62e2330aaaa0bb44dbef48, + 0x2cda68234c7e22d8fd725d952d3c529b6997b68dc02065f6a047b6cabdd29e42, + 0x1f9ab3e8029afc72f56af02ced5a6b145ebc81444ed12e82c7ea547e9ad23650, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x18a2e32bb69277e0f5e82c2a60a008b3db5caf3c53a669215c0b3493b73c7138, + 0x224c4f2e98b4fa10d4ddc83f26ada461e5b4f412f94a1eb153be707470746fbf, + 0x1b2a8787e954d981add1b123a6f6c100a609e8135c0781ac9a1e7e326c4b0f4e, + 0x2da288c34f32d86d5dfc0b2dc9891091d396d36de9f70589b7beee769a058622, + 0x2e24d351b0d0e94f3e0f83eb60f2d476b8b64dcb47674290e87b27eda7f20180, + 0x14af016f9da2f982e82aec1ff6ee809445db2c6d85382f959508a31830dce9d7, + 0x91aeac9bde9ce64a54cbad523032180c2135b51ec4547ebcda08824bc9cdf9e, + 0xcaa07eac62d9f07c17f63f749b7047eaa1adda97f5716d76f23affd6d845dd3, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x554f06e31b164d9d7ada3e01c4bbf452fdccac121ca787b08ad50dd2928ed42, + 0xbf8f8d7702b1e8830bf126dc420158a624359067a0f6385068390b01d176601, + 0x1604d181baf488dce4f99bf63c065ed934ee29f0649af4dcc9ac2a2887e8690c, + 0xac951e2944f7532d4ddce72d31c8e91c0795cdfab82df338f172dd9bffdae43, + 0x24d53d9f665348c12bdc3425c2b83e24fbea3b66b0c9d119146ed5d5a1d1e9f3, + 0x1ee01a89a7ebc6b8e93f2ac2e60b9909e3e3d855852e0e113a72a118f56e2da3, + 0x2b78c3171a3c8ec6231bb7c208e5b7c2c90a85956a7f2a1f763cb6c883059938, + 0x7ca1e306d90787461696fc7e4a3938712312494329be76c8e2b402cc0d617e1, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x1febc25f88aab92179ac3cefeea663f51562f6fc631bb236c04f5ef85b464784, + 0x1b1b065eb60dbd39a34da94414fdfa4415933a6bdba5c2de470ad8ccef1b28fd, + 0x60fcebd24cc08503ac4f80c0ffb87d0898f34bdce41420e84d941b5f7d352a, + 0x2a7b16d282447357a66d83fc5aafab7d3edbcb3f01105f193954c5ed496ae165, + 0xac39f59e76b9e296ef53921ae0436ab01217493f948bf6eca12b11ce46678b5, + 0x90b38aaae1df1873784a8966f1f62b68bbd93d34b0f4c637e208f9aeaedfc26, + 0x1ba601baf813cb2d40ed5674747b9e3d5760143501e0f21e31a7dd44b7135eb8, + 0x17695ec6204f10059ae5ca72c1332bc882cb7b4e161accd1ba9ef760b7365d5d, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0xab5930a06bb6b9a78e664dc5308da0b64d1e09e6c69fa583bc737245c5a469, + 0x16ab9a5de48bf089fba600dc70d2790ce0e8f79c1430566802f97fee43bc4e2b, + 0x75df7d5cdb7ccc175462dfad73927bf5a5f465e15ad267930c5ec846f42ae5e, + 0x23e4a7be74d0f0930279585aeaa432b5c28a4a2b21e3990aa45b5092f08d48ed, + 0x298795a8af97b8b3d378279e60b276b95227e66d74e2dc66cffa1c495af98c25, + 0x133d1455b6ea278f4acd91c65906bf75f2c90e41cdbefc2721b1e96adc5eeda7, + 0x24b722af1967cddac6a1745b71aca7bac72d436ed464e2b8ce55aa2ad5ff3502, + 0x276cb6e59cf4a06ff6775a537a4b04c6b42780c9c98a51ff634804b23acfac2b, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x1044b0ed6b39096c0ff4d292c18632c909d1519149139b1cd192de01485dce3e, + 0x2dc918abffffceeb34cb17a8cb532f889d7dea98e9ad2686ef8e30936ecdb03a, + 0x2a5030937ec5690d090ad8b3d897541ecd187d2ee126fac5be6a280fbd4aa465, + 0x16961c105f85925010e0fdd445ee840dbd3370aab933ccfcb6e4b24a8826037, + 0x17262da0f8e41b6c42707dfbabec1d9f79ecdfdd25a32c2a640d3c5a4a3e8770, + 0x59935903a135cffc7c5e8cb06de7a0adbc6fe4f66b07a74172eb65951c6a345, + 0x1ea2228bc5f09dadfabf025e3d19db3cca4e448e60f2973605d2559a27b3bff8, + 0x1e35c4737f19de2debd3760ddc81e1f5857a01c42c86f4e264ba323f4165d5ed, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x5958875cfb17091058a7e29cbfe20d0d242ecdfbd3635279cd1e0c3a1144dd8, + 0x19fd165b2741329dc18d2a5b03d7b58eb3dcdf2c2b0870731a924387139033dd, + 0x11cea375386801203c61577504cdc68493716d023d116356def9ad9825be5887, + 0x2e911408231ad83ab40e44e28ee0b017a82f7e080a0d4bc1b42c52e9205ed13a, + 0x9d3f08c1d2cd4de393b703a7dd94df0540c91b59b288df6c1ad8ba0e51f179a, + 0xd8bac92c12807a3fb4b20ec11e083a88b953070c08c1ae9be28c80cddb29a50, + 0x22829b774491c0e3add8e7d2de8096cb55a1009ae9ce983b80c14972bc68b84e, + 0x2aec91a87a1731f6b2f534955aef3d09ca7e2ee2dbdb5e9a0d15db232557c621, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x281ec503552e6778fbafd7270951cfef153fcfeca0517410e495c62b81655f9e, + 0x98a3183f2ee18973943856c28e0dceb4392af147ca8b528ebee97577178bcf1, + 0x794a78e51b51af07808b643ed37bad31e6d6c68e5ef3171dcd06de598c6c29e, + 0x214a19348cd7cc8b1f985287e637e7987a3bedfa233f98dae9774daaea42fce9, + 0x130acc584954a9048597bda6395bd25ba02fce56102928cea7d5a6f520683ca4, + 0x1d09e1227434a4bcf72d8e91f5419ffd6da212a1d1ccb2a51b03e80aa258243, + 0x127397f2b156ba00d83847f03dd242007faf326271d0e2cd4f6dc84c961b19a6, + 0x971a3d373d35db8f181e0d7b26c33cff17e533e8f560d844694f853e7197e47, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x241c8bcc463ac96e3c1cc240ce83c44edcf9c781e258a2dad09d1976d9dc6dd6, + 0x1a0b489baf0a182599f458897aa340e57986dcde7bfd34738851092a75ae6e0e, + 0x102c886ce6381276fe52d15c51dbd571e94904a8ec4d4445d457d596442e443e, + 0x289f8a46d6792691caac00cd43dde74940f122c0e5ac202588349c2eee473f6b, + 0x2ed1721123242c33f23f809f6e431511594c10b0533afde3304ba62afc55f5ec, + 0xc730a9beb7b64f090a39929af4901900e772b0f817098adace287cc20dd9e84, + 0x480eb2f48521f46f5049f8d9d682d6f4060ff6c4190b2a22c40c27d0754b912, + 0x221d30bbccbb39bc23ffe2c8571a8cd1763cd48de6dfe21d7d8f2805db1e5066, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x22eff0bad54cf4f8fda9e07bfdae36713527756cff255aa481b730bd286cc90, + 0x220c6f4c23ec9272eafb522055494a1af4de6fe7456b39c5db851e1299b7a86e, + 0x18d66b43fd01a9cc88dd14b1b5d6c0d23b29ac28775ff60d3ccf36039de0963a, + 0x1f62901537c1c56f671fabbb4fc31fa743f3236c26f9f5c98ecbf332eda817df, + 0x130beece629451200a3de22eab4c45bb592aad667f9fc6729842971d4a802fcc, + 0x24411acb2c9c481c59adc41bc54fdb0fac658ed6e0b3636cdadfd12c386f8c98, + 0x2370059923938a3552819155a8b3816fb90cbde45871f6c122c190a27e7fdc43, + 0x217ccb823582bf7edbf4a6a64692e37928f2b02d79b43775abf304500dd2da46, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0xe2be5d3f9ee73557a1c421fe42cb29bdf8f4a58679a61496bf8a5a4f9bba3be, + 0x27639d7e461732f3baeb172103de2bc4a26708623919783fe54774153bdb59bf, + 0x159c005b660c7fb3551cbf624aadcec047ce72625673c866c5fb289f8c865fff, + 0x130d38734b549e833b50c550a90580c53248bb96731c0921ad6373316dfdaa8c, + 0x13ee4afd14334602b6791a7b8f49c4f4979d485b8d1b1119cb4a2a7c31a74f39, + 0x2d2647b74c63579e81a6270afc73e636e588996745ac0499dbeb6a7cf80a889e, + 0x1b884086fa3c4173be0fd5cb1c866c87e0f9ae4c3d9f1e3df630cb4c2fa59af5, + 0x2289328b5db5b2b2d00e76ff78815696e77eb19acdcb6c84279e65fcce29d15d, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0xbbd293300c70f612c8f5b7bcc6c4106246d2f713df02774a29742c31efeb4ae, + 0x278e2893fbb5d590fe623652e50086d58ab18d3015a59d6a61602b409252ec2b, + 0x2fcc41f73df0c835b0b514cbdd469af1e2b494f05269d15a6343af34668b18c9, + 0x378097f57525674b961d42a2f57a937c1fecaba4c673bdce345050d981b8fe0, + 0x15a6727e6f181a5da795ce173f1889e07f12892e13f889c4f8f6c71725ab9f62, + 0x1edc3a58673d364ba5906c3b39ff7f654c5d42f4ff94e6e75d2c500842846477, + 0x1aeddbe743c87ec10fe447a5d08ab5c73836eb214ef95a08ce91131b8e1a7f8, + 0x286e544456f114ce609d6b805b31064ab65482585699c91b9b3e83a75ca386b3, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x1477e88daf9348ea5f95cb08426f4285c654a897a2c4895333052fe2cdba34cb, + 0xc9918bbd089bc26c937ae2e0a92a1d8c87cf4480b055e43831a5e6a3acbe5b5, + 0x283c24f7bedf789f31465682347ff86b4c0fbb7f9aacbe5630021b41532f7931, + 0xb1e5f0ca68bafaf026438a4682a55c1df5d387c4c5f3e111ead3163eb5b2754, + 0x2d9da1df21f14ce401ff84b99fba07311a9da3cd7efc200695ab55b1233b9043, + 0xbb61e50ddc0821f0c03b3bed9476f580a02157b6a69a17f2afb0eff5f1e2a37, + 0x21dc1358f62ff3dc24cfc896fdfbae88b0074323dfc7b36d680edba89c470e4b, + 0xdc75868b6f7e6ec9c26221637eb789b9e4c2b892ce81b527c7da05627ec2dc8, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x8606e28acd8b2ee4c23a757886d7e99e407d177a58fb31b410ead7fbe1ef272, + 0x2f70d379513ce458231a8ee6b3029bcbbb4860ef48c104ddcffe65603d81592d, + 0x15315ba38b9e4c7a64a0844985e7b45db39eaec4c63b490cecfb19f02e102669, + 0x2a1529e4b1ca0cee97cde58af1536c4823f7e558bdc13f774e4ef3ec8454675b, + 0x2a70b9f1d4bbccdbc03e17c1d1dcdb02052903dc6609ea6969f661b2eb74c839, + 0x2f69a7198e1fbcc7dea43265306a37ed55b91bff652ad69aa4fa8478970d401d, + 0xc3f050a6bf5af151981e55e3e1a29a13c3ffa4550bd2514f1afd6c5f721f830, + 0x2a20e3a4a0e57d92f97c9d6186c6c3ea7c5e55c20146259be2f78c2ccc2e3595 + ] ) } + // noir-fmt:ignore -pub fn x5_6_config() -> PoseidonConfig<408, 36> { +pub fn x5_6_config() -> PoseidonConfig<6, 108, 660> { config( 6, 8, 60, alpha(), - [9174141306060971809979631725764298697615039980311809306145004207410652431953,4847693924685156250211477469465516228032151306221739650606132660616428517315,19669833054057639609249840291533340493211768292967819468538893000195036768991,19800508893433268850924828171290876015556093796000695603651522426066333836892,8244699449852279148780456022144420353408196866113049322676048275081354214716,1563672068712965454176533719400672258364596155638916268717470967009721945171,12723223712027468580318230235559705540011996847167975439677647504573149248849,19944398841194165937952509356635863229327574447452745793253427406349161295763,21218058308392585368594275702746106483411305671883946244077923955757637296177,18442884961885927579732373746933397748806426938144021013884176466434407012116,11138408360119814115926439449668526422561003790198269766757675305576549475808,12724564576884231109847024566806896391934587839830522481308995309797961575379,4897733190252075532660075013731462724561461746919488679609618967302541674417,4797748331306263412471031924618974997396620231469532262170060449304337691527,8626839560132907403537141283531395025838110825355541158539075100658769738351,6096293906324574249636975851522292408228519044739444932687579741964974917617,2351617695830568421216396081605990689071283678701192113347036659596049514149,3045682390398203085155257535118136303069379656645406266260961816947178911890,6935829264874515341379952008241845470659188886156484974987865751370715745075,19847439266968955911971997829840067368072860877451092633069920565944933744280,12795097343831149148337906863235678514689648096503928066579129201713661539889,10424580232112390318877053133877999442988769389050776486274146627765228950235,11651452649618223740363812212607761589812354035139843126315028745587570714609,21307929358023177131550002602820591970791247513576735567457471459920519084552,2579908580162153663820021562014873149811195641589016321720930006635393981680,8198198178555784054784079137247244121807775986273563786249987394640289859893,17176088986876377315956611075288620878117708836881362200541916957398026761276,671389874397910339333118510595007038137908096657753354622355890021074216004,19161949137729278558310070194809106779119877882343914445178348849980058405327,10827554013954037091657804154642286174226562252063767377995268439458401752538,11693672899474469123468133710607776304784343543318650064064636202512816205843,7026547767612627656560992117440221331093280829523426249915938274837157551621,14422968137896343032446633683271253661000603582016449215470992885331170459671,7685352543184863430081115767111935982586458632527708735083385591291346555502,14089009391529192464370954954330128327830078875414722902347666490457756695535,8424161061743752192085022963953944100289245618074575727145394775891645849043,9809236779073852557054640507912802523501426410996355424610807253990040160483,14100245203768962710288059230665566265892855964739454261791429988929622355986,7775683622333704945225255741567928967674629526812606133980425422182282014012,8739247215686497264451630351996892836638898510934389758205488381695687859658,9431876969679115468275053745264413939426444105271849398322497961102606290132,257914055321743732506701382989022126153391940932933566664491918941925247878,21801414068435960590201256257290267142214176965736081788536576642934903066059,9465495933537134443327560834432669768951376466867005153580146079082722525723,7862366214258716333873810314803222267215825847232397599183717032713290878315,10701164906390193792620967030790214270231326273599373762943959252633779929633,11951628827727068395937910010248864431667047516686609553745879936868276916066,14268744039571470490378560085356767818183790841094115879980723591887874138419,14468215915818797151199796266933432577607248341385185700017147731054148927023,1523824033338639123415809477892820349580561577160869448927791050266158538520,13559991428776910947424645696251487328999214391124402586267086012691140984198,18151203063828433535061866995346135260543721730169485344610433976436663085882,13436242600153492361692256644258899977135098134175123174795293078081801647137,9384556671429507406657070680351030238568956203341356106463890924933167416522,20321079285577981781556986944841048777999006905303986053275199507771332527205,13510502130738135726695195328780836716597947131948116750163533622597187969844,20903049289119144354363108865308751668897757360882852151457514926552553533040,5611953645512225417723205546533389174830971368309601830751921473015551069534,8816886019615642422040038431962872654062471314244185285424018745071289038220,16751828354835345790163611999302863949792305206769993810746019449909446216365,10421654749141018171116296259626916395875529220250947127973888230084671091757,6065225315766552671037285757918350882361743810888619479819895087632281975681,5737755346739850738724717271213687543479332312420206954339242459110768587128,14770522272891919220644639305274656491731294860310497013287297810648680944682,2777394791070450473479179489594969793054480209411136328689318984981401732197,10039559932930709555975364107098145624058027439566384376771787183526929807647,20757756003754261934858081777796652436155530474748550156383127600004580439167,13253166894715452480712170898662712132411702335275401581167208877688374856806,2037004052447343668129085129987646907388123739343356363273464870501805506884,21829471491172175426560705585746893969222010633542962882847909490991398830669,5130395545419191392223692116621486075405299333195732914002649716762739787586,20333821730990393095934147177227294218344864602777744425090741435432040213391,13629653802252084129446975515814037702423511189484562534040643669977716900228,18489091892360842692678715136565494502607711254719045543684163289077857041829,21380328601365035012832876315565064374684993115210423862017233170195286906080,2280052193465635727584791148501382679094142036232980037838088033232747821762,21415541711468815972744677841317235994302058341802530962394281077076174148777,17146992672828650459975820445250769505470616910596779130798889014378635881076,21676475584514120109058208398560066698690773910598518925936412952356431597439,18337052978997482578725645166749278142628133291693686105612531426715865276143,14864089429815580405957698645045711801464462794754089671996837547347950054532,10834607317840698149140890207826430113987295440254355899459691878793978994131,1157143498448645320415276909137008396665083714591338741616893578930275511205,5027542104048754930085470328670427788489455916338375169351586496298129661248,1922685817237874482932428650501872692326329693528175054457715565489676406535,3071473720617798005831658342971536643616129392641449174655528578463370685788,21091078808046042460442535848913779439792606439995062001271357804782672390627,19773167374024045118471391738750949555178717045037157435777574972149053404157,6418695831178793575992210834992785624340084513619644969535805236049937971859,6317875495482489567338519005308431806047606843913867465201005132273298011425,18001249545956637376455848019549801116909661454019565655561439372098476761813,15530167556609139699164228289904946047951254183080358784988008899829027775935,8702757129830652230304011519426558036441096750485189115358314568895250616455,6369986882953061252605652398893489899416599935424066958291402945530517772170,6842894437627604179732847187262933342846269043996061072487488027804029200046,20951621154051947571647917571547811655800779287153833018533872651413529893817,1219277535080749134805291725937516331501172121638812333911793209536894469364,11704605822590166851511022757496386950530399074796545751042566537118336773236,5983427701962592508775640503988144495847156070437130549832329402380170245893,20169091361583397776908351163571343158517532527313940288212943504015977979442,3347733015762117176159731683196584632702931062411889821726902331981723958255,16217509027282489850987935065936382820558307489954122630844029918951230268972,10781269196927764524006466217779648732772805761839205677745819812868343369087,10568911823766972365218731330080733630028238366288098114239172953421915095075,5568774544682750792074131352530555554984876659733959079036284517928264996437,17854353469028651373397049175548228061144941710027186166132671198740388767529,6573034112757039329551886086829829282007989555105157401271097204633906940776,14069627287078359391137554212536883450595451640858724555679971658981340584258,21119713641590541511025673864154852875977162278614553796484277752677323191505,12802116677235410441672624559825044917295689876859311183079161588690810005363,16037054471696658545113065872215787085337497333273419984439267709950724531124,11698654309680908244303850432833183602706804558317993513795996394673734185716,15147889780127043019188099948246961619198549928908180192590946633702778981583,3657342516407201801006680507925024451922115018712017224805778401726428603983,19776786467141868744713630352693556348834540992018636838044610844396164981103,7980994848490005281733955776875257044050741738176865989521982608944874160873,12415191330803073018395217955802011585094769098717180100014182475381600382452,9300986814650530426668152137665814177758578011365736727321578452726378799933,4412208980274764197258090802604347599791567698589180187154608728755887977460,2582317668924231956058541757507620542434237159213236485179804217989764223164,19860814395849792324574773787600734118308975251437485131415273418632757301303,2765909129639570206766170018363951893338720647679193401532780051354569922989,5402210382809272147099442645489124829067576777592680891367494969197685281513,21011104174655621871977821285307554463403659856745964274018020456838460357574,7018364707286303918877589672878574811337524823085078243421192184715151775983,136380103284908296988715215087018020601815024625535396780012012453684253071,15953315437474610448052466140270091879233956524793052736202793153707558909889,5912305909658884889781037379491781973092020933879206417274479331390062715252,21575635295587180789566592951559325743281772394055590203112195979769645712827,1541325805478255472079288730846072146731241030100908414806224735345400173350,17207219201921814683730773200330679841907450967511507012179337438654141678023,18266907794578843029196926509122804272900478710738403531664855427655744759655,1204224895193276222782842236712348692319665277014183965830735736728887994581,4023246588034712778784328407820569751989619386134504404739514704773521558127,9064437981037864995763386367268294611921404895425171966596873454090899491243,18733802217274421976148972926716884457128521840010001893311936746027998476583,684088380644531080099595788833220377905013807951051638705160997709156627273,11994830816367980341637110785269531718699655485484715851375754143223090344544,1831724566362300629700078416489434571462666430381219293205871349415506993475,476710745682537342427691635955087951551678644045621275039835625280220347951,3586272766499559446129476613035465343616602918105042144185864609818186807939,21220348736799044560439132291243370111879983677197111626309132298278891334631,13683795063599185801186093771702503913590598475095473714851383723199050309401,16118007386401646906425171859166434660243697555307927508268622819509657450614,20930641024767526790605168032291665313905337763598128831404465184891980632233,8098646212401100552303711812039666794078834386731698810205195111722330322418,11585783577173465460243373201831086724911159484415020913089605532852648999143,6939053275662244505087635417541857793206828446247848992283188764105131966721,12798043540382494855660472922674138947867597503468216532170157050160462426199,20713389801600667412553956346192236970217099413304167366340548074880917096741,8708207547232102069057776099666995672015399188924281674772351753887161579745,16016293152251662056020528248861487281148011452459422778601663166015837379163,14324897997637439510797191208789711173129460994362368408063402682894248793270,5652996184880208428967511742390474289004021508049280419259474250332590598159,9877106633097964013050071703002221796318046172981334418310092241450453368579,5385816971548914185604875069230499528103133871233951354186676373318036241822,8683091293306949708478955451280670950858818602696102489349595054818146782362,16854975838650963077652189417311897888852709425835763860743171659164792100482,2485160816649177905834265823672532710299580013309324666453183278408904845122,13571692148185502188613896013359942531817915076247598483272449919094247957149,11899399615412173136098732970606292047945698835588882297719609812145308198009,16827672312681684936590464376780346837611857292837989006980972390576065571472,15588237822592586948064701827497915157359094833395277985658706133691498343174,18356642512438827417103800170157877145465512961188328254773957819312191285168,21642368145757804795143182901389223409544979732781450480847315495418822041608,13104082060493963869934085622104709047787444250961437496674916673804812287386,1561532086277971111804773016487251313460788916643968126116038406859074212104,2718320602791009266532615731130512762296058687816604986701989820504700684864,6182683520717583142027400659687593712743548729948584058329789905227082638908,5757242145794370726637363237313640925174531077560764545993554185332488520899,13688467192244237790806289073845563960119021610896694359815485764764608925981,12528461541936459922472167643986446262977222390263675720335825628163511159437,4897268894447399415795897967133432014527122426051771866816059363418177665482,764332419588242767884018802335623760055144509861323437945071732931233600264,11755468878196093893190753985692714003062307843033761257593209352165323938879,6006022813561851182403581780143813226749481175437001910923100661321563995672,13901542382190510449243772206670622017835690746895066410475076631498053123535,17648853891656481911225897080296737974064729032668806126284849597245044343224,15106333841965710929952896897521673254279668876709612770907537801609875568099,20899315415025260484895459315726322363345188136910564549344894025053466430346,1409310408943258102775009950750654615881913956151269414096059752250092035807,3899088673345731523976816322438172722785832982334214339521575164464706226294,21406686765584824639201351330529610299177537976609066339927938099572420696135,9121591670793901722224770893633585291275002987585289305307167711146944200595,10711764678410479049841945177317023555168593838022414378232020467195337241279,6599257303974597452501135281719536074294806740553273627128065549267140155175,2142616913275380526921597026822750992917222975992774063376747381991404337593,16361086527663411948363284957489078505159658832010445114438602510508720771278,17122647864721668762640781848678028227021534122268561738445496382823789619088,21708018685042482318786273055293241752114005312590172460099480713746031274624,8303630654111760473056607545365338851734309857718959193970615705292826806179,3658686547507488906491014260011151850549759409901579684176172268581462329020,7720024124908065424512743488999250878143598904717873371853608249805302871508,8805244918657836956533473437651380347005779399042661429698187314657501156241,6303681354794120075893215838935586592706844702088252970663343726024171795351,21512507181643408509426104627003618425209526633080701556628608990726677651135,11835373417333287523801757951049679177935522717858158305516568595764125190183,13059698839045014411602727811400239840163533672024084777768305507840091151855,17635240655824524168378284083397931667938326555447077097306236826752492079430,3374412791113107178205006579112630099131939030015047870738873452427211677886,649711083340882271985565833699379436167716866997851102439037906608755280128,20002805138014565226408902156524463368767807620908543995020210484077706418135,11071355197960433041624284534649121637702414580710232237233568479006159191217,1105441595020980635809093220782460032826849883993030969714432603468135735502,9652765957610682812348919340146799318537766051849796416434577860126024594091,19248299650856496267902926731608572596705132576830681367365128976226233392929,15285802367070100569572399512275861017714681455564415244982064571963339715277,19970416835730683993734843405673457882587154729456022607061085470691843864556,1017865638757684714433500504002748241987153668285974836527484933462490771227,17284848056169793253916338792235498052654877955690514601079806604278964099314,11718277105372928962350331838305733149270432706448484259807630484543527733952,6670793378364949883511003949124179112275066568088468958915163969545409700112,17088789393958965094855662340742013087397643056458490270185660553870734946796,1930788514812600942005320214284180860980345276633471423966020111188605196111,8844343159753729614645407314580317697758296041737296276765583948670245312842,16657939543606018325703787748629433167511611178952563626096990460124133990109,15333343644239485619497914931918504163396626751908652058758135581206765801100,16533875915742793452819179569144271760125646811168930162441077117553849625884,19679534317472082858641184998487299940737032844519038845860980362664393659234,16385719932525604857740698205965045007053424961009717093945644387917936681719,14490521084213123170781774542655088188106794646066074998587858678154251198444,6386781978322405984893078797365492485297499058328348606653460996474947075858,17508047533433736707046937662428611868296556965172642086594091783148965906980,14904597000414815084666285064575232635645852687797347860862157463159487771060,14979972442969995336727018758631782107138089738395941038626891064816880204567,5299243186271864957800928637599294208954109271450189950375274196644046222516,16189884555052883188473617525411302750109401983487269295700675997730645714379,1645560170870292006287241616671417605853047420339675073261660626733726665673,17866745974872498136933906591373095763114066893081150553715211393380040095383,5744849574386643500716045532645657520001448510343827372577217716983339773799,14021966200238971589811034967347517039341058556783068950884921208853167419283,1201178089866013320759085637098781870734315826415474628546655403142858044361,5875644793836087035760988842421852197052681650818034527831700615895391179258,10875065950479466897559006840696567433921014267247530366235539292597441428702,2221662399199449388725697795500999209427453463134383582414172135385907744785,9758513532658579204941116584445291102215928928145103503086996542188799521709,20879593323317766577775570558015407573466986714590017262168011643343469361329,17225846522404915080676699509636264825833159640824918876741681229188434930856,15189442986691997434021855855358620506645387296294217783597931695143376252483,15973617135551858849206811241799666696907820418171736027820254766840973764431,11888113439449420418408437784450952639345990804839507528208325036625374967083,12365920814385241227394825974928370916184942218042429533600397623369545597697,11966175169612449906889690852332416255478894176917636726028104087408060623141,11163554022908212145274813635928762748847331295589087669583554722521180712379,15273476004030808005186443499782264987539818978741159793745891769358221570633,2013969196885866182480519514425192091338553670034650196068995589691938248955,5008975446746271526106846692137145404766553748264648461545948417006052208130,3926749194225734582453671614337621250954608160208554883789519551411469033731,1635544156808471185144068767649088695307748439189898784051754434524720057896,17144944482517962143604430553750908864860079758005337246916094084534304051981,13823503533305241872793740090687668844401004819859520464168798913603662683770,16335911272023134851779534303717879370955813837529588982953758998930285394340,14467284210444150699969889681308566002886261365990840091849371665183151060295,10578205764525658336257882813734672799527733392763965031628376897794294290414,18771425328697137255453620743509164311086906349726510394566012237817674245865,21804626093983212038528370352039806004465345685985435415809095637323683466452,12056805308954301132385034564357716323176447186932453788072119595595483786736,14307195735327805282612857510308008767450554777122724855715789120735513378827,6848201070063637295416045855906784325422580350462489495889308309540335269587,631364713487758647973016689203003205602593076699875191323345338325349259049,16214655556434201961140525501007839859074077768660052713461045928979956365067,20940788212183642266181811368870506130164462254923655617893660245551698033523,8257440848494309435270838240795567828478627302119374684511017376568090372435,13701089242130867705897643891164147923878521147124165292045879194108024940909,6895272953337895406509859406973110417619874994579965619097329249292199573333,530437169778092455975584310016745919549274205817234464915791595041990209639,9008612822403008353420189298381046023002474279157557733428254452507266389025,14863423501786052071018008300345884780479084379412157784789951872243409629758,20091026239041315645045502002997446404106877721183777765607724358538559881231,11103877261161399045807234470901399725912406134008627937945079980590775715243,21529163495181909351665093277427712610965764606448489357319207727176092439794,19540446772694448035410067193880900774391072899517686330271100773183944540294,17549510450820803306426739851959754252204444648959723652883552677325100583689,12252518814610348662318155253547558779974557529822012236107550517806390105567,8058115132085119666951861652409945532276905989404523986413207631657437321956,15916100116790431839835734530362130437167135501074855072245598938219364570910,14256533476494466694764843270015662315303617568641801280831873052211753536970,17865471381417606502707639037418669122823481329049436020149405646709537112534,14015711483636570179335132940981982618090553643653746531174110949872682031017,6075776171664976866533080327142904134938121198707020111533599997509054627652,6357981809351565370498807027309828058036389418343890944791766504532174516243,15145296985037303761634018005118672316118004891352906450983918852209191841446,2473672396516437070485250176897956191104549656554290725379242542480862701754,11059085933391482002269653121188853142706883316754376424538662772943167665341,14804069155713123448375113552227724310276294677318593116834685772120057819258,10146378656966122923223443263705119557842694560695035707977826044606938090895,21828309590915152213768434346306434851424116996828875020020066586363340244814,15568879616082229996551157805731419126872501425454775741945679993142071548779,17504079509060638501918729619244098692140123800571022969294759717277257664716,2998311560047298465700351970612785742605093777116697796464434026101441410385,20229972737818088327107446854254558628041027965197447598027135778783710740259,14884874200763033520375899992902136897590350894844904733314191389520252900641,9619409751736964504139815024141276029474791187139050183491749032619248817404,11534029087676783672833531415041588991838838078174102967049055562568798961925,17106297093375816944137015955705541133308466659538554159312635106186252148471,21676736161168806529097919794022110433487869702564846859065695507460463414524,12596447704589377083704857810305080195761099125652005594925931498073219198049,310943124066162607352831846280730445558498286205117614171844835745706684432,16013029710570597613246104892930389004941711962070683476555063566372534206859,14282564976066063966062366540992448474634085812789771416509095817495183298269,20757241092771652500911491636894210910134068426068355089789205706892703219255,17084251309147907751212619949757520468224028014308500329099194408342072624132,14680350698112448759886861002622963534698534998651150537754386791270019720748,17739512731440543100681958009173086667000199263945053345384367808940651002571,8967486063900234709994801661246451094429250620940593387993430620369318619734,3906067814916986286272005884942051451306945488494283077675304366798199289520,2517004675157816404807349457307096161030587393097616279110332574293494030636,9995302877359286298434340810356550712107485295049220989690824504445305103587,12849909876017357260683411536833847986127911582040960825577300322066595609115,18074515800779889507358182860997188274134395074469953155084226981497567860114,6692811728183968363967959295970424292426462800383828091752006855360167264617,17859827663908740084792157440799065184931609649811664442236242315795442091367,12243409340804252499520308602187370739653046835019551522661290645230850934962,3009118420068966587115224335717185828292538080040896739662684632413054772046,15856202298588272962175258696610233941787471472716811521132004805327415486141,7549804594729480554341356998842376772514802673462970334329441043324983960866,6390806437030742378988258255983502109201709511321162596105974797942236431761,17370236522182003753669946647208335160124999930136364231371998757664000198520,2261672244214630177095236704932243497157963117166120717011661647779055001646,17325026196605130064689259977831126468940872193987407658419640959345091161632,3631641025220845885502691330008982895233731506600778684638817282531001457735,8656561399441987116927438675277763317789561532507396244334062468892541066084,4069166732330197412844703565599514109399373916243310212229125901351402003915,19808198732373520522982274785888742523226720967259539531129335924093928174880,8555796834031869022510134190573521699378201702450788201649007358450530423866,17759660636058865290579521740750449606781204755231964378855563896473545202303,1335826395218609619260020055566056869243760115287254209950063597653055872566,21596200365241795669701682696176077888309278223833581800772036945674858315765,12619752319673193899296833725747186284394167228468888029626464753793997178599,17420588547980145067421969830249755561311178399975476925894947008643385243007,10337481272389772505654575850886249605422739785111225132545740838911222864209,17928431631046752749930349099366498612885288622404560316665023363985966878427,3075798659324203306711977985120251896073145961913793478792728028765206521425,4639500613932181914847461422373341918892878975546430906324216810326467690534,15396322795715441250300995201889120935591602515487993982711884319616897970533,6391276937505284102735701938724106665734769352007891548547667448647832351929,6811373320779057384916660178551330838095673247430496448933336925226142036083,6590973140323934807800215988687710942074412987201753370126190631819398102173,19364648614154949386936259588484266535262135334799266379433252509193375956715,4702754284612371917466042550086249683933140314858807272591351280832918881874,1081036249074169248236179367049085684430282426446509768147097371368406374049,18548093223441988703029589168425055383154624592689171393242936199350770119589,11098999608073377668352846814752381891400020647878345005629685447730764310163,16001262992680194260590639872321865154716987495605624862471107193457192704714,21696229443869118415905915570780926763029898831113534481730746953640692230062,11716215712634983607563947056324900205144202447594949676250978337464771243867,1778908113733035314726603632369389424542091991692308812147944884836647395775,4019081204388123040098634987844274011285321286777408246805308194144238418480,3473266952388383063447927231564219811787341139731701190625605897592140631276,10457881304788072618845101933412333126160339089704353596608910674508961127232,14926101732700077295531234099443522459232814784151318061435025890154852791802,4036967072197259618286839959572768559469665646019907384624959071646231971399,12776716624632228928613396031717959431597335742467953143594165782617234803915,18894783424164609284436913400522166453255844750192864579927645453695213022195,6303809107919167113924303987533838414137996606980561570652539716097058487126,4729698693443803882717817492985796053343431875965792864932005291979914613160,1645790034267553926884568714540144778649055395816210525904813567839945991808,8138260225269705405100573121045873922755899939885385491610389913906979427176,680936760009829486282006800072001712155424246576949107399338687767760991887,17240357869291182045663678468827695873425113788704614245279840174870850373113,19100963939745621863641468371111320143895293700517367016077996431570157414340,16188989656090417148189510820963186890780289777598053654241741803194118100843,18027402882394597868782011288920739982398714370069420860949975937357531046151,17780529984916796963712255733293310230026423072958099290880849386941451922559,20004531511171838591303710792081846238092292916166965045929062171308088520097,13855731634251510230399834192704620793850325654395687428672253016405315169901,16872938837392115669581040432902657478544143723662502779821325505282093696739,2541555081244462826761076743762714962901590548271316707071685417008817634653,5136424039269088350807839181761422963254683236279333039713142751702136147963,19216238128964101420135465007632926445321991494181045543846024053552797518994,18868537488540023742258053821537824724371813776839672880900985865823137839953,18246710415801024039719497716350501105591286880983169809863166130543617917249,20608694004331631709610739723463009412162748201282986294016482926528443868949,11318113915971658853560322943565673154831611543653209084299774855226816037778,16240989418312335385576389959938922684406585560688799437547298624184839261343,16171299673760267132909753100946681733778389681324959987573199154235691694977,8036823955656422391918380552495301547890420665617977624790236120392727764522,20269862530534739231936251654244170650781428788816658397167110617927916774329,2368678892744667199202318323282128737449992006513656480477288092472671147090,4618078962163037429845764284139891171861860687111566735174912070413086829215,12695350627501306162901105159009497730633599768443844225981772758225613194238,16356283146491744069785034066388746989409816380917535719898337817088223419024,6407893217596287850421377738867081146106659458551198123106454022096864887316,18168868018352364136212098098453930600797374324006271488950341490483455519349,18352629174410142476418438008157117497168118524562206830585500251463010761689,4344169393287991961961456515301754172943022039566219343212376057129143739343,19424839806870716108478074501405697296961947409763509419111261767390677718987,5796037897847804302272999466834285170265203646465480652521088328457333766863,17402105801450379889120987010453669096275392789725153915905747267778100864362,15540989618743824352651126288511222263828123668208146479603617243655978402205,945810410725426921570254447269595873973858272778720657523509910503434094174,6962323734045776666289031609372270190654631739266635759799844631053633876675,11382945272742312954364642163371436855283161775445664525053938433459897196647,18940251871958826726849623572811640436342841713786099464305053400421580490631,13969540696178305383564753026163726563325318478290740131984853424331762285147,4841983966001277917879506889862519614692143906356361564304719688757862622407,8939049562492171082419559182596894186639203815268680721033389307282239000385,19265363396776097866041313346787101192508520582744521467413665478819721956884,337106861429123598189388456471513480497137213511877011021531147545809512194,251367482782327915297484770356856386307188967585026711663629212746150191478,19506616511267234489421548744907283107923549136620297132842391511025844759064,20633589633280372440758096707466273580151526293980868749421563697429194761212,18833062060138888612708634036427140134887774731041742144004707524569102994071,2927291160590267909596732410727396533948837350308818016906834558527125752899,7095572562193114209617459307511041110255341231707924363346373597653253806883,14274988113217913224290208839851596837329960221329537670822013510325939323091,9965830780560026128320556230399915681196410289456547935188741323403719404039,10333365845496980935202034863900757172839454015352626511769637076650624839070], - [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] + [0x1448614598e00f98e7ae7dea45fbd83bd968653ef8390cde2e86b706ad40c651, + 0xab7b291388e5c9e43c0dc1f591fb83ecdb65022e1b70af43b8a7b40c1dff7c3, + 0x2b7cbb217896f52c9a8c088e654af21e84cde754a3cef5b15c4d5466612d6adf, + 0x2bc6b0ddbe1d701b6570428bdc1ca1bf0da59ff3bbbb95fc2bc71c0c6e67a65c, + 0x123a55a31980384f3d20b2cecbc44ed60c38c11f7d20e9271efab9a905eefd3c, + 0x37501cc8c9dc819309a769f4df098e588b01858bc8eb7e279e2883be9fb8c53, + 0x15de231637a8ea3473c2499e1bee320c17c6a0a4f48a9b28ad1444d5351ddb36, + 0x1c9b1da36989206de9173b0ddfb539bdf07f89df055efc1cc489002da3f4b534, + 0x1f28ec9fdcb3854cb327e3e2fe3958550c37fd179198a41cf20a1a4c810654cb, + 0x2a0418e12dd26e796c091bc1fb1e50f8290263b3c80f68036e6593c2db2f83c6, + 0xdf6bc990dd688fabc1f8a5f8fa02a6a86f7a3a9ee452f5684d123eac1507890, + 0x24cd99ab301ee74e2382e238be9941d9876f320e9940481647fcbfbca7eb6a8c, + 0x1036eec6b3ab659a50c22ae3b357252e64641ce082e5c084bf61a4e61198ac85, + 0x21ece1030bf5ad5759f35ba96af936d82a64abe4f9bb2f50c28a488209286118, + 0x2e5d9059e62303d8d17fb509a60afdc4d8ee1d9137f8fff0d0c6e9135aaf66cb, + 0x2591d88c11580b75c4edf44dba6ba31c696f6789e22d3fa63bbaee71c6986857, + 0x1e647345c108005a7e2f870f01142223bb22ab44a03c7198852aaf6d765c3bdd, + 0x107e279d710e65358ef44f966e594d2ba04e3e15e37ca5aa5117adc71b441f09, + 0x173b298298adf659b3f695a02f51617ecca7e221f678375405f20405e377a44c, + 0x1228a0cd105946870acc7586969e7e3b3e8d4f5f46d450b14698202adb9ea1ce, + 0x778cb45d98c0ec68849bf203dc7b151840928cc9d7f40670bf7d48b3c661d68, + 0x72a7ff12706fa3b3400308feb33ef3ddeaeb9a5678bd4a17dff096fa99e9e64, + 0x2b0997b01165c2874503dc12fe77d6ab58a44c583b939c35d0805bb555cd09f3, + 0x80805129259af50e2e5f2d8efbde358132da1c19fcb7daf48985491c9d287b5, + 0x143e4e1f2af4def1b19038a0d6ac9606e33f40704799f0890b4aba0b2d6cb923, + 0x1c16b447df0a3026d5b9123abaf02d69076c59153052660df237b5221485da3d, + 0x2212763564a17c5b816703e5e52a7db0c5bfb668fe2e424cb251361426830b92, + 0x16dd30a48d96f76e9378f65bc341781e97cfb94af5a57091bf341342c0d7a6e, + 0xefae4a569514657f67e19ca11c01e2426ef0faa2bed48efe0711d338ea3b86b, + 0x281dcd532dc450be559536e252e0159ee21d5b91fbf9725f4a57dd870d80e779, + 0xfe4d11a8b3f24dc559b4a37118f15ab83dad5a74dfaed41637e994a81333f95, + 0x1857938e02790819328278a913222344640f200c51410456089768bfcea561a5, + 0x2007d043ddfc54fd999f6f4b63d4ca66c5f126951388cddb1dcde32944155675, + 0x23de66b927d576792c69a2c6e7df20d3fc745614f5202780bc2b4c2fb27e9e39, + 0x2bdfcbefe353fa2ffe79d2efd5a51c981345a2de40ef5c764bf90da86fedcfe3, + 0x26cffc0e5984933313e4f06dead07943880da66929d3aded77e0fa7f994244fe, + 0x21c532ad0d50674be3947ff2d4eb744eadbaa2812fc0fc25a41cb84c0fd3efb8, + 0x246ecf2ee4531862cc5a2d7842fe3c780b868ef445f70c9a1e2bff46149cc46d, + 0x397b3980a3cefa0fdc7339c4f9500b3643c54a3ee7a39600304741a2e772e90, + 0x144490957677636a9a7bf12b1ac99af955ea70999b2f972211552ac7562c6aef, + 0x4a96669777938cd9643ff257d5f56c5f4f1eb5adea49a678cec3ea17067f1d, + 0x2423a50871429a8c48ba13e4df938e6280d715b39af43449ff06030e346e3e2b, + 0x1ca50640e8f42c03c288014e8ef12b8014c3c40a62fc5856ee9b633146ec602a, + 0xa8335c2fa762d09bda1eb7e22b11cc117df788c0d023d6d8947727681a7a9eb, + 0x1c57af7a6796ed37bd964c33cd1bc9c89747ba21df6100209fc3df9f707f1cda, + 0x8f0ad5a6c01f0bde7d1a8e7d26848179f5ee31d6d59bb8e2c701e37a4cfbb22, + 0x50c7821c6e53eba185a6278fe04a5c1f2f28641bdc843c9fab2ac897e8a2466, + 0xbc5d445c5df52fb9b4b9d6954bc75763d53b0c2089832ebdca9605679f68d0e, + 0x10a6b2a07c472c2a32e9dc1f0501fbda5c9f05b861d1c78a5cff3594197b73d6, + 0x1a24448b3442479c7ac8191bfafc67d9c75e40200b318f7c72d0c2d908b3ddb3, + 0x5e230c7b91dc067802c6c9fead50897c03379389e2a7def370ef4c28e5671be, + 0x1eead685d9f3577f7e364da47f74d8ee2cf6cee31660055615d8f294a30294ac, + 0x4a22eaa10791b59b1bd8ad9626df74275535ebea301f8f912c521ef29c504b1, + 0x6377b60615b7b9a9f0eb2276786d028cca82fbce7db1cc27f50b8486c8806da, + 0xc76495da478bbdfd623fcac2f3b08d641c4c654738fad67b9e90ea0715714f, + 0x250ad6b94e1bd06817cfd2421423a95e18ba872b276c199e16a8fc650c5a9d61, + 0x1b2e0e66146fb5b1221c878286a0983e903e6a95390f57d298a50dce6f52ab47, + 0x18ca890aaeaef97c7c17cab2c3518fccf1180b8fbd134fbcbce38f786f2c0e03, + 0x1b5c3db94d9e0cd45571c1b88084186eb58930bceceb2c8f775b12f37961bea0, + 0x6294c72686a69b6069349a73a81542cb16a6ad71337b7c7ff5a5dfe06a260ae, + 0x2c18a25a8c2cae179b1a643e11159e8f5c9da448aaee3a44de48be3eca7bb253, + 0xfc45a2b9bd6f41901baa7afad40cc28d4479c304d101067c3567fe449332eb0, + 0x378bc3b5a32cf5ca088227c5b6f0a566e0b75733c704804619e6a979bc1d36f, + 0x255375346beabd092bfbfd7278b437bdd3c18bd951d7f4220cdc5013611fd9f, + 0x524853a2a9717af64500fec836c13807e5978be32886047bd3683a5a65b6859, + 0x1b3998553154fc26ce88f0488160c244e1dec648b930c132d077cb93997af5ea, + 0x12074b4d83e92f8e0ab92429aeb5270140338a97ee8e5c74f2b599d9577f25ff, + 0x1a40b1e01a096ea7ebce74c027536bc58778b45dcefb7cc056256dd07326a662, + 0xf5228bc094b9eec1967d778a2b7d6b4de58ede8e0f974165d37ab6f2336bee4, + 0x27314b961d2f96970977a33f2fac6823c043207e4b6a48a05537ea78d779c16f, + 0x2a78f5bdf98afa1da6dd45ab360b877703e1f9f0e797fecca45327ee4ab46595, + 0x2cfde59ca2f01a27fce554c265bc23fda32ddd9dff3dd0a2f1dfddd0764c20b4, + 0x1925a7d1cacee560010f843ef5fc9e7b0294667d871d49e3523a88fe0af56aa, + 0x199ff4bbaf94ee387560fbbec395db1af9eed9f50dd60dc3ca2cb92e92452263, + 0x26f7f91d959cdae91907b28fb2f149dbc275f13d55776da51a88200f8e7caf09, + 0x24cddd641b7ca3bc6c4d257832a5ae5e92126c3bd2e9f05e012731114d62d0c2, + 0x18547edf50bd77b2653c2a53284c999dce5dc69dd613804d10a0ee96bca55738, + 0x2b27178eca4b798ba72b2e6b566bdfeccb2a1e60d8504e4c8ec9192f2baebb, + 0x3020eb88ae7acfd6342709f3d3be45cf2c146bcdc906ee5795273ae4b6e7004a, + 0x54b81a6d3b1f002230c4cd623f77b0fb6eeca3afefafe694544eeeec1a170f, + 0x4d1e03c93510ba6fb49bd9ab51063d3b15e48e2ed449bda2765d03065f6cffc, + 0x2ca6a28e6b98b8c8220abc091a2fafe86f271eef1d93864b7b2bb5a160dd8d99, + 0x2a586600678651f144bf1e54de3d6f8fd519daaf4a4ad9a1f32233e89f9d6733, + 0xa94a9fb854a3c53411d736ce58dc82196b2cd13144a240a6fe173508a221d91, + 0x2d336c647cbb5478e3a72f20f41d135d35f96fbdd9b2b2884e6b23ec201e47fd, + 0x3dbe3f89948f9f4715c491a483dfbf6f6f9dcfb5853c5d3ced707f0050a218a, + 0x22466ec15338114c3b316b2d986c8c0d3d14800d82275a42f476b0ffdf9435b4, + 0x1c2d6c5b182f394e8d36999e91a9eee77da71f5490961fb783a4f8e6f842e687, + 0x4fc56515cf83247e370e48809d3bd245abb52638d86b48a1cb743167db2294d, + 0x1aaebc90617e5aa4b4f9036fcc5092da7edce9c110e3eaf00d7fd39b17aaed27, + 0x15f7dad928cb34e6858a2deb2f9d92c452a535a096c5d713f7319c0c577e413, + 0x60028307221323f46eb56773c5320fdaa2d7123875b420176e34b3ee079e972, + 0x157b288cec9b5356e60373bfa43e67511e2a7e62493650c8f38d819fc34e59d0, + 0x88dbe88f3fe8fdcbebc34ce3f00f07fda411d780ecff1da57660aebfd12ebfc, + 0x9f13c89213c82d5bfd38f8f8bcfe46fdf403d28e6d349ec0176e37df9c912fe, + 0x5bffad53722ac6c42236124c3200669abffa6dc923fbe5141c8e4157cd317a3, + 0x290a7829a4cef2e25d2f6f28421463344bfde52203d4cca736573537af33421e, + 0x9e7209dac7151697be17d3e3ac52b0ee6467929b878d814ae4cc2734b39348f, + 0x7629f5b7cd3dd536df6a866a071fb5df56352fafd0f097711cd1667ea344039, + 0x11641de0af5d033b442dce1f8334eafd4959f122304ea6c2177c377d55eae045, + 0x1021e806d83de4cbecb3c1650c761774e83cae4ecbbb0df13310150cbada88f4, + 0x4ae37e1e7676e1d3cf64285f704135c8cd640f70c895bdedd51ded260fbb69f, + 0x2a491d28b320ff77bf7221b59fcc2535c7cfc9c0f11a5fdc5e49c837a71f0239, + 0x2ba7c26958118f0b751444e8ea3524d45fccefd8744618e66e55679e42be29c6, + 0xc6516f4cbac8b8f29be9406c6c309df34e2da7d931133e4a34f29ec6283e9b3, + 0x2991acc7db5eb3159f8766c49d692079025b480a70656435ee70c5687daaeb0c, + 0x29d7605b413cddd192779b7325e1afb8e52ed3e97e92adf701c7a70c118c648d, + 0x2507bd3788f57cefee754d3ff5a92980dcf062ae4a3fad93ec0059eb2fe545ec + ], + [ + [ + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0xa514a5c227f4cec95dfa029e8dd124c34895aa46bb27c0911f3780d5015540a, + 0x278bb49a7b4e44aea46eb0f882cb692801a6e60fdd5b5c23c63cd65ccce4fe0a, + 0xc399e9f67aa40707a203feefb0b958bbdadcec5ca34901d253d026a2419f6a2, + 0x1d6b3d5f6ea369c26f825d2362933eaa31ea35ec0a77c1fbd9e01ca1523e4432, + 0x24be510095436206dd0abd0b0cbb95c883ab304aa52598b1a69306ec981a688d + ], + [ + 0x11924f02fd19b09255aaa1cf46ea0518e3d7bfeef47421609491011db0bd0b02, + 0x192e16d17d956b257b85a652eefdf2ee09589eac5be80915775723d2cb1da06d, + 0x63edec1bed831f506af8db648d6fdea145345887e8bdcff109035a1d9b674d7, + 0x83f0df3f1a0351d0330ec3ff602ca8cc353b7f6e762c7107184cd7b423449f6, + 0x119ef188bb3dd0d32306976c19941e8664be687e7a69692da27da215a6f06d40, + 0x211610e2ad4a377426fadf7068b0c1a6c299a164c1c1a603eaed944870d0b9b9 + ], + [ + 0x247fa7f022304a1994ff505456c2201ef9b717369498d3ffce446601ed9df845, + 0x298ce0c1e3113bb935c7058e7772b533b1aa9db0c0926bdc8917e5605ca3ac10, + 0x1baef1cb5509b526a42061fb53657f99b3232500e855192cbe8c940e068c475f, + 0x1a6764d5943fc4a720b4c0a19fdb8c711984307287a58b9b5f9f5d58212cb263, + 0x2d9e0ab5c06893dfdfd03481381ba86b6e6292df5609d71f2c64b2d9a79f809e, + 0x15a67d981041b1f6f09f3f9ebefd864e779d3af08157786ac077505e50ec79fc + ], + [ + 0x3fd7b19ef2c861f22f77ff810f54e277bc94eb76c02d79d986be3dcdf051c3f, + 0x94cb4e83621afd271e41bc71727f0158ebd612239ac9d698b17fe4be05b7fc8, + 0x1324564ac7bdf9e22164e9858d7fa8e368b165eaea3daf4eb67ee59c0df2e5d4, + 0x11a63a26feabf87fa66bde66cc25a922c96382d76c6a7ff48f1537beaed683a, + 0x25f16631bf77060f7ea34087c025bf135784319ef08cda2e31419ee0a529e658, + 0x49327fa79d28c12a2c82406947f77f06775b0287468b3136877701dbe7c9598 + ], + [ + 0x18bd41239c3e71579a677443ecffbd555a81eeeea69352a68b67c8563c0c2a06, + 0x3d880395be93c27d649af5fd142e76b33918cb8841d5a28173bd5cf7d328791, + 0x5761b8c6aecb1a8ca4ea4dfc2c8376064a4a8004ceeda210a55240562ddc13, + 0x8ca7b64657c3548f32bef5b63ad24288a41c0b251099ad27f9434307e3e64d4, + 0x144c7a11da5a7c5dabae3f33fbd03cad86d18bc594c79a497ecb9894edb554f1, + 0x230940dcc5232658ff9c29697a3fd416d170e8c998f1aa85dea0c42d79f951aa + ], + [ + 0x2d78c3a5d28de9ff35bf0a257635196e5730ca7f40493277078cd75da8b4ebdc, + 0x28eeae6b5866ad68e443bbaf91680db7d7e2b3037e38fef61b42cbccffceca81, + 0x10c9e283159d58cb4cb2e35fde83a3ba1fdc28002ed9963d2a99f186178a148d, + 0x1998270471e9361955446b0cdb8bea915ec0675f1cd648ddcb04303507a4489, + 0xf971162627723f3feadacb28b0c104cb8f74de508752fa8d7c0db2af13de8ee, + 0x1b121c049cd1159e289007e0c9da9995cc4bab4c26fb888ec3972a8a2e656964 + ] + ], + [ +[ +0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, +0x18ce75a35f7297cad2bcc25f0ed1bb4f7c592eea8c6903b19850511ddb83274c, +0x138f93361c6546d69015ad48ef50af34fa9e19c6e6844a847eba9d908572052f, +0x13c29b24c0e38e65a1b9428622ba42931bdb65eb5975e66d3c496c7fe6f7a30, +0x211a38485f1e9db425379f4b3fe9c20474c968aba2ef8a4bbb898a8420d0fc90, +0x2fa4d773833d944be46ec798f7d16e9fd02f51c086141af5d69acf97e9a80b2 +], +[ +0x11924f02fd19b09255aaa1cf46ea0518e3d7bfeef47421609491011db0bd0b02, +0x2c001eb6b378c49fc5b37aa41c13fdba486bf324eae0e0063ff83551827f338e, +0x51071183ba1b8fde055b8f273005056fb37684b241f88851a5b550ed0cbc452, +0x14201055ff5412f834d761da8017961213666e5c44d6c5a8237deb4d0f734d79, +0x182177db418ecda99e6e9999c3c0492f4ec27a89b2ab554dc8165da9ba8c9762, +0x1111d2d4d2a013e33fcad48d574587e3d7f7f6b484d7fefcf933dc833d13bf28 +], +[ +0x247fa7f022304a1994ff505456c2201ef9b717369498d3ffce446601ed9df845, +0x16e74e9c0932c76182ca25ffa7dc6ae62b2cfbe19142b2ce1d95ec0839d7faa, +0x1a13e7beefcfa55aef7815712c7b350b465c0785afe7d6b356342b61047d07c1, +0x1adcf63e81b22ad38811b20aa6175ec41784eb99fbee0f3e56a15df0c1ac5179, +0x2f3a76ad0307b740f6e6e7aa989335c6000d930029beebee83c0631b3b435123, +0x24dd1c38ec3e47cf711221cdaf4b2ccfc0991a178cf7df2f3d1b88f858763c40 +], +[ +0x3fd7b19ef2c861f22f77ff810f54e277bc94eb76c02d79d986be3dcdf051c3f, +0x24de008c4b20c4dd769afa3b377e2e72f0a74339f53c3f6ba8b84b0a85fbe9ab, +0x274ab81953247f18a26dae90d93deb1f33ea243af6aac4e05e117e233b922bd2, +0x16a796c4310ddbc2c435ea5ef0d6381e163250c33485426e97a566ab6f2bb07, +0x1befbb4037c8b847d2711cda8600d941a1583cf2fe06a8ae02bbc26e180259ba, +0x3a01ab7488d6cac69f70b90101e5c8beb78bf65a79fd6068c9010ec2e0fda4e +], +[ +0x18bd41239c3e71579a677443ecffbd555a81eeeea69352a68b67c8563c0c2a06, +0x2a28f2409cb364d31b858844023279404e2ce02d38430be77b2755aeb9193a56, +0x1b8e6cf61af064c9804f1888a6a83f6cea7c57e574c229f978aa922ddccd80da, +0xca6769d4383398d1a04d3d7a6f3510d85fba7f5f6e6d287d447908d11c71153, +0x125428fe689ac0be368c80b67e8b2ab83d8163ba30b4391927f352b3bf3dc5b0, +0x30516fe884be9bad887032b15a83c91d84147d44fe15c90935ec4d421f5ed05f +], +[ +0x2d78c3a5d28de9ff35bf0a257635196e5730ca7f40493277078cd75da8b4ebdc, +0x2afeb1a63b374a502180680156748121a68fd7002114733bb039f74ad576c0d1, +0x3ddf5c61fc2eae153e94adfab9b234d07b261ad228547ba9218c4caf6cbaae9, +0xc2e8c673f27f45ac1112d92cc8b81ef4af42657d7a114d2d6bcc4b74bbab7c7, +0xda5ededdd0fdac9af41d58581e5aecafee671a5253023205aa9a2b7e1df842c, +0x280364612aadf31ee5b176ccc54b4a5f961cc782168c8f83ff2ab5b4d12adc0f +] +], + [ + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0x6fac61a13c7139a37697a657fafd9c12611f196b60aab2342eb6e869de7069, + 0x27b4b4ea2ab70bb1a791b43c0571329ee6e44da480d8f0bfed4eb43125bdfdc4, + 0xfce2531c0dd9b1906513da21cc6442611222f8c05b5bb5ced0c5d392a1b4254, + 0x2278afba888b07c659b7d537ef4f2da49f03e42e6fd4f6ba90966b2bd89291f, + 0x456a8c01bcdcc91bda80b7c97f7e9019009163bc2613446a40a49fba3c70ff1, + 0x2e4c46b8f3ebe49417334ca76f3dad782cb15d40bd4fc143df9937aae5fdd9c, + 0x2c13f0f7c421c96b47743df05ba0a84d302823a72fa019c251cc653bf9fce8cb, + 0x57b6bc405c5ad7f6dba556199efad30bf33380cf4bf74ec23214edd123676a3, + 0x2d127c7a346cdfcc822076c8df679eb5cf6bd0b6a1fff70f753f1317acaaf8af, + 0x1a4dc6959d65fda6047532a57790a1426499672d67b10ea360603bcdabda06e1, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0x1ab539242bb16cb2ca4984bc82002d07c6fc29bd0d9a71e348669ec4f909e567, + 0x144bd8b4ba25cebbcc44c0847844f5d945e389efb61cebced8ac7740104e2da9, + 0x8325106daf6927a182c4d83e0bbe039fd390e2507a359747a98d35b41bf57, + 0x1469c5365c13ba0cb10b14f109d6893eba3239739e970ebc50b63a9870da0ede, + 0x111e82bf1fb3d4458829cb1d852b66f7c2ce4079ed210c88374dacb88c69c252, + 0x2bd6778059c21f8d5df3e825464319ba8d9f0fd7b2bdc4525ac788061031eab5, + 0x212d3cc6c2012c922fd9372f6be58aa0518c392a9e25338071401daa267e36c0, + 0x267547f0b00c32e85957a425dd05961a02626ac79b2eee417af0c450646ff99c, + 0x15f1012eb18a32c69ac392696cc974530f711109a197501b43d9b49c445d9dbf, + 0x24e5916738efe20b55496e3aecbca9239063458c2c562f3c0c2ad45ecb9a0c27, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0x537e9d61e32a91ac981e5442837942833efed46c25b4009d6622c1d5cd67228, + 0x2409867674021c13c26db12dc4687258c8a7b8c39ea9e5f0e538c9a5d79d00b1, + 0x12dd0ad0bbdad721a2bb795f4b54e08a21e4e5043e30bb1fdf1e369b45abbb8a, + 0x194d2892087f1485580dbd9db047343f73d71741cb1d679264d0f15f22011a17, + 0xce1f30705772a51b72eaffe307f73c59d16cec505e28a06352fec8497398b6, + 0xb4c42bfd8b2eee4229dc6b4b6ae934b6882a560dc0b056952cea95e04e84ce8, + 0x2831274ffa49361ca9ad0f3687f1fd840db43b13fc4bd747fcbcce877ed78fec, + 0x11c3faaea57cd532f952f56dac42a8d29c72c8d1b29459ec218d5280c374e141, + 0xd01440afe63c28b5820215a0a082fe296ae749a3ee6116967d46c4b9d59b77e, + 0x27fd7799437558165b866c1b89762a0b94bf7db886b158ce62dd2ba01dc6fd48, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0x2aa5a2f43e0f4bb8b52041f635ec810e7fbd82548dc722605bf2c15e7b2e044e, + 0x109e17fad36368fd93917a9c4919820ac8620c5baa64d813f420f25f0e97a087, + 0x1c6178a12c2d4fc816077f0e4825fcaed9b6ddbca03d665be624cbef3df6c10c, + 0xc8b545f3ba3005742d7867b42b2acb3895868630d4d1ca9bd2e7d18b22f7b1d, + 0x1cf272cf45a39a8f47599447b65ed8ec169b564e656acd8720550f78b1aea9e9, + 0xed81d4f2b8cc774767ad184b89c02d1cf3aef1866d4b8df571a8feac7e1fb26, + 0x25c22916d7c3d030b6207eef339a432d2f2a485a98a63fac53be6a93d90cdcc9, + 0x140c2f65889d437a0736acd2164839f1a951aa1e9ee18258b701b19d0f880820, + 0x19b9bf03c47ce774ff4541d66232a3a61a1eb767c37ec93730c2d29b43ec2d0b, + 0x1464a2e5c87714bb4afc1b5cb90f1cd587ac7f3133e7f4a5e45d0426bafa3946, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0x2fdf0895b6e7dd081135a74466610d02ec2f5e53d065f8f28f55626f8984590a, + 0x2136a6254155d5370c654be03d5f2ea833abac83f3ee2aa86080b4c812f6d9ee, + 0x2c25045d4ad7cabc1457656efe3091cffa14b2a3c3a74cde1619658015d69a3e, + 0x35edf90ee5ee2937a2258e02a11d996be7d2263c30a8111a8f461b31b61d756, + 0x24a6181596fefcf6b89c799218467001223efd7b39880e0b241bac300d20a3ad, + 0x29dcdaed731430d9695b46313d84713e6dec7b565f79b94b2cfa3dd7e9e4ea51, + 0x1724f4a9b1696abe55d95e9c0dc048d1d473394ccf983f198d9e90d2c73d1b8c, + 0x1af69c74aae418d0fa8d9c030ebc68c04e608e5a8cc00a35b1910ddbc6fcf143, + 0x27a0793076b09c2b5e775c8b738f488a11171c0066277483afa7fd8c1dc5bdb0, + 0x1d4ff6c75f1778615e31525a57fcef7dfa5b5d84382b5efe78fc90625f8e1e12, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0xfdf45f1143c7650173ddbf41fd32b101ac1058dcb360e4f55fb042d86b3bbef, + 0x28605df321f1d74a93860493ae581fac9bd5dfab8755373d8bbea346601a2a1c, + 0x2894568db7debb47fdb42ebcba7bb4c2bf391c73c0ea435ff611a9a721a2ab09, + 0x193887de99914c911549cd4c5a402b7b33e650ef0009d7c99075bee089ee532f, + 0xe5688ca400eea76906895ad874136e390c7545ba17d0b64b9da48aecfd53d91, + 0x2c60db3843ae2171a20f4eeddff7e6cd3bd2b06cd8d39e97f93b895a4096371b, + 0x8fb4f2d9d8a12c667625b7df6751d25d3409df0443411de74f779e90109ff34, + 0x4d7d91e3652705f015e14eefc3aa412c707a8615d7dc336fa2da72d1a1802, + 0xc60ca70bd06719bcb51c3a8664b73f8b921234656168e68d4ff6e9552808d54, + 0x1ed054abe9f3b4e19cb8a439399c5ff5f6de90c8463a09b82da225c567d05095, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0x2b3d78867b390b2fdb654d68512c316ec959c5b8c9aec49d5fe74188257c3b6b, + 0x19f72308eb341f3328570cdc9f78fa3838e628260d6e76bb3b09cb4e5136545a, + 0x54c9fdfc6bb12bd2061b153f433d828dd2ddf02d56e4d6eb280f19591597d9, + 0x20a858ce8c00fe452359acbce4df9110ff6c89a362ff4c8ccc7f9da470124a1c, + 0x1a55f3dae7d4d14c6eb851e44463ee0da6e66b0f56114b8f46dda9e717a9b1fa, + 0x65d52f3291af23a00e2d058bb6ba8e17889f7d03bfcbc5234272ae8660abf31, + 0x278715151d06026cdd68f4bb0fee4b041cd0a8c62bd5faf71b393ea9dc3bcf2b, + 0x9c6ec8631ac5a417f041efe2951033a622baf01b9f1630c7bc093ccd6f3fc60, + 0x9c078b2310e182f40304e342c5f965f8605102931254955aea231962f762f75, + 0x22f4faf4ed2ac6947282b926253d93751ab1118a05d1466bf117dc853dc3c532, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0xf24da597b74c3677589a6cf15426219cd0e2c1a60c9acb4b9764b8e5b4fb5fe, + 0xf39e91701d900bc7ea63b7f0d3b753cc31d2cf6666eef786a6400ad04515c96, + 0xb41187c60cc3bff1020fc4e647452ba940a5b3d9ffdd1b47ab613a515df66e5, + 0x619fadfd7cbaa89e7d5558c4d23275665531928f62fb14cc4aa42605f97a1b5, + 0x285ed3287367338bc9387c83fb8987cadf1b4ea7f1dc6b172e924ee0fd2ffb87, + 0x853d29d7e18010d04607ed8b3089833d55166ebf58aef558b3642f29ae2eb31, + 0xb1d3737cb97c59030221a7d5d112bb755d096d8766242158d0bad07bed5ba9b, + 0x272b60326347683fbe6dff2b97289dfefa1be8238526c8067ee0a126942ca6ae, + 0x2c7ef420b2bca189f6d7929af54403354933d68446096f3cfccd12e76818b23b, + 0x10fa5605e0b680e055175664a979aea1a45c45057f452e5b90cd613012b70508, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0x2ad6fe66fcc8eb73e2dd7dc6a2186c31107f8896b5f8c7f9ebbac9bacffc59, + 0x1db23b49760ab87c22237095db005ad9b792ba63647031f2f5e8d0c66ca2c833, + 0x2b51ab38d81609e885b8d8c3ce799cedac1febdec5e27a205ca82b010b3bd9f8, + 0x2bbd8df986114303d59bf8a408982796d6f1809269b983910bb6fcbbfa72af53, + 0x3516ee288a26a7555d7bc66bdbec4203e74c105513cd8be87a99c035a176c22, + 0x21161b2869e0be07d85e11051ac0d8894044cf1b4715d5dedd57cbd6aa48b240, + 0xf4723c169e787400b2153bac8a074da0d992f44a8558a0956d563e73ac03dc3, + 0x890ec1904c98ba5b3cef6bed816850fdf6734951b143faa0c2c643a1c1368b4, + 0x1453882ebd23e2ce3f5655eb4f2db4e7d6dcd892a14e3da655caaa5f45a2744e, + 0xdf69ed4eae9a6ffcf54a77d8d8ba14541af9d276327678b71e7c49c8deb41c6, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0x84cfab525ae12db3c30220f978a1b48bb652c2e47d1f5f4bf1cb3d5ea4ae0a1, + 0x220ee2aac4ec50cf3a51d76ea554c6960befe1a9b946be4b58cff8b4d8a16561, + 0x9d60891cc06c285c3ca3cf7a78e37e2516e4d0ff503179234ea12645848d45d, + 0x2f51338183dfa99604f1be042cc1dec8e96e08c7faf7bb3b7eb860dfdcdd295b, + 0x29fb82b7e1ea4acf9d2ca8b32f27e68d10b27214361156770bfa4732f85e1b01, + 0x24d4646bb66688b33367aeec4cfdcfe16b7d21f47f1bb1f88a25896e526ecb8b, + 0x2cdaecd1c5653769c095f9ab2e0b4131a3dc4f581954fa91120dc7864a5d5b5, + 0x2e48eb6f5a9dd830bab11e8f49f7431a851938335f6af547bdcde3b9a2595913, + 0xd3d729c3d04c7f9967a7f3ce11c053d5a5598f0847966dc9840eeebd9676b11, + 0x2c9c7d8f5c11a1cbf89ab2b794739a371d818f77cc71bffc6ca55d4472648f2b, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0xf330feb7fa24cbfbbafc2eae5d109a2bbe9d5358ec7a34035d728c6a531b17e, + 0x1b4af72b65b66913013263c37d97ffaddbb8a824b34d45819029b0867ccfb460, + 0x2ace1ffd40f56f145cea9e679db6c57732315343423ce026a8e9275e888307fc, + 0x1c328a5168d04cdbc31519e037fdcc5c426f9a6990fe80c875d625880c7d033f, + 0x1970922d81c9cd97d3030d53733e33e3d046684219f4960ecdd0910f5aae548d, + 0x76fcdeddfca38e6bc4c5e872eeb1628caf23d8d7b966d97963f38b8b55a86ab, + 0x3e273f1f05592ce120df7ff9ba32eff1c1bc065b149c2c2a7986c1569e4cc3a, + 0x2b1f8dfec05e8d4495fd0759474932a003b11289a3440792a48e2cb777badf6a, + 0x126fd80bd8f9f83f00cc51cde97f9e4a3bd540c93921e8f3603c0cb13f89cc9f, + 0x7cf5007a4ecae9f4cd74689126175d8a81f7c51a317a2c1657cfcd533b4a57a, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0x18793b6ef20fbe077cf212e603b2a491b8b9965510bf81c85b4cef874fba6093, + 0x5bc7621748131cb19ae5e7e6cfa468344c116dd37fae01e1780381f9b1ddebc, + 0x1aa859447f3acaff5c15fbc24bf7c164faeca846b555b02637fa84a52cc9efba, + 0x28c3d01915f85693e04821e4f2ca799c62b1fdc4739123d8dcdfbd1c77636c1f, + 0x2c7f8527d2ad7d02e7046dbe690997f033e351fd18d357089e988e041223f15, + 0x126b669244c7ea73d340ded56f5edce3632a0a69b9cddede297acf2f072db9c6, + 0x24f71ee920c1cc2790112e7a8e9d3d824255420604fe31b331e98d2bef539781, + 0x182fbdc24f8599ae291b3e8a96bd15251396a94167c8e34ed1f86069c067f03f, + 0xeab7f1b18721b3c154fb3b7fb067c4f7ec18a50fa3ab3aa5873a408d6d8cbbd, + 0x2012fdfd4d53aadbac3d7ab9172a826705d55e5862d1be643cd4449e1cc6b06d, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0x140490ba93d42481632e9924a725c65bf59f7e4975e98fbdf486a9772f4b6e8b, + 0x2adfb4e0a55448609a06a1ac31bc5d06d74c45a4dd23680923d985b867f054b9, + 0x2035a526748b686ac46231697cc52fb4c6d8e48c4314cb0a1ee08eaeb43938c8, + 0x242ec6b33cd2c625d1ca2833159053a0e9beeb37c59ec90e52d40c983e865096, + 0x10f8808d7f88620998e3f144046327b9522a07220a62c7986debf2820accb611, + 0x5d4d8a6023401b798a1b296dd42c9010da081b9e6073aa73dbed7a98bef4419, + 0x20be6be68c47dda41e08c5f858520b25c036923b978fa8be6e870e85fcc16ac8, + 0x39240da2e14965307bd9be9af5c0cdda03a4019f86c45bbbea90f40afcfc500, + 0x60457249c4fffb06481b95457ec48e2b795dc414d6b71350ad08b56cdba7c3c, + 0x239ebf95f3d5909ff12820066059f1b999f9ee594dc03af1fad6e0015d698e72, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0x90738838c7088a39b45b7b8466e003c1d0b85fc0c95153e85f9feea552cbed3, + 0xd0aa07eb53bc77f6a7c777fd33d11e4eec54afb97da769f937310f797df2469, + 0x22e87e33862f106af8bf1a6ac33f69d994ce06f021ad32236f5529eb399a8ef, + 0x16a3ff860e2110d98eceb0f5e7946d207273ff9a4f1e088a009f1aae19c5b0c0, + 0x13e35cdae4c6ff35a681118ecf4612503081b2920a59f54cbf5603c5690ead76, + 0x11dcdcbb80fe328963d887aa5443a88e602767afcff3938a877ef8b5e6b62084, + 0x1440ac3cf3a1ca78709a2a97a0255d08882b40ae287994670dc7d58d7b929c71, + 0x9112aba3d285034fd7808ce5c69caf188aa2192e3143ca73ce3ad404c503a9a, + 0x2c8eb1b5f21c2f320943badb09721ad68f1c2f3576531713981a905daf415450, + 0x695acc1afc2070eabaf2e2279eb6f11d6e24c787b37f3a311f2bdac5cf0b160, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0x1fb55d0f07f478f8d6f5a59e0856ad2bb9a4e1987cbb36e437895230685ceef5, + 0x24ffa19b717061f29d7befe633215f277119ea89aec1326f9f7e2fb3773f3a5a, + 0x16cf73a3eb3a86fe74cba7ab2b591ecf57d66ffae3113107298e11f21d7f69e5, + 0x115c7124e48b479e39faf24d853540716cea1bf2fdc19fdec358d1f740c1f874, + 0x1587c165c3d5592e72a8445bab791271ce64032bf746d66194ba23a413116cad, + 0x20677bb9ac0210a06115586f21fdcd1e6b28e8a1a8664e48681bb077b75e001c, + 0xfdcb34056ef1d893287ad074ffd8e4d767ed07f9ac97b5de1f34d8e3dd1a651, + 0x19ec313123a0d8e63b853a0931c9a99b14cc775f1c312bbb13d5d53f8818b79c, + 0x19c0eb17f727d16dc136af9e86888808b870b5e9e5d9e3a3c3f0d9431bdd5728, + 0x2b158fd09d9bb317ce4378cf6e0d574374690d42cc465100ac3f9a6bac9b6907, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0x67895e624f72c2ee73f06438d1e38b380f0259e6a04047dc2ee474d543df74, + 0x24d801233a58b2016b8c6af6bb88cdb17e194fbd8c619a7d844ce681b933d5f1, + 0x18bbcf6fa75ef7e68070f388815361f028acdf41c8e0d9f2afc62b8bbb9ab94f, + 0xd8f16cc1dac32ee244cc1837b1ba594c32a38e1a594a6f1367af545463db7a6, + 0x85b04652f4427e9220976032ce4aae7e1eca676f0c169f9570bf91014ec3d60, + 0x29b6e637abd64aa25e69de1bc8bc2061010a523a6319d49c8d908c46c2e76112, + 0x686bc450316a122c312fde6bfea7146f929091962bbe3225769f767ee92e1f9, + 0x1c7db281138ff861643018caafaf569efa4f7d1dd5fe8db8115679c9d4e464ba, + 0x434b9adf694ee77662c888fe50a3f24f9a680df2fb6f501422589800c123cac, + 0x26bf3831811b3222ad4a14f3b9a5357b756702139b7d8e7e2bb87dd6034b352d, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0x24b42bac7abee89474ff328bcb61e4ad5f128773e068dea11b88fc2ea6ab66b0, + 0x199ed05bbee1131c4dbba92583a02fbf9ea30aa59c7f2fc5bd5c0857cedb470f, + 0x2bd6670f967781e74ad00648e01596abb5117b74adb95734ade1c81fd02d100a, + 0x17127e11451908da53f67a87859373b4c6db941086091270d35f7742e286bb63, + 0x292010c36ff554b02f56a128071f54171b237591087f805189af62b616205261, + 0x2f6af6bf3c24ccd04480e6490018b489284a951f067750f4e8b461290402e3c, + 0x11ff6780b8da3672a8b9eceaf9d5ad240bf0f1d91028f3abce5147d0608449e7, + 0xdae6cefcea61ea52cc1bcd5bdd0c9a4f1cf123109cce7354405dd38054a8b2e, + 0x2234fe0dad3dd0ded7a39050f4478ac43bdcdeac99cb7ea75d61a66c2382c35f, + 0x1627a2a755f77f83d07a5cc58dc2aafec9ce48a85427f07f813e217e7d3e9272, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0xbc958ac5faec064de3de070d9605135bb3bc321f74b7f4795cfc4cdd4f64c7f, + 0x1761972f9f0d7d67e62f476c88b521ebe60cfe3e1aaf50580acd20f45590507, + 0x3ae68549640072b1b75251b5fe4b2282191f235ff9a753fcfccc995a3ed3734, + 0x1d3a95b2449e1d227b3cb97854bdfa5248b78bf8acc15feed87036a74829b12, + 0x1be688f94403019eb20b49acd9f201d5b765853301e9f30943647cdac98a983c, + 0xd40a2c767f9d882eb478793e2e146af99a620af4a76e6f3429d6259149311bf, + 0x2075d588d996d67e08cacafa27bdfbb6ff08a0d97d2b6470f475b87c034fad40, + 0x1db5acabacf79eef4e6079222f548fc488438af4e04f5f8e64f37a80eff37aeb, + 0x14042fd27044254958665e0fa0ef7ec155c9079147eab6fc55c9d8c35d433a04, + 0x21ca73c94e245ed00ec13dcbb943bf4ab0ae1c29b0f3c2dd27c7ed414a39c2ea, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0x20ddb53f4160aa862028ef9ffc0ca24edc8e7ce304602be7e8db7a7ea7aa22ac, + 0x182fcdfa75858b86631ea8d0e0308f3e1202f77cab67f448c118d2e47080c137, + 0x28cd7a17b0f3349700263450f631d80337f6f6e490e8736b4c322f77c6eb94b5, + 0x4a6cffef8bf0db8c769ef391c25c8162ad2588db68f202adc27f23e01199f97, + 0x1f208c20855afe52522395aa73d971db1dc111dc531adef15f24a91fd6cf7085, + 0x107fa0c5c5aeeb26505669eba119568c4e249d7c16da6fac168de7abe11b444d, + 0x210dce59a46fc548ea60317c73249bc85062f0c2cef2944df4484f967c6248b9, + 0x278cd8d83323de48695c3da57cce026e001525a3dd65bc57ca2612b3c6f1cd82, + 0xb9cb7e4dbe036abc7cb070e610b96d61b7fe2bf29a4aee59d5f051bdf1b942f, + 0x2aa13fa2731b295a9974aabe82b9cf343d27373cecdb3a83e03e0aa3af07baaa, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0x11e4ba066ef8a6cb251a9704dd23abb5e8ef31ffc2048d70400ab4029486d1cc, + 0x23578b304fd7b3d28d886e3d71f029c849885c84f9488e5687e5be7fbc2d2e4d, + 0x143068c60714bb1eb26b0991681a9117decf370a9e1a24ff5d2163fb6c8bb770, + 0x1a42d3af21b7f72faee430f085becc8598c057127907373ce297e1c1493715a9, + 0x260e79c967c0d5bc720f95ec7a7b088051dc85423f798776f2de0e8c26606002, + 0x2314b014bb5c57a4217f48112e9c91186bcd27feaa9a1f3800fc6b2fb6ada2d5, + 0x10ab73560f145dd61d66edf15e597c73871a80cf0645b714e6e7268bc1b59bd2, + 0x2da780f43e972a1ea7844b5cffe76215f0b86f708c3d0ebc758024a3328c67cf, + 0x26e5fd2c13423aee6c1a543b5d4fee91af5ce83d74efa84dce6ab9323d1644ce, + 0x91cf8a0d9aef97c341241ac92fade04f1f21f20c9af67c55a6a63626b73befd, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0x1ac2da30c9db6a34995d64973ba9137283144b108b9619f678cf3f4a95c096e3, + 0x11376660bfc8fe7104c949626d350f6b0dc1b37973819e4797017487619ec25f, + 0x21a72bfc29af637d0a76681e97a310e9ad1dc8b47a66598807e88fd34a46aa81, + 0x1d61ed0d0221cec05abe9d2e8c0f72cb74cf4ec2df3ed582d4acfc2afc972f13, + 0x2cf2377f25f134cd525ddc0a210ae1edc91adc51cfbd451a7b280d332463fbe0, + 0x128d871cc9d69dad9adc58ff843d01210527b2e434fb21b3770a9a7e639cd55e, + 0x180f7db2b079ef5027f9e517057b6186136b6631556ed4979d115704ad305729, + 0x271f62e52e4a218aa6d6af3d547117c04b4c082c24950714dff89dc0ca70cebd, + 0x1c33419ecb6f7066567d7fc5addff3010852e87e68f89d6b6dbce38850401526, + 0x1a75ac0eb3ff4f7b647206b926ab9b6b70e54815c7d169de9dfb34b4d9baf9ec, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0x1662417df464715005ce1228264c58708b62a54eb3d0300c7e2ed1017828f1bc, + 0x1bc3d8189b4c0993407f585a4e859ff2d038b607f678602ec2ee5af423dae356, + 0xd1fdc7177e273bb5962f8ade3aa5d858ed7fd9bbd22b2d9856348382e8481e6, + 0x2e847d92b4b1cd7198df2d2bd91b845c52b9d1f25d685bb54cf43d7cdc06a89e, + 0x2116ff3bbe130b9b1bd4b76f1cb4b4d7c7b472cefb4d98dc08789dc993aff289, + 0x1057a54ade240ea545bac05e9707460d7f0e1930cb04e460e261852a5aee96a1, + 0x24c6693b4bafa19500e73514069e278c2abfaa8370d62312ac7dff2d8f973327, + 0x2cb268850f0ed89fdce142c8511d2f583a22e580cbb3d0790e41bc7e47420331, + 0xa731e96f407cbd92e535d4a18dd9981ce5c8e4ab15bf7f5eccd29d831b0712e, + 0x9f9e3fd0498d86308ea480d5ffba80e367c19fb4a78b11712dbab0011cae43b, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0x4670b146f637567754612aecee2b9bfcb842e7d6785b7904a3b1e37b740d4c0, + 0x3c5e0facfdd5fdebc0255a4f78af5fc16c82892038137186db5687475ee26ca, + 0x23a34dc39f0b7bdf631f9c88dafedb4bade20015c869fc463a25b7c483254b57, + 0x20a919d5f1fb9b22abce924797ec204d7cf534a9c5e908e57315992edc06062b, + 0x41f1d89022bcd40dfcd978191b200f8a2b7adb2168f3202b4f2dcce8726d922, + 0x23c914f4087c43ee789ba6be9c4b99fb032b7b5f65ca9f3af46e14dadc38134d, + 0x2d61a559f806a5e382041aeab1d5456dd212c3018ffdcada5235fd842f37ae0e, + 0x2e5457db2f94992120c5c9054a6a45974270109e5c6b5a4830e175c812549aa3, + 0x9f4292ce6a22415c7f83c120b5613b9b66fae13bc8d1b1af298418be41079c3, + 0xf82a2950fe7f2169a76eb6c5ce246ded654db2f03ba27e88030124d9ceda7f0, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0xc8a9b44c11b429d1cb9eceaf7f5501e9f0a400fbf4f0ff3fbb5f977607542f7, + 0x116275de531eb4f4861812d5dba5dc91ac027d187072cd9aab4ebc5c316eaa0f, + 0x10face39f20b71707fe83569937fa20ccd528792796bafd01dc9e094ba7336e1, + 0x6cc30ed5380e3e57cb30f3cef40f3c49819eebd7784a7b0de815fe2c007956a, + 0x11e62c7d02773e2a4bf5e2d96b2e2a7ab172514dadece61b41632f613336200c, + 0x5688b27d4a2435fb45c8d5f3743b0b1cd380ba6ddc95abb6f117aadbdc83736, + 0x22e95383d9f4bc94e9e2be09ed243d6114041ffc729e7edcc238dd82c7d5ad19, + 0x1dcf7620094c223d73dae01624272a7706c44ea51c959df302fb6e91e70f2501, + 0xd686d6407ba6f204fb927b3628ab5becc48de21f3979f6818cf12b76f7a89c1, + 0x4059e8835ec958751f897986059ac067fecc5eef0911b714170e73c389169fb, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0xce22a6f7aa9168150d064857ce6f891c975c3191bbff919474702bf4c8d813, + 0x194f2018abf3467e78243e36ce971440b9e8aabc83687a0851c048d7eea72729, + 0x29974bc9d401f128049f4732d6610eb9f269743fa28db231db6ace55216d7764, + 0x23ad853475090c61403fcef91ea2d8a36afe29741569acb39f2e5333921739d2, + 0x4efe76826f38d11a7a761748f9622e4210ddc38454bb5329eb9cd5ff5bf4556, + 0x8a2e45b2884b3bcb463f58ca3a7e4f2e7f16aada17a609bc358e339486ea6f9, + 0x1c22ab2592802c8f64a76cbf083074d7d72de9bd3f8d993467b00dec27c6e28b, + 0x180c18b59f0dc43c04da21fa47b4bdff8fcd6d845d886f71855c212307514f7b, + 0x146346178cae4f0bf5bc9dcdb8e1bfe21a0ff0d80abf33418c72499e70aaa225, + 0x301de4fecad713260a57d4ecec83a8e4966d1b89797805c4b8f2b6be9561d1df, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0x80ff1bccc78688253119861fa90b44fdac2f5d2708a1be1225696d47db0da7a, + 0x2e8300243648b888b59914509ba219649e3f28cbe190cc3dfebb1c083a7a7fe9, + 0xcda045c07fc05561a686cfa9e82c9fa0774f17f34450dcfdddc1d15f88b52a3, + 0x21335dfd5874c230f903aa6249f64cdffaf2b30a19b4f8b9e42e6dc7472f3521, + 0x2e7bfd8d6d903cd0d2722ee33f82aa80805629516de6d9091afe9a1613183c05, + 0x443b099429cd33864738e414391c37d032dfc795378e8439afe62eebc49d241, + 0x215a81cf42f2710c48f96513f2d1ee0d350ae57ff01c96daf3eafbd0b769ae8f, + 0x156a1611ff9933ccf069fb2156159851c8fd02f7fc27bd5bad61ad00826c72b, + 0x90d3ac25b80c0f69e9b306380d3cc0418a5de630ffac363ec793a0fc54fcf97, + 0xf53453418098174e3a6214c9fa8b59792048cc0c963b668feb4b79fdfdfe4d7, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0x167dcc32fc7311f7c5df9a1d2955a928fb6a1ce771019241fa491c655c697381, + 0x2a191b6a2f8f96da4bb2f91cd377b32fc8e84aaa857e976fecb7dc98bf518a03, + 0xc2fd4887d8b704662b62339aef5380e2cfc1eecfde9a4c9c14abc52c2a0a8c4, + 0x1e630649bc36af20c735f3e55a10e18fb1192eb537dad2b23932079a5e3e039, + 0x210302a02dd75f2d3846da16ea7c309911eab034fb60adeb5ba69c1b31b8471a, + 0x1d9e0ac6e8f8b9bfc77b7439b345b772596f8cd23370855956e42366d42a172d, + 0x2a6cf61cb3658480617be7daa4072efe4c2063b9777c1fc7748cf00ebb670067, + 0x2c6d225faad9f6f0959163a42621d26c7c91941196ddac67a618b390bf84b5ef, + 0x2d2cea26566fae8c2853a5976075b6d73da65b6a7156ab30540aa9db05d9aa29, + 0x2e13c310c5e84e55bf6453d9cc647f87c90dc2625f366a6dd61f60a0b38ca3dc, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0x18f8e2508be0983a6ad4de69cd797d5f3974c5f2e4ed2dab4e67db7b13e9119a, + 0x122a34cadaaf871dbf14a2626be775882ee4653beeecd92d742541350f929c10, + 0x1eaa9c56276ed20072675773838cf7f72966a70537bcfc85874821b40bbcb7b6, + 0x10e0b85cefc5748eec9d7ebab1e9cec57d580b3d66e5b47772b1faa267eb7fd4, + 0x961d96cc4f121a184a78db78c217fa96c22521ef88e9f454ae88ac934832633, + 0x2d40eb8157494a91a99a67959fbefa10958f2f96111d46461d3abafdf3f89735, + 0x21807e2e88a4f906a998c7d9c6a395aab2c1a09b38878f047cd59a2e61f8f85d, + 0x2e19eaca5d16c8bbb6ef892613aac237eb47b65c64deb2d167904d719edcb77a, + 0x16714242c7b7e789d41c82a4c9722d57e294d6a566f6a48cdfe79123f8c1d32a, + 0x5566d38792f0671ce10c1ad7e93534075f422f61928eb6c2e4857e2ef1fa242, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0x13290f24b105f48dac27734782f076151f3192c0f432da08f73ee09570c143d6, + 0x1b4b953ada89454c82b19e887dfccc01784fa68082bba9a561beb496f267eaf8, + 0x2613eebb5f02fde5560e2f1aaedbe7ac32199983ff9ba2cedda7ad9a6d3855fd, + 0x1aec57bd5745a26c3c0219ef96fa6c69250bf9b6584e371cab2aa2bdb7ae4990, + 0x67389e348c3409b4cd299d8bce723984b5f2e95b0be560fc10132d8ef8d3e85, + 0xb0e06a1e7dc543f9187aba9ddaf2e32d32ca8b8a5da85597e6ee5fda0c9eef6, + 0xa1fb4cb7fd491382e2cf3347ce4ac8a42342a72afd1a1e64eb0ff970f54d5f9, + 0x1977003ba614ea8e81991f6f0d79d62feec3b0f15d20d899b87382fc3fb13aa3, + 0x286e912fa4b01948dd7b1cc0251084aa96017f4fbfcdc6c743feaceb1dea753b, + 0x23370231ef55f59d8f37515ad3cad730625e79325fb839e1d9e9c2d1630e6ecb, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0xb1cf6bfcfeb3cf344f8d1038fdc7b9faf945027ff5bf710d10286df9cbd4ca9, + 0x123d9a409d14c996b914c9a56c54b02c25f4a33a3ecb6066fec4a77c6525acb3, + 0x89f21498630a31293ede8725da4179396e31708754f8f26935a9593ab1c207d, + 0x2f5bfc653853a2d74ee03547dd49092a78177c6bc16eef3d4513709040705202, + 0xa18b08811ddbe006ac8516b188d76ed6e8abb635697bb576f438b5eb234729d, + 0x1e0fb18481c8d9535410561b4ced6025654b74d7caac3e4d487143d74155f7e8, + 0x936106e344c77a4425d0ae924553340214d5264abf959ff5c3de4cc163fac02, + 0x1abeb831643365e91e7266135607235fce484149cdce1551fa4577791ff62fc, + 0x22892af37e8064bf4d88322256bb872e0d733c032d1f7beff2bdb749fc0c7d5, + 0x29b830534e780d7205e38ca2f9ba43ea1f1eaab7d08b6060a9a8e52e1cecdfb6, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0x2ae98ec328e9150679a246222b5122c2c2e35d2044fec7950832b9774900bcb, + 0x155494f37217d033e8d586c6852ec501c6dcced5096404877c788f75f09c95e8, + 0x191c6cdbbacbbdf644b3bc357fabbbb79045e3200f2d10f824dc4761ada0db41, + 0x2d0f68dc5a731e30aeeb23a76c2d985338f7cf7aa1db7452ab7c05f6b96a1c12, + 0x8761ae31b00851939ebf81f3201610f53702765e42367d15a5a64e4fc780e75, + 0x22259606cc46b6876ed844c436ff76ee5dc734754a91bfb977d2ae9f620f738c, + 0x290031eb3efbfdd567219f6f69b6ea098dc1c7ff13db57bf22c699d9061923e, + 0x11a164ee321faecfcd283c24baaac523e609ad4dd6f6387206e8083d8ba2d08, + 0x14a6a424876b86e06f8a891826c3393bf9a9355f0f705d61c39bf65204a488a0, + 0xe1d8d72bd4c192af2d73279f2b7cc893ca0be9b313f90eeb64a5fb69e7a9771, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0x2720b31b0b3687a93e8203819f9fe8f41591cc67bba0bd4c050339c327d0a6c9, + 0x22ea080102094dcc01da97ec17bd1c5ff0e61f1afc3567ba2a4c79127e16e848, + 0x7a0740ef451bc5150556d1083b5108eba7660ba47f5cef92df76ad0cd53fdd0, + 0xc191e9d1d2ac3648df5a9fa6a347c9ed3c01a4176091e91f8191417c885b674, + 0x21a6605ece262ebf5658153119ada85793c68dceeb560782c533e7143c53435c, + 0x7b585c00d1974dadd86b01acc175939143e66f0dff55a7263b7f70507294f4c, + 0x30570c2f5807b56cc39cee5e1164c58506d902a348dd400be3f3ba1ea9b918c5, + 0x2724ae7cb7eaf7d39b6ab671df9d70a260fd1691cff81987460d2c19f200fb9a, + 0x112877dce9f6f179eab02788c44fc9da3d64b99966a71cedbfc4d5ce1606ee80, + 0x3006485215c00900e3c42c74ec9c58c6fca0047827f238431e387772a30febcd, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0x2f2b423c67329cc34adc75ef955e65a6ecf5fecdaddbccc7c69de3a12ae457, + 0x28020df7c36abcaba69762a94eee88063b5f132efc9bf99a8283d4fa34a7a1d9, + 0x1c1e47e09591c1ec91b7840a307819d89c19a567d6e3eb2f8fce818bafbde9a6, + 0x1a84ae16924b521e378f6db619d0a094066209f18492b604c6a8523d9574a4bd, + 0xf1f1f4fe16f636b8fb7d1aa4cecd1846bb37f73880a09eb9680ef2dc49dce4a, + 0x2033b19b71951e7d180851c4c0b54cb8e3d1df44ad55e08de3c10555ff434c0b, + 0x298497dba4b52d50c528b089cf9f51b98c797b5f9f1893df8bd71d6427957ca7, + 0x7979509bc42b0bd1855c2feeb4890c5a2e5cf6f6cbad87558b11b82e43ebab5, + 0xc027d8065b422a5d05af6953119cd1451ecdf3b1c2b49048bac9ffa19a29571, + 0x1cda0318f56da08e42b609732f23a762831ee22bd873a8565a2923adebd88e76, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0x109f467daedad2bbc6b984902be029aa07e7241a63ef242966db9c5b584c39d8, + 0xdf1e1a43181d21009c9873cb22a76337ca84b8196432cee8eec9975c3c1b9cb, + 0x20e2202c033befa6d32f13f6b4426e40121c40ae7cf8ce57c8271e0d7e5f1315, + 0x8fbc9206e82a3f139c8b86fd5da23bf86a2f719c6b7b7db42c10c62a0280bfb, + 0xafcd3b41eef210253ae3d684a1f816f6772b2f253c2ebba5b444b8edc05b775, + 0x2ad7e0ba8acf03ffb2fd84b30f89033119d3f34236df92d1a985d3a71faf5492, + 0x235b9840306c9bbda7e11c12ed8805fb2de3127555334e216bff8defdaf3fa5a, + 0x108abc439242ac2ba789aca0ca17f761aaaaa7f90be1398627dd51a5b5385f50, + 0x64cfee2a05138648491938218fb9c287038cfa0f29397e83e914f355e0f6efb, + 0x169b49780138618a4ac7de6e164f1f8a95dce8dbb68be3737bd1d1d17601b583, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0x37c1010183f05d3baeb2407c7105539b59355e854ee6ba69ad0ca93ffe304aa, + 0x7619f4a716dfa87c4180b37779fc156c1380a593cf4686b92f519e35431a0db, + 0x303a616ca0c021b513b39d551877b764b241e582140cd49c66650ed748742f6, + 0xe0a3c66b892792aba5936d212c510a929571e260f7ebd7e4d8fda17bbd6e4e, + 0x2db87865f56b59e6db18e9fa23e4797466341e3114f73d04a77aa96b0608289, + 0x16b7dd14f376839839b33d74035959e364029cb5ffc4a5197cf2f6654e07f9ce, + 0x1282d2dc0a5418205d397ca3b788ac90b617ab48777a3d0754f288e105bf0aa1, + 0x137494fbdd4f68f089812314c259f9d55b6f2ea9a5e01d31df36953bc67a6cd1, + 0x27939a8ae7cd5b8891f1effa260b4003c5d1f3588ca41b51fa66a15fbef587a8, + 0x209d342ed11c9c6a95f7beba1d6ae606dbb91d53c7b125329540632856980819, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0x2374ed44c2bf10061ff872112598b048396433c0e99ee618a978d7b52eead11d, + 0x5037cf03e8e4060b62671b6b3738c3326b57462d2df714d312dc3cf902e3499, + 0x1bdc6d72769d56d435d2664fc00867d0818ca90f30791fd9b2b1e397f018879e, + 0x125626a10725e4febc2526fea8f28eda9fc9facdc3f853bff34df2d870b6760, + 0x6d4bff3f90a1436f9eb4cff6768bc95d0748105b6bfad3efc469005b74dde6a, + 0xa7e7d0bd3eabab06af826e769285f473ba07336539872edfe4291e7d10f8863, + 0x5b7eee126f854c941925eba6d02d796947eab9ebce35b78f94b68068b8e2577, + 0xc787497b88a8df57e716224abfb8238149ee8cb2b41a30452ac5c8c9ea11bcb, + 0x12e46e1b82dc0fc451122f0d73c36150bbdac4266091f6f16e887c29e6ab3e66, + 0x13fd578c074db81ea352cb09285b53d7e8e9979bfab7cdbe954f2ebdb014c9f8, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0x9d89ecd0e9e76d53bab1d004dddb96233658cfac386ad366c614e0b270f97d4, + 0x1663ce3fd8e8a219e95598524d0a14e95ec2eddbeaceb5c91e3325f03b811cd1, + 0x2d7643a55ef8f191a8385f26b7933068bd8691d8bfacc0298edd54b5da3a81b2, + 0x10ef304c05d0641004092988202bd102a1b76a155469ebf41804b8556370ca28, + 0x2058baa454c35fe9ee8b0a8b6c3579e00d8dea44db1f036f286f8c1c5a489e10, + 0xfe297ae198ed7e6fd6836bcbc60670d9fa40d8196e48cd5e691b04cc7668744, + 0x1dc4589f1ccbbf2e48394a90cd3cb121c3bc56576398e14b37f117f3588e6156, + 0x2531aa8925a4e146a2178446d4213afe2b4bf59537090877084e08abb32b46f1, + 0x2b8d6fb09de987c69fd1423ca5ba68c7e47f24326997ee6ec06b27bb8202fd79, + 0x2cfa7103a4e60296297b5ceb2d5a59acda5b0f1c33c19c941a05b9c310f25ac7, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0x10202be4306b5ec29ef575c5214a35a3ebb8c8e808c572c87ebfa388b13e947b, + 0x1b5aa16b76926df627ac1ec6f6c12602520e67cb23106c456063e8faa4b902a4, + 0x19a92337476b5856c088850149772036f311a5ff94f05442f0a15f23c5c4df81, + 0xbe8fc498e64abe93a3891dd69b068a200b4fff681cd1ac1c8b6c0dec68489b8, + 0x1a0fc42aa273470caf30582564186291b8d122dc036309656303d48a9c3d5547, + 0x18db0efcc7f60ca3fcefa9809141bf46c3659de012760d8a1002f771c77971b8, + 0x1237b3bd8e9218944b33f45ea4c9e7872be40e3d71df354d0b4d22424152274e, + 0x65c096251bd3ae0ba92367a9db4753b90bac169e7bbe2da1a23ae3402e45d27, + 0x1dc83ef066fb306e222db36b1b368020ed31d2b1589cb6ec2e84e406213c8e04, + 0x2c1a8e6e5fbc28d95ac7e784228ac12d2d28be32c4fbbafbf21c6ab0776f449a, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0x17ca0461bce08a8a8853a8f49f7e9f52ab8f3d8a7cb8a925d4dfd834a92005c, + 0x1c90c977e1daec74c1d7e6d3ed14c7d41a17fec6d1440fcb3cfde4945ba43b7f, + 0x9f6aee2e43570fe682544dcaf6efe50f273784349ee907a7da08cf0a3892a09, + 0x1a9e810a073d7982a50a4a3ae97e16ef3cb1e231fe0aad228ddeff415e873d34, + 0x25fadb922987714ac135457abd253469ff387847e625a4f376a21f60c54aacf0, + 0x11b65d5a4e0393733848b5a18f5ba22c9df6667e9b87075de2dcca2a6322e980, + 0x22e9e700cc820ac9dc080e94407b9c18adc135535702c34b64005803881d3556, + 0x160c88605fad7ad65a5b926dc177fa9799c951ae17b067ed62b06679a4cf03f3, + 0x1dc2851df6d0947e5b3c9385544d31278346d45806328142b6d3b25702bd7510, + 0x8a42ac9c651c761dac4cd3334d8ff8541ecbba391cba04f21505589f39b4d00, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0x289fa0e8ce8df0c60be933c0ab3902f988a6a59adc39dd4d87456c88982edc70, + 0x1e70c2b91d3d44777fde9b8672508185789aa7af7d0ed1b3e08273c02eb63201, + 0x26202efdbdd93fbc22b59bb52b001dea2076ff49c1bd9aa0ac0e732406f85362, + 0x665130b10a00cc5088515f8e16903ba3156fa42285bf0b9d1cb845209425be3, + 0x20a044a5e1a405e1ad5d751492516684148b3755b1fac705fd6b6eb666fde2a, + 0x2640e021b9313db742e534158b3737b355779eb05ffbe6257bf3a96ccd0ebefe, + 0x1937f02a9ea7e1700da7773129f32911d991f2b872def0f10a176054e332ff51, + 0xb198e0da024b3dab3d6e79f1e1a0304c6055a8ea3f4f93b0ce24c6ede206873, + 0x2c0a30d51449d8db5f3dfd12c4dae7857a91ee88e297208dc151ccd8be4f0870, + 0x187c5f8a529149c6250007730a57ba31c7dc0461d40fcc17326702020a21d33e, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0x2085c1bdf91d64b88fa27cfc4c08e07efa31aedd384d465f558c3d60ffb0565b, + 0x25af25414fef41bc7e5f3320cb78b1ad4532319473caa7cbad0cebd1a77a91c6, + 0x1a1b25a6cafd3bd28f97f314456566c05ff153beed81b1db117f20ff97f132cc, + 0x2d9ab0595a2025fc0cc0850b027cbf4d778dfdb36b3f49fae8029efb2ea63f1f, + 0x2f30cc9b0e5b85bf04d9c921c26195c7431a50a6fedc28250bad8d5cfdae1d39, + 0xa37b2a74bd14072efd62cb285eff2901ae78fd90dc17e6fec4676cb04f244ac, + 0x1c424788fca025dfac66c90118b11c8272d4d68e315879b3bad72b595016b1a6, + 0x20f5240469332dac40167ee37438a75bd816dcc1fb4cce2ac7fbb77adaba5be2, + 0x38722e06b9b7d6ba8232eca553b288225456b08a94f8c0722196654430b5221, + 0x56eec5b756d6945d7f1ec8e5147ca2765ea9bf915399d7110f15bca953cb8c4, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0x27f0800ddcac9fa1f1cfab29f40c24fc7d4ca5b1590f2610520e88b510a1ccb4, + 0x1a6a8f6f7e612f637ab123355dda1d4bead9dff6643c35d5407652a392e70382, + 0x1b2a744cbf0e7326885b084f907e7756f3212136d607d074486fe4ac707a413e, + 0x4abaf721c7350f1696a88a898880c58962814c3821b12fef0927677ffead3a, + 0x2f194b7fb646175f3ec81abfd10bc33c5deb6b4f69955d8e37f90d5619bb1f96, + 0x1457d0d9729fd924f98a0ab82c379d9e1fa349c99ec5d40866961486f9c9441f, + 0x24022debb2e2b1ebc444755063ded047216aef7a53efcd357c33bcf18abf7d78, + 0x2f1a9fa9fa2d06c6afdfb03865806fac1f08d5b64a4a4102dd69b8ffaa16d9f9, + 0x2a39c8affd2c36951f2d65ce28583cdd27e8d09b3c4682d9a91a8e6da20f018d, + 0x6cd4a8162b4407a90a632bcc6e13d25a93501cd27df389a7f8240da9d0fb308, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0x240bdd87896f169f78702f2fddf10472d1e56b0c8dca668c3be9c5b9fc922f8, + 0x3cebc8d717886a58a2c2a2bc572e3f58922c19e6a8026dee09a8aaac59d9170, + 0xf2ac5c2f8ac681e231a623034707fabc5e81b7c766c12db359575e5402982dd, + 0x2dc50cb75530f53c584f0db1885d6c1fc03009cc8e8f8abc50b5ea096d8cc1f3, + 0x94c8952fde36c4126f4df8518ec3f831fdd80129f8fa8ff1b87d7739efde02d, + 0x180e29433d8dc3cbc26a9b063087678e5b7569bd759c2173ad0622557d942c0e, + 0x137513995f9a52a60cc08ec51aa5efd1f10828587cea9b2a5d016788021bd0e6, + 0x102c8b90ff6c327d16952ad18bc65d9d6efa7dc421443ff4159e72b02ae2cf2f, + 0x29f1e94ed28f72023e6584dbc4a4c090c6c5ee310d8b83f0f191ca9a382e83e3, + 0x1c5292bf3034389addc954d33494f4231ee9adaee58686e630548ff0eca63191, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0x1430d7953574889945b2851241e066ee9d6b5cd11c106e1fd2093d691a164ea, + 0x1b3448e3a38b05b85a691e2df172b46c7501f3ca292b5f484dab6286f4a23edb, + 0xdb96c5859d2163a39d6b3ba31694b603706633accf6529526ed570fe019f001, + 0x21b598a7b1f1990081af12292ae6d85107d314c05534cc1ed39f7fca3280fd0, + 0x2110995ecd4f7cae17dbb93117661040a5059bd20650a990dd6781e6e773790e, + 0x21893b6a2b4a66316b37eb749dff8ca4ee17c8bff8632ee3765f7f8fe572b0c4, + 0x2ccaf308f912ffd14b46f30d8f8e2d4680b6f3ca217587a4a6c1c1bb840f3683, + 0x10be28be53fa8a09cda9f67606978013149dd78dbafc39b3e4ec0ff2ec75b2d0, + 0x17e826d4b7b4a2040fcba809278bede0cd4a79c0b0da81342163270a1422931a, + 0x9ece717307f52d17f18b7bd204324209c011daf9ef789973e69f9f9e09940ef, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0x21c512b8be5a975e58cc3dc195f284a90a921a264c67f8723a5c9fc79c4ee590, + 0x1a9c325e96a34745f686eec8b268877ba7aa0d44b11f59b4eb11b24ba30ab1f6, + 0x256c5ed746133373328079945658a21927e576985c8c26c42fb0e27a37aeed5c, + 0x96dd009241c6a5a268d535f5ea13cb1f313735cd9ffbd97f580477251073fa7, + 0x1b5697a3492346753e3b41b5f690f4ed6cae7bc246e9050e461154da63b72346, + 0x212e6acfb305068286ecd6d2bba2ccba4bf952487d7db86840d1bc35d1890834, + 0x188957819ec0569d19dc54c6a31fac77b75a89c8190ea57720a7fc3f7e6a4917, + 0x551b30aa085a016401370424d8ec7b729442d95c263ab077ef1f717d805ed6e, + 0x22883b03ba4694c2602c5e0c148a2d8b142da732f2dae3402732527f1a57fcd1, + 0x53a4c4b2055a58c5ccb0f23464de37cc9c3af86cd2347d821612c4b017e8e25, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0x12ccea9183993e5d7dfc16fdef26d9f845eed10de2fbafe63008e29d3ca8b507, + 0x582c12381fe92ce0cb41392d98cf0bfc811a96519d717af5ffd45c6ca1679b, + 0x47527fea0d1a194240f9d9f4c5198bdd620ee5041d2dca5db40375fa6ec11bb, + 0x9803bd526d49e31dc0fa4188e3069b7ad81f2d6391934de41df4aefced4b086, + 0x21d3b002266d0893a5e7c1a7bc7ad2f2aedc63bca12b0107670b271010c2c177, + 0x18f7b09e05bf3b680428a2d2baa51298016ef23bb71ac95152bf75c82ab4cd2, + 0x18bea4252cbd7815e4bc3bd34b039be2027c226b930eab9cb0714c2ee80139a, + 0x100f77a4054eb625b22130838ccde66d21c66b6a4bf8c8b10edcd1d48665b7, + 0x9c8b96501ea765284653b0d464445b012086366ef33d57e3a9e388e740233f6, + 0x6c9ac27ccf47da2979230b1b6f6704a08a30029752acbf49942c1962ea2f9da, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0x68dfe569c59fe117f04ca4d04df9a59ce5c9327ab88894f60a8433cb3bbc7e7, + 0x29e21c7d1b3fdd04d0f89e3bec6e66c41347183faa487a085bcf1ad2a446319, + 0x61ac0b5b33b8d667219f7663fd68c937c548d342bc27e5f398b8f12c4fd54f9, + 0x2e8eaea01526ea362b730fa76697dcab6f0298fd91f0ee145ced504a164bfbc4, + 0x1bba6639ec598530de2706ca4264f5b42e6ed5374993f5517d407f3a287b2902, + 0x1da74a23eb1fd7db1b30cd5942ac540c379bc74a3d1e51d5b0bddd2087ed100c, + 0x2a0e3100447c818717bcadcdd0b7d120224d203c8d9ef48064d7b97f6aabe593, + 0x27753925a34a26b8a301c8531ba88815a976e1836858e054f90d6561c4373330, + 0x2370d8627c27ecd31b2b6a93c33ad409a2e785c8798bc444f361d667c59417e9, + 0x24447e984cae81901b8c1668e8a11d94557b39ddf2aec74ef457701e00d51e6b, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0xac0847e3de8e5f007ad7427f2555515e4079bdaf0b0e34b4be5e541f482f33, + 0xb2c4754b01925272d1ba4359fa02c399bdaba806b32f51c2285e2c16bf3316e, + 0xd33fb4ca1a013eb65ff09dc85098969747083ddbaf4e0093d86f29ef3948fd7, + 0xf06aa40d012cd276378c356edd414c02a77abec6bbbe8520d90b8ab96be7304, + 0x11620ba3b59e9e02401b1023d0e3675c1a26d896908931f88ac8f487cd408d26, + 0x2d1783e31f3c242476318403db851fb1a6b826651ae10aa2c8c6cee8b71e9bba, + 0x2c989d933295a819e388cbb736f1dfc008a813b11500d7a5d75c3de45443c7df, + 0x185d645f3186249ad6b20d2efeb6ae61ea7add22139c06f0fb143d4b36428a6a, + 0x295390e4301ff52cb4cc265685900719cf785fe42fb3fc7606eea8402d2c3be2, + 0x2cff591766f8ed033dd1004a216c9545cb1be5c235f59ac0189845a3f0fb623f, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0x1d2f561702487b43d9f7f6583fb8a342c82f15053b53c2952a7dd2d32491d880, + 0x1431b6537ec76dc2c30ee7476301e832700ce7f638553e84cd6fce7d6f14d7e8, + 0x9f68e9512cf4368a0b526aae1af2bfb818655c50e8a87dc157f83d79b409a00, + 0x2e07015e39f5f8af17cd2d0d04a76917c1b6c30f0b3bb3c35a24d099249b17d, + 0x22d3936579de1b153c68258f36a157477c7c746fbdc4f9f3d8d0ab07d651c28e, + 0x1c1511375128ea34b876fdf17a984c28f9f5f551b8f5008a559875d627caee62, + 0x142882177b08db528d3e30ac62d3325ceceb585c4cc091e5070a79abc3105fea, + 0x1a168d198284cb1386879a2642bffaba7bb7672c91bcd6c562be03e3ab636179, + 0x17221d50c79b06811d1d66e63757c063ce62dece8b1359c38932b53e0c199401, + 0xd1d4e722fc75c3f4931701cd9ac240a172a8e3b638bafba1c99fe987492809a, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0x27db073487a124e2eef709dcfbb41a62f07ee32aa952f69af50ac486b6caa7d, + 0x268c8bbdaaee13720df617507518283e1758788bd916fa548026485c7aa9a0b2, + 0x1fde18979072c0225095c73dce75c99e7c0ea3164cedac4ee985f4dd029b9e95, + 0x2531f077c0a77c6ce0ca7024c5b150a41489e06180688904997855777baa84f1, + 0x294a5bd8cf93bc687c0568c4e29e516d90acddfa5ca2c7df81eb09286583fcb6, + 0x294e322170c9ff2069704807e64caed0a0e9f31683641a3012e867f5e913559c, + 0x2b3addd6cb0f23db00d6cd79dc8856992da36e648e3bf0ee0b2715d785d5b4b4, + 0x3135e79314a76a13df9cbfa22a7eeaaa6a5d2441ec32edbad2396c270eb6003, + 0x173a562d9eddfaf8ffa687c362e2bdc39da36db4a8557a6dc851055a2c48a2bc, + 0x612d864c1ff73f7b2d780725cffad529426a6e1aa5936875bd9aa472e7829bc, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0x2ba89301ebfc123b4220c6c74488005cb752c72f7487bc8ef630bebbd41bf6d9, + 0x10fd2909f9f7f2774720ce193a4c009bc92bab7f27f959a57842b3cb2f10e622, + 0x249c1b33cde3144fb9b9bdf30e45544cb98bb9304efacf2adbf1271d59bc00eb, + 0x75727d6b84d8e427bb742cea7e88009c286e83bd66e1d6951dd7929dcbe3621, + 0x1bddd7e537992438f10091b25a5225fb06132dec4ded9cbfeeb451a034acc670, + 0x7ef5e8e55faf5d9129f012479e12e08834b5e1a38ed28aea583e7ca6ebba680, + 0x14b714178fc8031d847db2e05553dded47111455674598347dce1ce8b8ce4e5f, + 0x119e1cb2a7e4cc688569e9b87952d4b229be2265a58ed6e619aaa93f30c38f0c, + 0x21575c98afb0fd8dc75ce88a04201c36aec620f733d6ce71bddd6c4dae189c0b, + 0x2e69188594acabdea88e257c19b0aabfc728d191a931d7a5f4e7ed8370c24fc4, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0xd30b0f7b463491b93ef9a20562faf35b4eee1b0dcaaf84964b850c3fa9f52, + 0x104f6ec28eac4f771576a7ec410980b2fdc63c39d1b90c3f0e721847209e2025, + 0x201753ba0a0a888b66ec516584f333b4cd1f57c164b75da22519a89811dcf077, + 0x16fc76f1f5f7644de6bc79cc484e010dd1da3d0631ef42714cf5dd21f59ebff2, + 0x10892fc5eec5ed00fc6d5d0975221d3d870685367f211ca576706cfb083b49f7, + 0x1c59c9b6844de29584ac93a73022b6761b196e0041e3fa32f548373a84307ad8, + 0x188a3064c72ee6e3b555ce35313f73c91a154bdb59e57fdbc95d286df429fb64, + 0x25a747a9139698f6b090741ac55c98ba3e55c845dc8af25ad83d6e48c945e249, + 0x19cf0ef78c77006fa9f4849ccfcc2c52dd326a646a5789cd25f79ed84f5ccc09, + 0x1145187227de632d3deb1d625a4e5fe3886f5103ae46615a8f07e6035f65397b, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0x12606f5141cbc1b9a349a9121e54295d17ff69f2f9027bacdb0ebc8a6dd2d0a7, + 0x2d1ec807263d78373ca6b3aa8f4c51ae94487ae04cb9f5fa6cb7a6155d44cfe0, + 0x2b83ffd72f83ccd4c18dd16bd1d406aee308fd475bf706f00cc287d9dcd97283, + 0x2378c35a0428264b3afafa0b782312463b724a4d281a0b56ba6036abb9d84c46, + 0xddba7feea2855679ecfe13432b420858ab5d93bc835c9a0ad59b8c011fc058a, + 0x60a0091b5a50a516e31bb6ae3023d902a23e57efdb4c571c143ad6321304673, + 0xd08421d815f9281094977237c6aa7e6243ab5cd76e38d9df19dd2b4a62211d0, + 0x165a3eeb547af156b4be28850c24586c0733767364429a0a1b7dcd2e7f99822f, + 0x2367643242f32a40574489345294604135469a362e8f6f8717c381dbef5d40e2, + 0x303a0941f18aa3166611976111e43a94d92f51f6fbdaa07557b47b4680a21af4, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0x1aecf5def09ba5be2ccd968996c5564145f38f60aab4191978db8089fdb31cdd, + 0x304ebc6fb5252ad8b42ca58356799e8c6961ac84708f8b465227103259913243, + 0x26ab128903aa48b65d12869a85697da4dd7dbbab09aed508b833a398855eaa29, + 0x245567a4087a5582bb36dd3803f7008596ac2514a1d7380d66ede29e27823942, + 0x46585da7e8d6c6cf0ff92b5e3394bc0499808442cde328d13646b44a69cadaa, + 0x12be98bc0a25716e254570afde08db45e96e159a86d7d1c685e1eb2a45a4b3ee, + 0x1853379c16580675d773c80841b8b6e7db0e8a2b97637204619472145e3ca760, + 0x138cc77819364fd983a34eb109c53295de653f1d905fd2de7b6f80814fe8cc0b, + 0x2db2fee2d496891332218a6eb709848a819f62b8725482c591bceeabc1e3fd43, + 0x22e95c3ae4db1cfe5e4cfb697815697cd9c34211c65111b8fe850ed25958057d, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0x14f0f0699aa9bd8326bbec5ddd0bccbe3a7caeab685d9ce7883e517164bd5994, + 0x1815774675d576817db84840bb9fa16b713472d72f4bc24c2cebc09aef0c203, + 0x2a82117a43030418e52b708eb696ab01c9ab04396eb53a3ea4194b9a19824238, + 0x1f02d515206f3d9a3c2086b2d7c6b19004cc8553a77908d534ad0af83a637097, + 0x3dd5240ce1c5530fda4993dae13bc07bee4c7994c1f65f263a2b8a2f7bc9db, + 0xc414ca1ed2f718060876a21de201d87b76f6fa224faf2775ec99cc13c534117, + 0xab48043b18014d78845ac07a6b9727cfe0b283b44404e20c5da462aaa24f7cd, + 0x3fac53034fc748ce7cf966aa1f6bf15445cb4f6f3a4a929cb27ede7928667cf, + 0x1f91737266e97b633fc63e5b0e1ca82b486680cf677b132ab7a6b4ac75f70482, + 0x2556e1170d24d8da980464376850938b361e16999f2f628e1281f5d6ab0b13f8, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0xd258cad10974250f6da3a9e068f6830d7c65f1253ae250324bfb72b50ee94e8, + 0x15e2bde6eee969fbbb22dde530a8e6117fd640972712b644ebe5b4bf0841fc90, + 0x231dd2a58fc24a20243b93b6ed5cf8b88b7a94a4137961852fb85a207b6e849a, + 0x4fcf48ba86493a6ed7afdbbd1b74fa91b715a0cab2e1cb27d416d1cfd220258, + 0x27313c2f8d4e5dd6764d672e1a6f951d50083e4e404b9c1cd22334e7eed12f4, + 0x1e8cc36fca79a1a3319d34db2305478ce58717e36f9710873528b16d4f0c1a22, + 0x266e3f3550eeee1d1e2931ff3be33ed142df41311f650e0704d1a333b0bfff52, + 0x88acc576b7bb1fd00b8e1783f7a48b72b48a529e130fb6f2f6550f41c67ae65, + 0x145537172cb306df020f911d46eeec82af8134b982f00dcad839c3c10073b1f1, + 0x897eada2a51e4cc2e55be2bab91c68a0d1378aaa4a65bd985e22cc675fae8d5, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0x1fede8462b07d0a305d02035683cf29be572a53ecfebc28c77d17ff531a0e873, + 0x64cddb26305c79f75302ceef162391813ffb575b21526a2a99d4d05fdd904bc, + 0x41688ddfe25e6f627d365fc18d74efe41659d9213f25808c81da4168f465efb, + 0x263065cabd50395ef40943af93df5370ad2f6d17bb6de59b3e8e7115ec56b82, + 0x1becfb943b8985991a66c0758322e4c3f22632c199c1737f83a7dc251164a730, + 0xe01451b1ef92c997edac826766a61525bc9a345dcd66955f9ff9911b653e737, + 0xb9f01062d426904168cf7092d57e2c86f6660111475f9978f6b0608ad2f2278, + 0x2f9dc8eb38534652d3eea5e1b8de7f088c3ea8f9015ae1347004c3122256efda, + 0x2d97e9440f1fca57f227bf0769729d3dba7fe6cff7fbddcebe492e1b1fa1557c, + 0x1b0553d2ee91c3a63730d686ff1a53a0478682a7363ddd4e7ece42ba0fe0cb2e, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0xe83184ff6e43582fabb4d62c346c957a365358123861b4061670720703577a7, + 0xce4cb25f594fd996c28d4578a4a8e3b0581299a6f165882fbd1ddb2d85b2ddc, + 0x585f5827997ef8691078d8ab635cf133358212340599c51e1bfa20c93226056, + 0x29bba7e4c28316d70bafc5d05ba5a97bd5451a127ed75d9ef2136a02fb0e75f8, + 0x5e8ce714d85ecab7027dc4ad12c3a5e75a211e771db239df7b3f661658d4d08, + 0x1d243f2bab7712f5d12fcc7e4239b39bc533ba6d7e1fe98779a5ced87dcf0f64, + 0x19207f2711d65bd5cc7d1f5afc770d74efbadf057865e27efe6e61db2a83f1ed, + 0x54538bfb0b84e707e000ec579bfb8d796106da1a5e4abfa8a273141d6f6ed, + 0xcbab8595eee6b93df0d9f2545d61416af5ae2dc55a4f332653af8ce11fb42d0, + 0x1dc6ca4abd54f254c1f401b871501e022c4200688e661613926a63ce19f78945, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0x164b183c9251e3f103a08c44ff9bdfdee4a7f8b860850fc3b0ddac111be2c24b, + 0x80435e71f368774466eb276b7cfa5f9a7a4b90aa4c34e1984fc4998816a9fd3, + 0x24a82532902cf98917319ef392e49cbd1c7906ebc78d24a4677e1014ceb98c83, + 0x9f961322ffb0b5ce846054c4c6dc75852776dc8dfa0c2f8b66229b3fb62fce7, + 0xb9af076f893d939a48902f2107976e8a8875aa5369806e57e8c1f6fc1f5527, + 0x6c40239edae3e7600dfd00e6cfe939db8a69799a826ab5e91f035e971232cd9, + 0x24701c675052c925f2baf10f661d4f719bf145893362632605adcfbdf5acaab2, + 0x11000d892cb37fbeb8e415c01e1cfc25cb3a25d287aeb67b247d0efce56c3c29, + 0x2caaccd757a3146300021050345effd1a9e5b64182e1cbb67653997b0e391086, + 0x10d9b51b3a086b412b1cdca5ce171ada65395036badcc79ef33f84aafe908bfe, + 0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, + 0x147c39dddaed8630bf1b92249600016fdddc5e9f5f08291ca1663358a41d3dde, + 0x2d25d39661406faf935d340fb1535be9086598121d96d85f84cb586880517fc1, + 0x1a2643c9cc6f7e74f27ecdc2e30158b4a6510773a5aedf52fe9fef5a2261c263, + 0x2d5d7010ca67e74c9a4d54c50188de26c802a2e02080d6d352fd3d5b5682c83a, + 0x3060121bf7682a4f51292933031818468d050b84c2809ae816f14340a635bc10, + 0xa514a5c227f4cec95dfa029e8dd124c34895aa46bb27c0911f3780d5015540a, + 0x278bb49a7b4e44aea46eb0f882cb692801a6e60fdd5b5c23c63cd65ccce4fe0a, + 0xc399e9f67aa40707a203feefb0b958bbdadcec5ca34901d253d026a2419f6a2, + 0x1d6b3d5f6ea369c26f825d2362933eaa31ea35ec0a77c1fbd9e01ca1523e4432, + 0x24be510095436206dd0abd0b0cbb95c883ab304aa52598b1a69306ec981a688d + ] ) } + // noir-fmt:ignore -pub fn x5_7_config() -> PoseidonConfig<497, 49> { +pub fn x5_7_config() -> PoseidonConfig<7, 119, 819> { config( 7, 8, 63, alpha(), - [15193892625865514930501893609026366493846449603945567488151250645948827690215,8655680243784803430516500496316192098841666200175185895457692057709359214457,11710807066713707084726423334946631888369490193496350458331067367713412617049,15442364818086019103203999366702499670382575019009657513015496640703659810202,1358747428976145481402682338881091555771254635226375581638965497131373838774,15658002471767984962034589730824699545808755102240624650914676102923421241582,6420480504329990097173256112095253518339231893829818344055438052479612135029,15457172495394305353698644252424643614748461590123908880271021612601244389162,5745943350537490600340174787616110056830333091917248931684290284533019091654,3877253492903478989342845512796806320713689655633086736499730391667425329322,11257677301507982757739320943403112189613848490812422490591766717141506751601,16906586852467953445509312290627525856126394969718997799028223470195783329296,15263589725854108297280528692120758129000336125328939290924952731952242586386,21735940039489460025710098364749096267519151075908323637361429746399161905338,20023056608360522105358681147781839024069418874082333862551226466128829664291,5677500725280079960679484373333947430817198394184436922575072427342643665917,3080516739494460477657748111767941482024045797587058388950619118994388252853,21486496065617100719537932626843898998311175055335457507845650282870586541596,5371049178920102602305531530023787518286335086323221270202212974241707302466,3074817222296007572297581554183445947239252698770067839721345984255386069425,19180807038569629573914331337874446591506172622522351734982093457681161813141,16937785199372956273358037645552299688842385008757508130180245705952406225194,1688218397616770248184651775433764527272029131542529408516364801909017591719,16315958669815317541884966612581197291281164499674338063931623110684590850347,6218230753007070123505625054833158632732536069700963073464625252554943737669,17774528060285257656595928889288330429565059134928074258373583886985960212139,16197131592052727313460949906369199026477758140133103701908949020106767192893,13418604038232148873269488320329340508522225417123160144993642839875173062296,7265658443160253752317166706266927598319661172006072732797351716897681315157,17200150079219747370109251547638276280610591698078334228421747259741754887,8627121890622175767416692555014275717515106888840919734160364408960047296494,14546964505431549758350267964924534495477687922558528647552728692912697049247,17132720822762740343718421124251772119916072270451579802112353604446214831761,234333065870376500756753915306346778417056884715946003873280290982247600083,18375643491701271245209094287106352436174133929245169725584150600992143374298,5158448692161567615645197008737390561357077078129599243188536485308363800282,614161645152783610732075198073600394068518413590650990586931263981193439341,12661793104597977909223565537293318966803153852970198322604479648383643541371,13041905650419760925682179803296711066088286278603171065755078690359168540579,15006023590144168506070897325649191051975999212058008674224953860265667513015,4983349941266961584317889823965291023669365981564144622292227613558024302012,482274340065333833495445682213681402212945945150526736364263233985449810602,3966893131006556898236790392613869798057510088913626163333804949895810673044,20923301526284527685000591080290190641416245135554916208054502046381491809443,20838692384005825835959734210506718428443540957544929066941550833051093000166,8282357714606447781782716442854085217089572080066047419459610560432999443766,5410651444876169088887579490283094453001167796545260026969919887357676973543,15276966646285075387317940436655285872037988805762800567413073418506412856419,15066911464727337689573664613158712498015597773345106524271610486257089622849,14583790985054968382519116885383608902981814292128186470697458065499359610203,12059090796146479535492139954279038037217093044815277624197659219529427760034,7273811886044732271171500579064359282424476926867187108258957006777685922641,1463086899665237074608503061872751147444637332808872866814340325832200880984,4403177494620214359779479537027014449448686844655371530169401219256448130398,10860968418848589590932601250051274256181778387706764281989724391784015147562,5268786978207139542368199165627108325282167169564314266747401266496556301775,10683355823176907476704511935094343405052640940909677712096702771871787224727,12998090263935761477316698114799901126086030852595294916463464609721875730852,21401280461419124637791689956622923839426783908187419462727763377498739154778,9827224472048063173905906705579289843819400982583185823840008976971109664519,6215804144039763858354471461864183189301201862376216122255322421321775987311,15461308489200344015891625455653488930440613755785081602434124530381300882814,19336334695450889400681207491394600659946256404722006637851709906131899294790,1712331165786355540802697725399423752392267480553199895882357858951999960061,18153038525983970702748717571053178456148003321236490384959117581005013333018,1080183517033034908031748897211289245459330899463186432840251241943892326023,8948022108193679628295152361559653763100984324221629445749311939820327674857,9553342289560502306921915013446606435600388298465288181461633559299564421155,12714965617376828547637017050548818007690047452402682720666099310241001848988,10945704657865102635748104464461970844653553427083981539165832149959193156197,17511714411688352203059545713591160825310809755917403629838415797949261359373,9253691969419856285051096287845246422848295397226841130282244592511676512433,12218945350859454581754463621617733341764245716874083264842931063272433793037,15268139709971695434346690496076067658968455677120655340969837725391575270485,7948825129295102283421620705853168119104356217418364837218892682579042520651,6887299291348589691868712194070626390224806410428583073294593431810559288717,3610235157455454109573625364057240708256027358184031380521552355839155549623,16532488069063334064099666525339953823111673083177894678898823509406678724969,19317517725107761280217103201908049748015068578935276576200982249386084367574,14980901224290526859762385599553818204548992110637275324411078408232697158492,7741797285700915051013289492475875831764653137095445146268474269974647962596,11964233864746181868467810392101989052496076326472717372132104394243614334823,12746657111181947224582102380049766839578185276220682311596480990298620200286,6408726946032901840418309506578019708113712492100046332894630652186614300568,20959261828945984489015610988397031913577918654575078054490013338416801523934,3173674599420546165852740604987014294355430358334465189504551707066179193914,16110281513253204315524614633789708146700074483476149119440509845258215816735,17135377580103690088853370572199271964414896742342749305424508776150797285064,1405769920008485935711505753346340073052795087429311991287498566024570212365,19088073362945853867763169651582894739272002359692597239222895238839593467749,19897231284455588615416169252449008151349728648961637517447194842672488184146,20476415629812014715153863754869742189693986277342067785614833846523246536739,11074321446706734150375041020583051611133090415774365192315805856051215270782,15231367549323128694183572409135806408519505225209496441892541205465727777072,10515952069292929457050921929301902464262874744159361114100398880194109971971,3216370118771824418364829250073852356774095079734089790620447714552849459645,1940445924652458480775282556203659335417827058983719042726494187979000691704,7899310668555694144370607061960060230071621529123669746309839400642332452086,3125410912833939638823760577011271607678545358020637189655641109813198731542,2980079409624774815878860133121670095839651294537928173829312563570356348730,3766498515736372882285796238406751547889526137955288498682767455795237989580,21751217522789414135074956130080241003845828660310903627224390345319859795839,4947229586642010378772262640583556676497656670779800090478805824039760706318,2168676839236948809859825591626629233985269801981092020040909992251312517552,21172906642114648036685108008020762271569381607092920279879047961076646303327,882675742500939602754673078407141697482716600335919344527751158504426951699,20942968937722199705624825492102184647835614761458159157410261242387423597787,21880640497503102067412608072166388563991106464538369680846671301780353850077,17593472026567804917122179982860735087124786197105685847979050530954084564297,4492875530722152383516030266828166766820778742874238188105265500984280376666,6799763500412433367637987497601148507907071065930142757525839585946238894092,7812331664758167657763399273963290017340604299019483750344476103319142702775,2222332747647756867926707541092465789402467819000336747029352557749400316077,20438798382149666667185974604464532451975024544676922060351031604444896151494,16155157103796724378615022758633778903205872772589663310774455593497441785913,20281325298063880945091623185126257485818350714264176365501683813650871716911,4922178080989486450454493110764936742315495846015561426329316977670113220071,19579063976700768282784922967523980346960151903154507737857728349662090787824,2458828873355000645851832396764221987760639423132968569631493912353159373462,21166618206785010755521994106737991950548963896649678270059527421944129497211,9131643699583013708059191290958290089892787165715294157378879201986981390031,1820371114511473946932363841206094088983972935646887524223011276305844153307,7264184404232663540867032945940974372967974872966180860960243405462016972362,11228656105550475045610757902396386402555430893045183008968975441800824215261,7151503559113638565935009743218857812859208253653498318591469659718664783964,16876040581364499037941813142092448836399042253618385783944016186340703846779,10334125383426918152464737478646460879481305348617711177774418125714273980769,18900559046103390399749767994653107625464807708680067464279674225251110804100,18685667289312169245526749652972366835289568864080726348092618145885982989561,19970582871354083670567197978171723431124602481748785146813441774826500485907,15873472427137024971035326229485784626398898771525077832924901475242073457867,9090803292122260583635467396769157643561973206888822931647063181944243467413,10156295009710074552070572489422360071526675259143523597882131082376797944708,18600630374968456966046654667577076758720435487386724419578803020365834014000,21292291483064245088298314957584631356250347533568992016547598449487977536460,2784266893057214755054197979675795184619614089277590464548240934105557638370,21206743389683892419024645604723431382001453245850423743581664552645211926469,7915761821775326316473924816837591351530533394717381318596295803119061411675,21881095237485064870468603451853549262304643738646051878343976465227744077912,2011784725603622472271597952122938645154942022107573948889667939904597454410,21059869383015715705096974077910228193608826877524913363323189378554601804559,13660545486380051482020817701263881806531607595506890631732662177505270213284,10831091042775967380899180760062457635694790868286967266013231823406639854653,149288128407476550494800886735600251983375852319258454101603889073198917321,4032475033542195421623899365282946172767274020529645277615759958662043553317,17860535012887415629230166789742533149365132198763199254812432302158542514395,611194463774512114860065022851497908950074400927073001695280142990812150583,5518364261187313845085346561539515049557757056751872639492957432879259341390,783263978868449790737487156609432867806742277074765259237378374864740012575,19059339826992310300213673274315612374137067865428300882729551175173242291657,3179709304184015397125565132235783368222831063701934511986753856772139349894,10954198701843076039176000728742415722273043852061382139560487789741501275316,16411266672500930935370066093245284646483148609897099268661795671514664627451,14614816948231085620934132277599546641612327229810158468490195811014141518325,2458257206135880430320027516329707989817636936777744813891328347210486074414,13549483340434455515002570470395006683062583844603627042649952800864870013910,14465927800403373425828183741641078057513049263889255157342086762479739044711,4039391352709218793104596256671892882216573882631238721514928981154171136548,12750457082077152291009387792121930725761848879916565703854704756389714536037,20703941646953337308096638741387402857948436803334980867971163138332859477843,20148755487317949638981041809982361196106823990400472213765926589941031736503,19035096428824471222963574043396024781574056587456391309795571372815435282399,13597108420431213178364236660710194375344287228654817880431599113069659963625,16737817219786305757887002253067607822378794077688837656791543060369162185533,5164935079689729145670846016031605160169301936105766707946436049006171651941,21653381930704765824477248798502813954284378782353810890869232482999795586793,2062605478140760101860087118379474541965619844748678233207247884294051836812,6841505950265078437298089354417829781031272459823272323626556598403583002674,18723551101558427097952125661588457059960574026361073828482106612260297969553,7898804490983679270754258611113569895515918945891808074921872907759024464249,10882278698112390755842292529204069263813359338030917602809789513528936860051,19447560013395173052961224723195565400117958329259001072560983848146677205053,6251288025262210726686494480483550276704856797649458538460443509657307219922,13176666617050786358406074057104742181338809005466316548399895981897535342946,20703225796049910173111490454489910459787604528779911406172217267261190895618,20336720518722954780604743873837334696992422089627753769439653667292899832714,21420427865372074512365684526694872695798980614525900481233709853915806389425,2498895690812694987926199054702295457557454143930759961192198950277119149872,18753512301709603592612141197073246313430368834576850495154922324845448997662,13229612292359498096055458608547157785066962647476451239567069089111704445000,2690879919643532184588441383789963956137193400890598777054187145581183393168,14142396602342548413722428497204107502988046500369932366351553161157672540408,20448725195660080278132534867269279218381543910636641344871383714386318629041,2559459540570011016181396098001618067535109329950570139376049832813577592045,2209294835847631004298393339896770055851570184195462947318472391473531519454,14610669112573509857774678749257346364319969641690596877040685661582231189775,15281088465087253563674405311018738676067395725444151577815750152538449780965,8600553033773805414817363397077178137667131851961144771667772828459236208319,2748346039979601666392027583251905158817539034260921486084376270967628661657,6854960712378511006304629447898292218014632388505703802374806527561178043857,20207552563190343462280438839438087615024485494479390954719687107061991587248,10281541252271366635718295778088948309847900730867531177275273130071062184625,18855605847424121529776135453072696981767402526737712879984848146282568841809,4160214035780913418097601322951078913381556877408879904436917334405689553255,2122867135885631508183413043949777333811557914428796322029495785048111325437,18793959580906171893053069386015945646795465354959679615181136313144978078417,1043591673717355695648236328597936528752358227297053230241551190351813693314,15686469257015275311444450012704351019335987785561570672026138336552980987277,14048856209379833670666148034655599475317994357805584661156301746235313941815,1011563953969880478397969933799483261900428580241502003261587014788238280391,19240556623066672446907714818724971233422104071815927265423017590508305430997,2121904286573815063480388650799381683473766736407678915747169455786741101182,6724437969134367395210139771738563153857495313330774537559578422672993498270,20206855573383441961836932177838081339503382415601366823182724056749038447809,3659051978213562322887447057085386386485486575515693147713900345497451171308,21246119528547168535908718411570119652856799993958321864163737649108920924448,10446114322905404392321651684574668727564081327779662579984472408056125404335,10052242287865403393859620372179811039720807230902452334457123873762222543944,6373462744579965543231173757071025010089494620309953425653057223643612177083,11716070974813426833631730493593924834405915845847679294742728105127112594434,6451284530793440411577197006976867289209413848762574411101073727224316913966,20143217291446069633369261481904349401356557325260758866598205109039367201468,7741896897172494958877302103827661518814930985518070029789560123401964418102,7414486245715284930410091802521351113719159777210731898112598211035848096490,6480506916211642204624111742530825907262535747743645014149694168805302825019,18349725066341807634895742572304899830893334427067633858521634672944685466440,1838291082333887710851505844271184097051704051003105078056248035350245616867,19201915197596065583046168024521824662441686729039260890206806469763190071269,11253788423541320580105520117231178489492440242200599071301755928628199128159,6048832714406694444296771635481934823208451249770515560893368035838759154821,6398008918881249487422929614611145638894557821587972164243877575640548705346,7013037564266297435879776776659289982125632651326438965546874242685502904730,5942504790082366811245813670914617310604940200824079289270465669331434165301,14344789199380317440464969138686896230070901882253997360605407637865754361287,19920212380356573378521292048728904573841049083972983190424200459025557666792,8983390577894750782268266038315113359711163721228398686939390484499979421166,14953991148867572055684497824790735528852361750007063016470842397064705671772,5592033578501586280289038012647352732276003389059749788953239057845882297561,14076883072716069263619564306953450824526010844333044566762059693672378725675,11108270411921226463443318601950168860230077781212396032908932369105145901793,3681277588815101350213324449908372578846563884174807724121308021640034446476,7194753190480156904207319938161903897566477363779122267985209483435838216959,21241255448366937244332942306324590869759761073985963892514045368815880517382,6203071960722514588958553813186803009742459823360660333787981951206442471249,19041823565851118046937769551785013706136778514067168239416647071096062639366,4928136619692555022185087228378238193895894009623071873887735418398682287593,16266329364886004534411977872528706660422476743809029518681886596981922182359,8814684891729998059175829142248330760704444206534875755023421115211106199303,11072277000652722690981202459933101924925520292174200155471966778637063588914,15889576313969861857250394875354819627977602318110620311480656842740292435237,6934515229262494305594741689326968268143898236690173897991110238064230886755,16212991575388366798683594066983659236103186124339324856776288894513503543244,21100508914867482363389012032457112622475533432309937238082785660233880354422,10381104469089401657446748653199843213201270332853172509558263968565255702795,8849389605935865968361613766905708889092097013638425059146677490704442276611,4826404934194100291623537890117339503344940312401101713754206109744511979962,9981819567268652304810465083896863711149056310505889216307212434682251812603,16218484218588441290424553684558267080330286201433140852298971691458926313766,21317661296916247018967238829275056855142711494630067664736600708605437812892,19523923008662567951910986132173659591346561824926093935331274289896011695634,21439241836891927940168832009944210084078628922824257988298290967895179737163,3818036890597976956138669961319975835941979944306305168232209375279960168960,10212547715001519604442389033695156945619060410131175896383181616280631586732,956283172524544133830416114111944076629240232397666924807554743752464221045,8545109273807246425343308224167362024331960554428088718932211551700420545275,5647769597708100114837534314408246331518385631750569421373379085922684908872,21776221280695269311212391423788179027868152904973644113087833004348746215729,15989020831232836203074762591626149244364214836699154611339161287030952623233,9384665943619921791886218744024370375464874104981653298499433530463000935024,15469006121097295841026542766455781293432005131673839148320165243166330403027,16103671377537767724271717097892044266704736999841135349844319906338275108222,842367229428650719054831004741080336526228967970570607897528985803108607790,8752325400224955775788313769797750158375262384121380328719514077259567119347,4803861091350023344885030428100876947830986453029412601567992550504530969575,7917553047944370948250445233027936387189889293110390303835890604428798853681,16378323148632546424902611135263436821435778030958161546757828745002247975096,19873719885630097137106352132870659633926425645300622070145979694717581586592,20324790419158243246762098227260178678767896786893299456278167341205663612964,4358908354524026935988729716331497263147669784003421920394531784876541301801,14403952632095852077754539203207047943619815438482171213105824864831554185165,16410713482142323347391147127545553384558868490870150984280601225023662513809,7304216341846662695189617252648753140769311862815448449926830269690397729157,16792943782280077475956215580025612636120139194657275471595325031090407485768,18494329391227402645175320826355306995912366111176422593669423022411884295357,3277597348237827068690736756050060740435013727549848360800059544123155276133,9396765756719511114743964794180256605700037182617127755220919249774110852382,5637053961584389263881381098869862042993858662768294676971865632259649027245,1752142832257643043564515360000718468888861086573246457619082905919623770956,14504506574384680785750882507533398260948836347427103366421836731538357314790,18947994518078004413210940685748534988014581551965984303066903086446389273117,8931855168578615387850254663107425567403115805663142600825724478150698936342,10982092525200624040399870568387498905840578524691489797530932831401946309626,4738907023206802373255186532236849256768509848242049657234258536668430260775,10888145285628319545262252531874405309329869513560101920454793431198094714989,4767721624212785367044047554655794533816937807005608600525762243335180089923,4054394679973840378112083329204220302222586590732553688297938891619998137578,15390471663419625573793381445844013245022413344196724396864223784781333233143,690498740448849288977645176879593806019080276382495160049117613302192708860,3326968907274045758110436838010900592335267522219473049427145975873344598768,19461545874830130561487975864151403334363998126023624462211037468138940028328,2255249425919459031033123095731665691066980364231819200773725596456576056043,17139538647342063569964264947811360956712827863014723985947727876623459280539,262834317961189780923232082352297808796511874872711860311746704570027370416,17784213646586812350819691264737755884800773322574478474130308351003659945289,9206479615073686723914227166450906925650471865894639492301222855979337534393,5955379232184076713510750681781395826148323482009739159408415185190732125682,16345512244217240951729073298135981012471478596479891072149124888060645303490,20053701095030547796310908765544502773063879272854547881438596069907281565287,11519146559536679602608982593432194283609736022486509747046459824035493513614,10868663839942247532249591973192159672852196011910414460124452013501564199585,12668355291693420029179738224611760713369106517542315102687346083105601320689,4091011252347209563858280520339886760216002486858313383741839652119084430270,11416347683590132388448480763970462739172261435271326798646502987745949753371,4462763980178675172541782335457125059884067698347130082276003539434128058577,21728891122467658477520865529973242372850367356840114983386033432316519759391,9556106604731806817435679463077765288658189491612307664294729425381901530224,5086982973132652080709554654284904229374030594786774699435814748257879554118,2278505454992311041650060186856758463754878439802195559533882189615578260695,16123495070352975934848591912315341924608875638550779884194576881433498909405,13177225503435100563531015597038445430211235761527278782674200718068329833622,11626932451843299545922103072142674578946680165802341368625957942237790110177,8872973246419344365802198448930136062421718851114220299577394844231810068090,11920016786052130191738519934437207519332291620474831138559948859328822621221,2773753221970604083383541092979093729869734021029185810064937974430862835870,1194583082499114147792330367943150006952486615245506995832323057119894886077,15293312601348482070373672684782686300692505365845870624263228679370968807837,2292156760291800990693425534213440357167359161992251338587906324724034592198,20920049766730284147153707151387304988393631464951398563908410768221002588086,3587899345078220957148828249287269521408604837648269936718299413697642586126,5857527906708110948691023855516662527925762284342493618496858248142623857037,18312267494676788897591109008609888960798722042916784593521762607767538629817,18354455618287562133438807735729369657256664914390381320892039403006410339493,18594037435499535688023807489676900345345731643180370940972090155512943637000,6361231157299815359812386352981667048590510979947935475914610076041390336883,6503045850716008738909204934356093641022474278658078426701342798380459107813,15826908470360778431798326530563200301151807861414464213699967513881040969457,913167165738148713876672473302437265273760468892350716109373788573860454641,5163418960719047707254162004625467116036830361107107814320243058319914687515,1852750695670141634014249062360862036043602867770163972096325792863710036947,16164029969996795952250343426848596535809001568622155377829217918121790073916,42291476149937488089591434144089904529405222471677684973768504172369443350,1329340386229357940610579826659090359930768580941108555938139535621252899508,14087936453397725507000489457270864434699508074557952952329368237400407748133,11454917885298514922755456675259734718428103879515668717779418480236210705323,17749966508430836878443008025013283275306943216523661550528505419303121693213,16617298839486771009961431205770630163409905047728421465641369616889696635464,5622873871440608391107520706189063847917690892897751818294742462879871297589,13537715561706278379083684257583804567523085149672090320983273122424669242274,12609629910090871112615676094781247031353826207267723991911250780907380059468,11881347692420971451998583525696964339513193164613288356598017302547676912004,3620434358220496198439193226313617496907852030586214671337652678218740406153,16586456872124455799862826347901525401871594428044067424833235946565396779382,19602593015746956165116919928045364895525104709835703557292833702385934632182,2465427491077301663150648330772125184470808854603184374760649420983178107738,12521323976712195518272978277895155774288446093713549157148428964880747896725,361951232333654306694462853852464888974834703718677826403016226307188397185,20048343816024297162848487251896481827914904696805156112188099141327595641104,997638030405613623344188782838773314122493364653596616029491564227193697621,10932007654988104622042938184134556963651043067553327861790671211490960094259,47171599193060570819891696279547021610376047998583333086685382152080932821,14669115378939104862697280661831896914139331878760241858539421915983017116504,17868874372855679948405169936193924176514630305572838555185339642210810710203,10178296575837129106771098084407669500326673901243393867574658658064222502028,11497182727976130924559852428316615034304736115488257034951588831868596612725,18847036158089242140209840241495282890278502700082131513222116906134183113862,15514518995390761662346743876733004358408187550386554449789531199638765348953,11474102901522012346251529527050392650125347221410246734211005177721289856415,6612195415835443084676700243243174090072629504450965229103970796390091290688,11572474094368358234669561324969692616275099241307798860733942350364532366113,3855324911963410548772360326122995145790506408472649961229511965629894550308,8802640003128749594245736338745752744580147773009816234644244502373660889677,15676839305513015047736600040932186843826469281853634239081282896349443894145,11124722103091011602185413968164672678635980457394627450785290630813993266691,15087674670944618980358596427703842917302233637812357643695687556421910213028,457555060782651847600218200815104907046227486293278645126081160142069992497,5340353060455057701755599760342180989590806327490432497082435572367648024359,3289809733259936118731355294329652879189400852472418229718273887860572748363,1821386174933044868215348232606758690922944887434531299978498726875279584854,17399236630582894158137572250502674699298844870791766041927951699287421557453,16772722824042046255416248879357647708113647471330900665176012648038469814744,331374066696126093678097185404981758791664151917354547180452342655690460271,5482079579065945934120471179616600325379965440378196448353560421120276746028,11861638874356162254375133266687016527365630872709665703116365332534843803431,19751278476934230895840638614095718373810690662562196455711240141902305648888,21017623330912840225230534280017695045717261514215145256795880310933667407841,9692530233397639077769939390011937602190121885296235066426091743618448584134,7914031992737639503490179289412369887137436318696390718781298556229610513180,5046304088054212585035723354298412694927209198400753780585596829596665931980,12735457541003664856181534137486291132119134214862779086936585300598349629287,8144204472889944485922664106370529127382213990656088602566223875490414163362,5526161442679804982165840590640681348630369336752481706044759543203459722566,4665464612431440885211271075488840033628676516298384234452346107374012633528,8451965709652752887539585363308640999657377914501438391781526068371105983117,18990458193856163728406448194111866469438835810342179114684453609893347662421,14602960690767985987882800342208585041637986661619503513589079723840776294824,294650277854196485752526848096008214721988745350555311479128101695333774927,9930361494944692931597991649915857642608730961125454734483697613693272941776,17972565769620820679641368732920396905240248490243886868922250461473059009007,11842743032528966560856860268344505094861546674985872961254820091273444880060,2260251491209762630871337015316066081541066308706934094017641769176593121838,21336986809148977544823484666876006147697590184356254785752148187171367963063,15637234083283356311249527335446193685599985235080555266374006156231977517227,7637477891046186378249227336975234440873859617986704147458186423096226771577,10435340982947407847927678888878882924793449778165415690957335683641419176012,21071574044063633264442120715854514033847137356154103023224485568597330648075,20085745552872944745120547909310789275453780111307008151203836541147270866122,2369255222739182549768488367357061329939116877812397072967912842660453854658,3320710154094663715463854219978294133429318041799642537800174050047893035878,2437552820481788519744888712380245016748276158860265401041560980354471184914,6687580113987208531705167517979176727449238324356562435678492283111952291541,13835828959457330678345759960614663723017667326485961761361157914420441377430,1823843951353887792473925888956554516299304358703549730900495356152013614424,18229384804985230011714562427207966412342158903455811854157839446374012856695,4983049472282717134994110428470567601005310848076496400503178535459679438524,2047051967230753763135778305592853785901616983565528680886843131244871631064,17059505494771925862841990046823342770591010831955480339095397897088168520686,5845823714127413134610517798305104245114036685335948729450609519089263487144,19810252752845594230307894817800427820113926573704856490871938876757561680148,20741340243371419379519807725035036726040739024854919427690724405113594586449,17305746835229988220561638584011917989169628535378748397361130724475478785704,16273970657972145440112726408308019138099820274904080726219726815138597785735,4927605725478881247988642936459897069651251926499343645614635597380235002430,4076655226193629464789557616268492785057128805549395585385432329518368497686,18134767316186963456589895259454813585756254459227058992203617493951135964914,20798436806114056077588608064161229365173163847083955162560624566238528904361,8811900287453512972593412116532745098600991077158875340182906101108258578231,1611466530857794066271650650204918615746591649578992581483080164777650137733,19520757346022691586967284723955378385034675472244175822936613026597514818901,8258287931139503595713718829279050060190693609290797346704848518381891359704,13807143439443425137076128013998009581746894329904809421858222329599144124143,2034200548964915935625429760202284220693125881760822084201315022529206424506,20594375914400911567795140472107624446159181622166676420027082349633992663301,17773828019575037451999782968066986504577459910353828196403976545023426528432,10645884969014005687699860915213473815514464399964009808411811895545112650817,3135829883501342672772973577699379927756997243617424917654928164800203666496,21807676600134151299257078976418813484444183016737321278512745883771478511369,14168063038909284721702678019083222059818438340503980617872573468231611140141,19022539506931505257153342575586362988716958060936788031721967221986624233067,919797128086310623571009200546035983274688764270933413427846490906074137487,10651353481391913627770814216074873532920753703051075188645774021198634943682,21601553598752750925049978818528421110707879819831249175157596816870100048288,9544964974935674319204796617933096476421551193682156030394816088243121582636,17113833205578964054057051521784698139661258340576694677296240312431808476286,9889647672195559279745677506312894570402108521106900082889976819798270827735,16028191999932520938901585234936954312994452706490572504997534210876573833649,19224701772787524647172128751148104366752057774529591812815327738829591289117,8065294760892477625290114823800398061529770004833832691347498933238361039736,8385011404987806129246014860479833290406969218526611328586242951296814426438,17626526623257098006524211054563886193098683828265081734658432468695686509315,9760584950604786147191288118087660976225563461953070125437519145090832114537,3282956645059793949082172795607530130101621492305193365378997603911833418463,3788543541342252822847978185963388795825378340921321139695221828685330606335,5728277403393912877393143174229934529937061751983246730506397742038949251701,20532577038632159357383817240596922896191478140446876998140515404169184846609,6138500779693128517529525961343097735306947649093633133232282430353593175172,16387038830089541476468870208162294639575042754761542956218362331966004300870,10184264376398708852688445921404363179240954227345322711923845040842165453208,12576299651793170522912156101640799825541149618303513174146382191633847258859,1340015400080181141720946234858756484323564628916867888877667239334982793481,733959369856163480135680991009606990817015555938726628110611986599242143578,11467033813562140192244869512537566463715027496952375979909160849747976831918,4619667645046391146577435774790188488541561222783010406420406869960248783331,58552761198135931030902257754896948615688045302818928845814661296914920622,1199849881730507352706524556330002080538296688430736582840314007371442152147,7124502590511184113044595527748024819132713282667933641439666531514739645089,8623660134669459112474551498616256867375253975034970808437732784494772311361,12655669439191191182341423414424342421477486764113555800095493091893820045534,18432703875775002490514477493898870315422995231506677048275960580528644904682,15467220287938881354678249472400749704814316816035426814619089032223454845193,2851120240492392321044027263769720216640877441121430445737594074121655318176,20519914249934881206828098454303256358482675671718589102535780334267934987941,17275124961392392047135728713829752470490098022504524438869454049765356211723,3323710067527231515807603961736782048796606296990840839366613937968342331886,4468708240622802562056471128793253296493002925988003094771284205007772045098,9006494818135081033869830730030943407240565201693254355620348420258773924028,2624130417875598753127999576825019766166727976335690685433712946223008520912,164131399455376615654870570697119442360078693174350746600132391198500093412,14931668887432843139264972187415200544679230597820424081936926034478502874299,1638753880783574431267395352024193675000113296497173968722590753809640941864,15505380865926802396097545843811910443367233632805651511272732002583232431557,17973744614207669251901495093091561913998272050499760575282030108740677066624,6137688223696761009295745609563284204827706564566466060484103844265403078408,14774243062532823236792831566222119634320864630838624098798648826842418775856,15864970393171078370207775103899428499600152663946379517190945807315353544891,19010063123357565300336230971672519561204810737546730911549311353159512986740,12607162829921425080830052984475623157169603642577010527391007035133383807243,17803108634879437217723652777640120469990779759700458421844361066182881628345,10065874953507223318296028499872542865030107611981933577973812883589535269142,3276471432535144390388324850641020151392959100393035635141206272558418581928,7532054601401798035926415744768772852833516520318445183340725930886329458991,18893822928119227829016544343228228897166113682019317256005502643243867377334,15940597493253236451533839310728876441657428995464658827726295547815292644378,4268009387843764409267791203070919313017052533005657826253994943184768120896,21611251949238422413354051947529388972078300717392131751061464498329326474580,12516447001729804412674006874184731098280474050775388553768469608793631490618,49838549447142926741568525697026885045023997277705726329780325103507790978,19763902910323896567698991616245963026306943100978479625077573937114135803058,12029297973430627253212633299020402005457460023136429653800185001711727387314,17676997725594777991384952086633589048516371093397126876621255518370680168503,10567543371894667303450346380722020266352683222046730266924342174164712049360,14583364850544999818712646438016435003942847076919084667364987497592599663937,17348091487238815837308569582101875357715798351834275089190053280855958465528,8743083090296259283603789316855921930102444739264013461469099560398359267240,15114064505647935792598848256320570567717917317803629185764147361301698519005,18332675991829764561879941291908436508530604635608341316693114747813051532006,1757567731797951053080580099911774643896363235228742197150882457231133285549,6526388717947413328592956348507481629843816325885832861915399601868279124246], - [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] + [ + 0x2197703fceb4cbf07c6dbf46c4ad93e7d14e554db66d09102ff84824743fe4e7, + 0x1322f0fffc7e4854bd8b5fc23e7106b51f59bd5061d8b565aca2fd3efe512f79, + 0x19e414f80380aa2d222133118c337d82a8c5894c2f88861ee46f448fa9d61359, + 0x22241199a4df9cb7d65249d9562cad6c65f16460e79a7939cbfdd6d7b9209d9a, + 0x301061735384dfcecf9a311c22ade327b51c78b211615f41c77f6d85e8a41b6, + 0x229e1d86c1f2810f4a2633b7b4b5bb61b7dc5d19ac95fd8d379548ff2b6850ee, + 0xe31dcf9c53209a817eeb292e989727c3f56bff65883afe5fdc28ac3dfbea675, + 0x68f917bb1b0805e5b5888b6a97824395baed195b5da0b71c42abd091c2ef54b, + 0x1d0bfb8bb90ac234002d837715613297802a5bbcb69aa2da8cfabd832f52d7b2, + 0xd67c182fbf41c18d5afcb48be20237413f02a64dbf09eaf71f23a14fb9e2103, + 0x3058909cb103557706304b9bb64d94aea4e504d8fda8b82313996f7962884886, + 0x4d06a80196e10e664adfefd075d0cca04961ee8a89f4fd6d601eeb9b60c8dbb, + 0xab062f8d4b5ed0ec21bdb42eb3fcb0a88fa13afcae4523d2386455228407b56, + 0x17380754792ad5f8195e327a5a63cd7570cd1994bd6a130e01c1fa1a173d4630, + 0x2d4f3780eef4ff99ac916f4b12dd575613cb9621bc5fa0980ed9a4ec8aade56c, + 0x2abbef481b368ca971e74dae04691439f845c10d1d57894269b275c196aaf9ee, + 0xf24324f82d68231dd9dd6f8c05f52d8eacb9ae01ccb1f3b30228222377d0e53, + 0x267617317f5146654295ef602b91250db010b45f4724ce7ec54884b29c404597, + 0x157f9e2f737498821bb01ab1001d715eb2c336dbdfcb867becf0a2bb6490c06, + 0xda7bec0cb98d337a52cdf0d66e8a97f24229671346848a552eac14c8a30c702, + 0x15fc820ef53302dca709f3ee480ba1371c91ade79f9f587fc7878d731c0596d1, + 0x845715adfca35c3e8057c0fcd4ce6a6128d0e8117d88f551d3ec6587d0f4296, + 0x422f744e2b736096bc8775a3906893a64cda874aa4457d2b442a9a771956d0f, + 0x15f421550bf6639d46ab5779fd26b1e11618e0497e05cc85c608b00faf3382a1, + 0x4f17cad2ba0ef6f8602e93f5b988d5f357e61ae5f3ec35066fcb4d1a7b720c8, + 0x1732ef5660d84ae50ca09c021eb0d77f1fb2a00cc7905b2479588c49c488673f, + 0x29b12501fa79e08bc25259985f730cdce9e2434192ec826e0f4b9d568bd351b2, + 0x207c8006aa78fc40a84db40ad82142d0f61b28dedf10e2201d815cf4f6274590, + 0xa25704ce4cb74a94d7bdcbdb5fa268abd589d88fe45b2f2c82f90326cd049a8, + 0x11211f3a71af30a00101c423ea40a9585a9eec75687725d7ee289f428f40efb2, + 0xe01e8bbf5ee611471380ce8bb8c34b932ac76e96faabcb7ad20be96187c2fa7, + 0x1c894a1430513df35523e22e4fe9f410a43de91dac73ae338c772fef1fb74363, + 0x2bee349392dfa0b5b4a08ee58ef54f002e06ab26834f94843d48ff0ced526d5c, + 0x84a60c1d70887d9f2d23a8c7713332829eb41cf3181149fb223b7abff4d7f0, + 0x23a4506c90c07f3ae176a0e2bf67f57f88d45898c97bcdebc8a8263ab602c7c5, + 0x1ab66896a1df95c0208b990e2c634707394a1110cb314bb82e0a2e2b4958aee7, + 0x2c6b842aabeb84ede49e559d8eea658293ff4bba9325b5a1d4cb649d317f4616, + 0x16321af63871328c2b88f46df432be9aa14b008b93f85cd971dd986dc16d2e35, + 0x13d647208d3dbcc9df10d1ee35b598e6c8ed85608f81ba6953088e7bc6db73ec, + 0x1c6aeda9e0fa69f5143e6f22e747b7e74e692b9254d55c61b890470cbd7f06b, + 0x287d74a5fa03a4ed65bd4a7c6daf033418f474c7dd9b957bf2b17965cac024b1, + 0x27a4327beb0b3e0cc219805b3f05e854bedcda1b7c93f11691ffd6bb76a5d0e9, + 0x271a03a000bf412e7fcfe8918baa689c6682417803f5b302f1ae30695c8e6770, + 0x1a4436200e4d0be65d2f0f4000157c957fee515e591c8b54bcd46c02d599235f, + 0x1bce9394a5dad0a4cee35b8e99b4b3c0cee058b8ae4fde301c3145a5a7a94c76, + 0x2b1b4ff2bc186b7dda9c3e05dd4932f38e6a7c04b0af0839441a5972125dc902, + 0x13c87d0e4bfa493cc2a197b1c9db49426979adfee4714048d865d4f6e95f699b, + 0xe861496d1b54e3530aa0dc64c6683ec0d01a4e3d1c69d50f4d6720b981ccd62, + 0xdb63bd46e06bcaffbcb03e5dd3faa88f26a0aaa728198c5d09a483fc4197100, + 0x2f8fca3a44bf9ea99452e1a055886af7c95850b716222ad89f0219054d45db87, + 0x5b7bb3e5a4e2946395d1d6ddd541bd9c166cfa1956d161713e7e350f5947d73, + 0x20e4e6c47a68be3175fcf5a7a3f8bf7b3b2198203b4552ed620b9593b66e5483, + 0x154a2a02379c7695ba4783e15d10a147560ee2b4d03a04a0b901dade72df4862, + 0x156f02cab5fb0e7e6fa0c743bfd64716e15e5e50e12774805b1c74dea89c5345, + 0x1d258218556d0152f0a3be042b1bd146774a616ffc7e7313e9519b5041318912, + 0x160a5da355d469412e5535804f99dfb8fa839d7ce2cb7afa50c1fd036219f4e8, + 0x1693c0c96b95f7037faf6a18289814c68237870edc94a72c883eb2c751d5ec43, + 0x2b0df0f463f69ca206ad5c4a115d1a6a83d5e0ac328bd468f35826a968d5708b, + 0x19cad23c14a9bed0e159f250bec8655c07149bba04161fe002f76954ca192b60, + 0x25857eae6be307b653c36a4090a3963d60842410e04c5722dfede28fa645f54e, + 0x29ac9714955b7a9c94e7959efbeba17c04839ad7bbabdc643b9840ae43155f72, + 0x2e637dbad876dd52a7284db266593aa85b2020bf340802625e74f45a2cdf962d, + 0x468d89779fadedbdb4f0093858113c5060321aaaf082a53d44fc74c65e7ee84, + 0x914cefd51a2822efcf8629d57eb5b6ec7195a90087762ec8814f14bde647522, + 0x120a9d3cbca58b917f4e61117c7fe2190ba6d238ce374949778c40a6d176707d, + 0x1cf1c75a1b2ca09ac655215cb308b39ecef96d746ecbc34b37583bd8e0480d5e, + 0x511cadc2d431769a953d0d2355cdd3d8c13dca7a6c5b19005bcbf3c5bcf7770, + 0x1e2aac063f4303e24a2a44b1bed5688a43279356dc78a772e4dcfad0562e5dd1, + 0x172a396d41cfb2b1241e096aa41f3a4788303d8824d5496871e03cb9590f89ba, + 0xbde068237cc41aadb7ac718d4c6b916cb7f35fb399ebb2515307e6004969e2e, + 0x1522d1f8f0cb9214b3f6602d9f867bd2ae07a8fa77aefbc3153af4d350d933ee, + 0x157d56053aca2c4cd30f7ba34e5d41b8a636961ef78c1dea1759dceaccd1ed69, + 0x10aff8c0fa2f25f58a299e22c732f1b901616f6e4bc6f63af79bb93d45fc188e, + 0xa9557d37fbb35ce046f2df3d8bd9cfccedf85eef2549843da7f2c2e36d2bde4, + 0x75029d8351a4949170136de66c179a8d6ee6b56b89598af199528d78e8d2c59, + 0x2aa767c911398696b2302fe15ad33ef35c6c97618e672f837aa4fd42930355cf, + 0x14d99c7417a329ff62d32828421e1b8a031d30242b285c86a4f63795e376623, + 0x186e1b78089467478310c35eca9d2058c0a8bb8e2ea5c324f1314e478a12894e, + 0x2ca9306ef62dfb1ad58244ac5bd70b0bc84f86368f6c9bd4e15ddaed432e9838, + 0x17630d6307628585661eaaee9438c67160f7eaf6d03d3ca6364d4adda49bdf27, + 0x21187c1dffae74340a488cdf08ce322226544816780af016098d8c39c7e72e31, + 0x1db210b93c320a18bab1769aee63276bd99ac89035b0da327cd06cb70854aca, + 0x18bb6f89805c1bd59d8d7ad109d5f26b4d18813f71cf3aaba26ee896709404e1, + 0x9c0a6c2d79cc06023f3f43196c9b8a60a55716d2c7ca095d849a5d67ff6fe98, + 0xbe6b7d6cfed9528f4d1ae306f3138306ea7c81cbf903e9b884eab5084dc4c16, + 0x16fc7c808552b1362d8a739bfdf6c6dbe70b00611780fb4818d424d5e017ed5c, + 0xf31a91e6db75df904be6bb14fe7271429e5787f9a918d1cb128ad76ac948836, + 0x230a66ce24feddd45fcfcb5ca7e4efb12461a7c0a0b673a73b252925d310d488, + 0x5ed3707e7ad3478ae508126cba274743cfe8685b46153f6da3a0b4b83ea92d0, + 0x465c370db40b8f14b4f6ef913550c11bcb2839ac707e2fe9a9c31b43cf8d938, + 0x85f42b894873a7451a60fec0539f9ff8b2e0a495e43db7b95c3a75c57c20ed, + 0x2e8b3ae9368c9c1f1542ae734cd995869f81aac64902fb1d3597022da08f9938, + 0x161485d4fa8620e6fd09b088159c4e223155019bfe9eae28f9870ff19ccff314, + 0xb6e400339e5e76c1d200fd27884599d473dd98fade9e648940833ea32b75416, + 0x261ee31fad47c0db7bc046f718437ee518fe73ec92c1e203155d8f284d44b310, + 0x4e106089b776d01a284b84adcddba4bf0ee56c2c85ac584b4d938f45023252e, + 0x4b14e89f42287dee36142a17718f7615789c9f9623b534afeffcf9c7e26449f, + 0x1d55915b20b60534f1d89f2f8c49568123fcb4c6d9197373e54662e7d9eb83b0, + 0xbf04f5b7d178a77ee32fe543be468e1c89aa457a2f4d6699aea743f80494b8, + 0x1bb1f31e887647cb45b8bc5be185e206e91accf86e5ce5bc1b39af12f857ea3e, + 0x26f0b4214212ea8030aba75b2eb699e84adf24bc4b856a3522b82c1edca87e9d, + 0x1ad7e1c6feade269c076b67239b316e7cfc194b036b5a53f9207f457599c5fca, + 0x11947cedad859f02ffb4b99e8108512fa325224ad7e1bcf82b28c61a89840035, + 0x1ef4f0330d6144228ef6cc36eda0d179384c4dc1858c95de12d070d11c43348c, + 0x1031abebb0216be506c04a6514d471f18b0dc1b5a9b616c87a465b689cd1336d, + 0x23f97eb680f5a13b3e8daae572abe2ac0dd92eaab473002f0708e6b6084b2df8, + 0x289b2ba2e3c8f665b94a4d73b5bdf7d6687468aaa84ef7f6e04fe123659e41b2, + 0xd40f713b31b2d041d3e01e2504af10020bfc45bd5bbde4f4b133f63536090b5, + 0x29204d73ce84b3fbbe047c74997ee799f92923cd16ece1eb6275c8b71659f149, + 0x23cd14b50f4129fa56263fefbe7475e51c85f67cdf38a9ae7637ad04ad644c6a, + 0x1603887bc7e6956ae4ff5b9f4423b2293ab52b69b2ec021acb90bb6da8dc3883, + 0x2137d99c24145e52ead0129bb220690c5ff8f6dbff755c8467054b645c74b0f9, + 0x1f3d6d1349096a8e0594443a487386f9f51b2fc366e910a9952d4f0b3dbec414, + 0x2148e1aab3e9c82a297d04af8191e2b05cec71b0cd6b8b4e079061dd00f01a00, + 0x17fb0721b3375406028ab6f04882a202e6801cbbbb50badcbd5d760d59e60c54, + 0x44f8ade334554cd610743aababa1196e00106e754cff8b088ac69a273ed074d, + 0x2e10e74d30679661fc3ac960b7c967cbc50029d2ea463ab8ef55633cc5405243, + 0x1e44030832526ce32d540c5cdd2def7f900509bc8019fec5e38848b3576dba8e, + 0x2c17bd7af463d52d3fd7e8723d11078369561ca3c4ece48f1298adabe7c822e0 + ], + [ + [ + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0x1fe9feb5c7f7c7a426bff032cd6a3158278b6c6b2cc57a871213fcafd6427989, + 0xcdb2db9e4f9d732d217c5e3114821165d49e5a2d41556bcd53d0c4d433224c, + 0x9664216ca565c1a44fc2b98347ea8b36904b3877f2159dcc999895adeb4d70b, + 0x1463f51d4a4cb1eba16dbc115566aa48fe77b43c244c9988a3c658d2f56493d6, + 0x214e41788bd2b990347c7f2a8f47612d4dfceb1a1e6da38165873df66ce51f59, + 0x548541724f64e20128260899abe8fbcdff184a1957a9385fb715923bf0fc79d + ], + [ + 0x1b4bc5885d1cfc8eb691875300db5a0c7362ae381898acaf8b63cad04ecb36c6, + 0xcc7eabb154aa7955eac47a19f6437a2b8dec0fe9e5686150ff6e88b1a7b4bc4, + 0x12f3bb29c972793182123f5c49306e16a3a787c4bcd9c798a131b70856d1cbe, + 0x111fd8dfce2bd3b7ba0cfa93e20fb685abf76d77305857b8df30914e4849ecef, + 0x16afd8f4c39038b8006a59d292aea84731c0f83832a61b82250ed90118e8fec2, + 0x3fba82d3f783620873da94e9f4e84c8b529d76f54e4b5d7d4805272af9b9775, + 0x21c5e25a6991364e59a205e5b01c811deeb095680a72928369cfd2de71b14f98 + ], + [ + 0x8a72fbb55dde3e93c5818571a424a54953695029eedbcf91eaeb012751c7f83, + 0x393efd96399aa0726ef9af79be8b6c715e429906ca0d15076b5a990fea75ace, + 0xbba9006404c5ede82b527677daf444ed43fd1e0dbdc5528dd2cd1f17ad73481, + 0x19f53c0a592b3ea93497a511e56f66753598265b1ab6774da48eec04e4d93426, + 0x2296361f3bf154efbab996921936e9b1dff8352711f958638172055333e07579, + 0x66782fe3e869de2cebd7ebbf60fb435785329dfb12ad9bd1b4e46ed36289511, + 0x11c5cc53f6338c825817aff7792a2efbce8fff171300d41455a2edac37663d02 + ], + [ + 0xf95359a1f6845d4921892f83e500bbb1b3d3763d8fc762400af039b0abb83f5, + 0x871233835b752ea030cf8a4f43771296eeb33f697d1b0825db47d39ac9e5955, + 0x17e4e73bf701f88d219acf1ca6390cc1e17c9f84b1713820837ca070be84a2dc, + 0x19b683c39d3b002fc3523b7bee5a60148b1dbdf18dd1c318e6a541e8cf66a174, + 0x1c3160ebaeb10f809f69843cf8d5bbaca198d1f8e3439be29beb92d909ec891c, + 0x1c5cd6b23ef336be01efa37a27e6b7aae5d1643fceeb212cdff51588835fb537, + 0x27a0949fdc9f10495c4ee7214aa0edd2ad8eef68f577da8b96f9d87a39504bf9 + ], + [ + 0x16f01751ce985328afde34d81619defb43e6c7b5dadf52d0f82472fbce7770d9, + 0x1a02798f047a51baaea34fcfb26ca6afe96a5fad1d2db4270497b6e6504891cb, + 0x234b8a077ef52b53a343b8da5b20cc358ad60760dd60276d485015f73d53d207, + 0x2547113a818779f13e3448719c7ef100b8036bb3e882dd5e6456c35311c1bd5b, + 0x94c66bdcff54382cd9213abe43312edb5b4d414c6e09acca24912a7635404c6, + 0x2f3b4bf0f105f88e27248af094e29feed9ff3fad9a794e15830bd2b311539453, + 0x1c7fc68f3fbde4a23c455ef0d0dbce0ce556a0194e6d552c0455cbb5b0c230e2 + ], + [ + 0x1c391626328457fcafa629f3e6d33e2555e8d885e3c07cecc8af1f4d56596417, + 0x55665d76df3cd0fcb713c234ea79d06a31d6e3e4c3bcc657dba4c664d5a0da0, + 0x2dc3fd77394b7b5ac1cbd1b46e6ded5b835d7217a4c50a487ae9a35a7fd45d9d, + 0xcf148f8045cdbe7bb1013f72ebd4126a3e35cba9a970441ba8d5bc76943b0b, + 0x2e883bd408c4c826d004ff777d7c0938434ab5bb84f3420e5d94b853b1746f89, + 0x2f4085eaa9f80a69b739fc23f2fe4057f64729b311783fcfab3a0a36fc1ff432, + 0x11d0f56fc00e7d85b3a2939fd33991dc8abc1ced0c3f3c530cbfb4500d63de9c + ], + [ + 0x970f671b9ba35e3e3c642d1e0b8032023ed5bac91c2c1056f03965a42c5297, + 0x26ee9691a638edc7c91887e302fc55e8e7758286a44845ad88fd7de3bb1052c1, + 0x1668477640fab14c72b1c16ff0192e48cf882f12276bd12f97f82c6ee2e61e48, + 0x3008421eed767a093322a09c3733973a038168cb28cd2e1f709076c00b869599, + 0x228af6d425e91a783dd18fd89a6b38bda053f2f23c094b875f27cb3abba2030b, + 0x2363603349e94f520fa1f98fe2507f6aae361934078aa59a16214c088185638b, + 0x1b2e9d20d9b55deb048cabe1636f0e96363bec886679cbd91f332fb2bade44f + ] + ], + [ +[ +0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, +0x90df29b70c5a783521503f92a45753c8bca03a74627a24c44dbca6eca32ac42, +0x11a48e9fa064121f52297162fd169e051d154a0e203583624a16c73534430b9b, +0x1636fd9a0457ce75aede0821e036773e39c37adf6fedcc7b2cdd72254e2ec7cc, +0x2e64b2e0bd6fb47559f585b63e8dd15b430058a63f2076636052efccdea98ec6, +0x2cb7863886cc4ee1640210d29a4a329d93a040ed45f2744c25731c8fcd15f0f8, +0xf3212046ef984438989c355db0984f93ea4bf99de1700ee0185886e81f2ef43 +], +[ +0x1b4bc5885d1cfc8eb691875300db5a0c7362ae381898acaf8b63cad04ecb36c6, +0x2c628e21a22008733e14f81e953a50072ac800560554df9e97971a56c509222b, +0x1cb1d2eca719de8ea352adccabcdd100c4fddbd380871e2190e33390b8bab1ef, +0x6a0175e0d8aa3e1b994a177af69a40bdf6dfae09c41d2fb3d8c599c76e7f07a, +0x5fc6589a1d1d35b2473c61ac293c6d6cbe24fab12a9086c0aee1f8d1a28a883, +0x26342b8b16928328123d727014822f00f4fbde2cd45046f5dbb6b986edfeb632, +0xd7565999ffac123203ee5a0699bd4a2f4c491fcfe05676f928694717e572878 +], +[ +0x8a72fbb55dde3e93c5818571a424a54953695029eedbcf91eaeb012751c7f83, +0x1567d8f8711949c036030ef808665350cfe9b648f13c675379aedd83d9b83767, +0xc9037b1b5cb3451595b4f8a1ca80c3d72ceb93d6d58dfe8eba02e88d211b281, +0x183d06dae1a0ce53171aa09f25f25ee397263dbad5306dd1b7428872baabd5f, +0x7da96bbf5fc4458741de810178e19a89631a95f2e0cd7e5f2783cd237f3d911, +0x1efe4b3bfbb320e15ac79fa9abd46e4a19b21f39bc40143351321f658f6cfe7c, +0x900505bde5ee2d55f5baa932e38805bd914afbcf3fc854219cf41d147b89db9 +], +[ +0xf95359a1f6845d4921892f83e500bbb1b3d3763d8fc762400af039b0abb83f5, +0x27630d326f12eed19ada60a1f6c496680425b457f42e8999f49676af0b637a6c, +0x26920194603a11727525c5e7b267ab6580abe2a7912789eea077a55f7ec3204, +0x10e5dd7a0862c4aba24ece684e502d3d6132a99d906908b20eba4f3466812e42, +0x2d30f6e371ba6fa64853fca459d0d6e0edf941c3e8177ad5d333d4eaecd7dc7c, +0x7ed952f7c3370e03880bfca6348ab2ad35bbdf9b7e9c266e7885b580edd59fd, +0x25b7a438b7dac4f0b36183f18766ce503f69d6c1d9cd29b986d7d2b8b44be433 +], +[ +0x16f01751ce985328afde34d81619defb43e6c7b5dadf52d0f82472fbce7770d9, +0x37e3c16dbd340ff80f49ee4f7dbe1098b474176a92b7a6964a63f2fbb8acfa, +0x2cf7810985ed56d898150ddcbd42edcfab6442f0d0a7f637693f676300c85c5, +0x2595dfbda733d0477a01cb6693b93eb4cb711bef3784b5fc9e17f1b342eb15d4, +0x7d9eb804f0a999ec586c58164da8467a481c1975e27b951f6f18411a7440cd8, +0x56b8df70be9577f94b6fc2a3a94f736d9c7b9de29134ff3a524e406e3143280, +0x258a0dbb961fc61bffd39764fe6d3c687a1061b59ad00fe85d1c18594b7e7270 +], +[ +0x1c391626328457fcafa629f3e6d33e2555e8d885e3c07cecc8af1f4d56596417, +0x1814234ad66f16a36711c9d2779c1358ef58f650cab5cfd95a0678af36224c98, +0x25965b4db95bc7104bffcc6ed99af5cf5328012a3a1a35cdcbcae4ed2470175a, +0x3090eb08e04a2d235c164b71a56dd730c6b95e5a2613d39cfd932b90af23ad0, +0xaca5e46d797e1748aa438d2e2967569992dfcd41997be143c3ebd2a823b7660, +0x18e6cc7c6ba50e61933de0f615fd4458d39a6c34c2f241a4cb78dab9dd1b4283, +0x216fe55a6f2e8daa2523b65eda5367ad3a3a6c55856c5447f398a280e57d6535 +], +[ +0x970f671b9ba35e3e3c642d1e0b8032023ed5bac91c2c1056f03965a42c5297, +0x1bfb7975cfa9022d9bea2acafbd020c85cd3f1091794d28413510f2d723ffdb3, +0x20c27ab9c365c5d2de660b9b31d4a406907c506b5488787bbe2de181b76e6a7c, +0x28feb3ed6c194200a579ff340040be172171c1f7980e63214a0b3f7603d68a02, +0x100d8a1a7ff31b30725190584c830b15c0cc5a41d9d530ed57c0bab464368b5d, +0x791d241f4743deb4afd41d9989448220d5a1d101bd96db5ab2968b981aad486, +0x1749c39995115eef14e1bcb1ccd4cdfc5c928ff14e078b38f5af326ed6b1e099 +] +], + [ + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0x277ac8a3178a356b9072bb7b469ccd57a0a63dbf08fd0dd7356008d5307bb3e6, + 0x24903bdf5d3968a8e49c6bfafc0e28d539ec1e2756e69301a8e38dab87c6c402, + 0x14e025a7131c3bc8bd2d48508aa4f791c8ebd10688d7e5566a41fa0c149b8602, + 0x2e41c7e320ecfc1d86df765fd7bf43ed2b6bf27ab8b7c74174ed61d57905c555, + 0x11bb3cde82e89bb0041907d66de91029b35a9c8c90ea44de1661ea2ace917451, + 0xa7460b280828af7d0a5bf4065b2b9640a9cf83d19899cca0171ff6abcb49751, + 0x234be66b59a16a323cb35d6516c5a92f4997b76e14e656a8c41f29fc94925b0e, + 0x27c512cd854e483667792d785ed1ed7e30569dbe12fc3fcb0c804110c937adff, + 0x1532821b842df3a4e64577b7c8917219c86fa82e68857a1a5be4056e8763a864, + 0x1ec15f1ce8c3cd648f325d92ace903521d7b0f668a01c6d2b92b43e35b5ac58b, + 0x234748a5e415d7b5cd0b75b712675e72e95b1e02ce6f48d299d5a3a489905ea5, + 0x14037feed35ba091ce3dbb4e6033098d07a3cc512e981a493c0788e3827a6694, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0xa7c49a32b5a05a6d74faaded50d303c066ec843a10ec59dc90cbd37ba4b1b6b, + 0x7fe2a4ab68b94f006bc1ed36af445905c8d234d308d57011dc1d393e6bcce8a, + 0x15b26f61d51ae17017b1b9d1c9034a51083f25b33f474c96bca5bf47e8a658f0, + 0x1a9c3ed5b8f524e8e2de1678002e73c63ebeb3606fffc29ae527fb94c60f5f78, + 0x153aafcf4923742708efe169c490514516a223537245aca3ea205df20b8b5ccf, + 0x239cbec4c84afc21975a40e29610d83c1d71a378cc58995e505def01cc6bc872, + 0x1edb2bf1ce76a49c4844b7e5692018b524b30c1660a2e003b5768787d7af6d32, + 0x222778dc5bf834f9320f037f4847ce62a2ae63be8cb846a5e10a3c2eb2ff22ee, + 0x17c2ef46844a5365828904ac73e5114f9bc2833cf35f65adde116491bc86e0c0, + 0x2fff9c9428727c51c6bd6c657e31314706237633e5cb78ae244d5d4c3ace4839, + 0x1d188182ea443a5a5cea9823f3eee70a2c1e18459e4305ef862666d16236b0b8, + 0x194dfe2339f7aa042818a43f4c6d3b5b2fadf648ba0dc219e56ec7f849ec7e5d, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0x1c7aa6d64a120d657fbeb04c84017166427d0f02f0406c0674899118aeb3a1c8, + 0x1dc18887cff4545b07d122b9086f80b9c464ee5aaf98ebbee8a648df3b74551d, + 0x27c28329d9f8519a1ad9973cbc710635e5cd01ff884e1c113cca7b35742578d9, + 0x289ce154bb02ab338ede3bdf7b2efe8de1fe22259477475987386544f3eb5cb8, + 0x2257e368b26697c9ae1bed7b5cae11efb9d48138dae5b7b3c499a37cde286d03, + 0x1bc9d5e7820a13f9f045f7b544abb2e4b954a8d9b6d38f198efe3275d9d7edd9, + 0x18d112c5305a06c15faf556d58b84ddc492912505da27bc8500fbd32e4df9c39, + 0x2c63e80087f924919d20067f050b7d7edbdaae2f3018fef6f8cdace9768faa75, + 0x877b395faf50d5d108121e29b7ca64c6408dbc08f173278ebf6de8b9685e113, + 0x40cdf2e7828e66a99121262b33701cc96696849e5532f492486d69b2779e9e4, + 0x16e80a1f3fe9b828493e83d1a31428b1c586b3dd54d735eedd257930a2f539b, + 0x994a923eee5e6fd6a4caa317c6926ff4beb82c3dfe033f37433d31898a60f20, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0x2060946803f18c085b6fde5a3d8750d80f9b21ed391e27e1c7bed180d708e87e, + 0x24fa5c0683c2eb83b0864853cded9d57d38f33fae496818450e2f6c49968dcd7, + 0x162824e200bf52b73914219f02ddc59785407c558eb4dd72ff9b11921a351eb, + 0x1edb37284aaca008c1703ddea2da4eb79521cc4cdcb7692ae344be2b880f574f, + 0x2189adace1c5a701dfa9c5354cefcd8204c60095f5b8568232dd01acb3c09688, + 0x19f1b2d64e3cddcf28e7187f16f3a90c93975e2569625ac689e3878b2de7c778, + 0xc62cf98668e5178bb9b6b261f36e1c8f176f190d372921c9b46f824db8c6190, + 0x16ef695c32d05c8c43431f284a33a0138455d93408ca2f742944d71eee85aba6, + 0x1916a7ff07956db69d712449d024d8272e2d9fbe9428d6562c503b99337b1c14, + 0x155303d79a49e28947744f334366acd9454fca21261d32bddc76ce6086e8f1aa, + 0x21dd4756d2217bdbb9b439bc12e5daf5a8661b1effd889c642cb49c4839cd533, + 0x197232e52cfe9adf15394e38dc30548d7cf495c7499bcdd993c2df59993d72a5, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0x2f1786e4f7d8187788ae6fc25c6818d2e7fb34a8896414ac9f6b958de481eb0d, + 0x7b914cb16d817387d79ee23fe9975ec91fed24d0e163dbcb5418d96b504c2ff, + 0x1958452705af91d4b3be5bbaba856067cae00977353897c5ac0d070f90e34ba8, + 0x20f47ed0ffd3fa2dd8dbfd9d0daa514b0d72d270d1327e33840cf178b27637e5, + 0x2bdcc2280fe50acaa851536e7432f37c888a6507168a4b79e2578d7372f5db82, + 0x100ca23f8d8ebcf656d1fa5cb225932b62772fe53e2c5650109e71231c3a9b0b, + 0x1d359baef3547113637ed1d8e44c89166eb4154d190d38a2c6d47afe5cc12e1, + 0xa78ae4732461eba1b90fc18b100cad3712d8b684324dd57343cc127b005a3bb, + 0x1a843ce91e265e4b6cf8ac90c3454584d4d481813247df111241cb4409b26b2d, + 0x140c4ee1c78bf8555602a74eccc3c3f71e050a5deab03ccde1d8431c151bc3b, + 0x7696859ae6cbcd413e8a035a9191cda79f3d04e6c3d18658434d0555824e4fc, + 0x2e7f9004dc09157cebb4e42884622e0307f85fe2c37fa7ad2674b0981b2c0d32, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0x17607febb988532e6c79c307d903056a2266735b7423da83843f70723f09a5bf, + 0x2c02579472877870c8c3457b6d3b284eed6cac0d43e93c38af218961a9ec3ee5, + 0x2b24eeb2617860189e832b5a50bd17938b2788858e58d9ea9bbcb7ea175ea012, + 0x18c375a125854f8fbf30b0a138ccb4c771dbcff64c77d1c62b79d70a13e307f7, + 0x7251d3e863183333fdbe9dba4f3abb21777555ec7f996db96352311cd9fc784, + 0x2adb341301b3948dc700e495384dcc124d5371ec6163615ee7263009fbfef1da, + 0x1472cc421bd8fa9a7efb991ea065ec1c822b44fe601640f46995c3f10f1323c3, + 0x2c3a91912dc2c2a792df5e43134bc6d7e582f822994a5c2a6352e789997f9258, + 0x15e8c106e6ea3898a09e7660ec87c5fb217270ee9a8ebb1d052e64f3dfb155d, + 0x196b68215343e220781a52bb0a324e4ca765394d2f3201a769bebbd931dbd2ed, + 0x2ea4a2d5188e98ec570e50b70d0303ede5207bee762ee8932a466bdf891a333f, + 0xfbf65aa42b0d900ec78b68de4b2041140fc85fa3458303276d99826e97a2783, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0x2d93d238704becd76c0220fc95afa0783f9695075c5d98b363f91cd249c47a22, + 0x1011608ec77a11a0ce8b8b1b36ce08de4f93af8682fa026b87d8a2795b71391b, + 0x108c04095f95a9fcbbd038c079842940d8105c509c729129f7cea1c5e968e194, + 0x27bab26eeabbce153dd52489db2fade373a936ac52383034ab82a9e252381e73, + 0xd2611e73e27ed17349dd52e13a90adec9830a5e2c7115d8823d23688ba4e570, + 0x1cb4e6780cd70a0bcb4662edfe8bb829e146a62c4461c271ff1a0d8db5c1974d, + 0x1d429b1257e514fae54614b4648d627169928dd3a496a3d021d8dd7b2a1cbfb6, + 0x919d557a82cd7294d666137090c7348da53c3b92bfa3346bf14903a12e5ffc0, + 0x1b99c14cb08972b58f1e7216933e31e2e67caf29f8e6e998fe2b1c30ecbc9473, + 0xf0435abfab0c4e0ffb1a687de5cc0ce3fed74cf9bb2b559b569a552e8ec86d9, + 0x99366a2b727e153c4e338c7cff84efbedfaf7dbf4c7904854574f75f3d8e848, + 0x187b41d7da085759b71c2028e359907408319e8c6ad842c79bb202ecb419be5f, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0xf8adabe145a57461fe9a583655046a75a03785a0a2942221ae2000664936e3b, + 0x21b8878c75b423cb1f80e0b574b3f62d28785663aa6b4e0caa3043a693bef6c2, + 0x1dec99dbe933ff6d1c4b6285f8c68771b3ee297afbb5c934aa2874765f64d602, + 0x2d23ed96c51ebc9c51489f7c87de4fa151cd8378cbbc701542f54bd4f4d808, + 0xabfef9fb01611d86e6ae1c1ce2d3febf41378ba90a38f11166b097187272e88, + 0x28f60239d945991b837eaeb4693d496be520241c8b739d3f21c7b838ee0f946d, + 0x18ad1fe91d4530ef15ee77e9ff06e2d3b05564aa44613bef3b191f6b12e1bd83, + 0x53844fdd99071115909fc518f92c7d0d7ee91beb16180cf9bd158d33c8679cc, + 0x28f997134ae9a3be6b79f6f3257aff2498774d1bb18f553b229f70076c979ddf, + 0x5dd57491f096cf44399e477bd78c20fd872d357f5d1d210873d01d3a014bfbf, + 0x1f1a859e7cd1cc205ba1a1b3cc2bf04e0b24d32a62dbed89e59e2113d54e0b37, + 0x75f98af212f11e1de886197216bd78258bb77287937f0af8e464f916d7ce5f2, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0x128d5ad7a08858a2ed8c161997ed55c8ca8ff495cd27ea475983d1715cc602d3, + 0x75c499dc0dfb0ce2005e7d13c1861e5f375e03bcf06951de3239d4b56f7868e, + 0x2917faec22c04d8b879d4490a8ae7a9d9cf7f3fcdd33634aabe189b50710f87d, + 0x1a86eef4ec1b75a75d97e62178663f995cf6fdf3913595632105284bce7cc346, + 0x65be02d94e4417edcba4b6b68675b107a25462092e90e7ea887af7870c0ffc0, + 0x2a1d799daf1e300abeb7f5a66264360c7984ef52c9b153f15411f9c62ac84d87, + 0x17c036c19ef8085449f760a6365e814823f270ba4a5e41d2ce4ae1c653f087dd, + 0x2151cb617d9f323ca37ce71d5c77ae83c8490057b9cbe8c17f150945893382bc, + 0x24624a8c4bf96cf50401f7361f74ce162c47ac803ed9424b7bbe4d7465d9f20d, + 0x2c01122a63dbde586507877763b572ccfdb59f2055ff15ef205fa8487f82a3a1, + 0x17a88764e660e91940993b5efc7d317ca4d0e28d7dc164f6ab6e8c0fd2bd111b, + 0x2287b5e929e98ac38199873b142845c015bb20880cd9a1d9316a7027a9b2d208, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0x25527f081eab2b3258ed36e0a72ebbfbcd874e81c49836faa218b94c0a330b87, + 0x186169de0e37c01f31821e0909bc4c7bec2129acf9a34948cf7a8ca58c9b57f9, + 0x6d5d287a7a8d09650979fd72764614e0384a22972d86d191d1255c999d3daa5, + 0x2c1f7628e8aaaee261c58c8966f5cc90e7aeb1dda64d590228e61de098e4ecf8, + 0x1c3761c8c7a1ee1f98871ebfaf81b0b89a5bd53a69966681681bb1352f1d4fa1, + 0x14d1774293d8bb21421fba59295456c98e3e9afd0c9858d6aef305318707e365, + 0x1df2d2c614e4fe2a6cae058be1dc9e56ce12171c7c3bc4b9d1e76b1916458f72, + 0xf27fd9322adc74859d8b58e4bc2595b276061b606acce303f2a90ae404beb2b, + 0xa2aeb992439b6e372a606b46e95bd4b52c2072e6fb28c0689e84b5f444f7a99, + 0x23e0b17792144b002252bc0490e7640a3d47784e77db53af09de2f3dd650e9b7, + 0x2aec9631493082d844e77232cd2202224fc38b2eb0d87e7e5e62c11c5af5d006, + 0x131847cf279637a5a337815fa4f40d51251f6e0174e59c5ff4ac4cb35e2f21fa, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0x1c8f5a7ebf52e4504d205b2b92ef4a87c99bf55fed83fe42edf01645332dcec8, + 0x1eed962a391acaa8a59d90d324a9ad8447d898f4b516db4a289a4bc0c565fdcb, + 0x2b7c65f02b600d4cb64a49b484840ebb11ed7e99a43db9113ed92bc07d2ac4e7, + 0x2b21e821c34c25f6fe3b027b3f9877d0966ee34e7224c738f0e1f454ae3e6d51, + 0x2331843ec8156532e5fc129b95d129546fe5ff9928bce0b17964a9fa4d8d16ab, + 0x22dfdad5cbedc015829fa14df6356c60037761a018d0cf78e13d3805464273ac, + 0x292c701ad0a3bf427a33e1bfcd073edd2cb8b5e6e949906e6efa9356b471cd62, + 0x253d7f1f0d16d4a21b0d14d04b927f0ad96d348e78a7e36107a9c2481f51c587, + 0x12f89c0d808f729c196c25f570d2027925fa37a17f07d9cd86b366793b5b89ca, + 0x28739fec5ce7338db7feb9b2996877e00c4c5d6f1587f24d5d165672d727d4b7, + 0x2ae7492c4a9864de31330c131c06f9de5d50bbfa4b6ee21132068d43e00d87d6, + 0x22d24c6c5b0ddfc162fe02b69859138f2428a54ee04d51b7d28db3dd1de5fe75, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0xce556d3d5727d4e62e2716588f873bd595b1c1a31499dacd96b724c4b7a0848, + 0x2e9e730ca4be19d180bc945c9284a0ac19a2d1b6523bb1c0ba4c105625e428f2, + 0x662d03f6ae59288dfe205ca54c24f7f33615c42212e9e759bdc519a37573214, + 0x130fb7df8e39fffdec5284ca63b4bfa2d450757eeebc88a4876f4538bd398d03, + 0x16a882ce517234ae0932404d34fd73070e27a824e337e1e99eb71abd536a9673, + 0x29c0802ac349b823b5b63267ab07fb4ac43717bfdd344a22ce4eb347dff10b8d, + 0x26a04ea7406058bc1b0892ce3a849ca4d4692db13e1efbed22eb8846f62700d, + 0x190401694ed647aedc22c5ddcfa7e5c0690182d5901c6cd17e72d053acbcdd16, + 0x210d51487ac153bd15fd95e70ce61c1760d2ca4ed3c8904a85a7be721dc2593d, + 0xb0b2f1b7b01b969254538e7e34f31c99abb093463df48171756cb005641b641, + 0x28c21cf93221e40e088a37b7e8c4e4f6b4eca3ceda40ee4b7307c9940076206f, + 0x6131acfb2371ead4b47df9a6f6e7ae744931224d78ea55cc67caaf0e5804ae, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0x2bebdfc924b28a04eafda183476a1a5add23075c9d02b679e1064e61e9482210, + 0x1faf98e88f5306663b31fd4e1e346eebf6e3a1cb1f21142e2c22344f2adb72d5, + 0x22cb488da424d56b9878634ac766c48a306371ab23ababb0688e9fbc2bd2f305, + 0x1ebc0f4f5901ae74815b159db10956d58d8faef0992a2c2cec68919d131a0c62, + 0x29c4ecf2d8c9d693dada0aec9e743bb283b0f02bf4ccfb0ab8fc3fd7fea381b8, + 0x2c4a092b45660f079277c81df9f8f3a7cb74d3603bc839eeb2fbfd798398919a, + 0x145c56ab4720f6ad4011ca83e7a29a83fb11f6f1a5f9fbc2782f7ff4f7f18618, + 0x2809c4d7a6aa62cf849cd656c9f76c7ebe815d51f180e1dee45cde9714261b6, + 0x14881d4e8659014f6dbdb9c1a45f273ff86fd6491a729c1b4cf5faaad83c1319, + 0x2e10104a54b4dee285b186d2ceebb3c520a6f08b0f2dc3ef071aac189ff90a6a, + 0x1aa6d9185256a7da783e9673f47a57a4f1a539ef39f3f7f1686995e7f6de9011, + 0x1433a78ede2442f29e1c90a35c75945079ba472a07a5fff22dd632611f0514d9, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0x2113235e983b253534d3373d425b2e65ad758d985010990e0cc4c8c0971fddc, + 0x2bbe5669cac7d09050c0479d3b77eb9d91f22a19776d9e396a4c79b90cdb6c80, + 0x251dce15ba53f2fcdfd39448e3ce48f74bce1d96cc2b4cac2383a40f45918c5, + 0x25af3b31579c2c0227ce1fbea8085d27d1301236e4a469f154422c0c00a3b47f, + 0x101f2400d1e814d019a47ad9bd6d800b821c2de5fec03914276fd7413071aa3d, + 0x1976bfe37936541354a1d66197e6a7818313cafdc2f4889f7647f808fa4a7b36, + 0x223ac76deff06a630762ccd8db9391023a783e28659eb7f9d57223812b6abd2c, + 0x2ac83b6435ac467384d3fe77f06d349c66d13274d40c37626c0e186ed73da3a5, + 0x1075e744bd71d84cd204e4652afab236f75fa604f833d02e2ac15f06e13ef92a, + 0x9684685d0631b2170daaeb0e82af4cbd5c2945f68dc758f05da1483c2633015, + 0x292e0a7a8cc10221f67d029c700ac0bc1a9e41dc376fd1f7ee52b1aced908f2a, + 0x1592dd8fded27b0499c5d7b77069e8eb2d27ed4d0159955db902ff47cec50d1b, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0x116530f4782990542c91156b83b5283f48a5b3b96f4cc9a5eccfe8db89446397, + 0x20792a7c07e235c08d2cc9d5b4ef2a93b7ab876d9f646d0f4538c7c1ff354fbe, + 0x1c934293f228bc73fa4b8d5af9d93bc21b7db38e654c0f69a82e6d53a3babbcc, + 0xadac0d1a0eb882f325bcd49c617778178187541c3f2b877c9a6e2e200b15c29, + 0x23788446ab58d10e48572e52577108cf0d9fe33539bd0e8ba8d635c0d135b409, + 0x2745bd6d0a95fe5be2bf988b86fdc7d17bdd6323777ffed4b0ef00e692a591f8, + 0x17cdaa3978f7d9243acd9d66de86ad0a1bc5a2767206d506b43fa8df769ee178, + 0x1cacfa3a8850decdd65a7de60fe3d4b063b9eafaa858e4455d6b0da518c6b221, + 0x2291ce130877baacecde1e1932143f97da67a5c3b2bfa99ea099893932fd3e6f, + 0x15adba2fc3b14d20852d217be0744d63363ac5bdc8aefa6be3d94ebca832c3ed, + 0x150619b091f5304ccc7d367cd48d4b878a2de06dce5d9d7137ad6ee307e9cade, + 0x6bcd482b40a5463d05a49cfae4907c05872388694c4548377ef2be93c2b1499, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0xc678bf7b43613dd2c36546b68ca0dd3890f78927c5b7898a79f0051aab7199d, + 0x4d55e1ef8446fdfdd9659d06180dd772bad31738654829e3f68a54625342b6c, + 0x17451474d0a043f2ecdb1c11311e7848637cad312badb49664776d9947a25578, + 0x166f2116cf6846c85bbe1e4c78bcaabb2823e0d4c0c27a6bcec3f1c1c3a4b001, + 0x1d2d00463d86b76474ac56cfbd0fbb7f5071c792f61145f1ffd1568645e83f39, + 0x52fa6833906fac636cf7a1bbe3b6d365f16d917e5786ccd1f303eff8439447e, + 0x1aee2e06db5d4e2ebdf163a8d1ef89b70510c37acbb47b5a14d0c6496e66669f, + 0x1e4d0a71dca74b2d4c0c403a8c99cd9582611412743944d25b97ee4108026fb9, + 0x1a31ea0102b313bc96cbe558f0fc662425e25fc5f9395a42a051e927ae3fa2f3, + 0x2e7d99fc4631683d67b62afc214c8e89bebc91b4adc4625c70fc5813840b9bc1, + 0xba02e66d788b4db2c10e4b63344e564cd24c1a3e7e7f3b5c8c0bc50f2aa8051, + 0x1938e6cee09167fe4f1b6256929ec89307fea623ff00a4c15993fd44b9b9ae2, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0x24ea9e2b25c1d10973fc2758114ac04d62292d75633e5a98d87d42245d3085dd, + 0xb7f3dadf80c5be4a9fe724d8c7ef9e4b4626d9e8ad61295f9482a5bdc1c6615, + 0x6d9a25f5efafbe0738e9c1d8e291d7dcc6e70434973971636fbf957353545df, + 0x57d08da194c641d1c1957a6ff6ea5037640f6b2910f854653c1d14909a73b92, + 0x1b1c3fb5c7160d87cae56ef5a808308a5188abf94b4f127411b3636a5098a628, + 0x4e0f9b281f00e246bcb7f3e5259e4554eba1148b92b1d464727259267b599d1, + 0x1f31a5baeff037edd6912779c79b566c6891b55bf02398c2a2f1f40a41b2aac9, + 0x24ecaac4d6023fb27cb5836794e1f821f6a61924d14810ec882e757bb5150709, + 0x151f138379a4341cfb1a1fa09bb3fc4ea4f58f0c0213bd2213971fdcf1791394, + 0x1f8ffc956b5fa5f6c5700394e863341ded45cbf64199185425651e92564c2fe9, + 0x17ec84b7ec93fc7204915e7cf163797456992c8b5bd1ce3879ff7238d60627ed, + 0x3a67e721da24139c6203edf65ee56debd2db5102b2c193aca10c98e70cc2354, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0x199a8c4c63048f8c92b96e2fe73c3ef1be1e2ae312bc504cd6edcad0bf96967b, + 0x20d5d5315614291c431a1f27ee637d098c6b2455e019872a06bfa9b1322bbc58, + 0x204e87cda44e50d72b36c9a0bef8906abb1471cb4faea1262bbe1f148eedb60f, + 0x1ae0dc4cf8615efcdbe69bf7e65863b9884297d7320b3d2c9abac80aedf519a, + 0x19ddcb6e703520397f566c8969b47605f907fd733a7531330329fd07d0daab63, + 0x224f871490b12271549e5bf1205ac16364f8c6f9cbfda8214068b69f3b58ca57, + 0x305888f9b716c0aad54f0ce4ee1c74052bcc42261232cda96eafd2c17faee5c5, + 0x797616b6e3a31ba4090fc46bf370854483846428e52ed4fbbde16ecdb407edf, + 0x10d0c9c192672de1a9ab86b469c6c9bdf474fd4c077fa2b27e702611295e06b6, + 0x1bbe4c061e88ab93144f0cdf7873acdcdf695abe01712409f942517bf2775c29, + 0x3f37c5294f581af0e0b407e1f1691acccc9b2f0fab04fc68d968627ce38fcc, + 0x10fd1cac0351284931df18b06d6d8baaae12879304e6567e96e024258a63d84c, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0x2f4ce93fa6f69179598530075c2dfed92480e40b5082c1e4d0884a6e5a970c95, + 0x48aa1e38a66c3d656ba67124986f27fbf41e16d1aea5d66b56d7ff786a5411f, + 0x69328b6c9761099bb94e1fbaff46a4643a6d52c2826038bfbad2b96aa800a55, + 0x18c5dfbb9611df4c176034f538bb3355c4ea9a34428b568b3d5484264fe2ec7e, + 0x250964c6e716f188f1a060bbfcc20bf6c9c575aed8eee7a952883875e3469e5f, + 0x1cafc40f71b4ea55f7449981d952e200242a375056b3ebeec542f743029d3680, + 0x1e345fd27b75da9f73b66d7d11fe53bf4d7d9907194ffff926b6fd73650eab00, + 0x1f86c19a4e41622c5cf6d297f3fb0966d1ddf28c14c2ef296d811dcd725656bb, + 0x67a9ca314c1b989a258f5306f02017756676c8555e15e331674dfe2de960aed, + 0x1a8c2c393c5940ee66a9fcb7745c711183ddd8d5336cd2b72880d1534fbd954f, + 0x2d0fe4e3cea76d8b33f29cf85eb4268e0097270b955369782adf6f3b56a2762c, + 0x83f71c1657f460360ace088b5682357e7d591b331beca39de70e7c057acaecd, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0x1029b4658ee5d03c9476e1df7b7ec5447dca910ddf67e610247695140f7ae6b, + 0x2d2fbe8b4aa2a78e6d15b471d034a31c0710a8cb23cd64bf8a105b0f5f6c5088, + 0x2c68d13a038f7cc21d4035f2fae3ce2e44b06076755e64dbc95a48ef8fd32ec8, + 0x255433e441013f28b645c439abd003cf216195cd6ac89e9cca3a2605e2afafe9, + 0x2b6131efd66fa044954f1b2cf0798c44840b9ac5f91f73bc1d6a435d192c0606, + 0xc50cf3d47abc4d5094e4faa45ef8950e9f30f6125953caabe1240c70dac54c4, + 0x19ac7bb02c466c14f957a8683f2dc7a0f888f0bb9f233acae0568493f353b438, + 0x134932780855ca4e70db189d5439192d257a8560daab00be7ac2bb05a5f43d49, + 0x14652e3f019f18958f6e8c521fb5b375f755691cdb4cf7cc5de4ea7e5443845a, + 0xeee4bb3c7a628fe38bd14dfa58f7a774001261e2c1b0013b8abc115e4059685, + 0x1ad10967a8fa3bd36d86621d021c46dba709ff285387c064ae6f305cbb0dc77e, + 0x6fc3833718a4e8937f1151ced67bd1059ab386ffca63596129980ffe0ceb943, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0x16d751a67c79f9914851155d386e13b0058b4682283da2d2078704c75576c7e1, + 0x2ded2eddee5893bd27e85a03d6501a2968b3ef18a20ecf50642d5201fd40252f, + 0x1ac7670ba55f7ee1c2ee56e825e80ee2da811ef8fa08b90d8beeedbee104929b, + 0x64cfb658abd66706a012f10e3f27e0d8c9b83b3e8e5234774dfec5e1202712d, + 0x806d16963ae96badc162c4595f484fc6a8cdf753d18d336aff5b24ce1303ddb, + 0x148cd069f578f6a864c92ca38fad53423c9a8792967e44378305739c39c3951b, + 0x1513984d0c1ca0b24ab794ed86a4b94f4750a3a5bf1977fb6feac9afc85f45d3, + 0x51f998093e4dbb4e7f8e410139a65ea44764f0d2af6ab5461b34717a9561bf6, + 0x1f87df4d84ecd7b55bd03728de507a7c5409886811152634e16cd2d35a18db0b, + 0x956f375546f0b19f6d2f31c5be42795b17904341594daa5f98886bad442108c, + 0xf17b03f697af65662c25f3dc43f1f5e050f1ecf009ab004f3fc632938130339, + 0x2d40326e94d3dd13c0534db03b0f6ba6ee54bb280af99fdd05d1cc7c94c9536d, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0x2b0eee4044939efed29b0a5002b16ab0e02f75d1e193a21787d6a7f93a018508, + 0x1b59d055ed845b4c304fc1e713c622d1dfcc7eca8fdaa57f38d7182d52b1b4a9, + 0x1d2d4adfe8bf73cebefe07a088507412eef5a1efc020c7e3c81fc9c6a11036a6, + 0x2857125d19ae926856a3ccfcaf70acf2b258f9fad70fe242f7168ffa2d02d2e0, + 0x2f1da0ad4d4cdbd868691a65495006eb3728c6e410a57db82f874671f75d7c81, + 0x294d34350a9bbf726992bee62b3cd7d2a333002340a4bfed74f6209c4b6173ce, + 0x16e5f374066b223ca5a2401f102d65f5e7fbd677905b2e17e568612ff96b602c, + 0x17c1bc44d70706417225c79dcc9db569c79fbea66c018f2881321c4877b7fc31, + 0x264cd13057b3635518ee4425f88edba986a49776e94760a4d73b17902cc0d359, + 0x2b8fa1e65fdb45989701a0f231114c0ef7a8fd3725c62070a9d748e5aae95827, + 0x79f16e76efaa3caa7e2f266ae7b3f1bbb54a6ee571688463c9d62b17acfd6e8, + 0x1c5a6ff0893053c43c552cf41b68b48a7759e63d0fc6069d2ee247c170f71d25, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0x277dcb1f82810d091b7dbd02eba6e8edf5c97b08407a469c4ad99ec0a7938a26, + 0x1507357ce338a6f1c5f01907a91c62082e6e5182cd8b8c47f9051b2cbacd5238, + 0x10d9fb4dc60b7064e8d6ec643727c394da7318244c57696bbb473e2bfc273cb0, + 0x51cdb7af55af1483816cf02db477c5c21a2e16760ac17395417afc92cc78979, + 0x57d7491951dbf51f0b1b05406e58ea37d61518a67546fd430178a47e5c34dc0, + 0x1a512039992c0d21bd7f2436bad315a3955b38097568c306fa92e603d4129ec1, + 0x3047f751d881408a1f583df677a7313f341d0d90150b0031bfdaf5a17c1a71a6, + 0x182d95d647c5f27363818039527bbbbcf23f4c143f6bb98b064daa5f09d127d6, + 0x25973c85813c7ec78b26bd63395f522e0f8cfb0fa6a82375b9b65ef0e24c2aff, + 0x30016e4e94afa204d5c420908f1aa18fbbe286a9512a0f7dd492b268e2bd4d0a, + 0xde8759915e7ab1ba0347e7d3cead6663449cf3e56dfbc87b231f784a6a16f6c, + 0x2b3e7d63f286ab49bb3ccb30f9a8d337c2a871799020681e7c1e5170569bb6b6, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0x22f6dc515f2a6d844a494d3c307ec715cb4ac439abab7badd9f0084ce1785718, + 0x1ec843ef7fd4d4078d3c68f3f699197d1818a3321f64d15d940ea6816db2d4ed, + 0x27488355bc40e3b48175e215bb7937413eb1fe296f51266e42d421d1d744859c, + 0x2e5cb786cdfbe0c74b05fcc700ee95936658634d6bb9152251e1ad38f3ca6666, + 0x92f4b8b30e895442ee3f481121a04542cb01e9a458f3e61c773328e1b887f51, + 0x2943525f7b6302dcbdabfbf7ac5c27c0187bb016069c33b3947becc68c00a873, + 0x22a61651f69e2636019411d42edfbcb0cdbcc3b1c0f5bbee8ac9baf66b1b8487, + 0xcd43ea643c19e6eec4448fbae1ea6c40dd9665d93b04099658f4e216b0d7925, + 0xe6fb9ac72a3c4754de58d5b4ebce0f32aa651db3d14d5adbab0edf79d746644, + 0xe18bf3657ce59002f57e8a25131e39534ade10d742313d81f02beca3cbef04d, + 0x24d31ca462d9f59dfe6f114bafbbd67bbc9fb15e260bed3552e06e559bc049f2, + 0x1663ec74cf67dbb8e668d7eac5c8bf51c5742c090f7a707e297d44a0e300b093, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0x159eca9b923d7cbe5bd8ca7b3ded11c3ce6226130a63cb905289e0f02a5351cb, + 0x2abbc33b435baed63f3c31aa583ebf8061236d423321e6ca666d33a0159b1193, + 0x22798974294faef1e314beb8b7dffae46b50276230b06c98069b742d5bc789ce, + 0x56841bcb1c18a70dd298ada142c577a249b7ca301d1080a6be5a621d604f15f, + 0x1823a55887acaf96966399d381bdc7b8a792d40d71e5c5dc24a51d02f9946cd2, + 0x27bb9a8678b0a2cbd911e61b68f4a6928ec6f3db90fc28884af8e20ef711842b, + 0x1391eb35e10db17d84b0e7dd45145a754977c4cbb90ed1bece966ab89de71f10, + 0x1ddaad4930fb9cff01affe0c6bc2034acbc20df09fefb4fea7c346dfadcf99d8, + 0x967a6467b486450b51ca8d529d6aea1efb101edf31f3646efe1e969535a6a8c, + 0x26edad91bcac2202606d579d3682ee71417af365a5bd3cdeda16158d0059f32d, + 0x9c8e2fd871c35f3448ee49d7e7531dcb5301a6e748809ee639b152896773878, + 0x2de254340f39689fb3c5e3740c1d1ceee26e8ef87c64c8b3ef5eeae2712a2fd, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0x229ad4c71354c4b2ae2f011e374de05f72548aac7f407d8f52f00ddb74f2456c, + 0x15d1ae9e3d615f8321be16db99bd43b9231dc51fca7ae9ef2c1ff50cc948d5e5, + 0x1ad595eb60e44bda1591a4a7ea6facb03ed18e8e4c7fe44aa4949c176b3fdd93, + 0x21c6b958e8a24ddfd5686e18a1b1c93843ea3efba13869302f46382e6a57e567, + 0x1b4643c47be36a9608af217edbf9b2138045e295b062dd4b720896c55c1980e6, + 0x44415df1dbbaf342d11d905f569a68a53cdef58ce2bf19503ed0d032ad3cb58, + 0x2b1b266d410ad7a8990d350e5be5b1be70822f5cf0591cfbc00302c6a1504fad, + 0x3cf806a68e9ee25ea00b57abdeb9f4b5ca199f9af3428a8b5cc87db1efe81ad, + 0x1013c9c92352dfd09c3e6acaaffa2c44923b35492c5691bc7e9e734072fee822, + 0x18afc92340649e0d9608aa526d2f86866d4bc5280c3f45addc6567b8339286de, + 0x265cff469832ff20e35d2da4e50505b8e17a4eeaccdb516f36f3a71fc916a82d, + 0xc83c2b9df3aa4a874494e329206968b89b23b02f35258788e9bafb43c47c973, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0x10bfc00fe5269d28301b200756e26cf1281be271d1300b11d988a9ebc062b10a, + 0x303c1e41ec4614539b4edebbce405652475c1282eea708cf2ff39ba8aff4a4df, + 0xcb8f9cbe9420f6adf09e987a8bb44158ffba89abd7a738ed54ac6a95f17500a, + 0x2f0cb3011c761f84dc5b01ba7a89194919d06f94304fb99dcbc0ad7a7bfaf796, + 0x10151a6d8c2e4d4dd265b3ebcc0e778aaf056a02139fff9c2ef25968dd2abad9, + 0x1e50838bb4dc4ff216abf8455b8585010107e2d64d1fa600f6f3408655d36fc0, + 0x528850ff2c7ccccd074baa85e0989e57ce76ea60b697b8ff19c97f1f9b5771b, + 0xda83be0e16ae4edebd1fbbd5b3003486f5783bd79164ea1c6a4fbd945a285b, + 0x1bf809aaf61005aa262952e1ac2141e5a0aa596fb9d828cf2ee2639b59101e65, + 0x231a51ec8565bb72d6791bb758f8abbe5392ce08a655f2bd03f7593a026ed371, + 0x227aa3bd0866433629f3cfd228e20be57f8499f4a5597d3429c40eadb238f1f0, + 0x272b5a76f45cf6eee3210ca6df476b2555fd79fd06180b3f7eb546bdf2e9e4e8, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0xaba393911c001b6e701b44726a176bcdb276d02d3eff5e70b0cc16aa7570958, + 0x282c157f6cc7614232f974eb110212f786134a965872ff9ee9430cf05a7826a6, + 0x16cb3b06654e4997a543284ea7d12efa7b821e96889b0dfebaab9eb705d829b7, + 0x2364c3f74a3b18bc2af5f89126552fcb58c80ecee9c05c0fcb4e39332dedb205, + 0x267b1113aa1f20f45d5bd1e042290c8d1e7e7b4b5628184704b81f894d07fd0f, + 0xbd187c337ead48b6889b3e20026dbf604729fb27460fc1b51b7b3a03e9812e, + 0x2691351a32661a9080480e51d758cf0e3bbb9dbc43e108293576c153dbb92654, + 0x13c49152d941d3664ef620a47f29229b8b41060b9ae5880658772ac615f6c48b, + 0xac5e68b38810d5343dccc099076b7ac9388c25cd6a2b2d182800156ad18b438, + 0x18a7e5e6e2f6d92c409fcf6bc1978d963fa8093bd83667a95f19841f1a826022, + 0x1ee76fbde9ff833d860abfe09f44cce584cede5a6a20aa765975764d97c3c38f, + 0x29139e18d16666687e950c7f417aca14588356d6737bb72d04444fe31e15c292, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0x27ff4617698e6b395ced6d0e40bb327a4dda5467ae001e4ed828713c58e4cf72, + 0x1faeaa26b9d4016a7b060a1125b5b83e22174ac6131c860d77c34cf368d4d5fa, + 0x116b96192f543b8503130b1bf684a9bf282b41f400aad0041777f741f97d42af, + 0x1ace40f357a524887cbc0748e9cc2bd2f968a87ef94468359c48fdd333eaffd1, + 0xeb90e74f33e537563c4c2f8633e6d8f8d2304266741ab5b0c0c97a89c4f76b3, + 0x15f692b65b0e4a2729d1d07a728029a22e6aaf2d8013a26d80ea2f4ed7230b2d, + 0x199c258f1265f41f038d234249d79a9d7cd0f435355f9c9f9d671d12b3d81360, + 0x2aa4870dc13bc48b19f3d7ab5df282f855783d5cb1539cf358d235859cc38328, + 0x2fa96e08d4613eb78063774846b608be0b7014165df4207b83217229d452336b, + 0x1e45df6508abb41b74eef391fe603465e142e7331c1a11e6d1a6dce3b5af459e, + 0x157326de3fc278a3ab49527c3bbd66e6944065a068afdab3426acecda2fced3a, + 0x13cbb184686e4e800c03d32b9bb0e86322c0547ff70bdcd6b6dd622fe9cf772c, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0x2195bf264d78f5905511e946fa2bf8fd1c31e251405f24edc679fdc2e28c4935, + 0x2891a04c8c9333c3f86cb9c27db0cd4590b91574f283d98d87588c5329070ff8, + 0x25774ca47fb81e980d6024bcb7849e10bf90974712f1c15b3c5e42d48a990b32, + 0x19afc1bfca44fab6dd8cf347d13bd9d679a663ab864dd7474c095855a69489aa, + 0x2a855f347153503391af5cdd8f33ba84d9b7f330c5d71a3d4d1308aa36ee1f5e, + 0x2169a917b5586a2cd1f44fc39acee8a0af21c0b0551fe2823662087b50d3e183, + 0x165c3839b46f2b8d9c94cfd1acda9fe4cb4b37b64f7530324e44a859b82c083f, + 0x12bf9acf97c5d1b2c23723541455fbfa679d3539879434010843e578fe33ba26, + 0x973d4990abd501d246a5bea2b5d467ae07f8f141968bc7049a8d7d100b8d80a, + 0x281a0f1018049ce5560aed11919df7e93c341795c9fb1ea17ca7f6e61f56450b, + 0x1607dc7766404c513850fdefc9f3e25d2b9f6e90b4f566418fa142b787ba1d2, + 0x100010328a776d1e0c53f55c79556f12bee9f2fc908b0b19b215253b91c071af, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0xfe6e334c004b36f6a9aa7a1695325b8413cc3a527fd77093960d6da1da678bf, + 0x192c7a5566dbab04d61dcfaf9675cc88833477473f0742c7df458dc0c72492f6, + 0x16d9f79f4e2e32895e9b7d3a13cba3f9055c22ee00fafaf94cf1a2237279c28b, + 0xb3c970c3abc81a5c64df8177d69ce62aaabafe4c797eada6f8724ed59924963, + 0x1e3480b6b43165f2e9e98cdc6b1750c9f8552375c746fd9318f6e98dde188146, + 0x3ed9978d698020e1627fbde78f83dfd7267a525315d03c27f934a04901d717f, + 0x14f962e4f1786884e7ec52bda63442115550a7523e9840ed60e8ce1d97e81c27, + 0x352ef9bb93ac53fbf0cad44a4c9f359d8be239da7c8da512c3b8f339f1eb8ca, + 0x1d7daf3d516993cdf2ab5199f7fa038ec18b7bc1d7643191dca490734b41162a, + 0x19c4fb9c7330292b9859c4471c0558692ef015cbd58c7d6b9f8f6a61701055bf, + 0x22261c2ca798dbea2a989b4959a6ce59a327a1a5817ef4d0c99147d79e119d66, + 0x1c8a822a7cc949bc91f32624282c0b91835aecebcc805add937f2c33ef2b13e0, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0x241eafca2ffd1a89501dfb8ee9f6b91c270d2edfb22b77f5d96b64c074972866, + 0x1ebfd44d328c120e25331359b950e96faa3b24d803cfebfc3fbdb5aec7d3f21e, + 0x1d45f9e955be39be29b72435e60ccb82ceca4dd1f1bb242ca40461f9966dba18, + 0x3e68e982b6f9a1317a8c72d1519c8d992747107cd1647f55cf86f1274921934, + 0x24d58310c23fa88e127678cfdadc69ced4344aa62dffda5d17bfb5cc6cf92164, + 0x277159e31996dcdb712c9a030b14b40e45704c9debbf6c83381d23b98277564d, + 0x3fc9ff00ba6b7b1584eca5fb9bc2479289e05be8f7fae084849424cb08a1412, + 0x102731ced3c51f13b9f0c571a0327d5b16984151ac388ae71008e062b103c7ed, + 0x2aec624f610d949b7e050f9240bdc67eb00b17980637731a93401129babc51c5, + 0x348bd0822fa0e5733e59d37c6c25354a899286210dd11b006b45086b8936e64, + 0xf7b4685de34e45e8e884726809202d717000926dc62d3373ecdc8f6d6105a3b, + 0x229abf24fc333d2643cf514ec877c3155b9f5d4563975ddefa179e69e728ae0a, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0x1e9a882703f9fc17e0b9b0e13c13361beb7f37c04d00ab391d59bff4ea9cc738, + 0x18ae81de5d561926c49500b4a1c817e127ff35bd92ef713b8becd8ca934e18ee, + 0xf691c4241640871dccc03e386a591c9068711b69e35c618ae8213a7b976b467, + 0x1dd3a781963eacb7623f1a53996b79b1c5dbdeef63ba509d264179d7c7c58367, + 0xe30b8151c59129f74a868583f2da36f7f32cf07d93a21dcb8a418929a3bab4, + 0x176a4a7f6bf803a3b2d7b366d35468d449210f48f31753fb63d4c50a522f04ee, + 0x2d0138a0a5f600964d4ba4ce8391caaf610e7b9cb46ece6bac438658e7284606, + 0x1208049ec66dd8b35cdd748c6b7e54c3dfd4ce63937a8e5f5d7bb55c70bc3256, + 0x1c9f3c36dfe21664afaeb0f1d29166f2896455fe34a3e3a937767a3de6fb92ba, + 0x203ca885554ddda35c4ca58ed2150867f677c99a1afa4796fbec4c3ea534b7bb, + 0x20e28f5d901c425eb6d48980e9f86b212911fd94de850663e4bc4042cf2fb8e, + 0x8eee40dacd3ba8ca8953eb7713bf9c642327bb96f55a7200f7f19851a25147, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0x2de2cac04d23e8f84478018e4160a1cf34d66ecd6b4cb8ca67379b0dfed1707d, + 0xdee104be28ba9a4493e05d14072223610a77ef655f646a8ec1f254146b0739d, + 0x198546db1f9b3073c570cf4937bd3d716336b8267aeffda95debaad2764c91b0, + 0x2df10c785477ccf2aad54873a099f7a5245b7a1797d4b7692df35a01a4265e0c, + 0x38e6b803b72b22d07f3c4d4da85d583d1952dabe6f4cbfad8ae16ffe5aaed55, + 0x20ff66ad9f9056e8a0c513785f7f1aa1ad0b53ee305429c5d299ecb3b7d3ff95, + 0x2662e4ce6ef014cf95ae1041e8ee8f25eb02d188a234bdbcff2a4fdcd222fa0e, + 0x174299b27d180d0ac59e31ffb101a68ebee5b5e17e8ee251b61cdc2d73b5d96b, + 0x2cd73c6ce46c664bab760c4d73a7f05132e1ddfc0ec113e9b37f9144f7a1a24a, + 0x1c951a5015ebe45893a92af1b5b51688298fbbba474875f7b9bf97faaa69cdfb, + 0x1292a82ec348fc639f61c1b9d4f48e1a729f8e4d297289c45deb9d79245a7c6a, + 0xa0eb1649895b7028e7b286f147cd47655fd9380ad96b12f25d4d50134f1b624, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0x153879267fe585e41277a47095c2e71a556aecc89b880549a3e6598a2b679888, + 0x20564715ed17601ede44b0ddeaab78c07b24d7c384b2a278ae5902ae4d53ac21, + 0x244a763e10b0ebfdea4ad6e115bfc6294ab8592515a0f103750f23ff4745d4bb, + 0x2313de5d350a08f83a06f60301627b52170678ec4089d95e31a85ce639d4d3fa, + 0x2f61c7a357564272a6c31f1d4a2c37d68f947ebae5ef06f0003f47baaf8b2551, + 0x2ba56182022bfcaa94b28c4bac74fd7bab368e2f17b123aca7cad3c07377ba7d, + 0x903e97b86b03d63bda9d015cfac4e1df0c7eb553114d6603e1d9cc6def5a2bf, + 0x17ef136a59507887ee376c9d03155d5638f73695829bdf753f2027c93f6e0ff4, + 0xd2cf9780d3b8665f07b485f9b61c97ad43523b52b89a216175fb479596b429c, + 0x2cb10c6713c9c041f988e1d16e1974db3bbf64fa6a0dd716654d2f3d7ee3fa08, + 0x2a7fac0f7cce1677e53465203478eb2a87f4a5acfd0ac6b10b24261967f265c1, + 0x150f1a3251ea142ce9c8863adadf908f98b6f4eca4fa8c7f60834ebda805efce, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0x1f5f9f0a9e7226242aba685459ba2d087305dbcd15238e0d61537fbcb4e8ea54, + 0xfec778388bd29f1fdc01719aa2acfbbd07873a4c628caadf04ed461a49b5730, + 0x8fbb80d8ad67e52030c52512f3947eb0fa257e7a6bc97dbc18848ed6843fdb0, + 0x220ae6fc4a1411f922a67c3d2191d16fa72e4485881f5c44d07ad1b30ff72534, + 0xc24db144fed773dbf4a285f6b292f097e73c4210b64f60d0471099526125207, + 0x153e33da5f9393fb14de5f8d9ff25fec63f9c284563c9b75485b8c5965716022, + 0x28190eec890ed4fb51176a21643ca8bf8a4c6d1ddcdfbda70baee9842e771e0d, + 0xd352d314f8a649bedac97ade9cbe51cbb4c1d76124bcb753ff46124ae2c671f, + 0x589454222f880ff67b3b6771ac9579115ef98b4a5291ad1f466c37df59f7a0c, + 0x707968b36327eb7bf42d881932225d1e6a9cbae3e9a9eb1a3573575b081525f, + 0x24d15b907584822d94ed3cfb07644a1d9cf985b94ac08fbabbbf5070ca3ba2cf, + 0x2d51c48b63d97625628fc1a9c265a29f4b5ac1a1d0ba807f3f1d6a729e8d0d7, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0xc5d3e1681af8c731635a66d82e8ffa52d6fe9ae4551c31d9ce5c7e9f1482f3c, + 0x19f573c7bbaf4af57ab119d9c34a976c7a2770e9960f8324bf938e67a40bb621, + 0xdd53d93a158832a63ae02346cfb050f4aabd93d2c376a694322b70020af739a, + 0x122168471be451e1fe2383a1a82795668084d4602e136c3533156ae4eb44e5fe, + 0x181171e6af7921e268f8e4ca02a69df02f99e374f086433e2d8438465b878fa4, + 0x20fde424afb171516bdba5aba1302f3c40adbc6df6009941ce0978e1005f1570, + 0xc999a3c07697cd6e4632110862a0e3cd6f2ae7ead5a0c62f83e57e3752726ac, + 0x181e43350d64b75df7c57808060a8a467304a9b10766426597fb485016642d1c, + 0x22f941438fb638d0f6e1013d81672149e91bdd794816a149426830a140ba5520, + 0x27bc96df0a03fa540349df2a46633309b8e0d2935a624c7aa51cd859373b1d3a, + 0xda6574a31cb0b010480dfb6ad33015708e71c420b8f3664186876afb8b48b69, + 0x2a932da3d493f5d229a00f18bdc6b13a00783ef10510ef02d3836a9728e75653, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0x1aa840ec7905fbed4b22675c84cbd527218db6bdd21e9558fef98860bc337607, + 0x2c5107353c0edc8e05ad36b277477c9d3ab2d26fd43dd2252878ca814c48459d, + 0x1aced21cae771d0294a1630be67579d81245093d2731898a72b822f8185ef3f8, + 0x1a24a7fa4d6d5498af1df2f86ca66471a340c4747a1e24f592aa7667346aaa8, + 0x289caf37dc4c64fd8c66718013fc3f1492b3c76cd1ca713196aef3d95281e3a9, + 0x284c43505df8fa7ddd6f9ea7464f3caca8a3b3b55d39512a38b2f37b7437802, + 0x501489e7c91a13086c850a7174848dd37bcb7e6a2f8571ca3086415e22a249a, + 0x1d911e709cba9411cf221392b1d8e8f292d3895e5cf250977f7bdf724637e7a5, + 0x26ec755542bd45c2c4968fcc98192cac25bb539cfecb7c16c926edfebc0dd4a9, + 0x211b3d812f9687467d623861909909e8a579e66c135d0ad0d36038116e858ceb, + 0x1835f5c44c7bec7bff1c814c38d109572702ee85860c2977650db910dd555db5, + 0x22bb08010cdd744ace85c758c58576d6b353ca6326e9de8ca594c57b40a76b48, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0x178bdbd863dfd248db7cc60881b17996fa8cb0f5a806ba37e818d493dd4d04d5, + 0x2c2feebc25c3e9911fbcd7c77ddfc8feda0e36b3045e86059eb2507db84b20dc, + 0x1d8f0924e2fe93b786ea1ca32cd7dd268097e1144e5f386813e40d7de6385414, + 0x1d7b4297d5b583bc00d946ea2d45e79bca3b869f3889a3ef8b6986ee80515603, + 0x6b29e8a6cd82571306523e57a88ae2f1c627688af6a57ab4adec48071d864ad, + 0x23f708026a0738512248c05a5a51dc0f0b64cbd50c98f2c001301a8dada15649, + 0xfb9b67606d1b70a59afef99cc15b51ccdacd8ac412858e37fd0a5b685aa1187, + 0x2e507b8087200a7b14d7c84650e5683ef78d7e5281b489d43524206ced314cd2, + 0x1bec098d210e06aa6b800469725bb7d361da8f106e3df06fd5788b3b423bfecf, + 0x6ef2b78454ee5f43388a7ea4728996fcacb8c01c644534fa590de1da8642172, + 0xd5662f25569baaa0b10d66142378f0ff302a3654da318bfa370812bad2a66fc, + 0x2bf77b6c0aa149a79c695d67d64005c90e926b44890085b3fe631b4a8da64760, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0x1bd8975c90ca4e356f1c37f12fcec0ef5ecf484736f375f78566ba8aa9e86427, + 0x2bebb46043c675d8d4b13e9d3c243f49da64640954fd5e194022c846d69cdd69, + 0x1fb7e54c00e38234348206b136e17db48743a1e8833a4146f905113960314be1, + 0xfa50d544f0434df48d3dfdcfdd164b9ebd8e57d7a60be66b879294a40a9c396, + 0x283ea6139b65326666af04d9913f3200f9b93067867be1f2431796e9add5bdac, + 0x758ac2a306bb32c1030578921fe09a5d40d83d968ec10aad31a15a7c56da8b4, + 0xf413088d4106e8a46bf7cba046d1f47b7f8a741400768835d853830ea00ef3a, + 0x466358069d58f4786b2ca782dc4f7a6786fce88983fcf9275b9a5850f814f28, + 0x1385f23802d6bee8b76743564dd5510ed1200f094ae6c16f03ff8b4cefa07047, + 0x108072d197cc79b4188436a0c50845d245ccbfd1480a4882af2cc88351d5419e, + 0xb6d297f7ec667c68d5d7ff7aef48259dde62daeac24b7868e0fad90ab3f3a79, + 0xc82418faf403bde8e551554f4c8be945cfcd1f78615c9525d3c607930b0aba9, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0x297b1a1c6fb19a9f0490226d23936796caa8c47a390ce5e3414d91243adffdf5, + 0x1d8de05dd33fb6513962f6bf1406d3da402064e2d32000dcfba1aae1d39a2d97, + 0x19ac0a18a29761fe4968baa2f8d4d4d7a8d241c5fc5cb54a13997873a4bf8f0d, + 0x13009a2e1be50b353babfbfa0c9fc48341125c9028a93d99b16c31835e2191cd, + 0xd660995842ce191476ad064a5599e2c5415f48ce57392e66e671a503a30b119, + 0xe5587ae4cfd416edf434a263c9babb45d793a1b522fc96e7845005f516944b, + 0x10fbbc420434916261f6ce95d1ca7497b8237143757089de2c813388acc3070d, + 0x190d15507748b38ec5d8d96cbb40cbccd3cd004f1f500f3a8fdf9d9dd05cffc8, + 0x70e81c5cf9512b85087fec4b044bcacdf0ebc36939e0e33f12095929b153fa7, + 0x20577171accc171de1282cef827a5b3f7620c29566598066037947da13dc09fc, + 0x105c02eabf359c9fb180c1112e560bc894bc2c453941f29e1b52c28c0d8c6c31, + 0x701986232b2471f9bb70c70941f0732c59b9d1c1d7acd7df2b5c9a3d1063397, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0xbd0cfaeacb5343bc71818eec4baa3eb1f73e5ccdf4d4fb1e585b9326794d8ec, + 0xab6ce9fe9ad13beeeedb535f9cc7bdd51a9edd426a54a9b85b6f23911dbcb8e, + 0x20f5023d1e52fefee124ab42f5eb28a0c18cea887e3a0bb7c4626ee694946984, + 0x180f0ee72343b33cd7098990a9bf33abb509d454700f602d23067f031a314ab2, + 0x9e006f3e85886370bc11a2c92d6b1905da2e1d7389fbbfa8ce2b0c3797b3204, + 0xcd828a1733f7fe84eb56482b0c373b7bf9ffee9c70933a70782c46104a7abef, + 0x14ae5043d94b8f236d770e5435d370e07be470537fa8734aa62453ef2dba83ef, + 0xcfc46dedc8f1535ceabc7507cb5bc7dc27a44b69eb8d799ea037b9dc0cb49bf, + 0x13d10cd39447e65f03bcc27657ce46b8f4b9f0d6d0d9052eaa700aaac4e56204, + 0x1d19d4106503a113839685de852f7dfa1ccd2131552e18f9e62799bfdbd394e, + 0x1c1e57d62f76f88539ab7fd73bd7577c358aac8bfdbe0c0953cceccef55b1c7c, + 0x19f2dac762392328c37a5a54d4cb980383918297078ca2fccf8605c52f36ee48, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0x11104096d51f11f8db806853a470e1f2838eec2abef570a01a7bc833a27526f3, + 0x203846151d74394d322ecefd82202cb29361192fc6692f8de4c0788e5364bff3, + 0x2a3214dc89d8794cc308f0b2fed1240426e9095879935f4889f7bce9b06d1223, + 0x296caa3afab57aff0ceac16ecf05b6887ae6981c263b60b49eaadbbdf5332a76, + 0x2ca633b28c1343b7c3ca88c3b6f4f9da113daa93280626e98b3c79d6932d3932, + 0x2c62732b69393a4495154205a9b636650a201271da60b65433419ae8f4543f2c, + 0x54a20f1bce174b2063f5581a86913d9edb5b6b30de76348a881f320afcd4c0d, + 0x12dbc8f4c166edc2716c576248af681b69ed94ffa1e5b3b48459c9787ce39569, + 0x13d733d018ed7c6f4a1e471d7b8a6f36047ac9ca93167d7f0aa674f1704fe7b4, + 0x2baa1b752a095c0d7552dfb65cf2f568b47a132ffd5000cba2720ba8ac4c18a1, + 0xdc97cfacd4771b400ba35d33cbebba737c70e84f07d0ca37dba093a2460c944, + 0x2eb71ba2764a7250281b7d3506deaf0416593ec3428df1a9fe2312e66541f31b, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0x24a6b2f63282ecf9be0988f99d0b11798ca33f2c8bcc4e5669bc7a256ab3594b, + 0x13b074b54de58e9fa17ce6356d3a6da3d800419d9a7170e3bb1310daa4f4f96e, + 0x2711023ae2f03c0399399775a8ca018e7b91e50fb4c7529bbb09d5cc88dc9d90, + 0x9fbf1f0c9fc28e92f2040fb7b132373a55bdef07f9009c3aefd13ee0f7b369a, + 0x2b5a1ba0a4702083424b045869aff8680388290f4b164cc2f022b16eb0e96e58, + 0x1292c762ad6a3abd75f5ead608b8f2f90f8c528b772a42d750cd244d74db2e86, + 0x99282d849ffac983bc6cd99827a1d368dec42e7fbbedfb56a6947854f4177b3, + 0x176eac7dd262c43fff3d935c0c11db3d23b0542a6e5e07502dbcea633ae43106, + 0xfaa232a1d0ceb281c3a428f3e67aafe0fb1a27fbd58c89b3143f486dde5db27, + 0x20cca8c39156be9d3b7f3caa041af52ea538f3ec173cccc0b3497aa068b8e1a3, + 0x146799bee14e96cb93165e30306e78be322d11b4ff008af316286989d648ebd4, + 0x2b1d7a8ffc222693ea0d5398028d6042bcbfbce6894aae6c79c02d3398fe43f0, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0x13a158f9d67d4b35e8187f741513e818c32a15e9ce3d7ad17e5e0ff76861073b, + 0x2b64a21d911a768ed8f424092d85badea0a141699d41bb31b44d05ca7677f622, + 0x6721fc051436a604df0acd76947426dd9464034c79d02f434ebeae270b8f113, + 0x1ffeeeae4f5475d7b8cfb723d7daed094e18949532bb7f47635ea7290d27b75b, + 0x94d465c413d8f36b86f1a1d2cf263ec81a2588fe3784ad6c7e7abecb2e59853, + 0x205f5fdead5ce83dc8000b0320741d41c9d2c729ff5a7f0cf8acc2c875cd3257, + 0x1978d9908c11cde5f456e20e6ebbecb4d06fcd7e31e5e70ac0efabc721aa8a8f, + 0xdb51092fb5654d04e24dbca267fbaee53776bde616f4f87975b9759cd833207, + 0xa93c02bfdbe4c17a20506b1a5c56caf375aec6dee3b0b2a0884a48b104c00ca, + 0x26d4bd0047fbd72369c8f4834ed8144c5ff28a42ae16b56818b842b9b4d6b9dc, + 0x17c89c980d214a12738a2939cc7fc425406aed9be9a932e0c427991610c0cf73, + 0x49a23ee91a6c076fe5b135cb6f92a8081c604adcc21c8d6456332de80420263, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0x13f9655a5f1532244d4e030e782ca3f9d236f8d302af289b9c0a946376b45f3f, + 0x271d8aee48a5a8dc6bdbf29a491b31f24c71e023554a92693eaf0bc68a6f0272, + 0x250f4bf66572c4d089c73f90e1ffed7638ae0f926523295891cf7c765abcc0e6, + 0x155c20d00e84b634d4884c42359c91df2fbe1de2f75006677041c0e70bc23acc, + 0x14c2c6a209a7bc6aa6d978fb994d95646613ae8e6b0e0e5f5cc8f5707766c7b7, + 0xf12be26119ede0fddb6393af22db838f258136f2031fdd223dcd8e1bea243d9, + 0x2efdb0edc82b4dce032308b04745dd1f1fbbbb5640bf28b188031e0cb2e1c1dd, + 0x1ff34842585b84d2bb8c9151b3f6c65f48b84a4e34b07f60192c13a6ce08a7d4, + 0x2d9fc37d4a22c1f195838803941d2f629e69eeefc566990919974d8e7aa968bb, + 0x21b778120c0eb0974971f5a24e29c204042f8b50a61b785b7611b8c0ecc6bd8c, + 0x1fd36ff9b7adcf1b3cfa6ab317bdfe9115683da95b29f84c4e113fa6e55c6b90, + 0x151cf47cc2e82f3eea09b8d6aa86037caafdd0cd43a85ecf5fc3d314380e99d8, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0x19c8e29952ab4d0984bf1da922e2448fa9910c0123a999a592dcb473f296564e, + 0x23331f65cf68a733b5e8142daf41bb2cbc40b2c334b78820e92852637f1e87ab, + 0x2a7f938a6cdc65be6c071c8807ff6df4c48a36bfbd92f55fd06c057a48bc8aff, + 0x2c121d40b94585543cbb38980aa3e320f5bb460d165fed90e367f2799cc1e8ad, + 0x2082427ee8b6508762d08df82f8449c47d4b4b117165ff4fa1ff944d63b74d7f, + 0xbbf36473715a6bfeb2bd46b4650b2e48b4fabb9059c1d41675fa76d880edf08, + 0xfcc45095ed5a36166ce4033e91caa2446d9594905b652b7b56bfcbe7fe03ff6, + 0x270c8e9de025f4460363730d789c1f3dedea3343457841db516e129b670c25ad, + 0x1e9cfb5b0f1dfd2465ef5d2731a8d5d26b5479cc6b6e438783231e5b0e805faf, + 0x1884f4ef9e723cc405fe49803473ebda5080731b4878e1d3a5108fb20896d14b, + 0x182b8932fba285b925b7454327ae2a1aef739b088bfb47dcd675730bd1aafe4f, + 0x222f2075bf57fc059a247d5e733b3828fec1aac68509a2c0e4a8ca1fdada90fc, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0xef4c76e42df7e6d4e71b536872ef6816d62d64c06322bdaac4aae65ce6d59fe, + 0x4e28c59213cc28cfb7b21091bc98169875e4488188b70a385197588025ac778, + 0x2d69c1a48c1be2b798dd77218a0653f7bec46bdefb7f55cde3e6d28f56527260, + 0x198d2bf44196f81d74761554f80cc169eae8e817f44ecb588bc64f6277f1d625, + 0x13c8bbb561fe1109612865ee008786c5d50158e42d9e91b6f52b02508b67874d, + 0x1eb37605af262ce36884c03967bfc38d8f625e080c7bbeb4bfca07e25458d12e, + 0x25cd986975f4cb765e4a8f17706cc4438675bf8ab7b110470d88dea1a64f66ad, + 0x71d02268b089992a8d62240d94fe171bee083b1a2d9bbefce3cc7c8cff5a577, + 0x12ee53cf69c9a0be3be3de51789d16cbef35961c6114e4b01244d814a5ced3a0, + 0x94acc645dc2e6929022f4b4b946e8f51ac595fb3200074cde24b86643bbfc43, + 0x22af41b2a54ccf55b3030b344dbc82eb8499ca8c67c191d4b6873bcdb7639f9d, + 0x14c87352fe94d929e26aeedc2421c5812b7fbbcb00a7b20a79877ee086416778, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0x21cdd152af751112267ca585f98b2abd9bf78eae7bc404dfd9e8d34010af7c3e, + 0x20d39dbb9c5188640b6f30abed60efa7c61433e6ffeeaf7cd73bbd2d713f55b9, + 0x2642c98bb9bcf76eb3b6e3f86c309b400e79071f12bf462c19fc612a89722b65, + 0x2c2562c294b65505f0ffb6476def69c03e6d1324fd2ed7319368a61c7fc672d7, + 0x265a567985ea221426328919c3ec1bccf462516e6525bee01d1d810c172e88e2, + 0x7fe7a2e56090a75757a54a27a15711c9b7b3451536b61e6a5519a3a073a5a9e, + 0xea63f1b7258831a4f087c53827988f0a5033170186619e513ad470ac9691088, + 0x1d0082b1e2aba35d77b41e3fca46a4526360eae2d1d49d7be6a4498f315be6c8, + 0x17c7b18d8e5324867653d44a765f34f6653a43d2795b040900a2e0b4c03baf2c, + 0x29e0ca8dc73ca2f25b4dd5c756bf5316b25be6c0811e62c2f4437fdb9a7e278b, + 0x1f1e7e26201e619629f66ae5a3c2e09acde700436c22b1ff505280a62db0e242, + 0x2fbd789305950579f702ba8777534c2708028a7845173f13e187752cdc5d98c4, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0x2a88c6c0393f56fa63e8e340f708efaf40ac4b85b2ee681d39ee1aa0dfe396e5, + 0x20a321497aa9e78f16a5957492e3ea0428d22442056649de52d115b1c73b1079, + 0x1f00d5da2a0498a2c1341f1698df1a0780c5169111a7b02fef79b0faf32d6498, + 0x15f194a187cba501891864984a6f52cfa2d4bc63ba2a35f61489c70cd651e9b9, + 0x5cd85fe0fc0c75c027f4e3f1bc62872153988eaa0b2ca20b0cb5e7fa3a687e8, + 0x1ed21eaf16b3d661b44df4003cb3636184353d25def19bb04baca933a3142e78, + 0x2b37b5e88cca20d2bb43f1718091b40fc1ab0ea7350f77a5a0ce905708bcf2df, + 0x232c7f2de11cfe7ee3c4dc933a0bd034b32c9979b48e2ca966c6a6cbceb82ffc, + 0x974bb70523301360dc181faffa4a31da9c89a158d446cf9f1d0dd078d681a5e, + 0x6231c17adcde68b2df5512d5137e4207b5ab127b989e551710a7cc87562fe8f, + 0x2694daf5d67e6751c38511d595f6ab520ca299dc52eea4783a1c6fbaf85e843a, + 0x2eb55960ecababf455a49b9ea9db9801a47ff818217381b791b546b262df5836, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0x2e375ca4dd0623584c0be2078652c7e0f1999eaf84f80e86f6161d129ce76f8, + 0x206f7162f5d7700b7cce6981f0748ba08695dcfa544eb1a903207220febabc67, + 0x176a8b69b12a5a3269ee7ef982044b9895baaeb85938900d7ef35a89f93b879c, + 0xc58b1d3319260e528cc712e2f2a6c606d711cca0b2856a30f2ebbe57d5fc733, + 0x19b13e16ddad7823e970721ebfc7e4a7c6563a7e3d92de2135873e0e60e750a, + 0xa4e8fd444448adda180b0c6a3ffd32026f0644911a7f4ff85797d7e834fb383, + 0x18be2ac266e3d98839e5efaf7ef5f17abdfd6b6fc729e1f18d834e9a383bab83, + 0xc56583074bd6c3a67fddc94f840cf7b97b35256e00a647bdd7f992e731eb61e, + 0x28ab1c80f8d8221dccd8818785b995aaff05e17d4fd8f55664b3729715f67715, + 0xb886b2ff06d6d3db570b2060a95b75e3a085d74c6ed9dd8c4f96065ab77c5b0, + 0x841d7473d45e77983a689c8bf384015f323838d32fe65cb9991784db323e25d, + 0x1c1ee3b1346ad2c298b7ae7d837d8cf98af1cfb7a2af5e1d06f0c9a826ab1bc8, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0x11e7a68f1defb47369a757ad1d47eac4fd12ec54eaa4c2f3a84e2b97e56697f6, + 0x2386b42cc098f278197163ea21b9f6758c7bf1e8a97fc99d0d48b329c908698b, + 0x2d1e8f11167a3889b194c794e8566bb92d1c622807fc519445bb09a92c10d11b, + 0x1e998707bd13625c95c9599bae3261e67f2d517f78805aa50356b8a5e6792427, + 0x1c6b72fa7c47168bc0c13b70af218b5f37ed9977f1903c64c6b0317cd1b5f738, + 0x2f50f79c2c896a12658ba1449023f04c4dba2c68e327ee5796e83b6cc7bc7218, + 0x4b15dbc180b8634691f763a02187916b21f6a9b230302cdb226c9c20b1f56bf, + 0x23c08c77cc0ed597c537ad1232524e7f9cde922aa3b9acb7a8e0eecb3f09dca3, + 0x246b55cb9b404e710f5430129208fd2f7d1c3b71b8d5d1a3c954ca326fd3e7e0, + 0x2a3c7dcb7f8fa6097e5c00f781f27f884c76c6b7ae85bd0a71ce537fd50388d8, + 0x268e6eb795786ecaaf037752d214a2422ead74f48d800ed7f14f4b174c53f76d, + 0x5ac3952618af339466cb8428c30acfd937e76257609d299f1346d72f87ed82c, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0x1b2b7aacc25b941e4a03f085a09a773154f908b9e5c2d20d3f67779ca448896, + 0x22cdca81e323db126eedc2d331697df5f2157d052ec4f66e69c17307bdd15692, + 0x267f9661ee6cfaed2fd4e4c8140c3e168d16232fb26a3c2a2517b6a4899dc512, + 0x10ce863d93a47aa85b421e17c96dd0b05510418e41c576b331770a10bd4d0baa, + 0xe26a35e642d56208bc813191e7980bc9b8cf0044ca564b4ff7d92f4a0410942, + 0x230f6e95f170836c89332e68f4522dc26f56be6fb7079958cb175770aac34fe8, + 0x1838b36fd6f0d488d9d7029a50a8520511aea9750ba69c8a7f08c711ac5f9ca9, + 0x4f19bf00ae88b7c9ea78742fff7593867760fad46d653ea407726b452cdc403, + 0x133619fd5268a1c03b2486e0a7a1ab4e8b83eb2540c2b9f02159c3e487d19602, + 0xd6268401cc2509a633dce917407f9a1b569c6f9e56063022183e4be7651a006, + 0x365d7940e1c53edea08251eef9a5529c9337a408926ce27f35d56389f2d0d63, + 0x125f88039ff7e0df7f265d09018809058d3e38c77907985c4c87c75d8a76f515, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0xfa21fe3e0314d2e7486a95e6feef8d81fd5fd1b6e34a456054787fd85453e68, + 0x2951984c7afbd03db22245a37d1df055eb109e4ac7344127f2c35dcfbed8e73b, + 0x156bf5310e6b76a3cc65f74c58593ff14ab052dd9d0fc09abeeb4a95fdf0de19, + 0x774fe420c3ab105f6dfbb8eb0cc6ed4f5a13299cbcbfa9a6e20d01ca5f834eb, + 0x13a7f1f4fa81d9e5e24d6236110fd39528fd3c216f0dc86a0c79b2c438470649, + 0x1019d2e8646ed7feedcfc77169f5e9fc2dd718dace5f6f8b9a67637d933a3041, + 0xc63653fc5eef7c50cde7d0c3856f90e2b0e0fcc9c5b16fcddd1e9740faf9b00, + 0x1343f7e28ede90c999f7312542d0fc39d1bc0d3c656440b6e170a6f3bc35b0f5, + 0x1bccca2bd0880591b20d5501ca0e4134c926c5d0d97bc70da24c4c70dcc61702, + 0x227006078f001421d3488f1bec3e70a69d8a51480ee878cfcfa26a8caafe9adb, + 0x2badd9b9334957d41b28808cceebe3e3c55807bbf4e7d1997d8b7a71121704b6, + 0x15fca0d19035e164f8fecb36822f26b07efe12ffb2d831c48e5ea9cc8258b755, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0x2316c328984e3a8d25f2a26fa5c8d29f762f70b66fd648c7df1248c6edebcdd8, + 0x14f86a4483471960a505e400b9adb874961582c40ad4f306ee61ca15f769db60, + 0x22448cc6b58101c266b94849c276c0b469f440cc5699098228fe293a3e15613a, + 0x9e98ce02891c97faf65620ce63a9279fc5c0ac4b7ad0073a03b8ae8951620ab, + 0x3d80d14e85f09ebe6840f5ac4f467568686cfc56acef42550d8d8c33677bf3a, + 0x3d857a698a64801730b3c11467d17cb8568fdb626cbdcd5a5586912e558c022, + 0x1793c7b3f75f911d0c7f4c64b74e7a1d344a52438774d42922a245fd55cf10e6, + 0xeefda98fc56b0b2f2467ab429a8e513b5d4ffca2b9355de8b8ef645b14732a6, + 0xb7efc4302f68263ac68294dc896062831725e4bdb1d2a6e8da2572aa4ff8471, + 0x2c4b370a050627bca60b267ee3154f0706975b6cd9df0fb5be76162dccd293c2, + 0x14b35f50c4e9103a3452cdc68fd4db02677bfe9dcc9d7619ef62197878176588, + 0x2e598155fa34aca3ecb0e66e290d99b9aa080539f461e9734bbace8c72bf2c60, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0x2f83ce87bde779865b4ccc5eff39d9bd2e8bd0ecc9c2cdea49ec7472976d923d, + 0x933a19319eea25c52f096207f6d8a2ea91fa531291fcf80436ae6ebb2ada32e, + 0x263439a31e513a82bd9fc8ce9e074df4e27e59683382019b7679cabe55618338, + 0x1584ecbb64a4db8dd2d5c4608ed26bda0e0c38c1130b28cc6c1b4308dcf40e44, + 0x49e790446ad72623caef9bc50395299d0221c2781686a04415190f52b5143a3, + 0x10b37775f18ed958dc5dae40b445b28b2c4413b5ffd672491334bc73470274b0, + 0x24701d4ce3d32060677e07f1267d9f7e55d4332b56379700ccf64ee9d57d1e11, + 0x202b8fb221cdec4a092a035d4e454528eaf0b319d671e60a063f4c0724cd8c15, + 0x1d43768bfae552891485d63ce8e1c3eed865af9e608b31a925f4a31a98675866, + 0x32b94736117256d76b6f85a01f3aff1e4d954eaabc9a367b61ca0d8bbd42c37, + 0x3231b4434df84936a826b7667aa33f161a86607219730bd78142eba4bea0dd4, + 0xf45de5ea90165e3da111af4a7775204d4ac83dbabe4eac41abf318487b1e996, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0x2ca2db65ad224b51a8b24e8042cdb875693897fd5503bc751d888f695d9607ec, + 0x44928f5528543c7f450eba9d4cb5db7e58b8081b98c7f752162303a16af1ed3, + 0x2733260b5780a3db7cb63e4fc82386491a217d4312c7a93e54707894e3b20da3, + 0x24f726fb193e627cb10dee649b4e3e2242b94a2524974242835db3e96befff11, + 0x1e38f6d8f6306aeade802545000b3da45ab90c9bfd2405dbc765d184b91df08, + 0x8ad1a8e37ea4e152a07cd69de6b60e41de49ad1047fad9194aa32849052b8e5, + 0x235d4b4258dc982dad9cb9a47a963088a59fae5f730093f1e9ce387abe83765c, + 0x2b01da9199fa4220f95e00c98cac996d65113f5af19912cb331c53f9c52334fb, + 0x1eda45b7f8edf24cacd398e7444437e30670bbde613facb9f1e4676b0d3f3d32, + 0x119f815c307628877d5e222bbbbfec68834f7b1338bfa7688adaf8c6e8c132a8, + 0x5f96bf0532d7b9065530d4777fa98b0410e5566b6b048b85cae029cb0e497e7, + 0x340a6c3788a26e7492b9d20754d96aa10ec846f07aed7cca49f234d45988d63, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0x2515fb66f81792d13ff8bbdd5c038ae895a028fd5527645f96496ac910d44e03, + 0x18dee821d0ad52dd6641fa0289b4ca755a70a603c6bfa5bd491ec55ba7af13e2, + 0x3015c688b294a9657c6ca12c65b33865b1b79556838bbe3f4bc1af83c1e1cc8d, + 0x14fd24e81aa0eed88a08b4ca95c08addbe4ee861d173dce5289aa6897d828128, + 0x19d02cb7110cd61dc1991b925320208985e0f64fa145d3017537470c77813deb, + 0x496cc3972bd13c9f0dd2715a9cc66b770699b0832a8248334ff5d213c5a7b12, + 0x528b341e3531d9d48b0a65c5d6316d2fd21cd8801adfbf0050e0cf6f0f74553, + 0x388cd95cf4d04968d3443ceadc7fa242abaf4eca59961cf3c850efb1319a4de, + 0x1e6588c7ee49bb4547504a62550304ed4d3e5affa5ac8f08b8c0cd0eec44dd46, + 0x23d611ae14db5a2638609c8212d29f327ce0956038039f270efe1a10537363fb, + 0x2b86d928a54b3f7c987dcf5ae89d7de994331f200381dd09d12ecb846a7a9b12, + 0x13055b796975dbbe1e5a913a59c11ae296ab60bbe64202c15d4d6108d086f462, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0x14f38d1ffa510f2b0332476733f9fc5c79df981b55acea4a8f0e3b4cc61dd759, + 0x1f312d4d6d9a3ca368e3dc8912bab32366d7204bd0fbdd3ebc577d3f26bc407c, + 0xd0f712e8570585e196ca13e8b1f1a2c963063f27d62427af9eaf6aad438e723, + 0x2dcbc4e8492001dd99dd80175771d5bdbb308436faa08e39f19b4dc21828c131, + 0xbbfd5086b33a2f0e5afd9be44f7ee3267d62833ae3019938c440d756a24588a, + 0x2e11c7002202decd43434c9730452b8ecfb543cd892429fc88db33c63c404387, + 0xa04ca0b4eb3a67bf9f7b699b179d0339883792d4bf4800802aea15318b7c0d0, + 0x19004be334dd838c3cfec0528bfb1f91db2d10d7d3d3454a5cf35b7f431d9f99, + 0xf0db552b704894427ab3ada1a9eb881506e592325b73d7ca4bd04002efbc259, + 0x1a1e713b1af5f35ab4fa7f9bfa19b0980ee21821afd1ab3445352cf784b8d27f, + 0x179f8e92246a7a24d55045b43b515200227c4be9e0087db3654a34db445d89f0, + 0xdf566626948128c150102e68c71e6cc60d52112b96993a1d15c43f2aa2d0d5f, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0x242d3b170212915d835e974b8f24c64c866611832cdf59aea0f9e9269dd8f615, + 0x780ab3cb7bf3cfe1cb4fd742ef1dea1daf725d4505f481c9089f9a6a1aadb10, + 0x224f1cd253223cd87977be41be77930bf651ac744d3b362b302fa36ed0f6c37f, + 0x4637e287df2d94786d07580a457013d8d54a6c31418d3f3ed4cfc582ef57154, + 0x2d703aad67bdcfc9855e65f429a8120ea93da66d877ebeca1ac3b1538f2dd96f, + 0x11c9e9aec8fb7bdabbf3696cdd441207e1749e0d8fdfb21535ef940f68e904e7, + 0x2be2aaa990f638dcd8bed18d9b76465b1f326abcde1ac1f3bb907b34c6029c27, + 0x16a6ff3478e400876366dcf2c41671f4ca6cae21bc985f0493b4cea2948e83fa, + 0x2d5c1ad3358720b486ff21f6ec096377f8564a544f54db36e9fcb540933022f5, + 0x2706883c34903b26fc209d59a13cf12ea7513995f226c80e6eb8fb69ae20bc67, + 0x1c0cfdb4290fbc3c53be1bed2a7e271ed1ba5aa5f372adf67132a8e53d2cda28, + 0x5d00b6e4b2d0a2d0067e0d1ad30789c2dae657135d627485a6e782c8b9ced92, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0xacd1175f3984a9e7cf08bbf5c1777cea1e7256defb95b191ad3d868d8092534, + 0xabffa5e8d3f345572069d11f25ad4e654e8006102f8d4759188a07201b43b95, + 0x3c0a0138dacff601c9d0631e83b8970db14ca395f83cc18c7a64db35eb6328f, + 0x26cca174ba7d6ee3fcecd1e16f868bcd4228785252b2b7de96fefea71306d5d9, + 0x15461d04466499fa137c5246d7c65ef254e24fcd50b5d43ec9d5e012f89a4840, + 0xba61686f2ac1ccae7946a24316c258848a86659591468507870c9983c272759, + 0x4017df4afcb1ba3116385bf4630e9cff49539b1ccebc1f4942b5f43ce3711d9, + 0x1424d70cbb9da7aba0be6bfe60c6ed4310efdb6c0a7389ec0c17d4a6e390ef53, + 0x1b4adfeb3a81ffc9088ab0cc532061a6d3e88830178f3771dcf7a02534532e8f, + 0xa12244e29cbbc56d28f49bad8f18c3bcdbe95681a7b84889c1b8f356db69c17, + 0x1d2798cf1798c27d89de5f07a9da5e45553ae27737020e51d7f6d365bad0491e, + 0x99921cc276f9a00e458f09183b359359740bcd453f652fc0e6f6c9a173ee5a1, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0x1ff1617e14011200242d96c976a9b73585ccc1103145cf23d1e2b922d03d5d6a, + 0x2c20a2a5dc3bf0aab0b87093f9c0e9ae5118db1173adf4f5117b33763bec7b68, + 0x1a5f9d44d0d30cae600f5592492ec4d112e9c0a24631d4b49f6e14ce69836859, + 0x2506549fb4f1fdb290bc61f697719b418f146af1cf8d61da1632e293230e302f, + 0x19761a80b065bb3820ea466dba6f358637f3a298d986e9a5024a8701149ec0b0, + 0x23f6ba2cafacff6a627f60f1ce6dc5b30a4caf64f4fb21c226d4c2d847b841c0, + 0x2e6f1caa062248065f02aad7120cf91d3a9c29ff5680cd4638144d7f2ca95e97, + 0x28b3b74cb98af781b0f5344c7d8526ab317280697e26d8503eff674cee5759a1, + 0x271858d8121deee03fc457245a298384b9a55b3a8359a7190ce8bd23de50eb84, + 0x2dd5829605b8e77bd72dc4ba2a12eb8a9aec46c1d253e3a8dafbceaff52cfe03, + 0x2d30204a0bede236a8b41721ec0376629eb558f6bce9a69e6a93a89af0a637f, + 0x2a6e862532fc598b61ed8c490ace702e5e92ef403111f4a9888e71f058b9883a, + 0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, + 0x8496e866a25167f5c61f388550c49bf6639d6394274cc49d136a8ea4aef8f04, + 0x14e8da7feefe3d716eb940bedfcb7a3f6cff1ef49e459c3d1d0df8d9a403e1de, + 0xdbbd1d73459a395ddb33c120018d9692897578dfb67ad660d628e3a46cd398a, + 0x1342655df63fac44d438d6f4a1b1288e693cc3b530cd73b3eeb588e8f2236cb9, + 0x31a141b9e2cb72dbaa792b5b29c8a7c748c5cb4f1cd6f5c0568861265504f6c, + 0x28f97968428b8a94432861d7fd12313a084d3c7514886fa6ed30521e588088b0, + 0x1fe9feb5c7f7c7a426bff032cd6a3158278b6c6b2cc57a871213fcafd6427989, + 0xcdb2db9e4f9d732d217c5e3114821165d49e5a2d41556bcd53d0c4d433224c, + 0x9664216ca565c1a44fc2b98347ea8b36904b3877f2159dcc999895adeb4d70b, + 0x1463f51d4a4cb1eba16dbc115566aa48fe77b43c244c9988a3c658d2f56493d6, + 0x214e41788bd2b990347c7f2a8f47612d4dfceb1a1e6da38165873df66ce51f59, + 0x548541724f64e20128260899abe8fbcdff184a1957a9385fb715923bf0fc79d + ] ) } + // noir-fmt:ignore -pub fn x5_8_config() -> PoseidonConfig<576, 64> { +pub fn x5_8_config() -> PoseidonConfig<8, 128, 960> { config( 8, 8, 64, alpha(), - [8243355230504186170667337521705529968548180153769821936979698914169521362326,21549235422807751640146583237936799392598740234259041629069949854834009192195,15309683586299089746803554818142261058154570215179112411063662706557055610156,12007539402495575255755232938576927941514879725482443887151392201585760698040,18793669376013417649313139054009540629720623019893420956495818743913188610515,6637074549079529416739232814950531409613090469922787253991308038219905474403,3042007484821627445120830225760006405192082634864137749621636257026891883326,5337388510268581167254715112479133594089770138749507073603490761032513368106,12325446798142239188409242319577957593792614990556679862642230477712636037037,676789245562467194073706116744095779362669155912771165373940448756070927910,5854747984773506278911353281567883752585612596682487681686710970786834920041,11245406467967785626327694659468342056789182160059009120973665143197638081760,10395601815816075071544509552592627172226369015806880764151195346316980080894,6756096862783612163697577917108261850810460757753491809406999449771712474223,1708595072322964393019739105130946639405776432058599259998973103484499438306,2817817145890818701877539103826217929456570347854153048034669346981432211659,20337270972708498869284875601749656006552838338471813066271573323209168221011,19192338172842323468707146045612196807750411464817516820711948717057036544820,17223253657227310295312621282100531845543865578630870272599545474783775759681,15004735209586276209064505708625280228119288986650187909395010184201059452346,3875652974956649356154345677088455126258183810851242537013757276075769588050,10514447960615206081458524578173743817818597124482828867666984705327684376752,2087647010835075851760610474040959236825470174942075295716631067964093542910,5927163251920754154392384551305623830535034440727310604898855074616515892551,20585333621997037505291454298836355589763292536744926081563336065939121006537,19320876518201905459682928158170419256739531666800973485138890064423348282196,15942638804716709831210239594904570403189415026144938623559274984027906868220,11197022744936474661934096628367688581641778841814728682794507017845346201383,11034020922250561671038205476395109731446686553549026383358725302157324264144,7574933006942933995255906769787776608010920618615581322603847524789684181970,10061361506744906780155460423367413099657465765582917482575074226383566926764,18611343221859570540963418999548488653944851224739716224660835306206658947980,17094203924957299390365889251598099482992645049968199405515681968938743421467,9407145832890449495071969940777105644547801064593141904558463573167881762713,10921438560879150587765515492087524756046482460218342400194862909363870270743,15101279960899220452674629307354995123411280418550386595937683027146194547144,1872357133681596467751878560069114718371273548294363719900935160833598069645,15505500304018853111989216259257978796595506623204851206292254759641600763191,2079667978353221447444850850900204451820443725835104896018664141845782871343,2852655320672908960411014862634757863509253400797831983637863741066632490909,2702824031197306101989338159138451445088523866133498139857862801497066633794,14553308731276493692643101846551382187575566516925133957384350697980935154102,4314969815396483242407853639218064117498232660761075778657880116870422414637,20236724297078811959918602376319440958076910292454596856154100774072250182183,6360017115980704736383763605019264589498600998515606807745670287390050560160,20856970531105411628054833058646203890148287930330473527735908484791842390307,17691356258507144960616314395885779533907781694329041597441621553108536658757,4464167934150673174817562382299722091160711333547138388803048452674668158635,11538922347277268848344412167140306567742076984016453903533772667841006045703,15558861252260038101730449864896864763293561339637017072015859069059083288561,931980552683520059135814229579184511049009637966018180567726214946979768011,12746506550979326220422215987591117730943427023997792332255149062957909690818,16416138987000536018990311324687201169959549714116951891693452597169869821726,7473835750915837381583185047008243788613524206396316652305987269933344653773,21223994082372071324452834147900730753626104062167370333103771844983134656961,11102363694946721470818933128034696027504133564649607436252022322296041603786,2666835000155694643357391634256423691785613060199379949509682292216642706081,16883033667413528795407641102416904598130659502290474063092941543309042023190,13093053604456598783294628038129487761924241298889312497497820946915331319389,7426349812936697309541457521193139970366533826612714195359894150484429907425,5243217285990182677741567384304278362485372018078770234262925321063263504918,21185490040917275396474067542756068684704036418473170810170344320388557093876,16181135763579884029508432324330748636846464150219757303321560798898398598349,18088358880437096005757355821526785623101357556483672471222924931365890201571,20418860027198053484245336569800730261127301261293595190270103940460998981236,2058948081811170389115771489993053947061173620273801887242248130631460165879,6353796008567532863300373986154930294334380098977007704532496889557690195858,15854609649070278722833415779491666201355987522519101725393408435189057056690,1355942327518086746604287131396672941922424788908995789539897301592998007690,10194046920666955610804398522181498854525794643476895032285888778350918459761,18342608728256650520630397534564293474806178807929639999068140223470256007117,16101948218093381908101491223075947943147313203969904451859930796280152622017,9866645853452683082481412876547916795343134459981103407915522925093474319332,9309485422719740772955698359258466728180120624442685713365406080485336040166,5201701081505060757054562398073722930344229781365241858092054974705598137660,5279555243870694216927790669819597822350327573071817682265773244733785382064,10661662716572743893824841881707597899963881485303936548294117975770384660590,4306964326426793675768869124893413588264762573088622132302954501394542576141,19945975928045383298785833694292459276727208605892865429301546022994613804030,5037834331249812829239656466783521330249138768989720606017856991559732121456,20693877087308232030611148201802513236570270737947270986743265610517665094074,17748932969923719316564673051784340920943155490113289807023660243301385585070,16950307665556055391386715682532553772527550247031548278958142572490582126842,15034211391483347494286112687349366897258989065045859280146461213731663274520,3455096385235320554100221104677124747996171720170690637998043454239897385610,11220329458242704347549150795173830262585759464331372299692251819012138352257,8230076319752658879891285909687940775399748755759819661970430769188439691274,4178690445391578185009939705412120505162313641744671740163024993195883735198,18632680236376151061913536149173846032710756800956417249233907621575802688710,14168747730472612819827430620596085566004981811676505988180237018638188025380,16777617016129912124437138351698263064579177499617525409625791377061066895460,403267570119386144603206457308168792379980670187570608148634410971295877610,11045890302538505532103216886575539246473207034538532950483165910580782953337,2632893274667647784827087132221744991131294771819888858265016332574437797556,14022461303364013571172470728150898521630042996798160127819093871974124417229,18349129573612583311962846403448135938849737390546876598640066736462315682295,8009723611300112743690923532773238474616291315457276539919568488041436720507,3287586297388209299132232426281031982329712892122181769502106059441842217623,19893256464101780566218598404932657965361824655069879954668551189408491121155,21779954643920608321663779655887581582907923850271820082121309309571440586162,13938145028737822338330333388496944993576078307754676998341398757402576278690,17280605833933949866452995551396279974325968699794264573823990818913515933775,11562775307500290654949270847967546133812416593099094805234457839659652146289,21556021192476590536800970202944195471695121915357500612310904064652863447972,17407055226077297021071802288772735837293135175537846248261973015744713174949,21295838064085671525042198277220548723525913660103018392096215316189390548013,14589917958236435754986191512564058641868109230240077937707647376289105324812,4538073055458854134606640263494592220617270326115451287834630189270577020111,21247609438242282269742265796811514090579388884916478939008977411932487423659,19263560475610984724826226948356735903574936974192558145730920786586162783055,1898614508331499418660051276594019416852890004788354240344418815409520758722,13346547977920686435662774643991891597826323722140876186086635239306340843003,12144969177194297999321084025481801838621405926243412487948189180755523714531,11624156909934489978766768065107924627236090741698411458481638802308500352917,8674349037900011131899280296161700067911742760618648557038290076406601619864,18627233188669469962636721109716646416813512041955577645627776298400086440228,1153719160094308748956884656041023320488424966635003188538565876464091909764,8000003066081501211900754070779689975656073731442793160620896624291841806771,12069801117560082050163959286673266840809976769131514316118288648293224324822,11694828863372498882861202648883355759680038037706633938668096525787115759720,1181495201505177954430275085371953511604847831716865494220845031383860562941,18321980275956746302814628602546438645691886543647725888694024551609678639266,2785661975937033521551267460848061931764727388015171856456622007438303671899,15557886094116287182932984983441793820379366058597052543066101158081817575352,175179830261452669822497364983291141568331314582563701393865403724263011876,10455128373814266139918350629083299308526836847946708764631040462916637941146,12622681406523708498691044494295298210175441851465578469593208754136900020434,9624138424345877000077746656879336097173254842107184716328214933320809030543,11726383465426411877912203592949370178096897707629953853811352568008881233112,17566146584557385507728086844334319515338136183689530813551207417981719751958,18423839150858891406289385710861955437811779173242111498197433255650436048047,17408376662161624435555256564084894291578222902661202310977717110546842356960,20995943422377609225953642092578140203148330329113983394181012996247925741957,10409490873284794620245703460832015892256721643100501421596423100640512505920,15047062105747285153444463303020356100177963702386173227676803770571846532695,4535940688608096040988822900684697329863791065464226849059470519882399535780,18980357680792173392910397806033731294240363676914829395702138582894418363978,16468042735091009392571235146440392007609078458297170996132218787642722263238,1869769403621899262774247370472546961521039203681166934356431996537822108263,6151829532330885020831674048300360431343535966534922988242884341920915237665,14373964388615044752046531046884609884388869283450342961030080770253954449754,21429869771065858399481388829822721985084474326196139156050788103070270663923,11836916222341149344359827526882466618136359738495035945807998286429671739008,4542193081188277792793758113018430324598765345700596639963408884670534634317,17262340128494663310404052919129368521415818617921877469042393034218456907650,11614110585474201606235056157412783071151951301104822431509283035322273244217,17241248261774133453753660970137875514052923171943595080766050681996607133130,2990875140768570679733810173464987023133165559726680992079139149034178002777,10032389096385585741539206260012253444831624820404318451026478423856181568200,8391217416130739565515338215591963109158836617019021044489286448654465296819,8553700889274799411012667201578367398970695661169430162294018618925895640041,13529692770771168133213371031275281478756443444824139121847596546264553079152,14478949636372928879378459122088894160202116364833386541382488835123981766413,18528743543311452855194545818079449921167163839226390851954136986727320245809,11724222260540829258562889360923785293478512718704276634048783603461995522859,2652532822068043785753514309321715043229885635900630208154874285707479247265,16473666207635815797882774885364997250503755116232911726426811919269547851975,12436631741803099512327160776479880302093882812091908650798222524569929954222,13061081443094122428989571162147084312340276850316867585582410062467362267361,20909566607465067204267258789556187669343825005173558971220332255443231196363,14278016202378252898173761523743422243750790190417896338147106476354187349947,7703701752136585609667768350038563449121231460368808945757767724712186009894,1622258312841010773225479468430896972269503924285598181547410615000034107894,4706114868510775588142857635375822293570353199661120256611528287780303504954,12723022498690150801900112713057006417552064300221766812928489357200260312668,7736508633931646965699972944684083339925061856252811104228904321699984469949,195095354858363944780141950724441876473553677166595890451203685104276178612,18877614091447727762374351623731936445361116363480970639310200637662433378180,17239262588506530491210045452642505719938421789517734104955853192075731537629,3391556611912995522919492308422471958888145521362922265487749943660431330300,10164629656754294522862462407441648133619259920942013682702008716587122474446,11939828733425435518898229234599966533928666730047925120030711579782543312731,17335155958861138542643885799966192412363788951639890938680530110842555336617,21068414996957890621467676209673805582866493104159841584377567318112060433438,18041291613104743972430309067462668732698702146146761776321539150844598296986,6149130772490689572076747194977244577047643214871016443290724757756394340290,12105848363324940274456322072887282559016226587661485273111872063034847034485,5683957548001811989600472365740829603387405501208071642225953069881259762607,16529542077365261070047716411124689196456625611983373158922227651721798753876,11961524596519782767188645738887896272947446382672325012202336646508449392990,9785728068011868312995387469680578201705397880590293454099364001157116688561,18127416268588083447440821307938591826251677223119815897950307944959875167560,19296461637807972438220899702591874518336722552660488565818484435311224286288,6801016831512114134395242293457679538495311188529990156831889204433183626116,2964298470426582070507861407971247200639242211740381994158541687335361446525,13485975887078791259342768620261671076376983307468484850600890777864999230190,18842264035089067687391583729082424222425351385494040849910540441253540345719,14703642210510851071131854548671393020078600676544458548174965732036621712435,21220214849253889952179905879367949668848598115028365535238742829171770487419,11808561815315084933226034934054773302447242219261466208644893422841430468026,13540888692913543742580940929469376532537583430034252053023468103862294761259,7244161097354558003276348625436123965060461415149286453943040900234287411785,14838699086047571226987010390426316539929576717533827724866261274778253262656,14556703155521968503536618488028548581329555701042498979115582733446728182407,7681623302896593715513288894378158777679657507901023568046253058158573848701,1088441387469941348668229287331864702951247349577784177659963097331109780661,7314603916265509104428110912296267885635061026393352039011815022900719549691,3986211915826218802854255636104488183733664187834078111248006041750140814882,7773946401984571616670752866609685859292708427659817737120107917606152933392,2842014599902358831415178364343115068084073955515903534808862171830738904933,5310724334723991338015239276468023426385678184604207589409781216959654582406,5255222348968955358505450804240823699077014235887887249383824524518164498567,4683270496545943333741165516340250527555279356319043788098737100323469078711,1419863943011284607504318632953959861647793372073243840131919334395882404459,7983638904317557271319561780754076927110887040374328063199742162092282580125,5569432847705373609838086039153225563020182698189928344759413994203981320990,15459233133041758499623402905899885787129812358908703405750502906067055055230,13557004098047782158753673078158469379829777184696159361573537670440394932233,15455882302725774286899673141535924396516348007554186719344822187820635072053,3420919058826876625284567898132572990967515410265578892047210512917031439632,20100418454140979684745740106982178755085746706837715848777042819378494283102,2569258507332519764813672456351707773863376375715947817185409500202699032309,11051426796304102496144764766958179671506736496976882366028801902480842422589,12740229748287653735988491742372785228070141556372656548689214318469788908817,21628842595664718258888324339774974922449098458375293925060310284267692457557,16339231976272978519029290439531768093693541721039081313180796119705575069472,40124736742096746520902512885311967045111742860721554225254094895613700655,17732965892472841235257958105891466451086090480423956940377743815006013439,21822629194074446176794925064792912534191501981075390813302606875002422233533,9308214945046921143097017249780654286051601646816113552080893008307002107495,1407926751839535775233537792971129618756456590720440342541085713782189375466,5640645423977029900985251540406734874840031539109774937559862819450972865688,5033216407501194252797695593441325021622991729008118693554186469034086370061,8067057037475400447259522316648004416684453970851364075976857314405950145375,3763719773038467529952189678629891209905984306908045328296798459182240539135,16939797418368521863388331657892541744299855742774206972703171911218723184714,4830944198856568835319759101429165879092462296316662230100861015921313890231,12704214658232136513943612645116991664417275945120192627735782298715562058820,9273823420095008025667777982828688153052061387261780450903573585273931011552,11055274871946976331353174512200687536982312509623944578515862663278819898965,6608499500253253446996042326570359354182967780655057286059057541317584758989,20888058022129906086941050692798413401844596394165346138911969309287247738108,13297667979268130800823342819300433555314639138313483863899090834749801969571,18968104066692458124571065270953767119743779337036553042450471941512165236867,14932841303199490878640323744926137685749952622800747995690439854118498001885,6250599214474930878673138968631643032807502364864165001640712550360147900771,13872044280192246670253542029636668414586465840988190477111017540404431909403,81456119668307937036914780206985985650137679027930766352442712034886058018,8178364156193615628946078892680068624209694278864784660439209878556857933585,20847565685305938921688196081711559611104247746032524045765048360946563554616,14790603163347071870110696142274029411377352843070075577069234486581346354229,18977464663780407707262531952390299277523056655145169930121579582916387871374,16780630803676794749613238124686604459373604071531057035207376612438682381040,20186476042367781999034353334494913683828163385175556939730585228743410724033,6782638209588187356802454014110236225878206067794807253486060610876934918759,8993456778572039939715813797180666624819850516232234360679317411311388323391,19966302498904269727099815984264954717659138861990152509516897188319443441697,20169703794592063233917650314404110898564218327366603108408586484609331826027,5979829627203584558315118820578826847995466683728103070319484562170838879477,8237679343008214539352062545936737645555361114339038346011678993504862443129,12382432100828502258569798167004899872248210099869176340581848176730802349663,1568185664985590267262857882936657784210740515169196983171026814738347336756,21214766447038120613598232832812136678657988502205964335817205381807920739938,7692941991237742474520327457310452870153482370889548010226143053981890424652,13595129445265049664221406027681079958478209116108739005508499004805469917071,19188096071580221579092496028987371780642557049389322053081699235155567772173,17975673380464001374676034638564230054429981676012676440863525293845130019904,20841685157342026757711329464299804445471940020955209397956987009823404283299,7510778644672212989684926383821874729073504800968951172295535413714975603558,5412964648109092367425127656145675316528154462488440576988541278054587052058,6998001450950528857399821530729656471745472711969582871968416561472553420135,10017795190513370580285083759517584035694996563220913850722002288744022757377,12113185651597474067026664715619946415749981707739597619454641751791169267554,20451540737363571466111039734160615184627155382583098695879349204357410296631,729116950403569953818905038668361626861855541652418271170712441039707291924,6874571610670154627346562968411422088198077609945741147515101915358108207688,20307824547105117373454598908217917152093200208838326389260620574762152675045,8758875530447210792904496135011086289851932865540018278850670496425499052683,13224694410602002105805224454797207933944742532123981533211431845662395381395,6621493224766717216701548708726891168784911176896760330321592836065310482866,13937858022779991611039558948054774910543950212969141252259896915615778617893,4917806030251482092362529677296731621677399228082641707762616055246746126061,16304922224312728276104330461175394847795848175925462853738047204383447573035,16678452722472429203861326329044632626530032631343862086351886162579978046420,9974691111613144697061424119079539196535411918411684404824080439336446439564,12391128852318795781829794456501239823062804741032268163807689059014957151322,16376931186038869228971542812469753097050036606517944132293138523631153279825,3057841358487505418761470758562979965285993261118087156094367416201750095404,15045409518037090814105826994439679855639635253710791541219370329682069820225,13442376736433669968016223589180307683361433436806777011753497283272674012644,18917174176736242961299708438032963296686220808211170958894252981698475343631,11380920704380401611525239094209208940853859054744619020167150893676619275400,5399632748693319676480270098239871368958944610827825094400876104909425716392,3072779406768337118240884091792704214322792415195488652476136252175179362880,8351873470285292321562674159922105545256148886389216816367528787141186556758,19039526722628732399365091326361517675801947890934047817293511021151913744591,11316453563295765895775061205389385485172841919365628835333993250531664655988,7850755275953939062184858524678116551304016605992491147837939252676680785208,189663666172994057560830062107872734380479327839628938168402275701561917176,8944554955574110171273295960753608410178793391130829960067372967633462961614,7116498249918759493875054905542634690892118438594298685578805598675410965669,2535963611074434631003149876163530430931993688129878286594756194015465278460,18022460558081751594574692271414706303627866472796139479944146908393139741182,15341193598946540230880135952221211503846552166425406354080863978843527894671,2942431717153385426545606490874257811230086292797817271859433296359160259239,3009774438756820489964746831334449123894740822794580986556997529296717581423,9496138301121689616049759054935646143502980987880350156990306735995260671175,4076156724842725224174300000468119057699244699381290980710548119313376968129,20301500572584246879220468905731058339249778940966192891128325027181404226629,12240449395531309263037726882974869058539543342019721791945417590157321444565,2734576041547526732946886809654954568832411068107541730145912482251139322538,1913611111144137178181099357504813610426696502807761974432419767623037547574,8323981703091520786969788588517080546120036429535328021157459160571413370125,17608089795804665912003122420873117027406690592641558991713120617999818930151,17954961401611739290579723858653246962839079599354059880628870682426849304674,7693642591048722104105715300765742636898670019493041402551952316778508785882,10925165536949195683545612102300879902373347522535838874708839717193999335745,16740598974035404805544189925980303793846400946043080633235004418045311113846,3028458114292500648266975052798389647613432243149006395166123161184170940972,2817600861932061603203157785548222970685465773360278995551965365313604217882,2811366666795973435332404603090484498270752802044239619104866535127344245139,6901007103297959557257110184636027233977945890205420866896244199105220459744,6811040256124961160848956238308470640308462502755753004833080999365205628787,846642049586630199735666112786431409696508103735494916428842550432654381594,13061166881718302681365231291832588791959186056326831853549555763101859584396,1581547457654855644173875819143310956457964952802128135344084991507959176621,12591698412731075291488515328885878994038884715020576113812619060374399968487,7129047166046749599109058206849766841261983329246180789653876287940952140294,17780920041966559015242418384239510699940753783778307759603993814380170147815,11411967002648206460094819913767451172535988461576286592244752756526683869398,6535147980143805768211908880661065989475773196469834562468932004056012068981,12872366293792794368642323198969017581196463071340612957009439105182673573396,3845096876544992085668616039795853840768469571100517631039776002796484609549,20386025860348257305841141103130861239832870083066852913792413739711579490278,5663975388273723452136125938377376330824298621841190787892884430812699456136,20880523335705106555101009571713688438858731841737802690910851430800496104934,8664815262171336902475127109386834836220742848950659183106085559300961747316,15212672296023611959246835252860546019670000046804751249547303425954183847429,3786255974807528210793957400325837912933369979823637013145025357556219775102,19646410587152058982763388053845872310164493339475512721275474101828150077273,14407426259630290801648546162995549804322572985407158009259933675410180400077,1275955073103101917295562169849127375209112030395179332033340866715396722452,5487750760448101899937260261898752719887276580825994742322208269609306618405,12414079753210256499611439235670285717945909010061941159696368398137523291140,18058271753030912252347026705895506604519018890772902865355002646910918153759,13935235821735626611156505080089322797654275868806802361406549798199236177528,17110498079878546324718511787669387410942622969712445909354000807236690314957,10687508266469903792000405420136150569946636272800228999781195239976105560612,1277956894120355360649091990517188151791867400124079104247693321263057601099,929982009519538400155920125117423265869657236620766216139182914925009802954,16559970949358997473575123467518158994842000800881347427572300986319432656507,863852544580033885106607226598354103099120172650200980695458006092725115354,436810575313416269983882563851323926836428928449351162094565391723605483516,6334913013691170767138698286357556285297887475783792365865857018173994149486,17785859069146472999908840832788077051672090890508101583397157534162626183973,427206014337914391283601765560115825767253196347193816620589108299037926541,15115704735938262072587983952645382098893412471333885175144579020987265065203,12017969315449748476118643575203596675122272214009056004034938899095907760206,20642434407226804845623813766397536183962927868804716012482833199686414302852,18982318327848493301474677819747807686491978396022748137991684529478469330097,2306193794828709014215315860179466106408084703631347012188232489780230095671,7060813397820173935956757571314686808083877731722252822508055423697679476893,9925864312610988474999359617458205534034473691089101964213562993662824159034,14036238569106986370932971272638702550236692459418895654245682921654874601312,9509048813859143088347263336607686057099400727479311504780670742158653486206,6842166521132564137619008158396211111980991013087076743268157882198576269675,10217353423046013950417213172971567565900229914457220187215408404202554351836,18220384419265532097596052952017594673237799959023133602933674050572298730193,17866822945198657177461453619458294532377313634196332518543246556611008452933,17694368679979949511817467967015330546905282492241200905890171992458134240678,18971922685739566979638356009544944454629162680819328093994329160719843056737,18684937612086669383439812199377945074448160740155966772829350355651237261795,9235876281667970051504588287667786944160228843888838710239865727309603061015,6187574163551283282357553100017400574873868151705871779659681332774938473442,17196369096305464930639002419417036905613312721767481044644254878990952814786,18296927216321111202881056198300973553112302777685079899199090840516364581791,4983948188027170589078739023086929105628955321978589464920358286161528573448,2276814237931645487686771259585160667452008745791625290365802841496721618760,4138273157833414032755498052453436990872835066620446328921138739885868998379,5835580830979414828575054128735121537583042482361311845838347096674448689116,20992630219061340843601881100837482710979119542034786928296223633950908472388,1118381353525339785976839119511758587763620520383755136959051018516094253090,10337002023922138844951367775712178432524190386722995225923120494344904079950,9765947418137225404722546740514250763898752374389411503005283184253024586058,15411836962046751164622748177831913963909013265942110958658714173394711125370,20722527012138131360820192152290968950993396481440050289358737370268218859591,16585853587281811014582898583977502965045639444130273779047322749735299560207,21436098743421172924014781240823435281025352300035264733201366114473419058727,14178112462860881459540462916598447735177675761773338824394753907217898488960,2590560710846804342662010467713568407285290476715663333366063002353018991264,17949223181156469858379065899254284317305309247290121304422294912030586532673,6940063127036366626640075420306454154706369567406835284901717013872681276911,13212339415583029091219180722363760875223983190396769244985733901171214077679,11143838426689049623360248250302972103117784521940658207527698432687552942591,4994693363062895106345077091869420711664571716019971952890352464184561249569,7785839099197795033948112451740381108555553042322704038905686323540025631473,15291655295654923849266753004503491258117644584862711291502217292211074445996,18223946690101945712849081159295298164630378278313069852577349403051751559726,13247893325056509281811135293440873471348664328435966021736203439379360560346,1838627965154116499570588511051176331708387980121591719463695143475045130831,21746931323535899361372833028120884537569529325326959379977185108159655128847,1569229799996373000993208676467175871896208509249271061977636872731081653113,18668959729045139805375896352501526759923123936419773886979446262254907152787,12698285530824454564359053510831159718450594302921296519937334733529589738160,5743752602883180080321224936560739109224279187008023590149271256478879997507,17615461436426765950762679333452659818080751337498512367037395397687644820677,4379963027402443949761342437016192165148025657715626365315450970388283739261,12622442863880120105122485141053297017921305018805552070109568547893924027508,16493349884995741255319414030015325273883108492981717376626952633010860098410,11501183900713163689133184470477728399861217340901493951105967658399341986313,13184464903575565740074003127437693743650101614906307232173855163739473476900,19056993236227362680720448341933549082689888775458266843506880469982452347227,1180947252747369471066257076205537751320494098262241412291924855089764608729,16229532924404554580195616835338949126663348103713418556119694233568376894947,8604714607572995451336310555882946070542334844212691610961393592348706930493,8362594100280133221998296898045505539071433915735634439526614339277300552370,16399159148365956463951582514857891684943332179297226423628752792536028483990,20791958918883897879651946680726738927333774947616022833294686415482396438838,6976099533465307077876553477341301102578695004868981952387720840685240842560,17588607896443047770053818219711270035985826074286753981361920802895326076124,12865981806811655044812914486873432317316688987331760480657262748139002813688,19080259696546964979932036247707282742365340353585423017939782931928015046575,5475353703257038456872747308072401784844227202792527428899399083236860900298,699444932025038530835460727165156424336147795146205258896894678525124927461,15695622674480818777943366659102932349783785381339274197766151422625765388038,7644428489984569999599080644830401450294253782967784792584750934960812468382,2484044190398385977417569061356693291812041338880061938702052957819048506706,8456986467797277421685766156179980502998860530369856189405630837033584471075,5054041625001826317568038929780665383894838531896986763764007995985738029810,5197336058480822437408118036219119090707158130910220019747427914262297331861,8896147437242770809876821567936215621570430903276974181159659855796295866923,20755757167342693300106178757642141909843395817794855978028122598254488316281,12495257799325917448205113238508489684392516282807104246531380538192500498286,17639970982424592615983334078785592256655637539816187733799215839326807071148,8140016957188286078776165555436655378303814378750387793587919949009492167586,17209468066776420206923060639618147772644663380208004030591040036263548572020,2619409586309117922582791327977378099828554504012201484641253637770276078843,11172679254412598275301264634812740710430873755458899712228629497147611473029,16829502099778629987235691213955928527920624415791356237580609633148661633897,592799060717298365629187138482067858694007427100574367745567028165989185342,16864381084532235865281462338072964457337415344658720676113860956416999505572,1015589663070446561434523645329239389344944669662180065723984179503017360337,9982212112174542265411457778485410853904388759147308861218634697975431894510,5412525702631618381358272227447367851318305617863423359948039591381065713581,9852930575259000100332996271562617389630146990442517175422889296173516799181,6036993105785310658467845672504384047591296265363803946714632979523201713762,1821500632172143873156399122734194851200445368324858351038486833883177057468,21556520116213603298246786137688925835788594639953568860110645708136881336676,658318860971707056155247027603536846915894897192791739866840963356575472681,602842622617647573132938965729563329852165494525296971607175031334298950242,1151063223719891516862415316972915766442753873652837551132768558136109394634,20030054542089253165409106868864476953251573918915762537158006593968012247497,14455078111822464502989472874268580626098857184523941794725425258923962713053,1699191450188970110166570608380346465689006650580298122024202987580198200132,13971136504849280501801880342723497383580392506287195375689019810750613223527,11259011415071078991947983706483998982146186263873384729739331890304233635860,17741270384736018529047001790810396141344433078911295725171243367964019815741,3617456068852846022110280599700245470402025130645759911795429861830057016581,18773989857774369564707484486703863617112883499664601804221477949481034222590,391101570414854801618801587626783162239406618115954162053108159404294160435,3752824438659815340558915518196975380567589032517034180452547083690665271869,13652227089592801810376789544861979384538590096633526007583054323554301421745,5753030785259259818058977992956569985665739253964735992489420513570911607,12794765444364718066463627091127875266371595037234762762560519184694440318642,1844165267423966444579133456200541636533189889959706801468771335509321515822,799352162562582415493264759184613437140226428304061991778193411771388762097,15915114786946818157476898276501926276831197920612814619300062353559927906953,13041871949144831370743756131359537126101784549008553888408794912277392285626,1684702427149441531010110315726002248751792272226034774456204740385384491604,10195318610969070608511028432066597876456281143783329459466964443360549551082,13714193389971576085579160116206487363436474313560046541969781285568217247624,12202470771012770210445954644081270058473831351768121852596394422757629850892,7784616613742667796197638965440313242748565680231200921682296807888993222090,18581613859576442652033888735999982405110741068271804741467526764394720805037,14828223806255884089537896775456938290494683211666564494946175120085694803958,6191868112332934762674478056112840408041237177775248347690069948259811627101,6055199518589075551800066499277675747934144570099354689629636497613775458486,20043219892592698889412649805669712950039510114250762278667968995416842502234,10591576812697540586115991527347511638405122244793393962099090930538459086772,8146910292072979142616688207315340017602882692938548874592904341871514175303,15451576003386544225828312996072681331940167554848966592330715947662789205180,21156998090948310800651324456525534600543417534335507361948830316109451323115,21421497039083336739241851024868234958744697872115637345287618993148799764131,8835309990713613011240324096693076755485475658999871502819747407829989219746,13102158958973358955423565573049580406238531533936309830903999596178966162490,19927703189662863743499379923522860979653455328626544661291243971618992342837,18417771183154820005238210056528713167003520086953806649233005148247829186154,13242250186667974182640987653516460478853973058739850129463954545512907574522,10971901023853281329361069638276077765206234747340067637718378767976633645829,20436550472837870181409690438226695091760115955076127106091878852797639823191,683842651763399941903331243661454687566310039977770092715404267515366625429,3304534668380354910105587611199035768704466410761708200478786163367382500984,14327892159763789670354328059011011973128878640806462164819794130243254129821,13712101990593648405837473744314130986494510088132644940425089514662460031793,1270386163717136732049662990020454155453019401464056820650142849751291739739,4559668312052315567004252521434018809625818725552950834596073025095274632653,10289456013947128246221059115194021747046925564818529566042034047888244657473,6981981682422059144716871555026845840161063380660424650450978975416029699739,13275723002453843398308458799872954358948259042779675411059905047590837397361,18372074965684100000331046096891533070433189717560527825752357282553296305210,6007153627662867365254986874716350833679184737288669421698890656788831322929,11557682792813633323168221751485510314542594132819842305598531070629168100143,10536598621155464430657941977974614272794233321865085717974545329727298277125,20566123440884795144385782557360498238445700080133152934423121801124172346047,5484210585392274768700243869223282957415576141086566136019633416151230114084,4675266041161206862174450141632759296562489084453522360678052892725376421684,14506966485061491552710372008504993235111668026216492386033611735228479487468,3682565950309631924420685101131217452257499881999322497664342243267291843503,16753306733039910894513530708776251948831720207834805689601646616427039909037,11892397629144764406188085785897237236955294380381710017192179450763501663923,17027229171478232498721421673139332166581061755210509139252013418924500461243,3560458480908782960366816146149753544371185355186140843210760460011482921556,2523290942811919827064721825289040221770310594770466909167316010377190569820,17586848354290518015476851435178627882600199642491204839902589087637701736514,18771893348474501482962831973790983143756587183687952333177929270650139940171,6788202157749582404834375771398928959748074435244246320016871403739257327326,11025631863450004428764861086496374449453982180198151399523240056816657483248,3256907622263919521402687344729539839835290137654795380148237049547054026004,729757374802086603625382264910105909740146180896096383332210024077887641124,19863253866253150070643618896444516678169346690564661550005769233120838139485,12468569017378925985548033310919519222810416238732327538088208928920140959143,712344748962578398623451251358410865586764243720605242158768608887082462846,8546087066371010720013920767653366050032317738437010080974697619001241722483,17144825509786899110344839698077839239721239583625175190269757913667929043953,10651563297701188942358589203989937961905153035428112097802788565849122022100,19602341346389413323180922571631527509531683866957468565049297030414658843948,9238186664745057178430953403953596421917515090260446457039212350976296818523,263640414028390180122517954487976369901122460517389747631764885875587715955,2311641918305077640172935641310996393584851078677397516017312506521775283636,12911852110192471656473443086611566556755106535388637084532737811151296554463,10436700004928765835031725654432267178079115705246966695358470216435798181674,12755555289896266917759922247555708737024386059041699214870911784508162783525,17390583422165077903045260639521919716984664232208360646931078032292219709718,7412526952366864882775200227476857681850213243362827192310877977391550357930,5016060582872027330190350728607317487069057897723717249157495640519710863591,70447200134990075406173842139872041532268968648265338736409860251327029352,1545500244158153586647380894391367444874762740407966854865957002078767363820,2082567114283705201161441383508830647153064041365131752708347264051557391980,7773933577113494097575644205473257493685202208592412633139277067190461074505,15907352821797623044340355088248954282080052141018731890243639338361458586983,2453390435048874114321626738320866552399505338711520013030652128583351121221,9182038581165182763924458518550360578443802241218652973210280653624820005202,13176557622325900598244222336641110473108400343854387783748570353220729582767,10599983241136666078578113335543683963633036808782400964809769571709020578918,1430816790456574892099931300141571059151141389317227589818258647628212654923,7207251746626434553568433426934231676780727971853793874008147862305418016123,3847365229378532841231862621068765430417579646617713430532944299440264931969,922422158589085666348657924088867593873646110588554410818179794404300446471,4298485174770134050325487753075508760849575591910135387686931072102416450479,9475141350581193757416877790061277619494551108434152557051757495614692231364,7750163624390542388958191386016094472536166330496081849246099823270737686866,14363173695671306304956071467171940429435853698217676411185837490356013810171,3402134714494071567155197273072160417049647120230862441840621369782667867977,11378968132153772980874973211734670604659991740586197794619174704886870525408,2500862781199005154907185089778932765489906994365960644306361544820582839768,21880931942133046355810983155922578513531850539420426025723154879488808270315,17850206894189265929807971665186479441938275634968267590809377452033564010382,18427883853363251276513100116480886898434829323430684895879968439179171503760,18758795974827407022563870795763356401215175366078230621502388363785425038612,15672649260544536516531393740985073476934112035694203841471047634286525005174,14497479780124030172334631091033639981498927489925809517218125709975200816290,11190855071574099336548308963044121660452976926988171712775481672446931541539,8339442292395337481335048552147626044800877206694030770577319544121541364092,2461178629683239975488518502624530284391365519847067341739449204945212652770,3972313936510404965199308344697399140590038866586718833591813109326652018667,3224811019580618549699828950033477378112059204060062023677479068506440937528,18443657715765406615721041820828109800966587434816919981514222787674698772960,666201271764511484388505793135876064418452477237751508215203932379618265382,4434899717815685275523711262432486808621984251515429736982413712108987655422,14584918585762085382434085071460369807803840154636220934254933165793423091295,15646480282455307022430957975574008173154630787861430193406352480280577045711,402840791633175231660910669665966910050981784044822648466848382615330599909,15437492296189220094817534101128968523410729375545135146260659057729649968314,13987760171743052442513877961667805977500573882586118554487715622045738218279,12589095501858681021442730872878907609617459069328956803139727387371467358051,17551064250089164193025672794811675406761638177060737129533175904585851772273,13500706213131978087516005477128059726177752268287240395927379509000435850498,7331629294073516250840302816971095420668983701195024195892939287001016568514,12949377725980318589136021850295478499564248427839661600142796482665024587971,3988955063770305621858590171391799353484164878730082586815877210936858093890,20512156157023978986265779260320491356890557397261515752540394821171756173724,11624190532749034673782735319581023504009231230729490439584417709012081446066,12473562150323140802035699452896239306300376623759190078147999182702752528013,21504777935543484323252258287484534200045631968996932563017737909760083499017,16104745906544338230790783632377375683831341202924378150021598903321494336736,8312554144734150053969625169851557776466370096299754626528722906617398229171], - [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] + [ + 0x123992df3b9daa65139ec13fbb52f7d348e134333684c1596feb0e8d8c3ad596, + 0x2fa46f5dba9909ce9984a01e2af30b550dfec978be92b49119a3959c7f623703, + 0x21d8f94d3bd98f0b63a7aacb175b2cca13b2dd8a8cf68fc36d94ae29401b2d2c, + 0x1a8c06c61046e0f8dc6a39bc57aea0d07fd7db34e68f73579da89e116af87eb8, + 0x298cd7046f58c0cab77523a58a6fdfd1401b89e7ae5eef4994442d167f7ad1d3, + 0xeac737966715df4a20b31ab693eda86a07f3e830fca475a6574d67fc5f19f63, + 0x6b9b718bb3b6d45e0cbe6d5d9a2f096a77beb056821750d072262af2a70a33e, + 0xbccdad6e8b1fdfba846a9553fc7905b3f96e435d653eec3972565e1fbbc302a, + 0x21c2dfe20dc5a72167bbabdd95a18c147f8483cb7c0e2e684a1ee4012f4bd92e, + 0x24ad6b2755a6a6ee51d92fa30df2489320e50a8ce7132504ceca30e9480079b0, + 0x67a46fc4c52c6ea102cd37b4478fdbdb5e749877ec437bcb7acbfb64e61ecca, + 0x1a2623975652d476f4b9cadc4b85219268910c7c3b2d0ae12fd47eb162257f35, + 0x25f8ce30441ce86e6b21d52ca87463cec299a3ef543220d72bc2491fdc04c4b, + 0x1acdf0b48d8a4789a9b3ac5ff8962b16e9a56c880e223668a25018657834aa5d, + 0x14d3fa7ee1cd2b8be2f42eb6f4b95bb8b1d156d77f143fae3e82bb8c5610ea77, + 0x3a224f6470a64f294fa4dd67524de58b18f70812e093c0e1c06b31d758a113f, + 0x2c822aea71402807ec21db11a089668fce2e6c2d23174de3eb69484a53148527, + 0x1305b66e890e97e11d52771a60509026baedd0e0bd5e797134259c748a289995, + 0x2b1e80bc5e3f546f4b11399e77a0784eb7c439c546e9fba26eb6c77d89c14517, + 0x1562326a8b0d5436bd7bd173d3f9e69c3be74dc79270b4fb1e8539d584eac1d1, + 0x8c9aca89b447e7468bf1ea6db080346b6a6827eff1fb81392cde7f6130910b4, + 0x138e002e8c0c597550b72acbfc9c50952175ba85c061b7e973d87d979476b54b, + 0x317ee43e6f4e38796821ad2d55844d012bfc5c2b990fa48b491ef7c6372bdc3, + 0x1b60831fc11521d122d9cdc6ff45c7005e6a166717e7aa1685cb286c9ecc992b, + 0x2e73d35eba9b43a5100de17bba5c59d871ffa2a9b522b0645e283a89259d446f, + 0x22a4d3cb7750e5f4d2f0381294578f698be7d678311595793ff6f1ee3eff2df4, + 0x2471b7a969af295b9d407634a486a1c82cc273506d89a9cd5c80a53b40e1935f, + 0x197b73e1d792a106452ac3d31fd02b5e1617f5442fe26bef5fffdb7e1497754, + 0xb2df733b3541c788362a5debf818a087bd9c9a9d39c1fcf2564ad3980bae8f8, + 0x1cc66ea285b3c09cb4653283b9c6ee66b7e7a3cae20cd50315dafe3a92113a2c, + 0x25b6152ba9ebe836c2f5679d0f891b30b96ae3e06a6132da2f6f6d212fc4b52, + 0x1a889aa16461370a4e75ea6bf7ff9405c29656295996b0b5884216311ecfd7a2, + 0x1f6faf41cf708d8307442a5194c1d38dc3e833ccc4ecdfdb8aa44c5e9fce566e, + 0x170221e35fe04da2303dea141113f7711c651dca57beb7fa3624d2881085d7d3, + 0x1f4fd254340f9509fc1ce072bf795c9abcfedd5f80ad8ebea2726be474197b1b, + 0x2bb4fa69cd631d5b418837b9155db02d5489e7feb92b2eb5a17bee8031058780, + 0x2fc737a4c1073c018432cd0f9e8bc5b75c19f94f554314251d510fc788b79d5f, + 0x299d38d16803616a9065d1820e2b8608280e8157f7e9ef5b954eb3d2beb2646e, + 0x6e8fa64f6f9e2a66650e0f002b2afa7e0c2c9ae417072c68b8f1f31b217bd67, + 0x151e2effa0eef7ae28945060179f4aafda3a50635be3b3cfd4252b5ec9c29449, + 0x13f225ff220789cf3d9547f15ff5f6bd6b057570636e25cbffae7b707d6b3a6b, + 0x75f0d5b2f3aef1e72cbe0d0b406505ec9a0c2b61f37ac0fac82b44d9fdd5f79, + 0x26f491b65ef18ffd2382c44ed506a506a375a9049e2f6fa392a837f3004c50d, + 0x26916c460b0e2d5697914d1652fbc3da25179b010a1158e546de85020742ae2, + 0x178e270b0c35c5ade3457fa5985c1295f64d458a2a25fe849c7eb5b4bfc81348, + 0x12b5fb7e1894d846ff3999b3f9105329a9cc459d5b605ed00f333da7b2130905, + 0x138f42f4f01f4b059cd6cbd6afa1aad443f29893e24313d2fd3b0e61a378cfa2, + 0xaf68a2bb5f9b6fb492356bf6a80f40730056bf1d85424614ae9703ebd20ae87, + 0x711a1f848efb7d202068d15ad1825720c2b82bb2114bc884043bc38d727f6b3, + 0xf7275b3afe158fde58367a5036fd26eadb8cd1c646afb4dea64fbf1d80e1f50, + 0x455acba2c77be3a518fc64f7977ee3c646b30b534294726ec896976d6a16529, + 0xbd261d1d46c99febb2cb1bd70ac8fbe0129528be059fce75cdba328f73d7348, + 0x2e5aeeb04dfbbf5fc35ddb3712549be8e643ea1429fa000872af2ed500152719, + 0x1c86ae64c468a452e8c1c2d5208ba6e17378cc3237380a48279889bceaacccbd, + 0x2acc9d15663027fc5b4fa467e70c3b476f2a07a6ea585caf7287921100567a40, + 0x230d03be86fe9114145312605773dcafdf71b97d8e2cf9e9ef246106b5fb1459, + 0x2ab60a4154e2261c6e4e82b20be3e08f7613cd334dbae29586e48c1df49ad592, + 0x2328aa6369f0af736abace3f7885d7dc566c39ef831508178e6d62bd4380cfc1, + 0x1164b8dce7e4179ec0e294da56e5ab43de2c20a75d57b8e583ffea2349e62539, + 0x2491cd6f23416063e77171095c0db217248a2c00adc3e146ba32d9ac2b941742, + 0x1cdc848d353fc772de151f8656a7e2e24b7fda385568d6596fe81a303ea208f4, + 0x2a398eb8ec4d3bd99bdc3520db7341946d4eed3a16f6faedf167905e6552884, + 0xb07f73cc8432e1f9e4095e392359fd46467f9bff3e24af5bc4cbe9b17b43e62, + 0x4e964ad5ded274940fe678e4f72079ebb09f289b8381bfa71d7c8ef0605954b, + 0xdb2a3aab326c1344771f4c5f872a050465f87469ca27704fd93ef3fe5a5a1d6, + 0x27b044fefd92da8972a60b0297f9b93f291786a749fef1e29f8ccf6bfde72564, + 0xc6c0bf5ece0bb9be0737e0c94f9b10594489ee5c00676e51f31781155ee8729, + 0xa36c8af931781acb11cc6922f0bf6e28ce01a1a18ee990da3421a0a9aea0147, + 0x255f76204e6137ac12ae576fdc49baa054ba182678d75a0a3cebd01d0cd6c286, + 0xaa31a68117f221fbe1b609d8e269e9ba1e9ac228e2e0a512ab9c774a3a63f79, + 0x14151310e656644c86a5cda7620c6440ad2bb09688c70530c1ebac60d96d56b5, + 0x27b953b1de0e30a1a423405b749d830285bfea294cfa1d3e11b4cc5801aaa640, + 0x30476b760f0b45ab4e5b7bebef2cceafb2b06f3b4193fb9938c946c63115b008, + 0xb70ffa00f97a377990544d9501602376ef9a496ab8dfc44856306bf28a1b920, + 0x2861adb9067f446db45b36bf93ab6345f53e07746c063546df691604ec026529, + 0x33e9b4274c357a8c6dd61a3e30236735b5a23f396acb52d92d6685a5f03ef67, + 0x28b4e505d5309e29a6da8f94fdec039ac44b43110bc0f8bcde42bd833dfb0d31, + 0xf6fae1122b219ee0b1675ee8bb5c7c48744954e3dae2f9d5d1ea71c0edb0a9c, + 0x2b4173bbd542f1b89fe8d3478a050e81d42fa495e9c96af263aaea3c498e917, + 0x8d72f5f016ab29391344f20b821450da912ff016e4da674ff97c5d92bd3a1a1, + 0x1d9e387998377d9e680b0b55e8309fb8a29719551de783c1cf817cff9ad6a90b, + 0x1424e2acf5db0d91956e15d5b5dc4132ad6c4fb863c9c8e572bb49feeebf7e22, + 0xb3db34e4253558779669b849ef2fab55ffc654d4f9f770f74cbc45ba117f483, + 0x1269861c49d7f3713673f6fec4b57436c9059aa10b541d64aebdbc11e6513f6a, + 0x2557b7a318681664ac27c48349b1b5f44892e5ad02c8b81493418bdc66517342, + 0x650dcd4d3610b1d776d673024e679b6c76b5cde0b985091ba00e1cf4eb26062, + 0xeae77312a73dc3ecb243143ba64f7cfdc9465cf00fb0872958286430fd41aa, + 0xf43d99f10bb7c8d851384f5215bcdbc90489bd63c9b4fa3ec48bf1851012d93, + 0x2d95bd041d1b5522fed823a5d9d607d7afd455461f33bc8c1404ef348221abb8, + 0x2fd83f519597b7e807ab80fd8701dca3f4085957b8f2955f5df79c24f00a1f53, + 0x25c0c9abd576c803e422eecd77a3ca4f63a32b9f90f5366ed37658eea86f271d, + 0x31509bde9a7286eed15ea23537ac72dfcc35a9f4c8cdc92baf39dd7cca4939b, + 0x2f6692e9fbfa0ad64b3f748425ce43c3c69cb5e4c13a0ff06c14f2bb75141af0, + 0x1aa375c879966cbd87d4ce7089e354786c6f2a58e26b97c760dfafb72df9c5eb, + 0x2f14baf1792365a476c4c193939244a6a4edf35f41616bb6db4b2bf511642a23, + 0xc1552511a3185d9730d9ad3a86c6dce629f5871d7e9ca38399758b587830ece, + 0xa499163b884b67402058e13910d1c89873c952ea1a7d1a3eefeaa22d2a37d7f, + 0x2cfdadc4634dc875e4c2be0f579768c85b32e5a19baf3b5d536a3d10a3199bfe, + 0x2ba9818b35db18cb7631164687c593c9badacb53bf720607b46212330be420ca, + 0xe37b0ae73060dc2b5f671e27e14a7cdbf6f37b7a03e69654bee75a9fbd52c6a, + 0xfdce2fc3a75a381f6dd84b4ca5f9753a5f0f8bebf5cb6e606c59717aa7b814, + 0xfb5a2ddc03041dffb808a10877d437c2764240964c2edfdbe545854aae282af, + 0x1ea4030900b9f74c33a53a950d21f40738813f69e8baf44444d6f0a1368c6d85, + 0x2b26ae52bbf7d41a66d984ee37a40c95129c4949cc74ede40fd7df3f3bfc7714, + 0x16062ea8f9c3d1bc9acece3e3afad961eaf765069773e679240dd723dd4530fa, + 0x78830573fab36a4777b4d82c044a60d06fc2abcaac1826fffd2ce0630d00eb0, + 0x2f17fdbeedaae54d1409c5cee2a3f3ded005fb6f84db8eb600111679e471be8, + 0x1a01b0c5b209af90e35799cf630441b0fe38394300a1dbdadf7e80230425ce03, + 0xfa20a26a6950d031e20c9fe19f1317c0e694eb4397a25fdf97946bfd66e5198, + 0x1b63869e274926ea2e91c0fa091b7074d5fcfd9987e887614da86eebd6b42c1d, + 0x728043328557038e7370dd984a822050199193a7da9c0a670af7af9094382d0, + 0x9570a7f7a06102b55bcfcdff64c42cf2ae994a20254054abecf6609318b3707, + 0x1c2ff23fd6d0090161db54a99810f76ec767e2db6e830afc9aabde9614829e6, + 0x7faf7d80752f501cf0eccc6bda01cd349376330df799ca842ed4f452517f6fd, + 0x2a25dc90d45e36b9367d207e45be38d449034231ed7c6422d2795baed9e08d3f, + 0x5d6d08e40d2741bc318cfdd961e62bd5b1439145206f49aeb0e8bb68a244851, + 0x9d7b3f8a46f030b3b0b27bdc77d990cc642e4f3dd667b085ef114d08bbda9f0, + 0x2d17960ecd06706c37ddcdad5e4707ddc0385d883f08fe7c8b36659d94ef85b1, + 0x15f2471564848a163204b074c1dba4c518b1e9a4052a3a7e5d9c2a0e77e8ea99, + 0xbc29d644405d0cf3ef18b311474b8f6d0e5bb9856059ea6b908d8eabbbe4a3f, + 0x1f3cc2b9a666ca5dab8bc17436762dece0ea6ef3becf39214992627d49595ee2, + 0xc5c7ec0b72c7947f7e1129191a11ea5c2d21a431561b3ee1513d0fe07b6b5d1, + 0x1b02b02f8547bf62c0250622fdbf6c094909fc25151c3941b5c8c2e06d675be2, + 0xd3213b732109beeaf102b359db224d86031ea2bbe1406f70b654eba980ab84c, + 0x15848ecf21e60c3ec1ef45998777202b708426a72b03f8dc4e5696dc74eefc8c, + 0x14dbf6efa7caed2cf9ec698db97e7552c62b386a3483ac39028be9fb5d6e3b0c, + 0x2616126b746c3d8a4dcdcbee6d4bb8c5ab7a3ac8c5c5b91a654747119bc70ae4, + 0x191fe12396efc23ef8865e32908d76c09ab0fe52a4665554020b7ba659386297 + ], + [ + [ + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x254b8126f45243f14dd8211df41fe5516b35952d56c62678c148e73cdbad3718, + 0x270712f18b1518fafe093660f492cdbc2fb70ffab31d8a4d8a1934be68792369, + 0x2bfc3981a249aeaaec4ab9001727d32d4e6fe75598ee964fc85cf30d50df584b, + 0x16060a17e1b11f851ceab20464572b3d78d582ea050014843101485f65ab723d, + 0xe73217a106c402e4c6c166cd9ef1fd2a0b16ac1cb43646bc1c726f83177770, + 0x4b959ca07e7182ca08f2351a03545bd7ab676f740b02331637ea1434c8545ec, + 0xfc9cc95222f92715cf7476010225e14cc38f314071e50e0f3bc9ec674a8aacc + ], + [ + 0xe1f4e4d26e9da5f8ee3deaf48b493610be61d7d3db1d9754feca30879adc644, + 0x2089c597feaa4ca9a202edfbc823763100e294c9e33000e513b2a216491d474a, + 0x107cfefa1e864045a668396526ed9f675b2bbf272ca635d8d3e8801099bb97d0, + 0x21630ec3f236ed219f73cc617b9f8b267dbee99a63c528544ea31b27cde49fb, + 0x2741203d66c523c7639ea713b20346119c961cc1e9659a458af74cbee16d71bf, + 0x17b2092b0f634576b654c6de21a1a8d812bd4c01559fff83217129082e2b2b20, + 0x68e8e63411df2b3a9d7c567f66419a580d3ba15bbfdd1226effa3fd6bd47b3c, + 0x2f5a2a0cd0cb24896c94878a8106d57e82c68dcf1e209167a45ae9cf8570fed2 + ], + [ + 0xc298c14356a5a7f226c5a549e59184900385aafd8ea41d9746729964ef75f34, + 0xddeaa906cb65f3e9c9bea6344dda8db90c253c0f7f99ecef88786fefe0e5cc3, + 0x4b96a296a35acf415929b8784b6bba64a630d29dff28b628fc98ef708230b57, + 0x28890a03199b727fede5ed0090ed69494c053c97930fbb6c52358b0d7d104c16, + 0x2208c5004806c7aaf58314590bcbea16168fe62ec0497afc6bdd2938c12d9a23, + 0x2f24d609cb23720eda55fae29ec6f19902c42d8bf904fb656202736d97b2eb69, + 0x344d0c772c2f053664a7b9266b19d48ae5d2ab3d1c1a18150754ab4b836afd3, + 0x2cd19b5c55bab1809e52cc9fc1a038c08935da19cfc563e7048d6bd1970a0c8e + ], + [ + 0x19e070982d3ee675e1622ca20d13b2375e528b676706882eb8f1afe1c5045ea1, + 0x1114c9120442750493d999d4dd45dbd4f3b75ab183209235396ce83d8ee9916f, + 0x1f0465a9c133a1c6805d705be6b3ea9912a2d062c34dbef92de46955b83e7bd9, + 0x1b80f3f439396c2f466b8e9b25765a014970455a1beaed7a6fa308dac75fb582, + 0x1c01f6db435dc4885eef9cdfed193250b9d3eb4cee366674b07bdd194ff349fd, + 0x2df183fe2bc9b8b75773fa961c8d4117e582a80b656af5c58763e7024ea4189c, + 0x7e0cca1a35ed15fbdb619bfaecc7a9a8f4c51293927562acea8eab817c6b84b, + 0x24ff2986781fe40ae61e8f5ca0ef17c5a5ea7bddbc127d431547c1f6a8f5cedd + ], + [ + 0x333e2923992e89dee570a650125eda75a20a72e69e10863a19d17b7beea9295, + 0x2e8b35a8c29e639dde8dfd49b4b347f00ee467863f6efcb355fa1534ef70783f, + 0x27a2b7f5549e5eedb90105c0f8e20f0571ab7af0801f1bdd23eaad91f2229a13, + 0x2a4bbad245a33e5d9701537f751410e4ff297b8f1d1d9098fe9c518c261a1b0a, + 0x1f0e36c2cf9ac2c4388e74966d9ee7d1a0b3186916a08cfa306f6bb36d21e548, + 0x15fe963f5bd0d92878c10a894e118018db82e63528afa4d4703e9881eda118d1, + 0x222edf3e26bf74b2f503983189201d4ee8e6d6fad341d7ff50748dd739749df6, + 0x12a87d0c5419f448419840e5e5a92d276ace00963d987f2a1008913d98a27114 + ], + [ + 0x1944aac72bf6fbcdec04361238c3c4d9510d5f07439a1b6ff41f652990be0139, + 0x20e6cc613ae6cb0a518425f53db1298a7f8859ee20aad08320d0a4f9bbfe8512, + 0x31b0afb7ab2f1d241f882178f7dcdad48591cc67905d651dbcafce94b14d073, + 0x1e431f2b1b7edae4f8cbb5d307bf5131c352c2a215a870d739617f4b017c6d16, + 0x199fc2be60e49e679ec2ede6cf3345dcb3b918e5b3e07c2cd8141333934e178f, + 0xaf594dc4030e8509701fbd3d8995f73126ad72a7af0fff344eee82a31ce77ff, + 0x2d4308b4823b465db653d36818181209d23cd12f844f72f7548d49e55055a601, + 0xaf3ceff2c865a901b9406d5d9b2fc58833d642f46c6493ca030ef595061ec6c + ], + [ + 0x27d802ad019a42fd04892ad167d9e83596a730605890401319661675736359f3, + 0x2420dd1281fc0dfac176a752d15906b55f137b9cc320d5d5daa9df3f3d43d3e6, + 0x22e0323bbbdace5fbc74a0b3dedea6e1e3bf10e84dfc71fe395089ac197af744, + 0x255639889a259ebe59f74a8fdf2efce7fde1e3a666b35d8e6ec601d4d0b22689, + 0xa38d163b8a2fa3092999c1797b1af909bd971a25a656baefbdbdfa3628e678f, + 0xb8e857d9fb1d554f3a4ec307ad907de7a436438603af1b28d4e4ee379960ce7, + 0x2e8e67fc85f9b4d00e9e1197b35bedf55afd7300a4c370987c83c15cf73cae3c, + 0x27f42d86842f4d8a8c3aff2f47ffc1e179f097aaecce55bba0b0fdfd5b190aa7 + ], + [ + 0x2bd05a040a0987ac6bc01f67242d54b7a2c527a970ad2815b273471eb9623e73, + 0x17bd4f2726748d99925af9a2f2929e231c1869428c13b1e397bb0099191723a3, + 0x1eef36d62f3f864eae67c63324e47a6344e33a2d5bfb82f05bef9900c54e745a, + 0x2d0d8a814cfa16c2323f174be2dcbe0c295829fc59bf2a89f13b4ead0eb056a8, + 0x198949eef2b27c2b9c3d699e3fe57da3d5b509c2b670afce400aba1aaa9ed51f, + 0x7ebcd25a10e56693a28155fcdaf7b3519d9e0e08241e21789696cb76ee06297, + 0x22f1bc4ec138b596128ce5ee5b8184964cc262318e17ad21d45c552477f53e61, + 0x2b6b3bc340d4119e57831e4a2187013f1216ab3b639945dd92a984943241f1d0 + ] + ], + [ +[ +0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, +0x2ed795314c562ca0b6d7070712495423ae6bea218cd94677d06e1043327d5d11, +0x1c700c219b9fd0ac323c67f0960cfa94e637aec4a5b68c8c8c579da52123752c, +0x126587f4ddc000b06931fd6bb92c2497aebd10bf7d001a3f664c6d6934225f1d, +0x1d322025a71f8a8445b7c50d8020f3d755b7ecef465abebec16e0d391bf9bb8d, +0x1d3fa515e56ec187ca7657d279ee613e0f993ad146ee2b37f12d142eb8108e07, +0x146acde01679ad962ede1caeb39836b4d818c68db52a9a1cde771be24b2e5e20, +0x48997cdde9b1ec6f3bc2ef708b27929596d02b366f44386093108703f4a6106 +], +[ +0xe1f4e4d26e9da5f8ee3deaf48b493610be61d7d3db1d9754feca30879adc644, +0x17ad6adb37b2fdc36e43baa800fc4a0fca98a20a2ff9c184a838a1bff5baf530, +0x14583143fe69954ead766939d693b018c9c6d99e86ba2002e2960640f993f19e, +0x9664ce4670db8421617eef97a4619d9914046ced174c5907e7305424656d460, +0x51301752f12f6de8c23dc31745b2b19b9bb7c39cc1ea08d08738c36a5e85885, +0x226238a28654ad973e1a259a8263c6b4aec4209093ce8e563b3eadb0f1144170, +0x1fd98a7ceef4a6d3b32de8b124c7e024e57c37498fbec5e451b92f5666a9e441, +0x1f471d25bb7448b69310b975678ddae2aa9080ef691242dc6871e6a680bf6a44 +], +[ +0xc298c14356a5a7f226c5a549e59184900385aafd8ea41d9746729964ef75f34, +0x4ef313ca88e6a46eb38c9aba804ec4264f79f1dd0c05857bbdf427a86de4483, +0x117bffb0996f3b8796bcf62f00e93cded9b3e7b07180721f2c01e53c98502f42, +0x36d342dca9ebe248ef3674d1399d5cb02a51b6ce92efed9de36f2adfc837cd9, +0x1521f1fad861eeea8bb068264dcbe68a93abb6076fae2f9e17066e4ff5be87c, +0x2d6baf82ccebf60b0fb1632990d9bff876ce740798a6613203cb078a9ca1a532, +0xa2ce4bc27cb25682f84ebfce048f14689f31b45e346b713dfe35716b9447431, +0x1e1b9c1ae86ec688bdae2fe7788b7311114a3a8d6f8d7fd8ac4d79a3cbb38e4e +], +[ +0x19e070982d3ee675e1622ca20d13b2375e528b676706882eb8f1afe1c5045ea1, +0x1562e5b3db42e4e28c9c3c085cfc8fe652b68e8bce182e6e1c84ab02661a8cfe, +0x1abaf63769a9a837a0d09e1dc6efb2dd1dc312b0c1c4a8c066663998ae04bda4, +0x338e5e98906f68a17cb1852bb77b5f42f287cb74e3afdb066fe966889db200c, +0x2d74e6c13b0856c0dd85188c8a80f41dca1e9791b1042521e7bae94bb36d499f, +0x7672fca8816914835cccdbbee62aa422a95d77118fe52444b5af200af0e00b2, +0x276718d84a065a288179b23b9b2d8ff3f6e55cbf97d873ad1f7e9a2cc8a09649, +0xa1bd98c224950369af79941d860914b7cfcca9596899786e6bd0889482641bd +], +[ +0x333e2923992e89dee570a650125eda75a20a72e69e10863a19d17b7beea9295, +0x1a197674d40c43447787e6079278b5812ccb17996403315e0f06230e2dbe016a, +0x1ae4af74d44320001b70a0a230327d586b0319d53a839f5fd27fac9169085169, +0xb169fad164bc7690cbadd1ffb6ab2e67be46376d16629d663b0b83ea7b7e4f5, +0x154b82a74672e1433c3417f9cd1c53d4ec0e4efc9d4c2655eee3c24e4449655d, +0x2c54cb56058d37bdfac59708d54a16c1c7cef8012ae5d1cd83d87140ea73adeb, +0xaedbd439fc8a60c641e55ba0f17880e00420bbbe5ae332855e7be146a0a0b24, +0x1b87ebdbf566fc8747d2430b3c45edfa8ea4f8c9770230ff4091f58d6cf6b61f +], +[ +0x1944aac72bf6fbcdec04361238c3c4d9510d5f07439a1b6ff41f652990be0139, +0x32aac2605d772f1fa6f328379ca86f4368bf679a39937cfc508a58e982db9a8, +0x3a38b1fc1f632c027894c17bbc4702d45616649d8e3759d1bd4239d89c9cfa3, +0x26492ca60cbc803da9930bf40b24ab2136a9275fa8b299cfc2674ef08234ad11, +0x37a36e914e568f3de0d6be824fb24b107bfc8c77ed767e707f8aa5f0199b205, +0x5de377805bca799a16d073b79fdbb07a672e7597d16df2739345938a20c5b3, +0x2eec7d749447d3df1f1c2da415cfc4b448b3fcd473b9cb5891f36db1c33b5c17, +0x5c539bdc0b98fdf23e2c568d8aa039f8d4e200a6da374c8e764b530e9b65d2f +], +[ +0x27d802ad019a42fd04892ad167d9e83596a730605890401319661675736359f3, +0x1e8382dcf318cd0d7f58ba77c1e4641ed3412a480f0b779ee6c9b73147b09d2d, +0x5fe56b2e7f2cdf071f3a588f1c604b2ab62cf34ffc1d2c72cf8a86079f01fd4, +0x177bd045809197d7bedb995ae85f213e19c1e301a646a8caaf7c9f3492042b, +0x179ab9300b69ae8b9b7540f256c0947b8dee0e53289ed0b5b7d0ef09fd10826a, +0x2c2ad35579f01d21b61c81721de5f2787950facb1755abc12e63b0ade9c66e4d, +0xe78c7c5a33ddcd2ac7aba36f3b50757bd7e867f9e6775bef50c85632f870959, +0x2010d6aaa2a1cc21415a72760a1a9d8e1aa82111c3f91e1a35f2abe8b79f2085 +], +[ +0x2bd05a040a0987ac6bc01f67242d54b7a2c527a970ad2815b273471eb9623e73, +0x2f337068a0ab32fb994362be568487a5c9974d9ff203f3db13234838c8246469, +0x305fc4e93cd1c823068e5063fa983fd71a9804864231e37d61035bef75f60188, +0x170e3b120459d017daed43224c80f6425f59ca2260178321543bb556d501c090, +0x1e1ceec2c1097c4b47a0523f89c94a42f52f2e011da379b6a0e57ad09973e16f, +0x13e72b920d7df0336d643ff47f37bc44888b98f7ea8064d5c96f8d39d11834e, +0x2fa9d8cfc04dba7c7f80eae1154d535657bc7015459a3df9dbe47ec7044ec009, +0x288ac5e38d20b5159d4c37374d8ca702decbc6265b6396d30b2c2959ae2af9b7 +] +], + [ + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x1aaae08b891f5b2046c0e697f481c70f34b0c71e81cadc7603c7e5d31139d196, + 0x2693bc2b2377f44f7d8c291f332a6bf184d993289445a794fd3f815824c7a4aa, + 0xfa4b8bf58974824edb3fb2d26038975f49c2cf84050c8208ea7a30aec1cdf02, + 0x1746022555831c140765eeaeb08a06bdbb7e2e65f5a5f70977d41f0f2a18b757, + 0x3004430cc176cbbe7f33aa7eaebd01856b009f291df0567d4fced835382f68ca, + 0x6406c73da9aef2475718a34075970df351312c5203526d0e55bb00aac90c6f6, + 0x27db71cc71c8a22d6133172f19b8bbaf0e37ff0772a58aecacd25e869675c3d2, + 0x25a9cb700e5decd6dc4544b9c5e3b49c0e04a8d1f8557e231da51d8bc228082e, + 0x1f8b293768d050b67db5fd50be414ea637f6ac51998971b57ecf4e4db972fdb3, + 0x537fd07b3ac0757eb471a2745efbccb327fe00df9da4b4b37ce2798d5441343, + 0xf3d208e42fd3d45dc0bf71a72621a3a1f735caa82faf0c3829e666889211ccf, + 0x21b6ec876fedb5cabffce8f4386966e8f1bfd0bbac488ed7c3a9cc73afe3638d, + 0x95100091241dbbbf7446ae4b3d1cc2e00fd45c725456edfbaed74111168db13, + 0xf1cf912f0d9e8be188f3d193aa91b094e79780511c3a3853b6f20c771a1051f, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x1c0b352556b629b1e64c6e3abac4b349c05801e9fa43439fd61a8392cf186509, + 0x1298fbf78e8967359120670758f382a8c951a8d2186b96e364e9b221d7b121a0, + 0x32529e49b3721ba593bd059db34fc4c01b5d036d2495b6d3221456edb02fa3d, + 0x2dbd37ed630dd234ae12f4c3dd4d106e277497f79cb16a71b4ed871d708729d5, + 0xe9a1b9cef20c937bd369647f84e2a310bd5d83e8d177ca9c7ea457169745b77, + 0x2f25b164c0610b5cc1a2ffc3e962a54ab01e0632b062e87a0bf249f8f7a51cf5, + 0x27b73694b83e0b1c06069c9cc1fc20dba1d037e481ef2161a30f4de74c4979f5, + 0x1aca98163961aa6b3b4bbb40fa812c86822948bf91d38e606bbf5e1dbb732f2c, + 0x23f67b87edb5d48126bd42b7f2a9f8be7db2ece0206f97d840d28dc3a4967c0f, + 0x2d7104faa91a3300e3ec93486228f3657b0aaa7277f0aff4760d0aed02ca07c, + 0x2f948955cf159477c7b411b0a868b9ae9a56a240cc20e40ce1a097a4749467a1, + 0x105151aad6d4d7960ffafca05d4f8ab4ac1930b222fb91eb9eaae07ddc18ba84, + 0x3cb3379d04500d1996cefd61c5032852d43e41e87148d92329bd98003fe5d8a, + 0x12cc617757c857678ec716ed94050bfe192215d9fd76be3bf98b65401e8d12a4, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0xc8716d8ded0a8c521da019c24594a1b859e53e85311efae748ec9312a0697d6, + 0x2e082be597fce21e7ed641c2a50feab6a4b26c6050cb7733979656d9a71988f2, + 0x1775849fbef452ce7a0863e715a67ad4361b9a2b72a055469333b0b8b8175b21, + 0x1fc8ebac9a5cabb10ecd4fb66339a2fec1ee8af951e69f5837775cdf4abd3e0c, + 0xc92dc16c65e5fc74d162103763ac39f2ca7ad692aa9dbbf9132b8d7af4025af, + 0x1e5b7963f79d2bdf1f857f13e667e9d7a97b4605846db4f0a26baec8daf691a3, + 0x19172d7e44ac5b1b381c2c893dd30cfda08c46fc6277dd38cfe1b1cc4daaa8b9, + 0x184154d48a6c6cbf9613d54a604aebd5820c53049749f533c0efd168e4e83e60, + 0x1ce093daa2ab71b132dc2d3bc1fdbfb91292c35f083d350eda02629f66eae2c4, + 0x12b07847ea7982e0e6dfb1b2864ac2e8f04ddf7d766c33bee75749015a91342, + 0x1b96c0239c9b6643850b8a653486e0df1d4c7f667a59ede3064e4b5068b44200, + 0xb053365816d9cc61b7e857531ea416ea33d60c4d8a529317e29a73a3aad422e, + 0x1fb9b2c50a99cd788717b3689d46c05e0d7dfa13c58f725a54851b1174c2278a, + 0x2c34ad3345bff455c0e461587b7332e19e0a9165375225769e8dbb2087391eff, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x60718f37a9480c0837f5a5e7c13eb75c07f60a8d8c1cf9ff30ae132251203f6, + 0x4f4bbea35e9b9001e92d6cf690b28e9c0a463382cb76c5b4e6acef622c0436, + 0x304a3b30d2300c7bcd5a2b7ecea51942b79b7d04bf346f95961d37dccdfaa238, + 0x626de3124c2c8f04ef55566942ffd3a46f2b7bfc898ee9c5313e50a3810a397, + 0xaeb9945d06bfb644e310b3109297f03f2ac002c31dea430b2a06666f4d93e09, + 0xb9264fb57be56298cdbd2084d379720375d397ef5d09a3ec90f29983f0a1538, + 0x17dbef787498ee541ccad5751663330e379ec632306e689cb3dd89480adf582c, + 0x15e36a3829fcaa26cec9655273017e83e621b84a1eac7be9a764638202a1724b, + 0x243a86766734068afe7659f078d7384e2ae7a73c2e2b6dbede12dd0ac2b71a76, + 0x19f171461fb4bca771adb125c689bdf519519dc2b7960b5a7caf07c1700f0921, + 0x1f5a2974eab40b787b5ffb6de24e939ec04b5bc31475cd803bb2fe0395a6ec5b, + 0x96ee06e8758968f1be067fb4582c810694a7205d39ac72247c3bc4e74fc02a0, + 0xb960361062101863b600c67724666f71ff5acc674628f46d840329eec2a20db, + 0x54f72b1aaf1f0531eaea95d0148b0525af381f598b075f56f86ac0f7edad99, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x15d5de1e8c0f0d18b7aad179279727eece9d2ff735ee49e3634167d4d440491a, + 0x16df68e36d342998fa4818e065c50d575012f4203a0ee73e155fb6f9c4ebc049, + 0x283e201525e86ba0ffe200bb698683a35d51810b72339aa3773217411af1ead, + 0x289ddd4c7635287baba51ebee25b7e42f98cad532e2f57073dd7e8465ace409f, + 0x16c3afd8596d8515eed82ca10249d26aa036c6abdfaa26efb7c98841b2719d33, + 0x4d76016f612698f913a86dc0749646b7f4517d3e668903f76effaa95351e90f, + 0xd021dbb869aff3f4fe189fe3015d9d5848393aa6f76eceff7f9d9a72a736843, + 0xe769248c92dd03d46e9e6ac5835329f2d5f7af5cfc5d1bd920f097379443e98, + 0x189d6ee4a5b445947e0efa11690f186e98a54d3e6406d880b7706f7defe167d8, + 0x2d9bcac46f7ca9415b13759c9b4cad42a113bc19565a01cb889e1d2d698c76d1, + 0x684c2e542b4e0c59a7f03a6d361369a5f6421a91b98b1fcf0ac1b7144e631b8, + 0x1f6608bda209f29ea2d9c7df3a924b661aa614e1fe034f6ff1ec18bba7a14f38, + 0x203c71fb9d4f1881845f258bf12de6153df99d35fa3da8cda1ef4e18ddc0a65d, + 0x2bddac5720ca5c69a727c029e4edfc393e4115f898b9da856f064321ee8e37f7, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0xf415650a23aed782936a31cc331b3856b64768dc9b29c9a68a8904a08a2366c, + 0x2a3272896962e7d3fb7a1c783e24ad141781fcd588f4cdc319b3deaca21f79ed, + 0x1aa729490f697568fa8cc7587c9d92bd19610d8712eb3d31a03ee9a65bd443d8, + 0x102aefa3ca3e1722980dae564122eac6ed4b1534b65d6effe5503b615d7b76fc, + 0x8fec616df09b477c42d44cacea45c18644a68c59183933f1fb67ec8c452008c, + 0x6b5b266f1fbe4ea9237a231f8c28ea19723adb47729b6913b7af9454f23dda5, + 0x2d4a264e748b499d97b3320cffb56648af68616fd73bd29e1225e2c45c1163b6, + 0x2224e659d1d7f55a80406d270debf092f713eec67aa001eb50cd8b173a766988, + 0x20260ec25a18f49225f3accf1020805f5982f34b658c553f5f744d360d50d571, + 0x1a692c93319abaaec066616f97e14c1d511e86965517496540cc0391490b1b57, + 0x2189d255d9ca828ade6cef86f5de626fc2689904db402a6131066b41616c23c8, + 0x43059b6857affa85b90d865eb1a9a91f036aabe5a12c9a03e8ad87934991a09, + 0x2a32437cdaa6a32a0a3c060c2865abcd8cc2a79bad7efbac1cb8cdece412be75, + 0x1746046edbf4fae210a3f0273bd7cf58beabba4c210b3617b030f7b51e6f8f44, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x166371ee86c08d7d38a594cd70011ea1ecd01154007d555fcce5796dfec39e35, + 0x22f89213a0580e56569c73128c8a41351b42106d11f08b6f900f8c61e89e3edd, + 0x1b3bcf6322de40853b5647f94ceafa4b109dec51c81cd7a38b51ad6d96ecfa8d, + 0x2fed79c7828b5f8fefc7c73f312de0739c9a2081e432cf2f62731a5f02fa16ca, + 0x243db465df5d6d34ade58f233829cedd38dfb57101da284d42207eb4df69c7ea, + 0x1d49c10bee07998c64facc37ae50dcd91a17966b8731f2d1a34b3f78559bfb14, + 0x2d7c4a750b7000a296da599f89c4ea7729cfb85883037333e1b4526aed397cea, + 0xd4f4d2dd076db4bd67ac279bb51826a827742918d35aa52a5c1df7a3ac5d339, + 0x228901e5388a5c10531d4122f7e0772759d1e4d026379ec16676f45a64b818ed, + 0x111e7f5a746d046f4d7c19f2fb49c31255ba045db988cddecfa0e4172fcb2d6e, + 0x1595f02fae7bf2b328680bc0ae805194fe9ee83f4fdf4dd0d35e84ab29a122ec, + 0x2d22c9fe81fe2db64f3ba5cbac4957fada1f0c6a6a4cc883db4dd922d35906ed, + 0x21587d485b2624d0549a6f5de06c009ed06c5b48201d8f9a750c5e5a98ff19ae, + 0x24c33e212e7e9d3faf0ce44a3cb2113e74ffb7c28b45c7b4ceba5c1d6944a64d, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x187f5db526575c180e8adcabdda34e701463bf8b1596130c0c6b815dfb5e7a24, + 0x75eccf8b0d6ecb184e0f168c64404e50e013ce0df06bf31cbcef2421ed7b0e9, + 0xbf2f82a1b14f888c48822e147e332a2bcaf77ebb32d7cb3cdde813f0b1a373e, + 0x1f587a1be361522f8568d2109e0984f059a87317a35f7ccd7365c5d97d447e62, + 0x24a69effda852c7d20fb4fd8c3f413db1b6ff3979409e83922789cca594a462d, + 0x2ce67cebac6bc12ace86bece70ae7a5a59a97023cab6db35a0f8cb7110552ad4, + 0x2ef4852f4fa73b0c40c37118ee2690692f1e7101a78a38771a8686ecd37023a1, + 0x4ea49b4f2225a5cbe53c157c56f62973f394fdb3076954bbbdf30786debedfe, + 0x2e874d03cebf495782ded304d1f37903b06c3f834f170e96d26812be0ff52466, + 0x23acdefba9e5cff344b212629dae61e76e03a8a8eecef4e6c0588277f53d81fa, + 0x1173808e27354b4bfa76d6bd920cfc8309f1e9e99f997f773195070843eda183, + 0x29aea310845b4a505ea34932e7bc2a8f2b936c47fec5f2269a3c999413d048f6, + 0xf5536e4420b891f4cc82c50a833a17f0cabb89c3ae4cba4c28fdd5cb02e3d2b, + 0x7a3576f0287b2a1c0d832be178d43b6858a4c8989e30041cc143f09e2012fb, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0xa260dcd98e220b61c2012dc6380f52adef96a11d38e7371c576d54563f7bfb9, + 0x224028c158b4b4adc53ae913cfd9ea42e4456690be5dd8d4c459779945157e4, + 0x166151c43e43373467888a2ed4bdaf3148d8ea2432d998162f62f8159cec690a, + 0x556f9ec39ba4bc77b183cff006a0a582adb55d52dd0f4a8c1f156b33898b28b, + 0x201670bf6f1fa62050110754b53b3d0671086156d9890ac85f40c69aa4aa297, + 0x18a78efc7a694b6e957b209c42d6044af319f194dc16451c6da27802e7f1c85c, + 0x28efacaa79a0af5fa9ddd71cc6a711629788664849b96ff0b42a61e2e43c87df, + 0x1d07f908b2ac7783f0d734e871a40be7b2e164afe885db6fd312bcecf4cbe9ab, + 0x8f97fb3cc640d078af3d17c569f37a9ebfa6f49c48db74b3d948a8675db96e4, + 0x2718e729e940dd2d26c6a6fc7de40b89927f8c9df032cdcc06ed4ebe194fd596, + 0x2c68ea4120e5abbe11f3b62801199cdd8686dbecdc52ca8a9458ba48b19aa6a6, + 0x2f39ffaf54a4cbf00809ff50047289530732279ea49607ee779fb149b87e10c6, + 0x130fb307c6cec609ab7c5f9bd5910a9ed9958fc11e443705609ef3066197a9a7, + 0x129a1c66d1eb5e84211c482bcaf70789e6d5cc473e1001dfbda059379f7b58e1, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x1cff973af21d88635ec9afbffd85b1cc595703ae5bd5f4faa6ead489d7aeea20, + 0x27ac0db61623f033dd102e118d47d847f34fe11826bc9d23d7e3e43386ad16a9, + 0x25ed2b22b59ed4baed8f5c957caed1fb52630971092d0af3ac8ffe5fe3a13904, + 0xb634c3abd9ad8e1b2da84a144207c4ddeb62c8f4860f65aa2209c1c0d0d7e75, + 0x2158eacda450c34d62fe6ed5e3c9e211c170f4c3bf4247c5caf0b9e2340e409d, + 0x1c0e715ac64d64535fc97e4d86b95c6120401f5c2697332b1ed6a9e83710afca, + 0x1a491a07ee1df9abb02aa300654e59bd34f593a15b74306b41c04e8b9530986a, + 0x1523cc6481931e85611b1844832abbf8763fab9c85130f50ab3075fa4f60762f, + 0x2816926c129f5c99a970733571d5c01be1cc18ec0f45bc5e46068f0d188bc9e5, + 0x2d94c81e271fb9800d333223a141c9e904476dec1f8f1e6d224ed49467e18a1f, + 0x1bf8ab0b8cefdeedac41738599d38ccaee7c03914364eb617b5421e9a51a0b27, + 0x21fd6c59b0f417453f2a4d669851364f5156b6adf104625f857681411bd04c64, + 0xaea3c50afc0806b117aa98c104499b4d84bee966a94865896a39b9f8ebcb917, + 0x29a8795e1f8f1e27e7e04b23788ac40e102536d56b57aa85fd1015cc21970f55, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x17e4ac7e489fb7da610506535bce04186426722fe24a261a3e286df2f3519b34, + 0x10ae4901e443ef76726afccf1c9099fc18001fbbf5d144ed721196ac9f2cc130, + 0xe60f58884bc252084c93a18b4feff245175727c03003f025100d435a0debb60, + 0x17de16da3692bd34ac4069982a1fb163da3119cc01d12c6f1ebf64db787deca7, + 0x78d14f36f6349d1af6d92afc8dd98ae7322f3c11993c59a225b079c7acbd4fe, + 0x2cfc356c4f60781e3cc83474da74607b9567ed3a08cdd7242ffec76f7d36cecc, + 0x1531440db56edd521c68fd2dffb627155130e6f3a2b47fde65bf8785ceea104f, + 0xc9d25b13772cda116107dc0c4fe9818b74f24a51f4bbca5a63bc4fc6441996b, + 0x28a4751755712b3d33f9eee850ccecea47ebbc32a1fd199fc256b69c04456500, + 0x1eb00cff68143cfad376aa8ec83216badcd664d55e990cb2d611fcdda52e4407, + 0x1bbcd528cc66eb76816135706b090ea3b46d45f0db08af962f17df4eb996dee5, + 0x19a41df7dae052bb5821aa4f32e9103dff752baa24b9fb51fcbe4359827f8cdb, + 0x6f34fe490adf4a07fee6398a39e84a0c32c04259c9691daba54ca4bf696ac5f, + 0x10cebd9c9c4b941425619aacf24419380dffdcc7f5326e766d38e72838be3120, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x214aea2850fed7223af80a5906052159cbfd07a30736ae5d95e6b60cb4989d14, + 0x15595aea45afbcab1d4d2e73c0a36cae9d2fb50d36cdfd5c0c127f95862add38, + 0xc4055b948c4a9fe79aff19190da8995eaa7c537a20cdd18f5bca5371d0c895f, + 0x202dc56d64cd4dd16ba2e50781fbf937803bccaf08b7ba8733eadb427c13989c, + 0x2ef4191b7deb37e92edd46f965bfcc66bc5a8539957f319958d91066c3fe15da, + 0x2f6942e918adbb191600a517edb486cc96e355737961c85e0d8595ecf579552a, + 0x2cd60b5a15f37871b552d8095cd8a6ffaf033b539d7bf1ae5f671e2ffcb9f2ce, + 0x2e05c44549c1ca99a8aa9e5ccf4726240f75a4060ad8a71012deb2ad55486afb, + 0x29b52fb3d57ee05634b2864e7b2977f7393906c12e903931531f95c5f4ae08f8, + 0x1a565be54d3bd12bc9a46a1e2853a18ed26d6744c98e5cf53c83e6600cc56a60, + 0xc806f9ac20225e54ea2ff82c73c6809497b46d85d51a4b05c46f667bb3ed592, + 0x2aac8b1272085c7986012bc5c7612d5b7eb5933a9140498359b260116290048d, + 0x1ef1b93e5e0c4bdeed8d40d74e84fb0ec5e8bd52af3ecfeaa54105e674611a3a, + 0x1a1fe313685a247b03cc9abf0f0ca133ea119ad01ef6a090baf774491a001296, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x694287a5d6c2f8c7e6ad899f7960ea1abd3aa7829422a66be8e8a1ad6bafc0b, + 0x2aa1bd4878e2ef8252ff42d595d2d0b59d774a98e3439d05682cd28463e15104, + 0xecb968856d9c8a1317c756d0e48d5b1c365e6eaf980989d3cf77d110237314d, + 0x8a950f1079254aa243fbd11fbb4d25fb0cb8a0c39bea71a3aa1c0df80943907, + 0x2ca441a867e40ca07b530a40b899052427bafd17c7a31d484188f96ea21cadc0, + 0x60117f9406bde6b52e0af3a54444fe9cb69bc9ef22405e2b85d223051852c23, + 0x18cfbf11b6c20bd7cb8fa67ff4c032c39fc2b3610cd8f90bca3e6136c6b04f4e, + 0x14addf2c0a38c601d30bf96a82d3fcba2ee369b0d2f232adf5da3e2bd2970a43, + 0x2677d87f29a2a948ca7e8f5a5341b56947563be4acc97c46e557f5c60eb84442, + 0x2f423100c2e9988b6cf5e9bcb1b2aac09d926458b9f1177f841977f39109c1ec, + 0x2549090369bcca257da260694265b951c15643c8103c9cc73fbb6b065db979a8, + 0x205c0e6789ef1fad3b8f1367cf4eb199b400b16499841e1feac1cfb774412d97, + 0x116a1eb2caf56acf7308b5b7a7ca6b98224c93a655d78ca7867a3ee170b33fba, + 0x319871e083a6e2cfa6a69f480121787a71853c4c6f772fab9dea2e267f3576b, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x5b98a534aa4041bb0c7e79ae6b2f5c164053b4c0a65dba7fa318a5aea8d22b6, + 0xdd5bbcdcf0d6fe99e9ab4774911a304957b461e3e2d809775da6d9c66ff2cf8, + 0xd5e13e77b22ec3447adb2487c15a4ced671076f0d0c0e8ebc9072f1d8e37b87, + 0x20468b6dc384b134a4538c25683b468c877cf30b1321dc7c39e0fc942dc64450, + 0xe2bfc13ac065e251caa703abd5362783941ed0060dd9d1b81f50c630dca8376, + 0xf300f277165a02ff123b3078e87e6251de0de93dd81e76e8f8197b949960e0d, + 0x19ecc98c331d8b440400e5a71e1ca2f830536b1900580b3348f3b7ce93f75a5c, + 0x2b60e2012b670944ceb50be1c78808ec4568c7c442933b21f125e9cdfa7ecba8, + 0x2c3e3476d128db70aba892a46c2061ef24df0ac74db004e7731b167f32697459, + 0x2eba0701ccabc0ab29863c74c80f1eb3f6a6ae79792249f4e4fbec63b6282e0c, + 0x1b821e2031ccfef578878ebe3481c9b5db9e7df929755b98059ae847b7871a1d, + 0x12424e45b885060002f66118e487a97bbb10ca97ee0414712f85f2154a6395a0, + 0x22dd55670c91344017558b62f32c530ef0f3387736514af44cd43812c3c3830d, + 0x18c607675f0a99f94f2e7b161c693472ca5963f71823a62bcb4545249ed116df, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x2d16a32d5c9663139709f054159cd7cf6f93c5f9133007b4ec8de3983231be32, + 0x1af2c4175ff13a4c27cdf6f91e6ee2d81e56a4d42d6c13f5e1b41d8f71a985fc, + 0x244100fc9f31adb4e58ef3e56c2fa32b5b534d42a226880d78eb3be202c9dd07, + 0x25fabd23de22009b978a089414dd805837cc0e1d2d68f919a50b7e17418f2151, + 0x22f32d43c35f5cb33a857ac06d5d9777a42b92268f0c06b26d68f7542a6b50e8, + 0x20b44788f504781a9951e09b497f1c1c2d2f723b864b84e74c1523527f48f996, + 0x17192ddb8a67bd2ccbb940532adb6e376759800df7429c45e5a09314e64cf7b0, + 0x116b6619b40c6172f572650a9566ed2b809164b994e388b6fc467637b61cc2ae, + 0x1e0133f2e4adbf08938a9ccc82fa3d3693316aada3b052fb02ed3900e1d730ae, + 0x1664c7e25e5a7d2f285156dee897b4af0c1446a32e575fce4d56a3cab23deb44, + 0x2512c8e3d7d525edbbd4bb03394bc4ae7aed7bab5ed55ce3fc4aeafc329b7f49, + 0xf5800164acb67ed0f6efc527bbcdb851e66995c9dd3ea18cdd9b54259f64bba, + 0x1e4dadc5ca72e83a6f54dc097f0c2f72d506ed77d576abce800858d48cdb9cc7, + 0x398b2ad87a996aec8db980123effebfc59ef1d35be0e6a7fdacbf3929551bbc, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x2e351fe58b5f36389df6c53ace1a5366d9c012a2ce2e0c4a9dcb30cf75f59869, + 0x290c7b5e749c1532ba364061abbbde22272b62ee90ff19be581c4ea68f58c5f3, + 0x1313fd3c761307310d30f5aa63cb0733244796351a9c6077ab5ea343e996a778, + 0x2c31bfd37ed16abb1583c403f09dd2a064e4d03f9487a076f496e0c8c5dbb3ac, + 0x10cabad2beffecd1d735b7284037753a85845e6fd5b7247f3b457ba9cc9a323f, + 0xe02a96e2faec73e916458f940919859a161b6b85894abe5ae146ea4d3736d10, + 0x1d6e090f0acd4da143b23f3ccc565567bdf49353b3416207af2096389b791b06, + 0x45f7f1687d62eaaeedbfe3fd4f725c85176968069afd815dda5778563ae1a93, + 0x2874ad2d5ff34d854490d2f41eb79295d0bd9befdd54580b257fb4f2da1cb9b3, + 0x201894e0f41d2f3f21a6641ff9e3959584a749648f98c6c6b3c3dc6e8285239c, + 0x1e51409dcf81bc661657b6f0cac27edeaa209baffb0c862fde7c0d0610506b73, + 0x2cf3f549a9651db991a798c7392afcb8cfff307af338cee2a501dc1be740598a, + 0x1b7aa8f35a2488bda1d6ee416a8be05035872fddbb96fa56645d0f63bad04b69, + 0x182132ead4b05f9e1a44e7422da93b1e0e94d5906a78f63469cfa1b0ffd06a02, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x863bf81ed562159fc915b628bb76e3bae663dc10556dae9cd432ef8de50b6f9, + 0x16eb9ab36c92c197c99c3d11ef6d1469a9c4f9779daedbe99a8e5f24c8f5c0fb, + 0x2a0f1728e8a783630378d81f1509e94bb9803a47a112d99f7a58c60943c5c97d, + 0x20b391efe82379701a0f86af56e5d22cd881f98d0ac433df14ed990881cb5ac, + 0x586a52cbe0c5a8a0c45440f80dc7fc52451e815c5b0f784bb25f0ce319a1c01, + 0x4af2601360cbbcef49162688f13409f2fb6026f4137a0b9f85d4e2272106766, + 0x9ad52f4be13ee678536dc64d24eb019da0f5cfb36d4c35b667c7ef4c85ed800, + 0x177a0d318b5c0b226c15afa0ebdb0f3d582caf9373d45e73c25ea6dbd1ef0e8e, + 0x1ad9d99de7417cec3a5d831e8a8cc4d633ba770104d76f19740f8483411bc837, + 0x69f24d59c4dbc2351edef37a68c5e0133da60eaf4ec85cc174f5509e4676f2c, + 0x2f87a8a8a421081d17480f0363088e6604780562ec2d97aa1780a7be1d7808f1, + 0x2c2318745d149dfbb796aaed50048227cb01c1885ab2eeec9897423d824e65bc, + 0x128ec586a98e49ffbb2a98e078eb12b4c504448f53a7c59a7e2944ce6636ac02, + 0x2ab7de0aed5e6302873d6cf0f642ecbcf4b84d263c5f60316ea0e434f518e270, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x642e786838ddb539b8b481d50922cf6acba80cbb8cd74d91558b4f7a59cfe41, + 0x1e02bec25bd53fcc6becefa234ab7a591e14d7e1b9dded90a1bf8bdfdee1ae72, + 0x261a2baf4b655675fadc57ed29369e831a3a236768779c26340007d048dabfb6, + 0x10b56d5ccdd0be5391c62cda87eca6a70f12f8465ab4004c6742beafa69afad3, + 0xd1e13710db39230e576013e5b339b6697349b6102a915993648b2097ad216d6, + 0x2d0bd075d622a9ffaefc6998e1d3a845ac07e8827ceb27da1eb79ff36386be91, + 0x17f840bc566db8a3debeac087e4c9d5db07e4eccd0871c09c5314fa935243f1, + 0x299f4beec86f210fa27d718f78fae4f2d94a7d0b1e029c92bb0e33456c572506, + 0x6aa7db000f3f4d915c35090ac9b1a90b269c8d90e76269053befd34b76c41a5, + 0x10dc89ce0e3e131a594f3bd90a12586629af838d2dd7cd9566a66785cfc7b8de, + 0x14e4b1cc172d23e0d5fc7f219fa43fc301be8d8702dc1311fd97f784d0d1d773, + 0x26390978a65b917ecae0242affc450f91c4649139b132aaeb1406b77a751216d, + 0x19aebfa3fa2b4cf836f3d9f5b672a682b20f82ef9cbf8f092608c22327f1663e, + 0x2917d6cbc77bba7388d8c43278a57baf86c1fc54fbf57d0dc985238678c404a4, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x2962061bef3a0b557f60a3af8ca0b4e6b44336359bbfc9d30149435deeece130, + 0x1ab2e3bd8c03c56d30372867a29a5017fc95e868c228c456e318ebb2a7c2de76, + 0xdce3071ee2164d465e882c1f319aa89d169d4216a2b3a29dca0d74244c36a5e, + 0x1c7ff77683589db1c00e5303d9568894c240201761b546d2aa38e6c63831a4c9, + 0xda3ad9016d141320edf78fb242fc386662fc9183a250242fbe72997646ede8a, + 0x108c858506802f97c0a8a005b6f3d0e73e56ade83d3e1ef9291783cebeb0104, + 0x18a041ad99415766535e735d35e2406d99f500507d44c121194ab5d62bb3dc73, + 0x804d788ecca64fcd1dc6eb9594fb8e91b5fc9027c2e0542369f2a125b1cd397, + 0x7731d16594681b792f143ae2ef1365e94c7f0fe15a472a29d71aef1760961ea, + 0x2bfa3cb90f13111146c89385af82d9051c4e02f738f2f996d2a5f1db712ec6bb, + 0x1fddcd4b1429134574b4f66c202cd63a4214580e654e739ecfbfa3fc3bf8b41d, + 0x886c258df023184bd7c942c2f273140834d867b8def498fb10218af80d66425, + 0x19ccae1db1a9300785f134702d3b1c8d13d9ac87b9c2013e5285209cb804e1c2, + 0x7a4b8155eb76363e05e5f00ff95defcbd37b94afd901c13045979dcb63d6ad9, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x11526ac8331c0fb6dd4e34233c163073d83300629288634713359b2dcfafcff0, + 0x2ee5b7cdcb61f59988e2794312192b8afddd8f8fa1cf883c998f7a782891dc7b, + 0x2b88c35e9f5dc25ddc81bc209216b88fb526ad94c189d5300c9476d0445426a, + 0x1947ffebc3ac4ac3ccd1d57cefaf6190f1c1035bc5ba84706dcce44d9706f1bc, + 0x99f8cc64e0503354ea12b5a678143fd74f1b4d69654c9a8baba1d58101a3147, + 0x1afffd8d0170799d162462549921f3c7344d8a27eea55b4f9397c509f59f0e83, + 0x2fcd5239954935486f68514bc4cbb30282b25171bb9227ac96ce5ec9e6486732, + 0x2ca2a102b6561ae65db852da22c3b486fc77c6a2f5583506720a328a3aed8e20, + 0x1002dc58bfec0fd85333fb805a44eaaa1b478ae253a3d4a57681590d0b52ddfb, + 0x139557f5ff664db54d6be4e42e0b4f7ab92b47d9d81da1307240385200759205, + 0x2c89c5c93e90d0a7039ca638e7a1ea5cbc2358e61044b6a09d103cfc9ac4d9c4, + 0xcd0d79c5b4c6e7875b58f2c619fc727aba63df991c99d25ad2f24beca0df141, + 0x184b385669595dd8fa774311e59b2abe04f59546686f74fec70c9514899894c6, + 0x1cf3e5292afd10a90414741ed3287263f4af9515b8cae7f41d45e4109ab0ff06, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x2e764ed9c7bcd1b4f7a64f1afd3efad5476eece0cbc566617cc52bc51885cfd, + 0x2e6eb18b75b4908c063a9204147ea1e9707791f2c6fd201d081703b4cdc97ddb, + 0x172b99d8419fe0858380c2295d156c711ccf85f150ed4917ebc0942aba4ae961, + 0x864eea049a1f9510949a12d9a6e74537b3aac9f670c50d4f4bb77a7b68d73f0, + 0x1f9a772d2f96ded0661156db1ac0bbb7829ad3cde0c3e63bb95a5a47d4a2ca23, + 0xe72ce0076500c498994a78879704743def13b87a1c78bb60557598652e84051, + 0x183ca9c331d42e15818e0dd9fe4cea99078e0cb54013eb596f798c3dc22c4e52, + 0xcf4da57b9a9c07ecd1427b2b437664b5a2e885e76e1eb08e234c7b12761beba, + 0xc7aeb1957239cebeb8c3f35f94ab2fe443234d88b99fa1a77cc669717410a30, + 0x120218ec06b07045ed6b079c2fa91b68cab9caf72ffef5816c4bb77cb3dca124, + 0x290ab4acbb20c93cf9c99d07c9fd3189dd8a395928cf9be93857f3be7a4dcfce, + 0x1da24af446511ae52972f6cb9490df5fb5ef6f0414b514380f9c645a78c8511f, + 0x8eadf51c905e829f936a2a68786a45c09296b064ef0764b59e05398f7601d65, + 0x19b72523f030bfb311fd94c66cb20d105ba2f1ff248bea6c3bc314cd4558005f, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x177f0b80a1de3ab56e24bf4f8e63b45b31685e1dc1da5e30553d6be482bad1ad, + 0x5b07ed986c2df68a97a40e1c227c2f72d5520271666cd41326394722b9932c2, + 0x24d2c3f8955b7a068cf9a7bf1cd3cc1f7daddbf2a99b581f3af4980fb1d17892, + 0x25838298a0cc4b774b6bc89dc923f9d330599a9d122629aa96ed251b5bf10bf5, + 0x2afd3dd5e0fc21f0d9a2926ae68745e8c7bdb307a5e790ea08872e878cd3bdcc, + 0x80f2fce3bab6286e19d950f3372e78d4afe22d2b2757373253b424858b37e6e, + 0x29ad15ea08093d81d74c6fef9f18aefa1a6915eeb05e47f4779c8c44bb17c8e8, + 0xe004451085075e404f3daac34818db8878cd02f134592adbed0cc081851599a, + 0x2c1793f6782d38379e1e1e3867db57bf514320c0e37fc2961e50ce2cd3a61c82, + 0xbf3dd46be8800ec0b7452c61319c2aa365307c9b7e9d955aa7aa1057e91dad3, + 0x2dc74ff53d61799295950b34ea3daf706a0acd6d5cd2ab7461ec706dba082402, + 0x12d0bf8b8fe9ecbabdc9464854f9df7fc9950388a9f68bf7920aebb5f0285a2c, + 0x1e939676347eeeeaa96e3c0bd51e14604ecd97336f72eb054c61fa71309e43cb, + 0xa5c3db062ebf2c84c384588b0e97a0d2431f7334ea9006436f6795aba6423a7, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x41b75c1586f0664a618abc2e19231f4230761fbbf90746fa7ec06d4a517311f, + 0x202eb00eddadb4c0761953255195ee55af32ca0621e408a73eec96f080f07d1f, + 0xf0cbd02267d601b91a1a62e5d54246f07b337e84661c9a7f40de79f8527e94, + 0x14f2c248139059dfe9f4d970c661fd17be54e8fcb3a7e2cfc1160288a01d3904, + 0x1ba2c5f95dfaf2df18985f49b0be1c1892b59dfcde7afcf553fbde41c2397183, + 0xe0b040e8c04374f4ff9c54e6ae1cbd79cf4e46a5a32d644ae35f95b6c924540, + 0x3d017d86b1b62da699920b08e0bcade7c6c365edb3b9b2ed28e1cc5c37351eb, + 0x23b785d6905e142dc5f955a2ed3b4f57c0f18c79b9599d1f21a9d370d323283c, + 0x860b1ccb980266b5c9800d56394061e4a39bb2b31d503e915c8e4f2678a66c9, + 0x1e3095884e8e3e82a4282d39e2020cd3f4dd4c14def98a1bb3e4dfba4f372cd, + 0x1c0063fdf232c7cacaeaaf3243b4acd8511f8b784129c8d6a7fbaca45477c377, + 0x2de234571d455023bde68bbae1fb69b62b80b889c8c8099beb25adef8da9f879, + 0x305e6097b1a9cd0761e08a2509895f2d6ebf453aa7f3841bd97809cfa9a46635, + 0x2bcc7b73e56788e3f70565b4168248b0321f65d941840f199ca849402bd52971, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x1d437882b57028c88c69eab64507b2649e1705eb397a4069781ac10151eb2258, + 0x1af1a36aae7b181df7ddbfb34e34a53ae40e8529c224ec940907fdbcf97522e2, + 0x2785516123326658487ced2a9e864d2a9372df4a480d96a810f3ae1246840a50, + 0x27d476e2c174e2eecb790e9d96acaf1b17c675fd85f84923f0bd1744a0f700cf, + 0x1eb090499e37004464a5edf2eeedeec40e2c2becdb31426992f382a1e1197753, + 0x92fe84aaf6c1b773c1e9afa8775db02848a85bed444d4133e1fca601c6c68ca, + 0x104d16cb816ebbc760c4b3e28fe8c18aed972dadeb94896a2310ff9d61d44e3b, + 0x2fa387f6bb06f1d9cd2e78be84286a7d58cfd870c5c1e8315232361f2b44cd0f, + 0x176b64eac41dadeaa403f9ed5910f11a419372fd90df93bed240c8f79ae5c550, + 0x2ad76ba01e94f7bb8412f271b92d24ad2d7efe5eed06b0852d8f53a7700022b3, + 0x1a8932f1b4cfac9286ce27de3faeaddfa0733d07261297a38cce6399d96fc38e, + 0x1eaa55a6354586d0087e1d042859f63927cf27def44830af38905e3d876ffd15, + 0x34c7817421f2bc213fd6caced95f1cf9b176473e8721a100b1b6eef4348b786, + 0x31efc323d83d4deceef06774dfe798dacc4c5946664b0431d54e67acbb840fe, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x9e3886c90029fe260f4a2fec7d2e1c9a0d07abe79ea3598a758ad63c20e807, + 0x1525c95ae08bd592e2e428803d4e6a493016a47943488b02a78f2d552d16c4a7, + 0xb1011a90a452ee3a6bad8aa9e4885a62472da29771ebb98cee7117ba1f0e77b, + 0x2fa5ca0f8d2c52fb2b4578e1efb6e1a77fffd1bc525809626d3535833c5001bb, + 0x1db0397e4ddd02c509cf2ed25df7b81dfc5ae489bb9415ccb7127a205d3e876e, + 0x27a3012fa6ee7c193ece6fd7692ee96b8e4c89797792262db8d6d1efd755dbe0, + 0x274e23c2c097373e9a0d952f34b70020e233fd2e0a67c4e20729a5fc17f88c, + 0xaef53482e7e1c25fb664756df6ae69506b5e7aef718b3b1486aec64c4078ab9, + 0x457365cb68df73941a3ba80edae9f25aa2250e63cdd3a3b86b031cca2134d8c, + 0x1ca262a197b5402ad0640e919508176a3988519d3bcf91b55930fed1fc89ea20, + 0x2131c2ae4df6b479dcf26ed81a1ecfd47e351d7dc790ee906dbafbd803991c4c, + 0x162bf8864391b12a2b1dafcb658fb94cbfc90e0bddf199cbbc66564550036827, + 0xc7a2f06399f8766bbc313a2f1fbda042eca4ba85734b4040db27cf4ac1e8ef2, + 0x2f9fa0e3320e9ac3cf702f8750b5bd1c71c697a583c34cf417706738314eead1, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x9f933726715613504e7cdc8700fac64aff61cd1899b4754249b7e61bdba19f4, + 0xebcc03b0c123f471bf2e57426211644f0098aac347c81fd12621c7187bb787d, + 0x246aed0e85ffca6527d79f2e223c37b5d7df029c52d38b340bac3b2d3e2257bc, + 0xeed1e00ab5b0ecbf337edc63d27cfcf9135997f860f96befc4198c56e59c72, + 0x4df1a4aa55992245ce955d325c1c08a841f727b9e9ce11cbe54835d575c56fd, + 0xd5e59bf9fe7755023aaf344298440987786568aa06aa9d03f8a33f70b227fde, + 0x2ffe56ed078cbe07667f7e48e1a360d4710d046f0bb51130f9b924eee01dc332, + 0xd13ed4075159b29a4d4ff4f9fd7d768fbd28dd4487a2bdf2a813540bfb99907, + 0x173512477cbd6d2a69801143d1e7fce3a6ce79cfe3bc2a2ebeed24bb7e6672a4, + 0xcbd4277bd737219d8739e4e818cecfb664e369782e296a56290020877778329, + 0x14588264fd7d1fdd6d4ae3e372417fc1ebd7fa434fb945fadc55ee805b81d3e0, + 0x14acd0cc6605c0c722a1d399ad5433d5450614fc3231d5af742ec5926c35e77c, + 0x14320d8cb13dcc09670d6e93819b69d7e66504066f9095ed4ff25566d3a066a0, + 0x1b3e47537a897026a989e433fb7c4eba62144a10781548577de3f370434b6578, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x263d424c886417f9b6ac1de0e2c1bb2e32b870fe671b11e8219760d1ae4ad0b, + 0x1545d2c32ddd1e1e37103adeeb116e09275624e964f6efba626787ea0b1089d, + 0x287183d246f54265d2283b5bad5c4dc4ff3e5765025efb643ed93015c1de8a71, + 0xbc24a36833b64ccaa323f7622d1b9bedcc204bf19b7f83be4c62b8771a2ecee, + 0x2ac5f667d34cfc3cc80a3788402696009dce7f61ad3483b54de3246cfbdbe164, + 0x269ec95973b00d3f96125e7daca220f7ebd6bcb6f08df2d39301ba36c6ea4fb, + 0x1bda71d6e900e79196f126cddb042592ce1b6c0c0b92cd7d86bbb8613c2ee0ef, + 0x2dd51fa2045a74f10e86b8301210f5acf7bcfb7f40b8d984ed23a00e3268219e, + 0x81f8b7c05030b310ec5adfe7f6ee0efc0c44b6facb8701fb1aa3852aaa29db2, + 0x12cd7c92b7efc7b50810ad410dee511e137f3c995e4b8080e98902c5c862452f, + 0x222b991677686866f2059fb4d66bd16b9f3fff5b65df7c782747dc0bc7dfefb9, + 0x171f3e3c2562f120982c7dd903d7b74665f3e8d085e398dfc4d7f73a837c0ae9, + 0x1b7b4bd3c56e17518b850f06f15341f6e610254b420dbd4873030c0f309c3c72, + 0x16c84ba6c4962352d3073fbefa9034f5d7d1035773e84ea47a70b5cf615c7147, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x3928b7c1f5234a3ef4caf7d19b815c0ce64a8e8906f2dcac43a5ad59c24f14c, + 0x254ec8b72f52e44c83734b672b33b630e8931d1522f5b25c69273784b997bb46, + 0x17084c1eb0e0ce6e4baf294ce40d5b24ca44b06ce6551b90d9f0ef7a5caf4339, + 0xc57ca90acee1624f9315266c48c653bd44400b9424e172953f044338a77b27e, + 0x5c7aa15848b5250efecf2eefb8b6758751f0e69ed1ece426fe6f85666b6a5a7, + 0x15ed7d3733abe5c01bc9491e0816d11aec10b0dbfaa86fb47279d7a1448e20b6, + 0x2fcca33e780707db84102f6a8f1e9a652874845769918754db5d936fbdbdc5d5, + 0x2d23b90c995b3b2956fbdb6448195ed441e717a7895dc1e433815b9a8077d315, + 0x138d37c5ccdfefe044ee28894bb422f29e9f3860154ac2ddefdc900bd5b1e2ee, + 0x801587f5637bdf253298bdb8c8fa556bba51f40c6c4713d73e31a0f0e72ce6f, + 0x23cf40715c260876a24e43b5c314c2a1cce16e1f412ebcb0916f2fea18e5893d, + 0x2733d53df2ccff16c87efc741114e39ebbaeff9f12ba0376b931b402629c525c, + 0x23e801d5f635e9af022f077b1a43f877db7241055d3c71b771ffa75cf6eee4ad, + 0xd094fe93f2bf4cd4af61d10a7bfe2b145692cb94337ecbff9c91aa88ffcf890, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x93b40efe6c068bfde4c0c198171a60e496e1d834c28765c9afda090405e4a56, + 0x2305950150a0b9c2cae71061661c181c1a6b3d5c87980b91ca959450e5cad30a, + 0x2107ba64be5e7797def29bd72b72b8bf0b1428062ee8902aaa58f0676ed03aed, + 0xed4b91b00cb5bfa594ed5cb57d703424a8f2dd9daf5f54f6fff74e5cb0198d9, + 0x2c7df01a6a701115c6d07756e4e0359ff5191b58300db58aa98cdf3c985252d1, + 0x5d54d23f2d684e0c609aaf56ce816de9d5871924ba47ea7025885674f2bd411, + 0x248f367c66a05a93adc27d36acc9ecdaceac63385cc5389d01a8d7bed9388525, + 0xef717b148e289194b332dec7ed2ac824317e40beb40d74ac7bfddb23d2b3cc9, + 0x1559abe59817b0a24492729506cadb87e76fb54f9214ac87346f8013c3032b3, + 0x3bd5cd6f008061a1c0b2da097013ed88d28caa10de0036904ca03a4bcfade75, + 0x2ba9dabbe0f9fdc8efff7060142fe244cda2d8feffe907ff23cc61c08b619da8, + 0x139f0add5443dfbe642f4f60a57ab2502a2faeae1b6f12e1e5e09b1909050fbd, + 0x8965484ff559d1e6864e3abadb5d8dd402ad180059473b76e9bf827b7542463, + 0x240c21fb9f6cf7f02e733c6609f9773970098adc7e21b041f7486156b4f78e3c, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x151923a505f13bee4d368e9f471b79b499975b00aabef8962a861e7c858f2999, + 0x20f6374e3f28e5665b4288c722551c898eb41fd64f2878b47ffc9188812c1e3c, + 0x1f26fe05c0ecf99843cc88c28bf5c7bb0f744153fcb405c37d4c9e5c60dff349, + 0x101a3d68872e2a2174e1e73cc53c3034532ccbfc8645ba9bd17744a0a9b7c7ab, + 0x1015cbc312d356c0ce96131b59584b0794aa717ea120efc994512c1dfdeb4226, + 0x1a7b53d07ebf6963fe87166c26f5c041019f2210f4eb48383c9abe98a35c3c77, + 0x8fd8a0e2a1df82e44da83d916b870960f621aa62a5336b9cd0bb124bd30ed8, + 0x2c43cee66409ac215740bc8b1f684999679b5e240301f8030ad3fef640e05c51, + 0x2c29dbf22349ffb1635b0182ea7d3ba41c0748fe4bf06b44a401cd15eb0ef330, + 0x1c13b6b5651a6d7f3929ab0946246f7366f5addc9d360bc5ddce3599638a090c, + 0x10171b916d8a14075abfe7c468b01d239c7043a8f97df103701e716bf5a73f29, + 0xc57c3d6c68c9d2da843ac9b37adcf1c46a3e0eac7c42fda4dfe0ce5c799ae5d, + 0x131e361e5a8725d01e57c3c77bfa27d1f3329533b82ef4b01a1ab3ddad098856, + 0xfd9e076ff4f5dc71afbb2743c74f080a43853793f8f6d80a93f3cdd39012fa8, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x1573d9a6d17cf8af947c125da5f9f64516344307d15be028600d7fbbf3a99080, + 0x2b6645695f714c85742f738822c21a26c8906c1bc19f98e0c34cd1eb463da48a, + 0x2fec770ae63e759af86d0742b049eb76e81d45f6807728e66930d00cb9e1a404, + 0x24ed0296e066560c8dcb239e7e7f39ddcb1898e5836543f8e98aeccb6f6144fc, + 0x1ace8484c0d96d050ade091dbcf0c6cd9bef86884bbec6f8ee56ca5ff46b9325, + 0x110a7faed51892c73e54c654f2fa35e47fd2647d90d6e5e5a8afef6dda4da73d, + 0x1491aa7f36d89ac133fa9992990af2913b71196cb0d0c3511c34aa52af7d4fe4, + 0x20cb0c1cd1adeefa16498b4673c4596b37f34fdfe83a41065c1fab66c42f34b5, + 0x1ba292539d1568ec6a3e2615134dbb5134c73e6b14deca4c1b1a993f9441c830, + 0x21bbe75d7c858ac948623d0de8c35924f28f466ef62a7a473d6a1b4f592a007d, + 0x1c96f9fb4c6bc33d46892d8826bd0c2f24d7dbbf38d9dbecf09e77f69bd701f2, + 0x12d33ecdd6482928f8aac0987910bbc372ba2f107d6e2a25fee34e82f10be2d5, + 0x2c1b610ce987acbfcda328fd40b56c209b6a944bf5781e3a77d1af9fa30baa6f, + 0x2d77c3f420a31d59dc0cf83c4518721eca03f4c8913fac371b553b966cfea46e, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x1e081cb9e91ff3eb0d111f2be59f4ec3febd9407a69ecb0778d7355ed3048ced, + 0x2e0888b957e0fcfecca2a1157dd74cb01a1d8545d15ca25f937c554195da3c9d, + 0x14434487e62089ed7659870346fb4acabe0f9f9ead2a19657a88cac39f773bbe, + 0x9299821c0f470cc59fb688b6e57522d7f57aff1e589dc15722869ede760a9e1, + 0x1f1ce2cba9b4c9aad6bcaf3bf03f690e267acf7e335863a54e6987634279b9d2, + 0x199fab9479b7b342dfb6dfcd8adcdb5ef8cd9cacd897ff15a3445379d86fd826, + 0x2bcff4e8008af4e04f02c3373fb37247aa873ce7b7caa35030fba7360479a6d6, + 0x3b2b37e288090ff11cd831c00b9fbedf6d82e97540c5607b59a1a5ab4e305c2, + 0xd3c39eb880cde63d9a4fec82a68313c912a25d4638a1f6177adf9d841d3d84, + 0x121da38157e113a3b3e4060acab7e1b40b36ce2e2a677e5bef5abebd6d4c94b1, + 0x1a5923736c007cdd31311b26d560615fadc7e01e86240033e1f2465e93df234a, + 0x90f568d806c5c4b1b5e61542ba122cf1f5d4aed3966c26508d824c3228e97a0, + 0x20d2b7987c326a68610ba3cecd0b4dc54c90390df012b7d96170d9693c29cd01, + 0x3020b14b8e1529cdd9289680c5ad441627632cab08b206759d28e76a0fbfe97, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x1aed16276f89ca766d4502fe21ccce046a63cd2f7d44a0aa8770771e2f012eee, + 0x29a61b71b5a33237899eca4e7f4e40d008c97a32bbeb0c7c09d8f24d6ca574c6, + 0x301dabbfd4bbca914d16943cbbfc3ebf006988c86b054d6b613f07ae1d092afc, + 0x2a3c6d1263e470cca3ae533107339b8dfed7700c910039b2b45b2bc67575f9f4, + 0x20ff2a6b8212735ccb82ff59798862854e3244244cb0566f5d3d59e341aa36d2, + 0x2e5dab75ff69d4a42e745287c98107ca9c3e423dc6f41096c039eb9724b8252, + 0x2f0f8690c7cd4737e913653ebd84f51d5f727bb6ec729c78c42972aa34d6e4cd, + 0x2be6c4a5efe483fe0a737eb77df7815a6599f091f021131ef37fd192305c4c53, + 0x2f18439786b79df3460f437b9fed74ffa5d899e2fc7774ac78afd1c75d7d98b, + 0x257eb2e8a7939be6bfc59d3fc6fba75da35049a36277c37513de03f6cae91538, + 0x12f8298c4a68070f15caaf500879659d02c3aa9b771106241917cb6638608133, + 0x22aa263182f19c8abe727e87a2291fdd6af7014f5ee5ac6c198a108dcf02f539, + 0x14cee2715a061bc708337507b88d099267ffd7d71962eba1bf7d2a117106b111, + 0xbea09b03b5e03d2565e9b4f7c43a91ed8137de6dfa41f70ec7b24d58eb7b1b4, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x1c01114013e2d2cc0f452ef7ef2b20226cc69e57b028464e95228e951d1cd855, + 0x25c7e0412d2072062684e96b656c4410dd5d77f644c64b1b1c84ad5e882cde60, + 0x1231e9e375c85c424c5fac79600e91904f849b8fb71c7ab4c37a7ae58c17d5e0, + 0x7a0a63d6b544338243ae9c846b542b213c67256036a719a44a451b8e621d846, + 0x2894d383becca5a477263e188d30dd81d7a41e56ef5c85c10d97a309b8daccfe, + 0x101c0e6bc868c92f99608d9839fb6263313c2ae6efe4d9efc642d577577066b3, + 0x1d2a84f7475ba65bf319106ab571e734611e0aa742df49e03c98814c215582f1, + 0x2d2913e61d8423d557920d0a4ce230a35e6f45df0092e1af389d420902295e2b, + 0x1eed01941020a3099668dfa81b2a57c1639ea6c61ffd2cfce89f696e78023df, + 0x25417306ef421d8d0a06515c241b62dba2f16368b56c0a09f876850c4d008621, + 0xbd0953d640552207b0df37f4ab00cfee2f4585286e008d53eb0124464fd5506, + 0x29beb31dd4af45a599dbda7e3014c88b4b0173b369e9674313022ec3c39d1875, + 0x25305ba821d4ecca68275fbdfe54f068a8e3b5435bcef6b7bc4a8da67f912917, + 0x1bfec9a5d8a1c5ed86c4e7fdbb6b96e302602d14f55488b1b98644e612208088, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x177f31701c5cd86c2135c582fa22d1fa1005ad148e125c80046a52f99a278a07, + 0x84b44037ca846dc363a64737ed25eae81e47527aad42c8b860d2f167fc86299, + 0x5db3b44bdbc42b1b4f26c99fe1a2cf645f28e6ce71253d92a406dd86a607bcf, + 0x1878ea943321eb7644a12615ea82860ffad4e28428239902a7f4fb2fd33464bf, + 0x124df4728f64270968bda5aef3424393b51e84bcc672db75983ccca6e6efb12d, + 0x23650e1dad9d21e3b5a1140b178f9d57e838a0938bdc88ad7c23256b09624fe3, + 0x201a52e3c2b36532a496eb42060c6150fd7dc3ac2db72df850c3a2e3f254654b, + 0x1f4978ca0763083af095848af1757750ea81d782d96385665df0b60121ede60, + 0xb98fdbb00789a5b9590ef157c1907a3e9bd3cb67887bba7a251b58cd45867bc, + 0xa497dff0328c9b639bfb1f441586b3db11c09773623bdbc12c40ce544d90504, + 0xeb016dd39c878c0b09b6c6e86c6527f9cbdf0992e71d929855f0d4525775008, + 0x18efdc04259cca1130aedc7167097d26eea98c38db92d699f7140d3148b782a1, + 0x126f37ef258caacf14662c6e1f6df9dc4fc6d1792a17be1af28439b6b7c98de2, + 0x288928203b020d9e6a57ee9e15ac29d64e2777ee080493070517c1a3338cbbf9, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x296ea4e3760ee3d1cbfabf9cb73a506d7cd78b9a28ea959e977d056cb07185dc, + 0x9a7542033713ab98cae7b350528046a818dc1bc4daf2c2119d38abb2e0877a3, + 0x3034706ae9245292d2aef241b738bd3b0b211757e4c2e0137e2c65c1e3c67d17, + 0x104ca211af2cb44baee1525e9c4887c1ca96f2d147148d6f8d7083ef975b4fd7, + 0x1b523f8867ec145c19ff50d4bdb5606c20ff01ab3bce0c0768fc28a4a3d595a6, + 0xd5edeaf84c1e75e0d4f670c09dfaa070db33640e744336c60b18d1b9b90496a, + 0x5124b407c8fb40067ff8163af388ac99b168031ecc22aa7423e756fef6c962c, + 0x8ca29ea50b36354afce9507079a06f06753a3e21362599c3b72d542050c49dc, + 0x4c3626ce2dbc4d64f6ab695c59f8f51f383a183e5033700af83f83c3189c1e9, + 0x14bf66fe46f1f1180c24f16aeb7dec3f4ad00c1b6e9988c5642b549609b37573, + 0x67b2bfe7bce2dfbfeb90eeedba00121ed2622c38d4044ea6de739dfd5f75d16, + 0x9287eb9fb34d9ff43ebf373466427795393823f8d70c88ea76dbd7ac989bd6d, + 0x16ff59f0d679ae8e74aeafccd0714d966c4fe1936aa0c7fbaf8828168850524b, + 0x2051d8ce6c5dcebc2d7ffe11130757bcf7cd14283103d3fde53e7f7a880a8519, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x1d360ee3116f0744286da43406049bd1b821cfa4c3e823752c00f0451c942254, + 0x1f6ccdc7743ba72305a0491a306aacf4e3b036b0f0602daa88feb8fd8cc62cac, + 0xf8507197161fa267d0c68cd381d423f3880ca56ebd0d7ecec6ae88fa68d7a2f, + 0x18b4a57860ae5f6b5ac2d4f8c924b2bb3872dca3db783bae02da366fc84b7a14, + 0xaf716e6f1286cfdfdd93f1417a064cd76b1a7e2347d61d9b1821eb8a4ddeebc, + 0x14f128af47080db5d122ae1a8bae27475c1933fe73cfe2a80d89380b2147915e, + 0x1f2f97cd81cfeaf9ab80320e688f2af45c9dfc4a74f7227c7205fb05697ce2f2, + 0x7a985fca61c3346a08e8fc31167636507b13885850b9cbc64798de9b76cc57a, + 0x280e7d98a95b9e3ebce1a4d8325d69f42ae8c7f7325a04bfdfcd531a70d0816b, + 0x1cce1cb692b8c6c02c7b6a2e20d1fc36f031bcc44ff6bff0c4abb5b1c743af5, + 0x2ac9fd902f4b6bc5f917228507b403859cb67077ec2beae84ca18677858e5686, + 0x1b69cbf6f6bcec50e71597c63a62a8253a63412612ce4e79b262753831b970e, + 0x981ecb674c4f9996a0f8f019d64520c9d933ad0c6375f17a643430355113cac, + 0x14faa8f8184c8aca46363826f864877722020035970dbf1090d4d3911db9a9eb, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x1a6906fda19b094b2bd4def4b25eaf4d799cf919d0e1483d9380180064116cf1, + 0x1ab6dc94517f1a235d1107902b6c034b5535cfbe94ca9096bf72330be04b179e, + 0x15669b5e4dcd66cf29b6c06a9308f8672f88d069e7e8eac7cb11808b82913038, + 0x132f02aebee7db7f69fdb68ca8fbd57f387664e6420fe20060941344fe5b63fc, + 0x46f52fecf6e77a95b31226d34954f28b9d0e2e8008de5b3d11c274d7e44fe1b, + 0x2b69ede24d4e37f1a8c1d58edf35d0a7f9a0716c3f709cfe5cfa6f069fc7dcd6, + 0xdc2cca8f0d3eff4d287722ba1c50b9062230d5b6c748aa4d7003385ec5424b2, + 0xd1b03d009a6a0295cdbc9f23ef32bc2933f30a8baf2360203ab064b69388339, + 0x1a1972438cf29f99b6802d9a1b24efc501739c6d7278a5f30b1667c2b7bfc5d6, + 0x203dd92f30579361e8ecfe9e084cb41cbaf7b93fad6d7f7abc9d0f73fba44075, + 0x9d6f86adffae5e4fa6d5dfa644e97a5b382a1c7e90514bea8ecd1da42773380, + 0x12d40572e1dbe47334a16c73922e7c4da9675a76d5fe099027ba003cee8f2b8e, + 0xc3c34e73158918b72653147d1e3d059b256c1657fe50430a778e63f6140550e, + 0x6973060f725dfae61acbcf3171f17ae957cd862e86f9fc6a47fc7ace24a8867, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x1b3a5512b18428893b48c2fe915756e7cc7aeaa8ca36c2eff6dab81568264de1, + 0x2ab9670c18ff8edc1c84c1ab36ca686990f07e16b567bf9642165edaa5a6346e, + 0x10660d5082b8fcb7f5f4eb051f926e99a5fedbd706fe191bb18c26d34be30763, + 0x1aecba1af9b70281bc2722c0d82a097305c208a383c68330a1633fe3b59c94a7, + 0xd23a06e79761902a6ef30749c86998c3d20bc827cfbe2f22bba0f484dcc04d7, + 0x282b6bffb062fbebaa4772f808780b00b77da1c52fa648bd74ae0ad49fc62d9f, + 0x27d48b15b151378a1e738977abc4ce2d8bcab816dc32797ca060ee009ac74444, + 0x2552efb9ecebe9e17a82574887359facf5cd61ab2ea64bcd60c50e053124376d, + 0x2e505630db4463f1d226d0e1fcc5be4ce4577e3911bd3262317a4fb32d7f8ea7, + 0x1d85ef93d9f0524c0d579400f62d8fa7f6235c8631bad07509d79e20db614ad7, + 0x24bac63bf16607fb32c48e942d0cbec8b7fb18554f342d6973a6fe3a309c6248, + 0x2403a33705855d9d4456779033eeb1938e9c9bcedc4f1b28f90c7fce3e4f39dc, + 0xe661908904f5e530a16e3c1184aacd43ecbbfaefe6b55899026b9fc9940db1b, + 0xee6336e66fcdb3a64d86b979baab0bd235291bdfb213ed532aefa0a72e5c3a8, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0xbc63f41651e844c66007421b547d69d694573b1343b8583aadeb8f39b9c5af7, + 0xe5cdb3465f12743f71ef5f504e6a5927eb824266a82bd02df035efe08e921f0, + 0x1a0af69734aab2e4304d15e7a69b2e64956b4214c330d935647b2b127f6afd94, + 0x2144915f6e6f829e7179c5c005ffe6c9ee3a796e32de5577225696a77e7c381d, + 0x24b6274d2f945bda6058c3366b6d91e33740897c6e6f133304487b63bf0ba435, + 0x10efc44751f6ba491452b84a92594336c6ff4012098f9fe85420242cdf082baf, + 0x36ebc6a6fcb98eed5d0dcf87239433879d99acf6fbdc570510ed6c825055dea, + 0x17a1b2378fea94d0b1a96ea700505bb45c4318c9b911949a7107414f636a91cc, + 0x2e455a7518e54ec2e0fdcdd2821e488877c594f854131e6a9aee732db95666d6, + 0x1e7397644ed4f4cbb8e931b0db4904f29102b50a3ca839c43ac4c0c399c9a8ae, + 0xdf88ef1f1a67a39feb725316726c97b084981300a496619a38d3fefb6d362f, + 0x24e11fc9c4c7763829d801dd3a205359bb3792da2ef8b2741ab3b2c54acec8ad, + 0x4920b3e800f77d7cc99d8ee4d0141a45d27929e6e4a7d7bc4193ae25ae82033, + 0x20ab7b6abd43a88f684217ef931c13cc11908564c8603e01993b0e277ab29f8e, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x10f8a59f8273eacdb9154a734653e4ff7fce0da404f36b2fd001b3f077ba68b0, + 0x1652153e375ecd237c21acdc3f96d39088fd656dff8d66f867de878470fb391f, + 0x12a4756111ec068e3b9c4a1427b09f9a313e018d831f7ae5efe9f3f6c61c13f4, + 0x11243b19f113241477e4790f89b8ea79666796ebaa31cc2ce3700ff51ed3cbf0, + 0x93d6ab40a9a4a3bd74f097120654c82fecfbefd1067f73ba5aaf031b1c18c35, + 0x2f26911b23466c23bdffbb8aba815752b6d0bde3d12088becad0b08fd1dc4976, + 0x1a03dabe66a3037832d93a1c3c33574c5b28787fa643ec5149830f81ecc92bda, + 0x223b10c2c547e1a2ba41fb918bb5ab602a9ff21a19c37c157ffaebc95bac4870, + 0x1f271876f17d7ccebb222aa3da4cc09407aab4dfdd453f1ddcf248631eec1088, + 0x1adb58add70e22de5100c3f187057e930c9d122e128c3d1159874c304dcc1090, + 0x27b3f7ea1e34373d8183be5e462f0ec51d5d0c8bf049a2b48d30ca821b368afc, + 0x1e5ab69a6f006ef5ff38e49fc34b58d101ae90bacc8a638c353a636ac6e0cc6, + 0x14ebbd0ad1f23e2c7af18b8c43a41e86492189f38299783c3edf8e9fa8a2073f, + 0x939c8f74cf317552b74f7ad2ad5d0accf3e02ac3b9e67a91964539bcf09295c, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x1a55cdf6625cb645cd6090c3f525f6e297864a501041dcbcdb37b6f15af7e36a, + 0x27af5f96cbc32f217ffe217d4d478a315f2095286d6589ae3510e847a7741009, + 0x2210a4f1e6607e23b90a45345ccc56984bc8a6256c661f04292b78523bdcc7e8, + 0x21f9fb0fc7ea61cd6d0ff2d35785d6e7d15c7a9cda7cbd3e39c44166f4b175b4, + 0x1ee5d14567c941c70d07adfb6dd50467eb0668b7bdd1fce1879bdceeb059f94f, + 0x246ed97e4eadebe50c8a0afdebd6598030f27e87b89f0bf73090da4d95f12c63, + 0x16f44dd900dd9f274617e2d614733244838171bf0c89ac30256eeabd5c8ee945, + 0x1e45e42c3dcea63b20518075c16745af5e20536983b16f632d3c15c91b3d7d16, + 0x19fac5ce0028674ce8bb40058162e50f9f9f8b8905540fb7722930cbb20112a1, + 0x1190997dcdb0f5772ca3de8b876a4be62f8ee0b39d6c233c95848d073a8ed6a0, + 0x96c7db7d0085737934ded26317191715fa6c789de3df7e68f00e8af528530f3, + 0x1c21d771cd0338f0c0c00ff71e4af2c1d7db81922ced098fe6989afe7d1e4d19, + 0x2dd43d3c40b768f5625758dc35668efb3ba747347d5ffc980ec0b0cbab709c8b, + 0x1030059f96d75e04bc5f81b89fb7b5b0fff0361adf04c4f0cede89630d2f037a, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x1635019295b65b0190fdd718927dafe4c0c965772665800cfd539d559f0900a9, + 0x2c17c890b715b3bbec14cfc8f060ea84d7c12df2e51cc1e8a6e987f45c01674a, + 0xc8ffea42dd7b206033427a512377d3054fe4f8f86357aac58032fa2dfe7c7ed, + 0x12fa55dfd670309af2d98c8de77c302a5ee4ca3eb08b90f27230f05ff4287c7f, + 0x9009662a5a28a89ae9d6da9b3981767d2cced18677e42773fd4334297d6efa9, + 0x25caebb5501e77f1731a54be0e06f8c005176127f3556ddcbe24fb5804e08206, + 0x195e006734786e591acd92fd233f784503f3fdb5db18299592de56d770028a9, + 0x47885b986f4d10ab44463042a0bfc3adfa3bb9b553bac96ed40f616291bce26, + 0x930f3aa1c5410395f9b17a20a1753b721a0291fda6f32bee8aaa6ede298d720, + 0x24af63803104e8318c3e7a41cf8027ad36a631ea11d56552bedb5f00239f902a, + 0x27c63e725d17d9a44f47fc73f02d7bb2150ba0f6031f004e600ce008440aef5, + 0x157270a74e4ecc8bb6f976c5bdce70912cf64fe9c8816d62d42b0eacd9514dab, + 0x2190e7e822c0508c71e3ab7134fd89a40775be99a1b38c2767f6313835eef8b0, + 0x234f3cd5e0cf731da507c91ae18d28061082ae9aa580746149d1a48f6a8db2a6, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x1433fc6bf42a2541e40c104a24d5cb9d462fb71bf094bd998c85933874eee2f3, + 0x10a8445d83f3b7ec65128083a39f5c759b9f52bb8ce5c024be8e2d300e0cc652, + 0x1a1d8481d39a772911f9bcee025d79049764dceb488a8275f03a39870fb4c909, + 0x82dea281aa11435a7429463b3fadaa3bc680aaf49f02ee5c40d110f63731a47, + 0x13556947fd0714aed251e0fcf91cd0e8d0fef2dac3db4ff9f3b6c5365ee9ba2d, + 0x29508794226e7cb06bc170032d377edc210dabebd3a254ecd4df794d65f8cf47, + 0x3cf4fecc54b529b247e48048a963709b22630ce719ac8a9e9d1f8e74b73e702, + 0x16cc17305b3d333276a9cb43d51089ead04dc2f1e197fff0012d4c7c4db5829a, + 0xc36f031884453fce7824bd724f25e8fe71d3e640baedd9398a719d8f01c560a, + 0x50ff40107aafa9a2e30ea1a24b64129fe55da84a294ca8d0afcb9956ab09797, + 0x28b18039884a6d69dafea66b723072e0c55b1fdab6b247e801d6cdd52c7f81b9, + 0xbe18fb2749573c5b7b7534ef3cb0ad5651a801b3c6bb875fdf30cf8b155d8e6, + 0x2ed3ba243fb561e308a7da234e581898983172e58ce98d9a94aee5b6de925b5f, + 0x248eb1ee129d515abdd9f65a6fa7711b708374187faa61acbbb6d21b2e26dc7c, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x89fb8b0837e0b7c9598c3bb5efc40e62ff31e66ea4f5e51b9330a20f9d5e553, + 0x2c17324ec8d80ef220016641f18bb8ef3ad0d18e4de8dec2ca81215591dae7be, + 0x23c089339439d665507c0e956ab3208b27d643526045f4afcbe6364c44bf1093, + 0x32af6e9b670edec4744d9be16c2fb05dffd7742b035c5d5e34589f5cae382e4, + 0x13cb85e74878132b6a20784e3bf61df1818c4d6141651d1dad1efacd58774174, + 0x2db07c1bff2eeec8c5b9dbae586d6a9e7dff129340512ee92c27fe3acba78c1b, + 0x9829878aad19da18247b6ee680b5d3f8d94c0b046c24fa5641cc07813031830, + 0x1eb00d50e3b0c3ecda0b569d961583ba3ba49a3fdf62eab4137ab4ecd16515e7, + 0x1c92d7b2ab89c954d36a5da4466d4ce8fe3476cab10bc76716e6fa1469d3c881, + 0x29412e4f79957b5aa484f896baa95977808d2ea76cd61e0be6e705aa9c31c419, + 0xba6668da5d5bde10cdc9aeda5a050d864ee2f72f84ca600a303aa2f380cfef2, + 0xe3041c5fe0dabf954e6d9ab5519e5389cb3ed02301755f24be4c400844a019a, + 0x46f80bc5455aac3228986ff1910d988a8608cc8eea186ab821e5b8cb88a8a9d, + 0x886037252df484b3b2e909f79ef69e24c2b0f0a9b912d666cf624b888d7958e, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x1e5db2e40041ad9d844fc08e4932c2a893f14e107a68534c2f70fed480beedbf, + 0x2d0e5945cf1ff11b864b86659e60292c1d76e29a88d35e2d25007c3aff574837, + 0x5eda1c9de06b29e901b43f4dbeef95746bade9533d07a22b08ee2cf948bf827, + 0x92156bc60919beb0e2c262d9b4ca9c888221b1236839a25a9457b4d475754a9, + 0x20346a64ef27480102685c39833600f03276e5e4094eba2077457246bb5b0920, + 0x10807d847901c2b7ae90b281bf84af1645abbcfb22fec7626418273a5c4061d8, + 0x1a02e561e4e6c7e5c33b9eed477176c2927cd2331f07d9eadd6ec80d2d77c3cf, + 0x1a20365486ae8bbffe437fff696c78cb344622ae0d25c8b6b1b1deb62fd03bb7, + 0x10f6bc198813943da2300d26f081cabc8dafd92a953077575e8e2ae4b5b60fb3, + 0x1d7d5aaea8bfae19980b3c529fab08e7187cd71a706f39115ad1cf0b7f57f556, + 0x1df1dd45ad494f1a872a88240c1a9ac86c18265890d36f5b57f84a6db388b35c, + 0x1c29d88c5a7e44b8511c878720f8edbd2ec09956d2a47125ad08cd791a72a786, + 0x2aee9b55a2f615b6fbffcce84c652a3f41351fcda1b830ff3beafb075d0472b4, + 0x1c9ca1baa0f3d242d39a3ab72580877c176e28a5c887c004279a59b0bcf1e66f, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x1e2b6b0bf7b3b4ed5126b8e8be6b6b070efc28d062f8914ba1b5fc68ed14ee06, + 0x2b00a882fcafe8d43e7da424366a73da0b7cab19478446f56da7a29bbf24abd5, + 0x441070dc965c1abb15cc4dcd6668cfa56f1122903318ebadbe52af6495c4e9e, + 0x1804350e3abaa426cf301eb0241d2f1726387efbf0df6f0c303cd0f983997d57, + 0x1eafed7d64d1deab8a1b3ef80d833b3aae94efc9f89286a55789c6b87d637b1f, + 0xc08b894acdae0abb3e1c1f653a150d96e0666a92e8a6f732d8b438e2ff7e631, + 0x2317408517ec88bd778bae7b26efbba777aa1b4460c3af71cac88aa1d4d2d7b, + 0x17dccbe73f5a7b036e83f6233c651c883a7957861eaefbb385468785b5592d3b, + 0xa9ad70b9945cdfa736dbac21e4b4426515ed32fdf0476217415ca4edcdec1f, + 0x12b21302572045aa13728b65b9e6da2dd6a00b49c9acf7418d03431b663ec316, + 0x2f73e6061be74d0dbe147fc3de191cf54657e3516a60a6da650dca53c6d4b8, + 0xb907e76289b21473c0e6491744411e520896aa614d955fa3b7e73d25d4f560e, + 0x23c6f78eb1f358e4f34d7a1d58577cd8af362c8d7a650c9c70b7cef28c8b77b0, + 0x1fe537054dffac7ef4fff98a49f253a17562d32eeb1903ff3172e8089f88a5c, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x22420a556a4009accb54c2b2266ba65776d5455a7944ece37405f2bbb849e352, + 0x1ad1968f9921575a75470f22eb1f2e2e3a6b973c58e22ff30c731f97064bd055, + 0x2d709e99d4fc4d59e9dab4baad17bbd75d2331e8a448c2595c835e96ece5930b, + 0xe1df1d829c920e063cdff32342f223e7b4851df78ffcba180df460988e8570a, + 0x23c4fbbe1b0de3e8b57a6137c331e3b284504bbb9f20fbe9dc2b304194ccb264, + 0x2ecbb2ad59823898278473d8a768598a22d2be7922c292a964c953080ad8a690, + 0x5dba95d04fff06245d0f4ced407a98571bb522547bfbba6c61731884c4d4e30, + 0x1b6b4761d189d1e2db04e13f1702f4a15315e1b4061312633fbd2f7d9c943b01, + 0x1ee6c5f07a003e7f7cf05ca63ec2c5cb85f0137f55e1e62c81c9b4a40d9bdc29, + 0x802b4548da3f90ea8a49c26cf583724835d8add489da81917c17ff7686c97e0, + 0x1a3089854e45defe9e953808e58f14cd0f0edb9d65302732ce5450c92ca79885, + 0x2133779fb03912c1f1db22b59f3a8e96d396173ce7c5abee98f05119b914b700, + 0x18dcc23fdade276e5c1ba4f96a47cba57ccbcd1102fb8d063723523e2d819b39, + 0x2a1b87020f3b905940f757cee7f0b459217ea429b77a9ed2404cf9655763e105, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x47bbdc4836a3ffd940aeb2c8608a75fb37d4e0ed1929fa893124a87046333f, + 0x2fe188cebef3df8090f27fd40d4e1f557b2a13aafcdbd36d53cdb99ec48fa13e, + 0x1eefea2f42ed57d18b8bf7591ddfd0f54a4e7434646e84e7c79a15d2f879aaac, + 0x1394c009ab5cc43d8ea089286a43d30c904d227e9a151549bbb7f4d0cf930aa2, + 0x2a0bb922c5a36f42819d00bec63da58d50b6dd46ff20d2a3b29c1c2e1e0ff837, + 0x270b2526008fda515788b4e38ea86c9c9dc4d650ffce9638f91b85453deded4d, + 0x2ba1e2d2ebe659e779301d63ecde988d55432d5bd7f8a4f76a03e20fa31fddd7, + 0xf56832b7f06a8a3a1c287b8497ae10dc05f216917450813f21ffda4c0effad0, + 0x1959a0963b974ace1dbef8ddb09c9ccff9ecbf4dfa10c2c174d42d523098cfdc, + 0x148da04f0aeb03cea78009e2d1192865f5b99d630681b71ce71f9ec05ed55b69, + 0x51a40af416f4fb5f9f0f51faee0ae6be210f9b93c4ead16f2c9a96a855c41ac, + 0x20973f1fab9890ed48723af234150d1ecca066629dc1d07031c6cab5e60a3efe, + 0x2a28a24ef1bdd75a7e501a4f035c1b431f4d7554df5facd800ecd3f024ec8152, + 0x1d2ee4e18fa1575fb3ff723b3f9ad35cb0997b436f85746c6857882068333148, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x2629999fb52514197199686aa4c0b0961d8aa48404241177e131bc2396fda732, + 0x1f99369d70a63bad0b76652ea69f388fa92ba1658836fa3aed366744ececdec0, + 0x4511f41649be85e455ce74338ebb425c895f88540244a554c9947bce88e6edc, + 0xb696f753615462876b9efe2ee1fed79c49becdcfa3a2d0d04a29051334ca110, + 0x214f09b5557846662636de4679dcd965611c3d78e8d50a2cb0589c3ec90c9924, + 0xbf5835b4c0bc4b13a3dbe0fbd68fabd6ea6749b70450547f0c2e3b658c01301, + 0xc48c640e88a6442ae5ac574221d7f10eb2e67ca30fb0bf169cde004f4ded504, + 0x1a5935756b57bfe02a3efedbae26e5a13200bee0994712005589ddfc1ab5b8c, + 0x386ba86a06566ae39b56cda79580aed0647b9636896a47a7e0e9aa9919d9c02, + 0xf00775e400bdc3e8685b204f07964e28163ecb3c63165d46c3f463e7baffe8, + 0x1a662d8ba07d915cf7504cdbc01ec2a676ed76347ddd4e07f370e249a7b8ea5c, + 0x1f06133283ad793171f99a4e8cbd2cfb465d9d6af9ffb4592d90293421750faa, + 0xf83059507c852c9750d5280c440af49da9bb328ee63d1daceefd0becb214fda, + 0x14d1ebfbc4c284f016134d6ab56daddb4e647593caa1324ecb302a77ef0b3bd1, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x5d4c4270c1e940348df545abf1e79bf647658d2e79eacd5dcbf97d68d05f3ec, + 0x275db6ddf370d2f7e21020dfc1106254f1c60fbb7de07efeec3d6722b04bc54e, + 0xd8e04364c5a23a60f46b4548459c7e7c002b73efa630bd165ab3b6a87f96489, + 0x17f1de99ff5b961493bef67f162e464c42481e448122fa5baecec8cae0b2192, + 0x23da50aaa25b76f0dad9f50db23d12f64a4819f547027b6bf52768799362e83d, + 0x6d4ab87edb0fa0ea037a4f5ea1583c4198129f067829169c06e7440f354499, + 0x18ff576eac16541cea173c61aeb541e0761cddbefb4a90f144818947d16013aa, + 0x1408d644973d6502f93fdd2f69a71093a9fe50d7f8061acb474a0a14ba304f44, + 0x29e8f556928e09634fd0b950e5bf4e90470d45e3c16b13864d598c555e57b1e6, + 0x1637adc0e2bc513402f3a8b5314017d7ae192c809c41f3348226dd50ed82542e, + 0x73235d0a9e96cf86e0976953988a3d9a260ceb59ba7633a40cbd7fede78a51a, + 0x6dd5e9ba875bfe6f6596ba3cf35ec2342bd03422f134ab99ab7dddb9778b830, + 0x18f491c6c3b12acd06a117563f067440ac753ec468a5df0c123498fbdf0f143d, + 0x2d09fae126d15952c2b91d311932c93cff8cda2b44ce74c5d1d6dd132f4cf0bc, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x1022b57f4ec134a8f7e574fb62093d415b876af638133d32d366a9b1adf620f0, + 0x14d51a25fd8d1dc5c7720bb793a275d83d812983965bc9b05d306794cf1dcdf3, + 0x2c6a7b31575f327009eed05f25f94a4f173a544a0d8fac673474177b3b9a1413, + 0x304d2a4701c43333827db71975d9c2c4e675056a2ea1e9b72a0eaf127b25efb0, + 0x11f7c6c76441a67bc5946687a40a28a6cdcbd0ade84c389115b744115c627fb0, + 0x9a1baacd8b557f09fc35e6434ecfe9182a04537171ee1d2bd603f5378206804, + 0x8926a69b2d5a4200ee36f786770139781eb60a7d272d31406b75104efcbd3a1, + 0x21135de3337256600fabf590e04c29c5e0875991a67d17eed5f5131c567bf4d8, + 0x14b248fabdbbed0fd66c899e0a801bbbef4e1afc9bd0abfef471884bfa160841, + 0x86e20d28f53332b9e09c5af815694ff83f10f379937f09105e98529fd4b4b01, + 0x1271f30b82cb798656e4465c44a9ff204325f5fd2d2e204f2b5673f78fefa4b7, + 0x2224a8d0963f1ac4f3e85695e2692e386a3c1492aa58127086e1385b9c2cde80, + 0xfae50434b1bf26f790caa16ef2562cad5d238130522db3a97c1893b0c81ffc3, + 0x3f2a142e4084164ecfa6300a4be6abefbe155f5ad84a684f761e75275926052, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x274d4d833700eebb5cf7c8f4fb81c174a108932a0e987d2889d9b93a95d187f4, + 0xe9bb8c9f9306791b77582a16c53947e12e0dfed0c2adc1ed2116dd451598821, + 0x26a098e91130e0d10603be0507dd975431923b338b6c0a3890fbb815af28f7b, + 0x26d653ce08eff8f162c1033b52ea7e67ba0f6a8036bc64d556a75817579698a0, + 0xa8ef549b90bbf3af6d9fb4db8656b7de9cf14212989422778c52691a0ca83f9, + 0xac39f4fce06a27f59b5f434e7ae2808da542d1cd5fd18bb4b90e4d15598676e, + 0x204aed1de3b314f39afe27b3b1bd589a851183aed39cb3004e67deca646266ba, + 0x158cb2e73c4aec4c054f1759e9f3293b62ae5fdf18f69be4f6ce1c65cc1c155c, + 0x13040aca2fbe7c001c14ad386c756ba465796b9ca677735d95861600b3ce6b53, + 0x2674a9a8dffb96d38295f6edd1c5c008e9320ac1e99672b9d05289ce45fc673a, + 0x57be234d78a86ab47e3691b67a63266519bb62985701f2072494d6343322a41, + 0x12bbfac6aed9fbbd81254753e8bf4bd4c562e4af62548e577ebc973f77d9af77, + 0x103b3e26bbc4767aeb96deacd771b5b694b4d57339e351c10507f61bf55d915, + 0x5f918dc84cbd6a0a32a65b188e3f1c6e3412b76230fc7f6e5b17612c1abe8b9, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x28e6b736e2337dc438ee643098ef22b69c869252509d605d6799ceacd28d6cf0, + 0x17326264714761dfead5cf52058e2559b4c57d30fa68b4162ab616d4ddf70448, + 0x26d0b9ad617c87b600e3b27cb797f4b0ded965500a6548b554d2445f49cb614, + 0x1a57505d738aff598d51ba2c25a4ed8b41f9479332bf95c4a289537dd22a366e, + 0xbc9463f62daa20f0f245379c9b36c48c26b8f2e7d393e29a3ab5e30539764fb, + 0xd2de2c5e221a927d1e90617e8be308d83a905bad2c5a5b29ffa06186bd62c96, + 0x2acfa6917c256caecdfc13513b404367163017f92c68314e4cee7c465c016bef, + 0x2300a55d94c34ecc47785790d4cebb3ee14f43f36ed26b8a69b1e7641f5703dd, + 0x1b18386cd94edcc53b5fc04a4f6463badb0b6f1908c53765eb2953449d3bc3db, + 0x168523fcd8de4e51f21ffaeb5194c5882350e2926f76d76b4908d3e0932b5ea, + 0x230836236981243f35eca0e25d7c73c4aad7b8b0375ebc53200c5a169d1ba5b8, + 0x1644931eb3e15ac27e176ba4a0efa23a8cd2cd0a495e0ff1459ba562c39f74a4, + 0xbdba47f648104678694d1dc3e485f87821387d63b40b643681f6920ee153dae, + 0x2934ee754f94b9cda4b4193c2da7abf8854286bd37ce1d10faff250466663729, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x15bca736827fe042d7bd64f77821bfb98ac7765effc787fda6427a9c1a3d7817, + 0x1702aabda38575c6034b350e4b88a2a6ef6a5bccaf04bc9f99321753dc12b1f9, + 0xfc69497af71268ae3b232540f8c9e5b16fe351e779646f5cf34bf7d41893078, + 0x13cf63991c3ea2c423f0069eef61d41d30b7a6d907a6cc3f723b241f676131ac, + 0x8212316344803402735c663b23ffd17261728f9fbd3d91b2f86e227a34cf2b9, + 0x1d76ef5ad83cca5d452debe5dd11a2a756924c26b546782299e7c9b9e7f6802c, + 0xff4763e1cbc755ebb7308094877f3ceb4cb0d393e00545eca169da0f82c6c1b, + 0x2ee17d2391f5e2ada6745b0a56c5b2915abb69437e28975e466d218efe4346f2, + 0xcdfcd1cf5fb6f404d7686731a9a326dcbab662736555ebe2964d81d7929c86, + 0xdfa35c85f23318fa0188cd8ccf7a174e89b324b94484e9f1efed3be25eee2ba, + 0x3020e7189aa0392850f96adb46c8476a9d62951093438a948858a8bdc3400b8b, + 0xf7d3dc3a1e33f5b68e2b84d9da05e7163b40e8724c46befb4030fa88768e536, + 0x2331b3e5f7f1277ecb6ef3e862f53047a7cfbfbcd001124d96437a7559e4d954, + 0x205334d2a003f29e2eba4a0f115f491e159af79d1871614252a23ec2c81ee321, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x5c88b264202385a48b939b006669c1866bcff2ce9be97fac1e2b7fb13ebd8ce, + 0x34938d22d020660d0a009ac6a5ed48bb0097cde47bbc0d8ce942fb31c464584, + 0x22162ccea7bdf2b786c635b0bc7132a04f76645b467df815cc521e977cc4f80a, + 0x27b9ec9c27c0f868a21ff55cf455c2b3a392dd5e57ce6870b90c217ed051b792, + 0x1d40a01732b59bc72804d5be3dba2fd2be8208fc2f1ffb9a44fbeb30895d6b78, + 0x25a3c16bb29635132684ee4964e4f7364c9edb73ff5d41c613347f90519098b2, + 0x2264db5f2b0206e0b97cebaef9ae578d534c98b8a20894d99ff4cc52dd4f35ea, + 0x8599a766249f3c836cab54623833af8da7345e0f976fc683d04699c33de0097, + 0x23a4e769c41d56c98af48d9d3eb4e65d5c3cb8f1dc50dcac0895f70176c65966, + 0x6863319f9840fe8a57bd754b58b7fed2466e86365ef6e678dbe7c495054551a, + 0x124f8b0efe11009c8a15c7830dac00743a617798bbabda3df6ac877625f3590d, + 0xc399275a8d3e83e832aab6df8b0849b9d1378376e90b8a24084074e85cc4e32, + 0x119e48a1b4a77a3a6f7c61ffb60b93c904286828355b63b3fa1f7efa5cba57cd, + 0x296e14fc6bee3bc2d9dbf89f2482f9891cf1f7df9ddbb7f98292f2bc7fd9a50b, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x26a69af895a05a3493040f735b754e16de06fa2c04c7d990fa5ff5747f83b413, + 0x9d38fd6121029734acccc26a34b6c0a9c5472d921ef1db0545ea0d2ee58dfc0, + 0x9258525c420c9158ae4a5b72f73cf036d988c7dd50700b1ed3796a595c5b6d9, + 0x240b4844e1a39d4cacdaa8cb96df170cc306bd32b46539a155a91d3dec72d330, + 0x2f7bfd78087629319d6485647f8267856ac5974200d94d165da35c13dd0f1c2b, + 0x10c3c9daa9b917522fb7c6bc6c18a2a70968ed139a349805a2242d8587b98160, + 0x42e830892fd09a016aa5998930a085f20871e7305b361d30690064e8680ad2f, + 0x1bd229a43207a8eb670f87a25910257b4d6e99ba62c30eaf92c41c887b92eeb0, + 0x179259aee9804902a592512d691fc31fe7369036e50df52f17899e9f310ad8cc, + 0xc94864bca0ef906ce0f56586a71ebf9cb21907610f55d0d597c910f1832f04a, + 0x1b8129aa9b54faded8b6e4594ac9c66268f761b4579bab75e4b84565ec6151f9, + 0x138fc45fe0e94d2f56d913eee6f4dc8362019d48b48bc11d566fb136a034e7fd, + 0x11ddf7e5f957f4348bd38cc6c2b7b21db6e688426842fe2790dee3e5c7970350, + 0x273e3a99347d8bb4443f8803f3144b1c79081762f0c89996e8ca6f41e2ce9eb, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x22e161940b597798709d5732b35b7a4a6b5738d60943450c0fcf0015f74a978d, + 0x2dc5270b47eb00ed0a19788755286e5153486071d8676de57bf1dcc0c95b8269, + 0x1a70ccda609d7bfdcd04227a1c7b3b5dc51ed832b3209ad05cfff7f94bd17d78, + 0x1acb2e3c8872171cf04e8e12bdf4aed98903f30427938ff2ce2ac2ca07e89b36, + 0x2adaf126a0f5fb02185e741d6944b194959178f84bfcf24c66caa70590d009f2, + 0x1d3244fd2a96a3c547cbcb56974d8a6286e71ade5e026544cfa6a239e32a4a14, + 0x1bd9988f3abf3347a931f562d4c26b2c6c7c3b157929f1d3529438687ddc9748, + 0x1ab2d592b1c45380283e92034c93e5a2e4afdd8082525f32728c8bef6293db03, + 0x25cb1ebe5ef8d7fe207cd159cf795ceda6553f6819f07ccfc9432344648093e5, + 0x30337709090c96eb2dd63569df081569d7cb09cbdf4a7c8c1a982b1a502bd31f, + 0x26767fe5b44f802d1ac590b4af55a4cd28f4a4565a03fa412dac54a2d953d6db, + 0x206a055992663ba140839fb48dde53a37509d75de3cffe05e543ad10e2a6a880, + 0x26f63a141092d97b431869438f6f4f2eafd3587d1759eb8dc51129be57d1c9e1, + 0x651190f970efd04e85ceb47f6bb491b2391e7e4c0229354bdd377435decdf02, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x16f9cc64f644433e68a60294430fa2cb5932712fbcf1d867628561f9057b714b, + 0x271bd08af5ec9271663f987e6d26c91b496975cdf5a2c6a7c5490b62c94041d6, + 0x29f3ffb8c6f14251d4e4e6479afc22e84b5c306798067eb2ca8530c01ef8f00, + 0x3011f9b6793cf8e594cffd490b2255eec2d7c84caf1fceb7276fc50d598c4631, + 0x1592b0301bc7a225be205d464faf0f2620c9879d06b7c97632c4996b255e8b1b, + 0x1a6cb5aa790973bd44ffb4ed2981c633750d9df8e6a122639648e0a305870d8b, + 0x3006f88fc72833b83c57897743bbdade1ab69f52bd8788b4406e17ec42bdae3f, + 0x2738654c515bfb4dd54512aed800e6c044bdb1d4f77cd438945579a03ffa1416, + 0xb321f51e6793cb25dcd5261f44260a3b7c9f9c44c5ff3ff64260a81d68eb977, + 0x1477b46d71b8684f6448203310aaf0f8948c1232cbba64f2e6372b26d3b96f59, + 0x2e11978278f26a764c2c61c66edb6f2964876d189ead6fdc76731044355d9086, + 0xab2312a0dfec5f56d70efde481c1222f08750d97f0f378e32416d8911347f32, + 0x293b455b67ef83fb98b09994d43c30ce29dfb9b499ca17c6774eec84412eae78, + 0x95b635c8679c2757a0299fba438ec55029818e3de0bb66721004d4fde342a5b, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x230291320aaf817c9bdaf62fadc83c8e9d55690dddc6ab42884102fbb8c1313b, + 0xebf9d983145fe427a9c98d8467c649a6b6fd0666f80cdc3edde2d6103a0bcb9, + 0x1b8a2f071acf45649491b58cf5576a862c45978ec121aba4cbc2b344f6adcca2, + 0x24287f43b82f4a84f3a2500829657e4890974e8321736b074241d6d4c6714cc4, + 0x2ce1f1627b642c8dfaad03fb46498d7f85eba85b778efaebb2bac14d3d4c2f0, + 0x11ee152a99a5a0de87751aab98180d05db1e64f3621498bef5a821d813fc7ae6, + 0xce62d91eb6161313ea7e48273122d6a1774f96e571277109302b68c53dadb0c, + 0x19824bcea6e4ccef8b23d501840bc4f3d40837dc60b4370146a4b68f6f889b91, + 0x2d1fc70e199a73668b4d0c37356f575269d258aae7199a266e63c88ab6eb4cef, + 0x321c2b5f8938df1e2cb30488e61521a99706c58f4237e4c61500bdfe47f5626, + 0xd7da06b4dec9fc5e1dff140172e0a84a9d147154745f2678a98aabc3f7989d, + 0x2fc41f67cd32d7ec4ee517c8b667c9a0ee2308f759ebd889f6ac043d8aa82f40, + 0x1fbd55b07a5725b3de1a9739d36114c9340a987b1e66ac212b12795249bd8102, + 0xae9b9d9f2101c972f848f0a2b7a8916a3a2987bcbdcfa1d300e0b781d2da062, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x19f45db7aec76df1b89fee8492cb760e8f6d298cac167d2aaba4702d30f3105e, + 0xeb3de3aa60a1e43df813790a7b02b5774bb93b654bb4f690bbbfd8b2e19c155, + 0xb506abb65dbe55553fa65bc43d1593be440b9c5227fdc84e142ee9365742ff8, + 0x1725cf40cdabdda24e0cb35d12315bb0bcf61a681ab3f3b6ca2cd06bb6f9d899, + 0x5b2e0df1727482fc6597c7ada0624819471e4c4f2dbeef58ced0c2e5a2844fb, + 0x2cb17d3d8a51790efcfaee971ca9155f0074b2e7622abb74d7b8c984feffa7f6, + 0x57cbe9626c16bb67d7f00009f1e7881b53643eabf6abf3f4bfadb6cf9678388, + 0x1d5a175df6dcdaa9375d954c5df8ba5bcfb394070967a231cdf753e2277257d, + 0x27453d445a464bedd2f943123064cf0d6675c8946f077957772f32e02a0fcf29, + 0xf2e2a7f140c38c5d932d2d6fb694914a060efe9e6bffe14fc1dcbb840bbb466, + 0x240f3c285bc1a1c717cc08ef209175ce1efbd0aaf894599c629114fb05024f77, + 0x2dc62be8336218eb9152ec653c5f2d0eda10ffb07a974bae8ee5a370aa497b55, + 0x1544549442e755807a39faa19a9e88cbe26fe1f5f4cd27fe68fa952806a6e72c, + 0x26d85311e5bb436e105c2eeccd768ee32acbcd275b22c135bceb61f6fcc99696, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x2d5c06ffb3d2b7cf9a0dc797193cfda855060c21de622962dc73de8bc7e5309a, + 0x1142dc3dd8bcfcffce00dc87253ce16475df11a72de8b35070e2a947e8df89bd, + 0x1ef9d5eb72934c51099404ef52f846564f9d5956a61fa690c1a474ec6dd4ad2f, + 0x1f875fbc8a4be018170a281b3f9c0dab5e91371ee3101e6eeece15ff9ba2a595, + 0xc7ea4455b4e9ea7958d0549f098eccc22e73f89b049f48558910bb97226db31, + 0x1781c95b5bb00bfc0c5280da9bbc2d16aeb1ddcaeb2c45644041366c0c57b8, + 0x7d46f4970f0af1bddb0baa2b45ea78c3e043c402b34fe44600919ebb3bc638e, + 0xb97d904e55808e8d3d847315766069b15e4eaf6e48533679e0d1dc00c70e6c4, + 0xa424cfc9ac1630f815e1867b2351bc8a7a0577a06a1b3eebf8e1c012883313a, + 0xab4976c40bbc9fe9106a7610e3e611f88e46839e484ed2160086e0e83c2e4c8, + 0x2bd44e217b9b1bd7c5c687ad7653730c6a9cbc73ab2e3eca6533ce3fb568a339, + 0xcce891fce830619bc5fefea2258df3f5653c3ca6050fd8efb3a653643334ed0, + 0x6cc269de739b7f75a505392122069f46ead236c9fe14dad4b89ed3be765ab46, + 0x2ce5dad6f8c706a1e48ebcd989cdb6e79161070d56b7f488b1ddaeb207d81805, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x2e77cf5ab513e1badea5c3c891925f9638bd14587f6e342c5a92452cb2216d10, + 0x1f0a2a3c8f119ff5dc221cd21cf450ccfd2a13a51992e227a040294c78d05bf7, + 0x8af508a7bea4393d740ddce0e6f0fb819f6e333f12273739f8216a7de28c19c, + 0xb7b0b5adc8e5b80228ddc5a3bd90a11a6a58fa87ab21faf6b5ee6b4786d3bad, + 0x29b2720d570c648e23e12c70c5d903c08897ec38e8f79e3dec9f892429df3f63, + 0x2b5d0114e15e9a524981ea2e38e06976616413a966172a365e702aeb81a3e8fc, + 0x2f04e33808a800ed501c43a1cc6aaff9ed0b2431f111836ecc36db9fcaf954d, + 0x75afde514ea96d4ddf31e02c2e3c59b857e12bbef9188703417fdff2b73f0ec, + 0x294c6a950fcf5693a8241c957ef737cb0e9a2ac3b7eb618a1bd1684db4353e99, + 0x2b5cfd45d895ab09fb03ee623cff22321018031c835f4bd9446d13995ebc2702, + 0xc9cc48c4d979b1d5267a49248134fedc8c18e6678c52f82e0ead42df94bc3d9, + 0x1ab81cab0d091253489ee59b36258e7f07ed92223988de2adf4f431790b7fe73, + 0x2586cbe245b6f98d39e52d3944cf6ecd7f6b02fe5125fc06677fa3adb5c4b3de, + 0x13b2352a38dbffaf3d06de3fa376edf5b2ee4e53a57be01229dbac8729a4fe01, + 0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, + 0x3d877056291c4194282a1028b33bbda54c8c56539d25d3813f0992d563fb344, + 0x708818327e42247f3895bd0af9998a7f3ab275831a1b7ffa2c0266090f86b75, + 0x2f6df4925de2c8eedf7a0dd36de0e83bf0ba0e6649447d6fd2a8dac7d4b1b819, + 0x1333c9e0db6849dd2fc1e56de942f8e59e6ce70f9815f74ec75ee7a710ffcd77, + 0x12abc89e5164e8c1a20e40cba62920df78cd0d31c641aa3526b5387aa499d864, + 0xb976c6394d0a9ff18c3ce234a56cf8d9625c11d0fce863278457cb08e1c4983, + 0x268b0a4cff7f67119358196bcfb46348ca332e1af2efa758b59e922a135d7e61, + 0x254b8126f45243f14dd8211df41fe5516b35952d56c62678c148e73cdbad3718, + 0x270712f18b1518fafe093660f492cdbc2fb70ffab31d8a4d8a1934be68792369, + 0x2bfc3981a249aeaaec4ab9001727d32d4e6fe75598ee964fc85cf30d50df584b, + 0x16060a17e1b11f851ceab20464572b3d78d582ea050014843101485f65ab723d, + 0xe73217a106c402e4c6c166cd9ef1fd2a0b16ac1cb43646bc1c726f83177770, + 0x4b959ca07e7182ca08f2351a03545bd7ab676f740b02331637ea1434c8545ec, + 0xfc9cc95222f92715cf7476010225e14cc38f314071e50e0f3bc9ec674a8aacc + ] ) } + // noir-fmt:ignore -pub fn x5_9_config() -> PoseidonConfig<639, 81> { +pub fn x5_9_config() -> PoseidonConfig<9, 135, 1071> { config( 9, 8, 63, alpha(), - [14715728137766105031387583973733149375806784983272780095398485311648630967927,12450793357728630597819493697261391961392738728208603858426218806728799382497,4427733724068610336929510244982091587998132283636864368924406075658439074153,17863554236640577761956319447874252524561947852685470820159498661269344021716,10723868775598272126873918500257797117892409794706524915527428530195343520361,8041366806917098496431513544630989490693774700064656765914266570204855843526,13046986480231887538692223126751085950758763070227069247275787663666591811005,20228999562936372999611354929112125019466353738760451044697249912024766542482,14238976012080913074226552202264063302466135977295108038770514743089287570221,19486717852389551661121716850619781027370627632295683938875312739716376501717,15733057748709959668511822511174594221965585899587926036013893958610587491491,12041333229715539748857491855115983195198694619439452683631630426350435252478,1829888811413627407640409778757789140470123549237476514374669162490680512211,10288898018349095056494632386514957183841700001184195479721999387950102580094,7360553146019695788111059047354435502690072975650576744373916804385350955674,17476063720528136669048514677420727796180556343667231122803521620226101935369,18384724266969916899691009636435516722111206340289089258767862754828208946542,11046121967047431151707881264774621308937270618998625466342467829704953599782,20018232138773775379089542131722766973741687507582662224374276186775807685863,7926534193496947015875888176706209291021745851605316909116853588598743879034,8826996877877607049084007876351017199517432230182001641783930871320527792100,11760708819943554023765145606995747732169597984739408998714117029765838566505,19598000655770319703844060561747179253151181702222064644764822676806532882514,15036675263180992517064890091049355832990063162957265821390555448206776251789,1053420874580688637503969479036991299021138740018858993455108201424412879748,3723543690610038931361367959096800720510056325209292666118208798533818425035,4599370243050726453512484851927735252841106375733105184316191846221056036380,18291400382386598447603657416871816375751118990979359745849342284893280004873,300341627009231088404894405580745838091318300821994947846008201887884150151,13332605655619720841053062902143052543375741442250678582318225211621890248982,13197729598850829723360679245789196039442968018972826673455394330035263151299,510788688496484172389408566109007465667555285205327059265048317979249570221,1685584118031999835794907889275254096486823415278284757369286336252006457602,15103945090904102223538479231258677032197950627619049222966748226967974852043,6653802896618953033344296077900828173967467309849915708475948018848254380036,9254803560511166426410537422101769642611302194250107918342410310963831784950,17006557344160230194691541621666219420787918477303225545533644141096551358258,773112329554511160545400721342977593377624843987783062638455005748446223137,6671483881284330250685026918783029584764740571210869197688044338476895092050,20812941492969561606721983530907505914064782270990490150214736286311482532652,1156984923268097592347582093730300227184163551449762803735684309575717323017,15303159756724065068145651405407765401796657934219121639364061501460295743948,18999785075801878445291021498876384414176522501978873700451842582224940767334,3782716983967799050957535371991538595453996691838733068933109780481907925378,810443910646366078824923626573819081371243815242873044781414798707744583851,3940687718063184864573934886068875138239553970085689518511531571139105765743,1222092197964451545227395363538155091563596468425395922702697716100572937718,11901775018663948557424314950737290815973735008800495766054692238446226616230,21839369981774608005059280910009281502958794510307248992429390932011110951241,819873152679629471918450179717035855395702808145570990556719950289951175212,2918016794043041559376798791171848118057043459636680115122516324180788251680,10788401265856066217998495397128704450484607734353922353470809976686155443188,13599498756047543641157208425687419183141596017402196474108059160235795892976,4993390793677030007023804867617329393931635615810976661139461248253851471412,973050533401342110180605419751137563184725082821038770229241448201970125921,14313276246574487682858906899808269544140218917497205965354285099641091349756,18746777136177241043722556179260854313319807637092383577312657349740719965076,14517023428366357570216698819722831600577825429761151189605029742824536459972,20223198094330596704408798588338060788093323967112845691364940702136543962642,2924401185705980722600796492514644487545258803954418619331883216838542308543,485440919681570468713530641755278841324413691217763990572458853294843435089,21560476826107225363638525612645382878298890750874072774141701406519608285783,7856508582404120415593106596945280577031904101959961641860467517902309769386,1505151890969527772884247006998953879441745452105187039442954300997320053301,18861812597641777105968621029392243993700881183944538936666186678355756609806,11964609307983840306843122014689504510236749206766494519381451521217569407396,17764783391855759749651949748230026302359698415337858912932633638930034077791,16562247632438820849068750036602367255890087581186727955070681252413797347277,3341595358840888933968836940161983842834749603437573997372892853189756769506,3198140245778498430686233550970322127895441994253754893043542706415030678798,9829840339700031668849847901844029075426216057792062644639239580989060312114,5999422607425238131817993672620301343082348300090537110946144186609066413585,19901271533560906428202710740924807375620638454776660078183104891177283526156,16697165654181109350158134734382046723004976300078845885330478879604895897280,19171906568090360833249366643372143476587242793789646446664643684138123124668,5557557332632668793539639636185643553639926364115539987556075445308999628265,4797522865199880517123583692586561796505378758857130153602827907909887751116,15409514194242892627651944305634286919424076146534027188938906487506413405089,10407013998132974348561594118793213466618426284969698091916131778477581263008,2534925381155806875978186916525958864791165037467997034976228683909613017312,16140842893634434452708565053572928560639256480905937421023970743339301598617,7517617592925372620130293329989654305076737363747701594349097857054039164182,17572708764253481596340159581412737527195601517063980704204677005617144607526,16697796470163537491131716229045730242536059781538196375577575057386248458494,38275164685285960308550480834951641755153240877853193094138358285155638204,19780228589871041196871406056718374983456578990309085234484187723923738516508,4573417308961077301452769955811063226515352449986725327722241421281202736681,4768055042642730073498433238804346134649067788593835428664493008393684000706,17566912618951175959416490797476610679702184562687840273697859062459883449046,11477598695424707935165112148975667441147635429812599883095916948275334113413,3408907078049921938725945268376819484694115736385272440041090673225197146180,2488590561390551829094067182419871806900177001183027832070626654223650976899,12116557895894464059885135778994901345424716569754903115015740397131803733982,15881232965640921626180413777392630630338847181632662075996983398726326426432,20914323757596181391651855665547258251038466184617935369425714249299063760685,4275923143992397246911855313401177253209967573031785993454148836244404305934,13098973753894185378061607442839048669135765294488505596582737281481575045554,7995472162206735324879506324600884378126850726543803581430135236761716527753,3690915804478314734124615543749602171459078573370790663994412906012450478823,1256453655839486811750227055618146120819862944082463957526146264573763714294,4406492967670422538631080907830590263463047897583684262207883537903678091970,13380843970691717863215678292643800288491103227905602355694129412234174194363,19680159398793220289979983679401118779763854719759576408245027038965290325739,8515713472495355510508289305321355004480161123461789103991491891201940557902,18392703846804297332972535728243845000077361414687818948278976164182674947067,19823604647876421559318429394175186838817554072847524297827763377975574273192,17719715026846703054856559310322577442906188886145763860157972477138788247667,8745282777320550983079435446349157218001552450433897097227622172209480270781,3259368608255603766247016957318442624095407655100612967940789373312058996520,3379679235619387594255002628664818227413294377266729211815713998759100259668,10282673789366804521601844018863748004632586596870138135887183100195194767004,8431227731426467642712572981755086675999345721043460063547234289139267810255,14117058124827023634266519281629142766485227596060997608233088670325722698559,17113232771025226173986361792697170950811880770802373827827162227101499645884,9906220434844104062978204733717072107397540599291396561476275675218575564970,711369587296778404961826907371863989722457674941832862265420496583620086218,10995654568685707735109869974152491589223292425449581061000447170660561828729,17197923097868441003908860864777521604587651639410061820516916970875615238246,3121715947184842829391029463556305441693293825061846129844634146823663627601,8817835750782344079827519863863370969960597321588294656839911940551490704717,21074199894730915603594812797833479514843396752652846676596119472522115586998,8903588044620722375103549330291845285230849782400990458525441823641905996819,7157451412319473873395155428325762769952294079544485671397508107346256362850,5366933733103001902997281886950280717532636892191522349820059149392915169558,3729196254269053915687004590799382892429870424157270200083981101426772909827,3918096703119862723362353838062260616080657756068272173354821697584630247209,11073027330528765229119199873305594827907404967404841004751556462671634016839,16424651511178205757967439516888026957937418127900739730326874335888617161971,17036562818332519536292487256920458988625450115083747105277938048739292827058,795554890382567685751618566957270321871701261784565632343709559354970377145,633072079840093073847779349151531317793918731920375040247534587265858418734,19421194221177975514787747427021411300539454454371387008642591623632727982196,9954719107136377193496025917640974425520732567100168938432529522254697824571,8674312532180246290069249621352567303340886011365637785384772665860996736758,14809129550856657213168714888239735820810817787153747648450536960647330811703,18479959092813678391370975524549834571584338614798320263799188362327888537937,11754080849414921164216607793483937490683185256818320971638570891360029327056,10287736699385961112844233987245832756528102056561178731804188514133469579013,14370616700332892416887680617217669883953806003377620695037833373409292189021,12131262377053219810698216976753909777223459611599034218924662817794274728701,15129974113281645648506209149692470898425572316691306513209191313993708898437,7871644959999350003348485402403894487663479920989578076708137744830000430296,1576915733292398470896862707357585951921545131195468346129170132189223165938,13316238922195025030929715018519212370128739646325014577776776032463179349855,15160020868051885495078648274966503057453505806774983308629511566464684311627,1692269682153339201433258246771340974628904846837119864247013056373782718416,19628837155426033423644376042848583705054394443378101622337255362403724735047,19222966046507618124793516210121558272031295169005274768240595331459420997142,12990748614547458190976906297393525840623470679364771518133250166378979874463,10124996030376091099517250678153357142212975502206884325977282211158514276950,17630673366223237394418802287655202715156124721482801416980858260564381593966,6743037447395702022066513290929048145404894812633440602191382691018136524423,3910195434942407507599129230554588207801501224467133349280934483448828467487,2025953242925331197360540874793022332074847486979998082380244277507702608951,17290925253475198968609624243667228472127383792887388480830073536530705682760,15557314422719360545874148111856256188428921052029295715627017447052250706766,19758557148246918190283097589287660972538989627091387035573386136809005998935,10859351185398338650386876904094285059182038967427299340069909694684844129362,3496018793417449121342556434800740598384008787187762642325224753304909741349,13695501250971489187692201493870442254612771332042272465953359508617675704938,13572242195808512474816152630443442412961099907068902213470234329372028271256,6257061132956659095252686302119011010885219692712894010340612889095488866530,4330599809632843338876238530496396340118064854909940219910748808728579051913,9157987606978264109338780586425009211347479724574125407732261019832259951031,2328698634372378957406958821467382289342903425118775270878244960387352862845,20636525922386221727012980541907198653039323429055563362662406273278160984146,15847894355448175995216566821171916679432807087340467956339517156584053817157,1942360378421747943668019094002571732886982847410366696537432314848905467679,9512432294361739988724195228775769058251373607278744642461344881575127503031,7373765909536890992660842391636719615263272667672747352621337161184389163446,16805165862480928364732162070809175154629112007405963636466097184868514458659,7667777941325858499291332847392489530780564386762784335358233711706517931292,6446208647487337326336908745536052288215677968074882840304817109073334759485,11285516171986135785540153632137541881991922296507010937224736080386568662797,10115214387228124714106659470937696440920497755599449040012569123044717722706,15485618097017003479590081826451772255273462073640651108645768569284210541135,14933383877101576453093795963534828854771957327481830015228527838452944594646,12699366929120600543724208703956381057734625711467645612998923493410472579972,12636366946456086231704939526732303791619337704833963854669708252203542584210,12149350767700952579168066320091211427411187251056390220529300991824437924228,7521252564104984899409328139379375498829232271563704354107116269254046402507,12033991121152464927378622393121300999333393690763174606686511857615848602007,17232776948709347607296344257668859070263618035653710252910881198999758003380,8692908682458431891302516268928916165669902656866484222966303081483718910104,1253076047322637463481069610081050841277544153675308425513468857300598987482,17753389824587331559955818909257943804816005297310986968447179587639048799696,5220269242560242526244582743085713945173060875457087963936380952653150665967,17126848126303954156127690428371193690154903947228604938919561454676410821149,16844245036721981603144243350071451732279678956963696493069130132912694448751,16797761350119564409426534689125994845767740388070744929816576998448097719798,19353620610135120026060560134469588460709151673182029068633909633596535108020,19135326024992044270104645311242450367403619348108625528873986701416220617679,17665816362466043406415418194780245586053150534372814020191541209753248047067,11399583108978058354832763133747562621839059603612742599115200702193127837394,10094334549114303273265943473013412623520307578724043117639269488721170750917,21601458494506173036246860827162868889968956934810679234022762622742359366252,6386580477827919478878489737663301647954047211008970416851133263802072756591,4792043837032853062947152822210390150724912812294333339974827814683543135564,20876886123310865680023706563792643033695666593071136348323857270657128199374,5931154799422838405687052216230902279350178420072288819326391251206607447359,5239679324690579237822809044372316561806419523557737441242604861240795339076,10385003741667422202343482240152986976068622687279646189490976516013598227432,8464156248644168452015929033942509092145250244998026718035923409819766539834,13177537753162628205208392995644675716264814191265988042404781479197639366733,5919477377826036950488668794024141041792143979412430063956231337921980979482,1351402666854456730370541080745509803482004768817122599092881844387000676155,6818673776641149273361875347660949176445649468306471072411086367313332518455,1366646945884507587781123424154966453464902291438811059924651777083838835678,16219293249111347900064666257423013936256436002819357345030961998874555359000,779230149490072246312543789505064727370429119089791148581854356816464370377,18480337167389263493513952937037301086055810692872257722500635290543939189393,1345414110418158215433956620396568245327910182467730711109133441878095212920,12518315654451653143886317929532883727219058399486775127781649065277400104111,19716171362713656659833259243590727588692449255201500490000859973307782246016,1865072487559894165339723956247507020827160163812334855490266264867949416605,8915174456326318257703177400411158958853446829269268103252573093652570933472,20191934956657253997484040571514242713447218897800997897558899754776252309230,3900170788760364547006546697350123842323924137566872497612605525517074710000,2242244954905694264442292936230335662862827521454977184433268725352453968501,17212753633823250440920113486091598217346743686574392123683302470302281044057,11939276774333100126191320505078174289237596631307779156488772314461752488631,361355126674011999247836373885105218009746852422112563922207274436194144681,3861054771271956681986534133247127581996350841974597302976225613765246291116,19968479093411941747037123171825881488638273087679549521610505739311299462846,8537196135596544183619390135426012949552627827993128615534814021127294540392,2438879838432432949185118142364194193697006515067980632650379470739663214843,10769366200854175394348657213265947929465261545591304593688343101111720627317,8455019976119342575889554308499186802278388693477937667704910645050957262689,20644389417984700539779514908032253651696357386572813102276555909201716748299,8820039786383750409041489202684137325382534899692778928304664068322226640076,8636461459675525672530300171201543901107046823820677414340465229975162161919,9061524648737340075438868917468774023866583922769991567001812766008277156749,7602969742956570438827438826124187210014769304752116695796494779120606534919,17880480383024583813657184645997268710007005482705400161841684734099773182094,12468433127385453618607022105559942067759302463679348320088817783890080634670,5227335513133160328788197758812517500875193491652227971114102085123079105787,6151293357148965084809035339276030775032864902311425722089088413878852880603,13699219811250783019541356007733829713463891996344484242492968708316395244276,20523944015644472920486129305620987253227711059638489683670518491277805771642,10421521516830672217871475174620176828341870738569247402138774913961149048583,15243709334491280025949017219424981672670169674700467979049999809115231651422,15516151337135073170256217447458198066207320794936363948307836943072374966170,17337341094266438501679457986886656365327787301649468585664115813920643670255,13262611487153423909813660830277859169133522588408913308784951544213550636850,18531665394082016871726276363920851282983017715104457591860421181826617619235,3700454591945927209171569025131477008196191968736477330379417168348613474972,3604972001659087732761769946443190920343158947813896848729866695375607825911,20952949990925307134028293094501736726689724950451065635729323134614933963162,9405357171465854081502883779215538022417071330241830295392540662303830897477,21638057691528924765719568024989208898293733581278465977164525893773900371884,1423261214711655336057796638966786076518765517452404205191550645234914655224,4051452662373209612509106830833400151748328181316060758960838588997502328136,18894191275634392250799133342573131067016712303481664374003128715704286175519,8319722910647187566775047002603641370685637216565762886509056643924765393708,18376807271218398458453428415456722166053637869198381036620575958015471551748,12035584964270041086110602893321059914382792217135345721427943800456312398294,12648928151571890511419082198798501903838843998709266232987169892491925610349,21412038262513052722667255278175073999553643537758589877888129674442282140610,7706735190856341161262212613554225730619876208755452623628315796884166016734,10999966015370832078836488333389544875338251739488999274500058322944383211399,4088296406085952300442596245852961024918851819760395990644634222875937267642,19399822412575078284884340953745677500886533272999950579143260384703504507006,3008499431966541245607724530938385192395211534821775780577277325698653345072,21447244586691806434401916456546893987941039399147865009673973728056412619884,893624395222035047010673050230651164575948871010677581303166873938544655581,21402344785412208717452894839332459679574051179708007417742748857146495441368,9392712010553327328684355664342647815409597079361837524976044019430681532876,11566000613582826375650817776243972243778859250974226949316472392849073658674,12900046757905605731200852057204734685283283637014313056501123642345467590346,2147232762440136333246788660102778148879449441151868600321283583777116020664,16301766972982581403924204059742972933467455194833897714073756335881543890771,9546560122931098895129690583175071306095759562194496054583390881525378967396,3814097068175987733354103462855355721851435755267819873064912557751073632829,10704509016547426355599213335456446765914211024738080860797634337598031536580,11921271012710313311785310319425095342886561942032945429395596578758895308264,21265249694322068914280109016742517903125526413969519857556032179013285196924,7207578215754030787157150149235357460121567678249968060366462431427104673093,20820013978092841458072065536574129286011620075823185493370309064760526240362,16441600678335369077753559950421185577542163640313037056248177018465084864223,297097313501884278852369638329400055327872945847645211148627847628970916078,18298084629287541333205519012404334789930413367615524379442280529941257264699,15206243674059814574375077493088319889784970587286591062649045683132661681752,18726053049188513051286348977772545167577661574609708038977390139794201099882,20262858185621074639529176348089123044694437795099449154711162805012934737131,2249345697973053772423677422936999849381692933292653912080014325442939977122,20814726663898441680439335735982981967722006066824203970896314191676769388296,3816485989624386223507317175678560807682224519267326958526058565555245734714,16741230612980371365533431648017361867585544111098407772560748428499802539906,2436865301432265520692873922135716828388518032014231744012990863912440945389,5265261577128499220460184630262997769060828863581478135168474766310582001180,20550548783058990082416235781987882123241946829605049684648813233836863290502,21523044301008793877416122201092687874337292497403523925455260117417170777735,9283421400783174646451499708802113832695004549893166692004850391713463380536,17813773547838391112844362681067751767404443478918792865885006908077545151618,16486730475669947890512191574075897324037778751496940417084163322433837359720,11367125189013824464048785896422572845103707778462525259651446893275289247873,4759445724467851058773503846834304672223785226936531021666916376323562671488,782273457631193956426744043048759353979593033245260492990657945904665284910,13487130697992008212099652811750242205045881544509489831523448570173633517977,15621563974535086891768796441515013364217522966350445838133979748032034816142,19364835034502915244801518193980688426244659266819997726035650961451415757173,21037385853462058267099182407141652124171361973889761119816789091401609511088,20434791917020905003166852059282129255412677606775079570484129378535005615291,4835039666519156760310260600042269943079463379265872618778854224413385690994,17796521681519947552208651467058827825861565135255248123077469895978163706264,2823350440792171019111081223801188552138104039380675927963458669980277420276,16030935304664378631941573945857397096373696981104104381156313618686049806120,17523561865544155408760007908067668065236326734119657233234283826019015377013,3861341406966982603014220134107636493882146780655211775629734223927755221098,1327887013530867777305056212037691710827939709365211251951525926327942169414,16874372098146373517691588057974501095408377103185981262983559391956463291137,1335930538845994150082853775454018356383085560294444442667355553131066129276,16846954448852864630121063053695845658867759327963014776419090787323732938912,1910615356880143423765930148112668984411979710628153215580997630269783916489,8793723522335768214688108364110927144836722932802666660252079036893034856492,3725321587522884864935206279104882080790553804758085564413847527197687551835,17549397166194503933313005107479073474671951786436058351827338574279485542057,6575272615526665941236934551769345604089554458721499014263130089965203838692,19479945993771870488240738504390121923410154808673876321101554256856036124677,15218540520084042504179141700157006972641510542203443030571191341196460163766,11605382280428426652337162672330854829498688801746852913129963366330544359414,19452583367341408020642116770501289011436457479987875413223766731278874726613,2498463382382553480222037299113185800507848748313035345734629490930688205092,1815123960727364421144419865126922339611466868807520419660969560789979822474,20531692711768862540943545541715345229360673134388506876856593310216372259130,21106443640856542784867046664180461359993554892163126756059125921876166419615,8538925154199646282458477113696635826112766123791239931164489946578874271866,6179996393486486548378164504724190431464526698002381214818146508779777698063,1334556948430115939422649531996020210538905726908545666936164977436729124944,14555087544451841622469763698691954343538388285983305607235034906273022598676,3263678860186354326206053303615515256258748076250020171477442794745232038780,1342606052959540554052550853649027290857482440100275878202185177537473434874,19067318604617984900108104413860593038444834168491290140413988853573796446193,11453576191720077983310542494091726783885546118293459348522522324645101050430,3772400828106882724656632136643514300687950364203707059277582466654856015909,19928616354232846804233301414766074864065580313304404532140360351457581578733,17669618023197654971616078177762451816976570462585423216749814198562722234016,20487504497482961764356160511764652912371612840137405927810776425577238052311,15959943319286858239034503624455112049217253792773599324329593237810330429519,18384331160163107383609864825156022277275076414745740108239579270660154123750,11807744905122445070761653068499781933485269571078706728521902995972849333739,21636069700028297640587439425598371999203459272489053044479958900301869951268,5974406255004817187688462241155741022204236935194897255519053490391727654963,18655439470676485950283686008645538637216956533059508817637925480405213882893,15164692255429309369428108531856612257028649418370969640920631880841690009016,12342219963417210875401056442100023070134657858086394031902694268469750570612,481209231155250366998260270814874408671884781003382050138985430923825730090,3242985953168013112117560001466320034030784952490866310190327264524235633420,13671160391160864796369771052335315926068131063004086507703804642392143876725,16716228406804746939632807079686149044089946710213611348848847599210659020138,9496049727665863372935045496498617414460003517119878231671018103126084599100,16483340875218689502751737973203780724082025375353804209734656041473116836207,2627597076078148403546873341483726933849452415436198036537442451261384383723,20527956374075302103516613197928664717455732919429461243667758971357150882342,11711450220231538029408058975978592998998598526983681112180323327131923215776,14877293714143600802178367397934915488570060506993092692625720179311507474506,17326201000468992158693082078045140389930457394232528033746431682308160431934,8241890704089720408679017565592201736334812957892898769189351788325500937732,6134985085876540657808139826388808003135254271482158519839818774839726308917,6944918715501093472287921248184355748547193680657762762284351108190443908482,20293371855859360749476040038457808453751087076170457949707661658124460443795,12686929429491234226470786986230897140429036877303905464553700071658994784104,17469937611674874489854850805106365496296990924579100118175990663783068480118,4389315288495042551686883151731749050970801790377604942482415778510472384968,11356013296312574683565144017425132580728729177241949155779586695189495537084,5103616537832821778796048073410908442363049367034544148603830689894368565040,17797731362169406634431131949969435652804582561417001546024888062211188454886,14413974530545126251158359344156378502844867672748912889426381728267720393327,18860675036245741580291857551498220749884348391920381715922087052471051304459,2078681010293955893545295223175290151677764183673754633340142745613957031877,11594462210573371469687203943585180057860108341927961420756260896877407822187,8232172476137304604696594035794651005660416081930158074561971898151387789159,16234745736110953717672420346414210260779855851076189537371942811750295876135,12403261277735118438898936378116787991453555210970659659639856670648844247938,10260185954137740247486488192570496092684935183379388125044125653647328054023,12655661577981598013787126068450556825218951206788052328715378240540030673155,18875782029492829253540920061867800401544385695523240332551730645990253683286,13000939909369679921538945109975441940863265779072482929455684540500587590629,239651505606383903278277662841450805219997298453219985892834268956273681444,14053674646208577108881262953518523519057705122297176784230960366018789686467,3606574524342197944154321263420984044427893927972300192386619594198948706444,4925738689374393290519002876270198297196104042467164940497567711764321354393,9820857610236925174040210045575219513594477725958302510866127781620764675531,8644935227560188528158307606853375529544842899940616765747319983176480635667,12589563927120228887319930197852404057542625019034806374830349240796880735981,13728987671030134173563628755348391107370774536000844606094840710456114349003,15280672692530045491619672502933299001869276703035606138561063102232345967821,21236672540209166733321925277807375026701626666734236841532747395149863205571,18193368154219306112046312834283644566129199372283662927472078427038205531636,17828956732555553542546753429670551891943977601119756829631880115504235233984,16641047964358580103472953437535358748387376425127849904658691126285684204504,7196281413799658043487145161620082973834461754768351228587249162400339111893,21279455923934963235610861427104388147894350922169838127737714784897083581830,10868227810739752166142906769497786680491652628709341836398414527811509748689,2545479497580424357309396388184225593698470568625667945691755386799845345027,18560104754451358950174079457178017278416450108044438296553162755384040068059,11209544817144484509471895492404241079181269159060632258040504564376475442191,14007605578670373547623429803718323316371456029307063658189484725071020560017,19316201371814679831554697580647476192318282119512681720915001227483533198021,16788142218280927569387096932066591137887806957079516944927766625343518189548,961359518362994763330685811948798278197676602059504713988410706948791494727,19776591693739287332042935252284088014720557305781829207369487992244783048185,9480779019638564372864984254416095889603560407402750333423136372713778963272,7812061847536565125280880398757948966749177710701972331770694629380983832516,14806224217889264732099766866344263686300132511433376375954468192761174167878,10982734897602724370866115596864634266746118759609469486863878972425453415519,9054801238670111257982773992849940941038784597792282084645523468554872244495,16788499373458165601983802204061832376825550128562541027433580619384299691535,4361212778425224413929793165968418385407821814716394404713983701050982051159,21198869506404830651226227162808186595284220877501140400488215541390720176503,7255012904510681544072472510832565052731304049336267892176928038570971034121,9737409770400739938717035426255379270654933363992002237053138761832402079248,14206577906412186888550704503752653056320975796075254442765439825369882967977,19036632138581200062386943078412086222459679497578993523004498970778925638274,2855178582526872375806959544405581665248537620420194093904041355969926293337,12896727255458884273207928529421874672712973447260798892551468479503233439215,20930350939164528694912500193219456539952966506926646436560438515643683077210,184093243282405111677536457857692693581379037444126410664343605529966199122,15658149328429348710722591333703516363901544310832580304722884306208924451465,17544235160628712643216064131303569753533519783718786133736357990785709619346,9378984995834426590515136439048146470293781405649183047514776402081048834772,15827462476470655610816981948418438654022314364182315935007413461648751735708,13474113844360907776462232979612140726930720201237003164521648175005015977732,1846676454601041085237775396212630553832771346942418764660365576890630152018,8958790186410745003596973786908460746144469347369569174866696175944574520886,16716100142556090678395507171596864615262575578180211444515549196841601774046,17584363243087108058467208592097637069605249776196694465943790236027601639916,15462568643993327150997687623907692370120490318886920754261967569094539968909,11670427917584674115542198398366950879185738970881616803513412243898491416455,5883010686944177614793479335292002976406988590121850032334552332298599405710,20848023045403944451304856285219275218146149181988087184275301094312642906291,20892609628755793476767683891284835591758207667306100001065280698890821585620,11041559416099382923560246079300939393371149141074957197352566129686429429340,17004024027027164912556351303862470964296900000646134239805113699616064012220,110742314120280698533248152539115345099402903868297760208823130532853128340,13611598917097489441998314826578736196564311189470688979687759717921520208428,20362978391139708024092837231934567580385484740720090300868417284017430844864,4130975720087443718484415210347908638971321493417335260526136858657572592254,15799784358302997284875412214187555553319485274948108081666806701893845835839,12410480753305882251320943831026503736012757975027018073585110506521877824193,11835843853657957571888855948788121206617247107501669280697395787347649231752,3326313455005237548503557557286834479752096887215379141590090769222516357133,3193633369267878319453517203588676707547172638050950764150162277144428673066,3543696055990388683071939150214505536733386566291338758519836333135488212473,453840133795717001022433249997110059635014609516452256954528366651276289770,10086004265216215714804100477403907145516617200748655771783383139854288214070,18938459257787140207383332020952460039308194017940327258304986766920440675756,18017538799787896442217663532610710859333377084532654794368604069493775630216,5517691591172342790575564654696650661133600869824307632295945043592492062300,5846204096126701465613249085053971321249645306247508562697696901334354225619,3177064511134248081568628736306700282095095665917536853000298191943047784014,7886005759395499452194553110700824805018792487440311729836576312028682853862,19249432464407391173245558257296856631584193393398113008165174416171947900609,16818455958785909569371690525990846776263170512884599090849081099178789681425,16250344336602567919050898941410625842485562539342327155695417850618940905704,6273998461375119044609362240019558608655450921258416376794979330773412610302,15933077340738498731035173703791932079747269039222967104684412531145625747085,17631878023023477567294765381542867314814954498487832435087010633074888584009,3387656327342575368928488173891176548794878068816523542226413637288662472792,15770343706243316227190526252701886989383556270818375222569120097305537622560,21025947829537149117391184273139276031347299127217645728072786010534368285621,11728430055160129100077268133090903533902452454196978455625432056779499908581,2184576630760971645143677026393147474439766939689140114811262608230414186937,20744811853491523948066896610767067484129121010717068573365370365324040781186,5378129452609441814399329369785055593231824205814541852039878139773312247469,18082900764136659604287793533371380099349929291808230688664846500365863263118,10463958995559323021196963984934883570109613942564610388110191948063546468897,244120224370345949702567256216804961153505781666838608095297311545160357032,17924705581798291273661662368787600134425123985006190354093511903371507000154,3107793385049037773698181795186417899797325916401357881664725445733609110598,5665818573123185227274537904890713907625420710982346291959547939830358917272,967322682615997637785254033877348832211978156650281338584051044602311410196,19419941178285529854771216440310658103611219351729270204884834098822007849679,6901963792883328370624032472781824547409040392368725235274158498520441238159,13721659825627300509722716825333808233371435398666022190921612703736274379535,2784281502858555298249063959836879135450746982163416748737579846439268828933,9904373282060708277943634486822397019446454722637742217276784802015824898651,5782567592658163731724098371574354386783075175203877502094122152538152467682,10854330629450460532485325799036675355255970975925867222693267730198057197195,7162558805520478103072398765799613453839879264508883857822705210986309908966,14561060495007338369036260685346480181377385446422680685283066135483167829865,11521954935420160563214644175207412771411940789064933791820101643809540481492,3893071612329582305940837979511590531534863287842007408024123330272447072664,19982770443796802008915975147614604175753586689418309845602797606117149147490,19714753609495058998670661272525609201695470529132258598980221623379639411831,10656632215192474178114431876399520721084839753473211054259843433641616176373,15519943627473966175746342389219894179761085602008029155282295063466585111230,429220418726674010600368106136723992478318707196454289985261340376476917460,16943119555428737036287647863079565463224985076466268175824843518378134856246,7079268853451648384434335899135383974808119657387366504271184409878695702895,5787261347913259367727842908192773692002199385877294080619854106978539332397,8254314874636465273639128395147895313719165057850599581478980264860146008069,15417738281457065064716789110361253613929614783743035738325702945037527193953,8995940809050737092434676062651493038351424361820394016896779859938155003450,8930952966754141446126393622188683431566029237395186071059700311531927009283,9012970415439810859538557593310902447051948348093454112737452817814629449500,21700461010267441715993595978543322483687194036588160210184366057201658507847,19191426116308521669196161733982754533604260068907220372422504926794231257150,18022413735343984488479130392027693687461867574196874267731354592562070094392,13853879871506882218224060020827336496729967255850404386800036291019021382781,13303720125164503437055631247918150173085142868095887759030649510172293881844,12463581809293287384469946044562671884924464520288697069370030386140109068261,20468619377263375923071378952981485015200979956112400596511865225946853604157,16682148710681177357125570715056314888342059670705617513402649433802720432267,16299073895000203963165709887505572454180623116454760411179563591228007694413,6439155427163506786329349605983728674821430800627321435200421453561910062302,16531483734580605436075637034861280240342858648848575098901014901746112480232,17413802217650584016261506268242623594956116228659732892682224912798301233645,19833018739354446018077109493089909435818386368530968355647208939546565982905,13005203599293796776324509750491064421128717423989464867065044987475986374420,15433711189444672576513248931602290892518442446252602686878477157678233603772,11272192842480959445178012145556234469776261923967845001064211055340129168135,21349777755000957327199310930646977290027138137542241555905014230683052104267,2414795183415356147955181901405712632718942970568205736628916600696077941534,13910388410253717440990758214044472114511432613509643223811561885135488623236,10073917454281511762447567386654530277776617831005093724557094001489771821135,15674657915196276639699997458656008228696751013801231738985398708672037426000,12030695425048598984176709301472822771003849589255577773183310838231109921591,6658172369461756755506276881582345916252610724131747740625283609123100367529,6460801016753822141904293563006139350014125998787400018150863192907944207957,10798491465896968361800574703868612181389697312199241920447162078078725409638,6331917501914253534943383807348566698937757752033630507696817298838693259937,21521172968280414216108032807577565012642487518706778276505136864150789112592,11443202152743097070847729825799673217706162711935940510632741405015900516668,10360970774813507384412119692215277392320350056791930702078433469299837875151,8111678922881662305935841208620197469657237670526301850210945861223648259810,3828566775247110089904016755996284741548002327940628727687176763639903716661,21019871488460899469684764817167629979753844957147537040703291790231271795829,11744049805554498869931942573519884330545637954557542018916739662277241821806,4521092770491436085084640166923844634777984445583984077999595768778116564222,2428018726292924561718904390333390438951211767580762396913313600061529081905,2672992591753804066533616673591169777906973091506536575810912266557203322920,5631180351966611479340932319081124575466459942666630580683510336616679680271,10149209329290376952496655294191511204529081153402908137750268385347783758010,18292794133971639465196495021864699906132845458944945214425906730119328661326,21442863185355178191454777233963814974940050392649316620141474331670970354424,3768420898310640667772098495371174917665155708578905018940113026409140957987,13677778555119984843885943251631654212176086447994430552012266440677394344669,13884681165958999171515885225547717032289759601884108191367706162606597842698,123196094575938824660055152882088188411485715788351262262924974166600702398,1121836698372380581784934880625694675020871234049336489788624481922395781738,20941331435492311592529607715649713508861806194386837398916323083940590908651,2470912827043971002614412337239267059969980871643559631900987795139200233821,10806505189594612637071931546921663393081238567888534876058498530874738324701,667951375802630033661777802749339877422061577764798227349674331630120025667,18416355600415187627018330134584431345513028652497077471935121971918269469363,14167152054564590179475064444026440101215733530475912312508414765738108715862,18633695428427030575173671831485026260967985663658201463236228419717189642766,152822669216765741203342297512101138657182497046533047369566701489981099230,13835701173750333056481994253160471551109858589047436642253159392878873667798,3993942321148722649703549241999711668949060533276325947207349685002693878681,15582244332423092177434976075689385819450099629893355758782548118218073388706,15110236879710270343688993144525012407319759236015974251051640787524859884359,5104405092803829419537383694663582438349376353030379488011426113631155364320,11034886586481561934231698674217393887518948538322130743646058638919797229737,21614370562083755709911993869347579638113152610927033622836963904672826178593,11909716327216431973191112809713028257963610176155315584304717743448686635887,9670047520194835060472941420215502268522351803257892125345072551055025494562,8752044341583145728028411582583224350471084864272507077624316823400738066962,20685513123216586620977713797881862528998788503897607377725195418550074311551,20219162196364967181713755472576994456615542213293827108438968625041058321145,18287830464300889532838439052863785386620820747210980263612361113628554829988,10146051396529576924597355409059465520468869175466632446875430377637660889879,13466459020798488583841582724067017412922317425102130151754649408559458307937,14062280191830459071860023268317938748180670907089383563443465249500572357980,18486553995294693573565546696966437493113894571993019524170031057367640632085,11156566424349445901806390826392443373766529722049710427351550423908421767094,209671637225069235519570008386635562520193585953162475265417907100134848923,17226989944018790920809176115775819865824823495740082575382169759054625372382,15644589951345053163188258692419292119540702867922222648564209455819510994564,3689635641036835670663293726548900381724135109917216986885298700630212836435,3367607896403464195671402279459329078003744183784952830994679539910724667259,6227320552634621985217890398406127207902736210419315868051857823685244516725,7357930890687295365886228617478473072206575811998185548162905341534675558305,9337019296542497689612612043175604595811913796434346282222317112981594913389,14658782859891978670907070276103444826326577838777644289370207112293812556778,1700861002075407761970169168361393086239805454951858464329713573177596208454,8422307882422345667268572118847227804767508317685246864132851358134342544918,3824678171886439611637777800578730196591582015637069631407414390326082519384,7520989644070067743500997565082513560943860081670904302057616063200273050286,5278276919931895959830110725703210158384647399821914390314400092195592076331,14590632939277529585876696200177152214896495867542780671631701634592299041714,14365499645924743985349770983085181263329435144891175678390938245209017764418,2519790270252875654107597063434691592006935573176284731324585122712988059511,17688843544040778657269233842324532395371012201506418912518394656290716826075,16584068781164994465207120381716024087231836173689783891650623302438290695506,12224860044594664185598615945328866758529752520066027818906177267571423023661,13664317767999211366109254182438581912610775541954425083255023643648887081779,19324196860555787958873349597666822462940695051471419602454830948112942481945,15338841226759355791277440652242849878000656382388414806186764010001628984934,11076363155150973228897602285090741665942726007445165132980573631249449594126,11228309866140794620879641097623963859536328868056691748463227126359575786386,4762608512226640372168720665137259637840828925512114281702049841301872652787,18282645934358125859102195916568492018711932725386725562892735740355836227532,12803228415054755333149187333584509982900042807310255834005394843350472605458,17675693156369747720817703064233611574822178844066411565804543111769294187197,9900029048144575309490519431063332695303076438539483419053219772370202428926,3684590949621971596368895784562632626464811455818343794800044114209066071601,5443335602638685057982926800093482287199751584817191972983546508574786160090,11352900694666160844325992247118358443639716695965864728670968730093466793722,9836739435541786452166525951732520477055729763398281521212184905286650567233,8222926590877635625730738050718327099397892409701316035188479123499338707893,8154558268770648194631329585722892880905143452138234292827603893129808716905,20661038342485310632612091028394348057035659683250957045340774030445861865592,9136910062528018177460276667688174167129493547069053533874280111057356360561,4362513385797089229061458501847196255783651860098500705320631416351847846956,2061137061600029258110405980965338431925491466724330216028866028449889153371,14607676885409772552908782897874144975643999944034675480739173900267789420534,215346512487318428553079809620502708407272005519315271404209452927497999118,18044026902282362371439577283764019415115969502361960218708274179281044595578,9652478245641134951513165220881528043195466248948069255527062590256621034842,20994154929281322813927859895894589885437941429166007529912073756113466975582,20752721666010515144550782025078875036488075535083563976118804420187462745253,20857028711523544595627940704882176284224509745902984714255291431664146535922,9631521770540523913735742126933921923952197512938165111866628665235591582568,18950423265182779471595998716023482060645307106263127634953888715515988505533,1436791836740130330138273456892846001841969807914099860317370076565131805680,18145299176463660895047063984288790313564980703886502044680749544519011424826,7008134596456692891696131297028980612714475387065733972352529833092170154127,18054087496593103261596842546955317831262607456582498514349407492750291465651,2460661191051979147731673103829326449069370361298340160666765010767300969003,1121019547339042268901204213478561141018690742635442229019134496736639790078,13486140142607002128358893931572108539446504181590991898872881746144618091798,14485083458755292442253176062192342099468601222388603924363708902524652589634,17684636079328478898730536417772675839399177918554869673260926729643471105206,12382939536995562937141167025903251534081453604974163882762565576243762872206,5191757256912351314880102858899907666377813090645991709894707944196053941770,18397247107649643640823283145149323187327745749077714626730537494597891967945,21508632378351416585385353654317189405917247727406155133342616741543833680788,19108354768686907995261340253443420621814860995097718380505789237761300853182,3649609518051015699386442513879956346519312025847003339036530556474594795760,11893851425092314587513815253407979901615516208632062595457152391110352908805,13296593391067251947204447959241604616835056311051696511507435925462940176830,18493557674615580922923001229788184231889430766683327472934879670006059540367,7669746659590113244880799806073731587177781693253502772068846650012974230120,19370654200032786851343971085637480775724705092664059950989935645178139099864,1331955346226787928500793024038189892044219824334532771311923855914410290305,14488880297827410405382492933041130286687512096290491259710680579157544248910,6760882547908259908954677726421351194118695606292587659467769365205068189814], - [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] + [ + 0x2088ce9534577bf38be7bc457f2756d558d66e0c07b9cc001a580bd42cda0e77, + 0x1b86e63908c4b12af43cec6810356c94d21c9e37d73dfff9742a58e0ec356be1, + 0x9ca022ba1142d170f755212e2edc9d0a4ace33e16825f540d5d50d5a021a169, + 0x277e69d47a133804241f6aebe9449be6e22c849c6d8ad8c938eaf613bc1aecd4, + 0x17b57ea03754e24ae0ef425aa2ad931aac9ba5457a18cec594545a235db6b269, + 0x11c740983395e0f4a026e2c7c939236375c9077755eb1a37a77d5a1fd74abac6, + 0x1cd85529010dd7e2fb7ea403515bab5727556a479c59b822efc5a81eb37bc5bd, + 0x2cb9354002cec4bcbfa985de34f43d702ced83d197aa374b5a1f96f87b12f292, + 0x1f7af98e08f6877923f27a3dad40c525ac52f56fbbd878506544f9acd61aa32d, + 0x1a0b807de55ef1263cb74d73f1c8bf3403bb3f1e03cc502a9e2b8d423688ec18, + 0x1fd59a493af01f538eaee9b1cbcb2cd1b799d6093f0159107344047c2158d90d, + 0x1d3fa4c04d54e5263e743a2fa010370098773853777b73c7c92af64eea079612, + 0x1dc892a8d006e9b99d597f449d0553ebb51b259319ab9d8b2d02ed9c6582c232, + 0x2a0537379dcab76d9308d2699e0e900109318a740c75b8ee1ba71120edbfe071, + 0x149d2cc892e7cbc1f4102493bb96b4a36928dcf62f7dba6d9e0d446f5ffd4fa1, + 0x1e49f2771b7510aea77ee000e757ac105699c62a33a418ebda572969037b5bc8, + 0x5649ffbf48a15d39385cb62912bf049e9706155ff3dd43f7ce0e4cb35c86c3d, + 0x2698b359bbb3686b626831d596fc5b5039f4af516bc683a289876271ed62897b, + 0xcd8c08efc5d2bc627ee727dac325af99b4f72ac70f61c890b0593eb03c8cd2, + 0x36a9a9ad327aa70232cfe6c78884ec23aea703814c701a1862789367b45b3f5, + 0x2b5899d038a234824746d697d38ff423459f7bd4015782f528a3705a6f2feb9f, + 0x2524bd7a1969744168f11aa03fa82da034edcd1c31141420b2309344d2741aef, + 0x89189570593679da35b668bd5b3542489bab1022dd790ca6a99c09ed0a79aca, + 0x6608970a49c0ea65f21a544c215ebd89b4023c387e8339ec7c9cb80b6b87ae4, + 0x283a6336d81e02e8dcfbd4be67fcd7f8b73cff4ce3f8a7f3451b26e81679309d, + 0x14536ea1bd43af4d7927054ecdc962563f6f396e372f35cae0e5218d62bff454, + 0x3036ae3f4cef8a4a0a324f409f290c172e5ec23a34f75d57233a04a055648e00, + 0x22262d9a1cb0b5941b3f193c381403425b83e6fd9e1b4d930183148e414db99d, + 0x1555e4726cf5d78d11b66f4969724e64be8dc3047d0953aa84be42c4a3ab4098, + 0x2a3e9e52ac1fa4915e262406c27cecf24b0411fa674ea5046ac44897629e8544, + 0x14d8abc9700624bfc54939ff64f75e0ad187662ddd0215e3cfff56a350371231, + 0x1e0eb685b561bdcc6cb793504a4c1b5056af33ddf6f5e93c72396f6e53eeaaa5, + 0x2e7e146d9111c11d9348ec2230270bf211b4325c2e878d09faedef98bcd10dbd, + 0x18c036ef9e573369755af33142bb856437f6498fb1162b8f8af4523c390b09b2, + 0x195ce383cf5b4e65acdb300d6e359320ea6bac8fa881456c72526b4513ee1d71, + 0xc12860b292d22e5520d416427e1ff80eeeeee47799b322e0580c2d45d60e6ac, + 0x2ff73b859f68c9b8eaa94078545f54dd1e9dfd74fdd762dd65f522af19ec3ffe, + 0x1205dc46155d9cc22a89e838ff1a462738d3ef1972a01864c72af0f342e524ff, + 0xfecb680ff19b124ce745b6f70fba1b91716e12f664fe93562d93700adf0bc45, + 0x234391b786f9498db2680c6e7aabf4b0ace0f0368e21eff94528d051128cbc6a, + 0x2937dad89e2bf12f95cce70dbe3ba4c2ee0184226387421bd18038894ceaedc9, + 0x22c7ab9a912c2aa92e2afd4749e70968322f7e5750ce6c697dcb34446102b85a, + 0x1bdd8241cc91cf091780328ea6a0ca6dae8c10c50796006d462455b90e7f600e, + 0x49e3eb4d3bdb8ea3fb6ec3dc065556eace18a719864184b36da835bf3e8de11, + 0x20a8611ee3a91a1513e11ae962ec82884ba24f32171939892a34ec6d4622a88b, + 0x27d281f482154b5c001ca383a1087bb1481782f2bb457fb32505ff63315ec376, + 0x530c5ee45b6b16abc8306ebbf102a1c0774f8618699278d5d3a99f42495a3f0, + 0x256f402ec1732288a2ae27f56a2fee2199bde67ca2917984e2a6c7f3952a8e32, + 0xed544bd301d33d4b9ef359de3bf01e61397f2f29911944c5d091ddbc518e146, + 0x1370ffbb023d66ee62ec3895f61de73212207ab83194bf6cb1d49d37bdd4f34d, + 0x2a46d5538a5a9bdaf47e44594f3092112e755cdde1a6c128568994a040e9a04e, + 0x1f3396d7db31c19111069135ef2d095c1aafbe2c76d7cc387944b2f137edba64, + 0x225f3203fed96b846724c146b3d3b351d6615ee5cb1df8390a02a715ee206f18, + 0xb405da3510e7abe759298137d4853f651e35b7660028d9ce680ef29db4c22b, + 0x162df9d9cf874a89630d906160abd114b09274c010636c440c3773b5f012374c, + 0x26349d07dbfe862f47393d354491dffd8ed56bcc1424d45dc3292669be8ce0d3, + 0x1a75a0ebd02bd60bf851e0cc564a07ca5145d4ecb970625acc7f225480e29903, + 0x22dc35316d34324dc4fc4812b24468a33b94bd1187fde4092670d789f8372ba0, + 0x1f260c2068ddd344bf8fd0d985ad999e0a2a0b345b5d4e15647c60a0019ddeb9, + 0x43098906f60ba8b964c3d33854bea3bfc728ebd374b871eb716e1bee8f6fa81, + 0x17fc06025f7d0132912f6cd189b75845e8a8ebe264a3561610ec2db4cb22f800, + 0x1853501b6a22237cf790f64d592e46b76bd78d7a6e11a86a5e964bfdf98b35f8, + 0x13f85a860c328d7fe96970fbb13dac19233067b186ddca81f7b805dc7e8d4de0, + 0x2553858a2dfdee2556d24923c609eb3bd92e58f1cab1c406317019df0bddfbc7, + 0x18db95df1ef5cac1f4d5e21dd81e4e7d4fbf98deef329bac3e4744b2f72cc2d, + 0x218cfa400a003da69ff396f9a2fb282d544a43697b68fc6baccccd9cf9933939, + 0x15b192afdaf7ccc461209127b95647cd661c37044642f0207cc9cc699ee8a3fa, + 0xfa2a193cc8addadf7766d712c7af10074bc8149460ee35b5c78d15cf527034e, + 0x6f3dd41dd4a94658628fa7cfc17eb024a59ceacd9ef0fc0617f275cd9dc0fc5, + 0x7a9cbf46611387ced1b18c4f371d582cd7b05a50caf7e230a3b5fc9e028bae2, + 0x135f98871577c5e638e56325377721fbcbd590d85e93ed310fc1c0c802dd06a0, + 0xe8f8ada4fffe0a6b9faff17f6a926f28ffc38d958ddf259ddf4090083bd66e, + 0x225df6aa9bc49e9b2f5c8dc81e15c91ec1064db201be633f1e5fce6bc5b9b6a0, + 0x171c3bf7f45ba571930991e63dc8f4d823ea1d885357a37f7825274e9b9e0d40, + 0x171207761f4d71c5d5fa62352b306da902f0259f4c0470bc82409144feb9acf3, + 0x26a8805900a6087f4d916c5f8b752ab3211023d730a1c5f745d9122fd9c19973, + 0x129433d6ab5a8f5443489c357b69bc0c27cac6ae3c24997e5728ffc76439d5b9, + 0x1c0c02bd9a4f7a36fc2ad938f9a742c0af5d7745f1f0ac5b664aa3e4057a6f18, + 0x165ff7309c19adfcc8ee6ddf752f94fa5c24bd0e3ebdbac72c1fb06aef56dfb0, + 0x26b387d2dcda5acfe48872f1c9077083043981a4d22ec361830489ccb49d384c, + 0x136f73b20066bf9bb629e14dc8524e6026c159059fdbf51160066ef7c416be4c, + 0x2ab4b86e7cde3982d2e88235c312d1413d85e69d3f5d51bff97f8521bd7c35b0, + 0x15ab3bf7cdd8944501d4f6e1fbf9bcc650c5b7a96860f75ce08f5299a560e3ca, + 0x63757b1ee01190b18aaa9078ce6c59b4ff979a43897f7ac41f667ac1300c522, + 0x7235d5c897327b9b2dea43a9c924d63adf0962c8024e9486b31c7f7dc93f93d, + 0xc793e095f24f97300294b90f9c734241509ae31ac0e13f9f1df46e0fe537f8c, + 0x16c461135e143c6fb08d9c33fe385b0c7a012bc208fa6671e4619534b3e73139, + 0x3695a3fcb6f3778dd4884dad62e4e86c750e28d14fb31cd59567e3aefd0fb71, + 0x17501f012f54c4f196aa31cbd91bb126c254f553e55d4ab844f4d4c689d1a1fb, + 0x20ff8c2701723ebe114d932d485fb4af9af641e52cab0d5390db4dc624295cd8, + 0x605d48243e21cfef1ed9130f5844a0c14c790624b93ec98930d250c1b410bbf, + 0xffa032ab9b633d34909bb748a498d1d76f82057973eccae9fcfac45f50ea6e6, + 0x202d96f16f6276129f835fccc83f52e4cc1a7d5f2ac32ae4363e9421f6704beb, + 0x97e3fd4d35bd1394cd482c2fe4bc3c02881e452adbf58858a24106a1cbf0ad6, + 0x277c2847ae8ca64446c9d04e2be45b786a4ffdc7dd1d27d6bc978db85ac85ac8, + 0x3410aa7a2038d75d33082a5fd6bd77d018578ad7fba9f7712e4f41e7d397e6f, + 0xff02f1d79d410c828dd44c6338c31048ced79c8aadbc45afe4559dabec02981, + 0x49e781f466e2561b92d45a40fb76025afb1732b39a48dbae1c5542272b1e126, + 0xa88c49a585914a1ad99805da9dec850fffb2bbda64f7b509516a6713b884286, + 0x45e7bc4beec7107b2edf2649f982863c6e106589588189eb0c9de4b0e039017, + 0x828aea263b9f5db239f9c49e36a2e8cdc8e348f58904138e089cfcb8470ae5b, + 0x253955f1058a3387b40981cdfb33b74623817a3894b51087d3f9a4b39d716a10, + 0x177c69bc3df7a463c4d26b065562461ef1caff9c92d3bb143ce2b29be13b2336, + 0x14d6068c39b97b9a103cb0d40e9a8bf3ef7a6c7bd1d622d7da57b7a22cb1dfab, + 0x25dd2b57b4799f6110366e0baea665aa42325019581b8901fcaf78864b51f107, + 0x305ec758fa6ebbe5ce50bb2f16ec00d0430133a0dfd4cd79c12d69f8cc0e8ec3, + 0x11ac0a8009ce27d3e2183e31dd0175f81284b37c9f6e714e82de746969c98865, + 0x1d109b8b68f442a09a062c5a663a0935a96a91219587efcf3e95f0aa293578e5, + 0xc7b0a104e403dadc80eef55d68fd56d56aeffc40bedad4f44b2ebe780d08ae1, + 0x1807654841ffb72e7b046942c0080d97f43191c6d2e78b70e69ff867015cfa78, + 0x1b63da1a99ed90f40b0292180dba78b6e09454b75bde64ac9e5ccaf2b2b64043, + 0xd7e5c4d321bc6d180104e6a134450b8a62034e98d72c9318c61176453c96d4, + 0x2e252a397bdf1b53547239e3c6e9bb5260c1905930644e22985f41eb6a226f4d, + 0xbe3e9b1a8abdb889375ae6082e14e37bdd21b8e2a675ea56626e9f4b9d57c81, + 0x161b52904a998f03ea62ae67b561f1d74804ce154f928c1e086731d68efb5213, + 0x852f56672fc06cbe726036617efd210b8025c85b96766e95925e17f08564aff, + 0x21c4e873d8d03af989f22dbe4fa0a6af2a8719d289707ae506b39518349b6cbf, + 0x1ac41a44314ee18b9f9d4fdca582a052c9b69c09309ae447404b3ba58104581e, + 0xee333ba934442e498cede6609a1828ffce94cf07fa7b14c1c991889ad1448d9, + 0x2996c68d007ea8d16c014fdb33190fa58ee5de793f07fe4413ee3a4fca43466f, + 0x23f678b22fec25ba357cc068eb259f114754a65477022abe24cd07507825fc17, + 0x1f6c82714288549da4646534547189349ec908aa2fa02729e979df6a5882855b, + 0x1f818e74b9c3a490b612926bfe89e7947168d343c78084a3bedf771216014354, + 0x206833435ec4988772ee1f0ebb9313319cb243705c1313de603fdf61a323ef04, + 0x171785b03104df15a632aaf4dc7cb7acf47934c72c96310f1342500805120d11, + 0x20b7363891cd3589efe83abb91d9f2e6c59b575b8d3ada6c6cc84faf06763db0, + 0x2d60609bc685d0925cdec6f78d731df0a040638a754da555b8bfe26536a325d, + 0x1a91979ab3ad3401872d210b3b41347d44312e5d58df0c1217881d544ba301ab, + 0x166546d364e42050f2c39d196dd4189ae824a570d39c02ae6a85d82b00419bfc, + 0x1ac2089f74aa7d61b7c44c57ebbb6751be4c8a22b2f82f13b513959bc2f200c9, + 0x908ca864a04bcf677dba3cd272c6a1770e7a9c6381eedbf9f0491b02800ff0e, + 0x24bc8a866d9b7bed9242ed6a482252db77e9d83ace606293193994aaa126e72f, + 0x17a33b4d4a0821176c406b479e38da80d26522fec0931f218c8e54e269b0ffac, + 0x12d6d179f18bf6c6c13661026c0fdcfee596af082545f3299e05a8a78bff2e28, + 0x15c7fb9fcf8f1a92cf0c677fe58b79065a5a502d778ac6967c022f6f31132405 + ], + [ + [ + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x607cd8ff9b889773c9eb68b8a4366469d470cd7c6004106caae95c10c424419, + 0x1da524cff60b64856dc1f5dde0ff62da7b182da26908f6ba6e590adebf91b40c, + 0x22f33eaee3c481e65801b761a72832908f066fe21dab5fa5ec1d4c6e99dd6dfc, + 0x75f84e9c719bb8de8e61083290daff19aaa4337454e5ba804257787470f2f54, + 0x2084be9a57e9adb80303a8dcaffd4bb77adb6815168b36a1d363b38425437135, + 0xb303449f1bf4b92d2cbc26ab34b4215b6dd7af010747a705b2a6e3398882922, + 0xc099bc68243537203f97254f08dfb7efc09de8f96d72f3b3e0aaded45e18b4a, + 0x1c5fd9060d4e0d999264429a5004c165570bd1675b09f977708b1ca48e616388 + ], + [ + 0x1f8d3a9d2d31ab32d9bdb6375170dbba89f6f8f74d16e4fd02f3675d5fe2baad, + 0x2591580b73e7b5d5f34d9fdc0cf7fe3de7f6a18a255e4376fde3eb31dfa51d79, + 0x2bb4565893b6ffc5799139cdc151158749c2c65db48672abaf24c5b3813c0e2b, + 0x1c5ce77776893d48147444b9f6d66a4da29c95707de832756c739eab8e87658f, + 0x175505391c619b75530fa83e513184381e603d8449d1e070017ee8ec0a4d25f9, + 0x6ed1d14dedf763a3065f27e7a46d7fbf20d2b4e86a0db86692a269767d577e3, + 0x140cdda33bb7a79b2baa851df5ad459e7df569b9f2c3da542d3b8d5b76b356ce, + 0x35e9ecc464cb431cc92c3356e8a98547e843ed1324c1e971179fd1ad9fd51a0, + 0x129f06c930edd36fc2fb7044a6332751a2e3bcdbe756d883716cead6bc7063cb + ], + [ + 0x230c694139416f40422d713e13c056c45c3c631b346854523970eaea58a37df4, + 0x93cff12150aecb3465c4c99f044be85dcc1eba21d429132c2260dd3d12ea441, + 0x25081a00fc20ae366b1fe7ea6b09e62a51f6fd377f608368c12ba4e3bf89935f, + 0x2ab8edd22fbe2a1cd3ce9a4212d0efb282ccac28af4d876fc946203070c920bd, + 0x29c5ce97710c1578a0990d862cf881badf10e4f6bde629199e803cd1c426be4e, + 0x1324544a54174cf7b3cd8ffc4b86320f2319d9b88c1779b89b1916018f3fb9b7, + 0x1d18b25aac98b282e10b5a3a74ce5caa169a5c30bae52bba280ed517f3f82fef, + 0x2f35e921dae87f1284c0c8ae737dbdc4936cbbb03a03a5918552fe565270a8d, + 0x14a5ce1603228d6e6fade57c1da536659ba46d1b25566f12c28debcbedc5b4f4 + ], + [ + 0x2063a461ad06315ae5992a53a14bb598367624afc2833ccbb83af92ca0f6a334, + 0x59116da88a081267dd888204fc6fb79046c3297ccb65f9e0fe0d50b4db44ec6, + 0x1b43719cd10b60c5647c097d1fa84b8f3c12c9c475ade13b388c7ec47240be11, + 0x26e49154acca24424d5f8d29f650f9824de82eb7887329cbc83a56ae01dee4a2, + 0x2caf86cff60521ccc5ec6e2e2c83b4707bb90f948644bfaa8f80b0afcd4cde10, + 0x2e923ea46d492247e12e0a7dccf6620f5eea6629b7532b3af246809398859633, + 0x1ec6c32f513b8f30c7aab42e7d91aecbe54aeb188a84f8ca46bd7e9741b9a389, + 0x23a72c27f4f5e6ea5325d5b368f98b40693b2db1e8ca3d096739753dc5678303, + 0x143617efcdbbc0d27a091f28039eba8abb39392e2a462850b1f9cd8532f5075f + ], + [ + 0xc574e628f84b6ba9d17b9d2bfd4747e06dd68cda2383d64ce365927098c046f, + 0x2c948497373514e7d9846dea9ddf5755337ddb661043d6c628cecb8f55173bd8, + 0x22dd201ecbab94a2ee393796fefcca63aa54d9a19ab9c7f20a0bedcfb9d191f2, + 0xbadd77f516d4fa321d1099bc1e51909001591ad9919f08ce9718aeeb2bca4d6, + 0x24f92793d67638b4abfdf48ce3b62ab5d0e1b250dc274d746f2f7d0544185b62, + 0xbbbbb87eccc91d5fb07b6c55088ca514d68ddd93cf31c8ed2d2cc7f23b22b, + 0x89beeb21c346cb9bc182aa2b70f853f1a2258d56893ce5a948d9c645ecbc9bb, + 0xe07b1d22eed54fdf966ffdfbcebb653b5dac3b2a91f50272876efb17158be2c, + 0x2885f2d44be0ecff57d92a4384edb5bebfb585bb23eae2a2ea50806bab8b7bd7 + ], + [ + 0x276428d88040a3e0f442424d2ffcb8d19becf3fb6ca02c1b5c61b5ddc53ceb90, + 0x2c2729812be9ed432e75709133119cb0a14e1b6ea31c1279b7c3e495deaf108e, + 0xb8e79838cd30707999c621621e77e69c0f433d543b79c668cf379b6623bac84, + 0x23671c5d1fb556063a64b5f664340936dc5ffedd4bdbaa2e96205704da5864f5, + 0x2809dfe24c7fd7cd49b97b27150f4d38a340b60f0733fd4530cd4269b4811e4, + 0x26010a3f5295bb4481310cbca5384a47af0f9905e4c76bf54b870ef0ffefa1c8, + 0x2790643a66038cce4a6488847d8d2da2eea84961f8134b1be36947f803527e67, + 0x5fa56d431d4bd09625a86d3623464dc90bd541ea41748f2026f65025ea9d2f2, + 0x4715db6d86b513d002589f1f9522f7de3b1a8bd702c167559ede97da2c0076d + ], + [ + 0x24bdf6101b2f223174e869d6aecbe8ea5b04a14c38fdf1494393cc6fdb3e42a5, + 0x2280d6d4718f9f06b551a988408f0515070e455ed63377e910be087fb79bd191, + 0x2082d5647658eae648936cefbedfad2cd0538572aa6122ca68ccced68f432f4, + 0x20d7202ccde24901d6ce2d107e79e1fd78d6c9398ba7a4996f116adef14def3, + 0x26709688150ed035f959687edf7747ee8ee946b770173dbe50390ab8c08c5f9c, + 0x751a4a4af246255ce412c4bb47fa34a51b8628f3cd902077775c8fa488e7519, + 0x159e25e00326a76f25c1143a5be6f53fa51ccf368d9974cc6d93cce8eb81d37c, + 0x2d6f3e0e98413d5d6a1101b245c9e711bb2e956e27a5870784fd5403b39867cc, + 0x88887966c079d2e689a8d6d7bd913e92d326959bada59b99a653feaadf6c467 + ], + [ + 0x180fca184150c0e354b4b3a4a075824d4b68e8274943f4dd8b0c64eca25dc68e, + 0x1b1bba125505ae9675bcec7c9af579c5cc83533c9d555be398afa09cbf95d6a7, + 0x277bae2fc597a536adbe9c24bc8ee81731eddb574c6a5142c1c5a48c51f82e81, + 0x1d86496995f14264e7a054cc8224900368775c3e5ac6b5f54285f4a73c2171ae, + 0x1e5ae4c295ad5a17e00f973f136f1230a6fb85637631b306d3705f80effac24a, + 0x28d2351619ccc6fb31ad4206e2c064bf4d9b2292b28463e53e4771f10670ddbf, + 0x2486b884370d49a003fd041e800f0a898ab61b5e947997461ee3284241f3baaa, + 0x213176bc1a04939fe7d6bc30691aabd6152ed24f309bff3939a0d91d54c67a66, + 0x12ded41f8047da3e6c22bfed3ec5bb52d027e560048db4c0f96ca9fa85e17bc3 + ], + [ + 0x10726dcff87299c8532159976607633f1bc2ad24453c1bab26b726b82d756ebb, + 0x17013257716d3cbae28e1c272cb6aaa2844136049ffbca05ca201523032c64d4, + 0x30354c9f29c920c05e99d7cc747510e76f7fa69a71594a290eae7293c5a48441, + 0x136961746d34fd196025173c4d79bf8b3d1d05291c584928d97258fd5fb4fb4e, + 0x2310e2337e4d53c1635da18a2722178d55af583591bcc317eba842df247deaa9, + 0x1815e4f7b40a7027878640a6cdc4b2854300cf6fd4953c2ac2c77625ef44ae04, + 0x111efc136a9dfe0ebcffae8943e679cc0fbf62fd0ce03b409fecd932a8281b10, + 0xa5a1148dad4562eab18162b3914b64d5753e9617a5154e93f7e43e6860687ea, + 0x1f47c67a4325672f17b8bd1ddbd80e4e9e6c62419a9c204cc7e8821892431aae + ] + ], + [ +[ +0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, +0x7341fdd8b6d7c94a710e78e47ae71d8a2d2c45bf48dcd6fe346d2f9263adce, +0x1c4350bba48cff51ab2e0c56301b9d3b289a6fc4744b61fb90dd5bec31107ebf, +0xc6c426215bd132ce2efae38e5bcd7cbda5cbbff829320f99be9dbda88fa8a3d, +0x2810b0317abd6345a234fbe4661070c9bbd1712c64d04bc8430847e6a5435a22, +0x16ccf6000486cf0ee9eb858de4de15afda028275ae86398b37a27f1586257f4d, +0x1756383b6b2b1db75e494e291804c5ad7d947d6c79dfbc5e72009f11b69c3503, +0x55fe8568018f82fd47de970828d3b5f30fa7f671670bf1b615f8ab4b5df6c4b, +0x21b8cb5fcab5ac1e4a8e968e95a134731f85c9fb488d200998c1152f49d3c599 +], +[ +0x1f8d3a9d2d31ab32d9bdb6375170dbba89f6f8f74d16e4fd02f3675d5fe2baad, +0x3d8602794854484bae8cefc996d566594d166c98e8dbb73e70c0ee829da35d6, +0x1c6b76e0d60e628fd7ca0d7d60de7382c8c7ffdabefcce98d45a1042b4330121, +0x2deecde3659cb16fae536b2a1d81ddc50da450c1e96c100a58157b0b2707ae8c, +0x1ecce2c394a577ba99982bf4035574776ae9fbf51aa4b218a363eb0bd1b743b3, +0xb754798119ccd26f34de2ad1caefa4fc586ec4d6bcad8788a831331802bebe4, +0xf246352b2864232a8afd890b5a5c1114127ff9e80e539b5d922b3d53b4c2cb6, +0x1d6fb6b7c89bb84d5f7fa77fcc40ae0bdb914388f6578747f62f388344139ce6, +0x1aab4fcdeeec99f73a94f5e8503b377394eeea13c9c345d177c7b97923b1014d +], +[ +0x230c694139416f40422d713e13c056c45c3c631b346854523970eaea58a37df4, +0x20151c663660a16fc26c7452d683b1ae0a4bfe25e01e2d2ff682d6f8c5ad91fd, +0x22d746e18a8eb6059d6913f3d2219fe1d1abfcb21936bf4462f3deabb86ca232, +0x12bf39e8f879b7dfefaa4be7d615736957975d6b386c0cc89bb81a1b381f05dc, +0xd639e4276aa71f97d6d061929e08d78b690054d7933907c91989891d7e04496, +0x22d621427b2b65407fda26214625aa8cdaab5e27bf99cb8f8aef492030fd40e6, +0x1f9ed3d81ff1494a3e555e532cec14085a7d2897ca721cfb41627fd387d4c6ee, +0x1202c35b5378961b68f410413270c6c5eb4861f5f016891a9d3101da67f24c24, +0x1fc69a3e806ab5007fb930b1c0e8837529f3c18357d74533f14c2152147b6a88 +], +[ +0x2063a461ad06315ae5992a53a14bb598367624afc2833ccbb83af92ca0f6a334, +0x14be2c9eea6708b8055784ff7a6eaef5f2423ecd3c987507edb4d57f42263c8a, +0x1c94e3008e7fb1ccf9b36a3b272b4ebf56872e9d3ad09fc7fec8b73f3edc8dbd, +0x19c33a1bef2695e72cd132a78c4893d762540fa2eb33c56a7e4b6f88a15ffdf1, +0x129cda4d6b758aae7d636a11364f08165187bfb7cffdf51c90e7f6feeaa44d7, +0x14fd9137c30861213d9081982e9c1e3627180371bf7bdde642ce8212b70a5ad1, +0x1835c38dfb0f16b1ec8a341397cfb66317dd543c48852d8ea875827e2d5f68ad, +0x70a63f4db1f63477a7245d0577d38f8ecbbd9fd8a253adf5e36c86f285598bc, +0x1c4546e0f6a7ec769233d0ec55edb3cfbe528b846ed015e41d063b9dd42bf1ff +], +[ +0xc574e628f84b6ba9d17b9d2bfd4747e06dd68cda2383d64ce365927098c046f, +0x21e114b50d11303e7d5e39d69abc346d8c062b3bc70b5a88e0d04c104c89e576, +0x15c4bb533ce05422d3201cd04a12d976dd8d4b41ffb77dbc5f58904d9fee034f, +0x14f45f4497c4a67c90f50bef58ae132c54459facfda9a6afd38dd06113bd09cd, +0x154093b24b8ae3e4c7ecb11ce7f6d10326366c410153cec3543b8f8c696f5fe5, +0x80ef3bf4cf0ee1d45e6e64fb415c76bb901b1ae802c7ddc2f8fcf9a7c4a8f91, +0x1228c23f9d6c7b75373a17d421f64b589d7f486511f846b19d5b5a7a4ae888dd, +0x7d4d3ae7019c26ac7038b866eb5f0b9913b54315d879065236c20ed87c3f2fc, +0x1df9042167db948e9c137df365881a2137baa8afdcc75f9985d2e2a54ff2808 +], +[ +0x276428d88040a3e0f442424d2ffcb8d19becf3fb6ca02c1b5c61b5ddc53ceb90, +0x2d764f3f9ddefa066b449acde74eb4270b819cee10a4125abeb091cdca204756, +0x106913bc4e38bb6868247a3ddb23f7ac12b78d688df4cb4cce0e2a0027317fcb, +0x2968de39216f3f05107f5715ca891c8cc9a238893d7c75e8684813f9b8f489f7, +0x20f194b853c3b9aef7a751d3922d17428d595a02f6e9562f568e2cf07c928ae0, +0x30593e502ac9b6856131ba8d187dfe8d53ad20d4ce7a3b8d89ed228c91045401, +0x2dadaf44fe7fca4988d5777f9324ab2aa8606dd3c4ab4cec318e0dfa9d02d76, +0x2b30b0b25fc57a37cb46759047e4c1906a2d64b1da6bc8048d683a3aae105814, +0x2af620d499b90b1b8bdfbfed437d5c71ffe5112b22d538a33c9511cfe434cfbe +], +[ +0x24bdf6101b2f223174e869d6aecbe8ea5b04a14c38fdf1494393cc6fdb3e42a5, +0x1a8803986af5a84f9aeab49f048c67ee6ffb4689ef31cb51eff59977d250c4c9, +0x2c95ea22f6df6c0975156b08f16516ca905a828aaa2fae35c5465bc99ebd0b07, +0x17aa91194ea3c39030e17603d9b8bb80fdfd271fc603180bf0ec0b49206a76b, +0xf6884885a376b75b81ed233294372cf65cadae30ff9a657ab93592ceb935c95, +0x16a7398598ffc414f79d6d0dcc11eb3830bc6b97917ae1d9c0486fc6a162546d, +0x259a2acc8e87e4a08a384199ee3bdc03df7a3a1b07c83f49fff07b4da49e4ee0, +0x19cfa837f30749fbd33925eabe3b222452dc4f4569c826e602f2397007c0a858, +0x22be9a5ad9f369512913ab2213536ef1ea927d91f42c69c35be9071d3208dd5a +], +[ +0x180fca184150c0e354b4b3a4a075824d4b68e8274943f4dd8b0c64eca25dc68e, +0x1540dc30a1b9aedaf029e5ee97b63a63fa1a47a7c59304e2bd1fe7947ce6774b, +0x302fbf64fe705ee3a34e33211937a3cb487838f3a697e0f77c173999486876b4, +0x202f3f28f786f3047f7030428878b673a3152c0500874263b99f2a3f3652eefa, +0x24145768e616bdf16b3099e09e9e56f114c3ee6fa6e49513c2c4f2b3d0002b54, +0x80ecb13362f44510286df98f696ad51beb124014f31fc8cbd9d2dadfede5e55, +0x10a2dd7c6bdcffcaf5b00340731e2da029f81dea7271c8c19825060cbe5db6db, +0x17bb125cabad9ea535325629cbca4d37e5f30a3bc3c7f12d1aa1b63326974fe6, +0x1f5576505ab6cf76adb88b8a85e1bff7d1ccb35691118d4180034fef90d2a873 +], +[ +0x10726dcff87299c8532159976607633f1bc2ad24453c1bab26b726b82d756ebb, +0xf08d47f49171fd7d603461458053fb30596012a345aca5e6c8d307c5ef68130, +0x1e1e54bb56826529a37fb6b7bfd6af40dc9da70e6f6bdf7fc89787a7a2ed0785, +0x275c0ac30445ca28c7836765c9877e439f0b1308e5b8b5bc30be95808c9b7c03, +0x1d3ecd8624f2fbc7aee4dbeb91ff442a018b9a60b23d7e607ea9eb2f6ab6c239, +0x237522466e8ad65c715717c5273d65815a10185498c9e71b48fb441d90b5e3e6, +0x1f23b760586a694ffd7cba2757f935ade52b1b3593968ada9e0268cd71f6ed64, +0x36083127b4a9a1671954c4ec341dab8d8419322c722061075861b41df631a9, +0x236a813f6235546014ac3a47d20bd75b4b6357e043e1fba18a05ac59a9aded9b +] +], + [ + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x152fa675f337216339a9274b97b08d74eba0f31110688589baac5df73d06ba99, + 0xa60560c145b77121171f32dc6d2fa22fb894749d2686475001e0b4563ddf68e, + 0x2402bc21cbfc23a80116e7535240403b3e7ada326d3f5f28e7071680d1b57df1, + 0x26770c5cda1a14d4003cb55ac927d68a843b0a81acbdf4d1871a66201e3378e8, + 0x4ef6e3423ecb4bd4137b2b7fe78100b84a1ff459cd0a1f7212668bb96ddf0fd, + 0x16c6d4fe10c08c64f2bb14fc6d8d650b05c56fc689a93d0c4c0a79abfcf96887, + 0x1069cff9be3245f60606f94c1f214a3ac43d2249e725dc57d45716d06d905ff2, + 0xaca974e63942bfe230694165a4f72d184d4b7fb8a1674a70cb19cfd61329f13, + 0x15ea665435c28d287bdfd4978bd127392ccd486c9afa99454e9561fa992040b7, + 0x2545f2cb24c7a7c7af6beac75e34deeea9d532c0308187f7bd3b47b133a744fb, + 0x29b34fa5653b3ac5f3eedd790c7b94be1abf24beeb24ee50a34ee12159e94b15, + 0x3d5d55635085b4d05b57f78094a130400e4b60548da9cf59b90baab8e664235, + 0x2b4768592e18dee0d620b4bb3ec1f0892390a9177108346f9fc611e1cf592dc6, + 0x198e90e2b6f066f99bdbb201258054e8758dafdd397a4044af7fe73ebd0b05bc, + 0x209c25806fd4006da67b80c5f7a3fb03990dcfe087375143a7a09cc99aef143d, + 0x125cff70ce16a10ff53be8b26683420c895d366fa9d3763f14d376cbad453b79, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x2fcc1e873c2460c19aa8ea31876a63c06b6b16c56bf45ea23b2979351661c066, + 0x265596228bc6c434d211a6340c4a331df2be3b1e433aee26875876ab83840e3b, + 0x13cd5d84d4458fdf99666b4f567ee9bc2663223fea98383d29668084a67efa07, + 0xe4546898234e2c9981d06fbe84630d92d6854979472695a2aed5aa1c2fc018d, + 0x15ead9f1be93476ca2a93c83125918403b835eb9547d3ce31856d119ae8df0fb, + 0x2209a03017696e3a73afcb978c53731ae3186f4ba315ed5dc8ed6578b3d9e428, + 0x5b358d46bbf09ffb07f06af770b4c3f695e35af5f32f449a912310c69165652, + 0xd4ec14ac84189f1e114ad899c7dff8da5000fb3726ba88b6ed828451e9a4027, + 0x212a27391f1accc7e7e01e05868e41a62a2076efdc6ee94f26c30e5eb5c63359, + 0x1cf3fedf016306b0bbe65fda50235bc16cbcb1559c3f34ea6ee752f4b70b4848, + 0x52d3e0d566bd58d8097a8d1389d1caf33a2f2662de98f06518670773f74215e, + 0x2852bb73795f54c6adc9c635d5e70b03dcd03cc1229046fe2173c31b10efec53, + 0x23b69fe902f42c3489061de846512d346ad54cbde1d54984e26b551b29cfdd89, + 0x8a501e4d110e059ea6a0621d18bd4346af275aaebef1f402449c9f675feaab6, + 0x17f6697583d43520562d008293a70980e2c6564131faab56fd71c285392f5bc4, + 0x1b7e8e80739ab54fb01d2637963a91622ba49401fd5b961e892f00107781788c, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x1cad07b82878b8c153b0278fbb2e90973327826a09fe720d37166bba7c53acea, + 0x988724d5f424785949062a55133a433e27d8c89a7ec78016db5f064cf786948, + 0x2d81921df5457361416733155b8135b53f6410a41170670e3fc8204a0bec2d59, + 0x131cf6530e31b3541b8312eae98495b9b5435a8d32d35e5247c53f3170a58110, + 0x26ca4df270856d7d89521b850e376f46c84685eb832ff0abc83be2e46d008692, + 0x148832d14674b5bd61f45b882d08ce10b65eeda4a8d90caeda39210526a2930e, + 0x19395b170131e4b969e01d8bcd1a6fd6311b3375c0dbd1e31b879fa6835b9dcc, + 0x2617b1f4ad2fdf615bbf88b4efad44b6a7cd5ec6e2c469a94471d5a3add577bc, + 0xe0507aca633caa740518c6ed6ff9ca084bb59a7d0d97decf2530fb6ae3cf24c, + 0x176ed52c8a9f3f7bef3e084c2e5235496a2177f3418364c3eda28fea7f2a6624, + 0x1b1ddd3ed3c82536d4e2cc47820f37b772335bf4530356e590c69938c1ad9eb5, + 0x13c8300e2bc52c8d4c12f2cd9442cdbad38235a1e34541b42a274be0146455ce, + 0x2f5239bdf0e8f441fc01fe081832618bf1b9628cc80ef508dcd4273420cad1f2, + 0x21a41e1e2c6e4922de2cb723d64cbb9496216429a3a5a3c0c6c0019bbbdda93, + 0x3825cc9ed4f752a3a61be70f3f2bae0a22416870a8f692206aecf4570b4d751, + 0x16e3f668cb7ed8c2bd6cb4687d11dfbd02a8265f671cb58a7bb33a03a5238a1, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0xd94596be2cb2587e41dd5ac38707f4a718dda9076b74a2567949a627bcca82e, + 0xda56e7fef653a7528ebcb12a7a01082f7e23054bbf948da64bf2ec2452d098b, + 0x22ed449e9752660719b8d34f4962772d7c7b08e4882442044c73a8aadab72c4a, + 0xca9d3e4986304f7ff2894c105218dab722390273c42c427c4dae8f29d66ca5f, + 0x10b01235bf874a5b2e184a8410ab01107cbf0648040ed6633d179509f5041191, + 0x126206165d8d964565d3220cbc84cdec26a7643c68f7cc42ac60d1f8618a6200, + 0x4878d524f362da3e3aa6dd357f0bb7d5615f26cb758747cdb30490707218854, + 0x21127103c61b8936aa157eb73855ef46d5b01587aa8a199478424f3c84d9adcd, + 0x15d5439ab67e845a1f55af2ced4e06ce2d577a29fe250f1e8116500d11681999, + 0x16a7318212f1751abe1b5c422ff830f1892dfd76737c7b49433e7877358e2db9, + 0x245579de75e5089b4f5f0de11d5b88bc5e395ff9a0747a2d33b8cb3e3394aa91, + 0x2ee3d749e038889f77c0ddc80bb7cd55df093664716a75f0274b1955a8712a06, + 0x277b64ed9137d7914f9445969c33db2f0db95938df3cdad46e6c8d4ac996796d, + 0x28c9181f359dfa1ecfe51ec8331b999c4be610300576e07d8461d468672e9571, + 0x18a1ec6f905a49044a4920d0a4a1f74a907db755d1f06d2d75551c6e9b5bb520, + 0x269587fc49db8b933a31bc6678b4087a12ff762c1a19c3699e0703a39f822906, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x1c423fef62d7ed3b20636135bed12f56c33b6ed3866b4deef95935b4fdb3fcc7, + 0x2c39e9c9ffd3f1acdc23821afad680c199de68c72500ba9affa091fc35d8b230, + 0x200be427ad5d644255178ffba022a54e5ba811aa0a0cdba615991897d312933d, + 0x5bc3aef5509b9df5380dc3ff1806ab689428626a44293af5a2bc33dfd98541d, + 0x19d3a7be7f42755c49327c0865f7df015df793d73c5a036f3beadf16022d1bc7, + 0x1fce5fb51256a4df3e994252d479c8006547bfa2649b9fcbac1e77699f31e917, + 0x24d5b2801c808c74305280fec1d16f0a2185f4f7ea2709627454797e1d694aa9, + 0x1b4a744a7602f165651e06044235910295d5be42f5e5cb902cf1bd0a449f44cb, + 0x221aa0d3a117f313e2a2a20c6927618baff0fc77188801b96188ad8518b419ee, + 0x2cff615d12e087e7d90119fc9c184c7903abe446e206a02d1ade996431e0f282, + 0xcbc5ef09419a755b598b1517a196b2ba15521c55e4b940b410e647a57713310, + 0x243e638c46a410bef0335b65a5e2dfaef63e3030d9c20894d43dd580fb36aeb6, + 0x11ae740f93b3cbb1262d1a6232a4d8c32a9b4e2fcce71620dfcb541a6bf3083e, + 0x14ee58652277e60cf9d5c2690dc83b833c66db0f8a3524d9d73b4b78846b145, + 0x1bda443673db00ba4dbbe09d15420b772ee22d921a43d236368285d42bced6d7, + 0x2de86a4384d67c5e44837bf469091304ab5e77d2eea4421edf64ba3321a12718, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x1b917b840ef31eb7e0a628bc85f7c2c200daa2c53ed4ba7f6a9e1b24b1ddea35, + 0xc54f4f9747bf23552798112aec65d4e9ea425c25e4ffbbfbbc3de49009f8858, + 0x2ebdec8a92cdfa3d690a4419d1928b4b4d93d5f911521cf06140340913462731, + 0x1b74699cc5eb637115960b5f70998323c9c3db826844682cfb8ea43c375673ae, + 0xe09a75d4dbde40d4e18b88f63acf3ab1ce50c80252a3012152ac38fbbdaa61a, + 0xf7c0e52c6acfe356ef5c75f08788edd3e75cbfb209436f7a5d0c3ac9b250c5b, + 0x250fab500f159fe411838e3ac03d2587f7e358cb6c5847df2b427a6c074df62a, + 0xdcc8241d56d88000a8b7aa90f6af3a4fdffa80db18bf815ff7a0b02032b2aea, + 0x1a34b7894985f4d6b216af15dedc398d4ba39351bd325651972de2a64fd810f4, + 0x277bdbfc7a614412262af936a8be70b47e7e5d31537d85ecf155ac3ee482b920, + 0xd3a2e73d19987bba8d72256028ea7052faa7e99aca09d9a08bf0035e402c03f, + 0x1c00718f76c7b7bb506c09b6e1596c137117668022fcab596984aff97c858155, + 0xdbd5f1c327ae5b775eecb71009a20720365c0e482fde75e1bc1371e5c11fcb3, + 0x867c2b4fea85a4cab294824e2276bda8a7406fbcd5da41b6e0fdd8b69a2f1d7, + 0x1d393af52503c0a9aff9fc1da41662cf9a76ad7d3240890bd456a47731a35b4d, + 0xc4efef6ca45633d4ece8715dbdf4b9abe4121a608606d971845e47c70aa5db4, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x280e2e4d9836fd6f43a90fa68a9220a0e5679ad45fb21c8e396dd7c267e5d3a9, + 0x50dcf95a7b3b535a88ef70504cc8a444e78f8b5ef48a3486112408d1aab3b87, + 0x1ded90abdac843e977abebc17ed03d58eacc961cc82dff032df1e60371acbd1b, + 0xc83114862faa4b053ecd3df00bc7bb610d8f777319da6695211696cacc7c2da, + 0x2f38535fca1d0fcb6656a7bc9f8d6fb0951cac281e7204191d124ee1f9597056, + 0x15a8a27ccdf7f31e9c9bdeb0aa12189a62420b3fc3af4c0ccd527bccdfb31261, + 0x8538ca91007b4af17747450f2d048adfbba6ada49300d46163a6141d0d60a23, + 0x219358a11f299fe602b8336d6c74c8ed45e0af3437ee3dbd73c7415dd954f229, + 0x1a7ae67fd2b95fa482e68cfb6adf7a5f703170ef536e0c07c8f45e212331891e, + 0x2d8a33dc859b421d03eb431ef70e9955863e4bfa9a7650cb11f8cfe45521929a, + 0x23e68686a4e6ab0a2e24b04c5f89c2db9b6890816e7305ca2c92a912636772ba, + 0xc27986848ef557c8645754b95ed9edc215e526d52dd369c0777d4f378465d03, + 0x6e2cceaa215aaabf58f2e6ccb3aa062e24e506f3819645131a1f846cfc24749, + 0x4ca455e242a91ca2143ae13d31d0ad024552abe39636c4215d7772512868b97, + 0x20107d5efa2baafdc19cdb78750be25074d5052d77309209d83feaf764ef4493, + 0x284a8c5b8405a825d8acdd215c16bc5170fb4c5460d6e775207047b109fc3e63, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x2617b4b39592cb7eb00834dfb430ac37e799da74e8ea6c2cbac3bff74f3282c3, + 0x260555fed187679e25946324ff117f1f487d75d8811aaeb6afb29e02bf9e9b77, + 0x29d66baa1db480fa0976c227b8be2b1dff6206980b543319ab8e6e46bf1af27b, + 0xcd6ba2405ef9e333036c7567e0e368109489be5791633c12042106eb0dd43b4, + 0xbb6ef374a10b4538ef1ce3c0cf6ef6c885dbc2f449892bfd17e82e7fe9890f5, + 0x294e76b2d0fc3b732ec3ed8f73b8e1c616ee0012b69d61417a4cd5f18f893c00, + 0x2a2d473497afdb60a7008c7dc7ced5a33fed7c5424bb6a1299c24f373e7f16ae, + 0x60533676e96c73a3e183dd8f585c78427c0cbe99e97f8acdb098889df1439ee, + 0x4d3ad331506308539d84de77d62f6cb661c870bc064fd3359cc711a06baf4e5, + 0x23444c530e318b22418fbca527fbf9fff0c2c92d623f365277d65ac7ab90058b, + 0x84a073506da63fae8ee908965d634da2a789160f1ff73faf58b676e5c914b52, + 0x6c1018af2ab1b629440d513a4971e62b2dda42233dadeed10e4629fb1e15c48, + 0xfeae12c9ea34bbf39373aa3c159e553dcf7412caf17269a6c9b7e9dc594adb, + 0x21f5f23b0e3f44f8768aa1ca35edcf5e919eefc9d9dd47e44efcc99694e51b54, + 0x6209e20306d5ff2ae4443bffed0948b2bab65487650f1e1f956c9e5413b168d, + 0xe981747daf6de6e6be60f7ecc28e84be0e4b7e8c07ad2128fbcc12e0c7096b9, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x20802f8ba4a922457a1aefdccc804a9c34b885a1e9f0fd94473479c74e6ae02f, + 0x19cac2ada760fa14ad038d2482dc86661772ae15de0ebe6a1a767082432bfdb, + 0x2c484464a823c43053113755869610b16e5116f2bb1f3e024d65d9206c3c63f3, + 0x20aefc9cd863f976e7e5f601102158b578357e3072ad22e68028640e5513b471, + 0x1310a6b902d3736b0a50a32048c81feb98e02943bdb12700c714bf6b255f3f6c, + 0x28a2e47b087e9828ea526825aef8a8b4d5a36020f87b4672c36a0b3bea12d308, + 0x2edacc0aa69661a65100e4686e467aba4f2c430f61c77707e0ad3c2fac66c096, + 0x23b811e8af4e671b9bfd2c2d83a00883108e704dfdcd7944fa40c20e72e359ad, + 0x36cf4860115229cc61870796bfb55ab6da45a3dd204e1e66af397018f34187b, + 0x1ed097ff6526283590ece731b725b9f734a7f516d6a8b1eabd4120c8d0fce65d, + 0x2242d9a8c934bd0f2b097e37feea098bb500091a496bf689a59b795c8d7469b6, + 0x2e1dbf3119ea622492c1f15dce5addcdecb3ec045028e9ad6a8bccc85a456ef5, + 0x2d034fb552635fa6bd63f5e91ee8d7bfb8a2f1ba395190a177b2bf1aa76642b9, + 0x12c8e6f621ed980c07cca4bef17af232d32c2fd7cb3fcbfc971947e66ecff2f, + 0x548b4a31bab4692a858acd30fe523c42e8f2dce046f2f121b0c82cf5bd306b6, + 0x4985d3b7fc1a4b5fbc70fd37205abe31e33c4beb6f13777967ac5fc07a3df18, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x176ad5e77dbf9eff47130906d9f295bf1139d3cf00fa5ab42bd3e10d357bcda1, + 0x37fc3c302395fca97bfbdbdf5ff14d1f71300057e7d994fedd19f2d779e41b4, + 0x67b7fa5f5b640eea5c1173aa40084c2893f0b66c4d8eedf9e48444de48cbd81, + 0x1ef50a9851144552374b8b175f1a069b99271337c29a94945140eb7e1a9560d0, + 0x4a8f411eae9b96fceee318a3d82e839354b0999e8354ca66bf7f11281c865ba, + 0x17c90c447cd83ef7d547209c4644ac95cc1017bd65360faf58a8cfb5210bc891, + 0x2b324c5a69146a0b1d502937c9f1764757d43065f7c3c7d0a7979552354b3f98, + 0xcd0a626b860fcc13465134f015336740cef85aa91bb7c919d4f1285dbe4953c, + 0x1f2baade720437f5af71bd826e87e155552a95da11c06402c76c8c574707de8b, + 0x1ce2ccd7a415304ac0e6f1b265590359f970553a10bf8df85a55eeebf5cdabe5, + 0x1498ca31f8887cce647ee52fb4b3a177a3d8256354cfbc83ef0349fe3685d1db, + 0xe6e210f18faca167bf3d82bf9f9e58d6e094c03b56dcbd243fa737e0ef93bb3, + 0x12cf450b5228e1b7823665a58c105ab37fb064d287b28f115ccd128cae7e440b, + 0x1fde1a9a7f3a95883481d25eda60225f3dd6f67b127fd2db690aac68bb53fcf2, + 0x16b2c4b1a4276fd90d0803113fda96bd017491d592118ed721b2660a5576b192, + 0x301ae24bfd116b2a5a8ab9c08fe26cbb20d111ec34b7f7b62ad4a95c95531436, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x887f2970f378099bd8129636f847065b81b3cc57e229d2d00a15f314f1b705b, + 0x19b3b01cb6aabb13901f8fb5dc1490ca360284f262672e7f0d39dbbfe0cf5e, + 0x1b3a6e328bf97c4a2bb7b62451d8d21da221d9f79dde1d20961a5730191499e0, + 0x170932e63d8ed05d6b66499f32e6261b8001bddc0ca176081b7fd35f9c2a019c, + 0x1899457555eb5581fddb51340488569c2b4adb0e7e6e1b59a36293b3aef835e0, + 0x164f7a46d01b3ed26cf79280d675584af03ef532ffca9b0aa1fa4c046ab9729, + 0xea2ffdcabe9727588526bbfd56012495f1d56b06a5737726073eb9aa7052aaa, + 0x7ecb58097193ca637d89cd708a6610e9bff056d5d477f0f0baff2fc922d0334, + 0xf47e601e82ed174b715554cd3d5529682511ac8dfe48cf7f2ccc1093a892d5f, + 0x174f79e424542b0e34f0fba0d6451539aa56c56f72fc1b006156f46a7cb7c2ec, + 0x1609850116dfde24d7cb5510912ec1f4bc416f9a5e57cbba8de63a2556af662d, + 0x10ab565bb9cf436914f214352b48bdb7457ecada07f09215c9522fc79701ebed, + 0x25903539c56c72c86dff0d320e4b89921f177b9be69aecca9e52da81175eb5c2, + 0x24be2bc0726dec8e7e12fa3a18808211b32d0725f4d6414911c250223fde21bc, + 0x5522494472ece35e80ca3ef35636e8e5265563cbe43e50a14d77ed0d9f894d7, + 0x2a9d37d9b9bec22eefffec1acf6a2dbdaf5054fd455c300a6763169d4c4c2505, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0xfb784243c37202b1648a784010d674f2ccc662e3e72dc97c1e76f0f815948a1, + 0x993e6aad24c4d252ac53905907ca3610ef2a5e6e48eb3da752bcca5dca973a4, + 0x15fab250b63506ef0b6fbe565b15ca337504a59617751f3e91e75891e8f2fa0a, + 0x22b851ba2d74cc07a36f73cec3f54f2e24f7a5ea54bb5356e5570a4e55ed1f8, + 0xcc28d557fcbe39f2da5a831f97ab31d4c9748a30c1c027286f47660fca9fc27, + 0x392cb28a2f6f3e8bd6f869dee34d83fd84625f658d2c6b02a6acec49940d369, + 0x223232ed91851f7027a7413f23b889f73f18f20ea91b308360b074250eb5b133, + 0x247502139fe5a4fcceafc47ab0835fab3778866a0387f67c0c11730b7086b423, + 0x574e7796304031aa15766be5b419486db72f2cc43798e8a8ee6ade15ea64cb3, + 0x1d18392864858785d134b2848d7fc32cf91da60461efc01731ad49bbb99ce7f0, + 0x2b927f1d1eacf0ee5d3246fec97f13ddb9ba2e34419a7f0fe151f8d366df48a6, + 0x29ca195348764c2600076d9a475508b7fae52d6a9c92196241ac3f08d090459, + 0x291930cdffd0acc873be352600a12a6aa056da7621cf3324e7636f25ef4d905, + 0x13e6e58779312fd8a2ed9368587b5e4c207cb8cb99621f4254a1704c41477656, + 0x74c6fc957511e7287e7b6065c03d55ab19881e2cabab988bcaf997d96b90802, + 0x1da0150f5a7104c25413c83f1edcd3dbcc49a91881af8b3809d40221bbe8cf09, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x17b4a6a22f90ec5575a31b71aa505b70cc19abc0fabedce5dfc7108bd5472ed4, + 0xfb75a413209d1ea511b520b3ad4e96dd0a548ec6d5ce2de9b0edfaf667bf213, + 0x7229fa12e5e9aec5a258249b3667fa5a1a7e9bf69245efdc66a11d4cf9d16eb, + 0x29344527ccc73bd6ae01d4ab76d7d8205643e8c39628e5975b0e68ac647e7dd7, + 0x2e06815f466128d5b0fa1325a96d6f63e513c3c3590f612d01f0ef02fdf74ef5, + 0x2381219c79d22ca23e9bb37cf7f3da8125510c1a9d7e9e26d028ad61f3ba94ab, + 0xf724878c378b234a5bc4fe6f51c000682ce95721afa4c802498ff5f4e3599d, + 0x2961aca4c9ed99dcc5db33902857ae905af926ba044b93d1b8cbfdd82de72c6c, + 0x1a661c53d875032769a8a89ff224b3703864fd77adba88076f9507884ea8dc0e, + 0x20d8c84a77dbf187d873feb492185f9341bd7d20d4c82d4c588009102389aa1, + 0x273944a60bd81f3c014cff9a5e1b1d99079a7db63860abdc5b850138c3ed89bf, + 0x2c3483ea9e8733bc2df8605d84cc2903a10a4f675f803e33090bf1b96d7b6f5, + 0x2c1570fa771ac87f6c1c7dcb0f5efe2ae8bceb26280adb11f1565bdb3234193a, + 0xf8f2bcada2b15807d4e400663abb7ad2a6c653bd3e27352d2aa03cfacebaa3d, + 0x13b356322af7bf7ed892859c3512f21831d23d6ed46bf4c3514762c2a468cddf, + 0xe8ffc445422b035202aeb459085298e5c3d52ad57a4e0c982e4bf6bc430879a, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x266878c7dbb3ebf725baf09bad62441c2a05a8cac838d637371bcb71f7e637ec, + 0x69ca7aea6fe25ee984031f308b491f2a550e4134769d30dd374c0c97ee16568, + 0x190c3bdc4ae56b9371806f99c5247c7f6071ccf725631c6f3435075889f34956, + 0x1d325902dda87290a07b115f3673203fbb2039cf470f229881c786e115ee6abb, + 0x1b2936a6bb1b221aa267ce939f99c211b758c2128f8d544c4d0b5cbc660fcd54, + 0xf9fff4eb7e28845be6a783736f297193297a7cc12caf5dea6f07b5eceaf6323, + 0x20e98cfcb657b1f49c92a069ca501f89e96d73ce0791edd336a7f5e129e5ea11, + 0x15ddf382f5b945869af8a3bd1a030c98d8350e73600aa0e8e1d4ed5e9a89b5a, + 0x93aa5d4e7c2e0b87bf1135f3f0d94b40d59bb293a582031adabfc2a8ab17bed, + 0x83ea048a2fab7aed31a80902174faa9f1960bc2531d18de673fa873fe688207, + 0x4849567874ad0253387252406f2d8860b26b6b605e98c874a585bc157c57a39, + 0x10315d0548c6fde9fd87ab4a523f74d3a5c791e455f90c34b399503fd9662149, + 0x29b768d0c1c037e2c20b133eeeee017166d2797ba47a2e647595e5f0bb433c7c, + 0x2072b5dd1028087414d36c4fcb845d4e4e719885af8f4abfab39fa404fc68e6f, + 0x1434175409254eea7c9b9fc3dd93314403e8cdd56f9cd48348198334c700fe6d, + 0x2da9b2eb148cca6790f4b12286fe560880d75e66bd4c64ef8ee58d7551ca56d0, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x16bfb5fdd4ef9b81e92336ef013f8430727960333b76b5eb81dad8ef220bd284, + 0xf746438c3f4e612f088a4113940619b5d96eec18099f5b912b816fcacd03ac3, + 0x25f8d85e6102bc16cfcb5dfe2a0a6850c4f7d045a3614908d332702320cd2445, + 0x19a23070f8afa08c4a0a2e8a1067db44e95847e5ef5337057437eb68b023ddbe, + 0x19e74aea657fd4206322de101be54c0a70ed001eb5a3b897aadb178cee98303b, + 0x2a32e9f7f76615c5bc2cea017e1e937997d33d011ca2c543dcbf08664f247607, + 0x2eb2f9782b5103cce27210e54c6d760ad28af00a23b0252a608ee0536525990f, + 0x324cbb7ff16c463fd8860a5c6719122702f8f055f721f7c2ad5121d03ccb6a0, + 0x4fb92743eed5177e7a4eec1917d48ba4bf2df9864f477edd9984b5a1b37d95c, + 0x232e90742d5251ee73e1e55ede489421aa4d9b7f731d9209e18ae772b1dbf163, + 0x2888b0287bd050425c3241bd7d5336708c1d2410434d0bb8a094320552499791, + 0x5e878a6e2dcb5fb6176345fb830caf6edf06061a452e94d1d49a862b1563411, + 0x603e7150eb9b06c9c0b94832d53bfacc98e26386e2de0047d289e44483331cd, + 0x40392b8780bb071d2acf492bc6c49d03ab66a7d7d1689f16a47160923d6303e, + 0x27005786e8d1cba94d005f8821f564a42500562da999b4c40163fd15d20a7188, + 0x2f6ee6456256df4b7b4534f97dc725df7d9e359a8af4f84035db5ead72d85594, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x249d2e3a72d67b9ff1c12f00d2e2d15213b2c3d534ee1fa7e0726235d5f8a76e, + 0x66af81c271fdb20f0f7947ba7689567fa0acec8e8760311b200713a3cbf2915, + 0x2d07f33cec08d772afc8a847245583d60fba733b2874e3f14d59770a6eecc1d9, + 0x2b5752992e1969c88ef2bd4cee7cb74d7af5c73b2c43c148d47c0094163b7a03, + 0x17eed7f1d2c6c6d5a9ead4a939871196848682bc2aeb713409769599c6fb99d9, + 0x2b0443e7dd8fa52629acb60c4d9f489a3b485f9bdaa3049cce07b90494140c99, + 0x52e92369cc40d1c0cfa00124ea29c928b85c7b64c1b5a9111c07a33d28cdb7c, + 0x2d590ad359f3f6d0aaf8317cc35b62d92b05b0f5c685cc8c3a369de6d1d1ca99, + 0x2983673217a3388ea6ec1746e62fd0c1d2b2d774e63564ae271d77dba331817d, + 0xd5ce1123b37edc685e8c234f618c830e87b1b95c108a83cd9d5065ce002130f, + 0xf9b69256d0d0e083ba08fdf1bcc73a95b7b378ede36d8066cb024b8820bb003, + 0x290490f51237cd7ab3824f2057a7a2eb725f946442c7987f7392e4c85e8dbd77, + 0x2bd1c921b2655ffb99e5a5de025d08c692fce4e57a3c401fd655e2d05d92a653, + 0x3fec0bf41ee1a2c0a7a0b7ce73053431a26d2b7db92d42a41911e6129e3fa9a, + 0x2d6233e08181a3c9db09017c0160c2ef359139513990884baeee525b2597eb81, + 0xfbc98b8d3b0b6f2b8eb1e780db16d98ef5d4bf4e65ca518e62dc72f693544ac, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x1f04cf1ca4f6db30e843ddcaabd4cc71fcda39b55533db1a8b61488aafaaba74, + 0x1a6f6a78583cddaa58898327f4ca8e00ed729dd41c464fc9ab0c5e0d1b2e9bfc, + 0x3e70e81573bda5c6ab953bcf41581cfe4c65e2d3c04cf1ecf43a2c8ad250d06, + 0x13fb5b6c8df4a5257dd67b782727d8a7d90ca92c5d9a755847a1d3b6b71cdb90, + 0x4d54595c25b41536d1f203e1a367acda8feed3369537ca2557f5da49f290e84, + 0x13671d8ca7ecb93d29c9123bca96103e22f68fc5a16968fe903c0f30e8bd0b44, + 0x1486a9a8302df3771d974c562e1b03b96daff1e1fc6bebe86595d32608a85bd8, + 0x7cd279d7d44931e437f59bef5027f14e49400b0847f4117c762ce21ea66775, + 0x2358686de458647dcf3873e187eaa940fca529dd9398d2eb002a1e6f0878ac8b, + 0x196d60cd8de82119c9360e9ab96b1bc31029ea6bc5a9c891584febe494ad5d53, + 0x1e18e5d708702aec708672582aebcf2e4dad6be0100a7d84f4822e156f2370b2, + 0x18d0a6119479f34c41acce9a1086c6b1a340a3d4eca4bfa561e4205eeeb8438f, + 0x41e39755ed3b12972463551f41d5f1739433b966b759014bdb9d214ad9a6fc0, + 0x1becd98d1916cbaabea2082b8e7f1765f838f2337121baa896e437be5d4278bc, + 0x2d11307d21979b68119899fc08b91e02822cfb7c49ce878ac58584913d6c8a29, + 0x24b7d69ead7cf1c4c204d6d3e23368fd40db0f2df00a4a8388557b6110917538, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x1c414080171ef43535efed9c5babd2275b89e5b175f3b71314f6c59040c97808, + 0x397889b8011160475bb4d6d3379351bf5ecf90800b9cdf57bd3aedb21053cce, + 0x24ca54f1fda634f9bfc0e39b0d4d6a738f7a012898e9c2bfa4a42ed533e52845, + 0x171598e7caa20c990e43306d06b2fbd5879619ac63904e4395a53ad5d60e60cb, + 0x305dda5b8003c236ca1d724beb0335d07aa3b2ade1ba21c59dd763f3019b5ec7, + 0x1ab2ed07578120b399df57c5f109a40e47eaa956e66a6629e1796bde7174bd21, + 0x2a47862d2f0d0629863c878ad7fe7df592ba7f8f3f94e5e5a85aca3958229f76, + 0x1bbc9591c66436dc5cf4bb562468584632cc91a200b1f08e1a28ae61e5c30abe, + 0x265e971c9adce13dd324bc968020828cca064ecf477268ab534265d7e5e2ea21, + 0x1df96d7436aa2918ea082546a9e3e149130fbae6776590846e0632f3570657e1, + 0x10a8c8aaeaea0414d87c0c1553784b744ff2e8965942d3828e14c484f84d2535, + 0x63e4901d2d6197831f94a5ead9b058847ad67bcd8514eda44ca69a0b0ba9c19, + 0x1af00487deaaba2511ec6bba34b8f248a5106b11d69cebe26fb5f35d2745feec, + 0xceb1792ea63e2bace5b317ceff4597ccf3071a67199612396650e8defea646a, + 0x7fc963b8ac37064379d5a652f999038ee4a250e0e3948cba3b899840a119387, + 0x17aa663de33227a947a00ebad16999a905bb2976d0c997a9a5a9fda6690754e2, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x27e7f01f7e5850decff3c8f5c3ee53951fbe076ca41a7e1807cbfc4b8eedda63, + 0x13e9c09190f744dc7563c578dcf432de2522b7c7f995b2880957c5d2c54b27eb, + 0x291cdae728ab7b72e119248c0646d1a7c305afcf50c9dc1c1eaacdc9660d21a5, + 0x2df268da059255b2d959f934bc217781108e61710f0e3c460419d11f1366f45e, + 0x959f13f2c04b17e795093b408f590b85f707e54795f5df80bb57b35c994dbe, + 0x2d83db369e2b48848a27b55553a8bdb77e067a93f1f28db9de6c65b14818558e, + 0x2cac7303cf0462f21c4c154984fef173c428c47215feb2c0355c15de4dc64ae9, + 0x1f16c3b17497d87c65b61123d1954717fff18f21ccf4c86b4ae27444b535222, + 0x211a857b06dfe2df621d3a89a4bc05dd0247add6ce13502fe7fa37e63888f7db, + 0x1bebd0b81ea6cf89919ea765ea6d04d035d73cf7745eaa757cedfe625d10573b, + 0x2cb676f0cac23cd80bc40f3269d2610fbdeb7f20f5a74d72224525c6e3ff69e9, + 0x1e478ad6535f1ecc579056c6ac6ac8744f8e35209b7a081f47a5b0c33bf144d6, + 0x1669c72208abd4ae25158c9c73156e966504dfbb6a4bf9b6fe37a1e1053b049c, + 0x18a94771fbadbe268f58cc38e48ee81e3cb5a94b8b2cffa8cadaf75a171de693, + 0x203411c7e08bbc6a10164451062b19e131ea52d02dc1588d3591c8abdfe1fde6, + 0x6cff9d23d331be245ca3ea0e37355132a367f5ceedfd64c842dc9aef97651ef, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x167961cb9db6a7f1e253bf7c7d0711beed69fc736276820f1f7df8cfd1305bf5, + 0x251b413e3039cec0af54ae9d0dc7ac5ccf5feeb9ccc482a4a4e93df5dff6eaa1, + 0x22461b5ae9c4937eff6dd0c2ad5475f20abd4c5d13aa3894f20ce1ceef0511d4, + 0xd3c8cb0ca400d52f3eb96f6e403aee53c9e2283a19826f9b770d5270d3f2316, + 0x14fe9ead6519febc01088fab56bdd7826c35952169e8c60782ea746036fcef1, + 0x9e8b9302c470b946bb4e24b13b1692266be83cbb0f833527e1971abc11676e5, + 0xaa736ba6817640b3613ce5c87cac8f64ba74ec23f8f5c75f0cb1dd2ee552f00, + 0x195c4f3bfe08a064f19d6fbb6690f5f723ccf6851db01e64dce49b82640d624e, + 0x10bf96df637b9926a92efe91a6095501db10b10b9b8207e73eecc3147dfbe14a, + 0x6f9ea58e02e97445f704f68bc535b1d9d6ecbcd4d151bf2bf9f6bace985c14c, + 0xdb1da59cb0bc70afbd95e428861a2b708b9894749a2a88e62520a767c4e6d48, + 0x41dc2cccf102bb7168276813ff0dd2a3ae59f4f35de8aa1404160be701d566a, + 0x33b21d96a57d2c1d44c1482289bc607254a0395fbefa3bea25983d6e1d70893, + 0x27b5df4b4bde32d934353e58dc214d02a835318804ddb812a81effded6706985, + 0x16c436812dc3bb29c680d81bbda2fc964fc0cedea2cfbe4f9f0bca7451e2c26a, + 0x1075ab0069e8017ef2b84b9034c0e4e981de009440f57ffc72ac633624caab5b, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x1f158c6c1065f78b5f780520f03c584465ffce26ad183a50e11efb956a8ee412, + 0xbe6ce6cad51b6bc14791f01fbc62bf26f20be46ad5839ddc356afaf24dbb219, + 0x226643746553477c60b99089eaaeac4ae64b308a3c56ab343e55a6174922306b, + 0x2e82b3412adb8919fea66a8e2c0d8c5fb6376944728224b79ee3edbe56334e2d, + 0x25af6deaf2918fe03edb3989dc037a834610d69bcc3409e13e7fd657b6c404f2, + 0x10168c4b7ba5c85008a4f87c0325d238562951366b754259c06402e69422398f, + 0x20441555acd94f03732b606acbb25afa0e3cc39c7f0602214eefb497b4a340de, + 0x200658fc08ceb25b3e1ecece3989b682546d415f3eab6596fd7f63a9ebcaf3a5, + 0x8dbbd95a7fee39cb863987f4a9dd8c40ec8c1b94f21735819fa9d6fc524547a, + 0x1679802a70dd63806557cd2d8dbb8788a91dfc982c672d9c2df04efdb12c6980, + 0x18b5ee46c9ef30ba46b5c242bddd68c8a1f891122ec62eb0a1ce4e0efd408297, + 0x1760042648d3c88f3800bbac32caf5e5fd6b808f50af91cc5d834f3aa9bd2128, + 0x2bc24aa17ef22eb5273e6812a0e597bde1cb74b65fc35ae06f09358d966b243f, + 0x1871a1352a74bfb73dc35b7245903c1906a12dc3d9448667225b1d61a83e8cc5, + 0x15ffecc09ae5dab7e235644f38c84af5aa6ca42f2d23b64bdf7ec536f9e7d5f4, + 0x2c9c4d817a1351cc3f659d10453598cddcb7369f9f5978f44025b9d847935a55, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x258f6b7174e2619e3c94d65ab10273d210ddb46eca06a22f81117fe5f02bc38c, + 0x7b65580ab28befad1640084a12ab11bde32586ed38470937985e2ea07eebdde, + 0x2251fd1d0a5bd91d3f958b9377996bfb6f7e777f3b2a3bec54befd9a19b429a0, + 0x226bb0f7370463f705b99cade44a76fcd63a762a9685f7a254d9bf67d9711d19, + 0x125b1f6876e2cd4548eff5a6ea0598ebe43aa0748cfdc53c83987489c871d0c, + 0xd6400436f874ac40bc4e3e392043675a8f8bd071e38ac56d630f810a6c382b2, + 0x152557b0f424f9188e7c816e36f83ff9be71abffa7caea38fe42b0b7d2731395, + 0x2419922a2d394b1837d8687453eed9aac005a6128ae835110a204cd57663f4e5, + 0x28de832e55c53a37639618510388ac059fac106d2833311efd450dea8b112d6d, + 0x19e9bcba7b55e568c983d797460754fad7f04c39a4d078a0faa9868557f34ae1, + 0x283908c8bb48fee64ac955e7fcb47040fee47edd7810e5ea26e1d9bea337e1a7, + 0x25c8ea766fae5e6a1a1a20af4b178812c0e3e38eb4c5c2340b1fbf4468c9bcae, + 0x18cf37ce25ef86d2f7c9aeef0e79f0abb007fee6222e9952c9f734480bf974ab, + 0xd41106aab9ca69696aaea2184622f814fe087b12f716e2dae58069776e1cc02, + 0x25a1462f1d5a2353e1af93865e7ebaa573bcdd2271b268415b05fe113c8851d8, + 0x2d96abf52f1de16d6ed6d4d9279035f5bf5b825754dc21d11feb94e3b1700cb8, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x18e5610502d2a1bdca2d2cd38baabc9fd641ca4e9ab4be237ad32c72dc880c85, + 0x2bc2a1228621dc365cacd7d5607b93181b585843070c12a7abe98c2ddf0b8ce2, + 0x3e57b7e7ba3e4e3caccb663416bf20ba7df9fd5fa25d95ad29970a6098b5d47, + 0x95beee076b8de68c794636c1a75a0f1f79e694e9470af6557dd0a756ecec4b, + 0x2063d0dce7c0e4dcb6eda83c1d2e9d2f8fb7d2754b2a116c80a5fce17ecbdfb8, + 0x2793560a50cb73953010b7881649cf034817d3803411649c83fe7de6c7dddd22, + 0x927b8161885b12371bed6743e7f3cff4e26596f26ca6e10ef9b62824c6d9408, + 0x21e570ce0b93102f53c6621c813a62dfef04444d67147e86bdcf6d89982174c2, + 0x4da2abb8299af33e497e76256a8829bf2e90fdd6e170ae91514dd25fef2450, + 0xaed6f83384c5c1b36797223e5b98e0dc7e322b205d9946ad59be72a56401995, + 0x1043df1375a10cac3d79397e2572c2de5910c9b0cf9c8a36a8597362e2cad2d7, + 0x102b5227284acad6650de094677a51bce725c6da6fc1043a7668e939829a5593, + 0x71b883401c25bfdce86be56ab497a10814bb19804c57834b4eefb6990b0ca4a, + 0xee706d85983efe15078748f8f19a299283737b33a3c7a74f3c10d2e8d938fa, + 0x1e3ea0d9146581209b7018ac5660e20c5033641c101f09823d5f305220da9b2c, + 0x1135f9d772fcefd07385bb7c8b5fc0bfd38c1c41ab6de2da8c8b3bb3dc6ba093, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x5580932f510469f70096c820d9601ad87ef2f66990c8e6eb98d6a6dfde27a7, + 0xc072aa3c1344e5535661baaf0855759b2489b40320116ec0b304f81402a9a73, + 0x2c5e60d6d9cee50f3880234e54b391aab138c81550ffb9cf7ffc83e118fb1612, + 0xea984db0b29d0ceeef9eb065131137d696b4dcbe9b29e12d0bdb74736fa3cb9, + 0x1461bb4b296851abe76ef1ea0df56b555c76879960935307fce97eba31a58550, + 0x217814f2d889b58d9728a46eebe679760022e1d564c5024f6b77667d3a31838b, + 0x2e34b63991a98aeef1161f9c02adde896d1be685e9887af5ec9bfe845d2fbd25, + 0xbb51a53298cbb5297405c865b6ed23804c9926319ae9c5c7c1ce2478d90c59c, + 0xf0f1ad048e7b93df29617d62561ac209b488f58234f3461286e592f64a1dc90, + 0x24856651f6c6c72ccdb29fdf1fe0a24388247c5dbb8973c1c87f3a933fb1a341, + 0x13161ed9d7133008bfb93eedf4c667744c0df4cee0e0ad9038fd0968f726087, + 0x1ff88f2a80b4078a90df72d706725ed9e450488f975fd006196208e399d8dec1, + 0x2c300ce9260279a67bded94acaf125b7c98cc2208455fdcbff7fe98165c1d4f0, + 0x180152334a015c3e7d433b92f0ed2365345ba1b3dd06e556eb6a39b45b924ba5, + 0x1469185941b34b5a4f529c1b5a724dfac28aa98c8f830f8b1045ecc65b787f4d, + 0x7be7c3b4de9f53e54e3f4f871cf62f4c7720d3a2e7baccb74924faeb3bedf89, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0xdbd81cdf5b54b534485c26ecf29628e9e8070fec90c34b780acd5bbd4e7f0c3, + 0x1735ed9f6fd2ea72803084da6d7e20c4735bf3de68156bdabb3888dd500476b5, + 0x302871833d038dc61a984da78e5037234c7b2f114e495451bd388879b8ee1532, + 0x5bf32698276e20768a54f9bed48935b674ac85bb3d9251e1075207c1edc0060, + 0xae9a1e0aeffd431594e5745e8f4d3e5800361e8028ea0b4ba98419fb0fb578, + 0x2b98b2ea75766211d9a125db8e6e7fb4a913812216365b1f6d2663deb1f0c19d, + 0x15c0f1926bd600c94b15ee1c00e0ff93c7de8b4a935023bb59c664fe01f30bf8, + 0x18f86036c6136aa605da0ad3d4251e64ff31cd436d72b90ee5d3157af6d79e40, + 0x28542871e40749022211b244fce0bd160867865206c873f6668ec51a429f9a39, + 0x2432259e7f4740024bfb2b71fc694fa8460971ff8869fa46f539faf994d23d42, + 0x2cdbbb1f729d6ba0040b0fe63e0ab2e24a1ed05f4c2947f2a4dc78d49bf68617, + 0x1f7d6c170f7a83d6241fbec95436b20478184b02ff7f4cef3deccc92da64b3a8, + 0x18e6f168622d4679b6579a5bbe6419d8c868d67294944f8246a81415b30e6119, + 0x9a3e52a4ddb98644cf4a701766c1ca5ae4a35ef1c11a017dd6aa11945fa53d4, + 0x136a031823304ab94c93e3bf39b189e240a81e0a42b6060e38c7c2064b8148fb, + 0xd82d0c90c41c41fb24d7160c8f1708c258222ef0539a2776a20c742dae0a624, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x2b0f98b255bc9fbaffc4b09dfe423873babfeb16c64a31d8f7ba70db133e8425, + 0x137ffcc374ae9e222e733fdf9d0c515946baf3c1aeacab2c6218180eec5d6a48, + 0xe6a056e92c767cd1fc970b338fa5c7377240432e6bd45aadd958d48f15d6033, + 0x264c9a5c6eda708da60f401ff1171c9ea279af17f1df202bb27cc56773a37853, + 0x1862618d4abfaf9e176dff2dfa86f1b94e291ee3e02dfea816637787edf4f37f, + 0x4d0d2b042b8d971610b3b9433f373d693a306f1082186a35a8ed6a758e0c11c, + 0x8854bcafc5f356516b2df46f5386a116f14de1b197290316d49869ee6dd0187, + 0x4b8696c509d9557bd8cc6227caa099f002c5101ff6d5b7a4e48284e31992562, + 0x125c58848e89261172f9ad256ef6cb755841d2913f2ee2ae9d68fd2eefa84d9b, + 0x181ffc981c54778532d7ddd39ede7dd3e54d655cfe6681b049df6d85f76439fe, + 0x198f1451b611973be77cc3ae7c744af71b1c94e3e87056b7af1e949e92cee5a, + 0x4c9f885fd1b69729a871eb611c4a9ef1e009b0605a0cc3befbb806701b63853, + 0xaafeadc15dddce6b214e3991babc93af04e3c6db03ae0e1408a503e1eec3433, + 0x225622d35902840ed662b3dc9480d941545df10f2f1a8199260a65018d7af93, + 0x209d4d14e8b9192e061a42f149c09d0c9831a1f02c35412f4563cfc03304ff9c, + 0x1192a624780a6633d00dcfc49ab6cacdbe3d4a62f6c7d8abff6094a678714f2a, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x23278ece68d054afc53c1489204000d720cba66a63842ba7269e35e0bbc6d14, + 0x9177ed9f3f33508db8be8f15b53360afeccc2f208bc7143bd226b4c885786ae, + 0x175a7d6713e16fdb34e680606af50037ac78419ba5cf0dece2aba5d849184975, + 0x1bd2f6eff3f24489dd492eaababe1b0c09b50e983658c1dafb2bcdb69a724195, + 0x16b53ba34c5215013c262d62007837ae1cbfae155bc7cb3da840bf945becccce, + 0x2c062183d49d2fd7140548607e86ab487b7a6f4da0109dc8b37955c866ba91c9, + 0x22451ab479c09eecc408145baafa7f51fa598b3ff2d057365903ea317ab9064, + 0x82f7e3f789ae657cef0f342c994968f47fed29262d4242964e0e793edd2af9, + 0x11139d29901eaeae25fe8a6b8b27062045be218be37844305ca3b7e348b0438c, + 0xcbb2e8c216cfa7779e8085a1a8b24ea1ca6446a664b48d576accae16c0e12b6, + 0x48f7ffdaec0a2144b28a00ffeb5b61300386fbeee792be38552bfc8363561b7, + 0xe0bba24d78116594570dd93a932c82b5b6730cda14170f58b73105e29fd59cd, + 0xa4dc036fd4d9bc2561d3d0c35a0222670c59e5a0626e36811b56646b345a0bc, + 0x1a1f2f87b5b4221b764e44a68abc8f56f6a97936fcfec06a3022ce00a3017373, + 0x1dd702226b6b31fede8c6b8067fd51da81ad5b970b023875c1ae5bd2d56cc29c, + 0x22c40118e01863b586d4bc9b2640c4f6c903410c17f5bffc7032420d494d5058, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x18b43cb399d143c97d4f8de9fe9c4aaffb6dd3785d9ce5dc9651b975b9054167, + 0x12c599db262111be3d9842cd39f3a6f34e51abe1c1bc0711e12f69c3cc973e7e, + 0x8bb47ee7a3961cbb9c94a68b2ccd3cf4ac95e8836f7538addff55f926bf496e, + 0x2f5694920b9644b4396caec1b4c4150eb46a18cca0ebd71c4be28cedb456b39f, + 0x307bc951cc2c9d4eff936eb6098bc1fb25254728e3906bf089bced7826fb137, + 0x17bcfa98efb68a8236a23a716d27b3cc4539c8e79ca9026a9b5423a6442e2eda, + 0x14787ef740948dfc067ea4f81bc1346453f77806e6bc39e3defdaf82eb952e96, + 0x257a201998e59bfb34cf5494e14c65dc3f2fad4fcc76aa9dbaefd0005446972d, + 0x12a8d99dd91ae7dc9bd892be2c72d980ab6459d3a6fb8efb96a54dd414906257, + 0x200bf208f11f7a4a4de085188220177b52da270fcaadd23e79e9e879dce364c1, + 0x1a9f530729b8ca369b1d5e6937ae365f01dde06c24722bf111ce4ca5c764cb06, + 0x651d7f9fbca106c4e8b3b5a1ce48b2db6bc1657f7aed28d952e28711132c0ea, + 0x2a3316648cb65a090f0faea9d38323345b7d4a91a9587a9e8d1cae632896dcc9, + 0x1553ad82056a8d74b3bb80bcced6a7779eeba7eae923ca8b492b9bdae81110ed, + 0x130aa152e81341ae6952e6732a315d1567f3ab12cdff38449e42c18ee55e388a, + 0x2162c9c868800aabd5be303b798357d4530f56e0d8c94c99e095740337911cc9, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x138ee349a5126b8c59ffcc05c3e58041d520f8cb80be3db2d0b72af7a24d090, + 0x2e59364c831ea593aad5fe14da76a1d7705b7af94f331ab85362c4b5943b8b68, + 0x24b0f5945c543f6ca8126782d2337ef8dc930a1b77c0e133c6fa94fa2a19a462, + 0x2d8f29c644853834a8f1a61a8965a9890fd8460a82ed2520a9fb332e6a22b983, + 0x1e408424ad586d58ca0a0481dc08b8ee63f96c838175dc8a652ada892c293dc0, + 0x1cae05e2d2ed01ae5077fea699a2119531fc30938a5ae2c55ce656b6eef33b8a, + 0x1f0c1735c782a57b3049ebfdb7de3238a608fb6fa9f89bdfe199c3df1c1db15f, + 0x1c9b672560571e96a5590c64c2c5b799e1e317634d8de5b731bd7a51a68d5d4f, + 0xc6e7bd2073ed42eaf2db5a728b6d4f1245a87e614b322c25fc51eb0ffaa6eaa, + 0x1fae1dfd513367218a20406dde57d573c62196c4e12f5347ef486102e809cef3, + 0xe408e6db3d016f993a53e864198deee0f2aeb8309bd66f33fcfa38f401c780d, + 0x2684ad738e6116f3db8dcccb6c61cbb27fcba040b598ded972d6422299e0c09f, + 0x2ccc5b6bf5cfb7ba1e8a89e76404ba0067c3d817bf3ebfbbe4635a789c7bf067, + 0x2e3dcba12acbf09be187f2b4d453be5dd4f3cce2994f18cd1226c63de056e868, + 0x23e70e3f73723a94ddfcbba70771ce2f5a4e15b4a8f51b2828c05cb07ad2a19, + 0x169c46ee7bf4e148cbe64b6cb8aa1abee9fb5fbb04997f18ed315345a8594c5e, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x7cdcc3b6498adde2756987e13560d7664f1e805180ae0fbbee1dcf1fa417d7b, + 0x2d9b8536ae52537df2579df0ff0a06d4a99757ad71652f91d3d724b4eb970acb, + 0xa1f0085c5a9cd49df855b92dd309c3681293e5af0417301e9e5e68d1b34128c, + 0xd1376badc16946a4a5f324390a4c6fb00baf670827048805a36b06357c39c1f, + 0x106d0427df7fc4dd7aa26de279073df7fa15370084bc27e16f5f12a8b01551f2, + 0x1cadca4ffc5bd9eb861f7ef6e7ba8aa20d7709c633c90111b98e094af29df8c, + 0xff923b3ab95cf5a3957cd89d03319b4bba3287807830e11073542019971eab2, + 0x1202a33c0359b51491e38826ccf21bb0c545e660b3da916ab91b0e02e30484aa, + 0x11608aa64cc3dc635c119d0691f46b0a479e142e0532f9256d3414369f5e3010, + 0x127d38a920bd78f2b5feba943466e85100ead21ffb0bd048683c7e7ba457443f, + 0x21f792c3d068276d10650a4ef8c8e6101d763990945f044ebfc6f51126332d07, + 0x1bdbd707d55dc4709b586695c5708e9973eba79a19d6504181cf8692f7f636be, + 0x123ed252de9f1a986305fb990661544d1f0bb2d12e3e5abf36130d680d61450c, + 0xead6abad94e79729b5e708c60dca274356c3e5142349c43382984d4df096650, + 0x21eb504af959f21f9c7a6b50a58bf5278209a2631dd62bfdf6175af8f22b3c0a, + 0x27a7eed4d44ade3583fbe7ddd6fe43796ab32266aa3f4ee382c20b99debc6e1d, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x1462238c5857d995aa2c7ccdbe788cb06271537ea1a299f28c307a825e8cdfd2, + 0x20c2ff1b99b7a949739ea108f5f462a0aeea077303cbd515bc7591ae02a0d43c, + 0x2aaa992acebf67c5ac50fce7824cbf41e6e5a9f87cf42926fb964505ba60c198, + 0x2797fd373735895c3192ae84ed39007478a4b3435d8a497549edda3d559833c0, + 0x135eb9d0101c2a78ca1b03ca53bc556a8c9af537d77bacafbff7f9bc66be9b98, + 0x2f594669789d1b805b611c27ca33a5a102ca3854938369a172c78de5a4083851, + 0xb8f930192502857b534625bb6ad2ff73e94ef4db9565a7de5c513f46fbc3e83, + 0xa520b7ed463311aa8ab8e7b8fedb2fe271214127264cb3a0f7a32d0fb871735, + 0x17198721be91de95ad64e64495b07d2dfae45ea67b2c824debefece304d25858, + 0x12b591844eeeeb06eed46691ba7e1bd4d6615d2aee6f1c040e6334596ee06d0d, + 0x2e1d81aaa4a22d294a4f57ca1199bdd171c6bdc0ceb9e9e4f7371b50bf3fc969, + 0xd18e43e3b9d5671e7f8080d1b451523e655cbf183ccccbd58793628aa689057, + 0xaca56cd420446d0f57751deb06906cca2c88c5bac6d35a2f721702b1bb56c53, + 0x18370450204ee070cab3e252535bd279023c9ade36b971986e9f4a821bb0ca0, + 0x10717c1af2308a9d4ae527c637257974d71bf361d742cccfd9cbeefb04120e56, + 0x229af48ad01840fada729de64d9ac6c4e2ced8d16820f464b60969310998be7a, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x1f6027d1806f3db36b0e2918305ea28007622b62282d0aa7d2d1c38bc3a14580, + 0xd023c3469f5337eb7ad3f6a1a9a3cc877415f1aebb7e9e5a955ce93ffb786da, + 0x2b7436beb1e205a4e723df370f2c669857eff6da7fc85771e7dc8256f511c547, + 0x2cf4f5bd0389a8d20b9cf97d0b2e75a429f36d01e1a1e6a9eaebc6002e6d7f27, + 0x2c689316dee7e23d23cb31070bf6225d9cc562fb57e3fbdcec3def3143d073db, + 0x1dbe68dff3088f0cb02990e0c030039e116d0196eed2410a30e91c08cbde3dcd, + 0x16a3fcc3080e28463fa4da66d305d58b74885dc099dd32b159209361fda491f6, + 0x2f84ea8936e6f0e98529bcd5d666e87d8c7e68aaa1787fa673b8920669b10a6f, + 0xf67f541e326dfc3555b54a5a8089013085f3cef05dcdae0666cbe4d1476c1ce, + 0x22c68a5cd419b439a367b742715697ce0d2e09a481dae8751d7c7726837211aa, + 0x2063328c09ac22652283d91a52d9851b919051815bb5ad070ee015040835b157, + 0xe78527a4658f58dac40430d4ddc9043ed3cc910a8a0e30b03ea904a781ba8b6, + 0x1935fe3bceae0bc5b8a13b073b2678048252e77d85f393f84a1bbf1911b41bfd, + 0xdc76ca0df681fe5c3b9ccebaf864ae495c8f92b48bb3d9d40274154da97286, + 0x119aa817917a73d46dec3e58fea0eb8ebf74041c1b069b1a83ad4856b1809ef7, + 0x2aa46d04f1238c646746e8df5bd0cf9dbecafd57d5de4f743fdb593379ff138, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x100148238e0ea61c5b6b81fba32193d55597904d4b1220500edcac81ad52f68c, + 0x8243c72e44e0114151fd9b102eaaa569fad5df40df83a1b52accee13fe49fab, + 0x156b1e5836f0f59be75c7f198a5d153ca30f0b79882036489937fa8c3b6d8323, + 0x2c0e264b43ed6c4b0c36fef6aaf1aaed9091f35a830550ac4364d602bc9e9e4a, + 0x534b4de30df58163e970ffa0ecef0738a9fec8c0ec4e7d9d15a666a16f45c07, + 0x4dfc3e86105970cac41059c73d5f2ce55b16f40cf638a85521ff270c6e11e29, + 0x183720d9443c6a59364afe5312050095e335b211598478c7b005249e89ced914, + 0x1dd461fcefb3549ba9a151df4013b323b1183ebdf913126b53003e86c08d99ef, + 0x2656efdbacd1d58ceac9a0e79d35044753ff9b7f6dedbbc6d8a48fa48028fb5d, + 0x2ef319b13362ac4e82896c082a6fd4a64b9cb25efe1e0f5068deb6fddf95d02d, + 0x13e976b891949cb18b46fe1130d4fa1b16342e954779fdaf98258da7192b9c91, + 0x8c80492d0cc609e181c3f9d8e2da90f68390facc7e468d29d49ad9257f55c28, + 0x1aa3c7c7a08d082afa7fb91c6f1c9f989b98f9619b56dc62c7ff1e18c6b72c86, + 0x1d115ed240331ec2adbd0a398df0d4dbbbf2f6392bdb03085e088d60d7f02ba9, + 0x1444e0fd467ba09ef9c1c6ce9a80b4e7be755d0e9f81a90f74f0ab7d110015da, + 0x3ce99d4bd9007aff4e13c2679d14a31d6467b32827e68f234314d3013266217, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x1129b914cee489016fc3ff8d20e2be4c9abc873041ba82bb7e7781e976961b24, + 0x21dbd50af59bdf352310dc018015a605fe2dfe0e8e65ce1feb72f2972b985640, + 0x25a5291beb01d9f13ed31c588755e56e5e6158b2f46341c86eddd86aecd52d7f, + 0x8de172c56eebbffb029ee873bff13163cb2d06caa46108bae1dbb2c40d22216, + 0x1dd2d55f238308639169dba6066e0922ad620678106ac7a1091b7f7ae0d3090, + 0x189191a64c9e4d960a7f281e378669034e779be7ac0cdc6e4fee4da0659b04ff, + 0x141fd736c823aff77ac2f28632342c25d14a649b026ef03f36961bf4eb85d4bb, + 0x113a24d1bc9d10e47f90f308781ddcc9b9249d95bbacd113d88d5a6ea33721b2, + 0x8f0b7b38b133684b73d01fc731f895bcb30ea14364715ea92920501722d81a2, + 0x1bf14ce82aaffec31f46bdce8d22f3baff0f96b8bfa00499581fad99e61f6076, + 0x14b7be33a41e00d0333a0917a729539fdb90ba42f12451c63de66fd411f6e379, + 0x2107e9e2811d6ac968dfadd3ae015e3f71f87d0c5d5c5ce4f9f7c66bc92a3931, + 0x9e1397c5f39d763040b82fc2be1a64262cd5a4d9f32491ada436ce437bcfbea, + 0x1d1a01986546a0812d3a4dae34ab33abe9cedf2060a4f654c7cb05d1298a03cf, + 0xda3f22ff498a9cfef80f63e2c92dbd95928e85463777018a0d3204d1e50f38, + 0x25b74b90af9818fe0fd8fbf33e539dc037a45ad9f433bac8dd3717b64600b622, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0xf3d58dc69226c994ada311ddd4f11174b51c490cf3fdd93047540be437cfc8c, + 0x1d948e7f1fa4705b5ae3e5f030a59ef966fa374f1d6bb87fb74d57b76f2b61fc, + 0x224176ed89ccb581b45f6afac435d9b2fdf08a0f2622a5a20c2ba4ca8738fbcf, + 0xf5cfe8147eeb9451b966cc087d2a9927396a83cd407d7f22afbea6ed6313ad5, + 0x1b73e95446d5beaad0bb2c324a27dd0fdc5445ea8a553289a88cd540a7a8a633, + 0x1b0f4b75472ab2e5ad4482742bcedf3b45d90177dd52680bc781786ea3e96be3, + 0x2e189fd270377427f98adf8a3f49917ebddffe7716ad08db78761da20e671fa, + 0x7c0a2036465c336f0fc397665c86a87ca0173ee19696b8fe7e6075283e5f0fe, + 0x2fb5497d60412c8bbc14b961d96bcd9d2cf82a25da250d7860453dc0c36d3760, + 0x25aa324c8bdacb11e81d612e258814beb13dd01a7de07d57b721a6c83101233a, + 0x29266b9fc1cca7e41d3c58443362cce77c81557f56e3b2a9a0e3165f38fb28dd, + 0x1557e3cbcfa7fa080014f6ceadf2ddc22cc1c6debade1eb605d0cc2755268dd8, + 0x28ad3d8ba97896df26b3281b73de59d9d3a055cf84e24bf4b7cfca4a6f18e1c, + 0x27692be22a3100758923b4b09be3c0e1ca34c62eb2875d4ca2e95199ef57e13f, + 0x26cb523869e976355b8b2ead6493c3b1af3b24b9f619648976a925dbfb9c2520, + 0x2a943b5d83171ed1ba5b2d0151f770d05cf117e28c8a2d0bd07901124b7a78ec, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x24917421c163008e468b59990ce9c9659723c7a143eeddf00b22bea911a23faf, + 0x20347f9b860c7318d8abb5924973a6032790ed146dd51c2b175890e67c7c14eb, + 0xc7b4b3d63f3985e07d15f46bff54c7f1382c7fcead2fc4d2732369ecf62312a, + 0x16c3c15bfb090d3c32b6783b8f35b56bf1ed17cafab462123eb872e18f40bc84, + 0xf4bf0d79b3a4f157a77cb759e8c3a950c2bf08d3b37e6e2252feda118dfeb6c, + 0x207bc2820e9268ac4529e9415d7094f6c4a3dd32c21fb6f34a6721806e60a66e, + 0x46d6e4942fc73df5a5c24e50a1390fcd3971f81416ec30338d988421d471e62, + 0x25d86cb7ab23b7d7829d52fb3d3c2dc42ecb745bc74e6e29c00faf2eceda60e6, + 0x291e27d656977488568245f7d60e5d31f7993b3530b6e7a5d2ecc5ed8bfcab9e, + 0xdde8d80231232c0283b7ad84aa356bbf7a3e7605dba21f29b53fd949cd378cd, + 0x16b9bca3f4757ee5bd884c08642d294730db13f90182970a962c956d5ded06bc, + 0x148e1434a77d59aafd26c76dfcd0d9dd58709b43c99173ceae6ddc899e39d810, + 0x23e38e3fa1713fb566e00717c0a22fe7e056067f7f455cf67c239fed5313c484, + 0xecb380bf60702c006a2e0b413bb060a7dafdcf4d8c736483da381315d128380, + 0x1504e0be27d971001c9c52f6ddabd8839fbf3cda3a42dc01c201788063ece2ad, + 0x204cd425d4fe74aa1fc3966950209bd6e9966aa7df1f515e5ff4eb504623704c, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x26b0354a46c4b6f840abef50577ae0160c403ac2ae154cc44dd1b3ef95cc9a32, + 0x76acba1cd92e4c02cec66b997f2136e03c86a5099967b8d2d6c3fa51ce470a6, + 0x1b9f835efd362eced66b1b4feb359a5a292e5179eca20536bc05fcf71ce8b0cf, + 0x1554b5740239a036650e957cf54880a05ffda13bd4a40b9946d1454b6e5ee619, + 0x2337f0f2350dcf2d2c4cb2f2e3c8cbfe8eac44b18a4e7df6ab9659c6d3bd51f8, + 0x2f70347a3e263a829f4c9524c0528c57aad8197d74f498c96618b82d6e38c750, + 0x2ae047c01e6b790967c9af15fe9700bf12a32cb4742c75ec4f2264355251b598, + 0x12bdad753525224488f0df2411e45b18e6d99df86b64ee5c2e1eaaa26b6b1165, + 0x7ed14a9dec030c79ab897464c9c31e89ac5d398e5fc2330ebd747dc62704e80, + 0x2586c2f08326503a7ccc396ada19284c6381f5402a1ddee59134036c6f9f4c85, + 0xe28de3e58815af816aa0e449cb6b0b68151fc3b74c8844b0433fb556e13bf35, + 0x15ed9ae17b48708404c20e204de218462f5c1de7a672c0400b1a4a97d82be2fc, + 0x2897a3c61ab7e1096d59db7d062d3509dbbe5288e8503eb723a783668f39363e, + 0x19382e0101202bcff4c8186a39e4ced12ada7adcbc0d3d535a37fd8e4e65d6a8, + 0x1dccf64cf1043efc8ff525df9a110883db70b13bb644c6567c0ed56006979547, + 0x14f753284093a5bc753e6e4516dc5f1856c363cde9ecc95745dde82f8f475dfe, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x47ce0768d3b94501b69470f61a3279af86cceda48efc0aeb4f755ce355a8c06, + 0xa838da94e6aa2b7e3c8d24fbbd1abf9fe09cda8242afff691d57aff64a307c7, + 0x2ccf7207714857e1b96f90a10f6662a0a161fef6f8554acffb454b475cad2249, + 0x2c964702e998844a760e735d74ec7fc17e793f656653128910e08a1c48b27399, + 0x26c73fcc286358f8a8c45940e32da21acecd2723a3e6c00003b875972e7e4215, + 0x2503bb71691693c6cd6c045d3f40b4cd2885a71adf5348642d80b44b4274164b, + 0x21abb0f3aa09de0569e24a9adf7863bd965ce656e4ee30611d0f063c1b6b1d49, + 0x1e6c18a3ca281852b9738876128c7d16d2fd27789043907cd624471d1356d10c, + 0xbb323797079be60788e8c257caa1e1e9b52b8f58128eb49dfd8d7595fa8275c, + 0x16ed4d5164745fdda2328ab28d0ef0350a3bb50589d72655d0e0d5a8f1dbab81, + 0x1719e6626ea03d94441eddcffb00dc8e76767224986c45f5f8bf746f72e33805, + 0x20dd2444d1b30a7e45a076776b4366f04e9c5d1b32a43b260d706f646a098db7, + 0x2276006ca87d973c1f5841a3b63aa9e6a4f8446a8a0ee03e068fda23a8a2e0b1, + 0x2d3e7d6feeaad7f3c8700e6293a0d896028d4149d57c219935463621fa77998e, + 0x26f15d4ba4736c73750ddbff4a7d9865f06d5676e449e9d249d3dc9ea62053c1, + 0x3636803242973ab91fef85aa46df13cba4ac9f6537aa3730c0da88b9d05c751, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x2ef01bca238ea43551e5857e412427af1daae81b8d9aa0c33bf392bb9e71f123, + 0x3030333648057d1d46a7a3973031a86637d6cdec3559bc12fa3bec6c0aab01cc, + 0x24dce91bc3df505f0593715987d3e6bab8f1847e5eea91341a9d1e83bfc39abe, + 0x27a2aa95ce7bd870fda385fc945d76269a9cb6d64b85f943430c796311d03868, + 0xf32e1ed6656688b400c42da52ffa8fac2d25ee877612e565f9271c1cdb216e, + 0xd69d7d99a58af860357adcbab763a96d048806bb1b3352c3ddcc0795e6bfc0f, + 0xfca01158c0aecddc404d7561a6d4ee7c6e7baf54eef93f1b4c72bd9468d8140, + 0x24f65dd1622f5993f172c7a803a71af6d9936a45fcf2f11c65a2291693c409c0, + 0x23b6c1c4a9697834526084cc56e8b53ab3ccb20e06ed7bd94e752cae13e04650, + 0x6b0b0674f9e70ca31b8658df5a918b6aa90ee4da8272d7ad50109ab73af2372, + 0x119ea3133debe120feb5b0ff2128b745ade6329c228d8c93ef9ecac933de75bb, + 0x28fe0921f3e250bd0d74df9669ece211330111bcda65ff19fe8bd02779da7686, + 0x121bc322c37b3a84cfa33407bca08421c76577f4ed5009151ee61de9538906f0, + 0xc6c6d133c64df4a3f148d03064ab681f6754192023f96e5c660181bf6708e7a, + 0x1f357b000c8ec106142c05d7fcb45bee3ca8602aceed83c3254d1596854d8e9c, + 0x2c635fbb8a475d22cc9388f33298ca3286d55e529d8167d036cc97e28b5c1109, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x1416e46669e99f6376ed9f1b60b4c1cbe2c13f36ac1a0961b28c0a4ded622be, + 0x83b993a01c06914fae37498067d1cc7575d4d6692e905a76c01012829848e35, + 0x7d66eff962ec6ddaeb23a84cb8fc53fb2435fb0779fdc6de042af8cbf653e, + 0x243493ca2e9aefca93b6f729cd48e89c5b6977dc8b9f128e80f2181a0c9321f9, + 0x25315cd8d5b5f0935df3ad290e18c8fbb1aa8a200af1b3b7acb784f2b1eb65f4, + 0x219e9f27376ebda36a9da6a406a6c2346e6db6c35e36390500ffbdd24c754013, + 0x2784f770d363c088139614dcafe4e82fec4aff60cbb9420b2defa1e5ceaf52ff, + 0x2ef0972f7624a2c71c7339890b350f716c7fc3cb884c48df73788cb38e8efe3d, + 0x2638005f1bfa951f04d3e6967a19ba68e797261d015fb0b4a200084da0520420, + 0x19952bfc2b15a1b7a44e59a4f007076a56aa61c9cb4fec45f42301ef9157a095, + 0x21bfebd7f0dbfa952f62f95d4475c079f623f56f67ec13f29e51fea4b142befd, + 0xabe0cbbdad752e9c30c665546f1b68cdd2d556f659c98c9d0c4048cbf0ba4d4, + 0x20c4f2c291c5f0b15e54fad44d549bdfa06e8405141d07446ecea299bded58d4, + 0xc703a5af22bea77a163ee98e379877fc276a2e60a134bfa6b3e0f3674aad830, + 0x23898a43fb970529f4c12bd16e98f891aed64fcb59738bd5c2ef1d7f5b9bd4a7, + 0x27de205e3b4f798811873af0dc39f91c449bae168ea2b2ca268f0fff421969d, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x34e0217aaa3133ffb88fd09bad59e44d8f0e74e1a64c86f3e9aa4587000464d, + 0xf0d2954a3425d4ef6291aeeca8d1e1927250f8e566688bf01f77206b6a0e0da, + 0x38ae6c953b05fde8ec1997151d62106c38561a6563b7c5c42c3ca3f254ebba8, + 0x129dae3e6abc9b3eef8419054977e8ebb35956b5da4731f87a1558b93d5b676a, + 0x43331ce5bf13e212c36bb6028ea5edc909d6807630483960ffd1e472333de8a, + 0x6edd2bca6596515c7bfa7f82c123947366efc923072442cd0d6cb3cb95b6590, + 0x218d39e5cb24a98ff778833ec9cc9c97154a2f0dcf576e36841e61f2a9d53c10, + 0x7babdb5f969df1056dcd1a4d25ecdaab931bdcd410f51443221f43ee9ad60d7, + 0x51f51c6edca7ad20f95cbd07ce9c5c51918dd6639ecb58e2db44f9da92ac45b, + 0x18d0cb9110ed2c13ca697c51731265461aa40cbff3eec69770c471bfab8547b5, + 0x151c0d100750fd3fc64ac7ca148c41bf2634c161746e664b6403e1d5ff99edb6, + 0x1badce073db9156bc6bc0b05a5f9ad32826ff80c20dbb90991c59b84f1887631, + 0x1d09611b11f20c357da69b64b7f235ea79741583cf177a43141caee3928bc88a, + 0x15903ccf8bd20aaf86dc7a0c1919a20b2beefa10ee9373ba62a75da5db50cd54, + 0xa3ed89f4229594227e8d35c0f775d81daef83cf50f6daf6c92584dbc86bbd7f, + 0x15c5a6fdd9b6ba06ec2cdeb9f465fb29a83a9345daed49e0c27064b2a745f832, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x29c47b21c3c1399dcde464739cd972c2ae7dd8511ef4dc4ab062de40904cd041, + 0x5d20c3e118f7e163803874435eb8c4f939fad669606a0f8823155b46636b40d, + 0x2a8adf7b64ebaf6bbae4363b8de139b047e49cc258d86927cdb17f64d7a76365, + 0xcfab49644bb24735309134d8f1160397b61c23766c13afa2f67350700ea184c, + 0x978c1e24a56e9f48e04a00ebacf84a971bf524a94ff82c9fa6cf2a4145ea323, + 0x1e7feb08ad0759f1632751fda2c80347296a181f33553bfd11c84e3b99e4dca1, + 0x1636f1c4c6be9b16647fd56e418b432d81dee2c09c00d14df526a491d03df083, + 0x1d0941c7678aa3814c49962f80f06a3b6ff48c4563cb563925c87b621392968f, + 0x1ba792f0e7770d294979a396e2c55b21baee98d0be48705b32f831f2d09f470d, + 0x1adfb90be5993e8a8e82466fd94d2142e05c507c38a0095535894369079e2858, + 0x1701417adcc7a63515f58d3fe4840f96d7b87646be925abf5831c7d9f6839e9a, + 0x16669c07129defa028d468884eec4825c1852e6ae60f5acc4a7a7754f9383ee, + 0xc030db661bf66032b9e0abfe88cc482f134b5f39b13e8aa20b540d23a5cb4d6, + 0x6c29b50030b9f9653c8cfe80928a76e6ba1fe5385109b7e606ef07634d53130, + 0x158eff715b637ea2e1c4312cfcfc154d3dcae6d2e240826e791dc661d4122a0e, + 0xb7414bf9dacff0d87b4613d9bb448ef0583f07948cb26d86963b0442a478865, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x2fc5816a8a9d54f1397ed6dcc705505ca28a50d608f2d6b0351d133ea65cf8aa, + 0x24d04d2b53f9f94b51e0300c6bf97e655ab6bb25f790365c64949876fc8e400a, + 0x12c2d385c706f78b68d132d1677f1c43fe555d3d9bd6622de8dce6a01aed702a, + 0x2cfc07b04b7ac6bd6ff67cc6d32ace4717cbc56974a70b9e3dda54b1741ce3e, + 0xdbec9e92d14512f3a95f1bd6eb87e7684fd099d747641e16956e281834fcbde, + 0x11110cac8dad45362476f50536e03d139076972f5e03db946753ed0034ed3050, + 0x17be085a196605f2b021add82a2fefe6c062bf2042537e054642c521dda6e462, + 0x2d30434c0cef5fb5dd60f6b52c01556819bedd08f87f0c191941f95b833853d0, + 0x297804121986231c72d5f3db2bb23cfc41d9091b7f085eebf0905f59854ad640, + 0x263cfbe2843370e8f2352bb41b51d59a8f9dd4a39552922021dae9bd777d64f3, + 0x1ada1b57547ba0b44cec18e94b273c02af369be58ba4ca5dddfc0c54c6d952cd, + 0x1a022e3c7f181a5af4ca6b68ea1e8636ad7a51eb2e49779fea2abda08058ce2a, + 0x1a51a742b5e2a8cb02194fe5442fe8160f887d71a8c624097cc751e6fc9e106c, + 0x33a3c4fb2a336862528fe456e4b28417f0cd5b8d702fa598648593cb27ff95b, + 0x275297e881159b1ff115beb9741fefff245fcebf2267fb7788bcfdb710ee11ec, + 0xc4330cf0545fe0d4d56dcebff69cc7564232b0ba94e58e879f9a838fa43b50d, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x7b613d8cbe7c7e104e3144d883270530e6b3190606a2df92791fee2f3f0db30, + 0x328bb8607f89952c7a0e199a914abfe679afd366f57160513708a57b0bc0665, + 0x2797d2a42bf2c3f860818f92783ee5b77ea5c8ef3ac3433a4ba8f8934fe40e7f, + 0x233e6f522a14ca24067c5c09affc7b53af6c87776525bb21d9058d01fc106af, + 0x390562c095c160aa786394027404bbd6a3882cc1118cc8ed82307c6e8d80084, + 0x17106e1ac0cfcf36e9d75f64a39807c812cc85b77e3c5ada491629f71d978f6e, + 0x1aa28e48122d0a44733a370e5031375a8c9c648cc46dcf3344621e6cd4ca5c76, + 0x18f6e768b9bcf25d37f90fae8b9a4c5cac181b9b05c6bceb922d50d8444bb79e, + 0xfa9340f079ddc476b10060bfb852af827ff712c5c9fea03f62d13d0c670d988, + 0x1db99f295b05ab42a946c2c3a5c73b225ba99ee53dc906eaf360675867efafeb, + 0x97578aeb43a7d6b1b10240c0a6b9b771d65b7c5a3a5555226e3ce45de3d3477, + 0x1974c34d88938d66ade5546a726dcba9bd76c31f1b4ee763af03f8d5698f4a87, + 0xe25a828aaee6f1168bbd9ca2c177973a8f20f4d8bf3aec06a0c24512df222ce, + 0x2e13ee7394e626ffebeaa09712936f8402400971986556871516f2a0eca9057e, + 0x20be54787d3e6d7e91de4a052172de99a251cb83be6fad47ec5a56b053717254, + 0x2019386dbf15958ed2efabc0f81184a6710e0f8239e8932e25827ccaabb750, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x1195db45235e0b286717bbb0e7fb7f4bd5f1346a8d6d47dde45513baa490207c, + 0x257be62b59d6f54c021c27f0c3c0a7ca3222dc5ecfb298bed986f1b6cb74f79, + 0x2fc61e8c69f1b6a89a698d4bd390f1ad961ef1c979c315fc069d1d3364630829, + 0x4ed6dd96dd4ba79b9474bfe10517c93ceb5a6dc5b95497a71a38c42c4171dbb, + 0x10c8d7d4846014d1d37d7aa27311dce9257ea1de1700a7175a03b358f12c0dd1, + 0x7f833418697f43d68c6792ed1b6a4274500d96c2894313f43d9185129ed01b8, + 0xaa1fb14156f9db59737b23efdaccc40d8f609b346809f66d96402e5f9a2c102, + 0x1a3b635b05a022877abf26c5378da756752882d30152a75e75095a4992926de2, + 0x5ff6852ef2c7807df8c68cc1fb842fe07ef08892e6706f4ccb3059f1d80714c, + 0x18e93ae4b4c092b271ce21881f133bb369d09e3726967ceb0484698a6cb02374, + 0x5f1d71fc99fd6e8dd1a4ff1c6fb4d16aad3445b2c5b2698a8ca995b3ec32fdd, + 0x260b2c665cf863248a5c9a03fc5ec713c1d32dd3bb17f3a6dba7af1690317514, + 0x199dc26831d1b81e333ea797e6aa2e76ea2e6cfdd888393682076ce77fbd4cf3, + 0x1fc7841c3762549185cf197f765c50f4da97358c40cb69cf74940eeb165417e8, + 0x3dd8db3c33075dc724dab7416f943e45adc39e147443ffcbf3fbed8068089fd, + 0x1415d87f2ece25dd6da8a9b56a5bdcef4f235a1b676ac4fe0ece8bea54f0d620, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x173e973d92b03e8f7cd54b5dcbd49e5c93046288c5bd8ac95f711e384807a40a, + 0x1e9e9e8f087fe7eae21b84385017d6306c73ee4dcc5b09efe1f91b9df6396353, + 0x2cd39e6fda7b0a75926254d1b4bd27ad6018ea559290d2041a6a1cd485026cee, + 0x2babe32c6ad1c466c0923e89242ff07997ad91281972ca9690ad77806c79f9a8, + 0x1671e3aefead10c1eab057577cef2d003653275ea183f956583dab5e6717aef6, + 0x638040b4e068d6330e2073b9042e25763872c4564b413d1d8df3dc5271cde9d, + 0x13a1be086b1c130fc9b0377bf5f4c7ab4166b34dc1442af15bd9ada0b316489f, + 0xe92a08c67a64c7e267acf28a048035d8d702bc0e49b7157132781f3f912c04, + 0x24fcf21bb660a9465b6a50ea1e0ff6c88d463e5c14cc82e7f333bd8cd9e9da57, + 0x19c3400c22778ad2608cc33d103d7558b909f2bffe1128945021cfa3996b90ce, + 0x1804ddf73341fab213bd15ac4fb0b38b210038ab3097df363df15449ca092955, + 0x2d030e104eb695f158216f2d17baf589c6b7eb3174702acffff3459faa369209, + 0x2ac28b5273536d5520dbc0f2d1ca6225372569f2c1f815eb0d98ea23bde3e0a9, + 0x132369e44fa5b49f309bdb51e3f76481bc7151112c28ee7c6058d4404d326aab, + 0x1030d8dd6355ef0e8b3bd213083f0540158a13dc059335b0a68471c1d8f995cf, + 0x10754be6667d0c88da8d27c8d885c68c2ec53e66879efc8664a313846c8db7f4, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x245fdf24ed7cac6d987a5f1098a3dc2094e8445ea8a34d409caa0de9ee8833ad, + 0x2ddcd4b1ef28429efb5371343d7c1aa34394b214ba4d3786a72ff4a260f80341, + 0x9796da1c54e94658988e1e47f2ab2a18fb54bd12c0f69761a11428d2bf8060b, + 0x2b820079829572e4737fd84b55e00d69b9842681762d614c4cc9f4c83dc7c88a, + 0x2a2c8f2dd7ed7049029ac58e2483bbc92ca9deb979598179962834099a206d0b, + 0x2e5131ed99601233301a58544eb5b390adc2aed2f7bb8975f4e3089ba598e03d, + 0x6f800a70d479c89318ce14ace0c1f7ded913cb3186aa67acc7290b35f941c80, + 0x848edf27122e8c897ece8ff31c76e8e3da4ec246480e769809bebcdb4680146, + 0x3032a7d711f11783b0cfa12d0a9bbaff62fb9d75cbe50aa6e684f9285d55840a, + 0x156bb4b89a15827370ed5326bc516f90e80da2b33bfa976b4c9a26f4c0bcb5d4, + 0x104b800aad84f2de01925253de1300447944ff027999bf3a113dfe28236e707e, + 0xee24634e1374e506d3186a10f60315beb8a311ca69d595c0afa0e4dfad5ec22, + 0x886f6c8618d45654de796ffb0a718eb65e5236deff84adc493e6a49308509bf, + 0x303f792b77de056334bf4b95c535b224edccc1d65b28e52d569695fe0a86f7e7, + 0x2ce5f9bdc64ab48b32e5ed411be107b280119255d976673c14ca2e70c76fa68a, + 0x26f0252f0b0b6f638aa04dab03f6a8fe7875a84fe5c6763aa9443faabd36d6af, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x895eaa7421d5c92db73111875ff0e97d1f1cf13454c8d0ee65ae0c86cb9f0c6, + 0x5a37e53d3c5dbbf9cd972b637bfb018efcfa1fd5cbe8b5dbf9f37608783392a, + 0x2151abfa55e801a5dd55f82b711f05b3e61fd9c94dc77201a9e62c89091da8c0, + 0x1df7040bdf6398bfbc5dc0bcfd52e2cb6acc1e32ea9eec40e1c14a173615a901, + 0x82d9c0993ae4a12a039c11aad12743c5f5d286c648a89b4342169aa4100b9aa, + 0x295f9f8fa059d54d4b582213965eabc5ed6f785e4aa71196f6238be2c511bd11, + 0x11489075194474f063993741279cea5cea810bce027e64ad900225ced81b35e, + 0xc308adc9b0dea53e1c37e06d0576f4ed39c2aea66bf429ac00575a9105112b0, + 0x1c8ae9521d6579b43520c3cbcd712b3dfbbd2b1543d1564f7d918c6e330e08a6, + 0xc69ad644957599bb3eda1d9f831ca67b021b33f6407ff2e56870e7ab3d5a569, + 0x17de4f74815fb3a0f45728b381e2ddf7c1157e5d65989ebde47f8bcb88f36836, + 0x1fc13b76344108f12af68f0bc80c99577f09a266368f0e274794a3cf65b48d17, + 0x2fad04c4a1bf440fe56076df74e5c30a58a6e26fa9da0865bd0374b6ae37f4a2, + 0x20766bcc7f359bfe765ce87998097a7501d7924730fe7325aacceaa054e2ea5b, + 0x14eb221ab65d0dbc5edf6a2065188ea9057f935d028f7ed14729ebdd66ed5fd7, + 0x1cade81c4d562aff84daadd630392b735b948175c064ace958e0c789c9d93bf, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x19b64914374910bacc33326c70be0a8518e71f26b4e1aae5d33fd5dcebbb1f44, + 0xec087bc39e5058e0c5c1432b20c612537441be0107ed759d3a9468ada975dda, + 0x25f6ade6e9833696c4dbc19c765ca2ced09f47f0745dfc850efd26e3a8bfc5f6, + 0x842f674f65a495938dba020f22a476840e0591f179780d72c00153ddef5a9ae, + 0x24b3232f05be57ef3c4c22af9cc37a73f0ae40289fb0fa880630f7e3d00997aa, + 0x2f4b230d825a682520ac0b5326d130a24bb89363318961ef5f65391b8e7f6bc3, + 0xf1644020d8a6c0dde5068f18ab196d348172aadcfd6391c31ff1b54f513509d, + 0x73fd850ca9561f8a645c9e4af943d372a4b8620b78bbbc357a97d14f531797, + 0x284f86b9cce13fbb6fd660d8e52cf27f7bf2723a494278f3cb0c3bad0574d104, + 0x16bee52d1d6d362b9430ccf4d2f1afeafe3572ae4eaa03be6af6f1bcc05de855, + 0x254cec1178e80740cca318d1b5db37b5dd23fa2c44abb7f1535200618b9ba0c5, + 0x113069cf767ed4afc61e592e98a63edaef98278c2ce59db109c94ef6dea9cf, + 0x2829e1532b4fcdb2df9104cc23b3331a1d51c7d0da9b645a4a43dbeaea77d229, + 0x24a03c0f7b51b6e24a889690a3341f55deacaddafc1ff871af6fd6a76dce8bee, + 0x24a7c2c124131ab37ed62a0182114a5dce4ab7e62b14ff632703b23a78f391a0, + 0x19529e943e466da82e6bae8f1750de8620e060306d9df5a9d20a83a4b68fc09c, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x274c0f68f679da53bdcdf9c11393c34ef8fe59cdeeecf859d4ad53069a88789c, + 0x1c900ca5882b107a3b8a8938140b127cd3ffbf539c9145f385cea5e7dc6978f5, + 0x55a3264b130bb4316f4503af137f0d964b753ba575456a74581b68c6789df33, + 0x290033424503055ab2e6b8093a758db0f02dcfc4adaf26a30f467b0e8aa1af13, + 0x1b415d6ec7893774bf9a598a8496f83a5422861a044211e0d525493f75c7bca1, + 0x2d5e6a92650786e6ab35f3a62c5689a0288849d1eec7ebf89b9a6df75cdafd39, + 0x15b1c6c75717d38e94265523f0f6491e22d8b79a791b10b21139f008651e3037, + 0x1f929349fb5222c4a6f17fde7f0aaca6430b6785cc5f65c3e1b7842c338dc1e3, + 0x23034bb8b8618de8c8890fc8fee6422147545d11d45e41ed6326b767ff099cba, + 0x2ab706c6d21e887b5906d4db350e41b176323ed39f88a75b80f1eb2680169f69, + 0x4c1031dda5e43ef325b33a80e6cd32cb22b16ad324fbd90ccf79c1f7e9ee062, + 0x1d663d31705eefca25d29b8894223a7daf06bfecf4e8e0bb845682fce0b1a41e, + 0x18c97bc6dc2ee1c3d66bdad7046019b6d4aba6592823a51ae2a8052824c6e332, + 0xdde410729932dcaff0490adec752faade582e2eff9d05896da43fac32e1ad3a, + 0xb12de1270d788dabec1456611485a6841cdfe411a09f80c0e132828568d8eab, + 0x5194088cb1b0f39c5b1527bd0a3ac4d16c845c2388cd22dee75544eceab640c, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x2a2904f92bdc035f347c6fb6df54ac6b482a2642dd8e798f9df0915fcc86872b, + 0x8bc0f22b597fa12cd8189c5fd0f79b2b10d6c65946b287890dc5f594761d665, + 0x2bb55a554f9bcc5ea8dbd4d5453e188122c66c507fdd08d0589706c1335619d4, + 0x2471e91078add335f5c48457785ef1b469484ed697e2e9f80d0fc73852492508, + 0x2ccf72b7324cbdd4a1b980d883532ef2887c798ef446408e885f8cbd14ac42ac, + 0x1c3b75aada78c1b204a35386f68e09a8ed700bd88685d0e38cedadfbd88a583d, + 0x11164ea9623704eafef86bbcfecad592597038fc1b097380effca4502577c733, + 0x4b961c368270196ac2ada2e66e44a4440905eff5b58341302ceaddfa215f691, + 0x39dcd1dd3ff8d7fe019dda64104e9bbfa1c60fabd54065c85e727302d8335db, + 0x90f27feffe276b6c1d77f6a80d2c25680fb854af9ad1be11268064e735060b8, + 0x202922769a226e1dea3c39d791bf28ec93639c7937eb7be2c10912ee896fd3e2, + 0x163bb1b115962019e41bd1c7cf0d8783d4baa163dcbf6e25d368c543f9560a5, + 0x255dd24ea1b49972007c3b74fd98c3ccc682fde58858a2073be4b90b39e57cf8, + 0x2be5aecc70e89fd7fd3e2683bea0ce600cf42759ec5941f0746f126b11beccdc, + 0x1584587c91f57bbdc41e85ea3ac8ea67ed261cd8d5014b424a1dc01bac478b91, + 0x2131be5b4387d226c22bcd102973756cd7ff955452e9eae429107ab244294b14, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x254b0e91bf714a1b45748d756729102fdab89301fc89d029d5537f9226e042f7, + 0x303c21aa2f173c290af9ea8e0a10f7858ffab7519185843d2049a22946026b11, + 0x41e6ecfc8a13cdf52f9c21662906f395ae172f944c7575073c0eee9962941f9, + 0x19eb35e2795098faffef9ef5baca33da9ecf94d5973c0ecd25e6899630af7a76, + 0x1142d22ec011a94a940fe203deb1997b64f780bf35d06276644f98e48e2c9ff8, + 0xfddc36dde84e16a5c2f631470943ce31e4be6305bca6e5c753c6186f1059f62, + 0x5b14ba6526be3dcc17bf7d609a42aac1adfe0f449a3d9374e0c22e26b2c2362, + 0x16152ab0a00c391d450290ae825cf5ca2769fbbf2e7eb69f8764025f68e9ff5b, + 0x28cc90877e4cce38fd08c1af95cc3f885a5c5328fa0ee0bc89ca190694d8e484, + 0x2df5ab9a480bba00072c401baae420c1800155b9f7d1ab9b31e976ad800929d1, + 0x12640a01d9b60560290065a3fd812afc07a6e795408f988071aeedf22ab75e66, + 0x1b2792d807f55ebab5f4274d43ccdb9d23c155b8b9f6df8694ecc6f67e20028b, + 0x16c2ea687479d257e26a655b5c6c27bc1f455eeeac28c3b3ce654bc76cac38f3, + 0x26da8fd5fc478751e06453b0ecb6cdaabf231a58e603ac4ad14717d70db2f27d, + 0x14f3a3e34739d7c727b010a5022d9f0f3e035e91db3aa947e3ebe3366eed27c3, + 0x366141d1115aafb084cfa866c52ef40a5fa57fdc8e06fc2f1e46b967c9c6615, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x15658afd9b2c13d4bc0c637cef9717e943c50f83b67c8676d67d17050494e5cc, + 0x1f318dc3e277bd895a88dbd9e3c4febd43cdb9064683ffbf1be9e6f9b2a71669, + 0x141cdd5f2c18d63eec6e82248935eaeac4ef044ee76cb7ef0e9259ab6f93daaa, + 0xe4b254bc67d3857f499682863a0f95b76e9d5cc9fb7c2c59729db203050299f, + 0x2cc2b90a7bf9f3663b0f41ede34f60d63a99860760ed6027fe17d4fa9eb1b396, + 0x2e0819713df7c7a942c08b3ea50add92e39214104120803a5806aad10234abc1, + 0x24164a433840a28d2615c719c716f2f7c01f7c3854a327da6c5db75097fef1ee, + 0x272543f2284921391729ae58db1d9db0807629d9211778b0756ea7e4f88297b1, + 0x194af27987f50ed8730d267dcfd98a9a284a3582cfb7356e3dc46bbca1eeed6a, + 0x2044ba55f5e44c7069590bd2abfcb2b7b163d47e0e1bf2e2524c0948da4b1a37, + 0x19d37fca1b67b7ac626349cbf2928b9457863637baa2613b494d9da18cc384f0, + 0x1230ea231084e3641817b74662caf5732556c3d94a01d209fea1f6777ae6cca1, + 0x2f924a42d4d9446cb488295883fdadce8debda5ac727901eabf2d8627dc6d698, + 0x2da745785ae0d3eff1a3281d7537383abfdfba2031a880acd8dabb3388a4ce95, + 0x72fa635414d1673fab8d057107792b3039c033d924cc0b1530497c2c810428, + 0x19db329f086a50781b0c6eb2552ba454db2fcbbc125a5ec41ed2c0e840bd6774, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x1ea4f3fe9b4abfce9e655b05c4f64a0849003f9b349bdbf349ea2a249bdc945d, + 0x23c87854133b5d392742dce58aa01cf376e3983dd939634c4fee6326db21db4c, + 0xbc4774e1e80349b9a704c01709de843f3b20a75be630d1b6c6555adf3bda042, + 0x143ffd0adddc79c51edcfac6ffc1aa3d99ebf2d55349df53a54842c945a82f55, + 0x2b813146b9e70f53e3cb2549a91e68963928c40e02c08729e0fd3f5941b3d602, + 0x13de9ef153bd22f5063cb42abc061c09eec510e4b694a4e9b9bf6de56cc2f206, + 0x30015dd143c80d113c290bf94ee9d7b10cbfb93959e846751c3b3ef9f8d07490, + 0x2515eeb903d6537674e4fb3cee0b3a4c5051ef3cfc1a3d1dd2a25f4ddf96e05a, + 0x20ec5ec6cb5f91d860925a6341af5cb15fcf4b2694083235ebc7ea78ccf6421f, + 0x77160d3b99920220fa591a49f79c56a282b6e368cd1419ef09632e869599f14, + 0x2dc01f61427888cb2d5ae9d8a0499cafc03945dbf111727b1a2cbae73bb41b0d, + 0x1df3b805da3b583cc8f736372e7b16d3d0407e634b6cb7ebef2b168932194147, + 0x224a6cb7f4e964e616ca5b0f23c77859232674745d32072096bb9f12131f0075, + 0x7f74f0de535231775307017a09328c7491bf0fb7ce86ad5fb589594154983fd, + 0x2816d118f59d3cead1cedf5cc76a1a87829b2d8c1fa10adbb2fd4eebc0373b26, + 0x1698c0df24945164067e5d0d9b0321a757818a0cbfae969e28c76dc470974440, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x2d878d0119485477be8dbf01a3aefa927a230065cefa169e34cdcd8e97efee48, + 0x2af377e1ffcb6909a07fb9d03937ce4a8fead2190cabda6baebd5943445dc0e4, + 0x110ffaae8772ac77a0fe26f368484344ff681843ef616c6d73e0dd95d5f1f3e8, + 0x92cde477438d1a1335b795d5a5ae15d0949877c734a0eca249865ae30a4ce2d, + 0x2cb1dcc78144adfca1e53dc251c2e4084970c941855ee6a772d30dfbb1a6448b, + 0x1e80f366933f00562d3facb54015e72fc4cf46897bd71f3f3015bb3f8895231d, + 0x20c5d9b2e153f4787a765096aa7c1f47f990e810004ee7737c211150c40b79ed, + 0x12e81ecb7ef55b86893278ce37c429400af30b34c10b0acd786fbd7b25c3469d, + 0x1cbbeabe0289ed5942f50531a647530f105e72d1f912eb11539d1fc5588ce1f7, + 0x213c4970760a5882661e0e818f43450b8cf9e02dbd0046f27ea4d66403ed0ee7, + 0x286f73e14f72495fbb280d713b0161ff695a21091150ee6c9ae96eddf36e212b, + 0xd64a21cebd1f59801551216c693b181aa963bce18a7f4439f179e7105836296, + 0x14bb39c836c00f33ea9903dba3d3d434ec33deaec35076eafc1a4c5a01a417c3, + 0x2ca5b88e6bb11f61e5dcc2a4ef664b49a3801009f1eb74208313b7b04d59edd8, + 0x2c44af041ac89242a8bd751d96ce0f86eddf8c312e6b3127c53e6017c0d22e77, + 0x1466d21f848850fbea559a4c76b1a00787f997c1a4a5bd40643036ab684553d7, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x220cecbc247151bc202a81a4573f923bc92a2208b17e1c0bf2dfba0de4fd26da, + 0xb71d939b546f609ccb189dcbeed82a34d8f2faa2c597a3b3678369a471d817a, + 0x2cfba88722ad37fda1b7ec9489a96e09e88bbf6649c8b7014bdde34ef18a64e0, + 0xd0debc0f0d5dcdf74f2192da068f87631213a52aaf59eada0bd59bb99ba9510, + 0x1d202504d57a61c4cd6bf007e478d9588d8e6585ebc602227379aaf25bbf6ad7, + 0x251253367a3e28a691d3b6fff1209f6cf0e03736928725dea0f9f0824ae70dc2, + 0x260c55e9c06f653d9202d03f1c184fb70df2f937ad157719685863e4338fb4be, + 0x200b2246239844344cce8854c24c9a9b14e438de6a3ea445151882f23168fd20, + 0x2e3e47be40c7216d9db75470bd8193c3558ba3c61c552bc56dab2713af62506c, + 0x2784c2b142bf3e8639e090358a1a3c81e25f23edcab18001514c617cd0918a5c, + 0x125de24f4fbc6e879b4039af38a1d041e6c38a270b3b9502e10c09f149445d66, + 0x29740adacf9d3689e443639c25e367b23d07d690c9ea8da6e12fa6443502f903, + 0x2bb9d36c36a107db72deb4262776967926f923df9c96cf07708d5659cc04ac81, + 0xb3d9827d898e83333c83c65818f7fc1761fcf632d1b5f03ee95085b518dfb67, + 0x10a6e860715f76969d739bd3c393f1af2c6d27f3f8c21e101dc8cf7a515eef7e, + 0x2d8b0a8bf894b7d607d9a49dc6f8725431f69ef0541debd9a41ccec4b7c1853e, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x2f127fbd7f50d13e1ed144760d37a375a507ac1f0475fd1fa1cab401ecafc7fb, + 0x1577d27a4a8983d54a364994db2232806dc6a3f1ae005960adbcb4352a88b9e2, + 0x52914cca13bf1c8dd7b8ae8329393ccb24dcbb32c4625ea2ba6cf935be4f231, + 0x3ae3cb86c125ba7e22c68fc612f2928a961ba4967a5afc661ed2c32de93fd30, + 0x297797def82244ac873c64c1e3b0586725adff324eeb9b15a9b476823e6179e1, + 0x124a7a8c6e44e7135b58fc2b76062171b5054af0def6044d99637adfdb5b403, + 0x1122cd468ae5a811791bbfd990f5ef430eb1e1f1c6f7469e5746db7ec0426892, + 0x2409be076f6bbfe87a660f865fe5aeb4abf064c12bdada933eed7824ba271cdf, + 0x300cab922f89292915e01a78def7ae323501694f122737b9ec6739f123278b3b, + 0xd743547bd321fbd1b27ebfc7d52797b2f97323d25f1a374afec19a1630ab63b, + 0x9563550bdacc55218984e8413a1226c22b38c12d69ac16bf6e3f952a787a504, + 0x1985c8553ee8e78bd1c65b3f375fe99cb0c14d60e69fc6d205cc54bd173f5204, + 0x1bd7b38a27edbf115143764d25bdac7e921e83b29964101b494f8075a7800763, + 0x2766850751254f44f4e93db5621839bf0eced728a6d2b8cff05b0fcda945e, + 0x135b92c76b52af013119fdf43e9ff79cb40208b2c78cccd727781ff1f456039e, + 0x19da226a03cebea345c9a56cf3b4c7e6980d613471b97894a7d5fed6f3e1c743, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x92f4acca2e0ede5ba901916da9e1f67bf4458f8495eea238d17332da63aa71a, + 0x1641d2d820f16a7e3f48def116b6cd078de47aeb782d8295c5f505d89a9e4ba, + 0x85201a2d77102c3d0c63353013c47c2adea146120e8d6b3e2319d8e63ba0cca, + 0xa53d758d0108ebf22dace7bbbb70afa26f400485dee9e4e7f4f7ab7d9299677, + 0x262d9423cd20852bc68c46fe5eae59a81d1d814a66a638c8c00127fe2dd98761, + 0x2ade8678e1c4e5a88001f70873e9c28bb8b86bc77c1712731057b410468c8f30, + 0xee8ff3fc24bcd3063e995a4cbcd34f46142c9f3abff0f8e46a86795b5b46552, + 0x2b825f9cd4585ef46a5da502209c12464c824adfb18032718bb37e4738cb3292, + 0x1ac8101da6ddec552238fcff3932ff2eb40ba38ed0c39eb5903e3adccff791d, + 0x1ab95f20ef0daa5ceb85f821413b046e9fb8a70b61e77f8f5469711f508f178f, + 0x580d8b79189de04500aa5749909874f8b5968c9204d6511e05ba1a3953362c, + 0x275875a979f31b1c8db47f6dba4c553c8732aa37c4c74d7fe9f979274dc27c95, + 0x13d84732bb3b9bc97162533644a7515d91f08d970584510db56caba62dfa0d66, + 0x4d47f94ed591c3969fee09e23f392dcd0831126d621ff5a07784bbb5178e876, + 0x268be50015a5f4676f202ecef15e094130bab5822d63d777374c8a0b9f4f3832, + 0xc44a75d5020d4aed139ad7294f27763391f2be6bd3343691ea6e122c4356fcb, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x212e7e2ecfce78922708fcaf276bbbded3c0e2d8804d66a13fa020749c48ecc0, + 0x158fa860b8267b4011780eeb782c4d2b878ae2615e317b798961be28a7ca2462, + 0x1def7622e54639fd40813cf1bf8162198af19e07d88a0d42d436368745e3cca6, + 0x145ad4994d42ca69669e4c78ef8db06461047f4976dbc5ad4a6cf2c3ff78bf57, + 0x197d0463b10a21649f25670cdd2504ba58621ab912b643293b32a515f50afdfc, + 0x23398d180006069a68c7742caf4c669b87742b603d5ec75c13d2a835103a0fd4, + 0x1e0258bd63687d7b17c4fa3789f9fd82108a3d38ed4458e50a071c4b622866c8, + 0x423f6744b5b95af35bb9caa720088b05e7fe89176569010e96792e0fd06a28c, + 0xc50436db6d99e5a8933aef29ac83fa2817395c577d0ba3e0152fd383542088a, + 0x10a22724b783a4ed75e92202a6121ad76eec88c3f6b6d2b0cd5a2f829d7caa37, + 0xf49f1ad9de4f057eb3acadbe2279d617384c0f594503c616c8a1f7c05fcc886, + 0x2141c09b30eaac9f355f49e98905435476bfa52fa5339ea30fc48beabece0f4b, + 0x15c1c2b59c45dfc274c111fbcc2b79bd7440d738d0b433518ad3c8ce8d064ed, + 0x1db3bd1d64fe08c2dae2ddaddc2c339ca0402bec8b41b74d74998aabfdfb7bfc, + 0x29a5a2015c3c31790000852191471c62442721881310f01e2fb0b92157a6adaf, + 0xc8dc01d3f82d41bd600fd0759bfe0aa674a0b7d089b0ed0ea9127fd0847832, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x2a824ce1fd2a8c476123e3a989bf2d6709db1ae25b6003b35f4e9a63b414a58, + 0x12ebc9623cf8edf6e519f0b679939b74b2e4b4097992d2ed382afa7dc08b484f, + 0x16be2e58e7c791d1a9edeb27d648d697ac592d085c504517cac06dcccc9b80b9, + 0x11f10e1bbfb29ef8257b3f13add23550576bae71f723613ffadbda16f76e67de, + 0x1ad4858514fea633d11ef8b8460a55cbbff262b90a7704fc2ae9f4de51d43328, + 0x215f4b249b5c5e65fabe4b485656a746d564d4451568c1949d28e35624cd5d60, + 0x1fbad1d2ea18f2f77723b3dcf4acde26751b05615c0af9d607481ae4155b0b31, + 0x21662871d695f76be370b37b3214a511fa6a186c5c856af4f830950ca601a9e0, + 0x23ef880efe39676ca81b90ff6258371415feffe1514a33fb3b944360cebab527, + 0x2821c241fcaebd3a0039501eb930cf9a84760a177be827540ba0f3c7aec6e354, + 0x146be2228a62f0b2678d113c1e9bc68ec984fbc98358441882c3223c5d08ddac, + 0xb88bf45643cca07b10d4c2d229d9f4f8186e5da1b4a7921bdb81082d525ff22, + 0x8fc9cbeac386e14a1121a09f0ba01977c6a4b444528bf675ffa538229fd0b1e, + 0x1b50431a74a6fbb3653b07cb93b41b31f4b8e8f0069132630d85d6247c754a05, + 0x1e406be857f7f834e34e4366a64203a4587e3d15e3fb68fce7cd1648bf281d9b, + 0x148eba772251ed3515118d4b1cd35d1dad67cb449e93053aeedf6c90725deec4, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x2e04360710f57315981909dd928e62c44c44034647842dfa31526f83f4e02671, + 0x2aafcfc0a678286f879baff9f360018f642f5dc0fcdd24efede6f42ab41f3876, + 0xc056d71fbe0367362ee12d47779dbac6784d03b9effcfdeb97b91c57f65e433, + 0x115524aab9917d448fef5342d3773f10c7bc33b0fe015fc39851bb6afb542fd7, + 0x117e6ade5e05bc5efbd21dd42adbec70159c427bdabafa5df3bafe8d48240958, + 0x381334a0ddf5db66871f8bd943e4a54dfd1f9b7d13c52944fa0ff2562250fc8, + 0x43e8c4009abbada6a3350bee3e92556368245a5aac0c1b52f2338e1ce1121c4, + 0x2e88167d899544487a1cff38e196dc25b3b8ebd01a2289b382c965e11128cb7c, + 0x1c308d8fbd04e1e349b4e0ce629b3fbac322460faa3a3731112d44c3a4db27ae, + 0x34ef7e4e0ac0d3d85f4adb5bef214c96512accc1c0f3a11470b493d4a6e7946, + 0x2b6f7ec4e66fade014011c277952b270953966e9fc9def4bcd21052f62315a76, + 0x2a8510585ae4c162b269375af5bf36d48824b1cd4d323125f061dc90f06fe318, + 0x19008b99b3e1da588b1094f3110f9032354d1aaf9c93ca9f1dd0010f974c3fde, + 0x2560926db4543ac9b3ec4ad64b12021d232944ba8ddc47bdc494f5ba051f65e3, + 0x29ccea21d8edecf6359058c36019960b8e0cd6e0878f835879477fa3ba09965, + 0x22200c2de87d7552604e1ecc47c639ec983525fe8484a3d24655d5dec1a4ba33, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x2ad7a0d2da92e10ea6eb68264ba502da9a0a5b35bab9699cbc29fd8fe2e30ab1, + 0x20590023505117aecc066d41c1adbd5ad4cbf0e9b8dfeaf9f9e8799f07534408, + 0x222c46e262ca50113017fcf937c68bc5a2ce66216ece4254ac3d07fdacbff44d, + 0x18e7420a44ea5b1e13f4779818b97a2081be214baeb62671e0dae86c4023ae13, + 0x22ea7ca068c59b65cc056374a848ac65417a6f02d8caa04407d1394ea1ba8256, + 0xd3a07b74e65318c9e1879c337057cc712c0f533ba49c1c626d1b7ab155936db, + 0x61d5292ac1d8dc58ab73a0a48f6f631262c6601fb7c0b48c1a16452b546db6d, + 0x5833012960b055133c9ba572828b91414cd7ba31d68ef46f5f76078c3ca1841, + 0x2f2764c49d1bc1427e519f7690e301a620a62a89bd44dd766d6ca181d02eb406, + 0xb8a8d7bade0db2c62bb09b73bf7444c087ff5e82ef4df25cd0f9ecaa12bfff9, + 0x1bd2b4b1504d8c446a5125fa97754b345cce5966a6e0ece3586933510071283c, + 0x87c0b8b7b9ed1a7f917066f04927482b71b00120114f6eb57c272cb26ab0ab0, + 0x20fd707a8cc61d2a031709dab4ae58bf5032a09b570e7497c3415596d3d5fd24, + 0x1a33b2e800ae297e35eeaf4e3bd055dc56e533f4441bb24bfd130b924d71cf72, + 0x18415cd52a959280d64154df2c538469ce854f7561e19b7d05235c9fa478ce0c, + 0x2e6a310ed3f24d835969e401ff1df8540801ab6fafa90e70e50a8230f334ae66, + 0x190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, + 0x2fc4ba3b1f7871a2df1a801b29d1eb494e3a4d072b6638da905d5fceefd93c51, + 0x1162c765b187e20f079a417abec80c369b6e1efebdd9a6bad7577c1722b597b, + 0x9a3571080ab89c41d2c53279c9ab9ced52efb9cd1526d24dd58b31771a75606, + 0x2fdf9f81c2ad998f2229e64e084f9149ea3f0948cd928136086120b68ae69651, + 0x178e83d7f2f9ed92d3d783287f25fe8d0d28bef0cbf2315ca03da314aaeb94bf, + 0x278d681f603da186319befa5d2c5567a9fb52eed6061787cefa92b27c28a64ee, + 0x108fd8bc50dcc43af4d73686abf8fd70b42245c1af2edcf11090784a24aa5fb9, + 0x4ff765c30d4e035bcfbc196c646541fa1d27c05d5d087e01c03ef11224b78f3, + 0x607cd8ff9b889773c9eb68b8a4366469d470cd7c6004106caae95c10c424419, + 0x1da524cff60b64856dc1f5dde0ff62da7b182da26908f6ba6e590adebf91b40c, + 0x22f33eaee3c481e65801b761a72832908f066fe21dab5fa5ec1d4c6e99dd6dfc, + 0x75f84e9c719bb8de8e61083290daff19aaa4337454e5ba804257787470f2f54, + 0x2084be9a57e9adb80303a8dcaffd4bb77adb6815168b36a1d363b38425437135, + 0xb303449f1bf4b92d2cbc26ab34b4215b6dd7af010747a705b2a6e3398882922, + 0xc099bc68243537203f97254f08dfb7efc09de8f96d72f3b3e0aaded45e18b4a, + 0x1c5fd9060d4e0d999264429a5004c165570bd1675b09f977708b1ca48e616388 + ] ) } + // noir-fmt:ignore -pub fn x5_10_config() -> PoseidonConfig<680, 100> { +pub fn x5_10_config() -> PoseidonConfig<10, 140, 1140> { config( 10, 8, 60, alpha(), - [6377232663526537440095439257883018477761342422116697881186123375221738885878,851539971462439380385862352460596759101811723695394639617127852578681769809,8777577262325190174206575699458733195047013200879424709893142671840513604890,21694543997668766291509756109744969193435163886467863962355853609369758783238,9577278996811393500051721677710083593799044422389686435650597107832854019185,16323954252044716897246121150114593642230197187021287621193086593549237094775,9789909425016820105251161906130605326280235056822272235912508431951118212950,5766700650277227528545902607164112169119010038912902265869378685414299620760,14342521005374081251816746055115831251291272287569749723238975882435091047876,2566050045458470252423704003188705777658084864238473334290159653618543192811,8762700051029310248153110133778709519032029454737126719215892745208105815416,4708553466520767412303631379034292236924119642035476122997253385705160556618,4755252554118675759917549980023743559070421272488077422007409392838436797712,8781462767081720534606018702554359272062136386754094559457527802951016005606,19167810216492792969016670752653089791475857662598893252819620255611011677188,12379801295054424513880366937656969081677178004556540562031393564676230427743,3873349522143254287251699452075145107916086554326675869006906246349942638560,1683302064923931554193379270562867202085645938091131834974486624990867609624,2777362700160137801933468204963311934247500177582714816722898763176642740860,5330041075666088752029210636784758218847391095319460299231210692948196701638,11849341704739004206642161112350419905150271791787570525216826204427280723792,7477184099861050355308565098520563835117942875101546634259876195229073147282,18811741129290507103385501216699521500514849038287903802256059864942452310117,15644162092778325718506673614750051639809307056147336506838023349115605106787,15072682042494620166496832302000289519302436589952610199010633012972669445593,7385535266916101728534366006042662339391797772494836337087929961280561819695,10606300178546340442574451452231017670874690381506662581848460294140286741651,343808333592012682122858022517390819973432303579818622412786360520154826142,6686378289544833739489172513893542192299224296746579469451376125664696638046,9325668720082019512834072623751272154060473105966456255302021143714657867878,13237356616132921941407245964289360960304194019926733744472216846697663447262,1723892942664599421365079138681309575413323508685958773158319650163306910931,6845174279248890961319599668687600484787455619619716546069389087383603254137,14429592766972645051919899517480716657546426049902884218808698177731678278944,2012555589304829161260427679955782678928810146332132910441113793264100264511,15162287124358358727307007568219331690174000191414576263088727973180750593247,6171544970310792508799412092397912280594923286679674322244394636145740843662,11560360683323732335070294251287274796083850957500974817278726137032659811346,7954890646285422519425515982220441977570181574595597355546782742910060927756,2121066076676892095526555416241546752515994960009188371572036715916593676611,1030002705665772802770205305890036009903459272665864721338890073927102958060,16664112528630425414995233349042921759383114978671010908728891678245502701008,16224205339340335222764551648549356562936176805367408466634736640263613613659,5567916191875465998022755280584031341089937668974064792042640432034217833475,10561503261915825576621563677167739482566911623771072553907339314680805249099,1281495108038254322634503929806042733441491866895195579580212370919762081047,9600700315845518751455006692480832601523246124684033595437676082879283709816,15989333248905201890715282122260615227836016238448185882687783867814184655170,3846245593630362971844915233982274952290718501967612724027782949411933001202,9981027954269438386336412342904724691774209648042702865994578173145958992921,8623595877941915162474742420309695649920307514068323484728910858137792561119,21103940025922636831675399050467233863786411927021772979799068688191712316972,18892924253208304354853962839524897599416779246859691035714354037906441368765,17137414752196927825772499610314584261795745874954692214656847237011815603711,20412422497099028107138997806006051244688526968840932637543351831550882135155,11225636734520002481404086272590673372060731353304957503311626880321065568136,18380442589598191047463232737740533198002604231823107797039491680652883496794,1080201698768913889646664841066956319958767123758689784419321296338840961295,14348402455238680465583355269916779409600823120873923092214453448424409970818,3841435364722615893087024818655055436552226081083242159440517874888324292581,3408210599862246992363134715624815235769905293647431849706383726509064300506,12828232946525727915578787875290899244261094596690184893334123105536745936334,5483797730688489537248191960281635992343565537360149542110268773175134131314,15646042484365011867018844828962923289034117590475224947755290094723626891273,2658047411395048849255440353544966399245817841159701280361972904541325691434,19496407504291857422030801612379213952698163884670351003527359060477191854359,11599969200544990318778456235768317543324325704256981991953010275435791017626,12534635949431553834868179572769836881352677117158862189611147293522496413113,14223314197724082301050736397492110631416043159307338723464864105007185825079,19822547161504065277026677714514212915462043072809743766437313193660041742198,18248624683501549165279508462273639851850239430868786828229911137041335077425,1772507929668430466250295341031184282507314702999122972093244182511342701791,12698826328883589821004991321815018437184890565199562478819948777685095680390,2107256591274868946942358544310209350935597133418111664653447540003390113607,8347096431391887603955816523197766644723983907921702200049607244690524226105,7546736802459880596530318577784618006564482951653292089248497980343037655783,7337317896163766810388205540011597034395961854295494001017429381228506327036,7657535373588628884973408484470050620893383237179421367090832333743641042323,13132621069544809006163499228792832380417930375502811639756010731409020775733,3045981446877420174701593721028589257508837379178848429319604486793747007869,1665034234802535695418712526119528879364535660712727125979361452433857586005,7153904853002570654968228858836861252211159237410458977141045356668538557384,20486065252261216388496191302294274939758504298167574880569796877079451248375,21146476302842253436461025615017889905755773199293419435978649511293941220143,4692883070549935264853696204165792104522817067387529940796053065681435988854,6240088307004733902463222083449545201088681283438656231355545734118814247048,11555561118019341206516697020813127391202363312629469259248586095720628837415,19260547999655668000047734411254185932378393753746099027853756019009568507886,20469506109273046972497148219051635976793704979896239651651205124084812945608,1236647274759658638933992315999684238758461477931896092313814863963831171033,11384423918232921171964979139440160725835135313593824548598134875347314405204,19785250372370249720518667471906851686135385809175031332352733767471970846466,4246521523867165828929729227115582186945308737715737226156399485201514735146,9952732737001449699912255226665360960719170484486452179287528363081995818191,16411145939754797754686024918808322973332629854064127851496226070432060579489,18478056933955827759744830164752062474839918604932227276753757763884050277828,13204687970556138498219183195522996570326298997850204255083662628089078309770,6486083806326529246393301553077241033740361238170679962888274443184188794118,9215573806816888307072467120643373006129084289252457249266574218300367297487,5157456141970297671458245970390083650482632128904852982724214364911239574334,17822680498490868828738779948851745357227318213932493146619109948725716270324,8322423511882718045936027421959946860221136505721064786938368517081088404769,1146280240837664421126981150154328736275224000612293306261498532925677882509,20006445160687044351950305884447426432577260116801089758873885688911862838124,13132217654381318972692935199671458140461723506405656953229384472487720023845,2321904844688587860096390475332685957247396755436885306389445060312694195758,17673723499361727802425795357032445257876321564734597671004472729727016538966,17836648739374245973743495166940645001620159031723548669336786509810303589036,19509523664323410269318198214695596019790796169778932865716910251136766472034,21365014298519541792222476772118358897898683224332026502540401938408420183049,2443777802329356458012563966932795162347891060116795715814546844741577072487,6373148417441446230918754690291753760232604931431996749195267137425734054207,17543938461501434657363693054851238526018672792888706636605942303973500302856,13900881200135928840365427722717255359580153642574547892815287601924416317614,9982616108044216660339683982954165936737826707471259937628917232293660834440,16457765153339087464480638859689501343872608914611554385236118860039346779707,6882633521418674793651640056518599843365736128725139938457347614662141371026,6558481420440543921623853603383694405865402572023705828527015346924767906364,21119564418700154632542186570611885700968350571284986971813890102274419338575,15668498634043584871060292933787839904928585875204605204028656239629550300891,17754567428791571673016885915321661773655444664247443414002133544771398853149,11486839919314218506003227795241691164988634920977758623356018460082101365168,7521215937712438604222096500164256001666624136838511497877267672752282058366,1168385489601974578347279341199760237159478798101796567718644776242789923601,13117296414138131801834212262010987517820472685866772554743932452738843734333,7749628482107487230728683638475509704638633069294493147970362304145477016517,17102526463093059579604328209955502975564943362848110499048688895825859834607,11877937469390065191819717631885427975032604373385026940117533544572408798485,9490483077873795676333795591814325768750891664453067983811838122306462917887,10191097995163502256819397252907242166733175440759424521233105453843778654820,20532048353899648065110204116821557712236052515292993984913500569982446829913,17354150523998248091397848718695616500251280749145663998809707730330346369346,7747355680464214426243190602078017576496231133574539162185621451748634683393,8756715326391069596985357282435500586860011252775122994945356255643854963530,21536474090524236379254986352553305027867958936847041677436373000730213533274,19764807787330426181831011653714787282097837960248105858049804952757136862708,16451394978386784206980716591328721244692005310628203853347165858510983157051,9958807580185090358651106618892828843813431270139145526116189671892797920190,8667474404638571999095228348352836564567923532278597424241711463350637692261,9754527193113710990714009078343561220541479581342251031659489697296746296505,11755501121260346797952875679164705763574741595098729931802001980529024314166,17343653273660706017905395390969914833245644319150049521732399082825162090569,1010378412861729818622385301577181571311206842734096023690850995284550560689,12422787992288066268619146495902983268274452848893191113634050431879037454803,13351916057777123695069150362950067630454763506856720439068955445038740053267,3268740447474291563746626019604727880178668296496938516526099943483641022899,17039539378002212101604857371251026489627400179253250833603358068705093844865,12719626976782614661983190476189661930540289684710840404911817755168256363569,7334691511591452788631693316255271478502517924558055271367172394856435073355,4177321927122082121158728850724807513004613701936483594734414988911849675880,8517156232219806038206488131493677748028421797072860831547349043281348142926,5916342138159497146131772146268734765710150180676587683832045824388433290036,21136252379072914855830890952695340864582847490462136128874077543348574696616,10470343058787342159878702644341062172468027793693540114390435145428370707552,9367903847960780027900264774906616911120367129803429048363499797310012009648,9181708529218875829085211480957344367690955470310754169594385873272587183681,5161879954208731149141751476094480416185338457043041781556700389106447006281,14144603730790033561496908848503636331176898859925995171200576238014458649562,17528475461722173509900495818763366567939364295306035018228011778228457876695,449678858200791083139507971543902712490268199763356935472396275788444419520,16677139862336739737616497869711537864422474730319606529800927093596292773684,5307258894824770781811695261046705160386034275400321369052582330095447609528,7066455454850758706236264136180958260707829859148436565416678574940588976717,17464972536694182038180604993012612781624892485542021128713500864406129068272,1827574381303563082711258077787177320452649985803311391711223171032580182910,5005224603218153811845694200896301756909926774436577539307979565859865998867,13761569869627153404623558442531816440237410187883129666707204029577726405280,7377645231791556592153877817212695036000405157132509030366572797100109551371,18929000938053222386693378771208400814166536156735504775432130183653620422676,10277912490419902146704238375228669373848088391763413912903062245600018539005,18100670309576234559559738539779745691447892297890679181953368845735547051936,19792596568315968292503371918803163404916721074550555295039247624601141857094,6568943725774928078767297883788056758405958920376813493652098209237338819058,9708751028820311560873537735196353024741491886920686045780276405320332052014,20999195425108372543557431885250084840784235258564621629580763574508120639473,4668167020556593094762451685509419403613005848434427529155545560914783238805,10260166712816802791730167674468655124354432849926388591536360669342400828562,3588854010476278115364011192514859807683141010842317346600561233941024545452,955642453625490778540666824328669289325333312941525596301926803494785606357,4102026113333601512449185655242077481750021570821512149654744152647996823622,12901729067332459436197297782018174449541114313233855185609986472102830633274,1432400515841095916662233518576616625504866912337953671606919993429647264779,13448330934580056368019676193029108114576729981976748604441994201646531786832,18698774355061680075847219006041299002465669495077065798256778682757699200357,6114255237222848342826972972054203376750041293553715842262723528673741797160,8290432657858704891136963220676191057527195528510584103201077577863568506432,10245893420315465808958329213978599152040050245022584266757834865645078424612,16235075160725310956334026818354575166666144493784149178325740173109469893465,6096223185593495310139379444667947750109489326578429517185410779366192202063,15140535409353326038030605492985074291044727716595244779768492745470176024609,2176086602170005476358821348469239586548222322021168089824748815230407069862,13619789468668594404222482251836770591464929359372018436289664558758704681508,8310543107961996371575168146304294641952910047046695374038288287522235989972,7738370036488385965043396010845927300705713772735513648600973583706126470834,4479339978160586717158719172802732929733916533373426058515465717943672025882,4249199078635815430904933856748414549211196022798648243994671515262509861644,4217767457132611540965149700331359170343442048612092095364557557503970133933,13153296757017742961007840475261159306564053749538202546045661292791402275573,4396888098805340064553349190742819413046668458070694926676742098287729413444,16734434548572604008363129496559919254718993826492605430831689587940707338899,9015659000250675923210953833943081286931414181352124970688626484896488861379,7859006238840384066905305454236928888746240833462349287375399918976884871408,20111156231978127386472936347996655414872475039138926155687856551161732442682,20628144438246471187747981572742727430082255446467380395647482352559593647287,10829450719086027299358038584474043478547531034689618353624096053194488185624,3900905003848877440680433966861518022290921312029158328541666844523704712962,17855611209216805679188603521771950395726550847102335142668673883933213178620,3545647030011914165273791133303433140616659042668342263053968795372726840341,12285059161807384662955183653994648298401051593713604819454219983692697182696,11819552939527124997493513022814576182004246358800352547817016502521627790011,14301577158059901977856927221571457807294693699285069296999743154546478489569,3571634356329355229397931369891424491520267531585441552581855575412868351910,4493956823795845864156868703591503758707793967931549819151350879135230170242,18261935892851512416084887686097384445742684392402688030129684935728742717201,11603603642132262206403092178979219208473125803069223229133184466185736048060,4847487817017177565347080569283215504545281846426948697937793918200171528656,4069745589764729706654816299792297539062872486670505242875943264008484198412,21282151145529600768369623290936085172906963145870658008436208961308948924585,10721916615176439690683002129869911178402752315827226965537395702918089626824,20400924989628432852029073867249809947097995745931036434033577251949709693425,13612038717302251316998414209460162307179960669236088330389280060785328588738,2142054298626034610320009155682451576863946725173133307732467701538715335347,6814074799679801916559787533428482395152765022569535278039545933747386331226,3320993272550636151137746220977818986579019792097013138902071906802378678391,14404588996507110096126959822135132305375204264088975725278990285893078946890,19449156048766944910033639666691724350749810714682158108539166281157709899569,21600390672948543610212878389553096169635598817477527886039588952230732642418,16122909565998431497578901034409662715618749437754826295511086000491610510803,3814026203802323919937341565517130280297397500968227915639071188757380515963,6912908852134560099979027891279882003635111070588372993239339154823206466274,8991012532130902495044589989450658026455069044478725949828656540931441650779,19794616058753707346170576299297623557371037336156984230370345545981446397931,2577593820399732466692625387687370505160505291664134162589397465829320209836,10545990182245838392125531729060296377668723705525703355179325185018108067002,12532592142366733026886391992589159605208721772700692225488484422366892623887,19135911891605926936423877585461852787990719411437518367185457251216578059981,11635603342092216271740512684448806260427922119693878652222869987036671146111,7718247137511759231158297248913810065531288952022630354624599924037308251451,15449533941190926955831618735652142785144234166497064450979389633622292725920,14793399192194938994493676084408874396657844744757917843286252680102153699293,9379880417179271734210305738187417887144762048262218697049423795232738616822,10001585874846875226646763599153358317197291234293545431914341192928883246454,17564611789675170872923370710570629576001514727841256489502945348076745512773,13526676577413987112607573245391605865887231830025935262602066777025060147701,18771091487566471187260929156402254761992313431761027006794035379840343952064,17672790933843778353408361605666344788858296349839035375070469185645819063077,10136925806345148466019786355963896194230642602748938687391144254701550469628,11669469369568255529354542182318275079656673415035219767446071893709388727608,8717156787967537877037123555054580463721012975068417092258849467938967272751,3574689732222366081898222156809576015147776290993716837975298246375762980084,2936447189567283726966987004410103389002644634186413346432130822474131530801,1699723231413680239740710996339133622208402062115605498128909025253321290927,20239438661176091033530372775196947702401783521122338633601531691101072063415,509222199143055079823531599510182326541217708021228426946045537726376153595,12460587031004227589188413497497959758507406039249371767737225675508588807598,9172361948368872306701383997811949982264909388810393902913358291336142380374,15024321518919789320143737927991052999071746110692384451602809887435324670247,19363337726355099236128975299462078599854604247644073095764375371642393487744,11352512845451687563998689687452223516295911399723160879302208800753615647616,5033097489048897691788022265636063060230313291173145751178865731392231547832,9342768693529219155995840295623046316860027403351256239528640640660995546250,11343407235843410518451234635552443892628096773317032816539735746541252484029,20271637634427257791277080766628733956630399511643807969496831759934416995624,12979118904307784600641734806775453265865076574307149193300157552133646759000,2609049561347471594361989318849223604030501563821990609941361801853208873325,16638136645184843973996251461253142824084602885453534706330402604048300209367,6290150467317840195062942193162131367777911299731759519747208884085640022080,21846903793348064415550139579740558481601211918214432128739680250084492380404,6881355315007836102200696266576401649721953812561017678365140505591991478449,11991852144633415808902015898168146769921125504309617193757255165202163636329,20579180498569037366675392921380645532641402855187025365767529341564826966764,4127941604046459390852849136716344563624191244387948802112999500161867081345,12726445769512078351769013120614118104254671239018619408743816227993876252991,12822824504588887927083519548290538468815267612767490908011540889502830894241,3525790082239104371118456157894419087904422095178764587616607951352330724979,5534817540911273750657456222142677256882873311813581893871590176089715612985,1615881228089658726040568147025008122728572958650432110106281742560315865517,1471725164982594409495579793735446246197281099521356897919523009694047660159,1375309198078109412495220212570536673190607625762682203229827372752214429058,19114911117517497826908513598723039822664580418797141695087511229965144677908,9628666313906709051161166309431160628627430386029173286325286404453712266410,21852518218578549606473925058864730694915463701150591631085298334480610743316,12775432117186202301959614842766511797651599815903402927721712100175714308106,139892473068642488659633517109052420816080027074176062905422560867217142259,8678567564479314009205848092936065091488089332028298130303782323700697895584,11749646464324896227459490085151303579078783519261033148424203540751860385879,20522934943803615109303532925965718163549240564060985032796290524829499285217,20661244899066232726889114470941159662948096319289349895724712936883638757146,1712076112157842791409364964341168524175271666408017461435914200921357859979,5274198338007371549113715286886410970476178374473353058525495747031417868052,6737897812641394021946938592351495323837784050553060267876717564065727066209,7802413308864463219891658906834234180067201307743855789866460725804890591074,10598878996622948168711729113266592565050867869138946404948068606726933771770,8999501853368885436259381006393167420075229434053961224100936590306072807402,10154159140828416502096070052350440839365634698281866510618130671547713671046,10116420503162714112005525549243891887026278400783073704446798028762825422117,5545266571933610687233921232979606259360579780771113897229483385986421780729,21233107093610116862049125654360754386798111684938073821049243264439651570366,5307392033140435516838295705521564813869712246929667484768640666687057034707,21375317482759736213193607973501605926935171024163842355374965533706641104549,2517892809920213533018018674089754443879541674948230773132283920676903837393,14360345633113115894388501084706102426582517876835778852281477705852716869669,17053269301717416242405268053150416723822210193991005718303172171427452536837,9906602428995106334942925928993621430906117671319208771657883136890126991982,10354603022009709342018106446249264303223237761462844795940043835225457441783,13398916116699661698644750814188836272580610770712272177556442659081018605804,3191149493139822128538617654520106298782669019011287540692938944153323592958,4691984423256762483396977170887219469164634656601998705889064679728271695271,17844101314007938193168524989091446035911779338131517299817551328197378135054,635635940269936042377013194809642013073936660346940411744079076043939544740,12630888356903717277892931534313436641457206712723665520324533786104375264085,14140466574121870700874387789856251566070511990708575066948924661369491559256,20370174501238434846223710470633284656345430614321812270231526837854520663574,654339196866659831266130941576738975707930915283825590200406138066808189370,5107706503321722709363385752813500904785775244074262870879244969961234309572,12198789333458214522406820255828653820578540569170284513887146039452722146485,16249136895399135618027043741098607972773831911496869243661084436243711109565,11074204104909151859533339603597929732173550047640253831218390211736882449440,17207343273400097590016935219508528858538698779767314862863101225959250875891,21262587236682681589242692923329018584317630804742733118429592061667487058638,2280753183511690306986430331340197673251265546818209861935234085004534230414,10254003274920664842497725816382563578440196723429688051808776569200020879745,7759959068226022198572347902743272598191759849179433231578496544131111538092,14214316923200364820492127575076874888948881174491573576707716667988807435892,9095544195644789922175839073929462149959586189940443682544660563790242551416,12649782796197868227327830841571149621604197483943737926454728454326532192518,16667983042241619901264223140344714132852698906756725392221839503187142280785,18383173644675687530390651274503384113459403614974472825953064896216388971884,14628141534803375030737634780152921077373561843078668533631869027351905379871,4561456211241649459019745200365185624320798675863426759321227045069329801664,12289778497980320566229781933786841623485008232338420865642173363101571189872,11975067175623680843959076988032062157059134808170430074549557650028254491562,13608090049838182253377471459358669610089588259298499702848843266957511619603,18788677463812827554544269966162484344784391485047475243938219549074331613206,4881667965195655156201239071358064948072146968570883219541497388280721871638,16809375763554448903183355905513828131657823301396908506126469252462160193891,11654980193951434743713680917141406309927211470940308818720103124789012440740,5948986090649283108120495678646398398833638108013243775975352725637369743753,13726437662355203524944601292802877111764435687388166013301616156301223567122,17457684154769676997584569814978347304006793119360850469355899127743508915640,12768218426713967613672155360932690915682228245638743313771591055379281067565,18615157783057763780308448635283319685644271696762198401466573335150909781420,17036103965935103170115214353570299052411478859579659720326549902160146217969,7150547909167136034355368387927463942994048322819447869013206336674786486676,2719491185384365067577935615529406253538979948934035375021293885648964670289,855254098406697810192507782360318218871612459371212156821698546331701832542,17895542168549626634871327801987932137768300191314912757298899767762396172426,1291731410872228901975204398582554998148747251553901848273154130903421546804,11405841699040163552814729751623598889450140001218648787184675782417123019196,20354628821067577915648505449000078769730992376974982139779446148223962828730,10728669080369994464716817080074001337835696213713101955141340296929303809038,12274798389677182426524706446934567986140214102647161938159083665963012760572,9739537323825422719175243872981907235223292084323462340852187679763167385510,6755543715589769777862111458854566169790920787355600259792850662088606657716,12126305553295538434422174339664597983843351746744739132557070380077267264590,21398878068159838390422213444802849205194012142590812651530393856342428295355,2774987220129009778448086748836270418387857350731020745311729965596748575420,12913355749231079157637607439722332211156795881932799993926379679617800720875,14002442102691266344434178456827064608589741346471232083579257521903268988567,3222000382376546717389770889292702303294866053055569943089969635516575396692,3351662579522271904655802780809448930926900026265684873057471441126697202347,8791346592452796050710862947776730913908702488104309880248248201823569029744,9103312554290751080966931020955359921020213554904162168782078094097630022273,11400762474859869669799163954742952133400547669811496311736883651700759825519,21705862854411927719091657128107442151318579935925212397760983799549487960024,43293469326476059594440269130071583321324378720711508957751360314337673988,15189563636069530033236842376689049504908622054060814965474910283072587672143,8828581874201341688220445093730125081012615712886123840297097551587278948881,4848334665131642773713411076824550175891079883511516252808850475348208758729,12614662329834759430739626588497950629642362637723265950380896878486239042155,14266355110863104530316810105072189601641436180167942829728212140901379263956,17294822327168915058983104150822364346325840621309612804535067234675456850670,455077676048323303580854786776522812365753723694705688462762996845811407009,1883008531326217838820507370543781882290544271112198177704053499351851681273,4529982458238957976485223202768823175919650810452913863593242825418350872543,2955110035783314707155321084983433537364088072013879095266124577362993635626,12967684942790110900749491528799008728014372120122130310632754743394775825471,2505175694719163834796124853767853797404065196427012487113935936321224863546,3664644243909527501109080877083112285282350623935581596506736195569817810680,13149615309511991949247749473495035486060198385636687198656459619774102038819,11675634552285986901460163850174089221624080337542386824203554725353862698973,13792241875469760333807839408609766753472484847219134966123237707758891089388,10227619387285566606296112062328719372414665296090743089679008143127205545123,12205580044090621048077686897527020579927082420674484835775119696613313405371,15208177648579495968812696435767989756568450150931633443711377393141060828911,6203604398339912597796330237774861234098507297133105016255969208311447220376,8763991852009928642943035844463232737815423121200913107779495834216057423172,94997075732443240393502290740081268967228130793200255689370554790238240979,5269706528648934838705302424114829386876854870088873864481541735257304941866,16262872163060208420029150392453401749302720607531142669546071916932112668551,8143677473154806611855981628530143157024134934286519271401846470427527147543,11345763412284980808950171535310000445785575947246043879446971501610507015402,11334003190684962190461352102674801284421167648666972792173808801060633658405,16679481501466111466382494296272414977838924060754574747550155015005991797168,8717276046214261706367755700328685033217888501922395351508483646143935055357,7961818553714372394804939036958306706260485011393197807672306728909086465660,11525513262393719593247460022637862437588876074380005892794471847411833011017,606475753731577839300896422047168640216288859417610094202862133247546805011,16216814510391154599441870283663624434960433363418315765904453229709017881340,15952802892860522124812654660125132147349553268606042022775941410073735145502,21186206422036180717988803903908106965745591204944021637150186904241796046981,6944713991333056327587649834988524981544213700413795245346955488518554424877,10185921515443194095530439914620341794217076478391514698779175769548747359464,2855919726997577698604215361496800379220625688194012864111223639042676660976,10433229026112136773123800168383892031427061365180473556460194903407247351339,19427072191035469870347195569940358526740232693667547123354147821192789102650,15644214414239800285411872105206002044880495869535621299007907341206661859610,17127893436675976263942308327239908450163069123121279064123261885014993455970,14398850115453023364458586202624524741971410970483408578015632196929131043640,2352925542671141920909613532344506652984644250240272091365991738093178607788,10172679680316429884824619312723045840067903978738893283037233244389430249509,5772194565812391639885669321239603226420464592665765672957012371288977540856,1472565977275775489403659554782408548523807638115405629626295474159727078930,13025952383827165156872004962772766979272981810832459552230024272976389350529,17564758020035152957739819749712385631015761969283204715352893305611222727560,16405514590762165467156068648660873304776064039873164250553927264160414855875,3690038285204558326066250230248548873947936562327070117434442040765096220855,17531140782998595396669833094850381400841695523035934903128529012616296113949,13168227885444297954910232183764567700890648537512256626187184942939569199780,18839532764289221356950914594613087164434882227921649252297932780104554074257,15690093187279544523035828189537219904387587938956853550130942856247262425989,4880718242480815050016604653617276367751146942554754727539176934739417585000,5767740184065294852679113060036925102298292735253600173647375101014669432601,15274885987576180935369267696345371924274924872703997373047266442038483500100,3761934589481780435501384301483991135823312027596840500386086136996196777919,17076314579416028845718050745024649043011795764818118471181221546277962595385,15977291426665432194805519962451891500931039499992781917651419845757747435870,16614058019242709692964725060926415535596693985378737640811775269245183858531,1462290731020299561638622134991867491216642860791478796650694102212515942203,15285513431606451603488599544624561225569394909979737124945690710031449859251,2108108609418057784389651014871434275919186190456064517027979476451544519949,20785453923508177251995968212118965193411372702846000862603422090322205734041,10673883530097564269607463521683039178512337022363698173454334902283390457863,5454676180617583613153450533396644120109614173104204009158828769649771925347,2308424025465899393970422846699273218513861797562089060060302466408498727592,7521209677407171946300925747807233725946342430543358547121236461545495788103,20573024021944297233730031260403312250074182051596062256738574515403295322803,9021049816696497696749267473705619787233696328020950183323376943545740004437,1865524799085825018345305851095200435959748376626055576269783687778950437080,4246459257342056987998012962024687622955192847494871592608632692951161262129,19427245695591302750338395658196139112041609989862338102918570832807123117503,21526088318229932910068935959652342185575362039375447361171773752278498069664,16191911454644420751852228901282854304136684923356871310294001321086062307024,19158667047991453406718020435447139785846629820299132383267410641682384370576,17700355947456307421977232728703295781949761612179494776757369350093380226828,4397993077875324081650432554749300545148338322818494126385494799541152486594,7333345984549245920976934899658584162392463672999208699449239323807521633803,16152786000399924760932165522677937364378936868710087711558780050692283598645,11094138063712503930108269043784479707229515809275605844595768164840752472377,1142389644011176261530925136868504263430131536560167284105696375014595703389,7947253178759456244011070491140902256859556283134055577001208685178146652802,10134714213573683528928794197545260748403530346308318902760067810116839777206,10883490621674448000789965625707254871804535943755669299023415555830424281655,3066669045698349285650257964282463204141692000014900401186330770537030238642,20081606580658665084706560391544166403289461596409550084066896490552960642479,6155695406737593769799569079058291297835886186017961489006277167996716002247,8515542419918302650566740947332213674125125387478669670818010011334680546574,20110138544602147391149732696810223660265845787019234225223667638537351747051,10742562600839811890186721654855708402836531506887842079602293928208078373859,1525909842404376057305890458989201366856740974115647536551418424527131666169,9234236770964972467234889051483942687447344616202849085905582739078803045160,2606008597707158849245186414604531348516676367660138989733829835914698874012,11796760152309688912186437926169763667717914107947289133346750725444306914631,3851377590989618761627509080069107348568977801140383151662774695134986557597,3154796336225549288800236024241376487736097402096695364582935878596928093781,5510420220665221034838403251084456079592641926247054056939582862556776533398,16879696361470925506825934570612427394067380616879319126544582610342257894977,17284649816450637986813517327310560148892948427878914253815654865007623581799,2833030338755501226260678429168722114253235114087325082893557705288230185302,7251727070132476220556183457711849452579027647540936257172964240637390843337,9575600794079237337218029036087316899348403790684983148717343996829930177678,5979306342004680208572077566967420789575741134560343288662733429960668391430,6933647198431187357226909706624729057428619440859131169201765838043283476077,19168763196217781731628598897969332495895458624888700544934409934147951462602,19829437720109810470479999873902618673477593710269745617035524777507262876935,10801527657674630131387061424571233632050383122132208702068470808513632048030,3324631869609728132956796851449123815871495758162118183753705724979320742705,15660020223439851550062020388305149722004313049334322631321250103301499692604,5967221174170233933880215190156392465136752773253659731223749128915793467895,11552412840249358443126681313794466948899653896063684296070673264241626555196,18888906666917921069717332466525186303442592625253328171173131193932302764004,9002714106167484391528827546180572105064179104525774089102236612700713696717,11048302793662652213631623254022096575352405761944396370134943300004028917865,16407259962762436968310192538354523615684343650696199890141991953040162326636,2164382359471710099213275616027528225843146809226250465653585796261822737346,10534211142437421383941598776341383955315039281979396571221999789915575101599,10666069653734320813631520107249402109728041265475244772290972049841823847727,1065893272480854115563003062650162503958098706206084024581187831004515125777,7996693710845330472615496754914137367924796497947601638820266498225398515015,779460584637732468426955849206233546264346430125102128427414524469939157403,18123487244613769854380966736011971128129435530397043581264858565849669710522,16483639590865705054952634993109499660754781472434181022666579985294889582777,15847717171578788545161470441065692492419364914649476971042627117577578420712,20212509548766945890162316166677458350544092615956421310024681889193656903241,11915838540527285091679839305488591026042934314354878896592571753630253407873,1911170159637126384084881836969666801716554202345435461162520643252230842951,2519681707616189243873692429706701363981726227724944939887394039132311807155,10525548620009931418869190498282964825273460634626042574365806552478535675090,1007287689974936217568163398662729361983046876939574893360458678319961439943,8918601076290071318953673276836220960249911431394510238963515695083601259416,1730552670090087588255812224149698933189694835321291448382024953001539943933,2692212389857059051251821082045515561682372012597270034725442717100828072430,5182752960118030069130081328243349382982053565156074602369672154634481788415,4186223293158399083027342405464955373429347225209836842209182753945871255191,20698226478040525601636369286446332773903307913544069889209490555501069209140,7848961029873906562639009619165977234892385836769337804546327846501965814365,13921935366749820642106107225856381492084238464963488385755265898574906919842,16615913254044390064369275838835406299949293202833109553557777908673881552518,17884323890135880903838623664692905800576770771455839982202688346472867240539,7671240599961467753478651569648667266853727017714987691902517051845809028276,20540170969725852651721054123169504183251616229771312133024479630289328600435,10885911618876068300178014171685162848957603467763239389113505729594133953822,1821956738503711086168534921235313501143676686594517809385967874500584768914,13900019517803309945097308036151373598859036005433194049333364013307418921490,5611521340578197244418404931199594069340846248086844299279812110836336410894,3871676825880602831129014665958446397148564007925285835033897270539554583982,8660883522091722908446182204212531338997991855689061026827047565345925404852,21369377758054514487929500216341215576252815582773920801000959327560535036910,2412441365534353741053138780929948381707801794421791967644299920632399699760,3962365750665624098182798369136001622041855947680873409890054621414139629589,15001230629104674518532645948322038846835064889071294141298776340346988584355,14880674002301694876681052915629907300219131310128131182663986425102259721980,1824158054562585980316309768551123828629842232225429989383412402628330419987,2859240361399565691265380107352020662064288346296545444794991049234114013603,5166447910779952920543762328108096228333459621541947567522578212254733957716,1007490453560275100906582245944853446313521002614529198832736321283620962455,12357031909288499920427512282658173574064133416008366625033457013843709684703,4908601693798278768903637729333835430381717019653632816739154645536641464365,3707521788266753982537350852704241176639571081938875735935799519005785641932,843648473424733414090549470297108007717585086811320449394192229155836735429,15745469357122732280411707850429686485179261034785562466267026969795211925342,10805521614324416411410037641243182724170403739698507241460822321812492198235,12065996971764501469604703952781437881524721789450462435182323617647626062291,18470487586372818033539023969236693307855263683332928699228943202064060965843,9678881733477238994400069917737562227773718359505757479334487914298656155782,14188770590313091787681039051598250350716760439974403531322107017294575035366,1689506610383677575502055715917181866056070036146379850885318902788859831848,7506643906911078844726412866492372822643011138706243954480387034094577464841,8878900588521598109866546176968107824348718386295453778616479348498221694856,6870283245627392817090238076492510507322368840526195161203457308149059064709,13770891113056770539767147807436112954402870897635701688432832537357791153049,8780360192411651104527843471573635887257900701816701590232913021169255451999,16171874311798197525909736376097249943669070404511356154621097034937309906406,5735048971584791925371366175024708991668126697294479025115320761565490442773,13229825087263355390945471875664433936256658682181329545626347347763439801377,7075776235062840728475772028477434335481293337646194082436681309306082067951,3621624535897102185304108550400513064448572525424419762329290603569136345699,8909048763816678806291702062491546272181098732106818908949274412295033032278,5679617488269393681126385387791795896201443046828191787132461584904242222704,10105279386430545635207898937992374339634464824905552041741267814807859103503,1875089455725008938828188584567435691926878726057441578850433616115151436992,7477746898926143788312536189451854889707733370802231032871868774692083118085,16386910598448767875426039948412876247096832715449382492730559004257126956048,6033432876275593677037331179852069653085950234927263672572175689211500790655,791047936106933006999775822964245334290371384592876255418502363688874468612,3694863804142244539430013086697918876101028434198177049748051320963196192691,13376682105243214738309576815193178135837123827716063891638620885853287922296,13805679067029770984721773402288418271927678860935425166689344094492548637057,17136756160106085935819446871311843510549583818138636089816199715569134828084,8109923439508142364330425377154151984256104223553589804214354752109994937475,11286249512402084538299269911568404171399278286810916548813396237061620605376,2584359677745194465235893977254941998996461095474372764450843406506578038395,416048929518775256195106483480946138344969950953407172345234478269849793039,13382468529403508085121262401866099849753365548098731797553497976873204205709,18439376867491626480684697800985907843592103465829293677253579863338320195923,17849262151524731521717998935547978553691621192854239431428238124396600612632,14944765584636478787586231666077419063063746476683640145827104348311750508175,5770158920816863002535760768793204546036568907423666489027939717423021627834,8964766646616906071571735802649575322546984330618572612076303377141821583837,12741361066585979303854420163873489016934487106922559130204774618881492938249,17155650977068989655844853330647332708031817408933941319367040661444377002549,15853135222927269109853709968587618568449580274775781838704992776508260190624,18643405831130205120436044797258461126994691116505008303058249039104682298143,18381699905134802759607923737176411134148483921733890751508148644565049938661,20771413818150322305462626795715653983446198751749952090107489229813229842550,6565230743597462418756949526565014729968376635326046194605417268756666319845,7773589221172310936780704579925742277511016906417542067089964629576305572209,14322739515259154048217383149571029180760938501429981700631245079741667837826,2211777926093208827662641428669122029599076421656786665814449320380720581777,11959359909854207341226535525210590494408522984553921513181278512110987087969,15631964544474412103208297614910610111786652867610037534463100143218625118186,6469947677147265061709088012775208497425320831040679910475868641704170242154,14273192286218513903657400373354426033843730885130815917604222619132646117025,1642305946822726119533692746690241550779067996073465721872854402290979482744,12434472654594642340204970901697561562492434882039006954954548364905225683590,18258333676501263903599077497799178704676070138517903780843551776313851126197,3154393734777301102615783657097778679162307608952237328943250741895135803910,21442924273325571860480847088112128477994226721014369494483203254968684948447,12633492209679682779165226815843032818326050497846354378961630197925565487104,5676035885913185017175294353150288993325590895201150557890586619719458353554,7971989338965840486933559372839713095797443968865735128939127037392334228821,21734085994605079916025200907658739534755548178328895704833631044593482792710,2240615781815075893018901266381250882106533308854256044823388761533658366337,19418757086351270137870941178188715468785231202435740939860626745964359442005,17658978545567285097910442499706845586224912649469751675828983048696346031860,5266889563561183172939683250833485521316204021724495164611029326138684723583,11128996685041402949333841527417312168812141699419947558499636572258705639448,4876070090528783965375514438749842173086453529590096369168455769565070437109,21181864929467364713132566956143162901336986129207766576689052262132856884478,6923705508410326350945166370499325965219890886201185955752583121521122421736,21369826512764035509040463750392604795868027299873193291279213169276615858803,4704097774288345414783119239472343512761071550401447208590340029300816575296,19335571041256357691347835994830129551703141581491004773597606130380555930148,13594634273515260829141229000646270213542265375428591690952060475706589483636,9015254066149037983117828022107604427546915195306105494160093361353622246415,4212072016320343773172520900223699632828574585381041109390033407447488634385,1102272748190005338904701274717935307889530536456982005034282115032583335111,2736300324710728232038909644774832551915915663932530690557461126955645530086,4835822801818378290852301048163831283974282641105089345434084063764482095069,8984658187927452678459930452346646248663512083082894198317485712426204609811,16633394668571656740012069555016467267297836103775110968049070854163114237249,19001311544890254637467757524866604779430904938238046630395635640108752440416,1519708912837962563938791348422981399413816048437970967955664087668434079252,21331841844372791543710397499630585987940452814579176990050363535517182938392,8907423080053260966677751803467685389883909962381980865910698188903614425511,20461083176034684313938738010980183835826228331514122093950995340802162488751,5841016603634386755712428070725428370463826644379529834480138063613116133165,6169966163271811065481708286709332934104602048421028222790926506913444959185,11123503881380576416779399092503011764979780788355198614717104650873109848686,5910862578643213547409014086432565110080048906429291885019036113399453987536,15326247930625028665035962093121096584742207235393215425729927190450227004180,11869108106148533163877422279522558694860624980410176225979111384418155447592,11642189959177792725300751489041811935498998846917246538427709581655066866054,17383982459896791073091103411713034950019457760840905433100761135071197717377,12914884881288305014413720371780941499071473169305332026567402160980899728234,1208570539962036907751277903184876797538221568150857585830629441131315144451,2323312703274674937703540014228631818729280611690694743543061204714949346767,17526158529185414889134597474769916490357130956125485429641429836800727655323,16037781653504828212828867735133494813590828457250361954137565662868257318996,5407222038113928707955890035984954296613370389143420455278606330416003035740,6601323218218927237946555844476405370566012808107313139506360075146521702852,21534867504549849931394770956914633425223988570769925897030241609788158519056,11391084204734238133980784274225569005339670690396227409155789097373857915450,19888681657658973285687297761078939800531741094128408699392512189997402853670,5332577406232753436405602237019361733171667669604896195130680826397119398314,9059600173937645065621009092166260440988612068018047518892978276246308722168,5301647598491778367767843695092267888185214608095464352349739315757388259345,15071875841892141860455823800612444188659593796102096590428526661356131692597,435778089283152858387915635050172265804266241934673566488879021420875384052,7253178577349028822394834490127746885621571949621301778647260365262978601526,1165301643600280009322317413038719889346104283514223548696059636052018656756,19642265897347119192967952847445594557926149874981543320111550169192389374838,18546070171142820328487316603855788669722411491547154393382552167546945234264,7547722208697813989490512139624144757215998986985181672151192221427497361833,21765466939205480830726051696775103538365853268148356693813986094780619132689,18066916718526031105430041386116904278122614509807635157495047212689329422097,5567247965934318360602471432895130358745239227464728512128895794990091560111,5268155242325913085615961568740884974081158441192412337454790453319219641639,15275184776514682919662155241139211655693258637032715569152004434925162363584,2179932316974455074499483491372661376888522799119184614149917286749483028849,4621405833740121725678441855520519041228014222881228746009997774516764304847,18479339496682302897017710580780845640172065272400836860950352488372424120096,18557033214894447033261016367420154444088029564584596463030003672186270737859,17200647521217215683722635843299601233863161230648748208816378327209201596867,2688200399163263049122461117289599907708945179806531635658550456745433215543,17415923022624960613510570384321832458760537169605919976471719634183381965151,8535568676654346647569376193583594529721160524940659464514765031328360321359,2988350233499987577118772810582267364198360724494195915351933486792072227259,6210620559937378902878629998722853418159056595764204463986805098114518009318,18310997638100731876764014221687199913435941820864752235028122857262977059320,13808863093029019329144013239638801163784179422135484562563156294580677444841,12914098780625672320372746314998075565042263956380764233047047668841824625393,3305953095296069725576430940963322680842934544212876613078125492458854044556,17822002370183286453254419050088898676184956527990121400547957986510775899261,14649614548507754711891632411080554775651572143141206447218484052001553765684,8109105787614676314388565737575005920261787167569229710081822989465469152070,10883787415840547710621559198296269932318487849486120162467244238276174398529,19330421887539219495728995383446553835046303504116353064676615752269857951508,10124601385542856860656799235536724683363368315551234368605365576161456958605,12586681054057195636996904714881904902720157016325364273875514276164279959735,3757165144866249284026269096089043031459271594379869902321741804365836799544,462405354647627586345675602760959074379157140949064478801734872040710235207,1920260561025181767428737283255569518557618670101985233779064285550376374001,16427781514757709627041602025461703818581117100125480080881962557048804215419,11285710669637766333985664845741699850953316015510407645702772350620723934913,12651159368793078896654108663982020308442449053255003548814357252262150375808,5416603170144910655254279621683623582654125103494176617805338836184837812634,11735378404903665808621855768545179642393017572035737886573368447383433091210,12201557541429330882554855185927797569372240536806738921957792139394552229540,12315234857861194987612137097457466405047598720463755079786381945885951345726], - [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] + [ + 0xe1962c232fd0a6bb54ad8962a82b9838cfef19d290a55fc49d6debd061cd2f6, + 0x1e1f45cff3e74168accd0a94536fca6317128953eb47d8d2d79b847b355cf51, + 0x1367eec3b20cb74953618fd9261047755ef7f8aae5ffe96fc8f7d9a02e37bd1a, + 0x2ff6ad40533afa2acb78c9b91650d7ccbd274b09f78c100479f3a4d72956d706, + 0x152c8c3d9e43d90ad8094831a74af8151fdcda0b18d7bd8374ffda68d1a5fc71, + 0x241707db26f96df502364d26712c7f465d0ac5597a309559b075406351a20977, + 0x15a4e4728a197dae6303d0cdd2b6d1e4114a9fad38a530bca6fd06ca1ffc1f56, + 0xcbfd63f363978c387d656e93f11e336987a68748c8f54f385887e64b1075598, + 0x1fb594474b8334f9aea6fe5e323fb0e0ac27d2895921ac64e93e524e4ffd25c4, + 0x5ac55361da931c1b4c560aa8dbabc8624ba225871bce224addb5af901676aeb, + 0xe7266f909395b5d42ec298ad3eb73f6c11149f491164f997ea76b64282b9af5, + 0x1d928ce916ec0178a2c0d8a890af90468c8af68c4c128c68f042cad51c6d7895, + 0x11521e378f229844263410fe44628fca9ffad17eae9965dee900ef14a4d2d6d2, + 0x23f3ea3b55ad3710a0052d7a4b9c9a65456ef71bc4eb16c1e908034b3cd3b2d0, + 0xd4f972e795bbca8623bb08503764a90e4384be644f57b4a56f1e7e1548922bf, + 0x2a53e60ecb9c00dd99692d57d7a54d893934468203995267e83954859d21b595, + 0x18583bb0a83ad2e710369475bd54ae1d821d75a9e1e870df11c154f41be1a632, + 0xd45688dc986f78e71c463b76ed2c056881c76dc552ccf8d3a1d795d7682efb2, + 0x1448256830ab79d2618c6ebc5af5624fd064e2a16194e5a0c35c76fcb094d371, + 0xc0c7912bf67c273baae265c68f378a3fc06eed7778ba6ad3181428bd55a148a, + 0x900cfc715edb109d3e6c02b7a578326f57efeb3da6f58e64792dca3452a55f9, + 0xb84b851d9d0d621eb2872fd75b848ad6a905911a988b46a3d0d70d264c8790a, + 0x69b8105bc60bee13097c0fb14d05a1b932d37db703f6ff557675bfbbda8a5b0, + 0xa0ad082a6226840334524022e1d3c7168423449df9c2ffcb44cd9d4d2302325, + 0x18c350500a7bb9fecc04b286ee0ebe76cf71281b4463dbbcf8e266221817d32c, + 0x2da317c459c0b0d973e04bcca9c112726c7618ce9760c2228c308b7433d907a0, + 0x232a07d1aef79c1113e3ffe7094ac379cd67c41981b9dbd30dc691eddeddbc6f, + 0x6f8ebb8cb046c0aa7ea795744cefbc827e5727dd16d0f27675d99f8964492ca, + 0x10db78837d0652586afa0666b721e1c94180173183300992c4602c8c1c415478, + 0x12f5fb7778fb2b8e1b5ec306d3d8f2a497ee4e9aa5bf1924a694d04cadd5c526, + 0xf6a94bf66121d5993932988636d0aa2479e0299aff2cea5b7efc311a15007d, + 0x18b818a1c250d6f8b77870c1ef5942250214655460e4b5aa09c8066489041732, + 0xd25185fdb4a3c65e05963b80310584f2a6069c2c0b07ab2b6df2d04bea0f52a, + 0x63666f719c9dacd3ff39599926802bd9e07c61050b10ee79adf0da04c59e8e2, + 0x25f9e2e4766cf4b7bf91a63f7dbe954b2ffa4cee7269933134b5309eaf9d702e, + 0x1237a2bfe7efc853fc4e9c4fb84d8e7c56b125286d8bc81a5434c6d8737206d3, + 0x149b17921a60f02551a03ebdd0a3a71f7048d0f9f47893075c625341ae06159, + 0x21e129ee052da457e94cbdc1ac5738ab300aabb76a3cc3c23637cb6221874630, + 0xffbccf818cccf47beddf8558b8242c90e41fb603f137b02f0774228d6978d94, + 0x13018c64072bda036ce65310501ef57816d397a9eba56f87b56024bac5ebe9e6, + 0x1b009f2e8abc03f498fdb84857c2091bbb0095778f990fe799d0f2c97e2c2670, + 0x101546fdb71f32991c1180cc07eaecf47920cd0704691e555b3bc44de5c5289f, + 0x1d1f66a2ec0621f229c3f8cc7b153683d993e220ec5a1f01d42a14db46a785c7, + 0xc0d0d8c79f76f62eb8ea785853ee6aeaac59256172a14479d34101dc8e63ad0, + 0xa3f038a5f37073c1ea7a4edfc1dcb60859c1218e1fb611ba59dd245399c9572, + 0xb7e89abaf697afea2ab793f7cbc3e807dba45231d4fbe6b657a95f03f1b1705, + 0x91c47a22bfbe8cc067f70019ea1a2eaa9b381fdf90ffa8971b247812b977f6c, + 0x23502619e347553b5bbd886ba0ebaf4b63c07c289da07b0c7728fbd6092241d1, + 0x2f5d5281749be90119354e751ea126e578ccc43a4c372d67ae66d87c0c01336b, + 0x1ce6855b5db80c42971cc52c9c35275e8bfc7705684a391bce4151ad9fcd9be7, + 0x4f03f23505d6e117603510ef25bf46de44b95506011b5642b120b76c4a7a277, + 0x2f0f36a6ecd8f53af95b4b9514997ae0a208d89e974bd3359dd98fe2e2b3d41, + 0x1cf3c4ff9ab589d0a5660b86b5fdf8f38ec3ca5e92c445bd4cfbe6c70de64929, + 0xd907e14510611fc14612e406616cfcc0b3b1258278d802a5a3d7dd785284e63, + 0x148575fd984cf84d0f3dbb49564b397c17ac817e6ffe348881321ce76e35c44, + 0x13c32c26889cbbfaaf4d1f25e64bcb720e1cca45312f90fbdea8435d9e6729af, + 0x2f28f702d684198114e721efafb6922c3a42dd08fbb1fd6831902df4b55a6a96, + 0x5fd91ec054800f61ee128bbcbe332ec4c4eb25bc57781c436c931d5a44b6367, + 0x2a07137e0211d40057d39d707b177cb576f3399b29b9a7019c3dfc7d7a22d27c, + 0x1b9592c1a0852470e5fa045d32725f7ce17982505aa3317a7daa6cb31e3e359c, + 0xcfd305387cda42a1f5a8e00a0ef5286e0504738073dcc8713a43c2439c170c1, + 0x2e10c62b1b5566b5047f18279f4680073494290584c69708553c7729b6a04da9, + 0x2bb1653a56221c6263b0c62ab8a0a773d225b414a984994b6d3d5afd0892e67d, + 0xf270ab89bd220ddf62f18fdf8d278f678379e7b616006a8bead9fac9f473c70, + 0xa1301e2c189208513673b88d6b3238759488f79b99a79dd11d0bd1c973b95a6, + 0x24cb02fc34a8ce75eecf534184d7373b7e1c90fb5f7e24fbe8ec8ea1ef54e393, + 0x1603165537fda2e431b75d03df01dee7b39fd851a472243dcebc2c96d0deff54, + 0x287166d87790f5cf540ecffb1bf65acdaf18cc46a4f1164b5bc0778022e11a18, + 0x2a81c998baf847bbb21f7b7141efe84f7ac56a834c7967ea6f45429fa2fb1a5, + 0x20c95c47c2ce176a500fc18e5b798ebf4df4eabeba1d695fe217e003ac2f0e10, + 0x54cfe239b46d49baf4568088a72b2bfed0773be27f6e7e9a2c02bbb1ffa515b, + 0x8774564392fba9a0289bd2012b509bcc7b126d9ef3378da0769d8af37cb44c7, + 0x24a7f216983732c11ad301538184100e2cb090742dd81c09783918404f1c7538, + 0xfafa523ca9deb758cc5c0f54e485919a3b1c6caab6f322a36b014821c74645c, + 0xc8b11f331a17d83848b10efb6f8716baa92e649d9ee1c9584b334d0378b5318, + 0x2fe8b8a523a08c2e5ea7600b7876fa4b75938fd56c03c74ee2b60b9d1e8299a, + 0x1d039ad8acc6c9515c4b4a78f1b8a85784c287d5fa0eccef43901435c1c41942, + 0x1b89217c5104374c0b74a3a3ee0971ca583f59d0980c37566ef8ef363b1a417a, + 0x228b4d065bd84d6104e3828caed06fe9aa11d7dd8ea90efefc28489330674b2d, + 0x1d57f64ca6fb25d9a4b65736683dc6f8f90b4d5594fcffd6034443e98733af72, + 0x11ece5bbbbb611968ad64b52d89d7ae5d1eebc4169217e07b99dfdfea0fb69d8, + 0x21ca2fb7b186974b4bb67f95f943a07adf662eb02c7392d9f5e7526764e7b986, + 0x1f47138d833b0c8cf6294ef77d0ebede94ea57a28ac0a3e64bcb5df91320f10a, + 0xb95be5cad31b06ca97ca74289d89772aab0e8007d0558228d88f11364a1496c, + 0x794a48d6d0201d4b3af86c0fcd5479391f98f75623105f3e266dde215d76157, + 0x2455a03e833b1dafa17f29a71fd76f94d8c5d09fa1fb1665373d509a88f3763e, + 0x799ea93d781c35dea4b487f9849ff1800f1b63cc97842e2fde69f547bb76763, + 0x28fd070e349d506942cc217a50064cfb2e3ebbd3cde16c09fd68b7e4eab1b822, + 0x1cf5001c9cfcee852fcb9f8d89e19e336dba95bec545410f4435b5b01f4b80d3, + 0x8edfc4e49ac404861074e34237a1b124e4d8e5d6ccde29d1ee9c043756c44f4, + 0x2ee5b6524289cdd37ce4ccc8dd19e94cd2ee72ff264b468044bda8227b110dfc, + 0x2775a93e2b3eef8dc0bf9bd322e5f14281eb5bbbff98cf7ad93d35f4c4392624, + 0x4c564ee74a1199444d3dc4261e90b1886d760a7fa68ebaeeb5b5e353684e24b, + 0x25ffe7b20eaee8f694fa81039440b5c63eca1cac712f5e3b21af1b9a7be117ad, + 0x14a1035368093069b2a4337027fa695e985b6e56ca818ff944780c1677a836aa, + 0xfd53ab1fc6def97651d2d66d0f58976b39d07db8c4c9ac195db0dab73060274, + 0x16476bc3bc364193912051b64c939c0001e95953c76f7a748957d78ccc881040, + 0xc5a52339fd84b1ecac4a163b36d41941a156f53b2559061602e64d2dd031039, + 0x21b63c30dc0baf2b71ee86b7d5c91da1c17cdcebe5a0a0e5f2c8446584e05c20, + 0x1bccca220986d8fc3d22391a70bfba575a47b4f83230652e1772e2dcd1a06ed6, + 0x162a9696d6df2a13038e0bc6da2f52239951a204bd05a9e2a09066cf6b13a6bf, + 0x1d661af4be59bd53da92acdf5736a7dce50da796c393b4e43001d27f88d58d6f, + 0x1fb43feff48b0a4e5ac9b17a6c93e241f17b5dfc76523b65dc366bc04c9f06b, + 0x1e70af5d289fea2ef26141246e9635fd007be3c3d755abf3bbcda9c4e4a600b1, + 0x148928433fc03d3a878b420efc8954f04fdd4958bc822a6123df1d4d15d02dfa, + 0x61b30453d8edaeb5a0e7a3a9f951a7211a50fc360903c4b25a51e4e36dc434a, + 0xacad4bf22e14bf31537f39286d25fb493fe67f163bddebc3e94de911a9556f1, + 0x5a4dc602f73e13984177dc0a6f2d7af269988f872b817c837c8559c79b03819, + 0x1d1f813dca1d8f54d73441c814ccb0e84beae8ef4463effb612eb6ad131cf05f, + 0xe82c3574b61d4c239a3024d6822bfa186d5989ba1ae0597092560e8694ad9ab, + 0x17ea9ef9ef7da806c992916b2409a277fff09d36339cbfdf4687606793fdee9d, + 0x19454e5c7ffa9716bd1db5d707d4d24b909f4c718137ebb73a9661ef41a7ce44, + 0xaf8dccfbedea2064586771a23ac776db9ac4df3787fdf857db4a2193e934a3b, + 0x2748872a6ad3a07b30161ae37440d5dda279a12cc2ffe14747bf9082e72630e2, + 0x1a529a39f6519dcdfe38e311c7b0f661550e388870772650e1ce02135bdae984, + 0x8a57affe13513b3bb19680381a17f82101be9f5ac7be0cf9c7e61f710e63892, + 0x200d13b0170c124a25026f780273c4f557a3e95cbd68684e4e4df5ec00610f60, + 0x14c79a357f53469f91d01f4432b728551db863ab232525c2d95cf616f7a098d8, + 0xc513fd43af43ec6c905092c6d5d50aac833f144b9630e99483a83c3402f4832, + 0xab802177b395f6b6ad3dc7d1995f60eddb63e9c378a75247a08002d2986482f, + 0x589d228f316da74fbd8f0806ba45fcc1f31dc452e37430050bd9cb8f3e0acc, + 0x1b46df6f8889fd075b585d61925fe1f08d15900074bce706ea5fb211dcc63d43, + 0x1d2b938132acf70f122b64ae172ec1a822ecbde5a188b478e789c5c3e91cefa1, + 0x2308c203544d162d54a4b87d92102ef85cbbf1ab4c3c02d6642af038730333da, + 0x2eb7379bd69996d813136c99c2e66f45ca467bcdfae03a315cfe39ea99eeda3a, + 0xcbcf8be09e77a9b7004faa49c560e84077038326398196c04f948d09ac57388, + 0x72ed6973242f117e5fc1c344d9bc38d5fb3e94bcc02f48843a057e19bacc917, + 0x6670c3a568d7efb7f10eaebd727e7a424a5e2b40d7201fb66d0b74723081ee4, + 0x1e2105cd356ebeaaa12233233a2a22e0524c822b84fbb368b409d448192ef9d7, + 0x10f3092cb126d913e829eb1e09cef850812658485e5ac06c140bd1b549f53907, + 0x2bcf1b9917cb73d1856ae5dad349ff08660e800a5b69a959add19af6558884c4, + 0x7bfcd988feeabe2fbe03ae71408c1a394daf2943c8d32e41f6b72f2493bfae, + 0x2a977dd5735a9110178e2bb0989c7129bab2c6f9276ff1a9c4b3867a115b815d, + 0x229f01e653f7b280153de1f8d4e9eaa0e18e81c3ddfe9cf0f5185b63dcf8f3ae, + 0x272ebef10616ab9c79e34eff00b0faea7521fcea55df526bdc9e342592da9469, + 0x2c8a5085170dc8e626fd9f5f1186f99763976ea6ac08c253d025fb46e1526c7, + 0x2b77b7c7f7b862b6bd45b894af1cd1cca444f426d63571ffe6d57e608f12441c, + 0x1518209639e513d5623184871ccc1a02e82536b68d48395774930dbd4f130ddd, + 0x2417244fc99acce8d1da6685df7e33876bda3dd632cd684242a60d54555b0ef4, + 0x12dbd5616e93afff056e7402afb361f5753ed668d6ded08cc8be3febe58ae3d1 + ], + [ + [ + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0x1abb95b6e33243a050e563b5c4fd059de5513ec28994a6f60e57c98d3bc8f586, + 0x110d213a836478aa301bc1fd4edd388507d87745b3abfba5bf282afd21f7242a, + 0x18edb2d105bb53b768ae0137850dc2d2bf6d1303a1f8ee4aadf76d8f81990588, + 0x1e53e92df6c53ecec4c0de5b07dc4c9a0c5545f2abcc1fabf4ccb84a0a6e2c27, + 0x10fcb817e10f69f7074e64c393b807cdddf33c84a8b5cfe33f44b73fe18c0e36, + 0x2b1d8c11fc652c593543b6f9800bb7d0c9371dedb96f08bbbccffdc6cc44db98, + 0x19f473e40c05676d5f8d51e11336e9c65cb32828c397cc8125f1dc667b6cadf7, + 0xfcf3a4d9c6c3392de1bdfe25cfb86817ecb80c51be17d47f79750201f1fcd01, + 0x23b02d00fe2634889673a7d04736fe15b9f62652b1c0626a19af8d6085d70822 + ], + [ + 0x2fe429db8068e61b82624f25766273cd9fe6368ff097eab97aaa09be4c630e27, + 0xa5b604c958bc90071ad10618b1772599e0c8dddfb641131fef39daa58a39923, + 0x2cdee0c635a4fcd9549f0f91b4f4a9b628aa7319e2eaa094a693b38b5cf9a242, + 0x2c962d7d54a98c3a82a638d8c82450813f42071a17c6c05f470b44958f57ef15, + 0x2bc761185f59efb7b67bcf1d3e54da00daea067fe49e3f1d9334e5470438b454, + 0x2e450d1fe7773c9889a0be55e44453bcc844c94b56fc0bb806eb9982ac553428, + 0x25c0f87c946f375e341f72f6a8dd63a94e86f4ad182715bcfcbf2b28df6b4a0d, + 0xbfe6fc08e2a2e1b8911ae065b985388fcd105a490a4ab943b25558cf3d054b6, + 0xc182e438257c4ad7e7b79c3b68d60984e507ac597cb47dc31d913a7a540fd9a, + 0x2ff4d0b8798a82667793533730083c25223d589cdd079362f1e8c2e01d54476a + ], + [ + 0x2e750867942439083365d21fe760c7dfec9e3593c67de12a4255c6b01648b690, + 0x24e82df5873953792baca345b7c19f61039adeb1190592bca18cf4f907c1a6fe, + 0xd60f0585755d48577b465746de8e286e49925150f1784f29fb6b96dbd8f0ec, + 0x1f495e93014314988dace5e4e867f5109e09fa00fce87929d1e0ece95a449345, + 0x124331e0ecb1d9808a1d91efaa98950abe930c46fee5a30d5ad07976a5bc0263, + 0x2f421fcf54d77dd38930cd69076f9baadd3d3f1947371215a66c894d637e89b9, + 0x543b2bc66f3b2d93d4c1882039ddb37c70c0b437ac23ac5bb9868e6df24485e, + 0x203d9ee6462a586914fe7dbfc1bfa29773b7f9b3d63aea4120c601129c16660f, + 0x25a1ecbd7e7893f646f35d3e07ee997c94354737884fe6c26ae8155760db8aa, + 0x1d897f60e87fce5ceed8da7f2f4a63fdee7ff9dcf179c08e05e9e5cdd8238ac7 + ], + [ + 0x23237985a96b177ff7c01486ab0d603d29991b8324abd6b07dbb96f5c21ba17f, + 0x10e3349eefd3a112417e110fd9e832078e54b5f4537cd018aee3dfbb90541581, + 0x2168dcf216d8369a626ccc61453236a389d02519f3052e87eff9ccb8aa299c46, + 0x262903f36acf0dc055f610397df0794fbc30927ef185c6356bc33e5c31faef9f, + 0x46887724f29321895c2ef8bc0cf545df773c04baa097c352a4165395cca786, + 0x13276081db012d1d4f4b7dd2d8a2f8a5180d2ecc33854cdd35f9ceb07bf40d53, + 0x2dd117218538e8acb0301eb40adfa2435f5bffa8028ff52f96a99d77fe927066, + 0x1b912abf2e1649ad4834ca5b2a3831cc9c207d4d08e4bf274a79dca80e52fe24, + 0x20135ff263867f708ee0275170cc9788689c088b2933a361c775cf430748ef1f, + 0xba6d4ceee2182d3f2ab2e4a3ad08fc31f7f4cc0fec91ad53e92bf8ada3e278f + ], + [ + 0x15ccec857b25934ffd429af92c910db31d00dc1c3fb83745a31d8131ea5baa85, + 0x165adebe00c7ba019499018c96f5c5870eca5679c90c843d9527184a525fcca0, + 0x3530dd962ef23dc16f79b28c1fc1ddafe9458be15174cbbbf3a806de5f63cef, + 0x1b7e922b3dd503e6441ada966c8b3ba7b908cb2b98b5fbe1e4c2fb982455baa2, + 0x247460ad4580a18639eada69b904c91b19f7d4387435707696c40bac3bfbdd33, + 0x144d5be38d44c5bf8f3c5735334fb1a07c13702d86af39ba0b4220ec9a7568a2, + 0x269b06b31e89ff132daebc200efdc8ab068136fce65f2fc55a1dcb939b7fc6f5, + 0x62caa3c9fd39b69864faf701dc8a4588571cb31bfd5c9c3c59dfd97e99f701a, + 0x20e160f772998a2f7d0064c7efa15884ebc6d8b71821cd5336e2df14341c95ee, + 0x5ce94b8e9a60b28947710461d87c7757246266ae8fa5d3af3ea81776b5b8c07 + ], + [ + 0x17102ad2d98043e5509e76c331e6b22d5fb62d074760806aa675764660eb56d2, + 0x1fb81218feeedf4e7e0e33dd8ecbe62d65c6b7d4233f32e073571ff862d89c3, + 0x1cedc6d4e1476741c1099557e58e642c42892aa36e2d0a793f670781a21b0dbd, + 0x1a88ae2fde12ba32e5f4eccacf11c25bc163bdedaaa8824474cae5869e5ec20f, + 0x265412a4e3b5560aba502d20ed833deff707b7d425ba3c09f3b6392b6f1f4339, + 0x12691b599d32edc48ae99c7a73abd59e5b18f4bf773fa1051cabd2c49aaabf6b, + 0x20d4401cbbf92877ecf616d7d28551cb0aec552fae9518dcf9218c38c1a0bc90, + 0x138c03a2ecea183cb8f265eecd7e93275b0bb98297c1545a72197dc6ddd9335f, + 0x150df11291b680e3ba925a0471c7fbb30e704ab4b554ea5d8c07b70b2b96202a, + 0xc346b046af03cb9048c29353e1107d6b75e590bb2d422ea83c09a5da1ba0c65 + ], + [ + 0xa4ecaabde9d1ea11c81dafa8d5d4869bee7ad0bf4eb78397b71b8f989cf9812, + 0x1be2802fbea51003aafae82ff4499d1158377b108f8b020c82b8460a8d603afa, + 0x269c8c139a4f61e16bfaae9e8bbb1c69808c9071083b0a339dff9e4904b443d6, + 0x23407728269c70fe712b021915059dc8dc2124ae648e2cb549fc76362bc2b97d, + 0x2ad06fc9f81684542e0458aae19c0a7c18be94f1de3fce6a3e5d2335a01e90e, + 0x578a55f0fda29909b9f850c3d74be6668e4444ac691764f1644a626498218e4, + 0x2ee2da24b7f8e7035fb73b08c3414833ffa38e14b1faac198a860a5767d2feed, + 0x11589959fc2493292fb6c50730e74994ad7cd6d3533c3b00a57dae833cc701e5, + 0x17572029e8e897202d0e65c2172c571d4b91ca856e7ad3f118ad922127b87054, + 0x2fbf8cc6ec7efb30106423f2e67b0aa9403360e56e88b6c5cbaec34a80bdc7f4 + ], + [ + 0xec1821648fddc448a1512aecc8ac37714923981940f5542737a468d4d887c8f, + 0x418081de8c2958355a1e45e28ee51ba2c66cad04835f4fbd81e696de6398769, + 0xea7bc52503e2039d277912e022fd6d0ded5bc687c6ff97194976f3a28bd30c6, + 0x12ab318626d511c23d28baa9fb5b5802e0ab95e3cb17aedbaa25f4d084cfda57, + 0xd1e34192343d66fc1b6591cb6a3b0602b0835a403c7227dbcbd72fd8000c6f2, + 0x12e3b04924b2cf6e407bd26b3cd47bca61d6ffcf7efa1aea1c2e0d8a49de64be, + 0x6dd89fabf92546847b9c13b3a36bbc7e679c5bb0dd785403f3ff49bbe61c8e7, + 0x17b9facdbe747d7c5163ca00e3b0b825d012ed4357604e7185750d677c6b357f, + 0xaff15650b805bff6f8b3515d5e29cf914b7349af8924e796009f8a4f1b7264c, + 0xd064e72449efc11d1e90b97749de3909490b912bb1f72f542f41d62ab2d847a + ], + [ + 0x255a493aa4becd9d137eb76941c4120784c1233f6c5fdf5d65c0832af543e415, + 0x1f3e937ab29f3a88c6fe438698a7198a5209aa6ac9f141319f3bb201e7fd6716, + 0x2180b9eb156eb33cad1aa750ea0fa3ddbfa4127296e497f86e6441e052a23b45, + 0x1cc69d8f34ee877838950e20a9d4c4bd3e9acaf3d693aa64cae04faa225a2e1e, + 0xb565179887ee30e381631d8e5dd357c70ee2ebb410617d2321f6d8537f98970, + 0x1162a56ed3bbbb4b6760a16a300ba7202130086da4d5588a70926423ff8c242f, + 0x1360f719034572b59410c529b62a62aa94565654597e42779f33400f1d17d652, + 0xc603d03f92860da8a68c6dcb1924d1a45099aea50f1a362edb2f2a7ddfe90ff, + 0x1a918fc117d9a6445e363ee5833dc01411034b95384d98eee47ae896f92a7d67, + 0x2a88e0c35617665f3cc2fc77d90afc7a8d1001c71debcf2733ca0c71a19e1ea + ], + [ + 0x120f44670301b1435249294d9833d59e01682af4c8658719727678fd9ab7ef2e, + 0x113e968769b0ea32cb7b5ff70484aacc96f13dc2827a8e5e611695e0797fc3c, + 0x18cd1471430adad31e45b529494fc8a7e319bd2fc0619c99207dfacdb657bbf7, + 0x23d0fa965e920dfc530b52670b1e32e2d5fc2821fc918c0844a003b7141825ad, + 0x2ea6b32af37cd765d728ddefa30918902a21e19b291400854f56393c56d69460, + 0x3340cacb04d5a85614eacc4be3352938baa3fc714c2575aa9d85f739113c50b, + 0x15ff827e034c02a90767f0152840e7fc6db983e496ea0519c0ff41dea8180628, + 0x5d56f0c844d169248503135e4deb9ffd6329d54cfceed4b947d78a568681147, + 0x2e5618411efea30cc7de310d4872597d087c1e122e02ebb117db0c2dff04fc0c, + 0x15eeb3e0541bcf010da0c47adb12f6df540b974d439c93e19ea4d02f9975d446 + ] + ], + [ +[ +0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, +0x2376caeace68ac7d5504c33a2219f5c7c5ad25784cea62a8df008c4fcab50d07, +0x11738aa054dba194b2e82013feb222a4257eaec8a01f131fc657ee766f408d04, +0x22683ac3c69cb11bc0879ea8b2a5c88aecb222d25c68a660a2f4999cde166655, +0x713c79d90ea4f0449b01031fb6149994fc9b764fa494a3b0bbaea522d4e48d3, +0xc372107400e1f8f8e93964c84da46d78197aa045614a1dd700f1dce65779437, +0x5abac870bca413db4ef84c71b44676ff7e7c741c9b5e3f3c8efaa73e446c02c, +0x11c5eb9e0e5c1669df902352e35eff4517033d2a2a946a8e5fd1492a3a141229, +0x20caf8e87737232b8c429d7f8e9c9827cd7fca92cbc159a319567e646480c7ca, +0x185ebe5ac788074f48748c8b4f66564a581e615b3df9c78fc5ddb70b80475d3 +], +[ +0x2fe429db8068e61b82624f25766273cd9fe6368ff097eab97aaa09be4c630e27, +0x1b1d1d024385e8a3b81c435ef9079a52dcec3cf811253a83325e7432443ec02a, +0xa5f2f19c49d9ae6d6d8acab3a944b93221a074e7a84939dead82506063120ea, +0xba8903c5a36e9ed67d21b2297f06616760d8beb3ef96c69dc9c843bf52a3015, +0x2a850b071614649f6e6ea4c4382d7aa9981736848c3bdc0cebccf3bd795c65dd, +0x20090c8c6b2e41e84178c0700c9f81b1e128b15f65806648c6166ca8769ab30a, +0x1f9c5c5cd58a682a6155b2db3923cacc1944362035acb2eef2b421fe5bd91f44, +0x2a2190daf9de7f46b5c80235a0a468c68226c193ff86cc8a6ffaa7033626d093, +0x2dab478180d47e197cc91da2f1ff30bc0fb35da934ba38c8e5587e005cdc2f05, +0xc38b0564f60610324268079496ce366271d5693ed6646a6470acef4e779aac7 +], +[ +0x2e750867942439083365d21fe760c7dfec9e3593c67de12a4255c6b01648b690, +0x77d21c1db0df5aefc4a82442165dc0c6671bf7c8ae708c8f9b6d44b033f2139, +0x1b974a1b3977e8bf679394da2b702e724d2fde8aa4e60b83c631de610d1eeb30, +0x12f77c314190ff649ec4a608780c3ef7bd065902802f2bd41a93a0666fb8a90b, +0x7626c698acdc1e4ec6fd26aa192bb334d96a0f3935e5a88a8d7abfbdade4f03, +0x269aa03a5af8a48e20ba3147943c07e1d1ac7760edad58d9d03d0f45157935d1, +0x45f5c794d9706b43bd71f2a4d4f376bcbb76c7276da8fa942eb766955c53efa, +0x6ff77c4c464330deed91103d652330809d17045c75cca24e8b1b0a61d572af1, +0x29e529381ccf3f80fc5d54b7c39adfff8c2ebb5dfb86745cb974a21e9467455, +0x6b50f490125ae0bc287d018d60c4d6752ea3f61ad3e939622c1773df67a7f4a +], +[ +0x23237985a96b177ff7c01486ab0d603d29991b8324abd6b07dbb96f5c21ba17f, +0x2b9c40e97f4e7e6eaf4d342b420fcae7bfdebc3460c120b7a4b99240ea0db532, +0xddfa16097871dbb1337b5ed7ae8d2bca1e5ba44e482df13dc7ad593ef27a5bb, +0x165e20a2a8ea0382f56df39ade0accaab08fd9db8a7657b74ee54b114393aeef, +0x174b9be8f359863993e57e21e4c6fbd4b4a4d339d943ede1d85255ee48b3ffa0, +0x304b87fcdd673ea0ae58bba75c29249f964913b2170aa9f23d4d03894208ed87, +0x278ec34449ad1c5182395a44f2826314db9fafa533e518a5bf082096c2484918, +0x301cbe6e44e903ab193531261770925dacc71b88207e18f793f59f69a4347771, +0x20334328490fd8682bd47066200b77f9509a72a11f2d91d456220c629280aa44, +0x2301d3af42d47b43c8a8052646c069e046ee7d180c62a5d36e52dd6f215bf37d +], +[ +0x15ccec857b25934ffd429af92c910db31d00dc1c3fb83745a31d8131ea5baa85, +0x2655c9fd294d40b9dbb9566609c264c9e602c777c8701b1b2b542a5f08cf976d, +0x29898ad417130c472e0c1da3b017f7166e3a3eb80481efa32503e81a3772e5e7, +0x1681ed2917381cd1217a0c9a2f675353982a438cb3e9108fa5b2048e6b7e32de, +0xdc075092f8f83009ee73cd35e511ac13eedf5e3999f9bf5b41ef3e1a15a8fcd, +0x837fd755c29dc2c29036c497fcdfc23f95c7bffb90a62db5cc43a25e20054c2, +0x19d489fa1fa1ec6441b82b735dbf0b84788c542263d4c1ae5335e49297ed4bcd, +0xeb25d1b0322624190db666759db3c82bc9718a990288d865116787e8c527351, +0x19084cece4945482947cfe51a1f6f4e2e216f5b54742b9d71cc3840bdcbbaabd, +0x3a99be2c75989dccb246bf31a58f88dfc494ce2569c5d8b18a9a876317ecef0 +], +[ +0x17102ad2d98043e5509e76c331e6b22d5fb62d074760806aa675764660eb56d2, +0x795d5914d87c0dc8fbaedfd46afdd6451258f80779112edfcdf1a71d23af4df, +0x2c202548a326cadc3ee595a16a2c2d54ada779390f7bdd4c4fc9417d3e463d03, +0x181db647369841eb58ceb7a1b9ef841a7f3358cc6f224152dc7ad3c1d3b1c1e8, +0x26e7aa2ef4c91ee3f704849f4c181fb83b860da15f62f2250c792e0ee66c0ae6, +0x17189249537630e942f5ac39c1498bce39996c15400d052dcb6cb839aa45322, +0x23bb4a76f79b77f9f6b4940ef2538c7d60d69f1fe9922d66cfb92af9dcd0867a, +0x1ab80a8b5fbd7923f0cf79707d56f7677d1071e924cb497486766a4c4bd7f6d0, +0x1f8f4c40a0cfe0d05603433a0ed2d424c7fd040077b0a1642c25797c20d22d16, +0x29177f698bc5a897ef9aa6b915189f689efcfd88f3da8e60b84b9bccc2ae33b7 +], +[ +0xa4ecaabde9d1ea11c81dafa8d5d4869bee7ad0bf4eb78397b71b8f989cf9812, +0xc066f7a1e10d00fd3e97cd8c67212c28b43423b03ca4ac03efb4d8a376ae098, +0x1a6947c4e87ca0c30ed9f47004e53b7a45455b14da41f79045c2405d2e3cb859, +0x2481ff49ed6259def9fa646c167c8864061c04cfc022051f83ef8a3ef8db5819, +0xc13692adcb86437a860d6296d74b4253e790cae6f41683b99c1760d09921d37, +0x27a6be35c45e5f46b2eca0aedd98f67638b6645acecf50351c5a9f3c428b0e27, +0x4660af4e63d1c9ff6f059b75dd870df938980e43985c5607a38dc0ac8d273f2, +0x2eb8302f1381d9118d9c713d50e117f92837dca8a8610e9de759e76e8ee987f9, +0xe9f931dd923dc4398ac12b101aa7b5e2a22f09caa416ff8745821ff165b07c, +0x209945fe475f6767f668abc045e0c47ae6cb25cdb1efd5586da6c4e655d68e82 +], +[ +0xec1821648fddc448a1512aecc8ac37714923981940f5542737a468d4d887c8f, +0x1049076d8dd43ffc6f4ea10a82dcd60dcf4d60a2125a1b4d8c4ff954e7da3380, +0x192a1bc8e7dd6203116a0c40d58111850edd5b50f9d6e882d16f95fa6a76d80d, +0x1beae2daa2a697afd9b1388dbcd6c93731fbb4eaa0fa439f92bf777769055293, +0x1a31b8769a838df03348e01462b564e08849955efb968d1f41342f02fd627de0, +0x12f1bd9058590ca45a76e19b5891f5bfdc95d653394adb4f32090c60505de408, +0xaac3c820280c7658321df7aaf69274032fccd21be96174582a8c0c9de580068, +0x7c216183f03a4b7c77070c68b3790b31b5fa6d1df5ae42437b6a2283d5b8891, +0xda9d210a43aae4d13625782341ece1d0221bd6ee0dc4a639b7f13a6daa3c93f, +0xc0d8ee0a08021baca7a5799ed7b03734e4b9bd35430279d3f7b2ed473c48c6e +], +[ +0x255a493aa4becd9d137eb76941c4120784c1233f6c5fdf5d65c0832af543e415, +0x19a05dc5bdf1243b57474519b375ba67bd83e122b095e4272c14f9646e733666, +0xdd31347136b2eba27f0528eae1c25a710c3707bde9dff3d76ecbe33f188bb02, +0x248cdf26597e0746d01d8b7ab0e9f88aa452d90eeb039dbaf586563945972fae, +0x25718cec512fa137f8a5851510caee0dd2c000af55af09dee767e2084796a71b, +0x23688bbb9cf13bb7bb972d0d18d0e05c51bff96ba5314bef0af2d912dc5e8d1d, +0x1ee8c54669e6f0ab1fb6a54c809d1fad213e8ffb7a7b40387ef594b7cf50f4f5, +0x282e578ad2799ca36191b37835889bca6e2e8bdf7e4412628bed5e39885d688e, +0x831616989168d514c0fa151fc3874b8cedcf88d27185e7e037cbe93391022e7, +0xbc5380f3490175b28f01eb5cea3914924df2b1f745d33a9e39ab872b19c4fb5 +], +[ +0x120f44670301b1435249294d9833d59e01682af4c8658719727678fd9ab7ef2e, +0x2a25bac660d90d85f22fe81abdc80c403a86e75d4f1434ba2eda3184dc5f2833, +0x2d19334d3eb5a9781f3b8105b0b1131ee95d4012e7faacf71864762b6fcc7011, +0x267b655f26896341492acd89edc7ae96dbcc24161d1e73ac652ea55d61efc3e3, +0x1d9c8ad973feacddad16da2be2ed7eca235b3bda01521da956f1c8a7d65ea58c, +0x15b9ffc66af5ac2aafbf2dcb199a57bbd334c9f971d903d7da7fd65e920cc9bc, +0x25814a817412e861b4318985ff3cb706db6e56dece08c2c6dc20584ed6fa6c7a, +0x4190e2e1cf613602ba331d0185b43c960ff5c57bc2f86f5c8bcd84b95c789a4, +0xe3999f52ed0ec7f486ff150acc84c266aeee72529234a010988f95a1b5885fd, +0x1fcfdb43cbd7992f0088a9a85c95e4621873666105510f25ae576bc08d7f2084 +] +], + [ + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0x199593eecc85367004177e717d8adae09206aac28506281403748f85ebe9985f, + 0x8dd94e1b09d8b9823fde4d4fc4a3794d631616a2c192a47fe257bfbdbccb7d, + 0xa0cd01bd7b3c21552ee7c0ba8783ad231802aa4f847d00de820e9176e227744, + 0x287eaab3e59c1cdfce30b6151543b6ef49a3be7206f3cea62db4e80fe1ca1529, + 0x2a8230f7ed05f7e334f91cf214c7bf12852996083c456a506eb316c249cfb4c8, + 0xa38f089600747a6b6e35342c2e321042ebf690726aa9431031351cbaedfb5aa, + 0x1d5301168a7dac6891b7a9f6dbcd505fbf7522f875a61254149449869d316e05, + 0x13abafc765fb2e45f793640bd7f1ea2f88d202f0d7b4200410cd96128d3ef472, + 0xda7e244a420237fbd8730ebea03fff45156a52ac87b9ff605ff1ba20f7e83fe, + 0x271d315532755b1d48814699af18654bb310bb94d1258dde0e589bcc2a5e28bb, + 0x12fb6f92ff04b5d5de41c9508842798a8b9454a99f0cc49a92afead482e84bba, + 0x24cbf9280b713f95571b177799a76e23f555db290a1187aa5ab7db69a2dda2b6, + 0x18f43c99a1b72e7cbd6fd781a46c13c38202b4b0ba7ee75cd36fcb79b5ea67e, + 0x1c69528b3df94c6f7e8a794ea0308fc165f1bc1c1e3ef090c7aaf4405f7cf3bc, + 0x1cb0d8aa6512a7543bd8e8bae1c0f0d2db1b3457e1bcc0ffd372d4eee3c6fafa, + 0x2e1fce1597591bb776ef16340aeddaffdaf039487cb42bfa6752a3ea0cfe18f7, + 0xe486a7b7cdf0fdb88306d96e72161d4549b281152c6cfc98d84b031e95ca166, + 0x1141e26a80698b742d900fd1e734839d51e4d50e0176303a675809ac47201782, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0xe3f8ddade546278648095cc835e94063972b1d55c6414506592ab57e54c8042, + 0x21933a3bc4989347b0703d7cdeddeaf6588a166e6a3f984e318de63ce674e8fa, + 0x2ca6f945f5f755039c8e1bc30935de1ad33312a7cf325b065f91083cfb001a78, + 0x129a9ad876815d96566600a97d41f958d7df9ef97291de611d28d7d9b2af46fc, + 0x26b8f200c0d0371558755081221dc59767afc5a4ddbe6f7d403c5ccb4035289b, + 0xc7c739377b0ad2ff9d3b0a8fa53e39c7016f049ea860e8113b055ec96ee3d64, + 0xd17a36749f8f9d493a0a57bd87618c969cbcf83edb4b207c89aa5ccb3feb20d, + 0xbcfe1266d757503881d56c7e64cfbbc3cb6a47ef4e655565864e01b9bd3f872, + 0x13f89db06ca471b07ac0ad1f4448cb225868b63131700d1ddddda16e6d5fcc7, + 0x24d344ea0550d7720827b6be6c09b027c8e4ad104d57d57771c258177a302b8f, + 0x208ce89913e633aea3a855a854e7daec40afa1939dc1f728dde6b349e39ba30, + 0x1fc4565041d810a750e306a14d21695074e31eda2baf0821774add15c0e2fc3d, + 0x2fa22f80d4309be21ab298ba4bc16a5b20f2ce8f3ed7bc3453135655da269649, + 0x26f3a23903d1e7d835db70f3005b3d5a67043fca7eb62aa8d78942a0c1cc8add, + 0x1ce0343fae8a12e25f2391eb038b2377e7c0c21aa60100818539d6092eeeafb0, + 0x244a2bb870f1e6f4ba5e20f1c225723f305841bd0ab932b7334990cb0572c33e, + 0x1ec61e9126f4c8fd6f0d00b28c5f02334c077e99ecb358d2536b2d321cc00aad, + 0x18b2ab087e3f0a7fa8a6bc1687900a5481ea991ffddf017ff52a7f371c22db87, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0x140b91ca0e53110e898a67ba8853d04821952e760e56de985180975ad237ea52, + 0x3385f50412cc6d4caaeab9aaf1099e8c3c61295754345534a1476144a9c2678, + 0xcc396f0b80e2638615bb4a250f84e54dfe33ce76386edf22da2dbb233546ac1, + 0x2810d8ef50de86e04cd8a07f6585a06eabc4ac5efdc4410904d7a906ecd172dc, + 0x1f8b8501e9db678cc274b33246e39eb95635ac4ad2ff759a9201ac0c3f16c12b, + 0x9b10e50dc0703b65199c6cff8510a9ef2172545f366ec2aaedbb2f5ad4e391d, + 0x158a6e9ae44d1ebc7fb99b5b38e5139257c68f0ddea96593ff7a87dfe79cbbe2, + 0x68dba3eb9f1b909707e666c1e7c745192f6ec2d8439c186faf6d3bb978b42a8, + 0x100be98775675cb0864cb56fa3f82b66b216071d10cdf87358c7e46be055c723, + 0x1684c4b116063b5e05cbf4eb9b3a6ba6d68ce1f30ae3978e1bbea7a71bd20cfa, + 0x678cf4e455f8359f498a22b87a3dbfc50ce233cbbd99995cc259e419899e53d, + 0x305d111beaf3f510a104ed93aa254f20a4c539eeca95756ae03bdbdf0c8eebc1, + 0x197b0550e8e09c375f4b1976395ae6051649d6c7a8c39b78676e45d33a8630d2, + 0x190712928fc6ac88f24cd9179348b4a2832748dcf708e01c50efcd32e2b83de6, + 0xa77bfa4113e98b47e8d705a9f60160ba144ba344c274744f135f207b24929ef, + 0x2962a7083e7830d287de0a3436cc093e0fd7c2d9631b4937ac124d58fe3fb901, + 0x91a715976bd99e40777c119f68ebec701e3777cc9b9e52602588a5ff89583eb, + 0x61e3488cc92892520449518af4f4133b52412a19fb8b98d3d0812dea2636e3c, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0x197ce59bc87f624e9629b7383452b9858362754ba76cabd0e3d3161eb8ca76d6, + 0x276e2e6272ab2858142f0ddaa038f436e9f4c53eb4d5dfd8812cf10ca5bab1ac, + 0x9c49831a9e1c453d072ce83e5088666b56dfd1ad0977b2abcb2aa9ec83e2ca6, + 0x2a4aadbf31a1c58a26626ef9de341f2268bca243eb859a465911da18af0173e7, + 0x21b0460dfc8645851be88e96ed5f67cc2ea5ee00f4f3025ec4b5253494105a47, + 0x120a8288745f9dc360cb1d580b012b52543030b53b9b97ac9324df79fc46df06, + 0x9f0d911f5eb1bbef4c9ee96c2fec0b0c00945de4706b4cbf64f62a02015d7c5, + 0xdd0124d8c9d7b7c202379a001263e0522ce49d1081f63816134ad16bb34277d, + 0x2bd803e20cb341debccbad79b053df6e53f567874a52ddeb9422758e73cf6ec8, + 0x19b2b4b0e24bee790fba0867847f947f975dddfbe3c11b4c566ed4673684c0cf, + 0x1acda97c75929ac11c21cb081f177a6e550331b2670e6a66c2793e4ca4bcc3e1, + 0x251c70a93b81276ea3438709b96351fd8004dbee0abc0df79329caa4d932bd62, + 0x28918984ffdfc01138df3fba5221a8604c954b7ee40de7070fb0e34e7038ea3, + 0x2ea1cff24f208aed6f4da7cf837817ebfb6f545528d85a32430aba357eef776f, + 0x15b61ada681df7de801547bc9937b1c2e75a4f9728cfb5586f765b058735ccbf, + 0x16a4ad2b453006d9fcef31919daf7ded6dedff3c5b3ba4fed692e2350899167, + 0xe8cdd7c3d33927077543bda5b1777f6369d06876b8636cb95a9060c7936be90, + 0x26152760e5dfe9f0a2fe901bed5e0dff3049827e43a1091e24aee4d457490a63, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0x1ce56e15f41c99a2a005acc7f78b735e8330dba4db4cc96c524b4638010937ac, + 0x2b33ef11fc26750d1497df0fa1b969f1c01c5556522150ff976912649af06a99, + 0x47e2b54830ccb7ac893e39afe89b1d7eac35c7ec0f28b343e0249b924f15d37, + 0x2e820332c7266af2a59ddcb5206d404827e9563ca2c5dde5d2d34be269c82612, + 0x28fc123f79ace39838b7af8f86be8cbf89a3540015bed059fb7a55868edee623, + 0x121ae712c922e7ef55ebb73809f3036db42852c52fa63bff322237bd883dd555, + 0x3002f25a7ef8e035c0e82597953a107fc73a5a406770dd47ca93a34cdf8040a7, + 0x23ea2cf159ca1b8a17ca61b73bc84b33ca7204c4120cec087424470dd062076e, + 0x179e72146176bd15051df789ddc3d0f48437c973232846e4223daf05529248fe, + 0x25edc52b2cd7bb6690692d75c3f1b999f2ae0749c5d2741d2b53284b5655d46d, + 0x1cdbea76c865750ceb85ec17f20c955f2edd46df09f0ad90d04cf416b10fcaae, + 0x2edd29ae05591244e1124edc195033a404aa98a863678d3769ddb5797a2a748d, + 0x2d9d2a342475cc1662da5b26453efb92f1549efbac72a1226373414a49a13590, + 0x4783348904bbd884be3c608fa349287d2e4d4284baaac9b6ffed192a641406e, + 0x1588ed490b8448cfb883d790bb0f97a2f1962d14289c946b8ee49a4ddcf7a3eb, + 0xbf107dfc33fc7e66153c7e5d6beedd252d17b8ca1bf1f6499a9dafea570fb07, + 0x201d0f15aef01a1e0b401f946f7b29e6f01147b6257d7ee235c6d319c4474326, + 0x1015804003503668b1dbf9bbc98eea304dcdeea4eb7dafc67b41a6446af10385, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0xbee3e128dae75005ceb095d9e6e0e55285ff7edd96dc89654f5b83570593503, + 0x1853cf3ebd47b13b2f218990eb3ea26379c1d213e70feea5b84882d76241ceae, + 0x2c25e50d363cc08774bee7d9e6232855f6d8977ab169e38fc6fc76de9a63e6f, + 0x21ccc1e8f8b5ad39b401f79c51ed881ec892d2a7eebb8ffbd848ef158afcaf68, + 0x2193aa94ecd57e962604ab428aa0a8971644707c6e85663ef9b3720a685d71b0, + 0x1d3b5cd3133a0533eb15cd908cbbb5dce76ecf5b711f2535e852aa472ee4c9d1, + 0x11f29d358de76ef38d31d6d7247b64d41c42ebddc7ef5e4445c7897f57ad08b3, + 0xfcc2984d1d2b762d6fa16a3a407f4d3eec484a9129763864265add7c900836d, + 0x2f79d03e732317585ff9abb62a371800553f1eb717a71437e225b204c18f9e9b, + 0x2f4f14eee6382dd0c54d10739b354abf104cf134babadf2dff9b8cf286f9733, + 0xd0c5aa4bc4f774d03ef5b2f9619f618edd9afb37defcc420b0aa4f4fd145e85, + 0x9b150f8dc9342c87a8b7e871345e5998c084662c897899df45d73157c4fd0f0, + 0x28148860436280cd8a5fd6645fd1eb86abdb72dbcb02e8ef47065a4a681e9eb9, + 0x2cf619fe3735ed9bccedfbdf3de64031cd203231a0e178417bbcdeaf69c85d15, + 0x32f164c4f4e5122d438a9e0309459141505621343ab1c19abb63ce7c036ad03, + 0x2a3efdef552208ce3441637e2cd610386f41f402bec452d674bd2fe16c273581, + 0x1a9e7a13e4d57cd1ab3e38f0991fcaa4cac542f66fc2a46f9cf7d20029cac792, + 0x20871908a0ec043e1e43ee1f520584f15b3a7f24a2d03aa1de50e27ca599d872, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0x4767ef42341d3930d7e5219fabbff62f44e103b3a0905cffaea5a2dee73c19, + 0xc4a1786e515cd9bcab2b7c9723c597e730c532555003cae4e36131a721f6ff9, + 0x147f468c58deafdcf47e57114df0ead2c77452a45020e73955cb150e10153520, + 0x1d1309f96110c70d9ef884374676b9cc3a599fde74388ef68d99e54b5802c760, + 0x134281c387edde8b6f807d253bc0ace7a625fb3c1f65b88e4537febff52e1d62, + 0x2fec2d972ac4b8ba14bbc95cee2ac6cb8c669abc35e77ae2f7dc962dccdad59b, + 0x1782c9e451cbde261da8b4ad3a15e23ef7f4daf7b406732de05570c73040c663, + 0x261bf6a9f68e313088d8b2016d3e7763a6f6eecd9b506fd2baa8d8f3593b4c4b, + 0x133315cca34af406eae080edf7ce27574fb984710e4e8ec39aeb6491b97f98b7, + 0x216763174ddb0395182ebe57e4feb91be8f13746e89949557e023df397cb679b, + 0x9dbb42bf26459d3f9ba2ed5f491b4f01fff6222c6bddb7776450edb6c652ce5, + 0xea832a969ad1d94f55cb34f35c7327f62f24fa140817b238bc676edf1f77b6c, + 0xda7dc395978e8ee00ea5ba5103a39930e284533b1a51fbcd3d7daa542142dda, + 0x183cf55053b7981ac506fe1c56fee73fe3a39ae042171e21541b2b7312618722, + 0x16eabfa4236b9b61ba1b336ce55febf1cc84343f0449a54873cccfce0ff9389e, + 0x2b62c1083fbc23f58fd694646499bcb90368a2e63794b1d39dbaa36bf782e363, + 0x11ecdbc47a72138aafe44263356d01e931541ad49ac28c048428ecd233fe3c6d, + 0xeb0e1c7cae7c3f491cff7216ddce50aeb98935e405316c6daff1c21046af99f, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0x2323c898ca30f7e8fce9b31d21283d3545705a71d0ce9577c5012fde6caaa11f, + 0x2373f9b1c4df6c500768ddb13eedecf0a82bda6029c0abf90f3f15f2e7a9f87a, + 0x2b4a1e59a52b1b825f6f8dca5ef66b929032dab32a9d3a58ebb44887f84c18ca, + 0x3034ae984f1538e2163148617760f62569231a619a0e2b620d206211b232ef29, + 0xf1fb16f83c8ddd6959d01a9576a8d70c226a1a422ffae89ee0baeeb37e9a8be, + 0x58d583dcf975f97dbf31e32ebfb0841298f765476b2e4833260ad9bb82f2f2d, + 0x2b1060a96e8a6de59e2deac81b17d40ecaaa4087276b7d5a9ac2b47598c2facb, + 0x70579f1869154a6efcb59f85b43b90affe755efd5d4e62686aff46646e0808f, + 0x21444d26f9de3b9fd22efea95d62f5193c3eb0b2e1a6b393e85996439aa43992, + 0x138671f92f9ed9a8131ff4c7da6806dbc33f6c02cfd3d946aa92288df2ff9d9a, + 0x1e629d7b8f61fa02a5fb2fb163a5a57a593b158df70413fe868b338307a449d6, + 0x10f0f884186e996c19ce4939bf317b3d12cd24bb87bba0d3bb763ab716ed41b, + 0xe2f06ba65a2c7c8500850ba6a489879252d0db2af69dd23fa3ed106c92739c1, + 0x19823b0af9feb33ea07566495f0de05e7ebfa52aa89f5a5d7c66f96ad60c828e, + 0x16b0527fc6aac4b4485dded0afd8905e6b53e056efd33df7b8fc2d3d4b54cd, + 0x8a584f510af49572ee86cf723346066002e5e7621e502e946f8f35003b793fc, + 0x8a63466c0bbbdfe79375f181ed0266c97e6057653d0b285696a5ef3e93c27c7, + 0x28ae69c874a3ab1ee6360bb1ff560fbab69591e837a4bc4d80ffb4d253e232c5, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0x26751aa290792a4fb3921d9ff8b5967efdf68b1fd85981b4d96401bc621b381, + 0x1cb215d90f4015cc5934293e248b2d6aca4e0afd46cca219a89eb4f676199481, + 0xb8f12cbe7152d6f3e5fbbe978884a5b7be6f35fda4c00f5c5975158df2f338e, + 0x17d6d8fe5ede1ba531918c33df5c6c9efefbc20304b2fbee19c01aef81299774, + 0xb53ad598a4e14448fd044b8ce15b6336af6b91cfb81c0da827e7dd68e98e59d, + 0x15e20ee8fc573330fa52fd42ec7b636e28cede5437be371b1990898751adeb74, + 0x154fa8d9c7f09c1ffc7fdfcb58fe7b91e6d81b03adfb8f9e2fe0522f6f7c2541, + 0xc17e59b4750d7443f8030f26ebd82d25623e2b8e5540cba1f310828e5e66988, + 0x7dfbe56e6ae749917b93471525255853fba26222d45e0504d8f74784b1a86f3, + 0xae4cd50975a86aff25632e8c9b7c0e915bc38159c90dfd9459e29ea9432e467, + 0x1fd9cc61b67d700ec892a8c09af677c9e28097463010126823cb72d07583754c, + 0x1bb36856ba8992334e795626486a4608c5d9a076cd93c8aa0e1a934ae4e8f3b4, + 0x2f9cce5050f66f493cc95213db4336536a3a0e2a17311cecc27cfd9d88e339d8, + 0x14839ed69feeab49ef110556d96b4f1793f8c95f3a38de800e9ca0df690f958f, + 0x7b5c5afb6a826ccf1b740cfc8aa6f0279ab50c3de8a98f6692bff8cedbe5f0e, + 0x142f7788b72c5fd5a9065ebef59f6e8d32eed74588cfc22ad0962aeb24a7bd0e, + 0x1d07d62eeb6dabe9df4fa00ad642bfa7d36687d6ca9c8f023a40b5d04bc78ae8, + 0x13e55cabc0bfbb9ed41bf205be0674e8668a8908c411ae821d2539d8cc587fca, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0x262b44719763ef2a486e59231d9624bcf1ecb95f576bde1e7088dd5a7e4a5f89, + 0x2dfde9e5ea549d50c4497d25b4a4cecd096226253b3c7c3874057fa62b8743e2, + 0x21a567f428d745b4cfdda7100163871a5383e5d8ebbda66f7a305a4c6be0abdd, + 0x1dda63eedb6364b5da1fd1acc28b6a57b9a4033ee7749a8c2ac152a1e94d4b4f, + 0x685e2a27b7ec3fdbcbe3e017953374976ff85371aea9109c2d76f0ae1ceecd7, + 0xbadd4c6541613422a3c2b71626af0df7f380d6f3f6da676b7e6dda463f63ffc, + 0xe270311e05a64fe34fab3018b68616f08a2bf4c06a47ca457defa4c199fb96c, + 0x20782abf7216f6c5e781a8f0350099551c5e9a1a3d4b3ed2d985e5a7f566b24d, + 0x2b1a699f26b1fc4beb031df4f37b8d5cbabf780572fdc64a56de00748a65c07, + 0x791e4fd31ebc85df2e06aae29edd808f129493f8583732492fbd7056e93dee5, + 0x2cda35be891732bed62392cddd00557b6f4b195e000c1bd4fcfb605f8e369d64, + 0x6b17710849d27210afb3ecca7e7c7ad3bfa36075ddf1b46d7bf0a557c7afba4, + 0x2a1ad86529da724870dbf3bd6fc20cccc1998102cf0d7007a6b2263999e4fcd2, + 0x2ca7a691f176d709c8799b5094d28a68db601ffb5d133cdfcbfae9e565f1ed84, + 0x92ee47cd58d3038bf80c70d798516c0dc371ee7fc7715da95ccdd5a1e820347, + 0x2f0a3f3ab9033e8640e9c1b7112b31242b7eb493837b84bbdc9cf56ce5858752, + 0x2bafa447b4f5b878e812ea7b2467c72890c119992bd1f6e3ca60f926e812d2c6, + 0x6f980dec5d6b3665f1cf9fea725ecdad874c5c9cb63e7987fb41e7430a3e352, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0x2d69490ba2ee43e841922e9a426a5bbc264f17ed379f8bc91ae3d275e724c21a, + 0x55c6b789c7c9586e4c88fbf4eb60783cdf8e9e58d356bba1ef92f8ec3514aac, + 0x160f356a6a05a6919dc7d2e03878c6eb552a14995edcab05f623273c0cd29a1c, + 0x2a178e1d8e4e4609710499245dc91e66f3795b5c0227a2ba8cc8a9f8830aa212, + 0x2dff2498b5124e3bc2587f3b1cfef4dbc1168c2172dc43f1d801cb75c7e18ff7, + 0x3062dff835ea1ef8f6960d05f57368fb48357ece82fd7ef12cb5254a55e3d102, + 0x7f83dab6ad44900a3be2e049bac44fc5eafddc0e261ed5d1795fd513f12722, + 0x1a037c2eb85f1dd82bc9988c67646efed697444ea2739b6800d214e8fc52c8d5, + 0x17cc92ab3464a089e4f7747fcbee5043b59bf9d7cb744346cc2d889051463061, + 0x36ec634c1127401f9a2206720e26e7198702b85deb2314a37c1f06217cfad7, + 0x13e7e74a49ed94c2a714a46b12c19e3ed6793364b22763ae2c28b53318669510, + 0x304fecd133011329f98954047995691c6991eaeba7141494506fc3876cf8268b, + 0x4e860ca205e4d78f0d93d3b743e2d82d77737faaf2704e5540e163aefe75b51, + 0x128cd6494ecba913473703b110fbd66d627440384a6187aca8088de1d51aaa60, + 0x2c7111b9259f4fca63e218ad354e9107e80a436a3e82d62f180c0ff1c7055743, + 0xb3901ec96ea864778a698866a852170eac53ec5c05c024373cb38585977fcca, + 0x9aa27e7fd140dff6a20f7696c85702c3f60ae58e60233012be3996d839f8d6e, + 0x1e3d51555af4c3321630aa1d1134ff631ce25a12b77d3c2f3068a4a981f79491, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0x19b9a37490c9b0507423635e95f10a0f27a2dd48b840393432eb41c3fb9aa265, + 0x7783facafa95b276e52a4e6957b6145806c64f5c0305fac11c14095e6770e7b, + 0x1dd174936ad30ba73ea372209ca23d51868b21e533cbd15ffd438c51c9515c89, + 0x1fa6bdba3839fafe0ef67bb8f50f2bfcca95ff34ccdd072bcf4451e1b3a8f098, + 0x2a3116f7f050869bd4b0181245fb41613f482cf81d09b95898f9f813caf7c97f, + 0x2c16907e9d82fe0a3799dd07efc106bf60d114def959261470623220d9d9224c, + 0x3c373a0664f0389702f966c124355796a3819e6fcbf29583b4a33891961bff7, + 0x2e67195c545bf86e5737e4d28dbf075c11cd21965127da4aeac13b49fbadc2de, + 0xe0d816cd83dfd0535a9706aa8d7225342cd76b82d2c3df0425857d92aec38f6, + 0x1d623c057cceaf69f4438d54e954e59f7f04065ab72132da788b28fe08ae403, + 0xd7f30107ef57c75975e5a489dd2e39053d12cf5ff9f74bad3e647d6b4278659, + 0x32f7466d62e6c9dd8c02064ac112042b9082c7ea2e8caa266d04a68f9d9b15b, + 0x2a4bc62d27e720a9e53c02e6519ecdc684ed42222c063c698a9fa024c1bd0669, + 0x2f11dad1623f57beb48f1f781bdd9cf57752dab6fa75b6442db3834cebf6d5ae, + 0x7448b576267dd9d742ff7a7fc8324ddf3f340df575917d1583256b8a26c001e, + 0x10c06e0e81bba5139387282c3883c5967d1ebad7ed164f970dd697de036db5c4, + 0x30c7e1595a11101143f8997b7b9f63d265bb69efb4afffe36eb47ac4e170960, + 0x2081add9a69f880110449f883df1816b141c11bc52fee4c355821501e3fcf05d, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0x288949d7c29bca2b52de67a970192cd195390c7ed0788f81d85db64c98c78aab, + 0x2589eefe89ee66a650a27700d7ad9ee3ced14f507536405c21a90857b6a3c8e8, + 0x28ff008aa0b3a7732cd4059620a76a9d1cf8286a5ef84ee4df54b435656f14da, + 0x2155df46713041cde67a10d82c7c13921f0e394bc66eb78f9047782cd17ea643, + 0x2c16fb8505a4a94a7b5c775792cabfa62e014b33a5479a81c2fc8a52e8044d36, + 0x2b1e314362badfaf84b4d272a4b6509698305104e27fd317fbbd0178137cc708, + 0x2c27c6d894ba49e73659ae668667796a1547338cdcf3c35914b3d3e004f935c1, + 0x24c4d70a62d779e831a38a510142c88b2071251f2737dbda104dc3cd5585041d, + 0x172cd6c4cfcaa0085db59ffa6051971fefa9934458a50b5e3b98bef6053f7fa9, + 0x1068776f66d6f04edcdfc6e6cb9473ee2f57d670941e4a191f6f69e7bca61a, + 0xb5fbd532099ded25d17a8ba4db930a0c9655056fa6a01c56e825843d763790a, + 0x20d62b8df28b9d5677bd4f3ac8095772befee8b2b761f9a4a7d9b9aa719209ac, + 0xab9f332e0d0c4ddb998fcd6da668a8f744260e3ea8947b6f6189ca82c5db01, + 0x2953639aa84c6c0feedbc71e3af4e4a15bc408f5cf3ba2bcb98ba5bc01c9875a, + 0x1afc3b62187190e90184c6f1f1878020f0efcfa38235f5980ec372c2d9b4a56d, + 0x2c67d12ebccd059b365736302f01da9088f2a40ae49d88e58c7ecab80621db4, + 0x23a3292e40578b5fe32b0c7ca158b298fc7d6397ca3d46a50157a528a6ada69a, + 0x2d5a92ce3878d73e89d645f35ea2b179fadea64310ff752a48a94aab957cda66, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0xfb3cf3d82f7442edce7ae58c2fcbde983a9991bfa8c583cc9e8675176f5f500, + 0x1441b92ceeaf3e93bb74d84875b7b32f66218d23cc25b747d522344c853e69ce, + 0xc66500308b0fbfef99d8dda3ee219ee7faeeb6ac7c993572c13a93b172c09a4, + 0x104281140d7c64b5bd415c250830aec689e5868c58a2396c8f4af87c06c0a617, + 0x297d4462db9786475248b39bcdc40ba0ec662e5e772f6d07c3178964c86bb6b0, + 0x882cd69f5f1b0c14f1a5f1473f44952e042d81134a25c45a01e4d997761b6be, + 0xa663c1280a5f4d285524e6163aef8f83a42ac4a8fd6d3c44bf01c5f76393e75, + 0x64ff7dc46adfef44b40646c79afa99d0c14ca6bdbf7da5aa322f346f169bf41, + 0x901c9594190b84ee79b7282a6a5bf82cda6d28d1c513fcc679b42c5da8570fe, + 0x21257b75cdd1fac9c5a38abc15274df2aa318adfad33a5263ea3cdb1a1990577, + 0x255cf0a823fa7cbf9cde67161df7378969730138f3bab39b5be3575dd62e8b51, + 0x1d4b1fbaba2e064f59db8d8a6e72ab84d49a8d82f6a2f9fd532caac3530bbdb7, + 0x3e5ecf7a394eb453de6cfd3fe8da36f826abe096b15add7bc22ada6d2ec83ad, + 0x1f068ef1dd48f8934037a95c94b3740ab3d399a0e36cdf8c91adb39ed90c5151, + 0x13b5b483529badcd3ea50b491b6a042ffe9c38f2761e8367eac4e11a85210971, + 0x28955844381caa81ec9032541abdf3f00b77b9a80b9f6e363cf4369e0b1b6642, + 0x2a3fe34d0e5e72044a5af113255b129d78fdd2fccc280f3d6b81c985d16cd288, + 0x8757825685a90d9476b5bcf376eec9556c41811a9c017fcd7d6ac44fbbb8a0f, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0x5454d37baa3a2f999a53fb59504aabfee05108628378a3a9feb587663d274a4, + 0x129a7b8af836412572e06774394c69bdae4033b15dcc2a4efc10d5b4d850fb05, + 0xcbbe121aa60c9979b941f94e86121f984e67334708eb05850777184734a08bc, + 0x1925ac7783c308bb5aa53769d434c44de6faeda6015848693c50fdfc7f465d86, + 0x1e24206b35f67393f1d61933aede02c01ecbd9cd12929e48300e37e1def7b1f5, + 0x4276737b519ede14db1b652fc56169408d4cc1abf043d8a9ce90a16447a06fd, + 0x27b946d91e4453a4854c29cd248e0cda329d67a2ea66450d51b57f8b159df5fd, + 0x2cdec054ad08c8c5e31588959e605ab5b0518517fd809d437edc27f33da7580b, + 0x26e434190d53125fc7718bfae9f34f2124d41bb51bb2c23c37deea8407da3523, + 0x519d0e4b6c1228368f420926c69ff37ee7dcf8e3dc45c4e95c821477d075eda, + 0x2aae1f5ea6015e4acf22f950f6620cf74e7d7bb7a33ec09b372cfe562e5f2e12, + 0x2ffb9c618799bbf03e071bca26d130a936a380f74f6e475f567adfd9adc269ab, + 0x22a6091317f474f780d2c4e11d78e6eb875686f797f82a8ba7b3212879dd63ea, + 0x79b093f80d89162556a653dbe714975928ba10cfd5f1d0bd47c0fea68f03493, + 0x2741b4234834eca3dfd3ad4a3064246c4496defd8197e450b8416e4852028c44, + 0x15adc0ef2ac09ba1689bc3bf21e4fa50141c0089d00a80225f39a8ee63ef0032, + 0x168017fe19343b5d7d8476c0936a0870ac87beb8ef2ef9b02cb773dad72d2401, + 0x2dc5d64afabdf089bffe3152fa2b290726cbbb4d52e3e08ab52b1876070a8b03, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0x2631312e2a6d973442d5dd7efea28e5073c5cc17c878cc594e2c39dea7a51950, + 0x1ae2f96df9a1a71be2965eb1f504ffe75742ff7f81a45df9086822ea4ff83f9a, + 0x17a4bb48a247c563499f4b71a2ed4763c579ba38009184f3607d9b4b5b2594c5, + 0xc9a0ebe3610863f0da6992f19a565911e14e72687f798d90b98f2c2b24bda63, + 0x2f2731211090929d349ecff21490ef33747d4a402c8c1995b827292ad299201a, + 0x9b7a78ed8d062af7d0ef55e464376fa6a4ef0de0e0cfddb6095156359825480, + 0x28abb1d3e1bfd68df633d19408b66ec34a580540eb92794fbaa033f8eb0e01b3, + 0x1e2014bbd5d2db2f97744448f2d57d1e27b6dfde486085a5d8c128058fa0e656, + 0x25f9ef11d4ff48535b9301a31a5413236fbb50568745d44af96d5d307490eb62, + 0x241b430c52d322bb0971e127e4e68fd3fad0a845f235b3e80bb514a00b75ebd2, + 0x21b6603896d2fd23cfa9b8db8fd0e550decf29eec015b5cfd665313d91014bdf, + 0x2066a222ed385ff7d9620fdd0343bc67d3fe9027c450917deb4c126ab9c5843b, + 0x148ab2277866b9d0c72eab8df30a3abb6fab1610e164a9f2400ea397e0de92a7, + 0x22b514cdab8e05d5b1289978bff23e2aa763565fe504c7e3bbc86069e0352239, + 0x15adb32fd53195fce581f92dad1925b14c6273d02a73ce8a21e988944645e829, + 0x26514ed0266951c35ca0ef8ce1de46874ec132fffec62807e01831664eb427cd, + 0x24a1401fffe3c86451355add7ffe24db5672d8656cf51377c38351f1fef09a6f, + 0x53da14e5e7a25894a0b0efdb05617d4f0922398022d656b13d24ac31c66838, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0x23d4d5f42b19c73015c0c481446416d929469dfa05ec46df0163b835b30d08d0, + 0xc34142c7d90f966770924de9bd02290f2a25d7e627ec80bb3d7ba339d0e8829, + 0x15693ac825018e52a0d4c3aef740c97437e4dc3331d552a1c8e4b8a3c9e176f4, + 0xc1d7701d2b195781d2ec69c9c91b532a326163ec4fa2f0dc4afcc58540acd57, + 0x29f55706b8105e02770e12158f34ebf47fa7ef35f2ca62de699524be584a17ea, + 0x15948078ad1c9f08c03facc3daebcba846a02cd92994d709ae047be01ae1c676, + 0x1fff985fd1db0e045d0ac983e602592bdaadc7ee35c696f55da0bcad75e20a1a, + 0x16b370312e2012c15fa0c6b9619f0ce24ff0586c10b4bd02589d2b7b2dae4eff, + 0x2358120a60a01628aebf65fc72181ff9a0ecbee9ae148ebb4ab4bdc9b216e76, + 0x2f1a1712d5a7eeef8647c7a32c2c9491c10ec872fb7a8280bd5f360a3411cfc7, + 0x23b8d022a8e866d4095cac47c7ba7111429f6c08950a19de476ba2fd836b6cf1, + 0x139ad96c1432a53b6fee35ecd66f2b9da8ce4bea3ebdfbd2c4a75961efe0d892, + 0xd1a3762903cf32fffb016810eb11daccbff2d7dbd6b2a447ad32f810d88893, + 0x1e2fcaecfaaa32924f964b021dd552cac420f822a0a71e37c28654221d472b7f, + 0x12102994668f97d887812f0151144111aeb19e748eb198c3a75a9965176f8f07, + 0x2cb68b7e634347542711e393d188b6fc2eb0f6aab7a7cc9177543b3ec6d7d, + 0x215a89522290e4cbc142deb1584f336ad401aa76d058da586baedadb4c0b7b9d, + 0x508c70de806cb78a62250db957fe5ed69e4c335b86635be74a068f200768a, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0x3f5d10d3e2dfdcaaaf5d2251baa6e7deef7fe6016e0e33f67413b576e78439e, + 0x5160b38288f77fe866c353e3fc4bdfaf39b54fb22c0361c6bdaa645131dcd32, + 0x1a1f53585e77207de93ff07741144e90b6f8858f6c68d52b62c96efe319aae23, + 0x2c48ab25015e0bdd2cebd18df7edf7766a28d757827818c284f15302df3d0285, + 0x3001d8c6b2c0a9c4e7f80cb2688f909dbb1bce96b7abb884f405158aca90ad9c, + 0x14ba759b81b8115d220b3bb5e077e597f805e30d961d02b132ed6d6dde416d8d, + 0x2e3b3d96803a71c846f5654d3bc43f69edd66885224a46f6c5b67967cd9b0476, + 0x1515804d3972a797545bfd5143cd3d3c2b85b18b734fbfa60e28a7d8024cb8ca, + 0x2122b140a17e84a1ce854a0f924abbb7941eeb8af8831dedee228e4ed462e38, + 0x1efeffb998ae5510b386fe1687a04b18411e23f5300e26b0dae71a1da6a16ef5, + 0xaebe0890cab1a8d389ad98ac4e56b74e1176dde08cd90b0b69037167d221c07, + 0x1392810e135502a38d126a0dbc2cf8d1977357dbefa4d84484d36a4a6e4c7799, + 0xafe48f0248af7d2f35057667e79a08c2c2bffd8225b6219d94e785c41a796e9, + 0x198eb323d5b100e891e9327f661d15848df9f2e3bc2e34692b0c644ff091b62c, + 0x29c62456a430517fcaecf1a752a55dbf245a88ccd664e1c824da61000919c45e, + 0x2817a686e5a15a89212dfdcf69fd15fa73b8bf0a5c5cd893372a7deb18d1a7f7, + 0x12d401440bb03153830e9adb349d891ae4fd80cbbe414250d9f3c2d71448d93e, + 0xfa1b160c62129071551cfdc0d384b81866bda034159475cd5107b92044b8157, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0x3046d1d934cca5a2f7039907e78cd8dcdbb50c5e8cab13a78dafcef27ba5597, + 0x2d724a2ce967f1115a32a74ee7cf63760165fc405621008476db3bb65b346b47, + 0x6684ffbc3e9a720f7ac9be9c867f2532240fc9ed20c21430e2685abbae63ca0, + 0x1e4caa2fe0f585e91bf011c1755396d39dcbc30e94aa4ae3ceefd381fefc0d43, + 0x24a9509908f6b0a4aedc444647d1de173078d900d23e2770b410624472bcfe70, + 0xa444eb331e3a9d4f98039f6d9a7a45482ad85d6e9d0917486bae82a5047f729, + 0xcaac550d739a7699d5dabeabd3bdb5e37449e87f07b95ccb82fa742471b8ef4, + 0x4e0c67a911f80f93720ce27d4ce2815f7c4f2e5d234c259fecbf562f863121e, + 0x1ff8f4767dae471c0c2a4c2ef44275aaf07e1e155989a5ccf1e10537f860f72d, + 0x2f6863db06c9adeedb84708e3b7c091cf44b4251023fe8f6bef72d61519e7651, + 0x2e788ebb5af871b9ed5e9fab07da7b58126109807e5915e6f54d7cf7dc79199f, + 0x2cdafe599e42909bc0475abddf4f10a4f14df5a2c0f429bef913ced315d116f6, + 0x1b0a72225d8796640b16fec15a58e11d4be5a9a473d1337fbb495ad93b432f6c, + 0x1cb387a29a3345bbf6cc407a81958e61fe98f7708f40bb8b96741f730c7e7081, + 0x15ef88ba22652780eb14b3ab276c1dea798361f7631344cac3e771a16910179f, + 0x26893d124895c43a1a271e72a5f99c4fa9fce6ffa7bf6c31e4926a4efb888e67, + 0x9dc58192b21af8f6033bd84e9f5d696c602e0bb4c924f790b27df7db675049a, + 0x1d659f67ea472288e942baa853889e47435056a2da4398acb9ca288c2404c7f8, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0x17812ce47ed47b09cf9fed086e7764010e70afef63a806d9890a0c3113fdd15d, + 0x5bc448e17449644d41ef38b762a183d1f9c0bd6f6008b4c902ca3fda45d9e4b, + 0xb8f14bac67ece8b1f9a960f436bfc6a75ae541945689bf78b89e2d768d1b1c, + 0x6e843ac5711fe5e7551ae25506875ba9eefc93563d15e03f15bb5d6e307b294, + 0x37c5948a6f6dcdd4378f4e6220a96e4fc27c8fdb102c6f2fe0988b199ad2860, + 0x9bb55e5908b10cca78ddac3e7a880cf469fc418c8b0ec0e2f96220fcddd983f, + 0x549938eec4ef16ad9d89081f27be2a2c4af49ae918988ae5574965b506f0126, + 0x13b4215b89af0652d5598eb29b34ca980cb1a1eb44eaff0e83ed8b6ef5c5cb73, + 0x2d8f43577fb26728a6f2305e2f868a4298ac5f4bebf8419f072cf709b9bf6979, + 0x58782a9e8860cb1b60314d2b18e437f36c169b5362e07575aca80c3bbcf8242, + 0xf6ed9ca8c19eab0c5100e7dff2a1e4d09b3c2ec9e19a9aabddfa4de4903cbde, + 0x11c3ba734cc607cfaabc73f220cc21f2422ab5e31d04818137793092015a1150, + 0x1ecbe5795e0f92f55c9784d7687271c7f1d99474a4c9f66fa41618d17342666a, + 0x2ed6fa55a83b01452c9e30b9888dea9544c10db14356cace8dcddcdb0a2fd223, + 0x79287ad9db6ce54e8902962f53403735a76fb7eaf2fb92e8fc7e6cec890885b, + 0x2e26aa5ce56c08151e6c8457e0ca280a1cd8117e7b4fe6895058b964859d73a4, + 0xa889a87584a87178ad4b8ee2230ebc06301c08cf8407e631e71d6467079ac3a, + 0x9c2891001f2a119d1126659c30f6123f65be071bf93729d2a76d9bdd41798ce, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0x51fce24183d75c4dd506c99b7be05f0d326a972645730c2a76babdd8c7992f8, + 0x1094ccf4dbff390c02df760b78ae8360348f9ceb187059aff7dcc1a3b5d9e8cb, + 0x2d4966667b830669b5fcd632c6f3cee90687341f51653aec9f0214ab5db4a847, + 0x1b6e79f0b003e313be5fc611155d4322d1c56f22957bd201a45b53854291012c, + 0xc9d7ef70784cc153f1a325031dbb8dbac58625dc7610fd453c17cf8dee3b489, + 0x2eaba31d2ad4b02948ea76ed4d931d5a42683adb9edeb564d065363190e766ea, + 0x3af6bf9c7eaedeabe073487509937cd73b00a8fa5aeeccd8d4a9b9ccca1666, + 0x24d4c2116faf69b99c84e389413f710cef10de5cd87c041669ca51c21f3b6318, + 0x1f5cabd4bd22948e2c5cd975f92fd0850731301e6291fce364d7f5d951157b0b, + 0x32aaadbc1decf6ecf33b074eb63f5fd75bcf94af261ed3b75e049d63dbc66ee, + 0x194830799464f8ee702d72e41ac3aca3c4ab419b02428605b00829948a201752, + 0x1a88bf75b55c097681b6c07feaecaea5a7e7a84c2d9b549381c51c9b0cb64532, + 0x2c7969063d1fc97a8d063049637ca6ba63a6cdd9200b95c1ff1c941c390b89e1, + 0x79a0abd9ba495c5859ff6e10ce393b50c9f04bd92a9261ec1ef7f99f77e46cd, + 0xaf8f7e9f3eac9e6e82bc956dd7c53bdf91272cc7ae955d734c8f9c6a4e7385f, + 0x1f45d6872234334442f08c99bce292c089d3f34f4763419d02ca14f24c4b1b8, + 0x3a4a9d99286b1752d6cb735b9cd0fa27d4f1b8f0a1521d18d1517f6148b677a, + 0x19484e61180700e93699ea2a7d64814841cf11535480dbde83f6936f5ab68fb1, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0x68117f11b7f8d736af79ab2ae3328e576a95d12b637b944cdff9b5758499915, + 0x118a504d77cc49d22cf454a7cb3d9ae8049efe9447a78201468e90ce576da872, + 0x1e21ecd473c3deacf25a495ebb4301092012529381b52e0d1286fac898e3c370, + 0x2e38b65fab0ea1b8152773205f8d39e6b81976426d0d64cf48cbaee81818ee56, + 0x19414eb55e2b2717e2affe4f6a520a87977e938319b9b49d02db373469bf6ccb, + 0x1f04b3026adc9f2f0995631d4ee83ad3910fababe4e78dc8b211e9c72084ce4, + 0xc1cee5ac82b0ba4ac8578c934c415a0f2a50bc7521d2058853b0a59415f6f72, + 0x1a0b86be3ba0c37e5fcba4f8f33d0af3333cc3bfb74aa262d3d484cbd60fbfb9, + 0x277f4d465b4a3f950592907b651c5ada6dbad43f7ad0dfdbaa4b5c0edbec7e4, + 0x2cbc8485f96542fe22965a7bb768cfcf79f4cea845cd70eaac0f6c383f542fd5, + 0x13b306fd43acac725673d286fbabe249cba9a5194a6b2062953b75149f02cd19, + 0x19bb715b15ee11c3f973eea2656300c00d6d96576c3724b070f38a764cd58add, + 0x2579c1bbae48a8bf9c43de695574e7d4576c2c73358b18dd15a1673528fa4d21, + 0x29bb732726698d3e98745354beed55ada619a0d0e5b8d05cc29f0ce1bedf01bf, + 0x101b8a972da8e777f74c68fc481c37f0b999ef0df3c90b6505ab2a6527c95d77, + 0x28d282b4a80e8079287ad62249731647b36221be836c246e9176c6e243623602, + 0x30f5a91d4bd3a7a00ccfb936619a49c9cae07fdd02d5f7281ead5ec765a5c68, + 0x23aeb8d675cc85209a4f47d7ce9374c6dd1bdc34caedd947a05836f8f3880cb, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0x13efe2b7fcf22b13dde356329022c10caf94d0a67e448020cdf70a2a1bac2de4, + 0x20116d8a08ef558a247c6f5f943a982d94b63e8a1580c81a049ae62db7550d8f, + 0x2d082ae4142d9cf00383067665261118fc20b41dd5e3844d95d283ee935fd9ce, + 0x103520a0cf36cd976f2243249d25d74bd11b4afad705051b28f5677e7726d5f7, + 0x1e820f7db38b24a06bbc3dfc78c47d040c9dff7d8ba0160b522c6313c107852e, + 0x275832ae1f1cd86102dd968a76e57d3df95b5c1cbb1ef28dd38fa2bef749dec, + 0xece66ec104a392cd7d1e5a11f16cac7899588ee5f523b93f779b80f56ee42a2, + 0x174586e5d012f172439b4d437e58dfd9c58e7d29ed659a7471f0b80151dece5c, + 0xcc17b4f871cb91bd63924098c54be2744a3131d8a9ad21b1a55069f005ba35d, + 0x24e6611ad441830b7fc88414d4902bfa9043e60933a6d1ba6e12d6795c3c1b37, + 0x9392f480df40275b9d639dd95f8a1e0a62fb3b162b41efdb5625c90155fd3a5, + 0x19fd18a6a69d2e9327fb48fccd6e0549395b2c9362af152d9d7e9901c68154ed, + 0x174bd47eb0d06dcc5f5121b04bc3c61e02a262ef3c77f11c548b8f2580e664ff, + 0x1be5877032c20df6d798e8bf265fe511739db9d9b1042b2a9843a261cb5a53c2, + 0x263fdff0aed026e3b8654e2711dce2aabdc81bf44695f0a6694ec29174392aa2, + 0x1f71c71eb6f683d7b8516f7de5b5f0ebbf0a581077fde56843c0dfaff80acad0, + 0x115b998963794a6c504dd65e1b7d99ff4ccfe24b04462b5788cce32861eeed61, + 0x17f43dba64c1eb81be96ed641cf7801b3a45c614ccb85daa14a8153d4e57e6da, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0x1e1c19e05021208ac3fdfe2d3f116c8e72ddd60fb5530005656683f528bae627, + 0x2596fa2a97ea6905c598c64a25768fa5bde504ea3004705ada129f936ed946ea, + 0x429be063b1c6a85e848627ce4bdb658eb148f89887b08e4699f37e1c4d63888, + 0x2571cd3671bb7bd7b52cc19e2291572e4dd8f8d077e295a22907d15cec049643, + 0x23e2edfaf71fb3796d9f00bd618d48df5454e6edb91a509d173c431668c494c, + 0x1a9b4db70aa7cd04e33a10c5f4188b7b7546ddb4b4215611965194caec7d961c, + 0x115d0f27b177d1bac2960bb00feb3be427e4e0184f8f6324d0a06fb47ae2366, + 0x24158958a69587f1c15512552045620f1fe1569c9f3e3668ed06dffbf0a73686, + 0x1c6761dde78638d734eb9eb1a1b33a98cef7efa4255fc3662bae703182c01fb8, + 0x2750d8eade4dae97328c60a645fd3c8431d96ae7482a818b0ae3b4cc46b9bdc8, + 0x1fd32b82dcbeb8c048e9269c2e53002f6b7fad13aa737f386a6cdfc1e2c5a9e6, + 0x594fc59fe25d24b2545c6650795cee8ba30d2ae04dd07b5d676b089ddbefa9c, + 0xc84ab77e8af0ba2da61c55b53cf3534e766735740836aac2427587fbea5c8bd, + 0x53cb97662f38bb4b44b958d4ec02f8c25fcc795969bfb079e664b87cef93dff, + 0x1603ca0816ddaba4cef9853184cd3a94d6c881b73d2d6d893db88a48c3de3447, + 0x18ea8dd9a27ca4410a40bc8becd0b6d42338881ac4c31a3ba7caa40cd1b56131, + 0x1a527748bdf0057723c86acbe4909490d3e2415647a82f1461a42f3296bf4c07, + 0x14175f91c0ddb823543a0167ffab7bd8c50273090aead801da30b25f4550584a, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0x25f932ba4af84ae43ba5291e604cf8ca5fd208fd16b78c38eabc57286298d557, + 0x25475d7d649f8bff2630d97844bdc0fe8df6efb89baec75e5ab9bdba2777d431, + 0x89f1655b69d28450d05c9dfc610305d46a77dcd50eaf28042ebc878caf30d5c, + 0x123980c7cf8538b96942135959a4af1708aba866cba105e1f5a382e9bb6aade4, + 0x78cc219ae73e2ecb4025d0e0d90cf09f82f948a63243ddc062872b1070b6b30, + 0xcda20a3684d79a2e18078fea3261650a2cca213f705b56eeba2949ca203b816, + 0x21b9c66d1190ff2ddb30db322ca2508d231f7aaf8f7f5f5b95bc1711a672ea6b, + 0x22016741afc2d1ee9549ce4b74318bef293bb2b2d6495d424cdf700060dc813, + 0xd722902b755cd16c7977247cb28068a616adeaa13c00b1e2ff628c892bdc6d4, + 0x217793a53d0ac28751e3fda8caff3f8003b084c474e2458cda30330e338e22c3, + 0x2d31e0c6e311f327b0e780f291a81e25aebd9660648b0ff51fe8851d29671cfd, + 0x216d14211de9aed77200602ed78caa665a310ee03fafb5b993ddbb5ae2230f83, + 0x2681c24a56759b77d5e0a7afd37d286ae3422745564fdc15d25e0dd158c9f4e4, + 0x1e3b6edad3fcbd9d991c34f5e4d838fb76c255542d27f82d58989912b5bc7dd2, + 0x2eefb7b5eb265aa610c4356f2282dd92a03744a1b8484dedb115321df7518c2f, + 0x5a848b35a8e270224242f52686cf785d9f11ec3bad27529c02f6448a432ec41, + 0x9ff782048c9d9aa8690ed707e82164ad320e1daf646a3b30421f03dcf772423, + 0x2b294de4467526f4914af8f9895903124f2a91249c23e8d012a04e3b6fefd504, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0x27d44f13d66a77a645f895ff821ddcf8cced8c8af984dbb8cf82b84653a5db10, + 0xe50c72da36c1a968102edf30c6b810795d41ce41c49783028cd0830acc37c98, + 0x2341aeac831f989ac84a00d127c0809fbc0040495ad77e1d1f589cebe120904, + 0x2071faf6e96fb5cd4400b6c58eb4ff5e527bf7d9492180bc2f4534cd0ae0679f, + 0x14da2ed4e175cc095a8d68ac6e7f9e2d702e82b1791204921bc4806b157be02f, + 0xc6232c7e84ea35400bdc0f7b8d0cd211fb5186df1fe8e927bc51ce0247d13cd, + 0x1f65c4563e9f61ed7f7f2eb3fedcde581ad3b660c5079c16e7ddb053facc5396, + 0x144675f4c54bc33e1bd7aabe8685c740738cf1c7891c5c659b07c6281fc67a8d, + 0x14ece2c3c47e0435cbb019db4708ef6c904b4af975d729a0fcd75e65abf744ab, + 0x118f931e904fffde6ba4e22eb0429be857819f9fd64f1273253b3f152fa18b0e, + 0xbade4f966d523e4656c44854982d4546abfe2f5dec203a45cc463da1093ce09, + 0x1783c94f37d6d9057a1c2e78e0d0f78efeb161a14dc2107a21661829f135d226, + 0xdeaffffd0feb209c00793e5f800761b5419d8725f4c88286eab224160ec43f1, + 0x8746a72fb64c2cdc1ef14613cb535911394a29c802d4a6a94cfef844610c609, + 0x4882711fd9c5508fdd0a1ec5a2a0810b93a6cfce441a192047a827f58ddb2d3, + 0xf2b738d3eb3b803bca325347b7af954cc10492832479183808b3aea72435c2, + 0x2b5d5eba00e09e21bd9202d72e53306361608eddc951ac1f08a53dc3bc6e955c, + 0x16d96e78a6078437404b5bf21aacd5a43d23ddd5bc2172412ad36390b3ce4512, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0x2f6fd52b25a9485df2878599be34808517d5eed6c1d83ce497e1a9ea8d1c3844, + 0x2f0dc0c61f11a53d419b3fb805fc2d476837c53c1c990c66fd1539ec9d2e4e44, + 0x1b004ab51f77388c427453263ea600792a6be597e6f736509c2dbe87d4a298b1, + 0xa690789ef915053a2ed12aa90a8621340337bcae525139c9e1ab973e1bf8881, + 0xc925171c7431dace3626b7e5036dfa622bc08747fe849d6a6ae5c831143d104, + 0x27e2a355bcdae99405fcd39ac25b9ffe773ae5b0ed9a87a9e470715fe2bc271, + 0xd44cd56f0210228281e116260bc8aabf64fa0701601e98781fbc6b14faea9ed, + 0x1ee8d9f2950080571a9605c7b454c3480e64876ad27891241b8f62d71d6ebfdc, + 0x13edf09ae8addbf851e00d79fe8b990277b431d72ce0d9b48b55e3095b483bfb, + 0x1d2c7f3a44dcbed040fe5f5dabd49064622c34af68c5b4afecf631fd998de93, + 0x17e04fb5f49c12a6a91bec113708d943cdc774e64c6ec431bdbda3a6c1c0f57a, + 0x21d9dbd68c54cdb2ea8beaf7de31afad1cd404c478c62e8f59653895909a18ba, + 0x276950c5f6c44bacaee68fd94f14a44a07a0033515b10a76203ab2b12bd60440, + 0x2ca5b12a8ff6ee0156650ef67333a07ff08b156454897b370734c4b98977c6d0, + 0x2379fe3fe77b505f5fad59cc93f5fed7624e99f5359c30d56efcd0915460668, + 0x10e790cb3f6be51c0b4fd7f6e29519bf9bec842ac6e0f6f5584d5cc1431b5c56, + 0x20a94567158dc5f7b21cb0358dfd6fcf75abdd806b150bb4ef55756701d568ec, + 0x191a6a82b77415d9a305c90b8189e93ad9d915a411a544d0fd090a157113d557, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0x2ce2a89b4c51f97166c6adb43491a88c24a3276110055a0deac88f7e71f976b1, + 0xe85242efe6b78087e6f76495c7bef828bab7776b3b6f5b4ae77b9a3d854933, + 0x92654dcf9e69fc2da394139bafb0592b4cae24d00e34981bddcd4b089dd948a, + 0x152d35166a3e900ca89d58fbdbe99caf3bdb1f984deae8e02cf703dd55e78a6d, + 0x250159b61c5e545befaed62a349cd00e1fcd3ea588f29ead5deb675a0101d936, + 0x1e66442753c8d95188bb9f59bad17a6ab9018f052ce8e1de58790b59bc4cd7c7, + 0x1a91965586db156cc0d4fe08208ea762030e390bc498435d3a04d41b95e854cc, + 0x205d22ff80ffd23060ee1aeb5050c709a63a4eaba0847ff587171db7d9ef27f8, + 0xe92e1e54bc59e642a77b5333ddbb2e15594a1956a3ed0e2605dbfe4cd29dd9d, + 0xecb39d5fb42dc2dc2f2b74c13e24307a1f3be67f35ab79b0ac974eaf4a0c41, + 0x77aebae118635d5a0e0160df4961f3c5b796887d878ddcd2688fe1d618150ec, + 0x2d0db6e2eb4386d10a3719148038523ebc7baf66dc538818b0b5d843002e07bb, + 0x1dc7e3849dcf39a59aa7a87ef122afb09009aeeea37dbdef6e850e57ea37f604, + 0x97559815d3b62c28056095e39c8b1a8e366bb8aa42af85f673e45273d0ae1ee, + 0x7e08fce9a5121c2188a96e591b92b958da520778ac0bca67b59da2b3b06f0fa, + 0xe3d58fdb4543949957ea33bd03e3abbfb109a1691de6696419d4b1207f542c, + 0xc991fe43818ea306d3b776847d14f4019bca2070d200e07735c62da31a3138e, + 0xaec16bb8df541908f11df6a64c676183c76bfcaf7748c503d6099acbb3f2a9c, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0x85b7265354e883298caeca1761cd19e2c5c2119b36c37d6f5d666ba8ecbf19f, + 0x10d7d5e67042939ab9d5eed4d520c3fe081f9ef97b3ea8f7ffec5d5e1889e031, + 0x1cfac1f08b7bc16a7482dede1d624a8637eff2c6f5b38e5fbeda6f6bc5cea6d8, + 0x6b10274305c15e9adb7f7fe7cdbb4071c1e4968e46e461c6642a861d0ee68fe, + 0x2cf401be1c32c95cde4ebfc65cbbea9c09f9632239b314f53acc63bf37d86a56, + 0x2fd0c9ebacd03258bfb689a7a700d43b1fec422b22299d73e478801d9533a36a, + 0x4ec21b44c21c6c358789f92b5d126597e1b60f05050975b924cd7042087e630, + 0x2d42130581a19be2488f98c4473e80511c275be79f5077db40b74b43881eb4db, + 0xdf73be8b64e045f882edee4f17e9da2c5f25b2859e904595844adcf3df8f7f3, + 0x1b05101b32ca2be2837624bd01f437abcd43cf6c4b561052e0e6df3d5f0ee39, + 0x8a4f42ecec6f626427ce116b20f3405898759d0531091a87936427a99d5c919, + 0x67eb4a3514d45d7e6468f85a7a606eb86395bef7b23018f25e133f7416cfe65, + 0x3037c22112964f6f3d8e4a607f1f35ee562d505e4a22fdf24b41e6c03e506785, + 0x23c4745c095e5970dac166326b875df52d94db0c9456b5afb55077d92996a8b6, + 0x12ca85b142f5d2d2d87b44b4f190810b0a2ef1cbb96ffb43fe4094ac0bb450f4, + 0x262501f3e02e6a5c95bfcf11749917b22125ff7d02ecdfdadfa374a45173c662, + 0x2c3ec00db9c8e44aaf94ea99dae52f7688c663f0b42d186fc1d030813a4ca1b4, + 0x120aa50356c54653eb5399b101bac1eeb8d728626800003f8858a183cc1320f5, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0xb6c1dd3d2dadac79672ca69e272e4dede9b2bcbace5d12db15fd6c855bcc7f3, + 0x1dc5cfb71f9c9ff08886866b9270504c330bffed807e5f608839afd49bef8961, + 0x2ba9c16f49734f3bbf98296629f2a1a4e6d1b10063193206528ea39b11869cce, + 0x21c37ce612e1b0d5fcb0271e20f27c062dd81f2c8efabe92c73f54d87aeca299, + 0x29ca29c57a516f80006150ba546d332ace95854d3dbbb9ceb57a80f221f45b75, + 0x9644e84f727604d62f2d77c2d5c1897f8b90f362740a8c6eef25ed898e18ed2, + 0x18488a89e78505a807ffca282555f117bc71bfbbb9443d7d06e3060d9798728a, + 0x17f99a49abde27c74d8fe51bbc0a223591121cb9c0efdb32a6ef4bbbc976049, + 0x1106936fe4d91cad9dc00af8b85f8dfdca9298ac4207788a47c97ebd5adac9aa, + 0xb19213f24f13dd43d620c6d4fe77574e3ba66807d606f96055af06344a953cd, + 0x284fb79d4b5bdeb823b0a7e93566380739c2ddde6f2c1cb102f491389af88601, + 0x2bee8122aaeb513f5cd47546f15090cc6730e39d28df08a9ef4f0726dc69a1d4, + 0x109712b4385f9d1941bc8ed4cbee06fece38379f962681ff1f49f2c7577aaf01, + 0x1cee8dbc9e7c22eaa815aab454705b2c2b61ccf56bcc5181d8eb9acd08a4b708, + 0x123f9868d7ebd3d7c576a79f4bb3f0f6f8466aa50c642b2b8fb2938b2533acb6, + 0xc0fbb5f96f795f870d7a4affa961ab0a80a95f9814f2231debbe27352088c5a, + 0x3b268cc3e3aad22d4f8e5edbd7c5179e219201ba62987e3b4a5aa484a30c651, + 0x2e3ff582310fb1449330c0dfed129154d2f8aec3871d2d593b73926a70d8e5f1, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0x18b0d069fd19a7ac7776eb39fd607c75bd860a3b2fa17f90f1c016881eba042f, + 0x12f75e7771d5d27c66ce2bf10cc3e3d6d542f3d39f1847e2fa726386ac83c28e, + 0x107b04155a7d9c1881def05be1797dbc8018beb8fadfc9935e569e2f2a2aa474, + 0x17318bbc96a3594382626c795cc986dd77a81a983bf0bcdc9aa59e6d71a59, + 0x132974c4fafdf621f1fadc45daef9bfe5a92a1b59d33056448a125ae2654d20b, + 0x258538ea87a962769068037de62fdd272eab79bfd68489fbbd478a7cb72e068d, + 0x2cb1201c76a7fa15f79b9ba6ea261d17e0b62c2643709e0f984c937c42115e2c, + 0x2e65cfe91bdd49c663d8749f335176abaf6377f582d48484f6748e24cc816647, + 0x2cd3d763fe99f1b6627e6352b95ab5489d191d0e5d41df07810fd7c52b9db26c, + 0x27bc4a5ea2a66172650286cbea4ff02ee1869e854ed4fcc270c8679a38cc8ef7, + 0x88ff579628efad419d54070c10f57b7e69348ae96ad0fd68b5daaf303ee96da, + 0x1cb43928e58efb24ee214ce17d29752fdce31605fe517609a60f8d2edb3ac6ca, + 0x1dcbf79109a7193b75fd86b82c1590b31abb899d0fc5da91e43fe9cefbe45a4a, + 0x2758dee8dc30394bbf30a412c6dffdb1c7b3c1588f4a93e9620db80265e128c3, + 0x18d1cf4a6c8482ec7330af0eafb66fdd2e4289ddfb61c36f76fe87c3648aafe3, + 0x2485597cfdf560f34e11989c881799ceb14143e0d5c4de20ee4a407904cf1e05, + 0x6151f2ab033782abc7bfd3aaec47dd9c428681acf32d745e37d0be4642aa764, + 0x6d2e5ef950f679c0195dfda3966ed8f2db4ccdea5739731627c012a453a9d99, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0x2d3138fdcbae36004b71f47afa0ec092b328d2205d4952b47e9c90f286787d9, + 0x1c8e178d93f93f9cc56b13c437128dab31456360dbe2415edc316dd0a4cef579, + 0x25bea2246bf9516b6fd6299407d737b445cc6e2f158cd5944c194852cc32956, + 0xffdd4b3b72bb34089f3b91170fae0a6560efbd23ad5c76bea5e8ce46b7c9f3b, + 0x7c622418ddbf99ba65d8ffe6296f3907c1589d4ea2087034bcda1f7c52218f5, + 0x170dbdbc927d2213df51e928d1288f1bb989cbc074537cf64485b5ff05ab8f0a, + 0x6111fd3b375eb2fe504987aee580cfd1acfc7c39cb7a9171adedaabfa2656a2, + 0x25b706a850ee172c03d98a8a1a04dec56d264d07d7995a7bd3b50996f552f9ea, + 0x13a5b2bbccfed9c5c5f846496df832e8b3166104a183299b87cf2e0dfff8964, + 0x256b7b5635f25f506009162f09e2aeac9a24a22d194db0987e9e0196bf805ee2, + 0xa0d91ff25cbc2ef3a667475f91299ee679bffce4ece8eadf3ae0e86713e6c4c, + 0x1f799a5f2a9fe2846d8fcbe9fef4004f2aab2cfbd8380486985787f9e82f739c, + 0x8f8a5d38982c8c9eba1afb2d463d9b87cb412064271a6d721823ba76b13786b, + 0x13f2f9a571f61c75b4485d9f3f74d84222f1d3258f5446e9afb9d82bbccd5c5b, + 0x1ada050207bf232b77af0445cd3ad24ac2856a32df135462c196b718a4e2818f, + 0x2270c97bfedbe3b54bcabf5df1b60fee20cfa8b1dda8ba4c832b580d71930c59, + 0x17e429879da51390e1253592134df6fc0e6149656142baace891a5ac0b3dcad3, + 0x2ca1a03e86b8e8d2cdc32f998a9a2ae3d604104dad81ce44d7b70b7d2c147b1, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0x179e9cc5ce81c3b957469968a01d8f4155d1fab43566892efeb4aac8e730bd1f, + 0x245436e222f18f0a95c5edfdbe70beb3cee0bbe4357c0ad27ec637b8276be10b, + 0x12082995e500dde2a8f5e3db03cfb08fef2e717c59536b6a48a757fe897af0b7, + 0x1ed351a76be7e560be38729f4c221d52e1b2e6b1c9a9906925d9d7fc659af29, + 0x22cea0520bc1691068292d1320ab844c4ff641bd0f3f8b3bce4e50b5302d4291, + 0x10d8cefa20bdf64f680f9f65e2f7f1181485743849125ee5009bb535fbd6737b, + 0x7cd86f2f3733907b2893e812f536766b45c7590516b8e0da820af563de5053d, + 0x18f7e2b8ed7ea1c7ccf0675a588747409ffdc5e0d9a1bd80b54bf47833ba43de, + 0x11ad65aaa14357d137232ee3e2460a65310bfeba447590580d165a80bb87bac5, + 0x149ddeff968dd3e4873a88f82aab2252e424934d62cecebf3c05e04101232c6d, + 0x216e4879dbeb136adcd2e2f9c79d1a899123ec8921531fd19e8f3db769e9b9a7, + 0xb32ffdc93ba89e798035496aa0f0e5f35173420d9605df5c29176b9c8fea9cb, + 0x10059787e4b7b91491cad89e95af648197aab657bef0347224aafea1bd70f0f8, + 0x11feafbb6d30aba9905fc46b2cfa8bd5a1cd6685c3411924f652003f98ce61f0, + 0x18737f1b8ed644fcd203182f9f71ec606dfe5722848319eb06addba0862192c2, + 0xdb96451b25bc2211c315c94b7396080febd132e48883ba5be7c6352454b2531, + 0x14a12c8868c6998c77975fb80588dc50121cb3fe9070179f48ff086ddb44cbec, + 0x64f7699ab015d1466ce5ba0fd8a92531c592eb91011e024e3a90dda0d38d3c4, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0x27370d48e084e132bff2e3af0f91f787a9648ebd4fe7cdbc1cedec26c11cff0b, + 0x16f9385f9edfa3dcc7c06b94ed2c0d8609451634db5a4e6e1997cc144e1415fd, + 0x148bb2cb914552eb1ce755beda59e784541d31b0b9743c10e7d6d798afcff7d5, + 0x2e9181388b5eb930247bb3bf036adace30496887c3fe5e51a08501a57834d778, + 0x45e39ea727e4ff254ba2593f698f79e8e4b4f538d1b263912ba9f0d572a8eed, + 0x1174f11359628820efaa3cca1f5f19974f475fd989692911a7dd59754df86a59, + 0x2ed2ce65b2ae9ab3e5c33366e50e7f9a2622b21df40b38e6f0606ebbd6399143, + 0x14a902e483b773bd59d298c316ba79c4abb6bf6e625312672fc529ad2e1334af, + 0x1e68f7bd5130ceb11d06b8075b2da5fd09c5e2401fd816ccf5e6b14f3ce77b4e, + 0x29827cb7a70ff0095050678d19f2eec6994c2db9aac20c2328029b37cc1d94e, + 0x18b67ae206c91b0907dd5cb14430d2d00b7ca10382cfc464c9451accb64b3da1, + 0x1bab9c538b70fbb24712c9c9fcb250b2725138131fc8887dd31c0ee10d7853, + 0x1bb888723fe04304ff56a7c1aaa2a13edbb8c6d9b84c95c34cfaa32c44cb18e7, + 0x15b938c5888d46730f0efb92f3829ee53afc9b4b9b3e2a58729c31f21c078085, + 0xe56668d5e18b59ed8afb9f3b66f03bb0d8d0be49b2ff0ee4cf05802a6840a2e, + 0x286d890c9e0b00dc5a3185b312d61f861935f4cf230267dd147843d085cb9814, + 0x169b367b1b5b432d3e5f13374bb46fee87ebddae52745969b4d80b371a52984, + 0x2616061981a127f1f90517d00c67ccf537e6a1e60f76e2c18ceca5b4fdd39ac9, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0x2505d3c4eb01aad3e3759156410967fcb1309f9028133f32b61fe8dca05e7039, + 0x6582da47cd85c00d4e318a61669afe8e1969d2c486e76ebe01968bc21302418, + 0x41b8979d269f6ec28ac184c5b2f02af58c26351c6cd943cec6adf2369cdb1e5, + 0x1443d53abe81ab259cbbe0494e98dddbd8284c1145321c2fe24b0fe672cf9115, + 0x78377bdb2570000965c2505997614b99e6affb63d0f8ac1d8909ffc8c2b7826, + 0x21343622cb874753f0d2c35633e7877c6f2f35247f080a1b0ef7012721579271, + 0x2726e864c23bab466a4e2e9c1e6c90bccce6114a31f4283b8a87be3eefbdac02, + 0x8c3cb7979e51a25092b8e3667b5ab696327cedf1db257537071a718d7a4a347, + 0xeadc7f0735863ae63f6d3a2d980cca143ddbc94203075b1a9341fb52b54e7b6, + 0x302733698edfe476ce1360d9dd8885e2fac48f10fd9b6aa494ccc84663016071, + 0x390d135ec3fb0cc6bebb4ffd755406169d4b71ab559edfc3d03da2739f99c35, + 0x29814b855ae75985f8c5a6475383bd701e5279d430aca51d87671614a2eec37f, + 0x1c8271bcd402c844d59746fbb8c809265247177b175fc929101de73f741709d5, + 0x2ea7af5aff4c8335a4556b1e621c3fb76e507132971a4452635d76310c241990, + 0x3758c3722cb764b0eef270fb45c6c76b9d03816b0feae879a3436fdc9ba2abc, + 0x2122e9a87a29841216a1c1e5dcc02363eb1185edc68f6eefdb38fc43454b588f, + 0x2e5132a0aed649314c6665d51926a7a15bdd6a1a5c6f5134faf96d52caadd140, + 0xaaca5b7aa27811dea3376af9fef0cd8275e8f98e235db83ab1361b4c49a834, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0x203898b92bb3f8344f220e9f0790ab77acd669b383111e300fdd94d560eb661a, + 0x1d55edcfada4cde82093e306a8a85e703e70d62f77f83aa4158c7ae06558e2c3, + 0x1c57ec21152ef1becaac482ba2cd28adce9bce68434b291a73dafad3a2a4ab1a, + 0x2c77f75ff6857d39dc5e0ede6ee9b6574764e4ceb3d2235aafaf9d8c296bd1fa, + 0x264024c571ae242f530a593ade47778e04de4fafc1998d04196b3f8dc466b672, + 0x123a17496bdc1d2ece7ee0ab1632b43c278328056b8609eebfc76de77780e8b3, + 0x15d806ca8c7a7c727e02ed3aeb1210453d4d39cc3f2d188f421b58b7fb9b5fe7, + 0x2938fef22503472ffde7a36b04c4b36b639064aeb9d77fdebff756e82ed8e6f, + 0x1d5bd19b2c05765e3c4b83781b4d0037fec97bda292e3167002587051efd0445, + 0x5a5ea7612d82dbbecd031202c5503ab73cf5ac0eceefea81ca45697ad5dfbae, + 0x1dff1bb202e9a71287d999a4436ab81298e44daded91984d6422477266da4fa4, + 0x1a65f01a835cc6df08fe1168ef8dc72e04f3c84bc4129d8b1c57c7055fd528dc, + 0xc6bfebef542cd78b44786f865317d384a64ffabde52f6a5bc29f405d3e45c49, + 0xa06a55ed8f52246944ba9e1b351b0f04e95e8e3c80337f7bf4c4cb3682ccbe1, + 0x237af0b506f0185fc81451144bdf3ccdf7b66cbe1ad77e2ce4212f62d6271006, + 0x1d6b421f3143a560e5066eca69e6939c13cb2fb22bcdbfb96e8d55af76d0a7fb, + 0x1ea4cdc48eeb87bdc70e034a0ee1ce699e94b5b1126776f3bfa43c2facbcaf12, + 0xcfe1b82dde8c5eb500403f5ddedf6165106b28c70cd941f1b65e49725335b68, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0x10cd524d82fe05ba307dd3aab96a838f6b1fb98e10e284ccc8f8b2b9585a647a, + 0x29069f8a102d5fd5db23e1e81b42867620f6af7e64b36f7444176a9febaf9a1a, + 0x3021dd41004ec315704a8d77ab12c93d89a3baba330666cf8b96cc8042eef1b6, + 0x173dbe8f25c7fa7ebb28578e0fd3103fda835507d8b53d905189757d6638eb50, + 0x1ec7dcb5fd4210ff0361f44b48f4818dfce283dcbaba35c96d77ec9888f43718, + 0xe52deb0da59b5f92497e0ba6a2a358342a8d731ce2f8c19c8df9d58ecd818d7, + 0x77276a2ab3c0fad69733ad1fd53ca148350ba77681b6bc98a0cc52bed3ee671, + 0xe62986c860d75a4502cee8d7d8932b7c77a9330c4b0884cd7152383cf21301d, + 0x1977e4ab4ef72d06317496905d6cde467a424f82f7491ade88b7027645c05600, + 0xe5fc86e5a4aa5897a6653760a4e72555f0ff79de77d4de9f5aa20db5afbc65c, + 0x133c080c57426c50ae24fbe4145ecad201b964fa12abdf7ed16ba45bb76c0d56, + 0x9809f0d9404684e91754565e4ed714b4853b2dfe29e44aed4df3df632f9664c, + 0xb9ea2ad9eb74df89ef8f3132245aee0f0d0b3c91975aca7660071a8066b9fcc, + 0x2bb6bbb4b8f9011e6167cefd64bb4874f6527a7eacdaa10ef403474e332824eb, + 0xe7505f5d74a168934234e8a83b2fd267bccfd4e6c79dd64fb024268dba03ea1, + 0xa96e9aab6d37e9d1a4d3e0ec375ed16cf201f7bf07d2db66c43d48f7dd06d2e, + 0x19109a9f6cbaa378475c1ae70ad79d2f83100b33653b9a16bd84cce3e651616f, + 0x2455d14dfc4e34f8b2f0c411722c66ec626c1727fc695abd1c849780bd746a0d, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0x2720fa35b76500f2acefffd7ebf331c17d96a400b4084b78253e3284f942f855, + 0xaf8af05904f43895b5e9236f1782ff4338cdf90b962a3ac0d086812ae628cbe, + 0x25f57c83e4d1831829078d17e98537d56e3c3ca16318f2792b71a07055b11f8d, + 0x122275903e7cd0419e6c815909fd6b655ef0f3516f9c9767ef7c7eb3d8f22465, + 0x20da2a3fb1adcba29246bb19e16ec3a9f51abbd59aadf30737ff92b8efc61ee0, + 0x1942ef506c145d9b15ee431212e1be7bc2861b49e7e68c6ac9dcee40344749a2, + 0x29c8628087cf8197c8538332d6f0253bfa46480244ba31e30d23704022f55a13, + 0x23ec0870cc4460faa687538179bbb9f395a1715195e86a6bb5240d5477ef3193, + 0x220e9648212c6250017065d86188b9612f73f9039803bd329ba7040a9e53f14e, + 0x1e424309dfb1a00240f4dda0e4ddbce8f4ff4a57017fe888e78790e7bce6e92c, + 0x22dc20b39997ba1b40288caabd9dfd3e9f9dc4fd7bcd9fd11079bd602a2fe535, + 0x22275186225901c11a65a53e0a89f199541fc1212b4e96aa7bd3c5bf875ab52f, + 0x17ad868f1ce516279d8d50fd809a1c40e78010418c7aa4ee6a09f9b523a2a61a, + 0x27dff28396bef2873c44964b33b30e44b27a8fc1d08a09175f1cc9641584359a, + 0x9022e1272e97e9aa32634bc3bfc10224a2eed161b9b60f101595f8df207cff8, + 0x10e1f1602cfc30dc4ab3920be41ec7daf5bbe3d96dab568aeafbc350c5ee934a, + 0x1b1aa6b279c2a5fc8dd9a622891bf4878aaed7122fddeec0a20bcf2f9da868b8, + 0x283b86d8cbfdbc913ffd3849a5e70f92b69f5f7917a0401db92f6f1ea11ef2d7, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0xd21897ac3d9b9e3be9e5d182d1ca0441cb3b92776df8798362a4bb4035aa424, + 0x20b3d4db18dd6de3efb359c8e60c86f1d21c20e7a9f1dbe67c4505ee7a3bdd67, + 0x27db9f494aa78c119ef8358a8b122f4aed87152f92391ac9d187f9cecb07237d, + 0x203a42bc685316f63fe61c9146a7426525fff758fc625540d9ad7a5602c6cda8, + 0x2786086cb07a5e84a7bb5516818a0139fbbb33881cd289a36d55dda334f0dd5, + 0x17197184f893d19475737bd7202447e5ef385d2b5f0a5e75533cbbea61e7d791, + 0x505d0e83c6b5bd0ba7da5059689f8f448b27321c23ab4da273db77c954d55e0, + 0x167393ca748cc53ebc1ae07b28ec6a3a2f0d4113b4bd302cec7c0b398a48715, + 0xd479338ab58fc837c9197c0c1c5a3ec515cc52a1a9b2d42b7a3134f2fa13859, + 0x21c2423dd4c9fd1d183de5619442f91ffda880143e43f16bbfd42806fa6c7417, + 0x2cf480612db52dc3cbcd0fb630a07a92e2ea594304763509450bf2d199a2cc55, + 0x71f821a426e22b9a20cfc997f266c5a7a9bb521f6a7353e25dc163a35c07522, + 0x1461f8fe38f4a760b4f4d09b51e6a126d4c5e9ea529eb18c7c94cfadd1ed45fa, + 0x1357d0271c479b5dbfee4a3cb14ddcedd8cf50365a31166c5462acae0b72b38c, + 0x2b328c0d80b8e81a1de5804422b454f019947f4cc167476ae5ac14862181abda, + 0x2e3b540ace24978dedde505b42c9bfab888ae08d442362449012e0806891b93b, + 0x1ce4c3196ea44d6a2aacef87560cc1df5d652527f00924c598abceb3fa9fae01, + 0x2851d688c92c184c79c18d06e3d80ef439074686397a5ebf0800004ed10b715d, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0x196637f7373413fc37b3ac318b969590ff0be31ced0513dca26a263d5dd965d9, + 0x174d93a947b4b73d687a5ebb5a4fdac7afce1d9c34af4feb7ffc41be2aa210ad, + 0x1a844947654e868c7ee686ab18a2224639739de7ade503530f19e2743f3640fa, + 0x2ca2906ae9b528c0ff4e3e3257c8d319f8c1368eb73a80ab26cdf1ce15cd497d, + 0xa94ad92e43366cba7b3db85cb00b7b950f1d221f05642cba4d9519a6afc9a1b, + 0x22bbc0a3d2c1cf2c8556116779eab7110ea892f32dfb0ba1db5ed38c6fde17a9, + 0x1e04ab6b0dd11b6c3f59c29bb6fd62733161d74a9952794eae23df935454357d, + 0x229f3e8f6afdba218d948aeb539787170f4e836aee874123698c47fcf37c175a, + 0x995cb64172f8220d642030a21f1d525c39724738d58054d8cb6ac84a16aec03, + 0x12b8663b8e3a6bcd9e2d7d334c88c0fd315117db2052793a7c2434776efb8358, + 0xe306e47bc917fa7e38db51ab6102290228c40250770884029469817b112469e, + 0x290d8cbe5211d46c41f561e89988de784422a5f75088d0cbf2679d753af7ca2d, + 0x1e0aefaf9cd8ef424965e8ac51a7562e11506da29886ec17006b289370ec77d2, + 0x4df18fcce60a87f50455c9d563db8f7630a0dd63c55df4a3f549ce98663649d, + 0x95973dc58f6505b00c033973bcc95f1d068c316710b63260c75e300e8f20f98, + 0x1d18acab418de031d02587a3df05d9dc50321e206878959871c7c2681d9e9ffe, + 0x213d73843dbd3c4e90fe3ff4afb54f113a94a1e94ae7c93e062ab7cfd7ca42a7, + 0x13807261e197788f606915b736d04f3127e3a532870f6a2885a09e47c7a9bb03, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0x250b609ce88f0983f177aa4b1293825acf49cbe1ccc1d0d2218eb7b54d8720e6, + 0x2a3d7388587ce77ad142e1762efdf17d8904edd69a6a90161b19a806ca2e5361, + 0x1905f00fc3b1cf3fadde47cb7e1b25bfd0fc503fa90b34c13b3b1d660fa8478e, + 0x28d30399b0b09d77d5113875af727910162825bdf73eea4dc375729c8b1b4415, + 0xf6056c7c8bb29f47a2337228d5bf342fbedffd5237d233b3f1505e09b063b94, + 0x25e6ecb2921119f783a410b7d24c83a5d9c917461edc62d0cf95d21be424a561, + 0x28da486586fa7a6ee7a2505d51be49e38100470b4ede3b1ee7a5c364ca500cf3, + 0x1e7a7c44e72cd5a635bbd41a543c9f46945b7851ee8b482871b3176557846ad5, + 0xf8529665d21549208b12388dbbd55184f23fd713258c518249d4ee7f3acda6, + 0x1632d84a0d31502ce509b0149da1a5293df1f8c11b2e2f10d214a2f52e4ca22, + 0xe576e8ba8cebe7bb81ab72d7bf1a08c9830ad49016e9bdb83765bc6a05dd3cf, + 0x116f9f8556eac9dddd689100fc4e27dc9a42c4534322f4e18379bee32b53adf3, + 0x2617cb3f694b9d35852d5341c15fa51a47076430dc407b88dc708a57a4dad9f7, + 0x2e1dabfcdc2242aaad7c5601c45aa376f8bf128954b04c477946e91893bcc19d, + 0x20561db57fda4a5d18be48461c4209d39b3fd760fcbcee93874249d4a56dd4a0, + 0x25ff336f1b5fa16576da765273bde6d1966d96264cc4e70766d170cffa123475, + 0x2ebcfead11a0a9f882539b2129420c8c952361a46298713c3ed4d5d6af8ec602, + 0x17f4133aeaa19e905765128b43d633f345bd34b512f2eef16a1dccebc1cc56db, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0x1b3a49687cfb69278fcec9c9024c2cca61a3ef43728c21bdd11f378bc219aaf3, + 0x21c2f9fbd8e7212a57051f8e39c6e68f3849797e36692723f44e0861264a5676, + 0x115d3df00fd3bd6e540dd0390165eedc883ee6efc07b409f3675deb598eade42, + 0xe5729bb5e9bad3ee592068ecaa3e9fe83de56e38603925bdb9862a460ef4615, + 0x285440545506adcfdb2776c74d3aaa25f7a7b0de3b7c55f0e5b87fb7b6e0db46, + 0x233f80e930f4324a6a0b146d07acd6fc8f3d9bb48cfe1f072d75f58da84e1eba, + 0x21f9ccd305b8bc81a6b2116e883c69ad27c8455063e66e31d6da818ad1e74de7, + 0x28fe2473f0cfc0914c93b9a49af57b809d9b205f2631dae15c8c9efc67c5ab3d, + 0x2ec03f45ffe70531d6caa30b55289cff6ce7f852160797a2b9c90768c5c4692a, + 0x1b6d0de6db03f0bad2f0d4879bddc431708a821df4cac5ee89cc9c9ef70dd9f6, + 0xa11e8876f08f694ed493dd39340e775eb7a6a41aeeb94b274f24be97e39a3b6, + 0x17ede99ae68e039acf3cb8d353b0db916c2f2e721f19965a474f47f1341cdc16, + 0x18fff4f3ec52c43729d8294575f23f8bc41d85b9bea877df8fd12726dccc4909, + 0x21df71f2c6a62f3945fddce6d52d2aa7d326b29262ef4b298027c26473b9eb10, + 0x11b89da0475d9f041a5380c999272eb4f787090d1d55b9860ede80ba3983400e, + 0x8dc1602808b04a2f3c3a15545d364304f4f7cdb9dbddbdd6f632991d0a5bc34, + 0x7faf1ea463a24aa2845460d38458855ebbfcc9e1d4e775a350a0e88275d6fe8, + 0xee38f40f3c1ef1102552cfd03824d68bea40bfde95785d7a4c3adfaeeb4ea1, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0x17fbc184678cfb88bd30c7b1c3d7b28864204d74133ef42de469187f5ffdeda4, + 0x1cf9d597555605a940cde10452784e867f46a2ae74fe0465f4938c46a546c3ea, + 0x1c092bb49f2b4366b33e2dc2f6ee171468f95570188e4b2995b925b5539e8d63, + 0x12f62053127e2084dae1db28a6d94ff62ef6a1a4732ab052b20395d0cd4ad478, + 0x1eeb4476ad29cbea12ad7cb44732113e58c0ff598ab4648df979c474eb3835, + 0x2c38250647fad3eedcae687b1ab54f6daa582bd29631c73fea1d2f5c403ddb7d, + 0x2eec86ab0272f57df25d8453fb38e9fcf0dbcad228ed15b9e7ff30dc91feb902, + 0x254f0f4597efcac8bf9ee78bbbfcddc5781f71565217ef7af0beec6e5d5f06fa, + 0x12a47fcdb1b19d720a4398b659b2c74c27adbd2c24ffae0101c4d129bece130a, + 0x1bc890c0199da7edf2f39365c4118f3c1d1ae24d666af9ffb83ab48b3e00a204, + 0x125272075c48ad5c41dc73c2d27de0026796d6b47932bbeef89bccdf92fb7598, + 0xaeb8e71cc24b05d8b4a1aafb1a16f8400cddb91e6d42fc8588ce50a191b8c4, + 0x60ece14c283b3465418c6b9a9f56cf9c96218b68576081014122ba05654b3, + 0x14728be414cd1dc79e436e4d72fd9392e44ec7d6093af846a49deb20f2823269, + 0x21d5f66e745ef28c0f7178722cdc14bebe02412911433fb460be724281ec8361, + 0x6bc631335961a7b600aec2c433a850ef58c811cecbb74bd1244e0304ec9b6ef, + 0x125b7c277f162a0a077cd6f1981e5f22dbda2a0b0bec465a384387527ce3ed3, + 0x2a2a1ff5ede20300c015be7630d8f1060ea8aefcc7ec0f9606e8aa8cae99bf4b, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0x247c5ff976e2ad2713b0ed0c228a561962155f3455fe766e747b3cc613629cbf, + 0x28cb0837980e09daa3e697291898baf1629eeac4e46342bc071da656c7bf5fe, + 0xfa57cf86065e02c71402e6dbdc251b1b76c1205eb14d883d95b957b376c6bf3, + 0x1333d78ac8096483ce1959d954323802c853a4a0369fee7ce1261828501ced20, + 0x14d5ea7f1472388751201a664b15f402974aa24f6cda9a91a84d56b1b6eaa776, + 0x77a697d92ad2c070d058b32564a9efc7e1a037a1d03962db5f2719de5cc6c7f, + 0x27c6793303f3e75361c67fe56b8ede9c3b13ebc8d10e6ff787e69aad56595064, + 0xd69340f71fbe2b9772464b2f1fdb25c5d93cd365e24b6926705a77a890e08d5, + 0x1e2d709a891be7d5411fcb2eabc3cafcfcfdabab79964189758d1afaf70a6970, + 0x2cdb124943fc7c3287733a0a3c078eb98adc3938120ca02b14a58a46a44f4fa7, + 0x27af11497cb4a8d207471064e855bb48d8786f0b14366f833c710766612908bd, + 0x392c9300d049ca31025170880a47ad61b80b1dc03f3e6db3264ed1219db5b04, + 0x2aa58c8c95a91bd321d83ce2682a4b7d2f6e869a0a4cec637a272b0b30d58434, + 0x16f7b5e9d83339c0a151b1142423fcd8d2c1758d677a0ff7d1dfaedd525762bb, + 0x240b50d50ff6a5930a55ed800af55fc621e8b5f0333e022a49e1382ef80231a4, + 0x16e43d57fc3ecee17611fafe5e8e7b053808f780dcb1112d1841f4ce52c15f3a, + 0x18b989d920dbb70d51598fb2a6ba22b1825c2f3f05f7fd4897516fd749e8cee4, + 0xe4db6c770ce5d662b21e5b463d99371bec01b6220af53375b8d24bf76685d9a, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0x145563ae8e6e1472ade73ff73dc88ec306cf540be2894be758c99953826664f6, + 0x1892c99793221d1f11e9c5637757db12c001ecef9965c00c697cf49ba9b881d1, + 0x1f965f8daa018ee30596706f17773d33e6835e66b8aad44e71955303fce6eda0, + 0x2935511ac83c99085b247a68119593d44307b95394392d8bc1e4366b54021442, + 0x907907697dec1e1a3bd179fa8ca9a87265997bcc1bed376bbb2647430afceb7, + 0x3396c267b0ba914a9c4ba45fe06a86a8b3960aa1dc12ed7943cc8a45fcd50e4, + 0x679ebb051d64df99a0b2c93744857adaa8802bbcc6c17cf0cb29776fa229e85, + 0x2f93483d03549c31b606b33224139de1998c0be6f9e4b900d9fe9728588c98d4, + 0x1458fbe748fee53d852d83b0e7e032dea42fc174733ee672f833d8c91b811a65, + 0x1a90f8cdc1c63f289f22cd6e4eb3bdd3b7ac9f04cca49d7d7d8cfb0f725805ad, + 0x132a4fa82d6276051f33621249f4c6692cdde99766e52b21a0896e2faa1ce5ab, + 0x1d79444933015ed9a7b37b53da5f35dfdd9da1dcefe3a454ec98da690ef1880b, + 0x268a91dc77ae88ff05486fed8eddebea679c01bde73d634f5cfb29babdbefd07, + 0x1e011a8f14bd69d6439cded45b157075e5d44ce51f4f9fe6279fa269e999e1da, + 0x9d4ccb992e2ed6a7d1e09649849084e4c7af1c79db784e239c39daabbc69a66, + 0x4bd333ef75b6e20a0a9566c7f072498868dbe38e028bead637408c6aa43f232, + 0x7a22ff875664c4db8334871b434ba01e949c60a4264e8724abbec4d9822994, + 0x2ce7c0aaa7d361da7d2d170270aa48f0a962db88bc02f6779be5a5079e40c85b, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0x5c14e041616b9d457521c279f662e02245266a12b5164bfe05a7503440ef15b, + 0x302134832f0832bcb9fc6fbd7f03c49e7d5d081d455eb0e3267a6e48677a417, + 0x1ff1fc0a5041e83cf8c145b226ba9e4f38e42e58d15479caf6102d5f0a46c1b9, + 0x743a2f884e7cc1bf16bd83352a5b3324366cd09838da3b7af8c09aa8b907ffe, + 0x1602376f4173d959749ec5daed8394b50facff3fb8765a89b59b6fef0a7d1b41, + 0x7d2cb9c94b0a81818fce3f94e82bdfbd1074e8c5159e7fb0ffe12291e9d833a, + 0xbb2f1a3fa920981b76feca1519db3aa3c26b703facde82423479b244bfd05bc, + 0xef15ab6018db6f518505668756a151c50ce609657ac3a1390df76759e9eeffc, + 0xe6e886b5371587ec93eadca0b54cb77c72d4a709bfd9431c5e4eafdb1f3f3bd, + 0x43868f796a09019cee928cddd4779ef6de4ad17578c1eb5ed9ea01761f46a30, + 0x244a691b12e0202fd70fb283580700f2e25747c504c2a0ebd58993becaf84eba, + 0x7db83a16d8673bbf160b3b0d5d96e7b14040490acb6787052778aeab1bbd9a4, + 0xa38eb2851046d266aa8aa6d124f312e00bd995992adb16e47a60a086d5b7819, + 0x9afd14102f5641fac42f5aad7e1e04fd5779dca6d20f21819ef3eedc779a27f, + 0x17f1055f567a079eebc36cb46488e34062e598ff88e9e4280f0472021891d500, + 0xe742b77b8daced0467679873f984332608e5cf5f573295ab6ff101c86bec259, + 0x1e0137861ce424e6fe1f8161847e1c804525945db0267bf56e8af64c14cc2d2, + 0x26af9938a85c56e60ad89ac9ea7ac83e04f574d33d340f143ca5f058e2ae18ff, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0xca3bbffa94a2440660ee1481664e28729a7a581eb47fb1e7f2b8d19b33a7633, + 0x56ddf288c8533174801eb64e46e332ba077df88559d617bbfdeffeac12c935e, + 0x18f68bd602682d1267ce57ab65f27dce1859bbbf29ea5ca4c1a7c47ee6921f3c, + 0x30595b7e6e83bacac2e1b9744f97c045f81ba17ab940a093f0786aebf107f4c7, + 0x636950f2ee62115195d570a6c43d18e92a3edafb2eb0389482211b486f979bd, + 0x874eb8555f4444b951b3e3134f96d75ad8866a0da0775fcaea7d80cc0be0c95, + 0x165b30894e68376015f8589abacd55512eb63d272ce68ce7d478beab7672b55a, + 0x19e4b9ddc57a559648da219a93cb0ddb0df84b89cb0192814743bda58e7e025e, + 0x25eccd6b96f10e2a0da8fe7001a7458e10c3e669cc6e9df84e4b108c20a7802f, + 0x12cee7ff70207b2601a5198a71c1430fe3754958721cb810b8de2fa6c464488f, + 0x1f99c9efbb41738ea513af1bb140f11e84ce414f08168e165620a36032e844de, + 0x12529d825e81e3cc950c208d2e40375f320daf93ae7e401dd21f31f69ec39dd1, + 0x60570f962275a45bde460c929edce1c9e56d5bfdea7f5165a9ad1f338e43278, + 0x13d11f33f4e872a1d7fca8fbe95fa47baf3e57002783f5503c6522c2835d8c20, + 0x2359f3c444f7908a0e3a80861a42251115f650fa4e66febf815cab17676fde4c, + 0x137c3d8494fafe8b81567121140a8933a957e06a86af79f21aa0786ee032071c, + 0x3527cd631d2e66d0f82218ec1a2ae78d58abbc17519750f028e010153b5476a, + 0xd67de5a809c3c17ec81f87ea47056557cd9a21c12e615f68b5a3b8b2be5ce9, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0xe0a49d17b5fd53e41c716eeb7c3170aa596a3d994cf780bb4fb099a3e628ced, + 0x1b7180247c35af01d58bf18ce746e193c5f9d6cb530deb707cc81f01663c2409, + 0x2093c5ad6ec79e87b4c99af53c32b7c13559735acc74ec744a45da050d6d56b, + 0x26c4d026b6da4a405fe6d74238747fd571561b7265ee49910c447438e9c0e1c4, + 0x1fd3b662959f05a5ca35ae543da8095f78a4544159475be1e9d84592c526f777, + 0x1d8a119da46c01ecd28598b1843020f2affcffbd0d2ab74513903b0271176911, + 0xdef9ecbfc4c245d08fa20010a22886c01234245042181ccad19ec06eecc5aa9, + 0x2f389eb9dd0db3310260a089bb9d0846ed025ac437c1eea56dc5c7159e8474fb, + 0x192d09f6e1f97e95858b09dda316902de5e0b946d3050a296e86fb90c0824460, + 0x2abe84bdc7a81e92248e62816419516f31b9df3c36088df8b0dadfa242af8f96, + 0xec8036ad332bbb0d8eb631bcc55ff0dd1c71823b8ebd6b8e0699417b22d64d9, + 0x212d905745129480f6496bff628cdb728a729394f7e5dfaa13004a4dd6d7ce01, + 0x28b10eae188741517e25e6abdfb63f5c0b8234a453ba5f73d55731b126b8c442, + 0x2b55e73628a3146399c9c4328e7b7c2b06c3f9c6b2d1c2f06de3b2b54c2c50cf, + 0xa288f1c2c2e7b4fd66632360642bd18970ca489714681efa3a79597368000cb, + 0x2a98c6af21ac38e6d8f70a8cbb5988d6aa929c6cd8a7bd41de02d6a461e00398, + 0x28131733b6f0f9dcab73a997d3de4c14bbfbe517135d1a8d0559f0974ebb89e3, + 0x1a0422b448652f8ff28c4099a5857e35474e8864c82b0705aa291052fadb42de, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0x759e02ddcf9c02faeb9b1441d3e04e2e26b1c3c21c1a69dd452798b1ecebff5, + 0x1e6e510013a7d26108d160b3bfcf269ff0f51a0759e1e1b2731f7c3fd9f65679, + 0x87b228c959aec21d112b82be8167799104fcf2f6a1311a8f8c6ffbc9b91c0d6, + 0x1db2a8fdf80413cfcb6c77e97c570ad471dabc38e8cb2fe680016f0dd6d2c5e1, + 0x2c866e9e002f7ba0ff4a92bfc05fd5a9cbd2c4497ad9957ac9434acf2a3d3aad, + 0x29032ecf930c2a41ff93c287e9bacfe4ed6435f5bb377527f945ddd90f02269, + 0x21a948d59bbbb4b75d7e62e29f28fdc1ad21e673c3d895d264f3cbc0b9c0e0f1, + 0x1dcace62396a9c5fefb317bf0771ba35e345a4e113a9be8b9ad3bb4f6a62a287, + 0x29f8ae5c1ee78bcc95db21cba9113f31c1046c41d866a70383ce008a9e6aa748, + 0x27c5c8707b69d2ab24fdc16a043d24f3a2aacce0994aafbcb79754e26d7a3c0a, + 0x2d34b96bbc3259695bdc35d7ddb28d896f64b94f0923627193d50d82930a61fc, + 0x150254ed341e43d3a5edf9fd4825f8094317dfe0f198f908355c9ffc0485b4a3, + 0x2c4ca99c167d67e6ad639409ecf7669b0a99ace688c6c9c33a34d71dd3ef3c97, + 0x3930cd56e534c58be531f7e9e2b9cb3efd62d541bb6580a1246dc9a4067a7e0, + 0x24f69e897348f292f1ff886d4992b6b108f1312a3b194296f07314af94c27016, + 0x2334c3ba5fd553bf774f53d77c3f556d404f487ad7597abf505626e5fc34a054, + 0x2d72d7bd580f41990e776a68e9a1252d1c5d003fbc9bed64162a1dda8952ca5a, + 0x2a311a00f6cd8196a6f12a725b9791b49f46a20955a0cc05435e136c3ffaf3e2, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0x15eeb7dc60695985cc24a901b81f2c2ac6aee050695ab1de79e300d546b1f043, + 0x1065fd42737ec473c96a3741ef8119bfd955ab6066955d4cdebaf9761ae33e3d, + 0x17c3d9212a09026f12794eee3b04840280b12ab06bf5c688f02cc772608fad92, + 0x1b3d7424ea8664710a024d5f57c9d3b372e2c1f5428683da382464e39154bfb0, + 0x1122aedb98479614cfe5927434d6cb11a1ddea539e33c7771ca44535c510427, + 0x55e9bded4cbbba7dad989d9b1295c5230d5a799a6211895bc412ee24086d628, + 0x30263db0209be791391ad08f2108574a6a882f05b6c8055b0ba9e0ca8715217c, + 0x643bec3e72fe54060c78a6188b7098bbbcedd5ae549f5d0f95594d03501c1d2, + 0x24739ac04c239ad6549658ca1b7e0f62067bbd53c3f0ae9c3a0160dc8982cd4, + 0x831cfa01b84554e6f26b9d604c0f91447c6c5ac03ed1d318b7944c5773827b3, + 0xc0570121f291d8fb7b7a62cae11ea568a394915a9cd70f634830a5e36f93025, + 0x2994d07daf7152b5024957f7188fab4452714606c505530854cec14a582bb6e2, + 0x2e5ad16ef38f802fc789dc46eced2ccca71fd25cead1d5d1f14c482061cc703a, + 0x9f1fd3fd77d399d36089d589dbce43f1f563d8d4d927122bf29819a0224053e, + 0x1cdd5d1efa77002334e3af50973ad87009b6d26818bf78396b7d8924c7aac675, + 0x2bfaf90c55d63a08a0ac948874f9b1fb60c0faa0a530926acf868296f8478e0a, + 0x12d3e6c5009562c1647269d1b507123a2f0b7729804b66643f081bb782ba7cfe, + 0x36e9be313a952e3b77fa42cf13942e292982a7568964ff200356a1c6f82e473, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0xc34e42c97488447c321d23db64b398c6c25d4d9fd1fcfd3b5626674a42d1cba, + 0x27d82eee53199316ed144a5591fdae1f6e2be76b469f606e7ff6759a8920dde9, + 0x895f2c2986316092a0366d6dd018ffd6439c477996b4d2eb5c3aed2cb0c1025, + 0x22ea26e3404fa1f74ca0be2b73237d0a44014f6036f9a96a1ad1b6a1393622a5, + 0x245f9c36081e0229dff1c693e33858b05299349c921d4163c12b8a60cddffd9f, + 0x120718feaf2106067a3dd824dc15c3639312811c1d8e57825aa782de88a2c3e9, + 0x1cda330df4f05747f9fdf518d146f9160556d32d06f8c21f9f22432ae2abbf0d, + 0x17c8bde1641bf784599b38a3ed9568cb3e2a8366bcedd556711e85bdfa71fcc3, + 0x3b039fece617d27bb74f64fb7c0e24adadab1215fa077988fcb513b7990caba, + 0x2585f69b3b7caeb08b4fd4403b72457ff3953e708f20a2a0d40872d5571dc707, + 0x1cf1dd7016fc72885e841cbf7e92c931d99a2cddce535f72b065485b39fde3c2, + 0x11f30f1bb28bfba19b81bf60611b0f26c1a2a7f6623aab774f999ed62be03449, + 0x179f6c3ca3fcbd7aad8e1ef759216d589ab51482a6f7395c93d5105ad79c5e00, + 0x5193282c4bce9d58154eb75ea6fa29683e2d2376d1e2b9d2265103b323c014a, + 0x13f144857af17bff0c12f0fd177a6da9b1b3b10842f4805689f124d52d1063c7, + 0x290400f022f09b1359bcb9812dcb353472449f4be850a28d949f914290aa598e, + 0x26a590e2d283ea4e4bdcc39fe4cdfcf9b8e974b4603ee78ba0cef07e042da923, + 0xb0bc561fb4ba346db8f28d41eb0bcc6bb1c40217610f165c5ccf4f2940ca1a, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0xfc4b28f50f749c8b55bb53cfd3c76ed13a11e16eb3816520d732174b68f9694, + 0x1c2ea86841afa29997e495b0e1cea881562319d9edc2aaefde7b30da0118baf5, + 0x181f1de1e627bc0229055b2c08f12ad3b70d540b24fec6128e359cb8f32a8a, + 0x2a4b0a0fe77c7afd26b08ac0eec6a30854cac5eb8c070db07a0a3c5b80626747, + 0x13f62bb9fa1cf209e303e7626fd734710668d02b4efb3ec507c1f5a4b59ea94a, + 0x2b5f4bcb8b0c0c1aaf90e370e93b611bd34015d4f4083b6feff51c60fc7f90da, + 0xf61bfbacfe1eab14181c0b9ccda1da0272742a0c64ac873321c85af7c0f4253, + 0xf29b98701d484f65bde657f17209bb04d1cdc52d1d45b8357d64153ee0639e1, + 0x4f50fac0a62268e7cc24a64ce7f784bb1d7982be69a9dd168b0f191da33a5bf, + 0x31b6743a6fee9be625862c05ffc4d4c656e30e17a4d1e9a68cd906ba9c5c784, + 0x1b2d7a1f0ad3dce2e4b7fdb43de39d6044b9713b47c82097fb72721de84b629, + 0xf2090d83056f23a0a8519ef633ad3f7454196a1da06db6aa93bb72bab913dac, + 0x1f36ea15e1ef84a869d23f3fc7c3fc0bf425301e98022694e534a564ef69610, + 0x1e7fdf4b6edfd3e8e19e73fc8f938b96bb271f0a8b5beaee67efb0f5fe1d8945, + 0x58727d0875e0a1a590634c527e8b69a4c6e443265d013000cfdd5f00b9faac0, + 0x65c67297180d56cefd31cbde7691cecd344e5517d93d36a2ca00b84f2ac6406, + 0x26efd963a80f4104192b1e66102143aa18c6956b4edb14eac83399cbb957d426, + 0x2d36f46690e480d2cbfe0f647ac99c753cb01490ad79327a1192e7c5bab301d0, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0x1ae20386490ddf16dc579da580c4736d5e20066e4ca980efec6c412d6c5fbf20, + 0x13855655eb53d070d6a3b9283176ec875cdd04a2310a8bc7da3778bba3a8bf65, + 0x216a5047fc9a6423e0dce5c2fc7ed22e17a889ecd7dc313ec97da530b0012dcf, + 0xce0a7fe4c77e0d037ce338a7272ed67864f566705e5422b954effa901c1190b, + 0x295c4b9a9a97eb19dd9bc5cbc4704fd57c100276b7af57e07be392c18a953bc2, + 0x2989d23a947312faab571c5ddaf9c4d09c22d1876e7d007847511d6e42c2f407, + 0x185d73d77a0e88f9a67e2c1a59d6473706e24c79b845ce5f9950f0fe26d6c794, + 0x182b0ed46716f64fece882661791a29bb29986afb83cc9e194efe397288aad4e, + 0x22ff21a0030a575a4c62a82b286a37188b4cddf6d4285c60b60d030db206b1c8, + 0x1313437aa7949a4ab64fe85327645748fd2a58e0e3d3b85626e88f7339d7b261, + 0x6efe22994b02451beba2f6d0dcbfbe9b920817d74cb212adb7f738178ad2f40, + 0x301063036e4697bba8d213d35d188697239bbd1b369e7bd294ff4dffd10885f, + 0x1c90fb3a46ac9ade74d20bbfe8403ef060fda9603773064369d4c344bef5e817, + 0x2c52c601cc0042b449329c045fea856de70f98ea8d1b5ce3a30ccf0fa3dd8a52, + 0x19034b0b0a87c257ac4944e0500e97bfede7ed2dcb148c9546e3b581aba9db21, + 0x27b086852644a1c773f0ee6c7cb6e58d7bffa32638b79b2990bd7f1dd683eed7, + 0x16cec1cfec5d548a707a44ddc3afee7db168b5e986eaaa885748a368d1fc7607, + 0x23e0d5c20594133dc55043bcc80a422dc9d59ff92f3e1a9e934d7c7486bbd410, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0xfc871014612f0f2153585878907f011cca957eb00e86bc50f319ccba20a005e, + 0x179dfedea941ec28ce16ad4a6ff320656632b0750e6616889e853719bfc6e88, + 0x2200eedc6d000a31ba05af605292a6ac3db87e5e852b7edcda9ba306192823e0, + 0xe0627308b4486b9922aaff007d2dc88a4cb80da9d90be1bd13d63f3ed7e1fc7, + 0x941ece97766c9dd37c07cae87220151b9672f02bff4006700310b95efbf4f4d, + 0x2d8806727504e7c422452287f378c0a9b859897254372eeb4e4cabd2c038067, + 0x1f44136953c36a85d85da27e57a6dfaf955dc7e1d456790e53526625f470624e, + 0x2ad2db1a37881b1f73e5ae98d404672ece9487a08ccced17974e1c925b0f0234, + 0x1ff27989f4d74b500ad47ef372b8f08396499e4461ca7ccc5914675365cbdc8, + 0x1d9e4bb1ebbf654ac8d81380ab49c45c698f4552fc2b385d61f1729f9a434fee, + 0x269d2125ceaf4911300dab597dae2d4d97714a48abaf059f0060c26a6b462411, + 0x85fe9b1797ff4833c76f23b0dad53a01728edbfd28b9dd5097a727725bae3f6, + 0x2a1e5b7a8bbde19a0e4e3e189a5375543ce6879b8ac6c94b3541aa7b1ee5d73e, + 0x38f9b328c38f8ceba41d67319a3186ece9be1bc9d16142abc3099e2a910e1a8, + 0x3ebea7ba2a89695b6be00973736a209479d0e834a37f5ef2863063552d840a7, + 0x29a1eb861aafda5c9a36ac4c094cc8763b491902b18b9dd29bb1b8dc216bd96e, + 0xfe28a88001c17b2b1ceaeef8891bfc5abdb937c7fc6d51b2dfb56e5347c6294, + 0x26ae83ff720fb65932e831bdb0705d7ae60c0289f7bcfd89a020a5f3b30eafdf, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0x1492bdc61b5ceb6fc3b3d91065f585e0d1b037bee203ca82743459c1ec00c65a, + 0x275f2dd31c5b79b5f188ae669923494e6ffed430e8c75bf202132e50b25c1a3c, + 0xb327a4ebdc41f56502186a656ca06819d1d29a32a6e70588f548c4fdb2f689e, + 0x2c5e3d0108521c8af0d038a617f2a0725d5003a5b9dd824a95a59ec6bde20b1a, + 0x1b611cb1e5f7f2a0c4fbcad4e9dc65da5c6a34190fb27a8148359d465165f9f2, + 0x22365c55c48c5736cb4b7dae8fff495e9c661e9e130af620cff5f40fa1210e96, + 0x73fb93220556a2bfae1e07d2d076caa44c085e2ba6644bf4256094af48ebf3a, + 0x213fb8bc8c11ecd95bb3311eb046398f377c3ea4208d14b80eaec8c4aff2bff6, + 0x1a617c5b998762909c55ac93513a6d19ed1c1e28ff8b78fb3f551158a9d0d99c, + 0x2e1284a59a10203966d53cdd502405dea6889490f9bcfc5a33ff9d8b6fee17c6, + 0x27c73897b8aea1c08380d8ca28d0405351b957b064abd17afcc647b73ab348cc, + 0x2bc53359578a242289a79806c04853ab89fca02a6232f152d05b3d1dfbeb6908, + 0xa8ec1ba29e112cfc42aff081ccd3e7e01410696cb5510377072bbcb2f9600c, + 0x2e0634f26f73f112cc5f285e4a232f694b79c05ac5bb9c9dab89dadfd0112ce4, + 0xac9a6885431d005e4aedee93dbcdb638cea5b17c363289adbba9ae9e3fe744c, + 0x216854bce3077af7b8294565ec200c0c455b9d5fb35cc98ca36a323620b5eae1, + 0x1603ef2a582a0adbbac5655b3c3202b60ed3c22e59fb442c2a7962b9031a33ae, + 0x2cfd0eb51e60c1c0869f5dd163666ee8630bb2f3b527af9860f8e23b2fe1a869, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0x183f34db24beb7107f0f5bf9fd4c2532033855c37b5463ccbd658b68d870e6b5, + 0x1a5079190245f746de5345f0775f5ea91712edcb4f165f391e9c8f0b1268280b, + 0x249da4641b8f13206d3cb7b3943d4ff5d0813654aa5d8ef4eca39cc6cddcda09, + 0x2e99f0d1ad289d3d780147284155f335f34224f7f8d3db6b008d952a84a12f2d, + 0x1a95c807b653b762910fb0b9d8d0b4a32b000f490fbe925e0e207842a2dac0c5, + 0x127a15cfbd88e0c122b2905572c496df5eac209879a235afe08e8d2e631cf46d, + 0x1c22d61ac34f05eab74aaff0cfc01689132754d26de62038964b5a8acb1fb340, + 0x2ee46c0fbefbfd75eff882d395294889d915a1a1e858e18a5b14c4200754f9aa, + 0xab5eff34c9c0bd9fc90db5b058bdf68fab4f25eb7602e9369060fcb6df9139, + 0xa91d479dcbe07bdbda4249188361f7aa7e00c8edd81eb74dc176f19bf05e8f7, + 0x276a57e2c21843be0b10b8877849309b33d19089838744ffc2454199e6833f63, + 0x2a56e477fb4a285b4edb52b2f19fd159914ec3b384dbad98850a19dd9f44c2cc, + 0x2fc33d4b761a6ffe69a5f4f2ef4f41f727d7131a2ce15f74f67ba17236e89263, + 0xb9ed85bc3e43eb0c395ab7dfdcff5da94fa809bcf5d20da866a2e0712dddcde, + 0x2921971bfb16df44acaf0447858eae04720bff84acedf57d1059016932c0a9e3, + 0x1ef4f47e8d9e92d554c8bf9312e0c80f5850fb5f124421a4a032243627170429, + 0xb099dd3d5498781141cebbaef8b3c9a071d88ccca2efdb8d97071e878718f44, + 0x304a086e6735ef7a00c6d5fbc6a55daba181f3ca901f5de3c9a29f6161ba5f36, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0x286686a6d53d085d60793a0815cc1b77c61ea45fc4451e7b99e9c8e6bc80dda8, + 0x1609e1fceea6ca88af1bc5075582363ff305d5f39683e70710f2f85501f4ef87, + 0x124f27013e00d9b8e11f6550ccbd6a2b9426da5f482ae5746601d82fbabad65a, + 0x2c47c743ff1069ae71b811ee87050e9e176a0461d8f6e0472af4a7d8328071bf, + 0x11a058b976dc5fb8424c68192aecab8f56b683f5eaf1559420349281d849d746, + 0x2222ec9d6eb62f5f431eb27a65f792b19817580562d8482027c7e84dbee5d7a, + 0xf866b167acb845b0905fc05dcf985849cc7b32a76c532fe2774353ea37f1fff, + 0x7197c02fc0c5f1e13bcd825e1f0df47111d16be06e4f90e1ce2452ed2758089, + 0x99aaa6bef62d6b1f3098bd34ec2916caada19756bfa2dd222cad7fc9b296c66, + 0x1a210aae2dc13bd0bf76b45124f771c486cd2c4ded5f125600ec961e3eff5d16, + 0x4ae93e4ec96ef4a97132edc6219ee43d41d3d3820331152a83374b363cefc61, + 0x2140d4f69e842e9257960fa14aa526f36d6b3204952c5763551600a17e9c5c06, + 0x16f77df72961ff15724b2cac0f79106cc9bdb2b3d25534263883e2e379722303, + 0x2a679813106d2d1a88e194dd55641143a5aebcc2204fb4e8f2cbb40f637e506, + 0x12582d2bfe22fab8079bbfcd7bffcfdfa6a33221fefe31e74edadd5e0e58a361, + 0x390e71fefb45b223ab77d04c90727eb97540b7d3d9ca70798bf3b3f97d91f21, + 0x26b440f48d1c54c8300aaa49b9ab8afe622d6f7579857ff986966832584f82d5, + 0x1dea175296f5bb238d04bdb371b31bdfe62974b0a219f55be2c3e644e82b5bfd, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0xe0e6eeab1dade829f7d80aa510ed423c86bdac7b39dc5fef6df9b6932cc812a, + 0x2cebbd5b0d62b44d3f06728f5db838c617d933c08491c23b707220a2d6060af3, + 0x2dc31eb7528e36ab16fe4e845b1858b44b7f4ebcff8c5e2916b5dbc93aada42a, + 0x1eb3bec02ab6b2a2977c89984273b17a0156202f622edd7adf787246ccc75f2c, + 0x220f79359bc26509ccbbfc429980c2e65b195b3c8b0695c8765057a2d025a67e, + 0x1590491b1dbde002f869c666a1f9feb983770740ede60e726926dfff31f24806, + 0x2feea161ac374df1bd1e90c3d84f0bccc39efcfa6b34e12dae7ddcd0b3d7257b, + 0x1a29866fc7a388cbc6c3c93ff3eb7f37e1c5e83659b05b0522bac1dcb33534d8, + 0xb8199ba3edbfd7da088f17687da77fdbcce7f4730915cd9f18aa86cd03574f6, + 0x2791b7c58a031d038d076f7d6ac43730933a76ef48f203fe92400d60b98d6a2d, + 0x2f454625556eacc7f31439c8f2b0ef06ff37ed616f19533f9266f28ca846019f, + 0x249369afe3c0b2111d448303abcbc18110aed1a1a4456e4b3bda7e8e2dbefc7e, + 0x12edc078ee15bebc5ad4509f3d44d7c25607fbd61e9d464d84ba3223582de54a, + 0x22580da134a629da679be562a7a84163a1565af42558a04c64579d98bba260fc, + 0x1dda309f47e45f9a6cc38c7ec04588c51a650c8f0f101044ad6c0b14a5b0e6e9, + 0x2ad483577232eb393cb943dcde6c616285468d4b5af36779d86bd789c499482c, + 0x28ebef81b1b34667338b9828e4858f956349d34cc99584e1622e6e676c221847, + 0x1352a39d4ec27f0e72f991c448a1511e1e7ecc4f4e76b705ff2551f2cd17233f, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0x2697ec9fcc93302d5f66b3e1c1ad9b203521f05ba99903596fcdb8fb70e4cef, + 0x957519127bd1afa0826384ece846813066831571e2aaacca4494fbb2a628c48, + 0x1d8a3eb38e9a520787f7b37c59fd309e3ecf19a45e4e4855b53dc670de8d395, + 0x13ca248a44825ad1fd500351378a1c873fcbf6fa6aa3da48c274d1227afc90eb, + 0xde6ab6ae985160148e09d5d5b35acc7b0f61cdd119ca66ba72a11c89ffb99ae, + 0x6177434dff8487f01d4e7fe5dc1f5963020409384269ba24b5751da9470fd57, + 0x195ff62cbbd66aa75406290ea773f0e6ffecc1fb8be9b6313bd30a4e0626b6e5, + 0x17ca97378ab5b95fd548bdcf531da28e4336edffda8d3c5adbed45b7f224a04, + 0x5b258f2284fff0798c69fe24b70f96038cef3a3e7bee367a51a7e62907669dc, + 0x20a38dbc01d5a38c6908056f5c4862c351754fae0750094c93cf54bdcfe75b25, + 0x27649f4bceebf6d71f6581d40e0407b020dc73ec56bf16748c61854c6afc6c84, + 0x12eba7df6b9e4a5a1b7b92bfd51d12e756831af7133a79a622338cc53e19fd5f, + 0x8487f84ccd636bfd508b5584d1cdbf24cc1605c779e5300d4328bfcd4dd6db1, + 0xe780d26ee909fc75487670a4cc043740af57e89d045b69ee6babd8089746bb3, + 0xa58128a2fdbf500e89c8b81a8b883bb5004b4b29507158b7947178b58421d30, + 0xb680246f8aeb38b7e4eef807ecb493c3aabad1d705435fa2bb37cedd04e9695, + 0x2909a2616f3a24ab48ad9f50e4f18c75bee2c2f434bcba5ce605c1dab5721877, + 0x143f55ba8ee25793ded43c6f14c92025153c79c964b44b35c886af59bcfac0a3, + 0xb1e797eee3f15b88ce3a1fafec88da1d6329ac3c34712db570de886cf569098, + 0x216f405b93971c6d85d700b4d991a983737006cc1099f0cc1c6c98a366d5e28a, + 0xefb44ff1e32edd4f8db74ae8764f6493bb0f76744f41f2f1f35205975b49020, + 0x125e52e4d58e859809ae43a4865b821c65e630a0de0a2f4cfd5188ce3cfa93f1, + 0x4c652e865b682c60c57f60bd33a174e9b9b22b52a1d47aac4aa084b1174b929, + 0x9cad80a5de2e6e280dd9b65d56860754dce0ab2becfa07b30853a32af5b011b, + 0x81544e3cace3761ab3563b6666160aec7a52d7331dcfb34e7b035d46d9aa6db, + 0x29c9f89966182d3c7c4bdb1c751fabf9dec6ca6fd0f3d2c4b2651fcd35916a67, + 0x25ae65ab6ad76f18d3423dd2829bc059e43251ca5491c2e11c04e3e241db0e5e, + 0x1821e88b8cdb1686c33ad7c1dcd41c61f47a6435beb00bd8d68644b930e7c317, + 0x1abb95b6e33243a050e563b5c4fd059de5513ec28994a6f60e57c98d3bc8f586, + 0x110d213a836478aa301bc1fd4edd388507d87745b3abfba5bf282afd21f7242a, + 0x18edb2d105bb53b768ae0137850dc2d2bf6d1303a1f8ee4aadf76d8f81990588, + 0x1e53e92df6c53ecec4c0de5b07dc4c9a0c5545f2abcc1fabf4ccb84a0a6e2c27, + 0x10fcb817e10f69f7074e64c393b807cdddf33c84a8b5cfe33f44b73fe18c0e36, + 0x2b1d8c11fc652c593543b6f9800bb7d0c9371dedb96f08bbbccffdc6cc44db98, + 0x19f473e40c05676d5f8d51e11336e9c65cb32828c397cc8125f1dc667b6cadf7, + 0xfcf3a4d9c6c3392de1bdfe25cfb86817ecb80c51be17d47f79750201f1fcd01, + 0x23b02d00fe2634889673a7d04736fe15b9f62652b1c0626a19af8d6085d70822 + ] ) } + // noir-fmt:ignore -pub fn x5_11_config() -> PoseidonConfig<814, 121> { +pub fn x5_11_config() -> PoseidonConfig<11, 154, 1386> { config( 11, 8, 66, alpha(), - [3312280834382673867321630616941760639861515464094877629805120494360011490649,2977163727414618213643725802224710174200189681501907689708278449275625624600,17077799405481633745546679084486353025600250694578521370656758513725453934742,16210306379465933080277173890273457210762404430253284947889895341785601089390,12306944281360832043572721821716739944034354411349456264300159795863030116042,18510116198433364516004461541873904955505055486081639325191415467980353992665,20171004681243290383397478639749648403640483231061520437292129889020927831789,14216817867363924461443287436236130110420963767734530602158091056747850914504,1744244489393376249430799522637230427855625055124494576876957852023791759325,7129585843913921821110812028399979173266826966429993304814409727296136874103,13988404968409685403326663187671698975733642730286219911002602918437679901860,16920638563061193407835052036305459051417920006020130846290964059193276218943,13427470979587753937642822251845898994765547507421045262408080469011197338416,4951343674183369875263494313821909834781608226183187917185914650592996842297,8735432128376864913532575297691608527208524295369583136876379560735670033436,11506191123509320764309490571835590914265043835723578099434891464809664894670,11860937155601787389575216601739962955686948385964703064981923542694893487713,10828014814384016644406621862814561467981545748254521286078083584574739936124,4776443388323724363690349417451836132533385226194261923508005690866227183177,16639991477904781874568583121789695884424899367435699700192357030587346907362,63646460855616590932366082663720069120195784636826940928051354727568777173,13872046592464170980392921000435473279488582870563366687909512908597101541579,2903974073963148433036990643522953333905364588702098342158750794553468542208,13972003294927197976860685316247379324920372226280483226377669417062686947906,13868504415208879955736997036981136359599594082926486546672963310629609974499,8628454286960990606041697926325623221475249983044062173729208432417417750989,11883151436851199698252725037318235080760967011947670552161788839027156740653,12343286145222861673187914724623142745362406729785896500578210646320713733295,13240444180513188371213070455300718988708567038226911680564203350475184135088,17225520781620743741263824011599257737446498734177523099795883619924078366351,19655364901125310778629982245392767297984820167114789563931170716695750865678,10695212283696096281132213692300627346215324066996398339089365835910730561368,17455827037964560948521638828961298975187156274841334841074216120311558804710,4382628454630801450077593442523632674983545561122254229775876033334437860489,2989679808908579687765205532943224072820070594304724633625888454150084631070,11805110513334566809098991762079653200819786354513225301120697798603509678793,11155601993809199490094826448585668454159517005968097566996288487138255635079,20815808565222781796761554019974947099963702926722486604443826341123930622896,13761986205307878615460321377264044874010177269812603883540272922422883198979,4128370443753246025606114169149035926146394950057754901868026654335917771101,9124459754124711043815747649012164723935008821275709951889811488049411892152,9090302853448501945809598864330384875455576758214379286451409039855851539841,2611158043123761410817152601927516372222739024190920897371539155273224585905,7810155525349201315441227323507184944737106980192978514457375337581213081055,15249792920950763850993517571920601821568311809174912509031437118050063777525,9921562618684201533699293485620188871082795988970107962425978745591461148033,5414565587238798987874533039507833069864773781235217517734130524969939419113,11085088558016600803149927568829483866020077054827488081829062938808919799801,14625818170426402577283649455001357862456467374537021301451880577607106726350,11633423263664104506250995123678976351167359685182986641330218055115412525059,850899676511673590463501492472742017261347013078251845952824541653369171366,1151196396804070641219917031443763313740170846357000808196046482153806050391,14335865562369989392722415692597018596062508514718062574213639729550753584518,16165235837546690396792041022833296046736592940683337326949013823518030323769,6408098377682813619850142098164780329355428625834955152400958576961120931380,21423078154100258346688828020904418548554497199114189102725137286930868022538,21410217312460027364452766052404349950133415202888862471159726884511205456308,11096458349387432633781125315606380225216758142658673665437375204143306261827,8325016245207932555950059013310928498109578689420634828690059159861280125058,19120379171572846193451984132488836287003157955913585086569467602620121544962,15548527549295346334479152412121638073047322389003226521019746206475690857238,18510388922178653264949279980605433471616208226685385338922150015851847524587,10348792093961922144290405029634579505420677504732581441616360506905620826544,15620530873228503134208333316448182712901874887467615537478242394290577386453,20675095206674416295505702734315255961699360732886837937979451051773488542601,21623072135556656816074223163769126264910877148099315666172910436076676028248,20081866552983231525843337497912436927329172443916196026679813450860013966767,18951602909834406133815764463249536936478826139929746486734639774975812472830,2378298801465585253495854322066504889300467395616155363977621341822205588163,7488881447347091058309495011922138185162376888083687541108039236558708660027,7225960736862847948475548065508931552528126330579521291190635548005260333390,2970482373109443685421063487292183827150496377598629996362474558885993864176,21734396161383902760672518999845141937065773419899625136190973118533490737305,18986003927424880427453510819113519633513383085919786483726156674699889468820,9438591792749742425198760386567115998731905494024392289196006582112950891516,1973470346155075248881651300830631935042830364217214073906277058522882105581,13791817954605171888781711015587425735543149752618332811612012047724803625120,19907506629242812934309078271817109951335091294976452370249234742626462372763,7913144809845970358468253448033359382532594356254540499933138806226450398795,18786719915196826164016145948631708915544945593653634575689240810328854731069,6216910690440344513687669938632060553287695043116654216600911463719413604341,13963849909448408572632889978998938642084255012365277702934245702305832007005,15044749345099947962217476120263824356898437745229321420257770262954985403569,16364542436173489908162544844694842746117292595057249540926274681176755002520,18582462045999492294572047486602601352613220856614634390669602502489215736186,17106926147340558311732938581031578597532846523271406141897942990261560966411,21322204968737434192679865858477095835509790782891920152044718985713652659654,5180799590809942717590072710973007480225145652031514943521639316776384894144,17327427769240537767056224186269899694170666500703858813203303301835294225360,12795226231932513901983143961810913124288321956641191561823103283353203953207,21372571405151778511626450096485639101933984498294796899325401511071517993005,17332300051629640554924347563178488077648079908152291094969979591786473880576,15196566643676483159109284476812079407469293035334983717971092729005139246767,11231435533605861369104078150337976075098864909987541459896164149690464379912,2542242881481757350297627187544723135156543853134475677976341602496676452300,8414397814915895101029770303847330205837773505982623383796193602695811122514,20884120591077768210550361293303217187539921930869577755703150175746557517590,890887689926165781226591337399563217015154445631688026491595317246205069769,7911456647213080390137926613780820211986390960677915664339039845274033704843,8086506254215085366863905182926378819432294332631815038288539116592866850975,17073560037383161517623747613125771654997798954263090273202401066518468858416,7837662874931236958961077774488634261606966280628598881837875736120392183663,1858593536177571875355498014960393860692560832490490994119420708212532861823,2029815832061982114925482969267067531992443107339599745974909462412297854269,9638056659007828434670080110322180928336402529095853481855440674860675897358,12340090961747329883452841216385303705169146011720720105809463143491658552866,8529510825845236935037301291679257193837435275552609577171369718448324660013,4191225223853834143599110761318464286196261585898512902425773974473427757456,21023319679135760820789157052868478773370737850886002789313940767424256194356,2142526213326613906831098262446296658577569180284637200640763867788179991570,4585042017455545746057351957720948202590802829528217263388726369695890670411,10010708638531752335740573636867640657039858389864446260449096531856416238708,12350783923218275606957028867683130968505845112714635024839732952215498877130,11964414264447046767815837108295373861475122940092369903025175128013924386713,18615506936496648840383399989920850970951406181285583088268789582149764054418,14310480127014971068920522498055725465578544829224822580493909725079522528728,19209887743481507043830894286806384055543596834772181434542567255388724841969,9558553005299269735641084020216560749888705968385627813150807919487080187993,16359179198438658598155755638987769554841536772865629517841526255130745409879,13009386603860183254204895522650012288119732961876401784040013994677688723325,16165167702867558446013999607792716532235725666199142971707303433269257270111,9526255138490973975321568846030367381138407886665647949792126204681244064012,11173959697998471600463637717719289778917744248391051771189332133876606070906,8924806383303834750473706479936998674798746387089627706877519918521882863256,12086306023907343271920056592137012844278234154616893254064962297944646888123,20523426725749375175935122656912302902564898343946638208821839160006976692150,5207650950010803883388912523741229153368067016192964642079270816449299041225,1323145474328028634780912405048390126320417262412962953050466352509016682042,15985641921260285694054233699922160344414776687043687582488491933807565444789,13031771899737217701535545098380455304311851135903656399978477292561795000214,12687226379083740035799525440904048416465917656850081330730343990236073218003,5180214195408850700722613770944601169370584228844657891855699394648642429923,1934847650429153525882808430984088614158092322287601778579498068360011630130,13221691213669397834454903625729859574410480120034103769424898865047475910400,7358428584159841472154153892839275459119229492180053472830555381908577651936,10890590867941343184378544765218808644776443230231834463183835780142311216436,18106794932751537043075991633023418950145862470753313409722049187095789146702,20653121417027117499755994750040261936029675942959877982604976723194002882577,14917693547715740204091617501230563717468258023142717832164274356453628117609,12588115399854852983923905079011727575933343603816172388719899888494451203866,8737187804839661132607601320524529444256555649101505512380882940221377341037,20181178129036534248081631452735124104458169744675071995191727629040780050092,11847774883596070919125373409969812806188814542338127843683622869859801757028,11792352762436629909341171173296810156800556812208317414203786807634354583560,5039046929001603921830951923781308597413960825857893817665425268295870771062,12894400705986579725245788498699203221654445738734999525700614560206785491732,791109735149055364851227398853119460170782218988367975658618461497391330160,9962476109282060862882002156903460806939219308562214446822701651882476052460,1691961422009775486402337895262889415967004356867228407841177856000156435254,13137802539241815005932694907183711832661205367415214501122657136334369092290,14887252261014844625921142022701177088174316290502741584519763408145964517832,4710184813279024135486906523528903891606006797755655291767343324947631364837,3801875732725114698561125696836343357073399124260852478317754268545097096329,9198233237012512530002016044631468704269680036230256629514440524866699707396,19696310211066978020836317292330659233588020682368119069383469865122133603780,3893729283153055478198590025767324126269879907832064182575052081004216821718,17970322286541481482483545514302125656124172449128411566036569217140609597331,3173691464765770821621367532348960211199783691357143005417355252781889173280,2243542900289123996173306626857758207765925487218044091235839910321809834188,9813067765525696381929832954440764980538359181380263390331469145209686852182,7510903347384066721813722580189668539045635640361656120910145998846374499699,6798424040308056706713925899327404372610976624998869962003671422212921682045,13151104198292309578579089832681402880200764912297978086539824832412224275732,2808835590734075710953411057250272995919027932824027538775542577464926767888,12588027297759258617444062604210692398005597744782878589643963326768133974361,20852428689501418456174033597851660248293428726014401905473174242849532966301,21296758342898944987847487225137782473520558597036376704831839057822676021941,17749269130031982625604134600446353874123371420684509963863640790293640598822,12696062143950532198094822890688877675740383270827145944853466311043725527586,10234631072965977425954576972633890272283449053659669736631819751429358646105,15090656934406651728161310654614148547687401766770336347796859883364028754099,20297283938807526130287519089364625872430415084303524848853727877999978340129,4196012712072569404315829685460688625941300450108222372646584487742105064258,7048902004425912498834833883033670218379565315927717075817051690008258707008,10997088676112427186865690409423506551772833502185768664867716439827194601092,16660341545280246485425051709291678711850828822636537086457121822086705580853,7507040282824500274626435275567162035280839409294222666356976034789594111255,16582934771732736721752353176711248084060824111646755305570354937871610952840,8438441158635690733311342509710555256926785449251473129940736660330253698675,5997879363655967621652122271982901641685668225243330913415373444659935275798,377781155818540738714095913828188470350179572448699653767572496979822660266,21256042944489939677834126729197446597005830228623173527229465226360970832340,13462424045682641929202812263623136219335301688716109209361496824976128063539,16369985325316675741289392258637854017776166143141100299636544614904713590628,19352389303901189710313048379405187204819083083443266317372096723889889111665,10276552469336314142974101263431204498273961662600910736694134016860746072245,18939965576088516958025629296747895354615121399053610843001474455787438484084,16990956322664851054201977827659189601868639970054898553161570861097544812211,9274107214677498542007885890977699632511964198928324688228114708372115109190,19938102848869576488504727710754065647382136279175127752338128473551869244856,10947279549049485525804912961584261533182913140524900494781425525696586998449,17561385783620224695956276284426542193322408499898012489406312644517964425011,18549237431132768472559432396178388563409301393950605704070488347475233640622,4658944912168763919889884489643908669977608714692544551960581141528777169667,14358732577825715965736448712278683090180078342840106686279626250756225140484,12281258853616996819181958497578187729715864708853144319900642420503103456870,4069586715276899433893814672543891090785738315323966746105563017207510306537,15392338154382717986608388646339008932890583126043490476751054331156284554276,4517279215584833397018875849825808766631742728356316383241841280072723947253,11495036315995422771228762992950108862694073551665420165823433137577472792783,3488400840286926839516544735442894876148193865245875295688572119503866691461,4483680161275568275540790250446502401130629200290761781427443716038558729253,3942379126490099533582685851970104926928015397351808560877929535138811915511,11401623410099323944960285754389435394954200879740972352984594598244147798394,1704354226179051409424294551695786920602664449209459493691051505451583669264,6126483205301561395856828080510799275633402498512671992649940369928504550860,13606061849345999397793916269931170782757704442972401347887622528829626440142,15164492401059698496285802476110470458129619713288710918549993367398699891422,3351459252264231792942138342057542378418534651418845818443384064630601195925,2825813294993932054460723098369264495005871082754465730530978747926493034970,10630213694333677464069113775948160876773011480314305970870772509710784295967,17166444840808098079862920467594387590120730690478215313452389257289409232274,15584725536763467888732670366582920601197464509911998898151204840990765872853,3842723796922381697995350228115144219456021393259361082360164730224542750465,4831891679443026612628331848829793784542170442278947325598774522135713804734,7600866468317146506151393588648544489445105617254544624521183070936649742997,10583687645778325936823793169279337717905917984785560251868239070559362307278,6634607933824414124502549710741812867975263049249231353927669720791801705509,21200609344869125199593456019818101515444150712862469998882355110348140005358,14361714336789127058022203168794208348007919167174968797533361168719704534209,1575806469795254200103212820564180016945577757735332906646132503588215912546,10628306906313535336091114056786842183955113155572070406112143573768388478883,3089301712473516586340147971264840334080312453733093398291612940108596635146,8645795529068430110488497380845362622141451911891312096721911200350500642213,16022924422796267113820566797422451700895182144910797483992348492987850640540,21668559624091676943635408329170173151410363888407430983622558174006481336306,2072754212505196807037151376956574080111414803663052483852517767215769333105,344312312360359816789223515659978323664333965848417356296539814750513103748,8220091259162471818305840126401210949950597324344081712931466340258084434570,8081153019090920515448830088459971939645826679918559179389404338475619307845,21449241241855558649730447089457892378091011965030006823417837265982774602267,6067510299282418337933484892144351034696356612154920492037935939636907603847,21026143172839641048848076059364862575379425612028621103404211601411048352556,6070438567473697541030303531314185338530006003062193748841965554522662407077,8255130291759907832990229603685682560848952190335394603030993899908706198932,9546680581091867708464426246566048171085730057856647964775027268282058986619,19031748019605060953238957886441808197649034817040423262874632275713470713752,17096522586030137478189913833428299115382271406265963567569748424828047092166,14391874539708946761001075594593462740437739522325069415219274013650732876769,5044944855410335767979170189040984719402886766879289090117403978287180516155,12039442478120524220891851909305716836138223152615593874775855237995395028479,3523930243951081542915282337519662387190599423550808129910485998252637662407,21645562630446380089971004272761942543158290220498842219097308729146973947053,9635476273420949200636403482900193969961822409725076345852310152023632001652,20108896868320980092863545615065555118659548096203643467891646750271137801454,9185755445384903374596265352827852278482253313517817304360514098507824628136,15729448650969486701474329849747687235995473855623732466626603841221282908291,17997496197003273211403721001065741564292124821674411166555153239941325690779,1543484160386036195130212436149054066156454121707864502325718576708010327712,16363634132599571248968010449034783328746466576733841612125967259037812456762,11430550344567145066773020651025090506980499195413761807852670685184554749682,6562474642758509619875130343887830140546824045253242049540363976665708088792,3689788469446976140319903688077885060368720863836266384022598571957269060684,946161443553297471232017467760713330784613638346698353392670707850882897488,17775152994890017803033120420023910950366134526347402563464114996856742054838,18013595561755224808896799093133992096629438550898908281663802197342115179235,19550347733494203322271272376490635125389454301454207200256111665786140278650,12387591141491143807678990173849961323772837586376210707337202980616282598236,15615445216195972598868146032329101929277001754848917412471279643674750521844,11157377570334948360516367332475698893237579888172217677485190937247699033770,7130958205578403403951515578418204249480908544151977781217247531796937245530,13077463747714835214281685128657845926832593706922024570198457201391820941874,20874866618752897980777992983172936086725928829995747401713185587049763764007,9529341163966534350579350780474173060797076273832542721772111561732792505333,11142469391388881243303156644691476683457853027534314004453288809998298235798,15759641247899199119184149872340402267600476479959598970774176792522105838715,4932052011278518183097054145820640615211087138945458940865038794988474891006,10432003521315545222242540576886148188507417318972677351911763831484066879233,17415623007807480250676335953220588929877876653555913668269587494499596716638,6058502442301803313347169632367675883843035525640290470399543491756905404121,4937981332834016148179351587580087161307555148093009345111656135565068163315,4767276541447291442260238717093680167532207332378535289044385385412677713720,3479278227276561004751092786681066281912177752486503430342235086646969267132,7943278285140068849348170498689330975011840215116541312829451500334428180149,17789865444817191695636689430256327163274376252861234888599341795716694863906,11313788642745794682263060233193097297009786646629777858110154245289610960322,15451318802981646436556355654707114069777551322432702430595933898879175343955,7517270022604650172540378758621070031306040808100514057036893386092388842581,10009597627594120061689516706238257978394705225993629762944338270984243419952,16287228641302237661911798504390175297327206600486567815634358152959586818336,16488249714776419229986970659608164306511103745532215897060984940903927940510,13354728687549843942265910857129412843774195483459170542959107134210371522923,5514821690255816781301952402733589181643174815400146100135235253605240813486,5770103106430309708547950317514210165673407448643264387718101428086149468878,2694023365380190286709306630457152471177911482921639231487592222438630988204,2596360308486910596331175398746479488324950265788021808703834738076552537175,9039714509260386661160667890165090643713802650277924766536703740888044388658,9604908742305952316295642934650340892998619318487917447839433792965436657411,10397877232904834686750242142278095498016920001087513253065011131758634311960,9647356378465005298504489726754445992380752731297711041297431711301119823740,2901124847048448064485279495316677205686659456282057720583010224075223188929,19604711253175713682339631659824057587938105276478055043815802354580551412854,13814073762260094871340458282144499467492241477826265605381954643255652812563,19191277082146641271114112092268339387374938745710902056016346575725741574791,4351438127825195342433511764688522108908810411430938576079426214421798123584,13791103210113222833666019051739255444684344392875106989928046003279497788407,21004705702783423413965111534445421935934565517891538415275359891592731977145,2271618466337144497382665490697115072125990892802659816927722507215828359501,17558902460062424775395394774553055038697408789830072471787389990226026812332,19541727150539905151936633341362726755459275099586077305409909896489919664394,13692791587272861333747931194991249996571271400946738920492512367046518055252,16261859926552105019169611795692937520291616941485096436900016176047007140288,13364750885171681175943985569408970262762845797040643237076315743322239541667,13621972138767941419375174302334978784396954063748685093059444353200957635883,7816366958996751828525267034982378444982423551198678280151852851213963203655,5387588357364980194077356588147257085032575072648295273044945567343418708153,5561769804258805723102666784326040807434856561620360208220095378441903055863,2759015372384926293713393955452664141507032820282479368223024343744582995438,13981134543106614704319578938205751472742054796552637642168049339888724312989,7990257879146478669584929211133379459065259065980981194790047745364505663434,11876127927930413842997415069288338406075999315865409152476435081888707100248,16570551097531678234333612414250188586376313376162262758608423816369347322204,2912142129158840181609698148893520848427743435752721748118484524307819669362,21302711682094568025057587941584825132522581272692339045586256377620698610739,12312191496853376716581371884132892074646637957572159612619070514615509157537,6766172753918389200603997763713298721859536050788836585740520353915599111166,11495484070470791342676704007304510997655718568304345126153023374072812971624,20811664890504244597768955277493527673608205732118233091518542968150115526854,16063703627762167667966504135478113457485558849729490090362731172389730931393,14866560644094965611504947304610358591133796414154206860995591970456047599477,14070826318654672995642970624813758954945583937085129314124463556918282721543,2479865882631638665546581282869746245766113042059506929860680221143260292935,17398990555602339276684995684280302899074008602689308101178965669933564447317,608876042484390223586509032355843816374709085426455763238940304845396291392,19093816648588316664468783915406437520968219066632631005915358745999525844761,6752057404464894771427129594636749868828376343179986455821808045648379935245,19888182199106435309043037013966294783272588579928340631894231065863897158437,10082296017960550499269875102368612265371627577709879253045116718197037435449,14616172738414901831631177911088055616005574740810051337096702495520738285374,14075121030661423148825920501776601474873747801291899275268094618775991305078,186569155903133115291205664388893859453551519692185893083420327670792162388,21299949831814715974370318270705239305629929085336938013302553408219032200083,10073139629403946009284887013173459030563893496973388848686052378045073830551,1412198475257996126786641438141729921783447169582336707894995512036569315500,7779964092821851708726534513875342218194584080198381624983100710844846404634,948257338952437735532120031007610523249359469819114853137850805544224196883,21258332661476723168534084283213459804574003007208501208541743948207937371185,3571248067320885077052671052657329120832155265049255115581589211873377624342,18767668432875868101830472546043294158876614861521938962321471373462978174897,9300839292250613795491408219504842564421473000721822643979051375966405606193,7064697496603343927134791624768930499810256237088252983584462738613126284623,11853953981626198865163123682396255427116155876021473995289924391523536239496,19771876990095842377875081223218001588478929046615599374496234715810020326293,14316898881193279100266501073998404340884941240727243537292505454856307190130,14519359582636080510571261582400983934670011637905562203617314435861115398211,15526562931305845620715599917553561556373761549853248996847605985788604583130,13078262487107679022841832022599167182597313495640194703513299650288211974881,8245559318515118189428376002847388656528865763199194533482833563489439004385,14003329258302578586391126522614048791257224051921678844212914592624869865893,11725000422609501650997806599141176528384787601555518111375908215801780233121,16350891150329350826705554113837971740496662498788954571303936439413078899269,6411076187467760129645481080704474318810486795627076355267125729971512535475,21018151777353913573383620107187764987866574825379316352340980146357643078382,11358423056150266238825561031091840555431271536659827607676154506546242135862,19065833030377987569441381994102534825367123386452612836837050555888073644388,2562667974917478689245733861669928078902565222389031120733094553006681886960,3471326938285931978123873023764646019622642761349433536231294291602304868485,2563009390241284210001442885151389460822558817932742264596703331331069807625,1840397005312580276560341795534676176103474806443827954038672349702326279641,13608853165319143662474434916965520937512197511217746962619929048696566631710,19629513285164329969551640449451527909298649847319347893901982383162686335860,15394390010333989214892827255905093646577605209323130947826658910240751517983,12111906652703403073758441298171362667165880553934054594322507856217299245492,4297972575899320549167090598678621826992022863628750628394635867928789323371,13452780308396674980210210234355016032880538147426066947029982271570560372078,2831837563806484576977992168295535809035697292555489411927347217736327891352,16435334356674630023459784576727565801947528558756855054741604645713144334059,4127342592978010203327455190780821692230702238156658795505993209368069797198,19169399182658468533946629204100516992531108319585640665183465573285725904462,8598406387986750884545663645357594697293280337319305106433909682884489291980,13371924317816745712309163118606793190008424593275425616115063429517298127531,6966840677637301630181597160079353321163372268840965853806074036299182143344,7360050884120437815429010939441335996325758450523147733433611465713273074289,18472779235592140583651215638681270421642809888489121199352426980884551699243,20418315222771285674269327640703205319629639584244730201946908647328012868945,17026399731940643956418206353642733600139323525975091345342870617418039094945,12615211028716399762155462346481728092959316603121559521948867446476882144221,12396056279980752806946158389419170236239219009894918041607073720841998512650,3020267183116758520311575446823726815087071183512473845404855371056317502914,4656542918173262538192266136796850668036544742787442489947994092170369122585,6651580153776746866797134628474708113133308603326248742448594405127096716435,11937440848975251505322944134185172341897441221500443657141975704868428110206,1361826966800566560222081321267933925488529241685130208478269338961124266689,19943953771229014728170188452413560878330164558859793245021220185499985258316,5000555778712004519940673290591853777960346285299451454158729230859752281548,8421588432304272431559534311544652626307929129739056740355326524785204863675,20295164315900629557422352618552527295246432971816033569783057482727719683327,19373368537162638225474243050103347264636555313351270279300938524044041811781,19301584842175411162376576546656332386749822306022512981007234449440059593206,10803063363791701506227503212696578672701333662552932509544627248354076467851,21190447586310863247879892773912245039992873717104751727825265558975676297878,10001943442280168315414950100438358800275893831224620600570013850341287546634,11419108205602584425734602189435177828356990665164795815514509894518490834107,9176365528060199110731574560388345526295591893454204513780413140739307927521,14645264015971411259428809172021065485340465742768211283864072707152051283922,2059680394752128527783641175137415159902594391639901766513696812385555753758,1362210878544210374207986445190412893419873862912439530157828224644264948744,1767020623225215375042202191031932704135774649037849280381750341452687445659,12814227243430147774278313161816717185894261558098935373927981841389635793984,3650392274313221017884542662769899210301363377135174682150190146413571526895,8605030053804448166307797789010404548793085578661466947278557642849458591843,16243873345435203695859375103717652101719490281058055690129195139240095336348,18253688126813406708458581768662237883226849901952565733241285746065046225854,16894577548232574374120767026426945561995165201786189772245769116072691636300,6423863987901820348928069732046971656713531289251833729857903917381295249467,2313252375346549956530493743826026444705500798866360084159932659530274395286,14351648867218654569586186362113600409735374191851776253843321710353903071560,12748602702906129786642754668169435482057869301200357523545630557138115816573,9709541611470508424169916733595066328177420935464065317839768365879702321494,7178910033786777709713498702843323736165699178795466682345863412805925816311,3353312211975166615897632007255179570864390972587901806985844706830647691440,21333017166590824659869638126407263965780255207193356400088734092911593056348,5028007188794597820037691911407426228966175740057746443994889279713514676932,10712123321028508395224612143524241532236128389312765281020405990000255535908,9585591632158092894254183832493550005011787447364800638915694118244958639233,19409055735214428219964362626158681016506721676720000843605743187110212915626,7013515054956821958187738653419570061640238138610196975216698509582854871893,14195757172805460680435532998286722310304400118130745528870652671654335152142,21642947172805342858920270288264451136332732954445458690700494722054302963125,17447291201981220908729619112892222175870413627521563259423394750686485556049,7142752135376494645636618098683429493620847661912582079125447091506892873792,11965386305718013298615263282817897360134689279593443592649060011294217114060,3269287439460269094755519346810063037578116295811194645623863516503159243267,2159120529508493457616143785556394024190164584915596617279717229000244189542,13216089736556667969033672749174760723927614320685905176389819791237404133418,5739580235677403106179902507340026453834485061930671765794215270028117113169,10146496637166180435280660177294964473638207568055892239396905092844948797979,1559489237751880726567698923572583310388557924219345825351973445625480867548,2596197625765120503438747432434144655985802369868414306286213301002200644404,9161937832793127953923149604860857118908349157525975074572071369698144813595,6530106539927673920262526515085998672101393587740796643755609207665748320714,3454043461578374982297475090824066193432500488323777575207325753404726668622,3344507163548616813143529013320782527939556912905450999614978312225536850079,3495919320773160724078129285494188621289377270658655167666727615227933095154,5516726577701478990891722326081439827260225708304904918582005618283443949920,15205180713187999862939063125387810274995561110852513151225711366795547591281,6648123555675422871529580981673252698816139021904779960285680145979314385726,15841058754930028584592543963971426098015345537516384042315342065435733026794,11980445534925903182700789375967305825089780148976633769394511063611931605378,13752792603594569707463845404055123799321888887568435005345905056744143696677,451907199992567080921227130990235823262116394775607208182891587168397627680,18806959341268394516719451015233616843300011700855654586308376758853129828525,11666933396513215238559883168577675591860013867821037377342211197150469047378,18261858072527055096686249862512380033913481610225001662137639137871862029384,21560391742011390943072232187892257373961479111877969400490351307926336615662,21610883506787217615067001898587573081135488752397283684823910785658887961932,8408073424459585535553155824732179764716727837637392334926567945546036849813,15210371269884178529776581719481988665617111145372052101377092280056914506280,12126920168856651470145408021353708994570254510986190646194434994722466503351,5069682791790920726869832051575701989172948895827442056320603681340757243410,5206562653380935478898854557078389821615981777078527007269200218469247241072,20147037355698495391549064646435751868583938479186070809834102358533096530919,21648765692141622487379563405180427559394486974406039602691179361899957186441,20151743655500786952430656789085402151537047806266385436562459773879995501836,5934394754413383977455838937623522376367295023125030069688154658727645145368,12603931706566171371403975785994747990660901389421654410200684089833302667483,10026374951811566765702661526223829303823304592138671853309110795200798195351,20990348049520375634430049514368373247447730079841716683325070058824866344618,21619384435032220705428130345438986008128830023896849505537357845578039663569,13891656325513979012692764566925054630715484836057215275096343649598208636064,10516755320080836193722788097986010349704472844888704193817055904209452357159,1187924241706018031195408222997566778745910130631759501304388015015493122577,18176236836230977144874543476758297865658817104610686283126581582188371550406,12485836949850082215229286502965907740610097753180405472080386359153328488121,11294821091195763819640094447903397628795163768975434879119673473115769322204,15235618132532149904626305329048631193060570832794115447207190941624057752196,5247748280389397626917162873894276536157877881047135043409628106456158304439,12327729816009770868743571696284061855435639336028566901611215454206952326402,16602949418050455338609614423670909880567257158111141482461606053345944875474,19481131052077011331591495382924133179323957631986844309716638852480977994007,14534922095860994138017014871440884145230839148117198707882202478464336849118,14698138249781405938575978017673685687915842935570150501408655390412744761438,2268825110634009232539217412695133214837154986621027045784924577498202527005,48564023730318244345588908855562476416102457310638224830024196372769683274,13911429573364091016107598756829373924944177606409768266066645212252032518222,3072739629129037084628601278178937800555134277149245900071628775426363271424,17673164704069533606602950374212967524179027652656167791832581708629862878595,13337993423730131992645864661190106010697884214050744564788997133642079615746,10864361443255322638825945640705455870794346349925711501403405779308411872877,12776251935559898232336391171201768361485692108948381787636663233683642720570,5216617488642405414264845781989153364217494006051772154230377224854279460364,19003202417167005941636726827739223707886908723467287344441657245420838333458,1782933238160323149082341139973263731861637960761110984576354403382733192508,14049307335094461452125704957817909153045723261672970005965857346428556786126,602292860913070228058919352868668861608870961459967730841598276439118039884,4532222937868395031497077142687900610420285824272982687191592830322532698890,2099811981776987988652353966067242893298763890123265819355994207644365313244,14963517993601358850130080519783504904964131507655857293183966569857011289997,5628630657751613134050345890283140633799644494629647136869171968642164797575,20616991532748403949152312405329497795753361035307036075488592441729795933793,9449735601866166994904286297362590639752895462487835902681383517319419222042,4855933188947772127110139132590210785552455770275991391814399396690242166773,5236021116842873402180213939626155398638345682608182461380158609761274518585,8831771317829874397651604675303149337495578376535991692269465791612651585623,3088758799070584868972772977513492687395394215140736055156925465547111629717,9647320052871832007164877116869148540664111922421469306708391658695763892785,13710265959446629407575266748628250489155448638018691055085275421674700880156,3990937300186809757319839603902135620837406120640478356311388415953195593911,14183797850975043036582133930342253303942122026304366900989797745492038794070,7977072622674677196160507229659485240881624765782396719467815964585050639939,19241094982310069445586766283605264689470697759972104264399773392459234417767,1955047691838825101723033568109446280275825112435318858983042058841632309045,19123726709557210987172343550395139275104840920797922301604764165695899093438,11017985516143054945716095457545428692165844636350104202156363406141221710733,6698050162913212144220380056054973138261583127187888344395668170533632399574,9966258961247618428931643789269822918034016436345337589754558490493039380634,5992044103018260979899747087179477222620402658511576502983751749529532417546,4323136703775346257297028867845707816483717723305960372757928628051725499745,21794175040927871006132858751099842549067139289302899933403157116500725993565,4135205477235797120209733594064542822286242795709961420067213468324705376738,10502424667236605030274589825431626273558506810276755098371543260305259735173,14846816339594032738719600614652189538461600190221870378597670293625955865265,2524366986896165752091070306635323844562001546653320749202855717200081979142,20323646694453380576115350130108187509393437723558716335846490151009228206070,17922328316124774235198837264790120266787900323072144966876142176581863552114,1182636510606531787673615350114833983759075243161678674924493347851641505038,3207389967170019411093119580069334588690357331504170475184259410760933425232,8369192092815635351510306100580533943309224255100566350954698456188479225517,12030967886392195699293618525716046167148513246572831396936379799444387335164,14022141444250217995147289887822373716179013971005541169826207913322588624137,1819830254074794257713310243249746692467827341614315920377358118637602832394,5214222934428733796770137135908910242359102117443480657729178969918179851403,18138416073511031005117669443972799853597050093891426716335475360173308913456,15787040542336098200132680028140910620950068073851656692331927514281562129727,821824702031897351041935750619058900741428025283533564678462466715419856156,13945650681120508256113693182498673378848691411623235404408416652983710360306,21565424898814963463657730321537398782420569248706699928677873449861325896156,19609389297655053996872511820224772969554473578452634334180619061868015512289,11052162512235765382251445485034453773059444701618444976454738201341222665559,12166351899911550354968692629609980749815884172876848625284742219657445788950,9357004866878440721090407569238169828150449366762652916034388742054494762892,12114234396159313460221530030197986658691629189646106573755288837341527114909,20697910091918282046230152102481351960195609070206375824763685775389954486953,21217736707553075351032987119547432929010871168087324138739787787951139001106,17381364776399568820088774691862728632279841729367582228657079823795538435769,20943148878105082737615418415826125298002846495574584317442899738454169666093,7269215523851335046672197634746347471983448536436098948086942864058221294848,11453469784625194830295468663538063129244082440999065497133984430619118688913,21018146386490226380790917971415394820859127890200962707883416995754459780694,4499764602796942905287899120539899295087557389188509075023605344029409757976,6253534478331781543005728896589051616547370996281199587944537185086057029207,11552217017582571341399470106065323830802102428782340770897703340827468796773,10819374663920577173719455195284609222419659549106826920462161534187158953031,14349899656862395011953779288216924779057701185080247070042551534943737976358,909510146269051589147289065017979551607491214019225341737807929286505047312,7822991049400510485087251716608572124487352922137650148085367861004077510787,725869830997965165130427627260429551001667760503255008495920045139979612999,16876874328062330437058858063404447748425817762641981976045186363782457609729,5386742002628492275210178331450945300388007254427357938003565527570148075266,5628231453725040085705711150750978455046683883113398227942371706440013519778,5207331605257641510707403983352805778295440159078505882865873548456617745902,10535586157456772677635305329613970037048119551546559771279117980166707049697,10634858349767776643334691454267563140934605084766184133586786266071708634005,8194830686373761187394649827049013218313677678976649876752071409303459578949,7100588172111463994475475315895964854310052675103208262359133193362837864219,12698529806569743134165801249102690453926582725077752506169518961941228191732,3192504222109013167359339531059877081526474219178099463731713708944911915094,4863002263813052668246974534880517465192842993905851311847938713684622052826,5692128778265216733946522388190452257048514412064102477216511313048856040820,10126422206202050217110361146045359045967276838268265874082659894234609632351,5816818864633980489627669987512782856651289984181002178349070605011354887917,6571596820513333489228887403836877987952738840623146829273932098108053062770,14089943097204317257370418561461590134190932157472606744328891293369209454647,15650892875459028952140088123225234819706577582764200222337535746289113550733,15234537030902822319330116055095343429285315370864285347784850359841976501754,19442144493035982963093880999374393289974808397308087180018619507528159896278,4787721462177588970261549242306006751465139812381940463247588627972131957846,21188266388402646362923963971922131649215999518682418035026104849712460470697,7670120618673949888866627327541465118295930474243507723982310418317698793909,5278076033158881738611446681468941913572289692389442858337761263328869905538,6812114686357362596670812436414685361641526159356770435320544521002690748983,14512519858142345768369977582630083215640443350401036244408402584958380156234,2883669043634370578290606585906686768752718215322315377961330865510599230166,1390031372189262099215439174834826964629551818632345640955909690959488475368,2621604580741170950714666893803390793334876512814103152393976192943909783864,16238046050182542127054230631321316896861946156551854572617517416519877517341,17244586605437271554745538098470023522850216211045683035769492251097903894816,19367233841767536085266806989570452145418274769895229567119343509637411304432,60922694691641059020255299196606231058588207683679919735176896931621476211,11404572340596870708576661187798839793333697334049619025922813709736021654992,19297195320049214749532857744175644917624562154332216539771469808458364580570,20000477679980055675786972902810034261882771620364631737011618258163102706803,5145215345848317594229128468995966108988375785838942899274867896011577909800,12745405048448113216886186019434813760835051470566703617056298583393105029140,6134671602520394562619244398452258969460576801019889394876295515660617122846,4914589878992627637690178006894707570950584383330674027731006564533772285206,12220903700447451099363813812957915640017509928028867600267100643383476677026,11628588304761135026225316417404056298817057087404654319307918387873030085506,17423007615206678675839176821651284038190814226425327926691523730687305701329,8965704645750924279210398083172931641857031322145961884520939048845530423732,20213900813945518409362660921232075042618186257655700796304283970465683248159,14023473417795456589963878717505287517669917599805973068283274798230783465678,9113725901633633321816296721315176702107873006937820201651085782607150391484,548172112211359610960958872299753762974328909291797522208085351481742658142,21706861375052844683595820457538688901531393763031119579322611763049792865067,12400834297098033195346480176669546452877127463842848395269580039592533946307,18693408652472113120418656602007998722418946699666834214243410738193362834090,5734025542584829419095063290697837279993460564092839068131370421231150830964,18924630076511631254945042871273344212804227110396594419618744375738473997458,21814215076304113439159605823570645338718666334965210428557308969012775849083,15874497347478704100595228569012157674761828758432798819588001847304550645894,15630701992043410338260010633128892269216736379332650587736588580296378591400,21182316539430719202319661920312710080481096926576230463259085025268931402724,13427632056110349253603837202352903590918428276805663374267217475392463207302,10911219508671048309975190269088900191221091803425594935965400900508004506426,9158857576095512666804740759126852985161480036845995629848333137432364744220,3061727900948996735547324485012991687515955796128872254459502313385493651603,9484087600338383596528641950981362023967545451847364854943599173866192324557,15244438304843092101886329998640757457334825678432810119480500702489267475870,966872391220567196912397735096848312956568724961332613947113843660023937964,11463695793311663093741054432425795718511021724948561649345772770204331282701,4301779131461344863695073848029046722184482171568650483218315300688393400530,503085225024315480816360605760267420357374543116157267432728664696709665901,2152733644489285468694016160698899213530839938744988003049661235638107035210,15311799268435674361916200869320882308334015315600749428161144697607223747926,8821276262247279528293843357774532114304424863546634692022624148120506964899,15012215707563410212327951685975753138452396938302623171526151974041926043490,3832600555460338220245921307060619972944914111584149730708347861160918312276,4945512356937128186743764272299580525076021077689098424357488427223926571902,6352619611110096346414873193740535134097751304211531527845737802795592283759,10487432688972604512516548109465855881572886261854521534610720416206960307854,17622489873780167264774227253975567347204222125869234241462457566132215071928,7633353550826098030742486107449393642153730338494606903118637850284315354119,14024635247358847977026819464107185157647377185834445176147145227141238505750,3839080266490755896783758766005919524636645447105234209420661161997449147283,14295400414627547924873035695592309131547135626435254888679625991957098691157,9699346383521400413122931609905328425995515996718354291677850659748262244552,15892775179188924258683368801772704553840476123482448500492733919344870447160,20199645131225911044918007618559374867899861460760047877106143132248914945273,12001320852019564045161245401305456578767647373680507608908849898281736831048,14109337051994798438391426281455499687696832970217465295841248395157195678143,16327788711327335703187954019173408665382603544801329348791567767829649582022,14165345295389244679058422302892574411018017024852263235622041585515310700440,18098328140605761490641355018350075852862336947591383947449899194910504851997,17531934292095415392849417096338882004139134123682574245576387314018394586354,1733676683546726275638177172968959379163822515869952716090548401850898249951,15390925956113897743988821133394062442365524479421281886945584164621467664839,6308234777769318028945248133710542338224131559387923000379414195599812605031,18195940437872982705964842501287028751711989848794835251153117845868361639502,17490283477945958076039190253339223109810835246475119772790163703167194121322,15408396829836728115954873718864748500411741345264521674331031030247235075214,3551438511462216897614311415123740632223550882497302889988823516019801455881,1211190935634033568807015118513121103447278874630092924424376539010769615279,17406162668797550222384115208538224445727151774389004540678231208053715695274,20479453675762626017106163313206256229631927324901802475043478933123265498282,14782425647559744167182627327791886056751281195680302914811546501028210982186,925131908338441634745517290354664216337826881101842522634123686010539186420,8849707997196192490777875561563208206085973382242717199438345627124299133090,2076454320990941741925816538401596397546951763404696804371822796867698785368,17173134576726258494214130646402838956462459094351663199002055284799185636563,8278507153110957550422039807446721030659313329793830361362606551912544734153,21454855413436031867439010732150284197408206511012140387650556740240705522088,8938141846612216610282603832016394896549074914747256157702516831379429923666,3753004427655295864092888874901033504634515083469621309422669489429783662244,2366435134561993720630980767268361780485124472309182242565985427615594260755,16165357231356434631067514709216775568766632800191759830231349057343507534434,19619001519241758891959372143573350428188652312535228885075978087065138604446,18529730720102625006097708392875275467779439015225330756494090875760858662324,5652897308997297007169294392190006281027830654965418415676327691132517009477,13575260089385236342970650047136574844156206796954949409405285738862382638131,13051488122183433321152129519814259420249179451391427892934958106760313757814,16675947070785780493219656951197382898525312482169747446344506906972920892954,7175175603774065686796811506353067100604576034944842446058484596637779839013,1400986416499873501628131339252214540318552035055662222249409246587339999877,3464466866466806017745751012761954006390229805750136348643137486103734148919,18217858987033907489494644734206558680641423556261333390037659204834788684410,8406086726746620686898224574302006639796660679494669881199476338693847188630,17762341698784805474670945153199304225802481228485479435097247827908738620552,6223712186181276291315191942450380783893133091457934083606193355728586611122,4282900419919891825156385371067226030543529098387005106356966928605004273721,21245665052422749020204481966374990873300815343268950998971123603215733315757,6982432590923765268313576400153302843651774940912624901824133236148956994132,14604328114465343527250129263480156133215257207190011581958944554537477242146,4419171346687102376610201013900704798965178967312178557853149472731770706501,13245918223750947891398096117311260221538002135539665270124077712098715822692,3347693769680689230259648405537595614327886881079646330652620517715295020391,11097962153704048182055796266608903112109780112107618586656031611021161690259,103842991820173997936966388104541957651469231887516072360536421395334472158,10458487052445928020397135451416595147106158179032040258831628955988702925482,10900270612365580629478084761129851570116267768979394602611763172198923647648,9903203205178879991225339006690459919299342990467545909511182892622541268992,7206476963459461034052924246171589839665793743462578906114104789862742647145,6264046538214382166095990603552597379083154170591970728068583459736905241469,15208506074912456921421298757607137779904668310165212805848069781063650192568,14399898497646210477881830976333295219807765057833256267205543494652425724063,14270878504405431259159385066097540588788179903719271466546150744452837482681,2299469207691207005105135549235035285287116575059039549352935321891742095084,16821622844104951063765780536072686283845403348056960050391910562149383647957,9956020421344380373447956054462292461416421439742573500231969663699680679093,15930825774426452340437887971015387876460967360948156787859264923789690195070,10985728214199775151782154608793108221074450547445302100877022826701613291080,11760641126739413999815391346325702178866867588284525333479386263279622799779,12964764722311909921385583909124655151898642200440943348322605636391779313939,18379853927966213921019716164768637873544788239921704156188954474082485441441,15296912762863693782000299085702814599512114536531293086824435743573000852798,11055306663322542945964813101077231103838051414460193023274311763885249453027,8057951225246999526336336507654165264870114340865557474750852826611325059180,7217454204491887928591297314854022623729750971598154127245160014826014134117,14565102336180706753392276751790538414003260023904084675564779334184014612773,16932806574869520697162166869588187543526028859439455500295852309668070598166,9179898117866495045233038402762881324885778157159220317172535561846474551689,18779105085403868166483619694881906385652758088668461143173550878413116028260,11214136111470281555815079365242861297786837712776840366750250043823307862209,11442992999493383524983810131599863922453401327420664873617599429059754849857,16271323289864628346209913310699661044288655850612550590359075955707090062050,17108025350334840622180169650569770852833940341473970170517727066627050749958,13146248878892216294361188166665572028549000139712229260161108594416711673870,11427372820077962289622241022478467149286157602797953190515658164839928300751,893014835995617411380095483743111031917691099253220683676712243294883268295,8517095300100078150575343693630592663417209558229239005971749331683768522616,17927627171733468726764817859266182414919024487868681391571481635385817509424,2910874756516541331498135086483127887295864033618596807255973264881493597680,10351245804237587891981133156579115865490473264567370459691707360959684413970,12694211070090545997357986982035119982901819345677093614248046140600061957940,20283022323110075954579979019632104756139185475301167929737027848763705068147,15931844873010780159923673780071721836876296130477744289335217834580073984287,21827223850924748993974869213271539530659373002293617263857321497283795014386,2216130285102621170883691491664557599377015082391517585865064633069426967470,11373405503815639839270612384753272139664561558477978654573651197371057815151,12313875735580427829620793313088533328915412934622924938520740599744871213525,15142465061035421304605695594042142745567585293979295525147576522422528415408,19911123862342914329674984568751978176595422003509172434076759943963715219260,14262659769499978824697304563726231560538953195673261355416096174585413608681,14610683638141173050828300939153196590488444327501938863403192781649951814095,6637311287977459850936997036417480664822288091481538821362996372726159029429,15501657635921439788956110615190078759397404083654787694613599184616807587119,12415917438013473637314666005336278137449129158908612828862230927356476129214,3977073659694868689017260754925680384676839395821102222683036599314487912596,18021973030966989893231530982789547568199608264409750239459349680822956679629,4358661372125150502295103743733014495017362384424029473164385391234779773434,12150574573348685676904261170022340625206210894206500162919624199154445311926,19059564947466261856206182248882637129860510906425942015878496836349348075264,457803388293300831659933030795457353247367081441494540658944608302089214573,5212046878650303869536834084593989055518385481488493726863247051727387374999,10866963984944634834508529257930003255650324224099527428753028080514409460102,1567398629202166035061920213544077752133493577343656913517034032663760331227,1641623291671542299150077964313362112100008772415510478337935841080756871031,1814807183609065925468700221459835599229505862471630844515076416397596161921,18676591284813153230980779135662585498854259214169962891045023401932640144792,14582715392475730800118541203172619815507444658499922254753619352141615271717,5971201190012257917828174333108220091030383280212145099110362036705465802488,9745736062659480171553506036948675113562718355498342585124081392171087285152,20654605762814031873434196876396785695406369410937473580199071780191334325949,11844011087342569590330041590202444612516395732736950853259915342942395929104,12960729918447154570349545809398065983315955190065107446283057843674060399978,1912969365260456210218541172655492769437123937988143458973053151759348812779,6751278463897225433246228986310134589363747158535699169746372748837067912354,1405433090804402720301319240257714728362644500702704160642087476923303165683,17334203531491537592342457272578981899701055200802551766264091441355104806736,16575765689548766530893504204590870417122916172019674976779799591211403721688,12220976854598379181285138460526335801169364473128100040253401652070229420610,18565358629024373944198152078259356971563125515748886809957420832630624111647,18999218340435052500780578040305741910732238048488832712380773170203478504280,828469997232485965462944215365058139980461203417902215718115878220834198655,2385864265255813442011864217087321326832147642514277043179825610035123479208,11753087538734344167619786844012793078263845468062416000491296071906848786208,15297341509659920002867070368227904487875907462849401568145592054120947559782,17451904737564664855895845058410281315610351460549944647244100267528838462231,16288687708586503845827496209229686543350756101251970070831852982828263987682,17372190154611010904681208309570706747429785600046317069452832284803213135091,15112572862198958048036722322696004521384539985617885597335257056722713402392,3090030985871039557449539908126365491166718509536148045184016492804246563853,7579986120189318071341140006570025802626137718385790787108832330451957404666,4656625991418301006397045145531617124589866163929416672123076523538862286851,19496020801558863926434816068743011465607626373023757648812447085667986307007,13805329389975072362759970417944582121050551902725997016013251740633448473430,18188229086122124131780255528737492392822604407289151260248713532509782736083,14611835504502434276576475613524726992333885650957002636192032800434268523844,10917400920268125157880112072188560060076995206390296416305594303287585051306,13972231301490257961012583958703459454850999751676553092417436936263553366685,18328503113772388769765260234570641415081417900145352728842854263561232438288,237123037398988309289930744284813441581716633481073379308753775064025864085,1703922543704124573472350868371820728886443372137290454699485327716109471338,11303106151640297276547682977648977961130813769323129464984120148868796657869,780835119818217499025356174332702814577120774118181250962295467182217505278,7513776436281774240010548782707301011961852707217067098086617267751060890346,7053386733865795782344919942070418964042982090173077686333893187474076408826,15388377229685250353999590264475768848666849601695837177100149716633411294502,18619784384287698574679414094727959444475916860934398666937358687019863556637,6843956467116800550015577789758902600855297665349663446001269088726857226048,15027464760260005079316932218316611292633334115528481474392667994765319146064,3113497944921123135464097580210634621999169473508798646842600013742294203321,13922875552185745353363519166943408041900501129716418917715862175817917028807,6529143033058355347608548436453630783222625692384446386966623567146527415664,10224300829854530831381318053279338710395220281107133842738514322747972858570,20406735123273907201110501114056492687992916259913310564107896450511212255632,14266011897697023567365526625467367950062937074006135166584691625548787309637,6266823350995327247595338658995148275348018579417278062676982980758032485160,13382224019010393958018966744541120649420499028243672845532376433487586111361,17219221786488657036851893458562210759167416100910882352030211878162886142909,20162856829897101788693886235042939518715128237037117615656868509223185121680,19255871117980259796107225408238738190418971755264416661458453217281817348088,14978990393744959794726413403754476561984809686673856442658550453303982912228,19671827853594912540136789344716532059747421261482796306917878259275666282337,10732390517629598846596313835253769945253387192277550975463036830136687386844,17133415435299159639005309603217597288690767318016826234871049396559867937550,4238294829801619171082019239832000810131476156600856298143082034448277968560,7722327574874647121890494265704613777043492303801725732359520952354380593844,12398521387704975769381094211621106917110829744392349946808293674617176531795,11200776058775831613393435187103560072186926574904464246036376746754002391683,1438209332219971409989076556134294085612745796338690516891328286502107803440,2937570830929161760131625263024599999319751748792625900610926821498514203833,11043761204766219739712866580984621876221567501998807492499956572251345283273,17161703263657344245212174231645949667297741070344916641526821962829393621412,18619070492541478298708071132730313137437250499943292747935022132254737182602,8379242582671699656964937417808578910591927550726975853520669689659712748923,4461581878275014470922963327129159901508275066328903674248853463321568123734,8814779309876923204577653695802478749454337142645142889405691969158642344463,5916090197404556150255058868159426544438846565532168821258584401868379000295,13450130187167769463125976820336122102195298233114472585228206936434118870547,16312137321831916960674847439149202523298938366384118998520447019250845846949,3523905992883153108179926090860559860264215076129040324355490516029055984441,9941544263434232818617581658227915119072214833223636007382930887032695504069,5866421591020072450638507367259603444231034674337808358938713064987239652864], - [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] + [ + 0x752af3c6fdccaf3868276685f0a69b9749e1706a82917b64ec2ef847f804559, + 0x69503d417e25f4568c7858ba8334301c0fa19c1b348bc7e18a4c1ace1d15418, + 0x25c1b121f33f4cf7b308ec4630f27b603d22aa81ca3595e801c5fa7d9770a096, + 0x23d6b55145bdb32827c1456af4d7be4c2d213e825c1d2f0c9ff99b2273751f6e, + 0x1b357bce3ef3f2b76afc2b5804805adb14cf6bf37fe2357c79aa7d6b32acaeca, + 0x28ec5ac0881c1e6426ba499409894a6f3c276fe5689f2c35c9027e80944877d9, + 0x2c9862524ac8a07b47d211c9c504c8b0bd398d028acf690e4b8ed4005dd06eed, + 0x1f6e6f0ac4aeb7a52343f30418078b40644cd43e290da0baee92891c4c065ac8, + 0x3db3517e233f8a76d21b2fb23c85fa7cacc577769edea09aae39407b9af2fdd, + 0xfc333dca4183dab479c5962eb05ee4b79a8ac6e0cce9e9b0a2142247bfd0877, + 0x1eed281978a8395c04289b86197673b0f2b65e1a135264527e250a5cdf99aca4, + 0x2e370db23857de3689fc9b908bf45ad8f42da900fdb4cc94a7a416286555a7f5, + 0x109bb6e5e04c0eb5297130c6524097470f3375c12fc9092d21ed33400617a0a5, + 0x73f4a17d45ce4cb6f4db87d6f3f5f4f1650c618e403e1873ea3b8c4dc187cfb, + 0x1a3bcd45a2b1dfb8e75686d3651cace13e1a22f5d838cb4a61b17417665eecf0, + 0x27214751aa86fd2654ea05fd2611f0d907287433875a8b0c3eb4b22d24d73ab7, + 0x1c5463d40460415dc684ef2415ba66628b17ab5f9fbc9597ba65b74892d34401, + 0xf934ec1ecd7ad74de590817347658a22a783496bab9943ca1a3c604d4cb745e, + 0xec2ad1eca0b260c4c6573f2f3b506e946d2a82aa5f9e65c2fc4bf65d310b1d1, + 0x10403c6f930519af3177a82f2be1532e5758127ca9fc84c93c652279618acab6, + 0x12cb8319683971740fa81660831ab6dbd3d93c7bcd441a912810d963582bf346, + 0x2c7cbab33b6294f292ee0eb31d53daf2eb8494d96a81c0fdbd62ffc681e71302, + 0x19e16c1b9123bbbf8fade03b4a36c5df8580f8de0163679b1815dc90ec581bf2, + 0x2d2734fdaea6da570313df4a533c0049e44b72b64906ae9cdcb3c86708637a4, + 0xfed7ce5d50ca2d33d1adfa990161fc780cdc30c5bf2d588184a190f686567c6, + 0x2533b8b3df21fce8544a6e12fd4c3c1fa09d3e1f146ccfab52af1ea4d6ea361c, + 0x254a9b0da17f1d13495dfaf68cde98e224f80697a0c31b89af097f3cb270f277, + 0x52a196789e7e3c6a020a0d2f82c246a903ad7f8ce3cede8153db72ac41ce566, + 0x21df9d899981e100541aafa28753e763a4c5a2af9845b0e9b7c4ed1e7beee2c5, + 0x10e9254d95c04bf4988f6de51fb019c8a7c5a20168b6a59479355e880028c873, + 0x1872d404afb8424952958f29d07b60d9f868d5f26a4d260f843373b706c3e850, + 0x2f7fbbb32af67d88737201022b56a6df47d476dafa7b88784aa9ab73c57a6f9e, + 0x27b5ad383fc085d2c2639e80629d7086e4030ae8e08ebb403860b4eb2b4ac487, + 0x20a04ba73975ea1af86ea418e5b9fff424b93a3807ecc3aeccec77de9c1d5b1f, + 0x4d2735db418968e804766f579f2a4abf79deeb66240fb29907b034db93472e6, + 0x210ba11f3526101019b98aaf9492c04491eeda701ebac8c66c453503176fc0d5, + 0x598c75413f3f84338c4ddf176e856f6ced73ccac8d5bc8fc6f12d5f306ec8ec, + 0xf1a2d9fa8407e310c58af407bf730becd9192070d7aa4215379d1efd9e6d2ba, + 0xbaf577ac2621cabdcf7ffed4073e27d1f711f9eb5a9739c12bd6df07a3cf257, + 0x23ba3057e5d9f1429ec7848b893ab3b40161bdbc6387c958c5872b4491b366a, + 0x1b6010fd6990d3e4928fdff736fa857bd517e35935e54a1d6cadd941eadb8408, + 0x2943fdadb96607530cd9f1000db50da2fc5cb030b03985d1d3cb53dcd6937ae9, + 0x9375b98fdd737f277a2ec26a56d374658f448c690fc8e376e0f1012e4da40fb, + 0x1c124f9f3a2672361b19fabaf0f2e1158b313fa2374b72c370b4662bf96e8a26, + 0x10e282b93792c2a893c54294446a63bb36a5b3565aad7504499fc22ebcc58836, + 0x4bf8cd673199f41df6b67b76dc46cefb40971f0fdd5e1fa15ee1921ab5d8603, + 0x1410cbdc261964a2ad500e3b6eaeaa50ea8b119ea11666f6558f9b3d5855acf7, + 0x2b17833b6c99d8d44c68f1a662a47493daba582bc549c3cd8ce47d572ffc9137, + 0x1ac55a0f9d9d4983292eb30427f1ca01b861f17809f2fd94d3d89b2f72627ec0, + 0xa5efc41de76c914410e9147e5e67f89c7792b20285cd0d15a1c1891e91ac293, + 0x1344b6db5439c46a22d144f4d5843e29c750b1acf7b0727106bfdb94cc023cf3, + 0x1a041839e844cdaa0f7c2a61ca9259e860599258495fb00d6a75b5c503e71977, + 0x2555c529d366e3d95899d9c4ad4c2d4ab284de4a45d6060ad91b8a8bc5fc24df, + 0x137894d2c7ff06b141e601c9a95f5664119ca32b55dc5e1667ba62524954a724, + 0x1f2ed1b26cfa389194477925f4dd3bcef79e89829c8c9645678343a13ab2f637, + 0x2072b0c4af46fd5d200122be5c5011f1bff2d44ab5d440ad946db4ba11b52350, + 0xcab3a8e77c43896efc4ab5bb12e3fd6d234a0dcb236c7c935c57a00338511ee, + 0x400e867efb3a8887126f96ca884358e969f14ba81be4df7668652e15a581cb7, + 0x594f14af7027250911a4b05478f659bab181ab426631fa4c369c361fef0e09d, + 0x171345094adedc87f3840f78d3f3ed67cef3b6a6a269b97198e012abf0ebb722, + 0x1fdbee4f85800afcffa10d76c25c01867b472d48da1296ecaab478190f81e242, + 0x1a37c8b010fe5a7f299fcf41738c50f5a904cab582e411ac14828e0c18ba8753, + 0x59cbe918d4cc5dcf2d3a31b3af2c2cc107b6cfb03b1be9a939a7f73c5075b8e, + 0x2f0054d719e7f0d3991e52178a020d3b7820a7f2a075695df201a5e292831b33, + 0xd3353ad739baccf5ca9a56840d99776b5a7fb60f9179dc15950c0639d18fb83, + 0x507a8c3d3f5f3965e2e9fe62fe9e824691cb53afd7430b625153661da3e94df, + 0x1eab1d2b44f79f50e2ba917a96b21934ebd43ef50caa5b21def5efd8c38d9174, + 0xfff97abc5a6318b03b46ea4361c8d29fd8a5a4dad51286897e77c2aba9f25ed, + 0x228907c146b4efa56af5b8f2e59beaa01741ab10f3287369efcd78e1b16ded07, + 0x183a209d14af4a1a9db0c647ad826fb75aa67506d03a50e6e937e3a4dcc2d0ce, + 0x17052b40860ecfd4bae684ae12271e93a32e1b703c3127d5d23558bd75496d2c, + 0x3a61810b60e019e3a5fb53fb055f81600c8f269b3c97fc228b373bc6a5e564d, + 0x296d0434d977a105b07f8e8d537a8381e885dcfe482c3ab773cf1c39b3bde3c9, + 0xbfac73b8e7f9882bf69125684ae20c7184882d3763ce87911dbc3eaecfe86c4, + 0x13900e213c48cdefe3e7090111aaf1c0873e21ba0f0b124daa1e9089677ea937, + 0x19f5725d859bd99469369d8a5b029401d90a4c7cf37267b4700ddcee31f78bef, + 0x10f8c20b30622bb769d902fec064d87fe8700497de4c3a32673414603f341f22, + 0x1a5d44a9d6eb166727f3bad1e4c9e4f20dd9e5c09b8ff1685813e84875f7c267, + 0x285812d1f7e9c5652ea549efde3426019405bb080408b01f51ff04af5ca4f7b9, + 0x17b5d657ca524c4fdcb6421bbf15dceaaec891e7a730177865542a3ec67644b4, + 0x1512120e54def6119fc731a80ebf8b9aa449a5e6a5654dcb16ee8781b55c40ef, + 0xce6fd9ff326d991817ed66f0fed93298dc8116c05f09e2144830c07afa25700, + 0x14c9e544ffe86f310c027522adca6e667dbf138a586e6fa425bf1f2b2114bf80, + 0x2e8ba8e57fe1c4ea06a941cdd2242c414fcc9a1e645b7e137ce61fc4456dfa25, + 0x1a1fb2e69ebf43dcb8ac7cf0e6856170be8c62ca1db0f77120d36aade9fae908, + 0x599e10ddc716d701d5857e23dec1130b5509c3913fffc727ce207783a2acca0, + 0x2908ace556ff1f368f843e0842ccd0dfaa42a34faf67e0b78de6c47de2b6a036, + 0x1e80d381cfe184b2f11fe38d64454a6292eff23f524d6fafae34ce150d1b8405, + 0x32c3b2a8872c39fb3edc92ef95e76fdb6381f829fbfcddef26004da5b5d720e, + 0xf058306e4f397b7b02a58ddae87d5165f21bb6109be64cd3175097f63d0d402, + 0x2a978242c551fa8626d0def5ee59675998dd8ff90eeafa7d935b58b8a2d0d1fc, + 0x2c646cf8d9ed14746f8a2a438cdfc86b70fa1c31033d4afd8694a7363d1ca0b1, + 0x1cc7d59c756a8e93071f95f1eb8a5cbc2aeea366715432873be8f94e3f9c8733, + 0xd09d0e6b64757bdfd7128d041c430b0d21a80a3792d0674f0028872c14fd8eb, + 0xc28d39d145cb8b6afe18576403080ed19451473b578949a491a095b6a19d082, + 0x22a2a85f132915aa09898077bcbd76e572e4340d8085708eefaabecc37ceca1d, + 0x1ad68c4e148a6c6197fdd9fa2c45f8c6f3111ddac52db08bd2ae77860e203a6d, + 0x19b59a4eb2398896e27a0e670529fbf4b72c3953a82c2bba9541a52186cf7477, + 0x1e3aeed61e3a7bc6dbf7674f8002a59ee28d3d5d51abbeb5d850dbb3af50559d, + 0x237d14fe10cc10d41cf7b9545c5dacd245207725227ee5d5578a3cd163c4c161, + 0x7a561b03c03a856f5d7b15e895448401a8a4ddf1de311b51663640c81cf44c0, + 0x20e3c12021f53fc206893985647a3ddd64fb1660257a4b9d7d33fba8be729a1a, + 0x11cfdd5386f9ddf36e9e1a271c0a8565e03aa7e427c624c5050dbeab40b10b65, + 0x97b90f7016668c55385a0f101b699d0c924d1556918eb58c9d9a16c7815b3cc, + 0x23dd4f8205e9cb9e123e27e80f46b8ebfb4554df41528acdbca14166af70a8b1, + 0x2004cf48392d1d3492069d0b20c5ea636c7de4704668bae0400f32d0678b5f90, + 0x10efba7ebb220de9af4af5b3d2cf4e3a463d6f61b3a51b190b392897922b15ae, + 0x26ca8fa32860470e9ba95f2b328f45b6d3aea8c6694f52f7b2b6139b31f0e659, + 0x2e7a6096889e932c3bbdc1234b042946ca8dbc3bd9d42894e227abe994b3954c, + 0x2b2a5b222000c7485717e5134d31d966d01094d20142ce0be0ed5bcd238fa4fc, + 0x5d252566db243c26ceed95719ff4e6b2db926a82a90af66c3913457724d688b, + 0x3016d7a342ccaefff833834f8c85e4cdde502f4cfd2e5e67a434ceea8e7e8734, + 0x22e4a5742720cc545f5a8b5ec81fc76c856674c2956c74e93d09da15b9ea85da, + 0x158c039583d91471651b425b67a9c428746b7d2ff4d3f9c7805cd097252882b0, + 0x2e2b9193aee7573ba18105d36d5452636f0a4a23f6bb808dd7b8351b3104288c, + 0x15288eeec077977863bbecc27af0e88653434f9db50041bc64cae3a4ab0267d6, + 0x294ac3d23fadc39ffde4fc51c231fcb1e9043d207384a51281ec6993806fcbc3, + 0xc994f0154a6042df030cfcb8775ea9baf8790d101fb004f7921bdefee4dd, + 0x23be197c83df334c3818a4eb54f3755fba5ad61c6ca408d6fcaee753a2e449e2, + 0xabe4f60f5710062df7838a25e613eec5c7c500292cfcdd88c4b104f92e66dcf, + 0x22d9eea2ce981be68d03a627a1ac38ae17393b42fd589e8492df86bd03f69ba5, + 0x17fd7f4e675f456e77902bd68da43d7a0cc8ba75075bdec73800b670faef2c81, + 0x3cbf13917d8f6962b85bd9b1b475e083a9a6503290264d732bc7045eb4c0e7a, + 0x13e3842e78b6be3414c29bd5528593673bcf7a071c9e547d4a6a8e8c1f29f43c, + 0x2638bcc34e7ec977e6205a356d8073edaeb37d6d0cb2ee15ccc657e00884f71, + 0x1824a36f9b33cd88b29d9d56794c02f0498c8c3520cfeb8d7d23df01dd11bcb8, + 0x2f64d3e9e9660efd747a28a181719770cb89acc868f1db0b42a0d41424d5b97c, + 0x27e976b95c1db0a431cc63d2bcb77b7420eab7240caafbd4f6ed94b771d7ee20, + 0x71017cf059038a6f1ad9223c843e6f687774a7b677edb7d7dd6d4d8aaddff, + 0x263e1eb69b7b2c87f3d9f4d492100367041a00cc20091402d6bf495d74deeba5, + 0x1dbd8f7a790ee4fb6123d8162e879b6d334e137c224da75baf9b00dbd5b14a27, + 0x1df0f444008cdfef43484dc04f5fdd1694d6c90e8f2e35a1850831879d9d7a2b, + 0x2ac29049462ba770408914036f0fc449f4ac15c4a5c16768e95e2486c62da8b9, + 0xafee4216cde441ab47db90ffdadb12b08978ac6f623f3acde4d4f9d8c77f3a8, + 0x1f5df5e1d3372dcbc83d7072bfbf2ba8914024e3398ebbc3461403d39a1e9895, + 0x11c09f4be4433544bb604db662a722bb16824fd85c484c45bf25dfa5ea9732e, + 0x111ea5feb756eb07f942b5fb23849db24d1065b278b4643d55311c0672cff942, + 0xab7c194763587f1dc30e0ed53aeb6eeb6036acd702bbec9509d649a81f940bf, + 0x282c5951f988191603f9dd07759a4f653f19976943d20e30d4c0f8faba0daa05, + 0x23b82721a7cdaac2a39f7b4bd10176e50983f32cfda8bab88ea746ebd4d25ee5, + 0xbafc22c31e735870dfad91a56a46ebbad29b29e531649c85bf79c8dc91c792a, + 0x24710e9cd9f6f42f71cc8815934ce87ca0d677facf1f3d89a9abc2da898f9687, + 0x2475ccab50e2c13fb5d772a07571e0e6be551a55e250e44f22adf1c7a4d7ede8, + 0x17326fde68e193e4a31782f2acecd7a468493aa94d63833575ae5184e9ba2441, + 0x1d044be025c79f610d4009ee0a3f3b50dc556e785718d196e67c60fcda498459, + 0xbc38517b0bedb66a044e38b1c199d110fa36adfa1251d46e635f22ce8fb3b61, + 0x218a7ed7b5b4e39d21cbd4ecdf0d4f31308cc205583a9ef6d91ed6969b45c27, + 0x70989c23efe1c0d6089f9bf987be86854b4bf5aa88b37dda3b4fbdddb068f36, + 0x11f0a1f2d5894630701027346163a4c6974023d321780e91c8df5e91ea930c7b, + 0x9070202bd144c45ab704c72dcc40a5566cbfd5826f7af4746b4472b1e68c390, + 0x243392fe4cd6ca6b6747596c387450ce6a1ae7b0a90eba222c3470d8a80138f7, + 0x1a94265093ab44062e5d0e67df9f4b702df8de8dfadcac6cb4229681117a5da9, + 0x1ab31ce49e37f690baf9ec7b1443357cd24d7bad16a9e6e95e43b6564d987b1c, + 0x2179ceef0feee3b0b03c9658e97b6342f25b208d7ed8e526150fc3b559128c5f + ], + [ + [ + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0x9813c803ff84a3694eedaf4b1c2172615275dc18ca654c799a70440946ccf0, + 0x202973f7fba5bd21ed58bfe7156d7b29010d41090f63f1bb290c1d5da1ad60, + 0x12305eadf64dac24a7913a62d95aefd45f48355576c671e56fde9cc7c8344ffd, + 0x25c783ad66d6a1fc6c84770bd637f6207097dffb0378d7e0395f8c0b86b505f9, + 0x222deb606f13cf28c73a67216d88b16f5958d5d292ba10ef3bc2c10f5a0b613f, + 0x1614d025472771fd870a9e9d422b3571c5494e7d679824d8fe1212177d5fa2ec, + 0x1358bdd6b7a51b1f5b5d094dbd8ee086ccdcfb9c27faad0806e8ef718d0e2b1, + 0x1c2007eba4d1629846bb69404acc84565de5d24620f75cfcd9f11feeeb3f3748, + 0x22f49d7244077e41f409c0b353afd1696e3aa15ffdb4a0bdb883ffe7a1a87217, + 0x1951523a4270c54403dfe3218fd3d4ccefa43114f1b19fb2c2821a4374718b9d + ], + [ + 0x11a131a3778c3774233bc54096419d463d3abbae18322a7e77a511881665f93, + 0x1495af03dc9180c886f0e1bdaf9d18e32e6b0d1b80370e7cbe5745dafc433523, + 0x119344c53707f00243983c6d024fd49a0f8af80e5871933e58ff87c3a1f48b93, + 0xa92bd6a919d1605615786f2efe80743ca57c10ec80cfb926722b5bed408b79, + 0x1c7d3a92caa435cdd974520bb6fb6cac81634cc9bf4e534df77736e06d768c3c, + 0x12fb88a0f6f749d68da9250d5adecf088442827248d67f989fd14b5c9cd4d4c7, + 0x2f6c4e097bb5851be12bbe2c712c2fa906f310b78048d695b4aad301ffc0d268, + 0x1c06c782fbc0980b9e493b29a5e4a04aefc668cd4255d6cfe208e9e7c8b9a1c4, + 0x211865b7f9c1c791a33d703ad3280f69756324349afc8912a19b83de2cd06a0c, + 0x25542e07c1c13979bb14f8d4ee93dab7a3dc750806cf37f2c02ff53b4bb9e66d, + 0x12b5a09e1e95e0d01fbcd234fad473d8ee2ba976fa22827ffa6dd03c8b25a64f + ], + [ + 0x2a18ab4dc4777e13cb8358c1c423153570d1cb909544243abdacd4547c8ec3aa, + 0xd95e8cf8a66b56c32e7d11e0107e41e1297122d1acc41332f1b49895a3c97fc, + 0x7c22f96f2f55653d04edc63150567a7a04609b0b79eecfacb1485dceb7bc873, + 0xf716c54de41920c401a62df8f9186e19b9523e98637a5b113d61ccc30ba0213, + 0x2cd68fc31b67dc45fb6b16f42b5eb89dba2ae7e9aa50c5f1915275a81887190a, + 0x66292e64e6a2c64673aed365cb50f7bd4e1d3b5270f6b2e9982590c3f8400e, + 0x8a1ef65f52128eb3b22df2b6aca30509b0af8af2f7888eee766c0c24871188b, + 0x24529638ebcdf26de8816287fec6370614e112e10c039190c103a75ced11b426, + 0x12e4b5408f48641951739ea27e521067240b82aa51a42de2d4dc1e8225908187, + 0x84b88b1ce4598b701cf96a3379a02a3157d4193c8a8f1157459f6a34ec32fb, + 0x2c184e904d7bfd368d4495b9e3027f9af6b9313c8f193f929ac9e24d10d7a36f + ], + [ + 0x16ebd782cbcf6d63c38b87b27db2a4a5af5847a9a60889c4cf6aa318d6866b1e, + 0xb05f16108c4616a973b01d82e50d4fc9dcdcce67d2d21f852816bd234e9872b, + 0x2f394cfd3e442503c3a22512aa4b76b95b743c7076ca4115a9fbbb7c6b07ee5d, + 0xa157e244f939125d57f9c8e66f7d88ec0fb3c05b90f526bac0871bca84677f5, + 0x1d4567c12db648d4a9c41324c0329325b76a07730fad72ef9e490a748674985c, + 0xa94a2d7c4093c638823b095733f37176d7e747ba24645b515ac2a241ffdda81, + 0x2f6f14502f20d958a9ff23b696cac3ae24967517ae8b2e9592daf451840bb98e, + 0x12641cc3cf50ca67bc93bc8c19ed89d4613e9e281a51cdf313cbc8111922242c, + 0x2185c7a4ad8cb21f19009396f134a2c3fd614d305e475ddd19f26f6d4b3f9ce, + 0x2f6da385450911cd272e13601e7ce66c2b91d809307492f7ee578ae34d6f5fb4, + 0x16fc48e55d64d83010ad573377ea2422397fc3a7e6c88af808a566de0223f0c0 + ], + [ + 0x2b7ed47fac275d34f842f09b01ef9421014de040c26a591595b227ba7bc6fb2, + 0x230b62315b30bc49d73dff8a9de79c620e03c747b14c432f170715e588d605aa, + 0x206351750037bdc90d4f3e7918619fc690c2b5857f8bfbd86d7c001e4cf2ca18, + 0x2218be861d524eaf03b9420b1368e9c5aa7cefee72d0e6ef80732ee9d7e6e2c0, + 0x69ee4eb20b4860d4af91afe1781338f53aa354562ecd873e0e625af70746f26, + 0xa226128da1d9bd5b329f55f52c75682def3369ab13359dcb7d212eefca86229, + 0x17ceb42a19de6dd32e3b38cc2990e64273b52a5618263eebfa49d84518ea3bef, + 0x29012deffb112eb14034159c59162f866d4a1803b4d192a4329359f0f903266f, + 0x9c4b2f61adf245266168cc918e96f7f8dfc35bd3df7b23fc641ef01bcc71cce, + 0x1802b97e54bf3a8978632cbe10e429705b03680325d26ea190c0f1ebc7362ea3, + 0x2db1ac4c2b1c23a00027fdcf0f663af896d87415bb035b149d28ad3da98c6fcc + ], + [ + 0xc5e49e319fb9535073f07f9e055accaf3e3f24a35dcb46cab67dfc648efaf30, + 0x15d217a31784741048f326e155af96e90b5aae734f06779e698864039c92e123, + 0x1accea09c2bfd17f4061725c712fd1976a07e773e54d906da166215201a58136, + 0x2f9bd19d0c8c3887a7fc0173f863f075e66b183ad89f13704930416e1d5cb7ec, + 0x6cad0c2bd438c4dba2ed64bbf75066e731484c36d1f6738b6e98601e9fb498d, + 0x1b5da83966361586e8810fed032435caa80a9b476db21290474ed1977fcef22f, + 0x2adbde5c7b73e9a7e22b913f99e40d95e689c65c428c2397cd273923cf68ddbd, + 0x1a8b8ad1ecb6cb888273a90bef8b1a2cfc03dd44e0b28b18e1074e404a9e0f4c, + 0x281eca14bbc3920919e001150451c3e44ff18e1dd1171412ff5e663d74a073c1, + 0x54cc81c7d1d59581ebcd26b16ccbdcbf1968d77f87a2081d13054f51118f7c, + 0x170c05a5f8a55d5c9fdc5e8238b367be358917a19a28b4c47e46f3e73d42a085 + ], + [ + 0x161e4ae5b2d24cd638ba5c32bc2317bf90d404e37e003f1055d9a96e406d30d, + 0xaf9afbecae1761cc17d44b51ca66d1dbdeaf341e85f1082958f9cb72f7b55d4, + 0x5e52c0ff8c04a8e5e3c7eafa1d0902fe63e35898934b00f4333b38fe614f913, + 0x14eb401c1084a9ddcd5d0092e5d1a299aa0f55c351545c781703c01ce87d6b29, + 0x1e0e166d734aa614c6b53db4f691179841a33f8105430a3ee70abca83ba6ec6e, + 0x2fa75deed281db734faba5b70eaf57962f93e2eea1d3dcee34c81ab1e9fcc0ee, + 0x14bfe33115df293670393e1dc8da4d6947acc4b60249e5b1c8cae376665cd580, + 0x17ea198f3ab261da000152f26b0eb0ebe088a709e8b06a18a3dc2108c2096864, + 0x533e8a454b8cd6df8d48fa9b0a9cb2952933e1a6b1d423cbc54d0533a72599b, + 0x19681b4242d11e28aa72530cf33a7d15719f1a888fff625e04652c77ee2b2de3, + 0x1eb7f6e5520215c15e274355b19bbf71abbf04aa426cd07da536cb3f909f6e57 + ], + [ + 0x223c7fc6d24fc53d1b428edb8f1c52d20ceec592187d2c7a6b0b147b6292b81e, + 0x1da4f4e3c6790ae1b89c4118861d8ca2a50cc82a4e7f1ed3c5ba8cb944ba4689, + 0x2e708baaf894bc5835e5fea81227fa8cfaef99086d12b0a3a7f3f85bbca61d28, + 0x13fe23be24261ba5b92d363989f58e17fceed4a858d1c61fc2cf2b71dbdb6936, + 0x1c879c9428e19607d647f5ef1415e76f7c59fd01e52afb80486081851f9a5284, + 0x128cb3150b15cbc4faab14bf7d676ef3682b52cabfc8d3419dfd98109d19ecc0, + 0x2bf523cd8aa3be20ce7d891f8727a7b24b72a4d4838484de842acc782fd8bd32, + 0x45aaa99ce1e06a3c02150804a91087f57a43b79797773e83216ca969e873380, + 0x284ccf70859547fcb9c3c7b64cf0ad62e51726ec81b58eb01c1a1f8ec7a9eb70, + 0x1abfe4b1cf5db29d4078e5289bb143498abbbdc9af56720470a26a3dfa2ba855, + 0x14111a74bd24730c833699eb41b38f1d4ed16fcf0fecc1655b76f2437d4a0c9a + ], + [ + 0x1ae060e39b338d09845e2e9ebeb70bfb74cd4af926217f5732be2b6cb7fe72a6, + 0x2860aa52dc2f967c0c1a0b942ac81e02189d031430c11a919a5aa895bcfb6151, + 0xac23f00ff015baab1c8be9a90943c3c72d17818be7ad427c45eb3ff1828727d, + 0x32fa2f166622f057f61a9405c9256223cab2ba82c9495607921755ab018f690, + 0x215c0cd4e3f1bdb482b93e571879d7931be90023d7a220e8f93b21c8add41ffa, + 0x52700b19ef6d42ea392e044a094cbfc308eea1f72f2a3428b1e721bfc32c6ad, + 0x33b93a5cf15ffbafa2726f2527824a11af8e42e01d3a7ee159b273ca0a6520c, + 0x254e3acdbc75ac592679b032b65a9c91d2e092ab5e5719551b5da635b13e9471, + 0x4fa5620a2c057dc552a59fdefe50a901068190fdc3df8761991cab50a01a449, + 0x1d2279673f6cabf0a1c4b8eebf8e9c78361680b2e59d7ec19348819f5b3d5a14, + 0x2d46b48e5090c0c56a390de373f4c9a2008db311fe31063cf4fed54629113585 + ], + [ + 0x46191ab41e93929ea51f190fd4e773ac8d5083328d4b2f04828dca3e69098c3, + 0x16ff33d67c85121bcee7d81cff1618927f1c92b4d1d21c2a07b6ae18b2b7b9b7, + 0x2134798f4ca7fb9928012c937f37de87432b8665aeedf373e7ffa6fe0c13d00, + 0x2aeddbfa245756ad1e1658629f747b8da7593b195cc950324f95edc9eda42aaf, + 0x1f41fc67ca1322b37b7aa01b631fd19105281f6c6a4d37fbf68fc1b5f62802c6, + 0x22d1e64d4ee15e60c459d851ef9f3495e937f5a90990382c97867c45b7940071, + 0x249f416fae5ab52a435d65201006dd8ae8d54266e4d5643307551902423f7cc6, + 0x12a996abc8577021ac7880c16f058d9e06e9511187f0aadff6bb640e4316d26c, + 0x2d2640a74ede9af6c9888e5f68a84fac92b13337dad8fc6152fab34b55419908, + 0xf246d2fbb4e1217f09631fbc8770827c36751e6ad8d6fb16810e3395143ad80, + 0x15f30ebdfb8b8ee644241039a26b408dc7a8de77f2cc6fed754b703ea92dde53 + ], + [ + 0x14ba1b5383e3733c63d00c32c2bbffd8e54507ed33bf7544c86388191eca3e40, + 0x1ba0e835f47626b0d82426900c49170a8be29c39d90337aa5fc10764e2321a1b, + 0x219f5e28a5fa52689d2b7be432624280c940c9bf9883c1fb0fe929f78873c1b, + 0x123a6055681023b16570c70fcdf3ae8e387a973690b9e6761be22f9941d7ef76, + 0x1dce36062af7e4b0098f5590622ced7af9f28e88d476cde1391eb30408d5d266, + 0x252e74746677fd7584ceb0f8aa6936bd04f9528ef600737e9913fe4b5698eb28, + 0x19a9079a9897a237074252767912bed7b7635ae8ca0ede2dd3a42a75c1c6b81a, + 0x777edef4d91520fcd490a22dc569a97e540a0fdb527b4b1a3a854fe346b8e7f, + 0x121a3764269fd35cdf1e621c3dc6318f47b862380ba00357849d8840059463ee, + 0x2f80ca151b077b50767281ea5d4c1f7457f8da444dda16d8149bb6c1061ed0aa, + 0x1ee950c45a0c2f4a4b64688a7935ed2b63d4fe5b414afa05c1a284674409f165 + ] + ], + [ +[ +0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, +0x254a28279a58c838f7392034aa21d51ae44e1449433d90824b817e44b90cd22b, +0x281d2ccd521bc060d152223d46196f27b048f33ce6ffbbbb0884f3d5c64a6061, +0x10b388ce0c7860c8a70c4e903e61b3bf97b87e324c9150ce576aade8b2d06a1d, +0x3ed1d46b39ed65512e3e4c8d53cc1d2cf110cc65e1d65b37f1e5e785a6fe6e0, +0xbbac4700573f9573a123ac6a2735b63c48df92a7c91cfd1e88186a061a102d6, +0x4083e23f948783c32f671cad0395794a2cfa8aa1c1cb6a0c0105590904b2593, +0x1fa80347e1bb24e08599758c895a5a13fbc63df14dd9063f5ee23e5cac163b61, +0x1e465c7a4b123984937605aa07cb8cb830591e22e25b4d94d2efef2f25c17f3e, +0x125febe3a720ed956f1fdf75648260e56e67d32d0e785788d1cf97ef61f6ff69, +0xa3e7d3671a213b3184ac44ea74e12085cf5380c688ad23e8300e69333c123a7 +], +[ +0x11a131a3778c3774233bc54096419d463d3abbae18322a7e77a511881665f93, +0x11f3eefe7629e655ea90af7061b775bdffbf26dfcb0f67a5578774e4b237376d, +0x11f896a08f039c3fe481a03e0b8c880edbf71b783d169f4bff14bed5e1b5f15, +0x127270ce679a10a9b93645264ed270d96f109e3f65a437240d629e59eff1b2cd, +0xe81abedbcf77d0706b6a4a7438b5a9c42257b1233f0426225c8d410de5806f5, +0x1bd40e4b13c0eb7bac78d2650586a59f28b7ee26be01fa2a677e734078bdc210, +0x22202ee3e2df678269ac3833b87fd279d1d045fc42eb3ae75107188ad0e39bc5, +0x196301b7681fd2882ee086f61a83db475a030017f92f72dcf3ebeaedbc571520, +0xcb517d9337709a54dd958c64afc6c8ad84fca2f59fe3098f74a7537debe0d2e, +0xd9be42ce8bb76bd249d36ba2d8c5a70b52d20c9c8686b7cfe346d5c72bdc15a, +0x2240e2f64b6f5bacdb2d6aa0b444887a91d1ce0eb1bbcbdd58ea71499b7a85d5 +], +[ +0x2a18ab4dc4777e13cb8358c1c423153570d1cb909544243abdacd4547c8ec3aa, +0x1f19f9b9169b49713bfbe59154cd93aac19d03b4668733473fefac6eceaf9a63, +0x1e6425bea9db8ee466777ec75d3103cd11ad6ed24283a0b188b5aade7d496cd4, +0x22e2d64bc44841b96bb9286970439150d70c55f8d65fa79f1a4ab34befdf3c15, +0x22ea712a97059dfd8af604c752e478b8d883333e6749b2ace5385f0ba8697f67, +0xc19fc53d6d946af3d7fb79d8f22c46df2e1b0d0f2cfc983345db3287c44853e, +0x177800e892cde6dcf66dcb1c337b6f7f6f6cdb54dbe7e2e2776abbfda1fc67af, +0x133f706a099e95021e46b79e7f0fffdb210d87a4db1d129bd6fa5f62113cee23, +0x2c540ac453bc95fb61ad879a56126d5fec7ed9300d545938bcd80c2feee7a3e7, +0x2575061c9a069654a195fe41554ac0f4080dc8f7e808d676f3f33c615978d593, +0x283d7487aa3b5d0ede9c741fe754882776708f9bf68c745abdd38250ce70c288 +], +[ +0x16ebd782cbcf6d63c38b87b27db2a4a5af5847a9a60889c4cf6aa318d6866b1e, +0x15b3fe328216827e93598e15425979e9dc4d9b9ab421f25aee3e49bc6067d6bc, +0x11cb96a094be409eca05bc42f6d8ad0f6cf09cef2b286fe5945d587cc36862ea, +0x1e5c6cea55983c991761cf70ca77fc17c3789a8023d2752554b49d0b8fd1be7f, +0x257d458a2883c760b295e5b2789e6a942b8d50fa6fd3eb093a96ab81a9aa693d, +0x4603c35c98c1e379b235724bb309885e9b56284a6cdb1cd0d3953270109bed7, +0x1b2957f0c085f578b4a1b58a21143c551e5451ec46b9fbf6ffdd0cf6e586a00a, +0x17bbaa8b0ea832469bf933ec6ee5941a1bf97f0b7b1f6b0ce3f708d43795365, +0xca0c774b1bd1c2b00fe8f6698cb08022e4a3fcecf13d79953485c905b76f8a7, +0x1b0265724a00dfdba001c87dcd71e5c04736a61821b19f30e02a4b53eb59a12c, +0x29ddc736b1d7fdce1bf6a2f684702703e857b3be81599e485932a1c03f4fa16d +], +[ +0x2b7ed47fac275d34f842f09b01ef9421014de040c26a591595b227ba7bc6fb2, +0x15a1af15f1f7a77a5e6e760470e7b7cc4da48f3fd35b1b01f019384381e37135, +0x15810baa26cba809c29275debafe2859cf2350199af232bf920496c5315947a1, +0xa1c89983188b5230102c213ce35a9fa49743c5490356fa305a8578c716f7202, +0x2a9243c6a61b2b7464f22e1603009e6b6f7946f31cb71cfd4d291601458ec39e, +0x14b216d879b61949c8bb2ff6d43bc7fc3c634a90b766f2276b0a5c6b09938cb2, +0x2b2b79db9b5bdc6a1844c4e5c7f33806d44ad8644fa0117f5bbfd7183754bafc, +0x20f56843ab66f86615274f77030d662e1f6cec212015e14896139ff6d28116d5, +0xf2a31d4612576ccc0cb003c57ad2db723008007b066054d114a9ae32d8e604e, +0x1a265ab962a3796d2cb4ee2980ff3bcfa03e8d6738d59c8cfb899cb771f9a61f, +0x5f7ca424f02338e81927a8928c0f02fc78eb1d1a08c3bfb8965cc7b43d8e056 +], +[ +0xc5e49e319fb9535073f07f9e055accaf3e3f24a35dcb46cab67dfc648efaf30, +0x1d22b55a0b71329ee03adbd79c0a1e7d32efc4d765e6e581ecb349e2940f394b, +0x825a6da8cf0213b181fba494995ef1fedf1d867f8c777ddb93d10b64f1f3bac, +0x189642d90074b6ef89e102eefefd69d4d69e106cc6d77281b971315feca3f6c4, +0x1976bffe10562085862cc586a3cbff8d260055e1ca382a74332328c0eacecaf6, +0x25195d63f3bc30c2896cafcbcca1f5b73ef4b74929359594e4421c7c9a1c8f8d, +0x1f523a01526f1b783c2e3760a4e7e9ccf8ade4e32b56002d15baee4eb794465a, +0x17cb6777e65329e7c510142a85cf3781ba33de3ceb98a4ba021d783d212e7492, +0x1308c2b9ba44163ab7190c4c151c7f44f2e19eb186dc82a2443446972d667ec2, +0x3006fd98ea0d9db2b33144f885e201534edcf4c3ba6e96d8a22db2bcfe8ced48, +0x14f241ecdcca69b025108efd0fbf00ed34448e7bd804d5e85a835619791468a4 +], +[ +0x161e4ae5b2d24cd638ba5c32bc2317bf90d404e37e003f1055d9a96e406d30d, +0x2b04ed9f42228f06802c0b537dd014217f3c444670a0c6f88b3b5ce001b0197b, +0xda48eb83004661d01df489e8156b75d9b661c61a9ee1329fad03ef74521def7, +0x1ba1cb5df0f9b236e9f7c4f637dd1e70784a2b07f8e062088b72c3a392d44b2d, +0x2c22be8e5b7f7c91490c46c27a09e91872e361c1e6628793b9674569ab3c0b1f, +0x83511f996c9f415dbe56786f78ec97fd8c84f5d4ffbda454b3c4d5901ec92a6, +0xc3e13ba070756735522097a41a9138f5a44cb5856648daf70bca100d2346b1a, +0xb14339306b1b2e3114e50b0607215d3f92ba684690d78d2a6ee417a73933c65, +0x25c2045be7d9a915562c78bc1ea2d954155a0289f900c757b7138596edd9db6b, +0x1b909b20dd52d51184b58d123962b7fb22cbe54881117270d279402c4056dc39, +0x1afef8497500f3d89345974c67a21f1e18fa930f7d78a1ca691bde258c5e2c7e +], +[ +0x223c7fc6d24fc53d1b428edb8f1c52d20ceec592187d2c7a6b0b147b6292b81e, +0x8bd608629b132b0d741a305ba0002b9ec1470499f5c0ae88e26f269ef00320f, +0x238b46140eeecb9a32c7289626b692dce13cd51bc3812f1b0d866945c0e08e41, +0xa5ca2631a8379a163fd40936e6913afa60c1850b9e04b622f2b6e109d179ecf, +0x1656737ceb63a2d43d462ffd902804d11283820356001961f1239a1e7cd23108, +0x168df74339cc5c612553d91ce34b44f60123aa40e8486e3177cef84844529bfe, +0x1d1cea63939b21940f784f77c0f79ed523beb6df5432911930878b59f92c7f63, +0xa2768ee0edf0b7e5e69a734e4de8129136b926e5ad1891e6cf57a5c39a14da6, +0x22c57e5689822b5d931e748dec46c5e64c04067f579d96b89b608ab5eb5a1e38, +0x1d4ee90cc3cedbb9973609382c57bbb1b7629fc5398ba62e2f8f7a9c55496ca6, +0xf9c70d6ee5ba237f04597a71278dba03151a3efcc594cfe61ddf16b5cf1722c +], +[ +0x1ae060e39b338d09845e2e9ebeb70bfb74cd4af926217f5732be2b6cb7fe72a6, +0x81e512179c27b63294fdc958ac35b91ca61cb3fcdbe4e661ce465eb3b060adb, +0x64bd952087ea3f724ecaab7ab891c7164148247b3d9534508559f290ab2c455, +0xf48a6aba18109eb41509d160d2b6e2bb75b73f2d360b142e2253e99285a613d, +0x2144765053902fbc1577578eccf3fc1990cffbc464b8d5955e387653e427eca0, +0x149178f36e2a8348229d4e5f829a53620864b7f8c3829adb1ce2f4f8f6198a95, +0x9e651e10ec1fe98ba2bd23aa05696c4bc5acd233717b7069069a206301f7e16, +0x2f995fb2fe9a457e970030416b7811a93b31b3f2ed7c7300034cf958575b3ef, +0x98eccc1107806d905139f5aad87c4dfe9ff0d1eecc1de30e8c6a4cea8c51dcf, +0x1720f40d61fac0f66408099bb1e34e3a48b29ad05b8910a7bc257e01de20dbe5, +0x18fce50e6f51644e0968c44adeda32e68bc24c25e81ec37ce5e8771383cb76e6 +], +[ +0x46191ab41e93929ea51f190fd4e773ac8d5083328d4b2f04828dca3e69098c3, +0x662f21223a41d37668404a75b278b868ab602e313e8c423798b47c47f1f56ab, +0xebaf002ad31782757a58dca1b295b2e0ec0ff3115a8c931ebf74fddcfb734cd, +0x1e1567bb8636626357515a40b0d5ebeb351422e19acc9bb5b7edfda91649841c, +0xfdceb3ae2d8a55f07822d7b92026ef83ee8bc326e3a8b35225d587bdde25205, +0x130e0c983de0ad6d15d8770698e39fa4569f38848ee05757951cfefa1f338fd, +0x2f7be21619fd5f7c05e31d90607acc55e36fcb5b6c55f970170e660f2d818fed, +0x5338e9847d4e29692f22f938875dcc5610464d7393c6d87dd799bb3bbf810da, +0xdc0a5c9bf0d5b38785df58fb22ede06709eac85f230639056bbf1333b9a2d21, +0x10ce79d030bc12a43f0b6fff0d884c15c263113b3a6ce3b24318f0a60164f6a7, +0x232926077aaf9a6e42e885290c6ad736f29cedc9b0ed5c5a0530e405d57756b3 +], +[ +0x14ba1b5383e3733c63d00c32c2bbffd8e54507ed33bf7544c86388191eca3e40, +0xdeb781e30eced913c20323aa3f86be585d4cce7f556abd2c2a0815bde87b775, +0xa877d868ac293ccec0f559d48e3dced60c81fef80ddffc8f70905664b3bc0f, +0x1d635d1267a513c78be7288e584254f53012b3f7955147ec7153532760c6c9d5, +0x120a95649ccf899fc3a8048ec4adb59a84d3ff5c292328f6cf32ee0c14d8227a, +0xbcf6e6daea072a539fa1030a61bd0c6f425e9982286ee468ae2ab7bf1b8d114, +0x1c4a6464c867d43eb5fdce8a731867e1b9730ab208fbe77bc9ca7ca010a74192, +0x562e63099a7630323f701d2fa312c654a891e682a7e0925429c0321f6155621, +0x1bb2aca445944760eb02e57360e6d3fae93056dc357ff0dd8882d08983be3325, +0x210f17a9d928eb4f42cc8dbf8d6a7865ab53bd038180c9a1c9a506a2dbb0602a, +0x277425a5970de392ade13f6ee3752600050830d3bbea3566438924ad5159df4a +] +], + [ + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0x239bbee0bd0536587314f5429186856d92bf093cb902a7513b11373dbcbf7134, + 0xac0bca8c1a15d53ce77475eaa398fc316f791caa305403407056f9b14f47f64, + 0x11ad8281442fceb40a4c536b728ee79730be6407d603333ba18ef5b7492cdd13, + 0x2927ae7db23955f84264264e7dc4f4015b070620841d9035f54c501d0d4975b1, + 0xd9455f3c59c9ea9302e721c00003feb40ec8231463b84c2d66c403cb9110dd2, + 0x14d50f175c19900cae3eac1f457e2e02218929f5c6548a6e601f3038240df458, + 0x237b9200970d84323901b9d7a12626a3d828affd132d9ac43ae01d5ac3cf618c, + 0x19d66d04ca7851e0cbaccbe73156524606cba6bd174d94bb79d3fd99da05a2e, + 0x2ca5d1e4cd8007c2a6e745ce9d3581c2661d28ebcf7b723bfafdea4a97004061, + 0xd54ce53ed8160546c3555b48c6dc1a95bfc11a529d863ef3d6d63f3799fd407, + 0x2c21c6df9e87d0942740cfed6b692c5e4868b781085a292f505a9f53e2969b94, + 0x6351ae4eccfe35f6fa2f0e50faf512ebf3bdc02a9b61fc2baad2e18c4c7e128, + 0x1c86e871f69f568ec2e47ce015f7b324c6833ab9fbfa2013173857efc040f95b, + 0x2175813936c314627ae23d64f217d0725097891f1b1cefeae407bbcddeee09b8, + 0x2ec44113a689ea96c746225258ebf92460b065c25e979e5bffbf0f8590315eaa, + 0x2facae956086465c460b678df8d1a10bc8256e85fe5a3dba26ba637f3d4eeb94, + 0x1865d5f9b9b920317a5751591a3275d233aff5b7f6e6ca7c0f6b2e3f1ea0184a, + 0x412169c5bd61a200567219a93b8df6b4391fe1da096b22755680536a2173411, + 0xbef9d4f49681702d6176c94ef8563f7d1cd1556ef5adf986cd9dd6402456513, + 0x10c7e674a66fb25905751a9f355309c0a6b4a622b7c3b29e93c61f64d95d881b, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0x1934288830ec4d6ef05046f36c7e664fc0790fe76e390dae265502624f3e6764, + 0x21fe8f4f8f4fa08615bad7638ab88a92cf8f0a6f9e3e695f3458a459fabf9a8d, + 0x4e0a4f483d51dd00d1062226b3266d95da5866968c6abdb721d96f8f7e2bb1a, + 0x2d3806f1ea209c26c7b3fa95f40e8d213829e28811223aeffe523cddb5246ea1, + 0x5f7a9f8fbc8104008bcca318850c76b19c624671782c0104a04b1b03c16d792, + 0x1c429b4f17c25e0c73fca45ee8f69e5afff9bbc21b4648ec497276a7366568c0, + 0x2a5f492892b38ae10a0615eec76d2f514c9f3251000383d1d1e13a90a9dfe059, + 0x1eb8bd92044de59e84b8ff7e28347243a0cf0a665dc38be0a809245cf2632846, + 0x65ee5b5e74d35c9e411443393e2462959a11fb9fc95bc1b627cd0f48429837c, + 0x10829a880633680e7078e1fe50cbbb362a20d7a313647297a99dbdf6578bbe84, + 0xa83ccb34dc841eb9cc8d2974f083c61a9d9f162d6169db459e0544be9935d3f, + 0xf8f126cb3833ae566d7020e8bba5f7ee02525d4378d81d36730f97ddd2c358f, + 0x2783557cf3c6a0b59926f5804752bfd7de101c1e831a4ad421b12d2ec9f7bf24, + 0x91f200acb6c0436b64c4425917f2fa4c6373133a25ca40a19a28cfda9b219fc, + 0x1e4a28170c7a5034f70a700fad1088648e97a11fb4856e22a5239385099caaf2, + 0x29d63ae313de07d1dc59205c4b29f8b95baaf7efeface383982252f1173dfd2, + 0x188a2d62c5e3519664418fefd0fd0f214b101577643ef5674cb5e5e4d69bb7ff, + 0x230324a35fb7ded74a04c7fd4cf7ee0f68cd8851e1e86b5e4c2d9c1857d2dbce, + 0x27e120b07d441aa2864beace6201c4aee9a06aa4357fd66ef765c6f10b3d3c88, + 0x2d6a0fac700c78ef54b97bd61d43e88b5215f352dc6806201f3e32ef06a1dfea, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0x19214ffdc30bd79894098fd3804b092c50b04ed072d36155e2003204e1628efd, + 0x2f15bce2fbc19f00682f8ef66ebefd1fc0a67d43e4255f72ff9ceda492c98752, + 0x215fec7c7c775fbdd3bd2317d73399873ec497b6dfcf434c606dc22603b41b05, + 0x28965510c52457b2b0d9e49812da55f08028f23ff9764622f2af19ced2eb250, + 0x2798d59530d1d41a6a311e90c9c37f0bd389a39737394a11829181d1f26c4988, + 0x11542d205011b400201141b40f0e818051b0a983ae9387786906bfa71cdc1f5, + 0xbaabe59e61426a7f5ebc2174ac06d27ca7854ddc67e51b8bb9573911387eb31, + 0x268937a0fa2e75f79c04d9f2aa6cc56ca52f3c34352cee551aff2b99eb953a79, + 0x1bc3e33a03e620069e915e78112c4b39bb36f9f3ce5d75e9d51624f0beb1528a, + 0x1bc41b054898379199236443a43315088018c303cfa8760d7f679149ed53d3bf, + 0x2ee37960ab5cd93080139be75dbf02d205adbc6887e96d278ad3e430a43c59dc, + 0x1cdde27557fa9f3e2540dfe7deec2ea92d7862361a4a7ada6e4b68f2f3b4e867, + 0x2215b23457c72fb4df6cb05ebb6e695a02c0c7fee8c1ea4553d130e9ab7c3a25, + 0x2c0a94bae0c8d81169dc3c1b3efbb544d16fcb0a11b18bcdc68c4b6756c1816, + 0x9c4335fe7a502889970a7670ee8537837526594d94bee1008d51506b0baab6a, + 0x1d54c7fab67c393a91a61e0e2e38d5b7ad4e43f646286e64e31704c748ba9db1, + 0x300b58fb17814ea816d0f7bcd9c3aee0c411ef4281917824180a3547f8f41b73, + 0x27855ac29fa4b1abf74da38a4ce42de382834c90dceb506eb1f1259823889f0f, + 0x2259c5da3d87b0a065ffb5a9fd340f8bc3ffc41113b77bbf66a2613a03b04874, + 0xfe5e47f909ecf12bcfb1e96d2f6a5f96e8e95f7091a921d225fb33bace62388, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0x2cf624bcc1b57941669693a6ee517fe56dcf7ae5f8dc152456d68cd4c839643f, + 0x284fc4f8f116661b9dd2690be9979691b33a6af7b521472a36c154c5ecf94b54, + 0x15f336d2348dd647d17cffa8507990c62d9355d63fb15fb7b7181c0aac883733, + 0x2b097ff93c8883e63327f4009f9d0ad5518484aecc9ebbe42ab9ff386beb2d09, + 0x2b0e0d9bb68edcc80f960a98b948c1a172236a4461c5f13d2b7d1fb648d1cbf, + 0x21fb862d3aa99493e303f1fbecb67e2ff829a890338ebf642b1bcebcdd3eeba6, + 0x1d742e5595d6548a4e5cde3fa1a024fc04ba950de76aeef9d094ef3a6aa80e01, + 0x2f00e60ddbc4d8cbf208aace4afbe88c9025e161a5b3dbf495f11520fb314713, + 0x937367d77f41edb078d7efd73191a38ec61b2f7ea633aacc172fc808e6e20b9, + 0x20cc21ebecbeb50a3e7b6f0ffc58f95d9bd9990c8e0cb2b51bea7cf817e0501c, + 0x2153722c6eeac70d60abd76aa40279e600a739a3c24b2d9950e7e0d08468ae60, + 0x170429ceffee65277a55842cc1c6089270d658bc86565a5618a4e1156546957e, + 0x2881b86019bc624704431bc3ed315ae4dd4c6589118f6a60d920f1c4937696a4, + 0xf75ac5249bce09549072133d80f299f5e194bd34f820433eebeb5e020817091, + 0x9a487d60d8c77e941b03d1a4cf0e9a92b8328bc432b437318c0bf096b8c95e8, + 0xc4c7b8be9ade992204bed2fba9ab541af980a47b389cccf61abf5353640bcf0, + 0x13c6f29a13b808abc57cdc98bd5b32326c0d37640b2b1c58a988c50dd0a66e90, + 0xdcf77d7d72c03c43842c43d906862cbfa78b60f89780b9385a2d81e316d96a2, + 0x1af4ecef93add6d17e589cb3e93a7240f2285e18c1882da49b0996fa64a5f7d2, + 0x16500f1e2eb13aef4078724a58c869cf7af3bb0a8eb50236c3e2463ce54554ec, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0x2fb22f7c0dcc8f0710df44a538564fa4835d8297a65bd032793c44d1ecbc66e, + 0x186c3597d2e95409839a6577665c9247c61d1d4e39ed975d7eab0407571a3cfd, + 0x268a806ff91bdb7848e65fcffcae8ab72e771dcd9e44918bbbf961d024c4e780, + 0x22a72134e6b344238cfde291a9c27c8d91a7ce8ca75efc932a3ac0fce7229618, + 0x2f3d93275b7e8f80483d94dcb59ecbb02d578565b6f3510a3b362db38b806990, + 0x2188074227737f56f2ed000fb0557da0fce247b29e3fc1e94c782497dfedca5, + 0x2795cb6a4c716bfb133f5aa5e413d7ec0643932100bee8003e35125e908e92e6, + 0x168669f585369a0e9e1e1800a4a64e59198f67da9022257ae38ed2dae2f3e890, + 0x1ffa32112a81bc68e5ce9b45a08becec9463ced766f99e3f70c5295bb287cf05, + 0x24305de92f0bb0f4bf743d990721957c6147f9712ad12bd0970d35471343f1f2, + 0x2553d6aca650db381e5a5cff064f3ae81d10dcf60fdc1b88d0b4a182cc3b86a5, + 0x2f3c1b421f6d478376b135c9d120317b4290120dc11218033e249e6f660738a0, + 0x245b4bed81074004368bbf0206d685ea4aad9ec2c5c27404550b134d60301858, + 0x5d189b960a83b4cd0a7038f8a5bb9fc4f86a1195041c3d5aca8020cbf92a015, + 0x2842fd81790b045c74803f7569b25eff6c992c2e571bbaf1cf9917f9dd45eeab, + 0xbb806b253f4b014dac7ec4b9150635e5dab4505e9194ce2046af74db06e6fb4, + 0x1130802bdbf1ce4ad31b52a3b3380ad274eaec3ad8217a45429e7b8bf9f57291, + 0x236b083a817afa7114155de365d7157d5c45d3ff29a665828689c98c118887c1, + 0x2b1118c83315eed11ca8a5128ddb9fbdfcb0944e37f30f57ae91e81344f76eb3, + 0x26c7bf0a07d43c11dd2460b3d339014666f2ccc0d6f926dc5320693ce6530213, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0x62d864c511b8873334e836d12eb72f7552810f28b4b9270ea837e9118dd92fb, + 0x25587eb09d2cdb6628c520a7111ed2287f8ef7d5bf15e7ff0d9415616c14beb9, + 0x20344cc75c81860502190a88a9753741eb82f1355eff6272a687af15b3370983, + 0xcee668ab7cafe0c92f12586b73566a59fa7d9e14624394bca99d6fe9e082c57, + 0x41098b20212f04cc7fed3b8aa272d37dd719e4304f79301d4b7ae6efefeaa72, + 0x193870bbe39e62100358a649faa3ff6f81d1915da932545ad5ae3dd951529dd2, + 0x1d86daa8ff221daf2c5910e1b9adc7d1a320575c43ec64b6f8aca53cab46f16c, + 0x25923c7c452a59c736795ec2d6993a2d27a18b01107b018164dc30ffc6c7e36d, + 0x166f933a262efecbfefd5d1218289e8306130b9b3ae903564812aae0c357b73e, + 0xe710428c953a764b43ffbdd166707d10a6a08ed48aaeb562ca63a19b70c1c50, + 0x14212cc175586510bb7e0107b7e99a1add7be5eca7445e35b23a9bf5e9bc26b7, + 0x7922b817e326535d89ad077f917aa3f5ca180e982a89628502299515bd1db4b, + 0x17b1b0209846528ed24450b5b6910c3dac0d79a35c1297c2e0ad518bef18ec2b, + 0x1fcf8f4d3ba39e14ce346b78e781ccb86fa80a2c9b91b53b2b917d32201bb0e8, + 0x1328e374326bd95e9a909683113443b309c75dd559c78e48589f91d3d667fd7b, + 0x186b0b6795393cfd4a4961f0d34cd0f86d491ec8859ed1f39649f4a77d23d0be, + 0x22866b41e186a1a499d3862f90ed2138b052753dc15fb43f71d071fa54e8ca21, + 0x1a21712b5674e92a8fcdba2df567658a78f1c6409972912f59a3fca3fe10010a, + 0x169c1593ef30d80f8f26d4c287a790cec8e41ae53c718b5aca62baea5e7a7f63, + 0x10cfc561fd16648777627b6f289f95a96fbb95ecd84ee59ed541e7b81edb4d69, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0x2f44dd9b3903bbe40ed4f0a14f06a691510f25d683942e3fede322c7f27db564, + 0x1be695baecbf688d6618060b85965e37e50ae175e45f09704d33f2605ae3ed6, + 0x163a43dabce2f70ea0d35c105ad54d85eea9b0953d028fe4e11c604e8b5e69a6, + 0x2956dda14554b0ab7db32968d172b733bf92a1efdec6320b0c3c9114da88bb7f, + 0x10f41dd81a27925bd837952dae5a9c494dd285ffa9a40d9ccb17d71b9098dbad, + 0x280ad3fca7cff3b3cbdf6781f295bc0ee70275c10a6409b7b8c99157753013cd, + 0xf12826ee6e2f4690c360410aceaf27726e64d0c6d39bb5eb8bcaafdb4266aea, + 0xe9f48dc6fbc4706c6375c87d3fbbce3fe78427250b0fcae92e07890d3fd942e, + 0x1c7a967977120a43bfbfc9351f2ccc84a2e1a2b9f440867e9d9257a1573c1f3f, + 0x19d6f7ac7339519c004c1893c15b90c6b50fb09410e9ce523bddd88aa3dd3d75, + 0x1b92f3e79d7fe18dd5a8a7c74fe697b800921cb181be388e65b39cc8114b32aa, + 0x22998601081051242be4d99570e60ca7ff816acddfc3605f463a1221b11e097, + 0x17f81154836c1b89e026090ab505be76f2da2674a77bb65196f29123106f15e4, + 0x27b439487ca8865a03fc7699acf9c74e7589ec1282fbb0eea9f6fc4215fb8d5f, + 0x2ebf049a07d92affe4877c3e4faa5bb176d58c7b514ce03b85ff8eea6b17011c, + 0x14b55de484bf2eda58a874c907aed547c35e892592a8704e330457a6927eb9c6, + 0x2cf300af23253ae125944cac6565ad837e1b4857ac3b9003951c414d167e4622, + 0x11a0cdf58417864a0399eb08e3af0cfca6afe79e831eb14c2c7e6ae904ac14f1, + 0x13f038e1602814d23b07765cbcb44033562f7c8192fd2e45ae1372cd3f9100ab, + 0xa324aa4a2273af5015991b7e47dc180ec2c6cdd3afaa7ca1ffba46e4cb5a78e, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0x2335a58b2a4893de3bb776a21abcc6bd01746d21d60dc99407a58ec99ca5394d, + 0x3792e932762b5353053cd478898e7067fa59e0aa0f97bb5d075b83e7f1068b1, + 0x171f0973baffed9d21be47d121de7717d9200520579e674c345741ee2c0c9af0, + 0x1ff55845a587dee8b90bb11b2490e5abb7bacf3963f7739421b471e1f3cb589d, + 0x6db58db2db6fe63f54d05adb8aeaa9cb89f48d8248e45d647b9148d1fd202bf, + 0x207a78198a8af61712585f9e3aa8fb315320232612f83529fb1b5892c30527ab, + 0xda95af66e6e0aa2f1a0ac71fa29c74d75bb9f99e9458079fbc43fcdddfc1be3, + 0x244dff1663f2935bea98c07d041221ff4b866285a999a04e7badb7932a91e7ee, + 0xf1666c15799e77aab89a2b35be57b29222ba0bcb4c690b05f144b61c61099f9, + 0x2e9b5aed7ff481e79e49c949604b1d7dc241700cbf5d6e7748e13f74f30e5ac1, + 0x16834fb2ba464871b1815f1495a872d63e79504d5324e80b34adf43ca7a68908, + 0x143a59fd2f1e040c91f7230be230101ce4e6323eec738f2906357464515206a1, + 0x43dbd8535bb232d99c3535dc3d655a963324bf70d1a3274e40e64393030471c, + 0x7b166c254454f4b8d6fb5aa80087856a5f3affc248c814703364663f08fb766, + 0x2047d44ad52bb40ba8e9f31f521339de3e41cbc7ef94245e7b9c82e3d5239f2a, + 0x1e23eadfe8cd5443f15abfde942370f48254cf355214fead4e4d85a0722e3452, + 0x1371b1a0c0ef71a90bf7c32118ae414f81d593f95f864cea9a1b60607b1ecba4, + 0x29c9b03f3f02faa3d633b65dbf083f24565eb29e36ed1eee4bc5376889b5a0f5, + 0x11c0d488111b7ed7b91e9be524819faeb74d64619847d9e96cd916a50d17311, + 0x2d389c9b04a7aaa0eba8940233e3630c8b98f061a7565a7d5caaf28a3fb77307, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0x12e351fea34839d65253cbc1cf32d39e34b1037767f5c2b90627d90d73d3bb0a, + 0x2e27a42188a58299c9d8044c410844229d17a11812405d3d35537974652ead64, + 0x14bdf13946d48ef5a08883efab512ddf10596421d031823284426fe729475367, + 0x9a068a755057ee06efb7fd6667bb62353ec9cd08fbc887cf5f4fcb2ccba098f, + 0x519b4409ec8e3a7860ee5c90956903fd27fadae89854357f81cf33fee0e8cfc, + 0x2e810ccf1dd607ec36f7ab647ca38d42710eab334142a8398b5da402a5840054, + 0x233108c004672dd480bed52d6f25174cd89d1a025a60ff6888a978503ddfd96b, + 0x5be8a2527d11c6c19b0e5c5a0e75a0b54c5e21e68c1850494e4fe7784cfcdc8, + 0x1c4d74ec5ad43fa3f3f50702399181ac51aa69d9260f1b32fe7c1ccbc232a0ec, + 0x2c98c881a993b1aca5ee9e7f559ccdf305e696156bd0ad4515afcf5bd168de28, + 0xac8b8f35d94988510c83febbd4925feedb7115380f6c4e167aaa9ba11ae739, + 0x28b2d2b745647c152ad021d9e1e7e87aa179c49626348fcd0c29444aee62d71d, + 0x232dd2860f628248f1b55a1f1b7f4205d5d8c86139e182b31518eb4fa1eba077, + 0x2d45676dafb1b4e4f2e5326ad8f2d6a382ccce3969091d48ce0635bccd9f1f84, + 0x23c9bab33c8ca65ba9579f56ddbd8967db1e9e3530889762e743a32277f4a56e, + 0x2e3f511a8650b0493951efe1029eac8006bb5d44f214508ae0870daf794eee04, + 0x1fadef99b87a98d042116dc8d68a6eba75609dcbba24feceedc576a5f8c56ec0, + 0x13b1c1adee57755d2c3da15fe50fe6332e5d5c5b5929c5ef8ea0387043fc156c, + 0x22a338fe1a442d6afe886f9cbcac11a4f7f9bdd77fb3a8b78dc8368a5613da63, + 0x1c069ae1b1241b93546ccf9d02a0279737dd1065e075da8cb88190a71fd2e887, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0xcd4ceac7e7f2cd68f2aadd77f8a89a35b39e6fe20795800da208139d3a12390, + 0x1c2ee3595af8de51bbd5eb8567f18d3e1db383bfa37973f87cb36e72a88c81c0, + 0xa7c2fc763da1bf375377589baab4d68685a7d3d23f08d106e5326eea97b0333, + 0x1b50d5a9d6db07dd3f14eb594c51c1cd119a0e734a1f2459cf989a47e557359a, + 0x30161bd3b8b78d824bd26c4ac8eaebf0c3bf2ac2a428c274b458406cba4799e4, + 0x7274702734590bfd2fa48046b2b21cd261a226526c126dc9841a00c5b74747d, + 0x23064c35e504e677bf3c438b120a1c02bd6e8edbc70778e46b7e5f00d1633597, + 0x7b4b8fcf8c2cabf527256c84aaccb348d19a3d8e41caecab110f3dcd563d0bd, + 0xa95e011e6866c8550e42efbedd76eddbae2a133a82edd6308f4c8d629d42964, + 0x180517d31f2656d1cf425f6aaae0751054c71dd9df0a236c6c049a3b33cb4da0, + 0xaa7c1d96d99bf95d733baeb6e88f4a8536c1f846730f460731b2074f534ff99, + 0xdd0dfedf6a1d0e3368d8f79d159d585f181aadb93429e0287324179d1e37e4b, + 0x572df3598f8791d83d3401b87b3d6e6b3a778a9a4a33e1b6c24746070a3bf18, + 0xf9cb4e73d3b6c128f629e12d409ecd7048781ea825ac98c564f11fabdff8d14, + 0x1db3c7279ff54baa1b579a2d00acce27d1f80dac5da005ac5a50052cf4ea6143, + 0x2942a1875714a0c00d3b2d20dc216f466bbc448af3a63e05aef6353073503b0c, + 0x2522caff7f2a2bf9cdf836ec99ab832e3f792614b5cef40cd3e9f00c9b2df92e, + 0x1cc0d08465538de8bc30077a0fca970b6bc309fedf4f48c79ac7ec6ba1f4a6a7, + 0x1be86dc6dca9d90b15bed5bf60edea532e1510007055893ccd65741037c814b9, + 0x2ecc73f82062b8a6d91bed0d221022331d55436042ce722797c1ab25f77a9f2b, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0x1e954a04dbc733e4ad843f23a7f402bba126324674450eed047e158c4342f75a, + 0x1bf6934a5502144b995fd7a26c8be4f9507169f7d29691e460277ce8a06886b, + 0x10a770647e157ab71fc08d6e560bfc21954d55647c32096c258e244fec48629d, + 0x2379fd0b045b1b43d59bd7cc2760c8bc5055f3a441fa6288c84a3c7c7488a566, + 0x242557dd84169e034b9c9ece2f2dc4bf4f4b3520b2ec0c62754cdda61aa13759, + 0x24d0e65867e83cf7f865e89a44c0fa4f31df8eaf20194cc9e773188322020fbe, + 0xf08e39c0aca58fd66c96bb21691c0b06fc564cc300040ffd985b0ffdab6ba89, + 0x1c3119af9b3e6b5bff8c6915f68472b22cf3f9e187ab26981b86c3e90dc767e5, + 0x18836e6cd384b031b1a462ad8d0a11c34910f35baa8a92fb3e56f9615cd702c0, + 0x10b2bcb24625ababda8c1c7186890382b9ce83854d7bc4f2460f30d706a4cb48, + 0x237fdf2809ea511ef064a7c036f29c1d555c0b32dfd257334ff535fe42cd81f8, + 0x21b9cc4ec4c0832479f7cc5e15b4ad4722477a5ba013d9d359d540afc5737f67, + 0x258e26b354d7ebe2793cd3fb7c3bf6d170cf9db55cda38f57158d9b865298d8e, + 0x1d48d2d440fb27a8ed1fdf8212e7b34cc231bd2d893402412f96f938165bf3ad, + 0x138fe1103d55fc0267df8380c50775947493bf88f75a73d783b21caa92197f3c, + 0x1edf94fb5b430b784be783f8980634ad92449f73e33c25e9f7d63f3a62f30fff, + 0x8eae1383cf79a2ea6482185fb4b72345ca8689c16e67bd0a253eff22c5cffde, + 0x761d160fec46a8c06e3e055d34791703f805a77bf30042a43b6f04e35dde41d, + 0x2e23c612794a7f8cbce764b156e02bc21f2289396e30ab846536239dc8938efb, + 0x1539abe4d27172e4ab5380afc595d723f9ef3fb7e8063705f9a07c40a67e372e, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0x4d800ab616d72aee2f1cfb8eaa194dbb2bd95d9bc9d8327943da4f45befc2b5, + 0x2207ae07dccbc047ccce5415be0c4941ccd2aa15ffe4f4a8e07a60c0a7fad9bd, + 0x64d711ce20b70d512f1ca107456bd158586fc1e3219d09f3de8fdece43088a5, + 0x56adb05c833c5d1984c7f6bd75b02cfc1c7b21dd7bf6daf1b52522c96978158, + 0x2efc241aa72e16ff31abc7977dacf9a6df53b26217544c53bb87807d5d61506e, + 0xf41fed22cb32a447dcf33e989193fff2157f3075848ed1e46a181128ebb7e5, + 0x169291f2bb1381ce3b16e812c546890ef5ce32c1d768d81264cd719e4e1502d5, + 0x2f9fc1e4f2924d82d17c7ea7d3b09f67be93560ba39f29537ec0c1f2befd4729, + 0x13ac8de14556e9b886de3944edae4c601a01f78fb263730f44f7d9991b8c7e2d, + 0x29a69af8e28052f2c56dc24bda3a5e61cfb3e9c6ede0fdb857a1971fa932aedb, + 0x180e9a2e161d21013486fb8598113f7a280697e89643400cbefd587893787172, + 0x29fec555b91dfa57a42cb368560d4bc471c77a2e236a9d7c9c6aab1b6d1117f2, + 0x231ef485473f733d46f0e2acbfe7e3961d045f30244244ab3bb7165863c1a46, + 0xe6c1b39867e21ef0c630a99754d1a66a6688192254d40492ce88d47e5fa15c3, + 0x2e0a260d61bad61b7891e6306df8b2310d8b8db9232fd1f7219e7fba86597031, + 0x176aa7da52727a85134b313308a4c62994d4149bd6c6fc59d6e6c0f09eac859f, + 0x12922be1b7fdc58e582eb1adc46890c48e10c8550eb8b9b11d8541694ef3a9f1, + 0x32268b4c29827a65066e67d71e10cc978a73e0442bb1c9f67bacc883a3f4fdf, + 0x10beab6538e0141fcfbfa8da4cf3070e69b2b49da1818ec8a9e54757a51b3c19, + 0x36192a82ba9eea93a2f4b1994440a11a556d0d157ae5da57192e56c21c28256, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0x34207380baf33709aed4bf2cf5d387a15f30dd072028305cdce60c1737ac627, + 0x1eb09b8ad28ff81a7b21236652960fe9bcdc84caa6b21549da93a72d92ccbc8, + 0x2545313ea42693cc8c0d6315d8bf240ae624d66f60f6f0a356a105ca6a7220bf, + 0x1269b1b6e6ffd9938f8b4d7c4ae3c7feb7686b9de06a6831fd957cfc3c3bf7b7, + 0x281e84c6cc599d853fcf8ca0a606f70aadc893adf4a4a099364b8c052f169ab8, + 0xaeee3f27983d8e9eec8d6873cb1cbeb38c3d5912c74066bd0dbc559edb12c69, + 0xfdc47ab86a0a3d8e9217faaee18d9b5b86e9d64deba55018f355d3b9a36b6a8, + 0x2c35a627b5540525beacc313eb5733cf97e1ff3ddb3f9b4e8b4f063b686d2e12, + 0x332c87526e40afec8b93f9735204bcacd4c6431c60b0b3daab4fb7f120bb301, + 0xd5d00fda5d7c9aca26fec63f2565a7b64fcb58a67e7c29a64d0e450fb2b956e, + 0x1b9cb4b5f32f1ba38a685870d7a5f7f44370b9b0e4c12ed349fdf28de5f49865, + 0x1c63e1e8141a5a498ea10713d8bd8ebc5d61aad6e0ab492baff25befbbb26a26, + 0x26ab3869c42b4e0139459f133c996241607f280672e2db244466d3e425c50fc5, + 0xe8a1f3050352b43a39fde443e466884d09945cca09f31f043ef872a85511bc8, + 0x51d4fe0ed70b240156e4fdd7fb3351d55841c4fd97d1a4fdfe0910932052536, + 0xb0a1015d5b0b6a572187b97a4427f7e938485515cbe32e0016d11de7d6bc760, + 0xfbfa326f445e39a06bdb999832f75f80114c3ead6206339d7a5edf276ee54b4, + 0x9ca06de513672e4bf3625d0cebfa2286a44737b84647df4154d524528e82750, + 0x281dba97e7243b1d3437c626fda37e43c95cbe3987bea3be9d19860672ed4719, + 0x26de57caaf86357521f470a899d072f52a41043ff0bf242a845b71b8ba0dc6ae, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0x2fdb2e183ab509617feaa6e075cb9de40e5165621c2a4266fb894471e9c1946d, + 0x6188498691a27faf8c8f4a2b3425dada1a87d06c53861823232acedb25d6def, + 0xbfedca0dd5e506b091baae85be99b391358740f9a7c6578c58349f522323a18, + 0x78b237302bdc513c9965872103d4588c8b19a002b784ea4217fb04455d3133e, + 0x25f15182a955582df5a3f58d36648b5cdef4bbbdddeca93eae6c94fafb198305, + 0xa07fd1f3e8a7d1f026578e5999ed3c7d63d5bffe07ff0c96cf8b23e2e0f7820, + 0xbd64bd942a57b8c209d7602bf222a0ba5c84251dde43bc098e938f75a0b678b, + 0x2cbe62c979e608377112ff7050870162a94dc68556270ee7a66e65305d1b16dd, + 0x9da1c5dbe788effd900ea877c8f099af1c03e112300d9e070e6c6f8c07b6a36, + 0x7981ab3c73beaa4e1e775d4e4abce3bc86eb79168d6f157f9cadbbc30ca97e5, + 0x3dced6534fd07a1107d6c54510a07f25c0a10b260c7376bdeb10c4e768d91a3, + 0x988db118a1974fdd8b434549e13ec8654644298f3388bac401b75b4d550ed76, + 0x1deff1662df511afe108d5322ab104e70703d65b729c1dfdc2bc74345d4170b3, + 0x3a1bb1a92965c2cfce4124a8abf82b54e3ca37474728dfbe965f7e04fae0f1d, + 0x281f0cbf3e036b4ae183795116b65070d16e37621d83b3d88ae69e98d8c44d83, + 0x15c4576d8475a4291a8db61a22db870c56b013d0849b1066386e859b996d9035, + 0x675b067ff63a96141eada800b0ad12de8eacad15c7f53e6241feb94cbe87f3b, + 0x201aa00289c06147c4b86a521818881469fd0e4f91be7bb271afcaeb1037fd56, + 0x1d590ada5a94b49917ebf20bdc55e03d0362b3f719aab865957c76b84a4413a, + 0x6011f23c13d5ec3df59516c72371f2ea28e930f73189337762e3d4df3f7193, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0x289927a769b163dd67f7165490a1a4d9fc3b8ec189ad4fcee07368a3e75a7573, + 0x5a0ca87482e1f242157b180cd02fa975c72bec4c25d87f82b7c53e3a6830947, + 0x2b328309cfe721d78f7a6e8634f54524c4eacc42ef998093e0b77c24d5ff9e80, + 0x1ddfe1d1e5e9458ffb1d342e1b99a73b0083613406f932d7abadc8442204c061, + 0x2da94a9b44a2e2681f75ee004c7d9cab662ca66c1ce78fb2ebd617ce449ee43f, + 0x1efb5c3e6f22f498ced2f4e63c366b9dab0cb06adc4e92fc3f868709cdac330e, + 0x464f0cbf6ac670c19420e79606bc447e259f8b203a4ba15f72ac220e853c884, + 0x67e3c61a95e28c26b5628f679c7843e1e042d7841a670219194e99dcc618f82, + 0x2d1ec49939d788c853f85da08552dd458a48a197cf0b023157ad04a49a72a28d, + 0x25c69cc3ab094c56e86147024ede9ddabf71ddb294ab37659e9b2be22dd9e289, + 0xbec17f5afb43e6faff2a6b09a02eed8455bdacf16ca542ccfcaffb119ea2c0a, + 0x543caae6f7afe71cde9b817c9a746870d2cc62d2e7e1c6fe7fecfed5a98978d, + 0x142025c358454da1e1cb0de99504766fa297d1f6fc62deb14ae0bec430d58087, + 0x12b565ffd06708fd98bf8353991bd236bdc518c7fbb243fb05497ec7ae08939a, + 0x12f287f0f3686375ba8431deb018fe9c28382d0b3f6d42c0c8bfef68b99b0639, + 0x1b97a4c6e3b1340d563513c29d704429098877af661ac3d14a8e5caf2ec67622, + 0x1160e192c3592d85262513d57850fa5f8ab05a95877afcacdf616cf742991fc, + 0xde9cdc2af5b4780acd93ea46be905a8530e8bf89a97d41041cd39fa90975884, + 0x29a2c79a9dc7c39e8ae57cc00010cc2aec866d9106a8f2c0def35fbc29b304c3, + 0x1b39fe57a5648b6b19ed40ddeeda02db1a6a0590bcb4ac75d52c016bb5f004ab, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0x2eaafd2a94018113bfeca9f6f909c380ccb8c99788645cd8169586e66968a6e0, + 0x27f7e86e479c9eb87a4c05e80dd23700a81c2e720bf0e889a6a5d5d2f2a385c4, + 0x15fd4d2d4de641f8d803e4942f19aad8bf6b01a1b703dfd0f0b51acc263aed92, + 0x172a8e725dd29bc4e28ac7a67a7f86bde15c58b1fe2f87bb21d06349bbf6a858, + 0x11820ecad02878ccdd901bf88011203539ed7f14c17edf151f237b8f3f357bf3, + 0x157bb0ec622781bd0485ed79ceb944a23eceb119dac4f88f3aa4878f082f60a, + 0x1a0c8beae4e98f3c36307ba5a8ecb345cc5ff4d33963002e42b36242c7ee6f11, + 0x19398691a16329089e7dd608cd6ea18749597908b9885b7a3818feddab8737f9, + 0x2c92297efa4d689e784dd5ca22480de59b1ee91203331f44dc2c33877789a888, + 0x2b05adc1b6cae6f7b6a2382c527c9e486e825d2f6ba1b1f9aa395fdc793e9bbe, + 0xeac0d420eaa22d35e8f1dcf344a5bf8c05559171f5b3d8490e7cc58244b619a, + 0x1f14c4c41d337360748c3f37c2e1c72f831a6f811893d188902688b43ff7ba89, + 0x2dff4909b43986a532997bb6881979cc68bcae8e01bf9caa69389dd064a21288, + 0xc5cb5da369f1f4f874bab1f706b652ef2c50b297b5340f7f6c0fad98f6f41de, + 0x13c2c78c6e2b39691d5e7da33ce14fb2cff83ce3577f1909d2a9b1b73810067d, + 0x8bcbec544fb37718da2d30fbd757ca63187f342440c8052bd9510314f6fa22, + 0x12d845717c2b2c79c55769851913284ad56f2fe4ca359ee39e569cbd52c44b74, + 0x10c0c4538604fe7ad96a08ea533aadf5307c89534a51dc4d958f769a0d225963, + 0xd2a590e3fc8aa2260656e13a383726d6490425ca80eac6481467c17f1050265, + 0x3030d8c3cade8438d664d3ebcb0b0889f57ffeef914c655e50cb68ae14c2f283, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0x1ec953704f6bb2e359a38b99d230ca7a4c8eb37e3479238a282da769f0425beb, + 0x1eb6626b17b9fe129966d1ae7f272514826a0bb877d54a3a7d6fea8e46c94914, + 0x2c31aba1b873c7d14d82ed3b033e75b871a7264f4ff1beb961a532d8a3b50698, + 0xdb6e1d43e7479d449ea8e0fa42ef14a41cc880de1c7699cab480edd8a79ac7f, + 0x21d8a97ad31f1192c8d87f08764c4f9a8f6c90940a6d444d922151dc812f4275, + 0x29bd140ba4c910a6d297d316c9bb12f3a67ef0acb14f68af7afe36dcab638ca7, + 0xa61d2fd60c57f574e19261a4a5f15b98af58e10836f3175d48fa7c361e98ec8, + 0x1d593a571d4d07b6b677c7c987263c4f9ecd5d264071a49e6a65a9fbea46da81, + 0xa764ac4206cae37430c7e6554f45e251bf3a4c8348e686d3103d44a3a53b565, + 0xfc4c56a0e57f381acc4c3d8ccc8f9bc02332375f6a47343896e019f2679a7f0, + 0x1c34df18abe2bd65c68b1e40a634311aee1429b49de0ac7a0ad890d434665a9e, + 0xfa890b0f4e407242899e2812dceefc2e8e5daa8d41964612d862b182fb084bb, + 0x1df4265e4bcb86f8df10427976b496708404d3eb8370ffe06d2fb5eb21597ab9, + 0x14b74c5d557ec1780f3a0409c6d53b3b97190734d6f48b60ea42c5d54c194ab0, + 0x112e82b702e99d25a62f79b82d5f0620605381ae21c311eb3b9b6407ef712a27, + 0xb22a611ecdec54a9e15a98fbaef9be8bffe8c6f65b594fd8647ce0d03b1a819, + 0x13552102754e83cff6a90cadf9a9fb9c9c4704c65200cb87144e7bbef93823f5, + 0x90872282ea971f0593587dc8e0f8b7bbdf36a1a762b9d000353407306f7e732, + 0x101e86c640c3bb179c0805a76ae6f326efb5ce0c7b584c0aeec2ddadd727c97f, + 0x17a1236e80618f661c6b0932b1332b40802aacd5fea74c8575ab87a38bb7debb, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0x12398407948eaecd57ed99dce52b4051d9a7f862241f682e26f29366b26e8acc, + 0x1846ebf17d453d52ee6bc5f217abe6a0d5aa43084af5ced178a081ae3e204fa, + 0x2054f2993d487237bf6e4a985c3abaf3ea8f0578ad5eb731f94a0dd533e846f, + 0x1911b97db6f1c83692aa3a44172aaf316d863adacf721463e9b34e93c3499d5e, + 0x1e7f11887082042971c2cf546c3fe7031d955ea7e371cff4d270e56aeb0a162, + 0x12170e18a97a2c89b045eec5263655c47fb08fdc4622c5936d0b9d2aaa721cfc, + 0x209b3d0342a6bbbcea6b3ec256daed1605bb9afb9adcb0ac9ff0d409751f136, + 0x6144e781f4197e7402726ed1e01d1a9df01807d8f679e5bff27837902bf4b85, + 0x129444fc0f4808af8a64b51d94d9be48764ade198781acd87360efc9dcc7a8a5, + 0x1f12b62b42b308fa0b8677bd62e9b5fb6644cffd6ae43eacad6d127f8437334b, + 0x2a1e7df0ce57b7a7c3fcbd73c68791c5aaf538727082f773c41e94fa24433fba, + 0x11ac54cbcf0e6175c34eb7e364adc9a26eea739c22aff79208ae371bfc8b1cf6, + 0x263230c117421eed84437ed926810a77a756789fc8b3cace2da917ee6311974a, + 0x10df3a59e7ec06ae62a749bc6791d1b9b2e7cf0bbcf519f3c023e543514e5c5b, + 0x2ee43f7cbc305d64cddff15cd91b7f6dbc0425e706b107e6b146316a8ed4c433, + 0x15e9ba236c3bd1b8efe4391047d6de8b2d8ebd45ca5912a619f7667655a1b750, + 0x1d74abec20aa969ad6f1991585c09cf7b2e4b68998a748fc84fe304511c6b599, + 0x5ae72091e906e7f9d94e8b5e00f4dd0b43039d0ee9ac1598c3616c86d7ab06c, + 0x2b548c790a449adefc53712a777b2b90bea7061df2f57d337b9f512940bff3ec, + 0xc79e3413149346cf672ce76f5181de7604163cd00c9a5263fec43477ba2fadd, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0x3017a09725154c2672bc149b4bcd370771a14807833c069d712618e207531b30, + 0xb93ab490450416ec4a761155768efac5d022a8b3712cb410b78e43826dc07fd, + 0xf7ef4a57e815865508ac5e78bd6ff37c11dbc4bf0773864e943b14e0f79c872, + 0x28d3598fc9de7f8e645588886736a239902008f4c0c54525e1927cf66bd0a047, + 0x178d2dfede02ec9735d83ae6ecb07d875b78360c45d9796753b52162050f2473, + 0x2055e88d1c4873c3fc760261b724a8c8c852b05773e03e4781e03dcd410c878a, + 0x201af7d279732ff24a7300d4a63a327a0d152d481e75701bfb1ae60001808de4, + 0x20b9d7719511885b8e03da08d1289fa02923259857fa5c51a4fd3f6bbecbe8e4, + 0xc0c12d9eb25cf37cd472d0ec9f4e283832823607ca823e3ad30de69cb10bd97, + 0xc413585abc142ff58981d211bed7b8d7fbc6c0538dbffe36105ba44e18b38ec, + 0x1ad95bcc4eb2757c070d732f7f27ca45f4685886ec1a21e6222dd7b99487aef8, + 0xe9cd75323a37d831825a99061f0920e6594ae3e3e94d45a3a33aae620d670ab, + 0xfe94376e19c40263ded62340d5042f64e3708e0c556ab677b64a252de7e7201, + 0x236be50f0fe1b1545413d3a6d2c60cd28cb80b5cecaf301fb32d687ab8639656, + 0x28033ec35e8541ea37b843d7cd1613c7c95de6d6a3c1e7688cc26ac5c0433dd, + 0x186eea9c433f8f5ba4318087295fae6003a63a5250cce25ff3127ceb8ea62226, + 0x1997be30d551c31424dd592c2df897dedf13631320bf71075ebd15dd0eb234e1, + 0xc86b6e4ec0b7673c81e2a33cfab7f5ebdcf740fa723952f5553a60d7866c0fd, + 0x2079ea58606d87fa8eb2de37607a65768044990a0329f877b16141d63675cc3, + 0x17d722901c37847aaa1f74a31f9948d916c880d547bec7b0f2b9b1957ad97934, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0xe81a4c71073cfff9bc2053e730c22f6f04712a44b6fdfa3e5d031ae937ba4ec, + 0x1b643ddf9217a65dcf59a7c4a40f0a8ab16d034cc1281c981940d2ac528c11b4, + 0x26cd2f5364c6d09211ed0c9944602e97e582b47e93f8877923f0367c25ecb766, + 0x14e4f38d385b57d8cef67ce66e5199f2fdda3ff261a139a9a421ec1f2bd540b2, + 0x168e02a829c74f8224d6ec0f2a87b93714d60848920306ad51309b5f2736c998, + 0x2fb61a6b4f14e47f6ec64e4acdc941829a48782090c2f399435382ff67b7747c, + 0x2b8353e21e9a695ae8b58e8a11460e8dd7630b073db22e59ef804f570e8a55e1, + 0x29dc5e33af36ae34947c29d674778729ec99b8ab4fffd5c3d957ce532ae7ec10, + 0xf36d6ea37c6705c7ea7bcc34950a883ec6505ac89b6b5d41cc743516e6876, + 0x2799caf6a25f94e81d9f8e362093d9c5440aa9be99dee55c54f7120492a40cfb, + 0x2bcd01c7e5c45ca9764c04385a1636e247e47382b443d73a905ece066790e08c, + 0xf0d76223683dfda5320cdafcc711a2038f7ef465f9847a8c1c4904d6066adf8, + 0x2974f8366a339e664e9b42672012b8ffae9079796783a178ea0009179fd6577b, + 0x156f973d0d9d785674e3b7e05e96c5b11a582c75655082796018e9dc11bc5b64, + 0x19da910e2a4be9d039440b18d700dde2f65455708e7cafabb61809e4103c87d0, + 0x2cfc58b0abe0def0fb166d114edc3d0d3cea117ac3dedde6e6f4fe7ae4768505, + 0x2c0c40c61c6598dd8aba498ad9199f38bee4e39fc06ea761a2de890aabb5d9a4, + 0x1e30543b1ce12e136f719a5920cde3bc35e1b94142a993b522b96ea9703d4cba, + 0x12fc3e01e274c109f341fd2f9869165284c3c7567e2604dd638d0f2267d63db, + 0x2a9680b2eda565239cab76b7b7aa8089f732fe9f0167c9beeac9ca8b146387f7, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0x1421e02cf82980b68a9c81a28eeb397e0ccaf80055d5aa562d9b5f68bbebee41, + 0x217804431d1cfbcd6e2ae64af07ef7eb31e21baa352bcee45c73af5f07db8d33, + 0x2d15bdfb3a952df31cade21c99f2933edaf8d7aa3f69fc1a16a3e6bef6c7f5bd, + 0x27f5885f9ddc3ec7e7f2b43d6cb0c0ae1e0e2555ef46cdbb753d13528e239f0e, + 0x3a37a151a0a4214c78b52217dfb4bc323c833a25e0c6fa5b2c9c4e1c3deb674, + 0x11a6fda46b867456af4f194a5f0571a3053adde7288f9fa84793b3516dc1ae4a, + 0x24f22cde459accabe8eba8e9608341086af4cd4c04da2440b067cf6ed63b196, + 0x532b9c8c9c2627b9822eb7cb4e26ba7356c4c867c42889e19d80903be433a1a, + 0x7f309d33a4d334ca3179048797197b7f6729a3518735d608057330342520b0f, + 0x947f36abcd0fad800f8abf23edd43565b6b6c26b7e244af6527036971340f67, + 0xbb49c33a2751cfb8848554d24c216ddb7e6b88234769ba9304ca0bd580c2493, + 0x1f791d5f90371b44b925e5fe04c2e994a584fc427e4219f551c35215e022fa9a, + 0x1618299c6088e1d3a91f6cbc0956c6afbc3c38fd691feadc8d6787ad52d976b2, + 0xcd4c820d82ae74e29d1915d6eed53be77e06c36f27598cf78773b06b362e029, + 0x158545181f2bd7b64bfa41c26e3d4f5917ef52851c0046a7f18c26a0544b2ef5, + 0x1af91ea8fc2319db6925b994492b65f631b416992595c9bfaf93ffe5839d86, + 0x26c03eac9227b0be2a855f95de0c97d337d763af75f1ba327a9e409cd5a718ca, + 0x189b176cd8975d36e0ef78f2f39f8780769d4c7411a5ad2724927981ccb1ab03, + 0x41d9c7ccbf82c77e0580400cf1f9b530aefcdee51dc5a1a4b5a142d4170c6f8, + 0x274278f69995b40626a7796e2f70b1d6b52f9fcff1dc50967080d9f0332ec782, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0x1c9a29a3fb7f2b95c153503276233cb8b1e4336434661d97a25389fbabf3037, + 0x2cb5533d1d73b7b385328261659124419a9a7967483f0e3a3e63e3a4172d1712, + 0x2e9bf13980f73bc9d03f4d644e7757f4a254235e659364b078607b15841ff222, + 0x1467a26136dc7c21ae1d2eb531fd9af993c9c0f7923a0f17683babf7847ff5c7, + 0x188210cd164a330cda3a1ec91c7b55c8210ddf706cbb38ede5d8b6ad98122539, + 0x21789113e7aad51c02f8b3831e2133e1997ed31239ca267c6682b003d00f46a2, + 0xd6ae72f4cac38afb4f95f69e9af3571df0ea4d7a726ec3bad4c9c3ce743543e, + 0x29f63bb7c7b8dfc1a470d95f246c1ce2fd3126baa620abe230e181c191cb7cd1, + 0x2f0fe6071d605469e17000e29ca7b618efcb9fa7f5b296f7312515b7080ba1e5, + 0x2c993b62a92c8ceb812cad18de9b0ca96e041be6b12bedb8f64797a6b26fe167, + 0x2fa9ced73852f04ca937475317f1ca35adfc8c2b89bcc4ceae7fe40a28f05896, + 0x130264e8ed86dcaeec0aff16f605f7fd4577783b348758655222d4b6c003855e, + 0x5137ce88eb7162f2c2ee9fa54b56b951a4479f53ffe656fd6a5ff4c9a03853e, + 0x275c55e247d72ce00068db24abb786eed71968b226330472f6c8a609f2dee36c, + 0x1cd13cb77f0c869c445fa8f9d6d49189f7ef7ec00cb4c00dae22db33c763197c, + 0x6d9b6b1fd1e26a4ca07e71e3f9d40647caa0ef100a990ff9cc4b73ecee81bcb, + 0x169dd62b282e78ff51548fc12731cea18b3bb95e8262d139b1974b2933a7b373, + 0xc0653c4aa7fefb13ab5210cc32133a9faa456bbca5f4f0a4f4a1b8d14702afd, + 0x2ddeae46a42784ce32df7b9f7118aef9f13552acac2046005af17748815c23a5, + 0x2263646d28d39b4b0ff6d2243ea0e67239533523f83fa0f4f6d575bebd7bcfa2, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0xf91c7a21016b36d9010165ac8b1b7169da842bc0a274adb5abf99aadb62b936, + 0x1a2e0a81ccc7ca01220f2e7ecf9189a5f2b9b46e53ff92d8cd238b5d195e743e, + 0xbf18f381ca8ee6f9ff4bde5897d635bb27dec564132e744ef8dd436d1cd97b, + 0x13296783d0803516483338c7df1b5fcf81f710522c631a1d6db1a1feb7efe67d, + 0x21c82f469bf6605a5ee156b2511e0f67e9a242e3d1172f826864a0606ef594ad, + 0x28dc10865221c98f25307ed8eb2e235e27d5a5d41ab3fba09baa0909fc939838, + 0x23cdb14dc014cfc69098cffe231e4d43a20c6b3e4db8c6d17fc3463fe94051fc, + 0x21edeea093570815944d629d7ab442d595b6e468ceb883687bf4a1ad49fb2968, + 0xae1075937d8413c6471b481f04b5f6da78c486c9ec3a39f166de8edbf6ef5c9, + 0x2fce3f0792f5cd047fa8bc04de4cdf33e1fb7813fbe14320cf794b05df31e9b5, + 0x19d1204d38bebb4547c168a8b8e5f9266c5c88f9d30ca6097a5939ec41366bc, + 0xde612e0e3ff1ec8c10f2f6683274e98c095439b57c178a5bc0c322d94ef05aa, + 0xefa0f50e18937701c781ab79f263cf9fd325d58dd4d0936c592867f49707561, + 0x22e1e777da6b3d2afe2a2f6f74ed2487163085e736f587089fb120e5c149f8d0, + 0x18556105a08859a354db011951e9f9c5967a71ce648bf0aba15f2a559fd3976b, + 0x1a5931f9bf826e643d72f1e85104e5108ca339af493cf5b1cc364552a309326b, + 0x19473fd23dcbda0867c0d7655f4a2b99dd34160fd90b3a12dba802b661dad14c, + 0x29c96a2d870db1de1e35ba02b37449a947dcec5e3708fc592414acb59812c708, + 0x157097a50fe704e1f4c54a55088edb174721db69c7b7ae1b7394403ce694b789, + 0x21e90e34302deccd9b3588cc6c5bcf0abdb909e8c75bf618bb5a5334af7a164b, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0x1d31a42740e431e210fc1553f20308cd05e93fc59b6bf166af395f9a66fdef38, + 0x7d5c120df5efe5ad44d43cf7966f6260b523a9b25da639017e7f14dfdbe22aa, + 0x1e4a39cd76190bd1b656e2982671758a893fc7d65985929f0c914553fbe793, + 0x2762072623790fc85fea72d6c64a298bfb16f90ca429e91a1db2dca2451110dc, + 0x144554ecdbfe88dc6f0c11c5f6b11fee2a86b1ec4cf9d69750091a7835ed3d20, + 0x1983b95a2c8b6fc3734c7645ebb497b942da887c3f91c054fb1a48d3c8a1fc2d, + 0x1113d1a221def2da4cb7faf3684ceb9f6bd2f3b0f52609bf08b2732252e9294d, + 0xbf64c4ef1310f286504c25a637ec31686cfbaff0c10ddf272a92f6fa8af8441, + 0x1209796e263e0d9999996e9f742ddcc4d92a12fd58ea384fe0a639da9334dcdd, + 0xb1eeb6c4cd2d793bf5e7c27bb55c1ccf4a8d010c6e6fd4909619960ab127655, + 0x4b05da50f761f6e8b2e065c6c6ec74e9277ad16d1829311bbebe773bc234a18, + 0x328086aad9ebc7aa0190d029b1b9ff8c89bd85b90206799d7f0b9a67806e99b, + 0x1ddfbad99857e4b84449e1076c3ff7a80585378d2194d944ed9a6fe227b16b85, + 0x86cc93c30e9bc4bf90c09dffe4e3755ca2272a216434ee6df144c2414930217, + 0x261fdfb4046f9f04902356a5682d941d98de74d39de11374bdc24fc441d7946a, + 0x21672ca29365e252389c40a058d9af3cd23d84e9a5c4c405b7197488037cfc09, + 0x2e04c3ce66b9cfecba87989ded13eba5fafb48fb63088e48010dbe8fa1638dbf, + 0x2c8b25d7c74be5b163c04e13cbc7478735c966253677c689ea1819e760b20aac, + 0xe9cd4551fb4ace8e62491b7e6a32d6ac5eb57fb5f801de1b27715cf1c770216, + 0x17cdc28c38b48f61a48be7d1e5e5c57e8d3caef8f59159cb8017b21d67be834f, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0x1edcbf1e8c9add9f39b44ea9a4616fa51a90aa8d376e251e034a309dd69330b3, + 0x123673f7bf110ef3e41b81a4450a12dd2ca03a8e2048aa76f46be766192c68fe, + 0xee62eb21957dccda2e276ed02acdca3cf83ef2d381de42a0952ba4e2e71a086, + 0x67c268f3b750898c2a26b57a4018e3be45c9453001a6205ccbb4abb9a07696c, + 0x15a74bcb36f93b558f2f215ee8d41c64c4780df231ffa1b991e116f0c6e545f3, + 0xfd15b70fa8970f88e689bcfe746a1357b99a5b73354129d3d49673ae432210c, + 0x217e872910c020e9f11ea5437b1dbc0f45bff9a2c050bcdcfa2b6c345ac11451, + 0x1d12a9b49accc9f63862064b6f3d0a2510aa99f1d835880cba6ac0891e172578, + 0x2c9baba92c77edcd883f32d4c34ff1dd285e99653e602c33ed3a6ebb65e70a0b, + 0x2476eb407cc255bcb6509912e6748cff7adeb4cb933993b4f8c9643c03988fec, + 0x629b9717c416be51a6bb98c3716043450d39fc02078e1498121393a09663302, + 0x1b8a88c8fe80358d0e1532f7ea232f1716e561326b5000f53ae948fa3eff7e78, + 0x23739fa9f1d477e950ff4d63f82d632390546879165819be81219773004dfce9, + 0xe7522fcd267e8fac57c87e271f4cbd13d488f4c25aea6719c2a17cfde4aa8f0, + 0x58a36221cf3818847bd604233233e69a718cecf262baa457cf1e5cccb9ff6b5, + 0x9e192a9e456d483afc81ea5fc9cf93bb91a03334eb4d239753802785c6c8fdd, + 0x74cbcb738b033d9e9be837569ad0dff3d8ffc1eb3ede44892566568cb66b68, + 0x283e0b8b91557645c15defd2d8f6e21f27621adae3ffd0a7d7e9f31359110260, + 0x10eade70c487ee2cd5e43d51525ccd0f345a69ad735b603cc108c17b498152e6, + 0x2f01b82b8346c4257c16eff957b22028c5502667fa6874ce956e03fb6939f21c, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0x664e78dad6b22d4333a1f9ca0ba708ad6ab875efa8e8997a0a8540a2599b0c4, + 0x4e1f57eab14954bd0b21619ace372b8d8aead861ac55f082aa3bc1d8245074e, + 0x41d00073a80f790beb8d4b4e2ac64f807f806d5fe9057aa196f880e653e6c78, + 0x2d2d71f2fb3d724683423f92661c8f441565d2e5a878b47af687fb9b76e1737f, + 0x2c80f1f732fd19836516ecae7d53f145076edfe857a6cd0749b85406ecfc14f2, + 0x2c4c5978cbe976f81116003e82010a291a0082dbd92daacb0a39bcb060a8d5e2, + 0x13e3c874118b9913d81f2d8bdf4a87a01d6e521d6548c66d7c0421db714dffac, + 0x1c0abdb801cd736feaa3fe7f98515e72f7a8d72ef56b5952e6a0e807e2c685a6, + 0xbd705c574e698fafc2d0979e92e9bbf0ff92ecb0a71378be168bda88c33d0d0, + 0x49067c522e1f0393a320557b41676f2539d7815ef2b21fcf310cf626d13a133, + 0x1989344c4aa025dd6a33c0f2ca58b22ea3f49ee5d29f0150ec05da44a6babd2e, + 0x2059839a6b9192e77c6182e6e564002b930aed9f328d24061701ce784408e3b7, + 0x2e29f425e322f7780dfc808e679480fcaa0761f752420a49075d76a085e80e28, + 0x2b310e22ebc1bbfa6514fbdee2a48cea36c1e938a6927486fcaac8201ff253a4, + 0x243b6f33e43a7d1ed19e7f1b8163316c0408e456180d572d52321b622a2296c, + 0x3028c94e563bc654584b3f335b0bc3312ec0ff0df98d3c7f2d02d710e1c7642c, + 0xce5a4699a96b251fe3c809248875d0b1d60b90cab8a30ec6f882e5ce1823fa1, + 0x2b9f25a7fb74acd52831e38877f95297970b3086d7888a5c2e1c11ce1fab81f3, + 0x2bfb58abfed4844f986fec4419dd8d83eb0d8a097b72b84c81c72a9eb4e4f7d5, + 0x239bc1e4d55fc6ed2c1e41d18252c011fc588e358fe839e1075fb344ff366d8c, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0xa948ca5c1f9c7d679c476d6cdeb6483d28b8fff1f4b3258aca45312da96c7d1, + 0xc5c83d7d624699c3654b32ca98a4da4723c4601cd7609db406bdcc5a9634a9d, + 0xfaa398f6fc63cc36b00addcfd69233489a8f96cac8fac8d91cc3c3b502d2e2e, + 0x1db588b11e10eba9c51ad6d4d990dbb580c64c0bf499a3b41006dbcac277e1e7, + 0x1cb8fddcaf050feb6977ef7fb82625d63f7286e4a0bfa52a9f601de563bcd96e, + 0x22154748d72b0e00f0f33d6d49e08b874ed2c638fe4c33648adf8862748b2f71, + 0x18bd4153a10ebedb78f02b14ea2663a857f458f2708394c628288cfbc802b043, + 0x111deeaa497d2d32e93d6d783dadfac2726f8487093472ec4fe8c36bbe2bb5d2, + 0x12edd647677abeaa0d99f2e4596bd64e1604f69552b6971c8ac3b44e7cd10a2a, + 0x2a1d5873e48e00abde4902969a921782430bec7be01a4284d0455219675df9b7, + 0x1470d1c0f33d2d5e2b2098376d16cba0738c4fe278ccfc3b824879535448338d, + 0x16899463366b193f0dfb39b35df617118d55074561482e0a91283bdf40804051, + 0x2af12631ed9ea59d387e2b2aa14a3ae1d28cc496e7fd28dc9cc149120108369e, + 0x6eefb335586d1eb862c09c79eda3712bf64ee5f51913c14e64787f59ebd4fea, + 0x256768779e0e07e677ca90aa7e514bb6eee69ceb47e749fb90ac20923d3af52a, + 0x5ab1585ae26b10fb8645be74d3e1afe99f25546e0708fd16ee2493844574dae, + 0x9b5ea9a096902a104e5b1fe5188a98ea78a373e7f9bf27f6218fd5f71f6e6ae, + 0x2d34bed47cafecc7b37ca25901e9f5e3c658950001d728722dc56b71e2d4619c, + 0x2d0071d201824d43fb057a0a523c701d2b8a37278b5178c18ed6910cbdceda12, + 0xa770d994f92bda5a4b63e65ff8cc35f59ef5dbc20732e1580f703d41b5b6281, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0x1949dfa21e6b27c70609ed2bcc7aaf4f6244e289500c48fd1245566837cc74ea, + 0x18eacf1750c093e10b18f45702a42766f1803f4d2ad79399b86856d56d51f25e, + 0x29c3379e427d4e89862989d63a72321fb73197b029092ab8bf24c127183cdc8e, + 0x29fa50d3448bd783cc59afe8975b7da38d3410fcce680210b3295f8af30929e1, + 0x1bd6d35f109a3549dc1da7f96953f1c38f069e9a44141e85e69908366cd65823, + 0x2a58f6745b90dfe97d3f89415e375c43f464351bfbe3d140cabd8a343313eba4, + 0x1e34e898a082d5a1bb452870e41bd67cc5932031ea8afbf460d6fe4c253ec6f8, + 0x1f2884e10b6e90a0bb15c6ec37d269489c35a9fd5f2f8a548002cabaf189be32, + 0x1297717d266d0f55d1a8d83e85c22948a89227f47408b0a6bba88cad4e4064fb, + 0x2b9d9801a1b0a616582b65b84d5b76da1d6f428807f074108cce867bf1ecac7, + 0x701f771295984199a107564c0918dd3c397380bd47e0a9f0cecc0d57dec9feb, + 0x1a294c810d83e3f3b9bcf709dd22b810055dd3e6a11e456b284dcd40e084a263, + 0x10103201721be8dfdc55548826c8f2c6c5ac249a66079509091b71179eed1d4f, + 0x22d656009cc9ad0ea9a60cbd4eb058c820fb5387714d8b4ff52609638f3952f1, + 0x1d493a429f8db9f3df571b9eb1d25d425a09d75e6bac7ea1c8c0da141445ba5d, + 0x3d1a76c0fecbbd1ebc3b20370894284bbe97b8cf7b14bbc95dca839ec9c4c8b, + 0x230688c1f26ce65d683b5a4033cc5b781ff38d4a4e28aaeaf57b495cf843b0a5, + 0x159c9adea02eeb1276c2e1600930929edbd7e47b1283ed273db5ebdc596bc672, + 0x1abb8a81b4629456b639965a0ffee6ecaae145990d97b2b05546f47fa416e57f, + 0x12ad1b21a9c02da3018f187ac6a54e376f8f71fce321933f5ec8a55adbcd0ee5, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0x3c6c55cca4740582956cee40ce3053e89ed882ea253a366d07dfc9a508c2e78, + 0x1fad53f449b581d0ed39dd41975d9330768364c1a97d9fd511d0df16cb3f408e, + 0x1fe8bcb3f7fbf9c21fedb5a0ae4dfb7ca275d535c7847b23cb74c18251b726ec, + 0x218b93667ede394ae16efa07315ff7616f6864cb8293bfd3418f9d5b14756396, + 0x41a688c1fb421db3d8716a64fc39d0e0677a5c43de90fd04dd9f3622baeb3ce, + 0x2987dcb79171d214817a006127171695659ea28858ae18c6fa8e505a4ea02033, + 0x14f45ac12d071af305059de0fc028778d5c1c8afb476d5b7b3ce2ea6a5f3250f, + 0x959f1dec81c5f8225c1f2ff4ae2c67c73e4d379756f40ee9f691c82ee08c6e9, + 0xac0780131779ad691069ecbc4f80886c0bd9518d9e04b99146d29bd7d9ffc9c, + 0x2a7e23e5aa5668bc719b0cc26dcf781d2ca359987f1bd6f9099b953751c61fbb, + 0x92c0b897d36323123bed6c99dcb3b50e397c722cdfaaa9bf6740907a4b653ea, + 0x29b1674c1e4b705e7fd93d10a380145be75934710cf6b43d24817ca38699e702, + 0x25db198e1a5de34b6974aa38ff53572ccc4036447a654aa7f068602233cdc0c1, + 0xff3174ad5ae186606ffacbd55936b65838c2be6a635bf8c9941652a485b8c6d, + 0x1bafb08bdbc32bf6b81d2026005e3ac6390ad3e36f9178be21034262ea674e90, + 0xebcf6fc297c34138661ce9235e7c0153eda1f0c99173970442976ff849eef13, + 0xd729230e5d6913a779746f2975e35197eed83aa613b7f9dcbfd2f713b8740b7, + 0x20870e26b114e1e20c70ad2d6c3c29bd78918bea5bbd7ec8bc0a60980e601dbc, + 0x84a3105ccbeb8137931901cc0a48ca7426e5dbe4d0095c11d63d0f91c64dedc, + 0x1b1e9b1d59d5f4518412a828475ca50044fdaa1c3490491bb508d7296436d5bc, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0x1f4bea0f3c5dbf0b4261b9df35e5cf6a5cc36973d09f0b35fad3dcd0a4c69acd, + 0x1222849342a144de2b23e8bd848ffd096cd3332f57a245dd3ebfc26032a6186, + 0xca7b33f1129a98d404e882ed0a70737543706248c7374d9aa6470583b24ab7c, + 0x18f80a875ca2972a4d13d41d81a1cec56cf384780b5738e59988d9aba4cbb66e, + 0x2428fdee2ef9912f4693ee9c2a59e82c625e23e9af79e990dd7884410846f8e7, + 0x154781a2b5c4401f6ad2809fb9ac23f3136a8e3950ea6e3f084600a730c42d95, + 0x2c554db641533606c10532eafe2439e48d2925c9d6e183dd85f0c24986ae38ef, + 0x3b8b288b1e1a1fd2faefab9b4e00d9c503f8574e67112bbe603eea37b97ec18, + 0x93a9b03da561b4ed6aae3a98f4d2a9d1d28146eb0e91464c25a0e8f2f6011c0, + 0x108843f8d4eee7c9df86bd9a2dcf003d3ece8c1fbb2db80a0e225597ccc54286, + 0x1f043a72cb5432a4c78f14505ee630bbd2367e83f18db047defb3ff1a495715d, + 0x15a8fb06e0c14c181244b3f43d4967e28ba32bae1e84223037abb1524fc26413, + 0x1ddbc950967b1769cdb4f8684b34d9bc25b04deb0fe5fb117ad609a5b7f4049a, + 0x246a58e326b240d18618908b13785636f051ca1c3d5accddcf7cf4af1362b5c9, + 0x1cf99a40b8265758ba68441a45b4993993d732a8b3b88b4d983a62044c0bf7db, + 0xd7de5619f4c546050439e79af5f2d0b964ec40ac92ab9f33c617623c9d0479, + 0xe5e16504bd5429f1989950e8f41adacc95bc94789df4f29eb5c623a9ce4ad87, + 0x41f35a7896a627bb884f8fea782cb487c872dcfb82dce7d0e6941765d1ec149, + 0x1537debc183e50b25642a94332739b9dfa8610ef8297d963ad4f25114897675b, + 0x2d702440567bcd957920abfe3ca1796dc105a9d6d69df68f7040d45e14825154, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0x14849e30e423d2818b033824be79e994d3b294a7745d47ba7a04412c976a4d86, + 0x136803dc9b44527a2831afd600b224d3be36a4fcf1f1bb12f6f3d9c78a49b55a, + 0x28ceeac4f3b856158657defc6ec2d98ae8222838625951aba51df3d92323af9d, + 0x24e2a9e2a33795f29eec4e3e5171cd1a4f102b387032736248d51da2ca097dba, + 0x176b7c931c84fc51a695bfc635c9b2d7e38c0fc9e39119a5d270be388a7ecbac, + 0xd230fbc8ba30ea43febe4d7d57cd646c1679a1e1a8066637e19d7b5f783c465, + 0xa3d177852fb1432eae4cea8005dffe984df233705a362ea87fd318658b1b10b, + 0xea4e2627f1b0f14a84fb72f14025e3f2d4087b5e23e197b4be18de9bc5d07cb, + 0x2b5a5586e185e6aff9ca42ddaaf4a48fcbeb342a33b7d8c30334f69917695c18, + 0x930ff45950e0b3a55c7b5d59b1bb103f43dad87f10dc01af4f029f1334860d4, + 0x13bf29d884e6f2f7718c62b49b2e4488f78abf3371e60ff6a55f8fe614093af9, + 0x1347ec6f72f1e6424af5dc07e72c8ed704c1de25df8d0298a06ce875337f16d, + 0x7f98eec37ea11c6a953ed4074e0de0319c71c5d80c6d9a7f1a7ed1642cdb3ef, + 0x1fbd5467ac28426e82ee95d4e67c1bf39ddbb0d00c8edc994d01b085e81025f0, + 0x160ad25d0a5b481711dfd537166e9a758f46ae98705c09a31bb5dc9ca672e06c, + 0xd1b059d762e26c7b237c2529c1a2c0420112b04b34071f365768e31c4ee44f4, + 0x576eaf22ed6ba9247a7c1cd5f36da28d3c82fee37029d5a564eae4a149f2ca7, + 0x189097900e6ed2067403aefd8cb2d68f8be1386dac2cb067f346d027b92c13ac, + 0x1d611f1ac08a2fd6b50b23612cd9a2dfbc77d3f1f01cdf0c97776885ee5f538f, + 0x21966ac51d732445609cafb1fa452a675d16df7f7c0c932aa136c7914da84816, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0xc4339f0ecf040eca09a8ce68b829e18174e1838978d18ffc85013bc4569bd80, + 0x20bf882ac8fa2b8a798c0bef93c8faaf79248ddf7520bf6615b8d4438f3e2f4a, + 0x1e097984b47ab98e3f1af30e8db0aeb16dfb7257a5d717b74a0302c0c65be5ac, + 0x2124c450afb451c834597afcdeae34d494f42b83ce16525ddd426897cb85256, + 0xae46f4aac64bbb73cbc4861b9d67dac7a5b9461185f1af393d30e0f14e6c86e, + 0x29608e35e4618f2d31f77f1222d8461c5daf83f8f96a1c3c22ece574bad1892a, + 0x8dda504925b8e72976d7225b9348b621d411c42725054f92bc5ac7f20ee1063, + 0x2d83e776ee847bb606165d71c5395381883eefe3e72db208d05671166672892e, + 0x158c6db4fa12040276f28c52fc4179c40c0b992ce3ff614cc8a335badcb5625c, + 0x2ba81ac87e1ba4a0abd35ef4d5e708098d5b3ea59df026301d29b0c639001d1c, + 0x297ca48636c22e1b41ac10da84d18930f4293297be2de6724d4a1c927ce6ac92, + 0x1ec2fa366088aa3d24faa8b0857b0ee947e7ac412a5c383d80a52219e3036715, + 0xef8e90ab9a0d92209ebc7ae7eef599134faead83d4cdc6a35e11486f256f91a, + 0x1a1ba37ce6b31c46f06b166007b84b1b5a729277769da12ac45a05329b1ab25e, + 0x1ce58fd6bb4c70f222a00ce15e034aa7f951e55745f7eb0e89d9945dc648ca8c, + 0xc96b4aebaaf211ee53c2592611cbd815cd8ad79ab87eb426ac951d465200f31, + 0x2ff556ea91ea4010ae322b26cc3dfdde21b77814aeeecd224d83754b6fa95b91, + 0x51d4d2e3822d407607a763652423f88ab8ac41d836032e330dcbdeb89dd94d5, + 0x1f484dcbd4ae03263c1043e2c67dcd871af9f682bd063efb99d6f2c1f58dc89f, + 0x3625c6bbbeba41cef4419cfc7885a6acd236f23c10bc21eb96fa3329b0aa808, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0x132c2bd9c3df321b8329f997d51ea4756f06d20599a69b00d9f5d327f431bd9d, + 0x223271db36c5a5b734893666d05f8c23472da5750c9cc2185251d1ce898cdc31, + 0xe442d13a0489c8ff0792219ab95cdcb6aac03d12617b498eed4f437e9e90f8b, + 0x49bd7714d013f9d4ae5d6b0d8a1966e3b6ec2991f80938e99496db12778c62a, + 0x16863ace52579a519dc0983e73f391982f34daeb311b455cd75b3c7f75c4a406, + 0xb043bbb7a835e934403443a871e8b09789e825314c553ddb593c117ed9f7a29, + 0x2233e42b11b31512cd6662e6e2d0f6123b84428079fd25823e39ac7be086c286, + 0x1eec2344b54ebb5d2d89282cef20b5a8297eca522759df7ee82f9306cf7013f2, + 0x7d3c2f7ffa7d307b1b80cfe7fc4fdc571ee008081d1a37b83d83f928aecbed5, + 0x2040b72eb4e1314e2c6fe28b0e10cda2f444baa97cf15b110a5571ad006f36a2, + 0x968c69a272239d4657b02e1e1157635654c2493c5dc21c80e459c36943c0c7f, + 0x113daea091f19279a75d148f3407940605147f41277347181a2eb45da5e1deb3, + 0x1db9caad8a73497abeeed4ce12162d16c8ea56a6ba6680cee0253d7010c8b0c6, + 0x323906b531b036a422544f9a789b4818947bd7e1010a9d3147dfb298d747c97, + 0x2a17b02e605c66f2e9191f6001fe8d0c054e9fdd72aa912d61b14db3e9e5ff36, + 0x20215701f065bea87da0f51f31fb17022a2ff12ff86a3a7d50bf196b9a1793b3, + 0x2ffb3a8d5050efe66c798eae2e37fcb0e75c8d3098463728f1258d3d15e9c58d, + 0x42aafa50849b504124ea788b0ba7d398ce77b42c09f25618b1661af76c42d7c, + 0x1f0760c47e75e2988c7c5f2729776fd656ca950959500807c33b15d2a20b8d0b, + 0x1b41324592d37fafa8175af1dae1daf093b7bd074de9dbe0f47bf246fd338295, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0x1326782be064b822cd54a82d526e0861f69cd054922b7809cb2f1c685b255442, + 0x140941464435a4da425c24627a01d5d0620429caf2b74c1cd8217f6ec0c5952, + 0x16d038333ef8265b4437495d35251402386b448bf2c652bd752875cd6abdd7a, + 0x14b3bded0283d8f82452086053472baaa94214fc64e23eefab04ff3a666ef793, + 0x265423dd06e1bc30d7ba50361df7b08371080b61cffa5cfcb4de6b840cdfce11, + 0x28c4d3106aa551425285a62673853db6ee69f820a38010b1e986ecb25a517c43, + 0xef4196f06abd4be2c6c77cdd3d9fc71b7056fcf82ba878a3c0f4a642184f33d, + 0x9ae72038e07e063172beeef085b160204d41fff261164869ddd3b35aaa852ba, + 0x1e653d313dc085a19473cbf173a65a752d300ac1001b2cc6f868c5aed1d5a957, + 0xfc8d4790130083f7d876b437a36a5a07861bd3fde394a7297affba00cc0266b, + 0x8889eb9c02f2805d59ad7c1cc11f1f8eac7d10cabb324cd28a4ceb64fab9335, + 0x5e2245fb34a0b6d4fc8c7d9b98faaaaa578a4bc650b9ccfc08f2f94596579df, + 0x1f303116020fcf151af2121de29d1237c03b89d27ccddfe6283c1edd985a8e75, + 0xf0deb6bc06f2954f1ff6e7f2b0f5874a40a67621147f49d9208913e3da2ee1d, + 0x138bd70bb31ee416686431f11be6768999f8a881cd5ded3fba47b1e715b98a76, + 0x2323cc181a6d96004077fc8afa78000b67af7eba4a37699675326751ca3587bf, + 0x2cc5a935240839d0916adf0ba2a13b373cd9a249f3dff29d4e636ea39bb2d47c, + 0x2c2f7e211539740f135771a5613be1b9d5626f84bd9bd3d086f6e33e497d4301, + 0x23a3b12944728d9d8aecd5b9ac2c1e8683a6d6fcde6de09f9d4981576f60bf7b, + 0x98c6085a8de8062c4882a80a9b53bf605cd6d3afde925b4bd97dd0ced63a2d1, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0x2b1aa48ed061330641b7610a5ca3ba0397bac5aed1220abf1ff3c053799d5798, + 0x27cfd05fdfaab10d703c5613ac9c30f2fde048b85315e4cad39a76c2625878f, + 0x2c6768184cf84573a0e970704987f3627cf4f467e72d878aba9ff0e6c32c76dd, + 0x1660e8db6fb22994cd208878039549f85464278a6d593dd871de03c5fed8233d, + 0x583531effd84ca69b517fded392f636537ccac39575313c04564411eb381b38, + 0x1b1f369306d9312d665302317d2ef8ba8a5673364ebb84b82de156accbc68485, + 0x26e1ae1e46325eef62e0ad0702b7c20411e5687ac8bc8b0c42f2294ad511e36a, + 0x2267a248407bd8dc0be8d6d60a901e6a6f63198e43ce9ded8b48f35117cca600, + 0xaf3dae82886360e75e265f24f928417f3404fcdc18896104e07dac544146d05, + 0x1322272068ace8538671a961e8182ca7379ae8066dfa8824036856446ce68262, + 0x2ad6d87af121d4b9d388dc3bd0fb2160dd0d43deb5d5fce770b3f66d22a865ac, + 0x2db628ad83bdb8c87642ab36796e64464a71c8dcc07db41090014d6824e9e55, + 0xbcc76f8301e3daafd571227cd8dd395fe5b1ef2a88262aaaa30eae1be85a66a, + 0xe953f3e2a6ea919a39845e34a8fff06874f40fa0c021102551523f0052f2ac3, + 0x4ed6096b59252ceee6dabce4945012b3afa929619e124fc1674f9742de6ce9b, + 0xc45fabe45fad457d5e763ba6f401e038a8f05187a50156e2e4f73e9eb0c1521, + 0x9cd9ddf426f07cd7ca72e4abbc3ca38063705cfe04a002396d91101f41a8ebd, + 0x37124c13e8f5393d02c7dda6fc39b986e10f7eee7eb4d8e8b6798aea8bf8116, + 0x12326c23b50b4f2ad7ad2a6e2f81e766da9dbaae3a85d5256c36f54f99504c10, + 0x27097f5dd86e6bd0c09ec07ed1d565846382d11310d53e11e4ad9dadda2d2a2d, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0x213719ecc1401b7f148d90bb4ceb0cfeccb1f84a03670a65cf2071a97c55188c, + 0x3ce9eb2e5a78e09fd8f99bf3677cfb69d8d81fac2ed57a3796fda4c4a75e067, + 0x2085f6b2ed31422f2ef8c9e8132320a9ea78f629f40050f9ae1f8d2212822423, + 0x18c42b10a0239a0788ca80f40bca9eceb54cce28ad7025ad73c0441f46e25d7b, + 0x2296d46885d7edc9e2f4552a8f61e0320ab91104076ba093415f525ee1bfcb4, + 0xf464a47774953e1647c8823c1f0e7965faf6e8e51a392f342e27f6b7e1e3fac, + 0x1afa5a730a377f7595ff598c11a257e2b25dc96a71a536671e98c4fef8fbb126, + 0x275f04d5ff1c821ef2729f6851a372c7db62bd3d45b68fd05375753a9ca38ad6, + 0x1ab45e9a2aa1daec4586bc866bac1bae78d8b8aa112962f34c5c19a4588f11b1, + 0x2c2b2b27465ba8f6c19c1b3e4b52ad9e76df8671ac3817d8c467fb7ce1a0d9b1, + 0x3cc2c6cd22dd586414a1f19bb9bb0f8b7dfde77369f2033f036bd19412410e7, + 0x17b6daf401b7e08bd9c414d067a6cb484ee05cb2e7c0791ac2bf415e847705ac, + 0x43084224ffff7fb2e73981b3d2da64588e746e1ff0a8e41021cf814e846cef3, + 0x19d25137be34aa73379f19107fefaab7ed485b5d49124232a91341747818b125, + 0xfbc00ac7aab927fcab38cc1f033d0c79ae42cbd8af8b9c676235361805f797, + 0x2a452e57d835dfb153c5d5ab716c615586a692f22ee8bb70cd32ce786675b85a, + 0x14ee41c5beb4f4eebb844ad27cd712b8b7b7d3bd96afb18417b0bd83650ecf59, + 0x151e1b6f64a2a6ac4afd3ed3adcb59a2f246e4d018a85a4dec29867998bdeb1f, + 0xdbc95be9577eda26c26b97276780a2c44046eff2d20ef3e233bc513eef1d289, + 0x2142c00dc3ef56e58d4fa535297d2349fe5a8720609a459de7d10ee2ac206735, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0x14f9e34fb8cf902037da0287f7fd59460ee42d86542ea027f5065f4fdb362030, + 0x1af072ef30b93499a21687071d9596f8c0720959f5aadd473015a320f525f3ea, + 0x1f79f8f436951eab483845158d798af4940c43b6c7606496ac7787e23d513562, + 0x32ac1327d91fda3e58b64a629d066b7618b0d2bb14bf0054f8a99ea94a7f9d0, + 0x1690528ebb80ebae626e4c7ad7808201106c3f6958a8fcccaafbf105bb982969, + 0x28d5726bbe2136f717cba221424342090f8922b607e61fddb1278c9090879724, + 0x2b8c6cdb0da43e1a2436f8c43ab3746356bbd0a40ae0f4bc282c8f24d205b2aa, + 0x1057e1a29e1cf4f016b0ae4b377cb2946f4ecec14d8a9e906e8bcf994968ccc7, + 0x26175299ec4bce279b5cd865110cb0f7253e035e4dd530dc78e98dd167a02c40, + 0x2fe4d13a9ea0682f7c6c79e2faa642823c6ec6166864a3becc3aa96a06023078, + 0x8faf60f2754c6f88af83be51d4d8fcd91a530c7fe1a7e15c04672be2e26ff80, + 0x1125b0b9078268105061cd44cfd53e59b4441c494e4e621513c0e2a7897f2ac3, + 0x2ca18674217c0814c200984a2e6d96fa6ad7a93a350ccb857f291dfa0a6b7c87, + 0x1b654e8ca3777847d7febd35e71555b5fea755b167581b91b8e66e7557a13755, + 0x25cb5e571aef3c5ea542332f3cc646f940ce1ea986284074b9ec9a26028fc3e4, + 0x10152a1913afbe44180af20ec59ec32a3935fd2b531d968f71f0365054faae15, + 0x27d1880942fecf4f9e46d11a1e3db53c0ae9385a676104de122c85c67a61b3d0, + 0xb4adee6ba01707c232fc173d7db356fd6dcba566709cc81dce13db425685c, + 0x1e4ce7b0213b39db08d07fb861278fc32ded0de6232c7e050f9e93e4abecf7f8, + 0x9e5542f2b8481d63429010b3f89aa2c01b07684b08c406d0c85cbd0fd01d2cb, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0xe24744fcd2826a25131911f4fa8edcf83597f52c72906932a58f3047f9d16a3, + 0x17a27cff4f6f9a2f2a1bffc998f0ec03338c0fc3d3ec9794b13af50b3ed177be, + 0xbf90dbe6022bd7df688eaaf3b9030c5b6ad0c3633b351abe5905c2a2b2eccb2, + 0x2678e3c1f390d5459696d950dbadb7b264f8284ddcefaebd120eb27e2b19783a, + 0x26df8104d4cdb377d22ad344e942b76261b457f52d8498fa69de4e1b8ed37599, + 0x29c0d6adeada68a869e934d2350a77c91eeec6da2c0d7dd111b8f03d73a2f54d, + 0x1517295c7a2561c1186efce6e54a6070307540b69bffe623abffc8984451bf14, + 0xd79894bd7300df6fd04a93836438358cc4d6e6921da38520a04fbc8fb4ece95, + 0xbda733ef7b53f5843811029b9a5c412237a72b96800bcdc6c71223d57157917, + 0x27d91c5d822f56a78c86f2422ca4786b94aaa2f3e066fbeb35b81c7e16c0a1b1, + 0x1e6dd8c7e739fadd91888860adf0392f260272a68d32b914f8862493847431e0, + 0x115d86835c20a27ca16c0aef5afdd73a1b6b7ca6f12116720b235274ca89fb5f, + 0x24df0f59376b1b5e39d9ec2aad776278fab288047a2df5df60990dcf935aa50f, + 0x45885167ee8e695c6ac79eaee96e087946c584049012a309ab8ec2087491be, + 0x44b70f5e0df4319827685be272a32a36ca3c4148b97c13bdab2bd0fe365bae6, + 0x2cc8eb658bd3afc8f4209a1c99566705cafc79332571f133979940b14d736f15, + 0x238c44c84ee349b63030b0fb02fa7653e547c4a6329b9902de3602c3c4fdda0d, + 0x19a32cb6029fcc93db2b01deb8264a9eb157e995ca21aa0e335589b06ff77be7, + 0x1c8612ec98aa9278caa8cb6afdbd00c02ee2f551d3d521ff5e9f92748557933e, + 0x2a6509f5e770cc50d718f8590f5f9de7748372d2d39f59a859c9211ee4bfd50, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0x1bab122c560118bee8f3e7fbe1712ab2b2a7312af61fb9820b77dee8d44d6ded, + 0x27172e3eb51483dac0c98e32f05fbce687414c3a3cc27ab1c277b13ce2378217, + 0xa9e3d7f3ef34d138cdaf36b92bff06b4b73bc9ce36156505741195b98d049b1, + 0x1eca82667b9ff6adea09ea840efcbafa5e206c97037e01ffbb28412fd2bb44af, + 0x1dd8dfcac157843cf5f94f9b10baa21f00e02a2cb5193944c3d3e970f910cd77, + 0x23a1e6890522a89b9b88d7db407b00dc68a40692a366936de0eb9a57bbf1c219, + 0x204f236b39b9136dc92f8135192c87c98c7984f1c77cb6064c71ec047975ff67, + 0x2c7480b893a528fe00d1ce1e4d22b330bf286443fa443590a63e27aa91eecd53, + 0xc5370a183a6f75b698c0fc6deb4447cba5de9ef2002cd8eb2904adfa4645843, + 0x237300db179a8dd6b6d784735cdf4640d61d44b518ea8848d8321cda2b7b4789, + 0xd9c58331bea02ccab4b9ef03eb202f1955b266c6666ad886272fdce7b289da7, + 0xfccf4375bda2c5db513e2dd0638ea1d2edaf41c2c754482f833e17c62d92019, + 0xc414e955b84493a9a6c827f24c39f62a9f9c2c8bdd9f76c3884d16217d30c87, + 0x20544d89fcc7941ac4972e5528300d0c35d5a650b8ff51f72974008a312d40aa, + 0x1af59412421b520c1171d8b74057dbb01653f41082f856ba5aa6abb79a43c354, + 0x2fc1a459440613daf728da1cf3a258c093bf41706724e6260afcecc13d324b51, + 0x177c1e93ee0ed483c73f148fc7f9891cbfc36a338075bc01498a69b0e1f8c49a, + 0x98c005b2959ede9425452eee49a4b0803237cf111f046511f8d56bedefa7682, + 0x15866d82d251f9afc692c1a115cdc5ac28b4771bea862dc26643e6db1d61978d, + 0x2797e81dc6fc1e231f5051d228081b46fe53fc394524ff424963da9a91070bb, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0xfd25da5fe62ce50a1525fe9e3566e9ff0c9587302f778d7756bd05d8c6aaafa, + 0x2a1a6a789e908952cc8c2e72ef95a937179c9248b091d016f28e38db12312308, + 0x2bb3bf8f61d1ed85e2175534e9a5ba3d17dcadce45eecb3d58749a03e2b04fbd, + 0x1a30a88ce2e48fe060eff18e1c7bca6257b8e39351823a819daf303f5fe641d9, + 0x5ecd325b357e47482e4e749cc8305b45ac1e65aa7ddd915ac37f3098dfd2d98, + 0xfd33eed2e51061ed5cbbe5de05b6ede9152f36b11468387f518a997e4f72214, + 0x95e4c2caedb1de02a6c60b086b8d8b67b9afd186f65e158d2748d2514d37b0f, + 0x1842d38786dbac9400929648db9205d259677647a5024e35caab08260744f013, + 0x203defcfa6213a500d5a788db1e0ffe30874406355502644de206a7303dff361, + 0x2941a9e3edbd2aad6138cb7582c8522c1ac4885b719dfaaf49ab0a138c24c657, + 0x10ff2a2017cba3c024111db07e677587896bf77e0673a928c5c2c9edc53cf2b7, + 0x26f456aaabdad81d33930cd48342be34c4884d52c17c604b45e9bd80cf3c19c, + 0x28e34a4031ce3e5b92d5d92f9b4733668ea65762bbe5fbbf82cb2eca7e208d9d, + 0x9479c03abe2fc4bd11f410d7fe958aa64aad1ed9ce46de12e16dce1aa9007a1, + 0x1901a62758c3b95378ffd836f543a2c2c1922ebb864000184b1a29167ed608b3, + 0x24bbe4299e388e01c96d7de61ba9e9ad46256f8d8c186b2e3a387d558cf912ae, + 0x27c84170d0a49798dfc9ab4d6a96731d0e8de772ca951c3ebb799378d22033e0, + 0xf12a9b9e0cf4da08c085755f42f2c83cf9f9addaabe06fedafbd1ccb7696e1b, + 0x2e34fc5a79f3d7859fff73ee159f8a963cc180ce2351f2709dbcbf6ec0a2d7e5, + 0x6d2b2ce15705618d1574127c9324560d2c222065da0c669ffd2304a1bd31661, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0x5b22e29f9914100e09f1d9faa6ec48b849d06dbb567b978c8e2875b8eddf2ee, + 0x121d7d80eca14c71d3a9d568d1fb3d17d848312ac21722507029ec3df61d64a0, + 0x248644294d40fc12cf53892614ec0e91eb6261ddb4de5a54590770b5a63791e0, + 0x8fc50ee296f9fc6e508a23b38d180aa92fec743bb5e62017ee4a3f7c98aea88, + 0x2f233d2487f18e22836df893982a593c74b7294f6cfe3ba3edb8272bd2559179, + 0x10f6d94022fd2c078fc6dacb1532820021f50f288ba40ae4016366dfa703e8d1, + 0x37d5df7e15cf95ac9c4bd02ba53e6d03bddd677a412bee4e0603f88ea1d6ef2, + 0x12354c8b1801f10dfe6c394b08317c7e86f49e212ec933fff49d8b26553f3e72, + 0x79679dd2756be024feb1bb2ee0aa5061a39752cf710ed6c9cb588f33ede8d0e, + 0xd3b424ee9455f137160fa1dd534f67bf068cfce1913a075fdf1cae7e8324ca6, + 0x227338281ee7da633b4b3938f5bb981f838c40ade4a0710875147f526fbae49, + 0x234ac22358b519377341651ca93dad434807cce449087bd4384f46fc732f7997, + 0x2e0c95ffbe680fa7622598933adab2a57c472a0073bffe10c0284739b26700b6, + 0x15e0c89cc6c36a7db841d4270855d1d9b8849197f9b08131b625d5a6d9ba693e, + 0x2f8952ad83b1ffb3c1a4fbd1064faac4f1c9cc31d0ff156a17478a1e3d255117, + 0x1c7c48183ec207dab68d73aafeb96047ccf668318c084453e495ebd5f927d173, + 0xecf362a269cbb8e56c2b0537f108a412ac9a3c6e351d0d27d365a4db7cd75e8, + 0x11cd56f9dedcb991c0c6cd9c9a0def911edcb915dc1904390782a7ee90d0de8, + 0x1ee74e2178baae842dd9658694381cc93b01592c655160923d40f4af2b53eede, + 0x12a2830e24c8bf4e9c7f019526f71cc57bad7995f38c6ed20306bd7b00f0d7f7, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0x14e12ee2c2f82a572d97c0b811a25584bbccc9be1b67ed1aa2141b2cc793fbc2, + 0x4f32291e7636221ba7905a9a3a1cae812ad570260c81b3ded9af33619fde33e, + 0x8a081bf1497e5210f6e0413c8b510f000fcf4a46be0a1b8442c5bc7e5fb7751, + 0x284571ffcffe707510d0feb89560623db7e3bf57c9675b02febce95fb7969e8, + 0x204b298a08577c1269dfb8ec9b4b3b502ed6fc3303544047d56d4135d3c01ab8, + 0x484b3ef7bcf5d63934bdcf53d8aa372a0b0363b0241320baa3701e8a1d0da03, + 0x9da34491e52c865a5b080cb9791a1fb80152c04335b1dabc34ffa6ad622842c, + 0x1fa3cef56374f00878372c54070d9c41c5ab9ab1d385968daf9ca2ad67d494f5, + 0x20b55b39b8df6f86a2ca381e2037d64987d1844c599feb2829648955ad16f758, + 0xff1c5369778d4fd96e295c21bef4dd4648fad9531f669e704ad2e4178674564, + 0x4c4c92112d998d5736b3f46120404369c9c0e428e47577c857509fa556a15ac, + 0x27a72f4b6e9896945e7d584e41fbd3cd5f75862fc6ec94651f5033c8da34cd05, + 0x2a1e46726ed9068504f7becf06cc70a5f645811bd65be579194b54486158599e, + 0x15dadcb67e30b77d8b1e5dd79edc36c3d8d0afb29b6e7f0207455e92a301dc93, + 0x29c1bcabaefb4954743a7a04502647c11c9f18de67e21c811c8d2b9f3ed82dad, + 0x7d089a851d1c43af05e6c9243b69b77b12f0c0b0dd25351c522ce8dd99fe5b6, + 0x1003d2e1e5368d1318992f181b7cda7786ec3e721be4bb89089bd794c6e9fc6b, + 0x1747c287ece311b5484adecef423434d71ca807924c54a53e31109e6a502ea15, + 0x134eff601bde8da30e62898b2e05c17f6e74d4ac31919c41363884ce7e30f017, + 0xa2d92f328082a3fcf5809958671e304daabfdb5708edc2cc207175526ba3e27, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0x4ebed2d43be5a74e8a00caa83989f16c0b9e82194db68d072226148c0a3d710, + 0x29ab24663cace590f69751506905667079db84d33f78204a31c93e7bea1fa839, + 0x14351a07d387943cf46b65496c66bc6f3bec8ea200d622074ac2430eaf521d78, + 0x1c423576a075f1d7376168b207a6d7203712c523c67a9d38882e8642c8fcee02, + 0x2c0564f1c52ac2d9f46211743b632ff07b210916de258f83d04df68ba0e29228, + 0x7ae7e44ebe17fc24a06c9caaaf787c2f007c640faaac6bd1790793712a69525, + 0xc4e1c566871f3484afba7d364ab755b839b09c5771413b0c31ed6a0fd2f4293, + 0x17c4f2873e2da004f2eddea08a30a9cf2e05f196fd3331b6f7f1227ddd8e7fa2, + 0x26f0a8ab7b5b0ac4593c98a899ed92d839837d520c5f6f0afd65da69a1205cec, + 0x94dcf41915c6c7ffa168dc7137afa6778076c2b63ed63d1ab1b787681bd60a4, + 0x15240235912d9c5ead8feecc29a4d77d8da47e9d1909763294ea18c027f1bace, + 0x2bfec6d12a548b0fb9fd176c7200df86c3bd785d86b51b2076bd9d3e8247312a, + 0x15954dffe4cd018acc436b70b029e0146529a26cdb39151468767b88c80ac82f, + 0x1f430be26a11f722560b348b1c5b526894cb458d8a30b49887713d76368302da, + 0x1360de1351ff67b63c312a8cacc2a465bb82dfdd3d792244068292aac083c8f3, + 0xcae448f98a72597e67867a24eb6ef2c1ce5d454fcf1c9eb4d84d21ce81590c4, + 0x20e9336dd103f61a54f27fab65e5fd1a317e75fbb5b22a81fff27ae4c8afbc95, + 0x2e36c0ee853342906730e7a2061c3aa2dbdfefbdb554b3a330c0ef34bba74020, + 0x21be1082ecbbc3a316c9d73495cc08c60082e1c20ad3d4eeb55553eef1a96dd0, + 0x2c7cec0d47c779dc5b614efda39049642f1ff409a40be89cc93e29366df96dc2, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0x287c8d33c0bd8b9ffcc38d1a3501b462711a41833390aa6291b5691321f34f3c, + 0x524f490297bfff16e253a88a02b039f4d7be41c62a47525d615558fbb91a31a, + 0x3a6f7a96eb42aca86cff7e2417d245dc19e8c7934e91f3dedb429ac4de7c61e, + 0x155dd1bf1b5319c5993ffd435ba45f0a0ac8d47ef063423008b858ba214844d1, + 0x1970a0db54455db508f369e376345b47d7df8dd58f6d69cce8330ed48723773, + 0xa17d8e77907e26a6c23a52ef2b39064da014f030b5785f3ced98a8daaeca3f5, + 0x199b42a0db3b829ede26736dc7fef94f2f211679cca63e75dfb6a221d4897807, + 0x1d492d7c7daa80eb64f335e9cdf306b0be4b418fb7edf32eabbf0e89df5b8e61, + 0x17c60af0291bf796fffdbc57db59d03897c671fd729bbd4c498e6069d0671ad3, + 0xc646e58e3442bf43b2255aa0b44c45c87bf5c947ca5192eb906432afb47791a, + 0x27bc23b6488e38e2ea87dcebd6360dd420d7ec90a58601eb1e312c6998a952b3, + 0x1c50a70dabeed7c79cbe2f91b2f9a1d3ca9ccad68afa0a419745160b03cc07be, + 0x120ae724abcc772ec7b0ac90719be72e9c17059b191f6e562620484e691f6e4, + 0x69f84058a0565f943c4f5cff4c939581975165144f1d21c05217d64978ad803, + 0x14a086d34d0cb4c050cf996b086aa3a21e451ae658ee0b037e7b0ec28f5905bb, + 0x2fe2f8e67ac2734b8b1f6eb408f5f62fe88780b37d4d0e3396c8561309f1392e, + 0x1b125268df7d9e01d789ba26c5956069989aa5328bbd46bb3a1c83e29b54f3b8, + 0x3006fe14ef14b876c2e1e2c7415c98b78918cec927d8b711c4e11987c2e2cc59, + 0x19332e6cc8221b23fd7926c431b68c75583036a24b7e6524527eacf775b5be7, + 0x2780775cfe1ae1fe97897c286142833fe289028ac4e51285719df14c4ec967fe, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0x1474d911726d98132a38828196f72ba9ea28de0e540822b530d53431c3f787c2, + 0x29778cb7afc99ff62da1a393d60b87bb8573606ab7ad7cd0ce647bc1984cbb10, + 0x1483d10c35376ed7a027168198d871358c79afbba7885d27c01b766770646814, + 0x1a8c31c239faf47d773bdba0f70801eac0ac001c6df938463cce819a72a11591, + 0x2c58e07b869bc14bb0eeb649f5c7d9c278b6f7639874ec404ebf75f58dec4831, + 0x1d649850732837e1c07c9f303d6278bb14f5a54ca14c86a26379029023c3c6d1, + 0x14306d8668280502119170da14128f6a340f1ded7e2ba209004c42fa628b3a0c, + 0xd417ecfdcb5924437742605073656307d039e23dc9cffe05ef8416e9dba3a1b, + 0x1b5881474a4679cde79a4b63249d1f98d8b417f1161599f6725471f582019156, + 0x2c571e0b35cca4cf4ca7121c9de0c4c5aafc7fa6f75498e8ec57928fb1c67d64, + 0x2637d9a03ba20a6cd7ed99a69c38a6d70b79d05904e37c9dbf46ab2c90583770, + 0x1cde7eb4a685a52ecd269169466eaa897ca783401860eba2b6026e513d6d393e, + 0x4f817cbdfd445391ae482fe7248567a0c8b82136358d239d4ef180dde2f489d, + 0xda99ce6262676118f51f86309d5288eb65c95fddade417046403bfdbb087d7e, + 0x2505fbe37c3109a4d1d321b72070a152625ff3b0fb76ca925e5aa2c058879ada, + 0x2783007044f2d12e5db30735edac84614cdb1b19f69901e0f601efb3d44cd5b9, + 0x1e145eaedf86b1c5cabe622df4cffdd8155e6db891ff498ff0b887f4ceab124d, + 0x8bd690af3ee78b6d212cf184b969f3112d45cceb738558962382227a434540, + 0x5a5462e764a4f4780125247cb6befaab7e4dc0d26e2d75f44087af9f6187b4a, + 0x12c972140783d7889663c3c9da5cc43cd1a9740471de97908a62cc21d43e6e7d, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0x16109bf9f0eed78c726bcbde7de40cadd12343460b04ba93a52d969201f97f7a, + 0x1e85f44c0c271ef8b9a9a29e3cc73b3b782c60d4ed7cc7624d6aeaff8e492030, + 0x9deb8ecc3bb2cdedba96ab5bd80b15d4abcc49b6528e84c1ed6971fb3aecb86, + 0x7ebccff0e97b9ffcbc6a2b256bf888739c0db05bc5d98d9e591bea4d74b5c7c, + 0x2124e4a429fa993d32f641febec0b25b9725342879f76afdf4e9eff7608eb81c, + 0x1f4217ea25fafd2a62aa709ef72365c70d66a4bd4d756ead776b40521b29e76d, + 0x10fdddc5f968f32bb7eb9555c0dd44462771f57424a761cd884cd0c152a35fe4, + 0x201c0f5551305ce9fe25f26526e409c0968c80b9e065553803aa38bdaff0182f, + 0x1cfeab50c568b3dd5c252b7cbbe28678939231d1287580ff6222d30821191ff, + 0x2b4c60bb89f1ab1bee21f45cf38de8335a2e85b513fe3a9624eeaa1bf6255765, + 0x285dc6058b80d18829ee46322acf51d442ec61ac331af40ffab6cd30a07ddd8b, + 0x13b9bd7d2cc334d2f60d6249ee87d05e356fd182830d3b3e9f435c6240f47603, + 0xfea707f44889ee47e8d9859c523f99c432083d85fdd6a8c75e1bb5771c10825, + 0x809a77036dcfb9ecb677ffe4e09ee7fab157ac28330abde61af824725d9e74f, + 0x152bb1a773b27f82406efdb0e1557c03a9397a6d87d461fa6f2e06ea9dd4e208, + 0x29da79b1af8bb1fd1dacddbcac71ac28de5fbe6aaa9e30f471acc532f5fe9290, + 0x252419542bfcaecc57733b02751f5142834e93f4560d7b95b85ad6423073be, + 0xc9ddd8aed9e907c27fcc361067f1b6c104c2b0a553e6d6053d2f82fd8cf1cf, + 0x2311bf775d429e2b982ca78c015cfb0a863fe4753625c4b63caf8e4ce36e37e0, + 0x2a72547e8d5bb41f0623072d419bcf39d08e5aea781b7358e95757a0664d4b23, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0x13ee4f15f3b425aa17da17f6b1f5d00cf09454a9515ae5c719a2d2dcfb41112d, + 0x190daca6e75275d36dd65c372d302d698b1a03757c0b4c7689e59bc1a0169f61, + 0x994ac0e199f04446e19887d6aea50a4e94172fe29818bf60354e92ba3ec6d37, + 0x19d35ebcf34f6d72d2cc738a968ff2acee72f5a54cfede510482076fae55c450, + 0x13b39ce996b064bda9880f5a6ee1677d731851ed9c895f19add559025c0decb9, + 0xd53028037010842c02855ed8d3143166621d870199dcd06bcb970d30b8adb7, + 0x26abf84cccb79dab1c143c12cd741320c9811199329ac1b13c240f33cb0a1476, + 0x2f94d075a38862b56155e5bd18fef09e29267c0fe03259af2122abd935054209, + 0x1d073e9398a1528b81d2a14baf97ce3081340b03c22ece28408cd284c2752b32, + 0x1dbebbfaeb42d7d727f73f93ec0644264cd18a0180ec41db0a558f3b4430abd2, + 0x2fac339c24fe87e3763ae29dd6d341aca13594792f6d48c66fae31b464234fbe, + 0x89dbbd04d315a29ca4c4ab69cd041eb3f8484a1f4a726139de0103404e073b0, + 0x7b9bd575f2ab6d2e57a6112b84c02fd38e25987794b65487f4975d098578ee0, + 0x26563d3ad82384b0c3bdaaf1770c3cd5a04873b239fe06dc21900ffeca0346c5, + 0x24d55232a8e458e4738c163f81ab363774595c7b79722847e3d6341e1650c80b, + 0x15f6a6be40f74352caf5e8c0d27c8a96d233f38d778756dd8b09546416a42a75, + 0x2e195aac1f98bb6fd894b6c8c78d0339d8ad8b48f6753046eb438897ca67cfa, + 0x240c714f2346df0e0a84bfe85b6f624b177e2fbe84b253cc4dd67c84fb30e574, + 0x15f8e5e81c571e42d0ba368ff59ad375c2de65558b61c63d08117bc95de0a133, + 0xbc0472f8203755eea5f4a54c4202293e72cedce2f9e697cef329b4a2e4f365f, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0xc8d9a3a7bfc7f53284d3f2d8493110979d2c58fa350b37572ba8ecb87eaf0bf, + 0x2a431044a8b80f847d099afa8c1e72d7f21894f3946b0126655720f8a6c77857, + 0x1181a1791fd2439ea67078819652478d6767154c7a9d04918373cc072d53ae2e, + 0xf0ccfb008217426f92cc5dfec764630d0861c6ff9be2459b227266741a7de7a, + 0x41f755b4afa6ff133e8e46fc826c9b3e70b45db7edb7ee2ac500e47e9844a9f, + 0x1751a37439e9124554ecb92e3006d8c560d6109b98570800c2edc590016b5709, + 0x2abf7e7390de929b5c7d29f75e5c341be84679aebf5cdf21ce295cae5881865a, + 0x173d1a4bd47ad310c1227e8d26c8c7ac003258ec98cb99c4f5da10c2fed0be99, + 0x208d34eb4ac78f934ee023480a4b55edb26e044d9a46008804113b8b3ea6e237, + 0x125616d001a18f80550970d010e57191b13574c8f737e4c82b47be6b1984fa62, + 0x671703eb5922282742b194f3c2d494840e872e60fa6e77c66fc03868c71abfa, + 0xe335455fdb0c93b70a21ae7ea60638481071649d6bb76343651667a6205ed83, + 0xe83b80d5c774f2c4e2a8c7f7dcea61c0b0f000c7bcdca6bae8781aedc2513d, + 0x58c57cfec4eb7be81eea51addafb135b89b2c5a111bca597f5212eed8547da5, + 0xb1f27ab7d0817ea3f949179fc135b60938c8c20bb9cc0cec20b1bc8c5fad7c1, + 0xae5de9d9b873cc4211b1fd9fb2e0717ce46072da5f7d8610560c9582b7f06ee, + 0x4e515f4aa39a0a8667cf06abff04d87ebef4d85dc32ce64a80be9073b8e0163, + 0x19f6c6c86ba20bec8725fefa5ee70cd0b1bb88b9b20847927e963ecc6f46d376, + 0xb97af80e65d5a12a9178351fe47f3c6741b18408ef108cd73a56a785f657fe2, + 0x11001edf4b5785917fb4ba3f1cb07e46f8f038edd5eba9c657dc39b3f6a254c1, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0x1f57e91f818cb6ec2ea89a4c5248e21db4ad238c11e2824455224c316c6de448, + 0xbcbc929529eeab2f4001235f0dc786e792af2641c0db97dbb1780aa611ac51e, + 0x2ffec2a43cb616c220af4bef1265a368c46b0d1c049e79d489bd62e461669061, + 0x18cfa39baabd3a1f352d1ff2571411e36ff0c72a2796a40e9fc2238d89d99383, + 0x26d86eeda466378285e93d468c3686ab5f649a40ed46a52c29c2b9aed41391cf, + 0x2120bae48bc4d0b019112e48f3daef5b38b9991285c3d03e150a21fc03826de9, + 0x2872ab1dad0eebe81027996467b9767b38ec6dfbefb43d9537d0ceff4b0d8032, + 0xcadd0bbb15b10a2a3b5976ced621686e190691ddcf2911a6d7911aace0ee731, + 0x12f83ac35b2e971f68f375e239c28cbfc8010f2d20a609ffa4bf3ca8078870d, + 0x247b58e9d413e3b9647f7204b141fb1599eea15d505520b47d61c11aea6b1eaa, + 0x13e4b5310fafb562358633169e17e3431a821e301a178c33279f5485290de69, + 0x1da54e38f590b18af24713a270573e2c12e2b569b0e90992eb88312117269373, + 0x28b85a60621eb6d7d4633f180f515bac0757a3377dfd68181bf6a65a9599121d, + 0x1a152410d786dc50b32af794cea9b7fcb7fa48231d536b3c18dbcc7509606036, + 0x92699deed292bfeeb718c76b997538a59e7ac548342832dafd64637e738f1a0, + 0x774bf3637103073fe707caa2d322d9a9044e4bd92d81c1e0ba56467c591a487, + 0x1a2f16440b008c3f42154123ee5c0c0f06eca84795d9b104c43857bf528cf79b, + 0x149a1d50c2c217a068dd2ebce1907172d58fd0a3123debf849d13d873648a8bc, + 0x246086052d1ce8675e03b097029adfed9a97c8f67f606d7093f6e412a7b4bb8d, + 0xe2a84c4e9aa19be7da3e5d4dd74a495d308369e4b26a165dab9c4238eafa4ed, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0xa62dc9863ad7e45ef7f77431acd332fc30280f65ef1ceda4ccdea63b3ceed3, + 0x1b2446bbff67b4093c04a6f3e904075a796c5e28a5a6e586d6440753ba97551c, + 0x165b84f51091009c389eabcd7fbbc992996fe32d9f8435354368e1e5b1dcd59a, + 0xc193a00c3e7e8e353d0475afadbe369f9a5d17169a169ec197977619136eff3, + 0x2088473c2b6a6ae33c857f94f2f12b90d7f5ee0569d96d801fa8b87194fc4595, + 0x8787d2cebcabac086e9e7e1fafc216e3f8fe5335bd4642dfd1708a82a5371eb, + 0x11191767947a0e4f9c3f782d1abd55624b55ff7087f34478ce0a7aa7b2715cc4, + 0x2d28a1d818e8eb1efff60aaaff9483679cd5d77a701688dd53df7a9df567f5e1, + 0x2fe813fab1011dc74f8a18e5b039dd373f0070ab1dd4fd126718a087cb2b8f9, + 0x170e6e3fcd10c27d012f844c21af6850284e6b19fd5d1fe8258861d9db249136, + 0x107d6816c1e3db9ea8bdc485fdbcc7f13e6134e807d7e4d686c587b4b02174, + 0x19758af0d83c9505493b5419c17e6c4dd7f2ff338e60e9609259dcf15f33cb96, + 0x94462f324ece93eddd9764f77d342e248121b7f1dede3f149571a9d9890ba7e, + 0x86086b36fcdb387c6dfa2ff39c4910fd0af2fb3ecdedf957350e20ad3c843a, + 0x2e3cfaefc61b8b4800158fede4808cedd9d7cb5b2280c9b1590e0429a83b3db0, + 0x828cdea83f97fbf72dbdafad73f0954b8849f09a7f12c3bae6989012f8d9fc0, + 0x462d87fc2c8185981a6d5efc6e31654b2696a1c42ae60b99eda523fd8c13ec7, + 0xe8224f268418104de9a75f6bd915d2861e8e74a74057319dec312cf8be4dfc, + 0x89163233ad979f94876f77c9717a7cc3171425a1b484d1050f7550e31c5b42a, + 0x13f4fd6d8abcafc2d57797c252abf6319f2d2122dd71b15bec6dde9544f60448, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0x2cd268e81100d72c444d6246f8003ebbc08c1b5b5850a508f162541e43804c31, + 0xdece92e3458e7d6e3ed03f44c57b6a597f2a0851662e51f30c7e345ab3fc44e, + 0x2782c56f48794e225a91ffec94d427fbc775704a57e24c93a1092b003ffbba12, + 0xdea062e2b07f7c6afba58a89e4f46c9586b6ff9abca5d59ed857f5b65e618f2, + 0x53f7495e4b1275b15b3f9cd75aa20f9f7693363d4311764a772f2956af6fac5, + 0x2d8223dd32694c54cbca71235970b8f70f1a7428bd738646ca6a862f46f64ded, + 0x230d3770de4960732ed1114493287bcba5a8b219308f15bdf3d66ab0303845e3, + 0xa08b786f3debb023c5ac7f28402aeed473d83cf7345cc4e3ff319ef710c8e92, + 0x1abec3768c3f0fb09fb3f77f12a70683a00aa39dfa9bb1df8ec678d38d2f59aa, + 0x285759f5a94427ddcf1462454842a9d1f953a3d2f7ec048846fd78d01a0493e2, + 0x2b4f0d69284e2851b5e39f369bc98b54d589c08c487f8c89d1eb0c873cc4be5d, + 0x447dbf76029e36fa2eaa60a6235e5462decefe44e558246910c8f6d57b00875, + 0x275415ec216217739aa767153b11ae80c6b8b5c55c70f2b971c41ebe8e2b6af5, + 0x1a7afd3f33137e9fdcb3dc28cadb4a2dc634ec68033c4121f2e55e1fad47d19f, + 0xda8b0bf0f0197a311ecf8a70c17d6b73882fa3d36a2966583161a3f767a5cdc, + 0x2dc11aa7fc35288f4c50ead3bec7cc0e75b9e52e8a3fddb61492ba94948d5ada, + 0x195f7447bdebfa31bd8bb43dd8d1e6875c5c135b15c3b4d609d52345559d71b5, + 0xfb172e6709df3831ca8632986ef7d85745139a51a45c169c830c4e691b451aa, + 0x88051acf2f4c7ba673361201ff1639e06fa376b2a6505a1e62038906a31cc95, + 0x19e57228a8198e58cb5bccca90c63d15e07a0f3e6d5d130d973db1a831af0bab, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0x22e5666a758743c42fdb3096ec7a7e4266ad74824b6be3619435d172f438e2d4, + 0x13ea60e7594766cadf7e4aa1f9f005f9d9e06177456cb4a43d919b4538492a06, + 0xff1eeeb246ed508d96db973e2c50b126fa55bc7094854acba766574c0889a7b, + 0xaffdc5342a12d31f878c045e76796ad01bd19a313b08cbe6071c9fa06d37178, + 0x291973a60e03d9e088f91cf2e0d5d4b814b2d84bb97aec7993175e5d6dc519f, + 0x11739b8ee3040e282f6d5039784f6b749c3a4d6befe0ec6276270da24f8772be, + 0xe74e778ce3b28a1acf824de6d089b276e535117c55c361debf0a40573c67eb3, + 0x1a527cc72db1098870ef84543fa630c207a6094df73caca62c47ebfe12c4dabe, + 0x12f701614f5391cc72251c38e11391e9aa2d1703c47e84a041ab471ed77450a4, + 0x11936336d54527a9299aed9f52635b8a53f9a958598336c9848564b86516ceb4, + 0x272318da87365e9fd6249ec7615961b138ae0c7a36b5175ef5465898c711be04, + 0x236b144cf42999283d59501e46fe4ea1d60003599b4046d7a60373f0688093ae, + 0x1a239569e5888ba9ff7c90a4aeb505659415da6efcd3c101e791228149b35b61, + 0x1e9e91cc7f554dc236e84f167e2baecef5a26769296b73a94648d454028ccf34, + 0x148af5b46862ea8269491067a96aa3e71f424fe1bee820cd988fd8b19527bb5b, + 0x24772a606417d978acf26d46756665b3c414dce37ee779c91e98a4caf803b6e5, + 0x1ed8140073fb5244cba84342b2727e8258108dfb63d1daa824f4330932a7f292, + 0x109b45b57572882b3de57c6d043e9477acc341231247aadf512cfefb46159244, + 0x12563836d2c2fe6d077a81786800dbbc8e90d758a5a323f549f9b8d523b630b0, + 0x1ba00aa80b49e70bd2b3748968ce6d19e9d3fdae0bdbc10cc50e90dde09dfe0, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0xf24297c2abe65471b0746d085d394de0919936ec477876d32f44707fe0bf799, + 0x20eb0b298c48450c7f613bf10e04bdd22ed3115756fa21731aedc3ffbe7cba27, + 0x176482f9dab80cb5c4d91f707575f2a2b552fced3c3b96a5bf37f9b80fcc9f64, + 0x1f79915591cfa6648201a28d89355cbc6875e30f78d96a32c3f108bb3a8d5a76, + 0x2961cce7579ff9f9f0e867a02cfa8bb2e7401cacee24f5556e9d2fce5d0cec8f, + 0x2a41178e5d6a04a7a1463ca1799dd1ba6a7b5c4782097e585793f987485559b4, + 0xec4ae2219594ec22f648bc1fd42b82673c47d95bf48e9efdc39e0da9406eae1, + 0x261794a9029605c2a4aad5463047d0cb96f9da25f3b18f391047e684519a6e05, + 0x2e2bf6b18878b8335e40349e7f475e2c85cc279f99f76c0bb717d0ff7866e5e4, + 0x153ca309df24c9e664025e69edcc363ca33cc1a9a2bef69b44f607830195235, + 0x2db12f885abe64af44a3ee3f8478b92cc71fd91b096d65099be20ef87c64628c, + 0x1f2c5b4c49bf8be7e7d4d9f83e18e6ff0c70ce913f2e246e65024ce32e0b231f, + 0x9180876813742a23b9376d01579ef57c1fb39a60e825320fa0eaca8953152e3, + 0x2ddf635158aef59c7d8a6de274b34eb7a5d0088a7fc4b0f7f4ce699a18e73a5f, + 0x77f3965e42d9f1951cc9528c4a10b099bf49f4eb00e54d389af199a8a474125, + 0x23b552370636186071152d808dcf55927b95422529bbe9900d1a1244532efa2a, + 0x10b40997e86c5be3b64959e84b6ff95dc3afd77d7a8f708ba81d649075c74ebd, + 0x19e7c76c1b1e67f86073187b4f730e17bab59bf1fa5a00365be2f3541983633d, + 0x1c1b3ca31b5179b6dcb9ee3ab883ad56a355810877c058d64e345815eb365f91, + 0x75afbdbd2dab2064406909fe766072f532bccffa959708bd53863b53f1323c1, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0x2d6bd5f440b052c36e1896ae00904b584661666912e14b5a76917f2a4023a975, + 0x9fadca902762e1b9b2ea83254c1422c3fdb99ab470149b91d818f74c166448b, + 0x1fc2ef7556e6b217f26c4ce8b049b857fa69b7f22ae9665d8fe061e57ccd86b8, + 0x277e0a5d5df37f2272903866a0f10472e3e4d61505b48279dd78f9e5eb18dc6d, + 0x1926393f89d142b831b5a9463ae3860bb088973ee5ee9008f0e1c7965c79be27, + 0x2917f5ea018334c0f05c07baf8c846d354e3945fbd67d5a22d058a793275a35, + 0xf1816fcf77643185cbcd7f0b141007670a027cc2891280006f4e0fb6f700113, + 0xe5eddd2746b7345563203a3a02ba3f3be5c9de6fa3d6819c1dc8c10ca61962, + 0x2fc0ffd1f2fb9e525e97afb88c5c1f16369b7864f845a922f56af6b567abb127, + 0x13a6d507cf38dd7ab84c4fe55fc37ccc00e54ff9114fb7dda131aafaf5e3d8b4, + 0x209e31eb994b1224949ef724609a754624b12e3e96aaa426519369d729d7f0d6, + 0x29b95c4e0998e017f9a6efa329e997d750c315a7091995543108bbf2ef92ea5f, + 0x273017f65d54a8a19e933a2850fe33bcdc56245fc66dd40bd16d1963065a8215, + 0x9a00a7bb4d3c41d31473d0c97194d90a94a4348aed808ae2d9b68d66ac6da34, + 0x58f37eb54a0d174ad881009a16e033b0413350052445162508f2e3f1fbd13a8, + 0x2991d56ab55bed4794d78fbe8ba2d84e0402b704c63e8bb477815b94c0b6e72b, + 0x2cf9ac97f208cbe23d5daadf7ce8eaf17b949ea0694202d6d3b4f6802c20c8f1, + 0x2b2ffc8ad52ca2742997d3fb13e13abcb7c44ffea14776362b6bd9e1c5aad18c, + 0x3f78a9a65aa3f5e30ce1ba2779ac3c5f275ab77961819dd01638a42d14fea57, + 0x28a9d40e9c58592742de7987c8acdc7fa5e622f5e87508936c5c90e5a2b0111d, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0x2da971edce5951e175b20231e2caecdd672054df0a81abceac87182f9bf2ab39, + 0x4852b72a76fcfca8332cf2fca53426d44a81025b049c6fe56186da6b592b8ed, + 0x12678cd0dd103dbf00c083c3d563aaaa6e6e39e940c80c14575ea53f7da93714, + 0x63be8111dc061b7b1f827eba7cc5e10703843b6878cf85160b1d8c37f8cf20a, + 0x1292d1489e40b2b7a96a47889a8c08c9bb62ba92c2fb6ca290d3026828b90a38, + 0x131928f8c7f6b292af217e6a3798bb3c3740fe744c9754f71e964e739fa84c7c, + 0x9dd09c082e6ef61242bae94103d3413d8e280c3d824f566b6191d86c3e52e7f, + 0x13a9b7f650fbebb1c30c63886605cfe65fb13044bbf58f6b6d6d4754a8803d9a, + 0x278e646f62cd15b671eab2feb4b10833606a737023c50356dbcc6802c47e22e8, + 0x63a048acaaba44b87639a3d246f7bf5721b2dfef3bc6387eb9a7a1753bc9edc, + 0x19137d8c7c05b4380c5427ba3589505a29927ad701293341a797f8dfc6b64eaa, + 0x4605aab2cbf1c8db31f3530518b1b058e8a9fdd52380d4365e7faf99ab86431, + 0x1a662725c05570d0cb0ce0e3cb83f5a9a0d641d7f7b5f0395b3cbaf27ee8e7a1, + 0x2f00701e4012136574084fcdcfdb8a03d4370327b6778f7dbe08468a3a221d3c, + 0xeeb43bee0ce1170554f5365901cc66aad614c7db44ee7d933114e56ae13645f, + 0x514bd58df752da3a43dd75147804956f833e61091c33e8b6ebc059d1668c3b0, + 0x2e501a1cb67757564a27a930415497ad671f61899a37206e4bd4f70525dac248, + 0x16d477454abad4ab36e15a385dfeb9d8ecbbd645a459befd544456bad6de8e6d, + 0x3c052112963b411255ac9f4937ba4162dcf4dc56fdfb5f11f585a2f973d1ceb, + 0x12dbfa8b1f22ca2b3338b85b1a1cd75ff557cbb18bf220312b18a91a24d55d81, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0x10818548ab73fd03d26ee40e1a406f294dfd8c805e21f8689f1001d1d3808e16, + 0x24a35e4eb8df49312d9fefc8887e52fe90b836c0cff7f7c07a848a14b01fcbe8, + 0x2e0f1e7d21d2d04fce40c67c3746330043b7168c16650a4f2c9dbc17eaeeef9e, + 0x230af3cc2c7ce9edb2179f8615ae8a62e458eb13c246f9b673170f1466dfa17, + 0x1134692f5f1f941f285cc493c3f2327065c452ad32cf715486dcebfc2d36e000, + 0xa9d37ced0d525c9d8577b969975227cbfef65e389d902e6c4aadd01322e8ae4, + 0x1db2e2b5cd0288b1d7c7faf003be7703b5c5e45ed5cd77c0f47bb8d3f2703afd, + 0x12d629c5fe0a3943083c96e3e532897bb2f63db5519122159b61723410ada8, + 0x54da7deba9f7f2f2e2180728042a935674a8446804c3cc47c9d15178e8d6666, + 0x29fc7ab2d3d544f25354a989848126e23d60efc67d30c1d7e6dec4f01c8bd52a, + 0x14dc9c3565c4d246607923146b654a06c3a6f33ff2e7b285cc339e7e045b10f3, + 0x257f594d047a720f1ef7ae56ee5cebea62ac2239715a55b1ffcb394af09ac0b0, + 0x1202ed4a356316e5710f9f1a5727b083c1ab217050e8bbe7d95ff5f826c77669, + 0x30fe2beb49b890033bbdd087b9e263add126966570888915b43101888b8b962, + 0x5ca2c86c6b813c5ab7ecc7fa53fbafef3678c328accc49fa70b5f71a1e368dd, + 0x22b38b500c9b360fc2b4ac16b0f8fe71e8e30a9a5fffb2275f40112e01c59f71, + 0x1a85a376a332e4ed41c5b9e85dbc2806bb3c3c6f38c7f251fba31eb492d2811, + 0x30b8dd372a1546b35d430c7592b24a762c0e748b857190aa47ba294da43f9bc, + 0x58804d2aa2f1e9d511cb4bf4459d8747a00af3f8cefa52c3af281d7b71a468e, + 0x2be9874c17f4811897b082ce47809991d57d081de49d4f9259bac0c2bbb69e4d, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0x10127c52ea1f6d2ae8cb3a7af70916ab29fd85fbde5d15596076ce30524ade37, + 0x2d887f38f4f5c278b142bb09fa17210717bc38dedc721327c34b5af25fa4975f, + 0x18413dd99e547cd6112c9b3890a4a927660153967a2fa3cc78281aa3743b7ca, + 0x2c8375bf705e811aea8583b90f6004ca186f06ba9005d92cf3ce7317b4fbeea4, + 0x26672152eee139f933ea3a888e343a211776aa698206a6b970cde470ad510e72, + 0x179472871d26f2e278673df45769f49f3943f98b5bc9e76bc7bd639f5cb94a3f, + 0x1ed0f4a870226c8afae5b2719e3aa60c8a4f3f491290ecb6a6fa8ed8fec32f0f, + 0x1e8ab7c5158984fd536a1fcba52e4a9a99d2406c681d0d54c194a1378aae7bf7, + 0x6e50409b0cc763889daeec7624be727dce09632fe17945329fbbbba7336b56c, + 0x5ef96066a1106782bd7942af6ee88ae6c642890863ded5c908a70f0e97188f7, + 0x275a393c79c2e975e32088fa28e808ef7b3a28ed55d7908b3304c6270b68474, + 0x232f41ac9fb55828ad89fb910fd53a80463ad16ad787e2869f315a59ce7766d6, + 0x275bb8e491e9023da98884c13b73892f2b1eb2e77dd1dda8b5095bf5c9adc9b, + 0x761b386807668eee2b21b55ffc77eac91c6081c52308c6dbafc6c07028b4e3a, + 0x493e9a3b80d179228d2a81e903a9fe8d65ad2dd99a733e8ffe044ec71a668f4, + 0x304413ebc59f08c82a9e2356ea09341910ff74938709f03599a4f0524ec719a8, + 0x2d1e1f38f6702b847019dd697437b90bbb302f642fe0d71df7faced0a3dad14c, + 0x16ac849076bc69c52529d4baa1c20d39991d1d1bdc92c8e0ff1c5bcad374f25b, + 0x1a85ec6762d6cbe146dc87cd11c2b2daa1ea599f611965a59bcfc3355a684318, + 0x196530945d3d7b35c950174d0b08a4e423a8ea2bcb1d455f4b5e042d66cf2ca0, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0x7052091360f5985cd717c188ee4aa7b12542f1ff3dad0a1996b00fde6e3652b, + 0x291b5860cdbc43b0f0e3d258bdf8f8b58c839a56779bab5f918e042293b9868e, + 0xd74d3b457f71267a00679f5b34b57cd193626e69dff827153cb0a07245f97a5, + 0x6063d52c65712f8ea7af7b3405c330f3a0e1e4a1652cc21d3dc5e0f60cdbf76, + 0x66b0a3103e081f9125c429640d2db5993037180131ed22bdd413d33d6a830e9, + 0x1a1ec3ab8c7e73bee5257c0669cb9e5958eed3d51d6b8bb1a43f2683e2082a4, + 0x25bcddfb7d8a0a191d30fd1325f71e08124ad4b099485d80f41ac677e0094152, + 0x10436855078393e34186a26936181b385e1f4babccecf88b189a51b052d6931b, + 0x13fd2892c02f51e42d36d9d6986a773f1cf644bcbcca74318c486e1b1887a8d0, + 0x2c28f6b8646fe071a4d6eeaabc22f4398d09adc041da503fa5e13d55f280424a, + 0x8283969c57b0158cd5bf0dd9ee3bf1d6008dcc45c1ef3288de7d1be2423832f, + 0x1130ad17e3000bea708aa2ea9293faa1bb33c9fa734c13ad351f0409c649ca65, + 0x741c5c7d36f11cdc84ec58d9e6d7428f8cf2d15110ec45d7218f7991be58206, + 0x1f449a6d7afec87c3391d5f306fcaa5ba7498feae544c6048dbdc847c7dad3ce, + 0x13c20e3e2bc12fc0d3ef6ba869311fbc5b6a3a4d779dafed35a96098e97f2167, + 0x1fdabc23fa86f1b12e840c491a7d7bc267bdccf6eb113729e41f09eb416c0d90, + 0xb18abdac519be96bae35d898d40a26e9d9e0561f6934be88da9a5c24e498652, + 0x28b6810fffb6ed56cb0ab3df49bbeee7cf4f978461189f205aec741cbe843202, + 0xbec82d9037048c805a293a708427fbfb95dea117a6dcd1e6f34f13fc9e088f8, + 0x2f63a41ae9a12da286de92e8e7d65162eef3e275eeda01b2f1dde4a6b69826de, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0x265c4fc58d97632fcf19a923a0667b9e9b28b7add612d7a71061bc93a8db0d34, + 0x12885bff48b6298f10b722b699ea5cfefd234005c83ff78a16da563a95758d70, + 0x151d53cc6bbeda594c839f198afdf5419d1c87ca6c45e23b4b5df9ce6590fa24, + 0x14d55af045f1dfd8f49d4f256e081a6b3ed093f01a72e9e7fa95964d274b990e, + 0xd2eabd86f01fa64ba065b8ed26f82ce2fc47e9e016448e3d727a7c66a7abdd6, + 0x28b3060c2dcb657bf0ad4e015552f6c057d08d94e6a7aa8f65ccaf576ae19c9, + 0x29999685e5c96a1b905f85dc5bd585d018468c52eaf77a65a6a7f7252d015006, + 0x2cc36566d5372f76a5bdd4fad63e709b1c9a1fd8c638d508d11386a963949d17, + 0xf45e1a65d563313981d7fbd8646e8b6c0a513e921fa4d91d06d1def1ac535fb, + 0xbe5a47fdf5f5ebb05760335c19650934d3c9fd5bf6a947d230ec07b04b63361, + 0x8e06c579f1e6e0130c801b93e325ccba4488227d52279b600cea03c02f55841, + 0x2f50f7000c45cd941aedbfe73b0022a95ef948e1672e5e4ae7f818c5af7a5da0, + 0x10e83f3ecde3d5babb785328a70cad7f1266ada3811812961cdd561855792100, + 0x2391b1a42d1ad62765e51ebd3fcaec9feda26eb1a8e4bc397b4a7692e5036354, + 0x5dd281f4536f0e512cf632d8fc3bc3b198fcd503172259acd0a43f6f3b2ca8d, + 0x1805c870c9eaa246e93fe07b6de600b300eb1d2cc768abb8a325d1b35a73a383, + 0x735b3cb5309a63477b17662d70e873a588e82e15bc083fca92f3b1272de5930, + 0x15a7b08ffbfad70da2050e2c609621cc2817e9fab3f8e06f0f7d37599f374039, + 0x1c7725a85e6a7f0ebaac87408b38e5e6ecfb4de63ab1819008926a7d1ed9162b, + 0x2371b576f67ab802e647290dc0ca0728bf11fa282a106e52567e430aa5cd6df9, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0x2d76222e6f0ba0ffd8667c9cfb2a8bf2ffccc92e74cde3aaf9d515f6770be25b, + 0x21a9df030fc2c38623949ccc0e27da5c02225e2e4cb94258767e67046b1c9ad7, + 0xc994ae387461d0c7104186c1f4e140f224a0c8590490a5d28bf872596eae2d, + 0x27c61ff34f721d9b86250fdf7a433505b8fa72ebe9a28c0f8f9a5a86e25bd642, + 0x115aa7aae6b9596eca97b6726a631722dae0a8f630a3368604dbcaa9811a851f, + 0x18ce760e701aecf766400d3c8303e28aa7937c3c89c3109a5f0b8f9209729faa, + 0x2e8d27465c96902538919868872618261b07e2771f087e9686a07b02744a0149, + 0x100661eb6f7639b3cddca06469b717369b84248f18a9a0250198228d8580de14, + 0xbba9475dd449868c67d4d7394ed448eaafd0384f417ab5ec3582db8962e423, + 0x2ec4cea2ec233f82b5c3afc658cf0f1d5056dfe434c209ee3d3ae5101c5d38a9, + 0x15a99df7e6b5ef0315db045932d7a24de603b0b6897f567626fd1dd9f47c8553, + 0x1be6d866794b25f0ad77226028183b38ba4faffe5a4375d4b2560306acde3c5f, + 0x27257e94b2e95e861b7120ed9762d8c4c94080b7612d9b58d00691fbeef97374, + 0x3af51f300cd6fcb4ea567e6c8513d81dad94aa1d0c125a8408cdf1ed9f103e2, + 0x193b1cb5ebd78dbe0428c993ddefd3df2414c558078f757b3f8035b047090913, + 0xdc86ca1c3c10a634dba579115794017366d06315b67d84381f4e3d530800e52, + 0x1235404239a1bd35d8a5d7e41fbf7979bc1132e1316236fce4704951990487e4, + 0x17e965fa385145f2d79704557938893089dd6a9411e1a4054614bba0f1453b45, + 0x17cf6ef863dfc27d9e23767c80219a62279a7c1df9553c8c3fba34d8d80706f7, + 0x568c86457d66bf962613ccfcf294e2bdfdc444406b20a6563eb382164f6b38, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0x2f5139526746698879515dc547fc4a18a47bb7b1069cf42d88c1699f37bf70e2, + 0xe9ec645e63a3358158ca6bc99b354570c61b50ae0b66a9b2cdbd5b7bd2528f6, + 0x110bf55f969e6beb814a08bedfcc429368f8a65317d9df987fdf690464e82792, + 0x50a2f40f3337b14663877a5c5c66bbad6bd40810303fc9077996384fb942223, + 0x9fa261cf5150dae90270799121e56745c2e3aff6c6edeb0d9f37ad73f2e92b7, + 0x18db0fda1f48a43c15c1d72d7a8e8ec2042ceedc57f08cde78484f8a0175afe0, + 0x12cd152e6a482b22678e14feb1d2b463560eb39b0a27bd82dc9cc6791c70e234, + 0x208785a8e7d01f556b883d201a43071c922863abb6b5b9d62b06cdbe1ca198cb, + 0xa2f6f2777331ff62db3918731dfb0f8981e3f15b0715a44a3e076abf1e29710, + 0x2e40f60a955d8717e55b97ff156a8bd9c6f2e806d042d0213ceef2356fc97f74, + 0x15b824ec28269dd4d8e6a563169d415cad68d9c1c7aee1aa279b76abed3cee6f, + 0xcb83c1917e41f61a32024d11b6d8f43c8a9e9547568b817ea72b3ac253edbe4, + 0x131c6c3ae3535f15bb791ba5c1f52051635c44d8e13e7c28d60812a763cf62fa, + 0x274de569e20256784aca3a5ddca5222476b2c06e6976e4b5332578eb744ba058, + 0x4cd6d293061e45cdf3f30796a24e66007a0aeff1b9c7cf7cc869dda589a8d14, + 0x2045eab29038ee2c289a564f10fa0ba6377679514a389b836dd6998b4799a07d, + 0x20f10e37bae5a8193adb95b06981b0f7623baf32b69b61a11696e7a8795494bb, + 0x1f55e36adac5b9b352d7cbe55651b680c4b342c335bd8562fb45aadd3e83e619, + 0x29602ba7068d0b754d8a59a67b5cb83de5a6d86092f8ba5da32960ac4237e424, + 0x16707fcaee953e548b9f04c22b714507ad45c63e242d1f386fe813701e59d18c, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0x26443bd83569c93383cc8cd7a2e05eb2bcead4621e70cc188f6405c89e778a7a, + 0x5a35d0e22be0f9bd2528eb55583ced870d362ee72476e9706625e49bc556498, + 0x1021e56558839fc8b5fb2205d2c799e3b31e7657cfa3106b0651ca9f6e9def53, + 0xa4aa165b7771c0810e9caf04fdc8d6b4fa87e2b88cc08aba3c8ec908739be27, + 0xb711cd6dc591dcf07f400fabe5cc8b78ec01724bb2b9e62d11456b6de351974, + 0xdb4f89a973ddb25f113a6df8e80aa798cd2107439ca4c3a7cb4787f23148c72, + 0x24580560fa1df7a3a4921875187ef0cad6db94f0bf7348fb7aeb4c9e31bd8dd4, + 0x1de8c3e482d87d19a3348c786983ba4bae3ab00870d28ae3dc18bdbc0c8561e, + 0x35ec9a49296b184f2225b3d68de6d1d5a623236576d838e557b150893bea66c, + 0x1f7f2e438c0695e2057f62a661aa8e85793ec168e2aac1ce06ef7ddbdad1e115, + 0xdba6ba79098331b4dc93515778b2497c38c3ddb2b20e6dc9df6ed5ad85c32b5, + 0x22fa5dcd5070a8f46ad637e3cbf69c256afc6ab58dc0b0d98ff15740abee7e59, + 0x26a5fd93dff7f5eb49942b51b03b98e9cd2ab261d56db7516afb897ac2706ef9, + 0x2216a1a787d05bbccce19eff5d852b92e317606d55c6b5b3fb02afd41e69721e, + 0x2228040c2cc6457ecb0acf3ef4699eab804d0251bc75025ea928d16d15065953, + 0x1c20e02da095541abc6481a5c1594ceaa688ec99b43ffce38b098ba817af0477, + 0x106f19142419a86a234f4c8b94c9ad6f3b6f4dab9e47ff3c9d6669bed5ff3795, + 0x104c7b997f5f83d8da35fab234f56c49716df4b0a7318bdae91786b0a007f857, + 0x272b659e78a33f1541fcf58f4cb3e64e806f3cd0e2438dce20a9ab7d416a3080, + 0x1249186ebedf49fac85f76d0e10ade878518daa306d2b586e295868576a13ea9, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0x1490ad8e9d330e2beaad58cbcbabda75796a6e00166bd7b9de35c84dca1fb7e4, + 0x29cedacd10b839b576f81408dba8ff1cd699b9b0b11e16e5267c217e574a559f, + 0xd55f5e0d31ed8c032f1b31ebc07fcb088feba88583dd5815f85431f3829cdbd, + 0x22c2de78b8f8caee3778d4825710b080807cd14bfb6080488f99e303dea9c4e3, + 0x256bf262a0b931d87affd8233c61534d9f5f33a3ffe59460ca8af7d0d3ba946f, + 0x259e4f6cfcc7a4b6d2246333479df052ee0477b9ee8faa7f47da45d1495d909, + 0x235e716b22b67894aef5bcad49467c7c9e8fb689bfc03f058176c9b2f2cfa6de, + 0x91246bee1d5f4063a2ab453e658c50c994dae678cfa15b73b14b0f48408e18d, + 0x1594541dd396d5948b6b0172b31330333f099973d8a3a1a9d299bba6f45d1bde, + 0x24cc95bb62ee85ac17d1e8c36c15cc50c8c66c7cb12e08f2a8b865653cca586b, + 0x2dba892c4f9bc80cdfa40ee9aa9b1c37f0d4ea781c3fbe5ec7ebda39e2272dba, + 0x2f3f255428b447ee2819975595dddeef9fa3cbd71b62f34aee8594771d350a27, + 0x2f4b81914b52b75c46b6ebcb52605d073fb458f8b1cbf68fb9db225e4919b8b8, + 0x1e35a658cb61031459363447cde6165233b2bb5107c6dbb4c2d50c459940f2a5, + 0x21938bd170ef0b687752b8714b803b82a4358bf72b74265a4623d5594de772ef, + 0xd54bc01b18dcf2553834c7a2330ac8163083186d738637650ae7bbb67e69c01, + 0x166ef423ea8ce954adec38214c8412bcb52dfc2af3ad407cc94edf187e4d825a, + 0x304b27a7490ba0e5c20d3b273abc31ab57d4c9c39f2928b81ace40b26ae3454, + 0x1873ef347ff8231585a15dd61cb7140998b4a07d1ffe2045dd368594edc0f171, + 0x67a470e0c4795e245e75c97cb69745c9d9bab71c1b8836aeff01be895f3634, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0x14189f783f0179d6a700e43b6f3412af189203e47b5f6bffaccbb0faa6cf850d, + 0x121bc25b16a45c18843035e84ea0f03e550b85c5d5d865c391608764d8f9da3e, + 0x2e7705b125455c88939ebff9c94d94b32cd19988de9033421ad2497299e1c07e, + 0x4de92a097cbcd0eda877c95e7d7c623205a82e9264d48093144c02affe35f46, + 0x56267827dfdd2c8e13c31ffee09c665605e6d0f76ecfce63a1a3e0ff9ba083a, + 0x214e0300f805ffc715666db69a32b5ded6c1a5e46ce21278ef56df4cf75d6d7c, + 0xa3e3961aed3e8da84d9b2fe01de35febafd742ba83c0cfcd82c48142cf1c42a, + 0x2ec69abd5acb3679c257c3814520f5a2d4e15a9e1eda480e25744cc31074d12c, + 0x1c68a794990b7866dd921b417960123999f52f198f279489f00d5db71205a6ad, + 0x11838fb23d5f3322bbecdb09dd7f8b581465c87a0f6db0216e23c9231aaa5584, + 0x5088200a18b6f27d2d094a42fec2247f9b19a17a2f85f9827bf372ff495e118, + 0x20a562ef82e57831ee85dfb0b18b716e63de36bce2d28fe067a1ce10e365a8c7, + 0xda77e103a18b438ac860d49030a95756dc69c0118e067bba3732b3a29d8fa9a, + 0x2e71181976c28449e32e07d66706ca4fd1b6cab8da61b18e712f5816bf7e94d4, + 0x1321a6faa0815eb83709c5f4bccf3deb91d918ee15267afc6b029d923bff2b5e, + 0x27c3ea888b30068677247481893caf50ad99ce732dd4549e2f651c3e266187fc, + 0x47172c54759f37b2b4d64ac2fb6ae6c6428edb065d5b7f185394515114dea81, + 0x19fa875a5e821b2fa6c2ffe8acfa446ddd4d6f253338376fa289b20e83de1915, + 0x2db07878d810de30ca07c22cee53280d160186e6e27c4c3a0bf895fe2c3349e0, + 0xa8c2b4b98315d9c006a0a54992474ac89e5935a1346976400de47d115ca4389, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0xc098e14e0b8ea8d519e73df8da0ef38276518e4e103d8a6101993f21ade6828, + 0x26a7ab22e3d4701a4d54216b73e906da3d66859bee38d02be8f120e000a5b4f6, + 0x211a846a0b674674aa04b33558a7d8050af880d13e6762872d4560e3f7f55b73, + 0x13595dd19c159220e93fc8bf8645c5b9af252edacd343c89bae98a3a37314c7d, + 0xd839375c08776325c25610cd2e5ecf8a969154c0979ac7f14f1e58a0e7e0441, + 0x136b3190bc5d892cbe1762bceceb68b500861a7f6b590efd62be25ad1c73b2b, + 0x8765d20fa4770fa4979632a6e5b500975b173eca79b0300856e7130f6657930, + 0x3b2d35ea0ad26b1535413a38f690954f224a6f78896baa496b8e8502bf34331, + 0x290489818e00b9c0ea5d2fce994ca9256bcd9775e9ca5bfdac81972b46a4b82, + 0x24b7c1b84ec626f59c7952c4098123e690f221504c68006ae1e5815eae2e233a, + 0x2d256f845196bec5b35c52a663e4cf84dd433348157a3c877a9ad08d41da5d65, + 0xd1150f01d5d7e30b0fb3a6362c631f4664f6c7f6291e6b889544ff778131376, + 0x79717001ed6744cae07a2e491a2338a79cb8c95755392c98459c1284c70ebb5, + 0x2cd2058b448f75bc368a7cdd20f0c67f74206366bd8882235da404d702d2be65, + 0x1b7a766baff43fa8a52e26085427a1beeddd80b70edd992547818c62bd2342ef, + 0xd10757ea13e688a4d99cbfe646f4268cb2498d2f2fc8bc352694aaf44f71855, + 0x1fe27d15068f85f384f63af983d10d1ccb94147d8560d456171c3d741d427f22, + 0x2ec657144f084e48f4eeb405543606e23fe2c1b581fbf942fc3da65d8a6228ea, + 0xb71ff8252f9e1c1d3773854103c48fa3857563e8b2de93b78a54d1c929464dd, + 0x182b99aac23bebb445feb24cf5f4920497d1c735985248f317c36ee35c343115, + 0x26dba58ade8cda188f49e52fce7167b8f219dbd924d7786b0f98fb799fefa2e, + 0x1332f4f2281120300496b962963720e68a075590aa803c5c1cd8d3d582bb75eb, + 0x24c4647a7db1c869bda030a3f816ea27e8dc93909416ff20eaf39ba54576b452, + 0xf5df55c2bfac795888d3aae8751afcbc3f2c5bc2b2dec28148a252de9729426, + 0x23a4ad4858fd3c269b1df5858ee89dd659dee776a895dd5acffb17c632b66592, + 0x526ed32d567e190ff5628e6b64d762447caee284b84fa15adc9384a24ac178e, + 0x144d89dd1b606b27d51d742d02deda341a5f96e7ae5ee380263f7a23020cfd5f, + 0x8086e639a5f96c89faaf0ec803513e9c68647bc9778fc779d144991bab029b4, + 0x24a2d9babdafa3f42f87ab39e269c2edd458cc87e9e3c66dbe8b0cce81db9fb5, + 0x1fd030e5d50ca388859b18fa5617527cf0064d91bec5c81dda5ad3b611a28fde, + 0x21e5cd68cdb35c3027433f525cc2fd4f460132cbe83505823bbcb12b11ebad88, + 0x9813c803ff84a3694eedaf4b1c2172615275dc18ca654c799a70440946ccf0, + 0x202973f7fba5bd21ed58bfe7156d7b29010d41090f63f1bb290c1d5da1ad60, + 0x12305eadf64dac24a7913a62d95aefd45f48355576c671e56fde9cc7c8344ffd, + 0x25c783ad66d6a1fc6c84770bd637f6207097dffb0378d7e0395f8c0b86b505f9, + 0x222deb606f13cf28c73a67216d88b16f5958d5d292ba10ef3bc2c10f5a0b613f, + 0x1614d025472771fd870a9e9d422b3571c5494e7d679824d8fe1212177d5fa2ec, + 0x1358bdd6b7a51b1f5b5d094dbd8ee086ccdcfb9c27faad0806e8ef718d0e2b1, + 0x1c2007eba4d1629846bb69404acc84565de5d24620f75cfcd9f11feeeb3f3748, + 0x22f49d7244077e41f409c0b353afd1696e3aa15ffdb4a0bdb883ffe7a1a87217, + 0x1951523a4270c54403dfe3218fd3d4ccefa43114f1b19fb2c2821a4374718b9d + ] ) } + // noir-fmt:ignore -pub fn x5_12_config() -> PoseidonConfig<816, 144> { +pub fn x5_12_config() -> PoseidonConfig<12, 156, 1380> { config( 12, 8, 60, alpha(), - [9531912189466476916568861603725087174113765795321185751191491139118805372511,19478790955972117697384547134063865214385101762783978876290106323878777065880,1060742683967616999946346623778902980408439861665078741681079083728753884980,903807389911706192945621790390189278582333785459643079682311503388875632444,12234856961774107626670146718644057065701939000315796085771709903680607765980,7144222788160875459149511026237781941826966456792731247241581603475033054157,20698157631699630824067955298548696950174021158305550220448729049898476869972,2568732479597962725718653653192533652726437462680484211279054254158600287844,15284734447838568972934847154537240941736455475374750484902463133334986327455,11481338136657097309136761414013103615752281785975103234128467186355727286020,10612154017018914947135783711517517074090274235061056248497547614631916723906,3055604116750189009829046286798613018321687824856056202070161812694453230232,15724356578668121294244613323219019733691132614053416867337612541744349705307,14233178571890186223833398248040498471414046807101676904418988635462870136058,15569884202072601673299042953201725479510195453493088500579693825511613908294,2457655896277475748047646151777860503559023325500398204274047419681119270433,18721554772384051287322049295337473476448259922773695010270945658995924622719,14475562052679553333706265906284533085428658760049287899372861273825967798347,15603408794229592986464670990674550905587371918421438132217255356917740776753,16291020844798157226549685169153735235751877205762229274467406522127105739380,1562912009705461355815110217333069399929165391790667011738168557818438924927,11269000847557922376283381139665491298931690005135341373215203639253515983197,7952882227157644034022652849613475711023423321505769231128945987664804912273,8477623463686474590677390307150152439632807913002306242882220286965657503044,16240923770208341542260111895431885216031871921759466016566105290964433552216,3342849074804996662671621919352322750206307938435597035721084610748972602222,17931702006999673813463835283048793204134166638699010505988519059393386641671,20775104403560355444897460398679593487716638645215251442678183285176599574637,5119120619161234799144523865081220455479981813019860080498855561756227023701,14966757356872002341966020507506536570537078023526508344654458912397759281515,4186575643717625662604368224196455420957673000117335440321019421096129003102,19732993039041335023904970539797704576579318087957672270477209415993860238993,12070985110749915673363345667648496564808814323429491368289711883810537898097,11426729904237322553170474047093755836047277723343283963043397762276736900525,3316549680511845723553051012477874001156246623643069548980284069093192393275,8181145696278572952623145148622555644838658979012817598939443116317742063663,5285104126733708771192424010645473580676014333664755598112717745696037070786,20879460004955312065246827250994614761073401947673232470833608851757692374701,9225423353187148331993357472363957540141522302215231248106234750413173980751,15882456781720382955442431000301149138213435084361689595107598612703885378636,740238561845104412391944006282242126007894120431256540495139829806405656182,180417058725083825889148913143008776006125349068680455724690397852076567353,14174293519955274733372251014027762210778831326913295280840585355009025244339,8589132560109336742397080501737400189892522466285798728529721670916644735009,18608579889305084432265993644262889161778187018060113992221234915464772250895,13255562856310211555141734542720764165551582487712004861593515585281326120780,20040426996876166323258012360708147873405329072458300306708975663127708222443,3623806905318973096995680510049954452579199046783492207512283522220396562822,11410684734000900004860241940266501902598169149094443542781697771532926351566,17135477854627682759515989387435395911766329083966273406049980901836411403416,13593359321772915930716800157828568438953037754245269488538472861500074218774,8851367853862849158416384345517193602505667487160151588020171989122435915705,8486258745426030087193511835657366486234171438833758681014633470174920075557,14747490337504821136965789527401826047053378817043597026988257648138435336926,5328238162919446506214025777104049372124957345257645933410622558507658284713,11965770224330607826076459132274399741504292999992921785782448737931531131492,6397958737008655664539418210486834384969900796875514632281024739857683313517,19298424785220686762403958616740155152857782164943661260316780711617884649980,20019455348785333548837795973650078300677031008828877476192963238765813699604,498876295068369039941891884133922605442597373275805987652958540603151502762,15673948845182330978914854481229214769118100412263880346214990198207268219918,15636974430517603355685549955558840639961287398389993551242671229593610041279,21849352155479133596816471850644588093828045783688624472176874329078465894038,3710541309080539224803365587698192640065043989988405183436118622332060826084,7400908409303343897763329119747918294591391269311551693625176644493777241247,19095563460120996369257805492605849292942048841569757166438202426234116219528,7450358777752652255259382961368280387692895530851667830759412613948095056314,12616362847029801456780520061399223912377922714639139395311897747307063246381,2962396389753936883856793158008198181187288822144777145656778061306062270271,20597083262311447290143345580862519411179427096464102505623468932397345199901,5990063075931255958499395880323163728626495197217954905778613462408195572191,9361904499252311797420064091418454593805808979929563324171298064587942042557,15745983602860127054098117502599813732367772584805282887983680577406906842509,12155753549127535852899642287036910835293646693799050941038502705904075221647,17784550108352452858546269360461997898333463961938370347697582728197589684086,2486952113321483072183664368099776164387734014933893158352223909214365526945,4903545427310923282188595180893897246459463256398425200307382903876773643166,4976787025628832138140129068285715692634473783721132777844066348049003658995,17903848557396420363857191109854268785343114927997153696759251220232810232708,4112316506554809604392743006504568448930584669405889138267627731770713169451,12564921445775298869601661793895717261354052767541351424764087809438338341443,21338339987232841174606235608205622863643553456415651377028015070388899605425,15088854240518267391884187352051335059960134381458770666979402557846290860043,6521785672326022155410896706891346109402758862672817874198014517122929534795,17713017733654015756718215699238009705617793897969373435335184169505068045344,17520588725173134454654213370481559878188684108641520017594192886986887410727,20370353420481573040209617326772538556774101029132132235011046989968543481853,1112630910445876674622022594317693604373148988518983600314476620278857862788,13947879294001229379895373879944689637841444307211953543137372048528771620266,19992733820130513366333925886960985070219788486605690639975080516132656879852,20463686239191469605722985205294798392601180601616445763439546206772797296794,2399836272490730222789561326076432853292090595513010294231690669763899804691,1034212741378241815550350670737161423052400169194393567236687087583799668630,11440929010875860174917763753574001672473682534215635955505970318252592490865,14189960926817818424784917441574757301766760887770685069486059337906765736963,12315331213328078044898516229848174792421271854142211159524426707506661472774,19715153274097520886062594899069030152815615989925596868748132112713500919606,5263645674775021082527379900656937946372398687742691252725061831191269814647,17116922705336407879424247270343125398621621836566941362988393678055183546962,12965075932786028962944831711285166109972351055088920502397645336995474504411,12016029264981766758974787101200878559176627961323691741528038308088561486007,5729800253105809140207889626731612970039128485797787837679696331851897001188,12918441439057112476878371772096947366502166083699226943980929800631997660377,12122801182972566919042281354391366131886072331873675435499031824985283406080,2001381046477673840829875588313268487326797326656965151814712798463828403972,19581992323872865003173357646589705276192927057599589666190396129558198469295,12032241883699803399815479981073900218390137511663730251199663857029681112519,4486673663248066106745570699596745555749344770988892121755846988206654958447,5880818668316784480273321916242537222449799562687899946001667784663774949284,2395463900919111658295342588362130947823185484448880299307422522723986076206,12950983061674357110606111858229311283119838941890561558124046774295323335099,2237414129351562764861995011211505967387529547007150899242139479636758409691,11297958435815311160313316754342324739290776717531068730041530178142477489469,5317255860197359110199894572100590405469568868980740298600361799734023336258,20883201721979021051679862781044901365707874143019054645125857460321063446040,8182241566037373547703812967620649098015366536333588850170211599244447070966,9597640642388296782056528355964209027337895123387144965957122193392739912194,17036534143228977344737945793420370811715806669058615712195620745133828881359,11612810822316258618979762480131695561483235138506664012253801075650313633340,8933421864748994361777741056369848147887887317449099739627452478628920292098,14444070019150868677613599250973948199109012042816076287250439535772792130077,1409252976182963241946410463334709182528602279352691338387472032099813179046,11952347912832393217697966069578145988700552783923451999893230696985016550129,20459418532142116378042115609733769114184932636063412849272885250416180990630,3551971311295052916014184741437675944777358383038912487497306982998424802991,17338671457268891559841041605089015291458737421392337141908035764681448452092,20968343054904260510606682646995696017767749421435540168583945905747214877394,21712394213185895207403184789091961285240129068046002376558625468598692072071,7634967402785998572909457534910529497063727153788753124164657866643377741907,19849927917300065970782875128524194424999119369431340457180683372405088384137,15012913963479022629048645986836271605475934011232886489828149973693122241964,9429717687014890707005420840742234597648724772846627377968206537995029096421,2567188197501474210757971384017028034832891166328657542206945684532913152990,8254698320328328672738727190211578815599233720695888584349629846354725718490,17284254811803472776585305793072871837922263190673228934354908231725144505079,14935255735939697495362584034949670161356891451287847368207930876840786524288,15799240079228766996307573606262831147697506141321254927976890662889015144612,6455095726770008351501849656650198371508317633852287113372325351871125339180,13561632639572229898860364095655372109051739280251390860766414218384828962360,3063643914261015068338656198636076696013594289440915753234546912875968584726,523490668760084285231907250925228161954264885492417167368043075448446094968,8963235882996992436242593243282162189452480942366129170093695041925502792493,2822355405499444122504244694377602321152414880107322020961544617958820110728,9900962978347352867015759419877923426715239847996616012083851486863818525240,8479746689369630997477042503538860863372007378750903762662394891426272525808,16389683851395581748247134197181679668454182692374139436248933773102047859911,53288238128999697340898456182379718764153689572603829218558226366719788005,19367926616347613140684682635393090785537600078242140764999539757098535716540,15865351283225378120524944291419029041302905726785499676495076019805256191362,3306541431760940351422576606963790342897050957331449111434563465335195596604,15691440019263506851813897307599578949230726834044329611626721124859202292981,5471927110529676053035425189646230106778686168719884591627642899285735629074,21754232156244379849332999145646221923063494235010275675811923863906511018870,12691978963824033486319665437354495198660382717956695927101804737187302726210,18287930615191907073854709805749959615454583394829992950666668999967617218809,19651897318700114806760486800306423305046969021116395207725042165875775288623,14108212236437313184992367338426565912378398742941435667080068116020546770682,16999325425454851471000400176480399381440753089661500361295692310681628123507,3115621817064730307934070024882122808835435845590131246374645701268123516395,7664237802103239138782764325077413451892718354904226049706189059570344004578,10628974555344045044380058670185713528581140293158876652923633181919907860739,14113596208322488293154755998142305972509624369829087071590744312673264784912,17464956897498328434098241327703906248729109105264442832066471889452262140737,3306236514619936703817193243747225028048646569484446722868278187142340885606,1623642646505969781806818562148062924427827461950798461560800231691312453957,20812904557023426950178015281581063697341146335603865156046444216576536158479,19408105996475064309045111496637572365855316086113347445820645560307476671120,19899769975875815048945884537401834080401837433178820364413791122141366658704,19592039825831921790276944621603771771915464940035526138844575559711905257984,16653297576149039984587104062729832787430849403617977005988111857683169262526,9600749907793807254814822662348056400280037933879058284466549496283747987313,4481371968429561669477332540784950497549507725682080986909471734800926537000,901971752662861027246344512729868409066847439697888994727629776003122477075,13205641411901359105414809635566186722302364256582520884685762468367549487609,8771921370123544696277176259984315154171500395079224159374189372693912295384,5174975161282723002634664972730414710732925114695376584668768207090019053678,19270513804464040100949263044402755496385234769453916866026752765439740596759,21159175882383323828715178134104379154154907971797847682741774730382256211237,12713085776674794152643870369276859988930155976989577699924346924648017649124,14416880591724909781230787197474161383703110620356522560207527702042764430665,5782775977590089860582593877799736603230821040322957359619681360364621989990,4476458740184410293724437897879594951652562625859170065641235900450054752275,2721806229175990973363729919729809746838498228946916302499795336059265315654,20919749045138523262313225773151110447007311142131682485436367417448435698000,8313744079461516868330165973726769605125778482558912200259619501953066297351,4735608165219550054732197605756732753518722979705458514715803339137012677807,7197734920840596436781335789800800949073525267054200029424794448358957228282,21023118349982419692339995216673708826739468972915634059252379895041124776477,7361684304536881013610906796097454038829033466585052789468836114776912784525,20982662530655024673207268539471241193218964077396502472563124088553292010609,16223276590978113205386347640415975693035764887550533934078089596214147119142,16855050273631391834996719887442993598537594692357829619807594900987141342279,9447886870473301829371932239272857617552029212858469830955734178259213680272,20832064076469714454949991237859093636177561963691091143340405814107144265638,8639667923938888615556970427023258757087537766667818930469506422086574042603,17264766416417856804513499340974616744303058001571461329697855072803549043449,17850880215521300838724196369662075783108857625488733013926883881070746974079,2555423581835096020752363625782761123603321345233444467023623837801470232396,287393475373800420687070196983041262901299109116957212897422666775745916878,8502409129845334137896426506380979458386453989629214624807418474240644490658,17018903560361810748608552810594034468026623560117430817297647108682661433399,3048293276213593502083356886493678223968770697826563060833194090969377703128,21410637907835525984647506144589609474305790431496436733818309371828966617019,11884766464429332615888730245830253775469158860120272524933094891366345545984,1404751133279371734382153067811682787285007352946819870030827863597870240066,18533103709771766357713924189614422821669511650512088621974348524596673777463,2245746843374377731985282335022648129668387693745835052018700591124673151499,7164798246992914028921284523335117888604816694373355756451086598952914018661,6547792475751145534229851742995938089417776974069115284886265458921995253635,20902177810420148842648372790754609922473216539157084210657172695295335305053,6725829188763173291829388608607411327488468861041838394166490103857184986505,14877246205681405878429147764831613204208078224683457409980647858475648710211,12044111044800943869325640584272709159106488829628178962818078442934011738582,19605231155471418918091518582371485038913937726379108169052428896528644150703,7703294969707260451899023373169584023358521879520637237253564638222384534453,8646812596577526500078198446696820195057640949335282980927180585777038852172,21737243780210633072252501142816485256289884504027720271756348514717163502438,11106629219138713431737722416937344915839184447234152498273695046605412717853,10776231601191535915748483208366958548059216019309096513250460388757814780540,9570793764533387448268417521329594330897759769553789809193103230402046525968,17679865315281322154038759337512810633677645281028940369384987651076506608513,20575490035801628850469464797342943234291317406364190353186174477643080398289,1245923103633930975302215942611213577964303545113844948930979175833556792302,14007490679559289327503467618330290757962057021886611213555145469946035182448,11028796735236022300483437389742268989348582903251651368706557599156682851942,1556450270937619861275756908441730263281625715497049030992434005539032147429,7378353234583563315614681819214067843031828330274954124783678863055213281539,14666996645204144598922205770204386241062541706976832276647424877691625110244,753795180391574509648864319525512763100129705111118203505048417049290278879,14153559413038217294172720643039696432149555359470735393924921410988488820985,17643076982867120574893553230100217333463357095994549461637738074442388603622,3578933943193517852178000450144796032210613197873582924120228282439809826887,15520463167953252157432945917399723977264972626433304226673421190651502497625,17211537329205623730168383274756825219539545439487707555783029872192419895198,9802003881898384149235538364488830129822967333024012959168976309447054827302,4277753965394311084543194762939932271526308682615262493526499362805330624922,3936260403240718180440931086768355327655463497858616640513270218914599723610,11517607066800361513856730397176372083814736323098377670788083637850655404741,2243213365229554429675654538157029776597503775940697016289614299870958139625,19764298184704281654348385808308820923079630109704889940202178107926508921613,21440201729469627284915716136426033084639303793622913729895539439609852676483,18865357344271429482320975819341476664123167289165510208121280487753271844163,12062934463233700754743031150573591813637006411260363192982014497532786059086,7253500424782653645261846666860267886758998073654253013071356444451212225059,17688280285743970528696341296072681725398428119833052669003422836815517127146,7296931094727393709963826609746626294291079390951795401509403882666626382710,8944898010968990710934167772370816765379846965311172103743060979737069116954,2895100563060833104606048044246656016901407622471819180004918143679777127583,10049128690674011365994516711808882356477362224046294433720641467109283787161,20809590643316933764584815864182144455784236186778450054494378700964393080470,2552959198983852034601282535517138215015669324552132996051383405020865478519,90024510729703363025920398892759893841503303159824575434815310687587906738,2438402150656393945636277445769226062775867161339657212187540106747284678617,10290839327200266675482043018636710429195359786802953032677212989307055380477,13366445998820331718698457472184546771717827833722684584206646838628538349970,12045715338147601791240214774093449384918104627310882799600088155093595426276,5295711531017416568724842720044505396040371477829249515344865310124246197980,16400063927954668864214504458520657934817841218321732614334739112437744352318,21834268150215228276838182444784793459928322632598421948695291555558497507284,4036405082017497222204927366812040809401891394189816634089482334837550533053,16758010699927998006904853632308429832737059675503937996784758385473294734767,6851323788614107612891077153396783509346340795017622764414273403342247098685,21242220940510077461844092816930517552035812681947928514550083154475902790925,13803558028343943472219115813916734264304316037691831164863336831915596589841,3876897423511600793257560948470150518761848801469200306022138001232700430094,7873917719931107857936523614722924550340227737594948157729078597073258431354,17791290553613199208672721864188024787529313403544902623821727403694762316966,4509080040196139117885863635009327583647452661266153933806446923314670630597,7350149044068266301432651752105457672961955568647004218727518439545294630219,11503072465150450162639608555774152895393875487845468619329760555955360089418,20146546283112595992038998747954746814923105695946909075842241737548546646215,3500661581148278300592438598016870333493992384875150415517341312342838567317,16461061867640825231072403805782329353930546739796841505995525047519357319535,17419473457085759867681212087981664406569947154579733189885809269345147937957,10330084554893529954763451132860402555512473901655458870771994310647661645739,10271306411842332407495000297515719691188342515212338700550984155237667774587,6010614376730465540824294088181704678570427743830238021642540164120787031818,12211956821531047081164047854393417207581329108889222238958146335322243725690,18026227011560759880520787750218090767851915271628616216035782860818091527867,18039053385352422125173521135868691523650276298214786020953324823686654441993,21572961947836757087236508142423227244602094617521885308238188781724980380450,6952631457061838308719934275464119179697248499343745875411129234786468691942,19811900079804396120677471049757957457743518480096470411626681111649768726526,163137711020707070877550733174177256426010367795106166965347507600009523229,1531253433144642057738530256773902523524280331634644205392973718192895734956,1179712150612295194734157884657760659826346075044485388437451245699680152105,2729710616419138683641657553469892671426309689560939345577118202079250084236,14266054344296739494440365684098525973737250786286154516241047965660978988270,15026169712587706365294070206936700891511371850326743083547381843796350317368,18744742519058537072956390943103111325221767611576688631532967525091526599212,6993198712278030093898597400393962073007955430382142820465138278710889662382,2553141820754951085470014997086944345325965756649326165555729099768987826967,9720940197604032044323074196225989267295799246574437528002073812640512558241,17856885570331180579712689563952926777618369125836010409080422245803122826927,9316647413775248445962902207564207480723728241070369123275732644991331488677,14494957198204561202111268006350266984666563257512595231100502951029167863544,20990514914454458611724181917618445270429441499421925167963524958552424564602,4471904645719453756418626304970674400441871174741396875599881395188613340474,4684361390046158999250125407700867527620809473388545037966531069883415383449,21702205249470184149930308057282607474924454457414198304211876480322358864836,14125417641286741606705374243071146588481196226954437992372061774013416347499,3703736300177825900679993762695155186404123107499914435631005694624510941992,11732888492654216406505460448043873705030240266921135732988822696780340208946,11933466978112969006229130396464073172307879223153980062784019174478752039844,15171000950368540171664824924290660122824429581656415561069429955358449308299,10369486846273450968605452628621668108353399309158716739554974304206007657467,13426080534643441487992009643036732384216019130391445221701162507604477874092,17202835976136422766224805235458239972845135749171745123647755691905320873240,13003013510914746051603710434071109936447243726946691715828935535255320452661,1672563195387555152025850519159013960714433928303467231569405674199001377183,3249806644396047380745964934114987054912135505311534093405371566690536038255,10852655605415322578561541069174913253244788503288539822168510897694861970183,21180450898750475729531605846185254439124003420647553715507766256141444893981,17598208134643261198923845998804266441503487273381944592003474913329048411161,10560430398658881239820534975865220513135495522309722014743734708940471341227,15940735766678288146218967299383564752403182243037693045705028442779781161429,19840721391058424508364187473208857771270089687968326863727366457103504697646,15270655938735284505864085399423312069359806468400434801172200215370037695961,1774340315063362619348165557959238806046379939754082379283600857530102490105,1931473872849034457489264575043647960104881629328524494861951197166741512954,16037503795660448209256659529206619750469738788435653064537663524466496564778,11157294725944164923451173319705000360949753554936504404517553331688337467555,1860977382172821235372346764481514761526862185187436148114012977011560461667,7554608809888667328824255380474433026692004240460849082770678269699854930661,3812849161473445621072899414157938525926417912914872301607900000816805333995,3248257538394266288019799770714987078883986769586407060306626631267726656239,8987711810247040851774885826425578893413569065851274558714617106373602624631,7002808931888012021033077336936962976185388694934605760542880449764655464580,16260071391005121724128685673030785454758719454582904114834030329423907463299,17301316944867831355470414388420250906247821380560618462329913428602672908525,19139125176792761113369565771916762091089412261263410641074341972472699592037,8186463001964086803315373078973607488567538876768905527322257145549601226661,19715283945499391078117757449557157262014864431503022516493444981357377102136,10201366877793384824708227219959809605313335011896439133665539069386849213406,18657679796594390529926518390837962343392692362549805385222541270238612706361,7486580570539115306934569904905950241452751461260355433571179343632374451808,13210602081373832317780583229140785143149759155013988676929972636959898239126,20547921916591862189543062064340935912295194861078724580978244369580188659785,11184938862747662895633149920437248716375494917732149572183883382335006977362,4564430184172465843641043220857544376847031874739611967386619487659896927977,7141474497649513954000384074955704105249233034539438859110223132506810864380,18152904455695511183625765039917137650094202440231199346119983777378283365068,3538073603808733813419298816140509998806938194073503117538238879763400661830,9176198085009858977059589400831647890975463959467315677036348254379008625292,5358677810755468005042017406822742639656433122059352601335552810789858869197,14917263528903508585499167331159661105708948785920472586609175307188322712065,17459264445642522670023202416244479198596207282984954048459225794985333792860,18314375996391380435570814127239902609672007999779514985166492867417826496725,3831982114680501270333115239154594098561342624259756350309439921335535690506,20912918104665637113589191778450022009791755974254243256571842103252066396138,13641033990672188411010402475025484333293999311081344333460071084676167264579,11812251882211406110219542299092601278938747815723382992634003397593468524422,6831378526897417143208721431885442730179700977603214290972417120210221051272,20566372962271447276247738296560940562676849411310335464134428317792972599703,12645078398048087182293658191360551774451388858142913314124550234755654392800,18848512616065065931619133098070120448249278799586409723288680340437325332421,1336951976108001940844939305921535183133161033109848951359362159969984671656,12850569062942139371781102794220985236887099863147625303610933201225464388254,17095240610637692323679811976243261972135774635008876108449261858372552686880,9827905280236638995189439521379169431346954052078412963417337148237294494508,21756974284757687824674400821247092844224232050435881799264172836701664225928,21071024335098050648915070341467331164448998348673899538194227711074199728981,4575704980288845009798550678411618457862054601563658773482638217288811407473,17637889149961283902802970141414602882266203898461797433796173000208254839889,11333768795263093043465906246853631488076833683398258097056018834885708094795,13237413177387831469342322098638791101575804381099372225484902457329675766563,17644690723564191319649063794394358703071761592119981992193950976485565800738,4591566130221102246468298018361020201365534301234509687763578673293960293459,16880258892960147740975242226985692424894589139379261939284621634132328476631,10753253761433799332298845732798867046726308621524332340930656512278172577964,6294042736878992012448357827249736553756583459648169754872627240315677645950,2668606416345354198548309314080005930475082556427535177631964192773305378348,5244780336143933367304708103198860683485779489995095073384345019218674347056,6113177497707123341972721698332981926287006839555002718473535918066824223034,19824522867272770281143825792424101858356781501070734931688923418771980499872,16889524920861245550560790459946848535789402393200784095555799980201051324212,8007523897573727144887255293212203546407757295680344011669395834627039767919,10043972607564040581522896355091368769007227979993058004755493078808025405133,10815879623965899246220301442969866254505652264417667341661157537312485515831,11534947289183790267549825879293816175921818072299730180286203718992863665552,19282679238458671513808783870622522462539288436443040483594699323647255140729,20993973658899710060621174143488118082242133512002997296378188507484929417581,2207137584463635998515616548473102748156816296061395772266322132360447742245,1906176303891379788266254493945992658935732580384991589403254257107793504984,356009908103458769499047304270411564071705602811825215044685668712377389204,21267156990661889558161221297711049481880243497825013463587260785886036981575,9511026544995595131578865949819301816364113937202346971334793771967449171857,8732150772674776446232653795368043280414095192666412295836279503085501609742,10433912179719211724964521733928883750833304291050102060071171195374738464494,5892753211405353458072760353770523366305643800457149832130812257775605711230,6072173732058843459603530982418555383917328480859906190255818160437636798624,12537411810282601586400313857613201485446415283134353086651901233218273826014,6917382548294560607950289035591212885648538608975878502811670462230179895717,17522466317865452308300593635805699602531255301383258028599652149794243037329,13441087273853521452830121325700732493909228483089386934391461759499905593163,16343244966838333682425984150791963916204788641990311583878776392583665902296,5360331632046740140575498209972912123753748791093482084409464010367952817372,17326261745640411514384830391871497358293487167841563962966663074154000109605,11832463539058003103012764436368900007479300735896611859760466513560696030373,9332530307651641794919337618798260519292245685937263028043423079258661105173,18589656636963228136343540063542372097923688201290293330159927366465643313091,19867733544550615468612533273987508641098463295160374186223389748717034468502,21122779377039628476144200947919650885809091682970982371472379500808529828990,3027016623356326893238890601376138710903222026620502687697483362378227239102,18688538985571458464198537125324538836996766056814806096466271703920561848229,7011851562043637216927989978271187524190844597096440024970832115577672150682,6976276474543022394298383474157051715295086098335344328214084449502467982887,17332130117530488369551999111592288939240424248347612731261799228734373086235,11760005773828232229811117479200618747574322788890348748345009852749579147876,2298592572354833593457878362078773063587664198044761229360308644323231458063,17955258451898615415362730916130728340133607644716002859752428726933265234272,1495160066997898368260698151648234013994510168440470178901776412293213577673,9194083678217569822513593808499809262580238989709793956568701401108176409146,7873147134182176342443626581580817861100691419143183095128784103924898338758,16767569430250994260298195321407617265691776202802582359934917139510241475993,21740623993440608033243076692676917908105712281956015230238773795741552902992,13259811027098062609299383180292487555512077058811432839971137250443197786014,9862179315713982904488948286370860706178740748908626205136774943873439543978,5283798667794826693954690769969228006851703579605314207478989967594232871036,4252584733067990475653166725237187089775889157323429734580856783776820381431,12973205666610532230766585121029838349435114222222352682635156927179891214439,287633827640277544463301235265949941438188349560881553375976425107945733447,9088334958857736274159987824864641712847858830802240840003039491617952671684,2339929702478917712535010770935571285116447513742167345028949204167372785538,15676860121778371383024352289403909294835655990865877574625753945822204636877,12764603061737711341313014678756180651482961849974746341425597804386430732092,4838308895208597109198370123135942497394705098532245211834944708850927126449,15227615340505775109084051882530634970803647261111629470904659446755110863564,4983488923883229416538630982432842594678976476580011041728398828823305128910,13108944499697608875788753758764556629418014383923261351989967790696566041318,12840723598548611269818280989252209606886290717050913748780108061152527561849,2952676596403552231673795576822772308483388566436384169804788313391241403511,6122163114479319080164532464109940924328926458633830912986940513870140253539,10991285734105320972904604247873526149047475605919579896179431815938092849653,7998273930160782917435322581864589776803914924450929021174489205585585635343,18738565009620163104846733922742158284630011729404799909319718271414375079555,5267789578561581666385683546519898747246978052550117863765974145167441262779,11531529707082144080873135819545917882620969294873081450175882450957416920799,18780101368050367674291690806832757013309591034560713102040071432479406757422,4294785451272921756656022299749163922793391211928749628139961864310109196353,4709384663557124742915933403093691049837232917871836683405730215659929289723,14881387167977166163300411047605462807380624840482159906092434632182882848470,17882364021447094903093424534075826770336257800280425962604559742290433282224,11702502532561044172145178834042891352292518800414731965233576503757342967409,14059864978850405613608096166397211820819484772138676470000521070869797461865,1780174207952381531321288553792322300359882548955331030522024911690744446923,13028727766195703514931384985263026051594836628118028800883341509333550916528,7588265429164678210439639249095081332309245305288210445601269417147124081569,9642265589138009721420730439928969906364025440120910401773575492361904450076,10203823545087224726196594521548654230876294164502500177215475003344697986058,17120058099854629688232575694825768634386944759592366006492580522962871073389,4222192359475448381394699451673800507222765289015074154697111370954996368735,3993784121910007141124454385846036053674166308991223986620192089439929299772,8723933019744566416337803833347252328328807961776170035099333968332078001000,9712660217038548658606833881897330347907173853654574936296015219821374200265,2760535358459121107870901826259907500576486637522442431581134088651955908758,17117109873353435959712351313249763994000699552995926658366410602189225375298,15834046942685590805387820842211523319635967093317938586307927436446892526328,20540611330857822392080560199608407622162192943120548518785800532555099780387,859364761671967022958373408533303411107861007743219314752373993491065278500,2969887420026581030514962118165604753428498019600416703008438822193590952680,18165207804423071202274226128984095583162198441473954125845000361590859071975,1625906472120027348769657238152772240899619610263515830625917309020852034930,20463932955653127762144495520150037479624855783264043490725916287067071124695,4638144661708592747026214570394653618741348169520846615537958570570478926642,14161574596481971299443338101939032775184122775644932228990090697003591542529,8347184524978696917103428134030602422953969299144482352589164719698955992623,15813323300222999983430155647025925955486314051966513470055962106024932062990,15881789235120065904292616653574390818033995432226550640643889297228035707625,7140692095240485283381028349925581289679980854833888018152159900503732423858,19010917339674038277064587622527941116247281757743905062456743932291367865210,14626089726879708665184866329935404127909714172968102824599946119716141024551,7794590602415713436531570478653055404401179384350609462543106242181653823825,8762400452539506415642761970628528841241237486958209742944443338295503154358,8591771034219068368320608087757251879675617969654197927442982939795060041474,16722135923767200283514351262528880285637400101562656889998995533577538049598,89464124861540540773346410834052352014308242060847315373495379383140228595,527363371365063907312062782674442937761539145521639367736772902232593392996,2507841963726490485511335482108618130879932510673214677761709746737826243610,11600559113928855816564236457966654301430060930571013803772049573600205529037,4588632959705258135254026492226920833318427708514752831324568512946022675194,10614112216523109461118034753484116653637318222297437542653638803709000476069,9172525851971416839816439437260881435627775489982516326698553647792223169716,5792656644651436247861358501481981837063028644438334753333821264192324104118,12896881102412475846285309217744373816727588379892851016206737393174951411645,11468716910877986153680082696909131615615571055661580004775449060276352989554,16433370238306953119452573705529989067794419309147323079675422756276020408035,1273883504219371718563834088540759123243117439006904940363157254976913033897,12035946135822991823593467599431819071656367730183582372112230833767543617935,1584468415480349659495095652095228645182004993793756033988320959253925346826,21386287619427343417104905630296265178906342440158736945069239788114458023785,8353771053561995945612416527531464945642582086497086814556341372197660908215,21451387710023590786286131498774138351594763095518652036485484549943942198584,4310607037909191923700937557843586755810945477870372794480216273434853743125,14760194187040766562518106717503624683554510559335502353786749509033100485706,1989722256243159180961728174407914946336713030784288455577084756567680416269,6686508185527220254925691658356528598024140978521686081374828691583660936030,10702736220547282218129581824426150350875608542279410979052446031034395032616,21518832429688884430739158604898893220375510075322761868526168806092202700739,18894734518217824473490018310535147336620281698236505678307171602214420149474,13651080497325379255207286313267854150042736096310351308026009382931418587349,13005423795701931110183481387065874846108794433756894029607220148510576563022,1791508640954698127256430696076954377556671221508186631495000025000560314469,17328036510202475587667192203250772802218778208191122529787186719212302087427,10657963758634548274685968417226435837089760791121929723402922305566484150027,1373906129582260565717689440357805911187492936689152530374097510483815842229,9959127778329368795108284764279846598110110516049484774588901738715030294501,7658768549089819420025961609972525260083323240153758777076357709438863924071,8556349016311563259984530239150734383111823917689615136867121162886430935013,5584784611907644257624218172047384219563403421449130896517357173082649535408,12250428484720929053394094480089037225116943346244386549438429776642627577081,5894587027805929865241808030013307622768224687737099108946198448930484926182,4640000227377695114780725548825120725107463526354871525420448370293105443156,14209260856334030476503172714481690115491571124367768551485878619193949022436,12847259932859893012278918973069680996469229489435970735462165583338364177587,14707765228045361126133465815432967736466274565508518646993164305646449611538,4776938221827642494595066454007024055266353658953900973539209110395754289252,17345634507638246813894504405651157443245008745673515073520154967327741083655,14030342049076255140305545268617582878430218358427444316024303212302433090888,3081608613732784391792246085705209806228642369232320349344206761814264266822,6925544598968002128460287121334907968171640408686960604018975554503413545297,6436833790683001261207201071187060041301666725391276179040664384301147754533,15822971282077757697408895884235910303980603368062126288859779292088533186609,11405645516905544384081084440311050207481018746793339445931815864373601814301,8057851956466271394801907096296448157702512819801554261185443997708792484686,13400701029177845728937105456192536667124279186738602373189177143094323643048,11966218129646969536507242899486947493941404691279766045602150839476320695158,15426703084090770508053125497176086377457196612492405232875849008237608103107,6284964429736232174040445851307654679317453722810844133660225254133335862235,13541475439682330895175095901646773164410091796597408681295206023344696136380,746760486363018018017386520506969904420399625886684141218702464564311095236,17524104887381990279039312517306518062132617046713819525042298049738730617133,879502104476554315787832344079612181105511927448955207253764010183827781938,3322243116889956217287455917347322211093649776443788544812848110324752380511,20993304704177227988946248236539217504266305909163005794546179470620336655896,15297086470600095823350435092749336605284701364464412627268330863173424318784,7926831990131610326614433341787624222916431629609577848917665290693634271603,11271157869866761687706729926953398656059815012440629723619426315368733378302,18299023753364987381538199358983670915973737470621191699559419975990005285294,1896523269277706381575521315908503178186583134996425770080392278759498041496,12890346501512276297101448381578516979954988837373044432656264176509301317397,50683999778726139626379750772467319774169558910797110829251191014869406584,2535823474764747710030290051647541950275171691698903262059516064562837569538,21244438525273542723000364561332886617309030482024380299212725538173747919525,3566180332124074953578668480009215478053830658040437750684892555496819182968,6934760873335280553519652185111971021084408206212600990256329557702647231767,10716990663016621229729175818785901525044168020825517922453745625674725718755,16032906457960033408967366361214250817346739568272864358714497113973437241307,3843556041176221664914001975628278428195138883854078534543734996192939783081,20159201956050700213417267403145919082229292739510798606395981692137742005549,3946206250066677142194595031646387588831888396304269420593204783498093935566,15041638172488186356886629449548027800133537204416329580391498341162500701165,13278796648404195845011313500265526847654531008699937318834233691653233844557,9401997027308433525669054020953469816624994577441846092561461184007344721828,1983197599992175511555068756140439953159901969155075046465287261273690782516,14404434816783701517710626513536590424905462755924351795276920360393132910619,2265153992995968786485646516094566778663253373238301922539677847420824091645,7566790081073938501935204486802755123563765476651717380300659543531475311797,847895502208273199247564103189534214890423186204714047221696858073193176165,11963011786171849258296957535441472428283852585041548938428326288746833247421,17377294274187023009074658259347356248383537938503682836124988411002248431249,1025753579901801011233785198665030697958075722777337374303401815648687864152,19284019504590857558072823196945292661333776228606049953803221551974077538854,314204118013777455817026750462293710777754680076389729833422020056750157783,16480262479960754021966845575947830901794064422051876558808623512389290214607,1118467174052506904085279606913979573425427098904935496893365844271017524128,19632743231294128529717484081406317899334378150630214776880617163102648968680,3911642624469919820429547144355740104724495930390962678347147942124333228884,2066832981312040153658964981292230050110396574171753029116180129049784719869,5311750082320962006044746418239249402583149931726835813032955695199748985964,1668605805291951132468779303736499626803321838797652736089353191224211818512,8117527083300107176240321998574781132203045054266787492339353711594335529709,21295747743511951700871264160352432803897824342737595930859857743511472313518,17388383598447322131131146498858701344049179581377651662282122447439867066027,1285164961547283134680842635704675169007050470102043475645519044978941760131,1875066966449664224570600546742926101175136253576702799078476168727336032193,376316574400845651365366460471492295014146006765806307181242245707469972823,17926797393698382320151787394969682377223530524132422415508830165925306730854,12888413344274698384267384086384474622307363694087246755565655858542934044367,2287154516202749380541196057272317720805230156010471100500251268302509398358,12091269896021030725381711946583875149737687962883250402694805482865888072651,2866048333839936509265230844807967492604533527765757660355779329791008604324,11835071699154512268334373994146252361488263767766913426957050581680705629365,9769574961167512396467538163460983111263497516872198932597594846643533678886,6652717430998307400653769850757364796566010885765190753303419969578998970914,11706514210298927940240806568375915039663039872151275540599047371226868127844,14503173259289644850389467422758670421081762433800521230764199189580041755978,14819563269715549434612532555018280611140077716865566327825448288943759458075,10680481968851597237106707337987338182186447633463836689709242917734021556532,8842568676211857695295830062491586931539601201165478151045194686251206282625,6530738090493870852939715092085577161577833016969257865187421674974986108366,9122348442271830670856465114634608231502719005088669868106730029655164877153,8276880496499930549062062890222235677345093568048001523633692507246467514288,9159103567267771525632277936018480854652194329966882107551346987942837974086,16469319105211987147868896414457254521940280033150431057117354850784171354412,10187807714948737954868581824072203418416253898435396377923197796615888421106,12487902950231724077418777903531512931204649041424531773792238730349062186046,7128847500406995361903929050204217572789701023482188856789540128660376992648,5624482939513897521205456066520453513748417048856589163079298385117683428424,16435310041815433976313715464222273283215148709695464992270777828213079073600,6053110243546717824144224394047966869215089006720239359415188827006018953287,12155283178966050547567835509058470201630806787546132608678364857190533906654,4516299433052637321210501303761417706907638446979735686067715866937355560218,12667848710309960989666753249292981950689410172688589690222261363826904222200,20798966719534261926649504156624517814254561351583702314533431478871413942185,17967549743799112209110259394081841952094330269294500558315036929658897218889,17847714150935110939206476281446907230585782511584357788270839909827513843593,3706525735092193828297046649401002937097518714707649753675691741717374375329,7951431498272893618049118070591089643051946670270891223821638082032777246372,18050610739452223409884731462410705437134574403721907246909018802102148878228,7681233452521913704953218921671929208806506209990716853575264423980840711485,13423126358538883907022095116894303361057277664724853411599423630968340874618,16385186307753207860551232886321416660506143479955163989130433021552655688751,19863338799254785908021006319182666048802363286601429063342266271260238637645,18613864443384979831007688916611349052439959929170133474546815634162799183324,16332951432721718166552572222119667287478083212745997662304261644978474988848,15183520838042840868796366239500461619005160337097541115133209726620419190272,21819632461581352219365791577295628387565956152415171439862191463144627141459,14048533271709057229957508911818231901369646548751751133058494379648714713155,5460165509823151384714546779805746551465260311624889230527298343216031522426,7812320479950772901428223193019468171803323319794359571259026602925413892220,6861047298949697363524436975701264276161947671796912946484193048676968364570,15350000814702190667768044439440847568690389883802239839819456575900015807805,13617689242559757166326885110516025083265117478902533337635065578646035372109,7476843340092386505769477537028758806323421556263090744578424892783190404262,14826737006932111183364733677544376863485041173382717893595766527131815613201,20482222533304950354756700764919164516648372491559583778492129756055561547902,20761958166613639518991371846609568602964716408676516216766187562459779452764,383428479364004198529582849470440881390404766297544454256885030893768964772,9096063532469724072461386558496798312147772678120608720218640484115240695555,2933312980053872879818024429044461919397766967639471518371949595510364515880,9299316327986512295931957414766538459714522358165090755549540858707887390215,13488092390166418062347006407529577052576958127764741552594028975338262414671,9829077383468426688376344724031102291718825262406301642537010429132676001524,17306252922949843274941351200908184305715966839608017699204279919732909328171,17087445274779483487397521683084452362124400111143021068068404568736590545834,12957176730411938817539171430465916443660534484629425102659921020718336935547,13051137677735706323786222675600013609665436923061132301167672971485926193799,16896405620483797393236904159048703206424672638297382666760526590725313874095,12982786219003483259026043754729673677479461289605569386777999422861331902406,2025152781178874327274493576789397778291707054468278801142821085671743579422,4335304794121497318666085856101737871981186359433585080678838732369068576376,12639022425423716913754007933194900468141465623346480681305462334218095484056,8623058240535559764777469232729047628411050024996927445391922152785990079007,20506335897603554545414833361572976187621941529253485759521266317325651663673,21253532477517846630911098846446871983813752932337294199438073014278982612265,7690372912700906813961714562821752274841425123411432854046237798188463759714,14774079281706150157728885377093724231164512116594840467791057304501073046227,2057509476014278951878531863305791034496952436217061173216277825372715694262,11541539364361827516114507593054831030438985642093836719960774810015976254752,14751271529818502394785288765886130704541730104426205431367858892918636267768,20653824984831671829709191706456216192511770845470322444515326861038843106056,21794617070379980226628233360507465028625654800811478227502718633923944312665,12337675699660313500286885345145964244870355316351529815248466118884457457726,9527268832683847687152279087478212995292048665053951255936397859316414854388,9676848840550815858798680133955006115514366150476209999729932493584446713554,13718457801302749437654397628557435190188493872576865462727587887532950355038,3867324761996955514268635801392015956546058763053808698121442586705196957126,3945177530905850250597694151686052963152292050981415927393741981018273529029,9473309264240097344589730948390594137445381539328377904021534848676986947654,9996385364578703060792470002743943020203968343080025005448261317627854389642,7671875350824730767796781844941080563527207835942241721783016221076158519589,21342545963270813418079341151020475012992255268798567166496112378940512106806,8273987785742417777035293384288140933989540189974521462819168552306151314447,16162516432221515902182136237589464594279404001688534734264317844425059661177,13403805360231306331901242144909690435939614369536490494604700225511328976179,21640586272648741017978258285249302214133507217427529405059807093199643534960,13103298902142682492657114828016226525668797790480257241873358498200705227711,3251016042668618943397347852790038985788901898321438389540422820491143534512,19418047092207786422594959190763286166909227118034848590779428639908706128141,16018739283901993654877226905623763753431466873170287728134253742237701259452,17444946939314191179654576411859454283526068144165928707555552999432295774923,15128585121813842824984220733706899232093493608422847549831681212432769497258,14256042951767483060181875165067417249801798477941578288282791927486641413650,9120441102041865153472829977920901798404277796873323854759847010789551358565,16824614118285494743762017938800453590083305489658290570438237922163546634147,14066296536773839458459021526010711790088172526749593960873828093107983908643,5017173601281838065126812757441844223954524936921765951283764327160567691674,6254306109691187702602819001106221686689064495376117914248886700342291435542,8093845266500847743481398069264511597137596242374064050252920004891985410254,3578536483838573103029984288079029549393340013685219142070711310306738904812,4046636520929111297180341957015914921052723918845140326762981717454102872515,7446649718318072281388998859356555024817100796345520325890349758135889404482,12366828085438268177090003236704251656102820345668679675414643578247762288715,10235336658636336826692093860668421345161445948384101191460476320469211290719,21557699385719674753050624572282725191612933706864216121110471118396873804204,21676195031234643974566056999169564975565168161106308063972653296222128822558,6363029841115916180506080615867336124807912331702908898766344258887335068638,6363363442473598630315975560083028488315295047134858188348763022659100540644,7124701104304155953181957655778532711129611550814127577450223681003954918096,7205717562822389401795306034882449236003182581929449060008168502546885140420,9228704321577313703028591075278114440418729713968708821922150367010520752433,17614180549151511016628006398127365390131305608457060951973438257438000114647,6418032200333926158639440620980173724897942384057810379437154014285875236793,1563831431103246736895130173427149853201118983353993792302858411456255839836,2319462743404521965297213055024756354349733992588917297296444679195296432311,11927767606932195981021511932625975307755048477176557643420944859867328059951,11544836785666122785129617591037772824479186137515525949187438698705551844116,1594554937757396474339277849284988438779469013126014780880063013190163371374,3090898925598297656723114627648156566177591433413115455417582215942083585019,7446365483911748580722671015415226813450613606623816089630076567220802142731,7277804562221458254100595374565579800145724793164291138831756170012315181874,6742114513180059066582114839865181272182587124666919323239785847603969045455,17639336822454434815461281360929380680585323524008927548062809039584978130493,3577053914395256679157728351997326335158820293078866565158939674077090010647,8416461669288393104752370629542582785060946946477447413022986748926853429341,6094400991411029253990297530870616276561743402531435382960598226029406844554,17249210115827920255165876773266699947215322191164909559927557290769226533383,16910579881016588643870584852395328514859173042128957721312044020554328803878,18548800605828674358041671058553674062230830447893195908258772241250469878618,19911311709285615075760278233929935358167599770457743440215721586291252049005,14163239340563250030474254441824385465013759375574504142110478434407678615583,11636512441693145656185679602762396225011813780067642639202962721478584613773,11627821975451263242823912745820712501746551642630006051017450144021728526893,8744830043459757570443313311577350804214757169018319227421153827794333111861,15502529014760684785001315229904504412899268461167235130234930235025949266727,6349631474781311552829280885666605465500111601027794362415725063684145078154,3750521632595755853919734934063554601358504982902984744970328457148877834110,9151149071511054371049219579896119997746835784236581257692741291133486546793,19272083712610290647942715418077844472245445971738771938657138000646231164194,4825691749471936225587218745193692386291702673577201485716323799193545312215,10104595857457718843210330892798628518507052980455210862700838136878095844947,583353789674136864282067863249996585561603923757420881823548159264798915805,9605601189839871334439279312434848410060547509366999421152290140420275791851,9086947882810130237770476626970553738390827239675874433366363671998428155733,939087130792625935525433768373221635016459152936104283115879791761930303865,13281505022430256926767514868008519612680654933479762886734630854898956588159,8791789091182070262897704714134448615861594471173394864103714557845783501440,21362425094620759937169033441239641099917726266745789893288044988022041089124,21264794594588373773536904588090499011630449220310853635095227724956212914745,2201440000983888343103152416697093803247262395826184450099145084240341640621,3661470436482399872770855708635287053510507688269721514323020960038319367739,7839180633039164608733079650881737341586893235460147432870429877862925246133,1364292691308802542355455613317294540368840799230835218243676354771769346816,8772467089802087196594680904948784186594877728663145042664601336273257169460,3528294282612889297228918585517392070857581849271784732463382671241778115171,12283613789492092234060914364373118974353698674396863245366831728069561564466,12820604492590938203463369747918352644874868843295488782427665387357902190399,13019897240405241197543377542947534699610589548844172163916774096781016951470,8978439745720039208900766235834036199032761881062736449080983584518864263026,15222275515593239598230012498885809744566950744378381699594010392927659453864,6158846143100676033784762660398310184837175038752344358512599894306514737286,3419255917977463022603617504775890366430819682320515293245827217078337799273,2797549320616484645720845216321636133654549511963540737715630452964584943931,17033753202496389008484483700445909344644255293271694371709019653557282454651,1896525136564670388001069429586407694373044886658459111231294687089652643180,15410846104953506982390647924353051056630524372570695181992786623509940504512,19568185152800187670153137856814273221696851955003399523563214963248234462015,20371827999905064832491002071821973934784290275145413746617942892257828998608,18823477734276348993184895526705908983521278925070561827518170646437136680627,5656115226652970780235535706189807810471572029095698537591078819723656151288,6421434687984511183440563950015895899135677057679953590513947822215985604920,12040384754225464077155439050798210419160821091649797103441177013046869869449,9772259825341200622705640733478002328903138705997041039987261797557503104066,16498280031288829288227785307302736352936199535492502196962915104633784174443,2797879572297199909334218711222177900854374704477138347081058961121300793309,15644078107885262244699428484967291897698559437568086329631330880220396182101,1929505350484341295824323699861178332578728141996333839839142429658318709684,19829107623275996909068882503976730773632786622439634235897400991781002387336,2349581104996259830058120951667460730076264470159293978617685139254844279099,9982268711644224005105745225708318829304834159499232155579405472268549361372,9283048909915207444384413611285315401509676836116090349272606584736947471535,7228184586853275989616881380719765868918305938029647325846170897121335348738,9356148801854782728189493667017091537583121935960987886599900693915567464857,505609318575290577159607039016980344147219758564644283699477849237669899416,14366218774993226370408163695258733389122646477999733966996434517776361579764,2089359639878444205205504625611416181841134778729917955490118311877471215733,698820948911402576486200349924367867353277614409335325450207885100392818369,17294754169238631079500422194295778880256675645147530605338890302947026045725,5743114444764763990137499217919738961538814043960695215081370978081114004215,1532354676442440269809361487929394117850339080897231885482935144216545001511,15429279362464933048379761813318395642886047028548664371898579661267949218379,3996365200571187062769515782559269970838089444839642643284597375210723401466,13855942579438265547807447657820171102227439902714241541267837936207338677600,10017315263017624310653373895363026608166903346797759979504062819071927130663,16907630432341625239068562338272519243551636457245225084107387534876995927261,7499064872525146201613148795250282369576850162788310832273877734938523830020,18958126705503391332983508022395142836904315587480202621370522508346095401093,10592492611778631944134585106195825750734295091365114316628335289401976557048,10233935978161235645487498670591630814869863266947595645533111837358567006403,18003113120454128964459787917100973688362112412222897499908177070949705432002,7039143063746813662581342159908917130120555794319120640254054115394750527325,14642639620523941644124538953496946557379420056235185193901717503194398478844,12510354962778923417991098874785395513418703200631409704677335762559702597729,10937907264762102220987756825649855260366448774314976509103469790406549413612,2856291402269285412222070625188683697884675330846580808282552440813379388545,975737765008679829063246253813268073237541742979444038400325932865440884821,10846579585900798888776933082578183338805087990458930175500622018769094956268,4529602228982157635664617353676370544979061743349920696434925695574883870240,3217171861525061655884750653752887679288235310048470832136609603512214131719,8115945363448342140068934999604399115922267391140037880996539055087195710388,17017061429975823256838374218603998280878588780557395344098357759667769523464,17414822882733297737417491176979790219384604825369331340721407024843872424842,21674124478965998545524545297025636759207453169144537816299040483190680515948,17404327139726954519140759696696303110669221199013129437266401728134593481209,17114525865368445983838697023323950751616885090116888636158517909348665004808,13606067029568271979635008642466621607360271211611257253834134991337929444625,12697011972510852002753203688496604009044404157472710768958968780456921052232,17908262237776925120663573891641823998363270265606050465713306950786509533013,21456469759562487171462776687926242591840822996019886989101706511495101340835,266521013932216168881283771008004557613060760037591295825839278412991410595,4426122336489578598096667658844019947877597098504167195068107491300030650784,9386708946433085177945274757444606300245243689157314090008872819375610588441,17571201661176038894845217669278055388543910674470132087585433795958011317108,4455879691406517778738600662496288227132258098615032267607735047373372289231,10411615872931007756022633910690379435607807745769276655537160609832149769392,1369325193519585971093564667957731115918550810109208821335573114054160355015,11701493479673417478812558973813785951698004134589804881992366063053267216767,1604976076096057025943679983359889701146704427744088265030663068037609417365,5807894190026658662778129602314598491833803649976558289016319277596337255402,6604568830557716159440870492208510177395633789687151427836556682055398194130,13221322798326908033948171538573182873220915914806870794442015701313412462981,4276423994177015753526554880283981182675757973382385661312000468093685717116,20731982721228405909675906960993136550102478961136398510514645316644217252635,5084416110782735943752807643199425478022977025123417839387489101289418017943,2080632875247898509655097068576655654491657659787279629928499240720334125890], - [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] + [ + 0x1512df0135b6692589f071140a60749cf775c642b300da2fb4ad5c6e23ad4e5f, + 0x2b109ae037ed30361cf6544b2f4ce58f356589896d6a8849482ed3f9b66e1198, + 0x2585bece06eff553d485478a19eb149e2111ae4e1ecb1d61fc10cfe1c077f34, + 0x1ff896f4c0662f4b2ad926741b481d03b813a8cc343b9c2d2bc4819c70b2f3c, + 0x1b0caf02f434fa3d4cd4fbb13d3116ac8b7386a5afd6c67076ecbc3704aa45dc, + 0xfcb7c9f13c85517a7805894ac82b57c06f2f153a6f51f60f8e508684dfe5bcd, + 0x2dc2bdf7f43812e39cef210e42e92b4968ad8bf554541182354504d32cbf9954, + 0x5add9df20c1898da46bbf74594438beb07c9a65635c90f45c0a08febad13664, + 0x21cada6641664daa997fd55ace8b88191cdc4194fbdbb6ca5895447c8a58859f, + 0x19623504589a60f058b04489b153324d16ed66667a04df572b103590b848bf04, + 0x1776442d850a436a005e02c6475b72fd2d5f84452890c444162848ee1d57dec2, + 0x6c1691fd6d2ee98396610f3c868d70874f24eff853938d87face89234a09a98, + 0x17f0d5cf360c354a57e7fb986dadb3aaeba094920e772cdd9abc75850400aff2, + 0x3062c0db9c925c48cc2f80b698d9602642a84cfa30e1bd36408e2cf82ef3358a, + 0x239ec7e4b4723c8ed35b987db03d62c2a07c447bdd6ef183b0647821f6874c2f, + 0x2bd39ed7f4f6a72d02693e967740b5fa0314d9a1f8d9f8911c28dad3f15ffa6d, + 0x20350e75bbd562e339269cf7fd221fb7c6ed2cacfcc9036568bb4ba5cb17bdc0, + 0xe97bb9d9784920fb39abf35a433437ed6fb631525285dc3c126e24ef54e4b8f, + 0xb12ccc871d3272e80a216461403559048e4a5b3af445eeebd8224a7edac685d, + 0x1dfa3b05c202cd982e3d73cb81709d5d48b3cc105fa78ec8f0f216436826be2f, + 0x8d9fbb0715c9bf131d6de70b288d94afc02d46960459fea30e0733ed3be6b, + 0x292b7514248f1ae662e5437705ce49153e5be27c212e86107df1725ff465332e, + 0x1d58b0684f64db621ab3ad0dc98263fd7285d6bcd86e07a145bdc6aa75c901ef, + 0x4e7bbd68e9989a91190082f0b29b0b0adc2be282761c44d1ba687757514acc4, + 0xd93a5374677c75bdc1b4071b1948e53a1b67308e70ead178725b08fd9ed8d22, + 0x11eca18889e9f49b1f97d5998d235f97c163d1706b4d3d4c380d9ae1f3e79a28, + 0x266b924e67a868a585b398c2e3f28e3218783237862bab3e925e6e7a9d659a60, + 0xd2e26ad58eacea3b6a14c1c7803caca7ab3c5881bc6b5b274531c2d461867fc, + 0xbccba4532b7eea6c3e40135655171fbd92713ef6e8218169591e5013a84bddf, + 0x17a12ea9750405b3d59030af035c18e4f362e183da6b84e985808f320211d061, + 0x76510bb9eb19070dca388a1d3a95aecc5de4a2c69c3181665f982b60e0183c2, + 0x1b7034b3beb0680b858bc8f19528e8c122d6f68059b15c70599910c993b6bc00, + 0xeacf7ac9862ff85658521517138795da59f4273f1d969f815baab2382b28bd9, + 0x1344043beef1afc165d094c8c5da43e793bba98b579f2417a19fbfe538e2cb80, + 0x566dca10a0b92ce177b6f7282493e6b31391e6edd3ff4563277e504c441b1fa, + 0xc9c6b5c46b9877c2eeacd033f184fef497d2ed1a1ef276ba4548d05f3c78387, + 0x1a5f92921d4f34a7445fef0618f1b1a21d68714b80b6850dfb9c834f988a96ca, + 0x14d14e621cbe627022809f07ee078cb2b3fe4fa024715e3f7192a510f1d8e106, + 0x1b6f67ca2ff07a2de58f7a0ac8607c92fe8c4133355938cc9812c32b12b8fc75, + 0x4c3bb7f555a1a8747edde5fd33feec3ab52f53dbbe6ef23f7c26e62de26fa12, + 0x1aca03a3d87c90e7a3ffbb8233149beb0b6809492d33ce3e507951aa38a66331, + 0x2294ab2f143e49a23d279c6fe914d67ee878b3dc54f9d7ff107bbe78ac2ffaf1, + 0x2fb43038c0b4433ac0c9809f4e7d7e688f5c1d3c08f66ac64397fae941e6aa43, + 0x274479867a616c602e87c7521fffbaa85fbeb330128a3bc8c8b8360fb5a3296b, + 0x18a3410d063b4e72016500228d8889dc623201b4c055dab660b65347fb4ef820, + 0x2d6fe8d3d694ba5dadb904fd6904a251aa2d351f3cc11c6d1aa94ffeee452619, + 0x1ec5182518d6d3490ab0b3ff899ef89b61119743188eddfebb254dcd2a787e20, + 0x263a061f3ec9228bdf93eb93f2695fea629925d6dce82f18e6dba79b3be9ed0a, + 0x2fe0300a8196b9a46eb1f7d529b4d4c09dbc58765a42a9f3b61ef7c107bcd226, + 0x862f4486dc03350ea63843db9da09a5a3c3012c0854a7acb75ee18363dc0414, + 0x9ecd01d7dd15316f2d3df72a9e731274dae116592adae8a81eece51a4453353, + 0xfc127ceee377fedc0d2da69617739fe790bae028858dbe5db8a93e3254eb8f8, + 0x15d224160265df8e5e4c1b61e7f9560b3dfc57649f3038f440b64e928bd32970, + 0x110f785f7d04151a37b44935a1bbf4782afc72ad28e042c42fe63e6302550f50, + 0x17fffee137039b42943e6f8d044ae87ce06d5fb1c3e2e51e3009a45fa1873f70, + 0xacb1888950067efa97acad9291f63c05245cde116d7e0bedfa1dd90dac185a1, + 0x22a4abaa581375452fc3b531bd4ed54fef9bbfee016e665e42493f09c393fed1, + 0x25adecd63680d23f87be6226ec05a2bca8524963ddffaf863379d4c81fc793c4, + 0x220ce90ed6442f459eca1fe1f2027e6377e7189e0f6ef43e1cd364e9ca1ceb9e, + 0x2372d4e4009fed5ef65a3641db3c8d6ecb33040fc25989039394481a94b97195, + 0x11926b0acd944afe2030cf0e8994d90daa535f465967b64ab0b6cf69e316a51f, + 0x1229359753fb4a0dc741da84bc9758aa0a7662b314a31fe003474faad18e3800, + 0x2b3a66d166c51a62bf6af2e54897c51e45fd08bda74d5857adfe8fe3e4bc3977, + 0x1e7f4fa362bd86d6927781af2a4cac46a77a19b28c4ee55b2ba0881d2f7b8e2d, + 0x91f7d66fc8ea2e7ea95ec1876a93d33688f9f9d47d3c8b07df92d1554e38cba, + 0x2c17ae7d9af800bd393b5fa0f8b16293daf49e5afcada50847795b87e12b6bbe, + 0x266e76891b0271bcad1644b852ef8de9d3c3e7a53e22f6cf096ef44fb35bbbc7, + 0x24da30c34e49b417e6ce696fef7eb94e67b4d74db6d2d5cdaa4777c2602166c, + 0x4c3d31703ffeea22ef8509edd468586bad669b74c25fc9ada49a185937c2c94, + 0x2265314c66e182feca755f9a0cf7c5c7f7db6b501e010c283159f5fcc5bded33, + 0x1aa1766643eb30f96329fa3eccb67964d510054db9599f5f2536d7c37f5c1149, + 0x107e8da68896a4d3ab40eedf2fa75e025f787dd92799357218e823fabebc8947, + 0x191aff44b7bf99027bb1d6954ca0901c950f7ba8f1e1549475f0f28ac6e72d60, + 0x2d6a00ed5b8ab0055a4277b39d178918744ec5b4e5a392205dd4eae9b4f1f507, + 0x8bddd13ce3e6d0add2babc5f0da3ed9c24e10aafb289d03e968163c44f4e669, + 0x2f0575cf9b7deadb634320f90d84678d771833f9ac9d1b67c318973fcab18f13, + 0x1366a05d3047d5b3452fcc62417343245ea727795fb0d05efb80a75e1e4d7cb0, + 0x234dadc295579c62b1080fd64f340594eaf258b94225fcd6beb10e5efb4d6fe3, + 0x1f78b1c152a40027a2c7b0ac19bff6ede3202ea1b95e5d0af43125a33cea7821, + 0x1532e8db5fd0a6c2c785a0bca111741903fd089d9b73715bf0dd70c2e14df9b2, + 0x9012747fffe05e8b4482f278d35a28c6f58e6d502d69a5f351225225aa0279, + 0x105b192f778c42354f2a979d91b02fd33c52c59d542a128fc08e5d11c96fbd65, + 0x24bcbd8a492f542d2e6faee6c503c9c6f7a67cfc7d8e756759e0bae679920b81, + 0x13e55913295f26697ea8ce1aaffb07373dfbe24b8f41e789e05d8b96c2dc9e2b, + 0xac524f2908d8e1292a18ee6d5ed583c29626eebd03a593db01a61599c286139, + 0xdc402c7aebe3f023ca4b75dd5f69acf8af6607edad14bd806181077e41168a8, + 0x6d687b70f200804cb3b39546609c1ac2309c4b59fc96c7673ebdf2c900d9400, + 0x1e0c2662cdaa91336e10c7eb3c6eab12330a99da8a095e928f73a8b45accc8b3, + 0x14be0cbdb25a5f84d36b415f71ff807f9df89dbe6a9850213a288abde6db6264, + 0x2fc8c8938e2554d9d02e135eb0d2bd251390902e82d6ecb4ac37b8ab6d12233b, + 0x2059f3ad1d4ffa2787fe0577dfbf12701689bb3359647219d84a000e95c62c95, + 0x1e90ed09600b1ad7e5f927ba5e40d6fb87bb537c695d5ab6fef166da18fe7f4, + 0x64fb597e3bb0a3fdb8ed25eefa943f6ca21150b4e029836fd31d63cb81223ce, + 0x710644314ff7d6091eab77327421b8b18fbd64ab6f6756b61ba96d79854d6f2, + 0x17491b622e2f47caf07a2abf0b623896e973647d02be011f099b84af45dfd1dd, + 0x2c7aa4382c1cc1897988dd51243facdbb7d37e8cab2e27a26dd7fb0795d77712, + 0x14695d28c7fa12ea6044e898a6d8a6592a5f111a293624a45dc24944f77bb711, + 0x1602e77d6ee3a46b60aca6ba65c81457c4d36c8ee14b3559966cbea0ae32cef9, + 0x1ab02e5bfaf9d4ceac75f53983bae994d12d0c44a280d7e2df3283ee1f429ad5, + 0xd2b3a148b13d8a541e3cb82d624cb30209b4f58fef5121bb74e8eecacabd939, + 0x2e682ed8f03c5e95d84007e89a92043c968111cffe9d18665258df0d3a6a9b8e, + 0x1428a6b9c8cccc597a9eada39c3cfff0154fd9f5ce4878d9963b89c7a878cef5, + 0x125dae4075bd6f83314ff7172c70f192173a2d4eaf09d887b942d45b7cf7ada5, + 0x273aafea62ef6ad185bbfbe54a753e59f639ab2dff85b1f4c0a28e2136d4bec6, + 0x179314705df4e0b530f1d37f9d02c3a88b66e2272edca161365615999b1cf404, + 0xdc05aa8617d57fdbe30d76d7407add6a2e95fb73e9f942e4c242e2ed1016318, + 0x18469f35a1ad56b258b1e60243c962ee6dc99faf274f02feb42a8a51182652c1, + 0x2f79b79663182739a2fe0c607077163df7c0e9193143234337b9007cf472ff7a, + 0x1bb4d4ae946d5ec7cfb22cea828d263b7e574ea777aa891cb0ba07cb412c2413, + 0x27270b27dc8fb9ceb1c5aa5a49f97a795c1dc652f9012ea2110ac6877df6c20c, + 0x14da35468739dc3ff0110c91ef540be904c73e5d71e5b0b5eda5ec6dcb2f6eaf, + 0x2e90d9ee3e7c2164851b64afbcde004b6c0b82ae7ccdf6f78849fb981a35a2ee, + 0x2b15612eb94247469bd9475ae4bde9780511cacabd566c1e74ba1761d60b6158, + 0x121c521576ba4ae4a05ed2565651b2893d5f704e5c6f0a642c60e50df22c8ef9, + 0x23863fd0801582ee9b9a4c83f3b6eaef83c59068c0b1d4b9e93ec5ec1a0c2938, + 0x13a597a19307e90fb04778f82f2e6780a9e2c4e03cb0515e2cb960c51838693d, + 0xfe4f11040f7ec803ba86cc6dcc6ba00ed7569a00cb4aaf5685d014beeca35a8, + 0xc30eddac033e3f113894327db9763aafd747b32d1344b65ff7108177125de2f, + 0x16449ebb71737c6513326b4636914fdc9f7864c7f10025a09734880d423cd1c2, + 0x267f1aa1162b7284cec8df83403241884bf4a29547e2d0c470f6abc19fbc4e75, + 0xffa65c12b20f5ac05ab035a3b9cf0983bcb4cd0075d9a9e5be77ff9b4f17bfc, + 0xfe550d9e4e3eadc68883a977b6869a5887db153f6bdba49233f60bef77bf44a, + 0x255002f14c45aecf8cbdccc25c25cf16c9c771c653dd213a2ce22e190d7df111, + 0x160c6500540f89b145de5aa9fe944604eaacfcbf1c17550ec91da6078082ce1a, + 0x1383faf37b866d99769fc32b68e45a753f803ea36e351bec34222729356c6393, + 0x240b1af70af648da4ae6886dcad5c673e5b36aecfb7f2e58bd12564c5a77697c, + 0xdf9f10587e99fc6280b6a84f0ab1dcb4eaadc8958518ea2bbd5e648cca49e1a, + 0x26e4261f23f0856aef429a307bafdf1b57335d7a0f38ab992a77a5cca9b50ad0, + 0x145b8482c15986fbc1a4085dab239bf2d5b524632baed39273551273ce1765a5, + 0x25101aa4715ababd467f91767d0cd0e8037741883381e392c8521b08c6cf62dd, + 0x2896258f1d13f8b556b92d0b5fe0684f67a8665bd97747eb0364ed9b41cb2b9d, + 0xbfc25af60e375f1a7e09ec5c0411ee14b52346ede9837df5703420189fd877f, + 0x29a042bd25d6f3aa5df99619a794de17432fbd1c75fa33a1010c1af30cbcd828, + 0x1cd0de72b658cfa8975dce977ccc6b6cd06e4f8f49e620e72d7ea84ff2373c01, + 0x2197c4469eecca78bd4629b5d53bde29a8d3222bbfffc5948052e039f18e3461, + 0x59c6f40b2b1bb82739356c24e78eeb900d1d1057fa9d48289157af603d05dd0, + 0x18ce307b89e3700870c70a6e9460f1aed5169f729d2e75f7e6c7e6d0298fc334, + 0x27c70ab7d57ecf0b8348df89c42e3817450b3f018519673f9f508e5e1ddcae89, + 0x1aad5aabf3751e7d413b8138c2769035e8591227395d0d1ce29d1c5b3b42a54f, + 0x165634b54770542a49ff684eca304c99d9d06315412252bb82a2ce5efe24fde9, + 0xbe7826f267e77ace74a4eb0e10e5268f07f52cefc1d7b74e7a5b82a08c85266, + 0x263fdbeaa2840c05de52dd10fb42817361a189d2abd54ce145fec18cb11b7ed4, + 0x2c1ddd2e896c9dab5533d8400df17eb353a0191b9b97282df18774113657b473, + 0x894b90c18b05d7ea347b8dbe1471fe0020b9d0b1eb45a07b0f70d4b3bd90228, + 0x3056b80856c9e6ca2d92a5bb3ba46c03de22785d58565aba508d2d898068d741, + 0x1b3395901b0049172ec09a314e4a4183563727d32a87767a094d70535336be93, + 0x143e65a2a879b7a35660da4fe2141be33c17ae0e6f1324fb3cd9a1d061a15757, + 0x2f3f3a50c82372cac6815322698f09826210a571a9cd64c68dfec4711a5fe60b, + 0xbcc338d5a9ad15519aa00e89fe52cc24491416e1ab69635a67d3246e58b12ac, + 0x2a462fa9c4a682e118cced65a4aec9212496ddfb5de743729cb281ec3a76a8fc, + 0x7391449ce7efe315f816f0c1c3ad33b520007106ef8d11c2a2463de270ab282, + 0x8cc2bc080753c7730c57f179e38cbf95b95db1fdcabfae0a8d239342fc68c8b, + 0x1ce160503379a007e38ab3cce61d6fa0d78ff6b19526e1546023cb6dde3551a5, + 0x2fe5f53e6a16d7430ec9a765d640bd5de6587509be8bd773be71073e4e652975, + 0x2b9d6359e3de7b25159b8d2fd42c96244ad92bcb54f26ad8a6a10b2713de4d73, + 0x2f730a0fbf24810d49065521296809b50c5e96a6bdc4e3fe44d9d4517a259728 + ], + [ + [ + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0x1f930557a284998225f5f4e4dfbcf5ac211f1b12d91b0562ed3d63285d7a714a, + 0x18e8222f6907da5745eeb9cd4a9e62f28b8b710aa85fe729f9ea73a3ef0099d, + 0x180e924d757d0be4066feb146ed56212e38acf9df4957432653f370f905b8b07, + 0x2f7d0715d1391190e7b14a1242b6799eac3142e21f08ca02c21755eae77a55bc, + 0x2283ed8d5e6f9470b3f4f49a771061e4a4fc7dac683defcc0348a8862c6ce71, + 0x21f60efb132b62909990b9f994f381a9c02abc3ccb54c5c8e8c9c5664c6913d6, + 0x1cde82acee60b84424e9bcee49a5464ee05d1cf0b70469208a675635ac715495, + 0x118a24510a2153f818f0a996c87de913587805f16cdb1939d9406941f958e8e1, + 0x164567b0de16b7a5550fca229bac7cb0779524325e4ca5e78a86078881660264, + 0x188ff303194112a7034527cc9dd0b4deb0960c9c106ce115178dd7087e4e8c02, + 0x83d832adf9bb4a25f686abeda9f16ebf53263dcf9ef4311781d09920d094ead + ], + [ + 0xfd547840f3a30a533a994d1fdb3f60ae5073f4484f34be951ee16a276fdeb9a, + 0x4c4061820cda9bf472df3f64d6afa004f1e8623d0a4f6142cca1f19a4c275fb, + 0x107757eb0c0799f781308d83d2e057ef8106f6b656b45e7636181e113a2cdf32, + 0x2acd39e3892ac429ed812863efa05eda746b55bb974694a4e77b9a19abb55001, + 0x29788bb6cd947ea9efaeefd0eeb7fd563fcc2e40bd623ea2b2442b55d98dc5a6, + 0x6ab8672c936070a10757adb45031a5e2922f0fb8b5fab3a4f5e3872fb582ed3, + 0x1db98a562fcd1a5e4496e61264aad5ea3b455f46eabd8957ba671e9c31e5092b, + 0x1c4dde07d0f94d1aaa832ac2f5712d438b4e1804b5209ce55942d7afb24c6401, + 0x2cfc82712ed9d71ff4fdf63ee4ad116fac195794f8d910286c152efd9f959bee, + 0x18b49b773f5799888e9abe3f6883d7063333835b6cdd333580b2b4bf48f3b27e, + 0xb300de5b99c27d332091f8fb0d97cf04a86a51d4d2037788e0d4f38e8f4eab2, + 0x541af6b96524662084d1208d71b6b2a8d66d91179745b213679c2a2bbc94968 + ], + [ + 0x5019671bda026670c7ffa9081795105963f56ce327fcf78451fba2bdb3ac1c6, + 0xdbc22c3e54c924a882c22000951239cc263755dfcb38b27ef4f880e202cb5fa, + 0x966a21b9615af2b7563dfe41b8b9fc06039512dc9c8e1196891eb77f856b608, + 0x17b18621dbd61df085da4cf8a03395e3700269c7df4d98ce4851f90abcbb3631, + 0x12cc274647fc572bb79035bfc3332a4e566a28011f69dd0874f01c56bc44c3e2, + 0x2c7d538b9e6d2b2e06e72f8aaab26dbddead1fef6a740a11e9953f8e8e9ee057, + 0x2f30800c0ee461010569d36b60685a38b02912a020bc4708598854f65822f15c, + 0x116c45e4d88ceae4565c0e94da844eaf2775d5f5b435d94d2d3d38b583fa7841, + 0x2ffccbc40031ebafecfc3a97284bd0f6dc4d45eceb8b8998f1a667bee369ed62, + 0x2007424b129ade2194c73e6e2c9d79360d1360c4fbb8c5f31330f938558b3ace, + 0x2c53d6676d4d4c87d9eaf5d4da08d1e98d103a3388d59a7c0c3de51e2623aa3a, + 0x2cf2c992c02a36334ff5dc851646ee7da04b44eb544ee3c0fadb8dc5eef2a585 + ], + [ + 0x2952c18c15558f29b2ae77fc39e51a395f173a9097db404db765ab02906b27dc, + 0x2fbb1c59e9e8999d91c40f4d44233122ab35ffc975edfb43c53ed07dbf0d9c76, + 0x82046081498eee63c287c6fa3efcdefeba1b5272a77bba9cfddb56afa53c82d, + 0x2a429c2d06dcf34d34730c3af8bc19b04abd652468de5a85b5d5cbfd9c23e6e, + 0x2ef584c3aaeedbbe2b4b103a61e94ed40a97294156ad7ddf0de43b845249f534, + 0x28e4620d210536bcaa42ee46b1cdcb21bf215933bae4eec639efbd51f4bb6557, + 0x1e32b1e2e6b59273a113d609663af6b30c95b36884fe5faf371de3d564213c3b, + 0x18820364804d22119347b728135b409956f7933defa1059d634b977d9d3abcde, + 0x9b6c00a37df2770cec0f1bf62a6aac3bd380c6ce9f4f96e0f0879237ffa510b, + 0x445e26e26f91707da2df5c188baf80ea2f48c703614980fa798971cd8ec60f5, + 0x19f5101715162976766e2b57a58674bc58e1ba2be18a59b07a07e4a93e038075, + 0x6c5df8fd61eca2fb4923f0a46dd4e416a3a3b48c10ded13133ffeab6fd153e3 + ], + [ + 0x2353a60af6bd61e5eac2c9a4263d451fad07380654d4792378daf752e5cc33fa, + 0xb8f40d2c4d28c472085203a0e460af73bbecec3b2b3a63f27028f2ca8a71251, + 0x2c7ecbf14b2d6049a6439d0f29f10e26ec975acc3e3eddb77c831a509af59196, + 0x197dfb64189c09aaef94a1f542d8c34aea27fffba704202d5286d62bd0eed372, + 0x5f9a6a8d64cca12725dd15110f74aecf99dd30e57a7d99829cd8757b75b772f, + 0xfe0def70bfba40679aef8d5a239b3a1b5a52fe8fd7edb754aee2b182d64b66, + 0x1b1523463a45a2982889048681a422c02ea373f8b8c1bf16c74a375d5060c662, + 0xc849d07b1d9e6ecbac517fc19237ff73424a0678f94699b23f76952afa4514c, + 0x2c4036616c156006337771c1e355fc0f2f238e64cbd69d068aabb4b58116886f, + 0x176804ec1cf85d35298351245d32236546838d9b98cf4242d601c7e8e501b49b, + 0x2f5855a876a37f7bbbd6104accfcae507e9ddcd2a7219b487a76b17c525b50ca, + 0x1a233c7cebfb0c6eb72dfd07aa2b537ccf291e84093aae36cc68002ffb83639b + ], + [ + 0xed6a3bd48174e370b4f264b37488b03a5e3f4c0f61cf32d3157ad3e3b86f6bd, + 0x28c01a9f01601bb46417ed466be6008595052f782e46857d81229e64e6bda02, + 0x144022e7e077ff22a2ce3dfe9923107d5aef046d0a1f2cb5f36191ab04eae4ed, + 0xfd3bdb79cad913432b7d3828e072dadc26cf4903d56b8976200723846c6577e, + 0x2979d1aeafdf97988560d4ebbacfa6e2b7f3d026946abbb9d5397645e6e81825, + 0x22ae023520979741e5c58fb04fd25d12dc8f5fcb6ad15223a5da7e0f91c7b4f5, + 0x5246ee7854b2e20e8612da021b30798e5f0d02a5bfd5e79d3f9ac6c79fa609b, + 0x2b60a4d43d12cf31076e0690e931716c47a86e7728c34b2d3cb0cbcf95bbb74f, + 0x41b909a658d136993b3f509a9e9d50138baca48f6b66399ac5c649e68dd3aa4, + 0x25b6e65e90ffbf910d19fe3ae23d037f8f64da9fe3df483fc4f4977ca36a7b1c, + 0x2c0de448a88dfeaacc9bcf2850b6ff4f701e1a538d69098bc94087cc35930966, + 0x5f6d62f54518f039e79aa726bf15a5983583eca4062405400acca58ca9d2235 + ], + [ + 0x21103a7aa20c8d15501be8c23504c6a912c6100c5d88085cc2e42a52302f4483, + 0x23ce8e402939cccf36176a5bd83183a0d54a24ee6cabe4fc7f814dfbf26f85ea, + 0x170403d414148f4681b8213550951e238edc009f46b00693ce3d9c5800fadd0a, + 0x29b9ffe05db2c52ddd1bf0e5c532eefe70497c7df4b97db2f0624836576a6b29, + 0x153891052fca1290fbf83240d334fd4ce05de78adfaa2c9686488e0c47ce1fc0, + 0x105c0b246660c4bd8a6f1b36fc3cff86a2c432c0dc9321cb50abb98a10cd1bae, + 0x6cdf8055439ac8424c435e7e9bea3f0ae93eab171ac383ed2cedb460fcb04c4, + 0x3161d7b94e1b0411fc01dcfbd748a6df3156ff04536b3dd3101f7b2ebc3811b, + 0x25c075b41ea2d827a4955b6469db9d41760faf885f2c6e9c09407ebb1c4dc274, + 0x2fa2af7970e131f7efe3a7c788890ab860f76751e55b4ff634dd46cc4de660d8, + 0xce587066eae0c345c3368c53dff2170cdb081bee52b243a1e6de6d4f82451d7, + 0x2b09de93c6e3148cf7ff5731c8e144debb66ca896ecbe4089d2d22cbdb09777e + ], + [ + 0x2fb232573e85d68c536d100c3a6ea9172884451e677b0d1cd0fb4dc4c27536b7, + 0xdb82abbcd3a1b56f7fc8d116cb54c54fe26243702bd3d57e71f7ce0d470a40f, + 0x2997d92a5e9bc66c84f635e8cbf080eb720ecd4ca3e42c3ab8d088611880861a, + 0xa2a006e3b086bf502c5b1540eaaec14b9c15bf88471cb6d479fb4563f016497, + 0x1b8c7eb04d351aff4e76af7f9fa1114fe45aaedafdeb42c1c23503b122639c7b, + 0x2a5aba3b45e79eb2606b2a5b47eb907584aecfbfc0b4cd50cda1ce4854338597, + 0x2f9a5cdb79645e3454c617d77a774feaf24ef603454c02076fc4c9d7548cc455, + 0x6438e8b0220464039a7b8022f06beaee502c5de269db82f91d88fe1b72834fa, + 0x115a91867233cc75d1c906a42930e93cb9c16afced390cc14435e5cfefb4e96e, + 0xc8fd4ece5c205190cf6c842d1683444079bf49835d5c8b8dfbb11af956ccaf3, + 0x2cea98cc64abd926df963da57f2ef4c434141cb53ac6311b2566edb957982713, + 0x239ecd92517825174f796345db296562223760fb1b81c091b74a6a4a82968a4 + ], + [ + 0x302a085be040ff9a709ad0c73238b0d1e11e1d17409abaa34fc45de29b541535, + 0x2e703ea9af99161acf9949da7afb18d462d85b671656d61c2cdee3a72390213f, + 0x21427b3a9a2cdf1e2e6c628906b21e24271d72c18b0261be68cca44865dece11, + 0x237a9e020908cd0edbd9eae8772350e0e731e3228b892fc5f64fdfa9b9daa670, + 0x2d8125dbef602bd970d11fad7cfe06c3c64f5687b09b960ab92b14f69efbea57, + 0x23a3b23d5edf5cb66160fd2523b3a383142291c0e0ee666682e946b1d57937d6, + 0x1b1625d757786a19a93b37adf7f22ca8a502aa4462ca78f7da2d7c22b37d7f9, + 0x14898babc8810cbc626688531511a8473ed89a22569d47ba586c284e45bd0ae0, + 0x2f8fb37178b525758bf6aa527f25773e1ebcf8e1425379500c8245c741ba3fc4, + 0xe992f44463e2dfd267e6a4a1c3303ea7a1186252efd6c9fae9e5f0c1f6d8266, + 0x2c7ae475d90c475f73c0d29be8889d0c4b8536fee6c0389984bf9e4dbb1aae6d, + 0x2945cb85e34532e3a22fc576703797893ce290d0156430a8dce61c9df89a8bd5 + ], + [ + 0x683e640e6154ef73c3cd6b1d0f0fd86ebf7e292e63fa84cf0a883c2f1faa8ba, + 0x16512c150c1d2fb7235efd2d4f0fad5fdd78f8d0cde53a66bc90206c82c4b597, + 0x24bba58086a78541a8ebfd535c107c36946d78ba6cb26d227e615131f71d337d, + 0x6d349d6182ec30d68c9be010587c707f7e1e175c0d324e6added6337a72c2b, + 0x10924807f6fdc4e9e586792e3ace3001f16bc02e84ada5df51d7bd37243ee1ee, + 0x26635f4df7172107dad6b7c3068d2d438bfbf486471039f9e65a9c8462a2c9c2, + 0x28bf5488a525f5514400dce722430287fe8e4c810154056eb0f4d6fe61091cf5, + 0x90dfcc0327a541672cfc26c7e1370583c5f9214177093010fd3fbf279aafd4, + 0x29a14dc4bac0a4c52bf30aaf6b9b8e05453d0d797246b64732d50f176a7ca257, + 0x2609ff97ef574fd68d16a3de0872c3b59a5b928258dd1469826a191dcbf5bd0, + 0x23238fda1417302dd03ce54607749610292945bddbd587241714fd3964af5f10, + 0xd3be6a5b12bcf1bc705c20c30f320b8881c6c2ec00e857685c0599262a3cf0 + ], + [ + 0x1f09f3fb07f7f6476fac98946b7375095e014b28f23a07ac9fc7077144ac3979, + 0x298aa5d5a44565b75ef68df902d791d01d98a75e822ef553b1761c58d6fdf32, + 0x1fd5a6eba52e9ea1db389a1fc8dd3d0283d737c18eb06e090b6fd2dc88e0a14, + 0xaabba39d220f30604d0c44dd47c3c70de3b79f5baa70a3a7a0ca02ae1b080c5, + 0x230918919b6826faa7124c5bd15d10c036d565e100b696a3be7afaedb2abba6b, + 0x2bb28ef42f5fadab6a6ffd5655b36580deb063ae3081d587bb1598878590f1cc, + 0x21891bee31fb7bd89f0e4422b3c8f5b393299af0d9825db9be73e7b20097923c, + 0x38e0c2e29c79ccf46b5ea1bc589276aec95b74e8bb82e4385c0585637c885f8, + 0x2c89dc7562b91d8f2f7daa209b7560520b6bc62ec631db41cc5edac1fb142be4, + 0x15dc57879cb41d6015da9881f948b40d20f0e03fad87746d8575af009c96033d, + 0x1c674ff2ead27ce002f4befc7ad5f0f5123e59793c0fe21075e819ce56ce1e83, + 0x11e7bc4a39d2730196b6c334f99750de5bb5e4fbca5d6a19eb7fe14abe845dbd + ], + [ + 0x598c38d2e2c78dfe4907c74e82325cb191d52608955b583e5826ebebd1857b5, + 0x203fd2078ab2a8f88b7606543145ee34daeab2aefca31bc04a476065697cabf8, + 0x1276442d9383c52d50fc9b5ac34442a4ec8e9cd7aee6d6ceacc1a6f521aae4a4, + 0x16ee980a2c67de24fa1a34082f11c71b7c45966a6e8bc6aa1a1dbc7ef6a9bab2, + 0x1db922b8c249ff7bf96121eae9d9555ef7770f3dd7b056191ae9ab38a5ccf6ed, + 0x96dd43a832ab68e35e57c98d7b01f2a2e5936807704593ac72c74001383f7e2, + 0x2282e86ade85855d4ea0657c4add20625c6daa90bc93943b59a92dbb77b63681, + 0x28331d0d31ca8675ad4767c490261bbfe5b84adb4ca2c5599a87f331908130f4, + 0x14972bfc85de037b07e55332e6bc5b4f08f39ed4eb8a9721dffc4a586dd9a1df, + 0x6d039b64e82d7975dd21a37b5ee79308f20e82e23489382ec2d176190587896, + 0x2627be68d9cd0ccda3828d51621ba409f9acf09f1a9cc503a29ec306f8606ae7, + 0xc7c9db952865fb9470f8aa1402536cb3b82276d9e288082ac7f83b10bcb6d17 + ] + ], + [ +[ +0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, +0xc894a150b70154ed3c77c170df947769ac6fd8f4170d341613e7adaefc605c1, +0xf784c25d3497fb7f058d93af7ae1a182bea00ebc2806c19377ea19a77db346a, +0x1a4f48dbda22089500b402545867e341b6b6f14bcedd66ab59a1f1482e4f2d8c, +0xf61b0bc7dc5911ba7d353e201a1f480cff116ab06d9e735e01889b688078347, +0x15f5f8ed095948c58f2cb630b9b892b1289429c3c6169f26d4501cb4b24e7d72, +0x2644c801ffbcdb796abf1036e3a240514c45708f0bb0616dc9f5475ab7ddf80c, +0x15580d2d80baf18dd310bbce40e0447c78518aeabd02fc3d66bd0f573c1b7b4b, +0x2103a7704b61ecef423c74fc864f57077ae9e68fedf93c4c24b3191c05552e8e, +0x254310df353b2d1c72076f34db3ad823aa35b7fcea7124714bd5243d90c788af, +0x23c2a54a64588d3672e1e11e0449fca37349013eb30472982df8935a727808d7, +0xe25546d7af425b5954185a669c63c9fa25d3d269e036e2770451d2cbaeb887c +], +[ +0xfd547840f3a30a533a994d1fdb3f60ae5073f4484f34be951ee16a276fdeb9a, +0x39f5e3ba736458d66a7276a3f7fc143f4d2e10cce779a0288fa042477fa8111, +0x2834c6a4b3a7068b2959204bd9df5f9eb21582db300ac6cc9bc06188814e185, +0x365a1836d0c970acea6a65b34b4018ffbfd2334bfc29ea050300fbca592da7b, +0x7b2fe7cb2612a4b8ce45aadb192514490ad985b31686b75cb895938a99c35e9, +0x4c72c3e92bcf3c9450146921952051dd7b932e045c56d2b8d1225c557a02fa4, +0x18d459655484dea4af5de8922eb66fae69bf0b742ae678e6ac5ef937fd23f145, +0x28d575bf09788e6c9f404c4f2a4794c51393c9fd263cebc2aab4f575a88c1ddf, +0x15a78c5f1d6e0176ed4e931e25aa42576e7d172bc263bb5b22fbe2a1dd096b76, +0x253af96dc191b1ddcc7da399cf751f0531e2db5cfbacce3efccf23e9aee0635d, +0xbd6477a4e98ed1b6a052a7fe6a3d111fc2478b3817bd7c2dad8b1a813dd9445, +0x1c371f42917639fd59992e6dedb5a144b079a25f242578b21baa3fd6fe98b51a +], +[ +0x5019671bda026670c7ffa9081795105963f56ce327fcf78451fba2bdb3ac1c6, +0x1c9807d9b8968d8f620640d590f151e0914406af2136f902521b8f4da19cdf64, +0x10cbecac3303667992c537c54deaec58a34528a2fe041591a98e64a8d6da5588, +0x1bc32304ad49812a051886f8904e1af0a76149223fe72e96523937f339a5d9a, +0x15dc91d6fb987bbdca99c78dd90a57b386e9b9ff7e4a4faf70d5ae18f431edce, +0x22b26a76db2dafefccea7be76f0e139a0c568e92a447ad288257ef310794df28, +0x1c76650a0527fe929be54a7e8a47efc654b515547f9cdcd58c146a0bd11872f6, +0x23d3b9deecba2482b107832457fbbe5ff670a61069cdc34a6470d2293471231d, +0x2b9a6b170ff9ce22246aa0b5091a7f33ac5a1b39904b61f0a7360c435feaa593, +0x316258271c5c2be65d5e41b0bf6f9917c8c60944d1be7f60891236cde4c2676, +0x1c67cb4dc98d5f02eb96d20f1134177396cea0f4fe4c04f856b0e2dad8e1b56, +0x25a8f4490a5df4e1eb13e2e146e0deb4de3d633d11bc4a540c5a6a21934b94c9 +], +[ +0x2952c18c15558f29b2ae77fc39e51a395f173a9097db404db765ab02906b27dc, +0x1e7fcf514768abb1800ff4f4884ff5bb6af1ee7581b96e2984c2b2c4033379cd, +0x21828d603ee0c7651c0a3bf6b18217e1fe33f283bfeaa1fa9ef9eea3b2c32fba, +0xde712fca9d7df5e0f67d3eb731a53dfc7d1a7cbdcc34411f6138d6de60fa369, +0xc58a3374648de30ed82a9ee0f4294d493710fe813edfa46b09aaf44b3ce6d86, +0x14be55982212ae54cb8f0ce42a162a7ecb440a4c0c4d73189528e4b12d34e5c8, +0x9da7079e3ff632329ed76acc28bcd293d69f9298fa25b9d5231f9611ece2c22, +0x2d865f77a39255aea1b29c483eb4a3acbe7fdd909cf17d91a0100143979a18bc, +0x2a39a308231582d0a1d003b5244fbb85588de1df3ac866dbc2fee6d1d8248c0f, +0x474c582c59ef66cb29b984f6e4bd97bfeb5a41c6485aca67dc0555ed1eea61a, +0x65cc505a691aefd234e572640f6c731993aadfdb529a9aba4bf6377ae28b69, +0x2aaef152c413b4ef991bc228242822e2a6377aaeadc7ac22e502def3d839f2d0 +], +[ +0x2353a60af6bd61e5eac2c9a4263d451fad07380654d4792378daf752e5cc33fa, +0x28d0997942c3b3b0a4ae3b17ba382c8fa4e1809be0ec701d01501f142aa401f3, +0xecf00f71b1814ced4f6525c4765846440aa3d39e7ba0e4e4610b70b5a38209b, +0x1258d5a4d495bd4be6c704992ddc3e89f7ae5c6cbd7430014491fd234be89fc6, +0x30513cdc3149663999036b87af10c4a183f71722572b4d958cfea9e3dca618c4, +0xc658aba90de155384cd4d63e285ac2d004cd95a2e95da1540ef7f1237d851af, +0x13bf5098cc05b1035e2f22bd47ab4041d8adbeb53c40aba04a75fc5d2435df46, +0x2339c682b7084d04d3c9b6072b20b63b12003e5c52043c6336ba222397269a5a, +0x2cd36c4bd8257cf74834663fcc1e38be2c3fed64f7b568e1f0eb0c269b0e14ff, +0x37b5beeecf060cb73d6e08ebb984eb5d9075b31b128fa3e5234e969036ab5c0, +0x118fc51eea37540b35bc2ad77d91af14dacc152f86db157ff4c48db58e325225, +0x29efcd78bf5b6b7c9811b6e838f5563b349606a1959751d63d28fa4c1124b5bd +], +[ +0xed6a3bd48174e370b4f264b37488b03a5e3f4c0f61cf32d3157ad3e3b86f6bd, +0x287cd855b94877a396d39c336dacdb13452eff5917a877edce1412b7ab24ebb8, +0x4f06b7fdcc319605d038881cb47f61748f1e9f14d47dcf824abfad47a73bbca, +0x4eef0886e398163b9f0009c8204cf2d9b0a4a30fb019b3cc46cca6ab3ffe666, +0x2fb04567ad27a42a4ca2ea90a0f27660e1e10acefe62de96607aa26583695932, +0x1f1c7c6bbbdecb7ad8a2c8a91b983b075f4998fc620c36e28e2b59077ab57704, +0x78a3fd180d76eea922e4237fd65bb83ed4561b268751a20ec97d3e0d7460d27, +0x11ce8d6554294777e161cfd91ca86ac2fcf71bea4228f8aea857187d579b606d, +0x17607b33a1043bcf034c42feab79507a82488808f988fd0e13f2e2982ce55e0a, +0x2c90418c775ce44e34d9de72d06a7c2c9cb072518bda77828b1e82fd1d19525f, +0x1cfcedb53846d090e72523914eb33d6d2781bb18ff1a7c885eac1326e93f7a46, +0x2a4d8464358084800c89f6fbb98bf69d589164f9a648f48d3a42aac8c5cbf177 +], +[ +0x21103a7aa20c8d15501be8c23504c6a912c6100c5d88085cc2e42a52302f4483, +0xc783dba69038bd1673bc3bed51afbf51ecde783af95067c14de12f49e49570f, +0x1cf80bf06f3525aa85416d6cacd0e8251bf1b3a771be49253b60ca83f49b2369, +0x1b6e663aa128709d83c7e5a86284927920043926cf55678bacd8ee0322178495, +0x6146f62b14c25c15ac08d1756f2302395505138a4ee1184000a38f4c7f53905, +0x1c5eea7863fca5bdfb2f4a3dad7e2a16572998329ab695adecd136fba4f4063d, +0x197b13f8af70f642e878063aec6e21ba8978ef2322f2d64bb512ebfc7bc2c7c2, +0xdfce2c65e220994dd2deaaef6e04537b35ee47eb92cdbbd7c61cc6189ad3f5e, +0xf4b71f3763666a3dfce7517b6746ac033b2392ef742470ff7365ee5976bcfcc, +0x6fa7b6308e448573f3fdd11a2ae8e44d33c3d3cf0d9ff8601df20c55c6aafa4, +0x2390d163c2c0b5d461be5ae1f2dcf4c38c2aa514cb22b4b5e104dbb6889f8a9b, +0x21c9120f90988cffd032feb1aac143901de9cf42ea3cbe83015e9275cb67907d +], +[ +0x2fb232573e85d68c536d100c3a6ea9172884451e677b0d1cd0fb4dc4c27536b7, +0x266913da539f40df5123e01fb748b241795f1aeedaf1f7ae3cef0e5728d23aaf, +0x2f6910e50cc8a14ddd99b667c6255bf66dfb3386e62bce0d74cbb47419c31572, +0x24fe05893f5e7aabb44d705fe83fb319d29b511eba00b2705561c6bb0afd7b37, +0x1ef5275b46a65f69edccb39f50fb90cc578ce4e519d54c8e61c31e6ae0710a45, +0x137569526eda65a31fefc352a005bd0b10fff52cc5692edcbf46cc5f03538ea0, +0x8552774a893c4dc375ee4efca4dbb742277f07d8980c54581b5d4d0dc1b7688, +0x2d9b07507a9df2a587056f988c7caa44693a118daae6660e160561d276c83482, +0x2c90b4ad79e2316e7986b75730418fe5d2b1f252e77817385d78ebfa34710afd, +0x275fbe17c666f61f6cf5484db2e52083e856c718ff2b8f4d4e17f130d2989e9d, +0x17f57c813764e728dd240398690408ce71dc8adf83e53f5257ac34b643a3ec15, +0x2700ff01dce092807c3f143418c11a2f9db6bee6f478edcf7145d69af66e13ef +], +[ +0x302a085be040ff9a709ad0c73238b0d1e11e1d17409abaa34fc45de29b541535, +0xf259a3b7e18add912cdcd8674b0f8fa910fdbbfad967bd816b33c778feda3b8, +0x1e43f0a896764c42eb93be791fe26928f91c7bdd278b7c810a2f588268314b95, +0x268094abd638ee0145279900f8755e55e1adeaf2dc222f402d1f08ea4953abb2, +0x2e1bfa1a1aea7b44c84b866d9e7445e4acac75f82e0ea8ab03326214c84faa0f, +0x2e1e2e2f2065961056bb63f04c175c1682eff3bd9073fd7fd76e7df0e8f12d47, +0x3a2adbca7945b9a6367799a20c37944597333320cd815d054a5794f68460c83, +0x2ba338308820d232cdd019154fc49774b0c884c7f82b9aebce6ea211db294991, +0xcfcb2e3744279efac866e0228c1b3464a4048f4910d17042ba1a6b8cd12c8e8, +0x24cb3811355775bf9bbe6431305ffeac61c7de7c629d9a5ef84d960cccb940df, +0x257540e571a74fbe3ec524ff58f183ee0560d506a8d10973d77e54c9d9061161, +0x2652e1e037bffec0d7be1355de11170b7f916d148a7c3ee3ba8fa44817d48fea +], +[ +0x683e640e6154ef73c3cd6b1d0f0fd86ebf7e292e63fa84cf0a883c2f1faa8ba, +0x10017188ff4a2e0e9b05536c8d07e27d0f194cf0689d834af2be2b93ecf20ab, +0x2afd3c4028b2ada5d194c593bb5e4e2710cc5c32edcd5865b59d4c7ec037e251, +0xebfe1c74eb49cc73b0f6c3f32f096c2fa6288b0a04823e290cd02dfb5e5dbc1, +0x2be96b6dc6b5dc0f78ebf844a52f6c1d50562238dbe7b95c47a2ba4ebc0e1c17, +0x2eeb27f0c5a205ead76c92eed0ac8a112c171711b1d12d1e066fe3527174f6bb, +0x131560b779c80ad8cdd22a9c3ba80290c76de761b1dc6e788f7f9493f84d413f, +0x7039d5dc74b4dd2f6a0701a3179b502b212c3a4503557e6e8af0193f07a5669, +0x16b1fa736396549a38076cdd9df36cc3385540ac1d7e42c79aa0c9cefc66a65f, +0xf5008caa5bdfda3401446482b3ce891ca497cfac4a24ca2571a02a8ecd6e78b, +0x427946475c0460b0fff4ad995eb4a9c608e260007589d7195b5cfb892bae4f5, +0xad2c3c083a08091a9566bf29eb7506952d2ed27eda2fc0f51894b5d2e28aedc +], +[ +0x1f09f3fb07f7f6476fac98946b7375095e014b28f23a07ac9fc7077144ac3979, +0x2bb007eb9685bfa373e688be53f5d6dafd6f87413c9805d20c579933c6ab1124, +0x2b22adee2ededd40c3dcc8e1b15d38081edf590a9a7ec2eb630cbfc5292f238a, +0x6ac8237c50116ad33685d84005ae724cc52e0ff4ade0d47b194f7923231d67f, +0x217cef9e11c01178da427e2b9f7fcbe4c1f1525d76d3ba7c8850191545e58295, +0x46e7d8895837a4a02894e5d6f3ea8d51adb0ad4897434ab0d0e8079253f2fcc, +0x1f478986f1820203e99247b23f9ae06526a085c84cd31655f82c17037b1de5ff, +0x3a1fee4f5ef14a50af278a0b62247a6669570858ac9b2074df28b0a4e9303ab, +0x188a23c2b448e79af34b9b4866c954e698a6163ab9326f25f2dd746cd1347d35, +0x1cb09fac676323645d322c13c676eb4645446638d83fadcb37c4f1788acc1252, +0x263d998161f060aee0e6bfb95f1974efe466f739715e92c278128c7f18ad5e7f, +0x2488b89af9d856ebc2f9053be37e13f9e1e546146198b764e0e0ed784115d94a +], +[ +0x598c38d2e2c78dfe4907c74e82325cb191d52608955b583e5826ebebd1857b5, +0x27fe7a3879727f44da5d035c1ee30fd12b4a6d37a488981b4903d9340b67b7dc, +0x11033939341c415cf31321211e351744c0831403f53a65832694b35adfea49cb, +0xf47bcf189e8e4ba1b486290d0c9ee89ead181850d2ff29b97bca91518d8c2f3, +0x53090370cc10eadfa09d586810cd0da5ed707080999f1211f0094108e1b3d57, +0x2e2c801404eebd30297f3ec0ddf5e0dd9c1e0aab055268e647c3fd4712dfc84, +0x203f12fe19f06faeaa77bc8baf4983c763081a7af43dc5e7bb83f789eaeee5b9, +0x18837bc92a8af3d37214cb2724b4c8b904e641660e5a48f79ae4a49a7bc37ff9, +0x9f0706eab57f151b23e4b968ba0b6bbd4fc82700acd601333382757a15de2ed, +0x1e7d6dc15eb4669f914899901e7deaa91d102a4e4d569b40b9a11d1241167ef1, +0xbc8d092c5d38d087f9f34faaecec3a55ee916469ff5e23e619b73468ee8eb57, +0x2bfb96f78ef7fe047373d118c0aaa0140ff43e5dcabda257cde23856a654b6fb +] +], + [ + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0x2e57ee9089adcc51f2ec7d5fc42821e67fdf0a2f3d1add870823002a1e9ff4a9, + 0x2346c226491dde21f38b9eb1be8c16084774e9dd941895eb362c2bf763050cbe, + 0x2c294fa2466a0a9f1f89b1af5bab1ed3b86a0ea730770854684c754750efdcc9, + 0x2519e073c3abea02f7784cd8c841ddcc10d65507cb4e85e8df3bf85a8e41a70a, + 0x21ea0bdd27e0b8b71b91ab46798b907ee094cfaca4c68ad81f9c0c107e7a83a4, + 0xda23ea74cc325d3922665cba17876a643c4f6ed46f9813ad0f403955757dd80, + 0x1207beb18149148fb6f50f1090b05de32ec5d438fb30604f4c63c237a8cc1d55, + 0x1c357f783a3df3f09e57ffb971a7dfc50c1145da9f3f67f323b4742ef3ad7f82, + 0x234747b2d98835ee8b90f19b5ea03c13baeb410f21211383ddb20248608c5862, + 0xb38e11da34730bc74b7f3add58779f2e0bc55734962a059306e4b950276725d, + 0x14732e1bcc452fb9fa40e72910575640b674bb5f90353a52356a6133f26cbb9, + 0x197d6117415de8855e11099ed6c9c4d76433d39fc7f4cc800d5beba27dc7b40e, + 0x2b3a311741f8b94d8255d87810649ef6674c7a6c7711a83ff88f2ad9f7e23c53, + 0xaff38c1f5500a4ee4949e5eef338372179779bb29c95142b3ad18efa9e673ec, + 0xdd0c48ff292bc764e9fd84841939694a761178783ba99381df579cd3385d8dd, + 0x723a053723b6cab73e72b36722bfc52c957f8c7fe0322d77348955575e841bd, + 0x25ca5081fcbc5b5d8b808627af3c9494e0ef74245f9aa45419d3c400dde893f7, + 0x2df552ff14232529c8216996f16bfab8d5555923d2e4a53706da66f4bb013969, + 0x876f56eb6844dda9bf30ab548c8f0b3c4127ebe7fc31e1cb27e3ce62bb940b0, + 0xa8f10d1b35ca9268bf4403635f76f1b9ac2e39ef1b5c9e6d8174f4bcf095df1, + 0x1212b888592b16b273c55c09e887270a15efdef111fb3f0bbab6f34c4cc24d81, + 0x5f5771bd30e0b5160466f322ecc23f28e563a44a80a3df85eb30b2a6da5681f, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0x26bf7fced0bbe938cd67479fa2f03e67cb8a775892e972ff4ad493655237bd8d, + 0x10a49b9136eea6f2c3fc79d946f8b8fd64854ddc3a964c57462ce17262ad7d93, + 0x5bc772beda5709a6fd33b3625682927678d5d7db7296f5703ccd7e40e0d8dc3, + 0x15d73afa88e6fb1b74cdf3ea97c694ce695fd39695ff3b7266371d1870f610c4, + 0x20656f69e483c5b05a2c5e26aeeb9f30d17b01054be5d002b4c312a32df35daf, + 0x2629526c99e13dd1862ab8d125a34cc68db0f3bc297d974044668daec9e567de, + 0x1e204bb473dc75bef5f17f5f828e521f657d8c58db1f4e096f5046589275609, + 0x2a4fc3c7b54eebcd023dd0907ea97d73cefc2955a5a8347bfb5c41cdb10fb1cd, + 0x374b0643d980373a12d798e8ce0f9e016a3b3d9c71e56e0b979534aabc3410a, + 0x2d54f4a821cd3a86fbeaa914483d0fa23a7cc04a6be217b4144b668ae70770c9, + 0x29fcf234a9344cc6a8541f6da7b2ec3b0cdf256408c362bd72048d808e72893f, + 0x4254caca99daf3eb34030e734085eb2171f7346ca2e9f43ae8f61a4ee43c358, + 0x2b4c8db3065c297d08b7f1cccb32a84a4bbe657c16ab0d9dee4bfe59465030ff, + 0x1248ae908fd75fefc42b13be685cade6bc106684ae4a4513ad415029374ae02d, + 0x1cbd111af62201c242a38f3a1bd792501cfdc5035c71961c29199a4a7167edbf, + 0x2eeba2b31864903d017a3036f11985a8361caf73d4fdb215c5552d9e477a7a52, + 0xd32eaed9cd5aba29a1f8cf029d022f77f5eb2011fbd7b8bcf442df70261c724, + 0x20971ff3e27ffa9dc609a839e591d688d07dc636d2cc79ce570c2e5b79f63b6b, + 0x2a8bdd4b9b1ef96bae00899ca737d2e1dca4917679af1c64f62677d2d626e314, + 0x26cfb0174d91280bd05b4e9553c044886e8b8c8b30c36f4316eff726808ec638, + 0x29f510be57ad8e8a7358c0697b8f2d761e7e6237c8aa2ee452d645c4fb5f3548, + 0x1c1cbfacde1ca981ae5f91b44a95f4252aacf086637ee431dc81a89d4db6b41a, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0x2b7856136f545d69ebac3c459451f28a2a53aaa144ba679023b2161887ef1250, + 0x250c047260e50160cd6586bcf0ea5180821fc71c3788567481a78e7c8b9514b1, + 0xfbf82f8a52984b9d4153dd6e78c05163c8d4720915c19767cbfccd0c3973488, + 0x6bbc95542ed85d6012d232b16d3d01deca662a0f61bcc164b6554b32e61f31b, + 0x28186714392c789ae58ef7134248ad33a5f12470e416718a3354f34056fb12ff, + 0x53afba658da76de92084f426da8b4c0330e7725be947aa266b8c2f9c0c55c4a, + 0x1844872b8235f851728c66e0b29d5cbf1cd0a0ad5ea4885b2c9967508965c9b1, + 0xb09ec5a6d9b68331f53ca5fed46443c6fadd52ea4d9c4640de3fc2940c0deb7, + 0x638529db7cc2182751ea21241763d10d34cbc099c578b2603cb0d0c0fcd89cf, + 0x5d066dcaccac1ac0448d43671f20833fae00c106de7fe28c9803d7715feee67, + 0x65da2f374618a50e6fa3a0164160b1e6af42a76e9b187115b330d60a548b3af, + 0x2e202380b8f6d90705a135c42066f1cfb905077d39e7a02231a740a3262c1e08, + 0x14570c40a4e7ef1c096e9d8fcc0a46cbde32dbb57916695206ab03aac2e82f37, + 0x2d87c245080329821da248b17456f9e7c106ce8a803d3d015a8bfbf952897c4f, + 0xda8c6fc810ca1891938b417de296864f3af15c28d6cb1d59e2de28ebd010fc, + 0x2018992835e00507a6f2d97c728ca059eb76a7fca5237a36e9aad99a61265cc0, + 0x2d9099c975eb32f31f10f807baea25ddbff205c624a66a4966aa59bc8aaae718, + 0x298dee77db6b29e44395264887603d287c45850a18582a8ac9bd09d292882344, + 0xfcccb87f04870bca6382244b43a0f7f92d336e3bc4d7e7ddef48160e2de989f, + 0x1297b03aae9b949e9a5186975613ff59bea3a058d34baad1b3c15178f19e7ffd, + 0x893a222f29077408802aa74dc37c833df480b350eb1ae31eb1b9f9b20b3f02, + 0x1231b1b0d91bc7687c3813b2da32e7c71fc9189641ea0dbaf1556ead8f36182, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0x2077a6155ab34ab05777651d0151e0320005731dc875986256e103209606fb1, + 0x11a4f3347aa9f08e59856002487fe97a4ac16dcb9a7962d139a3b80ca952809a, + 0x146016f8ce100f6cdc37afd22f00aa5359d531ce7179a2fc691fd12b00c12d3, + 0x25045870f9da8f4c97e11825c52cf4ce40bca1271ddec4ed01b774fdab83886c, + 0x156094487d4626cd97ecebbdcb8d41d7e70f28a6734dd3fc3382765ea111fd63, + 0x24ade6dedeeb900110df4f92bd790ebe1514d4b24bc88062d6249eec85805471, + 0x12ad265f80d855a7adcc2ab7b6bb9f49b50287cbd36e7d9e41860fc6596734ad, + 0x2f16237203d13c693faa6da2d3162b25d0d1be895c8026cafdeedacec7d7c835, + 0x1868f1766d3e2f9bb152b15a718ecbab287f6d9cd2e9bc5e66423b5bbc76e43d, + 0x128e30bad26f11c3be9a689a10d093822b5d2b920a1b78ddcd7df1a8bfca5d60, + 0x2e72c3b1f6bd3a793b27cd802532d2768deb9668ef00490a0716e95431abbc5f, + 0xa3e8c07a5a634ea815e1f57afe9494515da623e363a408e505e01471c5a2bc4, + 0x1a5c7a54a81fd93762ce79db6dc604f03bf519d683cb2702839662e69271bd6d, + 0x13222674c9603db4a5e5a36398d24d77543ac79a4a31db13b48c9a1998046035, + 0x333b7ef8d75e61e9f44ff11182db70311648a7b78addfe4f2144291ab5987a5, + 0x231ef3a554066132798e544505b11d50106c4406a937c9702c7bde44457d4f47, + 0x3016482ccd1ff28db55d6532420e95b9d3c66d1b8fdcee5b45fd94a4ad77088e, + 0x284acbcd8d3b7c6e7e7fb246fa9b39811c045820eee55e57e68d7a6cbb7f165d, + 0x17751244cbe20f816b7490b7346b8ddaeac1635588b765fc0e7cc337546999d5, + 0xe3b27a81103dd231517acad6c69e41fbf488237d0fbee8f0d652ec72bf09a21, + 0xaaeffcbd016b27891ec8c80384a7356211b9996a5cc9adebb24700a976d71b7, + 0x118f45236c875283cde478df3bd4ccdfed53d087ecf8d85d24bdfdc78b4018ca, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0x2cb4a528ebaecb5ce5044e609a9ec5f36057185a88022e8340d74cf48579595d, + 0xb4aeb2205324cf9c91474b3909faa82059ace7d53f4ece6e91971c11d212adf, + 0x2e879ff17f31aa36666dcd42303d4aad9f55bc8d55ddcd7b8c54ef46fbc8e66, + 0x1bf5f6555edef79bb094218b0980f27db57f9709b63a9c94b18552be085a62c5, + 0x20a3689b70840d755fbf88c8fbe323fa7c7c5aad0e8923a165370511585f07ec, + 0x10a50b432864883bf92a5fb77e6003514f43fe4a5a1c070a932dd8340eaee2f3, + 0x6162a58c2fc725a6cd4746c8f229a99f9616dcfc54014a2c41e97b9ec1eb29c, + 0xa12e5fbbbd66f0de0d49810e948220591fa478abfcdfa1ab0fc5fe861b2140c, + 0xb899ccdc1131b112724493af11636d6421db516a59e8fc7f6e8240bd7581bfa, + 0x12506c3ee2d15b082a2cf3111e9bca3d255a2aaa48e16eaf5130461f5d8820e0, + 0x2135481566f8d976d6c776c65949849e7dc5a3097d8a7570240223569350397a, + 0x227608e1587276aed4b92b8c602d81fc32bc957826e2c4c83d8e82a46d8ab68, + 0x1f4fc5d8d275e923bd82f8f2fac04f63bba4fc9558326ac9ee895fcf682b158d, + 0x1de5b21d942edc83d8c79bfea64f54e681143399bbcf58d4b31c8c9d671355f, + 0xc8d9ae8381b7de88ac2894407c8158fe09fec7e372a4548cc0dba4d9283aeba, + 0x28e6f24ef229a25016cfaa7e3007304951e75ca14e8eaf7b19c7e1df58033833, + 0x16c93e94d5ec1faa31dbe2a105286d839588fd1517dca2e03d6b01d381adb9a4, + 0x12c51f2640a3c05726d08197e01fabf7d5da91671d33e40e00f924027ab24ae7, + 0x1ba9324d77e86ff6234db66d6183912bfe23527e2c056744231d99982d1cdedb, + 0x6616e7b8b4f34595a4591bfac7429663b852e626d20bce6ee7805367987d67a, + 0x2b291b00aada886311dbd8e92fa67673a2e9061f87b43a3d4570515dbe9656f, + 0x24bc1c978fcf44441f251c075eee52c7b0b733edab05b4d2081a4b52ea798fa, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0x258a9d2af52b4fefcd409d763bd8e406c4355a9c488878a5a2c282adeafa297f, + 0x2fd82f70d05f4bebd46634d329f317e76cff5149a81424d1da18580f5c1eefc2, + 0xf4b503f7be48c09319c5a9b034ce2dbf3040873c284ac09f254f5ce86e88f63, + 0x276d0381d413ba30b831d3fd4a292440091a1f7f4ff919fca4bb2b2c900c1115, + 0x28e661e4cf942f9c9f95c503ad1d0a2d078ac4644c5dff369d5543aa7c48f798, + 0x2173c6794694634cce267bc21991598f3debac70920c9d8775947bcbe3f51124, + 0xa3fba241019270d5cd8bcb540899795fc593b5dea208cf016a8af970cf7cc2c, + 0x20fcd9c08eea8de9d38dd10180e9622d5e7c7493d0f8c511a4d2f9e5da45fefb, + 0xebc5296052433f86416ac17583ef06db0b6abd8d47110b6fc40bebbe02ac291, + 0x1d76be7dd20256408dad6674c8d0e51d5a5a5cb8fac79067d3796456168d002c, + 0xa94d77bf887daf01ce54f21c6891f3a9fe14faec2a1401fa3ee22a0244ed155, + 0x1174fd29cb4654d093226766b105e7ce63f0016a0bf790d847522e906c357a86, + 0xfc72bc5d051c4abd69d91c14cec4cdc87fb115049f1b08aa482f7ac7d7c4e2f, + 0x845158555b18fab6a2be184849b6569c1530d836d9ec37f9e4e14c2067420cd, + 0x28220c506fb21d1ff3ebbc47c2c8d766d427a30b53a3964ba575a21021d8b9d6, + 0xf45897a8f2b5c4214db423321f9763aa25692e0c05d46e9a45e5253aa696a20, + 0xf71e156500b67e356c98999c688c8b2a354d0537660e0852bfe74d038a4785d, + 0x1b933d41cac25dfd0de679e86cafc7d13855e4871d9b61e119b04d5199c09f0b, + 0x19287775fc90903925ac37f60e269bf68dc05675079d212bfc9faa6ff6a49821, + 0x207b6ae3483a8ce2bc1b2f428c1ee240acf3e1ca010f5820b0655c9d8eb868ae, + 0x25d71d41264bd75fd50528062bed8223a243f25d2768169b343334d708740ff9, + 0x2eac8212fc2ad788f72ebe8710f3c6c98625e52894645f3d714ac951daf2031c, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0x172fd12d4e03af148aed931034e7060af7b8e8546e9e4e7935a32fe7727ae3fc, + 0x154dd36eb45f530fd949b85233eb745aedb76297c33ab036bca6f2eecfa030, + 0xd6fee6e12761c3832a48a89989abd5c6ac7a245be31dc258b03c12cc30818c9, + 0x1be1815b17dc7aeca4440d5850f787c64f7b251ddb137da5319dad8d9025fa8a, + 0x2be2edb8867a2c4cb3fe2653db4b526e7edabc44418341fb708a6620509b8bfc, + 0x6c0fe57a444d90391ceb5a94ad1de1443bd026cef8763daace23a3b701a5cd2, + 0x1544a456bd7e736ec88816982cbaeef38530e1c8480dc59bb74ce844de7ec438, + 0x13dcec7c410c82a7cf03cdf661e4c477cda63b31d34274653980cf3f6f04fe70, + 0x28832482d1891b799b37a9f34f26a72a8ba4cff953001ad0581cd4080d039492, + 0x1453cd3bc8d13cfcfdb0ca235673e3fe47f91772a386b11b3108faaa8b04446d, + 0x2948c35a60690dda3b5dfabbc2cc392c585671d64ba338f5112d4ac46720e3fe, + 0x15bad7a6723fea31ca2cfb8b79a656a16e6020406193e22d51897bfa4f5a2d0c, + 0x2a3eecdd1a4f9ba57ab6b9d31a359352c49dc129d68d9c509a74af0d1a27a25d, + 0xd1a72d9a9f731b1988ba20f99d8b3d81572f27035d9288d8bbd3685b288f94b, + 0x2099ac63775453e12762b57075cccfc6fd9574a65f15bac95091dd9475351a60, + 0x60d681d211c02f7909fa329f6e05dbe7455ad5879ac8d3d191138b05d207b82, + 0xb751b2674878344d13b251440475af9b37154209de0760456b1dadd1bf90288, + 0x12c11a657f6024257b1d2e79e5a9b76a1efbc3c3fdfcf0392c063086ac58a01a, + 0x17c91cad834837b9a48c46400d3e25e1a9a7154c8fcbe0115452d3d23d265b, + 0x1fc3820af6ae6515fde45a315961e27549884e2b367ff88b4ed93ceb05de6154, + 0x17a167b5b9014ca6330036496095ad717f6e37a4dc776aab1b82ea7fdf751ded, + 0x46702f62b69daf94a105978608dd2c3a8daedbe7823e8f8275c8cbe16a97dc7, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0x1c44223b01de8fbda664ca95848b813295f013b8c208c88e9947d3fa8d244cf5, + 0x25c7179c48928fee7e9caced6240b851052322c5820ba2bdc329868ffdcc17d6, + 0x1958a68f02408107fa1e5de776901270181b3eecf421c6aeadc11866a64e2b55, + 0x17ad9adfd56f8195f4cd55cc87a833e9d6a12e091b59529d00ce604e99307f4a, + 0x5638e90a5883705652412ca5cf9fe315bbaa74743995b600072dd4be5f5ccf0, + 0x2467cf163474afc71287ec56cd6d8c6f53479aeb3fa0dfe5f5129db4385e5ef7, + 0x23427150e60b6fc48b7c8d5140c07d0f97f81f4397c0959fc851c88699c8f02f, + 0x16f925f73e091b1749ba5560993157d7259fff13c2010e4734eb77e7ada60aa4, + 0x2dfd7d6796e20ddac5fa12f1e533957c671fabff0c8c74bc5b8ea8ea4a4c87ec, + 0x664c8b4ddb68209c1253e424883a0fc059fd49be46a468ffed7bbb2c8978eba, + 0x1f3ce48c3ee2922ba46f2bf0ed51535e1d559d223b489bea2989116d48e7bd25, + 0x84ae17ff7f684885a4f21d24613d733fa2de7c694722611fc1e86c144618455, + 0xae2be5c975fc9c57eeb14791c5234c2f3e74c8ab151d4943fb98f4391888c11, + 0x28ae3fb3896a81bbc583a2715c9e2193209c79be2a4e9a894ea265010fdff87f, + 0x1a66346aedcb602f39974b69bde3c83fc72944ac6c2dd32a32ea5b3384b4173c, + 0x224a43476e893bd20cae3950ebb698bc5594f0f70ec5be20708dc428b2aa0b05, + 0x1d78ef43d9271f5718da099a5ad658993aa6cc4e263f0227433c1c0700be9a13, + 0x1c2ade57dbe0afc29e9c116a8b52dc653e3b67e891ddd363e1dbcd515c7f07ba, + 0xd3432e9b73c810f7b1b013cd2c9204574e75dce2c85d7279ba1ee5cfa912acd, + 0x10c5edc9f4201dc2b0366ea68593aa279438745e4e98024b5da5300bbf594f95, + 0x1424d5095a3ed3c98e8d59c21743e2ee18e6cd2fb87a4f8fb566a51d550747bd, + 0x1ec3fdc3a02833039f3ef99f01c641c62f0f90af4e2d9a961048e9b87698f117, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0xd9abef260b1cb444cc28166a74e729a2833e12445aabcf151c1cd036d1cb5de, + 0xed6cbbab2f8701da54b8b692304d8a4e8cb2e08f655c88924e27f4f15a9a52b, + 0x2c637eacb602a657668bd513a7a1007d825cefd98444e38b021b2c1d950a76f1, + 0x20fa81a9bf57087cf32bd01facb98697426792c6ebc73d02db7e5ae21b750d19, + 0x4f1d239fee709de5b0b5e5d5de370404d7df82d22b08c30e38a7550738aef85, + 0xa1de402ccd1aaafecbf31017e71429162b1c6d80579bfdc5b1eff7c48bfb810, + 0x1c14d03118d712c8ec5c8fcdc25ec9f15bfe8857749a7d43df91232dd65f37b5, + 0xc5e0c42722e6a74e7c9d75d128df4a564da3e0fb809cf7768615a2cfc0e9183, + 0x78c4b7313d470130efab6d889ce7c18832e610f66981841824e6f1d812072bb, + 0x3668b307c93ec14fd047713c1acdbb0b9248574ee5d6fa34fe883f1c22f3cba, + 0x23d9be76930ec686660aeda8b0cf9753e10c87300ebc641ba98e09dd2f52fe4e, + 0x29a3b2345ec04133c77316b42130de0131eb92263c4dde2ea07063c5c128680, + 0x2094711a12812e287d245d3c3efef7c17f18aa907378ad5060d80712b195d4c4, + 0x5c8d6aed39e2d9fa9a2eba112b4ca0aea1afac2c3a68622b50484a2c356a567, + 0x15235ad2ec7319fc572119534453ceafc36bc0bc2e4507a2a8ef1f7fa9e3e856, + 0x2a25158b0df94b0aa9db35f56bae7b9935418e9d6ae0d7004e23fcbd38de35e2, + 0x12db88ed4056400b8f336eb2d50eefb47c8cb34c31708093cd4f7dc30a13e2d6, + 0x10f2112348242ce97f64d304a108694283ae8959e5c91731b625900540bed1e9, + 0xdeb481ab3456ccc232dfcd50eb82acb8feca59538be59659fbe39426181f3c4, + 0x2bae45f1c2ff62e6048fb24ea8b3f732f6ca9620040285b5f89bc2d4db28e16c, + 0x2b93089446d7130073970ca2059fb0c06102fc91a6288339b687470613fdbf77, + 0xf0115aff5d6fc582b77c744e7a3310f569a0e786e12b526a741ad7e958e1052, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0x116ba64981344053dbb50022cf797b7cc2fdd015965ef309453d3f249d581b04, + 0x15d813aa4208144a30d1b4509db1009a7eea4f4a8ba43145f72a0d9231a45553, + 0x1347fc037b2b26fb2308cf417715a9cfe43c2c65f2c71c7bb6c5c40ebf730e8b, + 0x153cbb5ae6b6d48a1360870cfd5f5e0f4c4ea591acd14df7a02b2edcc2eee347, + 0x249ff166662ab43663e65ec0789c6ba6bf1b8594471a26162cafe6c32106a003, + 0x72bc9e678fbc25cf9101f49cbcfc48cc0a51b86aa9d7e66c52897a5d3f5dcab, + 0xa6577ae2a5cabf4c9f00eea76f9fc2196288f1f8b3c16d54c21fbcb28a1da20, + 0x1c610a46a4eca6c1215870d8d35d92712544192b256de5f82ff6d3cd6eb327d1, + 0x2b9a13cbeb3acc4a615f45dcaf18828c844a1d61be9b59201a8fbd9db0cb2640, + 0x2ab0560dff6af3c0ff49de6b343eae05c665a0caf15792d3cbd8321119ce2b9b, + 0x16de08dca0ad6de9eb247866b16cf89da11890bf1285318b92cf302d8fe144fc, + 0xcf760300b2969518645ccbbc9d94ff315b966d828ce76e9e665fafe496dc979, + 0x260d564df3dc0db676e22fa410e41794fdde75c4f19584b43650ba909b44ef55, + 0x78c91572dd1477b07006fb1b5852ee50abd789a190db81c0c51de867ed1fc11, + 0x2280039d47ad466e5af645f064e0c10cf12e92c3d40675008d4c4eb9e873807e, + 0x57e2320efb4234e61691c9bb57aeda4fd11ab282b2cda1f69e91871700c81d, + 0x22f771ba7d2d275cf543283250aea007432a03973c77a82744bac9fd942136bd, + 0xf01220ddd07023709c7b55a1485f0a5443030435aa02d9ee677fe4d5ea0e62d, + 0x2e1da930eaa52749c15bb6bcd34b131e7c33ea3ada98437dd9b7eebb22db48e3, + 0x6d621c55789875af6fa6645af8da7331e54044a5ba01c54891ba11af10a36c6, + 0x1ac30223485713604244857141dacd036ab088f29363eb51c3113eba8ef808d1, + 0x24f06bb121eece3bc8c62e05fa6c0ebe28925e2a47a6d16e3269c5984682da4f, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0x146b2acd097033a165d7525b2ce6ccaab4d541d5ea58e215166d393cd5677dac, + 0x1fb587e5904d58efa007310b9d86684fac658ed406c70d0e2af913ea416003b, + 0x2ca7217280f3cb8744c3c3824e46c6de85b654c41b19f4b662f8250f742041ea, + 0x1ae6ea2012fe1e87bca1988cefb126d63082cb3fa74a717b3008a4026a6eb28b, + 0x2d80fe550d7a4f7f67d2b170a430270679f03d119839d9ca72efbb9982dabfc4, + 0x137557593958b59bdbce0dc6594c99cb85c80f3e518e99179d8000b339492575, + 0x1def05089b4444afbf11ff8fb6e10259ee3b837fd0dd3d9be17595ecb5480c92, + 0x201b23b3cfb13fdb40deb239b3ece158fd8c67950c242ededb39540f9d71788a, + 0x22d9d27ccfb5d874defd155bdb5e0f9255e7be972f912c44ada9b7a2831116bd, + 0x239a279e55c2fd47d5872597cf2ce10ab41dba4cde5bf4cd7fd478342234b264, + 0x137724d6aa363143908f50d990be5f70794e6b9fe17beea4dcfea9dc0b6073c4, + 0x1dd6e3fde1b84a0b4a9fd1016d1c6d22fa80abedf000368d34d8c069be2fee72, + 0x2c94522857162e4e67bfbd495e823aed177c8a5d87d237fc57e5355b177e73c7, + 0x183022fedba6c78d0076bb2c2c6bb4722444fe77703e0a6f462dab5579dabded, + 0x2252e07ab4d0fcf8dcda2fd18514f0314282297cc99819dfcf0a5a9f35544430, + 0x719e632cee131b853c0824f527980bf00f18d8a16aa7f265480cd10ed3428fd, + 0x302441b28d3b1cf39dda7be9eced59f318c188274c6adec584737856495fd875, + 0x12692c7d7301e18bcff106c275cdd2dbc67001502b21aa890d6bd70e95a76934, + 0x1eada016794439b4d460b47956301225601ba9273266a9e955fd3e3c347aa7df, + 0x5cb3b0ddfcf2ea8552ef578139d19816d5c3ea7084f80c8cfcc43960ac2c980, + 0x13b78f0215ed7f48f40363ea5640fb9a41bfe6ff5044ad3aff51d755d9bcfb15, + 0x1b3a63d2f5d84163f48ff24f99ccba5ef05b29ca80019907e1c3a789296b22df, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0x2957ffc8d1b0a3f2dd026ad7b90fb7eeb555d3772d8f2c7f47e37e913a921fd5, + 0x2a1c6c7b345e260cbe11154aa6a062d87725bb940dfe9798e794d551306f75f1, + 0x300cad430463e7de043c54011a594b2e5aa9f0aaf6558a5194a68a3285bda986, + 0xab63cd76eadd01e944a13e73f2f03afffc11b4823380c6d0f653cf2966b1eaa, + 0x26227ae79cdec5b80aff802dbb9bf4e8659ae92bd8a83be6dcba8d5917c4d34f, + 0xf30d1719ff31c8ac2175e5fd863b5b04516809e3c7ac6ec41a1a53d866a71e, + 0x11c786871cc25ea48df5ad070b2fd3969a4841f05885a80028d910b7b6e6eab2, + 0x2c7a714da7b75d6bb3eb16b8d1599f3729105bae675a1924f43c3239f9c1335b, + 0x24b7026b296c245b47ddbc1e44492034c4b7a8d35b2887cd539513c5d0532403, + 0x2c247c7290fbeec55bc8593b0f859b43451002df189238934b16bf1a20d3624a, + 0xb94893f2502d38fdb691bfd23b211fac95d934cf913f4c52eac9999fc059e6d, + 0x79b6b8524b8270e480562beac696afed88406015d4419a8ff123329050dd3b2, + 0x27e2e1708fc82a7868b3a0fabf059d164ed3dc38f0e6220534928b1cdf59e26c, + 0x3040afbc8482759cedf03abb41a1ee858cdf563190eecfb2a24424d4964911b5, + 0x1741752784ea1fc7304aca0447b2878de168c87b78e2c3ec32d6805b4d2a41e3, + 0x13445ec326f4aefaa2a84547767b65d8884679aeddb391598b219ae7ffd41830, + 0x2b23df120933a79eb1feea325a521ba5d53372e29d279a8c32dec33a83dceac5, + 0x2c6adf68e43f02f6721d9fd6d19e8934ce3a462ec543ff34210e828239177789, + 0x2e9faaed5c26fecc4672723370623d6f563537c06d1e98292134f4ae26f1cae, + 0x22c261e0c7bdfb933e808382fd75da681f46d90e703407326630768407e0c27, + 0x15605ce70aa2918973c4bff136303580b51fb071d5224a1732c10424b1fc7a82, + 0x21ecd0341474c3b4ce81101d267ca95d7cd2647fa4bfbc823956a9e348ddb877, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0x2932e8876d985ea09549df2c64e8097d85c3578aa46adf5eafac039999835c5, + 0x2c1bf660a1dc8b26995b0e78875b0c28de9ef7b591fa2bc01a15ce7729b9ac5b, + 0x1e88f3c4efa334fa5bf313a919c4de396bde82e124f0002f1c00229f8dbcb67b, + 0xc774d6acb4fcc45b139d92323da82304fc4e29a919c9468746dd20a6e03fced, + 0x17c11174c9104e2ea1a374b75bea6925ec45a1d9e5293741944e5359d4d34408, + 0x221f6d3412048020aa832d764a5b5e80af3b014139b28f06920cd3a3d3c7b7b3, + 0x2c0b403d133861410859b48131001ac956fe4c9e5a368d9c3f085560e5d37699, + 0x1da9a5cdcc8d5c8e8390afe24b8d801bb87b9fb9eed429aae52aba17570c9d03, + 0xc3e382527280ac6525b3922388b310dc9864d9fd11815a2c94f7378f3d52f53, + 0x2e733c656ab7308a5f77b1747c7c7562f0b48d9bc42b4c1392632840dc67eb83, + 0x5500ca3eb4bd08bd91997d4fc698fa050d5d80d881f634f84feaaac57b15b2d, + 0x112aac301ad5ced619c2925c297d3387bd0690d0972aa21f88d7437f42bb5cf9, + 0x273c9c5526da6130164e2360c9cf111e2a1fb2b5f02a5a463c6c64d55a6c4760, + 0x5b30e5e7b01d8730fd549eef232bd3824b3a670604ccfa2407f2a63eab5f5f2, + 0x26e905c3889e46597070e8b67d4ac9ed44f5a89d59efec7add002494da376c6c, + 0x3a4bd09500b265238ee8fe2cc149e058d35559d4af804be07119815b5b98960, + 0x301e86bf4790028b674b2497deb4370f32b2410defc6a4f3ef6e500a0f29827d, + 0x86d71db143455444d99b9993964b827cadf4feafebddcf019c278f32c8114f5, + 0x174ef177c132d7a3e91f02639d7dd88248435018525f095ef18cb846bb060e62, + 0x57af114d2416184735fcff06d88e734f7d8d5dd412b7c407bb3a0f09bc2d44b, + 0x2cd21076d55f5c9c8c3c3afbf7f0eb2faf05ff80d267eb692d93b8400c9b5fd6, + 0x1ab2f05ede0b3e9790517712ef714568d570da3a0833f8e8317c1644264ce97e, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0x134ff00b65e9a214f19212b4750781ba3dd2e28511f61cda7a69553bafb44dc7, + 0x144774a605bb8a7d11b2f8fbc2a0d05146812a9f1d03c4be608a544d18ad8f6d, + 0x2f1de3b0835804059ddeb1d93bbb9821f6e2070365ff34da2c43dff65d3edf8d, + 0x930a41a901ddf9dc66d27b2238016500aec43b06bac6e7113beaff39df69c74, + 0x5ea98895839deeb637c0693c60994afe4950a088d1005946b20c25f48b1f4a9, + 0x2b2ad0eb96fe5e5ca0062109b8c535d32ba984e38547f3d1050b72526884e14c, + 0xea3a0fc0b46da189a9dca213c0288e3369573fa66b3d3379ae56df2a25262f8, + 0x272ea64f54ab3526e4679a0d0982560233af7b7f2e85147a86298fe62afb073a, + 0x281aa6e665287f9540fb2f6d13a077d52e145ed62b38c64899b92a123357c089, + 0x2a432fcc6ed2fce50bf214a31f9546baa2fe8fb3d1d00145a7fca7482ae2c390, + 0xa9809138f12435ad1150f8fc74d401d992c42439a44ebd122991bece3824ed3, + 0x109adc1cf8528ec8f537cfe978e320e2a4027abba83a3781aee0b88444805154, + 0x979b7716c8be6bc4091a376ffd1fc1313e19f3266095bc753da2cd4df883ed2, + 0x163c946685c585d46b6eb8a3edaf018353549856ff6ec0a238f45a1f0d593af1, + 0xd3d1890201c5bb1a7e40dd5575b4267fad63ae91f429efc5f57f52f498f4203, + 0x1f4adf58a1ca1586815ac26a76d8d6a25c313e9b2b0ac7f830e6e1e0cee2dcc8, + 0x2916cd6ca0ee56ce79345046ce1a91a231895fe24628a840852474b240b53459, + 0x1390ae730e0297f1c7ef2e27b3c050d6713015a40370d6a281f1c985dbfe86f9, + 0x2b747562e4956de74f4b115e082bd95c00a7e2a175255c7ebef7cdc70598de11, + 0x26d57a5bdf2b1da9eda88e856c4909c4265ea86d8b7f630caf123aac328e0207, + 0x24410235e3faacc2da4215b96ccc5228faf00709dac6542f589409ee5d833901, + 0x2bb0d85f9daad9891a6ca76117c5912a19e2b959f03e59ac52ca61c6fc90bf32, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0x1c53d25cc30ee67b9ca5de92e574ae8e006378568883a35ec673078c5cffffa3, + 0x15809370254e24135947fa4d4c9bb5366a809244c42e44d58ad51041ee0ac0a1, + 0x1c7feb95c74dfad69a598a6569b5544b3138c293c78957c281e16178dd4d2ffc, + 0x7160482689f59cfff868ce436b6135ce5b8d2e15aeddfad236cbbd174fceae6, + 0x1e1716d8a49f0c324485bc3adc0f6a47ca4d7921e079fec272d79aa4d4f5036b, + 0x2234e7ce1e40056deb62ede7b86c7f6482f7a253ce49aa78aa5c636a5f0f942a, + 0x1134d89c4cc64ecb35202fc26b51689c745b812587ea60ae3e2636908b428a0e, + 0x13c6c021a7904ddd8cbf3d0a7db61e044403812726e369bdb97ca31cd05142a4, + 0x1c750f568881fa07bd9d06cf2c36356c5b824b71bf2060b763fb2895667b54af, + 0x8170199a5b260bcb05638100428def3df9efdb5233441d14fc219c1bcfb0a7a, + 0x1c0bf7af434ae20e594924e912515bbe260e21afd030f32eb7b0bf5cddbfb1e0, + 0x1217414da7ee96629d16d8d7b906df0c15bb7bd5bfa5595974714aed8b3de96b, + 0x19bcebdd18dd8cd827850f36a3f6849dc028bffcc10fd5864c0e37c50156964c, + 0x67a8b7fce532eaaf198ef0fd1126b45f7d0aa8645e35b0331d7eefdc9c7b364, + 0x2a92c17b2ba923484475d4bbf164caa1a8f16523b6a23b2dba260d7178530eae, + 0x21bad2c773c7b349b2930be09781138a061c06f4f06fc38e71332b942ff2939f, + 0x28d0786689c5a9bc8c7f2eb62f2fd0b21d776f3cd74725c0bc2aeec801048801, + 0x222cc9d34695b0088ad166a5defde21377627fdd32b789575085363d6d5ef907, + 0x2a54d465647c8ac5df86ec2bac782e9aa560977f7fb60b87ccf3cde01e40ac60, + 0x13822f37a288f99d881dd1e6f6df9a8ffff482f84179be0924e7768d678a2a90, + 0x1792175406aa3a9e7056233f4a70042e8226c943b7aba99805727ff7a9565071, + 0x80bc46879014fd6b55a3e4d7698925b2a6710b7a5478a51292964f64de1d762, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0x8aeebda8fdf99667caaa1b7f570e579375edf7fb6438af9b689bfc12e2c8ba3, + 0x4b0ff272995a13fede7f4465a2f0ad2134efef55626e1824c08ed67ad981bd7, + 0x63c3f451fb64fd5e95d21c8eab8fb98523a716c8f83e0f764b41a8e731daeae, + 0x1928de8cc64d6cf21107045a7fcc4e0cba4706e68cfe779044583f2aaf6e885d, + 0x1ef2ec873dca7eb1092b1835b74cdb403726d8fab6cbef50b231df9ab87ce725, + 0xae02db0ea401b8a1c747f50e885d087eea93fb3037870bd36b1440d88995031, + 0xcb7ba6cb4e056aeb2bde61a38521aeadd877772701fa572fc77915050db758b, + 0x18e89e7317025644f8043265ce00d61382467265fa055598066b9b19b47653f6, + 0x167a003eddaa7d10f96e547b66cc2bd9f2ca99d267e011fc69669f71d0b71fbb, + 0x573cbb272daa570f35256fd3826e34c3e2f35f300adea697a306f914db7a584, + 0x7fc9b6fdf58ee181a0141cff89e34513e7b4d61e01786c176dca84b9664eaa1, + 0x2b3af74c7a1c0f396429f7e2d70e68b014b3a268d92897330cb9fdb1615674c6, + 0x22580eb83a854a817e4277e8cf1a05f663d198c0b2b6458fa4cc45120b48883c, + 0xc03a653e7e2061d62e638a0931b767a550722b318ebfc8bd924b22c8a009b40, + 0x1f0f1d34546815b4410f8ddf67bec129e8ae08fe617497a70e85b80802e0557b, + 0x1dc998a827321537333b22cdf7bcf0a5fd9a72cf9ed9d9e05ca82df4105c02f3, + 0x21305fbed36a0b611ccd7139a48b7d36985041687c4b76483eef93d98e28debe, + 0x19caf75550855e1b4d0e580444a73db1d86d507b72031d11925f33fbcf7e9f10, + 0xfdea1098aa89298d72ddfdc5a47c8f9141955ff5a612b4c52ad3ea0461f3df7, + 0x15e15542d8176284cb1b007f4655236b1f6795f045634ec815fbb5f842bb3c64, + 0x24b51f84f0737f35c038d3801de3102fc32dbe223491c5367af7baca0e933482, + 0x22231a672bfb82faf7b867475382c2fc174937b53ce765f4b6fb9737177a0ecb, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0x2020cec5cf125567b97756ed7174259dec539b4c40bba51bb64779221b4bca9d, + 0x16b7ffb1a4af4b1dae8d82824c542e81b7380efebf3183208dd87f3368f2cd73, + 0x29474e7fba2de80bedfa9f2f8bcaa38e6b154ba2da3454fd1436fd5bacaf2bf0, + 0x29f55a4fd3170647fad71cf38c80c4cf8af0b1039acbd193732ff1bdcb049368, + 0x2383d1015508e17fa9ff282c175ea5ed655f74bd5793bae4700459b5600cceed, + 0xb21347d3f2e1ed0ed02262545a6aeb4209b1809b132f7f1036af67f9ecc114a, + 0x1c3b4d79046a0030b73e4ed03746ef2898778560012f14b8c151f4166e0c9cfe, + 0x2bbdcab9bc95ec1509f2aec2af8b117c34d8d8079173cc099e658c863088aad5, + 0x32c3e39a7299f29c816d761fbc2abda28743e917547eea1eeaa75975b22b7cd, + 0x2402ee3c6cfac01e1fb6551c34b1591e2b419d4ec69a0a9f1331cb546c31dfb1, + 0xffbdb63b86161ab9648a7bb7e5c25d1541847070efa58c6240937eabd05acd, + 0x2dd50132157285954cbfc6ec6f2e73b0d1218c699a07fb09984690d0fc8719bc, + 0x116fcfd48ab31fc4b622f442566be132d688edf27d5337fd8afb80932769151c, + 0x2c3c7ae7989bf23c86279e146798a3ecdd80898acbb6c2ec1f716eb7a91b017b, + 0x2b7e60fcbeef2020823e799448da1cb0b866d776c8f74c031de2f5452010186c, + 0x2b4a3e4a2db9c0cba63a23100fe5b9ad29b63e1e004b40a16fc00e20a83b7d0b, + 0xd1527b252bfd505f375cf86b9fc95dc55fe1ca65dcf37409ec48da8b1207735, + 0x1b0a396a158fa717511114766ffadeafc6cd82b72390aa908e1c5b496eaa2ed, + 0x25b7181ae26411c1705d3adb389716b615f7c1bb3051ab9b9af4df76cca672a5, + 0x1ce6e261ad4d6353538814957c5184ff343521f18ed1e8ac24dd380978f1b1ff, + 0x2114b703153c05d8a458b86daacb8a1180a0e0e06313c69f0319885218d57254, + 0xbba93da8fd45f0232aac88e242f83553799a5dd893a27697169d9ff3f628dbf, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0x234620365d9e508d8b7a01a20c8b84cfe78734bdd7a480a6f3c0270be6c9e031, + 0x18773402938384bdcf3ed2931a34af760d3401e10cca02854081209ca5bf9c71, + 0x12f489609e827ee3dd6a53036f1f8fb80243c0ba7ac2720ed6997504f7f50d3e, + 0x98af099212892af46e34cedbb21e88b9184ab2fccb8b8665a5324601d8c5909, + 0x229c5955c3b6f26373956d4e3ddbce6c4c97dbd1382ed1c141c6c6b8cbcfa95f, + 0x204c3dd1c157600ceb1cb55072ee278292a3003a7777febb080a33168f4fd9f6, + 0xfe2cb3ac38a35f9d943e20a4cd370598e5c1b128edfb9cb877f2d424cba56a7, + 0x2ae0af8492610bc178f36cf8887b6bc86f02da15b1dffb674706df0d9b62e9ee, + 0x1ed1520997dc0364683540a32fe3e4368385d140b61b09672ff0e0bc2b398115, + 0x25a0c2f522b7f27667a93c435c2bdc67d575da8a808bfdf2a43558b1eb12d9fd, + 0x24d9bf46734bea252329879adfb65782fa5c6809a1520a3656d7f67331348d3e, + 0x2b5277817669cc8df0c6b82feb1587ed59210f1414ae609f40def4c314d96e05, + 0x724f33acc2c20822fe7f8d3d1f0ac39b2fa1025dc18dccaa4b258a2654e705b, + 0x173f609ce483747dc7ead26598dd2227107af0521fcaac5efc2bdc3f48c07c99, + 0xcf0b2b3f0ab40d718173aad7993e6213ee48804e3e563f0e531e2c937abdf9e, + 0x17ce34f45aafd638238ac5846997636b58aa04d76b4b0bb46aa0cd078ae14f8d, + 0xaf51c9e93fa5991104504bba90149228d64eece560e4c8bc2ccf1b943cfa761, + 0x67a323bab4f3d03df325818a393ba5dfabd66405cf74e65e9dd52ee2d8fb197, + 0xc3d3445a27d7a042fa2b4c5e2b5d03c1332d38bf26a781449325896df57ebaf, + 0x1b5b3c710b37f195824a623712b2104d821ec8d859940bf0d27a3c50faa2e886, + 0x16fbcb1c414031ba771845e6f67151fa983a4e32972031ef813e5f43ff3a8cb7, + 0x2dbb1e93d3cdcff3ec3bb01debd9211951fab454e9a019fa4658a98f148cc8ff, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0x1f580786a86e622d9ea1bfd87c2d7a3a5f19f25105f0247f08b0e1ed89bd9dbb, + 0xe2debc6417cbce9356f75fb55b7ef0347205dfb84b5b0de2c02f4e130453c16, + 0x286b399e2ca189612a8d7dbbe938a61a273025779047f72ac5fc902847dfc0fd, + 0x13144b54692e577de4598ca0783dde7af2a3a81cc5f0030b6c3bd92d3bf76dee, + 0xaf7247e59389d0f9509b168845f46a72b4474d9ef66dd7e35f58450fdafe9ab, + 0x18b3c1a2e20476cef58aeb4b8ec1820d80c28a5309d85f974fa62a19d262f5b9, + 0x22d6ca5d958faf4940b74e3f50fe6eef888799302c7c99399331a9db0a9dde32, + 0x28ebcdb416210c7ea0a9c44cdcc1763bfeed08267cc7a17a935f0e75dd6beb6b, + 0x264522a85698bf1cd24c21e937f975faa4cbfb3534cdbaff55a89a17f947aedd, + 0x170ca38dff04f179223dcbf96e15609225436e47f6aad10c21059b549b8ace87, + 0x1980e8052c47daa2a7eceb160ba3cb93291acf7b84c3a1b83977766d78e7ca83, + 0x2ef55e77f32308739f0831d0a98f7a6961e4822e53027d86a46aa9c9ad39b64a, + 0x284ac526379b614a14c7ea0567aba7a459c269c32fd5af192240c11103a308c1, + 0x1d5a978ae2de2380a458d23f2c2c1f7bc1791d4fbeb38b6c7a356b6f033e6dc9, + 0x1fdd8752355eee4ecb1e8924b6541942da0c3f56e2f6c12e2ab75eebfcd1bd98, + 0x274b47507df843c5fd2f4c823c4c22057b76336affc6631035f28e57f6a6d387, + 0x2d46b1ea87a9f2ed6d8665f43aa1b4f6fe399bed08d9c77bd98e82350be3f379, + 0x21e50a36ee2e6ed562fd73013bb2d34724b4ef34525c51931610076b81d49eca, + 0x2f0a7fda21c19ae55233db913f1dd886bf71e9a0fe12f425d479f462f1cf4b06, + 0x2dc7e716c1b4d182cdb078f38ee7148f0ff45a65f7f6360a66d6a29fe78172a4, + 0xa24d8de1362fe9f8f23609dee59bbb4230f39236e6729ffdd95bedcf8f404dd, + 0x2b1c087ce01523c9e0f97d81c67a77014e6f791a656f8edca33133fe9206bbbf, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0x243ab6d29d356d147b7915a7a11f6ef485a0f3ef8d003ac239c0a926df820271, + 0x10f0ea299cfd16da7c54cf4315a4bf993f6c8ed21e1f1b629258655bb569f3b4, + 0x1057e97ac983fedfa508de5e9055c24629b7faa279f1e483a2927e621a45a16f, + 0x13ecb96925a985173e792bcadd76dbf62657e8aee6e732e1fef9ceb1d86688be, + 0xe6f9b2c64d9d97e1dcd59691a2944c4e610f2c9361a93284853c335ef448b93, + 0xf5130dfaac7698c83247ab7d37384c6f4fdea4c423691dbc0466cc847d22240, + 0x719c66d510d88d51a80f22c9ee06cab506ed395847532f0b0aef79e94ff5c37, + 0x19fe7de3a53de3d0cbfbbe226c6d9799cac73c343bb7f652246d3314de2cd748, + 0x1fb5113860f9c3717742da8ac8dc02d3d750447ae00236789ac400ab7b0a4a5a, + 0x28637c9718b8c1053ac27e6ccb68a14daced5c24c3932460d23aa40fe066611f, + 0x1049f5f885c559fe26f7d811c660cc9c6ffdb5103dd3217111b99808a28a10ca, + 0x11ec2b02d176c222bc479f6fba4e427738b96aca1b7c3aa11db89b27ae10f0e3, + 0x194af56781953f69e1b00c8040eae1bd59b4861dfbb3969d8161d77552233c16, + 0xe752eda03c9dc685060d7d0625d4882ee9ccf2748929286db03f0a453d8c21c, + 0x1440c319ce47daf613542b6085053ac22ace7246863f49df6488292e7bc72a2c, + 0x10cd79d6139155e4208ddc71ac9646aeb4ac61a3eadfaf337ff97ed9109e0971, + 0x2ef23590604b7f057aaa0583333f5766d25a43366d99ab87f9e290600b3f749, + 0x2ef2c45fc47b175cb8c6e23c2cd7d26332ee65470759893d167772f18b799f97, + 0x1e769953c74901e1cd39e0a9d7ea12db105fa2a0c3fe40cbe36965e11152482c, + 0x2713a7060c9901b904ee4efd31cbe1bb0ac6efee3756d59392e8b594db57a617, + 0x15b3bc638f4556ac765e5c60678b18ecc5a7aac5bcabef247da9cf116cf4249a, + 0x1df44e6b43f51e3a708b7b6f7a05c67e7817d8fe6f36e357e266265e3183535d, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0xda3ee283edb0e4256891ac9f4166ba14c17436c1ff8b6870f6dea7962f36c3c, + 0x2eed5fb764a1fa6cd387d19322790c87a6b6a0b13f832f24f0fa54f36aadc0d5, + 0xcb9fce02c3f2f82704477407a46991cab311db6e12f14e388c2a4b6093de75a, + 0x2eeba73653edce41cef62722997e5df9d2f76d799cf112d29bb5706a6eadad08, + 0x4318c41475504dce0c6bbd1e76fed829f7c8a71f1b02f45eedf5c3a71e63909, + 0x2a094657153ecc1710c0583c1c3b7e7966e67057c8faedd408e505127a78605e, + 0xf40aee2532a088cda6d1b13c48569022dea6023f85231a5544a9e6cc4edcce2, + 0xd97ae723214277576911235bc25ed81063fcd21b59e6279275f11f57c054459, + 0x82f1e5e8e5087c1aefd0f4fc62167bca4b73b8009e3a67e07cefaef1e475cee, + 0x284f24d43d09bf31c1b59d84a8f2ffd8b1b903a2b88827fba8b02468ff57a971, + 0x2b6538eb36991fc2429f8c38483f7d4ae728b7e105b4ac6bb449258eb89d3aa8, + 0x82e7991093e92b53c575b9f51f8bb8d1d2a405bb94359544a3106e033b3f2a4, + 0x288593b3cdd201b3f6ee7d9ff217e0badc9dde2bb6ca2a63359ceca59ed12d81, + 0x2762b0c05f66a7d3a2c4b46f6da9e207194c32a91a15d0c8c7a8601874649bd0, + 0x20851ccb233ef814435570f9435eaf7cd22baf2a89720b4b09d035dd42d0305, + 0x1e17e4ac7afb5980903d9faaa355d2d4bc00f661cea435cd563a0c08d89f52d7, + 0x11c64762f6e40528ef5f60c4905cd442e137348737ff11ef9fe186e85d88cc81, + 0x135a7893f0df31bdb093e2f1936efde3bf6c80cded53bbf23842d5cfa739c10d, + 0x670c942b19efe0e24ae667f88cf25482988d4fd289852b59c7400bb291fd22a, + 0x2feb899196016827ef03dffaae29bd9f7df66f312f728ac0398d2be90a10c46d, + 0x23bb8acfb809bdb5ed2b2306e5870465cd881e8517cf8d60b6eacb23993ec19d, + 0xa2f66d3d56165a8357ad4ede386e8bd3d2c1a6a51ec4a928d02aa9cf2c94025, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0x2621d53d90f51a97a82455d448359f1f876b08ee77917e55298b4a4f7f2c80c3, + 0x2e1713aa13a1ed2a7b57ece72d5599b6e239d5fa53866e407444290254f10515, + 0xb0e3135b9a9bb3900a312bce8cbfaa6bf7176bf09974e9224d63f81eeb9cdde, + 0x1b37ec261be552d7f9cacbdc0d0f22ebefd7c123cdcd54a0b493db30a65359fd, + 0x100051565c2e4d9fed118b55fbef6f060608dfe4555e486a44e6971696042dd1, + 0x298819bac61778b218142e4fb26533f0ab1f8f40c8d8070fe2f1d4170d93c58b, + 0x2cbb90e508952c4b5ed26079f85f11f3bd728140e3b8cb91c1da9152c8a82560, + 0x18e9de503cef0ae3f8901d7d9004170e4661e3792b464e8d7e1a7c7f8bb17091, + 0x240a6c59aa72438261cb26070ca93ef35db217770a207e7cd9af3a4df60768af, + 0x1c5c0274172befaeca201df876ee39b582fa848a0bc9454f6834b073c4ed7f73, + 0x1dd2fcb227876523c5d075aeaad2df556ca76939be98462768f94940ca73028d, + 0x1e0ebffd9567e4222b322bd16275af85e3a09c6db8f053a7027827bcfba8a0ce, + 0x549e3fd2d8b4c8f5e1f6e5ada4adc3125ece6af1041e4f297d14cc80bd7a865, + 0xa43a7e3ba83061b5379f61580f17fdb5068f57a18cf3d8f4431ef14a7fd8bbd, + 0x2a8c713fa0bf5e002dbde544aff988ed8b347afe2b3641a08eab979bddd4d2c9, + 0x307b423ad05a7c6c5a7feac041de1c236cf3db8e0da46368ab0a5113dcfd4d0, + 0x1202dca5513d8609b3e911ffc3c1f8da4138f56287f2837bc1f8820469bd5839, + 0xa109d2e7176796406f7fc25caf837f5c8d2306962baca62457fd49673b0e48d, + 0x2158fe72a1672fc1b0aeb56bdeceff410de2a404c9f4d7a2e39c4cf0800264d3, + 0x5e83a4f3ed30f863a148e66c1771a4634ed52e73dc1f9c35e479744dacb7c2e, + 0x15146f0169d0dcb2e678a62443c00442cc342091a6d18a293a17882adaf6f146, + 0xe27f3790482529695293a0defd1f44495f0adae815cdee0d3ce9f91512c1be5, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0x216bf6d0d240ce8a0b430f85259b74084cf9f998823dbf13091042a32b4ea56a, + 0x177227662dcc7ef354ef41fdb3f234ad93e7b70a6550e09be2c947ea462597b0, + 0x1864bb94cc95e4e33b7673809909ee3a156c892cea648f047f2864db12278e4a, + 0x2eba9c8ba56d6b800654a1e805d403bbaf22af7ff1aad92ab7cf420c129a2616, + 0x24133306f286c04d2c2e174c0cce34c64c21f81e0df67c2593de5b422dc1eb20, + 0xa1aeba71ae73f2846cbd57f9dda3c3e24b82291d22108a6a05a9c06e002b8d5, + 0xd2d0af3b16bd738a5e01bb7af549f842a2a9f847063845d36d7424e1d2bfeac, + 0x8e4a4d4fb97473cfd880c9285028c2883d6d08164ae7db26e6900b532e848d5, + 0x2b2ae02b9d6d53220998acbb749c29f4476c9f2cd34b74c66e4f2c4abaab6520, + 0x1fd0ca0b29e63609c2f6a3150ef62616a5fe2160266382030e48b29806298756, + 0x11e7f1f91826d815902e2d9d79e027c44e78197f4450cbf14128d704c2dd46d7, + 0x25ae141d31ff22370a99693adb350858a307e1fcfb60fe175a3279d99879e2dc, + 0x13047c24823af0bdf17ccaeda371552e8834990abeb7ee7a9a646aa7bb9f4753, + 0x266358e11e5081dc2944990007644733445e90ddab20cd50912c06cf1388e92a, + 0x1247a2077d577a1ef6f0aefe8a7a2df21828f69c44bb89b6ae70fe9c3ee1af91, + 0x2c338524f33f321e6f2e5e420edd47f14caca5bfdb7d3e065073b7b20d2814fc, + 0x2ced7c9cfc6cb9727179bfeaf0ffc028a759aa44e97257f72c3467f9a0974c26, + 0xe633982a359333b017dc5b4e683bfa274e74153f4f99d639e48de02fe239c9c, + 0x2ea0bf1ed70f15fc196a395ac836e6a579d4923fd13be32b1416d351a05afaf6, + 0x238f38e3b7a1d517e00c666c6670c099cd2bd7d8418c55facd6e511ea37c64e0, + 0x2da765692bbfefabcaeb0dab3ee18797ec0032c1feb257983ce753a8f286a75a, + 0x2cab9bc1d925ca3f6473d56a4c57ec136f52fcf02c9ee0e25ad07fe24dc281d1, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0x1210303a7705212e81f926482699c6d6b6aa13ba342f4576c873ce976435efe, + 0x2e1fe52ad49d5b2cf4c43c7fd551fd05bb0cad132226c92b47e4bd24bde2852b, + 0x16e6198e30d06c12d5535709100d47d0ab174704e4953b696bdcb8318c78d80f, + 0x11087fc4daf5c010f9ea8b66e2f01e9032597965c811afb9ca9c7004e01a7eb8, + 0x268cc3c909fbb19b2d737b0feb4aaafd6a2c0f0da4f6b391ead88673c187e8bd, + 0x1200152bacfbb5e21565b19d0e6b47ae2714cf2bd9ae7038fe9132879d4b4688, + 0x28db252e756f0ffa83fd845fa7d06ebaa301d37edf474a3b71f60539a630f59b, + 0x184e95906f85e4e36b0b77e9d862fc27a56ec38c3178f8904851700c703c9db5, + 0x14d66e67decb7a7f74926f2d5ec6497b965b4de941bddbd77371a3da470e5d96, + 0x12a5b346904fd63b6c52f603e8a0c351d2284ec345e50518492ba935b07ba7b9, + 0x269094e291d79246bb735d3c4a3df2ec9fb60a6b2f2340e63c91cc6d5dfb083b, + 0x13929b4087a818cd5f602ee40afecbc30ad8ecb2b7677530094d09309808ece0, + 0x14f878c52f6d09cc1b32f3ceb6f2459a5fd6668860b945b74457d819a6d18757, + 0x2d91fc38379e50d8addc35fdfb88d27e100837e513f329afc4fc9cbc6fa0140a, + 0x27b4dd2629f029c1ec11bb5f235252371947313993a0111e4f5cd14d47b505b8, + 0xfcf71b4f58f1e845394800f32015de09e4107ce8a7bc786810e3cabb67d5d5e, + 0xdb4f212a8d9f8036174d995937618dc8074ca32f5ca1bb537fbab6898dc679c, + 0xfa6cd0c9a74c1973656d44ae21323b5d29ee26065906f0747bc3364d9fa8ff9, + 0x2f5d612a89e3ff0157b8c05eb81cdb030b3aa80728ee5f2b484e027e9d7b587, + 0x12bc2f8ea309d0aae7cf1fd15767dbe97c288b2d72e1ea489a383169d7e5cf07, + 0x20e5a78984a6e437e16aafd2e43f119233b4bb35cfb628aebcca0ab3b102b4c5, + 0x155ec9570cd3e503fc1c73fabd38c4ae24d31e5a38bc56c992b5817c9a58c18d, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0x6a4859991b82108283b6091195b9244714a1997a97833c55c4e15c00747f5fa, + 0x1a17c910b931d2fa7fbf8d41a1ce86a3496148f0a62cbb541a94310c3bb931d6, + 0x13c27123ab15ac6f964022f94aefaa51f07391afc1095d7480acffec7e9cd6e1, + 0x171c742bb0ca2a0282f5fd7628191e6ccaf3e32c38305a00f6593b4fd7527f9d, + 0x16cf4b06cbdd21c5afd1ec787847f6956fc45cec34e95739af5ca67c27da7729, + 0x11e51d4503b1aedbfe993befc9c8078b70d4db75556da4942846d22f217dc694, + 0x8afd62076c7f946b4dd61967b32a6d09e794888c2702acfacead811a4fb4846, + 0x4158c5f8f1b10efa12aab63546ffc8f065ade0bb494a31a58391c41f62fa841, + 0x2f87837b6f5f2807659ec7565173893f91a4ac26b6c2e26e22d09a417309dd32, + 0x7c728d2e8d95bc8842ddf8db4c76412aefae425c2774ebdba4317ea783345f5, + 0x1455d8963d76e99083c896bf0f68f63db992b86a913f3b123a98889fd61a3b0d, + 0x8b4bf22aa0e03b5f857a51c0e04b64565f59c87efb6859f8c7169dec09e2841, + 0xed823b8b9d0f2e0b0c6aaaf3e5621308414d4be94ca3ccbc6c8aa0ce8e1b4b9, + 0x1642b64b6547c137ea9d16920d1d4273ec49148369a457cd28f73cd9098ee6a2, + 0xc9d91924e007af49ba20f16356373ae9cdd408bda9255583e41c1079c5c06ba, + 0x2f1518b8bcf463362e1e927f733dedbe8817de8dff121a6a5527b33e70778ce5, + 0x2114e089d96c5a4b64b2a6ad154fc6880bcad9eb3e8cd1d3ef980efda445281, + 0x1abc25ed5c0fae93b3813bd8fda0cf773df41cced07a8ab762fb36b6564922f7, + 0x2a5eddd216f0eadc4c50a2618f44a4dffd68ec6af8f7c0bce1a45894e6cbc010, + 0x75e0d34b920790fbbd21418ecb62663464bcfa06db3581dbec635c8cf864ec9, + 0x27b7beb430a31d0967dd287dea9fe9d0a16def46efb5518aba65fa025d82579b, + 0x270bcb008b10d32d8b92753219422002494e30327ee71b2379b09d5a8e519b9a, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0x26c4a3b0ff9b7f29c97c01b4fdc65d8ed1a07717da9b297d3d2a855fda54bee0, + 0x2c6dfb52d9648d18f5ff9db4e213c6c94f2fb8151aeddd80a1cf95df1ab4862e, + 0x2f7b7e795fd4f392f9810877d44523a6fd9ca59bf9f6f15502f4449b6fda8c85, + 0x5722aaa2080e70ce91c67932130feac2c7ce93eff67e453c4a10c7923d8282b, + 0x305247769dc2fc18b8f32cff8b1a08ebe60b0ce5179bc0fef9e41893007050db, + 0x25c0007547961e0f368c5bd7bcd2335c7d35c1dcd4e04b169ea6676a2713ebf, + 0xaf75b019c88a07fb24d01cbbb2ea86e75ce904560f06eaabd617cc627ab0cec, + 0x4707e08232d55d9c5a37b7378d94cfd74933b1f483a6db89a7f7cc83d17a228, + 0x1cb2bc2b494b4a6f9e502992730dcc6b94aada6d0a04a350087b3c9866c448cc, + 0x292295bf6257bde873af036dd6932b623fea12bb31928bdfc800d1a6bdb7dc5f, + 0x235b612e67013ebf3b74fa41157682a4169a17315695f54c73f290afc4574a3a, + 0x1f412dc0da42db6a648c19e9e9119b157483bdbc7ad3936efb9dcb3e72e12114, + 0x1402bde219d915bbc5f2958edd28a107072ce6cbf62346462754c21d6d5c9d16, + 0x265eef82382e05522d8c113ab42ab0b09da4c166e107b2fd0cfa47aaee5f4756, + 0x2b329efeaf663ff307ee9a682f883da59ea63242aacb620b61ef85c0110fde26, + 0x6004617ad663a46e41d79103d1de6e8364d2fa582271da3e8b39c01adc8aee2, + 0x1a10c1c3bdcd43ffa6ea4d58f408cd7d0e74a5ea38656a1b6fa88e2013025d55, + 0x9c705ca1ee96783e0530b69117d99337fa1aaf04c5fd26e5309c0118f4bdb32, + 0x978aa5435db1ee6896c737ba36d79120681758793e1a1d56718f6cde533dc5a, + 0x1934fc546cb215a23bef42d7124ceff70e1d469081c2cca343a9ebbcef1ffa60, + 0x1ea452043466f1c5d8f26fa48267014833214842b2d204fb253b97c9b3deed6a, + 0x876bcc65ef05f89d90f3a96070a57d48d6a2a09de2aaba161fd6b9e80cd6ccb, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0x1c9f9742d4bbbb6c9dec076b4b9c7ebec120c5740e04e3c62d0c786af006a303, + 0x18d9f9aee0ce3ea08d9164a5473ac114ae755c25b4f9566aee1c90d0a06e7029, + 0x22476bc02607cc745322595d63b98eb70db2782762e548e023837c9fb06021ac, + 0x22d83381d8f8800abdb2cced36e1c1d1c2f552594bfd9990abe06d0757eacae2, + 0x16382c1df41e7d0a3a4958656a42e3f1f314b21ff463c5f959b51d1a6c40118c, + 0x9e76815d09daa33a324f5d1d2404b3ee419b8e9b8833db59110c8d38f1373cf, + 0x1b0d5ae4cde6fed3fdef9312557d22f7da589e71e8712ba7d2986b4bdda6206d, + 0x2940f972586e13b6af08d49b838fbcdf24fb2a8a03f069ba612b0535ef94bf6e, + 0x19edcab2af3f18321eacf5fc4f3a933383d26aa37b1e3049d3c36c11c25f60e5, + 0x2deca7587b2175d50de4645fb5601b2599f5eb15ffdca763f0a24dd1dd4e735d, + 0x1f816bee20400357b01555222cbab8bdb2b5a6ff8aadc19f911042092e96a26a, + 0x2e950640b9cb8d14e70f81b06a9dbd4f5e01b81c448cedf2c2ea0b753d550e9e, + 0x6797a59fb805d4ccc041166d71d077763b50b1fac685126c84402f02f565179, + 0xad20de820c01db5e4c800abd15e3239b53a390d4a4a60348efc2dec244f81d8, + 0x174a6b87cea8f7dc3a7aea08317bcde182eb2aa39c927d46bb9b0dcd70954da3, + 0x2cdb547394356c92605c7b43aba9aeed3ec33a6ad515e55d8df4e678487186df, + 0x2d001f86169c7feec284389e39745c1a64345f978bdefa862e8c73f7fe610d98, + 0x2e40bd1d9e8c6b483f91eeea0e7f4f210aa786503d225e1fcf41166735737b44, + 0x149aa5d1015e9f2c509e36e547de312d41fa3d5d4a8062b05aacda70ea3923ce, + 0x284295e910196398945ebc9090400de8e5c509dd18ab3f4743a5eb521bda7d66, + 0x1a1f21bdf16296101dbcba94854f7c4b05d206a1d08b8796e6830077ddf99070, + 0x257f8d5e69aeed2ff7e194f398daf84d053941bfc75fea450fbca498389b2218, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0x215c6089e0a9a6256c901e33e306ac9c415abc1875a49add4de6d0429fde8234, + 0x2cbbb480fa68f33316f0d301f3cbcaa7eaea71e2784a0fabdccff2aeba9f718a, + 0x143619ab2212d1911a586be0f6acb6b8381e47b5a3e34b91eed83ff54937a34d, + 0x2385e3c9ae95a0459e974d29cf0e35f283144cb2ba13aa914b4e17ae5c988557, + 0x2bbe7e909fde4390a7cd944e0f309103447e91f3fad40b752733063fcea07054, + 0x24303758e4ea42a45a0419d88e426c95c68ca5811974c5b0c3abadd9c29d2b5, + 0x260bb40c5f1b22fb87dedda1706c608f78fde0e5b9735ad1fde63459244d4674, + 0x21f27302db4f5b28fe8845806f38ff1f0a04e28434a3e0043bcb57e65f6f75fc, + 0x16c95bed15dfc954a1a4ba25327ee14c5b0dcf76fd8dcc529027230e9c4a0d97, + 0x20996392773e30c8e64d792b010907d8848f28f691e8b2de13ea8226baea34d8, + 0xe20275c14333df445b794b515bd07b8bf90bd8035cf43cfd845976af63519a0, + 0x16422819af615c4a947afa3e272275b5d5bcd75d494042bdc81d84cec30f7f1a, + 0x16329eed1887886307c5a94706efe31795136ede8e9511bc42c77ffbdf22276f, + 0x1e9f59aa3535d598e32de9a4a370c6f4e5f8e6090a9efb2181560fea28519269, + 0x303df7dae20bb862e852232d75fb4f6468ab85a1d36472c3dcf567cbb233dbe, + 0x103c4294a67544648daeda2ec0a2bf81ec40e4c01d75d35be0a04fec32907b03, + 0xd9fb810fe920a795ae2c3dc1b9bac0ec25aa7df2e3628241ace688bbf78fa7a, + 0x235f2eded2c0024a03e1f050c1a32820b3c33f03445a830bd06bedc4654bd320, + 0x27fe4a10ee48d2ced432a47a2a6dd4083e4fdb9d9cf44ce4889b9c7d581ba529, + 0x5c97d4fec77f242636ebf0933f378eeb74467faab3477d6b8230966db1e9e56, + 0x17b0b7d570dc76bdbf3cf5d3def37e0a005c9b4e0b39803490c012b453ed60b7, + 0x4013b73ca35eb02837465c016ae8bd13994c335fa05de42835003ac53ce46c1, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0x4ed491d2af18388da53711df4d29318125bdaec68f9134c1b3f5e3bd7b831b9, + 0x16e1f43d878d2cfc40e58b5e77386d360cd3937828d8630ac2e736de89b0d118, + 0x45f7d97cd4d95f8e4e65c183869d4c15d354db95e5334ea1a5f3a0c34ad3bbb, + 0x242af80de0ae9607f5aad4250667e1cd450995afaa5293ceb1f184cc97ef25e2, + 0x2d149e6319f8dfea1e2c1893f5afd8325013eb9fe57e79b3655d626e748d931d, + 0x78a606fb0fae37d1e1a6fe99977001472cb272a670901f0da8e5126b3ef0899, + 0x1548a537c3810897af4f919f5e48b512eb727f3c47c53cd3ffcd5e3a559640df, + 0x1e3e9d29194598291365b7b7deff55f05a137b343cdb74c00037051b96cdc202, + 0x2ae46fd5b2a10a6908761a50c2f71e5f944abf11b568e0a070fb4a4cde0e9d74, + 0x1d5dbbfd82c2f3704059a5e3bf3db7b7f4dcfe27bde2786ea26063cd0921cd0a, + 0x221089932e5ffb0d72b8d896bb8243ce3d6adebcf7bae4ee56967e2b34a63946, + 0x2a5ba9e0c62d377751d13b5fcf5d8e7ba1087e74cf277212405440b3a8fa55ab, + 0x1ed96d07a94876906d0828524563f987414b2a45b4891092481659e053c7294c, + 0x1619ca922cd3654f97cba5f102327d7d6a0695bb3af22e94e33607f545c24641, + 0x93f881501a90112f530fd9185176fd85475f3427ec133cb5bccc6f277a16adb, + 0x2417824b008ac5a7e819ea42ac2e1bf2becb58661528bdc20ef63cea2e355a7d, + 0x1efb091123948573d0c0e6b95a628a617567971c5807c5d3e08bf566a3dc874a, + 0x1f2fc25f030934b6115600b1453820c4c70f8b454da461bc03cf773d033c0fe4, + 0x263a77c0aa2edd316947006fbbf4b3cebf660809da89166c7041c52169764b61, + 0x15d37f58a9589edadb9923907f947842ef6fb4b61251f8373b973dd422a1b940, + 0x76d6d847fcb997548c2b12beaa6a39876569f53e881ce861d85d9c41ce40820, + 0x1e220162696cbe1575cc2f4dd2fed5117c116d52a9965b434ddd7913272c5c6, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0x12eedc290453cd77c01e543e57d4d7ae0f6e7a76b576e880e852ea8b8e98bdc6, + 0xbdc3d78a5d0f3a92fd690b227d948ae6ca94d4342ece41593514efad7086439, + 0x2207296649856f043e2d7158f68f5b758b354cd022cfc04e811e1bbb4d3468d0, + 0x21430ade4c0144f819a79b2b6f849a968fb758f76a30f3e20b5f7999110f35f9, + 0x1a70bdca6f11701536dbe4d9926b6bea87a08f6f0efa754b1132dd4e123f7c0b, + 0x285d8e90abc1496915dfdb9e2a4c4d8c42126a3f15f4bcc1d8dc721fd813fae, + 0xe57676068d4b4e3a856f2cb7b22531f5e51bf1c6f09e35a645aa8953bc45ede, + 0x1053abdbffbfcdaabe5b794ee6bef5dfa367d198e7644962afc90f37590c025e, + 0x11660d7d44db731012b02f55c5a19e4b1a10041e0085aff26ff088797f54a057, + 0x2bbee9db0a412ba731979594cea45cdea2a1ea40c90bea1f3ace29d4df767920, + 0x119c59a67e312da970edca383f4e1cc1752e7fec6bde83e437acd6136e4dd63c, + 0x2a861198a0bdb354abc6d273b4f13854cd31d745e627c21ea107620242a8d233, + 0x1a8ac82f57894230abc7f3d010003d5914170d820095f3bbd01e977142351f12, + 0x3548b5e02d4f1f988144421ba37cf75fa0963b14c2ac961ac494828c1e655d0, + 0x2cfe3bafce8aea2bcb3c145ae29dedeb9ec7123b4f3295bfa5d05681c366709, + 0x274f38fbc034b51b94982df30832c69961d65637f808541c50a395c8e0dcd32f, + 0x1154c2e042ce659dfe447ef58e09e4514726945cc5abde427500fc5411a8a365, + 0x2b6203e305e19b7730ed2731f994303777fc1c2a52422d929ba6488c2c164c3, + 0x51917b944afa399ea1e621ee2ad62ea629a35d29387be06c077b79b9569e2aa, + 0x7cf3b4f4f274f711a4bba652eae5fcf6c950fcdaf92e77c118dddfb738d9ba7, + 0x1184568d03c28368300bf5724d6958355470e629221f5221676f69e22b717352, + 0x1857839c2d8b0d6d08c21279cb8a2cfe6138df1eaf6649888cf540965ab3c168, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0x26518ee75c590976af8e213b42e5988a7185438e593c9635a28ee89c60bac357, + 0x23645455ddb929ee2b596cabbd5f40df59e219b4efd8c1fcd4fcb67ae42bb5b9, + 0x16d0126c2df72ad69f419c74741165bf6e9f6c2abbe95a022efc903b62d25ebd, + 0x195050200adcbdb5e72bd63ed3e1d4d3d54e4cffe5a5fecd932e9c5684021dde, + 0x23c26b8f07749697bf6982f2e715c91f541b173fa0a3e8dfcb6bca01499134ce, + 0xffacbd7cec2233ce5a4b911dbcc61f87d759ba6e46780179e75f91ae5a720e9, + 0x231a2beac360f4917f433d7ea9eaf185e270778902e6e090ee5e207fbd0575a3, + 0x208cee18da850a2625d1500f835a216ecce022c8b08235c387b8cb1865ed8a59, + 0x2df938f310cedf2df8530cc3ea5ef1254ed966674bc08ab3f1ea148057b6c9, + 0x5cc71f44f496cfe8d69850022a141852f7dac001fdecce67de6265b69dde3ef, + 0x1e04cf375796f4714e6b51552107036d16f71fd0b77e357b61a2014449ef845b, + 0x177060e5eea7e3b800aee099735b074d3bee92ac18918a1be042ad000f861c17, + 0x27f7183ac04ef3b5307e450873f5a4cbd1ff709677de1a3de89476a7562127fa, + 0x272c4143f3f48b711d9e78964d27fde0614c2844861b23c1ba5ef6321fe64877, + 0x17c29df44b208e4d5b70aa3b57c92d0c65e0c4d780793000ab5b3ce79e90ac48, + 0x8426585ef062b24b9c4de439e0dba038e9d539a54ae8c4fa6554924c0f6b03, + 0xafaddc71d356bb01e344c03336f6c97fcf6c0ed9822cff5114e85b7fb18f3c3, + 0x27de3d9113a625f578e74566a25e54bb1d311364887d455699d89e65379e11e5, + 0xe8ae5a0eca1465645dc6b31f66d8356d6fcf434daf1cfba59ab08a91417e81d, + 0x1e41011401e99e5e548f813eb6c091f1ed7d03c1005affd1984e0149a2e59836, + 0x2fdde0adafb47ce46bd4e5d31bb8e840e8b2edded884c6c0522a0a323b078403, + 0x6d047a14724da146ae1314d38a559303e53808f6ffa90af4f2db3c52d2946b2, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0x27e98739b0e44313ce32f7c5b552a0814abeb32da96cd82de769b4d0f5c94c25, + 0x96c0e16b0dbf141e6bcfdbc0e2f49d013f35cac3e4235db39c5cb35f96a5e83, + 0xa5a4adbd74977d24c7cee2d6421ee7cf5e0534388e5f9e09b811a0544d1ee3, + 0x17939f4a2fe98de1c4f37b079b35e28f9fd918492317fe59311ee844fc3e773, + 0x2fad1489f14f53e5380db86b119e1fc4ab02fa84ec4b0f283bc28cde6b738aa1, + 0x2765769537137039a892f1c38aeb083dc07de1b728a580fff63f9bcaaf455bc1, + 0x1e31bc0fe231bae89cdd1ee8c3df3d8b06da2f88825e635df9bc7ad5c128f2da, + 0x1e516c3b9ae36f836ab9824f1c10b86a622b2f49f081cd7a50ae5192d296eabd, + 0x47cc90a4be717883e0189e898fa7d9f1dc998f91d255553a394b6b798326043, + 0x1c56d70a6472d972e35698eacd7ba8d40c9fe9fc9b04927d06404ae10ba35f53, + 0x205c05088541f74e95a23f5c7ee1d9913978e98fa759b621d0d2e3b0d57c5807, + 0x16874f1578735735add0540440cb042a966b8ddf3e51b4d812c673776bbc47c9, + 0x240f602afd2d97888bf4b64b23d6e44cec734a2746cf4580c430f72e46feb453, + 0x1abe8b11e0bfa0a5829568b66934e5da83b778ecfa452ee2a6b7140e191e7b98, + 0xc276760c90c65c9f228140185e42f3a7806840c8825bce562d0766a06dacddc, + 0xab7dd18d0804d394424f2b9e37439eb4bf3324198c44e7acc78d2e595d7dddf, + 0x74abe46b34d1daba12f1e78e3cfbe69a30dcc2b090897c040564f023ef7b9e8, + 0x2f240ffafdd27616a2eac36181dd8e9d9ff82f62b54537c48d497609858280bd, + 0x1009c918f84e7180e4864c0e20912026c62699bd562ee5bb24a00fd69a30332e, + 0x9e29496159b70b34f9707a8de9ec2cad82369b2d16885e98bada319d69e4512, + 0x21afdfa37d1b9218daef0b7abbb26e4d623f8ee412934fe8ebca9d9fcc2c6672, + 0x1ba7bae9ba2546ab2fa904877151066a9c5cdd44107d8aa829ba8ea0610b18b3, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0x2048256f57c9c8c24337bbfbd097c2627dcc0c2ae00ff560c3e82d32a55a4d4a, + 0x882758c559a9a38ed60d1113da22600ac3de62a8cc88e904342dfbd81f58058, + 0x54f6c1185a58025ca382d00657cea60c9667682c060fb5f2fad74f3d070d5a8, + 0x18da33071f0ebc4b2962d4b061144009608aae89e8285a326c0ba8eb0c370153, + 0x27102a58751c96a0afc1846801937ece25f59ff76675758d5388cce403ab4af3, + 0x234028cc85b8345eda398be9f3fefbd6d59973ded29c6ee52fca866a07b1f7a8, + 0xc3762675631dd7b529256732681b5b48ba5fad34019a65b1ef191b9211bbcc5, + 0xdb907e69984fa1f803f9f19d603391ec580bb3dc8357d170e3d4dbd9c107e6e, + 0x1c5a1126b94c62d06a2b2ec580e5e4a165deaa7cd1bfb0872440de9606900dfe, + 0x2e3aa301ead4fdcb606e9aee72ba7a2cb90ddfd72162ad9478e94699f776f6c6, + 0x279d20b786fb6a7ac5d4fc5d78faf9c47a3090bd561b2fa430c5db64a552396, + 0xa951ccbe5d7d13404cce3fe60751477ce1088102dfa3732e323d055cf38340d, + 0x26a8d4b18704a5aa8e41ea652ce2f60e7975c0b7eb478abc55ba0ccbaf8149e9, + 0x787247335760468918257e7dbb38f97dfadb60256f603d51104f62e4e662953, + 0xb0a7b524cb7c7519436167aeb4b5b185d16c110c2b36f162abfca872b3f489b, + 0x1efceec837f27a592824f15644f3889165bb1bc56d5566179a951333b255398, + 0x2ffa74a07ef6aa2579a1f68f1de64b58eec51380c7dce9b8966c789b4777fe01, + 0x304582e03ea48dbf3043bbaf216ea5970d49e23aeae55b774ffc615ae80d1be3, + 0x1fede6f02a4595564cd768fd400cb5eaa28b2ba191240030e1d757d6a019537d, + 0x1e33187373750a7f284427194876c8ff05ee7aa94d5b3514f6083990d4ad0561, + 0x1c5a22361e914dfae231d634ad2c502b20e84feda4d506a1b7955128e9b24bb7, + 0x1310273c02734e60e3b1f4c7607a48961c3ab97ed9690c2b26c38e36cf56361b, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0x2eace5036bbf892b106d6ad25bf3acdc3c94834e60cd380a1815cc4620e79dcc, + 0x2cf399b03624f2fe3ddbf48c2fa326e788f3b6e4b4469ef0d3e6c0cc241b7ba9, + 0x22d41054830f4b29ce6882b49839e9942ae7a1ae84b6d366a98f42f7baf9e188, + 0x15ae7d83075b047fd367659fb588806f23b6be3b4690cfc3ca92c61e71f5c765, + 0x2825fd5f33d362703d2fc902578dab75ca7076ecbbf7cc916d4ed3dc43b3a0e6, + 0x12d12504ba541ca2b28129a673acf96d4f246e340574ffcdf24dbad99bd572cd, + 0x29653490a05368030d3690d4497e930fd4370b0c89d5996b75b420ec803189d6, + 0x21188ecfc9b8a96b6dcf99b67bdf3866314046229ec07c8767cc26ac6d2bc169, + 0x4ca521fed16e4c8271f4101514280093d189d84bb4129d2e54bbb1508b72908, + 0x27d867a046afbb0c3cd2eebda088e476752b08c462fa1a91effa16d22403e4a8, + 0x1e754e7744482f6d43e6990f631a35d9564f0485a116ab971d7c1ba0fc6ad629, + 0x1dff12c679a235887e6c896304b46e3833f216398da1338be75ddfba2d77bcec, + 0x1029ffd3ca881002e4f00872e7af3299d9ae979a0d9e0236d8bc4a6dc36dac09, + 0x2099a9d66b52f0ff88a110bf3247146dc2a39777bc01bae0ca27f3b3ba3f1f5b, + 0x212ed3e424ee90af48f2dfc1828a78e4c50fab366f51ce3fa716164c89787e85, + 0x3fe48adcb5e56246e6cc8968bc0a62eba94984a1472b01f5a4475628aa38cca, + 0x2d726e790f68ce53fee0841e1a8b8fe36b8a756b3a0444ea08af369ab6ff809e, + 0x168de57f2f5a7a31b7b9c96ccb8fb7b33fc545cc19452cc7a5342b70cff74ba8, + 0x1bcf256686de35f672d4e52cee81f74c552e08099b3ecb8c8e8348cd3f36f2e5, + 0x6f7d1f39f8bc8fa314984d88fe0283e64b452e260d4745f9514a012c31cc946, + 0x267158ac0a27dd2e94f422285ee979565877516c414630ca5911efee1a8e311, + 0xc4d16ebd4cb046bf8e0e7fe3218a3f23551c79e8388e65b1c7a557e2034f957, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0x22e7f291772140723c33a8ebfe15373f0468e295d1b724f6e94d522abfd5f535, + 0x2c5cfb9974cb2299069f8e21329d54e5ec4f6b837f1727daf66a21af858b56a8, + 0x27a1b5dc716f8f70f18e6eef36ca15ba5df295f9b6023d0c8b860ff0948ae9cd, + 0x1510814b5e9ea61f47e924bf9b21496b391e2efd97554b057bd9d6905eaf28f9, + 0x21ce0a7da429a54515927fcc1791f25c658766ce48934cc1937dea204f64996e, + 0x2e2617468ade83de353a5a7cf3ffb4aadad12b05bcb65cd570c7200059956b87, + 0x284052fe9e822298ea89afab784617fd413448012b8a713d8b8db7db9d111f, + 0x2f1299ecb664233c145d53e9ac62772c9f917ef5fd354f595fd151a739610f2, + 0x2a89d81e36b4e71698dd2968fe86c8bf4acbeaec381985f3a5e67a5ea1318d1f, + 0x1bd908426f44f80f02514742b4860a72c00ae90ded7aa472090e5c1062c3e764, + 0x1a43e9dac11dc11ac20f3cf1edc5eb8a25dab4389d675d9322237a05cfc6b95c, + 0x2692699c30d2cfceb23d589df2a5aed5a8219ba6c436d0d920033b2254ca6a28, + 0x28857f7da86b117cefcc105f4e504eff5f11dc71e1e3718d7ab027ef6383aba9, + 0xdb4febade50738b1ab87405bfd46d20cbd4a222a1f1f8627752cf1b9a76c6e3, + 0x18724360a40cc50d7046eab1f3ccd6ded2edafc5cb4cbffdb9bf734c1dff33a1, + 0x2187d4118b5f752636e205eb4982247b95dab037310349ddde471c782e60fb2d, + 0x709ba7ecd374680134ef58e9403582339e3a55166f7f3943f281c57a275e588, + 0x202fd3f05d2bd8e2dbcf6e44d3ee0db6cf72ed53b00b7f0785605d89d139ce0, + 0x9a760b6af4b4eed3ab69ecb0498a75fc71b815b6bde4a569d39b6086096898d, + 0x2218e6abd4e31c4e2c4e21dfc8a266e946c599fe44b9813f282ef3ac6d24ece1, + 0x3fce74af211c178898a2bbbde84568bc09b8c2228481f7ad87e7b1dcde6bf8b, + 0x2201d6ae9382dc02c5345b141db249c120b288860ec8f99d504eabe8e7f23573, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0x17b549a98305619700b722d1392e3f22f3515c947ca97bde2cd79a761dd9a7c, + 0x1321911b787b6c29f58b50a53d66c5f436848103f333aaeba5589e43db1208e0, + 0x9ba5765272979602f4c59c7d7ce1516f48137e61938e30460d262b22efe1fe2, + 0x1705b7f07f5aabec51703713714785de6f86c899d97f3d89ab53459801ad77e6, + 0x18ac4517cd9c3d9b13dd398e5ce614022042b3ccc82fc8bbabeae938af1e896a, + 0x2d2dcf4a755c21bb49b4028fb3dd8bfb641a08f00d045285c0ca64180234a26f, + 0x2420e764bc7ba63b706b6b39a10c092ade7b1873fc1ae1bcecb8374934383116, + 0x10eaafb36f88f19fdaa78ae39af01dd9dd5c3126eb87df41aa55ac344e440b2c, + 0x1adb582c6692385a8cefd33e6ed3c7f23a3252dbf4ce0ea80b2cb5d957844a53, + 0x17b3f1bf0717764c2f01570716b665e2ab308ec61b511dd3e65d6bfca9030a1b, + 0x27953c6c48de10d405e8225bbcc73ea9fbfdfcccaf0a3eda80ce4d7e5ec27214, + 0x15e794fec75f7c4f7e63dec570cffae247d8bbb1d0114270d44bd7ddb5ab3c80, + 0x40632b4454c59b282560f814afb01e9f60c4f24013cb1a8d450f2e23bce9d5f, + 0x1e9c0e04247d8e1f43b71350d991413eefb67c273a3ada726e15d81737717a6a, + 0x2f8dc731a366ddd2b76c0bd1418bc03b207d7065556f4796cb325b8dd1db30e, + 0x24463e539fa612ef3028038bdadfcdade3c8475e0637fa4b1dd3ce10b0aacbbc, + 0x28762b41feb35e6509ad33ea77bd88983e6fa85ca2f6738a1a1653d3bf54d52, + 0x247c44be326d67af902022444d80ea90776936a81592baa6702002b27d6b0737, + 0xa8ffb6524fac8a3820378ee0c9adb2345fea97112c2bdb9a57dd3b04be7f63f, + 0x264d334f14801fe44177ccf924d22e91f3d98e1cdf5c6388b735d60fa32c7000, + 0x1a96bd9bfc5432ea29a24ae3c46b126769d2d8f05cca70dbab11711117f2ed6f, + 0x16542734a0c4983f8b8203a8e67f1c2290f7de67a02b2e4285bf5d1c3049eb14, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0x46208656464d4ae0a420f4aebf63b775d2974ee08535ef11014d4400cca822c, + 0x15f6a9ef383741e16882272bbeb9ab135f295272ad7e45a26e063aaf656094ab, + 0x40a8985a8323dd3b2ad3c285159f2f158db48b9fdef72c8c859a462d7f117f9, + 0xb9b4c7ded97f1a7fbb1dbccb8fad09ada8183cfedb790e2f11c77074634a80e, + 0x10700446bc61701c9dd17bc4354ad727247a997ec9e541ee42d9d0d2acc376e4, + 0x98a404fdb1c37a38842752a31bb1d2bb5112fb422bab40a1b546b97c719d923, + 0x1843b850d5cef8871bfd1e31525996416a8550b748cc9fd13fe42aa1f7193bf6, + 0x279c28f81499a1d819fb67132c84220d124b668cc206dbdccefe9478358a97e, + 0x1d6fa109f9d33d9e144c5b25fd5b2f189273545fdadf88af3c4a7ef1f7189e35, + 0x1e89c2383d920c8a80837bcaabc2ae9060bba4a520fc7eaa7fa5dd3dfc18d5ec, + 0x180670edb0cc070ca05eaa724cafb4ed020561150ba343ac5877fd8585edcdb, + 0x44a14d1f731de503ecf2a6438ed17ff8a552a01d9fb66a36fbd08aee8a27a6b, + 0x1391644b83aba3c7c86a81f240efb147fe4c1c53e08ae3d3b0aa02fc1033b02, + 0x1a9373fa92867334ec17aedf833ef19fe6f67a68d031f7a088091730b2d5bc91, + 0x1c5c46a6852eefafee39b8f31935c3325f450000caddbb35538f8dfa02b3feb, + 0x185b3aa7a434a7225057c6bcc8e68180dd404e58e3f0a8733fe64a0c1d534102, + 0xb562eca994127ec94b90e76255955551cc1d6e8412918f9aaed138e19cb903d, + 0x1ab2db0ae479301dee234d231988298fd46bdcf3d1ad8cc11389ee780c0af1f4, + 0x2ec8c3feb4e03afb11402d5929fbc332b5bb7109fe326a5af8613dabe9a6a94, + 0x4dc3fb12329b17a70b760ae75d620133889283cbf88035505ffc97ce4641bc9, + 0x1297d2ec92df98f1ac1a318dc100557237dd9c4a96685f1d58d0fb61ffc4c094, + 0xa84c5d2f491a40654df4992df98f681f157bc9fb4a0a6ac1aad9e0e994cddf9, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0x1be6b03ffb55eaa0fcfa4ec007ad655c776ddcd62e7184dde03b1c90b1af001, + 0x2910d31a4ab9e0aca79eddd220c56905bcaa2dbd29b6d7bf389a4c50666219a3, + 0x2839abe3d67b01e69ced2af2ca20db9b2bf359230d7bf3c6bbb79232624a57f4, + 0x2d0c50609fd4832ac428bc6ed4606dc5e5cc48e9965c600c81325a8d4ef87ae7, + 0xa9180406884b203bb35bafbcf2f4abd0ffe90aa9e3e1a82ceaff556d2e22dcb, + 0xd5e3761475ba3a3d55133eb45a945042ee26b747e3eb42a077749f4f3676e4d, + 0x811919e5bf03ee004979e2164e244f1ec510eaf5fe6e5107e5e6f4bd123f77b, + 0x23d92b35fed4accbdc074695f6d1393c5c2bf6f2167fe239b2029d56579405b0, + 0x100576c563ad00ccd2b07afd817dd2f8dba2535b5c38de7bafd08691b04933e7, + 0x24cd184d143196317be3f594f8ea091f3442abcf3647c50be545e510994dd90a, + 0x128748993a58cefd65bafc84f486488896bcc8088006a3f7afacc28afd6fa380, + 0x126980393d9f697cfeca3c8cf5aa466cf7699c7b24ed1fe2bcdcb3d98e01eda, + 0x3d53b1b0659c95cef35a515696e13d67643790564a80ee3fbe3c5b2ff7dbb69, + 0xb1cbc1218a01ccaf22711fcaff805b05bffc45d21458e41527f06dbf423fb10, + 0x2d2b944d4f9dfd80472bab4f0ce520fca635f74c8b9f1e1ca0fd52ec8af49ee0, + 0x286ea70600778faee3383939faead69a24821fb400920778c7529a1b1c90f54e, + 0x1238e08378044550a836bcfb7129f0f0d6253eba654e96035de06513f6ee738d, + 0x20d38b283f1f0abbbd99af81d226cc6503ad86ea1a2ea8e9419ef15a74f8ad57, + 0x25f5d1c94a4423c994f81d1f5726c8133c5d2419fa58f226a94c09b61815c2cf, + 0x1ba4948c72f33685df0f9eb2f6678fa6bdde0ee261faab0a63917fdc30f0973c, + 0x2a306087a9453e96d0007ac70600c3f1e08b4fb5cef04232b64fe8c0598674cf, + 0x9e528bcade9d9b1e99ed53a6ca87dd8dc46140d57d0699a8f120e0c77af65bd, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0x2a779727d7ab06dbd553a840294589296f3aabb6a314afb5b083f650e39db967, + 0x11aa7127dce97c6f4beee5dbdde1d5c7de812e27376e249f41a52171c108324c, + 0x2e6df565cac73a4a04c2cb1fe541d9e3df002054622c790a6c8c778e484da06b, + 0x224c4dec007432ecea73e548cabf60846d0e6b72ed2f4c907dd9e03dcb381e92, + 0x2095194e2ecab4e0e731ec6e1cbb0aefb3bf646f6e6c804be5971167ebc58f76, + 0x2ef057063be57233d59137db76c7252f1d2cbf5f3c4c6c8ccb22203c98d6e2c7, + 0x15185ba1b9b8060768c5af0f70636dc62fc29ca5100d76fd4f9c4767e8f87fb4, + 0x1ba274d2184bfef2d0be986fc2d41617f43d29a30b328b6ce3fe41a406669532, + 0x27528f734c66543901cb1afad7414892ae14cdb75ed5fc59fedcfaa399fe74c0, + 0x1185229ce9c183d7dce8a64999623a469392ca6d2e4f72bc2b6c4772a6b04896, + 0xb36b20c33f83d20c1c49c00c65ba85deee8345f8563df448993a99bebbef6d6, + 0x1ee843386b3aa0c38471fe7c60b638218ef9266b542a9b1526deb8dc9aa3c559, + 0x107972f77e0382e5d3cff5b6858e85fe6ca29cfe95b60159a9dba68cf55ea21, + 0x2fc46021b9841db9dd3cde3ce58785eb5f5b9600c8d5c0f4086130cbfb261f5c, + 0x22b8c705b7b675b691343c7f19f68e23745e55aedf5eb931c37bd89563f14a8f, + 0x1db0aae1de8a581770c890de5e66c763301cc6d522ae042db366f330e87013cf, + 0x2b17c19b2ff64a3d9a5bd5cd0d4a21cae7b7d7c899228050f593b2da46652d3, + 0x1e3a4c2c9686927495d6cc3c6e90b519deff0b55ee3124d69ce5161c91119baa, + 0x384603dcc8e7748739a4f85462cee5fbc25345e02db231f40e50a851758452d, + 0xe842866ee1599809910ecde3d7ca9f1d867f96459985ba119b51066866224aa, + 0x19c09d8567e90a622516fd1973ce27ad5fcb66aba8b248d06de9ea306a6fb2c0, + 0x134176d3a40f1bcad9f536bb92b8aeb9a4c3d424b14cdec9beed77bffbe754cd, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0x1918c06693a26c41f0025c99e93ab46213ddac227215fbe5d1972dcdb6265afa, + 0x2c2d3ad00fcce75da6a5f510d5952918f446016a8fb4b1dc41af9321803468f2, + 0x18ff4731631733dd9f048503b481b9b7abd2ad7dde5a002d8e0ffc425f574c09, + 0xd14a3159cb458b4c5d65765b15c56653be2cde202d8b285f5c2cac7e01d57eb, + 0xaf7d40dbf6a9d2e138095f1499e6505c326422282f1bd30fe98d19590298e96, + 0x1f728b62200f84d56fd916f1033868066c5ff9eaf81726ac8f43f08f311bd806, + 0x2f1509a804a1e612847578f49ef3d4cf0067adf3c3575dbab3632f6e6e3dd5c, + 0x41c67e015b3770721ce4b96ae6219e6813ccffb152dbfa13fd37d25ba812f06, + 0xc336783fc41679f67e808e2eed1be9cda3fcee2b04394812df95f9febd467a2, + 0x1e34badeb3d92a88aa84decc7b70ea344c8852c9a17d3e0dcfcfd49f9d103548, + 0x2539fed64ca5f8bbd4016404921a292c7652ee3a7fba314d675e02ef29f01095, + 0xa83942d60d14f46c3c9cdaa90390faccc4fcd2e9c3ec8cc06604cd51ac820d6, + 0x2724f8dfd70e0094d613f65f6b48d42e22a961d06f589ca1a64b74e0ba9af8a5, + 0x226e101fcd7f365ac33c608817ee6a4c143504927affab95f4d7f95da55983c5, + 0x295d81ade71715f0c9071986b3771fa8621bf634006463df3b53dee9bf37b189, + 0x14aaf0e78ca5884fbdd6282dc2a2008a1b6165adffa6e9160a9e36190eb81afb, + 0x2652e6b66e323877eacdc4e0f32dc9f72d692ae7501d7fed6c96154529f45a39, + 0xfaa22bf6ee7ed51ebb087c35bd33ed34bd4474073349a80e9c9654883091a95, + 0x12bd1d8d922cb20e1d0e02d066b120f26a1979f4374bf0fae43cdcc0e5a366f3, + 0x158c1a5307ed0d18b58986c274968b23e404084a78aba5687e2e2c4f009606e6, + 0x28b5ba99540925c874c6b815bd7303dfbf774c5e1012ef2b305ca47559f597b3, + 0x2b845d95e442fcc4bb8a49be773609957b578e19ee28baa880226e3f911d26ef, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0x1b66e79c663bec66bf23b5cbbcbe9bac308c47817c3f242d3f66b6d565be3b9b, + 0x79f775f411c9c90149e59e6a34d6f6f47947db4337d9d3c18bc4b51d4cad270, + 0x3009d6cbb50dc688b7404cf82d589fbad43d0742333927bc049e48da6913e606, + 0x1fc70661054fdb2111e49907222387ad311058d73c0befd6314478175e356942, + 0x1ee04e8ba0265fce330585518894029b62d9bd50c9d0a6f87f1280e82859e9fe, + 0x644f526b432da58421456fd00e0e29291e8d0df2ed27626c42d503c62e4fc9, + 0x27e99dd0f8fe2ca6883ea897815b333de616c56c483c0c9e45283067dff3c4b8, + 0x581ac976cadd2b1dfc14d8b3cc604f1e8e79dcfef24b8f67032c18b90c17e9c, + 0x6750f648570d1eea536bc3842e8a9673cc564c9784e57793475bcdb399457fd, + 0x15822b758ce9dd864fa21222839e7eea4132d1b800819ea095a6465d9ce6044f, + 0xd9ee290eeb8ccad8fc7bd054d7e10ff3eb0e3615f770151fe6a276d53da7738, + 0x2aff79aa26d195d6001c0805b35a8c05a08b59a0e819c7689f176ab29deb33fe, + 0x237fa4d9fa2fa84b58ea68d75927afee778a5e476073a9b30d6328ad62f2d807, + 0x5d20936e308b6eb8373a899e602831ae0cb091abea22cf044de6f0cbfe6723c, + 0x20470a9f2d2a3cad5d2f92c333444b429333625d0e07e064fde8454fbee764af, + 0x2e5ee062393b836f391171b5c738e5d731de49e833031ce97055486def2d6a1b, + 0x15066a745e56deeb113b9dfa9e92ec1fc4003f8dacebb4f2f0a591e9491a96fc, + 0x15af3f3747ee7d63738b4b137be08c44f0c90448307d1d2d97788fdcaf30238a, + 0xa9db2ebd67bcfd0c5c2e2baf93fa206537a0be5e295da9334c19515018d4dec, + 0x9d819663eeedf9ce5b97d71abcaa195f6ac0ffca2e4a99d89510bd29da37cc8, + 0x43e45a7ab55e8ed770c8bb140c5cf98a079f0a286c76abd11486adec2b9a69a, + 0x267390f339be917c18588ec7f9b53eddda42bbad0e44351d1cd46421389b06d7, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0xdd2adfb2aa3b4128b087b5250d5e754672ef02ca8495a5b8f9c2e51d12fe27f, + 0xe44bb76a256740fe47a818596b6dcf40b9db85c744d3701bfb808a00f7ccbe1, + 0x68a25d2e27da4305caea7b47ed35d9712720f654d72d094e4d9b3796ce88a27, + 0xa6624b2e2d3551843723976c9168b1acd3ff196804a6cfe61555ed0048c3554, + 0x2830c3937da98493bda628849823e656aea96f309f417ee6a4907009a4957fe3, + 0x1dbfab542ad1a8d1b064c18f2da82b6e5320e8285d33d524229aed44da0fcfcf, + 0x12f049967453bf43dacf198aaac17d184f44850bf49820b37f36df953e57b08b, + 0x2ff0b4f794179f6cd4d0431d7aeca0e320270aa3b0e3f63d832f1830ced770f3, + 0x287045969073b1ba8007b65f351ee152d9bbb0e68c75fcf8a3a3e0dc9cb9935d, + 0x88750a390f67a5b19a63ee69e6055949015e796d41a2150f8b83f58c1086b4e, + 0x2a1b684b9357c3b9b675c9a56d3690d3b101ff4c50d5b7f97d68d6a247ad6e3f, + 0x924a953beb10fdabf6088068bc42d18c47a292d33fb12b1dd11c0942051a5f6, + 0x5fb81ee2e1ac5e198c62ea767270d3b52af1e24d4d6857f82c2ef4b94f39740, + 0x1afe1a783a2d68ce8f79cacb2bc57502c6c5ec9ac0bbe35f55b34bd4d944e15a, + 0x128e66b9d177d588af9f9a10ebd195f03030cb2806560ccec1c0469ece8ab9b9, + 0x2a89bbfccffb647312f31a2b0b68d731f65279273447021b716f8d7d1b9eddbf, + 0x2d2c1cc8346008effbe81b219d8dbec37bbf2a6f6dfeeac3b979b761663404ed, + 0x2a10df4948ebb56a6d1edf6b2d7bc7d7bc3b3a6085565a90bccaf53739093eb6, + 0x29f0a91579b0418cddeb5fe403d13c929178124713655833284ce4386673625d, + 0x2d60032c705ab2c8e457ee0d225acb206a5cabbd75b088d97656de6df83db165, + 0x1adc61e3889546408f21d1e1cd9533415a7cc177598464799da86e31778ea854, + 0x15d24ec281355e28a085dd996ea0c90aac7efb5d87f9bd70a2a6b9db6b50b7ba, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0x1be40669c4305af08dd9cfeb05bc7fcfa40b998bc74ffe11302c4f5b0553a38b, + 0xde0e333621fcd0fb11e36805f9722b7d5b53bc39cec2c63a02ff853f30c04fa, + 0x20f0930ce2a982f6372e84ab5310be3beae1b0b7f90b8e562c26c2e757702d47, + 0x299a425dac7d3a4c877808a7459597fda5984c422b6a994d81e195f30385f8dc, + 0x2f3b6c085ecf99a58b7507dde8971a225c511bd6f802ee3a6cacc0530e8a33d2, + 0x1dbfd1be6281a5c77b4fb2c7dc937a25dece301dd371ff67769ec907ff76c72, + 0x2057718828a717820912bf7aabe85d74d0e759d3357db223cfa111b82ef48f32, + 0x2634e710d328db82ab3d5c000a6e16e4cab4cf0b5c10975bf684488df5d7767, + 0x1508d73e31efd2a02b601a7151ca176fc79f3721fa686f737d66b4a43c1597d3, + 0xab1c757a2930fe704ad42fd54b19104397077d5e52947a92f810b0ef5d87871, + 0x9da497dd64c5e3273900635d09193df06c1d2426a0fd73d7dddc99c18daddf2, + 0x2381572e35bbe9d3fbdb3bb1f1963bdccc535817b1d3c077e51d7fa9cd9a6cab, + 0x1435a49f928494a49e2a67e4028810e23b7f26843d1e22e2d737b40f01da11ac, + 0xa41cdb54589156aab59180023dd35374103e5a4bbe746ed8f2fc3ddb26f8e25, + 0x14c484fdbe36491934a1eda09b63b86d803e7059cd8e3314e8d774b7910a7cfc, + 0x2a77a4002da2b4e2ab43232ac86e8fab1586b84ef60705d4f5aef26aa5421749, + 0xf63b8eebf3c4535bda0b094c007bec3bf0ebb888ceeb957858bfd41e3b33a49, + 0x1277d3fe5619089508669b1a53372f2f10ea0acfd07e684219b7526be3566d69, + 0x242bed90744413a413be2f93566487aecf7ed35f2f6886e79b95fced93648d2f, + 0x2f421f7536d6fe02069b4a2be1adef885983ef7ff87af5bdbb73904f96cc7044, + 0xdcb8d37d53a5df0f9ff37d9f8e111e005d70c93bc23557f6041711a167e62a4, + 0x2b8d52018de42ae27a896a6100b02cbb428bcef7fc95c21e0631a0edd273ecf8, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0x20ffc046123c9e7c161ec2fc0033671938b1bdbbb51504bb48a6bb7691f867c4, + 0x37fff4149f4439e438ce162d27ada4858d0292fdd5cba6ad88b72e73e552b2d, + 0x1de8c8e615fa608fe89f596053f7f2aa3b21158cf1116eb6bf12e98bdc5cd339, + 0xbe3251cdac6825fe72f5f701c19215869c21db3e146faec1b7d83e291deea6e, + 0x25cc68e0156fb406fe6a1d01bf926214705937bbb2dd5af7d2feb70cda04b273, + 0x1e6d41a49f875455a20e395c2f5466ac44d906c5b77e21cab176934d6ec92fc5, + 0x2e67c91faaf0d61303858bdce074a2f61220d62977a4d6963640808413273f31, + 0xd12fb42faa45cee5774d38145639dc1393ec43ceec5d54b8d81f8ce3d74cb49, + 0x23e70a4146133f0a77a4e1d743720692125531e4b83edaf6cac156afc870df9c, + 0x2df6f710ec27c2d652198613afc234f4c6d65ce1cf6b5488b3984e0976f75cb6, + 0x195ce59e69ed9141b51479ba07aebb50eda0d40c16335c1dc3371581b006b9d8, + 0x210f8fd97f1707c4ff9610daf5bece6fd2a7e0b4c61801662ba3aa177decc92c, + 0x25f1b7680e11f44ff74657d2d3bd43aab044798def28b435e75686606d12aa67, + 0xb2c75ac5a5fb6d2b4fd51256d3aa84daf97cd4611e54b1ce9aec26e298bbf88, + 0x78398cda47317311211740262c08710b86d61c54ae55636a4d15220da5b85e4, + 0x166af5abc6ac2210fc2e48e17a3426b597bdcaf849cfb535d3a4a83a16fabd84, + 0x27194ca79ac4773ec964accb35e09bfaf60f65fec69f6c53a45ab6a7720410d6, + 0x10c46d3c254d57f49a985c74732f27a402232da4419eee8d59c39fe0d25674ff, + 0x1621881967985ae3b969ef554ded7e95027c80a3fd24ac8233b7204c46b67b15, + 0x28e893994343597be2f4993da693ab68a1b6530fa187e0708e6dddd65e19f65d, + 0x5b240574850357b93cf99c2a4fa39529f34cd568be5b51fd6bbac19d66a13ce, + 0x2a3e91c0f5583245a4519e6d5fd37530ea97eabdcd9e0d2655ac4709a88e6b58, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0xbc9156ea781bb2f4a48a6971a1463c341447af7640c0dca22fee678aaafa67f, + 0x216532d67a620605bc236aa3d9967bba132c18ed4dc9fb1c7d0b6e414b69ed68, + 0x22ddb91daa4a4545901d12772b1442f5ba4e85eee6a77637fc31bf513fb116ed, + 0x2683cdb3a1a277aef9c2b9cc42d9835ac8731f42ee8c1d97c91843e330cc797e, + 0x2be49377140f55de27dd9605e7ae0438bea87e1027be1ccbd27547bb1882a71e, + 0x3aca5d3892e4e23a82e32970ae06cf7944979744108cd4014495820f3f3cafb, + 0x67c57ee42c925a4fd7f0b70805e871b1dea5c0c64eecf286f01a7f82496d0e, + 0xae7cee32928e8bb4b2e5428f6ed56733a955dbb415961e58bda4537603370eb, + 0x270c6be726a888900c325fce8361fee0766b4178288e29892e43ac4bc5a7a53b, + 0x2dc8ef31b5b489de3a0218cca5215bcd23860891d4be8eae01bd6b6a9fd89e0e, + 0x19643edd20d71982a49a09cb1e0db7d981d928413f5aed74a20b339a45cb3a1a, + 0xcac86cfd70c7bd0f964e2186efa830356866dad5402655391b164da07230607, + 0x1e28a98366dc2b5a1dd651c8cc239f7d6a65784260e4f99d5f22d3acbf089df3, + 0x65e579467ee3caf9abf6427ee70e3f04350efd4f240a721ecd614bf510a6d15, + 0x625a0ed5662a51dd09f1b361ee979a3d90999de6544dd012e0a3d0ca7f54290, + 0x14ca160eca3dcf16f63e65745c1fc7da76bd228af16cf74d2a322a02c2e63e9a, + 0x174e5a80b5654227609644c29b2ae1f7346475075b95bcf09781b29dca6da8b5, + 0x159f373903a0a9fa1b30f1e77887b7f4a13c034eee827f0bdce9efc244d50300, + 0x1e6a451f0965435e18b8c68ed523a5f5700731fee946b446a4a56d697a65e136, + 0x292002d89878ccb5914c5d7951b45952eb8a48c0d4b8ca78af9db15c0fffd2b0, + 0xcc6c8b2dc526673c038b258a850a754ad3da11b01690ed359b1073e37ace2ba, + 0x2abfd63285e9ac80fb865ff2fda5da230f278f9020001f8172727bd6f257059a, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0x2854b5984bd6b9e733809dfce1d7fe5ba63fa8d58d57e4cd9f540c2368db0dd3, + 0x2e88865414f2b4557548e383c7f525f471c9fe0d8d64f0b8001e630ea88ae41e, + 0x23790eec3f5a240f8398eca3719dd949c4e1b4c483a16aeb268afaebdda79a0e, + 0x2fcc8669dfcf04fa06c75b022b77b84d090df3b822dbbaad1fb8e3ee948e86ee, + 0x67fef650a45711037a1f204eac29045803fa922ccf8ad518334c03a29178838, + 0x248f8c46bb3f0bd3aaf83f0c410c0e56d9dec620820ae91d41c03c288c0d998d, + 0xd3b6a0004a85b63a85061b171d87480cb262b1fe4ccdb71be2114f4a8b13fa0, + 0x7b065a9ccab6b970669bc32838db4c48147f0661f53929f561a7a835fb9d567, + 0xe02b6d12d48362677df07056afc1bf5eee55cdeea65044de0648a0c7c0a7894, + 0x2fab90c9d26772010fe914e4b88a71e32f5563f4d4a138855f7ab4247252b84e, + 0x1989c2e54741cdcb6cd94407dc6ed84e7817384af807ba6ef8b85d4bcd313c5d, + 0x28de889080866bde3f19d84b253477607071c34e59569f2fb0aa180b44df1418, + 0x2804b79f457cbb808d034036efba0011bd3ab0419c39b094a7341eed26a322e4, + 0x24eb9b802012e11386b4ed5ac52da70957cefac5d3911ec1f042917e479bfa80, + 0x1666ca210112c32bb19b256acbacc96f58cc0fb7dd93874d50021fbc631b80c9, + 0x20799de358137dbfbc623c6e4acadc25845bd214d4073f52b8024ca43d99cd34, + 0x1bc10c44525f82f98f44fe8951d669c8bd1087ec8fb25d08c5da11ef1117e052, + 0x1d8dd037d73544d78d4811ce0d6b48264449172217cfcf67186eee425e18cbd8, + 0x2fbb2fcd6bbca136c183d5f94582c61f194aab068f915bfe0d85cc5d4b82bc08, + 0x1eeaaa5f7e1834a19655d80bf2daa1d2cf50d73d18e1973e6a74c487030474e2, + 0x1f7eb06d961fede066bfc2773ce8f36dd7aa35a727a60780719f0b9a627f56fe, + 0x2981fa5e6672d977bb169d70e070e73ab9d7c3f20950b3242e9295b45390f46f, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0x28776c75f54ae00f3190d1e711194bc03ff39d248d96027523b166f942920a86, + 0xa4ab73336b833957012f0e7bcc36899849b2db78f8fd707b692578e14b80328, + 0x21ebae99beab3aff541833d68c75fe506d857d8919a97e07e3902b919d3e143b, + 0x3029aa9bc55b8d1ae128f45ba368cfb20896feeabf39b966d0c12742bbd28bd7, + 0x239128973757a7e9c8d29d5336d1a53b277387b48afa946628f45d03eba49de, + 0x10a0435f8e32fcd6cd5d8ceb3a3c078227b5cbb69966a76d7f1d751e594479d6, + 0x2f5d49c2ab9c95d09cb160a6ddf47a0763fe11fc3504478e45d1d07e641ab29a, + 0x1181af9db194b4bdd65f61e51a4f7d562307f5745522e265198b320ae649556c, + 0x1b9d2c4a0df2bc6d9d56c76317180d89b9660b0e3ac54e2e7ee83868ac39a621, + 0x1f5c2501487912b1ef65f072a108f1e6cd640b1eeb0dc7dc0d579032000b8570, + 0x72c3f6dc95aebfeabd7b79bff8d0073670c5fca43b5b067caa4828e67bfee02, + 0x2328cc21742ae15efdbbba3067e95d0134f49ca25303ae9872315e29eaaf3d1e, + 0x1a2d67aba6dedc8f6838af4f2318ef7575a0de251cd8bd4b9944c0a96d703b20, + 0x2eaf6ca068bbcffdf36dbd475ae928d10a2055dc10da29f77ccff5204c506876, + 0x233188598d95df9ea9c86b38db0027051e6a4bbf4bf27711ed16489783187d5a, + 0x7b462ddad87175e51fe8bad7cb756973ce7763ea732b3f64dfa38a0a0cbde51, + 0x14bbd08ca052562716a460cd30d0c3d20a21db0742da1e4021feaac3a8da738c, + 0x17bab12d3266540f45d4ee8beb4e4f01267e296fc291ed54d0f4181a87e0a53a, + 0x2a168a263170030f88743436b706dfe82da391914f492e7c48a2f62d56cc9d40, + 0x233927efe170a047d3d309380bcdd2d2c7bba7541dac277c6cfcf3d1bb16571d, + 0x10b9e5f24f1f4ef89886d8ad3f571f8f3e8633eb6a3ce7a00551d123a1de0548, + 0x2767b7f7b872770da90c9b9fa57bbcd766b878f7bf6db0a1249ef4dab08c56d8, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0xded85a7aa57678558da049aadb3f84b88357510e6424702731b6f39e9824eb5, + 0x66bffbba5403655a7eff0286ea82797fb1b78ad448612d5e5ffdd513979fe8d, + 0x2be44851213461736ad1c62746a446b9b9ea157f592c1d54f3bdbca0e81b1d28, + 0x13c7aff223c351a0136cd825f10e41da937896c3eb153e712cabbdc0dafd01a9, + 0x1e1295fede0148bb32d784c659938de19d63cd8f070b793f4af6987d4b0a2ca1, + 0x108e731bd672ffd58f3bfb3d66c3281da9a79214ff667756c3193331f15ec2ca, + 0x28ee2087caa404a7b9c88d871ea969073c05aa2d7f8c8afaa372fbbd29fec908, + 0x1929e70c3df9677a16e6bc3ca6c8f45435f1781bc7d3fab5c2d9f21836bca492, + 0xb328f15c14da87621bf2b7b1482557b0e1e4b62ed771ef0b5c0dc2839391a9b, + 0x2463924e854fc278f78d41ac3ba4c82e9ae33933c1f673d8fb988f5257ea48cb, + 0x206b2c50fbd93e4ab16f20b5e1dd4e31b40b410bbba02146d1a7e7120a0bde78, + 0x22a8169f4dc83f66b725c9db0aeaf6944c49f7f59e084741b74dc75f17a2d582, + 0x131beaf6c38d2a148c91b01285e728d83c5b40309f89f2ee1d69ccac916cf9cd, + 0x1f2f76bc23a46c9ed5441b8e0e91058e2eb16165ae943eba8b61f7629f38708e, + 0x350963d2c0aa84941005b7fc8747fc61365ae03a600af938753c62384223d64, + 0x1f43a719acb173edf3cef4ff57b3e3b54434997e03bca2ac3164d6d206298ce3, + 0x2ff2c8be1964373563d96804dcba6db4f2004109e4d73abe431271981c9c8004, + 0xc8aa745ddf7f419258d9f829ce7abbde1f5be1343ff89d90a597b8101cf3317, + 0x8ec029d60cddffc7b81dc89586a6afc233826c1641ccad7dce7da7a0d552002, + 0xaf6f27d2211b12aee10a405ba1959fba32e4da7012c94dfa822b683857685e1, + 0x23cc9f4ca99d30fe0d7780397d7281775e7359c3be70471bc6482193ca3b318c, + 0x5de7e88f631488d23cddebbab25e128f8cdfb524acbbfeaa7d2d0bf47c2e7f3, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0x2ef97e821dcfca90bccc266cd3b7cfe86037c961414b970511a845251204cdf9, + 0x1e74c0e015eedebe75a4d569561ce744107d8f4f5406e65685a60f97c00c0c77, + 0xb9e7e57a6287f13cbf8760fcbd1bfb988e1dea2f70bb4352fe9acfc560d3a4a, + 0x1daceec3e24e703f54a27a8804d960d841af5a0a10b4ed8f2d5aca46b61ebdb4, + 0x14add4559507a7ff29e4e915a30bcbc79787408a6cc31c071199e81f03ed1b12, + 0x214af846405e33b9747a25b176edcd7c1934c101d36a2abb81c958a8be7c06d7, + 0x8f62c1e4c1e9fb62f1ffa5b262df316e32b769414445444c4e345b6e6a8e3d1, + 0x281cfbcfd9fe3fba3329b1e3d6da6ac72e3d401483efa9946cab0ab530342c59, + 0xc4930b204d10bf30ac793f21dd5cf84cf084aff28fbea40474f34056c4b81b8, + 0x75717917a0d4e210ed37f81df652af88c78224d99d13d46dad5a3d040907c65, + 0x10236e639476d565e1de655b0f816e859b5b3b38897ffea9ccdc9d95580dd0fa, + 0x16535568d792d43083a2c8a155e09645cb214c088e40b70589a610675f2b9bdf, + 0x209b82d2cbe5617f7cf4b7ca05f0bb1dd80dc2a652b50a23e68de856334edd78, + 0x10d0843c37e9ffcc0692fe6018d480df45f96e2ad41bf9539197ebb12ae5dcb5, + 0x175f7935e1d6d289b963b039c85cb1a3ffcba2f681cb27a6364566acf5ff2d1b, + 0x12f9631f7d9cba5b34733142a23a76a4e9bd76fc838bbb865a72aec17a3ba09e, + 0xa27aaf6ad1953f49c5240425b509144c9998735a59e27906e98518f7bcbcdf6, + 0x339c108d3ddd07caeedccf45ba3a1729cec3387338d45fb0b7b896faf618118, + 0x1c7eb764b1b6372c8a7f18549edb2dec9e713ec618365f169f0633181ed21da1, + 0x2d06b5cc446ac8715cd21b1c8889728aab4d3b5e7f4eed7faef3530fe3766440, + 0x183445f90535b07b08b20073ba06950f500eff3d0962ef609a221fc0df504b0b, + 0xe05fc0656468b85eab718ee19bcd04d0154edc633843570adc6e7d10592445b, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0x6941082d94398eebb54a701966a9cc45b303a0989725381645fbd0ff97d9d66, + 0x22ea9d22606530112502f8e40f9277e1a334e8eeb307a03e3924ab8c6701f186, + 0x16ce67e884bfd1782872fcd65b18b3f27af8c1edfc8ddefcda53f3669651df33, + 0x11fc35853f485f0ae0902c650b9749b481e336c553fdd90f9767d8bfd52c63a9, + 0xf04c0f3525c56f533b23a4dd4deeb7b31938dfb1531863ef1c2066e8758dde0, + 0x2e15668ff3beca65235e7912fed8b7ccad0928136db06090fb6938ace207f363, + 0x2fafbe916d3af6fd0924cd2973e1e2474b10be1db252cf038fc32e732484bf7f, + 0x9749b2bb5e6668839c8be56fa468598f7292780e294e47b155c12322e34a0be, + 0xc81643458c5af368b81dcb405aaeb3000b4c0ba29c376855470cfbf2c35e3dd, + 0x2f7745d6f815dd3cbe2c529c63f07d4a646015842c6678456406a248252d0f78, + 0x2540261ae5b2a3becfe0ccde660cf756cfdfbe8fce0713c061da7eae6e5bffcd, + 0x1af533c9109087f14eaf413f798f4f0e8d9453e7cba136d9f5b2e680e80ac911, + 0x27115fa52689f8b86f2966af42504d25dcb23d541dd6a1f5d328b37b9f982352, + 0x1f955bcb282c2c0e74b4169a61a510d4fa506ec8a905051cd4fbdc9ef1130654, + 0xf13fc20a68d983add2992ef921aa7d9294e574b8a0c697c5d56622a585ef6b6, + 0xe480c1fd8e61a5ed800036d9110caa9a55309bc46a4fb1d7756b7e96ebd2768, + 0x208a8b0cabc7890d78e18028768a0a37120ff1e0d81cb9541bbd781d3fb5a679, + 0xa4bd40c175726b644c3dad0e29d158fa1b1753a4a59a1606738c57026eac391, + 0x859bd87fb95504fae2c58816724777f1c93a172de0b231da82c08935a950dfb, + 0x1572f4f0f2f44e7ab54f3d0ee208d13bd9f4a16a2be71600d10651b35483ccc4, + 0x2595802b887ba581a6463dc3dd4e29be1b0977c87a724078d84fa16da9b8adad, + 0x28290084f5f35de74591e06a61e7a1d696a79b2fb8db90d5a3deebdccd483987, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0xdd61a5489d4bb7be05223e75e80040cffa4469bbc1d2ecee02d0d5d99412e85, + 0x6c52f4f90d713744ace66a17d3171c6d83f5abea58367a3aec7d538736ae17e, + 0x284ce8cd77c9caeb5222618bc77d4c3d299b41cc74812489591bb1f23a5e8a14, + 0x1e914c2446466051f961f69baa9b00c56f018232a1cae8c6933a1a54efdcf1aa, + 0x1f9f1d5d61c22831aa9647a5b81bc92666882640968d63c03a338173c0fc392, + 0x1381629462428cc21dea769021a08fb83f68960303ac1368cba88b871865f06a, + 0xb272b9552f9201b03d7ebe1a1887c7f8271ebab08e81ed125a70c8f7764e1e9, + 0x7b4d12c7e949d4ee6e2e0ea93dc105afbfa277b9373af2d12a6ff64e45356a6, + 0x1b38520ba1c4589fd42014d6e8049acbe95daf2c4c2d910c44ab141a86e21ac8, + 0x1f9ad110bf1bbcba3edb9173790599a653793009ec8ab285cb9567a868e41952, + 0x2e5b599ea8d25fc97e621eae08d130909178d450803edf6e853584304f3bb0ed, + 0x1b15f498744dd45c644224cbc078e921f7c1b3e1af764a8467257d6c069fa18f, + 0x1d4cec7d699719620437c0a48f205caa856cbfee94146fb0d1d8dc66c465f4a4, + 0x173543ba0e2d1b252191c8b9392abd96810103fa3057903aa1697429a9bb9185, + 0x1b9df3514d0b3177ea22b6d61bbba61e6ecc5ef8766404333fcf6f91da0127cb, + 0x2befa98a6a5c83888ab8f22f9504c9db9faee563278a894ce253b34980873ec8, + 0x295db1d483a66191171deb6a0b95d08b843827b02f5e691aaedb0845baa64d77, + 0x16fce7e0da0af20b730d87e50ff3b8153e377304d9d262bc3c1e2b4438d0e189, + 0x1660401c207ebb47773a099e512b117987bc8d102a2ca0a7cff9947e2f2cbd4, + 0x1bde105e9ebf2795607de216e544e9638fb23ef1f598ccc6066a5b1acbbdc1db, + 0x5ff2966cc2aeebb42f6cabc2aff4ba67881a3653168b1da8919ea64188d4a4c, + 0x1de18595180cdece76bc7a389c725303f8114625785e4f8e7cb987366b7d8b50, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0xb75306c52e9faa2532157457ca751484e5de2cbea41a357481e6be641c4feb1, + 0x4c7855c4b3a6e6db0595c294ad58c4c3a41ab7a671608e04eadf389a77d5dcf, + 0x2596ff7a33d026067f427e76dee78cb0cc93819ab599c3bdf93191bb9797a3c8, + 0x8aa0063dc5903d4aee032268c89e865b3269d7545ddb1084af2479f55225ade, + 0x1548a8bb67459d26258983882563f449a56c01e3df7a608d086eaab22f93708e, + 0xd5ce47fb827e13d9eafa9befefd32eb089ccf1c0275c85946e2dfe1f43e8cc9, + 0x1b5f4423b16a0cb4af1f7bcbdcaffdf51b021924dfab1be7fd33a56647a51999, + 0x18d535b7160e89968c9633cc71fb2d97df3139814c12fdadc1e5a6f7622a7c00, + 0x16a0d6cd63bb6b5ff4c2808707201602da7d6b0f44b701e8393f98db43c24fc7, + 0x232c12d6ce6ac0ab8eaf31cf01f9f8d2cf50d24b18ed216c6292672c8d5b490e, + 0x27fb96c5c58c40aaf14a9cef49cef5a5c0b60471fca8e907c4d56c092d8ba385, + 0x21ad1bddeb6296215e8e20714f3c301769cbb0436139ebe0db55fb961cf97738, + 0x19b16870babade7b8ac30c9e62817064ae98a876c93675b2398533783343e63, + 0x16fdcef57ba6577e0c963d013271e70215c8a3bf9e4a0d6f93be6a4e9faf2d00, + 0x830ce701a93a0d7f92677aa65d53ff28af57c823098c256fc1470b3005f546e, + 0x2295d7c8b14f2ad4cbb0f762a54c58383fb6a8feaf9d4e9bde35b95fe58ca05f, + 0x9b1e43bce3e52d112b238e8f72d93493f41a8620de6e4dc9b52cb5a2a1f3dbf, + 0x87c2f1fe382f705024d1bdcb8fe8adb33b82361d8cb931ddee3f9fafca2e4a2, + 0xb17d752334a51d02c091a68034489d30b3b4c7e7659422e50b32d07a17a10a6, + 0x18d4520269ba2bb7428758e1c74bdbcedf8f058f696da3bd8fafddc3f2543e88, + 0x6d0e15f1f1c2b037bfdcaf6b1e724b26ef28d76640e68110d50e426cafe5688, + 0x29b7bc033acd92ae8a6df93def58d498b79d1de519f6aed8de984fa296d8d9f3, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0x186d603bc6d93626732b1f85ea4ccac141cc8f45799dd48af4123a4f2e7a13ed, + 0x1e9fb44d51ec4915ed9a5809c50dd0bfe11b4edc69e99befd9ec30604445abc5, + 0xb48f62bf60c1124bd7be4e0b9ee6c66a642918a465fa1a50e1ab500d677cf85, + 0x247318154581bff6dc6333cbc14ae74202b1d419241b047dc891c0f60e68abe3, + 0xb26cbe5ceca89934bce5543f84e42bc739f25f298e556225742d987b0e6c269, + 0xc60ad9c62b74abf92a69f3f0c2559630ac51bc8f84c426130401b7890278a30, + 0x1b0470a9e3485e6cae2769f6a9b7aa5e3b56f101d7be6bb7c91178d594560e44, + 0x264d68f9e933b7f8263a465260aa839011aaa117eb02358945fcce72e0c93e2f, + 0xd93de8429c70415df7229fa233e610689e3145d5346511eaf5b8de2543517d6, + 0x24a99012c1ed7a1245f507ad4a9c8534658a4d1ae47ad653903dfccf66b4403e, + 0x7da99b57c2bfc56693da809691737e832191a765a51a276971f167c3a82ccb6, + 0x1cea1b13af00acb6c1f1596831afbd4be16fc313d954baa221204eb1035a8a1e, + 0x123bfb0630e8aaf56cd3744661919b2a88c0dff13bb0a571aab5253f98bb4762, + 0x1af132231252bfc602eb9d982d46f7981470c1f81d33bc2d50764daa4d0c33d4, + 0x2dba0bc37236d5b612363efeec5db5c4b8dabe365af1de7eabc4307d5d13a0e0, + 0x221ca65c9a1d3b45b69170b26e5a64921485f342c9d1796042a9d691dfa2b626, + 0x497f939c6b45ccc29d57e1291021d7fe4186becb765967766b7ef50e5f2af6f, + 0x20b8117d0bc5b325f5a6985deb0ea6c119add748d4432aaf52f1f18100c4c4cf, + 0x1fa73e129c14d72a4e3d45e1044b4e0237b38cd5f7a44284bc0e35fdce08e666, + 0x19f24a1c686e20b06039e60a1d522f8d521491a40698ea48a43219d401615c11, + 0x21f4738cd989617c3e28dfb8072f349b44fadd5bde90f169420bec4a0a89655e, + 0x14d1cea4227f6d369bc6015328bec36f0dd3cf1d9d2d088b5fe413ea7faef3a2, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0x985ccba651570f4575a0ed92fc815c4d262c6bf7b880a4a2e9a6f062e0539b7, + 0x21370081514ca3496f035319fa817e42c182855c938b09f5737bd5e0b040d387, + 0x28d51de160b191dfe5213005f019a3873bb60f2b9679a3df65617502d21538d4, + 0x1ccdc75e435b8deeaa4b0c8b715f0831dc225c7538266e90609f6a6285a2bd48, + 0x15ed8a603516e1f5617875a6146dc9c8d511cd100f9ee41a1fbdfd5810408c6b, + 0x1cc5e7a4d7ecbf4bcd15e2c0d54532f2c6f367980d5afe4e148b7bd8137373a4, + 0x2289679ed75bf564bd924ff42f14a4f63663e95822eba74b35f6c58d6ff54ecf, + 0x28a844dce08ee0b8fb55e7df9630e357928dbef92ee9be0c0163b51cd555503a, + 0x2521735424459701359a4c27c2cd0d55baa5380e4f4a06ef897b2ca89bdec56d, + 0x225abd618e11689670409cdb1a66ab70d077cdc0f5efc2b387258f280a24c36c, + 0x4d7a23e3eb7a46679ac5fc1d8a13d1670dbb5f00343cbb20893fc5576120b65, + 0x166f7e2b14c9b1776ef74e4dea3147b014234f58ad5ca5a41f5cc40775185157, + 0x12681987c944d15c132a93d6dfecbe502b5b7ae4daced230eafdb89d3e8d4ee6, + 0xaa7558052b83cea0ddba30060b4b443b3a4f00ef388d98aa6081641e7ab58e3, + 0x2c817b2fd2e5ec32c6bc84f11b3c63197aa4ae8c2f372952bd016162c5d71cb0, + 0x11962159a017e25334049df13f2bd013d77cf18b3decc7f66ff81041dcf354a5, + 0x1d63c9e5c4b133a0511c8624795f54474b2e6e465afd90330f50a44eee9e57b9, + 0x2d82e29c044d1096b8c16734a6f9c726ac5c5b47a199dbd7b1aa0792a16141e2, + 0x1b28d232a19693543110917b0ac82983b78b48fad53f25fa007748f630d524af, + 0x147ba0f7c38d875d1eeee53ee9112b75fb0ae91010332de8f9325aeb85e2e22a, + 0x1ccf269bf476fecbc12491a10b7a031a43c6df180a74fd76340546abe205a7a1, + 0xfe407a56ba91ac174fd49efbb61e8730a4397e8df24abef0666c46e1696f27a, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0x53ab7883a6bb37977a9f6c04b7430e1f23259c71bb63dbe2bf0fc296793b2b2, + 0xe791a7097b6e2ee5dc314d57432975400f92d69d4ffa60d7c9a004e8a8326c, + 0x4074d5f47b8529c9d8c79f8869dd7e53944046be065d4cf1d9e400cd30e005a, + 0x105b47899898ce40b7b74ce948c42b1a7f1c064c17a5588cab02b9f593b55744, + 0x2514168dc134c9550d7d4c5dd03dd3b6fa0f4c10fc363137f17a1cb71b8dc451, + 0xaf1d61be25cc6a191184e77234542f4946de687cbb08aa8cea91a61ada0548f, + 0x1dd5bea55d34b381ebdc842200ecaa4ffb28b9edc96025a7025da4d28af0c053, + 0x1c39e9f8a25300f88afc1d5aeca648517719f5c2f8977865deddc3da451f739f, + 0x3adf474709643e45b573ffe296c0cf64b0bce9705b91f83fc1092121474942, + 0x2e2bd30c5a414e196095e3e2e7acdf0762c6a54ea74dd82ded60f8e6343c44ef, + 0x2b53a13cc27545adbed481418cbf2bc4db7ac6aecda56492735ea2e9c828e876, + 0xd90f7595963d4c470a559f222fa2b6e9588660c9ab42474fbd3502b14cffc96, + 0x263b73e3488bf2c208876b22bee8e28aefac9d3a4b76768e9ec0b8395d2fcedb, + 0x2a0dbef5edad1d5b0146a0630de8e8588c6e9f8e343ceaeb1e90f1163e93e477, + 0x18c06136a1e2c542dd4cabafbb9232a98301c91bdb294072cef62ea4944b1f78, + 0x1652c71884fab33b816d894c62c6c773cc63179ee35cb7e73a568533547d323e, + 0x24c895fe21900e49b6c1e90825ecacb474a9e919a9d3451e170ef22189f5ab17, + 0xdf80fd4f963e8fec47fd44bc51d94d1a0489477b2963ea46739a99a3ebe343, + 0x1f03fdd86ee29e48309c79e90e0c1225a1ffb47ba0ca25e4e261e17e82567266, + 0x27ce3b368152a24912d9493bd7f75d54666d1633a7f95ad94ef9cb63b72b73ad, + 0x75d95500a93ba86bb52fde581cbbbd7ae1d288b85e9862fdb6a8460cd9a4d04, + 0x2987891ed79215bfdb0513344a736a5faef636e4dc1aafb953a27e60763bff4f, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0x2fcf686a3213ddf2ab8630b29d271f1c038040c01d6d40917e7665f59c0f411a, + 0x261ea88ea2119c8ee660600c1c26964559b0345f3360be71685620821638be7a, + 0xfe04a27aa636785c583c247067d0fe0328b8732b173b20171573497967d8a02, + 0x2cf0912ac2237a5091ec27db0a7d5284f13bd4630fb6b58f221a68f5f4fe3232, + 0x3041569dd972c73b88e73eccc715d7043f36ce79412db0df57ed902957facf9c, + 0x2a4f9b5c59b09834c07365f58f63ed64038366bd9d17c7016f04505abb878b3c, + 0x1fc17fccc2b1f4d051595c0e4151406c29d2eb02537696aebfb7b85e98371718, + 0x16fc002eaeadbc610d53818fb1a72c47f07e7834b9433e0276eedf4e0cc779c, + 0x2fe0f6bc3242cdc940d4ad67a40328a51da22100cea8628892a20d3680e6d9dc, + 0x43423406385c4db5ea885da5766246096064fc77dda460fe8d8deb97d34ba44, + 0x90ee6fd231f2b7fa73ff9baf6db0a47a0057e62664ddfd9355924242d050e02, + 0x3005c2f73ab58a8cadfadc4dda1e3422d7c0f6ad0fe7a752045ac72001c6d445, + 0xef228d7667c66faed8d7e3c7bbe5925a55d7451df7f51a6afa3bbe0747c1ba9, + 0x2161f7618113ba7d7842db94ad2ef24f21f8a31b4c1124688a2e4dfac810f01, + 0x20f085669bf228d7ba11d93866cb3c268b2e031ddb9697d80cf62628686938e, + 0x294372804d6e2359003c9cdd1677565423edf025a9933d0b25faae3947171bc7, + 0x15d37890f0af5bba4b3abb37bfa5d5e115ef5a4e805505e2cd021c4807ac901b, + 0x287ef1d880b317586e978d5fc8ea277aaa451ee6be1bbb8de5cb447b7db251cd, + 0x5d0ffe0d01c752afbfbc3e2c49f0d34d35ee5198603300d727a11b8e7eed593, + 0x42e5fb819552fb66da7667d664838b4bf65a50c422ab1e9a85b1ff6e92d30d8, + 0x1fce9b344a773117d21974d9c3a070368065377845171e46936cb95a3d38051c, + 0x217e2377d39a2d534ef281f973ae22fe8ec4f87500899431cece3c75c410248, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0x30073c53bd5375c642148a247e4260a05b56613dcdce4a093e85e10d296999e7, + 0x237c0bac139ca6595c3dbe7f8130d399906ec0710818ff44c05774b479d54fd8, + 0x1f2e23fcd2259faa7cb33a243bd212e89baaead143a7edbe6c6b1c295690db9c, + 0x2ec7439229a284f2c48edbe15599d462b1d073b3a6037e8f7c8020777f26ee4f, + 0x23c268b84e8c118733c2adb6b3b0935ff631f3b47843b112e80cd9ec5b5acc5e, + 0x136b39ab04af56cfda16f3f99411b1c3cbd3ef198b5f056e65718f52fabc7c9, + 0x29358a02315a9f5180f23577b3336be58d4039e6ce4fa251c4cf8618a955d9a4, + 0x29139674f1ed5967476c8dd777624e49bc90890a5c99750922a4725c81105775, + 0x2fce35cabeac14beb49bab9ade7e3811bba9f32b99a78e3ad655b77c473aa32e, + 0x2d0fbcf9cb5fb78fa20bd878ee7e6bdccc2eab0eb7d232741932c0e785301f0c, + 0x2ca38f6f88d6a37b8e126f72a82237850d9f26edc5b577558da58c2e55b0767b, + 0x19e38d09cdb939e187bfb8822e5c2297a897da1f16555a191157bb8a5af115a0, + 0xf61a58b977b2fd7323b48941cc010140e9b7da31271dbf3e4691b767dee7f9, + 0x22b5299787050ae04bf9fb86cfde9589253870bed1a0213b143b33eba1153df4, + 0x2becfc510eced53a873daa537c21d79a1d5071aa734f60553ee809520a9e22a6, + 0x14d5be5c690883ea5b406c10b0120725bf1e4c5de2177267d9e38e9c792bba8b, + 0xdcdc68aaff548dcc7842f194b1b30b604e4df04bca89830c0bc367e7703ddf8, + 0x1b0aa07f9f3f5aedc37e1f7266bdb1ade79a62db3714cdb833d1af86cb89d9d5, + 0x1e7b9c8adc9bee22f859972a13e0213314d43e1829f4f99fbf019de8ef79f3a2, + 0x3d090fdc48ebc009b4cc7ed3546d69ec87dedbc67970dcea6052642e517fe39, + 0x2fedb8119885c38398860a6e6c5db18431e4f0d981a2fa274a36d5c31f9cefaa, + 0xfa5fa0299ea7aeff8d357bd332f13abd6935460588e15adcd0ec76c8dd6750e, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0x12342a1391a6b59ff25a5c84f352a01a24422046622625d79588a43c40f4ea8f, + 0xe21849b6b4969714a121558331c18a2a8969004cd750c3fec6bdda6384f5a30, + 0x143fa84e95c7893e11c17306bcb7c7a64e395e3fd9f1f4f086ce3594728931d2, + 0x216b7f99cfbd8ab9e124fd7ff4b172c853cf23a2ac95cb41b3a42190f035b144, + 0x18bad0594a462f033d2be7d2151cddabc6cf21ed59510c1e56d080872fb95490, + 0x2c5b49fce206c612947ff5f4a12cf1e4763a3a1f7b9407c328e30b3497d69f3a, + 0x13fbbb66309924fea1153a649786a33fcd8dfb3e4222a3d59393b40ccb39b9a5, + 0x3b44f905e3c8a2b3e7487e0ff0e1277d5abe5e1301c165ed1c9258829622f7c, + 0x56c2fe32c1944e7c9400d0a6ec21aa54cc056562006c48458386c8d92f565ea, + 0x29c47e53143446f7bfc43afb3ee84548b5caa25f4987796415d68e318889ab19, + 0x2e43c52d27448282177163200168574de40c584fe61d4fae5dcae495890217d, + 0x2fcce12507cd0630f06a2992a515f45c2b469f2742e328e07555d22c75e51e40, + 0x1d2e6d9c5e8c220f9402b82ba4ebf641b2173e94ae76eaf7ee5559d43dec7611, + 0xb1d1a4591f233e710a8f245cff5cf759fe0b4e55f46307bbbbf5d4573a860f9, + 0x163aeadf9697fd15898344233a5a30236499b728c6fe54b2534c7c9fc648bb99, + 0x2e3345617de88523b5d09b27c9669fdcb2472c6cc832ae304ff960c0d4a5a348, + 0x1859a9bfd50b4bf8d40885c992654775ce35ec41a77b896206df0ef2281efc08, + 0x1232a777b5141ee4296798cb37ffeca708d0eab3142357e4e917b65e424ec478, + 0x10c4ce967cef015fa466bcf69079f8f23bb2826cfea14c78a3b4509ab2aebd8c, + 0xb980e8a923bd3a2a9d5e9192337f070f18c11a16c809440f426126ac390b7c6, + 0x2b1d91f4222d2984db754e4133fd4060d12c1dbe6158eb34fc1c1fd0f6327b99, + 0x19ca1b4e01a1671c771897b741b03ca691c2df986c339c6f2c6b24663fae3129, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0x15e4fc48c95a30a9b34e39c7e2e5b23cf96e72dca78d25cbf1d07f6bd1f35269, + 0x2d23fdc4c0c81c5cd12440066758541d7e4b9c6bc29cabaa7bb3217fe5580c65, + 0x1e1db0902c0b9743d3e60f71c53bdbccbb995466f39a9e044074a32086f519a1, + 0x24b7c98c30ccfbd3b3c87479bccd71122f3a41e0eac0c5a82916ad9e1c77ae80, + 0x22ac75fca4d3bb5bf0f9f25bee0293c50901c2d45f4c2e1d19d7433b2771cf91, + 0x2d0777b0c575fc2be9b13118b4bac03bdc856c03c9b7236f61670dac5da95b1b, + 0x2252fa35e811593e627c8d6ffedaa4503728b6d6d9676f2e3270545cd190be5b, + 0x20b37b4ed7445a96acb5891bfe84d9a5b96e8c5a67dd111cc4dcaa8269f4f0a8, + 0x2347986652295db79f804ba06d9551d3e2a6b5a1ae358d94a1d71c34f36fe0c5, + 0x19384ebe245dce94d5e68070e3114b1c5be9123e2a3728ac3af9d340058a35e7, + 0x1fc74a00232310ce6af9e233a4934550b0f3ef063f221a3dab64c2d907138a35, + 0x104721a9a6568d9e67db56ecc61ee18623e89e26a47b9e9e44f8977da8a7c16c, + 0x16d9fd4e5dcf75863f3ab7971dd72de63e09cf77787931b0868a5c15be47c163, + 0x392be8203347a51c9157a219aaa6787f54494b61e62c54e1c91bd995addd474, + 0x1728a3905a9130b0f570af0165bd2d00dea61d61f7d103ff7c13172b179099c7, + 0x145f03cb3abe12eb5f0cac73c11dba2bbcf94c72f2e30e22193a33906507934, + 0x87ae2a368db5f3d666730029fa0ae971b6f50432881c9c0d86f5f3aa716b842, + 0xe386543bef330d6c3cc14294ad86e2408894da265fcc041225196ab8064c737, + 0x1faaf3ab79da2b30406f111cd42aa6fcf187b19448b18f4617712bb95aea6ab2, + 0x1c68410bc6f75d9d773c5cc57af29ab138e98480e1a0de15195e64afdec8c525, + 0x5b529d09da83d895ddf1aaa9849f98955d81280eb9f4b71cb7694b2a21ecc0b, + 0x5b8ef58138e7c3284d9afc4541e7f291d87b2e26b50b7feeb75cd859e3ddcc7, + 0x2cb13179d6e8a4ad1b9fec37376253cf64386ad905e240575fca86539b272dc6, + 0xd2abe6bb0c097deeeb3f2162b41f9e969035ad6ca31e71eaaebaa590edae407, + 0x1909ae6f86d6d43332fd32caf83152de39aac3f2701441302012d3b4349c458, + 0x2f0ee3a8676b72e7e5ef4794aedc88051f0911ae43d036449d7c07fcf2f5dfe1, + 0x1e378a1fb4fb0b0e168121f86be8de342265f0d9443de37ff6e24a8f31c63003, + 0x2583b1b0912cdf162a046daec4856ba80ec6df1f1fa080101ccfd225176a0e8b, + 0x11d9e38aabbe2391dcb7dd17706edc894dea224f6cbccef182edae298800e746, + 0x1d486e5b90e3f3c789830bee968e6d544b54031477fdc8c9d002d6f9cefd598f, + 0x234434965f05028a4f5330a590ab06619914476348aeb87a1ebbafa1e568eb18, + 0x3eb55944fa1e36fd16239f7b3ddf108ff5f27955e2f386139493ea05c1bf509, + 0x22d683ecc91253d08e6e535a4b62627738c2cb877d2b125aa9b190b3ed2ed9a, + 0xff142864b0e14d2734c2ed0642a474fc1f0116d7e1c5dec18bdceacb2721958, + 0x1f930557a284998225f5f4e4dfbcf5ac211f1b12d91b0562ed3d63285d7a714a, + 0x18e8222f6907da5745eeb9cd4a9e62f28b8b710aa85fe729f9ea73a3ef0099d, + 0x180e924d757d0be4066feb146ed56212e38acf9df4957432653f370f905b8b07, + 0x2f7d0715d1391190e7b14a1242b6799eac3142e21f08ca02c21755eae77a55bc, + 0x2283ed8d5e6f9470b3f4f49a771061e4a4fc7dac683defcc0348a8862c6ce71, + 0x21f60efb132b62909990b9f994f381a9c02abc3ccb54c5c8e8c9c5664c6913d6, + 0x1cde82acee60b84424e9bcee49a5464ee05d1cf0b70469208a675635ac715495, + 0x118a24510a2153f818f0a996c87de913587805f16cdb1939d9406941f958e8e1, + 0x164567b0de16b7a5550fca229bac7cb0779524325e4ca5e78a86078881660264, + 0x188ff303194112a7034527cc9dd0b4deb0960c9c106ce115178dd7087e4e8c02, + 0x83d832adf9bb4a25f686abeda9f16ebf53263dcf9ef4311781d09920d094ead + ] ) } + // noir-fmt:ignore -pub fn x5_13_config() -> PoseidonConfig<949, 169> { +pub fn x5_13_config() -> PoseidonConfig<13, 169, 1625> { config( 13, 8, 65, alpha(), - [8798508051216852101945770298446195263426534955832706109793971883081428107277,18986509933027080134736570007084643366993581436980149915398754460582000677690,12888632176077676513526604615863975427335143923557716212154194444095746278696,15218363940991075171925464923999816479227567707705088260324253815128900522726,5123856245344699442960347063644568841985144075867098178729206123344695866632,937497109650566529304426914695525196119182564119552807475810542139513078711,824338985948318627675352935105995425917124279032809525354560876904860400681,13942203133811236390194976449250445722833065335401645546668049734024419803027,21193497547768556525501812324063541319364865851059424372272833186043647143451,8250588221665279725951753271334754148372733354841465281007604695074534688729,19810263445128123914159130235504848033923366950322026683325764129239721093372,14320576994914109414332501339118128158228930675887122896979269439627163060693,18889264041663920880871940494605753485014632588652805059026615325416030193719,10698608730721598729809918763148392473410663742558667693804099019738511427166,5471531298285601691838160103499608876767872950664004448938449413930813358696,11457601248269622750970644898105156673192281665198367584690238105651871243849,16992951642443963917535033612483493956841253647152989134657936764458589935104,10681874111209657199770620844475073359855652721773538207614365548304774934508,21875342192304323235337862160226992419479798345905340775869689347883470787957,18783598503862573040343207522848147282351537545213737188311758281500392127423,1221270316640374234025430293653174054626512367600614548099335037611485538579,3803127350594514565431185919859613836470412459545124433755604579955078714169,4692704173297526575662787527414813729052368393667564364621548376076502682045,14877344233698668087821753402566363996983618742746012792982725192235615274582,1054560579819817802724755404438987869385528807680314510667741074193700268397,8052216208184446695555642950254618937388238814298100142455645263386380520432,21528486310986712871728288619461268100617012373791428855787397091733571140849,9607239927604256097021258716815750648977424271874860033430637795556811442682,2196312812082021938532541315765264710074289763312450521728804241715253452502,6605540160838083938636248853297421723407665107595785929587574408377531474397,6525948153406525772960169117380395975817023461160134354401655738067058124631,1003556227519998429556476568497227440137917634405973503866888411893650518666,13677584968475474622689223355399150668790874783709262452797580070344541448836,4272686670447940608576804106249107479440735969672981187306042096242258850880,7723948150633857131095670967217469617626942590283045283879017721699420758313,9563761958679910727099148022742805150896356950128100201760652748527446140573,2850052690445041465388681891454371728435601558220304706587137488583335087257,8526775100524058290507772716277462650712450825299014127801740914862834880076,3867865860920444582361195032750323847757212456942796852256870663055781206979,9531131437985240947539412881613144640386246585015365913532093261866651903759,7876176264763636659141490167245054739857019306622806711043600468363729864093,19195073274099628437757763039411307254419435216466391625117296911023053159082,17201596318516267959242478674525331020962456681235714852429128354797936423512,16429987001981270427843548313178399452962937303668954688438246688799503164984,2808058398896238113910841463946229560728543614115874664163904810633100174930,14219106904819518684382581834179422938681605045169559176622588393807041033595,10530037691301443797595179975755234137332257307745168342967468344289118325757,1780683171090951191330938815635375996828930714110381590102230999415067289139,20631152509228411005601100836698224543066495368069041690921190101674287477942,808499207021654020396580110067573161997188131641925849629551231827774305643,16396331554632517617174441423319546296247483740125085437207362257874071846324,2856734177282633594896606301173852733142847026457749184584827572766646232552,10322006004350928347565262203595059371944943723449117022023179276501731876345,2683049508597401695548071522846046195699870016352617057472448981851954812059,16247545910658018105089170383534659574306111291405960552997108542031333797235,18622054704352443244328095600847746501599243235049513145116519278941866455272,8702183185743408572844482710294629749653378107594727106707156268893318308842,14401120539669001367195063486710670290450638416936122540739824928865783084126,1008932491940705147356558882115440120351684984366727805937095853000783157110,3335415470820584035672268458205991064638866247863327497697585974180788121327,675348271572506248948949205284720732296364868854507020989147277054109697307,11425495584918585085965114263893597096866227224211705734884180990929134229634,3139501819004172358132939651256683854267531704642601593201346365873114559764,5783084359807455756426365693604321435940832494660634548089377362001475784943,12095094864547001070709219304829411865589880746021553931719922191437710414601,16318907049539057156624360879403805284297767691522365017367114160528018468654,11395679267999229912686944592292906403252965050428182621076890662342583575672,20304144520028193526915712162937805381528012861129116050582705669151951550558,9782367134866186358061353221055410602027546275400836771195060684844149613708,5028029607389470804476265609647401798747012470860555590083631854016382301797,9007627713847325367341162188681367076476205669132463414398773746849014673910,14471089911822534831111187815987523323244485794708545360218598163622346282781,8019180100611273479652907195647951337613619920735853449223048779220663542855,9047131412613791119405208650892730556330287685760678509615107996866748231916,7335839265467743759482091707230237155828204454352010285192894893585057443442,14787708665825803366954624175778735065630831061644057898061768895034788739773,13527353131634051756987040962797036674382517083826397597671775590484363794989,14976182354818370036095296869648510633049821903988384882639150664375161429327,1560099560219605560187324067315095140041097722845226997637592687804174779694,571671177230396783003670900588907847431348620829409362554250135027808522430,3595401819266532411007886403698316446251107730632935527816690692561072394769,5582619801223860759886119158956613012355932421337001876528290847176002785551,12913958465964733555039885816821695149723050623118481194340346951472209298707,10229385924925018504492473674441213223237935733123654864337438778499472034702,21343876046925805512584981384457719270702482935633311830189677174062117124219,6420204451041321645976980917151646516083600244123365393849746698818033299571,19251614427061141498566572096097506725955838624383486128732046911906166384020,3637855341628865891325364423447146770285076487178203925892266081818756628695,6291095057555542758591776864498618016939082736178179913313186141723218066258,15680673126007380386463552533962308522676179674235002556809204723523731273305,14161910492383069106925371061927425194676913565753916851706224000847740857190,8408124204639665996401588312942126836254203358943885876199057731364731921137,1799578340300310412035304211591366593871976523584701800579066126447600019902,3622312705549913151631696033404711371424834689912295490477655370864706883384,13273792131373119117124844835198348538764494606049066494384531598904652565002,14270260908863510838028225519201826231421616414346395482851862560529215543207,1633715375341396582749269086363023314520014551113162582725277839347569228786,3306641014838747329624593360740422499925312234577578401365800985267347686108,14198045292969051397674853108255956449504264447127690313478218267366467132592,13392638089393029927126006202520304645547980480174653070691229667854016527907,3343885948493512216041748082192584170148231918609106413514016808164860398278,3168199878854830552224332084447744849594328418779455928665560385861883941432,4414580242526682670231711868212166617171432599055299074136917305689841663873,14102753845056293060191802617344737652392043747319090694003879675100249630273,5573924339361534820906966230551252047468623512376332682801232194633308271653,21326161716444219551593862645873877150197335577674154159730974795774063715301,19432958264517639868400987651848393946587739437911153002798497064389336859842,11213890749343283806487445619338898013466071000086191642490563684623068539710,9198922780305686612592947154769134303077110139729181291466776593119643796878,21136183246673473125620223552691909911094171966517655547561646692807715461191,18418245895226184084223713341727403858051315526021187444511237652982687814864,10761950212602122725874752124635327020166823895511275020048089638533400314021,16715137911831586771799460729625653907150059087921720918100590730689273071536,17773351327415330719066508685011039352345666357995827941409702750841801825772,20231347041576378765333233596636479502524461869780149044300194060543432934519,18064563634590190884918686050639690971635922850408462075670660991277444012424,19311806793959939929201104461555154688516767798907269687984909834335608414545,18574604846458382436863152415585348247597412723601050266815439019897542533749,6791419133329459189167506884324613003818238896866734783035998091675242101498,16020026112470750192482231650248429937269643957555877460849721131766422051297,20044512180053459577124670295358045421070313597307221323295226934357969810703,5766192039785553259974801912149788259566859976619902528741727877731329189756,13160650100556144411626475539530712035286115503483655434606927361569861225444,9256036311849117781394603817644061414251138927392105895934210116699839233747,16660304826343536533933296919943639532544710122612011090406376521894383168856,5613106871918486982198177086366936520094704188389198685078718794779139126942,13070598684216243718425316519583985756848433332087820965201044383296972346897,20442537178749694119236982549472062379434941056035907413284316764767638577672,7934380525369255820244941077363404413659578389361986061643146925957595190009,5098727584136148023264970031064585917675686576590855834683443649082028079965,20311250985440103383589841574737981968195820548330595923330987127317084128947,3768224286214159313341476585351274256214081884717440852909749729584659454712,9851045187544813632080431293737874643968516290829960553238754661188963821885,19015242154372799267961042586541854827581444440949327264389997835941454171864,6579883332160451787803375748174162900180016921849643588581107525271529605849,10040045688615204420748720492172111994988850765670088109590569954563466338788,16200830095429004437461800470410149972585288873073724430176128378316485348605,9682955393234868764418991570718636989945366768432593131049879027562290804128,12304247432606946020923001398973669839540045070461170795482951827192644001957,18191542513141047176662091981681722742011120542435182371090664849144982674881,18914155310347961884616925389217412880576183372588965807237661684331120845382,13251661686687775186900604006618374427674252707179991219741046747323389941232,10249194086135063113459170280632696947988284060709952681203426883826751049011,18372233147890747575375422462203968154682646712463764047424428288714397527619,4638790386282413677458315728120268440302827185471341027696814407017634332517,16623961311962310335126734990913554770362581939583424145026358913546809927380,17860493200690068167535851968852986582339867469465298666834410487621188113531,4608305735853858774877121807982873005510358307902418229099062852681969399389,14245817054597951763417586258404021745844024655622942045401677661648532977993,3809843434538253198074703856325693344260532607506586917570357443895551048805,17962207143381407459791220803798424686492359980872541932770670422523978330935,328196272784453082510222579442282995329426913454628381427614217629272010096,12374354866281475555079168690683958365929973901084398491477273797832999248789,20853802547446175043916531515983184048009878116903616041233975407782898112824,21496110961478435785328603969876614135441859248001892605282920516413194792470,174344306580108774551764089189043165870298462272157912012996952342994211137,20687536797191141044727224925607387673330130224876076220260820047611716395831,13067331728561732140381851790951434625007152955086246816336518249186949048391,3797862935019829095677036741096081889651388634128316641681020782687008662828,19718547173056417343715166978970272483152981364164960220358919266690668222316,4038867288048886379019053981446145278427073511478003014108759946240227146792,18486919751583655613568544119169758176904901075587096135301780773087898879007,9808503221335286135961820380426080374193561918865479543141400875074697503967,11673653729232546119337900700609058880494248359777926756321171038104786463073,2206576012107962093523647385331312771747616647783007209109500521090968991064,9800772269959998996051474306860888030671933506518907174943285018516216530078,704115937219213713489981656324169840669771632134921090864597729550810437103,10450936455424589171986477572900171091143445830786569605988162504754224051029,21102186642636060890935221995324710172830713161820423345683707273376266063905,9163879187976750746407679763920281609583516506018439539723656773309855786163,3472157821801145643950882966615731480318387993084591537527672102896556538908,2411890225861629547000508300507629335095483162292985158748687911181232049540,4985409929001444812993021607654361988376208034496482520498705351994820408485,11553789937761176964063895958945223002657928340200203811287735666719305693830,16847788791386791842258653027481339013349340413294800029138566625971691859716,6760556724223230789549789607828387138865070021837886343220335025271850431529,20596400847159894247975659733452116044170283916549483164302854789226390584120,11672317719239435686809215238371249803784157167042393847476181444969645566102,2540677976918908199177572390470632080272842549139729131369041579508211107531,19442658692908544356400723297250992586408893464353224580638700020103731410947,3126219492402213962620193562481318950501969435505738692018385930122987610651,13815812651475874136168661258439176421344570120756240838952907916838907109528,21443943680756083274641262528830913057368026549878765925197792130996882062057,4605307168758134905354332635309004486671872776946937049460665298426311628483,7482893834680785986692353891953868933021236845332400077427554963067657007377,5511796194740668281350270549653399801893104530256753635073935873703864854017,1743641818114051150153510266165400817966589635697948934570080374390326493276,479348932723256576178997677888058436058269610751399398192779646687149113652,2911895727864385123299618342188487304466499987531177084686132082340794352256,20721945554748282229818069151690746976633856763939126384250406858494706697945,12250582445106986808691543043877193096050336861542243284061992098674816799798,1203513568724767846410309911297210537295690041996158208540636591896498697618,6015583439542775167098811213988699848659623500530189193065070507681443523926,13090526755326389175310761634465981673176179379933796187486632857997253599596,5204691423542830100481358117753845481374238423707185894207602712512441617128,13451357406880550276974168929055560555273701366887507611491312211347374906677,10327523031922710495308957226255708193968398139079389167803483310323608563088,20154372727310541088852354530646786495003018189623626400646862775892232254942,14022574434398251358742711545518515409780772767696241502841372748111287365393,5800935164580219886597276061890276866350374777469717717325353972942679889986,4950159996548574497193804912590478284182513481419060390699450490223901282265,16651189959199821925513089100199135327590269582473005780223712025001916349248,21313574815160763657406207917526347065428582824748947465014119238740065134827,16527537328830884258876707902602749401809299353104838028680907493128406403510,15328203752181180061659863584748718494669846163715366299567183721088123843121,12748724793783078481516963303490468110393403014501561235873124284244901317221,18960625031156828010763136389916953653374660277691326636541170359289051172470,3539001622988573864365704884620979405364663891195701665878843924015974631139,19440492503123228668247641573804742990539424862427319298139890001019307139951,20663734806319981969735713814960326046259899097186434280597673603867647826563,5638550801924521462873676353658824547611149604620661155399127974706744652941,1371302213304057480201653073728712066696195910046203705054614806040591336203,14916746318031473743643312292935459967335724866678950897137588157969538011797,21398978398848411648231431125400371920346497858046605440294787662089399525957,17030308547789363149594169656019066171879481623126106541463663868095060483032,2440921987343876776494963936103708492610319137255329185550543355589457647052,16578274606037635679209783094809437790602872464993592428997022911117833097149,584917957795662537423624049408930838570931949382380283787668885015699442922,16787159358764578324620871006477408253726184555269443751955596568136636185295,16078611438600534298861481344414944861682463507987217038328914463538066716267,8692607842423869778858860521189757647588004328790444839011233818764128397786,17461551965098847063794186994739508584146822190403534677972847044656722703432,19452713388671907333636730760656181158378071792518077405629847148635099895953,12121230247359921951208053896624893871654915559955364031951409301929413070034,4704830575919764561517254527427722789804729564629801789022427396957683932024,10670972751746137966064978863033768730585193577203300636726301560193269271720,8049285218762936069773906017628569610476710004139648882735854791085139873871,5327956364112241273910968805653529609896670219677653687154759819173833984314,16209531049562245939203780811684066382629831507349840609244051677227948603148,2041493598600414785071850826176044493717208172684229753087779307523403234108,14983712813504746225033809615975227528832540720868897893292242774973221269350,12085999002734552992271490964670175347983721486216238101789957598273374406404,2010148192415347724117376912318888220341164166588569584654147279107677185092,14204865408877079652583508111640133693635228399739312350971609944706493769468,13330601146337713429471908542961289712020817519764634531830442337284933922809,9363311761287060295640718461317428792455498134298183595944737677775311452049,326899109513011756995862753231193478723114246336082392308214181273112126881,21599711748797254989207108046977874436425859822146104148381410251216892766416,4801349866375335173289265243677780019445351052028447809305464229839535867723,14155733033291624452674783678844450106798515225633669031829757876654937709468,6249525168453913775215814309255487077884826362528424439922890888603955052499,14928369633463338040897134982481546746234350670771618196847518086862393490357,9125617238450534926549876296505645845116172794938106232962454586773357787390,17103886312678741706528259762965004480595318892735191450742885850881411200483,9561133527164819548073730465187187729026229121272078865756229410363525806403,15499339092812475393717971205752228601033972883632736148845868837711619810573,4039978125105304479934956398755842410107811106124175538862554473225969256475,2947887467809254352800319275622693352512539235808226814612313636217910816213,10793550355337981917672616521499626144068251539193270238994640132315408061844,15282024117559604646251556024222379207458577842775127240432856222129525583388,4938487600404790095807201685235688647996095712925228362099985579653367819830,1580271313232748704254579894100134003454608977989565849293374431242287188203,17650488790850180925611249978112046323146336603695505846749648092705166179072,6318477650409317961441518371381185077182540555690253948041195660104038462403,18703841587534276582593528858657361438697750302064291203982535124189673569022,6570410039872146139634976314211122538651252189045191357367613723647837080131,4058984348953256905202616995215664252962770887032362374636631606975462596559,18730155671005907941866324013560951043352315199408210078231145351355402093830,9651860366009425828519962206873795166909640005109793700260660519169015873934,5838396248515026677336009419348618624164637668061855829375740686597759055073,15333954343347884216807246400300286008899152705372200767215516907035196412750,1930765848863686695612705389177613542562429368163669004940380022708446841540,10766617427881894379670242247746203663519351900247145805786260703840625869300,5568751333625760749025074267385171935854368145626703295693077672484816860148,1572988267140272358245681202814159120843671145631424724491020423275325461878,19938390788588115516825752214441323822601991108943527563767657270216212171610,7571912702211887911260059806577378242621772456912160075153794388926572849145,6858979093205494695976875629144179789647553123886814202229119872013338208712,18762692183810081055439753242004382629435200839335768813270546391733006575124,15741259924712306779754554541398522471185852133913466875986860727321229948852,2627808396704584386154002253183040546217470699174068260518444240974395718442,13588659892026426409480708338634242111974891480475426278869635762077927444692,19520457627758833811699878500944809253730386938893290068023237193482219846683,8924178241223608091232956607418048641173985923478293687667819226283386788940,5816806026738575389886097663948769844875803508574710698349454181988557080269,12475579687915690911104520027833630083645170013159764349224529153441972577879,21056333315327274333873056478119184274531121536034759580035646721078602460263,21444457911856423029054975409869505918084415765420838103204937942386934191806,9510785855264774762445687543927870120017463057252636764104600528992946593471,20924833468200564542464376523632289762564405387275694375761127017107713239560,10520571364539530696429244627292574117914912315372596265076914837029323332385,15676633242665585964368692080238475248556973102970746891067091503318954352189,7605218463440663468653884707661331637891252539306862971462289235362996643878,8655416175027898012639173297596079731611447754405890380300192905812736625807,6587158966606269464624627411770696301475420343587060761712532930272301692115,17855802086555955087208003626983743721607218545075932831175321330674668519051,19637270878895908891611772385398729322367589125936403809351999767233932966110,13844120079506591315671522711954211929776840478156307979285069853392230439385,3896487627666829488959793133071741228529962458688538373863209568407375861949,8072922412250331052234441827200394762964253395032633720559799911487619573310,3446650687448682504274462997312106041057536787701884723175991150707212663201,6750980474265223706441237350209360446038939446132826129894534048737231433466,7932667749655660682554204871450377554998925079055538597319130615505233358592,4551937123821223485620220711817547511116227596903370212234130807711068597972,8450248183513826743946014093205824327880033986070570398677443659142729011179,20523087403588105156975104084680617581362696346833272310988747947340344564064,8021873326844086700417206574915335220587232800373998588094532336448721297757,21537680614486477925570839538957839593006098192503694567393749587557940631967,16568393458463797316294547173419555682646841229029462217197639056287054602566,16910235738263410812877183305130636228751042299094737782744154576712268208807,5629150734321853465674510845327410940323442617216962413835214171701329559576,12765131184498380847448550948920304867469527623961001350816744753387093810315,9954645632746218155245325585480173993199044803581756137160936155060542951690,4353999640943599221118281386228426498583991413938542575297776232303344359940,4598711079993417664489400987736110506328223791894077517963275447468098340703,17317745377506102303500052440899062192892945727209124468437255966617200532771,12259326473392165107331141130100680225887121989921120777667514143912156322366,11811238683014115897858309619999599808008425203222607881921631505596453270838,16699081706307776306233318220897168744889069844294482997417168581249408879966,2568026780472621467236485312283731374848886964214142251868040165224695316461,14887991441574434999687627633546581501365901473545173785249018184685706196387,3569299155477721143892535842178855295807355615071744617918410766174933059043,5498879700681283951662042539400107058426136148099967700430316029080607629654,11559660278391175834668360323261696294263059777402960440249595574565141656556,2245933817469402341452987887837905070237745132811239554297372991710914298182,16951354954717164970902473060335333600574402706601527686301478774700332367102,21515931335312240603168050753263038826093559960430063520103206567658032925825,1249411708644964091210440756030782120444589186855809089574669034358018078687,5918980335509160299664261285796224662727132279493574691223062837411060350013,17739377184579332650035245294019601185834503109963479023132769460626331642282,18469744224495747473457470133545294362819142862108342977835066995529981406258,5759336781416534390511113561800934668877971293662332789437681884454072500101,21332416097583521698710421619829192185814871724795352151990455290564854827164,14991738373834450996520664429440490206770501447625984036209559286781489862494,2292383959319987392245961291693765909376521855421393945872334290076611679644,20271880109317422113691100242542434637543023179088091376781918851828907851136,16343203714510839250939280610780086672320399980775100100207359519193914733737,19668001496569040779289443981105684833630116796777138243208746501411413314400,14867270521039301446053304216390047301289545979306959364422905455339336587211,9929001722154986846461251622116577110986506194975595510541659282347340459331,2420696236635890839197290329114608036709859071844599545644710485458818798726,7023164250260724184662962208964026963022579890290101367655364067452762770181,20508512038053113727358039673385440054337319672353371627416928672143778575477,824002554707189532054522614675201805472052085843409216867120989167259938133,8081396930643908204119214488991799751072819763127464506132047127093449268743,6146669896192112367311424975035875525640347544666981144388229137148737996133,13917552221424458749711502489369248582964839439204214559672563587245770000377,8550914481815010035465313609214308578203171728075688232687655725801893823141,17861710896808118014581828397113186358973121215643160735097781787683890541230,15595160929818874035046864313228963482705740989418337036962890306288699599497,19810339910854592376336564454416808551332919752503671392907063850461349060479,14234414635213293332305234819580453743707554476430770368421971402668862484872,19388187253394163585379147543203559718098061800153070411989058669962446974654,9996031022330018431773704931033232677865134703871368350999928908636869707277,4533799599412452199761684722747577946145532223581271248962115254510905734009,21793143524581931493773122340799146504825838409926910431529124937257399233338,19692292712401787423885461139555179726227035221831860547833110141089023723875,15361825934066824966062130821388513267446230286103312548685290096230989843672,5736434899097417592114701714539404395501559559582922276628268708302331297718,6034516841645751575815362526363553327142008775019507199148571280847313939846,3103941851061425456578524836013350351780973108926423482048781831843642166611,5899337062497322191697133509006899741055733585263214548357752956989422491317,963781557317112122222004641921550021210279319264222273713987285679221730138,12218612067667826360750451807845242059538814081271178077944945859470451709133,19859087159769083790343803575983864397266266537354870798907672197319357964101,19984410602577911276019354715470427122599274838994470055478829965861962241047,1510088699001180548764185585999030426586790568209473093795384481408826277110,6626530934788897049551186952232009297818099583639020036000874279734503731588,11102385732315753875246033828526944990963999730005798544082045825035822583016,6109966799003077547022556221879889867437672084424732190493586606121191686895,11639465666095459063122039730377449150155515188121884615987948657973378713177,5087119226269603720517452201720024842953062937909041658414079638720935374157,14200979596305023031605438052846373683912540635435718213758112152603438068044,10504614528473632996392119937661213820553616805799536317962705212982659337252,16896136248461578519387122861681641687612480673542507251813953270071486348436,19381803511891750827107737252264239897475475490344583112691529084617905175082,17541407330179013144706644068775388402691308134663811736351559302382670708984,15072973642203756087665519422382641458207399650896006837784917038035882610771,2308847250281515017414251485377760361489324048295236605725148595795546323946,12235376578863551481515043248404435233298457594750687771966106520323367004722,234919702386651406701334351738513931283772159856053034152613436560637774413,21637694258900941342752268794989465303386552780774074413553118735507317693719,5017784917192017182377763628730148212610872485218540677293490321169201123948,770314504054605850178900177028157853527192178178763005605945816624700149604,15876814891128030074112970202145286137873841691080700504603122203177789175573,21396093758862368540558980838454280107203592525118989209906020509719986520353,12395505038782995420136281017345429633379095201006284425785781752730355509942,4615582568807690433357570528319145785065741006112040062899881545600179737110,8043772689074175830138340191606864001269151441770005593654367646112660385954,5087060495541107066427394344208368671085864351635929517190622637786924485857,16943670806889779731197043466545390303516518769717829999301840370920339407796,13534112488771797914884729261168139500575711545907958816183168317604824618336,16825197446319806977233945546803116869802796446301133858223973227155555550786,415637162126135168159032709770391274308945193836031409779140830879628784155,18387406758235678040900363524694503366739497074863830200933011303909731885356,11179137042211084753827842203552443809484306307318317082624519139125401844623,21558283039234113122805760097265638181763687038555764258857715920818106215523,984886258318300688046776785673289560458722425831829175079944141959971496951,15742677322520864401961943379313620949320295584851281667782848443614715444083,4674404119733957791400958869998857022224647524150794463860851329191601384751,8650727403827795422786989886519743572356271096745868930429292580249174286422,13805664248894834838953946033892670782284990791974158822573815009987148935892,16425836039758852245186956621689031634149287919733928973102442742483370034636,12636984265967190523588079564146349074168180793368546716527682276529007569774,6817261026014072560057398041777830163991050944713581458081292224492038152943,3842591846766588833800550804121369117907947886204778461433916219752157723658,37271592202861207450496704231110333036724082963271323982767766566562691532,12329580473492550135339911865680237906360631219143722403158320079104416996484,15059957190605121115530324002634619045808465757564252411076061916764353063726,11049964099753534691591813062197785153610766318641253048434615460367998657091,9547664187984679827610628603629867733891345475510185082362431432235944303887,18137012162384412674879864487567137486356542869085283721914855801046173331814,3685098687651674532509991642879131752314328195366675630043049707942891170584,4350994188192128309646975341689829464702598370274816402210557114155641708487,6257821888636845714306847817710237763041012260573089876542080703522920377274,13253018959425522927774577647502632317700972755867567550168937147898302735178,16128520328840705715994832968486859989808820923410546017533359121760378044520,20170678152633918405966535017048153387865751946705242558406886703664743352398,3126527212972403378701842254033672681067914451311377332339121677604578433846,6867262232134903047018643171960682024396916574079628095990181177262447593546,5158367668931323144529189475506903329651812153505452886267986731006143844385,12754662355373887343223103245500264953264637968818954284520990187567577818296,8184207275666143481387081482876989547621596168672026673494737134509515879012,18182047594483210481213043235431614943690478827150601132558952379296218497290,4111619186005075315994626077421177613466749589414703176717884282581714875444,12594743600504910896656839099899310633582995354714016930508253088263104106919,5906863249972407611468323572776947701049556100204019241509444413033282677489,1980080210708070252092652836439362225685565242001269004929621280778029319218,5317272650834519781155258400716302959016815255066834148961703371077671280690,6755929511172704567967900822149236127789264783942356076752317952971695408598,756653592358533438118443361825151465623048518178327516109550024774438883797,13279387228067311574007940426672455425799739197632963751860641037826906383836,3438061374000905227745499451129047661964429059615559246017344409320261233525,7182178722730387940200728260680152279805701386434851756285719594136478079342,3232238101879637288089008409532896629862152604458430213480076264229233742462,18349073713456068979069801924492847615265826078935260207982474961526062084683,14669461622305417414928378093274931180941168738663334898025953986981156308555,21025953377099738424497295026970813014051167806216418684116056037559447904210,5255626714680656571286256248936450375168592101301691959500945926924371301668,17282802977887473307860913184523745285865757781571388182716814513918008763083,7631811346302144382630250446520799917692672405169780636309223495193617534466,20646156492067995141068212601070346054539051558428492870963989969028947901818,11672162857509134152068238052735772663152403666766041363264045356497052787977,11887096806532260110007600390059506485935624620297229185953255478078857108029,21264877166054737412301473554803422700628127592263555002579170780541880711583,17943121804479032447858025131006451946994591698842739992603829945304217132668,21741868983463662771047103688885133076855201341036000119862339617136906339944,1382607011220387511006322153920014038613273342046755883486188937618436917353,15178143370568504520122235741397126257210602740650018201900729283546561696689,19508797361068986472532319429763120919434246449052564653746851758275251767862,15432472447501574952637182729640656917161000067956855273526749406835661136043,3646314932117173966129769917469131878046956851972292537742853525040261895364,9954239280150263233476434487622548184763162539776975088510280448547072413987,2860206851873890237457963710655623849107446413141590367626845970849894602577,7624884329556925103103971646513913063945080531848229875878001163429377892391,13360943796731806773064110741074091445121635972973177327949717322801106153527,11667836424651042501953164038576384835169183507720986280095771344954386965055,11905856768069261907772799745883705412557691028383268959241049562161180720782,12186322648958524087383458213507970038354441682650936942717890758775537576715,6206377886698888214976033056004148608870783801657981445534961772175420895794,9985786843211942401460306610504559890644549482837388550821870421722527522129,7131871091468632512858311810874313071133138864883788963707243539301333044473,6863753977467122978046292703800221264317404999280683794261458513920582107611,21254007028585610870255249088819596192746568962023826736493046170403367390748,19316740566828302369845437096994220205932229807972164794086423967490376053120,20911390901671963410235703071566058542087894960862283015326592608742412435513,10947283094344459246570251013404575174415295611564471102942451430110207789270,6629514866202977686466275098623310374411361176607669574816969946802287210730,4306637640746831336889157874035984930432037257905593217438853767758187627966,17842812026941818985973284751293083233650807309923063938909281923223690155081,20979787799837328650256681706033358558090809594843147876018416522952145532570,1084395234163143750754914936597532036526030294466367212427999310133490427432,16411000398229165199635990982959651490150157098065257264356189234661735382064,19529434083761568271396183578711196610141016284281861529889071952129275189455,16011589790708451889651677332030836112945970875991060135355201890489173794391,18538965510307116327958097310749618403759736800399477577603041239573656036369,575597941676167484590243546673541695594364334533047994047106268896055691965,10154888807896331879146339491538875786991737788606023861857914666322797287434,5751458975032524671409758081174846089867075271579936974413090425599016414105,20537352507069134091732836326103935751238399876923560688100837864640768370820,388393267636951339744357828936678047569934289925965154807382118853267759467,7988929055663996471299857775851374803891818939607048669296465149104280329338,15854279006908524023292733986043025770694447645646628114187722686173514956837,4521251106518907970739816189092928174098228189505033700492425014567434676545,8157530011801905607623371429913769514135441595931542848447134013030997901186,17210220909122096186649472888037140871466614174061205406900504999283153448361,8320732794514386532143557744115700882386234810376915665505736773284988176468,18545875500168811775790253714678031231209184655369087385271022571392488988409,1254781372250935292066700779746601577560528849791669968836092329802026798977,15937651643466826506099692353730922248216886908526960483039790489122416783291,19652922102341829730840072437940487297445121681514373922080785529489772301904,10503757973376634172224417598657275807288376059467419568957007645015644121173,21061128242218898797612547848348324784465891245956046422267179077655910293944,10184102990558905165359578703213338644155257878926023646496853865036973561949,8666994074867894594122739436332358585611317775525945925668413909058593367375,6295777974744736354234904948599345763309384248069989076851179466032501025536,20085880035576919555482594174603593248431976403050445801147514535176924689286,13336325268431575611445366940808804882241012554243123490613520755178670444338,2851570355537839451958385805591947257368741486463662868962800334058987150319,15338540229139367100976188303076834527818508966890772601613851240301217961568,10371461591548028790292642751110580057135152343433828303350260803216047518940,4721084162843564631441880187545375946421625038671651491284453281351611614059,3995968148066851603072141668595964652983129138292929197582737382184727007080,7098475965261931921667649758515107427024701354618287208328785191069896296466,4781012573672976409656547624587641549313089733225902702392506095387529662756,20670752440000061451737406274881546918677944716345491651236710839944182745380,12418063571138285842036790076814486174694060062447109012153384823149675212111,7811816758498775303698763826175925041786332617584902402713486064657610670887,12183449593956360154917192849776155473122126272381798975678273623416489913308,16618893942934404572687811463808390124523121286530811532642072424179325845074,19406638405969722482660214331214972298000686566522726077456272338753715959695,10114896891602590148908922343663289384078633766105057337614271468528428689648,12530180531394196901972330325311958484582015641092775027610123114239686805374,11041683014697540482690315932778449428117122302594146671576370088141482310955,1320027017053531867758788220662625751339386035447221928720928792758652779021,13527787960362675982060947767740337401799422304150087254060335221227857899395,13729174130954201937892395283664312766703232538508820386345658917013576288760,17930242209772558948222336463641867165312462566025913611385142785331060524930,271824668681816275326818116439977879809479607030794905583278884369947027319,21830554400118502077887728598392792929421142621825963621109394022313090676569,6549136256809735363529860847857612644334750418268339758975670928910634751983,7685854228210998769567354902455601859064733599194469796921674884534065104568,10199783250519025166562439623829544304874659364288345176426181874053651581987,5943875072296398061174787119165901172801385563744445220331957391085927545285,13636089974665970650510341064071559084615387545694695884611938887433039781695,15691183714733597776429523227229000727289026713809002490626629956876436864306,8559680887315082801378048339294171503207432568538176257628851229613536726966,18821447832687547445675145256777518497433117070692725937727249438327468662992,6902270693879104513901555672223877604634815519768564032457887408714154308149,12608804561676097764962511762420917859780577008987930524021637882085147011561,7174750477556160125005376833627217199860110410544187422988321767638233689286,8781965602133662570225157578692327961234407570869748187793896100695809894931,2495257954047729673944010345252038964921244093254482708244520480856454194795,12653575930477027537985334989917636556832984698125835912664116078189272484883,19470590483773048893847572401709923514063082100887826438398963400593333077944,11678017778870321267772215799288011478356485408686518093768970488464471570815,9301784115496434107640350077213193580405719087632828834385703690626291479546,16099421215741601628246289398699744194733547679841291314995675269636375173366,4867605962743281143953362108297759970476738545503236589613425112307423983682,4859206625232481008184446590986037965722621081800881620559019195768715084241,16443855645256733949926481287606183123363410685496841842812427755007713532892,9353805991413463049534222956121131872491808501219007024034024595326412518624,14757310122557726344690376086282772240920466622515316103858910465445116386412,16114284659120061956470765697027372797086020387576070056735297826889023849274,18127578981196629851526283391389653885301579188814495702848892722544020055239,19887508599212070022669423370158309019634146887428772891372609912344825709907,17077080577854056476313617926548386910187074435097123438936357029443634140037,13226301328255541197539849574625779242079524439809722670248005223174137129917,4960598616057280250789993806465640165902417481299684068727179165412382990160,1556369617946500605910052041338863524761596681612901076288655800401759143728,8895728155072279486251055328673751534060735340135019245331916382281698263288,2289316141803713796617375788451106287296998047295030310234564594074457471782,5743949466604344050156379807720583796608463915463812355649877415948657877907,4559156913695113135073666675680811432586708455776982064075705161369076248306,15885688417651643378493200422346595912547116850227590423936072108251702846077,21139883658951849592430718453383511736537035608453172046329191674046781461328,13189533415954149093943176775514655876533454488327933935436293535694805743518,17844001788757965004299951292259913492254300676101367510089343929865197748634,14359892033284780014175740986504899257072848573639227540808851637993574775227,6889876198036781721490463051636227217181360455045088258864933221139868422058,4553935378945711471651589030479778870996380701114996688086418055402491525866,21810472237273957206786186837441232294905360772841197216403531161190353859134,9053152935239668672905478856994179206897589996100634932367989982680043213185,7903591118665286176079138425128951407213501136276774569998580497121699548452,3172076359801796733031209099819054888498110723937314354878294115265190182330,20407097360746745587552307442773353270033615342704398250066232913190814364080,7972160291863108260254701271534596191348694866685225653124288422099219831356,2512979638327596184144169725891221385374685508088897591186666227523755823449,12288114406943148383409449156486826621388266177895423682705260002640229785204,2564780208026103504658010005943517057775957652807715289383367743075323562762,1819044074894043026843741029300477751989386054356309111356865205713103547767,15212165170979376853314159201892286112393022743512259361106527770911103031833,14546339564581115494538806968483958415473632518920533358183015375037245948160,16595063968058690402196826920205083730698910363019110917303832709685137640608,15141874678776355759677532828036793885858184118820760885539425739465598163481,18904695587436094037528024957965408339655627593105121455062940021234808627517,19691835186381553427610210595631576698057108693742599090126967830113381498354,8924094782966746617987215970302687574282302360164926405994916025579749820763,19703754039872652879247596753980834118500205932499483040527802680246732547089,1222369520366776525212393255592594259431640497623436777492426726914294313696,3172344047869282929514752164510333501174713324035401216632890990510873753170,20343327187307675920101255252384731549311614062918830229591450503470004905005,21822953127524319865522817898285572788301109254914611303940997016471607290917,4119200650145180459943542547991468255860361677520024595215679941381226516262,884147971363709313208000703986053560492302821976778288962675801741886201394,14179192339259619376051698338290832703239802203346051877647263334899616811424,6257894125748014033621520751032796530871364895580315426488126143829369988797,17601756798422918594467038792255913560794153830062518652267418453154739852356,2915639491551461190644833247357672612074490352906156209159755564104341441334,3231102949049971084860869512445280179160209744399934744399854930563348405672,13021414206859086129077179016730508855909534243359809624497206694614763740073,19605385510680022189244399663099114503798708854480688481468264949015383978657,17021346162472827600023529413773560471771827295900312703532075252918830714763,797420759229039341104668808766016498233266139304135256309887013677831743527,2664903618363391534009727112222679446988960947334573306133164042707563086517,3385549618192271440433411525547058485954511711526716925876581944420956285378,1363918352372003902477247159358100870270143261694504161661979865477181878601,17725129391688775312434400553484246750421349715293800612810825705415551685950,5565167518043825254697387383458520114240098359236753821784350172714709788630,12992626143189731743865280272360549263209967124441767673953882659571766635538,11778225061486552005541072536540594809710403539663018251279263069564781285228,14855802626429861561613008610208237167206379805668816510881008293269978954622,4625126357862179281586979391899300109486628847801168774082540966299465334987,6276441096446918387723860737716070503136385106381280295004924708881687527278,1795411699207968753627657631153296652726915050129212264930465577194539027180,3713335398598470745490569816543380122933539387356971485299483223125101783622,8168117481656071903083355331291793306622574934522412245021942135108094609781,2572110912790333345146174163319527254651486901580412685997510630243717870169,7025592394229454054105021012166569277499787182283497117950324822835039311263,4277841334216388876550672363276475272389275617444687843049115977026804420380,13307361877516070836117482544809649307840244674059174145753388549462990581425,3541353704173386321602971434547681828071166901335602064587889348895191485268,7930538155879758019336102161941128485659185437630747910453735785539584502699,16450196550849346986145420593545138121140944184099182530791513972233505276989,20317647049317277971067996601837330680914292615460278222929651175763284855258,12350794170306113031197271161768360871903372891508108500893141893703359009096,3619108225491731892480788907918892224372271737626523316019551923666189881560,7777524276793695474644184635794903798228263960698425657257115554422141857963,13186962355302544705310483262369096768297692231774754772442065918802639434148,3194922763633786447595049582526939577788731446948460263029416154575517633713,21764951733983707370163229447076318279945301269175491715317016754083795809766,16974123712053830964644120202072593533882217585039161631414357628477067270637,7898037946204257594215947941255236785530939710112474014338432350690918260891,13624131700578417700359325726622999876995826287578399131977467236788609909029,711696429159123395134741628515974061981015372797792603239801873522576934606,4454694656802154477610657384658122890655367951456133773797632953453271645583,11258512209244601689743240316900203988033840864814099786180897714348264963892,17104789493255338246571119977680210285205025930099647162805883642403493155704,2453935444829235217884190831569908545427042660161097975703593935054598308172,14865321440470518031331143407868649683664573698762400527582797926467679386433,2136979677653477082590579842429661891149048368379361009535231454875783700576,4168503404348819959713764969732410335826536398112246387116198899646877476352,14962916637001251079646555121263487095246900845890500033998976380566908488027,17784806976263484298477702017969482877962979780736193065620735094916915015057,5811232683701857296108715612406368550641241305997590112572736833619623657335,1137391750177492513773516911880446733365510948924761786959001414998578780190,10377533661461362184186134231677823404558478220398261395966741229154302153880,18289640374707184240721457180013244890344288557498104400868875166742835064845,9860550380532355283228261241815983394260110595913388936133793178666677861361,4874241362571018447675014656968369345960496639223360836208429603461250621707,16865415500549523957415217905648921092860879005547743663493860402980518775170,18108918097362824701832555936428153547583210042204293837516231255476913995307,5814882735302537469013996470647050035634690283351899637246825700230993102653,5547108529079575186420571231950116618134926722630598104799502651040507258925,15206849009490203249915056590647669409740170384956300636367240071539934234123,1640644832819090575801198338202018591671247888384450305015978486631872758131,7653538136953954504326423293731449069773903668694073045541918594328126765475,15742666466329712178554069131786945235650635594806638864788722339397338233904,11117991054142148551955400250530241420008368948211075786946321189997485480110,17233487593470788370048183367208371204821743424889641470669677410605695176177,1026146833779113517033720464553035587620506307190537032842523110750653300409,10367733177218458884804949015952210383318098385156812709591442491050289560766,19795952047370883108661392932328291359892331001341014799939338429402797554384,280679929395977649114582242142346138466205172264485418126097892277002431011,11242092785741474644852794535567939603118987148698147008638503870866024069513,5042585848515676287159684547630780418802525904631814404423696800729724702441,18076295265515176256373769387621576799326851284582393083567912446445089657195,7379637951216509909219158222610656534687563904425133806818053082443647546922,3558112975941340025714332950698945379582897448619066846171473836063116876320,9573479360636272045463430387538379484130343682411115582933078720270296582700,15319039730033276973173680817870390182683166144884901717164880903880948070156,12614337451840522588925552004159363860236857822744920028925848657320885223697,11264872143423037953370674414336573063122101340016831919048747444897009600345,63551039484071672399844495086043200468124594386399597718753671627443264469,16482682562437246084957175194240509231216838776265462897558195414149416246757,13173166853778783824789219649923900522843999506901247221151336885046420684780,1129677032059045391430942335190974518204360360119509444502890845544005628775,20501934327919041700769005911882447290880962332107224642437572131655999551570,8568499318929533224876840771639984749494220751421895884374508523238084517848,21259500369117112858046793730986192593905655365067722159200063822227414197523,18511737784245858621248028192284641888665848600116211193811323135518967443130,18603594203971848110309624617834986072777858306337940642153570206399896731227,10817810567854821052648176407774626914880746517118466269332776843576340211709,11799868341887426863553231699803195039814149532556595741528976577115279703638,3757945008672794110380903983621818494776340526769633536295923729698796873418,21147309772231799704776665377393022398575359474581992532654566514687692622381,10106161080097685505341186856462439849936096425798398803226308955853233801088,14262263816750661321610690116851316864336319623922717953366014185440110799541,15141933436196205178645622716666344645155868155385407285733185900575537844179,2528094772114073897461542081006497820213677180486542945691028610950494870091,5348148742466995347556247741747876445951253226718284728036059196493410775291,9450763449774399387985728640759709076413273047954552646207186077905960887466,4298191617478880606290362740003112985908172107645583722035275913358222519724,17030410720819419348097350980058866817562528502379090451415524440163140111041,20216724013881673832814480585345314476760112405406761404693215284600396014822,3030458477787500523997196317647453871345579139634715247165773460115609582330,4498462169050723804654682081938858063245557243640516301148855502903911071559,21824371776439248570562107317467644300343374167209593758174011062336014366712,203060629973198497909844961226448148781283822023116446785885526153889141133,13138719392503582101372758211337939905779727766832919837180755391232674501632,20854865022095468190800800251894006373048202378274232848293926367900444699099,18588694216199791340977948229034824338778108765317256872571104367383806683819,2107723674718153039822163382990954569558924075626979445723435572951885590282,17271751087973139804430243764301653129405836972234862722312699991367221547648,6601353498913454241063626951167220829716071681800808284181512008975791453478,12008446685921630692928691914657961114819560167122558958661337441533504934249,2546793791363939452366278657165405700949349144309147725354170056455546924821,7509639228703028871971491982924543490428017835786144030628769546327315651842,7823420836979374535855612407590511724416995784427817183396908887631615569374,14440328435891567217327191606342183091806515070572157964854472183381142306857,13108790694241576486381404587677845524627865147145072471473988738194261674445,19983383938241398968439231728950534655853676209193309061102635732967764422018,11284194381233971884183176274626185331731276627680969047259362251065411330490,1897088360814614813239622717000987185543144416227464749796311263447835372290,5857538086726776983838909617047765193294143035705320425608254315461849915283,4535962484854275896801499258204616949002112470323390523101255172552516276853,11469688959565470671946358524828946654780293319597759366277869041848383938506,20012499472065515722935879215306365340460493343044867272369823908813586319215,7237913775106599492643101364689422933623029044428357142837972864389129948204,4449045505867908852965142075471111990333999619831208332535528566178225482875,18979580728127588847832634342765381189070401746541099544183581604411319882119,19208895793797113211677254952138771238229741398313608749033216609457932026240,5693339887541566707818870620263679026120058867908674300592248504295030161683,5766336473322649734565794453161873006745293312886382597938223884039108263098,10170500372500319676592379791726967782477062446940064561124188934689788907641,10715178415744481025577257316838846623444784908902638764026977772991007652177,9619234464729169347469055561718306819745671419829947117176160764784203967441,1725396226859654685724455004555068750501182150139117204170589152838896682582,12812488682187532465982035305360477706619015575668642434536603051988822585780,11634913038840687277143479351580381035995147077852960651195662158592298943782,590921624537670966145684975359593307845422616174883518035926979611039297697,6994357700776589034911446516222866144704328090940819982199063011389928815878,3578735612848960352693685408184960756564585180098599373883079061082850989193,21635405933646037549623279995086014983969914199701848464885184930399308788578,12427020649229929152974948764411072254994310665316587507041988661972823471907,5659276116329803541059701770846868827421187991242679567541795719989019960482,14409569205409757172710837837486699395207656272569912916147975142886221411048,20174498258690846561506592709929532887311794985051466436061305284714705004116,16144749571419779339987554753326186342500618892721832987727063682036648217899,5806868382318732909919594488299463205875390466419224655308941273678069453955,10943981499006299439884803446608501609107021429051016441936415463311572940454,1924938839701254827227113595273674646757106690922839787536830436278569286096,13979276902289154914577571664895855335838520340557113744304695510562836235170,6432081587087260245919599999151100148827877257649626745290270317469081484560,5063153002404552050282559105432952932908381495673902142745313078991883601735,10740439837861405332126185761433228439796897508030224612484767505999462329793,12737167379130609027705740172196108812439282784347836729589408028420120550933,9849845512381592257963507051167559787679646439786540183276617129759373853388,16005888832870175950940829700448047001850581165998249926419521156267014986701,14353647838770412975928759605442634240665383526900174470441397150591603642336,9246400563934815769990941385821129793696094365581285133233487333862515377594,15148965960125250145435338272790355289745702742252704183388935133186551786499,16453015856957375440870560801879892220374643048047546023962049108638908959772,19594591292469468407344408128396176069613863801953800169935974455228391704047,4786494574332708919915792733222077450535137127349578261762663721149074161698,11960730258074073655703739602687794653921577208052039888289111813676118677358,9848013027466807250590439150605527564079804116846510943688041755058752584380,12899034273953092771018315472337883592076632199623658827592500124277160375343,7444799755957099892747756300128576168091670485463138298855357993349282405924,12078602067619785815908569606330383217651816461769668980367782310218465279082,13207091244585343533434026539671489949734093160191356902826819065281696899279,15052325250252549646358568907141836154046676521102037138442805194847473405285,2221581370746975227443137026410298234625504939466881398515488592571828181681,20243663867674839549278772384366563405687275170339456055149452630358919741102,9989690042997457961300135390803031791688603090074435089369924996763771804683,2394175383139107454721858241476296570939299158552117381451586030928104650195,14935488700038770608988697394320688627203362240444723637257364275046157727507,12264662514829291661352518974189445073203160920355111833291657311513159477694,3827639321249325764386581723986872585672536887010319153929792264348424272953,13487908627465024716967075008462681337662334712641104635432980395748705243220,2271300450003775887579228062020983806396606091928055215698274988642377017880,9536464905154879502929074042077088011040150301676217212058440880221802373843,11224187363394886568032176392622806663752975492652881881608898287407285044670,16348011463839183311989740909923102224397330137023072134870626410011917574109,658746784212845073728972419644775580738462236799285816112006815020578863053,10913847351958014923157235635013414182776322060119409210360083568773647202922,5174660898410477334415120015192903322111803813558785977142572971088703464181,13435625677277740540867428279095038525759637068783477185816475988654675258528,16042236961096516425577672868221946711334425239903980281947225696871186016946,5966732498522491800452631630164751678119619125003570554878083612603498334850,19244421524004466175382168721538493986709062021717633087544245374056859990844,8953835349510092921386508744116096000868233729683707705475555286120350297772,19400107730527891751069598685513048198266948717144299472180340676627124394816,1788315965311520067508595535605409766732846405132796308898593684888230118195,4155306741635339863500551353079678816173576578036039224848730508326156410064,314333752297483020587573946457568012126281776266668278461087690408622762890,5814056308990522321998868808930979798909264311720790843253044589964499450995,8139572664280730177398240130505806903517588262678422575082094265546418213115,5891945033023051894996849367995027817716659752927558196235762187145542665778,15816119508706283096011330636590931848201515685282376441014894443298875354927,19765585883129509218113831432898646175337020355613337867993568030797990428267,7571142440759701899321724284276618755088451471808734385481644938761653631281,21372154727662886563674173359368281518527052830463392775221052936073944196548,7081252182490962865977081179238366944226264513969472284114001831030270956045,5223967788855971504613125877205268444815856778995847146009869071113923642838,7616031404430100022715089975212311635761004286094499406826744277117238450802,2964922410519663416704982602737862878081135021433460716313695716253990013571,21452022130413843576926752262576843465698254258090353961686699256674273446998,5615506565720477707126907662373732333382367798591588442255590186949548315516,13758529852543878424689721858680184284389257236387722027067085472062441696813,12270911407050929770266474860904788952698196744336477194920983584641315683723,2263765921105974400584982144019036516750696376273595921030243162454245412438,3726743207790008961875115608784686494039367610419333613620227882409630379219,12237143845448219572451550465877077742264329541226110387544727976984528388742,2409964261853228751087973651622025781333933822306168735290950339250464395333,10085433407143766997440158468408095154887290417940533218330090781308733416929,21228510717137782368419571997756416328932321564657530623869061270948157027291,12056471592273332515153939599576024781202771932636795778229482480420755693571,18213366556788088673353762707270651486693693110301565439057413547158475404035,16502444929714671396753943873426599559613041594477504659253173973027014569781,15099656057998038622782214961934296168421711158711759920714280998215172598701,20662687648270300297638887955756931826210498273982273406811895752232434295545,11319823310823640550774639562916849455005127799420683680222546170719181512525,343967214752520057864245186069476394037815047607811439097329864410341714737,17503305564468603693734885462989691651193248463782636796950758256530838277067,12741605036457271400687978857670758064474033476970216981099556950125969853613,20739683061558313403494347679816765721522415874620086168947803143944678465016,7946584883804172227025447539224245968128890222556746649628342784345139347190,8360187202053456670989734732945943173170474770371603015342370151451116337951,20059356712109588518115933733238896878411826141623495434229710888297572857371,8908929255369499016159063161703140212756115979036668550222341666828086389886,17260316215848220480068274186000229981635360232751196604952216075987952224195,16051483806631795891066047812303438046492064609198644392699337542232076970683,13616797129917979734082711158569544985901822934952385632710806021914842733604,7121878885265063724099916056725320671644022545379534508159519935129387437912,5095784041111849236518098036393508072376638346067943869740820917637881991288,15064740101319510049989912367011238454044423307266600930402588789041306100213,12407265211081220177754043474825255990635653794940031741483370307852381609406,20223426484470923566833281385864037127075416246760538371032215131656571722149,3668052915108225265616930005001596789890471435407321351170819088999432868806,11366073886283256473381607209905269811061951337531274662130606966429881340996,12582247379355857288799702955077607346019480970920005735329811307693949234935,20186938619235157734865577521404397515633405422805778974853873925656656294650,16122019959033821849412382360062366364664833933984337294691025029563985515365,254648902211450148074737989547563835748091091484232032343713819397130138530,12172833228273710344765296926585753189586602769025493553315361303084014018635,19945409419975886341220734130071717017479702410716315294907303154809664173135,20712004789058289094102947689666173023011192678139675809444116843756511650735,21105077263104009643989508074340105423304108979860049556255519287288188396634,3538342015671194745411221642090452794460666099501316339752121561502241774127,16008085602703591565147288064897579335322875565262127586367715180903703479852,21422197449727241817827580893411034314307602976542729347805156844487333432241,18799547353759539084890273894754702756999055145524208124647385295339036997359,6376647829380850860365386439681035038162788714588766405462355210239582784337,15847703763893026451216792359491847622491103863033823028942752373064363683711,21753518314824757010443592444509359716445873322887601064788806456493419038035,8018616956493930393966420225569393035642655431019891986498475494315186954398,11747316959744110931059298678334515105505609504722662598929370282308351440074,17893257331206244838570586905501874457956496735362457086282197258342214145307,15961328802051806619901962582575367866289226289028087772591680471434203677570,3236169926687880505076444874746358996739587258202752103445199991661738621601,187795190351727293099714304116924667408668969503996281039583636956966649638,239392318624502435385014551926381415338676314268675338353695671324466753801,18674319341781941734600473869568608233805776945980535084119278717005726916471,2771345443147472606857365655976656180452504182686204076714773790025740827296,19450913042313320002652706987083488807755986380163327474873550819278969177372,17088122609555961904069874590098938791545854926952758736324719542173158272235,4614324608780439388145100049836115973615823562529414178724078049067318464093,480346578559945500918475024651677711916332481019644166207062710283884336501,3976896258432286534710425248577923525874780501683135711905396303214796569813,19747713021879142821191045416534012039092734284665942138998895512844748934520,18114341948852128544591474427791645861453096798290403362024577582905309063343,16389740922636415377645046847550552757683160597807953014971200028725848855677,14347956677754622309732029695580580261895229653511993172444407254733241454730,7001790022045736128714608604018732713668075078108360908557371520612055210303,19272993806385013542500911534969336370461053778032527920746797814743961064937,20666992739220376856615766377753030050985727426420972006419425641580077380709,18907720165776367637548948232402401955322000052328805042740522159109944714138,9414327783699575006459158047005978347088459439117502202158387157394567126641,1092342932834424845294743018087259301897007735031966382725140810717192908054,3953337326499755715834998572085254989073834902724154050737740470058759118498,11743581671122680453195477167432558941219274023697487318378655108983631999472,14292519320039108746758578387893135567048390166844266988895150640926606231575,3463895766707893138928153619402823425980920627031760477180165727285868840115,17329024693549080975670914737054013479227561926835421032215803061920086593805,17069029917639740020306921281456148921331852897276386771126788265397483239836,17757973687563632162101087414879272203562112761746273122681647748208587693311,4657037101807059847480820087972588696422739806756490960821623277361176723008,10031688077390763868641078069309072895683953752120759377432369407780311740458,13372959422785941027234359900894463458148714364727687916236363488102034358213,21074689968655856473305620806477766182958744184789493409758269023421704332636,19863757339575916461434905195916835719746715041076078424686010055572742030617,20973060471220514134365115793881078818914475917880454352814198678201263612788,20786322802664930407040804724442246307149058272537433665345242730163006184858,13503324543441706240017837835235888103455201530371938269103987765298019164241,21516545371414182695629550949358554432241582789246093981854557932438611855051,4189468076924692882857105215398697213714749255613940842113064700527656187139,6356916718613787191898160559615069566270314091650855868585425220261360364619,5420879043826588690498755027108627480358930425000012254678542105050717051191,20559290756493460657385989162478253178529811977588548661414171937311774738356,7472237964286313816282734103247675024752524054147218881654824853569171740182,5587656354563280475935968622322500135733558246449238814064790207486002634312,10477445403396666334274248654801801931117602962284736619479124362799824273546,6964581565574090633894249931196779138063582556737680018364077690424381812379,14818621060919997284977287223747030674994127751231587714382341838934955054844,1561884120897562502024552266455149126373072574485245753929487036177604271779,15924114719216774839217247278498830109576711552882853826759218581616445364187,4632899269214938328686734061038562662617634605056083586217293196683107383226,414275447940334199421265067114189311498845927325050140106659496782723706629,5919841635132642392689439793932385370460582843320887853171556097049171723480,18213825499960993231734509662843099396992046367870190109129172304011496568015,19071949566664135927732333412944575018103341781608323568493744120181505633727,8055738556659889630969832748361502052460816679489752687851823555653740856922,18552532582629910542384644188750599556440125083583835015670173118025699825513,2484657787081400262201491424080522833403834349414361745080712757081157295905,16983418852456608800545535696543676988540233741050842886180695807863040864765,4238493546779457743228884918170815223308340385056120983013226844661472349292,3630132677030524902934720712211822367613329466140887879132884750998038269473,21054939309368014542663397737839771438999660373085660928983975055849174262524,7764728564558131555197022370274162477498111431299751237388301945333560774986,3593305607441900907267751550709584072658973999555174092879673804077111387503,932359123290353753331737736031582956463161520044366983625790109891741693526,4731952008769040870131753442142911445224559732127188801247458162044777478911,1306090977867005427161468095288389390649620350907397989639122170049060845154,7759081335204598570892984361955322222987825766180300022358547686895179745422,6447993445251075592811527795404536687284747599271434406060192746881971850885,8266912047004162765439491557705745929139857757706428454484671294796825044391,1314461175505921794571050454800604608649221187723852105188152934159567388084,5074821468464653205102869421665358795805465509804176663850666382476895922210,587081217806702661903500809062925367993834792468594461022841500167739579474,5264606314717935678144297576598053656417231843504500779254542039497862460981,1236480134248818593225404950925034920588295884010411301784531216110810413323,13089489778236095768305861425107967360517148121020346060932975978601131790499,17291786821946523371971061686693758035121148041300868933078085040228288669056,18124176342257558638062889896829524322479803409217207498687844328613679520644,9905839015283285144616603221521153361618378103985458187286841556656656429741,11809535677454857598311615002421831170743476213662971184893106000202355262469,4105258996829645758179809917480600473288889890938687299484408634005613929027,7249994723657380623014328438319457303659016324967581867420756005957067258456,8317023308476962783876206275099298475926201657427120954368652120829272222159,2011843005377857984465704450777581623363347938947142463422784260490016214095,6478487501062645568595261797056495837204909062128557523543545066559983302854,11332891765024246297067848612322823673574497640669814572890785705324624377152,11310396674827683007586339726668223579107272179969446205517750064367092175748,11099104200525710724155767594487158698174345291601467682384866473391802992487,9363361473795780293736671173763300702046469200956940247194666073284271734887,15151887186592767507545683753579108698447339021705506097120199743211891524973,19881265730819081878858384565138117903272592569639633426872725304622695029688,3011117599368717267651471428189462533336275598139751114483084233022831296797,17520576180525374756578417994075832591962992432186234756248866458711765589626,6155276852486738773749976144225301808688416984253808800735523464178476071704,8631372484444450448190767419844298467817852912545286035361602469665228507964,12205507917633391792796810613135648610406161967483463808645931187075958213927,18222453239521787308656394705559544583576244681888667325435264246411012699229,9033412577366915161372037999993563962295812571996632039862860993305238914757,19454897503553988644403623432258520403053811767663131188695520064462224816016,19817199370883464197796219716426529872878349643708961034403389904486407134637,21290720498988312226623568214384902017696056682729297309424737295532449054922,5006872489582777310304924776769064242968147807589802114955067857036564413999,16420397542367588392786684585727906891797023280517827697299749514608736021404,1300345640934139074405647472243803688216465663235066735522675025627248393466,15474333493788166084607018352361187159147026284793436327548632778313351493399,5141280817333171025837036045163967613491344199994520722703718097693724060240,1674845241197502896336080529694883486542569529162942594482168089081833468174,20749587232360151357799983517636847191215950040853109011833662933435613635469,21065338667581575565163875505871743203827212418043845343534420193848874866739,7051564661861006096495144384640210161011647325580302475305699820188085915761,1121065721208670659965039607998179107433568481023836429952089959263844401629,2114003185799450303041425285829091463889299614202766352631616657722513595953,3334382524507526203206024024777692800878664806770692329489928846721311223692,5349561335050661854855918228516028812586933810356904077294751460675531266141,5703041280392778021418588942391165300974701557007394123618062308100870196445,13673663050707034371520553032876769213055293448602317144467901970892454938354,5483873888673148302254721546416819014852587382013956934541598037319090821435,19318734450985860065269203041456593881321456849029001758521815811241052123018,12851330354839827372437628165464795441114428848058858241484775351172304561256,10041542640844175943995712334828870579034783871076347036534323366252583734600,3589445341963638025665117050103495399260947312205835568650192524332423143081,6240962307810325966231999724200767949498419326824465195783823947519631917688], - [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] + [ + 0x1373c771cdf15121a224f330d84b6688ef9fe0038a3bc26a28e3196578a0000d, + 0x29f9fbda3c999836017f76e121af3aca5ce78bb48fa867a6a95e5b9db387533a, + 0x1c7eb5116a20075c169b786d9dc86a24ee7a2525b565bbc262209a8cda490528, + 0x21a549eb554f0f859f61d68f1b6bbe9aa3449a6238546bbdf2a1c308c9cc52e6, + 0xb53fff701347d1b9df98b46175800e0d3250ac6d4a1afa71a349ed195873508, + 0x2129ac4742415c020db2473999b34dfdbabba3cad4713718f95e6346e1583b7, + 0x1d28f305e8b0ec88da37c8251b0c8d230b68bea9401a15f5124d64c5454bc29, + 0x1ed301e02e3fc930999fce6d3744c23596700c03720705939d61cee451faff93, + 0x2edb1832966e34eaeee0903858afedb13dbba9f7c802c83ee628530d0e26ae1b, + 0x123daaddc930c65fc67bc77ca8bf4123fe81fbd0501e8f89ac31a698756d87d9, + 0x2bcc36362c90210acf67d5fe21d53104e9d5478d057141d3b17259fed8e4a8fc, + 0x1fa928cab5938207e898e61d99c7d616269144f7900815b17095f7ff76e3c9d5, + 0x29c2f1cfa72a0fb8f53a631e84cfdf5cc18fb426c254f5a905fd3e831fc7c837, + 0x2da58609f78b29ae6889f95ea2e8ef01a6a6c2814ed02317ae9e7142a29d301, + 0x2bef1f45efbae1a4f77721631df4f6982555d05ac5f5ed215dd25939af5c1b06, + 0x69266bb89813e77b00e34743aee026a873b7e31fc6f64ed57da189c460142f7, + 0x2b7198b043ff31d915deb9d5fdd0338e5bd8028992cdc033eefb9cebf92c9f55, + 0x20ff6cb38e8d9501add93d1684e5420d1bba60394e7c02787a8deb9573878000, + 0x16afd4f19d312cc4b2568dda85d89dd7c834b05b4d8ffabf4410f15c22b77cbc, + 0x2bc96c4bd9eb8f09c17483aa57c5c05f002c6a21aeae2201e882335bedf4f1fa, + 0x1827a11b658414b98b8f76dd10bd5e0fec96568c2fe059f71999ecafbab0a00a, + 0x202d1bece537583634b6e1e70659a1bcf1afe1c7775c478c00648b437578d9a9, + 0x218b5b58b3333e735ce7c88a6e2f179e907322150a7833fb841325bde83845, + 0x117267f052b39319c4ce34bc8a543b13e80784662c208ce378ad6118fdb0ace5, + 0x2979bc493ae1eb3e0df74316cf12fdef6dd1674174a00ae9ef908b3a2df98ab5, + 0x1925313243795f90651c448c814b13f2fa988cfc8895c9a2bfa8551164461a47, + 0x309b8bc3b0ab07525a643105acedd0ae664e53332f89a185ed3d7f1da80203, + 0x2c514d1803b41345f96cadcf983dcef5551b7ebe8ff78f23ecde23ebd5a36831, + 0x23d56ffd6d38c9ba909730fbe6443cb5b4cf9a9702efdd98696652c3f2d1775d, + 0x1eb7ae2f9df6ed33760e51a351cfaa3f4aaeba7c854b85bc6e2b63cc3f2a3dc6, + 0xb3a63736983f365880bedfae6fb8fe5eea0f32e0b398e16d610d62a82407957, + 0x249f511f31c4ddeb74d919cda9133fdbc1cf2d9b66288c9ad13e02c719c39612, + 0x121d3b76e65bd665f5f5d2908435c2571441546a9504370a0f0c33de6fd7e738, + 0x1e1fd57e79cf042b1b3b883d4f4265f15f08839a8b5c3f1802ab7b62d55eb238, + 0x16fefbda0580e528dbf2648ec82d6acc114c3c1b720d56af01c542ed6d656b22, + 0x83a8b8f4854d599ee237fbea3239f9090e06c223b77d130f591036be8209dbf, + 0x2a521323dfe7e7e2cd622674f46cc5d64123113e3423406966ed06f2e7d37935, + 0x10fad028a543b9445ee6841a44434121317b9a163e423a7bd6c0852ec521e965, + 0x274bdd049a73b6677e0ff3e64a8d76d34009e467760819a9b0189a94ff14f79a, + 0x2669e29b8bd468aa3991639947dfe76fc166111d6ff1b24139d2ffff1e1259ee, + 0x12f59494b5695acd76123fec001dd777e40278b7342b34863e61dab94779831f, + 0xe45ac1f353f45ff384658f34bad47b3b03da93784b770b607d22ee036c8ff62, + 0x270d5a7fc5af9d4ffbc6edc57c91594348c60f3ca8a794d141f57c7aea7b0e20, + 0x1c57c847fdb709bfd38776164af9aae7175005861f6cce68e7179dc8eb8d59da, + 0x97bd4c74c9ef8617f364e87d90a2e4f461c57f2e7b42dc48b245973a25f8198, + 0x9399dcf5fdabe6afe6c02a3fa831bf0a4f92cce46654d7aeb4aab80067863e6, + 0xa11daa6724ecf2f75d8e368d31ed437dff1bba0acd32ba12288d4428ab66d9, + 0x95ca5b00386b675738ee39827f9ae5a43ce09cd2b7a708c526c9d478f650906, + 0x1161eb2d96d8f5e199a01fb1712c5f4b29ebc97d5de98e644474aaa34391f75f, + 0x27ca09bcc614752905359dc489829b9ca0755de8b9efc1ccc6d83477db1bd60a, + 0x2f2ddd101005b0d76d47f4440b2de8d982ffcb26416bd7acd5b1218327097968, + 0x226bb0d31a8e961ff7925de0e07d33ae63c3e806ff19f375e8e96b150ac2eb9c, + 0x1e50f8ce5e8e48a47693351bc4c95fffc274e75aad2fe7e6d607d8061e08da17, + 0x17e98bdc10062dcab33e194593186fd29f06a5a3cd95a6bf373e314047ea75da, + 0x7e6d38b28db0d587b13ac7ca4056fe27cc6e51467253b9e1b9318b181f61ad9, + 0x7a06dd6230750e3f59b57edf6b3fdd71a4a1485e2b9765bc85402de6c539e15, + 0x224bcbf9e7ad9eb63bdaa8e679c0ba67c594e4c8bebd2e06f1d736c4fa5b9c19, + 0x14e43b10484fd331ef027a94de953dd133c14e823656e2a3f7580376d90b778a, + 0x21c2c69e30546f53363e24e6032202627228f2d32c61924ff4f64b7b3e93a8c8, + 0x3fe37796dedfc13fa0160d2da3998890a3f20e8c3522c4fa717e10796f40715, + 0x2bd5b2e11cda485bef53bb4c2c654c39bebb5814b06134902858ba1c79fe0883, + 0x1db6d06d30d62c08ffc1c2249d3297734c08dc141e9ad9abcc251bf4605b3b63, + 0x350d5175824d117a97a0c758ffad0d3d23df500f097a25f8e061d79dd42aeed, + 0xf46d145eace6b1dc1bb7f218431ae9af0c9278ac2912ca102627a656be2fad3, + 0xfbd2953a1cdb40ce84ca589f711a8aae5e75c745c5ca4826f65dd2bb50813d2, + 0x2e6fee6ff51b2abf66db3ce9c23271ba35caed4e6893762161bf7283e0c27982, + 0xeb4c21214c0ce434010f1fe4733a327820e1afe53ba7233312df51615d5897, + 0x149a01e3644a9aea475d77e728a2e9826f6b935ccb5de9f060c0a05d8904a470, + 0x3051abcbd422db239b04ed4beacd3b4db8bd045b8d4ab36a872454e362f82b22, + 0x138a0119816ee4ac8015badfe5abb7114820f161375b6074205af54887e788e7, + 0x16c8e1464970e0d76c1e3c4073e63fb2e514b25858bf46adef59b1751480f452, + 0x179ae599e009a3f1027b559b07961307ef54673d52e8bf8c4f87ac5f999a9ac2, + 0x13b3518cb4a884686be5ef802fe3c9a0761950f2e5f66a469df47c4980fbdbce, + 0x52a354e6f8a8c482b9ca8fa51e4732763bda214a65fe575ff12c954a433e27b, + 0x30348154b1407f9bb3b3d8fe8decc41c770cce188d64ba7b0218515b3622fe7e, + 0x22493fbdd06dc2accec415de98a9d411e393393e648cdf86ad3efb60373da4dc, + 0x2bd33c38d67da9e28ff22b4ae3b6e0ea68c6c8b275d64408cd7c0bc7f3c20746, + 0x18ca35802730ebd5aabf25fc7cd352283442bbfa6e925e66e8344345932ec3a0, + 0x123a15b31db64480736ee720631ab0088a24167d1460be4dd420f7cd40acf2e5, + 0x1ba31fb49dbfe083d1f4210e344596a9c61e6f4bccbfeddd88f3beb168921b07, + 0x10c73167a97d9141097672c848cf3ee8116d380e6f1301778533933a078f2a27, + 0x12b2f0963b677d68900fbe2500bdfd4b532085e5cafe9db9c2e636a8ab0c98cc, + 0x1feee9a8c818254bec43c0bfea4e01ce2a7e6faa9a4dd01208770a6f0bbe7c35, + 0x2388c6a47ec73b9c198bf0ad3d5922e3598457cbca82d0b1d2cdbcacf56ae36d, + 0x1bd9b76b67a672ec982cdbaeb55e14628a4db0792bc0f52451c475cab0ecf3dd, + 0xb2ee64ddecd3f26acc1c6c44ef1643b8eb6e589d0304fea3b7b7e1e91c2f534, + 0x107f80d883fd761322467565a99dc8786e69ac197fbedb7636432ec5cfcb2678, + 0x19f0a831e164772368d5365a0107d0ae264ba97bd5160bee069f1e2b459babc4, + 0x99ab87e7b852429782bcaff58bd19649ea26b24e493b243c71d411b48e36375, + 0x18db42f8cb42180422587e68173a24cd0dd62f6b17009897541f16263a405746, + 0x2a22132453db2d68d388b700545cde863d652bdbc5f733c692a1863754fc7294, + 0x2e3f81e949bbe1a2e8a06b70e21d433a1036aa684bf39b7e933839973867ea3c, + 0x2c21f85518cc932c232aafbca1e4eccaf6d7375a80b1542828e1aff7ad8d8442, + 0x21c0239127fe8b2965a32cc7ee8d063eb792ff468703c54cdde10092fa9d922d, + 0x201c6b5b791d42b85000a1011ac52b25bad5309ef4f482e26110310001bccb4e, + 0x2db1d234cd755ea9599fe56001866bb4b711ed049227d67ddb35c03bdb8c6df3, + 0x18498b6b4ebea39d429c25e5aab1b5fc97ec880e736331814a3cdf799bfea718, + 0x1e5d12fcc0c680824e0934a64153a1dedd491ec29effb629e35a45d889028343, + 0x1ddc4b9d3159354a45944b963b54081d3584448192659625d3f06fa98181f43a, + 0x11fc72e4994e6b2e99f8b58773a5eb8ab282dd06ef0607051371bada7b80c40a, + 0x21bc7461e5160f2dc86d270fbc2c8f91605a49e5c75ac57c7ae3481bf1f4bb4f, + 0x2d16510a22095aee95dac7335895a70e0ec56a9a9b33201d94b5f7cb6fc626b7, + 0x2fdfb1134a1f54ad7dd904be3991e086e1b8e0c4d5c0eb80420da5c0fe4b0944, + 0x28646d4e0061355d5cd936c08f7e8419701d959482990a46d4cbe164badafb26, + 0x1dbb1b476c0fdd507664a1c03624038c2cf2232c87bea9e711fd32dc9150622, + 0x81dbd4fdc8779da9472fc7c3dc8b35418c3f670643b4ec8e878c256f6cc22a4, + 0x886cdaa0b431c97d8463419ac5651ff457a7c15673fb88916e94fa55f584d31, + 0x2838331687e032e9ba3fff6492c1c547f685ebd7609536770c09dbd7ec3cd2de, + 0x2621bc61696ec99cf22f64501b131655f498c95fed719edc34691e18154354e5, + 0x2549d455daeaa01b7b52782493fe1b0b7c14dfb77087c9151b4ca36f15306ac9, + 0xa4c236eb53846ff3488a5bcf59fe22252f78a20e953516f22c88b4c06e7f4a7, + 0x10c077e94f0d3852b3e3c2b14eecba18c27b52cefd6fb1a1ff6a26ef95e41815, + 0x2eb187c8e8b5d69de44971a4b370ae917ecdd0286b75560c1d3036ecc54b196b, + 0xb395bd209a15083fb3a580abaa376a1fa397c54f91cf8a0c141ec7b4d7c1e97, + 0x2a1aa4e24d835d8a3f9ead7881aa391fa930752f8c9c1a448d53307ff930d8bc, + 0x1a3959bfaa6e5ec9fa45a9939b47676ed773b545d372e5f8403ce000528605ad, + 0x31eea5b773a9e18aa6a29863ff6c51130f4e76974071207bbca7f238e4910e9, + 0x109a8a86778d80cfdf86b4d6bbb1e57e218ab8fd8495f1fe051b576ff2e77c98, + 0x361d334bf2e907948c05b6252bff7903afddc738f2952a0dc893b09fb034ecf, + 0x11f636b7d7ee19603bd7eda90e668b7ecb2399750d002d9cd2978364b632ea0b, + 0x23af2f1d6a7dbe734d6006377fe06a202a5482cdf7cf324bff2c3eef417e8d9e, + 0x20057e0887d089856cd5bcdebb9e75b12474add58e57e3a77a26cb6cc36bb61c, + 0x2657371dbdb26288e4a31975410dd5772003e2255a15e5419f11e97da00aa5e2, + 0x149681e3e7671ece7381c6981fcfb46ec93264cc242f9a6140b3344aa641758d, + 0x4483482a502545fce490d73674becc29dec91db3a6721869a92856252f5ebe3, + 0x1afb1e247f5795105296f8f075ebc831ede8b5128e378bfc374343ee6f93197e, + 0x23140be54f97f6d1cc5ba00847848e4fc973656baa56ab3e1b754cc12a296bbe, + 0xae6ffce46e6c0bc0ce6341f9d308c792436f0a07142988a937db3fd8a333539, + 0x129231c0dfad986f9c0c2f9868b00c22b314e22b24b55a438770b320ef193ea7, + 0x1d62b56618a967c7d128e45a28062fe7f0bce6dc55083b58374ab6806e01573a, + 0x17e3794052d48c4aa936c5e189fde01b8bb4607fd478b67fdbbcad3e8aa9166b, + 0x24af4f43a91c5c51c6b2f3f44eca59bdc79ac86b06ca092cff9fc7d9c4691fb3, + 0x215075ce41bd685be3c97d2bc28bec174421398024a8bbe4d9122008e6e027c1, + 0x10ff29fe3e761d9f78518eb60b2a1daeb394753487490c9f5ef937df3b87699b, + 0x160ff9e43a764ba2280d5ff675a9db049a29e7924f5ba24583b1d6d90caa0324, + 0xad301157c28a1200715676e5ab5b2469fa39559c1a847f7787abf487d828055, + 0x3409e3a83bbf52d16fef10fbbeebbb40ba299ef770e3640651a48602f13d108, + 0xb1232364d87cdbc709442909811d0a0241d0d8b7933b59471799d6b30a58da4, + 0x195dcc72dd9f2629db85af3e0c9a3ff52fed868038cb27103d9f30c8c70e1fbc, + 0x192d2d9e31fb65b409ab273e7e2b050c1bff596ae56ca4687ff8e86ba8bc27af, + 0x2ad9eedb67e8bf182bb967045b906afce866e00258a320380a709b818521bf3b, + 0x2ddfe92956df2e751715ede80573cfa5308b46be5fd0f77def8a519f113a4107, + 0x1ef0dac6020d7b376e6f0fa82187820a0a4d8be7a8effda342f7f8806565f2a8, + 0xe4d6efe23c1496d8275f8a4dd536bf988a2c8ba2d2beba328f28606a4ca0f91, + 0x185b30ee2d3a166f2f59a03c7ee9f206411f74f777873b92045b6c128ff84202, + 0x19ea7d6275a6dd167757942770dac2861057e16a988d2e93e4f61849d8427aa4, + 0x23c3b4f5e49e16ae69e639b956d48ad6ba696f243a669aab13ab2c2855e1187f, + 0x29037d64b549d1c9ec4524ebbedb8069cb23218bef3cda811134b36d3551ddc7, + 0x2ea8637b89b798a2f731d98f2ab89ae9814f18deaa7effcc9633fe829a9d109b, + 0x2bb4bf36b15be77b7374a026352644b8e70b1ac9516eb87eba7672ecd03f1202, + 0x1006f07533b6e5f33d613b89b858bb6616c18f8478f225af2f4e3d726780cea8, + 0x1749f416df7b4f43257d9b8555e540bb0ad0d7c8ab0a4ae1296021da0d90ec59, + 0x26c86b58437b04557a96cc74b511dbda00e9c4c57bb86c15d49bce318da8b592, + 0x2679dc5e56ae1f6a54d38287c7ed606d0d9505a5cad5a0699b09041571c4560a, + 0x133eab2d7a718f3f741eb10e973bc5e29a021e83f6442418a832b091bc2d6136, + 0x1684a4b71cd72ec3cbee67151c638d5588e3705820c468c289c52e73d69a8fa0, + 0x17cb936bca97a37f63732c01e6c40f6807360cdb73f62d792eb910e034b4041f, + 0x1bf4b473f0c77aa5ac94a46972216b339d99c933a8f5034044b4b535adc388a7, + 0x2c6b76a42a2fd9fc8105378de5176d60c2f8129cdcca89fa0b00f3edc64e079b, + 0x2893d0cb426295edce9b5506b56a2b867eaf48b08c5242888ef79766f8d9aed2, + 0x192d74bf58f3dfad901612983c6bcc753902e2241a371f9880e351150e68292b, + 0x1bf69bb66db73ef6a0e04689e9698896ebed84d97966838113f5df5f5710736d, + 0x1f8201a8020ba29e8521a1a0cd3bff50603daafaf084f0373f2edb68fee7308d, + 0x2fc51d7afa548b449f40ee7c48386655db021f9e34e143c51b1382399bbf6e4c, + 0x1f4e909114c65d62e1a1e466d4968ba9f6fa612578d474e25cc1ea13888f360f, + 0x2957f8aa51d126b9961950fd72e1c7224668a359da4e5c0bf761d49913d147ec, + 0x1a80f9577c8384aeb8889b63361078284ef552c62d2cc0880667e85f01d0333e, + 0x1de416e08ad386d654b37fd2b61eadb5b555e0fec1b7b09d8435bee97e57b0e1, + 0x1ba2ce3d6e352d0643b2d3c5c7c023b6d1777f246278cfe6e1654e9e5413b535 + ], + [ + [ + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x2d8c70035731ad9efba92821a88119f6b8183a362be641729a93d6a327c03809, + 0x7b620c8a78e09e49ce547aa783aa78f3e4594c49ab3dd6f602bc6c0351d823f, + 0x231996b592528575567d39d00645a83b13929093bbfa00d6a661e4a690351d0f, + 0x4e47a72e49b9c5aa3f69f6af22fa0ab640c93fc524dd3c508486d66f079852a, + 0xa8cb4b2bf3f0c5da671e48f83e5c1b3018f0d31200a6f19fd5195db22eef7f4, + 0x18bbb002b46f2e5fec2b120faf87822ca8e77ace94e03aab5c16c4b931739dc8, + 0x2bfae1b054ef2e924d75a8a01283da29103c57bad129ec8396ce274ba4524df, + 0x6d101b19477d1627b9542581bf0cdfab38b05cdefdcb81965c5be00d780f192, + 0x18af61f6184ff85f104c2bef179b3ec5a5d242dfbebe8e27a2918f620e8a5be8, + 0x11e3a7c2d5f74371beb188c6e3d7a14b33128af8ee3287546d12d7777cef70cb, + 0x2de5d6a7a27343dd0422ac71b8d409b43ccb0b672e978f8fdfd214f4d7866404, + 0x227cb43b9818924f2a2588964a0ad7ddfa3df62284b4b3b10199a501ed970622 + ], + [ + 0x2b2ff5f27531b6f3d6a85d75e3e08f3a2f0dac3680a6c26d55ecbf803ca80569, + 0x9ef3492ad19dd1d0bfbeb191330a880ee7933c9d3b36bb5fa02283bae5d605e, + 0x27d6bd18703d7ca92aa24076d3187b6c0028d0b6213d9e5d2c66115237a19051, + 0x193f32a3f839f76049c9cbf2414590698a2118e83658327c4338aa3648d8f7d7, + 0x235d0e71a350f1f23d9bb5182ac44ec9e4615e77801e5aadcab8336aadb1712c, + 0x1df5c9ef694afe61bc253ae908a8f6af0a08cdb9e78a9f322c22388322f16c2a, + 0x1db2021eca3a3624a7d45bb16cf4a44e2af4fae0dc280030e7ebe55394f69d8c, + 0x1a46a26691841c26109a32ae07eb584a6b8af657273cdc4d8a112dea0bcc85cf, + 0xcae80cc05aedb66d6e649b057dbc5ae9759da5d7b43d5e25a400e1f92e9d1aa, + 0x195057af1319e24df1b905c6e2eb2957003cfc34b001c0e54b9dcf2ea5df6be9, + 0x2d4d35acd9f28a3e6bfd601472948293c1e4f084c714ddb1a075f2eae9ce21b3, + 0x25eb2ed84c520aba164e33f0353b5131886c0fbd18e55695541512dec563a0c, + 0x16c7c5c6161eda32c65bb347655acaa80bcc98bfc023f4ab12f5b2a899f37e3d + ], + [ + 0xb658849ce620bbeeff233b7d12258015ea9f87a5390f5614981eb6e4cb4a5fa, + 0x1458de516a534190c5550c6a1bed3af535c38b242eb9291373096ec60e39c1f1, + 0x2969eb5016f24b31accf173ca204668dc2229845bf6446cea007c113349bd4d7, + 0xa5da659b6fcb1a4273e1b7e3b544d2cbd362cac497afd004b8ea920fdb04bff, + 0x1219740c424743dbbf896996f0ee7a4076ba960a57e8d7679b828479218570d1, + 0x134431128e5ffc0ab60136c5d851a11dcdd63cdcf17ad64fd77517701de675f8, + 0x97c6133aea8fe48f3a5fc416bdf5e46d05de0723bc49e53b9fb5e83d350c295, + 0x107da0784dfb314d82859be44d37b4d2b6345c174b91651c65c98449682a5204, + 0x12256b3b99d31d8a372986f95d66cc139dd23e935487da26b3e249ea7cbf91ae, + 0x1d952ebffcbedd26036c54a1e8a2828fe320adf07a286e7f2c211b47f6c3ee86, + 0x26309b52cb55f6ea5a9030b01378f65d2e6b7a9619926d9b1b1e21cba01fa7e1, + 0xa12525f0781322371fd70b0928cce6e2eaaa67b8970dcdf319df25e8019a6de, + 0x27e37c68a01530f092cd37c4a26dece2737868dc2c3519435e1f2cb88f07b62c + ], + [ + 0x118132fbc1cd83f95167cb4473d54c6bd2c417e2782e5efea16e72d47b48b70f, + 0x136ef2515955ff6619498fac59424816189f896ac0ed69b59854d105df47c4b4, + 0x29c67bce04bfd020f4ff7eacab6cbde034b22fb86334675a361f059e50395311, + 0x2a832ceed3837e742196e09491fe23e3f6e51126eab9acec96e71953102ef24, + 0x2b501f1003e27aa809dc9e5cd84976a3b8c169c1e9c63977d7823f80d3f823be, + 0x3ea4e2bffe02da5977ced1f1a6e852e921abe2e015f35b36ce4bd0246c2cd89, + 0x150ef9e932a74b8debf670080641339b12684ff5a303b2fb7c1d8d56f56ab61f, + 0x2b45b3be2674fd820516acd6cc6183c4fae0f7edfa9afcd02dfeeccd02bfed46, + 0x238965d658967afa2bce50ff18cbbe535327c65b0b76e50da30739ded25eb492, + 0x370b757ac6cdd46610eec0c22d43a543d5e0482577bbdc14e71090307b5f69a, + 0x2aa84c1ef9e848a64f748b80e279ddcff871e9c4c3e2fafaaf79159b0b4e4018, + 0x1bbf43ddb5a0b0d2845923b1ce128292359cbb313c5876fbb52f5e6b1fcb7031, + 0x19dd1c6d45298248ad499531f33ce002505458d76178eca26298e39a62fb9501 + ], + [ + 0xb5944768d61c1b3562a5749f4f06c4dd085bb562b838d7e2ef14a21fdf524c0, + 0x18cbfde0cd21c183797a2f089594a81cd828f3b0742371ed02eb83fb0064dd43, + 0x124474b08829d9b717c50884bc895cd3f81d519859d21235d7a74450d0a9427b, + 0x98bb2c4c6334dfea474d04cb2e9761861f6b18a8058a52b619d6227a26228a8, + 0xf34db93ea8d2ad7d1eff86db5820cc7ada47bdcd8c82d01821f5c21a3ea2325, + 0x6e03ca1146705522bb5e9dc73560eeee6b9b4bf51d48f953fbd1f006d758a75, + 0x1237f44f036b2da0067a94947334e3afa2ac4cf1009896766f5b191cde284972, + 0x2082e9103cc45245924289111527312860f6e7ee94578f0118f4a920d0f8d525, + 0x23a6e143284e8f238c4b632ad78ace5b0dcd94a897cb05d1e297b4880e7433b2, + 0x22e076a3aa6ebfe996ba068bf5bffb17fa724338cd67f67ea25330195c628172, + 0x2fe31b0df04f276a525b619acc4a5ba3eb58d8c321c62390febab05ecdbc798d, + 0x23e8c3606aee818d2afa8c4465d5ecb9c45bde78dd819c0f35a620593c1f42e6, + 0x215f5563464e2df6a8daa8c34476a465e4ee9fa0ad01fc4399b649b2e07d1679 + ], + [ + 0x2b04d6ffbaf7144012d92c5c6212803c0b5bcc0d7b1950b889d1fa6f3e56445a, + 0x22757da9e822345297bd060a3f71bb1e70ce977049c393235035677e84357314, + 0x2c7e28f59fe8a8a3bb2fa2b2b1e114ce283fe22a978a3df9f62a171cb1d65e4e, + 0x101749f9dd2605191c1963f25694ae267f6b44bfe2d1af34fefcb65e958784b0, + 0x4d02ab05826fa50bcc5f9af9e396477e68542d076b683ee61b85869d4535893, + 0x14c499ee51925b231da17ee7b55a75f96f462e431675ee36c7be4e9b069e260, + 0x2d9ea99d2d237328266d59dd7e018bbd6bcc7941d9ff5f07a17baf0099f614d2, + 0x303a9e22855d95d07e8172f3a0536d4b95142f962b006a8ab09e7bb6335e8487, + 0x24e13a38f04d5e0fc0b6b6e0f782a6a523a8b3b0127224b8e23751b9cb9f8960, + 0x126851f3eadc0183288a750153910a41e074b3544f0610a51273ad3698be0cb9, + 0x27c1b406bd19ed13d533550b8b621186b1fd47f671e6604680317e6638b091e1, + 0x158880f5adb96dd1398128b9ff339f3d827da6463891cca129c012c06b16b321, + 0xf36d166e99139b9bfc1ac3270a3d98c4afa81bf97436076f57383da50436a5 + ], + [ + 0x29be2a42834ae32de3320fb0ee46b4c102a3d1ae44c5dce152fdeab5450c9c44, + 0x1622805125ddf344c18e351d11e82291618b975822ad0c903efbeada5a51d44f, + 0x165c0b978b4bb646a9ff225ac4900521292be54c879882d3f11eaa3103341487, + 0xc7b5e09343db5c63c110d3175d01bb498290d971b1e6dc0e9a0e9e7158356b1, + 0x2bcc82e75391be4ea9cd0f8a505f9e4f684778fc7a9b1bceb7868bb299cd2072, + 0x611ecd1f379a0062b05c4aedb100bc015244c6a88f1631a456cc2acca8930cc, + 0x477f951e19f531b8434ad755b6783d61b679efbb87fd956e394db9c434e2352, + 0x2963514313f046f844f950ffea80f5e5b424b707f16599662e5a2e3668cbe5fb, + 0x9010d73677620aae1b0fa8023ff1c812313ae9c3bf43066ea60bc1ab477a7f8, + 0x361f4082b75a6ebd23f9a6e7309d8c4e7520159da23441edd631a6ac14c20cd, + 0xcebcf30975b37267aedf521ee2bc753c3424dc4b6edf3984fb02ae1ead44daf, + 0x23a1ac07351946a974c8841e92092a4ffc6aefc7fa988e3c1f7e7c87e1512a90, + 0x1edd7c7deaf249e0fd3f5768aa92e9dad64118b491bcce12340c46f210b07ced + ], + [ + 0x1946fe9de0a943d5a716eac08561cd91f9031fec82da9ab72883c7b218b11eb7, + 0x29765d8cf77619a580658d127fb6faa44d6c70a0f4d65dbaa960754b4195d9fe, + 0x2066134bb299d9e359cb82a8380feb63b60e4b9859d9b9872edaf9152f92d4f, + 0x116a313d00cf99dc18e21f93a5bb198018bbea4b7cdced3e4d210971dd0a681b, + 0xfe29b5bead54c5bbf426bb12844a2920884ac447906101cea9888986a030b11, + 0x22af37c0e4a88deae9f7fad83819910735cb4b49311e0aae11cb7534d0bcee6e, + 0x1d8b8ba772c4cda72e8ef9b19c424d55d57251b247c632bea255271afcfc70b6, + 0x4b7f8d1d5ec8bf689adf12d656b94e15b0b229c1638c9c4757faf0d18fa6433, + 0xa41e5a4421defd5ed7acfd48401395a409a67c3edf4c168ce3368ed944212d7, + 0x1abe8badb2d12353b9bb98152086a9421b7cee17761730e25ac284d6b1ed7b37, + 0x291c0da731c016c0d6c4c75387030a962bf7a2eb35e15aac02fadf530278a3d1, + 0x34c460fff28862ef7a509a1750a26ed1e5960fcb58c4f48c7d267c77e58dd66, + 0x8e1741a97f6348ed6d68f4b7bc6ec8b2dbf03f426769cc779ceee4ba1beb03f + ], + [ + 0x1af3ca6240a55aba55df8e49835b92fa17e39ad5701ef70f8144109f894bf1d0, + 0x2bb0b6b08fc1bd11070edc42f23e807b82e8b88ef70355dfc74e096a7ff381cb, + 0x9372ed18ba1a774eafe1bff6deec4bc0814b0899c6196fa15a7acd15ecc5ca2, + 0x404c0fa1bd1f7e059054cbb87f6b5c69d11457e59f90419ce4bd10bb8a803df, + 0x1bb2091870a4fac03682fe5b1e2eb56b14ad6e48f4676fe41454bfeeb0ffd4d9, + 0x299ef95aed8c75494db82e8679fbc6d5a3d2e29aecdcf6979a9b272a607dd5df, + 0x206aa2f36e32b2b06d6be48ad493d354ca7468753f526e6bd82549fc36cd4109, + 0x259547168b64b2a228941a542f394a2699c081c149463dc2c3d21fd8b2e4f31c, + 0x2fc7d17f3a9afc1de289ad0f94126aeec834498120629cc87c4586c627780075, + 0x15a7e64a5a46f5973e4e82a263ef905ed64f182b2041baa00a1359e7e9c5eda7, + 0x1216f05607e032e49038ac1458100e89ac8519a5a3cee4545b08850d8bf160e0, + 0x223db18f31c85e98e1dd7b7245dddda0ff8e319bd7d1a67fdbc7eef56d667818, + 0x2f4aa8641ea4135031f4d97a7a2f679a8cbca562ba6aa54eae7d32ff7d04dbd2 + ], + [ + 0x81f58a91a4e0d100e0369fdd81a190035342fd0677ee1bf5215e47f8e58c2c3, + 0x4951e747b7ae6b99d9250108c5d2b70181a93ff1d4bf723781e1b938029827c, + 0x1e3a130e8caff9b5e563e8aaf84b2fc73668e351cfd28cf66f5012de61345b58, + 0xc1c216af33054c497ef04381f58582298b54335f632bd62add29e08067a59d9, + 0xf54c9c522a5c74e0d4e0c63611a7502657575b7a963c0e786d2a761c4e845bb, + 0x103cc8384be1be1087b9bb47c0eb6049f85e0413f7b408f1dc2fa1e6fc4af91b, + 0x28da9309acca103ecf19df72a722134d530bae6c660db3c364d0ebb200c2aeaa, + 0x27919dd2f9d3dc9fcbda1a23b95cf23e3630e6fd5210faca6acf4629b88e5ff1, + 0x1f86e3e9d147ed604c71e1fb6ef8459cfc40001bb4fc5ccc2661669b155abeba, + 0xe154ebd50db3c2864dbe1ed72b0816210851b86c353692d1744cb3372bfa72d, + 0x19ae65945a1dbed3965f2de3a39ff2d54ab1dee0f333b88fb49edb3fc9ac7899, + 0x99b97c878ce35c957d01b43dab07f8003e2c379b41ca61a6e56a9204fb16bc, + 0x21a0a43c88ce26effbf8b9ad668056b5b0362e5009f3d80033db473228fb7fc8 + ], + [ + 0x22a852af90680a8ca9688b71ed27c157d02b406bd6c7fd8121d7c7793ad2305d, + 0x17780b9469e81ca70c7cbb4347e7fb40c63ef68f3dde51d04cb47b3b83fc299e, + 0x255543a314afc5a2991413228c75eae398b90576b23b6cd86128665cc3bd9478, + 0x11cb20544f43437a688a7dcb573a7da4f8c7b4437349eedf3fce432a6f3c1653, + 0x160f5ac0b2481f8019e95e0b26445ba64dc03a4be8a15461496247e6ac29002a, + 0x206cf4290ac984434fa774bb0f8901a233905632b793c80b1d59966e96a73832, + 0x1b9435855d6cc4339240e9fa3819c2ff420980d6cf14721b75e4cb1fe57e118, + 0x2b9237e5941e1657efa507b892c3b8dd57fc8d52876ecb599dd5e1052b6b1f2f, + 0x182d8f91ee2a9a26215b35f3c0eecf8ec5cc360124cf6b903e70ca83126975dc, + 0x25528d5d31dbd77cfa6e7b1847f8e84c81c1ed5bae2a51c9e403cc754c54bb55, + 0x2f996ae620d00a3d4e55ef7a6ce0b681388f1b7ff3875b725aea6eb9039d8b25, + 0x2c2b1e7c70fec2f58ca01bef5ac37cbb9471ae7914bf08df7e47dd8e3bc3ce93, + 0x31b369d011f219e4a8fb21df9352878d93ff8035bcda834c3dcc41c3c2df85d + ], + [ + 0xb27ba82a0ffb98368981736ae927a227828985c00c3e5df8c1276b1001089a1, + 0x1913d51d9c71d042bfbf649d9e6e6ea5fdd82b4fd3173ff2fe02b85582528912, + 0x76547449fa03845f185e61578a5a8f2683a19733fc04c73ac6a0b89bebb8453, + 0x186f160ae866e10c4be0ea7d204cd64e57337c60c40b34c3a371d753f2ff001a, + 0x2f3d6b8e2361166089501b9147e84ab6b09792ac17a5f080d75b3e320affc86c, + 0xdd85dcf08fd38d22f316d91d812cb2a884308775afa9f667c6ca80954397c86, + 0x238832e643158e96689b5803b0b77601b59bdfb4926113a3455f1ff4df6e2b46, + 0x202e38e669883619ecbc6a6a45368b9b9a3e9ab67efef50f896dfe48b78d3dac, + 0x67d2b612d75f4f974312d04ae0fef43a35b60ef054c0f475302c55fc10bdab0, + 0x21f0c6b896fb14220d811441629c78f8e8e27746026220e331cceb89a0ee89a3, + 0x2c825ee561c4ab6a22331177999c89806fbc34518387e807c20c359739ba9eb6, + 0x4625f2258edf0262ba0647cae426a486fc801dc0b59d20ec0f4d0af8cbd23ce, + 0x20a72083579059cb659952d3f2a01ed90d21002275b5ea11f209c763baa8457 + ], + [ + 0x4b46526207edc70a0d23c8438bc49a365635552dee240661a2cdeef966f20f6, + 0x2a9e342a56c8b6466d3fe533b89f1ab441b62dff3153d3ae6500c2c3be6365e8, + 0x2f98bf081e0eb78f8025c03ee9c199f2e838c51e5a0aefd333e9f7cfb38f534b, + 0x1e1d5920edcfe9d6b2d0ddb2f6f741afb06590340fc07b182ea7c3ebbd933931, + 0x1b59bb60e986194987fcea070498bcc7c93dd561ce8af5fade754ceac07b1705, + 0x24ce0acb522da527d3eab72865cf073d954babbed3cd1706aa69d767e9afe7cd, + 0xb43b8facc43cfc067b5513abcce846504b9395cdc14df96861a528a52ae2ec5, + 0x262758fb3e076936995ff3140ef7d1b0a1e0fe4240a50747e2c3c120d977f3ac, + 0xeab3f26417e6b53c532072de92d4aa78ccdf1da91660a461abb0f9fd7bdcd7f, + 0x20addeb2afd20e752a39d2f21ebddc2772773b062922dc8dd3ba068836dba464, + 0x754947436c3cded29a60c9e898237c2183a49db7e70e7eb73aefb4b5c693246, + 0x239ca61a6ef7e501810aa89ab4996dbea8fbd47fd2f7a2c96a818e93a3c38c89, + 0x19f11771049b5be81b43ca81e3611f4108a4b9dc30cd122441f74319c3adcde9 + ] + ], + [ +[ +0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, +0x5da987f17a176320a821339189d24ff783be07f5a6adba84ea72fa0d7faa9a1, +0x142b410fdf81d2489b47702708422b35a9c6c3580144e7f3e94b971bf079585e, +0xb98437a312150d8171b81b1891f3cfc75b9d14473319a77c7043d8d2ec320bf, +0x2f88cac82b777c1c7b751129e0bc1d038481129c546e80007a6a6b73c52c7f4, +0x2b37af1db29d45113ebe8892bd41ba43e82d045eeefca95390f4a7f816639416, +0xe0fcfee5bd6119ea196992bc58dfcffba632cb20e07d9bd7f1f4c0738edf767, +0x1f801f49cc72b3cb1ad6d83474b3e98cc9ab427ac9d1807de151ff591c2d98f9, +0x5aba81d049688ec509fbf12aa240297e0a4cfbeb91c87e4d1d72bac8acb33ae, +0x1efaed0a28bad9712571c0f7200ed332ec1342c08a9270774ed84817ffe8943d, +0x2765f7a0abe74654c9182787a7d252f964c3e38c946a1f459579923b061b206f, +0x540383aee2f7779742ca518ed4d4d752980f2b5dff48339c128acb79daf88e1, +0x198d160f1f80e78fd1e93c5244d636d72185966e93e62dcd0fa8cad1b772f781 +], +[ +0x2b2ff5f27531b6f3d6a85d75e3e08f3a2f0dac3680a6c26d55ecbf803ca80569, +0x20dcb39566362206d4b38ed042277d966f03092b6910f3a05e5b1c3071f4a070, +0x2e3c5d5b931ba49c99edded32e4f404eebef7eb08ca9668d82c912cb5d428585, +0x11c900f3b1c7732081074d0a58091de7f826a4f106a930899d3798c6b02d7735, +0x2cfc4c4f3575a5f8bf5f2ef6b518a47fac9fe853558d584ede340b5e32eff61c, +0x7ba6d2ece419d75b37c87da9b00fd277259b4232542eaac3d6c7d85c8677a21, +0x2ad1869717ab4c539dac1f950998c537d101504b008b46b47d239eed0702f8a9, +0x6b21b6e86693de4b43f26771aa347307be78fc9585a91fc28b6f0f802850576, +0x1e54ea10d6b7cf0607b5224797eafc3b651b492aa74c92ae9a70a692a1965e2, +0x23b47244bbd00be19b1c8046145626bac795b4ba22beb692810bdff4794ae97, +0x16ba1b0ff54dacc9d88f85fa6bb69988a0633a3998eff403bd55f352a195192c, +0x2fca163547569280e953a94133047f3f9281b220b0c6334645e432143edbaa4, +0x262cc29dc7439873e862e94b1948eaef1068da52d8bd493fe44a9e48b47b88de +], +[ +0xb658849ce620bbeeff233b7d12258015ea9f87a5390f5614981eb6e4cb4a5fa, +0x2816fae6fcd39053c09df75bc62f75875e635472e790e295aaee0c8158961174, +0x5849562006496b3a32966a1a53d29f1c667a80e69e44993133184456ecc57a3, +0x23bdb40dc2a5072c7d0cde89e1baca83c53b963f4129487c1a68ffa36cfc46db, +0x2283767ef21ee3be90dac5aa35e2d5c39f7bdae014bd63b63039d19b042fb575, +0x1a2dc35b3c29c763895e67b7ca3ebb9c34484431cd2d1080544cee9d03194c13, +0xdf23b54c9ee2fd50b58ae1043cc7e0dc3a11f183ee0f815fe9a97caf186033, +0x160a65dbda0b6f118906dc50e0d5a8e64ce7765f4327700e11e753d7386e7392, +0x24b39cab2a81551d5d529ed57986b8ecded02a7650eedf67925eb9efad60dc20, +0x226f8e8bfff7dcdcd1980eed6f88a2566cd997d4f7bec484ef25bf8ee86eba7b, +0x2aaa2c1202b74f2dab3f58dbdc95eafd2ea49d5e3abb47f3b33cbd4ea13474c6, +0xfaa06fba9421c021c6133baf90169f65dcb46cc47ee532989d5ced54155f34f, +0x17af1f8b71c3656ec7d3262406399866d91470e4b912040132b923f891e63720 +], +[ +0x118132fbc1cd83f95167cb4473d54c6bd2c417e2782e5efea16e72d47b48b70f, +0x1df6a4c43bc5c69763183d36c26b6b37fbd5e4252de4b5c3c0da6b81d2bc00e9, +0x2fcd5953b4af9a49fd90b23229198d09fc8fc8ceafdbb53599b133d01023ef76, +0x24c66b7856c9a5d78819772b35eef0de88ae882c19af36039f785a48a75f450b, +0x1692394c144aece305a7f02749a63a355ed6fe024be532af2152a0d53d590a30, +0x2e0f2af806c4c37a9cee0b9d31be62616a7dc6eba5e51ed9854c1be1d9ebb9ed, +0xfda8fed741c4382c69bc3f63c48c052ef784b8f67ad573451a418f2f6401127, +0x1734a0338c0a652d147ea6c26feaa378580ac91d0c8801b3b06a4f50b580d01, +0x239102aa73485d2a291639612b53c10c8a729f09dbf45984e80688332199990d, +0x15c8103fc31eaee1fdcceaf57ff198cea6eeba5237969b036135084cd15e1b57, +0x1ce8ba9e5353bc50ec8a7cada1fb238a643d6d1c03449a5ad1b6826807821747, +0x13cc546736c859756b596bacedfd88344e4cfe16abcd44dfabf1234df19fb7e0, +0x1dcecb2dc57bd3cb8ed9aeae4fbae4f40e7ffc8dedb72e34c84a9318d9863678 +], +[ +0xb5944768d61c1b3562a5749f4f06c4dd085bb562b838d7e2ef14a21fdf524c0, +0x251e1806f1951c2a33eb6ae39afdf9be6b971da924ae9920246d98bc435d9c59, +0x2995212cf7dab0d9fe609ab9e441218c5181d91e3e2f6c5b6a07800c8698fede, +0x23f10d62357467c7e71eaccb73ec7cd5c44d69abfb91849559009504f81aa57f, +0xd435e4564d33704bb176ee01b59499df851abc0dd5bbd64b3ebdf9635ca39a5, +0xffb4165b1b9e112cd77c00ea81f751e9a2d46e3071e5bd3007fc3a987e842e, +0xc55394f0fbacf892378bbfcf44b8e9475af7e5d7e2373b65c205da9b1b8188d, +0x1563ed24f45a7e60b65a0379df8dc871aaab1b5cbdb24f9f675daeb6fa138423, +0x270dd42f73034ebbfbce9182a6e41fb80cdaa78c06605db3c342c0edcc22e577, +0x11293baf366c075e3cf66c9f14a4899e1d9807460f30af948e44c06d43d37653, +0xdbe92f1d5f635e182354a066756bc119c14060543e78a467507983a74f9707a, +0x22b8d93d76a89bc36f0b5d6a1ec3c6053510622713e2b833499ba773dcc0c217, +0x23b478d2e4e21e478ea7c859da3dfa7229f6a2fa20a2ef1f406d9fb0a7f62f28 +], +[ +0x2b04d6ffbaf7144012d92c5c6212803c0b5bcc0d7b1950b889d1fa6f3e56445a, +0xfdaef081ffa41b2a3c6f8f4c23a5980f85b3301bfc3c342c938199cf71aeb64, +0x33a135f38b760028fbd4b2270791912b0e3008c2007a89b30621086f994879d, +0x2e1eb1ea7a1684486cfcfcffff8c926be2670f226bd883d11591addbea75adda, +0x28bf473bec9d8842b84cdf474a435da4108204b09ca3512d6ef73c19d0be40b3, +0x2edb397ae478291b9f48edd50660fbc1b5d7d906947fdddc255ba787d02b0366, +0xfa157820a600d4a78390b8beac81aaf6e8d1607d7f4eab0afa5d7ee6abc605b, +0x283fa69d06b072eb8b27c7c655b71caec057124aa1669240971c1d04fa881c3a, +0xeaf5ba40262c5feb646c4f32ebe7cd2a1ae38a83c48a04e0c1d452730d63058, +0x2306577578a3acb6a7c070ef0649b6eb67c58224662895d470542fff984f5570, +0x2f204614994166d0a9fabf6bf5db5fc3daf0bc16645f0f202989de9df97c1161, +0x2a93e968eafe2ef56b6e5ef823e29d96b551221e994f08806f148c8d318e7920, +0x2f4f684d1f698b3aef34a939ddab2b80696f2246a13250f8978d597a6a20e202 +], +[ +0x29be2a42834ae32de3320fb0ee46b4c102a3d1ae44c5dce152fdeab5450c9c44, +0x2ec317d402fd363380a63c205dd966e0a9fdadd78b8b9485273b6902b17ed49, +0x1ac21ee4c3af5f8d60fb78d0c764adcfe0c20463b3d0abcd3b602409f2770743, +0x882e85d15875eca350c4e7c4e59a820e47a8381321dc5c7f8f78aa3e1aa68c5, +0x290075bb9d48ea0db89e805f26952bcdb6f96b1507580b45cf56e18c21871cb6, +0xdc29c413aa32c2199a2de5e9605e1129b1e681163b80f82cf846ec5f54377fd, +0x2dced935f82c932e7a2a837e2816cac70bf50da3aadafb7f8136bf973b0d3987, +0x104de5f8e59f98489ffa42926a8aa9701c422e4f13abe90507106f2a5a60f0eb, +0x23b7b05c996c963eaec7c5817eae6d0bfc78c01d9c5da84ef4acde5204c4997d, +0x177a7ae9bc58e64a1b3baa1975c6824cc81d32302740709b0c6fac0ed9fc1958, +0x1552bf00f696b1ec39debdba504f79ea16c9ac75458588eb8a879908c80c22c7, +0xbc4a8170c368a03c40fdb65123bcaacdec1f9ab057747d5a2562d28f4785ccf, +0x2593132f444b3731469755f9a76b92bb29f2e89e264ceb1e2881a4aeeec2751e +], +[ +0x1946fe9de0a943d5a716eac08561cd91f9031fec82da9ab72883c7b218b11eb7, +0xb5cfc2a2895a6f9f5ce97bf05bcd5fac012d6737d93be00df14f91d0e6e8d44, +0x1176eb406c82709b00e6c8aeb7437aee20d0e14b34c91b6d4759d425cea472f1, +0x151f15179f562e6fb43c853c9030c7d95da9bbcc9350b40862350b4339f74320, +0x1d83dbd5511b6cd9e553e82ebce5a91dd9f423bc9e311a211d6509e37e3c8283, +0x62edb4cec259e007c26a95be576fc925088cd487260bcb67fe88dbba993160a, +0xa390e27ae606a3530759c877186ef25fda97764052ade30cb5533f0ae878927, +0x17a961c4c7f021105e4facce2011ba1f6f7e4c18c6522a8879b371bc53eec16f, +0xfba90a3180e89f49b981d7f2d369f14b354f586ca695d5be51d562bb24f01f, +0x1b17b06f9727550affa91416dca65e6940ae6266c426f46a5b2a72201c9bf48f, +0x24aab8dff690a59f7a16863d2987edff9d240c46885a5fe39ce1400c1c6638e5, +0x48ed2132edee472d9b39de6eddaa2ecd7c1259af7c64ea368e66882d3cecb15, +0x3ee389275c64f648e0ef79dd7ef8d7c4034d8b0ff91a834705ad383278f1f7d +], +[ +0x1af3ca6240a55aba55df8e49835b92fa17e39ad5701ef70f8144109f894bf1d0, +0x2566dbba85110cc708700743aaa5c7061b174365a8efb5938b4bcd82ea79929a, +0x205197098d6814100ccf6c908eb3792b0294290afe47949c85b0cc054a60bed7, +0xcced1f9a364f77fe44b306c4539575f8b1ca45758c4fcbfee234e8dcd973ba6, +0x305e20ea1b93c0fc73307f4825e80471da211c98323f23b727919b63e42501e2, +0x1e473b357377aeb6c9eeca4adacf0ebbe72df720bb533055f056eb9f2c13d536, +0x56d703af2f1982a482cc560c2f4f2da32ef0356c73ce35f7b667b8f825b2451, +0x46beadefd1c7353469794eb81f574d38910f72d81431159d4c532eecc18d67, +0x2ad6ce3498864f0ae788665262f8b99756997eccbe50d70338ecd68dd1e92522, +0x8b39764e398e29ffe39a83c045a1218036653fe8071ecd3779cc6e79e643fe7, +0xffb07a9dd49578818cf9781beaf8940764dcd2f07aab4123f4c9f030513f622, +0x2e7b46afef5262f60443669d526b99983678236c8f5433cd130defb06a39023a, +0x13c717906e68279fd9e57e6419986ee2cfdf96b20d200e4adb31353b19a91470 +], +[ +0x81f58a91a4e0d100e0369fdd81a190035342fd0677ee1bf5215e47f8e58c2c3, +0xd94283e58978ce187d463c50a7277cd3c80e044e15729a6f8ec0422f2ef8b84, +0x440a6e12fefc1ebdb82b5e69c461e3e332fbd297474c18a65390fc8649a3d55, +0x12146efb02498c13aceac7fed685b0dd88fbefe8f5993c0cb21b0b4bb85b11b7, +0x64b0712fa159104820ac07e0d2723a3bbc1d1295ab39a108e2eee8230131f6a, +0x1e0f62f785734194e76cfced2e91600716eb46fa4d9235f28e47e366110af98d, +0x8204690216d1d2ef851dee5e4edd9fbfe66f098fb61c231a0e89bbbd9e9475e, +0x20bac589a995937086cb727fc2561ed052489eefb58cfcc260eefd58502b1ac6, +0x1f4bd25093fafea78a9db91966e6145c46472a4ed46af710826accac2034fe71, +0x278c85ceea23e4c040b66e41ad9cd09a7d0ac6d3457a6e596df14505f071de2e, +0x45ee69f0bcde13dcc97f5910d8228124b16945cbdf38db33cfd3933d2c15c97, +0x5ef0c0803ce631e81fcf86a7c270ded90e8127485d424abfcfa7c4a9da7d8f2, +0x12b584469f8cb8b5c200bd721bb2c299c5e63422d730a3baa52274093f9fc085 +], +[ +0x22a852af90680a8ca9688b71ed27c157d02b406bd6c7fd8121d7c7793ad2305d, +0x239a362ac4f07cd888facdc5e32f0b42e7ce6485e9697d14fb4089bb6074ead1, +0x101185b0a8c7d142bb221c50fc9840e9c5a0bf1110e9dc717b354f100b514422, +0x2719aa9c388ab97e084241110f428722c8f72de23a6ee33f7040c781fa5ae476, +0x18aacbd4af9ddb42418648314a53accac4af473cb54e3dad906a0210b98bcdf7, +0x28d0ac11170cf9ad662a2f31d00633af17b9f0e345889ce997829747120aef6, +0x1c76cca8e7372edc737fe1755f75986a465863a66539143a5f21f8ff9b0f8970, +0xafa7a7f02200447c0e943dd60c468ea6d1cd1e001505ce16ebbcc97297d6cd0, +0x28efb92a44b7e421bca73b274bc28bcf74f94c7212d72ab6913c1709386c5e3f, +0x1a03af000cdc46ccc12067c560bbda2a98119041bf9ad3ccd9053222fd2eb4c2, +0x2409f6c3cc378966ffae28eb4adef67f8c282d8a902db3ba471d9540c0039451, +0xad59025aa1e7d4a026d1f819695b3f7890b3d9631dd06f7da00abd0ecd94ab6, +0x7591d69aa28fbfb5b65dbb6f4420106f0b0906151307b976f6baeccffe2c488 +], +[ +0xb27ba82a0ffb98368981736ae927a227828985c00c3e5df8c1276b1001089a1, +0x2ceb1780957827f9d4fac39214a4e82e89a82a760a9fdd85393b285dedbd8114, +0x18259272125382f107a04abdc0d968efee527d2242e263015e121fc4b090b582, +0x10c97f58b9ca58426bd89a59173ce8493d2ea8d3c6cc827ece2453ef193bedae, +0xfdb0710ff8ec599e7ad5086a29d53a9d1834e1a4c71f0b6846849eb0dfc47bc, +0x2008c67e2365d2e73a882fe3ffe416e8e0edf4a3c490dbb05d6daf56b4da0546, +0x874dbfdc6d7035655981f935798b58b755c7a9d82876352cd26244518d67062, +0x29d294ae7d02f2371a16b483b2102e0055080956b53331aa171f50de5d9799cb, +0x2aa10edd36798bf46c3cb7bd749017867c029a54e0ead556e2f15cfeffb4d9dd, +0x2b457a5ddfc105f203eaeaaff9af5149e02c6cf80a9327ed502b29f4c3602704, +0x29ccc8e6be785237b8d99009dffe037979c7da79ab22fb062d6fc1f59d48a708, +0xd829ea3c10abe53f0153b4446f6e2a250dbd79f9ef7c45745572826549109e8, +0xcb3680ad25a34e351089474c8ae39b6091e553be4b67c2bd1fc7a62a04287e5 +], +[ +0x4b46526207edc70a0d23c8438bc49a365635552dee240661a2cdeef966f20f6, +0x1ce71edf5b935a231b0ea60402ba756a4bb45d65120cc0845f6c2ee2ba32e7ab, +0xea85373234c815ce2693a734fe28705dc6fd3fb29cacd0b9f4edb694c15672c, +0x10e60b02e5c0abb8dae47efa17b0582df94a3baebc52bcce8820f858341d7188, +0x67ac96b7ae162e5d0b43715f4c24b9031c082baa68ac7638a00f8594bc3b127, +0x293dc450b0e5c560a15853129e238b046a419ac6f0c8ec19a69bf8c409a73cab, +0x7a2dcd14fb017674965e82174a35decdaad75e42acf3d5ac1a1e235257d1fb9, +0x5cf8b0f380d29befa5eb75a0c032b7b7eafa895d98e0bc0e86f03ed066c9876, +0x2d00dde97b4150107fd9bd859c5832844e6be0d5a99cc6752d97585b560c4b2c, +0x6f2b210733fa0605a0cd753fb6ac80a0d893b2bef2d5453e5f6cfcbc6a14302, +0x1588e892f9f2d3c6a7dce89f132b3dbec142bf485e2142ae05db7fb5d7ce211d, +0x14c92dfaa3a1f830b20150093fa670dbef3c0c807f52321e5fcd28807179cca6, +0x1bb4555d8c5f8bbb268361d5e1c22f9555f7c9f4fabaa24355c963edc263af6a +] +], + [ + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x235ce940dbc6ae2af119016151581b3928bbf5dc663dc5f4b6cbf02305a440a5, + 0x1f41f49e23f371de6ee0539e873506283ef7303dcf1d6171a47311e9fabc25fe, + 0x2761de8796f7e0b5915f56fdff180ddd4f22001dfbf15bfc83fb8b76c2ed95a2, + 0x2030fa119e7ea727117fa18d61bebfdc5945b9ccfeb4173b77b373a88362544d, + 0x16fade125075ec0ee8bfb5acc676076d14b76e79b2daa5acd76fe6719476c017, + 0x154054c752e6e827543db8d8d6baafb02726fd7cdcb71489510e89dd2faf5d5d, + 0x1b492c6aa52f42a57aa6d9e9680c14875ca28a129fddb2fedbeebccb5c83cb4a, + 0x23d1d1bcdf6c2c14376e6619ef855a718aebf7d9918f578b59025e9808936311, + 0x1e509e854698b837ae62db6eae7730006480f64ecabc6189a6e923708d4aa5c1, + 0x104a16aecc2dade9539007d7a631cb12e7ea1ab9fa18e4c8d158941e13322bfa, + 0x167e341698c1e47880a08b21374178b7e318714eeb40b54504aea93443249f9d, + 0x16ff745c57280b832126534f65a36e051fcf161483d1a9ac4d2a882d55c4b3d7, + 0x16556da3145b12699852213b53eddd1859bf0c06464a69887a6ef1319cfe3dc, + 0x1f52e72aec02c1085861bec46d3c952a7b17e3b859e1e119e29f9d55b00a9d20, + 0x1439235c136533951e994a422857fcf8fd137963c823113e777cca92d5772330, + 0xa70ec5c87c2873d1927e525972dfef236ff91f79962eac7db98fec13c3ca6b, + 0x85c4d1ec109d4fe0daa8548c7b641d62bdcad7b01f0257ea54f9e6371d00550, + 0x2f4b2580ce56a2b5941abee8b7f98ae4b89e652a005b6d378edca751823992b8, + 0x134520116944cb30a05c694e90ccfe26376a23acdf44719d5e94a40c0cb4eba3, + 0x2c6f46236b3de631bb23dded37fe4349e986b9c26a99382a28125b2123e9612a, + 0xba54fa736725c45c9aa2edb10e2d160ee499707fc5d3fad092c6f6e60830363, + 0x9fec55075da3b0d949af21227dff641435e920034b8f3a054f6ceee03f8bbd6, + 0x2123de2c4d9657466e2c0994fc75161b658fccebcadb25d03e1005480ff65dbf, + 0x15190bff5104801efbac26fe09882fa5d5aa2bfa702efcd1b9e8ae4aca9f2ee1, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0xebeb78e24789d13e315aed03d6f9a7503f8027ac8c07bb31cab7d9f7c867273, + 0x1a7408d356b546b06ff9e11e706fe10311eddeb564d15f77e406c4a17eda0fae, + 0x7b909e9b3d766c0562bf5eae630eb1eaa3f486b67385e9f15840dcc75a4695c, + 0x2fbfae64d96df063622736669771b3763fe4d7e32a253b2e9a432fd404a5a1d7, + 0x2e8bae55338b9e7a202278022d1f4f1641e8dfedcb10173f8ffa47a394a792d3, + 0x95cf55bf75f13b6986a1d8dc6e23ef27c6e20049be69d275cca08a95c4fafd, + 0x590c80761bacb1996152bdc843ee9bc8d9e1106d6b44143cac61a582c93c707, + 0x2e2c9e1b232536be64e82e3fe38c9f83cc1e2ec77eb98d690ed88972c55d4dc1, + 0x2a0bdd075038ef925104da5f80d436819a8896b46194b795f9ede6451882f668, + 0x25e3f54e8788cc765abcbecddd2326c7ae8720dffc3df2e7cefb06bf572b019c, + 0x2c4e38ce29ded57148964df0816fa57324061c515ed02d9f5ca4cb4231e72d9f, + 0x17816a3115471f4af63e353a891e5c63a1de21b079324c7376c7fb778162d597, + 0x16b1e612a7910bdbb55b44174b22b72b63ccf452f485aadb834a8883f7a1129f, + 0x1cdbce6ec5631b7df36d7fbb1734c066329559906cf4c9cc7023b75445f2cdbf, + 0x8527bb0455abf9205319b4178ac91c89d27d73af39ca3eb5e267b407dc122bb, + 0x295a5be07d3fad3d9622f92a52742786741d19fa1f85424e6bb0383b2b3184df, + 0x1d10e15e892ef5c67b06061e9230a13aef08e3a2422e59ce6a7de3bdfced494b, + 0xa1cd7913f731a263b47880b483792d1eafe766bd397d6a37f9b03bff649ad97, + 0xaef18db0541091f4d0a8c6c0e04bb191c3b3eca9abfe91b336f37688f82381, + 0x2c240c1f57384c0eb11da2fefef668be130079616fbe953378ca4cee358ae80b, + 0x1ef04e55dbb7768b7ed264223a560b7462d131ac387b0e06e091075b036c2903, + 0x19df6cfa53448857b40764ac927e45c59a4ae69088b7bfec231217fb49bde976, + 0x1b794d61ed2a335a1b6ca4fb2df93b5de924f51c742c97eb1f45262f4cee3ddf, + 0x62906482824c01daf001d0b01e1558d7a2e921bc124099fa704a167305b0432, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x1ee5e91ba44d3919a02a4c05a704d15dbd6665d3a0caa7534f062cb702e12ea3, + 0x124e5670301689bd1d21125260ac980aa77f9927abfaf6625cfc4aea0542c38b, + 0x17f39c51b4f9aba0b50cf36cdb63d6485b3f79e0f4c56fcdeb1668eab22d2ee4, + 0x1e47876883221f61f5a85cbcf916e4255c146208100bdd75df2550b7f23d9ab4, + 0xf6cfbc348d0c46f2b4514fa4aec63685b7b4a77cc187f39f90352aeed2d4196, + 0x1ec916f0f8ab3534a45fb8b6fd52a0db612345f94a7d1047b9cb15bc4354d259, + 0x2299e8cfa278c8ff8acb571283f8d58b07285fd3db093f52816286f8059d745e, + 0xe63ae084d4165ef23463637d3c6c962642acba1dad62f5df322c00aaba6788b, + 0x2c652dbc12391bab6e6b1642278935adc57f028d75ae594e23e869dcd807a04b, + 0x23cca3a96c87c09a758f977f1e8e382898bdcc82debfae4df05bc7c16e74aab, + 0x2f5c19ae2b06aa09ff617a2dad69858ae545b8a63f5c730d50312ca740d538f6, + 0x185c013083f0dc7b1eecce3045555f593a1516f7c0486900029a21537acf8e03, + 0x2e4ded90ce2c40cad391f536718a6f107838719e6cf002f2e914ee1db3fda861, + 0xba3626706fae4da22a59bfc7d0b7c3cfff221ed8a6984553a6b605fb7ce4cae, + 0x228687cdc81f4bd727891f41911dfbfe24107d60dda4ea79b5b094886e89c4cf, + 0xc1a4374bc29963f2c4e68c51518e098dbe906d9c3a664e24938a403009ee28e, + 0xb49ed175ec0cb65d9fb76b9dda5859af6f7eb12e0a4895c3de51228e33662a4, + 0x26be812425de5be3e6f4fe6694d8b883ad156e67ebb1aacb6cb64fd41d64b19e, + 0x17cd4b4c75b978ac369c026e0e34885bab4c745ef05c471d7975300eff003dbf, + 0x28ecb3b468e0867e4dbe29f05490b90f6210108a30624715634e3cd6144085f6, + 0x2ad2a688d5e1fc7a853d17ff8e29487e6a9fe8e234b6423425afc192fd6926aa, + 0x177b3225d90e7c43f46ea85579f408bb2394983faa33d3eea7b7847e10b71a09, + 0x18c733d3fc6d5c4ed730650c512b0b2922fa4ede0e4281279df25cb57faf1749, + 0x25c287190fdd3f0fe552c72c747c521b8e47f042dee30f90c88cc49c425e2269, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x17223e88c5afdce6f98c3d3096fdaeb74fa99a0bf6237bb328466b843b5b481d, + 0x17edf7bb609e24ab634349d03bbac5d92a99f1f54571cdac8e155a3767946556, + 0x16384369e8e866d47b74c849496796fe485290080acb6d05a78b399906654ec8, + 0x38414054cab9daa6484886487f9b1491a0424c75dcfd6e69c00f88391963260, + 0x2add2a9f58afb253d9e9729b8510c6ded8cac2647871b4b2daf92c1ed8026670, + 0x2f59f831ed16663ae1e72b27df74f8878583b088726e2f77e2a9b71bd5eb4e8d, + 0x2c8563397614e4c977762b73467f74812d61eb6c921df0b18bf84dae0a448cda, + 0x10844b6d701b264d333ea6d5496ee62b7f99b0f3e81e4774f271acd4e6dfc452, + 0xd90e1221b226621bab0f84164c6bd657cedf457c1691c6492548cb503962f2c, + 0x675d5268e859d734fadfe6aa6a58f5bd47e9d9bcbf7311d928562f772a44312, + 0x231539abaa71d18f3c100449d2dbb5a78c8c6eca61debcf495670ab6881cdda7, + 0xc5e674c55e57e981b8de7f89d00aa088f47c5b01c39bce85ede170519bceb81, + 0x2e6b1e65cf7069fca7f5ffbf0760e5d2c6acec8da85ff34f2c3cd55f744c8446, + 0x348474ad39c09ecfa686a8710a7737acd19917fb66e90a3df84d110b5b26048, + 0x22380985f6c92bddd7a02d0187c845fb834c9b7e3664e1b064ec580536d1192, + 0x215293044ac2044e97d2d06e714e937bb16844b2c4e834bc3555633a31ce1d33, + 0x1076db0b38f462a6a9829ed423572f05d1658c390fca109dc6a5baeadb39ec85, + 0xe0b3b39e33b5f0f7689976066d5aca89f070fb078152378bbe4cbf608330e0c, + 0x1decd713548d0f04ca0fc3af31ef53eb04fafa773cc696bd5d7959d5b8781f3a, + 0x8eea1ae2e1dbabf4e3969bfba914a7a5be05a672d16aee9029c3477ad75c0b7, + 0xa3c813f669fd0550005be2ed025fd263f496cfc0c88708c5723fb6d4783090d, + 0x1482b39a31e48749f37e6cd63f9fd7498b70623637fae3183f1805deb488df4a, + 0x92c09a074272c56f7611ae231544253242fb998f1faf5a04032c897705cc180, + 0x218cae97227d24e5501a8c68d0f9b298d102b5bb4870acec8ceb068b219c5de7, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x19fd38d0a9fcfe44eab81a88bf83e966f625dccfb8c8e663c92783d2f36f435a, + 0x105b69e0c16b67fb448ce467efb92c03c0a03d0ee652aa1d3f57276bcda15b48, + 0x25d1fb19588b96b835cf451788b64356dae74ac4b1dd04105f4ff71ee538e69, + 0x1a3d3f0584d9937628708ae5bc1a677ca0d9734ba13f9f9bafd4d40ed09efd2, + 0xda29cb284f0b19e45ddd3688a097cd2fa147726da98e7d7565480753c3d69ff, + 0xbb245a4fe17933f1a323de946e9c79ecaefe27cb72746f02dd7f8a12fb97465, + 0x12968abc1e49e916dbfd8d32c99add0f2522613fdfa603384acad50adb3c93d4, + 0xb72090055db8eaed15c53223be0d59f134b6e2bc190ff8aa145de2bc81fd905, + 0x2ec92e332d64bf0a6d53aab3202f16e8f931b0b3a19d08397981e4d67f7e6149, + 0x10875e45751b9f7e6d229bcb6035a0f64d2fc266087bb15b46ed8dbac225a875, + 0x20a28d7e7bf2393dbf1e8fd1b5957d6696a586df80ea755679bc922b32214f06, + 0x2dbcb5a066131fe70e1035acecb96d60a3c48394ef025f9469318ae141b59474, + 0x5d382b11621ce81dfa3b2a5b9fce537f18f3e1a3c11b744c44b7daee0f539a4, + 0x2aa1cbda3b7224be26b553b60967d1e49a79cc1fcea1e28dcceae95257195fa5, + 0x119d098ff4fcd15606264dca209fa31b8f90d343d73408afd99cbc60bf31b38c, + 0x2d6a5ec1decfd860f606bb717c2d6fe04d5da0a512677bfb3b88c6eb828ccaa4, + 0x1d44cdd7e0f9ff30fa262b991bbd4b25b9798c52b5475288dda93773873b70f1, + 0x1a52bfe42c699db0584e9908947654007f895244c01b0827637fff73ee586351, + 0x26bc0e722f88daf0ae3100dd3603409108756c81c2d2526d432135867248f06c, + 0x2151d6544b541cbe98b57b17bcc32174691b7dede6da01a85964ff4d03c63ed0, + 0x1dc401101c1f1df1931569efaa9db035fb7eb1f94ae9ce86cd6dc0540b1a1fff, + 0x219d8e0b575d09e774acf4018fb6302ac990e13959c8bef55814abe703d0a4fe, + 0x7107aac0c5aff7df10b39501354acdd1ab5dc0091d0166c55cd063c3a3100e7, + 0x1541846836b18159c10af51567f8cbd22556df4f20dd74ed1cee58b3144fb464, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x1a21b2733e57ce5cc36d9770c7eff1ae09c59af2a97deb649f35e034173963f8, + 0xaa74005a1aba9f35de88f256300d0f55c9a568a0a3f962547fff0a2ffcf3faa, + 0x302cc36dbcf39b2bb8f4ff9da06a95c8a904275eb4ef75a5b82fb7cb80133143, + 0x1ba8fadf54ff193f90ce70d81d068ef1caff816cf4298a9e9c359b78c7b3c77c, + 0x177e25961a6d2d2538623d70bd43b86651ec63b0ab29b1e706308224a0b7f68a, + 0x29ade22a14cb16e95939ac85e6c50f089d187069df8659609634290249efc500, + 0xc3cbc360d3cc87126d6dc733e8c0276e1b576ca318d256669a2777f70d89308, + 0x138a5c75420e198be86010c147c10fb0b6c882ec10683dfab0ef1b8cc023639c, + 0xa350052193a49d3255030214d15b36a10e7b2561890a4c851128603b6a5f092, + 0x1002580094079011e6c17ea867b391cfe05b5e73c6de87869cf2545c10084594, + 0x8c06521680fa7df05e7c8fb8a3a2ffdc0526051a59411a0cdd29e5f993e8f47, + 0x2a3a540122300f3070651e9198f9d5bb0fb52546c35ae90a4deafd9baf4e65a, + 0x1416a8824238910444767922e320d38b543cca200ea6c5591db9092e224be615, + 0x507def96242fbb9a1ab87fef1da1a03f4c3349723ec4ae6de894e171a1b4af5, + 0x2d03148012d730729390a74fec2d3e7ba9fd23f45e801657fc5e2a49b43744d, + 0x19446791471a6f03c3e0e557ea0d4b24bbd2930669ed23dd286e81b7fe17abe5, + 0x23c198ae993dfc34a55d2cb02226db49afdaa1b8cfb934a05ca594e616f43f35, + 0x49ebd2c1b2507a1399a21690d0e6a900184d15280bda27f5b53099933aafe5a, + 0x28eb35a44903f387f0b17a692fc99cc80826f9f36eb1b9576e2c5c4c48ccec56, + 0x2e217b29bc22f5d1772b5bc1fadc11af5afbe87b223fd501b1b63ec28a77435e, + 0x5d617f4148cb5ad818ca83e3e25d1aac33119f4862592430498b6c044ae087d, + 0x196ddf78908da3e629df88726541e8f3dc6bf7b3434a93b25434b2773b546eff, + 0x19f43813c7b1361c536509de373c74ebd978b0f3613d0457e59295ccb3447940, + 0x1dac98a00317e1ad75b44dfd710de43a70e1a99afd151dec478a8d0b4ebd67dd, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x248389b6c1215ae80412361e031f9d19e83e305fade25b5151787bac24151f30, + 0x1d6245849595c3f2e658dff1f825202f744288c73d5b6fe3e47be01c85231a63, + 0x2828197fc5ec3d0b61e3cd35b39ff7ca0582844ea9893e47575ac698fe0fab44, + 0x5f98baa94403cbee299a7c38bca231773951a9b5ec47809445687c1fbfcae21, + 0x21c21725d982bf880516bdd009e9c82289429fd8470ee4f009281b6d610f86d7, + 0x25161628bb96c434fcdfed33abfb03d4492060f9c12e5d6e11a30da401f65624, + 0x98dfc41ac8db685ac12e9fcb277ab8b38fa0b4b943b5f5863189e57a4ec1726, + 0x20e5160dbc32bb70dd2b667ff122aac9c9a209830d177d065eedaa37c238b6d3, + 0x2282b92a3302808cdc7032e874419ad5b9445a5e6948c67e35af7b59647e6072, + 0x19183560ff143e5d855665e03136bd60d6e627117857e45ce3b170d335d19805, + 0x1cb1080ee04da98e9a546b1eafbfac68d7bbd31acd6602818742e1dbd035345, + 0x2e08e6eb7f7299ddbf4e83adb2f544c8e2bf1733140eae2a24ca09e8e190ba93, + 0x17313eb73d301839abcd85bcb243a96c662a9225d70e923f4966024ff3fea376, + 0x115a8fa0b0211dcf5a0625e77bf00d4eec93b313811c61441d04e2e927f99a1d, + 0x10671e260167bb4a73650275e517b30cb040d62e5d8bc65a23e2bab6fc0927bf, + 0x697b10896487efb0a81d149a959b22c8edd1b130e18ab45dd5e4f287fc567cf, + 0xe23561be0a6b6e5616ff582cba30e707dfb2d85aff42daeeebab0a41fdd2a9c, + 0xe6c17540a1832e4aa8682e0c1ca4471e2ad131c70a6abd6333268f39568dc32, + 0x77e8a2a9d0da541d9357eb1b603ee9410d49eda3140ba9abbe1b6cfbf8d4e36, + 0x1ef5a47f9491310e04e85c853bc42a12227721bc8ef99acf866256c6f0ac2b05, + 0x2d756bd8508664fdb9623bee29f62db368e7e9fb8c2f8cf806a2028a34a54ed8, + 0xb6440027e32df5bd12e4075461952f0c0a169f47e498833a0338776f3cfee4e, + 0x103b3141b18d49495ce38d5e0ab2a691e78193978da5888e36604c51eb757e96, + 0x4502bc324657c18c59a6bcadcc0735e706677a556f0ab33468abf64bd434649, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x226880584a57a7c552da325ea532bf382c67482108870675bac5d3d9b6a71abc, + 0x178d0b7b044c806c180b95dfbe188f99e7dad714554fae1365264f33b5204d38, + 0x110cbd05beed208043ab1cba8a604abe596258c516ea0c68b804d2e262989e28, + 0x2b4f9ba6e2d2e31078ed70f6a147e329d1c4b83c76119951dc7bcc6d2a944cd0, + 0x1712edcd1662f4dab78bdb08c5d2208e096d26aea6d8b5a2f1ea1a575dc29dbb, + 0x20e7ac1985805214842f811423601b3f18c8634e87b1433382bdf397b28b7e21, + 0x5e6b0e267ea884c7a767266b614d9f23883f297a9c40b2be9daf6af85f31fd6, + 0x15adb275543fbb0e083a10e1ec448b8eebf82185f0a99a06bca805737f0d7db1, + 0x23f2e8816906f5fc349e99c8241230167b50d8db22c5e752d640fc319c7354e1, + 0x8a8a0eb412422e0ff3bef4e8f9e98d0937293d8bd96c9ed823de14c7a60fe44, + 0x147392d188c52fe487d5e14652ff175b37253bd5fb04ec9e316de4cf5100500b, + 0x1a1a69d5bda4c559702d87b8ffbab347d61d5d5ffba016055b540409e90d050c, + 0x26265b87f8fac4c16383d9763460242746a0fbfc7fc375a251a39e5cb12c8ae, + 0x562af273c7d6798ad1772d383417f8baab7feffa3f8fe1b5061e695a63ea362, + 0x2277d743f99daccb8223eee9ed2647e6bc22c5f00a0dc9b45c26898227530c02, + 0x2ab7551e6b4731a0b2c00c1a1c57ad9dd66b2239a2754f64328d4023249f331c, + 0x67e6bb5600490688a67ca30a941a68f15dc97eb418f8cecceeb1d1f49af1cd9, + 0x299b048827a0cc67b44e53fb5897f27c57c448ed25d4be88b1b81b22186c0017, + 0x4ce6cdf689338f7df3c3ba84e7ef35ef59adce460340ea0d161a45123c4051f, + 0x17631e8c563356367e1607096074fcd220d0256a60e1e6d145bd243c5475cf9a, + 0x25be84baaea86bb16bc3de4e5578c796e1888ac898d37f1f835ea87f1aabcc04, + 0x7fd81c59493a306dec9f05c012a96c113a950a44cea7de572af401db8804f2d, + 0x2d71abfab45aa0b3d4689b2518ae16f87cb60b0fd9d40c3567e5dea122815ae4, + 0xbf1dacc9ee49263420b6b40b061e1de77884556be4629a011bb73c3cf8fd282, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x207e38309d97a6bf02d2c9071fb8c0243a8f6570c15c1dea211dcc2cbf45ea49, + 0x96401efc3b429395ea5c187ccef5c551ed99043ce3abe10e0b2f6c0fa0d29f1, + 0x25e2fb13f405f8cdc60da80af2df8f7aaea21aa8c5ea1b80edc22261c424810f, + 0x14f942438d0b6308e88366af640e59b35e7b90dafb9949cd395fb9edb36e57a, + 0x1a732391895868212d93a33c0c4de589333631c8260c991f7885b916d0037272, + 0x1e29088ed2ebabe07ada9617c87d6ae3eea384cca222ea5983550c9d25bb0648, + 0x5ee285acce6181041543d01d650e8314690f337372341336b4fb1b27dc1bdb2, + 0x252b8b5dff5e6788b2389b2e55c939e69871912bbcde09be55a0baf9f8c7a67f, + 0x5198e4ac3158c2f1f30e9c7333b8f185372db43467e884f9961396b75f7d60a, + 0x245a5fd31eed8204f89bceedefb467b89e3cf7fe91d24a33a3207bb6f083e19a, + 0x57bc812c85f04480fe94410a106b281d8f3e2d54b39e4fb45e0a5ead0910dfc, + 0x1afeecd7c598ce3f7281378c2e514c5be72109df6efe311497dbe12a819e406a, + 0x2fb8c6d1000b2bf11eac94956464fcdfb9633a271fa8b070f4b63efd7b5007b8, + 0x32899458487c72b4c48dc1f717a0b2aa3ce53b6a4b38558b7737ed21cafe78e, + 0x662f06913258bafb5bdf1aa929332c7c97d4c4490c6fbc8e798335ff76e126b, + 0x1584478d313986eb0ae24f5d342d3ec738138d749b5071e839c1693af46f3a3, + 0x2dba025efcaba3d1c4cf07885e8fbc1f11c012bcdc009087f306a399a7645111, + 0x9883180be89d40f292405a2d44f5b9bba1c37613ddf84bf28c4fe593fcf06ee, + 0x1ba2bca86f0f3a73f392649f65c1eeabb57e3527588289b4820a391a46475dcd, + 0x148b95dab3a784e6f57042365a46a01e5880f17e09f3141bf99c53ee8a1ff06, + 0x209b90e92015a18f13bd1343a34d905fca3ed55b88bf1eeabd3e542987a08628, + 0xb50cbb98c4c16293795735e6cad9a458e2d37f1c02af95b15272aeadee5307b, + 0x28f083282c1dc347bb8049f59580fc82bebfaae2fd4d5c3198eab42357656c01, + 0x1e3cfa063b3cd467a69c8a628a627faf26187744a879ed796956bc1e3b1ba00c, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x22063e51a25b5a045914651b3b3fbb41a432a2cd49fafa1a6da1f1b3abac6b39, + 0xed1ee65d2b2cb52e5c72dc18084cdaffdc8eed2dbf45309a9b31afa3239e0c5, + 0x9f1f1407a395396be8efd490907e71b2a1e1a761f5599060b1ddf9babe3ec3, + 0x24e22c3cd40dd01dea8ca00b4ac1dc8cf2fe8ec7404f09decdb5f2e27e4f6a51, + 0x297d190c65439de912d9b19a51a34f3af3062388bc90dcf02c95ac55f827f393, + 0xcbc6af2a7286736fff8c442d20accea23f927c42de68c5965be6b73f787871, + 0xbf4731c628503367f3a0979d34ebfc4e1b3a6ee8cb90f8e145ea71108f77b19, + 0x74ef632df5709022478511a69f0c35f167718dd3943a871dbabcfcfafccb99b, + 0xbf311d6ae97647aea1524d5c401392a2a6242420918607c8595073f00163f2b, + 0x2fb17a27e5d93c8fa198091d288eb25cc9a75a3cc2bb29c73b7c4962ba6b02b6, + 0x17eeb974a4bb33ec349adc4e3c5e9141c3fe5b52b8a9eb5f55897fcd3f13dff5, + 0x16c75dafa94b13f4baf5a849aa93deda4486711f92188ee41083f8ef0e2a19ac, + 0x122da8189ad70e3c28109ade01566f47039ce2a35d85eee2f2212139d7e6a83b, + 0x260972f4d1166f0a53272aaf203d54909f372f9ef5175fa8d15f863299bbac2e, + 0xaddc83c8f239eb4617cb1a6a99b9ea314b775252379d4a28092946834ec18d, + 0xcdfe4ff760184a4b1e1c7df835824830c35d9ae719993e1c8b61968341c74ff, + 0x6cb7b1d7ee8b715c2b325853d8374f2f1edd1c47defc42d560fb1ec2ec4093b, + 0x8d48ac917970f6318a8b999fcfa64bd0026915cfbbaf2356c0e68415b42cf64, + 0x20f5eca934a922f2324ec4f5cd1423fb342004e24db642dde32d4f49b020f19d, + 0x2926c1107b74752a5b0b0326f9775d3c0290079b81f1ee7b3540c857a2e6e7f3, + 0x2ad7b40da5583cbffe41e7ba8a9dcfa0aa04526e17a359e380152ab05659aa3e, + 0x157176042c8c3678e6a57db77c420cd2aac6658f392eefec6bd96ec3d75d16e1, + 0xd6e65707b940bb40ce868be699f58d8f328c635900db4f738d9ae05b337e4e3, + 0xd794b0f796362925d3c3f8f7a5fc0fa8995ff16b7cd198a7a4f2978033d3e61, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x20a525ca48bf502bca0dc9aab020e141e26b38ec47a44e1580c0d1b616351398, + 0x1ee320963332762900b4744bd20f6f06d90663c9a45ccf876dfa46ff7b6a648b, + 0x22635f8210cb3cd5a5f3d6f3c05db35f48f4dd99ce9689a4a49c1396fd0254b4, + 0x236867069537dc76045fbcc34387c0d659f274038f60bd46092c7c5c6d2a93ac, + 0x2949bfabb09d51a438ba0c845a569c3cfd415a4767babba43d49b4a7d23efe57, + 0x1834d2d0982cc3e0a6783a1817d0a70935296a1e1cf6ced2fb36e49399ff129f, + 0x42688f81e90f021c645ab69ead85df5637e8c35e5f747da2b9353fba3614759, + 0x2cbf3eaf39ad0427ce377701b0aed081ab11a4d8425a5d85eb6ed545e02a3e67, + 0x28ee79339c57962491524337981f039783042a61ba46bc4b6d27842ce253e295, + 0x2dc6b0d76d332c582bc225e0e3852a84e670441a34a35271183dd071b3a8b9f1, + 0x7cf8620fb65b2763c494dda02d454c32d86918bcd972c81af8896daa2e25220, + 0x19d3305037fe6d5dbdb1c2cf07dbccfbb3771dd745a1a776027e76b829c38e15, + 0x2e6f19575b0e917c325b5455bfc97e65b080d5ca3b0d866a13315efc1f5afb43, + 0x1e726c0acd6e169de2eeeaceff128e7691b7d4fa8a046ed41a828563547a3270, + 0x2527a428504d8fbad1a95451f6968dd7750e9b88eb737094d0d22806ea461bfa, + 0x1ee0e151bffcaf72aa962734818b53086af9a5eeeaf821fa85a16ceedf5006de, + 0x1332d8ea514225643ee26cf14ed13c2936780d3b0df8d13a0d80c7593339dc1a, + 0x67440d1b5c5c1e37921583ac6081d7c0b614430461abbce3445fdca1c25e52b, + 0x217e15b68bbd0d70328ba92eb9848533a76fa177015bbe167d9648e216d72fb, + 0x1d5f55517167e8f4e07ae1d8fb025baafb68072f0ecfc39c2ab6917e2883f001, + 0x1ce431894721293173604b5423cf3be2aa2a4c602244ca33cfc474364261e219, + 0x1870cdd25b0026ceb6ca8bb7a4abe4c835cc54fb5d4a2bdcab837776e4a41f36, + 0x13b6c4c8a9796559718d72ff32d05acd285d4e36b24a0dda09181dcc0b821225, + 0xe59398cb50c995ddf9469890c14f7eb35b6d1ff21b54fa88d75105180cc9c84, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x2471cdf128c6570022fa1786a35b379627cdf4a1cf0c888cddf80196fad77864, + 0x1eddc8c186b5952235d179801e4d1f5526b26e72d637d482d34aaf8acdfbc678, + 0x41287596ebb654ec2703cb288320c78b03e252a98d304b5c670d6a9f3b75f11, + 0x2d27cddd60f27e931720ad20633a2e0aa9e9fb34e53a1c92449c42539836cc84, + 0x386464e269edd20cd4abedb92ea083d5251633ec2ed40b9c9298a6b03d0c47f, + 0x7b28d6f381e7fb054165533e6c22be7235e01dc2111c2586c88cb6b13915daa, + 0x25a51836e32d3111c1ef3a5b222a45a8647f491b251a0e7d548aa579f04dd532, + 0x4133c14bb36f4f02735144703cf36b0e6eaec35a23b23a5b3d7bbccce729e3b, + 0x1a107c44417a85fe63fa5f32beae1188f7ef9c7e9887840e06c41442065fb590, + 0x11963a7f8f62abe87fd0e9f059bda23e56ea044fff31672c16653096035d6e60, + 0x63942281da7187cf115521332a5480ea6297764540daf35e844f9a9db14df1d, + 0x28323184f7d03f5fdb8c55416291a0f2893f3f8f704345fd197335bab60e6313, + 0x1d5ee3c314bccd0507e0e1f3d22cde05f8beef4006bdd196d1cd972a00f328b5, + 0xe3e7e1bf77551287cb3436a06bcba1356aee949507c50da7075fba70259055f, + 0xbdb1ba75288ad45c653e6731b73fcf8c2e5a06452a7e9b1055349ca1b954a8d, + 0x163efbc5313a19dfd299b4f7d24ac36fc09dae316bdaad22f2e7354890487b3c, + 0x655a2ee9811be4138b87caeac43693187ba723a4a252e1fe5aa481cdf35dcf0, + 0x221ab7029ca41cb3703fd26fdbfd99f83da62e3d6aed9c715fda493e703ded14, + 0x17e06a11e4766ab95ae693ef77be2fd5a816abeb8af48e77812af31a9bc97556, + 0x24fd79ff869a80007553fe52dae87841d271b05d3465e21632e97808db658a79, + 0x2937964cb5feff56156c0a2d36e7d717f5133c52311e8a9250e3e538c6d6a2e4, + 0x115b54ca59723ddcf0b8b72e014a3532bfb9461db00c87b805e6eb6f950eb2fb, + 0xb83ba59544995c109fe67c59e1c6682df4f0a94420449255f2e42125d1522e4, + 0x856ce0b9c472642563a58f67fbe8490d213f1e60c841539d6593ce72c8caa75, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x1234cde55f1ce07e8add8919dc2786c2a2e8baa0699f9309a24a6977cf4de312, + 0x2728518406453c21f80cdfbc5ae5a7e5bc660853c39c07f08f4ca48b866fe708, + 0x263c6e870681a568879af7059e9eee6c2107545775a707e5d397e090bb406681, + 0x264b910c5d9c7677ca26b01c95b2eabda02155d239a7525aacc9e7c3a1b31108, + 0x3626d5425f196e0ecc625c95caf99c1788ab08826db99cfc994dfc07cf7cde2, + 0x285b7fc8640c5644ef5acd76eba635788490408488d4c1c7fe5e154882885b20, + 0x806dfed34a9e837d6269442a1ac7f06b9329bc91b841651f866d001457a7e47, + 0x17d501d18a443c458bc2987ac700a167935fc95c0b43b2bc31d3d1e66f4f4185, + 0x1c265144d850ae945f896d29b8d25558fe572437cfbb23c0d2974ed75a8446c1, + 0x2d349fcab317e2f10486728b85b73fd55ef9e72913db57a96de3799d79331a5b, + 0xe3b16089c86c7518eccbf3e7b5d6c93a7f57dd663e313bd9278599baedbe8d6, + 0x16842185b0a19379239ac6fc9576f9662323e9ccb19c73ca551dae5a204363ba, + 0xafddf6a0ff562cf8cf83b9b4aa7f77ca5944dc203e6716ee136947b7774d185, + 0x1a7b9bf02113552d2267b66a6a183c58bd9b0a71b607424034ca249f48056aee, + 0x1b292db8eb2df955d186044eb865b53c345855fb04e0e7aa34728f3a33dc8f61, + 0x1166bc2548e4dd1a597827e1ff6b873b8c029056733c2b15524595f6646fb9ac, + 0x27ef791b1fb45f73950ca3297ad2eff668164240ca0fcec4d505379347a4b32f, + 0x94e36712d3e0387be23f4e8d2e8932333c2b5b329ff01b0bded642875aa8d8c, + 0xc3cb8c9451dc65e2baca4021012b4107b1277ec1e8cf85684523a86f4452caa, + 0xc16066d636413dba5340f2dc58657da3d04fd4f649280bed2ad6c43dba22557, + 0x26f53db3a19fbbae833e6dc50733326512531bacac05e1142b5169e0a6f37b16, + 0x17bfb665418fec0ddd649243c3b77515e92eba58355437ecce39a21b3da565de, + 0x21ed66971a5e0e1451a9657918e2bacc2cb244d2f101e4a870b7c40400d8e004, + 0x2fc72d372345e9a20344054b130f91cc301d409bd2ede08380b1d2cc9296a0a0, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x242b4eadff11c6d3d54f5372755d36c9829ab3f1ad36cde7fad1b4927bcfdf7f, + 0x85e6d5205bc517634147ec300edcf4d8e40d319b2774da859a677ee823b3474, + 0xd7857f8c2ef1d3f6cc0b9d269080a8352f716ced9a8541b58047570931c9a8, + 0xb8a79f4d635ec38c11720fdb6bca9a37e4ef8bbfd3c3a753815ecc975c6b1da, + 0x2d581f4dd4f7a4870f6924d8ccc3aead2778ef1e6dd93b766faa89733c57534d, + 0x26a82a89ac34602384406faabac1204664088042b012c62c312d10597d4473e, + 0x119c9ce0168defeea8eae1085b57836db28898019661e84f988bb0c5dd3cbb1a, + 0x1fdc49eac128a24057128d92ee2b8ae3a28d2ae331e53e898a9cc4baaa67e144, + 0xe63791edc085e7e68fe844a1e288175214f53697c447a06af668ebaf9624d7c, + 0x8e8a95d72c8b0f5572e434cd1e8f29a22c7a051beefe38bcc1c8c67021b6cd0, + 0x150bfbe651cb129452581c0ac0582068914d6b6225eee54f3d041e8a04ee959e, + 0x1f67b188cbddc9dfe73228557f41e28d562eb71233399c51a1120b6f6aa84fe4, + 0x3a94eec3b3b00da129a13059883d56b89d02876861ccafd677f1b692e74dedb, + 0x8a03a992c391bed4739308e90e2039caf26422b0fc314841229d9e65e29305a, + 0xf5db68b751ab629eab8876005534376e79c4cf2a3c0ce2c7681a9a67787afd5, + 0x14c1cf9ee31fc11c4611f6def094e6928ff1469cfad92b71c27eb02938999dc7, + 0x1c8430170e0d27fc8523ca6c5878db717b75136669b58b0582278e4b6a43207e, + 0x2eaabbe95b7e6d41e239af122c392f2c8a422309ca8fdf3f73fd18c4e266b50, + 0x28b85f746bc03b1a6497f9a85fa07e337b664a8e01bf96a096195cdd8dcfd78d, + 0x2eea090dddfab6d9d45f8fdc01e0697db257d6481ecee44eeb736310a57194a4, + 0x29461ccf449b9fe3a48b3527a1b792f31761ce88a12a1bd185d02989048c6723, + 0x2d1eba58a7196aeec7ff60c922a6a37d238bda29e3578e754940fe55f6b44f6a, + 0x1d8488523480035454dd45ab1136e55b48ce729fc37fb3bdf07cd401e3df9864, + 0x169904bf4f7348ccd343513cf038cc546cd137c740b77d3df58ada6cdd49b292, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0xfaa555c1adf771edfa1b4f67a73108c7325be034cbc2c2e6d24554e62efd737, + 0x1a4ceaae57de9dbb19bb3701ae021b7b246fb7550aa505df8f95be742293b7e2, + 0x22d8eb68a906dcad75da8ce62f6763cbeda8004739851057965302696e185ae8, + 0xcfc82aa08b2bf7faf7de17be9adb759389c398441bdd294ed0dc25d3f7c4f8c, + 0x216a462577d231190606ef2920c63455045b8d51fbc6981a103a5135335f83dc, + 0xe63715ac0c89614281493e16b0bfe6d11194b36c1247e22838771eb1ec766ed, + 0xd024106eade54b9f8b5874bc7c3499487354afa2db7df3be1a971c8d2405265, + 0x11daebdd919b5622e294312a5e34121ae33104fb3e1f9e89dad0668f0517158, + 0x274a0198961e0c98ea0f75fe1e38ee5e5962225738d6c8edcdd5623e7b24eb6f, + 0x136d49834864e42917bce7dbb0e439d28c2007fbf09beadc78497d1da2593b58, + 0x18daff02be933186319ae1bab91e42256c5b56ea3d2d0698189294828e2a9076, + 0x13fbadf8255db09ad6b28d0a13874e8586fa565155da2145f80fce40f0c175f8, + 0x75a76152cb77f3a74ebb64a8b949d032a2e1ef7ef0f35fddcfd89473b5c1e71, + 0x1d1a9d3eff8079f2fd739a8c1ec1a1d2c391befa15c4497ee78e2cca6a327495, + 0x29132a7d6dc081cc6d7a5c3524f2805c9ae3c66a7de1714c4e75a9ed06206bb3, + 0xc1457b4dc6efd6f506f14d2cb839adb6995e2565223add3079801818a2b3b9a, + 0x66406956a8af95c2f8e84f977161005287832eb4860d0e333bc2a6738be404e, + 0x2be8ce6965272c3ea5fef305d80056972b0cc10cc89ba56df234736a8168895, + 0xc624c5b84f86974e5992e2bf99aa7406db0bfc77db799e680ceed051578bb65, + 0x1c9fc7b076255b1dd44a3f77be12b8c0c7136880ef39f02aa002253ff808aab5, + 0x1ed5752920052d66ec89e671965ba4ef5beac9b982b7405174c8c2cf62ba9c2c, + 0x11a79d9e71816d2f90a16813583dbcb286ac19f81016b01ffa4318be074997d1, + 0x2332f2f0231e1a5f4adae2661a4988c773f58f806ad73cec7fa8410327c29ef9, + 0x92041cd3c1f24dc8700053b6d0b4d130f9709bae71ec397d1ebbcd08281e1e0, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x23402a04a12ab3776b14119bbf85cda4e8866dd1c8c2ed209c5cf5a94832d9af, + 0x21f6d7c6cc0750868e0310bb8a7fe02b70afad0229fdad5c5cf38f7231d80528, + 0xaa11c91a5f547de0061ad5ac646b4f17580e985d926dc48303da965dd994672, + 0x2542d51f269de541f7040d7d707fd4d8a045f02c7f0a662e0458abd1c787cfa, + 0xe9367b46e6b89363dc9cfd523f4abb4d123a0af9eddd5e356e63e3d49092542, + 0x13d2aae41f6b1c1b5bdd9c576c7458709c75eeb7af22fe0b7f5d98ea20609007, + 0x19a2b2dc5988a9ffdd458384dd5e0cee7970afb38c1823fe897e485fcda9dad2, + 0x8dddcf32490be94e7be38105e717382f7966deefcdbc67432c312b8aab15a1b, + 0x1a30ac3889e0467ad2178fbd85b93ccc493565c376202982dd16ec9bcced261d, + 0x2dd2470d7ca5e69e5728e76adba044e821425b245bb5cdfd48132b4df5f362e1, + 0x104563d762464be13f51050d3d210162ee31e4b14f0e37202aad99f8723f0ac0, + 0x121b7e910a0ccb4e4d5f220628cd64c2846fc5f470a7c2b6ea38170b9d058b38, + 0x2fd423fe5d1899fe054ff1b9684ff93540bc396589289388681b90fcb8e76c11, + 0x298f732a1a912702fa4c4090d00861d99bbd4eb800b20acdf1c9d4a6c8226a62, + 0x26f56ce61eaed10294727014eb88ada99fe5015c911705cf7ed7bd8f04269daa, + 0xc316eb74780def4c7c08420d1a887d3f3b8028f2d65ef3e18822ba972a50c96, + 0x1db5c65a2d669c928e82c2ba7a85213d03976e7355bd3aba90444c8d8ecbb108, + 0x29fbe3f0b5d6936f4e42cf5ed294e1a18f7c597faefd0087653f06f1cd7ce55e, + 0x133f5377394de76650324177d895cff11b4edb902724138669df63d064254274, + 0x1762e6a990654a18eb15171a84030e43a93481ec520b86ff65263055551d19cb, + 0x2bac62e64e374a494b9ba34ac9cb872ccef42966e1c98c9d12696e1b7b9caf0e, + 0x1dc2f5d192b065461e410a353b6e9ed48f8dd9a5b59e0d4567add1ca1edbbf74, + 0x1e78930fbea45070dc63eb82fa3b44feb8811842c8040f584482e5529b9c08fc, + 0x1161dd83445bc4ac05e88f82b6d4b395dcb7bc08bef6bc0394e2860e1b91a45d, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x2d84302b2f1ce369033aa5de5bb8498f718102642636ea98a13d9f2f9e03d70, + 0x3aa0b6d1722c2e927078f0d0d2a9e1651a387b0a50aabe4c3e9f9e29ce5808, + 0x1851a25520c47c40439abf21fa5b9007ae1557a0d7a737ebd36922e1ec2fe713, + 0xc88238b7bc582be65a3d9780b1c502a8b2a6bbfcf63863ea988e4caf6e75767, + 0x1231dfe4ea1c60c263b7a7f849c8d8cb42c5506161b7fa87e527e917c942c5e3, + 0x2ea0849f20d6ff258c0f184ca8057bfe236245dd4b8642c64e42ef4a1a9d8ffd, + 0x1ba62148f57f420101c599eeca0abf930464f2c0444acb90d2fb96d3db62f7b6, + 0x21f4a3066fad0b05bc69b92e00cea13278d1a5a67436c1f3f2139a6ee79bcbda, + 0x1be4c6e03d2807854d234372f267581058b173ac8b3c7483c6e8dc3352798b79, + 0x369cf9d45a15633cf75d2234f1014f60d1ab30cca21b0fc60af3c0fba6cc06, + 0x251ba00e6136bd990f4db7457a27df54e6e6a986726cb005ee21e173dc9c982a, + 0x290465aa219c5f39fc7dc5b210ce805d70d3137c43ab354abadac718f5357e1, + 0x72153d3d9304bcb121e16ac43ba352e3492aa9264e39abd0ad500003b2c1a0e, + 0x9ef6ef37f5f703229c7c5171a54a9e7d70151ab47b6312a3b592208c192cc2d, + 0x1041b9436273bece36bfd9801372251c2e753b50485953908c35b63979d9fd82, + 0x26afe74d2bbaa76d568a55b8fe35f02e5e913285cb5678ad631654ca03e11f22, + 0xab136a0298a4bbe0d53250d7be1179123aa3f7390c39c08d76facbcf387efb2, + 0x2154df61438fa728853b1e34064bf3bb988f36af48ac6097d2845a4ed924a360, + 0x59b12d8356358cdf3690ca2259447a7147e0e6d33dd5e0c62293c1fae3c7057, + 0x1a01646ed40505df3ebd020f7aefb2dfcd2b194d697f78eb2c6706193e25c783, + 0x27080e00f575ea9dfced456747507b55a0612618d5377ba4745b1a2c007fc4a1, + 0x3b12781eea743ad978032243b55ffa3c23ba980f8f1fe48f72ece1ffe09b1f7, + 0x10ac2c9f77fcd414c3bea9acf7308733892b1802d061fbe3e5ac7d93a437c85b, + 0xea74b2639185bdaa176c285f7e674e4ade050bb08aa1eaafe0a0516d5814623, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x42b91f98007bfadfc37f8c7be01e1e6d1a5a001f4163dec7e6fa8ecf7e5e9c1, + 0x4f0196b4cc4a2fd24b603ca65fa4eb23ce4523b695c34e9323a1f55693f09d5, + 0x20687749f9cbe6aef88c27b6bccc40204246a670ede772decba2f34a61bb824f, + 0x2f9039a4b8b4ab2278d0fdc4b35679678b1d8243ad4bb814b8b7bc3e1b8a4b43, + 0x6012407ccdb4f5accc26888a094e35750aa5d88775cdca0a9881e816fe240f5, + 0xe35046c49cc56a7ec8463053e159925bf55109e8fcff58caff08765476d823d, + 0xad83c2a587b98cb240f3feec78c6578473f99bf7224acc545793094333b700f, + 0xbda24254733d7bcd642ef47c6731761aa67e1ba0ec64e03609d3652e495fcaf, + 0x1eb04acee8c325faf51f6ac53200bd56b052e48806bc12513c165e90c0ea75cf, + 0x25f00927a77b2fc8aea3e3df5a038ef8249bd29e7f6422529dcce7692efd6376, + 0x86ff48a930b5807dacfe436fcc67766ad4253e352907c1957127d6a41b6387a, + 0x22d31103b21aa0b791235ce90ef06cf972c8165bce3c68b3714f89446a42f265, + 0x21f10bef68e2b8437330ebda744e2c3e1f26a92c3336c7de3b645a8f4369dc8f, + 0x2e3ed873b0f6ff7facbee3a110baba8af030fbccaeea386ce3a960bb31a71951, + 0x16d86751cd45d37bedabaca6ad75277e9864d3f6d30e4c0cc2dd25a9ae58dae, + 0x3d059764e5aac685b59387aa484960ed4ef9639843fe308f8cc3dee87e3314f, + 0x63f962a68390a818e545995d2b3d53f8a0a5f0aa23451e6d14b0851ab8bb573, + 0x2d7df484595413f83861ed05f30146f9a4efd46b0b90f7ca9440e30c27c9b931, + 0x5d966e25cf9cee974e405c86aa2a1b7ae63f5a8928e136e12249dae3cb12132, + 0x16bda6eb44145f870e0818bf6f60a068288a5ef23da1bc264e01a11fc1e013c1, + 0x287f1bc804ef51375cf720b680501f7ff1c97cbe98074ccc226d18bd5e18b381, + 0x27b1edf001e3a0a8562b991a2790a5b48e3bf45f2d637ae7b5f1ba7a6ad5822d, + 0x74ee1772d860b6ad09b16d82e458eb305228b24a28c70c5f690abbedf70d506, + 0x218ef3d8be2c4cebf3b2c6a75ddf98e77d79729a0f9d6b111ac0895ebdaba6b5, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x2e130f21aa3bc952d00ba26b10b65c1f55c92f34a51e0d6d6224d2daba241788, + 0x1e6f16db6a97a384c7164733400ef142c41deb040573adb8b0fc71efc2f76468, + 0xda66242a6a2e27b519dd2335e559ebf8334bcb00614dfce963dc07fdd7612f2, + 0x201d2a470fdb240a6d4008cfdebd4b579df34c273ffb66a52ec89962e1a59b5e, + 0x4d1c70932221e3983756ed5d5ca38ef603caff2d2168f5f937c1510775b0e9e, + 0x2a43db76fb42a082375f5e21c4daf3853e9c57d8627c2caee2d837ee857fc6e, + 0x188d71e846b0e63c5d65535a6d121a9648d99af72f72c3f38bc33751e999918a, + 0x1cb4d77c20517ccf346b92567ca15a4b7f7079a150a3b7fbc95b474d2c07d241, + 0x2de6abda392578254c6c2949559b851ca312e5c098ea17bdbff8815ac4216810, + 0x97bac96307e8ecd42940e30d9bde2904025715f5ddc8d6237691c3689635adb, + 0x11ef6e021d4e1b51f156a1c1863d497c95fc1df010d906859d510a2c2d01e537, + 0x54ed7f2b2e4cfea2ea62cb01379d94041481dc85e94cdc4bde08da9b1ba57fa, + 0x16d8390b0ba3174141236bf21283588887ce3eb966b7d45cde064d5cb2a35738, + 0x2db8640099fae4b29bc2ff73424df4851e33eb823b577e4354ccbcb1392ee0ae, + 0x1de2025f4beb8b5b58acbe6126a092ec0a6f3a664325a88e9a28bce898edf98a, + 0x21a514a8d477d92a308095092224f5562af41cf964d34be181e95370590b5788, + 0x140ce2c9605e31576e464e6cbfc8c9712ec8fa2e46f97422d52b0b6401aa5b55, + 0x20313b2273dbcf225f74da13f3e0d0909f47e77e53e833e4a12e439e185dceae, + 0xb8251930e6623b8c062163d973ecdb0f171608c126c7db4791116621f2869aa, + 0xd0b3893c4f70d16172884b37d6242f07ba39e4c7180462dbed175bb0db0714c, + 0x26917b241a12390182932069a99420c31580ecf06449a9fe7871e3193cda0bbd, + 0x179bba9ed0bc1ad6942990e43de2abcd2e7094d7d9fbc02dc2d82b50d9970e4a, + 0x2184a1b9adea49757d59d0c17c369efdc044f11ffa1598f2f3bf4bf1dc7fae58, + 0x65a085cec70ed53a9d53827c7766989219c6474bc5d415be1706e953de20273, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x13ec63dd902be70179d9a190f2e5f1dded28d2feda5d6ac4c9914c3bedcae90a, + 0x272d4b6c21e2f7d2c83b28588f5b0f462919554cf4faab4bcc668ab86c877eea, + 0x12e29b20a5157f1152c41c4e832287b963b6c774de743e4d3d7a5554cc39aac7, + 0x2c73520466905c9230aa6968c6ff3d7bed3130cdceb68bc5a24e51da861c1153, + 0xb370f950332b70ca2c247e2349d2e2e22e2d4a4f519efed6039504fa2b2b280, + 0x1c58bd926fa20dfa0ed3b7e53fde4e4d7bc4df78d13969fac999dd858f0df678, + 0x9d50596628e021f264983ab61a7bad3bcdecc9d6cd3ec46ecbd83bab569b66a, + 0xad3dd8c790db77df35aa78dc84ad3571f0a70fd70b5ec02fb62f4a459bb7d74, + 0x154ec11de0ba022622b33a918364a375f4632bbbd3a6c0c7b8fd77c3831584db, + 0x2bedf29086a4a80d125df6fca693c198a424226bf0eeacbf4c3990b7ac08c7cf, + 0x204ba94b0e1a592391c9fb397701c62d724b55d28665ff3908d277f2728c37e6, + 0x1191741fc0fcbdf5976b32953adea3cf062a2da42a317f0a9907426567d759ce, + 0x8453abba1a812cd70189049a362f26960ab98640e98233a9799ff9aebc15bce, + 0x2faa16a34bc765b803fc320e5c9c3d60cc7a62bc4317fe5996cb5352ef391f08, + 0x1073a4c13414e4f47e3dd58f411b86f1269b4662a27d153b2ea797f3af9d840e, + 0x20827cf24daa915decca0be0018f95f33da122dbc9d31890b45831132296dff8, + 0xc184be1457cd3f30372671039b63894ec186f79ac12d4155c363cf60da9c2b5, + 0x1d1037585c8c002e4fa645846b83aa46d418a7ec475f36a310b5e93ef30b4f19, + 0x1bfbe62e3714574bed5c8915cc913e23ce5654d217fa8933208cee6cd2a7a733, + 0x9ac8a47968e147d7abfcbfb80e479a5aa83ec32fc9a21fd80277a05e36d6900, + 0x6673e8c09274a6b074bac39a9280285cb628f4c90f329c27d3ba1d79b1cc17d, + 0x2a513229a77a36862deffa4a24f4e1d5602d52e7abb7734cb6a5bfb006a14c70, + 0x7aa8c2df4a2083e46169b3e24fb2d0a9867ea17103a19c13fc08f832aa17dc2, + 0x212c78bf0b03c88fe1681497cea1b03064c87db0aa244f061d8135a365168163, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x3a58dde40365d7a0250fc75c67454329da04685e04a51bf51854954a6af915a, + 0x70e75afdcb3d8000ab4d459e8be1c4c0dcac213e37c3443d5d33de59a31a0e1, + 0x1dc99b8142e7cc81ec21bc7e5b37dbe2b29e69c290c6c67aa4fc3a7d4d6f17dc, + 0x2f160a3625bcdb7eec2ebc6a27f6d3aaeaa28e9ab85df1d2c1a34126d2c648aa, + 0x1ae4132fe8261cafe562823d0e2f059cf7917203bd3e1ad0d71b58a0f0804a67, + 0x24d5f4bd7441dd4ccb80955ecb60b72e676401239370ad526851b7b2358809fd, + 0x494f46648ee996ed2e7f654ae6c07216c090b6c4f3599c6eb18aa4e7cb761e9, + 0xf5f67afb9c5934a2d662532a7ecbae90ad260df4189e76f71bf51ce6600ab1d, + 0x135cd20c46aa1a429fae22bac540071d4baa5aa1f7cc662549c2a115e1a0152a, + 0x10b14b45ef38b4d3bd1247e2da3a65dfe290fd02ff1a15ca598b05548d1f93c8, + 0x22bfb1953a1022f21f1738c8067d26e250c3da6d950f0c17a26a420f898c166c, + 0x22dd1a3efcada96371c4b909e8c42dc426e0e040d152910bffacca1ec9dc4b72, + 0x2ec9e354b5f7415057e69782bd7c0db477b2ebc45909255dc90dd3e6fa157173, + 0x1d176d1f403b4a44e598c6dc34fdaf9c08e582e542748d9f18c9c89887a7ca06, + 0x57d65c1955ac40ed215d39c30bc61d015e505e3212fbb230cc61caf6dc9ca16, + 0xc16cadb3191773117e0038e8fa48c9c200bbfe9f61359979c978de8dadb9220, + 0x228354c24667b494d2cd53dbd85eef57c0b3621228cfc75ef08ee11fb331521d, + 0x11dae093fb04008a9d994fc7cf27d09ec0e19ec3ad1d548b5e1d205e97de99a7, + 0x1e24d8a3371d286d6a87358c6acd6757f732bd816b6c77e2193f456c237f95d3, + 0x14f5fa99460312481bf2b2c6082e5fad5ac3659eb5a13978b2bf2a26627d076d, + 0x274f78864eacb329a3ebdef354bfba6a7a5d20aa8ca57917c01d5ea57bf5e449, + 0x1aef2197b2a3930a466c9f2f8ed512af424ee99cdedf0d939bf5323cc13ddc8a, + 0x241e5e13407be4e0e123f9106ba3342a687e6c966d288b3b7feda4af532a422e, + 0x7914b11b3cb937283ee3129dbde2435825df1ed64d760a62c30aebf0ea6d522, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x2ef64fd1945065ca12f48afffe7527ade3289ad350ffe9dcc51b2cb05886b4ae, + 0x1e903fd8974ca0ef97c187e30a5dacd75151b3de2615bb2b832a6c81801e82eb, + 0x20ecf1440148c2b31f9a3c33f59da812efa0755507284665a1d5d4bcfe47ef85, + 0x15e956ab5a1c5a357e9de409a19386abbac37b453bd1ddd174000079b106366c, + 0xde22a61fd6607441d0894264777d660bcfa0cdab9d1da887c81e70c7bb8f7be, + 0x14a1ab44de8546185905ec2bfb7e9b0c8a330266a62fba53b8c5356cb5f20e76, + 0x1427c18b34b9b1962db5e13937a3bbd61a2af9e9b3760eb42ae17394b9c64ffb, + 0x276b0876d63e316c4eb32dbb64a4f4db99aab13bff6d666aa985abba4e9c0b74, + 0x1856468cdd489ea75e75dfef8d33539afb3c3e8d57e0725554897319c692bf48, + 0x23da22d7fadf8ce07944da0d1ab4f4fc9e2d2bb2ba50909ad99c86f556db0481, + 0x1c41fdd0f5fffb3d99ddb3a2b67e62a13e0dbb521bb4afedbc54c7fda3406bf7, + 0xf0bfb6289d76f0eebab2d4b5fd854e030f11672c8f362334290e0cd1f9fa051, + 0x18ac33130e605df004d682d08f9b16b888f88c3e1562bf08a24f7d254ca270ad, + 0x2befdfb192edf72525e96cd3aee3a1e54d4068121a0eb34d1064e8b7c8c44267, + 0x7839fa38ddc35348448d92a9122d84ba951ccefcc88e2618712d4ef896b7a2a, + 0x2bc35b2b57bc9b2be7b8a728125403c5a78c2f4d645da33b408e6cc79674d515, + 0x1f38bf25ca2c67ef958d3e92a44c3b4b80b910d3e10c3d0ee768f28628d6d7c1, + 0x1cd11f045b25737df9183843f5fa01f7b5ab00714100f0a05bff9372f063b52, + 0xa7f87799313df2c5edcaf10983d8abf938467fa5df74bcfdf0d51efeca406c2, + 0x718d416b20114551ccde2747cb6b15e889cc3233fad8a339465abc3273dac24, + 0xb45368b0cf6a77ac6e73ed23f94d5f8fb90a77421972dadc0d70c17ce39cd62, + 0x262dac40e77efee5a07345c63e77e946aa5d7640408dfc0dd0f27be77f97ae9b, + 0xea488fc1f7afec912267c19315412c10754a080c11a7873ca4d027935fa8b89, + 0x297db1b6f71749696ce48fe0862fa63d5f28306715a19762ef8ba915b9fc49a2, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x156c90ff4f955e0fc967223524cad6608e4d9cc8715c249c3492353730d500b6, + 0x1f4644da64c00905c3a6e15ada27cf593998574f6ee744e85fa9723345632886, + 0x10d4e58ed6e17089661c0bccd2c4564df12ebd6c4a88115549e7147491c671cf, + 0x2ad782fc25c4f0db520280f8dd92871f7bed6d0e23337d36df2141fbddd7049d, + 0x2928371625d6dd4de31102aec7726a15d88df0da173ea8a047e46e4562162e5e, + 0x2665ff9e95204c0eba710556e91dbddec9f5060ddda6e898a06b9078d170abc3, + 0x110d5e6488836ae4bc344cbe2406f494dce067adb21d69eb96b43bb7083c0b1c, + 0x16f7045c1cfdb025d926b966bf994728ef8a9647acd20b245ea1c41ec07bd704, + 0x21533d8130aba1fda6a31d4be45e3b6f27e1165cc7acf062d9170a874f44566e, + 0x29b6d6e0065b8aedebd2048ffe74b6ae857373d583adef571b7ef4d8c1376cbf, + 0x2bd0d29ed27a49e3cf5804bc515475bd2482830530485f253279fe3df313651f, + 0x2e5a5bc179f78f549317605f271654bbb727f5b35fa38918a308374a221b30f9, + 0x17aa3fb8d187b2f16771319c0890cc9a814c4fef3c8fd90277eda73a7fc9c1ea, + 0xfecef506e9a1c5363eaabd2e5d75ff06657ea4a701577bcc0d31cec282e6e99, + 0x104e7bc5cb52c3949d4ced53464aa25cbd419273c7159717d4243b8ba3e66289, + 0x2e2d87bbd2649ee3d7feb4a665a658432b9864c9a4d3a5b52bb2813f43af845b, + 0x2a737d085c1ecad2baf1eba7d7b79f76f3385ec88cdf0d8823bc721e7f7d5ef6, + 0x134ffef044d6db42e7de09eb3151188391d4a52ed4df145749fc20b4d0aff94a, + 0x1f46b43cc2e57fb9f22aeb6cd6c9d671cfd6fa043702b613f3de6cf5dcd4a648, + 0x1427b946ca939159e1f36e6a4e88d850c84f00698173d8ded2dd3a649ebb811f, + 0x20efae422eaa4272a255d02f80c304ceb0eb99dbe70e734901ce8303b7e75996, + 0x1fbcd3f2b5a6b08a9f835d2c56ed46fb2b9b9f0008e71fad6f072cc23ecf4e73, + 0x1ab1d914d85a78fbe7db057ad0251cb103d0f1fe4fa9f1565bb1defeadffb560, + 0x185d3cbbbd397b4202e6d2d23a5475ef93aaae25e9c720a849189b38475f3ebb, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x9a33338a814ca4f92e0eb0145510136d27d1a970e859c461b90350506c0ec73, + 0x134919acbc6872a886527ad4607df32a93f8d4f86cbb15cccd389e3cff0d5595, + 0x2988cc231f59a14253e978202e190e60904d3641819600eec68e3bad58e6321e, + 0x7a7e7e0247dfb327857f6cb9b2cf9102847c8c16209be817cc8988f4aee731e, + 0x102415cfc2e84e3b54b636a1125c5acc86ac2414aa2a4a36fca51c0902e99a2, + 0x1205491dfda96dcd74d0ea64c9d05b74a7eb0b98cc4dce972e3c65072ec779b6, + 0xadef8dd1998f07ebf85734cd2d480c380b3ceee9c1669827f9590f1767dc148, + 0x225f99bbe94d5c93ee09123f4655dd2d6bd80aca624e4d8f0a064054e232848d, + 0x1e8c19265e6565151258ea11206b5d8a9356cb614709c31e4167046d52dba14b, + 0x452cbcfd4d1de35a869a85ac1013082dd4ac1470e430452d4a8ea1530f5a3a9, + 0x29bb179886a2e49631442fcaf681e790a8903c96d1eff6647945ed626dc4d68a, + 0x1e06f246e926b517f3de008067cd6bc9f52e8d382c458098bed8c4d2cb183ed8, + 0x92a8624e09cc127fd7d1a32aac8383e510e37d6beca3fa117cbb1355e6eb8ae, + 0x29e31cbd24fa9de5d401438492f9b920ffa56adef762687c61ea562893ce02e7, + 0x1d47bb665d1bf9254c3ea59be757187acbc504b5378076fe029c4570f835722d, + 0x224f1c92c0c3e84e360222c40aa0f4311563bbf62bc9f255a3d7641378a2cb8e, + 0x1021a099460d801d171bb0db1c7972013146d1b09625f028bdb55242d8c51f8c, + 0x1cd67c97e764b8097f62c6402fccdb45a9bd18e0bb4b41ae08c2a25c276426b, + 0xe5dbdc0ab1a14125d19d7eed9cc36af6bdd5fe07f8ff269842f0aeba902c2a1, + 0x1649e0489cb0aa3844e97f61bb769f039f60b9638524408e3425b3f030b5b068, + 0x2d8611f69f27f599ac672277c1f0787005b6fe3c162d836637fc1c890c6c70c8, + 0x19a828de992f3bb86650a8a9f3844ff27f70b612e158170f81b7e6b6f4eae660, + 0x157a427811761757bec0b2decd1c28acba88e70e8e2b3a7b53d732a471572981, + 0x1f66ff45f17e0ec5690cdff99c1ae5d22edbb0ae12aab18ba5c1adae5b36e52f, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x9c9fa00fddcf694e98845212afe04048b34923d4fb41d05f99d24955c609c01, + 0x1ac154fc3f42165840c54a350d8243a3a28f55fd038dcdff628c52e17f72aa94, + 0x28859cb23ee55c27bc363dae264a0494ae77617ba92f595dfbb1454aa2678ef, + 0x1fd179a66fdb3cb0a06e90d1404c50c38d2bacbfa030bcd0b26e6ae454e3f5f, + 0x87dc7319f4e880c7136373d13fd6fdb2e433f31e099efdde56de5f8297a69b3, + 0x1a93bc3018ec7d3475863fdfdaaab0233df37c3f6da5a966538b13818c15c43a, + 0x1174a66194739850644d05a902b25d188c67ac7bfa816f1a3b9b73ac9731c400, + 0xfde9ecbcc6fb8a9ce490e809277b9dbb717369641b96f84b3ddbaafa39d1731, + 0x21d4b10d2e577a751a1284d0d079d066f6bb300db35a9289c5f5eb39e1e4adf7, + 0x1b491207581efedddfcdf23376324b9969e36f6ba8018ec2eb055a5dd6f4f8e0, + 0x12490e92c38fc269311bdc1acd2410502ac8d7b3334e65ab644751d1c6e3ba4a, + 0x3c569375b94a021a27a56b34dfddd14c01f7feebe14e231e53eb811c0d4fc89, + 0x12f5ebe6a436e8551778858bb53f9780439eb09fa2ac457096d7158e7af3afb1, + 0x2817dca315e7d8c25ce85bca47ef2424701c91df547407c8920d4a974eeac9ce, + 0x237f87fb2661d3a16840d8b115116d7b61d99ef94043ea2fc2e311f63bfeeaa8, + 0x13b8b1ac45db6a26c854d447f2750c09dea12c26f6d4083e9e8b3df2428aac6f, + 0x1429fffd68050249e1275110a16addcfb1300f294d63c0b50b7d4764f4797077, + 0x27003d2b7f980530014a1f5e88c4cc2c4178613f657c2b40afc3816ae14e4e73, + 0x1e7c9269b68e8ff2ea5f21c376fff7f3c1dec1df43a0207dd41aad1ac7213378, + 0x73bccfee0274ee3704bac0788527f8708883699084d3ee9facecd19acc02d5f, + 0x1a23c2e99e22f60e0ecc9dbd269a6f8b56aa74bf318961a085e42375d92823f, + 0xb0b38a1ee81114a35eeeeb54d419459b1729450789f14202fb84f009f728206, + 0xb08bf53cdcd498a9fca9a0775d19a3fab7cd6f7709f007b0d2fb07d8ea7452c, + 0x1d37550ee8724571acc9ff409226d2075544fbe2b38276726ad1c8ef3d096283, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x8fce6150b67f549ff898958587c36655277440c4c8bd9565a7ba547580f81f1, + 0x9a3d90307cac625bce9dd71e513f14642153c7c4a411d59f5db597fde888b44, + 0x5e2cba2a305c29ccfe1a49bf1cfaa3f00f097ff163feb7308c40ac654c594a2, + 0x151eb4fa0b1ce608925e2459726afddd5ab7982d4749e6185e5f033d1893ade, + 0x2e3299bef41097ad9e56203ac25eb52612145c8b411375b15be4c60faf9a0e8d, + 0x2b5a4ff11bba3074f0e0c3dd34eb3e21bd00c753717f19509c49e2ca01ee48ce, + 0x1ec7a76d764fcac86c55ce076344f7bbc51826ccba7e90ac703216841fd78931, + 0x19fe7d31b79e7b1a85ae430ba472cf699a814227f0325d957ce13df654430b3a, + 0xc1066dc7ef478b2ed0fe10c9c7a0bcb9a7974a4f782d03f248087fac50ec851, + 0x23b371f53de43570805ed4c382a4e2afe26207f1e280bd963347f973cd8e26b0, + 0x15b58fbe273944415ee68b4e237fad7005ced82fd6c2f8afd13c84eb29488b19, + 0x23d8929ce30fdfb078938a291dd88e7f7a802f172c7f9d792ab7aa6ed0866b77, + 0x340691f3b793cee0cadac0b96aa26bc7072c5d1815117e302afa970e6449ef8, + 0x274ddbc823611ed63e8cbc2929430d025088373ac3be564a44a739d11e4b6ef3, + 0x23a37eb726b1fc29841728eb657191d290fa6aaac92636b177bc582465f1af43, + 0x18ee2248d9512725ba90308696beb3102e7ea86de2719d2c52b4efc02fd0223a, + 0x40a14cf4ef9e74d44383ae681c3ab35d7c6cd0ad5d94ad8fcc5050e203ee6bb, + 0x2cb32996313c6c6cfbcec54c4f5d5b5057bebbc4fb0c103b9d1436726f0b7083, + 0x2b7dafb754789ddcb1dec0ce4ec50fe340d6a3a37c8d81bdeda0755dcb14c344, + 0x13e442da971a4c71620b80f9cad48d7105535596d4b8f1fe550c3ee07328c440, + 0x198e90225a0ed6b87bd847a0102a61267f6cee4d77aa631e355cdcdf93b477d3, + 0x2006cc86ed54bf7a5fc389fa5bca90dcd5269aba4ddeca95de1719ed8ab63777, + 0x889ec7712c598251a59839e389dee66f6d9946d275a60c2ea2566cf586edf98, + 0x511826135536efaf9f5f21aee371125bb78412a608bb6c2b6d97882b672a08a, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x2f10170d2aac17a22b211248629533d81da00ca55cd8d70c6fe1b0689aa550dc, + 0x2a35dc09d4488fcaf436c893a13d4489677901a07f875537c538048ef51dd771, + 0x201b1978cbd392f6ce28a5c8d8296732f503ad63e6fa616fa639d7010f2455bc, + 0xcfdef165aa6bea35bddbdd97133f24fe5861913c9b6274f61bdb8ba42e68ca, + 0x24a14555c418ce41b24b5bf1430ba76791abd955022ba31e9ad2cc3a2bc72868, + 0x58d12e15c9d023ea1348b2dc5c9dc2b43c5854d72e3fe9841e1a2b084859ed4, + 0x29e5bd1a9bad6bebb5aab55558fc375c88a8a84cc5d7f3a569c7553f6b4abd29, + 0x1d203c249094728621279f6b8d53a7d2aca571edeae202f72656ae21c825f638, + 0x1cff362b0f9265141da25915b3ff9e4fd8b33d301a1cfb4f606b475fb5d2153b, + 0x6c0b55e10a02f6a9e5e8653b6f52029e076963f51f5a7ef4c2483781303db61, + 0x29baa73ca3725df97d26afb6e2a1a781059b81f8109082c3db2d2d076ac910a1, + 0x16bc71cf059b627baf4fde8702141c5c2ac31a8620a25f36f0f479a2749be7a9, + 0x1cb4f4979c4ba37235dbd8de125bdd0bfeeda74d1dbc8f87a9108468651cf8b7, + 0x1d9097b4f48e52e207dcb5ada14a004918dca62a16f28760d0516c3ccc9090f8, + 0x2cf444d1a5c6ed508013d34ff40f271027c9a9395cac64e6443cf88ad7481201, + 0x1af6065e84bc5d9f653c36a0c86b0f0d9fa8ff396c0cf722c97b8736aaf6ff0d, + 0x2e2c4ecf622db6f1e55623697c70b3dac0850e0369a2eeecafdca37bc120d719, + 0xae82700364dd6c301ef26d8440a1e0fb71e410355cbf7981fecb0e8ebf439e0, + 0x2b3bc2007b383da42e4f34269a47f629392643c0fd903029da5d60540aece8cb, + 0x9bf1b127c22cd17f462ed4972af3af610b5beb2818a9f405d852a168de34c87, + 0x1230f23e20b6011d5c3871017482fd38f82923d9eb4fbcf6c4c12fd744c8b7f, + 0x1b47c720f543277cdb27fd57b57e4a88be4a17f9367f5cc58a541ecd995005f4, + 0x2550ec7018dd8a12e43571625d58cbffc02e10c95e0e9297ba171d6087dd799e, + 0x2d357b96b3252065e81b5f1406be8027ac20d3919c668a746fec4e3205260dab, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x8500e01d94de904d7223966859b160af3f73ee1f67208935a726ef1f04a21b3, + 0xae88a58cd6d7dd1d38d427daaf10cbaf3be27e5abc2c2dbf94e6f4782cdfeb7, + 0x2356cf14cd716531ac576e30978c3e9af33fe0f5465c6928a70ab06769fb7c2b, + 0x4c9cc7ff1e61240f1c0cc8239aaf4522f564780415fc47bffb1c28fcdd5efed, + 0x2ac119534017f94c103fb6199dd0c4bcf237d435294d16269d69dc39be170eb7, + 0xf0389ce2af0f62066e0f0aaab541c7f1e013fa0edd0bad0c454a9befcff9b60, + 0x1df984d5fed72bed8d287cbe3bbff9ac811b56155a8d8f768b7222620bab2ab4, + 0x2464b6b8837edd47eb61562a8c1339d59446dc30b12bfe3feb6a676a5754fe1c, + 0x11e670fa739dc17de5939770830d3aca8a79190d413a8a69280275aa8848096a, + 0x8241341db938388de2e2f02c9f6dab7f2040a2a0fb2d674bd160c8fcf7513e1, + 0x215ff7a8bfce31939d8413ba030f72544092ebfe06f99f61100a6def22089576, + 0x2c7cd496518937ec37c1a7ce9e231f15087c0f266a2b6d894bee197b94b9cd58, + 0x9bc5b3a291f8de24754a6479956a704772bb305f1ab884a7a57a49c6ebc8d97, + 0xb15a0dfc22c6eba5d6617504732df69e30cff2c417d0dd2f1cb49545a026368, + 0x299e24a6a2df4e3dee797a9d9b309af7f38aa11c61bec87b3d9e01bc1b283474, + 0x14a1683e0ced5006fb58bd5f1e8fe10b5b4d5db8af6ee11f3542683d5cfa0e6e, + 0x25595e5888505e87a18dd8e2f3fd998387901198cc9823557e34167d2b6f4220, + 0x1a8ca160cb03b1c6e074c7ea982b1bb406e4b996a70f430da8a7855435dbcd8b, + 0x48fa511c78d046fa7b3f960ddba5eb39e753e40c03e026a13fdf2509362717, + 0x28606b25ca030890e0ab9d58ccb09875465d368c8fff1a9401a18a046d929341, + 0x99c988ee50b5a86686570aade7a07d7f3de7d1ebbe4a72161214fe1f59501a3, + 0xd423b8393f806bb9445a55f82aaa3663b257bce07981b55a9dcc640f9b3a6bb, + 0x20fd15ccaffbde08b904a96f9a18ce5e411128da59c299ce6a1886ba554e8858, + 0x2b8b731f93bbfd2ddf132f1b9f37f820ce2efc76485de21bee2229d03d986e54, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0xbcb4654350348f216da47f8a9085a24211feb151a906c5852a36eb7a590e5e8, + 0xe0bdd096a483b3c7159aecbfbfa52a4b66e7704b05a7df05c3fc79bec0aa903, + 0x2cea662f7c24e8a6111990ca10f7e539dca435c022fa5447ad17f1407b9e2c3e, + 0x260494fff3079a35eae887c593cf5791509815ae31538dcd7432ecc6c00dc0ce, + 0x15c010a4fc6cc1e54cad7f89188e2392df27f7d6fceb4958b7ac68c23b8deb0f, + 0x2f199edbca4bb59669b0e4ddef33a7b45821852699ad8b03c8d3dddd75e8b58e, + 0x1b63017c3c4dc94e32f7c17d67a31901875b20dd6757cbc80eefd96bbf73685e, + 0x21819c86119eee2a93533cc0557b7095119a6c6347e702aed6c41cdeb5436677, + 0x2c7ae6aae298a99a0dc53e2a0aae2cebb636e83e80f8ec2c0ca5e6d30c0de075, + 0x241559cb0c89c416bea1ee0866c17aeba29fdeca75ab98d2890d7e10697d7eb5, + 0x21de885c1616f460af9be2385dcb90a8a471f9cb4a4be8e76b45d0d0fe3f8e50, + 0x179ba320374c3c6c268f02176e13cb0d883f1ae24b145769035ba0cd28879e67, + 0x1ce20457c1471d83720591f79a33979ae70ee1e3830011d9494b7686f90434d5, + 0x9bc17ede919cfcad02017b4c83cc9e1ca6d4695eaff8e983c8451643cd7eb5c, + 0x10993c2085ece5f1f09343dd532543213ba3f046c5a39fca941374a9e8975c19, + 0x11e0deb1da2857341a2c4e2e59d5731fd240da2dad90a1e815b706f926a8f657, + 0x15313d500d879d6db9446e5465f9c08112330c9d1dca21b1cd298117456dc175, + 0x1a3da97fcba266c29d2f3b755892c4438cca1703d3685fcd263728372eb19dda, + 0x1ac3bc17591802ccf54210da2d2bf627725e11a8605503966732d16d82c7c0b6, + 0x13fd9ff54bff1a560857af2a620b2cb2d725ecdab99603c58d4b3d8311f86bbb, + 0x10cb890d09d7922b970d479473995d79d935256c9fd28f62212104d69f3c38f9, + 0x131649c6c37c467b3f8d6bd684c6cd121e1414ce5a2647fcf8d29c84fb22646, + 0x2784296e81cbe1ba5262170b35d24f5a9f428577c73f51888deee3bffb1245f3, + 0x262b646e6406d39067ecf4cd1c4e7d6dbd8f0929a1fa778906f709b8ddec0a7, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x2b78023b50bcfbb73b4497ddb0b519c703dee853fbb53438f906e8f03379822b, + 0x1834d6485429196629dfc50775e881aa5bc653d6186ebeaba1fbfa70d5459977, + 0x1e223eca065f07910015985c8185846bc6104889355c02eff9966f18aeed7383, + 0x21ce2cc395f1ea9eeb8a83f76d5ef268964304f891db51b907b57a39d40c74c0, + 0x3010da41b7bd91017bbe2f73f28d4847f1b15f7caae6f197c51aaad94942d5a7, + 0xfc7aa208e89f615b2b5ac6c1c84db0c87ed0354d3da012a505d3718205f8898, + 0x13153924c0fe679002dc1912a9669bde6c0bfc56893155fdf2e96e05a186b0aa, + 0x1e7ec9ca715167872d062b6a2f92ad6b425a3aeb45e5a44e0798451a5f3c6af1, + 0x1839eb87798ae0b89e6ce405734b770fa2e6092b0670b2f59fd93500ba32bc1d, + 0x2bd925800a8f95d0b2b6ca1ae4aeca0fedac4fbc889f464be243aef61e35d531, + 0xf1ec631ddc6f753f4288baaec5d90881966062d8e00a94d1c35caa5c1f87d81, + 0x9ab5e15c1e1cf58d46c55f0df4fa3a56cf3a41e52664b1a125bf3388887a1f9, + 0x2048f6f68b4dd0127d915cd6d7056a0104145aee77618077505619117f588ded, + 0xeed124614cf28d97c99c85a0a1456d303c6cdd2d2703982a42dd688b65559a0, + 0xe8fbccfb62b0842aaaaae01e8418d005687d3511606ee56c978d0dcfdebd825, + 0x7823b7784daa9ff5853129e7555f2fadb3898b5c4cbef6f4dd5d7e8c78bb73b, + 0x161e2a1db0ee0e75b26abf038ff6ba8b396d0c03d27b794a2eb64394680db0ed, + 0x2816d7a51708d99490bd97f5443df9a5203608feb1bcae4268d3da1e5198dc79, + 0xb298bfafa57aebe549b8f2b0f98554ae00a1761427298040bc8104ad81843e8, + 0x5b5779be0c8c88b6ef985df851f754310267048c6e68139baaa4b41d02cba63, + 0x2954e80ed49eb91d655f32571d6ed24724dcd6d013c62fd8daa0661b4c2e6f75, + 0x11f97bde1a830e979a7647e0eaf37967f2fbc2952bb50ca4575961a34b43ad70, + 0x2edabd7a99b98c5f9f8570c778e460dc19c4accd2de09381db2ae25b87affe51, + 0x285b59b5e4153c7188c7e918dffc0ef798d15695c9fa2921aef01e87bdf9bf98, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x8ebe850428b3b2e7534420e85cc70483a11f33d2b5fdf04f61382f7a12e9594, + 0xbc84e22a29a0c39bf8854d51235e45e1857ea3575fce20e891ea92d8f56de81, + 0xc546f855e8fe5529a31ced2d538dce04cbcc05379ab4f8dcf5a05b8e0030f98, + 0x4beff2ac6db7fc5ba1a66114ef2591000f8822497b661cf15e052719c05209d, + 0x17fe23f62d221e08af428582244a3a31d64a2fbb37f58f8e94bc719b2c4291e0, + 0x129c6ab33dabbe60b52c9444dedaa047775dd01de878636cb80b7d014fc98606, + 0x1ecc6d3b8bbf86ab614c85e5cf2c5dca31d86d2abc8ce91af23d37b52ed78562, + 0x2fa06eb4828858d3a737fa5170fc77e726e8a0cda438a8925fd55e593e204419, + 0x123d6c4cc8a7fd77c53de32f88e0e06bfdd78986842c8691cf7f3aedc43fccfa, + 0x29638f75c4d7ad4d6da92cc3681384bcaa6bda0aa14503de403f330f87700abe, + 0x2ca5b3f0ddb7a5c6ef388e33e501e0fc41a8b16858bfeb10882bd838238ccde7, + 0x1e7e20601229dce04a57f23005d7b8ad0375d4efabb3e276a38a0cb2cce2b7c2, + 0x1bb9781ae7d7cc141e7b72e2fff39fef57bdfb922f8ff88bfbf395738bed4043, + 0x2617acaac7e8547ebdae0bf2063a2056e5b42e39283fcef6578b256fb8ae01ef, + 0x1524426376418adb2ecbbe82913bcf05a08c0db6b1f3d80b5ba1771d72b80f1a, + 0x23b9a081fb49052cf4b2521ff600c471b22cec1c9b9c32097bc91192099f0b44, + 0x1c6cd0f87731287ebb12883e63991ce5aa8c768499f5c976285019b41ad6a272, + 0x564f9765361d0141a69ada9ac521ba33139a1bec81b1c39f9fc79d56f93d89f, + 0x18fba1f537d0bc06888730bcff570f62c8eba352d2890666846ec5c102bbec55, + 0x2ecd94fddc5654494fb41d46c4c91d264b3e17d5f37791df25a42cb680e12a55, + 0x25168b700310216d4ec9fa5c3e3514e712d694a46f169f7791bf4b01cf23fa0d, + 0xddf38a36dac9337b4add0d9a33a2c589134aeeaf141ec5a5b059db0a5466905, + 0xee74216109c48451af32cd7914b41734bdcc37c60e505a9845e5689313cbdf7, + 0x20b4aabbb4bbb48c4fa8155538d772088fc0ccd14ec9ed274c7f3356f9799e0a, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x18de85783488e68b46584675ff74d2bad45d686a789aaf80f0ccf3e3c331d973, + 0x23ab29889e8aeae37282dae6aee3a16624f058208c74af503deda66641d5b82f, + 0x2fbc8d06de03926ff1c3114b375d87283388625872b2966b781d26fb2ba5d7e6, + 0x219e0c4d566bcb09609118df2231e65e9e95f6b6e1c6149617acea7083fd9ed7, + 0x5b21b2c119617eea6edcd24e1feeb1cf75560b65b80af1027be2e1f14a15d9, + 0x5456d41afae3296fd4b13f8a096629d0b471691a4a29d9fbe2493c3ec377ff, + 0x14001dcf0234cbe8b3cf799bce377883176a4904360f83fb5908b5b7df92a447, + 0x2a5e9fdb1272447d7e50bd0ef668bff9fbc860f191c1e0cad1560e74f6d231c, + 0x22949879c5b83ea97413d666ae0eb3739decdbaacf1a33742bdc04f9e449f2c8, + 0x21eb23c8742f8d498029de7d0170a12a031c49f992f07a96af0494454e37d96a, + 0x70541062150a2f25267a8476f41bdacb2b3579c7856ba4904999f92d0b32bf1, + 0x2664518ca87044340bfd8c5a7c2b863601b8226dd566368da36b808691b9454c, + 0x14aa81c9279f3505b744bc86c3acafd4c5b03da18129f6a2b67d73a9d8e7b5db, + 0xecb94b163b561ad361efd85db88614c69a89bf74f5ef3a9387556ca3343a303, + 0x5a6d9a1efabce0a10d3389ed1571283698c90e766363859acc910968968b676, + 0x16b4dd09c4b2b3942c0019d9d39d4212626c492b7c0e7178196899f497f83082, + 0x460784ded949d3691d5bdf7d6029ece2deccf562f0e12482f001714895cbc9a, + 0x2d634ad66906cd6bea2fad599e45912c992901508aa915f0c219d66373c4f7be, + 0x1658eb086b54351ec3573b8ad8201f5a4d1f0026b8f04aca66c44c16e7516ef9, + 0x135a011e081cbe5475a1d316b78c724e181126ef44a9a352515afce9665a9d92, + 0xb4bc94836903c9787cd22b2962a05c42c7bd08182da579e277ec3977418fc64, + 0xa0a37d07785069f47e18f245effcfceb19f2405ca009947c9d2cd95673d3caa, + 0xf8ecd23da135c880c76d216fbda0267d32aee2b4a8039aa5783034d66dda113, + 0xe88eda335ac1a2204aac356a58a3ca503ae4543881ddd282bf7492f253e1930, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0xa4da37955db5d2bb893a0919e4d928361880aad89e87973b93638d9f46323dd, + 0x182420fd6b1d8bb94b35d9587499825eb5055d95f24c5a061f56af516e71c5b8, + 0x12ed236d1a3dec40061f9af7aad3cdbde95e5d41763d8b235c665d25b01151ca, + 0x2d2c50e36f2c2c402493fd98edbb914d591700011d383e289384c0fd26e46088, + 0x2e8ba0e65f5ee53abb58da0c792869bc7429749fdc88ccf7a429c1f35575c11, + 0x8491031ef5da5f6a50fe3e9fe4abccfeae091ea0992cf72a239d0dcc7000c0c, + 0xf4894b8ed58741566403ffb6a468cbe036e365d3b391b72bba73b3f916aed40, + 0x22727bcc3e3f1e76bbba95aa7aa2eb558063af92b5f624433aadbbb0ff33c700, + 0x1b120f999042730b4d2e9f4e22c528510cc26f6076905f37d5a3a6bfa19fd87f, + 0xb37ff36e5153c7abc2c0bd36db33be84dc7378340a8c6259deae5d1422d2f76, + 0x1655564966b05b47d171db24f81917a2296777b02cb30f893571217662009b93, + 0xa64dedbf4dabe0685fb8e4bfb4db52e4a3e1bc178bf7f49f1335bc3cff8fa6, + 0x21a953f0d0ca1d43ee920c54a8a1884a2dc58366e195f4a03270587bf385ffc2, + 0x228dc2c9d913d4f4588376be12a9cf6d55d7c59a14a15f9b8ebf8f0cb801a264, + 0x2b487e5c9abb4812830141572d8b1936b4b8cc3119a0038f773f3bcca83d49b0, + 0x285712493e67ed422052536731a32ab1920437cd807dcd658836beb912022bea, + 0x26c1b715b64f4ba9d47c1f97d99f91ea4b83ea105203bb5e4bbe8b3e6fabcc95, + 0xc188a42d4758ecbc3d35a73e735f3daca1295d0d93d01eed6c3a085ce1d95e9, + 0x2796103374b26554557f1efbf137c3caffec020e1de9d2e75f8a51b5dd52524d, + 0xe1523d8bab27bbf5fdb85ea4eeaf57bafeaf50481cdb89b80483698d4b47604, + 0x172ac77c37aa38790506830facdab06d091a9a98ba0a445020d87a548e68fdd5, + 0x1ea828b052ccc8c21c1417b2479bf21dbbeb8b07f1d294542e6b776c17a46ca2, + 0xc530e36f104f93cd29e9d5f6cc76b4982c8f06d52684ec9b6b6dbc6cf3e1618, + 0x257497d432a5ddb934157c1cf3218a104aa3fe58ec7de5002f82be85ff4a2992, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x9b0b4483df9298317fb5b068ecf3291dcacddad122d4f98ca84868cee25fdf6, + 0x1569ffd3186a443252de5569661c3f8eac7dfd987568aacb86e576d3f6894290, + 0x2335942544da68a26bb05c3c44845f0e9612fb8a6b33a4bd81b0da1811b1538a, + 0xf3fec305e46f3dec280a826087df17baaaca704840038f56f94f35406e6571, + 0x1c4fb366b69eea6c1ad580af7130f33ebe1ec91b044ea1c5697bcde572bfd4e2, + 0x11066a30034b0f5a0ac2e2c5d00720c5e11c1fcb71fa57e7c8dac938e7f4f8ca, + 0x136aece7d25ab58170f452dd50dbe69b1f9a77f060fb99b0e299e9bdbbfd244, + 0x656fe108785a97dff386df1e4e2edb6d68dcfc9cb961e7d44ab0d14847f3810, + 0x2132c9a946b2cacecc75bbd0b90e0fd7f1c864ec818a13cfc266379a48740a1a, + 0x26ce19f30359f871b860f7e740e1361a8dc3d4faca80890059f68742b50c1bb, + 0x7b34bb73c69a8befc171d04fdc512c2e6d29993be2aa537a5a927503d327f19, + 0x1d2076ef57a75151297521fe1aead57b361a0cfd90d9c56e5a4d94a03aea4d59, + 0x18b2d7645f44465de9d875354716726e36f092b43e11aa2feb4f749f5cc30552, + 0x29d9e936a88283376c4cc4105b7bde94ec648a2b02c4be0325ba0ee4e8e59466, + 0x8433318e395064bc720a18cda24df578cab51b13834e03f8303e988a8ecec7f, + 0x2981efbb1e761374fcb20715527de197d32cf4d87871619b505d3f5f67e0cfbf, + 0x28a84e7609bc4d9de494b53068730c0ffd154de77011ac4baa3a00bc1f565c94, + 0xb98fb0a42ca497662d3655e0f0b215aca776b94b0e842e7cc7bd80f6aa01470, + 0x92dfb1809ccdde8ecf61a6602a69fd7ab9ea0f883798425b9ca464637ca1feb, + 0x2229fecf42ca2b725ec5ab861ed051b30ad8dd362a8445e6e7f6e6d888cef6c9, + 0x2efa745708462a56d941659e4d63bbf2b15d7b5cb00f57f7d96de4987e0eb545, + 0x1eb88f6512326db22d5bb8e8ab1ce26efb8b551f8d6010438d0f26f972c9c868, + 0x357f464028357825ef34691fc07baabc77653105a5f895777bcc9fef6e4ca9f, + 0x2574b6b6eac59402740cd9ef0f50e229e4db641825d2fd7f0018dcdefbae67d1, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x22cd7ad481a520d21e467b2fa248d2cb54462c3dec29de294a16787befb181ee, + 0x1ea716292c21b4a96dc9e245738f17f364b4a9dd5cc762c7ab0a24b8ce63a95b, + 0xee07db295084e877f193bb734548249c566945980a987e853cf283e0de49c43, + 0x237a31e787ffab6bd803d4683ca9a5bac9ddc21219d119d5470a45678d916af5, + 0x22d591498fce7c5903d695cb79fdcabebb591fc68fe7a8ab4376279f3c8799de, + 0x25730debdf5daae2460cb78aceaac1540d1b32c4ac3fea8494a832c0ab9f4969, + 0x2f54afcc0ab9ef598814c0a9f83a16d44ec48ee96a06fb1dd7d8414ef40bcbff, + 0x110855e59ebf6c99c61bb7b3728db0141b0c7eb6877e3d867433277bcdb12ef2, + 0x100cbb38383038a7f72dc76e0ecb80487a1bd2afadb85eeaa6c4b38a6e2460d7, + 0xcf9ef03acb7eeee16d21ff6eee6b658c426551d5a346ec3d2226a74b9bbf085, + 0xd047f79f1c409f542bcfcac407087dc0968f9e0b82bc760d1ef72639bf0d3b3, + 0xc8d35b27373860acee2d851f3ff195897a5429797a40948ab0c18dd279cd35b, + 0xb34d4ccd429b28324635894a84e2d095c29ad520bc5434bbc004e43b79a3f90, + 0x15aa8094e890c3ce98ce64cd97f7c21445ceb3c863bdf8a788d49e233cc8926a, + 0x11637553427ccd52d28ef04c564ee9af0647215f7f4a764d97e34b3da65e664b, + 0xd77424bd2852d485495d929abc8ea1e5c2a07a938463db4e75b35f11646ff09, + 0xc48776d02d737edc95da3941a1f78a976c5051bd630deb38b10240cda1dba1f, + 0x23efafcc9a8ff43a2ee5067e9a631b0be21c1e4f028e4fa7cef38919e4f149c2, + 0x24dc88d6144669f65e8c8b0e0b84081de41ef00c3f872dabbebaa4ae3db80522, + 0x27b45f6635340a77f857c72220ab866f70739196835a22952186bc242cd69873, + 0x704b24632239ef816e17b12e0b1f95c1cf7b8f3367a263ae87cd628582563cd, + 0x176cb4987f9f3df738f3bc87712a4635656b484c52ca7624bd1245c2aabf3e79, + 0x227eb80636039b0ae67aa169b29b1ff9966feded7d239c51c6acb427cfb61f9a, + 0xc315aed179cba6ebf5470feeace0db2e1693c9fc11931f51265541c508ca784, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x1b8b75d83e3e955dbb4063f6ef293b4aee18c4a3be9227c3102d29c2a85df08b, + 0x62a3721fc4009918e908846ba5635032aa2eaa7489d5d74b13994486e1b621e, + 0x1f58606cb7e61fb55157784342ec52455c66fb882e3360b692a4677360134a68, + 0x41e93249e317db4958b8849dea281ea81d0e2041006620c78636354e20c45e1, + 0x156d561a4bfbc4b557aacf5ccc4701483f4c44c8256e619b6f7a7dae09d23c3c, + 0x11ed5fa9b46ad4b3f57a8c5084724469f36ba46cec847825e6245c4537a0e217, + 0x88a5d5188be741cd0e0ccdb10875d3fa01889e4f80e5be6ea7e127d5b28963f, + 0x271a632b843846485e2ab0f5c7d1e14f7275fc53b8cdcd8a743b7566461219d5, + 0x26c0a1c6632015e8689db93c50a3dc2e408d3c0521774aac099b931d7295c6d8, + 0x294070b0ef4e6a55e885a12b5874de04df23adf8f0a84f875cb18c4ceb8d101d, + 0x2f78931d96c5fd9d0ff47089e98809c64f5aff58b2d70080998bc0fe5e364303, + 0x230be21d8ea9e4c5d2139afd1b0eb61d14b227ea864c09175b23ae4a647d67db, + 0x23835945ae05c678cb2b9bf9100f51e7ffdaca93e74329a968c392bba321a232, + 0x187c39fab3ecc634166d78959fae651ab19b169817b7e508762ee36e8a88033d, + 0x194c8955c7e620135e624ff5abad58e58b5332c390e60f772e8b4dd477270dd, + 0x651970e3e8b816227d307071d84fdd9f417a2f1b844b7ec56a21a7b0241a684, + 0x188d9c9d0fbc3459f6a82532f1109a06c591d2b37df750c287244908f193eefc, + 0x3b8367be80bf4f8e3b9008aa9fc640b6cfac804451c91a6c51d60840f9e166d, + 0x8762e109aff306b803a0c90ff1031403458429b82dad5066a7c61c4fcd52e10, + 0x7e877480703f745c67b8bcdd6a1182bfabea54eec3b62b87f53e9eb6da0d5bf, + 0x83a1d0511d5576651a78abb8a14ac92d9d61a43f977cb5dc9befe2150e0335a, + 0x108f56572334a765f54db2146eaf1b44fa39b91203a58d3771eea19e46f3b58b, + 0x253717f1b3a60553ba8c5608d2e9b33db2e5aae1cdda665006620589183158a, + 0xf7d259d6a6986193bb88f21b9f687548b9793b1120e10386561ca5be801e762, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x2caec1da928de3ef257ea69d514c718f70d8d3820fe135dc81523d2e13494c2, + 0xffcc49b0327d4dab23fe993539c71e78cece70c65060fecf775248a4f3097d9, + 0x7d2f814a0d52f1676986648041c5ae57ec9b5fa328dfee5a22206c0f554fdb8, + 0x563d7a79d5f32dd2397acda206a6fa4947572ed4050aab01dc732ffeca2369d, + 0x2783fa364653815b9474a9972f573d171d08b4dbc9771054f0bc376a70eda070, + 0x26d7a7687e6c207f5fa597c84565bbe9d511243c1917de8656babdd38ba0eb81, + 0x1567832cd70e77ec20ef1041351577510628ac2a1c7d5c179c98315ff78c42c3, + 0x1c59c4c25db5ec760ad403047f3182e0c2db7b557883b227f8bd1e384a7b76e6, + 0x2fb984c5c36a06d07601fecccbdd1466c38f2ee47b7dd526a34bbb9e859a1fe5, + 0x193c691789f6f175105e969cabbbbc781119daac0927a2694d006edbc0845084, + 0x2934cca891879574e44e4b94f5554dce2e55070b19de421b4d2b743418b287e3, + 0x2223f7dc3c04faddc22f1c05e786dd4fb2837a1425c62d4defdcec15ff6fd6a5, + 0x267a1cd4eccdacae7277169d9000761606b0bdadf24dc97b6b50ad18f4084e57, + 0x23674c9dff69d9b06d1a41103f5b241f788624c972203d3a4804e2043eeaf97e, + 0xc86000f5a940dc4c26b7c2dceca10416c0de08242d8057506a867b181691451, + 0x237c120402aba89b701d7db41968e81e7ca9e63b6242e56d9e89b1e94b7b56f5, + 0x1f2adefdfe27e85d550a268e382e6af8e51b93d0303444311050a0bdc3a86b13, + 0x21026ca9e6c15e7e7754c24c15ef12d36969bb2505ea8eb9d24f21762063639c, + 0x257dbf207d8341ebe71a25c67f0bcfc71edcf46f5e655c2f94bb0027683e4ee7, + 0x297fc3567244be37e4b1ad88a0c3008e1f1326146b6588add2e12b812c53c7ea, + 0x2415eeb2220c514b4b50cee8df2f4f605477b540d75325287fa7df4957c388ed, + 0x2d1efae2ebd54890a00e868372dde24a8ab026c7397b54827bf51bf259371921, + 0x1f82db95c67b46b630a40310d8081c760e1bfffc39e91f179b99995a8e355615, + 0x2e817c24b08cf9346a21658572796f90b8132b6247e43a1d099c17b7823592c6, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x588c5021b24ccaee3b77fce64c0122f3cf21280619404967af6be821ac9e37f, + 0x191e71b4c665fd095461c7eb21794e3770c3b40b4bc0e22a210166e9c74aa0bf, + 0x29cb8c9eb9c4cf5bc6e1c2a782ac0503015efefe2d640a154e26b4b934dc9713, + 0xec1e3897905c451e98b774b636e1dcb80edbcaec959ba90d20a0286366ff74b, + 0x2ab786b7ffa171bb876603834679f4be8a18485f93b7b89f2dafeff334d5469e, + 0x204bbc64ac07613fd02f871122b8ef0206d670cff609fc1b2fdef7b8f1e1542b, + 0x1172cb8f6bfe22d7851f746626399b3c0536bdc6f8969c3b5ca6b697a87aba5d, + 0xcfcac24e6e99ac6a59d2946dfec1c87d4c14c95a9ce2e81ec8c8405f74ea79, + 0x25787156a9a5949b6493e08da731b2e15abb30e1d460dc238207d04302a7378c, + 0x246ac305851f4cc5079ed10d769d337af9649c46f374951dc674b2734840fe38, + 0x2db9cf683684eb9e2cc772571cf8da1bca70e222aab6ca7e60df039de8b23ff5, + 0x166212a0652ef46c22f6d8d8d8c53d99fe339c7aadc68b233c882f57925403eb, + 0x98c9afc1526b5729198f7f58b905563596143c611e1b2c8ff90dffc677d1e66, + 0x2358d524ec260f839956563785d1a727fb364547edecef5bf664e5706301a599, + 0x1901be07be45b4f8d3380b0a5e52c1e6aa94dc4f6f2e40baabb9f98fdebc91fb, + 0x92d99a4ade91479cdf8bcc22c05309ba07d86401532aafdff17bee681dfd12e, + 0x13af4969555a7dd69482d1c130eb70e05f0f9af3a93769f7fb5437173c71e1f3, + 0x28d3aae218aa0b296476d0dc373481f4ae746de4aaa1c8328370f17655614a51, + 0x14311125be69290b098c5ccb7e7a9534732886959d25d677e564d71ae1ae7647, + 0x1454832e2ed446d6ac9a981f567c57663450bb35ed147e4dddf8e7fbe30b0bb2, + 0x11055b5dc675e97c22358083da749bb066f8a99cf11a37083c1c991af56736b5, + 0x20b2ab6a88373738fec32590661140fc911f31be20d8a9b938717954ce5f1720, + 0x2171b013bb62ffa512500bb1ebad0e10cd39cc7094cbf806b10133a9f6ce3d68, + 0x13d9ae507067e98e67ca97ac691f2808251ba846c97091c99e46f8c03d6896e5, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x292e6fe5591c886319d394a3218aaf4a8fc00b2c98fc57a395ed2b52d72e5d1a, + 0x2e555bbfc78425a4fb2d9d8922252a1edb14ee448532800a36538eab6d3c3134, + 0x4b797fd25379849c5fa7039cbface5d5f01d17102671767c51dcc547a7c7f44, + 0x2bae8ca68718d729374e99bb9991ef4399fb9a5a14ff7361c52e4785781521cc, + 0x5ddac723ffda8067c2147fbae890884bf8572fb7b30810101de4369defb5612, + 0x1ec8e17ebce279adc46dde550fda171ed22736ce4e102cc8e36f3844ac67d77d, + 0xdc57f55bf67c1b68aa35126491d6e6b78f9883b5efa10b8f695e2a8fa0b83c9, + 0x2d3f4bced64b64b958b8d91bd0b7b168ba52bdfc7d5df18bbc1a176fde11b23e, + 0x2f10a6d7f877c814bc7693395dc357075d1c816495a4f03b0ba49d6d8d97a663, + 0x144b40fba529a8d725cf78c898112fc3e4826c83c1961332ed3bb0e17051bc67, + 0x9708226dc1bcda85d36d65ad6d0ca69340523e970daeceb5cc48c16db6cf3a3, + 0x1bc361e4208a017e152377add553852dae1b334c7948e008f7064f499916c154, + 0x218d7075025c32bd6ca4e15ccce886ef42a54823955d50d1abf906be69a1a10, + 0x2c36609083d08ad8df8211a51e75bc9b52691cf5c9996dee6cb39a13ab18de9a, + 0x2ee25f7ef8fed9bfb691d8a5e21717736795bbfa76df861492715c4b41261112, + 0xe02bebff560e49b14818c02e1535c5cae326071c0d74703b8ea9f1950e78e5c, + 0xa8e935c09bec781f68587e8aea897db4d3e8d643d4e8b65af941e6b56b35d82, + 0x24e4c8a3880c07950af15e4dd7785fdff4f46709f7e8a2dff46ea7670af9e69c, + 0x2d680316bb7fde988136fafd42ba36dbed8d09522f48ddb19a14d39e2305e4eb, + 0x151fc0242f88cb4b820f7960e519aa333c50260f1fac77ee841873ce4830a5fc, + 0x2a930a97b841a2680717d8322c463e7b4258340f87258c90f388f322b86a173, + 0x1a2d3151d244173a73624601b54782801bc6c0f8f7a70a3afc708a23b0af75bb, + 0x30ff291a9139cab6bc0b3568c21ad6e4542cbb3c6ec6970f01f4ab3f4e65a8b, + 0xc6142a38ef9e3709c786cf42056291aa1581aa5cb1e1c2aa01326501552075f, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x4478466a9c94183c431e91e2d96fad76caebc38cf4b6bd63d40a883887aa0e4, + 0xd2089c7872a5e0d120339c683d1243e0f56dfa30bd8ee38e9e9020be57cf9d7, + 0x7835f14f646ef12bfae699393ca8771079e5e5b105c549a6f740989bc71522d, + 0x2eb138b8e96a72fed66f988d76a56425930f788d23294bb16c006c15ba7a830e, + 0xd65fc46a4f555afe4d613d16960139d1b0ab9e97409be48d2c7d0ad708d57b8, + 0x5cb9d6fb0ea5d7c36af03889077124e159baf3f95d68f5c74b98db89b1fc3fc, + 0x1228b6eaa51d6497f12fcf864b7dc9d681b32176cab3dae788d5cdfd5fff3732, + 0x2c74a92c8d33ab0a358ff988fce0aa0ba475c783989734c9bcef6aa3d92e39aa, + 0x1800e5ce9cf840e32bbbe62d828c95e79c3e1c493ef70ff8743a88431b34dddd, + 0x58ff670014f46b7ba4bdbd48feb903fd37fb5eec4bccf5af21bda415478ecc2, + 0x21c73fcf9ad1b0107fc527d61e6d1a289ca1eb4616db1bf402579c7a9f141c61, + 0x2dab5b1427ba55d3fa1a90d83b0c569978e3ecfa9247509dd3f9e303b58dd0c0, + 0x13b905c6ad4434dbff6e782cf470c7f37cc129dd74580eedd8a8f85f984486ea, + 0x16542d30db773c54daf9fbbe3cc6329b0f1e30a5f27659b5718e073a6a3ff993, + 0x2fb9d2c332734cfd46c26f65328fccca168f58711368560028e2953c2a70965a, + 0x1bcbc6b5cb163a446455ed0879da1196a6bc4abe45d7b81af746f47db5292e7, + 0x1ddcf7b0e9bc54a5074e021add723164c981f6bd04db9e150e2f0e21a1a6a3d6, + 0xe49ca4ac1a6893b61701a02e1dd02a35f49e32a7efa7f297ac4d2c3e545b7be, + 0x268309dbe299749682f7030227677e5013880137014437f7433ad9e14ca8dea4, + 0x1bac242faedaafd205ffc4e05cecec603beadfe07666a7f970934a2ac6f629ca, + 0x28e2305a80b016478868cf732f9013b976fc92a34d1a4dca77ae572c3c69cdd2, + 0x145de9f18f59e36a93415b33aeceb48554a84eba20c56044880e1466bec0d0c6, + 0x1acb49bb5f0d3c9385fa202a23350e945f57259a6ece8a15afb3bff94fe92e13, + 0x26add7d9ed34ea73566b208120678707b1da9f64243c55a41189445672f974d0, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x16051748ed54c9e8d56e45a45a4eb202c4c91fba4ccfa8a05ee3a99100ef028, + 0x1a51e1a75bd54dc013a8365e8be4d93fc365ed1f85a41e451913a035c1a975fb, + 0x26dbf99d1718983964d70e45be99a786dc590c2b06726631e73e42cf19bcdad0, + 0x1132f8662c582598c12b82db868060fd02ab2dafd730d149f0f1c3dbb5c7540d, + 0xd20abd1b87b2dcc09f4abb60b6b936bf3196166849307a146bdda7953270fbf, + 0x1312f989d76c6cf93d0386523c2b447be5eee1a76770859a33e08baf79df94f6, + 0x28c79fe778abea865b37cb9fb6fcbff83eb5e3a6539a22c18cb0a7bb1ee3fe, + 0x19b577228ad8e6ee6c9b669d36ba8e0797ac74616e3efcc9e6a7e819610005de, + 0x152dd9b7778d894130a215abe32065d7adfe95428d02982301d4390896ac4a40, + 0x47e6db3dad97b60f47207eaa4dbf769e64880abba447ab42a64b4e9bf580f, + 0x16f9ad0b2919753c49509ba57e9c915aa32306664ce92ada426a22c9f6360d66, + 0x2921d7437d72b2235761183fef2292d581d60883f6f05163c7181e8930598142, + 0x361282380fd4190823218380191766a8c2eb6ef8f084426f9ab27ed7503d0df, + 0x2661574bc57b6eaa30224ba10cbf4c961ec5d3beafa17d846e660915b34b9ffb, + 0x2b50d64c6224a9fd03f14c5142231a82b313392062d70bb835116f71f861931, + 0x2e43be4ca9acd39a0b869ff361bdc22679619dbd7fb937ee499ef99c14b929dd, + 0x7458dcba827b917c731799c95185ebf349165eb8bd8837ad4c9a7a946acdbcc, + 0x2e565ac1c012c9b7001654e5c4b389eef1604d14da21e2cbf4682ddbde00ffee, + 0x2be1797b6ee4dab5c76f370802650571f72ff37afcd535e80c02a984257a4a31, + 0x13df73795946cbab79f5ab95a1ae07beeb368b6a672eeff9533467574cd5b637, + 0x271f3f4aa97903015b64624f4d65b15cd2fe5f18fc8dd6ccace0c520d5daf9ab, + 0x45e4c5231979d20d30f98e26acdd05b44c6101af23bab61b22b9f2ed4c2bacb, + 0x265d868fd9eb462095cd18e40ea2aeb074153cfc06fe0c62d268fc86e3fa1e9a, + 0x1c2acbdc137e6a8af39ad351f8e89255387e69c7d9cc4aa0cc0b4a3c9a2b2dd3, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x18b4e73dbe4d9c83510458712484b5a88154a64e4f000efd8a5d2d960b4d799d, + 0xe2fdde439a5f899cd7f813089c26f68018a3b0ecbfb2de15589e589c77c691, + 0x4f2b25402a03ac3a6fd61ba2e73b5acd1dcc221704afc22ab41ba3b158b7a5a, + 0x2ce09acd57a7c33da7a3083fd7336f59f1a21bb7403cc3152101127083df270c, + 0x1dc51c0843736ba1d7b5ca4ecace075a61486b9781deecb73ec0c9270880a5dc, + 0x24c96270bedcecc4ec08285665474ba417e43f1277878e25f64c7ed59d518993, + 0x1567b25ea10aa7639e7754e07fb26140e6b196466301266acb242ce0f80baa9e, + 0x1b8405e13b06a1190bf60e3fbfc762ee365d6e42a551c9449ac6e78c25c313bd, + 0x1ae7fcaa790af2f4aec1458d5e8fb9d2f6e9c4e1b3877eba711ad016a8f75883, + 0x230ffda3cf04839dda573ecd6cf6a765f419096e19c41a27e219f7624f63f918, + 0x1c821c8db96ded0ea28c83e01769d47e7cf531e5ee167154c5942dd1552c99c6, + 0x654e2ce5de54485cdbf636ff35aa519d3bb0ad0f65553c089035b399cd84ec9, + 0xcfb61bad637440ea70c21616c0021531b797dcc910b94583c7fa278feb71244, + 0xdde58a2d3a19ca8daced15c92f831571b71a3bedfff56df64ee3d3fea7c11e5, + 0x121e952932b7e95de7ec84c86576ce61bbb862ac2f13270054fe25b95540345e, + 0x77174b4e7741e4131a2adb24c6c9f223bf77e2678d9ae5b3279d86e55f87fa0, + 0x5d3eb46a0d9a2f0f47f0962a63d534c9a77d3927234620d2c928bf09ce7e5c2, + 0x246f5a9f3cb48cf1f4a13aea5a54ba53d8d3046b61871dfc1fb5d9f358cb51bf, + 0xa2e62faa91efb3dc7d4c6482d41ced93aefae8d13275135e509bb3a117b19fa, + 0x21eaba42c45ccbed93fe3468dc8b98fc42a9855e60ce78562080053784c20256, + 0x1e2cfcac1e924008271b086131dba3dd0044a03a28dfbb2f008611fec230994d, + 0x2c97d275a36bfdd250e2e2abfc4953d8e04d5e92795a914aa91a168f1a993059, + 0xb1d67cb1a69e071bb57b3f4eaed9fb9989c12e249c0900920bbfe0fe7ac6c93, + 0x1f0f655f87c30461e7c2d6a3b55d5092e4542c805f29ded8c499fe4603df979f, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x1c9a4884cf6e9cc19782fbff77ff6a2df0b1353c2e1bcc80f80685b4da9a9962, + 0x2031dbc469ef5d2ab8bbf080e779c81da08a138d18b1bce086d9650d044cda52, + 0x26d411c661443edb9fe290206a84618128d1e85e1a8fbcb9908859876db87376, + 0x21083c2f6587d4d94351b5e8d4d37ca1ed3bba605bb05ac45151c5b828acc8e2, + 0x252aa5220ba089fec5d79e776cfbcc3be42167e2b24ba6245dc60c7cf0fe818a, + 0x15aae505663cafd83758de1e586058a24e69295863d59c1221678d0a997af128, + 0x2d8e7eac5ca3205436aa38fe08be53a0fb7b57e4c35abb9c8dfb722eabc4b4f7, + 0x1d4b0338ca8f97e7f6da84d54af30e30d065138190d0c36098a69db08f44b97e, + 0x1af838255d6973d5b0b19585c52f4dc7ac7ee024b541e4c103942b7485a5f82f, + 0x301b9339d3863e05daac5aa39aa79eb948f6be9a56ade53ff27fe98531f1ba11, + 0x1e03df8a06e4161781c43cd5da85f9c521dd1f5987bcef858048020944852c7c, + 0x2caddd2b00b5b15d18a3ecb0d013c71966ca47d579403d64d0b41bd736ddb7ac, + 0xb87a369e470ab99e2c4349ce109985391d848aa3b60202f7a17ef6a0e4adf1b, + 0x21814ac94b3e32f6f295c65c4b234aabde202d9607b171ec00d826f998a6c92f, + 0x29b1228b3346a79953774564fa631d8aa6f2314f2c9216d4aa8d89299909f352, + 0x1a5e40ae67493e00371f4796181b9c0ed9f909bc5a6d9361f9b75b4c5f48d270, + 0x1ac79eac0e5bd64eff5d74fd02f19cf0a066d6e5ad8d169a2ae42a935f454e3c, + 0x1cc1592df343627349a25bda9ff38febef99da952ea6d33014b9e062d0b9c65, + 0x246ae2ade241e443bde03d8e2b323db4208434d53428628bf92a2fad2058ec10, + 0x18d00d6e9f9ca8e1f315aa97fa121430125eb2ed841bdd81f1efe69379f786f3, + 0x2a147b464ef73244b29cc4e4fd24a29f0fcb62711a840ed075c77682801b54f9, + 0x30188a7d39b26173b10d7767135b841640c15708089e2be2bf8f5d31861ae140, + 0x1cf70ee72aeb25c85554b6de9c01877c8ef5164a1e118250aa14bb0ff8cc5d94, + 0x2a27cb25999e82f8abee1351c8083c8393e5038113619e783649651c286967ac, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x16f3b44e7a69563f9b9cb04a43140d2c51a2a2641b9dd9ad5dd7b942b3898e6e, + 0x1ef9dba4b9fd5363a7c5855a1c3ae00c1874ef693336b606b1f25c4fd32c5b3c, + 0x3be108cd7d21185b6364bd86883fab9fc63c9356edefc708c05882280b75515, + 0x21631c522c8f458394bd234946f326f0a0e0caeb2dab4014e8e089f36b25d766, + 0x2b469c787003cdcf37233bdb9f3eed9dabeda742284d6f7286a426bc9022fa9e, + 0x409e474d3841d04d8f6a521cae62224e4d15d729a48f7af7357288e1af200af, + 0x239db39ca9b31c21ec61b7f3306cfd1a9c20b3aebf0ecf4af7df18c2a498ac32, + 0x3062a14d58830bdfe5c97f9111ca779b253e09f8337e457a6c4ecc1ba1bdd8fa, + 0x22e8958e08ed54020aeee58d8bd6bd816c3b99f53d664fe6c1bbaac2bb5c12ac, + 0x2689f68f2ccab8aba87dad5aaf8f24c89f24d94c33a3554413ec94c9309c2201, + 0x7ddcd764dbf337080c16b4c68e93eede25a567bde1f7dac0e3bcf6edfb4c472, + 0x293c704451a1aa66e1aa0d4c7dd56cc5392fd8cf7b8cc998f6a54b8c30b24e19, + 0x2cbffa47d2c28e5d0ec4a2dc0a168ae258368feea0ba17662168d4cba27906b2, + 0x208c5ef46b238daa217fe46cc26ae7460c70eb25fab5f1122f4edbd48318946, + 0x24fe6c2e5f21c4cba02f4c15ba1d07c732017ac72f262626eee292a4c3484c8e, + 0x1dfde7457418ea9643108cc1d13371791b90fb3a4346f4ea6830fc8601afa196, + 0x19eba78507eb7f4332dde5342776cffb8b3f53973e9d191b0f312f7f05c1e732, + 0x2be0c4e211e0892ff5d3f3b7aa0281e1602cd23684b82ba12cb61be1eba411f, + 0x9cae53a049def9f8088909b1ba59670f0d8a2180b04062eb2c8cb2c3893c11a, + 0x2e2adf7ac157ffaddf5ba5fd0b3b009b13c8e1454b54d298e5a50f15ba24a957, + 0x960206a1b5fd7f8caa23c6f979a77b2df76e53ca4071a30e96e203f6d611945, + 0x1709ed8801ed661f54156b3da294eb591aecded73dc4bab8e884618899d61929, + 0x213a699fb63a980c7dd352008ad46d6c423e77fdd87348879208531b1dcf7de3, + 0x372666a5afcbe6f5458e78471e9ef6fcfa3420dea49e713a8ce1c19cad53b49, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x17f4a43fbcf12508a933527a8912f2842333780fd30c0c46d15af216dbc9251c, + 0x2c5744c9ae7f6d8c3d5b66d4d43b95afd79ca38594b9049d886488cf10cef463, + 0x2dafa6f3c603c4c0b0ab7dea2b559314dff4f7b2a1a65894613d2194595f4476, + 0x2f7218004fcb62dc5ab37c7b3803626296dd6f876ea5eb4834eb7626c1d82217, + 0x6dfa42020ea166652a7a392a6cec8a63171b943d6853730df3c846e32176cff, + 0x23f87a617f1e8f021b83f41ccfe5e7526864953a9eeff56d62d85731ec090826, + 0x1cda3fe46da8e3f2595bd22ae9327c2d2968ffc0c686741a13456fe5b2185861, + 0xfa8625bd9c3af09956eb74e2f983eb6079a050c0186221b1a32ef5050969007, + 0x111520b0f559fe2476e6a6f48060038efb0166ff9f6bda812a02f793228af23b, + 0xc23dee172299609bd3dbc9f2ccfd1e3f76e594c5ac2c3e5ddfaa62289ed7656, + 0x105f42aec8a1b60c20e7041acb94bfeb6f6b5f8c5b71218fee02047d57c0c218, + 0x299f915785e8adc1c2378fedef3083e487db1f6f1807cc7bc66e51b73bc39147, + 0x1ef3836591f803fdb8a0bd89373dd79176fbc2e92ede7006faa5d95e9397d81, + 0x1a2785db4d9a3409adf3b7ddca9ec408b2f93044338ac23122588de468c59408, + 0x1a6ead13bcc1a5afbc63d85db0a41c4a031e480585fe7ae5fce9b64bc866a216, + 0x1f5996a035a306096eff22ff3aa805378e9f4e3ed56f9834f62144f57eb2d414, + 0x238498bc99b623c9fb4daf8ca4e4c87607338433a9bc2546c9f37c86af431840, + 0x273915d627d37ede450dbc5e96ce9489b78ee048f5756082227e62db6b9a56df, + 0x21c11618cdbabff657a20c8d84812b984a017810e97ffc169c585ee296fff9fc, + 0x203e0bf4be8fe2ad1f1eeb4926647caa4f6e429ce794db082fc07ee5330e7cf3, + 0x294ba4a28f070410c4c4f8cb5c09a56252ad05dbe4b5bccd24a4adb4fdf71df7, + 0xe403cbeb904d1582f7872035f81eeab4010de844540a9b2bfe5419d43f8bbb3, + 0x27c86e516b80bede0756a21db1a6ced3ac126996f64f9f6edfb2417fcd3829e9, + 0x26c02ced384da01a247d225b0931e3310f7f689426b3384c65bcfcf1a1e0d8f6, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x23c28b7d927210270a66d02ce14454c7608540c1c4111989c66fa5c83b953441, + 0x175c47171e64b9fcfd9a0e5ff2cbf87d0911c01f7cfcb4287a219dfb65a3c946, + 0x2b0dc6705e72fb39676c099284f87987580419e380019cec6529297780e9f143, + 0x2cd30e4b096b2ac50182c596fc4bd8de276e1d1f058acc010bfe056b50498347, + 0x213717e1ab4fe340c8edaa0f2b003ffa2adf4890ee9ab0bbe6528a2f4e436184, + 0x167ce1eb87442469edc20f5be85f41176a2bf1a7e44ad9a920605c5be99bf975, + 0x2c0874699b7fbae13046dae49db97858a6950199f9a3f3bf8238aeeb73501797, + 0x1a565a10adafab01ae826b619cb79c9c7420a140d41365669ec361b37cb5c8d1, + 0x2c8c416f3d61924456ecc73119c6ee327dc717b411a4ebdb673b48e8ccd1d4d5, + 0x267fd0effc34952354f05332b71fe925b3548f0159ee361467784ef8fb986315, + 0x2bd251e35bedda84bfaff55de37d2835277758a60db4a9bc4fda3571df5ae523, + 0xb7a443712b33fcd61028542457a0da3ab1f087b58aacb25439af6e1e55375a2, + 0x2404133570623570acc718f19ff26c6b47ba03857394f55d17e8ddafd46cb5d1, + 0xda485d8a8d3a97968c8b0789dde653796430641c4dfce40db5cbaea4f392071, + 0x2146d7115c9adecdfd5ba061103729167ca82a2e9e58df7177d10645a23744f4, + 0x2c957d723ab55cfa5de8995ef9904c3be5b70b5774a12d17efd71d7fb10b2895, + 0x80bc3e98f6ec909c5161c498e0613bb736889eeed8ce7bcc93bed02f4bc5be6, + 0x19dcf73cfac4b44c2761e024d6cb2678cc104a528c02799bf3a091908ae780cc, + 0x199422fe9fa1f5d2dbf402c9bd634d4bdc9cdaf70fcab9d0ebfbafd12a02e49e, + 0x1a4077b1cf49f41fc3a2240a37ae60309d6941b839ebf51e1e118c16a23c6aef, + 0xe53e5ebd64346a83c1e7f33878ac8753b1b45f0e1747f680311eeccadd89a17, + 0x5aeff75c7b60d39afafbcae4f99e77e223c35e301db1dbea5becba73535885e, + 0x1f9764d4b036ee9b186d5dc379c2826b17595849ac829e2d52230e243fff309b, + 0x1cbd64e54e94a1499df6fd784df7709f93942071463eab3db602a804337a436, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x190f2a683d41d29fa79f653057c0851c76bf7301c355e46d514e62a2116d7188, + 0x358bdeb885279de421d0b5bced75e4b0b909340f8a3445a3dd17d76e4abcd1a, + 0xbf755f699b7e4252b3fd62793827e613c40b0c1285a2eacd4ef65e3abfd281, + 0x26753dea98885ca2c4aa18a49b9162277722858ab51e3a482275278c53842496, + 0x2c3bb4bee55f665db599acbbb270af82a9f8320f7c3adf113cfa86d9cfb4754c, + 0x149ba255f720eda11444f804e9814260008b187f26ce17e4152c092dd477b00e, + 0x21344c682b1f31453cafeda3081b76096340dac56062762ca80a78870dab3bec, + 0x11b6c7953ad5ab4ae16f501101b9b577f0b8a1d7c6a793d66e4fa161b1e06e52, + 0xeb1bee9bfa6eac0e22bee9a13fa2155ebfcabd0908e74145bbf9428ae0b0209, + 0xf89e6f767ef77ce6ec818807d30706fc114d9e02aa610c0f3f77a3a08aaf9c7, + 0x18a72ade9ee9765de8ccff2950b0a3e8c8abb4a336ad417ea75837e8301b8dfe, + 0x239367bf5652c2b293bf645bd88f1169b6f872ccf8405c2b4f09f4d135f6fed9, + 0x239747dfc96f5ef11b8573b4714b20381ea4ca958761b44e11872f306722792b, + 0xee7d51ee88f040e9c21d5362bfa085adbb01485abe1ed5717b55b8687e40b31, + 0x216277a3d920e1266639f61d0c22d76858e85daf5fa83d6230c6b1628a077051, + 0x43527556626973735d511d252e2a1dd3b55026e3d5b38324a50d1cd44d0f9f1, + 0x16e435ebcff7dc72244e74fef07cda6add05c08a52cf07309bd2eff2ea896b39, + 0x128020b31dce80e89ac5e01bb13329cea3c62ad115a5d65ce68555e4494a867c, + 0xc840cb172dcdbb1502749bb1beb46e0439aa167caa4317282fc78056262eb46, + 0x542b0852563c2bf928db174369c82da60d6d41e9c61425d417f009c46fac67d, + 0x22452f2d9043bcbab68e526d22af55fb835a3e554e5101a82ddbbcc047411884, + 0x11b919c0b7abc6b28c582a84c158d5d68c928475503c312f86ad3a2ca97c0ec6, + 0x2d1e6445ea67dca7ec1db0b08659adb177c9379f4569bd3efd060e06d0bd01e5, + 0x251ba02f642cd5e0ff35e008a0a309c4c6780dafa9fac55b163256d39a4e4119, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x2f09e5f58f262c5f4c9ac2458e58dc1c3f5e0a409ff3f095d8ecec957ac50f2b, + 0x1315b742c5de4460a27229e970e546750da9ae91fe8ca5e51548c60c12aa8359, + 0x60e6ecb8723e793eda04e490c818bd07cc8a972dd900d0cbdc4c28c9e3ac13, + 0x1677aa582feef6ec348f1b194f4f978d6af473133203d0d22a81b08bdcf26a9, + 0x106e8e67c7213d1c649b08f8163f849d0e0cb36391672b3dc5e632983451f457, + 0x218baabcf27c9046b7ce52309a3d6d3a2ca1b3924bd2fb64c157353a88567c8e, + 0x2b2717d36fdfce6e134f255adafaab3d1a9f719b3a661cc1fe490b1e190f2b10, + 0xb0b2c3bac72604b4c5d568e4f4cf53596050af1e7bac3627e9b2cce934eb482, + 0x217a15b51fce1bdfb5678864acc464e95225e47ea40bbc78155c14a41f2be20b, + 0x1ba5231ae9c793948686f7dd7be9c44435dd6a981b3e880f344e2935e14b64b8, + 0x253e39215ddc07e604684a22eb2e7bff9c138b17d2089ba9f451cee209f14177, + 0x291dfe1da2b968d3837a2b2b94f8eea9606535776a260664e8227e212354ca64, + 0x1d3a7e1e04c422de9b7e0b090180518372473ae8ecd8d1fb81f4981bba63122d, + 0x217d25ca6a61a6551abe4bde579165d171513a7c15fdd69e62b46269a1cefb04, + 0x1d65f0b99037a8506c7ac7811c3b8ddfec719fd951a7337dd01e22c6e00f4d34, + 0x2288e24daba6872e61c70d8a4b8dbc67c63a495d41649761198efd7e4275882c, + 0x29811fb1aa54a2592816797a866eb8126f4b333f1526eb6e25bb626224493360, + 0x2d8f4b4f41d9abbc9f03c50e4da5e64fdfe87c5d07545cefcd30131f20f00d9, + 0x28d7a552fa2a86a8dbe41059439b0e35614cfdd841e0d6ef1db1af78d7108e4f, + 0x96cddca2ab8c7ae201908ba1a671a9117e24ba7bbc16b331babdea12bcad5c7, + 0x23e387be7e8d63cd8b769e13b718b560bca4a602c8992be3d75e71747a10dcfc, + 0x1f77dc7b1dd84dd7ec1069c065121f51c036a41237408070c45ff15d2462a60, + 0x7765f1e2b28bac34ff4c1574654563e8f672a14fb105676a57f2554f49da9c, + 0xe1356ea8e8068b1ef8287fe1362ced74d7e1ec18a1bb36e6fd2f22593b51e9c, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x9d1f2588934f14551f899de997bdbfc9192ea76d1490b6bd5e1d691d3403af8, + 0x1d48285a000b66b39acca3bd48ae38d761b590d846ebec486db4899d1d3c4d72, + 0xbc56781b0480256d3661ac6e0898a7084005d607165224d494103866e256c47, + 0x88867a8bfef1eb88b2ebd34daf3524cdc118d232bd1b91646c11a2a54556b06, + 0x29938e679bf6bec4d293fee8615186bb09287291d69bd50953790fb09db7ff36, + 0xf3078e2dba998b8202b3eb91f500e8cdf87e2ac9f86edccd8b907b1d73f10d5, + 0x2feca0ea4cab180c357b1dcef1e8816caa115f572fb2da374e27b2f7d2a17108, + 0x19a53e4e1a8aa7a15029ff45f528f42c8dd0360c8dacfc125ce7d192a0a70765, + 0x18ac83f6bde2bd90432ee9fc03f0e62871969e8ba27aa1dee2c72e2fb42e9351, + 0x2cf369a36a64a81b17c4521b17c8ef65d09442ac2858d03785fff1f8ae4e3881, + 0x16d6acb3b445a2dd2ce6c6bb79f1f61f15019a090285fca38fbe54e04704c55c, + 0x1bfa4fdd27298d16aa06bdc9ddb3c29f48aff4fef45b5ce80b4acdfa43fa1355, + 0xc6d30e4b903bdb97453a996931ed19b556b3887f54d63084263d278bc2de531, + 0x173ca2118a8b85e6e3667d2dcc1c480e163a338cc2d47992b0e6f09f2d363c24, + 0xaa825097578d91eacb40da93cb739f9a435c8a9bfe2ef8f63d4d392672506f1, + 0x2869d724819d09fb172258ab1fddded25d8f0afb23f1a87b331d229eb61e032d, + 0xfa3dc0a38fbb92e5f714183536dd2cec7163726a64117973fd1d927ab7b0c42, + 0x1f0f50f138ddd25e9c77dfa15f2201bc43fe818595195782fdce833664fdd244, + 0x1a8bd852a6a8a26b23057e5bb85facaf706a6487a0651c7c226d0cdff09f4507, + 0x20d045353b22be410aad1286b4a362f79c73f96103392c5c4ed31889729807d7, + 0x2830a23a528b1c1e7e277f97424cbb153b3d316fe1b167ea01309bdfa6a0f623, + 0x1f8f3d87ef4767679cbf773af4a2f27614124d5270015c7d64c0b13d25ee63b, + 0x2843847fdedc907101ab1b8915d7151dcbc7e27419d2cc24490d2020f3193683, + 0x1fd3dcb19e924d226e9b428d29f70978d7715bcbda1ec70e5984a67ae61537f0, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x22afc2a215e589f41511280dcd9a4d2f7714e205f2c4d0b663c9d2da07a231d8, + 0x256117a01b4903a52e27a41f92d7a65de53876e832d5d0013fbbfdececdcb17e, + 0x1bd505fe2027ac17a51db28bca97087a4336103a375f5d726c4957c63c1377b2, + 0x1370beeb7c62a69367b6d83f639e5eb0744df8b7197e44410965c697938a9e3e, + 0x1b23ee8b148269858c2f44c34f1058f44e4f066b2b97a357f81a0694bbf3baa2, + 0xc11837fa154861251a3c6d09c4590cf5b738abb440c9f221b6fdd86b62b950f, + 0x1e41b6d8be08383c6279628ffab3e3329bd391e954f5333c2c24bea41b1b6107, + 0x7921a5cebe4c7e339b84f0e635a48591367584d0c12a64b5637d960f35b3d11, + 0x14969d5919a6d85c58ba30919c0f0e52cde9197db39681160c5be3b98aabb92f, + 0x1d6e48aabeb209860512a8935eaf23b1bafea8797a6a81284fbfe6e81c1f7a34, + 0x2e3ce888f840d34ed8c660bfd5a48b4f4a0c040f5b39165e2615427831f86803, + 0x3383db94e9d7ac3e3abfe0d27482c9ba837264a10f482ae80f226e51042cc26, + 0xaf89e9e5eee9173993784fb566e6d538efe46346ff5cf61b1c993b52a42e46a, + 0x1ef03efbffd92cd2da93741eef43a8bed80a76f4f68cebb61493e971b8b7e7e8, + 0x274067b2a04222952d6577de3245f38219ae54f0582d9e05b7d8a01330395345, + 0x16ba37bbec0a43c8f30d001bbecb30bc3cf3db728da538ceee4ef9ff4ba486a9, + 0xce229b9c289b8e7cbc4e020a0372a370a7f282201b47781caff3d01642b8c2a, + 0x2f80729c7338be1c0dd613c22e836ee2e9a9d0b06a2fb5e52af024ba8678b5e3, + 0x1cdc6d2ae50c1329a117d13ebbfc1fe86d5526a9f9c59a50e031f37b6710dc4f, + 0x2530a467ba204bca45d83f9ca4c5ac9a568c053266ee1126607ac33c7e94650d, + 0x371303ff0fc68a7c62e17b71ff98bd5715c6717d794b69df439a6d7c00011d2, + 0x378305e20bbf96aa0c633930f4011bc20789b5c1be3f2929d693e704c552bf4, + 0x1a3636567c1ef3005e7d5839bca900888aa34197fbae582cf6826f855020d24, + 0x281e2a06fed1cf5b0e0b6e03fa2652cd608fa474299b5c7d0e59c6aa35c0b17c, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x2b3d84e5c61b2b97939674b7ef13780988f0c2da109e71d17d0598f080236a27, + 0x29e2b9bdc8dcba3617e5663dedd89fdac40bc1714f767f327c6503d7f146fa2a, + 0x216f7ae6ccd7bac97e2bb068168cf18b23505999ad5916e52ce95a23894806e3, + 0xe8d298cae881515ab0f74ec935567a5b249314023b3856d5f9ec1a5599a9b55, + 0xf1e1e45f847cb03591997bc8812b0f422dd0db2fc99c2417a81989f2e46, + 0x5132e56caac6351c00de73247be0cf09de357c4780bf705fb1d12954047a302, + 0x2c1f7dceb1501489cd4782c13dce297dfe75af4b4065dfd0fd51191e0f03489a, + 0xdd3f24843220bcd4a66586631e888956a0ed26f717c556dc5e20f38b455d4e0, + 0x2f3224043392306423d22f0e9e5c15889df84a9c1c6e2bd406a469139d132844, + 0x2b572f7e5208c5e52a759e04500a1c7d641ff06df5984a926dcab2e17ca28503, + 0xb1988858934c8a353456d44c461a763b6c98ed3cbf72a21e2e4690083399907, + 0xb0ce76163a25f724929f8ffe5592bf64313660ebe1b160472466bc091c5c3de, + 0x173b128e873c2dd53e94e438b4cd066ecfa28eb42d13bedee742efd4ebe4dc3d, + 0x22f7d627420794cb514df36097c3dd8d2e92e2890af2c1afd4b5f5bc26a6629, + 0x1f343201df3060d03e313eba7690883ba77fdec3d663fc6884ebd401938af261, + 0x2472c968883b169ab912d4327cef96e6d4fb7b2c00959bde150b5ed9708929e9, + 0x134c248a14ff13c4202f997bb87ee93058de60144cf2f5141236f01455438526, + 0x206b6361e6139253e6070f905d6b7d08eac74e4ef2f54ce09643926bf5c8e814, + 0x2db2cff5528de7a26e0643b161e7b318e554aaab93fa72f9f475d9aa7c6ec8bf, + 0x25e05b8a3965fe0a250aa7ca030e3a7439445478e59dccab16a621928d014571, + 0x2a8c5a77c61420b6b4ebe974da7140a25eaf9dbc9092f063111283e773adfd1d, + 0x13389b7bf63bef6a68983125b86f93b62b6d9e4783f96b710e2ebed3adbcbe2d, + 0x2731cadff040622fccb533fd62a0d43090455881080a898488d55c89083395db, + 0x1886f751efed6e401c5851f88bc285e68de3b94062bc810b092c3e4160b0e12c, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x1a1de7217c640816ca96d69dfa3a9ead0a32f62b2d864c5cf3d66e2977616a60, + 0x21bfb88e0d52b7dce5432f55c443964e46e72879baaba7aaa04577b59fbbf100, + 0x1e1c9ba5f1413166786c96401b61f687ba50dc735d815a4e811570bdd8954a11, + 0x378dd10a31675f7bcdb8018c96cc8da6d034a42cdb62b406c5bc00900a3377c, + 0x274d6dc05dd550d77fb31d349b2adb5f38eb4b27ec15e8f9cfaf56fe2f8b318b, + 0x24fe1bc328cc95e0857e89e99d2ca97f327c21aa4de5c111a72c2c37235e7d1c, + 0x2a98fa37a16d2f8369b3ce72873960006ea67075c023fed5b32dfe407e636057, + 0x1097f947557042baf445bdf5b8a92021976c14cd0354ee88e43e8c8c5caec4ab, + 0x7734a2111d925edc13496d0f5922ab36acba8467999f5fb727ebfeb37a38077, + 0x2fca881eadd43cd4b9b3bde9046f6a2505bc46132b2c24da4e27c102d63eef34, + 0x27c952411017987d666bec758d6036c17e440940b77db47b40d539ee1156c1a2, + 0x1b329d612f773e77721b7a0f9154b359c24a6ff2ee0f5b9733a78a798caf0f28, + 0x2e165793b072eaa3576cd18b9027582368581339ba3dc1acba9cd4a202701686, + 0x218665404266df9d5ba6ba1f5a7d9a628ad7c74a092860e287be14f0bf58774e, + 0xf42176ddc2c84d12bb3798fb2b3a06e44a4c33ac39ebe036c7d6ac6ffdaae80, + 0x21dd47b40fc1e454614ab099787fe65d6d8ea9eb0e4055bb51e34c51bebc1dcb, + 0x7d3a26830f8b14342a63c1ab7f713db81ad94ee6e5c519cbba0bf6d2b87b265, + 0x13a106fb1b648c8490a71e9c16886e0049270240189d44278c63a46f744edbaa, + 0x1caa59825f86da2ce09134f4ad823df1faec3d556f9756312cdd8991c3b56d60, + 0x15cdad7e7f40503431e7a8c20a7e1b48ace6d194ee7d7829805a38d04020426f, + 0x35c2a4fc2c424ff77ca180b9b522abf519f1fd8b5bb7ef7f1f8fc7d31c117c4, + 0xae2ec57575aeeb3814613d2390f8ea28130ed34725d1605b585b4e8cbbfb4b9, + 0x1ded456ffe562fc6df999ea5cc80de0ff6ca5fff1b0fb2607273ef1ba5262edb, + 0x2ae307a4f4670d11f5ac1c7a3a23b6dac613d3f104e107d0438e2ca6d0ed55f5, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x17570a15226e3cb10d0e0cf627fee157af900cf4b22d8bebfa0f05ab45d56306, + 0xec2cba7becd9f7b3b07b59be1f747b3fe3f40ff31873dd306105ffdfba14106, + 0x115a73bfcecc700e34ebe87a02338ec4c9e1bd0d95c2554b12cd5cafa1f75f87, + 0x271882e1e88d3a90e536ac91109d8940ae411f75de7cbd43000d6316c5ef48ab, + 0x28d797cb88e36cce87e39090fedfa11dfacdf2adf148618d262e46fda6ecd899, + 0x903165475cdefc056bf3cea7cf26e39e87e7d1c8e1497271df24330ad02d8fb, + 0x521dc03abcf3c15278e90552e8162b2dac92220d99e69ef9e449b5a0370afb0, + 0x1f80e4baee043beb212593df11501a79c07c898df6cc578190c679e64c34a2ed, + 0x1133a6e8c5d0315d2775206b849588eaabb0b63a8faddc67806ac13faf127b7, + 0x22af22b064becadae113b24d113f0cc3dd0d178f9cc56d78e84bf341354918ab, + 0x16f91f204c2bd84fb907a7ab7442742ff24ab831ba252806ca7b6e69c77ce94d, + 0x1d2c02fb8f7780faa24f3da1f29e9101c1cde4461b7d567b949bff5ce1c71ee2, + 0xf8e78d6c9a055af147b74439decce135691562dc5b8bac4e471fecb73562363, + 0x134cd1d2c86faa3bff3a72cb6226109880094173ee2cc808abe6f9586bd47844, + 0x1b9edce59f36f20f7acff0cd78bdf614f6a8f1bcf95ae9d6ddbf5c8c7fcf625f, + 0x5a6771daf1f2b83d0a92a118f30d42178846e5e209b82491656febef65abf3, + 0x1508cef9d99fd03d1b6479b90399ca9dfe3792fc63bfbdd35661e0d44bad8096, + 0x291cc5c3f65ae5bf17598f432aef5de08724ab30026f25adb70f85fb3bb0d455, + 0x2c7723a807b3944705b71db8c04cc468820d3bfb99706528f66965bb8c9734d4, + 0x9bb171d7c99e8b5b35def3624957074dc2f0a6beb861bdf417b2ae290832dc0, + 0x1943ca5707ee772b8391b577e295dad4f10c2db1c770e33d8c37fc2280d71ae8, + 0x1d7852588ccf0c51663abd65b87004ad5880721019214e00190cc8e939eb22d0, + 0xee871118f882a42a8acbe733a64b7333a2d14413c511b6a79d58aa96c08ef8c, + 0x1ae19930e083754140dd85378ca87078feea1703c3c0404e2776bbfb4cdba8d4, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0xa7c934a0347f0de7e9e7dda8b1ae9b094bd6a309b8323e06780821d7894fb5e, + 0xfcfbe728f5c1f06572e5a750260efe423bb6992a7b1bf8f0e761e7277e71d30, + 0x170dca9f0f6e9057372e380cfa924e65cb86afad866a330ec9ed35ebdae1973d, + 0xa4a917f344bce3b5f92568450a4f17e6a17e251c7357e708ec3d6e559bd89bb, + 0x127ff432555f7e08beafe0fedba0ea990b49ca5df42cbb999c3bd7b911195362, + 0x65b6e437cbc026c1623071777b10b8dfd605a3598fbda0687c74eaf525dc1b8, + 0x2faee8e6ee2f7bdd25ff36c3189aedc3b05c4bdaffde640c0e4d9284f7d9a8a5, + 0x1294fbb432ac3864a9c12eabef13d07f732b652836e66a954c485735899241d8, + 0x2dd3ab4f03573f3362bb7ddf9648bad1b43ac6939d6c4fa9ee73dc7fe66deee3, + 0x2029b79d88ff15c860971aeefb2ebe0d523faafdd6096642b018856793e74b4c, + 0x2e5c56ab0934eec6ff8c8224ffeea657f1b99f880a002f6ad5352d30f7c0b85b, + 0x24888adee436dd67b6742858809073a5c4393d61283a825b65b883114d44220e, + 0x1fb80c654292d64f24d331f4f6fac1a20a76379865a6331e7528de236f44eb11, + 0x3e8ff048f23e53a5c6ef02dc7d37f316cd4528da4e1f6cbc4582889e1470039, + 0x23a4cda868726fac1665985e13d800d100b56bace43f67e29da05733c2a351f8, + 0xe25a1b132ba0bf76f1e361bff6b9bb9fa2d3aaad114f589e100625225a04b9e, + 0xf534c5ad59c9d1c4a37bda4e52ade866d305b982309a004f3b2c6f8b10e9854, + 0x1269fd5d157f5bb62bfdbf4f3f88c1b2b684e40ce07749cfce657a373e1e4b91, + 0x1fb70d1ec4776f91b42677c88d2983442b78ef00e03b82b5de606a45ffd3b4e6, + 0x29eecc22d8e5725e00c85a0651edaf5f3e9530505cae2d7a3eff6ef496d7b1d2, + 0x2355c9e8fd9fe0eb681e8aa1e3ad43740a79cc9d930a029fd161c3ee32f7257e, + 0x390f12f658c6d9291b118f5e116727e2f4a07140e8f3563ec5b12a0ff6f6a7a, + 0x140256a4a9cc33d93eb486b96b737dbd17580a77f20924e4a3d87c23b25b233a, + 0x2d2be9983d14c81d2cb8665b0c08f89d6140539c712cf4c2ac8cc75b2daffe46, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x2cdce0a94aa8c1acc2db79358c3e67d954983ef0927dc6b26f9abad820f1d420, + 0xf49eb6531ab1674ea9a6ff88bd8148690c04addf9a9164b13ff2c4cf008443, + 0x26403014e3cc48e1cf112ed79bee8ee1467acd303d0da5c88b8683e38bcb7205, + 0xc5f602b9f3fda8e647ef7a42af34741d11abbe0a99f464c101e534b51cdea4f, + 0x18ac38aa55e95efef98c347335a80caf7fc5c3efc95901321e3b13b12cf46a2d, + 0x2b1960c727b10b666328f0c37f5cbb3b06a1ad54f61b9503f23b02e5c4678519, + 0x16f13b53b3c6a47f01c73f7e26c2fe6ab61b3e1f5e553413f2ca127e53ce4879, + 0xfc4ef669021d86d29dc04139b88f55a5a57fe0bfa253631918e0d808b1236c7, + 0x8834ddf96f673a786dc5af125eb83c9ffe1537fc773c21d101768aac7ada57a, + 0x233f13c0ce9b48867dedb88a15b1461cd1befdeb99a9c0acd863dd45e0672508, + 0x2099a619097f9565ca65ac96aff19cbea16a90e056a33b9b49dcbb725903edeb, + 0x269898a890a0eb11e9b84db6ae0735714123d4f0aa0a30db183134d279f1a90d, + 0x27fb03bad7fa46a625fb06a4799bf7a07ce3bf8dc01860cf6174f5d9cd49522e, + 0x1f0a5bd99fd979d0edddd243d6966152706bffc8326fb088545b38d95fda103e, + 0x1b082065bfb2e151552d1aeb3f2435ae8c522db79c1c3fb847fe73b728dea05a, + 0x196840a15a65ee462a8312520b868084ed0213c1a881adf907ebff992226833a, + 0x1bb7d7bc4ea0f7b8fb5a3b059478ce7f5ce2069e7d62a307c21d0400f386049c, + 0x2c0b3d687226a36e523c0677e0f3949eaa45d0d3b9c9c2d11b0431d8ecc7410d, + 0x2a22096acae1d75aedd8fc843d8130cc869b142405d3967781ecf9ff0062cfa9, + 0x11d3df41e1d31751c5b00b775f33925b4fd5f8f66dd2c5b2e2e04cb090ffb97b, + 0x29d0fc08ded332bba4a34cedcb8e3eca9d9a6929a5efbf58a72e849856a9cc67, + 0x1a0ae664c389dbc11046bb170c0ddb422c4c6c2f10c68ee98ae7ac8c00c4ee83, + 0x6f3c77706973637c7f2d5b9bd92d6e2424b926c38a2cca7bca5dfa0794e5845, + 0x56965616b2df66e2918ba840e0809b85a567a3e7d13ac5f1e532061af856a57, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x2dfcf11eef61a008f27f61a5de96abc2e329dced7092f941def6b523960afc93, + 0x4f73f5afb82d2297d4e51498f0828eeb3eddc016ae0e15a2a9e3cfff340d500, + 0x26290fc492220c99dd821c4a4d1acfe1b7f40b37a13bbd3ab51405a9f958ac93, + 0x7b53809466ff55e2e4f5ad0f029ccc5a1ac5d261732ab2b010037e8ad080317, + 0x80ca5188ef7378b939057774b2ecd1f98abf27dcd473edebccc06ac7a942e26, + 0x2b6b01434a47ed188b43157e1964f3725cf4f8113fb0a6cb4c01ec7dc2bd47e3, + 0x2c2106b5cb401bd68e15746349b56238f670e58a021ee2ac8915288d5361475d, + 0x88ee10bba489475547984b890d7e794ab25535f1fcc8fae04a33d300a5eb6c3, + 0x29108e4588512ad0ab28e432c789fa3d3e0dc0d6002e19cc3fb6795a75d6971b, + 0x241c4817a914814ced21c06ec5351e85ed7a90f2843d23bd5363aebbcedde7b9, + 0x22ecde699dc8dbd7cd3d81e80d9a81ad023c57bf3aec5a8239871472fabc551a, + 0x20dccbfe3e84b40f3908bf43f0512048facdd8686ca5f17192f983599daac6ed, + 0x2c96389333c5459ec65960d848b06bad4d6b8abc6f2602bfd81824cf43c7218a, + 0x28c59dfea6fcab6ae73beba612e62083a58bb80306a3bc2746ace09d650c83e6, + 0xdd478a62c6871c699ecb4ea12e454027212fd8f1e03a8efc005df6d20ecdd40, + 0x28772e7be45e36b90c2d439748c0d77c0b523711ea398e7dbd85b0d7df1300d5, + 0x2a37740039be074389e76e1ef0095d7d111f778072d4a57334ebca290d667a4a, + 0x2f37845d94aec2d63ddcf2cbd3fb56fead92ea8ecd819d7eac3c2b036c6c2cef, + 0x15edccc5a7e695dff4db9dacf405612f00ba80a16dfda1b55cf4beeedf90ddbf, + 0x2817134845b5ec6aeda4961644d513269f86e07a21ac3b7344d582ed07b5f46a, + 0x1ef5390790a2a3214140b10962d9435bfb0b4e6ce24b7a1ea0c9af689234b6bc, + 0x18427d6f7cd9bf7ace6341d16dd845cd1bd18ed4b9b8ecdcab36fa45860855d0, + 0x9de33bc7e2ef786db74db7eecc7ff8720454637bdf51b281a4a1478f198bae, + 0x5d2c63aa2de4534fa4df7a6c5f6d10599412fd247a59f778366bff5706110fa, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x23aba695154e684ff482751cb761dcc1637ec5e99aaea18d0bf2e2fb26eb142, + 0xba208c04ac11ef4543112dbd88212917dbaab5a87268d8158a487ae3241584e, + 0x1cfed0b58000d3ef4cac1e6fe54e64af54f393accaca4d5b8cb05f61ad9cd776, + 0xba1df4ea027f8349fcb15d1edb328a76fb536ab65ebd535787945634d09c5ae, + 0x1e136b44ef141c91945c8768805ce01001958ecdac9b065874d21717da99b408, + 0x20643e3f3c68b214605c6df2d802e1e539b465b98307fcdd0f8d5bfa1778db69, + 0x2127d0e7d940b3132fab6b1cd719577f51bf8db531e37edad5194875ee74936c, + 0x17249cdabe9c9db4a1b88bd5636d3bdb48eb0ba6a17357452c97f695b080d5f9, + 0xa6b94822882ba1ca1da954566ad30322e3458a6e0ddb143e4f5f306fc9e3336, + 0x2486410df8f9b4817d82adfbd24aae41ebf7c4bbd8708d3a7c3b18a999cf79bb, + 0xc0b7684e8ae46845e7766bf7620d2791a3d218bfd812d008f73ad351ba86aae, + 0x97d3ee321f0db8c04cede13ecfa87cca6ffc215653dbcdbf62825059b8521e3, + 0x2bff71dafae458bf4854d7957865e2362b99a7891cdd38e17f76c5828aa16531, + 0xfe15f8b13351058806bcaf16fdb68f3ccdf3c30f15a85a58df2dcfad72e296a, + 0x2bd586480aa18c155f688c75ba812ff81990930c1aafa4058ebaf667d41e53ca, + 0x2b91cb72fc45f6dcb1dabf0473e2455f28be6eb1b59cff91b5fef3b81d628ee9, + 0xcdacb5ed20f18668a7c3f21366e04150d0e877756e2ee1cee11921184a31a71, + 0x9239d69b632ebcc1f559752a2fab086bd46cee120504a8c94b4427a2fecd5b8, + 0x12bcdb6b20dc77d3d5741b3fc61e1ec6f53137b01a23f48c2a267d6fd59ca0c2, + 0x11ea73b3f04690ce2ddefc2af3bf8f8054ba74dc313b09ec09c96fa29e865b0d, + 0xdda6467c64b0249d2f065df90fbc7a685022ace6d9cc6d9c983dbd7d29eab53, + 0x15d7c61e8a8308e4a43d992947c0262b65bad163a8f101423dee64c22bc3ab02, + 0xa825acf9f09d653e06be5dba7ca63648ebd6060377101080daf3de7bd9d5380, + 0x2dfbdf5d427e2fe6892fd40d4e97ed7808dd823ead27629d894982b7aba08a66, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x1c9ea68943d8c846364060646de0e33534d528a23ad82b8ba6870754281db559, + 0xa15008aecf43fe4b9a3bdc26ff03e3867e974352926cb3ad1535f7459648a98, + 0xab17a8ff84f7fa5d0daac95c36e606fc6e133e7cb04f0f7b5334e8e6c44ea88, + 0x1495d888378f7e12c016cab0bee2534903fe878d5650aeeafb3814b3a8b1ccbc, + 0x29a054aa447d63b2124f50ddbc4c2d943636ed53f22651aaf90fd93dcedfc941, + 0x395b15a827e37a6adf3175a2691c288aca68e16154c2d98d96bb0dbee6a3f47, + 0x2f47066bab9349dfa62b25ecb43354246a47eca6216c1d12c36601fe3413ea6b, + 0x1b1ad81eede52f8a8c0aff49a041dce0b55a1f06c826b441951b6d654b804012, + 0x137f27f0b79cf88476110b34e7ef630d03ea21338c200322990157f50a8f3fec, + 0x131ff85cf21b1a68336160757d135e1d605144f82b3adac0fda110084d120349, + 0x5f848d592e921b0c3c7a36a84765487b1357d0ec01f8f329aa8c6f266f4a85, + 0x2f8999412ae8dcb4475413e72f68817ec1a094272744d32be4b8a0ff74bfdf1b, + 0xb42e032237f3bf21ae95c4062868751dd39d0f68c06ddb849f691288f33e261, + 0x199c8b45cac96bb0db0f2dcbf92c361191cedff0d949606a140d3420dfad31dc, + 0xfda38b5f5bd1100dab719bcfb3889371f5ab9ce9c42868e7bbb1ce2d5a85f58, + 0x1bbfe63a7558b0e9a002b3983058c3cf399d479f7e2193d2491d585d541a086a, + 0xeb005763e3b3d55840741f0cbfc95fe55483854e817b4d7cfb4549ac79cb34a, + 0xae77d49a777e5a22a3fc6aec242a7a80f52af3e1cd395cb8862b09bf3230ece, + 0x25c1db48d2561608e3478c8238b3872dea6de1de597c4f26ed8baa958480e5b9, + 0x150bf881bbd323068ed07cea87050866e7b29818f3d36e08fcd35b31de21b85e, + 0x2e9d25423c272d1989d6ec5e983812e73575f6040b3f775fc9bd1c7817c55, + 0x229ed6f052976bcf9f11e48f4fccbfb450a7b92efcfaa532c1c85a059db33cae, + 0x3ba04ce72a78038c64773239e8f8c1da608b93fbde21c2ce94af9615ae10f44, + 0x2ea6dd6483856ca2a36102227dc147fbb29fcb62ef939915a9db66c103a99abb, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x29e75237c1ee6bb877b6e95b7355cac03170fbf57421be8dbcc50f08693db587, + 0x137b76a84a30e906a38827cc4b62b1a22e942d835192a98c514eafd9013a2dc5, + 0x1e2a3dcda8868ab407f15b612c405069a5c1c545af827bb0f8f6e32dc55e0277, + 0x5b71c5d1613cd9b6b3cfe9400cb5d8583a16dbc1142cf760ca6aa9f816e9f28, + 0xa7603ec122e8e0178a7cb29db181e2a9a71f825effc8415b8d09feb7bf6ed31, + 0x12e4a61dd3e9834662b78d9a820c25660926039237ef579fd1eb260bce13112, + 0x17c89d0343777a479dea31744f2848ac06045696d8f0017b7fa9d3abf88cb373, + 0x104a21bdcb8e49245acd6fc281bb1263976f138797f19634c79423f349d6dded, + 0x1e6ad3ab8037bed2e36c872a9757a796696ee2950f97cf31eb83bcd4f63805, + 0x248ad6966b401086060a913af010da4ea282c2d1461e3dc100569b3bd1685a16, + 0x1b4d21b426441caf2545938d41bcb3b37c32b3fa15ed8ffd1162e65242ea4d39, + 0x29c4422c99599bab17470ab9388ee796951c249645ab164e90530fc851ea1fd7, + 0x1ce500e40779238422cd47a0a6d7f3dcfdc0c6902869966211b0b6a9acf5171d, + 0x19102e3c727844fb898c083bc1ff45d106a293d8dce6ed43895782daf691a7b9, + 0x12947f4ac2f6fe4b1125a28d17cc4a3e2db92fab0e0b97728c8b7bb2047078f3, + 0x2a7639bcd6591dbafef49fb61db710e9ca0d712cbe81cb86340d0f1698103515, + 0x83ac15141e94aa73277ab521d9eba44ee30f4e02d6e9c1568172bd18c9b7e6b, + 0x480635cff8314d917d8a55b349529dc633170a143f4865713f10007f7f4b7d9, + 0x1c03ca2e6ebcce9a2f4ce66bb039d036b2b7424ae916bda6240280d5e5ed0a1f, + 0x15e7db7d25266f604b8f942efb4e0c32c1e45621336d280f1b904c3f4052936a, + 0x2215b41943b064cdbc20179c98c4a6948c8cf249f04ddd18f519e9595aa33b, + 0xba3d24e5581d6959c2bf9c0c69560f1dcb6486734dee56834898b97e8c04b7d, + 0x10de6cbb712419d84dbecd375963ae617b7496be8ca89c5cf3ece9d30f4f854a, + 0x2a4f4573863cbfb189e17e80bc465161a508dd069ee4fac346c2b024c88b5cb3, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x79c218efa2fcbe1cac587faa89bcf970134391c8edadfc9d54c666c091a6829, + 0x112316416efb7fa45be2c134395b446f048902531554fd38e0bfbb364d196924, + 0xd77ef457994c37f8a3bd0068572311673ea26b0fd473aa1ba9c25c6a627692e, + 0x189bfb671bf421730764e771fd68f01e883f98b0aeac6e5c9b623bdf1505ea70, + 0xd77f35f4ab33fd80625be829594190adface4ea623ab12520920ff8e707a591, + 0x26288f7ab16b1812ff362b7d283539b18dfd08362e2a7c4466744a8b815b0fe9, + 0x26f1bd644a7b3118e55d6beed008d72deffbde92815b8871ff8d861153eba032, + 0xeb8a1d5ae4081352c7ef3d50b0622816fea17a0fb9cb163c0e544da8a7e8ae0, + 0xdb56b6264829c99f094eef0b8c5baf36f6c9518555a9b8ce5845b4d32eb96e2, + 0x20883c599a195873758fd917f44d2079778ccb41dc128b8003cc007b6fd664ee, + 0x19f29faf9c5393cd0b7c07a902457096ee6543d1dfaf22a4f897d2ea6599860, + 0x20a2bbb3ebc1f46f939e64356d5d1609b5e50b5b3fdc7462b4faf735cff66ee6, + 0xdf989faa8055df73bc2acd9e8d9842bfdfa81140488ecf67db886d58d2a84d3, + 0x1c208f8e89b2c7fd65a95e2fcce432f5da8e71640467d21f351b169d03395c9f, + 0x1356fbcda43f79998b2833fe6eeaaf63886cf799f55505d81164c882009151d4, + 0x2e99fece2dc2aa38fc4055171969feafb838a5f2735ecba803bb9f4d18a5dae6, + 0xe39c64bd29c62c85340ab8eb5f7086e1c9bd733945179b108891f966b220874, + 0x8432d0352bce6861217bfb3bdf0a04f3ecbeeaee2d360cd5a28c5d2305911d1, + 0x103424d7f89182df35cf2d59dbc2b453542beafd78d95995a5e386aa2e55aacb, + 0x10e4ff8e36e76842ca11e222592d318986689fed7328b94cc15104c8d86e2def, + 0xa6b0020177e766bb234bec7dee733678251b1c8899c516ed2832aec23623c5a, + 0x7514523d425b76b3a7812057725c07333577023bc38d70d079eb2d524d94f87, + 0xe666408d6019b0c96d7c9dd5ab9e08a47cc988d93292535265f710873da5b08, + 0x2339395b0617cd94dd101a4d03051e9436327044ac470ed0420b6e9bd876bb5, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x823e9cf59d9e29590ea5d5caa60265f1eefb9ef497a8a653e21e6b884bf380c, + 0x25015bc12c22856eddaff514db520795225428b8b63b82d54e6ead88904e716f, + 0x147f4836af834c89e12c52da5d778726c878bc2005e78e9c0bb46ed47740bc8b, + 0x695c3ae3f6aa362df3220e3b4b230d3aea7ce4dfa4629a0b3da2cf68ab08b2, + 0x2de7695bf1b96fcc94dd6b9f46184a9843a90ccf1891093670cff21e6f9a6fe4, + 0x21326346451906a82345ff6a916bc7ffa139b3edf1ccea12b1ccaa554eee5faf, + 0x112efaadc386b3c1abd2d173beae1b5a9424fe57fbab2c2825c2e6a7e663fbf3, + 0x1a2a5c2b2990f00cb8bde45b57589cd7fd1c5e0df587d6718999a1893f0bc8c3, + 0x2087e95ae6df27098e3ebcd46f3e4feca4aec7df172d5ef293849f671322789c, + 0x254c2d79bc6811203b55ce01f1e8295095201f0f03613708366a7af5f7b9600c, + 0x10f23dd383d2ea9524e512e2c7a3b75b76acc7766a95067116493a0d1db0efd2, + 0x80154347a02980ff5274996369c7d439951efb11b19c3607010b03de802b81e, + 0x155940fc6e3236f82e7b7257f0828b1f43cad68677571d814eeab2a6986b223e, + 0xfba722c1bb656ed1c16203506d15a78c79088a9dcbad00a18e707b71f326ac7, + 0xa31c81db83a6746fb9747989509010c547d619d1823298f1f5674551479bc09, + 0x16a2ffcbe9959f75223188ee2d7bed0c4cb9ddf552c98fea86a6c01f1c7e0dd0, + 0x2e7e9b9c74526581808097354419679f2d878fe4312934613b01820d66080fe7, + 0x2df5d5cf7d48de207d7ff06b292961084478a6023f4ee1a0da7619008977d815, + 0xe1c110badcba8d0d3190b37de62dedfdc2a25675f54d4c5bd6956fa5b6c1d91, + 0x1257af1a62fb76f7a2abb3ddeb256bde2cc31596ed9a5aa2da5df05cb56b9ebb, + 0x1197774ef4175d674951e91d56afee6229e236a6112a802c20621423b0a66f3f, + 0x15787ba0abf814438a3c358e48b84cac38c4dcf66441e29b5a89bb17b6dc50af, + 0x10df04b3f297cfd58260e1933420a96f126fe4a3f9d53000e140d4f55c2217f9, + 0x26522aedb4ef7245ad2e50ababed3e320f4ec30b43f2bf1904c956cb3b9f430e, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x30084328d537eeb68e55d5593d350824f01bcc9a9d8cf28558982dde43bb8ddc, + 0x5921d17d596463a98fabd2e90e2ed92eeca8b791f75134c9aa7538ecf90e450, + 0x1349f05b3e3290ea030b6f2696ed6df35c27205e6bd904b569c363d985c81fdb, + 0x1d92c460a4cd6ffe4582a5aa95ff6a8369a804f55d0341dd94d495d538dac09a, + 0x1e27ce95b6ad61a67da6b7ff01d06998a5e66b70ad7086962f8b6f6687fbe00a, + 0x260b78052f342b0f62c4a6d75c2aec7321b71c084fd3659255713de667cc742, + 0x131e63069626670c022ddda083bfed93280ed3db252d51ad6a7ea8948ebc9a63, + 0xd89b6c7f1e046e139cd4b937b5f30e293b478845aac1e1e64cd90738dbd2fe9, + 0x13b662585b95a62cf47a3d74e971dd1a2195a9987ba5c35349b2ac299bf6daea, + 0x299cddcb1afe110299b2c4589888afdfc8b33293a4b4f7cf822a74a922f4d61d, + 0x243f933137a5377ca39a64f788a1bdd25027e4c1579908aa2329c18f13654b40, + 0x152517da46773ba3a5708a14db3239e59b4cdaf84ca55ba6b7c61e9bffb6feec, + 0x1811c08f29173c3ffd29aaeb2d9123a5e2b5bc32e5d74a23f0dc026199f9c8db, + 0x2beb86f7fc3941962809bd8c7209613eb2f403a1db90acacbd487034b4e734e0, + 0x22d40f04d25617323bf6481a7116f5c77922d4a98d867730e9717a181c24ebdb, + 0x7984c5792dff5a244e45e8d9ca13d787cf5725f45513595bbff1405f8a12f62, + 0x54f16dcf84267fdbd028fc4e88d51fa7624405920d6f85771606130c735454c, + 0x1e14b42a14dc7272d18f47c28dd8050fb3993b0c0571a12f3b3e4a4c49ef788d, + 0x125ddc89a4aeecea6d3620f026c2a9372fa856b53d8ad5d8ad495a5eec7ba24d, + 0x149d09583cb39f4124a7145923205b3bfb7121c62a39d6238cfb380c782475b2, + 0xecae7698bbf994d656a1d3b3df5668350112f80a5787730c8d32436aae6ee32, + 0xd48fbb1cd222f052942818e73b12562f7490892f474402274151763ea668369, + 0x21ff6e0e9dc2c5eeb19793fb2b3e64cc11233b81df41803b6524ae510cf0a29e, + 0xdee76eef76340680e4f3d4a0c51b87a162db5254e981a7684756e55d8b513a2, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x1c72c610ee727a6dd1e885a0607d35cca9127f006e26ce1f986bad89bc3bf3b1, + 0x1d8bff20f53a1b7fbd3ed4f015ca18fa484cc6fe4fda3821016d43a62db85681, + 0x1c13c5149e5fabedd52729f4e4502a7d0d5058c532728db8377aa92f1c3e70e8, + 0xa2044c5c41c0e874f005528327e695ada2337dc81c9257b6663ad1e37416a31, + 0x27a159845c8347dce715b4de7d305d529b7c9bea09d3fb1615b69d5d0e2e9991, + 0x28a37316b111822f43ce287c632cdcde70bd0a094fbb0ded49467acf199cd86, + 0x69b007be4fffd6c1611b22a1f73aba8d334eb39e36488f6dcaf8f61b07cc842, + 0x159cfe01b040d2ed27293355e3ddc2727906018eab4f0be23a0fbf924d74bd12, + 0xb538e8f3455ff2d7f95203ec7c7d12262d7d25b224a92500923726f20f4dffc, + 0x1f188392740ecb474a4a589a3b83deecab0c1c583c390ae1e3654bc90d0705dd, + 0x85e8ab77fc680dbfddd3a41d1f749a5b25f207a10fbb591b2b2b70705d88911, + 0x18038e5ab85927a21df17e8a5db6e3e62242f7bdf6e662a2f973a794d132ecb7, + 0x25975674afcc9637d27a23b97bbd8b82874bee41e7b84057be13951531fa9fc2, + 0x2ff9d4e295691f9979acf589c59991f2f8917c6358b76e61a1b53e1184dd3611, + 0xff8d053d841882947fb4d33026c489c53b410dbb7afd04a3461f2c6b46869f, + 0x1c6d41952c53460b094bb1d727059e7ef08feb073f1d844845d53b9640a09f64, + 0x291c286327312c533d3e244d73732e212202e546807d2b5d7582e7bbdd28b10f, + 0x2c29cc08dd040a2ccf3c5ceb34882c68f0c773d055766b389051276b2dcdafd6, + 0xb51d6531aef720d40d878bdfb54a8dc43686066cf85e6eb5188c094b173930a, + 0x2eff7e9766928007d29d2555f466ae211166ddc034d13531728246b23850edb9, + 0x1c856f1e898cd9241df7e1bdb20857061acb1d825ce2b9c05c785be35a5066c, + 0xa88dec27698d5f11c3e2619b75601bb5f8bed6c59defa4270341b8048cadba9, + 0x171ca4dba69a7f21c315e9ec1d4324f8a365828508d62c205a0c8ab55322458e, + 0x2192264db77dda74e05a8c7389bf314447eccfea329054f694fad2ac11a8997f, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x2f9db1272bf8daf7461f68a046226bf5eb50de5222634ff09f06cd08c8d90647, + 0x2dcf0a905f69dcc006ecf519557f50b60cec57e406fbe85ce719240ac8ad4d96, + 0x1ef1e8e3bcabdd9c59f5c8bbe9c8eb2fee860feb4aca30cb0339394dd9aa845c, + 0x1f11157aed6e03678558e187e731f4e6c70b98fc36b5337562c565680e64bc04, + 0xa38ce884c10d28d82a3b6316f30c7fc833f4e1204c984b7c20098a13a0d5a2, + 0x1db78e384fc722f1290a337231d3c8986448b867adde280ef5eb72c45fbbde08, + 0x1e815a5b2ff405454bffb88b3d8ae428682375fdd858d9fc2fee3f76cd3a6d4c, + 0x370b02885c192b687c2cbb330888c9f4b3f26a6c054f70b092acf96d93f7c90, + 0x8203f9ff8db7576e14876f45be708f58f48e5f951be08bbdb4e9cfb23c244b9, + 0x29dc1ae19a1f06c6d67ad121f185ece6d0751d0ac335a9b7c879bab33dfb0e84, + 0xd3c1af0faea85e54e7da575cff80e5c027cf3876da141377410a28026ad4619, + 0x29609aac1d88be4d5aff5dc808e01361309a1a6c8c0defde126fb554c79944e2, + 0x2da5231bb84b05c467f6fe2b9b3e3bda77854f6de32ceb380fe0309c3c8c5d50, + 0x24658abc45d1109f9cb4ef1cfcea11de3ab442f13e710d10c0bb6bebe5b012ee, + 0x1f38ead2636865f16a72e393dddc1622ffc5417e5194d6c15ad8bfbd0073946d, + 0xde6a95902d88df02192471691daa4ac55617b73f448a4611f3d89172831542a, + 0x1cb8cad4994c3af3a2ae4584827640cd9dd5012fe4b55136bdf53357b4c168bf, + 0xc4b166f5e4c3ebd2ce9c84e88b3d42cfaee7aad923d9807b04a2bde61151b1b, + 0xa125c564bd818b114e3af44a87e694061155e19cbc84c50e0d29656de2a03d9, + 0x18cd16fb943e369664b89db857f6787b1d82a17b3940f15add4047f8bdf4dee1, + 0x22100b866fb7d36e656990a2c832bd09d7d0036ffc7d2693b22fcf5c26b05735, + 0x2228191716f3aed9191659eeda5fe346b80af580b666159ff25456172562c5e5, + 0x2dca6c96c30284bb8f7cf3467103d39f922aeddb431bfa3b62a7bc1f61fd9baf, + 0xa242a4882954de8d3d1e8cf0984236cd4665abdbb4d980c625c1d470349380f, + 0xd064dee824928d39f2a8be7d2fa583223c33995784d228839adde2559592592, + 0x116c85a250d461dd5bf2249536e50de23ab8e0287f5cbc62363c54c690c6d716, + 0x750eaaf76a03769c97c684d448ac7ae2ad93950a75c24f3482340bd29f566fc, + 0xde057ca401a6fa8a17d35a643f71515678944f33d6253778d116b55b7599cfb, + 0xc944093f1183d2fd822cf70dc124a07ac9397f3a941a50d0c35da8df5e35180, + 0x19376e5bb4d2266f833d7fae60c8c5f2f484b203f008003038515c66e2677233, + 0x169bcc309d7b6f8c73594d7563262ecd332ed38cb317d2c43f6f8dd704d32178, + 0x304811527f616bc8ef59c55565337f63a42094023b3abf89ae99193034cbc9c9, + 0x24bfb86617225eddd82f86320315dc68e8a7fad755ec408012968449dbe1ceb3, + 0x242f4b3a3535d5307261e9a75c570e6c06174ccdf398c934958ca129e7bde3a2, + 0x2b2f283271455095d3c2012a1f4fda54ba8f365cdbe014328e0753d94824f643, + 0x35a852e7bf5cf60b00f15be184e707d345fa227d8e44e1f4c37050d79a53a1d, + 0x150f777da222071015c6c4e025f67bc356fdfd678d9840dd2c93ba1a43f98ef6, + 0x2d8c70035731ad9efba92821a88119f6b8183a362be641729a93d6a327c03809, + 0x7b620c8a78e09e49ce547aa783aa78f3e4594c49ab3dd6f602bc6c0351d823f, + 0x231996b592528575567d39d00645a83b13929093bbfa00d6a661e4a690351d0f, + 0x4e47a72e49b9c5aa3f69f6af22fa0ab640c93fc524dd3c508486d66f079852a, + 0xa8cb4b2bf3f0c5da671e48f83e5c1b3018f0d31200a6f19fd5195db22eef7f4, + 0x18bbb002b46f2e5fec2b120faf87822ca8e77ace94e03aab5c16c4b931739dc8, + 0x2bfae1b054ef2e924d75a8a01283da29103c57bad129ec8396ce274ba4524df, + 0x6d101b19477d1627b9542581bf0cdfab38b05cdefdcb81965c5be00d780f192, + 0x18af61f6184ff85f104c2bef179b3ec5a5d242dfbebe8e27a2918f620e8a5be8, + 0x11e3a7c2d5f74371beb188c6e3d7a14b33128af8ee3287546d12d7777cef70cb, + 0x2de5d6a7a27343dd0422ac71b8d409b43ccb0b672e978f8fdfd214f4d7866404, + 0x227cb43b9818924f2a2588964a0ad7ddfa3df62284b4b3b10199a501ed970622 + ] ) } + // noir-fmt:ignore -pub fn x5_14_config() -> PoseidonConfig<1092, 196> { +pub fn x5_14_config() -> PoseidonConfig<14, 182, 1890> { config( 14, 8, 70, alpha(), - [21845584790817078371458083471368949437776490472877850604640045078191512294989,19653529167194186573342031346879012675435131167180408423801998487681049609228,2161640783454164110262374377277313793192503897274785966059544028153063342839,3054385704838408049711788708109646820127990212588286684954516786776077717445,16635301713639076283966918721405743045341739008997361549904617279107633739991,16225725689449395070421553385264743934675104858051374243666267106604469686859,13459300344588917210133884568970491767131781128923804903594902942358152425193,18076808066595657160589765822638228194586496301618971676220813553508533309824,15694780501519741286439086116053845024521602672078716577385749258673935540935,16872540725652861460604107748085417998883467929955001131816309200004825208678,18265717256656085201140362928095712147159090935193139243454994794524622317396,19947609676398163035598483882491861002323351300468831661031717096486749401185,7065348755377637300800426777670517297442798705186719592553630280930183590981,5932961695686545421777788171001317503890223201383043783424823453778021729657,2576876576710667081195577161905871971928185892200731156106299121736713352612,12555802030075275558510564984903031995058560722557285963258561359487710166944,6675427211912119210966904017515062933064977336124153512189140864737663166184,12222599141329943348111473622063042423140762381594560767061296463113725630598,10362975561623981137760844569177506781739504467939943515494131756563631401384,12107531632347826132438108083855485290921771214734424618157420540758495466114,3236413362865617508850894632024597913345632839215458268170009274560894755059,13269640842689962370480760671727240164372687082286848502921603339956981268889,8634391395282326489812410144806386699066840792624899435283359752045476380023,14222253145252965302168372301361324351891663598874510374220732501857922860417,8638897321585802770244834010345336579513350450350318876059595307827518698264,3865974821285567306249300995778666703191077355251395536574998983854299535502,7110975263857442529682465175399830853738223819847928136560110618272170902664,20747849667914457283564964533975989346418433637631755372433299771504842519646,8525337218586373689263383636693181730826089466845186214607593322372086164902,15284698092379128147447314807096025894174546974949762301780223877793581148749,7697267363768037767923915437621109821518467158489394234232803683407232938777,18552464418403713636184903318257896949762751716606049583572368219578636617127,8197992130246671682417102475937137101180310399693221498504232752936385287840,6267215711691005252092821645736755217101102985763928035625443919819600833817,17433952956528062441211440388577119958754746388457390005635829394680376947181,4412646415700345908595327060988016573431087490581498127967913815901104779675,15833191543444816612091389727640172975373200401937212078659643034429446372420,2496738022051529758808536908421531340554055955151436808600608028881270179985,18865821309368781007158439319264225124435320863391412688953283839208730853556,17356853444859379852104523062654303386446700475095103588258687890090805160214,13809314487709569674040696128771324530575306163394456992422515709961741509179,16441057642509466688507318755613056920894191930223829210993196564779122458374,13126203992288988176378067141418363395032818736472538500506274256104409609416,13787967697762688988712839398243982920760030565931489906532854488857802399817,19656786571615920765259702874045834039087950126970888730192726308970074475638,9496155930249199891836650339371004045437843955429376625371983436016490755144,6133650980214690439646563353939486183333374330790371938934927663849630407389,9878750392407472855744714788091164958447986838940220983459727015586370325700,17172636845539329981401043696407061375416986816086343858560846660524543673690,18266068074968659293646594793202575012585251834459743250538629833034512472364,88170009072279647351671114053985696295758726185186407584170034409102883821,7161623553009701438320582200845261728475099875569530553253147102879319777702,19053465421328592764143131116469165876378776722378567877265112443326967288533,15787821054928042708896412640384007326676625326396861263135967977164294783653,9615173323505112477217305395762776033870692647990635021315350642536385774258,10748585844981412663149047472971001536312431184916168605042111548221680655573,17193496554920138070905215774356694517155445370515924892481894322048517125340,20981027561373479728773182418686452188471940655764396684028110979140369006827,21262972686125563821794309741130556914165641373895499794098515843451753652777,17107658081493676403630365275304097003600155220274082934263833389505162130032,12511894931761241561787052333055670047472612011302194769826693935710455626001,17806912269440585736864672280987816575618315620498245554921738316327046304192,19545292022072695979212345737390709562681030627834519269858193519314537426533,7543800958185166098093959246645025070235714806654195385000743554473922936618,4625475082534149232161405731224600013881237737740742465433231001161153655617,12763413547514960206069967971684559703789391875445961922711624474020658766608,16881857439631059221437594346198587121133192812269921863116602807689099485795,3231850141984038920375478271531925025564375094627983241106994584163478821676,12025284448956248150398233143375971306100458475218939512492496426861431663478,4525425011555084029555870990647344303529266577387030581756537915893006804174,3795501990414375556011654275060518399449630146003978757203023617760680325709,4509128642188781738213513757207125341975604363824265606323571895455672910764,12203047758734592203615462366516348191118610129553686354997732038970187121007,13638687018405787761639420673973367506339916347486774445588648879776248875396,1480604348496719441038523415355764543336234934845679094037807499653490493865,10692361717579001228187212442602435054487474561573499974105521910665132275515,5007773285184019093586454921139763432640822738583548849737728483623941935472,14779176361271780821074929551122175132746249520990325894754727749064980218318,8810869743928256631039877155210471039332035226261305285283609913565228857800,18154173501970140404154140565370264376529820426626464552253141823874364956900,11656303509442573507998921894257944851336988233800378817636452696829680890350,17658875741559155615021995850723408238216088494443352771306394733637591342379,18902160612986281748775835015982844003483334222891067179969353562662106908838,21595310045201809412620701470963174488544609749637202383626402540041734306075,19479000691333638193560008307308022198954460138615126342769742031420251871629,2972632723219534905306782557604159867920608086253824361540409985645334537267,3847529854347283694984727631990010016411937091308711649053729266492176961919,2403423343103741792664345548178046472942690163193710191494177026621927723840,4715026270007766325068951713831542483223564562870257986931331836552507312912,10050946066792704139911540686518561899625455529845988837175998569612056291645,8462612443675205626907647847435181314299724037672159352834910195653278990554,21536131862603746518459731430650379927614037990254564979711500405913555717860,7888269140704212528047592848167567446827917489655456773861487833453406017069,1170377169572693438349285053961454675716678619265656860173330864613871015536,19621259602533287127007734174330694952187330430513568066156633937834027643682,17165866032840109673438683878903959007172818091757219456373859826178202458170,14933333727688891927411002006378277183547380244506194877231532901665762194033,9343867619319423527260818064767777717418825720619434299636538864535443951928,20583768764298760141290708372295636534035063275069820261065362331153347542719,2577125135040205550039517386386446603255535410845714513971957864613256569227,17000415305135911202592785659979381300200707282766529883690542305214226820231,12511346220893686853445962138128902612419766727072608028194026193211924059518,4149764657828794758957335209849218835702975200988138041342768571619211624011,12689460200478357229673533402655824055278729189265502524126586766684281271735,13400421547966647260602415862775725767930791927979420926402318903131836007467,2276424802663141757392692926366037451925020546827329479674513290273559843227,13207120510498253902527141512742067250437249796266587317279641215901655830896,11305234940211349140158920206630802129159533495623653407204084399910372957174,5497774303468738593952657049388763226915569613134333653497976925327612433620,11780989050042171707300156320134237383624870460000896361633114513125178671303,11197132624111031475729914540831613691695800675640925983729890209473799714664,16140443794881450163624886684327741887016098106725788249967592676372285999349,11051595327889397185166361039119529941213436445931880650633610124485963060123,4836646605031570157308209197698105249544981108702254887271797808619270080413,8209009069949005083422618473679185090070432230901987251869909206753231145136,16474909562767173375575972470108350369290532718799369728226238753027802729614,6086055204212098936385823679317209054285543683998660974885049732319143968166,15845663692001601094665565765687773803894441337616861842355695214969875896066,9098420601018427903226168857535773321796962623728010568581252061114961655465,14398020486027915166775907825392652502550084557499300430668649177321914768934,2529766650486869899750453189656713618464482405989854109458777379339220142554,10340604539765718682878802989600110179317791699890691229388614321680034249914,9878876288226000720310995235539201725902546228232202248134844052052896121876,15598631334601739991411156353640870142866768421111507060679644747315412727160,12476036027414150699365888926628033468852849122092016651897900659667567319806,20803031063635652861008057675598133287087428947752503544588637173888166669892,11219667600899420706469792543049361323110081262796605270588885844619718041942,9239500483618882938511561535687911499489200513580468310964041871852656042420,2295137860333409753273134561401486593645236761709753752653034489900637997862,513840239484316074257070195372896343613221099656421936676995152626965728304,1240423160571920455132480263739570027604064696559298170495781456216075158172,1000335770452092111597579881696386094005166181014081250146819592415429840281,17732477784640275643871498532120858657597895452427536145089468999578047484919,17170981021801009209909418054936322243367033572422755593175460758882664580508,10474002915893131225108722048498342055539813455822038310171605686332057287523,9603348396520941909404735719689357385027896452682306755794683717883589365434,13997990766251226080324180880591113480591220558468819674906322487254600879864,19165322589470665586312376362321121865643126447966933590462565164041476345514,15889877351963901365648141054999234691357421706029208812358207119735767519856,8668047067682657740038874191537478915165931784511538119786089297082841482372,17366185630903586492716760756481097015828466883331247688174482412238176387717,21876355395221655909209577718688727663428003322801196411166438189091863032706,8342495812890419318878301820827026193204690451839354912098079931173365213850,15887225707174335160711915570149252929623026695369026542224074924735308390993,6378295267974387238182583304654614405910401210077434367173120406371155400542,8599288341856208016511446109829802753279910611437057243892303163654271528710,14384569526991087242726852106274677884712683003324629101047489219988189168985,12554858483255821944447983588851327925753928086067377749529759729841684476442,1244202115364291386279329790002693224358694897412189477392486275482043163127,12995340746860271768506969399635216407185990298275348495956441603189500195767,183027008509741755078232756367286076025735908110463758323021771971495606238,3573731114015522988150416514182944755210001235963017910935079689853918043877,18230391763740278339288441222957881377176531304894832542129957275399074045651,5937391935832132177003018978899438941930145516233683431615177125757010459652,11430996404641585372503695535042106445550893936697962891622779166741655729488,9708207568505790825432073778606679121879367766370067169784170835562004694648,13398805456168802594406839007653458669253514721606724093311019328402863953525,9509172607193998955864433140854270981598209332315830561489225794322679022459,15502257451151630587420754221500874210427552449899109970701467342791400645333,11123898636843146818131986172543146864729611142704598768652657993190010179131,14756654073235850387277128827870550186598788932163678015197111219905127222330,2775596743802877046549055877116659535653734622828894792515801349479916697007,19393614735747455293764838818808226619563895886462373669050764399041257455003,1249320178045456927170274664240781660345447736835400684416240818258732622074,12796406917637014666646024992328239080230785967810042823382614274279812889313,8731150020101451449969760761271583792743252060005019647239509560664328018351,9933789898048906634037638211430912333233899173340437080629891912049447301727,7466451925704968193666093494894304477671721132981190905063657961063858961172,18149794038935586919422942907608353967008376245075544434132167909292547581560,2645338086907790474420268058095037943265764190369965623902938950146047558570,3805226260777608297922168382052882356808083423152211373837998107098065055539,4989302370880302660583716899846990066057960576662320219898456979014043515025,1070415851697739963236557454136444292508409566097266743684211383600964969141,12944245506579810779814853939016758644439439209107032516878032396119045414701,11769349237256342071683275569967616595926207710668472449278925821680308524365,7515880964846644263997052091312985911975830135506678004303761824155773875060,12464357909913670578721898201968110981078170975300784494985401212355213230335,12531063240134560397069746994123636136169642575111678588073390651101761449521,6147041690306761331612194490775813268707261569782473045839636103273693189609,20058953556654404269207947758850631052629168082562724690664696238258819343333,10671449076032051862717464872993019906670729457438083279869852502398951441572,9263778898906682528709315203073828182663073896201474787696895934306219116039,4280018790033654530253273135477384827165889895493311470077828964783579313988,830995672310831856642518343627405480722960393571135174568745694822266602592,12314576340884680561277987296413286687270775984122709242612931854296075085360,17095784374018350334250759671947431499861842886424783004809423482855754115377,1870276341686143971262732849057691846357227120913088159474346497974038463590,13105414947588023527779026549450388391878972150198998416931943855651155797800,18101033009026370452679604491367700242633788731529564744613454397646795133212,19518878118392884244142849835491751668891129028130325012169949275103156284312,10048097099868399020473369161831917580618232227587941412911792567651718843249,13720988503976110065971074438615366180970893755318530444813194189426744566454,10206920761042395073417518236713913313307032364045319534823111708069826397746,18034670825630502903409981952109964720282628088881306395156166316305807778803,17265902307488235822005808880948915593987424296023174321440226533612013329935,9429365481099850064016032865663594803605999180077296169535937496741805848481,13186685927810765291293578499657740344232117785406437983769041709812502541933,8033401834359804746763731113146503141828920003868357417085510169143014612168,14829873372988191912376824090708426813704721449621613864198115299064092181833,18455257181054398358097306328798734574318231150508108527392947186444436439740,8119199559569330746396633117116309013908934582593556748077373019932279318500,1284108314616459045915004998457007728060914233392140668856369685125999999332,21852625948025981910963631951406283302114607467722317806583142816175293668265,14294796340840469579766310516350659401625921390409030932793069064155351769891,1783113620816999591947201004404230259494066685648885624939940386561651976668,20631226309571056417714477834545747594141696200863258945898766619654143617824,6903938062054591003542771080232078653298889568458433305746325082721608484955,8256881116864939888001716449324731552833717991541507741291129726788047573071,13687405621147199886679388919812090637070670174751017085656416653029285459311,3996906960213710686419471713152378445913261990655942335471489495797584984773,18609485914058202995712970621084391939086418713703752883448366703199989106805,4737790485362149715518348725962346663474900881645708435962411601476490671749,2822552925802124863166593828171280409095683790486058849977885272116463701928,10894109234909999803847798036461479359595641981247612273970502633226141682614,7246294570777241116302579516225659482637719855779307083700855528941826872713,9013198024264523556163293154624511496427558116561774530941327330691750043628,15151960056770776873319338589377108700463507419234056013408936730718825997019,13896307757522598026854039348754398062744662686124720657491498342048635150631,936098917227958663269717535799277732372546413929626514061262842640907378836,5762347306349503820330412402395950955095460299470544346332901816556543923381,9011672463961728692091882997147124758454879881989902775354620290305441817434,8298508790377315029478690089877957774356278876814712068800423484382883105746,18441738918640842202469737660313781809854248733890462980130113721522272925935,11674356714078179732189659380227960024612632400322071192164520398757529418670,21741531861742185590228910897294372846694047325677774428196013372184305103642,10726909710822683151420187237143914110905744739798587383554354069582246136039,14605794533892313551961292244462849563801666394421863533658628423573613615452,18252321089326369077368015604893296999452816437445326292408407276685442204248,16489511737082127400599277690755867907347415222776413612685047279770378853014,12335271216576477339942530570019671580774683415225712107993157387028894905764,4626127015007086021549442631728304324061443778286284381465764558652325702889,20204422163930758830873934092037602825061261159909688022442254278786267559979,5908008139766198991903649413759936674892226062609391695798412118889649830013,18949218162516421406624855541340518738013110700902674485216824630035967277648,7857158354961323527996104954036841386964344142685428573605787682122921808752,18862506387045373228977985979058776771998946696427211846227485792071994347569,21130307920872379374988363214010414716464915978170248808030666261671221223543,4313228149429751211745340097430041420420928800665815874510443032063502322102,14718887479978402714517595897896626933964355973039392802299204272000024809808,6557683321264859885031038170253446373377122179252187766556430383002360480784,17122476831292693338874176268140351589680349774087615644242938775777697017452,1742427015172593656128486448061422456944242303531295475988475807736737942042,2027235762831193006217486738647428392424417413253628143597055373587736173882,18820467606179165158872620834655197843967670286762404094202648563691406576741,10125524296683464483537740904779830909043887085914486254166411012113004643542,449309305485238804235855079592488366640797157061432847068620096879828248038,18174298857888178621780055946769726501913338858930582293820343672195281946232,6524685458133323533884653748284163312203275737781993034758692071803006590911,5779446108310889204396522202292098396120321905868746440329327547028173740638,12117601207346032264472777912492513317230650895345305236204051403325746076935,17386891799362994472985052445984141822367941805998642899269245566076967495748,9179366996073356039318771265789433069240332535719540885945532359919512410546,17951430600208154118507690771734790328820535928178248368783575740656844500941,14192271756367781523935569988212364655718978403224403387301537958961554173399,8221174165933793163901377098818684602634389528051583218569555199418881843300,619524678975534727395248661178123212036053322038080027161284774894885656968,6811391538547034359716390364062047260775039349151599816482953672829058524341,10339322550348888691122766885623110168053574406341544663827975995639398303045,834547622517043358034390288436661677632262995429052976763390684889069201500,4521430246419400790694482286290497928487157243703675820424059696776489816307,2856429439451475378239016597030439586695051951861405539943990631405466607827,4111906549409128541352401705521383327041723912730932911918947847640475304547,21238392279368838153073998702772069142756942255081903718049634748881681359750,8024413919212120225608654701439440497293912481641002166919294547045993866155,19638917754035941400580825054915831416618623037514650566052024405861982044782,6363298127640737755043533904928034878703559551572444680730376201407773738099,5951378579926778764731263132308899303911912211097125509228135617058018449106,4299191983632622048727922852687899517860127872286225781380066638217198421795,13147530014153459600370443470203975351218206668086180214214011567772265521187,8932462500427500118784677946351185252169486521981702322459979960456999825085,12898236202423618599592389067167172325929052486002381527830813712396261626227,11097514049007489440587570256998525432340163981998515135891661207289091581098,16939217257331433664860194883658557949066598882598231827843396489027582239493,13558314929316884214321653422030897165706985165664325794343497050086242614930,19068785933927002693740188802713137005358154768592984493993019480794959714772,16219047234078325455733500620647043268680743772219676241027699492382953851822,11566125486619880337971321232314420701391596877779136632592874470668332390604,20247803830618639726625840441081484205981495541890152476410337155981008644211,10982561928418184138823352638412764796110898816926174525705905870653768875109,13865455597687551061085338688013943905732507438297014744008229213490729171094,4623686187146061526075222395870304599606839445854872221666055672567414423759,1297323969860517810025547983969849541225259454470688019030850877270479215579,14722215188887952104786572716523684038024407798912988920497316253897978502603,6270780574886929570568937279666637132374218041131318249843841984676427785096,19252799885324088942740034016032302070594496616562387546044018090542659494091,18789886326443791197255838067795128702043473536108855579944353350374719120963,4004428942869607083699086726311786949460607919907288923307322356602295441411,2877506877897472797549134443444956093653579146599656174810841010891875571228,17100820986561348145097462952844272816935030845535472396118435485954197036467,1347748684215721199150368750223253727950390142032926135229664962610534785585,4154005697105794859947043472401749393077233408100643568245878899626874345951,20933456016305992700551258430315019036248529816811141758791937748005878705139,13670472427221544431486503737474464655536253995920989690199387492221273597238,4887586768965099882782231950154450807371608927535862225573402423957578253712,20873520765554306935202238707923195971241799663989834594965009759362455236319,835408880898587261190035308896108471998627156220026699783039947254106997118,1168560772528590466033559747490971813513190425644816736321133758228053063362,11336620716299236865855310989061343228509583886619209006261263862998075759368,12980812954661261543443724949390081395650693161075132555819949729859873154552,10084252406967656001546402499122907140953995723236718543311202294822930374906,1644532730355076490850165587814950390528959259229216666472798276024619697665,9132885938811460827145905853169583367514769405887568204387077749084430489477,2725900975136309543580364211869546121021875237274249313229081305044972484552,16649132526365476017376435851279563056385888284228253635122650167497125722498,12731917506454877589272897239554773638029036473865906141458475592969608419975,13594653727945200481903485136384279897657772670755085103508581365171774040719,113624989360858461940510511528457240403880397732971520793552365714387680115,7789436153009366426158912863312519977840172895511546817589361831513864987768,16143950714560148477045714466178426422461079160482754992311521791041688103078,1313437798365489562563299651704767522651128839986029835665434483203980839176,11252213995691856633725287186457035931029344732702134439407400361778220541650,17736157138183214282785525992210357080431726331346127883418866302441793685861,7180555369115773227093283745784562042441101566557650242391581159039035173198,12210449409908576791549312007483796989239766997007433768188337654528776461829,21645736522624670721457131423612680680560891552619001261475935027688037968464,5181231859976513481992166491356437447372643837921293039933901630631480168455,1822647984377309820943781894578040991064004363022862403681677456868041924061,18871375493748399832446064841374255973869421566131394074253151764055941485971,17104418810613244184376069439022653413672092602368197196666088607272531673120,21352793177578730013875622823471064860889253282644816974785905687738185801553,9232438288408252188083609458343687653050330220889343945216702072572457878290,10304159048240945355136802455474936548590756836618851032143486546904634881690,20884395191144673183897559585241012685606665510456998263218110825947409467914,2819516448715556874313717913942313640504691377816634987702668983716292161632,7032608084905515886212514778954491987158299018684745883187663518324250619807,7559036428305013706113865872782652760220550823937161831466421604635377603666,6166475941379369323404906159647871547076193215494151224037609592313271326716,16084803679651600781285997577643662084204923480676236051120275962952234677286,6658815199061181195201720843092877884603511322340036305618980989430727251871,11532335040368550811455379206918215244397070466594500713220916970398105300183,223243445248411375033016341241378810903532891138952541245228108341484828711,3833279990355432746436294779672706393587026552206068860301259597964955244359,20021860409670140006280261770552932742716715786145482153861376747693162890815,3960940475385499730462877864983553000107482077213680397288242993303568324972,15345391775733994458108231909936015494312151716517317512597014646307002937890,18277195779471824870812914706668217603589292191686932445872231693455894425796,12683998657212817923655738438553698764065257310760896868569072930043411914592,2381616850898069714423289625050293940364468416728632275660762167225224591308,17069254001556064617313013226218540738464402615134272312196301018778835133248,18389457738365086195717208767239120166429330517506018082718782715649157736034,5051258247116083013584227503078370155132486498229823799712010421955209135014,7997986980169935581373258514853533781209293632678320920663489466999553296266,9084231611273069170288134842362168520424117219722297893241580415854843050029,9612017102514059830687104062100896777017998502712927457146148255553769995330,9213917869163068338076473790268314749980273391311658654819685979854193078147,3968414534544698110694188177667553264094402034823447016934487565301236025995,13588240166210590726886944410340082403890007139576685347416857458181479170063,8425770643762906660570072207190993414304346471106950840911695090319487814275,1652806391920335323990555627698612547647520442841733871570123598479115999627,18130776043151518739068856550215769502964647168112043888178493846726550417660,19135684176515473484108881204420762325009779099777199113513850601885029049659,18523926306415003163998391622948236629256503699057039444767412461271077678701,14918281748682691271882204320979112338671695483566718123583225923120856316295,8780852767944315665594165432479024772720494001116664689088446074574987494813,12668508386943347180515022360355291044387148272127255261058463414454846963242,4925095646155669413280350202274427260281996843455607837164490899877054944846,2595801235413574965831438899756848851934934001108314616806171013774086568322,16016207465062828688275342866097975914741628027802243675066228993942777558633,15024416797683381415563755573423733835281624847950439607885361353822729812986,13470695612540254635863734898909669181168896043111281127113964919743317383261,16896649112088097145823038767205812267673142507502911459577638240816340032813,5645009976160313260833270091943535119457478455011072475922688828021639421410,602871159134715892643983949134724748180211299390344137568222174867411670803,16865933848430240952665445021880291168087114172384742393439371745277930120747,10638616947682848797128584610899807071800790542581123346366834113610995491100,15823119882352004895965266205059246906297215947121418230976223923682971872516,6335662959372125109139397987508104273775067107064186843021683240893850916670,9015302195224176847832179354591500534302983921972567063156768309852422127379,2916208839246568972516202976435804092919863447720049244313355052730101892832,12462097677706957512887764105458513125712391543206668564860335255817545411462,12645432056886268747459912808478608940565989560801243474226148714998374680219,3180920336675161838114354449885404230480750260525222632193238650778186030194,2765038069658052652090069059291472962961753315554068900506936144102952443412,5456153930594691794518876425254629839890061712982880399455001410106283524009,475588857464770407073340860667255085025964024669275489020055454066130988320,11604422213771358649337761367286746573670774367844043829963235653833716835011,21672531595983328080827235954964353440581013778240609331813180834517858151965,4158282767336475980124978163165153479336138216933325437750412278000398054990,6032343652765967766200639763117076693275022773598878447445516751911914770612,1408994971542022766817088410277637989937031937486427645416181643240579694602,5675369397167644827707774427966283386689036453227097867563588663607826158481,16553836408556819911384314376537283029998074714786222283151724244687848945589,11305817545614916257748042736988000193121142053044277161651567885557438654074,830935697282120891923075627410843569046784310505888414612692179620161520408,7111327705324010951262975966073430392141084274376586856008212260205185475707,6041014280799995292240499899142298082182090482839684923821947404991902712715,6861532079489296739625909197765090537384733717891476126939216899495278356435,19512767336722762932902171703888917915267449700217444230295060094846152793374,11362087145491820831916999481856548088963000118526088967383804499026380829346,5345785713105818128869449775136443413167434948951799284901802489769456439786,17034353050546517551433657764343123751855407033689772581554238132654775360523,20948587704598096549680941899688868509854524167514075706787714294359604474171,4994911941995400553330254818898448719600721576253446166237206475949959408151,9688152172628114951713346942216519356583583295750612146456768853572234580639,1343745797764784294443121474436370243518251011725658365765145682550385976553,14125032499992691719199426991191077310874247595141214711018898761632184485555,7693434862282992683488101124262547552730705787109948156284399632991566403920,358969526543359888045815665915036908949414956460937733680920722686744813444,10388303602140838746049100800433273910870825475060431768126678575590491651119,12003019672927505670536349874007900046436859031431459357691867861903891807068,100475008966885612365204906854412018822648141035087921833385587863034960276,4380976634270985228665957813264807511324931231158992383372104805973515660993,6796890817241810905532067210297629305992402701618394901609217064231507595098,7688772779168713577464553940881893522916379475003769246647902913600123216803,3719641128095581959416223705616297841752773711170097329183166123897200928969,5811339040244843745049016703193592081836868671814750017107506365287109556605,10595470132919677811136446867941153163237789139416696690218064678877242827885,13030722908918648575860840375066614839148197698661025042088986261543919080554,14270313844057453712442736904892342369114041625795108985761645871570953543978,20755955200977796735614094726104970512145122846293966132203844248531587786651,9582579815411229200777590264696860160165980649555432144848137253789895405534,4350662320089661964064338788392477540031840065706369837322029959874552780000,11294656075067466938178599864610454390092206885966775647004601601555888026051,18946972646213006149468901853070557711933198234858050136328420076856760929327,6183788518442229735210652665497651321434896307527846329693517674734369795163,4357012315121006561105620778754114894493832281520086713987988030701496525309,4220425144490786998849301484441980495606132822919030749888073325247349169938,14847262709636261703845309954203315918152776098063861666522433996841734492983,2207604061881398535333278399637137320820424466179707349350037157354962490429,10374520449793714488752224568044645973292278262497536584844249765683309087900,10046752763001031505421631811000499551831682948464981948135908582555522139635,10191830759680421095919984376117799343794470779618993576052513294297834150862,15076222662591944075232357720469485509899269012588377631779056491168825321779,10030346249770809877262359992756272056670319300684833869196768465826414079904,4720507975531560789365265597577186025064384475474978173798769571327267599028,17191621856092434134985786932980111138837305571579695662259528942970338620884,20148399372131987633026319910847242205929076170415419364579318442517450329463,18536741510173922435024204045457609239829288683624474544615917164289358647693,13631750264342742049519923217689863850040711017202360015936348405918551837067,15610854494548438731317902472235239790464071411103741562289565846725908998069,18387668285066173974072893371855420071639764562065930624890442086525580978084,14766673420520500288514312076124802867192062521660406237863986898959550205282,3732185864446238105520935485353063605521423641525603230547743875428671598696,6726861976047081116380559824755952195618930495454092484512720173680677582718,14230102015194545129058653592673168907799074203765469344837164009883877641547,923698051441061755360657704655014798009775419003226945193621553062258046271,9689434574353223411824004165283477169808920117596652474458537007050145695959,6653548670473374668472111797166160911158340899061222339537692495508721251614,3795538039750942962828904073106200577850807348658267681985654384336620251059,16992880538370345570685975897913090022139738512471371596260168908478239467806,2201111019550353407862043052634082471477202486461462021878536956251970423986,10288260758300652435946350416864664136108249309736639494191503136475372654927,15709483617520776431567199768118570957603227217270596124343406544848127051229,15072326085023560939831375504206736581668538451241556883193631319058350825383,12561979699882391671048614617301093740097194439650447103774288376923816448076,11578577676104716528266269909528660737784973170422409028333858070522660907599,4774024940257712349371248845501840009544530180895035663519273410524858053238,6492684254039247711120616647406430763803059236762636509335603649550553435616,20771468823570726361366818215861608649059576818091620623157713556101748134372,11770234809483645852438195876591109251904813195909801267796013610714277347278,10322220982623441869990996687272667519839773221084466704263092761447901512117,3873750796549479014998049182061589742243147534079044128452565125163635863792,16822068107147748367260830510353037256008422122115738671496285709779217814945,9894626898191884524351933214321095257519558205219922050393534754827614996074,14601192892171927905999982540260020693712306290426245380657926166256138073598,9507456803001734658737641235710642159379435011566715643921196640676158132603,17204767985326745166438450937743889339302038750836189001173941240117259581627,11493735704785585407432943012768068237407868899310349385901453142043105992145,20264601365705944529765978188292560353562052194559042151183990689436087045415,6396166643103201291451232462310280514789516631380296812005611744416636341945,6058445133237719937803819124490281802427048168421128127070586670707895911082,17832742609350217271111001369998668554917153176201832135065834598001176606174,8301910681660121964370976371283430908357731729231997961142961954342095329645,21200700180783276860226125147359033530111487784446376587831447494082008760372,1364486141742658225769231963526281625713690163326935801558529383187840699159,20160669267302086336804098028492246933121636960809421351182280337233197662342,3635162620064198915033858334726014494627531534027138539712906873727339940152,20185829971410353373403938384712968683319708682735072330111840928607967762630,201523690073703194002962504757428126542763652704293724447838128821998746350,9709386469732131146744455888595822333747765095732359649526137736669486544832,6214797208590500165345122859363723824928963832472111818012074756679462353515,9545179136572857559578932159310632305901168870225039498707457861463081350889,7958214991370581593237224161079745627463630298171564909746677637838740804837,10143975143960280812282386246733660505472918014880729933237691446362785576312,19887571710409013601609612720342170573208042935750400481652798519320490462147,4385901431531790517574018221866017216283585679251714390188554453215701245125,1664624586830909279573419685895566313699996183243836877427547144869129575305,15793134038802395204513915871355486670799044444942914383804421551073411566881,20470704207635104884647349860077097804311221255557839038451274311052027499926,6142526726838860239230170135812194898945683787933736938595250804972260353985,13855192186192101570267811921410903075943095341965742420598451678343592386178,21061758735696246985536203700046768078820850320825204373370639318620908053680,5662817483820503797666808429029051672943117302178352551614788456216271483237,10333519634297417737172450445440333857302089078097476871967805971949123871529,8218569982501149814702324407474792474686368395700170296571212557818282461359,20233400137285640555195780437569385053497789288081872387339896466294226099158,10072372834150094335098617649200237176564672558260325152023334458902878530776,9266800412877476308026297272156162694485705323044163059710847355278349659379,5276337117659173276438760052296857124207008171563166875174912047683077401125,2006436301001583347899849869571017812498189722949517889639315185888688453745,21001242218121797019239763758294108685115914209711313091446808028690842184156,15200074016374430224281445993551091543367930754541238817021042732526880610544,19710826528876999823124699885521051879572010811534557471867248186884736123929,21404362987802009741223312847298906544768900296657310719715972255986007016585,7600530036229891939971232581797836974827849142680304648314541550980439417795,21632454463616985503979878539576013805183337895553881618120668190150301665261,6334758595723856085036854188165101506598081801208405745986881361560891199193,8057222251861033664666134852961391247267479839150238989503146436301385103200,3219721852432286392418844864881031568045047266727931843416507933961433025545,15429997317679838542619650717630685653076454689042566593207301547187192181410,329174031237742757022307048272693803097641581155976690924186132266202912753,21732746139483704151357074738923965870601454140619898689390165872304758524581,12807082000874685484816248695921308340943213652025179667821051958845707861874,16064026146032729000070008033632737632876654216683451632905581465015365908257,4212217153278443796283906098959531995688364954974810176542537190766858609818,21143229289970553639173591837823586981543332391397328546878889800049585920625,16608191574158019592113901126750079565651977188938492362618874182536574927398,3624421885419003645925287958934125046517213705659854889615838255824651468218,19316501828231774431815118527212477451661840620435061360743197812130426231605,7662891999266634580053960517366506438335835205004858023405036760628949585740,16083409929948531376998108923041427957606534473459279085237388567102877584234,13084239861882397209044914415955882241492175271640738785828432132564815850793,18210156525345343590423422394059177051429214768712959878778772626339164549874,12315464041324428320313158873511378501430493994363943547122434404767709664853,8954605304811330146055184939317681861245665333018873540562258152334326318605,17293224339343743174562117843833611404589728024045173960633854068798646969854,12077428955835955218060944701333382577662880272982277398053344529073555194830,7126046228531607392073289758329125358329379287853920330519927955077178144953,18588044234272060286987286081803360761513524944191766041826466047510554640918,20890448514466943340126201065304171306189507157689256667534257974304306634091,6801003349507087476371788107799511762780253146305342273491215439215969413940,3780619510354109448305575837112860323918556596060836509041441555683227828678,8767334354313558924867811651574408725653000725545478833889044301516199439630,21066572358677074507410523123848261256731407535120503516033231013762098795269,18362039042064137510549303809539961459419339855353944845069477034687076489851,8913523920256755688178316396983509800293437764919338700779034854771483564854,11723401432613346160205532396432709544892024270048469362382924649893252868073,13215697753311268652932970590975269015978051881025604765698398517094385751294,10096875802507022627888049762027565166660383010058121573194339315127497644823,20585340774134656767573027722172296226739825364200221949739798500696627689159,10445154974790139558211972190334915738383718443406895551366524953208899973439,21673116720904254079937605482525822519756033862602805679958950491098633276310,8625969092860470813380520419082444422545844964279894335272441710185243798934,4025288875907887520103326512414690750293134922246866469493778161136380894049,14323499257030290650454481578106573336673758956871892054979745929234879010775,4477626471847050821212591107628903165841822822191648560679737237549532746098,6035678895480961290473069135353807694173152744259585744720200702817852056059,13087537929005319145430419950489154179166101298384003566794942619862071759110,15034538492744821867836124336381708186593112293438604485661643830336837149153,8805139564894882006885168301537536158944953788019925854273090624783308357258,19958581387726270611337524069699729934757503443234146496516617463929755531372,18594586877352581063978277344172832910008313781358399221576815775414535759101,20126420557250610569978010728469817957691099256920991551072367148797364737827,12608220343122929299383466116607513455913710378844501818574872277345002049133,7472029840435729707246144983643315764441672074448478483499047549570431985698,9145534859649655987690711448922451001707059796425112511085875363972462746054,14833791973699407961392823324214593517418186311389016446279089810253909982772,5890565022258491346280610728283677536409667465411457717498759331136098626193,6036941096143250281821883413338948223454138251490770618188682101941802166158,21282043678033183106352077009071810571452663281954166213888935238324321673748,20333804372144772829649652869275200527604963503726633269029046116798625871599,588131164750999180590569033490334261814498911261696634224331209454245047082,6825251444721740074952317618082720927334521807162055931163012547596328197449,917697824543986394290655655205290161739195186499427989467675782006019774097,15041830455925245428849291972925354368991606611607025955853683450026323915411,18474239974098280549955893651580150846097530768719853315252027744284466692200,3611784158748153035104121136455977264222066374809674800505557964617331443457,20604659450393945231663570065906647078596881678092078709858521111095167311757,12029452301550033145724326108003255082656089254479215038003174967331098163936,15356676148621236051968257733981998213914051180019702757440018429006515803587,9423362269266211501814985604120446961293044110825100766698681717935266136618,15899728330782424719479421593102373102438201721567285551304437858855478298992,19106020154064303782722594063821106692950347246115176981502414167189733529368,18908465093637028691441981127932774442154173676388632144231302290143899401470,14007866203893293106212925571168282959988090650409909185874688109550330526342,5342742216767912627176491444663860490435717482395442556665323768598286007506,3597106827456013501397704575480537495681742041904755766922490829038770978602,19345954862705630389044258042054882168728404897041130532396992253851595567599,13651761202893618441816264801125692678934609890284167560926428043317180108703,16448172308101926626190311626973854215995348130429072972101942893358814042334,13856649049195496934480457183055513754814884703875171340785294070612325977764,2593658379576055879381789234288074898757591156526450196693707683508079496462,12697568363447920404231218962893478531573733618972364303216707079428387821529,10578645587798138343532931014102095372709438567484299904261443385326645475306,9492492460728662705158180596118275120458955222134204696298182307017420905508,18064023256112871749609279367679203109309609541901431681842430343172099602354,1989944422169611668560419735240024090899518972063746001231995750158992709746,19903230879435744155012664241474498197586597172440005182506995303093565641777,1728511243862152479724441453437511013527085523030423049007411340644871969509,1750200860549110325737825369011951368084185262869489413254703181129282667828,8859957468047988361338455823958226995655820770262073750796277641227321341998,19127783638542055071733839851815229696558338746338070032734486927449049698521,7078877955496438548183194474726026189811269821062629263278508622456589680639,3091324818623570240229136118759236075549426086908228304466341498471627762399,14195346783292343393569267444162421134560117165562018311694222203790784872224,7366930408724527902650425878366319531313526362168392830194685421619273052822,2217598702761121052299380093973147900304006951260118283287015270774119856107,16027808241528674736324615318588531063352235936452195394658431080548186455840,9737799828204615060867766665537725835381601825573025977613959705161843611093,8064501393540602388259218046920616332801811052858376733153856073004571475196,16842422805430821078995618361206787780503480464556310995070028960079907202166,11112062472802799468234830097050518793604563281810316763737206541428998286081,3996143098194824093843968965659132847407504849137530967999278126450907191255,6307499143062236655628471047117923013144505466650278288900215043429516667827,13925586587992763438435497293527949989397459231522640308463502932206077961500,13087452945182453051277972085750711303320428980713041081211383304385877763691,18093207370226721487749634577199906992299418255969574006908138736154443387826,14272048411789712231464337625432600879032064592923947963806042930999866142049,5112973508688401012277318169584325529641020499005098236869086381676918059371,15127813438826152618698293752642344087924814601034550461410899877754994198299,6969695649962440087033894050377257471647257275605050327543911409064993144574,6755033946723836072389613036793975461823169166252828563832361834388266522342,6630309846049050707531890910192358661458908514573775713066783149977348075866,19770918646745678079472470109308561511682083548143260940369403377403283034557,21433670531093667302664653834628387344084043216006808509497422477800438816334,20400712430451351419962326556923150417233487338363092310732550512855900177990,9914702749825526925254257687000920413318621895298404563035360292451257098124,18640006733688503648022700222053193091432820833842731658823766601630552120045,15001143407594668782401370718438100322710708950874705625981291998887962398836,6239670443845313966789296359213657096108058977356600364820415786936148776478,6433425223024186602967246363501689243341949458306873394092764835636608100956,4675918067976678709774913862522295500806856576135412363070396552169178386308,1601751749870408670839362316137379218159388455643443723425257645986433854434,13458041123361531838745263080315252882353509187267791623642428828275334206638,14471699013899259577738777309533960354293333303365529990782321200494073324178,20280430398960027135010448240285550337237252858424335652593355698129656795752,15301671314764260006262782923235826735016067425075232061024349010859210176138,8527420415370243636986575303113397012724035052720519440118106033441076019119,3475125085974928986675306749785419160190213748540322213576708845513558192234,9006980194944928107206620529900294492273459999862240882500316250867368209534,18341113199274904243447557429147408702772610985345439625451614852727142466679,641303854841744162878167226844505402377828908784963225549380412498130669293,12717068536550964634894133707393353175533641253913906785707227145457684209533,4743152264042462778433711542894756531279965736412696362852105777475691147133,12538011691198347241319721961633309700824171196141123297965193643240835576405,20609816220088637782952524444771775704801169004700347625707989982325840582078,5706720205331708334089980420369782946367580993809969730038974418250776704373,13670952207260779576827977242585356546757059123105172869720468020067882252702,14767430839071230390516499921530329576551075490453331584132978354378461913602,13855121278897572089789093806573448194721330823581341784260637700156610112500,9029464346382645337824607466955710618425900404147532427117006888589723750841,1522014999882036268928376276435422913665212355063956230967744832498304066925,8291362624704304963260873050727236420693946064959013721544766852407674345583,13589063181500587026605394799486087482543530017803239994475549538732438667645,13329949252386676079710645426263377053183751810973538969788279784055444085091,12386680681590613307772862225908657100001403625719832791304530216719729923003,7313059443635334631417408104276385788845981785748211548782869561833456731323,20041885136971069417608157269779303040508951822068411540615824115716811017904,6497376869042504752008054895287149835408180730990917088183191265348284326357,11125724561218240201117500197186012921479012541837342663628667709300377769139,19153359808996709649541642396803885814514927865816858283729145733607372609049,20152572433538554395328147373104228881714506304708579989936661727209606561409,20016439558639474267285355593250644884337484988031314831332037478976434317958,7527238505813249238885718653381005755459117986453125478349742303052560976989,18157976047185465548629298047288220777638494790360987385974875362640599836871,12215475598068312355286440209098941716275384959997573662132780937926913300161,19661498481048830903134453807971238540013636804700867840177613880955309016673,16552339415724980921932277403793066165528259484794112971750640492538556458696,18694143444126088750994041983752049518157493949000498621268553485531912882317,3713967579039675465490867111467075244841382142654006118952820645091137343179,18003791572957152311824638498878311682370695010264579557670846595111585019742,12786965212577099174577804313633357821910340940882518052929431837084369088642,19196303109560878004701565248872597636081713248916827960361832879728708100252,13503920737086542355495290621258674491187655992864087131383678759555676293479,11236070378728091455898747203990505205014449224981497050563648348504784872625,9626632821060958086537183012642203130268418644318548991569123722985663518084,13034637881184844942276438495251249937482750510182566475651230823087848537016,1332579251268852603948763724532278782861309157968811258504214239247723497919,4440487054089857105584789445239911365602192945489433191329897791642671641022,6061652828396333618822938589797622370923339089332057787863230635686741988906,20443625886285957158375952392918402164453450517610142032850159380049279019890,4971727988681610479349722318571442785499756930724120997617079739694258077982,18834174333023112536455562602096071615163100988222060601738058925300216483554,1418358707619290124642186511810240322979679442148132663647788839527968980321,9146563693745266063334532013679253366507504975079644933043489415067653903203,10198203189192787713857436708411760529883983417357336104059303759507359385362,13457105298809247477659188594503481428440666731107167805254859937557834208828,17541364687047908905500996158296679129819772711555398152345796866338919060112,20692063470613585148684100931411467587781915529223705941251811918651910411051,255059205539662129885859108675295842232143503986252525395037544865412535350,12717171726844166947240066436059787676718930218202178144871226850052045252628,11844159733516000729567466032644347431569093736490287481873540624836993897027,11002794037358979127166193862990494036532493412598623614028528989937231393875,74143635505641635571137692594773070124419429312664778822553090280375104361,7056329304173643667817989532223449288690091032171349984912618184745639839146,18641921263165235968711057500989010664480104039807002554029677125998810936539,19559632820551845243777081617723524038257569278710484296878486836843940297771,20335178684657665532201643783226288715290471620876336715869115375508863124376,1400810679146237783184309652518065868576549410755675655514372408922313217181,4901107318137271229016627403293875571324832946427895930672961592355892796524,5432919409806696890084817096600220639163358481346859637851564223110298016918,7553857716186244958951458648858814979749280269320630962042771757992327513590,10889701053782808013047326782283414392744894366555627960860238324337962809504,10225055313049541990073049693496605844127702734102449597528239569584063842673,3178201789995579607967020188792297279206559603024986232709441132816492873170,6847656471793158091195364320441056206778429470543211654532315995128613054310,12528583474708786099486823217911492959125739967840882229222854187982855300696,18467266119817551899238434875437425808022051394845724810256998883759435014686,17038264911128891077018547486438046001433165723713308233430847345626729200927,17955218916742955831569749120296633004126823963586826720707041154002710061824,7211241300282304354221867200910811631523632613327223837945134059614958044309,3903314564827641199204912578257298318982395101598969445634590319788688787892,5807166989004370646148664081075213577472290526426314941919217927313093625705,7286215868775919967580841436085988310805057373157718787975640918960675793864,1250176112708058341117534856693109443612022505613546634776485361294747168622,16240306074762036443870399577875028338427695244117010393369806321281281115890,15136410716022250493730454911117704953380153308032786787731835907574927894490,12835091061815802274496704101037812141879397401714459083078081237987781157602,9740091907879287748866588073726349058132835900960520906530105112062664428632,15914692134543071914048151066306389736053927516189539093172532429297748396169,981367411385768085119476192577825808403597700860420619441932576179905250934,8146729957224132449602418119478334118295844780357577983658167000941734233326,590349410629703152398401018217258970865749864711821880028353966569788201764,1825395473256187220041087977011184605194426952605089376835233620262931194993,7123515738169356759148725471278134181610254795201025187792320024480691382570,17726785796913877143757425784904469412799726913909454284181133920507167220504,11651205611193223879329620496932918885123654427491270580240367578782038527170,7363492115511936228845261039013774575631247230570693094937015313770023603570,12933273009260754826631125313953911983930122727552157672205237418903525642215,4587914992471995247205971137457571771256946895956563575187244174461900917940,10792746122808647351065474080470836119851772052088452562229191086431179404978,20854485826587742461285159604615271614646978291370447131740817759213177014870,7837325030066353684135714390699866228186086140255598480265046489057880448954,6126605304840233971990826423459339578353618021565536707601222973624714560789,9552503931384803960142614388346661043921110897228435044165354206374121160883,21548322368276531554717543098918449676251611754505041151177909568762524391378,18180071753020516412865055548290459200005267908156340472690024449103604081545,19794881883035632088168728687250887611858393833912902865301935760311201163703,12697056234954492550471667283339416001528754790033934829512770385731960713685,18997188462081688420104936253788181208943789361069483606382840563484861418437,13583525090048988441168973253797491422796978202781056749054729098883924623495,19314654753949754551488116156913608959581776089474885903850748881648064831000,15181859580303507964634708303997342165949140724201743603210372837522352052588,1716462370658876925282526879979978257325560447381441363811430134855582914078,8712634103130722740728459133380535370865755065924597276965974996780521350960,9765286726648838325814219419835139491993130621932376855733750920135287306908,19656947946994771960907781244127562602401277628142459052853670194718812445557,19486837510931007596539998551154014974137134735704825357816939421451262185625,21628438018144169767837932394788626973405404712219671990762156320628259145217,3756950750264795710121609861402232041406397600142239597456522141772347776528,17539873562638205978340064500452614593864489286304276949397837992418594034919,31501567535731664761828271772320938243617735864979347171792246363428922702,20352331732176385362929127748957145775981304217223745596870640808444167485233,11226695452056490225554147366326688917799653401898260586559601210633144658136,11279669284613566548129429232553360604072423151872075897074160621145515173607,18292000567925132069216498991188575797602397842406377969706321176845302551280,17394537715319668724138949078062966852069669620345676386188677668125466782838,1758531732991926253426465239898570102024009352558916489602014827893071642025,10665213752467842898072683993424618781459586563812993734884914172018996230127,8324794334508227576619756931916312729743681044831168054976090310260143855664,6775442988166121274859488523805155937302608291295720635827623408019663108145,18295585939863028658565671525942083548149809167848494003118620027469243247255,12098041580596728911973293152187391806099106269046962124832995425376587592750,4179756701368801644640767039230959196272720402682759516084041748778250510583,16793512481702225401381949294778305375341554886405623120613660547710034551886,4048682207452656355407948755890074205160404299490847582459375283758637453365,1909268909139397440485048370655601811806256012192941212480683118923705439669,3957160465110711873678443805553768764193925226448354732024034759529771356073,19248605214573594176390251265821595013690814611654024253657271349217548577373,13868854211319335141393401333112190211632180475309484073606978199113030773403,18603198177495186944736198329095228547417364118472010561530819889899131849965,14961608796326843943228062129500114917120869339277918579779470648489101516583,1868951368661473960034964936590962790214375788389753455318330338723533775732,10905586386180037341368454391941851073795645267274288454955833628477189437397,14954127679800529819463733123869358237687206843820983026443645382142721727317,100097327222806530673180018653982439008319453432490738486899052539918122124,12805546034879808469495394895280673159114129337420886322224562831326122327785,14806980879080756440413940765209361196073245400503251970584575890653655885707,11244087337738788153622356037614703414595488262581651455100475566242231927775,18570222240753995928776550172488765352849447095675359684346868515783858763055,8341186767195379582987673341587963265518616797937499770780867790468554256976,16417432689254526830515766295056137071443518160358174458760640472715479776587,16841713253514960386433216886097940412703740575768017997853214356595383383598,14194887769957144867963380965988802472719946120213216012427494993012946567028,11529543378722012166333054004374317420377342192547947476057235546295927556027,6228288822288755015903485852969606389475962987032899088796179982251184963398,7936701363023944576389877378554772776727492414245244625252565794409904100031,15001498940712434912521276724772034272928752268882108797824422534795904619598,8473716056033059546731002019964120133827043541589774095605930332153697155158,13622250811616358253729853546023741257702106070523773564774458974873057917325,365025468139420802765331768400644334625920629446545823780682161731304140845,15188301566744221387195339021364877229016833910188161414607699674936046087814,15485783106434451702559510093123052549288846753530302451778527951586674987922,16738591797575541545215307991580378005049794467812864864257667302719418546088,20925739023580534811148616300343740428924012857265956692833219002712597286911,14889383841375932440118953385212403650477118619024418302909728838111026909639,16907126208352189929083708812165010150781216847422378013750129578871272492354,14806337329187045580963626107721698864963698880842972656340333617747451702084,18421538430347165869364634373319132341572867349320823968976066555816366184444,2434665826886017086044423893890240566257398976888986717506547657107156268130,4107084864210868857776853415457685723648054900688044144581857773829680966286,9975696437638488842544898875508262421180359453753428380941136617917797565651,4271657746853939228219168189957401961257189278944783942462379137544482211389,6197095881644784733476508213210037292053663537272178396466755799876037787454,17213367299854554180584426411972899951945067477706586927352113350447914118348,459213126097844409580498104618008133837044548373643874721876534610892189686,11543212578280368772068695265607222577889093375221336525779600349460584250291,6403298899310300874478654413460079479003477532791552465502800475489780616607,9679879153779101961935393514698788441597495345714510688032433497970373876200,13406313792037016685976311954559553063553089970578743589839464948184425020319,18447061183141116334003130470774130153225311547501637266696790170481921881877,8380490825353548292894683756629385493171585978110314915970595197861650821468,17748778220767931278266669246252235981422317813726374848817938354712043425250,6989443852838917282085440504075239616539844445576232297589557657622451430824,7831657729066776489302369169030303662771324770284845700052063314128105065459,3925294941359174220766529276974428294409483857727579665373968233976340302182,11937917292063962829330707841648838486196775641195800632090436249316243167473,5653419633240940595644007985875227652581749358539968324306529520430709397246,4710671638294627998538116427765044043262338916893456876128991289569569324348,71394869385825610742630406624465024289788832054180269745498390791493509963,14738615985593994376179875742690333041302941042023229128451420345640432224466,19352351801479363044593690690009745314348194116715421753626607893015433391861,7828134540699329284695760683671979636145431779072416908240193138816504514982,21767328407325385326066972839469738803639297445302836419167176746643393964398,4363185783182535592354777041764733165968243966270266866378133278599205816107,12861900092547198665663242905083918119082751367916515401033164113207531942792,26199715195773805806030726371679979491296157888969354080702618784507347327,11422842882875515086151723214834881230789142279246505109137919711737652087050,19051762302341786952522177542948673906514656868374502102797859778503069987555,15304419135175746829806105353267450572438302765436283477928256874309497427510,15459263896362250252603436487314027681146892842462223021544635764438917687246,8022722450368098005612162808615173120915189731064159685566153653273958491689,9933514811147109956084664025371824141534792260321581906034445537159964992688,13658822996647839872436185744737341749492205026854185105317636224609004876375,14379624233209822191260559290771588358188218543089774948098229868966603288924,14958992313261503520770373701642009455846990471215730792533739030356906680013,3008264124109355458910031641850139041159853342729069847393839537381972950880,19920038730043462715603813734444323019432755215636179923851277692610637123174,17230906594400326225968287949357928337332875589057677202822764136401667097576,3295851897757873055813703602696670024935942454512523388333117755329662151138,18768678356443319065659286382395610390856779982946155969362775884999359596659,12460586127165955570640740026112067337902936125125513451212701690418329829958,11058259665604247832957658651506896706861484197660414347806317812760432481190,4480738127714472007170345890289828985073762836671874831610164101698497828459,20356672216023774813369271811683185179666462848912908217024611254147608738543,14909200607508800723484308159953932832836734953149954532962622450689109093081,9061041843468229886389838095513813426084716371809563990186852970500432288083,13877210447577198749973239837374936528445414390167357430100753821987322195433,2839635391670662085450211408709683689698694308308101424896263880864913513894,446790459594546823193048947973948688374393610819268956164912891701746906791,15513394297485200475424313247005293190116598898090270540649465364671255026149,6430544300458423909335482367339522552006494240640365398487065900428380674587,167620735842959596421416387102879695919480795342009064535989276983300514975,7851629689216713462310956055612887013872895546158054432042649792702892211944,6972603886636382162328373670318167574093559853635999968924151410796861460213,19413944499150555955013296242054320685906330193520693124525832782341915610104,12263527706889748735493918123122221596983902069097405802497958581677957096038,12724987466750360537318099905062339029588038359925927031456282032606443592484,9708897601683631082524518294366690107466919479336384437075715215088985624241,5574496517333770677326807465934080003942242224011251056548046091202080747952,4426233947499799157064891373345188337862104712594055992042177154581455374210,3323616387049914826284182817146044206680302487334156840960948301224727078983,13004254604656434940963009501076991894817629784556574456240824509876544606284,7301157702835275823143922645275544869236677259284614641634323459896004519527,18085948818621221598774302236513376768745135801526414290158313790799455691975,15187850571325688566534378765892972581891242830408971491252049503437712864152,1246313402425855943486273052355580345666640430821848725745627960892819218740,8647394846748193532697036206738902082890058434940110730560542269988727795912,10064655809228901737773717896104022245084200167358447082271876992404069509689,11849936299337845059630533008021049942767799074160683892846518986534992566533,17222503330227123082665055850287821041983218187459530901865330120583332963245,13182290359799776528759669559625168410983932493170206108456280901111876076502,16922308846046171347608544335458702314243928203269931669473214292617484140503,7558805163644194610710740916145749972491144028571940176012011742150030513578,19569775351485108268007779638227959360722563519500120339858146797114197471682,11059423706111256170971735544260170713544645580527143674901672982061741530101,14932750633257527497920398771292456029356930315768552640257901217840963910603,3437896142924792262479946438539259423504563537021031548773393821349707014872,14782805101152549038431586973278748014002447400847124060642259960939628565044,19682001999640336579725059393603666122104885151774112167088565361216155864092,4233558995266469322360257198354042357488781625226686110373130567271844168385,4047511689246902987779521780711143086427724115291088073014684434358317932158,13856430748589477860039479213633534029749590309123560510004500567115861827367,5679747763871928801801426015291106236767446876847749477902392536633742028903,2480123750122829773963967496725275864472046134363280592972001159541781284867,3193376214066985989527250356837102042223952356102254301113166141443841024511,8062756153672663466999843325461563174537500405375937887043564985230465866772,20934273497132536703003386629581299436206618333301538059074736379428757199398,3964142000339408965627671968349646710437601305543271274636785761452376263382,17659047756049778260030257809618419752271933594271518827815853540916989127582,3930343349615664221386794926953117177573248229077177174315534154624751347076,2895341264817391965072938270159088942930942041694844772295944189135688863196,20818043348799096204572140288297522915577162783223193328931006646915252532953,2323581855503968054101786162741712103392782241966098143187644164748998373979,21506950445835751487883729097676565482258136522526260378635240810473639421131,15652663761688777314836638604018575636259220826467294056546736904699739444415,7055942973426557227578535789272026034619140718369524980726263182702440802766,4949575918974841751734514119081067078445927926837555007268000255590820633720,1398399621038450203083960309132739969264364773648996881599178794373813964423,15732506799197618296258053128654220838812930643001991164136863850944185860296,7794835596508268056707656540537636605902268233816181487738953353424162592877,19334780957038992630028385332334147629399375592719839985802296503565556738324,21635034093671076768880953665214862813027411650977124864184274112296716574632,10688534301651495143056852052149424865722511689194196231759927113549978532269,976280778878149721615236526300424224199708100054560296745736876703945737879,1661236337347680899528966953581439111854379099437324147973193626090712244045,376684649999303144466214973033408609742031466036082108742020038605665915381,4455377013377822379614998251281676782235647079572422444530523356359416320717,19050227778954804843017265242388770579299436899390433258601701002663268793950,20176738847900667540339144241305449384029623393968373234965844794399275414945,6563336600400724498009526486444642892816244088883489205001024055715188696046,1774742053125969896553337470644410955775448576794083561882186570750312466523,4720344938456070076793371724100707050168913253766155392188169516296487837219,12386484928350266729292976320659720907387619673269670145583838638028478942370,16511156064543308562970376025636430728255148453048880933972883964686852788569,20161060548546289109867983393573712303980348945862267966490524939511877278515,15745678416495620522776570951840736496696200297848371457414809276602866061937,4371269787269411959190919691547618186773560770535442840395153562222650962400,9183286542027774648383851710226269089477011745654659545146528858483988667073,6831030131135399650979313302695351819580359371445002328037898607795789751628,13808316624446561665670975675845412570522644424965154154503596711464812129094,16573850887526809906244420164574513771138034770054149931125695105829690192839,6536774143914522904090235450413350153861560318210355846585220439397199352760,7433401028165144185448409996814186253264882020047922839648723974949988749262,12023679188187515805015064799648457297092902074185758947196154639017034370941,11526239531876823273618354625960431640864995247037473959040869772406787371745,9965606134640358953439667616539308986324141554480312185321082780157059913160,3745993460581557715489390110730324720335274000085036229679909083358071037494,9383224303353982312273937680493563948228572509816601479265308820357851069284,1487827268845002359294235769079867448539095616058866371843794273898817464325,12752425410737476015270360130920506733622111261208379938979967899453342006543,8485480321269023262044616550897625372838041041299338618725089063696829309383,12576415359894007789769349543504370901641305511107563487651205088993508989632,21051289172896982928450490300579871201387152257916628019163266526462496896736,15867382033370376377605746630898769390447074387330276410404020451043720395429,19175636645506837972748760370147539503389959528500852183571848133179892449157,18562815464677471696203191443459870050160752363485379734113024945295929018010,10670914301723557472895334516073215554660627986142935452136687134270343499283,15711527071984806338686904487656233279759984782956970430068615997429454331060,8708497335606838864375996732302168404094513852034309829472484268061328157580,4188819471869628756655847772489988754984005896205326092058226221066145721122,6512127543122355053584585699891817324589817660150620823656474181624359941201,485283184789889690494624068272585257719678055879291431306025716514618916201,12469998319178098719636931437231251055837496888416524814745527432538031712785,1296020106178851400649855820617531046666668928599018437234450345456859444266,10011446468770184926016968173857732818096269728811257796162165899021103326404,21669153150071610384945525175896288044525929994331131233225247540220566590451,20224127309865911841696813826362911446819981503618978937382553360215894705096,11995994988481623386912855165099904216709109375061333173068533008232786187218,9410915142880940758336239494539529470909530692135279575732428340046078892946,540343796196110456420764600417592095932817965626261174892651237721778500283,13684306082150121243464309606855998092353075421168995445316517423697818489078,20162825761581699251737493230139692067729837621407892263730870777826880180708,5352686262532923758786328475456237662420216644156835779261605606151509572690,14736042040902670309572407869335525984156459843045648740121852458089457172710,15139196852186360494919007897486360521240977399849539996614669434222882428974,15545525411887550591483485994597179301368938856348279539852576272926020931130,11742635236612776978185392287408975566560283293946133146948657681925156152641,15933911044011218543142885674144914931062698638612248403425430247045038884929,11224528638969252327238392070525091272297579382723799722332333037066879094771,10619901685741876140226157641208788563882472537632692937793306998778377039845,735284898318336599638540292516453331642892791568249331436388578312138627149,12167882615164420400306427908818494367178873976878804005748498778042330871045,963476496798286039732969224933550470500612316061831761002103352026702296408,10589214229258115348033093903975219788029199245856576715398082842145004049938,21557152519616203688970824263287584036198859167308821872261472006356046725775,573869759526051245236872936984426432239686428333700586079723439581218874054,9487380087795664760223154980070289042545005448274508346993861027000032902237,15336219129184315874932697305233742095099896250996970622669888209373427981768,18404646237880969912286263998117686518695361809473583072241508209656556652987,11799938531163685220849832019747758716514224719376128562353011229084757783628,16344281677414470708413218213072185241641469290932113189992078158350700334823,13411067297619308137174262243170594092291209705703155674514006442224279302094,347096376483719141995221552155578565668868956459941108952060114777596679497,21711034316629345478518202673372708169627878437940325626238942704003376069559,18882050099612599842940192045274010067786778900079004241849918566254608017530,5764257238170917062706360501552002326820365975520365982521494644422134554879,15701229555594307124251301047127236083745198814231032790649389796695363681317,19380342180431843316217793484208165905833096992510614135124089140124740832734,5309407894979098314097225178362235237148427064335413702368413584568729847810,19819307748431076945425543888401840319829139172119377623119035071741874422686,20514761050842041997240240118048816505140382250318444479066954659053422537618,1344402086478653057873064952452423683387555289301580402150577440089615404706,16697255135945674012509919105064086681485448643989533271078867487484115301326,4621832835239804428359762201398927678345509964776233571546153039277467113103,3806403786653298341904285490244574263470519864399252904304315511448068846106,19829858960657679259830225387994355131769725454664502533894857362311545270016,14331370957097049770140547885384829422939088321033246508644491038102571773100,17602213870111183187455849162801944225604239824059691632957781727843794239813,13431951289066965496411295925849182623784324208488725900281691974104907065599,16717461480909222952301202387848079129664321734166452456973177865963036285419,5335304795187086185403562863303763030150108130150704291401586263249269328606,12084224077193103457678419187386990486069302392148214780322095375978824542075,16562074867094659170642419054272949287052074902139533680078784684856883275478,5593185214695460463728593774938986800789091570195563391333689785627694694435,20794081973744988874029976307272029218401016626938878812907621515041534590160,15290613354786940528909115982493729676786892068577902693057827852601851859953,12549551509495378488198674258192692896591847320322918116198744545244343099813,16172760618549958023639071988927160267123900859890153325976796899698706870529,21355970775695686114097146789571025790146162225961276367865670606869296144640,6758388446832091660422761046124378827605916325205674642673860154638138778023,14106404069959859167123546389809591376301394503370836987998148793984105405167,9246221316655556670219438263600949328330249756179668376432941216174575243170,17439153852461693097676073072037755599321185173017314957734642307684740219597,8081777382362242695298005068719699951526876053236775057946263871745968444089,5955062815471620144467538738332476050500085920379711183343040972831100802372,7135549743533376618652729621156592228493633259664287822661943632128030927327,6448789306286809743113676641229641365524354356867853498363388856986312333060,3836133206442752775823759632522089911744536837043185745585363415112795166600,8306967267195429229901513132397768469414281874455321140328179401973148164445,14279081291461540920232629360665447603436685365844514491245275283801357455033,18801535274021869273717064373621101183756544015062966551566128881569524508060,1290309525505162730469471418279301124342110934722264762505649909318202025429,3684482296351796270499952631629720483486993312250657634474107248508746062899,13174517099719760880623841117042663715711430443825712743356469456554740491052,12367323038661460523248093127080567074978912019587769246568174104058982359108,5328098381011440170293483375144450438184897394389341853376147620924621832373,12027556664769952184858265393953265399418219730267455116938121684665358512140,5729732888348277625941886883620484887709258694699060380279441089816970092500,4021085134780294168590418396176917282024838594185209785357282466818023080991,17212964584402772629081731052343755101208077509065176631705574779383125014657,20917432005010641713392920477403385909781374146458276502002720501978360592707,15295563898035514774486916635776497660635050791955975586488426545424778559212,1359821178683766445655942489230783986383452848368510940932965034076334706033,8110406013405532283463947127567634123149268608919736912581466809002624991926,827196241038734359771319428856617658913932049877272548875698342240161957065,3791462512735380195191512407306530846222290938359064542531485381855595890578,11406017533405938491480863229977030648871769070115386849200353035840595881771,520670302347263967262738466276891414776779776742458165836379179429124641366,2448606803226047006259184225386977543879941109635656602752172963011710994490,7191227529515483786577983572625758056228282372415415309332838080598142611412,3307446417204024568218448979093609311776086880103323372856728466529459088211,3813554883592508538818724202670630447381185344079357801330890767369937578758,5250709431012867357277423372041580897716232143432581463056922412233378167706,1091692079685509315891403580607856616782786079784896146193867325719999481531,4469622327160639333299363654867070539113198566013450831894562184457403911597,17323310137022557438196735285237348172608407585356043526322906169573029382454,16687301461250715912904355201855034952586622338354151885963080312175524252322,4918535113766539148632870060160447192025270821762409737556656897638575667317,11072593994523457387389747805751581908149754361901108358077132406445033545004,3195233728052289389067022539306995714028010328554486938319749354377057516714,20817686894891259203267112342163112292566908705837357461445233267117792429649,17690940439879640319699865226478735545090209049084370958835445823603146902951,21690628807014351230241926358993998569388931315165663025074689739408667261702,20459556268654252373755265495950372631044421643418312123931432417755203158692,2615012003869030558909061586486157199297754407476408867239954327608829725401,10416424720480840919038397124331362407722217483977166150169359209212504823727,21194909967788113390574471899389319930586662664636393856442773352403088570772,21522774899908415003330605964114671001565200771087582504208866633533540017562,5506611081865651016465481008237511873335242056816344474949867549242155650988,9546865422597752417260521115459137295056544614907437375816616393702205361356,21830596616035544007289279751950703469521180388685936491933709578982542912017,749611610802485176586202226352686769865522163389912514564999424571463284657,6755555316754154503813947597597343604907450943684878399336695170747270471709,12170672505455181293754012516713072944675179516356563083524964881029055628483,6707337549725648754250613641063009246814657413626673293152655855698987287596,10796498904992920132771232449170737749742455370471689413932089087977711623836,8377594495858973573128154823903039902710916666748285670520960751078778241055,3984683583649079079845275538974168947709880082512288559917193166572776389589,3342097912826432514400613460588054784328673911636756618761620185294261653370,16454683529696451672086473280821594992928717172228276559555553609303793416523,18807899744562842658522302889072060930222870278511178161869216361165074271071,15733467702619867688911165419464811721151813607792971238595067966297846247623,18142314765654743253383559257284245535624730148238939832089390410939642651454,11195224772751371350570884976842181779831961285896963666553011681145523971069,439244367736881667144534860370666344402105076566699968755250684892603338082,10704735720989025726743300184412677969903347430627186939154207946469729017738,18578876165452990292495920166540986834727225658030437088905164910953626259691,8557967377050572410782106944750290348752651270453684627569664713996263383548,8761045577121588487744533431678957572685193486431511842082771483510204390408,21449005117895748002614414579158497856671036353929407470614229969798846654314,8742763699897193075490808534988551410985191733407596422193467672281063172120,21640560187468057824325948244870722744182743184907610616373323268039154063822,20504827051323136179653341596769205909304116951166709098994304340550034816775,16172525553351370894318080522373536864524825253487998830365706514360525527841,3591685457927038924948528662301423116917211093679974227116322357454330018554,6023337410706762262272160833625601604408129024083079173527188974815598816732,18314718271070348604361238020618683829686900661152269809595508349472847942062,7836153641990744469550400020392942083885339413553995305082889896550143678297,17661458352757891434962464787581216134089171454741034624471153568868635718017,4122036760441574620764812242429576792598439550172741100479310420694208068906,20862235339890611718235387895311549206105487705288574136561783190763219344570,2850551701806552645458448511649317843914427882049290827414738885733429831896,11247005361958789340696615426808536553465247486357927152826112838641725799209,595377141566787974548956333113514797724094819448399289547808025689225222483,11650535249856393960142913145219442364845834591244773725262296147168383099202,20317269079309969728497469029861008772266846936951222269809633626856816105008,18373353028723033673212698815557995243796350917201491012576826029280066160567,7414281571887634589036890397094381209738607746338326059409587963803891852201,18038763738650749116346354096722212724532913209902202281075842225944189538168,1770786615956839194004148114013826935077292967352199469327501774219607260953,7488031997643483244135856650059587771856081877857609929648968340004445042854,8828420155416920637244885570572746512651260806059857940333819295380848667606,10713758486859145329962611447140189455100648474003892294431344231535672892839,19425964738010714594065721309197326935753724219070408633462182732050226443166,2074939531697630696938698501714595125993887544292881866150005180791766942998,12047170609336587447894029543834769407220306562179617939497216596360229783300,1264730939976742978058162525644425945405879597356760675420608373469615068174,16770820387947475117163540876143499701759349964098540413422664664028819497801,16280068293625117002805552395286584356701604835446863786447466051605766622630,5829399622833188992426267462479081456743106260845929463922917463933701539334,10637584899633814574790036401685386209425675304700886428980902763634911791837,9291782595793252587833322197337655894886134207930378095811922971339860144588,5951026341599354622946777675133435736866407426534732764305509667517377130324,4403580174404926097288523091529640188805282235669930524399146786861723458014,5003639966922553172252470768563093188889050306376650665702227782913343083764,6558197410800499965347594156873334155413890035105551024236266846011615264982,2475377503098365612622742300317283313185534384082772531168342518799898155594,13480086440294256226712366993542304396509909765502683907895525126405850150623,6847184584651376043889746562956674365958636593745423518578010394007380039425,834503921046130599339994952233856873876410737494970024102211605603428829597,3623466614124962325494185109684730979089103423795285554788413052641061197022], - [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] + [ + 0x304c29aeb6f1873847879576d30f1f6e8a3ce41082c15c7632df920d6db5164d, + 0x2b7380d8b25bca649b3f8bbd0a86ae417109069be27066f46fdd1c7c87d4c40c, + 0x4c77200e5494b1cb8a3d334f69ae5bafa7e8775ba1924e563efe591eff302f7, + 0x6c0b8966df93080c3ac1576486e61ab0d027637aac41bb35e482bfa10e34fc5, + 0x24c73f425903904f40dbff590225f251ce1980a5a5ce2d07ae436e1d090778d7, + 0x23df6f6f4448273c745ce53d5d7abb5d26c46724a58d68844d3c3ee45e9b924b, + 0x1dc1b1ac389280188e937566071b84bf8189b955d0579b6de5ea8a5136bc2ee9, + 0x27f71c5ca774ce20028b8140f144472043917cd4919cff64d848a745bd569180, + 0x22b2ee53b302ba2e836b98783e15eb6de9d15a72cc7caa374e61b51dd0d2e2c7, + 0x254d85065f87271e86d7b411d6acc280f9ed257c098c9fdb04a2ca4df7c7d766, + 0x28620793f378bfe881e098bd2ec62beb46899f37a54abd053cfb0b3bb8d5e754, + 0x2c19f26d0836635b04f38fa30ee5c648fa0ea1b202eb0846821acd3c699cf061, + 0xf9ed87e9a1ba7ee7c28bfd7ac38ff3ba10849fb04d3322898ba9fe0104fb445, + 0xd1deff42263b7cae8a123a1641b7258015476161ab881e1dc20e165b3f04579, + 0x1ad882b228b5f22b9f6a02e10ba09049c9281b32ad71818502b66ac77ee3ac6, + 0x1822ba8c558e0e6bd0efd1ab4b45129879e43b7a6acf07579b1e6343c531a248, + 0x192c005d746c0d045f5530f10f38a29b50cb6c86039410e634d25a809203f492, + 0x2e9e6de4e745193d2eb8b89b5b573eddf8a6506746afb98a2db858134acd808d, + 0x13373a062c71d0754ee8b1872dd2861bd4c2545e807dddc654d68af43ae87f0, + 0x130c94f39a9a07d71dac7df61fb56cb975c9092ac2ab73b113b341e8198eab08, + 0x1934eeb7210877c3c2e07d9ace7b72ab4d659bb1431f8e8ae79a1a5e8daff5ee, + 0x22547365b9069f419ae8b9370816f030a387cf0ce6b88fdc54fce91c485dcdf1, + 0x108b2099b7264eec50ebab5ccd3558a359e34fca1cfb69df4e3f8c9da9faaa73, + 0x22b946f1886cee07fb01b7f8e3bc585ea8f9a7fcdb2aaec5faa878f378eb200e, + 0x229337b2b316c279097644d8fa861e5e5c07377cbe3ba168b55613542874681, + 0xe9283cb85fa800120344cab9a7f792e975f5c25d64f5cb6a521b62665af7451, + 0x112956bf9c763ec101af9a335159df07d1b0bd90bc84be291aff9a85f30f5163, + 0x26f27df4fdaf33f3d12d5948690653ad1ee625cb00aef92b73527d37365c4726, + 0x2ed4c4b73e2547622bb78403cd983c6f1d33b25534127e98a7472897a84e4b3a, + 0x9f0108ead7dd31504de2b846076a8019827086a0c4dd6570c1b7423ca05b0cd, + 0x1172c6ec16cc502fbc633f8a4c308b14551d2c4822b5918179946e6545e9de5f, + 0x26488ee5f0d4f8b5766c5b8cbf414970b750e7488aa316976dff5ab72f349f1a, + 0x392aecd00da38bf4e39fb198ef96e70bb8774b8152970dd2e1629b51ff10ae5, + 0x2f6d971cd5f9931144acd9b9e98bad6e1e78d60cbd966fb18e6f630a76dfa6b6, + 0x5a795d1230d3c781b9717735bf45464f36c41df07376364986d0fd12c8317cc, + 0x1e238a362ffe560b31e3b050539e6c8fe0da221fba18b12ad661945e22e5f5b9, + 0x35fbe3e0d9d9276c990a3b1719e27550545a077f6215eacb2479af1b3686364, + 0x7ed14110e9abeb3520e14682efad791ad5c2feb51d558ed013675289b1c6bdc, + 0x11dad822671724ee6a786e210e9536e0ada0796d4aa0fced69c1d411e11e0c06, + 0x110b32907aac869005443ad66a33ce28508c925f505e44a34b53f70a3aa45385, + 0x55a8f4be4acd26e362a4dbadf39c198b43ea025ec429df6b2011177dd8e6cfa, + 0x1bce99ccd0f37478be3ecc5b67ec7c0a84b03f7231630dffa5e16ce6f90d6bae, + 0x1d61595a714a5f1b32a5255dd5522d633a0ebf7fdf82a9cfb22271cc962c801f, + 0xde4fba8ef10768324aa1e91e606f2a3c3f3f6a29dc8d31bf7a670d31695bf02, + 0xeeaf11740f270654239779cb83a05182d0c98f3d4bb8a7a118ce4c0de477e3d, + 0x25c397489e65820a955d6284c002427a1784233faa7089c6677f103d2fafdb7c, + 0xeb3a160356c8929495bd9f58d3a8657f69f3eecab1517123e724a946dc50c4, + 0x19122ffd9b6430a6f6c81cac0bfc8b488e1a28758e9407fdef8f77aa1fe4c0ee, + 0x770ca4c67aa40a1659365097ddb70eeed6d6230739265f76786cbea0899e823, + 0x20cf3df7dbbf47bb220ccaf0ecd8f3d54e0575628a7291a72cf8db5e42e1498b, + 0x21fe2c9c9625d66a931fa931bf7fbea6c2808ffd7d07fd3bde15775957c62768, + 0x2ad158bb675ff14b1dcddc993d9d60a5b4e9f3648afbdb5bebb2cd9a98ccb881, + 0xf89c7c34499d981c6cc376c6fbeafc88b7ddf87515dfec65da9bbcdcd68eaef, + 0xd6f33ac650e35d3d642aa3fd35912fdfe5014b86cd11e8a8321794b9a9c2992, + 0x9cdcd7858f273636fc033c778e5f588b9fe6315476254f17aa602c20065caac, + 0x2bc68e029d800355300648a36fd8a24157750a0d6fb2f2303906451f3b3d9820, + 0x163f8a2427805d02620c54bc1d32186ee3d07dac41d9289e9aa3dd2cad337601, + 0x2b72cb042e079dee8d56b1762d0052790105395fa0299e79cc72f4c27bfa20f4, + 0x1aa578a5ee2c66ab8299fe99133089e90676c4a2e6d56cb9da0679fff6cbdcfd, + 0x262d1529ab1e7f58925030e6caf0e79a14c436e5926e33cd79d321388b966dfa, + 0x1aa6b71c17be336b1b1cf2384d6d3ee0a7ece1ad2003ca727f636bd4b70617a5, + 0x286a8a2c71f53994524a189eb5bf41eed57904d91f44eee40976778362547af3, + 0x37ade52ed2960d80bc2d92b815a5315883cd42d26709ae64a822ff92ff373e4, + 0xd641f097ab6260b2dc240a85b7799541f6e73a3a25649ce98b4b64a6c499dcd, + 0x1176510cc674b0f0caab00f4e9be1f8c6efbac7b7315ff6d4169184b8ef009bb, + 0x29b6783918f37a8015d122ab39713848ca84008abaa716882b0492c6ccd15642, + 0x28a8be58f110dd8c2b90428fb4feb59b67eff815e928fb7d75747d35cbc40ebd, + 0x183f2632e3ca6ec2377e8358c3205d23f9211b759f62fcabc5fb2314d0728a9a, + 0x6aeb9e100b47eacc2dacdeca2ea990f7066a79e2c7c83f2490bdab3eb43620a, + 0x212949467cdd807e8f3576d403fef09e9bb63ca3754897541c6cd77de4ceedae, + 0x1858f747bddf594d663ca49fd2aab93402ff9d186cb230a025d53b8d4c626e70, + 0x19a293adeb09485ccc03800b821707060dc27e8663e355e908e368e2e8bc0150, + 0x1d4241ed038279263a184eb3aab7f2e14326b7faf040a48628ce8a38c7b0abf8, + 0x1692838188071f73ff82734223e5999c726b055dd19bb5a68e513d57055d8bbf, + 0x81d819dda57265e88fb9eb5f7454ae7dcde39a14b00f45cdb19406e8bf24efb, + 0x1fa7ad5a2bc799dfa38a9c581b0d17990d1f53a145e26e7b10a0901a9dfbe8aa, + 0x140107d97554b55ec285011aa53f372689e16d68abd763cdffabf8718bcc77d7, + 0x1aa6e52c05aa7d40dce61bc38b038a69bb36490d2014dacf4fa46e71be012ad6, + 0x233c7ba71f9e0ca09ec20277fe09a96399a1474e4dca5158e97536892de72b56, + 0x223709deb8827076f29c20778d24a2006fab590092c7bb34f212c331b4b1b932, + 0x14187c4e94d059b6565591e16dfe2cea40731d582c1487e3efbe1cf305a9b459, + 0x12d57f9c3775b0509f5c95f1cc2e17f1264a5121afa6355611de2a71ee23d803, + 0x23ba06ba8305823e5e62cac1ed25888b6234f13294c93e1d36d5f2f73c8b613e, + 0x9018322b8f274623a4ef0562223a166c0fca597d4527ae8fbcdf297c8f6d1c7, + 0x1a8d0fc5616edc0238e5287d9fb6869468a83ac168452c5cf3f9a4063452f22, + 0x2b1a8db9aa3b060be428900b352808a1821e9c9f34f8c8e75b172def7f0b3d07, + 0x14e78cb6524a7125d7718d49dd76525f58cf2739ab9cbb0d408dcf2e12f604d0, + 0x1208b734f978bdae45714bfb76d3fa83c558d0976e9c9a1fa93a1fa69f7bead, + 0x26cb6b7c1d65f9e5b5235c3f31f9d7ff1d817e4b5b945fac94a99b3cffac3d5a, + 0x11344656431a0d87de96e6806fc0abb9e1514cdf175d617b70008b1cdfa7fb17, + 0x28180778e94d900df231aa7e551f6d7207f3344f5b4164d19ad4627e53aade25, + 0x1497cc0587aa9a662cb2e9bb2ae6bf3e75a0716db37ff072d6c5cce6ffa65277, + 0x1155b889f1798c1b597cdf4ea98b7a22e2291aa2f49d4628179115ad19817a1f, + 0x136bcfc49ef4ecf9c613bfeface129644a00a283c8e9567c0b0149ed7d7e0268, + 0x2c94ea318df6e3131d85a4681682551ce652db2f76ff670212c5375994d2da9b, + 0x11a008577edb87e5285159e1655d70b5f6ad4abbf3f8f19d66ee1a7172623cce, + 0x14262b879f58b553126cc175743b09b5deacf5aed297fe3e4124417ed2016a99, + 0x338d86b8e84fe8bd613d57a3a713ac1e971d52a586e94106b49d7d390c92658, + 0x1ad169875101e162c49ec27ec32be37ae3d379f347930fbb656d718b87c14c36, + 0x1e33654824c915e16fad4a166ee216d1b3a36428d90443dc9131f818df850f6e, + 0x23d15701d8f5da053866a07f4788c49476c5518c8a812295dee3aa1074db6d9d, + 0x2d2fba372de705aa005c21db4d71bba12c9d47dd0161bcd45409c883423948ec, + 0x168371dfb98b380fa2d2630c612f8613042e6df90658c2350b270eece90d67d, + 0x412112ecd0cac61c445ce46a8518b56e0f2baf839488591ead4aaced85fa01f, + 0x23ad0edb1f4fe974eef543fc17fcd7dc1a0f05e2ce5ac18e374c87bc09f75c78, + 0xed6be3eeb0b9147d7c509a9dab4ba2d57c7b9d4b2780fb0515525fea4278eb8, + 0x690d08198823c10f51a7ea3cb473a6d98ed0cff6a17069b50971a68567a7b11, + 0xbf5caee488cee887f67db3206cd5da24ecd1baa6badb44bc761757e2137ce3a, + 0x3dc319068295544dd33221944b9e285f7219f85e8855975c48f69f77edf0a17, + 0x164c0f9fd358e2a011e55931b51e5654352bb6fdc6cb2dfa4d8a75722f2621cc, + 0x7e8978e88b1c0789e9397e09c9eb10e368fce8724ca948f6f2ac92cf230e6ea, + 0x22c5462508c480867b3cd96e18dc3c42ffd90e1586ca41fa67158838cdf1593, + 0x922b97a92d6a11fb18178d05f054345b43db4f5c6b91c73e28f6ce3a22dec5, + 0x17626303d1bda8e47dd6d0da342e4327eae6c4200525217a20f6226cb54bd44e, + 0x16ed2d702c6f848039b31ff87fb1daaf88b23f6b00acd7f6409a7cdef83b5ae3, + 0x1d9552a42def1750b55d27edb09ce26409f8f89050fb74cc53072f788feca6c9, + 0x93f2eac6c08b0a43d4df37c1b20d1965c77103de2e6dd88862f77b322a32dd3, + 0x63648259abf1b9feb8c0b03db31f559e47f0e11de2b371b299043914d0ebda0, + 0xa8db8ae7570818bd9ce7c02dce89712cfc04f800d55f1562eb1ed27da9deaef, + 0x2addd8a7fa94a011e12910a98b2b8ae5387701242ee2281df132f9e9dd3fc7c6, + 0x82532cbc9a72e056668946fab08eac4817547cf26ef3eb8f159e76f9023dea7, + 0x2abcba0aaec141d7742c0f0785daa2726200b6ae69d464e849afd70465c9b557, + 0x113ac02d59778ac96902e3fdd0562c504b418cf8a8e349da7d61450a2fc6d685, + 0x193a7f639d4ce4d62dc7567ee718853f5c5284ba09de428fdf02846ee22331aa, + 0x76d49b5c0dc78dd9c8e7ccc9b5a35df69dce86805aa47fe3f8cf062e47e95cf, + 0x23051faea37aac8e12ae94b87a02411747b14de73751aa1a3f6a07fee98695e4, + 0x2c3a84859c46bedc24120441bb6dfb113c09dc8070b2e0cd139ed49c9647b737, + 0x165df45e8460cb7b423a9468d2935c14c93c33c700c654e32c2e6743de59deb, + 0x243c1dcf2e801df1b53ab72ad31fc24cccb07b2518594c4e5f3024da67121454, + 0x2d4f07748851869bc581212b431c20cb3e268cb7f6aef272deaef66e929bd859, + 0x1445dd9248e8bfa4e6698e7f51553ef1a152d37d88949e15b9c50c3e8074aca7, + 0x3f3128f5fceea223432d31ceae2f8b11b38a15ca9c3fce21cb8756e8e09642, + 0xe574b6201e927e5f369a966151ddfc5c06fad66e64d5e09702ef172b5ade467, + 0x784b51a7ae1076c1737eae2fc4c3bdbc2187b28f714e56cdde0cd322292aa4c, + 0x289012d3d1fb3419e3fa81294f3a64c15685ffaa658927c09c1833ce59ce5ff7, + 0x2bcf3e35ab8919e05d55166908beca23a711c712284c45695c6558e0e3da22f3, + 0x3df5cdc10feafd361d978330cb95515bc2e587e7dbb89da4ecac57461b75b6d, + 0x19dc65b4afbaa8127015b3f68d35b557c8fac9938dee95ae35ea12da61b7dcd0, + 0x1fa279d539fc9bf724da2e7622bc326f9535d00adc596916791d77d03bf016c8, + 0x237dd96ce03469858cabff18944f05521971d1ad373ed6e041987754dbfcec17, + 0x31261638cc3762eb025a716ad3bcf1d6447a080f3ccc60f8117315254f568d4, + 0x24fb403026e10160607af2e0a214aa725637f19af7ed44130a9400365bf61a7, + 0xa773f9bbec6c35b5d7a95005477796366c4f36ca634e94b283233afff57521a, + 0x2ff29b7dd04750f926b880f54acc39f2e828852f40698afac2661b3053278580, + 0x1555a820b4069893e6625d113049c46bc5b4394d627c2668adccd3ac0c6492e8, + 0x2a5d25cf71c81e5b129e7d37a5e2728dad5d99d3109d23a18c4627b4afcf8fd0, + 0xd749c5dedcefb1910ec9450ab388da7aeb25adc78cd029a75bcec29559e8d51, + 0x2134979a55dad645ef838322058e7bc8ede30969481ff2bbe496d8ccd6aa8ca5, + 0x1a5d28f1ec79a8a70d8cfb783cff4c2b96e4ce5beb97665a0f6a52e73a70bb6b, + 0x2248fef1cc977b18bf5051a571374c36cad0b338bae217bcd9cff038fcd7bc57, + 0x1a3105c3234d4afbc112d7a9f38d22206c0a1e77112d6ac26c6d6aa63ef50088, + 0x6ff45e6cf264bdcb9e8b3b4f13a44d1c197ad77ee53d02fabd0c0a78ddf6ae4, + 0x7ea34caf7f9c9734f489953d428cad95bf98cd32d5c18e5b51e01d1444b8f91, + 0xbb9bd4ea562fa887d4e6723a798e7641a08dbb42cd72852b8002a86c57f1f92, + 0xbe1e28fd888e42fad37e72eaf884f6c6c5d037afc0957bc9ebb4893e4ca121d, + 0x1de8955b5f752e29e7e7d92d6345da11bcf32937a8c2abc93c497d1affaed055, + 0x140faed032e51900fe203d8d32fa61d9842d6b7283864ceb9a4d1857d6a9cb5e, + 0x653a45ace7457b472ead1b3438668c57d36faf59e2a19134756356ce5cbe131, + 0x6d23369e024dfc31a1e36cd9114fb7892316dc57da6613ecc41ca0849a1a7e5, + 0x106a234f7e4c5d097cf00f256609b029de983d04044a66023d477897b91adb19, + 0xd5907c353b674540c20db872cd6e0de8bd66f9b3d691396aa06678b5a9b8bd4, + 0x1c8cc4858cdcd5f36aebcebb9cf185feba809a92308ff5f63b66c2b1f52dd14e, + 0x18709a5ed55ee4f8614ff04e503872021e88f83d488d8a0567597b60e8cdb3f7, + 0x20573eb7a426d39fdcd5f46fa19973e6be531160e75ae9401b99ddd7e2ac25c5, + 0x1b68b1cebbf59b96e23aec11f075769b54ac1e7de44ff13708fab5a9bfe17719, + 0x1e74628fd280b451eae0d00add965f95bf19fba43425c3c0589207782f702b7d, + 0x1adf6672bbada9f83494ca2bab97f2e90f630525f9c68338ba4b34ccc484b478, + 0x6ba3daddf68d283a85f65a0ac15913461a7ac09a320e394d09aa5ae97a50db4, + 0x23613483e811cacaf27820d0a9ca552ad22ab29d4f1d579f10bfebd39f14ee66, + 0x5ba1370283ba319cf17f631a9291fce5e0e682ec1d01bd6df2843528e363db7, + 0x130a1c1a83e91a21cb376e0df81b196d8c229ec60df85a30bce4ca8f466fc589, + 0x2ad745158e0bd5aed17084d5fe12d671b0829a83392e6dd0a90a1c0292eca0, + 0x1a4703eca8fec84cd8234d5fc467737761e6d2d6bb6d502a40e25f94044e0aef, + 0x17eeda53608b4be7d2c9b6664dd8fc672bd48641e29f6402bf55443c667bab4a, + 0x1af9e7886090fcbbe73d9b70b729ee9f8a384c4862626ea685673b4837ae2627, + 0x2c300d04412f79e15c95dfd44889ef4a7df828c6b32776db3797c674fccb5fda, + 0xf617c15c41c424a39aa8a1601c5ca44207b3c6e44b003bc13179fa7afb8232a, + 0x280e6721e233a91f7f26004f753a82aa3403fbd9ff420411c058ef275fb54295, + 0x391c3b4c6aad3203ef3e9d7d217d4b77ff1fdd8c63a9fecbe5e702d51c53f23, + 0x203f9c14aedd6319d3ec84ed7517d5fc4703aa085f45f590e86504213b17fb6b, + 0x10842bd57c470e718b75553ddf18278b60594ad3bd7fe120bc46cb0fb450d424, + 0x30250c77a64030f322e0fce46eb9783655a93645784b5219c09eb0ccf3fe88a8 + ], + [ + [ + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x12826e5b9be1c9b85f7c98aaca9ce28a870687d3628d60def0ab3072b57b09b8, + 0x22fea1297a4a5f08904d555c2e15d016102a4ed29c32b4bb10809ef14af42c77, + 0x24cc6751894087b831598b5bc7f9db3cbb48ce294d9208e1aa436cb5fa2e80e1, + 0x2cc3d0503a0e1da952b081ba5dc5b117e646bed572a645266c6ec3ce0a1474b9, + 0x11eedbe5a5969f33446503494b469a2b83f88d3aa477e5d6d7963a8333a61315, + 0x189ae9e9b162ab1a19d599cedcef428bd1325c78740aaad6715b710bfac4c1e6, + 0x1aad11449d6e2c6e1adcf9e89114c336c0145528f356ac049f52fd8cb084370a, + 0xd7e1eae2cfec406402d34c259e5966f6e2eb261d4f08e29088325a6bb669a63, + 0x796a23ad6ed2ac995104a0d3e6c75e977ce29aba1d25e62a9a8a20364ea1be0, + 0x299b8e8621d7d8c8d3d6286cb126b34ee53b2dc9a3697b8380c6e47f5711345c, + 0x20f11ee81d2ac9a9ed1cac61d9cfdf10bf1b49cdfbb6d232872a1df1427c1839, + 0xa403e979943b8d2f947f6eda6d41170881341bb5e4fbbb3b4fe3dd7dccdd777, + 0x4646253380f4bf642972ae81977779454aa0833fda36b1822cb9c09719e3dd1 + ], + [ + 0x12186bb22000ad84b6bf29179ade2d4e7e94ff07e51627e09580571061fa8ce8, + 0x237e39980f9007bbf8699dbece054fea1f19766be6101885d421fa3ea46b5348, + 0x1808cbe7ddf2a3684d8a164fe2d150df62206f6be33d577dc5798f193aeed7a1, + 0x33cccef05b0bcf7b77aa5560a0f949c90be5cc2c57122f9885d24a117c63f98, + 0x2854c82b4b5f5df6dd3872e3f371372de0d12e16e9108766920b5458105e76bd, + 0x9b63c75dfcab572d280b057fbc3640d35dd5f16244863ab8a31e0956da8802, + 0x28fd36f1c761ea7bce29e6f00067fa40b32e6b318f506b6c94bb847bf72b5b52, + 0x2b56c2e44f703a3b143da03c25749367f752b16817257e6d123b10bc85543432, + 0x184e5824689e4f81438567df435f39e1d35a819041d7eaf3af908429beb2bc2f, + 0x1004c5ecbab6b7d12f6bb4caeab33dd56c1f829ee28f47c29fbfbb147e884654, + 0xa973a665693ed09434edb2cb0a971ad277a82b3385788552349ae09e8bd0c85, + 0x125478c8973bc395b648c822091f8df469504a71ca4fdf1dab59a708d0fe4719, + 0x2b0696d45980020a2a421073440e3a4fd39edc5288e6900a5958e0cd81e0eee6, + 0x264625c74f2a3bbbdc19481b7866757e639c124b4eb560da531fcef99773903 + ], + [ + 0x2399faa648aedf9024c6ac3ceafea248216e24a9e56caf5acd29ce2546a9f6b2, + 0x540f5492497595e13080f02f6b1e653e2e51895160ffd5ca14d26aed93b8672, + 0x1c1ccb44ff8ab6da854e9271f4bef26d2ac26cd7441f1b69d16eee0d7a7b481b, + 0xe8efc85cfebde295ce589de60aec0db43c81f4be7da44eb26fa4b71f7cb7ee9, + 0xb1d810fcc721551e2a596e9009367fc6a924857ab29b703207b08c95ecd001d, + 0x9fcacc3998065124de01bf7c0c8ba26ac4241f1f7deca1eefe5ef3d5015e3ad, + 0x5d2f0a3c223122ac01214250320b52ff5a3d242118e19778b2c8cd1a976c611, + 0xc7513f762b64022a151d62302099dffd51791d9afd3dcf96cbfcf6035a2c27c, + 0x18fde6451062016edeaa32e40a8fc30751e17e9bac192f8ca891c11f39ebff81, + 0x77559473737549dfb2016dfa72558bb2c1c816d7318763a5e4fd516b04914e8, + 0x2de9ee6529e5abc7aee93b794c4eefdd517c4fe12fa56bce06a3708d86336bbe, + 0x12b591b7af35ffd997b3a613687e449225625dd5d101cef2d6f2af02d9dbd6d7, + 0x2f9f88fe9be36457e8a546455aa00a0f5100a7f32580b78f26a77bd0b7612181, + 0x9714e717daa3ceb3e9794d24abcd172831cba18066c4c048b0995e9e6df1dec + ], + [ + 0x3add29fe398ed2d44f233125ecd1509e3cede77e6be08b94af4fec87eb3e48e, + 0x12bbfbb110ec2971007ddac5f8e36f655465d05f2462996b2114efacac70afb5, + 0x1b8d209d66b2c1acbaba435e304ae20662d336d10330beb3355cf801f194733f, + 0xa9d7ee7ee91677affd3ca4fc674625be897df79f82ec438e80f1e000c8b1f70, + 0xb6eb2254edfae1d7503c3518e64cf19f3443d6cd03b71cfbf1be5936da4e046, + 0x1a9ab3fc2059b0cff7e3cc431f7db45f59d8f7f724cd10a03f31a36638f8b52, + 0x23fba23ab4bc24d4880ba5a6ffd6eb5050dfb8d0f56476d3a30290eda372ac4, + 0xb26700fd4e950c25ad78fedb63fcb0d9ba73ecab858c071664866a9096f14d5, + 0x4a572b86105dba5253d7ed1e76d35a126e6718551b976b208f593f08158dea9, + 0x1bcbe67ed5fb7522adeafd1d9a150f8d57ada218db346915c86e6c00c00e38b8, + 0x2ea6b7a7265c503fcb284c2bb19512dae71ef357125c3ac755c6bc6cc37bdb66, + 0x30544eda9c322c6c872671d667fc5fcf09cfb8d34e8e5812b6e738e7ab40d8ef, + 0x206733e327a64b78d3c48b6f7580d0887c1778343b67768859e2532d7d1c46a7, + 0x14dac9059c9e78d96c7ef807ba342b946870679782231d2af0f6e4ab76cbd101 + ], + [ + 0x121af61f4dc5bb24890abeb9251e5cea94770ab062dc0c28bb8995dd8f183635, + 0x2f2ec51c48f8b73c51b264a70d2ba0b46bdb43f933de0faea8a7da2a97cb41f3, + 0x11738ced3933c4b27de13911db71ccd58b7b31344ed9153dbddddb91fbdbceab, + 0x9175b1fafacdc0e62b5f95e6ca67c3ffc96a26e37cfc734795b92f1e46124d4, + 0x210a4a80e6eaa799f7ce05752bbda4d4ff0520742c943e1efeeb12a91229a5af, + 0x19bafd0d7942b839f36ad3d70d9c87b55674b9bdee02a7dc30e4f99ebcc1d94f, + 0x26b8eab0dd0d95b7a8439e0ff7d3438a73a27b5993d81fcece729a824a3521b1, + 0x173985fe17f3b0fb85de6104c02b46c3d79eee9dc28b567f02ab1a1c0ddec576, + 0x1d948e8774b180fa5e1a3932439dfe8c5f32a437657d21277e42614b4c9a3dc3, + 0x1b61a03e218362204fd20b67536e5e6ca7b96dbb53d53ed1602302988614876f, + 0x1380beac7b062c6b89914a976a8d0b9d3276a13c82c23fa21f4fa4403e3267cd, + 0x2110c105efb481b679ceb2f112d6ea704442763ae2ac65edf8f15cfd169c560d, + 0xc272d10af2ef78a98dff7486c49d7505edd88c922e5672a3abb15cc49f4134, + 0x129dd677c1f8aa2d36d2a7d5340645dfac34a64ae456f91b97de9f8e91313615 + ], + [ + 0x2ca8ffee2d58f2945297b00cd0b511da167080d53949b3f1fceaca9616b6143d, + 0x26e36544d0b5952dde4007d11818465bde91c4dce65abc015e7556ba58b95ffa, + 0x1e97ce013afaa6e9c993e9cfdc9aaec91b06787819830985a72e9f7c6e516ab7, + 0x3016b074c814225e2d5c1091a8303eee4be476b1458ad54c16b4e1691f6b4724, + 0x1c1b2cf11f0d3a3a121be7d0ddfb24dc71f54b9bef943aee32963966922a8399, + 0xc474824afd2a880c6a85a7b7a5a434ac422c7a63aaf8ddc7c4d9325edef40e, + 0x19775ec781fd4089859f6b7f127c91eb83eeb7ec9eade14677b0a6b10b9e6e24, + 0x20a9a6284cfc4381795e3b06837e9596815fd5b6f162bde02f97db687c8479fd, + 0x20441aa5f4d5638e64d7ad9982b1bfcfde158f6a3cd6af62941e05cc8e533151, + 0x2d3d269ee324e7c43c11aa84cd15bad65444ef8369df15749a8a6b2c8121e2b9, + 0x1a5718f4a92dd8d179b932b0820f65c7bb93eabce398f997324f98ac76323b92, + 0x8fd4397aa8b3a84dd1ba4e2d0eb7c6d1c5eda1f764814b5ffe204c8ec735606, + 0x1a327ff2c46f5969fcacb463506e102d682502381fc3f999b9ffbd4520ba4695, + 0x10879ceabc3ad045d76f6cd5b26b56dc47b512d6509458f9ffde8da79e6649cd + ], + [ + 0x2c99ef5e064147da9782b914a294b6c14d21ea7eec1f72e8761671069d82a134, + 0x226bf94b86b177cfe7f03103d59e3f9ce2393821954708e7c723f8104a68c664, + 0x66ab8beadae7bebd26a33adbd6bb392d6825da37a679e8af9ae8bc4813c3168, + 0xc099861545e013a687cdd49a3a296a8d2c2e99691c2535da712d351d5e63c10, + 0x1574c9e5caaa8a6a7fb4894d2c45d1901d1c42b3214fe9a72fd3cc668e399f76, + 0x3a65a91d35b6e877908d5c419e7850f645f62b1c913765a214bb0f7a2915b49, + 0xc073eaddb5d3f79e5bf83bac00f37700bd64502d8bf7d5a099fb3eff7d3b03f, + 0x217aa400b2b625bc36432a545e533124f99c1cb98eb85df747319e85d530470a, + 0x178a58ff122d168cd4ff11a47280a4b8e5cdb313411b6f6e9a947c7fb577a51f, + 0xea45d22479ef5773e58b0fe740868fc1e8b50bff76049d5b6ed5e723711867b, + 0x1c7cbf2448de7114eed701b041809034e07b946a0340b777268529d582c225aa, + 0x2487df9d5e066b76ffcb2f0ca190abf5fc1e5872c4b6a36a46870e9159201010, + 0x2c0cbbe46422917152ca1906462bcb5a13ef536322a8715237da09b8c594cac5, + 0xf7c3f3cc96ceda039e43c86c1b680c77d6f49f50e94de23e4db42f8e9caf7d3 + ], + [ + 0xd7d07cd3798f44d832a6571c21706758693e5e93684ce2d1a5e8a53e0cc6709, + 0x25e311b37cee693545e2c2efc2043bc073552115b3a065cef13d36547b6b9dc5, + 0x21b37be521835c32b673a31d71aed1bc7f3ea96fe1d4c23f14623a0a851a3cd8, + 0xb71a06bb75b0a10bfd28a3788bf54a8a144b3287df9c591a2643c4100fe388f, + 0x26ed5fff06ef9e1942bd3d0d3ba6848e47ec045cd26f93049d80cbfa6bcc73b0, + 0x137908baac2e35e13f86834abfe98d1b54b7c25d6c85fc6c05ec7cded9175517, + 0x143991e8386d62334ca0d87832a0845b48416ef5158c18e7b9db8cd6aee223aa, + 0x148dc9335f621fff9c8d2fa72a9cf5b6febabe1f5ce77689c1a29e393185fba3, + 0x256e145378d2604db8c509dda4552452b6c4a891fac5da199c7560768d948836, + 0x2280250e212be2a48d293796a88ac62b05411012f46a66f87a0220a3dff3f79d, + 0x9c89e06cad5430153dd52cc66ae4f521bf4145df048681beb2e06a385050117, + 0xaad68c20fade1e3e2bf70fcef4b550ba00d6399e20d83402fe09b52ddcdf527, + 0x25f4103521e36d55e418162ef8ebfec6d45695520ef47b8548ba38b52a27fbf5, + 0x10bd7824fc1b883b3da0072d2c6194c4a1e5957156594e908adbf6e6b1912b9b + ], + [ + 0x29195117106623ffffb0af525c838686d0d97259fc73a5194609ac7b7b171313, + 0xf2336e0eee4685741ca23828c34c24f073491f0e72c139610524a56f71aa405, + 0x1e86ec086805bc7712b7510def651249ba1d491076241d99d00c692880f39a75, + 0x14937879c4c7127644c765b6362f8b98cfd32f8572d7aad9cc329bed5b507a69, + 0x59de873c59806f55114bc3f8309f9b64cfcba7434aae220447ea0e9c4a66da2, + 0x1662f26cf04f5b969cdd6b93e890ef2b5b1124f51822888dc2167bbecf7c31e7, + 0x5fb897d71edd8d8eb1f3b5c823a5882a06d964056afd532e6c88893a25f2615, + 0xecfacaad0c147e0b3c7e049771e6d4072b02ee4d171c0e53224214d17ade351, + 0x25f64d42a750971afcb8023070f6ec97bb2362b196a5aae2af6a70f2e7b357af, + 0x20be703f86d7c0b9dad98ff8bb9fc92fe8ac0a84c6897a75d851146f74840b71, + 0x296f3a9c104222692a44ad24f0f6fd8190027e0755567e9a7009ec71ef440ea0, + 0x6301679b6cdb17aa6c212ce342ecf681ab7cd96bf0bfb93350368004d97c353, + 0x7940eb04b61ec5341c1702f03993faed167db6fa2cea92290cd821b15fe4c2, + 0x90da12e1595551d2500f90310b7701df97676404113c33e475b2e7749adb613 + ], + [ + 0x1b62d4b17de67375b58f248a88dbf707cc9d1491bce0095644ca0219a01e40a, + 0xd9bb7dab4a189a3b6990a5526c82b0ae50ba7dd558f951bb9fd343cbb4b0e19, + 0x75d1aa6cd2b8d181c9e0f42275c9884ae6fa09186fe227e5c4673e56e3acd28, + 0x28f9e0058ebcf1591bc007cb02ac3acde0851427db20c7358dbef9fa9c57c2ba, + 0x17e39ccba3432a135c0075d720c649562ee4d31b6da2e9c90bd72a039765e73, + 0xcd0a4c27de11aeb6460e32fa2bcb289cb83321723155304929eb0ca4eea03c9, + 0x2745a059d0962f1bf0dde1e1b97e0bbf4c4143d10fd3fdeb8d2b295ee4d7a9dd, + 0x1365a904c7f6721002dbce17077a89a92bb8038bd27af53333f447c4cf035a80, + 0x2f812121e2eaccc7d51bf266398d5ba8f601a2aa6d335eb69f7864642177667, + 0x21f8d854091ddb601dab1b01fb30c3d4f77cc3167fa3332c3b32377a07e6aac8, + 0x18393505ea6230669a8030f6e76130a14c1070a901ba5b640b88ae80d7d30b5, + 0x1e151fedfea11659c189a31ba27f2ccf6956084188eb2c4c99b827f645f1db61, + 0x2ae1ec9e09577c82c97b4b09142ace51aaad1df7dc352cd4e5813d8cee9c98db, + 0x24ceb0766de25fc22789286a09287be740310c41747320bdf2eb5c956e040356 + ], + [ + 0x2e1681bc7c22d24c433f81dd3a326fd0242bfc7e2bdeb6307e4d2aca32adda1d, + 0x2a4a6cc884cfd08af4b0dbe89b6d8e0e58113207aded8cbab2d075053efe998c, + 0x142a83206747200fdb02773e766f504c65af82b200c0e7fd942f92be23d586be, + 0xdf653524fff92dde8ec1c9a51c1bec30bf36a4f01e9b3b62eb13f8ffdf7b8bf, + 0x2ae7f1414f1443735318163e1bfb1e1bcf5c271f37f6abf1aa86766b2e59e049, + 0x2030b7bc2a70905d031674efb420336fabb0769ac0125c35dfe2ff372c1aa4eb, + 0x12a710de6d17f91af890102226853bb64209f1b41331a1d17305bf5b7b52172d, + 0x1fba713b98742311dfb3fa356ff83eef234ce8bf2b0d4a52de7af4d2519f2f12, + 0xc8f8722892a2f06c5ab454e407bd557e9c2ea77ef807ee0e3d89c6785b0d33, + 0xdbd093dc16e73832bde62d05cbb06f8271fa47229470462d8c18cf8a124f9eb, + 0x1dca3060a6bbc4c324f7efba22274fd8d1f2560a4eeba8c8b0d38997e0d9c46b, + 0x291bd9401de20916b9002a0066114b3bfae4d3c8308aba4afdccdf0aec12d66a, + 0x1c97fc775f962fe05a7b66346b93c3260c8f6a90a7f5c63223a3386e19852ead, + 0x1c7dcecea59e6f7beb6d702e2fe74588415d30e5dc09970bb2d56acc8e08328f + ], + [ + 0x65850d11d0eca87c3697b6f5e57f78ca86952bad1c9047dbd2eb6be9e9db30, + 0x1eb97819b3531ebb640ed6b42134335419101d1db60dd1a924ef9665f7a91af5, + 0xee4683c8da536b6b50773a469bbbde2e417a1cf9be221520af1e755968d7ff6, + 0x2dfcfb280a3d372dbc15639eace45c0bac562c44e292f1429bc916578fb0bfd, + 0x12ea921acf5b8adc6a4e36be85713576d658099230b0b1766c666f12d92ab142, + 0xb5342503af446ef824df4df6a088195fb67276657d420e6f312b2628e922986, + 0x9265fb314a676b6b3f827f07283a1ed4f300e8d90f967b20ff61f455d2ab2fe, + 0xab913f65e1ceb39ed8b83bd5d7fd900e78511edabcfe62314dd10d567858d8e, + 0x407d585a6a7efb561377e5f3972319a3e7285e146c5499ef6c8504a3d0b62e3, + 0x2ff5bbbc022d1b74fe184c064e58d967f1aad1f0926c906a5e356cfc3b81ad24, + 0x6da6d88c233e3182c5fa5ccda1392c0f89f7c6bec4e60da8df8054807eb0922, + 0xaab27e6279952c7291f036918f0b279d3b1d9f8e4e8ac380da77ec2fc24ea0, + 0x27737fcd76dd296c28817646d30b1168c4d00e1f764c4565caa3276defd15c7e, + 0x110a5e84de09209e9363c03c22b537ac6a7aaba2f6a9d1a1f6bfab71a960a583 + ], + [ + 0x1a59b36b94f9d723577e504d600c493f2810f0e67112672c743abbb13abf43b8, + 0x226b91e352c65de4fcee112445bff20e4a67af0e110957319b2860d5087406bb, + 0x168e771e9f8f860c49367ef919a00d4f128bab01c13d7dd72ce8d36bc6d1d835, + 0xb345890b33c23d167396c583d12e4f3d9efc904f261202512350190ab1961c5, + 0x1815d4c2e6a18f4f3fa538a004146d7f540fbe80a4605857714fba2795615df9, + 0x282a555f9ad4fb57698faa1fc3279bb8c28c1f8dc8c693225bd8520db4313489, + 0x148ab15972a6925b714602710fe9e64c0a015053acb838d0e876a46cb5653f59, + 0x8e13c2e61c446b53024d2116ab176c843600d00e676402c4641745158c243f8, + 0x11cb83e01ff5803b049a2b59ae9915b3e0045e1db694a6df9de9c4e7152d191d, + 0x119816862c8226e9e5dfabf3167b3b2bf7fb3d19063989b24a16d97c94bd53d7, + 0xc61ec79b106e9dc6494a6359f175ff637839ca53ac8e7a13471c56646180390, + 0x1e8ee641308ba6fe5600b2df492cf2f14f9892ba1025826c53c77aeb7bcdb04b, + 0x16b61b242d41e1975843309a01a36a14397d7c8e7beb4afbd9233b453aaccdba, + 0x13822dcc3f6271b71549c2cd917b859cdac36af6848804d15a354d4de0f67ef9 + ], + [ + 0x1a4b186b77cd53f961c8ccb7815d9781cef7a52af64d0bf746cb522512d3d0af, + 0xac5b86128ee47944c12af531cf1458042c35adfcd9e5b6a7531973714559de7, + 0xc2a439067121449c1ef3dba6be1ff84f6ab7fac4bbd54ad7539e61826ca1971, + 0x4f7f1fafee121bb811344f73f54f4a3583076739dd9dfc462b3ae6343c93cb0, + 0x18f6c40e3ccf885804b374433af0a962b2963fb9aa01e8bae8cc834b3e17a31d, + 0x174c1a1095e95d4f098c8d60826776c2f73691db37ec3b937835b65b01ba13d6, + 0x1f7f9704cab1cfea2b2471d579ef99d193b234af90e62ca09b5a671c2428a515, + 0x1fa02616024cd9bedf643ea36d262d1b24f38a557a77a82c686618c3c33edf9, + 0x2e1c292e06b7f8a6e4344f10540675a63ca49e452f69565fcfbcd43bac0f3af4, + 0x6fbced52576a913e6cdc5c5c96fdc8f9f4e931fa90beeb46d9b3c2d775e1e36, + 0x2cec67e62320bc6a0ca32518ec81c74363a4b6d259bd275a63425d6cede468d8, + 0x276e2623828949e6a2fdc917e2ed45dce0ee503cdaffc9add815f6d1d3c4f9d5, + 0xc75ba60f8e0f6afa126e75703b83d9908116147b8b2db45ef24f3156b8f1855, + 0x85e380905eb2cb7e753d0ab0ff4918b232c734418b6bfe1331de492fc76b21c + ] + ], + [ +[ +0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, +0x2525da24e1d134d9e989838304af65260bc9e8f31225ca603420c6f22782a31, +0x138f42d30ae01982ed697be56da923021ca5ec09fd9fdeafecaf1b815a8eb44d, +0xb68eaed660cd2cafd2ac447e6b5f44a4acc0acc59379fa1e1d6d6c23e29fd18, +0x23a87eff7dac26756048b8a99cef16bbd4ed93f085177da15c763bfbdd413a72, +0x298b224b535d0d32e971977b9fc2b3f83df09ab550af80b838c2e1308a388aff, +0x21fd7ef66c4ff374e85b552f0c1162831af7f2e1feaa30e4d42c9ffe585e730, +0x2a75ec0f43bf0249456ef5cb1e58b4716e135e1033791b706c1198e370cf5912, +0x217005316ff983a988abb4150d5b89fd58f5e7ef95d275207afab9bc736dcf79, +0xd200fbac6500899253294ec3394f5fc2374ca3e3243c34cd97c5f8f31f78edb, +0x225829f1730cfeb97ccdb5b1df418bac0f761d57293a39d5ec293014c78f38cc, +0x17b09625ab3ab20b7be3da6740eac6450972d5297ef55ff4bee47857841685e1, +0xb98d9ccb5cd1979a0c45a9ff8f87be8f15ba1cb758c602775d2a5711dab8f70, +0x26c6a596dcfab11f05dda86122034b6f2046c51c0024c4c673dd93c63ecca6e8 +], +[ +0x12186bb22000ad84b6bf29179ade2d4e7e94ff07e51627e09580571061fa8ce8, +0x945c0594d96052f702d1c0c8d423cc5f054bca11e54a939531e5c6616696a8a, +0x1a8993400bafdba532b42fe60fa719ee2bb70744c9684c87431ad462b69f6234, +0x271684ec4ed2564694dd8fd7f7ce52f573c22c72e8268ecffdb3f3256cf94d86, +0x199d5f44df92c42cdedb75daae78948bd1b812ef63e72c6d01d77c9d513bc32, +0x1554c7a78e970212db02a0c7478c02343ddeaf350d52ad460966c2198475e5d5, +0x222ab7be52097210638f70d1bcf3ad6842230e0561e1ae556519ed6e44ab56a9, +0x391e74d9ce9444812f42cfbe156e7403ec00c10888b716132c819542982da3a, +0x145f48fde51a4c7f0469cca2a20bd5c5794c594c08ea063412b82e4c21fb67ac, +0x1c346dc47106b6a9c0e34f2b6a59aa07c0e23a7f0dcd72f98698b6bbe2440a9e, +0x1d881f9bc6c0a69ad8c4cf8ae0854f5e39d7f120543ee72fc776156a6dc41e25, +0x1d6405c7bbef29b6526df75b9b3a43749f55a7cd60c2956e61ce35446a14055e, +0xe1f6e07f1a7310ed0af6b08fba57b93adf17ac40ad5b334a7b5b8d2b21822b6, +0x1dc01119987d2a025898bddb1d79385b99960e97c100208b5e992d9dc74ee608 +], +[ +0x2399faa648aedf9024c6ac3ceafea248216e24a9e56caf5acd29ce2546a9f6b2, +0x14a0f9e89a7bd2f9e93a28113256f5909e18bd8f2d4c6a4b91fa764f5d6e9813, +0x223cf3744fa802eecb6e33bb5d345a4e2e494e2e0868296a075010d891596cf3, +0x1cae3329696575edb1c98df16a20e97a0dba9988601fe24a6ac327233edbd7ef, +0x2d2d2d79eedb473fc052705abd07b5d7d13aa9a52bfa0a34b29bccb2768ce812, +0x13d95f949c83e09efec7464df18f95b0f569fb43aacf2e2b2b0d1b8d6a4ad5e, +0xdb367b50c96c5ad714104e535fcde5cc2d98a7358dd85bd98cd4e7398985874, +0x24d565383969b188f2900ee27741e48500dfaab461965ccf6acc7290c5c07b38, +0x2c08d33aa07452ec8d30fed9ac5f8218885c18de68857395b7361d06d5d50c64, +0x2eb969d5960104432dbec4c924f829411bcd4eb2582508844fb46c57e4b971de, +0x1899d3ef6a66651b27035f47a0030d77085b988bfb2595392d46a09eca668e9, +0xdcd018b542eb51472ef63566573192f167b8a41b243d2f9cf7efe0427bdc769, +0x1e76abfe0e0c0907983d49bc07cd22392c9a9fba1cad773f87877d8514e4103, +0x270775b57362a96f142cf0560a3c1f28f8b8f84b1695cfa20b271217cb9460b8 +], +[ +0x3add29fe398ed2d44f233125ecd1509e3cede77e6be08b94af4fec87eb3e48e, +0x292e485c257794ef8e1fec5dacdd6ca69f168408249a6e203853615080cd2cd5, +0x22a26c25e3631f154c6447ba2e8543b1d0f8454bd027168e715f21c86d09d399, +0x2013efe5dd2c054f547d532fd6f38d63bf3cdc07c1b3beae0b830c536936dfc2, +0x10b99b04d7a8e09059e28c723db16cb75528957858c3f9988f0050d18a30e660, +0x17e35329c9aaa754c345d6eb317c368788b093ed1d2d136714ea1b2f793da580, +0x28ec7da8ea43b28add669ec05c0866c2498ffe99bfdfbec896bbd70d08720f64, +0x145115518f4ddc7a878c4a4c3a0cda353142b420cbfcaf2f2eb7d67c6817ed1b, +0x21c96a22d60f44c34f543b5086ab4fcdec036b280b9f5a64a3a2003a2a79e906, +0x2fe67a3792bfa46545ba3633c2d504d9735e7d03b58f9208f584a3ffb3f04a82, +0xc27c0b2f86856b2350007a8501222d7c7d89c02919d2a310032c4ede9da6d5b, +0x76eb0679a3bc5901abf1204e92462dd0049c8b80f0d0b110ea12ca6d9da5808, +0x28b6ca5d7278ca2537b3167bd0e8c8094a06ff3453e060a1f52f077ce3c0f9cb, +0xf7036425c9f4bc087576419d0534698adef68a0ded0fda90b211bdcda6e05d5 +], +[ +0x121af61f4dc5bb24890abeb9251e5cea94770ab062dc0c28bb8995dd8f183635, +0x1b75bf6cc3265511f786609179f18b582a1b6261e9e6a9f05ac7e9a4bb015a3a, +0x26b90bebc295253c79bbc8d0324cec9805f3730a7c7e3c8cfe7220cc90b2ea91, +0xca34892eb7fa3d7bb497043be8462cb387ed055f83566b165a7dabc75bcc623, +0x1ce0f7ea351be6aa78e3ded0a3d69d69de3890cabc1bfcf40583226decc32d54, +0x1b5b9f9ac26a2e054deca324c9c92bf4d64b0b7be729631f2350c4db32232768, +0x94707149dc563db7a45c5cdd80091c3972bf52a6ee3f8eaf0e6bcc6ac0e3976, +0x25ceea2ec9fe11994d5d6c2e2af196963dfbe8112cfbcdb49c5b80615cbddecb, +0x2952f32d846a2cff15c9f028f02fb60bfcd8a7b34ed120ab6e393a1ec2794a4b, +0x930264343e7f5af2b7e5a4f7f25d0be85825666a68d5c02c5a813e958c3253c, +0x3f289db20976c1ec1aafcd0daba9c386dd8edb8e577311dda9ae8082369891a, +0x183e186c2c72f4a35c4fbb1eef8237e1aaa2379dd8d61facc59d6e5f44da0a83, +0x1c921c4536be42aa8a93ec0ab11a37231dcbc0ca9ab7749e3d5cf9913adefa8b, +0x8ecaa57e55d210f56d9c8141f70394e59185625df57435ee2cc924602212203 +], +[ +0x2ca8ffee2d58f2945297b00cd0b511da167080d53949b3f1fceaca9616b6143d, +0x23894e025a72e4ffd1580bfc4748a2725ab6f214a8f84e40d266e5183c6db8ed, +0x2600d56e9f728b982f23746da7a2993bce578e7204b9edd1f474405bd7593103, +0x23e3b3568798af43a561614af2c8aee40d2249d9f58452847c453594dc8f38d4, +0x2145a0959a46b3c43bc559b8811d309d48a452423025b85cbb3febcb24f4066e, +0x2f172acf4fcd26f6f939157d0da15bcbffa981ef6b22f7525c69f9ebf801192d, +0x28f529934ce9fece64356acf523f32443178669ff77a0ad6e7b86020e413ca4e, +0x9385ccdd032e8784bde4412886e9a590ec85ff5cbfee02a6c5dafcaeb90250e, +0x2a4b9eb8b2f9e4c4f2fd334185a45d0d2349163bcd7b808815b2e89543c09412, +0x3bb2a5b659f1f5c2c82bbe5824ad64a260e21e688f5fe01c61632fcda348adb, +0x29e0c22a0db446552403a18473a2e5d923f0d2a81b23f593877de4657fb1e877, +0xbb85f352ad58d8e5998cac57a0fba1d49349aae47164fba3343ae32ccbe4206, +0x24e9c71c5607519169015cca5f0be8e416f21194fc7d610a38d3e48df56dd40f, +0xa098b67cc231ed6a2b72bee29f823702b67dd0bca78f7316543097856b478cc +], +[ +0x2c99ef5e064147da9782b914a294b6c14d21ea7eec1f72e8761671069d82a134, +0x1605b0bd96a60af6d3ce4feeaba7498571b693596f79c09a3485cb6e37b1480f, +0x1b322f4a92d336fb2b92e1347e0f73037655b344fa6ceb1275eda5baabf61dd6, +0xde44974e91df8151d38ddb337dbefb7b2423f8c2db33c95249664256049447e, +0x1cbf2e32e48308fd5254bc8466ee1b448825badcd0d038171d39d77bd61c122b, +0x1e25aef828ae1b75374d1806053383a3afeb4c247bb3f4fc602a31258129088f, +0x28796af2b46e4481c8c68767d755b2f28c2229892c093faa86ea6daccf4f403b, +0x2b9c2881bdbbcab60ca2981c28b4228f8ad48e64a7b393ef4ed080907e6a1774, +0xd00d400c8809e16db25f2f1593dba403ceabbe3d0b868399bf12c1ce2a6284d, +0x17767169e7d1636e0cdab5d29588e903e1d4343000d5b54f3e523e956af6fd58, +0x12e4b3d7107e8bbf73c227c3fe04ddc9277aae8cf8b15a769c7039d282661866, +0xf53bacde9c9005381ed7bd0d3a35048f9b04d99b54cad41bbffc9704a574abc, +0x241e0bb48bf63003f858adf8134bfec90214a7836f7af1bdd263f5ac91906803, +0x106f70b5c82b6a41e401fb3c05ed0d4a5c1d6ab66ab048d2a928a323556632f0 +], +[ +0xd7d07cd3798f44d832a6571c21706758693e5e93684ce2d1a5e8a53e0cc6709, +0xb6ea459a3eea9912c01005ac024cdcb60d77df03bf6d57f9de9277855f5669c, +0x26f749e039b1b58e9fd714e0b5edbadd2ba23f0faece28348ab8eb36126e4a7b, +0x1a8077b3370f7e65d450e0e536e1e73c9ce33596023de1cb2d4f1321896f5184, +0x2f6784fa0636348e5b73d52307c09dc7de28dac12256995b7d2d8014be1511d4, +0x1b4e7d76dd8cbb42c1e90574b4f832a07a53912dc74b2f1983440252c232ab0a, +0x9367ecd533634327435fbb0317bfd4de720261bd6c77f2348f0547d4dcd155f, +0x290e7fdfa796c9a6a1b3c2e6d746601f49febda2af0d2e7ede804b822400e81c, +0xd532c4429d77c08679ecb541865f7230787381786f7d98d62a06e8a7f33f3a8, +0x78ec6b19c1d89049a01ea1a959df4525e1fa2b5c6d9c7fe00ecd899af5b8693, +0x27932ea804885d901c0a89103c29995ef207e753574a7ed679b162342c54f27f, +0x20fdd250fd434a5fb9072c597b940cc96fec2986fd603526b2becc58e431c8a, +0x211dd323ffb6bf1f7a0c747597593c44053c3d5ad428b1145d04f0a728f4199a, +0x437b94aeaefff8e636816d1f7484e12de60de9199fe298c3a8466036fde9053 +], +[ +0x29195117106623ffffb0af525c838686d0d97259fc73a5194609ac7b7b171313, +0x16be4a147414ff8080b2a744735ee85e2327c3645e26a4d21846bbda0f5f6ac1, +0x15302004242f418b70c701b89e3585ac1d2cef27046b512c7fa841e1c7fe564d, +0x103099f79452ce6c8848e50bb04b50723aff5ef915d2d7ffa0b8f72bfbb6a906, +0x1cddc847d2f8d9e6c20ff55628cc4e9cefc59a283a38842462cbe60a9a1d0336, +0x29bb557aa48769cff8a9d0ab0e7149f835c5552e5e5ae7e6384043790e45c1ed, +0x1cb2f7fda98a18a6fd20de6fbf412d07f0f41fcdf2088dfcd0e0b852fdfb1aad, +0xcddfa96db02b40d78f740716d6aa26c2c6cf125772a9835c9a34a9046702db8, +0x1f0f734e95a45cf07b70b85846b65ffd3c1eac10a95e0b917f27ce25c0ee4afd, +0x14ec222b4b95c3b602c222640d8d6dcae21dabbf1e805637ec3bfd8984577c08, +0x18f31da4274218b2691aba9611a798cbc9e9405f111267cbf424a67799ef67ee, +0x18a38fbc04f4e85a687161544a2e3323bc7bf504a5ce34e8ba4335767cb4eedd, +0x218b8f679b6f2f6070519663f49d69fd9043ba6d1bcd7b7b85e825abf8bfecdc, +0x1a3d570d5a331ae41c938e81e8155ded345d180ad5ba49b4e1bb70eeab467a36 +], +[ +0x1b62d4b17de67375b58f248a88dbf707cc9d1491bce0095644ca0219a01e40a, +0x23dfcb4155e378ef7d127383d66785b33808a3223e22a226a3e3a0f7bc5200a8, +0x1bba25ef90c2742d6bab9309747fc14cc73e4024c803db5e58c7d2525839b2ae, +0x4b3c3687111107b6b39fde1f5eabb0de5e2fafb481c0845f0e9e3e5f90057b7, +0x189aeb454f60721eede010a005c4ce55509f152e6d0e93e8c5f9a9a6d3adbbd3, +0x18572091465cabeb96748f5482d37d3926bf7c1d6680dc932f45f55a7042b02d, +0x1a5ccf7ef451a14b3fdc531a52831728f5ec26b86ba77c952701db2913a698df, +0x152f38cb9808d5c942c23624abe88852a59f2813392030fdb7b1753025829991, +0x9e543a62e93aa3005be9112a49c5308f5b6f79591b4824f6355ae12300988e8, +0x1a145f49ae38f332ad67bd90734b8bf9d97dbc5912cbac8f57417e334f14230f, +0x8857c8b3f0b9a7649805371c01a74c84c67575d9a17be0e5590aab52143377e, +0x25fda357cdab4ca130314a01d381febf812c14473e4bc9b13ce8849eef1cbf96, +0x27b831fd2727802f6a873109adb4196ece489fb5b48113565d8113427aad42d7, +0xeb8c6eb7b2a00cb45db63f58e55d78f1130d92a56095b485c662be692644733 +], +[ +0x2e1681bc7c22d24c433f81dd3a326fd0242bfc7e2bdeb6307e4d2aca32adda1d, +0x22415ca10b65c83a039f1a749e649fbda0cfe2fe3403477a40c10689ad5af158, +0x21c92d239c137b9a280a728acbd058a8c75f321e0d254c346aef2b0f3390b07e, +0x41fc409e13a628d9632b87385d24bf4f2a712e3642a36c9875cbb5e90028065, +0x6850ae560ad9a7e89bf454f4300cac5f5184453afe49fd3552e63e44e72ac55, +0x291f4b78708af2e6d2021bc67b8b43177e7c0533ae1d89287612d85cbd16a4a3, +0x22aba2a6f80e91b2b4912240c72983f027a4c158910c03cc1cff66c545f8750c, +0x22e33116da2228316bf3d68b2f1506bb5b5b87ed556aafe4f1c1638f723b0a5d, +0x27885fcd66e6a1bda1f55599328bda53f0dbbf8fe39d8e025fd500e44ffdcee2, +0x28dfb66df089941c1b64c42f01e015b5f3bf8764452add9b24f4065b7d276244, +0x2e5ffb493cfee9eeaae1200f360829d0c2c09ddb592d37d0821363aff6ece299, +0x21157a29f47613a80bdfc774d1c8278abc3f76e15937ce9b24176e1b4c9e3b7e, +0x1cc9014506211730afa1e9e45c9f38b6e6218ec646e79dfd38ae0cb8d96ccffc, +0x210396c1be722404813dca0f052e321e183c00dd1671044b18bdf1560b04ed6f +], +[ +0x65850d11d0eca87c3697b6f5e57f78ca86952bad1c9047dbd2eb6be9e9db30, +0x854fec1c464e2fbad9ed6737f451f4ea27b6a1d97349941928b5911b5b7e3b9, +0x2c240af2cced1a6d0d5aeddc36c875d3a8e74325772748ce1cbd5e01801b188f, +0x804921684796339f40259855eb51f118262da54c1ead0364ed73b7b6f328dce, +0xfea56a59a68a9d3131f96672be04f078937cfae01bb185c074be5f74a37b226, +0x11f61a3860411316eee42dfb735b05e0ab5a905a2478b9d446acd0fb1403d00d, +0xa80fee34581fae3188ac5f2c5aac9493e6db12ee7a2782a036aa65ed89f3825, +0x75c8623c44462e495ac4b62536c790a89875e9fb559e29fb51c32d6601ef297, +0xd4ee74163fe389031e01f793b3cd7f76971649372ef075dd3f2596333c5a6f8, +0x2a06bde137eb0fec584cfe2f11c2ca43be25ba8dc31e0522191cbb63ffc50b6d, +0x237277467500a6589f208fe577a0ed6bbd805f5bb1fc0543a22f21cb98b46108, +0xe20cd93d855c7f14979bcdb315d2f9891e09e4099cab4f82b66481d013eac94, +0x12dfaf2a058c0890bca0bc89b72eb4a575f10b43a009c6ae22207149884b4638, +0x299298324b7b1e7cfb05fa7c62c2c471b5a8dcb233f8c9e1becf67d8bdcb4416 +], +[ +0x1a59b36b94f9d723577e504d600c493f2810f0e67112672c743abbb13abf43b8, +0x258e09e408d6f662f3539a649aa156f18cb46302fd0fe34f007b731db06825ac, +0x2049f9cf12d0e210a7d82a56694e58c76d2f1c5ac572aaf9b6fb770c09f8dfae, +0x2d4687de2ad43600f6852c2a191cf74d0c3e4a7ca0506f974610833fa201a72b, +0x2803e055305e45f9ba2d154206439c02a37e8a5c3fa8eb38d883c75137d96216, +0x7ec1b96a04d4eb1f0728f1fa0493019c6f1a95456997ba5003bc2bfdcf43ba0, +0x1dece2bd9b515875c114246d055fbd55492a7d26aa8022227192600fb17c8c82, +0xa1973619cf434b77422536477683d092d710c68a3644946e11dfc5daf4c3e35, +0x1e4a2c836090a5c960931f020bd616629e93cb093ee02285f8b9d850a74f8b57, +0x2a12cbb75facd8548f0d464d85c961acb166b73aeb3422edcd1c3c0400824673, +0x2ba25258891906648372370673f8b9701a7a17f5159c26f83acd03dbddecb683, +0x19e70fe4bddddbd1a2010dd7f35ad802004b8486a6a1296b75fe87c2c5246908, +0x27d1991b6be57840c86c76792fd9c3b44cc9bc56569d8f5d78012c17c9d01b20, +0x26a6b81d5d4c3e4df5e93aeb39266b56a536c153210b9f4dec10ece36e3f9e +], +[ +0x1a4b186b77cd53f961c8ccb7815d9781cef7a52af64d0bf746cb522512d3d0af, +0x8b39f702949a0a1a5906339e83e663519b264c3039aba4688bf2e3788b3ecb6, +0x152877c59e07350aa9f0b36db00c436234c76249dd0099607b03567b4e7f056f, +0x1156a55febc770d3e72337b4db1bd2fd680594a9c9dad08777aa5d898510e5c, +0x1e2cdbd10cd7e2993c0a41fb073400ff938f590e30b3db6855f12c129d681f12, +0x4f089c87cb7babaf031a4d0d0f5c08e00bfc99cc7befcdb22e55256170cfea5, +0x2ebc3e6c61ae6901d3047afb5095d5f86071a28026a7351945d6fc4626c2f1f9, +0x230959791080b2d262131ee7b43c2de9422a9b3a59ee1241e762ff0da380856c, +0x10bf2e728bec374033c31e16bab6772056a1ace43bb4c3333a086256e0ed9d8e, +0xcf6a0317dc98ba7fbcb0dcef53d804271bb932225cf3c2fb8c0564b898c13b, +0x1306e43717156fb4e21ac64165dc5fd04b3f5dcbf52314fc0c84d09ba5b6578f, +0x9a6e0063c05651d63e8365f4e17415f0ab59d07df4916e9f3c6f649c4f10250, +0x211a3b4e93de320852f06668c192079c3d65a00de2a7cfab966ce0fbf9322ec0, +0x63781e7bb64e40ef54a4ac17d47785b8fae5da0c4b3bdfe4de8edbda7029bef +] +], + [ + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x1578623ddfe303311ac327a432aee9ac8552cf37d7be9b4323c9a792c5776c4, + 0x17536451518c265209c2d9d8512a80f5abe4df372bd9aeb5eebc2b799fb1d978, + 0x1025b7c8b5b38ccd6fff7dbea3215f6a1cc80c64973d8972c0bc7674c733a157, + 0x1a7c14617cefb39cde217f3c2583bf35d538750ca9818e2f04268322c282012e, + 0x27993e8fd8e80385b78a6214675405361deecbf2c86441634eafb7c99fcdda8d, + 0xeb7c2b5ac700501da181caaa6d42837f6f51713924eb3e5d6543801ee3c974d, + 0x22313b179534e4b6af14a56f8eec32f02c41988093cc7f4fefb281956250b170, + 0x277988ddf7fa2eccfb2560b2b169e12a48dd0b3707ba3cf1c0a514c4852ca68, + 0x2aff90506172c4300c94d20c37a877bdd98630c899aaa00bc83f1b7d99e6c943, + 0xad7537b0825edcd460d01970323bf5f0c336d57b4ec04b155e361068216f859, + 0x16573e4361e87edabb67f04a10a84b8655a796aadaf0ace71d282a03ef73369e, + 0x7befd625351a2e970860afe5ef0eab07dc7dd518eb6145de77252bc4769a4b4, + 0x250d2c639105c9c5a3ce4b6df01973cc41819fb85be886084076f4114fa0e654, + 0xcd782c85933dd07ae0f3f6b0e3c440acbfd915c2fd7da79cab1cfa57f634f4c, + 0x23b6198a0c85767848c17cbe8708eb23bf53938a60a99576e4c2a7caca25d18a, + 0x1f7e50e68a089b2286a3ab4c8764b2cb8d0da8b26b85c0f3a468c781f7cc114, + 0x258ebf40c08515d8976fb6d05da5f7a43455448d998e8682aa49acf25a307d24, + 0xde67b3b49cb60cf0f2074e36325065707c58c2fed40ac7a1e2856a8fcc3211c, + 0x178c746273a2650cb608c7abed3bab595e8c1403a7d01f8a8d1cb4197e3e96d5, + 0x2ab3c9a0a6988f6fe5e3739e7ab333de77084e6177b0778931f004083f807de6, + 0x2d86755d3a375e8b14ef5aae6e2eeb5105e7ec1607de4d61258de2617f790ea, + 0x196725d332dc50d6d916a1a6347fd70973f461d2a1fc2b941ab891aa04b3f5e6, + 0x132d62cf82833c79ff5136eb2e396d5719f76ec0c556565b5a7869234afda829, + 0xae37c618053667860b08f31cd97e4e266191da715708bb84444741d9eb591e, + 0x604994f682990576a6e1c907633bcae2b29d2b91ef8af1911b41fd3fd168, + 0x182aa4ce666d170a3aa6bb17e7ec00bd00dcbfebd02f3fa500e8a01d6b094a49, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x10f8dbfade79085f2d9cc0a15334272898e50848407cf0d1b6866cde260a043a, + 0x1953bff54ebfac7d02d5cb8e079d56c84eed51d6f341dea31c6eeabf1a65967, + 0x1344c0e662baa299ac79300aef7ef1387b1926b0c323ea279be046775a8ead2d, + 0x2f027dae71476ebb6b5f3b1630f9a92126bb31a72e50cfbbe9e19ba8942feda4, + 0x2b5570a23123c5568920deaa8d1f8882ecc0404bf73bec01f67562b600568862, + 0x2485dc5ae845e8acc0c38c7ac313607479e4ceeb25f35ebcecab10d829fba247, + 0x25b7907ad098b9a7ec9773bdef17a1d315baccf502a2a303ae9292fcf24cf86e, + 0x25bb66388a0f8630d499fd04740c16ae3f6f8481b2f9637a370e921489558902, + 0x2a00221d8edc58656999ae7406d58758e795a9741c004d3b99e0624d1ed9651f, + 0x41ea47bbe1f576a1bf165e9eb6c82b74cacc22011c02d1295aa68a734108477, + 0x2fa5eca22a4bfc0739f0671dadb74de19a49bcdbc6b23b3e4acd659b3ab7e2ad, + 0x1a103aceb4a30c1289f86ee6d359ee808a1075dbaa86a9b590da829f89e0e56a, + 0xea6e1b215fdc970b74cf8f31e3e78129cfad0e545939cb6ea55b4e72f348838, + 0x1017db78c2c1d169597ed69a3dcd02467e30071dd418eb6e9db209805314814a, + 0x22002c2422ecc59939f303b6e3d02d35aafd288b4f7936838314e2047b669672, + 0x7c83bfe3e0cd2efa62ff8cdf694ccf8b3268c2356be960335b45c9d57751940, + 0x256b5d75847a3cfd5c4a79c7890ff08c58b73a31f14bd07247241b70e3b892d4, + 0xaa8d8fe4f42d5ec00f582f56d0d64aad9977a43b185d66000c139614d9ea30c, + 0x221dd9b914aee821ea23c359b337345a22da01eef81613e55c97fe275b42c4b7, + 0x7a71841bdf7ee0dcf51ae4195cc8adf79be1563616fa5f6b5d932eab3cf4d9e, + 0x3f7813649d46bcc7419f8ef37cf29e9b486e285da3045d96b5e3c6b636643f, + 0x2e4b8a3c581c527e8a12b4778ff69d8405b2dbef389d6bc8ed143f72cf2e3b89, + 0x17c1a87f4f960d913f5eea140959526f4c8ed7a7fbc2744fe37ed332e26bfabb, + 0x2c46585ae9f6cb77c3217988da69423b71724cff7fbd8cd879a0c4479af148bb, + 0x2d54300c647a770fdc4340e7422d79b643596ee6ac6f7e1b3b6339022a1768fb, + 0x1bfe46241f2211c6ed0e7723765850aa6da18b5d6c692d33eea7647a73d097f2, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0xe2cbddf65c2ae0452e3eb2578ac21a1e5279c42481e4a41affbad2969721705, + 0x16ac1278c3b044618e61a767b13dee22fe364509ef89845b2fad1a47c2b9b5ad, + 0x224149478db068fb7141fdf2746d34283ea9e42313f8bfa3e9dca597a23ffd95, + 0x1a8f0b2c1be34d3d04ea78b2c38118f6e05ec781ab95c964e9fec00e9da70f45, + 0x9ac6d36b9a63d40259a98a78c9a223de633299b75cd49a944ef361e6f9fb9d7, + 0x12810af0ee251f24fb86894b758bc4e0db0db4522260a9bd5406baae536b23e, + 0x13e21a7cb8f49dfb990df144ce9b950ace2762a38331d90bfd5121a7d8cbeaf6, + 0xbf46bbc35ce9bab54a45c3b9a308df40b6b771b3a0c82634e86f0e8369aa2e6, + 0x2d3905ba22fd54bb55e4ca78722d0c3c6d922ebee33c024e3b530414b0e27819, + 0x21e94a20b029bd68674fbe1179ca813dfe61b3ac9a2cbec68fc63f4625ddf20d, + 0x2eda11aa8cf8a13cc36a5ee865c465bc8a7b91e41061abe33ba2a48945be03b2, + 0x1e86878d1a99e02c9108ca361563f8120dd46552dee8cd864599bd965905acfd, + 0x213f9fb0da20d21d4bd549eb2cd60f2e951cdf11bbaed2e8347637c28e90dccd, + 0x9ec04662663c012175d047b3badb9cefdd56abd0e1bb8824f8b1af84c81cea2, + 0x2cf6e22ebf6b69c9dcfb9b5e66d03f2c9dead8b168be2671fa0c900dc0349c62, + 0x1cb3909eae030fd0ae2a623232e8daf5a527642386e6a1a5cf8cbf36e49c9f41, + 0x2a954bb1d6463b7b6723ea7a79b331b5201cff98ebdf77311f8eaab7a4bac880, + 0x1d232685a73dc553d0e1b8099acd8936bddf42a40813d52edb2ba0e2a72a3853, + 0x252d7955742982802013cedab484c8d461f9315fd6c30a13a076ee1fd84ac652, + 0x2144739dc6440cf4f08908cadc61413b30e9fdea3d600ff64f05c5afe2742a52, + 0x26d2ef597c02295f490a26be40bf56c9505e4a977f017b0ee1b4539bab40f92b, + 0x2effc6807ad79b837e532bf4a9f65a83f920df891e563011c34c585b8b5118ff, + 0x2e095a7e1c68ccf1cebbfd1d9e6b10661fb3cef485f2ecc8dedeb107be1a99d2, + 0x226f0b52596d08e12c5d979f74cd74461c37b9ca4b74c2d3d72a467f682f67a1, + 0x27e4dc61b7f4c719754040db80c2c2103197f34a54a5de92fde3460eccf92b38, + 0x2a0121e238a13d0dfb1507f0ca6c1686f838aac334cc1ecb2f7d1ffb7b89c130, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x33c6d4d77acdece9099b3b1c2820a64c2f753582562ace2cc24fb4bf2099d13, + 0x8158a4f4a451c60b9c190787757dc064f45712636cf0171e54775a94bdf1954, + 0x1d18e0af711abc6617c0385617d21b4c1896f0199ba927f33692b3c1171294cf, + 0xc8ff9debc6b5b90f826623c99e25cc8ba5b83f810b1c2be42298e445cd1e516, + 0x7455ff7474bf2511d200716e916cb97e0842864cb89a42fdb87a479a63f5055, + 0x2b796bc4350006ffb852f826d4261ff6fc792aebc1cd37f273e652180dcdd65d, + 0x2231f46d69ae4d0ae2429ba6080b7fe51f3f934c3d6607aea12139450e394dd1, + 0x2e37b2806360065a4e80fa3e6f3acf0cc90fbfee5e8e29fe20367345f8979dc5, + 0x1e52b1dad965f7d359b8dec0592575d918b48baf65dc217a442db727e46ff8b9, + 0x266f2edefdeedb61c866a0ea64d019f31d1ddeff9607667a5e89412393765810, + 0x622b99a4f10e3ea4c1a9f0a2c0823602a1f37fcf2d70b6e729f8a50751dde06, + 0x20b6fa4bb93ba74bb91a9680f4dc15e2436baaa16cbd85173881a89d2d39bf07, + 0x1edf9a959b552bfa30461615955d8bd5ab7a2d826fb2b440d363029b7d8a16c6, + 0x2352faffb1f4d71dcc7870bade6df391c49d4046451de035837feed53448ef50, + 0xbb1c8476707800ecb7b2cf40d86e6a7d5aed4214b9d535b21a0292790294b29, + 0x1a004861dbc666a632c6ef9fca6214a36256e7b0ca97cee63d02d5740f7f72fa, + 0x115cc0fb69c30646288e34277bb9d59f5cffd364b3a48dc5df13936780e452cf, + 0x20b9d6ea816b25eef2eae178eb85edf16d922e259758611f8ca73a8560e5f612, + 0x1b7650b9721a1589244d0bb8910acba3020e5a849738c729261d229252d7570d, + 0x228969388482a46d9d2c33e3cee3f07ce2c8d2438e0023a20c7d5e7c1c84bdfb, + 0x1a1c5996f580dd93a0d48654c03d9fbd053a6d4a64b21d4487b7d16d586b9575, + 0x25c69df2d6d1a1203df21d682d24907f08c34b941f5351caa2b3c26efff3d1cc, + 0x12848ecece4c7385b709ff7c98962c528865e86bbb652a874c495e5931986f75, + 0x76bd3756046b7989e8aa9115b57abc352f470b3e8e981200cf37548edcc00fd, + 0x2884069a9ac9139181cef297a585728448ac6a74a26a6fe56bf9ef62d13ec6a3, + 0x7feff811d5e99b474c5fa155004bea6a6fcdf03a681acfef2e25ad334f71e5c, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x1d20333ffc3cf745d561f12c425d8e1148000b7d042aeb5f26c5dc223fe31865, + 0x28abbec7c9caa428c519415063a6f2d5e1a0d349e3061f05c40ef35803686d42, + 0x3a8e10fe7fabee8686830b8234275a3abf3cf888d9ac500bfc643c47d476c3a, + 0x18c2e2dc3d8b832d050468b7a71e26bc0d6e887165176ed06c07fbecd3d15a5c, + 0xd50f1334b2bcbc0cdb0117a17c5542080751590a269f4530441ee1a428cf53d, + 0x13806f8807551b28f4a063f853d51c621cf08b2f67259b03c7b1b10734945688, + 0x2b08fe6c94ebbbcaa380b0dd6bf50430c5bead290a5cefef3e75aeaeaf7b63fd, + 0x20196101b753985b8d81c33fed2d02bfc0594ed7b25aec355a1efdee746c5633, + 0x3745c143e9794534ba8e09393a84d537e45a0d9f4777e77fbc14d22daa2f067, + 0x23e0047f3bcd71895bdb2030e2656ed5ba74f2340b2cc87626a6739b65b69299, + 0x2b7432db324f5d63ee6df8a327ad7d03752feaea63b8483523e1b1ac50af5356, + 0x3230e5463fa892ae37f38ff6bffcfdb09a881baeb117cd45199c5f78498334e, + 0x6d227987110bba2e393ccee1a5d01fb046f88e9e82c975d69c25505fbe2f7e0, + 0x2137c2037b936b9af605dda34fe4424a2f095aa784956c7e1a8410602381d2e, + 0x1b85811f361794bfad1d365f9278b8ecccae2e29f16e81a4e81f8a76980b06df, + 0x18ce9e29cabc3a88ae1032aa09a664a307f07c41d0d495fd88f4729fa471d83b, + 0x16117eb08d088c3146a297600420e21723b75d24767e3e927a465ce543a442e9, + 0x143137a07224a1f3df382f66ed1eaa0000006ace56412ba51954dcecd725f03e, + 0x104d16d80f93f2955a067d5b615b3169cffa4c95c7bd28c57df7a098608b52cb, + 0x1d486d6cc1ce7b6f2b3aadc680d663e9afed57c6df3948a99edfd8d21f3283e8, + 0x26b9676c3f4be27618037e6b8681c624cc2badc95e3dcc2858f44e4227b90ec5, + 0x1b9d6e78b161f530bc835a17a56ce26bb302ca73846a159744389cba664d9309, + 0x133c6470bb5a345bbb1e3a3650b9a5f39295bcfb97ce888cb775b07188be130e, + 0x2eb4042daaad9726c71a3b6be579dee9df64b6aca59cbcdd4e014ddaf860cc82, + 0x2b7e6bf97ec1a114b17e6bc4b4808ddff15614a70e43318f7840ed715603338f, + 0xa1125917e9750fdb258e4113f2e3beff8cd77b2e4840d2a0a3efae84324f1fd, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x28f2406d5b2006a8163fa449cab775337ec435075e08f76dcb360575f1d0f9a8, + 0x2833ed76d81d99573f405e2418760ecbfad333f71b35f293fb3fb2550d32fd32, + 0x1329680ba1700fd38f42d6f88a166d7128ee68baed48025f1bd8273c6d13d5b9, + 0x2e406c465948d552b82b4d0443d9b4393e9d034c1eb96779b25554850f8d582c, + 0x16870864c7481c37732c1226601c0fd0912ecaec9c4986893da2ecf1e7e9bea5, + 0x16f0206a256a1eaf579b789362d74a6df9b4e8f4c3bc43a69d5d84f8e2b86e1b, + 0xd3769821a46417d7c41de7fd8a44cf0e6b03851b33d35f9105b91fd045f4364, + 0x208072d81c7b1e0c7fb8bcf2e372a3a6142d3643084a78bfad3232dbc4d0421b, + 0x1b00364bfd8258bc091a61caf85bdb512a8319ce47c9dce782e62103c2c7a71a, + 0x39d9478f244268c4803f9dd0dd5e63217be3c8118476c3c36c463acecc573cd, + 0x1702787253c770367113ca024f835dbae15b5c16bcb2121cf3d89bf60993d771, + 0xd424c24ab70fe46dc0b70ac44f1560b98a7c179b6fd59f87b51cb1580404f3b, + 0xc8eec67747155b02438d197c9d55437492eae235c05e385f5aff238ecbff493, + 0x19318a85cac2967adc34c434ced1261abf43e1bf1184a43a0897436121191ff7, + 0x100d0e39b0ac4162d13e523a8308b3d1185ff1abc0a44f80aab198f4d4af2e77, + 0x1dc9edb515bd622a09d6f164eaaf2cb987aca23e7a0a79c8e00d02ab44c71cdf, + 0x2cb0a4d99188559afba7226f3a7dc66b1293a6d5dd7ebf396ac96d3bb1b0dc69, + 0x457e9defe2b2e3ace40217181c5cf8a361c3303bae8d1b867e62386ee0aec8d, + 0x27cb603ef3700431472d85ceaca537bcaa301d220e8cd68c8db9b2e1f53e99d2, + 0x2a0f737481bfdbd65f8fa4cb4463e56a31bec6e77c94e27216f4d5aa734df9ed, + 0x88e30685326b92f6007d6efa42d8af737bdf42ec7e1c4d565318181d8295ea0, + 0x185dee7ffc1c09332fc1436f1c6d67eb3c6dccb36bb98177de5f2802302c68a8, + 0x1a3c2ca9dcba78005a28af3b621e50155295f14ac746057dcce986f6368d3d98, + 0x2c899f8d46c18eea46b9b431d69f5449bf5c896b07343a5199e587c748443f7e, + 0x12b7b81c78c7112c7f79de2eba33f1859e77ee9bfe54d5f3ee15bbae2d6b90aa, + 0xa9c41fcacf18941604fb129682761803f162c0e7cc1152f70bb76a28995aee8, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x18c2c80c193bf893f8e24328bb79195e1cb8ec5c30fa4d0aeb228c820e7edc8, + 0x840212cc8df69cdec9a5d73b33f77e6630cd08a0462709391407c8857b09be1, + 0x23a2a69b4c1f2a9d5da9bbc185ddfc88facc9958428e06fba83d67a6bb7cca8e, + 0x2990a00237ce280ba705df85715600a7d425d4ebe2b13ed3b42b1b44ae48fe01, + 0x268d4b3af37b5f5ec11836ac54c1ced9c569390d0463c316c2caaf71ff452c50, + 0x151286c34d2d1a88fc9f696e6c762e833309a6710e03831212d317296b1c211c, + 0x5a0f37b771fcb8d26bea09722510af9bf510ae84c5f0106d3824aa274e80f4c, + 0x2186448573dabfd800c596cf64703bb0bb45ef5b8a91fa21009862ae3aae0c0, + 0x27ac5eed415340d9907c6b414708cde2b99de1a550be1c26d6ef95c6ed5fb9ac, + 0x118baf60eb743773cde629142c30f86d49d633c5879f1977aeb8496971b3b956, + 0x2206f4af9dc21a5e94a00775629d9eb46a104ecaf0d2188122187fbd9c5f666e, + 0x1874fa5cd6fedd8dce56a38552b35512bbbc6ca56a4bc6410406ad149bd30589, + 0xf22dcdbfea00f4bc89dbfeac7b3dee60b16ee9a74f13588f5879ba714c827aa, + 0xedf94bf49c040df972e27701e16229766d84197b29f023406564e32cfd8358b, + 0x2d24ceb96532b06e751d109a7efcd29ba741e61e3472bece30c7128c47042813, + 0x26fb8b8eb2d90ed4886b9982bd3255b9df4690f84047ccd4bdf21810720bda44, + 0x1952641fff4b577803eac12d290acc39f4728e3fc086f3f76313fb2b78da5b20, + 0x2233ba51923c10394d1ef8718a6e82d84d9054de8c8498bd05d52787faa25e32, + 0x10550f7d00d83f1e7fb7e1c9772f545e32e0a60ca3ba0ae168c750147df29eec, + 0x7e5e890c3e62c5109e3790d2bd1406f8425883abfdde19cbba3b5aa7b7f2bfe, + 0xd611acfe2f91f645a07af0ed66ea813d7395b09b4e4b3cb92afc27a31e7cfb6, + 0x1fc4f96fd7c7a69fee8092b6d11c7bada79e851324da48e658a166d00e66820c, + 0x10b23d2c5bd7e976228e19064ff33921faa59f2eb4c8652d39546479d26ecb7a, + 0x2f21166be2ed1b2da47425d6bbf4ea1f2c5aac82b83265913f6ea70a3321cdf0, + 0x2ab0952fb29bbeb0d5728f07aa4d67431c1d3c348a0f1db6126e47cbefdde394, + 0x2a10c76f857e47245d3c145ce70c87a1995448579647698c122d3c7f8087639b, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0xe8bed4d86934cc84383480e2301331becf2a8756e9098c8a5541d39b3be2084, + 0xbdb68bb05cbd1a32bea32b8daee97ede7a999c31e66621b4ecc57e806e9b68b, + 0x1c68215101419d83d15a0260a0d19456d8a4d552edcef12b8eb3c8d0fce018b6, + 0x14c45f6a32e995585ac81545545d2803fdd9cd0fa462a89f2cc8d2f2869289fe, + 0x3c63147df05188262fe56d1991f872b8069a6c07b7358d166003ab422a2bf67, + 0x27b093996711ee7e4d1d6566008eb46b53bc45925a385ba64c4b314e68f5f939, + 0x1a67fc8776cf402c94587340f50ff6a0037570c50f24daf71d3b14f12c37515a, + 0x368384bc98a519dd78434f63f92be511aa6ebe497a0f202c40dad53cc9ac41d, + 0x1cb8fa7ce16b44e38432742589d4857c290e41ddecf1c04d19475381588dbe15, + 0x23597b850f364b4569de68f1ac728565dc30fa8ca25fbc7cb04de5d7c4b97c62, + 0xdd8ff19d5e1308fe4266a519030fcbe2a9dad492bf87320fee1b56378548b74, + 0x20feb7de1a5e96b834f33f0cfd2be704639c024c4d40b2e130272ee52abd43b1, + 0x20885682bab854ad9b308b29e93bcd9744b30a32a86b43656eb9eb398958c569, + 0x19d3a25bcaa553994b945b1966f0e88877b49a0eba7cfb7436425ac980d1f4b1, + 0x2ac8cfd84802b67174c30e48b6b805af5ae5c0e308beb82cf3734fab1cebda79, + 0xe7309eb986b717f72684842ee44266078aa935820e854ecc26e86b304a3aaf8, + 0x2bf7eab7ccb382e902533c265b264ffa63278fa298fd28467cd075a7e3bc332e, + 0x83dd2953c55d5c2b9f2835c418fabe9f31d712601bb68964101149a09100404, + 0x714ed30fb5590de5189a271e1a8c643e52ab0e5f138671efefe328d85eee14b, + 0x21148f9fd3b0722bd321a3f3fb59dfb18dec828c71a820e50e2dc0b77ba06c28, + 0x2232e4d97bfb4af6fa023ed73bdf899e040c85e086ec61f64d9e76bc8aefda1e, + 0x2f130c81592d14daa4a108219e2381a3c3d43f9a7fd9407eac791568a7290d97, + 0x1bc3006aeca257aa1e0a79238a6aeca17b61c6dd8c5e38ff259cecc70c6d957b, + 0x1e2cd754d9765e6bf4ee604c3027dd1553e6bc4c96f0a1860de5ec1ed4e7789d, + 0x1b03008489762f18d350e6f59491be94b91125f6d564810b226020fbf1266feb, + 0x4139587c94008d2ae2862f17f4623e00a60f095650f0f954d33e2b3e028c8a3, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x2e92d0d003478aad469bcb62a9ca4fc6a4b8b7b54aa20082421047b49526bc1b, + 0x2fa9f127e186da4adc277ed2d0fe8ecf65d7686171b3dd9b5ba57a41d94be782, + 0x16b524b227c91d14ae22fece795ab7b4e0672f93bc0be11a4bfdedba618ec632, + 0x1bae132d3cb67233efb7501a87ef7d5304d43d84795422a5980fef6deb8d9e0f, + 0xd64e85826004f524fa9633ff3dbd2acfe2147df88df435e71935e5184c0b5df, + 0x7a8991e9213182f06e7f27126e583ff1002b732d48fe69898c3dd1854468c4, + 0x78a71ff06f3a7037e3acea1df2f04e326774ddb20d6717052065d5b48e4d9c6, + 0x2bdbcc0653dff0b864ba7c35a2053688b9a13ccf83fc78b5857a91183c634ba0, + 0x135c4770b984ca724061061017f6fac63ce3fd5f42e3271af748221eafa486dc, + 0xbe4b3d77e216a0284da484fa0ec171130980d6648a10e81494264284df500af, + 0x1d33a1eac83aa2e8e33f90bf9ac51bdaa186d7714de7cee4357b5768bdaa03cf, + 0xc80a19a319c0095d10de1473bde0636e199b13b8d838336a0133f86e9fd280c, + 0x1fb00a5d5448228839fca9b108ddf4cbeee2e5c6a7cb8d6bbbb33daf72e5dff0, + 0x3428c5cf5139a60a19d3faabaf6d8571c01242000e216e3e417d37476da91cf, + 0x15313c7636e93c90281b5946d1223bb25d849c6b05a9c6e58e3459d4058b424c, + 0xbe94e5c44e86577fbf39b9db0d3ab08a8e90a14881360a3be8e77b1465d6a08, + 0x215f4fc3b36e8ef41ea226080fa331489bb1f5d5b2e9924b5f419a2900390614, + 0x16b0162d774c50882a9f2739bdb279317918d0f75e2fa75bf24e9ec3f1a21102, + 0x12c30feb12fc441d6dd5059c269074f10a69decc148bd2283dfbe594d2a538a, + 0x1649c52ddf7788ecb2150a1a48aad096b4dcda9f517ab877a11927cc3eb7fe9b, + 0x6edf4bba85eb1927ffaa307aa9385c0e11eff4ba249a8e605d624f35af6f9db, + 0xf61ad25f3641eacf1ca4fcee3830d5222f357f046c474ebdb732e0211e49e40, + 0x2adcc2f96c95a40d796e0c8bddf303d75badc37ac9aa6cd3173b868f6d177dea, + 0xa50edd8bd899b1d15dac22136bd3a3ce00ad0d581188aa6c2db96ff696613ba, + 0x26a9ed9b96681106cac0e7706f4293fe79d078d918f25f07a9243b912f5d5238, + 0x19595ba4019162353cf21250cafa1aa64a7c0597c0d0af5b1de0a18131520439, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x969363ad2fc56dedd932a66bf1193a1b96276f16e423f78cfd790850bf93477, + 0xf364b0a5a1b00f7192697f5ca0960680b217e3fee2ccd320cd408fdca0fa7fb, + 0x100fe28b46e80f15e12ef4d5759fddd560f76bf74cee6051f23ab10c8803f474, + 0x2dd0aad73d277f8bc1c76d2133bd8c8a8ba8bbd573bdfc1adce1380345bf233d, + 0x1ca5603c3bd89198d450960c8bef433ae368efe4be568d1f8f63418bc67ba269, + 0x1eb4203b299398722feb50f86e2131f870ab2fee6f726876b9a213a69c8b34c5, + 0x20d3eac3a69ed9d9963de0a1d4b554ce0b5e350033c7aab8742fd258af31392c, + 0x38ba0b5c2b7c3d41293047fb42ed9df347056965c4d73994fd38e0b3d0c3c74, + 0x226c68b53ad316f22f8aa803a90ffb02c489364fcb807ab2a6dae085a2c548e4, + 0x1159ad22fb4656dab10da606d298a856831454bfb237a222fa393a997dada332, + 0x22d898f074eadbe133b38174e7629a3fa47f8c92e8e67f62130a00fa7502b956, + 0xe118395fc451a7aa4612da12097c4372c92f7b978f5af092a4771e09a13343c, + 0x5b91237560989a738bbcf80a2175422656dd27e0f5f96741d141fd19392e462, + 0x1bb3f133c2d5f7930a9decd0caf63f17c5528844db26efc336e5101f1868545c, + 0xa39ee8089241c5cbd69954994abee040ccf43b9510d54a05056194912963bfe, + 0x11d1a72d9666be10fe5fef74e6e06431532f5157ee24ada70683b9f0a586b585, + 0x2a0872f23949f213b46b463ad828919ebe034950429f91fa3bffb275d722b47c, + 0x1da2741d74cfe7a159666231eb9981749a40bde5cea6f1a069dea57cf460ed45, + 0x225046f36d161704c26a8c378e2fa58859a2808f94d5242cdc3c742c530f60be, + 0x2ac5e790d78a3b19e40fb98b247ed9caf78b47d884da4bbd70359482c2f4ac84, + 0x2a9febeb411787c59c6b8e51108aef6d9dc63aa97cb314907602d5f6b702175b, + 0x10519bf4b5d77f8397a4e51ad3dedf5b0dee2b25e08cb5b866eeb2a891e0a6b2, + 0x21e9add284054cb149e67ec3fc4208b9e0f8a8c2011ab17bfb3c4e4419ee700f, + 0x861419b33d1a9e2a944bd86a22a03490fc560a6e3f3922410b1f4ceadbf2fce, + 0x204bee088f716345187c1c25fcfad33eef88a8be606b0441139f03be3d39de21, + 0x21a8509dc07b690f149ace959540eee40d485db5a21e3a2ce9dbe808f621c92f, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x2bcc9e799065b89040280d6bfa90d9b0f98ac91d5051d683c4dc19c6d078592e, + 0x2a2af9ccc8cd9b8976ec203de687836e6025e0197a9e756a094168da234c6255, + 0x22cda8a2057a524f13ec0bfd8cf44482691536cecc3218c934ca7f21126903d4, + 0x195abafa1531518d101c427496305c52e3d2c9e5f7192207f23985a15a85b384, + 0x226c92973e2bf06e8800bce486d3b5c5b086e9717d93b79e4084a9a3cbf41dc8, + 0x2d4b19bdffed4790eba5957e4545ccc65ffdc300d945b11fead52f83825cbbd7, + 0x20c83290d5ef608ecbd330a998cde98936060e1fb520652c9d6eb1a57558f91a, + 0x2baadcb57bf46a22bf299c393d1537bf2d612cfdc70413af5e5d8261f87dd73b, + 0xf09875c2570527eb866d31f96e357946cf01307d89962db0c6f16a02097d08d, + 0x2a29246703689c0d7c52136c2b548245b34bd6b6c341ed99c340e114b856e0fc, + 0x2f05d7232622eba1583bf831f6a810ea116f0fd933e142650c58d6af1bcb66c3, + 0x1afe5d1e1b64e7741039d6c26a054b7300ecb7d052d89e8df8ce8f1fdb5289e7, + 0x1925f2484e57a2cf13139ddeddfdc2b9235640c4e40e7332d1d632c724801f88, + 0x7752556340dcd48531bcb144583ec742cf7539c9ac2347363f9636ea060f39e, + 0x43c28a9d6f38ca50f057fa71bb6f07c62295fca2197e056160e93a6c82fc15a, + 0x417aaa17f575f42328eaa4ba22be7207ffe9d26564b42a24b41967f3e3173bd, + 0xe6da876303fbed7ee756fd87a8f3e1636325532adf26bff8910198c92e0caf5, + 0x27fa572643a35732cda21571d390600f9188739764febb8ddaf9c01bca807ff5, + 0x1a510cee95e7b6f4efdba5612e8c5121c1ce9cca1a376d8379a1fdc206a55fc8, + 0x14424c4b3e51ffba1869ff6527ce3ae53dc13cc1ea19ccb5c8792ca6be287753, + 0x21a57d8854d6cae5d0818d294fcd9e1a2dc71691a2e3f9b227fc7889cb72182e, + 0x225cb50db0b73b20058ef3f671fdbd2c0877a0defb8392630a01ceefda042d16, + 0x58641892ea470cfc83e363c5b880eb8263212533f8ba6728527c4636f3e0113, + 0x1f4505746ce4f65004b43f9f0017d2602e1bd44ee569e08fdf832d91531cc2a1, + 0x2a076d8186db2528d94fa47dc41721629bcc2fe83eeedfc433c20e8cf4c3efce, + 0x1dec0d6f62e19a1d2ab02d6c4d6a6d7a1dd1387a4a1fb15edc8622e1a3def5, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x2a48253491abad4561b2ca9cd08cc1ce7ae0335240facfa6efb4fc653a48efa4, + 0xcfd514f09e0699217166e20a7eda9b00512b6146af51fc1776dd6980588083a, + 0x1937a11923000d95131baf310078bfeb84b99a77e027e8d0d96201b918132ee9, + 0x303cfb90a228509ecf58fc6e94dcfa0860d206b34b28a8368a3559a57add1cdf, + 0x28930e4b9ec17c58ffa7934c216ab1af55df309d115d0789233f84f2c441a535, + 0x18aabdce0da91d3b644bd5ecaf154ab7148f3c3326cb01b593f8af9efcad0728, + 0x391f2ddcc9bd6fac600eb0c26e0b1a9a27571629e9b00f080d876ee2f1b648, + 0x1d765c20a588ab7217fdda5e01dcccde23dcf9a9cccec4d8f424735f39e25f3b, + 0xd914d807b0fda1cdd76d1955f170ab3616a35ce53516a81e315825f93165905, + 0x22492619b16183d3180c15994c2508c83737ae2a42d968dac85af30392294e7d, + 0x11b3baf3833cd4a6039f2bd42af1633a47f240fb88a7f0ac0902fae2a5be3510, + 0x207c403b77244c8018d8845714e68566216fbfc49acd0107c55ebb88e0de3949, + 0x2c9e431e04871524a5262b21286d04333dedb393a078f2fed92266ac22fefa6a, + 0x1fd093032821a7772421e62b4e3c23a195d27ea4798f9a3f5a6c7d4d2db583e6, + 0x2eaa82b7fd1c061940c2a77bdd2fb653842bf1b0466696b292cd304b490752eb, + 0xf98f710e410dc1552fb69cc85076b89b4fde8f27428a30b58219f52e422d130, + 0x12229b56730ba20a6a52d21bf8f7312696e8cf6537f1f6c50bfdcaaa4ed4a7ed, + 0x1c2fb95b64a0f66b65d9060f1f065bb82ef882af760419aabdc6cd3529431e7d, + 0x2f2fce632964228eef7908478c90107a5dde45af647f2323ad8a612e41c48154, + 0x61849aba4451458f718c3be3f76a38347e512cf422d1f907a82da750dc21478, + 0x2cd60c32d6ee36c374016bd4f1c0b273ff87315f6bfe1dc9a81fa0ecb1264599, + 0xc3e897a8b91c108ad19b152e9842cfb87c4af0aec8dc950e0fa325ed4d69ab, + 0x7a38f888ba67b2150b0e6431ce02408681d2ec80c8daca4c51e65b59d329fff, + 0x1af524a87fddafaad82b5231a1e75e8076c66c44d3b527a259a15422870db619, + 0x1159290a4743365d781e01a0d6bc626832260b07df2d0f288d15c95272eb1f9c, + 0x9e51cd15182d20f87b09cf6966f9268578c3d9cc58b3e7f981f67502f9478e2, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0xb0bceee45e31b08c0548711d59c548f51b7d1a80ccefe6599b5dbad0db4b738, + 0x241c6fed92ae4e391bafe3af5103035f9fc1f727a6dc8ee5f61ba9b1e3eadb9f, + 0x26aefffc4043b22cedde88f2bce76faf6fb3c21b4eda9d682c14dba06fb9e87a, + 0x2673296dd62cd736659080d030b98914f6f799752403ba5c29bf9af6afccc8f1, + 0x22ca97c4de769662b071f7cd75657c15e9cb20d744edd0a7911d78b6a4aaabe8, + 0x188fa74b7eda792dc3660885901c82d57050e74b09a12b5f346d34e1e5f67614, + 0xea0166cc4c51c2252e4f3dc92fcf33a03964a03050f9f125b87a7fe074dfea6, + 0x2134da7fb4f089a21363011b08fb72aaa8fe767c618bdf08d7b87810d5fdb594, + 0x2be62c9234dc7d3db66ac72c758b15628df1cdb781c90d0f2f23de2a29005105, + 0x282ae8812d729f2eff86f2ec478a65707c4b63d33443bf6d8f872569c40e442b, + 0x189e7984fa57098dd737293a19d6f60971ea7c74fec600b4e6fa20cc314f015b, + 0x1e20cd3dbf4a75643421e4fa713f5ceaa35ed0197150182f653ae9663a9e45c3, + 0x23bd66cfdc54f92e0d532ff413a2e2ff3cf6f561a344463e5e0a0a8c5a010304, + 0x42657182ee4b72e3e4408528c19b71ccf1d4f5f38acb0e5a5efd641cdfc6b7f, + 0xa11abc1daf1ff8ed6afb6b0a6370bd55fbbe7507f1da568f39b2ab9dbb6e340, + 0x200edeab8b94daf3135eb6046388ccf8c7140d91873d2fef04b9c60f509c7de7, + 0x58546b9e80b2dc22250fe5c53d66aa14be31d5d92b5c04a05e3525810fc78a8, + 0x1670b9e07e02e88814eb40a43d83bdc010739e9ad6799c10bba24e1f40b8afd1, + 0x1bf39f979c015af4af119c137d5c8a334ed0bd0d7f89626d4f79ef4793b91324, + 0xe19dcdf5b4a1ae01fcb6c6579db3fb615bf176d53e6ad047ccf905861acd584, + 0x28f22053f72ea545761afc9557c84b05c6f736ebe7bfd2c8c5c044d09bbd4d4, + 0x56e7854a96d6bffb29945d76b51fb9e81f5f19ad767171c568b742e926054c9, + 0x2aecacf169f418d8f47472db625ac3bdb5403667c61457666d4238bbf39d6638, + 0x15b04e62d4167a166f14364bed196d1d0e49c8ccde5bd560e261600dda4d3c3f, + 0x15f88c4b31508718af67c6e3c30cf3cf594fbf481a837e80e89156d9c2d1be74, + 0x14e6645c7627e744f9e6140679c863325d1d95e1e4786e573a498b0a790b431, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x1afd97fac1f6e77c5cfe4bce848b93051a26a3b7d3d6b18dda048863a013cce4, + 0xdf68cfb65503007db81044af06d38ce63fda1f569a7057f1848ee4597d87c01, + 0x1086b32477529f9476fa324d6d9552bbab58956c2e2095548dd1bb20e9be078, + 0x1611046b126acf5767561c32d31a36c5070d645bdf08684240a72b9832c3bf2a, + 0x1bf3eb5fbf1e5bbde992521837a8d3a15a187921832989b4d357a1b2ced9b36d, + 0x799a349b10cdde87ae631ad3959d6f9664ce23ee91e010679ddcc6017ef120e, + 0xc55d0ca35aa0d453acbdd8993d05b479e13fce555b634fc6d3e470035b0de8, + 0x20444c1bf67d6ce8afb0a20e79d6b691bac54bcb31ce4182b1579ee21ea9fc8a, + 0x22e8f59cbb4f92639cf517fd119eb650704b00e6eb3f58e92eb31e713c1b91aa, + 0x1b4841aeb035b2e896d64b59b47873cb9c74cd05ba12436e9d1865a4a74e8be7, + 0x133d49d56c7809b942db891b424b30d56ca44ee7f73aa028a5e577e82f509968, + 0x698faf29f83281d3fd421c78ebe694cf5eb371e29a09354741c59f4a4abc6ae, + 0x9cf68b95e1a447226a8c39440513f965a41fff89a1e1618c70ae4be00e92c66, + 0x57a0141a7ba203881e5a90e6d422e6d9001eac737fd9860344191026c5fe545, + 0x1b71aca0b352c5ee4eb06dea7f4202fa1b908f08e2be55dc0834a1a873607597, + 0x142915304bb01cec99a22a96d1af31c3133829bea002ae98d7011fa1516160d2, + 0x4aad51b11363b30a26aef78b4af431dd8bd65dececfcd1a6673d8f96a0e6c16, + 0xb63c18b78503b6a47a88f4d54c4da7a9c23fe346de39a8884224a2a85a9511a, + 0xfe10d1f3c9b406bfb832e85b8a844c5c4dac7398f2dc3ce2541dfa71260d259, + 0x2a42420809746917645806d70631564f61103186f9cc644df5b7b0ee4e6a27d5, + 0x5a66c6f50d393da791e5768de874774d066f0874118f0f417b6a036a657dcb9, + 0x21a4d71862dccb7c0a0a9b80945c5be92307f147f29917684378111cdbe9d2fd, + 0x46f855f83e16426aed3c81f5a2f7f92bec7ceb71e3dc7e2453514c1081ca202, + 0x185eb4c67d4f479827980a96827cdb79988cdf8d31c2f8d2532765f4155cbef7, + 0x2a4294d3919b5debce649b27b63f40e5406b2f044e1d41d58411bc00719d3e7c, + 0x2a802da0e4d59259bbaa7dc3227ea2d725f6cce50332661f0837cfb87af4af94, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x154eb8f04d175057207d617931b51ba18ec3c830e1afa755e8ade5bfa71c1d44, + 0x1c5fbb238cd09b4ad76154a2fadb7e7d732bd534603ff3cbbee8031cdde7b994, + 0x1c3a7fe14c3ef7f03426643cca0e6faad2806f9dee971ba41c0103d42f4f116a, + 0x928a9730b25d647c4563b4a7273307c94c347565eee36c781c3b8adc53973f3, + 0x2aefe39f4fea948261cdbe0accc5c7ccff6714fd741fbdcd6e298249560dd97a, + 0x1feadf4aecbf7c7f1f526d0ab1ae1513f1b4fc8731187f9b65713377c9062037, + 0xcd2f2d4d826d98ce3bf08da02ad5866f34c9b43f2068da4e5b33378d93c4c24, + 0x2e7b56a6409134126d411b560967c46ddf3a46fa47dec457fb82a070bd448b05, + 0x23ee37d1d1e1f8a3b10680bdcabcb89268a4958051e8230d14a0605af857d190, + 0x1a910c02479a6795981001f40273c702cfbdcc1c00fd03de1f8057bf2809873a, + 0x2786abcea27c34cf4ff274769e51787932001c0640033a7c89914f44bca3297f, + 0xb27d402fc69e2f23ef8e60420a38e429da969f038cfceedb073e12f28a5a260, + 0x5c8f462872ea76897742babd1099b0aca77864a1b165eaeb8dcbb3fbfb95286, + 0xd29130c3cd0ab2358ab1683597256a2f7ee611376b9329b8aed30f69505bda1, + 0x167beb74665c1a02b90450914870d4480472b6b2bd22563750afafe3de5fef8f, + 0x2574275c7bc58879004d63dd307638b057eb9bf99388ad4788659f957ef5623, + 0x1bafe22329c00fceba1e48c5f61bdc519b20eb352e183859b2434eba6cbfc4f, + 0x40f25fb048f262d0b88e5a557234c4f35ab898d104cb2eb960905e1e8ba5a80, + 0x2fc7cf259a1474e83243039afef87ae87f1a07bd433405084e3e4241c413aecf, + 0x30144980af35b582d434cab99e08835bb09644dad47fbe036aefd9b19b713ae1, + 0x140f2ab47ba1a08e4ff8c38a8245b79fc20c2916fc3470e4eaeb0b3654b4a6d8, + 0x97cb1acd89b5b12e82e14571e4a4ef516f5c2693f0bf70d4c05cd4efc72dd9f, + 0x30435adf792ba5a8a2c9fb599c91a1de531c7fa809f3fc364761e8e68f3c99de, + 0x17acbbffacec919a115cdc4c303f9335febbb1dad12f0a1825fd41359ef73491, + 0x45ac0782c8edd00c6d7c0eb594b799de598bf538c80f467fb7a4eb1f6b01d85, + 0x1e15d1be8d2281c6f25efc56b33d72bfb59a61bd91518a3de93caf2a357d0256, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x125b96c678d2ef181f7e4bfbb795150eedb5b46a913d6571d1b204790a2c7b0f, + 0x130be605c83bc01c1fa0e64c79ee75b27d4b4efd892368f66959cebd8ef1d79e, + 0x3051c6918396878ef98b13b7c484c6695a093ad607bfdcd87f01b79d420e731d, + 0x2635445a3f66389b4638ebb81a36f4ceb210d5fc5466209ec215c08023aca95f, + 0x10bce0fbd3a8796152759cc25f72601dcd99b699a8c34686e43fd2b6d1b27d89, + 0x17dae8299eebde0062043e9e93267fd1b38d6f0bcde5827c10822b137e4bbca4, + 0x2664e95646ec5ed0536a1ae2ffc84165b5a3c295c21e58606c95037ab746a878, + 0x2b8b53c8e90382786b60fa50994f281866ace7a311a40af07b633f3c30fc7776, + 0x16ae53f5d4c63a81f4fd487793eaf5cd2cb03e3c8236be7ccab8c20372f911f8, + 0x127dad336628ad2bc403718c4983c136f34cbfafdf3e45c616af7c7e1ca8793d, + 0x10a10801dfd21422b4f5a264c2eff2121e0f716512a9dde5e6371eab17e6e7f8, + 0xac6189eec8ef4ce3928d7756fac44685b425ce64bee3d4852698709e769f45d, + 0x6f49e55c72efdc84f7ff6306157d770310b1c4e6e509ba3919b9466bdede393, + 0xad1247adf1e4bc8665343425bee4d3f35429c54d6bf4a8ec3b16dfdd1dd3a45, + 0x9f989c92995f86daf29a92cfeeadce5f105a0ae272b2253bb2de3758a771c26, + 0x1fef396daa237f6467f62441a55b75cb5a09fa94cb1fdb270ac309487fa682be, + 0x130d74deb88099e35362801333bf7fae8abf96165fae4b8179579761ae1de1d4, + 0x1b1e63b7d8b5f8d9612dc59e1aa9422f962761a992079a8e8bfc91695ca204bf, + 0x2d5d5c8feaed5dec95fb9d6674066c03d6cbd0d584084827214b09553adddbd3, + 0x2278a2b596a3d0af0a9365f954adbdd2c8a1514cc906369d3b0402811c952a48, + 0x11291006cc6718940fff0378cb6cefa09db4b7b7c84d447ab132a7a47573babb, + 0x1e0bf04d48d54e8cbe871bcdbfe619ed38fe69bf9d2a61fb5def330b2d7f4078, + 0x2b0907cd35c62152c10e47e930dca88d4b12c5afa7e2836c2637ae73500b765e, + 0x2e5051c91020bf6c73339f653843436ce182cfd487c02a16578cfc96d27c31cf, + 0x1227e0c86ab02adcaf01cfc56cffc815efeab33ece8c164c31bba50b28477b13, + 0x103b328f8e9fef02f340e3f679d91d9508bb1eed21d98d569a41583aab595707, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x1e3d52642e16240dd7e2b0ee21cf4b3b4cc10c805fe52009dc7520457180945c, + 0x1fde6f3b98df6104d07b84a703494892d8fd21cce53cfe9ea41c4ac6e5125269, + 0x6934a63e04749754a1980371301caa1bc00ce38505933b1ed0e085a5755856e, + 0x2897d663791c69c9bfe9b313759be1cea16299e667c3acb3e9f18079d39209b4, + 0x2f30ba6752d0900a64be8d6be8b718eda67cf96af95a1e0dc91e720dde3eca49, + 0x219898fe3438a5e5bdc5a79611084e0977456513586fde2b23b5e8e34d7eb7dc, + 0xd90f0afc59b011d2949f998d7c5e4c2a53953aef58f971a458704fd88f6a27f, + 0xf21f3710b4f641ddfdfcbb67d13f845216ed16a0f1c0b450acb82e81c85a93d, + 0x2eb036baa89d926515281aba071798e7397122fb51f4504e07b6acccbaa17af5, + 0x1adb3f0ad3c7e2300c717a6674e22ffa2611978d8c29e3d21012fbe7606ade6, + 0x11e1d1fe7ad3865581a1a8930698e676212b04c64773601034223475f91a7b69, + 0x14648747b8bb5b1e8b433222a964b95c4e143f70d6b26e6aa620e1c57c842ed6, + 0x14558bf2daf718b30756ccb88e3890ec47f25b4b5e087cf9d47f33423e97a902, + 0x2e6d0bac325dda6331e2117c682066a1be931e8b6bf889e5aa8f716bc14358b, + 0x1bbe690c183e54f281bfb4bd843afb3961bd3e428c81dcfdaeb8220a3858736d, + 0x23528de8742f3238128e65c88122a5e74f26fb2c1162fdba69f65f7d971d52c0, + 0x13e395afe32392f6fd5c4c5c728eae324d9c247649a6c3412475c4d04c6b0ea7, + 0x1ff38b45c4e5b8682a7357723d20949f7b792ec55dfca74c72dcb53fe68c92fe, + 0x245ded3dbd6c3db094bc040def9c4e8a96e67498f9923224388fcbb441109dfb, + 0x1f6ec4aeaf3545dbe65de9602ff4a22c48911ca6647bcc632c857ffc99a42d99, + 0x2431b237299f1a5e8ef22569cf8db020247dd0e7a298716462106e5519d3fdfb, + 0x2e4939b015f27fdc938f5f1ca55e5d7e912045ecbdcffedeefcf37ac77ddbe5a, + 0x26c061cde477c7011c04505b0126eff13fa555d248df1968878956209d36e031, + 0x1c6f21300d13f52bed69b2aeb3dba9760a94ed945673e3283848cfa5c4555c44, + 0xaecfdb86a64315429605fd463ed664f224d10b2e0a32d35d3a5acab914655b4, + 0x25a11f201fcfa64aede18e05fb19be93cfb4c15587759d5e5110420a267a44b7, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x133fbbd86858b9143bcc298a4d783e5b8b4ffc4290d1d61e87d1ce5fa4f9856a, + 0x2cf3bb0c00e204f18bbac1f7f093b9febf2ca7542f44072be70cd915d2c43b53, + 0x13c1a4bbd3a938e8d0399ff791d86962d7ef1504597419c2c00f421d4459c55e, + 0x1b008db98dcf53332b67c287841ed73838203b2d8598187413c17308bd8cbe30, + 0x1e42bc2844c8f32ca38ba9a1d029c7250d75a237eadd2d40969ed5674ff88fab, + 0x5e9909d9b2a8645974d54fd3ce3e734fc0b99236a2a590e6fc564fa00c806d2, + 0x1e26282b7dbf93f3aab257ba1e13eaac39ab22fc81b7252c079a192c113ed7f4, + 0x102a6b3d3a90d1f67e639a27e76023612e096c02df65bf64110ba239361e35e9, + 0x1f8d425b3b39db5096f4897d43838bb2cc77b4ed0f1d99a7208fdb45faa3b3d7, + 0x3d122f74d869433e1457806b82f38cd91103972e456ced5ca9fbc375497ca3c, + 0x17943c0d333da5d18d0856b442553e882c75af5684f2a8127a9d52123b350c43, + 0x1cf484412484df0cb49e3916db14d6bed50eee93dfdfdd081480da21b5388ce1, + 0x3e41d466271e7fc632ee7e0acd2c4c446957175ebebf55463ef9e16f48bb9f5, + 0x2abd2c1f5f2ee158080419092b91d64876bb73f9aa94d20824e06448278f88c6, + 0x1e979043b35e1d57826c8f7192a1866ce1b287772cb266eddbd177b3c6186d8e, + 0xbdad4e92dc796512c4daf27a755b5c5dc6c666084c648c4bbff65ff662c667c, + 0x305dfb6283eebb8f5bef8a33e0dad282ca92ba895e85853d210c7cc82f56aedb, + 0x273238f0bf3b029f5064ad1beb0129b9539edf1ab828a4d113fa7652f12fd273, + 0x14b12b9068950f98de141ba4b38cddb1e398b0093d7e118651d518a7980cf6e8, + 0x3015c78de17c6ccb86e47c1ef08680b12b948b5a56da8a371e6e2e0147c42f51, + 0x1989f7bfdc360a572379c14223f75aebdf04254a589c9a9aea6d80e020e13a21, + 0x2a65e0ea8cc0ea69c631c16bd174828cc79e80143a51c35a8dcddc6a36e7e717, + 0x718f6894c8d87898d8db2c9e3fe7e924b9e31221235f56a11d91c64e4d65fac, + 0x26fcf8cceb403f4ba44219c27d6e595b794f4fa99db88133fe1a031cfd32b498, + 0x78d5c5f6e5f3e7bc47044a82bab78a85279d741c5f9d5c8f3522d34da3d8b99, + 0x8f0b5ea35e699ebc6443284da3218e73f20e8c7eefa51962ed8f0706db54bdd, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0xfb6c5b68b5bf3fc0bf849c18e813e610eee228716ce01fad6f05e005802d35c, + 0xc602aae4b39cd1a84195fc795b9f4650d45b791afe4368689339630feffbc6, + 0x110455540d38fc9c7ae7fece8bcfeda5602ca72823a8162cc4edf21ff54867bd, + 0xb380e9795f1ae5eef24029c17d3c2f1b77f2dfd1de38d84e4c95a344070ec48, + 0x2ecac08767288364ad3ab00f106c9d45fe106b02e624bdbf2bda3f92739ff03e, + 0x1743f85f877aa121f1a8ebde66a3ced16e0e2c61cfea1f89f8f050d872929332, + 0x4d0cbd1d1dd0a87474e35d15e860233328e67057c1398d9921f930db1c32b97, + 0x2d22b693ec70adb123adb300d69ae39ccdfe6873afbe66fbfed0fd1170f0e49c, + 0xfc8ea8eec07829ad468e18f804cb685425a7f56702c78bf3ef9ce424d2ff611, + 0xf4aa2f3aad32e709a407a80affce97c751d6d188b6c9ed4dd13bffe6ecdee76, + 0x5374852d2261dadf1e1404368b67bf8377399ab2a4371ac71ec0c6ec525150c, + 0x496f544992e33a4f0c52c8406887623656aad3f25ef8feb0f485903e94a2260, + 0x18a9a16e6ed044b20459820025be1a938747b97db166552581a0372127a75ef9, + 0xa2f1c011a921def0baeecda662d0cd96c5d54efccc20897ff67bc18e6359636, + 0x22aec007a72e506f9b0708c0dcadd6a95a61bdde90849d9fa0f7d6ca4900252d, + 0x12f1607ee6f4c110aaa5575fe992f47e024df0955ab3a985ff5797c7447db36c, + 0x8a0e21aebd5298400802ad68a96d644378b580aed9c46cb70bc39408bb5d961, + 0x77214bdfbecbffecf5bf823ee5dce410483c9af4906d7e5e3a6966e446924c0, + 0xd8a51d698768c1f62ff879f0e478e98f1157ffc88ccc234f8322449689ac79d, + 0x2ca7d5473e3a7a69e048db0b7eaf1cbe2d15bd97dd62c088cc222af396daf89b, + 0x1db504c331d3895a78674b2f685fcab2081482fb20b16843abd4c34f91e754c2, + 0x226760b82659919d5795bb171b21f92fdf931045381c5f341d772a6018d78f27, + 0x2c6ee4af1e71f1f46a56943cd1a40ae76de4db5447ce6603eae52581f81b35cd, + 0x18f11a6b7218237066ddf0f730b11e52404b6418028f591d2b03dde94bf407d8, + 0x1c726bc6da34803fc45168badccfbd6d0e90838303b5256be9f3e29ff5f6b2a7, + 0x230da928c59a36907165396cc12f5155e3358dbb891941e3a70d239183132785, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0xa6958be4b971b6fb712329b991d9c28ff15be0c1eae89cdd4610ce27a2c7c12, + 0x18fb79983ed105bbab4fffc7c6c532808676e702d5d4deeb82ac9bf3ae9118c9, + 0x2cf2b459fd8fbeea84fe88a081b89db2e7b502d94d149126f6a532831e31764e, + 0x24879d31eb0e13c6968d486a3bb01ebafbfe6fb47a67f3634d1294334d834e5, + 0xb2103302dbc0c7c6c86efa0fc45ccff544cf89e07377b37bd81b2e8453d953b, + 0x2e2e1fc4c5443e2ee84483bb71d753ac2c70e0993cb280e0d6f6e420763fb7fe, + 0x1a9e105d58a6f8fca7fb505e6240b2fa3f7d84d1bdf1dc5d60baed683049b488, + 0x2a1042ce88edc0b73ef4c2c44c12d6d9ca419b2f8144c4af86ed8df0379f02e4, + 0xda87077919cafe94aba4f234b6fb078f93704bb4155e9a8d55f4c7c8b887529, + 0x10df86ad83b48800b7b66fec0843926e7d958f1f69e0c2ce3305a5aad0d6b8ba, + 0x5ca67cbd464f830c5633b84cf3d172f88acb852692358e4bed0a5b69fa194e7, + 0x6f1f54b5acc18eb09f7ac569c51177a0248e9e8e9da408cda7f06826cf19cad, + 0xedcfcb405af9c2132a3992aed66c0d945d01ef726888c65a260f3c56f208b2d, + 0x3009525f3f6c8641daa9fce108036bee7bd265e758ad202810cd526101201528, + 0x943a87f4b786f072e9637b5b58e280b0ef10cf747cf13729fd4edcb5c09d76e, + 0x2fcfcd4647f625c42f4c129dc9d782771c761134be63d3140279960e6b5e3223, + 0x12afa4b24ee867bc58bc57d2e55195215bdfc1f29d541b09bf8f1311d8dcdb7a, + 0x27721fde56e70f248964e39185a35af7c38e46d8f86a160b508fd63b623489b0, + 0x2bc75c98655a355c8ef7d48b0db3654bb2c579f0fdccdcee9cf277f2af834077, + 0x1f49b0d6af4bba3a9d89764eb3fc5a63da95b559607ae0df206034450e40195f, + 0x1ca12480c0ab186896c01ecc28e0a41014814b9a28de45fa0b79b90a7cc8cf9, + 0x1040b4f3bbeedbd2ffafba407c214cdd8abd6555cb54d590f2edea7145d9a48b, + 0x131f9b70a247303bf84112dacde19a9b953f26e7274279dc974b643314f51d61, + 0x102a78fe962133773dcdc7e30a00f87fcf3a3ef135fe4f01f9a9517b572e0379, + 0x1389adcc893fb4478e38b3f3477b8c23c41382aa0bffed4b8a54f8c87ccc6285, + 0x59eb07efee98970dd36e2857a183c43d6ee9560b3c90fe54515a5dbe55621b, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x2ff7ccae4b6aed16c52d5cd2b2be44d66968914941d91a3c9c4d38d5c76ff881, + 0x27404d8154cb43997a5d6576fa461096c9ac1d885a17188bb9d7417803697661, + 0x41f16639e3d600cb3859f701e46e5e38b88927dc20e429030894d0d2bfa5f07, + 0x280cbce70a5f719bdf3096cecac201b2c79693c13f01d40af06b7dae353685a9, + 0xaeba2eab11f80d6527144cb8f13afaf2ec9cb4c55ef424bd00e2ac6f09cbbcf, + 0x11473e38a5168c35404178e0c40b35a7b2e49584246518c521375af70e99e194, + 0xdb9935eab2a555400c37dcf884cb2ccf1226c4d931ad3167493ff0a272fada4, + 0xd9a481cfa6ef0c5c441c790cb8c9b30e2be0adfd2723ea5c1cf0b962dc7a40b, + 0x2e8fefe6bb8a391222b65341bd25b01b02ce0d88b65a496a9c59abaf25ca0b5d, + 0x19dad0c5b078ac863acab028bede54e6c1f5d8f4b8c8172176ccfb53740bb10b, + 0x1dcdd9fbaeea72955e6752f92205e88e094fc5aa4e9b75fa0e173e0425a95e28, + 0x125eb35ed67f035219169de7f612c1bb3eb788e3740b9054ec89352aab2e506, + 0x1f64f0f4b2802abd8f6ec78b6a061bd3345ddd898998ab9160a12ba55f997760, + 0x1fb921d2f30b13504d31f42d0cbc3b3e83714a37353246e6426f2a8da6d26c3d, + 0x241438f09da43d99917952c9f600d47a3f30b79b5ec80924f4427326d284abae, + 0x2ca504ece10e731645d09ebe52614c3e0fe99679b4e210297887f45f99f055d, + 0xef909466b00c00c4d39e13ce788fce28c32eb73e1e4575f396110cd78c690ca, + 0x28aa2ad31f21f32f1b898fd025f6a9d34abd75cbcf29694cc35178717db80d69, + 0x2e7e619b01a79ef24869bb8a57f0c1668ace7d7b721e253167ad661f279f67be, + 0x10925878a22951d216c53068b9e2b8d2a2d4c235ee483963c68e75b246392d9a, + 0x25bf71cbaa22e93f533d72118b04e187d20eaf3c07c96b86a857e4435e870c2d, + 0x2c12c98fe7f663cc207ffb753b9c099ddc0de2d774771a7c84fdb379fbadb65b, + 0x2879d4cfc6efd84feb0d05d1546968f98e11c38374db3f72b753412d2cf2e3f9, + 0x213c205c362aa0d41804809efa5f53a93c4c26ac9d1e91ecd081922fae6346ef, + 0x1a65b2fcd5d9c0db8dad898a002a9c11ec40412378c107a8aa0ff70d7416d3aa, + 0xd6ad0b286a355b4026058b97cc6a952a6ca1ae3ae23641e81bcb757831405f6, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x13b5aadba85b01644fae9e2e542b8ebd5003686bc751399421a798a1ffac6d84, + 0x207a44c8e2044f2f2e6953c2bf4568e8abd69824f301cca26972266e0e18577c, + 0x20366c61e53dc8718125d04f64ff70881d22e856a3f4d9224cf8633143a9555f, + 0x7dd546b57abb0a5f0fc753b8a97526ef3417b06a79f30e5a2f2833d205bd29b, + 0xbb6251b7bbceeedb0b366e3fb117676d1a31802d373e10117cb07c8ef4abac3, + 0xc19b0d2fc9236505c7c7b6a4b1bea3f91f56b56d2d4d6b0dda2b6e0f428777e, + 0x3238596803492252af333365adde8b43ba1ea6722b0bef2d89eb8b215e7a568, + 0x119c3970cc386d6f0e39d351d0d1f308c857c3547373173d673b72c5d555fc96, + 0x13574c0b39382b249280ca5e86593852ad435417157fcc4a7d7af23b1425bf3, + 0x2c41dfb547330e3cd1ab36dcd14b2b65f6db6bff0cf3fc858d7b4555e1ad2c87, + 0x151ac386d35911a265199613ddf17d28ccad77333887120cd6ec04b1ae5d7844, + 0x2142f184dad54cfab54f49734a6dc8e858cdea2a2039dfdd261319fbd8ed1396, + 0x232960591ef4ac647c6f02bd38cd0b4e0f26293eb1bbe703603714676de7e4ef, + 0x2d33e28f33c118eaa8c9a50322e0796a657acca1822b9caa8368199501a577d9, + 0x12da53680185973a1018f3c8ebda54b5fdbd196a2b192f27dd4e13bda2530a6c, + 0x2cea06b27f51acf0607fc354f64c2c3687f86bcf5616dbe9e56385ed5f7246f1, + 0x12ae9658e5e33252bbc1761824ec8131cddd4f006d354f1dcbd17c6133fd84ea, + 0x1500265313eafa13e4db72b664aa06998f7d0f08603f3b59a2d4109263c8668d, + 0x121cb82b95c9461189b38b4f9d1535debbe5e49954ed684767d191d8ffd5d613, + 0x2792672831f5282bcdb13cb16e9049386e09bc11a74c1b34c2ae3a52a3d69dca, + 0x9c49e3fde0a20b1aaa8e0cfea69eb95377ad867be9df04c11fa23e9e559ca3d, + 0x2b2ef2807d34d975db74f912e385f76efedd545addecb765209f531b82c957df, + 0x7a76c4304adb61e8611d9356708e26b98920a0a3fc54bf7e8341e9e189e365b, + 0x1175aab1e1215106386e7d6ab6e8c8ab11898648556d135e9d779d932bd654e6, + 0x95881e72157a04b0e21686523efcc318cd810a2d31afa2c20a49bfa3ceca7da, + 0x1bc2595f9eb575721f2cc048180d6a1dfd39b2c9432c4288b896ff27338a0c15, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x2d72542a02d6093f229924f57769054f0c9f2341187cfcb456b25f659cca62ff, + 0x2a00d2a68a415131906040f416d85a4293bfe098ef6c6cad01deb413ede2cec8, + 0x1cb01e5cd271049bb0325eb6957d2e04fe46c4f43b88948edd3b0faea5b69528, + 0x2e83b677673216f321facbd90699c9f22c2e2629191c76f7ef99b51449c8f763, + 0x2575e049e33d2f09c8ced4d3f663f7721007dccad5ef54af1bf0503a545d78c0, + 0x27885d131c5352064f2b1dfd7eccc9c1eb563d86f3d11a4901a4ced089dd2537, + 0xbe09ca0f50c25da57ac348af3c0c51483babda2e62b2c3b55d00f1eab40c7c3, + 0x20ea980b40600cbe365168750117a9d40e156e1e7633ff512573544ee7be34cf, + 0x3f0218ea64202e828409a7c012c47419edcf7ff1c2902792c117fe42756ef64, + 0xe6a42b289d3df7f5355f32dcf2a507735a0b4e6b4ad2ec1dbe976187f62eadf, + 0x224853c3ca29c4fa226d98c4e2497e21000225c6a0e0902b3d801d8522606b2f, + 0xc5295480691ee73d8098e95570a794cff16c70ce743bb8a42dd627715648416, + 0x148645a642117f6c5870fe24306f9b0401ffa1da04908e1aa0f6b9423986badb, + 0xbe448a3f7e892d80d18a4f34e16919f8547536c517b49ca457fc4ec9162a334, + 0x2bc573630f948a668f64606f9128f8f0105c11b08a9dce89aff3b02a00f0a5c8, + 0x2519650010b2b9642414e33338b47f1d33ce4976d19f1fabf8298db70deca1ee, + 0x2825ddb803da718800beef69a8630fc7f3b58206f06c008c9876772d5227736f, + 0x2f2c24da651d81f403fdb4dce59e64a2a6bf17e83f562426a52b79ab5e7401cb, + 0x3bfdef37744dd23f5ac9e47fde12035773eb7a1c666890f3d8115a0c0f1749a, + 0x2df9d9e9d2c54cc87d0cacacc229d561566b56b0cd00a68b31dc706e3f06351b, + 0x14c29bac822f6d9d454c11d35520dea723fd79b06110c8135e178536120a0b8f, + 0x8b6fe4157191851acee98ca63208dda32c9bf73c833dd1caf158e992847a5a, + 0x25a3dfe68d7513c1a26bcda26c412412a2f7ae80cfda7afbf996bc81cfbccc54, + 0x2d3c0299af854fc8e64fde3e0ed04c3bc54292273adb103f74bf623e889691d2, + 0x8cc27272e1668638fe3f85e5ec76f5ee1595328112a949263afc8d1406d3e48, + 0x2aeb2bd0a8da3fcb57f5b428f850f41790fa68f5b54b506794af4db04a30a1d2, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x11ef04a3823d72d4a7e073114b2e6791e38b5b6aed376228ac4a20b2eea244d3, + 0x101022055653fcd3d2659d6a42694578ebd518b5738e6cc884192e1091f58878, + 0x180f05913fdc0f67f5074c976b3ce2137afcd1c1b2940eb951b8de723397d036, + 0x29ecb8a00aff8bb64fe2df4221cc57bb0cd6eb6b002eef1f735b0231a72c7e91, + 0x16156078057591db5810dade70d6c21de3a782d5fa3143211da32ed8f22c0e8c, + 0x29af8f09441dc2c0e1344abf63fd38ba7f08490f435fca75a26390b4e59b9ba1, + 0x24d8bef242f5ea95cd238844e9134d9519d6682b7448d40bc9f1ed8920eb49bb, + 0x2b76b5027eafdd7a6a3902665416cb07e713952521c74857cec4a829375fcba0, + 0x293dcd5247e1143980134b15f9efbdcad3e7700b6effaa97e17339745e004a5f, + 0x2ac6a13e798388a97a5d9b856f8fa5aee5036fd0422f9444749f3b8c4b9e884d, + 0x1f5dc64952b9c1bb892ddae76de8212aa15c49508cb760a4f579d608c665eb68, + 0xeb5587c5c438db178f2725efc1b739d53d261f52cc4340f6488a8242b74913d, + 0x2f58f77c4c03e9591ab2cc38567d41272c1dcca473cc4bcdd0a4783d2b07bcda, + 0x1c908cf8e41976b7d63c3f59cdddcf83cab22433870351c60e4bea21aaf373cf, + 0x23581184440c2ce0f3acbd6ef778e504f6162f1930e06688417c82d85a83e9dd, + 0x2fca62a378c65e6d2a0b3b6d89489e8ea6bf5d95cf27f40b16c58a15f05e0ee9, + 0x2390511812e8b21ad50a44d1eaad9690f187541f7ffb8a0ff44e35ce3b2733c7, + 0x24660a052455c262cfb78be90a43345338dbd808c422e880eed6b19a76a42d9e, + 0xdb011c8a8f6df9cc0163eec3eba51b230837db2013659415ffb24b3958cf107, + 0x1bdd458fa2cd40ad49ba12709f1bd117ba67639f7b52a7732c56b98e6df5b2f8, + 0x21fd3e66b238769774a650e1159c04c47ea364a48157df08d90d4eb53974c15, + 0x7556eebb12fbeed954d3e9dc4d5da1ffadd578d4ccaf273acdcc0635edc98aa, + 0x200a1f0fa4e71fb1aa1c9b45949185769e97d29d11caf13185fab33fab36e09c, + 0x1795336032f18e1f4e392b03b65bc3dd268813b2f9bebbec00548a18ba37900f, + 0xb3d2d7ddc758d320c61ee6ea8137f08d2f31f3d159bc918b0fae895c42fedbc, + 0x2bf1a39486382c117a286a19ab96d73bdaa9c9b45096518f69491f157df85c0e, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x22dc5c692d9baea0fa2685d2c25fc510a43bafde0315da1c52c108124bd40b0f, + 0x1c9a763950a409e9363997de4e3beaa0944b0f1feb3d917238409584e9c8fb68, + 0x15761f0591d99bc354aa0bc4a11153cfb0b5335993e4e600d4da4ed88fb33199, + 0x19374736f4b0ebf7dd3aecf4e7cbb669a53b4dfba1ddd4b951769ee44c51edc0, + 0x1616bc37e489b1559a3e813544f2d3f6c05a33dd8a39c644e0179aeebc274cc8, + 0x2fbed52ea54d56a8aae40a2f16262b5cab2bee4e964f32acba16067841ef5edf, + 0x1ee85a9999931500883944493baf240eb51de8e8015fabdcb9ea68797bb03696, + 0x2b78ea79b23365607e821a947bb4ba8035f28820f1ddddf1caba7edae1eb2919, + 0xe84e11e29a4b9ac41c2e953f61cc86d33254120f426e217d2e5727424cdd81d, + 0x2f28c96987a9aeea275da5f6bd86a15986784da79796f308fe96d7b28bc3b2f4, + 0x2c14cf8c8c895efacd96c501d5461df5c2f9494911100a4c1baa5b40f8751ae7, + 0xd311aba1168e2352b438015bd49b31d9f5ca1e8460801bbe65ebf019776ce17, + 0x2d1ff9afaca2339c66e640fde96fdbe0e586e71d79e76d145acdd126066c119f, + 0x1c5ec2267db567e8d5f1880899e3add17e7ee0c611605320bf32fa2d3b1842d1, + 0x202908d4f1a4ebead7acbd09fcecf10a8fe557435ecf51e30834bf136827a83, + 0x188d37c6825523715475a10e21e432d21a8f921b32665cdaa6dc91d31913d982, + 0xd976b5ddbc8409fb64b65e1c5f458bd058ff8d789386fdd595eef3a064eabc8, + 0x19268d14b34ccccd93947b6ec6455b6dbaeeda1ca9cba82f33d6e4e682066db6, + 0x68d38aec68f918213eeb15a3d5e65b3a3a4ff930b59b733e34b0b295f6db1b0, + 0x24cf117219d823994d2210d2bc2b60585cbf6d667eaffbc726c2b68a3fe466f0, + 0x122577912131a547f85c741fffc4d5aa5f6e45453119a63c3004f64651e821c7, + 0x1996ff6a6f3dafad0245a77ba200d39de3371ca2be5264952657ac703241d4fb, + 0x1c84f6cd3c3b1d091534dff90e04f0675e6c6e60aa660c3dc4366eaab3ddfd33, + 0x11f23290442ae048c2622f3be83e52ab302660bc6df31171f26bd42a5f356fe7, + 0x2311bcb36c72d2a3f8b103c39583be307ab91a5b020252f7c8015e1c9ae7e56c, + 0x125707cf76963d6475a5dc5c1f832166070dad40eaab70cd31b51e83ccadbcfc, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0xb4b8a05506a055387dd95d95f3c91bf6a1da689ded43e1f548f703649486988, + 0x1d0c6ac842eccd47045e4ddb34e04c1938f9e93aa78b5fe2c0f44b00c6131ae6, + 0x8eae224067879f0830f967241ed0821f41b0e20f9cd8a6121f07aac10e30cc8, + 0x73f79694b751847664cd5da30f38013f2a52fc2530a56f01a10901cef975cdc, + 0x1294381efbe257c11ce6136df76cae6caa4ca5ec1934f1a7f5d4895e97391a5f, + 0xc80e686ab09da319588f7c17b27db8dc60981c0feb8b2dd58be98ff6b3f553c, + 0x28b442efb75aa8e6b0d277ac13613d59b09959b3a1e90b457f7d93fa7bae6766, + 0x302904181cdfa19f33aa2838f6ba83cf0202f22054856155d5c10a0d5970042c, + 0x2b17dcbf694b6ee011663776b422100989f2576d78504227d547db889adc4dc9, + 0xb89fd0b5f5fcb94a3fc154664390d7dbc7a8f028db060b7a594f205eb554de6, + 0x29643b0ab6cd148bffeb6bad54e34bf13cca00ea98c538d900e949f8a223d1c0, + 0x25ac40e12ff5d3ab47779044da20a35fd1ec747e7f9804f951d3e3994f0be643, + 0x22b19dae475254f480d6ff651654f808e6c99cf54186094f5a4fcb3d9c992524, + 0x1c5591a266c5ac14f1c83848bbe3f9bc926c83b4a19031af0334da64ebcc0f57, + 0x22dfd894770188e65c40390d7ef1a907800ab916118530a0c1b736c885a42643, + 0x3ce73087e6cf15f4c0c9e94c05b1490f58f2cc4ad3fc746bbace3ee6134f65f, + 0x2d391381bc0ec52a224a9add14af01b875b9ffd69dc115e348c1d6c3c743ce29, + 0x1561f352a096cb328906c091a612b9ab92a4433f5d65f4f55e78b02c4f84414b, + 0x25de146f3cc4f32b6cf8694fdd876a1c9f0269e89d63d48a8ae9ca064ab2ae64, + 0xf410294c8d91a9bcc60d25f4c73a4797913a27067d1f664771da8d1284a77e9, + 0x11a522b6b25687e258df304954bb84ceb1aaa9d977ba292ef1ba49c652b033d5, + 0xd061366179c02608f06b6984ad53a5adc8b1effc60275817e79e7eb031f5dd1, + 0x14b4604d095f37b5974254e48d7dbccb68da55306e08d00fbbb8f06bebf15f8b, + 0x2f0d5f558fd4454b062fa33f1e52c5a6559ac1379ae507aab152104f511eb53b, + 0x11b307ffd788170d196853547920b916d6a6fb63a15d4cab5452e215f62674c2, + 0x2c4b021e2b757863b41bced2e1aa5be7e77c152e396026fbaa09cea515001c35, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x32fbae1fe345271632403da8c2a96a35805c2a3e87c4457c8a251137bcde383, + 0x197360c47371eb2f8266e052762cbf42283dd8c4ff1446213c1c11752c6c30d1, + 0x213ae97ea4c10ec4a64720db8810df370ce3e9d8492f6806e06c871f0dcc4ba0, + 0x23ea027e72e70e5db4ef89316ef3a127454fa082bd84b255763878395ce18af3, + 0x1a522fc99812fc6ade296385a9f64cefbabdc59b664d33b02cb1c805465e0bac, + 0x282bdd7da996a1d58ccd9e4797e17d6a30224531f3d773b48ef23daa5077298b, + 0x278f051ff5a35ad9a0f1e5ce9a99c9e1b669f58b127b174b1573e76b9a95cb66, + 0x14d2d438ddd5fd9756f4afe9649c2ff2c9ddaf2e6d1ad10b8dc4550862f7424c, + 0x18dbca4af7f465ad6968bc7a1837c03d10d09a94f03c3e7fd3f2767e86be7b9f, + 0xb2f4c4bb0ad8c2047f62d2e6b1024da131588d16986b03e63e8ce9ede6c7fe0, + 0x21316797b3870762390b31a48e8b33b319da5dab6cd4a0c28170eeea58f782, + 0x6b3f86ee68e72580f8949c7ce7e789b629efeecb5e71a64d17cb1e8f4b57211, + 0x21a36423378fe8ddd4d3ac4a6ded8b65b8ba023593a99758ab917ca0b67a324a, + 0x1ff68d97b4ee71f22110b03e7e9f14641d8e98513a9b70c9e1eff000fd537006, + 0x2e0d1aad3b8bf21314fd506d418cd7f78887789585a28aaed747cdacf7765b7f, + 0x148bd4a9f6dcf19bbda66f4531eb4e876443c729ece0612fc005dd89c808efa4, + 0xc11decd7766f5601e8d5dc09960399e2a441254b57aa25bb3bb80724a8510d5, + 0x653950fb31c1384207cb5f22e6adbe9392e0fd3b6fbbc9eb25f4064656e5b7, + 0x61c7be518e2a7e7d9ff8af58dcacfcb3f0499cf7c35ed13929affaf57c95818, + 0x632546dddba57da93cb55ae4fd8dd0065ec22c94686a63cafb6b151d94fefa3, + 0x1458d6428e6cbba4df84a44ba6aad2a9cb0d1c9041283c1ec5277b2990418750, + 0x1c58296b3da9f61460610a21dff1ba812b726a9011f0180e4f457874f7d8b8fa, + 0x11b039dcb0af8c795298f360dc7f55aca201c35487b1b81cf009fefc204bdcc3, + 0x1fcdbcfd2065473d499a075bf5857bacba94563f2814577e5705a020211dd0e6, + 0x2d9f02a658742633b88fe4185dc29bc4297d7aa9dd473740183ae46042dfb040, + 0x100e915a9be179a7cb25c2332a3d48481deec2ed9196214a55d765309cbc8af5, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x1a618c68dba0afe90df2de9e4aa3091ae73582b53555822bc903932747e520b7, + 0x2cc1683d5312031d06b89710f03b3889066006177c574ce3cadb093e7ff5a301, + 0x16e6197f7c10ac35b2432c0ca10249b3b39a8e3eb83d702482ffdd8a0888fe09, + 0x221e4bff156c6a15260b4c5651064fbe3b3cf8f10721e87ee9f72e7021759490, + 0x17ce9f46591fb9ea7e5794a6fa66b1434fec12507de6e8fbc1e4472d27109b28, + 0x22fce270c4b0961c89d92325c52c85141461e0994e04132d632ee19d9c51e556, + 0x15cfedfe30848fa55432b62e7791109698a457ecd5469ecaeddb9f083f66590f, + 0x3343e9088cfc374b61b75ad600de6236aacc4769e5ee8b9aec9f07bd0969f51, + 0x233d73ed21179810ccace1227dc72f2f8c80ddb446861d6e833a29c4084d44b7, + 0x20c8fd20ca1ef20c39e6c99478f2bde9c46dbbc0afa8c840ed93cb153fbc0be3, + 0x696b187d4df08aaa80aaf272d12f72352f6be2e67568dc45b9b22df83b4c672, + 0x26242eaea95d43830574a5378f27299753c7907135c9350cc0afa30c1873c429, + 0x2db7e74c58283b55cf6be1fe422fb2f2523020e04549b7cb88815694bdc078ca, + 0x1c3db6fc9f3fab8d9e62d048cb1a820bea78c43a71f202f779b8996a1559d821, + 0x14eaa8042ada3a2a7d247d46b7cc0138b9fd124674823942d207c7c6a330d395, + 0x7de2b61b5d7796c55c6c9cf4808569d61c78671f7484453d201d29cbe419aa4, + 0x1db38a0c262bf63e0aa7929777ac0914eda83aab24aa47d84e60ac4ff18bfc4d, + 0x2f2c6dc0cbcc26d091d95038e04a2886fbe8f4b368a738beeb995255fff09df9, + 0xcc224d62b63572de577993e48205d0a7f574cf32add5cbe518e55163cf540c7, + 0xf301c14380b822e1f0319cd575d63e603ec8666f361b500d1d6c28494c309a6, + 0x2e5cbdd4c1599557d596522efbd078c8e2f9deca7503fa533ea5230b622e7a9c, + 0x2b7b5611c6e8b5f05fe9fd010bda63b3d6bec1a90dd4e4d95da40bb720503d53, + 0xac828155aa6627ebf486d5491bac13c32b61cecb4d3178cd4701369c2740155, + 0x1946be8c11cae21fdd176eafd23fd635352031a5df260edc493c820fe05b00c3, + 0x19f2dfcfbf6dfb65a8051d60ccc08795e63fa53e3a4acf89b85259e6f85f0030, + 0xfe752a9169dff4e402c76a809563f0d83c6e26d9ed3ab2a3b0e4070ee7baa4e, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x275833d56c1035de1383b7eb6759e6971286af950f5b5b98ceb2a2a9fc52f45b, + 0x2c02e7a87debeb5cacd4f9c776b5999b8216f0621e87720a8f672ffd3051198f, + 0x3a6f6d6dbbd957561e33bff1e7f97ce1b8bcbb97e5e363a58810cef7ee91851, + 0x116fa8d34d5c67d290555db1263b34d2bb0ce83a89a81c5a0bd4110976efda34, + 0x1e81d2d2d04f5cc16db99fdb340df3e85d75e9c305b541d2d933f8b808b6e075, + 0x284898f56dcde9b85983aabb51a7324472955b62538c8c6fbe554080a871497c, + 0x1ff3a909f501d15420e9efb7f8071c0f4c55649d5e0f81a4de0fe31bc4e694a9, + 0x47be1a9fcf3bc7845474b57d44fb1218bde905cfa1da8c052a9614280bd9cdc, + 0x2a3787a31e5611ca3856cc840fad2b0a07bbfb4172859fa6fe527b7e0d5b35d9, + 0x2eb3bf4b3a98c7da655259991393cf7b87eb9f4908c475f00facfc5572c885b2, + 0x26aa5f863ce3498db1f5b71c96457cf97232cff235365a2a1091b6a85fc94d6d, + 0x19a6bc7f148d056a10ed1610f5f9b22a827ba85e51144c0414400ff4d2e91edf, + 0x196f5c78726e289ecfca7a2d2f6f2a5e82f51df54cd54d4ced1627b9e7f30a72, + 0x1118c048d3dead019a262810944ef9fe5fa017f472d5cbe8d27b7ffd2041db4d, + 0x4c7b810ff3f0ded46f2d4cf346e22e402a529d4793314a3bc85f963a6bb428, + 0x2e843295db044df4ab207a6c7aae26693f37a5e5765663f22c6809e22fa0ed24, + 0x17cbf9e9e90196672fcf0d0530c0a02ddf4879954bccd82f75bfefb4833842e8, + 0x27ea08561c8d05998b53f428166ca0a25ceccde43a9ca8bd275b4f7c537eee18, + 0x3491984564105af9bbe74e7d14e96eea58d73c39727a8ae616bdccb8a2451f8, + 0x287011118b922300780d5ba09878c898c662b7d5bcc838fdd8750170b643eeaf, + 0x19af1b66a5d2c6e5a4c34856b37a5a2aa1992546461d6cb65190f74d731e7b82, + 0x438f8d1a68e04ded124f370274324e9db5b35c0114b3d5e19fbea7d867e1b5c, + 0x1b7df25e02c2d88bafb19b2f9725a3ddac024746f30b4b0232518d3d4b8e9f1c, + 0x2fca63f9577b3f88ce614fdf17473f7d033bd30f104931fac24fb3878cbbe2bc, + 0x1a782b1c4732869014b1ef8926206360460ee6e9b7541f5eb0bea1a0ef184db4, + 0x16bcba1157829125674fa67f49a62a3da742c2639c62cab43c92362c29c8c186, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0xfaa456a4f334a6d64ec7443330027c0f6fdc3d0232029ec5e0b7299ea372295, + 0x21ae168025d871601564cb94712b6fd70efc57a75bd794f96e09556ac9fa499f, + 0x2659b387d06b87d28b97c58326d60f8a8e9e20956925cb774f4fb99cb0fc7bf2, + 0x6ecd6537384d3f96bcfd794a53b1cb3d4ac7574d23c753e20185ac05641a510, + 0x2c47b359757b6aadaf39168580ca135268ee4030f857e83079409db9f61a7a88, + 0x2e3c4551ba4ea1bd2f3bb46f4b411ca86accc38c54777867e6b6de8b6381e60f, + 0x1aaa42d6777c0cccdf6dd9c4628cfb4f9091c8c4e19b218d13c5ce8d41b02747, + 0x101d7175ecd398cf6b5e339400ed17866953ffde1fd49caf2327ae39ea805e2e, + 0x47aac02ad51c60e7b013d7e76e0219a33395d4103c62d76426b97fb8a720bdb, + 0x2159734df6ba0ebfcbdb4412f5e985870f836d55eac7278057bdb5fa002139a6, + 0x12c80a7f80bc5789e17e76a5323cc6e879e26b2eec7f70adc14e91a679d715fc, + 0xb37ff835c21aa08cf5e82063ef6dec2dfeddcc987e7fe222a78bc9827c797ad, + 0x136a6d023c29c33b1812073bf0cf9fb61603ad40ddeb3cadf8f202598cb3f7db, + 0xbdbf9722d2aed63d0059307617c47ac2688d9d01a8bb20f4a61b95252dd7b32, + 0x1d90c4f4c52e4c8157ec6ecb3fe1a70937ac8c365100935c3ec4c359137d468d, + 0x25d8cfba9177d817bfe2db087ca7ff74f3a4ef92986c6e5cfdea5703affac237, + 0x30562348197f23b21238c777e3d7f366cc9e69e796cb218281b210ac3f1a142, + 0x2e6b5b67a5f7449b426e3fd32efe3df98af0bfad5006d6370b574b40c645c1e0, + 0x60c72ab89831fbcfd1084cd3dc94aa8f69794540671bee622d6837d41add442, + 0x949047c842cce9e422d779c80fa13ecf5aca5859086ae9c3759cd3b02d7476b, + 0x8c9031e3f9fcc8fef60f82e8026db19bdbb5113c77a4c06fa4af3dd7bdaeb45, + 0x2850905ce0c275e427478ffb5bf44685dd95cf1f57056bc19108d6c85c3e7cd2, + 0xc76f19ff9f52168d20cb4f0cc0d10bce93d28b3acd6d479ea38b8a96f944455, + 0xb66fa2f9d2feda710dca114c22cabeaf616c70ed2bb793a7eaa328ea1ca3c99, + 0x6198754cf90bc048b64a8e925c41c9298890c946aba20953090e05e55e768ca, + 0xc637cab8864b9bff868591c6bd14424892702a1d3e654037d0625b258126c6b, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x21325a5b2ae982ee23a4c911b190b63005919d1ace55a101818397c73be72f7a, + 0x48d6872b84e860e934e439b065e7a162d5705b576d4fc14c47535d9e08bec23, + 0xde725e2f88af9c238e880d725e71d8a1d79c4be4421fd9529cbda976462ed81, + 0x27eb4b06d352a3404e16264a0fb08537ddcac2add0782481c2e7735d7ef1803, + 0x1b47254e3cdd4412e01829f03e74fbfcaf9f882b745358294012761106a0955a, + 0x1b4332f4bc0f47d8728dac5d12fe99070a53ab0ed1462c6add9ba42c2323f755, + 0x218d22d5f13b09ace89e377cd7e02d3b52b74a1285072d62540842686f728ae5, + 0x68ad6997a9ced270daca95813e82527f7e6a4d5cc4911c7e0fdde7a1a062d03, + 0x67a187bc1e0d1740ebc7f7343397b235ce0034bd6f6fdbe43fc50394edd65cd, + 0x26d27d9b4d504feb1adc50f40bc7171e56e9cc7b17086d68ac09bd337ab9a756, + 0x6e901afc5dc879d75ef7d324c7b7c8cb8772f7948829dbd2293ab032a9ce962, + 0x14c8e19997ea7bb4131f9765ed587425a2fe5f91aa4f4c918201e74110bc7526, + 0x273abe5cd98541349618c993b7192c978fb02fc236bd40dc3a4a4f61dbce96fc, + 0x715d346135f3b13f84a62b794f2d00bc19cab24d35d168d1f95429d8856e296, + 0x2b9bcfa6deb252ccf6a2550e198f21b5fe0800fd3af70329500481a1f472f174, + 0x239f7dc3817df74d0e93174b1564fbdb7e4010b69b32ad0618a169748e496c9c, + 0x21978d48e2d9c7b097fd4d0cb72c238855c33bc79834ef7b08405b1b6a25b3f6, + 0x269c70c27b7564c9d24a631fd3604d4238528e20b010912916e2c1927df5b950, + 0x2c583dc96a0a9dc9f9efaac1de85327f007597a5e812fd564df9e490b5dd8f68, + 0x121e4187606e3b3382106069e0d56de26dddd453c81d009647a9cb5f48418094, + 0xbeeab0c615c4acfb17eb9f8dd647bf03917e1169c9c38d0f397c10e9dad80ee, + 0x1e07049aefd34f62eb9b702cdd93e84e4f5bc2bf88ac583ee4c8f7f358638c3b, + 0x59c6422f0c9d34dc813948bfdbd3d525a5050122abaa725261b21794a4bb03f, + 0xada60827cce301bb3aba3c0dbc1a32d14cf5723ab4a85abd48baa37b85b318a, + 0x10370b82fad9fa38906fc9afd3d2103760b279a5a79803039ac6d7b47fbfb080, + 0x22b53d470c374ee90f3477d1bb36a57a7cd3e39305dbf4895d1a38df65828962, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x121bac144ebf731b7e106308001501b5aba39256622dc16b6832959ef32d6a8d, + 0x2ce538366c9cee7a91c93252cb96b7c42b4e4b26a6be57c1e5448524e5acf376, + 0xe1eb214d4443a823686062d4f44fbecbe3cac0513ec37dc6969a24a5c2f34ea, + 0x2b10f3aa519015cb9f2d8e03efc3e54d82cdaa8825760f40856158eea75583de, + 0x13dcdc97aaf8d23d666426b008a02be78565ea485fc5b3175f2a36d3c6589a4a, + 0x1e179f5a8d8cf761188a1af7f3aabfd0c6586a3ba2da4ac2e609406494d8b04d, + 0x26350c1076435ab7615ef9103dbd8224d3780d72055c5bf265bd8f5bc459c5cd, + 0x2569aad1663fbf0c512be5d7549b856f5058b8d9254ba788ab4b67f957703dd6, + 0x21d296071bb18ffc608d41b9284b25f99e896f90b73c4b6ebc6c7e845dd2756b, + 0x3403ad2e4edbad53108b19db3580bbeb575989bf763939ace10bf3ac11ac946, + 0x2e87a068e7e10cd0a27806e4eb87fc4a909b75602e7ef4d9b49732d30f8f68b2, + 0xfecb01322ccd429e5afeee9ec8f3888c528252874e09ee6c82110bc67e1133d, + 0x21b1a2e21480c8623fbf9fec55cda799a152e941e99d0d6426d24666ecd9a7ed, + 0x10787afe51951f551c5ea3de6eecc8c08adae2debcf2c0add7a578db5db669a, + 0x129a75842ce7f380f4adce069972a00aa0550841e41ad2f46d1665177576f052, + 0x33844a0d5987a19e66c014e83db7c903b6aa7baff5cae3ec6f2e7f9870a7102, + 0x2af0d00127c68081dd29a5c0858f6bb0d20d0e8c8c1fa50d0d539436a66b4950, + 0x2452bc4a8de2db1f282d2d8063ab568d11cf00ddd0ccfb165523b0e7199b4278, + 0x7053595c4f99205b79bf985336e456422650f494c2f79670c0d34257ec689f1, + 0x1bad1a52d292401b1a8335df15429443cd8dc8c5e856e185b8c5f9d0c9bd2a24, + 0x24635b7d3ad41a5bc44a3a17d80a7818355ff8f18379004e5344a7b1713a31b7, + 0x2e7876129f03a5f90702ccaaa35e3d3c2709756360421113997cfdfb1ed927be, + 0x1f6028d50d8a7ee644320cef9612807c7ef8fe40223751dbf8f791ac516fa897, + 0x771c9d46f602c613a689a8334d46e0e5cd1d214a4831ebbc53525ab2d80e5bc, + 0x269f052ff6df5ae60f76c891df96d8e4a23e80371c82349ef960088ef64b141e, + 0x2961710040a2b2d6ac5101cb03a28f3bc2fe649baa6efc5100592077f15de362, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x10740ce6766bd5d45ef53a0b79f688c0c9a075938902c676cefec8a82c3da53b, + 0x27f3dbcb60ac79ca5eeba26c3971c64600543857b0d7a6019b292df5d6084e02, + 0x21093160140db2a25e4a17cc7600123cee22ba57790926c04610b8c95f1fd186, + 0x891be8d562bb6feb60c7571f367d6048c3b083b2adb097a27e62e336cb27a47, + 0x2ffb17d674958fcb7a8da2d38554bc5571c6efebc77e89514688212c68d50a1f, + 0x94c68828cd769c940b27f645dba1922d26898c64fef55d5638fd6e1d357b75, + 0xd55cbcf35eb4b2a41cab995bd1b90571e4a87677a90e62793f6073343e798f0, + 0x18e91bc3e095f9b687fe66cfdbbf8c234c27af317f13fc27707d271e871e7061, + 0xec0612f29bc32d89f73f7f0926fe0b3f3587dd7eed49c772b3aef2c5d41019, + 0xccf5311099aecc81a34b567999eb4c663d907a8bf4b22c2f2ab63a324ac3451, + 0x183ffbe622900edf9b6a8021ab80db00676f619dbc1732dcc8fad67128772d26, + 0x8f4331aefe28fb6f009e17ff632db3505b18ffaa61c6b0d341fe0b6387ce2bf, + 0x9eb7f33498704db8dff1c8777ff539d1ded2bd207fae4bb7465c375b8747161, + 0xa531199830d7120018b3039c7afa9a084d529d930f865c38fadcdc40bb008e5, + 0x194b3cf28d7b62413f9b837b687bbb4804733c8e174e76bed846f92068c066f1, + 0x1b8604e1486a35ebe8e6b900127d0dbb54dc8aaca97a4eb0c8956773035f3ef6, + 0x9b8de36766da341c7e0b810a53903be22879912b707e1f3f752e6f079ade75c, + 0x1a435eb920d2b84fe3c0b803ca2cf85a6721d31f21778706d4a87a923ad0ac35, + 0x2566d9e893c2afd892f4702accbcbb979c7cceb980d234de549a3c6c34bdaf59, + 0x18df8272b0340557ca8fa98dc6e75c6d788484702d389f13fb82bb09dd5edb19, + 0x20b183f7293c68cc2324f01a2693d3edacf0c28691685520cb6c1ff79f25bb29, + 0x128c7a2624a1bc92093ebab7ea53e0d5d53b059e21004b19cb0d2bb3dba74f31, + 0x40287c11b5a3f980d59ec06db46c6fa3b54e9d4fe0f474ca15a7aad1ad0ec1, + 0x21d7fa42bc56b52d557e34b091518d6a694595207a099c718b87b6f216ffcd7f, + 0x169dc2796511017c3e4ebefbe57d6f93194a77513fda84ef7457afbada8a5d58, + 0x1d74ad732a1dc804b9584e557a9c18c0b497200e0d27312bd2432691470566cc, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x2aca8e251964d1a3261f98ec83cb17d611d17f5758aeb8b34a8121121f7eec67, + 0x12e284f43dd76a9f1751d11335d43514ef963ffdf2036171cdfd4f47c99eb5b3, + 0x5071e18392facabeab0a39fea36c393572e98073e18330d9c4c7e654572065e, + 0x260d7455c8470a5ca5cb7a63c39b0d1fcca3eb1029d2994c5f2c19a39086eae7, + 0x1cf8584e37677b19fb7a05446448d550fe72a4fc79c92e93e7576f101dd05099, + 0x2d19dba2b7658adf60d8840e9c7b115fc37503198335c9050470ca3c098cafce, + 0xd98ea1ad72116cea32da96c74565bdb292b6f62671c5cc9de0904e1ac8a3918, + 0x24ac021320aa1f1addee655d4feaf537e470915474a285ab11b80fd166a20cf0, + 0x216feb63069f6947beb294a1c7240b202d132ae945f7cb81368a2c79223d1131, + 0x20ecca83ee5156e6092763d78973859dab5cbf438b6782f4d4727f07e7951bb, + 0x1e632a42fc326036c1f3313f372803cf8912d762b3026cb4b868ffbec464da38, + 0x2e652d54941af14d90b4347529d6e8734e184f48c5827373e35e96a0441d56b1, + 0x251ff531befaaafc6933e195e6327a853e70f7956ea16f99bae74ce703e13eee, + 0x12ac47acb9b712578207e429b989e017e010e2f8e513e5fdca0d5d70cf69cfa2, + 0xcccf17e0d61b8413ac667303d31b27e5bbdbe2de4fb79272fd26a96a6033c00, + 0x20f2060a29ea58ae11aed61e371eeaedf8c49f7d2d310a20daa4b08742a9c195, + 0x1cb9f0d68dd3c14610ff690400ac156b0f88ddb3496842a82976bec878c1fcd0, + 0x1e75fd54061e8660fb82a6f24ca385580d37c17fc731ecb67aae86ddcbd2c363, + 0x2d29ebc4f807741c6975700aac34dd02857b9ca3f389a34d281aee269e9509da, + 0x1871cf71711f4036a0104f07506e2211c40ed44327c7e19acbc2400345eb7bbf, + 0x630b7ea40ac6a040959e71933395a414a78ef993f03d2306233b0aaffe4a814, + 0x1ea87ac112d60f22961d5b2da26c0a06bd4dc1e73788a388ca3bee772cc78e7f, + 0x26a7a6c245da9cf530f87c9b20ed86af369087bde004bb6dc3eee8b32882c7cf, + 0x1adf5a028ce2b8a0787eca43ebcf427dce7bb7b3ac19fe0a8c0b7016afb25e6c, + 0x5e2e3348c9fb090e628aa40101db8b4f46b6adfc7d31fa82e1f6c9fe5b55a1d, + 0x81d87bc2e14f185b9c19f4cec48fa501d99c70a2bc881ccd6ec4f6e677721aa, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x2a7ab507906adcb6522c043a1b2cb2f221e5470822f048220ba731b3933f3212, + 0x1e0791ec0c83cd1f3a0007ff027dd589fb0866c6257c181d293cfb70b62abe59, + 0x19ad62da7c5d8766ef927edd0f7fbd997d0e6c6555a6c38fdbee7f5299b26d8c, + 0x1cf518d282e00b1894f86c42ccaa292dd208bd0d3576ecd1cb1c45d426f660cc, + 0x86e5c668f2c7540e65a379bb9738416e1f43e0b41619cdc040c321aa89db7c7, + 0x2bcd694a683fb621601f2a5f0f900f6bab1f4291d65bb8c26537029484b38496, + 0x2b6f0a65bade0adb23efce9c6e3629a07cefca2718b3949029362c6da4baebaa, + 0x12b25f49fb1cd92da7fe1fdfdbcf0ab1d715ee92ae7e2c0b2a60b8f4106abbfd, + 0x797c7a863ba81aa2acc620e089ac0afe2f713e46fe4d52ccc637953a4ac2f02, + 0x113166107727b2ccd9e2bde6285860c912a318ff3cbe1cca006973f444238f17, + 0x29d8beab8a793123bdb47e3bd56d6e0d6e4c9d957b38d6ac7ca7d53a30fdc94c, + 0x68f99bd269ec2bcca30a5c05afd5136feb63a3315e05dadb2acad3caad1c7b0, + 0x1d8a2e95f5012b9744d33e3db84253261797fadda47ae08eebd349753511d342, + 0x26a6dfcbfcd2a98fa147bd0b18f3e4f66e1f1a329a168e3a61336e4da3bb8f80, + 0x1d5bdb15bbcfd215d8caa665e9687c2d8add0b51cf54c5226ed9b89866f767c5, + 0x2bea457b568fc29ac1a23ff4322caed5463a9cd648769e8a1a118aae84df1309, + 0x1dbe7419ee59dd580a0ab4305440a57fb651830f979f8d21656ff28b1590ce4d, + 0x17ab1d55da8ff17391ba874c4b6e52c77dfd316a0cd9566d1e28c5dc9308d309, + 0x4a3a0d0f9e1b091bdd336acd117c4ede9d64621c6b2ea4f07726e065f17e2cb, + 0x2634ad4e91d1f63da6e2534c1161abec660d92371ed85e8f0e39aa91523b9e60, + 0x1afec968060a10697a3889bf3456a23a4e98c3781d0ee88e29334b14cf7614c1, + 0x23a5fd23ec8919d62176ff3954f983577d5ea821cee695387f096c7fbb93808f, + 0x283039c47dab36071299505922ebc21482295f95632d17c49fb8f07e382641ff, + 0x1a0084bc1b3e951aeb3dc6388708f8ebb52247527a393209664d43a1812e13, + 0x16fdfa540f269b40f27696610cac06faa7eba7d87542dfa42d28d3f453a70622, + 0x638bad28fc8427c2349d2930b08631be095bf0c03572131f3a8132f38f4c0a8, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x2b960b4aa6bdb5968fd27106ed926399bf40c9ef7a0abce38158191156d94b47, + 0x21ee2ffd320737215ba399d91f5287b56286e5f286441b29e7f4950f2a108d82, + 0x1a912af8a3a82ac944bc34390ad7af703d1e4a8f32996ea0eca203709bd526c4, + 0x1e2d77fe49d12a919d8ee0b0bdc15475f9d3d5dda831b098a921ef8547542ab2, + 0x1e461b0bfa65838c31b66e8973fd153308af46e6563e523b4c97bad304ce6bce, + 0x1222b1bba586c324581ddde55054315ea378754416b7b74406a44d90468839d3, + 0x231cb90d301a6e6e3f6c47a07a3f262f14370bda5a9844a4c128076b5fdde8ac, + 0xe3e66e543fb59290a8d57f5fda43c4b74b235e00adf1e1440859d8f252fde19, + 0x1bcae3acb52de61f2f907f6fc16c142016e053640c8ad9b4e3baecff97b2c13d, + 0x2a2e7e286f90e3554ac96ed8f80267a3bd9f747d787fb2533bb98f465931f724, + 0x1729e7b06ac26c624dc5c6cc6d761f94d93875ca170cd57f87cff909e922223d, + 0x9565b3ec6e63401bcd15d12f12d8c805ec5c8936c2223ca4dd510a57afb12c1, + 0x1ade0fa28ee13df4d382a505b3893baf5b4568bcce7121b5d48d29567da13a9e, + 0x2301dc6a1236420c051aaf16a095e77aa88f23f63cb30b410a323ba77f21f7f0, + 0x158c6a01fb01f542f7dd93ddf2ba1771d726cfaa7c39ba5260a5f6bbbce3b9de, + 0x2757b9eec4cb27d4e4274cca6e00289f2d12e987465c267b1fa104b02932a84b, + 0x3043d8b0cdac25b084aeab7475766326ccfd15758870a4b47a8783f73f5e4f36, + 0x1a1739fefe6488c79c6c32818ff62a65afdefb9dc62a23bcb3d46428cae5cd88, + 0x56f91cf9e2444d0d477c13c994388d88a2d8e1b88d6080b5a415a53117643ca, + 0x28c8f42ca93036c7226451ee7ae0c1a7b87b0c560de7b11350dc7f74e4ae51e6, + 0x18dcb540315a43872fc246fe3f6779a237c61ef5527e87a400b24b3eda058469, + 0x1ba374f70de60473f60fb7452d42c59f4748debdd345afdcf94d09305b601a3d, + 0x1b40af6c2e106fd4756b548837d64bcf6dbfb9d9380e1a70e010769efc2281ba, + 0x2578f4a6e3dbbf2ccc5e1837b4038327925cffd00f96e8d2fdac677f2b0faa3d, + 0x2ea53ec4f2f8900d39df68853f2ae9e969819d33bbe6ab9686e1185c37933660, + 0x1cb7cd707a851d764b7c3d2da544afa59cb87f6ae19971eef7f403342c205aea, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x6bd8c397b1e2d8e3b0d32ef2594a311d49a259567ae4c635582de9cd15689bf, + 0x291adb6944892dabcf5217145ff77361815e58600ea6248b0c0069802557ddad, + 0x96477873e56e5691171631e4eb74c7d2f9b2806b4f0e45508220739587a890e, + 0x1ff4f6ed8be43e079ad849d03ff3147fd6b1fc0db8c1b8477d65c096d4b25a48, + 0x9e5e4056e55464d9d5e6ecdf7127667de411a716e88014861d5436cffeabcb7, + 0xa73b0495d174fe15185e4bc010a545402736752585288200ea5922c5f8d29a6, + 0x108e0279556e28f04c5570a6274d115d4b3b1bffd7fbcc289cebae7053f40427, + 0x20d97451d83aecfb5c0f6cded427ddd517ada729de160d4ebe2429dba9d28a53, + 0x2d8a77024da1f633ae52a6cf17898c5b908f50ae49fdbe65b4662853337cc919, + 0x10571ff92352d4e69df05c3cdc65c0e52747e03f86476850a47f092bc272b263, + 0x18f7cada1c661e5f8f2074f16e72baaa705c2ce42b68e16fdb4d6945a33054e8, + 0x786ff337450d3614fc75c4d314a61395b71473e735332d78a7aeb270443cb93, + 0xcefe88f60cb9a382d5eeded9e7bacac15e7c906dead35cec09ee6e6d0016b3d, + 0xf163a2012b2484e1de36b5991e59ab0ffd4a531574f6c72382fe92576ce82e8, + 0x63dc4f07d9f069d06a30e7c5a96830d2731ca8165abd9ed89d187753f29c682, + 0x71a3293473c1dcd0ccd5a08dec6a321265ac88dac53eea581264663e1dff0d7, + 0x41b8d2a056f60d8d3ce5e3780a341b97592920b170625c1a69f2a23e1290268, + 0x2deddd6775308aa027b3449357f8abb6a6d10e11cc3a14d0feff23e3a8597ff4, + 0xac050f54534015c810863a63b7354a35fe52279ce4b7a142b48f5502702a4f9, + 0x215bca7ae4832c5946f9ad54abc0b3e7c547f8a5a962e4df85d0b82dce914799, + 0x1efcb27d3c098f574e7fd799e2a585ccf54a59147400ce00c86da0ae0ce90684, + 0x24ddc6ad9a48856da363007a1923d1106affa889e44ffa7959bf41edba382efb, + 0x2ef8e41f289aa4c64244554413eb515b9759a6b5ed9e2562d1a674267171650c, + 0x2f1c219c4d272380eb411db7ef93f6e692eca339fa507b656e0d532801c0e205, + 0x5f18c83d3464488a90182139c312e753a60ca4499e3c2c13f7c2e72fbf47395, + 0x179165ec0d175758f57172f5a9f7d1ce6e435a4a1351d77139b92c6ebec86da, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x11c208a0495e0e7c3e473f98dd1e8c61b27b44de88dae7850122421cda7cfbe1, + 0x297f95f2fbd4565360712a71bf3c80b798b17dfac6c54d884d99f3aa7d673dc8, + 0x224ceefcf32d746010d8069e79d356d69671e3aa9403f39892e5882a1891e718, + 0x2732b23001c43c62c459cf0a1f48790deedbdc489a6372138594a5a74e5f85ef, + 0xcffe59dbecf21803d789c62b67f94bb027de571a963be229c54c84ab106f9f1, + 0x29b8feb4a9a3585ec376063cff8e0f5a4292f37f7a4b7b1ff228f03f5fac0510, + 0x26a0c0e60a2ffa10be7d6b2c878312de74cc43fcc7f9eba49e05fcfcaa3a8b90, + 0x2e570656db41e2f88c3de3c09d68baba727e76e3511dd4d1291443db29aa5f70, + 0x12bb58e4672200ef2816a8237dfcdf70a9fb07b2ddc8789b748d0b559b7cbb78, + 0x216e369c8afad59e15e88e3ffdfbb1e137e9b314785632ad2c7c81bab01a77dd, + 0x2279e39d7921b8e04b6f36503059b1bf2ed79a3b94f15af97b9720bff85ac25a, + 0x60564813a0ce62e4ac21a85ba36fe359b53e84244f908b866568084e31c4afd, + 0x2268a405631dae60e8eac4f408fbd5268b40b1c254970e3c22eab22fb8ecc554, + 0x300263f7d8a2567496a37ab94c57e2015442257c062ecad9d8412f6c6ddc0089, + 0x1963bc7aa03a152df1eb518cd9588bd04f3fd21a318314fe0e54c1f369be3c0e, + 0x136b67c2b78e28a9c5276c6fedd9afad286d344700fac868de5548c404abee95, + 0x29a329f4a94c6c6c9fc81e8cd90f7f1c9e5f6c89875a280dd9ea0b4b90b8ad2f, + 0xc3d92aec4b647cb21e6f0ebb98ef3c65c3450672ce4694f49f39919ce6da1df, + 0x2f5235ceb5912869936811f841c3ee0f648bafc9edebcba4aad0168d03f9b52, + 0x63a760609f24b3692d205c9b3bebfe088c215877de8d79deaa84dff83abb2cb, + 0x1965360730aaa2fb621c470e9042cf5db28c4824575c994b255c92b02d0b6524, + 0x1838e4b596dc759d6a97b0b763d959bdffc4ba10f84ab4b1c4c71d50a924d179, + 0x258cf09bdda431facd55b62aa65712248056e3edd9428b010a809ec78c41ac86, + 0x1e587e52329f0a29bf3db7337442690422a9722e228dec682be39df28b3bf14a, + 0x120effe3050205b3ed1c06aa186bcacbe860b61e77bd06b9b71e78a710a09500, + 0x18213dc619ab928f68d5aac28df923f90282b6ec64d5ac376880d31fa3bc1d5a, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x1f02f7e2e07843a88bcaa2797d91edf88cbd70ad743e938e35396628fff818c5, + 0xdc5a85d95f105d8e4b18eded697c62a032136374296ea9b14f54cb0ecadb9ee, + 0x219b60e6d5a22578775e83f4474206559204025913238a98fe09297e6c473c8f, + 0x435530e014db11e2bfcd58362982d8a33e222783a5bd6db56bbd327cc5237d7, + 0x28c1ffc5c10600c0dc9dc3d193bc58552b235922bdf46161b6f8c4cb5a6cea5f, + 0x1bf7a2f7bf358cd12302582a3b02600994fce154fffc218ae6442bb46026f98a, + 0x179d43fb87170d3d97f4a0166d1663da78664d328cadb544dbf5d6c5d611de99, + 0x8cabf5f7d8a6d458bb6576754fba5a716ae9e484a668217adced3296b7cccc1, + 0x177be1eacf22f916417a28651e18d379eb44e5c2000e329c1d3c8df516c1194e, + 0xa5fae0f09f85d5ab6b22833947da6cba0daa2a9671ade494b7f9d8367394987, + 0x28df87b43e795b370762f1d3f9dc2685e91bbb7a6854acc152f705c89db4938d, + 0x58de2c0fe8e6f09f1b853dac8eaa473e4f6f80fc20e0f4190875d94cada6ecc, + 0x1ba657cd2bdb97e5d24bdadfe5cc11a7543f54c18e65039c0e616e138de5e368, + 0xea5b3a4116ce4ad61e32cfbf9662a60c542aac16016d551149c76700ecc44f7, + 0x2c219d3a2b0e433c1ff243db27a237fe15c733edf0f0084d7a5ba40123fb7361, + 0x19ad974a2285cbd14d04045c6414f199a891524b798cf1e3d692b742cd6d89f6, + 0x2c7d9c944d792ce4b7535207891386b722458c54fbd627ba39521ab9cbc1ebc7, + 0x2e71a3a451566f8919a27edb83647652520bc5b920531fcdcb2859a5ec77bf73, + 0x6a4b1b530cc5e64e84e725629950bd7644f65e7223dfd4986161de535cee83b, + 0xf55042c0a72b5b62d2107153b60482981bda1190bc8b8ce4e30ad101fac7464, + 0x20378dc7686d64b35b84440493ca10a587a5505169d380fc5c5f4a9ee803fc11, + 0x26c526f859170915382b65592aa1957e73f3145c970cd7c891dc86b7d3cd41b3, + 0x194c4e5ab7214877317adfd216f34310e5bc07da13b67139dec08cc25bf2a052, + 0x29e0d646063e27cfaf0e4ffc0546f1b309333958e0ecaa3632bb9fbdcd0388aa, + 0x121b4451014b6382209a13bb0fd2727e59f0702a081fd34e04c8ddeb87d349fd, + 0x3018ea843d3f3f525b9f96b6c6c07e5c86d4a113d183cf66141aa80960048ef7, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x26a889065a9131ee8541587286f27b8ab978d106cf21e7cba567839eb83cf5c7, + 0x12f2322938e02f96227e539152719a6fa62147cf82937a0c980eb011c62b01d6, + 0x2a7052a220aa258284d8bcb1e0646c0266349044ca3c17bd0bb628ec5422a75b, + 0x1e01d825bd60d76a2040b5de5e43b90d1bfbb0876dabf550baa3a5dd47ad62d7, + 0x3002ff6560000420d0de98e87d335432be4a58ff3eea053d2d332354cbc22da9, + 0x3d28736a2952e396f2de28f3a567902027214706657773431d54cd10c0a0464, + 0x27716d5bd3e14b61afb8d6ba91b27739f9075ff2630b19c6c2c26c5d5496e195, + 0x13cde7afb44e0f9b6db2793a51226e40aee9d5e7fc75ed7c663fc2d06e9b8526, + 0x503aae89801bbfc5f702f60ffa566477a634dc17aff8f9747d1fd1fbb3cd336, + 0x1ea910a5da3ba8d8a39930b38b64ffce7616fc9c8bc7fc1fdcf12b650d04089c, + 0xeb1ff569a325e123ede757ea250df5f41f75dd2b75c6532ab96dfe64cf7f3e2, + 0x16cc1752c575ce984729208e79714c336bc3224f951fd6cd0b82a2ac4d43f892, + 0x2653378743d2eea387c330a375bb80e67878a9740fc2425a36315206a140175a, + 0x175b14e3bd393d825ff9560dc4ee5834c69beaceb5f8580156ef162c6d36369b, + 0x162b65eff59b3bc39a2ddc923c77da7a17dfe79b7557b8383367922fdd8aa5e6, + 0x297d9796101df9152043297c780dd5137e6bb2d9a25a8fa92187b5de2399affc, + 0x292db1438ce4bced35048fa12b049bfa359709bca7dc314c937f0514679f0d24, + 0x19c2715e87c332adbcd530ce981d8704f0a207e822f190baab421d4d03d24bd9, + 0x139bf2e121b6694f773a58f70956cb782a37e4949e482d87dc820b034ffd0f28, + 0x281e06a2a3e9c7ad29265b2ef8c1f4814adc59e5b3b605a05c3cce8a59e321d3, + 0xbaa4181dbff92f83386e95c6cae0c8efa07f0cd6e822bd3769e4ae8c64e7d9f, + 0x2288cd08659c856e697d93558197d16c03fac590096ede68e959636d09956d9f, + 0x2af86b3b3cafb3ace42a0cba5c99dcce7b0fc35313b2edddf0401bc029373c1d, + 0x173806fe4b0512b715cb7e3cc8679d3a7a4c2b7174e8cd710574b3c142b8197d, + 0x25b66da637a8d92f088d8faecf034ab77e2b2c3f88fce5c560922f648eef960d, + 0x12f5922b95ad36bc7a81c2fe8ffc729342bd3aeb1555969590bf2248d70a3e91, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x170bcf0294ae4059d95f36684abb4fc2cd0369a67be4bb919fe185aa39467569, + 0x17d247983fbaecafd39c9dbb1fc2633ee7ccf02383978abe8bba05e7bf498144, + 0x275c74ba59d68ebd78d02ea7bfc087b17708544436bb5438b41b053072df4836, + 0xb97a196195430ef69cf23dfd0906653e5808c3593449bf58c374242ef82bdc6, + 0x25bf621be7fe04105e8a50b02ed9025840affde6bb3bbdd06df97f2fe9e02e38, + 0x296928baa83c1016ead86e5c9011b134d5d24179b1970e68dc89794b73d024d0, + 0x23e6fc3b8617b6b51f35d983c470a99546099a6361ee1626e6e44e5e3e2f7dbc, + 0x1b9b57f457f685d54e7f7f332af4233d293106f56ac093a07c209205217108b6, + 0x290f0ac712987d7956e8b4dbdd8b6706399adce9506e3373d229d45605637311, + 0x262a3b6b3986c250d387fcb734cd914f5e8bb751b571fad1ff366a479e3e6538, + 0x295b88ac50fee49245bfd9bd911734324c8d00abea718917a4dc6c21b3e507de, + 0x2e7a6894330ce6d6478206619aff889fb1bbdcec80e6f09de69398f344a4f6e1, + 0xc3bf1bb2ee94489afed3633b8ec12dbaa4b6a2003eac80e7f1668ff340bbefc, + 0x2d61629d203317ea4449e200880be2ed8421aa6f2de73aaa56810fc304eeaae5, + 0x1d94aec8d967eabceea3de4acbd2c3b19fee00212d2dece58d5ae53bfe6037b6, + 0x2f76d72fd59722c377e315583f91b326ea792968fbe6bf73582aaf7af697d3dc, + 0xd243da739e905f8b000912519379de3a3bad6de3c3aaf91cfd78f9735b0c1bd, + 0xacfdf5f69c09506cb85199eacdba0b9b3c5a0fa1a60cf283877ff7efaf3bcf7, + 0x44de47687196189473b125ea91ec1ceb1481f8f49fcd47becef1b01f4c9fe09, + 0x27e155dea5a1134466a8e2ba58e2b03cad8c38c20716a7d3e78c483b019e79b0, + 0x2860ac51f3e70148561d5c109abdb096225aaf9b7bbc17bd7aa31ad26e243e75, + 0x1a33e054ae45916951f73826b9badc032ed3d0f3c21acc7dd18d46f268cd2a86, + 0x237acb3608d9158738b6b37b6f6b287531d9683bbe16b463c946b752c089ab8, + 0x9328966036d95ecd345f77dc984391d09732acf567d010b855e0422365c6209, + 0x6a41ffd9721ef018d7e9e2d67b8d9820d6a80be401e1617e07b29b3c5f8e53a, + 0x1bac3b3b9cd40ec41b542b47ff0dbda03997f88a37aa23de69d0d5113e5b448e, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x17dedb52641d9f9e688a673980bf47c462346d1d6731db6bbf0c27ccb2565173, + 0xd947949f35e75c29a986ed662cf1e1d85c2e3f3a9489da6d7a6a6573bf3bdff, + 0x2bdb20a8327ea3f509eea1f81865ac34f7e7c5dc43d516294a29c208cd0bac7e, + 0x2fecb170873731d070ccec6d88733be3275e5be22a47cd294ad7247cd75247f6, + 0x1183c981f815c35119fe4558a0aea9f533f9d7980195d96d75a80cb1fed40c02, + 0x5fa320ab5dae365f8a114d10921a5fa13f79f44f18b57021a483eedc2c5bba8, + 0x2b951512add2c708a010d1ca59bed166f3726cae5cb1525dd379156d810e6c2c, + 0x11f646514881127c9f1067238c06a7ca39b9c1a0234eb1b8658c2bc70404578f, + 0x72413e94aca278eeebaca63c7941b548147387d21578f97e58ec27198fd4e58, + 0x2aace8cefc1be4d4175001aebebe91fc87a46a280be0a90886383ff2d561d7b7, + 0x69e64230343d9ac3c6130b300cfa24cec6086c85a1aa1c8edd073a7d33adb2, + 0x1ce84829e4e67cd9fd3bcc8d1169a15c731e06ba76c77ad60e84b045d5d731aa, + 0x23b52a113ac4ea90a8330c189a63fe9520f2d73db94406abea72150ea2b7ea0e, + 0x160218f2b7e2d22653b3ca12190f5538563aeb27ad8ac8f2f71943bbdb0c5928, + 0x84c1a87e7fed6aa9c80f455dd132e06f897f43b6bc12f3f5ff56a4297eaa153, + 0xcecba653fff37ab5fb266ae654c23b2cab83b0f7ba92c706a078b4de3221adc, + 0x2ef80d5e15aba6b2652fef7e0419167f804f2cf713200eecf30682cd138781d1, + 0x14bd930a77fef4cdf7d47bcb46ee6fa596c43e9dd40ba87a488c613d5968cb58, + 0x1ced050594cb02e43a97cf4126a5dead21217e9b5dec28ffd803a381ada6dbc0, + 0x2efdbbe781cc22b39fdc48af3424a354c48ceb17113136ec794a9b3319fc9429, + 0x2070e4e04671601ccd0842cb7a374ff2b93838af86ae464f82ceae2f1539c1d8, + 0x123741e7f63e77fa3e2d8abd9f222b23dbba1c14e8af53385cad56594f065e1e, + 0x1b75035c35b201efc55a1d47aada8976f5fb0dc1da22482a6b61d33d555eceb6, + 0x25d76dabc919ef40ebe597d4bae43fdbd2197e9b0f7b7dda83a1360295e9fcf6, + 0x666b59c9ad666ed3fc9d1e9af97fcf7ab94ba3387573d8d31f03084f9e5c976, + 0x654f99795543eefc6e1b1e646108896ea5161c9c9a5e174f2e1cb9093809b4c, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x2a4984518cf4d03a9b3598bdc254484a1805160612b943ff7b509637f12a70cc, + 0x36731a2bdca86fe011dd7bde4043f89ca492084165aefa6ad9f74717ed54536, + 0xf5fc4d1e67992e65abcde194f07cb07b72800a4f4a26e5020e96c5d4ae3a952, + 0x20d02c9669942a2fda0de7a67b8c5cfca08b2e914f65652a71044ac9a09190be, + 0x20b3c785c2072c1016dc316a7933ad541fffa7df2d289b32799e106dc4f9c1b4, + 0x1007df7ccc98951aae782b87985756784a1444531492615315080e2c80a33131, + 0x223a10997957b12816110049ac7b56d550cd7a5c0b47bebc1f8b35167189b2da, + 0x358632186da4fff1765d4d688ccf425c333995bd7438240be0cce1428717270, + 0x216b1f88bf14a781c99ad7a394781182d40162fddaa8391917aca465382be039, + 0x108441368a058a30c565ac01d4145056d5a5614892879844c07a1c0289b2c928, + 0x3df1a412eb02d17bcc82088f46cb5f77ec6279ff7161856c52480d00554a366, + 0x2cf2d9f080d1219e2dd3d7cda1442b178464a583260e6d9632e12812b08c38b, + 0xff8f5f8d239c9afc6c9d041ff0805ee22c3ef3cf5248fa2ab198a303597d82f, + 0x22baee6a9025f961d95afb122fe50ce73d0acd9a913f2fc8d07a050f4de65dd2, + 0x1131e942fc36296247e9d9013e71cc89498a7090a683bf08bdd23e267340fe1e, + 0xac6a1c394f929725acb0a1b5e11ad9e28aa1c79da25624596451b04645d8a76, + 0x3cc80ba68d89cdcc935b0d872d775b3b8f2a0cd50df89edbc3a6269290d6950, + 0x1db513c2f29ae454a99bf928ffc2d93fbc363d0bb6cd0bcd93106d1bfe5f789a, + 0xd05dae2a4b1ec3585f98d84bee7d10717da3b17a71281672e3451916260a301, + 0x2adcd4c6f191ccdbcd5a98bdc6050ba95009e2039de7f0fd9bbeecf0c4f1ecef, + 0x4d0d5708e1d87ca69eb4d44350313730d9d8403801606def36f035183ae03e3, + 0x11184dfa1ada7118e79f8890036facdd47001b7b63b74c3d2983fceecf3ecae5, + 0xd32f8b975e939f7efa097c2a3d4cee8340deae3012758e3b3a4ee0a2fd193b4, + 0x1a24e9162049895bdba49f57cee0396e4734bcab60d8ec4305a5b685b3ca66ed, + 0x19873998ebfde4a585f34a40a6e1fa702b7fbd29b09aa141c5a878e448e48e2a, + 0x2d055b284ae3e229cbe0d4901ce6b687eef40d815da38cde743f3851c774fbc5, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x301d2bd94a2a85a3c802d0467c1cfb28e2aee547d2f7d51c2af108a549462a23, + 0x19ef6ff9413f7a05af63f528a7f80dac32bb3fe601e02ca15feb99f91a844d0c, + 0xf1cb5dd8ea58b523d3e9d9de030ea9db932b770ed97d2755da22a1512696ebb, + 0x151ec2edecad41d2a4a74e8b09748ac3d11acff9c8a825e0f0c539376313fc8e, + 0xbf605154c6e6cfca764590093b09ecec2e38a0426d4f8f0f6f9ce771d4ccfcd, + 0x10d1c2b4f3622195ccd9bc64ab73145907e7358d92beb85826770d174810cf56, + 0x79c01911499171a82059606f1a0e1683eb2f076a4a72314e51924b61259fb79, + 0x1886095782a7c6abf9faf6549080c2a72f8ececc22bf58073df90be6920473dc, + 0x261c4081f13edba795488c906dfa2b59917affb44cedf1727cb27da0b0b2c20a, + 0x2cfdc7ffc3609e9d82b3bd1f2f1d42e15d1e0b7eb24719123e0b67d060800dca, + 0x3c9ce71c00e243a950dff0d9e0a5d3c42f823983f6c1d3d50e0de1822993d84, + 0x13714ab10fbbc54e15fa5ff0d6bca9846fc940a9c6bdd87b044868600f89bbee, + 0x134d4838b8c77e7270460739fb444e60580e951d914a5a20493a2b03d294890a, + 0x1e6f53eed7f86f7291436624847ef6451457756a213c168c3bd7a5945a4f2873, + 0x8c4e9815652721c5293235dec1eae97fb8f93ac48d86c37ad6adfa77055665c, + 0x18d007112ac9205d16ff209b80cf0b5260387ce770d4e6978edee9e0003fabec, + 0x5140e8f5d27d7248a3e50e84c6bf700fa31c1a1a7ac144390f4bcff5ad61243, + 0x19f153d66e44c662af026dbe5be9be834a10a3dfeae59729555d709d61e38f7c, + 0x11e0299ac3f3ed3ee71377dce3b85768cd2a6b65e9d3bea24743d150e19f943c, + 0x190ab7e9ed8c741d54fc558afc96b35d9319d317ff6d6332ae4ca77a8a3a7911, + 0x5bf8fc4ad0126d42c22ed2c659b66f053ca3604f0968520ce5c7ef06c5a8793, + 0x28c05200db6d51df10d8a4986cb65c078001f295343de608d68fae45cabdc5f0, + 0x1d64d0d4143f869056ecb1026a361b48dd5162f38beefad1a6d139843d3dac9a, + 0x56869389330224064b29f958f37fe90fc2bb4dc2454425b0d362b892be0fb73, + 0x21124fa7acd6d96ec308ffca46465e5da69c44814c6e40e705b7c6b4d7eaa333, + 0x210de4f22732824523dd4fd0587eebdd78cc339e8dc44fbdc2a317244132f7, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0xc231a81780a5f9babc1f4137106d456a5cdf0a356e0c3b79b330982dde6c5db, + 0xd2286ef77f15b562ba8316151a92458c52ab6979d36481abb6ee9420befc144, + 0x14cd6adb239444df9b510c5e1c2a378f3ddfbc75b61371b688931bf3c6ec2563, + 0x1f94577cc0cb87a180811923adfca9a8cc77b8ef41c0efef36e1b319679f0f10, + 0x2bf8ecc53796cac7b1b4b8e8cbfe8f92c31f726dba638783eb063b675fa96064, + 0x2443dff5793f12826c9195fc95caf2162cb739d837c4e15d426e65eb20c44884, + 0x28807445f05857e5db18c6ba6c0f3d67cfd08d7ee0a1b5a3ec259c11e57f6581, + 0x2d7181a0eb717fc3d9554bb1996ee527cc29fa9dd3ddebabf346725d84389a45, + 0x1d467a0dad4ca6c95707e95f8780ca40fcc983a7e1171b111a8874b122574488, + 0x2cd6049a0ad06e9a9a9eef6333566fe7558db0007e6e92d71250ce582189453, + 0x2ec06f373cb79c1143d0ead6ea94a531574b642a2a88ed6cb21bbafbe2932c57, + 0xdadde1785a6e8705856c47207ee42045dd0360c3cb332e866dd032ef9bad925, + 0x26ef0863b7b4eb4223c88b5864b903526d84ff81c099ea942fa99ffa0e376678, + 0x26f1a2490186a61de95667c8672dffbee6bc1451ac11fe2e9d159d308f87caf9, + 0x913a0a4317ae24b6cbef39c87f10a3f47b4fa74b6e7f9286a6991027af81d6c, + 0x101d691311e602f1bf45e2bad29994880376f57804517525eb169240d21ef3b9, + 0x1c55eab0a94644305995dd5b9a4f2724390d88fd3e982be43b01a627accf5b16, + 0x1f788dca1edff5172b4e948868bc18e7c0ef3602033d72ef3227f8776bcd40b8, + 0xc5dc41e36fe501aacb4d8f8d33b12da167a12fcdc10626a1cdfc90cc25cd819, + 0x18a6e567865d428f2dbbb6e9bf298ab8958c5d1737618e5f1c5679c76787bac7, + 0xcdfb3e5975fb90caee98497768f37dd465586e1669d6bfc512b32a3895c62f6, + 0x30edc8429fa6230b5bf9553ce19f0a78055f2d68dec10957d0d64e8a3bdb3e, + 0x5ff6dbf8c00e9f32a61f908e6fa7518e49ce0bc92dab519524887ad9bcb3a8f, + 0x187c0035a20f42bb04a4d3f172d8dd71761fbe16405a0c73658a18e177012b32, + 0x267e0e37151a8018949bd766e65170ad7944b54b191df4904b67d181a3b0341d, + 0xde2f39c45dc6b47bad47d29d8ce587e60c432bf03f9924e3d70152bab232ead, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x284591632913e57214bc02159bb3e8e81c06bed2fe6f302a3d238f14152cb3e4, + 0x2f6110333487576bb66188bb38170601a18b160a41c655f55b366e138ddc3c88, + 0x10e8a25fd4ff737b1fd8eaa1ca0fdc107a1d9e48ffbcbd86fe2b388dd10ac80c, + 0x934ae9d36b935e477c1d92c9ea1b80bcd2d81f3fe0e37a4df894293f7ee2e0c, + 0x1d48097697bd76fe5b0fe21d8c182a9a032700c0aa94fa147765147a66c7a732, + 0x26a007b8e7c5a0f095c47c27e9a68c6be8b08766863ba33854b2dfcb6c708f74, + 0x1db9c979d26dc221830cfd85bb16b9bf6e6ed9032c917ed64046d24b19feca2d, + 0xeb6abf55ab892abe5ed8ad7223d04460eb7cc6591216c260250ec0ea22852f4, + 0xaf52963d2d8ca1d85fe433b3e20e360f488dc7ae40a074925f612959482fd7c, + 0x21a08ad9c5da7fbfa096b1773acb293efdb29b76a2b0d54f107110e7f7e7ae8c, + 0x6cbf675121397f0657bae080980b2b22566613e0501f74eff8f71826a5aef4b, + 0x31a23d2ad653f7306b849eff0b4373a7a2eae9279e8f048279d90241561b192, + 0x2f086707d317470467a8e0ae03ba725ef79ed1ef014395b67ad4da788237769c, + 0x24360122ee8c5a9ceb21696d69d5456a3166419377b098388a2f19966ce62005, + 0x17c0f7d233d0fbcc5c520f1ce3a5d4b095bd11fe8f39f090ab7e9d24ebca8195, + 0x3f293140b7d07e158f63f94792f943632ced772d71cdbd93e171a98a2bdb1a9, + 0x280d4d680de44f4a35a8d0baa4a1feb3701fec97a152e977b5352563c797f68b, + 0x1633dd4196cf695bfb9e5138ccbb381b0bab619ad1b728802c0e9b35770503e5, + 0x549cb9c6b3ab14ade93f695dc31df816e13e6cff79023f91c5ead9311fa37e0, + 0x12dcea4ce3927ca8c308751550a77c5ce4e095e0e9a417108c18102e4b0aba31, + 0x78331ac4c2c6702655cbabe212124d4f1a1f5005a75faf2c6fee507b9996541, + 0x5674b32b037c937ab00bb7ef41befd1c0004014b66acc26b117bd0b462870b5, + 0x165c541ff3c38f4a9af878034316bc4c08ec15fcccc77657e7aea32c982e26d9, + 0x16477e2f6956b2a232be8389586b0569feefab7d635f173ebfcaaa06040441db, + 0x1698424bc862b0a96fe6843dd5c7626ae0182d50f8323c338917bd9e8c8a8744, + 0x1dfbc6764488855933fe75e10ddd60b09d67d98c622f36cb565931d97e922988, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x2f722fe53b252f8256f3c9d613fcb12205dc97de726ac8f23c6d4ee0a9575add, + 0x4ce7f85039445253ecbcbf393061759062e52a54060331db27947bb0e04b101, + 0x2ad1ccb6918b4dbb68bbe0389521d418f1930df1cffc91de8e8ee648a6a4e62f, + 0x119ab9bbd433ff01c7e43079d288d053e7e0c4a76facdecde1a77d544906b4ed, + 0x17d263f75f3d3f0d472bce50e641017a291f8466e6c03a768c138deb1b50f3f4, + 0x248be6746b30e18cc13259078ec848411532ad11d4506ac6ccde131495c9fc42, + 0xb02fe4295790760e1fa72811dd63502ea36bed8eb8652e6b35f4faf9b554312, + 0x148b519dc0b5daa50f0073094e87db4449c8a068ccd109872696973f9eb806c0, + 0x1bb5e7ef82c1a2a02827a2f16a34cbe60209f8475d3bfc0b6652e61f4113e6da, + 0xfb76804e630b9b522d9af08f1b53880f5cdc691bb22c27151f541fc8e1bf2fb, + 0x25f15fdbcc16e5c1ab1066d294bc774db9166ec45d4dcdadc4597ede1da532c8, + 0x18cf6ec7ac6dd943c57b9472b58af18929a94dd92a340b3e43c074f62b7cffb9, + 0x28993fba9683f72a8727701674e3e657fdccac4649f82879df4295e858857317, + 0x1fdd6bf585ede657728a4e97eadf195c08f8e6144b28bd92ef6cb706e4f6b05e, + 0x1810b0fdc26d123bac819ba150ffb6ac9455ada7dec6deabf178f0dfffab05d7, + 0x17935bc39ce241e78bbd64ffc72166b8d8054be62c494f3b89abf88810808fcd, + 0x23b66feb87a9b7a105923883b0ea0c73f795e445e3cb6f68c9217cc0ffea43ef, + 0x9f6acc9470a3ca1b06e023cb2f6d68a46ca6c434c521b2d0a799cc3f7b29a9d, + 0x7059db933a49a59d77c7dd8226ea452868ab183d14aa09ba3f62011a08ca31a, + 0x110283c2d84ef498d54d8cc89f3ccd48990382ae73b8993a3644ab9961b71141, + 0x2e0861925cc9b76c5b0046d8178cb36a13b26aa4ce4e5f7d3be453378928627d, + 0x186d7f00229ad745a0123ad95fae9d1136d4dff9fb693f954ad9fca972ce9d89, + 0x22c7a666156ed3e7813e98f60d15e23a461d2e9cf389a581dbf8be0bf5afd011, + 0x1cdeb50c6bcc3f9cd2f59588fd72fb929034685f88506e891f41dd572c67c360, + 0x2978a2a151c95155411e8acb3c12cdbcf929d675fb978e636c93da663800c33b, + 0x167e72f7db7e8e21f7daf4f02fa830884851d562c3b51606b52ad3e80d4757bf, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x1957be621bd6207736b0374c7077ef66cdcfa4bf575a16d2724ec94e2d764876, + 0x3b264ea2c2a171ce3bc6672fa95706ae37155fed16218080f33e469bc9b6e54, + 0x1cac742468595a01d58239fa27bfd73e5e4c811d31bf2307e3ad7d9f7a440c82, + 0x1308e2503e1623793102a3c6ef79b0041696191d4cd1a089d440e717d15675b6, + 0x135997d11a8ab3d418e1b34376d3193d0b8355902aedfdb2f29aa43278e2790d, + 0x6f8a541f16f9f3d8bb1757aaec5ed1fdfbe7990e7b046fe6deb8c6af212ff4a, + 0x9a4037450ac7d74675a6abf0169890a2161dac550cbdbb257ca22f4026ee4e1, + 0x1bb22813c573e8209b7100e77ef81cedf79e7ce616b229a7540505854c2612fa, + 0xd5235d7acd8bad965dbeeaaac39d599543b2766dad81dfa738988f8c4fecacc, + 0x24522e82642d0c00deb6406ab28a1867dfa50cd6d0ecaa0e18b6e5824005abaf, + 0x51808f718e4a3898d1266b473a2e0fa470b9ab592f9e1efdfb177a8f1b1a863, + 0x2ebf139bad53a7408b452fdfaf8847141346688e05da4e0e5b478c178bc36c17, + 0x18f177bfdabe5eccaa6dc0fc28f75e20dbd9e470ad50337724be79e46f4b4298, + 0x23f5e3e09744ca3e73ff2660e40ac6b8152e1c0a93e507f311090e6574458779, + 0x23fc5867bd5b4d52686ae8ebe3c1454e266bc576aec1f682bf18f783853d8527, + 0xde2e3ab296be75fe02af329d61d80c5c4d29886528315b4698223699ec70de3, + 0x2f4c1d3cf6793b0f8a707de4909c1df3f888a37f5f8e382065b500936c33d207, + 0x26bfb7031fd16e59d70dc1720d4d04301d97e07a0023e58765b2b6b735b02443, + 0x8f0bea4f928caae9d19e71f19dd85c7d700b1b05b3170548784677bcc4dce73, + 0x206dd86edb0388abd591546b376a7ae6dc433041b7d248ea75d908c4b3740afc, + 0xbd896df632e39aad4e575444b0bf49de0e10183b09137b8f79f704cf2feebe6, + 0x2188116488e4192be2569647ea81c6caa45d08b896ac14e497ded7a6b80d9852, + 0xe95540fcc2df2d1f630191f9e5f48b7e4695fdd5f4e9a7c930f16598b3e9e53, + 0x29d25da59f9b238929d0eb4c669216770673bba9a48a1160793ec66e75259040, + 0x998c56e22c0fe57c936f19774ec4368ff33aca06589807db3a1e8138395b4f9, + 0x1f460a24b80724cb88af9fd2b73b512e6d5fde9ad6d0b73801db0cae1d0c0357, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0xdc5b4d3482661089384d18500ed0afdb1a635c006ec67b3137ef97cb03d27d0, + 0x22c7492f2fa7b9f297c2f0365945ce0e262793331d3cda1cb73d083fc8a0e21d, + 0x266af95c1174ed0a5781bad21a2397578ec4d16642d729c4daca8f14f6c86a91, + 0x14c46169d20fa3e4a67fd8da381ac224d61cef48dd27c1971273519b6f9b703f, + 0x1269bce1327ee515c7de22ced7aa99a4df202cf661ea0f2c520ce2a721a640f2, + 0x172bcf2621fe4e5c2919490728ee5d19f6d1b3db328addcb2f70a792490e9bc0, + 0xf26dd040a3d43e4788c20be85b4bf774763729fce73037ae53a5f490ab99c49, + 0x2fe304bb2aad7c3a3fe30b77087600d1da7ca2d9053f7ed264c1865cc8231907, + 0x2e365d1b4f6d9946faf2ba71fade06bbbf2f8475eec5a56fc4843765fb4a49fc, + 0x25a82f1231627dd4fa32b82d274658a1b64e8ebad06ee903aab649e32ffadbcf, + 0x2cb9324b95c056a7dac8511562fdb8049c4f08e6fbd3ee222bab96ecacb89c9a, + 0x1e3c03ec4cccb96e93e7b8fa96f6915a0ea2f392b4f5ebac5b2f251013fcd3a7, + 0x21011730617a2b7c760f7758dfe37725189c39224023ff0d819dbebb1a81c07, + 0x28b05c0a2e98dbe8f090863730a24b597d97ec3adb4a00f3f1a176d02f495138, + 0x27355701c30ec033287bc103652855c341a8e80aed9b0bf7a1633b3f0ab11a43, + 0xfad7793054577536c56651b9585ad1ecc2af28c4065c6fae4ff47df4289d5f0, + 0x21bb038dbba587b85cf0fbfcd5e69de9f329f6646bdd40e8e27a107161f624b3, + 0x21b1f094f3e78cbf60067b3b785e3b3f24c4161c91c452318ee990e07e225524, + 0x52d8b24d73c86adbc8311390a5b2c9b6300671f92717203ad7c463bbe0789df, + 0xd7039ff767a3d8bb07fb62d6b2ebe8c543277e3da1531da94cc861d4574f648, + 0x1b916f0851986c4edc2b927aa8bf9d92178ebe75b77552ce47a63ef70409bc03, + 0x33cab9f4d3c360924e9227254f4f9bd52fa7712fb518e534f9fe69d04d994e, + 0xe26a5327b3a023b0d1a432d4be5f7f0b09f8c4143ab881b985f2cf7e458fde4, + 0x2ca57bd0c629753607a4c9e37b783668abbec7e8e306f75b88ba97772d371595, + 0xb7533836731172ac9dbb56e54588a5eb800fd80d6754af74fdf13460c340ef3, + 0x28c3653d647bd221d2b3c79f3da382a937cd1be9a33232748f04f8e1c880bdad, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x7fc230b6a36abb1c7f4b7504fa51ab01aa880f7b3c0a60eee1637ff68889dbe, + 0xbbfe36421ba52a2fc87f6d7976aec0165e41aee0f71cbfc87f41b6b965ca6e6, + 0xfd2424b028d4d8ac1a8c66e6306af2c3df213a3a7979e367c2957eb631f17af, + 0x1b674725a1f99e1dfeeb07dffa4d961ec24a31d433d83f858cf3ffdfd2fabaeb, + 0x12c9cc35e0ea2482935ddba214f21a8c08df3dc9d6b29f75619f9ffe0d055f10, + 0x1ad3b10f3f584f4811c804d95b3709ded70c5a7d3bbbf6f91339943d85bbe21c, + 0x2abfcda5b9f799b2d0af0861c17c33253781df51eb186a65eac958b34e8c35a5, + 0xd9cf52fd20c189982504d02aa80500a5c732434dfc9e7cacaf08ddc0d0c76dd, + 0xd87620da15c58c50af67bf3533b399edf83c1e7dbc0bd9773d40d5ea287aba4, + 0x289e55051ec741e27389dce0eca1cfc0fa57be3381c12943fdfc6aa392b60af1, + 0x285ec1799c195e638e16e4cc7fe5bb7ce06b1c82105cc4d61385dc2d2ecbb979, + 0x284ce6e7141920ad4159f9c97ee921a24cd188718f7000f1ccb091067d4ddeed, + 0x2403b3f3f99fd0daa8ad77cb3f8d515055cf80d1d5e8d32e4e4627e95489f57e, + 0x2ef65bcc67502169c5c5d324e09297b7253302c82a337f00033c814aa33d9cee, + 0x2b1ced8656b92329d623a85ee61e310495566ce4effcfefb6e6606ecfcdbff4e, + 0x2cf6166a9183e66bd94be5aae54afff0f02cc6eb68d7456cdfdd86e0e7f0719d, + 0x60d392a31de88d78b696e7238af3ca3eaa5e412437c66e59d7049b69d2507c0, + 0xc2b62bd89e35735926f6474264c899eb2b5956738a478b6e76d792bf420cd16, + 0xe070af64e603d24608847ce8677d0291e08d5c10ec31f23d898d716f1c39d1a, + 0x2de645e3763155f48ca18d06dd21370f314e26382c6c9e883d84e387bd892893, + 0x17deebc35147ac645572140ca181a81785e74dfce063b37e326ce6e79c66a6da, + 0xb035d43bfeca4b7a464054eaa0f892cb035db06a3150ad9ce1ce45f6ad0b811, + 0x100c78328ef5a499443541c1e27f78d0e77f65f93738e393bdcf4b098681be52, + 0x180cd1e5a1262087a60bf156e8ed528070936923605d5fb078f4f6f956a55aef, + 0x1409c9afb266f52723089bcc3b495bb15c9f10cb55b32b73dead030f87e6e24a, + 0x100ee62d3a9d66d3b6360f540f954493d7af73e6cd95a10ddbcdd79d6739fd38, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0xf8533b51bd9ed54a1703fa8399239d3a7fe77b0a55210917343e09342a0fd81, + 0xa38a8515b1393a083782c40f7261e921d87155c081b7039db8f409beb2dc8f4, + 0x1dbe26b8ab56c6de11196b0ffe7355348b99083a94d2f2966d227fde43821f7, + 0x2fae58b811204fbf3232b298e274df120020289d06ba343bc9532fae7ccfa76a, + 0x2c33c971128abcaffde44567163b071c1c845d5e04e4b3e4f3256c690cc61efd, + 0x1d6879298603d7ce919895eaaf857157bfaf20b46ebad48c36e85927e004967d, + 0x154e2b495b2894e24c7b64fb83c0473186b256f83de4e7b5f82abc3e97b9d176, + 0x1108e6590ee097d6177f9b0e8f6df631e91ca6aad1744fdfc36a5a7cf73689c2, + 0x30e4cc0defe07e0c0ffc72ec35cfa5f902e564359dc27e6f500c921db4f22c2, + 0x1c4f81779c8633490f3e3e276603162c4a5e42fe6db58a53316f805c5c822922, + 0x2954c55e5111eb033ad80c867317b4aaba9d750b9f9bedbfc48abe8430ba3c20, + 0xd519d7237511791c479d178f6500e54532625fef17aef20782d15be156830b4, + 0xb18f5604bef3748e0e8ecb40e7f636d2452a42ed19299820a5d41241e3e27ac, + 0x2719c5dffb3c5e099e2ebe58e16855ef505dd10daf7cc2f213113ff647614b42, + 0x16e635dbb0038d05bd950a92b785afacb3fd0e6b86cce3d242132d4f1c1c0ce, + 0x3920a662038566aca072b265532745baf239bb3e60326891222047605015b23, + 0x2c4f137391f3b5e4e6024a97f1c9cbdedb1297d123add7adf4d6461ae5a875bf, + 0x2264a7d603db95df9f07582fb03dce9340e2de326cea846bba043b0946f812d9, + 0x2f1f379f002c49094dd938433a986b519a123c4d9d0189d66533665d0745067c, + 0xd29276a5ac511cfc3a3fe7b9244d4b7010cf0bdfa90d7df0d6c4000b9585d45, + 0xac3ab6802fcf30b3b6d2b1a69e54b3699179b4f30b464e0b71b6b4b6b1124bf, + 0x2dc0c34175e61183601ba4dcf9ffb457defd36abc2e24babedbb0a9450155fdd, + 0x6fd088a7bca20b5570d68665ae17172c13bb3698f3640cce22ab74ead7c5663, + 0x1de87003640c024ab5d55c378a74e14e1adea072f8d22ee932b49150dfd1126a, + 0x2e01b475d78e669a868129b1f173a77a0b28d82a89b4ebbfa274a0a41eff3e06, + 0x1ba9c82ee2f9ce1b70390faa1d3c40585d751775bc8596e32acf34bcfd58f814, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x2a61fb95295b3b5c0949c486673d1ce6ed7328f42c9dd1c82e27fa3dbb0e3bf8, + 0x156befb6eeb13f52ba65eb7390b7c812ba6aabc5d1acfc189b95f71fb47db283, + 0x13422f783a978ed5ce35e1540d99c3cbc67803de00a3a4fdbd37f7c120d7aac3, + 0x1995d00ce7c99415c2727e89618e705a87fd4456149fbd899c40f43320d5ec8b, + 0x24ebb318e440a45956fae1a46a3303ffabbcad5acb8cf98b6ee6805672ea84b3, + 0x2c6c1b35e7979c2e34b071a03101db8cf753b5c26193f206e2ad214ed47387cc, + 0x2fb55d17e5a50b80b168fcdd0d618f2da007510bdbc429c5ed7fc9e9a1ee5c0d, + 0x117c39033ac0e1f5f8b57844220b7260e3085bb99925eaf937d4a43a06bcd2bf, + 0x154a4ff3064027d0d4aaba2fccbb05fc4b074ad7bc4443132ed23c5f03d38ef1, + 0x16ea33e7327d3fab4e15cf66ccc4e99104aa40a4ae0eefbd478517475c274d62, + 0x7af162f6a41d5623cd47181367c6f1f5ee0be7b9e0b53fb8097789ea9a0cdfb, + 0x1a732e3765405223cdb6eb28abd2d425dc7d1cdbe575e08568e1028d8ddbc398, + 0x1208ce1a3a017db5d1024920a6a0f94fba55f5b88620ace2e180c3d517163641, + 0xbf9ac6ccc83f71dfb86d40b19b7609b555fbc1ad465b09f9b47b21cb230e174, + 0x1ae8cbc6e5e4b91ea924aa8045967abf4d22d687639e7f64df40e1baec14a3d0, + 0x2a1be1e4d0fddc88eadca5e835f30bf7ee39b0aadd995b48a7ba601b87d16380, + 0x1dcf4c29bab85ce96ae81703ff26262a09c8895f886a71c01413d440a2f783fc, + 0x2bde5bc567bc599e209587d01a8e5b83c9f27fd4988c978294ed9b680b03047d, + 0xd7f63416aaa46e1a5ab07653c98721b3848f7f40dda0cbe24f5be957249bfd6, + 0x201c0d5ba18737cce0bcf6069d82ac70b7c6da968029939fd793e7dfc11997c1, + 0xfd4dfde771c21adf5ff971e0bd0301b0f9c0079a5ccbebf6cc05a578218cf9f, + 0x6e26ebfae0d7f5596bc1719d578b1645bdccb473c802820e8d1e73ba95fdae5, + 0x153a90c4a4df503ade4670a019c1c539fa9abb1d7bd85c5627e2a236816e9e94, + 0x268ddb0d3607d6d88ab21623db322f70881c865d1baa284eef7b6f504649f5ca, + 0x10ad938c2c97c8785232011e8e9956ca87ab31b6e9947a3f5a9cb2dfa526c178, + 0x100a9d42b7617d60e4b3aea5150d059bbe751456c4249f0d807247629e61f0c4, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x13bc85e2ad431df8a6705d1990ac925ccc3df1282405746025b8a5b9dea661fd, + 0xcf2d89cb39c2d88605c0a34e07eb31436a77a2909604c6917c1c8ef5b490d8e, + 0x2612eaba8d6b833432665b1334d612cd9bc430a3bfe2ebb3e34b7a9d878f4054, + 0x17f2915802e376c5827e719a6890d90fb067762c96bb3bb86bb34f2f14211011, + 0x1ec7edddf6e2543f5e457ad0adfe66ff55ec07302a6051d90797b65380b8f07e, + 0x1d4406aa079fb976bf4d8a3bfac81347bcea2cc9b8ca732d3064f9413f202082, + 0x29b71a20d311389c672d8a857b34b04e5b4c95624ca72067879cd312d8b17cb0, + 0x6df0c4c7d3b8552c2298f518a19665ec355cdedba299b20eb193c67c0e72d43, + 0x26779e10800437760c7bc212ceaa5d63d53a234368296d667f1d19784f47cda8, + 0xed1c5edb7053068b07ee60910ed3d1c1e41684b276a0ade50c654de10a44cc, + 0x24b4046af28ee5013cb1662a81ae6b60c9431724b3b16202a5d9d5ecdb0dd322, + 0x2710607671674451e9da2932f51616f1478e7440017bcbe5f1df1031baa582fe, + 0xba845a38009864ca2478e043645bb6d035ab0ae20053ae65c99ae914819878f, + 0x15c5c54f3efc26d2836a2ce81c045bcb20e137945f8a64ec93b50b05fcea1624, + 0x2f416e4189aeae931290aa08d84764da18dce217ec716ec1ad530d21d035c1a6, + 0xc92385c63d6c451389a83dd7a46784f98852b6ded3100b65a8b7c5b96d89305, + 0x222e8105aa188083af23785e36e1eb3b483fec353b832f97e2d66d79dd0e2926, + 0xe98d7f5e45ac6610fd164ed687041f2952e6dd3c9fd12ebc8395a6893ae9fd, + 0x11591f35ad1543a7a8398cc80d8d46980fb2d5a91848942956072a3b58c3fb7c, + 0xfda43471cb17ed2c9e4ad1bcdaa962da09fb99a5bf74024d3223784df4e043d, + 0xa12e81049a88849ad74b40f381be30c2c2e9ec8d8c50bacec5d1868f498285a, + 0x7c6d194a73f848f7d716d6f30acb48ac7baec5affc571b6b8b6b84996168339, + 0x194f847f3c7d048a1937426a78e0784cde6075dd3ecaad21a4d8b0c29e6dcc58, + 0x478225c0df10ae1047eaa6bb766c7cba55d1b2f4ad2c92b579287d4afabd622, + 0x7098d85221394b7dd9d5e01bb8d8fa324f52cc50a01d04959f7cf47a9d426ba, + 0x152237727876536fb0492b77e2ca5083d39421c48dc34e5079a33fa3d2a86379, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x1420a14de2cbafff2579616faf1bfa74f7c6542b053a499ab551a3408f0170c1, + 0xb9d1c211a3135cf248f2ce8bbd1fe9c687788d37dca581e76ef796a06abb333, + 0x2d90ad8b96b95e07f313d485195a90e8cdee4c30fd11b740617caa864d20ba4f, + 0x1841439f401d20be41e3aa8154a1ffb5b06a7cba6987fec7f41df5f92a6bc91d, + 0x2388640642c291a6a1eb98d73ea78b7d176c2b70c6d9bb637abdb842c0f4a78, + 0x26847393fc7364e97651b2b787111e2863ae61218c0a21b8ef93292d6d3f59a3, + 0xa97aa86b7cbf546c5722540fbc3257e37e701c44023e6382785a6b8f5e2aa6d, + 0x1e66c9e1d497faeee46a478ab27fbaf5f9af29f43fde16f9a6385e0d05b17930, + 0x15dd9d1744c08352420e756cc25e76537e8dcfd70c5e0dcc445f77560b730ee8, + 0x907dbd7263cf90b8cb5dfb3bf60610d4fd44beeea309945d8205cdaeadd2a2, + 0x233dce7ca21fd1e909e98dcf2b584e9ad879edeb0f395bf9a44aa7fd588ff23d, + 0x28d0f25cc88f3d33af54d011063c0a2900fb50e18d1517d52d63ce72b435a3a6, + 0x20db88c936bfe7c6e86126581cbf8bd7edddff26237df67c02777070d012ac71, + 0x27531eb0037dc5b938ef188fb167f38039f82f2cffbb8fb6511b05676af6e230, + 0x174c8436d7632117178d777c3174aaa21b1908cedef20997afd4f9de59dbaf61, + 0x610a7245fb111b8632cd43f8d356a839751a7ea383870e108f45815e7dfe527, + 0x51ec3ebb56094e6fd5fb48401dc97a7aebc08c0321260a03ce15a64401d57f7, + 0xe79a17117660b79651058aaa102bf530a98c0fc27890c0e572ecc6d6669c36e, + 0xad64295a0a164517040af0cef26fa9e39b1ea67db4ab22db5d607c4fca3de99, + 0x2861d3d53c2665d9ac962a2a78fa4fe8cb6e81e7ab229f66c432a80dde7116c7, + 0x2ffa7a7a62d5e1bd03cbebfbc5c758444ae0d0734c4a5d667a158fba11a9ac8e, + 0x2fceca53023c3cc3e8991961644decb60806c5e26bd2ee6459424033cbea06df, + 0x1b315dd83c8b16a2aaeb9119436076344d2fa321f3359d6a9ef6cc15b45aaafa, + 0x27c786865b0c424bc2e21f43f42168d668ece1b7707b62b6ea77682a60a4b1c8, + 0x2f55ac5fe9c4deeb92cd318504423f31894b80e6a340fd21ada215856fcbf5b5, + 0x8484c73576645af031da8d059f7cacd28c66906a7ae10ad91c196373601335b, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x1f1e99a24da4de93564a110744d481be210f6020ad98006f0bd4610a054bb397, + 0x1313ce9497a6e074c155fc0218d858202308ed1c1241013fdb1b23967fa23167, + 0x20dd2b7ad2c4f1f1d19f18b29a3ae436405b6866b8dfc4fbbf0877fbb3e7eb1d, + 0x1d9a3b14077a7c4d585632de9c1e0d4a68c71203492d5911cb16f3afa68bd2e1, + 0x1731badd5397325e2221f6739002faa9da0372fef8043ebf93e4627a3fad156c, + 0x23e7e3fe8c10b5580a79f4c3298c8e1862b7f5237942f23a5455d4eac9275685, + 0x2c014180a6ecc47452808fea233b82f39e3b7caf0175687777ace7544a29e37c, + 0x292a5b755731fa19173af35e46536550ab67aaf5f7302a003d0f6df204e8976b, + 0xed8c6981ca41600dba450a860b85784655bc05193481ddbe475de4f351d243a, + 0x1a19597908036c20ac63ccefefe74a7d4a34247f7471bfa743f7d1858c8fbf19, + 0x21d82813886827e8c1985bae1dd3b8377bfcaec6e7fbe0924232f059501eb278, + 0x1a3ba88e071dfb03e2af64d4efbbab382517f94566c7268650899eb6bb1971d9, + 0x1d48d408a857660c5fa36286c7fddd68d2a4831cb0cd055f950be3c3c9607347, + 0x23a912ee06a717208ac5f8e94a3ef1c0dccb7cb14a2fc32be71d8d25e65827e0, + 0x24f16318b8064d97d3543dc09c0c2895745bdfc96371bcc99b5c6d6ff6af3e13, + 0x732c0b040e6bffbae6ac8cee5748cc4b1dd79559d2b84d73347e7868ee45e36, + 0x28d961a33687f15d8e4239aaa2edaab1dcfd543bd30437afc151cba1d8b6f93f, + 0x295338d4f509a0e6ac18622299635bd3930bbfaa4dec3b885b817bad870885dc, + 0x20bfa91fd05c7fbc2fab0619637bf4fed31f95731d89c2f7040f4c893cfab9a3, + 0x40df188035ab2406a932606a391e146c51463a5129c2bc5ab3416e6455dcc03, + 0x2483ffcf685a6a42aba1af8b1c9af41b66796946957e69947f9790615422c61b, + 0x285aaafdd3180b1543fc1994846ffac22fe06908e5a6bdd3fa3d22b3644b6ea7, + 0x2dc5f343de5cf59a69c9429e96289dc1c4c8cf08fe69184b68690f33e233fdc5, + 0x6e3d7b62ce4436fedd0a240d7a777adce79716f5a22b5efeeaad0abf1e8b5f2, + 0x1482cba9741ff1dc43ea1fc5189a2a59fd5b2bc2f1959c164241662658f2507e, + 0x1348498420e5f9e977c9db960818c96b1f93cf370a2380138bbd56e0c9d0d526, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x14fe503bb439d34ea8eaa57cfa1caae71e4284521ba6240b0afba874b93ae8f7, + 0x1f9c9a83a952c1e72697d8a93b00a57bdb092d66ebde1ad8b169343f93c3f8e0, + 0x24fbb0c0f2ace05a5faf061867d2cefb35494ed9fb7e5b590db562486c88b0ac, + 0x10f738bd7905a3db9f0d6fb73b2cf3c4877dce60cea5925d5bbece78cc5516fd, + 0x2a62e245b8b68d45298987ecf40a0a3419ea8653e4da0d6a6f55b2152d85ca67, + 0x275b72887f4a3fd32bea4bbf47394106963761ef3e007f2f1e4460140896c168, + 0x1552e36d16435150e476fa6665c4f058355854cf2202d91573072ba3dfd2807f, + 0xbe9ef904aac486fbddd1b8da7d57f9ce8d1bc5fc7ba2abc179c1fa20873b597, + 0x1e81ddff4f76a1b2dce1bd10aaa16530f8636a0e563bf33a02cb9801d7f762ea, + 0x1c9d6fd38c151b16888ff3ee7dc7a8f653fead50f462a6045cc6bdaa72231de2, + 0x249f6caee2d3f22549b753cc0857a89a85dc00258402594a5ebfbd7235c85a4f, + 0xa5bae6c55380bc6c3c5cef4aadbee3d7ba2e30ace0dec7fa2c3e852bf030798, + 0x1a591bd8ba8f5c6e64b984ad9274257d38caaf25b99cab177c84c8f0ace22c47, + 0x2f14e7a4d071ec394f43f46d60b1552aa9980bb50e7c963d42f483da3211a0ee, + 0x9dffc259c60af5ff5822cf8a170477695ac5775dc1b90104503cac64914f86f, + 0x295af9152dc405a43b353775e93828dc0dd1ad4657f1f324f75e25fc67d355bc, + 0x4ed39653bd52f01b25db50f75b0f9a7868dacf3c6f2999c23bf95f58cd5333c, + 0x10e815500f22b57ba8056deff42b51f4a4130f6e6d364bc1de7117b9023c0b37, + 0x2286d75a72832bab29d58395c45ad419d3d1273062c893a70c56fe9e38750886, + 0x111df543f14f2ae7ada849b80d01be30e23fb49ae805d09afb7a1cc98057a27f, + 0x25c1d1e13619f1ad04831b2339d163ad83da3809a89efc10610d5c62bc03da3d, + 0x2fa4fe7aa2dc0ece1dd482768838b9ab913010539fd9a94c00528b037e4f8ec4, + 0x1950f2d47f38a0976e8801a03edd51f982faa74392a70a0d381194dc258770ea, + 0xe6945795a878954644fd4d36dbdfa856c6b1513c8c38dfd71e3f6f648d568cf, + 0xf15e86e69bf0d747c7eb9d100a26930e44b558de46b2e9246c4cd269f4e0707, + 0x132cccee9c47ea27484dc9d759d93d560988d9a42ac6f90be4737761e0d438f7, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x1f19d5b58c771b1022d6aea73259634d1c9e1db227bd7face0cf3d7ec6f04a89, + 0x9e99a9892ec5c92fcb2db34f0a80d01f93db6675b839e54ac081e2616efff4c, + 0x2e39982857d71f53bdfa8b2d2fd8481727267c00bf284a011e75de1090b5ea11, + 0xa4c0ebe2118c2ac564272eb8f8996dc8ffc649480a144bda57e7c33f14ad552, + 0x25451345b35213964ce431f6f9ecd15934443b435a7f175abd80d97d999fda60, + 0xbbc4376c1f85523bc7c8ae9fcd8a172f4a4f9905d09f1de0a6d48e273ee9809, + 0x2bdd1037469a47d75d5b8994731ede44306e137f4460f2ac7c178bde7bd9fc6e, + 0xf677b2a55e756de8223dca8cbe59954989d27ca87f57b8b8e59078ee30b2748, + 0x2fb0b17b679ed6fa3e528b009e444bb34b173fe18925971a3b6777863a936411, + 0x8e4988e8ab1a27420dc600aa4fd13ea9d701291e005defdaa33e0df72d180b4, + 0x2aa3f6fb81b544fa5d338c2a7299d28d499bf86f77109ef9cd91f3156595f0f2, + 0x202ce667a6cefe69a1d12ec6f0b7674cae7fb0e02dde42e47fcfeb6afc011bd, + 0x13fc451c175cd7d0ac88a8b7013cd460af9f68982753e01eb0b9ccccc2c7b57a, + 0x1b86a2f0867f4a97d6f2ee4701f23d7e05c7700ae53c0d57284c69e170e90858, + 0x1fbf812f6d014d7c0134b54d9d6aff50f0dd76d7889926aaf59e86e69c720821, + 0x11ae5f1bc0b2f10956e35b2a125ded0ea4b312aa52707bd5e98452f6ed0d9d2b, + 0xebfd2844a28d08df2ccbddc8d52e51bf9714e9279ae25b7f7015d37769c76a3, + 0x1c9e2830d53d2fb38ec3fb2cd6f45061058949dd18312b212fde7082778eb970, + 0x2c89a19cc675823c61843f218bdcb0cccb5b9b4f0069ddbf7e900fd643c2963b, + 0x8da85ff8b6200e090cff0a2c2f05042e30c79e425907ad9a055a9a2a496e73d, + 0x960180e5d5ff549130360038aac26bf7d2f5828e88327a1fbe2227194ee270c, + 0x17ea53188c77a5760fd3da3213f549e5a45c743db6b27f4f1af87e4ef28609a, + 0x1cd300160e5cbe7b9cd7ad1180598c065a08ea594897a8b2c667508e93aad2c6, + 0x1b8db86cfd31fb27ffd05312139ac8594e4b9a587927f1d5fbb378be75fdff94, + 0x9ce92eb753807b4cd89cefe94e7f31b0eae43b4cd6b97d8248731cca7817df9, + 0xf953e8b043a5bce5c459ae0c1758ee52707f6f0dfbddc5e407483709df22a70, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0xe61fb7e75ef9295c4189d5926940c65bef29f9460fd6acab96fed3d1be3e626, + 0xda574faa3851b0f89ee096792e722ef02c0e09793b829579e62d43e9745078b, + 0x29e8bfb4394174320d8c3521f9a665b547cb0560f726a0d70f52f613b0f24686, + 0x138864a60c066835f127cc7fc18ad0bc92774eed55a5735b8f4e58f1c4de54b0, + 0xc4061a8556cba5eb98d6966f7014b7f093e6c16ca1c498bab266918efd24982, + 0x29a31f9aaa8ddea5ffe0debc4ca6968854ac196215df67c09fcbd03352180b8f, + 0x1cf3ae0b1b9b5d99445a7f94998c5e59488c6041a6205045683c42f7417b8a57, + 0x297c9cf4083fe500908bd1f4c886306df9b080e77569a534c558ab552bc61a14, + 0x1fee3441a345869bbef74446fee4f51e9303d36e0a3316905b917db8b33ee846, + 0x29f81a706163b55c6e55324777703a9303ef8bc5650160e0f46e5b800d62abce, + 0x82ef985b1721ecc770cb73b1287f745769f9652c7aa177e43706ffb01683fcc, + 0xd2909479aba19cdf059dfd28915cb101756fd0be6fdd65af27163d3d4db80a2, + 0x2f9cd946fd1c2dc74bd0f3ce5737ac83b1071b7d4e720bbb2d8f138c24e9f336, + 0x24ec8557ae626b291b510d9ec1bd354247dc3727f72832da7a79c4fcaf8cbc8c, + 0xf11a41f841b89ce70505543d7028f8c852cc0df7c8d840917239c3724114e6e, + 0x114bb82795b43471c48a7d4f21e17c270f98c6907c37f2fb1f99856266cb8089, + 0x2b62ff5f01bbb491c744a8286db0aded602f287abaec3b1fb1b4212e58e6a4c1, + 0x65601f8bdd487ec395b20fa5fc276d78ba591835f481113b3a5c59b005e499c, + 0x1fc7286cd0168e84301b48ef87d7cab67e45883e166ce3d5b398389230d9ae4b, + 0x795f23bad239c2e465601e109ffcb16e153f5e47a47354138940d99088c5069, + 0x2e953e715e0c47fdcd618c2c5291215a73d3c1a29bcbcb7b9b7d362f211072c7, + 0x577b3abeddb1cba0385cd479d5b80be73ac18ea5564d9726681d8c29857b509, + 0x17f68ef80fe53b639194195275d6dd5671d2016e67b777a0600d69fd4e72384f, + 0x20ff4e58659cb0932f9be3455d13d0e6591b12da8f4c61489013cf9060b12ede, + 0x1e22384181c19d8b6c515b275db8401e900192f0ae54d144fa7c43c0295de2d2, + 0x2b73bd9ba3aa22ee4fcb81ac91cf8ad03f66f640dfbb1cc7b61a83c4e7aa2ea8, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x6e077d5c2e4e5c9705827a87bf1d03ba0d1ad0d1ad6ca1d634d25e4c66a0a15, + 0x121a212dacbbbc0ccf4c3b4292f681523da7c9e1a46e1ba0856b900911e4f84, + 0x14a5405a71e3bf12ce347c54fde1d22398fc616db34d6d6ec57d8d0395589341, + 0xf09fa7c4eeaba22ff000bda61bd7d4e87734f3f8195b38bfcecc6ff221d2863, + 0x16c25869bd517bdef88345315641374ea86e66541f12724938ac7dff3fc14353, + 0x293cf96970b904d201ef1baa8bdaca1321ad3ff0d67548d7ad07287d2908518b, + 0xc5f2232813e8dd413410645a1385493ba715260b3d968149f307b53ecc793f8, + 0x2e620a39a57898eba4992b7a1b2bd9b0c28573a1ff470f544c625a60ef624173, + 0x1c68b64c8887d3dba495c6bb3608065f7b26b8d39050099770330891de2e8722, + 0xfe00e735c41fd0086afc250224c2d48cd0e771edab73eb5e75c58f957082478, + 0x1b668eca521af2f9222ae86819b5aef6d32d8179275e7b98f6b9c314b62653a9, + 0x285025c188e98d4e6e58b0eb6dd46fd1f8d26ad5199eb9b647e99f70472dc4ba, + 0x20dfdbeabb8900090725b38f84f661cd2ff5b11ceb3c6835ef698f7d8e02d2a0, + 0x7d91adadd5a4f674b69907c533d124ee9f15988cb71a732d1c31888924d3729, + 0x22c3db5b12155b945c7cc04c0cdb534db2f8836b88742cb32db40fd0e46c9f7e, + 0x14b640a03dd9207764cffecd90500a5f0901946bf55e6f37b4fb1764baf8382, + 0x1e9b912709e85957b58fa0e0d424c7262cfcf3c0840667012cab0d06542c6594, + 0x1f4a75e965d66b9d9665ddb5a15ad09a9d688eb2b774fc8a86af46fd72796bd0, + 0x3d5c637f69677e08331c185d53ba9759ae018a832da036e31f00dcee14513bc, + 0x1e42641bb29a48b1b9c8a187dd6cdf6ba6029cb0760df90734b5d3bad8e212b4, + 0x2d80ba897d626e0d3bb15479044bb007cb55262149e10f53e63f42a53b3e87fe, + 0x2071abfa33f109a693fd07c4da6a5ca1175ff0413513d36add5bc72012e73a1b, + 0x2857675a3c236532833e6c04c6c9cc91d4aa3e18eb8f38cea6e421c4933f058f, + 0x9d0978a861b9d85265039a22191824e4974b2b113622dd453c71b0b1f8ec663, + 0xb1ffb601c946e8089d531bbb8bc34d4a36e257e8596c47a3c773d71c68602b3, + 0x1b8cfc651b9b2a51849dbfa72c4f39ae01b098997b226f58616383513c76ac0a, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x27d167fe78708447e11dd1f9e1342f67a9d2be1dcccb7c0bf1cac60b0d1f956f, + 0x2d211a9a9b13bee0382fb707a0744ca47b3cc0f5a0afcdabb5c34e52dc8fa277, + 0x41215a7139109b953e3f75f039c3019d9a32526461cb1e749bb5e4ae9e6df14, + 0x139255318820d9f769864e4b9011bdcac24f5491a409c8d0088c0687554d0d28, + 0x26dda446062c11b3ee8a7d9f8383db1f189859d91a03d35e92c2ae1399b994e5, + 0x2a9d3359aa3ab359799d23c03f3ff677ece3080df978214c9ba08836846e31e7, + 0x25571de296a11ec26c7f5b378dbc5837c3e8cf09679fc63da463d5a26e99f24, + 0x2e9d042c2deb3cabd6d758a54cdeb282891e695d463cadaac01a44b64981e963, + 0x1ccfe17477787c3bd72741265e5ac419cf04f60ebab95dda3cd74efebf34af95, + 0x1aabcbbff42769176f05c33ed6e957f6efb3f404451d83c6c107313eb098d57d, + 0x1c3a79dc7ac79b401429b1284780f82052b0217a69adc6ce431fb6de7075da31, + 0x2451bc265dac3547353b487c443d19230f1d4f305ecb2d61baea643f183fd1da, + 0x146ee9dc5bc8dddb22c7ce8a3be636d69c0c0609709b7d183bb8a5230f490c14, + 0x1722db13180d33ba99b8199a7e6e14bfba7ddceec3bf35161a7e875c336fbdf3, + 0xf90b19061d11f2a032bad6982196c3ec2132eae07e73a7d7b7aa1a1353712f6, + 0x29dc1b8c70a75052d431288905d64240c6979f04290472b941f943deb7f7893a, + 0x1cbd570d3b626cbff744b8fab455a37c54760431142aa6780e7b346a93f32fa5, + 0x122e0d5aef6a9d944211b3087266a4dfdc64c2c1e129b146e4b45c93e8128789, + 0x6a2e87f6c251c2f8a54661ac4c177f2ead8c66bd42cdbfcf0642e4b025375c1, + 0x121b14b512f2b6767bc67691906e59d0c6f1f4be4b77e15e277526a51dbe1a62, + 0x24337459df3d36f14130ef1c8950fd267b58a86b37c30ab87d57245719f3843c, + 0x2d751407d72c38bd7803630b12fddc7a076db32d9016d3b0a938231b5f667540, + 0x1fcfa3e97394e1057eb5ef247b47a0f610ed67d67225f4c8a246f54bde575cf5, + 0x1ce46568fc2b31fc458c65d79893bacfb0cc96b0e08b51e85d4d5432e2447e84, + 0x2a2035389af7aac382d3515d999e6a687c9c2e93918c56253c6ae9695d16d79f, + 0xa7485a573492c38febb77b703b0675290ec615974c9f705fa63b175628b8548, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x3c0b95d22504012438e7da78b1a5dbeb4f95569d68fad5fa51f126e434251a, + 0x12422748193dd5410de675c58584a4b6612ee3cb8fd929320a9e70720756cba9, + 0x560d13602278afd0f96096d2554342cf3bc86970f27fc807dce69bcc0b874cc, + 0x1339418b7b039d8e68260015f55b9d91fac69bf8232722f941738aabea21cdc3, + 0x1cbb466b02755d32eb5d7924147801125833e9020af6f52be688e5d8c071bc77, + 0xf5c38aa299be85be03b8f06c2908f0aafaf67662a714edaa407df93fd1a327f, + 0x6445747eda857a8191b68e27d640cfd91d68273e54d888ff057001e476f00a3, + 0x1604659a656d9ed6e5dec461a593c3eeb6a5be5dd722675425cf883debc696ce, + 0x11fc146f9aa45f748a6cce102854720cbfb60f5297ed2f77b16c9f8ec9a4acd5, + 0x22ebd4f9bcd07c59828633805fc99370cc17c8a818e04281fc862f425a83fae3, + 0x51c3a4921bd206f65a1cab1bb83da2ec6128b927e2376508c74a7bba353712d, + 0x1b04cf2d7a71282e57b33b3a67235c89acc5a03e6e5b8c2fc784891eaba9e221, + 0x242de34ed5316ba97ae4f46f05aa9e7c2c1c15dad9dbf8695288c13171bea890, + 0x2046c91a59d50c271c09271aa40ded980c91a88ea5f7e3b2b08858464e082c12, + 0x26cd545999428c5142048b641af7077594238778d17196da2e5c8e1b253b36dc, + 0x256b2f4800071aee94ac6b9031974f26fa6dc520938c96952878364f6f9790fd, + 0x164a0f897508f50e81a4a51e1abe56413d3b53306c3761dd408e1743fb060a33, + 0x1f7569343079826f0b1240702ec507915173f38d7a39bc75ad1c86cf79bd4414, + 0x5272bb3e84e9d0cc586a7d6af710026f809ea06526ffe9da350fddccc09d1a3, + 0x22ac9bed266b94c00d2f9d34f71a2d36c0d09bb30d9ef6587be752ed8b7fbc26, + 0x7674836517777ed3779e8a584732a9509e49db9d94a77161b7870cef981c1e7, + 0xffe7a0170bb48fb6c3e0b80e6244e1d6ef99ccf3e8a3061aa3136b1f7956cf1, + 0x1afd9dce91b191147c5f764300d8eed362eee907616d0bd56c931aaa7683194d, + 0x1ae34688936fcc0968249cf2077a1a982df5358dd5abc8deceb6f33b848b455c, + 0x3386d6e82aedb6f4bc05d34e96805cf875bbdcd9f59da3b3b95f7063442b228, + 0x1a1c06ea0926bd024640936f97377319fab6833349ac323240167651f3a01037, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x30192336409d16bb77389625d09d75f79f82e3e249b9b80a56d541a463184498, + 0x19c8967febcf45820a2fac7a8f7475b591f3dc87e263392789d247b39eb74b29, + 0x97570b91ed5d59d977e8e71ee895a590b529db6ee364fd82bda34ac18fd21c8, + 0x1a4393d778fea4efd093c5a43b4f0fb318caedd91ed30e2affe80054b6cd8e4d, + 0x31f540e1c1038a98ad3b80d8fc9bdfaea35d1d153da0011063b2472004b67b, + 0x165f001bcb8a3a0f9d4e00eeaed05614063d65735dec8c39737a83da4a293f6b, + 0x22e6b223b3e435309ee74f4920584e681c03c0382ad4d4d45f7f1e04c8f1e29, + 0x153d4c74f674e56647007566cfc575d08220dd89f88e9199174e81006f4bc589, + 0x46d4654e5ea12ef7d79ea7b540efd8cfcb0f8c803be7a9f3133227f8b673919, + 0x872d96c258f6400c031024c81eb9e49f1aefbad34225fa5633347f615910152, + 0x15e8a238d295f566b70246488ae7ffd1465a0efd12d2d688ceb2ad1cce50fb28, + 0xa7c019933d1c0a25cb8de67da2926591274ac799ae7a0800e79dfb1a66b09ac, + 0x1271c70f8805321068c895e1e0370f17bd49d7b75cf8e055b87f7615892c6c3, + 0x11356c90cf6bd40bdd299859f2439cd098f43baf710198aaa457bed29b78dcd3, + 0x1cfed55f4f804d76ddbdc211f248a7a7b9441ff124e31bae6f9f7a734f75abc0, + 0x2f9fc15fa8a7aa7217dfcb63bc31e6e9a2ec67668ef14499eb4a6b932234aa3, + 0x682ca8b867c78c917f04c2a7745a9a79182816677c65a771b019e64eff93abb, + 0x21dca8a6aba3d3f01bc0e27ea518f049bd57897f1354141d461b4a0c8682e484, + 0x227615abf38c854ee4abdef8b53b2687832b44eb05210ca355082ae06d9b5f6c, + 0x2921d807cfeed7a85927966f1dd5bf26835d3877c7227ad8fce96f28d00b66f6, + 0x1c9045d27121eb200e99a9df2b8e956f570e7cb06aaa424872e64da24668fc04, + 0x40850a1c2d1b7b78b59dccb79077605dc647e3971b26679142cfa657b3e77a4, + 0x4800dd5d34860acc745f73e61c474dc48e5ed88cc2a6556fd7d8ba47f7fe19b, + 0xcd605cc107283534180cfecb268068cce0e324f8eed13dc548d238559feb80d, + 0x265a4560a8a1ccecfd48264d9ee16af19c125244c13ee626b23d72bd6c1b69dc, + 0x2d72b58f878e0d96fe819ac630ebae41297a09fbc79fff372928e6bf929a0850, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x783e03e1c20687dcfa329bfe762847ef8469b9a16f1aff46e721bcfeb4ed9a2, + 0x7c549879769b6127b1fdd9e119c7f1088459b2444ca62f946f80265c08d96b1, + 0x1025885c29c40db31ca8f1f490caa4bc621924e88725428fbc670555e4222db3, + 0x21f0feca587fe54622a731ec88768d986581c07465c474729691e31a8b4fdb75, + 0x66df9e27127d7003f397e03dad246027125ae6c99200dad3cd5faf2fe43de22, + 0x27f3ab0ce10f55f231d7d249eaf38aa45375dcfae6add9b21783d1ebc38e4913, + 0x1e2dee4d94a3cbe678af8b0a8bf277469150364496efc0ace58540865a6288b6, + 0x9972d0bc51270751cf7fdfc95ab7208812d7e9d93a9b45386e0bbd3fb23c709, + 0x147d3302a23dfa4867fcf2168badaff8e987e90f6c141e92bec278ce816a9566, + 0x2e95c0b710cc179b4e39f3d45c97d0555437195d3e894e5bf238ab9fb9929c54, + 0xedff84d026026b621e6de741849300748078db140c9fe04236c2e05a35d7f0d, + 0x245d05ec0b5dc822bea9b8a2cd6c56da38bfdda0a4fa5744da442ba833098574, + 0x138874360b6e98e6ccd8fef742dca0d8ec44826aacce221b311cf421a6ec0292, + 0x1cc05be64c2f3cd2b68699c52f15d6265d493e7bd5ab4030a53c8be2fed67e89, + 0x2f5edc508ba14e8271fc7fbccb3e7d8750f4322606b2e5dcaac7239ba72143d2, + 0x1557d4eee207353143eed1b01c37806b4f0b6e688069a13b296214439bbe0949, + 0x258650e8ca6e1162e19f92302d2a6e8e40b00bb161c7f2ca5b92364cb553b5fc, + 0x12ec2381a018b71858df6bf6b0c9e02f14d8ca492878055dcfce660c7d915532, + 0x2aecb59a26510953e9d38b5669447df6bf4c2dc1a9bae6f4b84ffdfdff6a2a29, + 0x13201907ff8421dc74e517a6b72e4f997135c8f0e8ea5446907c6fd26f1609cf, + 0x1db130e5583c812ea25e107e27899c895214abb225bb3807ea80232015d21e2, + 0x27db99bc289ac5e1ad7b1192ca0c0f3b1614c77a77781cf00ee2e411835185bd, + 0x21a326712c5b109272d6aaebb73cc74cd389543fd17e6f12cb3a6c201ae735e6, + 0x2716f822617a359b60ba9d853d76a5d051c9bebe9ea9425d51b98475a9485809, + 0xe99f2580adcf372f1c99d009a22816c53cd5272d479fd64016a45e75eeea381, + 0xa3113a6affe5598d9d8ad2ddbf83ff94d56ca7f078a48713d0af15c4529291a, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x2cf67d5d1a9383ce14adf8d7b63005e058980ca148deb3bf0f17855cb115097e, + 0x14182d28f17d764f790f9185a15a6a03144c9e41ed22e8a2269619775dd3365b, + 0x2d63510ce0f51ac8f325327191ae2e8dac8775c05f87b87897e73416a53d1007, + 0x11d2023fe50f1147998bdb7d03b70f70f1a583a67646b055be252e3393bb0fde, + 0xd5beabdfc8def1c0fafd2b625bf1f4eacb6d3dd8870d0557af54c9c98b5b799, + 0x2e8f4e6bb6f7a28422636a7d3b0fe12ca20ab14cd0c5c45c4ef13f326ea5fee8, + 0x1ae5ebcaae05bedb59194e96c92c288479dce2ab43fceb24541ca2648245762a, + 0x24cafb4c21af1cd16216dd42b7e5c42457d5fbf4bf87bdb65730418efd682a5e, + 0x2e139e0df93864516aabdb86d6ab65d6598a0017346fd732e7f895aff36e9481, + 0x2ff83bb2884713055564970f1e39cded077a9205cbd74adad70411e2f963159c, + 0x2552f8295742fd94e0f264d182e9e34023f4163fc929c6b143cb35dbc61a32c5, + 0xb05c0f1defa2ff4e6a56a7582a568d650a7a2ae9ccbc478be52bb4fe3452299, + 0x2c0588283e0bb713ea7a22fb189fa359dcab39f137c9d5953ccd0ae136770f8, + 0x18bfcedbba1f9279d2dbd1d0b4b728a4836b9682905e03f6d9ab9992ee702bdb, + 0x4b314d086daebc4f33a7e8fb2ee578c668e91adff3ac3168dd3183965f51ec8, + 0x6cd84135ffdd74d9c315bfe319d01b17060fee963e8373d1458e181027ff005, + 0x29eea9039c59c939cb82a69a7def6a60623b9868e1a7137590b930140bae4ec2, + 0x1972fc96c24121bddcc76c44074dba6ac02ca1a10bbaa7bb49ce6d7161b4ffe4, + 0x1bacfc2d72d57f6bf695f3d82859859b329b87539e0c18313a1d3f27ab9afbe7, + 0x1069e2eda47e9fb6bfddfbb48d740256acd9be07d2ea9883b63e3214d0ded0f8, + 0x1d87dc8c8e73c38d20d2edd3f6b5abd456a881deeda90d0780176cd7770419c5, + 0x1d08c8a0952b5e4fd915b39382a0ee45893e3c207e339e6c78f28f1787bce94b, + 0xfdbab60a929d492017a0691032f8042201a3223c7ad628a6e1b6340d0893c, + 0x13f25826edf3001e3d8ade5dd2965989ae6c2578b7e886116949553b6f0ce244, + 0x44fa02e1da99bc4866c220784a4ba55ae28cfc47c4b9e5ba488f43b6141c7c3, + 0x7492d98f774f6c8f67583aaa485ac632906a19003a7757119536b19ab78b9d8, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x1fbb89d438ac14128a40437352ed7182d10f22964833efe6fb46eb21b780ec01, + 0x6ae819a8e0c57d44ee1ab07a49be82ca5544d89ab8518f844385576aec43234, + 0x2b3d3a7605543d350b0838b9b3fa9656cb91a84287d6f06e9338154f316cbadb, + 0x1620323cc24fb81854d716dcd972c108ea5d3b062841752a36c994c594199774, + 0x53924bafabdf89232353e5c853dd8b946f617a28f094f9f92badf1c233c925c, + 0x199241c82a57014e3375029b265ea7683611ead5148a8f83a231065c7887951, + 0x1e8b6db0d447c099ae7433fae22a2e779d110bd3b8feca58aee056f7ec325a4f, + 0xb3908d2ea7af26d42a913972fe10c3565f627cbf3b05af7b03a03b455d2745a, + 0xc337f61785e502287e274c817e5f380e5cd314d1a3ce42887dfe19bd20e8348, + 0x965a7d0f2799aa6f3ecb0ab4fdf5f02e0fd5386bf137cd2bdbc3e6aab74b608, + 0x18d8dc79d76890bb7586c65d83acce6185e11ba38d288f4933f33db74234eaa, + 0x2048602c11e8e771bb35415db4519798c36b593ea0b8fd4560410a7057d5d6a0, + 0x2966833633f29aaaf9d5f8d206fd1353f140d989a7214cd13bfed0657b0b5407, + 0x1c6ba85ab5f85ed4b53dc40cedaba63e5ef8006c724440b9448d64ac2b394b08, + 0x65adc608aa6dc0878f5bfcc2b89b3dbc18c5944c5b868dbd6d263cfd386ccbd, + 0x2f5c69bd32960af29ce7ab14150ba089073d74b14c18b63dce9242df8da666e6, + 0xd4e47c2eefa2d97991d58198e147c5dc3f856665f35905c8dcc0c7981979669, + 0x21dc79896380c9936d5da47117ee730c16563d40826cfed9a1415636bb6d9f6c, + 0x11393d10b1b89df9a2e7c68df33f1ee41656ee8509570cd4aec6d68917732245, + 0x2501a832c4be33ce1a4752aa3c3840b89c7eb9d7a2a267b16f076d9c90a6e98c, + 0x29417a7ecc3faed51f8f4e599e13699d32073c5f3865d8ac92f664016060c84a, + 0x1e6ee4be7b5f89fe5eb7f50ea73935fbeebc6ca8756580099b3c9a41a8a66f3f, + 0x24b1094cffa81631dd9fc78b33cbd8d7a93d0269ac60501af8ff82fa646e30df, + 0x1bad44f174f12802c4ec1dcafb6852b6b99dc3723bef629361b5bea594a7e3f6, + 0x2aed2c26dc890d5283b53ad5f30f9354e22804016335e4190b551be5e28e4e44, + 0x247d59448600ad981156c2e19e2be924d7b83bed1bacf16899dab7d7a8bf7f51, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x105097314bce2c2588aa56f191b813fee58479e8b541c13bd6c9bc8e654172ae, + 0x28d5354a0ceb5dbb339ec880b3b6fbc0e7e4f07ac0ecf5348429e1af57069bef, + 0xa31c76780b39b494f7334a7a2ce004b80f56d898ac155716f65172fce3dd454, + 0x1225a8ce4e27af6625ad1a92530a1fdb3206135eb09f679b2b38c13869b9370e, + 0x98a16fe6c6a2a433a045fd0d02346e5c024d7b4bcbe12d2594469a4a7a2925b, + 0x205ad0dfc7a7298bcca92aba3ec23f7dcee21785c96aea116bcf71e07d9ba361, + 0x148f1eadc8be731f95ef81b8e1f3634f44182101b2f13d8fe46bb3aafd2300b9, + 0x4372474a7938acc947df6d261fbba26850a09a16587d069cd877151e287e1d4, + 0x2ca6979a079cb2f455da4e23b90e191cff23e2d76b7d0a6d613e0c1a4507c4a9, + 0x2ca59df55ad4923070a4669629aad754a88b50fbd4643d544045d76148451dc4, + 0x2a7055f1e24448b52bbf572d0efc12754593d59062345f918ba7d90a27130580, + 0xa644e2fe975a3d062ff496a17e7113a395ecf678289de53b2137df5811be1c4, + 0x259bb7d88bf3f1c2f0521ff84c05423a250fc32477823c44d53e11cae6028ae3, + 0x27d551eb8809df2e1c200a661838fd96bea30a7a0b7ffb20795741a46ec359c9, + 0x17e37e4432360ed9a16dcb9cf0584b47ba049cba55b53ad5b5bfdb55cbd36ac3, + 0x263693f36da574e9f6b1af2e2817e803080035a19ac1c2ff754f0f970d20c6f9, + 0x1a893c4de3717842ede135fdb2a63f3c05c834cab22572bec21d57db7c3cb052, + 0x9bca88fc417d85c16bc98e2fca531206336226ba3a02a51a7fbdc2310e26f51, + 0xfe6944c3317d58ffa98fb3a991c22698ff20765d34c2b8b95802b83fbbd9cd0, + 0x1ba3d144274a073e17ed52348cd82eb3e00c743b7d9d3e944a1e3f5a361474f7, + 0x2cc42995586265e9cdfbaa845525177269b37ba7fcd3294074613d2d12af4070, + 0xa83811bff1e7f22000720d598ed2e3508ee14a9e12ff6125dbdb78cf07a2d62, + 0x4242918a5fc9ca3c34867d674dc7d1d1136ffb519de0eace1e6f911ea197350, + 0xedba1a161aae781bab92363fa0d12d8fcfb5e3b818cddef8844f94e9db890, + 0x230942de72fe0db9196d787b929144bf4faceb69b6f12aacb6e0d6b51cc7931a, + 0x1a9561c0d020fb28ea2ebf3851832058ad1cf972e99841f4772a8c578b6ef48f, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x22c0fc9c00f53d4247c908976b1ed1e55c4138b96e9c3ac1dc1f4d268e64ef49, + 0x22729d77b7b881af2f484a1a8438f52cb7be3b93c607310c5038a1d07253a184, + 0x14883acec95e824ab505756a5336b2c5e1b984c6a193d4bdbb014c097734b464, + 0x120d96dc5b428589ffb9f37b5001c6f5915b3ce4460b25331c62d59d65adc01c, + 0x130325a89c8e74b5feebd6340dde992f569aaa3f9350e45d0904027087e89b2e, + 0x16e6e793c81a10719f613ab182ad57ebec76df8dbef775cf03e1e316646d05f5, + 0x18bb788f4ff54dc0981e35a7178809d1f2518cbd12e5e78a77c2e366d0543cf7, + 0xcedee51d5b87d9ba52d6f12490b24cee9e61c1889ef46f2f882644046626461, + 0x1bfe0f0059a451175348f8af855e1f384d1299adfd1f8d852df6c325130bfdc6, + 0x1ca82eb1aa4d6081a46094f403954399af76a7d7dad88d5a9ca921a30ae1dc9b, + 0x11e1d384eb2a64472a26e40594253acd255027b2bf1f7a9a518b954d0de04321, + 0xdc70139469e918276bb65ff8334f64ba442cdd64bc1865efe3e788ff0c74341, + 0x1896f5f3c754db9d8812e99665c89c873620d9f0e599c0b2db25f9b186c05bca, + 0x2b1eb292fbf05207b3a916692003abc04683db775eb3e97bdd5f388df5b9e6e9, + 0xe822a8b6bdab9cfadfc98982d3d27df53300922ea795b29e1ed4e61f2ef6b9e, + 0x14447323538128d076a4a7c5e7d487256a671dce167e1a37f69601c64783ee7, + 0x1731ac8243601c9ad1c2d81f6ca118d479b9d71d03ab34c282bf68f3caaca5a5, + 0x1efef24cd417daeb7fbc1789fc2381fc194f515d6bf1b7a61bccd70a0fd13c2a, + 0x26c6de8f5b580b7d222bfee2f19dbe02580da4e383217b4870f1d4c8f7b692cc, + 0xd3823efb4c4808c275f720c340a733ffaab28c36479978b485b346e4ebb1ab4, + 0x24a2b1d438ee871cdf765b899d2f068811a6f46d02422c133ff6695a7f304593, + 0x9fe29e36bc74cf6d477ce054610f63a43855a08c27b86af1ff58e98c9fe686d, + 0x123e4ce6ab585e748a6424819b24aa2fd60e371b9842355df95ef13318346c10, + 0x257d0d633e7b8e40fa3a0c30548ff79d268d90296d8b5d3e9e7ee4f39ec814f0, + 0x21f4b792c1fcaf55e70e1b1804cdfd952a7ea45dcb9982c315024446e36b4b5b, + 0x18cec0d331cbb93e5cb4c1d4f1080de356f465e2ffb2fa712feb858bace4f5c8, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x1e5f08ebfc9f997ece7730536dd4cff8b519ebf519ad1342de3c2e26473a0b5b, + 0x2d77d34a218a752dfa4b941b63d7b02ab6078037ce22ec0608d3b7b402e4efbb, + 0x19004b8f6ea39ba279e5ecf8210460c112c1a563cf106736d9a0a46b7b842695, + 0x11fb4988936908db3d50905adda5065ee297a7e7187c36212ffdf5f81220f256, + 0x1081ebe3ee722e4f687bedf259ccdcb6fa46420c44d0ea88389917cf6717c04a, + 0x185aa8d933cc96791097565775894b15e2858ec2980311e55d9827471bbba810, + 0x1ab306868bac9a5ba65245b93f2c9b936de449a9091b45f3473bf97dd425aedb, + 0x2f1fc8f6cd473593cf38527156e482897df8441db84c875587c24966f6523973, + 0x17770ba5bd03c9275e2fe0ebf158ca85503ce65969cc9f86e3fb3be24e1fbada, + 0x1d0d275c4971978edab4b7a7cdd85ad72c204a13415f140d9d28b8af514bd692, + 0x1ca07f602b20372b8d50c9863fb5ec9fa033c63eeb293015a4bc91038be3f7fc, + 0x4782f31c8fcdd4898af76effd524fd0739c8ac290480fd0f32ddfa082dbbec6, + 0x68de12e587aa2c26e2e509faea0fadf79602aaea46e45b608be969ebf46ede6, + 0xf47f3f88ec297c36cc16581fe223a95388c7c3baffe6cabc7f4f669bf746e96, + 0x17bc99581c7bd39bae9f593ae1d72e99d7628db94135a65c2c510727f6148029, + 0x1d85dc0db735b4877d9f1639020da87afa6580963e0c2dc95c30a77ec57ee2b1, + 0x27c21a6c642486aa075c9a7757b96e68419cab8ed819e40d179992652eaaf1d8, + 0x1c15013e0719650306487b07e421e718ba9c35256964071760ef99c6b8aaad28, + 0x26bb2e4e2bf9a53e1147608d79a93bf730b09f4e651d6b08db6a509ce44ebbfa, + 0x2cc7e0fa1e964c48a3e0fc90f35e4e74cc01b2f74cc4de884a2dfde37331faa2, + 0xb9c87dd914a25c9d75070b7997507399970d9add413b9a8e4397f46ab8b97df, + 0x7f9ce6c590326b73f00c860875f2c7d4e6bb52725d8e4d6958caac8f46a4ae3, + 0xc289d670c7e2e743fbd60fd2a2a5e3ca077b4bf44df78babdffa232626d3900, + 0x190ce149a93a528cb01fb27da9eaa39de2bbaea50552a99286d4fa80b8e7b22d, + 0x20633ae2a05b6d69d765ab6fc2e335ae0c5dbcac130b204c01f88f9cd091b12, + 0x2543a932d6cd8dbd7533f3bf5a905c366dd1ac737290f6671e7ad6adb557778d, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x22187dc1425cbf505392f976a839df01c17067dd9a7e67d09e9078f1ec43abac, + 0x274579b98b4831b89a42351a2bef67f33a0741af871e3b1911edce28d6b1320e, + 0x2c52925562b2b08d1d1b2696af293157692f2a0b7f34052cbe8e26e80071d256, + 0x2e2f8231db4f3786fef48e7b65f9c890f1aa834729f769feba60a3554b9284a8, + 0x521922aba91806b1e4e13a4bdf92fde9737099751626a1c4d6011cb0d28d488, + 0x2ee11408d02e460309bfd46344e5557bb6711504030c84d81d127a17aa72c787, + 0x175981ace0eca15153600235260b821b4b05013f3e0e3cad3323bd32588b398, + 0x1d17093c739566880702816f776d54eee78164e5716335708fd67bae6407b863, + 0x7a6e2b3a2495845ca96a757a279b823bec23e6e2c2ee41f3ed6705a9df22548, + 0x1dee69a0aaac76360a66e057a8eef5bf7d845cb09a3eb27bfd152239bc8a6818, + 0x15df16ae54e8e3e211eb27f95f7da0bdf38da9530007085afc20553468eee2e0, + 0x2d85cd78c80244f0900115c6f5f5cc4cfbf8295c2a0b685f987144b9151618d0, + 0x1e894f052db0012cb83762d3fb2a824db10684db641c6e3eaa9fe45c9561541f, + 0x19bde06d6e7eb6c84a02e9a0f224c77c0b2cafce0fba9fbfc063a46b69e81406, + 0x2897de5d9c274ad4302ae652103f0d8d3a041ae93c0d461ac15d30d36a60edbf, + 0xfb0ac77f9a6cfe96bbaa646fe280d4b5449eda51b5cc1ac36325c3af0f4f830, + 0x2c3f06f6f736cbfcb1b6927b53543c31a95c648d4828ec34401c2474c932a48a, + 0x23e564383465f1d1f7cb62a80d4995fa2145cf6b06fa2f1e0541effffc19f5f4, + 0x18c139146446dbc956ff95270022370c93ee09947cabee3b0377d1524ec20807, + 0x2bb3b1a1771678092e80390f181fdc6df345e7641c8b7e4932708ac1f332f0b9, + 0x8df0d04a0d8d1b2b80f219c33a9266675bfc080532e9e66430bb67e05360f7d, + 0xd39efb103e032f986c875db6b9f6a6748cfaeb333c93ad7cb45e755eafe48c8, + 0x5f47c6fdbbd7b4e59cc7877eeaf63cb8c16c4dd77f214428dc94b9b2c0214e0, + 0xee1051b33292d8a7dc350916b62440745f2f47981721b80496d2aae0c9ff288, + 0x2bbf58da087230463a98b210824453823aed830f60432ce3156c583e06edf08, + 0x1674e5bc670e98029ca22d400ffc19a4200352fb152c784da88be0b67ffa14a2, + 0xe30a774c353a2cbf244d3d014d1a0e5ff0bac5e242673ae33f1bb2030feff68, + 0x8a1e55de3e637ffa6b051ee33ab203483029584daf0c57c454bba30cf6363a8, + 0xe5b4497c397b27ca78254adc0c66a45514929a3dc0cfe2ed3c447a5d3926088, + 0xbccfad82d3fbec329e684d19569993c855483814fb2547e7b96cf79ba875616, + 0x1908c79adfdad4c4aeda2295a9db560a33e91b01050448491632705b189ae1d6, + 0x1299565dbf2547b30db50f5dd49ca835c3213eeba0130e835aea4add65037abe, + 0x2b4906e765f1e80f6e84d5852f34da89ec6d996c4a40a066c68b6a98100a2f9c, + 0x124a247b0b866c09ee5d3783bc715de3244599016f0fbe385738f95cb5dc0a28, + 0x77d1bac0f5b226607b2765d8d48118b1c55380c60aaac2ec0940afd0c05b24b, + 0x2ac41a842793f693dcffbebc5c08ed6b4aecee7db956ec59ddc230a7b3579c1d, + 0x137d327d41a9c6e42e20bb705fc3da5a282c911c8e7a79cab4e3665fbc3b529b, + 0x2dbd1fe87204abe2f9c27a8343c7257a93e781451d8e159feb4ef12f38b28e58, + 0x20d9cb838e454e9841ddd4792e4ea7b8f51cd7d7f271d6e32f3fa963a6d2cdf6, + 0xb34270663039e315f63a5c992e31d5d09451221504f85b37e1480067fe92174, + 0x12826e5b9be1c9b85f7c98aaca9ce28a870687d3628d60def0ab3072b57b09b8, + 0x22fea1297a4a5f08904d555c2e15d016102a4ed29c32b4bb10809ef14af42c77, + 0x24cc6751894087b831598b5bc7f9db3cbb48ce294d9208e1aa436cb5fa2e80e1, + 0x2cc3d0503a0e1da952b081ba5dc5b117e646bed572a645266c6ec3ce0a1474b9, + 0x11eedbe5a5969f33446503494b469a2b83f88d3aa477e5d6d7963a8333a61315, + 0x189ae9e9b162ab1a19d599cedcef428bd1325c78740aaad6715b710bfac4c1e6, + 0x1aad11449d6e2c6e1adcf9e89114c336c0145528f356ac049f52fd8cb084370a, + 0xd7e1eae2cfec406402d34c259e5966f6e2eb261d4f08e29088325a6bb669a63, + 0x796a23ad6ed2ac995104a0d3e6c75e977ce29aba1d25e62a9a8a20364ea1be0, + 0x299b8e8621d7d8c8d3d6286cb126b34ee53b2dc9a3697b8380c6e47f5711345c, + 0x20f11ee81d2ac9a9ed1cac61d9cfdf10bf1b49cdfbb6d232872a1df1427c1839, + 0xa403e979943b8d2f947f6eda6d41170881341bb5e4fbbb3b4fe3dd7dccdd777, + 0x4646253380f4bf642972ae81977779454aa0833fda36b1822cb9c09719e3dd1 + ] ) } + // noir-fmt:ignore -pub fn x5_15_config() -> PoseidonConfig<1020, 225> { +pub fn x5_15_config() -> PoseidonConfig<15, 180, 1740> { config( 15, 8, 60, alpha(), - [9296474750911444465025945061626611450573261102544117494435956219223872045013,5146180402642819236271333772846779841277266622562021651959982317806096554632,20454733758478774733902661862471466785458678414673417084919753466149262477949,16939720779646471039361700224425387363963401457766730187304254365590145685643,16508379613071589632225608856524646606497744838305343752126125339777944056893,20867355466989514329400908378893992018169546886162092188544040547127653338003,9562028189723224670918372808954372258890790835333923497839294908971703629044,9227509288281899178360094205033853851646604997619773877005168383222677033411,8509781355418257783679010460137433931646066572707591432255985024195888527301,16352397893201944000231474199631274335610857147594743875684031732171609392779,7168331327842901194795012403324475179802342440545189729818235304752196473490,6805437858781519809721294519096505646809998863249026857458359222740400480093,23666102285914319661214067066621928648019777016465806627627356483470384578,4937167589168346771422573562192746031838523475116047879790134471501476035621,1346691375815699628539641638232212515770545677194558930872887124097351576509,40983635009581820916284370715993074471281691288657861297464948812277259151,9682480346612414028382424944197316598030638601235308149341398931369789543950,20156146228109066705562831124708208402478981918458654302206305397911512087980,20244794515708180670563002449620617650597057411850557162891558214158122324521,5973431503164625202944413714022034366590666955289560873103517106326649624937,19003031440781649161524015602474761488168160816940423515211864494962159501828,20712605099727052887180337155696823289955789009114447705180663042338119444677,15751263674652110912724722781530878809312788917232502379399572977178318108528,9759440007076373606849230657528653877996372541705166313887529308971932175875,15753864581145946158736383142711883662973744817981456049085179548487345401534,18516736976984654236711834595195133682620758902795528251669085852778367276210,12505762035583653640932505661921159087471940695093437071026827168265805916842,17973475260212324625956540069233265735155253700466680406635575121618318752819,16893238145591341977099515648275086133943062918579997543738633084157810726656,9669071880586595648023284909288486812190820353718106940661900367937844527179,9349088318894477564190440283477178116641834248883927901328258581942583077569,12186865849936919100247208155624431297953689379595363409626510899600302936538,14191429059221279746000430832297028082244506830783856999765158986408198377932,180235525898780969912044806879591313131227292826139844018949863600387171682,10889092107911649889040150092427122550710450427668385404292705974881857473203,20693842198933957663269842304864226322478103663024796211607837700737760050747,19741631810531886646761927581354810838182866370317964412790883870153217103250,20514964832794580053019916730141871673725635044918093569735954402314586611172,1563081830952767432323468775999289294801679977848773475307184358241727189864,6541733180459084604825913391805383670644609126706479690307729028795470985900,14338950551652503213249338133071776308134322059752479422120853035176120166434,9445962403225070324948180958168278025259517118659455884585920056598191781467,17673503748974627902616087621827013509215108587044719385816919777868083778907,6529067669277048252246949093210874205656745103861744893697681349157159395382,18670351688014831561846153455584274335550086431574922181801742319576494275746,16087198812208315804697003049026004024678636407919712012630915190666161641979,5409244980912243970485734262038475969739470891565229610070736907935180643717,68998709875023468479905615300134369445692715997447916337587330860748485243,20797106660136416987264043187693969873379408007710762405000375236313842719688,5277839105793767851333321356647781091931078040812937205152067116052352239761,19813316014421099365974197500618281012606383357022846408656988057396247542705,14651854807736789020692970167659260203349703129364255901280500438993569147591,1953950121645869390891017290629473806985703435547819703015178261443018199466,16966986407661837074189113052135209905137771226341312735335483526986039302676,12196911666087491240035929989808617508758866763772938948559650992149525851273,6748262588722620715981149705241221174138004527637005241186672382866432164292,12351853389756326378242661122644604232955500481743248231924728979085806709527,2565243335980149108987604508873860765952308183381198225102084152967125103373,20241307878322245036836862464964995816180104231642798486998859049422772672116,6173912854438429518808824631217531662651777757438489861961683800252069642271,20373949892834246498138105881327221987245360841655169052122063615887220321147,13269719501466581754706990055797732063851220874637620573076979035861249715318,1578162066274870756439515512829351279665654675138074205960935197210851459902,15699466465478499203883101572116714566818501168342041974225130392829754730992,11504917391580472762574218883359632564098492996052059988389474392975779673931,2471534962918953214626354556158558932844702538697900698209059019370494276871,4461270721380837522838335428169036184773145514356202591842435276161887233701,17625308215993897091838888595388246859096597033404108848402595233466786865507,18815388073919190191562579690732647812407368396854637581401819367329270645091,18268550843300936597164339843045347137811481798420250960800057984676328312298,7226998309855583456700105258532413039112576746166962016437941756495852856370,8072980663193342911861442510877605529321700341477138509973424538392015970628,15269265747158306563417251524571764365372430081923021726955952481038826679058,19910037920320033458941731683391812599895690039363377502140416867160565960964,15486045363368901308969563040163325835584354680260407824152890548047474173382,16416166568440710996186902352749667794644450153896415669656858302452107263361,16719876352169334284151333613847626557780385036803676145001883066946186048592,21250242709366561537300491285945444276614074599553674495821079421382627519383,18996863118748910427791883574992010505069161233259708625680518449974859990560,17413984989888387572882804568722637770904232773299911698227583956354366272051,21597529235679499224130811468867862981087206894945208547265972184954721846149,17271950603399986802591192304636434671723720851969778588610595038101316019146,6798909530322911571363098835602980477334813891267210720952461019098407212259,15221754151466299785203667902143040752208351220550667002070154445706666401776,9969565572595685753856723561942014758757583006296150732797865871416014191612,213937728610177048236193694412457038661914578783162813372436128728852762482,15615646173777239619093550417838782753019556951599702936217300723011405507797,7718045694050546136660011535056217361530495049313202420611728185159583583910,6681562236645975908164269312121030538373320810986198141132181047805166475529,15406190007218505433124772738477886033924738791369244099805663445061334497251,12748925302440648174656014197639220978675653093966691038521528280766659388490,18792405480956246176786158899722364426273579869771820318487342148987615503627,21034833205180901867479986245412384531166379419487221053266758595893395608147,14993530305792055254503672111497655292586320227932876629369830030730566504041,9717186869050569007497148725820161576480205291215534893842038294586234260310,8846581556095542298416062056868302371695747263219967935160771313384250848220,5719380810982615524673837631402222949910527678512468701059039624789965209167,5973398204091658428913223841081738015584068771535532858878785900515770169284,390665721029373984714826019392824960041229454845430836402699997231854884676,16884099579377843869279635395084651641533249525144181522512029929860550566335,16716976662979247989662403288430439465273241484103184167374388250697744962395,1289338592939287230201589454150014946433268062090374613616251000166621302313,9317927644121595578754625372882467923006787730797841509740916536436754202554,9792346806272266839932159619375452292987210695578600955864989901266954094960,9296083977157792888817756474494818556822681079104304334773148774182988756476,10323608200914404656342379674401080164220099943588034731349775904877409752904,5665882510779783554356611639475035143817214951779938939820232711292028607543,312967658452369621468725894369965307895839161467077935727514890821777198625,20664282841391311519597819314930060269576136022608505709992590417893434920589,5323350315725158992622594066490821193659726275127554898433661812401256218478,16039351301369040724720782620886565139379163954982512295794534252600896786349,13820693026747418768344065399393852077420709727979822490883114289330249839237,13797176144228246839971555725332102191019905588045129521304130064480669479604,20861818286081952786814445160300163171950644955642439845329412070095760317081,6607366884537402504576829976217056754321721309944806800456553075345742381854,16676075047056109258708765855713030298752565264610707737757882684833916800885,2596872657894796835537858907147863451585796495210087845405329734139833282637,1129905770296794876904745792895109768657958745069004656310552795892948378584,3524768344101236852745306230236516385903870540974561871381448404874187920054,990706121628678949689364737717640674078492689689565457695471004362978678643,12808278123975447545284898374625872643451056414444411676912801184092083815084,6358161990036632946294642058872786712712883111056083194592676110308231876108,2793873016535929696420652383221830923887713214117784093571041985641508474546,17305928010614439499134847438771424617226147912488714899621343734884653872709,16284502064199759145361743401051151176267685561605421586130298595070638086967,16669378724978577155412758169912049188272082311653969294949527064226374258950,11861408925173541719238679231659983919027526756130925399544116580983984008351,20319862771317637561778652893808792643716731292949307597222212602977661607952,9965217723779805596104842963458526859730058546126612755023280528059812781678,2231229143040861060383699098560329742848948229177358362095200642518040448582,13286704465412914480712873676020914803973411257385854321890647189069199504571,10047635595882320884409798135378777636448641999630707194378323292740008960417,17087336000400458291414525340830964856800142468906625956701637877370905283650,13535594575282729223473509709844990145664370669908108705760692736046179136608,18619202345418036145538258744454149503028380077256559127312056952610301046510,17607804586369163727645967551963527279187781470886431384954240254070602283137,2633042556450301220705608140363996319867584411611510879359782399294296770849,21731768638998447189300033743436435314153248129574741734083353285598244080117,17469131737454037935821691482173830563221091395109883834897114256467877636669,7750519651616125729362402583651846123740462681349952291880562002377909054050,9447081032000164239615272903502339392629921187510175841323135270498903409976,21517411732531464267453023393592251500842566572268409532461770072252092958721,7876501141846244962862794902521772277174190799788868978106856756141641727971,112943796512817751182977688559740204117088697116147815915631198815244286561,21045605911504121416853713285261007893735116973950420994950288232723845218749,1753558144636632850096274509984476357404441186238175375676398948118672743832,15932527070583999576056453444162361416070384829011926782656187054064561647022,10670345925352776542283780467580832901477001176626927666485810080031890388634,7579612604695836258451031149594628860115515363868399672164640908835805063913,16678286807861813265032290142015890821080993558199809221760573633471452514219,15414078726286200869397977002633905619706559151321201886825291326757189172060,3948850363929702397926233515670425547474212215810847662989169477642088807390,16676527723244281555583733536047809454744760551541688199219131455695588765207,14087355065973222250918209290719451048172913300838805685888196087459492418503,8104074033209440421654249234822181338065658024406724406758136674393332631833,5187207728881418438225188748028865692950088102865770071392557429006545519499,10194509841193628413711183989804813746356025348148221750035788743075560349210,10011332996303549537072329954668024063758462809797094286213034989313201039795,16531650268844669358279021502930777186663937554425443224519161588787088219270,4198803426144178314296362723890875454161257236407666607766866723687553739691,4796265297638646381399181426481493643799772847333437062194249373663993441511,5547609802231005143723955844984958632609857658378828698100141356246667308579,9238958429509576319892727665041354560043563806656332888234436819654598656915,12517630133819614217261779870726755029108748195491643235440705119352058557308,10368014234449326131235994433740216752312468149182650354075154587397704894585,487465315883418182347663117280302929984519597673016955398438666336416216955,11185034244837678424376295011043645561088905841730131726788873681031338174455,7421225151165727634904994585688522807152162423870550118585658136113463984936,364806019968570676099566454292016788351689833960119434834370974516536828706,19587762041779243275917908822520467733740516572707471226884058208850887204874,17699580368555821903526305272862177569486615328343491839828472034082952960813,15739138573269259325517597876326746482937619260543240058947651429318524320399,17749815771695585990262895269645295514834869871993754550237121995617786628911,6001281843453332722738415535953496883454214144943230146026585272790933236244,12226248842279453247400486197034488006724059955941344491855600110495696624034,6471818050024319863197241387509891745688912297463370650154695351698691437030,17643944916136214612858153024594861226464689685432825152621939791565281052364,21110507073644152221308742247603861828087429176260377204494317652281698346306,5767681379026755049166284789191192306599058359643996830685583640018326835809,20268516002780303771030074402103352053711651542638490897887552979541377898692,12422024375924323315232423143442023050941283872688585715847426230444960244284,20694378016149655833849108581703458975143197158248183642690852771732423212333,3589864715711417186674798636588069952164879749159939425060725590030374075726,12536189236026623553502052145542282538682809966098904986394409008189339523570,2807680329090948893979159370041090163078264208853025987363628558807228757758,11134364423913486029994525311335222090667061028008118303028273833566959977738,17354950677485256631166408496835881692979370134492552889236570818914175381226,9148772489395197941519683034415731069796332771510468178434252005940900987586,11051248410353114396778661421385387052304377861539041695630551535039137025728,18136540266852326106685174083549032333515525540247442551401150755180487725743,3985310545130175559232554478662499499843818415947765870117105273186277940709,4596525943567680471287409788454878169502290977680316722474714256040545023213,21372340401058762695712005390221995267277180470546612925471076506446695116009,14075257312640062020412482491643121652025454294874360644194100265009640244905,16944503245314408069496787236107780704688926045771652862339257733069860638621,6654085263135548167634225627185378533095825854533316762555824971264586187651,14273015308464032668640083373269579252065688901233915918278293118708191497972,11764478817260526126925152191588101018315006712336605965222952598280968869260,18155813367404719470487615677791656111973118264369674303621800593085173024524,10850039649283761393985741586943649861203783935137056310000609328911733104269,14974871370837446170027589325430324426484756076474120128444445200816418916077,11027268992558661543645635853060250199670617750348905948352231500166030736735,7737561462151958609897925089803246494900406501278116203687665387696545068888,8536397585289585667363111427598616854125268561779225310999422087929379230845,20520653588911738970276129298340919743898256960050723343166349159335019506767,15573689478722985997422248150576705853901581704550704092699815959211941071233,14024637413191434115623282477558112970843649259330326803453616105375507215588,21353180477994165001466351039795610246389619571796579650797005446278678838787,10956420585038523642301267761059211443146357574323727078003385100699325814188,17634836995596798350536418601573649005517540866687768902898663209263471034753,9073831830223507407321206741538426673038288500939999264368323867070102600399,8100061233881358546546217363648928017848251671613674228091904606518338839516,14292884686436880002999028765738013651173249817687065086024117836878136072418,17843666610704256421074257091600372846189412242040711501888312601205476877610,7418496999733433074316279404200997784331208365418356982886646484553701153757,21292338796777812243292835631771215001169911232666037289555901315952974221584,21287440813442297789932443224883752220885368198719782335487617798315717278443,12316285862536720021079405901921917335504024672055930573734336005894401174699,3187192338760815459509556016254324490807541427929108750144803145054500486833,6482850190067117044880439000213252508905126459059393355671593783930481002065,8071947666795842917503687890154152458243669781913953337362618950188906690910,21450848111897538423936810899713904909897296879883982984541189476327391575319,10587193221429670115264727936502940314613396351335733485096445152378181351510,3385684482890050363671196710999686076700864071377274740326856556910758812375,15982506074704654515559890904595916307715088473006256644287900474899011899187,11051707205631537861946095917392475702553421314274237258592689190929368154151,9251268179161501251470629870144065342881530535654006637177099334228872748754,15384401424299601275458808814042231311961518546060835375991090955541715971658,15147611899621647169760029554894128666862161642594655274320073446753024250644,10615109639224170479859701634647953864795396211020891058926612120687182210257,14404478161927699835476596901422616937403414811611272602635749875651680921447,8066178271733489868262162784101440625233465103401108911752234818690246453789,20248276648316419325977215090702991722051292305169422329958075780094418699373,2029002457916171156303194520244672392499138634810303216935386602108547985314,21075731183134253416827200425853801562619807215475840771703429923133977728069,14328824218343127380036695796575765857116907766196272954596277912518546721093,19160580257616407097132379087560824295215411994049928358528355359904099586504,8132787339090119872084216324271073977022107784441826475259174173324397592845,13163912407679060956610455137901723175820157380216990622789851897632818074059,8592347632837509846508131492057017267103172209796052768156176559923311880083,7893378189384253642782385691967744125589477790209699483381677762080196748261,12191210041395050728454216483522186705806341251170673836903099334267999015601,2618630263994051322846776438484808085311498796047898764787894432257296575984,13304976328362334711292646669717074062694791647749224129724116074506061700957,624484185190294110172011007497433523891084548746061325634035014633317325140,15930533828823189720011923265223664488732840218774700941123034073028585645207,8694885217655511794794497743599831016837108207363203834593510913033381737488,17331704109224667609742217259848258607875799984699711250101367091564505664522,1143531962761362035993655799963451435028684354850849659611727546724143302608,5414384052493950126841753058585655621007207302558963578017856767058437816718,8343436020075567035126766344602793013516161248129384290738181959425998466132,4832334637017830367140676637457267590768883455902783371477346052893423021577,15960489327340978673041589758216206637417346222123069896632550487782527402630,4557633726568362237945959401789921266559833502098724828463753976542737136513,21292745345591415194683498267204047392092318996401128975083535124377610645118,9328286636803072400168705383927986130049573701928015781654594560657277940196,4380226305886799411237881027947999265683595948968607979382183326525427173817,9767464780410766464122903880954110687963200055038905098288212464855640106788,2341077008076389666838372736815646466482189988625828995627083487505977087946,20374148380136094638123722089889049817432074134077941767483383760377289749825,15787533442296590591714142770598935669897792586470392297628568666971956576563,7633568663576517885027652011215374332444473983000466204175445586239040766264,9580455424171239687884724329420941872151195359863514187490663550878551019919,19911295277809179559313541842789165346180998073715101124443882860854846201169,4696263765841909122685466774945153879000521574484303419094957852664345027123,6118063668634440692631158765198200090955204724365488531804099825202234531440,19475295610121478762637598544231725416556110773059271107863119783250115177307,20179584065699439977644558242108004135948300904465438207718184556293527131765,2676625519221951651755843575492662910087680586300055636532952929295968711540,13080027857034076796318609243033548218531614593023186061246772929628249264284,14263363493033688982783626695159053510832721506041125050282934376406154340703,2706925569052822828207630841519123914917406668054471879280093987418440726365,4296262245978655924075197707705805754837595446469608588294115404804858164512,18695068331082119185822574502658840301072706119995753204333012565779354028154,3337114200744822151016415017664070914837554273478224716426789950128003958134,6975962532267211837956893753783559781855104297873769130878094791004904433267,12231027575978562434100945363599501995871801149646690231633189894762835916126,3888650643207658707541674459822797638642380807202524073478543941467788883170,7676102615198465271172138409531332193754467889637067928466752449336805364120,9811623913757464238022803188199125269665959963552692281954397128646993550529,156972936087215783948417984577273879197745728180593700417440323304914519034,16588845615557743733989563376260327418375621586848888397570715079613783522187,12011819284668339582414804793555969540908484357893010282713633444914261107919,9658635959610321892309182692375199095125363721825304507540533137281497868500,12870566947850007704602286722292111587887779596594529150836676091488336717955,17017505534531720639069672825866463960388881234646040969078396172375695830933,12828756987874340466657656310127299330830014385503837959876241551509225608029,18359630725137047619220866091928132852289131876343072040435717392635728807670,17863140285101027979634946030001422306163257009614315954049905801373677640874,3360582341611046517265570944669154454984314353967466888538655993528259823694,17502670755424560054495200659249586316206934247721147538443383457515937914644,13927649797430421409818392324255621487749881718200898095569535249421816857631,7898469048097586242538236499785851298058905177690518852139435937277393454608,5393613856505501947177492775058221051864341377769606207857027894289988034452,3985540196927201732264077382523049411262602519666474163140081018404802939018,9933548682032172763206440650514545057762401680471287764841975167579530669418,4792769546077532311825527426101752293398958175332337087633556291257147047450,5156370681902535309417699137971512021677704826447998658592162481410036210325,4763178997526214364264420973622397594953864683634906055109407846288865926145,16580450694184328601228411647550657642835283837702883837525078295714435399937,18999059441252116518985471589622428967202991051386298987587330050320210739909,10924663926297817693040648165612355343542542868891379772060513577838006191064,21154439824594463741340124378173590149781737214921140238108168355994559155084,19866718036982650474956880892863081255204850747846301678102177541466640536845,5726341152794890743559900317356587749078768834368131432915420083753465739652,9721930072810562138700262351588760483759343649062887160202262013979665248772,8692713109320385702126858931428174471319167530336355188864897071149715822466,17412352102001079694372298819013833514973940827985696439109156982412245617083,12672821032755011921233434696998986247906307111868736700673800862103166163534,10172970004738576173270726006846527765711642326938611469845242801391711907951,9780618262465502284058891490165578338456400832996467543839344602761711940182,18851700024286130309776897830342991020297865786362943013731692845791157935866,1702470413617318930175864989944938294024268866839160834076264568335720361305,4126610465068493007303692923323412316073023198781919888394734000856090363586,18923463588257096056764527998950010226471775437259486940005784970583303111186,21839276475997615446044485384539051285181302015654907519320251876081314334359,8307810470154672938299109640101353533274474986026012646848648110658880568963,21681710504784331775159894287594944141623698915845714535863219742158877134446,13673546849110664891321911520052734162092211680871085198884137808051757614727,2216218889963359247084339208809391515747106874740680794343547186367655541588,19115757323666287625233094721549891816100455942516447718127879700062782999180,9695759088071708435257280035083149593819491025470776577904130348886983773393,14990538824992915759805383740971251128446161760292769615173978580109946105509,13500547160059033639084125020765777005399100253116035721012986936873938870871,11690620517343570003741441631732985155983668292416671376092598551135607742688,14092995167301878045390831717670181419253620142006537525508736966592448309458,3134074644668983555014847848317126775181820544161601574897784886291988720093,21356667096328346522478877399307107750543924879742810010071567516379232573327,19328894389922014017090671733282649341431509867352021154566219841026028128702,16777200051435195914695940482277275703598221309253917444691069340963118078548,12283150914371601398948839801032083610952821665268602559004246563482653048467,8031025780211541530328680242940535108474848337234033825435617391087509668168,11393488534594129202264782038673712630583567081414606145740976603672179543089,9489545274708587303435157546929129885054870357881034831999260754593859728111,6440297901700932642712459656137166095980435930130325599953289987347675780242,6894515864899267480052927589331916028154612433273964297048946097044117290367,16589536620737203892631819952021004148548871602361830198268389856564419047101,4583341011172551024562134025995013510576215116397573125685762514159294995879,5241434939346739917434576806032039711895865193494390109560604956906855912755,17826720085025179303670747265498956093868413968174402515352860124554701720680,14064177224800231170886754123172947484113558685092392153296947056267698509591,20746239761736290080585462212523994318855974409743295600262800987044075760592,9275091732796562047971474774056076192970912855497078395575768670699769126364,19100348980922843718890560618583044384034028895423544873772560921345167893474,8069571373226602742410885815839523915870737256484068502291195820379222033494,1467293981248465102656318727619114500592839521238995988554329217082570049573,6381288201275521270245376318098534380164014423572839901345374016424121324717,15155207472765568640645705040738739058676005958167290460723767903432317983809,11827307205908787524136950608324322915050519697651400085361964512106546953617,21374803923432823385981703420361272374739614104998515368780896432531799636069,1620198401197709963530631727016287708030541032398661971728351531077981225770,4800625217713746765755573372019630732124860961049092382553729057755156854314,16885045113746325978276736698359862381890909478720549186885416774857519433844,18940059701033384450370562570502818829119108154708321114250461189220553261490,17028163572961360646345264113167539623561504425952365941615928454393252072957,1611295667261368131094571297996490796385397691978293531693197200319130547745,12046456112369511110295802643603369841325461255354393474919590204243253663937,7754599975225661234551263660451457408477000193002987626530262268904609507135,2313209556333942391083901663566216617901599085931440197682535151404828238681,11201045085233852526555327068198185072847585214550933934267941732063511616826,4467724481011544137869960218540384367398804813150942792543111067523429032279,20757297420378962887523157926616026028995120570567878138398997747263606554197,17461435854008784993561933203163122288937104371480871856334630516397129102735,11233240529972088933066139644647717712375997842172826165553170491212908480221,13986517480527430903609790838030615892444640383875866009325809535938190376249,4301929714047907689515030408708811722641058401192285565408232097014641811166,17696794946098216231804098416293622660221918490072683908415671549432039016947,7439888160491058128389941744272690247182736763968209695016076283096704865863,18423890552826544443227868172047086037747632248290044990903922658938527547680,2138999949837278709489832079964510183830385901897653052233908704951853637094,8615970277754580973564280361114435711269905378483503993334701750963152744511,1245284434872653312507712347938909167594598148561528981150147522912318212857,16245768201990863935411700653063134435976966358871420800168843470345424885412,12879861318323580145511978223564804504159396722688932396568245995032194740594,2552284675231253239834976615340003107373525651900622595931449498227491766869,980488019139379194961142515231528163966929536082343598209628148732322981564,7264750621517252424008399274736151499285393886075664598878039391991523050881,2234522067987218377738399151771319350093309605278907663987720519875860528325,3115352127411243786318531509959426596747177553864136971519102170874744602976,3667866402502198123848250630765454744061857715778956702490214141676773902196,3070805472938376665214561241692318374677535766486562510422267606125416243825,7823349275852374866499481666710330223055954666864547234510846404777769619933,15260540996982618345416395328474127890176746670866447824367770359510137832585,16879450644311650077796590833984905697151358442225768059780947025899660370589,15320151525992649849875202875042133283365355535963553893454329179458534031485,14632268633016875179098944659717422356155019599115523094512078700042675723400,2897293850461343844445387032809649396366859437152990471719742534237008502809,19666002760225463497556206571085469154515092232825812732816997876615778032614,20118956923652349866364311940594053676005949829436315819799225245413961818420,11744985056755246878773405286931074634975698324846162530423833591918403445926,2015290434884472026423323399096281629968890595973845384920383969402450506434,18249544278720359760062826368546772272198884406461513288445757927068468076813,10696154943059697598572810332978032400281533074175542497867727183214332201316,3971341798054170372777083512695270701169903687966221904151853325481552612966,9959663659512617071119055590004415036736845473755952682208877124936249722622,2181868782404294694165345801562667214869325590275262047722759281472694906368,16543662218198449396015118334228119894116585978443535797616874635898860943302,56444853332991525451220607324577660725674378827134771417770990653696578708,18053264525785010356112278932118420278769989354317119094784720416230380388033,963511433856494437037779480692599956325036862396765985497581773445785537789,1640548195682821030419870544261428767973895477020340173398587128599119014650,15577232677357883687312806010171709394572550002708034453277797023283497421495,11090954381098620504472251563901051846520004004959525348540953956152044818938,17126684395012300883745178409829259734795520186865031009709416122834152378303,8422844186088908124243365558762687987341862957152073183459572023886741121702,14662184649744589649763530324217861015549859438835398957469773613387857845572,21031377022606130696364565229626602575982595290181000993536506695259062820250,12689389963301532909415546365757541009330035137990488344057816579888146178666,5214588312023400585366048036841380932988375130807938893042700215898846591858,15041893128824524382738883860992957588596383766546394405410998279035324015705,782192460855406809992878758154419200401389375934686194113667662665836876265,5661239444927590688224044135973292706791664398184824354673135332710484834774,3817944105257087067488946967989598283409314186886285679195995872866829761906,9462770371773357009169408492776891016388486549772557694482752113820123322232,15769763308905916572724877727092407815390795595917044619305377061254245212113,13771914451667791497863967930538877162560051760275863288476375824988661915333,706561967078473376761233253052150494577539018705821668938338502999740910843,12390235197745683286169097117092390888206044377209705969844343148646378449506,11145596728577531179888406424537808841248238586984730649700720979694309693930,15681641822349110677199695953283484509740812777386467296516920337242539284544,17574569459993920657262688380744386356573422289886331853177778938058648912158,5624326259006122381461763176192388804186780246412847832931645688163746289220,16496277716358307095107833912170230220700599576045238114071305799889738129888,13435082168481898917836725813624706153275101528359222531631402061384065427333,14145359265331851785705850315135126451460028716020850520657056103361268407457,7994845231841309191598369070742738315856499258678582728014902950258896103570,15231733338108258465034981184038200743349384534550555337079556783807466295081,7713361220902077511242971379188205561979775701167781811837114504665826686675,11242747039712276301478013037107867308448907318991409117791290960665848463140,578482125379746689637837359294794469152617864738083364508568444154322295070,10411717957746838375775334848320973308009407649021455865417509560443692302903,20227006425680272844667600313609218155469920109215388465037566152370252232679,4086233333215814731082706125141659248745981704236593522409792368006446650781,6808584534953180557531972017829075410964510413317063595166364533912498333198,14933356623681974917513408843614143743808832277364712291262158931793965369957,8361829936147528340154802497787058714748584629340813748839621641190595526650,5538387899076347863195504194335672966840748823754653039217054113809390157835,6615705984888160955628612086123920128735091346352058978084487503753552928718,4247091362085081761865598677360777173802067597672781739780149117241511260340,4974625254311074298909209418614844254599548567616598303359921500987075775722,9907284404283923304330882823688663208972219438730081750092058981162203620514,14238658152145851054995618234965786835935641311230999365757330392464542182773,5602036166343678358319941150088594172266643715315669628685676756102877898852,10315461382975117983285315435824656113503983463182219407091635205239799886780,18907680493658247637744313142676664986314600274326418373879671192300682190898,8553303723584937031207437681614026720261370015480962759264727133956998736136,6891145490942460969785177369488530687011218911690606251233112277697487049464,19170245246106596353570021916624717497160367167030242670159454715827568730304,12963872577905157066479007532642021260793201956955966146918319119859824768103,19825143672793576100800645640010743262329532693712002233459160547290155991184,122363237387596939334930000068508772338726942066663977131612051418977350004,14083010722716557573128541885186700095072789367734739290283132018427397490175,3438988943822218606847460625826294857914025511956848084069535393649532189446,10824463893276561180588773956898041497815337719354064658470380006885795713398,16647020853733827256761129360155419271528077519934494581063879760642045999108,14779736608400098952280783906738683105991809429340153405681057429405486938750,13142746404873014842415191205878004285381311757484122253939053617110681448928,1386333773150414920705543260472370744952980454893569383627231135209073588228,9697679119976816079822213749536923969219789272727871054723095487806154942217,3460404774244857416356250946884568630025797822298777944076755223444927083223,1247968706400267099989617117009880060043946421405967563604685657862139452642,4507768933023927635709805634829365165299253230159842263645571663212665854586,3426290614024232855381062903753364259178390841306198547519682507770097215868,14446229460062832266543880366376059431654246279317515826580297094759435628761,8067953446832743759173288639514778564060677449303509306198517269476636669111,21177512050925009490126830107933732327927737774182499659239090599165030659885,17012508948587701524178526490941665696519922093511307343255635334215277408110,13790566627669249053646494281027520203709518820977624221038904711079372230598,16958540834863372886175563802155893167203339755555003665356919890498736433754,13423323660143533006628485455163236538714121124914329148003611317540843114521,18732130441148222818743122719599795831305992743627249485606912380686722650328,21744582565522883116221789698750442373155722956313850154199652336110648496029,7144354002506963954801968243991190427536676772300009377345054067229788469802,546773555852952995236535448961524872583912665647152978722419200006698017228,4115449488659159484679292884434524602598250771770554945188450323754895822199,8595752591492411960378746550184866534422481915151040676780917721787338199480,10165757572338172851680092102888140824090130405358311565741520039277283108819,13881202481966783370628597357006999877307398877082297393247431527668438855111,164079380527758195225075822377759030452558671627014461867366308987961032431,16597854725561663920154725753244355279782548142174519652163898109297275062756,18782804026635015341133877400860675283426234307512052057983648925359584161851,11803457827110915157916889714293161979623605698803927824089144848270204757888,3790889121366006080676961526219702764983373811240106724685417109395959845261,547387322589169298813085629174571402766705427171260176930124272482922852550,2250336107342267953278191463235028062291289397936525878162948482155007182474,18878522248575655887331882357174227152771300904536167927922454904180276940063,5479817494658339363150524278522534672218076031607309533533517453567105458144,14471434214677769494999424343272645790653559928767779107202935041996962964627,15118605967190623209837537416237887934162874725496448474965882020979641133025,3039022034764509339398468046956573675942916248030956764556346100611315129267,11040960503243486479242227243433964824049773842453715686240136222246114618507,14522024554516641986547166200505804498300840654246791399797761270595590503741,6835224295711983166071915743041027338226822865794125690776093851440377194137,13366807550844486078755421216059218883003148232530961590657899207604510596943,13252007130485429909186723432146549270562877209239528962258894291232641470721,2492164358128252077612941728095518049849413853275094452844245158937134153493,17908308295682961911088181370570531617402259473536245650574431533231050717409,19598815799287079436414455405296166262841941910574843546435474727483962158191,12296683988787359527811189035096536832943622321600079901820428531954001883453,3034216468239708296411368036093482845790159680213461245275097466511477145032,21365662921308444671672644376862924257055009191312934218262773003828812482536,21643121605272677508602911313799693744649969093302740901187983246336863173757,17106474623853535335864151625226941722837229436558906235895607080504648969673,5170493063367583327862860118856811567748934103888623432970286709351028834594,16157297782580756629356992582192341437261969693717401640006420404649789675283,12726902817862860900369295542623896245980247290073629666117912397630392192361,3081548921497703421223514856379500960238907095191066190890406228882786538855,13383733165408518558908753036431726341720113406574723548828112868926423953299,17114711170811861625673949085444809223764181246137324935055609379301828432643,490084821539048617783395755779188347718107877537460289908857747116706971191,4649874458515161549974867873095987666703831126237318082002364917533053056940,18309757296672459101064597681764458207032523283974093139605613289699615669226,7819183041486966141608141659813055168335432042159899601871834502038946555307,21341796073041881721040729550176895226179046215340279859887156449076052673189,8964280440056181910087237574225882257648057952084687707991537684955336080915,17214415387533445163014526685896715822410886705201252936359885537015585673030,1103535976918892886566275197010540828604931300309949743647411661976344710321,18989472017473838846112035962614068658032619400049135145786394166114140582702,3261305106935504628452223922938937365963307399148885220969836911471709180672,8250352610228962368545929233808273614693022774196635878184474970985288333646,21336821559645974200167373849850832540612240140661136750527391104897925746090,4804442184264650022914507746660662354579855239722797010340948536245079163068,2980351069317208287298989743520302917458165906618872700838358045014403829821,20789178264137518066753395738491570400211130020259232167860189045958431732223,7043197173168479199982037485481873468680373055205806152875339535752299138160,8803416368756444354155108122527515347994446936702934474369040166131196644971,2327814593413519022021694520242495352706688146726587158472403609475455845031,21198136442842149822575509914524766455809483419897291889042050133491478146813,5588816308782619790412052393435292678862962083038610001710149574381906419148,18457707371647662280814248200286355752809748069618488571669726734664943098742,1234389524319480772210519595012254096434562205385972935754568629194134383384,8590188161561261795686801611365857510200794054668578839168287669047410512276,14470989978325106127256991312163042779416463931400090968073878504946069484989,2305522070968512786738458204005001050714630746016184992510479809638463479749,7477355783744938536562522733347415235458953622739577251175967178186753572312,567290291622042941074701939710650764088062581452752653943609540087956251460,20440460641466928749670992266608077799893623138336747959135603955102479614007,3054829023148086310176268593952124817160009906490401089445995945337990758835,1115018683950178281685995685874075286310060333362422341896901389981346771770,7809307874649635295815564328714298840313171873184814252455880392757245438416,16435322760021026161995603943756578712245360106977256514516858926570158830261,15538054347747268689904146479533221617920707373984233068744782064536586402847,2145106610221843472170037420099674539983626911224263405264737836509031499186,10469489855508967606640238771767546316388755621910047798817316247787439887327,19269976274347330455450094587958438145203987980029244301223712026832424496030,9442647357194564700611387347788116150552532746010343621293769302924097756012,3958820742734683830021295040986048520026707752457985546687457778678735761219,11348329600459394107897118896385152488024741286593365288318995787678872184581,7994061748163511046803584801099079098965771882190345699910054751589174660915,17839452077827445141859404251925903822746019560954563061323642101356666431414,13232228834563301156710808377438125900543901439977087615805079133929315161755,21820445178921591403441486524597609508081666751352389500190809234730066099269,16335255581063466649418326314739202718270800342509998411094897137707475468574,7815038267931398026175910302031438514210779836695664391140597883647619726660,6108907775060665614604453427927916450888778767561273091208488690292223394553,18731401306874205485033288380603219954710608893214981010860304692443381676445,9207310842136026530277150017022352541117999932757777916196896007342718304978,4275597059348294910195928059046438407683127030809544814087898068951365707578,8551726143850685533914504884506052366269066663000473253249997846823470852089,17722307737167433007678801800007589919417323324870850217087785924251047414732,9659885913999670803985648240505723928144853579243576606650908903914665975845,4127785260298795455679482228123141201810011802311941172182140342819621401490,7995480315864311476694461046721076190059098585527103653430045699541205743090,2710887853573837837653751249029686223333938865050270571041154550753948687821,10929954836518904033304553904442567770321295457957205208591304372724905918438,14001950425766109615209637768509276336684867788731325954527529665290504740308,13093798171633818149701610236482430519636222108426384974269506295925166461929,341112534319506600537441322030652722098845095671561271148940215817004993097,6110906587902719841743444555887325466851146812889558891609843725163499179004,4611067237252812652698946201052371234192768537459773069641551009583406296376,8813661389433335471770742946393259278020908342551057181562786643750538648664,4082028201221928661179738646263379819458232996637786410627338568216272942842,4387150015663192481675842540873436578480016784260152864928968972841893485475,5798957359608013690581519427700262504660783802132038228115867574470007647157,19722104754281068600204006779633412991974614044671884281702255273995426048636,13237763289640918787304198678609438981723281080085860502804175876747302592942,10350397375768871942356366001436797697061286173475393119069375716517495164748,9716754658986776864790426519095473979615270133917036668138857377100462313944,12559455792963077442707649745319068600669837985026401838048238001273610719876,15691474792343664499590886820783843178573436351948842211318848415073250926238,2315152971409777702150694033027032394728963326020928261979764797562368859984,10145932773746660365948684949555749309408495540108698054181994778319619682499,21031755674184251231918386922772885560228556184297650283520145773416227622020,9656774539408247026483766906298154647226870877463506520381115258572281833777,3703366867036538119931629591865173960052419475390100010069369247148720449735,1155849517605989105668895794996696646805146181003961935923384046079365333956,9462523438649504157500459081869061592673258626587962773726459717365228540892,14558942402093706312345858485376818615887511613771478694966109228129293547963,2812048253376149161843484904554248272181353897695109556171864471465530141300,14581264237688674105789045795632866727938915214983870169917226308316644895751,11806517668379902968824386871470726201210807458248501270142903146174354419162,4072157532402496076820064418241903939352389786658517709744366379045220383162,21813972253527564887362886309776329116642260196272043100875592141144150622785,10464853353887659405357329005361733216328104382848677769669050984745487501147,14772015460668233451710325522019255336227111235340236488781640750731630746977,21527357780259989210243319716428302865642384867695769975035672624351025254966,10891794486798293092627071927690327494090905691269827842959180201330098409394,13485855904336418644657500553650073084861569474830727752625752553358760580285,11448242815253167183767068865945471000243774132210813929164325622036544013989,19410155802742110833632454245227392555968304439001009443806761608484053045554,12167659128474886745250741538637209499739823457162062821474270919941304684088,16680628007927224771777485144832808896272748488695838488671868152342742322186,21298757047923195531118553955836039383942072424271519371368119907422148509278,11697718923718927022148851233178802389523673168156063462791132046990360699116,14786267704709019791824267590492332247783919098705756794174245591027365669638,4029431706248165284072638415134780930697313346853706588481402470852714029894,6637339357364931518321345115064554926275905427738668939829923099637974821930,11721089735875799137502005413616822380279134029969641544449026524015093316862,11258510956066696357188198767462611223354755428568008829233602610737417570759,17382216798452684990847332797566093767764854060615116426813871855967998298795,4497813725838018324398390685637602656336499793658559967801659260213189483769,9309905740467289615895980718346712749846725019185323382202916800724200146653,4554312255934480823406477691403023661425250519363902231000470326223736059080,15877126774677139396238817617140527789790929268045936819000883506734809330678,102909811737053415440204213495606488273727867104784554516589930311835745189,18412616692627375517300170963764173086100899052204830988805458281556342306704,12497849254798953635808071778933029738229621492383212989583296055326390275927,13190130371739872388747884175792586030658495147350847435106581404654633998344,6569505978975360946878354767391913708682729333577071120385232557177773967150,5486573030999616702165020120135398562758060949059349810688840632469582165448,10402649247177704342444720212899468852439313211834653468379224661013914061054,14870393688688048179476829039887867662050219694351765548412705799226912185902,11112866336990864101289111553915677602536611363742637349719791431991672470238,786378775702052024749700197105312354581130448431768994347811552323325137023,12804314666740390639363966758718513558509859637020806917779321368800352250093,16383777838797313001717025761299072170493145903921192845224827276088079299324,18390795790658866542478563024059495583921996400061610405032233720404354578517,19071180375782447479569450482330188708754447860024817674265020413221587566028,7064459298524756483115092315588548572944660746058573142372140457074172044435,1201661337668100759364810191918525473246105501963149603200893010746984240574,14673821426225418930674597108599685172091690120026694257549676255194170791868,8007695637892306475030605880993450528464588921978475145792244443873714795074,11523933430814198704411556653252358930965476928606503642553530463689321317157,4720685254208822524727003349181010163122046826828742211508555904133729568685,2704641256375089357490975523544121554540568505171014265704664461404637160537,17873735287572402838142305036318020439254672746974064930437541429239252592118,15591377870113101853150486245422804312550411754131695747717894157544182932395,18680866424621452161410252746147706712971801673312117262770403991597018010533,351092121232997110902065296627489736041463573095030601146795248738327912247,21410776897919290439576321311168524383878404907590335964810760611175870803022,17236852113726644484641871544732171570702656662638441976539579805457648241354,5141902767347064892821277441749408218256386923351945667768202586451461154007,9061206488410388460545711706154817066096529615910172728152676288649487389209,21501744386281091461333207234319069661329384520296829009605344252699881602491,20523123786355828261901087089746676928050070859811577818342254696196216070331,16340183952833650334331728750144828293293213803155672739442287164371494962264,11997165266626958619141537683193751516111129514708339075256579474097934990898,11727998419969202419125826890516046584560800158309390774599325003825426052070,13931457202894182485995482691171342703522733597260457019434686547274942752168,8889288417892697124945054364222718721845070552969370183001562339292498026982,10607636906736209971474676586549274600168449611294688931553643349980364319662,13373379279879419696628639312899105244563309886546920506727138704477895635504,7516778707927565776230701116353902556324173125006482617300170811322359880287,284142816263687923446544408203711951081978657997111022490562722442340431026,1663629018772009800050577108421747444431944008366135531327269967377988698730,15976560170935104892839671978479711290979780560451333565745657902528940986567,2821894717706045749560970435026664943807315523436547166205412842765540126279,16411046577927712325274395387891881155718376469810123282180259561336053360599,14830500017171075678309056171812981524309710840633235720674153550980163992149,18516862946535092410308127384088576733043708186179828736204273213102857123131,2803122828384011132142130003641446021361083629354222582787564441368260233535,8655048519095208179618171351501333519098495288987579151859877773818991560313,17628029087309631764673769418575149062296127129914718449980855676793923700717,12213182221565572417730092495989703548687597794044608925789870740387528958423,1942254992896992114200957837548346988692238147738540593160350563013662461747,18572481120445885888145197091838633506611989952111678544191205873056195137330,18140911659901689098303870986888083953843757583911874535981587625576530534701,12576912117641358754786901787127955567685279522839676706223096592944048067439,9853587546273100154686512094544697531675085181100931274409412440600306885014,11051022304629047704897656757884328402546597879242426643246383517726104682373,21747178377575326127773834076417831630856635794535286757990250257220185876652,14802894612148412188667842094308733856318572638297904757997514236587913861527,20978447371728675031404263158195920974895558458780873769079890388209356430130,1037699465155917084450585874080268028561047537346921243992399961945112783290,4796870784617170576045350520159043022811420003073563826183620782718648038813,9853767424749529094226213721882427217388134769321854800041359789143412725618,16909978741728448404835572592895383783360498936047937910269991412415349672326,1843438491269241815751499591631260690521017848626075859779071605413804154431,14341379518602865584962107623594010671519157088756134035711400970326861508492,11148607079771922951721552848779822101435560243853139254657574581631328105418,7236118376476006500577604441648338380683405215283131664289729852364085763863,9771089868728917573774866709686459919517030662395798431632764214674312680212,9110797416046523350769719273137039416172041255824880845510758575776777500007,11171998782921300624880315291878283252073139909993544537205045086249176031551,6662646470172779612845827572259867913830316914285246080650610642251248472832,7840073244312824502623215399534211251667887906747521505446844849673459134791,15746172297311038934003440308705797271829102199583540526113736537482577060229,6886137335014489748489631206590121074634704468637741127875111216297167474235,420232306382434242751186173486850411467398307214919587427625546445400284482,6101917029417345450869344197624899835171925047771043819872045680173320199082,20902767593677591005062278004159629853556955206212143592781424915847484793984,5806682782059166443158221425741828463380368530625835045262822570023351074794,8937322067898730475133772449174500828509823386740428196387523130412301822446,10698423376034838319080023911266285836831986186258448454885030311257173631094,3804139705083664873950903601295520892698549383396840546300663481183626370753,11666167980086510761582909817125709232688171970969608229444060852628732414641,5195343484230074513500630640199601466733948553952258905990513870281939709899,14624340714306078897305540751958284706578556105002276099158477226484579202503,10083361130687068583126496521090418135813124339806220406205408201612392141304,18641596433875997766126569678124500204213295416321224520910179376654463020142,2202590858941069122312246576796422760143586439968023643572584733807707875591,5606778593839139538330184356292709713321311150529135965207704575468867770974,11958475164655758519149540613838246197985233378525766327961909142873639847913,9229670488942629146704143920529444712626724835075235979345002293458105678408,16754443145923358894066339463409997111280948017357151500387305969742481068301,2409255870410101963458063337813762581436752424874011147061097403491760442109,2214559337316973031881614971177447231501212859777889339656681156270831720504,11421110362488121690592793129931919017457696830596130693048382951666066696299,3820500999703948691966833683611482557851819710346178343790665741738753374219,8756218158739871072278901807217627680176358846778830959237385752221505342071,8032449730250468861487267430306584116120245106718506069817646852031479757007,10243677923364935391432160448413375676421376200851541463326287529268288890040,1128776597481264636069298358213640667665677523022374620075432951501260575292,5644093261057489381910165706940112111858706948653266534656144218172488885132,10992382177616530304259484530083164550434687278050566643026419033635199094809,14561508845841116001383562169823893923516132174944052932403904968433057227748,21863964650894297432572505174186286520067123468863642727441839125002713095277,20755119936203820147240015392257516486599536773168698212709082762309828651450,16959073226608628398387152299601201172109169744065562346871992262472923761717,1422360831209405989940170583665509252269399522601915800432845527860741426172,17389326678043835536716857792606285368419240597293609647618693076258681847452,12197527885708217940863852882450902665816552534167940448166754267717839462635,21611570070424770005490607477701523898795002037965850794497143400504853790221,11892102040110397810197867975938039639353004723546075702397206087388005784781,13516538003340091563836438322533954338394185445401173280530387106662595790317,12048467357966566407092445451263285920234083860460644072449020638723740218202,1735010081751908190348908571270511873519447755491670766716880879623393561967,1975466263323070433866371621575002630840361531361829342799564009137157551290,14332158763257273099367529977375112575029271371581919959093592722516585473205,18308662877208906527685104306067008785578317983243580533749074382175572194649,16147771244577038318738675557955640363954546932826136022515936117397152662906,12310104474053287506280911462776789511537301762185944649254713583392295220302,20727834941236374148190412755081722896905078541838912474132444343774737989102,4772017368444066833412562265277526529104319024388995968178984274657250179860,21049615822069603562632099674853063708639208121642147875791882100914627258965,17646394174446098039184464463379581654623553955171175600685924254263103033801,20405917523260600357692281918105892289710334792700216851356175227972968907413,1288067623955526969302061242482178260544140652671589048188723078863398511616,10835537730223027316050378066698794099751744792059501849218931290020119106372,20990157274288749983727934109087848093794137769592917583326461140632177148526,16941875865072358419938961334635058647868180482918222959682613586029647175353,9843778843793690986119532637057920745140536160016368781021998854678847780413,5125414792982533413337556654533863770640044560799521974799727390524971858377,10864462495296760172304401051361158670010031482061392973919136670275578530070,18638188379508145413237672170551928898223721010749214505292285199256581752296,128198311352192300389214509562427846527025583978725552204209143056794270869,8639617857907165397429617535993768106671328412853872156360019116822694247239,4844530255382539675437452182943895677920405337347260379412255490567182702620,1804675521808388615789572941859899805904819249465788091888167545049898256219,13789062391664555041422570123657413036572356127853659660401072142070681096201,2984776938673077398183780839702246034953572367406345432704517332443032892459,2992847031807357662780885550148860874749067596604232667894089534007015158636,8223481330716908812358677489080309112433589978061949842348101802357147464280,15829423985005178435297810317464595131483457001231013788201382741845473393508,7862158982782368203916129371016962734683904219117743973675651114828548094092,19398173801438973209233005992391884365223581634877055780725266290648936529417,19275863963890569296158744143112092383404704340976692571347641477470540348192,21372102182460094800056358406250397703306525384763761377034855645794765423371,9476173056510831081934271835896053957562178504127106649888600367232767217909,8945631126280639679924915282277004291625109402912694487894772245410534789081,7926253519938744933656970287399447078338275573508348380139787090085253922642,16018716520675458445608001155996902645263605619338294478505090713237417816972,14921856253793536148329746401088158240205455851010569917169181161371242017185,2079875574141510421000322245042248069972426430967618609676296915817312672160,15980599742048633141868186018745285129739756803812956666022183903444182047036,12114893033109318668956482804227784987572764113979211644064098174620745412136,2810098426330816525728669143855005497849959012191227510766066867001705905451,9142041039259596869436365631928849454803241725030479248178020744616036193428,16789255887716308252460957605463144609726855240455194269099382954389067176728,17736208027338616948877595063010911429975090558603409155923157365536120955065,21150410646727639080649942919157548722144769190804322567561458114897439673110,8728923715723554965990413741235509264041126517176940864777942728557354521757,18877975508697261368601618378333048287851497514619873601021983336084282573042,5857216433172498779920090709564798696432088771454963449283671260189720263346,3416739349758310085403544797458080484340996684307665591910516201053743952382,10014661157797313244292934148350131996657869525790562708237180274791925878615,5349492492153439871560702687440086188179846024931646961141799958661743380684,8090802326500729500530853058367718173141097881651767619458686010109346379147,3243876699925510348842975998823895571182658963945930929780026879935610333017,2417624030466093278001094443901143647464035143208058634414228940495675339286,14707208083442648370683763592077614356382972898797034092783713393639907619177,17545631002841426592730923010822053419499562660641460363423698482744533869073,4421380624161160840991891701912641613710893511150975452841445166075745805974,1077414817249103950943875081715965937853608110732127257676522759590623460183,3507723951294024188735232556852951953031271591466929388169161213367649583178,20744267413157655820488615250021371239675627876287191610069053435816486296093,10030806611757571510773710000844469375387967668887810533790132098599140714696,4098608919187988291739821341638774871917086915024686655297087774191912756808,13453755776490865531134267856063521315028666076529776333450382526888445047611,11760020934758140446049369723964305600159936563536726075225660675360331528465,6406037247037697473727755924858735296546535018055390677906442691851004797953,11557358458236767995494355298696159281191676229524038284238319440638237580594,6743825309135636487078170799646071187521226570701598888088674184356446519660,1363740300261508449387087660891142217813794297057216573859174333622397381039,17353086088993821287882776856791148032337098217763977250246938079060857079815,6718938715458951426350417166499489427024335443629489544367851434423278337209,18987489742261748676564017446964953975327326154943753293417429206546308211028,15965659332352377592570514074534026676650570619443318860049459797446297666148,20815651494112396184410166336624878644932077115689590904142342335838514032225,13289193671002988855733226768851953818541013880219936597636372756289364866355,1567979574094562858336626709833690822884595003609499722973068728155414218656,1406894286237293229723971624858421702390230552459261102967091748375073005174,127524353461789027170460839609791116742773867221485647945877046573898816494,14964917196913210912898635537202273294898388149888129789323384554911752584731,17573975090037837489354042024755208350546900760352759486497415097145199425437,2810800768573675011848063715305835214048305201677436448513685242208560656239,3182831596404920556846849906787256417421227529749874859977287400581732004348,9293221288281284622603029762317683176118521399756060307438914930508616154161,16673727443492180846335195490607282587311771952172084861120865668023189607968,14861970206393540357193848383493197595010751639867769363872113104941368881368,1947459730453714728047065931026988640356317164613412029204943819757651786269,19307336986855330171250472129691969885469727663168817962206758878226019668925,16272723820736869927531258455696258295545428585773733795358621236250129636598,14067203273048816019998838866277520003916774532401938198162316693809632760951,21551507147108044169777874975479534770240991315165807000112720115356653530622,17717640130827927258645965421731152649890280820567693269781156985346197796607,8341245955737785666220035421009659068228682392298228242003714027037157516189,12339617302318828762816142250616108419519769797732290739230041883942137188888,10123566056273217296763559440410478584111931737336670797432668142672222468278,100330409846079023411270961296323123363585075447874304748480232510662674144,1571586856190083814591643193451371280998279878174710717174319810741950319455,17626078717574459956178559042223066518589738318146553446930321898524763562145,12597474837573442277568310997313425097295312228965354157636545560783225415194,9282629691296360927786998265863490172450342562246145699272852196309154676715,11475383910279033220892799115018315595968658540404734297367799982184306742405,21207578382911046461925166339581302823631975619749313031737447832273859578217,9867737209512713742156966231095908977298144995685201344042106615506717185970,5419250263664842635521293741086549956576183663718321466133029062700646217820,10680301618473120824196964202055452643700003562180874183620820959381512387087,11734118782551011491731695279474438578347930162244424307495336916011158044578,15017496989515336959243556328206095618035482039354824183597442359483266217611,6511621188986288868363472995938291798169517601112511039955221592826262879815,1057116630043531259822644333647831844583791045276219751332477616072560117378,19059685203310882657000346272623187407133972415131525465827340360192915270217,658459778905143381055609790895794611242407110015004801647654573954369450993,7603036257465538034144194526422841628761243007297872008772468055256213693455,9990634061622229590998343828576831787715708492431159246049355339866257946620,8811452869339089802509557934124104823648284438116748217266488878838078556311,377338624779519383654026004940027827544698613282452894117899417005371283013,20372432760811032237009833207612531537192479064270437032142982696970398716892,15755624168218886509358985223476988622172061232118179707766784427029774962558,813530157019364022188179508608879306640863329215682533796638454834580544088,15366777101659035236493629475299055460750095122762878608882821037262385854171,9412569363133467481819948072214644683803929543842857451635373713673797937906,7663229432381596357590875498997196481050744300865119408024986926994876708428,2802277205489381760400127515311144092806348374683690687945106801827615715524,10398607437116928120233501860786387490329760704107357815670770315190035281298,7713454417232694103114115606745926964297583014900008700978733395172058088330,13765632281005573885638376819890884715413389187071206345092080625293363780493,8481595129822383153686510359174155430289248263706955785322350737378030164791,19662013748902527903033807785062252860528102610990787703983459073558867314734,9308675917577065974819002737905225232234719968566022906777214056034139366532,4460305046275724592205653945612957908431797179457871442468403547092050276501,15300682822970503133550740797435695997154332692415846288727432330759835456273,12237959719178772655779639362705631668446778143915144512652426042298606318280,9074337685905972785113091085216241647906400276520026931456332814507320753649,5631451392609103370493346239448329080866515797549576094657011047227839672541,2121343968626452536232091590081231792044261748288461026059952209827486505534,13428337287072393077290174792209446111049614088462784414150825648173933048712,7637923455564736402006004688931010233604652911202725935144306827988683195798,14145144407093909228652602933032447693975357132368479264731012546112843610158,12996083206893173697199261663271430611160188106624571072102983887472126762111,1731425456500536573020772566007405873501250425959888611809221924317821607399,7235256019731839713165664289644294928953374624035695945735560280325779220974,21068041929715170328271489788020516757451181357080748023363808822374772951544,2613269578304019608168678260820703130619030694547890166073793773931717299431,2895580764674798551230549071717806800560472156999393716124982187189744328131,18080627279556321451131957341924578248984242962783250736655220087867816491510,8541787229490752355605354050088489559660583814306921152210039891158051673167,4773003619955976464416147076099271361363813479523212833233541104584120420092,3902657294907605469046100206491238707374466860318674919042657295835038516976,3278680356861257827773728996810819308957995332730291009303523122858553038927,15799387696541061708257049935405397874115977721965461912710489016029411671536,772127417921361022785917422978769290675101599783616547948775836973315286693,21172675246800560416431972802840350117631380023487771635657330436402785697771,18058055216124783386618232874069776997923635894599900180049394490069349321671,6486774126469831729812548493701084245613732338682698890925717889323571075377,15523424894706974280109344562353257665535312014690869100282355992032362528753,1155165761749577539253357611425533199963683430668786603835581376097524220748,12293270303409235416382105881403663503297523019464344830582632347870203818941,3805029697086536368150132668072389131584837710357108954351676850002928826418,10383737378445903520223858424352769490012472500810730319338019642336472424460,19139905240360031959084644666653677709382597275601060683474709422388012451876,20662040367334915413974593999171397527205617639639561319218396170856657836909,20693045501044506792047932972050932132614012706885392044610670760209701329210,7646436833143149025181986338139180317049527836176583246163126009131421429218,18468267029773286403821867293367277456399346317458918979624725373649687804739,3368837325920673645463134045719391515049969019513957645401010913338888270435,11009184090818836540140614853735105475441340244881441725231380311734117124613,16438249098211375676141540117467319174575385934122099955146653152842543524308,1978426318655034633621003481179913733408584009919893346861360079137199026039,10835870076129494328875329193612835430557328436367520958854318265497818180707,9238585128656275231406470048000584932169168279280345637986485301554767537943,9860408784513424998732752702463731273076404557148376009384338221275998841902,6200534253629734756957567067039457925613934220422888818001227120423772581272,17839095320044387599555680620747734440255270476109368494374200849742690805825,15852210333828297391427169949742706715097259872699655846272917384634556986629,13333830495117301018203298033441593118871576320662915411592512406905971557482,20141868252044007123768212581882815770873248742867175012988635705853879924105,19536412434762756561256835516560484981006774488160067264157868466806483409550,13376474825075395326396381198361278687546895119831914117080307993251668968861,5426793384935877497416931155195289044246814775306615779818726668069304816143,7377826504693724659923090551901604172560455391003832805477022207542742841455,15304023433512090811722731808458537014494291201252876199903945357536893662723,21332460757344630529450409218029849205820804076582364819572498755186176235236,10123770219692666599208924625777509883271312561577690589112346574716432563379,19563297971101084260099820862783813929179580711197283960855071977068075400435,4447207254069026895839688542596519844298864167018271339727580848327164733569,10805247891957676953966507705079087855877568284903068495618773980630496028625,15247455859749071900237435930523136345408272002648820316650110622790580875976,1523513713815340967949299977561986680730112913862622151113511170812079722460,2250092345142769832690429177076582432571233932766644284160212961505086786198,5502205194489637815685308301009607192191278776537698439488907603617260091996,12376110094727246736838305034851207905481280418572145688559541407100489476563,10967543165217223191795950135818653456591208931427429972754586323384063916713,3007127915385490247377746617881910295130312971235615226220093403044166435816,15039810425747682043693978030807314591772830040893968588297240388685740832440,21282434502237090849892927101680045504469095017581606642683944529102929897154,17820554077495649709432871866725766383400924076526622095222498536082233385393,3238921346058569633798159055732162989904755716515207404910193961449538091755,6963065779232897395043653410311694992252845745677523471496668662716409139923,12741150889158293058202855298380167280366511627706735086836055155215291856874,8505231440570036863755136868680092759740858472921139738784962359970555463386,16263867309272856871859017360735124501630350380225439505739588230939592341511,11994652030543012675378700484156120788799454178056174639173766735729691200407,7531001745062176388176369578077819605743320864253593427909699809569190244306,11827863847264026226445842677102655786795007713756694062525124054010199531855,16129429107591815909860445595042156146087129962390514833959473605760944146527,7516787161495467824155321560594800913116855117833255279107222188682607365695,10052162714097814491117037623656731155747350728656529965818461926126557689689,15866126693591846474201863966897712396582450897559972801925967203045783070614,1769345590280238074854062499047542732649300047644326060581629862863392048630,6419881722518831944067972549598430355215508824227908646199374367237336336567,8427762909619307952658968866443552584787988597438819510120993141703552873807,7893311334904009120458996652611823451343891633360441850908461624396886564456,19760139770663625588230394835227131962944058142185140281511805786245566094372,3986819882418057034478817109485859706183862449050678809809350743539886112292,19462740190201175689471975116541495793256811137828607475310915853573746549315,4950984269438746319161544135494005780273536398471035822969257463380210776783,5114126436371649572151778297196722433397981560175541938915777654399517384867,6500502433233986724406965295441070598123907669991330544723786166137230830713,16317287950659298477752416750967064455139776512193467637272228586615836234506,14644311768591599882243015624322844079095287900058309581805861693953854143586,5280400910054229241086158902425292691428494311972092134978890627089874392610,15127218399002910266114392708998449241113801821878209170134753716497261629315,2711401246560501813405727886361637939228317090729002412066290100904319360960,1913027325164607464956755298437679573731669261937548387089448543475389709293,19048913840687946111515885036078245399510860136071611921573959765837451269059,21295287720552550910280526966903203926240851680963634134437049744624969307301,3797109693086078196558789257647252246485873371501397666934942661912968057995,17220092189283987679009565165189257352830222471797888201205665583060198133070,15728859045813610297052814756440978974533041326711446421367132340721185641530,7915246674314292718027357038683169057328569313936589479968179748005116348962,3168535062320575750000050980968432832479836571078965478747377498891053785750,13803986818738311305292789973880566948405947108749390476554600214529398575121,2887021549045614886550633658248390500136948561362661868354602793719521054017,9835777853770722919097370759265493857673816349027354889969484370501195735082,9162920843634529872148328448437467777954760966007230180656824492469148201817,1074954035830520777949184022573483523978030205622574039670230048399504082838,14573949395382273725648387764764104587706358354270169802238874779976052312087,392719645589691148855449884443988672799862378880367658864925364810308158541,3685551641667332817505970777889874263257498648047179005679069858878239338060,21636266924388678043670779518381645484139129597308274177295703055588816929542,7321567536895702720774368439707249290671186165402244403568878177007380798611,7172839196695686167303608986523055739039297465612557351529643226329584487820,4229778574282653726990227569322645489471840372440828936529243607112035640074,18782302953492985194605877986375464862209789031757664619583780308051670003641,11974809482173143458078984920442199204778548823433238304966088658895546634996,16243115558222486864600123441049281534776025041710213515085053285162975382052,20774412501254836125508172987964523733402936236671082985700605339729723682856,1483065919525318072073144044234229344901017930590205131905224416619628808251,13859608645215082985012618178187462696738961393768893322969190913266642570277,21405376459105682082984005097612235541120033931778677874212817450507078023807,11689238963312530686999514700594656275688886785400717773550428094425955677451,13770805346049970815658755939543097628223982878203541747699103196190562329538,13464128750778834946158208517080192694313764854534278881787962107045396572111,21407849640224904790247752730042846775377573219483807581870525715728151019912,17742435015936027530371893290930447550842976399042348699434701387859868436168,21607472280994630036571403820711131618277491312399185275464826427174795496015,7688464458545967396781600592854525549649369419708847302997939388491317131965,4387376978957625118504779199367262576455322502411234315349687321331690532595,18931911591990162605728772083755015441650830148575725789586998382906047952930,14640568984073443762298448827081280142493018130989596534711086636304928257387,13306842042380077440486698326492089142513016713060879132515526658677539077869,16831808713587057769987931635351931409992316524094756901264732606403438287007,11322415449116068033081427912158622347193126836157199640557951056169543153666,6851604032522439802523441319645962614365864202922586227207366934548805743971,7865033453112245503939716349145002950003125074081779764874079104952011815860,7859039670086457402270651853161690366745490673814388503748678622683637617076,12915205729177842184089675224634811499690953326168778547490092950902372657871,20937773388247481346344394224147944853257697507105144044681818248765914256516,13287060897761790924722969858390853273555324655965292728828260759103061260482,13306896346810583848301553492224587956204219709116827141735317644044595737290,18219814232296473414944129594782177430971511097498319923644038792152844524438,5428298390273304248312869576101694361963883992477060046151268450358678474516,15201216935560530575994837331432805679558316705524948725894686934721622162910,9185979018761703837993382762881735970994413889163208925197647077666234876915,19181785293325954761013200262201782189994371972312628530578184844339518606203,16637687071791710254394571978230957592057586799407792249481371375691006025241,7540695380854477789623159801158526233798259867148336812702557598270412992232,21033749924623312349444484016552328468392604073844480133610758629121621931608,9900738449713019488539657454744856913719757496206137183076543026413680378482,20521005306019974539700555774138941983710853964949502636832851583991666071090,9148625417956423696904186924742393962087070575705980963607554918018064302410,21162567363216498523188025354796572574708404245885103426215436531517848841283,516078530341213545969683556809078278712251743628535410360059529914040404316,16846240853341179628895683480146570801780199580812523539736983428470139888117,3725063466997152760713869763783030250548722164672702170123853642540240150907,15613553480222544404649584760559934580548305353382956847869893563076098726977,20351109682633578989341194704546173168875553988784930480177729322649037322556,11996883326331293630396983616262966081550223706386102455796773922602029237495,7467763103586466278784854382537524995001493410600869109792768087664508057830,2017508073008218056990628353468704346479637577205333604607959225275229259220,1314798328573144515884513072855778523099366140621231925682355151505185465849,8723657373526005784062072282873485835867170661363188128978957400998918352651,17008566456391889354408264184115222893038736754092176958021304795161250142258,1277201481182954066723110290486484624236238076832533331201564897838632505678,2883326282329572573598657327001707359250291449257261775578634065330832194673,4435817386812736743435792142021329255563452933485604716406076651024269234049,12698961373404268899870565736817085990987024732021219796534551825706597317720], - [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] + [ + 0x148d9e4542066b125da6d69ff3fb676ebd27e6a38a1ff4281bd639c97af6ffd5, + 0xb60a28805324295fcaf51bb88d9692372cbf4eef1cba8b85cbc059346691a88, + 0x2d38f812ad1d7ac79c32fdd57a56edb861885f20fa4bc6d0d942c2f41e8e4a7d, + 0x25738acd1163580033367fd8f1ee199d7eb3c37891e06bc20e6b476a0357588b, + 0x247f6967fca42689ae8e20b5a7a198d63086549b78c1620a51f5d36824ccf43d, + 0x2e22813077a668b2b75249b8d515a3dcd93502006694245bb087ff0732708b93, + 0x1523ea89be61be47e1c36b0e024068c28c48da74bf7069ab2d77389c83d474f4, + 0x146695ce138230e087b53ef1bf81601f2591dd344a7cb509f138939369e0d1c3, + 0x12d05d9571fa4b4171886d9c2cd44c7d7fc5a4125195e7d28c3c47cb5cb5b7c5, + 0x242721147084d4613543788977111f3fde6c89326a556e35bccd2a2e73cac68b, + 0xfd921ba8395a5dde833e6dba4173385007b38d1af5e3841a345c9a480c9d292, + 0xf0bbdc7a39e5146929f2e1ca9fb4a63550cea8f12109c1d82e601975d581f5d, + 0xd65008588b2ee1a4dee0313b6d4396952d901385f2e1afe6a0a0def765dc2, + 0xaea567be31e1c42ce33f589d903363a482f21c1c3d8fe50fa6df018a2dc7c25, + 0x2fa334757b03dec6be1df758ebe0353317b35316ecfc72934d069f182346bbd, + 0x2180dd9f972b1eb5e8819a843d24f650e8257e7a8ccf6eef3fa3d744b16f073a, + 0x1787a3fd66cb49328100d3574d7070199a6bb88b84df6e9b44afce9798233c4f, + 0xfbf506b6714d64dc8623fc0cf426f918053ae81e5847d3367ae7df02293da8, + 0x14f57bdb3ddc75b65eb0720e27daa09412b30ecf7b115e8162b9e55faf49f5bd, + 0xdab0bef8d2d1adc80dcca581e1891ed800bbf4153eed15ce71ee5e0b0bf940a, + 0x25f6be3a9c5f2a6ff32087b2caa01b3a1b7909811f025196f156319239d359ac, + 0x25b541b96923b17550e137a4a5bc0d544d00c5da7715c6f00bdffb9bc56d0dc7, + 0x2b4ad0860f8c3c432f2a037b0e2f7da7a4a5b3601044ba24a56b5b9a3dbda40e, + 0x7d5817bd123f90a4a3c2d77528fd9366321d8dc69988458cc425581c9643af3, + 0x13fda3b1d02a53b106c4ba4652cd90f466b97acfd136c9a8431f1dce531aa443, + 0x2450fd6b1a17be1ec4638786bd3fca4cca4cd871268eb07b1e5aeeade36fcb44, + 0x1c0753ebf63794a29dfd83eb0d0e76f6d1ead583f72f64c0be39aef9e577a0a1, + 0xf110dc007ad810c0fae508899bed20aa5cc8dc3d8324f0f7bbc3995119daf8c, + 0x30623c2f24a7c6ab307f0e88488a009922fc2b8235fc741526a4d3e6a59228af, + 0x1d895817e78f2f1f18e53130a6ed8bd6e1d189543380f691a969483f0ae3148c, + 0x3abf174d2075102797f61660105cf418ded1fab324bae35d136b17a0254c01d, + 0x237478172f073d15dba9d12cae6433ee71521ac294b54d78eace7dc941b2f82e, + 0x180f820a7408dee73a72ac02f7dcc75f99a2b9f75a9aab82377d373eddca712d, + 0x2a5ebba744ea7a6e8210f483f0b6b61c1feecaa867c8c11aea0488b822772614, + 0x2282d8326c3c12e0f7575e1acc4bd941893732e1e7d3c0bcddd35e366edd5f7e, + 0xeb67d8e687cb2cba01552ecfd4fd7ffc3d5788cb47aa3887a1f2ec3beeb08f3, + 0x176f406cc04bbcc4bbb82c56e4ec20bceea588f1bef8fd757e1e58d47545b77f, + 0x1c4d0cec6c8b22be0f1a3e9e32705a8a221d887ea0bee1bea1a8226608905658, + 0x1e35dec79f5a579a42f82c45b1a191147bcc4e3fd02f45af412eddae08db4ad9, + 0x75c4a33b1289f7923abb46d7a684eeda712004f974ef5715f4e2b504397e9bf, + 0x2f416c15f901818152911089ce2a96018e79a8fb7f311c4c6a4d9ee9f7d8a83e, + 0x7a92367d210292658449ef3d46ec96b982c3448053bffc8d27b17a643f43979, + 0x168799e51ef2e7c7b435a220052e06295f6c08b1e6b0b5122aba31e2d953e44f, + 0x2c422cb4040ce223ae9c21dd7331896b68704c26a8f4ddc877bd0659e75c8c48, + 0x29966fed42c09b35591edb4cac0574441dfcfd4f52bf0cc31b2e624b7eac280a, + 0x26ddc145a94457eaf0283876d4ea7d6bf10b7827bf3a684afb10fac1d172894e, + 0x13a8a30590a2c5d476f60d9e9ea7a4c1783a5fea077af03299b8c389641bf4c2, + 0x21d12e7122c437251656760882eef8f3168c237646f3a58a51c265d8b45184f6, + 0x271a6257306b4337cceea57039d404e1996058c68e71d63ce1329810af2da4ee, + 0x1980478607e68ab7961860e38dc78da21f2e453f89acdf82ea62ad9295d8f625, + 0x260653cfe0ebc0562b54b9599ba00669da343a3cb3a14c64f86149d8510df8aa, + 0x2c4fd7be2751f8b6129d997351088081e60585ff012498424b526483f8372f98, + 0x640c9db6f458697dfe17610b0692908cc7f72c1c0bf5cff33168c4867c22a0e, + 0x925e62b7772164055008f8765b827f251b006f2dd2370535df1a16e872b923c, + 0xaf4d8cd74eaebbf7a29bceedd1dcf0ab0d00f8de6442bb8626e7f04b043f40e, + 0xcf6a34e2cd376d6b000d8b0a5ed004e7cfcad8987f3650095f4d9740afda335, + 0x1e75dc69b7b94f915b925a773280b9b3a2341ab9069eb87c883ac87da102d9e7, + 0x26bd58259c27facfca63e248ab6a130ea9893b53928f3d373a0a197c5c2737e6, + 0x1511b6c19aef08f6e79cbc7282cf4b5d3eb07aad10b9f5d65e005e5433db1130, + 0x26d816f8378615ea31b08673baef673c5151c036a5a34ff11cc0ceaffe4ad982, + 0x1c38d60817c3a646a15d82ede53a8ef821ffbeb2b16c8feabd6fa7ed02e65c2a, + 0x2ab192357923d1198143414d448648ba1f60a917f4806bbc2a4ad3b2617ecbc7, + 0x2920a902ac2c11523c9425ea2fcf9cf430b6e27c0ae9f587dc9bbbeb96536352, + 0xd4e9bfdc6f8dc1a6ee5aba8e5f9f67ef3b83a526012953a99c83edb0ae1994b, + 0x295bf676ef95ef309c1d3f8dedef57582ec317807a72ec10674adcd1b79a1717, + 0x232180e854fede1a3359dc8f1a5e14c3ae7b5186fbb1a3f6a6fd9f5252351812, + 0x2405a43f35d247ffb75de7586ba2287f9b057bb321bd9ce9bed8c89807d67979, + 0x18931b27ff3a9e92903717b2eedae0dfdf33e9cb5f0fb10a35bfa8f3badbcdc2, + 0x1fd6e10af1b3189d42548c7ccb93749c4146adf3997b8d377c095445d90af092, + 0xc4772ff9abefc798f553554cc392284b2a8ac4b043708c183f18bdf6d69be41, + 0x227fd4734e7471641aacf664825d3b15ee10d0283c2dc35364c9b167ccecaad7, + 0x132faeaa250b60ef57f7e0ae17f1799fc9530ba5e6f2baadaf01b089595df9df, + 0x1fe24af9ab6246e0c85104cc31ba59175c60b155647623f893718608efa2047e, + 0x2f376b18215290f25c3fb987cc89569a3f18ac443fff16989678e205871becb2, + 0x2f2fc0ee912aa02875b096e48336411eeeca6f3de85152f51038ca291bc0cb18, + 0x2cad38124d882410c386b4eb1445ffe1c73f7b789a273a9cd266bc232e4c68b0, + 0x52002de9c04553df4716c46a80102ed453be8d5bfd9b2f0ec7c1d3002a7e7b2, + 0x302d680ad3444e026b06cd6e4bf62cf7df234ff9e5a46c48c17c2937507cfccb, + 0x2b3a9dccd38768197abc3b4cb640ab3c01206f49add14d1d705c371c7f705afe, + 0x96a6e47d4345707b5c25e86c8a690268f5e831e6df4d864e1f3fa90f2d8537c, + 0x2e2b005a0a54d0fefacdc8c153e84f5cbb50ebca105fa0f0242343fc4893783c, + 0x11c8ac2a7f796c7852e23e76cdb576cdf35bdaba6918f90cbfe7aa2265554a95, + 0x2c2e66451aadb830f1c91d8554f2e39e4ee19b15709052851f481629bbf12b91, + 0xdb078c9e2f68eb7d8f869554da434b9576f186dd943b1f586b9be61a172f960, + 0x79328f87f73198430e17dcd7613bf651afdc86b514295f7c238d2f267618abd, + 0x57924e8f3e798044d6591af796b74ce96bfeb676de3313eb50e0810136b8b09, + 0x1730b8bb9dd03d8326981225e8e51fb9237e4c03fbdde5f0ee12004339b6b9a5, + 0xd121b54def21112d91a5bc9fed5249f5dfbde7c63bf2aa63d14cb59b0dccefb, + 0x13924c1b5bbe6d5c01944d682370c13cfdfd90f17b55f07b05860713ba9457bf, + 0x1cfaf7ae08968c76279003598eb1f7eb6b76ca3efbaa873f21e3e0ebaa637ce2, + 0x20908d07c87e65c8c66ae29d2ef20f8b8049e304a818e769a3c3c63ee4eee0d2, + 0xd225f408959d91768201fdc03575a68e7a855939852c02cf64e3348fb383d42, + 0x112785d72b09b749a03120b3ed7cf793a99ce5710afd2f07d1eeb39974f03340, + 0x2dc01fd745f8ec43d61a5b355b459750010ec7e6b4a13acdcca627d7f6f6babf, + 0x16f35ad4dc8075f6c173b9588be33839ad67fa5883783b0ae6f0601de726afa4, + 0x1bbc143e6c93e6741dae37037285fa42ef8dae0d6fe3728b9e92e79ea566b277, + 0xdf7e17da597a37884ec03429b49764d9e8cda46fd656a122f8c61d9123d4aba, + 0xd73b0c0a745dd49bcddd632d4e41f57b39c28db722520c24cb3d9ced0d8ab33, + 0x263f950c95141a28873f4ecc0d18c82b89f60e7042cb3e9f128cfc5f03e38580, + 0x195e19715160d996ce7464f95db19bec2c71c02faba0f2c6c5ce0ad748fd3d3c, + 0x1cee7204151b6a47ab8ceffea244d1928621fe2661b5c095d1cc24c1a6579693, + 0x29d7696ce5bb66f2bea6d55ccec4dbd464298d8018135f734d115430cc82c42d, + 0x26c47c18b71c8e81dd025369e12e24ccdfcec6cab974c0f86da98deedeacedc9, + 0xfac9631760c0b7f0824bf81492797db8cb3f5e4918040c4af17a4c042b116e0, + 0x7e7ea789ab2f31184f5a93820b08a4f6bddf02fe83f7c42a6af69a6328de863, + 0x20eb37fc65efcf8d87ab26c7cbd24ce2b597e7d9a73fb6f2b9db3e0775534bc0, + 0x20f4028b63bdfeba4e2dad61f4232d2a584560aeb71bdc2f6c3929a7600d64aa, + 0x60e204b7c08f1784b366a37a86d0d8d90c386989cd167fcfabc8c2741aef9cd, + 0x408cadd2b0c8fc39ccbe8366e16edee16ef6fcb00bca0b843681ed56a6784f, + 0x1722aea32703f506f24c5551e3b591dd24fc4ab9d188c149fd1b75e7b90dd353, + 0x2b056ea316811928d984e2796d56842e444501dbaa8cdcb546af5de36364f4e3, + 0x276f12a02aa48133e660f6e93ceecfa60a529dbb444a4553824b981e3396d169, + 0x1199c8941c5f8f8ed0cb67c02c5e014364ad7f708222ef17e82378e4c155a8cb, + 0x28a3d2a547967bbd877ebb18ed238e91706b259a1723c1e345de5b545b8a943f, + 0x244dde50ec65e0e66cc3bc269ca9689e25a89c5269a4b7fd5137e9ab6b7b1be3, + 0x18dd271a54f6e5ac3aa02025470b4612c9044be00c51b80e347938a528fa9d70, + 0x218e424622d7d41f3362cf743106e890d8d2108695e25d279a2e88beba3db8a2, + 0x1f05c5f5041b178a54143a02e8850a9e94625955af047d9e658e7cde580fcd4c, + 0x191da8c6357930716bc0fc614b80b71ea6b2540d14bcbfcf251086764f3f6e7f, + 0xd54bfbbf8a8cf7c99b0aa8e6a688b964e50e68f2de8ce26038e155ac0632fdc, + 0x22e1e8bb2d7d1216a9814ff5454f064d67a9c56e4bebf7700cfa1b651decf8ef, + 0x1f0fa78dc7e2300fa36abd2a40c858fc10ae1455bc43695d121c187a26dfe7c3, + 0x151c8de5c4d6b41254130c6977f790f13b73f6fe786f47d32d6a0e098dc8ca10, + 0x191451e550240b9f0f15a5f0ebbb360ea9b98c6730e1097fdf6b7b8028266433, + 0x88c58a21c4ac05f1169de675c2c543cdd22bc1dd06c42fcc4eb890bf0e518c6, + 0x1e431a01a34cf72247817b3c5684f042878c6d8f67ebeddd047773744bccdcf3, + 0x8a6ad0a360a0f2558f78abb268a4c7dce19ccecf989a34ad2abbcea4f50986e, + 0x2fa7d3a514d879b93b93049fe276e60716c547d4f290126c15e8b666224acfa3, + 0x2f352d9675da8d7c81494e015133a5b8b4c62020898be4468de2fd81a4c2cef8, + 0xf6ebe0388d424da0c79ac329f4b571cc3fd8d5bae54d596e6382da769c4fa6b, + 0x1fe4cb5bb70a9da24e0f598396e434beba5ed2e9ad539951dc93a38c37fe3fb6, + 0x29f316d8c7f3c8e7929d30849ba99edf66e61a2d414e6960081d0114f45c07bf, + 0x4febefaae3e20b5358213eef06d52c7b7817a4e5bd8db4902d2ffde8868564e, + 0x4d6b864cd130aef3a066bace271902047aa0564eb05701efaf55d1f218eecb2, + 0x159747ffd019c389e54acb68074802edf33332662d5dbbba9b67a3c21dbed46c, + 0x2116bfbf5067716afcba7419b07b3315f0ee9c8ddb034a6e6b5fd2e78793ef3b, + 0x2ba76cc7a25af15695fadb8fd7d436d91635eb3f251b2b46dc317c8f5060c4c4, + 0x238465fd273e538d938139210520a07f2ce3bdf50e381959486dbfd4dd0b35c, + 0x5c340a5328ed50d2b10d24af11e763ccf9d30906e5bfdc2a0f23fa8f23edecf, + 0x279ab61cfe4f25485cea4bb3491598d816d5734e391bd1a3edcbbfee0da1c6ba, + 0x76e2fbd39d4fab2ad6de8d53e70194771528f4ca4018fc56c68b85f041568d3, + 0x75cf8404428a1a38f04accf51f5ea6a7f7d7cf66ee412149c23bf4c4e61fad2, + 0x1b45baff5397fea5757900b2499c0aa66447e5e6372253457b9d2472dfc8622b, + 0x1a39fbeff40b73bbfff7232c26d92db4afe3286cff840d193b4256a66432b09c, + 0x1a4d4e0e68afaa99c0890c322d58e46ebfdfc24808688b64fd23ddef4e70c7f0, + 0x24d619da14e5505a0466ebd24a766f2af1fcc6fe2dc4bb58440f618d8c57a7ab, + 0x274442dd02cb4d494bb38c28a42fc02494ab3eae56e115cb3c65ae4aa728716b, + 0x26a9f2469481a594f9b546553c12df66c0fdd4b4637370cbe695cab374f5f115, + 0x19b6db087b1cc1c4b765e70274236d981d5b022a6cf0d3aabd478eda2f895894, + 0x231b94b5e1f8eda3405c1a9a05024fbb79f8722847c8c4dba6af33b0b5e8d072, + 0x276a571b8b2cf637ae48734c01c30a91890729cb137862d09b0dee2f255c5681, + 0x63d0dc1ce85c55433a780bc6ac9fa8bf4511ce6c37a121b6712cd8905787751, + 0x1b5766499bbbe4410e990a078a5ee8d6ad5c4ba9d0468a056c10e0df4f3af63c, + 0x121b65097837a750d24e9dca2ca61b8ef80e1ef478c3d4f1cbff64d4256da110, + 0x155bdd180e1446723320311ebf6ce1668158921dec0c5d9496888eef28fa8396, + 0x2c8541d4945a6610c164b4a4546b2f3b9bbf6dc9316b5658927b635d8bab8589, + 0x34a08d31b52da90215ae00874307d421ea20c786605ae7fc87d0be172b8c3c4, + 0x12552fe7124ee6d20886a7268d73a94850f06a600448641df55b08e7933077c7, + 0x2d19c9d4694d594c5382702070e7057a9f0c7f7bb2ab83ff684810de0e2106cd, + 0x20a7d7794bdbe939ba166d34ae843e1d84eb4632122b7fca26f4e341b0e28b29, + 0x225c213c0a3c9addf32f0c5bdb33fd6957691135d84757b4c44eeba59469e561, + 0x2eb542a5c77f34c674c1df077e89408f5481f4133e3ba62a4b449cf64f9b2537, + 0x303a003af9c1e54d9d3189920396d0c752c9affe1c17e3fdbaf67b3811fec7ec, + 0x2c42a27e94cb62ffb6c169979d09f39387a9e9f9b6e9df71c9ff4165a8ed5673, + 0xae6ba5ef2e7dd64e3f24af20271927e95859827e9a9d32aa247de70c5af9835, + 0x4c58d44d2b14455273dda0c92739446ed59599cee1a505d0cb3631118845410, + 0x2a5c4931de9f553fe4e020755d8b5c10c12ebc234ddd501d6f45b1b2058373f0, + 0x2fd94eb892152b5ac3b73e6061f3a4f952198f3c330e150d4f44c933e6c8fb38, + 0x1b5395c281e1bd5763201cd1c72a3b5db71a99ffcfcf7db793704c0bb4d53c94, + 0x26d18b9ffcf39ae62f03177f4639f37f569b80500e0bb4553466d67b46342b82, + 0x2c4eb768a6db2db295d215ba0f81dcdcd77e0e34bc123791c03ee7d391812b38, + 0xc2e3f65db73f4058ec7c6cc3c3ee5c49550dc106c35929f0bd2d04590309313, + 0x28f15a4dfe1c74ae128ab27ca3208dffd9313d4e87a759136eee3e194cc925de, + 0x11ecc3e8d929c5be84af974cce44aa80bc74a16f13e9b9627f705e3929fd2119, + 0x239d451ea3e39517351019674cbc2a84c6a7add8fa6080371768859e9a89f275, + 0x2a2a9313720b4adb8e4f5795c3224053b31bf2d6016d9096e56cb87f01f81124, + 0xc0089ad49e3644745a0e3596312b34ba6c0faaf19e362bcb56f4a7974c6db74, + 0x2ee82c31a946f5d71be03b9a041596afe624c9c6a6c4907a8be5dd274c3d1524, + 0x1ae0e9d39c6100a8ded3e7ecc34988b75c5338dc936c91c6f1d95c405c07bbbe, + 0x1f11f75c7d0ac841001b3123c045526e98c203d1a6caa18d635f2f2bfa735738 + ], + [ + [ + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0x113ad8b46c3eec20c9965b5a7b2e8a51529871d0401b4de6f63de9e5211623e2, + 0x1fc50a16dbdfa1c3b99038f47f81a1c5d1ef6e7b221d4ccca6e821220130e000, + 0x1214a9d6d7288fe85651a8cb83048c7669c83b5ed82ca2642fff01e852a44b4a, + 0xd421a7c25af5538788f49475836712af5da156f88c5867568cd958e305026cc, + 0x2de8ba83d2b6ab6a711fb9230adee1cba46de8c930c86d266acb8c1cb9684e24, + 0xea7be82f1cb493b1bbd83ab7ca285bf0a1559ea05c3f59827b3b013d0a91fb2, + 0x1e3ae7e5775d352651d713ebdfcebf9ca8e905cfb792bf7874239450f914c8c5, + 0x5943e3618a32cf050018a4e2375f4d027b8c14ac82a0de57cbb90c5122a64b4, + 0x603755180f66e98215d61e5346b116cc00cfd058274d7d969b3af95e78bb335, + 0x19817db66fdb8215ecf70476c4044c3f41d78ac5a549c684e35845947dca0b11, + 0x73965f7a9ba8cb33a955d42da55fd7c37a3f0226b029d36dcb3fbea95d642f3, + 0x9a550431430846b6694125b5642b00607f36a1a29485361a3cf427da77eccd0, + 0x68eb4e9d6e0a588b61a6ad501f380da0f009067666c0853d156e33d59c43515, + 0x225e00a0da5a7f7496b70d0923a7cf7ff332bff06958cc0f3fad439874f6024d + ], + [ + 0x19a92ac6087ab89982fe5650e5e799f91003fd8b45400748d2c25e40f04c578d, + 0x7930cd5256f8ab77ab92b08bbb5b195a44a2382c66e27514619efb94e649110, + 0x2d8d3d924f2897199e38eafbc7e101d17d7e563488a9f3198060796ae84c1b08, + 0x1c0de2bfeafce164c9838067a8df6340f9d97edf0122333159b714f45c3f13b1, + 0x20e4a28303dd55e5cee332f30eebafbd7932e7b3531d942454c344b8b8c17cde, + 0x1bb15ee4d492a8e2cf1b10db1b738c6780066ea8347abe536357a723f6cf57be, + 0x2ccf31a572412bb7d9cfa637707853217e7db5550b1cc30a894cdf483a3b63e3, + 0x1d492c34b245bc12941bb163c5118bfcf85bc4f344042b2031ed8662a1f6ffa, + 0x1c9b5c2c07fccfd9dc6b3abfe05675fc997eb7b8cbd8d8b4cb7e671615b0ecce, + 0x243930ba01dfd3945f2aa02d588922b47c1bef2ff8023a849b4ca66a1bfe98b, + 0x8f328e5e66c0b879b36c233f598bd8578d18e2da9f019f0411731524f42d90b, + 0x284a2f083ee32a6663081c800713e0f2395e348dcecc89fc81aa75a5db2ba12b, + 0x19772e83816fc2c49b96427c6ad0573347fa49a5df691252592aebc390055a35, + 0x2dc5900039d4c8523ac379945cb9b58a54e01dbacd67f0c4baee85d353d3fe97, + 0xcc378b44e58f668b45832fdab4a49372731ef2415c37f40b5ded5594aef3cca + ], + [ + 0x302608d750f16491df5a285f5f7f6a5ce6b554f5dacf0b69d450b24bbb4967d7, + 0x28f8144bdae1b904ead70b3b72c7943037de6b48490efd3177783594edd28b9f, + 0x2aa9aae62cdb852490c650ff9e27c9b33d4cd4020ca66f5e1a6b374e662935bc, + 0x1e394d80067f0e10baa95de0d99b4e39204a18727d1401b476ec976b5f173a82, + 0x20bd028c958d57b79e35218fe34e469ebdaa8e8e714e918d58191f65046b972a, + 0x27fa2120431379cbd86205ff114f34dd2dbce13e1c2a0a8e46a1dc27e7b686fd, + 0x564651bc1179170e3c97afbc4f493617017b43b213eeed86b9b1bffe521fe86, + 0x7333cbd0ff13c8ade1febe72892d9ad435c7b451aa72a8c05a7082395882865, + 0x290a7ae732f4754e0cb91923c9248971932607be2e829163f11612ff8a955b10, + 0x1eb520feac62e4545f4fe7cdb675e36474b8b1fd19e15d7c73a2b1dfbb23fed7, + 0x259a2a1f046844724cf992aedc2635f6680f55e8a0fdac695ecd05fbc2cbbd19, + 0x8f78e6dc59cd4694c41abbca086569a9083ca8cc800bd9134e4d48ed9d89dc3, + 0x2d8ec6adad3a646843c88cda01285f8f32d29c6b1025cb5421422bf8bdba7fce, + 0x1b72ac4374e95b7b7d28cd2909507f3006e8352d4af19e47b0b909682a03200e, + 0xd7d8273de237ba2d4d5e8051c5bd5e312d298b6726ffbd3af7e732af91dff27 + ], + [ + 0x1a3c7daa6b4af5662d0d8407b287674d83eae5b7563405f48def49981c98c424, + 0x2474f543d1f2f33b5ef3fbb190651135a59390c8a3661fae2df1d3f14432b608, + 0x1848a60efc89965073b95773f467666687e38d59be208e8377d31903921057e4, + 0x2ca2d8b0a793d90ed318cdb5f697193137155bcfb942d82bef558be5fab359bd, + 0x6ed98a185bb2358f334eb257ae5e3183599c054c1b4e2022569b8368da1abc8, + 0x1ab527614a37c2ffb00c0fad360abaa447ac1063fb9fc656d0148cdce2d7c372, + 0xbc769cd7b34fcd1b454abff0c00b89b540a619b87c95444679c3ac6be84d450, + 0x29ad5236ffbb598a2f8d238703608db7a497a7453ef9d579fbf05be38f8f76f1, + 0x1434ece209d491280c5ae05d7e26cf92d99bb7289a5c1cac09a38ce53b6e03df, + 0x255dfbdf30553413a1f8f5113d60e98583838d13e11c1ee02b25a387ea00cccf, + 0x67d9294b4072b12c368c2816a53bb16b7e7e2a79979a416f2d02af862abedfb, + 0x293ca8a06c5f179d938065ea47f80f65ff21969a9429e400aa177ecf6b6ae853, + 0x255b96258dc8e1644f1bcaecee773632f25a6ea803cd32a1e01f82573775f6fc, + 0x1f2a8dcafe79fd0ea22bb1563c3b28b23c5c4d7591d45e06744b3b379d426618, + 0x22ebe0a315e07be4b0928885f52449b011b3967e519e438c424cc0428c35726f + ], + [ + 0x2db1c9855ac29acc679367dbf70f08d98894077df2411f91ef68dd90177c1e9b, + 0x21715a84742c02d057ac41f743b166da023228425681950edfaff8581201a097, + 0xc893808103549d2030cbfe0004ea6655e24ee71a1f8c1f072d5cf6e17ae2499, + 0x28427ab007a68c7ab12371f13bd7dba0acf7e97ea6e64ae52d5219210fe8a2b0, + 0x51deb4b234890e31f5ac8e69a1e532453774ae93a9e9360fe009ed377ae9c36, + 0x170cee2983fa3d3ecef2f806f40eed8d8e135ceff076fc530bbfee876c9e7f1e, + 0x244b6b63f8041a5975f4640b18c7d067e4a0627f18751dc906016b8893c35123, + 0x2e72b1b114dfee7e8d7f0161255c6895fa786070ce62d806c45a22d7d98a0a30, + 0x228e7399b0e05802852bdd5d5e09966f03c4c3aff53c683eb2f69e0fcc21c0bb, + 0x18451132581b9adf996c6cae15b92d2e4c09fdc7d6c27b4426f32b5e66a0b723, + 0xe1d7ec2a54b11b36e65d7551e9a875a88ccc7a6c0470e7c26e199670a0859b2, + 0x29b68e652deac818824da0c2a11b408d7a839a2e8576c55bfa5f1335ffc5b93, + 0x186e1360041193e12f38099b0e35e767affc3410f6a8dfce9bc75567e39bc402, + 0x19294dd22da673470377d671fabdf42cecd37ecbc018386a438706d6106b04a8, + 0x2ed3cf0214f444d436655e03af8aee2b4d96961eea06e8133bd6e8d3e38234f + ], + [ + 0xf06ee47558f182d810bbcb214a25da7f70a567a0464b348e1b30eca7de99d27, + 0x1ef0e0c1f0b5f67644c486fecf02238cb7f4fa63a082a3c030daddce65a4b82a, + 0xad80718c6e9d1c67b4a37b9e103db32f225fe42a9ba655ff065618b87b82aea, + 0x2cffc378d2cec76ba7080b37fc671a96328bcdfc4630fcc2f2133dcf29c70dd1, + 0x21f1f6a630471e32a8b9ac4b7ed4b04c56b96a71ee20a66a5458c6b8d5c6d346, + 0x288851770f1a13822251da91c84e123593fae1c9cbce6c4ff2317e70bb658209, + 0x2ff4ee110ee1be62e2715dcd119c95b95413376e88ec3ddc3f06fc9db8c27a94, + 0x2ad369a84b57f7455ba31064001ca7779d2b4b96b0b4a91f156abec366aab786, + 0x24f0fa154fcc6d6459d6c56f711f25e38d57e90be7b8046c9e001815edb41404, + 0x7221cad39d9b5f8db705a8723038b92b6baf87284131735eafbecd533dda6d1, + 0x173b3b349ee888d934aee9c14e889cd7d785d1e3e4f1eb72a5c2e56c48fd54c9, + 0x9bc3e40bfe5f616fbd520f3894a0fdd37feb29429fd3a5015953171de3a70f9, + 0x29cb31e1afef4f252578aabd76f23a1320aac90d4a0a66c2225e3d94cc48d22f, + 0x1932bc6bb488b736e0d4bf306d41e622e66c1d685aa4598153054b40f75c0b00, + 0xcb6fa0a5e11b9192a51904939d45a05af8055bdea3f379faac29d1309830e85 + ], + [ + 0x2166d78d948dafa963381cf1560d00bf3a0a1c288a743344c8643a58daf8cbb3, + 0x278e8dac8c56b28a23dba4d90fba91eb947f5092d4a7a9ec7802f61778488e87, + 0x20d87476f1243f490246f88736ee5fd6d33191f0561271487e9693fcfd7a649, + 0xcfcaa1d7d382e1fe1fcb950e14df202a08793d7185255b025d562eb8d97544, + 0xc39dbdf6e6d24a91a0a45f922c894be252baa127d9ac76909f86dc0bcc68a66, + 0x1795384e91bafa554dedf5156cd799e11210ffd2afe817b5c63ad5b85e7fdd06, + 0x2666ec1a67daa7beb057aa0e6e8a10396601a21884372369c012b49aaf849049, + 0x15793f31caea39de315dc5bf5a3662ad5d8e1a12fa1a7280f2efaadafa97adf4, + 0x18800bda17a89832fea54f26741d86c6b6fb9e15b02e7bd065533cb5661d2a95, + 0x156f6a09e6a81d8eecf4dbf21646bb968b2406786cd1dedd4cc732b7532f7fe0, + 0x2977658a10de6e7921ab9e34bcf07bbca61a72549ae57d0c15691bd143d4d2de, + 0x284181093e43419789263736e544817111fdcb559a43773f05186608acc542e4, + 0x200fa20ed1b871313900c01f8b697760d030d8cc0150fdc58e04a0d8a2b344b1, + 0x8d1d68b8437bc980aa7c59d83393b162a0827de74070d2d34b4eaedc17e7e60, + 0x39598a1443c009678602b8dd3474f276da5d62425083ec628a1737e8cca3e7c + ], + [ + 0x2929be9bfe3f93cd34fceae665d96b1de1afb26bcaeea2f4edc454c50cbc4401, + 0xfaf33843e6733437e98995e6f7bfa6feefa73d7410d8585918c347f3cfe92a5, + 0x134b86642ff202388f4fe37356ca4f0ec3805566b7d4d412d8937a359ef9b401, + 0x1d8724c5e641d96f6e372771b0a776bb742fd3c08e1ae250432246cd3bd01bde, + 0x305614aacdfd4167cd1bfdd8fcdece6892d84d4a65e86e6f7c6349fb75e48b96, + 0x2cda26473cfdcd185ba28cfdaa15e7de2359646a0287ebe8b60d702df009010c, + 0x2b0666971fd911529e70ef918d019f44b5c9d77442b6d1866f6e76832d478847, + 0x56c55df543a8d4043a12f409cd2c4bcf43a770f3e38c3fc79ad214b42da834c, + 0x16b11f24502aa4cc3b0c2562a18a24ab8f986431b244034d3fc29555402b5f4a, + 0x18ea0ede9010c7bf0fac361b5b8e7f97c75ed93a13a7ad4a017d920c03c98686, + 0x396097733de5a1fa4a548749b73ff7c426f98d9e5ad16920614d337897f6b1f, + 0xb9d5a3a957eef251ae9c26e53423f9be6f2efc24bb18756893a9d80e56a0825, + 0x1a63a589d1710aa705136cb520c2f1c44d778e490c212d4b72e9f1538e5555cf, + 0x1c0343816b8cecba48519b59b0fb6d4a9bad309ee38311dc3e8cfe8bad75dfbf, + 0x1af56e6575123f99c5d7ab7b83770f0fd60fb9f4038c2942644069e3c243793d + ], + [ + 0x1076d439c67997c37c6c1fda9a37dc2f762dd577946f36fcfdccd7898ec67cd4, + 0x2ba437d6ae6c588c6b71506c8b508347e634b65cee317af1fbb9cc2a997fc006, + 0x2c04878b4cb8156e9983d11574ed99dc7562d3fbb1878257abbc68852fdd2680, + 0xfee8f9731397974100834649ee87a27ac92be7a3810303460141aafb542a429, + 0xef9ae65eb922605d4260ab2021dfbb4774cd5ffaedc1b79dc681208be6f85c5, + 0x27ab4b40901465ef59007114ecf1fbfab6157c24f402246b86a60397267308f3, + 0x2bb5bf03cef933e4ee87f511de3985cff0323ab7b718d4cbca3f429addbf3052, + 0x1ee10e28c612d9d6ee72f1274850c3e829be5c06f5bb293280152a5610eb01e3, + 0x20a9d575fea891302b106439ab03a8a951d8b2ef2b562991946eb2541f1fbad, + 0xb73119c98d25eb6de14246b1401bef485c9dc6accedc23494b9526a39d53221, + 0x2a66defcf489c23eec5079a0ece1c5341027a59e7c592e760184b826d70dba9c, + 0x4aa8e91dc30f9ca318fe24718fe595871f7897e92d57f2d87d4b1bcf9a635e1, + 0x133369b3bcc73ee793e869360cd50d8df60fe398ed9d9c0d0d03e669f796e87f, + 0x709eab96cc6255f2ae917914f25085025490c423284916e23b608638ccce29c, + 0xe8d9c0707dc5bf80a2f08c343c69cc659def86630af3141a003acb3d3e90c08 + ], + [ + 0x185c9ad0da87cf824624d02bec3ba4665822a0f6b3b25deff3afcc687ce1321d, + 0x24a6c1919f94aba9db98a5af38feaa5391cda79f9debfaf118670d7927e41db0, + 0x1783a45215805ade9d359232120b183db54b43f9a7e8fb8dcd95ba9bbabbba59, + 0x116f239abe820737b5e1e82b2ace3a45cefac489a6bff084e323036f54277108, + 0x1adccb898e5fe18b5c29a4708c4b112b56d0fa5d299b5edc07d6f5bc00428b8b, + 0x27122781df7bb05f6ae9e14e8e99da5c23dc77cc06108c0ebb061e5d1be93626, + 0x2e37a7440e75b649a0799cffeb7f9dae38fadfc7cab6c5585e4a84f437729d02, + 0x29f356dcec3b79523c0589a7046ef0758486828b212146c3f5ce987af3fd719e, + 0xf9c05f609ad14debeaff107b95accd60e62662259905105abfafa9e8e08eaea, + 0x1c66828552cac1443334ed70b7fd7fb525f907ab64479d117864c92e911986c6, + 0x10f43368c0567f405aa6aafcf367e3e68beff957c4b0cba17c30c62b3f95490c, + 0x253a11c66463a6dcafd8399fca58ba27febbc307d8833c666e0d8df072c5f69f, + 0x1e99516c240d42bcaaad9c73f21a46193db8433349203035eea30398f9df7893, + 0xc67a06b33cf73882b1c7152d4585b78223d85c77cddc2c7d3594824c5016565, + 0x1f6dd8e85d3597bb6d37b47a1f063122014c888250b38cf8e82e3e5471ef84a9 + ], + [ + 0x2702b1be39e91044fb73926c1104719f4c037aa4151823ceab24f0cec49f4648, + 0x4d80e7ef7e27a2b1397678ac42abcc6e2662c880503e4643fdfbace67273b92, + 0xfc96302e8662de23cc5c8c228ac8ac2dcdbfc488a59f4dd41e3f27095f7e195, + 0x2a31cadb918d78b96dcd548b394425a42e2aa7a28a6b63e509261bfae6fa25b3, + 0x18a2661c03ab9b0d8f7d01091c7e563efc033196747e34139d3f5cc7ac001e9a, + 0x26812acd03db3412cad4bba1aef71bd44b0094d318ace0366c79e729ff0eb2e6, + 0x371f0d49346df2d88b9f1ada8ac99dd8125cfa6c30f3738fb9932a853268e, + 0x27cea9c43fe0bf1ce9e53c0c026e839d80a7d869136603102cddf63cdf28b975, + 0x95f1db43c827e6f0b9cd4fe929e7b8c78c93fd02ec9e0f10992feb753b4ca07, + 0x10a66268dd9a2f368e95507efc2085eeeee8ce977ca1eff5b2e3d94bc342ff58, + 0x25a2a43ee612663dbd61814f2deb06ed005a7414f99825f8be66f542f95a7b2f, + 0xe4fd498778c2c76a02d0d91d8f89825856e706f598337dfebbf3ca33397968f, + 0x13d84ca7f358aaffb1ee8ebae81c32e01adc01e90d09c9451af36e31af82170e, + 0x740c1e9b8ed16e9fae204369c554cfb72007dccfd2530f2e34d544003ae5994, + 0xcc8f90bab68e6de84845da1899bfc52440bdddb940b208301ae94a95777cb72 + ], + [ + 0xaf71a51cd463b9faeda93803cdc03186c7781845252fdf4e0155709d93dd375, + 0x17f6a3aedb0005a9b0a258e31b8e6e2a48f3f9551cef6812a49075aebb8785f5, + 0x24b22e5ce671ce79dff8de16d7cd2bd6375d7ecaa016ecf59cfeb246dac80720, + 0x240caf6d7ab2f7b6ab3d15efcf3074f5b2142a1e804f25012d988454809e096c, + 0xf8aeec74144d00a3ca38bff10bb0f3a8dbff4af6197847db879745aeb57b5ea, + 0x213d29d4e1b6c01fc0d109ea6169490076d131d8e034b3040f7bd9c3c373ea17, + 0xd0327b593042de04f58e0ff93386d1608d33a86872c1d3e7e089120aac7a4ff, + 0xbdc078b1edd9cb1fd2c2a01a97bdf7d458648439fac1f28509b41a2dc9e7740, + 0x26bc00d9cd25124442832d97abd90866d3fa7a401bf38bd95fa7ad526548fea2, + 0x1f14aab5a59ad452cf692b123c65873dd80ffc188798a4570eca792b3f2f257e, + 0x182f1c93c6eb29867b1559c58207a6aeaf40b66eaaf579ca6bd7ca40aaeb7abd, + 0x126ec8c200262c45d1133bf9da5f1e5fd62bcea1e493a080af1bd283ab86f122, + 0x5a78464a4b6bbca6e96d839827bfddbaa9d924840aef6555de643df167d4caa, + 0x2a84c424eb58f9c38b4380af38e0458468980988faa1f0d4c6e723845678523, + 0xc0dcf2b13552ec55c97166be347ca2f93b07e2a10164096d353fa280c796821 + ], + [ + 0x28667f9c7332073e293c80b98edffae01af4f67b4c52ab45e49db8b30f182d28, + 0x1e62029129492c8bdf8514945950681361591a9f5eedc2449e5f229c85bb97db, + 0x52c33fce08d4a39fd805156c8affb84349428ba4920cfd2e7902ddcf9b0557f, + 0x2224c85f0c0b4093014db1e817d1ff16918f15e0cd231b848a48cf83324c4144, + 0x1f53514a97e8b57204e57bd6b1b1d9555f3b50368154154e67c2134fd3151591, + 0x2132f71ac89892c984a0a73653f2d45222ada34181a9e6dbcea0d63961f934f3, + 0x4dbc4c8de708e59aa4b2116e53944bec97ed42309b4a184561d8f32d291f9c1, + 0x2565a17a6bc56e87b0b63664319b8a47bf662c1f49e2ec9251be4fdf33d90f4f, + 0x173e80596756cd9aee04bd6dd9dc15e4b8ebbfefe3771d9819bd4d444726f79d, + 0x1d34655b5776e24701621acb41324cacb50165e019bff1e65f98304f7d822a6, + 0x42eea616d905025147a482eb436a3b75535c9869b76d6cdace118e15c91fb77, + 0xcf030b10a1b4291e576ebabb39c583fea0fa6decfa98cff7a96dc06cb77da51, + 0x260ef13ac7e80fd2db3de9eb942edeef3f5e252d4c04508b1e1b130191ad0df6, + 0xbc367fd93ceacb599c614aa28068783a5d27eec1fc8fa1765015b76dd82f5cf, + 0x1f126117a949dff900fa5d111a0ce2661bd9d5444577c491a9951cfb58192d + ], + [ + 0x2763c33f5b2d7bc3a23040afbcdaf998bb13254c272a5f8635a12606a59c2e5c, + 0x16bae774867656e64fc95f3c249f801f150fd7ee28d195bad9eae43743875278, + 0xf0d475225c99702bba4fd01276102b5cabff7bd4d147c0e3cdee4c07ac31b1, + 0x39a288951a0381e3aaf598ef132853b5d694716c20db87923f0bcf14c914a8, + 0x27bcd639c47482d2dc8b6d13da19fb8d63f3d6c875f6fea486da6ff2ee11e107, + 0x121395023931f6bb3ef28b6063eb7a2ed7839e083fdb92c1e5593c83edff5f53, + 0x290ed9ae7479f9be13af13f98bf88507e6fdf018710e4859fd2e48cc66ff9b24, + 0x15b085b5eb678f8cedf21bfb30e2d64ae1cbdd7472449ed24e6034101c658868, + 0x12a643f4a327acd2454514dd469551e36ab0e3f24ecc3b28a76dc1f38214fe38, + 0x16a1eedbbea79c5411a639e3bf0e90f6e3f740f141599af8e6a43a2069572f95, + 0x5ce7f592dca2148e198554fd64db8c479f29d23f1f16daf3cb8930d9456e4c5, + 0x110298fe7f2bcfdac0bcdc3affeeb436d7b3a377453ae778fabd37a9acb299a7, + 0x14829f09d4beebbe6fc30545047243fb3dab99c62aab7364a7a5b427457a02c0, + 0x278b58503e0b9014104f8c446bed4c6de575c72d4dd9db3d1866846979aab9b, + 0x138f67fbd9cb91ef5206d48cabb269ac42bd352cf371e43311bccad89acc509e + ], + [ + 0xf81a8d8e08758e8a32aa8292666c4cb6ba3f5f06c4dcf4fc502ff97f03a85a6, + 0x10f0172799be23a8fc3f156adfb6c512ba415e35167b563bf7b186fd12a41e57, + 0x1183e91b7ab7372f157d4c477691eeaffc9e8863fb2d806570c67f4b1858fc54, + 0x17620d438499f6c0a66bb577add4cadd66ad39e3377d302bf83d3bba126b2aca, + 0xe9e8373114ad25af97d28e272fc42d8490373cab582193b874a10428ee6cd21, + 0x1f665ba33da4ab9d9806caff77ced39c9be254fcc4c5da8f570096111fb109b5, + 0x135aa38339bd927dd5064e4d572df55811b226bab54b0acaee511d60aedb02fa, + 0x22bc96cbe7f8cbca81b29ba7df848dd6599035ff515b6d485550842e1a35a1c2, + 0x11e1b0af7f5fc9f049877154ae173a1a72c7bc3ba192e438a9d0fa81fdfa4900, + 0x14de448becba6ca0adb21b07455d2c2864c7b85382267026e28f0978822d65ac, + 0x1844a81d4fab57aedbb4c4628e2e47fcb2922883eab0b2e1de16f248de4bb902, + 0xeef04f24ae210ee0a94bc5621574783e49d4d93365a2b3dd069fafd43055452, + 0x1328467c87ba73028921a89333bab97f8b24fcaa72f43837cbcfe5dfb7a945fe, + 0x791d832e976b66bdaaff450731ff35d998595ab9748f695bb45d2c0fef06930, + 0x11492ba406435f35623906ff45df11c39efb59fff09f501fb893d717e34f9d61 + ] + ], + [ +[ +0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, +0x312e3298297ce9b613e755220138a61f6fcb449e9f297bd2ab37fa4b060c4f8, +0x237ee46d48fc4719f3b0c74d1ce32d25ee1a406c86226b14963597d77d3b26d7, +0xe643d3d4ee78128b65244451e50daa769353d675b70cd9f3642127c70afc096, +0x276252adc5f9add05d80d4d975aa6c8506e5f3615ad04dd19b6a8fdf44554816, +0x40e4596ca95fc409132c1497cce79ce1293bf459cbf2e0b1ceda174d0e53e65, +0x6efbf7c9bf4c721cb0ebff67730a41eb0d4498251681593f54d16da5cf2e24f, +0x460e5c59d6292faa4ffea5c4f0f5b618c30291ef6259d2d5bf756df87a5df8f, +0x136b729f22d1ca74db0f67b12512925ab8597467cedf52e6d289407563cb253b, +0x28aaa152884edf31944d72dc318424c0da3492c9f7154dc8fbcb6537cd7e06bc, +0x23fdac37f71f97739b9ac6b9862be4bb4075a31e9d2118c7f4ac5074bd7f2692, +0x767aa1fbc4ea303a476f04423458ac3f6e45404c9f22c30e2ee5dbd7c9348a1, +0xcc0452c4e5cd956ef1a3b4ae5bbcaa7be7acd4c2f72d22d65077587a91c0b01, +0x1ceb88c33c35ed1e6738b9ed039e4ab506bf7ab0f08a7aaf7dab0caf13eb0e68, +0x12a998baf33d6fbf6fafcf03c462c8a5ef7704b181abf2414b689f9eb08566d1 +], +[ +0x19a92ac6087ab89982fe5650e5e799f91003fd8b45400748d2c25e40f04c578d, +0x27dc8579136c0e71f75b1cf6f5083dd8354d115bf414dd1fa540e5f39f7afc72, +0x20428c044d22ee0bcd7a3e6fab424e8b80af5027762db1e96f6580139e2bc093, +0xd17aad3b6fbd4fd8bae145159eba2a61ac1244b3fb460222167b77139c9da6d, +0x180d3e114e0939812b91fb0eff3e0b6109043c1d4018d1d2f9cbc79e384618e9, +0xcf213b1d3f6fe0b137e4524b963bed40993416f8f1b174fe697fd55079f3343, +0x190b37e8c9b7bd5ee60d0a8537d47a1a377f7a5674c75a99540baee608fd8f25, +0x3034b01c2fb47a98674d730818419829480394df38d331ade2700d39138a43dc, +0x6b1dd2a5fd27efc3cd1aceab1969f68e4959b36a0da5ca5b42c10abf0d230a8, +0x488a359cb7c3cd4063adc6ffe91ae4613f72a681535e35b7b96bc26086bda29, +0x153a1ae9f00d026c31b3462001a07a114b4276497c8144c42af93d11bb383d0a, +0x16c499c243fb5cec60a76c3292e05a6217471eacfd3ab2b95b409a367f5a77fe, +0xec171c476265c4877db3554fa9f482a8d6b647239b89e48a9097f174d5c5b56, +0x445f4d9f49d4dcb1ae866956c374e1a3cb45419e00f5836b88e5ad16d639eeb, +0xd9d065a53ec9ea1f2f08c32c30a37cf2b7ad1614e60aaf3b91508a3ffb3b301 +], +[ +0x302608d750f16491df5a285f5f7f6a5ce6b554f5dacf0b69d450b24bbb4967d7, +0x298a90da4f4bce9de81be6912c6ffb796d04c14432c8c40a105a28b135ae2735, +0x16065604a60cf2d7e406310a514e428a734b27a86e2def6fedb3f714c1679c58, +0x1b8dbca850e849940b154d50c6ee570c32444d12c847c2016b35149230395060, +0x2e93afeb1b3520058245bebe0d269664b12e730fc45bbf46cb66044d57b5bab8, +0x2eed04ef2e97eeb4738187710d3c3d598e60a7b9e6484d4b4a2f0983d2970945, +0x1b76f377622072daa3d1619b1bdc692333d5345b67f36f430cf516ef16eda936, +0xa20b0fc9107098578122aeef4dd1bbb7ef353e400ff70d382ee8abb7c481e01, +0x8e34a0ccd379ed1c637f8272a3a4cad64937438043f4ba7f5e5f5b0adf687a1, +0x1d48b6efe372666fc8519de0f01a8e5d360708e47dadce1fc01000e7dd4527c4, +0x260f8a62766f0e259aaf537577b1a99d50bc02074e10f624e91c36f3bad5491b, +0x27ffca574c26cda5aa09d071c5894e0ed95cd93036e2193e84b4e5ea7df06b0, +0x2d723e71184abac895077f84c811f4135f4d7acf5ab28f532990182a43873833, +0x278e3dfc235e7b04caeb106a14460dd6a7471b6f19d441c1f738aa625c45f28d, +0x20fd0cdac44c5b5c22cea47ac2b0d7565819a0e8110932f0e04c300eb32b223f +], +[ +0x1a3c7daa6b4af5662d0d8407b287674d83eae5b7563405f48def49981c98c424, +0x2ff508346df0d408d3d1109b26123bde5c4558bdab26d9cf3c6374a6f9291864, +0x13674b5d0d749caf2d93724d234c9a3a7b9aa8ced4f854b853c07a6d575b7ff2, +0x526e69c73070647cd5d45609e6f557bbb3b4cd4ced38e3982fe8fa217a5c22c, +0x26ea6a7932de98e85daf38c6a9a75cc6c016aa9eb31e78d7b5af1ef3936cdf54, +0x2ea7c830de80ac304f4a4342818cac408fbe27c811b25a9e6c1c2cd7a3a63ec4, +0x213b177aacada821231c6bc2090ff354d629cc89617d52a340673497b0c9b294, +0x178cdf015d8bc8ed5294bb31b6299345cd5a33e5ea30e4f03f4b6bbb2aabb2e3, +0x28548c8bb786f47791c98c20d6921d39d82a2c98681cd10f1805d4b3384605c5, +0x2a7d9ae2a915561a62c884f5ac71ef11815fa7345f61466abaae9bb172382462, +0x131105c4381b5f577a61629a53e074ae66a120d7ef9bb5c27ac675bf90676156, +0x185c152024c4fd6afd5f7f6f95134da079ce1614a9f4e03f2043914281041384, +0x1ca9f045f715d29458cb1fbdc8d84a668938b789bb4e9837cc7a2dccf90cc569, +0x1f22be26d5167ef4bb00117f8e6ea1f2866e602a986289bba484ba2f1e875591, +0x4bbff61811db870b42bcce9be11642d53a88243f2f8271b60897565ba6a6a60 +], +[ +0x2db1c9855ac29acc679367dbf70f08d98894077df2411f91ef68dd90177c1e9b, +0x1347afe5529f60fe7a738494455139994ef976212daeb0289737fc17d67bdc30, +0x17832a57483ab46808e944495407d84b427a250d2f4d8adedb0da2bf8b00f21c, +0x18aff8fe5a1798ba94632917ad3e19d4d8eccb81195395d89b7d631cf2962663, +0xa3ebcde6fceb125aee70284064b2f3524ba816c151fb6245e07cc33c13d97f5, +0x17230666ed67a7740bdd76a96b3ebcd29eca4301e827b218ea24a4a56cf11eae, +0x2efaf6a0e622f10e54e08e0e0acd1e4263ccde6164d805fc5317f9eb83418c0f, +0x2f1240e45287424dd94a661e56b89f0e5a11b9e15fcf896d04b76404ee53148d, +0x2bab506569e55b5d04ce7afa2434a095d3b43f0329b74519f88c1d63c705ec41, +0x280c7256bd6775f497c95849ff56a53a8cd9b01a60205fd41702a10532a7ceb1, +0x3de768cf69223497fd2ea181708751bcb42a0e8cf3f8580ba7d0a86fff12881, +0xaceb3f030450738e2cd5f1b0177872a632cce047ce9861db835554b1bd9de83, +0x14b711d1cabba4675d177f17d623824b3a28229a551f320b3355a9e3f9608c9f, +0x24bb09e90e64f5c63d53580b531079784e4d59d287c933d613aeeaf59add06be, +0x213b22a447492a79d3152f0ed7ff35ed7f580591cb2dfb8d91ee9dbd67ba64ad +], +[ +0xf06ee47558f182d810bbcb214a25da7f70a567a0464b348e1b30eca7de99d27, +0xfcd2ff5c8f0bd2947b6fbf00d0b81ebfb76064cd51bebbcdfdb6209e6634bb9, +0x302b344f13b30ca0578bd6eb52afb66c031b33a229b18a61a98395a95cc4a77d, +0x22b451ac56f38245014eee401568e5cc508bdec222355ab1f7194493ad7f083, +0x1b3bf735cc8f4d38d737f7fb6d87d70646bcf2fdaaaa2a02fbd0e7585d24f37b, +0x1df0e1d73bee56ad584211352e7cabb7c748edf107cd8c5750c6293ef7fa1d87, +0x994b0fad98bd40de62c6a239fd21624a196ff95d2bbfa22e0416be5694d67ea, +0x4cd761f316ecc1b03668f55b6a6a9a82ba2fd797ecbd57013176ac85d8517ec, +0x2398afa197096947d567f16acabed2956bb62acd9a5d898be5f7e154b5ce331a, +0x1f63018449c6f982d1364b473737e009d0004837e9b417d100aeaef53e5571bf, +0x1b531701fd6b02b680ac96125396ebf4df7f83acf2edfe833893eeb5f2c3a848, +0x1412ef160245006ba8ffedae4e0a1aaffb7da57e70128959a5b5e1503b4e4087, +0x3ea51d0d3eae6f814251d648892fe5985019645a2d39bb4d4928e6b4dd9d702, +0x181a8292b083644b0357e5c5b0fdd3162877cd14d98c3ae8e4e01fa39b19f468, +0x1aaeca8c009c0588d25f56bb9457a2cb260b14e88c8e81389479edbd174d73ce +], +[ +0x2166d78d948dafa963381cf1560d00bf3a0a1c288a743344c8643a58daf8cbb3, +0x2fd8655505991d7319eaca4c4b736ee81976b7b325c494ab80c69db132e55196, +0x14b1c418f3c123d91e084f3867dd62b9c73866a494c0646054f7d152824cb0b7, +0x29e7183a40f1812fd9e690cc6991f46516c6a11b6d63dfb275bdf45c2e830daf, +0x2d6e071c9a8c12592824b246bc5024f68d7f15780b8e81cb917032ea3448c77c, +0x2bcd6ecd21d028a8af782686b423a5491be09d311e8b8b311a76c6fa3b6e846b, +0x2995eda96f028f0d823d390a39a08cec8844eb9ce6c8e081c573263505dbe1c, +0x190c2382ceb77e73d72488efff7a47394c9eabaa55e913b3876f5c7425e5072, +0x1cb68d0b5a7d1e5ec01d0604e9ada4e8b0e5d657e0c3a4b981d9a89585b5b1e4, +0x17258254d8e0d6f925e7c0185f2098d534afb0760706557c11cc93481dd34dc, +0x559f237de62143ce58c3f3ffc6fd45cba5c2cc03d7a5b004324a2673ff6d5b6, +0x2d1bae8c0c7b65e609125c9900ed01b4fee0b246e1d5b40f26a321cfe962044c, +0xbb07c4601eda15ffa0c7ed3e9b5a7331deae9260915c930d39745da694ded96, +0x29a3328fef53e260a43f8fde8842280d1b74ed96c3233c5058fcf5748459fc26, +0x2694a19e4af7c2b87a94dbccdd1b3ac611b1373131cd5a9d70bc7837d8f820a2 +], +[ +0x2929be9bfe3f93cd34fceae665d96b1de1afb26bcaeea2f4edc454c50cbc4401, +0x19edbb7a983fcd768fb267d9c4a1fea3ce0b2a2b9b443f0aaa46f06e589d14b6, +0x2c1ddb439b10a092b3971318cad5b08debe8dff603bef4532577c495be1a724e, +0x28449718fd137470b9cf97b815c2140dd1c972ba998e2fe4822b7c0b33bbdfdc, +0x1f0655560b2334547cb948d9d6b9b5907c788a38ef864ae0673a78094fe7ee7b, +0x136fa4ab79c28e0be9bb475e8d02fe991a4c3e1963f8f02bd99fc08feb8af068, +0x1145dc67ca067f540d071fef09cbb91e1d3deb8202530be3829f4a74b97c83a, +0x2befa2b6dee51479054fd8dd18588a47a402dd5c3c4edca0c6c5fe3cac3058a5, +0x1589963f1ad9685037a5090e0a726b46f0d68e01b41fff4e51d7a7ee3ca0384e, +0x2e23caeb146870890855c6e35016e8fbc54757333d84d986487193341a6942b6, +0x5749c39afeb687fbf56b6749a6d2422caa3b4a4a98b702a4958b7e4ecb2d37f, +0x178880d1f6ff2f9b8e1ac338c92a0c8f92803e7f4c277c589d8f4d96102bd7d8, +0x2458edb63177cd46b51ff3f5054376a76640b495d598e472877d4efb647a629f, +0x15ac4c506f0e4516834191a3a6aa8cda30a2b3882ddc8d063ec7a9c38c4dc014, +0x24a5f8b16d150a9683e69c3ae603931192560079eb25d141ff7c2cbaab4dc9c3 +], +[ +0x1076d439c67997c37c6c1fda9a37dc2f762dd577946f36fcfdccd7898ec67cd4, +0x2d9c1650b528398e8d52dbc23335384e54aee2432d635c70a02d96243ca0b26f, +0x1b2c5206d50be044598c5897e0b4b0221bd37b510a437fe5a1b4c1c69c601b6d, +0x2edd1fa77896a64dbbfced0977e08337ee4bf613f76e8a2ce26414548b231653, +0xcbb908762517b41e306b6909833d5a107634426f22973fe83f00b0e17f13296, +0x24cbb3c94a026a76c045e4c6edfbb1367d256acf26d02cc09412eda7f59a7ecb, +0xa0bd0ea059162db49db00cb2a940d57b4a174de0f3aa95507bbf8bddfe17b1, +0x1b2b047e9e413d748553f99dd8af9b25efcc5e22d45fe891dd28f8fbc2fb5301, +0xcb96ace8a27b43f9e6227f6712da13e1fdcf8f3f9908a3a1c26a35a05b14922, +0x29ac01ae36569271195fe075de8ddfb4380c3a02d43d7342a1fb5117b8de2a53, +0x42ebef9c6a4cdbd7c6cb04d45d2e0c2aaa80deaf78bc1f58ef40906cf3d0210, +0x2e38bf07c16b3203bdbc7746fe5f9179277cca8363c860155d140ec63673791, +0x207e9157c54acea4ef46af721cd9b2f57447ed4e87be8933f1d0b6d814d6ff2, +0x167fda86032760fe696b4920c81f53d843f93d6dd536f230d2004eb414bffadf, +0xfdd5ddada0b045a445aa344bc61b1ac05142e1b5641aeb7e767de15abbc9bf5 +], +[ +0x185c9ad0da87cf824624d02bec3ba4665822a0f6b3b25deff3afcc687ce1321d, +0x99fe609dce91a41f172017be2754fe99ebf6c15cc57f31bb6f5b7d807b1f7ab, +0xd8b8636d4598fdf5326235d176c94628e61b4e7c82e78b4e564850ca2b2375a, +0xd65ab8a42892dbf60587c701d4ee79885301867045a954e709a0b39a96e3432, +0x1ff952bebf30d706276910172a3cdfcafb099480002dd0fa8c68288188ffb47, +0x1b317bd89d4ff133f75ab4d3d0b76a79ae01b0dff996cf34a725196ce703c17e, +0x124794d78885d5936bd03ff734b5c1adac8a4a596ad9f82102c00d3a684dd7c8, +0x24ffd623daab9fe13588a1c00b7f8c8f1ca8caa530a1c7131b466d950f2518ca, +0x2b38ad1a7b652e9f8bf0ef32be28b745c099922eb755a34186ac9090567d8bd2, +0x19babc734091a3be933427e66c377144245e7db110c6a2baa986003947a240ca, +0xd0289a40cf02926cbcb2747a0e1c1518e9c4f704df6aea14276211c24086080, +0x28bd66c5e1338f9704ff07003bfc744bccc39f7ce6c8ab5a577dc903cd264016, +0x170f77a7b3b9caeaf5659fce45eada32edab843510f0c1c1918e78d0f6f250f3, +0x4bf7c50eb8083a1b1aed2f2eb1e3e6ac6dac94088c526643d43fc4ffd6750bd, +0x2cacaf80e8db29ba80807838954a59a587b839dae77fae26c3766144af1c1731 +], +[ +0x2702b1be39e91044fb73926c1104719f4c037aa4151823ceab24f0cec49f4648, +0x13b4dec836bd9ccf38a503e625ed8e236c54e696c74637ae6a3686a805695912, +0x1715f73ecf73e36f8e513b1cc9ab6d82c38edc2000876f5d1bae037be5c99715, +0x133105b55e6c880ddfdf28747478b9cee5fda98c7ebb0dda7501a2798386f9f2, +0x2c728d02ad11c999b2b9b9ea9e57d496572871e774331ae56374f238082b27ad, +0x23ef277dfa1c0e0d94bc61cb2e8bbdcea30f4d4024531391a4c3e9cab4543b3b, +0x16431ad5871bcae4168c2b861ef4b0b01935d119758db9aae06c00bd30db4df8, +0x28db93b12307f5bee8a6c0b7bcca8b2305b688020740d4345fae2d04ed2505dd, +0x21b0ef1e524d8d9ebbfc6c2c749d0ec90fae708de520385ea8bf0428508c5d5b, +0x19d13c633e260305a71528af4eaa906ca4427977dc0c747c8a6a4503fef43e8c, +0x23d809de14b02c1069c3e14dff538b910e484afeff400b2c1d24fb0e0099cbef, +0x13fcf2fab4b4b66a25dac0cd517fec58f5ac1850d867be3be4aeb9854eb30efb, +0x161967aef1a7f7907817e10adad374693d3d1f981ec444384c4db438195d4daf, +0x1694d5ab473f9de3701a254240a02a4743ed5291b9208af4956404ddb30a4380, +0x1c710c033318dcb32177032074580a3504f248668c7c53de567b4830f74c9ea8 +], +[ +0xaf71a51cd463b9faeda93803cdc03186c7781845252fdf4e0155709d93dd375, +0x5fc3b1799e5b191257c7a3bc75e9fa97b164f3f4edda6ea6649c83267be51a5, +0x1c4497521275cd86c918551760f4d35becefa8ed08036c9c18d83815a9fc7f8c, +0x1c65c1b912286c5b2274387fa7965d6b2843b5b01b806bbfceb590da531c68eb, +0x29d4202e4558503b0449242495fd9ad2381705256affbba80117b4c2287175f3, +0x2933124ced84942c7077b2ac393d14464d517c7d8f1e340694ed5f1acbdff129, +0xbd580f80ea79136a9b520cea04461da846d9f23e62277f13d6b3aa6ab108ad1, +0x57b88d83808d3675ba199bfc5780633adfaa44c9b1e32463d66b79e1c6dff3a, +0x3a6c87ee34cdae1ddd7982cd318362e1a278dc9cdf1cd1dd03b6c36aff836, +0x22692fb680511799b8ceec96e7ca0e1cd21de90f94856acf334ffbe2fc262053, +0x1d85033ba0c5dd804c5237c31ab8b09684c635b8b7578c50c246b15314926871, +0x2b52e9a0a9a535ae05d79b8b555d461f148db269f49e38dd8ec6f8b8da106aa3, +0x2773fcd9cd996f38297b95daab22c1e79f179f4c79fd4bf6f4abf8725ecd5032, +0x18ad7311ad63af100808f64bdc63392bfaa0a3881ab03c3157ca8140868a70e1, +0x19b88372c544a69321b273cc62a95b006931a64222cab4536e797e578a56305f +], +[ +0x28667f9c7332073e293c80b98edffae01af4f67b4c52ab45e49db8b30f182d28, +0x1d0cea849dc7409b3b26de35715b32db618691bc123cd9c4c5e6f40b4a1e49bf, +0x161556e03e94c7156607cba64c0bb7fa00bcaa126df8afb5d42976c03b7d5e0d, +0x419c20a2ef9d70e930629591eae4c63276c5d79d6948e98f2c37acc29f1a4aa, +0x1d4a3584e3933abffe0977179b8c112f2cf08e409d33362df4775d1373f4d366, +0x104bd1b4c028b287ac3fea1ecdcbabdfa6a065e9772791c3de84d945542fc206, +0x267ef84e628bff8a9a85df724e4c32cbd3237d91bd65c43618d86502032a3694, +0x2d361efa8fc65b03d45507cfb53549b3b26a84ac50b3593dbc052806ecf59fec, +0x1285c484100d70c992f6b6953a9955f56957e9a17641679bdfd388b6bf60ea42, +0xe1a46a527394539c39e9f1e4426d3188c0d9077021790734ec0126d0828fbc7, +0xef206f21658db03fc8d5d6be5b18374247aee43b3f29b430a6fed7fa5102a84, +0x2ac3db07d831b461f38204aa0454b1edfc1a0de5b7a6e15e49c63bc7140c3327, +0xeeadf9b5fd85f9405991af7f4cb2bda816e5aca76103b34b891502f921d6096, +0x2931d38792a3769da52491346c7c6f8f106c2735ef2a1ca03725396983a0049b, +0x131154cd6dcbb9b469cd6860b861699845abcc41f428331b1d2beebba8ceb767 +], +[ +0x2763c33f5b2d7bc3a23040afbcdaf998bb13254c272a5f8635a12606a59c2e5c, +0x27ade810ab16b1c9d9b363d48e397adfc79af3a4836ed63c650053ca057a03c0, +0x177d3d44dd549944ff5772d4742603e163124583cfa4b673ccf1a25454ea3be2, +0x2c0de2ff6c43c1d034459dc8458237d808fb0ed445eae2cf7e972c83f006995, +0x27ac47846175fcaa604d687cd2ed41f2ca52905b2eefa79eaa8583ebae76291, +0x165a3778b89cc7da792542f4c9a6dba92b85175a60d3661beb77852b238629b3, +0x27e08a80dc448a0ea08c79c9198e57512968df40d45f08c26ac8242d126aedc0, +0x1fd804ca6b5d2a3cc76ae1f125a0bee456764db7a553f48bb47f468f3c57a95a, +0x174de7ca0ebe6a1290ac6a8076d51b85fe8fb4022da95a59a6e9f1fc2fbb2efb, +0xf3deafe2fe6fbae9417eb6b144885051e5d1642e49b37469d39a6bd6cbbdbbb, +0xecfff476860b104100ab4d0dc92d93b993024a1c0d6d50b339243e9ae67ccbb, +0x2cee2efaf90a0e74febcd521cb5fc61304ada5f8760adc044cb684f341b646c7, +0x140214189bf9a4001311fb36b9e5d27a3f3ceba32a457135a3c66d76e8403553, +0x2a90f5ad074f3e239345c3d75b7081804b34fdfc2fb9f720a6448818946ee976, +0x1c373710856290660f38b96ad9baaba487a10183260e1d06f9b9935d36e9b0b9 +], +[ +0xf81a8d8e08758e8a32aa8292666c4cb6ba3f5f06c4dcf4fc502ff97f03a85a6, +0xc3bf8b042a0fc9b018e64d500484eeccc8086ec911012ee19a8e94c97b1f8ba, +0x10539e3badcbe0386b58327fa5ec50e92d483bcb819b41b21dd7c54eda76a99c, +0x308a3fa0a2d7ab2ef746509f2fb76d1a5db994586a54e9d109448f18b281b31, +0x3ae04f50079403a7c6f13c02d0ecbbce7631eeeb2f9f284dc7c2a52fbff4770, +0x6bf4105aeb7839b9deb71934169cc975451f8d76f834499b281eb6cd69c071f, +0x28cd5b5220315f32a404bf919a9cd01a3082f5cf1ed6e92dd79a323bfc62df5, +0xdb2421285ea7f5979122022c62e752e1b15c491cca462b4e71b7bb0661990cb, +0x200d26a5d00a2c154aa75036fc4e24885f7d8e3ecdfa19beb7cc15767eb2de8b, +0x1a1c643b8d0510676c8afea7a4c4af98432406731046ca882a497b29a7c61777, +0x1e80c6db7632f6d64766cce10b56d0762622eba0de31b6271e95ac94cec6ef32, +0x16c8f7d85e411d0f9ba685f0fb815c6ff517ab5463c74bb9984dfdeab8299477, +0x20830e9933ab9c82b1d99369207399eb347fecd8d8ba430b5925038cc3295055, +0x256a4d8167c0f602f9f3b663dbde4a7cd3d47353587b017f4f03627650b813ff, +0x11139f7a6884d0c2efc32997248db307bbc0cba48037fc518478e9634fcc745e +] +], + [ + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0xd4e118218c553f4fd17f1dbb39ba942efd76cd18298bd6b72e1fde271c74372, + 0x1c9814a36ea57e27bd838375e1c1a562dcd2af6a66aad460bfc8afcf3d63ab8b, + 0x1c573e2904e49c6abed20981459d41c560544306978535d6becd7106ed3e41fb, + 0x9e39b302efe7ebc4307cd009e6bd6f7b5128a23298b11eb8e73047cf2f2e920, + 0x1fc427692601beee8d5f6bffaa3faa89af61a2ce7a048f9a596cf2c38ac2cfd7, + 0x1e5b7cbf92351abd6a71a235d9d2ba54bebc40e693a66f3b893174ccac29766d, + 0x2ee69d018063e4752c402c2255b267a05e49736814f2c9b7247240d61e8b684b, + 0x1eaea919368dbdf57be4a55db999baf940ba81052b4e4d5b8e7e16253274f5a, + 0x297f770923ed719ff3167e17564126bc6dda16c8cfd27aad29dfa7a466038453, + 0x13a94e1e1ffd11c4a28c86290a71162f82c03ea2634b67d98c1a5c1d06912186, + 0x19cea28494b1210a4098ac0e79d99fb546c2c3588f3cfe4a068359bb6082e56e, + 0x13841448d03b83eea61935f4d495503643436e90a8efa58be47c85e581b050b7, + 0x2df272af26c5aa5407188de71beb7cdfcf870c778b2093cae868000a2dbfaccd, + 0x29fe73f14e2420c982548ec713b85e374c1d8a43c2bc2ddb6302bef9fb2b6e24, + 0x9070c4406fbd360eca9c300edbd0a65fe8f59b876c18ae13bde14e3330e3175, + 0x2c82ea6755166fd89b688200788ba82d29734ca1b04494d0643b8689ab0b7cc2, + 0x26e76b10c0dd0dde0a57f9b731be061ae57c1d964e2e525081e1fa6084632b57, + 0x277298f3554969bc6937d1b5d5fdc5821b3c809206a3930ec894caf9a37240bd, + 0x287e53a89a23bf624bf6613a821ee5d502838605198c699cdb6ae5d274bb8453, + 0x2e9f85b46415dab53d2c1820226d4e7117e6cc96b7ddffa9f6a96cc697256255, + 0x17fcc4d649ce2696bb0e00460172bce45e5deb8c57904e5ca0d056c9df3e5297, + 0x2c971b630f9a4bca7a950159ff4411578bb39eedee8d9f0171b61ef7febbff4a, + 0x9b526beea2b32c93c9205ce33c6dd79824ee0123e0ee8309814432299a9756c, + 0xc8311c2fe1acce872212bc73164132f8fc89039b4b297090ef07e1997704279, + 0x2ea4d48161c13add4b1dc83b3666ef388ada7a353f3da4c8053efafdd1742bcb, + 0x447cfb281dd95e5bcf7a195bc52e08d78aed9e64cc9d7973873d06a42b8964a, + 0x2828d9d20b414b800a028afa5e61ec4362ada01cbd66f3a4e018f941a9edc227, + 0xf37dee2a8dc76e8cccbcfc527cd8c3383032e1f3f5065e39d2aa70b8fed775a, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0x2ab166f28cfdbcfc32e51fc1db9264b527e40c696357cbdfa6bf90bf09fb97fc, + 0x2e156785cef17b7d942ced8e2ee15ce4bbe2ba73c0e55bd50eb898a1bedcf3c0, + 0xd4641251d71b781208156ca3680d6a5676f749b7588d5db0464c76ab985a43a, + 0xce5cf743d721f040dec40606144f5bcc8b068d2bbb11c3623eb423b1030e147, + 0x15e35852381a52021bfaccaff799de57d8dc8606f2465e875c7f9e22a3183ba6, + 0x7e9b4e0821320afbbb23fbe3a2027192f2ec891fde602faf446d06b3a770c04, + 0xb743d70dcb58a6acc70835a005c7ce366876fe3efe504909b0cb87aece170f6, + 0x10643f7d6181a8b5df1e921eb1a841476a937fc6a473185d8322c9a18c487a3e, + 0x2928df7c94de7ff8a3770980f0fbe3cc4e4f5908537c40b9e75247bc31e6585c, + 0x168d44f63e58a5c713c37e067709bc369c27f428af5eb3eaa79d445b9d073318, + 0x2b8845a96842f965343a94e76efa217b83bc1ebe804c7b25e8b3b58dd165e79c, + 0x1f44fb02f387d2ce14dd149cd24fb411a7c738157715d6a1be66ec028fc01bdb, + 0x217b5aaf9893ae41030f6c64ee6870bc995427c81e04a265e1774401a5412a53, + 0x45a1e21cd1e0e5b296cc6e02e249a6cd0eef3f6487292f0f1c742de712a4a4d, + 0x1901d160707a8edfbb7d4533914b9b8bb06f565b1abace77f7f761eb33f39e5c, + 0x27dee99b80374f3c665a4dc5c89a8e365a5a93d07e51c727ddd6a896c7ef8a7, + 0xb1c7058abc3ca4f1633d64c0dd5f068d7fdc10f96e3ca682d1b2ae6e289aaf6, + 0x1c495d660ada6c32fa2f107a811730d99ec01d9a17dca7001e659fb8454b9a1c, + 0x100885f5765de1733a91853cf668563b88c9c36005cb54cae61a82b6bb65160c, + 0x233544636d02f161bfe5bae6e687558cecee34870235d36cace44c6d372f0545, + 0x222a180a868a589137d947276e3cbaa74ca5052e685e02c178f64767a4e66446, + 0x22b1b89514b6a597c1331e24ec3f4e3232821a7330a525629d4d7e04950fdcd0, + 0x229fd163ea1ae80446877d78272ce7c50b8abac8fc591ba25c22661cb1e1d5a2, + 0x5efb45e61466bbb89d081dfbcc8bd398bbecd324d5950d65151b80c102a0503, + 0xcdf2465b92dd04b968ea8419be7466b0ea3785fbdf1a7550dc5b99e781853a3, + 0x2acbe99eeb7c3a167376c64ce28e10b1628cc3f7f480e68dba68bd470f29ffc6, + 0x21c173647249e75c7c8cb1d097da2d4ccda1031ccb8be5a1d2c3d392fdea5bd2, + 0x426c0054e199f89ccdd26940f3b6e8e30bb744886d5ae6677ce75f0abcb1a2, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0x2664a99501d9fcc7afebe82773b4ea88245d531d59a7a0708522c437a2c63c8, + 0x1dc35aa8ae4c95f4a17d44a790157b7f27045bfea974ef5818a2ad557ae4d1ab, + 0xfdae6869465240d7a6280616afc83e937cc5821d8cdef8ae9a085395aa708cb, + 0x1782b019aadd454d509149e265b8474467c1ac219af05a53b8f671a3d1c7ab8, + 0xe543d031bc1748852a333f2e031cbcb39d5715e8637ffa18f18d620de3b1ca2, + 0x104993ba9cad115c79a58320fb01233fb0124a73e040581c6621429cf2fd8e2f, + 0x2aec2aa10254227e5e0cef19dc491ffae856bd5a9b029d926b60cdee38a2e30a, + 0x14395653083408edce60edf4f3232a9614c781cfd7f6fd183ee22e08e9d46daf, + 0x2e200704e49142bb68b20d9f7df040a1bd32118b21d44f74dca2b31818693012, + 0x2797778f8ed2e9af3fc79ec16f248b6209c03036a7f0d5066237befbab16e11c, + 0x25e0e403bfbbb31be8c5360007aa9f2e36a4dc4b5b2b0823f8cbd4349970ba35, + 0x2e8423bdead0b3ee1516ec6c5c816c7ea3004a45a0443192427bbc4415251771, + 0x2a34015d21144652f722f141385ba0510cd38da886bc0df34352ee7ae76a07be, + 0x2a3fee652dcedc95a0b44a072aaa54f5155b036b22bbaf7eaf0b9c3cde42f4cc, + 0x135692d47c5a0d4df037949a54fc72f230314fe7629e0dd7987b620c66543505, + 0x142093c728ea36edf0844de5e3c4b4f1e1b44b72a413b7b2a758b5be41c8d616, + 0x2a0b459ab3f636567fe0f1330ecb15453f62a6993b748edab79ad8cdd0d535b4, + 0x330b0a428235522e1d5e4728b882d56a82cfda90452ab9187127ce73658a9f2, + 0x2c44b22ae15ba0f22763004e8fcf0af6c602a0cbadc67eff70a74000b67017f9, + 0x1c68c04dca5f72aab61b7b60219e29d1183c8d1de5c7c8c09460738b6bf9760, + 0x1c74af78ca0448531b773a27c47800cace7f86e68e4969d29a8a12f1b9d59330, + 0x14e2ebfdbf9c76e96911a23a9f9c7076b38316393fe11a0a7492e605ec7a9c42, + 0x119a85d4048b76c56f636acfce7dae71759828d711dd6b28ed0e9a236e4d8fb3, + 0xde9be78e2e3c344a0b76a171b8d7ce1a1d05f25790a2451102e05a91472bf35, + 0x1e91cd25f12f2f3cffc2490773f8af707fe1a6843a766a3c44eb5b8fc134b002, + 0x20956c83b24ba2bb0086a91f597d0a902f2d74e53216bbd9592d35c438648061, + 0xc716d79b1bfa9d016fe75522d771400fcd75862133046a9b1011540d2331e87, + 0x2c4f3e61d58aab9d3c10abc4656fea493fb3d6374708cdb2e084a67e2fb6ea6a, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0x15762393eeb335167599c130b4b6d22fc3f053dbbaf7635f39701683f9642dfe, + 0xd7579361389b5dec0c5817e57dd5b775c48facbabb151eb0f7e2da5ae19d158, + 0x265b9eb82ef9bb6fe2f70ccf516bee6b9be401183f0932784a40a61186f47a42, + 0xad7dc8d9d0b28ae3046b8f23c3a7cb614090e05a3c9ec3fe8e2fab367df2272, + 0x2a3f87839d7b3e0528e7b9c221379203354304e363684e38f5fbeb698bcb19f7, + 0x2834e210d211aeb395ae05198f7a1c475be1cb0d89a8c0877d8e88a9d62fc5ea, + 0x8cf6af0f8c7017f0de1cf6ea6947009c1041169d5b57c49938a6a4c863debbf, + 0xf9b0115c9097f360d0fb624b14c8b4a1ceff857220a181da4c32f619b164bed, + 0x10902d17db9823294cebb8706f44e8752e5a3abfd8218ac27718a4c0fc8a458c, + 0x2ffc17ee98848d878ed4315e3ce007667b4f18bd43993e4d969e9cb38d8d118f, + 0xf878f0a4df67255f88423ffb527014656515eaea2e9cc36be9c37135041fd98, + 0x5dd3e66670174cdbc764ce0711c58f427dc503c798e29140820053da7694d26, + 0x2de49ecdb01104151943ace205edcc81ab91a9ef2af4c33ee2aa2d08bad6c023, + 0x2cb9a3284c718a566d7db309aa0ce6f8e61dba64a225f746b757ef2eaf0b9311, + 0x1d1c9593d0c4ea4ed9a491dc73821969ced386145cff808364bc37335ccf5a69, + 0x23a29371ad7760d5c5de4ae5024a4612743fa77b09eb566c9f41d216c9552854, + 0xee30c0ca292c3dbbcdc2471f750036531b0cb85eb8464d3f92466008ab94247, + 0x1727f0d18b422010f97058ff5e8ac23fc850951774b431a38f60a1d9b5560175, + 0x2ac5457bc236f8945365b828183f8266e3d1b5b3dc2d9ca52febacdcde11b71b, + 0x166d29ead2255e356ca2170969b7b9b94bbd88bb34ad7e5663f4d3a25a330ee7, + 0x2e386cdbee46199b48299bcd0cc8ec486f6c6caadb087b52ea86e51d4f39e736, + 0x7937bbf56ef747bfc1543e6cf5c653434e85a225f09199ce11747da5d44a530, + 0xae9d9852098390b4a5b9a075d32020a5d61d0a2a05fc6037408840d43bd04fa, + 0x1181b5e009f4e51aa287e113ed3be581245601ea27ce4b35219c7317087568f3, + 0x2475a06052db24962d86bfe804db3f65205984e5966c1a8695351dec487b611, + 0x1e9530a8088a3c241b2e5ced4157949565aa90425ec8b494def155581d6e10d4, + 0xc9c3bdd72c3442d12734c0f3bcf2bd1bc679cf8fac9127abfb316fbcae53202, + 0x2fca60f1092c4d48164a2e2c81fe134cb4bea555f4569e095389e181a4ceb5ec, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0x1115614e19e210b59b4b0e708130dd845be5bee11aa1ce43984ccb99beb3624c, + 0x26643a2ea75d103a87b50ca1690a55117340ab3f4fe78e63f81187f58a392382, + 0x699ce3db9d5882c04716cd74bc49c2bcd5cfa34039856d27ac7354b60ab8412, + 0x147e382354cd1bd30bb3383eff03f89974b035a00897f89d9545cf501ecfb243, + 0x76e68370ceb55cca9757765b0c2eff1e05426fd3b1eeae4de2bd9f49c121700, + 0x8064483b1ee3733f6b6e9dae47a7dedf7baa9b67ff8471ced25395fa38cd884, + 0x26225db4d7860e869a00f54fa10923c8041cf313eb912318aaf8f4f897401f44, + 0x15ba41ce4e4e0b3c6633aa83180dab522a28b25887f78e8acb61b6cfc6f837db, + 0x29bf9692a1f8c909bf1d0fac4a04de3804e89c3fcc2b081cd25d44b0afff7b09, + 0x29838b380b43fda29e4b8824229a76291808c2a9c4864ba8e5577fdac75a85e6, + 0x165e81bf9d1b5b89ed739b99c84c53dc3fca070e83a818d5bbfeed37630a0b48, + 0x10a7013127742057201e42ecbc83099b49a60af2365f8bf7cc403a3095ed3fa7, + 0x223759ffd12a39e3e384c76802544c3778f14149d0123c1280fbb92ed556d9ff, + 0x707296bc5dc73b70944cfa07f21c77042753a479540db83d9115f9fe9ee3e59, + 0x205f5d69af9f4bb66c51fbbd99ecd7108c76240f97f758a17e60f46bdcef86d0, + 0x1210dd2f4c47992f4d5c7150f1bd9346860046534bec9bcbb3a977802fe9037e, + 0x144ccf1aeb8b78de9437aa82f7a82ffcb958529cc51dd5a283635ffc0b0a6c8a, + 0xf996b911c7c650ebcbf4bade79e10411e3d4ab0e2ec01fce87928c4c0f77e80, + 0x1b46a1b0ed04080cb068fdff6e531b02c002fc3d66b3ed2d656137001b7926af, + 0x19fce53edadf9d4cb5eae86fd8b1c68c238aef46a5ca33603367b8de0927b2f1, + 0x26b0885672f6494dfb46ed42a401176f2a2f42790725f14adaee8e9638a986ea, + 0x2db620812477b8d733297937c52ae01076f5928ec0b7488e855dfc5b938b80a2, + 0x20d30fe0ff4f57a3cc6e6330182f23fdd72c24aaf0a5b372a32a19e80a638112, + 0x2a5e3d7b9813aa7a0cbd2ba1c425d80e81e12de4060b90ba7eaf832f00f34d2e, + 0xab8b6d9abc9cf77de47f36daec39db0f7e3c7a31db631ac6ebfa501a4b3f94f, + 0x16c8438c2ff89c19e2f9cdce14dc380a8a31c1f65d059e23931f69b921e5b4dc, + 0x13d36ffb25914bff0a9c1b490db18fc8fd7a2ff9fa3b673aa2ccb2a64539c7e7, + 0x28b8ee6f7ee1d8d0d3ebe26bf4246e8eb545148ca86e60cbd0bfdf4e9b22660d, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0x10dd321b7a11a2bc96b3f4719b4b443d94e5aa2ddbf428d32e863d7b956aa085, + 0x5fc6b8b740e55f5d0690b7e2309f312d089c4555f057172a6214835460a342f, + 0x2951ef2c77380bae297a4fbc05ea97de562ed3d80aa8a986359c3ff00bcad10b, + 0x2b7c767b440ca0ddb88adb86af53231819ad6c21c222b09a8fc8f9d61108276d, + 0xe44d122f91c40d9470afc3e484ec8f8fe6ad0fd24146f1d38d717da4db7673c, + 0x1ba47ae303c2e76854d7f399c74f48dfaaa3287c07b9b79bf1fd08f9da703c4a, + 0x11b425d8000810e925867f7a9850aa799aa2338185b6f97ebbeb7b481a52feea, + 0x27abc591fdfc4152cee25f4fb6d0a1e932a396b72c311c05a99a9f923b1f7014, + 0x2a7294a73da17a02829961f0cd5b34c67c909acc3874a238637fb570d4c23046, + 0x8b325e346b09a1eef8be7fc3d81867135e87ee9958f16dab759bfba34b0adad, + 0x1d8bfded258e085fd2c871a9db0ca38ce5e5d232d2859c9e3da87829057ff232, + 0x10321b7d5466be1e92a7b8f17a16a37baba2987ed57399fa903b5385d81b19bd, + 0x1385299af14ad7cefe90edbd656d72126e0e9078317306984f201a98e3e87ff6, + 0x1b3f863460bd743da42eb33e47d2cfffd9a1855e9fe571674798d3b0d2aaa8c3, + 0x16f65f24d40213e86452cb242e20a222d8bda274251b4fbd82dc110ad78f1101, + 0x271aae4782989dad19f84117ce0466a52e16551386b42a74552db0c6e00442f, + 0x2913b1df62de1405241829ebd6bbf2719510cfde2d374c171f2b0a3956beacb7, + 0x102108bf4a73ec9abced652ec51ca12fb06e48b5df049b9e37102ce0a77b657d, + 0x206603d022cc8608f807ace7c0ec31d9dd98c202be6d1bc47a4d44df54bb48fa, + 0x28c4e8e4ef10710d1e972ee6a4a2f88aa08a0d6fbbd77cbd057ce83ab6b75bcf, + 0x1431769f19552b0579c9a23e91e9f017ccef784eaf0b52f33819bfd72ae98f42, + 0x20c42490a8ca07d9f39b11e720b833ccc033e1ed16a310d53222877b0630336, + 0x27e9b6a362bfbe53ee9fe071410ca804a9bbfd2d2e579b95a50d63a16c988da0, + 0x2e937b74fb17d63c90d32c1258c1cb4108f5e3f82246fd704d44233653aab860, + 0xb1b6974c506d78acccb5e1b6c9a5583e9c922152ec0d113495dc49b14a61c8d, + 0x18554cce997dedb95d27bf135c8bddd3b0c8aad0551a6f372bba51613c0335ac, + 0x132069ecac9f244a5e447a1cc19a998073aec780e8236c827a66bf9fc6ccf8a5, + 0x17d40185a9458fc6b98948ad7da77f035fd7a3618233a43af0d0e511e5fa37b1, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0x275d28b52043874241a3fbf29f0fc8725346929cb378a7e4e9e8c7a8ac1c4128, + 0x168eb99c86d705c289b00227d74828339e88cda8ea726d3d9acbb57ae75043b1, + 0x2a76294553220b5ba2abadf6bc42a902641312f0bc1953286b08ba16ae65f435, + 0x4f55222eec01a996c9c4c70c11f6375714c601e1547cd47f1dee0b3999be4ca, + 0x26afe145a5c9d058fd25a6404e4acb62cb13d299de81fac1deb35ff9f4a40c33, + 0x2cd5c836e175ed7a902fe2334f239d499f51b58db73bbf2b1180cfe4c4df7936, + 0x29b7a4911bb67a29bd7368c0f42079aeda1fc0d452efb2b129b0ad93fec02eb1, + 0x258d09a47dffa2af8a1dd733c8b08f63911dff878a2fdb4794e319d46a63df7f, + 0x22e2643fe45193389fd7981bf191826724d5ff1f0a68651c1c98ef02d81f1b0a, + 0xecb1213c8df26deaa40d8f6c4f0a1d4e3c72da3dfc1f4370de7dad7e32618d, + 0x14ba09c0956dddfe7410192712238658b4d65506c78e318ae769d2732c63adde, + 0x2dcd28c30f44c2ee7d8121acb638debab46d0feee4dce60d494acb677134a60f, + 0x117c6959729d1d774ce1a8fe1fa28251592f3bd62f86253929ee45ca959e4b79, + 0x2c290cbd7d76fc9f9cdcfc47b48fd66ab55d20b7e2f73357e68319367c7fae08, + 0x1f40cb5c53ab688c259fc3a2bdb401115330f3b2850955a39764374e5f2b5195, + 0x2a58a19ce1744a2411fde6401a6f33d899f9fa9c59eb6375530f45bd8a751339, + 0xdf6ce7e1bb5c41d366d6d7d5707c63eb3ae9478043fe167f712758a05b49206, + 0x2a32f08c015e3dba1d7193b31362ea88156b370fccf15c48abb7133747833ae, + 0xe549b8f127e7ee7a8e67f9dc534fc8e3a627059b406379c63d86a54a593d86d, + 0x2ad6b517cba39a16caa6fcfd53d3b8a43758e360c703aed8691d721a523ac174, + 0xe000e82e93b69d72b8385885464cb1531c74d6255f1c1156539c89dfc84091, + 0x24b57d1e4c920be2b95c0fc8a84f5d5603f0c286e80d71669d60049b94770419, + 0x24c65f0e2ad6e614ea9a53b058651459f966152275afd3cd6924a1e990e7d201, + 0x1d0ae8c3033577ea4b1f2dd4b68b83620a1ffcb4d5426e9603d4ccfcb6f1fb66, + 0x12c81853619d70f737544addf33b8d104af13ee311ed522df131bf24d83dac85, + 0x50fefb4229d0fbb58756c49b28c0ad0fee9338a1fb239f8d8ef12e168aa162f, + 0x1dc4a881539b03ca1b5493a594be14ebdcb60bcb2b4d1b58868d3a6558410173, + 0x1e7e5f574d74633a061ca773e969dce83ad758e4d08c37e3900f62c5f9b805c5, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0x2d030d498dd22e5f9b3761b019f812c2df002ebbdbe5da92f38be1ff1cd97e65, + 0x227f6e1b292aeefdaeefeeaa2e7af21fcd012a794ca2c18d284661cb0fb1dcaf, + 0x9a991758be8db845ca4b488dfd11e27f0c773c88c2507ad584dd73eb1709358, + 0x5b3c08cb06d23cedf2cd4c5cd248514a89b09ff70ff56f90221492081480705, + 0x207e60dbdbbbef1f316198b79e4df3e688c3c71b8f82e0480763cf729b6bba03, + 0x1d94aa3d4e98c691b3efaae72ae18d50d90ae56629eb00e7bc324eb2362d27e4, + 0x2f99f4602d8a7612c573c3ed2232eba3f91f030f8b5c2dc6de3d8aa60bba2869, + 0x185a7fb027b40f8efcfcbbde02cbe15567d64ae6ac9bf206781703c07d6272ea, + 0xeb85ffa7ee5e9fa96ae4697ca527ee7bbfb69b5df611a1b6b715a30f9b69b44, + 0xe6507cc613c091c3f6d563b24b8b78d78262d7e6a470ffd98a1ca6cd0da5ef1, + 0xfeb286fa095e4decdc49ea3f57da799b2818746837f591941e67a93f2bdcdbf, + 0x157de51c339785fabf4ea584b55e158485bce7dd521c0a25160247a84d13e6b, + 0x118b39a323a6ab543f005f26c89c673480204a183a1f68e0100d6be4d55df254, + 0x200f0d9065e79bf29e35fa9ce14f0d87038e43ec1c1c2d4fabcca003e2f2d724, + 0x271b6dbd7bbbf9d98a9c5c8814c58923aed6e4a31d7bcf8d723561f5116df99f, + 0x22594da35eddc1850dc757649b53c126403a907c6113f39e940e363bd2830509, + 0x9a6a3e13a6aed0fb709786ffc8a7d560642a59f2cee2dc68781130407455a81, + 0xd5de9b94917addd8b8ebc8eface4fdc044380a27446e5d0170c4aa965b8e48a, + 0x1ba4f74d7dbf44f967060c619e429485254c8aa06ac08bb8fb101a4c88811cad, + 0x2bd393ac0c6602f63ef13835a3601f6c4f84f09cd47cedf02ab0a92f0f59e813, + 0x132cd8a625910f7fa7a999d0338010825c353659385ea10a419255dbc0a3456d, + 0x2bc9e5ad597c8f773a7ac2dfe21c16a9d5493a1e319dc942e635067ac6924754, + 0x21af2adf48b95cc677f255d44aea3d1132115782cea08bb82a526366b7affcbc, + 0x1baa899af3a60f883362aa1b88ea17778e258d3defa44fec1b3f4f9c13b890cd, + 0x1083673f89cf1ffe18b41d3cb7084270363c519ef6a16484220e30209f83d976, + 0x5a5be7182497c5c2ec9e91b1a4af88703cb01ea7e7d8dcc535d72a60611f271, + 0xff6f076a63edf8d87f70b60ac0d64f311eb1771d961b6b33867a6378181088a, + 0xab810f3e1dce08d5e5289d8d32a3ab20ebe56a1e3f6cfec818462804b0aad37, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0x36339f709425b44b4b4158479da0b011c1a67fc8edb682b0a4437607b9aab74, + 0x25f49340da53700404b20e59243b4e5158b8a2dc24acb8f072504149481dc8da, + 0x14b076d2ce8f4cb8d8323ec8d743947a7c8fc96f149c0dc4a74d883939d620b2, + 0x4a6fdd5c06168268ddb9886b5b9d23f146ee182a155e175d17b07ddce7df8f9, + 0x8868cbb867db89dc7895e3c2c06466e0cd0936eca7e35ab5fb8f63f7a4722ac, + 0x13639b2e24f941877911b94bb9a0256f480021097c2f8d713c088c628d8fe61d, + 0x2487694daea37ed9f66185b6ba5700abd9144c18def2fb87af3a4fcc5b8a6b5e, + 0x62db9b179c1677bf6cd17e9bab4cbbc17a113c73c137dc6664bf4938f723352, + 0x25d7d897d92a0fafaca382402a1034b20ffde5b709d6092aad0e89ee43f48fde, + 0xbc883b75255e0e7b62094e1ca2aa65cb2a2dc7c4b30233f6e057257b25adcc8, + 0x1e902b42eb37ffe108655260991d4f28d286585d6e9c172b6d87be8e08eccf31, + 0x41a3b254a2c8446d8e99a292e24bc1858eb3d8fc841bc7e1ab03dd5f1c40ebb, + 0x21f4b9d60cc5ec13b8e87d116b27d89626bc76c0e8ff4caad5f825f158feefff, + 0x246be41807bdfd90b7cb066201cb33203cfd557d218cca9ccfe1451a86f4b258, + 0x13760f834ed0e52211b6d9b36080dafe079c30c279777ed992882ede9fdccf3c, + 0x24e75fe9b1f75436c465b22fb0520ac1afe2cd26e0a2d7b6476a3c9740e1ada8, + 0x210a9a4b2b1e03dd5fd270b8303f7bf9eb268844761f67473372cd665b1f319b, + 0x133c572bc84ed9a77b6651162bda90620f004f61aef467671ff8019ca6c09bed, + 0x1bc35641ed2b845a94e93bb2b89889d0b9d3338d45503f21f1fe9b0c09394eac, + 0x1ee1cb63ff99f240cb1d5f11c0abf418d696a0b73560afd9302a5119750daebd, + 0x25e5840c2abad4b937edcfc1ef54894d9556774b1e921d1a437278f8c3386222, + 0x137cac7ea18f1785a86b769785cfa6d919af27b77d7e1cf07cb4070275c91384, + 0x2e39652c251cb2e6a89166be880e1021996ffc55dde4b823cca3c305a1836794, + 0x3ec58cafe270aa7824551c1948911a0412a4985d79feef0324bd63960c6995b, + 0x293b947e1e6860bd81442b2c2a6fb3ae59375d12f857b5b8161e0f4bfb430ef4, + 0x2727bae7d504f2181e1910bb7eee349eaeb0480d214fafd019662edc067a1290, + 0x1be2f1a5593378d6fc1505e59c4c28ffb6cdf5859a5e2e1bb5b49a36051f77b1, + 0xb1e3d4a0d6e3bdd411c1f8dd4f2553ae84544b84a57b1f09fbdd26670d4b007, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0x1f1099181737a09a66b13631030982bf438bf84d3715a0bed3cbebecaacac44, + 0x249a7a0b3a015a04fc08a2c6cbc7787aba1cc983c94a3d5074f584edfeb2416b, + 0x237bace2c06976c536b56fb5acdd2ac51fb2be8c204834b011106f03eb3a297d, + 0x20d83c51cb9e2a1fb0a0fa7f32c69cca88e6af24878f21fad622e364a6be6c1a, + 0xe65df5618a774c899d19e6a6d8f0aad4a10c347b12ac1fcbfedf7a9f17ed09d, + 0x16ab51042d2c056da53bbedaca317fb7543846fe6fb147279b5872eee7821e54, + 0x2e2d8b570da9329bdf02f5feb01f2b6e32fb795631c6be29e03a1c0ce31c629a, + 0x24d1fd499e7bb80cb2d0ca1fd09039bc4cf518ff43725796bc2b48d237c82e78, + 0x6a96b7d99b2b7a6e57cbb355217ecb8637bc3d4ded1e046783a6d5f63689392, + 0x19a143f1c5ff5191d99a6f144d8635ee4e4833b0b80a86434a494a6a97273239, + 0xd4e60cac8694ce18785f94c5c2f18ddd5eea3cb8a70ab4bc3e533b3baa0c674, + 0x3062c4cdaf43e790dea387e5bb1bb16a167f30e644e5411f9252042d516b8f0c, + 0x1b378a25d0cd861fbc9491836aa9c1fc169456c2027b34ac1b61a6d7090faed9, + 0x21cc1b4f8732b2a733b42718b6a48429df379711208deaa65a7eea4af1cc7d30, + 0x2115e1786ec90fa373ee1a8f50768702b3b89e4c0aceff138ac487343d707792, + 0x15ce8b9c8e950b1292ee1f80d7e271d3c0b714c1de34b76063624d00a686a39a, + 0x1d0e917e058eb6cb8ee32e9da420bd6399f8b2297876d84d997ecf8ab3b0d156, + 0x24d9b1d31cd6eb19c0c63513a6c3fb04a43033968696e954431d00f128bd6349, + 0x1e4dae551bca600dacc58fd37cac50bf2713052e2a4935d64471f585508f0d9b, + 0x11b1cc629721ced48c3494595863dee3de1598c11a681412062610ac859735df, + 0x26ef5031ab96b02b00df512752c7165e368f406857478f18d7230b6e4a1c80dc, + 0xd83775fafda795718ca9d4777d79b9c4354a73bba6813c415b3b970fbac6e62, + 0x20be2cd9b7d6dabd4db0dff89911987ab0479dd9c1c081fa64b97fb97c8d3143, + 0x255bcd5c215aa3bb5bd9e05f4bae4a68e152e3118fd09368fab9fe69e23149d2, + 0x1947d75ae45108e7a86d0e3e034bbaf27b7fe718451e3a5c206dd5a122a917f8, + 0x17af7f16f78c7b517171424fc4f47ba88cf15c4224bbd13afb3bfb05df96d89e, + 0xf736ed6532f0b90d30bcdcec9b05d1c59070f105255e7d60f8d3178e753c5c4, + 0x223efe61713a8d50c4d8f00ff69c45ea5f27defce0f08a9bc74e7a82084bc788, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0x13a0d52fa98cce5cd43bcb4aae2038de35a787f86d375b019d7279a135ce710d, + 0x57d3beb3548cc7650f10f293fc2d393227dfb72422e89072dd8b90466bb57c8, + 0x1a6533a65e764adb163780a18df2e7f0233bef0eeb6276895c76a474998afb79, + 0x1913a71c0e6f8c87f433ed6ec0bbe2e7397544c0dbed7199c5f4b7edceb06a79, + 0x2266891fa5e56d0240ee9871ad7107c0d740398f8cc9165a1b09e10a2b740c17, + 0xf5652567afe30f4d5e934d9852bcee7ea0a8fc142b4822d2340853022128fd0, + 0x5bbf0f89f5ae6f5713c18b57ab2997abd8bc8c0fce08e2047ffee7ff4e8bb61, + 0x1a7bcce0d63b580b6779957d56f9abfe5aa8ec1fe610e952c4259091046d42, + 0x2b775827170698c370c7fc1706cd95b8f6c7750f338ac0fcde91ebe40cad9dbb, + 0x1b9c97f57c84b5f780373eeafecd7a4ec3e065219785272820672d59e985526e, + 0x1c89b9708064d8558f1361c6acba6d73eecd06c4e4a157abcdce2731cbea3e95, + 0x9a22dd01ccbf3e6ed2de7d74e16f58edeb748843b19d0cde8756bdf30e7f222, + 0x2678274dec9c2180d4f5b5e07cfb42c2489afa4673c61f091a5dd00ab0e6018e, + 0x1400af0c777fd9934b9fa5d1fab3576164ef9b31a6c8be59f72cbfee446aa148, + 0x2bb2d320c6f15fc80d7c78fd8110e715403df00154b1d275fe6422aae8d68cc8, + 0x912b48b8c530838be3512cec8d4c210726e17d660b2a726bdb44f686052300b, + 0xfce537edac05ca8b03b6b472dbe1813bfca33c05fa1acdc695c6e91d60529c7, + 0x1be4e4888a092ed1691160e4381ccfa8997237e78cbd7ecdf8c12066a49c19e8, + 0x28bd303aebbdad8a14ee284102ac2ac5e23680287d8c3587a71cc61ccd6c5b90, + 0x110b79c0bf8f52881c24f4e7598c5f5b30112675a2655ab183be54c69f8a85f7, + 0x2d17b110312b5b8d233dce3470269203776b47b85d143e1f45d59c1685ccf272, + 0xdff609373bc4eed749b401df1e7948ce8c8084f4c816844c29ea7a07cdf320, + 0x21445547b6584627b60ff1364308b6d6d1d08615de63a5c2ff1ec7f7764304e6, + 0x1ad2606e3877709593699f24a0287e2be54a2ba74f3551ddb1332c7cedad0d30, + 0x10c695276f9d6578a7bd5c351c1cab9affdeaf9abedfdbac72ffac057b67d7fa, + 0x100f820a8faa0bc1165b8a16f64ab9baa87fc7e94ee23f5a16125a71cb06b838, + 0x7bf7f1faf360f65cdf14fa9ff38b2619b616f2913b7403a4fe0431ec15a57e7, + 0x7b95e787e34c76215dbd3e1c548e5646bf3a061d087ad6477cf962a3cf73dad, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0x2ec7afda93383730c9043913c6b866c20a5122081a7744f6d6a317b01177affb, + 0xeceed2a6602d291aab1064254c70fd4113a09bbf3527f603f67f01336915d35, + 0x284b37b2fd2c4ddbb2bcdd057a56680d46b7d69fac63b80c991f14db1ab5b345, + 0x10ddbb4173b040104f12ffb5fcc87bf6730ea0c8aee88f9e2c00eaa1a4231804, + 0xb87d2c0dab9ff1ec96017e8c43bb5281266fc92231375e78f02354355eb0c74, + 0x255c350cb26d49d41652f9a27f8d6c223b8756f8797c0c960aaf36fe91b4c910, + 0x2ffb78c0bea2534d67c0b061f4ecb9cff5cdc0bbb9ba0567b35b5434329ce24, + 0x16aec970d0f171ac2f7183d67c969ce69cf1f4dc73b38e3a72d8adbad367ac92, + 0x2e74c92c412e2d6943dfb7946c80f5fa9ae87255fcdbb98c437b65f97fec81b4, + 0xbdb1fbc8b81f57cf6725c95bb9428bbed046d555dddbaeb02b3fb9baa750fe6, + 0x7bf15085936894c23de42271ca102d554a45b54ae80fa0c7e6d7aa9c72cb65a, + 0x12e18b956f687e1c43f50a6571caeee8bde8d7da9ad5e5e27ffad30f833eae36, + 0x2c45b659cd395880788e5215997b77761c46555ff084f24a0d28dacfeecf5c84, + 0x2805d6c3bf0de9aa5c7c354947020efa9489995e8baac233ddf04e8ea8ba902b, + 0x18187c330b42dbf89ecc0435f0d77a7cec28d256f65047d4a3e1ac8aa6cb199b, + 0x2fef8da38b7959eacb7ec6155488836641655c11b8babc8f12e715afff115d4f, + 0x88011673864ca6778bb97d51eb1f2962b69d07a496b6b7b370cec217c601ae8, + 0xf6e83f3c55d5fb8b6b6c89e176a5a4f81a3a0acba7113ebee661b411613438f, + 0x2d59be2aec0efbc67f59da156d934313e8be205c1460699f0e70e7fe5ecfebcc, + 0x2aa0544263e125a82d9ca1beea6d9cf22b40afc7155bcb0f1c8b1ac23a24f6c4, + 0x7e3a92c9ebc149a74d4180ffdc30e8ac7bd6598d78bb8f3530403fcd9b12221, + 0x1827bf9f11d4061c506954039093e66e60041b2c96b8f7e1e4e550582d1ea13a, + 0x2e147c8ee46a45f0ecc64de8647e833b1ec708269b37f4e29b17c91b9bab8280, + 0x3117f4c71dc298ea7cdc53dc55f0a15541a369691622934416026bb1a65b8fe, + 0x122fefefa669bf51b544de5c0aca38753c8f32419b2ece3a97f0232e523f4cb3, + 0x18e8e58431e6dd229b88f142f9cdff129883bb54edba0854b29a8add15354d97, + 0x12e0b4787edc9f9d3b12781839f3edfa715accb3e527bb66bb08d355b87afa29, + 0x2489282bdb046d49227adbf0c44fdd3abf0bb2ecb21a2886336554389d452c2d, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0x1e2fa77b090a5c2e5f1d37e25ba7d06596bfa3b546362103a4ff19bbacf7e9bb, + 0x162a1276d397eeaa3cd6ee80478788dad2650b1433b55b07919d966a1b87ce8, + 0x26eb2facb83a5a98dd405a0e6a94735a4c04c19ad847c53fbf047732eb114fc, + 0x2b7496ef4e35f11f739db9bd69ffbfc416a0c45512e31f86141641bba04f3675, + 0x26792a375f1ca2315b76d17b3f2bc3d6a3edc3c54f8ae682171143a91e48f091, + 0xbff276591776a997acb59a579846525f8fe7634d66c9477f5406b05985e7769, + 0x20e9af0c21b5cad7c87e554c98052eba561458f8f6b6534c4a1a0d0713681866, + 0x1f5e270d7be396c13a4f29cdb58c7e4f267423ce2d242c93049edea4b9fb4ca7, + 0x26ff7c1cf25310bd71e59d175c3c3a0f068a54c8493c401a3b67030922b5a757, + 0x1276fdeb195702a6a855465cdd5b807f685ce377132b625b3f1a5e934636e59e, + 0xfb72a4d993f139baa0ef2fb229cda32db7cde0f10c9031ff2f9ce3f2b883491, + 0x15a52948bb2ee184cbfd9d2b419836e859f2d39291654c082261a8a1986aac6c, + 0x1a9d4106f5a30c459a80769db1359ea4a3fa0e42cb32ea4ff03c9b800dd8bec2, + 0x1d9250e3e49f0b5829ce06d877703ee0c8e9a51b516f09df7dac3410d6a7b5d8, + 0x2524fab526c690d264888df207397be10a2626b71e97dbc66d1928e358bd243d, + 0x508f820d3a3cb5e0d30b4a9712a99eddcbd3adac2b1301f123e1556e975d30e, + 0x2ef65d57e70b07fd0a22938cf1065e3ac3996df77e0c100d354eebb224dc449a, + 0x26b914f529af1a7e31afa5334e60374474b998ae18e99efdf19e40b2dedd49fb, + 0x155837584dbdbc23962e00fa5a6115c10eee76681f25c51280a1bb2842d8488, + 0x222e724b780a46377b77fd83af70b53cb39a1dddccb0eae70e4d5dd6dded8da6, + 0xd050bd15578fe41175ad1e75a8ad0b27fe8943d894ddd74aed4b463b7f02790, + 0x5c5f00321782b3d2fa6fdcb67fa63d1a00a9f63d35f4ecb08481ab535907d46, + 0x207a0c370129f953e15836e8f91d7fbde34553f94d6b899e8645c96f1731f098, + 0xf875acc749b0abfb86f3bac9e8a8e56be9b9b55ea8815d19bee069150d27fd2, + 0x38a70dd168196731fddef341631e16a97447553f924d6c204d440dfddc0b1fa, + 0x1502b8a3411c7391414156fc640e8a51a1171ad07586bd6de2be2e38fc6486a8, + 0x7984908f8931b938e16c96dac3b58d151c4dd0a92d671cda98e16953c2b7f6, + 0x694d96a531fe9e369427b3457bbed265de03924ccb0331d4bc445c4260c551e, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0x17efc478730ddf82a8540cc83c4770636959f1b0d8cf438b239f60df816d7519, + 0x6d6d06423d66562ef9caef0773f3fdbdced70fab47b0de7876b7bfc1216df7c, + 0xc750b14cdfdecf7394c6039339cd465a8a010272c1bff8c9190ffe3f0018d7, + 0x15000d48d85c719b68db8c9ed7e68cd481437c653ce647bb7c965ef9fc1c07ea, + 0x1b18af3d53da20198957288dca6a567b798666bc14c13dec46429100e01f94df, + 0x16e129dc67d5c08c79c6fdaf38def1b90f6257ce0017488b42ed2d46bdec04d2, + 0x1c958e9abba1ec33523e756e8be1e0fac90cf1ed314b37d21a7b4d3c84e574c, + 0xa4487b4c046d0e836db729d214a2b6995146b527ea42d9f1b1008d321a4c7c0, + 0x169b2c93aceb1182e58c94204e285380af13476c86b6c6ab3c3a65c15fa21c4, + 0x797bc2c0b8e08a4eddead0572838c237d0d825e236b725ef88269b0eea4d28b, + 0x2179889dc88d5096ee6914c03f347b9d9e7c5cd8c8b9930b5faffac69478b6f8, + 0x1057d99f4e9409dc2a83b8940d79e8e1c8e9c1b55a2a10f4261575653bcc89ee, + 0x168c49e73137bd006b0b0996b3da6d2562db2a94f94a8e763ea36f950c0f6342, + 0x588b7dc72c564a70347721e31544dfac82344701d29b12bcfcb99c951165ff5, + 0x30052c56471167c83d58a970764a1bb51f602f45b8fe42494182d48386d19001, + 0x284487bda08c8fb308bd9f50b700e107e82ac7ecc25ce91362303a2a2286af92, + 0x2e1e79d879db7beb9259bfa882fe3a1a34345451b230d4e27d7cc8358e43dcb2, + 0x1fdae630269a40c8ab1a64d8fa09af3a160bc7ec218f7aa5ebca2346c54590da, + 0x1d6caaddfaa7d7f98b2a093524361dbccf489a6d2bcc0ea1e2e13abcb025c83d, + 0x5c7c0b2bea90e985b2fd8c7e1e9801335eee69801dcd879edb5101739294534, + 0xee54de6bffe8629a8fef48dc9de7a50885054a28dc85c6649c42abecd607dc7, + 0x93c826c2837f20a15a7dab825f873ca79fee1607b2a1ed279d561b346aa9e63, + 0x21c75ffc19ad7b92256ac9ecba8768feb4b6eace676e2f6700c87b8ea6867341, + 0x2dec2f08ab0884ac001557f139ba7305a30d8c342d4ee53e4d4e6abe61879023, + 0x12612b1a8d7ce43e1cba045f5c0ff9cd61ff60a4df948847a5f352996c0150a4, + 0xd0bfc972a52fd760da54a5e78a4d47042f43be8ce046bb4522be2beb644dc8a, + 0x1bce51a4e501309316d08e24fda303a3f39e962cf2776588c22381009c08298e, + 0x19e6822defe86285515bdee389f08a4cb9e8042ca87435a47443cbdb76d30814, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0x2e931e74616f42a131d4a8b56506fbff77845d8bdd66420beb3325097c35d2ae, + 0x12cb5dfc2abb8252e9ff46727444ac95b3ea73f0410424424488e144f8699673, + 0xab23891e07d9b14ab6468d8b54083479ddbcc3aa385804af4531058b6f52f21, + 0x76c297b77611e733d1e889aa59629450dc9a47d6b0f134ccda083f436d85a5f, + 0xbeb7545c1a73b517a6c89f22ad332b7e343bec5aab4aa67759d1bd5c513cc8c, + 0x4c7d041c29a50e697120f25caaabd6be874d81442d23142978d9e30a18fcc0, + 0x564102c95e897c7df22c2a4ebd2f41df79b27754dc83ddadc1e8fb5011bef46, + 0x2c05ce35ea49db3699362c4b4b64a5ba68cc375ad8aade0365ef5421901a5a94, + 0x1656b1dd63124d1354b1830de366e2c3e19075d195f6fe6dd5b28a599f37dcdc, + 0x2507b36b6b8e24780ab4b7be3c26ad57c16fb9da2edb33c3f1dadf3ad05f6119, + 0x126e91f50c4a00292aef54cd15052c4bc6114e85478479b60318e6dcca5d6c32, + 0x2f9ab42a46ccd83e7a7005d4553ad3414e5211cc2730424122170c92769905de, + 0x25aeb979b8ba4e466651dd441683325ca06867a60d27d0b51bab47a73ef3b303, + 0x1856e09404e55249a6d7114a4554ed94bc09dbe373ee994cfe64a06a70b2cb46, + 0xb6edf4c57e87dc5eb7cda564eb72f7673631ed91a612fb422487ad732be85db, + 0x2eeb7ac6201d76d7272b2b8861c44f18045fb30837baf0040fe472d972a0051, + 0x25e7df19e834ef4fc02b6bc24f1e45c42d935dc8e324467f216fb7456e344584, + 0x22254c3bfc63bd575812867c85be048ba6f3cd2d2b600594703450a16ba7b35b, + 0x1f04d9141844aee56a08a3e8b056715e347c668ccc6f1fda6dabf94b2a077531, + 0xff41228c1c85b1f6d2df6e37422bf7ed8b7dbeaba7da63f6f96bf9b3a525fc8, + 0x286cc1fd10f3b5e4d3b48d6996d85e284b6a6b215c0b862d5a29972f6ee1b681, + 0x2cb3455b4afc670928e65d5aa1461ed1f048865f31b87ff6bae6f1b13303a69c, + 0x23dd832c9d5244d3f7d185b3e8b3d759c11b86ce8102dd3811fc743e62a44dab, + 0x128a2af0f0d1965fcb13344373cc1bb6f4fda4a5c28cb7eb31fdec881348eb90, + 0x2b9f84c295307fd52151b60b7b676d157ecad172fc2a8cc89f8dac7dd6696921, + 0x10a3da81ead6ed37cb8334cf6c7d65b69862ed22f485b092bada3c0e516c48ba, + 0xd34d3d1a4e840d8e2cebc5d527a72ce929fdc7ef27e482a0f029a7b8c6875f8, + 0x5a6ae7b5423c19aa7ec80748ae9c1f5d189935cea5723cffe87ee7ceeea8c04, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0x1578614d9a2967236aeda5f4a4dfff54693efe351787f006c743eb600a936bf2, + 0x285c79334945bed5f5c307dd65410ce6d6093d95dca5550146995d79028aeb09, + 0x10b5fbbefe482164a1e9c30bb4631861a12476186ebba60da59a8172a24fbc4e, + 0x1cdbb43b87d76d420ff6e1adef1ade355edf97a1646107d44993af476b78b98, + 0x19733eab4c8e4779cc914f07598df3bb1c2aca04fbdd5a116f864a85f7a81fe3, + 0x3009eeefe893a6b04a2d51a027b63406170c305d525e5b959e057825757a8ff4, + 0x2fe6c9de6a79e7bb2342a0c0992a9b8488b4bf43da0ce566e53bea4bd24e6018, + 0x2d40f2520a5df3a80ddab03db8ed7af99ea054e3a159c4a3fb6fe79a769b685c, + 0x22340e058329ac548f679421e17152d6106de7393cda87a9f7351cedd26408ce, + 0x5609d6cb0bc2a003ef02b3f62902f51b49bbed72fdf724675ede239432cdb29, + 0xa4481c88c41e347a2ef5fd6b915772289c2c90b91b3fff301844dabc1c51cda, + 0x14ade810e267932c4023ef6fea6ab0fc56063c5740a256c89e75a17264fa2898, + 0x199252b794492b2d35beeae8c1411bd1b5177e17af65c6f86ddd3261c2f8999f, + 0x1ef0142a7d35ea276712c1b5b86e1386201c18e3f774321cf69b6a0d2ee3f226, + 0x24cf18fdd7098067ebe68731ff580f7c01de7251814a4666ff518222130aa2f3, + 0x1087f37b188ac4ae2e05051a05b60e0579df8f4223d874716a6c251ab62e5b0, + 0x1f0aeda37e4d1e81150239b71a4cda04f0e4d8d7588ce691721df28fe9f18c61, + 0x1184563ea49c28693ec800bf53d6100048fbed518e1317ad922c095d486778f7, + 0x28bb14de4caa8db804e9cfd9e92cde9011c829e5cc88a709d1761638c88a0593, + 0x5e1f290e1cd58efecd18bdb15575356b84677a59c118b465b9671f81639783e, + 0x25f7a0d0ce8b40f8b02ca63dfa95a68e391df9f6d24180cb3cc976b4ce04fc11, + 0x480ccb16af84b2184c6f5b529a3d8f444f83dc11781a106ae10da23f61587ba, + 0x539296f5b7b7008de45d5c8516fa99db18f1a822529d3266f60fbb9959d4eed, + 0x1e424153fac06000bbadc168cd28c2456abc7b0be95eb89d8dfc7b9bba75769f, + 0x932c03c10fc912a134329f330f819e8d619aa8a9b6f52599e0761ba32c60e01, + 0x1211f6c693e1d0dea72aa0a0c505dcf1f9fd56e16545cae0818d554937473906, + 0x423bc3cd7620b919908d77becca14373a0fd5e3e9ba4470d967da7ee65479, + 0x2118cbee96964430e47912132f0d6f1c2e6fef1c001c8f55ab591052123d04fc, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0x1f1e2374f0f17846133ddb87fa54430c6c3ddc9c532111de01eda3684f397a94, + 0x208b76b6732f2ed681d8ab9f1b5c510c8867ac976a3fae72d5f9d88676a75a7e, + 0x1fca7fa1aef782e5f42195a7691e73b90033df38495b91e5c38e820426446820, + 0x17f136e334658510bf76430b18584795cc8bef7a11c33a61b5259339acca3353, + 0x2c03456c81a5e2e32aaf6ff4f1d5720677c920bce4adb99d1d89a60618da2320, + 0x1a5ed510e6e51803fd72011c2d6de4c638d51c6d9a57dee093680dc336f5d34e, + 0x1a936bc6777c2da71bce31f6fbd646a3d62a815680203edc66acd1148132029, + 0x1b4a61fadb468df53bf54dc94e9a1892f69e693a26623b6c768c9b6f08eb260d, + 0x22072ccc189a669fc9c1dec178dee22e6810db51fb07d2e1c4aba223a89f25f9, + 0x1970d123b4ed8e8bfb50c817284430e9349f042e456fe5d518f499c071f89430, + 0x259064221267af8baa25e034c726164172e8ac0889f3d62d29ef05acf962f9b4, + 0x2287530ba760334e46b1a49861dd542fcf4151293041712c8544a467a9071ff3, + 0x840062bb032fa90a3eaad025fd47a6353793130aa0b8626565b48035782aa66, + 0x1d555f3bbdd6465b30b7da0ecba9891624d6d041bb781264a89aa7b16d346c0a, + 0x23d4f39d8b478d9f3fe9c56850eb091e6fb14326aa5cbc9b2b0d7d87c283d763, + 0x2901b8a58d07adf7c3080c1a36cd9d70652aea9b07702d07ad0923d758cdb949, + 0x2d5fd10271ad1b7fb5f053107e3e769cd3509ed4d501be13cfa1421b5394605d, + 0x207c3b106d337e3362d760cc41cdb5be011fce738e5f485d2b46b93c64cf9b83, + 0x1492c0ecb1dbcfa1c6635de3f6b7d9eed6613a602d44fee471a9757bc7b42898, + 0x1644d335356808c816d04419514ff5ec328dfb9ddf78e623cbbb6b20b4ed3bea, + 0x2fa67fff02c7d3ca002389d54c6efc4687da94708f6e27d1bc5825f164cbf4a, + 0x21e1ca08175564b26d688202433c40a419bdaf250b832229f4a1f31e8ace5464, + 0x2cef2de85c29234f8717a47931f3e7e5d26de54c4009f0cfbed5742defb3bde7, + 0xf9101275c6d82c585bb03708869626a1b0edf857aa536ba105733f0043efda3, + 0x13d2ac8ccf60c75462050c8f441e1ef92d1b9a842c36bfc82ddff6561efd49b, + 0x23a7cbaee856630abc2b423732eeebc1ec3e071391d03f9c9b51351c67943e5b, + 0x2d3d1ee5d3afda1af49ea526d8f250430e61921b93adf072ac5202b5fd8d0f38, + 0x2c40a0792e0eec8a8ff8b91a36835ff0774e11e3f13120c7a6a0efbbd6ef1f0f, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0xce2acb8e9575bad440cc92c82f19694f1ef1e5f0dc1dfc83c39ed80919709db, + 0x255e8b6bfcd73f20e6c4bd3f61ed3b8bd17626c5e5a843858093a7ef55eb1d61, + 0x71756e3a68459939af3577f77567bf688b996b47f0003c4509df83345846c16, + 0xbffe3446589b3eea6ac107b311307d20faccc7bb45dd5d6849cfdf7ebcec41f, + 0x18787bd666cffd2d76b9b7344eed8e34feb8f96edbc138486fbba2cd628ca4b0, + 0x24dd90cfbf38861e307d9dcfd5507b2298bf6b2618fa97d7e36b07690fa7c13c, + 0x1410db3d1ff17500d908b029552bfb5c44e3cad85b44d8b7070a60c359be7abe, + 0x114c5d80f6a4fac9b3962788dc0c542378352eb593c0cf88355d8c8032efdea1, + 0x1faae4eaa27310edfbc782b40c6ba0969779c813807d81630b192d053d4d5c71, + 0x1c6a9217a08e3d6b4961cfc839d6e8218df84ad042219111f80d068524566422, + 0x2779a31633b41cf11d988b3560faa03f2fef06ac2b58f88d89fc5f386f28b6fa, + 0x1fef33a133dc716d8477f6c00854b9bbbb087ad39704e2aac12ec22518ca42c6, + 0x51d3217b934abd02e647c9cf0f9642b2c35af886b2a45cc7b50fd3268175a65, + 0x23e2976b87ebf7b64a5a3aca1926bfb61744e0f4f8360df40500f479e052e17, + 0x266d4f55ce9e2183ac237c1cb82a138cfec9b415769742b2feb57d27eba7027d, + 0x220ed82038edb07e0f74092c809db76ce01adf533a42b51200f67cd58bada0d5, + 0x1739b7715b95db81ac96c21ec1fe7bf0bc6766b37d0572066766e34ee44500e7, + 0x270da5e7651be197e4b200aea12cc8b88c633d4086a0320fbd7b25ba6bb603cf, + 0x6f6db411a03949e6bb5c0a24f49967f1eb39c35eae012aa873ea0b3447d6f5a, + 0x117a292cd83ceb0d341c01e65590f4b38741c3ba51c0d717d273ddaae5c59cbe, + 0x263e482df03f958b16c2130b9cea9b74b47ee5d7f070ed5a6ab849074386f863, + 0x2803f7d7e3cbdf5be9306a32a90b58cbfc5490d1d74609cbf6384476b29265cb, + 0x142c7e2c2e91322de905b8420ed32d6ff157d64e792a38ee29cc9b316fcea3c8, + 0x147d7bfb2d88839714acc1080d935f9c289434d5d0af4772699bf4732c13323d, + 0x24bdce338ee348af82a60c960800094d5794d7a2607d5f3ccdd1fd4fe7b95583, + 0x10a0a7c38506d41a52e6ed0c4e14dc1283848beb7de73e0e92d4a065121c25e2, + 0x2f5162740cafbc5f21e10a4eaed36ac331b046f846c46a319b54d9e2206c892d, + 0x2c74369be037f8a5d985bf78b1e89838e0f7c1aa845979b6c5142747a0bc6b0, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0x28580a3d76cb8ac7d4ded32ed3b70d34ba761e0b09803f10d1196eee812c8e69, + 0x19cf15cc84de7c87a59a44d02e83f88120bd3f7d1ab07ffac878a17320f4b2dc, + 0x21ffb716f9f4688f477d2b03bfb4c4f57fc37c75b46f85ff3d8da6e028263594, + 0x1c5e5652ee5c51f74663b5612d00e002ecaeac6dfb26d143e8f52a7b62c81346, + 0x309be74d7ea79ab9868e691afcd53fdd6591a5c8cedf965a1895229eff54a7a, + 0x8533bd365bcfcca44a62b4a3d7e1b0963ba990d5bc5577aca90f3edae8e319c, + 0xe7b927fe75b3e3322651fbdea1e01e7b5b9a3022e640476d39738a016e11728, + 0x2c044e77e1889c9f2efa9d217fefb1003978eaec9d8c99a494ca9c6bae1e980d, + 0x16ca28c9c6815d47c13eeb8a6baee797a2f9fe8fafccd65bc714c8165737d172, + 0x10e2a1c88ffa4f4f58ef6974b6f612c37755a1aac408008ab7b3b47160925666, + 0x2af08e42bfe36b6a795d78d34a4d4bfbba27adc10a144920d5709fdef7977301, + 0x1312b9ac40cedcdc7154c3a110803222b42b2b0d944ce7308a992074c0fdc257, + 0x1dc24b75a241225e913226bb4e43d43c7d47be4def03fd1b569eacf726f4ed27, + 0x13d3a4fe3528fbe42ec423e367bed051490e1b014ede6b776b07d8e15509d882, + 0x32d8f0cf21c697ffbd788f3f63ee8fdc1dcfd3ab649b39cb5e11a6bd2a24d03, + 0x28c7587692973d407a133b2fb5502ee9a51a4671568fcb05435cf0b5fbe69ff0, + 0x28e40378256e3cbd8a7f8cafdbed2021aa49f01a7d7056858bd3eaac1dc0538b, + 0x25d943e06d1e141cc39bf61f79e7af2d71ee93b361fc7237a2d9a8abc986056a, + 0x17081444189ad527d5b845af2a97df8c7a4293f485b483f9e8ed7021102f6443, + 0x1c79729fbddab541d2ecdafb93faac1db19b4de80d06b964cf4cdc81e1e6da71, + 0x45619b6eb27ecb55a5fa865895e4bb27712f4e95a84af9bd717b58e500de857, + 0xe2a9db5bdf2e81d036943df530d84e17424ec54f39c8039d37dd85ef65e3dc8, + 0x2ce50979f6944eb44498a1265db4d51ade51e18ca81bc69c0324103cd4116d6a, + 0x2a77de1a9d04ffe3b955ddb3ca44d5cde5ab83aca3057ad21d2275326fe032a3, + 0x17cc644fba9e3aa9ff2cb6b1386494c67079d7904d5d02828a84f100798d4ecf, + 0x231b0e5dffe1731eef0342d728926ae7c9d14cf32b1873115a3d47b231dff70a, + 0x2975aca67d081b04e4e00d824d5007a02f47891c5b0e6d74fe4bdc36a2c3dc35, + 0x12dfba0cbb1703dd03aa3c6e434c14e50ce09615152380a14b97bad4aec1a8d7, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0x138e38994513bf4cda526bbb6d9a7ad3fa60bbb5b8922f3fa889be7f81acc688, + 0x233a737f744a6f8bf1fd4d3099a005b4783893e8203403271ac14116bb96bed5, + 0x1c8af617088b03edd11e2697f3f1d61aea527eb312465a7d1d97120547e5eeac, + 0x29e028abd359a281cffcf8e6def73b243c8c0b7dfc781fe16d85c9636647b689, + 0x11cebc3218317d6a3fc99fa24c0297c3c917d2c79953fe6b195043c1ef2a2911, + 0xd9eff7d690ca6de96fd8d2f757fabff01e7cff5f9af21a331beb5bf3c2b1384, + 0x2c10ae179ec436144d591b58693d48867a3080302df8f221f646d00519233ac7, + 0x195340f99f3142d58a8374368ba7b0aabe7551bdf4c84114c543733fd41633a2, + 0x175a317578f2686003214142b6ac875027c021572904376694f8469ea2da5c31, + 0x16ffe892781788c756069f60af49a1edaccddd1252b0add84fa3850c4f80002d, + 0x82ea1876cb380488c70f7cdc9cbf6c494a3dc6db449b27b2ad55500a9132673, + 0x1cac7d7d70279321973432ff45248a4497541d07c9a2b26eac2938d661eeee13, + 0x8755249140b336749da4930b6a82f6f7190eb05c7daf28948aed60049d00f71, + 0x207de9d69726515af8d068d0d26537798246579d29ba32be2dc2175e53cdd044, + 0x1405eac8634a44a35197a6503a005446b48e7f415210523162c39a8a8df15829, + 0x22f87c997cd1bd13a3cbb02d3d534c897528939d9e6714fe0c611c673d67d86f, + 0x143d40dbf8cd786ae5b20fdc9242fceb6224b64c187b36a7ca66489c86489299, + 0x2fde0b770674587f1be3feb619b4276125f643518ef715e694213e3134b7773d, + 0x160ea6110b10e9e3f0d14cacc486c0ba8f9bec3498024257ca96c50b2d2dec4c, + 0x15b8418dc1c46f3f546d70d983bc32122e40682185698f7f567f13590a1ace6a, + 0x20d9d10cbe767a538eca9be227274944094b9e9fc01b61b657afbdf6bcdff00d, + 0x104952b13891c92a6d7f1c5cba983aee4a3dfb31a1772d99192ab343d4e8519a, + 0x107209e0e414a0e40dffbdc7b52e2ae3de04e4385a8c810e92ed2bc2f67411e, + 0x1bbff156637ba8444d8679abf776687b8dc2462d876f17229f0d0b62b6eaf9c5, + 0x61f0e30d8aeca231af662496c1a4a5f4c6b283a79ac0e01bb677cb14fda83e4, + 0x3062b61d13e9c6d61471833d8e6b52f8669578314817ac28d650af7512e2386a, + 0x156a1c93bb1bb19c46f2d621ed100918d9f3194221788493be08644da83e4aa0, + 0x1366584ccaadb9ef95ec40f53e9cc7905204400b52fc6b9c0d21672fabf65753, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0x727060f004a12682948595634ffb74c7351aeb401f8c16c31a333c8638cbcee, + 0xb43e5d620c5f01be5a5a3193bd458a6ee196533aa8fea3efbed64a83ef2ff93, + 0x711911f15ad7134cb9ff97051a0f73f346b4be3f9754508ffad823c11e60415, + 0x62c118ab0b9ee4f81d12e70d751dbff7d7047c895aec5d87b0e1dbfb311f9bd, + 0x1edc90b1e2679d7b61040b272d2ecf8d471417e3df89be715d5a85a6759ec37d, + 0x2bd026a17123ff82ef6a745e786ce3b69171c73f00a518889c320675a4a31824, + 0x18b9a646b8279f3242e40800752742093df705aefdc130e903026d7e6f37711c, + 0x2b6d003cb10653085f4ca141b8674a257140e4ad022a6e85a5681cd3f415f3cf, + 0x29ca967040bb4ef6fdec0008a3a1821b9a2682629abc6c2f37911be83c4d7b51, + 0x29c5fe585036f56f24bf281bbe3891d42d867ad8df031759f34586abd4341cc2, + 0x18250473c36c6b2fc023d9f980e9117d2b7d815386613cf518a5d5e1cd98fe8, + 0x21ecaed2c0849f445ce370dbbff7a0f4e3ab45444ca614ad818856b057d0b559, + 0x50f18bada3b7265d2194dcf45262069827248a1f68fccd800ff0c8f498fcf7d, + 0x1056d0bf8e1c158a403fcba81d1b25ed10ce7bbf7436a0f82af53417d7758da7, + 0x10ec2167737c5bf2fe50fe1c44e562a4fa629576c43c31c2a067d3f7e199aec7, + 0x78d695069c5a1d37c71299f3f5667516b76a4507a4320117ed26b3b6c05efec, + 0x302b34000b8a4c5f411458a6c12a335a1e0f345bd012c03e9afc62c8fc07dc72, + 0x25110107d94ba32e47336fb64a434e02f723e7a429eb23b8413ba03500c56e7f, + 0x239c9ad23c9efd9a7be7489e4a1240870a605c5b8e84021f3bace86281f5fe6d, + 0xa71eb71ed1cfc23167804f59bf51324c69d188602e732e5cc5a6e3f73455033, + 0x22f12028dd01cbb90141cfdf5497ad73403416e437f063e1ba391cc18bc0bc5d, + 0x1d2ad4ea7240a2f71841635c52eb7a7484cb97abd94c70bdb187724db31c953d, + 0xafc6833626de473ca08a5538a64a06cf9b604242f029c4ec576ba6a1376cf97, + 0x19e01b3ffd3d1c30017cbb3ed8dfd60838f70e001773558fc4a1c9818bd4c197, + 0x26db05b80a904a64db20297cc63e2d0a190ec9fcf9d528b9db88f7e079ca4d49, + 0x2d8286dfebb09365859e524291676812918ebcd2b5e25131884e71037a5def72, + 0xf3c76d71a422101870aca73667ead0b355e8f9a8009aa29941293e5cc105d, + 0x2c7142225dd5a38f329349d4bed6e06f58baa1c3dc32a6abd057bab3a45eedca, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0xd4830722141cace7a3d588567117cd756deae9d215cdec0d2c55c7dd293cf31, + 0x826bf62570b5a5f61782845b349810b7a481153e7ec33bb3667e4a2c7ce4912, + 0xb74da59928d6c22800edc212200770147b8fcbd5d40217cba2c1ae784ac3c66, + 0xf5da0d1390cf5d4fead2ae4e463fed71d0b1d5095428572009022a7550864f1, + 0x2704d9998e1e17d5a61ea377b1b78ed6d7ec951afeaff523a406624a99447c04, + 0x300f822aa4b956ea43ab45b043adc967d41d2f7d67445ecce1bfd3259e62df82, + 0x43f2876cf4a9b33af023d447bb90b634b37fd6a432b920e2dad4fe1b9f734e3, + 0x20d982fe655c37b7c046a07110e57fa8649939e376a4fd1bb6bff3f13f88dbf0, + 0x21d6cba8317dac264ca383630b4da90214d803c503ea5520c5b44dffe2c138dc, + 0x873018963b4084347ad81b085693cfca0345ab963f656890c90882cfc5dcaf2, + 0x1e6176f2c8c0e6acb5b02f4e54d245f806b9fa7bc126b3435b79e5819fa8c9cd, + 0x21d440ca5e509e1ae0476ae546df34414d7abf9152806b4c799177b87b153f90, + 0x85ac321a5407d7ee948b0cad303f92751532cb1b55ff17e7267c0c9821bcf80, + 0x225fc6208bc12aaa5deba3688931a2bc8617e6b4ae76c1de0e85defe38e2f14a, + 0xaa6847f08b61d6fc7ea711789b76255d14b6ad7de89124c962fe57f534be98c, + 0xbb3bf6dc922baf1d7a9f555396d78f31cfc3cbbc534c016ba6879d02cf400a6, + 0x24118b406a39de6a222bbb99be1828f9d70c24cce6ae452b20644f3a6730b95, + 0x23f88043dcf501f06a9ba388b05f1c14ba29078b978e7f9a3aba55cb0bf1a7b7, + 0x1e9ff4d090215f88d9af53bbf57282d31a835a8a052dbb19b5c0b366b451cda1, + 0x26ff7979c38be718b092842e02cf124d1cec12b426a5ed8351b832385ddee404, + 0x62eed7ae94588f149905a7d148f763c8422e7e0b6bf5cf5ceaf80f7a0754fc3, + 0x2ddcb93912364f750150441743c32dfca87fba3bcfd285a5cdd854cc312a6d7f, + 0x1a61c812aa97e5dc63b827db3b987d759738826488abecce0592af6e7281336d, + 0xaf260c0175dc1188ad11222368b122a1f0cb5f71d5df47517f2190748f803ce, + 0x6c547f8d368f03ec5aa00693a85d2b4cc56aad88006aca1e46b1eabb84a5d54, + 0x15a040ea72ef3252816f453da8dc97a9b417011e9a65b0a8606248591e597199, + 0x2e0ae86bd039654fcbf8795450a36958139b3e0941b98778395b8ecbf3b40e84, + 0x71936ae5ec7e0ec777485d9400a8c414ce233e07352a9ce683ae41943341c9a, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0x1fc8ace75c85e6d3a7404fe02b03139b6a67dcfe2d14f7af11cc30a2a8ece33, + 0x263815b2a80b71e1222801ac39bd44faf23d0e21d2f31fd213d300689a720d8d, + 0x1a91fe38ad898189e9dd7ef77559185a79d80481808f4044daafed03742d3ff7, + 0xb99a6192c5bbf619624d1c7cc7d90930f1ffb79a6d4cd145bdb58a85f35e324, + 0x29df5b722979b8c9c63743c5d997b720d1f938edefd5a7359651bdce60c352fa, + 0xeeffa5c228914c03da9a2eb5fc92f23254bcde82c459c81266223e6fcd3d89c, + 0x2b3647ce374ceafb0ee9c4f5ed4762db7240d45a5b01f3873f2a4c8b86a68be5, + 0x21e2872db7718e97286c2239b5b721a58d89ca37d43dde81d5cf049477dd1c74, + 0x173909ac99ccc3ecd1ab2fb89246a648ae3abbe251ce9c0160bca5712c0626ad, + 0x2e2fd250ad31b0f543e958e16c10b3cc9e62e52c1a40ec5ebab4061d3880dd32, + 0x2dc7cd826f2f2b963a180b5a0fb1b5d20d4a7cbc860679267142a707c6ba48d7, + 0xcdf628de6b0bc2b35d3f9a0b2cac4cad27e7e1966c39af983d63e1461592bf0, + 0x2bf2f603e91d6eeeb104ac9141798accd525fa3e241b1182753d4ff3f59b1630, + 0x49c9676b595755be2f328863936312442c1c07504c5bfecd793e1eba7c3f675, + 0xd1fd4d6ff542b060b3b90ecbb825f0f890820144be4bd0334a2eaf8339c9af0, + 0x2206a93fd04efa7e79130c0aac582fa50c5ca7dad614331281c3d49ee4c1c67f, + 0x1b8b1f32ab840765cb6250f4c9c019d994fa5858c67bd585a5f4a7663143ecb0, + 0x55cbd5d71b787fb96fab44c8c6a1eaf3aea505c675c32f608ae0b6ae2e71319, + 0x24a63962fa639928e90311ce846f99b35213568b65cc1db5fa65555a0141ea9d, + 0x2d41835ec9c8dc848bf62b784a9d029cf7632369d3b6e9f6877c671495831bc6, + 0x1c3ebf1cde47404db2c523c680ea3df60668ad37b67fe50298c632b77bd3f625, + 0x4d92032856d1eb29140d9825a6cffcccf00f5fea91b85aaeb68d47391a67f46, + 0x13fd59cdc2da8766343e9dc78d0604c7a453c4a4639f1e1f66b154605dd00cd4, + 0x2d56a2d39a3db620d7b172bd74553d09cfada80fe7b1f2bef3fc4cc115f76123, + 0xe8cfc663445dc81cd06b084d36c85d946c6eb49871add263ce14f2b477ad27f, + 0x2233e0d00be5b7a77da192a5fdd91db5f196705ea0754e4bd1db5a357b335092, + 0x153dcc887f5dca8999d51ae06fdda165dc03e01c67bd8790316bc465ec4b961b, + 0x1e3ea34066a170114f0c76573452033360809012bb9ae4c24b6c1fb476d5d5d5, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0x6662bced08b16d3d3a50c9dbca0743d66c2b0d5060c68983d8448ba7e09735d, + 0x207357fa70e47358e4df94e0fe2860bb2ade565460c2f2ac9968718b512fd761, + 0xd88b7243e4ba947985ab06738bfdbcd72be75c0539fc2c65e016612cf48a0a8, + 0x29032f478c7b5fb111f8d32720abc1fa050676c58f783bb6740b5876211527d9, + 0x1f58b00a5be5baf9e1da120d8dbc12a767e304eb63c0c05528efad2b95f6d010, + 0x5645d027e203626b8a8c15707cad7f9954b915bdf620a343812470c63d6fd5, + 0xab572420dfe8794515a8ff4fe71b0838d46a42e63b488bdbef2c6721668758d, + 0x1876c13f9de5d341e254b3d2c4bc8c272e270b58c863ffb16324a178986dd709, + 0x21ff416c00f6e478e470f77aead4decff3ab847e058e66bb56b1c75379d67d55, + 0x104056d5d775740ba150f6807d251607c5072fcb6d204b3a92646b76f97db4eb, + 0x2859bc2f280545367b3844134b23d2fb6ca07c51c42eec18800cfc795464ffd0, + 0x232f777c06ca70171d09129c01814b57a685224a3a752deefde04487f731dc54, + 0x2cab0c414d906b4cdd83f08fcd68d3b3554fda8f17967c89d0b281f9e6e8085b, + 0x291dc030472a4633fe37225419e9e26ab406b12c6c78b40bb17a9ed3af85841c, + 0x11b3be92352e34d0894a108302d097e94aede2b931b40b162b6792f127d0dd51, + 0x1821450cf9950eb2f0ca14ee17385735c0c0f6b58ecfb4c341732c580e15289a, + 0x2c7185a2965a3dfe86d2f88a14e66ff3cde5f1a4072fdc5e903a5367012d6bc8, + 0x19f8b88431be608148ecc8a862b043c66277c6d244d4bc9b063488d470f91c57, + 0x2e07597ce199e34f1a907e135ef8c7f1d43ae46459065f5ef56dbfada7b14086, + 0x20dd50883de922f31411aa269a38a809f86ae985da0dd572a02b0a115e57317d, + 0x1deb58e4db0e059b5e4233a27f3ebfd5c56fb7c8a2e0952870ff89bd985b7fb8, + 0x772b8311e52b960baba8f9ccb8d74d520f5653608ba810243854ca306e9c5ac, + 0x26508ad8ff73d70862d1ec04e406f165c53c04a0c3e466a11a2456656a2008a8, + 0x2e03dc18ddda2eea605f357d82c0a7a9e05f74d078d0d940a0e7506dd7dbb2b7, + 0x2651122e5715b7d5d0d396b8b0a6b3b219e1b5c95a0532623d9976330dc0c7a2, + 0x1d2fa1a7f55da05e2e77eb2c7ce09b4f4c0f832722262e7e57108223bf2e4a75, + 0x20991d3f8eb785ca08fbf1695aa09c0664465858de5f63e628cfd6dff4dfa7d5, + 0x2ae4c4986606935874c81b044f450a6ad91c1c6aba4670091cf83dd34d8bdd45, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0x22d5dcb58b751b33e61941e034ec6a5da20162b44a67f2f2c2a32fb2bb19efc0, + 0x18a2197cf988fa8737f9ea1f8f7cf8e1b3da3a130177b80c47efb5fe8ab3ba89, + 0x56472b01f8796af3bb76fc84acbda7f174f54c3129f03f6b36d80375bef622d, + 0x28a91c2f74f72ecbe75a6fec418b9ff6bf08c731ca114d6609478e2a498f947c, + 0xecd04c63ed1ee68ae94d51633155868402dac39e3c8383e8f0d45ffdd1daef, + 0x2865c65b845d8061dcebbc8f2e91762a9af0a69c4d7692d60e3dfe98400a40d9, + 0x2f50ae99cf9753fc9a1344a654574dd7d4bec32df7d1d4b1cb4d03dd1f7319b, + 0x26b34e635792eeb315bf2e03ecfb8b00f7b6bfc137e759436fd0e5285fa5e8fc, + 0x26cb59e555d2111646327f7ec9cafb3fb4344b894d7746069794c491f71b5f82, + 0x165c43eda77147c1408da412d24ac1314a327a371d2f6c0e3dc2c7e956e96046, + 0x172edd07fa59daaeb04cc4a4c783027401ed8b47fc6fbdfce05543136805e1b2, + 0x2bc36f035f7bceca4001545d9fd98b0f2eae858e5c4b0f0e219121591762b378, + 0x22d96b2e558884ca077f0fa9c41a38155875af1e91f5e69dded36499c5786cd7, + 0xf1146e591fc72056c2fa40a35b202e6ae29a5e6d91180713ccf8ebdaeedb917, + 0x29510d1143600cbda4f235f0c6c480f436e20daadaf9461a032204de009d6fb4, + 0x1dbad14882314499c14316375e9b8888be4351bdf3b96e2651125fd03ca89a29, + 0x19d651b0c567b6507eb6a7202081fb6311e8398a80d53195a5b327b7e5810427, + 0x196d972248e180296caa0f943f4a034746a000205310b155fd0071bf6a20341d, + 0x2e823807f3a2c2db81181bf7761447252307c8c7e088f9a470c257ad83a1fad4, + 0xae07a00e65e68f06fb34219cf2f0b819ea6bf147168ab5f982c9513a661e10c, + 0x1f3ffa4e4b5ac02fa89072fbfa10d169ff5cf382ed54a86b69fe5ec3b025c3d4, + 0x94323f9b77a979d42a49cb1fd0f4a5ea253e908b0e96f47a308e44085f0bb51, + 0x7568c62660c919b4295dae1e761a5e9bd1ddbd05f77de4977e99ea46ebddc59, + 0x1d28e05e1aee78e0a9c10c97e01193eb1771c3dc84ac0af0b7e9b7a5df35937f, + 0x1479d6a6a967e7a7672a01c2c541bb92b677308c3e365b73349327f39f4593e8, + 0x6872919996f740aa2559418c0da042d15ccbba1cda06c95daef9f0ddde4a6b, + 0x587b0974583ba3b84934a500bd726018b08125f5f007d01856fb2c124e00e4c, + 0x2ee0bbcaf6798f8cc107dc4ec3157dfcaec549f36a87c934a83f1c080035adef, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0x76373d256d68ccdb201590f87f661a13d618407140b6ec21bfcffb267e0dad0, + 0x13a5be09677fa0af3fb23e95428b7cf9e7b8276baebb1a39b87a1bdc416b270f, + 0x227a7259c3b2135612d12638b5ca5973ab9d6aa6d6a335781d81821fa8be02c9, + 0x25d96493ac371c2ba8dcdc9bf29b1b512f43aaf38fcc86f17e9d44d59d870cdf, + 0x1ec1120411deede740e7e3481b96ce1492b47232b208f15afb2127b41189afed, + 0x12067c9f5be28c0974e55e19274c65f752c82287637ffc5104b35799362b0f0, + 0x462ea3958f9c42d0b2406bec8e38576c88d964597ae61f1f07d811873c464db, + 0x20450babc7a6e637d32d8b57f218412a430fe087706d88eac441d6871f5d639f, + 0xb29f887572517d826f977c371341f2819995e65a2929c078cf4a937dc68558b, + 0x27d93349e2cac8325e4006aceccfb9ab165aca3895697e42e23b78bb1f172a54, + 0x1969ee0572799902a937545397b4fecbb83446841ce8525b714d765fb25d9028, + 0x1edebdf580772f616131435b17c46e0e385b3ab83494207efb4d9a32f4667bdb, + 0x430dc17c3f1957758e57ca93c94c5623073e5580c28cabafa400c2e5eba5fda, + 0x1dfdc9b2152615a4dcc8b252f17d97b8998543e84b9b8cedf8d683d917186b64, + 0x48a9afbd6c11ff4a680204e895b655e004211e495f2bc46dffec598bf40ce49, + 0x2511be820087db2191a273650de721dbf7abd3ce15bc9e95e2a7153443ca7fe9, + 0x1b255c37973fada56a1251fe07d617ce802b4ec2f60a002e1fdd9052090d3884, + 0x5c36fe03574074a04ceecbbcf02d231d9d868aae698b20582aa556e6ee34bc2, + 0x14071daf49fe401a508085071812c378491178f66712eee8f1cd7f611f8632b0, + 0x1e8a45f66dae3bf77aced336508d0b566ef1aa9d582d9a44b9028d2e1a5c28a2, + 0x3470d55418841efb8777bb16984dc9d71ca55b601c6a9acbcc06dd8a3a4e4b1, + 0x194cd0a75e5edf346e694e78b831d42070d93b69555b692da6fb979a78afce0b, + 0x22d1fd9d50ef28dfab1c35553601cebb2dffe723e366e956a2d9f2001517b92b, + 0x64a916906b28a8a1a2df80019b67d7e40dc686d00333fcacd63ccf129d1e281, + 0xcadf1f120a7ba6a73fb4f5980c5aba2e0e44280b5c9478f5d800e61fc39c824, + 0x11783cca91ae0cd06b91cacd517e51d4f2e7fb59202993dafde30ee181115b17, + 0x1563d52bb66c227361975dcdfcfd8f6bb9749f86297a5bd3a6be74b8d5bd2bc1, + 0x2e3cf2cbb16d4b6a76f171d80a9b92c4b8324721e6c3a29b77e2c9727863314, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0x106cd44586872a1e98d029a76a334797c6950fb72f241e344040ec5d1e766ebf, + 0x267c81eebd4f9bec2d7fb13ae6ab345774192825ec38779a8883265df4b743b2, + 0x5cde6fbc024c52d0dd9c940b9450547804aa6aae2bf06ab7bb2c3946fb09aa7, + 0x1db696f29132c9a065e392e606d3bb4110213b88b7125ca0157a776212418837, + 0x269b78b6fb577d3a5463b0b88bfa91ad56c1f7768b55a6908120ebadf7faabfb, + 0x1e32a4b9639edbd369aeb322109c919476aa85e28c2b7a8a111f9cd906bdfb31, + 0x2387b1982e0083a0621b4305c2faf4aaa0abd33dc265069e9b1d59673f5b1816, + 0x16f2a181e0d79d0a39169a1c9389d0b67e50fc5ecd2598d2d875ccbafc659ade, + 0x1c418ee3dafe2d97e5b84ecd7625b8598c7323e4beaa809d77cd7a3ab52f5c57, + 0x235d1dab5f72d1b0c0cad82e5f46ae1972117eba7612ae0581ab85d4dd9b77de, + 0x11eeabcb505206e74ddf6a4417f4d6c302d843dad5e5c1e536004e100f729c4, + 0x14b4f6ffdc590f859a491af89cdcff26ec963551676e4e109f333c34a0b3eca3, + 0xea3a8bd722b025559ae438ef85f1fa8364cebc831084a3129b7498fc7067aca, + 0x26a63daf3c27700bc4e5a0c13c12a234e8a13dab66deb6ff2a8b805b107a4518, + 0xdd28ac1c88f9959311bc53387840e131726a6ab9b7fdba12f403a3095034ae7, + 0x1221db6f8687604bd35fd586e0944a36880fdd1d1da2b771fc06bc80480d89ba, + 0x5dfb8aad4d6b89619e41ed02e593f0de05dde06b6aeeb1ee8b89bafb087234c, + 0x10ba8b3d427fe867422065e1b2a8e0d06d567e73717deaec3438fe36b1bddd55, + 0x13cc217fbf1b60972234be03ee877b96d287e30fb869bf816662d2887d2dc68d, + 0x1031f3acc4288235e55b67f3435fb1915cba9ce0d0d1f12e0e602e2d605497c5, + 0x18ebdc6dd67f2d5853541af16af792756aee1dd1132d3a6b1d0734db793a46db, + 0x10a4bdea8bf3a0440f456c507069645ab3738171f896cfe3b5890c9a0abebc0c, + 0x21e5b46f2b85977f8e4c67f37c30ddf03556eb1b56d8339f046a7d1aa8d9bbc2, + 0xa8735e02e11c8a1e0a56b24ebe7a39223e2beccae352597972fadd8f4fd3abb, + 0x27d5d5655c3a948d91278714a40fab8da89ca600e748a238014c98b932609fb2, + 0x18b4b6e0794cf364c6d4b5fb44a2899d4ab038d6b15ed634c6c12accead7e73d, + 0x1b89b8c9a5250e9edb3b9fff6e54be5b8c173bfbecb8eef3847d8718de0fe29, + 0x27a5ddf99d9c4cdc9643219a9cd3e4f47f63a581af9a499f8e064f4d2c726a01, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0x237b081a68e30cacc4213ba3d2b153672483ed173125bad4014448763d2dfcea, + 0x29af4e6cae10dd99b672d741c5034f91762b99be844b0a938e967009578e6ccb, + 0x91bd6b2497eaa902ae05480699f34734c7f74b073af6c4c559bfa3a33d4e6e8, + 0x2f7f9c0d61cb36e331f2780b0edda03598067caaf184dfe95613950f8700360d, + 0x244d6e7fa5583e36d41ab75c679191497f27583a7ea7f5cb4e87feacf2b4dece, + 0x1f174e5f54c883afb9ae5b7e955380190767072e59db3a1e1b90d7035521359f, + 0x97f23268924c4ccf4659499274ee72a1a9c83e43178454d49d675f4e5b27150, + 0x3d2ab62fef78fb69b7049c41e34e6f1870662b336afbd1518ba776218600fec, + 0x2718711c73da1e256d1b5c21c6b2e5e43e2b0039e86f78fe5790e04b3c7938a6, + 0xd396383655c27ca25603d88e3d35c3dc6334506a93d6909745e52aa7854bd4e, + 0x1c66fd746293e23154ab298c3e4ca0ca14980c6a0a3cbac979d4ed8fdb9f692e, + 0x15708a52c8abdc860d066e0ab2a6b5b5cabdf1301f676b07feaf5342a971caeb, + 0x2b821cfd139e0da4c55cfbd8b67a7d7a4e7bf5e3ce1932b96f6701fd39e926d4, + 0xaafbee598eca5624a31b7f40b836023f364d41b6b24d0d7832eb180a60885e2, + 0x15c92eb4730eb68b229bb67da73fff3ca720814450162a81d1a7a56c83c3fc7, + 0x2f7200c5afe273cc787b0add86e9e0380db97cba269f59d0fd264b9ef144e839, + 0x2eac5180790ad9bb069b4f7e1842ae9fb0b069216c9b412da6094e2a69572126, + 0x1b7a0422eaf807c0c824c511a7b52be353c2a3789591deba9bca9a99e4d92869, + 0x1662fa1c78a1621b5bbded5e9e5880a86aee481fbc455b3849d16a37cdeda515, + 0x28972f5963c0ae4ab2b03cb80b4ae1f1dbd905fdc3c657550648bfefc4c719cf, + 0x2424d119a1299933b209b85d4af1aa89f8523801efeeebbfcf49c1b6f95ac740, + 0x262a05cbc85dc177e174047c94905083a27b4d887f8050c1b98a07608ac8e373, + 0x89d1b0af58744cdb06e1c0636306751f6b6ede06527eba770eabb7195465a93, + 0x26d8b08764b7240789d927ad67270da8521ffd23995b67f3b25de7fc60f033c0, + 0x19c594f452b69d9aba24aea1f48887b5b2bd351e7bc6984e56c346264e5c5f28, + 0x9a984983ac12405239b7d71d7e94ab74a5d7e23b3e651f61988e258147f5a61, + 0x2edfe7a5c13ee6fcf27ca3a98d230c3158dc1eab9a12a734e78e69d7bcc5ddc7, + 0x190ac6e66fc0244544a3780ae6c5a0d6e56894965b345a1b731cd96c89defed1, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0x24888d5352a17beac4d1196b9ba56563192a21650b6e8cf734abbb5dc6fe0b86, + 0x27f1a77d912fc4ffeb051b44845cdca1360b3dff10f646cf4e2e31b0b52706ea, + 0x281d4a45a8beb80c2974562cc98785b37551ca4258c7b7292006e387b20d5f49, + 0x1d06a2f6b95d207416e97b18e0a33aa504251bd5473313ec4ba4aebdbcac8dec, + 0x11dc2b5aac6c6b58904b8370d622f408d4b8a22a54a59f060a9336509285500f, + 0xf03457b87c6491c043633bb8f90a9dba8eef6067f86926dc4df4a6145b9cc81, + 0x17982901cf92be1b7f477e61747a5450b97ddfe41bb5d7760bd1c25df17eb204, + 0x848af60d2939b3983df6d9fe56343916aa046933c4517a6c0c29025a3da1781, + 0x1dab170558f1782df01501d1a810d1f491caf3a03a5563c8638eb6649d852272, + 0x17c31798bf48cc0a63986b914236ba21a04dd2a2bda0afcf15213df56c46370a, + 0x2ebd4bfb0ae3e1f540f31fd15a70e59de4ab8ffacd899d56060ba394e224ccf7, + 0x16c3ea32466b179ebe57bcbbe97e3a7f94b0a4b3e091f15e3aaa9222e8b182f2, + 0x157740e3058872c28ca7331055f3daf8b9aeb36e9c2d7d231f22171c6315733e, + 0x6a974a75d941a54412814d68e6955b7f4da2b281f2a9ac426afe81b98ec27eb, + 0xfa950037d21d72090c5bdcb8bb6be911ff4a359f3e76ec625c64f1202bab37, + 0x19065585b553aa2649a420625c707e61f7e0e70c753dadf474bda8fba0354fd, + 0x183bb2b9d85c3a9368017cd1e1cd884967c0b048dc243f35b6813af5b279872a, + 0x271a9d19b99115dff27a86779104a54b252373c18105cf5f86ab5ffcb2a9942e, + 0x284fd24cc3cb45ca644f15228d786fb82cbbf3d66f1a276ccc3a1182af4fc1bc, + 0xe62b392dc27b2b80a868a9501c9e1c72410bffa12b77732ce1df084ed0a7a30, + 0x265311e1422fc3e5cecb4158eba0b249404842b16e8954bab3d80d6805fc4f65, + 0x1186e446615d83a940d96d2286d9b411b62697864531172f5e8d3d9ab6a5f9c9, + 0xa22515b9c7fdeadf64fb896271bd8d96f1f53bdb32ddd9be7cb22400d69ab77, + 0x1343f2ea91b46be725baaf77a092d6b790c1429ba87a3d4105e005b85c901551, + 0x2a58da207ab04101d89a09c69f8d8309d8e8a938deddff70e2eea30f4c884bf7, + 0x1bddc742015df54718d5a89b181f3a0110732b0ab1e014f63202f6d9eca2eabf, + 0x301144f5830574650e6093a4b75b9a34b59066777ed21d2c008f2636177e9b61, + 0x1ef4af22668248890aa7ad05b07462d777b0f09a98d8c17d59ed2a127fd2c55a, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0x25b20abb9883f59516afd1b89f80c4b18be2270c4ad70f7f9f9b9188c9809ed9, + 0x27c5f600e46a854a26efc7ede1108cef8b607dcfa047c259ec32934669c1d155, + 0x1fcb1b54e79f2f06aaee7955186d71564101088f13837f11bf2ceaf9393619e1, + 0x1d24da31bcb08eb64df9e69b729ab135cf1b63cb23c4c8acc073a9d50f33bb79, + 0x21c0a2bf8c0ea05f8f319e57408ec4ca46f0003325efdeb8c84b23026d9a8952, + 0x1931ad5d7ab126465234d8fa1905de0f77eb5858758e6c838d748f23508ac1df, + 0x17af6e15929f2bca918d404d56b4cee0ccd8969195f2f3edfe56dbd1937baedd, + 0x36b2cc2645cfadcea80c47cab8cdf6eba7fb8fb2bbad631a5cf24fce6966854, + 0xf10bbaf98e0b1ce2cca1977ba2e271b89cf46933d4c7a797671c8fb0754e10d, + 0x1ae0f9bb7b72a3239de677048151e6dc40637e6559d726158debfe779a72a708, + 0x1912fe07ee7840b055e68317eded61b0283418138b9fa2fee286fb999da2e6e8, + 0x24a8a1af47ef25f18b39b5caa36c1a6df571d3c833fc1c54fbedad560aa5571d, + 0x2d3f665ea69116d266057ea4e9ef5225800a1cb2ec6b7d6ba9f3edbbfe1faced, + 0x2c5b2cabc24bdcc0e95d2e54c52c0fd0ceeea439d8fa83c0036feee0e9730e3f, + 0x1a79348c882afaa9480c28acb01547d816148bfb8e70f22a0ad3a3f534bc0452, + 0x3942e232a30d4a941a32ab45958ac49b08b0a8a416ff6dec7edf4f0dd16b8ff, + 0x24de94fdc7fa872eef8ac471ba7719d5f3f534cd988248c154ee122ec2090ec1, + 0x13af3a6a5530327a659e6bdb0e3f2643db75dc7e9eb06a5c139d84a2888aefa7, + 0xfff230d63a7ea1823e5c5eb49fadbb46522853f0d6eee45948d326f54571ead, + 0x1f67b3c311ad5eee7495b1e9ac1236f8acdd8dbbf5b20aded3c3947baa0d7fc4, + 0x5be06d2aaece5cdeb721c87ce053e8523c8992c91a1884edcdd72b96e8e448b, + 0xf3b86d20e5d8b37d9c47c0a1e0e5654edd5bf9fc4202959848cc3951f58971d, + 0x28047bfb585f17ad6e7cde5bc033d8072f3b3e90d63b884df2ea6f3a24d10603, + 0x1186aea12da52c270bcaf4bd0f87943cf5cd9ddb63bbbb2d7f34dd184baeeed, + 0x1e4d65e0bac14ec3fc7970af0d64f4ca9b932012dbee59b3a93ee42b8e52e06c, + 0x265d09835a19ac5c29f4327b9df3f35988ca8893c1ca8813a1f92b555550aa0d, + 0x255b843c053e9dd9b00d06db176106b632b4ef0e6e345ed96775e4ae313dae6d, + 0x1cdbf2d9c9e1f4099652361d830c6d691ec5eb951ae3164acd715f49aae612a2, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0x26cd056174dc2477de6fde6a95b7805ed343877ab35f7bd16afceaa9771fad20, + 0x286c63dc377caf0ca4697164bddfd29a79aec07b52ebe4fff1a4601bf3178ef6, + 0x4404a2d97266886b3a00244a049d2232727c70f864afa44d11a2d37ba4179b1, + 0x2d7b33ced5c2aff1ad6b4ccd8482024effb1dfdbfa20ceb1f2d59aed40da523c, + 0x1a5a78c756a7ee0cce31b132cf6752a1fa0e904e2d6dd9ab3818fbe9426d24ef, + 0x26634b7dd87a8c0e9878b1383582b9a3bf658dd13c467e52804ebdb1698044d1, + 0x2222ed015dbbe37bc2578814782740abfa00c4118dcadc8e6a656587aa25bec5, + 0x243a463d1befd0cce1a46b772f3d11351d47cdd86ff8e0a6e6b8d0f8c7486da8, + 0xf4a9dd0ccf52f31360db5fedcde0405406d4ce2042b1856c7c14bac187ad37d, + 0x25c6e507371aba88824acd8974ec363c21ddd450a13b130f38eacd5dbc5e8c74, + 0x864d7ea740ee93ec7d2ffeb7adf4a03174c89904d9c33a683d8897eaba353a2, + 0x146cae6d1bdb0318058f424e893e0892b0a1070de370a5f460444ad2e535a920, + 0x1ebcd64df7ad6f0e1619e26eecdfe6e2ff1e69210578cdc6c052e1451e9c17c4, + 0x1a7f76a8b9a868b7abf0bbf29992d82728ad277aa0c48d2db00ab45c7a77bfc2, + 0x32b7050fdbd512fdcbc9e9f530c139f120df1b53f26240c01dfa397e227d62a, + 0x118e701ff219612ffe9524bfa2e515bbe11f2fd581a4371f18d7f45f64c7aba2, + 0xae4dd0aa671c0a3dd08f394fc0eda68ab2beeeb58c6c94e60229145f0869468, + 0x187cd95af561e161bc1a2954e04a82488721c80e7b970b51a11e318b43e3c340, + 0x13c74e83abff731872630e45384b122ed9fd07176f336d1c3e3b87837adc1c39, + 0x30392808edc88e0c24a9f0f4a384e3bfdbb65382fba12b4e7ae01b712b5073e1, + 0x1bb68781b9f841dcca210b93a99320760e7f3ac43b4ed9d621fb50ebc3440467, + 0x514eeca7cd002d04a4716478bf62c108b3f314a288be687fcba7c6d5103ed5f, + 0x1a4c1caa217b647d099e3c3de03d9677dc2398277856140804f95848275cb05a, + 0x1959d1f1414c9a59879e9489315264b7691dacd96ad16f890ebb2ec8c55f40a7, + 0x2c0e761217503c6c0b20014558eb78e6314e607130844c97ee67dbe1940b3d4d, + 0x248c9aa70622ffe24240bff18d191276417eff7762d96594e4fdb9d6803b9609, + 0x21dba9d46e89f5875fd5e925eeffd10ddfc09ac71634e69c61e9805bd0a07d1d, + 0x21280806713dc524e7eb2c697ee2e197d89bd2e73f1817609be21c35dd5bdd5a, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0x3cd1743a3de44e9a172804c7b159ec17a83d2ad838f9a51f5497bb5aefe9666, + 0x64682ebaf66d718813a4d06db5e8bdf665dc8654df4af96578526fd7eff644c, + 0x27bdca50a989caa4dcad2f45d2bfa7e6d455549753fb3e8c4c3ff2553803b024, + 0x263a2119f3bf5d5330c11f3036d2521e40f391da9efb1879bf1af39f5f4dff0c, + 0x2df2f13f954b1a7cb58e84ca4f3e2ab7d0f4272b559e58c7dce7ef229213c5bf, + 0x2ac40d567d483e8d671c8e194075fdb2ddf9ec51a174219e8c351dce02d32d52, + 0x159b9154fbbcadc7209c9978cf5783aa8a47cba1a729bb297182aa674f7fd820, + 0x1a2295de4f8dc401aaa4a2b1a83d62fdb4828ced253dacc132ec9d5186e1e2c7, + 0x2404bbdf4995ad241cba1169ca4d85d5ad276ca9d009081ee3e2b5181d46d29c, + 0x6fd221e32b98c2db6dc1602ead395001edced38761cf45ebbbc340ea35cd7e1, + 0xaf3118afd7dcf599b5c65b5a3e74a8ed04faa2791f47cd2cce3a31e541032, + 0x2b2dd6d065365f0b808bee0a2f7ec63eacb1990cc04608b08549d65024113ad7, + 0x180941c6fd6e1dc8a0aa4fd86020ddc4928884b68074c8d78e52764aba6c9f9a, + 0xb86cb785671c76300f9e6d4dd23b53aeb9e2d5b6d209f966986aca09ec59801, + 0xae841f0d25bfbd009e0011201b47e2042ea8d961248d90ef9d44a360b317617, + 0x1b2f66bcbdb6fc59dda5f34ee11c654d0f2dec29e31928d5b111393c8e0f943f, + 0x2f16b66d80614604ae85a13440d46bba9d09d98d5161c878be67a0dedabe3aff, + 0x196328adca8167c649b987ae985e9e54c0822077188b8af34b3c518dc21416af, + 0x107664f2d3f3bc3ed01013faec284477785f08e9932b4226945efca7fcf56b85, + 0x2fc54bc47cdc7f7146f9b81462c64093374c71647d4ca27439406ae6e6f7cca9, + 0x8779b3359720a0f3e0898942f611aeae102f875627f2c973c97356554911cc9, + 0x2e30be5c5cb07090ca3249386926194684d1f3d2d3ddc114bae2bca9d4a07f9c, + 0x1ea45a4f0b12b578b58600b9d085aa8d9c68a583cea665805b9389f8563d53aa, + 0x1753a308b286260ee6ec2934cbd59f0f211c11647cbf22f6bf5fa7c154c0f577, + 0x102ffeb8a2a94fcde9001e08ab603aa8975edc2465d6de14b73c14df40d61db9, + 0x1ae8a9e95ee69c8774f8d3a8ff484788ab272d3d174f526a107b2c8ac34ecd95, + 0x166b84b5e6975b9e8d7ffcb7be641fd89c53d1b7238748e85f32084ddaa3aabf, + 0x2b2e47acd6445423d9e61e96965da98e206b611f52af1d13becb4ce4966e1a3a, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0x10e7554983562b62de4660b318bcd5324003e95edc617d6b1c23a97b93802e4, + 0x187483dca9aca475f85b9f8cbd78aa6048bd2c848caf3973c8feb07573883a99, + 0x2c13309dec41b4df5d8fdda2b063e8264c35442bb120e28de7555569ee771f8, + 0x11710271c6783060aecd410a60cc5c96641c1cb26591b21632914aa9fd94eaa2, + 0x12bbd77d7be4e06b77b5c40e1f9888054041bdf4f8af2c5378e6386337716b6b, + 0x23ee2c9a0d3324166028728c80d60cf0e21a7bd9ee90817058ad3b87c6f28cc9, + 0x58dd3f4009e8ac3fa07e285bbd7391c2dea81930c732c3a769c9c9249084d71, + 0x128d27c4805d2365d84c754621ca2d1a82297ea43dbeda87c0baef506c851079, + 0x20f552e4cc3a62cc2f3eb768b69d8549ef4c24d2887d7de0550b17ab4f7b436d, + 0x235730472fedbab358bc7dcf25b1d0befcc70746de99e78a6dfec8f626c5a9f8, + 0x280c2ed868aeacb6be7c9e773b08c56f43ea871c01acfdf9ff5ce9d4443d3376, + 0x1bc74fb92afe9db8c0da68365326cd9944db988b65f46d032989326fd901e923, + 0x2d9c89c56578fa5031afd1a53d21212f1c3ef24cf7076460ff533ede5fc360, + 0x1e2413f3b8f23a2304735feb3fde9d2d0f88d8aa72c1c60eac921588bfaf69cf, + 0x53a4cbf4b57d882174b8891d918af78b40a7caf832c2e2af02b8ba5bf5c1cde, + 0x5e736b9e5f8a1b93fe3aef1ee0a69234f7fe62ea998a9f2559f650669d76dbd, + 0x1e88d8b3d140ec659d6cb33736a0254e178fc6c0c37d2fa5b36ae4a85b28b5a5, + 0x257237c9ee699f5d79a62f2647a3b51c8362759cd955f10872346ab3b401b04a, + 0x2b6d25849d6b81e36cd329d20ee973c15cd9b62921e27acff048e7589ddf7739, + 0x1ac7317e2e5e3011420558ffa430fcab50b2f3fb778311bb25b1019c88ced146, + 0xf3223d7e88918a33250b61acdffacf1965a5ba9807a23cef7c89c837afe5b93, + 0x1f733faa9efa2db68363757b1a50f443fe9bd4e3b8639f21f1e12ac25ef00b79, + 0x8e2e6b13aa7a352b8c33d0f52939c16819e6a92f7159986588a09e2196efa3f, + 0x208995a721ababfb4d527db0b69d35d50e263bb1c7d97b24ac52c2b316b58727, + 0x1f91d022a78f70863204042dde629c18af85757bcf4863b3eb916a8af132ba1e, + 0x63a2f4c8d518fa72d9ab87e414eb7ccae4ed3ecb6d24fb734d68b43a92e8cb0, + 0x2915c64a0bf35200cca5779c140c7f9e888ce72b9c458a9ade0f0108eb2ccf5a, + 0x17a2028a54a30e4e0eded3f7d8681d6dddfadf26ef5c43cbd1952e584ad5b0af, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0x2aa225f58d57ec9fcb1d6a6711daed13537cc6db5dbc485b21a8c4b13ee4ef5, + 0x2a9a824715fb8db1d5d27fe975f011320887f593d36d6ca7e2be7cc305eabbd4, + 0x9bc4b62c4e071e43c1e20d96810ff912dab86a98b4870d66af75d10ab6578b, + 0x2d7d326fb2cd64b543ef4afc9d2969abdd53042e6038cf53f12d36ba07c21807, + 0x1e66dbd30fe311dac75382ed3843cfd75e560bf2634f4213a0d37be91c269cbc, + 0xa6115e876e097c8651c2370fc0c0a79d4f67199cbca00b3c69891c56dc81cc7, + 0x2b4cd16c063e8d125a334909b5f9271bef61a5e6fcd117405e24b7a8d505453b, + 0x19734eda61ff0dc7c62643d71daeb291cd8f18e1083f82a73ff05e5f8be31906, + 0xf44441cb1795b60b9a424df927fb54b55a53c75a98eb90708fea4b42da18eed, + 0x1e0b6f3e7526e310b7b870cccf69b9d716929e7b1f078652588617ea0b71feb9, + 0x1abfb56c8889d36a1cea7d9658016c9ff5418745bc418d8134eb44e3700d56b7, + 0x450b96e26195e4290a1e94d896daa601b0bdf44651b8575602ffea487fb536c, + 0x75d3fba1c1f0b0869714cc5b4e54a019e13c5a9b745bf38139f2b0f09c93231, + 0x22a1e5663700b7b7af22ac5604b120c3ab73294147889f73b3c986a036fdd5c2, + 0xef19ddef71117af6afddfcb5ba454602d35ebb7497d65ee1e7805dd61d807c0, + 0x293a52d85a881e3845f02993f54c6af700f6344def2da90a2dc13a714760e224, + 0x10f47c70823694adb395246c750745eda7fb57dddf5f6e71ce1a41c2e9839cf7, + 0x5b7b0f8a9586e0ecb9df50b8450b577fa537c94ab7b770ccd883184ae2718d, + 0x2694639d8fd48e40ba301e56097cb270ca1e4a6d0cb5b09933142aefd1c44efa, + 0x2b40678245e68225c4c9d8f78d2e660c5e7fcbac631d1299b1a78df3b283b195, + 0x88322cb02937145ffa566b2f0256d5c8dda53b85ff611a658f4de8aa9ca5672, + 0xf5f45c91500d38fe1acc462a8622298c1a6f53c735abf1d4a971d3d9fd10cd4, + 0x17af880583031ee7067fec80f5b3760f9e19dbbde06343e59591da9080b8dbfb, + 0x1248c5b2d3ebd0f2870307d965eda53ef7d83392cf601d95da0eb124b05c35f6, + 0x286b506a8883d6f29ebff1bcde7429156792da00142bb1292f378d0f8962a158, + 0x2fcf9e1e6970e8b883f8f72bb1c48c53541fbf72f7b43ee9f3273f9102b5548b, + 0x17f7f929e38a4357770f905e9cc5ff7e287e043d06054c78d44097a446174e7b, + 0x8326d0c8a128c073a72c7d722a129fa450fd429856732886fbda3ef61606bf5, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0x244fd94ac9d2b6a02aec10be6bdfde0707d8a95440b04a34feec4eac0a881823, + 0x18f0be2e75ec1ac912920d0403ccfce0ae11a66068ed5e7f0e60146c1eb78757, + 0x67d513ea87808ec1cf7f5880f13c4ff07cb83b06a442573c2e74a679363edb8, + 0x2fad3ebee463c805024a9884e2212288d97d343a199eb1ed449d7f0cf21fb86d, + 0x29e2c3e0e04f7685d1e2cd797de07f3de790cccbcdaf77f1686f159d4e90b0ea, + 0x10bdf28bfcacb8635108ea9153bebce77eab04539700acc64c084f8bc3f4a20b, + 0x10b6a895914a782aa94948c650f6c045d9a15d2706b259acf5fd4da311e1d425, + 0x2cd506792539dbd2f2cc3c96795d96831c21fdca7bd8988bbaac60f254da8ffa, + 0xca9da7606615f15506a87151200b468c11dfc0e28dbc306bcddc6d4828ce2d1, + 0x20d854f50910c52ab1f923102bd6ca5d82da15ba3f0f54f89a1becb7ce1f94ff, + 0x10de4900ee8ec243ca53404556e6dc15caa2bab8dd7f83148dca55a598ea88bf, + 0x1b6a8eb28c126c8682542278e4e4b2c922caf387f9f08980c8b469aefbc69b75, + 0xc2a3124091527d21e1bfd56cd88f9fa0616f2209454b5d1793cbc1dce9d250a, + 0x1d4744f598a2e98144d017acc5fcf08c5187aedea146de6ec74a5612aff8c7f6, + 0xbd79ea1a224987ccdd83f9ac4490b76bcbc554fa7c2418e0fe38e9da27dea1e, + 0x2405592dc81a66a17567e6acc20cca7179ae3c0971658fb792c0986882e57107, + 0x14f497a9e8110eec107450c0fae64d03bc8a8416db391d4c4770dde9bd38d3ff, + 0x29f8bb3529da3fe6152c5ef9cd0046568adbdd9daadfca8195ff20a0df7a5bfc, + 0x2a032300fc92bf19b9cde88cbe9da3f72e3ff50c62b6342e57f713b118a5fb87, + 0x1b59a7709a531a650d5ec2ac01fb09ced8327abd4588f619f36e0886c16c3df4, + 0x1fc0a3436f100a4d61ccbc321771ef6f85e421d5663bcb4c01c889ea5049fb5c, + 0xe9acd5d917d4160434a8fe7037b041c269eddceebb9129b6a176c8a00910d22, + 0x196cc8a225f2c2986abab4268b3d6342ddb645bbcd692863e93274b717d02844, + 0x11459356b20c2ca8913d1c0b45087f5a28559190d486f04038c05221381d4aed, + 0x25e96c07ab87f3f5c0688608c095a86f80ddff5c250f0f6375a45398034d64e3, + 0x15d58252815ac471aee3a3d097d799e9efeb969cccb08c33ae0b7adef18f0250, + 0x6546b3b7f85042fde21f23c3949c39c2276f87701537434f147a3cfeec10387, + 0x1e2aa3704b080c4cf11798a00cc0c8619c8d5997bc3121a17553be7b2dd65678, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0x19e24f5e120e53bfe7fc01338211f4faa1f95084f2716e5587660295ecea8d03, + 0x2ff252a61572b7b92960841bfecc4bf5940bc0d682f1770fc272f70d41682844, + 0x2b9ce87d63d943afd940ae87979d5ddf50b784fdf8cd4d1ef0e7c4f220c98647, + 0x18eef6bbabd4d2a581f11e2b22a591364f5a4fba59146a97551fbeebb865fc2f, + 0x1b094af27259dae5e2f1929f16f00fe53d3acca1867d359d4681ae8a71f9ed65, + 0x2f2fb2e00ecc111f573d8002c53959067f3bc7b52959d0269ccfea9729d89435, + 0x48c4f81825c5584e76fa65b19b9b9fff7db07039d3750f3a65faa0a608b71f6, + 0x20be19e025ea25f85f5998c77a52710dfa5dc65bb2665e58faaa5db7a0c8a92a, + 0x222a05083d24105754e3f7fe45ece6add87677e8e64df3f44041618593aaf5f7, + 0x14f3d89c38b0249acb03dd0e1130100dde039b1e442c1c92ba36f8368ea16825, + 0x13667b7bba6c07aa7e18db6ce06e1308cff4eb1c0aeccc1187798aa1e97967d5, + 0x2bc234f4828ddcf587bc65d2a2bd5ad0974f5acd1f790d590d66e8f2ec739e1a, + 0x21464644fa0fb22494f8f6a7f7a929362ece3b3eb9fcd77cfbc23b2c9066a9bd, + 0x8b65df38447cc47455b407b32c8bc2c740c0b7b37ebc4c61d867b75b844fbdb, + 0x2369e1c199639bc505ce0da45601e0a51eff0f26588d74853d07b41a40b5b701, + 0x199051763385672f6f8303896f959d2b24b4cfa4d62faeebd54cd43e190c5e6c, + 0x201ac20d62b94056b6da288cb5a75fe62dc788a8b0d37063e22318f8c8b5dda2, + 0x18157f398ab7dfe77094ab6e91a5ef4e0ec471fa1a04e89969d1c11a2cbdce5d, + 0xf33f8f6546777c507e2a79f099a48d743325864e9e90a927478545a21fd721b, + 0x23703db4b584d2c4873e7674c6f3df0e16dafd344ffa9431cc3348424e2fbaf9, + 0x4501063364805e7a5e7d0a9b8797953e7f08a5caaf873917dfbc3da3c5be895, + 0x2ea0b23d55d50d907bfb16497f56a979ac7f460172477dbeda7b450c7625d243, + 0x68dadf39001f91f51a0613004e9614a54402b6fcbb0f4b8bd8aa546275e3075, + 0x241c7eecc6aa39719bf6c6ac8a980e2100d8c341565d138ede2b374177333aeb, + 0xbb9576b315160e6d9e5878bc54cdd9cea38c935d75fdf8b39daa3479a29b27, + 0x202599b284bf67ea50cacca315c66218f4c59a49a27e193edec4b9f93bf05322, + 0x170070a071a8648635667f8315e5412c48c3196d1d551ecd114857cbff9b9d3a, + 0x302e841876fe659903563549979b9e27ca6d36f004a559bd2461d5dcaa40d2eb, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0x2731f1ac5dc030ec117fbad7b53c6b02a6c9e04a17f64bc0e56885fba0c2ef3b, + 0x8e4443070b7fcb1a28f620f990800bf0a23bd32146d7eaa824f2b02f50a48ae, + 0x7f1ea73f15d8be5ee132c68b1ceb3573909753f86582c57150eb71932972e5a, + 0x5d68802b26f0b520b248a7d4fc2461df7756641131a1ad109fa2588c462320c, + 0x2c6db9f72cad44c3dd15a83d5ef9eb7216db1e716bd8bef960e52cabbfca8101, + 0x26365d95008667a1e1b2653e98f899a378e08643d7bbf706c7d3eedaac0b16f8, + 0x52ff974b2d04537b8413b1b0c85065f727ad6da454f909dda0aa5994f7cc2ba, + 0x2b769645daa19e2b07470aae4cd88672e7160cf3c07c7b271b60668382810327, + 0x25f56a0ae50d333f294efa08376a37c386dc4cf24367139c640514547dbae38e, + 0x2f2d49b2a257d8aa58b838af6357d865236ecb76e7db136a09a5a094ab7c53dc, + 0x2b173636674e54aa05d0bf2c60c5df0b31b2e801e6afb149eaa2c6fd73d6a626, + 0x2eb41bfb627052e1e7373a7392264e7d680a19cde030d8687053755207c44037, + 0x1841952650b7215b249cf50f8b6c78511c2983145ac405cebdfa1a8f54b986d2, + 0x16569fbfaa5e330f4ce139b103980e0569db854d701d76a233ec9c5a8f7bce2c, + 0x60c71281c4ed3a23d7ce20dd30c22aa172e245ce529234ed18a130222a9e611, + 0xecd53722d116536580be7b8a5c43aedc798e1110c99fe9d806be2140f5c7786, + 0x213c0693e38ab9e0cd02d2447613d5033fce7f5444387652f03e95b9a18dca64, + 0x772d0faa6c722c861da9582961e239c0f4554580a5a067f9d9e9bd71f978f85, + 0x139feacf69de1ee3d14f4fb9ecd06681b58d4ea37d309f6062a2bb34806e4b0d, + 0xfdcd35d68b9a0a9f0d39ba065449a7ff04c9301927aef113c5f34061299da94, + 0x125be84a276a6acba551894f5dc8e14f3734797d489cbe94542be8bca82c5e23, + 0x2be65bd8dbfe8d435018dda75806ee34820686caaddb53f133ccd9877913370c, + 0x78ee87a14ac262c2d74b17aba71d620685987727ca21484bad37052d59d3bf4, + 0xdff2aa73f9fc438777ec8be74d494ec8c36fc04ad3f12113624a58ba52abab9, + 0x282f6e2312ac752d294d116b0308981e7ed45e2162403c5ff705d136fc05ae60, + 0x2791a0a3c213582e9a272d6b667c740e63cd918d53ba444d23d095df767b68d6, + 0x17477c566355c80fc784384715356f69c8f104b0154533af3c92e0a8a1319ac0, + 0x2fe67e79a807315060135431a9b4426982e90f3b38ecd5d8e0ed7a0cf58d6c1f, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0x957903e40cf2319059c20c0fc70a5f3f8a79a64f3330d165e2c60b5b2e7bff, + 0xfc99ae6ab79445327c6d487e32997d5b476717bd26b47b073471c8367a3cc, + 0x2962bbf10efd8a8efeccd09ff80e9ee162249389094019af228cdacd2e42549d, + 0x25a909692ae443abd87eddd74f8705c80584216d5be8a42c79ca3079fddab520, + 0x1c0e8c1b8bdcb489bb68d7239dfcfd5271c4ac39d27e222be925de97750ad5fb, + 0xba6ee96962c66ec04c070eb3e71285d8c91cc967d20d72de7291f020f2c35ab, + 0xcba1238e9ce747c7d499320e3bd270db14cd796ba829328556f7c98d64c0d5a, + 0xc875635083ed6976d068751efdd6cbc3cd65da7c97f642b5361ea734f970295, + 0x1697dcd735de9b176c4d10fc5ab1228775788ed4beb16dcb0629efa99a6a7e57, + 0x244cf5956b0289a789aaf00f2e2cad480cf0824afe8eae41e259df395bebf2d8, + 0x206c3705f63d7b871045c5245bd3bcf720e12e4f0a82fa89a1f913646d38babf, + 0x20b58ed4e80e868305522f5eb670ce452ca9b1d541897d51ad7b42c4ecd13205, + 0xaf72e95de70f64d621db85a37f69f5712ce06e7596aa97a1188bcd3861d6c2c, + 0x1c1d15ca4b3e0508280869c3ef38eee25c3d0cfae188b5f3d59d5c7c5211d773, + 0x4af306d94e8e36627df09ffc20ec563aec05452b6b8c1a17e93c8a3f30a9207, + 0x2f697c34b59c559aa232e40024bc6da390426adae165002df519d7f2c71461ca, + 0x8a7299528acfb65d196dd9a7a136401178a7d03f6fbf5df3c69e6629895dcd5, + 0x221f628204240732be38e2d0fd3addb1080248592ccf3d655364e171302b4780, + 0x2b4a05f00a373b8fb7938b4f8812be582796986113ba1d80749be041dac49088, + 0x16d94da79927c24b7bbd25defd5c0fcd67073d738f31b93ff08bad9078b2a23d, + 0xb536adba2330baa9a070a63f86c465e3463d4afcebadf59a233a0319d1bd21d, + 0x1c57a599441a0b1474521bd0470a9cdcce3615e2575ee4baaa38a25958cf1784, + 0x1f13db4a9d7ce5fdeaebf3a571fa14807e979a23d8f1d426fa16ba9941421c60, + 0x12b527cd8c1fe08e9d909cfae1c405f11321538cf59af3a2cee67a06b11d9859, + 0x1f2c0fb5f11e6d74db0c30125e48be344c15529c61d4debb013a7b06f07fff95, + 0x1352f4a6320fb513348dd5f02ca53ceb1a47d8616892608eff2284ccb7fb1d01, + 0x146dfeab263219dcae7613a9b5403759d5122c9aa490e36ba5b4a37d489f8e5c, + 0x1edaf73615e187effe0d876478e3682fef5d63e3a12edccc216dc302d776680e, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0x1c28442722fb49d44d40b2b6e86e2218f956de3f4b376c3963955666a8f57189, + 0x20e9e5c1b5d8cae475cd16e899d1c9d923d8d20ec60727d9266e66cb0585a67a, + 0x2f8dfa1f54af676eea3d05bcc648b8f511ea011b5ad23e961e1b695b4b5267f2, + 0x1a1a5037e57e4ae723753d3d22f965ad8b911f613d6b0e5d64ca9050ae43633e, + 0x1ba983e3c28f6398d73ca8f7e2963564a9be471ccd5c3eb0c4f8e96635059529, + 0xd4adfe4a7dfeb3cf86702e54888304e36057c89f10d46186d647bfa700688ff, + 0x15c0166eea20cd705dec4b44aaca007e6c9e4aaf131b47789cf70e53c069e6be, + 0xceafabeda1dca814433c969943e534008012b6555b08cb2a4abf43793fe0e5b, + 0xbd15d8a31cbfbdb7c36e540f4c70a5eeead9d43a9414023c763d2fb643fbc76, + 0x17b69dff9f9dfdbf6bffec7c7ee15eab02eef17254a526022d878fcaffaedc75, + 0x272fe422dd56f28e6375cb725ad469069e1e48aa945dffdc1e9942b46307b763, + 0x27d2db5651e5293ff051000a36a2c949a7a3e7ce326b8c993845ad572ed1816e, + 0xe83466c2741c36fe6f5f5e6e60bad5bfe3ea06a7db58680dc4a518f42b6ddb9, + 0x1b97b0489274a5912c53c18137e918d8f7d3985034c617d9d5dae4cb75990486, + 0x8b09b027647befc8884bf237a58efd361641e4a25ab1e8831616ad9096aa157, + 0x22f46a0157b70196720c57a7636285c4b10854721e4533294283652b1911bfc2, + 0x2f1f803aa4a96a296bc8dae8d07335ad018e77ae6d779789bd718e72d8709a53, + 0x2245e61dfb52be01fddb5fb4179140e4b5bf8cb1c7afbbb6976382cc712d981c, + 0x1683f9bd4b791410d1a889953b716d95c440692fe4b4886107d052a8d50307c4, + 0x242e864ffee30fe0a080e21e4d275db8355560f07b7745a4e5aef58d09b653a1, + 0x1eb483efd8310203c93a42e06b18be5b4a0cc9612c335cdcc82c104c38b3e8e8, + 0xa5b1b4c8982984b6ef162eae01f0a53337c0991c27faeed2b61ce3cf99f6503, + 0x10c25a14e51fd3df8e34f70db38cd60124a4f4837d0b024d5a0cbcfa8e316724, + 0x17e9f3efea4275ce4dd5a760f4215644cf5fda3659cc82c8cdc1c66ba5336c29, + 0x25c1bfc4e679b3b3a692755b3313ada05f6d747365325250e0d6c0c566070ca5, + 0x1356277171f1d2a2e677bcb161d9d760648150d1f297247ea842abf2633d4715, + 0x28aab6b87f9f0f8c708695594610fc99a820dd994d63ab25829c0eee980d246f, + 0x148d7520ea0a3d7ab3ee550cf30cdebe434ca7c84ee346a5b8b6d5d35ae06e88, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0x24170fadfbcf05e5d3c5d0d5d051f71de23175002d1f02002939eb24ce5d6d29, + 0x29491e9171d578c03ba302262531a6d8ff03ab25af7db467947e543553b25e50, + 0x10acd03b983a457e3eb10f10666a7540b46066effdfbb50a1c5996e8e42879e0, + 0x1fb89a866bed5ce87cc2170f998132512ebfde77a2aafa84f288024ebd9e6c78, + 0xd98b830d880dad4a0755da7626c0cb7dbc454bef88b16992f3242c9fdea3cb6, + 0x1c0d9302769b138d161d471195f06bb20a5a59f53f083731bb4b9407af705880, + 0x299bbd2c9b64bffc601a51ce60185e770765abb952375055e0f8c6edc3c1e7e7, + 0x1e3e012a3a23cc56b69b92c5a82ddef538fa2745d68bf99e6c4f65670b8a2581, + 0x11f5e20407ee480fba59b35af723c3c1e7e60fc4817f92d6394cd7a9c65ec766, + 0x26d3be3bd30f29131705a60fc4f5d51c6617919993bff2a9e9cbfe08819ca686, + 0x2b29ffafe79893a89844e650ccc01ada03f91f4853166006e0efd05aaf3e3647, + 0x1fbe32c5de07b6d625c86ff0062102ea1ae1f63e80ea0473ec747ad9a67e8a08, + 0x24e36875d9f11a3fc2dc23d8ae5270150759b92a7dd422d2bb196603835715c4, + 0x1859e0cdd36899ba3ea1a15b6a5343985e2429576894dcfcb39b17485e965a37, + 0x2e823c343fa815b8850dd85825f5ea80cb32e17ed0a8ecddc478609b094952c8, + 0x27ae666b5dbc3dc0d19c32a000a7df0fdf669ef25691627c4d7b17c6f4348d0d, + 0x13d3988c983fcb3cb784b222b2bb8d4e947afdd3fb1d0e5bf2ab876eab1ebfd2, + 0x26055ed2f7cfe90bc54ebeee9ae37eaf62f11d4ce7ebe370e7776167a51779a9, + 0x187a3031170f0e0ccb8ca67fc2cdab2c2a5274613a5ce191a1790b91cc6c5888, + 0x979a5a4f896cec804a633285c9457728b5a6fbfacad62593a23aeddefffe055, + 0x17a9aad3bfa4cd25d929abf715dcbda7ab2933a6868d33720a5e6c60f88e31c6, + 0x51192a624e65c0f7590c37385cb1a0b52b46205d2ae7109e076c08b307add00, + 0x2aa14feee17ac6700e5e58952f28d5435fbac37769c3275ea9fd35ca622fe7b1, + 0x354581b4a29a9ad673f3c57801bbb6f8a57098c9cf5c15860b4dd240d83b536, + 0x23bf29c02d8d818da4257fadea084078a4f7d772795ddcba9e53030e06cfe36c, + 0x209923e9cc079197d001f330069b05b75547e48685afb804931af5a3a241390c, + 0x6d614256aa7a08f67ea8d06bf03ae83b820669ef7d7c1c7fd992acb22ae6773, + 0x1131b48492673e474c8e23277571bd9f9b892b8ecd3b6af754ef83a1f30a429b, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0x17ff3c20af33dcd172bc3042ca7ba8b9acc7c5d35694a795bcc8ae3c35d9e748, + 0x273eca5bc74073b2f6761b6b0494d48407c4a021056f88b79f0dc3c475802c39, + 0x24edf79bc35300c727d39b301de82e8cc21435e8ff3f34905436bedbfa6f9d91, + 0x2cb3232131a5d86145127c61ecc8afd66fcea63e3ed9b1ff1ef3099aeb2047ac, + 0x1ea49fb0e46edcc3a90651f6e1a4b36175bdb25505cc998a101710a4fceef13c, + 0x1e40d394feff0707116e1d43c523a36ea293d11ce3059b5562ee678a008a594e, + 0xfe47524266480df132a54698b09e844745eb540cba498623a93f36e48c63bee, + 0x1f113b5d7c4a3e1f1156dcc68358318ce699b352814ae0253672d6c185422980, + 0x1aed347277640a0a0cebbc2f4ce523b9a51b3750672eab8a9e689c488bc416f2, + 0x1ef98e57380c6a8084a8d77b701e23dfbb56339ef9cbdcb9644460a72a1f32e3, + 0x297ab0678798b06a4cc7147cc125baa11a058cf0889354e63229f185336cd356, + 0xee54e4f901531d3811aa6575c60409c7e6ad4b475e249fd3334883b438a2097, + 0x1b9b0f52375f34b4210e078d4824d0d385e6e412cf177f862aaafc3b6f11deef, + 0x261fe98c4a6882bf586ce9c03ba90555d428567bd98761ecb57bf8b1ec408458, + 0x28d8a46abca186e9fe9b326c166870f98acf6655eca805b881ee02ed4f3e8134, + 0x4da6035fa7dd89980485ac0feb277b1eadc58f522abf010de5bf9d33974f232, + 0x1a9738d1389ca170c20ab5bc4d39eb39992acf40d0c4da20ef3e3394ef369b88, + 0x183dd4932830f3f29bf1421cf0e03a90321b974c93a2779cc64031c4c0166274, + 0x1daefa57c81865e8a1e3163ca39d400cf5ce472f21a1888f300741ca61d61a3f, + 0x2ae49d27bf8dae3b5f8499fe9f76fd2f247b3825a8f4e89e5c53596a6ac5b13f, + 0x9063107e2a28ad8dec4ee2a43760006c728ea07dc7eff26f34c0e88becd87b0, + 0x327db09f5185889ae36e52db244214053b27bf18d3f240552dae62b60badfff, + 0x6e61b73f704a3cd70cfe843f37956d0c35cafe6bd28c5dfc1be98399c734fd, + 0x484994555a799cbc175bce4f3add547300ea3bf0597b52f08adba0d0d7478fb, + 0x1509af8f777631bb65bbe5ae68fb4bfd3e61040cc4c28250704e3e52e393a7c9, + 0x2502148be563d2dbed722eb34a878e32686eddc63235292ff336430ca6bd5f34, + 0xa90580e651271747716e4e65ea8dc039345e0609e4596fe65fe9539daa129fc, + 0x1268ac93435ddc3de28c7401ed6612751f4b244dccfe1a75269da8036a1173bc, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0x11aa913289660f7deb7ccff2f4be6dad755ef59eed4b716fc8d87e247a6fdb45, + 0x29e72a16e4534eafdcdd6139bec5eb95e22b7566508e1b748614d450b54c15ff, + 0x1a958e6a0b1a339f1d3dcd38ce1328571f35f09abb1686e2fb4c3459f036c58c, + 0x2ed8337208e410744d73bfaa8049dd98a673eb4734b2f1e6c50dbfeed2532eac, + 0x29377f640a7f6f76b922b18954b3ec12216ba9c13e0010002b59ea34fa974bef, + 0x23454f27137134b9af8d43dbeb2f146c9a943bd5ec7fc7642da2ec887e9bc4cd, + 0x209816b4da19597eda949b4db4754061c72a3c902f9130edc98b592470b0ee5a, + 0xc1eae8b0bf925b0a155e42b2e51678cf5efc23a07e62a16ce7de2b5fa23a43b, + 0x86f81d19a31671e41a874adaa71edac75c4eccc6a2115c2ac96bab6e4da91b6, + 0x4c599ac0280aed84f94db0e328837392ea3338153ff37de61a7e28bd24392ce, + 0x2c4b7cb11e988d5451ea53bd7bc59c1d92a3250e5cb1b81c8017efd00693ae0b, + 0x20b49fc26af7d51f043b48670b79a409c4fc366332e67dcab28cdaed5fcb8f32, + 0x2b2de9914033de3d614ff1cc2a46234dd1f3605a9f4e52fdf2169986b31a754e, + 0x2a0a9aedae2ddb9eabbe22dedd043c670ff098249bca89b2d7b789c1a200e832, + 0x78bbcc544330029c5703ad867d374a907efee1f38764e417f6b724ba2156685, + 0x27f2b059159be5955c9e227e865d0a8add82aa951ebd9b2fe43545704f0c4bde, + 0x7a6c429e1100125d872120c307bde17b721dc31e16763cc096a989c97df7843, + 0x10424964905ef646913f708e8d4321e9ae2263875b83e5c65d096516581d4090, + 0x2c33aae7d921d4b90a0376b93aef9a02975fa8343dc0026066d791e9030e04a7, + 0x1232983e555c7d4bb4288fbdba3df682913813bbe616c9ef9568820e02459b4d, + 0x1ab5023e5ffbea8d4fe8e006beeebb3162a26e2a4546f51b1d836d3467816c0b, + 0x1cbda131f20b33ebceacff9339451b84854e65775fdc1f5ddbe8c35fab2116dc, + 0x2ba0bb8404000f7361cab18e78692a17d953323a30934ab439e23b6605c023a5, + 0x35fa0580ae06fc96e0e4af43e63b089591bebe233c526a67973f25cc7fb482c, + 0x70babb38665a3546e6e23f8f3b26f058bf131abf19d3c13d6d0588a317c6d8b, + 0xb642882c1295343e9ea28b89a62ceebe0b7919b6ca5e18811aa978bc181849e, + 0xc68a36f6df8c27deea1f66f891c80fc215aefc646f545d63cadf22ab44b5914, + 0x66489b3cc989e807be1363d97207014a2a14052de80edcd15c4e2f88d2c65dc, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0x1026e6257b43e0afee22a0189f28e10718f4cc5e49b3d15405df85d8153e8e1b, + 0x3947588e943dfdbd95694ddb3a1ba7f51028c847b8a45164e87b5522418aec8, + 0x1b1cb2c496ae764bfde288ea50405ca6ae4ac6f9ad1998b83b7557787120cb1a, + 0x24fa4f9ef707a77f4f3742aaac6b8fc5bc59fa8c4046f9d024e3d5d80ac0c38b, + 0x21dca28d7160687fbc8d0d144c062711e4207f617895fa46dd87922777ff10fd, + 0x82cd14685bc3b3219e1a76ba6b2cd6b8286405a38705273a7faeda1da62b3a7, + 0x288c7734ce6cf001742b8e84fe502cf5205a623a3f0fe1d79f0fe916df073c4a, + 0xcbeaf576571ebb86d175b804c4655da7603096f9865f983a044bd8ebc416714, + 0x257aece5dd9d7be08e83df64b50b5ff1e31e4cb6ef8610c6dbc9eab409ae7383, + 0x178df36af677df81aba8a9fa9d31f995378d1f69d782058f7ef769555ad5363d, + 0x889c87f38b0244685014312d379ae5ae934531ba20b7e89f6e1e975e96d5bed, + 0x28898ecb6a12d999474f7cd98e7d0e3eb9da404cb45de9285115b647caf3102b, + 0x1544b607ee25873cc317f6eb88b72ba9371ff52bcb64753b0e90dcef61032604, + 0x30b741264c73950635ba61ae3be32eb643d9a78fb6a6f695ad4046f1b29a87d, + 0x25052d3381e118c1995ce20ebee9f1cf615053caf4d2ccc143fb1e6c4ce154f9, + 0x2f30bea892f8f2b335b8e8bd925f244335e430f0c77a2313013ddd6ed40de0aa, + 0xb0d65fa768e06aa8e5b1aea32a2d0eaa75d2548296268d7bdc1c4b7a2234989, + 0x1fa1a1014ba36436c1a7d8cea18580c577928229ed8e30ce94dabd98b873fe27, + 0x301c506433828eccfffbf89757d52692c7ec633f32e726ade9fb89f7839150a5, + 0x154a7110569dce2d4dfbb0c4d590669811751558a06207a1602bef10d3428ee, + 0x2f27c0dd673d6353840612d1cfdec89407d7a23e25678d1fc57aaf210355a84b, + 0x48683bcd4388885dd3956fb83e1890710c7d1cc5d103b48c2eb7a4e48d3c5ad, + 0x151c3648a02ad924ee9afe8dfa7f163033d1683aa8ad9508a6c96ab29c08908b, + 0x14baa70addf9eba4a80bbda03d2fce92e571486eda83f0c0fe59a7e4605eaec5, + 0xba6cd972cbb3905ed976b62ed34d972444d8211c71f82a79c089fef7a030e4d, + 0x25adc9138d823eee97b0dcf9e7142c4d791bab92c10215d5b4f44ee166c44018, + 0xf0416997a418d2a20cdac6c53e67640da3ab4b5cad5aa3c9c442efb895b7744, + 0x1dc3e4e5d9f2e587fd95028c6372a304d987eda0525879d1b7da7c775f0a417f, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0xcdacd248084fbe79ef314cb06a96f929ce94f525301e8858e6b0ab419a7b247, + 0x28765df4d0b75915b2000538e00a7dcc8219c6e428e82f452ce8882e609eef99, + 0xe81a5592eedab517a051cb7235c8bf0dc0c332258a65ca6e29a8625a334fe8e, + 0x88c064bf7c553c7e4d1b38425883f54d57f18a7f8e9800e06a3c2310f01b2b4, + 0x1d24333468728c030f01a3c93fe035e9fe913f3222c7149cc22e21d444fa49f2, + 0x81e4d01326c4596d16d5d9df406a063f0c6b323e2a8e406b2788391a6b2addf, + 0x352a5a0fac781a16a2d8bd72c9402a3b1d36199bd4ea46125e33c33732ab311, + 0x26618bc0fd81464f23f6e22fc19fad753df1b3c076275c95e0ffc437760fbbc, + 0x228b70124680c991be94ba0f8016e384609e7a7fdb2ab40d661614d65a52193, + 0x1d0ba067834fa54b50347297a3525a6198bfc7d47dd47106072c7901b900a4a0, + 0x196b16b4a3f2641cc6b343a57a66867f96be45005df9c9fc9d07710010a1df0a, + 0x2f45695ff148cac7bd348b093d94e075a73f4f60b52227eb8ed6048fbc47aeb0, + 0xe93289c741402aa1bc152dd82b4889b657db2944dd6cc5c9cbd8e72e69063e, + 0x123380ecc6c09da5e9f5ad2d298dc60dd0a9d37a4b67d4833d2fe428ae7a8db2, + 0x883e804219d5edfe1b0bfae68a76df18f1ca939207b6b0bfff7bef4309c7187, + 0x21588588decbc2f33ff25a389fec95f429fbf43b54ab23ab20d3914ab844eab, + 0x182c5a52fe6c6d2aac38a2fc06ffb65595a1ca4110cb09ab6f5070f5962fc478, + 0x6a58def11f1c27cd234bd7d9be04610f52b68575d9560d3dccf8ad9b5b741dc, + 0x29cbbb5cab2c9dffc5b12c9230afaa59c7d0b1846ff9bbd0e31de3218afb7742, + 0x9a1d4f4f00323630dc4f2d326a5ca2823e77944ebf1c22cb9343963c627f17b, + 0x25f5157f8a190e6bfbb1eae9cd55819609220a196fd89cd44b5b4603e80e87a6, + 0x2f0794e7af6874b7463bf9d7f7f6cd2b9141b2c71754e4a8e487e26b723d0d8d, + 0x2a816cbc315eb725995b6ab706c6da8757bec6f588849f85d10b31767998bd4c, + 0x2c5fd92cb6990590e62056205768da25c8132d8bed9cc787e73b81dd9ddc5448, + 0x2e80276a04b486b1a36aaaf7c15d1b6b4bd48238065cef5eab1c153235ca6937, + 0x15257a77d445dde9259c6151c0af6a1771f5c23924a4c4f7fed58669ce49bfa4, + 0x1219c007e9664d8a54be73a03262d03bfe15eb3a2f8e7c9194271235eb435814, + 0x95144c721ba3b18324e55e532885ce67613444d3cb3e95955d7201d779812d8, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0x101a646241a8315f204d41adb7fad83b1a502ea09e7cdd815b21625cc0ebe09c, + 0x19282d6967bd22091e34c47fe72266e1cadc9f58d4f4679dc9255c09c2854963, + 0x42b2e9365e95f6b6afec41632d9a933f4744106315e3df2eb6633fb87356af2, + 0x86ed6b49511d6bd4815c76513809a77c277e506c3052c2beded9606623a4c99, + 0x58a4f66ba158c1aa28b651917f1fbc744b5286b3f6672ad39fe177be503345, + 0x28dde10bcf8969aa7a5b6ba1d48e2dcc3f69dfbb224566cb3fc977244a196cd1, + 0x3842b61df1832bc6b4e0ea70d7131f7b2561a94f78de3371aa976d05d635894, + 0x2c3bedddafb94b9427993c19bfa19472ed8cc066084c7cfa5c5e7f803a7582bf, + 0x163541b79f81db7f2742efa3584f07e1e7dd25a19ad934623e14b87f99601790, + 0x1846f2e5b96f8abbf20a2a6ed0d9a263337310372cf570a318dc3c91c849f112, + 0x6c7a3cee3f4166e6212f93f7d6eff60103cf16e252df30d110cfa0102331b15, + 0x25be194f6a3d69e3bf5f0b7cf58030a761e628b1a4de003d9e8a02fc2080ef74, + 0x2699fb6f71316244c10b2c672b2fbf077f217e1c910ccef06524af80f9c3fe0f, + 0x20e39137899fc0d2c5391fe185394173003faf87cdf3e438798b1666146b56c, + 0x22b9615e9d1b58292148c5aaa8c9eee5d540aa62bac93ccbe16c5b657161da59, + 0x17a4039cf90fb2c8ca78a2ab8474e5fcd1bcc7dd4974302128890f792960a722, + 0x296a7947ed0816212521f82cc836f1b747640ed9311e5a8432b24f131abf74da, + 0xe6222d1f658021ae1a8c83fef1078b54fe29719d30a30e33e95530140b2ac5e, + 0x24a832d0b62d7fedb241b289e95fc7f4507556c422183cdf1bafd1a516301960, + 0x314978ffbd36b1bf6b6efff9ceffdfd22c3128dab03035bc4d1811ed3a22465, + 0x23456fedebbef43f154140b56f0106c7b3a5b7cd60f7ce2a085a59d219364080, + 0x2bdfd3aa4bca894312e9f392192596efe7aadbe7b2c22aae990c18ce32c56f2c, + 0x1767d8e87ff8dde844b861af172f011a8094f2c93f14a367e3f4008414779996, + 0x9afea3b803901209c60fbed76494748e3af704cd3d68f6dcd846b5b37efd752, + 0x1eef9a7f080331471dd29d7d0106b95b1cf30854c201d0c7354699f2c0ff18fa, + 0x1ac0df8788f7b6b264c4b5fb1d15f9f43ccb6914fa627a6454bd7b107398f328, + 0x153587dd8856ef1c5ba584cbc5c6206ff27316111bcb089a37000e01fe12156c, + 0x1ec3422f01d367deb6566ea3f37caaeba6e6f1ab9b487e6adcd9abe7fa2d17a3, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0x92ab362071be64ee1defe4c464b18ea957003ddd4fb25ef1ce8c93eb0da67e2, + 0x2087c4812bd0d03d971979f341256e284a686b63564b913c6203e3a3316a0bbe, + 0x15e9d37afb1e0877c55cd521cb79c5f20658f8f238b8679a50abfab5edd498ad, + 0x2d3aef5f158c34c12fe84c4d48d49dfc4b27ef3ad9f6e9c29b9516be85df233e, + 0x244a3d476b0a0690158a1bedff28cfab8bf6f5ba4491691326e6b1b71bb2650b, + 0x10e9d046cdec45124f7bd3aac446b7f0eba568df3462c86c60751ce3e51c3ee1, + 0x2590289589edc3112e5d87b4f474904fa9dd4dc4f26298d1e9666c281dd58357, + 0x13765e0ca93cb708b9cf1ecb6427f1a0df0b53a7d112bc1a1439c3afc8e8c13a, + 0x196d3192651b1e8b5b1cf54e775eea3a4f4d67e60db2f0be380ee48819fd495e, + 0x18c81e4ef19c7276d9cda9d9bde0b3d4334f4748c76db52bdc4cb0de91def3a5, + 0x25f4226ce2c992fdb6affc2c85c8ca64c9db486e8471f93e30d97045eb4aee58, + 0x2a152c83769c9a975382957eacc862459e4227080ef497775273995c3f30c3e7, + 0x13bdc6f2694024b1e21e3fe7b281e44a48e32c31ae815aeea28a283187bfce73, + 0x18be50dd564a7b862bb9f3fd822a9e6cf8527290d0fffd2986b6efb0e4ec3ecc, + 0x76b689cf6fc26746914c11187642ad45b934b9dba8499e1e0f645d1e7360976, + 0x24cb96220d02e7d183cd28cdd89024647df21deba55e20bb0a529909ed483db5, + 0x109261482d8eefedd9555eaa2d4466e1b9582cdb50dad968f73ad96df83b6afa, + 0x24f33850fe4d7019ffafbd669532788d02c6a0dbb39948ada0b07f444aa824ef, + 0x175369adaefa269a66baec32ffd60d1be0ee1f39ca8525dcb73a6357860abb2e, + 0x25b9fec7cc7f651e8354d7aae86dc9b3964fbdec440c6c8369fea81eeaaae8b1, + 0x2d0c8b82de5ce4c55025fcd286e9ca575c3b0b90a7da5f677a0504c05a4b0cb7, + 0x227437dd063cea6ebb85f7b564232d22be29cdd7772640936c3698b7c9fecf66, + 0x1bbba5bfc8a010cb25f637ba686157eea46f820848fc2c2fc636f933d4014101, + 0x14471102a5ec4909add2c73da2c60ca518809f1e160be7dfd14a6e9b397683e6, + 0x1b13fb4a716a8661bd984574b55249784576b8346fc245fa7ff1154e748623e5, + 0x26344c34f453274463aaf170748550a3e5cd38fb0dfff173a2ffca0a7f2dded, + 0x2541b62c8a52ffbdd29ea87ae0919225e12dcabe2104b5f4708708a2cf4fc38c, + 0xfbd922b73f16d661458c67bf7b4b325aaf303c5a12902a667a78c8507036976, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0x2355f03ba072a620b568e7d310d9fa639d134ffd98561cdbd2297beb13ea0f10, + 0x25ff4bb05b96f0a0b05562057a8db99f97e1e2951137c0c40fa932de73ca19ed, + 0x2daf950c80154f6e7c49704d705e14871273499f2f619b86c5c5d157a6203dfd, + 0x51cefccdb8cf6928b91c3127747d700e86844f1148f0a34c6d77c5b849fe690, + 0x238262ec5467d6af343b33543cd5fdcdf909062c84f812fe01aed5cc87fc476b, + 0xb7daca406fc36c69aa958fa616f4838d61a9dde2e45ac8bc788fb2cb21019e4, + 0x15bc83c5e68048d36ab9dd5750982c086ebf0d155254d898c60e644231c54e13, + 0x1c63961d501d08c43558a7bbb6adf0248ce7d85c46ed8d18cb57fd255d70da87, + 0x2509bb8169fdbbd47da25a7229eea6ded1c619d3c047b7838aaace2693656732, + 0x69a50d4c1eec1a0ed50274c6fa4867ef658dc1379d8fbf9878d4b35e9fa99bf, + 0x15d74c0872e9b1164992ce0394cab9fd723220e0696d28ea011620716be1af17, + 0x10b0c815190863422b42d8bfbc68921d1ed561055ae5057b45c5e46be5a6eb4e, + 0xc11c306b5211eb36fcbe505a754052252ddc622d02f4420c77390851d6c42d2, + 0x150cfca445b9336ce22dfcad1175f597794b2f4bfd18a9780eaa12eef2ee5c55, + 0x194de31d0ce18660aa746a9356d96070ce237944e5304630884874a2fba798d5, + 0x14c2071d9d7df808b50b19e77e314406aee8b339c4a245b2770b802af790ebb5, + 0x15847c79aa8e1c92c18c3bff302c31eb38f001804c8291fd590cb9025a7d12a3, + 0xfbba1d54897882de6c7d26203aa96c3db29d788b0bd435c1d354c271b126973, + 0x1a3b7ee6c4f24ea92d2228b4b760223f9a34d8f70c3872400920bc066465877, + 0x2ce61015cc1e5520a83c0124f38a8359caeda53051194702485e00cc2ed02bf4, + 0x2b8be03a29a0e8fb62bbc207e587deb46eda5bdbe99e522e773bf63e6cff6334, + 0x105e1aedf0cf9f12ad2416a44fbf458d6237ee895960bb8c25299ac72bde12f2, + 0x120c504e8e99eeb16539249612eb1a9687e2f99e4fec80123f0c29378553bbf8, + 0xf35ac3925b66d52bde5da31655b11df9975be00efcbca7da24e85509dea2f50, + 0xf4957169958f20b8cb24ddd2c1fa8668bb5694fb82c2779a93e2d993c2a4369, + 0x7f61b3cc5f1220535cdc630b9033172c02afa0a7988a57c373a91c13263d805, + 0xe16429a495a0878289a4e187af2b3b9e0395ca3401938b70f07c0647273ad8d, + 0x18190cef50589e6c73faf348b5cd88be8dcbb44f37ecdf70e94a3b4045fb2620, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0x227f232164c4e3c741afa130d206cd84d835e4817c4bab99ceabe0bf4da575df, + 0x1b1d09c8b7aea951d45cf1390c95b03c29f6820492ce2478739df09b9bf0fe5a, + 0x1bd040cdcfded9e6d08d3d6bbbf55a86aba6aa5c13cf09ff4cc6db28420a1830, + 0x2c4d2f16535632f050256086dd4e2c88479a1d3684ecb8c25fcf3096b3e1a6ca, + 0xead790bfabc7e81f7ce3b6d68134286977c619a13efef5ac110244721c097a9, + 0x8900754358a5d9716c6e2fc17133da9069794fadd42410213b5e30e7dba7565, + 0x24c0631f518904d6a003e225b34d3d02e2e5645f7c6bcebcf4f9944fad419f2a, + 0x9ec6105a057621f9bd18fe13e9dede1ebedce6d72461dc1c4faabfa1aa7f105, + 0x79b0343c865e073462767b20213ffa9443db0387c9506503586ee533302e802, + 0x7df63d142bd6c29ee03aca8d1d5428920a7fde6437b949149327c2967d14245, + 0x2ff26c8169cec62032f72ac25650a6c94a18afca7d04da0e3291d3ce71a7711c, + 0x164edabbfeeda046884e4f8595e438127c32f8467d9de721fb50a816688e33db, + 0xbf8306af475136a305a5a78b818c1f2d49ab9fa181c11de516e38a96ebf9f55, + 0x16da51bf32b4e134bdb05926f7b975562a7f2fcb671bf0584fb0e4d33f33638c, + 0x142930caa1828bd842e28c8790df9d033eefae7b165ddce53fcd46f86d3be2f0, + 0x1ae7e0a72e9bad383d09d0555a1f5a0bf1753ce1a17e254b49bef0fc899a6e99, + 0x280313df7e066df1cb639a4b30ea2aa78ba46720595d77ee31b55de2a713dc54, + 0x1ba62055d4a6b3257fa66b471f11be979422c05d3a839ee6aaffe7ac1c0b247, + 0xfddc6ca4b45778c49a7db293c78628431edc830512b7b1c8e5754ed2f39ff04, + 0x929d32df53f196e858a97b178b1d47e42247d5dcf37b08b4852ad74f9cc78a8, + 0xf967d1490ffa3280071a718013b3ae7f9727755d261fa1d85c3ef7b0559283f, + 0xf5490a89b5fc95c115da17e181a7e95b3d3d2229e73581c6bea89a0edf5421b, + 0x674bfe177fdc1301f1d49c2879734cae162898d11000050734402c75384c736, + 0x18e1ade3d71eef67b1499555516671ec9978a13c5da32b3cc87a373a6515eb66, + 0x1f9179afb7f5975be537568da903fe09944e257b2757934ccf2e36149021f009, + 0xc11a256c35c638a65f02d745d35712fd303bd7d3137311a1322339402479ee8, + 0x2ab557843dbbcbff147b3f03de15fe79e8d40e9cd6cc556b12958bee7a900f67, + 0x168dd127ba4582848eac364d737e87bd02024b8924b4adda31a9a37a3415cea4, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0x2c4d427a7bec8d19617045360e52794c7a1a6de79c4e919698a87ec516366cca, + 0x36d01a16f30bd802544df169c77ea02c0008342cd8a415e67e49f2ab20538b8, + 0x104dada7b72b24405dc07a4feafa385fdd6e87d0eb0d0b0d461bce56c4f574d4, + 0x1d189ce1540193127426e68c7efbf6116be294f4e39c2ac7fb43eece2a5230f2, + 0x20969c1c5a7537d61331393f6a5a2ad15ebf51efacf6b61f37c08c8ea0823cd6, + 0x1727f8b0eb9595229baf305b3fc99c51d538637e2d2ea8931037c7350d5f96ca, + 0x1897f619c615a92fc082a589d89a7c522625432213d6a92fad9e2626aa0ee79b, + 0x1f62599143f1f32cd4efb433f14ed14544681878db55878f13e69694a226b3f6, + 0x118c2c92848d6aaeda5c8b61d8ed6953b7b659a25efae602f9961353f7c781d5, + 0x18997289e946839e6c3554194b87e6c0d4cbf30f47bc73b126d6eebe47a1cec6, + 0x130da6eb344dee64037fb513703caa96d8aaba83f7c8099308b4e6c82b14cd83, + 0x245357b0b612c4aeb12540db9ae1526513e7885ce50ee8ca0b58c5bf54261563, + 0x16efacd482e07f1fee18c96ad1725aaa33cac494d4e7301aa173f1c29a625581, + 0x1aaf282a0db417234b2f0afcd782874ec2a635899f3ebdf33f4bad118acdfaec, + 0xbb16e9a26f6e4449016a392f58cc0abdc15838cec0863a15cf24737b7a9c804, + 0x1ab091e043a032a1a8a17875c09930f2f3f8f014966977c7672e052387a88724, + 0x17a1b1b5e07302afe1156372691356ad32f77ab95b6dc1766cfdd4c02d260e0e, + 0x198f8c2021281502a922a03b04b3418571d4ce4f5359ca251015e477fd983d96, + 0x1cd705bc50da7642e8f41975abb2ac63593ce9575a0ebe0ec412e33c2955131c, + 0x2f634bc6e688daeb64b11b71780307d998916ea7db4cd7ac0761a03dd3fb1744, + 0x70efde061570346ca148955dee284634e28b4f5ef14d09018e289a5b6b5c643, + 0x129e1fa03e4374b6aa7cc2ccbc35e20a6124b84f3df49bbcc3f5aa1c25f8567a, + 0x872750e7e4e00867ca29aab19b0221191e89a4e7e17fbc0e0a97a6b99d79816, + 0x23e8c43c57b9dc6fd6b899818a44200e2544bf0865fdcac5b4256777fc765928, + 0x2a6b794cd03c70ef06885cb5ad01698f2340877a5a848c8f49ede93b5c9e830b, + 0x94578409d6462e7e25ad9d0816a6f6e2b198c464796c9c8d4fd566df266099d, + 0x1b2b611f853458bb3f92b07d97f4a8d0fe323b635959664d7003ace44646b9c6, + 0x205b0fa2b6f2ebaad41abd2b1feb4f7af003b5e73f91d342dc196ae182fbea21, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0x18813c17a1991709dfc3d21cef51ad2b5a728731db369c24f53c9c18f7537922, + 0x28e2f1491faa1312b2fc0756fc93e6faf260cf3c9a798c4c75567e6e2450f189, + 0x2456cf94d7ff6e124cf859d5c41e4cf38e76e96c66356df4959af90e84caa6b7, + 0x19d01fae3e6bf2a3d738e5adc140ccb0566748abd79323db3085fd1bd3a938a8, + 0x15b9bb8c1653e644f0ce9be50bc599be543d181a965c47b1e55e75c128df6451, + 0xaf54a3486b44d6cd344d767948c8bab86a3b770730d578d35c946076ba55628, + 0x2c403933d9fdce9b2356ea5599a17ca6fa2c527472702d33a1bbe1dc6481585, + 0x1f8600480399291bcdb8f2bd4410cac16f4cc035599a6e7f7fc3896dc95595e4, + 0x20853b736e1ef67fc8dd165d3fe11a6734287efcbb6524fb6eae1a66a7b1e8df, + 0x2f4630a0f0018b04c6bb77e84776e06e3b2452d47be2d16220ead1da61106b20, + 0x2b9036c48f9af1b32085e3eae9f541c4ea7b650f1a5226ea661b9125215e8995, + 0x16e06530b370ba9ce030ecc30f063bc064d716de78cd74c2262d483406e0e68d, + 0x16965fc262e0ca879a932d721e95d16953229eea7b3e95cbe325b48bbf4e851f, + 0x282361e61365be447c940bc7b8caddef10a82e8a51423e7ce17f4ccc8ac6826e, + 0xe5f05bc3d2f27eaf48ba6efbb95fd33d29dd9d371afdb46065089f07b5aaad7, + 0x45e49d05e82f9c8192a3fd3c936e73ed07f0edd6db0007205695a23c9272ba6, + 0x1aec3601dc7eaf614f812cbc025ea069d2ad1eb2b1c8bb602500cdc8b4ec97d7, + 0x29182e5f19d8e48e13b7a98a19be4552f09b452d0e93fb876b3672cbdbd48d82, + 0xe82f9feb507fd178f0e2c0c324e07dcedcdc0cb2ad743ceeb4e2b62dd1355e3, + 0x9c0bf03083c7a7f84dad628b3528a89001d43100039491bb3729319bd75f304, + 0x1ac08c4bc322282517d3e9201c601823165882a09f83e43fac846c1620aa01b8, + 0x25661bfb76d976aa63291de2624e7f306a50ec4a32128a39bcbb6cfe34a227d0, + 0x2dfbf71289f57fad67be3438cc1f0dbc969529942a623a899addfeb77ef1945e, + 0x805aaa9f12a17bf01288cca68aec10cf08db6bcf49a8bb56edbffb97f6886df, + 0x2bfea7d79a17720df5f215d42ab5736098c83da075facb964eb2fef730b22564, + 0x297315ed7ac6f9bc92b4dd4a4052519a5029ce7c97eef84ff11a461864dbf9d8, + 0x172960704ca74222cdd9c8ebf1821031312b4c21cbb282c1f11cdee3ec28284c, + 0x14b30a8e90ee6a1e22fde21503094bafa3d61004b38a69cf94b493e101a3dd29, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0x25c2fb93758a36327dbeb7dfec90e331cad05a04e5c84e6b40e65987d73ee448, + 0x15be6f22cbd5f38ec70f9133e8392e8fdb41f28d831c27bcb36e415fcf9fe843, + 0x1d2187e9af970cefee949d0888c73dc41e7e257e327a9f20e4648928551e062a, + 0x699ddcb91e856bd25bec8b21980bbb163d38a20d47fa9d813a32324e80ac79b, + 0xfced0a1de64093947616ade5773e0f7ba22eac4862322dd5ec787fdffe3325f, + 0x27768b29635a400d365c934202e4bded719df8effad85e6eeabedc24a4154888, + 0x1b1f6642ad87106cd16ec5421b38c40392423fe0d12f282efc8474efeb957d1e, + 0xa3e365d3159084cc673a44044bdd4260e1bd25b74f746772a3c77ef3e48cb9a, + 0x24179d5e64991d45a0634da43510ccf0a34059695e151682b9d356411edb7cf5, + 0xfbbbb67aa88655564de38814ec6376f4da97ee274586c5287c163d1b0f98dd5, + 0x11edd5438d9b4168d6e2bbaed31f31ea464dbab80ed5e702126fd82ed38350eb, + 0x1b76cf5e219ed4bc311a00cdb03e28ffbf86542cbd0252d0715bb48469c15dd6, + 0x148437b32c2bc48962d356ffcaa4edc05be984134fb75f3956d5d91044f79393, + 0x10942207a5f66bb8252988730fb82f23a45be26389489f66da6fa113a40ab0c0, + 0x124681e28623f42196e8ad7bb2374c77487c37485bba1a9075859582d10c061b, + 0x2f9dc5b15dc408e7e97ead3b9d8cfc654f6914922e33d7bbf4c061cd8583bb2e, + 0x11597e8f45721d0f8a2900ec7823302003282aafabbbdfffc64e5f3caa274777, + 0x14ee771b1e80f23b2fc58d2f98d43a75dde2a5c7d37fb0ec3a90b661ee4f191b, + 0x22142acbf84a03df8d16dd2ea6dad8b4100f864e5dab2f6afaa6a4a36612a4c1, + 0x17cca25c3d45d22a57fe904ab20f916d9b1890d5b7f70f56e5732325a790e637, + 0x3120041b1c3a4c87445672333283fe28d18f05deb5c7e9fdce6cda7fa4d069a, + 0x965b18e93bde84a1d8424a74e69eb6aae7a73fc920e5cf5e86410a46511ffac, + 0x3601f2a0058f85efa835c5ef0276719f80779d854e881370a3d4150a68a4b65, + 0x14f0454cb6ddaf09579651aaea20532036ee6f54bd9893614b2eadcfc041d756, + 0x11844e3d73731aa76edd24afb82a49d60c861eaa25579c45fcb23de6a45667d3, + 0xd49b3c8de5c8a009efb91116d019f97c01ee5289ca666b6807fc89fa0697e32, + 0x15ac66208d53f730d995abc5cd72d50ad90909c8cdce17c5aa78bc0b274a8571, + 0x1c9c5cb02fb78be508a818a070deeb6963c687dce2975aa4593a89ff1ea675a0, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0x210b5dd8b7bfe15189d3aea8e53b5bb7b462204e8eae1f9596bfbf1cab727bcc, + 0x1e72e11f21abc22a4f68b374dd8726a2c72f9891deb6536f3a4bed98cec40858, + 0x1d0ea48d109e37ba4d144a4251066d6d7b7910bf92f44aefe7081027e1e94ffb, + 0x19c6c9e54dd8314a776b1b1e8d423cb2fd5b6d4951f3abdf7176875a0837b3e8, + 0x1722bd20050713407ab428b4a1598dbce86e6a04f9093d0d415b546bc1d265e9, + 0x1bee9ee0577f4a46e9500f2066dfbffcbaf775211450f521e13aceacd519010d, + 0x4f1c326c88072a05332ad14d25ede90d430394bd8e80321dd6869a561282e37, + 0x2db49dfe6b2f6f8f38102e019206a908503e268cdbd5fd7689855932394952e5, + 0x18cacf5fcbe1e383706c2ae6e294c691eb86074e611439200f39b49db2739409, + 0x251e39efdd606e5efeefe439a1d01dacfd6c29729472ed884160d4018d1e510, + 0x20ca4abd314e386d0154234a94bc5b85522a1730c005528a74d7f2147e449437, + 0xfd8d3092bca7b55b7ccecf94172ad86eeb0336257108ca5a1786cb88be7249f, + 0x14a262e3bfae15e0345a1f837f1343b2b245fa3dc706956bdd64a74c48e86e23, + 0x21e54491928f3904814373340aa65a0f97be52dbead9b91011fc454b2dc8f6ea, + 0x1a41918b8c68ea8d675330f618419302cdb44d7c4821561bf3f75f10824cc06c, + 0x21930445fb5f525159a17da94a2dd4d28485794801b0c9a694b03b849e0878da, + 0x17535af3d952f2a356554ad0183697eec1c86ed9db1121036de89df8f758c7cf, + 0x1a82f3c943c80fe4ee37b238146142decb389d69918a0d7abd97a691e2ab80f2, + 0x53b942c6f210f073fa9c58f6e607da4fcacadae35e5bea34eeb6a54cca2eebc, + 0xd34f91b743a6ba52c32052bd0623804fc8cf2bd384bc98002434a2c9614337c, + 0x2749b7c85c71adfbeb5900b6334c4dabc9925e9885c9a525e74f1edb1e630a8f, + 0x2284a0f1ee6a86ff447d51e642951ca76a50fc3f4c0d009228aa67f9a9b1f953, + 0x22c7f25053d11e887909b02af7de7e57f5b5f9d37ff75acd8ccdbb74b717e23a, + 0x29c30ea916675045cb996f3d2f3662cae115e6822329f93a4d159f18afcfc49b, + 0xe555cdfb1576e9bb5cb70a9234a6e9238b912c9d65100f2dd5f3130bf5a000f, + 0x2f16e6a9e0bd6fc0b41d91bd065f60dbc36179607545fd58f0b1e6efbc86e172, + 0x25f261e99981d3fd2b094a13dfdd14e1ace2d0100973ce0331081826b8c69ca7, + 0x14d1b4bde07ea82505ebc4f4f9b599ca214a099e081a286a223bf8309e9b1348, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0xc2161d0dfe1fb1b030d25ba9e72e2d0f9c7be11edc3ee0310dff7dec3ed10e0, + 0x1de725c7f6c995721e1a1d0a90cb31563110eeaf81456a3f8a9809440c9e9e14, + 0x12389968950116f0177afe2b7732608bafa5e8d50393668844f9db50455729a6, + 0x17aaa2062cdde57f4a67c7052c0990ba08b3e874633dd41237cb6094246d678c, + 0xb9984737ec0a6541f484c9fe4837a7639b58d017cdccd2beb305a937a0b79b0, + 0x320982d756176f852dcd74ce8be156b5d7f92db99df5ccbc5cc96e93d83773d, + 0x2a4319d0bc04e4c18b9b105983c8744ca4cfc428f20ea477e9a60441ca15cd52, + 0x182b9434e89db547bd499a5122ad77854562962cf0435e21d960d1c4498edb5f, + 0x1d26abc0becb0e422d36f4c59b34f6fe77ba771192b2fcadc8cd0965bf0ccfb1, + 0x958a9dce1b6a17620dfb54c364af3ee428dc932d81d1dc4669503840dcb541f, + 0xa8a70a8379d71136fbe77851617cbf9d52257c32c9c3ca4c8078c90ced7160f, + 0x208a9a840025bc0c38b883213fbbb42c311c4d7a3f1c2d53924999892fa9f931, + 0x1f1acec1766b25775db439929b1550734fd8204b77afab09e4251a2e1e123664, + 0x387e51920edf06b64c6bbf3aa91d6de80a4c3a6a55493c4cb038f55ab379b97, + 0x283a3b099b37a60369426569295e1919635a5f557c26e2d9bd62024ed42f6cb1, + 0x3a82b07486a61e769d4f4a9691129b1497ead1ea2dcd4d44fdb626b31fa4c2c, + 0x15aea7b6a44e01bd2a1993a824bb751773d6ff20d3459974f00602982b20f837, + 0x91383aa8ee58024a7d0eaacba661fa0afa042d4490bb02061a005799d8926fd, + 0x1c4738d32fed84629967a249121d25afda758ec66b825730f4c0171f05981826, + 0x5e10a29beb202a5238338a3cb6f3ad81f78d044a791cb03cfd63367678373c7, + 0xe3405582a614f4ec28465cccae382ee3e56fc67f4574846f5a011c2ae4bb316, + 0x13c2e18736871254346e7951da5758a3bfdbaea4a37c62f5204e2d833c9ffec6, + 0xe892a08fd4d17f277eb16d8cf6ea60a8ab263ed317c20970c54e02655bbbd4d, + 0x38c23026542424fca9729f5959d6b7a300d7c8663dc2de7d63c98fb737c885d, + 0x242560875a24ccbded928c30e4c78e28f36975b1767933888f3a3eedc4e56759, + 0xe32ec6d6c80d3bac0aad1635fb195ab640de35ed9e19e60033751b9b17b7938, + 0x127f81d915a7546cb2d35659181f70a31cda6b1c0f011cf3d4d2d908e44755fb, + 0x2feeb1c3f308139ae4f23ced4a2bd3df75c7dbe7ff9d89ab31405ff4e1f88034, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0x1abfd157d65b0faade670c600f964a0582539691f909a27f1342ae7f1d1f1659, + 0x287edf9809122fe7f424748beab604c04270dc4bb549932ab49db3e42ccf675e, + 0x574627cd0b8f02033621b45ee0293376d29811f14dc701b6aac4565c5e2346e, + 0x13be344cefe3cb23d84de26cb8dcef9ec21de4e275675cb81d8e071b52dbbc54, + 0x2bd04c2debf244a79c22c363e0656dca89ee4a641137602268796e048f222ffe, + 0x21671759ce3b7fa3b8dd29ef4be836d011c802e90a5bd2850db423f0b84b8f97, + 0x15e2eca1f4f24c534ee99f492613185b6eee35daa601ef5c73ccc1b2183b5928, + 0x1ac428a1c403acacea5b19eb5a9db448badb082eaf12a0bdb39e33de1b2acff5, + 0x18d056fe0886b5342e70987aa78d6760e87ebf840fce54ab3790159a2359ba63, + 0x103478de82699756c898690ad0431b1a62d0779b072728b2e8f9f1c3dc0fdc44, + 0x3ad3345d4e0b9af20a5acebcd23f067ccd8aad3109ac7d180430242a083bef3, + 0x84a2a0a197a762bd6c633ed789ae1c92af3d189421801e2cff4ca4cb7bb4b9b, + 0xb9fac3f1b5b7769bf369780edeae7d4009586d8eed37df7613d8532240a4b2b, + 0x2b6c5a5b0b2e999c52d385c1ec41bf6fa8bee62c6be1e4896ec6eebcb6577f, + 0x2b891566a83432ef436b4c379f8033c4297d73e413ab6d3dde28a446727d6d01, + 0x215093cbac4cd6a567810f829abc65d556c7c7d81937770546c68fee9b0bc5aa, + 0x59542cf02d9ed7aee0b72da0ec5092043be68c53e4207e4c9d05cdee2620c95, + 0x2c5db84b283b99e21c2d7387fcbd3d71bcc262ceb616379ed537e29d3d4f4511, + 0x23a84bc9d5e7f467120927f9570e3c4646a6ab1d7177df4a0972c42588ea47da, + 0x1af62c1dd6f9e0526f8c4eb716f2cb087122b6efbab08fe32af30d76825c7e59, + 0x240df1209a4dc3cfa2e57e4e0b8369b81ae2d530ee1e022f45476ef3d5541f14, + 0x1d663e716dc9e681f325217cdd3394e128afe26e727a3e74df24263781c370a9, + 0x280935cb8ce696be4fa88e7502cf01612d955d783b8703024a85cc776ba98bb1, + 0x13dcbefa8c14a98bf73e722e6aa233610b00c4687a29badca7ce239074b0b6d8, + 0x10184429c03a6a7dcb093b06a4180cf8c2b1ebe3786a5a58149398a80bf85015, + 0x2b9b91c8e29a94d655338b761838c1698e4b8cb751a103b0a35bca7380413e61, + 0xe8036f74c51d11dfc744f686ee20f62dfb45bf99bbdaf43a5512b087566369d, + 0x1e20b85a64e45febbac3f5fbfbb8b1efc111cd57c8cd56e83dd51bf62a4b2903, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0x27d3fefc3fc713f9ddb2e3fb5a4943e55c336d9881f463532e63bd3257825095, + 0x64c66b3bb1fdcd169d3d15cd51d5f7b598642e290207911002b652693f48a9a, + 0xe9a5387f39fff6e25b4c460cc50c1d9a9d772e889ad7b3d357f016eb7bbaafe, + 0x30372e3fd7ca7cf85f5c5fce64deffc2eb2f6bc1f0f81b9447ced714e4dd47e3, + 0x1c698c1fb76b93d6036f01961482e8db670da8178aa66c57ea8d6f02218046c0, + 0x165745c3218528545f671cd07fe2a521f2cd6a5cc268601b120b9794a583b2f, + 0x1bd6ac92ec06f6ac1f1f348ce1f5608e60679a7a13c7d37f881c147233749072, + 0x646a2c8ed477619f611baf19f5f2315d030d93485d7c72a057d7521b05126cd, + 0xc5d7ece37cb949c5fcf9dfd72b620951ecfa5411f8ac7f9cf6706346077b2ee, + 0xe0f95062611089d30cf1641ef9f5142d5c09677428dde2a5b70990ce98862c1, + 0x1167dfcdef684e802ee0ad2745b448bc9488677fb4a9f21f4306ad438e8a7154, + 0x8b58d9c87ea695ddef4557a17c6c6ce8b34b20ecf1dde355d4f564f529d9e52, + 0x2c0c0c0caa80990aa8b3db0b093748f6d4148b7d56d6ac8448363d592d495bb4, + 0x22cf8f510e15dbb54dd7aaaa9acbb79d93c91caa6790069822f17eadc58f3bee, + 0x1dcbdcc87c651a39a1cbbf4a2429512ef5d3d5d2ef8c2c272bb11943f15dc73f, + 0x268f76f1dcf5f445f31a5c3e2f77f9370f0c039da51a0bcf499e89c50dde72ea, + 0x12ea4be23cef2bc588a2c5d3f0a473d86fe2e62aa05e4993fd8e3c3a04fc81de, + 0xaa8a1b42480a433972000e6b714bd6205cd020e387ab80ce788b4d244893d9b, + 0x9c9635e93ef111fc995b0f41181d644507a96adc5036626025d14c67280340e, + 0x2f19542276afae3f9bf2d8bc1ff25277634b5e44631c88a3ededd309a35fc238, + 0x2bf08e4ad9318465d011b6fad36953dd572e1a06e6ae04acbddcfde42ea6c978, + 0x2e415ee818590fff4a8eba14dc2db89eab455471fcb48723a23d28bd07f22181, + 0x2ba1b1348857a0dddb145fd370c4a5145794b555fe90aaab30eaabbb831e57b2, + 0x2c45b38c22d1834fad94146ecd9e2084fa0801d4d2500d3c9b02dfdae2c686d5, + 0x55fde4fa51238ae151360d0bb3e53d6bc88454434e0a3e7e81886971f44f1bd, + 0x1b500c091d518878d60bb9c1e46487120fafcc07d99070f6abeb94cf72d099c1, + 0x1507c80ac988a1d66a9b7d7e0d489e3dfa903dccdd39cbe30d66e70a4465cfda, + 0x2c5389c4c3d7db5534ec96975e24b341bb8a3950817c95fa6886ffa17e3729ad, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0x220d668f431ca31318ddab3a7d699e1daccc2681c19e28782245bf06aa393eee, + 0xf82c73508a680275741c5449a2108b0b4deabb7adce05695c6a9a56491b09c9, + 0x81d2dcbe555ead7fea3650ec79e20c01aea1bd8694204cfcb53f440ee9f0c4c, + 0x12d6def4feb3b9695f3a33305c190d41b44360fe4f7edec96b9ac2ee5d19d237, + 0x188a70595236991b549396dd83dc110ab7848143320ffbd8bfbb8d067daa0dc2, + 0x1ee5cd9ffc83473d252da6d5f220a32b0f14054ed87e47d163f611b0a03c0500, + 0x336f443081e4e4ef2f80daa0d427376db59a5cd44d09c4ca4fced8213c49792, + 0x2e31f59a54ad75b935c7968deccae44c7651c6989e7a194d8eb75db56f3c8e6e, + 0xfc66fe6e89f9c6b8fcfb1b825a394b791404b4c535db02105a0cf9b814718cb, + 0x19392614602253f18fff6c6add01041fbf1ac573c430bafd1be9d0bed661f9e, + 0x26bc696c9022801b5558f13a240c2f2595cba3d923740bb15f857012d65b4e30, + 0x3e41f8254eea920e176dab66a494aac26a9050a6083321aed3e9c60da60f30f, + 0x277e13cf936573c9ea57fec54bc20dcb76b9bb22e43dd7d3f0c88ccc4350d4cd, + 0x100790eb28152be3bbec49d19719f1e819559e0b83cd3fa5f55b3f11e2ba7c5b, + 0x8a5bcc49a8ef4b71ccba577422b91bf7b0eb873ed4f819a03f84b7b22b3748b, + 0xfe17cdcc7b34315c294c9afd7ada649e535d66e18bf207d0627af9b985f0fc0, + 0x8423e16c6102fbc4eab76ad8b96e75ab86107261c8be93c4fd3312a65ab5bf3, + 0x24659f4e6909f198d2da3d29a4be15ff86b279a012972befc5ab6d55e6d38807, + 0x145fb5febeebb5b6feb24341d5ad656cbe31346d4146c778f495fb1948270c4, + 0x13ad1e400a7375f25b79fffb3e0ad1d1022bfb6eec76f9f2762919eabe8d63ca, + 0x1d087711ceeef2c9423d13cd5d262f9c6d536fb84d1c171bef1feb446ecf88cb, + 0x2a914d202be77991a1357bb453bd09062b6073f195f314e552608fafea4fb38d, + 0x1660b2ad261b31ed9a13147bc1ee06a9f186e70cd619111a21b51b33d2d1169e, + 0x1bcc7790328fa163162a0e8544eed39b1a7a96cd61e0aa49b117ae18af29e75f, + 0x2ac02b109eeacd4b06cb5378f08cb37d622a856d0629fd3bc03d8e2cabe54ea8, + 0x30616182ee240c6e1792a51a9bfe54aa6851cc10b377c468021dccbbfa60a3fa, + 0x37e7fc430f341384ae6aa7f96a7173a91f7d896e77d464e1f8fa8c470e187ac, + 0x2c238e1df2dcb6d7c94bff7c9e3a4951fe54db4e926c431fb6332e3f6ad23da4, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0x200ff178d06931904472b00fe23a8a113d17ceb33d6d0c910068fd5168a541b7, + 0x2c3afc766aee27aad8b1ba9fb14b3d56e2217c9c7e9ad3363d56fe5b31721680, + 0x2128f1a125e0c64edcf0d03a397dbca56375f0fb87ce41480e525c2470391e7d, + 0x9c62fdb776c4fd510eea089910bd2537f8efda0286768d88a2c9ffd4b8151f2, + 0x20426c548d66b90866a7ecd77278c69e33b3d1ab23f0801342e4064b3be82618, + 0x7adcb9b76dfa25de61d2902ce37140c9cfc7d51fb2f8ef8e2317163f06641d9, + 0x914a79c6d02adc94876ebafea2b8e6ada5ac238e7320147fdfda370afed4e94, + 0x3a5d3e37105e1d08281bb2840176dc462a386409ac1e7eac82be7dba931e9a8, + 0x12aa83b029bfb3b8f742e689995ddf71c0aa28984dc073e73a38aa8dd8a72de8, + 0x1b293978db1884bd8802eb86d98477a690036f148d0a07b165b9437a87c8d30, + 0x29f5d2ca3bbe30251e5228e63e1eed9c906c4d98647410c4a3c74315101fd5ff, + 0x7bf47ac1aeee2ae48457ad8031ce6b2c072a65acac7427ef29ec2166c2d1f1f, + 0x1316c94951ec5aa5a37e96922334dc116d22f3e3fb219f8195e25d93e62d282e, + 0xe5a891e769da4c1b0d10fbde39d81225fa6c48216717edfbd9443541130abd1, + 0x10a84451b6d2e943ef60255bb33321f4d3eae64981695a27bd75d7c72cd85d, + 0x344e6fa9e638ded4d99a92b2dae4381ab2401aefd50558fd8ea90764cade9b3, + 0x28a513ee6230bebef34ead9978b224ec3d8f252f2c3956a781854d04a293d5a4, + 0x1e21c489a47bf56a811404304e04714ece44f376ce998e3499ba91fbcb0fd207, + 0x2563badf855b5dd41a35570028bf5d97e9430a60962fba0441d52860765a4120, + 0x209333ede8112c2a18bed033eec46e7899c53627cbe5d7ff49e932455ab51612, + 0x1b740c4dce2fa0cf3af1053e8da92456db1f2e31c99caa6918c8297e3350fe88, + 0x2310a0173db9d135f259497b3f27551d01feb64d4e0cf2233f7823c8d4e16219, + 0x2362c8df290b748b65a8680c1ce2c43c5fa82837c5f84f8107c12ca823709f6, + 0x24bf53879bc6be25827e47537248702baa3a4773fb5c17476e142e70ab17cb69, + 0x193b4986cecdda54bf346868bb20f1d62e3e795ae49a775191a01eaa4bf095af, + 0x171de60c3b1f06108a0ea4c621016c0400fc9b96af211250f9c25062aa3f971c, + 0x170208c0bb8840367fc496ede9af48ef98913cc6800a76318fd8fef208860c19, + 0x19305439f5cd0d17d75d1981b097bf61709a427cc09e83e6e983b41bdee4d8ab, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0x14d4a3a0742364a9f659b29349bfa5455751e48da07705179afb0d01e8989db, + 0x14507c7d18dbf71926567faf318f25bae7d15d1627e930fbef4dc76068a1eb9a, + 0xab92e37d54cdf29da56dfe18704f6517ee8894c9db8e42ac9d3f8c80009e6de, + 0xd3a5cce50b706d0e2d5ab6d99cc5ee19d414a99901ae56d8ed2b90c70161473, + 0x1faacbc551048977f44fdf37a9c68496027dfb6de98761ce68087ca0892cf084, + 0x82e2d6fbcfedb2a32622e4c9f6d4ced6cf0a570062df9b838c4684f4a8f6c2a, + 0x15345de0a699ca5370e036b6b65ee4d4d3412d46901b471ca44787cfba69d203, + 0x125429d4185d9e71c4e428cc2cd6b98da229e56e941f37b846d46c6dfccba94e, + 0x10f072b77d74f20ba0d03b4115303bf37ea98a20a51f03b54756e770e3503601, + 0x3a5a00dddccd6eaa0b88cc6ab2ef6b0452a206a04bb5bf2361baa3f2136b2dc, + 0x301071c4a6d3e6b3e274dd6ecd6f5889e65e92dcb190e6980d8765f946ea5ff7, + 0x497842511b8c65d38dd10ea79c157976239b771f5ee8a72930b45c15b0ce6e4, + 0x1a7f3811571bf5bcd0786a27a61702e4165a02f734965b52996a6cbc1abf6248, + 0x29b6c15ea8aacdc694b94efd98045716dc81aa60c6ae224970ebd0395a6c2039, + 0x1ac6bb7492d1e4f715604b57a281164ac925c56efc0cd0fe495e189914f1478a, + 0x1671405a7351ef20e4b093337091a308e1858d50656a24a08993b416dd0750d5, + 0x29784e4a72baef66066c6b4a580e5ee0d6010543ff0edf90ae6177bccbe3f34a, + 0x15bb878d0c3129d4ae1e3203a7e88cd90f025c8ba652403e8be7241c2908a334, + 0x145ff66f889d0eba5e243c1c4780f5ccefc25775a82f555aa6acfbb1e6f44792, + 0x2397dc005d52a49fe64bcc7e71398f4668e4b1d7d23e2cd41f5a240b7fd2015a, + 0x104fae947bc81f5ebb40171e9ce8e51d91d558d686cb92d39ab245db3b7f980d, + 0x11d92195df064b6bc2f2702af25e1d57a49adc4774f769d32b632ad5cb29c38a, + 0x1de8fb3988b840fedd6f1ec8f4156fdcadb7781b895ac7267ff16635a57cfa81, + 0x27089624e599b1c50dcca8257a778965238f557d50adeee696f52f5656affbdf, + 0x1e5b7ee2346227404b1492732b5e6f36722d8bb7c99f2ad8f48c6123519218c1, + 0x44744daf2989bde9d3d36878bbd2116fb0e6f03f36ec8c360ac7180c6a87a9c, + 0x18b6b8ae538910b9634a54cc1903d21f0e9a4626abe012f424ff26e7a4f389db, + 0x1ea586928d1078d44a1a4bdbd2e566b924a14187c428717894ec06f47d01269e, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0x299ee7098c20a8d8485fb78b37b5794235fb37625243103d86edaac65fe67351, + 0x173d58cc84bfde0327aa48c131cab0183f9b471f25ecfff26cd950bfb4c4f744, + 0x163536baa734cee7b3ed0d01cf2dbefdfa8e8f5b26e6fe1eac9411f87cfbdb7e, + 0xc348237f64f9f76bae51d147a191aa505fa9134ddf66975b7f54ca99b377894, + 0x23efe24fb00b171697d7a06849d9eac5e14e032631c17ac0dfd273eecbaaa293, + 0x1e7878f760e864ef15b4039e253047ddee33b082b6e3ec3828e35c184d455a66, + 0x2bef7ad013467126fe0cd58abb1dc92d50314c8ae9410163fbf8c886f86fe02a, + 0x2202801fc79b3c1ce769d85ac6bbe8b8225e81bad63c2a26fdbd813eab14a147, + 0x12a9c7120c9ac72e58a53bec642e04890a20bd2080b06717d971c5cbc74e9d31, + 0x2dc68da29a775c40fe59bfb40d1bf330871f453995f7cdef71b67e14356086e1, + 0x110afe2764fc7945d4fb2f8bee04cf7b8cb3859bf62c54bb37d0cbbc8fa283e5, + 0x21ef54ad10c3962befed62137a17e8cca0ef4476d68f57cb31290cbd089e9123, + 0x1c4faa0f27dd17f4d20fc930a295dc90afe4b2b319b72c7ab3d5d67fd659a716, + 0x496dac1141cce7811aa16c3cc7ee5bf926b19b57e4c2a3fef441f6a4f3e5e0f, + 0x1124c584f931153f9eb51cc7bf62a908c7d935eeac92ad89be0cf7b3b70bf0a5, + 0xd60e7160e15c49ac0535919cfe58b9bba626b7a560d187d93c02a2013d7a25b, + 0x1fb86c2a75e7eb166c625ae15189b3395bbac9ca27fc7140420929c57f254dfe, + 0x302e9af922d3af8a056f402150e34809253afae3405b769561958e2ece0eb937, + 0x208a3e5caddbd869846894744991f2d5b855cf126f2fbd0da3c7655f6c44e6a7, + 0xfd167a0ef538adf695b83b0c7e2b65edf204f994296f4154adcb45d5afbd5cb, + 0x1231fcf2898720a22a2a98204af8bc2b06e0cf72daacaac1af1b08d1310e2b30, + 0xad52af94770e15ede8be17b72e4f2bc1bfe73902d78b7f3a52a254898131b43, + 0x63dedd90276c2738935a71b3acef9d2f2dd3b9bd49e54ea8b62261422d3d77d, + 0xf58416b4af85510a6f3becec11d8db6c097194ed62d4a04e5a2a295011a3bff, + 0x15933b922f212592a806daee6209c9a02ecb21ce2bfdb1353862d7629df1ef97, + 0x1228654cad70cfa7a1f1f30b4cb5d9279d2f49bfc233411477c333cb630256b6, + 0x1b099efaf6a089382b0231daf9a65505b77b54b6af4491365b9316f988bcdca6, + 0x75756cb31cafce46aff3d873280c21ab9253a0c587f5a5e107364178091e73b, + 0x4523bf1a8f284c6d95b310dec2b54e0e00e59b571dd9d46b6201c18e1b56dfe, + 0x2e36976f35a34be56bf3881e93370f08203d1f8b0be967cad4ccf4d9d2c83c52, + 0x1650b34e0e8b2ad5ab5de19ff253eaf6dcd3e20d22bc69539c834437e0888513, + 0x2154f3f4c1b5b2a42078df70bd1c6b4f042ed01adcefe5b603b4830008715af8, + 0x281286cb63e657f78e369c0f6db3c980cdab1e57fdcf32505ccc325e7a9e8c40, + 0x3008b3f202e3d206436f7dac2412d51744cccbc8e1ac457c11e0faf6d6060cf2, + 0x2c0268fe5d032bcf88a2803e4ddd2f3e1dbfb58915b47d0fca518043272d5b27, + 0x22e8ab4fa7bac348cedbcfd376a8ec6512fdf78adf936f6548594d6584953227, + 0xbf717c0f092d04fa4598afbcc898ccbcdea3eb9d3d1f5042b0f325ebd57028, + 0x1f500e6028390530690b82421f359563c768803db6fb3d0135c5366c9cae12c1, + 0x1b9881d9fb9346520e1e411de0696df0a4dac3684a15c02154dc0e7fae528484, + 0x24ecaab85ce3beec4c380c207c564f4ba6995c3290f2766a89b73010eacfca19, + 0x756a8ad9f562abf2600b8dc808abe6a2bfb0d4352824251e07be2c0e64dca67, + 0x2a1d50d0f3da33a873e9dd5e5e2966bd40445c1e6eb9504dd4b276ecfa0b318c, + 0x1fad2242540d4366495a5ad4fb69ad25b8261d2e1ee56d56669be07686e9217d, + 0x113ad8b46c3eec20c9965b5a7b2e8a51529871d0401b4de6f63de9e5211623e2, + 0x1fc50a16dbdfa1c3b99038f47f81a1c5d1ef6e7b221d4ccca6e821220130e000, + 0x1214a9d6d7288fe85651a8cb83048c7669c83b5ed82ca2642fff01e852a44b4a, + 0xd421a7c25af5538788f49475836712af5da156f88c5867568cd958e305026cc, + 0x2de8ba83d2b6ab6a711fb9230adee1cba46de8c930c86d266acb8c1cb9684e24, + 0xea7be82f1cb493b1bbd83ab7ca285bf0a1559ea05c3f59827b3b013d0a91fb2, + 0x1e3ae7e5775d352651d713ebdfcebf9ca8e905cfb792bf7874239450f914c8c5, + 0x5943e3618a32cf050018a4e2375f4d027b8c14ac82a0de57cbb90c5122a64b4, + 0x603755180f66e98215d61e5346b116cc00cfd058274d7d969b3af95e78bb335, + 0x19817db66fdb8215ecf70476c4044c3f41d78ac5a549c684e35845947dca0b11, + 0x73965f7a9ba8cb33a955d42da55fd7c37a3f0226b029d36dcb3fbea95d642f3, + 0x9a550431430846b6694125b5642b00607f36a1a29485361a3cf427da77eccd0, + 0x68eb4e9d6e0a588b61a6ad501f380da0f009067666c0853d156e33d59c43515, + 0x225e00a0da5a7f7496b70d0923a7cf7ff332bff06958cc0f3fad439874f6024d + ] ) } + // noir-fmt:ignore -pub fn x5_16_config() -> PoseidonConfig<1152, 256> { +pub fn x5_16_config() -> PoseidonConfig<16, 192, 1984> { config( 16, 8, 64, alpha(), - [8089493102530595468824649860529717181797071865148765611726566631095271469313,14191702863884040950201894968554909828474263688190658890761244249722339089253,7127251756910107506817428481560230656411897313679770455026102671367474097624,4637045655841785226199626823170615348821917492997807409130873179711115857270,20694397780982417522377524687614391225351058648522092200738043379276991211973,7370528537006777008458800981771544164650999525791518443407240929647301337224,8357863226135085648491488089966537213596680483394798064376015085804610201240,20367087512494301090653054692863377975501664994817680661442168333644299005261,1950307616347822794878104597377932622958317394806719432040871827549672571148,19534568412595886801081532478416580190048212177563706092280027206347120417736,3526428150493332211163778868665379218281231008068537115657136020226387337771,8661888879209475483716403816709663500534119170711151152467249807886559994385,2374871949454649266019269203973683966955509927334059254254180194157352943840,2602346264611026079459352146265308073912201263350931622963181149514761751618,16750875216633927741061710170647391823629779494283192027015930006045661350833,17325348607596842041611786882495470980592459865615213806942169413086586278610,19257833407854296241609506861086921463964253377452883026082737974007723285939,16875536222414380047765946704936299627494679557426090013440678117262080229388,2035577529925145134060996791483051399276402053645795728801937468290487364296,14222296831200170749164428995066771764920247405996747821740895709606052517407,19708208883712347371628256596476366883171584832295648266624355950215220127904,9765600454835189412776212142789582666145342479104764891694616693066517922502,13365055082376018935548592209736650793571432301565333849832704476237136996118,12420692692663472732723794387493491467146971343430969855362995088112286983728,17844493444787722109223680249951335211927705850925719012603471955916755628715,11924944537382281343613401541176014853361783437608625866798343540969055542140,11538333989403053525558050588509973706031711021450280471202165095037142068477,18764881783775503232423409005005138632447539466481045749407270569758537393398,883162740610443285913150132085694648635519837269866659825930623017971541006,10171610390436513861069093903522467940290613868370765425375996220687957422386,3782996878040749700177878799895260702330488343333700969514291046490113056911,2239298968343190621001798397134314102896115970272480212453695048745962826317,8391302051404015178833807081994898536482484463022532956140929200199667853077,18096164030411129129794470313655227930799185448547884977984818798794318221345,14613424916575212836238688482051323957035101724778773648452919665593660234946,21828842930708391060823304507355770719075227415675853536112390374449711667078,16155169369395425892836659730715232159396910561858841286007416017756724971516,6878543234699575736262375462702866780772252779651204219697567141737826275015,6515580357485419559928692633356133128461299871887195169242750902403019378404,3124270150531482035695013416051086970123461406854560487654035672981879561715,10574698281815682641771693421115734396172155905702803455639975437772362072107,16383053320907906491543185419013182425229207444535577699313377451249772804551,14128602818455692582904557734609240140547347183347545360942329621911511704432,5010441108136365108046592406551529565385874487432431586303802326844966531017,20105162467673383983751690623903949493335895059047083944279780871549558030082,4243524359837792598965046978953117623831146922720880550516255054678204683627,13992943040313469850370025986460260524555943628212884466234808367632688288666,1356223459509978352432345061666791804860823828908318470584528377749655994659,18723939192823222870283999271398340959482157197116460943968917507878394278385,20636603031793247786862933945150382157149390912061952007323929980504212222032,2128636310217902240014588202116301452804441854659460379597999718252532068242,8892458127594737495267008183431736534386964959413452688074230438040504386190,11063574691797903196312547816101464620325790434381460261930676459857164737407,6204567085759054728130072959301910137692879386674785283047171198023995380593,801138962072186678791979363551434811728526970692377261272697294596118718403,12941641588837981062781447688458784558606932072335320068724403816548547438675,1341967686547656677059175660053506857201298028878352128737987225407679621418,11183207447266717668611438117401741351804062326702937903525908319309155043524,18507917680426998547390822933408085624123062783706353845158832700169805897057,17600956758590554476691669608345000941959084040124470813766683278150335958657,483394656899715242498310209793599026850663551066988094136788591643990355221,10090827432001200203094010206359607863114405903353400294360808239534902160627,10039403020393871677252553778177538625214464462052976366251977746523421324197,1924712848258707645798108847678093621275398467857399987976700805356929290674,2167923809975069342404582706442301809782773089534518796665536897555762931998,17151337466618795643803903749019481111634005237742283518609358703199930418386,4693404918498880046514671012411195415185134287680728307646808116832211396470,4839381186041991439202094011010050618021148651243083039175474529769659591768,6368336559448535344096548979708211013055912139451892726345028976601375052582,1969826462127986113899121152613324197819709993940588880171966228829834184618,10949071784553227115382687140318153702912633728202525040498248461299029092720,14575837988956266060370685891330921140979730144767405243152428616625585430364,19025750374860322288379311751788635906611708349625974065695544669443137256255,8764838805814072278932908632105809429351124473407135322177352737762640822858,9508966145895699172941574119083482387827406291145211775810415653335356563307,1499853062814132179278896768948580432185360181707926223121987796423000161587,6748895423937754323870965728722563272366114856617067613970193226138372983547,9814536604142267489967579335173323116472525708739068285104384748406479290252,18898551978119284539473648820403307265793266184829523824179430658011490726286,13332891294455702171134399009213907075208764727059236543259960129130320074982,5806223588823614408610900761814632517803554600662169829453323047489266087405,8600992771060584427141790133616651912076186875693672268259185811464115092188,2345229032656719135417406942532115442859563039531904661440827899574284256939,3389225209359511603097670682835778418062727662626674404140526378611375444627,4001034682434006987902788179906586121095610380401857294704332109514659937637,13067063794999809131589470979742146742674772176859338210659998590141023560073,6021149641876662294720012642501582990883570287510418620500730995186581678990,19744062936660555217694711756418639275110313106982456779211457821487189038259,4280146833782122185864346406516267200729946534205141990397627632307276252746,461380210352497258096433274264553487092816458993207056498455795007735775326,9185904966475190600688426658264723956468287249470549941528026771035049026029,14362213733702712122544208087232387435453213772974406963783416068708716342186,3376133122839395926880247692021311631985267298172444834121553500975764354590,15430636928872496244042298024957854104479533547499980110816885404855993587926,10066678820787654667318707571747478964216410231002799394324814978870300697084,13679726663800139966289976616317518761749708307387522908283736372782010246091,14452498713182028708607687209189129972318024710956800636750706657647839477841,4665977443169087186016514814881141858109411469723890078365751966690257156734,20673947333628935106924449469424554002781432367358546714606202194020160454893,8371937803667063739943392730412639954872585103736021824547232324141910768530,4915642891224254203187535229956007243890165147322145197624420790022741880987,17737894427474715513464524059598818432164911920893615068415915800842574129123,21257751286440468433003251296883236318376753833102432675015194790356307947025,11831044910484530710733100158936923549935832556815349526083442021617595246222,6362553671302097483758288321671356788227750730995074141338726755028234269753,14935971406087488699083625022278942628959200513244202282294495763807242526556,15337281352851760799121170871115742187805714822038335053341937333897883894609,11913020597445264316110942608419581486071629740611054234626537590474050938474,1838104841451540707239841220222372684744879960533787766800248740162155353463,12200586110950172266226854658183951607066336178441918240404611233042731023944,19022187774400544497696484163376638844589760125070799280660843859892595613745,20574219232807646025576258258887918895888511977194786423008507430088227970769,16786939539299167614623107235117810634408742454195124075763115939760135086779,17293110551721019748567259052064171353712124247596873005371071440209356535788,3515336831584582569659665150343000056186787768627351931657274076732504326799,281425181255898711371985357453012506419817930424882315501470435479210893648,12703632225346671660598644961986122293501524448004046573092229475506828991982,5589259102510829346047060861494427710966525350274659545392525201677772096380,16136155264962057601674035851031539132207654054954939479993843931937787809008,6577810342827559587628942717478127045802616172145914985109615391025970118111,21163359977438641650165237544426961690819476598192610702649950529921750524674,20111680006656824813833529237249851680178501017371275377838319189183351852836,5575615948519348213741695691025005079345478514823636124237182535409145360452,5523844323060926872300411712160500242292621601876678751811292002367512597282,2341781247790586645587607723874752210647545627417738353111026163429313125329,6287726121450538785847268284295299220404766172163996260292255850387839422364,7510648235102286772333427364079209113816404370140168905255311267436378725194,5010598474035699846534727472507206499428871255705467310762876793528248455251,5700900579731011250748267725185425351062102227041063523439252105791254824347,260864497479086430816275699586473497971665832148788274905912958670548982986,789172560806161139006535038197594038879692565830598745604163919464033838458,8100205286609553283468855217617464988341806863414698413875768149192804914582,8832923720458983936387697888604823914542155000760959167380458346468815941677,16408716740290439442219096309603613006830415688534254451854294128560591562449,1113287770802944863484309232492725673552460311886837538428140710794437752025,6321319205351235108330320300049882062942831936257890309503365991814791003082,18560922321672258596191688202021423732168869299915307979899958586924038420673,5189180998718572459539043290302679421565915950138990634526371489122263353689,21059088895950142731136323564720383671175925416797251043903234558355128937274,1758538453070760465213341124871446098960577889968251388551632606564361922354,8880106936008308891697048583874212287093823544613405494775675377028797786924,478113991762053058066048308336221551443374933771727184756201865704929054005,5364027562586142278013801938849728210749918309705526248720112356632858758221,16060418035757996187280816105829974246762721308664137780198420107462005497738,5211176330971465153824216149376981285606706263050338982115099875409328929990,10368007546243825628853187421535635929255384415227635572356066208437184727920,11427684168459596442778160390157786957054817508127224050241732612892526145073,18949700777601180659579150208396846544227381511915556752893455904600581402034,7164876529024763696100437397763470424696261670104386888341279210050743231742,11672893202716354350665939605724566655297144836947407230492353459173601370992,3909710158111676258105703555994764863745260060728195069107924779522169147903,11345007057187618276350650167405783488453459256756441881422153715183450077456,16177820285119478894470005926103825065477859050875380004945625842748711696023,14605787997931757094644238801452595674783310674883843033832086542610678460710,8394271758834499906719701243007064560791869846306715272114566194508664069904,21873434283102736245937985212570921154785039540401524103800440576512828034687,5288693737755970825903341313388382553570352630888453317445067182115774973600,21527468641133089700262079461319550104586512157305923587305104390806741900810,20906707665998407830558869509347677772600060055286961495556134628147066213175,12592377229521260472205372896527756013482774884841906928184642093380092134349,12910817347876296654185371831758099341950752668436921762585644650086702363745,19707023277054651202681442144426045379962145417802880101371794305270012080065,5370501568233094600905283140114160955385907390235753857797923590879732764547,4893525410028747500809250162311718717246192757157339358355279414251440821369,16933412769230696712087772684638356779344465843185712014276708361284654443016,14752252971762751211424871408209457845535321896357466404820315342528474475265,4381439374316418237204510331759065345075613480172639747277311241150560517970,18983302468109324889867853797358234303151484569217755559414917991855202421044,1720853637877748574561923069656227402993841601703014320322493127808042278354,18055674086054269831422192610284879350534759472987936156359168085840018213729,10022985435599924530950214242280707656465340100733875531414649379326713485700,19489289237398317489155396973411927208825921597467958674111652983018260376467,2483969152386321683533021854216836603663579724438750369420802837936459253247,7096495647820661985493920714559517131838710818830485847136203068929085317377,11239734991193991562092142618442979132467959527040707676033760692044595660477,13964689425465688308583323493745924709191744803740806305195114536185949582431,16765583167493792488003846249322412563932361325466895848165782639635509252698,9258699025821383775657130802030622351199780460158138938453769223645462201380,7261743362549790776698831974802523106349906457536556119083744106556343806039,12174595715224479314914773177369125156875875973781826642881907250708051936707,5012109434360646519756574765661145101042498088812514145017131935992653466441,4700224901573028234520633038757562359543812027452948633531739331172070339917,5524276305760203869547781419982228286567487292869238897177777816144717638402,17095081617164642751160867282346616888601375485714887290060713493809720024377,13598351826191942256399407492736185075239065075291047608049023984461266141081,17308136644455825036504551600136601372687794695239587014243640872267542984788,21730115551932424945388178787861491256026727823117641122401508483473017057216,5949879858200957394974414439063213931632579243992797429658708423363937192395,12803563373135008849577150591968062878999687541475931973931310610530915756774,6197313147432278847012935526443261694774265540021863115632496255704682355001,7028974783929794816060380650452873559926928309476428464943277081506765913122,4456589108827474318002287720505015907920793224049488679883557016295128273089,6100631380538490803600079371988603006023173019183128962118450543769518343550,20177888580254527519697427670797609876974132471313961205784103868094735572841,12073238358529645427878918495905605836088922482621503239707831646933770345610,21856100081180867115422179532992210187999850914786148325024530634866939637660,12466984235357303385071417632152615871825808908890287534009467031177378240877,21079839629488810269856967110699842674750899640941851601070908540874579869846,17874776547285892135748821889881943162098691701279199858985484844123833691703,1051310306073108765618056817409777616413695911463346454738615844650030082984,13201928900083471438265807470373218252839081683324776881761206414378175945385,10190119257010511211543154766347424644241552289850760573785222226686792626364,4688333485355359912766058497543573340825697092661609637162867722200016624599,17123765906835174464437643379916457993692257252235548439872663365295598699138,17134395901615480964750415429455088485278477136528521479550104193427850309670,17940167838269540610857156370913968688439335297994033024607831012271846654207,17211561414938780959438190369003172382648707317417933395371238331823656001285,16098871745352156970746489901084198750790375003919623885201193800062775011577,8110023901773238127710250492301336333009382423651067999842110155158638763822,2422126936887420595943345532312996428472865746519279257114791700143799243285,10404075183720133448708607844137643895914849868988851944394714021532771347787,15058460651933569411128043696753704901683095219148372416995175617698935925786,12723555146577954839266714779606964953587444931552430067661560518513484316738,5711657581065990142612711893585463369566607394626940266394184697079173482347,536257458004844094090200378771107142207864145916201798362001449936167413480,16904097338561724274235483260490381087656469057354151613747001642006805270380,5885951988825802528717928331501311151617037953699202264796404860914064325522,1638374036867203230684496314040773233229976276864977417441853704948079389600,12231982678049991867660964493898657015614690001085229646831798098083877705620,15427058040900308626278462505422407030810836290013997730209614367042825008816,8287021582226423932765127558352821849475385690410389396789209560743363809623,1082920048469231434960727235146664410555571531264546962637788898495946680112,12010985569823806398477426440616395624594456642130882649075614403521532359981,1296330560506042268524168200578272313263311415565810607634491211599523487141,13952994457760775342452243315330031022436205430079469228726234965837656704462,16985743548885988875181345488907967382109958231690477723834234297604193256890,18108965571078287240054765173491615799731924163046353815744437352944165909003,767530387704511846542067425779936904920481384673999726390798572580115466105,13028307645272598127894992332463015335938472044187733546491605798735426870634,7618140648066747223455845067208730203353985191563779819124185938438241329003,9331096408013670718143367691921833484100954507332698681105640867440874379095,18801244145798024592964955007270988394935375648640247134868164095028295260248,3795459656522732094044639001176736675357207553263371458375866920248726997086,837603424793724140470838171288512417218344963365692836088493443407197621528,5831962429370013799978251611601242499647911352287066127245255213245836916243,15608629818832866779793800587027419050315344573115273720682841552596629193016,1032806196152635164955947370516112750756471391006183599859124038948506281039,15696208732714216759620197747787990886188845785832889089576996959760026394301,7234583861372635173862436546128104054595325252312930586077823639855585372879,9351673222157837029929340587547626334173727344379333167413124993232252858910,9944025695384518607461067522154717153892207999526158631473359210163311199905,2388456762928315498284690717786606118379553818175612967295585468860359388241,8762894023280585818322989976434413098781364467068028456427186735232945062041,3982990592887978322236356963193527056120817698005386105106663667178275102339,15305580827228104504176089928458181616132990558748682555478070517971443343847,19329984412710376451608868772829323267202139442902035837598118892290482040500,16858720166203416564086563387111926247316950607110418622245689767918477559853,18241191751089003023961171787624834962373436019307905123520202159673396473314,4235718345809909430818933555490446039661741163040234575769526351800272747420,19336790216312697816897624746946849815032853517670504993859895524588720552146,5833407345693372936993877824926303626341316298366978224289402960052763586750,1246029211601050773151495439169819001283925818386531745942667315981536442422,15220086581176169769190817430254624676596374261069714496878816359393753960898,2365861900029834138601812494207710261363070950725532631535675557556177296586,11098939996500166020441603457997996414027684936264124308565274744828953147961,10188381420146390141161084654671015083379584925005132911919536024814384766817,4842017639583023386245773507388835267437650777401251470903076835565728725044,2473142702350888708640145449504461869356502285425231033191892981515210840933,3420689338060147901034254227618353913575873772273264928595432321920193621195,17283074258384994096612354354366039962078336488852681769982384814157770475001,21006196209784588036771700052971738964442512933084691689593009338899209077510,18493924441589584713280363204662484496255740376612784432044649586411869984552,18050342602178255577111253065667811034294368946566845729063425104069824407598,3678841436690736561960339537207788725774745841190361109044779271967419319179,7229032436003943468306271354423246592397907094971085338195794532946516086746,6074543407778673702938004547803408348112315194664133731027958879041743082105,20066840392762178519205386382693042859978931394221116082945207576871299356172,7392805501563984757154630589230967797392843859128971344647830779113836888313,12821992933916071670969878929371658252743368422895791718047075564423909142719,17668945380988406358182777882021562738916627352451654449781528301527115094220,11046977583853814151360987998476416244370762366051844251247672138778958746421,14002539550635338734484852844372585460419306414704948112807545053902011590061,6606166606298514036368338857611676551502463523513184670555953533985389963443,5446061818493011809543734117506203755719984305445968514525154959975352640311,1111668700238284277732413088411620500087954609586256178652323895010927817926,14149444834268176201304046807022441432518948094788616136522350328948362984806,11145589672768136991149928307436511325152474561287303838823870178226307903252,10735913608001838681702607049464645919999926391398426712273901727922068271016,21604506935173200936527132172076877500255612688310066661071635553990139487164,15839861321575777225084554553361389979179161218821903561853968278717519007256,4119757287481158134674144154651639875410119871143992982693366998676854632059,21215853876753845584435912754954004476252409742434691973232278809063267703513,6474112081529376586123095858950370103982143188298415134572081362206457634840,9652012486829416433331453480518336590399776148133427672040049807230079809918,15197188648271522366095502604900923401004235531330211517976306351199244466155,20653133196783868133525869637730316323485671920172550159454294692576016995406,5372382735415117884334788700701478755716540017619541377211078296573383620529,13207488856826369213621681118482759531513035177166234417284384049787214456366,9796874023172008376751307392327706745295558991768659529793122654595100420492,9923897870015737084413253850361127061692788482930375413255676958440886663490,20345695890485642585927456012849850866425595188379347054737827588286474285546,5970363931303429796131779726714445177344307738485323531135738898520018230730,11099832493605970375935052305980301651220466371839450598182845139430995541342,3984084259485258180085200952180050171170098877962423607492480207306084313759,14795772399510400766677766636479617776597353783628606580152075755214440944984,12411649494499018184602448007465543838785542392797557004957418343044512599298,16626394877225947777126043865023393002546807148362691512796749460115071596438,19056586788697785123807358806982924302021705802715675015657752728604200366151,4434453689868848221439283056960830923558217744100875597646474729523600908085,1558497076513757145941997689136111603376893591128645477322800957597462648163,19855312204158524284458047353907697917092904349885231039917644721609392348549,14296610840588714282305996857377052531476403374009704740496611471123591762688,4255702919775232787836264045412364184259731261431115977947396605020618214051,11933778709913818332041068411271656949772987367132405709674023277986614336789,17039721891026771364303633162265090865698196106396237296534502784700270974342,17677496806049413057414389850646660368467945835594987026827101037177591654389,870853693457310346529819971157542197768087609061398183617507613118675541833,18050709179661944189572532609164386192084249162773126990656248077533050260547,12509892200475964347152748879404468874956023169504780638942472032501158691943,21290469710465436947459252705329759527038443945558987181251205171276803887919,11697948989002333965655987240828667368730889495575710652080571936823918605037,8736925166569662118997397920658489847012314542439353474077461070832299486573,15840706598368315931966990863663232282633707371020640698077565307266653295218,2336556619780315190172318504866216965057876522664932909981631800248874766723,3401386693708589750154291055903211427275255738949699968058464589080271508279,2985234144487193053560662812519604867522985647272968908108472491424983944847,4708870044417079288579972819522537183137753616055169595344370650267781985451,14922125937386550210569417108464732470846637538443952204254988396764974305556,21120247382250540544939703044577215089934389719849213503558017786742393072448,2316928219829771701890891437885406935408196453098584469128414556890718887397,6617231706636202699892427347447707304283374531129890683057423079735568483257,8090371166463272188656489380541987815472988984318384965972491395697937697839,15553944362864127106455863696894507934518908899701997904436263710171474812555,13969363969212770297664533823398202808376213044430873505018872984372178723135,12323663899898371993768411530695190245261583246438004058508426675150745422627,16566875439359417854141203050455423662432117146587478868034846190942245403701,2085197407488705803446596939115235993629808393250087488250514287409223581616,3353163139852271259915937989527822937141797275129253304946488349312180510876,12046433326685614994434242499247496702084910418498830651483913063626259071609,14532850787151304296314608701306827699237853461438425922459530673831764439726,1248026383149472348014634990743396120794718445584945878307644249641199424325,8057577408830637105543973735712037717868264099646638037329061041095961932706,483318248530006664922961695058460281946793595997210254862751288308569479187,7597115662868588435202039449596982590007976221501668730777779068799655592123,20576588045443131888269350588198092656950342341724106762422448997215666028156,1519447772833782137513870714676314005111021965782273965574223992106447841589,4564008647036378562957325007261730909909040333020122431007246472496053026801,20058604285923748821870861850977236730661592466138938301165874489677433369725,7444135345158592582936132362592519965410456021574373937334236087846829245911,2619748000882337075816263795535027848943303678661676628903586805250445194179,16416961968137667392446268131224700809614764673462182053193218154672694280838,11133666903754924307114887742321725054257211678992195923482419349863465176820,18185607668620497969429683073093259678523061297809671850245875139394070019601,21100277417778348195596070047101971906596351310455360764416675735903158404363,19242696527172349562445561603976204919773321047775511674132373901693664836452,17641599298698108341739444819055281386405281781490793437098263180756526877861,3867854105746657505538112984381791148258872175005817045777653312620913799165,13673929044343556285939637616797217757029992003977067790150536754605693560092,1413616068844936743999269099411394796998593026467324669628149625629672193659,17182247321635044788965517464433108044764735758956097220834338897775232927292,20369403412607032840251975012855741679474191692713337906759271231600952698270,3368021137971787382116663997287877185273428758197831072626886100000321343009,4058882993633327642712241699549337354407965426094339469485649412411970892252,16745738472558294852806571713586420783108275141805815749526145532281107769806,15581910313143599067008775890965264886765882549739040775187928885624726340064,18274240790635707268508029122006654280996256674828118427269328392146795445159,20233611060321484677112349983942832171860822463387331585688221516502467246411,9578794697709092641086862842633192064390680557390699768090648655701242260988,2852999879330450264744202807076238853213578558186322493583347517686662265691,10741465223456896033565854764716115079295016404042872162238148987621341827594,1287682441013790555075762279132093640356858755666376578858076731440259199594,2754348824392215081276565702993043505186786457070961060283939332925679390910,11228376276796390660691597656113154929593350154734497204665175991737933493193,3311568804745845654494413785473574358224291288129470978720234105131364795989,13909323234259677397453192122165186938471237491769110758142097116703508140857,16483726454860443352311561107200491233365512138292033674515348800113826861405,9812016698744294015002456058504358834959473085649393839832264042031387688048,15177982625372891489410897122382147270421146795964397363826406495667593673282,7519222254582187388553575935727848524972644886624855076224718541180666103816,8301393036521557606902463799168007719863879180990998631543603658427343679902,12294426767414989378173056202553334768408199886443392931845979330633289559578,6739869506728400044391551988623920236526787529007157619233939477743084008138,20069013437903411974438964103206724858007754851513756279456345172264534005155,2018834934981362435424318060070780595968114685660751661802811774334240763265,9403754976005906248280231838299490163038233707814936394634595857779528197369,10417979303761863711608825801177810340012849177958033395021985945544086842565,19604977682052360618680964990952175014659495782934855476845092758883928933035,2688418347826037364876739676610309530415711729219616027453603183128414252617,19429655781202385023906019671461539686080096105536288714975255299583443223945,21850552082723421744247018249567438591533518178485575560955887428084379635362,5617579950805240697000723938792084314286755653766678432489519653418680110671,9555670299297105865403034351288164766308791892391888668326102655956067266166,11495978801695516791606532228534536491719831441531647897999875880662918322774,13446240540987488159401062110915298027617715146895881354765875946092155869706,7830137135198409572038952404379496414181899227574329472045729197166487746395,9556039398803760338966955211123892534270670688829455928022562515996727400498,16536848921900120010270774925810022257466132951671306792158048247185847693295,14984883995702583492812943326719347992462648669814085270913355351041523830317,4449876409800178139287642958372279285293173800225271693328528758341654973266,7254404965814435397385340781449208987509307430022649779312503908065673947649,13482540945483896073831058930261724641277618328981766008722675404404347005009,8516464109813705017846673381161730340458008814885800650922822516855928737104,1123466447164703934328741246642448511199513706388932930170273400845584259512,3549658554379334242628536166107543119171319090515117171924404150785175614651,20050236656917680705173407104625075641049186986084540346810909246977321174260,4328179367990709150244102496965604541058014472966567986200766436334838205729,6523960484836646945629638483047198947455910731228954877131634689551005111678,840118507410487418552201986292140077062095264830249777356756239948365951505,9443485141542020716795178817254625558092596484849541439794346219916656780924,17517352113160950398700094980635300524550125065948318365273967900505416951637,3558475678500267728084169977682358432036940763329037251571517902892359350060,21782716253294940222641143651977099452381765047328512527623130468565364299843,5143600969269719315523014195013433247337519583796238248783742413790148311283,6937766932051718809641611511685721559694403467477888704545484121202675152929,10248511959409536383597760784458127936162061804351541810962726000050652155800,15584432188633520588792022977848834701354218910295071102828776215462904575092,16507813940325077551530806573175229924530686412372461197571308720671287449933,11975780799589036547299759597975704141323969091612997515060812893050562154894,2743143635303404960353780118079778350398309245035425997562746911685628540405,7772317651868959663361913464992926253491072635393117289337616002993612374782,2337519377771760840047685336751334655527732210909930380948789294151305059244,3616132500009609097754462360087761508553832847286785396472146776175233605533,16840763079152094997371697832566620838881567041180683145570810083272689914599,7660270111053834825889064071065415593147131275236956990950685283090480450184,20762611535627684584459315491847035257226740939101231132494468375819869523509,11042134071344142565200223013849882651956544247603198913312251335786248573941,1940414570916441943786503544322754456611678071701943345167834901237861815275,6726537219661359488596406444614225094882184675245355532878420949418407567309,13510096963519324808490741235975735288120771162631019837713476375721562862601,8622373819062603720895891234592129397052930901106318032071934400492518897707,17024729268332782126190150627072810510918979523772816301096433100167961982933,5587788522776741050743071285424100117576582212221222382824387609679897172811,12388474196602817840033287553175313493977358457560707192943603355479290048023,17628897462697931613283808657115398230150168968257584770836553363771557372104,14065018459890202233327759187460200256630019200670511082974394473420421694399,6104554150616525884927725557698817344144889522156367737688769378902924558634,10992664178398974993431947901729345793474931192615930318284939994040095999242,10969415364246753478074755753965479915045305330246521543663858633748866143603,1272956806332000540144317124032834499397723122931270496707464205344164793800,20231387145101186513751955054188659753720260135170026275339142463242692015712,13619345053559735757194629501334040876412094886252831860426351060385674007066,15232357465863047438256672278087920688704670526832495687820763524016520668185,398623536003273726220923501915643032345957170167431833298597360746684401150,7028250324917735970960317543369047790628992348836498053408852879988541935724,9906086796055827169135574765108677877733074061825927799032011921038506005373,12788056119136131846722253277450922603309904756259034915496788214657808474919,7651468821535297879836173382809170069017662802420683445433781610638854359553,783979512383179545035255083828374733462990002107251717097983319441159249905,8836457559777657917879541925866800908082149812458375523311279635635800064090,20144830911959238621340309337187081519944136818938895654338696747143855879203,6287181334311526693967500402732058645490470512478517679915786729496945390849,6578356433253304325301622313818326592018737710185433748824597250242226401957,7102838428799453179757741468552077315750505008228901893660362447987283707998,497820320926977947430162841325159818293818758853362781494155076005984229339,18160985608878840530944322708383120179552980243808985184923313895763861919637,13151612592624659285402557051397602661028781656351284997191435582230535568502,15780018535650817819214066689149640940245062275718550628416824107970066217991,20500218068755784102392504532520873969817687889455201735073738515957629646567,20888440956803193084788282136946318522770638138510716565517310266646640263708,15971618258529607882347998799169510722902529521092131094419433339204085498306,5293253007777884257810026986010586149314566166761521493811000336947093325852,11581497334099661755434309930999056492294889088823870215073663090290932016658,741799820113052677363038461398206547514107871854645629573511776865766479899,10132388802463968927185535273034278687094388163001210029432141519239006715163,9843127774781963908073388692741045845788815542021009420639678295559452765837,3807159091255176851037359514650776155078897682364934585802230436085278410633,6904224411392552889784909729922790171388456358295280077234569059475136886573,13434461271014860123956911179522881298853645897065359788401689426904150525428,12249944872255100022137726834287337969948262832177273992983186014370317983705,1080721436007830510323005297307130991703868335217850548555329006531295547187,20651452101643029862567543402727347872461377965899451538964773059299839803923,8902465483627533643127758766065785114055357770410218037441501029224645377694,17049203022284218301986830675304595858941437294636126244507847280421482250090,20389632733862984292955678575857173748595770609738193230360968914580393387194,2628553647311400613862969480533814764766703257834731382409245421165389763845,7113709286888238485244587172405174762331565517345483851543315956528264191390,21099219272139712501072896978936944264265953306877942445724732180674664269749,6196322429352603190460567397253889100476004214002852031233332452859780069595,8042719870001485176157425681827371545772290235839006373715151688719449512739,9109639854367609940132679558323551490721386060080938849664245212200893608513,20820097690315610819796383305043844702226083970185755192990081897048903995104,12474580713368057036057537615251118300654026141156267907684197425413737128906,4935701571378317615941939703137616736056472417588666676180454398865436202845,11284674041151323919882446027842742890041719161934493530658741778909469887490,10784274648620717180750449830334448050402020683452763192417352842268830091773,7221763500960709043106304906102942899855402476011030187016839441411503790134,21488573117797078819915291564603086854092528370673732237937703606783710747214,10368071846917543663295415889847910771342838450725996382692227125006143332582,7189971404170280285101021558651838178138415948558212834138150417852815291774,3622212247952623996680563730554546964978269732772060499110124228651174919309,4030261128316895271453652515658449745835613736325708089700420629607904984695,17917906020983172293093657775725231153822157764639429745264576611859524349990,7911943088433991265213669750138013059877768768674246542956611065207230165349,1237568201834766592374215633649772138875843120827112365624718270590862573855,3421335729151995408099494011827853754192179969298834320585486465552812589072,3983646153441614758977318714985842223356917025653336289250912061318144657309,11832501153279122995870584183546009144756312133876131903016034834496067810803,9642188977879773189558548598547584337663289943484049782260608599281971392829,17650631071515565052542834438104124084088724345481542312112093611903334892790,11727835841766435406263157822186528758001431234638936084294421464770985535272,4170985922866379778894675975982515174956777531610306941710536931798155932713,1904373901352853963433078121273558128713374926256562753718137883724136086536,20310106358538316988108567646970248789216107374650929380709349367764652307148,10755444294914746017826019531774644079659674520334374055753829758342372728308,21544150011748410796331015950886967191957797301800349750025078804307553228922,4791178272915634809747385261951447492552726497734131770971381971399880792451,21569911489317541997628510847711750299218484102264583013015022430206018097370,469129421958624587885163292532024178451414238938436764179429972880411747423,17178941568791193515971789991206572943108926053917999875254005411851993177716,10061493654971891913017572469769124056153763544567322059270144080123216592759,20809728888234709563099636671010468945654173909532666727272823672496239666493,13977154471274089663104412732631175732414148541501676926172952880637640768097,17159586220373273602393948660742324700378108883620196368910126875831365156676,4073500643742253412297370658761396932893392648826435730598979045413705716932,11493572320701213886088466735117685416116051720844612287863434228749232164029,20892362924238047571943713393658663337479326222564740924788211586758905169271,11301788649359616808987952401363629750830090004562424782094282760076674679757,5346827191385082048034578496490044229132766705726383391388695220005635473547,2201675309086116923924279562154152714268152257293936509978158351509848697027,17917826577478806664624583743441880347892085028222113450954395295616044284297,16998236939959525187887324821682683276592762127156629849525502305788028877451,4214391906402965555572230230924694640705243512659675242003943183722900957472,2247036556360539125313249919915213027481437766291950011195105972974928736865,9520057428546863347057860284023378728609842187323632161028631359500291204227,1828736612590741052604266070553266072363175828159047049110641125134408628099,18248580838532636162005188449054546706775958322552749296747411333541139803294,4834174634635006984667037697276171446677972706028785635301769650621697899268,489734793278913821067993383657373029590536750171301785048262915525334613888,20786356799510136039282916235428434827695977220581899018592633397684279594261,13145806261364716646031477788186247592609087183869974953048604633861380872823,3841420600164259772367211721293848988818647274121301867288590071853319905062,6882597113948243507685423253840830929482565588666222909972451758645869849656,18980943240416553858613600850285792319483905785062366023956546569017873987439,29028675420319059649770139934414847448931804950673695214332234580922091102,21775882073646833834016763184296217506960385126491507726769771477412306185790,21300410381086030882514625793664995316371660662503398686828472860934288345599,2472267536757789817746114566761390885333410401690592727164834695142144448445,9723880451630142367622302246353057781908243406397604481250639516011253801606,15313110769360181254868962440810453125247644871877064008660684649744823174300,20564192458187565149788272882595180521577855436987831222746293278781628416968,14590472970343049442795311527863765295112518097070620865372037933484660359574,17062841617700893799013325463153088719125540677385032193714935878731444635251,20200256413643364477818739581045874029732018697196252518589192345293202187361,4016942840923529049014357120480338974430876995693135820048221911362323816443,6537662900592412058939229458410964809681215707806173558553209350444735100542,18297886978176179234700005359672839811634650525194200352748308964228483504767,19662609243585750899960608765774063353658909677643282385185291970742157305960,10221731387204953046960523786878755517637874808703460048675288088446619398011,6359039963669314770815970957437041104980907769543152198211817790059980604175,12215821248736109157702052060566873526833550744650237478543432061962195037956,5935095671961849761918916493742868190941272209470285856382557274883130995501,4892952774759542491697203073862387895082272084344610213076129801679488176656,21229502683877666320987735203037721130704543292725579308736529207275811435612,17138707315635877064706472595294259087755028865414511496916808945331553578413,3064016632497858706665392042657089766401657752838410773325693629079632182414,10697546089228176531454125219656376659283555269092429548580998097316823780605,6383154332658396326745467904696030415502846256075951666613157084114882351628,15399057406934719483674477103950525850935787593222687850952111073065008222381,14222385230562109850723354194041721683341002968759594278414075630295191868997,4196055868873306164684774878036056827685013979028843775890547079994909550345,16495894724764636941708778916623546529990869478284583127943604032121307478877,16662872698072302151631604897467020278898785941962087730337008570271651661242,11474333637424192324648146148268767361869344542358721131204304533867910403346,12663733223747936066515430496850730759882234287115648507227477484368789774494,3278587449214209390499027872507714198695688159471276082957385919697290643338,19852281910336140665278848076045642033038867843956224684297984081107396007913,18119827693896204780441288678080897397841525584683046254519435612134656396725,3004914531848687259880590983112983929408762744461212501319599913078181196369,2744805266681634195002030539778050424843533661368265264531107280758966836574,12003425394929552979405575446174684244823087440054609540505332749485291543559,20899617298205776433505248799032591564097087832964850292073852661486959326400,18977355049070793830198782732221581680757588074059967640900502934882545605494,7774492678097446887356009465076901979542998304721485056654902284935411555748,6257979871454846095389581530427518297635929206624687597975380788548536091169,4200362970271656646831473686822497724241729322168501270846014047124987169639,9626555465339955137152373316361342798468143010897667050837558740100066479490,20599104767749131194316802432182162807569082153791773541255180345102031538229,263120164166236772856966508954885356163375871249262527569221312470198863328,14408635566922092915650756800314844499933046455992065014832556500390343919586,5183079049039149593555827045385122348972389627856098826226304101776790536649,9079663711634286747144802677527389482368428094888913737002695282424348199029,1730279784246934965982679327290069428428752739692892522465325889599043152257,19417355737429211343570897838176489391485942830255040228180844510907794134979,4688867852231614618639054238240140493597889866886829462162366294959927124611,9750344066229503722317800976404611879233170071789439067052923419204148303262,3998708829439769920633774213209304480109842139515896658207686741134489049438,21119879197425450902002580651023270363969638681856902851675391960298938692105,21081985423839377197813891376664505429739140831959287968556239547809632016084,2194830658993798006279037291585161216930179214066933009151541946587699367176,10072059773309529038163761158232080490764157196414798621723969165341603556957,12893922413945288356816723514764026149994443040839144958812668568890693761688,6289043885924508250801248626630354568142964747989700154772682955247795752635,7117847768519054206399668810694592559179837439189798231517777441723405148708,12250493458894268361669347775761796626700321541112455611623342396141245275173,7536889841233679602786965527644616779647633163370923759512908958092882343888,13743804807205248364239225685151790362682679734025326476864976250180416573459,15326756679387284645144696476114707028416084124671428061976908306742987298792,14138908940825881278249529554167499601250081601885817719517135886992016259170,18191604052705446018115707722428677617894390137039905732841218263472908863798,5747208788515494994202809520653945260017053266507158973974399964661798663161,16272405226087543462175411026937377018988783482980328154498443115982159189635,14959941590764331840350995267307957753388831891977493365286637018137237442649,17614662493206460042788564726025968337855721129414467376860164849857118120897,20540842142176422103053529661013282478418611089363263097515168740633056607687,3290501693077219671357645003459548779173001871326499393140572778475444534834,6447714071113870576284977914086213514251182728059734289291667058468678194763,10016099876948482641338204267737928588893338645093292975971465694121948536197,14390773887169232315205787249570222449199544947506512428178148864937891297988,14620241431433245619096116183667070956408821753296293274413828291589840475809,8494548643236049061832844399476487754775580533076308093638832054930352314493,13769276515160804060029880354652109198182914994347382081537158871751993099394,12260040442111865637116150785319893997124694704607680451569915655443058209529,18536763786390498498949547812325024712812297365266616445712766917775521176399,17646030323097974380890038898728697538005884509434748880882937861292172824089,20995211004588227271383296369921345208592928705280945008379701434887289620654,14012493030585128283500948776342859322003214361666347021120271800114480256613,13455652757462524273399933538052579123871086976307529744949349716824204294368,13176577891048443118691856747592745460758840755040242121263455031909886205386,10958007047406016650282891454669527247751542376915102729040783130554758505696,2403556896710211170900277969533691258363807287618829314859189083914528732150,21557822641920534343252006226462178185422073111762808253392360322675121740589,21301363144372514699996437466711759383396133417588035206347144265914876911832,21504297452761836117267872934293380498824936327520529664563583098264179167892,19008511347839951812168011659083529710470044770506456216838511009924048532294,20729557973386382250734811255901369475271445538588448251951105355722497057092,1596029835560146984478838415844959546370291207350745477127036146832708172428,18779043981021734310054761701946195503647990042042517453246401248591799960006,18389072889502391007861938373344479996746585336278814994866091596798460590651,11450018471721248431523978933304902015421867719856001119788032399031643640503,4695792303828705800181239521907223047109864872167868532243675764473118182293,7504424077032992561542388084424474665707766373549642837850671808747703476058,16201871852003230376980125294909568327837373609180822015372468013683148626476,9820880186139182810240320436271674897142093850866141441610372427566550592116,4474392152763162487463052318741100507628836016813487468299920576199966718180,6535313881166679884076402867701793095581869448631792643683900609540448349145,10375499075088306448884735241746141379659872937880333028048697275256343984198,3166175670215426596895103003450519990743126408554698027893417949729089445829,11825805020940873618060190367149910908253947573120883350031415196553790678909,15868728010683147011542066925511350470588043768845023267900379312401595633901,439641324715765398013368707995400811722128832670521930633684822154134655293,21389215620992100898484688007707226862245610434491939970737280409708735004882,13567457078921654178980424734811793190031829390199528822285370655562819201102,2491418221701715606532424215068729097730197896717397364135214058133617329024,2700199371443700220147927924846092239465972046042951758397024540313204379477,11101155530024798073181197117436499601132355735889219480985438157046671552075,7696323106369972761130328211405739772776004396041557644397285018363028133006,11874928928175576980576459276992229552831994515252269310033260164062026645644,240537705962136501448280118114493602675578232672944677099273394877211057455,2336277667844723086566433195865965121270861932965343039992167442067222380338,7139477698789264606031986148297940201890262913499702250627665080791275501502,5394022087396393768813205254315732819042275688988698297882925332496064046016,19793961339963600744392705441271116638543292070344579052218623579091649097618,15692138411890707768379631022903362931511371639119812810678572491600193150934,17870790093336984580535630746458834581867280473989239593391879854453602020534,8527221939827993709561548898140031570873635681631994323216682386420609693119,20583146985132338324328431878826670751588212915037908674977314222878838415115,18286401926708183610455794878977380145855167386311409319243563628128439897199,14883280595953108786791995875596640384464375470758397510182264364463199426941,15622372954112461900770387091989505548249197707826335911691325586886540655839,15015231518950399896087228957162542423583966819051318376374846686122344072726,4110275540712809298667287978052760900153083659165519222137609468305797552622,12194886690835058962976784720918154631659193272765999855977381550575603733993,15244557029932516875079143618219344257744782264536288508363832394149847400408,10234512862511661102613686672198745648772485307900923622631623670310818907316,11002446381083289255418443918954072583200871532274996806630154250111947858951,8253167315431388215871891033564848144784018068378784924459677347009078928353,12052362697319720881876615803891693831545089601220691511658506577522506606138,4222271910532283822428121153000170791277438320812055898378713943538215316712,5653799018158152396708984453701593562269544320974176828284977837083044089432,7882074107401771620456811688079120160013843021919844939348749959599330360070,16985024708206545567858733579435707605892308141313442111649869690900835499686,15657638292217617224447239244820122003415140104485558954475025681733455080516,5031435167133277726502623124488830505559857356049078624241295172338778604459,18251569826624635398451261785711619709466995337593606694180128347754947431611,13347210735949290753346060121453479592654490759925951960015474767685667320469,15097256163521186466089214691748103981791931847659339134237546471578704117651,18618539001972002803104792202843684224999903989910895364254642809781793542910,3535158924054577294148391849345768098132565619653646126038220164469413178376,5247111262643738028940705230194040190316748748116050300897903801701767549935,21069968641157288335927634486731267978865294883466175079455493856177243522705,15182016439888624540835624880056168611406902880254574867923247894452951108191,2598270152918575231168351721309733272482825217008498067779287914396446525010,5113774671804063464274403166444533180735260894306271253672198506848528131887,10007988864825946871589264454040608387449058007032979960058775715911078006740,6905160188004006948460048193173293195325586959399957154757620552653693466890,11995759573081381716106152146833656576924747390008060686555489446745383610128,3012863557306381401755965576258357584550751416148424411503270543269480674925,2913988303571063477501511529375194010078206270482236339308347176586704669764,5006524049092266462685266534385319119401827059140718482624293936686566174021,17563183357860154367150870160675168713982368687948283812578969167511639823963,17837755859790999437375156561325979429838685660428780384415700354505074279205,16080522246080742261793784524730583623229678427635608200910206239897175583035,2848708361765680705684254800195178864363439998055587286174501633177530616249,1557519954300916467422364113319270366979873515036760226798787393508368098341,11733665678441137100700293713589760125678167060800184611962879142675741739407,16521409005131685666434785453319000098069672876632224692360259274386316622759,18967967647390654785643258265157841586213408055603172849772769208320302959605,17571504476351312669488808692966809815779784230239825235217863108338926113527,1033277958139146991725614151292577955914352533347610456481561709576150765927,14781931979382308373625511201561097203707487976646566051328122813686985362864,4650875909473177450881505980066567106490273485086660264292847695230525365004,2914409799137239617504079923731151032417003482030433682771204258557926592318,1569377349856381614777306232175508373904011237210172681516586308749045834576,6819560317780627274403497421141083285449699366697573487561555149873327611188,16783037329427380826125478934695948949747971672927005004484739677562779828896,7015004192682971326660995855922915203604605225985220083215349611396572003775,4630816304408133216263172876471813378546980993666459834637527842126471866675,1048974869579541183196305195192354335945589066090693848404581740062134729282,18688715639285068183434963296396143793423259729912639999344372787920282768249,10934347243740746938446533383348729597078488045109074394137337392516949956248,6293725896350451546716316494602770048720703017891567394397586512386125658192,9703640866977553131835948007053717693480506246962404280815291341798629276781,7906707563931146558411066527524578790489630019846849753651156405406896838827,9702629288736663637774512920196886201521548938988112829178357919548773380071,11496918342981223624025423866080407628491859149911166113194854209867880853781,5310797284993667039758118840812749372556974855379167283523727209282978379416,4023078794142040206433592504682005395486039156676105856122688431286266944198,16871217006715623479558921653467262427043486550696934636603562460293483965032,11838323559167998464544738415089027103939009770214130070107400686110312526340,4980088349530490327691411848559646523716982917225546360214229685978505879808,9559603819596004088164413773616676054644268005451072511817132718244048934414,16706530320004737946238925506482163802145108867695620161891008305110107710231,17097818114876900788313405299390647115420321455669519337216918484593668351660,5849414403812965413267782406018277549067364089813096482998057955032613458546,15554882868930267918822925407791760045541474181510040631764755534058258253399,21580870201101672999738147681605702976639626554191473007622680366607482413326,6529597247071863795966038055163209598757897174702699285551712764342047434265,1034354038040835970585668649926410980243448725331655567931872752141342573332,6310767810288764607994771877877727315289627303796831154815613377794983946591,996939452759173758835198197713244238928300388619776170462989538225909183250,17830180799634516986244195887614846195714707335284590299432596686170229130983,19874559606908304758854510017033500134646556009065042866233430268619254302205,14009373839533951923879302153319163529100920268844053529575065501607218593395,14946211767155341356149843492542554767905660369447051530372801216288515919491,20201956319173972615406549564337979402376802300388863728690331165140287483581,10535506466358617363674252301599248223977286129433846317382254624662176433824,11029001794792043521930346330104687908171223556219538577009137251048931299365,8200934006947443074514571335915268415570710146769685554653690866413931711817,3756001813899409241012385101881052052933218317388650253688371184478299762463,18636887900618256435910622299263466888026971253061227337296887637280237818897,12062360063539460494176603336727957703003697981349882838776879968409682697224,11001722900962847730169711618381123657713397243841075174948041047383605406084,1100165499084337642558411348439001505815886538759724357694738775770474410180,17434145857282894864497601363005649089714522250566258141982190265575138829458,7528570688175530782083445771420581373161584322581902670613058236780353068011,19971690728399713343613282829324748110469462189895719072018362834001408037396,2720175852023799717892872520519566779572526301065275372226989199715421627391,14943825869290446747104357486851686014418770156528443888330443464181536442315,463946552619089332690398123288326517388219753658554785664250177816814153004,17828919314250532241077886046465359044175524922026640483099339343132288207680,17254663393643639301497528160788050107293708210389962463123967310041334977099,10548323428945380231342461328951126333180031707800802905121494905097297919778,15741600332199859123106892774234668638862408966232099592590755994226268019056,1447099980864195663747093395834509033779875532198378629216846242387465017398,5634271615965881595424665300014723762842669209816714518648909648355913896267,8004046094319510531556517659927356739393971820240935140962728964910152787977,20150098853172404856553856601505464455083744410516166414862502865711843962616,6051577504932496971373107947431966202921763803799244564057047344716078611429,11153752935200730615392163240542716924397740666674490478903681768299619893440,574571428841330767683871500343913695389489991910772848795148223306401258112,6644002840867033629815195671865575216742798076650013015371202918478434067981,10643887442409207306340562760946079189746204276290341516975302787467861819914,3310054989122793204488875713765468888781168322357480727671652094037000591815,14260109332138908810733885305730437910719800845345795697882239548319688811219,5210296637174697538908079595920299077484266890923778247313974722933789990659,12099525392201549319291916254076192583959301537918452056524775934199172994864,7553233508370030852973625898622143795815488816458055012305692281375143855601,338064484385145371035100049761904487152067475286477053744625247222287881704,21656711030424471443690125986754350631269722127039355499852011488517394872248,21372195548620232488593781254533859082570347959319967220919951808088029020212,6382011083971938503792804272844009960813722135917547320595901431805157825428,10487620314920598491955634712479265679552728563160570833716083687459951803271,12540875281457292616015016392478978686561298989814479837942710114246256185916,18617705893970874028060182711496372099359212095272496239846702650061090540602,18861927157583050522649066858336628481061253205783797036256319572504841854227,697040343546965749510304464460790931385381610135802696124987191773265224046,19957864832901242629222592391639674066674531543245225621817890196632976954948,18958366438463449522535881612753516577920408884030961917206372848340856779454,19038355323356709854907634385093529445778219247035572752290295596750121939785,1288546653652611126768551729241141142059005744057588910355805731786584613343,4046804685697550720337256987447438366138088525717758741922811410001913306096,1660762585827970516291367008365082875857712512262252287267067642443918638514,12490758580574114271593656499165833022285695011717771020275535753216014465968,16141486882419673588223773309048616384177430148674560859754337286781225436609,17480842754700647574286106752058337138867662945102069039800534716529718409113,15604353321749597155917847886619012355001132908396771273202434684314342259150,5617279871415371338336939332259796482400498338204339205308393954394249833452,15174696383871305992552314836076160250704499338484600692522408887766438439385,7427777880578061171924488290292477545896473049748950597878341286830693333925,14092813309756880555589883560674882809640120093304366339387019683168400944554,14371461943490927493590660203698012938705485668960202862586478499151043526062,15747628341829994869775701388730275581025993393892718204096081193836534027616,13069485962326240936812384345060376352182714448869348207061583108709995536141,12897613411832214271030930629934621444235734267985429117525716946550585934838,21009316561423875807053156778128985534726230082102006144117574738389765473006,1961079851137768143186691785724923358396590015729408078834852546188718166268,7449716401041984694438903080808992521397429308993548549788139074686598693961,541840132011603695915673487977337384196812668637554519620724199330714724824,8732237210312418481429872365007927003824155222103189850471564031658954501153,6523310024353124781137808005011914742907908537623530782692226224442022388987,21509127266455930277492767884139578463956043561699345583365079657386805307554,13989299184155011575724091657019750720502004610297338129834280607581254559697,13646882669283186383881254452527864262332184212165662411849024353857046450116,14437939637607347068422046603975325432039018873549816106341419990853530813605,12400256882351762977557053352624357859435580188305833994340851255855777961583,5318260629482404358266028277859623051836786599425915900288734688050650647740,1629695214770269012001751163254712973932233705878496747522731454404864982213,13712071936286520679632088394106925703538964875601961825262229735589116706613,16370398845138146853603171685418735096308178156853614168785529502102183447562,531316798023999736377588166858362632977098508125317800095882267717108741597,9318921203266238488822738977554047526587525733728386955697050423076330149397,270377449844572577022377874031006263208440602734811115345017690504339807539,9815014161182964374794581271513785279039355629218722105019385525592211310401,9645578731676628215511306357368922184828636697072609821617709363109131724528,8278125422456187544426337239756968442258418675393889722193805619331692372756,3793686014229600852890515574697744650225321239380634655110095131274614241795,11274706713173058310395599257524413726315092599580477329306442323879171602089,15700516289342200878818538157175110895267852686641088808116754074662814875793,14231470645515485158149500150154330504733538042275634884479799789708016096981,17009943350256143028237187628790018788978713833977098031809639804676372324573,11807744076512700514106955514318371416449053759940168158181473579522112561617,8941191247819458429052997300931331828693768320666304381154122720332624423159,20810756908118815132070882638097329621005628857845667418135716334205275433963,17633865705062992379853990460318358612898966723353031319355975229233791359833,20574714650596437874739546946725432737055645662464099228865520688481435554952,20753133214966494228304506683244546691191781338293295716113306511488052350935,20891917718961601440155839168193313007436009622881050810291426124657399756167,15254490709565398763344025189458873521593894682543200304507470388535826802423,1579686464441495454543935122179009252394402667945704420064352314351485765393,2776164910982632895181744444931014666522951510059312025217047160140701867676,18493452977704296940835401396385377366306134685072368153755232646737492155884,7466441893052199319529201615576158956429673118460829755667264030485444838721,4862779186474359727417788114204862127925883646628388801420770199523844825968,4332442906725686065471004321063349183397729160637280571390764069298441846158,6235595676847271156438843637266606946005787585155569320931268977334224113102,3283545972614629083851761609721595874215964445590540647737064482671122002155,20190238096841101806664255153033971438119127586536510897732203034569691981419,16218082928311959370464862694396129351602418127064911331498297863184968070057,18169106670538118432467974548733501686430842104311041161699612921427327878488,13082519725061669934177494520541983774227971959053999627907293338903728791646,17917738025521205167709067376626145668664963656058875474248539992479417821761,10201169720940960483107286532267011054369536208475708600788396458879352247717,10086018032281190838410153727159750412677882106214361975307419597102233105666,12682273581371325166244148831560984283003922721179649899812794401686084266959,21151848537444166847396763358911125604594195283585946282585966889014856464069,5870563280212708258714113395803290954804582727013499575940699343839714979459,15818574025355019546843656101475484151535156797083091329572001913076927497145,9172129818981348435701876676880219576808443896350696165457788920197063328446,10390962755465039363458687913467754632739357930439039623432597903165701965254,6161501669511652251380864592245214064026880951608726788784852344316145896868,5405539522259494292389572744962975583699928794990075330665720986459457361914,15953141686281883540154911071743713625324924225902448030996737734044456286469,21879157639189744211597108651045875700807085936267782759316146460177277605878,11434924404918060113007413962226874803102772070441693086168193464929290844877,20757082623598026102923542323531106955538082419998942072958829717667465557131,8919981096169474486495376362947226335482024821650926316923260800584787410595,4288509578096166644556335935101899777779885105511348520519380469688243082096,16046529059566280251436022453196743987059059184968007751447655603059461800273,11219038614950179129482943179862383597500934389713177845014944329948593838918,10043039951240572103842000677370211126438633625308559058041812947576435228523,13424594313385554045395046911081130962489696002268038176721598695954847052511,1211793291463193275930858215285948372240170625699602215748915241438580144093,13956919764638999174327326329058963982898576605238294264300483944344569472991,21763763972390992315030985535287866258485311664824948828240050483482084352503,10420983865433228040050251893025618324702726171912049836799135351770260802977,18753701818722627673883564699398410722354636353042388382508975546895568464372,3775364142286651074799331885877684616693199427012762917550076623916732710822,8292671711306889259828642403052383798091670542487370026886155070540857817510,12071789317828192902441324443833143078458416120447222512665882093850970086582,18221914904286916930821501101975619932383182494940702022220624561466550429056,1015894946220130503079847588005345557311861372219799708101258594371020452677,7497079366974677538814211796849030622236102734688468791057012961185250977217,10412524008150259624425778663311437889796006875864864836590446801100002463061,242804608586097049060214639927231617495599500538071474816862835383660136678,9327321863177171873474299501143270493456472132426279976071195256972553555122,20841963613720468677785103552893139903309688713322442693081971171914472255790,13630784939841089364059908940844732601072559390491244936534430865345773326547,20060990491599613171081634276027504616735657335613608029945430961773413795782,20369723769740268530808565104818084023349274297831884550854878783888535628782,15076862507709493588855118027827375721947856558107489434980647124128748591027,12996451838772518667606758612923003843581729895975567888341928977998771990237,4052235171895745508958823720790274122684550078188920081778152850440806616718,12335377703331511956642047444506386381049513479297082723690490432465187475758,19412573446052112260556809146936739541890274154067075795508039506436684757726,17815752693042999749244044082547565016456928313463444720511782669652296613554,15784264337580227630693723391508440881780776717973842946134335715743491257089,10667492170364941836778050228790234453197448653226319355770388144152747476935,211997855288770996034164566467801948520054169907247985981041869092209280055,4928982790134068590739975426823777812194464923471161503361037698280174981760,18608672135933853582317718913701178979379432491853388463545185599228146691207,2315480928424106999355320576364787114368100799067708928765166041722251581141,7132821772386644248930179957111951717051009389997169728630437453984113307524,11744909558588287567829975231377896922260739746243206347301263424478589809196,21821616737585515642213483301817094657757210129023396850436714925413476278715,11972412756334108055648790188313869962577071423570734765254546184728606861831,9898102092275580917130558353359107455579856499298488646821411779664420246304,9958879822047499292094876401302022972082946727826778952858218178060652972948,19871205375909775929744751330720905649873502681808501037344623586575605895174,16601345490108570384179778033128731955939874176242885190845545230306090545377,3600818319871189164836691793538369796689767756596935154198009735998848369707,20314694248383769870802453966233555256007670655653781360971318867730452026627,13418958906290175260633447769067612135267907574578622587604011162488451092514,14459952906281539694149485094281623760953141057796841403669604773900469687889,19448408956408494949564099234438127422205398424291589853947309097810118078185,7825443276535418239837092010081563810404777554695462770138005656816269166303,8463248112790565810949249352339633764856217758597371912588298951088604363676,9397106702637851943166369067733828452382029530464971824017078972309585633364,15452595095505449307828854722016355425252678164966267614739918073395150429984,10382687268437366227597120935808669117993505555024110738918156422833458968254,8525129123003317464420034009755418250374332671627293582800681623438541074422,2209915653341740331756848895690532824379055156318218590971248250386542567791,15183382625497370680223757887016738067273663916736248647060220264288252640054,5914882314939376011130904692287520473675802288813732481565058295269249787489,10737923811176739642308957871008944847331638141618843900584295941869359201136,1019349115878726003171044582547108836234898959299710235354611802499665438533,17364570285151724843778637821645803441762402239038594475632207111794332738860,1251558044831543718478805412133062543617572066062707552512150093969983011815,7568361578986094203490921683991770751640726490619033852251843934473195496119,15439738350303496845805351814211602783597897988159829928947802101119983398961,20009975853963282344191402380547695759759731502702993682892413834957351648692,2363424283223098643833999734510060612126929924822351279904900380971757668501,17136028473467909987260660923882066072229277631411461261810169503965426571985,21423452231832054119549543703585288464249234898851841557254723364015587266501,6300803647873111234660196693510491620063330061194984556803532776163457642510,2749674757601823156522337416483425720076662114029481936093706226193678544468,16123152544885237760040277581510833657110306240025009956733742940484347179299,1449335556475943566914615807167633374850907490355989852917815325720800540092,18225835808858885369557291110939124591374272404427656191824524491194015802997,10406157408365973197865488683230737937923502029339842530701446718978570586144,17998633938868470446795829948946241208954439598754402047898587965138352946507,17256506181869579387781206921456178119308959078547323103229058358574594315926,13094455817799190250176997937777121524540082751332502303810836528817463694222,773415265947842731444676861730775210907581945844672294668103420848288364110,19038336321288882240456993528476377501756672900320404015643432684581055112943,14760627809381104024315295117982862934682028410719221222838112174132134785643,2299176916578536045959722453832883315456156391111537255429863337814706171473,3669114713225196659381574151653298340387887549947282054635076450967251116153,18251972251689708305163349578105700140002711019536040700377516042131395885101,2208114007582253724814286240939815507122998650551224166265438176279104064289,5311319465851004438404228350963430011209528099234009157573275300632566893387,17704997085718018561575909495530243398580104458533121202802306468962737491818,1933762715500501610210207583856164878867609341004969983518458273086102828809,6386814998566871009542498039659511536698234159072885405476628256992102020495,18831772844239784973934592955595859276748324649808851586824036127112826604451,13462121128312374635146040270944207295588795209645130037644415451121036635451,19731805313375129918425060059406339849106971447864245585064948352741000760923,21643500371506858849424889544041572150599889621082729284012490052076449459481,138548710091390954908010216339657754049773930079521223071410504190290814535,6947102089761831011730597399319184690211329034898095828464106850135090631740,12831053427863630744244436108113801672008361468343188269856032816742671083134,4223577351003454708551493531516184634014386163092922955496011474432781253241,2714897164693927923639587351413494956248140707486375397510165870974510685388,20023038420823827383850598062203899779139064378489163672445486337197649825217,1767883277856872395041944981599210930967554162796692711247113543638244036456,11374943081906439317741616342767018365183355349301791743927619930324701508426,11803403776542021481872407152864894420411711895295228328072919482156044458427,10466014303238336135169608931533160584648879880459007777160264124745826740750,20569672017414729176046551969057922112780177375685900568749563089152585958033,17872595105302125548629012813042403567513885359499964690907253660570968601519,10903006438854654900289559455490687959429486945748385817337220540948365309048,18275515870643256842855966776500808668842291767076613550498342673701067299432,630933085628668840611776843471079145620019967645658920379584401715066362709,6825394902701793105668667323441283311921241346208501522910007054667207868452,6858750193485140252798450603380083764362623733369268015553477107387074944232,1478873465931112194691102753288035258894560238829532399713218315372158028033,20647986868364738274961741160207964168903320676158610371768611791255451415798,4340383424522509172928608655219336498337132315044301147894720301443278858359,15694054630954602584443160345828698433451692126398102396637062194669728150097,16587614091042345417694939817299154667821001841573634480871399767976428325370,6780948432583055051074963887359666213579607675322530873343441117551279310337,881888803549941181636901791599886290841557130000792317917044641982716656024,8375540908772391314073560695793592104950470672337969483097880419747173630602,10968989437172024632405943909737990264150382688586767944077705368389009715036,18851349698000339475263334762001556036662188445499369323276947028195614775701,17424154833179596191247217224032955577230090491464139783174467885567507995873,3084264395291045886600299855227253813661906050535885634611163481700929635296,9780424450121954867052166726264263906169948113675811543750657338499901472300,14927658638057710246989480138441311677749528914441518171301964877558977872737,9409069466927713011440733713350127030613235827582038407437204556786573082426,21532551006723685558182869738272976023905972040234419867623013049768952103538,5167833995989484123952079378988963389989994865716472465476503880641449880786,14740174761652743774118447006447618386992142680472177663315668117221175944698,10520805511348878943408706501985230943081177040800761729569633389778724896451,8700454790689589285537042584692084777365997167238651880195034227220137266589,2733945906594382609383183532639154621092632308934603150907320167864486314840,10291836929398020145429078280830166142519086643388813863997726059451399134380,1964652348248051415524467307507959105507630568171154193714989224874728277054,2594310934406347332341406086415178782930670052092905736460388995932291385927,14842121917468246033091527680370186171895171052114757236254597861059412933851,10375528532253513340592396399825408524430850232835146379883683152448199357827,12477762696438196028925893395417443678494787519078936487705085579706421333630,18021944163681185812898833787149788656465569272261580921039580457574363675422,14971348947199715425743490776577354350250241776207063239247262831298628671824,18527079575564336560853661036281436413609153640671180843997315618816477020062,10112969341623453459297605360048147871962444397321717541108011492952113746933,9306811905619197449152929816385830205919355838468334319731910917748600490999,3201856562784023690028197460260731000729676130502544364740684445045551547485,17677019524999624366971265277439539545709248668323859450511125252478150097491,13203760042423946863820551582066224159089369605713946028771025792976332967017,8225744798383097681411492868795146058284602972120901801159373206820642535790,1133207841388716114249120311196903646181388009397557241156806164775023041371,15623890151225925383841140893652872349082273871391477651993101123938000801867,21454879142557364834852736051259149378158105754952971451715419987896242909650,8531552648559366596105198828222595210930697829968414405502802286874489507133,9401758966490949657386555283103887925392012048184105735334446423864991206786,14182985100305261645378993603110572106752819147111838091043200594637885017186,3351125971378624693919014331249933776013465831551789721255791740304274394936,19684429419661111328145464896944065690801463972795522382446603218587092452167,10925858543362322055288327267322188904474484027644138316216578205314218206492,638388255012974167128675944413974318871770367985490338348509002020449680093,14959175299535994556786536841655834078592404933909341983568127492171858384391,4565657688930940961208733539150773567906556683309024875952853834684480507269,18262745015163208046754959923695809473174547423960055443621926543956602209348,20270410959376379064306739018970053272238947330997122046760265674383899359657,15290563044070434983378131412705775525253143318870138946525234035666015420725,584590168302279667271049654248756511695470228213252786062709717390671267095,4966088591187905712289854426727671159168968384675952400787560742388879645568,3319669368740731092651343449167365623382886973437878280133897523197651190312,9912174158284239213664392208740702249961859675813287499135373479592639861287,8516379350240514281945243250529128948244709428452350892659587420308554264613,2460558416671744640916958595519740745483455366236568201673238589517657340142,15249503582713331075672114681569135202331428122201669911203912573537116149514,5355701614078955989983290080356684040651137096346994307217952640790301753843,7986859541259474766804707773691600248831464381736783455743764933501866864285,20896597282789039779549640920767060676459830701472255011776479759676387046352,21156365340242937197411344791352838273101399835862399143303393482855843470763,8810320994466343375413166155559061722877903255339567630911647558329186883195,13305939854322882862383989397499916187143744662574072474260034250574401506438,14276510595076120373993498057833260625756300056428067994615344507361982835166,20071507901284477038407301846126798169150113895071357904039436046848822333309,8183811379732619835362931863732297053435925338898156873268534636771405892075,13219046823251102005239988390708288792968718105445890139009709283489860275155,9185773756453985715582986632685488321665392756676197265712130071752773976631,20421943269702844355893550089604182682047061852707721138511917444304707579860,12300280142885224975710767798713824153348765684179955650717019029210821361254,12007970010282235734724332615090869243055192449773846575955902036212263482679,6158352771477574748962005695592225162907260568470401385862937675095774244006,9907046449530603675289866399335586386847026415848055552734816021036571412645,20848733914096475328182569300389604774285326414256566622667108340302595094373,8365137332145458646854804122757179721555979085847877907343540983873210953635,5631007860876051233682685206319236038053360910127434722172168921859697775602,7724822014604490732390628840430579796440157358556500058829335597037618014759,369071834493409594945180455653375424679250473615867182702388739879310444614,16769246200562822457100153851476834038704115916651426939703296994708244449575,5761928395342052380070450997738075595651684639539927184355295101970822313162,5566206280191314323446398313438814776510866532854163164867370641136219947308,3342359366346342054674985507754083252076489241172458810297886110396010701777,20961070283557581225918432539907379409525514793918155863543775859703676727621,20556180232726542574747935614764094533414324377887922356987347326584809231233,15941149549798383978046697670090370142285790712496734802869937995562571324293,14600396724469636128403441949598983100001916970624980610808650856082650218424,8853454033412621833577484167285435511890615294361962242058729914818351640066,7796912448927288083851300561583091259511345752250157116939318925851741489961,3163019852372632897541834965385695185434873283151315355155397996458747882742,14952700133737822394693717249052150819987738575989807253015506109171868391432,18525964798774229541041472797217632579102334608286281048443267822115517194616,7102118124262431444884005767970969670970778150875473949502505015348122457394,14204638357887780388176917062053732214797428898508168337150295424689096270757,3277315675050465719399614805088484534242274431436504827247668714966713345731,8238377613232984055051747513217839877952472190522754887201501162730400770486,10224258402104106587652987351104010753816241645110952300303846844538654914570,15487805061491340966964538995368847025698196465175525562567846982560655044359,19219815971577427671261496058630992677146093954055100897228392314454716131964,20451783587558695494081025729566916635107391693056303514267562508131052495026,10604908883794901754591456082090038158328418399338332217230293938008589705164,12629655676673767414687101606277783347408094199429831144029123923860076780652,13709603387456116061265164612378749494975357559995793114409724336723134851988,12280342248736515373215500158719410978133041790040105888782814256839967443115,7016009627584978047738165231314996484413117067952510110423917440240605830479,1524894728322552104763656617099911162075578893415210522528939966083567287381,16110348090073067974052480411460325713852194746966461188536450049907379558864,15849314408692105099989833438461121938666945258532089314493985018340786241149,14526266680576776847324515988959661063035583100946967808594725417429124130409,12662059588246809623132277946460950856148161126345911747740066547195150214304,21784234245035153912497219470830935288918016717870099869682681847939205742526,9781991278293660355311618579950123622358901576863101735826839255817708999571,9734447579561113294373127302234593360683756540510409616709038385517649565283,15783703381085552443769424496547949342637297192593569766965137630433735196499,16818302710679242439066482280541233367708597536159643998239357880909455304,17208557330797764065799659085570688998141169399652780006230425322841317471944,68706297573456724111634550544331343558310761429949721000334906561427561646,5166796490382346553866700788131214421083284131608596259217301814881739273429,20336383765590527388425300334919391504612546166109544795528892908246473855987,3743358254907302851720282727384172290999978135762491123193685721554867920482,84015356866358900057683156333277329434974724445531256660202285630028495424,13076432415761967873214874574212608989827734997835707946240987502102677974919,674004304490160746369333425685153534516797008922146231179438460150958899661,18008401489523347421324064960257465802035658427821867761642737239891301877084,9230814159278735889507853746171683425354655931537527400639327580576056029011,2338224170787780983513724541155899891770286010849997183556172649088034621522,13774730216408957127941425099141817093498762972537953648152397183615811260761,2008226192472961561861571910859568903805945585734651871281309234451941696550,18191659524918356873059208424871952262892246019889299985115112751645849510652,9977051090514243658919274826700877766433577306278237326432737577914469740819,1382241145032463690710185532538145321402596788581319285825708537098818318411,19630880072807438067933226715597469053645950344003618599545076855182567392314,13804532717560570932337083609013921209558901545207945868049344755900793666387,19508550180350246129831873366824988420065599516069494466305637280501827380920,2848475116255698304240592397534148356674367429794174368229897070816851620326,12588734179864636951823212209185103123565413699799377322920024420368718083095,2232868200526350302935711180734463487873472319399673090914563494365441045552,21377055866142483679502571618984666212079397034684178104676086894866487789275,4635961124592421709613730717934803195170398911827834468836156717082833802089,4795610144270291375198683497266358163517248476702360287932565598454128564576,19878139464835077446055142241229890663517120197298970825225586650258704320634,9323502139000335770056400844753650839571196769328639117682123746249546059680,21112416038547244178847876677595343035216538411439215223028113590182490455841,12697374728966756322005607409702182672422756890620656219302331428706184232671,9995295835719608174333254715476035051015528223152237761898234348962139965339,19838681448410021391386343877373049070883481927354420971134124213644615857262,13348946731323604604321164467837298053616765723820806627202376009331748334141,14459243825598700354634855807582241585214330632597159841271530816381999251613,16398077966528830249699687699527475156225434078425955606570595942126461545256,7643106356234289086355359290357087474077139338168525601611444369470624871398,20959675452873599571224578970521717955557909237727928302612036851445583012450,4540025033646420810215611052662284909609074316113304153198697292213556037365,12027414908456226247222654846878068961735365399441671468269489072556154853636,1619579475293093356383780863588610629947769633032102520272612883476001600909,8181934427490631780501305508522146234029250148182651874753791841738732508561,15274797459753339681175428319112732573480605162611546476487133996977708752899,5881626303176748491435260832560365957494745248996859086310569735454431253109,3420994635070209394832291125346590627475632172750870826118213841463585026009,3253514739572615120245273590897551489662089732892213994698961442123844511104,20203053841592538933587679570153207252397020205630948336602455897993666135475,11921266577552501086897102705390311185747062744461377484820893183533643304437,13241907169609567850145071795854997578682645559619300976538988140768348089882,6151712987809690919701305472528460675037031217153195032569932714294427052374,12205705969228027397734509241211850240154931572324813086389133244191540704608,12945812038464520921512101569088203002779738300982254987224395885526111963420,11566504805689497712142963920462066842262053081516919575350242192944407040992,15723543550582708278977667347083710027075971342576647975064035406870923269719,7860258127934035634020846943939055662221372673596335233171159964609391837625,15528468237941422862373023290041270186925402725739650209357342065347651170444,11352800656251355849609307793804420136337526597168059373534052608892527331301,17897134085314321992998873273654112498897006369781950634488633467466113054350,17437455229098036757167276638155356442563492876806914963325540308515770959304,14997752382200324825750631040991638912810425809039371028733815341246302297900,14919207184372260640968465889336548904504385718633186760383678178843526009885,11844428225775333775773424762116332026943738109456526441415077427972318646084,15239467296659614730514306837963031027890655569818408146133916080687077630265,20117441496592956911595459290983302272515832294843762087476380541606326158806,11211331365407064571488620323378276965399956667340240900293979889578003659573,8791311092499361250396136430755948222248236194668427353488891370543849807047,1774021261549926243219732938834617869058292002083739109596586460663663531688,2787995130097988538722853640105055460288688373288517482894772682647739193296,14036419256752421574134832204020173449399727322774622383219518631065684283606,2503905040784637175494196915035325275253506707537902487189138102884611289404,21664450508754049721193573452150382260579289185348178882539067755355712577906,18957082022313129842427206117755534129197834418112547991189485282634468396440,16781909482475992329419834248503013105141202009836651280677498803323770600224,6643893904478082560922317503708920766922698054352006836803634579280954593309,20411224098851507032152776776680744497103387047587118749494718067214956146818,6932200046628136855984161612336282559188694975968887215970260451999517971798,13683745075914427134220228573435856137115339570721809234203113630305711234299,12049119081343437729871267418004147930387014906392381996118616615174663353079,2441975952742754201500338273078694079713769380080349023008653075072257968553,1011172201777323348203437837012280331103466286486119939185319004696667574496,4513858889726009970880526008944305706495472698013415303299122950266699858614,1829602352761774082971266699128478520319034089172917557099196106572588528973,20888913280392789424820640494940209099778028785108373950708163556643786717499,11546628016884748339883959858649314450404290142635813671623548341391668641333,21503514976315590685255962605196280426006590386762670744592186136529638021924], - [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] + [ + 0x11e27da7b7ef964948a332974d07cceea778bc33aedbcd09de222fa22ad0b101, + 0x1f60381b83b44a8fe65a0f4142faaafc5fbf55f79133c5740c53f036a3065b65, + 0xfc1e1ac8ad3524ebdbfa45dcc51576548234d0292adfe1cd70a706a1b6dadd8, + 0xa40798ead3a12b78bcd8f10bb15cb0c426bbd2282a81dcdc070084ce78b8d76, + 0x2dc09d3357051155987ea95594436b6cbf393b0135f51e2f675ea5f462f4a9c5, + 0x104b9241d534264532eda181de1a154dd175ee150f349033e46ddc54181da088, + 0x127a6208d98f6cd387b802fa44cab2037b3b91f0622f17084f1b8d8ac9d12698, + 0x2d075ceebab54341dc02fb1f50d938ce1dfdcde659955a930ec18f8625f86d4d, + 0x44fd5c2101a20be2ad923bebe15a477f40c6039a3dd0d7443fe72758042010c, + 0x2b302c8511fbd3702b815564c5399acb8a8f2a8eb77f96c7f0849628e09f9bc8, + 0x7cbe339db90599455d1eded1e8a870bd302c92a79b1d0f4ee87222cce99e22b, + 0x1326749312c6e8bd4ef24c97c809f78ae548394c94c3df2f28ffa8105debe211, + 0x54021406b8d1f8c7080e7c245304e4b7a797cd236dad92d929b223f269780e0, + 0x5c0e033b589f8ddb23a9d559eaeecf98691a8d018f1279bf406d08f2787cc42, + 0x2508a8cdd450f969b61c749d566c9459a16ead4330e35d5415b12eca38584bb1, + 0x264dccc02e574ca7e736da25072bd8fbe9909621fd4f4169b2bae8d368ff12d2, + 0x137199f796d310d7fe22d83663c8e607d342407dc28c10d27aedc4a45c8ff70d, + 0x2f6877c1a818cf1f087343dc38dd120833574b9691540d03128a2d051c1be240, + 0xf418e13a90e4295bd384c4d4764398e1e44865058e6d85f10396a7cb0716494, + 0x1a6864de7ca70730f8657bed417c428aa5dddafee26ee78b942c86be61a962c7, + 0xf8be2e253cba2f128e7365d8b1ad95f8986968cc60224445f2bd717c26088d9, + 0x16a8d9f265a66f69fad6d7b744cf090e490552c6d4ac77f89f09d0ae70095a5b, + 0x25f1a51ea7f88847cd19c9dfa9c8587ac7a4f4b8a10bf900d20270398b9613e5, + 0x28d4a6eebf392a9378b7ad9aab8862245279a9f2c0b1678cb6d3141ebb14644e, + 0xad7537d9d5bb7e34936eadf66fe924d80c893745fdcebd5ea08b79f9137aed5, + 0x6ae9e1b3a2edb869b5c6f231fede58dc7dfe42bf3802394ce5d62c3a65567f7, + 0x1f5d4250771eb130c046c8df1e77f7f77da20709346a334dbd22c72191045cb1, + 0x14bd6a1b5678cda4ea3a16c3b5abbf38ee1d82219849cc37fbcbd934e7de1162, + 0x22905156b6bb357e2727bdcb8f39a66a09828307046296c6d5322abdb932d0bf, + 0x2023fcb87f89e6fe4cefc3d315249ed8133834b56aeab6fe07b7fc246b096c, + 0xeef78e23ad00648fcdb65eb246c737b7b4060b37b6b845eb914108f1316646f, + 0x1f3030be5da4e16c0468d631074a65f5457462fd6be6db36c3a522453164e48e, + 0x10dc200b8c1b565d4c2e88d5bc1bad12c490a20d05dcc4cf55e9644f3534455c, + 0x11a9cf0b8e97ea26ed0d49abf3a09233703333789a390d72db661fa70b1cc2c6, + 0x15b97860d1a835a706f54a97ff04a15c69dd3beb0f86b51c83803d490c2cf2f, + 0x1225bfd0d701b349214873ab03716319d9c96e3cd8d962028b17db843e4a7f19, + 0xf4ebaee2abcbc49d408aa52c60dcc093cb0da884c4a92d0f280d7b100600560, + 0xadeeea75944cd5d35045ec8cb6a57487287a92d1f70cd0b2389a4f128792ac6, + 0x1874870c72a32f0d385294a73d0ff67d7234af8e0ec57c63b4f77e72130591fc, + 0xcd011ee52170682d3777ba0085ec1620e19b1485d9898800dd2b1d74f613576, + 0x2e72b9107cc1e1a9bef16bb21a308c9fe3fc9221e55f5d4cbd43ee8de297e02b, + 0x7ad8d8e863868745d2c0c6e1d08dd357803f4653ea2045792edb563399f7d84, + 0x273d3298e5b22284dd66bb0f5e963f0a6af68c14018c728fc42cc82acc384db3, + 0x111b832918546dae5a1a71d312b412462b9d2bbe867be4fdf089eb15820bfe13, + 0xc4dec2328aabeec22bef040c565b1227753c1dbcd9e470f906a4fcb5cdbe7ee, + 0xd21f2bf0ab2f74a5eb38abf787121f015d88ac22de1490c548d0606b8e6d7b4, + 0x1e08837512f3cfe1319b8f8babf49e738abd159e322227401b7a5441978f77d3, + 0x211eaccc37cea3485cb8300994538c153b1dc5b8d63c96b437b91434642a11b4, + 0x123e045851f8649e6332e3e208b9d4db39099f077a1104555bc38f68c62deee8, + 0x8b66ae60a35e192963af9ca3e8681012d5288a5abc67065ba52bb151d4042e1, + 0x2e9188c8e02a08b719f7cf8af307de827d424a166e6f9ebb172ba41855a405c, + 0x52458b94157b0e5d0b5cef9ffe8e014eafd7cfc1b43611faf31c2d8d59b4eac, + 0x24bb0266c20a04010addd514bf76e3da1276d13cc58faf89668e238b9ed2ed6f, + 0xcd9a619dc0621a5f4cdba8303b5f69da6206bf28a04b96d4fdfd3a214e3e54e, + 0x119949b91445ca55fa6ea8da2c11d93892e5b4cf3485599f41106eef149eea9a, + 0x265ec37b545cd5dc12a27c1128c314a13e8cb222b5d25c3b9061934e93cb97b, + 0x6aa84e7c246cd723c78fa394a7ded19596e074fff4ac200171a1f4c75bd7924, + 0x1b4e6c237527565068aa65269cd73b5c4675b1148fc31fbabcdcaa341f63205f, + 0x2bc7d97b099113c5ab67254ffaca493041bc43e8d344be98152e98a4fb786da1, + 0x1e8fd4145c4cda03e17eb62c0f9d8cc97f5b13b83ba8400b57a3d80009c00eeb, + 0xde458ac4a2ca65e25c6c028b23e73fcad1bdb3e3f1b6a730eb47e04dfa65318, + 0x2d1ba2bfddb58785ae140c239197729f0c60ef611f3b377d4aae3c6dd444b5b, + 0x29d94b0688e3236b20967ec747b92e837fcbc396fd6c348b1e0c748a6ee021f1, + 0x2ec6c5500bc7998c7b821d209c608a630195b734c02a5aeb15b1c755b7857d5f, + 0xd185c970b8d03fab0cb058605d2c0871c76af2047efcaca0e1be393a4817ef2, + 0x300c58a0b3c59893a5acfa7a0adc1de29dfa3f16b4689af0535cc2513d60920c, + 0x2360aebfee8827a4b9037013a6dec8af8f38308d119b3167df19e3eced62ef6, + 0x43ba139aaacd5a1c1349104235e9855ee8802cae5a30a85edad853b092b5181, + 0x1b0597b0023cc90297b8a4e996676d65276b1a4c6409d7c3c26008e56cfe6f63, + 0xeb1857692cae615046d0febd92edbed96417c07b841b462f78b90960771ed0, + 0x6399b5873506855684d027c760fa5b89721ac3004096114ee2b0c5ea727eaa0, + 0x92636eca31acead1a2e63131e25a2cb4cb5e5db766615861f4fcb06e4321eb, + 0x2e1d940f15c6a1f49a28f66c0d539f5ec4431ebc533ddfef8acf0f5463b7d0fd, + 0x946412137bd02c889bc3f6600635398e5c29347a580994338e44a6fa41b40b9, + 0x18ec2c5948557c8699e5e425ae42b5f51db8faeadb62bab808d1662253e61cae, + 0xac166679eb2864d7674a89bda016c235736783820591cb9504b890b9117fe4b, + 0x4db97e1cff9f2fb62e16077221c20306c32f579be40d7838e6ec15320c38443, + 0xc4d540ab17d3ba0328f95369e86fb073f3660896d85a679ff9c6c99268bb7fc, + 0x2e6b4be5eef898dd7bf66b3754ad1bdbab013ab0ed99c1632a489c76987f2ef2, + 0x15f2072ffd2d6caa3d6ca13f7703a47c0bba942b0d9ba0b141047a297ae19899, + 0x1ef8155e5c33f8855bfdcc24ac895db935559d5dbc442514d4272e0b2270604d, + 0x194f4e345835e516564677d1af5193e67f26573afe1d12fd77673126e4b6c1e0, + 0x2a3fd58a40436abcf4ff7d7a582c5bab55edf2150a786ed51c56c6ff2b668c98, + 0x11729c1bf0a0f91ac34e4456d39ee6d2dd1c064368c2f0a8b76f555802d9af0d, + 0x2e13f7ce1f37ee5f2839bacd94feb1063960ee6438f10e01000769bc2856e755, + 0xe1442f5f0fa8737f50d8935fdfc204cf07e6fb3acd7c7cbc78fd28dce78deea, + 0x1aac56dc7ff6d0adb2cb7b01c67f487e3c812350450993bccb186b2fba077957, + 0xdb64a35a35a8fd6b486cf00f5324887f84c20240637b071d462a8896af11134, + 0x2cf6b1eb727612b4676e65d750a2cb15c82f13bc858e0bf6c1cf87b96f8796f2, + 0x761d1ff3a90fa0ece518705f2f80055b7667ff667063fb5bdaa950efc805199, + 0x92a84456e8ab1a26ed09f4c9c78dfbedbf4904937bbbaaae9a23dc680fb01c0, + 0xcf9cb1a0a9e17a9d6bf4b296ee0530c1b88141bce69357f964fbc22796465ce, + 0x1fd3b34a7c3a44e18fa8eadb896e5a17ed439bed8efd723246a009446bb95f0d, + 0x4b5ad182b4ba40ada5f69e436740417c1bc901b58515f969cff2fbde530787a, + 0x17aed43f02895475ab9427f84c57b965683d44ac92554d140ebd0434fefd6944, + 0x302772848bcacef898d59e149ef84e4822edaa6091e236aa41bd683acbd43a7f, + 0x14b66c4b0f5ee36c9f94644a4110cd09825cc8c85f6cb328391e83fcc86c71e9, + 0x18d6d00bd7b85619dd8b979158baaa87e5fd97a0c6d536c211a3ec663458fb2b, + 0xc094c29ad77018d4da01ac5d06bbaf353330bafc55a942fbaa30b4876e11240, + 0x1f6c4bd9672a340c114623c83ff250c8e410f0a3a11b4fe769099f8be230e4d, + 0x279d9751ee739e974ab65792beb9276773537e2095dbe80baf236adaf2d9de3f, + 0x2560999bf8b9ba17804b13067dd4b0b0022219dcbe167dab5f9300b68236da2a, + 0x211d8050a0cc08d433d487381dfee76e39c8afc46292f336565121fddf4f8b4, + 0x26dc6f484d1445c5f5c208ff1a487e372f1f8782dec0a5da03a85f706ef48e8c, + 0xd11eab567c463fd6796c3bb711467a6a78f7d847de201eb717dba516808d237, + 0x239b30a866e3778491b842a8c2df9ae14a6315981c2394c26d99ce97c4e7fce0, + 0x2e35cdbf79533471e4849a97467eb4d1b21c6ad8ef34691e08b74ef19c27735a, + 0x2237729ead5273e8d6acd40a63eb08813a2293e21dff54ea02619c6bdbb18c77, + 0x290c8723936f36b91aa1fc42768007ea904952ec0e41480d074b96d41703d648, + 0x1c279f1d50860ece8148cc1b59f5c14a850af2f3a7e2afb8fddf72964fdf9c53, + 0x1938e4214605f8e2fa59e7f90eb10eba0e984c24a5f5c1b719f41421229922e2, + 0x1b45ae36a32c689150489056ea161cf38ed1506f33a711d6b471657277d770ee, + 0x2f0ac8b7be349d38f0ae7f7dcd7cc86eb3aa06c708b3faff90f6b24a8b691431, + 0x1c40238de6c61dc8fdb5a75611be0d4bf7f5c4eb39fe9c065c26ae970e2b1f06, + 0x1b4baa71e93d13018ae4ebb790bc188c4b46c892c6782a27115bcac4d165f3dc, + 0x145d0fd15960dfe597187dcdd2927c5170b853928ee08686555ca5a57ab4b1d3, + 0x83791a423ac40504e7c99084980599a3359ca693c6aacc47b192a325d6df626, + 0x2999885c947c9dd00616bbfc088819ffe4c0d2f9033b04f408acfcf1d79651a3, + 0x8d0a62a3ee05bc36241af5eea0b62dfd4f28c31fbe77fbaae392fa7b05af4f2, + 0x18e93970a8a8070a1835114c4316e7ffc242eb128031aca086d3ce2cd3558e33, + 0x126590f273bacddc28fc87c100b5bccf95eea5c1607dbbcbf05b6db2992cc12e, + 0x21a7b2a18aba9b81406cfe7c64c1b0b4037c241e7565b52760d74e7720e92117, + 0x4985dff243cbbd8eac16b7b6f03603118293966de095b2e057043891bf5174d, + 0x18ad558446b1c9342e3846c398d05727ebc22d4a8c03de6380cbe55aab7241bb, + 0x1b055d908da8e662ee4b05c3c66886a35bcefb67946cfa6baeeddd8cb06fb65f, + 0x1a10263fb63bd4f23fdbacba6fb3f0d7499fea2e1e1547b36b17c4fa79dc0eba, + 0x114b2c3f7730ae08a1a31bbdc27ca1b3fda63d5d8eb55bdac6578b27633395cc, + 0x1a3f27e20df3c4045f3a67065ed869377e0c63a9a367f09f7a3bc63d4006bae3, + 0x1eebb48e654885e9fdc60b3ad67b988530923f65fa76983851b1092640bebef7, + 0x2ab3b05b9cc58838ee853f9d4a4817c7bbb1efa9deedb84d52c90ad9d80c2b1e, + 0xbe8d510c3f0d8edd5716971f2452b3106ae0f4933d894404bc0b5eeecebe356, + 0x300225e792be5f679ad2d4f8b3d070495bcdf876e50523cd877b4fce9bd30543, + 0x2df4b36388d11c2ca5d95c24c93e8ad10ba7b74735753cd0c7aa4805fadbf0f7, + 0xef6deac5ae321c054639444d4f0031663195997b4cfde163c75e989eb0629b6, + 0xfe041753831aa6a6bc0ea08a153bd5a409de14ecf636b3682539074356e5852, + 0x107105d12a394dbcb31832b57081aedb73e0aa17ac7c2faee1870d2dac147f89, + 0x1c2618562f04166bcfa93b80c537ea8b35aa07d8ee33703fda76079f7b78f1ce, + 0x27f7f4d91b9f452211799438a638f0c80e3db58ecb8d194e97e211e158df46fb, + 0x2a9982f31c9f628b43652dc20217d9a91bdfa94bd125e1e032e4f6626eb3bb02, + 0x2676c1451011dab5891ee8f715409412396960849613d13334af036176b7f343, + 0x27c95df56dbab27660262717556e57b6d3d66869a0f834bffdcdf58c80de932, + 0x50255c8e75aa4e294b921733803da9d6b9a9eeee28606bbda643a9122fc76b7, + 0x26a0dbba1128c1eed674bf21e7a7d23163d48634967d0daf7e467501768d237, + 0x16e80c84883b3370e75f1ab266b46f0b839accab3726278ec206998b62e789df, + 0x9782b1fb5ac39e3124c5e857253337a4503950a6dd151f005963c92254ad7d, + 0xa6975f45d3f7bb18c7db0a286cfdfbe0d75b79c74e67ad2265cd168c1670c1f, + 0x9b2d6b4df7d70732ad35eeed1b468efd932a780e9e74cb82c3dc1c47b4c8440, + 0x96195e37522c163f5fd66f13cac8bee72ae4b445224ebd85340a69b5a322739, + 0x26d015d70931042ece8bd15db6b08bc1496b7501baf0c8bf4a5534fd60422941, + 0x39f5d3bf59ceb12854079a2675ecece7b8cc5d9ab9c3d79adc1d181ca6198a9, + 0x1352b30ec61d92dd82e2360d38137d2fb02c1e78d6f99cc437e8640becc56122, + 0xbd8e9fb03b03709c0be6510b233fcffbc1f9f63f4d6019b110f77417fe381b1, + 0x14d37b7920faff9ff10ac3568122fe38221ac783e675bd5f6e69494755853723, + 0x2208c576d439a6c9c0c380e7063fff76a1f2685bbed6fd7bed23c732f345501a, + 0x8f4fa71b7c3c71c66c0075a5b7a0cb6271c6f7568979d3742e2847cd650aa55, + 0x30553e47d42844f4dc97d3b96dee7b6c483d2868125eb7de508164de2466b74e, + 0xe10c2cb9014f110cb54d27ae0130988b0c32a55f8d111f2bf797dc5b2c39a86, + 0x2801868c0861bcc953405e4964dfd447a8888d8839aa7e414de176c7c061e238, + 0x23ea7dafbfe7bf1d8f8b4ec83aa1f0ce31fdfc9ac5d2cca02f14ed1b87caf599, + 0x22ff012edcab66b7416dca632a59caba6d641e02f6fe47e7510ce945966f3721, + 0x2dfd80076ffbaecd97311a5c0b2314400005a1f07b6c21d92228583ca5b5a4b, + 0x23c45a61f4f2c8b3e066a26e232e26db93aaa24e2f65d26601ab2d7a1b95606, + 0x2072907f984ca35bce9ad3e82d8c30f9acc0ce98d145e4fe277e628489594e2e, + 0x8964e49de9a9fee1ca762ffbf07f8c4a8122bc4e90e7b567fcff008a6e45e6, + 0x2dc503267b1497a821453a73030f2a3523213bf0db9d5b061342cd859a1cd907, + 0x5fd4295ee0e76dc56af4119e7376a593e4bb185af60adddf232b91e67fb2aee, + 0x2092ffeb6b7760870dfaf471823ed7591fcf6e6bd5b1bcf43775d3c07b462706, + 0xbf1a49f9b9ac34d30e463ba797e3e08dfb424791ea612b280932ec208c7f800, + 0x272a88a53e263ff0a56bff4cc645fcc269d3ad5a63f9625ffe9eac93a36b77d4, + 0x27bb4022b1f689184b10d6f29824311ccc5e2ef14a3914aea8f06ccb7f2aa8ce, + 0x178f0ee74c834c0d22f7aebc5171f960b20546dd9cb53b3ded78a351ab41ce10, + 0xbf6df276b3f28afd5206a8646dd6f4c095fd98871a5060502f3a6444be321b5, + 0x219d4e79092df13b3223f935d2a0a2573c1f7d509a91dd7fc5533d4c3c5d098f, + 0x20f5702b749f56df810411ad9950ca9f87f1e0f97b8163280b3b2df05b679b4d, + 0x117284f038872bce68c791ad18246ed84badb692e338f716793f5a6bf216386e, + 0x2c2dbc65a26b313f84567ed71d40847093d08ce8c2b8a343c62b7f57ef63d968, + 0x1743373e3858cdc0582049ef7e0284d33403cc8bf56997c508a10b5fb008ae77, + 0xba28f299d1ca31db5a3bc0e8202e9ce8fe85f80c4f03f9eae2dab5de051a659, + 0xe46831dc32f73c1086055faeadf047d3408c2cc0dc2e725c878dc9ce68f17eb, + 0x1d8635cde2ec64aa50d8d979e29ef11fa0060bf86ea00762250e314e2881f70a, + 0xeb6d86f7e11b1e3dc21882511e03b7aa64063688fc52f655f12e34a343dbcb9, + 0x20bb2d1b0caed114b06fca648b0703a7346f6b2690f220f82e7710b586b6a81, + 0x1c4db5ac81e0e47818bfc08f7ec2d66bf15daaab8ee766728f588539eb60075e, + 0x16eba5f5dd46415f55abb8199b0069ad3ab7a78e8eedfafcae845760a4b1e525, + 0x46718c49cfcd67cfc27daaf0bc00db0165a8b34bd1801110b85c3f890779f02, + 0x10eccf3b4cf167cd78f9eeeacc462eed71eb92a2e31bdc1fc4b16c0b19feb44f, + 0x16e1b2c0dd88527774f18bc53f4274fd15a5afcf3656f149ba7bf0d67050f3dd, + 0x1d13bd396da5a68e7b801ff0b2c6c2725f961bf633d0dfaf1a4b2c904969ae53, + 0x2023518104868b1b97d9a5170d7a33230bff0618df4a31b381fbe9a0ea3224f4, + 0x84c4f9050120239d86cb0d84535ccb94821f0a1def04495ffeb559f153ddc26, + 0x1ff6f423d94667ef2d79660600e05c570f74d77ae07139d2019069ff96c83566, + 0x7b5719a1e09b96a5ce2c130b9d3ec76002d81bd6a8b46ad27274036bb363bba + ], + [ + [ + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x111d04c083f51a6fdf87412a537f6601076d61f435094ea16946efbfa4893e97, + 0x133c5913f25ff5eaa860d0318f6a4b4349fd22f2d53530e5c785b70988a3a88, + 0x8875f47d6f518c8c2df51a786bf2207aade284067228f440e7d0307520a56cf, + 0xba9f44a107a81cb23fba66f2bc34152728f5f5ca68406649a7efe47c9473f21, + 0x542832ab23b6c7a4b547a1066037152a2442e998c5381ba97698413153ba6f1, + 0xba1f764367360952942ccb6edf051c8f937906a816641e0d1e9e2ed26906fa8, + 0x2e0611fa4ca3985d7bfaf512f21a4081141f4ed0dc4b022834d3cb6cfd8b7ffc, + 0xe6f23c0ef6f159dec68341a87830fb864b6c08cb954a14a2500876697897fb7, + 0x1a7a2a4a08d87e75f720302bead7ca21c8f7c2ed2debaced9b8b1b2da461cbc, + 0x1d8005df48c8565987dbb442b482cae5bfc10ee486ecc5b670ce861345979d1d, + 0x28122254823f8926acb7e98f557e796282e5e1271618858e76d49d0886da16f3, + 0x2414d4aefc7b4857df681328e68a582d23b2dcffd579a8e6aeed6c61050e05cd, + 0x2f710c72d6da19c7d87cbffd55665b472b0265d13e2326a9a33b96e95d3746b6, + 0x2e285441d0bed90bb41d6480836850e4d76da8211b04a236dbc7c3c30320c00e, + 0x2964901a2b42e9aea1a6593662aeb9e12077a287434bda4ec2012e36a19dc95c + ], + [ + 0x69b1779dec3eaded3f07d0c3e6cecd6cffe78d747faedad9c90665aa2d92cb3, + 0x187aae261ef3ee21b37023518a071675c6d00bde82bd7f5441448abb632a764b, + 0x169538094d4f752529471e3fddc9ef994cfad4f96dcc7d636f0fd509b8eb9c31, + 0xa68830f19c0a729b2f89be27373d397ae1157bf507e7799d4220166ea0982d7, + 0x18ae39086eebb98d1fc5f05fa0f87ddcb149b0afe38d1bbb85a65697895e63f, + 0x4c5ebc771344cc0612765710bfcb1c2e6097abc3d346f049495f7d7b7f06cb1, + 0x29faa7dadc8b7e9588d4a601e77bd80aadf272a1bfec3c443ca3ccac81d9e1e1, + 0x2acf3493012bbd818724e7ceda2431e97c8933bfaeb5d7463b512e6e8e8f7fcc, + 0x23b34612e7d052f6b312ca0e0cf70034ad232d9bf63c88821085383b6f6ec4a3, + 0x11680cc6e80b0e430a4cd3607017fa8331d86c4d03a96dfc18767c97cbe0a197, + 0x1fa772ebde6f3732444623d67fe991116298f8f30a2d1010c8ae6132a3d6907f, + 0x2e63f1740332f57e8317f2592ebd8db0812714d6604132d525e33e19b3c98494, + 0x1202e349d1d7b805846e90834efc911eb6b10c2a09eaeaa29ed288bd779b14f1, + 0x168fdc32d4aa8dc9034ad4a4fafee89f0ed5c980d3db424d38f8ce5cd04c237c, + 0xb9ae9f5ee6ad70a651b4b66e34f521b130d18c49464d86fe5d4b1820489028f, + 0x6c2194af72fac58ca13a2a5e3223104ef49a540fd2eaea0d67a920d8567040a + ], + [ + 0x1fa4effc83498d19aaa598b7771f88a0554dddda89d32dcf8a6f4cf776d13b99, + 0xda28ede7f63f75596a2568b2dd7a584576e5b282f284795b1a7aa21663822b1, + 0x199835da95f6eb22c591ebe514c7f283f674fcfa1eb787dfee5781a64f082439, + 0x2af560600b3e25abcc7f78a4d6e2cd3fd99bcba075ab82b55e9841bef7b9210d, + 0x101544d131454f20b549b24a65ec84f1b3221fd9b43461ddc6d156833b34c52a, + 0x1a51740cda5e45ea4d4bd7bf5ce5466a66a11afb5bc93cf10d5309e07d410e4e, + 0x1324558b8a5d4ba61b17790128be9f2440c0085dd5d6065b88f0a3b2537bdadd, + 0x13473024ba419fc2a7743e7df8fc8375aab150d3753a54250a808d66f2d06b91, + 0x13f15bc6453df6f9383446550534dc57aedb10139e3053e83bafdd99356175f0, + 0x1314b54f8786096244532c9f054b379636e2b58bfdceb3d48dfb2210b529b4e5, + 0x56a8ecd232a674c63d7b603ef8cd06321c560df2fd3f6c2649af576467fd798, + 0x98b740976c2a1031e75132e050bf3838b739d061582543c1c7f95c152ee262, + 0x24b96dbebfab6d23fa32c2c8e7758cb240bacd8143323c53cdb48dc8b65f8e4, + 0x15bbd5619f0d59790804f2b9b37e069fc909a2796d1f77d0c62609deda2d0278, + 0x4760054bd5d07132548bed7657f17c61c038ebcdfdd4025c7b802e08948e108, + 0xa5494c9bcfa06aa72c36fd22d98fe72dc14dc0e4e74e03d1755f38ac34050ad + ], + [ + 0x1676f5c07417ab54c37ec8ae1a8314bdeeb09964769881592043dffcb26bf41, + 0x2043bfe52d2964e4a3b2da5e30107716cc764f9b1c8ba463f215ab1f7f03498b, + 0xdbd8662511dd7000991b39da129f9d03b565a0cd2f218d6eabbb49a25f105e5, + 0x11b33a9f1818ed7f581cac020051de26fe28dc0bd8cb1a4457d5a8447bdbd6fc, + 0x26f2f58d63ca6ef59bb95206ce3ed3124885ec21762bbb1db1d6a7771ec6650, + 0x2eb6ed568377b696ad3cb237064ec68e390c24886e1f122d21d7cf3290dc6d08, + 0x18faaf1c91e002f7dbbd12f408bd5c5b92f38e02ce3635824821e0347faf53ec, + 0x29437af1b14f637a1f0e39955f2604bf20439fcb2a090e346aa65a9ebe69788e, + 0xedf86bf1b1599fe27c66f3494862d75df7764070a8263cf88778f7287938d8e, + 0x1336b208e00d8ebac83246a96ebdde351063fa3f635887e753a0ce3e29c7eedd, + 0x2646341eb44b4800d56084cb48500fac48fc533891f557e96784cc6004d8928b, + 0x6f53c79fed9e09848e112a0742d8ae84a04bd9ba5aa2765b1e5edfb1602140f, + 0x2a3c9f55afacee735a1b515526426384ad044291f7691974d9c05c634b43947e, + 0x1e16e9ca2502d696023bce3427244ad6553ce86bbc4c349a34ba61067c6b6d6a, + 0x2a4c6d3259779c396ef8173ae5fe87bd611dbe25d1c048ada96306db1e3a40d, + 0x265ca211180b012c378e0198f0b5f7758c155e3675fadf92ca79156bd56fe339 + ], + [ + 0x1f4e7bbc8d42779e58aa07bf54ff324b814fe687b4c8eb81b9b7e74448ee27ff, + 0x27b48a636a39b51a938aea3eb552091559fbfbe71e096d518c40d908dd2570ee, + 0xdd0c118f15ae07e5db55077dfa46e08109954d99e18d72cd2caf613920e390b, + 0x45c617f604c1ac9fb8d76e8d380322e5a3b69fa7b7c2ae2c8ec5966d6a4c788, + 0x25b974fc5129d82ae4c6246e35f802e03440ead09995865313c8ca91c820c2d1, + 0x181589b140c9109e492fc3ec7d8ca8e3c25a7ce58df06f13ef43561d58c5926e, + 0xee1288b29855e2e38dd26292b39e260529841344538d6499996a32e7cc523f3, + 0x206e4d445315b764280cc643b9479f49946ea86d7304b6a2c692ac34d7c98d34, + 0x1641648c26b5a2dc297daaa6d4ddb6a2f258ba738f9094e7c5cda6efa8c993b1, + 0x1887be87f7a352410482ef3bdcf7ef17976e087eb8990c76d7e971c44c048239, + 0x231f2c98bda8d48bb4a6d9c98bbbc16027235a22a1ed4f88bc8d3a6e582209f2, + 0x1fcea89286dc1db61fe1111606af396e98cb53dab5199750aa5e5d11561fb145, + 0xf7bfcfab17db34c144cee44636bdeadfab44a6bf4fc8ef384ec89a4ae9ed209, + 0x1dd0a5502743aaa9f583bd0ad35de13ad8d5fc98f1961f2612ad4c28fd9f9fa, + 0x1959db01f5c8bb0cf483490373e75b0451b87b43e59181be0b6016674f3f5efb, + 0x21f659fedaf6c2617f17d637cd6f54a27782f4e8431f87af5c8591932ce7dab7 + ], + [ + 0xf6b18c98fc89fbfa99a04c8c96ae5db35c296479f484b680df905d4cbd1dfa9, + 0x17fe75a3d11b4b9d2acf7856d6dea3bbac62ade0c501347b16864f3c73ebb7f9, + 0x7c921bf45e354848a60b0e5f292bb03c2469498b9c1e4d322f4afd1867408c9, + 0xe6197fe502328d0ef7f9b930355312b347204b877e7f85d9b569dc34f064c1a, + 0x2d409bf78bd6f6a4eca7397d065023f0bb6732207925d3ce4beef9f621da2ba2, + 0x205a6d5aab2d224b668c70fcb41582ee9ebe1ff099292b4bc50af8b292c0ea42, + 0x2380ab051d0ac580a7d116f4a9337eb31090a4c7ecbd4e638e7717b7a52bf106, + 0x1382c3c24bf2489fe9efd80a163e650111f5d9885e58a9ed729dca1f9a74e59f, + 0x280c4522ad0ffd92c391e94c70f87120b8341890c3329af050625f2be52f3a41, + 0x1f405a9483311e1497568f1bdcd6d58cd6bc813982a0e71561b620003b888204, + 0x1cafcfb62926fbc04857b0bd7d7392b8d8add16b5cbefb54b4d5312826e89942, + 0xa12e162620e71beeb203be56594416b083e7e94eec23e0f44a5ffe9e159508b, + 0x17203c4d2e1a428a17be2c27d1c4c5960dfc6aa36f22bdde8be56a0cd44e71ab, + 0xed2cfae7b36f470a7d1f6940f914e8ecd322bfd6b50f9ad9f6a2226e7a95db4, + 0x1849cd0910d72eacc32d891b71faf500bcb93e1cef2504af443b94f8b1ce7212, + 0x1e463ae3f4c3bd047aa1049f4f091a2f1d5d3550e3d5801fcff68f9a5e6828f4 + ], + [ + 0xe6cd10883e1e11c6c191d36329f30eb0045af06c2d86d0c439f5c1f4fef54b, + 0x2326c3dca7aab6b1852654fb13fff42a152ca9632124216cc7cc6f6d37522a59, + 0x1f694d1acbaab0ea5bc026a1864d568be555b89c0f49b6134e9b895ae141da86, + 0xcdfe099e7a154278dfb6c0388b9daa1e8ff323a20be6a6aa7a8438333f879cb, + 0x17f732cc1354b1fb476e70568d2dcb0b6683d30b02415dfd385504736aa86de6, + 0x28239a882dc7b2f3ff7b9aa8de9e3d81af736d4ee6ed991d5c6b4fa540148f43, + 0x158926b9e94b10fcb321b293bb8a8647627a5bd31315808d397c1c94f650f2cd, + 0x17cd11864fd2c73d0867d37264b4ca14df935a82f2a6f432c4998135fa5f4aa0, + 0x1d772098b6154921db8e7506e6f0372ca44f20af3386e13bcf71ff5dc0d61b1b, + 0x209576be72db7b0c9fe2b8329125e7dff0489a8e900a5f14c1e6e48604134264, + 0xb7ab1ef17ff6235f7737f044161902f03d594cf4a0cc67b4ffb4711ade1eb0f, + 0x1b1bbf4e9f706051716a0e28990caf17573086a5d818c038836696808b12d8e5, + 0x22a8ee74367413eccf7aa03fdd420c6bb6255a6dd82081d6b14eda9a9752329b, + 0x2c785f9d8834f5cf5d08f106d5f9918340fd414abe24f0a9ff2b8e0492b44d83, + 0x4b5dc2057b88170a718a102e0ca9177afc757ee26773a0290c6bab159ca4fb9, + 0x27412191fa2b2e5327a11d290e4b439a4124f48145c61ff4ece8448a4373eadf + ], + [ + 0x425a9641fb01558bc7170a2ffc24eb6a514198b296a1629cc284d983bca8757, + 0x80c442909227f4a9da92e33237f9a82cb0c6f7d0c4155bdea5c6517b046eb9e, + 0x1604de6a2db122bdd5d839540a1005ed402425bac3b85e3a72224d337402bdec, + 0x15ded859d501c2733feaddde22ff36fa8ae85803aec7a204f42b1f6553bcc655, + 0x40db0defe6ba4797b74a43125cf34d86a2b33e7a22e2710b0fb7a5568893aac, + 0x1ab15f2fde6f535e77e615c8c2602193d45860cc015849df578f9fef9a5bb283, + 0x264fadcc791aa18e76751a895242c30cdbbd1197a90a456dc278e10bf0bff5e5, + 0x2de279fcf77a270823a91a6cd1aafb58e9e3ab32fdff0b3b05c98d554db6fad3, + 0x53ed8ad550d8992f4b9814920183dd839bf355eaca8cc7b07020a22614a808a, + 0x279702b135d144ede943195269c00bf620f058bf0186ce9fff3cb38b22245a, + 0x179a82b77f2ccb94b38eb582ac4abbb16df429ecc22471be73cc7766f96d9948, + 0x89efed00e9d993f5fc1d5af2f2b5d47a9b70e6d5a603fbaaa8f65102123efd7, + 0x21e25f0a7f8edc38de25ba605a86cc08e08ccb03e77c5e0b9edabe74768b60c0, + 0xd8dbc3fc854c0665c30c48846d7bb0eb18d3d78a4f70fef07f242e45b865eaa, + 0x17bdf338072884b522ce3c50ef4711091b9daf48a43374bdc0a830c37e5dcdc8, + 0xb3a769c8b371562260395ee4f348f88bb056a2f0ec0f98e4e633bf7d943615f + ], + [ + 0x397a7d7434b0aa941348de45aec442cd5cad2c398884950e8233c58dd50335, + 0x2b1c00ea00893f9f91331bc907397db865c37d3bc6c4b39b81cd931696fd7837, + 0x25970ce31b7b10cef221267bb1be1656ec29146df06fdb5b4f6fe6607523aa08, + 0x2d4026bfa7b37a19a300abaf2e1d5c32dbcd42240ed860f681f61dd6d6214cef, + 0x29e89034942414a1ff6833d6e22742d4106e0f5f37d1f2ab80e5444e5a52c9c7, + 0x32b6266f24017fde1b281d0fe206dff30b539d5c5ba13b5312e488d8d6f194b, + 0x2ea014b61ed575392239bd9411c0a6c4202b7334cf2e0dd8c3040528e4a3dfda, + 0x12ced5254e260a9db7abe0cbea26396680f6e57dc07732a755d409ef751200b9, + 0x1d4f9ba4fd8ce4ef193b9f870f44956079538d63bce344f9016ac5ed63a99a5e, + 0x2c9c3135cf64b89eb5b714d7b2ebcd81fc7edae637cc6116591df208b6b2583, + 0x18b63685f6fed2aa1904856378442151dd1fa01c7ce6121d23e1e9ee20b42558, + 0x2b202e1d2626c6793d68aacf9c3a8fffb27cdf5a0b83ff8f3504f9ab26a43d15, + 0x6a78dfde1458ee341a089c15f953a2193527dffb43f552cdad595da7c6fecc6, + 0x22f62e45e50084696ac2512a25db9925244cf0214b6b543d3a9f83b8e8e58ffa, + 0x2d9379e69b178208b8496b8a0a0a90d578b21f090c53042be4767e3c10d3b40e, + 0x1adb4c87433d866e8fe5ae26d01477e3962879c20c8c3a170c0727167c06d0b8 + ], + [ + 0x1d66f208fc04411a1385c22e203dc08f0bac2f7cd9dfaccdec20d3b93252ad04, + 0x92f03c7e98e61c2a85943ffaf9c04dbb0145fc2055e4d5be90bb68b90109746, + 0x14956f80a65b01f9ee97e2eb070e9df2711cb8bcb538dd98e532636cc60782e8, + 0xbccb669cb016d498464944f7192ecff6716e6cb5f895d2715bcbbb65b1288c0, + 0x121d2ba5bd8f232ecf44aacf1044cd6ab6f93f1e537d7d1541754fd49f51b225, + 0x4e358f259a33244f4058a056110a26816bbec3c76ab6a5f7be93c9e0c92f3eb, + 0x2da2603a26d4fdec35318204ba5060663e15a0b1e4d9395258d5e6eecaea8fb1, + 0xef5f9ee6ba1ae1d1264cf1a36e0fe4b8043ab0bddf9b9c3200fb687a8ea5c83, + 0xd53d61c8a5214e0c4715274ad67a5d6a2cfb9fc3c1e791d41de22c8ba8468a4, + 0x252e78b4838ad5007f518bb9c6a4ce501871f71128eee3f0c9784cd64b183fbf, + 0xa27a8d1af6a0460ae1724f32f21a06b036668d0a863be50fcc47fec5763ce93, + 0x3048a265d0eeb40e5a531633ac22bb825f75cee9036e66a061be3d4d248c862, + 0x3fd94e51bbda6843d31a282530d54240aa496165d644d5d7737b1e5a7d60d52, + 0x2f26bc13ae48520a439c9f546abb35a1222a307e38fafc3e7ffc843f6c77d7ad, + 0x14057d02e5ebcf33c166e18fe904defa9e342a19e88d42336377f1c5e67ec30, + 0x1fc26ed027db7b9e7241c2c760176662f634ba05a9ca7a850e184ae588cbe215 + ], + [ + 0xec1ed3ae3beac4ddd1fdb17b9c7c648e7ec81885a07a5bcbd967e6a3676f356, + 0x2a0f77bb3624fc4826c9a2a66be4ec75dbc21642a16fcc4182d2d65c0fd8d7ff, + 0x1d799ae83ef6552f30edc47b9e82adc0503dc4b74da40ba0bbd2cc9eb1b0a53, + 0x5de1099c65f08a990ac0f1f45ec2fb872c771e10275dccfa4fce1146639d0d5, + 0xf0913eb4ee7d3c02d8ce73d1cec2b6cbb176a92129b34a294adf066243ff6bd, + 0x25a9ac2d1ef84abd98927b52c24f38796ea60e63858ec5b50196d7e169c93b84, + 0x20a0e3f4e1249c4c6af100dfdf63f8bdc69ec7885bcd0d2c2e98d98f9bb9d104, + 0x6b7e18d01b47ff8e4ef08078e8128a06693be657489492ac4195a854722bdfd, + 0x12cf87253913d45d287e975f2b4f5b909d16a87d89c889057f666f6ba61389b0, + 0x29a7d554e9ffbee639867842fd0e7d41ea9b1bc9621b654fcb398f71c95b668e, + 0x186756775058d09c639cdabbacd01bf3c2744152156fbf7e8f3e999fb610ed38, + 0x2532dd7487fcae0dc3a7ac50b80ec330c6fb6d4cf885f1135988bf6dfc010a6f, + 0x2efe529db1de3c01d6fe7fb8a71f1eaab6af1641fb1f7aad4f2b88cd13c9fe5, + 0xaf825f7ca24b4a285f544762d9defdc99f2b85c1b89fc5ff2079d3d50e6d4ea, + 0x17818dd0254b291d0d8f4f1a458c6a21d8841153661812bbe986b1403cf270df, + 0x10175fb6f81b16436af30682f36fbab396eddb7829a50e946c75f27e260987c7 + ], + [ + 0xb3e601e36a5d82e0214362c8419474dc1cc2c0ed8126534d69a3f790b27c603, + 0x1083b742d35332a8b79b80e7dc04a72f7e86692e529b6a1ec5687334b607da7c, + 0x12417c001be86197013b2b4871c4e9b0dceb83991919a9cafacfe54666f590af, + 0x2c465d9b5eb852d79338b427b3184d941f34046172a82cce44e2b8e5c4379478, + 0xa0fe66c0d4de00cc7761008732a0097fb14d6465f9d1df835e0423fb207d979, + 0x2f521f24bc02286ae2bf8484fbbc39843886755f52bfec7d3dd5df78d340721d, + 0x2f1d3eed36018f9679711e030bdbae51224b5efb8b1eb1cdca8ab886212f0fb, + 0x23aa7ccc3751b740eec9f35a29986bc958a4dbc7c4b12eab2be8376706deb20e, + 0x2b088cd30a10899babc325bba32aa343d329f9a8782469c4d25f0f237ff607fd, + 0x305a0c2c2c4d35998e9913829f5602504363f21bd720347350b604193e79bc3f, + 0x8bd9ddd192d797a19dd1da049beb39fa6596598a27031ea1c2b28966d96180c, + 0x12cee8e3d1cac1ca84517ab3def487c460aec058348ff220c801b78979af9e61, + 0xcab504b22a3573d09509f85d3fbd94e94417acb25392342bacd684006c37185, + 0x160590968429f480f55611c6448912fdf423d37bf483c36acccc1ac9a29d2a53, + 0x1c95c2917353c53b4cdb7f750a0fe86ce10f8d5bdb018032d3f793797d7c0a35, + 0x23d300373bb8ebf7dbcf314a3c0b1fdecd5cae23f7e7bb915bcdb6a6782b57fb + ], + [ + 0x163cb4e3a5ec92e57b25b095a3aaa8cfdc4ce59267718cc6090a07e14af10b0d, + 0x53e95f9455bc6499d447b6cedd0b6aad9cbced97ccf10060f3c9ef51e28e76d, + 0x2171fd11f94485466a819e24d0acef08b0c87d78b46d93bb9462b443fa40cdc5, + 0x23918075c8fa0929befc2b171f99ebe9ddd6683594ef9a83f84d4acfd9592d59, + 0x898ed1ec1a43687ff6aba32de5f819434528a0752b3928331899b0646b2f061, + 0x1dc3f7a659530a13accad181b6e265474108d8b1469266552dfbc38cb679d06d, + 0xe388bb105242406e372080e997a31392cf4ffbd9c694163fc366eae770e435d, + 0x2273c370eb5810c03903605d7cc94d5a92af6aaaa7b844f35189e77406a7e86b, + 0x19972ffdde7898ec8be4fb28e4b19efaa43c7ee20c88e29096ebe872e1c19475, + 0x61d78e1953d1943e2d968335b73e15fecef89075e96c943d39702b214ddc5fa, + 0x194184a825de9e9b63ed7a7bd071253ef5903e1e75a50536db93c26311a72017, + 0x21c0d1874decaf90613183ea827b91c1b2951839f71f329cb9c9b0753ffaefee, + 0x1cb33ad2ba7dd0c2063443432a847bccce775a8daf868e0c474905a4fa36d70e, + 0x2bb32cf60f8d469edb1b6c56493d4c9338b4051ae2514d4b6082ef18b1d5228a, + 0x2495b3c1bfec60741808149333fc43f04d79dec56582c292829ffdfb3c1a3c4, + 0xf0417fa6237167e741525261306c17664dc3efa9247aa0d4bcfff38e89dedee + ], + [ + 0x2dca90f3e5a15b29895f48d7a1290d7a33646b89620dd0a8ccde3aa3a51d41cb, + 0x5904dae3470d40ce12749b27d646e620e8519e2b17cfa016caeb89d9e34ee6e, + 0x22e9bf2aa02fe65e3cc74fb3d83d4e3351869bd30528c378958af462efd645ff, + 0x15d7fba62bac57be5d97452a3c06d9fa757f144df166479ee7306967480a287d, + 0x11e0b2343ef371d2d6d22805974f2539b6e510d761e0da170d0da90095a13262, + 0x2ba39845393fcc776fd383e535d567621c7f64005a83a6f7f48222bc902092a8, + 0x25143649c13e08d4b00bf34d2aa1a8e450f89788e27766896217047155c5bf1e, + 0x2a7310e75fafe902e20287a91abe388aae8420b1ea4660dd7c159c26b9632cd1, + 0x1fa6944703fe0012a16ee6042529ff02bc804313ef8c6d8b0f910a75e6f47739, + 0x261f975babd7692822473b8e39f948b9cf98730a9785de393179d4bb99dacdc8, + 0x2e08b28bdcc417d9643b3008085a27f4a9876792d3915c8b9da3567a6dd6ce82, + 0x17e9ed191c5641d768b0e55ec0d4a85f6e5419d32f5668d397d5b6cb805387f, + 0xaaf37d1f53dd0556e347ec705962379077cd543198e1c27593f4454521261f7, + 0x2a4a72e9dfe5bf25f6fde750a1847e5b44298ba58fb504be57a595e7fccdc404, + 0x2adec8549dffde7238b2bda6e7732990a911700c8d35288baa39e67015953231, + 0x1e8fd20a8030fdd94e2c4353d8f82b4b212bf887bc59615814890b0f92a47d90 + ], + [ + 0x2c78ee5ea16d38f0beb9dc0733c4bb1893cb33ff671b737a1122d64f729cff22, + 0x2e563b9dc5a3d4d5a93f476b466e371019c77fd6eea506126a4f79274f2f6b9b, + 0x72ea2f5cdc8a3789fbcea414a91e7b27bbfb3151df510d080ff4ef7cc73f0d9, + 0x2b6f16f812ba903901355955cc4ddb99f24f1c6e26430947e51811a68311bbf, + 0x1d59d5c10b0c9dd347899377da35b7e677c7d39ef1b49166b974a7f2bc99c946, + 0x4730fe04e0108c9a5145a5c48e60c5457e4708522157bfe0f82af5c664d6ea2, + 0x12ec24239ba1b0fc9f952550a223a52d209d8d22b8b21ac24881a2719276be0e, + 0x20098399725ee15d93ffd3e481e4a7b95c8c5083f9d69bff1714eea7c7d82d49, + 0x18237af733bc44418ac84e623f483a6be28b8f21d033fbf099d645ba20f1fc26, + 0x1e3d6cef37f9bdac23d1b381a6c58d0ecf06a6ebf58dfa7a995a443ed7df68e9, + 0x28e55b0bed59191216d5dbe1dd05b22c009b079de877fd54aaf5401d2c867e02, + 0xc6c9ec31c9e3be0744919fc555c77c0c125927bd16de2807712b35ca26dd045, + 0x2a607facd3936fdd0e84e9bc3e4b4bac86e8102c2b5ad15cae550d28b3654e73, + 0xc509a4bf48ad76e90410bea34a8919741608bbbb6b5503c93e732036f079d12, + 0x178074303b90d8985e376584b8b8dfb7f952f8f4cf84d815f90baaa3b644c4c6, + 0x18572826385dfc6eeca4d3c71d110b04abae013c5450d9e4947a3d019bb41b6f + ], + [ + 0x2af324ec4f9e7786dcf00439c75a294bff753e3292bbf62e66471fa730f19c79, + 0x14560083d980d172dd40c9426cff41467acea41d7f48ff11ac5fcc087ba2d5b8, + 0x260f751c7823abae61b8f3748c84791c0bd84acf7eb6854870250178e9a52cf5, + 0xf6673b7fb4be8cdea74aaa7802c9c73ff0d53a98e94a2bc60685d890a24fdeb, + 0x1a15b7e2de27125f2e6a74f4ec7cd2455f1bbfaeb1155f1af819bdb5fe54241d, + 0x75a09e41e74de8a2ac7fef27591e76a77c851e1a51185f31e99b5e08f01cc74, + 0x79c04944d50b4777dd0bebe953600645ceca9d65fba020f97365146bef9c6ce, + 0x2ca2bac7c1aa0c64e684123f0ffe22173923052b6a01f3c29be80137fd8972c, + 0x13d9035a0dc798b04dcef0f08edd241524fdca0e95ba9cac05d207bd317e19cf, + 0x1d6657d791831169c56b6e9a201f8b7b240246a2d0f854430489b983454032d4, + 0x1c89d8f975f0304282ad8f7bd41c12c3b18ac6b80e4065fccda423bbb3ffa786, + 0x20829ef3df9c183f8965e49c8f315c2995a6446a76053543eb750145f1a77400, + 0x14a2bd5a56f87009db981546533202f3af812d2ef4d6b037f2830853b9f9039c, + 0x199733da4aeed8d6cd148461617e8e46de22d3720431fc1605619b12a7fd4e2a, + 0x1f5fc060028ba07d11fc9477f4faffe79a81040ea9a04c568267644895e6737f, + 0x208b7c8c1ff8422d4a1bd13a02a94681ce217d925f40d2875f73def14de7a220 + ] + ], +[ +[ +0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, +0x214e865e2eabdb9fe5d563a141ce18bb254029e0e04e59c2fecb0850b5ff572f, +0x1e0e35883b0f1794db023f80354a83951383b62282dab4129db1d19e605c316e, +0x5c51080a74b8d28b50b14228c6a6de8ad5397cb9a4b9c6cf86bb807cad76074, +0x244e0857b01e7d7aa0eb2ef334fde51f16a2411abfec2c3beb6c62f7a7036217, +0x2a04852a90b74143f3808a150e9f1371e0177a1b6e72cbcb0fb8f1ddce8a8d02, +0x305a319725a0b7bf3def3f71517cc2bbae386b651550fe9405cec98dee21b1d6, +0xd92a7b009466985fef388ca3d70c7e2c0c2670d2260df83659d776002843107, +0x2a67eefc0930f82c8bc66ffad5ac09c107407814131cd645bc18cda6fff4f52e, +0x99674734918ce9329409e50f2e9041bd072f9d827737de601f09c7ade19d35, +0x449112125b3f10a53b2c465f2bf1183f03c13825e76d40af75da04b8137780e, +0x2c1ee387a8c15e7dbe92032a242801d1f7b411a7e5a36bfc4fa2749a22cacca, +0x1d687a4e31c6b3c91e67dc9d9dd9c47493c839b5e13ca1a9310e6ba011421cf7, +0x1dc79a5d9de443db444de0f08ac67be4826d018fd86139ee9eea781f4df48939, +0x2d5cf8172c587c0513f26105419f56319763c5cb42cf9ecb5e27d9a88c5d16c9, +0x25bacabe48b3f030c806aa879f25241fbbb17534d686bda8f5d478662b2a5ab5 +], +[ +0x69b1779dec3eaded3f07d0c3e6cecd6cffe78d747faedad9c90665aa2d92cb3, +0x29fb24fcfdda928bc18f54d5594a0c23bb822c277fe2bb999e04a37830c7595b, +0xc05c2d8ee022c59521bd441aa15fa2ddf43e6ef9811b10fe9640ee5e888c388, +0x122ca048d7c6d4b9053b59ab67650d10d22515f1365b2267c086dc7a168de657, +0x2fbb74d7dd4ab190e6244236580314c820bbfe34045f43ce14d1ec0049afa187, +0x2cadba86ff66600cf28005f0ac4870914118c62e110e3ae0513dedf3bd846d29, +0x30d436b101fcfc29d67d7fc4473218360f1a52bb7316c4a080a55c0d01a709e, +0x1041a8891a37452dae7c58396d225a87ef1985f94485bc3bb94588dd00132b2b, +0x20e8656cb5d68cf5f5aabd0cbc2384b00cd1b65ea77b1c0495a65f3270e4d881, +0x17107096614bacedf147ec8ba8ddbff1d99d5ec24df5495279a720144ad00dd2, +0x2615060f9b8b7972aad3c06f80079700edc591d0e701ac424203a6a7beb5931f, +0x1406d86f9f6ed52732899488e062f293c681767645a636d8f078dd40672e632f, +0x47dbe55f778c815cd8c79dac7d59526dc76570fef2224a93640c98770c056cf, +0x2dcdb0a971c5aa120c3d873cbd072083a649e903145e00829aa8202ef09be93b, +0x2bf712452a11b06765a0d8c7f0af790527a665863294a32cfa3d762a5aca3b0c, +0x12a68ac33549f6902b128cb376c2f52cff07f1279106386b26fde8fc49de31eb +], +[ +0x1fa4effc83498d19aaa598b7771f88a0554dddda89d32dcf8a6f4cf776d13b99, +0x19b1577a9e5fe67f71e733732ff6ba035dbb18d129f701a566068c4aad32165f, +0x82f3674a3860d8034eee2f705933c2ebf23a5ebc7a3d77c46c9279df8930298, +0x1011963b5e7be95fbbfa2848d56da05d6229a3f0292c50760027cfb98577a2fb, +0x2ab86635f447d66ea5ef5e5339031197ae8e86b7350744069280de59d7256486, +0x14fc3fe2445bef8547b023a1ced3ba9e137e16fb0e3645dec813cdd7e584ebc8, +0x136afe9a53acd5e1d68cfc75c5630d39701cae3744ad5aa2aa34f735ea830703, +0x18bef702cd3178eb4ba589b84783071cef268ed6828f70c960e379508b9ff1e2, +0x2c5c474a63c172ea6d6a1fa8be92e4bc6891e74e87c5a65c42b61aa42a9aae4e, +0x27e3943ac99174b2829fd8ffab17b16837fdb88a0c6060e20c3e5c72fb420f8, +0x288a44d1afb6a92a5c7dc766d4cde4874b0f49cc3e798fc25292cd13cfc4ebda, +0x2d255d4f28b56db356773293cbca39f6f9c06bc4cb5275839555db772a969ba6, +0x262650e9b1667b31877c8d79a5816cae80e222df97e48b574ba91e6cb509e931, +0x22bf34fc02aa2e215c993994c7cff2626dcb7212975f7ffcf11cd90b07808e70, +0x14078ef63c2a106c8895143763824ffec7a868e80b89ad6aea82263b298132ed, +0x1d16de8069581b62949f3e5bfc1188e21cbdf5d67a5bd403927da3a66f49c6b5 +], +[ +0x1676f5c07417ab54c37ec8ae1a8314bdeeb09964769881592043dffcb26bf41, +0x286415acbcc8aba3e5b854a6a357f300ba4037eb8b7c5ef6bbac868d1b4a5635, +0x1aef1d337ca51ca5d2c5c116a275a81a21f90d89834bd1af61b3aa6bed65c7c0, +0x17e864b0c0ebadbd2fd4f75177b9e7fd801bf3c066464070c6527f096b0b4e9, +0x2587c2ffb837fcc5be1b5a0d520f0f2145000b6797a9a5205ae30240af69c7a3, +0x2ad5b37b82f9ac35848de9a7b0bed4262b3074c8047d8a4736959a21946f7db2, +0xa32e49eccc90d7135c8c66fbb1953bed9da04400221cc606416f0db0b06930d, +0x24e2c86170a5b4a8c95066d5f553eaaede655dba90c32e485adb53c3db9f65df, +0x2e90955a65c11aa740e8592c94a983b542bf95bedd9bc24673647687c57a419b, +0x11ced1dc351f0b67b8de31d678da740e5a0c4bb1e9adb04b119e8de79e908283, +0x9de8b7bde7c2aa28539fc3f31b1f28538a766c53ca6e92a1639bf1706369482, +0x12550c43d8d9b152c039868ca4c52f074e02f31e1834978c8b554daf43632d88, +0x40dfc65f3133acc65a961dfc4b365d21d41b9e82cd7d65aa2a3238a3ac5b92d, +0x12f7124beb62cae35c093ed96975ab5dfc8e00f2668c6ddba351f458127e96a6, +0x530ae305c7c8a9ce61943baa1bfc0b2e16199a994469f41aec17cdbd7d074a5, +0x243efe17e4617bc0c20ecb5f9bd76f48a8dd796fa1058366f55826b80aa69794 +], +[ +0x1f4e7bbc8d42779e58aa07bf54ff324b814fe687b4c8eb81b9b7e74448ee27ff, +0x238f0b87f232229a5c7489e1c7edc9d319f816c21e6fe403ff65c60c1ca4b178, +0x1df906bd755c6a965e2ecd7d32768ae2fd8c522dd0ddcbb002389e90f5c6a707, +0x2da47d7b5389318990e3d6eb9f9e93eb7404439b362a0d84da24d8c715fa8bf1, +0x17c623def2d2610588b3c5dd236ac31026a16354f29b2f8a1b0955c391701f5a, +0x1c6c37b8caf25198a4a9cc93c559e73b7c90ca6df6ac721a2f52cee03f57221b, +0x27feaf5bb57db47ec317018969e6e767f48d768fb138698ceb4aad474f10fb3, +0x4e392117390c777ae93ee29db53979f4f0e168595d9dc5fec4eed18ea0e33c8, +0xa1bf9ddee072347f46524461f66c65582c5533be183c39ebc5325c2e111eb55, +0x23382c75620eda77c18e3d166fee7b74e30202ae8309890010849e1a79cb90db, +0x234c33dc7c164b187746919301403d75c58237965627738d9f48d393a44829af, +0x216ffb6e7e5316ddb852406f11331c24f717439f27d57ca15de065958ea44462, +0x21269800c6b53df048610f35d1b344e03a0fe15f0a5b21b73c799a48e4d0721f, +0x86ec72230cd5fc6c7842cd5eb4fd6b75c3051a915deaaeb61e9b22780579a70, +0x2f54161c4ccd936ae2c3edc204637dc114d4d3d6d98bd9b6d8bdf603bd4b7e72, +0xec71181ac2bd7226495ff60adb20a3c9a7636dd9faf14db5335d8c4c1ba3a06 +], +[ +0xf6b18c98fc89fbfa99a04c8c96ae5db35c296479f484b680df905d4cbd1dfa9, +0x12567e67abc9b35af4ffb381ed3acf244a2f9019839f5f8d2f0b442f51be88, +0x178391cf8f91a1e3b00f545a3a4a5331feafd2a0d10d9027c56954c8a3f8ebc6, +0x2abf38b2c05989402c75ec5263e3ac75bdbe9af0c1eb92883d5cda564ecbdc37, +0x2a2c5e5b24751e4a10e893ec2f7ab96f83a970cdf3a543b20a48357cc7ec8570, +0xdf7d4b832373582fd4fbcdf7f3c49749f6efb59fd99f4e8fbedbc8190a0d8de, +0x72011cfb8afcbd8b431269dd5d74aa99e795c6628dc1dcf6c2d8db003bfb436, +0x2e369b2dc96609f8c17a592f2ce063683d148204c2912b0e53a70a3c46bfa9b5, +0x59b27028b4f0949345ed48b3e799d1081350784e0042c994243297744e2e226, +0x222dddba5c72cc2d12f0aa37e940a09424f6e3d679cf725bd059b4182393c08d, +0x1d4f2427689a1dc5f1d7c68311ce5b0a56a961b3d42a746f356dd81fa147680b, +0x2b29f8fb4f37691d3981e3fc495ee58c25ecd758d6e24c3f41e5c56221a64fd4, +0x267bb17bba0da1b457e2fc71493f7d7b9da4ef5d13a62e525defa3d080b766bf, +0x2e6530de833c3b1d1f5bda0c6f6a244ad8288750865136dc22bb752c8e044039, +0x1f0b90c52358a8a14da112639c7d2ea2ff1df537b41227f4d3c9ebf7014c75e6, +0xd9acd7178242914b81219b9a60ef7a0d6dd0fb571609e4335f8d419ff982d12 +], +[ +0xe6cd10883e1e11c6c191d36329f30eb0045af06c2d86d0c439f5c1f4fef54b, +0x2bbfad45e5a92d2fccecc514648ba944d35abca3f6570958eda96ab2e03d8095, +0x1f8bbb7ab0780d5bf4070ddbd1b99eecde357757f3773ce6a8a33cb6d3d6060a, +0x2578863a750b236e5975de83fceb91727b4f588c453a94e40327a18394e835ea, +0x28284f2eb4ef38ef729f8637df230532e3a410186dbbe5ae5497c69a7cafac78, +0x1c535fdc7111ed734def9074724899bea8525c2571335159af33af57310a8db4, +0x29037a8126d3d81fcaadaff1995a15f9e5113b205c2f7c2d0bc0361f06a9678d, +0x1cc53180a2b9cfb4978339d086ed54c748a5f77190e30dc2879a76a107553e6, +0x2fd6d01024cdac4f279edd9fb5219b414815163b384f502b615537e03cff2b25, +0x205885190c6d00c1420074e1a4a3163c382f7193754fa5f87ddb98a393d032f0, +0x23cf89940b6418fdbed6f84bbfe0c5f850a9ba88c41e998554a4a4123d0ae5e9, +0x968d36ff2a38e6aeca306fe28458719e69ba1b0fc76bb561fed0f82255cba8, +0x2c9814c96a72fb32442dbda9249a412f98a23304a86ba9848567c5b0754554d, +0xc11ab9629bc935469b9fdb33f48f22db895f5dd5e182575b2cbbb221105fc69, +0x2b98eb64b8642bf4f5291ffce416102088b471aac3d2f80da585b5fe1f245886, +0x2ba9f7efe0d61c8460085cdca6c1bb78aa7bc086533f20f301e010d5099ee790 +], +[ +0x425a9641fb01558bc7170a2ffc24eb6a514198b296a1629cc284d983bca8757, +0xd964da26287f09bc190e8235411bb9bc9068003fa6d6ee03229dde65db07fcf, +0x289c0cb7f84d62638c2a2f37f10f30a58d8bd8b4c5bd8f5a3ca448e9c668f615, +0x6622bf28a5fcb361e0b7bdfd7fa08717b51640d05d1f6f6ba94b50d26ddcab6, +0x2aca8f7acb59233bc4d4df65b9c6f30479e9a72f5e6821860b39ba9dc4d03f82, +0x1330fe288bcb4ad27de36ef48f063baa8ab30be65940592fd97623c7faed4e50, +0x9efcc692545703bcbeb641ece624880f73a10c0d2c2e6132f9624eb5f41b1b6, +0x2ae8d813634a87b031bb08573bdf237ab3701215b77ee9a4e6a2c01c1c1d4ffc, +0xc2b9bb36e8ab693866b2885bd4482ed5c89f069b3e6445655d70f4d6687f8c0, +0x1a606372725698e7d7f3a7280617fd86de9acaf98bbd8971d8ee53932c2eb6a3, +0xa6632613bfca8afc8939b33e4912ddf18b034be621106ad695ebd5065afe00c, +0x2479769cd60838cc140a649e8937be28ac92c71980f149caaaf0100d1f102374, +0x1f925ba0001429fe493f48ea404a8ed283ab2cc2f3275ecfe320afe90426f462, +0x1231fe074b771ac643d6e188f5732c209c71b768739b22447e6b5dcf499b4887, +0xeda204f434a347cbc55ef698aefb23df064c57fcd4cd4cdd810e05ece651535, +0x33bf863141b2b9aea2e59cf6c4faf11466700aa5c383af451d403c9c53160bd +], +[ +0x397a7d7434b0aa941348de45aec442cd5cad2c398884950e8233c58dd50335, +0x1495e990865f559df4c7bd6f21272b8106e2c91cbb1a9e2089922c62b2a76ca7, +0x125496878120d9ff89d702f58154ba82158e818db90e3d12d6a08c5543536368, +0xf8ba5444de18d199aabbc5442c1d7c01cafafc79fe095da31928d776bf984, +0x1eeaa31dabd6b6a9efa74e4315917d902b02760a04b04eedb57e261fa2c6632a, +0x3776a7d69106118a4d22f86060ea7db0c9c8f3ce3ccd6c88ada43ee175cc811, +0xcef77234c42547957e950e45ad3b723735c011ef47ceee8ba422bd16759be2, +0x1cebeac557d2337e4687501f9f71fad7ecb14ad09550b52417ac33c2e8bca21, +0x6521b700ca47f222ea2e280f3193df67e1a5966b8cebffb01890aa3a87bb328, +0x100a85e6da4a0b92a81f1512710c889a29c8ed3e0695bc285a71ca5617705fbf, +0x1a6288255e7a54d4397ca40b3be72c0469bc489e66f916c1a90476816a2f791c, +0x33125b9cf766513a8e82a0d04374ff181bfa818f67ac1c7dd4298cf32b85e76, +0xf7e82720135b35277fc54ebdd88a026af545b745fc20449b7068c6865eac1fd, +0xa9f28e621172d911bffad3b5ea4b73a49a959de5c86e8ac52745d558a6f588, +0x18a93b5dbdde2e99c234253d4a49348312e58f033e87d4446945727da833c54, +0x2237324de68d18d407db3fce2a401e8af47ea8c5bc09d862d12b8dbfd3af5f3b +], +[ +0x1d66f208fc04411a1385c22e203dc08f0bac2f7cd9dfaccdec20d3b93252ad04, +0x1014b540da45955bbe759dfc9ec4bdf32a99d56cd2742d269ff8691d915cf247, +0x1720174606224668a7067c3e8c53b1ee68349144af6d6972d38c90bfa6bca639, +0x6693893b45a40bc7366925fe7978bb80fbd5b9a3ea27c9dcb456b2b04670c4f, +0x249c8751e7443e96c6e3b6b78d7f288e8a00c05f12597c984f8f0eb3f9c0d4f6, +0x19afe6d81031fe1cbdff2b24eb7d691a50bd6bd8da98ef658d75171480cd664c, +0x2034957e3fc373e94d77e0a050a8a84ba49095ffc6eb3a7776dd86940d90f01d, +0x1d65f2f3574c1fe006df2d50fed257bb935f902970c7aae131a41f2de4b48bb7, +0x1563bb61629e83922438cf0723716cd4daed36ae948e74c5c85dbb7e9893d645, +0x2f10b78f744104a54a8149200cae59e443e74edab1cc3cbc2d8c170ccf2f7889, +0x7396d51d19d94cb34b304ac606b54399e89273abb22ff7bb6b433e472ce1e8e, +0x1cbb8fa4be4e9fdf0ec9ea67df8df2c1b796291e75db4f427c843216fe48834a, +0x14e3a6920a412da81d917e7b9d98bba849cc165e406fb3c43ac421f9ade0c228, +0x2a8e486afaa01aa8eeda571541d2199b55c8f5f730ca5c3879f246c227809c9c, +0x7abc38167a01b6bc5831587de4d790de43e68e6ca9eabcb64b8af6895ad968, +0x1e825483a9f85081590c0ba40059fea7861719e2b7da11323437313b77b6a8d +], +[ +0xec1ed3ae3beac4ddd1fdb17b9c7c648e7ec81885a07a5bcbd967e6a3676f356, +0x1d8385e9787d1456bda399aa4d7f5c643cfaf25d6ed60e1be9ae8b98fbede91d, +0x2f574b85296045a2b1328f482a3ec674793ea300e0817720e6912d467df067a5, +0x291fb174e5ee77c060615a7f5a737a57d56e2060844aedd0aa86329b9b361496, +0x2362c38ea538ee898a12c6458c399d2870bdd8826307d56f03bb28e0e30d09f, +0x231713410ae9a8da08284c29b8b975410dab6f84f56475da37711345e68d5e2d, +0x2ef69fc1a737db3abc895f656811e59e7d873355b2e1342aa5134d8bf702ac90, +0xefb60fb18584fc86d88ee569da71046f765526b11f6c20099a6dcdfeebc4f70, +0xb044ec6d148637a47f917944f81e9c8b83b0c0c5ca1bd3462a4e0daa7703dac, +0x202678e431648172713afaabe2c8ea148061205c639f639b5e45d498be1550d7, +0x2a1e1954e5b010440c1679719e5a0db27c0aa7957b755ecf2c9b3571a8aa0a0d, +0x154d9e7b0dc8fa67c82016fc687836f61284431fc9d681405edfb38ccf28a6fc, +0x2a704d1d93253cb1096070fbf26d4df2baf4d92057d87596cadd063176267917, +0x2a24d4dfd6e9d6435e4ca1994ca11ad7adba2924b6ab7cf7c6a9ef5e7ef9ae21, +0x1688b9a9cbc3a63df3a2a35c6923aa0949816cb57fefa6e95d7627b7663a6317, +0x1d1caa8449da721f7c949ccdc38ec8c6134d97d7bbcdf58fa3c471c51a672ac +], +[ +0xb3e601e36a5d82e0214362c8419474dc1cc2c0ed8126534d69a3f790b27c603, +0xe6b936ecb8a59274624533d03746cd5d266e6c5490d3c95ada22f4a22e80e32, +0xd56cdd730e1401d9d7f93da88d6f3bfb8eb1fba440c552b078bb38a7cba55b2, +0x12c0b93d829ff5b9641d9f6f2ddb4f92c7a7b147b794139bce98ad87d680d717, +0x2de07475e19762eb5baccae3e88aa1493d35d276c4d05c670697b43824a41640, +0x2ea094a22ee4755e5df8352b2ac671e231c24785db343b9145f9e44297b361ac, +0x2ab4682e32feba55370b3a477ad83f30c88db387bb20c6a9b2e567f5d60a4a73, +0x1a70ee4fd1e45c498e771e9d0210dd14145cc2740c3607e044e3c68b6a6017d4, +0x20a815e19a6198e3a2f8a8bc2631c552521182f63e125477cf765a27707035a1, +0x266fe05c631b74ae1cceb24143a96e0e9fff59304f04fedcf4db3da13508578, +0x190dd58a88fdd887a0ca830681aca5949ea89050fab84b66297d7d14dcb91a74, +0x1ae686eecd7623655c55154aa8c5c82136eb56020fb8d1199aff5c8bc11eb0c0, +0x20ad4678ee812d96e544ff8e5e65d4fb7bf15cc6a524e6f19de6af983c997b03, +0x2caf670c84f98b68d05f4ee672a1388306376e7886e30bd2b163bfa7fc15b443, +0x1a336a86dd0b3325933238a53bf68f21ff35e9569fef12cbb61d8ab9c1f50ae6, +0xe5fc7c1d17854a0673479d4589da85e6e61f48cc950b3cc531564ce5fca874f +], +[ +0x163cb4e3a5ec92e57b25b095a3aaa8cfdc4ce59267718cc6090a07e14af10b0d, +0x19853b1669534b82fee656f037c33af733bed785ab726b0825dee79b629b9706, +0x1b164a2238c5e107696834ac58de1b21e49a366ff6307159dd461a3dd40c2f53, +0x2923c2a5464dc991733e46124db74c405e32b3fd9dfb2acb7d889b19a340ce9c, +0x2fa1a6b0c6b0e9d686ad60801c72955c1ac256d23c545152efa81dca6fe1480e, +0x27cf8750197630022efad9203e63aea2f195315a1d065a36894a5bed32bc8941, +0x23f9c83f88ce7c78d0c6cb8059fb86c2110c7c266778ba8169b665dafd9de184, +0x1d3ce51d11885aacc9a7a3b9fd2813e7ed602b33d3339fbd91bb869c6881ad73, +0x293f18aa77d8372bc9ca53668a9870de638a706734631c21edaddb20c4a6b85e, +0x197b9d069564454b7f26166ee1614896f153ed11f6215f06951b834c4da38045, +0x131c5cce643d2b8d9d294b32abf2c9010ec622bad6f1181e4dadba9545684bf3, +0x2556b61b7729a527f2c01544abc585ad6da9c92b3df9121f37bb0fd0c03d2cd1, +0x5a0d89380a2a2a14acb860c3bf32ab6b3c973d84b0d61a308ca73257c19cdb1, +0x24785c81f63404b46126436afb27fd2340122e9a98a58c467ff14abb5a90241e, +0x9fdc6f6ceaf2566ee3a618ac4d77e86327ef278b968013e33f0813190472b31, +0x2afc8316618c153350f4ba229e3382245c1399b2ee4aca25580229fc237f94e +], +[ +0x2dca90f3e5a15b29895f48d7a1290d7a33646b89620dd0a8ccde3aa3a51d41cb, +0x1ac11195f74d7fde657d093a313171f0bc3cfe2fb965e5c352900faac25305e5, +0x28fae6efd55d9648b0d9dd3b8c6e928c11a5941dd6ec235a9014c6dd35ad315a, +0x12e496bb2680b7d14ebabfb8797e9c6bbac68a40c8b8fd65b5dfb18e38c99680, +0x190489ef4eb4182eca51332b895875d6ccb7dd060aa364c1d289e2e1a7741119, +0x15776583d7d261c6e8b338c3b3fa4323abde66ed0f477d0355119c9ff5482eb8, +0x1370c01789f712284290ef1cffc5d33288fb504c5763d2801852b960ab98afe0, +0x786ebb71e920bd16e3ddfdeb748e040b7f1b1a0f04967f55210bae2f76bccf2, +0x15d4d2c713cf58f480500c6e5916f52b6ea1ac070771b0c83a6fa17cf6c9b904, +0xfab2ea8e500aed64630a51f8bf9ebf040073e23a3cf189638656d6dd1af86bb, +0x1338a1a447a9df2fde50aa09745ed3bf09e32e4ff2caea1b3b736a666c715014, +0x59df1b1e661d317d01a513fc7dfbbd80c9192d33adc60602b0b0b9d45e08535, +0x2f840b4ac5c9227c0a648693878cf37e955a037877bd5e5ccbd8efcfa38466c5, +0x844b5753fd61108fd7fb8a707e770af891ec99da9d5df68b013a3a87599ff7e, +0x2049ee37129926ecd6ff3a08e0632a007ccaadafd0d402a409561a2ce095b52, +0x1f6570fb39247442fc03a5139944567ea46f6f534a0214b611fd3b2d3b878369 +], +[ +0x2c78ee5ea16d38f0beb9dc0733c4bb1893cb33ff671b737a1122d64f729cff22, +0x350e8d2eed84802dfd14d7878b0b77cd9077778c41ff7733d2ce688961a4b30, +0x2aee7c9d86aeb8744b9d3bd7cec5c292e1c65cb633de0afc101e9d6fd2a36d5, +0x16ba6796332fb56050e3fc4111f320cc05255c292f34db71e816440fcc452baf, +0x14ae46529aa1f2b79da80878382a86338323f6a293adbd91cd58270513f4b693, +0xcf33eddfc73e29bbd785035283f6e805133bf1e34bb9e3cc2f915e06b272e27, +0x28f704162c3bd521df847d4a8a4f75439e668ef7816a91103158619fd52e5ee, +0x1c207d7a9081da93b7375312e4ea754523d9198c501f65638f5af885708d23ae, +0x1cc29ba8eed43aa2f71831b62eca71c1a46ab68007777679aaa8d6121faa5b55, +0xb39596ec65e453830650f8dd87d0fe8abc96cb59636252e27797920e06b6a2, +0x162ceb46008b073da8c811a25a68b56da01182fb893ae1c6b03d310ac8944fb5, +0x1f2526ae9adfccd223ab57e9de7e50f5d3ee83284a8d62a5e40148f4dceafab8, +0x28ff311d4a44251feee051511cac4832e177edc8a03053e133d206e9f6704f9a, +0x1c362078a104c738bf6c5fda0edf9ce2cac3b21eb2779e734d14d7276a8e5267, +0x4458b88b13af0f9d45c2b43df72abe53d6e9b56fafb1d0c15cd45a13d33b05e, +0x23897eb294a5fa4f300110fb96ec236f8c0e049f29da5078d1224337e256e703 +], +[ +0x2af324ec4f9e7786dcf00439c75a294bff753e3292bbf62e66471fa730f19c79, +0x11930ca8a8841441dd799a0e3e78e1a949f05bf99603b382ff771021770f92d3, +0x1bd210b6e6c2074d94d9f310d6906e81890175e675cc8dd659c287438a08cc4a, +0x14bb891ffdff2ba6b222332764a72059404e581f328265eafce4faee0637c6cf, +0xfa8399ba775a9e98ea3fc29231e1ae7177dd8f63c616ed4f4819f0db982aae3, +0x17749627adaf3ea1f31f149cb0fdb032b9c2f17c262aefa35ec1d516e577e6d3, +0x17a14cbbc6c3e70e50145daab58ccda20416fa7a0b0564056e0366be14d9754a, +0x1ff273747279cce54284fbfbb61bbd04f403afba107507f76812a645fa9fb774, +0x20edba75b3695a0f934c68c90d4ef19ccf1d8b1e3042d32362b5238b10deb274, +0x26852fe3fdad04b05eaab62ab7fe15fcfa55e0340534e28e2d8a3d8181b1c859, +0xbb7167ac0c34acc1d3e0b83212f50e3360eb4e967004da532861a8bb527ab66, +0x957401bb640d15d04d93e3ce3756b5f06f9869e51076b13d42a53be28a36b5a, +0x4d4b72c6c7a5922a3c9ab0b0154d7b12c45e50f8a237a930802e4c64cc7163c, +0x38fd3c972d8ed7705ffbf9d462381628ab654b76aedf4f4bb29a2fc6c922cbc, +0x98ff2fb46bfa9b48439294ce85ad25768cde5510c85175e073f1414a65e4ea0, +0xc872f10e24c0b992944862abd52152c0faa0aa508afb99a6e9a3d2d363a5c1e +] +], + [ + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x2fb280a1f23df0c4566f310cf31beafdc3e238a7d873fdc50655fe827868e909, + 0x36f175c993f4e409a6275e71558b9e1a0fcd7e4183891a7471ea6f987d6d0f2, + 0x3be177a0fe1bf76a94d443647e0f69c0a74cc5dc7af217762210b2855e849f1, + 0xed6491c4fd0f129acabcf5a68f01ebd10df6211d4d1fcf54ed75bf6c7cbc146, + 0x2158db47b374d9dd31d47c20844fa870005051c013941b2d710ee62e56c0e4ce, + 0x637d7b15c4259de4866d36005fb17b866227447e5dce4c27794413980eaa09f, + 0xb745dc1580e5e3d6319028050cb792ad8fcb5b1a156dfac6595edff287d4bd0, + 0xdc8bdccc8f3ddabca39be41a609714af65f518ef34738fda76e2755e7378699, + 0x1fdb7856e27d608c397fa9f7f6d2fdc4b31b17f45c8a347124c8c82ace7e1033, + 0xafff33732a140f6759bfd5b2949356a349c26c64b5bb018665e54acb329d3ec, + 0x1b1d97c16995fec9aee31a16facade0e2cca653efebee3d5ea70c0f7b39c1383, + 0x29ea18e6e4c75a1c3694bdbdb3fd274c37f51e2917f9e0b01d81870ef9235387, + 0x15d5f5aaf91baaebd34d07b9634610b85966c008feec7843fab7e50b0616427f, + 0xbd8e0c3a167d9eb943bf19f18d765230fd7d224df0645851e669591df01239f, + 0x129293724e2d76cbaccac841326365a0b92bfc00437147de6390d964cc0e055a, + 0x2d70576548941c2fb6bed6c525db5d0c33ca6c86f81db33838548d672b7b2641, + 0x2becbbc12e49825055888292d91ac7439a3cf337d5f9873c735d92e52a054434, + 0xcefd0b81bfabcb9920230f3a729ae3303943d8e396c5c0e5ca01f4611f3f617, + 0x6e47e966b1b597c61413dc4f996f1456719742257039015c9c1d0aa33c0b0ac, + 0xbf90647c85cbc82b06e3a94198e44335720b8afbdff06112e2aca505a43c47d, + 0x239bc57d7b109caefd8c614767a590a68f658c69cbec21fef283a50324179227, + 0xa36ae4cb35b4f865d7225191366fe691dd65ad5f2966b74f2adc28d26d2d322, + 0x11244585fece886e4685fc703c807ec8e0d591b575fcd089a969d684be4ce2b8, + 0xcaa7779dc16bdbf99a3f45903ace5079185e317efd5733fc7f766ce57e29694, + 0x26996b9d086885f9bd6908adb4aaf6deae8306e463250814dc66e00674193839, + 0x135e66a0ee13b287e51f5f1e8f79d4fe7ca55d9135e8921272920ec732bcdc16, + 0x233e95062085e2dec808029c59a0e8230077331e358613563788518a3972e5b1, + 0x23ab13b15889f8bb381efebe71172f91a0ad65d9f05af6b59e00d0c99f8ae082, + 0x1ede4de25a83103e2dea729f0c68a908589fe0e604c86f8d57e058fe11000742, + 0x2b5b5bee788dcb23bd488533ccae1431e3f3504e3b89e6eeda4ae8b5bbeb4c78, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x257363f01fbb108ce6360b115eb038270946eb8c46b6ececd68596765ed894d3, + 0xe06611bd4eee1605582fc2f0a195524e57a552ff9f2c76832189c382d763944, + 0xab70fb6823f52c277b8dd4ff261d965a9427d34af4afbf19f3b24260c15f8e0, + 0x179c941d644d804a3a4068884fd1c6d7a82d411d4698c91e1b242966d3bbdab5, + 0x37f916e90d419042d297bdc952c7cd02746cbc188149a51a0987cfefe0dc13d, + 0x43f3dc3d91b0abb531882dc015e1d9d05dd646d42dfd9f4c1493a085cc00a56, + 0x143ad19c1249acbef488ea0a074f56afd3f5b89666235cbf8bb5e6fe44096642, + 0x1b76610fc8cef2eb0f4fa76df7ce299237fe7b3a9d024b7d405ec095719c4279, + 0x1a5148d68913df74c872a1ea5aa4b542b3ab1b9c0dda2ec220cf2bc36d69ad59, + 0x13f11022ed02284972037000666e2d3edbeb9a5350c37fedc293be998eba32dc, + 0x806f266e4c35c6f066925ff73d6abde5e46f5bc55b01015db95162159092a70, + 0x2e14cdaace09d09b49d437ca48752123a6efe3c75660218f408878871d073f64, + 0x1c4fa8d7c6c8eaf33116df7af0abe56945403e111f0ed36af029a17a88027839, + 0x23436fd3d8d48c7de5ea32899d09e601877896e044051e59d481f26c6f44594, + 0x437191fdcb2c0fccb9dd2b70155e1e3eb91a104b14235a84f9c7f715f666b10, + 0x2f68a6ebb5daa3c1c0b1f8e1cc3ebbbb29dae51f21dcab1b8f24f30e52f6a1bb, + 0x2d82def6705911bbfa278a38d385fe17c9810bcafd7126f48ffbbdd197e1fec5, + 0x15fead0f7cceb9fa5a96b903121d234539c447f776bf13290f0d0fd9cd776a63, + 0x12390ef95e294ede3c435f9f14ae4f121cdaaa6b5de4f3f79969a8f91fb37793, + 0xa9f6f1757a4b1abc8e0a5b0fea83cd2b8e565105fc6d52e692dece89a6c11e6, + 0x996db2a2060b0454ec8a132ee6d810df2df49031ce420e4e790c723f578bd49, + 0x2670a74f37e6a32596938caea3cec3e05b337ced6c23d2bf2ec5987dfbcc6905, + 0x28ae07ea7a529805d3aafe9f5a2ae662f908b17f864ab59b98452ef28e3fd44e, + 0x24002c49771a2fcb63c046d1507b8b2259b4eff63a7be958329f6319fe8c787, + 0x2703e03745ed8810cc93cca78ea613cf39f492180d6ac47300e4babd4f357dce, + 0x22930293c333499085eae55a01cbf8c32b04d211a0709bd9b758f733e2ed7b7b, + 0x2a0ac5d7f2daa3edadbdeaaa440967d97baec637cf48a67a36810430014a902b, + 0x25fa48cb70003175db4b2241e6bbb08a9d30128c86f68bf6e79e9a3dd4f3f4ec, + 0xbae040ff4b1f63b97474a971446b680c23ff4d55212a99d03d1e27278770016, + 0x2fa5db728b6058cc42348c90267158f8e76ab99c646e66664dc2b93963218e16, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x114401a4ccc83c86ae0fa520a3ebe4478fa6d7c4c634b4a6503da334da8404de, + 0x1ca6273af6d2e51a8b7c2ba869a1bf10de7a5b9786ad947a02c2b1b6ee821274, + 0x2c7b4af671ec5fa12531b63b511782f1f46ee5428b9184d960caf0deb0e08d03, + 0x1230182c434b2175e9362b023e55456bf97d514e5332e4753ffeda60f5d97b0b, + 0x22e041c288ef26f1d07c86d6c24f48eb041d83a8260b6772892181e2120c91e1, + 0x28acbc69fbf7a25ed38927ba63cde5a18284f26ad6581317782219221cc6bd8e, + 0x2487337fffaa7fea6440fb59e8e888c1724bbd1f1118d32ada6a3651e46ef543, + 0x61f4630cd8a70b5c6a1950def1f7eeda1d2cfd750eac8bcd21d0928d54503db, + 0x3cfcdd58420e81bfedb04dfd4e5b57b03eb8afefb5963b81339d92445458b6, + 0x1211f09c601c31128561f10ffdef73487c927091f10086ffa889eec1378757e2, + 0xad6247ae3bacb716899003f881ae2cb44e40ff4863dc07a400bde10cabc91b, + 0x161bcf48d7d37906ef29d522a6631e22e344ff951be2f5418c1f58ef81106949, + 0x1615caafce9cf99656045f01b9050872d167219533072672a6261bdafc405e27, + 0x1f1fd1b64c8024c19dc4c906e121bc5023c76b1c9610fecc02e009e384fde164, + 0x1a343f06c742b6ea01dcca051e7f812097250e81efa506561817c2accde13fb2, + 0x1aa5ad37af4cf033774e8cedb40c36cc1bf2fd2e73c135a2145897e255644ab8, + 0xa8e74375e1ca92003153a84d2a88b38796905e42f05a2aeaa22b6174545679b, + 0xddcb524f3d1e36d26523b37e7a7a565ca7aafbe8b9d7d21805d79b391345944, + 0xc64669d92336353367ff746030b946691eed63a8710d15b44907913558ea892, + 0x18663caed52af3125ff734ea821f2b1c0ff63e253eb8df61c23998b3852eeb2b, + 0x8aa2a6dc1acace95ae99cfae9f48a5edb8d91e6be62ef97a8e48f7bf9d22cc3, + 0x1d810d45be42ede9157e37dd929a6b74d0ace0e72b96d6f1e048532027613e9d, + 0x2cc11816c46e64c6e7135d72c00a7dce65a7614cbc164dfca2be624668a51767, + 0x6bcac935d9e6233eee8555d901d6cb0b5a18e0baeb0774c42bb2c2216a8d3d7, + 0x81f422bb15ef7e9b57b79cad63226fc53cb080e6d412e790b5051b5adb01208, + 0x17233f2458d93db35c213a72c969a94aaef62fd6a76435c683129a9795177bfe, + 0x223c464793888525ecf5d3c873cdb3a6bd67587499a00b440d924c2fdc45f640, + 0x12ff515ef3e169b038bbacf953537c2b28dbd1b5ba3fc7a26900188aef36e2e7, + 0x55e0568770fbc4c9b3d698e621b1980736ec4259f0b09d9f1e820f7da4174b3, + 0x185b90addcc3b674ecbd0987f9480b74625fd07c91bdcbf048a647d561c756cc, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0xa4ab29f428a1b4040f5510e8b4f10494ebdbf12885955ce937a17360b4b295e, + 0x2a64788ea96296d7253a3a9e357715234f9318c08376c15de69487fbf9b0996d, + 0x2385278678bf43e06271b87c3f984f1b425b166ba786b2e1e723739a6752f6c9, + 0xf8d204bcf2efaa0866818f1c3986627ff998995317a960b56d8aa3f5c10fbfd, + 0x2d07b5bc553344a4887dc8f3db5858e5defda22caa9a6ccbe23e3332ba18aadd, + 0x1e1a6765877cb93580433e025985f80aa19c9089c17138480426bcae49aa1c7d, + 0x15f1a60617344d29b6da60f57ced335da1dadb402ae9a56ebad3c0aab3b69e73, + 0x6be01da4de9af6b0d2937bcb65697fdc23e8bdbf5343938315ef4dbf045d914, + 0x204479ba44f6c6079df123ba1a54e248db6d4d0480393913790ff1f10b9ead7e, + 0x1967ca2365849a5ba9abe3419797885af9736c42439f1481862a00cb4c83b24b, + 0x37b78ab4c6c1cbe83f197633c4c83e22fd38219786d9c5744ed4224eabba54b, + 0x21202d9fece3b3517c2d5e79e8a5b47824fe47658704341ba7bfda3a3414fc5a, + 0x18bd7e46303c3c2a31e68492472578708a68d1d6036b961650057b7d1ce55eb9, + 0xc5f32f34e129de8d01bf9010b16047bb2c2128ee021fce0ae2c03a2f0b20c55, + 0x1ea1c77b9ce7d24a4f32fff661e414f0793d9c4477fcc5a577b0e5145c80671f, + 0x2abb7ec37e2a52a09fa5ba144d29b8fea69efa205b4690330013d2da27fab6fb, + 0x196d47ff262f5a90329962beb3c403490547808ffe4fe96c699195d9ee5a2326, + 0x2da5dc389b073e52f92970aaef0d061beba25bbe8520b781911858598682f57e, + 0x2cce11343f974369dd5fdeb7a8a796d3a83feedcfa0a78db72dbb789bbe1d847, + 0x131262e283cf0b05fef60886f32f084a47755fcb4cb7ccc4c689e4e7f0437b75, + 0xae1188d015d3604fb38931c02d790fca244b8b284d547b62fb03f98ac887716, + 0x7579345afb1c183eb92a630bb7d061969cdc515414bf9399797d7413f8b904d, + 0x2429aebe4a674a80f0a8ae9b38a3f253e45b897ae71a7b5d0afe4fd77d5d8769, + 0x1382b92a6c573bb195a953dc0c697bbbf30dcf6806f6ab2a5f7b500a80052de9, + 0x1d182578837b58b32dd31a315254bb0a49b04b3d5ea49d582f6426637be87413, + 0x2d9888fc8880aa1e4b265cf60218727c3556ac8d31b7a3dc6a1dd5d51b902207, + 0x28fab72bbb99f1a6eaf2040a74ff55e87c5a48c2d392a7752c76fd2fb33e3390, + 0x2678f1ceacfa8e3b48b5eae7f060021a4f58cef56b12d52b9f06a09e4eda55af, + 0x1f61d359d1619ec4ff2f1eafe57827c9316e10754718b9f51b36c71979cc448f, + 0x1a1d9f64b52be377e509d5a57f004bcb6db0edc85aed26f51581d912da30e95b, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x23884cfd0f045915025a44e9bdb14491e626edf74afffee874c3e4d125a4a177, + 0x285d07475f22446af1515c134b10ef890bdd927d0328230d6374ceae21e5f169, + 0x353d664345c344fa26ce90da4f498fe33a62e8c46e7e05b47ce11b669bcccd4, + 0xa5f24df76f39b004c073e1cfcab0880702b9e84837cbcb21bd002e2449ebff0, + 0x12dc4fd8b792019288d665292050cf58bbb2c55be723d6678ddcbcf55cdf5c29, + 0x193f04538e44b693b5f03c328610092e8b253895beca308625b8bba24229e6bb, + 0xd40fe93ed90a0196dc17eb24b05dbfd08a2d9b85103dd44d887b78bbf08251e, + 0x1a1e1f731268025c10698efff9a1898281733296a02ec2e4286c0aa9d766250d, + 0x27e53cee0536c3e96bd4b78d76b1b99d611466b687c60dc5242304cf2c7f04aa, + 0x1e131e762835f631765d6a0548f8b99786b3379a5423669f348e63c1a3cd4057, + 0x18377b53a6b68420631a509767ab747af54ff52fc6a300f6759e89d0fa81f62d, + 0x2b52851f9a2c117d24b7b3ef861d3d98145e18be0ab17461bef9170dd124f2a5, + 0x203131dfe05f4f3859a2962ce2736f5f665679cd543440e5bbdf8c9e468f8f1a, + 0x11ba7216dd386406bd1ee9de577c3015b3b568f612b79d2b901955439b5f47b4, + 0x6cff68dad82139580b6ee40346acb41a1b88e34344b1ee124cd845ba4d8db12, + 0x176b605012f38593df0d0e12fdaba43a024327554f045875a394ab6d66596693, + 0x2bb40088a1add8496b2a0d0774c06d99000d9f7f5e78edefd8267bdc2602823c, + 0x6ab5edcd1a597a55efb6f5f3028b5d46dd1838af7e0a7618fabd206ae02db19, + 0x1ef4d4d25e3f6731401c06e2327e1dcdd251e5d868a49615d7c9e671b74e52ba, + 0x1132917918891833659ae5aa5d4608e9ee52f8bb8c6a15af2bb6c5b2538ee108, + 0x3ea727908383eb9c0c5fd4c8f4477c7d7cb3887c6b7408097c2a099ccdb436, + 0x1c671af55a23385b16b41f93bc5c9df9244a2b2917fa26f989936d9e10f58965, + 0x2877b09253cd0233d358dd5c03a15ebd382a94f65bb32f81a409c3209c83dd16, + 0x120ac765f71527adaadbb9e91c78bfbd17f30b1c5824bbbb6eb82d2745bd3352, + 0x1c2a7fe3bb93bafb54e3a35f4fccd2685dc5a59ff6b9e76538f37b7c79110633, + 0x245676b487e217c63beeb368b204d8fe8e5e051aa91efdbcf6854d9d5ee8aec4, + 0x1a0f4f24f3fa75b07185d59f382ff63f277dd1af0a902f7107b63fc9f450d87e, + 0x174bb5947efa62f904759a2e85cc92c84b797688ee8c2f05699d0305f6a68abc, + 0x93051276353b63507c05bf904de6f8d971f7d386c1748053840b7b775beba02, + 0x20110b96b513965874eec9b57166abe7a71dbac4300ded7aea9eb190ef9b082a, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x17a51da68d46000951b06fb3f9e3d5b83494d28feae75a0d77381129d1b5cc11, + 0x19124aeaabecf4135010e1a965341e48ca4fdb7b0cd507710ce685bece85a51f, + 0xd4eff1190530bdc2e0fad57504ad2d927a0d5d19c94424013818bbedac93ccd, + 0xc4e91e3b7cef308d9d42940dbf9a496e5e23f954bbf9cd9f6a141bc043c89f1, + 0x2a91fff770b866c8ca8c530d786a522131c1526c4694d8b7b7ad3ad8678c6140, + 0x211b948fb5c8a9cc45f8dff7f19d5092c441a1749009ee7b0d26d02d15302df7, + 0x1e30b1031a24069cc93961bcbe7ae460663d24ac25b376fa8d2a8cea3969e66a, + 0x18b82e2032f53458de5b5b8f6c69d0f59033e0e843d3523a0e433aac75004ec6, + 0x1dc22b5bfc2732c1f3481351752d7895f5594716a57b22de0953d8675f35784d, + 0xbc687ef3b18a77ed8495a8838fa82e35a2be17ae2bba47a9f5abaa26021afd8, + 0x2371c26d8f7425cee8f66acc9f647d889b78a20c02fef9bc8e65295536d55666, + 0x1477473a9e49c36a60b0415dba5e832e23ba2575682cb706c5cef38c2ee8b9b3, + 0x53e482959dcdb79f52e64a3bbe20793fad3af4f4d052c0cb9d36dfa396bf4f5, + 0x1f1b58b95eaef51e442d66ed24a23e300b3df3032f45040577402279da01620, + 0x141411af50e95784b5365ec3d4879e78d311c06d3b031a47b7b1989ff8e2a05c, + 0x2252323b3ec06cc62710778370917d94635eadd0ab946d83c7211df2fd18b12b, + 0x1f9f09cfcbdcebaea2b1053db41f39406c4bd7c08d69632e5fa88d11d8db2ff, + 0x69d5da11e6652375d70f87ebbe9b7df0addda9634eae09990b68560ac4ed710, + 0x1978e5d647456a8b3a66edba35753faa93e3f3af1c89f418aea0f68bb513a0c8, + 0x25d9a4e603b812f39a20e6e5eb99c0ed2845d383b952b42e23d65fe68209f458, + 0x234b43e3517f8573d5b4b6c905721747501928557ec4165d9513940880050221, + 0x3e66cf2636881c8a51bbb3532f0ee3abf099d16c6e029eebc7ae903a9b74d74, + 0x1e98f8fa7b0e98762453c23bac6735b00b4fadfe63c0448be0ce344456b7f189, + 0x8aa709b54a8df091ca048763f4573cf9917aeac083ca1b7f7eb84c060d0e932, + 0x52c7ca7fdca9ac2cd344a294d322f1d71d1384d5e0a6f44d0ac8b34e6aac4cd, + 0x331b02bc917bfc6691d8d7f52eba08a5fc3f47d16f02e440644390c39ab7361, + 0xd898949994a6f263a9f8225ca5d4a118b7955a4a79606262394ce69d7a7e127, + 0x10b47b130c16007b5379d744a7bc19e45f6d92e271a299766420139f20a7766e, + 0x1132f014fa7599d744c6d40d1be4ddd44e62b3fa4bdc439a48ca4c08caff36ee, + 0x1c5e38ab4551aaa2ab2ab5b69f5d6478d668719523787df968bec6e67c349a0f, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x11c9a8d1a7cf032ef4eeb3976cb45ab2639e2328e018f2450eed36a42b51724a, + 0xd68b0ef4859a99d9a3d358f48ec049222b4adc40f5211420ff9792d3380451c, + 0xf7e3fbe842d222839a6a28926d2b7dbb20cc776f5cc35ebe6de1972a8061070, + 0x20ee52f4c572121f278ca8f09daad2f1c0ef8541099378b0bae1913528b01102, + 0x24177470839e90548fe652abf877b6e788dfa4e0f4364a20487089349d2b14fa, + 0x1fa98b63c69a198ee335de75179b230861470a0f60459ed53930f592106154b0, + 0x18fed7ca1d352fdd257bd8999e955d46f48c3fb2f67e9c8b29ca0fd6ed5cc4dc, + 0x1e4afb9b1400def427a1a5c956e761be43bc3d15ef07098cb08bfa994e5c69b4, + 0x2b8b851fafcc041cedfa64521f6fb53a58788b5b166da469192a1d5aaba1ab06, + 0x91cf8ac82b6d84be9f81ac1351faa0de2226260a1019d1dfb24437ca34325de, + 0x6f7d61897e3a765d4e4526de3cc13b4c657cc5ec81e08388c41d94a808a9a5c, + 0x2862142916a2c23432ee3563951c646c4de7552008c928fa13ce3e3501ed8af, + 0x2cc6cc5a7e65d688d27ffcf1c4749764e7294c23d0108a57b29af443bb93f5a1, + 0x140d2a34847cb9f0776176010d8070cec8392f612f3573d63e58d69a4c9565bf, + 0x19800afc9d05a5b0386e87a855acdcc743a1c80b0f71063d56d0f4d6eafed03a, + 0x2691df476c22b56f9d6d0cfeb1b706d66a1e41e69de5f6da9f02b9dfd8954d35, + 0xe3d1a370a2c113f55e8be6a59667f72e0bc9018c6c2b7dc154de2ada843cf99, + 0x422041cdbb99e9110963285e90c233f1843361d8d36878b2b2425ecc9ad1468, + 0x18b3970150586c60e36243d9f787e9cd234ae54249bd47d53d8350431027541d, + 0x2608a620c9370842cc1e7eb75ced965212717b22032cff3a90f1916d5d6e4b47, + 0x102e638d33d73cd137a4bc97b16ed6ea8ff2114ef025e123a47fae1209212fa7, + 0x81127c379d08c86b6283e3ba2f7a163f156ff1efbe2d058b68ff1d8198115ea, + 0x1003330e6c9bb087c4e374163f1d93b51ea2747126942a891b93247dc3b9dfe0, + 0x26286df4b90a6d6a80afeb845b9b574c8e114dab2b23abd4d92c90d05611792f, + 0x2fcbce3693a0f365c77f5da41f04606747334c0e21ceaf4719a9c6c55a6db034, + 0xee49f7bf8d9a6b4657cca9a553b12ee1e0375a2251402b6233f14b3ae43c458, + 0x1a9ca035a5bba9e01a8339c07711d9c5e79cae3441f272af3e6fd0fa56889e06, + 0x1202f2ca7d4f98e448e3cc47113806ec2f94885d536976db84ac4f06b7df6567, + 0x89a14bbb8f0965a914cbbf83049d95598ed83fb7aebbc75a4f681efce3130fd, + 0x13488f3b0456524d4982305fef6e6c81f959a37da7bbafab57f87e8a2e3f264e, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x155c91db5f59fd8ea52fff20993ddc3285ecff97ce2ad697f4a078e8440361e2, + 0x5c61ec06f5561c87256ec21c6aa92ab1d3dce01496072af5c5081aed70a073d, + 0x9849dc13d2eca871c4dc1d117cb0d5eb5b1a98e63a1821f6e0895d0109138da, + 0x133c60ae1597bcae3f030cf1a3ef515ef77f8dfc0fecfff084411ff40a6505ce, + 0x120e93850c13de3d06be4ea933f3451cb3d4836d55f8b65b30e3814a1eac7cbd, + 0xd29374214e1a4abeeb8d36880e6f43a2a899b3bcca7ffe0fc1482411439cf27, + 0x1650118703315ae3ebf1b4f5e333373428251036a1245ace4134f4c9bd3f7a91, + 0x1853287541cd687bc66770237fe3e86db9c98208e838ad1c9fbb3c2e9f0d2f5b, + 0x845a0b9344d795ba81ca6dc433abb5b9d1e083d460254569573e8ee3e9da5ad, + 0x1903d07b2722c0dc818dda893d74a9ee7fcb8b01d3b24ac9d7604c970f68e002, + 0x2b153908b83d6a3fc4b9406f891c3d51ee429c8f6906c24326de4baa2c22d6d5, + 0x1074ad520b1b0be2f4590ce97d9927f4ba582fdbda90f73810e0a75475fd0d47, + 0x1d7a66fca345168c4cbb549ace2478d1e8f0a1906cdfc1c95d323f99d6602f2e, + 0x7d8e73fcd6a35b2d8390e56d670b9ecda356fc1da46551b8b4e15380f8cac0f, + 0x24398fe811ccf72bb1583121152844be014995a9c213ff371d0302d402a22ab, + 0x303c8e1b06ec487e715699736dd043dd4a6308ea6264525634841f4fb530be1c, + 0x15186cb1c51f7abd9485ea9ba77cf8fa72584dbc33f909e7e04b01ec550784e1, + 0x1800e20927198f24e362f7719ecbedecbfd8bf90b0aa0f804cebd483ea950dee, + 0x17b074100a4dda67b9e89789201ba089d0dc1553f4b75858f689d7f9f2608258, + 0x12a869d6d8348519d11d32e678bacfd6fe20d7b02422a1e63b958256e786f4dc, + 0xd400992babe16a1b5aab5e95bccb91660f22e401082eeec8a2a562cbb098832, + 0x67fa6a735e49401ad6d0d4043563326f8e063be13b28875f6f4a9751bed2879, + 0x8aa46ab3986198d493b9707ed84a61034da2a8bd1224c5ae8aaa3a839cdb114, + 0x7d061661185186a26c40bc3d65c84064b6819dc305e3ea6df08716f415e6be6, + 0x164b5a80cc2a390326f6062957d7d325ac244c8c497448f4b96fe6734dbe3058, + 0xd267132ff50a0e61e859189065f6bcdafa349aac4881cfeb1b0b68ee179981, + 0x29b34d0febeb62b856aaa548a5a9b7308936bd163a46f67f972d4cb32634b5f8, + 0x1b1dfe465e4578869a7a113457037d7d3180b6f8be40346f061524e76f9c7812, + 0x219d6d65c86a3850cf3648d981b51681ac8e1ac0a5d4d2646b780c9e46895f0d, + 0x1709bed140c96224597918a6d6e056c2a6f80c4d27dbba0269f35966aaad986c, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x1db013be405e1edce86acb997ef8ea68ad542ecb25ffbb8adecbb9e323e9dc4b, + 0x4672cb42f866056fff733c2d9b23531608c1b541ada0026f292d08230520f43, + 0x213116708c620427db2bbc1a422b8dbe43c50614ea1ef82ee32a92c71ba78715, + 0x1810bf41c304da8f92060da2bd4632295b784150716ec8b59a3a663925fbb556, + 0xe60fe1f6ac34ccee378a7743a96cdc77f27e36027f3ba4439f599547efff8e1, + 0x150fe3d5f19845673753c10d21683c39d806ba8b4401785d8b993d5d1485370b, + 0x106f91d87819b33c496345bfc0bdbaf0a4a6da037e2ee628a609716b120378cc, + 0x27f058d01a289b1ab1bea5dd839fc0db887d68fdfc623085c8aaef5a6cc2a2da, + 0xe0dc820be1b5a101b96f1536c465ce27a96436616a4fd1580c31e3f0be69d57, + 0x1150f83988fd71cce9335017391d240512eaa73c15f11973c28c36eb4be580b6, + 0x605b14fe858aca1b47a07bcafecb571d61c2a7d3f3559e78be31efa13632624, + 0x18579a82949ea313f07863f545e5f5365a77926f972361cf7104f2fcac832318, + 0x21b2b1c8062f7650217eb2d090922460361e6f0777c227cb685ea04e70393062, + 0xf83178738a3442e7e4ce6bbdc1750b29b3fc752d8d529d8b28be179f2808b8f, + 0x259a80dc2ea8a894232f5592feaa42db627973a90f50443e08bf743273eac236, + 0xaabc1bbb9251a3069e43205b96a072e8f69fb446dd7410e4819d6298e47cc95, + 0x18f44db51f091bf261627ab6e0be73c16b257fc358b36508627779722f45ecae, + 0x2cc4a9fe2f5afe3a0ce906c8339748dd29e2386e5ce4b5aeac22aeee17c3d79f, + 0x2c254dd92d7f002da3661a83147bcb7ede550313124d99c6288cfa538db4d904, + 0x2541852cd7c4fbea1361b129e8901ca32d9c4b20b7d51fa12c87a074a7fefe31, + 0x8c2f801a82520a9a121ffca321896ec7ad60ddd9a50b945cf3f430a05263413, + 0x25dfc7f152ac74084d93c2c517b91857c51a33f8cde248d393fa1c326916e93e, + 0x29760a2e5d63406ff254da4bbc97152ac8a6a38ad087702e594955add5c50d46, + 0x269b6bb00705c31e909147f919817dfc81d8b491b9a76f223e56f81e64a9527d, + 0x1a02cef4a79e0643edd8bfcdf61a009605843c26ebedb1e9060473418f75f0b3, + 0x12c0261d1e3b247b69e4582b3a80fd958762b0b3d3ba914a52c9e0be24918f0f, + 0x263f9acdeb8b3ce3ac83bccb1918a5d5fc712680a72fd8cfaf5e1c6712674375, + 0x207434df901289e8916ecdff56dee469a913970920c64804a7ed8a26f927f177, + 0x3a1c03c9f1fa1b8391f32fcbaa1efc6ff4b1dee7f377c8dfa5135d38a9c3ad9, + 0x1249e6129ef7507c99a866d902312d3876998ad9f62ac34454055d8ff1d352da, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x68d6807831b6e785e77a20b94dfbe5fc6c23484310d36a9fb74220671804ad4, + 0x85b97abe28e068ee5ef7bb4ccd81fadecedd4818c5a6c9cf4f53dd4b44ecad, + 0x2d2caa3b84f92053cc406a11ad2985c860c57a75ac356b95a86a83ca504bc4ee, + 0x230561c2208c63a3d10b95a64358c5bc4d68d01ae4447b5c6993c8f6132031e8, + 0x151f5672052113e6f14ddd32c28c71436daaadc71d57d830ca551e770c5035a7, + 0x2733c9d71eb1f1ce45ffba8efb3de22aef7b84fea901bebe793ffcc3ee20cc1d, + 0x122c0d0a07c233c687e8156be1567492ad00e6c48ff395d98541df9044d26051, + 0x2844674637b223f5779e688bb8adf49dcbcd9256d5c314a512707b24b7ffcd53, + 0x13a9188517254bca715d460f9c6f183ad8bdb5fca7770277117e9c477d0d3de6, + 0x1ddd8eec094dfacfe2f915e62129fcba3601daf332dc8e248b4d423586ebcd69, + 0x15f2e0c38ac84bf50c136e68f78f913f74562eae48a2c20820841a471208d051, + 0x1dd71e73cc0baf4aca734d106ac1a48cf85f182373d81a854575e65ced0dc73e, + 0xd3682c39a2dc0c0808498cee222076cfc00f11da2b929fa5e063ebfe307dac, + 0x259708945a214cbceecfc4cffd2905b0628b3dd3fa652f3efe1c2af12e8732f2, + 0x71baec7a429bd060593730c150ff1fdfa050aed0d708343259063796e831195, + 0x26865eff75e2f6fdbc66213ee03b9455a109aae2e97cce07b9319bda64cfc6b6, + 0x2864c12ac61c22d4f35fda4911370070e8b588a8ee4a82a89e15c0f1a0e2d7bf, + 0x2758b8b601674ca5f526d246d221519ec40a0498db997b8aa855545b3659127a, + 0x9002afa8899112493dca6ca6f5c6323db8f352008f7d18a048d265e8cfebef9, + 0x173c758aea38f6a7812683a6fa4589e1b4a956e8974af260ddb057519e20f7bd, + 0xefe6d624981ff5e0b45e575d0b648600bd184973ebf9d9f653d4a5a8ba17322, + 0xd14a691145b25ca49c49605c64a9bad81678ea4a4e8b03fe39321c87f09e1a0, + 0x247342aea19afa49a8dbb396dedaa253930af22b2d44fe96cefd464839482abf, + 0x161febe2355426c2fe883e58dacff6e6cdc5ad5a65b28335275feba43df71f8c, + 0x2dff5bf2cea76d0888dc40cdc73f00e3057e6ebf33793c8551e211aab41155b5, + 0x1e6b6e09f8195c35767dd23c82ef5d8862ca77e999d65c69d8dc6860d494e81a, + 0x3a8fc10bf4a3949e8469732b0148594cb3759123ce90ae3e692966e31040c61, + 0xb185f3d4ca214b2e833301ff4e99b1f9ed7179b41191c9960797b39776df2bb, + 0x1ac6b03901fdc40b1329bf3873ff9277c70fce9610151a0ef7921ed08567360c, + 0x2beb77187ad776989902a94d06a98deefb1312d0558513c3dea6df48bf637ea7, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x149e18f1233f506859275485cf5fc93cebb94ca26cde5d980e6fa2c34a2f7fd6, + 0x8a54ca25cc50b034f63d2e4d10b4c735aa759c422ebcac71f6f73c841976105, + 0x1c1210f2ce34c2958d640d0a0aaf146eedfaaaef0d37c0a0caf671a8332d34c7, + 0x17bfdbafe9e56498cb3d7b15d5cd41ab86ecd47895701cd2d6f26526aafc992a, + 0xcd27920c0441d98a8992d408c219f85989ad1056f9692e3db6e9e4196bd6d10, + 0x2dd7fb93c20805f91565bd67877e3a4ce43ec79dc435f8c7a85e82c6e5d16375, + 0x5b1e6892ff615742f728d3c0cf830aaeedb93ad22d870691a96d951dba7ff3c, + 0x831d0a313ccfd57b1cdc9f30e113c29aa35e574b1f55321ae09961b87b6d31e, + 0x600e0c844243eadb86618043d2a618ea1f5ed77f1aca63f5e0ef19f6ae09a80, + 0x5f0c79e16349cab481128d04a0cbc80b90c2bde9884a94c41ad1b0c4f868018, + 0x2aa7de5705ea010daaab30b3b20cef0e74874384af31c04de33a4e1ced8e925f, + 0x585493b750ddfe70e3eb6c9be7e72b18e65de229e357d4782b17c76deb2f566, + 0x2848f8e38361bd5512352609d7806af1fbc6b1fc285b1c761a78baaa68ff5ef6, + 0x2848a529d4f7cd4bf115528eb5e88284150af414523e25d1c012f38842d7a117, + 0x30aed4fbdf98cf0212d56baed9bf952466b5347667153e56bae4b0650d8c708, + 0x2350edbb556ef46cb8c21bd9841af642ff8b3a399569aa698ac63cb317a280de, + 0x2ae5b47ed7dbdef58bfa65f573639845e0677877926e63c9929e47338e4cb926, + 0x26e087a50e753431ab4f1ad7dd65cef00d9da6058601b8525a6c517e5259ce48, + 0x159d260467ef69e897f646782f03c24d7b3e1dfb3aeb48c469603f51cea2ac01, + 0x1e6059ee0ece798edbadc0f3c244b4bdcacb5181e9e470d0591fd8cc3c8798dd, + 0x21d0c6c19bc6bdfe12717c533169baf1a57e61fb65b7cb76be2c1265c2c90eab, + 0x96ff7a0c18ef35be9bbb3e0af410e1e4b3b902f38cb838150f8db8f034f96e0, + 0x27d16991da4e246fd333112d5d5092cd3c888d8ea89eb4ab90f3335f1e11fb80, + 0x8a1e7d8bc46b6d0b60d417e4894bdc5ec1b0da7d468cdf0f5b672544145480d, + 0x1bbb994d74d79b698beffb2c1360ad7a5da1bc9ed065a38072537bdf998d4ac0, + 0x6eaa75b2b8fb3757194332442bbe246a82300fe3d9aeb52548095747567da26, + 0x35066f49fddbb428a2316e56cb7542e5ee63e2b84a38caa27f5c07e37f0d514, + 0x1a8df2d50679834c0d1d9df72b6a33e1ff4d1a2a02659b635f3908b60411c8f, + 0x1a69f234855f2099ce018e287b94696abdd504ffdb8695755a89aac7628ec4d7, + 0x282c66cf66f278b3c8f0ed2e1936887b3f4a41968af38ba8435b4dacfe4fa1a1, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x85cd4807b25336e1ffefc9b4e5d618c7aba4c4c42e34b0ab5ec21f1e264e3da, + 0x1df72bf6d33b417979d0abc3a5879c9c18059bc954a21b1753f44c98a86531c5, + 0xed29b17ee6bc79f0d0da95407ff87f10b937c1b72f78ec36499601c536e027f, + 0x2d8f67cb6abae1b1cfe21f91b55fdfe5e62fa2fe3c7c2d61254d840c2e22d0e8, + 0xc4a844d33d7410ebfaa0be3c062b2876c22b8f4e6a4459a2942eca9902f72df, + 0x1597f8a417fa1c847018051e70eedfbb5a6020525e003b207a241f2251c88188, + 0x2dc8e5d6f14e2d43cf0b273522b35e2acc391774793f09014b27484e7b5fd137, + 0x2d24d4794146908185f2354fd271608d3098e04ab4e5c6991653a1e31ef4cec9, + 0x3343e0c40457a059a893250795a6c6ac5085fd7222dee07694f6c562d966312, + 0xaf7db3d2850fc1037428a9b6913cb57ed2b17ce12775d10a2ea59921e9ba3c1, + 0x2af76fe3326af61814f0596d1e9c7c981214efab22a78ac52e4c0d2ea5f3a559, + 0x28c5facdf2832d22fc8c7caebe4d49c28a3eac34e1c06aab03da51f4c675498b, + 0x67b910e6a3555653b7d646888b1620dab05b82afdb48c08b91422e1d089e617, + 0x1a8198a68db555bb70cbf396e3acf926b66dd19e4ae5f42a62e1870e17943d9, + 0xff3bc5a50528f42394cdb10000362e8b645cd1abca45814cae31c0c1736de96, + 0x17832e2f6a6abcf1dcf5084dfe2cc5ae9a5a9d51f3d68e74743efab4826951eb, + 0x707d9a111e2bf4971e1c28f0993d0700cc18742f7a217c4c1e2027c536d1d7d, + 0xd4674bba848291e0bc0b2c36c3e3662f09831f32af732d2163f7873dbd61031, + 0xb81f95f06e846785c898ae8f150761bdd156f063b744279ab030cee5e996788, + 0x1a4724e7a15045d9cec46bc059a6e06c0abae7410697e867f97e073e7c059e8, + 0x195b3b718107bb2d25b6546f49e1a497edc07a78a37c1de15b39b65ded042a6f, + 0x117c5877ba019563589a57a738d554caa7c8c4e3342dba0f33ecbb81cf46f7f7, + 0x29f739db99ca7b670979f4a8f3b852bab3b3a2fe0b98a4693c49484b2872ab71, + 0x8127119728f625a3d35d9dddd7d5393a9086e4192d1b203efbfe9623bd38162, + 0x143607b15463dc48fd12ddebae93c174396b76933c25dbf0b2433c789b211a30, + 0x271c4725f01cd9767c7908c9217f0377f0da33e9bc492d187df0a215cfe3e886, + 0x1053f9e74f700dd3161862102fcbe460e41f0a30adc546b62ffe3ecff5c142f0, + 0x19f6aa64f3f2298722cd31bb3789c6b74f6d12f0dbd38e6ce1ff23d667a9122c, + 0x1475d80686b48bab18eb1c32e800912b26b82ac0c4b9db036c513e0b30fa7e26, + 0x29f8598b62b2e76dfc939ae61c5e7d0a159549f309ebfe2f3f097aee1c41ac2d, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x3010b8ed80e49e580f884d5e98414cb0619b5381eb0b72bea15185c32e7f2ea7, + 0x18e9d0cd62c490a574aaba9b03b0a11dc0c11b4e632094c91ef72c14266a26d2, + 0x2495c41de1debd0cb51280193a02d320e978099f54ec96a970341abe80d96a85, + 0x92517d7731c97a877e552eebec76ee7400fd53d9be12d55ff9c6b170d68ec78, + 0x643ce7cae313fccba434207e99649376ee888d3e309bc8e5ee454466274d62c, + 0x2fa4485f1f97ad4c54fa908b0b25424bdc78255af9c77da99b95095619489583, + 0x1b327749a75f8db71a4c33e8b99e2c01808b9090d049e1ab3c7abfdf5aa908c0, + 0xa062169c4723669623251a50a4318e3b1381fb5c68556df9fe137474b624234, + 0x16c33ff536f271145daec8f03d97b56d0f8cfeedb7cc329290fdc1bbfdc2c74d, + 0x1280d067c4c7eced7dd8afac4e4cb3117be7901d7121ab53f3d43c4630f7b07b, + 0x479c7cdfb220e4d8d7aca9b5fe7380b2cd447ebf3d8a204320bf81fca29eb19, + 0x14e024fd7bab2d5031241686c4aae16ee300422df8b41919ccb73fb15ef06073, + 0x1a80d20677cd1bda8c97762d6b9a006cad73d95e78afb3eaf3b7f3f112e39bc0, + 0x1434e496824b8ea1ef9ea7f9e324c937492e33eb1af18459d89b29ba30549f84, + 0x30485e0cc5588a2f49932117b4dde4c933621ab227abe326f429c8688134893, + 0x100acb69114b53c1027ff56df9de3cfd561d7ccc81e881555696e0eddfb91f86, + 0x17a974539888ada5b3ee0bc7eaab414895d2111c3a9d5c51784889ec6d41546, + 0x194dde27e3f6373c944cf9079a28d68c7c73b7b60f5a1f5aeb7cbda3be4b9e85, + 0x2b563b2786180439fbd6f3bc4ab5f3ad52f9f20d7aa31c40b0f7906f2b0418a0, + 0x1abd1c97e97d7b5e6e9183f21305dfbc5855ed33636aa7a5cfc39e6329891c61, + 0x2aebca431ac4c7b1d96c54432751d6d20134cc8429a51bbdbf10d6a5da4dbcf7, + 0x1e93b372a671214f000aa220af2453bb8431f78694d76311abcdefde664b5bb0, + 0x195338e68902e870547679d0f4a548d1bc91eb3e144b403b6d9c05ebf879e274, + 0x2bb7a0b8bcf9f7540697e3bda7793d42e1ff60838f4b59f86a1ada0373bdb1ab, + 0x11be3da5945ef7d140bf9e06b468ec44aac37eb293dddbf871f9292f6969567f, + 0x481ae2c70bb522764ba40c7fe992913e56fc640bacb97794fee400861cd20c6, + 0x919cadc23acaa8b5e19a54a996c64b59a9032c3ee6b6aacde02696ca462116b, + 0x262de0b03fe8c9a6b04ace3660570271804c66ed640998d93362919e13dbe851, + 0x2b3c90ac3a4edfbe09b333ff56cec2918a5ef924359ad5e225e08bcf17249df9, + 0x1bbbe9819a05a6fdbb2827d1bac2c0c9736aa78280f8a81fc5969b576522014c, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x142ac1e836fc30278704b47fa49a84cdaec95cec40a60abfe73a30a10f2d72f3, + 0x102f24ed9b7cc4a98957278905f772fe4149fb11befc34b05c7556a0ce1a9444, + 0x59a56c684c34007e174577c81d669d1e0b9741d4d2b9d6077d8f8e8c1803df2, + 0x1f22f8c87034418d3a79a9f5fbb2ee493c6851499ee2a84800b0e711ba76a918, + 0x2614d18359d21d25731090abb6877365f49d58ea4e78a44a9e7adb4409a3aee3, + 0xc414a0ecac4fa0637e9a4c9679085a7bb3b1358b396b2bce7eb9af4f0c337c3, + 0x11930fb18ae2944cfc25c856cddcff702bbcc81a2c2a8a81ab68e2abd0d63d96, + 0x2ae750321489ad6aab14cf7f3089bee01f50f6f1b3a1c046060804d204d6d4, + 0x1532fb2f4f6a0dc23fab57fb2988ae3a61bd61eff35634f11687991465849525, + 0x29b85c7d9d52c98eaccfab07af6c2aaac1dd55a087ca82cf636f2868dddf398b, + 0xd50d222652f613b3cf0a36450c848108600b2c98b5d16e4b75b92a1fca288bd, + 0x16bd29ece6542611c44d90e72ca96e7e81bf04cad858b88f65b3cf059348be75, + 0x114e95888f1e263e9304531e672fa0533c59aad32e19a6c8e79a0be3daba9dc2, + 0x7ed4c3caca93550d939fee72f322f5c45c45c3262481dc6d3fc21a39ba4a9c0, + 0x2cf1d8e95a3b2cf8d4c1a0dd53adee6e975640bc902e05c357d43ce4070f6803, + 0x3730a82d1114f03ea0f98add20cd73889491c2d362fcf76eaae54df206bb984, + 0x2201627d02735d6def85f3d4409b5f675e4f5b670fc8fe334c2da72e9ebb74e9, + 0x1de69df65e50bff05222e7d15bb7c25935a419532031efbea0a88d412658025c, + 0x199e9757b4a447a466924aeee5f4e3c6c0f7c0f1545808377a8c0c436b374da9, + 0x1cc1175e9e818a6ea2646c194f36bec3c37c63294b25baa9c9f48ea3c312d08d, + 0x29d4552088b3053c16c885522c794ca388ba38c6b9eb2c55e011532a5f099fbc, + 0x23d3b2dc1c7ff3d298997d064606aff743e7df6d7834c775aedbff099d458f78, + 0x2388ad46e7bff8d8b43e0ef0fef084fa60cfe32993ea7183504ee738f6445cc0, + 0x304e1e25593dbba07c1aa88ebb4a80684d9147c0b2f9247b49b5416f13fc3898, + 0xd63f23dde7572c15586188a12a7a1c0b2bd109f6343294fc8f8bc1a778414d9, + 0x19cf6ed79057a5fc4398ae7569c1b85519c97218ab842723d6212cfa9a0a2dbe, + 0x986267435a69bf6ebcded378d2aa4a02ee3b7a8becaed9ca1e663600fc90c3f, + 0x2c1575ee85e8cd3cfb63424d84ea5000786e5927433aa8c0b0211e5d87929c84, + 0x300003af788c5a7576b764f88be5b3b1ac8cb0b9466090fb331569d4c6672c3b, + 0x9edd428de05fa06b6410c57a5796fcd1ced4e3d20d42bbdc40b00ea28aab387, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x1fcc025724948f53d0456e85fb56f3f81e0c8d4c2bced5efe3fa3af8ff77acc5, + 0xc37f3e2d38cd3138ea93327d59b885873d41ef32b76409638af6455b5bfd932, + 0x1cff93735f5e8bbdab731d6b1a60d946f268b082d912fed0b3ccb525d8cb6485, + 0x115632e11c1704f965ea72407243707ec477c716cc429f1a7eb457f4337a5b01, + 0x10d1bc0b019f8bc6d1d6f5b74ec4e472b855fb594585e4458e4c269750912717, + 0x1bfa4745da3b7737814426f2b9dd6ae7ea034a00263dd091cdd7e118a44d38c7, + 0x42f42c6cf5ed0f29ea6535ba858409145772498174886db7dd44bf9ac54d492, + 0x27da68d3c98d92e4e93777c0bac6c7cf508e16e748fccd3c0b7b9fb54e605aa7, + 0x1c0dd243e40090b31d093d35c80719303b7c49b088bdae82b248fc1dc37fa340, + 0x1c3e2814b6eb0de8347ff2db9de7d3bce67b5a97585fc9933bf45f406edb6ff5, + 0x4487bf6eb305b13eea5a82659858a64226428712237312fec1f6bd536d7c29, + 0x1d4dcc7fc6d31a37c95bdb711a21fa490f4786064834c25d2e15aa82dcb762ca, + 0x1ad252b23919c93380ebfd7fe5bcc221a3dbc4fa59e555b8d00bfad872c0c14, + 0x1b9bb478853c46abecf434115d5730c6dc59d0c70ae580013d216f9ff259656a, + 0xaa2849da666039877d1c63803500ddcb59258d9854bbd817c690b32643a696, + 0x1a80c40302e2c50b3a9a9303f10ffce49d7bb5f7e5e19ddc85838f01df61cb28, + 0xfa31af23f2b7a127dcc29d7a7896ac68e3ce309a70a86f7e680fae88ae11af1, + 0x10b6199654c3e28a05df36e3ece1922c3ef4b7641b2fa8fc80a84e3e47d15fd3, + 0x23002a3e74809dbd3de94260eccf0c50b15ad8f1d0b34296d06ae58e4a28b6f6, + 0x149568dfaf3fac96b2638c3506a8d25609ca18e846ade9d19afe0c1e05c02c68, + 0x27e032df87f6c1641dcbed6816aefdfda13783c301c6e0a90c31a98f4c0b9208, + 0x18d75157ff16e95990d83ca5bc9366251a45c6f7935adcd1eed6c944dc87f5e, + 0x3019b560b7eb66353bccfe2531464754259870d8246d7f35bbf10c6862bc73b7, + 0xf4649bbb3013488fe2f61ad0d590433f5c7876a97cf9c83e821f078834c45b9, + 0x2adab3e8388934d5ba7cf03b98c23defda5c4c153364936b136828d06db12d99, + 0x149faae0107b1cac1e064cc54d1950602711aa7308dbdad89ec173da0595ff69, + 0x18601dd152b8ac338eedb1278d537c16f70e1fccd0dd9f1b1ec673b4b86deb0d, + 0x1d65cc6e7ccb7077ab51de992f4282456b818da240f46de874bdd4f6af329aba, + 0xfdc0f5a32b65a84e134027c7353503c7e9ed38f49907e28a5969419e8438aa6, + 0x65d3e753bec13cdbd2d4cb085fc25c8733f52b5372a4aede46eba19258c2a6d, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x180a916e94037f9ef13f05a1ea22bd41ca2d4b0f5eedad386a420ba6188d4882, + 0xe6fc284e88c1403f06ab873ec9d803191655d35c290740cc682caca22fc13a0, + 0x2753bb09a0c4a77b3af2a69333e51bb27703615d09d56f86423f85cfc8827faf, + 0x272db4b6d71f80f52e4aa1061f6a24e98dc041a0bad07dc46aad59e67d96b010, + 0x2378ce2c52074b027940891562743047b7b57ffc1f6654c2dcc23bedf1cb7608, + 0x26e90f7cfd4093a277600d2c564b6cd8f4ba3899b646d7427ce907a96d25b4e3, + 0x1cadb3908ee02353a3c45fbb57dbf6b392d5b1e59a13d58b57b7e0dc71c8d3be, + 0x4d30d597f9dd6720e85eabb0a7808098f72d7beae23e0f5845283cb04334e2b, + 0x193da68a7a699b7cf33c3ac942a960c154f447a016d957e241786253101b1c88, + 0x26484e7897f16c30babb9a4eb821b94e204411ea78e3759bcb55f5f9e1f0ec02, + 0x26a496b2c2b5ca5ba3dd8af6dc73aaa2d8bfd2f6715876fc5703ad68aae6a1ed, + 0x385b7c09dd2a1a0c2595a940914780d61b49f081e20149c37d920a06dc8ae7c, + 0x215ad8b91b54598e0ad7129f26f6eb4e52a27da738fa5ec2aaf3b471c2ef63b8, + 0x25c029bc5468787fc40f8b968f9542a8cf39632ebdb520496cf9ade72f289656, + 0x2a8bf45fd684c408e8832341397ec0589167c0d26cd7bb73227cc83273632bb6, + 0x1621a4527a457936aa11821e0e183c83008e201ac922ef2491a720767d5ac282, + 0x2146604597997341b5b512c2d30536fa961d09b5195f4ffe20efd22f4e4e1088, + 0xf469417d25748e654a60d7a42da219c2c1ab164e0ecf4950a3c15aaec9d7b4b, + 0x854569ac15311adb77dd8f2cee810aca29c09a47b6130b51c16b95178d76f2b, + 0xe1696a6980d7dafa5bf5a2e10ae664e0c29153272874153cdbf2b303c6c8762, + 0x3eec28f72099f4081b58deb0a95abcef4ca06afe5250a29f565b18fc8c0f3f2, + 0xf0359dc677a2208a6b0c627912d16b736e91ab3fa83eb825a7b1ead71d000f1, + 0x1eb49e2d0f17845b3e559dc12cc37d706bf9e048e6cb55a766ddad1100a07b7e, + 0x2837d91b1501a5d4b95913f0d2c24966fef7f5c347aaa897c210ba15913def29, + 0x2bf39f6cf1cef6ccfbbf97a4254acd478c897c8cd9614d3f8f9bbef4de646c94, + 0x67912e7144d6029b3bc72d448dcfdbbfe0f7e9591293ab205b389d61eff77d, + 0x191b47b69e8adfc904ff67ab36d19fbb1021c70898b9d657fb6a020bd6bfe684, + 0x2fbeb5d54229ee582a6275b9977b77ccaa8ddc90265b7c5d59f8d19af69e46cd, + 0x223504acf848236a0f7cd946c84289c4b4aba0e123b1db8e588fde7de06ef2f3, + 0x11d8e8ef78b313743937e16395c1193c3e46d4b84c78189076d7941fbff04622, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x20d2e36125e681535785dc294c751d7557e31dc99c01cc45fb67d0e0f7031e5f, + 0x2108085ae6246ae7dd76f7b3f3e0e731b7e4067602f6026c9cc61321806d4b6c, + 0x19046a9fb27aa59fd7cbb075905c65e165d16248d948c1fab9ab472c57d8ad1a, + 0x93a926faf68ed92e943507a893163b433857a1dc564f3f26c2f497164852c86, + 0x2971a879c70793d54854f7ccdeba099226a7034fa5d9911dc81aee80cf49f279, + 0xf5f5ba9b74aed76259a159321e26cbe1cd7e5849ae8562ff497c1af96285d1f, + 0x20e7786221700e467df64d8d73e4c38753a44996aa732da38e621bd270a16e0e, + 0x1f4fc008a41a25739bd41118baabcf2465fcb0e05605bb2193aaca167737e6b5, + 0xc4a3ea3f708efc883a4bce4a0651d8517c70a1324de4935aa508c3c0ae24dca, + 0x2e7610fe10352af47b616891090714c6802f3fc1fb9efb21248694ef6246ac07, + 0x2eb8ad40c535f3b7b05c2fd963b8569e956259227ef21a24b7afe546effe4184, + 0x154989e705cf9e62b9416e28834a4a7bce6b573a1235264ce89d4b046b6ebbe1, + 0x184749a0e1bec0f94c8f3c5be0c76d87976952449c2bfe6304413dea612e2e1d, + 0x24ad4bf83c2f3341dca0c72a3575fb12805568e92cae4472fe19fdff27f11d50, + 0xe788a096b2d4192046ee742981fa38918777b65030ef53957571c3b5fb54a6d, + 0x1e22b9d4c274fad52d4e5640b4acbff2c4810127a087c42f9be9ab58809d0d5c, + 0xc8a3f2ee3246714404abf0521e74a63b83576496aaff85c2be74a7106846f12, + 0x21adde943461bfcbd7eb10345a94033b25d4701157c694519fb2b4093b756709, + 0x1ea99affaa689d6f19f8a6b82d4b81dfd1f17682831e0c00d7f2f8fd4938a37e, + 0x16949199fe4a38750de73fa737a283a6a9ad40a27b0deab631f9295ade2423cc, + 0x1e83bd581acd61c3b54afcb7a0a9a0138d9ac4c8739cdae89759da5150138fa, + 0x42a61a84c944dcf754f5a97b1dc8c2ee7bdfbde233f789210f506eda56973b3, + 0x2b93c28b157ce32bfa3b8d0f585061e75a03b79c366a75856cdb5ca2273e30bd, + 0x1f54218a5daea6045fa60b06ab2520c52560282b1cc3ade14b664bfa49752bf5, + 0xfbfdd369bdaf703669fa5e36a00aaf0b251a50912048adadc83aaf092e7f2de, + 0x3633bd5a72a51fdeca62aefe9434104b52e152655cc42f06e70455cc15f8e2f, + 0x2c0eb54b5f8cee8ba898a242dca64def09dda346d06323892957fa30b3c13af7, + 0x165035983f563b1e3bcbe6c873fbf911d194fbe54243e039b3cf7b6f2afbd822, + 0x2fd9820b3cbb131e3575de4ecece3471352587e10c96e72ad867bbc57f4c778b, + 0x1204b919d86a12cea70e977706ab2be78259c6c608dca628eeeccec50b829342, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x2f3cd03d82e80e8521a2366bf79e8d4ff5cfc3b4f46db99a4947e1ce4993b2b, + 0x1cac3fdc9674c64c1614a5f48d65239daa601e26766fcfcf29cc385d6b3735dd, + 0x65415e4dfe08e357c669d145be5fa6cc74b0126f099faf1d7e85fe9befd30d7, + 0x28ef19ab4bb2626906730f539497dde648a1a967da5ea31969feb620d115c8b6, + 0x3e88e9732a1a572e70d7cb6528857143fb51a949fe9e0fa0fa281b85b64b7d, + 0x2486ab5c5311e4bdc65ab49fc60b172f851908d6753f6a9cc40f9b1535af072e, + 0xc50469c6c6bd532c6f805d26a30a7e5d703e0537657518cda0e1c6044301ecb, + 0x28f8be525277b0346bcd664cfb0a24a028f90b89ca402254b4f95833cb7ee870, + 0xa68990da12f327a6d79b356c1d27642392b1b2cd9cc0b5d675d98436066e563, + 0x2216dafb41776a1941b1f17a5dd8cca1cbe0f60f81ceaac465861b3dc2ebbe61, + 0x20e6c97c374891d9328052361d932372efcb6c0c84628b6f3bfcd41c47d1521c, + 0xa2565ccebd103dd144534c109f53c5de275ac56e9170ad9e3ed0b600aa51ea0, + 0x1e79a45802b9e7592e60d7e4964e8920a458862cf40212db96483540a62acf3c, + 0x29f54f1a96514b9b42ec9d74b5d715e61c265b129a7061bac126bfd50f696fce, + 0x26bb61d61ff279242f1e5c7bccae627e1942ef8e103a915b64527fd0eb31a93c, + 0x1ed4d606d825d86ddee16689f24ee5d9832a140f44b437258969f41d4c442c7a, + 0x25131fe12798f1c8712f4eebbc7213e8f80b23e7d1bdebfd255c18793734f251, + 0xd921ed8053ca270d60349d85ba38dfcd05bc96c05a68677185956707385d626, + 0x25c7ab17f3ca72fef63042fcfbe1a3d5f1ef5d6e52da6d6dbb5aad46b1e17421, + 0x1ee03839ca2483009bebf461b58d11cab852212642d38d1d33e48d9956fc48e1, + 0x15a5a2eecd107f307d9565496448cfdbbd14ef42323275c0ab6597aaf1895475, + 0x3fe00f465767add4808ec12aab687e16cfd702c1453267b7a2575c6cb557ba7, + 0x1577821b07e4ba2ba893bf15ce062c0290a2c757ca7140f76c2f03b53d84edaf, + 0xc00f28af5cdd011907df891669d0a43892fbfd24ae7d2abbb951b67334158e0, + 0x11f2f4cde668fcb28b27153f0c0d85c86fdb4d0506d38fd5b76d33734868f4cc, + 0xf15bcf82d1d583869605309b58d382a4750fa8221ebe8126ee522ae696abfa3, + 0x2a87c83c58f55146158830df52d74403e32569179b409d8e97ca8a27c7446bcd, + 0x1b655b2c43eaab5b8d104f472d8d84a836246faf3733debaf470b8b68b3c6078, + 0x2b4c7891572319263680116a7a29e9ee3c39520dd8bbf33016e31b88444369da, + 0xd57a4ba309a380ed8f907c68adee0e2ec336a33d67abfa6d33c0b34191d5c3f, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x24d7026b9df6dee3dfc366bf883301d2f5b0d769ffe6f625614731c81638a5f, + 0x2ffa9260d3bc1a98adb5d9a4566a673a4ac815d921f66a78c7b6781f5a45bfed, + 0x1c49dd9439a135892456c194c0b8b727f5f8dfb8b46332cff79b0e88af0897e, + 0x20dc0d730c188f571f944cda64df0385f31ee47784649b38bc8b309fa731002f, + 0x2a57e4f3c1d3410302207d53fc653b091b9215b9914f7e21143c5ec3d6080206, + 0x18924496a011f1d0f7334c75efc82a756b5fa7b739ac213742e747f0bab85110, + 0xb488da92db9fb460de597bdff5917bc07393e560b75df7412a23f86782008ac, + 0x181707ed73abc47ed303001ae6fc388dfd30bcaa57b75d4667fbdedea39addf2, + 0x2f3fc44c1a30bcc3419b88de657072843f3eb73178989484e010a66c74a4bf41, + 0x19fc475149f3945f3fa3c88aa7bb166e056cb353a2bb28e98cb2c647aa72601b, + 0x24e52c7ecdfe59ac393a7e3659fc038f582a29f0907d9130e1615a60e0d8ab0, + 0x7be6f1cf7191d8cf88349cecd3f83df5493edce1708f65a305c3e749f06da66, + 0x1f21a4d143a3496cd6736f6462d52ce24b40630d8dc8ccaee1f4fe83d2d8f8e5, + 0x2d26efa6adf5af54f46c6835f4d6d13874b5f0f329b21a280b19399f855401ba, + 0x189d55e9c0ea390f2e219fe4abde4c0ec6fafa1b68f5a029e4d2d5f2698c0572, + 0xb825420f377252cd094db40d6f37806ac50896f01a6b563627b6fbf45bab59b, + 0x1fba0c700b9f301109b83fad61964385ccde2cde69510b66334feb80d8dc5e13, + 0xd4c0381cbbb23ff4199900fe9e98b0588229e95cdabde87734b7da4a96728b1, + 0x76f5d00e73e4dfcf13f558ced96fd848d34ba5ec48bcc141228c22d18689433, + 0x1dae42a7e24553210ec1d37a83e7e379f118af2833a638cfb2f637c2731b167a, + 0xa7cc5bf24de2b7a6553cdb103f7b93a2ca50e7b8b2947563fb8eaf4c96ac22a, + 0x2b027765c2982281f3f552c9fc239b96b0485bcd6b246567189760387d54a530, + 0x1001976662b6ff1ec3f6510318e518e6dba3e69ad0635a41153e18435653e16e, + 0x1f0a377816189522f724ea65404ef22847bac0fe95e2a6c666aab27cc4dce446, + 0x1e7a94ac5ea43fd868784c2943205aa45994575b494a0c0c469f6be322077c78, + 0x2791206766f62a06b3a0a0d71759944425e50d392218b999a86bbdd590184075, + 0x11ad87aca6c25e04cb85eb1557e42ecf5851a9d24d20f9ed554ab9de9a561814, + 0x7d76ff83e9aa3f5924ed313b0d183a5703f49eb17db9b5192bbc1e5935f41fb, + 0x18eec21072c91937e53d9fd0e38007a1d8ecfef89ee0a848e5c42a73324c0897, + 0xd7ea1d8a141670f5549461c8e6649e7c0dd2692756c6c25cc4525d437728ac9, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x1d9e4a0d2a85dbe20e640964806fa1e5122e2821f6f46ebd2f614f52586612c5, + 0x1b0529d2ba99f99c7e4958a1dd940160e451ad60a731f482e0eec4f26806ddb6, + 0x2d78de90b2cb9901ccf75821db641e2619beca024e3356fcd20b0744773bec1f, + 0xacb58a5c68bfa43b46977a9da02f76727974e24f13f1e6e7646fcc17235bd4, + 0x133449d082b88b55b324ec110cdb4dab792843e2915a039b52f1399096abb13d, + 0x1e40b0c57597c9efd9e21aa03b9e60edcfcc6313f2b325a1bb552a227f466cf3, + 0x1dc4ed7c60899b410745ed729ea5a0066568b97dc007b6e7e804769dcd4d7d36, + 0x1146cf1be34558e643e2850cbf90d1e25e3ee122f8292a12b8be4cbbc3b02f15, + 0x24cc8fc4c875a88eca4864b038945f81381b829ae63156e314ab257829531a0f, + 0x29f9668dddd6103594c092b4955bea42a78b762b014f853d12cc8a435deaf507, + 0x423f8acfb6425857f07e45bab4474b2746c987eeb3cccec94f838fe25d524eb, + 0x226d21a206f17d649306ea18a42e50d395d65136d082d91b09f226e63fb6540b, + 0x50d8e0202485f6ed926f1036d1cfcdc3252b49bee257218aa058f8b7a22323, + 0x2c6998a3a1d4988893eaba746cf07ec665089ee1498736a1580f2a7b3f840a5f, + 0x8f07def8f9291f940b044443a720f15109a6602e54670e4ddec4f9bed773f4a, + 0x15ad9c95848c4eee4228b1da242da640ecdbac2ca6f216306045c794e0cd41eb, + 0xb6c94ad59e7195e47046f5e2dbdb395bc45ec654b60c49d8f39d9f8b895d1cc, + 0x16915ac62623b19ce2101c05fe7276c373b329f20e1fe2b86f85e3bb18f2eedb, + 0x241c174139afa0867f108586e337df3173bca36eb41a669da121cc21cc52e157, + 0x2fbc48a493da3632871d2de5a8c22f22112afa88b1e71395eced016a149941d4, + 0x1faedef5274cad9d8a55c7f763fa86841960a0746745c35950bedda80b6f4224, + 0xe5ca90496f6ab2db273e54bdd99ae0d8bc1c6f0904de14932958f6c837c26f3, + 0x1783f5edffc02d572faa7798200083b86b2b1ce2320dc7c8a0b1ebffdbc9d567, + 0x1108f89b2285ad02285b4cea8eed22d0fab841f21df3d4ebfb398606a6ba3869, + 0xaf33de737c3e1f423c51d89384242ea23bc564bf402282002cd30e3b163468b, + 0xc5152ce065fcb30be4405cd338d85ca50d6a06e9344fcc7634d82e0e9759a74, + 0x29b859531add0b7229247872552339e4ac2ae3d4b6ca8c705763cc8193103aa0, + 0x87622acf27810277fe3cae6e270483d0d53158900fca1849650b0b5ecf0150c, + 0x228844894f0ecc516411b0b864dba98a8c26ef510627f2de70e1d13bc30a6e1e, + 0x196d69516c701eb00c670cb577336806429642be8b0e301fe0bb12293dbc2548, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x1f70d88a852cd16c82f70637d9d973d59f7e77b8268aacd484e4e53500f72b24, + 0x141cdcd52cc304528f7f93f23944dd16b3cca1a85b2a84670c504b9792beba19, + 0xdb56745ee0dd133af6f37bff1f6dac061ec7e40069f9a811e7d034d7a30abff, + 0x2569e01e00c725b48d55d26fd8c49785fc36248299eda8abd3b92b20b15020ba, + 0x353c1598121daacd532f8b0ffd175318b309bde28b7ffada32bb73b784d95f2, + 0x23dd1ba2b7ada18fb1337535b938fdd5318a1ad228cf00747d07efd159cc23cd, + 0xa449d239c51400de8f275b00787790aa508e1e160bb66e87d0f4e32ac5a5bb5, + 0x2bcc35ac47eaefc5ceae93b97187f199f4ea9776095a98efa5353da21540b9c9, + 0x22e49a4378b6b69566529f55b874d2304e24cbaa5d790f76900ee2f8478e3c07, + 0x66ad5b80133fd0a6391c05b7e20b13416e40c29a06469326768f24276fe1841, + 0x3f2253229c2810aae5c8411d5130ab418bbe077b0f1122623065532a259b857, + 0x2662e6c8a1134a005867e103901a5f6c67ac3737a6620accf8034cb83bdbd4a7, + 0x20a86066eeceb6979baadde6a2359befde49875bab142e57e171b0870b292086, + 0x13afbc5573e84312a43160ff4045190adc2a9db03980e7126381f4089e7c91f3, + 0x7d6db6cddf350cc1d59a474d84fbaad04fa0f2bff915f077708df41d5b2a746, + 0x268e93e46fd7f13e1a359ddf6ebb619a21c1068de6d899590aa1048b8829ddb2, + 0xf889928b305b304fce28f103f2e4194f2b29cdff231b05efe561e1cff4e70b9, + 0xc547ddbbf87c32bfe454d8e8b0ad4402c9b979caaceaebd9d59484d43cd37a9, + 0x20da83182faac059a9d00b35dc345ef0115117fd24a15f6b91b501728497ae52, + 0x1f6b643b60e535d0f2731a326273576ea723671e6c51e7b74281028ffb0462ef, + 0x2d14d43ab2196fc70e26a6b9ef3f2e9d18f60026af5833359f2a4f694ff6f9cf, + 0xe9b85853becdc05429b0a28a7e23baa59377d9037615ba740893eb971aadfa2, + 0xa664658bab11525d7086e1206ae3c6abb9ec31e3461d6b0b2547a5d6c2ed54f, + 0x2e0498e8539d8576df187245d0b1222f43cf4d3f8f0209afdcb2f68767633406, + 0x16c87c7662e6724263b44dec088080333793ba2002fb9669eb63dc3b1189b6eb, + 0x9c5eba75aefc04d0436380c834da36d20a67fd4e11653498b4ec21b30900f54, + 0x1066b5230eec70bbde6c98ed4e48e392feb18967be71a12ac18e732a04ba9841, + 0x2dd2a9adc1fd3ed04eb259dda630b58c0791d7ee79b85fc20ff8b37ca0dc0464, + 0x2e94a96ea1f18a9d99bfffc3fe43f0f751bcd549d1e5992e366943a85ccf4af4, + 0x8d72e9dff20d4f5c4543b725e43e01f1cbd2bd0d9ea8ce6b0c1a9b0b2e8499e, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x230050eb9901e2db2f16df59a7f5b8a1c441e5fe9cf3869a4ed073ba25f5d13c, + 0x1c2f7f401da1ad989e6cbb5c81e3559a7930ceb1916691b9b2d702eccfa3f844, + 0x9b391cab0c34b91b155483a41334a9ae97203942d7683850100acfa35c51600, + 0x134816b73312aacf2f573418283f27bca58d4d23624890f7a3b9ca81c12e9718, + 0x124b47f9ea87c94130ddcf77f87f4bc53ee087699d0e5f62663a63891c1675d1, + 0xfe5a21251a65261e6cfc3709404711f727a610f94057c304e1ba67b2f006526, + 0x28ab3b64f6f6f0ce2707fbe854295616d676dfb0d66177af6679b3ffa512e8d, + 0x1870499da8f58f00acf6b1133119d757220bb54ecbd793f9ed42d65c31760fb9, + 0x20db70356dd8d855ab92b28a96429acd5ca77cd9e5211aac448b991c1650893d, + 0x1a1ff1c58192f748174691a98d8c5e733ed80ea5c2fed11b098fcb815b438516, + 0x1ab2399c7e7ce1f5d3ef6c3cf33f39ba83f054bd73d8c5d7425666ef390e4f69, + 0x1e4b5f8ea2fa22e568978cfd90777937efc072338e173f49cdf7761a9caa2b7a, + 0x2305b22483287e9568160f0dfba637f50c63472dd89e56da0611b76cfe869104, + 0x1efc74710147e4e7df6580d0ca588b6f338befeb4c6f8e8a0967cf5c9dc07399, + 0x43c5e4ba3ceaec4190acd05a266e8d339681eaf1247af047fd0dce72fb37c0f, + 0x2ad5f9fe59cb81bb3eb3ae9985a905adbf2fee8426fe0ce3c1b108209aea844f, + 0x1f36ba0d22839b3176e55a9ed07dcbf0255e386bcea0a5be9823dbb3300ffc31, + 0xa565b3ce5c2aa38618127678d8aec23595e365f5e51d97474b85b16a13362f7, + 0x271dfc29144730cfa780f9accc99caaa7d14e05c42df401293d24759c12d8ed3, + 0x1119a78dd0cbf88014b97e6e5758b64c8c133a5989b758af60df2ee0540348a, + 0x157970a49dadaf8b39d46ada19fd06b34784a6f33b4d85547c2493f27f389e0b, + 0x8697357bac4131984b26ea8e352a3c5e5c33ff22f09019646f43b5137d4df31, + 0x29fecb3d70e1bd21087322a9d0f0db92c65f141f02b45936d9a5b8535f0b955e, + 0x14297a9dad6ee3dd0ad87ee9c2dc63685caae7391012e267da21ade2aaa434b1, + 0xc8f3a7ca1b4242199d6a0999b30cf3e61dfda56b98dca4c9bb199a070f9c782, + 0x2105bc020b9bfa1a23b0b2edbdfd4ce7bdedcad57906d2f58053b8ab35f11b43, + 0x2deb04f6f90c24a07d2f36e40d5bdef34639b092d395bb4a4fb483f84aecbcbf, + 0x2964c5940985822a64ac1443efdc41cf37e87dbf858535bc7c87181768091c60, + 0x20b68c1b5ede99ccfc7cd1231b13e90d5c9235c36f2f955dc6ff5352133ea9de, + 0x30096e11896ed1672687beb4f6725b749550667e8da418713bea7db5f838efca, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x6e21228ed894978b90a5e0b691d8916aa63720a5c795b9a07381452e22382b9, + 0xc9bcf80dc5fd89ebeb604437262768ae95fa7263924501540552e7a4f2414aa, + 0x9a6be7304c6da043de4c03ad5c76101a8bc21f1aac8dc10a695c7c5fc2f9072, + 0x1d78923d01c8ac2f59ddf5f046cb5bfc8bfd083ec61b1af080c79c2ddb27a832, + 0x272ae649640a5da291be7915b01cba87251bc6272140ff420b36f27774594209, + 0x4b1441ef166c520f9309f2f984011a00dfc71d6139603ee90496e59d715f775, + 0xe8d1281ac76ae45f6f8116bf74982ba76109c42a2ea163357febe0422658c42, + 0x1c5d4250da762fafbf313804257126fea15085a8ee9c103a9992950ab4af92e4, + 0x13d55c7c0b5e9acfac2196201e8e4a1ca091505b12b70064dcef6f9d3b1e18b7, + 0x3e8a03e1e25fed9131b3de7150da5ad0b53da4fdbea9729dbce40ce2535f0f8, + 0x12623c6993f1c30108c7c79868c88e3943a64595eb7bfb5814791aaad5a09ee5, + 0x1d38303334b2b1328d7453019c571fc28f1bc5e4e3c9450b491eb870d2c8fe89, + 0x192231ebe3469dd102a003b41ea79237429cfc4ae4d7d7b5f49154aa70b918e0, + 0x26587d8d2a074923798fa95b78d558a7357f48989f553ba03bbe800e4d4ee582, + 0xdbec60681a76725fcf9b009006e1235f2ba2d3f09ec62b50011d19ed58019c6, + 0xd79206c8a30d26abcfb375fb8c5a117f3cab1c9fda8ddee17c0991b11c63e13, + 0xbc57e048679764b958ec54b82fa3bc4690e99591f42216447ec6ab89e5752ee, + 0x19b73a25670160ec2631863fe8b93691a30a5e6cecff4e91e4b56dea4e9d75a8, + 0xb02dfd4eb79d59d665794ed829d301ce08e2e5285bcf6f75a83f23815f8c5c4, + 0x2e8eda48e5dfeb71e3302274f516a74131fd336a617126a1435cbed8ef6c9d90, + 0x282c1f1d562f2927e694715b631a176baaf7621c44a55b90ad2f1af512f2b499, + 0xe24552e72a2717b254956fce21df810fe3f1fb66ee0224be74aacac4f9bafee, + 0x619d6bb9fad7fe7a063998dec9888beec2a1c2206bc97f6853c10e62ede2ecd, + 0x10855580bfa613c21a4efdbb0f302d4d30a87a79a77cad82b37ac76abe5071ac, + 0x12e7d2df332cc5d618a22900e665529f2c22bd2b2aa387d9cb30da9483f71155, + 0x108fa054801185a6aff619e7ddd9dc8095884ddcf3c85b8c922aaade7fde8f66, + 0x2f8cddd8f2c5d14ab14b93182197b8073b4e9c41c138b6764ae3569771e617e9, + 0x1f4622a6c051e3696414b2024a39391743479968b4af8dcf07186d5c2ff07972, + 0xc379c514adbbdcce4502cce0b85fd03fae98db9d8f36d3f3c56cb9942ab7877, + 0x2b139708399f0c23fb51a4d24e7189fb1e619f5c7e03bcb8c8c32945d8e1930e, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x1a67fa389778c9489c495deb248e754c3aaaaa63c5ba3c6e5cfd96be4f516c01, + 0xa82b7efeec16e6c5aea5e99597b098504973c824edbd47a27cb33d65d7d09dd, + 0x58b5d72d0fb9836dab90890a9a9db183959618b7de3d6b7b1fc07621644bc7a, + 0x24411fc9331c4465de389c157199ca24f304424c0481d117e7b0ea23657af1bd, + 0x210351a45fa4ef26b2837ad06b46629051a464602e52b36ef24fae76d1d6d34e, + 0x1e05e49db66c3340e7db14921c0262a7346c687a8c26137437b510e30840eb59, + 0x2e6833d4c2d492a05a1c2be458d06a65f6be428714d1d44c2dcea661571da703, + 0x2747e0fb93ceedf91d0b703ccd88f179e8f10331090321660985bc63897241cd, + 0x21373fe7342c29074309be92546ca3308e28215172d43899d8b34e336e0c2feb, + 0x7aca07d0069a023d78e0a91f67dc748ab58990af12f54b14efbf83f6ea3f959, + 0xd31908df90c1e9debc10476b0f17dabb3ae150d731c20a321f5ad6d28213be4, + 0x28b90adb926df7693277ffd23ca737852a441517a8eca29eccd732b90dc0db56, + 0x104147d1f610150c79c7bcf61ef1eb1d1d620af87c49516a193790dc5cb1cd77, + 0x22704b0eea545e93d8567947f5736159b8c7559da9346851ef034943a9f64ea8, + 0x12cf13867e1f4c665d952955497197af8211929750dd706a6a65dc654b99e8c, + 0x2640c797ab409cc3b3ee21869418ced6c6aa32c8d96b9a3da85c99d8a2bc9501, + 0x123e01798d0948749ff8ed24a732705e44162826c2c7d28025da133ec358b822, + 0x22f5988c47c36f454fc5c2f982b854b4f4f64ac69db58a7820b10ed05a1c1b7b, + 0xd71a0b148c465727aec89bdc6601b3bf341159e0eb92672fd2cd29670509550, + 0x9c4450c0fab5b77b7feddc8f4c50031a113df973d3dbff0101564f4dda5eb64, + 0x216909b9a7ec927ff4be81f45f34004b80de648dccb64e956e689755c1d08c9c, + 0x1a676535420e170fdcc7784668b421502d69e5955992d13133f9f53829fbfc74, + 0x2f45e803db63d86ba61b8ed3af38c48a00d0ce69c1507e85647022d6f39ee208, + 0x3cf89993c4654efb4b1e804dc5abb423ff507f7abc65cc8d1a660671264a2a4, + 0x2eb840961ae22d47e776bf9f78d8f09786652eb99782097010e10fcdfdeb9ee3, + 0x13b3fcc3c156042dd30d9c935a465c52827dba78cde25cc87a436845a38cc1da, + 0x2ac2949357bcdc53d8a234e1954aa94813a0825a9308ee3659d5d386b2f10e59, + 0xe15460bf314de3c67d868973288483bc62926bcbd2e7042ea807888f7d9c19b, + 0x11c767a3163182d5eeb2ae857a5b3010395f9640b440f75a9b859c30ab1800cc, + 0xde4b8312d23ffa47cccedc65de54ccdf9596a2c26a8177b78890f9a0000f1ab, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x22a306748bbb7276a025b998d053c75dae5fa78e31d6457189abc977665065d7, + 0x11e89b2f5a9f708391bf115992b295c5df50eb4793379139749cd3718dee76c3, + 0x170d1801e156ba73911ab491c46bfed177c6cbec44bda6573298cfd6e925324e, + 0x99425a344bd24801fd74847ee7524054b2c0be72a58c42928008d7163340593, + 0xcb13076d62a1cceafc495baefa2cb03ddbf7bac1a8b24afbf0a84236a1fc1ed, + 0x105cd167cbc2994138f2492a42e39c90c71fa1112160c2c3cb86f4a3dc6f36f5, + 0x2fe235ad0ae252a09231abadf1884793e1479f8953587d08f0fd843c73cee60d, + 0x27b02875c28bfc1217490eaea552ce39441e6348a660a8dff460564b37002abf, + 0x1a48ee09ed16a03c4fe2c433bf85bdf4ae6ceaec8706c97bff764912bda1dcde, + 0x175b14cc4245b469dbffa6970992a1bfd6c61deab13c5dab26b1481b9e616fbb, + 0xd46b0974195aad4698bfd176ee33fcd84a725be4c13009c15d2d00fdc176a16, + 0x1aadcefcb3f21adf4b25dc908e1faabcbad408c2b2cc24ca5a35e5649c787361, + 0xee80d214b808612daf959f09c2314312cfd09a7050243e69cd993c351f865db, + 0x2b92ed72f750583d1091332acc37a8c11ff616ac98ced2e2ab47e2650b783ec3, + 0x7bb6c047a0ab37343ed2a2d1809345f72ee0921b06685f6356dca855053699d, + 0xb27c5c1f4f08810c4c71b00309204a5ea1602065f18c7c9568a073630551272, + 0x10eb21636ad3cc5b882f8eef50b164f5c0f05e3a45245b1f4517b3ba19693feb, + 0x139afa8d7c7016d8b50351f05260a2f1661a7be1166add0f281fee3a5fa57c22, + 0x10a8316597468b2f19a7ede834ff7ba4745e614ddcf43a373a5afebc45849d74, + 0xe7bc88dca5e934a90b30c06fc33c46eb88311db5ffd138d2cdb2376bcaf4ce1, + 0x1ed3520f1f7eb308510f20f8ad87099d28c26165a9deb3338c76fbc7b140b4e7, + 0xa5b057fe093ed51de90edec1f4fc54c24614c3540f8d36af16022affde42d34, + 0xfe1a3def2a011ba748f9b9f263e88aa32335ffb2e9857bb3a2e0a1d14edbc3f, + 0x1f6abc03a0caba9732b313a2bc3ee30d379088b772c6ed9e3d9d3cca471c249c, + 0x32cc35f494c7b826ddc1bb185d14421decdc35c89c4353e13838ec0de0e777a, + 0x3526b4fb75965e49be0d73d43e706e756d84f80db93afde6863cc49b017f199, + 0x19033bc3c4271ab5bafbeef999077c33386c044f05405600b0cf174fad12b8e2, + 0x17775184817378f639fcc8dbd97df0e13baccbd90c83f0b4807ae9a486bc0d4d, + 0xa9e1c95520650bb3f61a8fb1733069fb5eb759593c989c7c8c91cfa6108c3dc, + 0x5261006343d0f17ec876854ec7d41315565a07796e7c1735825e9dd2bf16e39, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x2fd7377f9006f870d0c079c8b10b62647b7c76cb481b2a330113cc7507effd1, + 0x1aa6d67de3f86bd58f04498f5e71270a58c7ecc20d81891ec7bcc29d92c84447, + 0x267b52a174ac8e9d118dd2d021043961fe9686c7156c324bfef84286a70a20c8, + 0x7131b4b73af0697a2a744e3483a653379f9a6f66e05821b9d12aa2b8fc7f52f, + 0x678652eac3805c1636bb62390323860ddaf6f1ebe10b167a39b975cdd89bb54, + 0x15209b10675cab6f50d0496771117e050ce5120126d241672e991c2dcc0cd1a2, + 0x1a1977bf61184ad35c53ebfdb3af41776eab03b2db826652e35ad3a12f745bd6, + 0x229644c842f9907a93becb162b12af3144a7c7f25d064d457db70e9c9cd9c099, + 0x17ed9abfbc0e4103e9e4ce7d1fcc95f2a8a0f8adde891b55e424f76a93f7a915, + 0x2104040d07bc2a79abc7fe60e6d2bd8ce79b937d7772ecae4e21cd38cef7f792, + 0x29b17696048b7c8b2805e7f2adb86cc14a6c54577d4d4b741c844203812cc98c, + 0x155b7c97543d530c1784eb12a8c8e9594d423dc45a5a93a6e2ab2aa25210f1b1, + 0x2d95cba17ff1a2f3ccb165e7009314c54d1f5d2ea514c54382ec918f0d18822, + 0xa9d8db94925ee88c53578d0312159ba4568c4c35b2160748f7dafcc99c966fd, + 0xb6f19b020cbf0eb74ccdceb22d7ae4730f72db5fff4462bd39941cb0bb2298b, + 0x2f709aa70fb82604e6614b07127fead0d6c889f96277da8085f886a592d8233f, + 0xc05d5e71c8ff96a669190965b0d7aed88d1c5df73b70de1783986bf8851507c, + 0x8facf13f8dc731b2f216581d4b35f10f3d54b6c41457fd83347417cc9a4dbd0, + 0x1bb219a4559f69a5e3ca3241a56ba26e36c86955feac34676c2d13a671f470ee, + 0x32054ccbfd7840e0fefec1ccafe4b21091c2b9262c0337b269d7bdeffbd615, + 0xad0e2165ff04113883d2e76bc8d519702644c1e938b80c614ef85b966c7ea95, + 0x5d0cd6f76ce14c2cc307b211409329b29fe0e80742c329b6468d4cb6c4f8938, + 0x2ac21c0635d3d249610b57d8312443a9c30fe4f353e75d7503d4cc646c7cc2f9, + 0x2c98f53ad12c6d2f2c1f4ae0922f10c9319cee3b55e1720799c16fa36c65af2c, + 0x1fafe9cdd001c028a8c9895b9075a18f93f8ad25632312000154e1b07d6cbafc, + 0x1c66e585cd1c5651a3b651ceba4e33bd7954af808b69f4e8171a58339b6754ae, + 0x2b8004d7066672e9c51b5efb0810da89bdc481658149d974641e43a8e6150512, + 0xf19a8fe86ec9c9146083520d9bd83bad613879a0e422c27e09cbae6558315cc, + 0x12199adee14b8fef20070207a6ebfa77f4f9202df37972a31e11cab9c622a3c6, + 0xf34bbf250e5eea168f1772d93ab7f53e1dc570c706dc9818639f0181174d8f5, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0xb2878f79547242381f83f53d71b4a5bb50ae79bac3b09690c2ec04c27952831, + 0x1636796259d819596441f2418e0c425ccfbfe67fb7b497c4361122748225fff, + 0x230101fb2086c3e4dbb4e19b17dcc891db81d3eef3b5c031b2b1429e46fb956d, + 0x2033e660632e0b2e8411b43b8b0fc9d23ba811a64aa846b0882516d954738316, + 0x244564f0c62510a5e6f69a1a8fe77d6bc22ec9989b0f97dc4113a2fddcf2fd3e, + 0xea22aab739936a78b3b85cf512de08c6ea303f53fb69e073d2da9b94d60ebca, + 0x701868cfc18808ef3f8196bdb7bf2a8aee96cd85d269db60a4cd5a1ff9b2e88, + 0x904cf11c0b58e3fe3aa7d70d8e365f6f20424f7cda13492c3a1089c3e209378, + 0x1d5930f08045de1418cfeab3a30c08015f77a7a19aba209b992fdae1837e01fe, + 0x13d07ccbe92ac9848da4c5651b692c3b298bdd002c76c1673e39b0c56c92cc4c, + 0x29fabafec859d0eaea7b49a815141e2d5e826c1bcf4fe2e2c4d80d0d9026a9e, + 0x1af5ab322e026a1b28a1dc06cba8585550db1bbfd3ee2355d8dd1c7d413126, + 0xc60f6e36113ce5d3b8824f68a33bce77f8a963eb0ac4208a35c0fec601a813f, + 0x17ac4c1dc0678e3afeeef3a11fabd3d699456839342277c4b6a57256a94cd1bf, + 0x18d140a27d4a76d1daace46e5201c2057b4e1353e6e6a90d250798e59b055209, + 0xf1336ac56c60c4bc9e27765f43bbc4a25830e514126dedcf518f1f501cab662, + 0x240e3c3a7dece37a8e4674ca411513bc5b2ef205d6afef56978ecdaa310a5fc6, + 0xc1f16c8ee024584c6e5243038d7324bd631263e4036e9df5422f78c8b01c9ca, + 0x236b70f7b76e6f16b6f4d08f6c6755776bbbf2beef38ed9f187294607fba3e4d, + 0x2fae92d9a4260c0eb67b8b5c535ef6f43913e506e546b3a1f217ecac1eb0ee5e, + 0x1e69a926148d04785f08760176dba2be1ee5b4ea19bd09135d5b68e7572cd1c, + 0x2a96f11408f216c5ade40371fac2bd452a578ec23bd220897aa3372513bc4530, + 0x1522e73fa41cc4c23e9ac6a6df46dc33e6921b802be72ccaeb06de4736cfe988, + 0x6d2c787e7b336c0556293aa8a6bcf7d31be6d8b6d4a644ce77b313bee3cdd01, + 0x1f80057bec504946a3e8d5e8d31412d2fb6461b5f174974017f2798fff57c306, + 0x139e43308691da278944e95e910ff3c4903e2faac75a6533e7f1fcf0dc8985ab, + 0x2958715623868ba98fd982a092a9eb18fd0f2cc9d3ad44d03970b8c2361ed38d, + 0x3d037c068aefcaf62bf84b4fe75a8a46a5d85d63b659278b049508fd31d673c, + 0x25f8654c412e7d630f046c138dfc4c18332573d9f2cdde26683fb472fc8b2edf, + 0x1874b9d07a26cf2fb8c65b8d47c6647008b42804af1e7ceb2c7ee466a2b5807, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x22b74f8ab6acc3f3ef0d9352aad479f2db3f5171684734ec6d18c69cfe0b14cd, + 0x28ddd3e0a84efcc63090346d5c5c0b9f7a6b8a20abd001e8ad01328ac5ff90b2, + 0x21ba1ee2990e2ba981f6e7e97f1aa879eda6e3e4a7f192be055d07d2332aac26, + 0x8923f775145f7243003eb5089160d2e0b4be6b68e77211d796e567b026e92db, + 0x2168e1158db076bd2c7503d8d78759b741f3d09e8c2863f1bbf77eb8a52f2bd5, + 0x2d91a6046ee638587087f34f8f3a45543e5a12e80db1462121d37f3d2f574ca4, + 0x19a362b36092714b50b86238ca35b3e9106efe2f1cf4a8f091a687cb71344a16, + 0x93ab3a1ec4ad5be6235fb805314d7e9f07ad5aafb214ceae7ebdcf81db72fd0, + 0x1e6f239f1cd9a373e4b8a283c86c7dd710a5aeb00a35338dabcd80e14079828e, + 0xf8b272d893f2288be54151a7c6e3e3e274b96a395616976d267ba31d59c0bac, + 0x22073c45cb975312538a8a8bed28c0a2858793e1e2a234d5fd8a6ebbf8098fad, + 0x5a2cdf46b89919b93bff18da44a4cf470a0de6b9bda0ed97d9ef3085678c9a2, + 0xb91b6af7828f5e23b06d2ec84a5acc0f6f670e64146bf82dba2cd09d8b9b160, + 0x26919b3ee33e46e95680cc8c216d561996b65915418a84d7b3d7bc0d29e3e56d, + 0x1615d651e47167b1ee9c70737c1376972ce475a1c66fd778ff5591b2e4e92017, + 0x1db6ba6e18012adf2f43482f224541dc5b5ffd5522f9336449fcfed6fdede339, + 0x157aee78ba392137b06bd8104872ec13558753788e044d38644249dde49b63f4, + 0x1bec3f9426534d61ef5ce8b40e3d9199d929a295c4b2e5768033fa7ba51f628f, + 0x1cc2614a3be0eef53905687b6d666d957c6f47b4f340d59106fc5add588b1272, + 0x17cc5ecfa4bcb4d4138bad0db4d25b8bdd921969465ce40c3783190855c0f9b6, + 0x2b71f219cdc5fca5c1ba861f3bcb51aa08fdfec6c8600ea26ea3f433090d9ec7, + 0x209098b02905832cc62767fa60e37a962c4cb7e51b23b6510389b56c510d3a61, + 0x22202b42235a0de23ef43301055066d26d87d0ac4ebfb8d4391b05fdcab190bc, + 0x27067a1a9cfa43df1faa7904359cebd06abc41ef694c89954ad076e296bc77f3, + 0x1dda2ec6fd0f92a515b4b9f0b80aa68260fd6570fe28c35acd8da5233c655c9e, + 0x20fcbe551e628d29e3625c948d92057dfb16a486be9fd88ffe308b886a7f3f5a, + 0x102b63b63b6594dba0d9502841aaa0bdf0d2aad08d25135f1090f0ed94cadf5c, + 0x2665d2b3b1f4711b362b28c1581c139aacf681f189d29cccde608c7f44dac4f7, + 0x2534e0a770bb00179e6f7621d96dab342ff960d361c91adb0f8faea486693df0, + 0x132de3965797959cbfaf61a239c5f09e1672d3b6387a1e34a53214e9d15c8201, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x1b6466ab641f7f30eb2dca03dedb89080833b2bce7b84b6a7b1eefd30677d2d8, + 0x690dec480f914c6f77ace87a47b0857ac7fdde73463e4b2445d4656c53653ee, + 0x65e0d65c2a3e1786c2bbfbf47102e427e9e31d2218112a86d821496a316d68b, + 0x2b5b1af812cfb77b30b821bdb2614c5f09aa73eefa9f6a48bf3eb146148b010c, + 0x260f7a81271cbfdc27a85f146221b30fa12e9ffba21d654a371bca4455a37bb4, + 0x2a2b6602a481c04475dacea41b360af3926cfcd4627112a8ed4192f213a823cd, + 0x11439386af5e26221df0905abda34142ce69f66151192d0143dbfddf3aeaaed8, + 0x230508e632c716e903e22a44c6002c2d39b1a0ee072bff9cd0901b3c4801e69e, + 0x23ce4e18ef472ed4e4aeb0dca528f14fb7301c6691d43e9632a65f1ec4e7bc7f, + 0x237dd8e70aa173bed421d4d488c4326af456322620483fe1a393066187a7cc08, + 0x24b0ab054d180e17971795754e027a756bc1f68ecf9cdc8b92b30b4af2c078d3, + 0xbaa7bef4cb2a2cbd1b33f9501ad22e365526a100273b8ef1a39152d779bdecf, + 0x1fb9b3569c3be925e480fd102a3432ceecdb59d346486b99d22284165df08262, + 0xed3418179e711b0a2d9bb44fdd0ff0c82741b531058111031cd123f508fc7a0, + 0x2e92aa6007576a4f815c645abb2e9ee10fe75baa5e13ab2a0b0aa700e084f071, + 0x2557fee713e3ed365d7fc7c6c07f113506d48dccb98510d84457b6d61c9a448f, + 0xeaee37321492b0595cc477585c9fe9573da00ad1619c7409ee76c625c11d447, + 0x1b9c9d4230433a193f315fab4f8cb8a7f4b0946f6241dbb2e858f3cec6c33f85, + 0x35b1d3045381d5053d0c329ef11458315d69335cd2371fecfefc8a2149a8583, + 0x2a0bf648759293e205b62ef858612f4e54cfa78dcf1fda84715cdde20acf4978, + 0x2d1f77f7bb34c7adcaac3e88bf34cc32e7aebb82e1dfec3491ed439c6b71c4a, + 0x63218d076827fb18e8fd4c14755443dcc3cbfa5bedb57a8aa1ed4b1a69b5261, + 0x2808b917c9417f47e1893c4a5b0053c64a054319988e721b42713d4abc351024, + 0x4c1b265648f11a5ed40c135675170ff486f6db120056d2b43e476bcda4e0876, + 0x1c9625a781c3530ecf4d532c0f1876e8281a454abdc914f34dec624dad8276c6, + 0xd9c2ef763966292a4585c0d7b4a1256c7b4687b8c19aefe0f2c5afdb8cb1093, + 0x11bacbb8c80b3caddc7be415c49d19c8207467eca352d2d65b3c950df899cf78, + 0x2f38ca64de487d59b0332f142c0cc9ee408f947e17bdf1ba7fe217cd50e3b088, + 0xa5b42f7d3ef308c007e91ad0b859f46582ca96b8a3fc12c6964b4e3ae230bc1, + 0xca6578515e51c2c7da9e898fa1541a6e93bea88ed529e5c1f411141884743cd, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x986957cb19cc10c36db88648feeeffc017bc7f344eca7e278313887c521b66e, + 0x2df451c36b1789c3b2a6719818a62d1d40597c6c2881225d9bcc95fd6d090f50, + 0x2bae223a93b08d3115a949252d906887fbbb2988c127c1e2668c55a00ef22483, + 0x5bebef52bb08431bbb9e92d219b4a0b2fe15e2f4346d0e837664369aefc1803, + 0x18842bff3ff8988d29a3737afc113f6bfb80c08d5a2cd06473baced406d3e2ad, + 0x2f78a8fabd2e97700ab4a2f2b5773ee348cbb2ee491bf33a5671c10e6326be6, + 0x8b3f1bcdba14103876b7f57f60d08ee3aaf9ea25f5495680a0c11876117feb5, + 0xe536221242a02f1c78e6c59133ed1768bb7c5805ad1a3e59066ad23dc8ad422, + 0x2d906eeeb9d7ed09f7fc504db42dfa79bdf74d094eab5d29fd91e70be78b472e, + 0x25ffc50d32b7badc1066a06268cdfe0a329957c10b2c448cfca1ff6ab6e0451, + 0xe77d99818d5d95b153667917050e800f778a07b2520e0cb2a8d9f3946a59bf3, + 0x2434b0943c80797cc13905ed7ee35a700a61bf601c7c3dfe20bd7fa3a62d0dd1, + 0x15f77d11fb4fc7c16e4a6670614d85b6eb833f0c96c9ef96dcc861bfbe2e1c8d, + 0x2e1db5f958cefae9e831f4d55d6c883847a2eb9f1b8ea404c6131e9cffcae8a4, + 0x205947544c2d5c9d1157bc26697d8e3c1949786e6210ab9deca2092dc55d4498, + 0xb9ba62195d29f54053e5fadce4e75e7323915fb2d047f61593c0cfe351c406, + 0x233eee9f5e744bce4d408b2c0fcd051285199f5e876fa3c6f6c99a289db64542, + 0x1818a3f0d1552f34caa7dc40defbb1ed62072bad77ff5a8221fe1bbc655e7dda, + 0xa8c36ed2f64ff121cceccda4d723afc80e17c1ed150d4d4afd9618a9be52fbd, + 0x2bbaffb37541a9f521ee370836ae3b6f0555f49b0569032f848e15e5d054054f, + 0x2dce53865aec616cfd8143aaff05c7bfbb728a48f2b81bc68eed629ffd6537f6, + 0x26a4a63df26dbff991a0fea4b9d00094354de33aea2f04f04312250deaf202dd, + 0x47dae867b6ada4550e18f2443c44281584a9b07e9104ab3790d65d0bfc2e15b, + 0x18672943f827e2833a8d9db988296aa281cac88816b11ea2ce6fc5ebff8566ee, + 0x1979353fb46d8cdf3b518ffe145af6a533b9ebfb990582fb36f31085546556a4, + 0x1b394c0b4ff11b67a1591f7d190c74f15bd83812ab056d7ba186998adfb5fbd2, + 0x2213fbfedeb46fb9bab30d5bbf854cd2945a30d1115a3e2cad6b771bf53a9c45, + 0x3045a6b98fe71341427e894e351402342da59067fc44b8a1e321de8b75b5384b, + 0x1e560b922f410efbc72ab3137afc2b4bb9d6d11e3d78ebc0c1ef970b8510b0db, + 0x793ace2e045d6dce7eb0c50bc654785c69eea92a5ff129ffe2b8224a4e66987, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x515c94018effb2fc24a7bb89b1a1055a274cce74cd1bb4fa3751331c55a830, + 0x228884947d2d1caacad64b4538521498e6a377f1f531c032a41e8c5999ce7fd5, + 0x2d7bb807c37a5dba31490c8996097552a930e55198a0c8f787cab498e4adf8c, + 0x15f5cb124b0a18bde04db081df667eb90d722fe38420c7a6a2340dd57823d4ef, + 0x2fdb6f2f83a138c09aaf67a5b7f4f2d21f9fb72def9246f8350b3d50fdcff090, + 0xdcf875be3c34cf38d62be56fe936e1f76d10f01c9acb657e4dfec02f98c84c, + 0x2f2bf29d6b7637980d02644b98030297e4ee87d51476bfe02e430700993b4e3, + 0x121dd63b185a3fbbf1e26721e1dc9207ba6ce83246856c780f1ff3f457925f1b, + 0x20e79bcfbc14855f607ffe7efdc0408b2366241ee80d388f58fc83f1140b4fc3, + 0x153dc31be4cd79fbc0f1757612c6316f994560d88ba2a0936aadabe71d3ab4fd, + 0x13804b12bdb77d63ef5f9807e60e1896a5212e1ce314a52f1e65cd6051545ae4, + 0xb6cecf0b015284998ff23c23a7c003629f8ee8f8e52d85ef6af13147fb8bb22, + 0x267f992fb1c5fd7a2adea64c4789617a205686c01f9743e29c3a36910902f83d, + 0x7c739e819b23013c6b2bba0db1f914573d0be98da778fcde3c44a82e8db6a76, + 0x15da652416fc44056205298e4837860a96e1accf42af4ddb4b6eec42fbd303a, + 0x1c33739471d1bd4fc613afe1e38b71ff3562acde29dc58bf6cabf73a192b372a, + 0xedf8c7db59823fb1f76cc67e0e3ebf8de8dd7cbe69ec468515a5f5511c8c1f5, + 0x8334b72ea2d0d35ab3dfac4f2696b0d980b65d6e0ec61fe2724c896bd3f517a, + 0xf4329ad37ea22a16517b9b1e6d38afdc75a8398df9b9a32aa2f8f2c3346e289, + 0x1f8d3e31cde1c2b3564ec9b8acb6d3dc56b946fd1ea3cc6067f04515fe80c352, + 0x94a21c0489acb58fc118cde1013f08105058d9e97d6a780ed30705c0e54a838, + 0x133b634d187f62fd2ef6d63daee9d3427ac1c9e215749786a2e17cbabda7dab4, + 0x18e1b03bf875c00f97c2d24bf7daca95935d8b176bc767f5659379937658f599, + 0x18242ad22da674a26206f354d85be06760137fa512cc7f30a5e38737854159a0, + 0x294268b5fe2beaa0c99688e9a9e4f7ceab6a87dd42bb950a25022247c790bb6b, + 0x1f13839b65eda77875e30eae082527d8b68a45094e0c63295a7130b78ee8ddf0, + 0x2baa1faf25902d89902124eda3986279278cc6007b1f7b0f193732e5527fc69e, + 0x265cf033142c6d433d701a040d8f9f35c15475a6c7ea5875d74927d37e3a6968, + 0x1c4eddd1412f02358286bf07dff4ab2e90e5adf051ff5adc369e93c3fb78cfe6, + 0x2fb924230c90e26ac6d37357a6df214f13c24c73725995873df37da56f7a3e77, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x19e494853af32baea08fcd358d25c37baa7b42e14a74e62773713083679489b1, + 0x24663e25937795d723aba2f413377e470b84418061ccbf2e7ab06545d4f69b15, + 0x28194cd3daa20ca6ae03a8dc12cc30cab003f2a1b784c9b64436a984862ad41a, + 0x3004d9469414f0a772c99f896e7f27c8d08abf0dc7e30feb91b51820e4591fc, + 0x4a90138ae63af6d831112c04dce879f943302f37a462f0c84b4f4b543737a2, + 0x16328fe8bc9d3c883accdd09cf2861ff33f072bc58cfe580113864913a5820b4, + 0x255342bb3760148dc048617882768a4d198230da53b4ddf87e5178ff4832f301, + 0xa494240f29dc89a98ec7fd0f8a70c3e82fc12d2894d92b36c5e472b51cec0c1, + 0x26d9764b65cb6775899164e5bb179aeafcaa7c262861bf582c5d6419f86946da, + 0xdc64acc51842f225a439b650e5eb3266d2ab80e7ac705ccad646770a338ea77, + 0x42d122c394166798b946f03da9b3e06fd5ba1fdbba49d3cfc9ece8244426044, + 0x20715b9135e15fd039a728fe347d6825e7cbadca0c792e2755921003b7cf9cee, + 0xb8465af4ffc725e0d9d50079c16f1a5a7d8df1fc7067728535b10e19cc70e32, + 0x1b3fe32fdaf4a4c9b5186604fb4746695561720c1a7886751635b2a416b4e37f, + 0x1ae2fdac7b7d0b3c4739dd9eb27377b3bad124823940e12d0bcb1177c96e0788, + 0x1e6b8f955ed56d144d1650f250bb0f8a8da2b631d38d75e6bca34a687eb96a5e, + 0x262dc534f682c8f874d877df14acf8ed7dc65a6e42198570d15f49520745c708, + 0xf9a4f0271d5c6aa02c42053a8d2b1fd8179a35cadd4f16299cc0037b0b16d6c, + 0x6f078c71788acce7f48fcd7271d85077c50ffa7a82ff67d81a10ddaf70d9301, + 0x2416d74e36b42dd5519bd3a03935b57120b33c05265a40cc15fa0b36e695185d, + 0x19efbe964add94b60109cf8e6795b8afb31ece021bd1e99e06a39b868ba5da18, + 0x217825dcb0fb4a2debd0856679d5f138bc28083b0583bcdd2fedd8226d71ea20, + 0x29ed9e1b8a1e7d0c5dc4e51ea5f277614970693b65758673625a6b81e0ea6305, + 0x8e7139bcf5e35d8c2826234a00c56696400cff2b012a94a6eddd3d1ea94e4bf, + 0x23b45cb4566041748ed409f32aaf3b7d59ec85f8ad75bdf008a733d500a24f7, + 0x59e1a9cc4208e8f4adc17e95a8dd0a0e0824aa4671a24075116ef1cd29ab280, + 0x1084b6a7bdcc2947835bb7f017c5fa4a018dae7a14db23c1f44e821a65434e3, + 0xae92ed115475902606d7f3e699d95659acb152108c586a30a912750ed18b0d2, + 0x11540ba858d368852b75bd5e3d31e289a182f3068ed6c2654ed4c92e9d4a9a12, + 0x219ad9e087618d15eae3780c3b2fbbbcb68667bbedb9d51490a04e4a2986b734, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x1af405bd496121de8bf68db182c52f8dcd863e5e9d0d07c332702c652f103155, + 0xfb5adb4f2ddee2c786bbd630e10b6af21566e13887264d2627e965b8a7657c0, + 0x5735d0a20981c3443c26321ce6aaeb22867087fb482f3fc52564231fe1fbfa1, + 0xd5f25ea7cd06c95915cabc11f61a2a640b5109771238b53526673bf353d8efa, + 0x276d9d19b50cc160870806a1622acf7cf1df7a5c0afeec2dd77a0962acf14cb1, + 0x2d52da76429ebef4234a94a2cf6a41afd471193888b6fdf668885a0c578d3c03, + 0x24f84ab4d1acc7cc1b4f842e502865a26591447b8bf24439782e17e032b6f535, + 0x21069f3feb18a6d2025501270c070b1bae6035caaa50bc68b6b402a909dca262, + 0x1430dd6ac598deab9432e5227ff5fa9da4994f08ea28a781f9fdae630aef746, + 0x6fc0f56ea9867dcc10385217771bae7c1901deb59d89d694a14fdad07ef7456, + 0x2ae95e39f51c7935a52f31d1e92c2fa1e2a2a43ecfff3849368a226bdf1067cc, + 0x2b53d9abe894c47db9a2e81ddc1ea0cfeea5ca257e8c0ae61d4c9db5d8a918f2, + 0x18dd0925e43f821fb7c3c9a72e5d409c13e5c42f35b1268e9b36685ab6c60a84, + 0xff74b6d96a8d00bb97508280e98c10a1eff834b46b15f474b9f4fe50174233a, + 0x18bfa382970f3598061f30c5c18b3e71105a5145ca3e6dd21f779395872e3616, + 0x1dee9f00f2b7548ffa9cc5a39edace63c461c528a7bba8a17f59b7df6e247b99, + 0x12c5810e9946497e1b6f928182d8511851683ecf234de99c649bcb3dbb8f1e76, + 0xe5953881e72ff398e4c34b50c3d66fd073fe79073f7ebd593fefdcc7bc4fe32, + 0xd25061d2528dd5351e4e8367c96fe57446429956594b2f752783f06251e1ddb, + 0xcd02124b62741431f4baa64fd8a759db1fe86465b36f26e7e91ada1a370e031, + 0x2d524e2c0a167d163be6863fb345539da3a8fceb3db496b765ea2fd7c4fedfaf, + 0x9f6ef3fd9b8eb4dd5cf6393f681db544e7339f6a129f9bf8e380041e0a43cd2, + 0x28bf2b88d392ba9823e2db09d12cda5a103b6e2f581a9a3abb8ce25c5d93476c, + 0x209e08cbdf5562b051300a64f3cba7d75c25e5032a2cd5331e6cc386db38c373, + 0xe18e80edd86792ddd92cee432ee33b15fc5102cde0ace9f8f7c9fa0663d51c5, + 0x27bd8795292bc68b6a8e0ff451cef39f92f7af2d407c1cfcf60297100a9c4841, + 0x87d2427a36da27e525bb1956015bb2e0811c037a0cc272f230cc4f18a756a13, + 0x5e017f8cba3d41aff70fd421eddd63f464254d65c086e7f5f07981790ffffd9, + 0x2eacb959ae5429d219c66b722feea009060a093d33df0cdf225553a0dfc8e7c8, + 0x27a8c07ea74055992c66e0003c03b07c090d30d45b940d303e51212a974f05b1, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x25b72e38946d8c146ee356367981e74d001803430d4ae023d08a9c68ce8fd58f, + 0x29d3d7fe8af458f8f444fc49c4cbb3fde970d6edf8ebd7bd3d067d45994075ed, + 0xdc25ac6f52dfc613dae0197322a98c7700cf04dd9d1627c90076bf2384b32d1, + 0xaf71c0bd1542973007bff10dfac94ee18f5da9221d3d6fbe04078971e3b80c0, + 0x1406d8cf97827b7d25ce71e62d17eff80c493bb0e1f2a6b951723431dde17c18, + 0xa177d75332f2aad209c9eef8004879afd6acd5ce56db116f834053ab51296cd, + 0x1e42feea60f7d4987938dd58bc9b53d4b5ae4f8ee14b2ad58d723c7c86c130d2, + 0x2c5921fa4ccd767fd2533f308d1c18c63cfdc3f7d8e10b217fccbeee2aca0ec7, + 0xac4e3d803a6c602ba6fc373c31988c294649478134d462772dbb91e40c56595, + 0x68fb1f094571ace723b59d1a0595cdbd2631d93806a5f5c758ce986289ecd0, + 0xf5a472661affd8730cefc698d6688fbca3ba07b12637beb8f0722f2f5e8c8d, + 0x2ed5af998e49f3d9c92a5badae4eb43a516b1ad840cc01d11c8a441786316c60, + 0x9929a608a5256575d7c287db82aacdf5381830b9e18b23ebdfa2adcfb46dbd9, + 0x26639e520710e998ed40fb1369c7cb039bdbe0e2e5778055072c8a5466ff9baf, + 0x2b3225c35a88f757d4c773363b825191df51b0e1cd4082541d382aff5f7b3f3b, + 0x1c1a368cc023f9aee70e3e53341a06e8095022c5413ff1de4286363b4e1b99b, + 0x1b39049a6f7088294202da65d65bb190d44745fb93f4073a00d473d38fc37392, + 0x2b966bc8a897d76c04f943c5a7aef551f3c6040d0586eebe1f4989a0248ad79f, + 0x67a2085143ae9a245bc66bd3374eea946135f565cc0efdb6358a3ccde5b6c6a, + 0x27c3ead3d76039b10f3bfe13f32df2823fb8ca146d9aa6b14d8cea182aa76bbc, + 0x13ae8e66bda5f40ad3ce0e83305176d5e73b03f2950d5dd78b1087651446f60, + 0x267e55ad34a8788497998b79193846c2822a266e8f60799978e66ffbe27018b2, + 0x1a964c5c4550c29516171a8a8766faa7159a1376a836d29809d5e901a584a686, + 0x216cce9e5b6062cd063ae93e53efdae64cf5479ae01d7549f8cc7e67a600d184, + 0x175109dd08b4de441ba589607706769fc506fdeddcf56ad57d0ec008fc3816c4, + 0x202ed46ac0e68827ffbab076167ceecbc7a9614234fd6621c6eeeb7283e439d0, + 0x2d265e49f35dc88b63abad32d14302d3555c221ae8eff1d3399a66959ee87e6, + 0x593f84a55c9e3af185e6e8e689981a9fbe1ab6282f393bf4ac2b77be21d91d6, + 0x2fc4427295d575a8fa93101a1b916e123f2652e7e9e94c364c4abae0a424334f, + 0xfd26a5a97c3cbdbec343e616c0d93f25d7c5eb827748114e4da61c017e25478, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x163e039587ae8bed242103f972c58d7b3570846f3a9ed3b6f65ca9935e0599e6, + 0x17b8c9347540a0cf46955fe40c29fe36680969a074eb4e1b7c40ce0c543df4ff, + 0x28939f23d63d09adbd1dd196dfd73eb65ffe2fba07a79e2049a8453c7caded55, + 0x22f4246a101673a3d58ce953a3740bf807f25fed08cebf1c124565310b10caa1, + 0x1335c6f50549b22023d2a973807c510d8c1b7e228e8629c35b7ea3a701ed0277, + 0x5cc88a2ab03f9f720d841583cc8387313503e804be95d3311a64d0cc3cce9c6, + 0x2000d4715746fa36d8abf22861719b23aaecfcdadcbe71d567b1bece77601904, + 0x3c2c00765201729fef4cb1ae8cef326a7de4f3fd5803521e715257f8b392e80, + 0xc5affc61d51001d7b0d8aaa6f99d44cc683af806ea1ea1d241ce56f386b5462, + 0x153a431981ad712ae13b7530797e5b2ab77c125bcf530880ac8566ad3a5ac417, + 0xd2047081d9a8fff7773d8011bbc0b61a6057fa6f9a1627a3cf321fdd666e8da, + 0x2eadef1fd011162138dfb0e0200683a3bc27e1ad12dbfb2b94b32203186e591a, + 0x21a05d0434000fb05886112242958d74bae54ed2b6f37ece00b0293322e53253, + 0x19732c8f836170ba403a0d379561bc5aa6eaecf21c4fb9fc26cd44bdeba475ea, + 0xff30532e9f7305c94c298848cf0d54dba01341a79da4db0f2a975c2e4380372, + 0x2afe8d3ea06405c8fcdab50d6d6e55b6faa676cd36e6acb87b3836581b06b46, + 0x2fd228d6e4c1a1acaeafc4597d69fa30e56282d8f11d4cbd09c360dccf546f80, + 0xc203a0ea25b7f9b4066daccb2928dcfb4d1cc0cd2d14671fab5a7928603c8, + 0x17ecb26056f6708cfa3aeb6274c3352d6bae402e4d2414526e4c2a2bc9b8e0b0, + 0x2b5745b27a5ba71c7afe5d1bf955c578d1ce3c915f4d30974f225f6f7bad7c8d, + 0x1a6eb6c48b529c6a0a166e53fa399fb68e8b414869b13ea713c1a0cab8480c23, + 0xac89d6b741aee6c180408d6006f130ed945185ee9a213dfe3c8baa49330ee36, + 0x86eca38e64cdf2e252134d79160d437d92537324cab25cd8698c5e92e94632f, + 0x2bbe2bc0467c7a4d9d1bf2157cd5cc3ee50f10166a0d442c706d9691ee60b8b0, + 0x22c4c3d27515f300d879e8bb85b0447341cb7a816d6fda516cdcf31386998d75, + 0x23e31259e8fdc69a23a603b4e5b47a90390966aafbb1f4eaf02f783219acd1b, + 0x20c0c0f899d24401bf7084d6d0be314dbb3ec267f87a2e8d3769a1f64b469a81, + 0x2daba47175558a5930490cadff1f3deaf100589f676649a3a2fb1dbd9bcfd3c0, + 0x1e759b766aa310dc7aba2245608ecaaf4fb90f509cdab694155b47e768af3417, + 0x135aafeb5b230e030273e42ba704da43085d0ef96408ea8323e7be8b546643c, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x2ca2e70a3d8145f60160984452b26220f303eaf6bf539c8055fe2ab037a64883, + 0xb25881ede6015137cdf99b53a8591aa6e0c042a5a8c6a9e6fbcd11a37023cf3, + 0x258b19d1bac9e53c3c5cc4c59c87543b0e9b33a5e631fdda56298997a5781a7a, + 0xd6e7177ca87aa3326c9420369803583d1a1d8d96adc6acc33a3e58cdd3587d9, + 0x23cbecf6d9fd7bdc4c426035908bdeef9c9c7a801667ff2b62e8ead282bbcab1, + 0x2841e2ca97eb7de3733f8a6d3299c6038e8b17f9d133ed12efb4dc6d923d804f, + 0x2bf228ab9b7490f4b0ce01cbf31bed2ee4a6ddc6d5a00a608ef1c7ebcb5a203a, + 0x22eb1fde7a1c175f0c152d5f7f85045961d2b01397db24d9de95ff0507627f0e, + 0x100932572c12a0bd1f2ee8c6b0af317dc5191c3bc2a177eee791d6e539e5b237, + 0x27e881557b4ec0f1128ef0069c22a6e5ce4fe48f7bc9d9789c48d6948bc24c85, + 0x25862853fd1b44c6aa26a414ab4f295aaae0fe4457e0fa0c4bc5dc9fc2972246, + 0x3947c7ab7d714f1f8d4503829e2edcd06baa8ba87d5b86354bd7254b841ed64, + 0x2676b506a75643609e6b0dd8986b8865a93000fc38eeb1f6cf3b026d6191ed47, + 0x1f45ca8395b4868c3b68b11911f52425202fcd2108aaba02230dddca7b36546e, + 0x1b5fe89e54f508b5188c8487302834d08095b14c1e0938aa82f9365ca3b2b44e, + 0x25826f9ae3904e80f7ded17b954c8989a04a060326ca40371dfa204e02b05eb4, + 0x2b5324e42bec45328632622c82644bde941e015946d2d9219dd0b805dbab5c26, + 0x25e011cab809208c9447ce75dbf6c90f76c6d50640829b861c2392271a51ee91, + 0x58ffecff608099006fd59ff7d75f03a528613b3633d1dde3fcb5d6f239a648c, + 0x26f052daeaab76f2ca8e18584b8586ae9a8f591a8b97a673d82d50be943aa00f, + 0x15d305bc6e3138c409925caf3968367850c6eed0384e46009d38bae5df81fcc9, + 0x16f0c3de9b8a76ff18370cc489da46a9bd962742fcbb0a0ab0aee9d12c3c5fb2, + 0x137a4fc5e63da4a366b6edd41e255fc4baa73ba9662ab7d2b69e0b7d4986b562, + 0x25a59d3b46f5c8b7a763518797faf55cc4773967c1772b01c7c23f186a75178, + 0x13df1d61814fda2e0d26ca861adbfe9b6a92c05bc3afc953cfe008d176be2c30, + 0x15b63fe5843c661cb40dd42feb664dbadbb27866e119a28f9ed8d35b537870b0, + 0x23352a3a3bae8c2e34359d75bcc9a5d870b69555ddf57948caaf074538044a80, + 0x2d223c52d6fbcb0e82e9fef6b9bd7384a2b789c4d9c273ebb35b4efe8e51e75f, + 0x1f208f14c51b48c7776faea01878bce6507182ea071505581658173217492863, + 0x194984a1a5106ddcb1bce1299b1b043edaf26b85c4afd80cb6785cc5c83b346f, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x28bdf0652d4964a6e9ea2faa6ce2d823253364d311762578721f87736aaad803, + 0x1183224ea82a68db5fdf6a21052477c8c8ff500e97b8cedc09427cbc02d57e6f, + 0xc61d22c912bef8507c6b08cbd36f7cb7979f3b56b36549613794515eb4e02d9, + 0x2ee8c7f8684dedbb1c177fa9f2574a20cc4ff3c10562877bcfb0d53c90649b77, + 0xf56193999816a0f4b15e38974273b5c5863422b93da9e94f47c5f10351d4705, + 0x90b70ecafba579d37d6d211358523ed992e26d5a7752598bbb68b637a59295, + 0x2de97266af0468dc5a587231f1b1e3aa2cdd4d1d7208205be90826491f263752, + 0x198553fff8aa46adc9af3b38d6c01cc00f1a6594ed0e1a8b8f370965f8a89669, + 0x192b3300ef2574b4a7053c24d7dbdea81c04da6f3c803269ee85c22c110782b0, + 0x1f4c7a76da30fd0e604d14833d0ceae25eaadfcf937d4ba5a6bd7507b70fcef3, + 0x11194b46ea91741f761662d56b64c9d127f2bf36142f681bca579af2e8856cc6, + 0x13233cba082bb1579428bd4a19847aef4c5031956805f6e2522e00dc9a92a087, + 0x6fc54c9a27cabca0bd75d53cefe2992bf4b744ee1f1e0cf7c254492e584886e, + 0x14870645f35e85921f579a47d013cf8812201a133bd14b6f5604f77c10ba8ba, + 0x246344f1ccee4dab0e0409bc96fbb618937e6bc629d9b1bb83a669055ee9e210, + 0x1e1c72c73d9444d6bc46a7834c66426ce4bb91446e804909153e6bf86511e628, + 0x662c514923e41038cfd078fee4bdbe72c8f6e90e5a3cfa51082a1a4f7523754, + 0x25c7e06ac250334f38bd664db0bba786d54e9d40e7c104b95989232ba0776db0, + 0x1c63774bb6aa72c366712c86792d85668f833b7af35eb91f36176de375fb2522, + 0xeef372e915f3263f31e2c3c4d214b4c9aea86fda813ddbe1cb15441881ade05, + 0x29db12448c6eb73422accef5a2a3794c7f372c283f37b2b194cbcf09b23b480e, + 0x161b72d834fdd269571186b3847084d251f4765a5b9ffaf77fe720319e0dc7c1, + 0x2434332138c93a69feb06521af0ef32c08b680bb50eb61398e377447ded461c2, + 0x140867fa61caa3dcea10be9b46b76871d983e8a7952e3d1f71aab2f531a85714, + 0x1e3877e58d7f25a988f737f229650cdd345c308a37c66366683771f9e249acd0, + 0x2e00f80aa5ba054560070a3f21c0bd37e311ce8060a7cc1c64650560c9715088, + 0x9673ea23dba537a4a0f6dd66a13df85d8887dc3431666a86730becd72f04fc4, + 0x2a05b10d1faf68ab7e607388f7c9b3de54bc151f0b2da02702e471eb5b786a50, + 0x2e8fb8bd00af6741fe18ee679ee378e8602ce8bbc429ca9986d016e17b2fb22e, + 0x23cf3f042a56c7d2da94772521a21ae6bcb3fd0433f8778cbf68fe1c365c8c08, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0xd4d295bd6bcb6716dd82907d89b8809a8af69859728773689e073bda41c709b, + 0x14f8df38aa9592d59519054d8f0ac2c79b6a1303905a9770731a3a7081b2bcda, + 0x27ca9533e2a56a644d35c53fa9cb66187a7c0ef7322168932c330724edbfbd0f, + 0x1acea5282de35d35337503c8c8a221fe22bc24d39164850efa9a7acdf1377f07, + 0xdde135f69d5ee7253d1cfffdf878b3ea75ca2c56b15907329147969fb120d46, + 0x8565cb565140d42d33d5b907a0e23f7af7daf91ea5aff759fd8ca916579ce25, + 0x19343a528505b6b303ed193e33810a005abe738057cb00f34c9a3329ca808b, + 0x9cd47fc8ac46b3e49d737eb4714d522ce235c1b0feffada0852d8173d4b080a, + 0x2b87d075e7fab29849291a7700eae8317cb01676a36c0d2c138257b852732a2f, + 0x106694e160db35b2d35998e4ebbd1769c69c448afd1ce6aaa8e1bc1ce53dbf4c, + 0x163d91a57022a4734ea17ab01fb85d94622acff6582dcf7e4b46dd0a5d72d823, + 0x2b8cbbe66ed1e1d9c5a1361ef0a80599de75573c62d6e3aa718ba233e2594408, + 0x305e4c4a93d931f927f0a213cebe1a5a3b258ec726fc912ca59590febd9b6020, + 0x26d0c3492063959cd8c3dc0e5c791356b19b9bc6e39b4da13a4d2a612e56356e, + 0x2076ca2026d04b98f821b9bd52d64fab129526fc2e626fafcc92d0d2e23a33bd, + 0xd89c4483e40c415d266d3c7f2ff6d1d66412132770be71bcf1178849502d231, + 0x13671ddf2f49e97410f41ead0e1a80564d862771c7543664bd20762324fafdbc, + 0x19694e401d2bd6b6ca4d8929129a85c9e8834e40fd1f6089da9bd69f66f840a1, + 0x1a801c574279164c937f3798748bf115f09f56044461771cdfd67c9606f1a170, + 0x7359e7661550f4af1bfd7620cedab2b030fb9645b06945a8c166a617423e588, + 0xdc31ce178e60f8dd171002e2e5849759d9caefc7dc7a1fc551b677b410c4274, + 0x3b7d51b2b8b3390923b28d0f1e181c8378bfd0910f03835a1edce3ded58ffa3, + 0x20feaca74003f750c7d517aca7f2c181745a7d26a47051da7209fd1b3ba67aed, + 0x7c71a9d84dc8d9b2d223b3302e1804f6d6cde6702ebe991c5c976a4aab0971a, + 0x1ff2e7a7045e92d955d0b3a679eb1168aaf735a7cffec5e90fd0e47fc946ee3b, + 0x1ccad4ad13abfe58d0a69ea967e9477f20630d928dc93970033796ca8049edd2, + 0x1d2277a4c8ac3e7ae945f05461d7a72caeedb456f30c1e12911c8e3dcc3a66b2, + 0x2ec2d28dcd7e75e100c13ef572e9e270d251a774f44b7c59df767ca50fe10434, + 0x2ea447c02e059970eb92d1fd14b1ecb189dd900b281e67d68b3e742523c6a801, + 0x2b4adec5ee014b305fdb460cdb1ae30796202ec0fe11d13c23dfd65703f0434f, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x1784bd17cb0965878549fc4b0e1b40bea37668f94d8da890caa7bd27d22cb2fd, + 0x149f1d9787366b84b3fc40ed430e96b646eb16901093590e7b68ba3601c364ef, + 0xe1161f13b91ea8432e12df3ab58706410da5e6a10ad20b1f62d1c34c09cdfa9, + 0x7e6d996431e217b60bc4d3e74aa3c337263f1183c92cc73807d19e59c4e6804, + 0x2086834b2a03db22c71e71dcbc89688aa02cc362496e4992be9845f57e8bee9f, + 0x1a593864d072783fe6e1ef8ac83665aaadd593b63b3dd3d4919237bf5b2c7106, + 0x1570ec833fe8f21ec48539c6ae273c34cae3bfee0acc5578c96cde92b493680, + 0x13b62a93db33b6f0e9114d3f2f19c083b397a193f6ef0f5b087f2079c2581a9b, + 0x2ab8bd24dd963ee466e2e0c3380cc88a4f82397cf9f7dada2d80ad5ea21db875, + 0xcedea082a17bcba725bc9633d2e5e67fcd43650e22b22df9aac3037daeef8e4, + 0x5df20d895beb2374b5ed6d81ed5494a6ae0e9c3bc184d7861bffbe7243b616a, + 0x1ab529db00143d7038a6e01e23d0e9d56ce89bd34002727061c8e56944e4003f, + 0x2548c562cab2de540520c050393f949e10bb8d9ed4c3fc387e21e454f1ac83cc, + 0x29042d35cc97955a80eb09f15a15b66f0c4193a58193a080662b6a5e79e68051, + 0x685b96bc1e8d70b1a7b70216b5c74a4e5db315dc36faa59eaa39f2e0494ac08, + 0x2ddbbc66fe69dd188a2e9c306cf6f7de9faa106756186b82f3fb440dd0b912a6, + 0x18c70260e52a67ab417aeea60b5d3f88eaeea2508829ae7ea3c063443cc0945b, + 0xfd423845f9f9970561e33fb0f913821e1e3180dbd45815a9238ad515543a634, + 0x6715e87f1daa773cab6957c11605b0c6ff2ee937057373dafdc2f284d95b1a9, + 0x20af32b63bd2e6aa4adb6d0f474ccd105b78a2dbb269dfbfcd615d4ccda0666a, + 0xa4333899e37c411cb633251ea98d8858dd944f73c4378b66fdfa5904ef8d9c2, + 0x92b057185e62fb11b22b5f3583d1943d561f827c54936cf20d7106b9416f3dd, + 0x1eda5120d5fdf5f2cfc9e303a45a4ac8710bdc7a9c28b5e801eb248f60ae08f6, + 0x1282a8b79cc5039edc8852ec1bbd5835f3b8004ccbc9a669f88a331e966db3d1, + 0x2335e0bc60883b59b1390d2b3652ed0bef230324e7fdab725a5d4743d5fff8c2, + 0x2e23e4d93a4b72ad0551b740879ffb0da4ee65bdc1ab71f8207d2d9da0f26d01, + 0x1b06fee7ffca419618d3bb646a203316838a684e7c878024bc058645fad01e55, + 0x66ddb3bad4a4b1374fed6b3a88b1bdc812ddf9a6bea1b028735dcf90a77bdbc, + 0x280b71aedbbd3761124fe6fad719c6930ce0ef6695938cce777ab77ea3536637, + 0x21d130fa258f6e1fe201071b3d0f643832f4aad07a3a983ea00c26890b546e5b, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x305f7337dfc2c6591e5b3d53a4783555e1ea91efc44648529448fa3e463333eb, + 0x1d69e17e5678ac53a1c046ed0326666c84b909b85e5aa9e34e516d26ab655573, + 0x1f5d0bf5a9c458a3c9c9bbe3fe48211a1127a176d4f54547aaf34589bf9128c2, + 0x2385bad332ae963b60ae73862cf86c5f723dfd37e56b05918373912d8f9754ad, + 0xd68dbe874d206f45efd8724adfd9b10999a7da1226c394c4e7959269a17a79c, + 0x27f8bff9822ba76b43b54939686caef37cac685d60efd3bb87b468808b480c1e, + 0xf2cbf2fed229b81bf91c08a642730c9633136dcf1e68907c192e34464560b24, + 0x27e6783451cd61e229f062e38e360d9d022cc244222ff2128d4901de0c5b3c1b, + 0xb0bf852c95f2476ab5280b94660b1d9d2cf5439c34d7b6a928d596b13555f32, + 0x2b543c7e1d2f84fac470489446df876c7f64956d82c8897e268cc4e2af130a2c, + 0x4367a2851e9b84ece7172ed126f7cfb63d5fb445ea19ef5a31a67517afd2fce, + 0x1dc8a2abfce437021fed52e83b1e6708a20e07d84206e4c6038bb9ff36b325a0, + 0xb217141d35c2aadebbad8d9a426b52df23d7db7c3c72f0914963046e120d5b, + 0x10682c3505cec77ba65f4af68963f3310562527b2bf1c812c04a2eff94d33376, + 0x2f3fa61cf4696622abc02bd664be628da8ff5f9b49d93db65af12a0ec0d25593, + 0x3798c88da7c1c70322f72888f6fd783585ad279f4cc06029f3bb23f3c32fd3a, + 0x154b3f2f885e3d61fa5c27875fc9b03509b9f36a18981b13e1aff4d29b7d23af, + 0x45e3caacff06ee391f46ae43cf78a2ba1e2134de0405120228cbad0694d2fdd, + 0x21a443268cf1db0a1edc3f7c366de6cbc690e1939658278de9679814a5ad4a30, + 0xfa574382520b0170ac21d000d9ab5d2523b5f86758226d49bab96fc1ad9c59b, + 0x1b8f07226473c28fc3cf78ffe2f5fb3967b6beeed42866814c648f5d4adf5fb6, + 0xdc48483de7d0df83232e5a41cc287618b7957ad2fa3db03556429286ed6a2d8, + 0x2327d3dacc8f80fa05d075b7f9b8544356c04f4e600f53d8d4d2d0f147590eef, + 0x16a6266bd6ed429272c69aac579c9032d9be7e86973b578f27d5cb8d2f6045da, + 0x9eb4e66285aa7cbb62217465768138d73953baf7eb68bcad15b749419255e25, + 0x15f3a6b27c8a2ce27e931cb599a0bbaf6042cc6f8d411d2daf1969c02c67f5e1, + 0x2727c9236d43b41a34c74c52420674daadfafc76eb313b17fcae0e77ccae7bfa, + 0x149bd00eb1da39e22ab0d8dc78d7abff54bd9c13ba38a6a531f696cc993a3f96, + 0x13ebcf06a5c9485e1767a124c3e035223eac6be5816041fa077d5cc6fcd10228, + 0x22aec7f8873c75702e0c55c1b1529b1290831cb4df73c3ae6441da67c21e8169, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x1d45f9fa11307f6de88e220e633519a3ff18d9dd8071a39b38ee29d5910fac47, + 0x215ff3e875d70ad4b7aa08800aebf47f83fdd05a246186a8ec09f674ef5aa160, + 0x1552de26acf195af643fa2625cbd3e1723284c2cfd05bfbc23495a0cf88aa369, + 0x1f9836a1eabee49b2d2e6cb1f1f666753813f5201323d302faae128f08e45168, + 0x1f8cf510bcd58b2fe258f3f812dabf08a301a71ed710d4647cd60fdf5beb779b, + 0x2c446f645eb661152de44865a3ac149bc20a76447616094884c9b6515ed45674, + 0x50a3718e48640cb644bb787fc184aa61f4e44044dc0f3f3006ceba81b8dcaae, + 0xb370b71f98dc10706712c7f348474fefe5dd772f6786fe96cce94999cb09fb7, + 0x287473939b5c47568612b150cdb25b30808c058b4b5a3633c03af83f7a7e26f2, + 0x1f5ec7598f6da577826ac5afcd6ec3721b963562999125d9d356eac51d0d513c, + 0xa9850058f74f3196f58585e6fc80ce0405dc510ea89e33eb1a9c87ff91e58b, + 0x22227d59d1ffc328aee2ff956f45c3b6adbeb782538809edbb6a1e70f262a23, + 0xac7b869caf4e71585f9f567e94b1ee6e0d802ed6af49d30b24d41b1c784e448, + 0x6d671ea1fc8bcd0d824e101c3732425de5a4435fae1bcfd1c85f501ca205d43, + 0x6cff4c2918d4ce74f4ebde86e5951ad143b09a951d136618cacc9cb40dd5799, + 0x2d9f0ee4ed51e979a0f1a582077e8e5f6669f89d79225a7da2687446184347aa, + 0x12dc6ad0e0daf28768e85b026179300312feb26584b2a4b50f830499e14f5e06, + 0x2f94df6b211d8a8a514facf931d71a3f23e3d9a8a51a11d29c0221fc9873d756, + 0x29ee741287f545a19cd02af760d56286c27ab5d4122c001fc297d43db2bd030, + 0x7d43ba525c44a894d64b500aca3b68f2e3c2577927390f60181ed36c0df68f, + 0x252866633477b3aaa0f9fda731b4dfa0d78905ab39c177ae1f4f76da5d9e5547, + 0x2308ec0db73437f83200db8f914733431ebe5149e61cf3afe3e67304c8fa8d44, + 0x517e4ee288992d99e59515e91c5be6957e839b8ba8c9c7430fd31eac44c56a2, + 0x2ab15d8887615c04e22f1e988b9d8450cddc2cfaf2b582bdb006204a50e596cf, + 0x116e33a713748ad93004391adb07d5ca64962c8af2a8835e50eb7e1b6662a557, + 0x68150e1248e7ae44ef5619127e8cc28616d7277091afb4c209ddd504923f50f, + 0x1e9e3d2964594dd5bc87a93e4bb67e6ad71b037049f90493165954fcd86a1e4e, + 0x1751f2e99cf8cf643a5ec6b3cbc81def5aa8679977cbd2779f34f476f9496911, + 0x248ef2921bdf968c74dbadcae0db56cb022ca98b983628d7110c724cdae048d6, + 0x2fb6d1bd57da1cc3610b201535bd42a2cd405ecb52b28c215237581257354352, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0xce40ef4d37ae58008a4d1b02e78aa4fec563e8840cc28fd1af61144986866fd, + 0x1f94afec8fa62f53e4bb20f756a08236e40e98a346afea85c78280f0ea33e337, + 0xf2164352021aaa641a7176ca76674a465b3b728d8af12c7b2a5f9339d6f5e47, + 0x1b86c9a7cb8287520b3943987397e8c7a742f3059fe12bea664989ae08d00e5b, + 0x11e4db5228177f30bb2a2f96098eaa7ea941229180bed1869a0d0be04cc60b0e, + 0x6378bcef2ce91bf24365b51a0970028dda29ebd7da3054a8440207c15eda844, + 0x192ef0949ebb3224247a83c74eba36e47252f4dd8c3f20eedaa39484ea78ca65, + 0x21c1cae79f5fa8283d7a8c2acb29a4f46a76b8b3f7d51fd93941bdf32d38fed8, + 0xfc260daea1f470febcdeb84cc58f03b1100ffe23ab52e88a7832c18b1b13213, + 0x1f6f7bc07589916ebe3fee5025672ad9af9a3ab798fd01c6c2228ecca20c395e, + 0x197e205923ec11dafeeb697b87ad973ba4a85d9d9d3817c364c3609ff78c18dc, + 0x2935c393a884a244b08aa314b2d261c999959d415d00857cd883277d439fc00a, + 0x2c639ac544a75088ec7aee01a854471f7b6538d83fc1c7541d9018c0a87b1916, + 0x25b2c9c2f413762e843c10e546ced0572e1a30d1a9b2c5c781d24de864ef4973, + 0x1d28735cd6da088ff72fe8cd4eadb8bc28268e15a9d754a5eede53d3513e0317, + 0x205c309b41e6c8bf2fea4671a502abcebbf0aa33c807369adb9869c0d0b1661b, + 0x2e8e8dbf8f9ab3be24fb4e8b95c2188103a384cdbcc2b65fc5b931a730416e0e, + 0x20e1291175551be80f70fa6ce6e111ad5403d1765c4bf47f611103fda64b098e, + 0xba9120de0cb289db8a951b5d348853a839af34529c972296703db5c217054dd, + 0x2898c38f27c64311d90346dfaaf3554ff6b104e56124b35af7cb322402264620, + 0x286e3762e815adfe1ce18e59928e04beb43dbdc6d4d1eb52b5741326da3c688e, + 0x2d316495c1c92a8ab5fc456dd8e7b1ea97f5cb70e90624d1af3e4bbc18cb75ef, + 0xdeb856e2bb0ca11bf197de3dbe8e8cc5dbaac998dcc275cab91acf7af3ff347, + 0x247b87e0ea690afabb1beeccffc7c12fb20f31484d684b97302ee67f588d1eed, + 0x2003afe0fe29cee7641b7f41a31c8a2fc27bdd619f85a8fe53a4536884d684f9, + 0x25d9c2e2d66052c7d5cf3d56c8865d939cba18e0bfac725dc04f468837112253, + 0x1a711ba1a3eece6595c4ee4dee4ab3e865dd77e6b58797c3677e1f494d13144, + 0x7c74f66ff199856f077f29b06acc03305bb03d7a1beae045e199b9596ac9a31, + 0x1a4d513506c6ae66d0e1a077b9e9604ad4359a6cba7738d9721db0ba826fe704, + 0x172f82b5caa7f65eb8044ae3faefe81d837e53b8e615c2d46ed02e4036142ecf, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x1c81a64c5d581191f40a709788a4fd607c71e461de2ad166b9bcca742e0a9db8, + 0x65284960bf09eab2773324ead048c3bec54af7ceba50805e3532a5a11b96b94, + 0x234f635b921f9d7a056c0fe63af46afb8b9b5430d81905bfb16ef051369fee7b, + 0x1488199577c500214d8d9c4bf6d64db0811d5e69b44f3b86a585d9410f875be5, + 0x2237a1388bd8962921cc637d8a4c5d0faa6b5fb138d589db98a508bdf9c225f6, + 0x1b89bdbe9e9ab40f2ac20793f4182a7f33ad93e907304fb0440d1e7d40063ed4, + 0x20bfe61092f2e5cb0508a73ca1dd8983127a395f6800ccbec4ed56aa95ad8c7f, + 0x5acd0c7611cfa9170896d7606a8f5c672883ceb42c2b829c29c8dae08df2ec4, + 0x2e3a22fd34491f153094c93bcf17a8e45940e4a1191fcd2d1741ef841681e0a8, + 0x26504b2d5b079c4aee6f588f825b8b28c337137e9ac1f945f715b85b5cdae979, + 0x201fbd4f4c9cac24b23d8bbf86efe15d86abe8f18838bb542975fa10e9f2a895, + 0xb13dc6afd9a8566a90cb50c82f1876fad84ffd092241c028b9ee470cd64cbbd, + 0x9c0853fae2070c4ea816a54daecef43a5940c647229be0fd869ef36f23159e, + 0x1a926cac03b4e6f41bf021460cb129cb4b20253b3c172a6f2b531d57d7a7d645, + 0x2334c0b56015f6c5a9083193b17d225ea2d977932521f5d7e328c3f0baaf7a5a, + 0x2cbf73905b5489ed3b0c5763eee04fed6594411a1381d0bd617a208a9e38d208, + 0x1e06c4d1e2edd5530f226649871f8fc83b9e7b5708d75bdf6b9a31b963be7bfb, + 0x260c2e5e5364bd914ccbfb785d01ab898a2a961daf708f5f3e34bff953b24b00, + 0x26689f7259e1061156947b136c0dbd5e8c2c1972b4823f4dcf04df33e95532cd, + 0x291df0e62b563da670d44db58d0060e20935852eb699daee6e342b3c59b6d73c, + 0x14e05591b9b889b8899134c8079886d87829cfc39538b78b7a6378b30be1c683, + 0x2be6bdf824d2cccd56cec6d1953e0f6b3117f6cba035592433b7daca12ed43db, + 0x1dbbd7c3c3ca0eaa01cd309dcc57d0c6331814ae9640071cc6bb9483ab6f9a8a, + 0x2227b2d0979591731b87cef94237e7068a5c5e03d609e61df240b7f7944e9264, + 0x1d351ed4b59e46571e5727529ed92e6ce55aaedb36e3d54cbc6c2a73fc4a2786, + 0x2312bb7364e690f64210acaf695e5d8d03a9059b261b9f5bc2fd2dd78ebfe499, + 0x1532d3c7fefda9a7e81fc949f72956bd5f6d55bc4be421d27d64847d81cdcbd4, + 0x8916c1ca3dc2d21a671ff4989f5f7ae581c2102c172054472cb63e25fd58101, + 0x199a3556e4c7a370f0832fd385952688d469177c78a0e77107ee586aeed025ca, + 0x4297e87f69747dad1391582ac26a54249d004fbd16bfc50ec12d7e6b95faa92, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x63db3a46c3e1e822357db637c8910722b22e531454a1da26f2768f59a8457bf, + 0x82793e5ecd44bfe57289068ca1bd6dcb1a9dac086bfec2ce99aba4d04c46b2f, + 0xb5214e4d1f2227947a3aa13e7b57a4d85dd94df40e39dbace02df0e7c0eec0f, + 0x15fde89fae0bd5593e8f2bea040a6f837a7bfd5c5e13b04514c39eb1ae15624d, + 0x27e7e6eea879199109f7a165585ffcb5da626a4d0c39b2681fc7b55402510f1d, + 0x82b46075b3da1e178cd6367971caf87a3676229dbc745e031b45136618255db, + 0x176668330b14e97d4f77547f3b9f430b7fdcfb1bfccd46fa70839bae63df4872, + 0x10104450f5b03a0638bddb9c1d9db41998094de2cd8a8cf7d3f04143122e5a9e, + 0x18c84287abb1d81afb7c16b5380aad2edf054867661c07e44b252ed26cc7b68e, + 0x4d7f1edeed756ae0598fe4b0ff7edc488b75f0376b1923fdc417fe7df3bae7b, + 0x16b3bcf2e5fe28543072f71ef9d83e31887dc632c0c86b4389ee730449207658, + 0x2f29c8f376d462946533c1f349391834f2ec826c08eab0eee6a263f759a43797, + 0x20d394abb3b23967e223f5b9f0a556ce582128c8ac5193f66f8c959a1efc3344, + 0xb207d38d762517ba978fd184ccf152ba1c46333dbd979194b9ff06b27a792a6, + 0xfadffe100a5861695b7059f6ad8e0d5426ffe92c2bff0d81825b72f6da517b0, + 0x279aebdde647b4118234d886bd169f051ed193b0edcf46f54a8aca2f4d3cdb4c, + 0x119f36daffe8b2be75f4e64c32fc2ecd118f319409499fa007819ce95ca2df6e, + 0x1242a6c181fe90f95fd6bdb02918b14c7bcef634ee3d02e30bad0caa161b1bb0, + 0x13b4546c3da77fdc8779f6ab0d770bcd3cd72d927c72c69fc1dd01de9ead8dc3, + 0x888fd59a93f104c423ecc2271c5926305abadf9f458f70ebbbe28a6fc401f71, + 0x25a8ff35f85072e4f8ac148e53991882409a73be3156a865cd00ce4f9fd05e39, + 0x11ebf2fa3b30212183347f0fe5632e3ac31f93a68a3b8ffb47960b505601a7dd, + 0x24e547cf052f879aed9d43e772fbe7809c500603eaf4ee69e41df75d2cdd213a, + 0xfc85a22c05e5ea21235ff75ce1128c7bdadfd9fcdf18f1bcb66e5eeb76125e6, + 0x2a9f2576a85c827399655ee856b94ee757335582e476846106dbccc7028bf19f, + 0x13a5b0372ba5ed8b2718e46b25d797b56a6cb0a2f03c621e8969b371a5d1f2dd, + 0x2cf328cd5a7f16316989013b1db59f8e8c148cea1a09bbcbefc464ec3577f253, + 0x2c6f8ae3d08a528068b4ff4da059a1a0dc88e311f87a1a9c5ba99738369762f2, + 0x2108fe376f8ae97694e36f575eaa0aa0dae306505c70d5a0575f5697daddf530, + 0x23a2991e713b01022cbb8d2d3b81cc5b71117d663e3be0f7153757231ad22cb9, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x1e9d125fb7c35dfc0064d4351a05731b95b37e5ebee77e1ca055ea754902c75c, + 0x119d649d362c0f09efab4076c479c9833ccbc80a2f0da6c362d653ecab381599, + 0xb682593d09250dc35e376127d33a34d30ea21f79f3f112066618f947872c35a, + 0x16670c641709033c5f1bb409f530b7799d280e7c9025defdbba706d9e1371733, + 0x16013d4393fb316871311a22728aa5de989bcd030f2a54ff08fbc7317375e8da, + 0x2a7d4518b4393070d22a8d824b75d8a474fef8ee3eae40cacc38d40cb525937a, + 0xa2af4ab955f7dc6d09a9c72bbff55d30ca01013651b387523782487fd6bfdb4, + 0x4fcc21d258b270458eb662ec8b16deae2c8039d68ccab74e19b4573ae413940, + 0xb5547d0028fa903aa9a2cf2eb9ba2d303bfff9ceb1d4070f87cb2821cf684c0, + 0x4eb04b4aa22c6ab9e0cd8c331a04aeb1546b58540f460621f2696f453c0e0e3, + 0x27757b5fad20eb99a306317b872275532a31ae4ac34dcbf20e80843f2511af23, + 0x23c5cd44bdc3e761827ccfffcf09d470a55aba69e7ad0fc83fd2eb7bfff41e67, + 0x21bb1a37cc6a1ca1d65febe7d1868754bf85d082215397b8985df2fa8c47c25c, + 0x2050602a2f6da4117d3257061d22608527508e58e8a578d00f2c3685f601846c, + 0x2a896c598d40d992207040a5f1629dc61549fbb0dba65e33a8cae98ad46afc16, + 0xb2f10b968c76b4a1c338057e1c67985cc3f571380db66b1c38ff9f6d630e34a, + 0x7a1e6e9dd512b10eb0817b56839e3bb85b736442b50f32e18f07a5ebdf3c191, + 0xc0a72a48434504036597a74ce362796f9021d0dc8d318ef086225a55ca1a9f1, + 0x28e3e34de5c1de1c85186e7d604e5e4a24ad603b676abbe3674a0ed2d802be72, + 0xa6d55bc7826b1e2b03850d677928f501bf4c6398104c009eccbc2b2fc5cbf17, + 0x2c042a68d06b5f7110513182d5c54efd6ab0dbbdce57f1eeb5ab12cac26322a4, + 0x18cbfbb6607f28f928f1fa2ef21ce8be9d4719a8d7c33a7fd1279b6722f151a3, + 0x2d7e6e039f81c66f329b2dc40ad3b116bb9bf4db88bd3e44be39acb676ab36ec, + 0x2ba3cf36a0580465928db18f630e47aaef388d04aea7f10ac3c600df5d2108cd, + 0x2403116000d75fb1a8bf3d0a18ab068fccc0c149c46a935d91678c45fc948b2b, + 0x62b5c358a18921954449fd14b3a2dcf3f2974710e9616b9805f715d7a9f9e50, + 0x14307431f749d428d15fa3fc56a517c677c22e0a80bfd0fa2bfa3f35f323e156, + 0x2c04854c96aaceae379bc0f7474cd235436186a5f9f01f4d059e0fc83037a57, + 0x1ba6107ff34a8cb1ec3b4536325f2845a05b0c4b8da6dc5c0e0327419880b484, + 0x1e7b9fcdcabb49b7aadb17219fb4a0bf4da78d4dcdbb6d1437e7fa56e13ff4fe, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x26968495cbd99f547d94c82d24b714e3cfea387ae1112be450ef48a93752ac5f, + 0x1ddd4f2ebf1e1ee5b8b6715e69df13d58c524c6b0bd5120777b78e26a054b978, + 0x1771396e072f342e14fa40e37a4f9e45a385b5badab8a10b8bae6bc325392c75, + 0x1334b3e12b51d4e658735203dfe259c022ddc5deac72bfc942bd8970c7d3f31e, + 0x2e7aef8fc027f0f4ed42c4ac674ff86a2314b9a88094a214325ae5f7611d3f5d, + 0x2f66d8f2e4c63ceff37adcb96812010dec93be84a18b260a659909f18ad00789, + 0x1cc80a4e8114c2086b90d7c7f0f33007d33b613444a63823b465939af409705e, + 0x4eee4396019744ef67fd43fa3739511a2370f23f80e2b5ebc5c5a1c9655135c, + 0x28ba26ef284bc535f288779980dfc0da8530588823a2f83a3d5edb7a5a25afb9, + 0x2fd84d8520146a01398ac84f33cfb557ac2850195fee0c5b28d2ee1d629b4d9b, + 0xd831e57b1adcb20c227a1adf2a6ab52a0a1cf4104e493c327cbea8897cbffdf, + 0x186b1b6b8ac98a038ece2b61971b0c83f28f32e097e28cdcdfb07aa8e685030c, + 0x7630c5932b486e74bfccc6d06d6ca99e499c8913a3a1a2ace3f6546696d9975, + 0x2ea3fc0c165f38d9aa02eec6a46e19a5854a0bb2584c2d35354e1c814babb896, + 0x1c62f3196e53f51fcda6620317b4d088d2132531a7367c8e5793bfdd5dc07395, + 0x1f352e27dd80d315a273a3ee1a159f18875744c5169bfdfa5ed6a29113caab02, + 0x193d8985e3f9126daaa4ecb2b4fec04425eafd71dafc86ff521d81fcf62cdcce, + 0x2271c906b9605c4dd48e925fa831f1267939342ec2a6f2d68dddb62a5241bb94, + 0x32817d35a0d57fe0fd10584116d3b5c48ddfd6ebe990e91ff469b1e679b7df6, + 0x164540210c18239fd0e4301e0e729018a7f419f438fcf829294179bb2c076221, + 0x2de749d2d5c5c9db3652813190e49ecd8ad1d3b3ae308c3c9efb6e98822e8dea, + 0x2a562decd5b704192adf41195234f4e1bd8d9d58b4cc48cf57a2ec9dee7ee410, + 0xdd5762ff7a8f652831aa96e9c74370e71b2e0fa1ddd1db85427bd2e79f84724, + 0x260f24c836dc07efdae65db907fd8390b38f5341faed0fc553cc7c0ad7fa549a, + 0x1a9d4050de78961851fd12689cc0f93fdf5278e1430d7295cf620713b01f2901, + 0x27d255a40de38041587f907cc4d84a8ab1a5ca07f6abf6d5342248c0df6dc441, + 0x2187634627013d30fff1a44ecd3d5a018c06352be5d480bd3146898cc004385a, + 0x2e0eed49a09486c41002557ade478e57b8ec175f9ca36fd481536189766291d, + 0x1abacf3780a60d304e373bd2f40ff6112b068c0c5d5966a3327c386e480c9181, + 0x2839a53cd148fc18db287c3ac9cbefa3a479e414095fe667b74151d2b78c6342, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x121ab2b6ab8e2c5ecf89dfc2bda8337d7f52d76cf7a2e444859fa1b714be8f01, + 0x23a405c7644f6a9b7106d4ebc99b0f2c6c5543352d391d31a2965478230f2c13, + 0x3de1ccb8e26e8dbfaf06a08bf5189bb38e8e5cf181d154fbb0c4afed03d551, + 0xd594c3a1903abb67bede24f66447fa6cc8f8696ddbdd54830a32ef205495e43, + 0x2d13cfd974b0624734fe4a5127b23dae16f69033c9b1b0d7a8ffcbb55158737, + 0x4ad4148506cf6e6d9795ef784c6c1875e322ab0cc3b6380311b19f9441d8f82, + 0x5bba1c4d35ea9bdb593e19848c3510f2450abcd24bc392456d97a6e4f18e49e, + 0x9236c366e97d741479d565c45311478a3c918e62d52d12c5f54b7366c5bf57d, + 0x2a5630fe33c0d5616c41d0953c305e67503306f2ab6942e472ee89cf34e4403f, + 0x2458e51f0164821f0ed092a42b94fedaf0d801a9e7baef3ada586ce5e8cd3c64, + 0xa3218660ff4767aca5b77aaa3060a4e1fc8f5fcc0fcd6813c9892deefd7e96e, + 0x10c628fb41830cad0df1d4045657412e0833451d9f6fb341987afcbb98cac300, + 0x365b8f2fc30b7f0e91046966b67e804b88f2e1eb7ec6c132456467e05d179a3, + 0xbde78ed9fb95b8dabde79d55c92e119f0ca502be0ed08a0dc381f89ad85cde1, + 0x1e98a3f1c8e8f9a35eeac2782615c96e12950e627ba89a9ac0b873797d30107f, + 0xc0308caff3a47cc92f51163e05a00bea0517f621a4d69cb9e680c79577542a7, + 0xbb209639cdeae029ede39f912e33007334877c0004842f75035a7ee26a5e4d5, + 0x13ffc065d98f8ba997a11cab00fea19d1efe62e20f1bd7103de4858e210b011d, + 0x24ce589a99dd7149b8a0a25f95e766a44b081e5d475d17b7cec54daa028418e0, + 0x2ab971f8aa28d7fb11b7cedc6d85bfb947bd64690e6d6cc0fd9cede6ccfc1e10, + 0x1b2e15dd9e25ad8b2506ff8f0286f34d26254d2b4732cab5dbb713d2203ac283, + 0x1f1c3559f788fed19f86c71628547cd1d5092b0d30b4be4ea634b744923cea21, + 0x1c83b3ff9fa324bc9a5316f0a85a8657123a493a9b0220006ba1100a393919a0, + 0x28958a5831727ed80010116885dc7c66a1c245f6fcab56362c986ac87caee035, + 0x282c38627758b1648078b241bbe3557375aed2e83f18278ca6c962963297a142, + 0xddeead8fcccedced8e4d4376a2bc530466bef45054731d5243454ff4acd04c1, + 0xbdb032ee13a67d9c75df4c44570244e4f78e19a039b30f9f12c532e9b0ad601, + 0x651ba2f04803d5f77235caf50305de5e55431a6abfac178f524a5a01fb4f1b3, + 0x6541fd461b311dfcdc647b2c33e272d9a3733b5ff38c7e0a2cf51a65e22c19, + 0x32293b2b6e94545d3606b723f7a3149ff5d997ff1e8097359e0e0eb2444fab4, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x1e47d96559f3d9eb6bd2fafe210c31f4a8140b853eab986dc12ee2527613016d, + 0x1aaa3fbb3f33fb63d4504fb8ea859f4156ee20b59e198b531546e6891a2497d4, + 0x65c97f1a22d2c6561ed6b3e8bb68fbc299fa56e40bbb54d49e02ec33ad6d913, + 0x2ccf556ae01de7dbe15ba504437271b8a33651d5249fc5282b8cd38fd23ef378, + 0xab4b8237c68daded18da81c5a6bfb657b4d879d4164db2b2e6ee4b854f34933, + 0x2c3329b267d11041b788317f56c3fb8a685b69c0f782ab2213d393befc80f0b, + 0x22f60f1fbc046baeefcae40d2b7843cd95c8dff7d49e0e18851f7fdacf3a4eb4, + 0x1d22dc88706281f80405f66fb60fbe665639969df32efc6e47d33635da644922, + 0x1aaf58dbdd1a14018d33f48de1b98e6f7a937d81ae46aa5313e9a6ad886e7f60, + 0x6f13d3dd83b99f56b8d840e73d3c695efa8ca7a38a891c9df57fb945b8507de, + 0x2d7c3ec573e9cc8350964a20d0a2ec03d2e948a3f8eaab6d520406808d80576b, + 0x293a2e55abaf167cedd278dc3d355975bc1f29dc3354310f21f9ce01574b0d23, + 0x2682132e373c18a17f78601edeea4f8772240bfb889b3db93b2e8ea10b2270e1, + 0x301508db6c1f9710285b1e6e44d46a133310c29c28426d90417d7c21e4f0b20d, + 0x1834c2d44e5774a7e63ba311a3896fa595c04c96df216e3f04ed409c2de9b112, + 0x76c49e633f12eb93ba03d627acf0c95d1d623b6cb42f773f3a20e02f23120af, + 0xfea2b1df3510f6e74dc89be1a061ec7f8255cff0eecea778e1cca99becab586, + 0x19c3a8e23b946d64526696670270f49298ee4eee4402888bf2ad3ced11f7ad53, + 0x86cbbeae69e83af8d6af50cd4f161f345017a925318acc46be5cca969697042, + 0x1a8a851cf400ea4e9b7a51f0bcd5b636e7894d05f3e0faedeba662bf80e901cf, + 0x1fb9f1ed4cfe567b8183fb0f9f5edd26e8af56bbae47cfb6fb6a2c5323303797, + 0xfd5bdd425e00b499e57e34f19cfae9bf0396e405fcd9b4df234a73d15f96f03, + 0x2dd4591301dce89c25a6b690ce98e4cb6c5603505055f6c84e9fb8980cdd3025, + 0x11cbe00cf364a4bfa71c70b6a4b180724765a2a4cc0f31035e44cea45c1719b, + 0x1919aba9eae5d5cbd57d3851ee4011af47be08e151339d0fe9b32602d1fbb827, + 0x6dc27862b0c4f31489bd8c0c6e2a9d8e1c8d52284f4f381b88f6ca94495f798, + 0x1911c33355ced9c551e5aadd528bde012e913b283a67667f4f269675ada590a0, + 0x2facca82fdc63330a3628ec9435d193a47caea8fd2de6617d601bbad8adb0faa, + 0x168bb7d0c7b38df856af9831f4b1da200df248edab92ab41e638e6800c57252e, + 0x33864c3cc0a4cc3fc23c51ba07bd1f797a55394f4e0c39ca4dec1dfd6473aec, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0xc732637dd53a9e2035cb048fb5ac32b68613e0cd12f68a8b8d07fabc738cbc2, + 0x2b44e82a5cbaec37e208762b75b37d4ad4bbc4d83192241a4acb22383f26dd06, + 0xcf7e6a8815f6122fceeb778851d85155384796be9a1df53639f5d81631a2555, + 0x976401c8c12d415f389d4bb64621b71f225619dd93897525be9e8134ab912a4, + 0x1a23f2aa5a0ca939496eeceea3d7a9e386f641a248fb689682a8616ea98202d3, + 0x1295f50377875eea2b8757bd93e3543b59a727da7874e646cc3ef523ffcb79fd, + 0x1f4a65f81b3fe858fee5fe292da8d2594efc08a385f89dc60be97c9c7cbd0032, + 0x12e6d92557037dc2fc85c17c4148e9018fca489e90ea096ea7f400c74297a2f7, + 0x2f1e3906e4a5b87c714556abde45934dad466c1044609b2c865e5a835667b38, + 0x102c4d0a2eb569486e7c6c7893f6491c03626259388fc7d55b519a55e377a921, + 0x2c427c75876fd20b334a45663dc28359937368097c46f7b685eb6e3fbda1a6bb, + 0x12f1968b1e77f14f0f2e90f5fa44799cf2d5cbb3b77558d1493667db2ae55267, + 0xb8730598feb9ee21584d55d5447d8bb6540b84e40c7d4f14b6062ec02ae00c6, + 0x2e13857a53b9dd57a62a790b221ecd3d8ac27dd7ddf4f10ec48e680f1a17041b, + 0x86f9752b777f6b6260f53770c94056c12f444af68c40c75bf7396dc1ca7ebd5, + 0x144d5e3d11651e180a16152b3106f937942d48ee746f217a89db2e410f06e08f, + 0x27956794096d302fe3cec23f3cd713e1e4c7ebf7a9599ac1b3734cc032811a03, + 0x2464182f248bc3f32e7d5650870a79c371dd8fc8d67034dcfca621a1f1bc596b, + 0xa75f1c2e431c46447da58c4b53b5a707030003dd525a6746963b144c9a51803, + 0x441eb396ba8329b88880db7d7b29b57e7165262b02108544170278e444e11e4, + 0x1c271f16943c48bb48f4e2d178b77e4c31f22355466d641974957a5804e78765, + 0x209c46dbafa81cd4c62071ab840fa1f138a8289e87150177ce20c6f9942dff38, + 0x3002dc8c48624cf7f6e207ed3dc4656f6c6fd56f260c96c9362714d4cd667726, + 0xfcb2bd431b6f99702c0f6b220885e57f93fadf7a8d3a365aeafa0ceb1fb7447, + 0x2a74154c3f7dc063f12decedcee953b7e7d3d71dc48f867f72c8a75b5dc7ef62, + 0x129ef0b882070816acf093a88c660245a4e58261b307457eb99fd6c697f0ed7f, + 0x24f76ebf17e1a43056e1e4767cf4aff954b2f9fde49f05fda6c18ee7d2909471, + 0x1d099f0d638efa534bd9c758f9856a7943eff18350feb2d90dd7bffc48e80c16, + 0x2c9f441f31d9aea42026c0e7cd8765aed321ad391f4c869d87118b7a1107e94b, + 0x7af13e241cfaaec4578b52b9315b5017dad324fd69bf1a6a6aa79ce75b044ad, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x255345cb88354e31d381742d0d5b42072662445df9b98a247d617c92f27cd9f1, + 0x17e5c7c425cad2fb89e6acb07a2cea4bd5b1cb02fc04fe38dbdb341be1cf7d89, + 0x146fa4eb974c8faa9f821f63aca3727479d548d9f663f6934c1f458af3999ad, + 0x727942876c6eda2c90f98458ef4f4d6ed010e0562236f1febfaa72bd11a5fff, + 0x1bc84a56570ec875efdf985272b5df66c86cfe58a5be052d91787a8e3f8d49a, + 0x1053ebe1413b33bc188e06fe047235dd3028615fed58dbd6c1d014980ed7777f, + 0x20b12ab6f4bfecc04ee5c75f4108f2d842f004e84437e9093b15542dc26803cd, + 0x1ec0cef9e5ffc3472ebeaec671ad6ccd1fc85e2fa7c5e02e619053976eae5d56, + 0x2a42e9eca9fcaefc84ca320b72a0415eece1512b0afed7bcf4938985727b633f, + 0x1a172b2e81e2559ff3ab9b31a103e77c71b2e617bf7064f7a910803ef7cc9f9a, + 0x2f2cb2dcec93e9d768a5e77302b98fe0c291467a8bf3922e270123e45f06bc56, + 0x73e947e3b071d91accefd64d9242ecf3516181b583e27222d05ac64e57e61ca, + 0x201e11dd656c3292b05c202ea3916c78752b9a796fb97bfdb2fe67a935b761ec, + 0x12ba1b074f8b55da42206d4637431163a1aa6c0891681fd604ee17a7b4a4d054, + 0x1caf77967696809dd4e470183d00c935860fe2758b85ee6c6b8212eab0bad880, + 0x2e2c8e680ddec801ea189dd679d2e16c364bf28a69d7b79cb81842ee2469b8a1, + 0x29fa1929e7f6864a6c4856e9cb2dbf44d4c77cca135cee9eae611cb42d1e950, + 0xfa23e57bcdb977f185df4258bc1ac55957909e6613086a44a6581cd275a7160, + 0x2bd1a5ba49a19dd33ecc36aad236b0e0b4a03942f42a62fe825750889d4a1524, + 0x160ac4ad5eec95bc5910faceeb460088ab7d25fa15cb698e9ed17e1612fe2bfc, + 0x4c78cf3e48577cedb8cb5245a9607cdc9254ca8a8704f78d18db58f2552b2e3, + 0x1e9ef315dfdc99112d0e410fd65fccc9c7ac728617537da3e977d7afde414c61, + 0x2b4421616df11dfe94cd2b5500891f07eaf2900bdd8ee8eb42b0175be52be74f, + 0x8a13f8dbc82ec943c8ecaae0690bd0a4bd51a9762d670c8d059038d4259744d, + 0x14167eea5c641fb122863698bbf6897cbcd778d289c28685417d02e86db36ca0, + 0x1b2d84e924984926c742b426b7ccc5841c4bd193d3e05bbd5c5ed5868991741b, + 0xa14c4040634221a68633cf4f4622251ca34e42c9ae254eb7d02a7eaf1abc3d, + 0x1aae6b2f56d3acc7ed2fa5f310a29d4e54bdb4e5f531f68c59ca5b430e1f3f81, + 0x1c6bef1a7a903d4fd215a1754ad8f30011e676e498a3812d4f15d0a8422b35d4, + 0x260d34eb550364a018d509e831a281cb5b187033ecb4814ef42f240a5c1ea119, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x29455194183fea94109c945206f2c16429d01c0a34919ffcf42ac314a969ba28, + 0x11f4f3b6a1a747fc1aa22c66926e6511a4cbf6269f30c62f36f54b580f891a86, + 0x2df1cbfe1e9ff79c44eac7909de01dbee45e899e3500bcce8269bfca310c5d39, + 0x1e3ed2a6dd4ec05059b8dd11063a93d0b6c48226115d09b7e58d6d0f620be4b, + 0x235eade019a1ac892102280841960624b179b82bb21f7a571cfbb8f4cae5434b, + 0x1063dc692e42acecc27654967d85f8c3b48760c3b269565f3581c30cecaeb6fc, + 0x144c087d0bba6b2651508013332ba01ca36cfa926efb37633cc9423e9b257275, + 0x8dc44909d34e4fbeded6e5b8802fcb8ac3c31e0c2a966956ecf0cf4c027eabc, + 0xdbb16e5b88711eb895a12babfb81dbedf8de29ce530aff091a3a16f9d363468, + 0x2bcf5c9c863de574f3fc6dd7e35b84d333faabe43e1d6cd827ad58061476fbce, + 0x13cc6568623778319060d01c7e7780d9ddf3e6fdc11dbd6e0d1daf61c0ca5904, + 0x17a2edcf8bf40ac243662fdb41e4156e987fc66e00d5077523caf74b970cecc1, + 0x193dcdfd2950a934cc3b92c1b9e826a11e6829cdd6bbf699d702c902c9c8bdf0, + 0x1f049cb7d14ebd687ac611414b6186ea76938c1d239f8bbf5f83972b778dde5b, + 0x4d9595ab4d18bed55ef3c3fd0cd99e829d8e55b8c101df09c2acda3acca9af5, + 0x11a10e1656c16d3c53f889073d9f910945506af2e029aacfd7223cd45b457f23, + 0x1c84c1b888ff8d6396ee63866219b3e1d7473ade3c14ceed3c1fdfa44b51edff, + 0xf5531ef3a85171c99a9927bd9d1cbe04e84dc94c7ac68c06004d99a391ed06a, + 0x6ee08fc691f0b4229dc871b3676f380042f6b7ac1e5344149cd7d64cc9ab46, + 0x237628e422a57b51577905847eec949cc0938adcda2e97fc960492898d0c8d4f, + 0x4b4e368d0d486b2d4772a9fb808db251fdfaadaabb59a5bcc20c97bfa38ce7b, + 0x2a0484d90b9de4de15deca9a4f8795a61a8cea3d5eed0e938bd5c2203fbe45c2, + 0x2cfa30139fcfe50e07673bfc8029dfd08f511118dd4a4bf0a77a7bb3e1e894ae, + 0x278fd68bb5971f9d8b52b9e924814f3e07af8931796fc2b5d09605eeeba95c3, + 0x24ea4315f2dfe3e361e0ec7213e50dd9b25ff8bd654d83f6d26ca562e2a7ddc9, + 0x8612599ae2e4a878ecd88d9194ec5ceedd16b40c51e6edae2cc43f5e94a2534, + 0x2003edf69a810b8a3eb8208b455fb3a6e04bfdfa7f6198f2a0475312da1da37c, + 0x1ed96d9e0748ab37d6984b7be85b6c4342d341113d255cbaca749da545d34981, + 0x24947686594e925c8ce4f919309d5ddd789f62d268e7c6340022fe0d45a8b816, + 0xa42b268cf646e69a84152d6323e1eb318392a14827ae3241981f6ef34173e, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x2c16f80293a1d647de56a4a26abf5cb6840e67570999e804d434ba92326b0758, + 0x10003b7c47202671bda6e5bd46c2564c634d600e0fb23f898d73a217eb1f7cbd, + 0x8f99c641f5a436daeb9e269146b505771e8d18f847cadd3028c959e39e47f77, + 0x174ecd880d0e89617db1a52d076801bbddcc8f63c753467e7e4b7284f9c065c6, + 0x124823019c96feb400979fbc9e8b3ea028ba45199a99118e5be4885ea25c594e, + 0x1476f2bb8bb265ecee769b8092d9687ce6b822ea2d4fc8d9aa75927be24bd03c, + 0x19dac45643cf0ec46184ef121ab7e9a1c03707c7aec4620bccc80ae83d4ceab8, + 0x14674e4b8eab3fc1f80cf57e344d0fca2081743241898bcad999dd7939cb9b7d, + 0x1ed72b8e2da7a2fd16d8accd8eafb4cbb51c59a9d05d221cc608f74b7230358b, + 0x1da5ab440f2cdb9bc079ecdeceb673ecd86b906ffc33509225c6364ebdf4f9d6, + 0xc751d0ea79515c1ac0584876431dc1ce6226dd8420077d52dcc644638eb389, + 0x6a9dda83669129d53d499be9d18471ccc3decdaa7ddb14c4c19981f7937033d, + 0x280a6226e729cc5a5fef6b66266003fb72a99a97e1985f9c1b2f3d6e1c5f4696, + 0x277ccb7f226a1920bf5ab883e320f05c6edb580037be022f9a699079c9ea1501, + 0x207e4c2a1f9d4bfda41396d244cbc313a5a5755ce9cb8780f6a6cf8ff67b090f, + 0xab72e9f2261bc7dacdf730b02c9772d67b34b71c154f06480e2576995ab7fbe, + 0x26dc9a65057fde68cbf2b518e47e52c3089085c30015d873da81924ee8117970, + 0xee4ec60b28b8ae1bde8ab75521531748078f397b9914ed1d600f94f65edb2cb, + 0x26f7aaca92a139c5e2a653e9ebb132aaa385aa192ed9e1702b04f2c89d9bb766, + 0x2d2f1c2e5326bf8b3439310ed43a8721d8705e6d1c031af9facfb15f4ff8de85, + 0x1fd6ab80e45a94d9ee539f3247f22d8fab16026c5d0126cc5570514599c94b22, + 0xf94a3d03ba6eb3cbb84ecbf443474976b4b610b2c7e0be7bd18ec026f26833d, + 0x9fda6221cf5e2593d796d7185867ab6576bf2f79813f55b6a1ae9a1fcb3437c, + 0x26846396de6a8b113b784a7dfb9c63b0b950a69a20e63634954936f520470063, + 0x19e400a2ed9606a0a39041bba22cbbeaa8547c89ca0eb006c614b5d6d1b9e0aa, + 0xe2a3a5f42587d60aec0abbbf38902fd54d392c4cf26f8359deeca160061a02e, + 0x165836d2e5f94bd9868ae471de1b194fb407c3c27a3b322c956f13789d95fa23, + 0x2bba296744ead7cb7fa4e64b0d9854814e303a8a685433053ada126285b12dd2, + 0x1c42b83e0bf8cd6e2072b5602d85f5161ba6cc9aa752366791cec9eee1228510, + 0x2a8345e521ad75f61773023d905bc873ae8754b28c0273063d4970030cf6afd1, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0xdc769889e4e60328ced67e231f45e241283d9435602a724dd8d1f8a709ba50b, + 0x1002f962d594a9b3a1cf2dfdc940b80a6b67d3fc3148be7c0d11be50e277f1fa, + 0x11604b56f285ee9acad757b62e0a8679ec868a468c6715500cb84e72be72c7a6, + 0x2cbee753288f68a90a3c4a83783d30862b6e89e21ec3ae112af1b016ee9445ce, + 0x2df869ed85aad1cf7a17b58d217df7738c29e7ee5b0d254c1d4976ab71916b6a, + 0x52b2ba2fc76a7c40e4eebc062b1c353e2c7af8430a11222e64b8f1c09e57b69, + 0x23446fb653ba07d93115d3413ff7c9676f57d1e17a08329c153eb0e89d3e303d, + 0x11f1fad8b82ef8c047feb379042297cebe6f2a6d5660e7a993f67fc10e58adff, + 0x17af0f2c5f514d29665cde2023d8662f453954101bb66e15ff582604b86147a, + 0x11d7ceb7a58360c894abafcafbbb0b08e302ea940d29f5c403971e7a7a014fab, + 0x74ad08dcce384bd2df324e56ae0ec65f035aa90479bf25d940ae94f25bcde95, + 0xa9e0e2b8db72860fd3308d7982d4c51766d89ccc8939e0087c3fc1e15d53558, + 0x10053dd72d3e24c8040482217ea6d61c3e419cbdefe8709bc58951fd2a0711a6, + 0xb8feb7949a8116ad1ec2cfe47910318bd5dc9e54ee0caffb08a23e4fa0ea22b, + 0x1b3f78f18b178ee8df4bad8cf2fade21d1698ef13f78d3598c44a063fefdda25, + 0x15af1e8fd71f0799f8c7dec891c12d89bb687b8f14d0f12b4a52084bd68af74d, + 0x147d419b1999d7896f7f2c9ab68937f4e1ddf75ce3615b51e275a33e5fa8fe96, + 0x28b7cdada2f2cb2b1ae17064a61f03b36fe64faf9db752b7470da8398a1578e7, + 0x2163e931b6d3e6641d34369bb808b3745c1003771dba9dec9bf9d5fe24c43577, + 0x1fe3bf03ba1752e0d93486397e28ff2a9350c56abb949f7f6a02575b1436636e, + 0x2ec24f69b227550297bee72b056181c91364f54f9cb31e0b14d38fc2ac37f147, + 0x98d9ca655e17d9af5fc7933beb8f6b100d78644eeb19c1e7346bbd6077fef4f, + 0x2e296e61aafd6d219daefc2b994d52310770830b5767a3c8220c2f5251e4d786, + 0x2f6884b2602c50e4cbdfb45ed64863dcb689af3b917fb10dfaf9cfa8307d112c, + 0x5e81ed97199a7c32f5844b9e3c48c60dfcae2e703bb19855260479d6556b63, + 0x7b3281ec445d3a58654d72a48b86be8a10380910a57602460c91e4efcc812ff, + 0x14e55ee2871da3b1e051cb0857adeaefa5e9101d9b5d7623580fa70cdd041385, + 0x53f6a1c6bba5a4ce92962a6a23cdf21096b5c1c0652444a52174efaaa6287ac, + 0xf55c1add25dc95f9602356a6ad006ec557378a038b09d9f46daf00b359d88e1, + 0x302ef214c4c4e78688cfe22c58544d3cb8888bac5512044709e1c56fb3a6a513, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x1e97abc82dd29d2284a66edf1d38115a8cf9d2316c79b2262afc5a43487217a, + 0x18c844b544ec0da670ba7fcad86b7e4cc3b790c3269507ce0cf608308e63d5f2, + 0x27e894e463d2d999c5bb6c29e9f5573603b4e3f55fa4b1eb315b0664794a8897, + 0x1ec3f26b1af76185f0de2d894157ddf696e80aaa3661e94163e9106a9fbddd3e, + 0x22978d983a255eae6840d50dcf586263d5a0afd5b8eb552f720cc0affc8cf533, + 0x1618d7d7b6d7ba2dafd24690ada4cfa7ec3e961f395b9c7fbf7d76d0dd837125, + 0x1df2e4ba9ba44ca6f24877919be6d84c97a6f6cc318c7297d608f1aa4f050848, + 0x1fa6c7cfaefb71fe88191e62ec1e69611c76c503ca8c6c2b45e0ae286588cacf, + 0x2f00266e50bc17514d27873eb92eee8038696ada6decb01a1138f09aaefb625, + 0x24b0ef6c8ddd8d74acd34fd2977a27c6e584febb5cc1ed119e43333934a5efa1, + 0x2eba590f514eb52770d140bbb2bfd1909fbb0056559a5bb18fbeb72f9bf1c7e5, + 0x1c01664f520b12562f93bb93f40874300703ca11b39eb1e8bae9f21944f0c4a6, + 0x158c6e1a418426179c9216cf35095705395180c264802302c2b5bdda75b4a4f6, + 0x2609db7fe10c939e0289595aad97807442c4ac5b28205bb6fd6ef7bfcb55adaa, + 0x68bca148cf00ddb73bcb32b580db9423292a3d0ca547207c281222c5ac64f05, + 0x17bcbd81a901026df975e1a27ca02b7db2b6c7daa5dc0fc9a7d71e4210c16715, + 0x2dfab84b8b358320cfd6fe1fdaadd8ee01d4658d701376506800ce70020c680c, + 0x120819aae37b3d91fc8c0babac388c536f3f091923ca13587c8fc91d2c27a9c7, + 0x12313b69bd606ca46c7008f6f4fccf3ddef09743f311adba1200581089985509, + 0x11e9b992c04a4ee4586a62142f37868d6535f948e89ebfc54151c61e1fc4378a, + 0x5f557dea69dabf8f49032a07a021b292a4cd73e51dc82f9b8e4d96d82569a53, + 0xce2bc653061b09a271f64d5ac546f7b2f3a270910f2505ed186e11b0d4eea44, + 0x195b61bc0d16c176128158e7463b3e3ee0df476d31cf641e297c8cb9f5d6368f, + 0x1d0df7d7da33f468a43a413dfd4e4e188385c6c87bd767486c4a4a6babcda2cc, + 0x13904564817a3bf9e98b1a21f1f360e5830764da4a300f059268111b51b0b761, + 0xee010fca95f45250a5ce94a89a91fbd64f2c118e2755127a562ebb00fd27ef5, + 0x279d86c488716103a7ec21aaf9d2139f72c7f72a18eabfd581ef619e0c3b20b6, + 0x11b803d7d692745f2ba754f16d795a2c51bc5576576c244edb6f80cd790dd8d3, + 0x3d093d2500c614852a3802e498bdd965dbb993e8d07397b6ccd9c3832a0907b, + 0x16652d5f69932fa04272068446046190f9c83f85e9ccbcd36210c5877778f1b8, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x2959b7c18c774ae5de1749af01c678a88eb32215afbd962a0561d6d198525e79, + 0xc26abdc5e7b095a4e2237c872e90bcbee8a10618572ec9aabe2d7b1a377d6a8, + 0x17303e79bb1728eecb88e18d8b7db784ea1a70e4eed67e7f9e6deba761b863ec, + 0x8f1351b765587773fc254d4e9c6215178b81698a6e1332bdbb16c5626879b92, + 0x24587c5be08773ab2fc2250421c4988b332bfc432cd4e283fc86de3882b7898c, + 0x972bc46f752662ec72acc9851fb74ef8fa89a03f2ceea01849ea839f9a80d2a, + 0x185382531567193bffc137ce0a17f1f087da191bab36af539545a6929b44697c, + 0x2f835f068a500a33e6b44b3a492d8f09228c2d660f84558123e6292e93f906b2, + 0x159abee658fae6ddaf7329b5f76a81e713dfff71c438f7e678a5b64365285949, + 0x2ceaccfe0874e534eb39a86b066ca9b40e25793df513a2e1a8edeee8398489ec, + 0x3e5251b721d2cd67a46b4e7bc90015c36a1134a8ec5d25194d5c7c309c0b029, + 0x1018c8b0a3de1c528680503ffa391ed74fb1b89e3dc09b140f7625249f061249, + 0x2c0015ecad1833f9b004d902644feebfde2a27e50aee9da314e4e7480a1eb9c0, + 0x24feb7104d161a328cdf2dc7c125422879578cce893fccf80e5bb265bfbe2e6c, + 0x2944d98697f7ddec78e5165cbaee2bbf0cea6359981a13c27bbd17a60709b7c3, + 0x1eb6e93cbfd035bc4f79bd6d32e25c05be28216616655908dd394f8e4beb0c17, + 0x15274c4215b3498cece507e5a9c78c728a2927ae24b72d580caca25885158c01, + 0x244439d87914ea7af64471c047d1afb3ef3e4d3eb41afc5ff4551e34e0b2e03b, + 0x7c60d6d98c85efea799c2d359aebd1cf865015712f99f6f5078776b44455899, + 0xb4448d85c58321886de5cad02508cb079e475ad06a5691610848e530cfcabdc, + 0x2d385f71e742fc3698c688df7df2ac0cd06bf1eda4db74246d5b3ef234d66603, + 0xc3c7aa72581cf03932ea40da64bf0454b26ca6c02b25798eaaa3ee0893f1479, + 0x2f4091dafd791bb3cf7089c8e714a34bbc2f5fab044416870a1110bd68da326e, + 0x9a9203152f7c7a322535f3c2445dca0be8621df8f0c9bc63a8e3654145b2388, + 0xc9944612dd0f8e184d07ec5a44ca257d67514ac9ae15e4f5be49b6c0356915a, + 0x465c847c7d119bdefe896bf452c77f78e124ee0bb245270d21ed2bd79e11721, + 0x1725856f51139de9097ed3842a414f8e8f63ea6b9e6414e5eb220842583af5bb, + 0x276c1b109f88cc834ed8c2e68672a592250c6cbfea5f9bddd0834c5563f9a886, + 0x2baf5485e19edbc5772e04a26dea28931742966fdf39011b1c16f2832ffbe3d7, + 0x2042b1e0d4a962b95c5dbcc044fa0ec53a00e8ad677a6dc39e36b41a016eb036, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x1eb87ed83839103c87434e39c910399447d9c63134d442335fb3e226f84b47b2, + 0x80a226b8c5b7ae68105818ce707b2441a0da70860d771bb4d58585ea1a62866, + 0x1b038c8d59fa36e1dfd4cca8bff7d38b6161bff01ffaad9e95e3c8591174525b, + 0x2ae9c92470f8f4d5ef9b96d9c1c235c46b5ca275d4e08dd1d193abee581d763b, + 0x21fb57daf9b4cdf828d74de7723985b3a1b0226d90f563ef1cbc0d9232fe3429, + 0x22bfeba5a5a36cd515fa31b9da51ef26a15ad6050bb42853f59ffda0277a99c4, + 0x20f3df888830ae894646d1166204af05d9817613c719cda745c09aa141590c02, + 0x63b2355acdad1a0032a2f2c7a2ea5f307e3c0321d261c9d7f5fa10934119f28, + 0x16de60437f4609882b9eafa6ac6ded955b8225b0985fc4e3983ea640add5028c, + 0x2ab849a10d24540498ba4c7ee7afac4ecdb81e0083fb82ef56b91d025e33756, + 0x25d60a27489116c12d3fb8af52c877f5691d57ad645946fc4dda53db186e2c50, + 0x1b1442dc351aedc7917b1008bbdc4a05d92e4639e7f3af1b7f8c1efc9bbc79c8, + 0x2502537d03523d64eacdc4da240a03f6981a89c3f3352ed51b95231d129f6efa, + 0x1b786044b15312f04f057fcb32f799f0176237a9e5c70bf309a9860ab90fc724, + 0x13aa1eb0dde09e3816e83ef9027b5b12fcb298f469d8523b588d728f6fbcc841, + 0x15d72e8723e077bfbcd6fc983a47dc7b580681f0c4c4225c58011bae84f8e1a, + 0x1369471512c4227330fa0c25299570db00e2db62554fdaae3159988504703cf4, + 0x1b7142089a165fc6d053090f4e2797f7ebd8faf20861604b3ca39ffa78d8fb6, + 0x65028c49121ab4bb6dd4b70ceda8065e546521a801b3690d836602df5c07a4e, + 0xb0c93a4ca60bd6782440a3ed7ed610e4ae11dbb6d73cbd43bab80e55c0ef062, + 0x538fe578ac88710d6dd29a5916aa739c9a9ffcf0f692b1f03d0e890a26a7ae7, + 0x2aaf085390a5682425de02d9feca6b1713d016d1682042a9283f70b773eb8388, + 0x12d3a3b814c1bbef754dd237698ca763867b464e9a81d9bb031ccc91574878b2, + 0x24fb699b2d537bd375a53a4cfca82569a0f7bf3417e1d05c2f0a996c5e85eded, + 0x11dff9e9c33f3786c5cceec919601c95a9569a01502843f7d4ea0a7078111ab3, + 0x261e407b0cd0b43f5b9e5c229e1372500707db45aca65d3c28421a3583367e4b, + 0x2351bf0327b143b2094e336337c156efd6dea461b8c2d23baacb18abdab7454b, + 0x1ccff891ab723798b4de646bb5ad6d3e3da5970a79a4f25dee25aee7ddc543d9, + 0x476e4b00efa019c97bd3cf545fe7a670aac04ebc418c4937827ca368ed3cbc2, + 0xc1e697b8e69d9e6cd15a5b7e2d446038e11a06250f693e21a7ef4d9ee11e53c, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x1a09d2b7e646521dd535d06cb8c4de0a1b42910ea066edc264f59380e26cffe9, + 0x17cd99a103a4adc1725b545ef98b3cb45b2bc761caf0eca510891356c0f6b6b, + 0x6b9bdeed92c495a84a828dd539be8327529a051131bea1a198bd849018a5a8b, + 0x8680012993a07914e68e1df59d14f13f130cb8c1099833fc0d2d2d11fb311d3, + 0x247b79afdd0a99fa80e82045bf81474ef05d19174b15ddfb6a5eaee7d98a66a7, + 0xeace989a2a643839e86a96e5f8a1e99e868ba1becec4171ed39c7bd2aacffc, + 0x1537fa1eb45e0b8dca81475c350eb64701fd14bacb0a2948609c9fa1b9d57fac, + 0x9ebc426effe66fcd5bbff51e0aa1f60385dbc0c7feb0d9c6f4fe06384456ea0, + 0x18467be5d0a4e54aab055cc7dbc4f876d56097c5eec5b27f9a15264059b0eea7, + 0x2dcdc0099307f6a54c05fe4f82494e0611c4909ebe6643697f44ac932f533934, + 0x3fb3d6990d8e8da405a112fc11f9caa56723a2f6093e1870a866c21d2f3433b, + 0x7903dff1ca5b78cd6e95e1284f7a87002f00a81d612f82842bb2af82fb850ab, + 0x1ccb172a7b0f1139bc8118dbba6bda8ef321cbdf153a4db826b08ad2450cb8a4, + 0x231cbab35a8a0e9dc999dba368451cb41d7456f2cc0481a14a2a7d72f201663f, + 0x1185df89f8a40ac6098d898334d0747a5b3d0285d41e2038e38712cd26081dba, + 0x2fa064d281be156cf97dda9141c6ac20d0e19d85474475ee359e109bc25a5670, + 0xa2114ecb4bb88293eba241bc0fc4a3b375da6aba30cca76e84810154a093044, + 0x2bd5621d46d2dcb41cd8f8a22620ef625d6fcee5d6d507250d157b39e469240b, + 0x1584517e545411ec6c849b82e0fe8cfe70cd715c5a657d78fe4dfa92cf690d64, + 0x612bd1a5329c91f6c6f6c31809951e143c4b5ecf97e2ff8c6b02463fe29ae6e, + 0x26d3d348ee74cbe27e5a4745e738151b3f61fbaac3ca334b1c6f0ee18a763294, + 0xd69c097ff13bad16f04826fcbc91eb99221410fdabfb06a04c69daf5d0d46ae, + 0x19df85abb6034b86a237f3c2a1849853eea70da522f725111bd78831a70f29b2, + 0xb67940a72701ac24d81e056c7ad73e3dfad45f6c1147693e8e56ae8759c75f1, + 0x2d067334ff4cab892a24cb40846b591176ac47451dbbcde9cac1de766bfd225e, + 0x250e8bf6d939e2294f6723c8b2e001809923b7157ba297cfe107b8220cbfc006, + 0x106265f59a713f1de605f071461cc7765c6eb2ce12b7494c021e07b5e0b0a121, + 0x268591932728ffa445ab526d9cb60f6a1de6c10e244cff633ba59b9bdb957e04, + 0x28a264cf3eeeb2d81d4c1532e63e34496b3500da9e62fc9e8070bd5967c5b9f5, + 0x2e289ec9d9fb747c577898f2104373a49adc00a51974b8fb1c63793f22414f2d, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x292cdc4fac941966f3f2fdcd0b64ced5ebf1766246e1cac45abc40423575d9c0, + 0x8f9166b886a64e24bd5cb9f5327942cd66aefe8904bab3ea68f1c93da72ff30, + 0x1d9346b55cfdbce62471674a48c93173f222039ca540946df8cad8f1adc4abbc, + 0x284445af50c975330a1d48657b764cf7b19c8b5d8cfd72bd8cd1aed812458804, + 0xe5caefd895dbae4ac6d9a50ba9da1fccf2e99182801e50def13f656cc52e823, + 0x2c549e8a4cd3cb9c925dcf4af0af39cc5d419957e85a1734fbe0cd495b4e6239, + 0x2f691c2890ed7ae20244dd12ee9fac94cbcacea42bbd323484146b83beef3964, + 0x189c18874e9397abc281643bfa747739e2ab4f51c2ce1c64d8e0f6e0f65f065, + 0x2eb6705a02c7da98061b74e10ca594d9fa85f2e8a76991313d2720268f65223d, + 0xb8c7b073c91922a0a25ac24de7c5781f5b95c1d29676b097409380c6e4f0d2a, + 0x2b254c1c989381315f1b091c685873377c05d1d40e3d20d41f56506756ce5ce3, + 0x1f9e68c2a44b9a206a5d1c428c27604031de91570926a23190329781dda14dec, + 0x107e82331d1a1db3aa814c0e3854ceef0db0270c842945e09b352cc69e959fdb, + 0x17fcb1867c52d50eff04a137a183d3f0dae94b5656c8818b4fe024b7a343dfda, + 0x263f802111aadcc99cc129d051f90acde70278801f4dcb1781b744c208b6aa52, + 0x27ecf8ec238d8089ba1393e8bacc856c9b4bb554dfa37c89a6d6bcb0a5954c9, + 0x2aac3bfa20e64a0c0012512611b5460908616ec7282197ab7345172daf70f421, + 0xf822bf90a6d6c7e046af505fa63c58152f880dba55cefc639313d104a99435, + 0x1d482f74f7352cc3b1e07f0c4e0ca4685417ff468574b7694f6ff7e9b438323b, + 0x9efb3fd5f2af95e1269ca6e40bfdecad8ed10297b2261e7a27cfa076bda8348, + 0xd70b85544585d7520bc48048e716d4bacc8a357c3efd735e10376c3a68e58f7, + 0x2a96c2d2c57ff7ff8a1fee90d4f30a427c4ee5faad1bc0c7640dd2628d7be337, + 0x467014fd75c87da4bc08542150237dc948da566956c03a7734f8aa3d4ce2a0b, + 0xb26d2f933b0b528867e896f30e7045af1f496d73a13e58fa1456f4aae1a911c, + 0x25d68e5bef9420f64c42a4d44aee71b216ad9054d968dab70bc5eff77556c9f, + 0x177f027b0cab57291463ca56e3be569fd5579d89ebf5fd528742f123718a79f, + 0x2c5132a44be83d88879ea114016e67092bd966a9ba0364ba501fc05b63887493, + 0x14bf8d2e43f7d1338bd93c4350007077fa9ec02ec8e64e03950d17efa18711a8, + 0x309414aa73703addc97561bbcecee45d25f19b4591dc6d772fcfe0801a85f30, + 0x40ea41587d4a40b935571880dcadf45e722e4273f0f2b32dda53e53e70a7a87, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x10b0d37ca26e90c6c139a01ff17861c46ebfb646f348fa543a44fa933dc6c7ef, + 0x175da5183f974e9606eb7d7e22cd12ae8e27dbecb9bd3c4c12b3f6ee0f7518f0, + 0xed8273a2cea837930a2c09a3f7b24188cf44b7d3b2fe41b13e03bcf26b925c9, + 0x1217c887532e425c1502f9fa496dc792acbce0cc79c661b16e4c35009e7d84a6, + 0x1903752f1c798c095c24ee714d1b8124a4b4b14d2ee2ff49ff7169ddbcd5b4b1, + 0x2803547df88fabd669511738ffb17cff8919c233c053e2b10d01bb398629deaf, + 0x4ee5ecf2b925246a34bfeaafc9239f9a5f7277fb1e39131900b432baada6dfd, + 0x4c37b33555c362050a25021d96f000d1a1dbc15c9965b2536bc4ef59b52fe8f, + 0x1a68530699df479a39fd71d5699898f91c440b61d7138d4c95a353ec2a60f0a4, + 0x62492de9362ceef05e663b2e14cfc1065415c4dabdca0d4b49b602228ab9aea, + 0xfb5d4b500ecd21e402496acd0c39a0ce6aa93741dd846628387324004b15dc7, + 0x1747b55b705c98dbe7c38903fca5260a313fb1ae77984671f6c2fd594bfddafd, + 0x2d5a953c65e21d277459d6ac17330055536bc85c49205e6e75cda3a58faf9b2c, + 0x12246b22f19de420b776858c17df7b57d3dcb9dc48a34167b9b92a429fd7a403, + 0x1133d3224669f992858632b54a9a2f3cae9a86979684bca621d21fb8a7a84dee, + 0x42c7ff4112c72f96e2a90a37d0b9755a935d43ada317de49047e45bace9214f, + 0x20948256d2882d787bd97ceb71a8f9413ca287382dead6b80ec8511a0f820a94, + 0x1a3624b0bd43a88ac7c7de460e246ca48ff71a5a23098ce0a713ed4cd3b42b7b, + 0x1df0dccc539de543bb1cc2f5a0747c1a1d39398b7e5d2542ad7df388cb9a2c1b, + 0x21dfd5ed89c255e1c584093f98d854f81cfc58f92674fe0fe8dfca8d7c1c70a, + 0x2161ac36dd50d34ad7ff8e2af49bbe1088d3318678e3a8d8e0e0b3f430d55d2a, + 0x1ed3cc39023610359593bf3e49a58dfbe99ee1afb33acb553bf08012aeac1747, + 0x24c8d8944de112708df57b28fd012d576868d998ed87276f7192f8fe82044fbc, + 0x183fb7baba3d12e905bb7184ef691982c1dd489844c06e9f7a048793c46a3b9e, + 0x67c083da1428ce521951ba41ccef834d99cb41e8b92a4c4cc7ce8dde2de4adc, + 0x1a18a9c1c45e95a541ac8dfb96cf2bcb5f93ceedd0135bde9344813b3b5762aa, + 0xddf7ac0878db5f4f384ed02d5fc90adf7215e4c3bc57d37f4c27ce4379db9a4, + 0x2adab562b4f7991948d9cebbe53a821fa08c96b9100b17a92d2ade4032f490c5, + 0x1f36cd6e66832646861d1a44378f81777cee66ee7b66ffa4466e9f9827d3efad, + 0x16c514bc623520a3c63d724ff9f8e2128de3a4e93ec26cd60596d2b74cf90df3, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x276235e6cd6b4ad073433414a39f872c42ae47d5caff6a0fd2b11db226627d13, + 0x288fc36fe0e39bf7f8deb74d5edcc5d6ac0b0e13f715a911a696212c8244cf30, + 0x1f6e77bcaf2e10160d53e81aa4bd1fb9620841cd7cdcf5626cd1347714f1790f, + 0x2c50c513ccdbe60dd9d14262db601d085beb529f9f9809e734b12cee63ad60b2, + 0x1048a932b87cf43cf61b9fe7d5e7824a9c0be2d3d8a6927819a1dbce4de7594b, + 0x258802f01620793e2b886ba9978721882e6ede295ab05ad492dfcb56055677d4, + 0x1fdefe23f71f9c4e4b5a27bb8c5ef9e97f8a272361f8e6ba93334d5292ab1c4f, + 0x1f46592f6d4c77467466a48358c5c195e12db247070f684bb30caf332e050b15, + 0x1a0628c0617ed94340450e8b212d19bb6d80e0c336a0c73ebd489718d0245512, + 0x362fec7e50a9ebf5cbc1bbd06320a44839f3e1a24c6dcec2cea98dc2ed8958a, + 0x1434da4216548b811c240f289b634c70bd0217c2c78d3515981a08f0b4228a56, + 0x2a5a298ee338866a51ab733cd5d912aefca609abb924c3b91334ff31968db1a8, + 0x2fe35de4f8239cb701957994cb678fa76b45ac2ca62d155abc6bd0063d8477f8, + 0xe81871313b59264be15b4d24465ccdfa520f1aae5e34762e48814c151eae20f, + 0x1dccfa84663bd168fead0d648a7024cc7f45de299a1552c65c9aee69800a21d, + 0xddcb95ed4ccd6154052d0399bbb3eed354d1348a26e7e3e3b767f888b7fc1c1, + 0xbdb5ed04d13305bc7abdc9a1f72a3cd3c325a8d5d0b37b3f6bc32f5bf2bc30e, + 0x1a3791a5d480f586e225f6a3419d92bc7c93d3c2c941e201aba2db0db9f15d73, + 0xab254daa5ccaa47e3ea7ddf885a32e8192d280ff8b96254036f22562e3280af, + 0x10d084b180585ee9000d1537f77b4d6d3befba3b2585edb286f9e382257acbd2, + 0xe99d44a8d7b3633a48109e8437a866139b546ddc3a43911413edf9c0abed951, + 0x1abb36484f304e28d2b406edd5d4232f52246a2642bb87e5e8049639a5a7e48e, + 0x1f24c896eadcd0d5f6b1067845c87cae3897a454e6093fc062b6e9fa9dc327db, + 0x1f8c613272cb2e0085c3de18d2c0063422bd3a3f7b34ebd39462a54f96690dd9, + 0x3f8600811917a21e6893b3147b75a987a7ad447437ad24fa472b3016129f86a, + 0x21268f597b84752db51be08a3a6a2a8b1b2284d8b0442b549ee5aaee395c020b, + 0x28d3ef83eb355a7d306caba33c70e6e86900ba153ad61f6b8b41ce49daaf52b, + 0x25d200e83b7288530086b690322a530ec8b502505f3080a7a46e6e822ac90d2, + 0x2a7f6b2aebe3142b2662d473a358fc1bb9d816498b3c2edfff86866e2ac00082, + 0x299afa0d0121fc23c6d42fb127eab14f2dd8ecb1ee0c04376b9c732e97a5bb71, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x292e5deb4d74974e5601e05fdd2a01a57ccfce1962e3f12ffc47ecf62cccddd5, + 0xb7fe07627b2b86b9e560c5c6058f62a23b9cb416af6d749319a5f0a731e9b99, + 0x1be04625c4aae2000e9e13a7959133e86b7888be0de9c4bed8431578d87ddbf6, + 0xd6b21b10daf3f589d71fb89c727278c0cce92db0d4b058ddb3b23e379fa5c7b, + 0x208f14de82a7cdf5b8f2d2c2d77fe963748847574dc8f168c53b1dc68674daed, + 0x261b3202a10a92f8f818f5c9b768d891b3fed3ae03b189e5a743b6a2f631210a, + 0x21da24b99fc179077a9f8ecd8f3ec7a3a6d4e8c62c3721f5a3f4a12fed074d91, + 0xf821357065851a94b6fc9d8d679679a05ca9ca81839c786603a98d92cd3be72, + 0x146cf2ddedf7045102306285a0322a26b9b312d8ae0d5638e122fa42221bd203, + 0x1f5595159d4bf74c70466f5a5df27f878727f037c6821bd0b4a16b9a1f9e22e1, + 0x2e555ab81d4af50711a229745a65dc974ecbbf16d855767d3ee973f261c6958b, + 0x9d88eb8fedc6dfcad4ab68ce84e1bf329725e89adb094aac5a25e36f8fa1248, + 0x5becaddb686664747af21bf5a5e4ddcb030a20314b123c58dca055cc8f47200, + 0x2b5133b32b578393ff342e4ba0169b60ad72d1082fda97c4b696610dcf06bc50, + 0x209f4bb986abb2671c9ac555ce282948dd3ec049e67812e9add90f3d83d62346, + 0x2986e1901bec371bcf3f2bfadcc34003a901cf3c6c8fce5a86715bfa70dd05d1, + 0x36f213f560cda1028bca7da534b8bcebf84ce7b4b275d873de14b03fbb8ecc, + 0x220d1b8cdb11be75d11b27932ab7026a54326b5b340ab065e1e4e35d26398677, + 0x1fcd7370575ccadc60429c962fcfd8f4b3ec9614c085d1383a943d7e487c4e37, + 0x1c49ea5e5ab4635be0cc07f0d40a8f6bf68622bed5daf5c3aae2a2001d19cce4, + 0x2c33a36c54999aaa2e54efe70048654f4d8fa8bf7001a8c92d86cce2077c8f26, + 0xe70e72a3a3d2e267a2b6af5dfdd55a25435c6f581a46ff5fd461f08d0e9f7dd, + 0x6cc0728f4993107d1ad1cc3c083d7f23847df303de20d92b5ec90ff8785e8d1, + 0x14adb5029eecd4e65bc58af84408697c8591fc5f6f74b6cb8335e7766a93ed1b, + 0x55d9943e138d24cf72d400134a020e38d4ffab9f52f85610b0e5e678b6ef47f, + 0x24659e5fd5b9d42642221039b404c0940c7a560dac0e780c59ef19df7fbb1134, + 0xe5d9ffb29775cf1d63fc54110f1e384ff63a353331c2935bc061eb0bcef7bf4, + 0x231f3394c59385b1e8bfd5709fd95d00e580cdf3e37f8a940c4213d03e6fc636, + 0x1d74d876aa5187f518188bece8d3f4510ad7c73380c362ad8252e6c61c4cbe88, + 0x22873eaa2fc0f1d24d83ad4e8c090f276cee48919965304fffe237a5c555a0ce, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x1cfde7b00570ae56d610b0ecf469c6d5417dae9656a9b36a35c5a72dd38f14a4, + 0x1a5111cb0a961ae216f5a1d83ac8da38d6910c2f74475efc1d49a8e494d161e5, + 0xcb1846e6664d919ddcd95c78357bf2029b750dd3cf02f4731b4975b4cac64f8, + 0x2cf7d663f92d7fb9c20dbd49208ff17b66a023c460eef5837a124bd89e3e607c, + 0x203ff2de4108ca7567b52a45ca3100b18c3015afbaa01b951010a46fe7b3a2d6, + 0x2abcc429149a29c4015959567a3aeb77ec781847dd62ce295a4cc9487f58d2e, + 0x172032b322c260b66b56d12d9f27327bb14859be5cc0238dfcb9d1f3a8a7c424, + 0xa0e87895274d1193436e943de47d8ee0909c998fa08a714a375656872fc5702, + 0x21eee81004b563924c0089d162a2a0b5047ad60910a5931ba25103364967bd41, + 0x19271e4f9e7b8a7f54041ca93fa5005d76e5960bc6d3dc132e1de6b2ea072329, + 0x42dc1a29bd582fd08c781efc0e67506afacecfb6997ac871b203cbf71df7120, + 0x6b8d08b07a1b58558a9dd55596a67cd72960514db555a0c21c6ba29fbe1d563, + 0x116c800fc674c2d6909c1e55568650ca2439ce3fc1ac3a81ef5ad8fe2e9ef30, + 0x21b9ef80d19679af571fb185e6c0eaa780bbff382e8bb7ed8bbd342c40aeaf04, + 0x1aed5bf3d3bf68f2ec32aaf43e0b43e380244f25666254b23a0321a33a6a5840, + 0x276ae4e84f3446a707103550805c52c0510cb0c2e253ec32f2fcba255e90ee3b, + 0x677e26ecdb28f20a7d565510f73b24c036bb6ee0636010e6bd2654a15ce49aa, + 0x144b679dfe4fdf64adcc33da78a377591421c486df1ac1247f8962762eec6353, + 0x2b3e47433e01893ba1416ba93aaa4e39de8ee93f6782e1b1f9d709701d26caeb, + 0x21007ada7a8cf858670017f02b6f452abbeea2cff05ba63511a32408bf8c55de, + 0x99eb11c109ca74fd589d0647392ff6056a100ae0659e60d0c34b9da3f27365d, + 0x256f44ae0dcaebe716aa9569b9373053ba6fa022693bd865017a093e029231e8, + 0xb43042d175b108a0e9c553cd99a4d288ba1bd0ab4b2cffc049bd63ee949bc2c, + 0x2820651d09922281a40505d755c0951dbc15977d8f3ac9c9bae3929044039a19, + 0x7c75e7a56b94c4942d893c12b0e8ba3d7ca49e2435fcafe0ec9fdf4520bb9f8, + 0x2407140cad6a6c1d58b3e8bb6f083b3d1ec411228763dc4cecef95c56ef9f801, + 0x19f6713df3399cc47648b497f80707e11c962f694d9486a1884214d63b1e2423, + 0x126880836b31b2ad4d3941a65eeb12015282959888382bbafb662ffcb146cdc9, + 0x10f48b8b5d3586007a9da374301e5246ab668094850451f601316f889073b66, + 0x2b35da385f9daebfec630113748adcdbec531e80323e00627efaaa55b9b9e977, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x413c2aabbde38d94bf1bba05b680f5fbeb526118e75df7740e03c6497fc2a93, + 0x1f5a1a9d111269b8fc9c4bf295f95df0068a17c12544161132d3d06cc6c28e17, + 0x212d07b689f77ab9b11d9c58b8eedfbc84a0f3a5c3d011c43558d04096b3c595, + 0x7c689aeb8426becf2d38e8e501aaee897c6a9aee5e479b40bf1b84a50fee324, + 0x20ad507d2e6bd8caa8b7b879d8a0f22b037fc7784994576a2053e173b8799f6, + 0x29a7b5d1df34024626bcd4d01586e1ac5addfc06e8ae7e20e4856705d6921e7d, + 0x1cbb5f6c2ab4fe1fb5e81b5bf2c583b7f0f6a3e23f51899071e6feda30610084, + 0x1ddfe3794bfaccff166ddf4fed76cb5ce75606b016aea81a4decd295fcb73d6, + 0x2b49298bd3a4415198bd2f444de89a1ad359aa90b14caf77d1afb21ce7a50b30, + 0x2c10b2b301be57504c8689054ac301f071e6aa6d9f60b9c428fce09a60acae5a, + 0x2672e1c103d7a3f8b4f25389d69b884d9bf997dc4caba63c15f4ae73f7db96a3, + 0x414ada0c4576f5279952e118e442480aabc46107cfeeda9ef834410483d7716, + 0x1c20492095f5c09599f0ca32e7df69be7724356280f799fbe074b29870e67700, + 0x3ac96e8e3ea740c8e808309ea5dcc35d62ebe5d72b66c239d5bd07be9523ce9, + 0x198f45a7fcf410eb81a12e1b309f0f95abc6608e847c5a68e3c352abf72bc469, + 0x1f46d6ace37983cc1f2e530296fef1142b1b074c0eb50521de863159edc3bd7d, + 0x95d0ed6735b0fe101e3b7ee0586f060355513c443ddf49071ad90dc1d05e4d9, + 0xb912abd1261b825f9e4b3fba00f8250befabfceeb00ceb5d0062b71e99efe2b, + 0x2fb34c0ec0486f139c4d6c674da593e2a92dd88b4556ac05151754050bf7870e, + 0xd3eba1daa20eb618ce265bb1da966997f4c131b3ff2ddafc0c71fc035a12f51, + 0x2364018273755eaac29eaae7e021dc0ee1e87dc603656b32fd3c671b7076c84c, + 0x1f05f9d5508343ae4597d0f01502a1660a8e5975a4ccf5b8915712c4e4a782c4, + 0x129498a8fb3540f610123f3187faec3fbd0f49e978dab3781e5fb0b117dff678, + 0x219e082f6b2eebcf1de778082e847881b9327f906f9b8e27d33e9ff0c10d8482, + 0x15b6568d2a70fdae1cc8b0ad01d746ff2fecba144f504261995b8c2f116780eb, + 0x16da3ade68d775f641465dfa1468999906f61926e73d3e08da7509b4a78888d, + 0x1e0899f2fb6d2385316656b5e8f64867b83dd2800633538a195f6860a750022, + 0xd5c49a0cfc9aeafaad6415787b8cfa7bfe62c569b7d69552f4c138b12db2710, + 0x58e978c6c092939294d1e723aa97c2e6000a5ca187653b0dc4858ceac8d1d56, + 0x188a71a52f914ec4bff04b742907b84cf6e1c57e855aa0097595f86caa7cb23b, + 0x2b6fd7bc3a3b595c206c43daac752b765a12255c37ab51ae183933737a8b8099, + 0x2f3a7566a10cf8d3ea9a794c4adff2f557808fc43b07e76fa4c61431a2063453, + 0x9a8e3349ecfd2e871b454f2b2e931d41dff9a96fccaa7ed0cb60361edd4ac48, + 0x6a81b30ef222ba0b2fbf14165d46c175989d325caedaf588014d126e7585a96, + 0x27c859acb50045e87ed4b70aa9a561acf5fbbc8d0a5215fbf0c5d49063f122be, + 0xe784382f4defe97fb1b1053651feaa5002b9d1c2cb522a0ccf949d59ee596e1, + 0x179e84bd06bd608d1d8cec72c4d182c13bc7d650ff510cf2b1f4e584eb24872e, + 0xf23d189f57b74ae31ab04b76d0cc3f67063ae1ff17a9648de59cc281f54fd1c, + 0x1f0d550989ea2cea26108bde473296824340fd2531a2b2c20ac14327b009d62, + 0x14a346d622c46513a5da377f73edb803a705ee18f9e447dfed88d5ada5ede42a, + 0xa71d5e77eb081c8570d2601466bfbea27f143f1b2c726a343034f015c81ece7, + 0x11fbd1c03b7aa3a9f5c607da1c4164f928055cf6e2a1272506df242230e9945e, + 0xb5dcbff27d668509bba8add0632d65ee5ddca9bac146648c6caf2bd09d9e46e, + 0xca07ef6ebaa5ffd1e6f748cac7192d6470b170355a8517eb697724cc1c3289c, + 0xe0dc71090198288bfffa79d2237c162ed9dfb5354c532f2d6369ed73df6374b, + 0x191093f164dd4120c06ab66dbaecad8a5284a96ab607afe1b0ad10048ac86920, + 0x111d04c083f51a6fdf87412a537f6601076d61f435094ea16946efbfa4893e97, + 0x133c5913f25ff5eaa860d0318f6a4b4349fd22f2d53530e5c785b70988a3a88, + 0x8875f47d6f518c8c2df51a786bf2207aade284067228f440e7d0307520a56cf, + 0xba9f44a107a81cb23fba66f2bc34152728f5f5ca68406649a7efe47c9473f21, + 0x542832ab23b6c7a4b547a1066037152a2442e998c5381ba97698413153ba6f1, + 0xba1f764367360952942ccb6edf051c8f937906a816641e0d1e9e2ed26906fa8, + 0x2e0611fa4ca3985d7bfaf512f21a4081141f4ed0dc4b022834d3cb6cfd8b7ffc, + 0xe6f23c0ef6f159dec68341a87830fb864b6c08cb954a14a2500876697897fb7, + 0x1a7a2a4a08d87e75f720302bead7ca21c8f7c2ed2debaced9b8b1b2da461cbc, + 0x1d8005df48c8565987dbb442b482cae5bfc10ee486ecc5b670ce861345979d1d, + 0x28122254823f8926acb7e98f557e796282e5e1271618858e76d49d0886da16f3, + 0x2414d4aefc7b4857df681328e68a582d23b2dcffd579a8e6aeed6c61050e05cd, + 0x2f710c72d6da19c7d87cbffd55665b472b0265d13e2326a9a33b96e95d3746b6, + 0x2e285441d0bed90bb41d6480836850e4d76da8211b04a236dbc7c3c30320c00e, + 0x2964901a2b42e9aea1a6593662aeb9e12077a287434bda4ec2012e36a19dc95c + ] ) } + // noir-fmt:ignore -pub fn x5_17_config() -> PoseidonConfig<1292, 289> { +pub fn x5_17_config() -> PoseidonConfig<17, 204, 2244> { config( 17, 8, 68, alpha(), - [21579410516734741630578831791708254656585702717204712919233299001262271512412,8554993601136913148229849281645942416873068991157116548355045570766869071269,8349770263904395404819051886764727880530744217762197718931556224723090619132,3123463970516625956994178947134086868722089624251980030957656091366977385793,21442360932957798040744480141231788172382126494033577704060991460078536626315,10231325350034913697901001930461380417506010080725776869094346614943052057882,6920436402694617694727322082450000548200664649231576891284834027764418393590,12792717999817516574604019538349201413861750406724026925198874802923611904714,7319083527910098850218832163004092895955809799710817531274971443221833500573,13757426179233640966146754686419290630140910517321420779897314617147307309749,4049033549996591060740078431987567671358359797940903000648212935570542836589,18201423118137949240970920992151778204900119273029679711616513196892916845798,20625824460928171809204757749985517429359815439093046150315733891121610507133,10457729085307334834523167401466014435492132985358294006123747181337070073721,21561527744019186913993064335391813055903937050713577176254373319368609289121,5599728995155490107164072595052340911357670532131511292391179640158683770855,13966745298956307615009517188536529139238646569224392383446375189982202020807,17756603569040095098346793596909383204174838953876788800894937537311312048006,21742079076354402484587060728532755692106347543073105531119578054037775042874,11100784872920528132266123983509067070706469425630493971770997902694662926998,20400085312205960400585536190272432205634747302273829805331461533195763963464,20028967251238446138082148432746545470729859763361092299497853989733022321309,21646094126368547381762879012999402861347883442032865497835121981839683154574,277256790316883617863153728392861425598900309956876809085316502674092638050,829273940377701999291777589563653090200708284690056650568100074655963961702,4606908934947031763433560217361121304957410936748694859993455652227072492205,10769441872728289230396615620861141176949118733537017427393172917499470840245,19521824504454300285368889620047541794275889938757845035419559810899465345698,17161053048471962353174720811774420740284389196847515292313979813334039268748,7908822737820790247231631548479205241063360318010733129560952138908448461427,4877162162397125215823403409232508291458423909077159953565289381413423118030,8487393998302601588798118543133789294087935184558260165377494640490662085979,7454433584826937164880257351721993831542783218228578962943846432869272993591,12600486335574416961082984651671003440366178113351945406282261259087640562075,229943091042136639964977508364517877844589816262259724739584329059854831474,5964363464498190105797451630207382654570897906930358361814931706994649645813,15027885081212300130366181566116370954163923966760653842199145107431036749190,6389712846176883524184535452348872799769012323597964483555439005016828865357,13050625522428562689464418495099691361897297012535198348448952952830181214686,1457960163867278804802442802649716001232992897386781587117754753421449788143,19121642548533119996481133068671203033851078573250942970641264441950592334007,3319626593342830359906793887689227542493167081286725783452961782138075389498,10182025658554317340763807114890885589336807302908478511429803960136159439487,5258867553475471512860996445670851629850555214065072419972647507253648925387,17105844700483111456515253413030059462544811526461544189616915804056937372339,15389507448590279891790879860335127747331525679865083633840630125275096453854,8628144040598587326275852302297295030455205882673458629883629373821226515849,7225764039772127797033872800338173049227188735693607855118081892986058306767,20070937673840272071045130712690506696769042932336737261842298381743641619092,12139783026483217581244209544149124607538399031092603229603855979370010147969,17581810038009568123079980574064070648109195109589787948955203592875730952957,12141791671600953962785570868053442402210784762014326945761482080946083167280,10216251141439191088257104654134450392253712707713481968388586155680061818083,1414175852848441331935246181908753253333655328715371554777242869802352097003,12411223399258687363418284739063179467323133097416451119653175668156302546282,14163252864986479721057694562184281568622251449154036885135516034438034547025,18935280158362457804125825095786762216868621594409914695877661895590787449138,19612073572528301850608997760721508284827614275438129248352825723957284031526,19819295714156197944855748114967530774512172286810045467127912108030396642179,11371593776080642722788656520803479745110058361122399788254568568846349693622,4027805955664709942434150181718117928301673452282014923837288829996079949500,12539691854417510068939338882045915380674719248923282579976372900935687263702,21456335515466708235982252733061551106892811579323562996977622319059624115114,1466175641997386496752167837552521008018514071345728218669064866303097231258,16954396739281784813954958963214415095472216566673098897333193147120371509076,12708223137926559496125521072416503266378368566414170219615449248989766379947,8788739220646322755486256871812144068464402944468818647293944655221095435821,13058732292597055849703973806172477675203122319912563406670103404654094386664,8931344638882118593791237662384261193166536469680242356398517062367452395384,15456845400516927354313637168726345061971892967841823745636300923188629474327,5751588038559337581650296498368532807067353107651773867820816744681643949204,11549544825319477431118343561134281237789591414423676704396089395115754641434,19234147263577254818888926168924920479297919454657521855750553715796101778809,3648349134208466654728357812767145066715472797730454946149007751312314206222,7718151953117918461425809889893754434608769559584222279828239292761893621712,8845522739821256867897474373924647700071798803600128774472020272335057310062,12793577303328701474174653130332291657457728764837263636620978444987214166803,12567791764609503071525053111715537148465248715927771041171097136254310005533,14173284996087186652368776168561110401474338255050963923163796413857580470909,18034666979500281081740131331708674377786999775618310647791265825609322054725,21422354834639531449049641141105504766268284938752536446702823580190877745329,10861911722118463296713372205424749768917665229584553370962914232866310912045,1426840929949909140164228257293070123281693940796332643637029311310121856472,14301944441994042783232016477141675248310618781100688243801831318561916576546,8689261616262362847656173161257424730101884874532916838450695695508844076137,15123977840288488307479771803223205244132730982232338102604391529168092315901,14782587644869453236501780556963556761570896168324364501980524203741590116061,20171126664277707857959263654502050384578410237255325322075457593732181023858,5586442008782671473934242848395070351077466917106669778054075503048330770950,14893034316669944289540729978541666240683450933307479859464390524607307041597,16358386602267214062406516556279496593235072850353941542010428321612942609886,18848866854232312978702044457572917667782740587353338084332267136131275700603,1579215194993191651478809349088803658155969078580739214414910140585581589538,17033458213089087701892498495271710586197475793707993846597834001983636294290,12940326624292849673877504632305122955030021835426715254781235159065401203407,2093340797218797584680567638361507396244460243439847174481303012347581894177,5964973748129501579884254138099588668727348462189690734364404017042795728252,1674681106235348685135834192630054282175690835155947917214719741317698144031,6021317549494232079997036595203156655990507346855425821696978600367848015237,6518804338080390019586997346732962982860290823548982950371646893604360711024,15170463834922876947772409926040699970156014460508617331830728121385518919006,15398930479669448663557196733417026149527004779216987588229439497346738958046,2669700622596766237628533802450875322874330587389952384417956610466102910333,3127548363874797616403801375102757494200866522631068411037184158214286131549,6584403272373574724590091428656742867168271029343425772452216864199113551892,18683280795877134163038651063011198948877602385157504892093537654399764426518,12422086496748175124620724672115957665892586761203533990582978803368996339430,9745099390463439278844126903162955736019504616033755299630228960871294951628,6064302059807957253392579676216068692721552882853761726090911957467256977688,860534097291826421956520903118828583111860517568849548148819591113129410233,9809207437695386100460912579554305365027175459186390700555141956544839955242,6576375143489291749779792018893403099848704832143183847385791291045583986902,2551573667498115865454648920084921687986702958687913960418526064766186248697,13043550024569409591105305093191112805611412364703194793685224224072149855745,5369051621601119248797945023525768932797813569336410551989722329535217332717,10399989003670197520503648853627144005300436598931266893609225004624861627954,6159561484143246751423457452493034991227592994791307133044136210702400602726,19651431183851896182934111830326153107040303776630454129626690653306388341484,14970612719926241839940820046954288242553272322468930717244806728631485407526,20461999502486452961875044483247881758853878278954851693532423676388213697528,5016750536904085805050275769221233811927007383797241751325050175740220466319,17316427284462136919522043989265881044949832745678035885743571937214912552561,14932533665158850512241105212984927846164589888111067103835286341225240509742,16012484446855626574765806641361955141820105388650596409595164514899481874274,4863651915422513654068087402811690721104417928537042800794511645180712743925,9478941069339421252769300213729433894403874553023597073962166402867140590783,17529734771936454727002429801459948360484278991049231778922771896004721758963,12672015814840095133854330679674924244657276110030612294537194913437310163995,13442667219867515606432268873704321985951188504382080502019480975401891351960,9346556839116407181813364316149756946394621057020562307256030525707411763792,11720199480542613604905913885140886560194773593236018605042270421391171700142,17713550818981273796962302212731756472046580671829192490772244177376146261137,10658520565101402948486320613747540160084586467440232263820881394770094857487,19120553688581692745126354026518291549778059267410591682456431863134002720631,5837704130879353469974552270945063041776968090189866547252204737075618880582,10952573317837731274507039100853076769322123807364252392559268333440123751056,16175443191562457274813386127054957574917457114692631929042817125665307085782,15651399869272720599280980856510555798668301135962902383119739133368631494409,17982602271750585864051043003255537160144994845232276906099438195600610259340,15564417296959768207318803300620712620729991326343744282367518107640962243181,20488793123009381941807231432363887878967153580282107905075818200161452173728,20845615892337349138315927113904389806784179140299978993512007141180651572609,13259443846669565093311907999318849863250202720247601058242623542433998488480,19583450200980335366984605451914375573108173291577305129314361755545713207859,838397221216450052117952481963960818729311704107008458344946293696441980221,5011508169974056046810100610889953041631883487165044189687841384459345302746,11361142794005243853743618662384069287777450724025651283005645149554307240000,633456298666951303063125949977139107258301407861096110769739192555903857431,21529743295731761646584336858048296237991767869832124757149704140550994020630,658601336565148638150196750528474813469384561163113116358457661687263150766,7199686023207207605469992040453620774208316115852720699379826196410259893822,6694724393708237460096397340665472114749949954099504252044742926933353832323,16157341357004248687598290467887486980266976396840580002635620741183071441576,18735931046113570691341052792512856145472697573166865032702507242384749856515,6329726929169898271848965669873324332951781357803010027329026944351232247476,7061209522680426874403579559245042585450674594552752972115778072823155787614,8946282535333125111854282749852344921885511854306802144459174056051518348720,3988279129283542026399878866455129212655792613180690875708855315104446444211,19788373916759119069273555853960393438264058803290744373422102428664987314058,14781179276955000841116554151929609467906998220188278865550170013658249984549,14439714507608577761834821622197467839862763277392515730094487176490304118865,7462417821368326183154895363497223167855553631230374112323789393782682375855,14594890619141141626245598750050255728680683081531253962411791337998057959565,10297822643679438597162031819677962851770740929826506853838015287832878785074,4231562753232550403815225933022904310027433526532932589628179163940950572874,10646529230382575523755302352793337142051175018996981972379640368359926883275,12164083461947216214412634084378451605511487715584004827824972078192861740778,14686738730377226817976749475359230017849316512373192440082122302915229733394,1972065207953025646946682878392649299678417507238551179215236414492110157365,2596220810659736571653162812588827790612138851645327014072494893329877375848,19742890478753895876191378843357325113803569368242719397467948082842949716134,3057722811279760312017893583084211485332195649925192440822130571411021625062,5078380046721228959752000757775271056076152925648793679038634805597314364689,13994065550182407605627049394529818937411332791332501915425485445970019749196,8718903390300613451595895490522223543548941022555756021584328963874682051659,2830037047734434537263368457077478915382396457133799070168011318577509852518,6351328336589112831842317252922662854527642572646149728733839010100363641064,2326811025141337415486606567159001979990362270551911801543813258783748664928,20631048108966815289784074608382072458460940973738551134226168800345554951214,14721204648069833595280990040775556291988674304257774357769088964732410863991,4551815408348203166379129282299441425423743023821112768447969406023780214645,16626589364834731158131207695359287961392723773324953999720551575045565560017,2119119902895954746578148914775899257881351646176141505001582342610666449702,21198001320003994532825962721847645202213745138854311312804244693213734456020,16575653563112300802890760228610449333758690368857078853765813869752023855520,19662199829424784148957376290310955285339135428848477356788149061587904074636,14365866723679934269369638167309959664282416562097092385771370076826961535871,10462405794880410718710911820471224752218613463413073336296570316774568383223,2875852545895825315521599376020869827316570932962420930916494831426174036683,9365014190378730240070787324401488407601702337948470069729769089736757502613,10207664772554042762314615033378156185686480986853035052764356129216234339601,14593204638464636358074700677706356615788934459664487787695216859702024204802,16870253735699395936222032450057462746120274245691549241725232755997497777650,10403141045354931831897350467824057442824486714796947030202528195269765938299,13491630075210993306306680088269974619065901790274179689314972497025507972072,11737690900303251277784941365088697342741256105580987740031964012547987099246,6479411522140791199878732386964631711912096436445632282256505752750116503021,1083921069605939352705123162314489784481429719496507658938926140311574639372,17653617267480348306435879910355154811805166995916787026122631473598046826333,14432164328022071373295386637326904766549408251892516429892690428586807444784,7793671760657336901389781721891199068620856343884708391197481940646184551315,1959765449995198342923438542063212054673245344496347360855620191194506656856,13782621216902843666964879695291399503179812919290969771526164415604545126461,19078359557987218636232226316587656499460623053969287998311225512418446587303,15876205697805498189610174935234268016677320029636416200517433249256912037787,7722805406045443730324325528663888753917114626390901464015754094863680930900,19209717507699122245389693034814796437142853968464799877186934474171699195095,6585127313235216502111419023607202115168882276771320178943546160044534358599,20805733952846662054565520828206551321957145521190409450891077526078523041277,1584895259816785676773529464055176663163421450657396866598813628883854756221,20856003384184708896097189495372900159489733605505425206950257455550934589790,14069406225378546242129093232844103602751521581800986668621079503726397000027,1028001874294327945398022002342466649656159450229921471622913285892988310568,17966371882429795190944428324003030336630819228004846253694564940042988400820,12876427863944186509000750451848678588143362805691657085788824358176114653258,8715273966427022806434959651283926754916348745411538421378504642158804932403,4267431569502908019256597205760133122178817596876838981125845973819244098360,19262568227942313166139131845806786518421402326465887345846202580592913547380,4587852954486808043358798482712674466376898718708260090686361850306798447997,14015025676058610927837367157870446606501041323636097276737547710444897937611,1144137690247115846969300874102656726503285917182531654472086138598330367043,9454537148137071892124156670991734830383436460928166061331273469365959775909,13012777452486288707879402995033258068339583475193898659333632638157561913335,14224623168753818289919819482009713832024545924040193705962378465158371078837,9505762419233185123340587169990814384174703626434894051560218285882560747356,7019256137023476309554512440166531052657689673592456244254319500937647800006,17246363017424260106221670693985197925080671704985089438076796011281669775795,14408593968797438981684807585445491387554770474935530894938751288467685293766,11991202914737654500568163346559814604911312199759237827422720619371707311619,17485055588733729741263685618351826350652951158142561188142663313955733134315,12950471790443580303905847354051728755537901376411054363054627208333559704631,1323445558625272814455691764419102369727943978699511295257501714917998936833,8841255445674311239873770890653537908142822789956793926192649058263474173411,9401395313777449751102417028930156506880556083443899378760756340424905478877,21060472724780336112168263494706975132712741930000971588397970288258676527061,3812019230904757099892361572360806117962259446525402823615305574055615634484,3514498070156020200040973833201476402797883738073136493951314455793989266387,7030071313560321306345374157122385026218445152391153750375781343870025689321,5268144785716401601955218888231720448573921710587461252164696334890979118029,8300685363844078100354914067414753644670881295812529449763437785519065857313,18450162872081547013081002634376155990252513846297828484205311669445865332085,13292716648615315298838871484647252965100904015865352978197979561906010036270,21013686439245380148735850740480550290335132408628769676980938610161935118557,3221231898146718165495762474085749772444251029483710808533124131909521295435,21706362586702075336538820540433124172473413960581336734430968480142138077992,13486895089928308553329688303040674812803987395822848864346610815697956322679,17668589109420826004140047157134934003621500937594400640720194981334871115223,15183620307048155399117286900834263744557758459406645835780045985078670266986,3170561135789021599641212581208901692806457808161683895582450799937372092628,6919102281737620426489877909256066802544737782816026767549277126151765906518,4002850049662127756373199253004358198702226377235167238172929008366286605110,1107642403321371666617924914652619792767807515753221818405051786669061003368,11885648350895482809772026695774528865889321558031441531978106387676087338277,15378937381250173939485112486205353769964903768096281219667852296031194688940,16437477998115322080973717158007622249171727785394053923880768422172683727081,7621121366936849931681051136134866470312478335111295204625916349299382392728,21215912298727134138155623335764864420030241120133029649046764814328222738790,3170821186412794476815678730429053912378444748965057631248759273529827834502,16084650047636623354069916778426687798588694909600147172336375822549887134716,5100048383300431022278915674482647701788618482574130930551328380700470664477,6089313816847452477548960449234592795575689699536263376449482717087314881254,3168424144644268762342999941888553529072271091445061821545187264931478820334,10404448021076504176124328273829362151757942013323044839630548232003974036828,4252171300134965718003785947840070216898476595813167252439064205515819918152,6217524790069168495104329195931800727381161902791016429835385350530530741236,10144395323727769803680924125110392290775229805005263966394467735634758369184,16773588435110330580333921944382990185799235928388619755745278707444537536196,7377711139925591251943689121143870901330717424145420584097007639933333168762,21066973161927891686455166855433069549513160220938455527728499561969343776185,19501795117214672544349409001236794757366887214419994956397195381058548371627,2696597170314397939863800656320896858584168884088153464800095340021127302558,21168940252375267860138608985225319663694276566348965377356649424639627399939,8729578229953090469373121531954476034394661891580932672218135172268595941310,2843049930012752804094477290180353526348132895187059237802643422297864799516,11477013052507658297840246977078282722343354831202397750212752940967096033484,15309765532985207981165438737385487871403890172460978621511228072457639715462,5276795386880565031975868524294990841634011123906486763299115154863864095167,16891192769456289619320007723900774808412675144364121907391915236424354884923,16679134204463371830386366769161735700621394109825781706069839015605424451750,3726779668847121591477372195002524410424328772388206362047548845558525545594,309779746952337123192541883987405477861316061278735939472746602872146210577,6116943109304762420893019486121829026477809860415070409858407396285217706031,15461534026148460547793521829520247652146949380168641953893161519404620248399,17490188391720816485403388897026469756907238275881766262188942134609165349946,695497190921838164093269283587166536603898439348751059907333515445935240850,5740644431998005711645731796487090897088650307567273144862464339327188211037,2924287064221347495709747210800576855931727720487579410745268421394700507499,14573731858717233227103947986267826915706941233771169473071405909223613015343,7774646633424887132991406013236011457803238614262239840323638862678503960297,17118778781828713462818509847054627300883191299007086864997977171169360843500,1050282722198137586289457046966751947431030691327586256768002473254440863847,13445581272162801515105119436838273760359267729139949483205892441735924907588,18349340856764570254875357271690106769333653675997142444108297087440025433976,4652091796588614730462648254434910913694389428280196479944835477366269369125,131910217723821243570751713964244292677069024546597890404591990585681690631,21456499410534986907068306761035738313492308692998775099405282472250364294940,16716064024995806321979269360595144737028204641252901859053814928024784155019,20095956414904309942694457361888203543242910622115746869354406017074786974736,3757071258857910927294547413264306476593820051587638010209583502745249383710,10923680137512329262337058371790257353876483628009769758330988714085083694256,9956537089548622902535815248396999405593511084482117014020012399528161074693,20271486778333058297667394153786073312398256884133810048721290976749349792007,14016317906581503528126751971528140956503207448983448742275011042750601060387,8746591469817011275278863986926266284079779997046001490419468813462270883629,8984522535046539605932734670718817033319009310710809111062522425202730307709,2799492130108020790397631531338556641981343238572990117018166640120082230253,20327087348772938506861277218558621387616751140016505866350214286146319911488,16319897245400426733698423830406514849234661290508433522979200712395774573821,1519870284239742680329151132587900987246869312347047206488363104123425891937,16461017950418215698742181372949724919904570515241953684108936425007551365381,18543391801737989528567594217602323229839954429370908362237267818290566814608,8685602143546136106524472764079001485875727469672211204721272795643296788175,12069346074371335540240816613547917114412632205795651309433084773115960400274,11988670992502988905175891565316960155103243235237609851490650832292602385997,17403966780192169176887636449182981656483203656331951842717004987726351707328,11324032593816374026994927363702518223149146507370165210922763265919399924610,20234844998585751045105028410680389242420574978256032494303069254030260948453,6845765195018211653702320958640753289098798259762906597713727891164248375213,3889696987737574856084707743921432094490126858489993810406205011091688718490,18124922133262643422852054628088483763756251512543531233603218549062255836441,12631624196128994950514018157378748957581711189609992774676240830354853053921,16425963978111788432975031188568839119447517807863396285900192209489855884936,8953995026906183527591662774513923704717356851383827135468523305945599975444,19118152579552440466145418131293777218789512388294771840750929877489494176003,1815764556579131181044414049066036485535218062641438722387702702907845125991,879360492005214940756250098489982523077085264774860932709313739626061471725,6498879898701797309689806511256248775170834501358785166173840360873803298370,6056271365753495672454589488039784798700896703812263056079587620516360143438,4967400286944517048147291964513981345417368809842939145340090658371340301574,4566978800722351857193060210384689061165216230883853755194411631523409885319,1472717723310974984615849145251472221350601734805367368974791217038995119259,13776027174095858271746500087697263062688345981919975914318610607049564847265,8855093701782146194984545464090688949611436896016570549019701846352658653421,18811023873792469394695147052306776708450724591075344787347859872893669250403,7691358114878791244762289651247071530769998349760928484062499608910793916658,7225113154421014531794800873967433806904006446284346811024995482075131277430,4255179040498688460969978231175134372259939403539293652133247789357971307025,20794639690572618510879417372961642037150870482839234645523330418091682849183,8794944058569076073698664070073889624033307879863301731569984292406059326253,2823363224083068189197562122730561866372340074232470613435703914053034396662,2975786158778622849913792385919164957459418638496064741275725856836606581091,16980083616151411398660130004732794369729853408844917920819260677159874549034,10213122016673910048073131434217437693976054853300442236815045010440415530751,15622844733073950747464963822187537454489639825890383970141531456136711221220,18921846985235911245949818418983694297719932450371747402698247786766269226032,3046395690298904837024144793490039860680756832120703445515317729068809524596,2583060914190138727980083409436742233507882746342184052904895573386721270220,15629635543342892581496645526353345602210475132913669274084203765913418607483,12153931408209967834920681475366877980388294821029465748773772434628588757707,7196162362609954988171353261930756212243825869655325258155368337285953898704,10832344161051287447174100117756887153534049211780756324764320129746636797806,6499757948467889740913713634114407800462786362067580649690672122741467699071,7899568931631241171429470880810625833615306002278541085808972359443075433638,12736525266255297750005081634236953960899087644399368181751506194282329326346,3885354407428541945392073706505699854042913519198595640992547091062316682031,3816703467689192492336832188741146914005957253921702912680936907951936401119,20505128951308490293180094071215431973523299690572491020108425696662802268726,12432320732362421179661978984313902638822551634634152631489842715192622778201,5512525665270220248672390077644266875095263411830016769341860810913920051168,10270457412178462574290846807202840698511884913948623978547229481110915603115,17881266377985198177178319262577725460740518218103427901653715311091974197536,8510066829287194091329244743814121446186389458433991751573612039633575413794,9055280011331581456260576278219343217137015829507887846588161405525910242827,8463744395607465452751391868824103994906876103054045629692996934328842962296,13446532739903962714217041803396024505862416007402976354796893648172348836934,20461627446006946445871657481203161690018232261049944659088120713658680145761,13772437540389795965930455187657216773904696937414401755764626097076342530873,1466290965505206997895149562488255231958570328271915401528301574657737237351,458020438009477539046680120243558779131470015073376206673948106465783075724,1421211327829956939723172049232055433330521137466148179271043779757165996383,10974718981737058413203531348845889514701700275404265370241257111393906385203,16573626183656890049533788707333278060585059246627869841186891657544526527154,9919036431890005168544961022934926297421650894480789723772572215746478261369,16576030844958446931425212176715038836356393446209694437953952981269181564296,14994178560671337822305816896620048994236927709898591331458613992689693774863,14008584724223915404998855561309674162219693188120257826434623735246475372519,1069086166685137961564210887004146480746150199033946836704942515923278172866,4441018674700315637078726026786902627166868710369033622977939038672598925463,7640939046542807984747271754089880008702702616120100267707112408768750045699,8165588904763498143729494321532511422369875008004817175656306909794360343847,7474879615118088486232080639206966699381035482748779385536890548622822072536,9155173050525839883630603125759778497949178563635870467694197797566249638786,1792459779962272311746727109790955426562388793812453852666007819191763428793,20263099395174426853367767733535578420938395109027150658334981283108594115829,10303451485708370514931418998595531573075964003678715177508051557531947678705,20321308667229656744129683025590573929765537488045735596831342276888215355579,3624395650764060579161285692706624195562301326135878674105170566731046375182,13334418042222364794805341409419804498243524763983861307681793920401725352392,6303209034428307796195867505386756492498981454350686160404486917810670093803,13336041503866400337979868539402126587964669853045701517757148479437143265311,18767353303859794045974955054051240567712613481262860811042439117400294729243,17648775923900705033106796825075257671428721760143056038927896765118752472038,21205320334769131061393260976939399463360336322318482845795119858952799244444,9155233455417262996613263565710157090618649015115334735214563627053911364986,4147290460198895367036286052342502315935666580918696244195287512520682701639,20798839743961894523110712994056132446749297094165852697406325453288254761759,10967475255107274575063249329253351284200208982490877243231819333935797701403,11107733429142106765947338633972307528508245023783319424287268815241476152303,1684156923230048092780410733570635056170405885844154942542264956876312136441,6785232819930341498287206635949744381666087373588334711760162570781902812411,3481752771358613640419060374040695972756380958880755418404724590727014534662,6255654521236333133437711371709951475374611142503566953029069344699939884443,9785296768537417566104801168235697242332552358062255540417443962942437906303,932526381863697246577606288678833611354323840639105626154693740791708621269,9020085732775576234837702925603013416533345825301814972240093864457581450960,9671990085159642158315772309293609967281764349933520964615615069622307368396,19046031964146698646372035717767563096934497588033260517438574042056341692955,4697021545834663993102099542459528774847962616007459562129439303924850728783,834623291329335140949595387679815012162663877433757180177587164505466461752,20037517567993747767719709123741990248999315495577556924410214834773675677458,17745162106287481150568322325139792027305354960331855484108228857447789511536,15954503136290327680020013900783441236098225469294487261574644367048211928766,9447580075462399824000861225221012934395732074158377365412928734066137521046,17638109886139425399034325504572336884601102137123870982594354109676619973628,4210479489522190727435015049116453108500323090316045735249662201929219316543,774908475070259367041407977077109033779248383557848908386935310773126844186,18071521129238587956292632288468255723364769404447125651660575676226691230621,13782927851189257932376007280798546946814788900735661108027866834341111483921,9061904191092017185731693336948023564331336704118962360596629665269886564501,4646677737877430404232975108246717822854320420060743321121290725024507501530,248089340757097041959106969939801712104654938085655092524027449699183655736,1925061776519306799931873233357921480445138537754738082308417409427350959191,15090381222590604653751344079459745088601676165498775998808367167579158825796,1507946310710275058017347456880204243614713444138569740896198937197257762391,9047126832872244897061755443779135724439127934417426920025891305321906533199,13210467659674398263347498463769321394392811495810195742972914861526145024497,14930790949584540337435206846889685669928690545385782178172828133028677953780,16709614617820458913659268544942181680363927832511699782451755998512279824691,21741729565131743651162167923641181853909251404044798652854243082519505872026,485748276371306614511019734420369335387299906747036897161996666725324275885,113729363155019628451995418785166919308643202089193856958029953269497359518,17315235749721747007692514702872348378105966945192310104719562066051041365785,18164826565342651411070681557540176534582615273713551079309038721773735887418,619154088023795178917549465782795919604596935887112076630902791174323663727,6356343581175745844660675205642675571886993827862033572086056964311839166798,9925861911435596968816749828945917008180837850750226489783169376408872855250,20485137494818996958862809145264015810010636121731140334074571507470008401090,19656735537075233905125360479201796779994483024563540752004528779684256455735,15774243068028338132223253794279808721177740456197787086161475053638867039504,10497591647442850110427658608196767909160517521573199077258279280018098065029,210438711366620938094565498037172584426960275594120406278610962685482768128,14574298645311491089278146576548733364636851707576602363349001846285614576119,12543161131818467611229160618197160281328232851440846538778664249828945509460,5869885827840429160723685065960013290766384774919021040094074809404023704797,14800413279643792835835488664661954863340552091411990276270728475507101877386,8706244411264045072904148746698442560958145712983473320099851020229801141593,13670524729264788581176214636184652482954266319986131183163702474027069017797,6632699635952855355682293206130135801472538218093800086693644923578553649842,14292924690435752338909900819628889644248019746008463256978678218121438364347,17727807116656957204562694366530472131199058877798797418410969267673712196106,11223858699504492688371995874202967948461173433281557745471419331000190821973,15274518373659950909975149452889634174127158243424169830798483206460674313743,7047593141729299688704504157654237466438485917193869775780994636019451364555,3378912259124002728608820025874776626345774864595321854977438303831475863909,8837103908146248796259735965370584845236705198353666155001962958984824353698,11869977356793268256679742068396296621649101901864556682314737356997442919617,16469201342422734819465744813830056682872807194264521097865986969265941221776,12990791567002738838300315843749937126679083554067128201599773654099601117791,20519376488199491586810872596388233936561051835647732260479226405592285629272,13549175857035221960740890286176570298280920124622104651989532035707272553373,15234870385685844193215578943145814211167163612264546132211506983633757513134,18704889004070339618907065844757112006583041625995006884582590095948666509530,2234955996987396568560381823250866120960007674191266942270485492312904973151,5564977611394684319243720881013051542355462582947649518330549023416464959605,1112602741380454855327102347931753030221494100363029829630354546334828994329,9128209482091812367673670394219617423875730198454831896130112252113491505252,4376101007428143823621574836425643116618104664163736787280388345260726375856,17331301745157506574267466700454501468193891305005371065208065202603272248798,21846545094192300969525954249087973697025055955155275797969191218036594965229,4498927631211901890366201669629694821005085404418517058539528045609417501903,21785888954457119007377380145673667061898185873161711282742721281162112687992,10412875728643419025694818649503070798945684772972009054835016566542500457165,10759299704717838172704330861378107927462309935609553476471308013349659622009,20590357061487044454315237834494568787816431390448334652405889873515373283815,15673836157910318771949663697819073723405442238797105611030274826598578081102,21475838557209838850221160141181337897147127057878049055974104365046170025610,12207716311215040854533276425309298962214124105108870363296256769166507046674,11559647355273809434894669847822031984160367996613651160672893927347403624957,591243049503910187533030984285442752553334033673422383798814281778102029479,16149820605774446835537612705920133098873928503868848274855310057025837143826,17994206225397988293963936097869072606400130753097128779836685484696065715846,14255641384045583862403050464134422000560975124837558223693835399889249787677,17504545541397972120376845150557483982076571058727369435414053758625774050033,20262964605263856854671661755299361371513888427580858149435552591882491905348,12438123120680430355474353651690582027160630756728481836282192739044572633306,10986893609190710977332579571229244255566870443973548516403950419251545530801,16087745879258651861681909407049342984746351306967389910641236570806978994348,3161560484131968841565856280480697486595651138902139808256180482675228360792,13935262764632300233548760451251751405084774897832419843437366109926436448024,3163708356211087269300587340868486145250960085863061247671736451529273060199,2135858951319828747123196912541413689531634489616050528404576322173340406195,19499372732572987294622585729244698705235805453794292187854255591946466724248,17894089552733756400990786239277662075181623012822588150546768816557117698135,10627476289794518149581909173158184680927686574280550541626159986648732476852,5936760260909841348473330607703047527686233710292277373302498592584078811475,1671632573007285452120449241726645612097503185776127730816609206067570503177,3240964061357526102193296883771275932317464053465161060634703562592821382373,1379991033533041123683674223861213511881534224092884787544607760074673933288,16612309984678362724113323611405699676953754495433780645121123868554119586714,8990362216544353251183644843626621823440172244041771554179888258848070990408,7792126163077137553546721412284336099138469839853005420022151183726709890605,3411642164274869168109174406711447272755835383047387248320765695217678712087,20744964603175609148844959505361532818311810796853446841217756183414690636777,15406348836110379416850862929702053477202461331674247559909297027963274533036,6655070454278595774182716706613320667767771244472415371150701320921454970910,5387596765852619562692588945067153848362301378074547750716364254552830548618,11374645815567953400996409579523063654937913407852397185357281079289695498202,4637259464430266322534397972465849540585061569384580106712860758129812888983,11664424120893756026105365780051433965998344366144921839621845056675798876861,12683173829762047157652990138425355617601406763777942452461639149511855161467,13231456998217432692837253637279353598668867747754119281167569613817285339906,18515103011277984777089818507163076049947207220694092563937098383351447664230,12292599779221056615130747040145001893088895814628302035476053980079114062115,6616224505832681391261988520162269850555430131210843369761179293711760268991,9345928984249349577886491000914566117062182722884874880308419980252230631490,18529045286534814640266328796625676801335117782021569247528965805503339014374,9213994428894984896264727606602499546795637673535140817494171390234365346197,16046191804660661030536723745809610250792224521907784347921533311133924729200,20387305341543872348027149959300247251122586296441271309757521233850527145501,20660888328716295053746457587105952359847177180169600462778173036912653930309,20868619915262427287234582212448052350184310305114553346457821129256743588185,17663781345821195819131504897468846255222386958594579879767055754372925042002,18948627844717262137578097615546021495287533410031083974644721619152121684198,13155646636245265066188794529431453696019006721019099462642586385520674193264,11607002707400435612558884657345015071868104333677950253781252883531031962578,7814494031495579790510272464332992505237344345380518199394208941034262720849,1133679025909186037940532130396250706184367022550359228793807250960294591300,17684405674061959945309711765066024811535672808158415749778270434181980067051,12226477960064982944626820350420332900927073584585614331096659786290796181633,19811925349932047710573270972607617621205677733103349721011497772488325290731,8648978019377605720004678083600719374811142735403518791266825142192290428262,13576053523641184415871793911230224707049224969614290468646557972152185575110,19246597006093201923867388663361027928531131674594730473459152193253618076466,658606426123772934076319360192555383963003130831902899767201848799898493860,17290137813713243852250776166370982880777712118107986170022122607636402519519,5468484217427333109722188824068218191654858622412608074953511216209386470685,21574260030527757195923820887880669668169386788465310192452085714817280961577,16977301410295947721817774534383483730974509825154556215531376468755351549427,15733754299741726976786941703016488589821960074385924955118036049474131193882,673051665852885808394122319132734442090810198084101653348055105938368910407,13398071607416834058601862099131647257306816396251547336997555114713122083633,12550653745423625869263455159672489463891823157792786197798074997479171696837,9401077435832768325771683033269047231487705804464911158715103022642914069963,12470382814922435426465904555965877134678525017061716145587676176477156930917,4934832010550666003820836613445526232712748207490447572633148755378222021432,10147431980198881931337046775655000300780675339813128987464503437796530727819,568707585724749374908018432889236271799675619271430223486579915440515081761,7940313483819289305875198195901580599194224791864182697672727755313391315497,18743990138882019355059105644701125600589318429506940478381096888059645669064,21390103921503672356366200239425679587351838964225860732507169466542370471389,1162301008434626626179696713526875746106593765970497860274277780972785074172,20866648005214775989252883040721823770262915606193206494879341544251201195074,7345491533727875108206436501195735628498565230546589655556895625258093485858,7625514906338569732343456767807169396379912415318224530910677456500209942160,7862757427463847382674463970373593668082249748547169027835585420099101631793,10678296207725321824311910857643347417220081751912275071080081222106552722672,16952109495603736214033791235849594583684019147749856522239399814261672810874,7275820797336428291178396248364001448190236523398157638561627689896470220284,9969981466756203881447261853491208039919719371961809442805550510895150629471,2820683912350770819480104529177445624170795283688064543451455124015297123761,1768227783012842108298280205661549942041342510905211540896799241998425991810,12106377471628405436369258554037168031059303858931832122655790690193581259368,11133684149892568979034305171877692043755100938665306193308979862319584720202,17034299967559262110637856726685484180103963204901371145115468175393665761738,7846191388095544813700988786315012990125413238605101219369138067522789941990,18501907765236851484806470528611625980973567313044760445349490286993727971054,1249778578878632628279160684089277562912849600486367726058714364522238473984,12800296338215947544269523539435530627816725976238738793426232070819346748361,21158276531398412025848449677754681262986399643402199704435277598413275051402,3445704611858969368326297112584817848554583085326694642313172161045347990986,1096936495127696656709715702297708886712481387809916555366077657639639717937,2595620917275871104056107465860277106075411236679259253450463497473275008081,17133880510415980077665570077127522127719512648188691671645676431813033706096,5074434632642876807560017812171878490042102579785821263047865225182212462287,12326838696626858713891707574688276984801973627108664533453869827609207218879,12304708188533179803341734069046800825101691162690698708386871234713091258421,17039317314373515840113235553933676165005713953680758739139458602566292834442,17138392904367957911746841143250516587142345504139102606501472531272348644184,1667176916358419631869035157338470222219117704099667397276080580945958414759,15905657308104601519308683078473840880633544254678278144766436492794698882065,5818790161586099604498469370871887484543304527772047827828829241332373438952,12442306790659206506330372960358262675060765197848150572966156688729178055833,8830924073341698588202301965823165752475570241349344118304602842583809330430,1875325218295968167735653385555759668710537053646457950513379995102733934773,17881009017973237557824378556848686261064176014957336169110006388300690909574,6685909350747636031504999384308339032316756393531361646826148497177153343308,4784523754559868056092042886072700730690109555243230003862073871950864412709,3579228774281988929604104014107948733265891035249209872698544379599035221295,4279085918474431382642565261103862932684902464862097608738233691705350921017,1137759862158982763491809087349360013612105180026300214422560224275715429456,19720837769260646491270657488868445833170057293472427873975392955686128702328,1718964391395646738355239526986888311027176887298320241700031309916500343965,19881985451679395586972172156300827725375888727627109004411614649624414408826,12172287315747539949563617756773178635584674160408496477097950831147264075213,17818348202724817301996509561425729131915819248800408750587580377834731903089,9526094675919376961704973755217702642807170426879590367299173409422751261551,3828510101756167773639196204933352052436416699730184799283196091112205339599,15234684891802383017182920097366274346299756278272648689423306851279308385365,5259340948631483055118623587523845455777103002480150827336361752510452569472,7522204711834833179288206454714805063533565847207420606996829544233502085239,4461024416231372224773966846126492961855795819183621636555920813846035684924,5024379057555899833767820321243484415757741022843259764504133153673503667684,1944348388731771850836911827979470257687115271361319233348322098245989069259,15065306781743278475238637320889039722240861069687500843669623160807616263519,10185565710140214717926900268233420932083773824278146477403635012592608678058,633282989982188437228855410820528038963373266773393154835968536206352769131,15070609296388507673139787908428420573100959040320412658731328587817279331759,21412207865606943642342520185052032190311633739645180935143927525277916223829,7878150466166009547688919693656375135045159152200952621922018706527536944814,21647238538593110963647188691796027858369673773306895927659346354059471769993,499258196791436830394876102694379667868532135110557694409916330175138906869,12884932140229984175244344672594504633237231438569204938753218905028898420879,13897088195397438949124517043146998392030835253375096249186075371152838123957,17292635307267344947001814307009165392877577631472640481991264040854674668918,3402459730835246576414179745580422332982133349475000364518392993042878622965,16196872248846772839551997397431726113069640679308998300903092440097004592538,18016286200009868237596690430345509415593965676022902141045234608328285884800,7857847074246536045428962801424396151797565515320554961976852417962849298458,3893665144753462156875073379241733664547431241880239458489799597153819411492,13248007323269384117634056450668957554780628822533632623855150478480951625390,18276875079677833610517929467816562761552054119550676368999897123627796943528,5189710327122023109841696471286837143455102090557692433286249568240177726287,7945689534444199447942235389147404638251522098536584100372965245456120158597,5423767002711680999240727030908088708424949959926318146878189397264151455693,5995072902526586585223000514086044396450113354893476089124870631086600489121,15275396095782853076485751600594247065910139735226081476243182046971110416839,7337085477458019807945256166142271568824298087615645600806448794391563720590,672727225441339286039441508031715798485173015033624765579287288711179551652,18686118639158601820164163991883068337953517102808111440802394108699280438488,14028695600256037576881239065837481650658243799767033132853744776667874365505,58443191205451688703601063117164997697541381759347793811443271650169777861,21065693836733911343227308560913091721048742432913504195640605496691788221566,330731975523362608415899785414131718097488715216703281999950906065685546389,16761217887229483694018038191674783405871691887163059178481478503168342732832,3038029821773816605245101973977979223409779873144308602734440877027458504742,15321291577034359343843366677170820527712726038561116015047816977743924220386,13707411308735348097061010267850476217721836580681738128758120478182032058809,17436870236156178819421588659602200365388268058796067042132167176029472760360,6398050943215095842335686342334715469621392080870897191300696782676608765887,3437851705781701539278760214561262405409371984542409183492392158766597659391,7124479506211457523573057217353911508610466081033238660465711588737967142974,17234798882124088040334413616145917195326697085511927239835381731514314303940,7189678840883577982600011373449005624085144056595391210996212544957416984457,11759897219791977703855743039753523539327151517291958119140418872939095386327,20863399992661754827674386311991156323060622036945800022666816987897813665853,19303856056826570957071409328135004293560711503205766767776395391371667771674,20145537319102686898024411390314804436660254524742986363357188082440068405993,10703774427752668974576334932100051927133058205544953271144849898179475571339,18572949224433194996605971200517412011627412770605201537755920772491000856992,17216568647787248412779004183002114283399247525457054305327730013550616639101,1149230406252660804924057240581611320485721839789360487426995484240018883527,16555038770640675528229594153638806495397639088923421322231578669556920716448,4570242682115771574920314226681534421057130734296724983202350760375592356599,17057311432878064305365984063315754288324488570316135529616408791432610322138,10528094520692277398437810246572829940408932590689365643375030258637643836256,18372709972473962897678516007961361205643396632377488479769034609756086158014,21838679058944462510227588871439974934573578287277780576996692447397949481484,1580935194501439869947304184720525369376830253681649968786933642354687903995,20467445367185359735288490209436765649401864859115524728703996670394981839178,1991219687938782033642326751499030593324853839359574632972633310438247709458,1439755133435743273361732699887115117694558270034210455263872898360142260289,16300147327505011303454000556020917254890545519131742846543658162285928042977,20520490665047234670156871323008670381517271529350180242819417364083994994438,6542862810250661443960454367170533117465189617181697143331232138215407738369,1321343667823388542880641322895423041177577518845790583045290901719235409147,2442599361719607622459103501177302579953568947914600055748918886479950617614,5868547468478431065596263697373807107429411676393246849408309043501871198941,12236312006031079186182743334640941452854376343312535021115608217162266564748,10096437059927455034494932369876021874913717336999122002472353603141122745838,16855287129299048285700210681474924546365514190517193678115189183373112094664,11157210691115027557284750949314979990011151769293562411757900634452166569473,12647512288244490046752876853167515938997386483355090398954955982145642073003,14545106158760908532417185649648478400561191409850112377631214176889261943702,13380884028176250201501329354617948687842379239413597035170382200236519084210,1405533288610146305353614064658402594063683037599662723217460924638972391780,12520645345847038927033831419634817247041895425958103228961545058464030447700,5466316270148149873459535347452815877745317540692907701390798166221830387727,5692512917835452114275964699861010134159019192212203758647174343214228494998,20406430429993275527714460195190469680616300984772360022156779114506307005915,2464398587529067351284637471629204475741470377175139272463319164375422871700,14514168707742420576792107362849792246555009352726620152895701096554575857830,13270866810108509432782712956020266539382253503195894711776480924657007904548,9134846497886036320932877977667565061646780167819704730891157458029677347762,6968315929580902986583144026090679082271496835598861747834541738159673277903,7271494204378938515839411341192945686765403888626619615653078042877068436796,18286507248612017881101512297381359645934672218434256889911439358758424747545,11110097749119198784554144689049124335810208369471373426127558546444086832925,8247301320031025187145317669710241636727060646792731418249820159438470005156,14294937643948997192288252800043984341826315689719836039426003941357321500134,7348709417616598268612977306891011618520420209855159927526151677200518293152,8241665213979757536094384437357490949853796937135356315008833005380426051194,14613486093064180194908604682667542845871833534699460114586605109597063839130,9113009852475701814533040575255279924173382591876828814441237692300104301457,13165038554179369948431676356672208670169443113631826535771459184335356285593,16086269628133108266869931705626389777530735876369884384351431845165268738278,6087260580031589238539099192443153008156470383537608551794229727048294996340,20512862830064709642749702619534843169107182362836772285105007708471619038567,19533181397104762456673826441378799870077181112746023293729567449839481548356,14705683451830296925170674619865205995188883759493716060771015969186134607704,12605792817445608495860292975716815181045267213200470818664710066347176280047,3592996587655107072245474938139935892949344064921754274126873928977701118749,15294232235999070733030126460937359944041996136808334336982336855120910512334,1582309023481075306597300823293668340335902140969083485284345214470852671798,1088465469116422019323930771299807477223547422484605269302564104323452973509,8883047416031049757538663266985855517015256170002963846635310997205392683864,3176854208559033403336658900147847127925792493324423188639056424099958393072,13232382305984866276823393930594443402152224642505744090163285056748376747918,2245408257366834949733190872330311995971080118654860159924241594642495281059,2379830947280597194685159865267943843813010731722978284837340564719341924509,17826177593330561305441136255554046830158210141415356927118963102466292013052,8247294876117518524724460400399686295737179004092227538368916244669417581296,9784484010004736296495309204028701732510703011300894445280176432324640320289,5252332428538395620048044694806285484695976570037776918613895482295008833982,14121980677685920870338206469007772221567007585360563336746921691628879549127,6873280017888024918917070095341125311616790755139638467124027157089622101088,11318363160576645628856748485098328456894971803038601852118504122294284627221,4121152361595345093207401693369225144531013563993157593094962034269624651820,20683333802753484511610127216996129924370396812165897253170891149253939360760,18647670031404843711327708343249425853609227031502475411522973225042672187860,2086657429367670063332013344180770222302417569271803215009583482264097874504,19709435480590614483363007409253356879041585154641286906159427713982563792526,4258866914660942354120395242129829740747833749509017072799985182732656616800,9040566395371463976833369354842616182669127821598268274888838547664814843928,4116084355554837400529216189356527577376881089426150781634827262283154963048,21605169971906188704396331617487188526616554159276096155817564565239435978416,17937211187232154582564924643486965895957558838414375726168318393094228123633,1992558685702604567028071709121593075020313087150274357559040691997376317338,3218330818271934662263059558699096796852863135305095433439395639068666897513,9251019796910681440348368762961435892628247766190360978557679196269677702320,15836693249656382763970061319175857247542072239256868703809948219144542014793,15037961154776922819548802422798270596812938540093547487192133997609110330498,2832985667948889103643595801116542064299718867280064733138075131374461684249,17231308893316371049725716015653771498326104062757761825930828499226120649063,18440767123713815329857061224743112764715289422724359826699690594664366648275,19107308066370859685275861140608997220650596581264375407813390731366162034891,5404929079073337935336499214267301362161341750373615311934457105389796446473,20619481508117738469430272904911772560595466539395055218439600469328451867796,13952701312362872281963137538185820474584748980975982879243876933687953690941,249746714007340023576169446261897246896602417046451816160506088486861113993,2031064645897563637919423800257706696891919492795925079196751344512608989440,11565396752616415432819810596660051755078386394477458037668058318114060397110,986400357247356567494096182209394879745469890962659581282966363140769490357,4537710479751915891784323654735525989928281714716787626598475607721311119956,6473679789570545843051971615499250002895246840329033388322918048865214899581,9663160517547239942952324390296932496372339501369452594336052141919689254511,5816463053578002459222339447164819661176549623835281810359748779077848682107,15884891878740533639319804312855499125304552172182333174674400304788572220390,3033403576169643300191876532878569681892028128211422158671974606431741064057,10358010399523377550281291332476224381854765291561168350961812145251103430188,5609119676745360689177377631509255444635743595725402489628064332010648311979,9629834817212476647292649072966526100818069994746003213667948679343174132340,9902671572518009781416980720459757101464549561371827438607346753254097417791,7861900468190840021147507239605680877304969442537895993247780719118539599806,17965713539282108900380748546130491121922627970953515439952089259237956451418,11875127160859896409551848475414052588524539216162668112975117611722753563101,12036060586969767703747823124372554748937989587973573397651022172958180951726,9687479700009208904244134411901361698716242095445472067017865326177763818896,9417881715546662771138833677126201059337478279387740105578558474324645551658,1453393784429512178361095160478955627301424316545464923297558140633602643591,3605661850144345838926820161654200172773665263094741288943401786929181563752,9633343945573595088617177094944240138296472849064303543706399640795820973418,12473139325003262775761026452954333162901791070446569863302424457084077761149,12050383798910643577317544771125034193641466979797280393384224161250051391008,10819280347517551331483926007074671789351833709996171469616831904311265033949,13165812145639084020184122275986846677464323294523670942848342958951658208097,4349080070868874275277456883424617452669491031060808106496345174056753179120,10004465749978899491390807601888552616948704671794075232666191099858337042324,5250553500845345497570122559573167112673420661316457421274200097450990672373,12898588403041862218453963458103462644872308284833558427909835998108927951654,18081519381738296094081786403175972446703155704846706982096034153576188388497,17428269008435424731165207394539747495252057789950545989706433801022598432683,21363561515458498091299721959548254375350819182606817501876503845082368630248,7730068437198222255038306872157350083702057866362961468917603557490811496832,804393402354592729694369925125379986785009558185994901175413585942989446396,5734375191529745066389276413443500729878560514347145222515433157787509440061,12298550311942812907291709877922367696701304981384797706564000787234950045527,11599955784759432052811066625229516027776562566066732630526030964712154732575,19052852164576098666742966317699449063762547007283635113650074658720294958279,10025188726400272980943623464270412609902684461295237328964275116870569460545,6716809200457040320003933672999684025455855713745782618771058247491604111902,13265049252191301811995103374452481986951626617983097109447548540667223415855,3243273032455921996687884516398249181181318053856384035604616213401999420878,17596345835810824358133183122550505795231799288513594802190425260560699653345,14128892069525759858946235743223382009747348980906404699362919849705747120829,13560912558482649403704338887070267536467549681310240991684055262800855969142,5146650134021051734120451478394931677954544403196703024645198760974236051136,3656624380537215154312224820978463973302627823287220718508509926228536255064,17192240779422792861455260231600955507004716950247796731699861536149977973585,14505892053752720060006987522044578502315422621292564446333307406645448977523,897766293354199284998764120885006378362273185992111179631631299334090746025,9385522526111341509707107108914634969549440746118599228963287393277576591675,16755551931355332730912571473383446100229118084434859591641172409884703288623,7998487350537565460407312493288045720319128967533762889043801066609578748620,7253071994474199371350196978282275858691584350754099653147319975858840509065,1574915908528094850594155669399292110958198100218448518346743116412237429711,4964033462714392747475438670479181630637512997723146160177292638427948047795,448448106178274062085484969210407935775566171618153143848162702130236340948,10632678501409460480908899293916037077432376165397750836428181066894132950422,6560185425582299240893314836102079088239101938875583740502225690151903320396,1579188680045650467520863974543764324416915154559115370865175124462148613819,7512915739904886375944428372792517861202973027020854741625268080946313568103,11437215569201917203849322845056384272839597879584906569042314064918170663914,12242031850346916661228168797937142001106743366886274501414812437377823138597,20754147834828558255955521879849243373047193258439455093561468286224927742847,8071694345199003059727834592733443749021397716021823212294503054151589204390,20008195907609188950845942022048531038227320303695709133926612651814670959266,3407176450804539102225412244906714437508697739163709736953739213204054495282,7164733851792769372626784323196646242013517015794517414070184073240948375536,9905209321913745841790507726277960404981926942651589731149669818541827874214,6005284264922151317117707687482989323446281090296110762814732182741632133904,3429846891758468105169655789950721158959212737421209807144772069541192906919,8594924739933231799186811828034272621585362372014000894229076451226180774305,11871888849049325223331295756953912508046243621607006393548707001434995954238,5685905463286653736673250214945816154927032180553041236977187605699044205816,213743477607202689216486321834878291503247072102535716407202454507834205331,12562677380228777117621213265298559705423375836884092254836487933903100167894,8185089847800873546122723865396073717154949803733075710451409261160174437901,6833793650798095878312843740119765700866687688998823144083128641706792979819,4953313804596399497426456604424338320630850621290040554640752190475708172557,2236942430605502498740725704270029328474562664606378240692747298661887827319,1513449164658866312019182303051862147479160906256039744485216368678117608853,20317977663255757433651259494490740600408545133225161089258307793180016743554,2805473554735433677734689688066817081805362311169954998301659824970436339447,15815182380045621180846286591593553907538664337286124104922652024183257765519,8995040978147557956715534525198883385024370476405764975921649687446895470970,8204191497925877512228406532110351579276808609895204619986274589454615200331,9804350573365946552974871840565664742492437387015600083520724662514547605734,2670072936416198613788578252423721270352613415834375050844481006480844299140,18981033918047008332984286244333212532097768099085053122971946780791175897494,12954085820551020895974547504930170442441222377530978192526624489157895091072,9097838829535778653934125096834099047122481765699682650259018742771271485024,7412500154264631610614836174268215158855286123479543445207793653417339063427,4570719057023209933442917712353770885061956176422382707340131424665352082829,3764270938841013974016907794451240962927342721628880682930414663597308799660,3003259409352957401069823305356475477293574843963128589242837442372343327078,4364045643562272249326662669199826714126432097046293502341074915354885207241,7862497546139280137858115009924456872495405978857024048016201451567691552233,2320345330709275050815413684718297588549014329479521210951823856644277128291,3472052133118830373581093491758594658278444460214482406644025496494813391646,18719780395522132269892764976785744172160001291971824246311191396996341879998,2052034405003094013719516407189467871257070713148889132320853589752948812286,12668293034393175159240347623878811740389002104040561234210863028172486003814,3030226117016103704707119677479690730613220303512226016348578882444095217375,10328007796868265401669271360208572151985515933147061282836598786351719442924,2936234154384973501504058165728446155253408008794108135203900159696674018692,488196422923618399001126311361138933209773385094782255292621218871598725659,9986243106324062707533627601692123931503570667062976466271294044444369357821,16946417777163299571223971859384083494444080413698624920773661721819621003999,6290655646787769345150128237305014645896272983703662862175950979175390099996,21576354856650767064171440939276202866931509433119578951322323205119147402280,12396222895516500136715256668686614381644469516081823538030375243855459590807,18323538829312240204982678233417444895412920429922269434090001873145951634449,5312977696789603985280968610327711512128871567270265803635161870118441769141,1256303934933114233929368123369287749699533819478400217199836088113619997588,1766722289253438664291189751442574085464717822269757100835532731400395828058,20358149792139162776765514570327167438522971057031059964363017830738523560815,18792275959974477341072288096653531684536236050557537981692565367846354045353,11262334644528432796511003492639130680887823443747110676752140224527884546026,20501847923202184923710061886495102946632889060597711856226126913397710337656,2407267120907499137598716355969720653158717479075795831021615986085480804669,17307860167097742136268530831561503531461792239855909861554172148017416960805,2162289869674344221546800054490037354766673860343307342595970088710829183154,7028199420603561050998184473139307688291589649001033510888359073812068249126,20994672525924208572413211399438489393060949253402639946739540459305617910138,20173431861606460093483867873896693022082731481398426039971589468498814864556,9008871249428555602906292660739315591043104408371562099899839775533895523948,10700805877647067083283505504782153003756758200729717834117016178491024406477,21112465741764258732843126921665151348166174697732269978267747373163853108430,11434984188666323224207642407059759324684918143122828248101482207244887988138,19774670032646206729857931401475084640123741797887602999266543966674579660422,674655537444683637096570248236990032160746930820910298495859277351312061534,12399952541366504233794506479162333424641228812125959815028858786807335765308,10787188444435222346993386033929793480957373636649543232735691292731739491178,8444484958726309128422673453859105535823575309761203789528942642797742183861,6178443234860827296437957284319327879259579261423150811121652495400576061977,9312686778448920745396192252021125483491892057300805307510293202738266404216,21035346041382930907137468070148126300607151584874513632902588011146411628958,21595380874048139145422335028184290720358814546434544789176692636485866078352,18101046998013962303174610041325057852573934184601619434223015638490343790989,19667939085949665955991312921627801957163412888505151951175612729243786613781,6926779782333484660471017512018931263032231687078574887001518725808608895509,21080823663408874605869582733040113428551737099016002655485931862299065393278,3655825253274650356501864672127621389343134570773587805971056417535174536245,3388541056162402337902270805874665052329588330241925030058121260891155159271,21883983703980930327495083710303031860831358299523823198355219501906879066592,6926045735792789706902681099796161456533517354066439495586980016226331896111,4122959111197116982155867189740721062669675590322734927703841118527609239459,13219980757163558837707442934888299444190968070207889541780648207183773341011,13812897721847878024718349018307386755424010495939938584588468146497630813114,12798580293550179822728288481477643428051047081525754174406779865733869649777,19217125674525037886170888487423869066614323854468572412518413433041373346147,375553361556668826677041847695421482571990138873344010326810282960129792132,10834658340690112017927173678735250754641576226700757836412274044036729618775,4000963705080416713341998395751411942820883040862140582570351568343523301185,11715758996898666999645486245570559500678491132871745818362150491793495427655,4263507095725155156517595569654198316584673531155392198157637482244808941446,328008196666170836733724513867841384647787752809351062335576481522598738696,16052279110256413457891846976681654137774297241350913171330588402386482933504,8560435921497695081829647680343824474942212198090196568605135998993570233835,18716362840678189592322462186141719951790452060116008532478803871048621361376,6373296854260461347237798330630093524006414867838125038061282895929391886849,18914705717475623119982002205679946947799155688028604423250694242332863378659,3615848956195277523544974986464432491666056752600413462508649484050878259586,14319383609652049721947038362087013158818175249064317958973877909037224815373,16735322269478335929131611670089342135588205793924787907856943392431725411629,20487989084414161462431324456040544956671737924589348832484117290264531005303,991404779256099913569561460005735823176831315250109345694197087497778707447,12403152875035099961283368388852584749460932263482397452647736730447907363221,4086427505181709923565832636992346270489207870131792488930389136658523450334,6143243951533181757415269381412864770996360748004903845141664179532399602512,866706669878257575355607694505677029531447447184317717274975559227499614511,5892914572161311963309388543417806910338156401784367910536431408323821746054,17195629524346618476376551682847818577110341498528926796026110967915240955181,11821298882555096497181913149211502245650586243756443688232286290083613236253,9353931901221302781036617146700068445151424017933715326811471823048576997254,287161824097962028466164990607592105232453331778514498980389789122436840050,10649681231914156546306210447083574697745999931000675911245824305402757632471,234428462053245029707379734508145490630528735544251100489484083890623632434,18386986463595680658295944092336172488193344109864388929828691162200829447922,12209205038092046905635371865560616384451716418834791040178049545643031921053,14186020280018069417447809370772570171911004194015095921511996859327548729773,18113938321789369780471778880758786581581161378582151974602552514969078582931,4811662992940356526245596671631791612493389462608103550402208802794345444140,20758900083194181903559645045132621401748979651195063688583538188953422299252,9153554145073302417837255133650907646404668180089275208960151746312542076673,9140083548410620433186361969381763393513996980985547052071730395844456832878,1995008884754637182207447536267941537231422109677541855619755654197330974956,20815985241080261061330547616924867409496454481048128927799047536950736307626,3230373257763661238115338374579765087994728137593244037768237534083906441753,15848607284344292541615961379571084541204910796797596203678379270219514113553,10428395164296448020881569101995272889447042680020183589472054992027224827786,13680122146242354024351667942887798315658431983426300974494489056276061013513,4339724378247845795006138666633339576672603219988412146454211158778911139049,16957453138566211779676251195537106997166365265767483860476580167187603818641,6903442910536492004022094150099887848831560470459811862902118892324229883825,13517533794136732881120013247194703467846939834067648417739110803619549581956,8573259981507024845652388913624603863752296398651459450944134507080250987145,7184725885552680253794089893559736740786331382981862187745268057810849566021,7444911651670419666243138241908768267984541319117854062859415506699726860996,11938251205745649282918409002562222384447298563524098642560439931062370036028,18732676061737136378462265890132297759828778436681433094170064283098167411411,8846532794008556689131513011423108042165045871690949838768507118557843169852,18388218263536244281946085549244925864711296342518046885707040924859244937400,17560203902531872086160045342305935339585392467343746359739902020514592872929,13543101793457457855715055504451796018964110256417682942067062541530681224758,12729201216656193290459172785293440324005383463664790973551946761644249872265,20749632282565878390585307142178974866932241415051524225408429188255209021839,2939350463247023543160206627078350892997171197177918468376868549940855641486,479410521971742071578523736929989300479738063431591906751176641695551615616,1215960229051771956876212387168875875104433482328478370485649365955599472636,7395834689442865088318136274271999810879214824816761763663704696957588580019,3437039086902274758103248708959011309309143141844585728091733160570479897488,17467540498235313026126845934481902834360708027699640261573503748997917041831,8422995023428881457749354920047230520807267797593122026229940569066728153312,11738236614524316047928272298201726059224571806912522830504677268234776263625,12990187369429149609670218646295887927962536468837638994349699374218402630706,21623781561819578622543358003640431769369503776252057790027825149203611468091,5669501143149367774701636329186878874504568114693026656335516415399035236206,4575509333922357841125659935390034260822150782714631158836599383911958256934,6033679984514005206127292322842556662338038222728990090780027736088500900555,20960588060390074988596726655693601209728221976889320157850211914560680389602,13413928900186225435324599444732846219399870995843202836070995363431243049194,9234295907731818534748337816708817747432963728163044189490249482655118848141,8555123146188721627588124037374319613226378704908045460846666824116325453744,15273216586585654487893582395632825165015207795457148545076967758704213266502,11125068324382272646583837096728304098536045737064996999867399544054690011336,14959670405320615939216519873622952189488168539376564485090492806106125094875,2609137341445825321095931245531863029306734693698914386115461720635228617677,18022833118482437226280994646426462585862398739142688151319660825030833751162,10525185277608968809171389414591123336341871721390818817629448578893073864965,6744998464824276672348708743166802119889279164929133576466782672127996471038,9344118411856392638882345685982595534877291739896163576786468663773481537247,5834845743289993456669132331911158234826336724070643002101495844260807919180,640787484559876348086629339096900566749702582335998287167888457763777550412,3289778183958313592191132419001427890244410850048418852950969831934946260405,21884067909485911557708530514125998779898644250629017666973972309955096019929,12413233158576537989326032313779399359311922621054801366572548255508592334846,19326971287642001797155516864971431422568657490079056599164481456075851978783,9713216558784550226779073929454993288918740379425900055346553812422457613427,18939709206067618242082635502394826733708666259540151764313557087718564592235,16287201832008230557120811959387085081039691924582377369304872636500446900292,5278016450516276499641394140854299047658079220708153291463991663971826612725,8340962164398516487176161966485950102648589482540787401234013926762930809122,2189360335587469104898894044890322510567148239646828290042687811234738731248,3449789621053765306024986494635371148296184209757783340117745997173900013891,9143283285825049929933624722851126967075894848265558258882809634241528781890,1762589836333836268173539283261821177424666871790048223025892425442664744623,14999716003380172870846520006929664713498492291151583767005426828389694408867,6657396937759865997077915983426704746176142403322137472681086594905173286297,15931240944401174032343453067874387364523175128749141502399457399279513999466,1093656103569127166341414994548826968375416499363412936873802336598768367672,15311996490740753142335607256171022029850671542830487572556180935394970969084,2114569000427676164059607854200438792707180857430926937778356703166016436297,20765151929972334364703309580474623940346949760797265180189525857343032900699,15086899750477019230037863517768898777026828694611906648102458179274814888575,11989598054307650119711820896035556261218721126425285775266572489599541225098,9091334194223602201291135947382348087276953920280768131063598550602333641673,662205156672119277592919023943339579805630811299947870362049797370818219037,1644010308269285824046398201622466330980474102922491226041283891094107089659,10802230809760799055453358968022894649048726749105153336410430294944584338077,10002812375469387387638524822236342839480428168589080127597945114460807065506,19156323136144190554785957482371465262949638224644638616894263767724257422262,17733486484176040486420248003268701811107138651833773383126692059485133299226,11591816707957137858747879818244290349664729458236317322129399152472444934827,13438697403526660565724658068461816155647612966569784134628157461074851140504,13266011411738324637226437761946084145971285033245245813436082422574964132769,19496324867803620550902836425197207665281935127556215366411961309085032313784,17828723725738030742535695874826508863700363541225603578112437608777873288872,1354878734330830246945810749621035198088901780682128075198035721915088394677,14191386869116296861827703975696048379271311137936832987484810982707013486938,19738102036337682966068176606232821315534061860926048846327720022609950683611,10125898950023999329674512710082674945903794489998271114320266993547905724563,9735132529803303628278600229677357854336331158152745512812889827254017680646,11236813353178034372164750145200156935906967316633703292491531523808184114591,2838710343346183231321901296981007702601287106254090132583144723338172491341,2260966150439461282635555159610786965904582998424984888756770014321125334804,16205138689269860259863339330838066928731455712034665818609854024821608206800,14474351689504859217283250911440109599364797953678136799363008066531050767071,6800897037717406782446195419208951974623496109363697062923841346454038837657,12439223794583479313810611548866683769924970108158641553689074442900057207206,13368632268650760591616092601174213792332738038582508245973036690611922918115,13045024155077800673372198196114071407850396125448182263497388710529843778012,15909614634449771616261546064207953846549526793661176217246033322484959782377,6286523689254946058242241932237494136885909209872547435875613686442878101066,1349982286621373054175291479185807897612755726394394337821103602455947583575,1790249021131563196559147247422502568900570496057134946620667686190353467913,6402193114585552816271289059052503078472437339555969654050634927290142355144,16657876151292774412640987426284773353540623435906797018927318161786869839630,9323926757990898215781025566456682055829536111985821344881754566754550287464,333557759600743416321063171376142987411973146341256173569676328325670137868,2979415176549537735678518951412460315394554685744871595392830851604961695296,11399925948142490745007741431204138659570087052831458877959853228053991616097,17621136800256980786736718847997675507300992679800923101555538476888606832414,19796186386112600298425768110232392434623500274218805673491160537841238382774,6150633696896276954724869550196553826388538976047912638783098883173888551921,8007744165470722314410652720217502653722691054745133622163922368886561184511,9311054107030040402449841855464250035701299963653145080544526434268446648883,17483374709267556993216232945834980676370211318754373298278341962960548363667,10342541634151745634549333576310088998125069092773405335947539258498170319639,2491113909032842407846736301373377587232014330531326042787834409966784029431,2868273648562988738033854616949524236294200717479306399357880720258598168313,10742331131465347969746591645056052543770202432577403033214021867405353469410,11262784136416067912059431910504651513874071545823747299137490135956765416093,1202953198131460912225596542947265149450470358249744433218140619832526467659,1357188592392022798249752911997083133072840552839921198518049365021930318735,6860322969159072475760401518666168198209741930191210869338776131213742985903,17512830541972446751364043570597924188477065675882039340228337890464360413831,11068769874220100931580712510878176008480346856568608049014134908792656846759,174592415638141512586004221919684850728269107225502531102930877822615095893,4529660791853304207880649392489892958123653811385478713812028357153062637877,7261086657925858393339848092042570053113017792782297779091045392687309229931,15947797860109427499686809495296483548232719158897790339724183452147879327839,20792174987130011436800220305375988411204569143955960269071283382992617027310,16004359657196683674112642475201997234099915262640166308760622340887283269558,3052232100533123772344258509339894427157169209304015026294337193048877370052,6932731371388662052904698619255543785138918159081404052613363170137706724722,18786344120940971245053939784556033915582618306965577644860589607674568931598,5543910602266336221969634219610367731229996706190750207556121552771043245699,21500331075127237626915881392062922706776178350223005349901601754581763355631,1647168321391235121087005294677186408057439085818209785557656918589059596681,18530920602212288118571329897791681729275409540471839847360270409798512800049,4854705606288041012191490612688235100018679131692705525031856778474580243436,14030500314224264714821884320124695887543721243139555484376859209010937666224,2929002685096227153223014766825090983318157894872369622190343561822695490151,19571082362460435625048830465870659122288859631947561605202388130763965600724,16262018111979731901324396497332329657354718141076944178560644525915310954979,16511368307044025445048172352133100276074403358941934299584092446434550554652,753252068911531248849891296487019536968643055711963719939888051839316478907,4925743538740679971454033971243400511986874154138434310761553437631037517931,6674573928014195188134308196945556256425786164998594495377003561132663149662,12252972387729677079741673273643386252988421977551152663330085764982570989423,8132942533382570630447992711549276375854208836400139615573300103975003948893,1767955113430187982507552626731364143386403228830412651051530991601802225661,15911785581735751807295094148896874484829666426702209837871379520505512480322,8457495441274725464495320737396221038491121993793647195771335087939175598066,4450592062983808718489321963811761580153883581981811699755824744572598554379,17594374172823696288546149573800906143533062920680825959471396256808502015697,5396987646216038506498234734744679865090292329649749592797349235509038812800,21252439428941443609961710022512211297072223091751149596182317370399721579385,18205060096578922655953660066798909616473486532390705801648322522122587090830,18335844957174152986460129513698965339432209604680688295392195893700811299508,2642745947776207344581721189041440984169021288344823913353017838424039626428,12274412791221963394261975707650556785293993588861677826296117405653175236519,9027620387743934195363518529726678172699541005293960006772332651314467807053,447942484646789701542537528994314353531710489288574350580201677777950035282,8057692910194936390243001022339132476522458573171096947792809940102911406995,12466422220613642034159029765007116066052620609909566451840020754182208020143,1171876794208841082635913903308771131102729703148972430947313152931064171577,2996001803829960955342682545650059577915377668754838044698518610136674338212,12306305078198172670943701974214620978597606399214937108559926306737496310941,1710451046983264379967941386456520655992388623198157754427123889803480356000,17294040628260706127805165314917539522165501484257724022309899345383198007240,14850723644587717617416204055806811021029607124589054329504158261611106696194,8626653016235921835569469801636971931942277275560421125462026339476626883966,16134665167778000757091607171765139146858141948472867080489695707419285323252,11129502792062576191937938132554397380912998297589916298721102071015359559556,15130530042530114554524440015929780266039077867502338045121803478767735700077,5922013411157909464044985892976718792018167710191222879749916950629215559119,15641877241146443425426298971354708474362723075989298367558100488623078084763,19807467678520679976886734556492012503982987205100734773481397135264223200444,7230620319188569738319728589376800438996515892335609872222230868954870926930,18168775389925542038768548563310374943094173375522704828602237046711660513509,15879478673208122828337915995586151196586860000621630078538789187695874266640,6026559623764003366786032824563693874782053604114144074018595121889075259493,6581629708588609217727738860658907189729022916858514019350636298557029783381,4392179832866307866014828901921327571555384668846640428849164693147430204259,4039689077078382209094762982217352133778072152116592303105622250221872775182,9439756845261909878224812875899975078023923372686432160229876632562036997401,6300039613750170323909974701574854925454386098696929245502563775636617169329,10245787402060152709811414110506095522941754087902005711632016024561712242938,10770509446150307821311775909967816156602102352374955635502734154581919715219,4445806424060983011786548514585153091691541530320683355086806781784085761841,10891448460108394317032887254041302638257759566726100966329794645560947944086,9055121436695773704587898653339600198373789357537888127317084878411452883579,8149630563292186659644235715307853879418282762593116603286751824944805128957,10164520096412584664920364217937374178249615925628067827666302990156368241543,18787580258401627795053641123916277779446570183960070225650619813208411270515,5840281460603743032409236132633000232507414411373674275076564056089047616513,1156412247030909285380152844453068577291565904060426536020772600017567322066,13125262001118293895463954353229315406286474760130294037415093324929424537303,19341994820951858136925352932235917695982462478372266716377719180643995594202,14230192493251599368583155353256194379698225636722091587422432258409725791125,18604655597949661495485553681980778009433340166469812699886221824297364988905,9484517765495232191823212744512718095318306206191891691619884709082351623103,20661548256453489016691122417433244991048818711049327729621550642733467464794,17946084952153038878596350204495193827996043096722462577062358769356218083033,9008616567490400741620365097652579204686050477332773331876377443733844010527,11222501299614818564801113661500553859475257082250633539503337648966645140931,17547881514301195137575407746474668605213387222566272868597007270413523256918,5795058045621081034219295632641782062332989904715400020698296776847639194943,10503000549984486673912349445691696940798628902104169170719393589667267164117,20627605141977035823281920467011832985049476688278934213570130229801586759490,1617802179061215386952772461423280627948056362689193604176834379576303877113,6791812933391289387114968397366223795809410677008110102514189342693442788856,21469327667867855439208525645169470185070216384607993883382520539336879692857,6209704596259199225388050030516880246912805490686902979517644524792187929012,15048235302521180373501889249113906037936587642496276368753413449431797081949,18778185090591194140890220889049934755279881763207537060835789721322305845157,4164373610491096709440557803327678927854304626112734913682240155408254130319,6352957909818668217728163741226734988658723962520906766539822539894434836600,2081726858060934846688892186400729209835095311388667168398290314717411097500,18997085104017244551079822479039381301947270057658366559839643454880390097993,15381301300391534710642382148869618456973733474322247178000572705046719371489,4198258606721523455517040976251319538290332464337310822593109666080121166366,7557782631251063800473816565466881793101085796415715068491278248627266080710,18931480224318877255548108668163955495398356426693160573742850933557366286581,14006438920977933743471268674953904657230294434994593269165676508225740552815,10552613214353127913757671512246056403297131067811718291694487016254806821431,6942360360107439367031353171424554084301681329082198856946152988574077265518,4821893567676204037011511732637248253220700045205121424698817536976139720741,8570797921121743873772790445200803600261480452613730673514117912909339929304,10210191620579364785116101817818502747961980686320008627354511305745123505207,2219514545666614569412405614553938185242666345781569909039944438048257115280,9472494948236350938478699115530847822498160599193967472596054792264811505177,1966000492511706985369338139654568276174679894528461227404736596640963023833,20046698515808110863133254224236843582890061845803004799852246848232152965906,844879645041461183539563036099295737132271525297913466134251805988318847548,4731835924119595590183070349774829521463227171971888362743688018910258502055,6665591397442095781758927683212527568272080607916992672135848576259567872049,12479020936095094085154050050726399793348028251321297846621658033596298393726,13547094394131143768607425506026982562580191167096570425566382504500825930959,14726791597032654225590630927699963688874228760066722543952181168729825328904,16458751398904781219324882164741165137205147400663608606201428995139003250837,1382702744652547575130131869708589984736039127219433507919721371542416805658,14166947289061517490924648855242003709961143010494793848406604325534604905674,17345393385322406098467895186375277399629828208438881931258894959842597584446,12612093274589904544460621781003810044552285394822234432357810635329000095532,2278721075910399058699498270814807833560549835812826924195171790394865401759,1421362911034706266530649492401610048326109063529762443419685870164992649589,20384150845787594899080953437004222732830782572958598551146508153682280572403,3495056095843097816017033529053032886550694720911641681721955773137850234745,14487246717687560703169821216097612442592434246076605506691782211475316706576,13114661974362015466065924612631881453272278776220284208159815065535423486323,9628837478322926908639029641093928246719582225562091179037197080152788423316,16456984127855989467975376775709400558526389914848937751741445859284106536098,19656266549615253685970702218272816322599871270060998775752454696892588799707,16028536897482325114555541492282064621526855756620164892739323385311597784598,11146275353887579825261271116625263398084632057838305651534583557054398181584,1266798071261939757558459653520435752781168817699931045808536221140555755937,11242956579746912399423902926753108012060763899073974272480062541403588053076,14588608018127887593991920960165305144719061971763947578582110087376128309227,5393054051309402705329828859286427425185515439646193479342950065083063200985,18307950351265411595229078848795494559405008993794506472277342386767679169011,743926999062879465491123202608691059211244131659206478586545917792531513741,11450449580887323007201214040662031298427088361641716342102428346626191862079,8918057399138776974775397421552812822591030597414174436378830421562569121660,14007657148016840281780221954150751472316590653604019267269105557294795817454,8897431240575139049076571283304115052162507033543918057893215164198174868677,17409416377040437657574990618884772475255396933561856228823381810258648281132,16403607054571283311114350132750182990388190855449188101005849970173367695642,1508877263063909922036861471040526805004287450733006660015588614987220564178,2405929790914208591765690668430163058227989428739435027301989746453297508008,18415257845847977290620817418058909465150962144437291827522053905306094819516,20783625745588167215135121578855692267545194811392233146323762172638833678083,12583735518159929222168953087285648797218797099708802919538903595273472024870,15030113532753402263141105846533650021837620483920708638977418255212037916690,2044646201923266135898414814098969242685760821863709223961924291978394037140,9562505824238493762747890608580676752653265912034931437600706699047478680911,8576622443481230638247834729157921300954369512398151853927361194153863723577,13502467573105057302451195240442043465889307076796874707692282952243564124313,8659508751425384756294968991737225118186991099981336883558347987313410663071,992836427155144083079734949008912409782777055146977880211513548288277680936,14478698156814197173486553402886358323315401752422792440407576984439553283243,20204662700070586254342470347097589341087597032672938910846995633724257876133,1812172830570486768023198219726218583158255123460220955281515074543933097836,17992769749806193849727573532001735714323064233429371707200828907106131204931,11275304845104653478990825724663443324387792098049434796341439810037846570595,11105199526118828533245892738176913532701964584183761946009726630431598631704,11393903979182757061241357325556769026145343989318381225525091986823175945546,14383047179623652129287498422471395756755287245693820194038638652931729043624,20453515719997662355844823439261666280107449255435062001366805179715649416520,16342434030539357589118587629035849207895930777526269265833103191510088418049,18401618409669783606190734020469430253158741609682792710560527808266513994586,16076963378432439787360187815002671229026877629938245603309362816936414414606,11529521787481754741418171353792184686967806427253956770441456297160607170941,12602344479327416239042579290059415968931395895265775848606068378636646131638,7874996576706323538862472352643073872193797790899948188898578232811415974069,4845431324532575010258701269749667428252187973009639700566740844013627970107,14802018959157569593654049670448062053140035551074745737518084801052997376690,1438261891736096301511736944301645044858355530036359764344568183983865122024,9702483734495711444970258278431697259819553205295174290488141405714571120392,745629299152271704331537263378566091569916279264951187804590327433939503876,13647050656573274198980106604763314305257288237932552445752822394869548724758,16745795700152546519998532820179128558740146524138261377398336069302091938316,6511309643923082597828923519243281993300211181014429981003702021394673484309,3158509665257424804238893020268668038794684527943417360064521274731483365497,10106711021741632147292275661510721445094446856823798214773373487329113893162,19539597394622940270506324036474158048415508212083560312665281444636039358507,9075752841443178653052367723489194637305474480630925657941805297419704103107,10984322959292625191378844945459317193701661510910417025411449026843907121641,17927313671844804578171839390174936993766288170716470877087434657482712787254,18872143162724264635018175304456023676931184143071101308504884978404622981510,20515902079806118899516548385287144085761546545950360604606371922174253859996,909520465300399063286844098900959690198495601569624327409635184475032912958,20206446745684213293565932220432184473350758436589542174203682990821527627997,18202239467972118142408259480727588505962487821013411792329301914239859726481,7983919062477498484336722979137049758716865253938030483468589967847498836327,8325614337212122905531318376855865321332189692321777599447159536409656516919,8597163804726192574292212854626326634508890118939606311848139014738137868745,18500944130179290196885189330659070775829081695220678669482033354888226989090,7688562031300833340110739922365866810835026837265955101002957176624104705373,19947182975808967149585827952170169153114833389807259043148589247054925861923,21517453591126354047928769118216728006629501856431780724965733122370735013602,19724728051616532722905708549906983762154956430000563385110162693578183573835,12901041676897371025108379309395257314967524835524863357724200518477312324601,3552976975075178791886580855175573474759766023206417049453393296909032090255,19723727023156957738383690313848921568395238875690539785344406327140649751346,8448482122526118108012095036728031952881057181233719818597059954973230302598,19506723656402269183886569439436103718740054288352928129647596321989076586438,14170198227468034198358292107569967739463050831964193487443803219358410981401,2398884471809169728404698398912564280110318964918284340553363751754870608551,20316276154960569208855163430299959763482642890911503054443013025286320052982,16819346170274370820168489515108636849055213099894018965040750518138293949687,14032485862625099598391073907784424901699264655891124043486362510876557553033,3741512032866709198636578814340035900693212341083373891378285003365821212725,12320998007117681710156579111620440763582440787871319835484669927670822914066,18497785580008161471127317447391820533755559610828409772165480020067085485597,4405750113669275276872999085838121306688869906871946649397890860602053182664,9830919490764773329556696442544208406733862221424439787824742578837854955405,11656214840454358128291973754562337687978444406755233034850997851692380129929,16862314752433119612255838474361565358197526603416756657147704910780503202458,13994730783691699927566696508271362101008053907735972055086535421903219406757,1854398114607336170485701571991055833572643201188015258021784624866312103211,20069390379729391520654648717585246938403361904664791681209786618785720069963,19778444821535136400266636630030874919578160245360989612631440824622767847607,21076683052368294199461719450518198858527944040936974409849054794891242446768,20411961758852468040955165630870750226459296665790953169982230333559560296737,7502887992944485334895259919103098713153732704425367381733235650810817022601,8197671201190749689041918593081864258260291777801687985230863071067546597951,570474345973383626887611250305231463005632817815912456645561438458026430574,16187881277000098252637261715701961539204559080071010626416256497925074197451,11845760454453819227975628605163841650771493308562299599588237256809780809041,12496905116588812906791602937225630677262600876144492834414412499317258049345,4202178453449927253051431595142836159883278283876420191896732301089503127871,15280239602029688372093391224297422856227971384132785248484775299588777602819,7675624637796659741242134119256859966414372807758392029058215748145801821134,1558712828795805480069595730092542425736929845400776453853052297930907571419,8635050664405255712941235442916789795311088451605341529181390886210645594786,20012080883240845774134523050094772793782396855825781678689671532280266223297,5332665745663855702669515489737590813722712486482340264533181716182162216492,4485713577378561256572703202440374134284884194291407499970429041545518915674,11594166683437400908552833183389222213106302657616725421515671119008232951402,12334131761060442183744872783660449330900007808735685674075245978195977188916,6469473140282499287719023824549928080797880736382216700350093546124693991876,9636916035199580181413428196442500662713954920605937945590797926723030993514,16259404193045476674338459391599179316200568243819582010383092764410171324132,20780929014533211529148194875929589500835169316324843103846798105106103748435,19665958036420604957261288306620614439114405875604211377014353932489316681936,15722491897648578237100473323139351762887860215830601049261437931157637153597,20474814639824406443111360000192533367769367587690127965461453022108167666929,15306300298273142257702357120212730128497075786589008381550108606914393296015,19116371381269652319147699604019975103087973589614811479290794650138683901396], - [11497693837059016825308731789443585196852778517742143582474723527597064448312,9160854578263429171202421862962594026987177464192712717562131193605088890171,16140003334191084124451468943070902129052879491017160345910048022420147165440,13954253824852759534031493316905992731351625718124698909948022659536770029356,21692459647877833789326815072729212414846887919903018341690717828718320112005,9941936267230985844518782624440910125063679135232844826673261884947459743883,13764916706054812213341909699290503443927147550756936312875016380348026052252,19102599208524798070012402067365820884265931087114568811319734727534891174260,2317229314815846955024814528087757341110607641360330608288042339421595574836,18416483069534816725178879766589878658686265350707575814092642317380006218736,1008780931278741447191637805167409477999443010661365677836100477728938308997,2545090804346934163783014162536858416885322260022963915511642447380970940906,20063061892576784746234714844937263854658165123147516223299128773175198821424,10515454963476061878165006305843100325941655508909556343534889232612007413255,14666046876279128708964624720946075308028756066224010008571298456055047416803,1019066804447509488848959767263827580870207313924599851872882869076383737080,12069305948801710705684828347680772060569105557945593846885134778987150642368,8621808318996908879998215444507382011199442894883948814246574848625262495021,2880093917191730817222149621749122107421670637456732204857760380124742164752,6542220672426887509675431131054437027921301676718161645952700116082427886835,5244163576308284656156828799646671881031097312780189786429450879353224489935,6473177356818363685990488940547034234726012773074061935352613261396549623686,21820960109882302233412313690073759484098924860992104203363318963429862834269,776485012941102583811996326817291151707768276005464663608504425462324969189,16008040671461692654565857317129301282959438973184407738728929267807682783872,11432621469217532329151110587073289606303873577842245393046608426744660231625,16529428848681190297024382986484471912959470051547049854507168832330777582917,21022141832384945339899318910964518260971220396886777286264903115370862218195,14654032557013894559632377088090851151746560959506805696507500157500224672350,21354688910115519251326230418165921377662159943573060390104844506964336391116,7752619774088278019865202458496784783724532278543560344508935599686049023521,9970654674664205783578937362441466301698784253920856829108173973533602978434,8766781005151378907464491478911534398597711022218593484510275842885145890118,427418044823104424459481289119034112585817787122063948281766019090147258009,20178400825368362428846659280983736786989246199446877730902913555280765010239,20090950791842994139452610863206653079874108855048809192426038290381481405709,20312256534186716461922298801781816516042265527822903054862895650988285562148,4909922693172591670749898596465752034935631291352031623980892388245203503556,14711873682305388680005649678171045910409841883308457847530167875811246495050,15958770417311022337941451962731041577578914593218560089308342731268531712920,14344571866504726216497643454572836820480317972842515429281824926793932325980,1769397319845168475613819781273574132774109508454697099778007579313922258588,258587389395146525547707547116022862705614858555176588203787762094788370646,7022463667655232121918607020344762877802128330181623732816227821885112788637,19845060031908398041047500648731073426448577406797522741285587091948148114644,8929070527835967284189505459276001504282186650781989399671939877306459603924,3547034362934554702033015610070536051926221082690581599667998618549114761320,4305372853651357563855521637099663044320680997112932657745973067738472275743,12214176886158725776791687535468106829515395407992835497927312162638766770078,11706938131011539306398383828922578377803816015869195385220014980091795489607,11651169608106469169652973769680487604343355235752770879131657116772958352610,13534129170664288430416028489502009030456779206590118389136628926201783734674,17992046595622622161177230469344714863802535922717313714552838880957499215981,10357743233228120740298650287569640748031608153491097653220067758242532130547,14517928487614900276301089165901434951535050275402697067248151083596639118376,8209182069608252268840455827520737704804441580266130568152978886513947166844,7640073974915695432060688995568585354936052110685953897202450273254409304465,6665784939677502535233010310165049782941185917893655988878440622136707103599,5556533518127592657586282330044128807869230494205809390140992474026365014562,408852126690043032125614061393097734033642541042497038832349288207856020928,12457107183372565990532088400464843754189254530767241274690121422398153743230,13376606774696045471509234199808902800235186345177397461276986609303176540711,5984750790245793264714000637029537436625478804219132653560918517073545131213,17088785934598552415567637681327922806463774512289686863420148678865116179843,20571346584413672249720180719864302959756306192295084730012069713189235458689,10563908856437897624492808163035753573292724651291788140893440219493498317425,8196914932493081300314276778567572383087801740102758457948867897900124032622,15351358433647454670571026954149706648025357095082471550411625465102412004635,4691549575923073479244290910433477874429633596189924034857922132851997509067,3824402350445187488499181297883462500055483166807595223590583390670577007868,3079709149206454455742256725666572935951085219797765997598190006202700553625,2933435916857570611285367519434342227981452027299670163614250683347221879812,11563256620627039928684054332499213986056102448749960304814905960272568400553,823982800920919472728462051408065816783743200056445901787723684868401502814,1426387027752743868839120378047531362360888408160839303820390910661721602405,5731997056751920185589748689260608921390513807500493745181552863591316000292,7720993839832885597994588400736035173902383878486875722645777844101744411689,9002464001048295091481045293483875664362475441902824699977741340020558338559,14092406920820325227424145554147519809410886190773484884502907926085878880530,17941121573263204671416572834368313711647830547916231506552438869447449377380,14129082317750218835304685520412323779932243077309313102580200435673568399019,12243264707350346605364305720479795822428336866265087370053925276897423448873,7359586883838006703688461248312304702229090925413466255532354254039350309505,3965462104895971860844762333128974051506845133345812196538391893357098668635,20413404046776512481224629835753522701244606906272947012890416028042446470875,14776939713848231582251698583594764736648030077584017202377553055729297756934,11733430377692682072369036122380634083002891720790435745639760545087660184574,11292503903510690808481905838273174776860675950299588217800551517281190922743,11420684871520848382159461165975179232780830769432469479502922603701278643559,508745459215920279034800716428719752357838311731203417677851933253804443780,13406614833603475717176189537057020401687589054028958458013676908546295198427,139498778461763532268768837474164379463641791532876816780917343085192436149,21267978943610728192699568453293742013765519272282009809779840168468272374983,13427075011225899058346282386775414644140701782157119231274761492276104178003,19408556542747941554117161987423225644412569826994655839704848575188694207985,4344748623903456736892311801593408666061687792073497811421388122550378864729,5249164170024197498338412206444867159273343488553715674803882832943638673489,2429321160057297680775462145791389342017255648014188548442207641044604477112,17633034583356484958669009250049760097861376611937917426871239574846566954163,8589358080626653532622087734866363152181033731195407703922685134228472217961,169706674245923892154983046053808641575955705892301306744269839968148939837,6930563539197568226045059034503291611681517204525149696500944995384070682620,7715180204730071272045176332163669182843407084675929323110162515552729145466,18820951479360410886797033460215573843065563410033088307349452904607006418510,13004571734426490172877737218587476803131320809388224624418159739666018276230,4221983194911935567520445796137770165826124860682996668925096525627918503987,4179458328609322852016864400883248432169808675570811233121213062838243996150,1974895668668582620251979849937803690939422905200315076249511583941627363923,6163089641798041487723906004413611225955533949531028903999813030048150618255,20798314848405704563578428763355242237484138146926032039199072579614133708498,7390763848541838674951447729994978703104555741288179669331719960925737939679,17595709281213749734228944927123024058411855966868873405155429088809356857614,2441295378821425129112278178696474169691086102217838124236465522719015824771,17849999656709233176331949642982487670074039937621948427273232063967495006615,5474039350730649299741439140946492457291098791158740216537321189511814004320,18047496680368319496003204418900793303422432417949101604087210129655489944730,13429638037186326961998474643589136448656547552567706898682870898125573018456,4946359485751570678621380009145072972898871622865400112232372288432448523287,3957822358540559545601980592836183988567881320017369675759228588453032530432,2400564715392273231728553914090327718988368277691346375047322875638060719294,11894303179337833272080120828007835602120013500741388580434416759507002392538,855198138664096487124576201178969627556714572486300747020353650684651888948,16178438790960495615141009256088177242852822581784859562011828222911238142141,10137977256085689928230181030370096331013301569857962720687404778057694535741,20515298296047282701750471139118794292164841708209011112551973440387123890479,7578927989884657210580284649728673292510875058413984297956940891614841867974,15739538064110791981043195085211350004676897766248503311173839899207608217532,8509314140684268376822128791119356380924264099968476717867240237437611156406,17940958334079989608306082569922896755033794405963583994940471979845228834401,6805144082112931458671099527607595264417843202533041916539891329055761729898,17799985834198911964923035884156388240555414131807336706586014102549806733421,1321093977038377443723007121319910985126631474786194145179087170534580192225,7212420993868874204016591911998823569295893131341249414736874789036080080431,16508732240056273863067547854850721821696261984346034975271352570374366672941,19365952558655609049762470933563228578883041309045062714419724629518231309330,7130642306151081144305696424018041594798737863203511582301667374235931034428,15515575256858646879456258778282520667217724217234033369846512585375869363745,9059306962111196078284859952597377729932287486280210246946890053176853282710,4280792737479805409403664514498090636723785279466801897971750554236293020515,597858655089478477234738420519139785711327216887739704481840585427214898574,12083197860096972935386715826619665719725493525449003092099143765304129114681,12386885105651539176174534724546204378869340659228252756723599802198672140462,16104345036536728728283892631581380860380214418375736872156768647788333934514,1354879242449295308208627398119082438254972230604954870747255418847391619159,4337243085646703769896498772355566596731636687256987520433742534413482763248,21848361732679483806572599977716282165817086425830260890883893707113846583427,19219603360817893268138318807528436572901663409914252265449565639651815377666,8493170221045553556330983879086435859112709446579471993956965243640551891229,14527043796091130553415865581526659472541220106744153300268446542314624889828,7937111786465239058321924657743649234315319708955946415168847089269341907969,6983241618969891267833664988834562719925952220932975709556427480787427509845,18465592203176453842524453315376851907098534348906659566313290009668304127477,12577134888425026368283611608059363450080978991251364658919457233283032077618,6518118228984271075704215109336988269949556606855830580887066004852197959585,10874313757780612756454383662805810655295466490423990025119534270332368723291,20050459982999023948350579488832955163413000705527333267976511300912322921717,21437528840108163281775491180120464654045652656938712316426352947376535924261,15993399358508475124653838111269121783855992741631266590611036066175654211556,10666318855988978766724392469406816805194254878125837815249460550109965279109,3728246313656508848829733684629154197051824118611903835393981369401120614690,15672779156766891637063280303644284349935441934769848438404666835306555334745,20385059098581842810391414884461531594818480948222590493458925664185735049630,17350905999329080753256083745369335770368978719306867594625495391694963226620,6853271030225637900654747228083647747830481256853322607732231926920221636638,16945013335725553221697952514726788415224349981949301561114619373330552300437,13958698773337419850196158271441769489630950623502500296722238460406723080346,10720560039907520317176701532328409797933913846226344831945799921818292744504,21881661898012375513399335499754096939362343783241122010305516740752509759219,8000150875389840177411621828177856485533123076967778453164076865957788973133,12006864256015504014085835403867962462497397391751885107034795661085483190829,11134943591559521791276826061536197135026619606969540608969613264694780202214,10460719249321273180939167776515335033037028258913526408809327052344611741158,15622824325483665989612723680117847052463187830077568039968213833454442303285,15410746446975895232352042328675463711076427815985485297730903996168105249910,2891625203408623652388062275887825901052275992286085168525244670232353662516,13945346776936592111645435552497641082181197055210791224507452108313960355724,9948029837520576958543862437428843878940881432043095435233721163595331057646,19462884070334019417166507501239463855294968830363882698967905077860898932836,5520136928844106525731832126160315598282989291025512087174203871698688956372,2261360495098633227748653797124151186175710067614537829940284371045336769476,18416255543912854662465760974639117371049579168655995592136361451572699752296,11463536517819692876416279640167390882172379596277754722588804736317693209031,14766312573746115666714530391277822821010415216258152152785909105008723593246,15974413313983607427146441647805917978765835122483385258268287590594890695726,7395768998784322986017026062700445312131764953109410144512127957624588026520,4984362060666297962621166548113407854009922708767986933509108968930963325593,7856069925664789206382562869453172139307214363990979700110954142509543954720,13392340056392075670742743235567931160245313927053798436913893965097578743589,14474853581934896987119860016624045909083123926480713073931600741515836999440,10281094117655562522718238098582121237113987849950975777935895552307296780258,15651874975250045926713763993802349605521485743295256479167713866101959393837,18837584337473843738351569365992574544592556787094567312567026738414350732486,5422285873429437751528536004788420694267218180077508101272917323525729776286,14483434861134394018133707852914799521209887335043004813883706597879855694501,20781651897373919207655051244184479648667009194959049646213659882342077548670,13257874746816536319517386553976680827294792028033921278407244416529098958298,11687595443717328453023567060513955787814475781716013805208754435947875015986,18166734702075655056906373297658555632769934998914813942424547912757194661408,21844245024899402789239043296889438934444349492098488274411135961103932824086,11576523423366505825808301659798885009429028155669986846400153307591026628871,1148929907457849288972409801053032039492913919668345502756020163532587226569,9833563661199700341560575887921549871699630430379479441644037429312353663854,3530072023449326955819177530541286351102246058096342120743109127661619847487,9578572618820421025088920868463234434017082077820664789170518853528041438058,7903274455513569732248555355877155817202990193424390098928646605922794954894,15657165496965632442135478212817895834512397576120080820666617370995124184076,20874620177603797416855214546759257732117862468392283423272496519554421621175,15225141515575386127960844403303707527145779098407107474807381929305493685913,18969726739742369826201131743053235807095357084892793088520738053078283905792,2273322388759602026766688787958421446004694547879317377854849512027808056744,5432511453110863684214390264939773007164867954188379597097897639266721931777,16573736113133010502307046980851924227669732687124639246608245168226674694938,14442377229880210285366376088368281053151209045775399428755468734230536622166,11507669956883827819118311484641373285663729813488745641363568933392081679659,17839532429606263422276008800408286253970022114288361307186094837217135904945,4014265539378515041529068347957642340321904838486974789543291691351911347680,13003411109936526663340169024379119873659186776343250211166084846025445488231,15306462549196010658398578543921194922332897913051564489815921371400376655492,15374920278441335059913374044144421033417626851032526544458034333565246831914,2323707387573936061377018731706151895551673463355017998838984100857163359959,8763825614293136074070194100490720958859071057754803255698169463529260604989,6460078619951263360498950096593765796985616066844041272594234887640757495947,7787749571541900537576366919010287855513576825542236245962970793208463720908,14155132064389382746286911268123763500605059883946776474093143918456417640061,5273412399684398435707041325417233001212071630727434066521150499193222197699,21782771343726562685905794523874393783448988772056027768682759741108535654588,2051311409953010480673263657665054154914165583084681916263406447692393737285,11875661765858469891704167021983258181748059479218144774825851054326067416765,21068403881106541076710977164706790160208140346094887767675202443752560686192,15758340092420689120259589661569467106735378390624556577895360824207644286190,6348044865909997285104441438862139025250301814988835887095459638724790173542,17932524652786058307278475190078972097828770914834668973535335630530452917847,3228816608788245618072625224844244257443056161113290604232896419878090903926,9551656383427589703749567396517141384933708835078892692797520811547619069163,9020946637763713728445703977273148745690000656147983844173946393849341364502,2943971707938849936044214925657955353752398302351355306608002652427585494465,13685248050363412502458409958081650237171619758299111626717716567774759779438,2868302441860272746035818268943730589208611466934920188905195434962368539498,12942754961762450702258615422302669970585456811961698112554744196254280397924,7774153016753223166594232439290374237307352882928845881491063153885238423849,6049199094489456460150873785624904803705527267070980629871787636829670320696,20845774618508072345571200270048422316984213457783733272821856328966613453129,893781271752145245996199566953390937322128434854461459523685354415462146991,18253521160421279022112163574719081086152283091051794425756555232523003389714,5830356839546054218884630677325272050228211705054095093735137780865196640272,465724850238100756077164119125411924005501292693566847128509233889037994810,16128424014911176575708362980592727342883849823936273728991741993116151256846,16294469866182032082852110477156803007474009685855833013024070339538767961172,16065302076211391028679793764673039756452069543133653373534107626161947643947,16884841668405833752583472630774457863811531316950980947099417366816649918715,6491186733352076588617073683591626846805330965399318749556699217006305107353,2905363039904017404089840194168764066155916074074586587258377722869451022895,12278525316798802696433043227895855967349302508482435733539545800309845622462,17314019937917464307399357201462393625411723762603710024519926241513301595993,17575148837153403621130441476206668397295797814863081080474688530411862819003,15471095648400918007606825575051718247465842587885842548618709676930106301461,12384318072593682092503177281279533170809948746241154089695346932340260672911,485123300957579906724434519828279717066415303115967428444773045074341666269,20783388705359037084238123327815399486599342641041862648140815340928809400500,782158089782171747510228803754257660300288627956397010472288943774913698434,3478639244366860518133129066736643188173227661380443503605881541719237123785,8117881660412001220282982503758841397343065193097821242261528946890929063115,35058721234476129650326366428341402515138917944396335645144933468879076532,16397938679668108498255642177027044558510343548921376375827648132906803583443,2433453154751221667718635947799318194191827076977739122814782387249355591958,10029257080729083671923349509739320383181145104464214096029001591053185820564,10656149073844062963681322014553075060763965763326275398946747079560564035850,16593959744982924702318121631183966060100893770061806448540495161947421822987,2068414540408163070577553011598011878961687148891918803076043034635892035594,7626934390068570344424013149524663454707020514194937543157326823804903603467,4554638618925430597188146675680715151198309496396245054063619103455584547039,13496396626587678250552586498039471308586222626132206600246125554024514007655,9386575758165199373292193827891788760863572720909068403298778509513288095168,7915179166050735066974287284338956896350001911949145779842510041370266325973,8167168351770465939827858686491835211463722244546741051891842055610292036496,2984855641991264563125921669666111398496570671860076360618117725463255935294,13345515131307851631101763161069239153529744919878592460694942948582652858318,1683899377816547722982571372970082226593844001913781056647398610840773630210,18082738493041031740109434905429676829872619916356658605260447196047710914008,3093627219579176143734483600677215286836843343902256951787659223143740127833,13711569243726999863512778161983125470458400981069655361767578939766971032706,2942999073656444791256166118886574877976523928599259988730412230442182398832,13741805436257583212406513632778404280140012772934699700695904335718144229392,2966496260001027437433299921197242880503083867421600405476235949236365134313,12214449406116917832159291589682410934022154504967698746834536840379875421993,14724028677081535225097028894192068729072210977241429998194582705094787450320,18532472576071611894578331306492326674151870705350144561012248059523768664658,12590949238667856614747230064159254583777806754508472794550424398198576585120,13228220894074693515947418568115512670466893414535562052872530653586084906533] + [ + 0x2fb583762b37592c6c5a95eb1d06694b6c6f9dc4f1ad4862dd8f5e67cb7a3f5c, + 0x12e9f46cd8231bb03d4028bf7a11d7c0e331dc05c088e6dc3d1d001da58b85a5, + 0x1275cd70326f52f816a7c53fe62e323efe61a5b8d3747f6dec5837a825873afc, + 0x6e7d165b57b0299d23e750a75ea2e12c9c7a16954c40a4d10904a61e8773541, + 0x2f67f23a93ef1e215a4add2ecb41bef4b9d85ef9135065d992800e34fa98108b, + 0x169eb9952e2a8623ef38de57e15e242df388019489e01b7c84fa839d864dcd1a, + 0xf4cd404b4024ca13a513ba3156d4de9cb3aa240c683b3e0eb7253bc98c8b5f6, + 0x1c486bfae3ab032ff519e8dca6dc41ea060b0ef9083127bd7c2c4e089fd45aca, + 0x102e745864251ce940c67b1e2f4bc4d27fd3851571ce6813baac665e8cc0c79d, + 0x1e6a6d620433d22293044ffe36a5f2a729c129cce3eeb0bdafdcd0d52bc3bab5, + 0x8f3abf97ad8d01cfd8651ff2d576e3d68ecc47aad82b4188d92138bae603b6d, + 0x283da3f1cf8477d9821ee60378b1c39c72428511a1b9d6683c0302938c248ce6, + 0x2d99cd8d88e49e0babc84cbd58adbc143a75a26ba16f96466a2e41629734437d, + 0x171edd6a7456a4c25fef8aa6d8b748ead869369f72a4e502861fd037dda8f779, + 0x2fab64694369e3a2bd573c0cc383695c02a381e785792a3fabd6e1ca8df2d3a1, + 0xc6155944f64f7694fc8ecd2a2b9a2370568c3c898db9531dc18c72474f9afe7, + 0x1ee0e5cfae030622249210cdcda71437f28f0b1730653c0915efbfc08607c3c7, + 0x1c15154895ebfcbade12f0e02f0cf65f87351b1972358beb0eae6b6976cadabc, + 0x467fedd16f9e87b3069ae697d185c9c884ed5d9e64bb814bd11f71885754083, + 0x2b5565852f65969bb087fcb51626b4754b69136d92546fff44b7048b2f9ef8a2, + 0x2250acc27d5ef8d0f4ae8ede77510a7ffb897d45d9c93fb2ece4fe4c9a520f97, + 0x2c0abe26ff8bd475ef727815bab8a81d154d2c1e36eecd07574222782b02a8c0, + 0x19b0bd9e0c5fa1f56885be00fe97cd4ce8e107e95a10838b70dff34051188a69, + 0x2342fa805eeb2b237633942aef80bafd3af387ec8d472f5d12e8f9834d32eaaa, + 0xed57663a2a64c73b2870af0065ceb8cdea397599ccd9823747f884cdcd8faf9, + 0x2c8da824719f86bbe3e601b19d3ee2a9fb766e7537aac2ea9f44ce4896e64bfc, + 0x242fba876b16361e11c677d62c6aac73930683c0c40bc11938247d2c244a4474, + 0x180cfd0b1cd3af7d5903e1e638bddc6711876fff6d5b12607290debd5e409b3, + 0xfe8ce1b265d657e790bb82e6881b2da774713b724b9a88ec36373fa66f915b, + 0xe8701cb0f031d03a5d81fcf949230dd38dec12218ed937cb31d58cc4640809, + 0x7ed575f9154b12b0fbc12bff4350c6a4d38859d10f557d38c513b37469f47be, + 0x22e9f46e17dda4066a4af81a4be19c94de4b12e0921f819030f8352aad050b91, + 0x2b21049f7b8e6e767d633dcbf2acb264dadc7a85a39b937458c134f652a6ea5d, + 0x216c5a5bff445ac3a3da1eeb706898437840905b9ff27dafbf38efa470bd0bd3, + 0x2e14bd4f01462ffd0c83929aa97706ac772f66a3a0a0326c00eac11f9d5a485b, + 0xf28e51e2f777239205f13ea21e8f33172ae538b21fb69bcfcd82ac51500eeae, + 0x2c2295ecbad9cf1b3f6a773c69714eb4663a01827044169e7f1edd5838106eea, + 0x1afe7b1d8ac438739d488ef003f9c3c679e7fe2f0918bbcf93ad1f127f2281e, + 0x2e0833dafe87279685cd5b5a0105f8b98774b3083833bef43608bca8451b210d, + 0xbbf4266fca0861341c7196fc15592fa22dce6141935e01fc6077c774cbb967c, + 0x530c66b07d2db8dee36ab00f91c5aa0a26b48d8940f0b72735a65481e5e781e, + 0x2ecabeec31877a68058a22f773e92d483867c01df7d050c3fa953ccce90acb51, + 0x1e379c0d2f9d0b659bc732b57689e48c0262a976379959e12b95cb5d45820f28, + 0x27767756606bf727b8e5361002c613d6c3a20df9c1788c9c122d3a7736a6b340, + 0x1be3d832de2196443062c3b42321ae05779368ff46eb68fe57d835d8d656ae25, + 0xe9b839700b18ef3eba297cb68ad992b3bece0cd5bec65e6e40712425447dc59, + 0x2760900970a34d2051ae587ec18f502d246070d70c2c3d7fedeeb51bdcb785d, + 0x370ec3f70286f496692cd5f50f6b06e21c5cd89fa28f9c8b71d42b4ba277906, + 0xba8f86362e1f301baeebb2333893f7fba2ea082d75969a97ee3095baabb10a8, + 0x2d683c3cd7b4f544bbe4a6baa9aaf78614434a5915299ffb37f92abcb4a4dd6a, + 0x25544ccf600d8604bf3e11aeebbed37b77cfb1b22f3b110a930c91e9e7951f82, + 0x1c583675e423f947344328315280966833f05f91a2a24aeec1ab6ed37376f959, + 0xcb752efd07c8400d50a06f3e1baba3cb35b0ba28b262f8526f5eb0ab5bc79d8, + 0x14cf442b6f22ca3f4c16974e2eb56ca084d05eb93ae1049275b8bcbe4dc238f0, + 0x1af1b935bdb5607897f4ff0745ab08140d6e80878652855b1947576fcfee4fa7, + 0x2499ad4b7965230d4dd5d1c41e00699c40433e22c2745807eff395a13e6f1f0e, + 0x2b582ea1669028196e62e62271a36f532b14c0a8109d34ce53df9b75b81d63aa, + 0x1c335a347abda047c4b5ad93dbb2e9412d526049fe1fabe1b5fee25ee99e0bef, + 0x1e3451c495c60dcd443730401ef329d70571e3644dd7b5664cea26daf8a70aa4, + 0x2d96286e6d9eadd63e393335f1217710746ccb928834e73105823acbd2da005c, + 0xc1033de21891ecce9bd0afe313334f7e65977994e545204d616ae0ec4c1bd8a, + 0xf0f51cf6db73e970a6b8efc8823bc82cac8403ec369c02a14affe5fb40eee36, + 0x8ed2dcec016b8eedc067a6da7b562484c010234d84821780662acf9d281b348, + 0x19a5ec3b7882ec910bf7590e9774b63ff37909995a6d695611d5532d6b81a5, + 0x23feec5d6235a405f0d53fc16c955fa0214cbb54fe973948a1dd39263607c33d, + 0x85438dd42c1d74fb0407e48ab1b44e0e42aa3f54b8d7d4f6efb87102c6a00e9, + 0x1916f1d621aaaf4f9072bfc4e41b4b78e82b595d7510d507591414c005fd0327, + 0xfc2435156d4ee76e9a85ac6aec2fbb50b0b77795c370c2183fca9bcbbd07693, + 0x26cf4d12199003f6978f80761784de0919d3a14887a57d4a28b4ff3ad39bd969, + 0x2c480375d8dbd4ac4f039f452fe1a9f074c811d48dc2b214d3f5de827a1a2025, + 0x219b5f8126784340f278b77b765dc4c697937b3d81ba2691f8979839f02cc0eb, + 0x14adc2f2733f55d49fb628c3ba41110e16946214996d1f93262b9347cfe69a21, + 0x230a5fe366e0aa4dfae1dc35e0206959781a64f22d5c684e53ffaa6614b1df31, + 0x1279f8d2e2d43a9eb3b7e4149d16451b78c65118b5a80f86678f5ee6fdcacbde, + 0x2be4cb4144aa4b8e705c37da42b8819f0165ef3476fbc327a3a3deb0a0e8d751, + 0x283b18f7a149cf2f2c8cc446513b5a03a06022cd859f16da1149e7dc7c60a45a, + 0x2d5baf88887aebe22d5d9096dd6c45e941f6a67369af01c75479e707803378ac, + 0x1cd9a6ffdd0daf7ca9890868d9ab398e0546335bf29623aded76e4f7afa5ad55, + 0x160767c1cb457de2acb400781d8cdd25b99f75af301e749cc46049c8db5563f7, + 0x1bbbb19bf384f9812aa63685729e0dfe06f3454c12139454707c1789c39fca6f, + 0xad3beb75c91ceb0b2bb8aba2a1c73c95e7de57b8d5a7984e9f4d010f15a1755, + 0x1841eb6cc35a1dd64feba1d8ad6cfecd65063e1e6c2cad4fd5bff1b4614e0b06, + 0x2356eedec4882d9032ce821d611b98779bd344e2abe0a57de4de06b72be6b447, + 0x10fede6245a9c78b391e69db91108306bee130faf298432d60a4944ee6ed6479, + 0x2b4f28161c7a843692b07410223d8b5db762ff16ac0cded416c3594de6a53443, + 0x1f0846b1b26aa3db14ac0d69972c9118051183ed1d1633876b44c92f022e011b, + 0x28ff7a7752e51734e1f568c6aa3dde3009c22ed210503d5dcd7dc25f7f6767da, + 0x1a3acbdd739794d252150399c6a8b3d114d97d643d4ce83fe8f64f41d8c34e93, + 0x290ba46b38179a447cc81d0031d18e9baa34da9a60ba7df3cb2c7654bef3f412, + 0xb9876589637ee3628c3a08500d67363a1a01da7a1ac81f528c450e9b050c6ea, + 0x35b7b33a1e17c6d1674cc229068e03d3d1767bc950d68a2e376f0c793a896df, + 0x7e6b30a0d3c2526be65920e6b873de72db1d761f7935202fce088538741b347, + 0xe5ed87393495c2a7f3b877578c6bc09653755179159351d8e67470abe9cc690, + 0x2824873ab7526115957736a5cdae583bfcee10b9d418ef8e17795de3386f21f, + 0x1db49ff47ea6ae80c26654ff5714e69cf3a1ff7b31b1fa7a3b9e64618305d582, + 0x1be421809f80b11a626a0eeb927a39c2413e7205d25c89276bf5633565038941, + 0x3b7c7629b535df5b487211f4e789b9a287abe7c453632ef7d42623c2d2c377e, + 0x12a9f7f6e0c65acdf8c9fd354f7ec84d6e41638465e347f3063adc04e00e809e, + 0x1df5905e387f8ec81128c20ffd995fad5402096e3cc6d2e229a23709b6859ac6, + 0x2d39da8ade615636070e6734fd848368d58428aa3b2aed784d8429f2075d122f, + 0x327c1d1f0dd35b08df840db2579623243c13d9c073b9d70984bcfc97c9beb7f, + 0x18a10f3e452a08076aeb6b825004322a48a6fb0f51956f50250a41a49454b6c1, + 0x1e94dfa0b21f7b3e6047d599b3ad491a693fe458add2a56c5ed16155fac59ea6, + 0xfe2016941461beb0f0bed25bf31e8c9a36f21fd61cf70095d2da2bb93bf3b2f, + 0xceb82937c84923d76bf855a1bbe412dd3e35d0378007404477883d885b425b4, + 0x16985b2ee64b42bf9ba0673beb0e47580763c527f4792fe994c23e3046621a9a, + 0x10e6ff96c5dad8a34d7af2e3c6ab2e1eb6ef57849233d2945fc0aabd404e5b6d, + 0x192fdbc53b382b45aa3020d21665ddd656bc1cc332581cc71ec97c3ad71dc542, + 0xd8431c14f1ff4640fbf6990506d930843bcdeb4deeef3380b5cf2161a3bd030, + 0x604632b70d1c0dbc74ed29d69d11d37b90669882c2e3d6784b47a5aad03495f, + 0xf2553c7fa5beb9cf2f6957b01ff7bb7d3ed61f9c2e6fa8a53264704f986c193, + 0x1fdc2bb41ac0418d8351414dc360ab2dd324d1622807cf59db5ca6aacae5d58e, + 0x18c42a157f39bfcada57e085c7cd33781cafc7b33d6505dda828972966a9c2ac, + 0x2645748d1b13c825bb457aa7761b9ce5425c56137e213c8634c87ab29543ba1d, + 0x2788af72cdb594ac08f41269497e1ae18d44232ed0f80a06bd9e72fd216e3972, + 0x21ae229ea6529c4f9de897bb849ab6bb15bb92ee41f73d348c10ba8d64acbcff, + 0x1abcfdf990784706f54792660668ad106d1a6936245785c3fd023a5344cc25ea, + 0x29ccf1d934f2a647595d1be0900002b9b7a343c3e7d3ab9ac3d2ab8de01abf8c, + 0x39c2ffda04fb850f5e70d97ca2d93fde05b651b310b1d27dc298b9fc888d9c0, + 0x1f2ba53bf1c99665fd6f4e862ac08899a41da938198153e4c638bade14719a16, + 0x2451b8e4232ce9c809e439b6eb5fd2bbad8f51e9bf0429a33bb0ee95b7890719, + 0x171a629d2c40364327666e0c05ce3097b2be05ea5c75123fa78851ba178980e0, + 0x8c9b34df311a18764044e24961a95d1b2dcac3c6df9bbe0480659611db8f137, + 0xb22a3e321a38a3801404091d2b160fc133530e8b7a52d2422c9f1a8b252bc20, + 0x797c435ebe5c845a743f87a7f0d267f33bfbafc9f1689c2796b392772e7d301, + 0x1e7306b31a137fcdfb389fac64b5f1ddc6147bd1cc7f30f11d67870454165dee, + 0x112f01c5aa8b6ae92e2c8ca7667f5d21a0b1e4a8ce00a2ccccdc459ade9b019, + 0x219de6b42df30699c66921c11e899b888e9ed317b586abed36fb7692b1216b1b, + 0x86a228ba57047dc5bbbb04bedef0d87c1a78cece6aaf9b698117b292705de04, + 0x14e98432357efd4cc323da2a344142e74f2aa117cc1aa4b559ad83e541ebea49, + 0x1e6b895858694eecad78b8b88d54217c879d8b86ad928190789a09147168fc96, + 0x15e37faf1d08493df2b643576e177c9fc704fecf164b7327481d32313d55d161, + 0x85d0f567ddacd3f8e5e00c4209cd9b296693dba11d00879629b522270e798ed, + 0x1067df821f616fc9635104d5b2150f831ff04a1f2b1399db49673e80c5c86db1, + 0x90332160427de3eb055f9b8748f7e2b88c11f415576e72e4e087416544557ba, + 0x2dc94749388ebd876e0d44ba0105f8da36fce0d45831e4255092d5c7f8b84225, + 0x118c857f29e5a253d50b4d24d2d0c29b82c68ac4ec31e88bc43c74a9487e795d, + 0xaf67f0d07a2fe41c72a457c92e95458a77db9ad0a28768b62b6681adeb11579, + 0x30104204ad0fae366f11620b2f12ee6bb7c141e2fec7e29d963e6fc94f8c828b, + 0x1976ac8ab874f49ccd63235f4d81cf0032ce66d53b0d9a910da3b8d0524a5a60, + 0x2c316de3167edeb721ab1270a0748ee7f77ed7a8a7c727559436f6fb9313bfa3, + 0x9d2011c83a4c911f4535e741f79432b5f2a5b8e53561d179496ddb63cb759f0, + 0x135bb87773cca2191cb5d22ed48e633d71149119bdee6569623af883ed734294, + 0x2d47ce655296753999d0d8cabcf056f0047eaa166f5f8bc3cc5eb601ed2c5600, + 0x12b3ae2f8d3633702674a4ea2e98ab5bb186da55cb7f5bad038be08a46f8f8fb, + 0x1941673c79be83924a43b0159e5f0919c3b4bd334df567e23a109d5ad7093a96, + 0xb524c1bf3c392285d49a42d8bdab4ca454514792e2abb5bb4f62c902c9b9190, + 0x1515ed77226a3311eadf3fc8f035c016fd3705a08b8a9dfc2175fd7bf58eb8da, + 0x64862973bd0b7b75f7b4624a84d680fab7da9b6741aa5d6edb76a9d0c40cbaf, + 0x1a23361fedfc5e494b0b2d4eeb80c93f8835a73100bacb989be5226fcf0df55, + 0x14752381dfb966594721cd9486750a4f1f8e337b06810938317563386d4e544, + 0x4a09034e0f69e26581ce66e097f9b5be008d08be687b8122540f2e3262914ac, + 0x10bb764a96bf402a53785cf2eb4af7b05e20d89ad0658aded12c1b581511538f, + 0x1499cfd036b8ae372458561c19a59aa635054692818f9b3234707168298fa14, + 0xa8b3b48ec68bc2fa9e34521099684e72258264b7796eaa9bc2130ca5f962fcd, + 0x1a46e59c6c21c9d54b9b231fc1403379d01e16680bfe9622dcc01555be87487e, + 0x9569a38ffb6c33d8ebcadc6029a3ba8ea8c8ade1a7874c3f017516c358cc698, + 0x16a9c201d574004d0276db42e7ef31592cd49a56b9b768ca73c7c6d1ddd6a2ca, + 0x19c05f9660f2cb6b113179e32656fe2b39c9307c0d1e9b3e680983e27bc941c7, + 0x29f4b811dddc6725ee59fa5a28af545cb21f15cb7fa6f9885cb7d6a405a063a9, + 0x1f99271ffe92b27fdf561572e5f6092fc06fb7faa9cbb2e07608067cdd529b10, + 0xb9fdcfdc7dfb8724957f00327ddd9372f8fceadbbd41583b66726b252b6c089, + 0x1936f5a41ce7135c9027047ec1d759bfd91ca70a62324400f15a31debf179ba0, + 0xe5eafa60334d7cd71251663f5b91dfe10ec503a1b2fe5b3886ad9b10662abb0, + 0x18065d065c304f7953231240f544ac51d897f58777c69bb9d1f8a486a10c177a, + 0x2678766be9d2c5251479999760ea8d6fe4a1525095e312fae3ccbaf689e7e809, + 0x23750f77af3988a0600ff868b61b9e5e3d00de0f8759612d4af260cf4b113ce2, + 0x7318b129e4789d21bec7920ba354193fdd6fc628eec1513638528431272925b, + 0x2a7bad1eb2e6418a954869513a7a531c58f0985c64aa07db26f8f7949fb0861d, + 0x1bab89c7aeb8f0f1c55bf1aebffd937a520cf6330add93cc33846077c83a987a, + 0x1552d5985864ef2844ae3d20a40a368a4e032a4ca49d8ff6546c450cb1e079a7, + 0x4b91151b3b35f11f5996365de43d43fe5476e5bafa6f711dc30face2623d320, + 0x7568334c7a0595b5ac2105b2b5f738a5df0931aba8576b970722d4e45c912dc, + 0xb162e458aeee52ea49ad59cd7b5fd2dfda24fbd9de8cfa1cdf06016e9d171c0, + 0x2cef3248eb4dae55793e1bcfa553c9315f6b78c356251508e79af7cfd8ad95d3, + 0x15e7245ad978573a5e2b912527de7964cd4add05fac3654847cc0b6edecfb9af, + 0x27c471daf0598daf80d02e06c8171f94dd4b689aa0bee6a68e57b388ddc52155, + 0x13cfdde932c2d8f94bdceae7ad7a0ba5d545f2ac20a04f7e9397d67b942b09a0, + 0x19f9a64fb9d109936e840d1cbe108c9c36eb46d237cdc8462ea8267faee7e8b7, + 0x14169ccdf08725826332bbd522d72ef94b5dc96d07a18359b0cf770331224d67, + 0x2e8744177cd2849b77040421907fc4a9c356c4cd02ccf32dd8f05386ff3122e2, + 0x1507d5deb9bf6bfa10e2b432b56daac4ca62d302fd8e37a021ecf111eb42018a, + 0x26d7097b3269c5d618a95bafb9b128a872c5c85d770515b2815b581e94c8b9fe, + 0x1c7ab275f1c221bc248d8498dbb05c47f41b97fbdb637bfe155cf1e75849d476, + 0x2673077405cc8bc1e0d88920eae1a797d7a40f9999385be0da776c0326b9206, + 0x23fe81be9b9219be0e6312f29022c7d0cec98da3c51c959852d951d6f1cb638b, + 0x10ba3c183fb3890c360fa562760adb456b01949ef7151ed8ab8103f31c7890a2, + 0x2d5259daac231ce0e74872c4065e14db8b32679927872701bae243f6842c34, + 0x1a637c2706a996ff57c037f4f5ee37501fb3e7de4d067c4c0f5ccf30f9d82a05, + 0x2e6067c558d96831add6dce3f7668546f96cd84c4e227cbce700964431ecefa0, + 0x1a0c5d35fc732851917ce3bd13a7f28f75898537f6ff8eef1a1ff41b4b7ae935, + 0x2edc867095cf941cb1ff7887926a4c8c44ceb1927172e39b362d2f7461bb1b84, + 0x2f2062a65c3fe731e2aea024198e417627f38d6cd91e0a4874a856122a9d965b, + 0x261a9965be69de3ffd74235c3a239e3e374cfe12090f6929e7c4442bfb8b61a0, + 0xe51a7f2109df256ff814fc310a3b08efd5bc160698af9ae219c26603e84b586, + 0x201537485c818bea2b1bc635035c7f92ac4be93b1a732a259e5081c6b10822ff, + 0xb1dc66c364df6ca43e96ce916012cfc49115a6635e8a76a13c56f966991ef4e, + 0x1b70f07090ddb1c480c10557d2f818c2355a0d0112f0448f457196db0ef585e4, + 0x1941694438a139d8dde10865876403207f657a2883117cd3a8cc2e7c5d24f32, + 0xcf031701838c4ceaa490cd36e710d3619ce54048ea826cf23a2c456f245e6ff, + 0x132d7fac73535b2c795ddaaa3a69281704e85097d78ac6e8b1e9e8a7721863f7, + 0x4aeffca0f9922fd0379b69a7fb710b49dcd05026a3f2576a48a6e04f91b630f, + 0x25f5b5001f87bf2581938f3ede0c2a7a35141c7abc3e5bb7bb8601a22a3cf43c, + 0xe7119275a25b2b8a4a6aca534650e84ec72b490a41384d44975ed8c80a2a28a + ], + [ + [ + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x130fc54477fd953377fc23abbd7a41be6764892a8787c759c1440fe0133c852d, + 0x2c9c91f48661771baeef6774578a78f69c355c8e907156fdf26db39d2446413f, + 0x1dec0bafa3e8190621e5e095ef751ea03c836dbb8045b2a73f8d397cfb815192, + 0xa5f52ad6ec4a8aa377d8dd2ae3aaf6eea0c68c63a1d034fbda67133ca0b85cb, + 0x20ab7394bfdab344cbb6f2123800a0e23508e2125bfe795ab4a767cecb4d9306, + 0x110ea322b0c26476c67bfa2c1b9d1713f93b3b9cf8320ce0dcd4b64288bda07a, + 0x54eabe6131681fa01fbc6dbf3e7d53595d0f8809987182142b890ac8af89cbe, + 0x224d811fbdef8ec0a006d376a019e57c93bd596213a07823b7d4abce1fd8e621, + 0xe691fca423128a7d4afcaa582b1a94799ba1f5d2a5d53bc2bba56bbecb227a1, + 0x189e279c92de0bab66707e6e6e310524e615cd4c6aacc665372a3b8e372d8ce6, + 0x1d9bcbbd17b93b1913d2f79cdf12844441237206f0294746d93f8e5bdceb4725, + 0x1179184635a9780ee1312dcc3d15c7ef042b18ae9409670e28c4c7f0fb9b608e, + 0xe48466182ae8333af1891a6aa19736741ed0680d57c931ede13fc07ae82e88b, + 0x1c9d56f71c2f22c44d3a8c17bf5b40452e05471f0b6dfe9ffe4725eb29f73464, + 0x2234546f5e8541e8f72ad794891950b32b1cd891cc66775c5b635961642e9c15, + 0x14c09d155c5d428198c234b553da338f227cbc12b0e42f2b9ce71563ee1495c0 + ], + [ + 0x1440dc2578f44694d18c25f892d98c23cfdb87a772200020e897823d4bc84d3b, + 0x65e134cb8d84447d6ea1e17932bd4a341ebef2568313c24594faf9d7eca2110, + 0x2c6b133e80abef84904fa4a75f968fbaabef890286d5fd11b87a1e52b7eb6d0d, + 0x27c72332f59a00135baa94bde294911d135d1d95f53c52eb8b3b95594374906d, + 0x87488f735b1fe2fa3c6c7148c4968e7f3479b1418a1a566743c1ca215dcfcfc, + 0x19f0e2e141896eae6d56d182b687b8a6c64cbb59e031b749f35822fc7ee353fe, + 0x299c47f1e3ecc557ab1c9abe36f0d2ba0ece01051e07f0858e97a9ce16f5664e, + 0x1a4befe11c0230c62de44ffafea0de903ba328c6d67af73680312b68f9acffda, + 0x140762d30c5c3a0b0750b1400a86a9e2f5cfc2531b729370f3ad9fe1dcd43f96, + 0x180aa4babfa7539753d9c222e5e3359aca59e06bbefc7cf3a3ffa4f961fa1d5b, + 0x17208ea9cd4dc1a6deebe6a8d27a3181ab5f86c6a706e6fd007fc1eb678e9de6, + 0x20007a0f5d37798789e0a8ef683536d9cf4831a6566eb727b41191d9f2974710, + 0x229da441a302929b0bae93741b7c75e11337c797e5721f9d7ee59235cda9a40c, + 0x1137b5c61b9684bec41e4dfaa76438256622a4378ea4e646a2844bbc85bf81cc, + 0x113003c1dc7baf35e4536f95f4eab2f3badda2c7a1c6b5afc956234ade3e7129, + 0x1b61468fab59c925f1986186bcb97965a858523a2582d434319a9525ae71158f, + 0x117fd528770fb17f718e29a2d91a63ec7c39ef1dd3039f0943f717d1804253d5 + ], + [ + 0x23aeeb0c6499b84bfc32ae3c42df9728798fd2ef774f1518b870bc57d1385900, + 0xe76c40392bd5f458bc187be54099312a0fefff44b441637020eb92670a6fcf3, + 0x2ce8546cb59f420ede61692e764e0e9f6715b16a2c8047cd8131c97646f50d24, + 0x16e64661144d816885b32f3f7809703477788268d57c14b1d939a26b29cb7ef3, + 0x6cf0db92f86b2732ee5fb881ef0176012dc4adfd849b9be4de17846a6ce5d99, + 0x18f754a95b0af0e4706ff9024bb135164abd6fc16ee40cc2d6852d88a2ffc9f7, + 0x1cc053a6a4d6f96da77e5e73adb9d49bc4d0ef2cc2f69fade48040b7f8d71386, + 0x1e40665f5bb8c5c0dc9c11f39d47e9d33e717afa31ba74f92f8737a55efe134, + 0x976d7c3844bc8deea0f0337f89b2a131302ffd2d0a870181ca5fd5fb6d4fb63, + 0x2c54287eee368d5d52dfb068282d68e6b09b76bd1b5c9333b36848ac277744f5, + 0x228a3488cabbf9f29efc0bce211a09031972b37f25ea35aca840dc2331a0cf35, + 0x16bae49f5ebb1ffe886b634d215de61ebf4f44d1cdc4f84670df8ed69310bfe2, + 0x2e269dc78f70f9103b2bced3edbd41e156e64910887b4dddf8a3eee960f601b7, + 0x1f4b85552b960d1c18b7b8f66af7305a6773d9b05faf51e0ed1a5f2ef2f95e7d, + 0xd5fb9b0e1503f2b92697c473b69cf76d38fc12912e2c3cb33996dbb0cdfaa38, + 0x11291ef514a10d6f0651e4ad0da5d4a489e3018927879da942defdbdf701ddd, + 0x120e7416d74308e24047f6828c68ae28bc288b216e8a25e8b0ebcf738480e390 + ], + [ + 0x1ed9d3e9276acb7b4dae53eba148806fd9bb07b2dd06187212fab7dcbe63d72c, + 0xb981765ecae69dd7af3b10ffa424b8aeb206cc4f49257265c6753b1cc54ebcf, + 0xadaeaf28776b813d518f645c793e57bf16067fd80eb921dd5a67e895646c9c4, + 0x2018db386a3e4e57eada8d91408b155061df050140fb22f9a4f34fb4e2d02428, + 0x67c4411745db6c6aa659ec737a586a8f4a1cde0352e30aa0063794865fc1c04, + 0x193fe0e9b48010fa319c33b86b6b18f428f323fa237ca918a38faaa91ba49567, + 0x9558ecc58bee4f3c578f62489dd900840a9889096c0a62114aa2db045a1d033, + 0x23c4abfeb83192362aae21b2e9ee5cfc765bf1000f798c3ae70133556abc78bd, + 0x152604201ca7df05994e9d5f058f3b6749cea63aa0cb5b4e1c3a00b6667958e, + 0x2f65361a4aed320fcd03a45c44dda740213571f3975ce20b96bffd960cbc6e25, + 0x22122c6313fc9a4c6d0f944d3ce238272bf35147b1b788aab2b8dbceb6024c76, + 0x229aa5b547a63780d8d129e209fdb92f85662616d59da908075e668fd817822d, + 0x21a91fed8bed14914c4fd491b6fa4dcbae7b3b8b3d456303af886c328abf4699, + 0xba8a54914886fae16700c02efdf7767413a0bec5a19ed0cf0a7d8ac60c1f1c3, + 0x2e164a524ee22eb5a8903fae1f35a3a78f882f3e3a9892b6ff4753baac934949, + 0x2df2fb2c2e321e3cce13d16091705a40c5c795f8b41b61dfd6ae7d97d63578b4, + 0x6995e510fd7669374c39d27903f342ac5bf8a1464807f308bef610b76cb693e + ], + [ + 0x2ff57f3f7e95b03411db790a86647467581197124d217520ef2e6332a5b35185, + 0xe4fb044a9fcb4087e351341f25d98b1399b576e2d6654534f348219a0acdf86, + 0x2086a01b816438a2a41c59e43d73fa9aacf0c24e4f6bac229d65fba59922554a, + 0x12263b7e3f3de60899a2c22fee919972cd79dc289a87f31f1b44baf2439dc87c, + 0x19909241cac50288c0d12343e0c12cf9b9790b405ef0a9001aa6be0289063aa9, + 0x11ff091dd551b6d586203ee0cafae2f7652e923aba82574a53b632a066f4884, + 0x93d7d5563e3ccd0b5f15a9b093fe6b863aacccf9af11ffea9b295b7dd42b1f6, + 0x1669e44bf0223a77f48fffbc9f4f20b5814f6185ae11a210f8fdfcb5f71d603d, + 0x1ab6d8fe39f87bb0ee5b883eea2725caa52c575740d5ac30b058f77113d05239, + 0x235bf178b5b56262d988bfc62708b0f85d57385cde2b4dacf9e6d592deb2afe4, + 0x6649a13e65023a713aaee5387d388e3609ae9b14ba4da10642ee0b7b4a16634, + 0x29a5b1e4e2f25445496adec230ed53a35993b37630aecb5d76e56608d1b78cc6, + 0x29f07c1effc65b5589e1ca52cbe00bd65ef5e962d01200302670b6dce79eeb00, + 0x30289c9678c0330f85cf8e362683a6144f22b841aa08f586f219dd9edaef78bc, + 0x1f9dcbde7d058134a510a711d036d1f1800e473a63b33a7e0fb04dc2e09e3af, + 0x1baaf8ff96bb2224bc34cf80c38bf13086f1e429bceec12090d8a7c376a9a82, + 0x1d814b3c17656c2327f94cc02472780b886b88394f1a5cbe34dc4f44ff134fce + ], + [ + 0x15faefbf8584a38969b4a719ffe5f02c2191a8cceda0b775162203d30b80208b, + 0x303e39ca88e8da6e5c963564712df8a7f8501a7af4a990e4ccec19e5f8fc805d, + 0x2348580de49aac01ce8fcb5aa2b467f6787dd8a96ccecd6fb47df7d5a4307398, + 0x10e420edcb6da76170b24d777ce9d31612edb1593ea6d30e8cfdacfb6974f991, + 0x1d25b94bb7c49c0170ee1fb2a5824b70e4554bcc54b6c8f8cc0cc9d74f19a5e, + 0x1da3e00601ca3fc0d90b197bd2a474b46efe3aff3b2cfaf1ebe15fa1afadf2db, + 0x45dc0579ca66e7e096d4dd86b882e68af2d35d70cf5e3b1783caaa0ec424253, + 0x2d5b3f523a9668cbe4887881bf7b40184f978713e358de270d87a600e5c5c92f, + 0x1b62ba8037a83f1261544c307f019dbea1cc6a84d481ea8960b0fc670745e8ae, + 0x1794ec2b0eeb22fbd753b21fcd949e7bedb305f15a59eaf74a961c3046635f85, + 0x1ed4c95c6283b45ec0cd88f511976f063ea2beb0695b8af7cc10589593a7978c, + 0xbfce7b120068b9a30029dbdb36be01d071e8163fa1724f13c6ca89be29b729e, + 0x506a7a5de6b56ebec5e708a70a3cecb3a2cfd25e7a20ed495e295a93023c5a8, + 0x4890048fcdbde6366761cd58fcc6ac0a3360d9a64233d3ea4d8d6be8a23ec45, + 0x285b20799970b58c63ac9f4af564ce0f28209b61802214da5bfafd0cf24c6712, + 0x7b0d70ccff1b70dad9bb4b0142e3f6dc5bc95d3766affad378cc5042484dec9, + 0x3b90da34b198cbca17e34aac98b169875ecf73aeb5c6ff1f00c9fe535aa9902 + ], + [ + 0x1e6eaab1191593de0d89cbb2399ab8aa955d829ad959428cd539be30b72fde9c, + 0x1b77995dbf30cc55f9d4cd4849ced949349da81239a015440fdb38b876abee5, + 0x1fb6bd6df650d27e8cac05ac0b45eef0700e308b29b4bd41eecff58027edc45c, + 0xebcb358f95f84b719c631d4045cef03ac6fc238f6834522cebd02e47411bb6f, + 0x3274e735db2faf186787528254272ee01967e6ae9d825141378b8354d843965, + 0x4ef41945559c1fb0b2116cb2be1f043bfce8dbc96feecccda47cbf68be59b5, + 0xda02f6410e24058a1e90412cd5302c57197f7b1af2a99496f9cff3ffd58808f, + 0x10c1856f282f556d7cf6d4a293621506724ba6d3c582e4c261842f2a4bdb0ec6, + 0x239abc7c9f866aec28685c26f4e046a92d4360d36cb50890f422e18ed6f8a7b2, + 0x83e1cd5943461ab505b200311bde4003fb4f7ed16aa58c8bc28f2e08e9f6922, + 0x15fe62a69b0438294395da1bfc93272d88797ceeef666ba2443f0c146f8ab7ee, + 0x20055568b33367bc12bf4aed7a0909c173588a5763c6a1a7598ba7c6c7e3c2a5, + 0xc02b148f4a1559b597cd320f00c02b96a7fc7c83811bd86a1e79cc3106b2201, + 0x1a4162e8a7704447be0c1d4d5cf2f777670f4841ea27ac2709cd6bffeed2cebd, + 0xce3dd727fdd11a8bc731500effa23763089ce3332cb730f9fe57146ee204810, + 0x11f28ee5da80d19e31581b566a439537466d9ca7fdf14b7086830bd8ac13c4cb, + 0x27fa77a0658791e6755781c367683f9c9333a41364f7870edff1935a347485d8 + ], + [ + 0x2a3bb020c8a50d310ef5b5c77cc408b077fe2481454754c4568ff668fe5f0974, + 0x23643add30be204734d029cf034c958144551060c1901c420a28c9688ec36a80, + 0x3e9718237c1700d7dd213e026f307e8000b3851467fed9e6f51fa5020c2369c, + 0xc48e2f304f730d48e83dae5c78a46188500bc8040a49542eea5ef1a21b9d222, + 0xcac320362e235b458d6d364cd0fff914f3c056adbb038dc2a861a49f7f70e24, + 0x2f053fdf1a72d6ad8c9df97a04d637916f25e3425b6dc33e99ca7cac5cc7e4c7, + 0x2dfb6dd598ada57ea71a8d68e6924608f0ec7838808688ee4b3fcd521f7be6d2, + 0x22cc4349f6baa3a8e0b61fc40ab97210e4bd3b3dec7f05bb8ef839c84692afbc, + 0x2fed5a03200417664537df8fa30276b85d91bd2ed21de33d901fb4d82439857, + 0x22a67a88776982d6a15f577dcf780ac485ebaae6fdf6fbe50b95ea266a7b6059, + 0x2b079a1d09b9d4a76d4e50c45c01fb7508b1c443a8fb21ebd28533e05def8864, + 0x2df1ff86644fcc42a1932cf15d314eed407608246f14a8098725ff7be809c87e, + 0x24a466f74e99a602894f421010f43a81c708b1b4ad076425190b85347f685b1a, + 0x2e944b449c1369ce9766fa6f4f99a87630b5c1f2d63677a437a537d61b6c7470, + 0x1079746ca51d9518a0c309296ca48206292798910494277be2bb65a6b134b3a, + 0x13d7b03e8fc9fa647fca6cdca97146901df7c675a164913c2bd2a3b6ee3cb4, + 0x6d6ee531ba3fdced05e24cf9103d0962dd227f1de692c0199483e92ab24ba59 + ], + [ + 0x51f815c454b6015c7ebf90c297b90e9604cd36acc6af07f99b5e51fdeb32234, + 0x1946a26ab8953f9be558105fa5179f175e76a24429dad5d532c2ceb3cfea05c9, + 0x925af35a3366801ac80a31d63f745fa807bda10560345ad572bef4cf2ce0d6, + 0xe766f03afbb7af630eaa8aff4fe60f3810f30f3f4438498efe0186333dadc0, + 0x1111ed7a66ba2ccd4bea0d43eec86ea35ab40253a1209e3637f103dcb84fc429, + 0x1daf74842c7e79104349ad399592c5c4cce16f79e1a86f50d941598772cca953, + 0x1057062b40bdcf1fe2aaef45898c871146799a92c87d0fce64302d6bc83172df, + 0x12d019e37cd1bd76fee065bb7380a9bd8331a4dbcd1c9c776792bc19045c23b6, + 0x996cae74d9627ca3c56c646095f39730274d25e82c42ce21cf789253d48a3f0, + 0x2d1188d9e7e6ac24c4b2c9dc3dfcfb0fe4782d689f31b94b1fb15ef29d11f19e, + 0xc34496a7db5abb330b2f6ce9adaef5ae6e308c8fc2c5634097ae352aa7457d4, + 0x1d4fb0f18f31c8270b4636e6b5d7a33e455b1050de1164182cfcb739cce965da, + 0x1fee18888425724970bd2897b54c7fa8e9c367dddbc8484da37864faff9f9056, + 0x22d6e787f44daa6b6593dfde5576d2fdf5dc0447e65a1d5e7712e4e62c3bdcee, + 0x23a85d4f91eda69f310c451d7d480c2f40c0d53382ddd3fcaaae627b9617170e, + 0x2440e786179a7fbcfe8d29ab18d0fc6cfa383cfb747f7a2d15b77d82d9b0d9d3, + 0x1e507921be7c76124879ffce5b62dd0e96259e98cc64c27208d62b40bfe3e482 + ], + [ + 0x28b75c2ac167fdf184725317c7bbb8083e5ac5bba937bcfa6cefcb69e4048bf0, + 0x248b533f875e5ee8e751cefa4b1d0732fcd30151c3a5cc4abbbb1e93b4655d45, + 0xf8692d64a5b69a956c4e2006bfec344477fdf5f0c9aab866609842b9d75269d, + 0x1b8a7909d7e7bd4f0bcc8003968e384ac2e8b405ad05cf610364d3ecb982db7e, + 0x13e736cc70b7c828a38dd6394ece76b9ccdae2ca4f43963432502fe8c2ad19ff, + 0x2ae8da8d0b129a22f834d0d234c8917c2f877ff00dc16215498d4b748fb40df1, + 0x26e6d18aea75a94861a02333b5364ceceaa78adfbb742817218ca3af607b910e, + 0x27aa38fa051c434189df57bafd80723ee29bdccd59fbc1aa9af11891d3722e61, + 0x304dbc0936862356e0024b2a32dfa3085abedbd337f22b89062be614d83cb083, + 0x265c43c886f07d025200d56cd246b01670b3e82ab482f5879b10608cc05a37fc, + 0x4ffe27a92cb4300e774388edc3147ab9dcc4ab354c380f51ca7a2e7fe0463c4, + 0x19d6f1d110d9f873db002ff2ed828905bd6cc5d7921c238d7569daa9b2401d32, + 0x19711c41d76f64a371aba62f3f46710dee0c3aad217b7cb00bd12613b24ef52b, + 0xe08ddb69d5efd949c3d671e4e78e4fc7628c65ec1cfbc18ba6a101aa19dbf66, + 0x240657d67f92b5e4261ace434fd286206c315565378ce8b81661523f0e6ddc54, + 0x56149221712b88ec291fc218324142d02873cdd53199679fce4dfcb5dda9116, + 0x681adaea79cf457db5701931f0ee2f15ecbb159ed50cf746a15b85c6f8a5370 + ], + [ + 0x23af324599683d9b71b61d093d63dcbbd97e44957333d2697fdd060c1e4b585, + 0x2e7a1c51da61dd214a1789d6f1ee2957f69d21b1f16d1f9458eb25a406500bd3, + 0x2bdfe7eb4fa803bc1dc0052a46d850ee3e091eba8a7f12579682f6f6fd5044d4, + 0x1d92e4213d840a330ecbdb08693dbf9a971bbd6229047eb88a03f334cadef227, + 0x1f2805084976b142f7c74a416ff439ff1bcd8b8e7b0570130040754a61b71912, + 0x99b0a6330926a4a1564dfe94f9a1104bb8374bb518a89de08c591c17dfaa059, + 0x565b96659025935d9c025c7ab20b1611db00b67ecc51426b342f8c7a17fed83, + 0xf0b9336db5c16d472fda3fb9ac13b13394c09ab9f484ecf6ad2060217b5896a, + 0x2a7de8f5ff476d81d393f1d274636ca956f05bd422bc9f3cc0fac0054b58cb02, + 0xf26d05e938f8317bd608eff0895d352dca712b653b1492f8c2ea96b26f9381e, + 0x28b73b335c72f0774871a2030d444e5fb954979c1c568e112fb911a46c666768, + 0x282a01e8f2ce09cbdd862f98fdaba3f9af02443edc962cb34802d04477de1e20, + 0x2770d14a220152fa7083040be9b3cd38c8ace9e207073486bcfafcad706748b1, + 0x27a573036509a8a29a90eaa34d2adaed5ed1ec6b207274f3c5ca23dad3880e57, + 0x2384a384bcc2c4a17ff7c9e3e7d131d39173c431333a9c7c1d6fd7110e25902b, + 0x162c5bbc81b44427be4e82c5e5253bd66c3054f5c5b73b28b29238487849a794, + 0x1e6196147508bf2edc872c4e897a967778b119f69fb431a7f646d2018eab4010 + ], + [ + 0x5a07868a7c95f50a015879fe7cdf1eb6c317e4d489d4515208ddf40a32329ea, + 0x2065e374edb1f3cbbd2919dc04d14adb07062dd01ec1501b85522e7e0faf925e, + 0x13bdacc137bbcf51d8bc9d281931d6e71122dc6e93e7ffe8b835e3393775c3d4, + 0xd3b3fb86a44b7422429a249884c85644af1975641206e610070c02ef5a9f4cd, + 0x27aa50a0e5d5588c1486e8e7fc8dda65489fffb866756c218f87e7280cddfa64, + 0xb9aebf041146c119199757ea8ceee5abcea9ec42cdb28b921caf21e84847851, + 0x2776bde52a1259472c1cc020e719f82191dec3ab7699b7d0fd769dd3fe392997, + 0x275a6f59623354d71d38b4e200ce2e9676aab74ea8b8366fce33bdbc47d0586d, + 0x12c6f6c83a3530faced60c88f19a82fd12b7d938a79864ed20a545a52fdce11d, + 0x257689a4e22f6a8768aafe54218d31de4e409fdbf42319582536bb583313a395, + 0x195821b99af2c217404ee582e29889072ba3cd994b74955c261b5ad364e5a9c7, + 0x304b679008e8a1f09448423a05889e0df663a2b65055ca9ee5a99dfe13fb9a16, + 0x8dffe684aa33f911d35e9a644b4bdbfcd15a4da49b6531816b60e8ce4f6b5e0, + 0x72372083f62195bcc2b5afab1038198a3f0546b62d171ea21c37c8f31551176, + 0x25547b51b2c6874e4538ca9b34093b714ad36a8f356e4c78e0d66b1f190038fb, + 0x178f2aa8df9a11ef33558dcc934971f7697e626cfef00ffcdeb6f3c9c1a7d10a, + 0x68efa35bc620124ab7d88990171bae4102ad21dfddfb387df0de0c8a3a189e9 + ], + [ + 0x2c5b4a65bc55ac5fbeebde53ce5fa68882faed2a92a7b3f5732832c72f7f2c30, + 0x2f36535a83a09cf09fc38a20a725477aec56668f034a364a9f4a5605fffd33cc, + 0x7d78ce0c1c87391a06a06c83d300d52524b29f183884e300e0eaddacd05f068, + 0x25c7e8faf6c48a156cb91d81a997c6673d32694a3fdd64f5e9594e9f504bad83, + 0x1f3cc6f65d9d34370825a38fd1f48f509f7c56171b9e7a624d9b0ecdf6ac4eab, + 0x55ef271e388278b1aca34d3cb00116bd6f7cb584b3c69f0de2a7afc8d98deb8, + 0xc1a324c49d15f87931821989b8c8437ea9eb46ed3aacf8895fd1cc311053e60, + 0x2ebb6730d7bafeac23fc0b457ea824eeea3c55eca634bf24b2ac2a9a21483e1, + 0x201e03f1ff672629473a24f32d2d502acdc8fdd2883014de74c98f40a195b3e4, + 0x1edc57f174e1322b627c6f9dbe27ae2703c3f11c364b38188bf41d8ca0c1709a, + 0x20a56fce37122b7400ab61a65eac815dd180f52fad2835f7fd9649063523881e, + 0x1998147edaf3a92ab179c61ac2c36af5caf3e78bcbfb684cfea15db17b835907, + 0x1cbfab7cb05e2f28254b230bfce017f005fb4f2dd8935ad11765b347d2003667, + 0x151e0bc2110e4300dd82a4c92442c4751c65b294426c8c320c69e61831958ceb, + 0xe59e1a990ec00f72edc37248349d7a5a6f7bcaef158110450f1e5985f0a5d99, + 0x24afd92f80e57788f40fbb2b79f29454dc485fbafb5a7263f462b7c84b4e500b, + 0x1b012224a4f050df841122d17c5ea4eded7c8ec2034743a432a2cee893976f29 + ], + [ + 0x173f895e472c4eb16a2aff3b8e0417fb32b83eb1e3233471c76a0550505d0607, + 0x1123d3c97ff8e6b589d118bc40ca0b9ac12ae909558f2582551f7a42345b4621, + 0x984c132b29a05f2b506ca07c06fe9a6584f36bb87506d2d316a4f353cac5f1f, + 0x2d7af834c9cdf1b38c8cfed218f1ef0ce0b9908de9e7aa7a5510c4fb917a0281, + 0x1b11713791ea4cb2e17c8c5867502043d0a8cf955384c1c793c506b75fc0db29, + 0x26fbf1a351963fbbdab590dbd760ce6284273525a1b46c41f29226c65339f4b3, + 0x27e68568e9cffd07f9253ef9dbc356251dc6b2d6a903d6c7046b5e90e1bcdc9a, + 0xff215eb1e38dc67432e262df27eda7c3aa9419d5b6e299bd948e970fc35a62f, + 0x118c3efe920c9c3f907c867743d35d2ccbff7c89e9c31bb6a17c552ef92b6c01, + 0x17b39f38636d5eff5e06eff089eb56051a602bc8f4bf1bb0ad2b2cd10cf07138, + 0x235132912db2da07a4750c5ed5df2590e718404aefc48be6953432f64424042e, + 0x28a4572cb654261cf9358435923e65aff8f40393752748b76acfd2e3f5755c9, + 0x21d7269a53d3712b20543b0039aecc9466520133d299e8442000b33184a39e84, + 0x13f1acc389c4f8e752cc7e4b81c37ae2130c60df9c8b7e87dc5fb7459caf4916, + 0x66c6090936f6b054f17dea91682954332b3e32d8f20a0ae171d417316d3622f, + 0x492ae5f5ac2a5102ea96e60ac8375553687151ae44042dbf5899232c8f2100a, + 0x208d814151bcdcddfcf835a958c259a6477bfe4b3392710edf9d80787a25c5d0 + ], + [ + 0x206cb038cc328526d0c3dc5af19437d83219751c5ee8f61b0e9e2f5881366be3, + 0x160b30c874d9c06704c92c266c7a5b7fd966a62a5db008f1bffdf443b1099a82, + 0x1b00faa85136b1bfc496e0ea9a6284cae525aa96612ffeeb514808955693879e, + 0x175af5e50e5685ec2dbb1cf7a2cd25d45680f6cddf68d7c0795dec98b87f6a71, + 0x104560e95c49febb7a030862edb3a33c2b2a3d414b0536b2e54e25ab36e8f281, + 0x12fd67863b2e03b6fb45224fb041ff280e936742b54c8e54d3823e090e144169, + 0x1db0e7e01722aad210e5296c36e9103e82d15765c318134d177146a1d9fd5358, + 0x247f9c7fa610322535feb0676cff549f1c177d0d39d3f1eee642e9253aafb82d, + 0xf705feba5f01cb27b27c104bc93f0c974f561fa26d5614f6a9d9e47d03bc655, + 0x306094ecfe63300b2f95bc98a0406c7898d86852330a7b69f9b04b5404b3eef3, + 0x1059db5e97f25826b0bbefd6bfaa6e9496c55ef5a88fefe9712691f6fbdf4298, + 0x15bd998c2729dbeaccc29b5d6e4f0fd96ad0a6037c84a1a1a785169fb336fb6e, + 0x21fde580a19886b13358f18a32d5aff685b4bd77d94f067f44f6e7a93350fd2a, + 0x6823a9baa55623732b02fa270b2f887fd3804a85c1a7f2a355df3fbefc69dc1, + 0x1b25662843b0986ab1a4e9a766193efca47c70d49364f03d50c5edb5b5517ebe, + 0x10dcb11f815c7e29c66be1dd3c5f7602c98e9fb1687c2d825b48789c521fbd0b, + 0x28f901fcaa860b0dc4192adef8ea4ae55af6ce432c85e0ce4d073e514ab24252 + ], + [ + 0x240c57897161666f28d000b88d3353921d967420f401ce86bbee42be287a4f8, + 0x1361d27c42a7b4bd6eaeb98a339592616c0d4d8fceadfdb16468162bdfa88d46, + 0x19e1e46536704ceceac3eab991bd806e347be40a0b7956dcd7037352fdbc4347, + 0x121f4a18d7b7d9650aab625ebe8695a8079439f2ab00c090279de74726234e6e, + 0x8c45f3c4c486f6b5378c779c607b517200bb70b5533bdacef18519f625b925b, + 0x600cf26635b2d546431507589739010d1b757ceaae617bf95b8e1efa98643d, + 0xaef8a4e47d5ec760e0565ae7acdabe7e8e98972de86dd2f447aaf216ab4cc17, + 0x2ad0bd9f71e2785084aa0b84616b7dada053207c418e65f4035be66a0cdc8c12, + 0x28d327a1c2d6012d9e69e9a3b4c11ad336d3c0dcdff4c5c84ddddf911eb645f5, + 0x11afecc85590543bd2df8ab952be164670a3f32593e962d4bd493bcd3c84f84d, + 0xb050c882073a581e767223705cd9510c04c30168c50ffe0c9875a28b6938299, + 0x7cdf3309e130f9ceddd688af3885369fbacf6d8a44de4d450667c0d7641213f, + 0x5232bf95807e48ad82a1eb4bc481e9b0720e95196dfe361f55c4d1cfc7926d7, + 0x1e41936e6bc0c3ed665c2e2466ab9216b9973fe136d9f9aad95878c1b5607c6e, + 0x2647635477ee5fa9e7ac5983f92db34d7336646c63c63e2dd53d60b8714bd759, + 0xa11d587cb75d48544eec662ad27ca6acfec98f7a8b7963a294e4bb329b170df, + 0x1bd639879731823c871f9cd4714e3cc56a6eb19884b73664eed24b11929119a0 + ], + [ + 0x1aaefc2e9925fcd453996fda804063fdab276b37c5f51dfdfef9255b4ec10cc0, + 0xf1e8f86860c3b5c78bc14dfb67d22c6beb8992123658842f23f75ae3a92e99, + 0x19c2540bbb1cd4e08f105437063c945cfef28ae9dd50b97e0b795f8dc5ae34e2, + 0x21f08f9b3c23f3a02518114a96929b6d1056eb4d1db147ce0c8882e1b0f7bd1b, + 0x2d2193c677bbcd56a74fc2ae50ab4f2cc69aa77ccfc33c7707452d5adac77edb, + 0xf528f5912be49455d4323b259e30ce2984d8170601eeb4bd7096b47353ab7fc, + 0x8c00c4e5b3467f01901f64f9f89c15bb0b90918d488b730cacc3296691e9200, + 0xfc3ccef00d6a64080abbed4fed90b69c5e5803134c22b42cdca0a60f03ec33c, + 0x1bce67f4dc99547f2caff1b5c6d63e3ee2565a404190664533c1c65dd9d8d532, + 0x1a8ba4f37d2315389c8560d74dac572a4447a02145516287053e6b9edefbca2d, + 0x115e60c4e2937eb53c6e4a5488f801266e84d07547a0b1cd91b18f49efef9920, + 0x152d47acb9b06c9d12c2138a31416bbbbb991a65dc4d4f8ef91a3dd728e63b6a, + 0x13602646b88ba31c0d544c757bd9181727835dbe690c30583a23f37f52fe5e3d, + 0x65766d2980331a55c0a39d83be78bd127baee77d53a24268e064c71daaf2b6a, + 0x26db2e85a9006ef5c11cd675a267d42efef9f5af90466b2aaf75eea8024b00bb, + 0x1dd6b095cb68459dcf6bdadd434aa81f80a55a08e6782c653a93afd8a65f3267, + 0x1d3ee85f078fbeecda2473efc2bedd1ba7ec6f4795faaeae3b0de48d3080c625 + ] + ], + [ +[ +0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, +0x197fc9fb21309218eb702b935044146cd33407ed33291cc599340b271c399668, +0xe8ab972df74eec491e4b8c416b4a97c3fe65a38d4e76093ebed05ff3e7d750f, +0x17af7102238531c988dc665323d3e3348ca13eff7d006be181cfca573bd77e79, +0x1b0b5e35d65981e836663ab49379580a659e1dda0d8c49c189b8078bcfdd3f0d, +0x1aa303c6d0552d6fa013df27f7f4aa907d10da9cb9e0881ef2db7ec1a74abbf5, +0xf4eea81fe11aa323228b430a2f9021e2639d66596b3821e131cd8fd5fafa0a7, +0x1b47097a86346051d2d42d6810ee8f3fa3b992b90c009040095fe8357b6be24f, +0x77cdf97e2049e1764e7169aa4ec11ed314badde9e84218bcff380ffebe45382, +0xb4d6879a54ebc4b74422f70789c1b7a47694f6bc0f88624ad0141721a89f73b, +0x14ba91f29fb5987a1d3dcab55e35edd10de3acf4199d877b5c6623b5a6ef8d9b, +0x1fabc01bf1091b88001e832b7ecaee26e5eb867f85b8f1c083832b1db57537a0, +0xb4d4c2920ec03187d1ff531b4cc1b879c7321315d7aeac09b53bad9439ec93, +0x2191792ed6ddd6c3ea8ae009cfd1174fb9efc01482488c101502e34db953815f, +0x162b05a1204ae66ca80d0a89e10426ee4d757f9b34ccf08c1aac697c55245980, +0x251575500ce3526f4b190061361eb2576591f9ef2f0a7ff9a7005efc3c71263c, +0x4384592e42ace8c8014f728704ad93695e50a16c5199d5815e00ce818ed8081 +], +[ +0x1440dc2578f44694d18c25f892d98c23cfdb87a772200020e897823d4bc84d3b, +0x2ff15351b14d1b852edfd01a8ef108ab001a10c8d66e887daf1817a315289259, +0x2fdcdec10d3354953fa9ca8769a3799d001626bb715f19a97e772f2ba1abc421, +0x146deec0773f075175a208469afb87199d1b063c994b98125db22e85844fb455, +0x20f00881fb533be89b9246780df72a26ecb103c554b9b6fb17844fddccb235f7, +0xb419e6fc9348d7c69dc15b49fa148232740635cf2e39904cb5bf7e4e1c85292, +0xc6321d9f04dfd91a4fc850ab7d1f7fa66de38d67faac26599ac62c80784319, +0x12784ae3aa761f38e035e7ee5f21242e28df65235da8599d80a93646dfdcbe9, +0x1e09ddd18fdc3c46c7b2aaf6cfd942c62720cd1630b63dca72b42b4a6409c5a2, +0x2a71a3a65e49942b825245aa127bac8dde2a6fca570c8365d3251b146dcd078c, +0x197d178b0f91d12bfaef18f402635554efba7da59bf45f6daaf3eeba444c3bc1, +0xcf6927b15b1b9df1656581cabd0909b7ee2f1dca0258e183b07b030b5db3320, +0x284151191b230312298ca0d1cc6fbf122b435f7e8de25d9d1927322b0b5a84f7, +0xcb8f5333099700c6d37c787c67bf7fa6ad5e35c32fc1a539a8df57b910257ca, +0x15d5a61db8e06697df1da0f06916eb32d90e86ddc53d177abbc7ccc86f14188, +0x2a9b60e4ae169f3d5fcb4bdd705d89e0a9361e239bc3417c30a42ce645e76d6b, +0x883b0b606695b0c96a67ccf221ab0169eba895363e66ca88425ce3700c0e7d4 +], +[ +0x23aeeb0c6499b84bfc32ae3c42df9728798fd2ef774f1518b870bc57d1385900, +0x101e7e35808991e8cdb0627796f331b89f2646cf0263924aa6003460b351a940, +0x2bb568a99f55bea84bbf76dbf0f54d5f1331ffa1f62d686f3709a56662e51931, +0xceed1b75b2f6ef1438b751e8ad4dea24f1a20f1d9a23589772db49baf9932f5, +0x2af501312e1b653155ec7f8e0e59649b2d078f5ce5121be83fa716e1b5dab2be, +0x152fdbabfe1a0ded6e2ba5497e140ecd1dbc9fa8df6705237fc8c764317ac751, +0xdf66c437cbccd268bdc448cbb706f4b179ba223b6bb87a921094257baf2b69d, +0x15e5521c580b9faa337d9ba06514ac965c373a2e604305b8efb0aad802e72a21, +0x9a09a903ce4f69ab99dd47c16087feca6fc2126ebc4cfd8def7a0253303f866, +0x2bb52dc2028e9887b2a82271ac46f7800dd147e706370ee5edb35b9550cf71b2, +0x9bf3d01f97e22646505f76fdd396b026bc8bcba0e0522ed2ba3079d301fdd88, +0x26b72c368b0bd0103cb7dcca08e68b4446ee788ef6114f6ba899202f1f19b5b1, +0x2bcbae8d5471d562e885b4b185b56ae0fe11ca5bf5461a1e0a41205568525f43, +0x805d6862cafcf5030ab30262a01f2c65b2b7312ac9279baed50c177516bd0dd, +0x2b8b1aa994b54ee5617766dc812d15d3cabf187d8db4ab8da85130f73f01e746, +0x1fed5b75b01e9f4af01ebd30a6f355e8b2cd88f19e49892a19403a895fcf284d, +0x17ee0034bef77cbb115fdd75be9880008af568ed633eb7b2abdf8361c4357500 +], +[ +0x1ed9d3e9276acb7b4dae53eba148806fd9bb07b2dd06187212fab7dcbe63d72c, +0x2c05638ae2f83e73ac9b1bac220509e30ff5757342ccad17261a4c30e3bc634b, +0xf1fa08e424e4691c66bf0a524b81e886da234ba5bbf78cc168c8a13353c9654, +0x1ee32a96f8d3e8fde8ffba0fcd72859847861b8143052e212bb56b103f6f742d, +0x20192d8adf841e5dc110994238180267954de29c8953738ae196447acb182a7a, +0x2419a609a380157d9f6c6e64ae2cfb6e4b39e0d6ec0661b546c1552a620f19c8, +0x3ce58f147c681728f2a2af586144d470e2231e80161f97200b7aa6d624b8bf9, +0x12aba963e415f9bbc95c5f1ca8affd59b6c6b03fcccdccb417a9d89a4eebfb32, +0x167f26eedae299f0e56157c8c7fdda1ecb48f90e553ecdbd4ef35b92ef9f39f9, +0x486a139560dd70e9054321196ddb973e7db09350cdacde3c1c7817fd2b8a46d, +0x1e4a632c34dad41873c541c5caeda02bf58f2127994bca0b0780bceae409256d, +0xa471e606e256e387d5e44d8de55dcdd833b364baf00a694b52e3c10f21f814c, +0xc52f1224066c212a3667bb2beeda181ea00294c5aab9348e5a71d696c8fcd20, +0x1b2e51bf0afc16188b7ec633248eacbdc550f592c742edc91b204d49dfac42a1, +0x25da91e9be50e3762edb77a90706df802461c374a7b90fb2ac018930f3b23518, +0x29db9bd9f3940384f177d7634721451ddd0c6a868fd047161c2358e9c305ad24, +0x7062de34f5c74ad5822948fb7c476255fd03a13d9d8781262712946db22156 +], +[ +0x2ff57f3f7e95b03411db790a86647467581197124d217520ef2e6332a5b35185, +0x27ca7b8c33207e75a42cba1237e0c568d3b31f475424d23a9fd0ba6ef188df9c, +0x1b6aeec49e5936a23d2182de5ca78ca56d4ffe8589d3e77d07a34692a7c5b44c, +0x5e94c1b81bbe16e77c7fd2db254949046cb85834c34e0d8986bff72ed22f6f0, +0x24a01b8801b2865c3a3d20b6f31df95350f5caa9ea158b3ac240ceb81c8f6cda, +0x18c647eabc6fb45dec61bdf9007f83863fb6b7827b23437e10e49baf8e835ca5, +0x523cbdc5787c220da27bcd517d57bf3b31cff9e4e2e97299d44d9f838d96465, +0x1799989ebc4fbcb84e487b4e42f0e4500c309c2d90e740d03f8f9bceda208616, +0x254d90f21c923e30fcb471688f64a6115f0f4340b744c5d732a077f5fd6b46aa, +0x10d8f1c90a94db10a7b730d8c21c69e793cc985e1ef2c62b8815e65c5fa91962, +0x1032ccd20d4ed4502df7faae0b2d9bf2c5368304a24611597d7651733053ce46, +0x39bed2152c1cc38fd8a0addd226c2b5d53097f83d826f7e9b9a3556a32c8001, +0x261d68c368aeeefc167d6b3e2d22be484231b5b800b51394133c7baeef2f879a, +0x28893305254197bef603078e333db361dec1a7775813bd95d39e386729cc665, +0x2f570c80d99ea49bbd76c199e961db6bf59ba6e0a47683923716f9e10e913221, +0x2318f3a1f9ef5c6326960014e622db56d8adfc885e3d0bc2d06e86ec07b156c4, +0x7946f795fb6251bbe041138607f0ee6e1243dca71d592cad53f634dffd91ccf +], +[ +0x15faefbf8584a38969b4a719ffe5f02c2191a8cceda0b775162203d30b80208b, +0x1dd8c52fbcd6e06ceddbc122ffcc656e4c28ae2e88b94da79f3a276bf5fe2acf, +0x2915408b3b7c2cf127999ef3a84a0a5c2de70e75bcb06ebac67c73ad36cd7153, +0x2e655f7e6277f2147665a414632eb3a418acd90f6a29748e4249f6713d54007e, +0xe0dedcb898406ec36e1ad2e3992b99c8b457ccaba2105b4436ba840e89bf0d0, +0x270a85dcfc9c8f202cdca355246fd989551495ec57f8b6533342e3af8a1e6d85, +0x494b4c62731baf8f3338f2cc0dd934f82606e768f563a755cc501504a50a9c6, +0x17061fdaa032097e06c003d9d719d29df4c30109d6fb86def324435e8176bbe, +0xf9e56a5af5386c4884ca7d0e7792a22d3b96a801f3e8e79a6ac6578c1ee0a75, +0x24a746819bb8574eed44e23319cefdd09c0e8c2dd1ce6924a63ffae59eb1a905, +0x703bfec7b532b9135f72a794d9e3a3c6ff665c08d590677026a06cda66055e9, +0x21bf1e826a3e2141ad2cd0c6b286146b530927f0ddca59fa78d06a36564b7a3f, +0x2f678070c83d71945038501c74ba5968b131939a6af6edb297de5f345e6692e5, +0x1c30abb88b3fb7fff8e97da6107209d608fbd9f2db97e61d74dff19d3e36f3bd, +0x2a14fabf9e37f4497914de5868daa628ef3347a611f675d94ef67fc317e28328, +0x9ea8d820c4e6ee47a4fcbfba19cd94e915de9dda25afd1399c921b1b7666854, +0x106d7b2ded46945b3901ef651245d519ae93b8d2eea8160970ed07fcb6f58015 +], +[ +0x1e6eaab1191593de0d89cbb2399ab8aa955d829ad959428cd539be30b72fde9c, +0x12f17c280efa40df0fafdb7148d7ae86b6401f823e47854b7f11c0a87ff00bf5, +0x2fd97c7d4e331e328d3eda047a68a64f7cac867b6bd3795e2932f350644374a4, +0x2c1c8f60b63e8cbba016d475ba0483d001c70653c1ebc256c51e18975371cf08, +0xfb2d646b505c61dc54f56fe9de66641c6797e59e860528aeb52867aabafc2fe, +0x1a44835e3e9620a13fdc072c1212e942ee95e683d6c07ef097527bc10616c622, +0x192e49c626530d5965c53dc6e4209856d71226aa5021b9eaaa1784044c8baaab, +0x80fa9dddf985137bcfe965068449cb6eb36b1ddb1706d8632864e954f5ac59, +0xff1355d96389f7c74b274950b3f70a3d74bbfe992860c7ba6d9066e59260c30, +0x237f4f3d794bd3a23cc52c74e0ee10dca1d4edd90a3a519af54944ac91deacc5, +0x1c94985507159d367f2aa5a1a04857bd44d205ef8439b844386b025976646bd2, +0x286fb15e9ab4224c0319add3a16b8c82dc71931fe3be2f4b3ff0289a5319c4ac, +0x236262438ed3acbbf4bd56c39d12be65fdc0126562bcd5468a49da6ba33fc9aa, +0xf695879295d610d1edb0da7c3fa43c3633e2d02d2e6af6799a2da41e41c3687, +0x22949d27c373e4447e9814d6f189d064b3b092b4480f8d21c8c12342a956cda6, +0xbe0a5f05b6f2deb2fb6bf836805d52d9ad224e8bb8af6e0ffb194a49ce026f3, +0x3070888a62ededfae0d72f144b8ab370f8a54c52597db33d98c24edf1daba0d +], +[ +0x2a3bb020c8a50d310ef5b5c77cc408b077fe2481454754c4568ff668fe5f0974, +0x1399820ddf4829a24bfacbe47f56b793117f599efdfcf9e042bd5780fabc29c4, +0x2303c2e89a14828a19a9f75d97f17fe08b6282fbc090e6dd69a4d780032624b6, +0x1f7a5f8fd30b1f9d7f5855c084e8995367889a1a076da17859cdbbfc8301afc9, +0x14f79e9e9c5998e8cbf5a2f1de18ca7707f5627b5637dcd962725f8ea1804d3c, +0x10199cfd4b1cca1f0cadacfcb429b44bcf83e13ccc098d908163aeaa1cf5a9a, +0x34459376fe4246c7ca6f298180c2150367ec05ede0dafdc4806d34e44c180fc, +0x2933eb342796a75af7e1dc15c04904b5f68bb56ac0478a85233a588509edae0e, +0xed494f6fb5598ab0a0a7c655890ddf4a7c0684f24522d2af98dbeb0204791e3, +0x228e31df905565ece7246c261aa5b700f60f6ddd5d7c249264748ab3e521a20d, +0xd36f7669a52260da523b388c608dc283f107e9578e0bcbe1e3d4201b6d5bfc, +0x2ee63ea38cc2cee0e08789581cb31eee9b112dd61e4032a8beebedceb6aaafe3, +0x2be13746d4b19b770fe382bc7e7a56e805c1ade0c9236e3e28f90a5fa874296e, +0x916249fbbb750e41ce6f9475e6cf6337ca4ace63f7a4a377c14fda9c7b205ad, +0x17855df635fe8e7fc7919412106e9852ecc57aa0b759b490cfc4773078016f53, +0xebb48f5378773ec048ac3eb5c84d44cb2585583ce45ff30a93721d70f289d0c, +0x33106bbde7d027db2f728b2563a62d3d6f8a02ae114bfb8a2593c6a2fc15524 +], +[ +0x51f815c454b6015c7ebf90c297b90e9604cd36acc6af07f99b5e51fdeb32234, +0xa44004794fbddceeac78010d88b2146984c75553cec26164754d72598358b37, +0x22423aac5a0b511923d747148e091d1945c252a77e51bcc62ee173c5483f80ab, +0x1e14c0a17f23e94ac435bb7f629c6c0ab66fca8c4db085fc56be0ad9da545827, +0x1958d6547accfb884d50229a4fd5b234a377f5c671fb865170d0a393680ba3de, +0x14bcc6d4b8326e66b453691e5c948a80a618b4f7ecdc3a380478d43dd4075ab8, +0x193025256b9871e2afebc966ed68f38d2f906a4870652805e4246353f567c5bb, +0x1e4200bffb9ca4e47bb270a09e8fd994093dbd4805c4cc15185ced28ff872e10, +0x1d1fa5a83742eb9bb853197f56a4732625b2474e7aadb9311dfbdc0f41ac61be, +0x2d650daa87c7e1c09b53b10595bab1e14c32a67142092876c57b4ba68efafd51, +0x33319bd5b5247a3cb7f63dae46dbd8136f3f3a9b4aa0a232309070d718f7d47, +0x26e56b19e55c9bb5df436c13eb6deffab5059804552442370be53a951b0a9e22, +0x1a0f0930bbea65ad095174ed8aaeaa84628d35471bdad37bdd624d2eedb6bf14, +0x297921088a94bfeeea233c91483a21bc59982034e0c8738c6526cd44f9a11306, +0x1082b0f264c61f37b71fad404cbc0207f809cf8002a7e39c0290d88a48120356, +0x25cc52901aebcb35f9ce47457bbc4507bba219c88a5bd1229f6dc46c503c769e, +0x2ae1b5b3e89117e08bb7385e0b711de334e8fdcbb50ea4bb3718d5e1a0bc8075 +], +[ +0x28b75c2ac167fdf184725317c7bbb8083e5ac5bba937bcfa6cefcb69e4048bf0, +0x4eb2ffac1de16288f52a4b74101cb73d53addd56bbed326bec180ed2363c224, +0x2bd52a360f3328d5c98a6b2de15df151e997cc92c2c72e542819e317c0ee1d2c, +0xff14782906fd866584bb5e93cd18678c22e320ddc66d6fe0e917e18de1094f7, +0xa4a053ffb41f84af21407c6151dc5496a9651a519e317664ecdedb017e3c50a, +0x19dfcf535e723327add95d36e7276afb472408699d7212f34abe32f808b4d292, +0x155dd9ca7898b0559b3e407149e6dd64bed6f9811d59b1ceca7486a110ec99aa, +0x2d9c5bcd84c97759e28dbfdbe9fce6b3c1cc7cbc9a2e35f2ce8a8bdc80a3154b, +0x1ff3d01d32a70fa0911119ebbcb4bcfc1b4fc30b2ec2298832f5da4dce3d7a4e, +0x44ce295745ded1737be0bf68729d669efc18e7e9b55e6ef65f895e2f9e95056, +0x117377429e138736228d8762c8c6567a936980b7c043882adad3951b9986859a, +0x39c17d50605261dabc76676120b2b889ae504138ba722976d8dc822bd1af974, +0x2a6f067cfc9dc40850f552ab42d6c096da045f8039453d7a9e028c39f2f1377c, +0x1d7e961151f8a1d1f6092f102a7c911194618a3bae9ef78de349a99ee05ef476, +0x20431e5d3bcff4bd90372a1eb637c04536317a81b02b48b5a3ae45a4e8380527, +0x116b0dcbc35fae766914fc09cfc359051f626100151eeb2a762d7a0738132a30, +0xab340604e81eb37a5dcbf1e7d5ffde8f2221d60b382d43cf75a0f1360ea5c72 +], +[ +0x23af324599683d9b71b61d093d63dcbbd97e44957333d2697fdd060c1e4b585, +0xb11660056e02d7f845b79d49bfbb685555febb54eaa503d987ca5299521d16d, +0x1f209382e3fcb44eb1b1c03dc2be195b3f92faa9c1ae1a0b57c4df69e7a53d51, +0x22e25afcf23ec18a36471d593ebc8d93372315cd666db66bf398f7730285f9ae, +0x18eaff4c9d5d00d3483d7b0c74551a4487c452cf672e6a74ca397be38f5d793f, +0x1ebb9f7b5f7f0c553b03552d104693515ccc17529c6c1a462c0c24473630f678, +0x1212ba1ac3bfe0c08096c503be351bbaea92aa3d3f6c264b73c7ceda7f8bd721, +0x2f0256f9b47269790f3f2b46a7ef2536d8661dae60d50a61bab58346e83885c0, +0x1b6a8442e48b709797a514e36c1f86b13a413eb1f7fef458887833ef4b482124, +0xc96e617f36391cc516eb3631eb8a18d4dd10d17135bd93f450ef6ae2a945117, +0xed9dc15c9f4a60f8150e367ba71a4a37a9cb50c9031194f55850a1e5e325911, +0x2b8b201e13900e638685cdb4d07c110a8f8e8d500cee83566aa733621cc20235, +0x23bf4e044f678ba1fef62ce070897d6373914ee936f92a2f4d5e09890e238e34, +0x22c93d459ac5db54f2b6a4f267b5f049b976a93d006b88a98a5fc0ea39f53a72, +0x1a54b0b47d98fe83acc4dfaf83b8bf7d972684923d5c7dcea9894b6a07d934ab, +0x22ccb3842b2d75a33b65465a5dcece6870afabb3e3401faeb6504de406348a23, +0x1e9abeacdd2ff75cca093b6d8826a46d8d2c05e30d1d3995da76a4a8ca9d2824 +], +[ +0x5a07868a7c95f50a015879fe7cdf1eb6c317e4d489d4515208ddf40a32329ea, +0x28c53ca5db5ceccab548d154ea6071e47ca73b6cd4fda7e423403cb684d3070e, +0x651a487e9ef91d9c4fd75178dc57aa1f76edf56c4c5c2ba6ea7c6d919e91440, +0x16d216f97bdea9f8b01025cb47acd5d03e8469dc6b558a235a23d2ba8773c71e, +0x2c8a5c7f394b071d0f329d51e451c8738f896a2b8f87c6eb3eaaec71ce1cf71c, +0x132175ccda95488f348ba37b6c3641dfbca9e4247ec43977e279f844330cb694, +0x28eba78439ba284229de2b1c6124fdde36323fc82805988501337a3b48aea040, +0x140f550b1cfe4079f7c44efcca6515f70a9ea190d2cb4a2cf116719737b15621, +0x1fa08142c4cf49ceb13532ff6f1c453f9ac4035d8ec5514f4f3b52c3dea9bb0e, +0x592cf45e5a2dd382f1c6ecb059c99232e2b52bac5475c10b6669698cae88827, +0x2897ccf4f75df225ab5b1c79de477945b24f2ea127c5cbb37954370505957a31, +0x288ec4309c81a0d2ecf16c037706ea4d526d717285ae02da008d14cb8ea23ec2, +0x12bd882b0d8af801ae2579a884b11f80f1ba15f48741f61609466bf04f68cefb, +0x2bbaca431e1d464281a1e6f483cb4e9b2002d0a0ba1fa70b60c1bececddb1e79, +0x173087cac123e07a0324ea3c2231cca859d7e4d112c8e2f4dc9249551c941007, +0xbabc1aa6aa0d7b234fe81651f7b6d616607fa766534d5baee6f63bf02995fed, +0x233f5274aab1d107af4bf7f2b7f4d57d8ee0936005a3525549cbfc75697ca640 +], +[ +0x2c5b4a65bc55ac5fbeebde53ce5fa68882faed2a92a7b3f5732832c72f7f2c30, +0x17d5e7e1862b3708cba3d41c556b070da60b73fc3ef198227f2dad5b202d5c9a, +0x1d7ef8564a9ac7dce945477d529ace63481ace463a86cbdc1140645ed57d0b3b, +0x1edca4960596d41548199aee6040d39d814e4562492a070730982f9755615117, +0x258655ae996ae6e4deba6fecf1190c2afbfc1dbe82454558a18bdc9819442f05, +0x279a42b218cc556132ecaf5666c04e89984f5ffba4225281d3261a48bec6eab9, +0x24605ce4aaa33a0bbc08d586cafd70bcf4c635bedcf98afc3fb0dd32909e8ff, +0x292481a792f2dd4979b04822d73eec02e90c1e4ea42ca5414989ba04c31529c0, +0x19f8effcd417b79016b57398a7bab72f946e75d8628f569f327df5c6832907a1, +0x279c71db7cc16b9c726b934545c2fdb75d956d16f89210aedfd7dbb4f1d9ecfe, +0x16f4afc47a61df3374a702f2800a3a39fb4450a9f92e11e240cc6d76c252de41, +0x1ba7d8b083eb0e83cf9178efe8514e612a5d3905cb9e4279b1c09ae53e8cf23a, +0xa1e2e12a51722b6e0acb9705c443d148b1334dd897185eedd4c4e87170e42c3, +0x1d6b7bb51eb9ba719799096e5e0c1aaa594456cbf08b2bf9a479279f7524d3f, +0x1129fb969355253e7cb31fa942978db34b7ccd3bc0d0cd02ba6a49e159d1cc7, +0x23e3f31479550cb197235af10741c376d326f85881d1f1076882c928212f8b9a, +0x1ac5a27a1a2ea0d7035f74d3a9b54b671e58711d79c87b56d32e40983b62c8d5 +], +[ +0x173f895e472c4eb16a2aff3b8e0417fb32b83eb1e3233471c76a0550505d0607, +0x500a676c5cd159e6351ef8d2b567646fb4d4c61d3c0b828ec201d4f425991ce, +0x1aba42213aa1f15e7550ca941d9bc485e195ac204c5036afee992a967fadc501, +0x20ebc05e620d2c7c362f8d7916ed7e3e12802cdf41c87b06790c40f5efdf724c, +0x191531c0fa2c547a1eb51cb026e79cd663abf458a2e8630e83c1f11876aeccea, +0x1ff17bff476047fd9a466842c8fbd711c1b3c1841e109c687ba4620ebc49969, +0x17d7ef1f4f75295cfe214dce7fc21dfff13ff8a3c7bb86224c8a79566037179b, +0xbc4494e3d58cd6841d0aab064400e6ae8594c35f7e9672c55f283869e0f3f93, +0x174a4219c4aadec5921ae738b7cb40a3219ef5dec8db3bdfef39b373b224d38c, +0xe989d36297ae2397d85b8025bb304fe42bfb8bf93108996d2ba13968bba9874, +0x1ad84e6a15633eba89050cc15d94e459a6c2d42825986f9c5803c66f08976329, +0x6f0eee01ada409058a818ba8369498fba956e713a7e9372b4220ef15f954a99, +0x74a08a71a7e34b1031b63978e329bd0e12ae631100f24fcecb5a60bef5c3ddc, +0x2185e4a0d25570c435162266b565c1db0f23ce4e61b85b8b8a1872517754b632, +0x2bcd8e3cf988891e58bf8b8d3a259ce52f86de01bb8e6c4d49dc903f4b3ecc07, +0x2027fe75d87804599fb66c0d65b287c4e0582a4e8d84bbbc85c6422cfb5eeb9, +0x1e2dbde2355a4d9c61ac0c0db87447c67e08550ac91bf04d96790142d88cdd00 +], +[ +0x206cb038cc328526d0c3dc5af19437d83219751c5ee8f61b0e9e2f5881366be3, +0x255fbd250e6628c5eb540c311936b282c52204f56fe81ef75c398d9f0adebe12, +0xe14d98de84653e22efab29261c9a36c207fc9f5650ec1a5bdce6ae992239e84, +0x1342f46c9e240aa8eb2f1dd6c61d0bc79fa6cdc3dd8fa67d79729b02343b6df7, +0xe41cdc0db95ad5d67946f0ff028aad8c3a3c88acf10519e736f9265ce19a2da, +0x1cc6d37794a5bf901341db685e790cd7f7427b669069e4d320efae1d55bd7157, +0x117c39e46a1ae3c90b26b0df85078ebdcb66362515c74d51cdb192f789c9cfc0, +0x2b4c77d18677eb99a966913f7ba7b478ccda159d0f61a58702e80f4952b37077, +0x250d35fabe31fb7fd1719ae0c13cafb64e706932fecfe47e475034289443f240, +0x2c712075e8848b2d26f7c8c6f7accba81a49800ed3515221f03d845407b1e1da, +0x1d04d22563bde8bff1b425e9bf113cfe2fd15dca666b9130e56511462e971465, +0x135cce03597dd23591aa6fb38b2e70ca41ef91ca05997adbc11354cd831d57f1, +0x24716ad2942c2268df507e25be255e45c00d5dba96093df6c63c8a4df733f0e, +0x11cdeee1ba873dc61888aff7be54fe50e03e3a4a5ea0f32c6acae7d15d9f7979, +0x1ae588627ea2e0c046ed4f6c208f29803a25c9b2c0c385be294b9c25a3287e47, +0x8e0df227ca5a17a9081c60caedb5435a8aff99371a70219715b05800ef811d4, +0xa1cb35782612c7998afa40dc467fd39c882e6b3dabab079e63c330bbc8e5f1c +], +[ +0x240c57897161666f28d000b88d3353921d967420f401ce86bbee42be287a4f8, +0x7c9f836c94eef4e831b3126c06a9b4ba19c11c7e886f65c0d6267e07882dc57, +0x156f5afd193a11d87249f3422912980daacb8fed225c60a5bdde7c4d93d5a019, +0x203a73837d577d910d3bce1b15fef96c1bb522d4f02cc4032becb907810bc85f, +0x217ac1a2f28cb7bd2509d90ee4c03aab4094e3fef4741cf4015e1e823f71c0e, +0xc2e41be00d98a8dff8b30f5dfbce2708412e200682bd596b2162700a67274de, +0x1fd5670b294ced78188cfd816a41358ca32bbe8e024a2a200fe11d060f8c5e1a, +0x2884fd57b70a2305bf5b94c325b01d03f3cc2e8901014e0be3dabb984514863e, +0x23e772e0725ef73aa18f59f934dc11bdbf5fae9cc67fa18a2319ea13a69b9c4e, +0x122366ae0642411af291571a8904f0b6c6fb11d1ce750b3316ac35f310e5dcef, +0x1d0b0c33d83a40412cdaf42cb7ee8e5042d9a73eb17a0d5867a3191aeaea61d7, +0x8eefbab2c1c522367f543c33400cf254fe07711f94e9036a7558565e7305c0d, +0x209ed5faeeef4d1d01bf753704574d34febc7afd299a04430bc0f8f0baafedc4, +0x1cb753a0f4efe61b05e95e099e4b556770b364873d99e1f77e38a53e9c262673, +0x2a32d7716eba1cf93c98e9bbf805b0e4d27cd7e3f26c560beb2aea41c1782d8a, +0x2936d36a869b8b2318109412bef3c1a0407a8e0b98b4959ee0b624c116040494, +0x281ad4ade7262394bc55b71a8aeb4135af3b0c2433070cb0ebd9ec8e20dc7280 +], +[ +0x1aaefc2e9925fcd453996fda804063fdab276b37c5f51dfdfef9255b4ec10cc0, +0x2eae17dc561c37084e990fd1bc5057d96e7367c4b801d27f6a6ad8e0d0c0875c, +0x247ee52031ac073a81f56a957908c200477513fcb9853942a62b06fb6eea3bc4, +0x275602e8ac1136b245f551cb053d7eaad7dff488df3f645907a5cb151c553523, +0x6143a7c97a91838b0ad68065370bc9503d3e0c8d11f2a840b2c32c3fe2e79b4, +0x1f3aed03d37f7b14629aa2e5f086bdfbac862325988c4da943f88f4313647df1, +0x18fc0aca1d4a45978f6e3fbc4a35a2579a4c12eb6ea700f79ba56727bab87117, +0x97c4f0ca6dfc073c84e97fd4b2c341ec3c45b6f716700cfd7647e423f5e634e, +0xde5765593280a32bbb1630216e58d1d669ba575b7d276a2432d9c6ee302a5d, +0x7475c2b72238b87b0d8cdc92890f037dad0bd67a3c741e5672bc8677a35c206, +0x244e984c6f2f2133efa9d5dbbc1c60463d26f7748650658395201b367a39f554, +0x27a55f5103ad08547128724e6c20a4ae7af36be03567e4efdeca9880214d42a9, +0x14b2c9ae1ec7a0c1593ef29e782b063ed48e580ddc3255c0a1f081e69b634448, +0xeaf70eb10be27fbcdcfa7ce5e1b289b66fe68a3114038522d61b435f17ef209, +0xbf40bc87a391c052a56e43aadd307df751dbc47ef7c6c5af3e7bc4ce0dc942e, +0x3afb962f8ea2cd1affb52a50cf59cd5b1f08f087537859e8a73524c3c7758e2, +0x240011c27da581b7e91efefbe8f37abfa3c6e456ac5a6da05d4af4884287bea3 +] +], + [ + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x2cbd265ce3e5beccb09bb3189ca08832cd4fe102f39f9ee2bfe851a8038ce383, + 0x1e0217f13e7f212053e2de966a7ad7fbde6a7d47335bb58b2b148ac4ad7b8cc0, + 0xf885c4008d2a4c2992b3337f1c0eb3b21bc5569e7eb6aede116420d33f981e5, + 0x2e9c594b2023ee628c88f7a8cd002e06fddca13a014922ea4fd489d7f00d0cc8, + 0x217afd05c2e55b85675cb39f0aa486a11691557ca9ee1b7ee42f06952bdae058, + 0x1f8f067c1602f54ba576795e16bc269cc4f34416fa619920126eb16da9878c5, + 0x25f3633c988971494c6c37a0de4b737a88cd5be9c14dfc66ffcc4c5200c3d6fc, + 0x18cdc8b1d7543efccdebadd46b6e9096117758a3e2c638bdab7767e74f88747c, + 0x1cd8be04f1ac72a0b7daaef83a36e688046a41b7d4ba83aa5ef3a3a4de8e58a5, + 0x1a31f69bd76c670a3183335cf97746f6676698514467df13194007eaf8ed8b8c, + 0x2ab2c3d35698ec035746c4131c8d4cdae3be77eac56e708b6fb6a9832afb3869, + 0x2217b8cac3e14934002e24683cb6fb96da2b282d12447fb97789670e716b3bb9, + 0x26d8ecc33cf52610b26d55145f298e5a387c1b4587d44bc89afd2ca81a21cb70, + 0x19b5fef4d9456e93fe0799c1b568e2f6deaf43067e119ee89cce7b1b0074e8a7, + 0x2f0ee317d5a1d6c6d6c8b01f100eaf5389bffe269131af9eff36f71b3cb7f4ba, + 0x1009a43a6a00db52b2d0e325312220738c996b79414b70b2d04f61bf8475759b, + 0x2881d241ad316ea5b04bb05c86484922c0b6c6f01173a1e84af83d8b69bd23d2, + 0xa3aa81c611a57f509b1f971352d680f75a03361e74a5c12594987287972c39b, + 0xbf1eb01ab9b46638fe9d0a135105ed65848bdd9929b93d37369240a6e5ac276, + 0x1666fad124b64cb1b1fbcc06ee6180e2d3d98bdff534ea0d4fffad2413b15925, + 0x13006947e1defbcba51ece18add637d08c38b973232ecc68b6b2f7fcc0e40f7e, + 0x20cef2fdcdcbf581527d5fdd9442d7d80e8c122c60aba74a349e318119a9b077, + 0x29308abcbb8c3d71812419611e6e3f30b64b8b3670579e5f7e6084c57f8180dc, + 0x20a651bd8eff8989f70625f7e1db0da19b408d63385e63f8b1f066d0c3912e0e, + 0x2fe8775003759af3f41c2f923f0b683c27cf89bfa609ec6fc26714b8fd7c5ea7, + 0x226d37fdd9023563a4d6e2a3bbcd23137d949f36b2d9b1b8dbafbc644ff2371d, + 0x2f11eaf353125b5b7110a75fde384c14365c2e2cbb1140f8b520204118ce6897, + 0x7cba6d14f09fa2eeec2242ee401fe0fa089c28bc77f02f0aa90a564c10b4e29, + 0x757d39b861897f4ca863713452abb9e6c14f8736417fce8359c5b4dac5be0b2, + 0x58992f42ff62ae08b3daca79a5ac83d258272802dc6556aa757b390ab22d6cc, + 0x1fa470cc67647213df51fc636fce6b6e69de3a665044696f6bda9316fadb5a1f, + 0x11049230da628e01b2a11af1b214327c58092bde0d949e8c08a0c929b39a13c8, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x29e2fa62bb11282bff23cddfbd44a2d9fca9bb0ca099f34c63153d32257e8f76, + 0x2ec58445b13f4e1b14d47aaa8d3c01489e81838dcf6a8fb2e79ae1c420dbac0a, + 0x2a26d88da92db338a1de3d64aa9f78389c45cad24daeea74fca5c5721cf0b079, + 0x25240495a831b1128568257ef0c438a227576328351ef52cc3f6a361ad097666, + 0x10356b86c6b5b46fd0913fe632fef7bcb9507005df6fe46be9089f96008fceb1, + 0x23967538833c9bf2f3a2387251089e68c81a47051f8c3154b5863fe78a6ff6f6, + 0x3dcf91d2608f94783343c6c1c9cd24847ab2cd6778f568418527be40ac23e89, + 0x1185195857959b965104d24285d2f83365412ce31a6abcfc936d74af9fb8fa13, + 0x14ef1e17d68e5cbcc3a90ead42b8c438fb56b5fbb950d8883c2d1660fb2d1ded, + 0x1175100c6ed2ddf68ba552b4f40c27047fe02cdd2b533a3b9975454399294205, + 0x230160f538e3585cff4bd3cf7b4fe333d2b2a35738fb135ae6dadc075f92ada5, + 0x88c4e4fc1b21270a933a937f739bbc7b6e7eb3e316ca1b3ebe5727e381742eb, + 0xe3e345debdf5cfbd7bb9a4cb5d36d89c20713e43323d4341795448aabbd76a3, + 0x1a4ed87c8037af1d025638bde6b974caa276671abbaf0210cc7e9db2fdc9a345, + 0x11ed48467664df00548f3cfc70eed4039f6a59e826e73dc4b95990c03a313829, + 0x18ed0bcc41aa34c5556a7ebdf27ccf1a50f32561793053215a03d931c4f72eb0, + 0x2e73e5ff39e58205a16e013ccd0dd935bebf06505cdcd650935840062e8b1f8a, + 0xf66bc73e8a87b0b028720dc420534528d2fe5609bcb3d600507a6c19d20cd59, + 0xbc095405abc012247bc4a7277cf59e25e39834bd5839542cab959ad534a23f1, + 0x1fc384fdb89e274dad330eef9dc51855c11fdadb0b9b052fa220eb3e38d61254, + 0x2805a26d24644536da5f7e9f5071443189a5f102b92613098a8c23dbe887cee0, + 0x2a2eab082079c60e24bb5dbe3549bf6390708e8ccd034a2a94a71aa9c414cfa1, + 0x5aa87bc4fe90cd48a59fcfa82226cf759ce8f60f8c208cf9632a28ff7b680ed, + 0x2038aefd81a73ef09b7d0fd466d2b3c8aed99ad9ce559eb2aa80d7e06996909f, + 0xfaf97c7bbde99e8853c67af9e2187b8ee3708e48da3446b3eac3b3252a057d4, + 0x5dd570bb1e0feb5e6f13b9dbeae629f6f3ad06a365d9ebcbd2c120c6f76deea, + 0x124548796b8905caf386a61bc868d1467251cb29948ff1f3ae4847c724ab97dd, + 0xdf9dc278a65d06f8c477dcb8b562c262dcb7f9ca4d875070b36e9c2e7fcf277, + 0x725e0e87db61e62269f56d25955fcfea65fd3882320ba3187611e7bca42c2e5, + 0x2f204d469d9ae7b364fc44f2959956654f613f60cf669afe7b69a944b6903390, + 0xf4165ffb8c3cd0c8df2a1cdcc6d99d487b204cea36ba8023e6a17c90c50d3cb, + 0x1ab6363cc8e8594caf364c93385aab21b86de4aea09591b34df2152f6b663079, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x273626b708fec9b5d1d1330bcbb2d80d97ac1c84b89895de0628a0f15fa73ac1, + 0x232c260995bc29571e821068a7fef290fc1fca974214b45cb6eb63c02f56101c, + 0x22a91317e4cd0f048e756b7b41c10a9a10f85683df9051b1aac41cfb73dfa959, + 0x1789ef31e5469c8fa9e265becaf3f6f0b66989dfdddfc52491933f990624062b, + 0x27502f81423df0f6f223bfcb038b0347be96880b4d9b26d685bc87df88a12f80, + 0x15944d6894aed7bdec1cebe81ea14066dc63e49db38b79b63b5711cdea0047de, + 0x2d5d79c75632ff589cea134763ba602c43390e05fcb6ff8e91fe8376c327cfe, + 0x1f83f223b3a559ac092b5ce1bfe95f81be64ed69bd2aba06181f9962c09ce680, + 0x1d9105ddf213b013cfd5589de071e9a19becac29cbd9f5699314f7163f14f642, + 0x2d8879a2f005d4829b5439aa1630fe03cb581dd32be37ec112cbc8fb76715870, + 0x898f42d31a6838f40ddf7874dd4afce3481b6e1eda04c4f22f82e3a7c339078, + 0x1e5273fcce91ec174a392d2b384eaeeb2856c1bdb4342e1a38976f97497e51ba, + 0x24a863988061d2464b7bcc8d4ed630e79a471fe07c829d9d6b5eccdee1740779, + 0xd3f2af2fde3dc00461fe65fc25d8ef32db567495a78776f0f4eac20d4c23222, + 0x11130f82fe058dbf04d8ea6be3175f22ecfef9c4983545870967c73267e0dd64, + 0xf327ffc10a298ab4376b35f28b7eb90e794b6c9617b9a9cb1fd60d1e6208fc1, + 0x2fc6a08cdc07224db9ed85c48555e9b6747d401fc30b477a376470a19189428d, + 0x1c33ad6d01026a48305011699dcd1ca89d10a95b096e2b7d60363374c038c62e, + 0x1e5457fba2d9da56d4ebe957e2a4960a45ce9bb8c941e2b1bcb861f1c1d88bfa, + 0x29d2839ebf586fac7dd395ce00036e0530bcfaf01c6619489494f78a6f7d5ec4, + 0x4d8bcbbde662005d7bd4ff16ef911dd1fd74e44d850f665faffe0d4724063e1, + 0x1f110564e1708c2705cbd95f592a618406fa8ccbcebfe3b4fa9420636764c7b8, + 0x1588d891ff3d8526d281bfb900ea2b4de960a5d2b3740c2562f6a8ed53f374b3, + 0x639f2677710d59d2708e3ed851a80e7133f603ae0276ec542b23181fff30907, + 0x2a2e29702f1ec78a47401585569f7b48e63e397bd64ddbef59fface62fb5591e, + 0x172b91ef6574d5d044f3e03e69e270257e80c9cd0f1000cb91d7a718971dddc6, + 0x93f4d3b969bbc023ba1de485797a6ecfc42e2e9f034ead04b17830f297c15f3, + 0x1eb585e563cd03b430e0947955e5b906db9b169af33cef14671865a04bbdc7c, + 0x15167514d32350029469eb274806d81d6ba80981c4694fd030f0bd93c8ffcf31, + 0x1240581c6c08675773597b9d50b9187f160fa7d7a739630f943e4df9b1801237, + 0x1598daab9828ae0f9490eeba9d3dbd6282a2490db8ec4789605289a3109a3079, + 0x15f48fc5ee41eb8cb97fee7e78b55d3fda674fedaea91534bb506a4b440ea560, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x6b19393be5286a5cad14b6fd12c51219467aa1dc7c4923753e7b1adeeb464f, + 0x12ab8709e0b7289c712a002a6f0bfe6e72844177720a0427631540c7695e0905, + 0x145662a0788a01d81bbc0df72d6eaf0e887d22a1e4aeac090900c432c4132fa5, + 0x1d403655755dcc00c298137bc7e029f140b9d9e71d30e9145f6dd2a040febb9b, + 0x2370434b953dd1d26c4eeed6cae501a3758014dbad14bfef1c3d26cd0f615837, + 0x1f13968a23ad91e74be05489afc4b2dcb41621f6fb8b52f73c27bc2f64d198ef, + 0x3012f6382c1bffa9df0240a0f66b310a7463e49e7cf74facc054c7fd124e20c8, + 0x1da5c938033392ffec34887bfb06e6317655c3094671a68247eafa70d630c144, + 0x1a94414d237c4ad29cdef25e46f49e5e939d9699e9a36824f51aa65ff2adcb04, + 0xa234e79999d9f55a21dc03c43eaf5e018035d2b588d5ec8cd2d1df72f83cd87, + 0x9f0c86d7cf4004d071e067316a8da875d4405044b0e799616e22c96a1140c26, + 0x11bdf8824a0955d04b5fc96abac08049c0fa9cd678bf055fec2d43634170f052, + 0x20e74a475a9faf92f4998eb559ba0d8f05659dde0ecb757950e8a6abf015d4b5, + 0x1366321b06c12b977c2c396974a2a6b0c4e58f09a53531213c6206d072f4d074, + 0x1b2b47e3ea9a39df6a054879cee1ffd2cfd789acd7823e765c675241c3acf498, + 0x1e94a144e18eafc014b1aac9157ec2faa99affa50a05f8a8ae8ecb152bdb85ca, + 0x2fc95ebe62bfd5cff9fa2464bfc67b854ab2aae650da63c494d87294735305a8, + 0x1ccaf110504e1fd4eec6cab1d20f863feff3910d832fb789ec7e31713d262bdb, + 0x151066f81bfe7b4f1ecd0f7a8fe09a48ed40b0c9450476042bc4303602891d0d, + 0x22f0502a277cf27f336d9f3ee1fb7d67fa355a2421d4a01d121f1020e44ae43b, + 0x234465d17d5ca11607fb6b7f3ed5d52d0c06dab7b1761356cbbf0227b5777de, + 0xee0c8ce14909dc5d73607dba19e39706783488f00b8cac649546d934dbeaa54, + 0xc1a12f8f600bcd0dd2963fcfb7172d5842b12aff081a8163fccf1eaec3284e, + 0x27813f720b7a7fee3b44b2fbf89888c664d960bfcd775816ceb70050e6d26308, + 0xef129ae227544508104a79cdd0fbb9e8247c352c97190b90b5e5892feb828ae, + 0x1c59bcacb92f3012c6299cc6b43ba9269481cd107c161406349db4f728bfe66, + 0x8944ab7daebb6884078a8d618105b8843503a90ba51855c079b13b6aaf5b4f6, + 0x215bf9136c8b81f9bd5b221d37fd0fa327f923dac9d52ba825cbd3d2d62459fd, + 0xea608a14f0b4b405017fa637237863552a98cbb9bc1e151b7edbe8e6d78b598, + 0xc1aad9a675df88deccc3864f8c6e16cbee74db5441a6fff425a2bf2a6f84d67, + 0x243e3a95bad03705f35109af4c8c377983f06fef4cadd95c03833dc06ea51296, + 0x29afdf61d86b2558a0cf6083069157e5039ad172997c8ae76857f73e05ca3eae, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x1a85e806efde07a54e9cc83eac927ee5f534b01fd41388f806298b28501a5f04, + 0x109d8bbad7c3c77bab1a8506d4d588e7f5b703361a6ce70d47478e7464a73574, + 0x12f04b1f932511c8596a8c3b5f3dbf1f7f1d91554020fc43db068d95b8e6168b, + 0x1f28636d87164d2217fb393b23d0bfbfec1d912dca3fc000ba1f3e2ef46b8b21, + 0x16179a1cfaa92c905e039047db38e288d336b355029b1ce1048168e55bc1d701, + 0x16c3deac1173e14fc8b54c4da1b1ff61b7bc4ee2b9c62c2871d70a14583432e0, + 0x176d6148624c45e210837dd7fd87d4dc9e89f8efa4dea7c3cff0702fc2bf042f, + 0x20dbb69374e977536f1cdc4a084edeef4ebbf0c9c3cc4191fc4a707961fa39cf, + 0x2bab10e7b585d418399454c7d80fd38bb23190eecc5f85f410d85300487b9ee9, + 0x1bdb9ff621833468a0476986be6d6d719779ec581cc283a11aaa42c5111d232a, + 0x6660bc2be087e505eed7f1d4e5d8418d55e799008cdd4f91bfd536900e9f7b3, + 0xd4beae63787b3447f813f245fd8b7d6f49c83d63fe74a400dcd66cb3d363af5, + 0x1d76613f447ed37b64000a928b3b48e2e8dd521aae874d97dad7fe9b4c57886c, + 0x1f84a0ec9dadcd3937a045561b6205385c12c2ea4c562bd420f3d27ce32677e6, + 0x1f6424f12e6950564745b305080c881ea931d9083649631687a5a302f1d86fd4, + 0x2bf626dec6b3c130ebf137a656988397de0601250e39822152d316537a891fde, + 0x134731482b66f87776639ae513fa3245540fa1d34e6d74d32f7e9587b851de32, + 0xcc894c9be43663bde1317a4e3591aff66c18abdf0d8b90d872d86012e2fc8bd, + 0x22e690f84991940125c64d8513be14cd3fa81c1efc12bb80a6beada80c7091e1, + 0x14287659216a6cb96496ea198bfae1408696c5561f01e9504d5904044d9cc1ee, + 0x237b66703bb797da48e0c64dd6633de18ec506dec2d4d72b28fe93aba30b1621, + 0x1eb201c3e2663322f85acc8d641a362ac1eb1dab575d105af0feac86d68ebb14, + 0xf2588703431e1b9b0d059f900572f8222df5e7749dc0f93c09a24285fd53e4d, + 0x18a8905e765a49b51060ddc06eacbfbfbfcc0736f621216de0f9a1a11cc66484, + 0x10e1e120dbf75198c342b585b49bd0999633fd5310840e725642ae873af4a53f, + 0xe65310148d5dc0fb00fc135ad071d9b07e28b32dff7dd8fb1a2e0670238de99, + 0x1b924a6cd822b0eb0c6227c810a51c540fe9d9d07f906e24a57ec6fece7639e3, + 0x14f708f7a7c1430e9f6adf3a23f1dc38c92ae2f175b39671aa297d590f7806bb, + 0x2c870cd5699f7a402a473b3610adc0b1b1dfba1798b30681de9359334891b5d1, + 0x2c2793cd489f2a0ba8efdda84b35034f81bc47c131a3c6b6f8107f7cbc5ab058, + 0xf12b486f743b8613685af0b508c3b3c41608d34b82c7dc3d8f15277e31842b6, + 0xea23cccde8252adc358410548ba3c53e224a3169e6ca958458940f318bbefa3, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x1e5a6dba6fde6063136d0d97f46d5f292f065b8a9db8f2ab07bc17d31566ca3b, + 0x2f5bb6281fb3085c9cf508288a809476a23c142a459949254f99e0461496897c, + 0x230133fa9c214b6cd63701c3a082ee211c2d4ffa7037d0d0a4cb63a77ef5b696, + 0x7b9beb8ce1dd13c153d36b636a7af56db3800d97c16400284b5563b192c7803, + 0x18a62bd663f364bfd0c79d7f3edbbaab5f58eaa44c0fc207291c8f71222059d3, + 0x909d7276a02aac190974de34558921d3dc8e6ce22964f0e97b69858bbf39108, + 0x191ce266e49cadd50eb403e7fad07cc9ced8d81d8d23df3dc653cc69a8e62310, + 0x29cd029dbaf281a5b72c6d730674b53cbc773dfb542428d45a11d443aee0c906, + 0x1235f2e3aa2a5663b1dc32d86d32a8e2ddcbde4e97a3edd894c7cf2f799e545c, + 0x11310308464e805034d840a94d25a3b8bd0c206d663f41d145fa66415c2dbc12, + 0x2007f67c3b1d638da29631206a6befa6e21365aa1edb39a6f3a0abfe94fd2392, + 0x121d527f117db7b0a614ad1be6fea1f84369a4c6e451c0d5d2537983fb6b913, + 0x1ca4a6c7ee32ae8f3d55e7b5f8753ffddcbc125e170dc7b7c8ba2d62701aeb80, + 0x2f4ff9505df9f5dc0ee5584631e6f331213d654435b5d2593d249b3ff4e64802, + 0x186af707cd1927045cb8ad1b1510d4150928d839d07c8c9a3d93411262351327, + 0x291caa38b2e4083119c579ad08328807d4ace7deb24f78a5d4d208cce95055a3, + 0x27e62d562d2936ef5dfd0aaee64cb42d6aa90006a6fa74a7ccee794d78c0faab, + 0x2706ec2021ef6f28fccac547cfb1aab2da02f453dac5b2daf393ac9bbfa63444, + 0x2c6c0b69710326e4bf73840601626d94cae75c92ca37aa5b5c6e61706cde5a5b, + 0x3bc51987425528eee7a4a3177a8ee4571ccbd028c70ada4bbb3f8e6da3f58eb, + 0x1273940d422f16d7b918e5b6bc3dfdba2b22abb42cd67aa154ed75496186025, + 0x253094fbc334240ab67c86378c9d8d7435f3d87d5d68f3ae901fad214e0dac85, + 0x1cda718ea0bd4ae40920c54c9d203f88deef3e00b3a6c3a5bc9243957c20133a, + 0x125308584766a4ec9815951c72a099b9ef423fab29783c9c8f8ba14ef8221ecc, + 0x130af16ef6729327847344cdc8439079d47871751ed3f0b871dc248c6b856b44, + 0x2f730d5dbd23018d8c91be93b9e666cfa9e9c077d3b2724c43a16092170d7040, + 0x278ad27534ef1afa5d3742e03bfbec8156aa660b0d663b054a5feff049aea2c8, + 0x6d35c831095f5def4afec1841c74aaf1b18880eaab4256ddba34e49653c6169, + 0x2a9eb03bb2a3ad110273c506031de6f432b6673655255c4189fd2db2d9956d24, + 0x237bad6e8955fe0485f4f72b4024855f35903b6d795cffd27468a7bd0e47056b, + 0xee091319736fcc0a648bc6cb1b31ee36b95b20c4d40f91392c315e5fcf26150, + 0x40a730f39a665fd9cb0c93989b291d281958057e9b898d0b50c752f9371a96c, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x30478f2543e91a3b1c9b3fac23fc86c06032ca0fca4bee9387722862c449cfc, + 0x41b7accd8054a88f4ed64394473fba2b13d9b9ea06fccd0f75439c8a09f968f, + 0x11bcaaccaa00dc4c80c43172a833a6fa50fa47827b3d4df0c221eedcb7e935ba, + 0x1276b1ec4d51cf23c53b104a7d1e127058b91f5a4cd2bfea420c15355b43553, + 0x144dc8dfbc21918abb47ec061c7e6a2f7fa9b32babf270047a2f465b7f8f6de5, + 0x1dd046beaf1e8476308af0089af19da322852346b18ffa584af9d98619dc8f53, + 0xfa7e283d56ded23e03a16d79c94298143d259d8c53c8e0de261d197a4a1c071, + 0x2e1a819abacfadb55e98efdbc5bcb57e216fa7ed9d60a4ed920b2a1de8fd1316, + 0x256938ee3b182642f778f742bc3bc00a60aaa25bb3ce9f7fc96559cf21b28570, + 0xe6a334e357792b5182d8b44d893ce322996913cab640a006c1a8b73c023284f, + 0x24073e4154b684459e0cbea690ef583feef556f092b2b17c82c31776725da906, + 0x2dfbe4b1760808ac37902dfb1e18691901b413b87c6d8c8ae54d79894ded6c80, + 0x20f447f6a67d3b8929e1efdde6688fa53d47964873d86ea01126f1e0d447d951, + 0x2c502b5ab202577f015431cc2b64b61f85f486161ac4ecd64c9603fe6d353d01, + 0x5caa2b6ed2b850a5ebcc686b7198604941d48d30932a09e2de9006ffa61afb7, + 0xa3d02ec260b02ef2a4d51c2979cc1b22cda27b543a1bad75d9e547b3a5c751d, + 0x724bf5486c9bd20c2427fbc1d6936ea65d052f442a417215cd089b9e4537843, + 0x1ea84269caab7c273d92e86ca287a8850995c9adf2624daa858932665fed66ea, + 0x1d7e6d3695ae5003b9dc6950af38af6b5319cf529a7a1d5076512dfd92b099ef, + 0x99642d891092eaa8df1bfbc45d79b13934c42f37f8e1dc969fd51caea4fc246, + 0xb94bf0fd8f907040c14c1fc8aa290aea61fc881aa82da20ae568c34990fc705, + 0x28fb0d75533a8263ef2ec6b85c97b5af21e526471056355253fc5f6fd3361375, + 0x10480841e4451bf366c111c8d3fdbf0a7ac9c04b9aa2d8d547285dd891e77eb1, + 0x112274c48dece347a089aec971f0cfb9d7bb1a15b32ad3678e77d15cf7107ff6, + 0x1a8c6d411ddc6e2dedd2fac64c324d88ab8a946fef1174c973dc0f658275f5e, + 0xd0a4a998536c490396be874d02c03de56bcafa3cf45590184f7b53ef5c3cd87, + 0x22016b957df82fa5c825f4fb8fcf8634e654988b63d9f9933bc7b7f256e7c67, + 0x26d2a9b0db83259f6c7d081a2d50317039076baf6151f1734883fa6c322b243, + 0x1593b4f33dd3053258dbea8117f435f21d6876e7fd2907e98bd81d13e1f8aefe, + 0x1ec80ad7ee2b685fd79b38b842b0d420b685e3c090acf3e7507a57739ff76185, + 0x10573113bb0d41c18513cef083fbba91266dfa7178674888ace5d566e1308eee, + 0x2c5bca238c2c3be6d5cf5971ee92ef3174d4a040ddd6b0431354ce434de989b4, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x2f77238c057e187797950c50dacd539a7b7a1be7baa3a3f3a617f88ec05513c1, + 0x1e4b327ddf07cc065b37a9af7f6d97b89c40479908be61b2e6312c351a4d5ef7, + 0x1fa0048409da60cdb12a2a3013fb60257940ee5f4f8c2b1bb56362e121b0c8a5, + 0x1c92ce2c35358268ac56a756f5ca943b43db8c7ec965770da62b649c45baf1b8, + 0x25a62912bc39aacc66055eb6cb404b6a4f09b703a344b752c526dcb93e768c73, + 0x2f3e3c91be6f5b034b00dafa6fdb33ed00735f48fb2300a783ab3307a6aac793, + 0x12618073f72606525b743e3ab8c2749bc83ebc31cd47ecff2f851adeb397b5f8, + 0x7e1a14a5fe9a127930b1ee9a4bbbaf3b33ecc0c23d7b3b906f59925c0670f85, + 0x185866c20721e1018a4eaf241031b69ed1f2aa25e05310a44a015aed45003576, + 0x1845f9656990a68b36e47e83b67e6d53f42df6a83cba95b016c349ff191ddbc1, + 0x285db5bd04516aa0416c2c52cc651c2690bc846621ddec2ff3037165c30444b1, + 0x230697cd1a79c303489232f2d060182c4101e0fb4b6d3ac38b82a370d59ca295, + 0x2d5d42436b19bd4916f035f323d6acddae9a252ebc7445adb1d7bf560b464bff, + 0x1ef94358c904246669907524ba5bffbdbd7c9a5afcf160e44d00f19cd804fd87, + 0xdc902c1c2f63aaebc2a69edb37331ca6c053513f29991bfcaf6dbf9cda9f8af, + 0x38cfec7101b2ee954fa5bd1156da5c5662bc77e2b4e16d39139bbf165f5e331, + 0x23940e1b0657dba41ee3c7edbe86d7ef9f3a45016a61c2dcdc39f0321af50fa2, + 0x300efb612aa09a721c8feb5775c639204c092bf5adbf9d4268dd3f24a406e969, + 0x1cdaab41d8141524f40389418576088f7c8aba62feb69e895d39843068dd5679, + 0x1f035b6f957e84c1eaeec71e31b19518f3dec9964753a2caa1a33ba14879d0e4, + 0x9ff1b666e47a433088329f94545bc44a179ff61e7988ec8c86715cdd25237fb, + 0x97ad004ad339a6ab46f92a80e303e5d431fcd77b46a5b4435f383af68f7d08, + 0x2189b934e1602af6e30d786a0e283f0877720cb8fe77369c37f7ac895886dc1e, + 0x1903bcde38ddde14e22209d72837f9b813e437099f71263f84e18bc6414ee74, + 0x81887e6be9c14e1b9ded51e9cdbfeba2001c9e6098d6ece905a0fcea98f6452, + 0x26c7af1f1cee86563e9292336fb6573a0970af2c6d49d469b682188ad55561ad, + 0x243e21405367c02b78c9da82c9102df9c32a26dea21da00beb62ca9e4e71fec5, + 0x16e3e6bb95f28d2f321e7b63f6acddf3dd6c2e9a05aef8ba4b9151b1de10a78a, + 0xb011142c18c2fd3740c07513612794c14506ad3094f440420d5265f225a84f4, + 0x836b51afd8ef110a57d3d82bcb1c294a3d0c942ac20f6f407cb20ae9f0addc3, + 0x1ef12a547707d7dd27529e8675e5e58c3f35bd50de464d5e9b1735ab22d95565, + 0x12f1b456a3fcabb116586107e089ccb38b8ea0ac2fde6f6d464302c5f62c5776, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x16e23bc3ba612e8d4104a5a608cce0d28bf3a06c6f9024f8f829edd7c84ff5e1, + 0xd4acfcea237e44009b358d998961b4719fe512aa2cdd6438aa30dd5baa6dab0, + 0x93cad17aaed41e759cfeb15461f0222addf78c3a0aedea7186431c535ed46fc, + 0x25e68166acd241fc301db582f896b8e314e398dad56de9f2926f9f131a81d5c0, + 0x8d9b1a38c7c71b2fd5dac87ef974ddb4f7119523d81f88b0d7e16d577db060c, + 0x150c5bf06a071be6de288b6deb00b6ee51ee41f96f71cdcc980a366e4049580d, + 0x1820e0533ea75404ef263e570250e25f9c0bea1228df9fa90a5da8176154f089, + 0x229fc7b637cf8316edc29145ed5f060a9188f10f71e078dbcb887d195e8da899, + 0x1cc5470c6bd5d73eee63996481a28466499751a0a9c784abdb1c3fefe643dd81, + 0xc4da78b5310d04853242a11df821ba84860fac1a2fee9fc04e25c6039bee8f4, + 0x94cc155e114ff824b23e67ebb28b2bda53aa526fd3f11927db7060ededd2bc1, + 0xdd872678b808e11045a657250172181e1fc7d9e2eabf893f09fc3c6be3a93c8, + 0x2177c7830ac6b2cb6d01ead266a371320f7069a0de0454e5dd3a2566ff9eb716, + 0x232dd9ffd97dd5068b1041fe3ed6e08e162265e9e814b85116a6561430aaf72e, + 0x87726ff3cabb6294d2106931b3160809d4d1e669ed7de25374390af8ca39b4f, + 0x364f607b21cfb12929ecdd65f7618ef65c8e9caacc4f42c440994d8b5dcd35b, + 0x304b195fa0bffadcbb23ae2267693c7da7607eaaf40c880843ba71521edeeb40, + 0x196610368a8764fcf4f0278601232bc0a5aa7ba6d20e2c5420a7862272b06749, + 0x218f52826b8e2b82e86d87d7bc87fe5cc69171430488282062d7008069c89dde, + 0x2a70f39b2d8cf212fe706545d1cc154d07405c1417712b388c919b35263c1343, + 0x65be4ea4d6caa4125badaf16b830538527414ecd718a923c3417c474fcf5032, + 0x527abf8fa6b64559c86b69eebb3f0acd94c9f23a01438ff78f034c80291d964, + 0x263078abe4570cb96d27cea17fe9b493fadb3a020605cc474be08ad173dd424e, + 0x2616b2e0a8970da8019208335d4cccaa489c6cb8da6a862f1867e246e1f36736, + 0x255f2df1f986f154768f0fc8a5a2ced1f18d395ff01165e77d6cbda3e8b7bbd9, + 0x1806ff1795d9d6c9292f980c957038acfa02ac32556c9ab826bc14a968dacc80, + 0x871baf013f2fb16c067858844cd395a520d8a8bb17abe207d3138bd591dcfbe, + 0x28f0493d5c747880a71a82644c20dc23cd3bdf84e05cbe0c0a1a48fa27312484, + 0x2a45ef02fe1dd41641c787b8611113bec4881a56784fcfa21bd896a8205798fb, + 0x7ed262400e2c66934b968e3f8713d66e85fae72ab73c6cd33eaf5b2b480f6ce, + 0x17984162d397a2b3b3bf3bb04af70532c4beae81a076d0b8e1b4c54e5feb2f7c, + 0x296ee291fc63605db9594241dfeb6576603a30c42d6d631d4123982adbf54cea, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x19933fc7d1aea36ed4516ea4768628c08d206e8cae12e53a61147f2301df7c31, + 0x2efd792c56ad19032f4e2307f7ee338895556de653bcf50239f56a6f595a59e3, + 0xd6c9475058e6029ca3162b0db37e71ca570a626e7812f8938db5bb9f54f352c, + 0x2d6e38ed12eda3856592e0348ccb4fad2477619bc8a37237d4e48a8b12d0d7e5, + 0x1b22798bb6b6e5711236933e2596905ec1a4eaf3c224cb8e18385857df475aea, + 0xee2bfadc6c771b8279d82f54770acab798e5d7e6b6c93123cd6d871ac0f9cb2, + 0x21dc8e7e1951b62eaca40550618cef0d32ff82f425264dff2743e287594d7d54, + 0x1e75bf782b602b28cb11f489a17ab323dfe881a7654af175cfabadf765d2b48e, + 0x2c49b7045f45347ea8498df2f5d5eb560154f3579016772dc017f6d43cfa563e, + 0x1a0ac37735eabe257b9c0c25c0e8ced477833e2368678c6449c1aa4baf0f2312, + 0x1f35e213914c01a5ebeb34838610578a4fba2c4a06d248e0d6b76212ef339560, + 0x236ab082f2cbd2668f53ed5a9ac5f29822440e4b06543b6ff3944739edb00a52, + 0x12261534f09c4b4f143717ec4e8b0afe58fc399671ff29f5fc8c3dd302eb70ee, + 0x1421d8d32235caeb8e90379b3abacea1d7ce42bb1ae928840a8739d85acb3127, + 0xd330afe8be63d8ace3a3a83b7da18804912e3b3c1a8ab3e556b3256f0c551c9, + 0x1563b55edf443890c4729a6c84d523e1133d54bec37000b9afda8ec393c0d2fd, + 0x2f6aaca00913c8a056867f42f64016d72982e3eddd62f7508c4b86651d2fc253, + 0x2f31927a218ce8d5931907542909a9a8a424857218573585e1a11aac34a4ac59, + 0x2245d56c69c9bcbe47ee570fa2cae8008a8bc3042410d29f84cf65adfb1d65f6, + 0xa6d1a50326bf87096bcfb5acfc3a84bdf112eff86b9fd10e935b3ea5cfe52f2, + 0xdca2fcb2fca35419f3ad6737417350e4fe4b3428e65d4f418143b97204355bb, + 0xeff0d35806c692f93f365c7ce6d5489b513aca79eca0a6663e9bbd8820f568c, + 0x761a1a536cf23aa1f57a5a10140d4b1cb968e9e3054833cd33b769db1cdd0ab, + 0x4fe0a5f272499e111984cb95f691ad3533008ae70634baef9e60bb0808feec3, + 0xe5e1a69a0f2521a67cbaa96783214399818adcf5104c8da98d45f3951df3d79, + 0x3042f99a1751ea962828ad563e8a6d6dc438459f9b912b3b5f2567ae31b74cf5, + 0x2191f2dd5699e7f46dfc7a0fb01c5abb9a34740c534690ed789a3bedbe15fa65, + 0x17886ed47f13d1d49c9c24836655683cf481f3e89d2b65b9de78b591a97b87e6, + 0x1913d17541b234d83fd9f7851782516da4bf4ffe9355c19400adbc995c417fc3, + 0x271e99ead6dfaff8400e390541cecf5146ae0f3b86d0d94898a77b67d0f59b89, + 0xb57c116f3a607094ae8b3e7a2b7ef123635bf131089ca8fc8d0264715bb72e1, + 0x1e097d47d4a82b797a5ab64eecfbc5026ad25c9aab94cbcfbeed04e47aec7e78, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0xeff65c0120d6929212be55e8e6ec2e468d7fddeb7951b01ad014948c174b971, + 0x2a5c1de1bf17f1fbb34987d445e22e3bda9510062ee81821d20944df27d1d6f1, + 0x106178470931e69d02288fd73abee97994704d2cf4c2142498fdb2487afffc91, + 0x1f2d17deb1a25ec04570838e8f5caa47250c1bc16c0406017f5b2afb2b2c8b4f, + 0x1ded3f9efde2ddbca11e2280038ded37eaf9a4542c959d9ea7edb29557118c00, + 0x132611d30c21b4909aa39e4331d2fe2a1f532198f34588e67dc92a375b1d95bd, + 0x2f5741043ed87b7272c7a0db20ad4626af621071cd0aa6759fab3518f420e751, + 0x20749c10519279b7ccb82ddcf1cab67a14b26b3080022997c05ceb47da0211e0, + 0x2f4b12cbeffe89cc8e0eb8fcce01ad903d14750534b107d1a5095b53f2eb994c, + 0x19f437a4cf9d69d918e2bd2c1ace4309e128fb911926c4396039790db1677211, + 0x2189142b8e8e62d3eabad7d3a9c92a2ffc07677dbb3927a55035436a4fe99084, + 0x26deb902804c50f44397613473add31799f85b20d1232ccdc220357e87e0444b, + 0x60feb6d13dc7538cdea6274969507ba784301ea76cef8af0eb914ab2339be82, + 0x76ef42dd0bb069840f761558e2005af793ea5beac349c3dfb9e610933b1728d, + 0x21718df0edbd2d21670fa990fc293f89f53cb169739bf7cd2b732967fd4e936b, + 0x21e9e1015d05a67cb7a314fdecdd1dac563dbee2b9edab3388ec4ef9e58eeb22, + 0x5fc174109c8e7779d39321d9b843cdfc1e0d89d8806e199e15edf3cbd724f8e, + 0x96aa7b7315c181d4bb6527c1abe5d758908a11d1443ee30c0706b31bb43da3f, + 0x100171ff805f808f17a40a9e80b4f6516ba5d39cae9cf62919e085edcb46e0d2, + 0x28a6f6698a4d25726a7e7bcb50264b66a9f377f6dd42e9affc077b5bee5680ac, + 0x2be4c72e7f354219484f1f1873eb38a8aca5924509c892c1fd072241d02cc624, + 0x120e09a9b5ba1d13db63a4d011a2ff38845564e057c641657ec24bf5ce8e532f, + 0x26c044b1e72e2ed87e620c3010acf302d6f19cb8d4d5c8554931d2e29a923da9, + 0x1621a950244b5d32dae27f189970ae10d14f0803d92f67d8912eb7588469471e, + 0x5065df755c536ba54bcc816f308c2e341f05d16254116d0e29bac9cd827250c, + 0x18165ae1001648c8d9987e38bff84bafed3414ba2dc09eb937b73a1e636f43c7, + 0x2e84dd68cccd069cad6fee65deb27c501b2a0a8c75fa6b012b6451977a1cfd14, + 0x29868ed0bed932d2ae0f4ef731251a4ae59470cce43250be9f7fd55c543ce635, + 0x296b41ce4bc8cdd06eef0021c564646332bbed4a8cd4216effa4a09a015b1e22, + 0x2c1558f35552fb1f9fd96fbfa1cf187ab296c941f0dcf1af18063db872028d57, + 0x8b1bc5debafe2cc01e92b310a9bd1b62278d9aefaf78a42ce169dbd7ccbc769, + 0x2c64eb96b29fa0e07efbd86bcdaa1fcfd342ff26fcc11adb163a3e778092fb44, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x1942e0e4dc6666d050565e3041b09d79fc20e99b393b2a3c53f67467c3dc9cd1, + 0x2a61fdc217a0fd51b44cda5669eb8c81b4e4cda33c07d96a3b3abf75bbb593a1, + 0x27676c9245df29af49d1614b032c86d99dbdfe04e1ae951e91ca88267de9fe59, + 0x796165a50209865f0c12eb768681ed7107f6e7976c76a36fe196ac36fdbc5b7, + 0xc3ee0c7cbf8623447c90b90e13d290d313b6d0c466e0c4e1629e54eea175092, + 0xca789430e09c72971ba49ab8cfbe88c7ee91571c1bdcebdb512adb061597f20, + 0x55c78ff2ca4e60c8d1fbe3c55b15ecc28f86f30e893fbc001836cc0632c955d, + 0x1b1ed198ea5aff5e8750e4fdd1b51c9e4db45a651b2d9e1b211acc3b124e31e, + 0x680a0131921ff15b6f737ed1ef99bbf554e5c41ef4fd6e200bf771134512a94, + 0x1c04574d4f435df24a38a6afd056c49edd61ce1dcbb160c69c6ab490716f4bd5, + 0x1f79fb349db705a247e689a2db091244c30680dcbda765fbacf3f36fb7feba36, + 0x1b6f45bdf0ed13a82c330a5d26eb992dbc9802f11bfc2669e3feef1c310baead, + 0x1ce38cb2bbdd94c03869f6bd81e5b7a0c359a932b676c0ba6369fc4ee9271584, + 0x2d918f60f8c7be29a0b6eb2d6c44c56f0cdd865fd8a19ed747f4c83a41a2d29f, + 0x2b1e6bef26c3c2a5f7ec39c3be4de1c0a5bb8c1dc434570d1cf9811c71c1e2dc, + 0x18231a4625a11e057412d2789b10144985ad15966fdb26809ab8091b06e3ce3c, + 0x2ba1777ec04222a9f98dcaba3a5c2023e77a8071a279c726b35482d6347fece1, + 0x183e2d6301b1e472e01e2360e02bc855b6f1a262a4d03517beca13ac2539fa50, + 0x4e6c329b88633c6a45be6f77f5a9d0d54eda85a4e015ef7c368bb145c6978eb, + 0x1f7d2b53a2456c0d398417386d87f4f760fb541cc225d0d84d9d000828b94fee, + 0x1e7e8f07fc7bd7b462f36924ade2a783ed2ad47f6a7d4a5051b9774d61dc480b, + 0x8ee6dc4b9baa362c6da82f6c3787aec48eee1f6ed33157d1a9bdff0cab20781, + 0x1fedf46ce5f0967f0d259a7ae19e5b781a801467ab97ec9b8d50265832471e92, + 0x610a62079b0c8c00ad3401ad0473fed44dcad28affdde92c74ca927a018403e, + 0x2f8dcdd501988f6da1f3d80308531ea26ad2eb7017eae7d97e867ccf9e5010d7, + 0x2bca9ade6aa068f60c0fd6a44e549bfd37df8499a589dbffb64b00d3c48fb730, + 0x1a145fd2fdce8ce3fd02830d4c4c8a68e315fe92a38fdd0f5ff7a38d698c1c1d, + 0x3874b554c5bc6c3988b1601616c70756a3f5f9de40edfbfbe0120631da540f0, + 0x2eb0cb6d015c48ad9d3065a505fd42ad811fb70d9fdb5c2d537843f63b378e8e, + 0x11454221dfba7bd389e8f03187a0723828428a6bb434c6d7bf20bfe5fd114b83, + 0x2a10c14110838c69329a80b0b2613bd9943a3ffd25f6a1e951d0a90fed4ea8ff, + 0x1e52a42d152b85d8a7807288f6f70e69634da7844d995b254f518724e4c3609c, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x2d54de07d84381601063b6e9bc507c93cded3cdab6cac3878cdc3c29720278b0, + 0x2d8d4a2f762f3df73356ba6bede1b007449304d062b2267b388e058c30d321f, + 0x109f39baaf3fc94e73d04fcc393a6b60af6c6e20d5953ee4a1b572857b4c0e76, + 0x12d501a7112aeffcc039e330790ffb66ba390d1dde79ab5ffc723f9fbae2875a, + 0x104a8ca53760ad5d9a630d85bf1d2880fc8e22a97c26864f6597b78ccda8e39a, + 0x156bf185e618c82fd5622d81779e5538941258d1ea3d26923f59b002ae7f48c5, + 0x177774923ca426cbb54827e2b0eea99d32c576101bac07394a15d89354e6eddf, + 0x113a5bceb59274549fc1801d16c19742fc8fc2139fe584c52a7bbba2a329924e, + 0xc6505ca747cb38e435eed24786617d5bf69034132a74f6464c6e802fa1fabd6, + 0x118069d4c4bb4779a3c231b4f9bb10c9e51bd7bc57cfcd602ee7a6fc0e1abf95, + 0x385980d35d14e90d64e9768701ebccc125891654fbb8d6b79a4ea17842a4975, + 0x1916313365e0bfe0bb7bed5b5f7bd03db314de71ce80422065c503181bb61c2b, + 0xbf8748279723ba405fc30c18b22b4d1c8bd2ee8a133b73c3e36170fbe2a04ba, + 0x18e633e3f93f527805cc7bdfa61eab0efc189b556f7c549f1596eab99d2e0e6b, + 0x152bc76d070352b5e3b4f350f4b07c8cefd23e9fa5c425a8b974d68aa3c07730, + 0xd27de87e407d89aed983b9db0f81620c9dfe423d47d3de44cfe3b273bc2bf85, + 0x2b50440572a0892b1c83bdb6fd2037c9ad720f13141798f8857283e01b1290e0, + 0xb5b0d8f6278e41ff57cbe18be038e3467f1bcc255156a660cfd16aa2ea9ac6a, + 0x1c4bbc69ba7ce83c1b223dddb0304428eb67dff461b719504d2a55c7bf380a4e, + 0x224b7d772c7a5d6fde26f2ba95e000eaf6fbcfa50398579c0833093d6ab8d7e6, + 0x130d060491a6bd90c3e5ee6bcff4181d9126f520c56d7d8233120e8449f0370f, + 0x26e1f7aaa668655ac3e092b9c8899994ca9e596ba992fa8863b52b3137cda92a, + 0xd910dfcde2f0b93948f265e861563afd9dd6326cde2a9c9489d22d62dbd3071, + 0x1a92a6fba93268b439845332988535624c93b616d2e972656ffb15175455e542, + 0xdb35e6ee7b9752c564e9132696f3052e39a46df1c4823fd05e246e928963d64, + 0x190484fb8797efff338127ac69877789cb80eaa47f674cae2035e2d903b6dd4b, + 0x281b15d146c4d56debf9f66bc0c8138b7c5be54cb206a9180987f1104347646c, + 0x2fa46d89ce68066bf1ab4d304d8d9163c8203f14758eeecbaeec0725cd663813, + 0x2f2ced28553cd93fd972e231deda1c8b53ec3300e9617dcaad0d2d25f2d61fa, + 0x2aee5484616632c7511346d4ac900eb5de7a04994eb95b4343d3af1e388fa74b, + 0x2bc085981337c2500fb80f2259d55e956963ef377ec1e2071c84639a19a581fb, + 0x232d9177d238a7e2d92ff1260e60e1d1199365f4cd6f911dd08315297bb6c648, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x152e232aa2f0b5ce86a9bb8ec7c916a66ea7d3eced20c3119fa4b32227a44224, + 0x2d541381556b2db0e934c244bd4f8ebbe198d35bcdfa56c77ad702ce2b4c0c5c, + 0x2e3dc0bef8262414d80245ceb411511467439879f538701e9ee094f7c14e408, + 0x16a011d07f05d6aa059d5c39ec295e27d697b94e0eb8ee80d090253627d54ce1, + 0xf2e71fb8b1efa67f9de9fa1f2a089cf8f1a995bf2efa733b40cc406b6e25cce, + 0x1231d7777e2dc2538a6a0c854cda59d734f0ce0a877b5271a1d38c67e682068e, + 0x24d78b8526e7b1c0637f2797968911f101462535e1df4d7a4c151bc6ff2ce040, + 0x22a988364a2deabc2ce747418dc02fef38ce6c811ee6074febd426aa59e135a4, + 0x15de00a932e2679f01402db621f4226348b05436f9cf4b4d6d6419e7770d1565, + 0x299e0373cd69ca5bad2e2ca004ff6dca193a9aa2e0e51de1c89770d2c260e229, + 0x1f48db87438ef28954de5702992fc180e1204b139cd825af6631d8eb0a4c9bfe, + 0x1bdff4383ad65036a6193cfd9f77601f48095adb5ffa44bb31a4acb8bf68b74c, + 0x17644aa682a852335aa5b1532c6fda9a980fff5e94c2b6358ca83ab58a9a77ed, + 0x1bfdd4600de694368af6447e16dc544f8565534d30f9581b5d81cc24a6503e26, + 0x18c8230d4cad7c815b3b71d905826a94022a81cd18a26427fdba3236667b24ff, + 0xe19493f16f0b05a6cbc8c6ee13f334f045868cb36c7e6013b5600e2eae2aefa, + 0xd2f393e71214f36cfd6a8f7f4f02b164c0bf4116e97f7198440fb9122583e4f, + 0xfee312ee60e18d3e7a6ba6bfa95e826f27a8ea0a865e3c7a7fb4e130d1c4c09, + 0x22a056cd7db5815347a2d035ecefda073dcf753bffe9415afd254621fc370eab, + 0xf5eabc9bc5fbb19864ef2113fc4c756e6b5f3d1dafb8abdedd3b04d0b80ae66, + 0x7c235ac19bd9379c4cc01b454b43218af5b573522aed311148404f3a5c743d, + 0x2d942aafd44c4635f7cc2f58e4b9314baa46e187ae91b69a70ce5ad08aae42b1, + 0x18b7536ddf2baf318f7d95ceae7c059898a997099b0e006b14a9619734d101ad, + 0x783549372d830804cccf9bfcadf1bb805df0cd74fdfd8a58ed78b2cd5493037, + 0xd0ff56581899da5c5e06929f9211224abc1701cc590571e4243ac5380251d75, + 0x10eb2ca01dbc69cf143a07d1ae33d465c21b004d93fd8ab3eccc330e8897a06d, + 0x1caff794c32f783cee39dee2bf130ea89316a74d9bf6568e1d0be5a2362f4273, + 0x26e43873787a976ee680508db2668f4e6c8ede06795ce54762ea9b7ca7654dba, + 0x8d378aa3982d2aee08f51d4ccf75af2b06f52ab03864d95d56aba9bbfcce7e8, + 0x2ff5d0d03b4b4f9d0b01d3e0db319dc28906e4dca3dfbbb4b37f99a85d1b38e2, + 0x18520d1a0bea45e0d3d8bf43f25ba325c6f2fc2a854477dd7bebdd9ac94038c5, + 0x48981c51b77cae321a249b580cb97b327075fbcc0e789b617e8d3694477e52, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x1487015218138ffaa0a59fa85396ac51e075d8925a724fd325424d928c654ac4, + 0x158e7709256be5b46df08d1e1b0be1938aa6f4e5c70197431f5f2801cb81ce9a, + 0x23ead31e3adb55af0de40f8ec4e5e40494192a137f36d6468cac8b9f8eba7888, + 0xda52b842c39529943fbff3afa9c3a75d580025df3c708ca7e312396e7c7ba62, + 0x20641a12ce32094370652c635921aee03831de2dbbe854b52d983dc669a0cfa4, + 0xe854c479dbc2e4674a8fb297f33513eaca7d1705e71cd403b3bfda7d594d063, + 0x22e3bb4d657720df9174b5bc721ec49ea213157e0a59d0fa2f2eefe9a8bd2376, + 0x3f35d5ab9a8715db37918b791480b3190493266747e93b2b922f17c4a8d303b, + 0x71d91869ac439a23c518effe61ce68bdd578204dc70878ea949b980e8ca5765, + 0xa5afe6671b39a880f2953d521327679dfc02d2cfa739e10ec0ce898a7e606fc, + 0x1a13161ee9c83cc5dad2019e320b65c9c0fb13afe6a473b03242fdf77e80607a, + 0x3026cf4032ab73cad3fb5363647b3617179ff403dcb0738688848252d5b6f2e, + 0x243e0c7d13dedc00a5a66e8ac3041de9cc0f107c69e38e0a5ac807fc57523424, + 0x2a9fcc31d5ba75ce13add9a2fbdd4bf8478f3d286638267e8d9889236ab48999, + 0x12355d3aaa77205407a218c67bf292f7389e48078ead3ad8b44a7f26b193a571, + 0x2fa06fd721aac5819fb8d72118cfc36835a96a57466c5d9c7ded627ff5f0925c, + 0x2009a1047f9adcaf5d077ebaa1d827ba73fff81d486a9bde79f66ddcf7b95670, + 0x23afd3d3c0e2e875b2a847cd2a686c1fc3c5837f41935caffa4bc413af451491, + 0x2726dd1f3fdfd05c33efe547ed972ad36a60674889b98d1786a505f73bcfe296, + 0xa1f79f8deb6a176a4a20a89c2f3134f7f2288e5e698d8daf9662f79a7df7253, + 0x233dbacfc9ba8c6e47588085cefa90f7ccf223ab050c4900ab2b262de8235c13, + 0x24e7c1d18385735c7be8ed97b21065ad3446b3a44540e129605efcac8b1d27ed, + 0x2218b114e6a493d7b5b767736aadd097ecad86b0f58972ac0efa546a5f1a4726, + 0xfe60e24f84080950e79f2dd5dc8ef6dcc5eca3bc6cd608f91b9e05a4575db3b, + 0x1d3ebedf3c91e56b3331c235edfab0c1de1b37c4fcc7506755a7e90b86a988ef, + 0x5b18530d7ead1dfd0d305e24244c90f8e66be3ff5195efa2c7f9317db72f17e, + 0xddd0529998868e7616a880793d4bfb9d9a25f7cbcf4f894d7c91443dd3a3e0f, + 0x58611fb32de45f6b800200ab76e38d4d88152beb86ece1462c2129509732672, + 0x2f4954ce179d833366a6cace0bb216235b5fc8331a0ef36ab40cf00881a1592f, + 0x10dae4642d4de29143dd5ae8b72f56fb7800d664ee0c121c9990e88976ceb878, + 0x9d1b3f83888c3b9a018f779ca69c7480aa60868a1dd1ae22d328df4667ac672, + 0x1f8cb04b5c6155dd321920c129465f8033161f66a6629acbf67d0ce8609cf2f, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x697468fa48ffbef2def6f8859c1276f40ed8603b54f336a9f5bf6c986dc4472, + 0x14845ae5256ccf9f52ef754d6e9f93df1320a86b1d085b642e9ac35fc8c659d4, + 0x20a0e20ca969d47c57a6fbf1d7c7be6fa22100b7c59f0701d589dc3a150ee595, + 0x1a54b1065df96a7fe52babdd1c8fc70975c19190d7e3f0cb6ff113eed0ac9601, + 0x60a95bf72d45427efcf1df7d0374ce564d824bd9371afbf03b58a7c2b8257bd, + 0xc6bae2f35f833cd1099626a254a8dfda1efb2aa199b74f9fa99777314688d8c, + 0x2e075d54e2f7837c58a23049c4c5bc210731775ef5ca93689d8e411d3e25c05b, + 0x7315b60ae704cd80a3649afc32608e8475c1b87ff88966d8e4bddd6bd5ca97, + 0x1c5f8d20fda642dcd8db43e9361d4188a8f48dae9021b84073ca261ae50f32df, + 0x13671823102cac626ae6c133fae6cc40e2a2e2d7f8a1191889988154b605a740, + 0x10f3889ecee1bec4a5e6c7f0336f7d193acb1cd6cc1b5de815daea4b3b760f8d, + 0x6290c4b1f8ce6ddc74050ca5d58142389edfcaaca0b3b23514e864e8aeade79, + 0xc359d3a8e6913715c369908a57f93775b7efcc28d300317a9c80812d9915a1f, + 0x1b7906c8c29ea1eaa52ea3073c80c666a686912cd52e0f8804d61087d3968f86, + 0x140e7636bb9af6ca0bc1a25757a7ddf14325f99ac07e34c22fac95cc25b47d2a, + 0x1a2ffb754f4df24371e274a2080def1f1eae921b272813446142b708219a4277, + 0x8925574c3dd6d39347dcf0d188e603ba86c85d8ad8c7bb96b503be1a4b01fc0, + 0xc4d557652fd1a40449b5245494f461ae0688771c6f4c6e287632ef3d9e19d86, + 0x2e9c11f9d848f461f467311174d68af36dd75eaee8fdeb0938fef3412cd09e48, + 0x198350eea49489bab667bac0f4c78b18f31c0d2fb615f3475ad0050bc0e99525, + 0x1feaa21fb6aa40e6d3b99d464f0c9f21c0e6d29fc4733bbf6513a40ff15e4db, + 0xbfe6c87d65833b8b7963d8c909b789d379c0a822c03e33591a77bde69936561, + 0x9d31ad63366f19f5de31ca26fddf1223533cb9809ac773c664e86ef943a5c97, + 0x2092b2bc145c4332074825b2deed1cf735a606687b4bd62d6b70147734da47f2, + 0x2c650be19dcb6005092570c6981b6c6701c999aef85850dd7524c99b0eb50772, + 0x1987da1e063088e505fe1c22279a2eee2ba492e2daedbf9bb7ff7fa0ea0c2244, + 0x2d964e6c97f1ce9fe98ec13e03e39a1418f7b586ef6b624c9b14fa7a56d43e57, + 0xe44e2dd16cd81347aa62325235cdbeac7496fb36bc98a405fb658891be8335d, + 0x2b3f3be77f4eaf5ee65b1dc9420fb479926f707b6494e45c0c3456c9b1149ac1, + 0x4510148cecaaa311e8815f62e0c11155a204b9e8419430708f270cc90369541, + 0x121f5e52b5ed6d974d5d8b5e9d535eb69c207cdfa494e75a99a26aff13c9c3ae, + 0x250897c08d5b8b109dfb0a60a31e2509ebfb5a453a57044cb4d1cee1cb36254a, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x170ded62e47a24d031e0d09a9739c181a05ffa6c072a0ae4476c8459026ac92f, + 0x7a7d93f07720b729d0fc11ea7c60a819a915cf083fc5590c8034b3e299ba0c7, + 0x2b38674819134ea743614550a13ff1e8c4ae2dca4c098dbae7179c8eca382411, + 0x271289dc176782bc802a40e2b98935e1f0cd9cce1cf75187e8bdbfc5fdaddfa5, + 0x50e0d49763f9965169c815ad6d976f2c1502d504427294ec650162b32d16249, + 0x1e16a7619369f7223562609f8571294ff3134b6d2900818958abb801ed25a2a4, + 0x55be327e8e9177db48e781385c7cb9fa1eaf7f944ad5806b8040d021328ff4c, + 0x1e218f8a23818b358a930aaac6880250eaa814f4e5f4ab3720bcb53cdb1f06d7, + 0x344ffbdf73e00c5ac9603bb8205edd7a75d44a8663da028fd643d4d6f4c2ba1, + 0x127fe6bca0178af93f621d5cb8c0f000c81096f0b6d97dbdf51785ae1d35581a, + 0x286df223607d95bb861a49f083b6dd9eac58b63dee9aea94b87f4a70e6e06e52, + 0x8e3e56ff4056ea0cce72cac7f1ab3a3f039d5948bfe24c59667056ede70e1ff, + 0x5530286c0e7eae0c6b693a0503fd0271785b1a9a8d159ead68b2777b07fb552, + 0xe5a8dc54f4762a808e384f96b9af4ac56fe9a046a3ce354ce3f7b02fe5f8840, + 0x12ae091a2d3ceb050262f732366d0461725681ef6a2c98e6cb2246e0821462f3, + 0x1bb12b01d476fb2d879e3d80e38294091670654bba4f2cc2556bf47a7fa3e533, + 0x183408f575aeeac085a605ea9934dd45294c7665bf3417c2ee55fed79fa3ff4e, + 0x13ed068f2325d6098bf97f4201013c9cc366c2212817303a540fa21a530b2186, + 0x86a1854cc12612ddc29d8130a224448fbb3f07faceef1c457b212865cbaf7f3, + 0x28e0905fb2b0cda24805076055e7a974487c163f6e275de6f0a79c2953f42686, + 0x13482a7e8bf17cbf0d729a877b9374b9bdc382818d0829df7785161c845df5a4, + 0x411f1eba980a1c2246e9dbbfc95ed50786591e99706eea93b50fd4eb7732792, + 0x2e4d2ef29fa7855a8479c385ee585e191afe05e4948d3afb261713ae3846944a, + 0x14d0b018b332223d8d3a458536fd4bb2c8ab2765b35cfbd1b4f5af2bc7eebb85, + 0x7ada6b05a15e228c703ea1deed0d89a090c888e04aeab93b903260d31fb63ab, + 0x2bf8f1482d4178227da9ba8141f98d764d7d25723d12a474a0aaf2b6f500fdf, + 0x1771ec5e8d202af9fbb5a6ccd92808069ff98a103ca38e60216f4c29bd138027, + 0x1cc45818383e71faabb1f0947a7f2e2c6fdf84ce43bdaeb3108eb95c853b951c, + 0x21ca4fbb38c5efb489a858ed9b5550cbe80765807ddeb5403956a91d3bea3921, + 0xb264544c114744badd140a81312486c6ece15085107fe41743ffbc42457190b, + 0x63f973d8f7955b230c3f623e86769a8f1fff6a2f16f542aa5d25450d77dfa26, + 0xca567c8c6074baf8976cfb1c5d6f2d339dd69b91c3b86360bb72b6cddf2a05a, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0xe84546d43156eca6ea9945a1f0bfe0d070c7b5f596a165d6f5b2db25d70c898, + 0x255224468137fa5731f4a79531b0e41467fc167a73eff9a2f8606ea4b8854157, + 0x5e444e0bfb3002592edf3b1a17b61aca96cc4f55369ea0b858d00a2429413b, + 0x2c9547cc8c30279572f43f6c98e57d007a8d8e00afe3232f22c86d92cfb3302e, + 0x128d1e7dd33b8a7eff38771210c3e2e32542927ab8a5bf70b304eac65a5e89a5, + 0x117ea550387989a27267059d04eab27171d97ad177b4722b9076ac7850469259, + 0x9c2d962801e81427424c3b82a3c2590f3d3a015f5d05dfae03f1646e85b83a8, + 0x26d1151c34d444d61380f618137cd12d3856a5112c1a229087d5237fce352402, + 0x71de2aa9593a6be60d825df98f433ccaff569e8f454b57a1a92a3a179419b40, + 0x78af695ca1926d0211a0c74b15ca6a21b21530751b6c89f16a7653d7b749273, + 0x10fac024afa92974f4f4b43777c31f0eaec838068e24173416e3e55f18f74229, + 0x252a24164cb696970f2696824ed7ab40a422cd2f561c1add5a7b94d9c8788416, + 0x2dc1cca380599b8d9c74524f5f370ecc41d22c4c792717a7ff91893c9e878bd2, + 0xf1970c566c802ca51f328d7a61668732660b84701dbcdc7388dddb0d503d32b, + 0x14410ae146ba19441bdfc99f88fd2425a30458ef81a97cb0757278de7c71b6e3, + 0xea9dd39706c27da7b07438387714c8e986a37c6bcb9cfe0aa413edb1d426620, + 0x12a0ec57214d783396e73e66cd8d163ae207afdea093f62ca08c1d03849eb81e, + 0x15f6e3cd0868b4e3bdeed8670ccbd35b084b2ec7d9f70e1b0e1bf9179f4e7aa2, + 0x273ffa3f96b6f990e5bac3da9121fead4c55e9a53a4cccded8ef7768777e04b7, + 0x265c7d50300accd451f9d10a056a0a9c4b61960abc7ac07f405544d2be981cd3, + 0x25704ec82bcf245817c0b0c38428f80e097d181fe4be674c56a431704b81220b, + 0x2bc004a70f93825fc7dda4611642819d5667d0c84de02d108fa24e7553a8ed9e, + 0x2c67b0e93decf3dd43ecf2affb6c8ec2681b530e89f028592649fb853ab6913d, + 0x25d1957093005c4eddf0f50960ec66bb0a71e99dfe635f3882224ba50ea2a19c, + 0xc05aad7df610539bee690ff338426700ee57012dfe44b456047c168d9f230f2, + 0xa09feb45b441685f960784f20a9daa679ffed8343997e028fd527f1c9615f1c, + 0xc3317b6e0f17024f3e8d48d7be78de51e60037b098935f715c5f7afeeee5559, + 0x186002e006875015c7995b512ab297b9b6a2ace2f8b1f23384f545a47a09eb4d, + 0x607f219a0a42d65871803946f468fe1a990978f7a7dc0a6565282240befe85d, + 0x83054c73153f2594282f425afb21bc06076820a2a936ca2e88aa93d198ad89f, + 0x1d279f18a4b248bbc61bf2647394bdced0fb95c8acee6dd036c0ede0c250049e, + 0x2e9fde89ba2dcecf4a0d11815b6dd2a93ad007660b67c14e84e4845521b47755, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x66bfcf07a648bceaa19dec1031fabc57395c4dca3503000a98eba19c54fe970, + 0x276ac7d1569f671ee8f23ea68b34b200488ba7f18d905e67ab0148bca152d25a, + 0x2f20f2f426186af0ee321282b00a2a641ee2b251399734d15e19af27ecd42de3, + 0x1c96a460e778f4af5015f52cd38cf2c41a6a9e85f6a30bb5f3435dbccb7b9e4e, + 0x227da7c9930fdc00476ca6928729411b9e65bdcd361ad27b66ec4c4e5b529a57, + 0x27b1127b1ce6f0686e0722d5c5a0cf8847ac68dd8eb498a1a2f6124a4e7d3eca, + 0xa510ccb52f446c48a9d886d6b7a6705680356500e63b4adfc43608a30c0d5ad, + 0x187297811a78c845dcc821d8193d2ae2ccc8be6fc0552f3e810ed9a2d044d7fa, + 0x229793d98c198e355838ad9410d16930e88ff01e0a86b8074ff75336afff596f, + 0x1214cf6c699c46ef88ff3713be9f3beec4ea27cafeed293326c7db4166b31ce9, + 0x2099cfaccaaacb25e8c1730ff9d91c6f82fcf436589b18d1a092f61c766af9c2, + 0x2322866854d0c03dbd891bca034f176e411dda04203b47ca04ca2c2a82aa5f23, + 0xafe4184fb8af7ae9177ded93afb51dff550c90fd4ab624c95b9e0bdb275ffc5, + 0x18981ec4e7b2dd5b75057171332150d62e2ebed5bc63ee632a6ccb4146745f94, + 0x1fb6ac0886f9dafcda077d270effeb93aa074c26a62ea6cfd141b82324dff556, + 0x2aeadacfa8410a4c07abda74bf85806b7034785279a95b17c6ec7a0ecbc4f72d, + 0xe640d01e5ed243961bd4361e2d3b669bcc5bf35bbd30181e231503e0ea04329, + 0x2e878ba571f0ae43c5d79cc04becc7c8e65316c9b6b83c0cd56124dd51966ffc, + 0xe4671548304dc6301e30360016f37d8289e8570c4fdd1189cc7fadbc02f6719, + 0x49f32a110437e1552ae6163e0890d534b044bbe2ff3839eb980ac72b15ca83d, + 0x29be7fd214d5ac3a21e930773ea4404cad8e7b751b02e186711e07797362be6b, + 0x6d4247fe770b6bf51c7b739fbecc3aa418f5920eef7624676835ac1ae061d66, + 0x21c02a9eec894a1ac2eb56d27410ad620122e3a5adfb8a8f83ee617f9525cbd2, + 0x232b4705581121f62cff2b79d0c8ea43db47514fadc741b3306a6900a0bb9021, + 0x2a3137d0e0a9987d06f2fd2dc9f61c22e3df55d4929a2322242d6a6b36e6141, + 0x12814250a734500401e41c65da8949663d7afe8c6868643a1dfd086389c29d15, + 0x1d221587e6acdcd041bc0e164a9ca84970807de46a767383c44262cbfa1bf972, + 0x115ec085da8a3839212ae49e93243a25f3b2f34c53b5786d5576e8a5e626319e, + 0xcdd08d5c710e497a583166923360d16215ad9a3a1629daaab0587b45de950b9, + 0x921c454f7b3d19a8c766875963305f4b4d6f7f8be1a2c4119315dff25c111a8, + 0x1b87d132d08fe5a6478b2ce4f40d73b8d4522fe23a4b26e96b31c9bb6a3bed69, + 0x22ae2be55bb3c7640477286be689776e1514c8872e1e0361ee36b13138d0f6fc, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x237ac6aaad2e2ade78bbbe46b6d53646c7404a2fba31795c331db8da4145e5ac, + 0x2877189f4c0d9fe01baa33a2b820b84a4a3a8b92964ea9c7b2149e4a2547d527, + 0x136a6e0031d277288d586824994cdd3da32221fc94bd9c961cbb4a371c6d16e4, + 0x18a97e7a120e79f25dc87650a56a580604ad0fe99a7b5c93b295b7231fc13e35, + 0x298a890330408d2eb3e6aa31347e4d68c1bb979a23d9c7266e63b47580fac913, + 0x191d5d7b95a739bb75bf19d63f8e787dd14fe945408aa987c749ac01a4e5d476, + 0x2449e2d526e2920627d993eed7cf4de57155a00e5f071f059b94eaed73645b35, + 0x1a0364ee68cb9c8a7a0e801daae0ccc07d92b82686bf5bde72c074247f6767a, + 0x1e88daef2272c0f1f9792a6d85f29b403deeb1f4f234522d28112c466790ce71, + 0x2c4b0d1c66062af96f71c6b23ea770f5e53c39967f0d3b1a950df67c9766432e, + 0x7ad869f9d13d9b270b37cf255b577346ca286f8979e546182c4b9139368d186, + 0x2015d96937e823b49d8eb2f7bcf3be82a8b6ea9bf53b5fdb52a4bf72c4375a9e, + 0x1ae82e2228f0080b37ac0d77083c3613fad8242b420de1a24fd6376cdc8d79f6, + 0x27f0ebfa6e2ec9fed23a25c07cdf68a7dd8bec39ce045c15fa0e921b75df31dd, + 0x1b129211eadf48d228e7a13a9bada042edd5164ea595d523503727419a5b6a5c, + 0x1541b4e3bd42e9287b5e0bde5ad7c3ce76dd326a0e53418892067a6cfbbc1bf1, + 0x3cb9cff50f4d9d174ffe46e382184d9a99306f350971156b859d76d13a4200e, + 0x2191176d2fe6b3607227f17aecd711d31ace1a71987962dab59e2d4dbdfdca3f, + 0x333a98f84a220a59b23b41a6eec5f1293aae65a9c1412fdbd05b6c730e7fe86, + 0x1d3133dc479ed041791efd9f449ac6b7a2ab67089c2aeadc033b12389534c8ca, + 0x11a957c8acc043e1dd0228a3bc3e2ca5054dad13c1c685d3fd1c7015dc541b88, + 0x9ab1d5764d1ab372770e72a734f3234e944f231d55b4802feeea21ff00cffed, + 0x2ab07fca009ae3784d9172cd0de7a03ab1b413207754249d54e0115671c61648, + 0x2f26dcb5b014b72bf8a7df0100847754ec09bf69ab23050aa6ab45b8bd49a8b4, + 0x12831914375fab4bf02d5923d4fb07f59ea7ec76fc424eada862287fac0121aa, + 0xf01b766464df2a94717e0b5670db63546816d0ec951e74fabd2070364513e10, + 0x1eec1596e07215f120c71f3b7fe2c872c0d1f0ecc2447cd0382ffc1b3d74ccb9, + 0x13a9df3f6c9c0363c8e81bb2ec06ac0124cacc3aafbfcb99ce0d12b15c1d960f, + 0x9941a17ae1ed8d69ce140125c49306cae9ea0a037563cd93dadcc09c1b8994a, + 0x790fc3d447ed1058bd5eca57d37adba8d645d5c42e7441e5c508e6cb2a7d581, + 0xe11f8951edc551adc073326138ef3493ec812ed643400c53da02d49033963c0, + 0x1ef50d438e0fb3260e615f2044df40bcf70bfadc6b819481222ddc36e39cf1c2, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x19a6c9e51754a1ba0ac6f28381aa453e929951403794d3f57566adca54593cee, + 0x2fe2b32027a048ab3c9fe57e0e0e63168c1beabe9cc3f5328bfc6e2620d1c0a8, + 0x252a353865d1bf6df4e243baea612d8d67a58c9b91b68be6f6ab9fd6cfa6f052, + 0x2445b945a65afd2c8c6d1e12224f0e1b5a7a4ea158a67dd4617f8d408239bd68, + 0x2aedc3a83dc324a21fc06b06f1394d6a5636c2f191f252e9d927ccab3b8a47d2, + 0x11ef3c2372ad8e0fedad2ada9740cf104fddfe5f26a74759e174eefa6f5aae49, + 0x16540a4f6d867388866e79a4f327c50bc06c7abf88df4fab1af55b9693c0833d, + 0x226a8cf3b4fd93fb027602a84e5c84e19fabdb3c6b0641903107238e7473f4d0, + 0x15829949331aecf0006a9e8f46f028a13efb7754976721622d65b6f9cac5756f, + 0x219a0633cbffa129b8be664c32a15d8c6f307fb00fa27267628de8a7cbd4da12, + 0xdef3ce304e0b1f868a4036fb628bce381a92931de8dd658f9a4db69808c2c5c, + 0x2bccbcda22270d6c62effb8e392bb7fb97637993bc102538c5cd58e88a228a4e, + 0x188172fe781d7b1804c9875e732ae5ba92da30e3fe79193172a9b2ad266b912f, + 0x1f30e5d70cc514c78a878299f52f298eaefbc73811fd69a8af04d6e1b235f8fc, + 0x36dd7eb2d37c58f0064ef539c409ff1b2866f3e37995a0e6b63d2e12794a65d, + 0x2943d171cc678d4b3e7bde9fba8cc6bec123fd9e18001704074c6b53b2d7fa55, + 0x16d3bd98a136cc6ed17d71e7ed150e659bc21e304859d7e91db4a75311b12c17, + 0x2cc46361954b156f22dea4b4e5836d017ad5e866df6f9179696836eb0b9ecde5, + 0x2093732993458c1dc5075a90772eeb28239503ebd2aee0b0831f253b5795f431, + 0x26fb0a33d8ba99f9d666fe22149b4b9c288f7a356f7d4d62ca019c426eae56f6, + 0x2ca9e5344928b4c5f6f6d72ec4bbf9f331563b93f78c5b6c693f9ca05a03b9d7, + 0xf86ace9eeacefd133e6f9e5b27e768d4dc41fa8a4b6d0b643d59a99b972b97e, + 0x16aa6528c3e5ca07060d40caf2050fc7c1199f3ea08c4bd2841f8816f8ddbbb6, + 0x1aaf0a3512751441abaf663b51bccc82b4aa9e031f95fc5ad831b6f5104b32e8, + 0x1693d12dc33373065921094c6ffb59f1f0361b0c5ce1b20e8f3f4f1bae805df, + 0x1a5b1eec5d855cc716abacd6b5ef79ad4813bc74fa3265e0f4966768088e24a5, + 0x1a98219aa97845f039309ae314e1658caf33c72235d5a045a11231048dc85871, + 0x27d38feb2f3ca73be6e78b2f51db9e904bd78d3f7ed495634b22c29b28847943, + 0x27b21eb7516a84220bc79c6ba5a35fde0c5804d4dc2b469f034f93245cd58e64, + 0x10882cc54c76c057e84e296d8568fd68a41a86bb595cfe644def5dee16e2b60c, + 0x2a5a015eeff7cd48c5f9d66baee6647ebf41fe73f15999b85aa738249667f809, + 0xbb55ca8ec263593081a7f140c88ff0eca81548ce6c2fc66d3c9041e7e61a52d, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x11a95faf7782644e66dd690770be8d58aff9b21c252a17353159e8e6a9cd2d04, + 0x1809bc4f74f8da0e56320179b35cfccf08531a383f8f38f055567f54de408856, + 0x29576ebe8b472aab3c418866b657b4bead5aebeb46731ac1686234f997c8064d, + 0x15fdd752a74e076a3bacc425ac17ef974ab4ce00d98e3b766e4e9da506338bf, + 0xa39afeb11772f20bd44212cc5274dbaaeb912c073ab120a0e3a5cff2f95321b, + 0x1bd3c83976780db74f4bf261b609505ba17d4269a823fac360138142fb482bc2, + 0x2455035975952299afab678e90178017ae59c02e88b66acbfd33a9a97e4053ec, + 0xf54c6e582707940d37a81057e0331967328f0402b139f40a152a537050d4eea, + 0xf3edf4b1021df9ee75bf77288e35c135bef2e641317adbff2cacd1cd63dfa68, + 0x15a4b29ef2de3e66e4ecbd99b63fe784c3d163534087d6e752935e3a66a81061, + 0x22de01c525edac04ce6418e44df62cfce81abc3238c0832a5721e81410124db, + 0x2f75cfbb2d72a93661691b3c313d73cbf48e570aff4a8981565691dbe6e7244e, + 0x176215e6dde458ba94fe6cd32886ab490c44d3f35708fb83ac032957477470e5, + 0x125224651632beae2362689f3f298c3d1cdde20786b700cf154dadf04aea02b2, + 0x25adc0480ab90662ace18ed71d4ec243b5d118bedf866880e5112278621657ea, + 0xf1656323cf512ca13dd9d53b6fea48d0bc03b7a0a510a1d1c376d7c879c0a6d, + 0x1f7fca35f19d9bc9a9c510bd904477a82a779df52b3d938a34ad370bcbe107a9, + 0x1650f10d70200c4cf9188ae72b638a48efa885d0d57e4eef3bad1908117cae47, + 0x2efa5eaf0d9848a2ba0426becb0edb4127f4afa0b9532f3cc8f63fdc6f9f14a3, + 0xad402c14a8aefcb0dc67b5d3c1df188d1cece3de0f53cb313bd630594e20123, + 0x9874e7aac804e0a72c21eff6800d99327636c1bd05752cd398c2e19210a92c2, + 0x127d6e66dc4de7272bc0e6174ca40f48618e1c90ce71f173e0363278e6e26edb, + 0x178b0d219dc9fb0d491fdca28d89d4f41d0e650c29d8097a6ef982a3d45686ee, + 0x856563611627d9d176f629668c19a7195b0bef83a02011485596c0fb37595bc, + 0x4f01e13e7e01f0fb607f39a334e5ac5a14649c65007df2e0125d2c07f165f4c, + 0x2fdd1f6a4746ffc3721fe601b31335874a23c0353b217cc6a65f98b52c48c32c, + 0x17732cc9a7ab756b3ed24f4b5cd348b27c476b0804a47e8e8024fca28b858022, + 0x8f9e4a25ef65884dd6b159c396447f11f374cf781a8932b436e428d8407efb0, + 0x185536364010888ec827263bd36282a0609556021920ad8349159c80d6895398, + 0x1fd0879f9628b76eaf032db092bb6caf8a03c437a8e7cc0c81c9531213d61b8b, + 0x122fc02a0d06dcaa8bc1ba52dc7905ca13f2766023a8e7811876071cb0bcbaf8, + 0x8130052ffef7fbdc6d1bd38334212f34f3715f0bd1dfc1b36eb58331f5e9106, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x21c85453b5c8f53b3e43499159ccef5152fc9bc3b14cf1d67e4a80e49bd83b, + 0x273d34ed60e945fe972b67c2c155653e1c5c38c4cdff7c5753de7c68d3bc3261, + 0xed8f8c0b64423895664ee04c994ffbf1aed16eb8f6d2c05b46edf07a56d2777, + 0x9dbc162c39375cf6247de315a85e1730c451e59671499b7bab9f73ec47c70c2, + 0x2bcc328db7c571f892d3d934ae7c031792571d716f51494e8b10fad60b9f52af, + 0xf2333e3ab2c7a3c13420d4380f2a8fc867538db7882a5fa6a8d899e4981889a, + 0x1bebbd7c3e88b63ed37c373e359a741a38d1b8de608adcc050b051dff7b51580, + 0x101b1cfce09e9afbcc995aee85711574de371ff76a293ecb26b4796a16bc57e9, + 0x9866b876de53973d54aa01a3095719031e0a5ea78e26194422dfaa80c7e39b8, + 0xd34bbeadd10a0556a40cb0e5f84ffd96baa82621d7d850260115312fef1a5ce, + 0x1dcdcddcc0aa7ee28522e5b331b2805fb95a75d2e90f876940091c4c57345433, + 0x222013e1cb04b56d232f806664f4b950bee1c8965d49dfe59c7d9a7f37be70a4, + 0x140eb0a40f600989bc70937e2fb3db0e1cbf4ee953bb5dfb11c3ac257105acbf, + 0x1c2a10c01046a2bd06eca1a7850d8815dba9dcb5002710d469763ee12ce733e, + 0x4be5c9c1a16eaf24f0fd62603edfab2a731488c6f0066a29bdd96f8595f903f, + 0x2aa1bd7546c15d05452c1ecec07be1a96d1a916f6306f11eaf52145be3efc41d, + 0x1ea9d7108069582c4db4000fe9c999d50a6732feff50099ed5863996a0f4dfc2, + 0x244b02346c1e7aa223e1cd73cc84de1c6a729e722410bcd9c6c21c10f81aca3, + 0x818f382294f0d2ad1e50c908d6d58b0567eace452491c7e7e2ec8f02dcdf30f, + 0x1a889d417861f076033045816bd9d152dc38a64344876435c43145551e938c57, + 0x2a741e0f1842497fbf481fdb838af76f016c7c7f902d0f1cf91946d9b19b8f0, + 0x6da5a57ba1e1f0e02b65254d7ba4170ad9f42f8c2e209dd3482d9d100dcb69c, + 0x2b015d97e986c22f639d439958e5582192ae2a3c5e63a93876ee2cef01cc64aa, + 0xe6fd84ece440532b1d2a84794a2c0905d14dedf21f1cb88ef011d6d40a44966, + 0x180cc40f9b1a551d6f21a2616a31fb14ae3de6cd3f90905090112f08cd2a517f, + 0x113bdae7dcdb55a5a29449e0196a7ca19785e8f406aaf81d74f7c658604d7b5a, + 0xaea1a111b956238e2034bd82eb6566729d6b744738d0f907c24e91cf0e270d9, + 0x2d877c0d3637dccbce6fced14de0db189ea37e2192595d31ef7be35042b49789, + 0x64a1369e5439801597f5f4e2a95058e001cc3b7d449aa87f991c81219590592, + 0x133405bb6e5e245a0ec3785cd300ed55706f465191cc6af05debfc09ff323eed, + 0x228bca7f9390e0cfe1125af0b7ceb2b228fe7d373e3bfe077385682669dd6231, + 0x90116384ea569082bdf437341c03094a1f388ee217c0e6aba3987a55cf62d3f, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x2dcedcc12959aba1b815150ec24051fb4dd8440208b0f4eef706f364709fd64e, + 0x4aa0509e7a94554490885f0bc0055b4f23a003e14a2cdc51a8f1500b738512c, + 0x1ad3b6634a63d1bd97d8d745888387e7030be2bd5219c84de5a4b21f6e6d5c9f, + 0x2722ff91fab311d5cd493305ca2e581d23ab35103b7a31d7436fb4351e5167c2, + 0x1756e34f7af0be32dc4312c914ac48b60ed892e0a941866b5990c475326a0a08, + 0x1f9681a26d581ac87fc486d845382aa8afb31782fcdc16ae3e996bf79e8910da, + 0x2c407593aa6fea946d0ec1289e59dc993dbc1d689a02efefd916c42b56d4e056, + 0x12d5a1f35a3bee7be87beb690bef3b422d4db19f18f457345c5b13732213de41, + 0x1e444d4510e2cb542a4bd1af5232ab8376e5998f69193243509b05648b59e317, + 0x1c51186bd573f6d8e39dc9e5f85ad954ee64951ba2455dcd9f415b2ef44813ae, + 0x24c84617d0f0266fcf18464eb08422f51633915380696b571dfcd52fdcab3825, + 0x4894d26fbb969454287e1560c81f0bd33e93a0ff0e360f882f03621ffbb724, + 0xd669e170c4428089bb490e8af37bf2b4885f61f49154eaf4bca6867321330cf, + 0x54ead1e70a68a2a5bf0f9831c8b37e0c4692840a5eecce2f10842aa9ff4c77d, + 0xaffcbcca6d353dc0060f6c0e87a7ed6926d6518e2e20181e76b0ebc3e55738b, + 0x21fca621016a771a181efcaff53647cf8ac55c30813c7e1b7e0c54b1b14d4fe1, + 0x12f2e46957b88910c30c9554fd01780e074870fb9df0252cb735dec70dfdd6df, + 0x16baad45361a5052c6008a02803656108d8bcf1ab65f3d1ee9c866e2a04f1713, + 0x202cfdc4cb85ce703b7ac41cbf904593481c951f9faa52e44594c3d0aff5f070, + 0x2782837366366c2f9b943714e6a11097321394713577fe59dbe72a78f4d93741, + 0xdd863bc6e9a0abd947b2684abe555a269da1eb7a491ea6c5d3c44e0cbdbc0d6, + 0x2b1ab0a5b5516d7a4f31b68c93f21638a3bbb9ed321b9915412b422929e8d42d, + 0x247c684cc872df52c2396d52f5c691e459e181546cd644fba41843beda35f07f, + 0x17b09bebdffdacc6d3abdfd4fddeb0a1d04150563119def60d9ae9de6b13d0b9, + 0x20377c6ac1d667eeaf88e001648da149ea26ecbaacaf079f0a089fd6ec42694d, + 0x27baae8b9a93a09459ff4c88150b93e9fa3fdeb4d719d37e4fb03b29afde1b0f, + 0xe105b04d1d6efb0def9dd3f43655181cbe4a1ea329e779cec335e27190d0840, + 0x1684a9463b01286e5ddac76b990c6ae285c81fc4f7e7715b1ddc827e5caa82f4, + 0x1a1171d2f0e3c131bab4ed613fa111bb85f3605028028f5c1337b4ab542af356, + 0x228742f926c112c443bc2e362be8a44c49ed66e17038f7be297d51482c548ad4, + 0x10bd84eea945febb47f7296e5bb833378ec26f61c36d954b87a5423754b0d1d1, + 0x2d17cac96f225898038e5ec16560f6563f768a7e127bf10ff8ce1bba63d032f, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x23091d6274d72f0516c11e52c62a89e2c218acfcec269d8588246bc63dafd307, + 0x9400b7e97812bf8321b96b3c4bb695dab509934e197ef9393d9921a320fdc5e, + 0x1c9c8e269b7b5d2527e20b5d340f2978fe4f0b969e2b1f33b5ad8ace05931036, + 0x29bcaf9978fe301ee64f032f3b6c5aee47fa89a118490ece975e4765a688e277, + 0x2c43ee462e5eaa57409884a4bf82116fc74f060cd3ed87b249066bd753e57833, + 0x1045ea9efdd2d37654f2f419bc1c1e07dffc13a78e78329d66a80e816b75e0f, + 0xbdd990f09c0fbfcafb0ad5d2e7609fc639f4643262b9fe6064b1cd9f59fea9f, + 0x1cc3aecb65d88c117e077773b2ac321f1e35552bb82ecfafc19a6d7f58cca0b5, + 0x234ca75eda2b98da7aa4bcbdaf01b94a0ba116a7cd4def0864e27ba56623ac56, + 0x1e5844a479ef874349416efe4ad14c691bbd4d60b6a069ff6fccf0b4268368a8, + 0x15cf4b909eddcc0af84d45aa2a5ce40f004cea2337de82214b5b1b8bc25fafc7, + 0x21fcbaa23db9816f459fe5dea6035f4416bfea9e46b1ab150335fc986a5d3454, + 0x23096d193c542015f5ea72945e427601d8c5213652cc7bed15a26118408f3528, + 0x11ef3930fae556e5688b2e5c5b646a9bcf2cc8c9ed84699798e380534da1ba1a, + 0xb2804a0c39e0406220d23e5180ea34743b823259dc5c037e27fa14d97aa1236, + 0x293618a713ae76e001654396f1e7ce9885f07515d1a52ae6188bb68411cde19, + 0x2083bc523f48f2310fd04db4378e73b3e4a774c04c82721c347d841cd429c1ee, + 0xaf7b362c84812df2052d0e04ad07d830100079327567a741f0e33b05f20a3af, + 0x2f0a9bfa024571a9eaebb8b6c838ee153298f8d66282665b8d413e67fb9cfe75, + 0x8e5f97cf239846c4bb22151c4fc6b54f6c078339d48834cb674108ebcd533d8, + 0x2ad7be60b34c132d62758a699ee2b9b9902b5a66f4d0a1732957fa312693130b, + 0x2bd813ea81fd2be04cf74361aa9ec03890ae9dc9f2c62e392aa0077bcef5c39f, + 0x2e720551011b0b99d8a0265f870ec80f9b866a0a5f158a2baf5647f07ebe9982, + 0x2bf18b6a692d4c64185b59523fd75a045a4844d8df2d931c739fa453740b3cc1, + 0x1c166f7ccb69a59db6b374b355fb08d50eaf4df7760b2c3084b229e822d858d4, + 0x79b610d77c02e9a71628bdb9524d75ae9822b98d32f5bc8624e3512fadac097, + 0x1916de884fe9cac13806c4f7061488f0a57abd1ae403ab0257d21b48a0e411ee, + 0xf107fa1c9d4a774cfc10bcbc3b38fd7078e0f374b5e9bdb38e1e04d26d3c383, + 0x1b3ef1482c15923666e1cd5dadca82661bfec0a3a58f89e54fbe8fe2428669e9, + 0xa27ba24a2a7ad35ec53a125a0447abffccc68a9158523ff88cfd738b0212802, + 0x1a525ed62eff06bd139f3fa58d088c836c381a9ef859bf16d0c4ed2400463a4f, + 0x822eb9645c965d4f6b677191294e0b5c757d448ce5266f76ae8ff8898b6d0df, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x1af46f08f6cf19a75e2deca250a062244a541413cca7183cdfb8ff3496283677, + 0x1839ce61b8c72bdac116fb26e68db1136b21e762a80dc263434ceae93e71e226, + 0x7bcd29e7a46c57bad325631b9dc70f779746e4e3e83b6149cf7d65224299cc1, + 0xa58deb34a1aa7a97fbd6de55294ad6ed911731da0f1973bb30cc4e50f974633, + 0xc189862d767c9d55128b55fbad2c53c3c7f09f3cc3805404bab81d881c1f79, + 0x3f08f5db02c8c4197fbb743163fa98e215093b833ca0c1d709a30517f1bff67, + 0x1bd997c5ae62f46a4fa08c71dd8281fa20da177c45a5b5e0ea4cbe42a9d768bc, + 0x1dcdc615a1d29786c2a6b9d356e15f14b0516022da0c8237329d9ce31e6c9064, + 0x2125c1065d8c42af0dbc0d44be29723de30316bb190e487fac79c6c65180c6da, + 0x2a9dd846b9a9250303ea18da7dd2f67d8525074d4259656b9d0def7f2ee018d1, + 0x2a1da460ab707f31653862ab6df0bfaf474d39cb909d7b84314482ad8015bcb8, + 0x2f4620be83dd42a9810cef816801cd8a77d59146753fd9589a4437f43c44e295, + 0x2390bc3ee228ab2dcae07fd77d2f2b82b39be4a3fa9d15a82678d487a4ced7e3, + 0xa0245ae7c93aaba110979562f1bb38e2d6e47f8f58146c2e0af29a42a8f2225, + 0x27e3d9f7c0d6c32a9db8c79a3fff7227825679bac449cc5567f21edc213d94a9, + 0x2172e74151fc03eb201e3e300b2a085798e6d27426da9b9e2eceac40374c95b6, + 0x246a685246a9403eb01cdb380b39b49b35d649136870954260afc23e51129460, + 0x4f050f7043b183cf35f65e5590bd1ef9b1a88b9a1154e5a6b48b90367679ccf, + 0x1ad58c70ac13714b721c7e1e43474983524bf5ed75ea0a375964c17eef897acd, + 0x9d3719d52186421cbe870a8dc16ca12d479447bbc1b7209991d2ada9cdd0552, + 0xb2d605b80d2d16b8bcc936be91a9b58bf372160c58214d5d05340268db293e7, + 0x15efc1be172f0c1cf80c28816163d6281796fe3f767449dce700031a9809382e, + 0x18a72ca7580618a6772dc37da2d0ec3721130a93ed2baf7ee8a458215351c5bd, + 0x18495f1fa2b09573b0122a6f3bbc62dc8eda0c773c24cfec946631bd226a5222, + 0x22835e515350739783c361cb745419032be6d7a16c27cde776cd9a43509d5027, + 0xfbf1fa536a4d74e1eb517dcb715dbd57e9c879fdd1184956e1aea742c4b0c11, + 0x1bfa4ad591bc024f156f69c1c6ce033e65507f6f2a1b50f9a370ea96dffb4fe1, + 0xb48ee00c1a3b873da040822c8d84a7d413b07806c5ef6ee1670502a2797788d, + 0x1b0c2c9ff1649fda06155af9c401957dad06ba11c9d6c284ac3d7f6b2e02196f, + 0x11b9857c7ac1e55d6696b9323eacd2b75e8e64d863221f4c49b50c0af4ddc907, + 0x4d2913e434864bcadcd0a0f187751dbcfee68f8d42eda00afdf9fcc254a9297, + 0xd47a86ba4e4c33ab37f00aaefefacf692c1baf9b37db068097f619f44061fb1, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x2ee08c0e4d7f163fcd113539b4be76d5b8c6dcc306994016e2f50b4065ac0c65, + 0x2e4ee3771e570cac361666fbb6230033f0d2e5df5a43207f4c8c4642fc9ca473, + 0x22e78c9bd18311d225b9f88c117cb18e658747d500bbbf61c291fe7ebe2bed, + 0x1b015cfa490fa705be3b9f5645d4daa23c2098cb0939f019d1697019b00a4435, + 0x153d716532b1856b425b07c5cf73f7ec4bad3458ff9e031d6c191da0c5150f5a, + 0x25ddff7645c1cdaabb52a3ae26931620a4186ed35cb914b0cb76bec51f7b561a, + 0x21bdea71747a451c7e825e508ee4c40df40404c011cd5f7dd62ced05f3841437, + 0x2feda62db255b655f3be96a4847d2f1691ce658456697ecc602589c3ff0674db, + 0xd3187541007936963cd4bb6c93596b7cfa56d828df39d9f8ff05d934def0ffe, + 0x26e633f970dbba038ffa30d735ff34541108e2f7bc0e58fb25b8d038eb574c1d, + 0x23c8473f9504bc04266fa76bf7064d8980fac8454fbf44f68c5e93fc37bbfd9b, + 0x187a7a328ebe30f3fef7620ec582ae3b457ed1d8dff8a30d60c518c1d3f8502a, + 0x1072a4199dd532ae3d36f2c3f07359148be4d81ca1f1ec06bcec2c94b50030d5, + 0x1d9c9c64cced19734c56f62f6adedccf54aadb170d499a91617c7bc34f0207a, + 0x1b09945179822511bc0b3b20afb76f146b119051e2c6c8f5b9dde03cc761b170, + 0x29d1379f40c09d9a8105f1814f9cf4cfa8419d5442c22575a0f9836ff6728216, + 0x200809b6e7114084a23b259cc6dd8d4aa9beca3ee806557a250f98523363d583, + 0x13169f87f4d5bcdc80277fd4bf931744a09d4b0332e4e54dc351ec16f256db24, + 0x22486dcd2b50c5a6e8b08cdbe012907083817073b975a842751aaa497389a092, + 0x986aed7b10fc9cff4a80d5e338f69eae4aa25b45d931499fbe7080fe13a841, + 0x2a3346c974a7faa8f021c72b4b516dc527033dd96dd87a29013a54ff235069d0, + 0x1ac08487b535338f18f39bbb2410e0c04feed1b023c2b31a69c42843b46c7b4e, + 0x2db4eb2420d57123dc86f82c289788f4f5882143e70237ed7aed2b318f2f3f6a, + 0x179e156f0f6229e6259dcb656daddb273efbdc57b78b1800b3fd492ad4e2ee85, + 0x18f1ed42c2dca995ba6b2b418378159005da5fd6d46f31d424e404fdf85ecd0e, + 0x12d1ddb3125c15c61e1a07709ecd1782cad928312bf4d32dabc0f3244b98c067, + 0x19a555ee9a57b0f249f762e63f02fc9dc41421569e40146d27b805d6926dbd17, + 0x22905039eb92f068da4da7f2bafe65b1743fc2ac15dbd1dfb50b6a8b890fc933, + 0x2aad30b3fda588c43367320323c66ea6cf3137cdcf1306e93d173f1a5f5bab0a, + 0x661d95dafea3da65844c73147d86b8a152a0c737c6550d2a590597b6be28986, + 0x149f69bee6b12529d2a1332a22ff6cae413b864da5232181dce528343488fb9c, + 0x2f40107da2eba4e1d816cf7cd488861863a460e5e00780c3c07f56c946096b24, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x89517399fdafcc090ffacbfa0f82b1a356c182a9b8bee5a125afa14416693a0, + 0x1eb0320ce68e5c0a8b9b6c8ceedddf2eec4a8dffc775f43aa9545f4432f1597, + 0x9b3b380291ed46dae5ec6779af517d4c8253ef609e78a3611e09a6a9ebcfb76, + 0x2712ea45ea88a54e4899de133f9d02454004209aea0434ed07cd33c9305c0107, + 0x13e4cec6c5fcb7a55d2c5c9e0dcab0ff3a3f7c26edb5c0c5f5bc00c036817e9d, + 0x132f73f3a5a70fe12bd077c340752e6837ebebea4e7e8c06672c3e0c09aa2436, + 0x24f5ae848c7765ed4cb20417114c602e8186fb02d209b22262ef6b2f9f4c2d4f, + 0x1f3203e2946c3e784da190ea76628d98ce46cec50d7720c6289b9a10b029102b, + 0x405b17b0927364ef8a190472cf69cc8fb91338ad0a037a6ccd6b71d3d8a5721, + 0xd7be909c6d203f7ebbb26f688c104599e34edad7bd4fa7fc11c6be8d2005234, + 0x23b843266076f360c24e39af50a5f74adf3ba002859b6bb7d503abf45cc9d338, + 0x12ecdca40e7a5ab513a78862d77f90435ce4ca0835a966112e42457c93520039, + 0x248096c473071c7c2d5c8dd84006c245c6152e0f86221d82f9d0b2ef68a0c1ea, + 0x1200227f631558e2d83c5b6c386dbccd8c019b327190ae6c21f5e6ab44bfc644, + 0x1d757abb199a6c84d960aab443cefeb6d6e433b5cebfeb198f803eee3effc0ae, + 0x273c19ee6be35b4b8999349c7b7b83cb57aa165f0b302a2d852be61e83409d9d, + 0x2d1ca26ca5d5dce1ea42db19426bd074157d35e28ac98e9d0e25cc710354ed88, + 0x2ecbd2ea29341b707d79a20744740982390655279542f9837e77f89b127d4a6, + 0x266a6643f4b1c323fd22d8bd34c4f9c431032f05b0c856e107d92c70d4bd5134, + 0x1062e99d5dbee4ab0c047ac41ccb0121b492e604fe10e2db4ad43ddf677f4266, + 0x15f2b18d006fb5f2bf5801f8973bb94ec3d4b03e8d656a59bc09954783ee2b6c, + 0x72368c0d5eff7b59f5b07b27540e85ea042a1c80ef063554f53982bc581dddb, + 0x17aa521645020d9a4914e5679bdc70c0772edabae0f82c0ec5ec29289e0cf286, + 0x2f968cd2126db9260be98ac5a64250d6b1dc60db752ce86342dea9d7d6eee209, + 0x1824ed09caa77169c3188a0a3287faa284ed7a51977826f1f64a1c2be32c909f, + 0x2b8fbabf299d9da38fbd033dc61444ae2500c1205b785a5fab8996dd9fd2ce68, + 0x1be598eea60828e10e0c4cbea95736584eb83c6ac8427320802d9083f5e6dd31, + 0x463af34caf20c7b2cfc3ba540ac128fae440690c1fbf4bd815ea2b854183ea5, + 0x2dbc1aa280bb43c06573fd90ab5f0530ad450b992bcec2797ce0adf60937ebef, + 0x2aa7cd41625eeed2f8e460ce63d2bafd64329959d40cc2e6fe1d5c48be5c501, + 0xe3c80439636f2b40b1ed8d33f792f2a5d2e602da651491913ba45df63e777de, + 0x3ae4d78e90fa89f943dc0b4c56d32f5c846734071ea1bf6bafeed9e83f40f4, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x1f3ba6f2a0ace67807ff54fb3752a740b90d4098ff54718df07cf6b99b4a3611, + 0x2b2d8688621a0b62968c64cab0db27f41a51b32a84980ef31760d2365d2c3c31, + 0x27ecb287f3d9aaf1137d4058abd749febc280bdf70dfb7e5b61a7efbdb32371a, + 0xda7a17691f64048331fdfa135dc56a636b1bb8e1c08ba7cb06e9bb1a8f5dc22, + 0x228e87cff48ac1eecddd22fa3f50214fe0505cceb58e8aa515a9b21a22cde940, + 0xbb1e094527421fde9a1229ff4878eef766152df2998fcfa44ac7b71906bdefb, + 0x2162e5b127d7ea5fb675aa6be31013c2b9d9429324fab62ba9ce1ca21b3c5f2, + 0x5e7c2a9c59abe90189615a15ad93e146c27642aadc29e4e40b8dd9cb735f4e7, + 0x3b7e7cd0a61c8a953ce16bb6adf8f61f49b560e1991497ec3af678413535e12, + 0x2b48a6d7de08553fae906852fc7fb1661e6f5036185a3f1a75c9a9abd0c784cf, + 0x1451c962e6d5dd24e45dc7e078dc64fcf59634073c13cbdc5b8792a51ffb8e37, + 0x22aba4d49ebc306f4b7b4e2bc7b7a1ff4411d89890f9fa5ba2408cfdfbfd18ae, + 0x8edd76a666b9264c34b0069c62d2cb61bbeee55882ea1625d3e178544cae4a3, + 0x1cfa9bda9fe33f9db0b1d190eea07fb0dc6855b74ef166743abf80aaa1504fbb, + 0x21825a8220bc43bf14b06dbd2b92424547a3fcd0e8b0d7ac7543f56382f98732, + 0x22a03c9f4361294621f902a43008812d5bfacad871172c3004b7b58126690dc0, + 0x2c4d459fcf7b58e7d7308af04d943530955cede00e37d3ed491b86f05c49beae, + 0xe099659a946824830b1fc5e17d4d60343f2879ef488fa45a9e3b3af3e80a143, + 0x3b256a5437fa8edaf6d7bf9a7b2e695f06dcbe80aebdca4f30e28c8c4a49882, + 0x473c1deeb016648a6d5f3d0fa4bf31d1d4b9b6ceb0c7f4a76051515104a617d, + 0xa21735e2b1040d8dfc4685c5c5a42ed07a02c216465ccdd3134c157361995d3, + 0x1a0b96ee186897808d9130525778e13d2259a406282456b2edf84434e081716, + 0x110d5d3866aa52ac620b233dc0d892c39f9e376307a7310c994c8aeac1233f4d, + 0x1fa9ce9d08bc9ef43200929b5512236852d4fdfb607f5ef24ccb666dbdf053c4, + 0x8b8fb57cdb79ddadf41dd3da20efbdcd502e89c8e21323ec99f0aa99b27dfea, + 0x20e451f487bf7f30afe6895258df980c732440567ef2be720f683b4d9bce93e4, + 0x18934ccd6b94d3d27af8fcd8f02b3b2aebe21465b9259c7def51799f1d971901, + 0x2502b2fcb6acfdf7bfdda3e968afc622b949e55d567100c4007fa0b9405936e1, + 0x1e22a9af8fdfe9185346e22a28e4fa435f64c8e0f382ef20f27c0f19df51e520, + 0x1bacd78770219cde479b8dee99d460c73a22f674ed0066ecc55d2344c72a0fed, + 0x1c5dcc7784cb1a230304a6905b05621618b89498a827ea77293b96d8fad9fe3, + 0x1514f7a6184d2f5de98511d358572d7d89d33bb2c6d27a5fdd768178af4d7789, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x2871dab4aed8cf27bf0e9a2f02f0e7f9c46057ea80fa64d358c4acd2bfbf35ca, + 0x16b48bc071b2d9d75c6715e959788a5c2c634a7ee951f61c6c252f9f4c96e139, + 0x2423991e2cecb8c7d0cbf1f6c75a96fdd9cc3e1d3404891054070888cf58c027, + 0xaf6489dcffa0471166ddb75d46bcbae57d239e90051d360100acad86309bb34, + 0xa8fb4c80f28764fb489926f032e0f6bd6bb878ab5632b94e6f960e841780072, + 0x2ab3c31cf9ddab37f0742aaee26190292952ba391eb6764ed69434d0553085e1, + 0x128a537033583b876442e4b5274483d0e766a01ee4ab310839f6d8a66c052ba4, + 0xec7bfaa62f8146ef2bb13af733cea64631b21106cd47d456823b3da92e41530, + 0x1d26f27900c3cf2629a540caa3f2fe0896977782cebec4a7c5fc610aaf9f288e, + 0xcd7296fc0086a3895770b3d0a7e27302c80383a017e432b69fe2503001d14d5, + 0x5efb5ee8e22ccf78945ddddeb3f6ab0ccdd2980aeed476369011dd2017d2cdc, + 0x2fd3058e8276c3e1044102e37c8bac9f9ceca3d4898dec5227152bdac4876063, + 0x3041d0de272cc4007331a1217ba0462b41f9396a251407964e90f77d20d2be54, + 0x22b44b6dc784db7a40c2e670800e462758b5249d78921516293fe1a51866ebeb, + 0x1472f9c6b744713482cf7c9f2c82edb0cdcb81f238ddb5305a14e164909a963, + 0x11cc50e647086a21c18d924e5cb407e0895d44337b760d95fc1254b690b857a8, + 0x1f6870318a97b3458482c2b2e8f4896d1bbfab317d95478653847bfe27f73a56, + 0x527b77967bb4404a5a78d8e449466ea5dd85d36d29792fcae4ae26f30c39253, + 0x114776906608a453804a6ab3ca1fb1357ef1e68772ce78d4fa53c219b47c4ecb, + 0x227cabf1187a8e8c8b983e4452b407d3ad0820e9cc000ea38d2298cebaf5ed10, + 0x2cdb16e7154d3366e88217ff94382b8a7dc86b47ecd50620b65ecd5f98aafd89, + 0xbba92a567cd15cd0923cb79ec491f17595d6af80463e9b7e2b2c9c6e662fe41, + 0x1621a037774eb85fbb2ae136893924aae5ec0394764f2bd204e6e3c2cd053e66, + 0x1b2f4b4974fe9c4d2f6ba8f3b51084b886a115dada554e313910e6a0a2a736be, + 0x17f058954543b8005d9e5cf0393b669790076e523dbb5bce473d67d98b4660a1, + 0x2a131d0e2c1938f53bfad52e5fb33120eb12d9412dfa7c2c79b20a4a9e618a96, + 0x1e1f17b82c8ec06747b63629d99e72f5f3cbebe8bded20c0bd7fcd7ff8422321, + 0xf92dae5b5070535247aa7062d15dff0dcd533f7ef798556b1f704acc72a1a91, + 0x1e26cb1e67c4ca4884975a5dbd44df8c05f6a7a813d9c3267fa7f735cc144db3, + 0x278e469316bcd00829620e438af377734719124f83c509d48472294be9910f9b, + 0x2d931e21c6bd70dd337a21eb006cccc570c8e248358e256655d4eb409db88256, + 0x1f3aae749c86c139151590615fceb9b55d78b0436d6846e4ab2c30abeed628a6, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x164cecda3aec3963de5deaa919a419e7c3e7ed67b00ed3fe37c941bd3aceec41, + 0x1ae5c087043dc196e76f2c1fcd004f07bf7622f91480c2f43dff37466824e28a, + 0x206d121a5d5c0e50c6696a4f6a3ce23d86e842db48b98006111cdf9eb6501362, + 0x273853516d030f966503bed07d9bb25e9a78daaaa8a16dd46ce4ead8b0ceb92b, + 0x2a473b17daa8052023496f81ff3471c76bae27ed780b23b659056288f9c80e8d, + 0x126700ad12b26c87c8f7c90e8a6edcc613530f09d04258d1d0ecf0732d143cf0, + 0x70f6900e211a2d3ed359a44c1949447264d51580679fa84dace529a0de19d42, + 0x1d196536166aafe99006756cbbb15e621903ccfb19346cd45ab951b01348abd1, + 0x16a6413bfd363eee8d28cedff00c8c86e15745dee50b2ae15d45f4d796213d15, + 0x14fe39f6bc1fb0e0a41f9cdb142b86ff95f1003519cb3a77a05e96a30153132c, + 0x2f3719862194ed2deca377a1f1b58eca9aa0b726d3d82859ac5acb5513159f08, + 0x2ca365f66b59cc38857d65e1ab5a841574d5bfbcd0f9c2607b704232d7d85a02, + 0x1823d36e1b33841eb34a4601668596fe20e08c28f8772ca3958fce53be2c6c20, + 0x15d27279b7f1b7514d007345f4702852507d07b64a2f1665718efe5b74578898, + 0x11b3efafbd53f96ed7d09373534f299562335045a51e43cb1aedf4002b7d6bb2, + 0x12a0a91a6025546911068e6f50fdd1c6e368a52afc769952c4fbd9734f5004b8, + 0xa9d7fc64fc90b912b49748faa4a4dcaeac8f3e15df09fc92f7066b55904538, + 0x15371b75e8adea4894822544c8d7cb6b670741aeb1f1c465e35786fc9c645df8, + 0x25fb2eaddcde34519e511e656d51a90db8518b6375646ff92caa4a914007d517, + 0x2dfbb6f1e212006c39bd89dd4a6543eb0fcf94882febc1c958eb81012f17cc53, + 0x29593bb7f971b987c1efaaf91cd3d70478b3b8f519e210d109413adc4de72807, + 0x134ce1956a848bec4ecf9b6033710c655b425fe7a2e42a9143d989c876e07b6e, + 0x232e589b327424a374dcc64152ec03029cbc6b1e6935e1878c89f7daca2fb8c3, + 0x2ac4f4d9d1ed520e21fbfde98b4e9169aad8f701b95f7aa6e1a2799d72b599b, + 0x13843ac1a48019a500ac2aa8313a9143b045dd338120bfc4b4e91c1750b27bb5, + 0x123366fe683fee8c58bfedfa072912dc1bf50c906115880d4954763e648a7c92, + 0x147bc77d1f7ef7f0604a669c3bbfa3aa535711a43a8ebc25f786db8c951dd7a9, + 0x2bb5eb86f2837f69911dc3afe716c5fc897ed54a1ca84c7e473a92012394166f, + 0x25e9535591df883d7704dbcd8ee87be36f7a40fa9d360b8dfb5a38892936d47d, + 0xcf22a6787e93e4af1d585205f039fe30280460e02c64b4aa6a0fd361fa09210, + 0x15daa89536023119f4f32836140088bce9082cd32db18edc2a4b963ed61665b8, + 0x26a41abc8b0969da23c9f511b4a47a978406ed147fb0687d146ff73f0a3f2908, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x24603e3d523263ba69d2161f7bd3c01b990b96aa479b47d8e7bfda5779b31a70, + 0x6f06827f0a52b2434751f1bd23bef70edc803704890114a33bc1b173cd3fa16, + 0x18821acd1d1a183b3974714b4c15b9aa338da2999ab219a65ef04d6538c9e681, + 0x25d1c75c19bd34c31e5dead0dbbabecb70a1952af3b9acc945e6bbb7af79ab85, + 0x2d16cd48d5eb9d3884782960fc5f27529562190c5c9203f1b0b220b07ebe2251, + 0x1bb2eb154cea451a7591bc895cf9cb65658133c6f63533a7b45362197d883e67, + 0x2c1c099ec563345fddf03a6c54e2915f1a7c890b6554cc496856553d2b2173c8, + 0x14de7c8a6f75d5c098439608aefd9d3f2224fd7ff2d301c62ae728c13cedcb56, + 0x2a12b1666687a8f3a14e61590ab004587a058e42c5f45840bcf0c7a03487f34c, + 0x124f681268028f4ebb6678e070951caa96bcaf09350bff4f72c093c2973d16ae, + 0xc61ee197e59676973cb1b0dccda3d618981b93d24285440f223146a7aed3f8c, + 0x1d6a13345c16963d0fc372a33a3ccb9d7113e42b8336ce4a0cf68c6c1c3bc24f, + 0xe90fe044265e093e82a00cb140c9ec848c3807ca216ae5ca0608b360547e72e, + 0x28a0106ab648b3fb1963e8b51f6a26cce8ab62d75ab26214c389e0c719737002, + 0x1903a3f14cccc405351a0a3ba23106102830c134d14c378226d3a6599e75527e, + 0xe69b6a45f98dc94d36e7f80045e56fa8927416f96bf9b2b603c32c6d0026730, + 0x24028083240f0415ae27d250b5e9d2611c5baf6b83ca01c5fa08b2c3984ba37b, + 0x10b97d7b32b7541cddf569d3fa3ba4fc792f67fb4bc8abf142bb9765ab3fbbc6, + 0x18514e6b6663e92d0b702f6830542f841872a9865e8116b68bf03d55352ed948, + 0x7e84a91c22df5f22e465c35f665c6a56c7d41e6f20f3d63589aba4a168981a0, + 0x24c67c3debacff4c75f5ab6011d39a6ba905a78980603f9b520dc5f07826d2cf, + 0x2302d72a48f7284aa9dd46013f218acf1551249c22d8331dfe48c181a06ca28e, + 0x1332fb9ed5a5a86c5f70cfdb899cd053af1cfb9557af1a5137be1e727e3169, + 0xecd3e7955fa603af46e69fcd1699d5d57db5eac3b9095c0c7e0b6d24dc7f542, + 0xb7012f95446a6e56b35ba5feabc8183ef882ab5e99b48dda6a00aa4b5282ef4, + 0x2d9a9de40201e8aedb6c83aa64d6801af749b464ca23db2a743bb6df13c72986, + 0x29bd4a19c267732d1f213a478c9c677a47804a525df520ae995bab6c79f0c375, + 0x1462f5ae05431a649833f4d33d7199c6af0a27a33c6aa74514d706bc5facb110, + 0x291f96083043911e45b87995cee2d52a0c4c1f1a2537b6e890d293b1fbfc05da, + 0x411cba90e608a51a8d3635d7e842ff58c4137db7eeef0ef16422402b588766f, + 0xf7b5ea5565816bbb8c16bfa946c6145d607e773ec10b74844511161469baf60, + 0x338cdfab4ce8fdc9f081c77f3b7a58f5331d3220cf548229c8bdc9f5e49baae, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x124f60ff00a0e62ddc0a356926a83b8892a7fb8602d5d3b955f41f9134953107, + 0x7ec673039830a0f06701ad707de762e97de268ad8218f4e771ccfef70fcaad6, + 0x740e5d063abce69067b719fb33e30e4b3da7b6c66f26bd2d7b5320a04dce396, + 0x7808acd3ea0c249f88efc1360f1c6e539561f31208e860921311b1c29b598a, + 0x112bf7f10ea174a939adcf38e91511c7c00990bf176d3478ba5c5bcf9c46d89f, + 0x197b19b25c2afe93631a78cfcbefee4d7ec4f7a5e9c87f5aa30861aa5f441049, + 0x1ee3070e40c0e0e740a67449c3789b6b1f5b64047b9adc4a1a7f9194a7ed7c62, + 0x2ea7f970eaef265df0ba7d65c20bf474925bbd7eff4c9af087c38b5bda5c8a40, + 0x87e362b638c1e17cd837e14f954fc02cc1a020c62e416bcf5106c0e84a42e4e, + 0x66c70edf98939e555fdc29bc6c8db703afd5f7317a97ec805c1aa28758081bf, + 0xb7cd01813db20a6c56bee471eb16719fad273719aacdba7c475b9cd9fd6ed2e, + 0x1baef4e284700ad99e75947e51988f8b21b306e85552c9586159cd2fa62d6208, + 0x2d70435bb7b0d2242b1bf4cfa9bd48cefa4f4949305956f07c6ce9f40a4f63cb, + 0x2c9f4b07125840d0a8db29b2c8f723da914abd2357de2d0bdfc761ed1d2cb190, + 0x1a68c6eecf6121045900f2d146f6e0dc1ffa95afca0130f4023ecc854ac90979, + 0x2bde9b2172e01e033c899e7dcb6910441e0b26ba61885817c19257c67a704459, + 0x196364688be6c007d5caf7f0aa60dde7a9d4df5a72201a010866f51d5b8e44d1, + 0x5e25bdeb203c4c1c10272422c44f883df61bd873a1181005937ac6897b820c1, + 0xf9392975fb3baceecec89ce8dde33d612f7b51809c70c79560e5aec4ea0f97e, + 0xb3a94a0d7fa6808d540ea7c94ac84329500fc61c1c921f6e1a02be72e0552e5, + 0x57f2f77f6f39fcc309ce2227ac987f88020c1156a521d8b4a6298ea3bec1f95, + 0x287141748ee5782d46d91412095b8ae8a817341797734ceed2fdf000f7bd2ca6, + 0x1d457716f5e27115f1b3bd602743ddb625242575ce407e78cec5c033380fea0b, + 0x1393304221b7afe064f39562a25a21c896a65c27cd93ed89f500e9eb5b39b2d7, + 0x1000b0acd83b8b51113119fd1783d3043017da2eb32954456b6c61faaa2ae29e, + 0x19c9c7938f860731025bd2bb1cd4add4ad7389433683ec7fd1c2c0a40840400b, + 0x218bd78be9fe83b8814a959ef810968be0cd8f20ca7778496f52251b1a5703ba, + 0x2724bc9c179c6b663419051e901b45a3c36d9f59d63f41dddccc120dfc3abbc7, + 0x1e9130d0ad5daa81b807d86cb977eefe449b9081cdfba59bf8e1b43bba4c1077, + 0x2d75c84b8825bad22720289707f2709c595d7a5ff8df9b2190359400d2e925e1, + 0x27628d274cbc76c2bbf5005702ad14bd8b44ab8cdecc65c2f323f232db788557, + 0x2a39cb3d3633cdbddcd0b7cc3744e46aff3450524dd573b8f67a3c7e3b9c7a09, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0xa09afb1c54f1db4544f6c0073aa43c0fe17ddede4eb2e965a0020b3734b3e40, + 0x18c1bc97aac4cd9735588413be17348e71d1a7d14a7bf175c8a48b5b85e9b54, + 0x1a3730dc03e7f844e8876edce2a2d00135702da038a3263faed39d048af8e466, + 0x25176e26f891655e4ecb9a383846a2aa15bb49936c1fb568519615a0d10327c, + 0x1190921ca2c2054af278beb8ae7e902f2f9fc032f1ee2e661fc045dd643569a, + 0x27301f456233aa2eaa5e58ca623471400a5885e066556edac068e8187bd53fc, + 0x14df7b40c8531784271338eb6101a7c565297bb9fd160f5633d1fe8a24f22b0f, + 0x201b7bcedc3f893285dd6a8d70641086091db277c47d721fda35ade3354d3756, + 0xd7ec7dce868dee03f3cc914c35bd061c8c075ab2b3a24d63514e43e61137f25, + 0x1f4366fbd21731723a6377369cafc1ead066d0e96336a6c0cdf44437ac6999f8, + 0xd4f720bd1b1d8dd2da533015643abbe2569c2142b3827f769bd4c8fad9eb7e3, + 0x2555325b985eb37f57ade931b07684d313c5fd72badc53f218cdf3637e28ac20, + 0x19577c98ebc619f92a0ff099cf5c3c78b18f4e5230eae7db5e2f88a18148bb4b, + 0xaab15d18bc399969878f0303b29e85aa3ed5b5f0d302efa97073d0580bcee54, + 0x15a5b74d5f80efff02db1df507fb260724238371f9da217db249b80650fc2ab, + 0x7863677bac12d9c8acb8e235fed719eca74497e0c85f1191132e72f877b4594, + 0x4622dd48eab686a6312f00bac77e56ac609832c1a3710062e2d19fa13b25059, + 0x1bfd373a0dfca60070a9cd0c5f70106366eafac34d74cad65149841c31e57659, + 0x12c3c104d455c723c30a2582a9fed0478089ecdd6256a6a14d5dd3a73e57e58b, + 0x1db62d5a9783dd6e3721980161c8e9f40b29066471ec2bb395b4de71521c9337, + 0xa1338e33d0d79c8c1143c1e94407be350de016aa190237e0fdf6aad194ec3db, + 0x230cd81310a9978fac2828de4ac38c19fe35aab2179f1e83a3127745dc709846, + 0x1d46545374f8b8117fe6aafbf40c162cfa3b13f7439191c43572ff8ca713d874, + 0x2f0bb6daff69ccbe41e11635d1a451816c1a39e3baa7359493754111c0d453d1, + 0x29329695f168370e3b3156e3ae2824a662edb778c2a23eb016d135caf72cd9d, + 0x1b9f8f4a4d8cf0878c3b5b57e82096972b7d773a197b6cd412956d9994f42393, + 0x1150ca485896d1fa88445f18deff9e46639579453dc8bd952deb10c53fc69025, + 0xeffc5e98f228858e49ca15bb98312385cd06a57a898b82a561f6fd9b5af1170, + 0x76a9c5ece422164d7689f5863a3752ad3681a28385e022c66dba35b8c87df7, + 0x1ea44dc1364ca5d1a9c217488e96b1138da5eaccfa62a3418d687da1308199a0, + 0x22390e0fb5c982881d62f7af9255b2c677559b525e70e1e993120e39cb386fd7, + 0x283880c9af3c5ee2ad175b97a9110e904ea6f1172b0abedd8726a1942bd21baf, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0xeb1b0ece2af5cde42043430b9c70ed679c2bae1000903072551ecada6dc0a6f, + 0x2da6e90774ac9bf5a07971085698cdff633c28eb52f2f57935b712c406e37066, + 0xa8125b935e8da1db2d1ad9a841efb10fab0966b438e0a6dac204ccc832ba951, + 0xd4e3b2440602bc4d019da80f29ee2ce86a44f098e32e6a47c512fa73173eb0c, + 0xca753aa57fa52ba572587eaa47c18ad91aa498048483d9a019457d014ca08e2, + 0xf9ea814187bc6dba58c6f7c1ecb3dbf62ab2ea29d075afb40fa75fafda6ccdd, + 0x1625e36facb0ba7558f4163e2f69b482cff1002b6e63a0297dd035b51126e214, + 0x1a8f5986c3af479a950f2f78c1cfb9e6eefc693568db3215ba3da8b95cf59997, + 0x2092ce2830d91cebd97e69ad4aacbf5947c8edd9e809d33aadff0a9c44c60dd2, + 0x2c34396dea567e1a3b6bbf21518b8b78bd08527d955ec8c3f71c153351975a48, + 0x27ef5d907c12b2473a024ef1ce2bf3770bb767118ab957911608ab99f5011e3d, + 0x1f290b20bef457eebf0ccce00bbc39ea19ea4c2625e54e0dccfe3db112e067d1, + 0x1db57788c30f2f18fff3908ce919ea10ac851b862b505246e81d61bdb51e0f70, + 0x2b041dbcf7846c4e72de5a0e5d201fa5306c8e797bc0c43702dee216497eba23, + 0x22a31ea557261176a10f8036c7f9aa32d7392a33e64ed90dae1fa3d9800f0077, + 0x2eced0082a7ac90051bfd190d97319e34021bd571d994f4fb633c299759876bf, + 0x171f3f295c67c80f97bb0678ad05c216e6df17c46995c7c8f801811b47f75db9, + 0x26de076f9b9cd4cd8e7f4373b3569c9c2ed867b182be695528c71e1dfc34553, + 0x18684d0ad8f841fc32151dc50ef602e4560b286339d9a299e6451d535596f41d, + 0x17baf0b6d89621ea69420282c32f94ad3a52db7394baaacc2a1ca3032656b834, + 0x19bad38eaa92c43ee1bf9289e9e66e32a2856a141ef2e36868975617765c0a13, + 0x52eda69d77234815d76a5a9b04e8f7245b9457541c4145d00fd263bcf9ac56f, + 0x2de5e640d8c2fc3acf28e99df17fd56dfb91fc1091d304773638a453037b17b2, + 0x7b075e004bfea80e69fbe1c460586a50b260289becc26cc92ea6ee18ad5c897, + 0x24ebb38197057bbdc006a2ed6d1c280e500539f98dc53f83c2b58503bafa8ca6, + 0x1ce51573e24a435d75b654a1bb80df8ec38f12bf9660d2abad366ec89770c3f8, + 0xff21e9bcae93244b09bdee7feb1841219d14b6d9e8ce6c5aa07915b5d81903d, + 0x9f7f1cb180b8111b6a3b22458cf94dcb289ef8addc4adcba913d99567bc43f, + 0x228a30bb9161835a3ca58ead6b9752d0332fd78608b1412a402fc045ef430f, + 0x15e9b1e05851c96b3bd7f09459669d852e65623f1b68f9f597ab7a0dda5e208b, + 0x196b3d652ca59d59663696ef17988ba14ada02ec506cb7e4caf2706001953bec, + 0x1c8749855c159f2b4cf83932f39f2676dc56258d3cbfde31d526b4b5ae3eeba0, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x221dd8a7d495ade1dfe6a6e119845add28d4fca1736fea74f367acb2f0c2c6b6, + 0x4b42317716dca3c5d82adef996100935cf38279042de9b6bf50b29f6a202f34, + 0x475894cb64dbaa6fa6a2ddb74816670bde6ed2bb1f535a9d5f86348369494c6, + 0x1c3946b391ed069e274939cee866a5f3d4d7dcd44bd28c59bceaa7953ba45dd, + 0x1825b793fd2ed840af6848d88c10fad3c14234a7dd3834121965a11926c5ce5e, + 0x282ec6f6215907e0cbece72ec50a5a90a2f17c3f514d85986b9983bb68f73cb7, + 0xd8f7801683a6488f5d54d9289e6cf33631007771a3580746446e05d48ebb741, + 0x1855412ba202a2a97b4bc4d141fbd547a4019f23cda4da726fd1aac4d409f48, + 0x1798f1c6901076abd77d7c40b401c93bd711d58af1b975106de72a6f6e2b250b, + 0x2edd97865d7faa4649469ad96a5e0542c35628e903e2be373a0ab7f1ca5a207d, + 0x13676cd7961ec25b87f7ab8b623d2cfad86cb66236386cce469386fd7998d956, + 0x16c0a91e9e9c2769401f26728c935e467693afac35f6476d7f45c3593496a4bc, + 0x29553d069f113822ab939a807c89614214d5866a2fc17e32d21c786ee26cd91e, + 0xcb66808581fe375cd41bb5410977379265c20dfe402d5400bc93ac24b4b03f3, + 0x243dff648c9f0c7654669b0628882c9309e5bc28587cc2b239bae21dbfaf03ee, + 0x2e171191951cef52833064fd4d4067816f2e9c892d7ec9595fcf15286fc58306, + 0x2bdb95923550209fa7cba2a746f0c2681195b0eccc5e6c253227b62c657e662, + 0x85aa13a52f4b623dd516a6a478fcd88e30c39642c22f7dfc0e4723e31fd0d5e, + 0x15f5dfb2f22e20cf08c1bf8ca7fe18ee12607615c5c3c1a7c2c9fe740bb9990b, + 0xfc58949bd8a136c38c706991c5288511da276d6fab95ef315c7ad3043f5f619, + 0x284e9569fc8ba77b4045b856dbff1c29eec71e850bed17e1533028e2d07cdd8d, + 0x5fb97885d94f32e89b37ed816cfe79118ab5f70784b3a546a50c32c52c5d7ca, + 0x1588f5edd5db73e9e42e1038f3e6817fecff001a704d18fbe96ed57022d6853b, + 0x16814981024fdcea5abca513e5674e7ef7573813b650daaebf34430a930d06ec, + 0x1b0b7c044e5a9cc60631dfadd62bf75f7976460d0a1ddd54c91f5ac00461ba9b, + 0x17d68098ed44b6a6c42a6e7e6f9fe2da0ac7059d1ecf0b26eae01afa117931be, + 0x6a32a1b358cb5288830b273671306d6e1af65718c3b4ef1a3c2c6ddf0ebf48, + 0x124899206ef866ee3d3253024894741166f53f48ef7f86c2955184d993cb6d98, + 0x282d1b8005e7c5e21adf146bbc3a80a41207d1ff7ee7b3bd2c3e6bdd5bf3121c, + 0x2ba860b0e392214dbee6ff237989665c30944617abb4b31d64b2ad85f397e33c, + 0x8dee425c9230a537b33445ffd0f032a8cd335bb0a6c95591e1bc641cfb5dac3, + 0x13e1f729e82032ae05a37e3eccdf95591b61a016f5cdfde65b9d61c84e0f0a09, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x234c770889eec5a24bc88f5a31d56e761f7487199276c8a6eee5b1a68997812a, + 0x245bfff7477831205a76d0aa1e9c55d24bc04143b3bf5dec9010569f945991a0, + 0x8f4069c0b10875a6c5a474a6632faa9ca5a971d207ed0895fb92f8ab363771f, + 0x837729d4fc85301d6b047a6dc71d2ed7ba33ee5e25cef22aeeca59f015ea9dc, + 0x294ef20f328ae6852d7f878918cfdce9ed950be58925d997ac533c91d5b6afd5, + 0x1f62b4ba6e7650e883f9c53c12adb7ac418d3d48a7514f183218c8d8c9f2e881, + 0x88e62ee0805a12f7512c58ebbbe7925c8d94d13ccae933af8ce5ad1d9c11fc9, + 0x2a15acb799a36536698c1471b93d206320f2721c13a32df2d30f40fb9b1fcf4d, + 0x2255ef233b2e051eb8fe5fbb4f03d5d0450ab225f926cc2ddf4e0f0d9de599f5, + 0xb3324f75f50fba89249228c37f2c9a3263a1ba03c624ff6b41d1c0eea4f6f7a, + 0x267abb876cf130e5ec0e545b41cb614e6b0dfb5eb2b668ca6ade5220de6d269e, + 0x19040678722dac94cc568ff3c0b9edd72deeb3cfce3f3d9fc81af7d49554afdf, + 0x9015509267d3d74355f8b8cb583ec4d4c41b01774fbb745ca58b2ee3cfed608, + 0x25792587eee7e693a2dfb7ed5fd429f501a3eeb917e6c17614fd3cd80b7356fe, + 0x2588230455c1640eef883b2650dea4b74fa7c0b2675869b3680a867f3f9983fe, + 0xa5d8e426e8a8633cb0dafabd4f32d946ee6b1c9d80e0172d2a9952e0f85ec56, + 0x2f47894426cb6983d71c100a0326090c8ec978454b359a02d618adb71fad8282, + 0x23bda45e45e20fb6c274f9a99c7083fa4ec596ec283a78d1b3682bc44c532383, + 0x6428e25941cf84268604cac47b8986bf3068257d3be89c3d6dac8f57093a650, + 0x199d93b935756b0e6f1ea60c72667b0e5686eb1b12d6cd88dad5f5d44d9bf6fa, + 0x171ce4623f0a49ff1f0b33205fbda2909f9c189b275cd7a717f4a38a5abda910, + 0xe6db378ce7e1de03348d3f7b7b17264be5adf0995de8e0273c39aad38229a, + 0x17b2b86cd66a73a60e46511acd7dec0fb3a32d6cb8bfaefcf4479b7d358fce81, + 0xd2ce771ec4979abb30c8a281fbfbe701aae7112066a813393de44e56161207d, + 0x86998aa35a19fb86ad35a9116c272887a26c95743d8214f1f2a1fc75050f867, + 0x5be1134da0692b8f92545cb326deb862136255794fa8383e1d3f266f3162243, + 0x1bcb6b8de9f866a39768466d15f521cf1e75e1e9ddbc30c05a45b53acb5f58e9, + 0x1b9e926867ec402e4fb4bfd240a82f240eda7df61c9b5ea3af1984f74089a93b, + 0xf408ecd2413f30c5794e777b8a0bde7dd69ee0e24a918253e9cefbc7d98913, + 0x2d7f052ebbb9bf5270016f796759f98056b8928efc35c09fe9e1aa26f18010e7, + 0x2da951984f4f03171413e1739831201e7346a45bbe9af89d3b23ffa2d615a952, + 0xb557ec46a7bfb8a0bc21bcaa56edb6e1c0be152d88b57fb5750cda2851c6231, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x13d3fef3eaff9b9563a1827637ad00789268d2b55a1fb6681f8b052d049a3fb3, + 0x2bc1cc959099f62eda527d7385cead603b637a28c9a223e817c9848fd78f4754, + 0xdaac8774332e509986178344e8caf8a91c6d01a275b9a1df469e5b735bd5082, + 0x27773f22500cdf92fec80f154847189a3f75f85e8cde35ce9171225d3cd8b676, + 0x79c499e130ed874a1383b978dd3c00fd5b6d0c18bf3b491cfd63787230cb9f, + 0x1ebfdb369fc74d1469c6e461f64206e4907b6f5b51b02496368aef1c54198cb7, + 0xca9e23d1f4071112543d4e8c1b303865a4064ed4e4110eea113130292d1e299, + 0x2357dfbdcbc869ea8068bb2ce056854f7a0a765a217af4a0a317888b08ae0af9, + 0x2c9e7d1ad79c49b37dfd93ff2d4aa43c8532fcc606927e975b21564a9c1070f2, + 0x837ff288c0aa9cfb3fa7cd38312ca6b83b9b2a3ff4dec506aca1af1176a4248, + 0x23d8de04d32b88a1b5102863416318011b412b11f1e609386c5d8d87da878e54, + 0xe2564431ced9aaddde433e7cacee42a04d09d3026f3ca1dd0ee3fb3085adbd9, + 0x61caeaaba163fef7965cb665f0cf305deeef1642cb63e122d845c5f6b095be1, + 0x23356942ef4d25d2b3542f5dcb54a77cf17d8fa64ba060462a3b71cb3b73d50e, + 0x1866373902a9a953c0768646f37941c805658c31f761dd39e6b4d292c8cbcd, + 0x86bb5bb78cb1149afeb670e1ef3470c5634f10b18eaa25450e87c5a9bf35146, + 0x2451e0f1a7bade779aaf54dd8a628b92d9cc8a7b7c0074076f860f87be2f8fba, + 0x84bf3740a546012b610a5bc78ae897973b85c2be04afb32fae0e39d0c085255, + 0xdef7e0528ea820d70cc9fab7935d6cb5b3f47fc8b5aba924bb237b7077f0275, + 0x1b7af60a579f6d6f9625a8b0f7c4fdb2a6af598daf08501f155665ab376f7ec6, + 0x4f92ee3832d8c4253278f77e9ed900be186f8c182a39662f59e4700213c98dc, + 0x147b948eeb385d71922becc54ba12130ff5643e49f71b7327c323ff0e2571c95, + 0x367fa68c919ef8c6a24c79f6bba07e7e839c9512b92a690d1a646bce08388ba, + 0xaadb8ffaf6b02a6a4f42e97afacf2b4d49b5d4201becf3a013dfabfa068b5a0, + 0x1f29fbe41d336788cf666a4378b1c82d5819c08e27115762277637235b9084ad, + 0x94397da30fa8ee480cc4cbc0cb3383218cef9602ccd1eb4655071c7bdcf3001, + 0x16a091b9a5cd952667b2f11309cc4e39f2c6c3ac2eb43465d99b409ab07711fb, + 0x1625cf4e2fbb6f7a25536a24bfe679c793e3bc01574d8af123d61d6b98ddb0cf, + 0x17f1ddf6108819ad72aa91411e08264c5a0756eef3101351abd131e8332e8276, + 0x272ac6af8670ef04eac5d621949f3c4ec7edbb65a38c4bd7d5ff440cab1f7a15, + 0x2ac81ebdf838c893a74deb1a575c929da0a6e12d2e6e1b0729bf0457cd7e134d, + 0x28198a6a7de09abe545ed428f83f9ca95a7bc9f91186305adc80d9a561045ddf, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x21c8f5212e43a884a0729986fc11af75bb7d2cecdf007a7175d000aad1c89e21, + 0x12e4a961e1801660228bb592204fc98865260be10e1e0288460f42b527c486d8, + 0x9ac00881ffcb7ff45a4f4530d1bf63af3de4c3eb7e8982f354d119d099b20c2, + 0x22b92591debead5bf556dfd040688701939a2dc72264c1b74c0e7b89b4557670, + 0x2388a2dfce036d5c898a465ab3c88fbde3fcdf8810c87e639f7abebec9decf80, + 0x9e2df6b54d923dd12bc44406c247281240924567a7a993e41a6eb027e959601, + 0xb05fccc0674af8deeab7d73646e2a28df0f4d76803a8b6fe7a2a5f9f444037e, + 0x148c72c32e02a21dbd3c4859046062f7a0a3a0a9c5425a5291beac5f3f54361d, + 0xcc72447af3608c9090af67a3a683e8d989688f2239bce43734d5808de3c048b, + 0xd923c01448dd3098d10140067ab3f5eaedb0a5b73fd6f29f28cb1f33a1615f7, + 0x9145690a8426952481e9c5f53c587aad25faba2f2af7a38d464c6c86e889c80, + 0xca36fff3a1b4bed7f8769fd50195c1ccff723fb1bec0db30767e922ed5c5bba, + 0x151f1a9546c4380ac89496bdc078ab54ec09e1ce303bcf99f5f7237cc7b150e9, + 0x16c046d8404c441eb03e5c0846fb9582414123eaf996781ee0b7268eb4b20682, + 0x251c3f386e8e92cd6ecbaf2cc2ad9d910f94135d41466698610f072e718ca410, + 0x1475e6349fbe26512b79202c02555f0fc6b0df8c74f12a1cf459fabdf4ec982c, + 0x2b4c00677708322d7af2ed6b2aec44c4926456b2d3829b3517f4064933e85bca, + 0x8c06b592eaeb2fad227fddcd082cbc40359d7ac8e01bf16f8c907e64c170ca5, + 0x211e364e0eeca2dcde7b7e5e45e21931fec7898963f20579ee0acc0711d66052, + 0xcd7ab2a448e03f55844c4bfb6b169790a0c8d70638d7ddc4b5e72375970a738, + 0x1930ac2e4e2ab703874dae8d6d84cb6de266b11470aceb681dc619889e61e454, + 0x1efe3fc036da6b22a66529ea8f04651ba88c4a88512711a32f4dcba84952bdff, + 0x1fc575f7be1400b0d7f57217a0993649494f6fd4dc81af8ff4f469ee25f4d3ca, + 0xf599eeafe4afe752ab67bc943a63bbd559b10d6d7340b19c5a48feacebedb2e, + 0x13161ff12c338e5fea3eab7086ea1b5c9e074e8c4343f5978dcaa9fe77d23bfb, + 0x19e8ce8bccf4d36548905830ccc2f9f13c6e0d997fb57c89415dccef20298d94, + 0xbad7770ce2057b3cc20f21c93a69b44be7b95403e6d4ccd373d8d855f42d48e, + 0xd68c25929eb71425958c7bb308245d86a52c4dd57af1f03ec17d73bd14a7b15, + 0x1a20f6c97cd59c0339e095236fb2955b50356fa59244f6173f1caf18deac4c08, + 0x13fbd61eec52c83d2dfc6b62cb1d1cb40e71c63fce17265ae9d631de6d683f17, + 0xc5c24fe6a6fce7831b9c8b2dbc30bd9dc8352c78d4431f5afec5d94a18f2522, + 0xe6f63bed21f2cb9b2886da97bb0d8f0e155f008c1e5039c2ed7080d6be70431, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x13b9e4a669c3fabe0c43f333992a5f698e08a9abbaad77cd400b2912f5ef7e8, + 0x2b0cbb582146576933f01c91c0dd2b095a2da43cf528f2273131788f1a6987cb, + 0x2e30fb85d199dca95475521b50700b699c50f1d7aae5b2de4e9b990780ce29d6, + 0x4ff7ca87e268b4a23af154c1102c8b705ec4682f08ace1273fabb3a865cafc6, + 0x23b371ac3c5e45d6d930df789f60ad510b784afe9ee4e82876081ec0ca7ef7e5, + 0x28c5fc831601998b96cccab01c028d613c200eff1d0e2caa7098eea165c119a0, + 0x1a649a762e15c9e33b6dd3a4c5daaed08ac2e5a7845df289d2c7ddfdc3771f97, + 0x1b76809608b2ca5793d346c52426aaf7228b7e4a09083c2b551bce8fc3022a0d, + 0x249de6f6cd65afa7bf206ac6a1fc864898a5135d0b0efaad0f4c86774a153d9d, + 0x162c8b3b5f7256af0a7bd83ba37d258ad7d4ab4f29d248bdd00ad36e612f6055, + 0x3a8b1979dfb950c0451ebba4e9137d78943d9eaf889becd291a669031680d1f, + 0x1fb9ae665dc60fd17dd0b4284b2eeab0845e6d4a5d6fb81b77e9f7c6b43d170a, + 0xe61edb12a4174e48a7b47b660e8175f42aa7926ff438c90692e43bc396bc6fd, + 0x2a21ad8241436a75ee8a90867aade180589a8c9c63b05253be876f192641b1fa, + 0x166620895a93525094f8bece65ae6fb9e14951d4bf7cf10a2169ce5cbd8b4cb8, + 0x22f7441fb0e816935c8813854ed5fd6ccce5e7b6a85d91d2b5a3a7a5c8a4ccf0, + 0x2523733ae5275aa5fb89c74de7ec80091727f495e729ea9bc557516b25e2cdfb, + 0x150f2ac4f573f5f9eda0d8e65fe866581f1bc11e46acd399cea41dc1ee3b4082, + 0x2e2c6a081127c11a80d60de162c1d5bd70c9e1b1312fd31f974d419d74e72a45, + 0x288f5e4a35d6a88e411113e8324d2af60b07aabb48650d27261f9e0172c063f9, + 0x1e94c48d6ccec07a6aec467ce9db1c7cf2f48f20406483bb873f696cb6139c7c, + 0x2317555099ef118ac1a6703493335db895aeab6cb1d7cb1e46caaa0e9d74ecf1, + 0x112b653324919b4300a6e9caa08f3a36c372d86bfdd4bcf10526ef3c2e8c8665, + 0x10d64d9dbfee84b7d8e426404f4f6302cd2f507c9536559f0050b2b77a15b85e, + 0xce3409a692acee5372266c97c47c2564d3268f5124fd3094ffb35d252efcd1d, + 0x1976232c6b5bc6ff77e7c6d266ea390c5fbd4fb3cad9ece623ced56ac860996a, + 0x85fe99053d3f947a665495f68291ade2c706600e56dae991b62833e75d21c5f, + 0x253875f4394f5962fe07f784c7fcae1df6d36d1840eaeb0e7c236e3d6786effa, + 0x811ef3bdcd3c837aa541d0df32d447ec54391911911e3e0739b7ffd4aeffcdc, + 0xbee1c554f9fc98cfc6b2f986fdf207859d78e2757d199e9a92b1501ef92ca06, + 0x2e46dc3b30b54925c313731501c5f003aa8d1490b16cfe28bbda33fcd0b9b0a8, + 0x29a557272646a8b096b2d1e8aec172491852af8f055779779043e048ed8edc6b, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x2cf567daf1e32b7e212860583eaa1783d871a1aacc61b1e17274d29d43c3d42b, + 0xde4e81211f6698cf1b5513963530b7b9d0b8ecc11435e75e1f8d3743dbedb1c, + 0x2441c69e3451809da5aea5422d4e21637469b4384372f06c5d6d9c14c6680981, + 0x2aeab770ed2acb63ce4026c9fb0bdea02bcd6d0e45b1c89854c2c827f09f8743, + 0x18086bea417322d173d3b67f0bbea727011d58a1307664d208687d50018c0849, + 0x1a5554a104ff43a6e64b7db4766e1ce6df735dd7d5d15bc04b224a81453b5a60, + 0x2372bbb558acc8f0a26eddb623338755aea1b2793d7e1130190fe2c6ec6393a2, + 0x10c33d11fbe22b97736174eaae79eba40bccf31bc846d8d0a8b44470c2af8cb1, + 0x3426163d8365dc4847d5bbf779c5577352e34ff6badab833597ddee1bae3f54, + 0x1c63281e368936ba2046f4c7f0b4279dbfc02ae7af0224d4bb03d847e157773e, + 0x2192bccee71b6b955f146efcc1a1781c1e1c5ce24dd9a55d2658f054614751ee, + 0x465383b8ca4136095399e23c44aa9fb454a47ce6590eaaae8517b97e476c396, + 0x57e4c25881806bd449481ec352088627fba202db4cd4b93dbd1409efcc8036c, + 0x9075ad76e6eb195188a775ab16ab65a001ac6eed2fb1455282cbfed80a0594, + 0xbe868e7bfdfa88434281a12e1753cd13b44df13b9e4f31ade7108de24a409e9, + 0x2e510e83757137479bf6a77478344c10bb07faba1f97da9c0537da9be515c5e3, + 0xda0ea6a6106068ef55cda415d30f30ac0e30877e2e03abf618ea2d79d980820, + 0x2452c916a252ad3c7c27a5257f4c8328d9027d66534d98ccc9a43421d70d83b2, + 0xf9c77bb51cac4d5ae3a97243b5b967a65f647598197721b487afdf40a7f68f7, + 0x1f9e045050fa171e0ee29df6cd436b6bf42a576b4ff50c2c913aeebc084f9115, + 0x2e7d45b66ed46a7205c8af1b5343d1d3fe32f2270741c450069783a4c5be0dd3, + 0x2516935ea1d2480e4350f961e778d72f56e02b57a98e892b0bad80ff8eebd7a6, + 0x105de12e7429ec594b85708128893f8ff201f6fa6b6e58a2f85403e04b3e3852, + 0x1fc9f7ca915a6cb6b67ef53d985021ec23469970c5eaf180b0deb0dece3bebad, + 0x2811b669db5b1a371c847093244ca2f8d653537d382f16c072df917cd59cddd2, + 0x117cbfbcfdcd7181ea2b182bdc6a43f72a78bc9a6b1c27d5a4d4f073b525f86b, + 0x1e8a05c84e5252cb9f3f4c81da5c5419ced59382540f32cf949b442f67512f78, + 0x24337a6b1cba32ffe53d724439c4554a2430c42da902997c096c26e7a3e88c8, + 0x2f90aa6e654fcb74227af9060991e0a68d47d8021f7968d384404b9d4476724f, + 0xb181fc79032f8437c5bf21425b264aa28adc4e92ab14a1e57964c79f150215b, + 0x99da6058ed7f95fe4cc85f3bd708620f371c9b32c18e235c44b415f4c12bf30, + 0x9212f04d8281e62b36d022532df405b8e5dbd81c15f00dd094130d43009b4cf, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x1107d939e735721d6dbf79d5f3060247a39316ea524ab8c0ec617b2ec201a26b, + 0x2f1c347523299d959fc1590f33534fc2a0e5adfc5de0fce0fa0eddaf5564cb21, + 0x149ef73788c5149f643a0d35623cfa246b6b83f3883475060ee613f74aec616d, + 0x2a8fd18e8e3ded0ad1e39b5e159e9b1298bda05646ac66dddb50e64280889670, + 0x47dbcd211f6c7ca6e60ad171965e1dd49d07b055b8468d33eb7c162b3627565, + 0x23ca2270b14221c76b77a1f919764a9399db0dec3db5bd28feb2d363e45de608, + 0xae18b193b1142e262a16d0d122154e48849d5cd821b8852a2cc2a2e7401e996, + 0x1857d1b6def0af45ef7d3d24dc7529d2826ffb00bc7c7c7aae74c740caba3caf, + 0xf3cc84626c45ab94e0b872c3779dfe3f41597c39094884678de39d8c1961891, + 0xe820957878be6285a630109dd71d5ab98ecf1c1e341c7f05be144a6808961e9, + 0x1dddf5d71605db9aab02d71866bcaa3f304707010eb12963e30f54270684f686, + 0x22cb55eb86c682ccce666ec7fdd5167af98a04c5731477cee41401f70bf05c89, + 0x2285685b32e30facba36b7813a94ae1486502f7c550c49b865cec83f46c2918b, + 0x89eb80349c3dcb0f5b5624debfba7da90f041de9bbcb5f0dd5e915c92377197, + 0x1ae6a640e952299c2aed2ffdfeeab32732e9c5e2dc95314d217f0642816be3a7, + 0x2ee58c48db87e8787a65b7adda68a844aa2dce2ebb95b85a0372219d5469934d, + 0x18e425f1816a3fd2371717b0210df14a186a184c14811245b0d2fb38e34da7f8, + 0x2d0b4c00ef039859dca8f5ec2242dee07eb08b40c134813ddd20f1e49cb46003, + 0x1bbf1b9e8426a43da69f0b718a93348b33ab7bfb49f32792d0b40a1df5791f2a, + 0x2bca73de43111cc97e7c860ff86c75c29b66c5cafd04f36a0673d0be35fbb343, + 0x1a77d34364e2186eda96a4c0576a632ca53a8579ea24ba17291eb71dc932e5e5, + 0x12757dbdd1ec1b481648041f49b600350ed839580fe4c022810e1f9ecae80b12, + 0x2491a75bb6c3231b90483b0f37596f07926a746aa6884f087f1b7694d191b51d, + 0x998ab89c76bd9f620abd41cff82b3d34203f4e6af0ee0f32e7f72f88e4209ce, + 0x2271c33914091a7b0760c2752a12ff2fccd4f512175ffdd949bdefe9b5444486, + 0x2b76d998c8fb9fd7a192e5bf3ad5948439cc061182456f9ecb60fcec97d69ef1, + 0xba089d24faa83dd9d34426596f4305119c2baac05c4f727363cc07dc37ce00e, + 0x168be56f3c38107ab39578355ad8f49ac0a80661977c3a758c29a08a3a7733ae, + 0x2cdd0f5feb4447b5120e670adba86c12d71e5f9860ec4b3eae28524825ca6e3a, + 0x36af5faba2b1777abb199b35334d12a4a01a92485d53fd6e9211949c43309b7, + 0x2c1dcb685cc47c1dbe9db43d809ed56ed6f5f9ac92d76bfb271c10b66b62fc77, + 0x24633d05c06303617624fc379b46a788b0d69bde4057dfc36eb3359055118bff, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x2224f3583f007840f77ac63371ade2a22805ffb999a54fd0feabba444ccebe18, + 0x26714311d757b433c90cbbef69da79f27493dd48c26aa00892a69f49412d71e1, + 0x2fcc716f7f57adc4e9cf765fa7d0d6f85b2e71b7d495d12d41657da92d50b402, + 0x294a3f5ca5239bb5a7b165470474ab58b5a07e2b3da2b4543d2cff4e1f0a1624, + 0x14b4beb63d909345cfc2891d52be18275fd436dfe64def3ee9a056da6df31674, + 0x84460af87c46a4276cfd2a1ceafadc83ae5e917669e8393ece9d52102d44ca0, + 0x141bc6edfd3d6ab0d76ccd6452f746e1e2a04d7dbea197c2ca2a6d498585de6c, + 0x1e757acda92690643a370b9c69cfeac5f2cbddc70fe984afafa7d8eb1519846f, + 0x9e92da83e2a6b8bae2a65c80e94f8ad0dd5aadd9374f9b666e5292b1c43edc7, + 0x28b539f7cf1b63612fe0e3f019dd8055760540cd2a998b70bdf5c755554a61ed, + 0x4f1315a1e31ab3f8eed8312a43dbd1b4b72362ccd637ed4dfebad3d350f2467, + 0x106aa158cdedbb22ce5caa3df644bde2d9763b32012a5fb391dfa3a761e2e33, + 0x205bcd60e27251d356cee0c9fbfe5cec10606aadcddf7dee7b6d50429248cf29, + 0x1fa4539519ef1cc1bc573c8af5bab6df0ef869778770109f8de349b606bbca41, + 0x17cab2199c1a13dd4608a9e1e4b3bc4965622d8b574ca6533a252aec9395ab05, + 0x2c34d65810a7e5a4b851f02a66ac4d1ad54ead2ab633ffdd88c95dd364b16420, + 0x128745a9a55f406ff9327e97690ef8137648a8ac585b1d483e87be00fb1e8866, + 0xd797eb05630c87b72ac57dabfd5e897f0679bcf0798652a327bb6a02bfcebce, + 0x2d49ac3f9e3ac8b8c0b37442e804c4487249047cd6a6ba32282c55ee72b9f4bd, + 0x2447bb4feec91d4b048bffde8de39dfdf87c8a9a3623cb563ff9d6203c6da1d1, + 0x790cd64d983c721f883cbb6f4aa15ea76aaa19dc39b1f44c4dba993bc9010cf, + 0x163a3b62e1a26e8604fab78ff1be0a3699a6b08d329feea137062fdac214b0b1, + 0x64d9003fc12c06923f798fbc0f49b33a6250e352180eedd7fd846b7f9593dd7, + 0x1f0d94af29f162d084ad70c2b138a6532db8d967573418a3ee82cb31cc8daa26, + 0xc30c7df8956774687f81e3881acce5c551fa89eaa5ff7369d2c9b68cf97a283, + 0x1814723bc7c2396b80b93f41ae3773543a232b0fcc80d78f92d48c908cecc77a, + 0x1efd30a08cf062ea109229b3bc2dfce564232dc6b181030d2c03ee486bca6d35, + 0x14e923cc919ce767c8d0c308031f1546740d512c6805a48b81ce2bd7e95cd9d5, + 0x21d74be8e343e93f759588cd7d29cd64a3afa4ebb48e1204a3d573ad1d56f4da, + 0x1b8e0086de4de522d5c81eb0a996955ea7004aa6e90d3dc9f37b3bf834b08430, + 0x17e5a80ec135e0c932f063972d785d9f89eb45ffe44dda9a8ffc11468081645, + 0x1a5caf74532f2c590fee8503a13bb0ee8e931b6cb92e8f1e52c337f3c7e188f5, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x1ac42d7b0a6e8b8f0a097d11d8651798aa5f2676574418f23b7fe6168f28257b, + 0x1ec67557d1bf0e6f851c89835c29d2334967383b9677c71e10f12ceda3593e41, + 0x2f47ab58a58e52340df845a782d6ce983366fa669f4d9373f849c0e3cfbca272, + 0x8f212a5650c4b2f68a8b7a14789198ad2c224facc562e07360904f0adb8efd3, + 0x2592c7276c9fb4e962b8f7f5bbb95018d17303a6e8a5b513b2f3ef87b66d5135, + 0x28eee34c1029e6eea0cc12e202dc1f4b50e73865acd6a7b69302a1b45f2c1907, + 0x11bd9407f0c9e1b9ebe379342b2a426ea14d87335522e8aaa880236f5129fd0, + 0x169f293f396fd012d20b323f9b3eb45362e5d272d2342696ddf1e3efed03c069, + 0x1e1f46890d389a50ac16e5422f79d449a6011c5be9e53c266285afcc7f5b2608, + 0x128da78e60b0758189982ebda43acd77c51eb6455d720455955ff631a922633a, + 0x1069251fcb9d2fdff50a041154e6ccc7579a360ceab1c360d20404630de5565, + 0x1ed383a4d6c433c6801b6853b5c40f67cc4fef27c2610aac9540d5355c6cdb88, + 0x6e9b3357bd837d1a5b8c7598412c78216daa02bbb25970182e089872cea4e1d, + 0x2fb62dd173e44023b3e784ae457bfc93adde1e08e98f3631c6e01bc6343c5bc, + 0x204797d9b16d45b093bb34c6ef5e27304af9ac7ca7c4a252134d3b61b6954b4d, + 0x2fa8b35e4e9405e7ef4f2d80820396ca8f026f3e330775368850d423394b2301, + 0x10c38e859ea854e2c6bbfe3acd613ed59d70053772c6fd7497ed2d4d99b2907e, + 0x1f44270853132e2b71724021bfd741e39c3414e8c63f7b148371a921355b5085, + 0x2eb4d6a5f16de3e5b2c2c33801421c2dee87a222374f4cb2c2fca1fee4fb1ce8, + 0x71e2443b4b9018d2a7ca057b35e2050e59409c688fdca9289c96444378486ac, + 0x1423a5126a2789082bcfc21a6901111b6b5299c4f76d341c8b0c2e9dc4712726, + 0x26e1e7b62d89a75f94630821b5385e6c48a97b8c5c5ae1b3b1f114444e8a10b8, + 0x14fd3ede10aa7bb382991a1128340eb1e6ce0a8d573f643bd8add5a2d8e8a45b, + 0x2aaa9048ecdf21e06da241868551cf548f683880615368a6a2cf87554d893b11, + 0x2e083ac42fa88939d480a976e73c6773d26c4583074073d6c2a9f90071bc830d, + 0x12cc2a0dc5c021316bc97e26a35a9f5b062087b78224526541f528acbde2d1c4, + 0x22adb7b0e9d4c335e55c7aff8bca2048a59c0101099e8ab99b79e64be46ecc7e, + 0x158cbe94e139620090b700f9fdef637d70081aafdf1aff2eddbb5e2f6bc02dd8, + 0xcb42f4bca1dca294e7e897d0a0b9e6cc72531cbc872789265fa904aac00252b, + 0x63156236d87d3673e07b739e18d79a22a6f1c99c2a4c3de4b982b5765c4de49, + 0xb7f0818b640763c1268912be50230493391a86d9de957810fb2d1548397a088, + 0x2aaeda58e831430d69a57059f933fa5deb7fd04fbedbb016a919bf5f4d8857c5, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x1d3a013444e777bc4e816c6f9194646b6009d5ed09931bd8011f5d3bbb01378e, + 0x18e4924f258930420b1fc45cfaa31fae7ebed37f375a17f1b8ec6e97675403f1, + 0x27c63021eb05577b17d50676669a6d590535b6114f74d6c14abb3efd3589781b, + 0x159d12a40b8694d9dcda1149dc98bc3228eedeb19040682a2c5254723a60bc61, + 0x1c04115e802bd71622e1b1425496f939414737bca8dcba1f070d8a44f6da2d21, + 0x4d0a06d0ce3dc2ac28ee5f7774898d7910714459b385b5874ac46dde92d79d6, + 0x30128d834fa6bd28116aa6cc19453b6f731a0970df12416c8c4e7830ef3f6f37, + 0x1ab7eaaaf3e533054595ab5a16d37af4b028bb6612017235432179802e34ae67, + 0x2a30c413b8cd102148977b0fd1f51d4cdd2684995eb899156438afb7bb4fdf9b, + 0x1eb6795f1e63f8933ed48dce55d257dbf972298f9186c56d0880ae76fe562730, + 0x21d1ef33916e6a7ebe055233c5e38e388ef6e2bfbac5530ec587719182cc0b40, + 0x9e2af7ab3d9206c3f54ded28a08f8b78396cba9de3d7696964d2529a0517c59, + 0x24564fb0247a0a53e81946f9f0365c5d45257ecef288d6d67d0bdc91055a80d6, + 0x1b9ded9f11fe5b6dd79066bd0e16b9253935e8d0bc2bfc130db23a8215d0de13, + 0x192711d3f80d452839ecbfff6dae32c92bde74d051a75bc14170bc690e69f9c2, + 0x1b3af1fa25c32da1a5467fef1dffb9cca1b7b92c4d50e3f7ad0548ff2c4da1c5, + 0x22bcbbbe6b9a39e310a03a9bf0e491451698d4d874aa192b828c1a4fcb86f3bb, + 0x3a947c69e09d64be68d7bf2316f4cdc647c912a6bc4a936232cb2b6d320af52, + 0x2d21f4596d98ac3b62dd919550859a7592e504009d268bb7f5bea0f38d4aaa46, + 0x2b2708b2cafc826207f80189733e6c53d6ec1ebb3c54656689c10a8526967bb2, + 0x13e69bc7a5decd620276116f40f9743e487cc219df1dc1d769b1aab8eb74316a, + 0x118aaa8f364cff4865df9535488935c34afa1943b1e28aa08d440a7a7d72d80a, + 0x11ad3bfa094695c23a74b1f23d9cf7808e7916b9f0eba90ec571e06e4f310106, + 0x2f4b6c06d0b996fac689e922707ad815b411539f857871cd1a6b9aa34386f108, + 0xa6288360ee10c1b02a2a6a6d34052b13ce79fa1ca91f8ddbed485dba92eeb9, + 0x25ddb8ea60be41e7e99c97b6b5a7822f071027932936673c02900ebddddaa88f, + 0x24c8c87f88b21ea24ac03cf1a498d64157a8bfe27ee0df70187f6d11eb856d2c, + 0x2f958a89827eb535aab871af8f3e1fda9e0b6dd0541d7c9830321202d467410a, + 0x2d2b3221d9d7539c627315e2422ae26dab5ae103cd8a8bd19d895ce97e19f866, + 0x13bddf23791d0989c17fd99bd435437bd8bcf676c689ca0595a0d04afd9c2603, + 0x2c15a1ae35281bd2fe7a611523dd767be99c5a32a8501ca19b1a8940e1062826, + 0xcec5e18e50beb5ab2c7f5c9eada9fe3f3e8689b0901afac80992dda3bbf8803, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x1d23ff4f22dbb142a5d4465aee8fcd2fbdd8e450d1cf6f29182445d4496a2e5e, + 0x172ee58685e83a795c76191742ce9df18765ec6f1e9d1233bf73ee4fbc53276d, + 0x352cf61f75587d4a82226e28ed9a38863d7e3fe6647117cd28c736cb2893b5a, + 0x1e571b53f1260a7fd4ed79e03d32e23b2627804ea5c038618a239b2873961fdd, + 0x150d7efd3ec4cb7eaa6703bb78913527c77b07e38c93a800841a123ebf3edebc, + 0x13cdaeb00438b5c6a40c0d8a039a8117269e15f580b8044214e5638f2e87a37b, + 0x9d76e8da13f87545b74c5f505af00e204eb2414a186b54e6dc3b7b8c24e27f0, + 0xb6ec96b7f761247ebbc27f64fb4275f1128472e7ed11e8a712a206cb9e16477, + 0x1e066da048cf035bcc17fbc4fae18348f4bb1140d9519f1bce81144da499a536, + 0x426afeba63d285758165a95db5df2aa86932ba9f50314c5f7ca4408bc3eaa86, + 0x2ce68ba3f40fa50262f137219ffa5e343650976b2d5d2d1e80b687e40e426d1a, + 0x1e1dbc3eccd20a0a96846877182b08ebdba8bcb16492fcdb60acaa42317ef8eb, + 0x282ae2fa425f91419dcdedfbe6800a0122a5211345524b9c320cf776a201b467, + 0x14bde086cfb19372690c53b0e04ad0ecaa78a8babbe21de8a47a796ae9730e5, + 0x114e76d2755ba6fbf01851955b051cb5e7d677db3fda594d6658ad4fc099236, + 0x2796ec5da2337effa6fc65cb8536ea82b5e60b14f10b005b07308b52d3011d2e, + 0x252c6e37471afd938b2c840b2818ed18eb7900adbe9209e038939f883a236f21, + 0x2b6e07212cf2e4304a307acfd16edc984c170d96e7953460d1cacd3e84dc9e75, + 0x2adaa99cc0a5150cfdd4e17ff6390c973f2491d4e2723918d35ac55b5deefb49, + 0x17759cb89386f9365fa875620b6f6e7cb6b5cee2d77f0b7355d9c33ba0e6a460, + 0x111bb071c2ca17121de11f36ba7cf79f699960dd76e09295610a136afd200e61, + 0xf394cb8fbdaabd31e43d4baeb5523945e29df4f720d026fe115bd1693a88818, + 0x241d58e1cf3ed5d94bdaf9f0c463fb645b65fa19c52c193ad67f1d38fcb343fc, + 0x16713a7b5d8cf3ed4c25d780a7968a80f70c566e6ba208859e6cd69801995242, + 0x19909ba7fd3b8fcb03b6f810f246f384563ebc5896fd61496737f65b5362dd02, + 0x2a9dfd2dd3048b0347dd42aef6561a277adf3d86fe83203df1778536e6c24aca, + 0x18532ee14e86e608555da020892086f155c685561272111e7f4b6c91781864d0, + 0x2509cd9ebd96c0d7cd88a3bab280b42068691da92e03f6de5930ae67ffe04f51, + 0x11c0877290f334877a26326ce2e6ca7a96dd732288d273efcabbc0294e2daf09, + 0x26009dbe4fefea6739e28a0a6fb1dffb35d8516e06914862db8738bbbafbfd1b, + 0xe9f75fd533fa509a499945055cfdd603dd9930a50634e41a935098d571012a8, + 0x1f3592557428f40b9e6582536aed2b7264c9166093b76df3ed68ff033c7ff93a, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x1befd6dac2acbea83cbc882c661e80b50b85af2021c7ce770cbd4e4cd48f69c, + 0x2ddb55369f02ada084136f4092258eff0be8e170cca9eeb6e2b65311edacdf9f, + 0x12dd67091b9f1d7101cb2cef74fd216fbf49d4cf33548e6d8310446e562cb7a9, + 0x1e824766a37cb1d1c7e75e3f9c261f4aefaaf65080f870e972b14132e7aa6cd7, + 0x4af8f03823d37cedd40c1791ac745b768c735234f5756d638b200e1c134bb1d, + 0x1b65a271d787e78382a9ee5a1715c9aa23e3570e92dacd75004aed46b5e4f778, + 0x1b239d4ebb80ce098356e864632edbe6affc3e5a34d92fb9518ab89f16ca4f22, + 0xa9f23337f4d86a82c5dd9a9216cc182a5a6b6eb6fc5e42797df022e276846ca, + 0x86e0f2ecc21e30809e1f2697cd036bbd6241d68668b26efcba5a63bfaf84037, + 0x29bdb60350b498b5e1ff14f7360deee6aa03cca4dee1a94c4181a28f0fd2a9f7, + 0x2ed66c1da1c54cb685c48a32d650d24c17162a3c758eb19aeb9779fd35ce5499, + 0x23731d564560385b611877a371f26ef53a64244728a8e8c5fb7af1d793e0c7c6, + 0x5d2071dddbfe020a1d54d3be85485fda55e94634c3c7f92b6a0e7df8c54cb47, + 0xf43e2482200419e7d6bd3242598add21ca3c7a6f1297401a48aeeeddf8c42c9, + 0x147a84a37131c4e46e9f9ca597b984d7b4a4239425a12ce32f8fd114874a8cb4, + 0x6acec506161a2536df8657ccae9de73d400b734124368cc4da6fd86ef670a19, + 0x23ca187dab655ca80e1af85d71cb254f05d27b6f8000e366443afbe83c4cc725, + 0x2f8a17922cd86c60691695f93bf0f432f1ef9f05e2e63e9532ab277fa47c0297, + 0x1846b9769a8f327eddc2fa52e235b3c54833f35db8c7989f4342d667ddf2caf2, + 0x243270c2e4a32bbc19d2bd52271b9a8da3f760251ae2f2d783d2854d749d0ab2, + 0x29e4f01c0da1655d98887dc01ea2faa33baf934660f2c934187ea6902f5e0dba, + 0x3e46dd55965a70ac8d048f6ef72742efe897a8a5cac24a0a323452a738a4271, + 0x3032ada92a06e725cfd5cf71879293c3b862c706221b604bf004900182588e87, + 0x9aa6962258ba57549d5496104be1d44d36adad0118ce7780f470655e7a79b9e, + 0x24f4c3f9b2fb7dde23f455ab4a5e76ac60617e46bb7900dd97769420911b59cb, + 0x10e408cfdce8d6f9b7b710d2cc93937cdb43d86d59580ff5417160745c80b7fd, + 0xc7e1f9439ed6f97010e5539ecf56bf151a2955f8ee20b2ec89879d81cd24a16, + 0x20bf7ddb42d4c9d7c8bc1e1b110f065665dbe466145402ba3a3febce0fbfb3d9, + 0x485724e08555b73d84eaafda9702a639baf4de0046875d1f0cf609a1270d720, + 0x2e67be03421ab1f822047861a72a6d08494e65bbfd13c3f7fe6ff48cb863749b, + 0xf79509c03da0c16557c73fb11286f9fddd8f86d235071eaa7aa71a85f547133, + 0x1df1ee0ab120c8673cd3cc8c6ef2e15d74810a03809c61e16e8bab3f20a296cf, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x214e36f5e05f24b3cff586c96031ae938f81cb8624b76697a7e1e79986f1cb94, + 0x26e5f56af93c25c1c66a64447449b0256433d47d6413c0b2fcf6210ee5f138c, + 0xb31a4ad9ec066989d7421b0f1cb06d7683bf5a64e0c3067e0b1a3bca5a64a2a, + 0x8561474777e7f179341123ab782afad4ff632de09860eff6ebe29e4fb1a0c36, + 0xffb57365252bbf56569562327f8db32f337001a18e56fceb006741a0de303ed, + 0x186989821e7ba7588a8634d87210552eec88f846e3701bb336a5b7f0507d01bb, + 0x2b68655758f842d0aa6dacaccd461eafddb981b75166e55dc1ee2c208308e5f3, + 0x2d399f586c89c60556a7651f9409b01aab8f7d9d9322ecaedc93c590d9cd0fc0, + 0x2da5bf9c9e9da4c394519580405b41e6545886063a830437dec32d7f1bdade47, + 0x2b65554e892585688e54d5bb49e321f507bc305fe56fb780e41d816dd9158369, + 0x2ba41319cdf6a416c9e11bca8441cc610c6e7e45c2108dae471840f71deac714, + 0x240f23cf9066f8f5308a2cb0f33e1b40cf634980a9f76bb6ff07e28730868f54, + 0x231ff9a1222347ab20a05faa8d43bf8cb62f0ff9df561f7af015c73d191ffe98, + 0x482fa25dc024367c8dd5429b56e7a0736c866fe84ea1afffc3f5d0f421fe651, + 0x2923732da6b8bf6ee5c73ce34d3ac60f9660eda207235d1d5af9784103f0fb3b, + 0x1753f96bcf7911bc332bcffd151e9e82248a44517474204b3e9888738e58c5f8, + 0x15e1d217ad8bcccb9a7b3009f26c09576e9a83a00f3751fd4ae4b396667be084, + 0x18e3a1c74fd50b4cf58f3096ed129eff1e129302507e6efdcc44c577ff23403, + 0x2ba6780071d6646fbda80d23fabebbaf0272a953fba3249e3af0b56f22ce8120, + 0x1f7f5e238b103729627d5c22c78d92ede19a56995972ca46a317efdc27fc70e0, + 0x2ea1bdf6dc4bb3ba6c3d068e085a361ec8676c6fe2ce66e842885b830315378c, + 0xa6fca77ea6f6437fc2bfa7f2beb768dd908dbbbe87aa75ad303c62790b34d17, + 0x6ce49d6e3d7f46d2175ae9a176153bfd3a3b8f93237a5e45ca9c4ee04ebc5da, + 0xa01cdcd06c3f24187bef0d4a83b8e21a54746f27f0f0d919e08b7cf0d241776, + 0x13c68e6f75234dd86b9568ea56dd98bce6c1b8d64fa4bde97dcd7562d0a9844b, + 0xa162dbfe59de052c7f1bfd5a6a0ed87c5d6120d538c40a537ecd0f3ac12d88b, + 0x2af4c78dae7b20fd7e337e83afb1feae26c555a544d8ca8fc5c9555423fe1c1d, + 0x2f6c75f43301c4a5bdc3d32fc1d66fdaaa4f3b04236427ede87ebcdcb6c7fe59, + 0x2a4aa9b8b9464b6ab6c584645c872959c9f68ba65c057c235b7e2fde8160e42d, + 0x2d8dcc78c6658c1188d60d080fb3cd8b34ee5fd1adccc8a47d499e62ca725b05, + 0x14d6380547e6c54a017d04ca2b2cbe305a4638b32b4163195b459db073fa9872, + 0x478b43d35f78cb355796e0ea0e8e9f5a8b8d6c59cd2cf58df4dbac1a55defef, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x1ef96c51c2b7b30f1e2c59a13e9e76f079c907a4718b3b1827228823b9d8172e, + 0x29321a97121f289220eb66f5382ef63c56ab3d289391c4db61c9dacd44a823a, + 0x1481bf24e7b45de9670afe57fdea41b8beeecfb23422e83c83de9f6845ea9576, + 0x1ef847d3c1b94f7d5dff4319c81691a1354f76fc73dbc600638472570c8c465, + 0xc266666de2f8bbbaa20aca7b4af2de342cf1930552784c300342f3896703b9e, + 0x149bb0f5b9d904cdef7c045ee236bc38a33dab8fab24381bbd14aac30b12ebc1, + 0x2ee176ae76a9196262b1d9b78ce2247cf2133e707cccd952e37d92fd71d88d9a, + 0x1376c5573ebb7265f70acb843f749ffab6f69d346c01e8fa59a1c61091e53f03, + 0x1098a7920a98fb50caa3540c5efc8f6db3dffe9b2c806aeb20501cd0e09a5b45, + 0xb01cc70e8b9fd48f7093dcc2ba65898771cb4302388e39d95095b446fbf6bc6, + 0x1b0e1d5d686b5c6879413df5c510fb672a6d6622bee86008f32c0c32d237b94, + 0x1f74ab5e561a3606ff3b9b334dce7c65d772ca2c1d8ab0e2591d7b8dbbd7870d, + 0x20de7f8e6a491ab79a1d638f7ab760fc5c27285e90c87ad512e86a1bff3b247f, + 0x2e48491edee5daef9ee63ac52cb1734aa69e15b68d8c9e0da68ad718858397d2, + 0xebddc875be02613b22701dadc5f3ad1020a797469a02c064545adfdfb73daff, + 0x171d043f251b701475bf87b388ee12b5a469cf0b5f4c120b34b7b8df3a50b898, + 0x11c7c2bb7facd8c4d0e37f220026818496ad96f0009975cade5a85dd0b319d3a, + 0x2b86058c080559f84c11d33ce0dd77e8f4aceff8644a1ccf78907b6f02f2a2e, + 0x1bd631d67d9ac357a1dfdde1c92a62b0c7fcfddc06376746b45231878b83da75, + 0x2cbdd86f5eaaeda63428d4a39c788df7e08cbe62027d423d3060f7a04fe40d13, + 0x120e0960c012805f36743a540c3b89f519e39fa631ba17d2542d13ef27469cb8, + 0x8e188acf6db761e26d65404bbfd7a0b5537d4e05d85f819de8bb08b1f9e6dd, + 0x2da3a719e3b97734dec894cdff62842dbcaf8ffc37040bdd3f2249d32df42e65, + 0x176acedbe2dc8cdbad093b2a591292b231289939391991be3b9ebf27276879d1, + 0x15964189dfb203bd5cb0a49c9d0fe330bc82a66e62b4bf29cf9a878b74133c92, + 0x7e6833725a1a694e290a34cf6d725401b7ba6c1b0b740226bfd38b66acd1b02, + 0xe4fa44c437c0b7871d7db91fee425aef4dec5461c08cb8f7e8990ab8aa30724, + 0x2e3f0bedffebdd3509be6b792530f2041b04171e729ddc9718a2caf15af84b38, + 0x1504dc8d0dcecc34da56ea5522a2bc7960d0dd2e0ea24466b84f59aa5db015a7, + 0x178c9a3999106b047952fb93395c214125f988fb1cebfffecdef4278a076e3b2, + 0x1af7832596eef3c4cc8630615883a143b7b6993e90b4332e66f36cdf167bc838, + 0x2822dceeeceb7a2e1cf3f25a018f8ebdfcfc720a39e370c67d4333e515ddc724, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x25ce0d19840e800b798a9033269b14f1726a4fd660cbd3b6dc3cb39c07f27f53, + 0x175f82195ac38e9f11db0773887a93338ee07d2852587fb4226f11d9422b8328, + 0x2017bd7838d0bfa3ea272ff2e883a80e63c7288a4433997b18b4c5f0da5f7e3, + 0x1818b2d93a4d80ce0068fd9ce46ddbd200b6040399f4355194edc9f2c55b5ac4, + 0x17c59d81c21e6f83f8972fe07e0ca9b352d04ef730fb76dd72931925c9a78427, + 0x13694ae68e1c55dd02a5b8c1915f878edfbddaf12b45fbe9fa27a2954b213a9, + 0x120221d8a84571726473bfc84ad47f1b04ff70e7a8d8e9c1e91e1165e9b4f18f, + 0x14d65cb6f3b2e4bae5ae5ed1cafb3e68ea86144d27fa8f33aeaba929cfef4d80, + 0x1a6104dae9627992b627b87d84e656009bb69a3a7a9bfee98aa80dbf21bb6ca6, + 0x1e3af87bd45255572d1d14ccba0d7b2f8dfd79b79068c6f3883ca9fee52830a7, + 0xf3d0df45aa7bd62a9768cd20f8466c37b7ec5661968b2cd18abd57367319079, + 0x13b8af0004234bf35f20a7cc7b9fccc999d0d8e4f5ff6f26c237835a1fe042fc, + 0x16e0bf0c9a24d467e38c3778c76b2e2250fb1c06fd4659fffa3093f493a9eca2, + 0x26d28c3453b3d7eca08e87a6c46bf8a698385ff358e23edbb1e174efe5c233c5, + 0x26fcf8eeebb1ea7b1754c047bac9ad888edbece428440fe2102d46969daae640, + 0x2731ccbaf234079c1038e6ab182efe0f1dba3c47effc3e21d2e195e3f0319503, + 0xc785f0fe165d5d26f6b5f2a0ffb7ded4408eb4a92f3eb3d13947eb094290d97, + 0x2581c7faa23de18b2596cfc15ff01dbc84bea0fa4806c7d1a0abc43e76ee0f3c, + 0x27e3f76b7335ff9fccffc865fffb83b368995521e989bd4dd6a86cf595d4a17e, + 0x13234d0fe49f03c4a28ed5ec2b8044e9c7dd20cb831e541b7c540db6c1800637, + 0x11a6eaf2aa5518374eea4199c11f3d937a426494ba614ddbc6ac6ea1dc804ff3, + 0x1fcc367b6de0eac68cb524cf8008e6adbd783e8c13821889031f886647664a0c, + 0x1458038bfbc93c12974f7474afe5bdc94cbd539c913100169cccbdd143151a2c, + 0xf24afffaaa9f04e88599ed696dbd4eae28447c2f05b997194ec832189cdfe25, + 0x7c8e157325437ae945c3c67c4c757493076bae3ae720b00d0c35c36453f6826, + 0x11198181950b4a2475dc01088b72115a94285ffec4c2a5ca614d13b1a14fb319, + 0xed57c8d4abec5e290ca22be70bc5e754e135771d5348f7d711d7383617ecf36, + 0xcec6b37e0709d4c9d5a8ce252840ada6dd5fb95603720af648319370941bfc3, + 0x192f0b18cf17855bfe94214aa47604eecc598f8df429d9c7a9f0c807a467511c, + 0x10323d6e384414dda110f50d67bd06633361960a357f9c6de63f837553cb58b5, + 0xadd901bde5b672bead23855ffaa43194e666b932d604f47000f08d1d2640511, + 0x16dd65f412cf9f1325a3cf4e9a8f02c27371b2c3d90888e7d4ee82713dbebaaf, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0xc86afa39353edb39b52bbff89c5c1a2bfbe2b4100df0895fa7c82d8e77c482e, + 0xc46613d67d66e8ae31191ad6e5bbae2539169134c5311d25c06ca54e9f3ab77, + 0x395678f2449c3e1a76b5b9df068e5dabe76e15ba8589e0703efa3fc1244184a, + 0x19cdd035008146af2718d7c2ea72fa725be2d10efb070b303c809b861b788b51, + 0x1a047c51c9647354891ea4acb582296dfb90bc65c97e8889f1d075fcf217cb48, + 0xc6cdfe9a0d4271a15018a2e3f2d80dfb7468e216397e85e138d20be790b2307, + 0xbc59105470408a58ed2e8816aaed1c29dd3af469e2e7eaf3e1ac366d40d312, + 0x2bd71a360bc27ecd0f2ceddb797ffc5a662dc96cc64cf15e03e2e63a19aa0453, + 0x45e127feeab8d5df95789dfd96426ae84c34723fc735865f80d98ee53eadd5d, + 0x153dfcb519caee780dbcf85d14af1fd03d6888a8f8f35e0f5d16fede2fc3be20, + 0x14e6a09539291352d800dcc6d07e0d0a15b544460b6a00c00b236fe5befec431, + 0x2eb026a3350a6d92b399aafa7e52a5e1730d63b9212e6431473dec34b227eb63, + 0x1641bb238c520d7b2da80d743f6325b013f7f2af04f83162314ca4554e4c034a, + 0x2e2b3857032c8659c4533fdbd59d3e118d810ef879943988e6239fa808bafb4d, + 0x2c37d689e22b1f332dc12fcb8490ec1b679a5e15b1f4b9b5edcc16507adbfd92, + 0x3025a60ca5e0d56b9507310cc9a8a7a6dac7bf6e942883c6f73356f8a0c2afb7, + 0x7f9e146e6c775ceee72b28edabe0f4735ac136ef900a6147570f0ea6de0782a, + 0x318bc71cb7dc9d5f8b099c165d26545fe0bbf112167860825c84c180493c6bf, + 0x2c6fe3f7e18010025df5e6b84648d0669067a473d849b4e181c3f4e03d42b128, + 0x2bfa2ee15d1c06192533994513500e6386bd767c78391160dc4ed7ec323e57a9, + 0x12f7e0085d724c9e28547f4fb7583a6b0fd4685f1fa9d8c012baf4701786270b, + 0x58f27cb9e4bb8bc4df8b66ea9b5a5f8b90cdc72b345c4b0a300b1ecb6e2aa63, + 0x1f34ca32f956eb4e099ab646d95af278ad8db5cd00ddb1c8a44593ea2fef03ec, + 0xc73343dbd1d62046a2df0d555812babf2ee35b1fc103bf6938d783ad0b44499, + 0x18e5fde3115a19d207ac2b687e135e438d915cb495c74a0069fda3370f46083, + 0x120fde4dcc6a7447775ff4e871e321ebdfea69a589ac90714ea4f9a9608e1e23, + 0x2d4601dddfecfe13175df8d48155e9aff8fcf449dafa39a245b8d6cb1706f490, + 0x173632b4f61f2083cbb3e04853acb5bafeec8c75dc4407123e2133c060905ed5, + 0x26b288e1ff854948e38cff794996597108b335f67b1fa2598c5ab2691a927730, + 0x2a688ae162bad939c6de4d889910df138d1f7dcc8989d48caf72e1e22b956422, + 0x160f4b8f49b226f36e72359509e3dac329b1372a7fb63f055d7f9b004d5734a, + 0xddb062d06f99f34542ed03bcaf07a59a456201d26f15d45b8f122e9565d4044, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x13785c4968bb97c8c769257653ae58a73b94a24553fae0e00988b29f47ab549c, + 0xec91cce07b1e9b778fdac5cb9ff8d8e6438292781351bedc3dda454afee474a, + 0x22ad585fe3ddddb3233f390ec3cf43a570cc4f56076ed366a63a50b493a6d655, + 0x11f51cd707f519aa4d0f07de79bd18a1f7b65d2b96b6023d18a87459396cffd6, + 0x16d2290bff342fae3e0f6366c4a3ccb44c611797e77ebc27d7f5ac31fdc6cb51, + 0x16d4e47f82ee3b3d81d48a335be28f4521f90a935641a451097b8298daf0a26c, + 0x269e6a80d58dbc19ef71e682b1faa7dc7394636fc15c747d04ac950496f6e118, + 0x2c1684229f0eae24af14f894023cebcab0e384703e71ad56199c4c8c70e2dd06, + 0x2d9ede2e8993c45794928190781b626fcc406ac3a977235f9d6e50267ef18fb0, + 0x11d67805271cb5d86a927303acd7fc45218098ab99eeef9756e62135bf77da70, + 0x170206f9a4e4e0d7ef55c5cd644aacce231f7727c7f98d97417b720bc37c7881, + 0x14a30c6b5536c74f98f7fc57d004129d4f887cf18ba9f869bd5630d66d341324, + 0x25804cc693b0e118e811f3a191a9d6e47a537cb64129293c947206d9290e7d10, + 0x1a7a17b400934be92901d4e91ad3cfc98231aa841e09627cce975bab7c15f2db, + 0x2c0632973f605ced6998435a7d0cad76c8c9c223c280080fb6a8c922ad09dae5, + 0x3044b16721e5ed81d39f2abd29d5f0a761c13fe26bb4f53d09d5a05620997fc1, + 0xe2cb4e18b26e4ea445c704748bc7682bc2834cef35ce6bdc043beee286025d2, + 0x1c033ddc1a9720312cc3541e886cb227d2d37eac1cf86c4588e98203692941f1, + 0x1ef28ce82fab806a49fa311c6f4e8d0423d051e0a3500db978ff731a9378bee2, + 0x51d7d3785234a09db1939ae4ceaaf14a46928189efc8ea0fa1889e5ad0d1224, + 0x462c9e533e4745c52df23623b0b72f3c9eb8e3a9f2a22a71b5ce6ca41927425, + 0x26a33280331d48e2aa9c5f8f63c4423a6dc8019b9633f49aebbdb6a55ea5cc93, + 0x8ed8b1b9618a2db7e4746115d96cc25ec51411bcb07985e9529b6111039e90f, + 0x18fe5d991dea77a7b18f1bd5c183a377cb9e5c9c2591867eb2f8e876c40c41f, + 0x25a3f5cf66d0e82be05ea92e3a982a6b3289d9a8e51618f9b21ea0e39a30e5b6, + 0x6182fd61e1b35b6f008e9909fe99904bfaef6519618e435130155d28d1dea2e, + 0x1af6ad164424b6c90ca4241382ca0cd2660ca388775973b08e6728570a22d844, + 0x6b534601619e55889aaa855c063a2ced889c6b4ba4190da327c8a612c255544, + 0x50555bc03cbfafbaaa38191f0cde54e8dcf4fde1ccafb5af5c7e00c316d655c, + 0x579cf40adfc069a0b3cac02a495fbaab0175fe948dc97ac85f7699ec9be97a4, + 0x1d9670b720e7af8fcf67b3c832d43a0e9b36c1ce11b679554086d3ebd3743815, + 0xb9f1b4372ddf2b552fb55e7d029267a0ed4f09c4f95d1b99a08c1d6585a6e74, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x80610bf8946c2cc782c83ec3eaea36684a2cb66366a9a801b63fad3332e8ec1, + 0x2837c8ba7f104dbc7503abda031731b4a7a1dee3ee8fdc708651a7385e56fc72, + 0xe4348619aa405bdc4f9fd965dac265ae73dcdfc0f71bfa3a943cf98965610fd, + 0x199e9e250ce12b1667cb730f801334157f29044410b1d98b2d6f2a261a2f7768, + 0xa0409a4aedc8480df4a99f9bd0bdb0151e5ec3cbb6707a594d8aad6334d4c75, + 0x2719d9f1e85015ea06b50d406af582c36d5e937522c974727b1e7a4eeaefdbf3, + 0x1066a17fec5e6cd2202792015dae55345167ea35b6a65ab7a7f2af91da59ca1f, + 0xe4b0a49c371457ba0eda6cd95fdc3cb81264ad715202e43e2dec5699fbe4d82, + 0x24b58a924ae3bf6ac96fc11ffab9221a2283830e95377deb2e5002c2bdd1323, + 0x259c8606be0c6467b6ef056c6a4192776c6c3536ffa82c89f038c856862af24c, + 0x21d6c0a2a54c5ae9ef9dd5f2aa73764f38df1e923aafd242e5f523b5332bbd05, + 0x3c099cdc3f61caaa2e49d484abb2b30e969416f4e1a5678bb025318e416678d, + 0x1d4d4b8c552ef0d318a9a8edd80a2f363c1c0a1dcdab35880dcc6bf3c548262f, + 0x7e4cf648e92c276185c416d6ce6f5b0c0e7cbc2eef1e250555699afdfec0a0, + 0x2992b02301dd18e00482a9940d59a69068127f06aaa50a32322dfa2af211f3d9, + 0x16871531e6fe81173d8082d8059270e70ac4125d0951616ff37e4b4aa6975598, + 0x221c08a0b7dc5aca357a52f0127797f9e9e01eb05d73655f6c779ff43f295f1e, + 0x2756a3d44e88bd6547d02fa4460c09a2e982a4d505a3421625b9bca2604bd862, + 0x2923fde3bde5751d8eac7a9a156d2444db92b629185e01e5600c4fb5a2ea53ac, + 0x179ebe0d2b17128a67f8fce5fc42ee26c654d2a892c4eb3c6577448d5fd556ba, + 0xa1814edd4f8466f7221dd98f8ef29107a18c66320825acdddd8de64feb0275b, + 0x1cf03d03226c78b2369f79beef10f08fde37c150d4e7aa197978365ad0bd316c, + 0x2fd3e923ee39fabc387d2170ea6b9a629b0a7e28296c84ba8843f8f03ec3bbc2, + 0x12c6bd4f25c2d042e4d0ed3a1e5cc01247c78ae90e49ae722d32a584286e1b4d, + 0x11b78a0b243bd45aaa4f3cdb1c79ab206e95c4011289c44ed4d8ca99686c9b9e, + 0x8945308107ba56486011898e6bb26a99ec0f0b9071ad9ce0af820d2727f459d, + 0x2172f85afc450cd67c1efebd6becbc01114bc8b3b62b4081e4cca3418693b323, + 0x2db81bcc85e548bef5059b2595b4f06b55386b9aeba12f483f49978ec6a9cfbd, + 0xef5d0ab806be48c7d0b46a2cec1766083eef4ba4373a16abb2226803305207d, + 0x17caf822e96f4cb68325943442e65736c0f1e01b845aa970824a3b193ccf8b30, + 0x2315b8f0ee989b11b9835d8ad7adb67e035f85c24835a4d53cc7d7b59ff15041, + 0x1f5c7dea1a88280a88e2a57c1015af5c5d4e84da900bb30de5fb8c5258b46794, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x92a67467c379af9424ffdcd9a81657b04289992027e3a841bfe322924e000b1, + 0x8c70f58f02446463906891b2604d2faf312cac00e6c254f30ae85874c112546, + 0xf4af67e5395b62af989d01c1fa9fbd219ad1aa4aa2be4624460940bc0c12a3c, + 0x17f7da080a7159316a1994a87177f0a4676e249247a2a577c3fc54ea8cf7fb27, + 0x1591bba9c620f87132b8ceea1de4c4c5f09872714fe1d63259e0ef80b5f333a8, + 0xcc30f15280abea47abe01145e5f35bd877550b79ae4262f61be65a5ed0cb24d, + 0x1fc9cb670a57f842d47bb906223b02a9ab6352ba622804ffa51ee99da3edaac3, + 0x8e8b798ab602d16910a34edf3f093333041aed6704a66d782d7a319dcda091, + 0x1548714c734096e2cadef4ae88dde9c8886029e21e9ff5696971f11dce6ca6e2, + 0xa133a39d296d427598f8acf721bdc057f2cd639a3317bfef3eed1bf38c610dd, + 0xa4190ed0b3c966b6d7d0bf0bfe4d586e77b84cd55bbf322dd62c4ce7a262914, + 0x26447ee04686542296d06c8f53902672e79514770b3d6490735ee9f5df35859e, + 0x2d1d51cdb7a8fdb0cd7da5fdc33db94bdd8d5128123693ab1f4aa3e78e177870, + 0x17b204236b11bd5c5c48edfde61d817b73d7cf2f5a32a888144c7b088d3ffdd9, + 0x1915106b66fdf208607ed6888d503f44723c87a5c5aec9eed658514f3692828f, + 0x1c171f06ea82d218b24213479856d66394e160dbe0b27e659a7294e07faa69c, + 0x2a4c40c22e17c0bc9f509eb1e30acebedd18ebdda1825e391523a74d4ab23f50, + 0x20515a5d86581b02f9176d72bec69e785a77c41a16fac68e1beb2ad41ee21f12, + 0xc401945dd3d8dbcca89faf8e58b0469e7e7520f2e8982214a4dc244dcca5cd1, + 0x28bf080eaf7736338ce614a62cbb2805eea22b0bfaeac1d0cd2cdeb2830ae0df, + 0x20ed87ececd54dc49ce955a83fd4db61891865b24bd09c3eac85037bd69c52c3, + 0x2baf7d6e7863aa68555f8bfd7648d1b4426f6c39fed82bac197368b3d22eaff6, + 0x1fcf69944cc889569269c5031cc1fe8a1efb0b1953ec7f9573bf63671ec7a947, + 0x980bdeb30e0498f3c45ed4e17a4ae4c8c3bee91095a6340207b69b4ddabb83a, + 0x2455522726c3c95dc14e7fcb5fc1c008b5736e569f80505e71454f8aaacfaac5, + 0x23541590ac6650296ea9c3b935009e79c446280d9bf1010b8e66cdda9f8970d9, + 0x1d14af4f4b54f0c9398e051d2a223193c78997d591a639109818b8cdd02f556c, + 0x22a747877bd35dcb97520a0f4a812c7b78702bad181237c01a05fee842840e4d, + 0x2eafe1740ca67f80d8ae595e84c17039a0560bcb9628b084a97d9ff4afaf6b2, + 0x1dba84e994a54a21666def22befb81abf49fec76c43c3f20da9043c9874ef2d8, + 0x137b47cf2f3d3afc02f3469e9d165e49a212ac255691a1bd3565bce046fcf153, + 0x1eeb1a0edc33a3e69b8445581ee8f0ddf84748fd901547d49440c863ca10caea, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x3e5726f2b2c60906deb00a314337a9c6e4eee70497a4a953ea206d200db8d69, + 0x528d0374310dd042d5f80b2e720b61c4200539fd1e1a23ee1f8f347041af0db, + 0x1da41de720a61ccf6e3b9b97ca36d7439da12c92549a11d238475e05f9037a03, + 0x21c1d92ba962ab12631e4f710fc9b066c369ef4aed709fd5f6992f57be251b99, + 0x2ebcb6f494b7d06a34d2d097c0f46ef929646c529f6efca0edeae7e733b0278d, + 0x26ba18bcbe43ee1a2ae6e1b4dd89151ec17e1341839b94e4b2bfbd70761aaf49, + 0xf05d9b39c0b9b3ca177ee5a8b12de457d00643d5a668a8fb30d6cba0266ae31, + 0xdbb12012ec467271d189184d086eacb530c1bc906895850bc80af72eb6e49a4, + 0x1e3d63755488479f0502c34e097c74fed1926b613e979d53a5353ea959ee6c9f, + 0x2939fe43f4690de6ecc251b7cbfffca082fdf3c841d5ec1aa77de64016d23c0d, + 0x29b304c4af9503a5a1ed74cfb37c9e98235404a851e915f9b476f96cf97208e9, + 0x17f58faffdddb92894ca7cdad4cd379da8c174076a250c3a69441d649ce04bc6, + 0x191456fee87886a7ae3d41901a05e755d8a3cc2a2519cc011a80724d430e918a, + 0x4301fbb26093e59eb5818971467c137eb7633a00e8d1f51856f2e38596f3d2f, + 0x127fe9f3329bc33759114950d8afe484a98e33011da6e40a41dc1f4ca2ce87a6, + 0x201ad991da475d146d85daa85c5ca3d2d9ca48ff7886b06e37dbacfb7ef69664, + 0x24a3d85006e0ccdd3d6fc62623fc5b36b1827ad57f7511a9677cc36327cebe65, + 0x273193d9b2986767b8934849938c7d1157ebc32578efcc7528d9a6a18a354953, + 0x2bb64a3b825a61f6c8b577993aa63ac00659221cafe92405be881026da729676, + 0xf656e73593dd090547fb5b3b8361d172c93f94a334e5feddc059fd03890690e, + 0x2889c18fa2eb572d474b6eee810b750942586f2792b146f455a023b89542d353, + 0x10ed5f7f60bab5b473285acbd59f0e3dd299f6d2d1e6412322ebf9378f4aa031, + 0x94d0f2d2dac4b549a1ac6b1e112ecb6e9eb337c0086cb2c39c5b98a180391cc, + 0x1b6950296c9a98930d2acc173d41e4788e70e42e3f568a97daa0fb7ad8d2eeb9, + 0x227c2f6979d9ca34ed1716207f3d70e78b9b76b1fdbf3ea97ae4b54826190e21, + 0x33ee70ee09fc264ff1cfa9060778cf77b725d24c55967846f6aeb468189f68e, + 0x103ab98622a6dd1bd90094a3b69b635873a4bfb0b1645964b8d03390192a264a, + 0x46f5bb0ba2b9a8cc19af50bd1fe9d3e73e4df3036ee569beef19fb47bba174e, + 0x1955685f6f6f936a887f4892fd66ae962f38fec2286788bd246f7eca45b5d7f3, + 0x7eaa9de669ef1442dc6d616ec080d6c921f95e73b87b7c3752782d7846d5a16, + 0x1103c98bc60cb276ac254178b668e743b6793de46309ff72291767e697516522, + 0x14e1141e0163ad2a79522578c5025149d4ad0b484ea0837c427ffd798b5c211c, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x4b913e824903a4b78ffbfa9043117402f816d24b695be147d26fb633ace8fb6, + 0x11b959c95a4da45d9da05602f07e696b8ac0ce6781702a1368d807d21eaab72f, + 0x1fbfc86fc58e1fa4032309165184ac8b6dc81dc1f81c09ff100758347243f289, + 0xfa7865327aef8246f45ac73dba9666a853fa8e71e1edc2409647207922a9041, + 0x3020170de7b6e86b2b0fcd04439ebdaaa8ce01089600b801945dded0c906d83d, + 0x10e72d8e4629ac7c8fffddca3f8374759040f8f61e1b2419cf266255d68496d3, + 0x5e90f1892363b99161345ab49317e3792eb9a536f473e85fa47480b90dd2a86, + 0x240e190d0b92f9aa7cd7bce008719c3f8d5fff587df3958c85f5a1286288f63, + 0x16e841b2ee682513db27e23b983f5fabbe6ad3a3d44303962910302eaf30840f, + 0x8a397b575fb86fad288ceb48f43315d70399c8bd9cf4af25faead935d02277a, + 0x2edad52145b10b3d0bcbd0216574b52cc2b442f9308ab528a018a78ae97067f1, + 0x1caca2ec3c3d6617fefbe6901c4252ec01ec7cdda757bdbd5f9cc62e911cda61, + 0x157303e9fe11497049ecf530db42fea5c87d7b14cc153120babb743935f30de0, + 0x20d93803a35f06d76ab5daeec28e4591d0066271d84edf26660e0350d30a9049, + 0x970dae33627a299a9cbf049505d94ce6cd1256c80a6322ad47479448bc808a2, + 0x178b6678bfc5c1d9fad6fa7aea247cb6b4facffbd49fd846c64f1411b2c2f6b0, + 0x6503b98a6cc525bd286b56e7ec81ab36835c969d4101ac249d3dd65834fd99c, + 0x21218ec0a783dc924ae7d9f38260750f0a0e039a4004cc095d5bb88e1f9be771, + 0xc0289c9220673997f0393267b29ab048761034a16f6b6e076b063ec6031846d, + 0x1984f03779ff4d9b4ccfd87d23700f204b38c3a606b0279327ca81ff9560b48d, + 0x17aa6042676f383383262058e28ab7c70d3d19b4f8ad4f54a43869e037470258, + 0x2ee1b009aa9a1ba5894110394a79e739754d9f2356ccf9293b2d851ddb6a6c52, + 0x22a586eb8ef3b8257479bca2d919afc56fd0846dbff4f3a9db9e42e4334b8727, + 0x643b1de630b4b9a250b0eb1857c4323bce1701afdb02ff2c6537a04847ac5b4, + 0x125bab28f5eb5c15dc0b3e9ce2b1e6bb246ebc56c44fe9943dc1ea4915830033, + 0x1bc10af70f7125d85f34ad4ef6e7347eeba2a11321da19894c5f826880d770ad, + 0xf6baa6289cf76db86d915ac19af0535773157e39b5423b43b1f3d0df2a4ef5c, + 0x2e80ef76053f6d815f5a779fba74e9b03bf8dbb8a19d40550c519a35f391301c, + 0x31efdb5d245fd16283ceaab1fb5d4ac1cd08918c0c22265f7f114a9ef22058a, + 0x25efb8eac91f3ab3d77ea8ef523c86fa555516d32798397a6ad00622095b9b0, + 0x14cdcee9150e86793e59fd2690a2aa102c2ec7f78d1da286826a37068c8859b5, + 0x101320abf4ad5bfdd7bf37fd1b5e5afa8f1b472c02e062a7058780fc215396c4, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x4d0659feee688cc4dbaaea4f05b259f7614cf5a5d970087016cb2f2eb343bf4, + 0x291dcb25510a3655066e860ade461e23fa4f89bc26f523b65b88aad5a753623c, + 0x1c40b5589a51a5bc3e746f93c18ee86f51331e8da3a246909b6a3063393a1b6e, + 0x50535d58a6b20676d9dde187a15c9676781eb6c1e46159f9e63d7db750c6410, + 0x1532765d3af5aad33c7cae523592894cf354ad9890479d662ce3cd51721178c1, + 0x8a6818b3d448d43c1b5ef357488c00883e342690a21d3fed21f7d62142dd589, + 0x17db4c5c59ff1ade79c01c45dbc7b6134c929ca5292cd7893a016573e7696756, + 0x2a7e1f2d365ce9b5abd3eeaf983c6f6434cdba5ea59222f6bd3a5d3ecd763f5a, + 0x6261e5b4d7188ac9e84d341f1152a4518f88d3e701ed5bfd7110577ce1dfa8f, + 0x199c5a8f0703767fe32daa280419f8c6793bb0888ecdfcbb4eb16332fbc028a9, + 0x13388d9d87929845924e078243a8d7e2476d77ccf84f1c05f7fb7c7da371bdee, + 0x7d044bf7a4fd698a6757c186c08d7c39c2083c8cbc5be29964e481592ee6684, + 0x283cd95f4743d216af04c17591b192367280dd2440ef47349a8f384f63887cd8, + 0x1356391f7516db1ad0481ebffa73034416caa2362bd2612a9f42034e35e93e27, + 0x26fd7e1f6d657b1bd8333e3f9b548f54941b9d13830bc88b8210e5b359b00f68, + 0x27ec948ca2028850a977addd6a9cccc697404d4d4b47eaadb54558c57435f916, + 0x27529d815efdab4fa4f21829ba3103982ab79e6052fa863044394fb5fc8d5dc7, + 0x1dce3f61f34639eefa0a344fea750a5751da0695e577434f20a38658cee96f09, + 0x917c97d46d5b4ff89b5cce4bd785c4b68f38c53beae9cec7e8ce31f7b11ab5e, + 0x1f389f75cde06c7ca3105a2b5769cf3915292ebb44e5819229fe3f33ff11d03a, + 0x2d9aac1c72b0a36a067ec7776c0ce2138eed3e90c3c381d13b28c43f297ff300, + 0xb8f7a8e4c0d2d5757c501e44a51e5f5160a01440281ebd4479b858614cfc09d, + 0xaa15536df2ec5905877e2ebf9d07d3763a3f94e9b4deb5c6639bd89efb86aca, + 0xb03dd77a7424fa8d945440f077f848e4137323442e11e1b4a2efe97df3214ae, + 0x70898a71952afad3ef0062e8420e92d94fa7bddc55beb355dcd1d3526f538d2, + 0x29d5413ba2416a2db49c14b165cb247362821494d738b57897a0bbe6cb53a287, + 0x7f3f807872bb8ec72dd2ccb223407a19c5b64e086cdb0c38a7b92458c5f7c8d, + 0x2f69330924f5ca89e8ea41b0334796a9961df24ad0abaef5106d89963a038f0a, + 0x2abdcf1940bf24e67ab4c8c0942df7d3440d04359da428541b0f128f6f53184e, + 0x209de37635d57f9ff0ea8a6be7cec5c70d701156bb34e25c0948c7090b319ec1, + 0x79b485de26ad58268a3b1bd5cdf3a1dbce291e7e30a1d645a7268d340a8f1f, + 0x2da731b7942de735663698b5d20570402d266df448d8a80110557643a906ba3f, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x2c8f848a56c338afe1290f12b67b57d00ff8e974e804ac53b174ea42c9970efd, + 0x2d02f17717bf0db48ac36ad0a19e621cbf73b049364d945ad2a962d481001430, + 0x2150b09c7e10ab5208e632f8dfd30bc323807c5c6b122a6783b9fe5458a859c8, + 0x5b10ef00e618a270ddc6f313e86197af2bb111ec623f2964518938e4d1ab8ce, + 0x813aef08c1ab8116f2ed8caa7eac00762afad0fcf0fed79077845b2b81888a3, + 0x217798429df3f4efe0b8010a3305f618cfa40b31226a7f01aacf05750f85e308, + 0x13dddd98f07da3c85a8a7e584a541a3d1c30131e58fd19a79d3583e1eab08db9, + 0x200c75e95d154cd5d9f42b940fd7090764594e0179db56e462c80da1b57e0826, + 0x24c60aa77eec80da564202803e367806e84056ea84571e7702e708eff20350bc, + 0x2008060f910cd57bd018a7fe79edc508e11897199106323a04369c0b2f110193, + 0x154b1730e35711d6b5e0596a7e9fdf40a369c96e9889573772e35153780d06a5, + 0x20b48f4a5019ab0f0229c8613c44f40d6ca7ff80ebc6bd6f4f595947c9e3e9a6, + 0x8da6678cb4513c79e70618c7f6a247376292a28f4b8a26d7b22cfe89262422f, + 0x1e32944ecb0c8e538be8b702f45748cbd910c621ba8c0462a03a6d536e8f3cf8, + 0x130383065e342214003bef6cd7ac224dfc22a799b13a089cefed9c8872c056c4, + 0x2bb1e946f9019e0f0a3a6f31c54d13d900e95b92657fb49a0bb1d8b085aa7bdc, + 0x12c6706724626b4a2511d5ef4cdc22e569da5743363f598b0985da3f74ebcc66, + 0x105f4876b371512fdd868e75e02332cb49f228f7f6c3ce9012fca57b9587fda7, + 0x1ecdf6fcce9eea60179494be5317b761a337f5c1eea7d4bd7b36c4b136ba893c, + 0x9cd2ef6d45dbbca0dc657384ddb563f367042010debc24bf026a4b9c59f0da7, + 0x254ac6855d05046745889295c485aa0d141421c2e7e46907c6ae60a50ee2f8ba, + 0xa99c054b9a38bbe19930906e64c1126c9f0aaeb16ab6c33d1e0e29418edcca4, + 0x220b4016fade57782896ac3ac88e5c69dca5e58f1d6ebe25f7caee67371b85a4, + 0xb1979da1c048f6ef5e0232ef793f134dbb2a9e2c8f83a710944e1ccbdb08da5, + 0x2eef2d924b88414b5f89ffa9dfd4b62047a12d0e08118d0d39a1a1fa99dd91e5, + 0x126ae3d2dcacca892ec8b9b2338953d3bd2a0b341b7ed5986138dae14b6bab77, + 0x19e7c32cf6e235f95e2ff6e9537b23f8fb2ef50b5a1f734eb757352a74eaf498, + 0x2f9bcb5e0cd5660350ea6151e4a514ac84dc6064adac393e9bc4daa628297fc6, + 0x1aa496f96372589a74cdb1523691b1fd072bd35560d30b8c48109d86c7776b75, + 0x2ea5a8d0da13d3a0051a7f1b186b35d6f0eb986a2769aee850d3945ee2409439, + 0xa633c25ff6bbbd07e365ee018c76dc3be74b40619892f106cdecf3cc4ff8372, + 0xf412148158955c69a302b9b42e5fedb330d5ab4a6cf31b25d4fd1d8135c9900, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x2f2ed1486990b9431be8fc1485b6eac869fef5cd8fd2a94c7d4d5da7e496db12, + 0xd5140886c23f2671e698c3733a296be1f4ecb97f7520b027d906189fd755860, + 0xd1b9427080a9865543b6fbe5502899198b228d02f2ee9287bd1bc1b71680370, + 0x25f14784419e0d86eba62a9cf2cb22f063caeca529be18af1fa084c73287c3fd, + 0x1cdf7679aeb1784cd81e69e41807377671163372ca50143e5b30eef5a31abea9, + 0x7abd6f3a4c53c8d3aefe49b257b3e7c0aace886107a6168a9f93e33733c1224, + 0x198e8dde62e4b800e4a5081cc43fffce5ba02ddb349795a9ba8d2ca36eaeceff, + 0x2a10fcbbc185ff7ae275115f56640a9ab88dfee8d2f371e21fade31ff9e7d249, + 0x3f74e702559a149c3ccb5dd839b3f80ce100c26671929236a4d703c6e53d53b, + 0x1e9cd241f96559366079809b034d98dc345a4814a7e947e17b41a19b4a119b75, + 0x7640b3b48b2cec9061c87ce4740d281ccaea62d865d0b3da726ffcd67d2d426, + 0xf224f2a3eeb002452e25fa54b360804dc9dd1a065655a31230e91a1f7896eda, + 0x296b25652ffb82041356634b505aec0d11bc8ffeab06b6ee76f97d3e90e11316, + 0x24b1e852a6168ca05bfe0e823f4a984b3b99ed9bf3f651cdd3ca31a2d93a21e9, + 0x1170380f35b0c131ca5d2ea71f42fed8b3caefc4ae2ddb42ffce4c72df975521, + 0x2a21146458a9b5cd2232544ec84b9c2e3c07b75cbc4a2e27f1458995a5cf7665, + 0x2cf40c380da1e84026e58bca73fc8821a6956f7866bbc6591330c7b0876d1e48, + 0xa4e5a8c25c79291e6e7906a8bb9897dbd91567061abbe4eb2b80f7e591abad5, + 0x219cccac1ff828ee50d9413629c80b870ed290d5b2197a0b9db61960913eb29e, + 0x18a4a743a05448844b46abe129001953306236ecccce1b8c885e712084ae40d9, + 0x23f5c0a65d6d3f4b017a68d513413e702ab2195a12d3007589a7ad4230792a99, + 0x248649d22bbd35db3c317fb6f1e20944adf80720fd085394e606fe58c93b227e, + 0x1da45cba740db4b50fc4b2571e40590ad20c725af7393d2e2096f782ca8451b0, + 0x59c9894d39a728ce35f569c8b59acff2a98903a73d6935236ac6ab8bb65e7d7, + 0x137afc1da2a1dd16e4049c3e23951f23e5324e12fe046652beb4cda449a21cd3, + 0x1c67f00b6836091d6642592a40c27b9b875f51cc9eb804221130d3f883d29765, + 0xbeacd79129b9b6c793b29450ce6458c86475951ca6f0941ffaaa73622709bc, + 0x1d7194f0b9970b103e3d4bd5a46b5054ab45bd42f537324cb6fec3c672cd5f0a, + 0x38c741f8607a78f328725ad18d2baf8642c005429c53f5b7f9b8be51c8a507b, + 0x1d32ee86d0a10d113b8400a3301ee9df0b4f9666c4c962073bab7f02f0c55e7, + 0xec78e82ba602f4ab67e987ff3eb4562b0818c481c6e8febf4a4a157ecea15a, + 0x2e0de6aecd184a6d47a6a7ae42b76346f15f98bc4f0f68ee1a55929939a7842a, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x93d13cd9b043a5b6a5acb2de0bc54de68b71c88e8d61c2c3c3bd52febfab688, + 0x80fab4e2e36da9276e4610197b32d28ecff28dcf155f5db596037e41a2888ae, + 0x7d2d245764c856372297c49ff64365a99137acfa81041932b4324877e33d9b6, + 0xab6a369f3d47ab68ba9add80b46b610d39531e22a75a30df3f32f4bede18a73, + 0x7a683cd3c4e68622283858eff121cf3a5ec2cb48763c290a4984f7e75a86139, + 0x1fd44c84d9e254b1c6e60cb8c1682f5e78a5c9f9cc88e53b8bd1d8e9bf20638f, + 0x2ac2bdddae01ecad6c097ec139f7d442b7a5c48c491c0a83a006e9dd1c44c9b9, + 0x24a03800df78ab8dac3b172aba870efde663176598e2489fe1371f1b8fd9ce09, + 0x12e453652194ddc8ff5f249f04214d2e0571ae46eda251ed66c9de6f412e08bf, + 0x592a798f42fe58f27f503f2ac512286fc9a0271edbbb43d263358697b731668, + 0xa92a96d55b5e02c8fe846f8cfef92f2243cbd535b6b3c0e44d3c6fcafc01963, + 0x2f43e2c6e8af0638e163e2f4d34aadf2debdb3a5df531296ee2bc5dfd2aa8d41, + 0x3117e986130d1c25eed39ddb3e1e4afef783e031d60bc17e0681288f2d910ca, + 0x25cafbb434aee06df5f90241702018c6fe677ba0bfac46f6b5b8314ef8f5d407, + 0x28b797a499c2b1082b6a674ac02ef5cc2440d6eee1ea1be1ed5a527a6e5ccc95, + 0x23bf393a579394003e64cc399506807aa684314a29992e3bbb3b67fee7f50e24, + 0x28656564d677d58df440de43115089a1790d1aa95183b390349688e8c8aa3e32, + 0x241a69500f5e134c993252fe1052c9cd7e235d501b3b2343ee0e4857e2d0209, + 0x3744e02ce85e599147162a48b8095c61ef582bd1b4027649a4b706e9d99f355, + 0x59b7a17e1c0e884def789033664d88ba112980ee5d7ce4320f4b59092a493ea, + 0x2a6efd68e5dabc912ec2b5f7814e6e1b7b8893acd10e93d8e88af5cece9e433f, + 0x20826fe980809fbe57d7af7d60262abd566278d70e03c7dbd24798c9c991ce5b, + 0x181e562d37922bad979ac96f562011311f09187613e196398d3cea64e7fcc7ca, + 0x1c4e70fbd4c9e09d3b341e1a9ff87d088e6bc4d88a5cb20bc39a2216e9a2e78b, + 0x170c6ee37a8fae5a940388717c1ed8237f9c2c51e0771fe1c5114f020720b1c2, + 0x68712f00eae99b3109162c3a1c8a6b836031f7b3fea61477d274fc39cf53b53, + 0x1937a02e7c8e39d7f3a88a82c38dc1b2b6a7f4326ceaf7aca3f8a2fd163f1388, + 0x8b99b6b338adaaec87f0f4e4106e1a76938bdcb0b55d66b9af257f46da5c6de, + 0x136d1108a8d4bcea80090baee33556f59dcf26a8365b6f657a6625029b73f354, + 0x2d8a56738cf6dc4785fdbc68f440fa3b2d4de0d5ab6d2d7c6c11649ec2e4da65, + 0x27f16feaf6fe1525cd67eef458297d1696dc45bf5f8f1ea18e17801399f3ca4f, + 0x340f8d664a1afe4fbd06793842133cd43ee4e0b2173405efa10445f43a1836a, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x14ad435cf9a9f41fbfaa62698ea2b01d778fa6ad3e6d75d628e535cec66f6183, + 0x229f1484514708285cb6c866fab78878bbc39aec362b9db5e258c101a7382806, + 0x55104ec0dfbeb910aa081864bd59497cfe65acc2091c2cc675ebb7c7b2a318f, + 0xd75b1f18144371f5a0de32dc9124230448f17584ef93ed84300270b6ef3d4cf, + 0xa1da3a581de2337e823d10c00af64ed8152a3375abc7c8e038592893e02f879, + 0x15ce644c9c753f2b508595d24c0905b3712411f8bd78c1dddb60a61e3574f50a, + 0x249251029b3a7d83a4442ef27a2f3bca3edbdfca88c33095f557cececa23fa7, + 0x2190e0657b7f4592ed17884e486aa0983f96d05d497f12d9bb08fcba65e146a2, + 0x18e7e7d031ea4b865475eca9cfa2f156d2bebd8f57c6c66630f2b3e9bdf3aa1b, + 0xc23dd68ce397790fa9d48e22108072ad02df0f80f684926ffa4b66e8871b1ee, + 0x1346be394582712818b12e409e1a2f80f258be08e8f5273e4223048a6ec68596, + 0x227413a36ae6153e431c4dc592eeb597ad18b0a119f1c644d8741c5d1302bf5d, + 0xb0ae3714255eb9abec3c60d3e9d3852c33db950e87bc17818ff0242955aa594, + 0x1f65fc46116912553c6c9bde179a09288bc29ab001fa7f58b2b36e10049da7a1, + 0x1c35284edba1cd391d618754b17f642eebed4127382b82f7c28b2e70a8f70d40, + 0x1080a3fde0e42ad7dd86de041cab7fdd025951641942374c1abcf62626f48a3, + 0x1428eb2a1f2d91707f546af2e0a14fd6f11eee2ca12eff4d36634a08a2501d8b, + 0x33503c434487731d754e92d6e8ce327ceecbae661711045060e165ed284fd29, + 0x137a5d67d8c2d7d92f83451a20d0698f3ec69d9bedca8fdf23e4cc761c30895c, + 0x33ff54a0543a859d10d23919d9353eb1c7df8c37cf77d71c033427f8785ef7f, + 0x2ef45d95ea7a2a6ebf7cd42d1bb3eede45cceeb3c13124fe3e4bf9bd43919aef, + 0x1503cc2c9f6869e97c3f356fc0888cee11b122576b7ac19e53e22e64541b864c, + 0x13b7e00bb153de07cecadd2525f0400ec81c7f3f01b2f8c0d4d923626f5074db, + 0x1560e82a44438c75cbe5e7bf4242e9b318e84d0f70c247b4941214a54e2ecbdd, + 0x16e6cbda059ea98cd388bc97b407a150d03cbc54db44314acd2fdcb856ed59ea, + 0x224e1109c1eb450d665db9aa5a324754e9de0f3645c36a4f42c06525a6a02f17, + 0x1fae1e95cc145b1b611ae98352921e5621563019bcec54ef9aa0a006c5ca9c0f, + 0x29c2c9268343afc2448493205d8efe3ca12ff4ba45195e125b1a585b3c15362c, + 0x1745aa01a6decfbf4742ca4eb4fb46936c593a8fbb1753e4b1bd8ac26107dcb6, + 0x2b8e149f0ad40ad21c74ba35026dddbf89dce7c2227dfcfc94a55130b282348d, + 0x21eb20b36f906d2693f37e6b25f10a251dae88ee9e5bed97d0bfea9d95eb6155, + 0x2e2d367ebd03ab9e863a272a0cb40240222f32d1ef3f7a79de99160236cde439, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x2e142d51bb3c63e11687bea27b03d2c1f47ff4617dcf1784fcb06139718bdc, + 0x2f9a0d8d22bb17dc91fb40146ab611c24fd7aff2721139eebc67f103abaa8abe, + 0x1cd3446fe74bd3cf4e8790869ca502315e2cb5e61bfd569b79e4bceba7dd18c5, + 0x4882cdf369a6b624cdcdf140521e2f5d4f056d5be8938eafdab02b2b6b28365, + 0xdaabd96d080089cc09b753a113f03c79cddb879fcd4fe92f64086af355320af, + 0x11fada765d840371159d393d9383846a758452164778b156ad07d2f97b1c81d5, + 0xf1bb77c65687d588f3afdd2e81ed31b0b14e7a6b34b3f194013310a430e72ff, + 0x1b6cbbda2504b6c7157070cab18a64cfa67b25174430ae34f88f41d06a5df61c, + 0x2caadb9815edd0b00891c8952f439654bff61c480d34304a559b2ee106e8555b, + 0x29d647c2ff17d90d8ac500cd862bc7cf3bcd63cae45d13ba2b2f5bd819cdf00a, + 0xf9577281c0113be755056c5a200c03b651cd175ef4c1c51526a262db78b6012, + 0x1c7a4104b1eb344a9d10ae34fe9f0d9b944b1f27b9ad60e78d076f14b1579dd1, + 0x28833764307c07236b8d64f1e872a15f26b93cbaa63062c5728b6a6126a2b3d8, + 0x245ff91d36df9a9301cc998a11ea027605aea0dac30a20a32fc5b9546ff5f22d, + 0x9c3b8ddc3c8a83b3dbc098cf547b51d197fa16571ca6ce1bfa603f23474188b, + 0x23123b0f1690f3c61a3d7877f26f33c4c26feb8579966b878f9313f2a7bb0724, + 0x2f42ef2f174748c44f63767b95d5e66b2554f75a164e00833336a9d990fe4279, + 0x1d8000747e03e93c37fe21b889bdbefdc234baa290a68aba51d3517a260e6944, + 0x103f779b0899d4250da3fc25d27e0444a18498ffc0bf0ce7ad7fb106ba311a18, + 0x7f4c9eacabf180b840cc30448d4926692e4a4d4b6c970e0e818c5e11d7a984b, + 0x17e5e03ecf01408a520c1c5bb8e1a4477b011178aec18404e414554fd78da779, + 0x116cd1a5deb317ac2200d91721cb4c794fd1bdb9e04c80d222b2ae77cdfe0412, + 0x259847fcd69413a8b787a452950cb9970981ce86ace933112f205b18b20af1ac, + 0x7244b4174980899193f70318c4c09239a011431b1f0bd3f5c79e8e36347e52c, + 0x27a6122c5882996b8b87923a9b66a2a4970c9844cd3034e847fecd91d6b13fcc, + 0x2c0bef6885d9a4d76f43a29ddde616fa8174cd24ab58d4dc707ba5f924739c41, + 0x2d0cd48e3952f4d64e4f37477e2c0ac65fcb78682dcd8fa4c4e9d744c1205af9, + 0x8d8edc9e81dfba6cd7305c1bfe73f42d7252dbb19889e125c5c9aef137804c7, + 0x20860a731c157ac1b7ad854b3b851d0c739f111995a8122aaa7147ce61355a1b, + 0x2b242cf51e3fc841f925153bac6ae94b84c0e4839da70c3639ae554a2ffb538b, + 0x71642f8fb008ca366c562ce0755bd0edc2cb3b1851d91871f7c217c6c17b812, + 0x10628390eb8c9489dd00520c4d1f3bcb7917ee849eaec5d03d662192e40e4c05, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x2c657cf556552ac00d3c6a312f941c21752d80f6fb971f6f237b9f067f55ef50, + 0x2274e5afd41f484d4bb846c23f4d15eec892ed12abfc57aadc71c431dec0ec94, + 0x21e3eead8292384cd4e9ab89698674acf899b310c4fb1474a50ed68ab15ee79b, + 0x275b0e09088d1a143b3834ed09babfca45694301eb39680c7e01456918596140, + 0x129eae0d0efd6629f2846e2659d11190f995e7f7976dba6706d5275f8ae42e2b, + 0x23c3296abead985b298d2f7359d6fc6b66428469efef7f33cce72f7d261e200e, + 0x120eb3949a1bc6dadb99eb797c5089f6c81b8489e8d2fdb648759f9b7d950c92, + 0x277b28338565bebe62ad1128dfd277e71dcc0f5cbf15884f3f4431aaa022ae2c, + 0x4f36e389ff9ebb3bcd6810d8b233c0cccd2d0a9a86f0c6eced01bccdf453a94, + 0x2548fa65475658066e282e043fb7e3a2e5916ad635f27977d292b0ad3ef3e4e5, + 0x4565577c55373eed95c9aaf5c9d202c270ce37dc1a1a2232c856f88dff9364f, + 0x233e72784c11da8ade7b9f172935e44a748c8cb94959122f9da6c7ed65a6cf10, + 0x158b72f3087e0267336e27fc3921ee3a3a534b925fecb827ca25f7dc77523334, + 0x15c260f3c32020be493ac81d6969ece9c8e8aab39cb11ad8c69bd97516886522, + 0x2396362d574b22bf4f2b162ddb6879ae4aee803609c5af81b0cc96e1dd77fb69, + 0x2d0bdfbd9147195907ed3568ae8309feb349fdff397c36b567099ae14a3770ff, + 0x2cd487c6239575748dce9a1b1e9cbaaaa9df4bdbbfa64f68ab6ed9f9685898ec, + 0x1e73a3297684b098cfd3e270ec4299fc88d970a924596014e9a7f602ee9b081b, + 0x248862b26667bf9e71255c8473c4d4f498bf02d6fe6c554e9d6a8194b443c7b1, + 0x12daded6502d15cc7ccfd3998e01c39851611629fd9a6562f628ef83c7910b8d, + 0x15e998f00cc4dd24ff559089cd43bec5566f2505b8136c5ab74d9a426d875c75, + 0x217fa23d5b14a9ffa837fcc744c4a64fd13e6fe162777fc834bf119df306c8c7, + 0xcadcf98c06aba7c6f354cd05bb28857f3798b83111652ddda6e2f8fad6a0518, + 0x1c5c0906f02d4a6e3fe315f26891dae1132436b3cfd048f897a2988abb14e005, + 0x8452c4131a7a4f5730e877519de1b927a02260f56ab0e7cf23dd41010093ced, + 0x72e4518998bb2aa7df1a094e4a1032a4f1651403a006aff7d8d3f8e0431b39a, + 0xab9888d29232bea4dcd77c9627693a4f292375d6ab81482eb0cd718adcc4752, + 0xfc2e5df60bb4a189253e73f07025b34dac9f8f6c215a26c53fa5b3b1482e105, + 0x50e82e90a419f91e690625c51ad3da156afca51ed13531b0e67a3b89385273b, + 0x2f88a4415d7e88cfd3cdf0a5b4bbc26b243319e20d0e4ce861a2f2a5042e93cb, + 0x1e10e776d5e15e0786cd5d0ef96d1ab332eb05773833ea20cd5a19891df8da96, + 0x17de64722cd216df23ac5fc20f4298bc5c23f17de82c80d361a1cc10c3f3b7a3, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x1b9c2c4eebbe7516481522714ccefbcf9f46b1d9acd32a7074f6e247ad6cc86c, + 0x1b40c39dbad124c570125eb0b2586ec99e260411e0dd871cff7869ec3864df9, + 0x33cd9b171a83f21a643c9db6174fdb0a12ed70e96e4dbcd7cd13888c4b3eb55, + 0x19cb8e0c054400347facfff66eacd97d794bd61b59323af411ad0fbe2f380942, + 0x26c218511f870b55f305e1787e4b19e1ab682b8c823153abf87d6b93d808e4d9, + 0x29e12c794848bfe525ab81ce659d2cf1111feb3fd7118f94e22a86b6f88b53cf, + 0x3a6658a834c4e3616dc5f917fa062d251c8ba4cccd09532eca0d77981b0170, + 0x168adabd67838fadbbf46c9d9716f71494ab077f42cacf9c45e489d342a3e15a, + 0x11742863039a6788df3464d2644c239b1929c3f16f43efaf505e2416f5e23a1c, + 0x126abad95e2b51fd989173eb24d170db35879d2ed95aeb53fc43f37b92e0da48, + 0x23c212335569ce5f39553eb328159fefbdba99ea37be97365fe8049e550c93da, + 0x2f4dd1170cd5681dd49cffa2b31105e7f1772c10277da6436208aa1a496c0ca3, + 0x1f1add5db460502e7d77a5abe06b5391bfd9363ec845f737ca6c072f46d26164, + 0xde4648c15ee1c296f4bbc50fcf033680afe8764c93b524d0c7f96a17c8fa0c1, + 0x2940f3f803b79a69ec13670c3bcef58b3aa6225c5ff1b9fd8bcf1ce7d9da83a9, + 0x6022a2c0e67a56ca21f209520eb78989c32443d6d66a659def8fb09e41dc3b, + 0x2614b22ed71c1ebf563048afad7b64934e51c6c1787f79d6cacb0cfa401692f3, + 0xae0351a3f38218d3f64682ea5b4bbd19c9da2312b6d66c98a4e5793f56037b6, + 0x2acb14246a8372f36e96bae26d0298d0dec2a8037325848540d092927b247af7, + 0x4ac1f3bf59ff8258755878919911219c901e45d368e485fd581702935e593b8, + 0x637c3722f5a87f3c148453456b4bd91dde864a8d689b73b12379558e5fe427, + 0x2ed10f87c57e6e4d78f31e18f1c7e9ee7c0b59117a6d034e2ead2aae114caa32, + 0x2db539eff29b1c4e93218c6e10e9552179fb7b03fc7308882fa9ada5a9eb4776, + 0xcaedc62eb88ea19a6ea5fde158da87c74f591099c56a110467fcbb2dcd21f79, + 0x485d5824b4d88b5c32a715605487a6b58ae93461b15110f2a7f71887069940e, + 0x20fa1c1846393fc776c5868c6eb0b841e64eaf613c2005ea361b317dabbca53e, + 0x2e17fb34208254172d03928de8c56b8cc29f87e29e8aef1f79b13bfb5e7ae90d, + 0x1d45f577db25f490276008376cf8b59a08f20d469d8676010f7f281d5cd1aeb1, + 0x48ea8cd9295a1a3e48cb22507e7237d0a6566b58e4747c0896fbefd7aa0c7c2, + 0x3059196428e054d558d0e6a091559ff419ddfeab8e2aa1ba796e98849098f404, + 0x1170eb002f68247115722d0638fcea7c2b7f70024953c733bc8cd94a86c23ca7, + 0x25fcb5f375ff3d5cc49ca2936b121d9591be3e09fc88efeea4cf90521aa04b97, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x23444707325fc7683a461c2dea2173d8472c0b5b13701b34b87203bffe8f4aa4, + 0x2b272e00da1d1d1d764b7da9384cd2efb8db8604c01b9f2b833a7c1520369e3b, + 0x17b59a35bca179afddf24993a2a28466862328d66cf18d77e8be5f950d7f957c, + 0x20460d5c7e4548772c619dbe8a220b477882005180887377c0ecb4b4c20ce625, + 0xd1346ae8fcfaefc96496235e8a4b6cac300a284f97be68f0a453c55569e2e1c, + 0x29d5c8e901d6f659e2c9b51f5da873c776a55de9fe0a95910c5893d9d64c180d, + 0x109297c57950d5ec34e371af14fe40615e26d74a4fd2562dbaf8b0cfc0da67b5, + 0xafa294b0b8973e74c6bcbcdf0953726679268df4b7ab3a0af0496d80f4e915a, + 0x1ccdae789483414efc596b7a74d20cc5af2de7595d53c80c6762e599c4c19918, + 0x7d80df4e972d5962e8447454033d912127d2930fd5229d1274aacb93ab35467, + 0x19e7ddd05077b3710fc6cf15a1746ff3f2ce7b0ad9355bdcc599e882881b7812, + 0x19c52a43b8a53bb146faf681e98fc8670800b6b9dde47ea38a849b82c1f17920, + 0x2ed2fd2f3a2f78c35d4ec54a41b9941d4040bf4f0766985c776b6726746efeb7, + 0x117e9b92ef305e1cecef90cb404f6b178b1d2c216e8c3bf650ad5b9f675a2446, + 0x27dbe49809655461a2940850aa8c41ce6dbd5221400a9dce49f9f3ff9b04dd57, + 0x8bc85ab2f7b9d3152fec37fd1c66ef688e2d71e325dba40eeed84dced4ea11, + 0x18550a78308e47e5ac75a3cd82d4389a37c6918ed42bffa89dd128c6b4cd6f53, + 0x22d06c4fb6f2b725a93cb9e97f08f466c2d2078953f43f4159bdafe3a9bbc2d2, + 0x1f3f2ff5ea4b6044d0d142c2850a8907dece24a9e7c508c09b3b7cbf1d2db33a, + 0x2985a2e4d66f1b2c18c3f647d444474d432fd597dc23671ccb3bf61c1351e990, + 0x177e8a83bcc683805e1af7e744206e05fc99f85b605b10f3f0867913ff45a521, + 0x97666874717688dba3d9546ff71cb3fa829d101f2bec9a191b5915ec120b658, + 0x15055d2177bd83ae6ef36e4f113f7a53fff218984f73588988acb7f890461698, + 0xe0197b38f1671c3fb6a078cb443ece122bfdd9f47486f3fc5ddcdafefdc9c5c, + 0x78b8c01a67c4e5cb15738416497b1d4b3d8fce7631cef919eb4a39015bb5b8e, + 0x26f58171d43f5d52535468f97f3f4a76a56d43bb0c8560ac98ad6fc409c6895b, + 0x2db3d892f554ae8b1b5819fbd4ae79f23a1f4627383656c93be2e3ff42f7e7c1, + 0x196b74fdd43c9fa4f77111911dced6856b397b19da47474fe1a8f0de62bc57fc, + 0x6238d5e3cdaa238c7670efd64dbcce481815965fdd55efa8ab1706d7a43aa38, + 0x22332a4ce6b7a223d45c777c7bdc960669e4a801b4a76b88b66d05039a53eea0, + 0x1f88fecb08e0101e470f5dcee2c8b846d2562f89cd27d92e6b00faacae30389f, + 0xc2ada53a5fcfb484d0a65c509305fa3f00db8a2f961d4515c149c85e677c8d4, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x1b28926cd83b4658afd2d9cfdfdce6b87aa9a072634889320a35cdcb9215e5b9, + 0x15d6448f76cf1b20262428f1e416bbd1af8630fb361d7f644639ad5b60d8f180, + 0x2af5dfa19ccc918de449d5d3b592e6d04d78bd796e6f07098e64630f2079d1c9, + 0x19d0ff169994b50d9ca896bffbd91f7f3b5c7d9ad51363fe5f0d2fb6185c2410, + 0x2755fe866df7e2d95bc2c8072e5402ca6f588b7f2734a2a54a4c519ca8297474, + 0x77a07258bfa21e2ac255e20a0d31d9a01cc85cad4bc02e6921a507ed5df4728, + 0x2ece250f68cd231dfbbdd343c367626f3cc413a32be08ebaf996dc8150003b5f, + 0x28d5f29f5df2a1b4fb5dc798dd2fb2d9099a9bb15e06933ccb382d3f712abc56, + 0x2af8e1fcf37dcf5f55699d9929ef5fc6505dfa79e061782ebc6a4bda3100fec5, + 0x1a391e08a393750010adbdfa7c621d382a29b98886d241cfe0c567bb37748954, + 0x1da3f4058cc2ce6554842588dafe5f4517661730183f0b99f9aeacabfc7acfcd, + 0x1e3b1802005fe7296d11441c07cbea61e32baf5484d40e315cb49e2063bb4942, + 0x1eca6728a58b997d09ac9d9eae05bcd86afaeec5800dfd73fb0280edc996d61b, + 0x2991dada2697975e05e0f74b4a69560557d34bef132ff73f3ecce501461f59c1, + 0x13a9e49e7875c154539d20cfef506535c91422054cd04aa195e12695a073487b, + 0xe97ef3325ec39935456c2a330435ef106d50b3d24a74e55045c58da778d2733, + 0x234fd4e50ddc42b1a40b1410ad7d9bbe27d21eb61d1b4ab05516422214059ee6, + 0xce167e175eb021fe2b91b0abb90c94667ea76c9a1139b958ecf14d64c617722, + 0x15871010759972a879b18a4d18bac0870013ee1f646d63f4bc63fcde2847ae87, + 0x168d81f62839ab0e29c4e03c0f570f9e44bd75eecde371611e98bac9a78c51cb, + 0x2c0c157479d4268e5a40179ab0a915072b91889b1eb06e1bb0e30c5936deac3b, + 0x2c1c6ea12c4f9343a80fd53d4169686705ffb51d3ff2766fd4c61f803e648e85, + 0x12c2c9b7086ab39752ea4a0afbd8703ba2ff66c309d48f404d7eb4edb90aadfa, + 0x16a90e916477870cb13cfc1ecfa73fe9365d36854efe87db94a2d8f019a3ee83, + 0x1e5674b6f90be35ef343540b191b0ee45707bdd34452407ad9035dd3bd282799, + 0x2daf0fbad1fe6737f7bca405e34dd0432a4bcd5acaaae29ddf9ed8ffc1f0c336, + 0x2908cd47730b9b031d14f778c53b64aec2838f3370f8832ac1fd7ab2d10a32e1, + 0x1385230fd1095a5c478a798071294b8a11c9805d10d4f27b670a868deff0a451, + 0x1d163c58cf48bb8e02eb3193cdfee3ef9c85133c14f87db1829663e74d10620a, + 0x2e557c38674c410f4d7c72ee1a36898f9c16ccbf5bf4709f49e1e727dffa2a55, + 0x1c05ef08c0686e237cccd7c9f7279e5abdbc39f7a27dda7238e73f37526346df, + 0x2527d4d7449be5d202aec33259a43c5daf25db035ba558b03308203a0e33f717, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x10a492ae5b487f258651a3aed0227cc02f6c7a8761586894c74e50b84ad8081a, + 0x2403d5c045640a3867d3fff22c33d5a7d4cc9c86fb7f746f0cfaa6cf0009165, + 0x2d5d1d7a9af2b5a434066ba829ad51a9d596c775d77dce9bb5e539df0869093d, + 0x9a863c700ddced174ab9a2f52feab6a6fc50d640f7cda128d3e0db7cc6d5421, + 0x2aab180f6e316fad89afe18cac953fe0795ad3b267d632d4192cdf7a7f09fb6f, + 0xd96040a550ca9da53410c291bb03f2597546be222c18ecc3ce1a6b934c9e79c, + 0x162f27f588a7684b059dcfe87e6f50d77e0b2b7c2a04d6b2bfea5e6677c07124, + 0xb923196444f67bb7b9a3549947da0d1d65c2d863062820159e7b8a15763fbe2, + 0x2004eab7ce64ce5a33d093bffdb3f5c8c062629a82df11c1b9d0237219653ab7, + 0x1227bf877742b79ae1f3f94f4a7d99e2ed3a6a9e531f224f865ef504a5bcaea0, + 0x20f776f86d93c05c559f42775c914befee8b6a77ce89e137ee9faf414a0985d7, + 0x172aa65c733a6035cda4bd931733ecb05f160dea5fac191c85b7f96c03c76ff, + 0x8be42f0fb8d0bd0918ae0c9a23d6c350992a03652a1443e10676ef0aab7758f, + 0x1fd0be6c49952151cd278ae5631d6760f0b7faa1da5cf1f86e88f04332962b0d, + 0xf9ac50342fd157a0cf0acac7bceaf4498140817dfb573e81bc6b455122abc7, + 0xcb3dfddba8d704f6abe9c8d4c31c36ba7aabd8b33866d5c34920a61a0971ca6, + 0xe770f3147cb0e321701d76e1090173d30171d6cb47618e96f0391cfe89a857c, + 0x737d887efe6fe8f9472901487cce5dd61e60b27b3a3987a5107cc0c747c73d3, + 0x1a385e2fdbacefe3fc505c0e8866ed36657ae93f963f4d8b9af435a98cc91fab, + 0x47765901d35e5b9c88c43dd5f4141cba4debe6bc675e49a08069b787252a3c1, + 0x1da4a4ede36f08e2b6f0000760e022e4c87b4828f5df067037e07ed0a3db70aa, + 0x847d2c6657d2fa009b736d83e33c9861b0192212fe8edd90dd9dfe16f52f861, + 0x3039ed5a92b2b6ac7e0dda476285292ccd649442508936442d4d3cc1d552383, + 0x77951dcf1d2ed93be5b91b720b5387db3a4097e55cc7781b69c27f5eeefe04, + 0xb585622b1f5eb8fdfcaad1c3cd7f944255a4618ebfc9f9dacf339e874df620a, + 0x1a2a7bbd62d97bb265d127d44fe34b17d9da8ee75813b5c51b9e16ee8dd7b402, + 0xdc48ec2dabd95e06d2987fd1824a959e084d4e62d1b2c5e503b33dbe6b30d02, + 0x290de95aae65845be12406a4585f7187d3d6528bf7daf00a84da01e8dfb69e1f, + 0xc017e46a4f39a1669a350ee495e7ad68562b222de7114a6c101adef47853293, + 0x2f0b5fb02d18a781e744403921d82e54c4919d1686d824bf4e62b2e4cc088cf9, + 0xe7e699b1dd9c60f0018d874e9364210eb920583d0d2d71567d38f4333bfa474, + 0x9472c6ed2b6494433a9319f2b093f2fd1923059b6002a6e896fee03e19546b8, + 0x196b76cefdcc7f6a54c71d40114a0bb82694c936f1573ac7ac1ea3fcce1fe938, + 0x2a8a40093e2bc9627fe39aa84ab78c1ce1265e8cbe28569136f8b83dbf1e1a0e, + 0x21d9b9f7094b3462aaa61148b272fba6556514dcb39cfb47b5414ac776944f82, + 0x22be02328bc62605ca6d890565b9726e83b9d8f925e702412edf291b777df027, + 0x27b5d7ddef018e17569d33d8c4e9003ae36382bb57caf96bb224b724cf237254, + 0x54ec141c594bace5c88a41767e82517f8dcd8e02dd54f8fdc1c7223d3614982, + 0x17f76454a7d3b049dc34c09012706560351dd12ff052187ba5228c9fd5abc646, + 0x189a082f5c10117ffb6b064329b31026c852cd41e01352e6c7b9d12686200598, + 0xc597daf1c2a8f602322f2796a1bca2aa3101cb8c9a876ee195a9bda90da5d5b, + 0x2ac2e1037357e29885d73882899652c5cdaf8560ae356bbdf7ded11c139dc663, + 0x6ca950f38af807cac3b6d74cb2937af0a2287576b78fddfd7200f06e66e5f22, + 0x736209bdf8c1ac643b8ecd0950d2bb4dcd8745be7c8cf64432da264fc4c6a33, + 0x1e96d9fd0f2db5bcee16ce782403a3a33acad70b237106686ad0bbd8bbc00d1f, + 0x2d7f5635e4b127aab06795499bb1a6c97c54806d79823ff7871e519f4081cc1c, + 0x1d8d18b18dd07bb89fe0c84a7740faed098c6a2b0cde5f426fb8c8b7643bf95c, + 0x28d51d4551904bbf04ec169bed853453358042ef76a08ea8d155f8677a051ccd, + 0x189be365face10b9a4183d6f21048d6c36ca9c28b0720c71d72ed529654aa624, + 0x130fc54477fd953377fc23abbd7a41be6764892a8787c759c1440fe0133c852d, + 0x2c9c91f48661771baeef6774578a78f69c355c8e907156fdf26db39d2446413f, + 0x1dec0bafa3e8190621e5e095ef751ea03c836dbb8045b2a73f8d397cfb815192, + 0xa5f52ad6ec4a8aa377d8dd2ae3aaf6eea0c68c63a1d034fbda67133ca0b85cb, + 0x20ab7394bfdab344cbb6f2123800a0e23508e2125bfe795ab4a767cecb4d9306, + 0x110ea322b0c26476c67bfa2c1b9d1713f93b3b9cf8320ce0dcd4b64288bda07a, + 0x54eabe6131681fa01fbc6dbf3e7d53595d0f8809987182142b890ac8af89cbe, + 0x224d811fbdef8ec0a006d376a019e57c93bd596213a07823b7d4abce1fd8e621, + 0xe691fca423128a7d4afcaa582b1a94799ba1f5d2a5d53bc2bba56bbecb227a1, + 0x189e279c92de0bab66707e6e6e310524e615cd4c6aacc665372a3b8e372d8ce6, + 0x1d9bcbbd17b93b1913d2f79cdf12844441237206f0294746d93f8e5bdceb4725, + 0x1179184635a9780ee1312dcc3d15c7ef042b18ae9409670e28c4c7f0fb9b608e, + 0xe48466182ae8333af1891a6aa19736741ed0680d57c931ede13fc07ae82e88b, + 0x1c9d56f71c2f22c44d3a8c17bf5b40452e05471f0b6dfe9ffe4725eb29f73464, + 0x2234546f5e8541e8f72ad794891950b32b1cd891cc66775c5b635961642e9c15, + 0x14c09d155c5d428198c234b553da338f227cbc12b0e42f2b9ce71563ee1495c0 + ] ) } diff --git a/noir_stdlib/src/hash/poseidon/bn254/perm.nr b/noir_stdlib/src/hash/poseidon/bn254/perm.nr index 890f54fdb3f..b7c022c5a00 100644 --- a/noir_stdlib/src/hash/poseidon/bn254/perm.nr +++ b/noir_stdlib/src/hash/poseidon/bn254/perm.nr @@ -1,6 +1,6 @@ // Instantiations of Poseidon permutation for the prime field of the same order as BN254 use crate::hash::poseidon::bn254::consts; -use crate::hash::poseidon::bn254::permute; +use crate::hash::poseidon::permute; use crate::hash::poseidon::PoseidonConfig; #[field(bn254)] diff --git a/noir_stdlib/src/hash/poseidon2.nr b/noir_stdlib/src/hash/poseidon2.nr index 40eea029e82..04d922b581d 100644 --- a/noir_stdlib/src/hash/poseidon2.nr +++ b/noir_stdlib/src/hash/poseidon2.nr @@ -1,4 +1,7 @@ -global RATE = 3; +use crate::hash::Hasher; +use crate::default::Default; + +global RATE: u32 = 3; struct Poseidon2 { cache: [Field;3], @@ -97,7 +100,7 @@ impl Poseidon2 { let iv : Field = (in_len as Field) * two_pow_64; let mut sponge = Poseidon2::new(iv); for i in 0..input.len() { - if i as u32 < in_len { + if i < in_len { sponge.absorb(input[i]); } } @@ -111,3 +114,30 @@ impl Poseidon2 { sponge.squeeze() } } + +struct Poseidon2Hasher{ + _state: [Field], +} + +impl Hasher for Poseidon2Hasher { + fn finish(self) -> Field { + let iv : Field = (self._state.len() as Field)*18446744073709551616; // iv = (self._state.len() << 64) + let mut sponge = Poseidon2::new(iv); + for i in 0..self._state.len() { + sponge.absorb(self._state[i]); + } + sponge.squeeze() + } + + fn write(&mut self, input: Field){ + self._state = self._state.push_back(input); + } +} + +impl Default for Poseidon2Hasher { + fn default() -> Self { + Poseidon2Hasher { + _state: &[], + } + } +} diff --git a/noir_stdlib/src/lib.nr b/noir_stdlib/src/lib.nr index 6586d10ca66..e272b5a85d6 100644 --- a/noir_stdlib/src/lib.nr +++ b/noir_stdlib/src/lib.nr @@ -1,4 +1,5 @@ mod hash; +mod aes128; mod array; mod slice; mod merkle; @@ -6,9 +7,7 @@ mod schnorr; mod ecdsa_secp256k1; mod ecdsa_secp256r1; mod eddsa; -mod grumpkin_scalar; -mod grumpkin_scalar_mul; -mod scalar_mul; +mod embedded_curve_ops; mod sha256; mod sha512; mod field; @@ -26,6 +25,7 @@ mod default; mod prelude; mod uint128; mod bigint; +mod runtime; // 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 @@ -76,3 +76,7 @@ pub fn wrapping_sub(x: T, y: T) -> T { pub fn wrapping_mul(x: T, y: T) -> T { crate::from_field(crate::as_field(x) * crate::as_field(y)) } + +#[builtin(as_witness)] +pub fn as_witness(x: Field) {} + diff --git a/noir_stdlib/src/ops.nr b/noir_stdlib/src/ops.nr index e561265629e..8b1903cff0b 100644 --- a/noir_stdlib/src/ops.nr +++ b/noir_stdlib/src/ops.nr @@ -1,155 +1,5 @@ -// docs:start:add-trait -trait Add { - fn add(self, other: Self) -> Self; -} -// docs:end:add-trait +mod arith; +mod bit; -impl Add for Field { fn add(self, other: Field) -> Field { self + other } } - -impl Add for u8 { fn add(self, other: u8) -> u8 { self + other } } -impl Add for u32 { fn add(self, other: u32) -> u32 { self + other } } -impl Add for u64 { fn add(self, other: u64) -> u64 { self + other } } - -impl Add for i8 { fn add(self, other: i8) -> i8 { self + other } } -impl Add for i32 { fn add(self, other: i32) -> i32 { self + other } } -impl Add for i64 { fn add(self, other: i64) -> i64 { self + other } } - -// docs:start:sub-trait -trait Sub { - fn sub(self, other: Self) -> Self; -} -// docs:end:sub-trait - -impl Sub for Field { fn sub(self, other: Field) -> Field { self - other } } - -impl Sub for u8 { fn sub(self, other: u8) -> u8 { self - other } } -impl Sub for u32 { fn sub(self, other: u32) -> u32 { self - other } } -impl Sub for u64 { fn sub(self, other: u64) -> u64 { self - other } } - -impl Sub for i8 { fn sub(self, other: i8) -> i8 { self - other } } -impl Sub for i32 { fn sub(self, other: i32) -> i32 { self - other } } -impl Sub for i64 { fn sub(self, other: i64) -> i64 { self - other } } - -// docs:start:mul-trait -trait Mul { - fn mul(self, other: Self) -> Self; -} -// docs:end:mul-trait - -impl Mul for Field { fn mul(self, other: Field) -> Field { self * other } } - -impl Mul for u8 { fn mul(self, other: u8) -> u8 { self * other } } -impl Mul for u32 { fn mul(self, other: u32) -> u32 { self * other } } -impl Mul for u64 { fn mul(self, other: u64) -> u64 { self * other } } - -impl Mul for i8 { fn mul(self, other: i8) -> i8 { self * other } } -impl Mul for i32 { fn mul(self, other: i32) -> i32 { self * other } } -impl Mul for i64 { fn mul(self, other: i64) -> i64 { self * other } } - -// docs:start:div-trait -trait Div { - fn div(self, other: Self) -> Self; -} -// docs:end:div-trait - -impl Div for Field { fn div(self, other: Field) -> Field { self / other } } - -impl Div for u8 { fn div(self, other: u8) -> u8 { self / other } } -impl Div for u32 { fn div(self, other: u32) -> u32 { self / other } } -impl Div for u64 { fn div(self, other: u64) -> u64 { self / other } } - -impl Div for i8 { fn div(self, other: i8) -> i8 { self / other } } -impl Div for i32 { fn div(self, other: i32) -> i32 { self / other } } -impl Div for i64 { fn div(self, other: i64) -> i64 { self / other } } - -// docs:start:rem-trait -trait Rem{ - fn rem(self, other: Self) -> Self; -} -// docs:end:rem-trait - -impl Rem for u8 { fn rem(self, other: u8) -> u8 { self % other } } -impl Rem for u32 { fn rem(self, other: u32) -> u32 { self % other } } -impl Rem for u64 { fn rem(self, other: u64) -> u64 { self % other } } - -impl Rem for i8 { fn rem(self, other: i8) -> i8 { self % other } } -impl Rem for i32 { fn rem(self, other: i32) -> i32 { self % other } } -impl Rem for i64 { fn rem(self, other: i64) -> i64 { self % other } } - -// docs:start:bitor-trait -trait BitOr { - fn bitor(self, other: Self) -> Self; -} -// docs:end:bitor-trait - -impl BitOr for bool { fn bitor(self, other: bool) -> bool { self | other } } - -impl BitOr for u8 { fn bitor(self, other: u8) -> u8 { self | other } } -impl BitOr for u32 { fn bitor(self, other: u32) -> u32 { self | other } } -impl BitOr for u64 { fn bitor(self, other: u64) -> u64 { self | other } } - -impl BitOr for i8 { fn bitor(self, other: i8) -> i8 { self | other } } -impl BitOr for i32 { fn bitor(self, other: i32) -> i32 { self | other } } -impl BitOr for i64 { fn bitor(self, other: i64) -> i64 { self | other } } - -// docs:start:bitand-trait -trait BitAnd { - fn bitand(self, other: Self) -> Self; -} -// docs:end:bitand-trait - -impl BitAnd for bool { fn bitand(self, other: bool) -> bool { self & other } } - -impl BitAnd for u8 { fn bitand(self, other: u8) -> u8 { self & other } } -impl BitAnd for u32 { fn bitand(self, other: u32) -> u32 { self & other } } -impl BitAnd for u64 { fn bitand(self, other: u64) -> u64 { self & other } } - -impl BitAnd for i8 { fn bitand(self, other: i8) -> i8 { self & other } } -impl BitAnd for i32 { fn bitand(self, other: i32) -> i32 { self & other } } -impl BitAnd for i64 { fn bitand(self, other: i64) -> i64 { self & other } } - -// docs:start:bitxor-trait -trait BitXor { - fn bitxor(self, other: Self) -> Self; -} -// docs:end:bitxor-trait - -impl BitXor for bool { fn bitxor(self, other: bool) -> bool { self ^ other } } - -impl BitXor for u8 { fn bitxor(self, other: u8) -> u8 { self ^ other } } -impl BitXor for u32 { fn bitxor(self, other: u32) -> u32 { self ^ other } } -impl BitXor for u64 { fn bitxor(self, other: u64) -> u64 { self ^ other } } - -impl BitXor for i8 { fn bitxor(self, other: i8) -> i8 { self ^ other } } -impl BitXor for i32 { fn bitxor(self, other: i32) -> i32 { self ^ other } } -impl BitXor for i64 { fn bitxor(self, other: i64) -> i64 { self ^ other } } - -// docs:start:shl-trait -trait Shl { - fn shl(self, other: Self) -> Self; -} -// docs:end:shl-trait - -impl Shl for u8 { fn shl(self, other: u8) -> u8 { self << other } } -impl Shl for u32 { fn shl(self, other: u32) -> u32 { self << other } } -impl Shl for u64 { fn shl(self, other: u64) -> u64 { self << other } } - -// Bit shifting is not currently supported for signed integer types -// impl Shl for i8 { fn shl(self, other: i8) -> i8 { self << other } } -// impl Shl for i32 { fn shl(self, other: i32) -> i32 { self << other } } -// impl Shl for i64 { fn shl(self, other: i64) -> i64 { self << other } } - -// docs:start:shr-trait -trait Shr { - fn shr(self, other: Self) -> Self; -} -// docs:end:shr-trait - -impl Shr for u8 { fn shr(self, other: u8) -> u8 { self >> other } } -impl Shr for u32 { fn shr(self, other: u32) -> u32 { self >> other } } -impl Shr for u64 { fn shr(self, other: u64) -> u64 { self >> other } } - -// Bit shifting is not currently supported for signed integer types -// impl Shr for i8 { fn shr(self, other: i8) -> i8 { self >> other } } -// impl Shr for i32 { fn shr(self, other: i32) -> i32 { self >> other } } -// impl Shr for i64 { fn shr(self, other: i64) -> i64 { self >> other } } +use arith::{Add, Sub, Mul, Div, Rem, Neg}; +use bit::{Not, BitOr, BitAnd, BitXor, Shl, Shr}; diff --git a/noir_stdlib/src/ops/arith.nr b/noir_stdlib/src/ops/arith.nr new file mode 100644 index 00000000000..df0ff978a7c --- /dev/null +++ b/noir_stdlib/src/ops/arith.nr @@ -0,0 +1,103 @@ +// docs:start:add-trait +trait Add { + fn add(self, other: Self) -> Self; +} +// docs:end:add-trait + +impl Add for Field { fn add(self, other: Field) -> Field { self + other } } + +impl Add for u64 { fn add(self, other: u64) -> u64 { self + other } } +impl Add for u32 { fn add(self, other: u32) -> u32 { self + other } } +impl Add for u16 { fn add(self, other: u16) -> u16 { self + other } } +impl Add for u8 { fn add(self, other: u8) -> u8 { self + other } } + +impl Add for i8 { fn add(self, other: i8) -> i8 { self + other } } +impl Add for i16 { fn add(self, other: i16) -> i16 { self + other } } +impl Add for i32 { fn add(self, other: i32) -> i32 { self + other } } +impl Add for i64 { fn add(self, other: i64) -> i64 { self + other } } + +// docs:start:sub-trait +trait Sub { + fn sub(self, other: Self) -> Self; +} +// docs:end:sub-trait + +impl Sub for Field { fn sub(self, other: Field) -> Field { self - other } } + +impl Sub for u64 { fn sub(self, other: u64) -> u64 { self - other } } +impl Sub for u32 { fn sub(self, other: u32) -> u32 { self - other } } +impl Sub for u16 { fn sub(self, other: u16) -> u16 { self - other } } +impl Sub for u8 { fn sub(self, other: u8) -> u8 { self - other } } + +impl Sub for i8 { fn sub(self, other: i8) -> i8 { self - other } } +impl Sub for i16 { fn sub(self, other: i16) -> i16 { self - other } } +impl Sub for i32 { fn sub(self, other: i32) -> i32 { self - other } } +impl Sub for i64 { fn sub(self, other: i64) -> i64 { self - other } } + +// docs:start:mul-trait +trait Mul { + fn mul(self, other: Self) -> Self; +} +// docs:end:mul-trait + +impl Mul for Field { fn mul(self, other: Field) -> Field { self * other } } + +impl Mul for u64 { fn mul(self, other: u64) -> u64 { self * other } } +impl Mul for u32 { fn mul(self, other: u32) -> u32 { self * other } } +impl Mul for u16 { fn mul(self, other: u16) -> u16 { self * other } } +impl Mul for u8 { fn mul(self, other: u8) -> u8 { self * other } } + +impl Mul for i8 { fn mul(self, other: i8) -> i8 { self * other } } +impl Mul for i16 { fn mul(self, other: i16) -> i16 { self * other } } +impl Mul for i32 { fn mul(self, other: i32) -> i32 { self * other } } +impl Mul for i64 { fn mul(self, other: i64) -> i64 { self * other } } + +// docs:start:div-trait +trait Div { + fn div(self, other: Self) -> Self; +} +// docs:end:div-trait + +impl Div for Field { fn div(self, other: Field) -> Field { self / other } } + +impl Div for u64 { fn div(self, other: u64) -> u64 { self / other } } +impl Div for u32 { fn div(self, other: u32) -> u32 { self / other } } +impl Div for u16 { fn div(self, other: u16) -> u16 { self / other } } +impl Div for u8 { fn div(self, other: u8) -> u8 { self / other } } + +impl Div for i8 { fn div(self, other: i8) -> i8 { self / other } } +impl Div for i16 { fn div(self, other: i16) -> i16 { self / other } } +impl Div for i32 { fn div(self, other: i32) -> i32 { self / other } } +impl Div for i64 { fn div(self, other: i64) -> i64 { self / other } } + +// docs:start:rem-trait +trait Rem{ + fn rem(self, other: Self) -> Self; +} +// docs:end:rem-trait + +impl Rem for u64 { fn rem(self, other: u64) -> u64 { self % other } } +impl Rem for u32 { fn rem(self, other: u32) -> u32 { self % other } } +impl Rem for u16 { fn rem(self, other: u16) -> u16 { self % other } } +impl Rem for u8 { fn rem(self, other: u8) -> u8 { self % other } } + +impl Rem for i8 { fn rem(self, other: i8) -> i8 { self % other } } +impl Rem for i16 { fn rem(self, other: i16) -> i16 { self % other } } +impl Rem for i32 { fn rem(self, other: i32) -> i32 { self % other } } +impl Rem for i64 { fn rem(self, other: i64) -> i64 { self % other } } + +// docs:start:neg-trait +trait Neg { + fn neg(self) -> Self; +} +// docs:end:neg-trait + +// docs:start:neg-trait-impls +impl Neg for Field { fn neg(self) -> Field { -self } } + +impl Neg for i8 { fn neg(self) -> i8 { -self } } +impl Neg for i16 { fn neg(self) -> i16 { -self } } +impl Neg for i32 { fn neg(self) -> i32 { -self } } +impl Neg for i64 { fn neg(self) -> i64 { -self } } +// docs:end:neg-trait-impls + diff --git a/noir_stdlib/src/ops/bit.nr b/noir_stdlib/src/ops/bit.nr new file mode 100644 index 00000000000..a31cfee878c --- /dev/null +++ b/noir_stdlib/src/ops/bit.nr @@ -0,0 +1,109 @@ +// docs:start:not-trait +trait Not { + fn not(self: Self) -> Self; +} +// docs:end:not-trait + +// docs:start:not-trait-impls +impl Not for bool { fn not(self) -> bool { !self } } + +impl Not for u64 { fn not(self) -> u64 { !self } } +impl Not for u32 { fn not(self) -> u32 { !self } } +impl Not for u16 { fn not(self) -> u16 { !self } } +impl Not for u8 { fn not(self) -> u8 { !self } } +impl Not for u1 { fn not(self) -> u1 { !self } } + +impl Not for i8 { fn not(self) -> i8 { !self } } +impl Not for i16 { fn not(self) -> i16 { !self } } +impl Not for i32 { fn not(self) -> i32 { !self } } +impl Not for i64 { fn not(self) -> i64 { !self } } +// docs:end:not-trait-impls + +// docs:start:bitor-trait +trait BitOr { + fn bitor(self, other: Self) -> Self; +} +// docs:end:bitor-trait + +impl BitOr for bool { fn bitor(self, other: bool) -> bool { self | other } } + +impl BitOr for u64 { fn bitor(self, other: u64) -> u64 { self | other } } +impl BitOr for u32 { fn bitor(self, other: u32) -> u32 { self | other } } +impl BitOr for u16 { fn bitor(self, other: u16) -> u16 { self | other } } +impl BitOr for u8 { fn bitor(self, other: u8) -> u8 { self | other } } + +impl BitOr for i8 { fn bitor(self, other: i8) -> i8 { self | other } } +impl BitOr for i16 { fn bitor(self, other: i16) -> i16 { self | other } } +impl BitOr for i32 { fn bitor(self, other: i32) -> i32 { self | other } } +impl BitOr for i64 { fn bitor(self, other: i64) -> i64 { self | other } } + +// docs:start:bitand-trait +trait BitAnd { + fn bitand(self, other: Self) -> Self; +} +// docs:end:bitand-trait + +impl BitAnd for bool { fn bitand(self, other: bool) -> bool { self & other } } + +impl BitAnd for u64 { fn bitand(self, other: u64) -> u64 { self & other } } +impl BitAnd for u32 { fn bitand(self, other: u32) -> u32 { self & other } } +impl BitAnd for u16 { fn bitand(self, other: u16) -> u16 { self & other } } +impl BitAnd for u8 { fn bitand(self, other: u8) -> u8 { self & other } } + +impl BitAnd for i8 { fn bitand(self, other: i8) -> i8 { self & other } } +impl BitAnd for i16 { fn bitand(self, other: i16) -> i16 { self & other } } +impl BitAnd for i32 { fn bitand(self, other: i32) -> i32 { self & other } } +impl BitAnd for i64 { fn bitand(self, other: i64) -> i64 { self & other } } + +// docs:start:bitxor-trait +trait BitXor { + fn bitxor(self, other: Self) -> Self; +} +// docs:end:bitxor-trait + +impl BitXor for bool { fn bitxor(self, other: bool) -> bool { self ^ other } } + +impl BitXor for u64 { fn bitxor(self, other: u64) -> u64 { self ^ other } } +impl BitXor for u32 { fn bitxor(self, other: u32) -> u32 { self ^ other } } +impl BitXor for u16 { fn bitxor(self, other: u16) -> u16 { self ^ other } } +impl BitXor for u8 { fn bitxor(self, other: u8) -> u8 { self ^ other } } + +impl BitXor for i8 { fn bitxor(self, other: i8) -> i8 { self ^ other } } +impl BitXor for i16 { fn bitxor(self, other: i16) -> i16 { self ^ other } } +impl BitXor for i32 { fn bitxor(self, other: i32) -> i32 { self ^ other } } +impl BitXor for i64 { fn bitxor(self, other: i64) -> i64 { self ^ other } } + +// docs:start:shl-trait +trait Shl { + fn shl(self, other: u8) -> Self; +} +// docs:end:shl-trait + +impl Shl for u32 { fn shl(self, other: u8) -> u32 { self << other } } +impl Shl for u64 { fn shl(self, other: u8) -> u64 { self << other } } +impl Shl for u16 { fn shl(self, other: u8) -> u16 { self << other } } +impl Shl for u8 { fn shl(self, other: u8) -> u8 { self << other } } +impl Shl for u1 { fn shl(self, other: u8) -> u1 { self << other } } + +impl Shl for i8 { fn shl(self, other: u8) -> i8 { self << other } } +impl Shl for i16 { fn shl(self, other: u8) -> i16 { self << other } } +impl Shl for i32 { fn shl(self, other: u8) -> i32 { self << other } } +impl Shl for i64 { fn shl(self, other: u8) -> i64 { self << other } } + +// docs:start:shr-trait +trait Shr { + fn shr(self, other: u8) -> Self; +} +// docs:end:shr-trait + +impl Shr for u64 { fn shr(self, other: u8) -> u64 { self >> other } } +impl Shr for u32 { fn shr(self, other: u8) -> u32 { self >> other } } +impl Shr for u16 { fn shr(self, other: u8) -> u16 { self >> other } } +impl Shr for u8 { fn shr(self, other: u8) -> u8 { self >> other } } +impl Shr for u1 { fn shr(self, other: u8) -> u1 { self >> other } } + +impl Shr for i8 { fn shr(self, other: u8) -> i8 { self >> other } } +impl Shr for i16 { fn shr(self, other: u8) -> i16 { self >> other } } +impl Shr for i32 { fn shr(self, other: u8) -> i32 { self >> other } } +impl Shr for i64 { fn shr(self, other: u8) -> i64 { self >> other } } + diff --git a/noir_stdlib/src/option.nr b/noir_stdlib/src/option.nr index 8029e4f68d8..995230e887c 100644 --- a/noir_stdlib/src/option.nr +++ b/noir_stdlib/src/option.nr @@ -1,3 +1,7 @@ +use crate::hash::{Hash, Hasher}; +use crate::cmp::{Ordering, Ord, Eq}; +use crate::default::Default; + struct Option { _is_some: bool, _value: T, @@ -152,3 +156,51 @@ impl Option { } } } + +impl Default for Option { + fn default() -> Self { + Option::none() + } +} + +impl Eq for Option where T: Eq { + fn eq(self, other: Self) -> bool { + if self._is_some == other._is_some { + if self._is_some { + self._value == other._value + } else { + true + } + } else { + false + } + } +} + +impl Hash for Option where T: Hash { + fn hash(self, state: &mut H) where H: Hasher { + self._is_some.hash(state); + if self._is_some { + self._value.hash(state); + } + } +} + +// For this impl we're declaring Option::none < Option::some +impl Ord for Option where T: Ord { + fn cmp(self, other: Self) -> Ordering { + if self._is_some { + if other._is_some { + self._value.cmp(other._value) + } else { + Ordering::greater() + } + } else { + if other._is_some { + Ordering::less() + } else { + Ordering::equal() + } + } + } +} diff --git a/noir_stdlib/src/runtime.nr b/noir_stdlib/src/runtime.nr new file mode 100644 index 00000000000..c075107cd52 --- /dev/null +++ b/noir_stdlib/src/runtime.nr @@ -0,0 +1,2 @@ +#[builtin(is_unconstrained)] +pub fn is_unconstrained() -> bool {} diff --git a/noir_stdlib/src/scalar_mul.nr b/noir_stdlib/src/scalar_mul.nr deleted file mode 100644 index eee7aac39f2..00000000000 --- a/noir_stdlib/src/scalar_mul.nr +++ /dev/null @@ -1,45 +0,0 @@ -use crate::ops::Add; - -struct EmbeddedCurvePoint { - x: Field, - y: Field, -} - -impl EmbeddedCurvePoint { - fn double(self) -> EmbeddedCurvePoint { - embedded_curve_add(self, self) - } -} - -impl Add for EmbeddedCurvePoint { - fn add(self, other: EmbeddedCurvePoint) -> EmbeddedCurvePoint { - embedded_curve_add(self, other) - } -} - -// Computes a fixed base scalar multiplication over the embedded curve. -// For bn254, We have Grumpkin and Baby JubJub. -// For bls12-381, we have JubJub and Bandersnatch. -// -// The embedded curve being used is decided by the -// underlying proof system. -#[foreign(fixed_base_scalar_mul)] -// docs:start:fixed_base_embedded_curve -pub fn fixed_base_embedded_curve( - low: Field, - high: Field -) -> [Field; 2] -// docs:end:fixed_base_embedded_curve -{} - -// This is a hack as returning an `EmbeddedCurvePoint` from a foreign function in brillig returns a [BrilligVariable::SingleAddr; 2] rather than BrilligVariable::BrilligArray -// as is defined in the brillig bytecode format. This is a workaround which allows us to fix this without modifying the serialization format. -fn embedded_curve_add(point1: EmbeddedCurvePoint, point2: EmbeddedCurvePoint) -> EmbeddedCurvePoint { - let point_array = embedded_curve_add_array_return(point1, point2); - let x = point_array[0]; - let y = point_array[1]; - EmbeddedCurvePoint { x, y } -} - -#[foreign(embedded_curve_add)] -fn embedded_curve_add_array_return(_point1: EmbeddedCurvePoint, _point2: EmbeddedCurvePoint) -> [Field; 2] {} diff --git a/noir_stdlib/src/schnorr.nr b/noir_stdlib/src/schnorr.nr index 757963d40d7..c63915061cb 100644 --- a/noir_stdlib/src/schnorr.nr +++ b/noir_stdlib/src/schnorr.nr @@ -8,3 +8,15 @@ pub fn verify_signature( ) -> bool // docs:end:schnorr_verify {} + +#[foreign(schnorr_verify)] +// docs:start:schnorr_verify_slice +pub fn verify_signature_slice( + public_key_x: Field, + public_key_y: Field, + signature: [u8; 64], + message: [u8] +) -> bool +// docs:end:schnorr_verify_slice +{} + diff --git a/noir_stdlib/src/sha256.nr b/noir_stdlib/src/sha256.nr index 2f686a64165..d856043fcfa 100644 --- a/noir_stdlib/src/sha256.nr +++ b/noir_stdlib/src/sha256.nr @@ -6,33 +6,58 @@ fn msg_u8_to_u32(msg: [u8; 64]) -> [u32; 16] { let mut msg32: [u32; 16] = [0; 16]; for i in 0..16 { + let mut msg_field: Field = 0; for j in 0..4 { - msg32[15 - i] = (msg32[15 - i] << 8) + msg[64 - 4*(i + 1) + j] as u32; + msg_field = msg_field * 256 + msg[64 - 4*(i + 1) + j] as Field; } + msg32[15 - i] = msg_field as u32; } msg32 } // SHA-256 hash function pub fn digest(msg: [u8; N]) -> [u8; 32] { + sha256_var(msg, N) +} + +fn hash_final_block(msg_block: [u8; 64], mut state: [u32; 8]) -> [u8; 32] { + let mut out_h: [u8; 32] = [0; 32]; // Digest as sequence of bytes + + // Hash final padded block + state = crate::hash::sha256_compression(msg_u8_to_u32(msg_block), state); + + // Return final hash as byte array + for j in 0..8 { + let h_bytes = (state[7 - j] as Field).to_le_bytes(4); + for k in 0..4 { + out_h[31 - 4*j - k] = h_bytes[k]; + } + } + + out_h +} + +// Variable size SHA-256 hash +pub fn sha256_var(msg: [u8; N], message_size: u64) -> [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 out_h: [u8; 32] = [0; 32]; // Digest as sequence of bytes let mut i: u64 = 0; // Message byte pointer for k in 0..N { - // Populate msg_block - msg_block[i as Field] = msg[k]; - i = i + 1; - if i == 64 { - // Enough to hash block - h = crate::hash::sha256_compression(msg_u8_to_u32(msg_block), h); + if k < message_size { + // Populate msg_block + msg_block[i] = msg[k]; + i = i + 1; + if i == 64 { + // Enough to hash block + h = crate::hash::sha256_compression(msg_u8_to_u32(msg_block), h); - i = 0; + 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; + msg_block[i] = 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. @@ -41,7 +66,7 @@ pub fn digest(msg: [u8; N]) -> [u8; 32] { if i < 64 { for _i in 57..64 { if i <= 63 { - msg_block[i as Field] = 0; + msg_block[i] = 0; i += 1; } } @@ -51,30 +76,19 @@ pub fn digest(msg: [u8; N]) -> [u8; 32] { i = 0; } + let len = 8 * message_size; + let len_bytes = (len as Field).to_le_bytes(8); 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; + msg_block[i] = 0; i = i + 1; } else if i < 64 { - let mut len = 8 * msg.len(); for j in 0..8 { - msg_block[63 - j] = len as u8; - len >>= 8; + msg_block[63 - j] = len_bytes[j]; } i += 8; } } - // Hash final padded block - h = crate::hash::sha256_compression(msg_u8_to_u32(msg_block), h); - - // Return final hash as byte array - for j in 0..8 { - for k in 0..4 { - out_h[31 - 4*j - k] = h[7 - j] as u8; - h[7-j] >>= 8; - } - } - - out_h + hash_final_block(msg_block, h) } diff --git a/noir_stdlib/src/sha512.nr b/noir_stdlib/src/sha512.nr index 4dfe78308e2..0f8ffcfcb1c 100644 --- a/noir_stdlib/src/sha512.nr +++ b/noir_stdlib/src/sha512.nr @@ -2,7 +2,7 @@ // 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 +fn rotr64(a: u64, b: u8) -> 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. @@ -77,9 +77,11 @@ fn msg_u8_to_u64(msg: [u8; 128]) -> [u64; 16] { let mut msg64: [u64; 16] = [0; 16]; for i in 0..16 { + let mut msg_field: Field = 0; for j in 0..8 { - msg64[15 - i] = (msg64[15 - i] << 8) + msg[128 - 8*(i + 1) + j] as u64; + msg_field = msg_field * 256 + msg[128 - 8*(i + 1) + j] as Field; } + msg64[15 - i] = msg_field as u64; } msg64 @@ -94,7 +96,7 @@ pub fn digest(msg: [u8; N]) -> [u8; 64] { let mut i: u64 = 0; // Message byte pointer for k in 0..msg.len() { // Populate msg_block - msg_block[i as Field] = msg[k]; + msg_block[i] = msg[k]; i = i + 1; if i == 128 { // Enough to hash block @@ -108,7 +110,7 @@ pub fn digest(msg: [u8; N]) -> [u8; 64] { } // 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; + msg_block[i] = 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. @@ -117,7 +119,7 @@ pub fn digest(msg: [u8; N]) -> [u8; 64] { if i < 128 { for _i in 113..128 { if i <= 127 { - msg_block[i as Field] = 0; + msg_block[i] = 0; i += 1; } } @@ -130,16 +132,16 @@ pub fn digest(msg: [u8; N]) -> [u8; 64] { i = 0; } + let len = 8 * msg.len(); + let len_bytes = (len as Field).to_le_bytes(16); 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; + msg_block[i] = 0; i += 1; } else if i < 128 { - let mut len = 8 * msg.len(); for j in 0..16 { - msg_block[127 - j] = len as u8; - len >>= 8; + msg_block[127 - j] = len_bytes[j]; } i += 16; // Done. } @@ -151,9 +153,9 @@ pub fn digest(msg: [u8; N]) -> [u8; 64] { } // Return final hash as byte array for j in 0..8 { + let h_bytes = (h[7 - j] as Field).to_le_bytes(8); for k in 0..8 { - out_h[63 - 8*j - k] = h[7 - j] as u8; - h[7-j] >>= 8; + out_h[63 - 8*j - k] = h_bytes[k]; } } diff --git a/noir_stdlib/src/slice.nr b/noir_stdlib/src/slice.nr index ea8d09d14ce..3e93c762ef2 100644 --- a/noir_stdlib/src/slice.nr +++ b/noir_stdlib/src/slice.nr @@ -1,4 +1,7 @@ impl [T] { + #[builtin(array_len)] + pub fn len(self) -> u32 {} + /// Push a new element to the end of the slice, returning a /// new slice with a length one greater than the /// original unmodified slice. @@ -24,13 +27,13 @@ impl [T] { /// Insert an element at a specified index, shifting all elements /// after it to the right #[builtin(slice_insert)] - pub fn insert(self, index: u64, elem: T) -> Self {} + pub fn insert(self, index: u32, elem: T) -> Self {} /// Remove an element at a specified index, shifting all elements /// after it to the left, returning the altered slice and /// the removed element #[builtin(slice_remove)] - pub fn remove(self, index: u64) -> (Self, T) {} + pub fn remove(self, index: u32) -> (Self, T) {} // Append each element of the `other` slice to the end of `self`. // This returns a new slice and leaves both input slices unchanged. @@ -40,4 +43,14 @@ impl [T] { } self } + + pub fn as_array(self) -> [T; N] { + assert(self.len() == N); + + let mut array = [crate::unsafe_func::zeroed(); N]; + for i in 0..N { + array[i] = self[i]; + } + array + } } diff --git a/noir_stdlib/src/test.nr b/noir_stdlib/src/test.nr index e1c320215de..e6a7e03fefc 100644 --- a/noir_stdlib/src/test.nr +++ b/noir_stdlib/src/test.nr @@ -4,6 +4,9 @@ unconstrained fn create_mock_oracle(name: str) -> Field {} #[oracle(set_mock_params)] unconstrained fn set_mock_params_oracle

(id: Field, params: P) {} +#[oracle(get_mock_last_params)] +unconstrained fn get_mock_last_params_oracle

(id: Field) -> P {} + #[oracle(set_mock_returns)] unconstrained fn set_mock_returns_oracle(id: Field, returns: R) {} @@ -27,6 +30,10 @@ impl OracleMock { self } + unconstrained pub fn get_last_params

(self) -> P { + get_mock_last_params_oracle(self.id) + } + unconstrained pub fn returns(self, returns: R) -> Self { set_mock_returns_oracle(self.id, returns); self diff --git a/noir_stdlib/src/uint128.nr b/noir_stdlib/src/uint128.nr index c65f83dcb44..e5b98765778 100644 --- a/noir_stdlib/src/uint128.nr +++ b/noir_stdlib/src/uint128.nr @@ -1,8 +1,9 @@ -use crate::ops::{Add, Sub, Mul, Div, Rem, BitOr, BitAnd, BitXor, Shl, Shr}; +use crate::ops::{Add, Sub, Mul, Div, Rem, Not, BitOr, BitAnd, BitXor, Shl, Shr}; use crate::cmp::{Eq, Ord, Ordering}; +use crate::println; global pow64 : Field = 18446744073709551616; //2^64; - +global pow63 : Field = 9223372036854775808; // 2^63; struct U128 { lo: Field, hi: Field, @@ -20,6 +21,13 @@ impl U128 { U128::from_u64s_le(lo, hi) } + pub fn zero() -> U128 { + U128 { lo: 0, hi: 0 } + } + + pub fn one() -> U128 { + U128 { lo: 1, hi: 0 } + } pub fn from_le_bytes(bytes: [u8; 16]) -> U128 { let mut lo = 0; let mut base = 1; @@ -87,27 +95,46 @@ impl U128 { U128 { lo: lo as Field, hi: hi as Field } } + unconstrained fn uconstrained_check_is_upper_ascii(ascii: u8) -> bool { + ((ascii >= 65) & (ascii <= 90)) // Between 'A' and 'Z' + } + fn decode_ascii(ascii: u8) -> Field { if ascii < 58 { ascii - 48 - } else if ascii < 71 { - ascii - 55 } else { - ascii - 87 + unsafe { + let ascii = ascii + 32 * (U128::uconstrained_check_is_upper_ascii(ascii) as u8); + assert(ascii >= 97); // enforce >= 'a' + assert(ascii <= 102); // enforce <= 'f' + ascii - 87 + } } as Field } + // TODO: Replace with a faster version. + // A circuit that uses this function can be slow to compute + // (we're doing up to 127 calls to compute the quotient) unconstrained fn unconstrained_div(self: Self, b: U128) -> (U128, U128) { - if self < b { - (U128::from_u64s_le(0, 0), self) + if b == U128::zero() { + // Return 0,0 to avoid eternal loop + (U128::zero(), U128::zero()) + } else if self < b { + (U128::zero(), self) + } else if self == b { + (U128::one(), U128::zero()) } else { - //TODO check if this can overflow? - let (q,r) = self.unconstrained_div(b * U128::from_u64s_le(2, 0)); + let (q,r) = if b.hi as u64 >= pow63 as u64 { + // The result of multiplication by 2 would overflow + (U128::zero(), self) + } else { + self.unconstrained_div(b * U128::from_u64s_le(2, 0)) + }; let q_mul_2 = q * U128::from_u64s_le(2, 0); if r < b { (q_mul_2, r) } else { - (q_mul_2 + U128::from_u64s_le(1, 0), r - b) + (q_mul_2 + U128::one(), r - b) } } } @@ -129,11 +156,7 @@ impl U128 { let low = self.lo * b.lo; let lo = low as u64 as Field; let carry = (low - lo) / pow64; - let high = if crate::field::modulus_num_bits() as u32 > 196 { - (self.lo + self.hi) * (b.lo + b.hi) - low + carry - } else { - self.lo * b.hi + self.hi * b.lo + carry - }; + let high = self.lo * b.hi + self.hi * b.lo + carry; let hi = high as u64 as Field; U128 { lo, hi } } @@ -233,11 +256,20 @@ impl Ord for U128 { } } +impl Not for U128 { + fn not(self) -> U128 { + U128 { + lo: (!(self.lo as u64)) as Field, + hi: (!(self.hi as u64)) as Field + } + } +} + impl BitOr for U128 { fn bitor(self, other: U128) -> U128 { U128 { lo: ((self.lo as u64) | (other.lo as u64)) as Field, - hi: ((self.hi as u64) | (other.hi as u64))as Field + hi: ((self.hi as u64) | (other.hi as u64)) as Field } } } @@ -261,9 +293,9 @@ impl BitXor for U128 { } impl Shl for U128 { - fn shl(self, other: U128) -> U128 { - assert(other < U128::from_u64s_le(128,0), "attempt to shift left with overflow"); - let exp_bits = other.lo.to_be_bits(7); + fn shl(self, other: u8) -> U128 { + assert(other < 128, "attempt to shift left with overflow"); + let exp_bits = (other as Field).to_be_bits(7); let mut r: Field = 2; let mut y: Field = 1; @@ -276,9 +308,9 @@ impl Shl for U128 { } impl Shr for U128 { - fn shr(self, other: U128) -> U128 { - assert(other < U128::from_u64s_le(128,0), "attempt to shift right with overflow"); - let exp_bits = other.lo.to_be_bits(7); + fn shr(self, other: u8) -> U128 { + assert(other < 128, "attempt to shift right with overflow"); + let exp_bits = (other as Field).to_be_bits(7); let mut r: Field = 2; let mut y: Field = 1; @@ -289,3 +321,222 @@ impl Shr for U128 { self / U128::from_integer(y) } } + +mod tests { + use crate::uint128::{U128, pow64, pow63}; + + #[test] + fn test_not() { + let num = U128::from_u64s_le(0, 0); + let not_num = num.not(); + + let max_u64: Field = pow64 - 1; + assert_eq(not_num.hi, max_u64); + assert_eq(not_num.lo, max_u64); + + let not_not_num = not_num.not(); + assert_eq(num, not_not_num); + } + #[test] + fn test_construction() { + // Check little-endian u64 is inversed with big-endian u64 construction + let a = U128::from_u64s_le(2, 1); + let b = U128::from_u64s_be(1, 2); + assert_eq(a, b); + // Check byte construction is equivalent + let c = U128::from_le_bytes([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]); + let d = U128::from_u64s_le(0x0706050403020100, 0x0f0e0d0c0b0a0908); + assert_eq(c, d); + } + #[test] + fn test_byte_decomposition() { + let a = U128::from_u64s_le(0x0706050403020100, 0x0f0e0d0c0b0a0908); + // Get big-endian and little-endian byte decompostions + let le_bytes_a= a.to_le_bytes(); + let be_bytes_a= a.to_be_bytes(); + + // Check equivalence + for i in 0..16 { + assert_eq(le_bytes_a[i], be_bytes_a[15 - i]); + } + // Reconstruct U128 from byte decomposition + let b= U128::from_le_bytes(le_bytes_a); + // Check that it's the same element + assert_eq(a, b); + } + #[test] + fn test_hex_constuction() { + let a = U128::from_u64s_le(0x1, 0x2); + let b = U128::from_hex("0x20000000000000001"); + assert_eq(a, b); + + let c= U128::from_hex("0xffffffffffffffffffffffffffffffff"); + let d= U128::from_u64s_le(0xffffffffffffffff, 0xffffffffffffffff); + assert_eq(c, d); + + let e= U128::from_hex("0x00000000000000000000000000000000"); + let f= U128::from_u64s_le(0, 0); + assert_eq(e, f); + } + + // Ascii decode tests + + #[test] + fn test_ascii_decode_correct_range() { + // '0'..'9' range + for i in 0..10 { + let decoded= U128::decode_ascii(48 + i); + assert_eq(decoded, i as Field); + } + // 'A'..'F' range + for i in 0..6 { + let decoded = U128::decode_ascii(65 + i); + assert_eq(decoded, (i + 10) as Field); + } + // 'a'..'f' range + for i in 0..6 { + let decoded = U128::decode_ascii(97 + i); + assert_eq(decoded, (i + 10) as Field); + } + } + + #[test(should_fail)] + fn test_ascii_decode_range_less_than_48_fails_0() { + crate::println(U128::decode_ascii(0)); + } + #[test(should_fail)] + fn test_ascii_decode_range_less_than_48_fails_1() { + crate::println(U128::decode_ascii(47)); + } + + #[test(should_fail)] + fn test_ascii_decode_range_58_64_fails_0() { + let _ = U128::decode_ascii(58); + } + #[test(should_fail)] + fn test_ascii_decode_range_58_64_fails_1() { + let _ = U128::decode_ascii(64); + } + #[test(should_fail)] + fn test_ascii_decode_range_71_96_fails_0() { + let _ = U128::decode_ascii(71); + } + #[test(should_fail)] + fn test_ascii_decode_range_71_96_fails_1() { + let _ = U128::decode_ascii(96); + } + #[test(should_fail)] + fn test_ascii_decode_range_greater_than_102_fails() { + let _ = U128::decode_ascii(103); + } + + #[test(should_fail)] + fn test_ascii_decode_regression() { + // This code will actually fail because of ascii_decode, + // but in the past it was possible to create a value > (1<<128) + let a = U128::from_hex("0x~fffffffffffffffffffffffffffffff"); + let b:Field= a.to_integer(); + let c= b.to_le_bytes(17); + assert(c[16] != 0); + } + + #[test] + fn test_unconstrained_div() { + // Test the potential overflow case + let a= U128::from_u64s_le(0x0, 0xffffffffffffffff); + let b= U128::from_u64s_le(0x0, 0xfffffffffffffffe); + let c= U128::one(); + let d= U128::from_u64s_le(0x0, 0x1); + unsafe { + let (q,r) = a.unconstrained_div(b); + assert_eq(q, c); + assert_eq(r, d); + } + + let a = U128::from_u64s_le(2, 0); + let b = U128::one(); + // Check the case where a is a multiple of b + unsafe { + let (c, d) = a.unconstrained_div(b); + assert_eq((c, d), (a, U128::zero())); + } + + // Check where b is a multiple of a + unsafe { + let (c,d) = b.unconstrained_div(a); + assert_eq((c, d), (U128::zero(), b)); + } + + // Dividing by zero returns 0,0 + let a = U128::from_u64s_le(0x1, 0x0); + let b = U128::zero(); + unsafe { + let (c, d)= a.unconstrained_div(b); + assert_eq((c, d), (U128::zero(), U128::zero())); + } + // Dividing 1<<127 by 1<<127 (special case) + let a = U128::from_u64s_le(0x0, pow63 as u64); + let b = U128::from_u64s_le(0x0, pow63 as u64); + unsafe { + let (c, d) = a.unconstrained_div(b); + assert_eq((c, d), (U128::one(), U128::zero())); + } + } + + #[test] + fn integer_conversions() { + // Maximum + let start:Field = 0xffffffffffffffffffffffffffffffff; + let a = U128::from_integer(start); + let end = a.to_integer(); + assert_eq(start, end); + + // Minimum + let start:Field = 0x0; + let a = U128::from_integer(start); + let end = a.to_integer(); + assert_eq(start, end); + + // Low limb + let start:Field = 0xffffffffffffffff; + let a = U128::from_integer(start); + let end = a.to_integer(); + assert_eq(start, end); + + // High limb + let start:Field = 0xffffffffffffffff0000000000000000; + let a = U128::from_integer(start); + let end = a.to_integer(); + assert_eq(start, end); + } + #[test] + fn test_wrapping_mul() { + // 1*0==0 + assert_eq(U128::zero(), U128::zero().wrapping_mul(U128::one())); + + // 0*1==0 + assert_eq(U128::zero(), U128::one().wrapping_mul(U128::zero())); + + // 1*1==1 + assert_eq(U128::one(), U128::one().wrapping_mul(U128::one())); + + // 0 * ( 1 << 64 ) == 0 + assert_eq(U128::zero(), U128::zero().wrapping_mul(U128::from_u64s_le(0, 1))); + + // ( 1 << 64 ) * 0 == 0 + assert_eq(U128::zero(), U128::from_u64s_le(0, 1).wrapping_mul(U128::zero())); + + // 1 * ( 1 << 64 ) == 1 << 64 + assert_eq(U128::from_u64s_le(0, 1), U128::from_u64s_le(0, 1).wrapping_mul(U128::one())); + + // ( 1 << 64 ) * 1 == 1 << 64 + assert_eq(U128::from_u64s_le(0, 1), U128::one().wrapping_mul(U128::from_u64s_le(0, 1))); + + // ( 1 << 64 ) * ( 1 << 64 ) == 1 << 64 + assert_eq(U128::zero(), U128::from_u64s_le(0, 1).wrapping_mul(U128::from_u64s_le(0, 1))); + // -1 * -1 == 1 + assert_eq( + U128::one(), U128::from_u64s_le(0xffffffffffffffff, 0xffffffffffffffff).wrapping_mul(U128::from_u64s_le(0xffffffffffffffff, 0xffffffffffffffff)) + ); + } +} diff --git a/noirc_macros/Cargo.toml b/noirc_macros/Cargo.toml deleted file mode 100644 index 699e6b01cae..00000000000 --- a/noirc_macros/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -name = "noirc_macros" -version.workspace = true -authors.workspace = true -edition.workspace = true -rust-version.workspace = true -license.workspace = true -repository.workspace = true - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -noirc_frontend.workspace = true -iter-extended.workspace = true \ No newline at end of file diff --git a/noirc_macros/src/lib.rs b/noirc_macros/src/lib.rs deleted file mode 100644 index 9a916843200..00000000000 --- a/noirc_macros/src/lib.rs +++ /dev/null @@ -1,73 +0,0 @@ -use noirc_frontend::hir::def_collector::dc_crate::UnresolvedFunctions; -use noirc_frontend::hir::def_collector::dc_crate::UnresolvedTraitImpl; -use noirc_frontend::macros_api::parse_program; -use noirc_frontend::macros_api::HirContext; -use noirc_frontend::macros_api::SortedModule; -use noirc_frontend::macros_api::{CrateId, FileId}; -use noirc_frontend::macros_api::{MacroError, MacroProcessor}; - -pub struct AssertMessageMacro; - -impl MacroProcessor for AssertMessageMacro { - fn process_untyped_ast( - &self, - ast: SortedModule, - crate_id: &CrateId, - _context: &HirContext, - ) -> Result { - transform(ast, crate_id) - } - - fn process_unresolved_traits_impls( - &self, - _crate_id: &CrateId, - _context: &mut HirContext, - _unresolved_traits_impls: &[UnresolvedTraitImpl], - _collected_functions: &mut Vec, - ) -> Result<(), (MacroError, FileId)> { - Ok(()) - } - - // This macro does not need to process any information after name resolution - fn process_typed_ast( - &self, - _crate_id: &CrateId, - _context: &mut HirContext, - ) -> Result<(), (MacroError, FileId)> { - Ok(()) - } -} - -fn transform(ast: SortedModule, crate_id: &CrateId) -> Result { - let ast = add_resolve_assert_message_funcs(ast, crate_id)?; - - Ok(ast) -} - -fn add_resolve_assert_message_funcs( - mut ast: SortedModule, - crate_id: &CrateId, -) -> Result { - if !crate_id.is_stdlib() { - return Ok(ast); - } - let assert_message_oracles = " - #[oracle(assert_message)] - unconstrained fn assert_message_oracle(_input: T) {} - unconstrained pub fn resolve_assert_message(input: T, condition: bool) { - if !condition { - assert_message_oracle(input); - } - }"; - - let (assert_msg_funcs_ast, errors) = parse_program(assert_message_oracles); - assert_eq!(errors.len(), 0, "Failed to parse Noir macro code. This is either a bug in the compiler or the Noir macro code"); - - let assert_msg_funcs_ast = assert_msg_funcs_ast.into_sorted(); - - for func in assert_msg_funcs_ast.functions { - ast.functions.push(func) - } - - Ok(ast) -} diff --git a/package.json b/package.json index f460b3db711..8abaced7bdd 100644 --- a/package.json +++ b/package.json @@ -13,37 +13,30 @@ "docs" ], "scripts": { - "build": "yarn workspaces foreach --parallel --topological-dev --verbose run build", - "test": "yarn workspaces foreach run test", + "build": "yarn workspaces foreach -vp --topological-dev --exclude \"{docs,@noir-lang/root}\" run build", + "test": "yarn workspaces foreach --parallel --verbose run test", "test:integration": "yarn workspace integration-tests test", "clean:workspaces": "yarn workspaces foreach --exclude @noir-lang/root run clean", - "clean:root": "rm -rf ./result ./target ./packages", + "clean:root": "rm -rf ./target ./packages", "clean": "yarn clean:workspaces && yarn clean:root", "lint": "yarn workspaces foreach --verbose run lint", "spellcheck": "cspell '**/*.{md,rs}' -c ./cspell.json", - "install:acvm_js": "yarn workspace @noir-lang/acvm_js run install:from:nix", - "install:noir_wasm": "yarn workspace @noir-lang/noir_wasm run install:from:nix", - "install:noirc_abi_wasm": "yarn workspace @noir-lang/noirc_abi run install:from:nix", - "install:from:nix": "yarn install:acvm_js && yarn install:noir_wasm && yarn install:noirc_abi_wasm", - "build:types": "yarn workspace @noir-lang/types run build", - "build:backend_barretenberg": "yarn workspace @noir-lang/backend_barretenberg run build", - "build:noir_js": "yarn workspace @noir-lang/noir_js run build", - "build:js:only": "yarn build:types && yarn build:backend_barretenberg && yarn build:noir_js", - "prepare:publish": "yarn clean && yarn install:from:nix && yarn build:js:only", + "prepare:publish": "yarn clean && yarn build", + "build:js:only": "yarn workspaces foreach -vtp --exclude \"{@noir-lang/acvm_js,@noir-lang/noirc_abi,@noir-lang/noir_wasm,docs,@noir-lang/root}\" run build", "nightly:version": "yarn workspaces foreach run nightly:version", "publish:all": "yarn install && yarn workspaces foreach run publish" }, "devDependencies": { "@typescript-eslint/eslint-plugin": "^6.7.3", "@typescript-eslint/parser": "^6.7.3", - "chai": "^4.3.7", + "chai": "^4.4.1", "cspell": "^8.3.2", - "eslint": "^8.56.0", - "eslint-plugin-prettier": "^5.0.0", + "eslint": "^8.57.0", + "eslint-plugin-prettier": "^5.1.3", "mocha": "^10.2.0", - "prettier": "3.0.3", + "prettier": "3.2.5", "ts-node": "^10.9.1", - "typescript": "^5.0.4" + "typescript": "^5.4.2" }, "packageManager": "yarn@3.6.4" } diff --git a/release-please-config.json b/release-please-config.json index e73993ca974..0ba192754a0 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -13,7 +13,6 @@ "include-component-in-tag": false, "extra-files": [ "Cargo.toml", - "flake.nix", { "type": "json", "path": "compiler/wasm/package.json", @@ -61,8 +60,8 @@ "acir_field/Cargo.toml", "acvm/Cargo.toml", "acvm_js/Cargo.toml", - "barretenberg_blackbox_solver/Cargo.toml", "blackbox_solver/Cargo.toml", + "bn254_blackbox_solver/Cargo.toml", "brillig/Cargo.toml", "brillig_vm/Cargo.toml", { @@ -82,4 +81,4 @@ "sentence-case" ], "bootstrap-sha": "690cfc0468de0b9aee53ccfe832c71c16e61e5fc" -} \ No newline at end of file +} diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 0e5ac891ce9..fe2949c8458 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,5 +1,5 @@ [toolchain] -channel = "1.73.0" +channel = "1.74.1" components = [ "rust-src" ] targets = [ "wasm32-unknown-unknown", "wasm32-wasi", "aarch64-apple-darwin" ] profile = "default" diff --git a/scripts/benchmark_start.sh b/scripts/benchmark_start.sh new file mode 100755 index 00000000000..3e69b3d2c65 --- /dev/null +++ b/scripts/benchmark_start.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +echo -1 | sudo tee /proc/sys/kernel/perf_event_paranoid diff --git a/scripts/benchmark_stop.sh b/scripts/benchmark_stop.sh new file mode 100755 index 00000000000..964e5291817 --- /dev/null +++ b/scripts/benchmark_stop.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +echo 4 | sudo tee /proc/sys/kernel/perf_event_paranoid diff --git a/scripts/bootstrap_native.sh b/scripts/bootstrap_native.sh deleted file mode 100755 index 974f0edcfec..00000000000 --- a/scripts/bootstrap_native.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env bash -set -eu - -cd $(dirname "$0")/.. - -# If this project has been subrepod into another project, set build data manually. -export SOURCE_DATE_EPOCH=$(date +%s) -export GIT_DIRTY=false -if [ -f ".gitrepo" ]; then - export GIT_COMMIT=$(awk '/commit =/ {print $3}' .gitrepo) -else - export GIT_COMMIT=$(git rev-parse --verify HEAD) -fi - -# Check if the 'cargo' command is available in the system -if ! command -v cargo > /dev/null; then - echo "Cargo is not installed. Please install Cargo and the Rust toolchain." - exit 1 -fi - -# Build native. -if [ -n "${DEBUG:-}" ]; then - cargo build -else - cargo build --release -fi diff --git a/scripts/bootstrap_packages.sh b/scripts/bootstrap_packages.sh deleted file mode 100755 index 47ffe12beec..00000000000 --- a/scripts/bootstrap_packages.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env bash -set -eu - -cd $(dirname "$0")/.. - -./.github/scripts/wasm-bindgen-install.sh - -# If this project has been subrepod into another project, set build data manually. -export SOURCE_DATE_EPOCH=$(date +%s) -export GIT_DIRTY=false -if [ -f ".gitrepo" ]; then - export GIT_COMMIT=$(awk '/commit =/ {print $3}' .gitrepo) -else - export GIT_COMMIT=$(git rev-parse --verify HEAD) -fi - -yarn --immutable -yarn build - -# We create a folder called packages, that contains each package as it would be published to npm, named correctly. -# These can be useful for testing, or portaling into other projects. -yarn workspaces foreach pack - -rm -rf packages && mkdir -p packages -tar zxfv acvm-repo/acvm_js/package.tgz -C packages && mv packages/package packages/acvm_js -tar zxfv compiler/wasm/package.tgz -C packages && mv packages/package packages/noir_wasm -tar zxfv tooling/noir_codegen/package.tgz -C packages && mv packages/package packages/noir_codegen -tar zxfv tooling/noir_js/package.tgz -C packages && mv packages/package packages/noir_js -tar zxfv tooling/noir_js_backend_barretenberg/package.tgz -C packages && mv packages/package packages/backend_barretenberg -tar zxfv tooling/noir_js_types/package.tgz -C packages && mv packages/package packages/types -tar zxfv tooling/noirc_abi_wasm/package.tgz -C packages && mv packages/package packages/noirc_abi diff --git a/scripts/count_loc.sh b/scripts/count_loc.sh new file mode 100755 index 00000000000..91565aa6c4a --- /dev/null +++ b/scripts/count_loc.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash +set -eu + +# Run relative to repo root +cd $(dirname "$0")/../ + +if ! command -v "tokei" >/dev/null 2>&1; then + echo "Error: tokei is required but not installed." >&2 + echo "Error: Run \`cargo install --git https://github.com/TomAFrench/tokei --branch tf/add-noir-support tokei\`" >&2 + + exit 1 +fi + +echo "" +echo "Total:" + +tokei ./ --sort code + +echo "" +echo "ACIR/ACVM:" +tokei ./acvm-repo --sort code + +echo "" +echo "Compiler:" +tokei ./compiler --sort code + +echo "" +echo "Tooling:" +tokei ./tooling --sort code + +echo "" +echo "Standard Library:" +tokei ./noir_stdlib --sort code diff --git a/scripts/install_bb.sh b/scripts/install_bb.sh new file mode 100755 index 00000000000..c3ed476200a --- /dev/null +++ b/scripts/install_bb.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +VERSION="0.41.0" + +BBUP_PATH=~/.bb/bbup + +if ! [ -f $BBUP_PATH ]; then + curl -L https://raw.githubusercontent.com/AztecProtocol/aztec-packages/master/barretenberg/cpp/installation/install | bash +fi + +$BBUP_PATH -v $VERSION diff --git a/scripts/test_js_packages.sh b/scripts/test_js_packages.sh deleted file mode 100755 index e1e10c543e0..00000000000 --- a/scripts/test_js_packages.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/bash -set -eu - -cd $(dirname "$0")/.. - -./.github/scripts/wasm-bindgen-install.sh - -# If this project has been subrepod into another project, set build data manually. -export SOURCE_DATE_EPOCH=$(date +%s) -export GIT_DIRTY=false -if [ -f ".gitrepo" ]; then - export GIT_COMMIT=$(awk '/commit =/ {print $3}' .gitrepo) -else - export GIT_COMMIT=$(git rev-parse --verify HEAD) -fi - -cargo build --release -export PATH="${PATH}:/usr/src/noir/target/release/" - -yarn --immutable -yarn build -./.github/scripts/playwright-install.sh - -./scripts/test.sh -yarn test diff --git a/scripts/test_native.sh b/scripts/test_native.sh deleted file mode 100755 index 9b9aa0ce4d7..00000000000 --- a/scripts/test_native.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash -set -eu - -cd $(dirname "$0")/.. - -# If this project has been subrepod into another project, set build data manually. -export SOURCE_DATE_EPOCH=$(date +%s) -export GIT_DIRTY=false -if [ -f ".gitrepo" ]; then - export GIT_COMMIT=$(awk '/commit =/ {print $3}' .gitrepo) -else - export GIT_COMMIT=$(git rev-parse --verify HEAD) -fi - -cargo fmt --all --check -cargo clippy --workspace --locked --release -cargo test --workspace --locked --release diff --git a/security/insectarium/noir_stdlib.md b/security/insectarium/noir_stdlib.md new file mode 100644 index 00000000000..5ec4eb5f6cd --- /dev/null +++ b/security/insectarium/noir_stdlib.md @@ -0,0 +1,61 @@ +# Bugs found in Noir stdlib + +## U128 + +### decode_ascii +Old **decode_ascii** function didn't check that the values of individual bytes in the string were just in the range of [0-9a-f-A-F]. +```rust +fn decode_ascii(ascii: u8) -> Field { + if ascii < 58 { + ascii - 48 + } else if ascii < 71 { + ascii - 55 + } else { + ascii - 87 + } as Field +} +``` +Since the function used the assumption that decode_ascii returns values in range [0,15] to construct **lo** and **hi** it was possible to overflow these 64-bit limbs. + +### unconstrained_div +```rust + unconstrained fn unconstrained_div(self: Self, b: U128) -> (U128, U128) { + if self < b { + (U128::from_u64s_le(0, 0), self) + } else { + //TODO check if this can overflow? + let (q,r) = self.unconstrained_div(b * U128::from_u64s_le(2, 0)); + let q_mul_2 = q * U128::from_u64s_le(2, 0); + if r < b { + (q_mul_2, r) + } else { + (q_mul_2 + U128::from_u64s_le(1, 0), r - b) + } + } + } +``` +There were 2 issues in unconstrained_div: +1) Attempting to divide by zero resulted in an infinite loop, because there was no check. +2) $a >= 2^{127}$ cause the function to multiply b to such power of 2 that the result would be more than $2^{128}$ and lead to assertion failure even though it was a legitimate input + +N.B. initial fix by Rumata888 also had an edgecase missing for when a==b and b >= (1<<127). + +### wrapping_mul +```rust +fn wrapping_mul(self: Self, b: U128) -> U128 { + let low = self.lo * b.lo; + let lo = low as u64 as Field; + let carry = (low - lo) / pow64; + let high = if crate::field::modulus_num_bits() as u32 > 196 { + (self.lo + self.hi) * (b.lo + b.hi) - low + carry // Bug + } else { + self.lo * b.hi + self.hi * b.lo + carry + }; + let hi = high as u64 as Field; + U128 { lo, hi } + } +``` +Wrapping mul had the code copied from regular mul barring the assertion that the product of high limbs is zero. Because that check was removed, the optimized path for moduli > 196 bits was incorrect, since it included their product (as at least one of them was supposed to be zero originally, but not for wrapping multiplication) + + + diff --git a/shell.nix b/shell.nix deleted file mode 100644 index b72d4a4697b..00000000000 --- a/shell.nix +++ /dev/null @@ -1,13 +0,0 @@ -let - lock = builtins.fromJSON (builtins.readFile ./flake.lock); - flakeCompatRev = lock.nodes.flake-compat.locked.rev; - flakeCompatHash = lock.nodes.flake-compat.locked.narHash; - flakeCompat = fetchTarball { - url = "https://github.com/edolstra/flake-compat/archive/${flakeCompatRev}.tar.gz"; - sha256 = flakeCompatHash; - }; - compat = import flakeCompat { - src = ./.; - }; -in -compat.shellNix diff --git a/test_programs/.gitignore b/test_programs/.gitignore index e98a2fb38b6..6da0100814a 100644 --- a/test_programs/.gitignore +++ b/test_programs/.gitignore @@ -1,3 +1,3 @@ acir_artifacts execution_success/**/crs -Nargo.toml +./Nargo.toml diff --git a/test_programs/compile_failure/array_length_defaulting/Nargo.toml b/test_programs/compile_failure/array_length_defaulting/Nargo.toml new file mode 100644 index 00000000000..fa376596ee2 --- /dev/null +++ b/test_programs/compile_failure/array_length_defaulting/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "array_length_defaulting" +type = "bin" +authors = [""] +compiler_version = ">=0.26.0" + +[dependencies] diff --git a/test_programs/compile_failure/array_length_defaulting/src/main.nr b/test_programs/compile_failure/array_length_defaulting/src/main.nr new file mode 100644 index 00000000000..216a9ae3f0c --- /dev/null +++ b/test_programs/compile_failure/array_length_defaulting/src/main.nr @@ -0,0 +1,10 @@ +fn main() { + let x = dep::std::unsafe::zeroed(); + foo(x); +} + +fn foo(array: [Field; N]) { + for elem in array { + println(elem); + } +} diff --git a/test_programs/compile_failure/brillig_mut_ref_from_acir/src/main.nr b/test_programs/compile_failure/brillig_mut_ref_from_acir/src/main.nr index cf3279cac0d..473ad8e8d6a 100644 --- a/test_programs/compile_failure/brillig_mut_ref_from_acir/src/main.nr +++ b/test_programs/compile_failure/brillig_mut_ref_from_acir/src/main.nr @@ -5,4 +5,4 @@ unconstrained fn mut_ref_identity(value: &mut Field) -> Field { fn main(mut x: Field, y: pub Field) { let returned_x = mut_ref_identity(&mut x); assert(returned_x == x); -} \ No newline at end of file +} diff --git a/test_programs/compile_failure/brillig_nested_slices/Prover.toml b/test_programs/compile_failure/brillig_nested_slices/Prover.toml deleted file mode 100644 index c52564de922..00000000000 --- a/test_programs/compile_failure/brillig_nested_slices/Prover.toml +++ /dev/null @@ -1,2 +0,0 @@ -a = "5" -b = "10" diff --git a/test_programs/compile_failure/depend_on_bin/Prover.toml b/test_programs/compile_failure/depend_on_bin/Prover.toml deleted file mode 100644 index 7d4290a117a..00000000000 --- a/test_programs/compile_failure/depend_on_bin/Prover.toml +++ /dev/null @@ -1 +0,0 @@ -x = 1 diff --git a/test_programs/compile_failure/dup_trait_items_1/Prover.toml b/test_programs/compile_failure/dup_trait_items_1/Prover.toml deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/test_programs/compile_failure/dup_trait_items_2/Prover.toml b/test_programs/compile_failure/dup_trait_items_2/Prover.toml deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/test_programs/compile_failure/dup_trait_items_3/Prover.toml b/test_programs/compile_failure/dup_trait_items_3/Prover.toml deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/test_programs/compile_failure/dup_trait_items_4/Prover.toml b/test_programs/compile_failure/dup_trait_items_4/Prover.toml deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/test_programs/compile_failure/dup_trait_items_5/Prover.toml b/test_programs/compile_failure/dup_trait_items_5/Prover.toml deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/test_programs/compile_failure/dup_trait_items_6/Prover.toml b/test_programs/compile_failure/dup_trait_items_6/Prover.toml deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/test_programs/compile_failure/hashmap_load_factor/Prover.toml b/test_programs/compile_failure/hashmap_load_factor/Prover.toml deleted file mode 100644 index e54319c61e9..00000000000 --- a/test_programs/compile_failure/hashmap_load_factor/Prover.toml +++ /dev/null @@ -1,26 +0,0 @@ -# Expected 6 key-value entries for hashmap capacity of 8. -# These must be distinct (both key-to-key, and value-to-value) for correct testing. - -[[input]] -key = 2 -value = 17 - -[[input]] -key = 3 -value = 19 - -[[input]] -key = 5 -value = 23 - -[[input]] -key = 7 -value = 29 - -[[input]] -key = 11 -value = 31 - -[[input]] -key = 41 -value = 43 \ No newline at end of file diff --git a/test_programs/compile_failure/negate_unsigned/Prover.toml b/test_programs/compile_failure/negate_unsigned/Prover.toml deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/test_programs/compile_failure/regression_5065_failure/Nargo.toml b/test_programs/compile_failure/regression_5065_failure/Nargo.toml new file mode 100644 index 00000000000..c3dda827d3c --- /dev/null +++ b/test_programs/compile_failure/regression_5065_failure/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "regression_5065_failure" +type = "bin" +authors = [""] +compiler_version = ">=0.30.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/regression_5065_failure/src/main.nr b/test_programs/compile_failure/regression_5065_failure/src/main.nr new file mode 100644 index 00000000000..ead1754209d --- /dev/null +++ b/test_programs/compile_failure/regression_5065_failure/src/main.nr @@ -0,0 +1,40 @@ +struct Wrapper { + _value: T, +} + +impl Wrapper { + fn new(value: T) -> Self { + Self { _value: value } + } + + fn unwrap(self) -> T { + self._value + } +} + +trait MyTrait { + fn new() -> Self; +} + +struct MyType {} + +impl MyTrait for MyType { + fn new() -> Self { + MyType {} + } +} + +fn foo() -> T where T: MyTrait { + MyTrait::new() +} + +struct BadType {} + +// Check that we get "No matching impl found for `BadType: MyTrait`" +fn concise_regression() -> BadType { + Wrapper::new(foo()).unwrap() +} + +fn main() { + let _ = concise_regression(); +} diff --git a/test_programs/compile_failure/self_referential_struct/Nargo.toml b/test_programs/compile_failure/self_referential_struct/Nargo.toml new file mode 100644 index 00000000000..a0693f9d4b1 --- /dev/null +++ b/test_programs/compile_failure/self_referential_struct/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "self_referential_struct" +type = "bin" +authors = [""] +compiler_version = ">=0.27.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/self_referential_struct/src/main.nr b/test_programs/compile_failure/self_referential_struct/src/main.nr new file mode 100644 index 00000000000..d70b1a10ded --- /dev/null +++ b/test_programs/compile_failure/self_referential_struct/src/main.nr @@ -0,0 +1,11 @@ +struct Option2 { + _is_some: bool, + _value: T, +} + +struct SelfReferential +{ + prop : Option2 +} + +fn main(x: SelfReferential) { assert(x._is_some); } diff --git a/test_programs/compile_failure/turbofish_generic_count/Nargo.toml b/test_programs/compile_failure/turbofish_generic_count/Nargo.toml new file mode 100644 index 00000000000..92be7dcb749 --- /dev/null +++ b/test_programs/compile_failure/turbofish_generic_count/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "turbofish_generic_count" +type = "bin" +authors = [""] +compiler_version = ">=0.29.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/turbofish_generic_count/src/main.nr b/test_programs/compile_failure/turbofish_generic_count/src/main.nr new file mode 100644 index 00000000000..a360641fa15 --- /dev/null +++ b/test_programs/compile_failure/turbofish_generic_count/src/main.nr @@ -0,0 +1,22 @@ + +struct Bar { + one: Field, + two: Field, + other: T, +} + +impl Bar { + fn zeroed(_self: Self) -> A { + dep::std::unsafe::zeroed() + } +} + +fn foo(bar: Bar) { + assert(bar.one == bar.two); +} + +fn main(x: Field, y: pub Field) { + let bar1: Bar = Bar { one: x, two: y, other: 0 }; + + assert(bar1.zeroed::() == 0); +} diff --git a/test_programs/compile_failure/typevar_default/Nargo.toml b/test_programs/compile_failure/typevar_default/Nargo.toml new file mode 100644 index 00000000000..b3cd08bb8fe --- /dev/null +++ b/test_programs/compile_failure/typevar_default/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "typevar_default" +type = "bin" +authors = [""] +compiler_version = ">=0.26.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/typevar_default/src/main.nr b/test_programs/compile_failure/typevar_default/src/main.nr new file mode 100644 index 00000000000..1eb9cf63de3 --- /dev/null +++ b/test_programs/compile_failure/typevar_default/src/main.nr @@ -0,0 +1,12 @@ +fn main() { + // Expecting error: type annotations needed (N not known) + let _ = slice_to_array(&[1, 2, 3]); +} + +fn slice_to_array(slice: [Field]) -> [Field; N] { + let mut array = [0; N]; + for i in 0 .. N { + array[i] = slice[i]; + } + array +} diff --git a/test_programs/compile_failure/unconstrained_oracle/Nargo.toml b/test_programs/compile_failure/unconstrained_oracle/Nargo.toml new file mode 100644 index 00000000000..7c3fb8766bf --- /dev/null +++ b/test_programs/compile_failure/unconstrained_oracle/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "unconstrained_oracle" +type = "bin" +authors = [""] +compiler_version = ">=0.25.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/unconstrained_oracle/src/main.nr b/test_programs/compile_failure/unconstrained_oracle/src/main.nr new file mode 100644 index 00000000000..abc7bf51ab8 --- /dev/null +++ b/test_programs/compile_failure/unconstrained_oracle/src/main.nr @@ -0,0 +1,9 @@ +#[oracle(getNoun)] +unconstrained fn external_fn() -> Field { + 100 / 5 +} + +fn main() { + let x = anon(); + assert(x * 5 == 100); +} diff --git a/test_programs/compile_failure/unconstrained_ref/Nargo.toml b/test_programs/compile_failure/unconstrained_ref/Nargo.toml new file mode 100644 index 00000000000..c03aaea5fca --- /dev/null +++ b/test_programs/compile_failure/unconstrained_ref/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "unconstrained_ref" +type = "bin" +authors = [""] +compiler_version = ">=0.25.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/unconstrained_ref/src/main.nr b/test_programs/compile_failure/unconstrained_ref/src/main.nr new file mode 100644 index 00000000000..1491badaa49 --- /dev/null +++ b/test_programs/compile_failure/unconstrained_ref/src/main.nr @@ -0,0 +1,8 @@ +unconstrained fn uncon_ref() -> &mut Field { + let lr = &mut 7; + lr +} + +fn main() { + let e = uncon_ref(); +} diff --git a/test_programs/compile_success_contract/contract_with_impl/src/main.nr b/test_programs/compile_success_contract/contract_with_impl/src/main.nr index ddcb5d54d78..1c6b6c217c4 100644 --- a/test_programs/compile_success_contract/contract_with_impl/src/main.nr +++ b/test_programs/compile_success_contract/contract_with_impl/src/main.nr @@ -2,6 +2,6 @@ contract Foo { struct T { x: [Field] } impl T { - fn t(self){} + fn t(self) {} } } diff --git a/test_programs/compile_success_contract/fold_non_contract_method/Nargo.toml b/test_programs/compile_success_contract/fold_non_contract_method/Nargo.toml new file mode 100644 index 00000000000..ff64bbb6f1b --- /dev/null +++ b/test_programs/compile_success_contract/fold_non_contract_method/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "fold_non_contract_method" +type = "contract" +authors = [""] +compiler_version = ">=0.26.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_success_contract/fold_non_contract_method/src/main.nr b/test_programs/compile_success_contract/fold_non_contract_method/src/main.nr new file mode 100644 index 00000000000..2e00ffa1381 --- /dev/null +++ b/test_programs/compile_success_contract/fold_non_contract_method/src/main.nr @@ -0,0 +1,18 @@ +contract Foo { + use crate::times_10; + + fn double(x: Field) -> pub Field { + x * 2 + } + fn triple(x: Field) -> pub Field { + x * 3 + } + fn times_40(x: Field) -> pub Field { + times_10(x) * 4 + } +} + +#[fold] +fn times_10(x: Field) -> Field { + x * 10 +} diff --git a/test_programs/compile_success_contract/simple_contract/src/main.nr b/test_programs/compile_success_contract/simple_contract/src/main.nr index fea0ae08c22..7412e1386bf 100644 --- a/test_programs/compile_success_contract/simple_contract/src/main.nr +++ b/test_programs/compile_success_contract/simple_contract/src/main.nr @@ -5,15 +5,12 @@ contract Foo { fn triple(x: Field) -> pub Field { x * 3 } - internal fn quadruple(x: Field) -> pub Field { + fn quadruple(x: Field) -> pub Field { x * 4 } - open internal fn skibbidy(x: Field) -> pub Field { - x * 5 - } // Regression for issue #3344 #[contract_library_method] - fn foo(x : u8) -> u8 { + fn foo(x: u8) -> u8 { x } } diff --git a/test_programs/compile_success_empty/brillig_integer_binary_operations/src/main.nr b/test_programs/compile_success_empty/brillig_integer_binary_operations/src/main.nr index ee8eb9b3518..7ecc21dbd2f 100644 --- a/test_programs/compile_success_empty/brillig_integer_binary_operations/src/main.nr +++ b/test_programs/compile_success_empty/brillig_integer_binary_operations/src/main.nr @@ -24,8 +24,8 @@ fn main() { 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)); + assert((x >> y as u8) == shr(x, y as u8)); + assert((x << y as u8) == shl(x, y as u8)); } } @@ -69,11 +69,11 @@ 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: u8) -> u32 { x >> y } -unconstrained fn shl(x: u32, y: u32) -> u32 { +unconstrained fn shl(x: u32, y: u8) -> u32 { x << y } diff --git a/test_programs/compile_success_empty/field_comparisons/Nargo.toml b/test_programs/compile_success_empty/brillig_slice_input/Nargo.toml similarity index 65% rename from test_programs/compile_success_empty/field_comparisons/Nargo.toml rename to test_programs/compile_success_empty/brillig_slice_input/Nargo.toml index e8b06655c58..a1c8cc3242b 100644 --- a/test_programs/compile_success_empty/field_comparisons/Nargo.toml +++ b/test_programs/compile_success_empty/brillig_slice_input/Nargo.toml @@ -1,5 +1,5 @@ [package] -name = "field_comparisons" +name = "brillig_slice_input" type = "bin" authors = [""] diff --git a/test_programs/compile_success_empty/brillig_slice_input/src/main.nr b/test_programs/compile_success_empty/brillig_slice_input/src/main.nr new file mode 100644 index 00000000000..8403cb7d4a0 --- /dev/null +++ b/test_programs/compile_success_empty/brillig_slice_input/src/main.nr @@ -0,0 +1,43 @@ +struct Point { + x: Field, + y: Field, +} + +unconstrained fn sum_slice(slice: [[Point; 2]]) -> Field { + let mut sum = 0; + for i in 0..slice.len() { + for j in 0..slice[i].len() { + sum += slice[i][j].x + slice[i][j].y; + } + } + sum +} + +fn main() { + let mut slice = &[]; + slice = slice.push_back([ + Point { + x: 13, + y: 14, + }, + Point { + x: 20, + y: 8, + } + ]); + let brillig_sum = sum_slice(slice); + assert_eq(brillig_sum, 55); + + slice = slice.push_back([ + Point { + x: 15, + y: 5, + }, + Point { + x: 12, + y: 13, + } + ]); + let brillig_sum = sum_slice(slice); + assert_eq(brillig_sum, 100); +} diff --git a/test_programs/compile_success_empty/comptime_mut_global/Nargo.toml b/test_programs/compile_success_empty/comptime_mut_global/Nargo.toml new file mode 100644 index 00000000000..c29aa8d83b9 --- /dev/null +++ b/test_programs/compile_success_empty/comptime_mut_global/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "comptime_mut_global" +type = "bin" +authors = [""] +compiler_version = ">=0.28.0" + +[dependencies] diff --git a/test_programs/compile_success_empty/comptime_mut_global/src/main.nr b/test_programs/compile_success_empty/comptime_mut_global/src/main.nr new file mode 100644 index 00000000000..fa739289d37 --- /dev/null +++ b/test_programs/compile_success_empty/comptime_mut_global/src/main.nr @@ -0,0 +1,30 @@ +comptime mut global COUNTER: Field = 0; + +comptime fn get_unique_id() -> Field { + let id = COUNTER; + COUNTER += 1; + id +} + +fn id1() -> Field { + comptime + { + get_unique_id() + } +} + +fn id2() -> Field { + comptime + { + get_unique_id() + } +} + +fn main() { + // Order of comptime evaluation between functions isn't guaranteed + // so we don't know if (id1 == 0 && id2 == 1) or if (id1 == 1 && id2 == 0). + // we only know they are not equal + let id1 = id1(); + let id2 = id2(); + assert(id1 != id2); +} diff --git a/test_programs/compile_success_empty/field_comparisons/src/main.nr b/test_programs/compile_success_empty/field_comparisons/src/main.nr deleted file mode 100644 index 9cc01c8ab2f..00000000000 --- a/test_programs/compile_success_empty/field_comparisons/src/main.nr +++ /dev/null @@ -1,94 +0,0 @@ -use dep::std::field::bn254::{PLO, PHI, TWO_POW_128, decompose, decompose_unsafe, lt_unsafe, lte_unsafe, assert_gt, gt}; - -fn check_plo_phi() { - assert_eq(PLO + PHI * TWO_POW_128, 0); - let p_bytes = dep::std::field::modulus_le_bytes(); - let mut p_low: Field = 0; - let mut p_high: Field = 0; - - let mut offset = 1; - for i in 0..16 { - p_low += (p_bytes[i] as Field) * offset; - p_high += (p_bytes[i + 16] as Field) * offset; - offset *= 256; - } - assert_eq(p_low, PLO); - assert_eq(p_high, PHI); -} - -fn check_decompose_unsafe() { - unsafe { - assert_eq(decompose_unsafe(TWO_POW_128), (0, 1)); - assert_eq(decompose_unsafe(TWO_POW_128 + 0x1234567890), (0x1234567890, 1)); - assert_eq(decompose_unsafe(0x1234567890), (0x1234567890, 0)); - } -} - -fn check_decompose() { - assert_eq(decompose(TWO_POW_128), (0, 1)); - assert_eq(decompose(TWO_POW_128 + 0x1234567890), (0x1234567890, 1)); - assert_eq(decompose(0x1234567890), (0x1234567890, 0)); -} - -fn check_lt_unsafe() { - unsafe { - assert(lt_unsafe(0, 1, 16)); - assert(lt_unsafe(0, 0x100, 16)); - assert(lt_unsafe(0x100, TWO_POW_128 - 1, 16)); - assert(!lt_unsafe(0, TWO_POW_128, 16)); - } -} - -fn check_lte_unsafe() { - unsafe { - assert(lte_unsafe(0, 1, 16)); - assert(lte_unsafe(0, 0x100, 16)); - assert(lte_unsafe(0x100, TWO_POW_128 - 1, 16)); - assert(!lte_unsafe(0, TWO_POW_128, 16)); - - assert(lte_unsafe(0, 0, 16)); - assert(lte_unsafe(0x100, 0x100, 16)); - assert(lte_unsafe(TWO_POW_128 - 1, TWO_POW_128 - 1, 16)); - assert(lte_unsafe(TWO_POW_128, TWO_POW_128, 16)); - } -} - -fn check_assert_gt() { - assert_gt(1, 0); - assert_gt(0x100, 0); - assert_gt((0 - 1), (0 - 2)); - assert_gt(TWO_POW_128, 0); - assert_gt(0 - 1, 0); -} - -fn check_gt() { - assert(gt(1, 0)); - assert(gt(0x100, 0)); - assert(gt((0 - 1), (0 - 2))); - assert(gt(TWO_POW_128, 0)); - assert(!gt(0, 0)); - assert(!gt(0, 0x100)); - assert(gt(0 - 1, 0 - 2)); - assert(!gt(0 - 2, 0 - 1)); -} - -fn checks() { - check_plo_phi(); - check_decompose_unsafe(); - check_decompose(); - check_lt_unsafe(); - check_lte_unsafe(); - check_assert_gt(); - check_gt(); -} - -unconstrained fn checks_in_brillig() { - checks(); -} - -fn main() { - checks(); - unsafe { - checks_in_brillig(); - } -} diff --git a/test_programs/compile_success_empty/impl_from_where_impl/Nargo.toml b/test_programs/compile_success_empty/impl_from_where_impl/Nargo.toml new file mode 100644 index 00000000000..5894e457dd8 --- /dev/null +++ b/test_programs/compile_success_empty/impl_from_where_impl/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "impl_from_where_impl" +type = "bin" +authors = [""] +compiler_version = ">=0.27.0" + +[dependencies] diff --git a/test_programs/compile_success_empty/impl_from_where_impl/src/main.nr b/test_programs/compile_success_empty/impl_from_where_impl/src/main.nr new file mode 100644 index 00000000000..3cec46bdfcd --- /dev/null +++ b/test_programs/compile_success_empty/impl_from_where_impl/src/main.nr @@ -0,0 +1,15 @@ +trait Bar { + fn ok(self) -> Self; + + fn ref_ok(self) -> Self { + self.ok() + } +} + +impl Bar for (T, T) where T: Bar { + fn ok(self) -> Self { + self + } +} + +fn main() {} diff --git a/test_programs/compile_success_empty/intrinsic_die/src/main.nr b/test_programs/compile_success_empty/intrinsic_die/src/main.nr index 8cac707dfea..a6c6d3df9a1 100644 --- a/test_programs/compile_success_empty/intrinsic_die/src/main.nr +++ b/test_programs/compile_success_empty/intrinsic_die/src/main.nr @@ -2,5 +2,9 @@ use dep::std; // This test checks that we perform dead-instruction-elimination on intrinsic functions. fn main(x: Field) { let hash = std::hash::pedersen_commitment([x]); - let _p1 = std::scalar_mul::fixed_base_embedded_curve(x, 0); + let g1_x = 0x0000000000000000000000000000000000000000000000000000000000000001; + let g1_y = 0x0000000000000002cf135e7506a45d632d270d45f1181294833fc48d823f272c; + let g1 = std::embedded_curve_ops::EmbeddedCurvePoint { x: g1_x, y: g1_y, is_infinite: false }; + let scalar = std::embedded_curve_ops::EmbeddedCurveScalar { lo: x, hi: 0 }; + let _p1 = std::embedded_curve_ops::multi_scalar_mul([g1], [scalar]); } diff --git a/test_programs/compile_success_empty/option/src/main.nr b/test_programs/compile_success_empty/option/src/main.nr index 989c8f65bf4..c5f321256b1 100644 --- a/test_programs/compile_success_empty/option/src/main.nr +++ b/test_programs/compile_success_empty/option/src/main.nr @@ -39,9 +39,9 @@ fn main() { let add1_u64 = |value: Field| Option::some(value as u64 + 1); - assert(none.and_then(|_value| Option::none()).is_none()); + assert(none.and_then(|_value| none).is_none()); assert(none.and_then(add1_u64).is_none()); - assert(some.and_then(|_value| Option::none()).is_none()); + assert(some.and_then(|_value| none).is_none()); assert(some.and_then(add1_u64).unwrap() == 4); assert(some.and_then(|x| Option::some(x + ten)).unwrap() == 13); diff --git a/test_programs/compile_success_empty/regression_4383/Nargo.toml b/test_programs/compile_success_empty/regression_4383/Nargo.toml new file mode 100644 index 00000000000..2ad8c208f24 --- /dev/null +++ b/test_programs/compile_success_empty/regression_4383/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "regression_4383" +type = "bin" +authors = [""] +compiler_version = ">=0.26.0" + +[dependencies] diff --git a/test_programs/compile_success_empty/regression_4383/src/main.nr b/test_programs/compile_success_empty/regression_4383/src/main.nr new file mode 100644 index 00000000000..fec63ea64a5 --- /dev/null +++ b/test_programs/compile_success_empty/regression_4383/src/main.nr @@ -0,0 +1,3 @@ +fn main() { + assert([[1]] == [[1]]); +} diff --git a/test_programs/compile_success_empty/regression_4436/Nargo.toml b/test_programs/compile_success_empty/regression_4436/Nargo.toml new file mode 100644 index 00000000000..0904d858596 --- /dev/null +++ b/test_programs/compile_success_empty/regression_4436/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "regression_4436" +type = "bin" +authors = [""] +compiler_version = ">=0.22.0" diff --git a/test_programs/compile_success_empty/regression_4436/src/main.nr b/test_programs/compile_success_empty/regression_4436/src/main.nr new file mode 100644 index 00000000000..834ea3250cc --- /dev/null +++ b/test_programs/compile_success_empty/regression_4436/src/main.nr @@ -0,0 +1,31 @@ +trait LibTrait { + fn broadcast(); + fn get_constant() -> Field; +} + +global STRUCT_A_LEN: Field = 3; +global STRUCT_B_LEN: Field = 5; + +struct StructA; +struct StructB; + +impl LibTrait for StructA { + fn broadcast() { + Self::get_constant(); + } + + fn get_constant() -> Field { + 1 + } +} +impl LibTrait for StructB { + fn broadcast() { + Self::get_constant(); + } + + fn get_constant() -> Field { + 1 + } +} + +fn main() {} diff --git a/test_programs/compile_success_empty/regression_4635/Nargo.toml b/test_programs/compile_success_empty/regression_4635/Nargo.toml new file mode 100644 index 00000000000..563e262410f --- /dev/null +++ b/test_programs/compile_success_empty/regression_4635/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "regression_4635" +type = "bin" +authors = [""] +compiler_version = ">=0.26.0" + +[dependencies] diff --git a/test_programs/compile_success_empty/regression_4635/src/main.nr b/test_programs/compile_success_empty/regression_4635/src/main.nr new file mode 100644 index 00000000000..23918e30785 --- /dev/null +++ b/test_programs/compile_success_empty/regression_4635/src/main.nr @@ -0,0 +1,59 @@ +trait FromField { + fn from_field(field: Field) -> Self; +} + +impl FromField for Field { + fn from_field(value: Field) -> Self { + value + } +} + +trait Deserialize { + fn deserialize(fields: [Field; N]) -> Self; +} + +global AZTEC_ADDRESS_LENGTH = 1; + +struct AztecAddress { + inner : Field +} + +impl FromField for AztecAddress { + fn from_field(value: Field) -> Self { + Self { inner: value } + } +} + +impl Deserialize for AztecAddress { + fn deserialize(fields: [Field; AZTEC_ADDRESS_LENGTH]) -> Self { + AztecAddress::from_field(fields[0]) + } +} + +impl Eq for AztecAddress { + fn eq(self, other: Self) -> bool { + self.inner == other.inner + } +} + +// Custom code + +struct MyStruct { + a: T +} + +impl Deserialize<1> for MyStruct { + fn deserialize(fields: [Field; 1]) -> Self where T: FromField { + Self{ a: FromField::from_field(fields[0]) } + } +} + +fn main() { + let fields = [5; 1]; + let foo = MyStruct::deserialize(fields); // Note I don't specify T here (the type of `foo.a`) + + let bar = AztecAddress { inner: 5 }; + + // Here `T` is apparently inferred to be `AztecAddress`, presumably because of the comparison. + assert(foo.a == bar); +} diff --git a/test_programs/compile_success_empty/regression_5065/Nargo.toml b/test_programs/compile_success_empty/regression_5065/Nargo.toml new file mode 100644 index 00000000000..b1cb9d9ba96 --- /dev/null +++ b/test_programs/compile_success_empty/regression_5065/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "regression_5065" +type = "bin" +authors = [""] +compiler_version = ">=0.30.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_success_empty/regression_5065/src/main.nr b/test_programs/compile_success_empty/regression_5065/src/main.nr new file mode 100644 index 00000000000..36b0570165f --- /dev/null +++ b/test_programs/compile_success_empty/regression_5065/src/main.nr @@ -0,0 +1,45 @@ +struct Wrapper { + _value: T, +} + +impl Wrapper { + fn new_wrapper(value: T) -> Self { + Self { _value: value } + } + + fn unwrap(self) -> T { + self._value + } +} + +trait MyTrait { + fn new() -> Self; +} + +struct MyType {} + +impl MyTrait for MyType { + fn new() -> Self { + MyType {} + } +} + +fn foo() -> T where T: MyTrait { + MyTrait::new() +} + +// fn verbose_but_compiles() -> MyType { +// let a = Wrapper::new_wrapper(foo()); +// a.unwrap() +// } + +// Check that are able to infer the return type of the call to `foo` +fn concise_regression() -> MyType { + Wrapper::new_wrapper(foo()).unwrap() + // Wrapper::unwrap(Wrapper::new_wrapper(foo())) +} + +fn main() { + // let _ = verbose_but_compiles(); + let _ = concise_regression(); +} diff --git a/test_programs/compile_success_empty/slice_init_with_complex_type/Nargo.toml b/test_programs/compile_success_empty/slice_init_with_complex_type/Nargo.toml new file mode 100644 index 00000000000..a372caf92e9 --- /dev/null +++ b/test_programs/compile_success_empty/slice_init_with_complex_type/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "slice_init_with_complex_type" +type = "bin" +authors = [""] +compiler_version = ">=0.28.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/cyclic_dep/Prover.toml b/test_programs/compile_success_empty/slice_init_with_complex_type/Prover.toml similarity index 100% rename from test_programs/compile_failure/cyclic_dep/Prover.toml rename to test_programs/compile_success_empty/slice_init_with_complex_type/Prover.toml diff --git a/test_programs/compile_success_empty/slice_init_with_complex_type/src/main.nr b/test_programs/compile_success_empty/slice_init_with_complex_type/src/main.nr new file mode 100644 index 00000000000..01ccf2fdeff --- /dev/null +++ b/test_programs/compile_success_empty/slice_init_with_complex_type/src/main.nr @@ -0,0 +1,17 @@ +struct strct1 { + elem1: Field, +} + +fn main() { + let var1: [[i32; 1]] = [[0]]; + let var2: [[i32; 1]] = var1; + + let var1: [(i32, u8)] = [(1, 2)]; + let var2: [(i32, u8)] = var1; + + let var3: [strct1] = [strct1 { elem1: 1321351 }]; + let var4: [strct1] = var3; + + let var1: [i32; 1] = [0]; + let var2: [[i32; 1]] = [var1]; +} diff --git a/test_programs/compile_success_empty/vectors/src/main.nr b/test_programs/compile_success_empty/vectors/src/main.nr index 28187a4f619..d105ceed180 100644 --- a/test_programs/compile_success_empty/vectors/src/main.nr +++ b/test_programs/compile_success_empty/vectors/src/main.nr @@ -26,7 +26,7 @@ fn main(x: Field, y: pub Field) { assert(vector.get(3) == 3); assert(vector.len() == 4); - let mut inputs_vector = Vec::from_slice([x, y]); + let mut inputs_vector = Vec::from_slice(&[x, y]); assert(inputs_vector.get(0) == x); assert(inputs_vector.get(1) == y); } diff --git a/test_programs/compile_failure/assert_msg_runtime/Nargo.toml b/test_programs/execution_failure/assert_msg_runtime/Nargo.toml similarity index 100% rename from test_programs/compile_failure/assert_msg_runtime/Nargo.toml rename to test_programs/execution_failure/assert_msg_runtime/Nargo.toml diff --git a/test_programs/compile_failure/assert_msg_runtime/Prover.toml b/test_programs/execution_failure/assert_msg_runtime/Prover.toml similarity index 100% rename from test_programs/compile_failure/assert_msg_runtime/Prover.toml rename to test_programs/execution_failure/assert_msg_runtime/Prover.toml diff --git a/test_programs/compile_failure/assert_msg_runtime/src/main.nr b/test_programs/execution_failure/assert_msg_runtime/src/main.nr similarity index 99% rename from test_programs/compile_failure/assert_msg_runtime/src/main.nr rename to test_programs/execution_failure/assert_msg_runtime/src/main.nr index bec3082550a..fa21442e816 100644 --- a/test_programs/compile_failure/assert_msg_runtime/src/main.nr +++ b/test_programs/execution_failure/assert_msg_runtime/src/main.nr @@ -4,4 +4,4 @@ fn main(x: Field, y: pub Field) { let z = x + y; assert(z != y, f"Expected z != y, but got both equal {z}"); assert_eq(x, y, f"Expected x == y, but x is {x} and y is {y}"); -} \ No newline at end of file +} diff --git a/test_programs/compile_failure/brillig_assert_fail/Nargo.toml b/test_programs/execution_failure/brillig_assert_fail/Nargo.toml similarity index 100% rename from test_programs/compile_failure/brillig_assert_fail/Nargo.toml rename to test_programs/execution_failure/brillig_assert_fail/Nargo.toml diff --git a/test_programs/compile_failure/brillig_assert_fail/Prover.toml b/test_programs/execution_failure/brillig_assert_fail/Prover.toml similarity index 100% rename from test_programs/compile_failure/brillig_assert_fail/Prover.toml rename to test_programs/execution_failure/brillig_assert_fail/Prover.toml diff --git a/test_programs/compile_failure/brillig_assert_fail/src/main.nr b/test_programs/execution_failure/brillig_assert_fail/src/main.nr similarity index 100% rename from test_programs/compile_failure/brillig_assert_fail/src/main.nr rename to test_programs/execution_failure/brillig_assert_fail/src/main.nr diff --git a/test_programs/compile_failure/brillig_assert_msg_runtime/Nargo.toml b/test_programs/execution_failure/brillig_assert_msg_runtime/Nargo.toml similarity index 100% rename from test_programs/compile_failure/brillig_assert_msg_runtime/Nargo.toml rename to test_programs/execution_failure/brillig_assert_msg_runtime/Nargo.toml diff --git a/test_programs/compile_failure/brillig_assert_msg_runtime/Prover.toml b/test_programs/execution_failure/brillig_assert_msg_runtime/Prover.toml similarity index 100% rename from test_programs/compile_failure/brillig_assert_msg_runtime/Prover.toml rename to test_programs/execution_failure/brillig_assert_msg_runtime/Prover.toml diff --git a/test_programs/compile_failure/brillig_assert_msg_runtime/src/main.nr b/test_programs/execution_failure/brillig_assert_msg_runtime/src/main.nr similarity index 99% rename from test_programs/compile_failure/brillig_assert_msg_runtime/src/main.nr rename to test_programs/execution_failure/brillig_assert_msg_runtime/src/main.nr index 428b2006363..bd77551e304 100644 --- a/test_programs/compile_failure/brillig_assert_msg_runtime/src/main.nr +++ b/test_programs/execution_failure/brillig_assert_msg_runtime/src/main.nr @@ -7,4 +7,4 @@ unconstrained fn conditional(x: Field) -> Field { assert_eq(z, 25, f"Expected 25 but got {z}"); assert(x == 10, f"Expected x to equal 10, but got {x}"); 1 -} \ No newline at end of file +} diff --git a/test_programs/compile_failure/div_by_zero_constants/Nargo.toml b/test_programs/execution_failure/div_by_zero_constants/Nargo.toml similarity index 100% rename from test_programs/compile_failure/div_by_zero_constants/Nargo.toml rename to test_programs/execution_failure/div_by_zero_constants/Nargo.toml diff --git a/test_programs/compile_failure/div_by_zero_constants/Prover.toml b/test_programs/execution_failure/div_by_zero_constants/Prover.toml similarity index 100% rename from test_programs/compile_failure/div_by_zero_constants/Prover.toml rename to test_programs/execution_failure/div_by_zero_constants/Prover.toml diff --git a/test_programs/compile_failure/div_by_zero_constants/src/main.nr b/test_programs/execution_failure/div_by_zero_constants/src/main.nr similarity index 100% rename from test_programs/compile_failure/div_by_zero_constants/src/main.nr rename to test_programs/execution_failure/div_by_zero_constants/src/main.nr diff --git a/test_programs/compile_failure/div_by_zero_modulo/Nargo.toml b/test_programs/execution_failure/div_by_zero_modulo/Nargo.toml similarity index 100% rename from test_programs/compile_failure/div_by_zero_modulo/Nargo.toml rename to test_programs/execution_failure/div_by_zero_modulo/Nargo.toml diff --git a/test_programs/compile_failure/div_by_zero_modulo/Prover.toml b/test_programs/execution_failure/div_by_zero_modulo/Prover.toml similarity index 100% rename from test_programs/compile_failure/div_by_zero_modulo/Prover.toml rename to test_programs/execution_failure/div_by_zero_modulo/Prover.toml diff --git a/test_programs/compile_failure/div_by_zero_modulo/src/main.nr b/test_programs/execution_failure/div_by_zero_modulo/src/main.nr similarity index 100% rename from test_programs/compile_failure/div_by_zero_modulo/src/main.nr rename to test_programs/execution_failure/div_by_zero_modulo/src/main.nr diff --git a/test_programs/compile_failure/div_by_zero_numerator_witness/Nargo.toml b/test_programs/execution_failure/div_by_zero_numerator_witness/Nargo.toml similarity index 100% rename from test_programs/compile_failure/div_by_zero_numerator_witness/Nargo.toml rename to test_programs/execution_failure/div_by_zero_numerator_witness/Nargo.toml diff --git a/test_programs/compile_failure/div_by_zero_numerator_witness/Prover.toml b/test_programs/execution_failure/div_by_zero_numerator_witness/Prover.toml similarity index 100% rename from test_programs/compile_failure/div_by_zero_numerator_witness/Prover.toml rename to test_programs/execution_failure/div_by_zero_numerator_witness/Prover.toml diff --git a/test_programs/compile_failure/div_by_zero_numerator_witness/src/main.nr b/test_programs/execution_failure/div_by_zero_numerator_witness/src/main.nr similarity index 100% rename from test_programs/compile_failure/div_by_zero_numerator_witness/src/main.nr rename to test_programs/execution_failure/div_by_zero_numerator_witness/src/main.nr diff --git a/test_programs/compile_failure/div_by_zero_witness/Nargo.toml b/test_programs/execution_failure/div_by_zero_witness/Nargo.toml similarity index 100% rename from test_programs/compile_failure/div_by_zero_witness/Nargo.toml rename to test_programs/execution_failure/div_by_zero_witness/Nargo.toml diff --git a/test_programs/compile_failure/div_by_zero_witness/Prover.toml b/test_programs/execution_failure/div_by_zero_witness/Prover.toml similarity index 100% rename from test_programs/compile_failure/div_by_zero_witness/Prover.toml rename to test_programs/execution_failure/div_by_zero_witness/Prover.toml diff --git a/test_programs/compile_failure/div_by_zero_witness/src/main.nr b/test_programs/execution_failure/div_by_zero_witness/src/main.nr similarity index 100% rename from test_programs/compile_failure/div_by_zero_witness/src/main.nr rename to test_programs/execution_failure/div_by_zero_witness/src/main.nr diff --git a/test_programs/compile_failure/dyn_index_fail_nested_array/Nargo.toml b/test_programs/execution_failure/dyn_index_fail_nested_array/Nargo.toml similarity index 100% rename from test_programs/compile_failure/dyn_index_fail_nested_array/Nargo.toml rename to test_programs/execution_failure/dyn_index_fail_nested_array/Nargo.toml diff --git a/test_programs/compile_failure/dyn_index_fail_nested_array/Prover.toml b/test_programs/execution_failure/dyn_index_fail_nested_array/Prover.toml similarity index 100% rename from test_programs/compile_failure/dyn_index_fail_nested_array/Prover.toml rename to test_programs/execution_failure/dyn_index_fail_nested_array/Prover.toml diff --git a/test_programs/compile_failure/dyn_index_fail_nested_array/src/main.nr b/test_programs/execution_failure/dyn_index_fail_nested_array/src/main.nr similarity index 100% rename from test_programs/compile_failure/dyn_index_fail_nested_array/src/main.nr rename to test_programs/execution_failure/dyn_index_fail_nested_array/src/main.nr diff --git a/test_programs/compile_failure/dynamic_index_failure/Nargo.toml b/test_programs/execution_failure/dynamic_index_failure/Nargo.toml similarity index 100% rename from test_programs/compile_failure/dynamic_index_failure/Nargo.toml rename to test_programs/execution_failure/dynamic_index_failure/Nargo.toml diff --git a/test_programs/compile_failure/dynamic_index_failure/Prover.toml b/test_programs/execution_failure/dynamic_index_failure/Prover.toml similarity index 100% rename from test_programs/compile_failure/dynamic_index_failure/Prover.toml rename to test_programs/execution_failure/dynamic_index_failure/Prover.toml diff --git a/test_programs/compile_failure/dynamic_index_failure/src/main.nr b/test_programs/execution_failure/dynamic_index_failure/src/main.nr similarity index 100% rename from test_programs/compile_failure/dynamic_index_failure/src/main.nr rename to test_programs/execution_failure/dynamic_index_failure/src/main.nr diff --git a/test_programs/execution_failure/fold_dyn_index_fail/Nargo.toml b/test_programs/execution_failure/fold_dyn_index_fail/Nargo.toml new file mode 100644 index 00000000000..e49a82cf0fb --- /dev/null +++ b/test_programs/execution_failure/fold_dyn_index_fail/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "fold_dyn_index_fail" +type = "bin" +authors = [""] +compiler_version = ">=0.26.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_failure/fold_dyn_index_fail/Prover.toml b/test_programs/execution_failure/fold_dyn_index_fail/Prover.toml new file mode 100644 index 00000000000..caf3448c56f --- /dev/null +++ b/test_programs/execution_failure/fold_dyn_index_fail/Prover.toml @@ -0,0 +1,2 @@ +x = [104, 101, 108, 108, 111] +z = "4" diff --git a/test_programs/execution_failure/fold_dyn_index_fail/src/main.nr b/test_programs/execution_failure/fold_dyn_index_fail/src/main.nr new file mode 100644 index 00000000000..b12dea630b0 --- /dev/null +++ b/test_programs/execution_failure/fold_dyn_index_fail/src/main.nr @@ -0,0 +1,10 @@ +fn main(mut x: [u32; 5], z: Field) { + x[z] = 4; + dynamic_index_check(x, z + 10); +} + +#[fold] +fn dynamic_index_check(x: [u32; 5], idx: Field) { + // Dynamic index is greater than length of the array + assert(x[idx] != 0); +} diff --git a/test_programs/execution_failure/fold_nested_brillig_assert_fail/Nargo.toml b/test_programs/execution_failure/fold_nested_brillig_assert_fail/Nargo.toml new file mode 100644 index 00000000000..bb7d5e20dcc --- /dev/null +++ b/test_programs/execution_failure/fold_nested_brillig_assert_fail/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "fold_nested_brillig_assert_fail" +type = "bin" +authors = [""] +compiler_version = ">=0.26.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_failure/fold_nested_brillig_assert_fail/Prover.toml b/test_programs/execution_failure/fold_nested_brillig_assert_fail/Prover.toml new file mode 100644 index 00000000000..11497a473bc --- /dev/null +++ b/test_programs/execution_failure/fold_nested_brillig_assert_fail/Prover.toml @@ -0,0 +1 @@ +x = "0" diff --git a/test_programs/execution_failure/fold_nested_brillig_assert_fail/src/main.nr b/test_programs/execution_failure/fold_nested_brillig_assert_fail/src/main.nr new file mode 100644 index 00000000000..0a5038c179b --- /dev/null +++ b/test_programs/execution_failure/fold_nested_brillig_assert_fail/src/main.nr @@ -0,0 +1,26 @@ +// Tests a very simple program. +// +// The features being tested is using assert on brillig that is triggered through nested ACIR calls. +// We want to make sure we get a call stack from the original call in main to the failed assert. +fn main(x: Field) { + assert(1 == fold_conditional_wrapper(x as bool)); +} + +#[fold] +fn fold_conditional_wrapper(x: bool) -> Field { + fold_conditional(x) +} + +#[fold] +fn fold_conditional(x: bool) -> Field { + conditional_wrapper(x) +} + +unconstrained fn conditional_wrapper(x: bool) -> Field { + conditional(x) +} + +unconstrained fn conditional(x: bool) -> Field { + assert(x); + 1 +} diff --git a/test_programs/compile_failure/hashmap_load_factor/Nargo.toml b/test_programs/execution_failure/hashmap_load_factor/Nargo.toml similarity index 100% rename from test_programs/compile_failure/hashmap_load_factor/Nargo.toml rename to test_programs/execution_failure/hashmap_load_factor/Nargo.toml diff --git a/test_programs/execution_failure/hashmap_load_factor/Prover.toml b/test_programs/execution_failure/hashmap_load_factor/Prover.toml new file mode 100644 index 00000000000..6d72cab47fa --- /dev/null +++ b/test_programs/execution_failure/hashmap_load_factor/Prover.toml @@ -0,0 +1,23 @@ +[[input]] +key = 1 +value = 0 + +[[input]] +key = 2 +value = 0 + +[[input]] +key = 3 +value = 0 + +[[input]] +key = 4 +value = 0 + +[[input]] +key = 5 +value = 0 + +[[input]] +key = 6 +value = 0 diff --git a/test_programs/compile_failure/hashmap_load_factor/src/main.nr b/test_programs/execution_failure/hashmap_load_factor/src/main.nr similarity index 91% rename from test_programs/compile_failure/hashmap_load_factor/src/main.nr rename to test_programs/execution_failure/hashmap_load_factor/src/main.nr index ade43f898e1..907c3628142 100644 --- a/test_programs/compile_failure/hashmap_load_factor/src/main.nr +++ b/test_programs/execution_failure/hashmap_load_factor/src/main.nr @@ -1,6 +1,6 @@ use dep::std::collections::map::HashMap; use dep::std::hash::BuildHasherDefault; -use dep::std::hash::pedersen::PedersenHasher; +use dep::std::hash::poseidon2::Poseidon2Hasher; struct Entry{ key: Field, @@ -10,7 +10,7 @@ struct Entry{ global HASHMAP_CAP = 8; global HASHMAP_LEN = 6; -fn allocate_hashmap() -> HashMap> { +fn allocate_hashmap() -> HashMap> { HashMap::default() } diff --git a/test_programs/compile_failure/option_expect/Nargo.toml b/test_programs/execution_failure/option_expect/Nargo.toml similarity index 100% rename from test_programs/compile_failure/option_expect/Nargo.toml rename to test_programs/execution_failure/option_expect/Nargo.toml diff --git a/test_programs/compile_failure/option_expect/src/main.nr b/test_programs/execution_failure/option_expect/src/main.nr similarity index 100% rename from test_programs/compile_failure/option_expect/src/main.nr rename to test_programs/execution_failure/option_expect/src/main.nr diff --git a/test_programs/compile_failure/slice_access_failure/Nargo.toml b/test_programs/execution_failure/slice_access_failure/Nargo.toml similarity index 100% rename from test_programs/compile_failure/slice_access_failure/Nargo.toml rename to test_programs/execution_failure/slice_access_failure/Nargo.toml diff --git a/test_programs/compile_failure/radix_non_constant_length/Prover.toml b/test_programs/execution_failure/slice_access_failure/Prover.toml similarity index 100% rename from test_programs/compile_failure/radix_non_constant_length/Prover.toml rename to test_programs/execution_failure/slice_access_failure/Prover.toml diff --git a/test_programs/compile_failure/slice_access_failure/src/main.nr b/test_programs/execution_failure/slice_access_failure/src/main.nr similarity index 100% rename from test_programs/compile_failure/slice_access_failure/src/main.nr rename to test_programs/execution_failure/slice_access_failure/src/main.nr diff --git a/test_programs/compile_failure/slice_insert_failure/Nargo.toml b/test_programs/execution_failure/slice_insert_failure/Nargo.toml similarity index 100% rename from test_programs/compile_failure/slice_insert_failure/Nargo.toml rename to test_programs/execution_failure/slice_insert_failure/Nargo.toml diff --git a/test_programs/compile_failure/slice_access_failure/Prover.toml b/test_programs/execution_failure/slice_insert_failure/Prover.toml similarity index 100% rename from test_programs/compile_failure/slice_access_failure/Prover.toml rename to test_programs/execution_failure/slice_insert_failure/Prover.toml diff --git a/test_programs/compile_failure/slice_insert_failure/src/main.nr b/test_programs/execution_failure/slice_insert_failure/src/main.nr similarity index 100% rename from test_programs/compile_failure/slice_insert_failure/src/main.nr rename to test_programs/execution_failure/slice_insert_failure/src/main.nr diff --git a/test_programs/compile_failure/slice_remove_failure/Nargo.toml b/test_programs/execution_failure/slice_remove_failure/Nargo.toml similarity index 100% rename from test_programs/compile_failure/slice_remove_failure/Nargo.toml rename to test_programs/execution_failure/slice_remove_failure/Nargo.toml diff --git a/test_programs/compile_failure/slice_insert_failure/Prover.toml b/test_programs/execution_failure/slice_remove_failure/Prover.toml similarity index 100% rename from test_programs/compile_failure/slice_insert_failure/Prover.toml rename to test_programs/execution_failure/slice_remove_failure/Prover.toml diff --git a/test_programs/compile_failure/slice_remove_failure/src/main.nr b/test_programs/execution_failure/slice_remove_failure/src/main.nr similarity index 100% rename from test_programs/compile_failure/slice_remove_failure/src/main.nr rename to test_programs/execution_failure/slice_remove_failure/src/main.nr diff --git a/test_programs/compile_failure/workspace_fail/Nargo.toml b/test_programs/execution_failure/workspace_fail/Nargo.toml similarity index 100% rename from test_programs/compile_failure/workspace_fail/Nargo.toml rename to test_programs/execution_failure/workspace_fail/Nargo.toml diff --git a/test_programs/compile_failure/workspace_fail/crates/a/Nargo.toml b/test_programs/execution_failure/workspace_fail/crates/a/Nargo.toml similarity index 100% rename from test_programs/compile_failure/workspace_fail/crates/a/Nargo.toml rename to test_programs/execution_failure/workspace_fail/crates/a/Nargo.toml diff --git a/test_programs/compile_failure/workspace_fail/crates/a/Prover.toml b/test_programs/execution_failure/workspace_fail/crates/a/Prover.toml similarity index 100% rename from test_programs/compile_failure/workspace_fail/crates/a/Prover.toml rename to test_programs/execution_failure/workspace_fail/crates/a/Prover.toml diff --git a/test_programs/compile_failure/workspace_fail/crates/a/src/main.nr b/test_programs/execution_failure/workspace_fail/crates/a/src/main.nr similarity index 100% rename from test_programs/compile_failure/workspace_fail/crates/a/src/main.nr rename to test_programs/execution_failure/workspace_fail/crates/a/src/main.nr diff --git a/test_programs/compile_failure/workspace_fail/crates/b/Nargo.toml b/test_programs/execution_failure/workspace_fail/crates/b/Nargo.toml similarity index 100% rename from test_programs/compile_failure/workspace_fail/crates/b/Nargo.toml rename to test_programs/execution_failure/workspace_fail/crates/b/Nargo.toml diff --git a/test_programs/compile_failure/workspace_fail/crates/b/Prover.toml b/test_programs/execution_failure/workspace_fail/crates/b/Prover.toml similarity index 100% rename from test_programs/compile_failure/workspace_fail/crates/b/Prover.toml rename to test_programs/execution_failure/workspace_fail/crates/b/Prover.toml diff --git a/test_programs/compile_failure/workspace_fail/crates/b/src/main.nr b/test_programs/execution_failure/workspace_fail/crates/b/src/main.nr similarity index 100% rename from test_programs/compile_failure/workspace_fail/crates/b/src/main.nr rename to test_programs/execution_failure/workspace_fail/crates/b/src/main.nr diff --git a/test_programs/execution_success/brillig_bit_shifts_runtime/Nargo.toml b/test_programs/execution_success/acir_inside_brillig_recursion/Nargo.toml similarity index 58% rename from test_programs/execution_success/brillig_bit_shifts_runtime/Nargo.toml rename to test_programs/execution_success/acir_inside_brillig_recursion/Nargo.toml index ed8200d8a95..462532bb484 100644 --- a/test_programs/execution_success/brillig_bit_shifts_runtime/Nargo.toml +++ b/test_programs/execution_success/acir_inside_brillig_recursion/Nargo.toml @@ -1,5 +1,5 @@ [package] -name = "brillig_bit_shifts_runtime" +name = "acir_inside_brillig_recursion" type = "bin" authors = [""] diff --git a/test_programs/compile_success_empty/field_comparisons/Prover.toml b/test_programs/execution_success/acir_inside_brillig_recursion/Prover.toml similarity index 100% rename from test_programs/compile_success_empty/field_comparisons/Prover.toml rename to test_programs/execution_success/acir_inside_brillig_recursion/Prover.toml diff --git a/test_programs/execution_success/acir_inside_brillig_recursion/src/main.nr b/test_programs/execution_success/acir_inside_brillig_recursion/src/main.nr new file mode 100644 index 00000000000..92f8524a771 --- /dev/null +++ b/test_programs/execution_success/acir_inside_brillig_recursion/src/main.nr @@ -0,0 +1,15 @@ +fn main() { + assert_eq(fibonacci(3), fibonacci_hint(3)); +} + +unconstrained fn fibonacci_hint(x: u32) -> u32 { + fibonacci(x) +} + +fn fibonacci(x: u32) -> u32 { + if x <= 1 { + x + } else { + fibonacci(x - 1) + fibonacci(x - 2) + } +} diff --git a/test_programs/execution_success/aes128_encrypt/Nargo.toml b/test_programs/execution_success/aes128_encrypt/Nargo.toml new file mode 100644 index 00000000000..29425131cff --- /dev/null +++ b/test_programs/execution_success/aes128_encrypt/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "aes128_encrypt" +type = "bin" +authors = [""] +compiler_version = ">=0.27.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/aes128_encrypt/Prover.toml b/test_programs/execution_success/aes128_encrypt/Prover.toml new file mode 100644 index 00000000000..b6b684790e1 --- /dev/null +++ b/test_programs/execution_success/aes128_encrypt/Prover.toml @@ -0,0 +1,4 @@ +inputs = "kevlovesrust" +iv = "0000000000000000" +key = "0000000000000000" +output = "F40E7EACAB28D0BAADB8E269EE7ACDBF" \ No newline at end of file diff --git a/test_programs/execution_success/aes128_encrypt/src/main.nr b/test_programs/execution_success/aes128_encrypt/src/main.nr new file mode 100644 index 00000000000..f6ed0f309c3 --- /dev/null +++ b/test_programs/execution_success/aes128_encrypt/src/main.nr @@ -0,0 +1,44 @@ +use dep::std; + +unconstrained fn decode_ascii(ascii: u8) -> u8 { + if ascii < 58 { + ascii - 48 + } else if ascii < 71 { + ascii - 55 + } else { + ascii - 87 + } +} + +unconstrained fn decode_hex(s: str) -> [u8; M] { + let mut result: [u8; M] = [0; M]; + let as_bytes = s.as_bytes(); + for i in 0..N { + if i % 2 != 0 { + continue; + } + result[i/2] = decode_ascii(as_bytes[i]) * 16 + decode_ascii(as_bytes[i + 1]); + } + result +} + +unconstrained fn cipher(plaintext: [u8; 12], iv: [u8; 16], key: [u8; 16]) -> [u8; 16] { + let slice_res = std::aes128::aes128_encrypt(plaintext, iv, key); + let mut result = [0; 16]; + for i in 0..16 { + result[i] = slice_res[i]; + } + result +} + +fn main(inputs: str<12>, iv: str<16>, key: str<16>, output: str<32>) { + let result = std::aes128::aes128_encrypt(inputs.as_bytes(), iv.as_bytes(), key.as_bytes()); + let output_bytes: [u8; 16] = decode_hex(output); + for i in 0..16 { + assert(result[i] == output_bytes[i]); + } + let unconstrained_result = cipher(inputs.as_bytes(), iv.as_bytes(), key.as_bytes()); + for i in 0..16 { + assert(unconstrained_result[i] == output_bytes[i]); + } +} diff --git a/test_programs/execution_success/array_if_cond_simple/Nargo.toml b/test_programs/execution_success/array_if_cond_simple/Nargo.toml new file mode 100644 index 00000000000..b885d22c019 --- /dev/null +++ b/test_programs/execution_success/array_if_cond_simple/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "array_if_cond_simple" +type = "bin" +authors = [""] +compiler_version = ">=0.28.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/array_if_cond_simple/Prover.toml b/test_programs/execution_success/array_if_cond_simple/Prover.toml new file mode 100644 index 00000000000..2825143e8ad --- /dev/null +++ b/test_programs/execution_success/array_if_cond_simple/Prover.toml @@ -0,0 +1,2 @@ +x = true +y = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] \ No newline at end of file diff --git a/test_programs/execution_success/array_if_cond_simple/src/main.nr b/test_programs/execution_success/array_if_cond_simple/src/main.nr new file mode 100644 index 00000000000..ee2f762d43c --- /dev/null +++ b/test_programs/execution_success/array_if_cond_simple/src/main.nr @@ -0,0 +1,8 @@ +fn main(x: bool, mut y: [u32; 30]) { + if x { + y[0] = 1; + } + + let z = y[0] + y[1]; + assert(z == 1); +} diff --git a/test_programs/execution_success/array_len/src/main.nr b/test_programs/execution_success/array_len/src/main.nr index f846cfb9844..45c09b8a282 100644 --- a/test_programs/execution_success/array_len/src/main.nr +++ b/test_programs/execution_success/array_len/src/main.nr @@ -1,12 +1,12 @@ -fn len_plus_1(array: [T; N]) -> u64 { +fn len_plus_1(array: [T; N]) -> u32 { array.len() + 1 } -fn add_lens(a: [T; N], b: [Field; M]) -> u64 { +fn add_lens(a: [T; N], b: [Field; M]) -> u32 { a.len() + b.len() } -fn nested_call(b: [Field; N]) -> u64 { +fn nested_call(b: [Field; N]) -> u32 { len_plus_1(b) } diff --git a/test_programs/execution_success/array_to_slice/Nargo.toml b/test_programs/execution_success/array_to_slice/Nargo.toml new file mode 100644 index 00000000000..90c67b07b2b --- /dev/null +++ b/test_programs/execution_success/array_to_slice/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "array_to_slice" +type = "bin" +authors = [""] +compiler_version = ">=0.24.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/array_to_slice/Prover.toml b/test_programs/execution_success/array_to_slice/Prover.toml new file mode 100644 index 00000000000..26fdbc19975 --- /dev/null +++ b/test_programs/execution_success/array_to_slice/Prover.toml @@ -0,0 +1,2 @@ +x = "0" +y = "1" diff --git a/test_programs/execution_success/array_to_slice/src/main.nr b/test_programs/execution_success/array_to_slice/src/main.nr new file mode 100644 index 00000000000..0d0f9562d7b --- /dev/null +++ b/test_programs/execution_success/array_to_slice/src/main.nr @@ -0,0 +1,56 @@ +// Converts an array into a slice. +fn as_slice_push(xs: [T; N]) -> [T] { + let mut slice = &[]; + for elem in xs { + slice = slice.push_back(elem); + } + slice +} + +// Expected that x == 0 and y == 1 +fn main(x: Field, y: pub Field) { + let xs: [Field; 0] = []; + let ys: [Field; 1] = [1]; + let zs: [Field; 2] = [1, 2]; + let ws: [Field; 3] = [1; 3]; + let qs: [Field; 4] = [3, 2, 1, 0]; + + let mut dynamic: [Field; 4] = [3, 2, 1, 0]; + let dynamic_expected: [Field; 4] = [1000, 2, 1, 0]; + dynamic[x] = 1000; + + assert(x != y); + assert(xs.as_slice() == as_slice_push(xs)); + assert(ys.as_slice() == as_slice_push(ys)); + assert(zs.as_slice() == as_slice_push(zs)); + assert(ws.as_slice() == as_slice_push(ws)); + assert(qs.as_slice() == as_slice_push(qs)); + + assert(dynamic.as_slice()[0] == dynamic_expected[0]); + assert(dynamic.as_slice()[1] == dynamic_expected[1]); + assert(dynamic.as_slice()[2] == dynamic_expected[2]); + assert(dynamic.as_slice()[3] == dynamic_expected[3]); + assert(dynamic.as_slice().len() == 4); + + regression_4609_append_slices(x, y); + regression_4609_append_dynamic_slices(x, y); +} + +fn regression_4609_append_slices(x: Field, y: Field) { + let sl = [x, 1, 2, 3].as_slice(); + let sl2 = [y, 5, 6].as_slice(); + let sl3 = sl.append(sl2); + assert(sl3[0] == x); + assert(sl3[4] == y); +} + +fn regression_4609_append_dynamic_slices(x: Field, y: Field) { + let mut sl = [x, 1, 2, 3].as_slice(); + sl[x] = x + 10; + let mut sl2 = [y, 5, 6].as_slice(); + sl2[y] = y + 5; + let sl3 = sl.append(sl2); + assert(sl3[0] == 10); + assert(sl3[4] == y); + assert(sl3[5] == 6); +} diff --git a/test_programs/execution_success/array_to_slice_constant_length/Nargo.toml b/test_programs/execution_success/array_to_slice_constant_length/Nargo.toml new file mode 100644 index 00000000000..b338cf9b6ae --- /dev/null +++ b/test_programs/execution_success/array_to_slice_constant_length/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "array_to_slice_constant_length" +type = "bin" +authors = [""] +compiler_version = ">=0.26.0" + +[dependencies] diff --git a/test_programs/execution_success/array_to_slice_constant_length/Prover.toml b/test_programs/execution_success/array_to_slice_constant_length/Prover.toml new file mode 100644 index 00000000000..a52e9d3c46a --- /dev/null +++ b/test_programs/execution_success/array_to_slice_constant_length/Prover.toml @@ -0,0 +1 @@ +val = "42" diff --git a/test_programs/execution_success/array_to_slice_constant_length/src/main.nr b/test_programs/execution_success/array_to_slice_constant_length/src/main.nr new file mode 100644 index 00000000000..e81dd4a0c5f --- /dev/null +++ b/test_programs/execution_success/array_to_slice_constant_length/src/main.nr @@ -0,0 +1,10 @@ +// Regression test for https://github.com/noir-lang/noir/issues/4722 + +unconstrained fn return_array(val: Field) -> [Field; 1] { + [val; 1] +} + +fn main(val: Field) { + let array = return_array(val); + assert_constant(array.as_slice().len()); +} diff --git a/test_programs/execution_success/bigint/src/main.nr b/test_programs/execution_success/bigint/src/main.nr index b93fec370e5..c454c2b66cd 100644 --- a/test_programs/execution_success/bigint/src/main.nr +++ b/test_programs/execution_success/bigint/src/main.nr @@ -1,16 +1,78 @@ use dep::std::bigint; +use dep::std::{bigint::Secpk1Fq, println}; fn main(mut x: [u8; 5], y: [u8; 5]) { - let a = bigint::Secpk1Fq::from_le_bytes([x[0], x[1], x[2], x[3], x[4]]); - let b = bigint::Secpk1Fq::from_le_bytes([y[0], y[1], y[2], y[3], y[4]]); + let a = bigint::Secpk1Fq::from_le_bytes(&[x[0], x[1], x[2], x[3], x[4]]); + let b = bigint::Secpk1Fq::from_le_bytes(&[y[0], y[1], y[2], y[3], y[4]]); + let mut a_be_bytes = [0; 32]; + let mut b_be_bytes = [0; 32]; + for i in 0..5 { + a_be_bytes[31-i] = x[i]; + b_be_bytes[31-i] = y[i]; + } + let a_field = dep::std::field::bytes32_to_field(a_be_bytes); + let b_field = dep::std::field::bytes32_to_field(b_be_bytes); + + // Regression for issue #4682 + let c = if x[0] != 0 { + test_unconstrained1(a, b) + } else { + test_unconstrained2(a, b) + }; + assert(c.array[0] == dep::std::wrapping_mul(x[0], y[0])); + let a_bytes = a.to_le_bytes(); let b_bytes = b.to_le_bytes(); for i in 0..5 { assert(a_bytes[i] == x[i]); assert(b_bytes[i] == y[i]); } + // Regression for issue #4578 + let d = a * b; + assert(d / b == a); - let d = a * b - b; - let d1 = bigint::Secpk1Fq::from_le_bytes(597243850900842442924.to_le_bytes(10)); + let d = d - b; + let mut result = [0; 32]; + let result_slice = (a_field * b_field - b_field).to_le_bytes(32); + for i in 0..32 { + result[i] = result_slice[i]; + } + let d1 = bigint::Secpk1Fq::from_le_bytes_32(result); assert(d1 == d); + big_int_example(x[0], x[1]); + + // Regression for issue #4882 + let num_b:[u8;32] = [ + 0, 0, 0, 240, 147, 245, 225, 67, 145, 112, 185, 121, 72, 232, 51, 40, 93, 88, 129, 129, 182, 69, 80, 184, 41, 160, 49, 225, 114, 78, 100, 48 + ]; + let num2_b:[u8;7] = [126, 193, 45, 39, 188, 84, 11]; + let num = bigint::Bn254Fr::from_le_bytes(num_b.as_slice()); + let num2 = bigint::Bn254Fr::from_le_bytes(num2_b.as_slice()); + + let ret_b:[u8;32] = [ + 131, 62, 210, 200, 215, 160, 214, 67, 145, 112, 185, 121, 72, 232, 51, 40, 93, 88, 129, 129, 182, 69, 80, 184, 41, 160, 49, 225, 114, 78, 100, 48 + ]; + let ret = bigint::Bn254Fr::from_le_bytes(ret_b.as_slice()); + assert(ret == num.mul(num2)); + let div = num.div(num2); + assert(div.mul(num2) == num); +} + +fn test_unconstrained1(a: Secpk1Fq, b: Secpk1Fq) -> Secpk1Fq { + let c = a * b; + c +} +unconstrained fn test_unconstrained2(a: Secpk1Fq, b: Secpk1Fq) -> Secpk1Fq { + let c = a + b; + test_unconstrained1(a, c) +} + +// docs:start:big_int_example +fn big_int_example(x: u8, y: u8) { + let a = Secpk1Fq::from_le_bytes(&[x, y, 0, 45, 2]); + let b = Secpk1Fq::from_le_bytes(&[y, x, 9]); + let c = (a + b) * b / a; + let d = c.to_le_bytes(); + println(d[0]); } +// docs:end:big_int_example diff --git a/test_programs/execution_success/bit_shifts_comptime/src/main.nr b/test_programs/execution_success/bit_shifts_comptime/src/main.nr index 9184b5bd5e6..6d9736b6abb 100644 --- a/test_programs/execution_success/bit_shifts_comptime/src/main.nr +++ b/test_programs/execution_success/bit_shifts_comptime/src/main.nr @@ -14,7 +14,7 @@ fn main(x: u64) { //regression for 3481 assert(x << 63 == 0); - assert_eq((1 as u64) << (32 as u64), 0x0100000000); + assert_eq((1 as u64) << 32, 0x0100000000); } fn regression_2250() { diff --git a/test_programs/execution_success/bit_shifts_runtime/src/main.nr b/test_programs/execution_success/bit_shifts_runtime/src/main.nr index 28b3ef656c1..059bbe84dac 100644 --- a/test_programs/execution_success/bit_shifts_runtime/src/main.nr +++ b/test_programs/execution_success/bit_shifts_runtime/src/main.nr @@ -1,4 +1,4 @@ -fn main(x: u64, y: u64) { +fn main(x: u64, y: u8) { // runtime shifts on compile-time known values assert(64 << y == 128); assert(64 >> y == 32); @@ -7,14 +7,14 @@ fn main(x: u64, y: u64) { assert(x >> y == 32); // Bit-shift with signed integers - let mut a :i8 = y as i8; + let mut a: i8 = y as i8; let mut b: i8 = x as i8; assert(b << 1 == -128); assert(b >> 2 == 16); - assert(b >> a == 32); + assert(b >> y == 32); a = -a; assert(a << 7 == -128); - assert(a << -a == -2); + assert(a << y == -2); - assert(x >> x == 0); + assert(x >> (x as u8) == 0); } diff --git a/test_programs/execution_success/break_and_continue/Nargo.toml b/test_programs/execution_success/break_and_continue/Nargo.toml new file mode 100644 index 00000000000..483602478ba --- /dev/null +++ b/test_programs/execution_success/break_and_continue/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "break_and_continue" +type = "bin" +authors = [""] +compiler_version = ">=0.24.0" + +[dependencies] diff --git a/test_programs/execution_success/break_and_continue/src/main.nr b/test_programs/execution_success/break_and_continue/src/main.nr new file mode 100644 index 00000000000..67dce03ac64 --- /dev/null +++ b/test_programs/execution_success/break_and_continue/src/main.nr @@ -0,0 +1,15 @@ +unconstrained fn main() { + let mut count = 0; + + for i in 0..10 { + if i == 2 { + continue; + } + if i == 5 { + break; + } + count += 1; + } + + assert(count == 4); +} diff --git a/test_programs/execution_success/brillig_array_eq/Prover.toml b/test_programs/execution_success/brillig_array_eq/Prover.toml deleted file mode 100644 index ecfed7de213..00000000000 --- a/test_programs/execution_success/brillig_array_eq/Prover.toml +++ /dev/null @@ -1,2 +0,0 @@ -a = [77,75,108,209,54,16,50,202,155,210,174,185,217,0,170,77,69,217,234,216,10,201,66,51,116,196,81,167,37,77,7,102] -b = [77,75,108,209,54,16,50,202,155,210,174,185,217,0,170,77,69,217,234,216,10,201,66,51,116,196,81,167,37,77,7,102] diff --git a/test_programs/execution_success/brillig_array_eq/src/main.nr b/test_programs/execution_success/brillig_array_eq/src/main.nr deleted file mode 100644 index 90f631dbed8..00000000000 --- a/test_programs/execution_success/brillig_array_eq/src/main.nr +++ /dev/null @@ -1,4 +0,0 @@ -// Simple example of checking where two arrays are equal -unconstrained fn main(a: [Field; 32], b: [Field; 32]) { - assert(a == b); -} diff --git a/test_programs/execution_success/brillig_array_to_slice/Nargo.toml b/test_programs/execution_success/brillig_array_to_slice/Nargo.toml new file mode 100644 index 00000000000..58157c38c26 --- /dev/null +++ b/test_programs/execution_success/brillig_array_to_slice/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "brillig_array_to_slice" +type = "bin" +authors = [""] +compiler_version = ">=0.25.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/brillig_array_to_slice/Prover.toml b/test_programs/execution_success/brillig_array_to_slice/Prover.toml new file mode 100644 index 00000000000..11497a473bc --- /dev/null +++ b/test_programs/execution_success/brillig_array_to_slice/Prover.toml @@ -0,0 +1 @@ +x = "0" diff --git a/test_programs/execution_success/brillig_array_to_slice/src/main.nr b/test_programs/execution_success/brillig_array_to_slice/src/main.nr new file mode 100644 index 00000000000..262d3b5d86a --- /dev/null +++ b/test_programs/execution_success/brillig_array_to_slice/src/main.nr @@ -0,0 +1,18 @@ +unconstrained fn brillig_as_slice(x: Field) -> (u32, Field, Field) { + let mut dynamic: [Field; 1] = [1]; + dynamic[x] = 2; + assert(dynamic[0] == 2); + + let brillig_slice = dynamic.as_slice(); + assert(brillig_slice.len() == 1); + + (brillig_slice.len(), dynamic[0], brillig_slice[0]) +} + +fn main(x: Field) { + let (slice_len, dynamic_0, slice_0) = brillig_as_slice(x); + assert(slice_len == 1); + assert(dynamic_0 == 2); + assert(slice_0 == 2); +} + diff --git a/test_programs/execution_success/brillig_bit_shifts_runtime/Prover.toml b/test_programs/execution_success/brillig_bit_shifts_runtime/Prover.toml deleted file mode 100644 index 98d8630792e..00000000000 --- a/test_programs/execution_success/brillig_bit_shifts_runtime/Prover.toml +++ /dev/null @@ -1,2 +0,0 @@ -x = 64 -y = 1 \ No newline at end of file diff --git a/test_programs/execution_success/brillig_bit_shifts_runtime/src/main.nr b/test_programs/execution_success/brillig_bit_shifts_runtime/src/main.nr deleted file mode 100644 index f22166b5993..00000000000 --- a/test_programs/execution_success/brillig_bit_shifts_runtime/src/main.nr +++ /dev/null @@ -1,20 +0,0 @@ -unconstrained 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); - - // Bit-shift with signed integers - let mut a :i8 = y as i8; - let mut b: i8 = x as i8; - assert(b << 1 == -128); - assert(b >> 2 == 16); - assert(b >> a == 32); - a = -a; - assert(a << 7 == -128); - assert(a << -a == -2); - - assert(x >> x == 0); -} diff --git a/test_programs/execution_success/brillig_block_parameter_liveness/Nargo.toml b/test_programs/execution_success/brillig_block_parameter_liveness/Nargo.toml new file mode 100644 index 00000000000..e094862a1dc --- /dev/null +++ b/test_programs/execution_success/brillig_block_parameter_liveness/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "brillig_block_parameter_liveness" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/brillig_block_parameter_liveness/Prover.toml b/test_programs/execution_success/brillig_block_parameter_liveness/Prover.toml new file mode 100644 index 00000000000..6b7fd9c6ab6 --- /dev/null +++ b/test_programs/execution_success/brillig_block_parameter_liveness/Prover.toml @@ -0,0 +1 @@ +conditions = ["1", "0", "1", "0", "1"] diff --git a/test_programs/execution_success/brillig_block_parameter_liveness/src/main.nr b/test_programs/execution_success/brillig_block_parameter_liveness/src/main.nr new file mode 100644 index 00000000000..142290ecbe2 --- /dev/null +++ b/test_programs/execution_success/brillig_block_parameter_liveness/src/main.nr @@ -0,0 +1,91 @@ +// Tests that we run liveness in block parameters by trying to create too many block parameters to fit in the stack + +// Uses up 10 stack items +struct Inner { + a: u64, + b: u64, + c: u64, + d: u64, + e: u64, + f: u64, + g: u64, + h: u64, + i: u64, + j: u64, +} + +// Uses up 50 stack items +struct Middle { + inner_a: Inner, + inner_b: Inner, + inner_c: Inner, + inner_d: Inner, + inner_e: Inner, +} + +// Uses up 500 stack items +struct Outer { + middle_a: Middle, + middle_b: Middle, + middle_c: Middle, + middle_d: Middle, + middle_e: Middle, + middle_f: Middle, + middle_g: Middle, + middle_h: Middle, +} + +// If we don't take into account block parameter liveness, this function will need 5*500=2500 stack items +unconstrained fn main(conditions: [bool; 5]) -> pub Outer { + let out0 = if conditions[0] { + let mut outer: Outer = dep::std::unsafe::zeroed(); + outer.middle_a.inner_a.a = 1; + outer + } else { + let mut outer: Outer= dep::std::unsafe::zeroed(); + outer.middle_f.inner_c.d = 2; + outer + }; + + let out1 = if conditions[1] { + let mut new_outer = out0; + new_outer.middle_a.inner_a.b = 3; + new_outer + } else { + let mut new_outer = out0; + new_outer.middle_f.inner_c.c = 4; + new_outer + }; + + let out2 = if conditions[2] { + let mut new_outer = out1; + new_outer.middle_a.inner_a.c = 5; + new_outer + } else { + let mut new_outer = out1; + new_outer.middle_f.inner_c.b = 6; + new_outer + }; + + let out3 = if conditions[3] { + let mut new_outer = out2; + new_outer.middle_a.inner_a.d = 7; + new_outer + } else { + let mut new_outer = out2; + new_outer.middle_f.inner_c.a = 8; + new_outer + }; + + let out4 = if conditions[4] { + let mut new_outer = out3; + new_outer.middle_a.inner_a.f = 9; + new_outer + } else { + let mut new_outer = out3; + new_outer.middle_f.inner_c.f = 10; + new_outer + }; + + out4 +} diff --git a/test_programs/execution_success/brillig_cow_assign/Nargo.toml b/test_programs/execution_success/brillig_cow_assign/Nargo.toml new file mode 100644 index 00000000000..a878566a372 --- /dev/null +++ b/test_programs/execution_success/brillig_cow_assign/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "brillig_cow_assign" +type = "bin" +authors = [""] +compiler_version = ">=0.23.0" + +[dependencies] diff --git a/test_programs/execution_success/brillig_cow_assign/Prover.toml b/test_programs/execution_success/brillig_cow_assign/Prover.toml new file mode 100644 index 00000000000..882c73b83f8 --- /dev/null +++ b/test_programs/execution_success/brillig_cow_assign/Prover.toml @@ -0,0 +1,2 @@ +items_to_update = 10 +index = 6 diff --git a/test_programs/execution_success/brillig_cow_assign/src/main.nr b/test_programs/execution_success/brillig_cow_assign/src/main.nr new file mode 100644 index 00000000000..e5c3e2bd2f5 --- /dev/null +++ b/test_programs/execution_success/brillig_cow_assign/src/main.nr @@ -0,0 +1,23 @@ +global N = 10; + +unconstrained fn main() { + let mut arr = [0; N]; + let mut mid_change = arr; + + for i in 0..N { + if i == N / 2 { + mid_change = arr; + } + arr[i] = 27; + } + + // Expect: + // arr = [27, 27, 27, 27, 27, 27, 27, 27, 27, 27] + // mid_change = [27, 27, 27, 27, 27, 0, 0, 0, 0, 0] + + let modified_i = N / 2 + 1; + assert_eq(arr[modified_i], 27); + + // Fail here! + assert(mid_change[modified_i] != 27); +} diff --git a/test_programs/execution_success/brillig_cow_regression/src/main.nr b/test_programs/execution_success/brillig_cow_regression/src/main.nr index ba51548d9dd..1cae9b1ba41 100644 --- a/test_programs/execution_success/brillig_cow_regression/src/main.nr +++ b/test_programs/execution_success/brillig_cow_regression/src/main.nr @@ -8,9 +8,9 @@ global MAX_NEW_CONTRACTS_PER_TX: u64 = 1; global NUM_ENCRYPTED_LOGS_HASHES_PER_TX: u64 = 1; global NUM_UNENCRYPTED_LOGS_HASHES_PER_TX: u64 = 1; global NUM_FIELDS_PER_SHA256 = 2; -global CALLDATA_HASH_INPUT_SIZE = 169; -global CALL_DATA_HASH_LOG_FIELDS = 4; -global CALL_DATA_HASH_FULL_FIELDS = 165; +global TX_EFFECT_HASH_INPUT_SIZE = 169; +global TX_EFFECT_HASH_LOG_FIELDS = 4; +global TX_EFFECT_HASH_FULL_FIELDS = 165; struct PublicDataUpdateRequest { leaf_slot : Field, @@ -99,7 +99,7 @@ impl U256 { } unconstrained fn main(kernel_data: DataToHash) -> pub [Field; NUM_FIELDS_PER_SHA256] { - let mut calldata_hash_inputs = [0; CALLDATA_HASH_INPUT_SIZE]; + let mut tx_effects_hash_inputs = [0; TX_EFFECT_HASH_INPUT_SIZE]; let new_note_hashes = kernel_data.new_note_hashes; let new_nullifiers = kernel_data.new_nullifiers; @@ -111,65 +111,65 @@ unconstrained fn main(kernel_data: DataToHash) -> pub [Field; NUM_FIELDS_PER_SHA let mut offset = 0; for j in 0..MAX_NEW_NOTE_HASHES_PER_TX { - calldata_hash_inputs[offset + j] = new_note_hashes[j]; + tx_effects_hash_inputs[offset + j] = new_note_hashes[j]; } offset += MAX_NEW_NOTE_HASHES_PER_TX ; for j in 0..MAX_NEW_NULLIFIERS_PER_TX { - calldata_hash_inputs[offset + j] = new_nullifiers[j]; + tx_effects_hash_inputs[offset + j] = new_nullifiers[j]; } offset += MAX_NEW_NULLIFIERS_PER_TX ; for j in 0..MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX { - calldata_hash_inputs[offset + j * 2] = + tx_effects_hash_inputs[offset + j * 2] = public_data_update_requests[j].leaf_slot; - calldata_hash_inputs[offset + j * 2 + 1] = + tx_effects_hash_inputs[offset + j * 2 + 1] = public_data_update_requests[j].new_value; } offset += MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * 2; for j in 0..MAX_NEW_L2_TO_L1_MSGS_PER_TX { - calldata_hash_inputs[offset + j] = newL2ToL1msgs[j]; + tx_effects_hash_inputs[offset + j] = newL2ToL1msgs[j]; } offset += MAX_NEW_L2_TO_L1_MSGS_PER_TX; let contract_leaf = kernel_data.new_contracts[0]; - calldata_hash_inputs[offset] = contract_leaf.hash(); + tx_effects_hash_inputs[offset] = contract_leaf.hash(); offset += MAX_NEW_CONTRACTS_PER_TX; let new_contracts = kernel_data.new_contracts; - calldata_hash_inputs[offset] = new_contracts[0].contract_address; + tx_effects_hash_inputs[offset] = new_contracts[0].contract_address; - calldata_hash_inputs[offset + 1] = new_contracts[0].portal_contract_address; + tx_effects_hash_inputs[offset + 1] = new_contracts[0].portal_contract_address; offset += MAX_NEW_CONTRACTS_PER_TX * 2; for j in 0..NUM_FIELDS_PER_SHA256 { - calldata_hash_inputs[offset + j] = encryptedLogsHash[j]; + tx_effects_hash_inputs[offset + j] = encryptedLogsHash[j]; } offset += NUM_ENCRYPTED_LOGS_HASHES_PER_TX * NUM_FIELDS_PER_SHA256; for j in 0..NUM_FIELDS_PER_SHA256 { - calldata_hash_inputs[offset + j] = unencryptedLogsHash[j]; + tx_effects_hash_inputs[offset + j] = unencryptedLogsHash[j]; } offset += NUM_UNENCRYPTED_LOGS_HASHES_PER_TX * NUM_FIELDS_PER_SHA256; - assert_eq(offset, CALLDATA_HASH_INPUT_SIZE); // Sanity check + assert_eq(offset, TX_EFFECT_HASH_INPUT_SIZE); // Sanity check - let mut hash_input_flattened = [0; CALL_DATA_HASH_FULL_FIELDS * 32 + CALL_DATA_HASH_LOG_FIELDS * 16]; - for offset in 0..CALL_DATA_HASH_FULL_FIELDS { - let input_as_bytes = calldata_hash_inputs[offset].to_be_bytes(32); + let mut hash_input_flattened = [0; TX_EFFECT_HASH_FULL_FIELDS * 32 + TX_EFFECT_HASH_LOG_FIELDS * 16]; + for offset in 0..TX_EFFECT_HASH_FULL_FIELDS { + let input_as_bytes = tx_effects_hash_inputs[offset].to_be_bytes(32); for byte_index in 0..32 { hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index]; } } - for log_field_index in 0..CALL_DATA_HASH_LOG_FIELDS { - let input_as_bytes = calldata_hash_inputs[CALL_DATA_HASH_FULL_FIELDS + log_field_index].to_be_bytes(16); + for log_field_index in 0..TX_EFFECT_HASH_LOG_FIELDS { + let input_as_bytes = tx_effects_hash_inputs[TX_EFFECT_HASH_FULL_FIELDS + log_field_index].to_be_bytes(16); for byte_index in 0..16 { - hash_input_flattened[CALL_DATA_HASH_FULL_FIELDS * 32 + log_field_index * 16 + byte_index] = input_as_bytes[byte_index]; + hash_input_flattened[TX_EFFECT_HASH_FULL_FIELDS * 32 + log_field_index * 16 + byte_index] = input_as_bytes[byte_index]; } } diff --git a/test_programs/execution_success/brillig_fns_as_values/Prover.toml b/test_programs/execution_success/brillig_fns_as_values/Prover.toml index 11497a473bc..4dd6b405159 100644 --- a/test_programs/execution_success/brillig_fns_as_values/Prover.toml +++ b/test_programs/execution_success/brillig_fns_as_values/Prover.toml @@ -1 +1 @@ -x = "0" +x = "1" diff --git a/test_programs/execution_success/brillig_fns_as_values/src/main.nr b/test_programs/execution_success/brillig_fns_as_values/src/main.nr index 207a88985be..5a0b967f583 100644 --- a/test_programs/execution_success/brillig_fns_as_values/src/main.nr +++ b/test_programs/execution_success/brillig_fns_as_values/src/main.nr @@ -8,9 +8,9 @@ fn main(x: u32) { unsafe { assert(wrapper(increment, x) == x + 1); assert(wrapper(increment_acir, x) == x + 1); - assert(wrapper(decrement, x) == std::wrapping_sub(x, 1)); + assert(wrapper(decrement, x) == x - 1); assert(wrapper_with_struct(MyStruct { operation: increment }, x) == x + 1); - assert(wrapper_with_struct(MyStruct { operation: decrement }, x) == std::wrapping_sub(x, 1)); + assert(wrapper_with_struct(MyStruct { operation: decrement }, x) == x - 1); // https://github.com/noir-lang/noir/issues/1975 assert(increment(x) == x + 1); } diff --git a/test_programs/execution_success/brillig_hash_to_field/src/main.nr b/test_programs/execution_success/brillig_hash_to_field/src/main.nr index dadf8441284..2e3f8474ce6 100644 --- a/test_programs/execution_success/brillig_hash_to_field/src/main.nr +++ b/test_programs/execution_success/brillig_hash_to_field/src/main.nr @@ -9,5 +9,5 @@ fn main(input: Field) -> pub Field { } unconstrained fn hash_to_field(input: Field) -> Field { - std::hash::hash_to_field([input]) + std::hash::hash_to_field(&[input]) } diff --git a/test_programs/execution_success/brillig_keccak/src/main.nr b/test_programs/execution_success/brillig_keccak/src/main.nr index 26072e2e432..46ffed88283 100644 --- a/test_programs/execution_success/brillig_keccak/src/main.nr +++ b/test_programs/execution_success/brillig_keccak/src/main.nr @@ -8,7 +8,7 @@ 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 + //#1399: variable message 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); diff --git a/test_programs/execution_success/brillig_scalar_mul/Prover.toml b/test_programs/execution_success/brillig_scalar_mul/Prover.toml deleted file mode 100644 index 69b91cb5f31..00000000000 --- a/test_programs/execution_success/brillig_scalar_mul/Prover.toml +++ /dev/null @@ -1,7 +0,0 @@ -a = "1" -a_pub_x = "0x0000000000000000000000000000000000000000000000000000000000000001" -a_pub_y = "0x0000000000000002cf135e7506a45d632d270d45f1181294833fc48d823f272c" - -b = "2" -b_pub_x = "0x06ce1b0827aafa85ddeb49cdaa36306d19a74caa311e13d46d8bc688cdbffffe" -b_pub_y = "0x1c122f81a3a14964909ede0ba2a6855fc93faf6fa1a788bf467be7e7a43f80ac" \ No newline at end of file diff --git a/test_programs/execution_success/brillig_scalar_mul/src/main.nr b/test_programs/execution_success/brillig_scalar_mul/src/main.nr deleted file mode 100644 index c7c3a85a4ff..00000000000 --- a/test_programs/execution_success/brillig_scalar_mul/src/main.nr +++ /dev/null @@ -1,32 +0,0 @@ -use dep::std; - -unconstrained fn main( - a: Field, - a_pub_x: pub Field, - a_pub_y: pub Field, - b: Field, - b_pub_x: pub Field, - b_pub_y: pub Field -) { - let mut priv_key = a; - let mut pub_x: Field = a_pub_x; - let mut pub_y: Field = a_pub_y; - if a != 1 { - // Change `a` in Prover.toml to test input `b` - priv_key = b; - pub_x = b_pub_x; - pub_y = b_pub_y; - } - let res = std::scalar_mul::fixed_base_embedded_curve(priv_key, 0); - assert(res[0] == pub_x); - assert(res[1] == pub_y); - - let pub_point= std::scalar_mul::EmbeddedCurvePoint { x: pub_x, y: pub_y }; - let g1_y = 17631683881184975370165255887551781615748388533673675138860; - let g1= std::scalar_mul::EmbeddedCurvePoint { x: 1, y: g1_y }; - - let res = pub_point.double(); - let double = g1.add(g1); - - assert(double.x == res.x); -} diff --git a/test_programs/execution_success/brillig_schnorr/Prover.toml b/test_programs/execution_success/brillig_schnorr/Prover.toml deleted file mode 100644 index 2faf2018e07..00000000000 --- a/test_programs/execution_success/brillig_schnorr/Prover.toml +++ /dev/null @@ -1,70 +0,0 @@ -message = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] -message_field = "0x010203040506070809" -pub_key_x = "0x04b260954662e97f00cab9adb773a259097f7a274b83b113532bce27fa3fb96a" -pub_key_y = "0x2fd51571db6c08666b0edfbfbc57d432068bccd0110a39b166ab243da0037197" -signature = [ - 1, - 13, - 119, - 112, - 212, - 39, - 233, - 41, - 84, - 235, - 255, - 93, - 245, - 172, - 186, - 83, - 157, - 253, - 76, - 77, - 33, - 128, - 178, - 15, - 214, - 67, - 105, - 107, - 177, - 234, - 77, - 48, - 27, - 237, - 155, - 84, - 39, - 84, - 247, - 27, - 22, - 8, - 176, - 230, - 24, - 115, - 145, - 220, - 254, - 122, - 135, - 179, - 171, - 4, - 214, - 202, - 64, - 199, - 19, - 84, - 239, - 138, - 124, - 12, -] diff --git a/test_programs/execution_success/brillig_schnorr/src/main.nr b/test_programs/execution_success/brillig_schnorr/src/main.nr deleted file mode 100644 index 4cc79ae7e07..00000000000 --- a/test_programs/execution_success/brillig_schnorr/src/main.nr +++ /dev/null @@ -1,25 +0,0 @@ -use dep::std; -// Note: If main has any unsized types, then the verifier will never be able -// to figure out the circuit instance -unconstrained fn main( - message: [u8; 10], - message_field: Field, - pub_key_x: Field, - pub_key_y: Field, - signature: [u8; 64] -) { - // Regression for issue #2421 - // We want to make sure that we can accurately verify a signature whose message is a slice vs. an array - let message_field_bytes = message_field.to_be_bytes(10); - for i in 0..10 { - assert(message[i] == message_field_bytes[i]); - } - // Is there ever a situation where someone would want - // to ensure that a signature was invalid? - // Check that passing a slice as the message is valid - let valid_signature = std::schnorr::verify_signature(pub_key_x, pub_key_y, signature, message_field_bytes); - assert(valid_signature); - // Check that passing an array as the message is valid - let valid_signature = std::schnorr::verify_signature(pub_key_x, pub_key_y, signature, message); - assert(valid_signature); -} diff --git a/test_programs/execution_success/brillig_slices/src/main.nr b/test_programs/execution_success/brillig_slices/src/main.nr index 847c41de25c..2cf1850f151 100644 --- a/test_programs/execution_success/brillig_slices/src/main.nr +++ b/test_programs/execution_success/brillig_slices/src/main.nr @@ -1,6 +1,6 @@ use dep::std::slice; unconstrained fn main(x: Field, y: Field) { - let mut slice: [Field] = [y, x]; + let mut slice: [Field] = &[y, x]; assert(slice.len() == 2); slice = slice.push_back(7); @@ -108,7 +108,7 @@ unconstrained fn merge_slices_else(x: Field) { } // Test returning a merged slice without a mutation unconstrained fn merge_slices_return(x: Field, y: Field) -> [Field] { - let slice = [0; 2]; + let slice = &[0; 2]; if x != y { if x != 20 { slice.push_back(y) } else { slice } } else { @@ -117,7 +117,7 @@ unconstrained fn merge_slices_return(x: Field, y: Field) -> [Field] { } // Test mutating a slice inside of an if statement unconstrained fn merge_slices_mutate(x: Field, y: Field) -> [Field] { - let mut slice = [0; 2]; + let mut slice = &[0; 2]; if x != y { slice = slice.push_back(y); slice = slice.push_back(x); @@ -128,7 +128,7 @@ unconstrained fn merge_slices_mutate(x: Field, y: Field) -> [Field] { } // 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]; + let mut slice = &[0; 2]; if x != y { for i in 0..5 { slice = slice.push_back(i as Field); diff --git a/test_programs/execution_success/brillig_to_be_bytes/Nargo.toml b/test_programs/execution_success/brillig_to_be_bytes/Nargo.toml deleted file mode 100644 index df6c818c90f..00000000000 --- a/test_programs/execution_success/brillig_to_be_bytes/Nargo.toml +++ /dev/null @@ -1,6 +0,0 @@ -[package] -name = "brillig_to_be_bytes" -type = "bin" -authors = [""] - -[dependencies] diff --git a/test_programs/execution_success/brillig_to_be_bytes/Prover.toml b/test_programs/execution_success/brillig_to_be_bytes/Prover.toml deleted file mode 100644 index 07fe857ac7c..00000000000 --- a/test_programs/execution_success/brillig_to_be_bytes/Prover.toml +++ /dev/null @@ -1 +0,0 @@ -x = "2040124" diff --git a/test_programs/execution_success/brillig_to_be_bytes/src/main.nr b/test_programs/execution_success/brillig_to_be_bytes/src/main.nr deleted file mode 100644 index 9d78411f060..00000000000 --- a/test_programs/execution_success/brillig_to_be_bytes/src/main.nr +++ /dev/null @@ -1,12 +0,0 @@ -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]; - for i in 0..31 { - bytes[i] = byte_array[i]; - } - assert(bytes[30] == 60); - assert(bytes[29] == 33); - assert(bytes[28] == 31); - bytes -} diff --git a/test_programs/execution_success/brillig_to_bytes_integration/Nargo.toml b/test_programs/execution_success/brillig_to_bytes_integration/Nargo.toml deleted file mode 100644 index 991f3d1e46c..00000000000 --- a/test_programs/execution_success/brillig_to_bytes_integration/Nargo.toml +++ /dev/null @@ -1,6 +0,0 @@ -[package] -name = "brillig_to_bytes_integration" -type = "bin" -authors = [""] - -[dependencies] diff --git a/test_programs/execution_success/brillig_to_bytes_integration/Prover.toml b/test_programs/execution_success/brillig_to_bytes_integration/Prover.toml deleted file mode 100644 index 23f7acea449..00000000000 --- a/test_programs/execution_success/brillig_to_bytes_integration/Prover.toml +++ /dev/null @@ -1,2 +0,0 @@ -x = "2040124" -_y = "0x2000000000000000000000000000000000000000000000000000000000000000" diff --git a/test_programs/execution_success/brillig_to_bytes_integration/src/main.nr b/test_programs/execution_success/brillig_to_bytes_integration/src/main.nr deleted file mode 100644 index e8e5b9db9ca..00000000000 --- a/test_programs/execution_success/brillig_to_bytes_integration/src/main.nr +++ /dev/null @@ -1,27 +0,0 @@ -use dep::std; - -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]); - assert(le_byte_array[2] == be_byte_array[28]); - - let z = 0 - 1; - let p_bytes = std::field::modulus_le_bytes(); - let z_bytes = z.to_le_bytes(32); - assert(p_bytes[10] == z_bytes[10]); - assert(p_bytes[0] == z_bytes[0] as u8 + 1 as u8); - - let p_bits = std::field::modulus_le_bits(); - let z_bits = z.to_le_bits(std::field::modulus_num_bits() as u32); - assert(z_bits[0] == 0); - assert(p_bits[100] == z_bits[100]); - - _y.to_le_bits(std::field::modulus_num_bits() as u32); -} diff --git a/test_programs/execution_success/brillig_to_le_bytes/Nargo.toml b/test_programs/execution_success/brillig_to_le_bytes/Nargo.toml deleted file mode 100644 index c2ce8ad01b5..00000000000 --- a/test_programs/execution_success/brillig_to_le_bytes/Nargo.toml +++ /dev/null @@ -1,6 +0,0 @@ -[package] -name = "brillig_to_le_bytes" -type = "bin" -authors = [""] - -[dependencies] diff --git a/test_programs/execution_success/brillig_to_le_bytes/Prover.toml b/test_programs/execution_success/brillig_to_le_bytes/Prover.toml deleted file mode 100644 index 07fe857ac7c..00000000000 --- a/test_programs/execution_success/brillig_to_le_bytes/Prover.toml +++ /dev/null @@ -1 +0,0 @@ -x = "2040124" diff --git a/test_programs/execution_success/brillig_to_le_bytes/src/main.nr b/test_programs/execution_success/brillig_to_le_bytes/src/main.nr deleted file mode 100644 index 77d292cf01b..00000000000 --- a/test_programs/execution_success/brillig_to_le_bytes/src/main.nr +++ /dev/null @@ -1,10 +0,0 @@ -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); - let mut bytes = [0; 31]; - for i in 0..31 { - bytes[i] = byte_array[i]; - } - bytes -} diff --git a/test_programs/execution_success/brillig_top_level/Nargo.toml b/test_programs/execution_success/brillig_top_level/Nargo.toml deleted file mode 100644 index f74a2a82964..00000000000 --- a/test_programs/execution_success/brillig_top_level/Nargo.toml +++ /dev/null @@ -1,6 +0,0 @@ -[package] -name = "brillig_top_level" -type = "bin" -authors = [""] - -[dependencies] diff --git a/test_programs/execution_success/brillig_top_level/Prover.toml b/test_programs/execution_success/brillig_top_level/Prover.toml deleted file mode 100644 index a0150a0e562..00000000000 --- a/test_programs/execution_success/brillig_top_level/Prover.toml +++ /dev/null @@ -1,2 +0,0 @@ -x = "1" -array = ["4", "5", "6"] \ No newline at end of file diff --git a/test_programs/execution_success/brillig_top_level/src/main.nr b/test_programs/execution_success/brillig_top_level/src/main.nr deleted file mode 100644 index 6dfd98b2c3e..00000000000 --- a/test_programs/execution_success/brillig_top_level/src/main.nr +++ /dev/null @@ -1,6 +0,0 @@ -// Tests a very simple program. -// -// The feature being tested is brillig as the entry point. -unconstrained fn main(array: [Field; 3], x: pub Field) -> pub [Field; 2] { - [array[x], array[x + 1]] -} diff --git a/test_programs/execution_success/cast_and_shift_global/Nargo.toml b/test_programs/execution_success/cast_and_shift_global/Nargo.toml new file mode 100644 index 00000000000..92af6ed8333 --- /dev/null +++ b/test_programs/execution_success/cast_and_shift_global/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "cast_and_shift_global" +type = "bin" +authors = [""] +compiler_version = ">=0.30.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/dup_trait_implementation_4/Prover.toml b/test_programs/execution_success/cast_and_shift_global/Prover.toml similarity index 100% rename from test_programs/compile_failure/dup_trait_implementation_4/Prover.toml rename to test_programs/execution_success/cast_and_shift_global/Prover.toml diff --git a/test_programs/execution_success/cast_and_shift_global/src/main.nr b/test_programs/execution_success/cast_and_shift_global/src/main.nr new file mode 100644 index 00000000000..577de78465c --- /dev/null +++ b/test_programs/execution_success/cast_and_shift_global/src/main.nr @@ -0,0 +1,8 @@ +global THREE: u64 = 3; +global EIGHT: u64 = 1 << THREE as u8; +global SEVEN: u64 = EIGHT - 1; + +fn main() { + assert([0; EIGHT] == [0; 8]); + assert([0; SEVEN] == [0; 7]); +} diff --git a/test_programs/compile_success_empty/conditional_regression_547/Nargo.toml b/test_programs/execution_success/conditional_regression_547/Nargo.toml similarity index 100% rename from test_programs/compile_success_empty/conditional_regression_547/Nargo.toml rename to test_programs/execution_success/conditional_regression_547/Nargo.toml diff --git a/test_programs/compile_success_empty/conditional_regression_547/Prover.toml b/test_programs/execution_success/conditional_regression_547/Prover.toml similarity index 100% rename from test_programs/compile_success_empty/conditional_regression_547/Prover.toml rename to test_programs/execution_success/conditional_regression_547/Prover.toml diff --git a/test_programs/compile_success_empty/conditional_regression_547/src/main.nr b/test_programs/execution_success/conditional_regression_547/src/main.nr similarity index 100% rename from test_programs/compile_success_empty/conditional_regression_547/src/main.nr rename to test_programs/execution_success/conditional_regression_547/src/main.nr diff --git a/test_programs/execution_success/debug_logs/src/main.nr b/test_programs/execution_success/debug_logs/src/main.nr index ec24b0cc8e8..c7fd01ebbc5 100644 --- a/test_programs/execution_success/debug_logs/src/main.nr +++ b/test_programs/execution_success/debug_logs/src/main.nr @@ -71,6 +71,8 @@ fn main(x: Field, y: pub Field) { let closured_lambda = |x| x + one; println(f"closured_lambda: {closured_lambda}, sentinel: {sentinel}"); println(closured_lambda); + + regression_4967(); } fn string_identity(string: fmtstr<14, (Field, Field)>) -> fmtstr<14, (Field, Field)> { @@ -122,3 +124,14 @@ fn regression_2906() { println(f"array_five_vals: {array_five_vals}, label_five_vals: {label_five_vals}"); } +fn regression_4967() { + let sentinel: u32 = 8888; + + let slice_of_tuples: [(i32, u8)] = &[(11, 22), (33, 44)]; + println(f"slice_of_tuples: {slice_of_tuples}, sentinel: {sentinel}"); + println(slice_of_tuples); + + let slice_of_tuples_coerced: [(i32, u8)] = [(11, 22), (33, 44)]; + println(f"slice_of_tuples: {slice_of_tuples_coerced}, sentinel: {sentinel}"); + println(slice_of_tuples_coerced); +} diff --git a/test_programs/execution_success/distinct_keyword/src/main.nr b/test_programs/execution_success/distinct_keyword/src/main.nr deleted file mode 100644 index 8e9b5c008ed..00000000000 --- a/test_programs/execution_success/distinct_keyword/src/main.nr +++ /dev/null @@ -1,4 +0,0 @@ -// Example that uses the distinct keyword -fn main(x: pub Field) -> distinct pub [Field; 2] { - [x + 1, x] -} diff --git a/test_programs/execution_success/double_verify_nested_proof/src/main.nr b/test_programs/execution_success/double_verify_nested_proof/src/main.nr index 0466f2a226d..95d4b6f6995 100644 --- a/test_programs/execution_success/double_verify_nested_proof/src/main.nr +++ b/test_programs/execution_success/double_verify_nested_proof/src/main.nr @@ -1,10 +1,18 @@ use dep::std; +// This circuit aggregates two recursive proofs from `double_verify_proof_recursive`. +// Recursive aggregation is a backend-specific process and it is expected for backends +// to attach any extra data they may need (e.g. aggregation objects) to their proofs. +// Whether the proof we are verifying itself contains a recursive proof is expected to be +// a circuit constant by the barretenberg. Barretenberg hides this circuit constant in the +// proof serialization. Thus, we must have separate circuits for verifying a normal proof and a recursive proof +// with two different proof sizes. fn main( verification_key: [Field; 114], - // This is the proof without public inputs attached. - // - // This means: the size of this does not change with the number of public inputs. + // This is the proof without user-specified public inputs attached. + // + // This means: the size of this does not change with the number of public inputs unless + // they have been attached by the backend. proof: [Field; 109], public_inputs: pub [Field; 1], // This is currently not public. It is fine given that the vk is a part of the circuit definition. diff --git a/test_programs/execution_success/double_verify_proof/Nargo.toml b/test_programs/execution_success/double_verify_proof/Nargo.toml index a4edd2e4288..c5954f54bdb 100644 --- a/test_programs/execution_success/double_verify_proof/Nargo.toml +++ b/test_programs/execution_success/double_verify_proof/Nargo.toml @@ -2,4 +2,6 @@ name = "double_verify_proof" type = "bin" authors = [""] -[dependencies] +compiler_version = ">=0.24.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/double_verify_proof/src/main.nr b/test_programs/execution_success/double_verify_proof/src/main.nr index e4c6926efbc..d832ce0f049 100644 --- a/test_programs/execution_success/double_verify_proof/src/main.nr +++ b/test_programs/execution_success/double_verify_proof/src/main.nr @@ -1,6 +1,6 @@ use dep::std; -#[recursive] +// This circuit aggregates two proofs from `assert_statement_recursive`. fn main( verification_key: [Field; 114], // This is the proof without public inputs attached. diff --git a/test_programs/execution_success/double_verify_proof_recursive/Nargo.toml b/test_programs/execution_success/double_verify_proof_recursive/Nargo.toml new file mode 100644 index 00000000000..b7688b33bfd --- /dev/null +++ b/test_programs/execution_success/double_verify_proof_recursive/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "double_verify_proof_recursive" +type = "bin" +authors = [""] +[dependencies] diff --git a/test_programs/execution_success/double_verify_proof_recursive/Prover.toml b/test_programs/execution_success/double_verify_proof_recursive/Prover.toml new file mode 100644 index 00000000000..dff48212e50 --- /dev/null +++ b/test_programs/execution_success/double_verify_proof_recursive/Prover.toml @@ -0,0 +1,5 @@ +key_hash = "0x096129b1c6e108252fc5c829c4cc9b7e8f0d1fd9f29c2532b563d6396645e08f" +proof = ["0x000000000000000000000000000000d62b795bec274279129a71195796825fcc","0x00000000000000000000000000000000000793ab763140f20a68a6bd2721fd74","0x00000000000000000000000000000053141d06d3307b36153f321511199e579c","0x00000000000000000000000000000000000a4b55d6c21f98a9c434911dcb5c67","0x0000000000000000000000000000005f9d324c0abd22cec92d99dbec438e9491","0x0000000000000000000000000000000000240dfafe1b53dc27147cbab14ea893","0x000000000000000000000000000000044a61d3aac32c6931247cf334a19d9611","0x000000000000000000000000000000000003f0f8cf4207bfa85c23ec9f8d0c88","0x00000000000000000000000000000002168a470e39ba2ac266f6b474de12045f","0x000000000000000000000000000000000025791e7d3feab542345c00ec5a30df","0x000000000000000000000000000000dcafd76d4c3640969c80e017b951ef6397","0x00000000000000000000000000000000001d27f75a1256771e88e0c86fc42dbc","0x0000000000000000000000000000007347ae7d2d9d7fc2b8f0baa014ee1fed9f","0x000000000000000000000000000000000018bd927f42bf7caf9555f56f09000d","0x000000000000000000000000000000041f765f83cbe5904c8f453f70a4531d10","0x00000000000000000000000000000000001858aabeeb5331a221419f4fed1c19","0x000000000000000000000000000000d254a54caaedf8287b9af951b2f2611121","0x000000000000000000000000000000000005ab493623c9563cf2e55ba5f18200","0x00000000000000000000000000000014f24cddc1a02440dc63637df8032c8074","0x000000000000000000000000000000000011950c16cef98471b1d78b935195a4","0x000000000000000000000000000000b0340b459e6bd5cc8f031c8654a502897f","0x00000000000000000000000000000000000e1cf3968dac4545a76a2ae58e512c","0x0000000000000000000000000000002adf7218aa06ca0d2c2e600dcc39193a2d","0x00000000000000000000000000000000001302e7e4b0f14749bd885ca25588b6","0x00000000000000000000000000000092009ce4056e79ab815d8cdfd4491138ae","0x000000000000000000000000000000000018af11e853c6cf2f0f6274b0da8133","0x000000000000000000000000000000dd3dc6f49232141718527b3a0e4b26e21d","0x00000000000000000000000000000000001a877853348a8b695c4f9a9aa4ce68","0x000000000000000000000000000000aecfc56ba07155450b368140d6324023b5","0x000000000000000000000000000000000029c11052798c57ece614617d33fcc2","0x000000000000000000000000000000eb106ffc816d16fb84e84b0b61157b2603","0x000000000000000000000000000000000026c3cac16206899a21cb5126841446","0x000000000000000000000000000000a782ed54805fe845068b362b58e2fa34ec","0x00000000000000000000000000000000000cf046a1bfcc666b7f28b572676073","0x000000000000000000000000000000b931c8dda60bb4aca4cc817f5540f1209f","0x000000000000000000000000000000000024ad50c3936fafc3d190e6a4874223","0x000000000000000000000000000000cce90cfbaf5671c8c8652db28a3a9566f7","0x000000000000000000000000000000000003574db9d0f84380c9635660f86354","0x0000000000000000000000000000003eb3e1dc31846a90f721e7a08c6d6dc4f7","0x000000000000000000000000000000000028999a700cd1abae1a288eebb9a91c","0x000000000000000000000000000000c1be4d385b11387e14eb9817050d772f78","0x000000000000000000000000000000000003c56b5bad8b4484c66ac921f1f102","0x000000000000000000000000000000ace245cabf0f00dc7fd253dd8af0377a14","0x0000000000000000000000000000000000107f1731fcf34b364c813599fa1df7","0x035b937d404932b542b706eb810ef4a7dca4566d4dde1ad6a8717f46167ead7e","0x17608cef3dc7960f41cb1295706df663727d45ee598a61e05e989d111449fb65","0x054712a950ad67da3aa860e49e6891f99b586b7f37caff94eb013fdb374b61ee","0x04b755083086c769b7f593e0e48d68dc54be808203351380ca5566a48149d8bb","0x17d7670b0915235f626fdc1d7e1134d2be906ef138d7843384b3ebc23b1d630f","0x064cf544ab5f4e3dab47960502cccc83321fb275068dfbdd3a2fcbc6dddcaa65","0x083338262712e2b66769ea40d9f412b18caa1bc81a51ff5a50b6c41f8c4b3d23","0x0cdd38958cab97defde00f4a5961b6fd676e29d9f2c352f6bb2c68b91f83f8af","0x02c8bdd005c2f43a0a8cbb2744916ce5c322dfa5b23367a829c12699f4036d32","0x25bac73c7e7b659fbea3135b7a0decf9db8dc3045bd2837dae337c64cc722546","0x19eb361aa419d37bce3d2e8b2b7692a02a9559e83d7f3d8fe9169970fbbc2cba","0x2494bd5106d00e05c7ea60e632e9fe03773b7f2c5b662aa37ec512a01f4a0775","0x18c52c2f2c6e7be1d7847c15e452a3a9c64316103d12e4b5b9a82fac4e940ee9","0x0e0342810456ef78f498c1bfa085a5f3cbc06db1f32fabd0ea9ad27dccac1680","0x024c13d6ef56af33ed7164ea8e47ddecc8a487b000d8b1b45edcd3895a503ba2","0x26e0d127f626bd39b55bc5d0c131dbf03fe006dc5c3edc57dda1e629799a4317","0x1b1140061bc52b15c4f5e100729a81968ee79dc03deb966a18850335a8e44a8b","0x1bb76f945199e71d531a89288912087a02dd0e83020e65d671485bf2e5e86e1a","0x29269900859c6d86e404185b415bf3b279cd100f38cfdb0077e8d6a299c4fd35","0x22b5e94bae2f6f0cdb424a3b12c4bf82cec3fb228e012c1974ed457827bbe012","0x18d3543a93249778e7a57936170dae85ffc47c2567f2d0076a32c0bb86fcf10a","0x03721dc2670206cde42a175fd56bcce32cf6cb8801450a8e8e4b3d4e07785973","0x2806db136dd214d3ac1478460855cae6a4324ab45cab35320d104fee26c260e8","0x1c3749f1937082afbbae9375b9be708cf339e1983e57ef4447f36cfa560c685c","0x1067b8cfb90ef08bcb48aea56b2716334241787c2004a95682d68a0685566fd0","0x0f41aee4416398f1d48ffc302403273cddef34a41f98507c53682041d82e51ff","0x10d854c9f0bfbdff7ca91a68f4978e9a79e7b14243d92f465f17bdf88d9f64f8","0x00000000000000000000000000000000018938b11099e0cdc05ddab84a153a97","0x0000000000000000000000000000000001d7dda1471f0dc3b3a3d3438c197982","0x00000000000000000000000000000000022682917da43ab9a6e9cbcece1db86d","0x2453913e6b0f36eab883ac4b0e0604d56aaeb9c55e641135173e63c342f1a660","0x05216c1b58dc43a49d01aaba3113b0e86be450fc17d28016e648e7162a1b67fb","0x152b34845a0222a2b41354c0d395a250d8363dc18748647d85acd89d6934ec56","0x1dfc6e971ce82b7dcda1f7f282713c6e22a8c79258a61209bda69719806da544","0x2968dd8b3af8e3953f1fbbd72f4c49b8270597bb27d4037adc157ac6083bee60","0x1b9425b88a4c7d39b3d75afe66917a9aa1d2055724392bc01fb918d84ff1410e","0x04ab571f236d8e750904dc307dd274003d9130f1a7110e4c1521cfb408877c73","0x2ad84f26fdc5831545272d02b806bb0e6dae44e71f73552c4eb9ff06030748c7","0x020e632b99d325db774b8630fb50b9a4e74d35b7f27d9fc02c65087ee747e42c","0x09a8c5a3171268cb61c02515c01c109889200ed13f415ae54df2078bbb887f92","0x1143281a9451abbb4c34c3fa84e7678c2af2e7ea8c05160a6f7f06988fc91af8","0x000000000000000000000000000000cbda736ca5cf6bc75413c2cc9e28ab0a68","0x00000000000000000000000000000000001ee78c9cc56aa5991062ae2e338587","0x000000000000000000000000000000bc9bfcdebb486f4cb314e681d2cc5f8df6","0x00000000000000000000000000000000000ad538431d04771bca7f633cb659ff","0x000000000000000000000000000000d45b317afcefa466a59bba9e171f1af70c","0x0000000000000000000000000000000000133c50180ea17932e4881124e7a7c6","0x000000000000000000000000000000fc9ed37f543775849f3e84eaa06f77f992","0x00000000000000000000000000000000001372873c9c051d1baff99248b8f70e"] +public_inputs = ["0x0000000000000000000000000000000000000000000000000000000000000003"] +verification_key = ["0x2b337de1c8c14f22ec9b9e2f96afef3652627366f8170a0a948dad4ac1bd5e80","0x0000000000000000000000000000000000000000000000000000000000000008","0x0000000000000000000000000000000000000000000000000000000000000005","0x0000000000000000000000000000000000000000000000000000000000000008","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x00000000000000000000000000000092139c61bae1a44f0fc7689507414be688","0x00000000000000000000000000000000000160ce4e279582f91bde4f03f5e9a2","0x0000000000000000000000000000005dc2d37f658c3b2d60f24740eb13b65d79","0x000000000000000000000000000000000007e3e8a5d98a1177ec85bf88f163a5","0x000000000000000000000000000000dc3035fbd7ff16412a8fd7da587a935298","0x000000000000000000000000000000000023d08e2817ac16990004ed11d8fc66","0x000000000000000000000000000000356a5ad59c646c746a8d09f5d154e47c4f","0x00000000000000000000000000000000000708529196af3c8e16ffa580c26182","0x0000000000000000000000000000002ddfe70eb7a1280596e8e4a804f118a6dd","0x000000000000000000000000000000000013757e15a0905f298303784a161b21","0x000000000000000000000000000000a23a729df796935c7824e3a26be794829b","0x000000000000000000000000000000000005775b6c146c4a59856e869fe5a70e","0x000000000000000000000000000000eef0c9e088fd2d45aa40311082d1f2809b","0x00000000000000000000000000000000001d539ccbfc556d0ad59307a218de65","0x000000000000000000000000000000a2c848beceb6ab7806fd3b88037b8410fc","0x0000000000000000000000000000000000177004deeb1f9d401fd7b1af1a5ac8","0x0000000000000000000000000000002508eb63672a733f20de1a97644be4f540","0x00000000000000000000000000000000000d82d51f2f75d806285fd248c819b8","0x000000000000000000000000000000d002f9100cbba8a29f13b11513c53c59d0","0x000000000000000000000000000000000006cd3b0e3460533b9e5ea2cdc0fcbb","0x000000000000000000000000000000f45ea38a93b2f810c5633ddb54927c1c96","0x000000000000000000000000000000000021791de65f9a28ec7024b1a87ab4f3","0x000000000000000000000000000000926511a0439502c86885a8c6f0327aa7ad","0x000000000000000000000000000000000029fa14a969c5d81ed3abbbfb11220a","0x000000000000000000000000000000b84c3258e8206f560e5b5b18cbeafef87e","0x00000000000000000000000000000000002a910445cd8fc895e5d235cd8ea185","0x000000000000000000000000000000887e67f15e84bcb8507a5064a363f6043b","0x000000000000000000000000000000000014dc6643d801c3ef27c2066b6e2bb4","0x000000000000000000000000000000e38e900b42c314ba803088e8fbf125203f","0x000000000000000000000000000000000020690fd4869db418306046b38161dc","0x0000000000000000000000000000001e2fa856bf7951b8292b1e88185993629c","0x0000000000000000000000000000000000048a85e0bbac7c60ad3d78f601f63c","0x0000000000000000000000000000006f457719495073d3666d77a625aeab0c51","0x00000000000000000000000000000000002623ad892dc62b1fa7d0a650f0d470","0x000000000000000000000000000000dbfcc8a467e021c03b13f74a9f79c3a10c","0x0000000000000000000000000000000000295f6f10976c37bd9c6f96bb7187d5","0x000000000000000000000000000000c13ef9a937cc12420fb38d9ab8e848e85e","0x000000000000000000000000000000000003560a3b334e887532f605c9cb7628","0x0000000000000000000000000000009bcebf08a4599cdda0fb96312d4dc0c7a9","0x000000000000000000000000000000000015adc8bb1e01c835f48959d1237bd6","0x00000000000000000000000000000047762ab839e4ff63c77605a9f383da37c2","0x000000000000000000000000000000000016a8c3c53d89660cf271522cd301fb","0x000000000000000000000000000000f0c8539a0b5f94420a513f9c305b932bfe","0x00000000000000000000000000000000002957ba01d9de5638f808f88a692533","0x000000000000000000000000000000ab17c6189d67d3bf5dd2f3885de0151b6f","0x0000000000000000000000000000000000060d8aa43fdc434d1942263f364d95","0x0000000000000000000000000000005d292333b3adb497f00b4bc32d45229060","0x00000000000000000000000000000000001a1018a66221883639f2898a66f345","0x00000000000000000000000000000006555a806b1993291deba0dc44e2abf431","0x00000000000000000000000000000000000cacff7099a9d5e35a21f4a00b2dc3","0x000000000000000000000000000000f50c11ba95d349c36d143eefd12e494950","0x00000000000000000000000000000000001022e8c5f02d639bc9dd8bc4407f99","0x000000000000000000000000000000c76828795098eda73d50b4b585c60afc60","0x00000000000000000000000000000000002bf09c0ec7011e93888962f2406630","0x00000000000000000000000000000049e5c83a8978d832fb8e144548e3ca1adb","0x00000000000000000000000000000000000e0ec242c2e160a984f61ca5adf5f5","0x0000000000000000000000000000009c5d6e08a6605ab4513748ac0fa017dd1c","0x00000000000000000000000000000000001f54baa07558e5fb055bd9ba49c067","0x0000000000000000000000000000001e1ee7ee29bbb5e4b080c6091c1433ce62","0x000000000000000000000000000000000024aec62a9d9763499267dc98c33428","0x0000000000000000000000000000001a96755946ff16f0d6632365f0eb0ab4d4","0x000000000000000000000000000000000028cf3e22bcd53782ebc3e0490e27e5","0x00000000000000000000000000000043148d7d8c9ba43f2133fab4201435a364","0x0000000000000000000000000000000000234ce541f1f5117dd404cfaf01a229","0x000000000000000000000000000000a7fb95ffb461d9514a1070e2d2403982ef","0x00000000000000000000000000000000003016955028b6390f446c3fd0c5b424","0x00000000000000000000000000000008863c3b7cd7cddc20ba79ce915051c56e","0x000000000000000000000000000000000013ef666111b0be56a235983d397d2a","0x000000000000000000000000000000e3993f465fc9f56e93ac769e597b752c1c","0x0000000000000000000000000000000000217f7c4235161e9a3c16c45b6ca499","0x0000000000000000000000000000008ffa4cd96bc67b0b7df5678271e1114075","0x0000000000000000000000000000000000256467bfcb63d9fdcb5dde397757ad","0x00000000000000000000000000000054e5eb270bb64bde6e6ececadfd8c3236c","0x00000000000000000000000000000000000e52d1bd75812c33c6f3d79ee4b94c","0x000000000000000000000000000000484a2c641dce55bc2dd64ef0cd790a7fea","0x00000000000000000000000000000000000ff417d256be43e73c8b1aa85bdda3","0x0000000000000000000000000000000b72e7b7713ab5da44e0f864182e748a23","0x00000000000000000000000000000000001a221055f1625ad833a44705f5f74e","0x00000000000000000000000000000067a99a34e9b81a17ad001db02e29bcb82a","0x000000000000000000000000000000000018a6c02e398389827568fa960e86e2","0x000000000000000000000000000000bb29f26f9890d6cc6401f4921d5884edca","0x00000000000000000000000000000000000868357b28039385c5a5058b6d358e","0x00000000000000000000000000000036fb6e229dde8edf7ec858b12d7e8be485","0x00000000000000000000000000000000001060afe929554ca473103f5e68193c","0x00000000000000000000000000000015226e07e207744c0857074dcab883af4a","0x00000000000000000000000000000000000b1c02619282755533457230b19b4a","0x0000000000000000000000000000001f2a0277e4807e6e1cbabca21dde5eb5e1","0x00000000000000000000000000000000000d928deafed363659688ed4ccdef52","0x000000000000000000000000000000363f0c994e91cecad25835338edee2294f","0x00000000000000000000000000000000002eea648c8732596b1314fe2a4d2f05","0x000000000000000000000000000000b2671d2ae51d31c1210433c3972bb64578","0x00000000000000000000000000000000000ab49886c2b94bd0bd3f6ed1dbbe2c"] +proof_b = ["0x000000000000000000000000000000f05c69448ca29bdf52076f9b073bb30fed","0x000000000000000000000000000000000028c86bb3e27b4aaaaef126f7df5349","0x00000000000000000000000000000026ae031fc93594375dfc7f3bbe027f97d5","0x000000000000000000000000000000000000dd12c7290fe7f775796a233b8590","0x000000000000000000000000000000c1ee6631704de424d010c5c4ac8293ac49","0x00000000000000000000000000000000002f41818c9aa83f5c8d9bdd128015b9","0x000000000000000000000000000000b50a5801482f7e3a5de8ab3cce0f10b0d3","0x000000000000000000000000000000000022a0bc69c293dbf293b25bc9eef7f8","0x0000000000000000000000000000003b02abf1967ef394154dc15d763135e903","0x00000000000000000000000000000000000d8a2ee46acc6d1ed8d517b56d47c8","0x00000000000000000000000000000039bf0d1b3d8cf9de898f101c626e978d78","0x0000000000000000000000000000000000008faa7df2451a24d291a9b584f1a5","0x000000000000000000000000000000c1dae329ed7adf63a2d89a5f16fb98b6d8","0x00000000000000000000000000000000001ff0bc16fc0bd4aa2d6255690453c2","0x000000000000000000000000000000d12d7589f853a9b472613efa56689beaf1","0x00000000000000000000000000000000002d6fbc798f4403751df6aeee8bedd3","0x0000000000000000000000000000007c1fa069cb17194fecf88db9dd54a4ee36","0x0000000000000000000000000000000000268e026f9814822a42b2d59eec5d24","0x000000000000000000000000000000c3fb56beab774218cd63498fc050a5fd9b","0x00000000000000000000000000000000000071c014d7b5063f005a0bc2ee1af4","0x000000000000000000000000000000ae12b25371c6af42bbe0a85cddd2eaebc7","0x000000000000000000000000000000000026d270e1ffc9c7c344c694dfadda83","0x00000000000000000000000000000080280858c6be461716921caa3c26f3f6f3","0x000000000000000000000000000000000001dcdd3f39e27d0ce6aa5d14dff4c1","0x000000000000000000000000000000080e1d2c913c834ebcf7e0600c076c08fd","0x00000000000000000000000000000000002df3d142217694e65fb7c355d62764","0x000000000000000000000000000000e5e336f3f59d77e500f49771bfbeb12e83","0x000000000000000000000000000000000028fffe08bdc4c0690643d2e1a1275f","0x000000000000000000000000000000db5618b32afc13e18f21b39f3fbede9d11","0x00000000000000000000000000000000001d244818370d43fb7e8bc67e03787b","0x0000000000000000000000000000006bcc1fd3f9f78449ad1df1bc11bc379edd","0x000000000000000000000000000000000009ac9cbb285edbf5b3a973f3f5f1cb","0x000000000000000000000000000000fd885905b6c0fc95bb4dd0b11f6797d4b3","0x000000000000000000000000000000000021f07995cdd835145e19c38127c562","0x000000000000000000000000000000bbbf2b975c2c97ae4b45c4a52059e53ee3","0x000000000000000000000000000000000024158163788841cf4590bbc1e89a90","0x0000000000000000000000000000009aca93d2b1386ea412d4b36ea5bb9894a8","0x00000000000000000000000000000000002532d1d210e8ed4c2f5c00cbaaa475","0x000000000000000000000000000000634a88caa1d77cb6b5fe77cac31458fc31","0x00000000000000000000000000000000000bdf18bae92fce7cfddab5520cac6e","0x000000000000000000000000000000622e9626255170ccec77602c755aa193e1","0x000000000000000000000000000000000001d4edba370e04436a988bad05dada","0x000000000000000000000000000000b52934323a0aec8f803cdaafee2ab7bfb2","0x0000000000000000000000000000000000155312af5e0e25ca9fd61aef9e58ed","0x06270b517855f6f6a608e432883d1d1030a12a1e33022dc142b7728691421da2","0x2af7c794d7b720b25eb1df0afd8c8e3c15b6e518194c3caea7966a5f8210ff04","0x073fe573aeb27d81a5713be93e1365390dcbc3c8e7439ff1d36a84cc014f5642","0x11351b961147431e54535248b58b35cf5cddb9b13827899167617d7a96794d64","0x297c9421c9c3db286770787c35b86bc41583386491b4ae55e5fa81aefa21efc4","0x0f4eeca3ff4a3495f859898937688652d33f9b4dd3e003e12adf15278e0997c3","0x133e3d8b82721d40d919f2326810ba6f07eff3f7d20d86b2bde692a811522019","0x2c502f53c9698b73bb8c8f9b9cf2d705d16a64a7040348b4b39c637a2064316c","0x0cbc1971e1c566cde9d9125c91cdc88e817db182692f836c1a5170a6246eaf73","0x12c47793e7db706c637cd4b4d96d227f569850176b852b1fe8ad522ddb38ef0e","0x0cd7b300e9309a135285be1aeb02b152f97931a7357ab6d609a2cb1970aab877","0x2a7789dfe286c9d0a7592f1c9316e730cb14c9d843aefc4764d76e7f8571c96a","0x248ac54ce3dbf37796621882a4ac76046df5ab680da487fd85cce76b1ae392d3","0x149d1d07cebe320f77b03533e34912545cedeae62bd9778d37724728762b5710","0x00fe29daebdaed61309790e70e2dcefa3f3af4c6c965ce424b8dbcf09b8e4b49","0x2b75b3bace61b731d7f0c003a144b62b0a4fbe9f0d14ca89b0652b70210014b3","0x2588ef27cfb6e0d8c6f9a969b2da44fead30a02ed70a563fd15aa45bb671de1c","0x2b74d7674b55642697b4a1e226eddb0e4918b2d57aa5b99093dc46cadcdea000","0x244c626845d3a5040f08f01e9611f968ad675ca857789149b13a0cfa83a2e064","0x2cb8d02f90cae33fd7bcfb80af4aff067c4f5fc4b3f9228d5b8f768bc8f6c971","0x1372f3d1f04e0c39a50e823d5da03d70bebe19a1b8e28f8c2ff601cc0bfc0095","0x19af6601d2613426a50b7c35d60562a5f2f2634e6af56dac13459632e15570ee","0x13c2a16ed3b65dcd9414659be79af17995d344de34eaf962343b0f1e76c73a57","0x0dd5dcdbd50b8774831d4f01f930804d38b4266dfee085185530880a0c3903c0","0x07e91848d660b11b722638680ac60f20db9507fdc8d610ce762600f5a1aacd29","0x1f9c2a94d10c0a7fb60292cfc46fd3d2501181bea0ffe1f5f2501d474be3a785","0x14edb9c5bd389eae08a5ea2a7a1662894e1e878c142084d966a625bef68cf7c3","0x00000000000000000000000000000000cecd01810814d175f0a533f0067618c4","0x00000000000000000000000000000000f82935013ce5c82720c63e533af41db8","0x000000000000000000000000000000012185688171b6bed850e748b66f7222ac","0x2dd7f5ff2150155c2ac86ebe28d9ecbca2eea812b0021ab2bceae111cfea8325","0x04ea6c2daf2b9e827d2213c3d03953410dcf1ed67ba34a3c00e772be92606a8b","0x163f2bd18dcde52f99b9867c944780fd718d1612927053b139b280fc55013d1b","0x05e388fd160ccac30a8f7b18a4bd042f705e92b5937e8c0e9478e2ff623907c6","0x00ba3f6f527d6ed3ff17a63b1d5be3c42bdfae88fdf63311fc7b871157939309","0x16187d9daa8c2e5a1a9ab15be7ca6a8feebfb31bea76f9a3ca69381881c70561","0x0f64522e4904edb7377b14a7b9dad848829167324ef5c016346b3ad8251191ee","0x273bbe6000a4001dce369e5a36cc0b0ca3fd351665b688238aa8c556a6ca6b8e","0x022d2232efb2faa8307846c9a4c697aabad1b7f1336b35ad72fa8922975b49d9","0x0d82d478bff3955c4b0a34ef94427ca5f9da23147ad953c89f2e428277ec2825","0x18d886be90343010659c231583be61a138e28e37c24771e3cb61fbe2587d0671","0x000000000000000000000000000000196ba6a58dbeb7c34cb1d6287e23d434de","0x00000000000000000000000000000000001df8ae8a1589590f8863c1fefd8dfd","0x000000000000000000000000000000f30e11b2c5fbefa166cbb9f58c5f8e1a4c","0x000000000000000000000000000000000026420ade7666bc0ab1cf1fd9d0c534","0x0000000000000000000000000000000feb5b7d8260d25a1ee1ce76ff461673fc","0x00000000000000000000000000000000002bd2ac6223a80671b777bf5dca70a4","0x000000000000000000000000000000690f757006d2fa1ddb0114c9f268783537","0x000000000000000000000000000000000023ad36feadd91e50118f32e97a0204"] \ No newline at end of file diff --git a/test_programs/execution_success/double_verify_proof_recursive/src/main.nr b/test_programs/execution_success/double_verify_proof_recursive/src/main.nr new file mode 100644 index 00000000000..86b4971c3a6 --- /dev/null +++ b/test_programs/execution_success/double_verify_proof_recursive/src/main.nr @@ -0,0 +1,30 @@ +use dep::std; + +// This circuit aggregates two proofs from `assert_statement_recursive`. +#[recursive] +fn main( + verification_key: [Field; 114], + // This is the proof without public inputs attached. + // + // This means: the size of this does not change with the number of public inputs. + proof: [Field; 93], + public_inputs: pub [Field; 1], + // This is currently not public. It is fine given that the vk is a part of the circuit definition. + // I believe we want to eventually make it public too though. + key_hash: Field, + proof_b: [Field; 93] +) { + std::verify_proof( + verification_key.as_slice(), + proof.as_slice(), + public_inputs.as_slice(), + key_hash + ); + + std::verify_proof( + verification_key.as_slice(), + proof_b.as_slice(), + public_inputs.as_slice(), + key_hash + ); +} diff --git a/test_programs/execution_success/ecdsa_secp256r1_3x/Nargo.toml b/test_programs/execution_success/ecdsa_secp256r1_3x/Nargo.toml new file mode 100644 index 00000000000..860b863a365 --- /dev/null +++ b/test_programs/execution_success/ecdsa_secp256r1_3x/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "ecdsa_secp256r1_3x" +description = "Three ECDSA secp256r1 verifications" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/ecdsa_secp256r1_3x/Prover.toml b/test_programs/execution_success/ecdsa_secp256r1_3x/Prover.toml new file mode 100644 index 00000000000..e8edf26b2f3 --- /dev/null +++ b/test_programs/execution_success/ecdsa_secp256r1_3x/Prover.toml @@ -0,0 +1,57 @@ +hashed_message = [ + 84, 112, 91, 163, 186, 175, 219, 223, 186, 140, 95, 154, 112, 247, 168, 155, 238, 152, + 217, 6, 181, 62, 49, 7, 77, 167, 186, 236, 220, 13, 169, 173, +] +pub_key_x = [ + 85, 15, 71, 16, 3, 243, 223, 151, 195, 223, 80, 106, 199, 151, 246, 114, 31, 177, 161, + 251, 123, 143, 111, 131, 210, 36, 73, 138, 101, 200, 142, 36, +] +pub_key_y = [ + 19, 96, 147, 215, 1, 46, 80, 154, 115, 113, 92, 189, 11, 0, 163, 204, 15, 244, 181, + 192, 27, 63, 250, 25, 106, 177, 251, 50, 112, 54, 184, 230, +] +signature = [ + 44, 112, 168, 208, 132, 182, 43, 252, 92, 224, 54, 65, 202, 249, 247, 42, + 212, 218, 140, 129, 191, 230, 236, 148, 135, 187, 94, 27, 239, 98, 161, 50, + 24, 173, 158, 226, 158, 175, 53, 31, 220, 80, 241, 82, 12, 66, 94, 155, + 144, 138, 7, 39, 139, 67, 176, 236, 123, 135, 39, 120, 193, 78, 7, 132 +] + +hashed_message_2 = [ + 84, 112, 91, 163, 186, 175, 219, 223, 186, 140, 95, 154, 112, 247, 168, 155, 238, 152, + 217, 6, 181, 62, 49, 7, 77, 167, 186, 236, 220, 13, 169, 173, +] +pub_key_x_2 = [ + 85, 15, 71, 16, 3, 243, 223, 151, 195, 223, 80, 106, 199, 151, 246, 114, 31, 177, 161, + 251, 123, 143, 111, 131, 210, 36, 73, 138, 101, 200, 142, 36, +] +pub_key_y_2 = [ + 19, 96, 147, 215, 1, 46, 80, 154, 115, 113, 92, 189, 11, 0, 163, 204, 15, 244, 181, + 192, 27, 63, 250, 25, 106, 177, 251, 50, 112, 54, 184, 230, +] +signature_2 = [ + 44, 112, 168, 208, 132, 182, 43, 252, 92, 224, 54, 65, 202, 249, 247, 42, + 212, 218, 140, 129, 191, 230, 236, 148, 135, 187, 94, 27, 239, 98, 161, 50, + 24, 173, 158, 226, 158, 175, 53, 31, 220, 80, 241, 82, 12, 66, 94, 155, + 144, 138, 7, 39, 139, 67, 176, 236, 123, 135, 39, 120, 193, 78, 7, 132 +] + + +hashed_message_3 = [ + 84, 112, 91, 163, 186, 175, 219, 223, 186, 140, 95, 154, 112, 247, 168, 155, 238, 152, + 217, 6, 181, 62, 49, 7, 77, 167, 186, 236, 220, 13, 169, 173, +] +pub_key_x_3 = [ + 85, 15, 71, 16, 3, 243, 223, 151, 195, 223, 80, 106, 199, 151, 246, 114, 31, 177, 161, + 251, 123, 143, 111, 131, 210, 36, 73, 138, 101, 200, 142, 36, +] +pub_key_y_3 = [ + 19, 96, 147, 215, 1, 46, 80, 154, 115, 113, 92, 189, 11, 0, 163, 204, 15, 244, 181, + 192, 27, 63, 250, 25, 106, 177, 251, 50, 112, 54, 184, 230, +] +signature_3 = [ + 44, 112, 168, 208, 132, 182, 43, 252, 92, 224, 54, 65, 202, 249, 247, 42, + 212, 218, 140, 129, 191, 230, 236, 148, 135, 187, 94, 27, 239, 98, 161, 50, + 24, 173, 158, 226, 158, 175, 53, 31, 220, 80, 241, 82, 12, 66, 94, 155, + 144, 138, 7, 39, 139, 67, 176, 236, 123, 135, 39, 120, 193, 78, 7, 132 +] \ No newline at end of file diff --git a/test_programs/execution_success/ecdsa_secp256r1_3x/src/main.nr b/test_programs/execution_success/ecdsa_secp256r1_3x/src/main.nr new file mode 100644 index 00000000000..e7a6be9d47a --- /dev/null +++ b/test_programs/execution_success/ecdsa_secp256r1_3x/src/main.nr @@ -0,0 +1,23 @@ +use dep::std; + +fn main( + hashed_message: [u8; 32], + pub_key_x: [u8; 32], + pub_key_y: [u8; 32], + signature: [u8; 64], + hashed_message_2: [u8; 32], + pub_key_x_2: [u8; 32], + pub_key_y_2: [u8; 32], + signature_2: [u8; 64], + hashed_message_3: [u8; 32], + pub_key_x_3: [u8; 32], + pub_key_y_3: [u8; 32], + signature_3: [u8; 64] +) { + let valid_signature = std::ecdsa_secp256r1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); + assert(valid_signature); + let valid_signature_2 = std::ecdsa_secp256r1::verify_signature(pub_key_x_2, pub_key_y_2, signature_2, hashed_message_2); + assert(valid_signature_2); + let valid_signature_3 = std::ecdsa_secp256r1::verify_signature(pub_key_x_3, pub_key_y_3, signature_3, hashed_message_3); + assert(valid_signature_3); +} diff --git a/test_programs/execution_success/eddsa/src/main.nr b/test_programs/execution_success/eddsa/src/main.nr index 12e8ea92785..ada15d5405c 100644 --- a/test_programs/execution_success/eddsa/src/main.nr +++ b/test_programs/execution_success/eddsa/src/main.nr @@ -1,14 +1,21 @@ use dep::std::compat; use dep::std::ec::consts::te::baby_jubjub; +use dep::std::ec::tecurve::affine::Point as TEPoint; use dep::std::hash; -use dep::std::eddsa::eddsa_poseidon_verify; +use dep::std::eddsa::{eddsa_to_pub, eddsa_poseidon_verify, eddsa_verify}; +use dep::std::hash::poseidon2::Poseidon2Hasher; + fn main(msg: pub Field, _priv_key_a: Field, _priv_key_b: Field) { // Skip this test for non-bn254 backends if compat::is_bn254() { let bjj = baby_jubjub(); 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); + let pub_key_b = bjj.curve.mul(_priv_key_b, bjj.curve.gen); + let (pub_key_a_x, pub_key_a_y) = eddsa_to_pub(_priv_key_a); + let (pub_key_b_x, pub_key_b_y) = eddsa_to_pub(_priv_key_b); + assert(TEPoint::new(pub_key_a_x, pub_key_a_y) == pub_key_a); + assert(TEPoint::new(pub_key_b_x, pub_key_b_y) == pub_key_b); // 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_commitment([_priv_key_a, msg])[0] % bjj.suborder; // modulus computed manually @@ -42,5 +49,7 @@ fn main(msg: pub Field, _priv_key_a: Field, _priv_key_b: Field) { 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)); + // Using a different hash should fail + assert(!eddsa_verify::(pub_key_a.x, pub_key_a.y, s_a, r8_a.x, r8_a.y, msg)); } } diff --git a/test_programs/execution_success/brillig_scalar_mul/Nargo.toml b/test_programs/execution_success/embedded_curve_ops/Nargo.toml similarity index 65% rename from test_programs/execution_success/brillig_scalar_mul/Nargo.toml rename to test_programs/execution_success/embedded_curve_ops/Nargo.toml index eefd041b899..1c389149aaf 100644 --- a/test_programs/execution_success/brillig_scalar_mul/Nargo.toml +++ b/test_programs/execution_success/embedded_curve_ops/Nargo.toml @@ -1,5 +1,5 @@ [package] -name = "brillig_scalar_mul" +name = "embedded_curve_ops" type = "bin" authors = [""] diff --git a/test_programs/execution_success/embedded_curve_ops/Prover.toml b/test_programs/execution_success/embedded_curve_ops/Prover.toml new file mode 100644 index 00000000000..7113b9cd038 --- /dev/null +++ b/test_programs/execution_success/embedded_curve_ops/Prover.toml @@ -0,0 +1,3 @@ +priv_key = "1" +pub_x = "0x0000000000000000000000000000000000000000000000000000000000000001" +pub_y = "0x0000000000000002cf135e7506a45d632d270d45f1181294833fc48d823f272c" \ No newline at end of file diff --git a/test_programs/execution_success/embedded_curve_ops/src/main.nr b/test_programs/execution_success/embedded_curve_ops/src/main.nr new file mode 100644 index 00000000000..46f919e947a --- /dev/null +++ b/test_programs/execution_success/embedded_curve_ops/src/main.nr @@ -0,0 +1,24 @@ +use dep::std; + +fn main(priv_key: Field, pub_x: pub Field, pub_y: pub Field) { + let g1_y = 17631683881184975370165255887551781615748388533673675138860; + let g1 = std::embedded_curve_ops::EmbeddedCurvePoint { x: 1, y: g1_y, is_infinite: false }; + let scalar = std::embedded_curve_ops::EmbeddedCurveScalar { lo: priv_key, hi: 0 }; + // Test that multi_scalar_mul correctly derives the public key + let res = std::embedded_curve_ops::multi_scalar_mul([g1], [scalar]); + assert(res[0] == pub_x); + assert(res[1] == pub_y); + + // Test that double function calling embedded_curve_add works as expected + let pub_point = std::embedded_curve_ops::EmbeddedCurvePoint { x: pub_x, y: pub_y, is_infinite: false }; + let res = pub_point.double(); + let double = g1.add(g1); + + assert(double.x == res.x); + + // Test calling multi_scalar_mul with multiple points and scalars + let res = std::embedded_curve_ops::multi_scalar_mul([g1, g1], [scalar, scalar]); + + // The results should be double the g1 point because the scalars are 1 and we pass in g1 twice + assert(double.x == res[0]); +} diff --git a/test_programs/execution_success/empty/Nargo.toml b/test_programs/execution_success/empty/Nargo.toml new file mode 100644 index 00000000000..168911f2b2b --- /dev/null +++ b/test_programs/execution_success/empty/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "empty" +type = "bin" +authors = [""] +[dependencies] diff --git a/test_programs/execution_success/empty/src/main.nr b/test_programs/execution_success/empty/src/main.nr new file mode 100644 index 00000000000..f328e4d9d04 --- /dev/null +++ b/test_programs/execution_success/empty/src/main.nr @@ -0,0 +1 @@ +fn main() {} diff --git a/test_programs/execution_success/fold_after_inlined_calls/Nargo.toml b/test_programs/execution_success/fold_after_inlined_calls/Nargo.toml new file mode 100644 index 00000000000..d23924af083 --- /dev/null +++ b/test_programs/execution_success/fold_after_inlined_calls/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "fold_after_inlined_calls" +type = "bin" +authors = [""] +compiler_version = ">=0.27.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/custom_entry_not_found/Prover.toml b/test_programs/execution_success/fold_after_inlined_calls/Prover.toml similarity index 100% rename from test_programs/compile_failure/custom_entry_not_found/Prover.toml rename to test_programs/execution_success/fold_after_inlined_calls/Prover.toml diff --git a/test_programs/execution_success/fold_after_inlined_calls/src/main.nr b/test_programs/execution_success/fold_after_inlined_calls/src/main.nr new file mode 100644 index 00000000000..84c81190b9b --- /dev/null +++ b/test_programs/execution_success/fold_after_inlined_calls/src/main.nr @@ -0,0 +1,14 @@ +fn main(x: u32) { + // We want to call a foldable function after a call to a function that is set to be inlined + assert(increment(x) == x + 1); + foo(x); +} + +#[fold] +fn foo(x: u32) { + assert(x == 1); +} + +fn increment(x: u32) -> u32 { + x + 1 +} diff --git a/test_programs/execution_success/fold_basic/Nargo.toml b/test_programs/execution_success/fold_basic/Nargo.toml new file mode 100644 index 00000000000..575ba1f3ad1 --- /dev/null +++ b/test_programs/execution_success/fold_basic/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "fold_basic" +type = "bin" +authors = [""] +compiler_version = ">=0.25.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/slice_remove_failure/Prover.toml b/test_programs/execution_success/fold_basic/Prover.toml similarity index 100% rename from test_programs/compile_failure/slice_remove_failure/Prover.toml rename to test_programs/execution_success/fold_basic/Prover.toml diff --git a/test_programs/execution_success/fold_basic/src/main.nr b/test_programs/execution_success/fold_basic/src/main.nr new file mode 100644 index 00000000000..6c17120660b --- /dev/null +++ b/test_programs/execution_success/fold_basic/src/main.nr @@ -0,0 +1,11 @@ +fn main(x: Field, y: pub Field) { + let z = foo(x, y); + let z2 = foo(x, y); + assert(z == z2); +} + +#[fold] +fn foo(x: Field, y: Field) -> Field { + assert(x != y); + x +} diff --git a/test_programs/execution_success/fold_basic_nested_call/Nargo.toml b/test_programs/execution_success/fold_basic_nested_call/Nargo.toml new file mode 100644 index 00000000000..1b3c32999ae --- /dev/null +++ b/test_programs/execution_success/fold_basic_nested_call/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "fold_basic_nested_call" +type = "bin" +authors = [""] +compiler_version = ">=0.25.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/fold_basic_nested_call/Prover.toml b/test_programs/execution_success/fold_basic_nested_call/Prover.toml new file mode 100644 index 00000000000..f28f2f8cc48 --- /dev/null +++ b/test_programs/execution_success/fold_basic_nested_call/Prover.toml @@ -0,0 +1,2 @@ +x = "5" +y = "10" diff --git a/test_programs/execution_success/fold_basic_nested_call/src/main.nr b/test_programs/execution_success/fold_basic_nested_call/src/main.nr new file mode 100644 index 00000000000..6d02b734727 --- /dev/null +++ b/test_programs/execution_success/fold_basic_nested_call/src/main.nr @@ -0,0 +1,16 @@ +fn main(x: Field, y: pub Field) { + let z = func_with_nested_foo_call(x, y); + let z2 = func_with_nested_foo_call(x, y); + assert(z == z2); +} + +#[fold] +fn func_with_nested_foo_call(x: Field, y: Field) -> Field { + foo(x + 2, y) +} + +#[fold] +fn foo(x: Field, y: Field) -> Field { + assert(x != y); + x +} diff --git a/test_programs/execution_success/fold_call_witness_condition/Nargo.toml b/test_programs/execution_success/fold_call_witness_condition/Nargo.toml new file mode 100644 index 00000000000..cedaea348c5 --- /dev/null +++ b/test_programs/execution_success/fold_call_witness_condition/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "fold_call_witness_condition" +type = "bin" +authors = [""] +compiler_version = ">=0.26.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/fold_call_witness_condition/Prover.toml b/test_programs/execution_success/fold_call_witness_condition/Prover.toml new file mode 100644 index 00000000000..a4d6339b661 --- /dev/null +++ b/test_programs/execution_success/fold_call_witness_condition/Prover.toml @@ -0,0 +1,3 @@ +x = "10" +y = "10" +enable = false diff --git a/test_programs/execution_success/fold_call_witness_condition/src/main.nr b/test_programs/execution_success/fold_call_witness_condition/src/main.nr new file mode 100644 index 00000000000..5dc75e4a99f --- /dev/null +++ b/test_programs/execution_success/fold_call_witness_condition/src/main.nr @@ -0,0 +1,16 @@ +global NUM_RESULTS = 2; +fn main(x: Field, y: pub Field, enable: bool) -> pub [Field; NUM_RESULTS] { + let mut result = [0; NUM_RESULTS]; + for i in 0..NUM_RESULTS { + if enable { + result[i] = return_value(x, y); + } + } + result +} + +#[fold] +fn return_value(x: Field, y: Field) -> Field { + assert(x != y); + x +} diff --git a/test_programs/execution_success/fold_complex_outputs/Nargo.toml b/test_programs/execution_success/fold_complex_outputs/Nargo.toml new file mode 100644 index 00000000000..f00c6520b4a --- /dev/null +++ b/test_programs/execution_success/fold_complex_outputs/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "fold_complex_outputs" +type = "bin" +authors = [""] +compiler_version = ">=0.28.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/fold_complex_outputs/Prover.toml b/test_programs/execution_success/fold_complex_outputs/Prover.toml new file mode 100644 index 00000000000..a26b97d6471 --- /dev/null +++ b/test_programs/execution_success/fold_complex_outputs/Prover.toml @@ -0,0 +1,2 @@ +x = "5" +y = "3" diff --git a/test_programs/execution_success/fold_complex_outputs/src/main.nr b/test_programs/execution_success/fold_complex_outputs/src/main.nr new file mode 100644 index 00000000000..309d9747598 --- /dev/null +++ b/test_programs/execution_success/fold_complex_outputs/src/main.nr @@ -0,0 +1,72 @@ +struct MyStruct { + x: u32, + y: u32, + z: u32, + nested_struct: InnerStruct +} + +struct InnerStruct { + small_array: [u32; 2], + big_array: [u32; 5], +} + +struct ParentStruct { + basic_array: [Field; 3], + id: u32, + my_structs: [MyStruct; 2], +} + +fn main(x: u32, y: pub u32) { + let nested_struct = InnerStruct { small_array: [1 as u32; 2], big_array: [0 as u32; 5] }; + let s = MyStruct { x, y, z: x + y, nested_struct }; + let parent = ParentStruct { basic_array: [1; 3], id: 100, my_structs: [s, s] }; + let new_parent = map_fields(parent); + + // Now check that the outputs are as we expect them to be + assert(new_parent.basic_array[0] == 1); + assert(new_parent.basic_array[1] == 18); + assert(new_parent.basic_array[2] == 1); + + let struct_0 = new_parent.my_structs[0]; + assert(struct_0.x == 5); + assert(struct_0.y == 3); + assert(struct_0.z == 8); + assert(struct_0.nested_struct.small_array == nested_struct.small_array); + assert(struct_0.nested_struct.big_array == nested_struct.big_array); + + let struct_1 = new_parent.my_structs[1]; + assert(struct_1.x == 50); + assert(struct_1.y == 30); + assert(struct_1.z == 80); + assert(struct_1.nested_struct.small_array == [5, 10]); + assert(struct_1.nested_struct.big_array == [15, 20, 25, 30, 35]); +} + +// Meaningless mapping to test whether the values returned are what we expect +#[fold] +fn map_fields(mut input: ParentStruct) -> ParentStruct { + let current_struct = input.my_structs[0]; + let mut sum = 0; + for value in current_struct.nested_struct.small_array { + sum += value; + } + for value in current_struct.nested_struct.big_array { + sum += value; + } + sum += (current_struct.x + current_struct.y + current_struct.z); + + input.basic_array[1] = sum as Field; + + input.my_structs[1].nested_struct.small_array = [5, 10]; + input.my_structs[1].nested_struct.big_array = [15, 20, 25, 30, 35]; + + // LHS input.my_structs[1].x == 50 + input.my_structs[1].x = input.my_structs[1].x * 10; + // LHS input.my_structs[1].y == 30 + input.my_structs[1].y = input.my_structs[1].y * 10; + // LHS input.my_structs[1].x == 80 + input.my_structs[1].z = input.my_structs[1].x + input.my_structs[1].y; + + input +} + diff --git a/test_programs/execution_success/fold_distinct_return/Nargo.toml b/test_programs/execution_success/fold_distinct_return/Nargo.toml new file mode 100644 index 00000000000..f18edb7e49d --- /dev/null +++ b/test_programs/execution_success/fold_distinct_return/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "fold_distinct_return" +type = "bin" +authors = [""] +compiler_version = ">=0.28.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/fold_distinct_return/Prover.toml b/test_programs/execution_success/fold_distinct_return/Prover.toml new file mode 100644 index 00000000000..f28f2f8cc48 --- /dev/null +++ b/test_programs/execution_success/fold_distinct_return/Prover.toml @@ -0,0 +1,2 @@ +x = "5" +y = "10" diff --git a/test_programs/execution_success/fold_distinct_return/src/main.nr b/test_programs/execution_success/fold_distinct_return/src/main.nr new file mode 100644 index 00000000000..b0843a02b80 --- /dev/null +++ b/test_programs/execution_success/fold_distinct_return/src/main.nr @@ -0,0 +1,10 @@ +fn main(x: u32, y: pub u32) { + let new_field = new_field_in_array([x, y, 3]); + assert(new_field[0] == 25); +} + +#[fold] +fn new_field_in_array(mut input: [u32; 3]) -> [u32; 3] { + input[0] = input[0] + 20; + input +} diff --git a/test_programs/execution_success/fold_fibonacci/Nargo.toml b/test_programs/execution_success/fold_fibonacci/Nargo.toml new file mode 100644 index 00000000000..6d8214689b0 --- /dev/null +++ b/test_programs/execution_success/fold_fibonacci/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "fold_fibonacci" +type = "bin" +authors = [""] +compiler_version = ">=0.28.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/mock_oracle/Prover.toml b/test_programs/execution_success/fold_fibonacci/Prover.toml similarity index 90% rename from test_programs/execution_success/mock_oracle/Prover.toml rename to test_programs/execution_success/fold_fibonacci/Prover.toml index 2b26a4ce471..3a627b9188b 100644 --- a/test_programs/execution_success/mock_oracle/Prover.toml +++ b/test_programs/execution_success/fold_fibonacci/Prover.toml @@ -1,2 +1 @@ x = "10" - diff --git a/test_programs/execution_success/fold_fibonacci/src/main.nr b/test_programs/execution_success/fold_fibonacci/src/main.nr new file mode 100644 index 00000000000..e150a586086 --- /dev/null +++ b/test_programs/execution_success/fold_fibonacci/src/main.nr @@ -0,0 +1,12 @@ +fn main(x: u32) { + assert(fibonacci(x) == 55); +} + +#[fold] +fn fibonacci(x: u32) -> u32 { + if x <= 1 { + x + } else { + fibonacci(x - 1) + fibonacci(x - 2) + } +} diff --git a/test_programs/execution_success/fold_numeric_generic_poseidon/Nargo.toml b/test_programs/execution_success/fold_numeric_generic_poseidon/Nargo.toml new file mode 100644 index 00000000000..8c2bc79ea8d --- /dev/null +++ b/test_programs/execution_success/fold_numeric_generic_poseidon/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "fold_numeric_generic_poseidon" +type = "bin" +authors = [""] +compiler_version = ">=0.27.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/fold_numeric_generic_poseidon/Prover.toml b/test_programs/execution_success/fold_numeric_generic_poseidon/Prover.toml new file mode 100644 index 00000000000..00e821cf89d --- /dev/null +++ b/test_programs/execution_success/fold_numeric_generic_poseidon/Prover.toml @@ -0,0 +1,2 @@ +enable = [true, false] +to_hash = [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]] diff --git a/test_programs/execution_success/fold_numeric_generic_poseidon/src/main.nr b/test_programs/execution_success/fold_numeric_generic_poseidon/src/main.nr new file mode 100644 index 00000000000..f9f3e75789b --- /dev/null +++ b/test_programs/execution_success/fold_numeric_generic_poseidon/src/main.nr @@ -0,0 +1,33 @@ +use dep::std::hash::{pedersen_hash_with_separator, poseidon2::Poseidon2}; + +global NUM_HASHES = 2; +global HASH_LENGTH = 10; + +#[fold] +pub fn poseidon_hash(inputs: [Field; N]) -> Field { + Poseidon2::hash(inputs, inputs.len()) +} + +fn main( + to_hash: [[Field; HASH_LENGTH]; NUM_HASHES], + enable: [bool; NUM_HASHES] +) -> pub [Field; NUM_HASHES + 1] { + let mut result = [0; NUM_HASHES + 1]; + for i in 0..NUM_HASHES { + let enable = enable[i]; + let to_hash = to_hash[i]; + if enable { + result[i] = poseidon_hash(to_hash); + } + } + + // We want to make sure that the foldable function with a numeric generic + // is monomorphized correctly. + let mut double_preimage = [0; 20]; + for i in 0..HASH_LENGTH * 2 { + double_preimage[i] = to_hash[0][i % HASH_LENGTH]; + } + result[NUM_HASHES] = poseidon_hash(double_preimage); + + result +} diff --git a/test_programs/execution_success/generics/src/main.nr b/test_programs/execution_success/generics/src/main.nr index 3edce1ed8e7..c8616960559 100644 --- a/test_programs/execution_success/generics/src/main.nr +++ b/test_programs/execution_success/generics/src/main.nr @@ -31,6 +31,13 @@ impl Bar { } } +impl Bar { + // This is to test that we can use turbofish on methods as well + fn zeroed(_self: Self) -> A { + dep::std::unsafe::zeroed() + } +} + fn main(x: Field, y: Field) { let bar1: Bar = Bar { one: x, two: y, other: 0 }; let bar2 = Bar { one: x, two: y, other: [0] }; @@ -51,6 +58,14 @@ fn main(x: Field, y: Field) { let nested_generics: Bar> = Bar { one, two, other: Bar { one, two, other: 0 } }; assert(nested_generics.other.other == bar1.get_other()); + // Test turbofish operator + foo::(bar1); + + // Test that turbofish works on methods and that it uses the generics on the methods + // While still handling the generic on the impl (T in this case) that is implicitly added + // to the method. + assert(bar1.zeroed::() == 0); + let _ = regression_2055([1, 2, 3]); } diff --git a/test_programs/execution_success/global_consts/src/main.nr b/test_programs/execution_success/global_consts/src/main.nr index bb40a238d90..966be2741d6 100644 --- a/test_programs/execution_success/global_consts/src/main.nr +++ b/test_programs/execution_success/global_consts/src/main.nr @@ -107,3 +107,20 @@ mod my_submodule { x } } + +struct Foo { + a: Field, +} + +struct Bar {} + +impl Bar { + fn get_a() -> Field { + 1 + } +} + +// Regression for #1440 +global foo = Foo { + a: Bar::get_a(), +}; diff --git a/test_programs/execution_success/hash_to_field/src/main.nr b/test_programs/execution_success/hash_to_field/src/main.nr index 5af1c5af55e..242b5ecbc18 100644 --- a/test_programs/execution_success/hash_to_field/src/main.nr +++ b/test_programs/execution_success/hash_to_field/src/main.nr @@ -1,5 +1,5 @@ use dep::std; fn main(input: Field) -> pub Field { - std::hash::hash_to_field([input]) + std::hash::hash_to_field(&[input]) } diff --git a/test_programs/execution_success/hashmap/src/main.nr b/test_programs/execution_success/hashmap/src/main.nr index 597a5c0b7de..76daa594a89 100644 --- a/test_programs/execution_success/hashmap/src/main.nr +++ b/test_programs/execution_success/hashmap/src/main.nr @@ -2,7 +2,7 @@ mod utils; use dep::std::collections::map::HashMap; use dep::std::hash::BuildHasherDefault; -use dep::std::hash::pedersen::PedersenHasher; +use dep::std::hash::poseidon2::Poseidon2Hasher; use dep::std::cmp::Eq; use utils::cut; @@ -25,7 +25,7 @@ global K_CMP = FIELD_CMP; global V_CMP = FIELD_CMP; global KV_CMP = |a: (K, V), b: (K, V)| a.0.lt(b.0); -global ALLOCATE_HASHMAP = || -> HashMap> +global ALLOCATE_HASHMAP = || -> HashMap> HashMap::default(); fn main(input: [Entry; HASHMAP_LEN]) { @@ -37,6 +37,8 @@ fn main(input: [Entry; HASHMAP_LEN]) { test_retain(); test_iterators(); test_mut_iterators(); + + doc_tests(); } // Insert, get, remove. @@ -154,9 +156,9 @@ fn test_iterators() { hashmap.insert(5, 7); hashmap.insert(11, 13); - let keys: [K; 3] = cut(hashmap.keys()).map(|k: Option| k.unwrap_unchecked()).sort_via(K_CMP); - let values: [V; 3] = cut(hashmap.values()).map(|v: Option| v.unwrap_unchecked()).sort_via(V_CMP); - let entries: [(K, V); 3] = cut(hashmap.entries()).map(|e: Option<(K, V)>| e.unwrap_unchecked()).sort_via(KV_CMP); + let keys: [K; 3] = cut(hashmap.keys()).sort_via(K_CMP); + let values: [V; 3] = cut(hashmap.values()).sort_via(V_CMP); + let entries: [(K, V); 3] = cut(hashmap.entries()).sort_via(KV_CMP); assert(keys == [2, 5, 11], "Got incorrect iteration of keys."); assert(values == [3, 7, 13], "Got incorrect iteration of values."); @@ -177,8 +179,8 @@ fn test_mut_iterators() { let f = |v: V| -> V{ v * 5}; hashmap.iter_values_mut(f); - let keys: [K; 3] = cut(hashmap.keys()).map(|k: Option| k.unwrap_unchecked()).sort_via(K_CMP); - let values: [V; 3] = cut(hashmap.values()).map(|v: Option| v.unwrap_unchecked()).sort_via(V_CMP); + let keys: [K; 3] = cut(hashmap.keys()).sort_via(K_CMP); + let values: [V; 3] = cut(hashmap.values()).sort_via(V_CMP); assert(keys == [6, 15, 33], f"Got incorrect iteration of keys: {keys}"); assert(values == [15, 35, 65], "Got incorrect iteration of values."); @@ -186,7 +188,175 @@ fn test_mut_iterators() { let f = |k: K, v: V| -> (K, V){(k * 2, v * 2)}; hashmap.iter_mut(f); - let entries: [(K, V); 3] = cut(hashmap.entries()).map(|e: Option<(K, V)>| e.unwrap_unchecked()).sort_via(KV_CMP); + let entries: [(K, V); 3] = cut(hashmap.entries()).sort_via(KV_CMP); assert(entries == [(12, 30), (30, 70), (66, 130)], "Got incorrect iteration of entries."); } + +// docs:start:type_alias +type MyMap = HashMap>; +// docs:end:type_alias + +/// Tests examples from the stdlib hashmap documentation +fn doc_tests() { + // docs:start:default_example + let hashmap: HashMap> = HashMap::default(); + assert(hashmap.is_empty()); + // docs:end:default_example + + // docs:start:with_hasher_example + let my_hasher: BuildHasherDefault = Default::default(); + let hashmap: HashMap> = HashMap::with_hasher(my_hasher); + assert(hashmap.is_empty()); + // docs:end:with_hasher_example + + // docs:start:insert_example + let mut map: HashMap> = HashMap::default(); + map.insert(12, 42); + assert(map.len() == 1); + // docs:end:insert_example + + get_example(map); + + // docs:start:remove_example + map.remove(12); + assert(map.is_empty()); + + // If a key was not present in the map, remove does nothing + map.remove(12); + assert(map.is_empty()); + // docs:end:remove_example + + // docs:start:is_empty_example + assert(map.is_empty()); + + map.insert(1, 2); + assert(!map.is_empty()); + + map.remove(1); + assert(map.is_empty()); + // docs:end:is_empty_example + + // docs:start:len_example + // This is equivalent to checking map.is_empty() + assert(map.len() == 0); + + map.insert(1, 2); + map.insert(3, 4); + map.insert(5, 6); + assert(map.len() == 3); + + // 3 was already present as a key in the hash map, so the length is unchanged + map.insert(3, 7); + assert(map.len() == 3); + + map.remove(1); + assert(map.len() == 2); + // docs:end:len_example + + // docs:start:capacity_example + let empty_map: HashMap> = HashMap::default(); + assert(empty_map.len() == 0); + assert(empty_map.capacity() == 42); + // docs:end:capacity_example + + // docs:start:clear_example + assert(!map.is_empty()); + map.clear(); + assert(map.is_empty()); + // docs:end:clear_example + + // docs:start:contains_key_example + if map.contains_key(7) { + let value = map.get(7); + assert(value.is_some()); + } else { + println("No value for key 7!"); + } + // docs:end:contains_key_example + + entries_examples(map); + iter_examples(map); + + // docs:start:retain_example + map.retain(|k, v| (k != 0) & (v != 0)); + // docs:end:retain_example + + // docs:start:eq_example + let mut map1: HashMap> = HashMap::default(); + let mut map2: HashMap> = HashMap::default(); + + map1.insert(1, 2); + map1.insert(3, 4); + + map2.insert(3, 4); + map2.insert(1, 2); + + assert(map1 == map2); + // docs:end:eq_example +} + +// docs:start:get_example +fn get_example(map: HashMap>) { + let x = map.get(12); + + if x.is_some() { + assert(x.unwrap() == 42); + } +} +// docs:end:get_example + +fn entries_examples(map: HashMap>) { + // docs:start:entries_example + let entries = map.entries(); + + // The length of a hashmap may not be compile-time known, so we + // need to loop over its capacity instead + for i in 0..map.capacity() { + if i < entries.len() { + let (key, value) = entries.get(i); + println(f"{key} -> {value}"); + } + } + // docs:end:entries_example + + // docs:start:keys_example + let keys = map.keys(); + + for i in 0..keys.max_len() { + if i < keys.len() { + let key = keys.get_unchecked(i); + let value = map.get(key).unwrap_unchecked(); + println(f"{key} -> {value}"); + } + } + // docs:end:keys_example + + // docs:start:values_example + let values = map.values(); + + for i in 0..values.max_len() { + if i < values.len() { + let value = values.get_unchecked(i); + println(f"Found value {value}"); + } + } + // docs:end:values_example +} + +fn iter_examples(mut map: HashMap>) { + // docs:start:iter_mut_example + // Add 1 to each key in the map, and double the value associated with that key. + map.iter_mut(|k, v| (k + 1, v * 2)); + // docs:end:iter_mut_example + + // docs:start:iter_keys_mut_example + // Double each key, leaving the value associated with that key untouched + map.iter_keys_mut(|k| k * 2); + // docs:end:iter_keys_mut_example + + // docs:start:iter_values_mut_example + // Halve each value + map.iter_values_mut(|v| v / 2); + // docs:end:iter_values_mut_example +} diff --git a/test_programs/execution_success/hashmap/src/utils.nr b/test_programs/execution_success/hashmap/src/utils.nr index 59c4b356f7c..ee73245a902 100644 --- a/test_programs/execution_success/hashmap/src/utils.nr +++ b/test_programs/execution_success/hashmap/src/utils.nr @@ -1,10 +1,10 @@ -// Compile-time: cuts the M first elements from the [T; N] array. -pub(crate) fn cut(input: [T; N]) -> [T; M] { - assert(M as u64 < N as u64, "M should be less than N."); +// Compile-time: cuts the M first elements from the BoundedVec. +pub(crate) fn cut(input: BoundedVec) -> [T; M] { + assert(M < N, "M should be less than N."); - let mut new = [dep::std::unsafe_func::zeroed(); M]; + let mut new = BoundedVec::new(); for i in 0..M { - new[i] = input[i]; + new.push(input.get(i)); } - new + new.storage() } diff --git a/test_programs/execution_success/inline_never_basic/Nargo.toml b/test_programs/execution_success/inline_never_basic/Nargo.toml new file mode 100644 index 00000000000..16691770d76 --- /dev/null +++ b/test_programs/execution_success/inline_never_basic/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "inline_never_basic" +type = "bin" +authors = [""] +compiler_version = ">=0.27.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/inline_never_basic/Prover.toml b/test_programs/execution_success/inline_never_basic/Prover.toml new file mode 100644 index 00000000000..f28f2f8cc48 --- /dev/null +++ b/test_programs/execution_success/inline_never_basic/Prover.toml @@ -0,0 +1,2 @@ +x = "5" +y = "10" diff --git a/test_programs/execution_success/inline_never_basic/src/main.nr b/test_programs/execution_success/inline_never_basic/src/main.nr new file mode 100644 index 00000000000..1922aaedb6c --- /dev/null +++ b/test_programs/execution_success/inline_never_basic/src/main.nr @@ -0,0 +1,8 @@ +fn main(x: Field, y: pub Field) { + basic_check(x, y); +} + +#[inline(never)] +fn basic_check(x: Field, y: Field) { + assert(x != y); +} diff --git a/test_programs/execution_success/distinct_keyword/Nargo.toml b/test_programs/execution_success/is_unconstrained/Nargo.toml similarity index 67% rename from test_programs/execution_success/distinct_keyword/Nargo.toml rename to test_programs/execution_success/is_unconstrained/Nargo.toml index 3f1b1386ba7..deef68c7f72 100644 --- a/test_programs/execution_success/distinct_keyword/Nargo.toml +++ b/test_programs/execution_success/is_unconstrained/Nargo.toml @@ -1,5 +1,5 @@ [package] -name = "distinct_keyword" +name = "is_unconstrained" type = "bin" authors = [""] diff --git a/test_programs/execution_success/is_unconstrained/Prover.toml b/test_programs/execution_success/is_unconstrained/Prover.toml new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/test_programs/execution_success/is_unconstrained/Prover.toml @@ -0,0 +1 @@ + diff --git a/test_programs/execution_success/is_unconstrained/src/main.nr b/test_programs/execution_success/is_unconstrained/src/main.nr new file mode 100644 index 00000000000..af40af1029f --- /dev/null +++ b/test_programs/execution_success/is_unconstrained/src/main.nr @@ -0,0 +1,14 @@ +use dep::std::runtime::is_unconstrained; + +fn check(should_be_unconstrained: bool) { + assert_eq(should_be_unconstrained, is_unconstrained()); +} + +unconstrained fn unconstrained_intermediate() { + check(true); +} + +fn main() { + unconstrained_intermediate(); + check(false); +} diff --git a/test_programs/compile_success_empty/main_return/Nargo.toml b/test_programs/execution_success/main_return/Nargo.toml similarity index 100% rename from test_programs/compile_success_empty/main_return/Nargo.toml rename to test_programs/execution_success/main_return/Nargo.toml diff --git a/test_programs/compile_success_empty/main_return/Prover.toml b/test_programs/execution_success/main_return/Prover.toml similarity index 100% rename from test_programs/compile_success_empty/main_return/Prover.toml rename to test_programs/execution_success/main_return/Prover.toml diff --git a/test_programs/compile_success_empty/main_return/src/main.nr b/test_programs/execution_success/main_return/src/main.nr similarity index 100% rename from test_programs/compile_success_empty/main_return/src/main.nr rename to test_programs/execution_success/main_return/src/main.nr diff --git a/test_programs/execution_success/mock_oracle/src/main.nr b/test_programs/execution_success/mock_oracle/src/main.nr deleted file mode 100644 index 90fca7993cc..00000000000 --- a/test_programs/execution_success/mock_oracle/src/main.nr +++ /dev/null @@ -1,27 +0,0 @@ -use dep::std::test::OracleMock; - -struct Point { - x: Field, - y: Field, -} - -#[oracle(foo)] -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 }; - - OracleMock::mock("foo").returns(42).times(1); - let mock = OracleMock::mock("foo").returns(0); - assert_eq(42, foo_oracle(point, array)); - assert_eq(0, foo_oracle(point, array)); - mock.clear(); - - OracleMock::mock("foo").with_params((point, array)).returns(10); - OracleMock::mock("foo").with_params((point, another_array)).returns(20); - assert_eq(10, foo_oracle(point, array)); - assert_eq(20, foo_oracle(point, another_array)); -} - diff --git a/test_programs/execution_success/nested_array_dynamic_simple/Nargo.toml b/test_programs/execution_success/nested_array_dynamic_simple/Nargo.toml new file mode 100644 index 00000000000..50ba1d194a6 --- /dev/null +++ b/test_programs/execution_success/nested_array_dynamic_simple/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "nested_array_dynamic_simple" +type = "bin" +authors = [""] +compiler_version = ">=0.28.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/distinct_keyword/Prover.toml b/test_programs/execution_success/nested_array_dynamic_simple/Prover.toml similarity index 100% rename from test_programs/execution_success/distinct_keyword/Prover.toml rename to test_programs/execution_success/nested_array_dynamic_simple/Prover.toml diff --git a/test_programs/execution_success/nested_array_dynamic_simple/src/main.nr b/test_programs/execution_success/nested_array_dynamic_simple/src/main.nr new file mode 100644 index 00000000000..3b1908a463b --- /dev/null +++ b/test_programs/execution_success/nested_array_dynamic_simple/src/main.nr @@ -0,0 +1,9 @@ +fn main(x: Field) { + // x = 3 + let array: [[(Field, [Field; 1], [Field; 1]); 1]; 1] = [[(1, [2], [3])]]; + + let fetched_value = array[x - 3]; + assert(fetched_value[0].0 == 1); + assert(fetched_value[0].1[0] == 2); + assert(fetched_value[0].2[0] == 3); +} diff --git a/test_programs/execution_success/nested_array_in_slice/src/main.nr b/test_programs/execution_success/nested_array_in_slice/src/main.nr index a3007d5d0dc..0890115e95a 100644 --- a/test_programs/execution_success/nested_array_in_slice/src/main.nr +++ b/test_programs/execution_success/nested_array_in_slice/src/main.nr @@ -13,7 +13,7 @@ fn main(y: Field) { 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] } }; let foo_four = Foo { a: 10, b: [11, 12, 23], bar: Bar { inner: [109, 110, 111] } }; - let mut x = [foo_one]; + let mut x = &[foo_one]; x = x.push_back(foo_two); x = x.push_back(foo_three); x = x.push_back(foo_four); diff --git a/test_programs/execution_success/no_predicates_basic/Nargo.toml b/test_programs/execution_success/no_predicates_basic/Nargo.toml new file mode 100644 index 00000000000..bcefd550fb0 --- /dev/null +++ b/test_programs/execution_success/no_predicates_basic/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "no_predicates_basic" +type = "bin" +authors = [""] +compiler_version = ">=0.27.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/no_predicates_basic/Prover.toml b/test_programs/execution_success/no_predicates_basic/Prover.toml new file mode 100644 index 00000000000..f28f2f8cc48 --- /dev/null +++ b/test_programs/execution_success/no_predicates_basic/Prover.toml @@ -0,0 +1,2 @@ +x = "5" +y = "10" diff --git a/test_programs/execution_success/no_predicates_basic/src/main.nr b/test_programs/execution_success/no_predicates_basic/src/main.nr new file mode 100644 index 00000000000..d6037c2ab26 --- /dev/null +++ b/test_programs/execution_success/no_predicates_basic/src/main.nr @@ -0,0 +1,8 @@ +fn main(x: Field, y: pub Field) { + basic_check(x, y); +} + +#[no_predicates] +fn basic_check(x: Field, y: Field) { + assert(x != y); +} diff --git a/test_programs/execution_success/no_predicates_brillig/Nargo.toml b/test_programs/execution_success/no_predicates_brillig/Nargo.toml new file mode 100644 index 00000000000..328d78c8f99 --- /dev/null +++ b/test_programs/execution_success/no_predicates_brillig/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "no_predicates_brillig" +type = "bin" +authors = [""] +compiler_version = ">=0.27.0" + +[dependencies] diff --git a/test_programs/execution_success/no_predicates_brillig/Prover.toml b/test_programs/execution_success/no_predicates_brillig/Prover.toml new file mode 100644 index 00000000000..93a825f609f --- /dev/null +++ b/test_programs/execution_success/no_predicates_brillig/Prover.toml @@ -0,0 +1,2 @@ +x = "10" +y = "20" diff --git a/test_programs/execution_success/no_predicates_brillig/src/main.nr b/test_programs/execution_success/no_predicates_brillig/src/main.nr new file mode 100644 index 00000000000..65e2e5d61fe --- /dev/null +++ b/test_programs/execution_success/no_predicates_brillig/src/main.nr @@ -0,0 +1,16 @@ +unconstrained fn main(x: u32, y: pub u32) { + intermediate_function(x, y); +} + +fn intermediate_function(x: u32, y: u32) { + basic_checks(x, y); +} + +#[no_predicates] +fn basic_checks(x: u32, y: u32) { + if x > y { + assert(x == 10); + } else { + assert(y == 20); + } +} diff --git a/test_programs/execution_success/no_predicates_numeric_generic_poseidon/Nargo.toml b/test_programs/execution_success/no_predicates_numeric_generic_poseidon/Nargo.toml new file mode 100644 index 00000000000..1ce13c24287 --- /dev/null +++ b/test_programs/execution_success/no_predicates_numeric_generic_poseidon/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "no_predicates_numeric_generic_poseidon" +type = "bin" +authors = [""] +compiler_version = ">=0.28.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/no_predicates_numeric_generic_poseidon/Prover.toml b/test_programs/execution_success/no_predicates_numeric_generic_poseidon/Prover.toml new file mode 100644 index 00000000000..00e821cf89d --- /dev/null +++ b/test_programs/execution_success/no_predicates_numeric_generic_poseidon/Prover.toml @@ -0,0 +1,2 @@ +enable = [true, false] +to_hash = [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]] diff --git a/test_programs/execution_success/no_predicates_numeric_generic_poseidon/src/main.nr b/test_programs/execution_success/no_predicates_numeric_generic_poseidon/src/main.nr new file mode 100644 index 00000000000..dcb5e6bc5ca --- /dev/null +++ b/test_programs/execution_success/no_predicates_numeric_generic_poseidon/src/main.nr @@ -0,0 +1,33 @@ +use dep::std::hash::{pedersen_hash_with_separator, poseidon2::Poseidon2}; + +global NUM_HASHES = 2; +global HASH_LENGTH = 10; + +#[no_predicates] +pub fn poseidon_hash(inputs: [Field; N]) -> Field { + Poseidon2::hash(inputs, inputs.len()) +} + +fn main( + to_hash: [[Field; HASH_LENGTH]; NUM_HASHES], + enable: [bool; NUM_HASHES] +) -> pub [Field; NUM_HASHES + 1] { + let mut result = [0; NUM_HASHES + 1]; + for i in 0..NUM_HASHES { + let enable = enable[i]; + let to_hash = to_hash[i]; + if enable { + result[i] = poseidon_hash(to_hash); + } + } + + // We want to make sure that the function marked with `#[no_predicates]` with a numeric generic + // is monomorphized correctly. + let mut double_preimage = [0; 20]; + for i in 0..HASH_LENGTH * 2 { + double_preimage[i] = to_hash[0][i % HASH_LENGTH]; + } + result[NUM_HASHES] = poseidon_hash(double_preimage); + + result +} diff --git a/test_programs/execution_success/operator_overloading/src/main.nr b/test_programs/execution_success/operator_overloading/src/main.nr index d61e1da170e..3956ea5c577 100644 --- a/test_programs/execution_success/operator_overloading/src/main.nr +++ b/test_programs/execution_success/operator_overloading/src/main.nr @@ -20,8 +20,8 @@ fn main(x: u32, y: u32) { assert((wx | wy).inner == (ex | ey)); assert((wx ^ wy).inner == (ex ^ ey)); - assert((wy << wx).inner == (ey << ex)); - assert((wy >> wx).inner == (ey >> ex)); + assert((wy << x as u8).inner == (ey << ex as u8)); + assert((wy >> x as u8).inner == (ey >> ex as u8)); assert((wx == wy) == (ex == ey)); assert((wx < wy) == (ex < ey)); @@ -103,14 +103,14 @@ impl BitXor for Wrapper { } impl Shl for Wrapper { - fn shl(self, other: Self) -> Self { - Wrapper::new(self.inner << other.inner) + fn shl(self, other: u8) -> Self { + Wrapper::new(self.inner << other) } } impl Shr for Wrapper { - fn shr(self, other: Self) -> Self { - Wrapper::new(self.inner >> other.inner) + fn shr(self, other: u8) -> Self { + Wrapper::new(self.inner >> other) } } diff --git a/test_programs/execution_success/pedersen_commitment/Prover.toml b/test_programs/execution_success/pedersen_commitment/Prover.toml index 6ad8c6bca57..0279f7d2096 100644 --- a/test_programs/execution_success/pedersen_commitment/Prover.toml +++ b/test_programs/execution_success/pedersen_commitment/Prover.toml @@ -4,3 +4,4 @@ y = "1" [expected_commitment] x = "0x054aa86a73cb8a34525e5bbed6e43ba1198e860f5f3950268f71df4591bde402" y = "0x209dcfbf2cfb57f9f6046f44d71ac6faf87254afc7407c04eb621a6287cac126" +is_infinite = false diff --git a/test_programs/execution_success/pedersen_commitment/src/main.nr b/test_programs/execution_success/pedersen_commitment/src/main.nr index 83cbe20851d..a3a9aea1cf0 100644 --- a/test_programs/execution_success/pedersen_commitment/src/main.nr +++ b/test_programs/execution_success/pedersen_commitment/src/main.nr @@ -1,7 +1,7 @@ // docs:start:pedersen-commitment use dep::std; -fn main(x: Field, y: Field, expected_commitment: std::hash::PedersenPoint) { +fn main(x: Field, y: Field, expected_commitment: std::embedded_curve_ops::EmbeddedCurvePoint) { let commitment = std::hash::pedersen_commitment([x, y]); assert_eq(commitment.x, expected_commitment.x); assert_eq(commitment.y, expected_commitment.y); diff --git a/test_programs/execution_success/poseidon_bn254_hash/src/main.nr b/test_programs/execution_success/poseidon_bn254_hash/src/main.nr index 939b99595c7..a1607956190 100644 --- a/test_programs/execution_success/poseidon_bn254_hash/src/main.nr +++ b/test_programs/execution_success/poseidon_bn254_hash/src/main.nr @@ -9,7 +9,7 @@ fn main(x1: [Field; 2], y1: pub Field, x2: [Field; 4], y2: pub Field, x3: [Field let hash2 = poseidon::bn254::hash_4(x2); assert(hash2 == y2); - let hash3 = poseidon2::Poseidon2::hash(x3, x3.len() as u32); + let hash3 = poseidon2::Poseidon2::hash(x3, x3.len()); assert(hash3 == y3); } // docs:end:poseidon diff --git a/test_programs/execution_success/prelude/src/main.nr b/test_programs/execution_success/prelude/src/main.nr index c9ae448c486..226341f1e7b 100644 --- a/test_programs/execution_success/prelude/src/main.nr +++ b/test_programs/execution_success/prelude/src/main.nr @@ -1,6 +1,6 @@ fn main() { - let _xs = Vec::new(); - let _option = Option::none(); + let _xs: Vec = Vec::new(); + let _option: Option = Option::none(); print("42\n"); println("42"); diff --git a/test_programs/execution_success/regression/src/main.nr b/test_programs/execution_success/regression/src/main.nr index c56f3ef4190..e60791aface 100644 --- a/test_programs/execution_success/regression/src/main.nr +++ b/test_programs/execution_success/regression/src/main.nr @@ -1,4 +1,4 @@ -global NIBBLE_LENGTH: u64 = 16; +global NIBBLE_LENGTH: u32 = 16; struct U4 { inner: u8, @@ -22,7 +22,7 @@ impl Eq for U4 { fn compact_decode(input: [u8; N], length: Field) -> ([U4; NIBBLE_LENGTH], Field) { assert(2 * input.len() <= NIBBLE_LENGTH); - assert(length as u64 <= input.len()); + assert(length as u32 <= input.len()); let mut nibble = [U4::zero(); NIBBLE_LENGTH]; @@ -32,7 +32,7 @@ fn compact_decode(input: [u8; N], length: Field) -> ([U4; NIBBLE_LENGTH], Fie if parity == 1 { nibble[0] = U4::from_u8(input[0] & 0x0f); for i in 1..input.len() { - if i as u64 < length as u64 { + if i as u32 < length as u32 { let x = input[i]; nibble[2*i - 1] = U4::from_u8(x >> 4); nibble[2*i] = U4::from_u8(x & 0x0f); @@ -40,7 +40,7 @@ fn compact_decode(input: [u8; N], length: Field) -> ([U4; NIBBLE_LENGTH], Fie } } else { for i in 0..2 { - if (i as u64) < length as u64 - 1 { + if (i as u32) < length as u32 - 1 { let x = input[i + 1]; nibble[2*i] = U4::from_u8(x >> 4); nibble[2*i + 1] = U4::from_u8(x & 0x0f); @@ -87,7 +87,7 @@ fn bitshift_literal_4() -> u64 { bits } -fn bitshift_variable(idx: u64) -> u64 { +fn bitshift_variable(idx: u8) -> u64 { let mut bits: u64 = 0; bits |= 1 << idx; diff --git a/test_programs/execution_success/regression_3051/Nargo.toml b/test_programs/execution_success/regression_3051/Nargo.toml new file mode 100644 index 00000000000..844f74cdcb3 --- /dev/null +++ b/test_programs/execution_success/regression_3051/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "regression_3051" +type = "bin" +authors = [""] +compiler_version = ">=0.27.0" + +[dependencies] diff --git a/test_programs/execution_success/regression_3051/src/main.nr b/test_programs/execution_success/regression_3051/src/main.nr new file mode 100644 index 00000000000..2e7d10fd7b0 --- /dev/null +++ b/test_programs/execution_success/regression_3051/src/main.nr @@ -0,0 +1,24 @@ +trait Foo { + fn foo(self) -> Field; +} + +impl Foo for Field { + fn foo(self) -> Field { + self + 1 + } +} + +trait Bar { + fn bar(self) -> u64; +} + +impl Bar for u64 { + fn bar(self) -> u64 { + self + 1 + } +} + +fn main() { + dep::std::println(1.foo()); + dep::std::println(1.bar()); +} diff --git a/test_programs/execution_success/regression_4202/src/main.nr b/test_programs/execution_success/regression_4202/src/main.nr index 37d2ee4578d..faa14f03912 100644 --- a/test_programs/execution_success/regression_4202/src/main.nr +++ b/test_programs/execution_success/regression_4202/src/main.nr @@ -1,5 +1,5 @@ fn main(input: [u32; 4]) { - let mut slice1: [u32] = [1, 2, 3, 4]; + let mut slice1: [u32] = &[1, 2, 3, 4]; if slice1[0] == 3 { slice1[1] = 4; } diff --git a/test_programs/execution_success/brillig_schnorr/Nargo.toml b/test_programs/execution_success/regression_4449/Nargo.toml similarity index 68% rename from test_programs/execution_success/brillig_schnorr/Nargo.toml rename to test_programs/execution_success/regression_4449/Nargo.toml index 1b598abbf74..925420a03a8 100644 --- a/test_programs/execution_success/brillig_schnorr/Nargo.toml +++ b/test_programs/execution_success/regression_4449/Nargo.toml @@ -1,5 +1,5 @@ [package] -name = "brillig_schnorr" +name = "regression_4449" type = "bin" authors = [""] diff --git a/test_programs/execution_success/regression_4449/Prover.toml b/test_programs/execution_success/regression_4449/Prover.toml new file mode 100644 index 00000000000..81af476bcc9 --- /dev/null +++ b/test_programs/execution_success/regression_4449/Prover.toml @@ -0,0 +1,3 @@ + +x = 0xbd +result = [204, 59, 83, 197, 18, 1, 128, 43, 247, 28, 104, 225, 106, 13, 20, 187, 42, 26, 67, 150, 48, 75, 238, 168, 121, 247, 142, 160, 71, 222, 97, 188] \ No newline at end of file diff --git a/test_programs/execution_success/regression_4449/src/main.nr b/test_programs/execution_success/regression_4449/src/main.nr new file mode 100644 index 00000000000..454a93f5d1a --- /dev/null +++ b/test_programs/execution_success/regression_4449/src/main.nr @@ -0,0 +1,14 @@ +// Regression test for issue #4449 +use dep::std; + +fn main(x: u8, result: [u8; 32]) { + let x = x % 31; + let mut digest = [0; 32]; + for i in 0..70 { + let y = x + i; + let a = [y, x, 32, 0, y + 1, y - 1, y - 2, 5]; + digest = std::sha256::digest(a); + } + + assert(digest == result); +} diff --git a/test_programs/execution_success/brillig_array_eq/Nargo.toml b/test_programs/execution_success/regression_4709/Nargo.toml similarity index 67% rename from test_programs/execution_success/brillig_array_eq/Nargo.toml rename to test_programs/execution_success/regression_4709/Nargo.toml index 62ce392f96b..2e0ce3fb5af 100644 --- a/test_programs/execution_success/brillig_array_eq/Nargo.toml +++ b/test_programs/execution_success/regression_4709/Nargo.toml @@ -1,5 +1,5 @@ [package] -name = "brillig_array_eq" +name = "regression_4709" type = "bin" authors = [""] diff --git a/test_programs/compile_failure/dep_impl_primitive/Prover.toml b/test_programs/execution_success/regression_4709/Prover.toml similarity index 54% rename from test_programs/compile_failure/dep_impl_primitive/Prover.toml rename to test_programs/execution_success/regression_4709/Prover.toml index 7d4290a117a..dcfab705327 100644 --- a/test_programs/compile_failure/dep_impl_primitive/Prover.toml +++ b/test_programs/execution_success/regression_4709/Prover.toml @@ -1 +1,2 @@ x = 1 +y = 2 \ No newline at end of file diff --git a/test_programs/execution_success/regression_4709/src/main.nr b/test_programs/execution_success/regression_4709/src/main.nr new file mode 100644 index 00000000000..1df09c53b55 --- /dev/null +++ b/test_programs/execution_success/regression_4709/src/main.nr @@ -0,0 +1,271 @@ +// Regression test for issue #4709 +global EXPONENTIATE: [[Field; 257]; 257] = [ +[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], +[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], +[1, 2, 4, 8, 16, 32, 64, 128, 256, 255, 253, 249, 241, 225, 193, 129, 1, 2, 4, 8, 16, 32, 64, 128, 256, 255, 253, 249, 241, 225, 193, 129, 1, 2, 4, 8, 16, 32, 64, 128, 256, 255, 253, 249, 241, 225, 193, 129, 1, 2, 4, 8, 16, 32, 64, 128, 256, 255, 253, 249, 241, 225, 193, 129, 1, 2, 4, 8, 16, 32, 64, 128, 256, 255, 253, 249, 241, 225, 193, 129, 1, 2, 4, 8, 16, 32, 64, 128, 256, 255, 253, 249, 241, 225, 193, 129, 1, 2, 4, 8, 16, 32, 64, 128, 256, 255, 253, 249, 241, 225, 193, 129, 1, 2, 4, 8, 16, 32, 64, 128, 256, 255, 253, 249, 241, 225, 193, 129, 1, 2, 4, 8, 16, 32, 64, 128, 256, 255, 253, 249, 241, 225, 193, 129, 1, 2, 4, 8, 16, 32, 64, 128, 256, 255, 253, 249, 241, 225, 193, 129, 1, 2, 4, 8, 16, 32, 64, 128, 256, 255, 253, 249, 241, 225, 193, 129, 1, 2, 4, 8, 16, 32, 64, 128, 256, 255, 253, 249, 241, 225, 193, 129, 1, 2, 4, 8, 16, 32, 64, 128, 256, 255, 253, 249, 241, 225, 193, 129, 1, 2, 4, 8, 16, 32, 64, 128, 256, 255, 253, 249, 241, 225, 193, 129, 1, 2, 4, 8, 16, 32, 64, 128, 256, 255, 253, 249, 241, 225, 193, 129, 1, 2, 4, 8, 16, 32, 64, 128, 256, 255, 253, 249, 241, 225, 193, 129, 1], +[1, 3, 9, 27, 81, 243, 215, 131, 136, 151, 196, 74, 222, 152, 199, 83, 249, 233, 185, 41, 123, 112, 79, 237, 197, 77, 231, 179, 23, 69, 207, 107, 64, 192, 62, 186, 44, 132, 139, 160, 223, 155, 208, 110, 73, 219, 143, 172, 2, 6, 18, 54, 162, 229, 173, 5, 15, 45, 135, 148, 187, 47, 141, 166, 241, 209, 113, 82, 246, 224, 158, 217, 137, 154, 205, 101, 46, 138, 157, 214, 128, 127, 124, 115, 88, 7, 21, 63, 189, 53, 159, 220, 146, 181, 29, 87, 4, 12, 36, 108, 67, 201, 89, 10, 30, 90, 13, 39, 117, 94, 25, 75, 225, 161, 226, 164, 235, 191, 59, 177, 17, 51, 153, 202, 92, 19, 57, 171, 256, 254, 248, 230, 176, 14, 42, 126, 121, 106, 61, 183, 35, 105, 58, 174, 8, 24, 72, 216, 134, 145, 178, 20, 60, 180, 26, 78, 234, 188, 50, 150, 193, 65, 195, 71, 213, 125, 118, 97, 34, 102, 49, 147, 184, 38, 114, 85, 255, 251, 239, 203, 95, 28, 84, 252, 242, 212, 122, 109, 70, 210, 116, 91, 16, 48, 144, 175, 11, 33, 99, 40, 120, 103, 52, 156, 211, 119, 100, 43, 129, 130, 133, 142, 169, 250, 236, 194, 68, 204, 98, 37, 111, 76, 228, 170, 253, 245, 221, 149, 190, 56, 168, 247, 227, 167, 244, 218, 140, 163, 232, 182, 32, 96, 31, 93, 22, 66, 198, 80, 240, 206, 104, 55, 165, 238, 200, 86, 1], +[1, 4, 16, 64, 256, 253, 241, 193, 1, 4, 16, 64, 256, 253, 241, 193, 1, 4, 16, 64, 256, 253, 241, 193, 1, 4, 16, 64, 256, 253, 241, 193, 1, 4, 16, 64, 256, 253, 241, 193, 1, 4, 16, 64, 256, 253, 241, 193, 1, 4, 16, 64, 256, 253, 241, 193, 1, 4, 16, 64, 256, 253, 241, 193, 1, 4, 16, 64, 256, 253, 241, 193, 1, 4, 16, 64, 256, 253, 241, 193, 1, 4, 16, 64, 256, 253, 241, 193, 1, 4, 16, 64, 256, 253, 241, 193, 1, 4, 16, 64, 256, 253, 241, 193, 1, 4, 16, 64, 256, 253, 241, 193, 1, 4, 16, 64, 256, 253, 241, 193, 1, 4, 16, 64, 256, 253, 241, 193, 1, 4, 16, 64, 256, 253, 241, 193, 1, 4, 16, 64, 256, 253, 241, 193, 1, 4, 16, 64, 256, 253, 241, 193, 1, 4, 16, 64, 256, 253, 241, 193, 1, 4, 16, 64, 256, 253, 241, 193, 1, 4, 16, 64, 256, 253, 241, 193, 1, 4, 16, 64, 256, 253, 241, 193, 1, 4, 16, 64, 256, 253, 241, 193, 1, 4, 16, 64, 256, 253, 241, 193, 1, 4, 16, 64, 256, 253, 241, 193, 1, 4, 16, 64, 256, 253, 241, 193, 1, 4, 16, 64, 256, 253, 241, 193, 1, 4, 16, 64, 256, 253, 241, 193, 1, 4, 16, 64, 256, 253, 241, 193, 1, 4, 16, 64, 256, 253, 241, 193, 1, 4, 16, 64, 256, 253, 241, 193, 1], +[1, 5, 25, 125, 111, 41, 205, 254, 242, 182, 139, 181, 134, 156, 9, 45, 225, 97, 228, 112, 46, 230, 122, 96, 223, 87, 178, 119, 81, 148, 226, 102, 253, 237, 157, 14, 70, 93, 208, 12, 60, 43, 215, 47, 235, 147, 221, 77, 128, 126, 116, 66, 73, 108, 26, 130, 136, 166, 59, 38, 190, 179, 124, 106, 16, 80, 143, 201, 234, 142, 196, 209, 17, 85, 168, 69, 88, 183, 144, 206, 2, 10, 50, 250, 222, 82, 153, 251, 227, 107, 21, 105, 11, 55, 18, 90, 193, 194, 199, 224, 92, 203, 244, 192, 189, 174, 99, 238, 162, 39, 195, 204, 249, 217, 57, 28, 140, 186, 159, 24, 120, 86, 173, 94, 213, 37, 185, 154, 256, 252, 232, 132, 146, 216, 52, 3, 15, 75, 118, 76, 123, 101, 248, 212, 32, 160, 29, 145, 211, 27, 135, 161, 34, 170, 79, 138, 176, 109, 31, 155, 4, 20, 100, 243, 187, 164, 49, 245, 197, 214, 42, 210, 22, 110, 36, 180, 129, 131, 141, 191, 184, 149, 231, 127, 121, 91, 198, 219, 67, 78, 133, 151, 241, 177, 114, 56, 23, 115, 61, 48, 240, 172, 89, 188, 169, 74, 113, 51, 255, 247, 207, 7, 35, 175, 104, 6, 30, 150, 236, 152, 246, 202, 239, 167, 64, 63, 58, 33, 165, 54, 13, 65, 68, 83, 158, 19, 95, 218, 62, 53, 8, 40, 200, 229, 117, 71, 98, 233, 137, 171, 84, 163, 44, 220, 72, 103, 1], +[1, 6, 36, 216, 11, 66, 139, 63, 121, 212, 244, 179, 46, 19, 114, 170, 249, 209, 226, 71, 169, 243, 173, 10, 60, 103, 104, 110, 146, 105, 116, 182, 64, 127, 248, 203, 190, 112, 158, 177, 34, 204, 196, 148, 117, 188, 100, 86, 2, 12, 72, 175, 22, 132, 21, 126, 242, 167, 231, 101, 92, 38, 228, 83, 241, 161, 195, 142, 81, 229, 89, 20, 120, 206, 208, 220, 35, 210, 232, 107, 128, 254, 239, 149, 123, 224, 59, 97, 68, 151, 135, 39, 234, 119, 200, 172, 4, 24, 144, 93, 44, 7, 42, 252, 227, 77, 205, 202, 184, 76, 199, 166, 225, 65, 133, 27, 162, 201, 178, 40, 240, 155, 159, 183, 70, 163, 207, 214, 256, 251, 221, 41, 246, 191, 118, 194, 136, 45, 13, 78, 211, 238, 143, 87, 8, 48, 31, 186, 88, 14, 84, 247, 197, 154, 153, 147, 111, 152, 141, 75, 193, 130, 9, 54, 67, 145, 99, 80, 223, 53, 61, 109, 140, 69, 157, 171, 255, 245, 185, 82, 235, 125, 236, 131, 15, 90, 26, 156, 165, 219, 29, 174, 16, 96, 62, 115, 176, 28, 168, 237, 137, 51, 49, 37, 222, 47, 25, 150, 129, 3, 18, 108, 134, 33, 198, 160, 189, 106, 122, 218, 23, 138, 57, 85, 253, 233, 113, 164, 213, 250, 215, 5, 30, 180, 52, 55, 73, 181, 58, 91, 32, 192, 124, 230, 95, 56, 79, 217, 17, 102, 98, 74, 187, 94, 50, 43, 1], +[1, 7, 49, 86, 88, 102, 200, 115, 34, 238, 124, 97, 165, 127, 118, 55, 128, 125, 104, 214, 213, 206, 157, 71, 240, 138, 195, 80, 46, 65, 198, 101, 193, 66, 205, 150, 22, 154, 50, 93, 137, 188, 31, 217, 234, 96, 158, 78, 32, 224, 26, 182, 246, 180, 232, 82, 60, 163, 113, 20, 140, 209, 178, 218, 241, 145, 244, 166, 134, 167, 141, 216, 227, 47, 72, 247, 187, 24, 168, 148, 8, 56, 135, 174, 190, 45, 58, 149, 15, 105, 221, 5, 35, 245, 173, 183, 253, 229, 61, 170, 162, 106, 228, 54, 121, 76, 18, 126, 111, 6, 42, 37, 2, 14, 98, 172, 176, 204, 143, 230, 68, 219, 248, 194, 73, 254, 236, 110, 256, 250, 208, 171, 169, 155, 57, 142, 223, 19, 133, 160, 92, 130, 139, 202, 129, 132, 153, 43, 44, 51, 100, 186, 17, 119, 62, 177, 211, 192, 59, 156, 64, 191, 52, 107, 235, 103, 207, 164, 120, 69, 226, 40, 23, 161, 99, 179, 225, 33, 231, 75, 11, 77, 25, 175, 197, 94, 144, 237, 117, 48, 79, 39, 16, 112, 13, 91, 123, 90, 116, 41, 30, 210, 185, 10, 70, 233, 89, 109, 249, 201, 122, 83, 67, 212, 199, 108, 242, 152, 36, 252, 222, 12, 84, 74, 4, 28, 196, 87, 95, 151, 29, 203, 136, 181, 239, 131, 146, 251, 215, 220, 255, 243, 159, 85, 81, 53, 114, 27, 189, 38, 9, 63, 184, 3, 21, 147, 1], +[1, 8, 64, 255, 241, 129, 4, 32, 256, 249, 193, 2, 16, 128, 253, 225, 1, 8, 64, 255, 241, 129, 4, 32, 256, 249, 193, 2, 16, 128, 253, 225, 1, 8, 64, 255, 241, 129, 4, 32, 256, 249, 193, 2, 16, 128, 253, 225, 1, 8, 64, 255, 241, 129, 4, 32, 256, 249, 193, 2, 16, 128, 253, 225, 1, 8, 64, 255, 241, 129, 4, 32, 256, 249, 193, 2, 16, 128, 253, 225, 1, 8, 64, 255, 241, 129, 4, 32, 256, 249, 193, 2, 16, 128, 253, 225, 1, 8, 64, 255, 241, 129, 4, 32, 256, 249, 193, 2, 16, 128, 253, 225, 1, 8, 64, 255, 241, 129, 4, 32, 256, 249, 193, 2, 16, 128, 253, 225, 1, 8, 64, 255, 241, 129, 4, 32, 256, 249, 193, 2, 16, 128, 253, 225, 1, 8, 64, 255, 241, 129, 4, 32, 256, 249, 193, 2, 16, 128, 253, 225, 1, 8, 64, 255, 241, 129, 4, 32, 256, 249, 193, 2, 16, 128, 253, 225, 1, 8, 64, 255, 241, 129, 4, 32, 256, 249, 193, 2, 16, 128, 253, 225, 1, 8, 64, 255, 241, 129, 4, 32, 256, 249, 193, 2, 16, 128, 253, 225, 1, 8, 64, 255, 241, 129, 4, 32, 256, 249, 193, 2, 16, 128, 253, 225, 1, 8, 64, 255, 241, 129, 4, 32, 256, 249, 193, 2, 16, 128, 253, 225, 1, 8, 64, 255, 241, 129, 4, 32, 256, 249, 193, 2, 16, 128, 253, 225, 1], +[1, 9, 81, 215, 136, 196, 222, 199, 249, 185, 123, 79, 197, 231, 23, 207, 64, 62, 44, 139, 223, 208, 73, 143, 2, 18, 162, 173, 15, 135, 187, 141, 241, 113, 246, 158, 137, 205, 46, 157, 128, 124, 88, 21, 189, 159, 146, 29, 4, 36, 67, 89, 30, 13, 117, 25, 225, 226, 235, 59, 17, 153, 92, 57, 256, 248, 176, 42, 121, 61, 35, 58, 8, 72, 134, 178, 60, 26, 234, 50, 193, 195, 213, 118, 34, 49, 184, 114, 255, 239, 95, 84, 242, 122, 70, 116, 16, 144, 11, 99, 120, 52, 211, 100, 129, 133, 169, 236, 68, 98, 111, 228, 253, 221, 190, 168, 227, 244, 140, 232, 32, 31, 22, 198, 240, 104, 165, 200, 1, 9, 81, 215, 136, 196, 222, 199, 249, 185, 123, 79, 197, 231, 23, 207, 64, 62, 44, 139, 223, 208, 73, 143, 2, 18, 162, 173, 15, 135, 187, 141, 241, 113, 246, 158, 137, 205, 46, 157, 128, 124, 88, 21, 189, 159, 146, 29, 4, 36, 67, 89, 30, 13, 117, 25, 225, 226, 235, 59, 17, 153, 92, 57, 256, 248, 176, 42, 121, 61, 35, 58, 8, 72, 134, 178, 60, 26, 234, 50, 193, 195, 213, 118, 34, 49, 184, 114, 255, 239, 95, 84, 242, 122, 70, 116, 16, 144, 11, 99, 120, 52, 211, 100, 129, 133, 169, 236, 68, 98, 111, 228, 253, 221, 190, 168, 227, 244, 140, 232, 32, 31, 22, 198, 240, 104, 165, 200, 1], +[1, 10, 100, 229, 234, 27, 13, 130, 15, 150, 215, 94, 169, 148, 195, 151, 225, 194, 141, 125, 222, 164, 98, 209, 34, 83, 59, 76, 246, 147, 185, 51, 253, 217, 114, 112, 92, 149, 205, 251, 197, 171, 168, 138, 95, 179, 248, 167, 128, 252, 207, 14, 140, 115, 122, 192, 121, 182, 21, 210, 44, 183, 31, 53, 16, 160, 58, 66, 146, 175, 208, 24, 240, 87, 99, 219, 134, 55, 36, 103, 2, 20, 200, 201, 211, 54, 26, 3, 30, 43, 173, 188, 81, 39, 133, 45, 193, 131, 25, 250, 187, 71, 196, 161, 68, 166, 118, 152, 235, 37, 113, 102, 249, 177, 228, 224, 184, 41, 153, 245, 137, 85, 79, 19, 190, 101, 239, 77, 256, 247, 157, 28, 23, 230, 244, 127, 242, 107, 42, 163, 88, 109, 62, 106, 32, 63, 116, 132, 35, 93, 159, 48, 223, 174, 198, 181, 11, 110, 72, 206, 4, 40, 143, 145, 165, 108, 52, 6, 60, 86, 89, 119, 162, 78, 9, 90, 129, 5, 50, 243, 117, 142, 135, 65, 136, 75, 236, 47, 213, 74, 226, 204, 241, 97, 199, 191, 111, 82, 49, 233, 17, 170, 158, 38, 123, 202, 221, 154, 255, 237, 57, 56, 46, 203, 231, 254, 227, 214, 84, 69, 176, 218, 124, 212, 64, 126, 232, 7, 70, 186, 61, 96, 189, 91, 139, 105, 22, 220, 144, 155, 8, 80, 29, 33, 73, 216, 104, 12, 120, 172, 178, 238, 67, 156, 18, 180, 1], +[1, 11, 121, 46, 249, 169, 60, 146, 64, 190, 34, 117, 2, 22, 242, 92, 241, 81, 120, 35, 128, 123, 68, 234, 4, 44, 227, 184, 225, 162, 240, 70, 256, 246, 136, 211, 8, 88, 197, 111, 193, 67, 223, 140, 255, 235, 15, 165, 16, 176, 137, 222, 129, 134, 189, 23, 253, 213, 30, 73, 32, 95, 17, 187, 1, 11, 121, 46, 249, 169, 60, 146, 64, 190, 34, 117, 2, 22, 242, 92, 241, 81, 120, 35, 128, 123, 68, 234, 4, 44, 227, 184, 225, 162, 240, 70, 256, 246, 136, 211, 8, 88, 197, 111, 193, 67, 223, 140, 255, 235, 15, 165, 16, 176, 137, 222, 129, 134, 189, 23, 253, 213, 30, 73, 32, 95, 17, 187, 1, 11, 121, 46, 249, 169, 60, 146, 64, 190, 34, 117, 2, 22, 242, 92, 241, 81, 120, 35, 128, 123, 68, 234, 4, 44, 227, 184, 225, 162, 240, 70, 256, 246, 136, 211, 8, 88, 197, 111, 193, 67, 223, 140, 255, 235, 15, 165, 16, 176, 137, 222, 129, 134, 189, 23, 253, 213, 30, 73, 32, 95, 17, 187, 1, 11, 121, 46, 249, 169, 60, 146, 64, 190, 34, 117, 2, 22, 242, 92, 241, 81, 120, 35, 128, 123, 68, 234, 4, 44, 227, 184, 225, 162, 240, 70, 256, 246, 136, 211, 8, 88, 197, 111, 193, 67, 223, 140, 255, 235, 15, 165, 16, 176, 137, 222, 129, 134, 189, 23, 253, 213, 30, 73, 32, 95, 17, 187, 1], +[1, 12, 144, 186, 176, 56, 158, 97, 136, 90, 52, 110, 35, 163, 157, 85, 249, 161, 133, 54, 134, 66, 21, 252, 197, 51, 98, 148, 234, 238, 29, 91, 64, 254, 221, 82, 213, 243, 89, 40, 223, 106, 244, 101, 184, 152, 25, 43, 2, 24, 31, 115, 95, 112, 59, 194, 15, 180, 104, 220, 70, 69, 57, 170, 241, 65, 9, 108, 11, 132, 42, 247, 137, 102, 196, 39, 211, 219, 58, 182, 128, 251, 185, 164, 169, 229, 178, 80, 189, 212, 231, 202, 111, 47, 50, 86, 4, 48, 62, 230, 190, 224, 118, 131, 30, 103, 208, 183, 140, 138, 114, 83, 225, 130, 18, 216, 22, 7, 84, 237, 17, 204, 135, 78, 165, 181, 116, 107, 256, 245, 113, 71, 81, 201, 99, 160, 121, 167, 205, 147, 222, 94, 100, 172, 8, 96, 124, 203, 123, 191, 236, 5, 60, 206, 159, 109, 23, 19, 228, 166, 193, 3, 36, 175, 44, 14, 168, 217, 34, 151, 13, 156, 73, 105, 232, 214, 255, 233, 226, 142, 162, 145, 198, 63, 242, 77, 153, 37, 187, 188, 200, 87, 16, 192, 248, 149, 246, 125, 215, 10, 120, 155, 61, 218, 46, 38, 199, 75, 129, 6, 72, 93, 88, 28, 79, 177, 68, 45, 26, 55, 146, 210, 207, 171, 253, 209, 195, 27, 67, 33, 139, 126, 227, 154, 49, 74, 117, 119, 143, 174, 32, 127, 239, 41, 235, 250, 173, 20, 240, 53, 122, 179, 92, 76, 141, 150, 1], +[1, 13, 169, 141, 34, 185, 92, 168, 128, 122, 44, 58, 240, 36, 211, 173, 193, 196, 235, 228, 137, 239, 23, 42, 32, 159, 11, 143, 60, 9, 117, 236, 241, 49, 123, 57, 227, 124, 70, 139, 8, 104, 67, 100, 15, 195, 222, 59, 253, 205, 95, 207, 121, 31, 146, 99, 2, 26, 81, 25, 68, 113, 184, 79, 256, 244, 88, 116, 223, 72, 165, 89, 129, 135, 213, 199, 17, 221, 46, 84, 64, 61, 22, 29, 120, 18, 234, 215, 225, 98, 246, 114, 197, 248, 140, 21, 16, 208, 134, 200, 30, 133, 187, 118, 249, 153, 190, 157, 242, 62, 35, 198, 4, 52, 162, 50, 136, 226, 111, 158, 255, 231, 176, 232, 189, 144, 73, 178, 1, 13, 169, 141, 34, 185, 92, 168, 128, 122, 44, 58, 240, 36, 211, 173, 193, 196, 235, 228, 137, 239, 23, 42, 32, 159, 11, 143, 60, 9, 117, 236, 241, 49, 123, 57, 227, 124, 70, 139, 8, 104, 67, 100, 15, 195, 222, 59, 253, 205, 95, 207, 121, 31, 146, 99, 2, 26, 81, 25, 68, 113, 184, 79, 256, 244, 88, 116, 223, 72, 165, 89, 129, 135, 213, 199, 17, 221, 46, 84, 64, 61, 22, 29, 120, 18, 234, 215, 225, 98, 246, 114, 197, 248, 140, 21, 16, 208, 134, 200, 30, 133, 187, 118, 249, 153, 190, 157, 242, 62, 35, 198, 4, 52, 162, 50, 136, 226, 111, 158, 255, 231, 176, 232, 189, 144, 73, 178, 1], +[1, 14, 196, 174, 123, 180, 207, 71, 223, 38, 18, 252, 187, 48, 158, 156, 128, 250, 159, 170, 67, 167, 25, 93, 17, 238, 248, 131, 35, 233, 178, 179, 193, 132, 49, 172, 95, 45, 116, 82, 120, 138, 133, 63, 111, 12, 168, 39, 32, 191, 104, 171, 81, 106, 199, 216, 197, 188, 62, 97, 73, 251, 173, 109, 241, 33, 205, 43, 88, 204, 29, 149, 30, 163, 226, 80, 92, 3, 42, 74, 8, 112, 26, 107, 213, 155, 114, 54, 242, 47, 144, 217, 211, 127, 236, 220, 253, 201, 244, 75, 22, 51, 200, 230, 136, 105, 185, 20, 23, 65, 139, 147, 2, 28, 135, 91, 246, 103, 157, 142, 189, 76, 36, 247, 117, 96, 59, 55, 256, 243, 61, 83, 134, 77, 50, 186, 34, 219, 239, 5, 70, 209, 99, 101, 129, 7, 98, 87, 190, 90, 232, 164, 240, 19, 9, 126, 222, 24, 79, 78, 64, 125, 208, 85, 162, 212, 141, 175, 137, 119, 124, 194, 146, 245, 89, 218, 225, 66, 153, 86, 176, 151, 58, 41, 60, 69, 195, 160, 184, 6, 84, 148, 16, 224, 52, 214, 169, 53, 228, 108, 227, 94, 31, 177, 165, 254, 215, 183, 249, 145, 231, 150, 44, 102, 143, 203, 15, 210, 113, 40, 46, 130, 21, 37, 4, 56, 13, 182, 235, 206, 57, 27, 121, 152, 72, 237, 234, 192, 118, 110, 255, 229, 122, 166, 11, 154, 100, 115, 68, 181, 221, 10, 140, 161, 198, 202, 1], +[1, 15, 225, 34, 253, 197, 128, 121, 16, 240, 2, 30, 193, 68, 249, 137, 256, 242, 32, 223, 4, 60, 129, 136, 241, 17, 255, 227, 64, 189, 8, 120, 1, 15, 225, 34, 253, 197, 128, 121, 16, 240, 2, 30, 193, 68, 249, 137, 256, 242, 32, 223, 4, 60, 129, 136, 241, 17, 255, 227, 64, 189, 8, 120, 1, 15, 225, 34, 253, 197, 128, 121, 16, 240, 2, 30, 193, 68, 249, 137, 256, 242, 32, 223, 4, 60, 129, 136, 241, 17, 255, 227, 64, 189, 8, 120, 1, 15, 225, 34, 253, 197, 128, 121, 16, 240, 2, 30, 193, 68, 249, 137, 256, 242, 32, 223, 4, 60, 129, 136, 241, 17, 255, 227, 64, 189, 8, 120, 1, 15, 225, 34, 253, 197, 128, 121, 16, 240, 2, 30, 193, 68, 249, 137, 256, 242, 32, 223, 4, 60, 129, 136, 241, 17, 255, 227, 64, 189, 8, 120, 1, 15, 225, 34, 253, 197, 128, 121, 16, 240, 2, 30, 193, 68, 249, 137, 256, 242, 32, 223, 4, 60, 129, 136, 241, 17, 255, 227, 64, 189, 8, 120, 1, 15, 225, 34, 253, 197, 128, 121, 16, 240, 2, 30, 193, 68, 249, 137, 256, 242, 32, 223, 4, 60, 129, 136, 241, 17, 255, 227, 64, 189, 8, 120, 1, 15, 225, 34, 253, 197, 128, 121, 16, 240, 2, 30, 193, 68, 249, 137, 256, 242, 32, 223, 4, 60, 129, 136, 241, 17, 255, 227, 64, 189, 8, 120, 1], +[1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1, 16, 256, 241, 1], +[1, 17, 32, 30, 253, 189, 129, 137, 16, 15, 255, 223, 193, 197, 8, 136, 256, 240, 225, 227, 4, 68, 128, 120, 241, 242, 2, 34, 64, 60, 249, 121, 1, 17, 32, 30, 253, 189, 129, 137, 16, 15, 255, 223, 193, 197, 8, 136, 256, 240, 225, 227, 4, 68, 128, 120, 241, 242, 2, 34, 64, 60, 249, 121, 1, 17, 32, 30, 253, 189, 129, 137, 16, 15, 255, 223, 193, 197, 8, 136, 256, 240, 225, 227, 4, 68, 128, 120, 241, 242, 2, 34, 64, 60, 249, 121, 1, 17, 32, 30, 253, 189, 129, 137, 16, 15, 255, 223, 193, 197, 8, 136, 256, 240, 225, 227, 4, 68, 128, 120, 241, 242, 2, 34, 64, 60, 249, 121, 1, 17, 32, 30, 253, 189, 129, 137, 16, 15, 255, 223, 193, 197, 8, 136, 256, 240, 225, 227, 4, 68, 128, 120, 241, 242, 2, 34, 64, 60, 249, 121, 1, 17, 32, 30, 253, 189, 129, 137, 16, 15, 255, 223, 193, 197, 8, 136, 256, 240, 225, 227, 4, 68, 128, 120, 241, 242, 2, 34, 64, 60, 249, 121, 1, 17, 32, 30, 253, 189, 129, 137, 16, 15, 255, 223, 193, 197, 8, 136, 256, 240, 225, 227, 4, 68, 128, 120, 241, 242, 2, 34, 64, 60, 249, 121, 1, 17, 32, 30, 253, 189, 129, 137, 16, 15, 255, 223, 193, 197, 8, 136, 256, 240, 225, 227, 4, 68, 128, 120, 241, 242, 2, 34, 64, 60, 249, 121, 1], +[1, 18, 67, 178, 120, 104, 73, 29, 8, 144, 22, 139, 189, 61, 70, 232, 64, 124, 176, 84, 227, 231, 46, 57, 255, 221, 123, 158, 17, 49, 111, 199, 241, 226, 213, 236, 136, 135, 117, 50, 129, 9, 162, 89, 60, 52, 165, 143, 4, 72, 11, 198, 223, 159, 35, 116, 32, 62, 88, 42, 242, 244, 23, 157, 256, 239, 190, 79, 137, 153, 184, 228, 249, 113, 235, 118, 68, 196, 187, 25, 193, 133, 81, 173, 30, 26, 211, 200, 2, 36, 134, 99, 240, 208, 146, 58, 16, 31, 44, 21, 121, 122, 140, 207, 128, 248, 95, 168, 197, 205, 92, 114, 253, 185, 246, 59, 34, 98, 222, 141, 225, 195, 169, 215, 15, 13, 234, 100, 1, 18, 67, 178, 120, 104, 73, 29, 8, 144, 22, 139, 189, 61, 70, 232, 64, 124, 176, 84, 227, 231, 46, 57, 255, 221, 123, 158, 17, 49, 111, 199, 241, 226, 213, 236, 136, 135, 117, 50, 129, 9, 162, 89, 60, 52, 165, 143, 4, 72, 11, 198, 223, 159, 35, 116, 32, 62, 88, 42, 242, 244, 23, 157, 256, 239, 190, 79, 137, 153, 184, 228, 249, 113, 235, 118, 68, 196, 187, 25, 193, 133, 81, 173, 30, 26, 211, 200, 2, 36, 134, 99, 240, 208, 146, 58, 16, 31, 44, 21, 121, 122, 140, 207, 128, 248, 95, 168, 197, 205, 92, 114, 253, 185, 246, 59, 34, 98, 222, 141, 225, 195, 169, 215, 15, 13, 234, 100, 1], +[1, 19, 104, 177, 22, 161, 232, 39, 227, 201, 221, 87, 111, 53, 236, 115, 129, 138, 52, 217, 11, 209, 116, 148, 242, 229, 239, 172, 184, 155, 118, 186, 193, 69, 26, 237, 134, 233, 58, 74, 121, 243, 248, 86, 92, 206, 59, 93, 225, 163, 13, 247, 67, 245, 29, 37, 189, 250, 124, 43, 46, 103, 158, 175, 241, 210, 135, 252, 162, 251, 143, 147, 223, 125, 62, 150, 23, 180, 79, 216, 249, 105, 196, 126, 81, 254, 200, 202, 240, 191, 31, 75, 140, 90, 168, 108, 253, 181, 98, 63, 169, 127, 100, 101, 120, 224, 144, 166, 70, 45, 84, 54, 255, 219, 49, 160, 213, 192, 50, 179, 60, 112, 72, 83, 35, 151, 42, 27, 256, 238, 153, 80, 235, 96, 25, 218, 30, 56, 36, 170, 146, 204, 21, 142, 128, 119, 205, 40, 246, 48, 141, 109, 15, 28, 18, 85, 73, 102, 139, 71, 64, 188, 231, 20, 123, 24, 199, 183, 136, 14, 9, 171, 165, 51, 198, 164, 32, 94, 244, 10, 190, 12, 228, 220, 68, 7, 133, 214, 211, 154, 99, 82, 16, 47, 122, 5, 95, 6, 114, 110, 34, 132, 195, 107, 234, 77, 178, 41, 8, 152, 61, 131, 176, 3, 57, 55, 17, 66, 226, 182, 117, 167, 89, 149, 4, 76, 159, 194, 88, 130, 157, 156, 137, 33, 113, 91, 187, 212, 173, 203, 2, 38, 208, 97, 44, 65, 207, 78, 197, 145, 185, 174, 222, 106, 215, 230, 1], +[1, 20, 143, 33, 146, 93, 61, 192, 242, 214, 168, 19, 123, 147, 113, 204, 225, 131, 50, 229, 211, 108, 104, 24, 223, 91, 21, 163, 176, 179, 239, 154, 253, 177, 199, 125, 187, 142, 13, 3, 60, 172, 99, 181, 22, 183, 62, 212, 128, 247, 57, 112, 184, 82, 98, 161, 136, 150, 173, 119, 67, 55, 72, 155, 16, 63, 232, 14, 23, 203, 205, 245, 17, 83, 118, 47, 169, 39, 9, 180, 2, 40, 29, 66, 35, 186, 122, 127, 227, 171, 79, 38, 246, 37, 226, 151, 193, 5, 100, 201, 165, 216, 208, 48, 189, 182, 42, 69, 95, 101, 221, 51, 249, 97, 141, 250, 117, 27, 26, 6, 120, 87, 198, 105, 44, 109, 124, 167, 256, 237, 114, 224, 111, 164, 196, 65, 15, 43, 89, 238, 134, 110, 144, 53, 32, 126, 207, 28, 46, 149, 153, 233, 34, 166, 236, 94, 81, 78, 18, 103, 4, 80, 58, 132, 70, 115, 244, 254, 197, 85, 158, 76, 235, 74, 195, 45, 129, 10, 200, 145, 73, 175, 159, 96, 121, 107, 84, 138, 190, 202, 185, 102, 241, 194, 25, 243, 234, 54, 52, 12, 240, 174, 139, 210, 88, 218, 248, 77, 255, 217, 228, 191, 222, 71, 135, 130, 30, 86, 178, 219, 11, 220, 31, 106, 64, 252, 157, 56, 92, 41, 49, 209, 68, 75, 215, 188, 162, 156, 36, 206, 8, 160, 116, 7, 140, 230, 231, 251, 137, 170, 59, 152, 213, 148, 133, 90, 1], +[1, 21, 184, 9, 189, 114, 81, 159, 255, 215, 146, 239, 136, 29, 95, 196, 4, 84, 222, 36, 242, 199, 67, 122, 249, 89, 70, 185, 30, 116, 123, 13, 16, 79, 117, 144, 197, 25, 11, 231, 225, 99, 23, 226, 120, 207, 235, 52, 64, 59, 211, 62, 17, 100, 44, 153, 129, 139, 92, 133, 223, 57, 169, 208, 256, 236, 73, 248, 68, 143, 176, 98, 2, 42, 111, 18, 121, 228, 162, 61, 253, 173, 35, 221, 15, 58, 190, 135, 8, 168, 187, 72, 227, 141, 134, 244, 241, 178, 140, 113, 60, 232, 246, 26, 32, 158, 234, 31, 137, 50, 22, 205, 193, 198, 46, 195, 240, 157, 213, 104, 128, 118, 165, 124, 34, 200, 88, 49, 1, 21, 184, 9, 189, 114, 81, 159, 255, 215, 146, 239, 136, 29, 95, 196, 4, 84, 222, 36, 242, 199, 67, 122, 249, 89, 70, 185, 30, 116, 123, 13, 16, 79, 117, 144, 197, 25, 11, 231, 225, 99, 23, 226, 120, 207, 235, 52, 64, 59, 211, 62, 17, 100, 44, 153, 129, 139, 92, 133, 223, 57, 169, 208, 256, 236, 73, 248, 68, 143, 176, 98, 2, 42, 111, 18, 121, 228, 162, 61, 253, 173, 35, 221, 15, 58, 190, 135, 8, 168, 187, 72, 227, 141, 134, 244, 241, 178, 140, 113, 60, 232, 246, 26, 32, 158, 234, 31, 137, 50, 22, 205, 193, 198, 46, 195, 240, 157, 213, 104, 128, 118, 165, 124, 34, 200, 88, 49, 1], +[1, 22, 227, 111, 129, 11, 242, 184, 193, 134, 121, 92, 225, 67, 189, 46, 241, 162, 223, 23, 249, 81, 240, 140, 253, 169, 120, 70, 255, 213, 60, 35, 256, 235, 30, 146, 128, 246, 15, 73, 64, 123, 136, 165, 32, 190, 68, 211, 16, 95, 34, 234, 8, 176, 17, 117, 4, 88, 137, 187, 2, 44, 197, 222, 1, 22, 227, 111, 129, 11, 242, 184, 193, 134, 121, 92, 225, 67, 189, 46, 241, 162, 223, 23, 249, 81, 240, 140, 253, 169, 120, 70, 255, 213, 60, 35, 256, 235, 30, 146, 128, 246, 15, 73, 64, 123, 136, 165, 32, 190, 68, 211, 16, 95, 34, 234, 8, 176, 17, 117, 4, 88, 137, 187, 2, 44, 197, 222, 1, 22, 227, 111, 129, 11, 242, 184, 193, 134, 121, 92, 225, 67, 189, 46, 241, 162, 223, 23, 249, 81, 240, 140, 253, 169, 120, 70, 255, 213, 60, 35, 256, 235, 30, 146, 128, 246, 15, 73, 64, 123, 136, 165, 32, 190, 68, 211, 16, 95, 34, 234, 8, 176, 17, 117, 4, 88, 137, 187, 2, 44, 197, 222, 1, 22, 227, 111, 129, 11, 242, 184, 193, 134, 121, 92, 225, 67, 189, 46, 241, 162, 223, 23, 249, 81, 240, 140, 253, 169, 120, 70, 255, 213, 60, 35, 256, 235, 30, 146, 128, 246, 15, 73, 64, 123, 136, 165, 32, 190, 68, 211, 16, 95, 34, 234, 8, 176, 17, 117, 4, 88, 137, 187, 2, 44, 197, 222, 1], +[1, 23, 15, 88, 225, 35, 34, 11, 253, 165, 197, 162, 128, 117, 121, 213, 16, 111, 240, 123, 2, 46, 30, 176, 193, 70, 68, 22, 249, 73, 137, 67, 256, 234, 242, 169, 32, 222, 223, 246, 4, 92, 60, 95, 129, 140, 136, 44, 241, 146, 17, 134, 255, 211, 227, 81, 64, 187, 189, 235, 8, 184, 120, 190, 1, 23, 15, 88, 225, 35, 34, 11, 253, 165, 197, 162, 128, 117, 121, 213, 16, 111, 240, 123, 2, 46, 30, 176, 193, 70, 68, 22, 249, 73, 137, 67, 256, 234, 242, 169, 32, 222, 223, 246, 4, 92, 60, 95, 129, 140, 136, 44, 241, 146, 17, 134, 255, 211, 227, 81, 64, 187, 189, 235, 8, 184, 120, 190, 1, 23, 15, 88, 225, 35, 34, 11, 253, 165, 197, 162, 128, 117, 121, 213, 16, 111, 240, 123, 2, 46, 30, 176, 193, 70, 68, 22, 249, 73, 137, 67, 256, 234, 242, 169, 32, 222, 223, 246, 4, 92, 60, 95, 129, 140, 136, 44, 241, 146, 17, 134, 255, 211, 227, 81, 64, 187, 189, 235, 8, 184, 120, 190, 1, 23, 15, 88, 225, 35, 34, 11, 253, 165, 197, 162, 128, 117, 121, 213, 16, 111, 240, 123, 2, 46, 30, 176, 193, 70, 68, 22, 249, 73, 137, 67, 256, 234, 242, 169, 32, 222, 223, 246, 4, 92, 60, 95, 129, 140, 136, 44, 241, 146, 17, 134, 255, 211, 227, 81, 64, 187, 189, 235, 8, 184, 120, 190, 1], +[1, 24, 62, 203, 246, 250, 89, 80, 121, 77, 49, 148, 211, 181, 232, 171, 249, 65, 18, 175, 88, 56, 59, 131, 60, 155, 122, 101, 111, 94, 200, 174, 64, 251, 113, 142, 67, 66, 42, 237, 34, 45, 52, 220, 140, 19, 199, 150, 2, 48, 124, 149, 235, 243, 178, 160, 242, 154, 98, 39, 165, 105, 207, 85, 241, 130, 36, 93, 176, 112, 118, 5, 120, 53, 244, 202, 222, 188, 143, 91, 128, 245, 226, 27, 134, 132, 84, 217, 68, 90, 104, 183, 23, 38, 141, 43, 4, 96, 248, 41, 213, 229, 99, 63, 227, 51, 196, 78, 73, 210, 157, 170, 225, 3, 72, 186, 95, 224, 236, 10, 240, 106, 231, 147, 187, 119, 29, 182, 256, 233, 195, 54, 11, 7, 168, 177, 136, 180, 208, 109, 46, 76, 25, 86, 8, 192, 239, 82, 169, 201, 198, 126, 197, 102, 135, 156, 146, 163, 57, 83, 193, 6, 144, 115, 190, 191, 215, 20, 223, 212, 205, 37, 117, 238, 58, 107, 255, 209, 133, 108, 22, 14, 79, 97, 15, 103, 159, 218, 92, 152, 50, 172, 16, 127, 221, 164, 81, 145, 139, 252, 137, 204, 13, 55, 35, 69, 114, 166, 129, 12, 31, 230, 123, 125, 173, 40, 189, 167, 153, 74, 234, 219, 116, 214, 253, 161, 9, 216, 44, 28, 158, 194, 30, 206, 61, 179, 184, 47, 100, 87, 32, 254, 185, 71, 162, 33, 21, 247, 17, 151, 26, 110, 70, 138, 228, 75, 1], +[1, 25, 111, 205, 242, 139, 134, 9, 225, 228, 46, 122, 223, 178, 81, 226, 253, 157, 70, 208, 60, 215, 235, 221, 128, 116, 73, 26, 136, 59, 190, 124, 16, 143, 234, 196, 17, 168, 88, 144, 2, 50, 222, 153, 227, 21, 11, 18, 193, 199, 92, 244, 189, 99, 162, 195, 249, 57, 140, 159, 120, 173, 213, 185, 256, 232, 146, 52, 15, 118, 123, 248, 32, 29, 211, 135, 34, 79, 176, 31, 4, 100, 187, 49, 197, 42, 22, 36, 129, 141, 184, 231, 121, 198, 67, 133, 241, 114, 23, 61, 240, 89, 169, 113, 255, 207, 35, 104, 30, 236, 246, 239, 64, 58, 165, 13, 68, 158, 95, 62, 8, 200, 117, 98, 137, 84, 44, 72, 1, 25, 111, 205, 242, 139, 134, 9, 225, 228, 46, 122, 223, 178, 81, 226, 253, 157, 70, 208, 60, 215, 235, 221, 128, 116, 73, 26, 136, 59, 190, 124, 16, 143, 234, 196, 17, 168, 88, 144, 2, 50, 222, 153, 227, 21, 11, 18, 193, 199, 92, 244, 189, 99, 162, 195, 249, 57, 140, 159, 120, 173, 213, 185, 256, 232, 146, 52, 15, 118, 123, 248, 32, 29, 211, 135, 34, 79, 176, 31, 4, 100, 187, 49, 197, 42, 22, 36, 129, 141, 184, 231, 121, 198, 67, 133, 241, 114, 23, 61, 240, 89, 169, 113, 255, 207, 35, 104, 30, 236, 246, 239, 64, 58, 165, 13, 68, 158, 95, 62, 8, 200, 117, 98, 137, 84, 44, 72, 1], +[1, 26, 162, 100, 30, 9, 234, 173, 129, 13, 81, 50, 15, 133, 117, 215, 193, 135, 169, 25, 136, 195, 187, 236, 225, 196, 213, 141, 68, 226, 222, 118, 241, 98, 235, 199, 34, 113, 111, 59, 249, 49, 246, 228, 17, 185, 184, 158, 253, 153, 123, 114, 137, 221, 92, 79, 255, 205, 190, 57, 197, 239, 46, 168, 256, 231, 95, 157, 227, 248, 23, 84, 128, 244, 176, 207, 242, 124, 140, 42, 64, 122, 88, 232, 121, 62, 70, 21, 32, 61, 44, 116, 189, 31, 35, 139, 16, 159, 22, 58, 223, 144, 146, 198, 8, 208, 11, 29, 240, 72, 73, 99, 4, 104, 134, 143, 120, 36, 165, 178, 2, 52, 67, 200, 60, 18, 211, 89, 1, 26, 162, 100, 30, 9, 234, 173, 129, 13, 81, 50, 15, 133, 117, 215, 193, 135, 169, 25, 136, 195, 187, 236, 225, 196, 213, 141, 68, 226, 222, 118, 241, 98, 235, 199, 34, 113, 111, 59, 249, 49, 246, 228, 17, 185, 184, 158, 253, 153, 123, 114, 137, 221, 92, 79, 255, 205, 190, 57, 197, 239, 46, 168, 256, 231, 95, 157, 227, 248, 23, 84, 128, 244, 176, 207, 242, 124, 140, 42, 64, 122, 88, 232, 121, 62, 70, 21, 32, 61, 44, 116, 189, 31, 35, 139, 16, 159, 22, 58, 223, 144, 146, 198, 8, 208, 11, 29, 240, 72, 73, 99, 4, 104, 134, 143, 120, 36, 165, 178, 2, 52, 67, 200, 60, 18, 211, 89, 1], +[1, 27, 215, 151, 222, 83, 185, 112, 197, 179, 207, 192, 44, 160, 208, 219, 2, 54, 173, 45, 187, 166, 113, 224, 137, 101, 157, 127, 88, 63, 159, 181, 4, 108, 89, 90, 117, 75, 226, 191, 17, 202, 57, 254, 176, 126, 61, 105, 8, 216, 178, 180, 234, 150, 195, 125, 34, 147, 114, 251, 95, 252, 122, 210, 16, 175, 99, 103, 211, 43, 133, 250, 68, 37, 228, 245, 190, 247, 244, 163, 32, 93, 198, 206, 165, 86, 9, 243, 136, 74, 199, 233, 123, 237, 231, 69, 64, 186, 139, 155, 73, 172, 18, 229, 15, 148, 141, 209, 246, 217, 205, 138, 128, 115, 21, 53, 146, 87, 36, 201, 30, 39, 25, 161, 235, 177, 153, 19, 256, 230, 42, 106, 35, 174, 72, 145, 60, 78, 50, 65, 213, 97, 49, 38, 255, 203, 84, 212, 70, 91, 144, 33, 120, 156, 100, 130, 169, 194, 98, 76, 253, 149, 168, 167, 140, 182, 31, 66, 240, 55, 200, 3, 81, 131, 196, 152, 249, 41, 79, 77, 23, 107, 62, 132, 223, 110, 143, 6, 162, 5, 135, 47, 241, 82, 158, 154, 46, 214, 124, 7, 189, 220, 29, 12, 67, 10, 13, 94, 225, 164, 59, 51, 92, 171, 248, 14, 121, 183, 58, 24, 134, 20, 26, 188, 193, 71, 118, 102, 184, 85, 239, 28, 242, 109, 116, 48, 11, 40, 52, 119, 129, 142, 236, 204, 111, 170, 221, 56, 227, 218, 232, 96, 22, 80, 104, 238, 1], +[1, 28, 13, 107, 169, 106, 141, 93, 34, 181, 185, 40, 92, 6, 168, 78, 128, 243, 122, 75, 44, 204, 58, 82, 240, 38, 36, 237, 211, 254, 173, 218, 193, 7, 196, 91, 235, 155, 228, 216, 137, 238, 239, 10, 23, 130, 42, 148, 32, 125, 159, 83, 11, 51, 143, 149, 60, 138, 9, 252, 117, 192, 236, 183, 241, 66, 49, 87, 123, 103, 57, 54, 227, 188, 124, 131, 70, 161, 139, 37, 8, 224, 104, 85, 67, 77, 100, 230, 15, 163, 195, 63, 222, 48, 59, 110, 253, 145, 205, 86, 95, 90, 207, 142, 121, 47, 31, 97, 146, 233, 99, 202, 2, 56, 26, 214, 81, 212, 25, 186, 68, 105, 113, 80, 184, 12, 79, 156, 256, 229, 244, 150, 88, 151, 116, 164, 223, 76, 72, 217, 165, 251, 89, 179, 129, 14, 135, 182, 213, 53, 199, 175, 17, 219, 221, 20, 46, 3, 84, 39, 64, 250, 61, 166, 22, 102, 29, 41, 120, 19, 18, 247, 234, 127, 215, 109, 225, 132, 98, 174, 246, 206, 114, 108, 197, 119, 248, 5, 140, 65, 21, 74, 16, 191, 208, 170, 134, 154, 200, 203, 30, 69, 133, 126, 187, 96, 118, 220, 249, 33, 153, 172, 190, 180, 157, 27, 242, 94, 62, 194, 35, 209, 198, 147, 4, 112, 52, 171, 162, 167, 50, 115, 136, 210, 226, 160, 111, 24, 158, 55, 255, 201, 231, 43, 176, 45, 232, 71, 189, 152, 144, 177, 73, 245, 178, 101, 1], +[1, 29, 70, 231, 17, 236, 162, 72, 32, 157, 184, 196, 30, 99, 44, 248, 253, 141, 234, 104, 189, 84, 123, 226, 129, 143, 35, 244, 137, 118, 81, 36, 16, 207, 92, 98, 15, 178, 22, 124, 255, 199, 117, 52, 223, 42, 190, 113, 193, 200, 146, 122, 197, 59, 169, 18, 8, 232, 46, 49, 136, 89, 11, 62, 256, 228, 187, 26, 240, 21, 95, 185, 225, 100, 73, 61, 227, 158, 213, 9, 4, 116, 23, 153, 68, 173, 134, 31, 128, 114, 222, 13, 120, 139, 176, 221, 241, 50, 165, 159, 242, 79, 235, 133, 2, 58, 140, 205, 34, 215, 67, 144, 64, 57, 111, 135, 60, 198, 88, 239, 249, 25, 211, 208, 121, 168, 246, 195, 1, 29, 70, 231, 17, 236, 162, 72, 32, 157, 184, 196, 30, 99, 44, 248, 253, 141, 234, 104, 189, 84, 123, 226, 129, 143, 35, 244, 137, 118, 81, 36, 16, 207, 92, 98, 15, 178, 22, 124, 255, 199, 117, 52, 223, 42, 190, 113, 193, 200, 146, 122, 197, 59, 169, 18, 8, 232, 46, 49, 136, 89, 11, 62, 256, 228, 187, 26, 240, 21, 95, 185, 225, 100, 73, 61, 227, 158, 213, 9, 4, 116, 23, 153, 68, 173, 134, 31, 128, 114, 222, 13, 120, 139, 176, 221, 241, 50, 165, 159, 242, 79, 235, 133, 2, 58, 140, 205, 34, 215, 67, 144, 64, 57, 111, 135, 60, 198, 88, 239, 249, 25, 211, 208, 121, 168, 246, 195, 1], +[1, 30, 129, 15, 193, 136, 225, 68, 241, 34, 249, 17, 253, 137, 255, 197, 256, 227, 128, 242, 64, 121, 32, 189, 16, 223, 8, 240, 4, 120, 2, 60, 1, 30, 129, 15, 193, 136, 225, 68, 241, 34, 249, 17, 253, 137, 255, 197, 256, 227, 128, 242, 64, 121, 32, 189, 16, 223, 8, 240, 4, 120, 2, 60, 1, 30, 129, 15, 193, 136, 225, 68, 241, 34, 249, 17, 253, 137, 255, 197, 256, 227, 128, 242, 64, 121, 32, 189, 16, 223, 8, 240, 4, 120, 2, 60, 1, 30, 129, 15, 193, 136, 225, 68, 241, 34, 249, 17, 253, 137, 255, 197, 256, 227, 128, 242, 64, 121, 32, 189, 16, 223, 8, 240, 4, 120, 2, 60, 1, 30, 129, 15, 193, 136, 225, 68, 241, 34, 249, 17, 253, 137, 255, 197, 256, 227, 128, 242, 64, 121, 32, 189, 16, 223, 8, 240, 4, 120, 2, 60, 1, 30, 129, 15, 193, 136, 225, 68, 241, 34, 249, 17, 253, 137, 255, 197, 256, 227, 128, 242, 64, 121, 32, 189, 16, 223, 8, 240, 4, 120, 2, 60, 1, 30, 129, 15, 193, 136, 225, 68, 241, 34, 249, 17, 253, 137, 255, 197, 256, 227, 128, 242, 64, 121, 32, 189, 16, 223, 8, 240, 4, 120, 2, 60, 1, 30, 129, 15, 193, 136, 225, 68, 241, 34, 249, 17, 253, 137, 255, 197, 256, 227, 128, 242, 64, 121, 32, 189, 16, 223, 8, 240, 4, 120, 2, 60, 1], +[1, 31, 190, 236, 120, 122, 184, 50, 8, 248, 235, 89, 189, 205, 187, 143, 64, 185, 81, 198, 227, 98, 211, 116, 255, 195, 134, 42, 17, 13, 146, 157, 241, 18, 44, 79, 136, 104, 140, 228, 129, 144, 95, 118, 60, 61, 92, 25, 4, 124, 246, 173, 223, 231, 222, 200, 32, 221, 169, 99, 242, 49, 234, 58, 256, 226, 67, 21, 137, 135, 73, 207, 249, 9, 22, 168, 68, 52, 70, 114, 193, 72, 176, 59, 30, 159, 46, 141, 2, 62, 123, 215, 240, 244, 111, 100, 16, 239, 213, 178, 121, 153, 117, 29, 128, 113, 162, 139, 197, 196, 165, 232, 253, 133, 11, 84, 34, 26, 35, 57, 225, 36, 88, 158, 15, 208, 23, 199, 1, 31, 190, 236, 120, 122, 184, 50, 8, 248, 235, 89, 189, 205, 187, 143, 64, 185, 81, 198, 227, 98, 211, 116, 255, 195, 134, 42, 17, 13, 146, 157, 241, 18, 44, 79, 136, 104, 140, 228, 129, 144, 95, 118, 60, 61, 92, 25, 4, 124, 246, 173, 223, 231, 222, 200, 32, 221, 169, 99, 242, 49, 234, 58, 256, 226, 67, 21, 137, 135, 73, 207, 249, 9, 22, 168, 68, 52, 70, 114, 193, 72, 176, 59, 30, 159, 46, 141, 2, 62, 123, 215, 240, 244, 111, 100, 16, 239, 213, 178, 121, 153, 117, 29, 128, 113, 162, 139, 197, 196, 165, 232, 253, 133, 11, 84, 34, 26, 35, 57, 225, 36, 88, 158, 15, 208, 23, 199, 1], +[1, 32, 253, 129, 16, 255, 193, 8, 256, 225, 4, 128, 241, 2, 64, 249, 1, 32, 253, 129, 16, 255, 193, 8, 256, 225, 4, 128, 241, 2, 64, 249, 1, 32, 253, 129, 16, 255, 193, 8, 256, 225, 4, 128, 241, 2, 64, 249, 1, 32, 253, 129, 16, 255, 193, 8, 256, 225, 4, 128, 241, 2, 64, 249, 1, 32, 253, 129, 16, 255, 193, 8, 256, 225, 4, 128, 241, 2, 64, 249, 1, 32, 253, 129, 16, 255, 193, 8, 256, 225, 4, 128, 241, 2, 64, 249, 1, 32, 253, 129, 16, 255, 193, 8, 256, 225, 4, 128, 241, 2, 64, 249, 1, 32, 253, 129, 16, 255, 193, 8, 256, 225, 4, 128, 241, 2, 64, 249, 1, 32, 253, 129, 16, 255, 193, 8, 256, 225, 4, 128, 241, 2, 64, 249, 1, 32, 253, 129, 16, 255, 193, 8, 256, 225, 4, 128, 241, 2, 64, 249, 1, 32, 253, 129, 16, 255, 193, 8, 256, 225, 4, 128, 241, 2, 64, 249, 1, 32, 253, 129, 16, 255, 193, 8, 256, 225, 4, 128, 241, 2, 64, 249, 1, 32, 253, 129, 16, 255, 193, 8, 256, 225, 4, 128, 241, 2, 64, 249, 1, 32, 253, 129, 16, 255, 193, 8, 256, 225, 4, 128, 241, 2, 64, 249, 1, 32, 253, 129, 16, 255, 193, 8, 256, 225, 4, 128, 241, 2, 64, 249, 1, 32, 253, 129, 16, 255, 193, 8, 256, 225, 4, 128, 241, 2, 64, 249, 1], +[1, 33, 61, 214, 123, 204, 50, 108, 223, 163, 239, 177, 187, 3, 99, 183, 128, 112, 98, 150, 67, 155, 232, 203, 17, 47, 9, 40, 35, 127, 79, 37, 193, 201, 208, 182, 95, 51, 141, 27, 120, 105, 124, 237, 111, 65, 89, 110, 32, 28, 153, 166, 81, 103, 58, 115, 197, 76, 195, 10, 73, 96, 84, 202, 241, 243, 52, 174, 88, 77, 228, 71, 30, 219, 31, 252, 92, 209, 215, 156, 8, 7, 231, 170, 213, 90, 143, 93, 242, 19, 113, 131, 211, 24, 21, 179, 253, 125, 13, 172, 22, 212, 57, 82, 136, 119, 72, 63, 23, 245, 118, 39, 2, 66, 122, 171, 246, 151, 100, 216, 189, 69, 221, 97, 117, 6, 198, 109, 256, 224, 196, 43, 134, 53, 207, 149, 34, 94, 18, 80, 70, 254, 158, 74, 129, 145, 159, 107, 190, 102, 25, 54, 240, 210, 248, 217, 222, 130, 178, 220, 64, 56, 49, 75, 162, 206, 116, 230, 137, 152, 133, 20, 146, 192, 168, 147, 225, 229, 104, 91, 176, 154, 199, 142, 60, 181, 62, 247, 184, 161, 173, 55, 16, 14, 205, 83, 169, 180, 29, 186, 227, 38, 226, 5, 165, 48, 42, 101, 249, 250, 26, 87, 44, 167, 114, 164, 15, 238, 144, 126, 46, 233, 236, 78, 4, 132, 244, 85, 235, 45, 200, 175, 121, 138, 185, 194, 234, 12, 139, 218, 255, 191, 135, 86, 11, 106, 157, 41, 68, 188, 36, 160, 140, 251, 59, 148, 1], +[1, 34, 128, 240, 193, 137, 32, 60, 241, 227, 8, 15, 253, 121, 2, 68, 256, 223, 129, 17, 64, 120, 225, 197, 16, 30, 249, 242, 4, 136, 255, 189, 1, 34, 128, 240, 193, 137, 32, 60, 241, 227, 8, 15, 253, 121, 2, 68, 256, 223, 129, 17, 64, 120, 225, 197, 16, 30, 249, 242, 4, 136, 255, 189, 1, 34, 128, 240, 193, 137, 32, 60, 241, 227, 8, 15, 253, 121, 2, 68, 256, 223, 129, 17, 64, 120, 225, 197, 16, 30, 249, 242, 4, 136, 255, 189, 1, 34, 128, 240, 193, 137, 32, 60, 241, 227, 8, 15, 253, 121, 2, 68, 256, 223, 129, 17, 64, 120, 225, 197, 16, 30, 249, 242, 4, 136, 255, 189, 1, 34, 128, 240, 193, 137, 32, 60, 241, 227, 8, 15, 253, 121, 2, 68, 256, 223, 129, 17, 64, 120, 225, 197, 16, 30, 249, 242, 4, 136, 255, 189, 1, 34, 128, 240, 193, 137, 32, 60, 241, 227, 8, 15, 253, 121, 2, 68, 256, 223, 129, 17, 64, 120, 225, 197, 16, 30, 249, 242, 4, 136, 255, 189, 1, 34, 128, 240, 193, 137, 32, 60, 241, 227, 8, 15, 253, 121, 2, 68, 256, 223, 129, 17, 64, 120, 225, 197, 16, 30, 249, 242, 4, 136, 255, 189, 1, 34, 128, 240, 193, 137, 32, 60, 241, 227, 8, 15, 253, 121, 2, 68, 256, 223, 129, 17, 64, 120, 225, 197, 16, 30, 249, 242, 4, 136, 255, 189, 1], +[1, 35, 197, 213, 2, 70, 137, 169, 4, 140, 17, 81, 8, 23, 34, 162, 16, 46, 68, 67, 32, 92, 136, 134, 64, 184, 15, 11, 128, 111, 30, 22, 256, 222, 60, 44, 255, 187, 120, 88, 253, 117, 240, 176, 249, 234, 223, 95, 241, 211, 189, 190, 225, 165, 121, 123, 193, 73, 242, 246, 129, 146, 227, 235, 1, 35, 197, 213, 2, 70, 137, 169, 4, 140, 17, 81, 8, 23, 34, 162, 16, 46, 68, 67, 32, 92, 136, 134, 64, 184, 15, 11, 128, 111, 30, 22, 256, 222, 60, 44, 255, 187, 120, 88, 253, 117, 240, 176, 249, 234, 223, 95, 241, 211, 189, 190, 225, 165, 121, 123, 193, 73, 242, 246, 129, 146, 227, 235, 1, 35, 197, 213, 2, 70, 137, 169, 4, 140, 17, 81, 8, 23, 34, 162, 16, 46, 68, 67, 32, 92, 136, 134, 64, 184, 15, 11, 128, 111, 30, 22, 256, 222, 60, 44, 255, 187, 120, 88, 253, 117, 240, 176, 249, 234, 223, 95, 241, 211, 189, 190, 225, 165, 121, 123, 193, 73, 242, 246, 129, 146, 227, 235, 1, 35, 197, 213, 2, 70, 137, 169, 4, 140, 17, 81, 8, 23, 34, 162, 16, 46, 68, 67, 32, 92, 136, 134, 64, 184, 15, 11, 128, 111, 30, 22, 256, 222, 60, 44, 255, 187, 120, 88, 253, 117, 240, 176, 249, 234, 223, 95, 241, 211, 189, 190, 225, 165, 121, 123, 193, 73, 242, 246, 129, 146, 227, 235, 1], +[1, 36, 11, 139, 121, 244, 46, 114, 249, 226, 169, 173, 60, 104, 146, 116, 64, 248, 190, 158, 34, 196, 117, 100, 2, 72, 22, 21, 242, 231, 92, 228, 241, 195, 81, 89, 120, 208, 35, 232, 128, 239, 123, 59, 68, 135, 234, 200, 4, 144, 44, 42, 227, 205, 184, 199, 225, 133, 162, 178, 240, 159, 70, 207, 256, 221, 246, 118, 136, 13, 211, 143, 8, 31, 88, 84, 197, 153, 111, 141, 193, 9, 67, 99, 223, 61, 140, 157, 255, 185, 235, 236, 15, 26, 165, 29, 16, 62, 176, 168, 137, 49, 222, 25, 129, 18, 134, 198, 189, 122, 23, 57, 253, 113, 213, 215, 30, 52, 73, 58, 32, 124, 95, 79, 17, 98, 187, 50, 1, 36, 11, 139, 121, 244, 46, 114, 249, 226, 169, 173, 60, 104, 146, 116, 64, 248, 190, 158, 34, 196, 117, 100, 2, 72, 22, 21, 242, 231, 92, 228, 241, 195, 81, 89, 120, 208, 35, 232, 128, 239, 123, 59, 68, 135, 234, 200, 4, 144, 44, 42, 227, 205, 184, 199, 225, 133, 162, 178, 240, 159, 70, 207, 256, 221, 246, 118, 136, 13, 211, 143, 8, 31, 88, 84, 197, 153, 111, 141, 193, 9, 67, 99, 223, 61, 140, 157, 255, 185, 235, 236, 15, 26, 165, 29, 16, 62, 176, 168, 137, 49, 222, 25, 129, 18, 134, 198, 189, 122, 23, 57, 253, 113, 213, 215, 30, 52, 73, 58, 32, 124, 95, 79, 17, 98, 187, 50, 1], +[1, 37, 84, 24, 117, 217, 62, 238, 68, 203, 58, 90, 246, 107, 104, 250, 255, 183, 89, 209, 23, 80, 133, 38, 121, 108, 141, 77, 22, 43, 49, 14, 4, 148, 79, 96, 211, 97, 248, 181, 15, 41, 232, 103, 213, 171, 159, 229, 249, 218, 99, 65, 92, 63, 18, 152, 227, 175, 50, 51, 88, 172, 196, 56, 16, 78, 59, 127, 73, 131, 221, 210, 60, 164, 157, 155, 81, 170, 122, 145, 225, 101, 139, 3, 111, 252, 72, 94, 137, 186, 200, 204, 95, 174, 13, 224, 64, 55, 236, 251, 35, 10, 113, 69, 240, 142, 114, 106, 67, 166, 231, 66, 129, 147, 42, 12, 187, 237, 31, 119, 34, 230, 29, 45, 123, 182, 52, 125, 256, 220, 173, 233, 140, 40, 195, 19, 189, 54, 199, 167, 11, 150, 153, 7, 2, 74, 168, 48, 234, 177, 124, 219, 136, 149, 116, 180, 235, 214, 208, 243, 253, 109, 178, 161, 46, 160, 9, 76, 242, 216, 25, 154, 44, 86, 98, 28, 8, 39, 158, 192, 165, 194, 239, 105, 30, 82, 207, 206, 169, 85, 61, 201, 241, 179, 198, 130, 184, 126, 36, 47, 197, 93, 100, 102, 176, 87, 135, 112, 32, 156, 118, 254, 146, 5, 185, 163, 120, 71, 57, 53, 162, 83, 244, 33, 193, 202, 21, 6, 222, 247, 144, 188, 17, 115, 143, 151, 190, 91, 26, 191, 128, 110, 215, 245, 70, 20, 226, 138, 223, 27, 228, 212, 134, 75, 205, 132, 1], +[1, 38, 159, 131, 95, 12, 199, 109, 30, 112, 144, 75, 23, 103, 59, 186, 129, 19, 208, 194, 176, 6, 228, 183, 15, 56, 72, 166, 140, 180, 158, 93, 193, 138, 104, 97, 88, 3, 114, 220, 136, 28, 36, 83, 70, 90, 79, 175, 225, 69, 52, 177, 44, 130, 57, 110, 68, 14, 18, 170, 35, 45, 168, 216, 241, 163, 26, 217, 22, 65, 157, 55, 34, 7, 9, 85, 146, 151, 84, 108, 249, 210, 13, 237, 11, 161, 207, 156, 17, 132, 133, 171, 73, 204, 42, 54, 253, 105, 135, 247, 134, 209, 232, 78, 137, 66, 195, 214, 165, 102, 21, 27, 255, 181, 196, 252, 67, 233, 116, 39, 197, 33, 226, 107, 211, 51, 139, 142, 256, 219, 98, 126, 162, 245, 58, 148, 227, 145, 113, 182, 234, 154, 198, 71, 128, 238, 49, 63, 81, 251, 29, 74, 242, 201, 185, 91, 117, 77, 99, 164, 64, 119, 153, 160, 169, 254, 143, 37, 121, 229, 221, 174, 187, 167, 178, 82, 32, 188, 205, 80, 213, 127, 200, 147, 189, 243, 239, 87, 222, 212, 89, 41, 16, 94, 231, 40, 235, 192, 100, 202, 223, 250, 248, 172, 111, 106, 173, 149, 8, 47, 244, 20, 246, 96, 50, 101, 240, 125, 124, 86, 184, 53, 215, 203, 4, 152, 122, 10, 123, 48, 25, 179, 120, 191, 62, 43, 92, 155, 236, 230, 2, 76, 61, 5, 190, 24, 141, 218, 60, 224, 31, 150, 46, 206, 118, 115, 1], +[1, 39, 236, 209, 184, 237, 248, 163, 189, 175, 143, 180, 81, 75, 98, 224, 255, 179, 42, 96, 146, 40, 18, 188, 136, 164, 228, 154, 95, 107, 61, 66, 4, 156, 173, 65, 222, 177, 221, 138, 242, 186, 58, 206, 67, 43, 135, 125, 249, 202, 168, 127, 70, 160, 72, 238, 30, 142, 141, 102, 123, 171, 244, 7, 16, 110, 178, 3, 117, 194, 113, 38, 197, 230, 232, 53, 11, 172, 26, 243, 225, 37, 158, 251, 23, 126, 31, 181, 120, 54, 50, 151, 235, 170, 205, 28, 64, 183, 198, 12, 211, 5, 195, 152, 17, 149, 157, 212, 44, 174, 104, 201, 129, 148, 118, 233, 92, 247, 124, 210, 223, 216, 200, 90, 169, 166, 49, 112, 256, 218, 21, 48, 73, 20, 9, 94, 68, 82, 114, 77, 176, 182, 159, 33, 2, 78, 215, 161, 111, 217, 239, 69, 121, 93, 29, 103, 162, 150, 196, 191, 253, 101, 84, 192, 35, 80, 36, 119, 15, 71, 199, 51, 190, 214, 122, 132, 8, 55, 89, 130, 187, 97, 185, 19, 227, 115, 116, 155, 134, 86, 13, 250, 241, 147, 79, 254, 140, 63, 144, 219, 60, 27, 25, 204, 246, 85, 231, 14, 32, 220, 99, 6, 234, 131, 226, 76, 137, 203, 207, 106, 22, 87, 52, 229, 193, 74, 59, 245, 46, 252, 62, 105, 240, 108, 100, 45, 213, 83, 153, 56, 128, 109, 139, 24, 165, 10, 133, 47, 34, 41, 57, 167, 88, 91, 208, 145, 1], +[1, 40, 58, 7, 23, 149, 49, 161, 15, 86, 99, 105, 88, 179, 221, 102, 225, 5, 200, 33, 35, 115, 231, 245, 34, 75, 173, 238, 11, 183, 124, 77, 253, 97, 25, 229, 165, 175, 61, 127, 197, 170, 118, 94, 162, 55, 144, 106, 128, 237, 228, 125, 117, 54, 104, 48, 121, 214, 79, 76, 213, 39, 18, 206, 16, 126, 157, 112, 111, 71, 13, 6, 240, 91, 42, 138, 123, 37, 195, 90, 2, 80, 116, 14, 46, 41, 98, 65, 30, 172, 198, 210, 176, 101, 185, 204, 193, 10, 143, 66, 70, 230, 205, 233, 68, 150, 89, 219, 22, 109, 248, 154, 249, 194, 50, 201, 73, 93, 122, 254, 137, 83, 236, 188, 67, 110, 31, 212, 256, 217, 199, 250, 234, 108, 208, 96, 242, 171, 158, 152, 169, 78, 36, 155, 32, 252, 57, 224, 222, 142, 26, 12, 223, 182, 84, 19, 246, 74, 133, 180, 4, 160, 232, 28, 92, 82, 196, 130, 60, 87, 139, 163, 95, 202, 113, 151, 129, 20, 29, 132, 140, 203, 153, 209, 136, 43, 178, 181, 44, 218, 239, 51, 241, 131, 100, 145, 146, 186, 244, 251, 17, 166, 215, 119, 134, 220, 62, 167, 255, 177, 141, 243, 211, 216, 159, 192, 227, 85, 59, 47, 81, 156, 72, 53, 64, 247, 114, 191, 187, 27, 52, 24, 189, 107, 168, 38, 235, 148, 9, 103, 8, 63, 207, 56, 184, 164, 135, 3, 120, 174, 21, 69, 190, 147, 226, 45, 1], +[1, 41, 139, 45, 46, 87, 226, 14, 60, 147, 116, 130, 190, 80, 196, 69, 2, 82, 21, 90, 92, 174, 195, 28, 120, 37, 232, 3, 123, 160, 135, 138, 4, 164, 42, 180, 184, 91, 133, 56, 240, 74, 207, 6, 246, 63, 13, 19, 8, 71, 84, 103, 111, 182, 9, 112, 223, 148, 157, 12, 235, 126, 26, 38, 16, 142, 168, 206, 222, 107, 18, 224, 189, 39, 57, 24, 213, 252, 52, 76, 32, 27, 79, 155, 187, 214, 36, 191, 121, 78, 114, 48, 169, 247, 104, 152, 64, 54, 158, 53, 117, 171, 72, 125, 242, 156, 228, 96, 81, 237, 208, 47, 128, 108, 59, 106, 234, 85, 144, 250, 227, 55, 199, 192, 162, 217, 159, 94, 256, 216, 118, 212, 211, 170, 31, 243, 197, 110, 141, 127, 67, 177, 61, 188, 255, 175, 236, 167, 165, 83, 62, 229, 137, 220, 25, 254, 134, 97, 122, 119, 253, 93, 215, 77, 73, 166, 124, 201, 17, 183, 50, 251, 11, 194, 244, 238, 249, 186, 173, 154, 146, 75, 248, 145, 34, 109, 100, 245, 22, 131, 231, 219, 241, 115, 89, 51, 35, 150, 239, 33, 68, 218, 200, 233, 44, 5, 205, 181, 225, 230, 178, 102, 70, 43, 221, 66, 136, 179, 143, 209, 88, 10, 153, 105, 193, 203, 99, 204, 140, 86, 185, 132, 15, 101, 29, 161, 176, 20, 49, 210, 129, 149, 198, 151, 23, 172, 113, 7, 30, 202, 58, 65, 95, 40, 98, 163, 1], +[1, 42, 222, 72, 197, 50, 44, 49, 2, 84, 187, 144, 137, 100, 88, 98, 4, 168, 117, 31, 17, 200, 176, 196, 8, 79, 234, 62, 34, 143, 95, 135, 16, 158, 211, 124, 68, 29, 190, 13, 32, 59, 165, 248, 136, 58, 123, 26, 64, 118, 73, 239, 15, 116, 246, 52, 128, 236, 146, 221, 30, 232, 235, 104, 256, 215, 35, 185, 60, 207, 213, 208, 255, 173, 70, 113, 120, 157, 169, 159, 253, 89, 140, 226, 240, 57, 81, 61, 249, 178, 23, 195, 223, 114, 162, 122, 241, 99, 46, 133, 189, 228, 67, 244, 225, 198, 92, 9, 121, 199, 134, 231, 193, 139, 184, 18, 242, 141, 11, 205, 129, 21, 111, 36, 227, 25, 22, 153, 1, 42, 222, 72, 197, 50, 44, 49, 2, 84, 187, 144, 137, 100, 88, 98, 4, 168, 117, 31, 17, 200, 176, 196, 8, 79, 234, 62, 34, 143, 95, 135, 16, 158, 211, 124, 68, 29, 190, 13, 32, 59, 165, 248, 136, 58, 123, 26, 64, 118, 73, 239, 15, 116, 246, 52, 128, 236, 146, 221, 30, 232, 235, 104, 256, 215, 35, 185, 60, 207, 213, 208, 255, 173, 70, 113, 120, 157, 169, 159, 253, 89, 140, 226, 240, 57, 81, 61, 249, 178, 23, 195, 223, 114, 162, 122, 241, 99, 46, 133, 189, 228, 67, 244, 225, 198, 92, 9, 121, 199, 134, 231, 193, 139, 184, 18, 242, 141, 11, 205, 129, 21, 111, 36, 227, 25, 22, 153, 1], +[1, 43, 50, 94, 187, 74, 98, 102, 17, 217, 79, 56, 95, 230, 124, 192, 32, 91, 58, 181, 73, 55, 52, 180, 30, 5, 215, 250, 213, 164, 113, 233, 253, 85, 57, 138, 23, 218, 122, 106, 189, 160, 198, 33, 134, 108, 18, 3, 129, 150, 25, 47, 222, 37, 49, 51, 137, 237, 168, 28, 176, 115, 62, 96, 16, 174, 29, 219, 165, 156, 26, 90, 15, 131, 236, 125, 235, 82, 185, 245, 255, 171, 157, 69, 140, 109, 61, 53, 223, 80, 99, 145, 67, 54, 9, 130, 193, 75, 141, 152, 111, 147, 153, 154, 197, 247, 84, 14, 88, 186, 31, 48, 8, 87, 143, 238, 211, 78, 13, 45, 136, 194, 118, 191, 246, 41, 221, 251, 256, 214, 207, 163, 70, 183, 159, 155, 240, 40, 178, 201, 162, 27, 133, 65, 225, 166, 199, 76, 184, 202, 205, 77, 227, 252, 42, 7, 44, 93, 144, 24, 4, 172, 200, 119, 234, 39, 135, 151, 68, 97, 59, 224, 123, 149, 239, 254, 128, 107, 232, 210, 35, 220, 208, 206, 120, 20, 89, 229, 81, 142, 195, 161, 241, 83, 228, 38, 92, 101, 231, 167, 242, 126, 21, 132, 22, 175, 72, 12, 2, 86, 100, 188, 117, 148, 196, 204, 34, 177, 158, 112, 190, 203, 248, 127, 64, 182, 116, 105, 146, 110, 104, 103, 60, 10, 173, 243, 169, 71, 226, 209, 249, 170, 114, 19, 46, 179, 244, 212, 121, 63, 139, 66, 11, 216, 36, 6, 1], +[1, 44, 137, 117, 8, 95, 68, 165, 64, 246, 30, 35, 255, 169, 240, 23, 241, 67, 121, 184, 129, 22, 197, 187, 4, 176, 34, 211, 32, 123, 15, 146, 256, 213, 120, 140, 249, 162, 189, 92, 193, 11, 227, 222, 2, 88, 17, 234, 16, 190, 136, 73, 128, 235, 60, 70, 253, 81, 223, 46, 225, 134, 242, 111, 1, 44, 137, 117, 8, 95, 68, 165, 64, 246, 30, 35, 255, 169, 240, 23, 241, 67, 121, 184, 129, 22, 197, 187, 4, 176, 34, 211, 32, 123, 15, 146, 256, 213, 120, 140, 249, 162, 189, 92, 193, 11, 227, 222, 2, 88, 17, 234, 16, 190, 136, 73, 128, 235, 60, 70, 253, 81, 223, 46, 225, 134, 242, 111, 1, 44, 137, 117, 8, 95, 68, 165, 64, 246, 30, 35, 255, 169, 240, 23, 241, 67, 121, 184, 129, 22, 197, 187, 4, 176, 34, 211, 32, 123, 15, 146, 256, 213, 120, 140, 249, 162, 189, 92, 193, 11, 227, 222, 2, 88, 17, 234, 16, 190, 136, 73, 128, 235, 60, 70, 253, 81, 223, 46, 225, 134, 242, 111, 1, 44, 137, 117, 8, 95, 68, 165, 64, 246, 30, 35, 255, 169, 240, 23, 241, 67, 121, 184, 129, 22, 197, 187, 4, 176, 34, 211, 32, 123, 15, 146, 256, 213, 120, 140, 249, 162, 189, 92, 193, 11, 227, 222, 2, 88, 17, 234, 16, 190, 136, 73, 128, 235, 60, 70, 253, 81, 223, 46, 225, 134, 242, 111, 1], +[1, 45, 226, 147, 190, 69, 21, 174, 120, 3, 135, 164, 184, 56, 207, 63, 8, 103, 9, 148, 235, 38, 168, 107, 189, 24, 52, 27, 187, 191, 114, 247, 64, 53, 72, 156, 81, 47, 59, 85, 227, 192, 159, 216, 211, 243, 141, 177, 255, 167, 62, 220, 134, 119, 215, 166, 17, 251, 244, 186, 146, 145, 100, 131, 241, 51, 239, 218, 44, 181, 178, 43, 136, 209, 153, 203, 140, 132, 29, 20, 129, 151, 113, 202, 95, 163, 139, 87, 60, 130, 196, 82, 92, 28, 232, 160, 4, 180, 133, 74, 246, 19, 84, 182, 223, 12, 26, 142, 222, 224, 57, 252, 32, 155, 36, 78, 169, 152, 158, 171, 242, 96, 208, 108, 234, 250, 199, 217, 256, 212, 31, 110, 67, 188, 236, 83, 137, 254, 122, 93, 73, 201, 50, 194, 249, 154, 248, 109, 22, 219, 89, 150, 68, 233, 205, 230, 70, 66, 143, 10, 193, 204, 185, 101, 176, 210, 198, 172, 30, 65, 98, 41, 46, 14, 116, 80, 2, 90, 195, 37, 123, 138, 42, 91, 240, 6, 13, 71, 111, 112, 157, 126, 16, 206, 18, 39, 213, 76, 79, 214, 121, 48, 104, 54, 117, 125, 228, 237, 128, 106, 144, 55, 162, 94, 118, 170, 197, 127, 61, 175, 165, 229, 25, 97, 253, 77, 124, 183, 11, 238, 173, 75, 34, 245, 231, 115, 35, 33, 200, 5, 225, 102, 221, 179, 88, 105, 99, 86, 15, 161, 49, 149, 23, 7, 58, 40, 1], +[1, 46, 60, 190, 2, 92, 120, 123, 4, 184, 240, 246, 8, 111, 223, 235, 16, 222, 189, 213, 32, 187, 121, 169, 64, 117, 242, 81, 128, 234, 227, 162, 256, 211, 197, 67, 255, 165, 137, 134, 253, 73, 17, 11, 249, 146, 34, 22, 241, 35, 68, 44, 225, 70, 136, 88, 193, 140, 15, 176, 129, 23, 30, 95, 1, 46, 60, 190, 2, 92, 120, 123, 4, 184, 240, 246, 8, 111, 223, 235, 16, 222, 189, 213, 32, 187, 121, 169, 64, 117, 242, 81, 128, 234, 227, 162, 256, 211, 197, 67, 255, 165, 137, 134, 253, 73, 17, 11, 249, 146, 34, 22, 241, 35, 68, 44, 225, 70, 136, 88, 193, 140, 15, 176, 129, 23, 30, 95, 1, 46, 60, 190, 2, 92, 120, 123, 4, 184, 240, 246, 8, 111, 223, 235, 16, 222, 189, 213, 32, 187, 121, 169, 64, 117, 242, 81, 128, 234, 227, 162, 256, 211, 197, 67, 255, 165, 137, 134, 253, 73, 17, 11, 249, 146, 34, 22, 241, 35, 68, 44, 225, 70, 136, 88, 193, 140, 15, 176, 129, 23, 30, 95, 1, 46, 60, 190, 2, 92, 120, 123, 4, 184, 240, 246, 8, 111, 223, 235, 16, 222, 189, 213, 32, 187, 121, 169, 64, 117, 242, 81, 128, 234, 227, 162, 256, 211, 197, 67, 255, 165, 137, 134, 253, 73, 17, 11, 249, 146, 34, 22, 241, 35, 68, 44, 225, 70, 136, 88, 193, 140, 15, 176, 129, 23, 30, 95, 1], +[1, 47, 153, 252, 22, 6, 25, 147, 227, 132, 36, 150, 111, 77, 21, 216, 129, 152, 205, 126, 11, 3, 141, 202, 242, 66, 18, 75, 184, 167, 139, 108, 193, 76, 231, 63, 134, 130, 199, 101, 121, 33, 9, 166, 92, 212, 198, 54, 225, 38, 244, 160, 67, 65, 228, 179, 189, 145, 133, 83, 46, 106, 99, 27, 241, 19, 122, 80, 162, 161, 114, 218, 223, 201, 195, 170, 23, 53, 178, 142, 249, 138, 61, 40, 81, 209, 57, 109, 240, 229, 226, 85, 140, 155, 89, 71, 253, 69, 159, 20, 169, 233, 157, 183, 120, 243, 113, 171, 70, 206, 173, 164, 255, 163, 208, 10, 213, 245, 207, 220, 60, 250, 185, 214, 35, 103, 215, 82, 256, 210, 104, 5, 235, 251, 232, 110, 30, 125, 221, 107, 146, 180, 236, 41, 128, 105, 52, 131, 246, 254, 116, 55, 15, 191, 239, 182, 73, 90, 118, 149, 64, 181, 26, 194, 123, 127, 58, 156, 136, 224, 248, 91, 165, 45, 59, 203, 32, 219, 13, 97, 190, 192, 29, 78, 68, 112, 124, 174, 211, 151, 158, 230, 16, 238, 135, 177, 95, 96, 143, 39, 34, 56, 62, 87, 234, 204, 79, 115, 8, 119, 196, 217, 176, 48, 200, 148, 17, 28, 31, 172, 117, 102, 168, 186, 4, 188, 98, 237, 88, 24, 100, 74, 137, 14, 144, 86, 187, 51, 84, 93, 2, 94, 49, 247, 44, 12, 50, 37, 197, 7, 72, 43, 222, 154, 42, 175, 1], +[1, 48, 248, 82, 81, 33, 42, 217, 136, 103, 61, 101, 222, 119, 58, 214, 249, 130, 72, 115, 123, 250, 178, 63, 197, 204, 26, 220, 23, 76, 50, 87, 64, 245, 195, 108, 44, 56, 118, 10, 223, 167, 49, 39, 73, 163, 114, 75, 2, 96, 239, 164, 162, 66, 84, 177, 15, 206, 122, 202, 187, 238, 116, 171, 241, 3, 144, 230, 246, 243, 99, 126, 137, 151, 52, 183, 46, 152, 100, 174, 128, 233, 133, 216, 88, 112, 236, 20, 189, 77, 98, 78, 146, 69, 228, 150, 4, 192, 221, 71, 67, 132, 168, 97, 30, 155, 244, 147, 117, 219, 232, 85, 225, 6, 31, 203, 235, 229, 198, 252, 17, 45, 104, 109, 92, 47, 200, 91, 256, 209, 9, 175, 176, 224, 215, 40, 121, 154, 196, 156, 35, 138, 199, 43, 8, 127, 185, 142, 134, 7, 79, 194, 60, 53, 231, 37, 234, 181, 207, 170, 193, 12, 62, 149, 213, 201, 139, 247, 34, 90, 208, 218, 184, 94, 143, 182, 255, 161, 18, 93, 95, 191, 173, 80, 242, 51, 135, 55, 70, 19, 141, 86, 16, 254, 113, 27, 11, 14, 158, 131, 120, 106, 205, 74, 211, 105, 157, 83, 129, 24, 124, 41, 169, 145, 21, 237, 68, 180, 159, 179, 111, 188, 29, 107, 253, 65, 36, 186, 190, 125, 89, 160, 227, 102, 13, 110, 140, 38, 25, 172, 32, 251, 226, 54, 22, 28, 59, 5, 240, 212, 153, 148, 165, 210, 57, 166, 1], +[1, 49, 88, 200, 34, 124, 165, 118, 128, 104, 213, 157, 240, 195, 46, 198, 193, 205, 22, 50, 137, 31, 234, 158, 32, 26, 246, 232, 60, 113, 140, 178, 241, 244, 134, 141, 227, 72, 187, 168, 8, 135, 190, 58, 15, 221, 35, 173, 253, 61, 162, 228, 121, 18, 111, 42, 2, 98, 176, 143, 68, 248, 73, 236, 256, 208, 169, 57, 223, 133, 92, 139, 129, 153, 44, 100, 17, 62, 211, 59, 64, 52, 235, 207, 120, 226, 23, 99, 225, 231, 11, 25, 197, 144, 117, 79, 16, 13, 123, 116, 30, 185, 70, 89, 249, 122, 67, 199, 242, 36, 222, 84, 4, 196, 95, 29, 136, 239, 146, 215, 255, 159, 81, 114, 189, 9, 184, 21, 1, 49, 88, 200, 34, 124, 165, 118, 128, 104, 213, 157, 240, 195, 46, 198, 193, 205, 22, 50, 137, 31, 234, 158, 32, 26, 246, 232, 60, 113, 140, 178, 241, 244, 134, 141, 227, 72, 187, 168, 8, 135, 190, 58, 15, 221, 35, 173, 253, 61, 162, 228, 121, 18, 111, 42, 2, 98, 176, 143, 68, 248, 73, 236, 256, 208, 169, 57, 223, 133, 92, 139, 129, 153, 44, 100, 17, 62, 211, 59, 64, 52, 235, 207, 120, 226, 23, 99, 225, 231, 11, 25, 197, 144, 117, 79, 16, 13, 123, 116, 30, 185, 70, 89, 249, 122, 67, 199, 242, 36, 222, 84, 4, 196, 95, 29, 136, 239, 146, 215, 255, 159, 81, 114, 189, 9, 184, 21, 1], +[1, 50, 187, 98, 17, 79, 95, 124, 32, 58, 73, 52, 30, 215, 213, 113, 253, 57, 23, 122, 189, 198, 134, 18, 129, 25, 222, 49, 137, 168, 176, 62, 16, 29, 165, 26, 15, 236, 235, 185, 255, 157, 140, 61, 223, 99, 67, 9, 193, 141, 111, 153, 197, 84, 88, 31, 8, 143, 211, 13, 136, 118, 246, 221, 256, 207, 70, 159, 240, 178, 162, 133, 225, 199, 184, 205, 227, 42, 44, 144, 4, 200, 234, 135, 68, 59, 123, 239, 128, 232, 35, 208, 120, 89, 81, 195, 241, 228, 92, 231, 242, 21, 22, 72, 2, 100, 117, 196, 34, 158, 190, 248, 64, 116, 146, 104, 60, 173, 169, 226, 249, 114, 46, 244, 121, 139, 11, 36, 1, 50, 187, 98, 17, 79, 95, 124, 32, 58, 73, 52, 30, 215, 213, 113, 253, 57, 23, 122, 189, 198, 134, 18, 129, 25, 222, 49, 137, 168, 176, 62, 16, 29, 165, 26, 15, 236, 235, 185, 255, 157, 140, 61, 223, 99, 67, 9, 193, 141, 111, 153, 197, 84, 88, 31, 8, 143, 211, 13, 136, 118, 246, 221, 256, 207, 70, 159, 240, 178, 162, 133, 225, 199, 184, 205, 227, 42, 44, 144, 4, 200, 234, 135, 68, 59, 123, 239, 128, 232, 35, 208, 120, 89, 81, 195, 241, 228, 92, 231, 242, 21, 22, 72, 2, 100, 117, 196, 34, 158, 190, 248, 64, 116, 146, 104, 60, 173, 169, 226, 249, 114, 46, 244, 121, 139, 11, 36, 1], +[1, 51, 31, 39, 190, 181, 236, 214, 120, 209, 122, 54, 184, 132, 50, 237, 8, 151, 248, 55, 235, 163, 89, 170, 189, 130, 205, 175, 187, 28, 143, 97, 64, 180, 185, 183, 81, 19, 198, 75, 227, 12, 98, 115, 211, 224, 116, 5, 255, 155, 195, 179, 134, 152, 42, 86, 17, 96, 13, 149, 146, 250, 157, 40, 241, 212, 18, 147, 44, 188, 79, 174, 136, 254, 104, 164, 140, 201, 228, 63, 129, 154, 144, 148, 95, 219, 118, 107, 60, 233, 61, 27, 92, 66, 25, 247, 4, 204, 124, 156, 246, 210, 173, 85, 223, 65, 231, 216, 222, 14, 200, 177, 32, 90, 221, 220, 169, 138, 99, 166, 242, 6, 49, 186, 234, 112, 58, 131, 256, 206, 226, 218, 67, 76, 21, 43, 137, 48, 135, 203, 73, 125, 207, 20, 249, 106, 9, 202, 22, 94, 168, 87, 68, 127, 52, 82, 70, 229, 114, 160, 193, 77, 72, 74, 176, 238, 59, 182, 30, 245, 159, 142, 46, 33, 141, 252, 2, 102, 62, 78, 123, 105, 215, 171, 240, 161, 244, 108, 111, 7, 100, 217, 16, 45, 239, 110, 213, 69, 178, 83, 121, 3, 153, 93, 117, 56, 29, 194, 128, 103, 113, 109, 162, 38, 139, 150, 197, 24, 196, 230, 165, 191, 232, 10, 253, 53, 133, 101, 11, 47, 84, 172, 34, 192, 26, 41, 35, 243, 57, 80, 225, 167, 36, 37, 88, 119, 158, 91, 15, 251, 208, 71, 23, 145, 199, 126, 1], +[1, 52, 134, 29, 223, 31, 70, 42, 128, 231, 190, 114, 17, 113, 222, 236, 193, 13, 162, 200, 120, 72, 146, 139, 32, 122, 176, 157, 197, 221, 184, 59, 241, 196, 169, 50, 30, 18, 165, 99, 8, 159, 44, 232, 242, 248, 46, 79, 253, 49, 235, 141, 136, 133, 234, 89, 2, 104, 11, 58, 189, 62, 140, 84, 256, 205, 123, 228, 34, 226, 187, 215, 129, 26, 67, 143, 240, 144, 35, 21, 64, 244, 95, 57, 137, 185, 111, 118, 225, 135, 81, 100, 60, 36, 73, 198, 16, 61, 88, 207, 227, 239, 92, 158, 249, 98, 213, 25, 15, 9, 211, 178, 4, 208, 22, 116, 121, 124, 23, 168, 255, 153, 246, 199, 68, 195, 117, 173, 1, 52, 134, 29, 223, 31, 70, 42, 128, 231, 190, 114, 17, 113, 222, 236, 193, 13, 162, 200, 120, 72, 146, 139, 32, 122, 176, 157, 197, 221, 184, 59, 241, 196, 169, 50, 30, 18, 165, 99, 8, 159, 44, 232, 242, 248, 46, 79, 253, 49, 235, 141, 136, 133, 234, 89, 2, 104, 11, 58, 189, 62, 140, 84, 256, 205, 123, 228, 34, 226, 187, 215, 129, 26, 67, 143, 240, 144, 35, 21, 64, 244, 95, 57, 137, 185, 111, 118, 225, 135, 81, 100, 60, 36, 73, 198, 16, 61, 88, 207, 227, 239, 92, 158, 249, 98, 213, 25, 15, 9, 211, 178, 4, 208, 22, 116, 121, 124, 23, 168, 255, 153, 246, 199, 68, 195, 117, 173, 1], +[1, 53, 239, 74, 67, 210, 79, 75, 120, 192, 153, 142, 73, 14, 228, 5, 8, 167, 113, 78, 22, 138, 118, 86, 189, 251, 196, 108, 70, 112, 25, 40, 64, 51, 133, 110, 176, 76, 173, 174, 227, 209, 26, 93, 46, 125, 200, 63, 255, 151, 36, 109, 123, 94, 99, 107, 17, 130, 208, 230, 111, 229, 58, 247, 241, 180, 31, 101, 213, 238, 21, 85, 136, 12, 122, 41, 117, 33, 207, 177, 129, 155, 248, 37, 162, 105, 168, 166, 60, 96, 205, 71, 165, 7, 114, 131, 4, 212, 185, 39, 11, 69, 59, 43, 223, 254, 98, 54, 35, 56, 141, 20, 32, 154, 195, 55, 88, 38, 215, 87, 242, 233, 13, 175, 23, 191, 100, 160, 256, 204, 18, 183, 190, 47, 178, 182, 137, 65, 104, 115, 184, 243, 29, 252, 249, 90, 144, 179, 235, 119, 139, 171, 68, 6, 61, 149, 187, 145, 232, 217, 193, 206, 124, 147, 81, 181, 84, 83, 30, 48, 231, 164, 211, 132, 57, 194, 2, 106, 221, 148, 134, 163, 158, 150, 240, 127, 49, 27, 146, 28, 199, 10, 16, 77, 226, 156, 44, 19, 236, 172, 121, 245, 135, 216, 140, 224, 50, 80, 128, 102, 9, 220, 95, 152, 89, 91, 197, 161, 52, 186, 92, 250, 143, 126, 253, 45, 72, 218, 246, 188, 198, 214, 34, 3, 159, 203, 222, 201, 116, 237, 225, 103, 62, 202, 169, 219, 42, 170, 15, 24, 244, 82, 234, 66, 157, 97, 1], +[1, 54, 89, 180, 211, 86, 18, 201, 60, 156, 200, 6, 67, 20, 52, 238, 2, 108, 178, 103, 165, 172, 36, 145, 120, 55, 143, 12, 134, 40, 104, 219, 4, 216, 99, 206, 73, 87, 72, 33, 240, 110, 29, 24, 11, 80, 208, 181, 8, 175, 198, 155, 146, 174, 144, 66, 223, 220, 58, 48, 22, 160, 159, 105, 16, 93, 139, 53, 35, 91, 31, 132, 189, 183, 116, 96, 44, 63, 61, 210, 32, 186, 21, 106, 70, 182, 62, 7, 121, 109, 232, 192, 88, 126, 122, 163, 64, 115, 42, 212, 140, 107, 124, 14, 242, 218, 207, 127, 176, 252, 244, 69, 128, 230, 84, 167, 23, 214, 248, 28, 227, 179, 157, 254, 95, 247, 231, 138, 256, 203, 168, 77, 46, 171, 239, 56, 197, 101, 57, 251, 190, 237, 205, 19, 255, 149, 79, 154, 92, 85, 221, 112, 137, 202, 114, 245, 123, 217, 153, 38, 253, 41, 158, 51, 184, 170, 185, 224, 17, 147, 228, 233, 246, 177, 49, 76, 249, 82, 59, 102, 111, 83, 113, 191, 34, 37, 199, 209, 235, 97, 98, 152, 241, 164, 118, 204, 222, 166, 226, 125, 68, 74, 141, 161, 213, 194, 196, 47, 225, 71, 236, 151, 187, 75, 195, 250, 136, 148, 25, 65, 169, 131, 135, 94, 193, 142, 215, 45, 117, 150, 133, 243, 15, 39, 50, 130, 81, 5, 13, 188, 129, 27, 173, 90, 234, 43, 9, 229, 30, 78, 100, 3, 162, 10, 26, 119, 1], +[1, 55, 198, 96, 140, 247, 221, 76, 68, 142, 100, 103, 11, 91, 122, 28, 255, 147, 118, 65, 234, 20, 72, 105, 121, 230, 57, 51, 235, 75, 13, 201, 4, 220, 21, 127, 46, 217, 113, 47, 15, 54, 143, 155, 44, 107, 231, 112, 249, 74, 215, 3, 165, 80, 31, 163, 227, 149, 228, 204, 169, 43, 52, 33, 16, 109, 84, 251, 184, 97, 195, 188, 60, 216, 58, 106, 176, 171, 153, 191, 225, 39, 89, 12, 146, 63, 124, 138, 137, 82, 141, 45, 162, 172, 208, 132, 64, 179, 79, 233, 222, 131, 9, 238, 240, 93, 232, 167, 190, 170, 98, 250, 129, 156, 99, 48, 70, 252, 239, 38, 34, 71, 50, 180, 134, 174, 61, 14, 256, 202, 59, 161, 117, 10, 36, 181, 189, 115, 157, 154, 246, 166, 135, 229, 2, 110, 139, 192, 23, 237, 185, 152, 136, 27, 200, 206, 22, 182, 244, 56, 253, 37, 236, 130, 211, 40, 144, 210, 242, 203, 114, 102, 213, 150, 26, 145, 8, 183, 42, 254, 92, 177, 226, 94, 30, 108, 29, 53, 88, 214, 205, 224, 241, 148, 173, 6, 73, 160, 62, 69, 197, 41, 199, 151, 81, 86, 104, 66, 32, 218, 168, 245, 111, 194, 133, 119, 120, 175, 116, 212, 95, 85, 49, 125, 193, 78, 178, 24, 35, 126, 248, 19, 17, 164, 25, 90, 67, 87, 159, 7, 128, 101, 158, 209, 187, 5, 18, 219, 223, 186, 207, 77, 123, 83, 196, 243, 1], +[1, 56, 52, 85, 134, 51, 29, 82, 223, 152, 31, 194, 70, 65, 42, 39, 128, 229, 231, 86, 190, 103, 114, 216, 17, 181, 113, 160, 222, 96, 236, 109, 193, 14, 13, 214, 162, 77, 200, 149, 120, 38, 72, 177, 146, 209, 139, 74, 32, 250, 122, 150, 176, 90, 157, 54, 197, 238, 221, 40, 184, 24, 59, 220, 241, 132, 196, 182, 169, 212, 50, 230, 30, 138, 18, 237, 165, 245, 99, 147, 8, 191, 159, 166, 44, 151, 232, 142, 242, 188, 248, 10, 46, 6, 79, 55, 253, 33, 49, 174, 235, 53, 141, 186, 136, 163, 133, 252, 234, 254, 89, 101, 2, 112, 104, 170, 11, 102, 58, 164, 189, 47, 62, 131, 140, 130, 84, 78, 256, 201, 205, 172, 123, 206, 228, 175, 34, 105, 226, 63, 187, 192, 215, 218, 129, 28, 26, 171, 67, 154, 143, 41, 240, 76, 144, 97, 35, 161, 21, 148, 64, 243, 244, 43, 95, 180, 57, 108, 137, 219, 185, 80, 111, 48, 118, 183, 225, 7, 135, 107, 81, 167, 100, 203, 60, 19, 36, 217, 73, 233, 198, 37, 16, 125, 61, 75, 88, 45, 207, 27, 227, 119, 239, 20, 92, 12, 158, 110, 249, 66, 98, 91, 213, 106, 25, 115, 15, 69, 9, 247, 211, 251, 178, 202, 4, 224, 208, 83, 22, 204, 116, 71, 121, 94, 124, 5, 23, 3, 168, 156, 255, 145, 153, 87, 246, 155, 199, 93, 68, 210, 195, 126, 117, 127, 173, 179, 1], +[1, 57, 165, 153, 240, 59, 22, 226, 32, 25, 140, 13, 227, 89, 190, 36, 253, 29, 111, 159, 68, 21, 169, 124, 129, 157, 211, 205, 120, 158, 11, 113, 16, 141, 70, 135, 242, 173, 95, 18, 255, 143, 184, 208, 34, 139, 213, 62, 193, 207, 234, 231, 60, 79, 134, 185, 8, 199, 35, 196, 121, 215, 176, 9, 256, 200, 92, 104, 17, 198, 235, 31, 225, 232, 117, 244, 30, 168, 67, 221, 4, 228, 146, 98, 189, 236, 88, 133, 128, 100, 46, 52, 137, 99, 246, 144, 241, 116, 187, 122, 15, 84, 162, 239, 2, 114, 73, 49, 223, 118, 44, 195, 64, 50, 23, 26, 197, 178, 123, 72, 249, 58, 222, 61, 136, 42, 81, 248, 1, 57, 165, 153, 240, 59, 22, 226, 32, 25, 140, 13, 227, 89, 190, 36, 253, 29, 111, 159, 68, 21, 169, 124, 129, 157, 211, 205, 120, 158, 11, 113, 16, 141, 70, 135, 242, 173, 95, 18, 255, 143, 184, 208, 34, 139, 213, 62, 193, 207, 234, 231, 60, 79, 134, 185, 8, 199, 35, 196, 121, 215, 176, 9, 256, 200, 92, 104, 17, 198, 235, 31, 225, 232, 117, 244, 30, 168, 67, 221, 4, 228, 146, 98, 189, 236, 88, 133, 128, 100, 46, 52, 137, 99, 246, 144, 241, 116, 187, 122, 15, 84, 162, 239, 2, 114, 73, 49, 223, 118, 44, 195, 64, 50, 23, 26, 197, 178, 123, 72, 249, 58, 222, 61, 136, 42, 81, 248, 1], +[1, 58, 23, 49, 15, 99, 88, 221, 225, 200, 35, 231, 34, 173, 11, 124, 253, 25, 165, 61, 197, 118, 162, 144, 128, 228, 117, 104, 121, 79, 213, 18, 16, 157, 111, 13, 240, 42, 123, 195, 2, 116, 46, 98, 30, 198, 176, 185, 193, 143, 70, 205, 68, 89, 22, 248, 249, 50, 73, 122, 137, 236, 67, 31, 256, 199, 234, 208, 242, 158, 169, 36, 32, 57, 222, 26, 223, 84, 246, 133, 4, 232, 92, 196, 60, 139, 95, 113, 129, 29, 140, 153, 136, 178, 44, 239, 241, 100, 146, 244, 17, 215, 134, 62, 255, 141, 211, 159, 227, 59, 81, 72, 64, 114, 187, 52, 189, 168, 235, 9, 8, 207, 184, 135, 120, 21, 190, 226, 1, 58, 23, 49, 15, 99, 88, 221, 225, 200, 35, 231, 34, 173, 11, 124, 253, 25, 165, 61, 197, 118, 162, 144, 128, 228, 117, 104, 121, 79, 213, 18, 16, 157, 111, 13, 240, 42, 123, 195, 2, 116, 46, 98, 30, 198, 176, 185, 193, 143, 70, 205, 68, 89, 22, 248, 249, 50, 73, 122, 137, 236, 67, 31, 256, 199, 234, 208, 242, 158, 169, 36, 32, 57, 222, 26, 223, 84, 246, 133, 4, 232, 92, 196, 60, 139, 95, 113, 129, 29, 140, 153, 136, 178, 44, 239, 241, 100, 146, 244, 17, 215, 134, 62, 255, 141, 211, 159, 227, 59, 81, 72, 64, 114, 187, 52, 189, 168, 235, 9, 8, 207, 184, 135, 120, 21, 190, 226, 1], +[1, 59, 140, 36, 68, 157, 11, 135, 255, 139, 234, 185, 121, 200, 235, 244, 4, 236, 46, 144, 15, 114, 44, 26, 249, 42, 165, 226, 227, 29, 169, 205, 16, 173, 184, 62, 60, 199, 176, 104, 225, 168, 146, 133, 137, 116, 162, 49, 64, 178, 222, 248, 240, 25, 190, 159, 129, 158, 70, 18, 34, 207, 134, 196, 256, 198, 117, 221, 189, 100, 246, 122, 2, 118, 23, 72, 136, 57, 22, 13, 253, 21, 211, 113, 242, 143, 213, 231, 8, 215, 92, 31, 30, 228, 88, 52, 241, 84, 73, 195, 197, 58, 81, 153, 32, 89, 111, 124, 120, 141, 95, 208, 193, 79, 35, 9, 17, 232, 67, 98, 128, 99, 187, 239, 223, 50, 123, 61, 1, 59, 140, 36, 68, 157, 11, 135, 255, 139, 234, 185, 121, 200, 235, 244, 4, 236, 46, 144, 15, 114, 44, 26, 249, 42, 165, 226, 227, 29, 169, 205, 16, 173, 184, 62, 60, 199, 176, 104, 225, 168, 146, 133, 137, 116, 162, 49, 64, 178, 222, 248, 240, 25, 190, 159, 129, 158, 70, 18, 34, 207, 134, 196, 256, 198, 117, 221, 189, 100, 246, 122, 2, 118, 23, 72, 136, 57, 22, 13, 253, 21, 211, 113, 242, 143, 213, 231, 8, 215, 92, 31, 30, 228, 88, 52, 241, 84, 73, 195, 197, 58, 81, 153, 32, 89, 111, 124, 120, 141, 95, 208, 193, 79, 35, 9, 17, 232, 67, 98, 128, 99, 187, 239, 223, 50, 123, 61, 1], +[1, 60, 2, 120, 4, 240, 8, 223, 16, 189, 32, 121, 64, 242, 128, 227, 256, 197, 255, 137, 253, 17, 249, 34, 241, 68, 225, 136, 193, 15, 129, 30, 1, 60, 2, 120, 4, 240, 8, 223, 16, 189, 32, 121, 64, 242, 128, 227, 256, 197, 255, 137, 253, 17, 249, 34, 241, 68, 225, 136, 193, 15, 129, 30, 1, 60, 2, 120, 4, 240, 8, 223, 16, 189, 32, 121, 64, 242, 128, 227, 256, 197, 255, 137, 253, 17, 249, 34, 241, 68, 225, 136, 193, 15, 129, 30, 1, 60, 2, 120, 4, 240, 8, 223, 16, 189, 32, 121, 64, 242, 128, 227, 256, 197, 255, 137, 253, 17, 249, 34, 241, 68, 225, 136, 193, 15, 129, 30, 1, 60, 2, 120, 4, 240, 8, 223, 16, 189, 32, 121, 64, 242, 128, 227, 256, 197, 255, 137, 253, 17, 249, 34, 241, 68, 225, 136, 193, 15, 129, 30, 1, 60, 2, 120, 4, 240, 8, 223, 16, 189, 32, 121, 64, 242, 128, 227, 256, 197, 255, 137, 253, 17, 249, 34, 241, 68, 225, 136, 193, 15, 129, 30, 1, 60, 2, 120, 4, 240, 8, 223, 16, 189, 32, 121, 64, 242, 128, 227, 256, 197, 255, 137, 253, 17, 249, 34, 241, 68, 225, 136, 193, 15, 129, 30, 1, 60, 2, 120, 4, 240, 8, 223, 16, 189, 32, 121, 64, 242, 128, 227, 256, 197, 255, 137, 253, 17, 249, 34, 241, 68, 225, 136, 193, 15, 129, 30, 1], +[1, 61, 123, 50, 223, 239, 187, 99, 128, 98, 67, 232, 17, 9, 35, 79, 193, 208, 95, 141, 120, 124, 111, 89, 32, 153, 81, 58, 197, 195, 73, 84, 241, 52, 88, 228, 30, 31, 92, 215, 8, 231, 213, 143, 242, 113, 211, 21, 253, 13, 22, 57, 136, 72, 23, 118, 2, 122, 246, 100, 189, 221, 117, 198, 256, 196, 134, 207, 34, 18, 70, 158, 129, 159, 190, 25, 240, 248, 222, 178, 64, 49, 162, 116, 137, 133, 146, 168, 225, 104, 176, 199, 60, 62, 184, 173, 16, 205, 169, 29, 227, 226, 165, 42, 249, 26, 44, 114, 15, 144, 46, 236, 4, 244, 235, 200, 121, 185, 234, 139, 255, 135, 11, 157, 68, 36, 140, 59, 1, 61, 123, 50, 223, 239, 187, 99, 128, 98, 67, 232, 17, 9, 35, 79, 193, 208, 95, 141, 120, 124, 111, 89, 32, 153, 81, 58, 197, 195, 73, 84, 241, 52, 88, 228, 30, 31, 92, 215, 8, 231, 213, 143, 242, 113, 211, 21, 253, 13, 22, 57, 136, 72, 23, 118, 2, 122, 246, 100, 189, 221, 117, 198, 256, 196, 134, 207, 34, 18, 70, 158, 129, 159, 190, 25, 240, 248, 222, 178, 64, 49, 162, 116, 137, 133, 146, 168, 225, 104, 176, 199, 60, 62, 184, 173, 16, 205, 169, 29, 227, 226, 165, 42, 249, 26, 44, 114, 15, 144, 46, 236, 4, 244, 235, 200, 121, 185, 234, 139, 255, 135, 11, 157, 68, 36, 140, 59, 1], +[1, 62, 246, 89, 121, 49, 211, 232, 249, 18, 88, 59, 60, 122, 111, 200, 64, 113, 67, 42, 34, 52, 140, 199, 2, 124, 235, 178, 242, 98, 165, 207, 241, 36, 176, 118, 120, 244, 222, 143, 128, 226, 134, 84, 68, 104, 23, 141, 4, 248, 213, 99, 227, 196, 73, 157, 225, 72, 95, 236, 240, 231, 187, 29, 256, 195, 11, 168, 136, 208, 46, 25, 8, 239, 169, 198, 197, 135, 146, 57, 193, 144, 190, 215, 223, 205, 117, 58, 255, 133, 22, 79, 15, 159, 92, 50, 16, 221, 81, 139, 137, 13, 35, 114, 129, 31, 123, 173, 189, 153, 234, 116, 253, 9, 44, 158, 30, 61, 184, 100, 32, 185, 162, 21, 17, 26, 70, 228, 1, 62, 246, 89, 121, 49, 211, 232, 249, 18, 88, 59, 60, 122, 111, 200, 64, 113, 67, 42, 34, 52, 140, 199, 2, 124, 235, 178, 242, 98, 165, 207, 241, 36, 176, 118, 120, 244, 222, 143, 128, 226, 134, 84, 68, 104, 23, 141, 4, 248, 213, 99, 227, 196, 73, 157, 225, 72, 95, 236, 240, 231, 187, 29, 256, 195, 11, 168, 136, 208, 46, 25, 8, 239, 169, 198, 197, 135, 146, 57, 193, 144, 190, 215, 223, 205, 117, 58, 255, 133, 22, 79, 15, 159, 92, 50, 16, 221, 81, 139, 137, 13, 35, 114, 129, 31, 123, 173, 189, 153, 234, 116, 253, 9, 44, 158, 30, 61, 184, 100, 32, 185, 162, 21, 17, 26, 70, 228, 1], +[1, 63, 114, 243, 146, 203, 196, 12, 242, 83, 89, 210, 123, 39, 144, 77, 225, 40, 207, 191, 211, 186, 153, 130, 223, 171, 236, 219, 176, 37, 18, 106, 253, 5, 58, 56, 187, 216, 244, 209, 60, 182, 158, 188, 22, 101, 195, 206, 128, 97, 200, 7, 184, 27, 159, 251, 136, 87, 84, 152, 67, 109, 185, 90, 16, 237, 25, 33, 23, 164, 52, 192, 17, 43, 139, 19, 169, 110, 248, 204, 2, 126, 228, 229, 35, 149, 135, 24, 227, 166, 178, 163, 246, 78, 31, 154, 193, 80, 157, 125, 165, 115, 49, 3, 189, 85, 215, 181, 95, 74, 36, 212, 249, 10, 116, 112, 117, 175, 231, 161, 120, 107, 59, 119, 44, 202, 133, 155, 256, 194, 143, 14, 111, 54, 61, 245, 15, 174, 168, 47, 134, 218, 113, 180, 32, 217, 50, 66, 46, 71, 104, 127, 34, 86, 21, 38, 81, 220, 239, 151, 4, 252, 199, 201, 70, 41, 13, 48, 197, 75, 99, 69, 235, 156, 62, 51, 129, 160, 57, 250, 73, 230, 98, 6, 121, 170, 173, 105, 190, 148, 72, 167, 241, 20, 232, 224, 234, 93, 205, 65, 240, 214, 118, 238, 88, 147, 9, 53, 255, 131, 29, 28, 222, 108, 122, 233, 30, 91, 79, 94, 11, 179, 226, 103, 64, 177, 100, 132, 92, 142, 208, 254, 68, 172, 42, 76, 162, 183, 221, 45, 8, 247, 141, 145, 140, 82, 26, 96, 137, 150, 198, 138, 213, 55, 124, 102, 1], +[1, 64, 241, 4, 256, 193, 16, 253, 1, 64, 241, 4, 256, 193, 16, 253, 1, 64, 241, 4, 256, 193, 16, 253, 1, 64, 241, 4, 256, 193, 16, 253, 1, 64, 241, 4, 256, 193, 16, 253, 1, 64, 241, 4, 256, 193, 16, 253, 1, 64, 241, 4, 256, 193, 16, 253, 1, 64, 241, 4, 256, 193, 16, 253, 1, 64, 241, 4, 256, 193, 16, 253, 1, 64, 241, 4, 256, 193, 16, 253, 1, 64, 241, 4, 256, 193, 16, 253, 1, 64, 241, 4, 256, 193, 16, 253, 1, 64, 241, 4, 256, 193, 16, 253, 1, 64, 241, 4, 256, 193, 16, 253, 1, 64, 241, 4, 256, 193, 16, 253, 1, 64, 241, 4, 256, 193, 16, 253, 1, 64, 241, 4, 256, 193, 16, 253, 1, 64, 241, 4, 256, 193, 16, 253, 1, 64, 241, 4, 256, 193, 16, 253, 1, 64, 241, 4, 256, 193, 16, 253, 1, 64, 241, 4, 256, 193, 16, 253, 1, 64, 241, 4, 256, 193, 16, 253, 1, 64, 241, 4, 256, 193, 16, 253, 1, 64, 241, 4, 256, 193, 16, 253, 1, 64, 241, 4, 256, 193, 16, 253, 1, 64, 241, 4, 256, 193, 16, 253, 1, 64, 241, 4, 256, 193, 16, 253, 1, 64, 241, 4, 256, 193, 16, 253, 1, 64, 241, 4, 256, 193, 16, 253, 1, 64, 241, 4, 256, 193, 16, 253, 1, 64, 241, 4, 256, 193, 16, 253, 1, 64, 241, 4, 256, 193, 16, 253, 1], +[1, 65, 113, 149, 176, 132, 99, 10, 136, 102, 205, 218, 35, 219, 100, 75, 249, 251, 124, 93, 134, 229, 236, 177, 197, 212, 159, 55, 234, 47, 228, 171, 64, 48, 36, 27, 213, 224, 168, 126, 223, 103, 13, 74, 184, 138, 232, 174, 2, 130, 226, 41, 95, 7, 198, 20, 15, 204, 153, 179, 70, 181, 200, 150, 241, 245, 248, 186, 11, 201, 215, 97, 137, 167, 61, 110, 211, 94, 199, 85, 128, 96, 72, 54, 169, 191, 79, 252, 189, 206, 26, 148, 111, 19, 207, 91, 4, 3, 195, 82, 190, 14, 139, 40, 30, 151, 49, 101, 140, 105, 143, 43, 225, 233, 239, 115, 22, 145, 173, 194, 17, 77, 122, 220, 165, 188, 141, 170, 256, 192, 144, 108, 81, 125, 158, 247, 121, 155, 52, 39, 222, 38, 157, 182, 8, 6, 133, 164, 123, 28, 21, 80, 60, 45, 98, 202, 23, 210, 29, 86, 193, 209, 221, 230, 44, 33, 89, 131, 34, 154, 244, 183, 73, 119, 25, 83, 255, 127, 31, 216, 162, 250, 59, 237, 242, 53, 104, 78, 187, 76, 57, 107, 16, 12, 9, 71, 246, 56, 42, 160, 120, 90, 196, 147, 46, 163, 58, 172, 129, 161, 185, 203, 88, 66, 178, 5, 68, 51, 231, 109, 146, 238, 50, 166, 253, 254, 62, 175, 67, 243, 118, 217, 227, 106, 208, 156, 117, 152, 114, 214, 32, 24, 18, 142, 235, 112, 84, 63, 240, 180, 135, 37, 92, 69, 116, 87, 1], +[1, 66, 244, 170, 169, 103, 116, 203, 34, 188, 72, 126, 92, 161, 89, 220, 128, 224, 135, 172, 44, 77, 199, 27, 240, 163, 221, 194, 211, 48, 84, 147, 193, 145, 61, 171, 235, 90, 29, 115, 137, 47, 18, 160, 23, 233, 215, 55, 32, 56, 98, 43, 11, 212, 114, 71, 60, 105, 248, 177, 117, 12, 21, 101, 241, 229, 208, 107, 123, 151, 200, 93, 227, 76, 133, 40, 70, 251, 118, 78, 8, 14, 153, 75, 67, 53, 157, 82, 15, 219, 62, 237, 222, 3, 198, 218, 253, 250, 52, 91, 95, 102, 50, 216, 121, 19, 226, 10, 146, 127, 158, 148, 2, 132, 231, 83, 81, 206, 232, 149, 68, 119, 144, 252, 184, 65, 178, 183, 256, 191, 13, 87, 88, 154, 141, 54, 223, 69, 185, 131, 165, 96, 168, 37, 129, 33, 122, 85, 213, 180, 58, 230, 17, 94, 36, 63, 46, 209, 173, 110, 64, 112, 196, 86, 22, 167, 228, 142, 120, 210, 239, 97, 234, 24, 42, 202, 225, 201, 159, 214, 246, 45, 143, 186, 197, 152, 9, 80, 140, 245, 236, 156, 16, 28, 49, 150, 134, 106, 57, 164, 30, 181, 124, 217, 187, 6, 139, 179, 249, 243, 104, 182, 190, 204, 100, 175, 242, 38, 195, 20, 35, 254, 59, 39, 4, 7, 205, 166, 162, 155, 207, 41, 136, 238, 31, 247, 111, 130, 99, 109, 255, 125, 26, 174, 176, 51, 25, 108, 189, 138, 113, 5, 73, 192, 79, 74, 1], +[1, 67, 120, 73, 8, 22, 189, 70, 64, 176, 227, 46, 255, 123, 17, 111, 241, 213, 136, 117, 129, 162, 60, 165, 4, 11, 223, 35, 32, 88, 242, 23, 256, 190, 137, 184, 249, 235, 68, 187, 193, 81, 30, 211, 2, 134, 240, 146, 16, 44, 121, 140, 128, 95, 197, 92, 253, 246, 34, 222, 225, 169, 15, 234, 1, 67, 120, 73, 8, 22, 189, 70, 64, 176, 227, 46, 255, 123, 17, 111, 241, 213, 136, 117, 129, 162, 60, 165, 4, 11, 223, 35, 32, 88, 242, 23, 256, 190, 137, 184, 249, 235, 68, 187, 193, 81, 30, 211, 2, 134, 240, 146, 16, 44, 121, 140, 128, 95, 197, 92, 253, 246, 34, 222, 225, 169, 15, 234, 1, 67, 120, 73, 8, 22, 189, 70, 64, 176, 227, 46, 255, 123, 17, 111, 241, 213, 136, 117, 129, 162, 60, 165, 4, 11, 223, 35, 32, 88, 242, 23, 256, 190, 137, 184, 249, 235, 68, 187, 193, 81, 30, 211, 2, 134, 240, 146, 16, 44, 121, 140, 128, 95, 197, 92, 253, 246, 34, 222, 225, 169, 15, 234, 1, 67, 120, 73, 8, 22, 189, 70, 64, 176, 227, 46, 255, 123, 17, 111, 241, 213, 136, 117, 129, 162, 60, 165, 4, 11, 223, 35, 32, 88, 242, 23, 256, 190, 137, 184, 249, 235, 68, 187, 193, 81, 30, 211, 2, 134, 240, 146, 16, 44, 121, 140, 128, 95, 197, 92, 253, 246, 34, 222, 225, 169, 15, 234, 1], +[1, 68, 255, 121, 4, 15, 249, 227, 16, 60, 225, 137, 64, 240, 129, 34, 256, 189, 2, 136, 253, 242, 8, 30, 241, 197, 32, 120, 193, 17, 128, 223, 1, 68, 255, 121, 4, 15, 249, 227, 16, 60, 225, 137, 64, 240, 129, 34, 256, 189, 2, 136, 253, 242, 8, 30, 241, 197, 32, 120, 193, 17, 128, 223, 1, 68, 255, 121, 4, 15, 249, 227, 16, 60, 225, 137, 64, 240, 129, 34, 256, 189, 2, 136, 253, 242, 8, 30, 241, 197, 32, 120, 193, 17, 128, 223, 1, 68, 255, 121, 4, 15, 249, 227, 16, 60, 225, 137, 64, 240, 129, 34, 256, 189, 2, 136, 253, 242, 8, 30, 241, 197, 32, 120, 193, 17, 128, 223, 1, 68, 255, 121, 4, 15, 249, 227, 16, 60, 225, 137, 64, 240, 129, 34, 256, 189, 2, 136, 253, 242, 8, 30, 241, 197, 32, 120, 193, 17, 128, 223, 1, 68, 255, 121, 4, 15, 249, 227, 16, 60, 225, 137, 64, 240, 129, 34, 256, 189, 2, 136, 253, 242, 8, 30, 241, 197, 32, 120, 193, 17, 128, 223, 1, 68, 255, 121, 4, 15, 249, 227, 16, 60, 225, 137, 64, 240, 129, 34, 256, 189, 2, 136, 253, 242, 8, 30, 241, 197, 32, 120, 193, 17, 128, 223, 1, 68, 255, 121, 4, 15, 249, 227, 16, 60, 225, 137, 64, 240, 129, 34, 256, 189, 2, 136, 253, 242, 8, 30, 241, 197, 32, 120, 193, 17, 128, 223, 1], +[1, 69, 135, 63, 235, 24, 114, 156, 227, 243, 62, 166, 146, 51, 178, 203, 129, 163, 196, 160, 246, 12, 57, 78, 242, 250, 31, 83, 73, 154, 89, 230, 193, 210, 98, 80, 123, 6, 157, 39, 121, 125, 144, 170, 165, 77, 173, 115, 225, 105, 49, 40, 190, 3, 207, 148, 189, 191, 72, 85, 211, 167, 215, 186, 241, 181, 153, 20, 95, 130, 232, 74, 223, 224, 36, 171, 234, 212, 236, 93, 249, 219, 205, 10, 176, 65, 116, 37, 240, 112, 18, 214, 117, 106, 118, 175, 253, 238, 231, 5, 88, 161, 58, 147, 120, 56, 9, 107, 187, 53, 59, 216, 255, 119, 244, 131, 44, 209, 29, 202, 60, 28, 133, 182, 222, 155, 158, 108, 256, 188, 122, 194, 22, 233, 143, 101, 30, 14, 195, 91, 111, 206, 79, 54, 128, 94, 61, 97, 11, 245, 200, 179, 15, 7, 226, 174, 184, 103, 168, 27, 64, 47, 159, 177, 134, 251, 100, 218, 136, 132, 113, 87, 92, 180, 84, 142, 32, 152, 208, 217, 67, 254, 50, 109, 68, 66, 185, 172, 46, 90, 42, 71, 16, 76, 104, 237, 162, 127, 25, 183, 34, 33, 221, 86, 23, 45, 21, 164, 8, 38, 52, 247, 81, 192, 141, 220, 17, 145, 239, 43, 140, 151, 139, 82, 4, 19, 26, 252, 169, 96, 199, 110, 137, 201, 248, 150, 70, 204, 198, 41, 2, 138, 13, 126, 213, 48, 228, 55, 197, 229, 124, 75, 35, 102, 99, 149, 1], +[1, 70, 17, 162, 32, 184, 30, 44, 253, 234, 189, 123, 129, 35, 137, 81, 16, 92, 15, 22, 255, 117, 223, 190, 193, 146, 197, 169, 8, 46, 136, 11, 256, 187, 240, 95, 225, 73, 227, 213, 4, 23, 68, 134, 128, 222, 120, 176, 241, 165, 242, 235, 2, 140, 34, 67, 64, 111, 60, 88, 249, 211, 121, 246, 1, 70, 17, 162, 32, 184, 30, 44, 253, 234, 189, 123, 129, 35, 137, 81, 16, 92, 15, 22, 255, 117, 223, 190, 193, 146, 197, 169, 8, 46, 136, 11, 256, 187, 240, 95, 225, 73, 227, 213, 4, 23, 68, 134, 128, 222, 120, 176, 241, 165, 242, 235, 2, 140, 34, 67, 64, 111, 60, 88, 249, 211, 121, 246, 1, 70, 17, 162, 32, 184, 30, 44, 253, 234, 189, 123, 129, 35, 137, 81, 16, 92, 15, 22, 255, 117, 223, 190, 193, 146, 197, 169, 8, 46, 136, 11, 256, 187, 240, 95, 225, 73, 227, 213, 4, 23, 68, 134, 128, 222, 120, 176, 241, 165, 242, 235, 2, 140, 34, 67, 64, 111, 60, 88, 249, 211, 121, 246, 1, 70, 17, 162, 32, 184, 30, 44, 253, 234, 189, 123, 129, 35, 137, 81, 16, 92, 15, 22, 255, 117, 223, 190, 193, 146, 197, 169, 8, 46, 136, 11, 256, 187, 240, 95, 225, 73, 227, 213, 4, 23, 68, 134, 128, 222, 120, 176, 241, 165, 242, 235, 2, 140, 34, 67, 64, 111, 60, 88, 249, 211, 121, 246, 1], +[1, 71, 158, 167, 35, 172, 133, 191, 197, 109, 29, 3, 213, 217, 244, 105, 2, 142, 59, 77, 70, 87, 9, 125, 137, 218, 58, 6, 169, 177, 231, 210, 4, 27, 118, 154, 140, 174, 18, 250, 17, 179, 116, 12, 81, 97, 205, 163, 8, 54, 236, 51, 23, 91, 36, 243, 34, 101, 232, 24, 162, 194, 153, 69, 16, 108, 215, 102, 46, 182, 72, 229, 68, 202, 207, 48, 67, 131, 49, 138, 32, 216, 173, 204, 92, 107, 144, 201, 136, 147, 157, 96, 134, 5, 98, 19, 64, 175, 89, 151, 184, 214, 31, 145, 15, 37, 57, 192, 11, 10, 196, 38, 128, 93, 178, 45, 111, 171, 62, 33, 30, 74, 114, 127, 22, 20, 135, 76, 256, 186, 99, 90, 222, 85, 124, 66, 60, 148, 228, 254, 44, 40, 13, 152, 255, 115, 198, 180, 187, 170, 248, 132, 120, 39, 199, 251, 88, 80, 26, 47, 253, 230, 139, 103, 117, 83, 239, 7, 240, 78, 141, 245, 176, 160, 52, 94, 249, 203, 21, 206, 234, 166, 221, 14, 223, 156, 25, 233, 95, 63, 104, 188, 241, 149, 42, 155, 211, 75, 185, 28, 189, 55, 50, 209, 190, 126, 208, 119, 225, 41, 84, 53, 165, 150, 113, 56, 121, 110, 100, 161, 123, 252, 159, 238, 193, 82, 168, 106, 73, 43, 226, 112, 242, 220, 200, 65, 246, 247, 61, 219, 129, 164, 79, 212, 146, 86, 195, 224, 227, 183, 143, 130, 235, 237, 122, 181, 1], +[1, 72, 44, 84, 137, 98, 117, 200, 8, 62, 95, 158, 68, 13, 165, 58, 64, 239, 246, 236, 30, 104, 35, 207, 255, 113, 169, 89, 240, 61, 23, 114, 241, 133, 67, 198, 121, 231, 184, 141, 129, 36, 22, 42, 197, 49, 187, 100, 4, 31, 176, 79, 34, 135, 211, 29, 32, 248, 123, 118, 15, 52, 146, 232, 256, 185, 213, 173, 120, 159, 140, 57, 249, 195, 162, 99, 189, 244, 92, 199, 193, 18, 11, 21, 227, 153, 222, 50, 2, 144, 88, 168, 17, 196, 234, 143, 16, 124, 190, 59, 136, 26, 73, 116, 128, 221, 235, 215, 60, 208, 70, 157, 253, 226, 81, 178, 223, 122, 46, 228, 225, 9, 134, 139, 242, 205, 111, 25, 1, 72, 44, 84, 137, 98, 117, 200, 8, 62, 95, 158, 68, 13, 165, 58, 64, 239, 246, 236, 30, 104, 35, 207, 255, 113, 169, 89, 240, 61, 23, 114, 241, 133, 67, 198, 121, 231, 184, 141, 129, 36, 22, 42, 197, 49, 187, 100, 4, 31, 176, 79, 34, 135, 211, 29, 32, 248, 123, 118, 15, 52, 146, 232, 256, 185, 213, 173, 120, 159, 140, 57, 249, 195, 162, 99, 189, 244, 92, 199, 193, 18, 11, 21, 227, 153, 222, 50, 2, 144, 88, 168, 17, 196, 234, 143, 16, 124, 190, 59, 136, 26, 73, 116, 128, 221, 235, 215, 60, 208, 70, 157, 253, 226, 81, 178, 223, 122, 46, 228, 225, 9, 134, 139, 242, 205, 111, 25, 1], +[1, 73, 189, 176, 255, 111, 136, 162, 4, 35, 242, 190, 249, 187, 30, 134, 16, 140, 197, 246, 225, 234, 120, 22, 64, 46, 17, 213, 129, 165, 223, 88, 256, 184, 68, 81, 2, 146, 121, 95, 253, 222, 15, 67, 8, 70, 227, 123, 241, 117, 60, 11, 32, 23, 137, 235, 193, 211, 240, 44, 128, 92, 34, 169, 1, 73, 189, 176, 255, 111, 136, 162, 4, 35, 242, 190, 249, 187, 30, 134, 16, 140, 197, 246, 225, 234, 120, 22, 64, 46, 17, 213, 129, 165, 223, 88, 256, 184, 68, 81, 2, 146, 121, 95, 253, 222, 15, 67, 8, 70, 227, 123, 241, 117, 60, 11, 32, 23, 137, 235, 193, 211, 240, 44, 128, 92, 34, 169, 1, 73, 189, 176, 255, 111, 136, 162, 4, 35, 242, 190, 249, 187, 30, 134, 16, 140, 197, 246, 225, 234, 120, 22, 64, 46, 17, 213, 129, 165, 223, 88, 256, 184, 68, 81, 2, 146, 121, 95, 253, 222, 15, 67, 8, 70, 227, 123, 241, 117, 60, 11, 32, 23, 137, 235, 193, 211, 240, 44, 128, 92, 34, 169, 1, 73, 189, 176, 255, 111, 136, 162, 4, 35, 242, 190, 249, 187, 30, 134, 16, 140, 197, 246, 225, 234, 120, 22, 64, 46, 17, 213, 129, 165, 223, 88, 256, 184, 68, 81, 2, 146, 121, 95, 253, 222, 15, 67, 8, 70, 227, 123, 241, 117, 60, 11, 32, 23, 137, 235, 193, 211, 240, 44, 128, 92, 34, 169, 1], +[1, 74, 79, 192, 73, 5, 113, 138, 189, 108, 25, 51, 176, 174, 26, 125, 255, 109, 99, 130, 111, 247, 31, 238, 136, 41, 207, 155, 162, 166, 205, 7, 4, 39, 59, 254, 35, 20, 195, 38, 242, 175, 100, 204, 190, 182, 104, 243, 249, 179, 139, 6, 187, 217, 124, 181, 30, 164, 57, 106, 134, 150, 49, 28, 16, 156, 236, 245, 140, 80, 9, 152, 197, 186, 143, 45, 246, 214, 159, 201, 225, 202, 42, 24, 234, 97, 239, 210, 120, 142, 228, 167, 22, 86, 196, 112, 64, 110, 173, 209, 46, 63, 36, 94, 17, 230, 58, 180, 213, 85, 122, 33, 129, 37, 168, 96, 165, 131, 185, 69, 223, 54, 141, 154, 88, 87, 13, 191, 256, 183, 178, 65, 184, 252, 144, 119, 68, 149, 232, 206, 81, 83, 231, 132, 2, 148, 158, 127, 146, 10, 226, 19, 121, 216, 50, 102, 95, 91, 52, 250, 253, 218, 198, 3, 222, 237, 62, 219, 15, 82, 157, 53, 67, 75, 153, 14, 8, 78, 118, 251, 70, 40, 133, 76, 227, 93, 200, 151, 123, 107, 208, 229, 241, 101, 21, 12, 117, 177, 248, 105, 60, 71, 114, 212, 11, 43, 98, 56, 32, 55, 215, 233, 23, 160, 18, 47, 137, 115, 29, 90, 235, 171, 61, 145, 193, 147, 84, 48, 211, 194, 221, 163, 240, 27, 199, 77, 44, 172, 135, 224, 128, 220, 89, 161, 92, 126, 72, 188, 34, 203, 116, 103, 169, 170, 244, 66, 1], +[1, 75, 228, 138, 70, 110, 26, 151, 17, 247, 21, 33, 162, 71, 185, 254, 32, 87, 100, 47, 184, 179, 61, 206, 30, 194, 158, 28, 44, 216, 9, 161, 253, 214, 116, 219, 234, 74, 153, 167, 189, 40, 173, 125, 123, 230, 31, 12, 129, 166, 114, 69, 35, 55, 13, 204, 137, 252, 139, 145, 81, 164, 221, 127, 16, 172, 50, 152, 92, 218, 159, 103, 15, 97, 79, 14, 22, 108, 133, 209, 255, 107, 58, 238, 117, 37, 205, 212, 223, 20, 215, 191, 190, 115, 144, 6, 193, 83, 57, 163, 146, 156, 135, 102, 197, 126, 198, 201, 169, 82, 239, 192, 8, 86, 25, 76, 46, 109, 208, 180, 136, 177, 168, 7, 11, 54, 195, 233, 256, 182, 29, 119, 187, 147, 231, 106, 240, 10, 236, 224, 95, 186, 72, 3, 225, 170, 157, 210, 73, 78, 196, 51, 227, 63, 99, 229, 213, 41, 248, 96, 4, 43, 141, 38, 23, 183, 104, 90, 68, 217, 84, 132, 134, 27, 226, 245, 128, 91, 143, 188, 222, 202, 244, 53, 120, 5, 118, 112, 176, 93, 36, 130, 241, 85, 207, 105, 165, 39, 98, 154, 242, 160, 178, 243, 235, 149, 124, 48, 2, 150, 199, 19, 140, 220, 52, 45, 34, 237, 42, 66, 67, 142, 113, 251, 64, 174, 200, 94, 111, 101, 122, 155, 60, 131, 59, 56, 88, 175, 18, 65, 249, 171, 232, 181, 211, 148, 49, 77, 121, 80, 89, 250, 246, 203, 62, 24, 1], +[1, 76, 122, 20, 235, 127, 143, 74, 227, 33, 195, 171, 146, 45, 79, 93, 129, 38, 61, 10, 246, 192, 200, 37, 242, 145, 226, 214, 73, 151, 168, 175, 193, 19, 159, 5, 123, 96, 100, 147, 121, 201, 113, 107, 165, 204, 84, 216, 225, 138, 208, 131, 190, 48, 50, 202, 189, 229, 185, 182, 211, 102, 42, 108, 241, 69, 104, 194, 95, 24, 25, 101, 223, 243, 221, 91, 234, 51, 21, 54, 249, 163, 52, 97, 176, 12, 141, 179, 240, 250, 239, 174, 117, 154, 139, 27, 253, 210, 26, 177, 88, 6, 199, 218, 120, 125, 248, 87, 187, 77, 198, 142, 255, 105, 13, 217, 44, 3, 228, 109, 60, 191, 124, 172, 222, 167, 99, 71, 256, 181, 135, 237, 22, 130, 114, 183, 30, 224, 62, 86, 111, 212, 178, 164, 128, 219, 196, 247, 11, 65, 57, 220, 15, 112, 31, 43, 184, 106, 89, 82, 64, 238, 98, 252, 134, 161, 157, 110, 136, 56, 144, 150, 92, 53, 173, 41, 32, 119, 49, 126, 67, 209, 207, 55, 68, 28, 72, 75, 46, 155, 215, 149, 16, 188, 153, 63, 162, 233, 232, 156, 34, 14, 36, 166, 23, 206, 236, 203, 8, 94, 205, 160, 81, 245, 116, 78, 17, 7, 18, 83, 140, 103, 118, 230, 4, 47, 231, 80, 169, 251, 58, 39, 137, 132, 9, 170, 70, 180, 59, 115, 2, 152, 244, 40, 213, 254, 29, 148, 197, 66, 133, 85, 35, 90, 158, 186, 1], +[1, 77, 18, 101, 67, 19, 178, 85, 120, 245, 104, 41, 73, 224, 29, 177, 8, 102, 144, 37, 22, 152, 139, 166, 189, 161, 61, 71, 70, 250, 232, 131, 64, 45, 124, 39, 176, 188, 84, 43, 227, 3, 231, 54, 46, 201, 57, 20, 255, 103, 221, 55, 123, 219, 158, 87, 17, 24, 49, 175, 111, 66, 199, 160, 241, 53, 226, 183, 213, 210, 236, 182, 136, 192, 135, 115, 117, 14, 50, 252, 129, 167, 9, 179, 162, 138, 89, 171, 60, 251, 52, 149, 165, 112, 143, 217, 4, 51, 72, 147, 11, 76, 198, 83, 223, 209, 159, 164, 35, 125, 116, 194, 32, 151, 62, 148, 88, 94, 42, 150, 242, 130, 244, 27, 23, 229, 157, 10, 256, 180, 239, 156, 190, 238, 79, 172, 137, 12, 153, 216, 184, 33, 228, 80, 249, 155, 113, 220, 235, 105, 118, 91, 68, 96, 196, 186, 187, 7, 25, 126, 193, 212, 133, 218, 81, 69, 173, 214, 30, 254, 26, 203, 211, 56, 200, 237, 2, 154, 36, 202, 134, 38, 99, 170, 240, 233, 208, 82, 146, 191, 58, 97, 16, 204, 31, 74, 44, 47, 21, 75, 121, 65, 122, 142, 140, 243, 207, 5, 128, 90, 248, 78, 95, 119, 168, 86, 197, 6, 205, 108, 92, 145, 114, 40, 253, 206, 185, 110, 246, 181, 59, 174, 34, 48, 98, 93, 222, 132, 141, 63, 225, 106, 195, 109, 169, 163, 215, 107, 15, 127, 13, 230, 234, 28, 100, 247, 1], +[1, 78, 173, 130, 117, 131, 195, 47, 68, 164, 199, 102, 246, 170, 153, 112, 255, 101, 168, 254, 23, 252, 124, 163, 121, 186, 116, 53, 22, 174, 208, 33, 4, 55, 178, 6, 211, 10, 9, 188, 15, 142, 25, 151, 213, 166, 98, 191, 249, 147, 158, 245, 92, 237, 239, 138, 227, 230, 207, 212, 88, 182, 61, 132, 16, 220, 198, 24, 73, 40, 36, 238, 60, 54, 100, 90, 81, 150, 135, 250, 225, 74, 118, 209, 111, 177, 185, 38, 137, 149, 57, 77, 95, 214, 244, 14, 64, 109, 21, 96, 35, 160, 144, 181, 240, 216, 143, 103, 67, 86, 26, 229, 129, 39, 215, 65, 187, 194, 226, 152, 34, 82, 228, 51, 123, 85, 205, 56, 256, 179, 84, 127, 140, 126, 62, 210, 189, 93, 58, 155, 11, 87, 104, 145, 2, 156, 89, 3, 234, 5, 133, 94, 136, 71, 141, 204, 235, 83, 49, 224, 253, 202, 79, 251, 46, 247, 248, 69, 242, 115, 232, 106, 44, 91, 159, 66, 8, 110, 99, 12, 165, 20, 18, 119, 30, 27, 50, 45, 169, 75, 196, 125, 241, 37, 59, 233, 184, 217, 221, 19, 197, 203, 157, 167, 176, 107, 122, 7, 32, 183, 139, 48, 146, 80, 72, 219, 120, 108, 200, 180, 162, 43, 13, 243, 193, 148, 236, 161, 222, 97, 113, 76, 17, 41, 114, 154, 190, 171, 231, 28, 128, 218, 42, 192, 70, 63, 31, 105, 223, 175, 29, 206, 134, 172, 52, 201, 1], +[1, 79, 73, 113, 189, 25, 176, 26, 255, 99, 111, 31, 136, 207, 162, 205, 4, 59, 35, 195, 242, 100, 190, 104, 249, 139, 187, 124, 30, 57, 134, 49, 16, 236, 140, 9, 197, 143, 246, 159, 225, 42, 234, 239, 120, 228, 22, 196, 64, 173, 46, 36, 17, 58, 213, 122, 129, 168, 165, 185, 223, 141, 88, 13, 256, 178, 184, 144, 68, 232, 81, 231, 2, 158, 146, 226, 121, 50, 95, 52, 253, 198, 222, 62, 15, 157, 67, 153, 8, 118, 70, 133, 227, 200, 123, 208, 241, 21, 117, 248, 60, 114, 11, 98, 32, 215, 23, 18, 137, 29, 235, 61, 193, 84, 211, 221, 240, 199, 44, 135, 128, 89, 92, 72, 34, 116, 169, 244, 1, 79, 73, 113, 189, 25, 176, 26, 255, 99, 111, 31, 136, 207, 162, 205, 4, 59, 35, 195, 242, 100, 190, 104, 249, 139, 187, 124, 30, 57, 134, 49, 16, 236, 140, 9, 197, 143, 246, 159, 225, 42, 234, 239, 120, 228, 22, 196, 64, 173, 46, 36, 17, 58, 213, 122, 129, 168, 165, 185, 223, 141, 88, 13, 256, 178, 184, 144, 68, 232, 81, 231, 2, 158, 146, 226, 121, 50, 95, 52, 253, 198, 222, 62, 15, 157, 67, 153, 8, 118, 70, 133, 227, 200, 123, 208, 241, 21, 117, 248, 60, 114, 11, 98, 32, 215, 23, 18, 137, 29, 235, 61, 193, 84, 211, 221, 240, 199, 44, 135, 128, 89, 92, 72, 34, 116, 169, 244, 1], +[1, 80, 232, 56, 111, 142, 52, 48, 242, 85, 118, 188, 134, 183, 248, 51, 225, 10, 29, 7, 46, 82, 135, 6, 223, 107, 79, 152, 81, 55, 31, 167, 253, 194, 100, 33, 70, 203, 49, 65, 60, 174, 42, 19, 235, 39, 36, 53, 128, 217, 141, 229, 73, 186, 231, 233, 136, 86, 198, 163, 190, 37, 133, 103, 16, 252, 114, 125, 234, 216, 61, 254, 17, 75, 89, 181, 88, 101, 113, 45, 2, 160, 207, 112, 222, 27, 104, 96, 227, 170, 236, 119, 11, 109, 239, 102, 193, 20, 58, 14, 92, 164, 13, 12, 189, 214, 158, 47, 162, 110, 62, 77, 249, 131, 200, 66, 140, 149, 98, 130, 120, 91, 84, 38, 213, 78, 72, 106, 256, 177, 25, 201, 146, 115, 205, 209, 15, 172, 139, 69, 123, 74, 9, 206, 32, 247, 228, 250, 211, 175, 122, 251, 34, 150, 178, 105, 176, 202, 226, 90, 4, 63, 157, 224, 187, 54, 208, 192, 197, 83, 215, 238, 22, 218, 221, 204, 129, 40, 116, 28, 184, 71, 26, 24, 121, 171, 59, 94, 67, 220, 124, 154, 241, 5, 143, 132, 23, 41, 196, 3, 240, 182, 168, 76, 169, 156, 144, 212, 255, 97, 50, 145, 35, 230, 153, 161, 30, 87, 21, 138, 246, 148, 18, 155, 64, 237, 199, 243, 165, 93, 244, 245, 68, 43, 99, 210, 95, 147, 195, 180, 8, 126, 57, 191, 117, 108, 159, 127, 137, 166, 173, 219, 44, 179, 185, 151, 1], +[1, 81, 136, 222, 249, 123, 197, 23, 64, 44, 223, 73, 2, 162, 15, 187, 241, 246, 137, 46, 128, 88, 189, 146, 4, 67, 30, 117, 225, 235, 17, 92, 256, 176, 121, 35, 8, 134, 60, 234, 193, 213, 34, 184, 255, 95, 242, 70, 16, 11, 120, 211, 129, 169, 68, 111, 253, 190, 227, 140, 32, 22, 240, 165, 1, 81, 136, 222, 249, 123, 197, 23, 64, 44, 223, 73, 2, 162, 15, 187, 241, 246, 137, 46, 128, 88, 189, 146, 4, 67, 30, 117, 225, 235, 17, 92, 256, 176, 121, 35, 8, 134, 60, 234, 193, 213, 34, 184, 255, 95, 242, 70, 16, 11, 120, 211, 129, 169, 68, 111, 253, 190, 227, 140, 32, 22, 240, 165, 1, 81, 136, 222, 249, 123, 197, 23, 64, 44, 223, 73, 2, 162, 15, 187, 241, 246, 137, 46, 128, 88, 189, 146, 4, 67, 30, 117, 225, 235, 17, 92, 256, 176, 121, 35, 8, 134, 60, 234, 193, 213, 34, 184, 255, 95, 242, 70, 16, 11, 120, 211, 129, 169, 68, 111, 253, 190, 227, 140, 32, 22, 240, 165, 1, 81, 136, 222, 249, 123, 197, 23, 64, 44, 223, 73, 2, 162, 15, 187, 241, 246, 137, 46, 128, 88, 189, 146, 4, 67, 30, 117, 225, 235, 17, 92, 256, 176, 121, 35, 8, 134, 60, 234, 193, 213, 34, 184, 255, 95, 242, 70, 16, 11, 120, 211, 129, 169, 68, 111, 253, 190, 227, 140, 32, 22, 240, 165, 1], +[1, 82, 42, 103, 222, 214, 72, 250, 197, 220, 50, 245, 44, 10, 49, 163, 2, 164, 84, 206, 187, 171, 144, 243, 137, 183, 100, 233, 88, 20, 98, 69, 4, 71, 168, 155, 117, 85, 31, 229, 17, 109, 200, 209, 176, 40, 196, 138, 8, 142, 79, 53, 234, 170, 62, 201, 34, 218, 143, 161, 95, 80, 135, 19, 16, 27, 158, 106, 211, 83, 124, 145, 68, 179, 29, 65, 190, 160, 13, 38, 32, 54, 59, 212, 165, 166, 248, 33, 136, 101, 58, 130, 123, 63, 26, 76, 64, 108, 118, 167, 73, 75, 239, 66, 15, 202, 116, 3, 246, 126, 52, 152, 128, 216, 236, 77, 146, 150, 221, 132, 30, 147, 232, 6, 235, 252, 104, 47, 256, 175, 215, 154, 35, 43, 185, 7, 60, 37, 207, 12, 213, 247, 208, 94, 255, 93, 173, 51, 70, 86, 113, 14, 120, 74, 157, 24, 169, 237, 159, 188, 253, 186, 89, 102, 140, 172, 226, 28, 240, 148, 57, 48, 81, 217, 61, 119, 249, 115, 178, 204, 23, 87, 195, 56, 223, 39, 114, 96, 162, 177, 122, 238, 241, 230, 99, 151, 46, 174, 133, 112, 189, 78, 228, 192, 67, 97, 244, 219, 225, 203, 198, 45, 92, 91, 9, 224, 121, 156, 199, 127, 134, 194, 231, 181, 193, 149, 139, 90, 184, 182, 18, 191, 242, 55, 141, 254, 11, 131, 205, 105, 129, 41, 21, 180, 111, 107, 36, 125, 227, 110, 25, 251, 22, 5, 153, 210, 1], +[1, 83, 207, 219, 187, 101, 159, 90, 17, 126, 178, 125, 95, 175, 133, 245, 32, 86, 199, 69, 73, 148, 205, 53, 30, 177, 42, 145, 213, 203, 144, 130, 253, 182, 200, 152, 23, 110, 135, 154, 189, 10, 59, 14, 134, 71, 239, 48, 129, 170, 232, 238, 222, 179, 208, 45, 137, 63, 89, 191, 176, 216, 195, 251, 16, 43, 228, 163, 165, 74, 231, 155, 15, 217, 21, 201, 235, 230, 72, 65, 255, 91, 100, 76, 140, 55, 196, 77, 223, 5, 158, 7, 67, 164, 248, 24, 193, 85, 116, 119, 111, 218, 104, 151, 197, 160, 173, 224, 88, 108, 226, 254, 8, 150, 114, 210, 211, 37, 244, 206, 136, 237, 139, 229, 246, 115, 36, 161, 256, 174, 50, 38, 70, 156, 98, 167, 240, 131, 79, 132, 162, 82, 124, 12, 225, 171, 58, 188, 184, 109, 52, 204, 227, 80, 215, 112, 44, 54, 113, 127, 4, 75, 57, 105, 234, 147, 122, 103, 68, 247, 198, 243, 123, 186, 18, 209, 128, 87, 25, 19, 35, 78, 49, 212, 120, 194, 168, 66, 81, 41, 62, 6, 241, 214, 29, 94, 92, 183, 26, 102, 242, 40, 236, 56, 22, 27, 185, 192, 2, 166, 157, 181, 117, 202, 61, 180, 34, 252, 99, 250, 190, 93, 9, 233, 64, 172, 141, 138, 146, 39, 153, 106, 60, 97, 84, 33, 169, 149, 31, 3, 249, 107, 143, 47, 46, 220, 13, 51, 121, 20, 118, 28, 11, 142, 221, 96, 1], +[1, 84, 117, 62, 68, 58, 246, 104, 255, 89, 23, 133, 121, 141, 22, 49, 4, 79, 211, 248, 15, 232, 213, 159, 249, 99, 92, 18, 227, 50, 88, 196, 16, 59, 73, 221, 60, 157, 81, 122, 225, 139, 111, 72, 137, 200, 95, 13, 64, 236, 35, 113, 240, 114, 67, 231, 129, 42, 187, 31, 34, 29, 123, 52, 256, 173, 140, 195, 189, 199, 11, 153, 2, 168, 234, 124, 136, 116, 235, 208, 253, 178, 46, 9, 242, 25, 44, 98, 8, 158, 165, 239, 30, 207, 169, 61, 241, 198, 184, 36, 197, 100, 176, 135, 32, 118, 146, 185, 120, 57, 162, 244, 193, 21, 222, 144, 17, 143, 190, 26, 128, 215, 70, 226, 223, 228, 134, 205, 1, 84, 117, 62, 68, 58, 246, 104, 255, 89, 23, 133, 121, 141, 22, 49, 4, 79, 211, 248, 15, 232, 213, 159, 249, 99, 92, 18, 227, 50, 88, 196, 16, 59, 73, 221, 60, 157, 81, 122, 225, 139, 111, 72, 137, 200, 95, 13, 64, 236, 35, 113, 240, 114, 67, 231, 129, 42, 187, 31, 34, 29, 123, 52, 256, 173, 140, 195, 189, 199, 11, 153, 2, 168, 234, 124, 136, 116, 235, 208, 253, 178, 46, 9, 242, 25, 44, 98, 8, 158, 165, 239, 30, 207, 169, 61, 241, 198, 184, 36, 197, 100, 176, 135, 32, 118, 146, 185, 120, 57, 162, 244, 193, 21, 222, 144, 17, 143, 190, 26, 128, 215, 70, 226, 223, 228, 134, 205, 1], +[1, 85, 29, 152, 70, 39, 231, 103, 17, 160, 236, 14, 162, 149, 72, 209, 32, 150, 157, 238, 184, 220, 196, 212, 30, 237, 99, 191, 44, 142, 248, 6, 253, 174, 141, 163, 234, 101, 104, 102, 189, 131, 84, 201, 123, 175, 226, 192, 129, 171, 143, 76, 35, 148, 244, 180, 137, 80, 118, 7, 81, 203, 36, 233, 16, 75, 207, 119, 92, 110, 98, 106, 15, 247, 178, 224, 22, 71, 124, 3, 255, 87, 199, 210, 117, 179, 52, 51, 223, 194, 42, 229, 190, 216, 113, 96, 193, 214, 200, 38, 146, 74, 122, 90, 197, 40, 59, 132, 169, 230, 18, 245, 8, 166, 232, 188, 46, 55, 49, 53, 136, 252, 89, 112, 11, 164, 62, 130, 256, 172, 228, 105, 187, 218, 26, 154, 240, 97, 21, 243, 95, 108, 185, 48, 225, 107, 100, 19, 73, 37, 61, 45, 227, 20, 158, 66, 213, 115, 9, 251, 4, 83, 116, 94, 23, 156, 153, 155, 68, 126, 173, 56, 134, 82, 31, 65, 128, 86, 114, 181, 222, 109, 13, 77, 120, 177, 139, 250, 176, 54, 221, 24, 241, 182, 50, 138, 165, 147, 159, 151, 242, 10, 79, 33, 235, 186, 133, 254, 2, 170, 58, 47, 140, 78, 205, 206, 34, 63, 215, 28, 67, 41, 144, 161, 64, 43, 57, 219, 111, 183, 135, 167, 60, 217, 198, 125, 88, 27, 239, 12, 249, 91, 25, 69, 211, 202, 208, 204, 121, 5, 168, 145, 246, 93, 195, 127, 1], +[1, 86, 200, 238, 165, 55, 104, 206, 240, 80, 198, 66, 22, 93, 31, 96, 32, 182, 232, 163, 140, 218, 244, 167, 227, 247, 168, 56, 190, 149, 221, 245, 253, 170, 228, 76, 111, 37, 98, 204, 68, 194, 236, 250, 169, 142, 133, 130, 129, 43, 100, 119, 211, 156, 52, 103, 120, 40, 99, 33, 11, 175, 144, 48, 16, 91, 116, 210, 70, 109, 122, 212, 242, 252, 84, 28, 95, 203, 239, 251, 255, 85, 114, 38, 184, 147, 49, 102, 34, 97, 118, 125, 213, 71, 195, 65, 193, 150, 50, 188, 234, 78, 26, 180, 60, 20, 178, 145, 134, 216, 72, 24, 8, 174, 58, 105, 35, 183, 61, 106, 121, 126, 42, 14, 176, 230, 248, 254, 256, 171, 57, 19, 92, 202, 153, 51, 17, 177, 59, 191, 235, 164, 226, 161, 225, 75, 25, 94, 117, 39, 13, 90, 30, 10, 89, 201, 67, 108, 36, 12, 4, 87, 29, 181, 146, 220, 159, 53, 189, 63, 21, 7, 88, 115, 124, 127, 128, 214, 157, 138, 46, 101, 205, 154, 137, 217, 158, 224, 246, 82, 113, 209, 241, 166, 141, 47, 187, 148, 135, 45, 15, 5, 173, 229, 162, 54, 18, 6, 2, 172, 143, 219, 73, 110, 208, 155, 223, 160, 139, 132, 44, 186, 62, 192, 64, 107, 207, 69, 23, 179, 231, 77, 197, 237, 79, 112, 123, 41, 185, 233, 249, 83, 199, 152, 222, 74, 196, 151, 136, 131, 215, 243, 81, 27, 9, 3, 1], +[1, 87, 116, 69, 92, 37, 135, 180, 240, 63, 84, 112, 235, 142, 18, 24, 32, 214, 114, 152, 117, 156, 208, 106, 227, 217, 118, 243, 67, 175, 62, 254, 253, 166, 50, 238, 146, 109, 231, 51, 68, 5, 178, 66, 88, 203, 185, 161, 129, 172, 58, 163, 46, 147, 196, 90, 120, 160, 42, 56, 246, 71, 9, 12, 16, 107, 57, 76, 187, 78, 104, 53, 242, 237, 59, 250, 162, 216, 31, 127, 255, 83, 25, 119, 73, 183, 244, 154, 34, 131, 89, 33, 44, 230, 221, 209, 193, 86, 29, 210, 23, 202, 98, 45, 60, 80, 21, 28, 123, 164, 133, 6, 8, 182, 157, 38, 222, 39, 52, 155, 121, 247, 158, 125, 81, 108, 144, 192, 256, 170, 141, 188, 165, 220, 122, 77, 17, 194, 173, 145, 22, 115, 239, 233, 225, 43, 143, 105, 140, 101, 49, 151, 30, 40, 139, 14, 190, 82, 195, 3, 4, 91, 207, 19, 111, 148, 26, 206, 189, 252, 79, 191, 169, 54, 72, 96, 128, 85, 199, 94, 211, 110, 61, 167, 137, 97, 215, 201, 11, 186, 248, 245, 241, 150, 200, 181, 70, 179, 153, 204, 15, 20, 198, 7, 95, 41, 226, 130, 2, 174, 232, 138, 184, 74, 13, 103, 223, 126, 168, 224, 213, 27, 36, 48, 64, 171, 228, 47, 234, 55, 159, 212, 197, 177, 236, 229, 134, 93, 124, 251, 249, 75, 100, 219, 35, 218, 205, 102, 136, 10, 99, 132, 176, 149, 113, 65, 1], +[1, 88, 34, 165, 128, 213, 240, 46, 193, 22, 137, 234, 32, 246, 60, 140, 241, 134, 227, 187, 8, 190, 15, 35, 253, 162, 121, 111, 2, 176, 68, 73, 256, 169, 223, 92, 129, 44, 17, 211, 64, 235, 120, 23, 225, 11, 197, 117, 16, 123, 30, 70, 249, 67, 242, 222, 4, 95, 136, 146, 255, 81, 189, 184, 1, 88, 34, 165, 128, 213, 240, 46, 193, 22, 137, 234, 32, 246, 60, 140, 241, 134, 227, 187, 8, 190, 15, 35, 253, 162, 121, 111, 2, 176, 68, 73, 256, 169, 223, 92, 129, 44, 17, 211, 64, 235, 120, 23, 225, 11, 197, 117, 16, 123, 30, 70, 249, 67, 242, 222, 4, 95, 136, 146, 255, 81, 189, 184, 1, 88, 34, 165, 128, 213, 240, 46, 193, 22, 137, 234, 32, 246, 60, 140, 241, 134, 227, 187, 8, 190, 15, 35, 253, 162, 121, 111, 2, 176, 68, 73, 256, 169, 223, 92, 129, 44, 17, 211, 64, 235, 120, 23, 225, 11, 197, 117, 16, 123, 30, 70, 249, 67, 242, 222, 4, 95, 136, 146, 255, 81, 189, 184, 1, 88, 34, 165, 128, 213, 240, 46, 193, 22, 137, 234, 32, 246, 60, 140, 241, 134, 227, 187, 8, 190, 15, 35, 253, 162, 121, 111, 2, 176, 68, 73, 256, 169, 223, 92, 129, 44, 17, 211, 64, 235, 120, 23, 225, 11, 197, 117, 16, 123, 30, 70, 249, 67, 242, 222, 4, 95, 136, 146, 255, 81, 189, 184, 1], +[1, 89, 211, 18, 60, 200, 67, 52, 2, 178, 165, 36, 120, 143, 134, 104, 4, 99, 73, 72, 240, 29, 11, 208, 8, 198, 146, 144, 223, 58, 22, 159, 16, 139, 35, 31, 189, 116, 44, 61, 32, 21, 70, 62, 121, 232, 88, 122, 64, 42, 140, 124, 242, 207, 176, 244, 128, 84, 23, 248, 227, 157, 95, 231, 256, 168, 46, 239, 197, 57, 190, 205, 255, 79, 92, 221, 137, 114, 123, 153, 253, 158, 184, 185, 17, 228, 246, 49, 249, 59, 111, 113, 34, 199, 235, 98, 241, 118, 222, 226, 68, 141, 213, 196, 225, 236, 187, 195, 136, 25, 169, 135, 193, 215, 117, 133, 15, 50, 81, 13, 129, 173, 234, 9, 30, 100, 162, 26, 1, 89, 211, 18, 60, 200, 67, 52, 2, 178, 165, 36, 120, 143, 134, 104, 4, 99, 73, 72, 240, 29, 11, 208, 8, 198, 146, 144, 223, 58, 22, 159, 16, 139, 35, 31, 189, 116, 44, 61, 32, 21, 70, 62, 121, 232, 88, 122, 64, 42, 140, 124, 242, 207, 176, 244, 128, 84, 23, 248, 227, 157, 95, 231, 256, 168, 46, 239, 197, 57, 190, 205, 255, 79, 92, 221, 137, 114, 123, 153, 253, 158, 184, 185, 17, 228, 246, 49, 249, 59, 111, 113, 34, 199, 235, 98, 241, 118, 222, 226, 68, 141, 213, 196, 225, 236, 187, 195, 136, 25, 169, 135, 193, 215, 117, 133, 15, 50, 81, 13, 129, 173, 234, 9, 30, 100, 162, 26, 1], +[1, 90, 133, 148, 213, 152, 59, 170, 137, 251, 231, 230, 140, 7, 116, 160, 8, 206, 36, 156, 162, 188, 215, 75, 68, 209, 49, 41, 92, 56, 157, 252, 64, 106, 31, 220, 11, 219, 178, 86, 30, 130, 135, 71, 222, 191, 228, 217, 255, 77, 248, 218, 88, 210, 139, 174, 240, 12, 52, 54, 234, 243, 25, 194, 241, 102, 185, 202, 190, 138, 84, 107, 121, 96, 159, 175, 73, 145, 200, 10, 129, 45, 195, 74, 235, 76, 158, 85, 197, 254, 244, 115, 70, 132, 58, 80, 4, 103, 18, 78, 81, 94, 236, 166, 34, 233, 153, 149, 46, 28, 207, 126, 32, 53, 144, 110, 134, 238, 89, 43, 15, 65, 196, 164, 111, 224, 114, 237, 256, 167, 124, 109, 44, 105, 198, 87, 120, 6, 26, 27, 117, 250, 141, 97, 249, 51, 221, 101, 95, 69, 42, 182, 189, 48, 208, 216, 165, 201, 100, 5, 193, 151, 226, 37, 246, 38, 79, 171, 227, 127, 122, 186, 35, 66, 29, 40, 2, 180, 9, 39, 169, 47, 118, 83, 17, 245, 205, 203, 23, 14, 232, 63, 16, 155, 72, 55, 67, 119, 173, 150, 136, 161, 98, 82, 184, 112, 57, 247, 128, 212, 62, 183, 22, 181, 99, 172, 60, 3, 13, 142, 187, 125, 199, 177, 253, 154, 239, 179, 176, 163, 21, 91, 223, 24, 104, 108, 211, 229, 50, 131, 225, 204, 113, 147, 123, 19, 168, 214, 242, 192, 61, 93, 146, 33, 143, 20, 1], +[1, 91, 57, 47, 165, 109, 153, 45, 240, 252, 59, 229, 22, 203, 226, 6, 32, 85, 25, 219, 140, 147, 13, 155, 227, 97, 89, 132, 190, 71, 36, 192, 253, 150, 29, 69, 111, 78, 159, 77, 68, 20, 21, 112, 169, 216, 124, 233, 129, 174, 157, 152, 211, 183, 205, 151, 120, 126, 158, 243, 11, 230, 113, 3, 16, 171, 141, 238, 70, 202, 135, 206, 242, 177, 173, 66, 95, 164, 18, 96, 255, 75, 143, 163, 184, 39, 208, 167, 34, 10, 139, 56, 213, 108, 62, 245, 193, 87, 207, 76, 234, 220, 231, 204, 60, 63, 79, 250, 134, 115, 185, 130, 8, 214, 199, 119, 35, 101, 196, 103, 121, 217, 215, 33, 176, 82, 9, 48, 256, 166, 200, 210, 92, 148, 104, 212, 17, 5, 198, 28, 235, 54, 31, 251, 225, 172, 232, 38, 117, 110, 244, 102, 30, 160, 168, 125, 67, 186, 221, 65, 4, 107, 228, 188, 146, 179, 98, 180, 189, 237, 236, 145, 88, 41, 133, 24, 128, 83, 100, 105, 46, 74, 52, 106, 137, 131, 99, 14, 246, 27, 144, 254, 241, 86, 116, 19, 187, 55, 122, 51, 15, 80, 84, 191, 162, 93, 239, 161, 2, 182, 114, 94, 73, 218, 49, 90, 223, 247, 118, 201, 44, 149, 195, 12, 64, 170, 50, 181, 23, 37, 26, 53, 197, 194, 178, 7, 123, 142, 72, 127, 249, 43, 58, 138, 222, 156, 61, 154, 136, 40, 42, 224, 81, 175, 248, 209, 1], +[1, 92, 240, 235, 32, 117, 227, 67, 253, 146, 68, 88, 129, 46, 120, 246, 16, 187, 242, 162, 255, 73, 34, 44, 193, 23, 60, 123, 8, 222, 121, 81, 256, 165, 17, 22, 225, 140, 30, 190, 4, 111, 189, 169, 128, 211, 137, 11, 241, 70, 15, 95, 2, 184, 223, 213, 64, 234, 197, 134, 249, 35, 136, 176, 1, 92, 240, 235, 32, 117, 227, 67, 253, 146, 68, 88, 129, 46, 120, 246, 16, 187, 242, 162, 255, 73, 34, 44, 193, 23, 60, 123, 8, 222, 121, 81, 256, 165, 17, 22, 225, 140, 30, 190, 4, 111, 189, 169, 128, 211, 137, 11, 241, 70, 15, 95, 2, 184, 223, 213, 64, 234, 197, 134, 249, 35, 136, 176, 1, 92, 240, 235, 32, 117, 227, 67, 253, 146, 68, 88, 129, 46, 120, 246, 16, 187, 242, 162, 255, 73, 34, 44, 193, 23, 60, 123, 8, 222, 121, 81, 256, 165, 17, 22, 225, 140, 30, 190, 4, 111, 189, 169, 128, 211, 137, 11, 241, 70, 15, 95, 2, 184, 223, 213, 64, 234, 197, 134, 249, 35, 136, 176, 1, 92, 240, 235, 32, 117, 227, 67, 253, 146, 68, 88, 129, 46, 120, 246, 16, 187, 242, 162, 255, 73, 34, 44, 193, 23, 60, 123, 8, 222, 121, 81, 256, 165, 17, 22, 225, 140, 30, 190, 4, 111, 189, 169, 128, 211, 137, 11, 241, 70, 15, 95, 2, 184, 223, 213, 64, 234, 197, 134, 249, 35, 136, 176, 1], +[1, 93, 168, 204, 211, 91, 239, 125, 60, 183, 57, 161, 67, 63, 205, 47, 2, 186, 79, 151, 165, 182, 221, 250, 120, 109, 114, 65, 134, 126, 153, 94, 4, 115, 158, 45, 73, 107, 185, 243, 240, 218, 228, 130, 11, 252, 49, 188, 8, 230, 59, 90, 146, 214, 113, 229, 223, 179, 199, 3, 22, 247, 98, 119, 16, 203, 118, 180, 35, 171, 226, 201, 189, 101, 141, 6, 44, 237, 196, 238, 32, 149, 236, 103, 70, 85, 195, 145, 121, 202, 25, 12, 88, 217, 135, 219, 64, 41, 215, 206, 140, 170, 133, 33, 242, 147, 50, 24, 176, 177, 13, 181, 128, 82, 173, 155, 23, 83, 9, 66, 227, 37, 100, 48, 95, 97, 26, 105, 256, 164, 89, 53, 46, 166, 18, 132, 197, 74, 200, 96, 190, 194, 52, 210, 255, 71, 178, 106, 92, 75, 36, 7, 137, 148, 143, 192, 123, 131, 104, 163, 253, 142, 99, 212, 184, 150, 72, 14, 17, 39, 29, 127, 246, 5, 208, 69, 249, 27, 198, 167, 111, 43, 144, 28, 34, 78, 58, 254, 235, 10, 159, 138, 241, 54, 139, 77, 222, 86, 31, 56, 68, 156, 116, 251, 213, 20, 61, 19, 225, 108, 21, 154, 187, 172, 62, 112, 136, 55, 232, 245, 169, 40, 122, 38, 193, 216, 42, 51, 117, 87, 124, 224, 15, 110, 207, 233, 81, 80, 244, 76, 129, 175, 84, 102, 234, 174, 248, 191, 30, 220, 157, 209, 162, 160, 231, 152, 1], +[1, 94, 98, 217, 95, 192, 58, 55, 30, 250, 113, 85, 23, 106, 198, 108, 129, 47, 49, 237, 176, 96, 29, 156, 15, 125, 185, 171, 140, 53, 99, 54, 193, 152, 153, 247, 88, 48, 143, 78, 136, 191, 221, 214, 70, 155, 178, 27, 225, 76, 205, 252, 44, 24, 200, 39, 68, 224, 239, 107, 35, 206, 89, 142, 241, 38, 231, 126, 22, 12, 100, 148, 34, 112, 248, 182, 146, 103, 173, 71, 249, 19, 244, 63, 11, 6, 50, 74, 17, 56, 124, 91, 73, 180, 215, 164, 253, 138, 122, 160, 134, 3, 25, 37, 137, 28, 62, 174, 165, 90, 236, 82, 255, 69, 61, 80, 67, 130, 141, 147, 197, 14, 31, 87, 211, 45, 118, 41, 256, 163, 159, 40, 162, 65, 199, 202, 227, 7, 144, 172, 234, 151, 59, 149, 128, 210, 208, 20, 81, 161, 228, 101, 242, 132, 72, 86, 117, 204, 158, 203, 64, 105, 104, 10, 169, 209, 114, 179, 121, 66, 36, 43, 187, 102, 79, 230, 32, 181, 52, 5, 213, 233, 57, 218, 189, 33, 18, 150, 222, 51, 168, 115, 16, 219, 26, 131, 235, 245, 157, 109, 223, 145, 9, 75, 111, 154, 84, 186, 8, 238, 13, 194, 246, 251, 207, 183, 240, 201, 133, 166, 184, 77, 42, 93, 4, 119, 135, 97, 123, 254, 232, 220, 120, 229, 195, 83, 92, 167, 21, 175, 2, 188, 196, 177, 190, 127, 116, 110, 60, 243, 226, 170, 46, 212, 139, 216, 1], +[1, 95, 30, 23, 129, 176, 15, 140, 193, 88, 136, 70, 225, 44, 68, 35, 241, 22, 34, 146, 249, 11, 17, 73, 253, 134, 137, 165, 255, 67, 197, 211, 256, 162, 227, 234, 128, 81, 242, 117, 64, 169, 121, 187, 32, 213, 189, 222, 16, 235, 223, 111, 8, 246, 240, 184, 4, 123, 120, 92, 2, 190, 60, 46, 1, 95, 30, 23, 129, 176, 15, 140, 193, 88, 136, 70, 225, 44, 68, 35, 241, 22, 34, 146, 249, 11, 17, 73, 253, 134, 137, 165, 255, 67, 197, 211, 256, 162, 227, 234, 128, 81, 242, 117, 64, 169, 121, 187, 32, 213, 189, 222, 16, 235, 223, 111, 8, 246, 240, 184, 4, 123, 120, 92, 2, 190, 60, 46, 1, 95, 30, 23, 129, 176, 15, 140, 193, 88, 136, 70, 225, 44, 68, 35, 241, 22, 34, 146, 249, 11, 17, 73, 253, 134, 137, 165, 255, 67, 197, 211, 256, 162, 227, 234, 128, 81, 242, 117, 64, 169, 121, 187, 32, 213, 189, 222, 16, 235, 223, 111, 8, 246, 240, 184, 4, 123, 120, 92, 2, 190, 60, 46, 1, 95, 30, 23, 129, 176, 15, 140, 193, 88, 136, 70, 225, 44, 68, 35, 241, 22, 34, 146, 249, 11, 17, 73, 253, 134, 137, 165, 255, 67, 197, 211, 256, 162, 227, 234, 128, 81, 242, 117, 64, 169, 121, 187, 32, 213, 189, 222, 16, 235, 223, 111, 8, 246, 240, 184, 4, 123, 120, 92, 2, 190, 60, 46, 1], +[1, 96, 221, 142, 11, 28, 118, 20, 121, 51, 13, 220, 46, 47, 143, 107, 249, 3, 31, 149, 169, 33, 84, 97, 60, 106, 153, 39, 146, 138, 141, 172, 64, 233, 9, 93, 190, 250, 99, 252, 34, 180, 61, 202, 117, 181, 157, 166, 2, 192, 185, 27, 22, 56, 236, 40, 242, 102, 26, 183, 92, 94, 29, 214, 241, 6, 62, 41, 81, 66, 168, 194, 120, 212, 49, 78, 35, 19, 25, 87, 128, 209, 18, 186, 123, 243, 198, 247, 68, 103, 122, 147, 234, 105, 57, 75, 4, 127, 113, 54, 44, 112, 215, 80, 227, 204, 52, 109, 184, 188, 58, 171, 225, 12, 124, 82, 162, 132, 79, 131, 240, 167, 98, 156, 70, 38, 50, 174, 256, 161, 36, 115, 246, 229, 139, 237, 136, 206, 244, 37, 211, 210, 114, 150, 8, 254, 226, 108, 88, 224, 173, 160, 197, 151, 104, 218, 111, 119, 116, 85, 193, 24, 248, 164, 67, 7, 158, 5, 223, 77, 196, 55, 140, 76, 100, 91, 255, 65, 72, 230, 235, 201, 21, 217, 15, 155, 231, 74, 165, 163, 228, 43, 16, 251, 195, 216, 176, 191, 89, 63, 137, 45, 208, 179, 222, 238, 232, 170, 129, 48, 239, 71, 134, 14, 59, 10, 189, 154, 135, 110, 23, 152, 200, 182, 253, 130, 144, 203, 213, 145, 42, 177, 30, 53, 205, 148, 73, 69, 199, 86, 32, 245, 133, 175, 95, 125, 178, 126, 17, 90, 159, 101, 187, 219, 207, 83, 1], +[1, 97, 157, 66, 234, 82, 244, 24, 15, 170, 42, 219, 169, 202, 62, 103, 225, 237, 116, 201, 222, 203, 159, 3, 34, 214, 198, 188, 246, 218, 72, 45, 253, 126, 143, 250, 92, 186, 52, 161, 197, 91, 89, 152, 95, 220, 9, 102, 128, 80, 50, 224, 140, 216, 135, 245, 121, 172, 236, 19, 44, 156, 226, 77, 16, 10, 199, 28, 146, 27, 49, 127, 240, 150, 158, 163, 134, 148, 221, 106, 2, 194, 57, 132, 211, 164, 231, 48, 30, 83, 84, 181, 81, 147, 124, 206, 193, 217, 232, 145, 187, 149, 61, 6, 68, 171, 139, 119, 235, 179, 144, 90, 249, 252, 29, 243, 184, 115, 104, 65, 137, 182, 178, 47, 190, 183, 18, 204, 256, 160, 100, 191, 23, 175, 13, 233, 242, 87, 215, 38, 88, 55, 195, 154, 32, 20, 141, 56, 35, 54, 98, 254, 223, 43, 59, 69, 11, 39, 185, 212, 4, 131, 114, 7, 165, 71, 205, 96, 60, 166, 168, 105, 162, 37, 248, 155, 129, 177, 207, 33, 117, 41, 122, 12, 136, 85, 21, 238, 213, 101, 31, 180, 241, 247, 58, 229, 111, 230, 208, 130, 17, 107, 99, 94, 123, 109, 36, 151, 255, 63, 200, 125, 46, 93, 26, 209, 227, 174, 173, 76, 176, 110, 133, 51, 64, 40, 25, 112, 70, 108, 196, 251, 189, 86, 118, 138, 22, 78, 113, 167, 8, 5, 228, 14, 73, 142, 153, 192, 120, 75, 79, 210, 67, 74, 239, 53, 1], +[1, 98, 95, 58, 30, 113, 23, 198, 129, 49, 176, 29, 15, 185, 140, 99, 193, 153, 88, 143, 136, 221, 70, 178, 225, 205, 44, 200, 68, 239, 35, 89, 241, 231, 22, 100, 34, 248, 146, 173, 249, 244, 11, 50, 17, 124, 73, 215, 253, 122, 134, 25, 137, 62, 165, 236, 255, 61, 67, 141, 197, 31, 211, 118, 256, 159, 162, 199, 227, 144, 234, 59, 128, 208, 81, 228, 242, 72, 117, 158, 64, 104, 169, 114, 121, 36, 187, 79, 32, 52, 213, 57, 189, 18, 222, 168, 16, 26, 235, 157, 223, 9, 111, 84, 8, 13, 246, 207, 240, 133, 184, 42, 4, 135, 123, 232, 120, 195, 92, 21, 2, 196, 190, 116, 60, 226, 46, 139, 1, 98, 95, 58, 30, 113, 23, 198, 129, 49, 176, 29, 15, 185, 140, 99, 193, 153, 88, 143, 136, 221, 70, 178, 225, 205, 44, 200, 68, 239, 35, 89, 241, 231, 22, 100, 34, 248, 146, 173, 249, 244, 11, 50, 17, 124, 73, 215, 253, 122, 134, 25, 137, 62, 165, 236, 255, 61, 67, 141, 197, 31, 211, 118, 256, 159, 162, 199, 227, 144, 234, 59, 128, 208, 81, 228, 242, 72, 117, 158, 64, 104, 169, 114, 121, 36, 187, 79, 32, 52, 213, 57, 189, 18, 222, 168, 16, 26, 235, 157, 223, 9, 111, 84, 8, 13, 246, 207, 240, 133, 184, 42, 4, 135, 123, 232, 120, 195, 92, 21, 2, 196, 190, 116, 60, 226, 46, 139, 1], +[1, 99, 35, 124, 197, 228, 213, 13, 2, 198, 70, 248, 137, 199, 169, 26, 4, 139, 140, 239, 17, 141, 81, 52, 8, 21, 23, 221, 34, 25, 162, 104, 16, 42, 46, 185, 68, 50, 67, 208, 32, 84, 92, 113, 136, 100, 134, 159, 64, 168, 184, 226, 15, 200, 11, 61, 128, 79, 111, 195, 30, 143, 22, 122, 256, 158, 222, 133, 60, 29, 44, 244, 255, 59, 187, 9, 120, 58, 88, 231, 253, 118, 117, 18, 240, 116, 176, 205, 249, 236, 234, 36, 223, 232, 95, 153, 241, 215, 211, 72, 189, 207, 190, 49, 225, 173, 165, 144, 121, 157, 123, 98, 193, 89, 73, 31, 242, 57, 246, 196, 129, 178, 146, 62, 227, 114, 235, 135, 1, 99, 35, 124, 197, 228, 213, 13, 2, 198, 70, 248, 137, 199, 169, 26, 4, 139, 140, 239, 17, 141, 81, 52, 8, 21, 23, 221, 34, 25, 162, 104, 16, 42, 46, 185, 68, 50, 67, 208, 32, 84, 92, 113, 136, 100, 134, 159, 64, 168, 184, 226, 15, 200, 11, 61, 128, 79, 111, 195, 30, 143, 22, 122, 256, 158, 222, 133, 60, 29, 44, 244, 255, 59, 187, 9, 120, 58, 88, 231, 253, 118, 117, 18, 240, 116, 176, 205, 249, 236, 234, 36, 223, 232, 95, 153, 241, 215, 211, 72, 189, 207, 190, 49, 225, 173, 165, 144, 121, 157, 123, 98, 193, 89, 73, 31, 242, 57, 246, 196, 129, 178, 146, 62, 227, 114, 235, 135, 1], +[1, 100, 234, 13, 15, 215, 169, 195, 225, 141, 222, 98, 34, 59, 246, 185, 253, 114, 92, 205, 197, 168, 95, 248, 128, 207, 140, 122, 121, 21, 44, 31, 16, 58, 146, 208, 240, 99, 134, 36, 2, 200, 211, 26, 30, 173, 81, 133, 193, 25, 187, 196, 68, 118, 235, 113, 249, 228, 184, 153, 137, 79, 190, 239, 256, 157, 23, 244, 242, 42, 88, 62, 32, 116, 35, 159, 223, 198, 11, 72, 4, 143, 165, 52, 60, 89, 162, 9, 129, 50, 117, 135, 136, 236, 213, 226, 241, 199, 111, 49, 17, 158, 123, 221, 255, 57, 46, 231, 227, 84, 176, 124, 64, 232, 70, 61, 189, 139, 22, 144, 8, 29, 73, 104, 120, 178, 67, 18, 1, 100, 234, 13, 15, 215, 169, 195, 225, 141, 222, 98, 34, 59, 246, 185, 253, 114, 92, 205, 197, 168, 95, 248, 128, 207, 140, 122, 121, 21, 44, 31, 16, 58, 146, 208, 240, 99, 134, 36, 2, 200, 211, 26, 30, 173, 81, 133, 193, 25, 187, 196, 68, 118, 235, 113, 249, 228, 184, 153, 137, 79, 190, 239, 256, 157, 23, 244, 242, 42, 88, 62, 32, 116, 35, 159, 223, 198, 11, 72, 4, 143, 165, 52, 60, 89, 162, 9, 129, 50, 117, 135, 136, 236, 213, 226, 241, 199, 111, 49, 17, 158, 123, 221, 255, 57, 46, 231, 227, 84, 176, 124, 64, 232, 70, 61, 189, 139, 22, 144, 8, 29, 73, 104, 120, 178, 67, 18, 1], +[1, 101, 178, 245, 73, 177, 144, 152, 189, 71, 232, 45, 176, 43, 231, 201, 255, 55, 158, 24, 111, 160, 226, 210, 136, 115, 50, 167, 162, 171, 52, 112, 4, 147, 198, 209, 35, 194, 62, 94, 242, 27, 157, 180, 190, 172, 153, 33, 249, 220, 118, 96, 187, 126, 133, 69, 30, 203, 200, 154, 134, 170, 208, 191, 16, 74, 21, 65, 140, 5, 248, 119, 197, 108, 114, 206, 246, 174, 98, 132, 225, 109, 215, 127, 234, 247, 18, 19, 120, 41, 29, 102, 22, 166, 61, 250, 64, 39, 84, 3, 46, 20, 221, 219, 17, 175, 199, 53, 213, 182, 135, 14, 129, 179, 89, 251, 165, 217, 72, 76, 223, 164, 116, 151, 88, 150, 244, 229, 256, 156, 79, 12, 184, 80, 113, 105, 68, 186, 25, 212, 81, 214, 26, 56, 2, 202, 99, 233, 146, 97, 31, 47, 121, 142, 207, 90, 95, 86, 205, 145, 253, 110, 59, 48, 222, 63, 195, 163, 15, 230, 100, 77, 67, 85, 104, 224, 8, 37, 139, 161, 70, 131, 124, 188, 227, 54, 57, 103, 123, 87, 49, 66, 241, 183, 236, 192, 117, 252, 9, 138, 60, 149, 143, 51, 11, 83, 159, 125, 32, 148, 42, 130, 23, 10, 239, 238, 137, 216, 228, 155, 235, 91, 196, 7, 193, 218, 173, 254, 211, 237, 36, 38, 240, 82, 58, 204, 44, 75, 122, 243, 128, 78, 168, 6, 92, 40, 185, 181, 34, 93, 141, 106, 169, 107, 13, 28, 1], +[1, 102, 124, 55, 213, 138, 198, 150, 137, 96, 26, 82, 140, 145, 141, 247, 8, 45, 221, 183, 162, 76, 42, 172, 68, 254, 208, 142, 92, 132, 100, 177, 64, 103, 226, 179, 11, 94, 79, 91, 30, 233, 122, 108, 222, 28, 29, 131, 255, 53, 9, 147, 88, 238, 118, 214, 240, 65, 205, 93, 234, 224, 232, 20, 241, 167, 72, 148, 190, 105, 173, 170, 121, 6, 98, 230, 73, 250, 57, 160, 129, 51, 62, 156, 235, 69, 99, 75, 197, 48, 13, 41, 70, 201, 199, 252, 4, 151, 239, 220, 81, 38, 21, 86, 34, 127, 104, 71, 46, 66, 50, 217, 32, 180, 113, 218, 134, 47, 168, 174, 15, 245, 61, 54, 111, 14, 143, 194, 256, 155, 133, 202, 44, 119, 59, 107, 120, 161, 231, 175, 117, 112, 116, 10, 249, 212, 36, 74, 95, 181, 215, 85, 189, 3, 49, 115, 165, 125, 157, 80, 193, 154, 31, 78, 246, 163, 178, 166, 227, 24, 135, 149, 35, 229, 228, 126, 2, 204, 248, 110, 169, 19, 139, 43, 17, 192, 52, 164, 23, 33, 25, 237, 16, 90, 185, 109, 67, 152, 84, 87, 136, 251, 159, 27, 184, 7, 200, 97, 128, 206, 195, 101, 22, 188, 158, 182, 60, 209, 244, 216, 187, 56, 58, 5, 253, 106, 18, 37, 176, 219, 236, 171, 223, 130, 153, 186, 211, 191, 207, 40, 225, 77, 144, 39, 123, 210, 89, 83, 242, 12, 196, 203, 146, 243, 114, 63, 1], +[1, 103, 72, 220, 44, 163, 84, 171, 137, 233, 98, 71, 117, 229, 200, 40, 8, 53, 62, 218, 95, 19, 158, 83, 68, 65, 13, 54, 165, 33, 58, 63, 64, 167, 239, 202, 246, 152, 236, 150, 30, 6, 104, 175, 35, 7, 207, 247, 255, 51, 113, 74, 169, 188, 89, 172, 240, 48, 61, 115, 23, 56, 114, 177, 241, 151, 133, 78, 67, 219, 198, 91, 121, 127, 231, 149, 184, 191, 141, 131, 129, 180, 36, 110, 22, 210, 42, 214, 197, 245, 49, 164, 187, 243, 100, 20, 4, 155, 31, 109, 176, 138, 79, 170, 34, 161, 135, 27, 211, 145, 29, 160, 32, 212, 248, 101, 123, 76, 118, 75, 15, 3, 52, 216, 146, 132, 232, 252, 256, 154, 185, 37, 213, 94, 173, 86, 120, 24, 159, 186, 140, 28, 57, 217, 249, 204, 195, 39, 162, 238, 99, 174, 189, 192, 244, 203, 92, 224, 199, 194, 193, 90, 18, 55, 11, 105, 21, 107, 227, 251, 153, 82, 222, 250, 50, 10, 2, 206, 144, 183, 88, 69, 168, 85, 17, 209, 196, 142, 234, 201, 143, 80, 16, 106, 124, 179, 190, 38, 59, 166, 136, 130, 26, 108, 73, 66, 116, 126, 128, 77, 221, 147, 235, 47, 215, 43, 60, 12, 208, 93, 70, 14, 157, 237, 253, 102, 226, 148, 81, 119, 178, 87, 223, 96, 122, 230, 46, 112, 228, 97, 225, 45, 9, 156, 134, 181, 139, 182, 242, 254, 205, 41, 111, 125, 25, 5, 1], +[1, 104, 22, 232, 227, 221, 111, 236, 129, 52, 11, 116, 242, 239, 184, 118, 193, 26, 134, 58, 121, 248, 92, 59, 225, 13, 67, 29, 189, 124, 46, 158, 241, 135, 162, 143, 223, 62, 23, 79, 249, 196, 81, 200, 240, 31, 140, 168, 253, 98, 169, 100, 120, 144, 70, 84, 255, 49, 213, 50, 60, 72, 35, 42, 256, 153, 235, 25, 30, 36, 146, 21, 128, 205, 246, 141, 15, 18, 73, 139, 64, 231, 123, 199, 136, 9, 165, 198, 32, 244, 190, 228, 68, 133, 211, 99, 16, 122, 95, 114, 34, 195, 234, 178, 8, 61, 176, 57, 17, 226, 117, 89, 4, 159, 88, 157, 137, 113, 187, 173, 2, 208, 44, 207, 197, 185, 222, 215, 1, 104, 22, 232, 227, 221, 111, 236, 129, 52, 11, 116, 242, 239, 184, 118, 193, 26, 134, 58, 121, 248, 92, 59, 225, 13, 67, 29, 189, 124, 46, 158, 241, 135, 162, 143, 223, 62, 23, 79, 249, 196, 81, 200, 240, 31, 140, 168, 253, 98, 169, 100, 120, 144, 70, 84, 255, 49, 213, 50, 60, 72, 35, 42, 256, 153, 235, 25, 30, 36, 146, 21, 128, 205, 246, 141, 15, 18, 73, 139, 64, 231, 123, 199, 136, 9, 165, 198, 32, 244, 190, 228, 68, 133, 211, 99, 16, 122, 95, 114, 34, 195, 234, 178, 8, 61, 176, 57, 17, 226, 117, 89, 4, 159, 88, 157, 137, 113, 187, 173, 2, 208, 44, 207, 197, 185, 222, 215, 1], +[1, 105, 231, 97, 162, 48, 157, 37, 30, 66, 248, 83, 234, 155, 84, 82, 129, 181, 244, 177, 81, 24, 207, 147, 15, 33, 124, 170, 117, 206, 42, 41, 193, 219, 122, 217, 169, 12, 232, 202, 136, 145, 62, 85, 187, 103, 21, 149, 225, 238, 61, 237, 213, 6, 116, 101, 68, 201, 31, 171, 222, 180, 139, 203, 241, 119, 159, 247, 235, 3, 58, 179, 34, 229, 144, 214, 111, 90, 198, 230, 249, 188, 208, 252, 246, 130, 29, 218, 17, 243, 72, 107, 184, 45, 99, 115, 253, 94, 104, 126, 123, 65, 143, 109, 137, 250, 36, 182, 92, 151, 178, 186, 255, 47, 52, 63, 190, 161, 200, 183, 197, 125, 18, 91, 46, 204, 89, 93, 256, 152, 26, 160, 95, 209, 100, 220, 227, 191, 9, 174, 23, 102, 173, 175, 128, 76, 13, 80, 176, 233, 50, 110, 242, 224, 133, 87, 140, 51, 215, 216, 64, 38, 135, 40, 88, 245, 25, 55, 121, 112, 195, 172, 70, 154, 236, 108, 32, 19, 196, 20, 44, 251, 141, 156, 189, 56, 226, 86, 35, 77, 118, 54, 16, 138, 98, 10, 22, 254, 199, 78, 223, 28, 113, 43, 146, 167, 59, 27, 8, 69, 49, 5, 11, 127, 228, 39, 240, 14, 185, 150, 73, 212, 158, 142, 4, 163, 153, 131, 134, 192, 114, 148, 120, 7, 221, 75, 165, 106, 79, 71, 2, 210, 205, 194, 67, 96, 57, 74, 60, 132, 239, 166, 211, 53, 168, 164, 1], +[1, 106, 185, 78, 44, 38, 173, 91, 137, 130, 159, 149, 117, 66, 57, 131, 8, 77, 195, 110, 95, 47, 99, 214, 68, 12, 244, 164, 165, 14, 199, 20, 64, 102, 18, 109, 246, 119, 21, 170, 30, 96, 153, 27, 35, 112, 50, 160, 255, 45, 144, 101, 169, 181, 168, 75, 240, 254, 196, 216, 23, 125, 143, 252, 241, 103, 124, 37, 67, 163, 59, 86, 121, 233, 26, 186, 184, 229, 116, 217, 129, 53, 221, 39, 22, 19, 215, 174, 197, 65, 208, 203, 187, 33, 157, 194, 4, 167, 226, 55, 176, 152, 178, 107, 34, 6, 122, 82, 211, 7, 228, 10, 32, 51, 9, 183, 123, 188, 139, 85, 15, 48, 205, 142, 146, 56, 25, 80, 256, 151, 72, 179, 213, 219, 84, 166, 120, 127, 98, 108, 140, 191, 200, 126, 249, 180, 62, 147, 162, 210, 158, 43, 189, 245, 13, 93, 92, 243, 58, 237, 193, 155, 239, 148, 11, 138, 236, 87, 227, 161, 104, 230, 222, 145, 207, 97, 2, 212, 113, 156, 88, 76, 89, 182, 17, 3, 61, 41, 234, 132, 114, 5, 16, 154, 133, 220, 190, 94, 198, 171, 136, 24, 231, 71, 73, 28, 141, 40, 128, 204, 36, 218, 235, 238, 42, 83, 60, 192, 49, 54, 70, 224, 100, 63, 253, 90, 31, 202, 81, 105, 79, 150, 223, 251, 135, 175, 46, 250, 29, 247, 225, 206, 248, 74, 134, 69, 118, 172, 242, 209, 52, 115, 111, 201, 232, 177, 1], +[1, 107, 141, 181, 92, 78, 122, 204, 240, 237, 173, 7, 235, 216, 239, 130, 32, 83, 143, 138, 117, 183, 49, 103, 227, 131, 139, 224, 67, 230, 195, 48, 253, 86, 207, 47, 146, 202, 26, 212, 68, 80, 79, 229, 88, 164, 72, 251, 129, 182, 199, 219, 46, 39, 61, 102, 120, 247, 215, 132, 246, 108, 248, 65, 16, 170, 200, 69, 187, 220, 153, 180, 242, 194, 198, 112, 162, 115, 226, 24, 255, 43, 232, 152, 73, 101, 13, 106, 34, 40, 168, 243, 44, 82, 36, 254, 193, 91, 228, 238, 23, 148, 159, 51, 60, 252, 236, 66, 123, 54, 124, 161, 8, 85, 100, 163, 222, 110, 205, 90, 121, 97, 99, 56, 81, 186, 113, 12, 256, 150, 116, 76, 165, 179, 135, 53, 17, 20, 84, 250, 22, 41, 18, 127, 225, 174, 114, 119, 140, 74, 208, 154, 30, 126, 118, 33, 190, 27, 62, 209, 4, 171, 50, 210, 111, 55, 231, 45, 189, 177, 178, 28, 169, 93, 185, 6, 128, 75, 58, 38, 211, 218, 196, 155, 137, 10, 42, 125, 11, 149, 9, 192, 241, 87, 57, 188, 70, 37, 104, 77, 15, 63, 59, 145, 95, 142, 31, 233, 2, 214, 25, 105, 184, 156, 244, 151, 223, 217, 89, 14, 213, 175, 221, 3, 64, 166, 29, 19, 234, 109, 98, 206, 197, 5, 21, 191, 134, 203, 133, 96, 249, 172, 157, 94, 35, 147, 52, 167, 136, 160, 158, 201, 176, 71, 144, 245, 1], +[1, 108, 99, 155, 35, 182, 124, 28, 197, 202, 228, 209, 213, 131, 13, 119, 2, 216, 198, 53, 70, 107, 248, 56, 137, 147, 199, 161, 169, 5, 26, 238, 4, 175, 139, 106, 140, 214, 239, 112, 17, 37, 141, 65, 81, 10, 52, 219, 8, 93, 21, 212, 23, 171, 221, 224, 34, 74, 25, 130, 162, 20, 104, 181, 16, 186, 42, 167, 46, 85, 185, 191, 68, 148, 50, 3, 67, 40, 208, 105, 32, 115, 84, 77, 92, 170, 113, 125, 136, 39, 100, 6, 134, 80, 159, 210, 64, 230, 168, 154, 184, 83, 226, 250, 15, 78, 200, 12, 11, 160, 61, 163, 128, 203, 79, 51, 111, 166, 195, 243, 30, 156, 143, 24, 22, 63, 122, 69, 256, 149, 158, 102, 222, 75, 133, 229, 60, 55, 29, 48, 44, 126, 244, 138, 255, 41, 59, 204, 187, 150, 9, 201, 120, 110, 58, 96, 88, 252, 231, 19, 253, 82, 118, 151, 117, 43, 18, 145, 240, 220, 116, 192, 176, 247, 205, 38, 249, 164, 236, 45, 234, 86, 36, 33, 223, 183, 232, 127, 95, 237, 153, 76, 241, 71, 215, 90, 211, 172, 72, 66, 189, 109, 207, 254, 190, 217, 49, 152, 225, 142, 173, 180, 165, 87, 144, 132, 121, 218, 157, 251, 123, 177, 98, 47, 193, 27, 89, 103, 73, 174, 31, 7, 242, 179, 57, 245, 246, 97, 196, 94, 129, 54, 178, 206, 146, 91, 62, 14, 227, 101, 114, 233, 235, 194, 135, 188, 1], +[1, 109, 59, 6, 140, 97, 36, 69, 68, 216, 157, 151, 11, 171, 135, 66, 255, 39, 139, 245, 234, 63, 185, 119, 121, 82, 200, 212, 235, 172, 244, 125, 4, 179, 236, 24, 46, 131, 144, 19, 15, 93, 114, 90, 44, 170, 26, 7, 249, 156, 42, 209, 165, 252, 226, 219, 227, 71, 29, 77, 169, 174, 205, 243, 16, 202, 173, 96, 184, 10, 62, 76, 60, 115, 199, 103, 176, 166, 104, 28, 225, 110, 168, 65, 146, 237, 133, 105, 137, 27, 116, 51, 162, 182, 49, 201, 64, 37, 178, 127, 222, 40, 248, 47, 240, 203, 25, 155, 190, 150, 159, 112, 129, 183, 158, 3, 70, 177, 18, 163, 34, 108, 207, 204, 134, 214, 196, 33, 256, 148, 198, 251, 117, 160, 221, 188, 189, 41, 100, 106, 246, 86, 122, 191, 2, 218, 118, 12, 23, 194, 72, 138, 136, 175, 57, 45, 22, 85, 13, 132, 253, 78, 21, 233, 211, 126, 113, 238, 242, 164, 143, 167, 213, 87, 231, 250, 8, 101, 215, 48, 92, 5, 31, 38, 30, 186, 228, 180, 88, 83, 52, 14, 241, 55, 84, 161, 73, 247, 195, 181, 197, 142, 58, 154, 81, 91, 153, 229, 32, 147, 89, 192, 111, 20, 124, 152, 120, 230, 141, 206, 95, 75, 208, 56, 193, 220, 79, 130, 35, 217, 9, 210, 17, 54, 232, 102, 67, 107, 98, 145, 128, 74, 99, 254, 187, 80, 239, 94, 223, 149, 50, 53, 123, 43, 61, 224, 1], +[1, 110, 21, 254, 184, 194, 9, 219, 189, 230, 114, 204, 81, 172, 159, 14, 255, 37, 215, 6, 146, 126, 239, 76, 136, 54, 29, 106, 95, 170, 196, 229, 4, 183, 84, 245, 222, 5, 36, 105, 242, 149, 199, 45, 67, 174, 122, 56, 249, 148, 89, 24, 70, 247, 185, 47, 30, 216, 116, 167, 123, 166, 13, 145, 16, 218, 79, 209, 117, 20, 144, 163, 197, 82, 25, 180, 11, 182, 231, 224, 225, 78, 99, 96, 23, 217, 226, 188, 120, 93, 207, 154, 235, 150, 52, 66, 64, 101, 59, 65, 211, 80, 62, 138, 17, 71, 100, 206, 44, 214, 153, 125, 129, 55, 139, 127, 92, 97, 133, 238, 223, 115, 57, 102, 169, 86, 208, 7, 256, 147, 236, 3, 73, 63, 248, 38, 68, 27, 143, 53, 176, 85, 98, 243, 2, 220, 42, 251, 111, 131, 18, 181, 121, 203, 228, 151, 162, 87, 61, 28, 253, 74, 173, 12, 35, 252, 221, 152, 15, 108, 58, 212, 190, 83, 135, 201, 8, 109, 168, 233, 187, 10, 72, 210, 227, 41, 141, 90, 134, 91, 244, 112, 241, 39, 178, 48, 140, 237, 113, 94, 60, 175, 232, 77, 246, 75, 26, 33, 32, 179, 158, 161, 234, 40, 31, 69, 137, 164, 50, 103, 22, 107, 205, 191, 193, 156, 198, 192, 46, 177, 195, 119, 240, 186, 157, 51, 213, 43, 104, 132, 128, 202, 118, 130, 165, 160, 124, 19, 34, 142, 200, 155, 88, 171, 49, 250, 1], +[1, 111, 242, 134, 225, 46, 223, 81, 253, 70, 60, 235, 128, 73, 136, 190, 16, 234, 17, 88, 2, 222, 227, 11, 193, 92, 189, 162, 249, 140, 120, 213, 256, 146, 15, 123, 32, 211, 34, 176, 4, 187, 197, 22, 129, 184, 121, 67, 241, 23, 240, 169, 255, 35, 30, 246, 64, 165, 68, 95, 8, 117, 137, 44, 1, 111, 242, 134, 225, 46, 223, 81, 253, 70, 60, 235, 128, 73, 136, 190, 16, 234, 17, 88, 2, 222, 227, 11, 193, 92, 189, 162, 249, 140, 120, 213, 256, 146, 15, 123, 32, 211, 34, 176, 4, 187, 197, 22, 129, 184, 121, 67, 241, 23, 240, 169, 255, 35, 30, 246, 64, 165, 68, 95, 8, 117, 137, 44, 1, 111, 242, 134, 225, 46, 223, 81, 253, 70, 60, 235, 128, 73, 136, 190, 16, 234, 17, 88, 2, 222, 227, 11, 193, 92, 189, 162, 249, 140, 120, 213, 256, 146, 15, 123, 32, 211, 34, 176, 4, 187, 197, 22, 129, 184, 121, 67, 241, 23, 240, 169, 255, 35, 30, 246, 64, 165, 68, 95, 8, 117, 137, 44, 1, 111, 242, 134, 225, 46, 223, 81, 253, 70, 60, 235, 128, 73, 136, 190, 16, 234, 17, 88, 2, 222, 227, 11, 193, 92, 189, 162, 249, 140, 120, 213, 256, 146, 15, 123, 32, 211, 34, 176, 4, 187, 197, 22, 129, 184, 121, 67, 241, 23, 240, 169, 255, 35, 30, 246, 64, 165, 68, 95, 8, 117, 137, 44, 1], +[1, 112, 208, 166, 88, 90, 57, 216, 34, 210, 133, 247, 165, 233, 139, 148, 128, 201, 153, 174, 213, 212, 100, 149, 240, 152, 62, 5, 46, 12, 59, 183, 193, 28, 52, 170, 22, 151, 207, 54, 137, 181, 226, 126, 234, 251, 99, 37, 32, 243, 231, 172, 246, 53, 25, 230, 60, 38, 144, 194, 140, 3, 79, 110, 241, 7, 13, 171, 134, 102, 116, 142, 227, 238, 185, 160, 187, 127, 89, 202, 8, 125, 122, 43, 190, 206, 199, 186, 15, 138, 36, 177, 35, 65, 84, 156, 253, 66, 196, 107, 162, 154, 29, 164, 121, 188, 239, 40, 111, 96, 215, 179, 2, 224, 159, 75, 176, 180, 114, 175, 68, 163, 9, 237, 73, 209, 21, 39, 256, 145, 49, 91, 169, 167, 200, 41, 223, 47, 124, 10, 92, 24, 118, 109, 129, 56, 104, 83, 44, 45, 157, 108, 17, 105, 195, 252, 211, 245, 198, 74, 64, 229, 205, 87, 235, 106, 50, 203, 120, 76, 31, 131, 23, 6, 158, 220, 225, 14, 26, 85, 11, 204, 232, 27, 197, 219, 113, 63, 117, 254, 178, 147, 16, 250, 244, 86, 123, 155, 141, 115, 30, 19, 72, 97, 70, 130, 168, 55, 249, 132, 135, 214, 67, 51, 58, 71, 242, 119, 221, 80, 222, 192, 173, 101, 4, 191, 61, 150, 95, 103, 228, 93, 136, 69, 18, 217, 146, 161, 42, 78, 255, 33, 98, 182, 81, 77, 143, 82, 189, 94, 248, 20, 184, 48, 236, 218, 1], +[1, 113, 176, 99, 136, 205, 35, 100, 249, 124, 134, 236, 197, 159, 234, 228, 64, 36, 213, 168, 223, 13, 184, 232, 2, 226, 95, 198, 15, 153, 70, 200, 241, 248, 11, 215, 137, 61, 211, 199, 128, 72, 169, 79, 189, 26, 111, 207, 4, 195, 190, 139, 30, 49, 140, 143, 225, 239, 22, 173, 17, 122, 165, 141, 256, 144, 81, 158, 121, 52, 222, 157, 8, 133, 123, 21, 60, 98, 23, 29, 193, 221, 44, 89, 34, 244, 73, 25, 255, 31, 162, 59, 242, 104, 187, 57, 16, 9, 246, 42, 120, 196, 46, 58, 129, 185, 88, 178, 68, 231, 146, 50, 253, 62, 67, 118, 227, 208, 117, 114, 32, 18, 235, 84, 240, 135, 92, 116, 1, 113, 176, 99, 136, 205, 35, 100, 249, 124, 134, 236, 197, 159, 234, 228, 64, 36, 213, 168, 223, 13, 184, 232, 2, 226, 95, 198, 15, 153, 70, 200, 241, 248, 11, 215, 137, 61, 211, 199, 128, 72, 169, 79, 189, 26, 111, 207, 4, 195, 190, 139, 30, 49, 140, 143, 225, 239, 22, 173, 17, 122, 165, 141, 256, 144, 81, 158, 121, 52, 222, 157, 8, 133, 123, 21, 60, 98, 23, 29, 193, 221, 44, 89, 34, 244, 73, 25, 255, 31, 162, 59, 242, 104, 187, 57, 16, 9, 246, 42, 120, 196, 46, 58, 129, 185, 88, 178, 68, 231, 146, 50, 253, 62, 67, 118, 227, 208, 117, 114, 32, 18, 235, 84, 240, 135, 92, 116, 1], +[1, 114, 146, 196, 242, 89, 123, 144, 225, 207, 211, 153, 223, 236, 176, 18, 253, 58, 187, 244, 60, 158, 22, 195, 128, 200, 184, 159, 136, 84, 67, 185, 16, 25, 23, 52, 17, 139, 169, 248, 2, 228, 35, 135, 227, 178, 246, 31, 193, 157, 165, 49, 189, 215, 95, 36, 249, 116, 117, 231, 120, 59, 44, 133, 256, 143, 111, 61, 15, 168, 134, 113, 32, 50, 46, 104, 34, 21, 81, 239, 4, 199, 70, 13, 197, 99, 235, 62, 129, 57, 73, 98, 121, 173, 190, 72, 241, 232, 234, 205, 240, 118, 88, 9, 255, 29, 222, 122, 30, 79, 11, 226, 64, 100, 92, 208, 68, 42, 162, 221, 8, 141, 140, 26, 137, 198, 213, 124, 1, 114, 146, 196, 242, 89, 123, 144, 225, 207, 211, 153, 223, 236, 176, 18, 253, 58, 187, 244, 60, 158, 22, 195, 128, 200, 184, 159, 136, 84, 67, 185, 16, 25, 23, 52, 17, 139, 169, 248, 2, 228, 35, 135, 227, 178, 246, 31, 193, 157, 165, 49, 189, 215, 95, 36, 249, 116, 117, 231, 120, 59, 44, 133, 256, 143, 111, 61, 15, 168, 134, 113, 32, 50, 46, 104, 34, 21, 81, 239, 4, 199, 70, 13, 197, 99, 235, 62, 129, 57, 73, 98, 121, 173, 190, 72, 241, 232, 234, 205, 240, 118, 88, 9, 255, 29, 222, 122, 30, 79, 11, 226, 64, 100, 92, 208, 68, 42, 162, 221, 8, 141, 140, 26, 137, 198, 213, 124, 1], +[1, 115, 118, 206, 46, 150, 31, 224, 60, 218, 141, 24, 190, 5, 61, 76, 2, 230, 236, 155, 92, 43, 62, 191, 120, 179, 25, 48, 123, 10, 122, 152, 4, 203, 215, 53, 184, 86, 124, 125, 240, 101, 50, 96, 246, 20, 244, 47, 8, 149, 173, 106, 111, 172, 248, 250, 223, 202, 100, 192, 235, 40, 231, 94, 16, 41, 89, 212, 222, 87, 239, 243, 189, 147, 200, 127, 213, 80, 205, 188, 32, 82, 178, 167, 187, 174, 221, 229, 121, 37, 143, 254, 169, 160, 153, 119, 64, 164, 99, 77, 117, 91, 185, 201, 242, 74, 29, 251, 81, 63, 49, 238, 128, 71, 198, 154, 234, 182, 113, 145, 227, 148, 58, 245, 162, 126, 98, 219, 256, 142, 139, 51, 211, 107, 226, 33, 197, 39, 116, 233, 67, 252, 196, 181, 255, 27, 21, 102, 165, 214, 195, 66, 137, 78, 232, 209, 134, 247, 135, 105, 253, 54, 42, 204, 73, 171, 133, 132, 17, 156, 207, 161, 11, 237, 13, 210, 249, 108, 84, 151, 146, 85, 9, 7, 34, 55, 157, 65, 22, 217, 26, 163, 241, 216, 168, 45, 35, 170, 18, 14, 68, 110, 57, 130, 44, 177, 52, 69, 225, 175, 79, 90, 70, 83, 36, 28, 136, 220, 114, 3, 88, 97, 104, 138, 193, 93, 158, 180, 140, 166, 72, 56, 15, 183, 228, 6, 176, 194, 208, 19, 129, 186, 59, 103, 23, 75, 144, 112, 30, 109, 199, 12, 95, 131, 159, 38, 1], +[1, 116, 92, 135, 240, 84, 235, 18, 32, 114, 117, 208, 227, 118, 67, 62, 253, 50, 146, 231, 68, 178, 88, 185, 129, 58, 46, 196, 120, 42, 246, 9, 16, 57, 187, 104, 242, 59, 162, 31, 255, 25, 73, 244, 34, 89, 44, 221, 193, 29, 23, 98, 60, 21, 123, 133, 8, 157, 222, 52, 121, 158, 81, 144, 256, 141, 165, 122, 17, 173, 22, 239, 225, 143, 140, 49, 30, 139, 190, 195, 4, 207, 111, 26, 189, 79, 169, 72, 128, 199, 211, 61, 137, 215, 11, 248, 241, 200, 70, 153, 15, 198, 95, 226, 2, 232, 184, 13, 223, 168, 213, 36, 64, 228, 234, 159, 197, 236, 134, 124, 249, 100, 35, 205, 136, 99, 176, 113, 1, 116, 92, 135, 240, 84, 235, 18, 32, 114, 117, 208, 227, 118, 67, 62, 253, 50, 146, 231, 68, 178, 88, 185, 129, 58, 46, 196, 120, 42, 246, 9, 16, 57, 187, 104, 242, 59, 162, 31, 255, 25, 73, 244, 34, 89, 44, 221, 193, 29, 23, 98, 60, 21, 123, 133, 8, 157, 222, 52, 121, 158, 81, 144, 256, 141, 165, 122, 17, 173, 22, 239, 225, 143, 140, 49, 30, 139, 190, 195, 4, 207, 111, 26, 189, 79, 169, 72, 128, 199, 211, 61, 137, 215, 11, 248, 241, 200, 70, 153, 15, 198, 95, 226, 2, 232, 184, 13, 223, 168, 213, 36, 64, 228, 234, 159, 197, 236, 134, 124, 249, 100, 35, 205, 136, 99, 176, 113, 1], +[1, 117, 68, 246, 255, 23, 121, 22, 4, 211, 15, 213, 249, 92, 227, 88, 16, 73, 60, 81, 225, 111, 137, 95, 64, 35, 240, 67, 129, 187, 34, 123, 256, 140, 189, 11, 2, 234, 136, 235, 253, 46, 242, 44, 8, 165, 30, 169, 241, 184, 197, 176, 32, 146, 120, 162, 193, 222, 17, 190, 128, 70, 223, 134, 1, 117, 68, 246, 255, 23, 121, 22, 4, 211, 15, 213, 249, 92, 227, 88, 16, 73, 60, 81, 225, 111, 137, 95, 64, 35, 240, 67, 129, 187, 34, 123, 256, 140, 189, 11, 2, 234, 136, 235, 253, 46, 242, 44, 8, 165, 30, 169, 241, 184, 197, 176, 32, 146, 120, 162, 193, 222, 17, 190, 128, 70, 223, 134, 1, 117, 68, 246, 255, 23, 121, 22, 4, 211, 15, 213, 249, 92, 227, 88, 16, 73, 60, 81, 225, 111, 137, 95, 64, 35, 240, 67, 129, 187, 34, 123, 256, 140, 189, 11, 2, 234, 136, 235, 253, 46, 242, 44, 8, 165, 30, 169, 241, 184, 197, 176, 32, 146, 120, 162, 193, 222, 17, 190, 128, 70, 223, 134, 1, 117, 68, 246, 255, 23, 121, 22, 4, 211, 15, 213, 249, 92, 227, 88, 16, 73, 60, 81, 225, 111, 137, 95, 64, 35, 240, 67, 129, 187, 34, 123, 256, 140, 189, 11, 2, 234, 136, 235, 253, 46, 242, 44, 8, 165, 30, 169, 241, 184, 197, 176, 32, 146, 120, 162, 193, 222, 17, 190, 128, 70, 223, 134, 1], +[1, 118, 46, 31, 60, 141, 190, 61, 2, 236, 92, 62, 120, 25, 123, 122, 4, 215, 184, 124, 240, 50, 246, 244, 8, 173, 111, 248, 223, 100, 235, 231, 16, 89, 222, 239, 189, 200, 213, 205, 32, 178, 187, 221, 121, 143, 169, 153, 64, 99, 117, 185, 242, 29, 81, 49, 128, 198, 234, 113, 227, 58, 162, 98, 256, 139, 211, 226, 197, 116, 67, 196, 255, 21, 165, 195, 137, 232, 134, 135, 253, 42, 73, 133, 17, 207, 11, 13, 249, 84, 146, 9, 34, 157, 22, 26, 241, 168, 35, 18, 68, 57, 44, 52, 225, 79, 70, 36, 136, 114, 88, 104, 193, 158, 140, 72, 15, 228, 176, 208, 129, 59, 23, 144, 30, 199, 95, 159, 1, 118, 46, 31, 60, 141, 190, 61, 2, 236, 92, 62, 120, 25, 123, 122, 4, 215, 184, 124, 240, 50, 246, 244, 8, 173, 111, 248, 223, 100, 235, 231, 16, 89, 222, 239, 189, 200, 213, 205, 32, 178, 187, 221, 121, 143, 169, 153, 64, 99, 117, 185, 242, 29, 81, 49, 128, 198, 234, 113, 227, 58, 162, 98, 256, 139, 211, 226, 197, 116, 67, 196, 255, 21, 165, 195, 137, 232, 134, 135, 253, 42, 73, 133, 17, 207, 11, 13, 249, 84, 146, 9, 34, 157, 22, 26, 241, 168, 35, 18, 68, 57, 44, 52, 225, 79, 70, 36, 136, 114, 88, 104, 193, 158, 140, 72, 15, 228, 176, 208, 129, 59, 23, 144, 30, 199, 95, 159, 1], +[1, 119, 26, 10, 162, 3, 100, 78, 30, 229, 9, 43, 234, 90, 173, 27, 129, 188, 13, 5, 81, 130, 50, 39, 15, 243, 133, 150, 117, 45, 215, 142, 193, 94, 135, 131, 169, 65, 25, 148, 136, 250, 195, 75, 187, 151, 236, 71, 225, 47, 196, 194, 213, 161, 141, 74, 68, 125, 226, 166, 222, 204, 118, 164, 241, 152, 98, 97, 235, 209, 199, 37, 34, 191, 113, 83, 111, 102, 59, 82, 249, 76, 49, 177, 246, 233, 228, 147, 17, 224, 185, 170, 184, 51, 158, 41, 253, 38, 153, 217, 123, 245, 114, 202, 137, 112, 221, 85, 92, 154, 79, 149, 255, 19, 205, 237, 190, 251, 57, 101, 197, 56, 239, 171, 46, 77, 168, 203, 256, 138, 231, 247, 95, 254, 157, 179, 227, 28, 248, 214, 23, 167, 84, 230, 128, 69, 244, 252, 176, 127, 207, 218, 242, 14, 124, 107, 140, 212, 42, 115, 64, 163, 122, 126, 88, 192, 232, 109, 121, 7, 62, 182, 70, 106, 21, 186, 32, 210, 61, 63, 44, 96, 116, 183, 189, 132, 31, 91, 35, 53, 139, 93, 16, 105, 159, 160, 22, 48, 58, 220, 223, 66, 144, 174, 146, 155, 198, 175, 8, 181, 208, 80, 11, 24, 29, 110, 240, 33, 72, 87, 73, 206, 99, 216, 4, 219, 104, 40, 134, 12, 143, 55, 120, 145, 36, 172, 165, 103, 178, 108, 2, 238, 52, 20, 67, 6, 200, 156, 60, 201, 18, 86, 211, 180, 89, 54, 1], +[1, 120, 8, 189, 64, 227, 255, 17, 241, 136, 129, 60, 4, 223, 32, 242, 256, 137, 249, 68, 193, 30, 2, 240, 16, 121, 128, 197, 253, 34, 225, 15, 1, 120, 8, 189, 64, 227, 255, 17, 241, 136, 129, 60, 4, 223, 32, 242, 256, 137, 249, 68, 193, 30, 2, 240, 16, 121, 128, 197, 253, 34, 225, 15, 1, 120, 8, 189, 64, 227, 255, 17, 241, 136, 129, 60, 4, 223, 32, 242, 256, 137, 249, 68, 193, 30, 2, 240, 16, 121, 128, 197, 253, 34, 225, 15, 1, 120, 8, 189, 64, 227, 255, 17, 241, 136, 129, 60, 4, 223, 32, 242, 256, 137, 249, 68, 193, 30, 2, 240, 16, 121, 128, 197, 253, 34, 225, 15, 1, 120, 8, 189, 64, 227, 255, 17, 241, 136, 129, 60, 4, 223, 32, 242, 256, 137, 249, 68, 193, 30, 2, 240, 16, 121, 128, 197, 253, 34, 225, 15, 1, 120, 8, 189, 64, 227, 255, 17, 241, 136, 129, 60, 4, 223, 32, 242, 256, 137, 249, 68, 193, 30, 2, 240, 16, 121, 128, 197, 253, 34, 225, 15, 1, 120, 8, 189, 64, 227, 255, 17, 241, 136, 129, 60, 4, 223, 32, 242, 256, 137, 249, 68, 193, 30, 2, 240, 16, 121, 128, 197, 253, 34, 225, 15, 1, 120, 8, 189, 64, 227, 255, 17, 241, 136, 129, 60, 4, 223, 32, 242, 256, 137, 249, 68, 193, 30, 2, 240, 16, 121, 128, 197, 253, 34, 225, 15, 1], +[1, 121, 249, 60, 64, 34, 2, 242, 241, 120, 128, 68, 4, 227, 225, 240, 256, 136, 8, 197, 193, 223, 255, 15, 16, 137, 129, 189, 253, 30, 32, 17, 1, 121, 249, 60, 64, 34, 2, 242, 241, 120, 128, 68, 4, 227, 225, 240, 256, 136, 8, 197, 193, 223, 255, 15, 16, 137, 129, 189, 253, 30, 32, 17, 1, 121, 249, 60, 64, 34, 2, 242, 241, 120, 128, 68, 4, 227, 225, 240, 256, 136, 8, 197, 193, 223, 255, 15, 16, 137, 129, 189, 253, 30, 32, 17, 1, 121, 249, 60, 64, 34, 2, 242, 241, 120, 128, 68, 4, 227, 225, 240, 256, 136, 8, 197, 193, 223, 255, 15, 16, 137, 129, 189, 253, 30, 32, 17, 1, 121, 249, 60, 64, 34, 2, 242, 241, 120, 128, 68, 4, 227, 225, 240, 256, 136, 8, 197, 193, 223, 255, 15, 16, 137, 129, 189, 253, 30, 32, 17, 1, 121, 249, 60, 64, 34, 2, 242, 241, 120, 128, 68, 4, 227, 225, 240, 256, 136, 8, 197, 193, 223, 255, 15, 16, 137, 129, 189, 253, 30, 32, 17, 1, 121, 249, 60, 64, 34, 2, 242, 241, 120, 128, 68, 4, 227, 225, 240, 256, 136, 8, 197, 193, 223, 255, 15, 16, 137, 129, 189, 253, 30, 32, 17, 1, 121, 249, 60, 64, 34, 2, 242, 241, 120, 128, 68, 4, 227, 225, 240, 256, 136, 8, 197, 193, 223, 255, 15, 16, 137, 129, 189, 253, 30, 32, 17, 1], +[1, 122, 235, 143, 227, 195, 146, 79, 129, 61, 246, 200, 242, 226, 73, 168, 193, 159, 123, 100, 121, 113, 165, 84, 225, 208, 190, 50, 189, 185, 211, 42, 241, 104, 95, 25, 223, 221, 234, 21, 249, 52, 176, 141, 240, 239, 117, 139, 253, 26, 88, 199, 120, 248, 187, 198, 255, 13, 44, 228, 60, 124, 222, 99, 256, 135, 22, 114, 30, 62, 111, 178, 128, 196, 11, 57, 15, 31, 184, 89, 64, 98, 134, 157, 136, 144, 92, 173, 32, 49, 67, 207, 68, 72, 46, 215, 16, 153, 162, 232, 34, 36, 23, 236, 8, 205, 81, 116, 17, 18, 140, 118, 4, 231, 169, 58, 137, 9, 70, 59, 2, 244, 213, 29, 197, 133, 35, 158, 1, 122, 235, 143, 227, 195, 146, 79, 129, 61, 246, 200, 242, 226, 73, 168, 193, 159, 123, 100, 121, 113, 165, 84, 225, 208, 190, 50, 189, 185, 211, 42, 241, 104, 95, 25, 223, 221, 234, 21, 249, 52, 176, 141, 240, 239, 117, 139, 253, 26, 88, 199, 120, 248, 187, 198, 255, 13, 44, 228, 60, 124, 222, 99, 256, 135, 22, 114, 30, 62, 111, 178, 128, 196, 11, 57, 15, 31, 184, 89, 64, 98, 134, 157, 136, 144, 92, 173, 32, 49, 67, 207, 68, 72, 46, 215, 16, 153, 162, 232, 34, 36, 23, 236, 8, 205, 81, 116, 17, 18, 140, 118, 4, 231, 169, 58, 137, 9, 70, 59, 2, 244, 213, 29, 197, 133, 35, 158, 1], +[1, 123, 223, 187, 128, 67, 17, 35, 193, 95, 120, 111, 32, 81, 197, 73, 241, 88, 30, 92, 8, 213, 242, 211, 253, 22, 136, 23, 2, 246, 189, 117, 256, 134, 34, 70, 129, 190, 240, 222, 64, 162, 137, 146, 225, 176, 60, 184, 16, 169, 227, 165, 249, 44, 15, 46, 4, 235, 121, 234, 255, 11, 68, 140, 1, 123, 223, 187, 128, 67, 17, 35, 193, 95, 120, 111, 32, 81, 197, 73, 241, 88, 30, 92, 8, 213, 242, 211, 253, 22, 136, 23, 2, 246, 189, 117, 256, 134, 34, 70, 129, 190, 240, 222, 64, 162, 137, 146, 225, 176, 60, 184, 16, 169, 227, 165, 249, 44, 15, 46, 4, 235, 121, 234, 255, 11, 68, 140, 1, 123, 223, 187, 128, 67, 17, 35, 193, 95, 120, 111, 32, 81, 197, 73, 241, 88, 30, 92, 8, 213, 242, 211, 253, 22, 136, 23, 2, 246, 189, 117, 256, 134, 34, 70, 129, 190, 240, 222, 64, 162, 137, 146, 225, 176, 60, 184, 16, 169, 227, 165, 249, 44, 15, 46, 4, 235, 121, 234, 255, 11, 68, 140, 1, 123, 223, 187, 128, 67, 17, 35, 193, 95, 120, 111, 32, 81, 197, 73, 241, 88, 30, 92, 8, 213, 242, 211, 253, 22, 136, 23, 2, 246, 189, 117, 256, 134, 34, 70, 129, 190, 240, 222, 64, 162, 137, 146, 225, 176, 60, 184, 16, 169, 227, 165, 249, 44, 15, 46, 4, 235, 121, 234, 255, 11, 68, 140, 1], +[1, 124, 213, 198, 137, 26, 140, 141, 8, 221, 162, 42, 68, 208, 92, 100, 64, 226, 11, 79, 30, 122, 222, 29, 255, 9, 88, 118, 240, 205, 234, 232, 241, 72, 190, 173, 121, 98, 73, 57, 129, 62, 235, 99, 197, 13, 70, 199, 4, 239, 81, 21, 34, 104, 46, 50, 32, 113, 134, 168, 15, 61, 111, 143, 256, 133, 44, 59, 120, 231, 117, 116, 249, 36, 95, 215, 189, 49, 165, 157, 193, 31, 246, 178, 227, 135, 35, 228, 2, 248, 169, 139, 17, 52, 23, 25, 16, 185, 67, 84, 136, 159, 184, 200, 128, 195, 22, 158, 60, 244, 187, 58, 253, 18, 176, 236, 223, 153, 211, 207, 225, 144, 123, 89, 242, 196, 146, 114, 1, 124, 213, 198, 137, 26, 140, 141, 8, 221, 162, 42, 68, 208, 92, 100, 64, 226, 11, 79, 30, 122, 222, 29, 255, 9, 88, 118, 240, 205, 234, 232, 241, 72, 190, 173, 121, 98, 73, 57, 129, 62, 235, 99, 197, 13, 70, 199, 4, 239, 81, 21, 34, 104, 46, 50, 32, 113, 134, 168, 15, 61, 111, 143, 256, 133, 44, 59, 120, 231, 117, 116, 249, 36, 95, 215, 189, 49, 165, 157, 193, 31, 246, 178, 227, 135, 35, 228, 2, 248, 169, 139, 17, 52, 23, 25, 16, 185, 67, 84, 136, 159, 184, 200, 128, 195, 22, 158, 60, 244, 187, 58, 253, 18, 176, 236, 223, 153, 211, 207, 225, 144, 123, 89, 242, 196, 146, 114, 1], +[1, 125, 205, 182, 134, 45, 228, 230, 223, 119, 226, 237, 70, 12, 215, 147, 128, 66, 26, 166, 190, 106, 143, 142, 17, 69, 144, 10, 222, 251, 21, 55, 193, 224, 244, 174, 162, 204, 57, 186, 120, 94, 185, 252, 146, 3, 118, 101, 32, 145, 135, 170, 176, 155, 100, 164, 197, 210, 36, 131, 184, 127, 198, 78, 241, 56, 61, 172, 169, 51, 207, 175, 30, 152, 239, 63, 165, 65, 158, 218, 8, 229, 98, 171, 44, 103, 25, 41, 242, 181, 9, 97, 46, 96, 178, 148, 253, 14, 208, 43, 235, 77, 116, 108, 136, 38, 124, 80, 234, 209, 168, 183, 2, 250, 153, 107, 11, 90, 199, 203, 189, 238, 195, 217, 140, 24, 173, 37, 256, 132, 52, 75, 123, 212, 29, 27, 34, 138, 31, 20, 187, 245, 42, 110, 129, 191, 231, 91, 67, 151, 114, 115, 240, 188, 113, 247, 35, 6, 236, 202, 64, 33, 13, 83, 95, 53, 200, 71, 137, 163, 72, 5, 111, 254, 139, 156, 225, 112, 122, 87, 81, 102, 157, 93, 60, 47, 221, 126, 73, 130, 59, 179, 16, 201, 196, 85, 88, 206, 50, 82, 227, 105, 18, 194, 92, 192, 99, 39, 249, 28, 159, 86, 213, 154, 232, 216, 15, 76, 248, 160, 211, 161, 79, 109, 4, 243, 49, 214, 22, 180, 141, 149, 121, 219, 133, 177, 23, 48, 89, 74, 255, 7, 104, 150, 246, 167, 58, 54, 68, 19, 62, 40, 117, 233, 84, 220, 1], +[1, 126, 199, 145, 23, 71, 208, 251, 15, 91, 158, 119, 88, 37, 36, 167, 225, 80, 57, 243, 35, 41, 26, 192, 34, 172, 84, 47, 11, 101, 133, 53, 253, 10, 232, 191, 165, 230, 196, 24, 197, 150, 139, 38, 162, 109, 113, 103, 128, 194, 29, 56, 117, 93, 153, 3, 121, 83, 178, 69, 213, 110, 239, 45, 16, 217, 100, 7, 111, 108, 244, 161, 240, 171, 215, 105, 123, 78, 62, 102, 2, 252, 141, 33, 46, 142, 159, 245, 30, 182, 59, 238, 176, 74, 72, 77, 193, 160, 114, 229, 70, 82, 52, 127, 68, 87, 168, 94, 22, 202, 9, 106, 249, 20, 207, 125, 73, 203, 135, 48, 137, 43, 21, 76, 67, 218, 226, 206, 256, 131, 58, 112, 234, 186, 49, 6, 242, 166, 99, 138, 169, 220, 221, 90, 32, 177, 200, 14, 222, 216, 231, 65, 223, 85, 173, 210, 246, 156, 124, 204, 4, 247, 25, 66, 92, 27, 61, 233, 60, 107, 118, 219, 95, 148, 144, 154, 129, 63, 228, 201, 140, 164, 104, 254, 136, 174, 79, 188, 44, 147, 18, 212, 241, 40, 157, 250, 146, 149, 13, 96, 17, 86, 42, 152, 134, 179, 195, 155, 255, 5, 116, 224, 211, 115, 98, 12, 227, 75, 198, 19, 81, 183, 185, 180, 64, 97, 143, 28, 187, 175, 205, 130, 189, 170, 89, 163, 235, 55, 248, 151, 8, 237, 50, 132, 184, 54, 122, 209, 120, 214, 236, 181, 190, 39, 31, 51, 1], +[1, 127, 195, 93, 246, 145, 168, 5, 121, 204, 208, 202, 211, 69, 25, 91, 249, 12, 239, 27, 88, 125, 198, 217, 60, 167, 135, 183, 111, 219, 57, 43, 64, 161, 144, 41, 67, 28, 215, 63, 34, 206, 205, 78, 140, 47, 58, 170, 2, 254, 133, 186, 235, 33, 79, 10, 242, 151, 159, 147, 165, 138, 50, 182, 241, 24, 221, 54, 176, 250, 139, 177, 120, 77, 13, 109, 222, 181, 114, 86, 128, 65, 31, 82, 134, 56, 173, 126, 68, 155, 153, 156, 23, 94, 116, 83, 4, 251, 9, 115, 213, 66, 158, 20, 227, 45, 61, 37, 73, 19, 100, 107, 225, 48, 185, 108, 95, 243, 21, 97, 240, 154, 26, 218, 187, 105, 228, 172, 256, 130, 62, 164, 11, 112, 89, 252, 136, 53, 49, 55, 46, 188, 232, 166, 8, 245, 18, 230, 169, 132, 59, 40, 197, 90, 122, 74, 146, 38, 200, 214, 193, 96, 113, 216, 190, 229, 42, 194, 223, 51, 52, 179, 117, 210, 199, 87, 255, 3, 124, 71, 22, 224, 178, 247, 15, 106, 98, 110, 92, 119, 207, 75, 16, 233, 36, 203, 81, 7, 118, 80, 137, 180, 244, 148, 35, 76, 143, 171, 129, 192, 226, 175, 123, 201, 84, 131, 189, 102, 104, 101, 234, 163, 141, 174, 253, 6, 248, 142, 44, 191, 99, 237, 30, 212, 196, 220, 184, 238, 157, 150, 32, 209, 72, 149, 162, 14, 236, 160, 17, 103, 231, 39, 70, 152, 29, 85, 1], +[1, 128, 193, 32, 241, 8, 253, 2, 256, 129, 64, 225, 16, 249, 4, 255, 1, 128, 193, 32, 241, 8, 253, 2, 256, 129, 64, 225, 16, 249, 4, 255, 1, 128, 193, 32, 241, 8, 253, 2, 256, 129, 64, 225, 16, 249, 4, 255, 1, 128, 193, 32, 241, 8, 253, 2, 256, 129, 64, 225, 16, 249, 4, 255, 1, 128, 193, 32, 241, 8, 253, 2, 256, 129, 64, 225, 16, 249, 4, 255, 1, 128, 193, 32, 241, 8, 253, 2, 256, 129, 64, 225, 16, 249, 4, 255, 1, 128, 193, 32, 241, 8, 253, 2, 256, 129, 64, 225, 16, 249, 4, 255, 1, 128, 193, 32, 241, 8, 253, 2, 256, 129, 64, 225, 16, 249, 4, 255, 1, 128, 193, 32, 241, 8, 253, 2, 256, 129, 64, 225, 16, 249, 4, 255, 1, 128, 193, 32, 241, 8, 253, 2, 256, 129, 64, 225, 16, 249, 4, 255, 1, 128, 193, 32, 241, 8, 253, 2, 256, 129, 64, 225, 16, 249, 4, 255, 1, 128, 193, 32, 241, 8, 253, 2, 256, 129, 64, 225, 16, 249, 4, 255, 1, 128, 193, 32, 241, 8, 253, 2, 256, 129, 64, 225, 16, 249, 4, 255, 1, 128, 193, 32, 241, 8, 253, 2, 256, 129, 64, 225, 16, 249, 4, 255, 1, 128, 193, 32, 241, 8, 253, 2, 256, 129, 64, 225, 16, 249, 4, 255, 1, 128, 193, 32, 241, 8, 253, 2, 256, 129, 64, 225, 16, 249, 4, 255, 1], +[1, 129, 193, 225, 241, 249, 253, 255, 256, 128, 64, 32, 16, 8, 4, 2, 1, 129, 193, 225, 241, 249, 253, 255, 256, 128, 64, 32, 16, 8, 4, 2, 1, 129, 193, 225, 241, 249, 253, 255, 256, 128, 64, 32, 16, 8, 4, 2, 1, 129, 193, 225, 241, 249, 253, 255, 256, 128, 64, 32, 16, 8, 4, 2, 1, 129, 193, 225, 241, 249, 253, 255, 256, 128, 64, 32, 16, 8, 4, 2, 1, 129, 193, 225, 241, 249, 253, 255, 256, 128, 64, 32, 16, 8, 4, 2, 1, 129, 193, 225, 241, 249, 253, 255, 256, 128, 64, 32, 16, 8, 4, 2, 1, 129, 193, 225, 241, 249, 253, 255, 256, 128, 64, 32, 16, 8, 4, 2, 1, 129, 193, 225, 241, 249, 253, 255, 256, 128, 64, 32, 16, 8, 4, 2, 1, 129, 193, 225, 241, 249, 253, 255, 256, 128, 64, 32, 16, 8, 4, 2, 1, 129, 193, 225, 241, 249, 253, 255, 256, 128, 64, 32, 16, 8, 4, 2, 1, 129, 193, 225, 241, 249, 253, 255, 256, 128, 64, 32, 16, 8, 4, 2, 1, 129, 193, 225, 241, 249, 253, 255, 256, 128, 64, 32, 16, 8, 4, 2, 1, 129, 193, 225, 241, 249, 253, 255, 256, 128, 64, 32, 16, 8, 4, 2, 1, 129, 193, 225, 241, 249, 253, 255, 256, 128, 64, 32, 16, 8, 4, 2, 1, 129, 193, 225, 241, 249, 253, 255, 256, 128, 64, 32, 16, 8, 4, 2, 1], +[1, 130, 195, 164, 246, 112, 168, 252, 121, 53, 208, 55, 211, 188, 25, 166, 249, 245, 239, 230, 88, 132, 198, 40, 60, 90, 135, 74, 111, 38, 57, 214, 64, 96, 144, 216, 67, 229, 215, 194, 34, 51, 205, 179, 140, 210, 58, 87, 2, 3, 133, 71, 235, 224, 79, 247, 242, 106, 159, 110, 165, 119, 50, 75, 241, 233, 221, 203, 176, 7, 139, 80, 120, 180, 13, 148, 222, 76, 114, 171, 128, 192, 31, 175, 134, 201, 173, 131, 68, 102, 153, 101, 23, 163, 116, 174, 4, 6, 9, 142, 213, 191, 158, 237, 227, 212, 61, 220, 73, 238, 100, 150, 225, 209, 185, 149, 95, 14, 21, 160, 240, 103, 26, 39, 187, 152, 228, 85, 256, 127, 62, 93, 11, 145, 89, 5, 136, 204, 49, 202, 46, 69, 232, 91, 8, 12, 18, 27, 169, 125, 59, 217, 197, 167, 122, 183, 146, 219, 200, 43, 193, 161, 113, 41, 190, 28, 42, 63, 223, 206, 52, 78, 117, 47, 199, 170, 255, 254, 124, 186, 22, 33, 178, 10, 15, 151, 98, 147, 92, 138, 207, 182, 16, 24, 36, 54, 81, 250, 118, 177, 137, 77, 244, 109, 35, 181, 143, 86, 129, 65, 226, 82, 123, 56, 84, 126, 189, 155, 104, 156, 234, 94, 141, 83, 253, 251, 248, 115, 44, 66, 99, 20, 30, 45, 196, 37, 184, 19, 157, 107, 32, 48, 72, 108, 162, 243, 236, 97, 17, 154, 231, 218, 70, 105, 29, 172, 1], +[1, 131, 199, 112, 23, 186, 208, 6, 15, 166, 158, 138, 88, 220, 36, 90, 225, 177, 57, 14, 35, 216, 26, 65, 34, 85, 84, 210, 11, 156, 133, 204, 253, 247, 232, 66, 165, 27, 196, 233, 197, 107, 139, 219, 162, 148, 113, 154, 128, 63, 29, 201, 117, 164, 153, 254, 121, 174, 178, 188, 213, 147, 239, 212, 16, 40, 100, 250, 111, 149, 244, 96, 240, 86, 215, 152, 123, 179, 62, 155, 2, 5, 141, 224, 46, 115, 159, 12, 30, 75, 59, 19, 176, 183, 72, 180, 193, 97, 114, 28, 70, 175, 52, 130, 68, 170, 168, 163, 22, 55, 9, 151, 249, 237, 207, 132, 73, 54, 135, 209, 137, 214, 21, 181, 67, 39, 226, 51, 256, 126, 58, 145, 234, 71, 49, 251, 242, 91, 99, 119, 169, 37, 221, 167, 32, 80, 200, 243, 222, 41, 231, 192, 223, 172, 173, 47, 246, 101, 124, 53, 4, 10, 25, 191, 92, 230, 61, 24, 60, 150, 118, 38, 95, 109, 144, 103, 129, 194, 228, 56, 140, 93, 104, 3, 136, 83, 79, 69, 44, 110, 18, 45, 241, 217, 157, 7, 146, 108, 13, 161, 17, 171, 42, 105, 134, 78, 195, 102, 255, 252, 116, 33, 211, 142, 98, 245, 227, 182, 198, 238, 81, 74, 185, 77, 64, 160, 143, 229, 187, 82, 205, 127, 189, 87, 89, 94, 235, 202, 248, 106, 8, 20, 50, 125, 184, 203, 122, 48, 120, 43, 236, 76, 190, 218, 31, 206, 1], +[1, 132, 205, 75, 134, 212, 228, 27, 223, 138, 226, 20, 70, 245, 215, 110, 128, 191, 26, 91, 190, 151, 143, 115, 17, 188, 144, 247, 222, 6, 21, 202, 193, 33, 244, 83, 162, 53, 57, 71, 120, 163, 185, 5, 146, 254, 118, 156, 32, 112, 135, 87, 176, 102, 100, 93, 197, 47, 36, 126, 184, 130, 198, 179, 241, 201, 61, 85, 169, 206, 207, 82, 30, 105, 239, 194, 165, 192, 158, 39, 8, 28, 98, 86, 44, 154, 25, 216, 242, 76, 9, 160, 46, 161, 178, 109, 253, 243, 208, 214, 235, 180, 116, 149, 136, 219, 124, 177, 234, 48, 168, 74, 2, 7, 153, 150, 11, 167, 199, 54, 189, 19, 195, 40, 140, 233, 173, 220, 256, 125, 52, 182, 123, 45, 29, 230, 34, 119, 31, 237, 187, 12, 42, 147, 129, 66, 231, 166, 67, 106, 114, 142, 240, 69, 113, 10, 35, 251, 236, 55, 64, 224, 13, 174, 95, 204, 200, 186, 137, 94, 72, 252, 111, 3, 139, 101, 225, 145, 122, 170, 81, 155, 157, 164, 60, 210, 221, 131, 73, 127, 59, 78, 16, 56, 196, 172, 88, 51, 50, 175, 227, 152, 18, 63, 92, 65, 99, 218, 249, 229, 159, 171, 213, 103, 232, 41, 15, 181, 248, 97, 211, 96, 79, 148, 4, 14, 49, 43, 22, 77, 141, 108, 121, 38, 133, 80, 23, 209, 89, 183, 255, 250, 104, 107, 246, 90, 58, 203, 68, 238, 62, 217, 117, 24, 84, 37, 1], +[1, 133, 213, 59, 137, 231, 140, 116, 8, 36, 162, 215, 68, 49, 92, 157, 64, 31, 11, 178, 30, 135, 222, 228, 255, 248, 88, 139, 240, 52, 234, 25, 241, 185, 190, 84, 121, 159, 73, 200, 129, 195, 235, 158, 197, 244, 70, 58, 4, 18, 81, 236, 34, 153, 46, 207, 32, 144, 134, 89, 15, 196, 111, 114, 256, 124, 44, 198, 120, 26, 117, 141, 249, 221, 95, 42, 189, 208, 165, 100, 193, 226, 246, 79, 227, 122, 35, 29, 2, 9, 169, 118, 17, 205, 23, 232, 16, 72, 67, 173, 136, 98, 184, 57, 128, 62, 22, 99, 60, 13, 187, 199, 253, 239, 176, 21, 223, 104, 211, 50, 225, 113, 123, 168, 242, 61, 146, 143, 1, 133, 213, 59, 137, 231, 140, 116, 8, 36, 162, 215, 68, 49, 92, 157, 64, 31, 11, 178, 30, 135, 222, 228, 255, 248, 88, 139, 240, 52, 234, 25, 241, 185, 190, 84, 121, 159, 73, 200, 129, 195, 235, 158, 197, 244, 70, 58, 4, 18, 81, 236, 34, 153, 46, 207, 32, 144, 134, 89, 15, 196, 111, 114, 256, 124, 44, 198, 120, 26, 117, 141, 249, 221, 95, 42, 189, 208, 165, 100, 193, 226, 246, 79, 227, 122, 35, 29, 2, 9, 169, 118, 17, 205, 23, 232, 16, 72, 67, 173, 136, 98, 184, 57, 128, 62, 22, 99, 60, 13, 187, 199, 253, 239, 176, 21, 223, 104, 211, 50, 225, 113, 123, 168, 242, 61, 146, 143, 1], +[1, 134, 223, 70, 128, 190, 17, 222, 193, 162, 120, 146, 32, 176, 197, 184, 241, 169, 30, 165, 8, 44, 242, 46, 253, 235, 136, 234, 2, 11, 189, 140, 256, 123, 34, 187, 129, 67, 240, 35, 64, 95, 137, 111, 225, 81, 60, 73, 16, 88, 227, 92, 249, 213, 15, 211, 4, 22, 121, 23, 255, 246, 68, 117, 1, 134, 223, 70, 128, 190, 17, 222, 193, 162, 120, 146, 32, 176, 197, 184, 241, 169, 30, 165, 8, 44, 242, 46, 253, 235, 136, 234, 2, 11, 189, 140, 256, 123, 34, 187, 129, 67, 240, 35, 64, 95, 137, 111, 225, 81, 60, 73, 16, 88, 227, 92, 249, 213, 15, 211, 4, 22, 121, 23, 255, 246, 68, 117, 1, 134, 223, 70, 128, 190, 17, 222, 193, 162, 120, 146, 32, 176, 197, 184, 241, 169, 30, 165, 8, 44, 242, 46, 253, 235, 136, 234, 2, 11, 189, 140, 256, 123, 34, 187, 129, 67, 240, 35, 64, 95, 137, 111, 225, 81, 60, 73, 16, 88, 227, 92, 249, 213, 15, 211, 4, 22, 121, 23, 255, 246, 68, 117, 1, 134, 223, 70, 128, 190, 17, 222, 193, 162, 120, 146, 32, 176, 197, 184, 241, 169, 30, 165, 8, 44, 242, 46, 253, 235, 136, 234, 2, 11, 189, 140, 256, 123, 34, 187, 129, 67, 240, 35, 64, 95, 137, 111, 225, 81, 60, 73, 16, 88, 227, 92, 249, 213, 15, 211, 4, 22, 121, 23, 255, 246, 68, 117, 1], +[1, 135, 235, 114, 227, 62, 146, 178, 129, 196, 246, 57, 242, 31, 73, 89, 193, 98, 123, 157, 121, 144, 165, 173, 225, 49, 190, 207, 189, 72, 211, 215, 241, 153, 95, 232, 223, 36, 234, 236, 249, 205, 176, 116, 240, 18, 117, 118, 253, 231, 88, 58, 120, 9, 187, 59, 255, 244, 44, 29, 60, 133, 222, 158, 256, 122, 22, 143, 30, 195, 111, 79, 128, 61, 11, 200, 15, 226, 184, 168, 64, 159, 134, 100, 136, 113, 92, 84, 32, 208, 67, 50, 68, 185, 46, 42, 16, 104, 162, 25, 34, 221, 23, 21, 8, 52, 81, 141, 17, 239, 140, 139, 4, 26, 169, 199, 137, 248, 70, 198, 2, 13, 213, 228, 197, 124, 35, 99, 1, 135, 235, 114, 227, 62, 146, 178, 129, 196, 246, 57, 242, 31, 73, 89, 193, 98, 123, 157, 121, 144, 165, 173, 225, 49, 190, 207, 189, 72, 211, 215, 241, 153, 95, 232, 223, 36, 234, 236, 249, 205, 176, 116, 240, 18, 117, 118, 253, 231, 88, 58, 120, 9, 187, 59, 255, 244, 44, 29, 60, 133, 222, 158, 256, 122, 22, 143, 30, 195, 111, 79, 128, 61, 11, 200, 15, 226, 184, 168, 64, 159, 134, 100, 136, 113, 92, 84, 32, 208, 67, 50, 68, 185, 46, 42, 16, 104, 162, 25, 34, 221, 23, 21, 8, 52, 81, 141, 17, 239, 140, 139, 4, 26, 169, 199, 137, 248, 70, 198, 2, 13, 213, 228, 197, 124, 35, 99, 1], +[1, 136, 249, 197, 64, 223, 2, 15, 241, 137, 128, 189, 4, 30, 225, 17, 256, 121, 8, 60, 193, 34, 255, 242, 16, 120, 129, 68, 253, 227, 32, 240, 1, 136, 249, 197, 64, 223, 2, 15, 241, 137, 128, 189, 4, 30, 225, 17, 256, 121, 8, 60, 193, 34, 255, 242, 16, 120, 129, 68, 253, 227, 32, 240, 1, 136, 249, 197, 64, 223, 2, 15, 241, 137, 128, 189, 4, 30, 225, 17, 256, 121, 8, 60, 193, 34, 255, 242, 16, 120, 129, 68, 253, 227, 32, 240, 1, 136, 249, 197, 64, 223, 2, 15, 241, 137, 128, 189, 4, 30, 225, 17, 256, 121, 8, 60, 193, 34, 255, 242, 16, 120, 129, 68, 253, 227, 32, 240, 1, 136, 249, 197, 64, 223, 2, 15, 241, 137, 128, 189, 4, 30, 225, 17, 256, 121, 8, 60, 193, 34, 255, 242, 16, 120, 129, 68, 253, 227, 32, 240, 1, 136, 249, 197, 64, 223, 2, 15, 241, 137, 128, 189, 4, 30, 225, 17, 256, 121, 8, 60, 193, 34, 255, 242, 16, 120, 129, 68, 253, 227, 32, 240, 1, 136, 249, 197, 64, 223, 2, 15, 241, 137, 128, 189, 4, 30, 225, 17, 256, 121, 8, 60, 193, 34, 255, 242, 16, 120, 129, 68, 253, 227, 32, 240, 1, 136, 249, 197, 64, 223, 2, 15, 241, 137, 128, 189, 4, 30, 225, 17, 256, 121, 8, 60, 193, 34, 255, 242, 16, 120, 129, 68, 253, 227, 32, 240, 1], +[1, 137, 8, 68, 64, 30, 255, 240, 241, 121, 129, 197, 4, 34, 32, 15, 256, 120, 249, 189, 193, 227, 2, 17, 16, 136, 128, 60, 253, 223, 225, 242, 1, 137, 8, 68, 64, 30, 255, 240, 241, 121, 129, 197, 4, 34, 32, 15, 256, 120, 249, 189, 193, 227, 2, 17, 16, 136, 128, 60, 253, 223, 225, 242, 1, 137, 8, 68, 64, 30, 255, 240, 241, 121, 129, 197, 4, 34, 32, 15, 256, 120, 249, 189, 193, 227, 2, 17, 16, 136, 128, 60, 253, 223, 225, 242, 1, 137, 8, 68, 64, 30, 255, 240, 241, 121, 129, 197, 4, 34, 32, 15, 256, 120, 249, 189, 193, 227, 2, 17, 16, 136, 128, 60, 253, 223, 225, 242, 1, 137, 8, 68, 64, 30, 255, 240, 241, 121, 129, 197, 4, 34, 32, 15, 256, 120, 249, 189, 193, 227, 2, 17, 16, 136, 128, 60, 253, 223, 225, 242, 1, 137, 8, 68, 64, 30, 255, 240, 241, 121, 129, 197, 4, 34, 32, 15, 256, 120, 249, 189, 193, 227, 2, 17, 16, 136, 128, 60, 253, 223, 225, 242, 1, 137, 8, 68, 64, 30, 255, 240, 241, 121, 129, 197, 4, 34, 32, 15, 256, 120, 249, 189, 193, 227, 2, 17, 16, 136, 128, 60, 253, 223, 225, 242, 1, 137, 8, 68, 64, 30, 255, 240, 241, 121, 129, 197, 4, 34, 32, 15, 256, 120, 249, 189, 193, 227, 2, 17, 16, 136, 128, 60, 253, 223, 225, 242, 1], +[1, 138, 26, 247, 162, 254, 100, 179, 30, 28, 9, 214, 234, 167, 173, 230, 129, 69, 13, 252, 81, 127, 50, 218, 15, 14, 133, 107, 117, 212, 215, 115, 193, 163, 135, 126, 169, 192, 25, 109, 136, 7, 195, 182, 187, 106, 236, 186, 225, 210, 196, 63, 213, 96, 141, 183, 68, 132, 226, 91, 222, 53, 118, 93, 241, 105, 98, 160, 235, 48, 199, 220, 34, 66, 113, 174, 111, 155, 59, 175, 249, 181, 49, 80, 246, 24, 228, 110, 17, 33, 185, 87, 184, 206, 158, 216, 253, 219, 153, 40, 123, 12, 114, 55, 137, 145, 221, 172, 92, 103, 79, 108, 255, 238, 205, 20, 190, 6, 57, 156, 197, 201, 239, 86, 46, 180, 168, 54, 256, 119, 231, 10, 95, 3, 157, 78, 227, 229, 248, 43, 23, 90, 84, 27, 128, 188, 244, 5, 176, 130, 207, 39, 242, 243, 124, 150, 140, 45, 42, 142, 64, 94, 122, 131, 88, 65, 232, 148, 121, 250, 62, 75, 70, 151, 21, 71, 32, 47, 61, 194, 44, 161, 116, 74, 189, 125, 31, 166, 35, 204, 139, 164, 16, 152, 159, 97, 22, 209, 58, 37, 223, 191, 144, 83, 146, 102, 198, 82, 8, 76, 208, 177, 11, 233, 29, 147, 240, 224, 72, 170, 73, 51, 99, 41, 4, 38, 104, 217, 134, 245, 143, 202, 120, 112, 36, 85, 165, 154, 178, 149, 2, 19, 52, 237, 67, 251, 200, 101, 60, 56, 18, 171, 211, 77, 89, 203, 1], +[1, 139, 46, 226, 60, 116, 190, 196, 2, 21, 92, 195, 120, 232, 123, 135, 4, 42, 184, 133, 240, 207, 246, 13, 8, 84, 111, 9, 223, 157, 235, 26, 16, 168, 222, 18, 189, 57, 213, 52, 32, 79, 187, 36, 121, 114, 169, 104, 64, 158, 117, 72, 242, 228, 81, 208, 128, 59, 234, 144, 227, 199, 162, 159, 256, 118, 211, 31, 197, 141, 67, 61, 255, 236, 165, 62, 137, 25, 134, 122, 253, 215, 73, 124, 17, 50, 11, 244, 249, 173, 146, 248, 34, 100, 22, 231, 241, 89, 35, 239, 68, 200, 44, 205, 225, 178, 70, 221, 136, 143, 88, 153, 193, 99, 140, 185, 15, 29, 176, 49, 129, 198, 23, 113, 30, 58, 95, 98, 1, 139, 46, 226, 60, 116, 190, 196, 2, 21, 92, 195, 120, 232, 123, 135, 4, 42, 184, 133, 240, 207, 246, 13, 8, 84, 111, 9, 223, 157, 235, 26, 16, 168, 222, 18, 189, 57, 213, 52, 32, 79, 187, 36, 121, 114, 169, 104, 64, 158, 117, 72, 242, 228, 81, 208, 128, 59, 234, 144, 227, 199, 162, 159, 256, 118, 211, 31, 197, 141, 67, 61, 255, 236, 165, 62, 137, 25, 134, 122, 253, 215, 73, 124, 17, 50, 11, 244, 249, 173, 146, 248, 34, 100, 22, 231, 241, 89, 35, 239, 68, 200, 44, 205, 225, 178, 70, 221, 136, 143, 88, 153, 193, 99, 140, 185, 15, 29, 176, 49, 129, 198, 23, 113, 30, 58, 95, 98, 1], +[1, 140, 68, 11, 255, 234, 121, 235, 4, 46, 15, 44, 249, 165, 227, 169, 16, 184, 60, 176, 225, 146, 137, 162, 64, 222, 240, 190, 129, 70, 34, 134, 256, 117, 189, 246, 2, 23, 136, 22, 253, 211, 242, 213, 8, 92, 30, 88, 241, 73, 197, 81, 32, 111, 120, 95, 193, 35, 17, 67, 128, 187, 223, 123, 1, 140, 68, 11, 255, 234, 121, 235, 4, 46, 15, 44, 249, 165, 227, 169, 16, 184, 60, 176, 225, 146, 137, 162, 64, 222, 240, 190, 129, 70, 34, 134, 256, 117, 189, 246, 2, 23, 136, 22, 253, 211, 242, 213, 8, 92, 30, 88, 241, 73, 197, 81, 32, 111, 120, 95, 193, 35, 17, 67, 128, 187, 223, 123, 1, 140, 68, 11, 255, 234, 121, 235, 4, 46, 15, 44, 249, 165, 227, 169, 16, 184, 60, 176, 225, 146, 137, 162, 64, 222, 240, 190, 129, 70, 34, 134, 256, 117, 189, 246, 2, 23, 136, 22, 253, 211, 242, 213, 8, 92, 30, 88, 241, 73, 197, 81, 32, 111, 120, 95, 193, 35, 17, 67, 128, 187, 223, 123, 1, 140, 68, 11, 255, 234, 121, 235, 4, 46, 15, 44, 249, 165, 227, 169, 16, 184, 60, 176, 225, 146, 137, 162, 64, 222, 240, 190, 129, 70, 34, 134, 256, 117, 189, 246, 2, 23, 136, 22, 253, 211, 242, 213, 8, 92, 30, 88, 241, 73, 197, 81, 32, 111, 120, 95, 193, 35, 17, 67, 128, 187, 223, 123, 1], +[1, 141, 92, 122, 240, 173, 235, 239, 32, 143, 117, 49, 227, 139, 67, 195, 253, 207, 146, 26, 68, 79, 88, 72, 129, 199, 46, 61, 120, 215, 246, 248, 16, 200, 187, 153, 242, 198, 162, 226, 255, 232, 73, 13, 34, 168, 44, 36, 193, 228, 23, 159, 60, 236, 123, 124, 8, 100, 222, 205, 121, 99, 81, 113, 256, 116, 165, 135, 17, 84, 22, 18, 225, 114, 140, 208, 30, 118, 190, 62, 4, 50, 111, 231, 189, 178, 169, 185, 128, 58, 211, 196, 137, 42, 11, 9, 241, 57, 70, 104, 15, 59, 95, 31, 2, 25, 184, 244, 223, 89, 213, 221, 64, 29, 234, 98, 197, 21, 134, 133, 249, 157, 35, 52, 136, 158, 176, 144, 1, 141, 92, 122, 240, 173, 235, 239, 32, 143, 117, 49, 227, 139, 67, 195, 253, 207, 146, 26, 68, 79, 88, 72, 129, 199, 46, 61, 120, 215, 246, 248, 16, 200, 187, 153, 242, 198, 162, 226, 255, 232, 73, 13, 34, 168, 44, 36, 193, 228, 23, 159, 60, 236, 123, 124, 8, 100, 222, 205, 121, 99, 81, 113, 256, 116, 165, 135, 17, 84, 22, 18, 225, 114, 140, 208, 30, 118, 190, 62, 4, 50, 111, 231, 189, 178, 169, 185, 128, 58, 211, 196, 137, 42, 11, 9, 241, 57, 70, 104, 15, 59, 95, 31, 2, 25, 184, 244, 223, 89, 213, 221, 64, 29, 234, 98, 197, 21, 134, 133, 249, 157, 35, 52, 136, 158, 176, 144, 1], +[1, 142, 118, 51, 46, 107, 31, 33, 60, 39, 141, 233, 190, 252, 61, 181, 2, 27, 236, 102, 92, 214, 62, 66, 120, 78, 25, 209, 123, 247, 122, 105, 4, 54, 215, 204, 184, 171, 124, 132, 240, 156, 50, 161, 246, 237, 244, 210, 8, 108, 173, 151, 111, 85, 248, 7, 223, 55, 100, 65, 235, 217, 231, 163, 16, 216, 89, 45, 222, 170, 239, 14, 189, 110, 200, 130, 213, 177, 205, 69, 32, 175, 178, 90, 187, 83, 221, 28, 121, 220, 143, 3, 169, 97, 153, 138, 64, 93, 99, 180, 117, 166, 185, 56, 242, 183, 29, 6, 81, 194, 49, 19, 128, 186, 198, 103, 234, 75, 113, 112, 227, 109, 58, 12, 162, 131, 98, 38, 256, 115, 139, 206, 211, 150, 226, 224, 197, 218, 116, 24, 67, 5, 196, 76, 255, 230, 21, 155, 165, 43, 195, 191, 137, 179, 232, 48, 134, 10, 135, 152, 253, 203, 42, 53, 73, 86, 133, 125, 17, 101, 207, 96, 11, 20, 13, 47, 249, 149, 84, 106, 146, 172, 9, 250, 34, 202, 157, 192, 22, 40, 26, 94, 241, 41, 168, 212, 35, 87, 18, 243, 68, 147, 57, 127, 44, 80, 52, 188, 225, 82, 79, 167, 70, 174, 36, 229, 136, 37, 114, 254, 88, 160, 104, 119, 193, 164, 158, 77, 140, 91, 72, 201, 15, 74, 228, 251, 176, 63, 208, 238, 129, 71, 59, 154, 23, 182, 144, 145, 30, 148, 199, 245, 95, 126, 159, 219, 1], +[1, 143, 146, 61, 242, 168, 123, 113, 225, 50, 211, 104, 223, 21, 176, 239, 253, 199, 187, 13, 60, 99, 22, 62, 128, 57, 184, 98, 136, 173, 67, 72, 16, 232, 23, 205, 17, 118, 169, 9, 2, 29, 35, 122, 227, 79, 246, 226, 193, 100, 165, 208, 189, 42, 95, 221, 249, 141, 117, 26, 120, 198, 44, 124, 256, 114, 111, 196, 15, 89, 134, 144, 32, 207, 46, 153, 34, 236, 81, 18, 4, 58, 70, 244, 197, 158, 235, 195, 129, 200, 73, 159, 121, 84, 190, 185, 241, 25, 234, 52, 240, 139, 88, 248, 255, 228, 222, 135, 30, 178, 11, 31, 64, 157, 92, 49, 68, 215, 162, 36, 8, 116, 140, 231, 137, 59, 213, 133, 1, 143, 146, 61, 242, 168, 123, 113, 225, 50, 211, 104, 223, 21, 176, 239, 253, 199, 187, 13, 60, 99, 22, 62, 128, 57, 184, 98, 136, 173, 67, 72, 16, 232, 23, 205, 17, 118, 169, 9, 2, 29, 35, 122, 227, 79, 246, 226, 193, 100, 165, 208, 189, 42, 95, 221, 249, 141, 117, 26, 120, 198, 44, 124, 256, 114, 111, 196, 15, 89, 134, 144, 32, 207, 46, 153, 34, 236, 81, 18, 4, 58, 70, 244, 197, 158, 235, 195, 129, 200, 73, 159, 121, 84, 190, 185, 241, 25, 234, 52, 240, 139, 88, 248, 255, 228, 222, 135, 30, 178, 11, 31, 64, 157, 92, 49, 68, 215, 162, 36, 8, 116, 140, 231, 137, 59, 213, 133, 1], +[1, 144, 176, 158, 136, 52, 35, 157, 249, 133, 134, 21, 197, 98, 234, 29, 64, 221, 213, 89, 223, 244, 184, 25, 2, 31, 95, 59, 15, 104, 70, 57, 241, 9, 11, 42, 137, 196, 211, 58, 128, 185, 169, 178, 189, 231, 111, 50, 4, 62, 190, 118, 30, 208, 140, 114, 225, 18, 22, 84, 17, 135, 165, 116, 256, 113, 81, 99, 121, 205, 222, 100, 8, 124, 123, 236, 60, 159, 23, 228, 193, 36, 44, 168, 34, 13, 73, 232, 255, 226, 162, 198, 242, 153, 187, 200, 16, 248, 246, 215, 120, 61, 46, 199, 129, 72, 88, 79, 68, 26, 146, 207, 253, 195, 67, 139, 227, 49, 117, 143, 32, 239, 235, 173, 240, 122, 92, 141, 1, 144, 176, 158, 136, 52, 35, 157, 249, 133, 134, 21, 197, 98, 234, 29, 64, 221, 213, 89, 223, 244, 184, 25, 2, 31, 95, 59, 15, 104, 70, 57, 241, 9, 11, 42, 137, 196, 211, 58, 128, 185, 169, 178, 189, 231, 111, 50, 4, 62, 190, 118, 30, 208, 140, 114, 225, 18, 22, 84, 17, 135, 165, 116, 256, 113, 81, 99, 121, 205, 222, 100, 8, 124, 123, 236, 60, 159, 23, 228, 193, 36, 44, 168, 34, 13, 73, 232, 255, 226, 162, 198, 242, 153, 187, 200, 16, 248, 246, 215, 120, 61, 46, 199, 129, 72, 88, 79, 68, 26, 146, 207, 253, 195, 67, 139, 227, 49, 117, 143, 32, 239, 235, 173, 240, 122, 92, 141, 1], +[1, 145, 208, 91, 88, 167, 57, 41, 34, 47, 133, 10, 165, 24, 139, 109, 128, 56, 153, 83, 213, 45, 100, 108, 240, 105, 62, 252, 46, 245, 59, 74, 193, 229, 52, 87, 22, 106, 207, 203, 137, 76, 226, 131, 234, 6, 99, 220, 32, 14, 231, 85, 246, 204, 25, 27, 60, 219, 144, 63, 140, 254, 79, 147, 241, 250, 13, 86, 134, 155, 116, 115, 227, 19, 185, 97, 187, 130, 89, 55, 8, 132, 122, 214, 190, 51, 199, 71, 15, 119, 36, 80, 35, 192, 84, 101, 253, 191, 196, 150, 162, 103, 29, 93, 121, 69, 239, 217, 111, 161, 215, 78, 2, 33, 159, 182, 176, 77, 114, 82, 68, 94, 9, 20, 73, 48, 21, 218, 256, 112, 49, 166, 169, 90, 200, 216, 223, 210, 124, 247, 92, 233, 118, 148, 129, 201, 104, 174, 44, 212, 157, 149, 17, 152, 195, 5, 211, 12, 198, 183, 64, 28, 205, 170, 235, 151, 50, 54, 120, 181, 31, 126, 23, 251, 158, 37, 225, 243, 26, 172, 11, 53, 232, 230, 197, 38, 113, 194, 117, 3, 178, 110, 16, 7, 244, 171, 123, 102, 141, 142, 30, 238, 72, 160, 70, 127, 168, 202, 249, 125, 135, 43, 67, 206, 58, 186, 242, 138, 221, 177, 222, 65, 173, 156, 4, 66, 61, 107, 95, 154, 228, 164, 136, 188, 18, 40, 146, 96, 42, 179, 255, 224, 98, 75, 81, 180, 143, 175, 189, 163, 248, 237, 184, 209, 236, 39, 1], +[1, 146, 242, 123, 225, 211, 223, 176, 253, 187, 60, 22, 128, 184, 136, 67, 16, 23, 17, 169, 2, 35, 227, 246, 193, 165, 189, 95, 249, 117, 120, 44, 256, 111, 15, 134, 32, 46, 34, 81, 4, 70, 197, 235, 129, 73, 121, 190, 241, 234, 240, 88, 255, 222, 30, 11, 64, 92, 68, 162, 8, 140, 137, 213, 1, 146, 242, 123, 225, 211, 223, 176, 253, 187, 60, 22, 128, 184, 136, 67, 16, 23, 17, 169, 2, 35, 227, 246, 193, 165, 189, 95, 249, 117, 120, 44, 256, 111, 15, 134, 32, 46, 34, 81, 4, 70, 197, 235, 129, 73, 121, 190, 241, 234, 240, 88, 255, 222, 30, 11, 64, 92, 68, 162, 8, 140, 137, 213, 1, 146, 242, 123, 225, 211, 223, 176, 253, 187, 60, 22, 128, 184, 136, 67, 16, 23, 17, 169, 2, 35, 227, 246, 193, 165, 189, 95, 249, 117, 120, 44, 256, 111, 15, 134, 32, 46, 34, 81, 4, 70, 197, 235, 129, 73, 121, 190, 241, 234, 240, 88, 255, 222, 30, 11, 64, 92, 68, 162, 8, 140, 137, 213, 1, 146, 242, 123, 225, 211, 223, 176, 253, 187, 60, 22, 128, 184, 136, 67, 16, 23, 17, 169, 2, 35, 227, 246, 193, 165, 189, 95, 249, 117, 120, 44, 256, 111, 15, 134, 32, 46, 34, 81, 4, 70, 197, 235, 129, 73, 121, 190, 241, 234, 240, 88, 255, 222, 30, 11, 64, 92, 68, 162, 8, 140, 137, 213, 1], +[1, 147, 21, 3, 184, 63, 9, 38, 189, 27, 114, 53, 81, 85, 159, 243, 255, 220, 215, 251, 146, 131, 239, 181, 136, 203, 29, 151, 95, 87, 196, 28, 4, 74, 84, 12, 222, 252, 36, 152, 242, 108, 199, 212, 67, 83, 122, 201, 249, 109, 89, 233, 70, 10, 185, 210, 30, 41, 116, 90, 123, 91, 13, 112, 16, 39, 79, 48, 117, 237, 144, 94, 197, 175, 25, 77, 11, 75, 231, 33, 225, 179, 99, 161, 23, 40, 226, 69, 120, 164, 207, 103, 235, 107, 52, 191, 64, 156, 59, 192, 211, 177, 62, 119, 17, 186, 100, 51, 44, 43, 153, 132, 129, 202, 139, 130, 92, 160, 133, 19, 223, 142, 57, 155, 169, 171, 208, 250, 256, 110, 236, 254, 73, 194, 248, 219, 68, 230, 143, 204, 176, 172, 98, 14, 2, 37, 42, 6, 111, 126, 18, 76, 121, 54, 228, 106, 162, 170, 61, 229, 253, 183, 173, 245, 35, 5, 221, 105, 15, 149, 58, 45, 190, 174, 135, 56, 8, 148, 168, 24, 187, 247, 72, 47, 227, 216, 141, 167, 134, 166, 244, 145, 241, 218, 178, 209, 140, 20, 113, 163, 60, 82, 232, 180, 246, 182, 26, 224, 32, 78, 158, 96, 234, 217, 31, 188, 137, 93, 50, 154, 22, 150, 205, 66, 193, 101, 198, 65, 46, 80, 195, 138, 240, 71, 157, 206, 213, 214, 104, 125, 128, 55, 118, 127, 165, 97, 124, 238, 34, 115, 200, 102, 88, 86, 49, 7, 1], +[1, 148, 59, 251, 140, 160, 36, 188, 68, 41, 157, 106, 11, 86, 135, 191, 255, 218, 139, 12, 234, 194, 185, 138, 121, 175, 200, 45, 235, 85, 244, 132, 4, 78, 236, 233, 46, 126, 144, 238, 15, 164, 114, 167, 44, 87, 26, 250, 249, 101, 42, 48, 165, 5, 226, 38, 227, 186, 29, 180, 169, 83, 205, 14, 16, 55, 173, 161, 184, 247, 62, 181, 60, 142, 199, 154, 176, 91, 104, 229, 225, 147, 168, 192, 146, 20, 133, 152, 137, 230, 116, 206, 162, 75, 49, 56, 64, 220, 178, 130, 222, 217, 248, 210, 240, 54, 25, 102, 190, 107, 159, 145, 129, 74, 158, 254, 70, 80, 18, 94, 34, 149, 207, 53, 134, 43, 196, 224, 256, 109, 198, 6, 117, 97, 221, 69, 189, 216, 100, 151, 246, 171, 122, 66, 2, 39, 118, 245, 23, 63, 72, 119, 136, 82, 57, 212, 22, 172, 13, 125, 253, 179, 21, 24, 211, 131, 113, 19, 242, 93, 143, 90, 213, 170, 231, 7, 8, 156, 215, 209, 92, 252, 31, 219, 30, 71, 228, 77, 88, 174, 52, 243, 241, 202, 84, 96, 73, 10, 195, 76, 197, 115, 58, 103, 81, 166, 153, 28, 32, 110, 89, 65, 111, 237, 124, 105, 120, 27, 141, 51, 95, 182, 208, 201, 193, 37, 79, 127, 35, 40, 9, 47, 17, 203, 232, 155, 67, 150, 98, 112, 128, 183, 99, 3, 187, 177, 239, 163, 223, 108, 50, 204, 123, 214, 61, 33, 1], +[1, 149, 99, 102, 35, 75, 124, 229, 197, 55, 228, 48, 213, 126, 13, 138, 2, 41, 198, 204, 70, 150, 248, 201, 137, 110, 199, 96, 169, 252, 26, 19, 4, 82, 139, 151, 140, 43, 239, 145, 17, 220, 141, 192, 81, 247, 52, 38, 8, 164, 21, 45, 23, 86, 221, 33, 34, 183, 25, 127, 162, 237, 104, 76, 16, 71, 42, 90, 46, 172, 185, 66, 68, 109, 50, 254, 67, 217, 208, 152, 32, 142, 84, 180, 92, 87, 113, 132, 136, 218, 100, 251, 134, 177, 159, 47, 64, 27, 168, 103, 184, 174, 226, 7, 15, 179, 200, 245, 11, 97, 61, 94, 128, 54, 79, 206, 111, 91, 195, 14, 30, 101, 143, 233, 22, 194, 122, 188, 256, 108, 158, 155, 222, 182, 133, 28, 60, 202, 29, 209, 44, 131, 244, 119, 255, 216, 59, 53, 187, 107, 9, 56, 120, 147, 58, 161, 88, 5, 231, 238, 253, 175, 118, 106, 117, 214, 18, 112, 240, 37, 116, 65, 176, 10, 205, 219, 249, 93, 236, 212, 234, 171, 36, 224, 223, 74, 232, 130, 95, 20, 153, 181, 241, 186, 215, 167, 211, 85, 72, 191, 189, 148, 207, 3, 190, 40, 49, 105, 225, 115, 173, 77, 165, 170, 144, 125, 121, 39, 157, 6, 123, 80, 98, 210, 193, 230, 89, 154, 73, 83, 31, 250, 242, 78, 57, 12, 246, 160, 196, 163, 129, 203, 178, 51, 146, 166, 62, 243, 227, 156, 114, 24, 235, 63, 135, 69, 1], +[1, 150, 141, 76, 92, 179, 122, 53, 240, 20, 173, 250, 235, 41, 239, 127, 32, 174, 143, 119, 117, 74, 49, 154, 227, 126, 139, 33, 67, 27, 195, 209, 253, 171, 207, 210, 146, 55, 26, 45, 68, 177, 79, 28, 88, 93, 72, 6, 129, 75, 199, 38, 46, 218, 61, 155, 120, 10, 215, 125, 246, 149, 248, 192, 16, 87, 200, 188, 187, 37, 153, 77, 242, 63, 198, 145, 162, 142, 226, 233, 255, 214, 232, 105, 73, 156, 13, 151, 34, 217, 168, 14, 44, 175, 36, 3, 193, 166, 228, 19, 23, 109, 159, 206, 60, 5, 236, 191, 123, 203, 124, 96, 8, 172, 100, 94, 222, 147, 205, 167, 121, 160, 99, 201, 81, 71, 113, 245, 256, 107, 116, 181, 165, 78, 135, 204, 17, 237, 84, 7, 22, 216, 18, 130, 225, 83, 114, 138, 140, 183, 208, 103, 30, 131, 118, 224, 190, 230, 62, 48, 4, 86, 50, 47, 111, 202, 231, 212, 189, 80, 178, 229, 169, 164, 185, 251, 128, 182, 58, 219, 211, 39, 196, 102, 137, 247, 42, 132, 11, 108, 9, 65, 241, 170, 57, 69, 70, 220, 104, 180, 15, 194, 59, 112, 95, 115, 31, 24, 2, 43, 25, 152, 184, 101, 244, 106, 223, 40, 89, 243, 213, 82, 221, 254, 64, 91, 29, 238, 234, 148, 98, 51, 197, 252, 21, 66, 134, 54, 133, 161, 249, 85, 157, 163, 35, 110, 52, 90, 136, 97, 158, 56, 176, 186, 144, 12, 1], +[1, 151, 185, 179, 44, 219, 173, 166, 137, 127, 159, 108, 117, 191, 57, 126, 8, 180, 195, 147, 95, 210, 99, 43, 68, 245, 244, 93, 165, 243, 199, 237, 64, 155, 18, 148, 246, 138, 21, 87, 30, 161, 153, 230, 35, 145, 50, 97, 255, 212, 144, 156, 169, 76, 168, 182, 240, 3, 196, 41, 23, 132, 143, 5, 241, 154, 124, 220, 67, 94, 59, 171, 121, 24, 26, 71, 184, 28, 116, 40, 129, 204, 221, 218, 22, 238, 215, 83, 197, 192, 208, 54, 187, 224, 157, 63, 4, 90, 226, 202, 176, 105, 178, 150, 34, 251, 122, 175, 211, 250, 228, 247, 32, 206, 9, 74, 123, 69, 139, 172, 15, 209, 205, 115, 146, 201, 25, 177, 256, 106, 72, 78, 213, 38, 84, 91, 120, 130, 98, 149, 140, 66, 200, 131, 249, 77, 62, 110, 162, 47, 158, 214, 189, 12, 13, 164, 92, 14, 58, 20, 193, 102, 239, 109, 11, 119, 236, 170, 227, 96, 104, 27, 222, 112, 207, 160, 2, 45, 113, 101, 88, 181, 89, 75, 17, 254, 61, 216, 234, 125, 114, 252, 16, 103, 133, 37, 190, 163, 198, 86, 136, 233, 231, 186, 73, 229, 141, 217, 128, 53, 36, 39, 235, 19, 42, 174, 60, 65, 49, 203, 70, 33, 100, 194, 253, 167, 31, 55, 81, 152, 79, 107, 223, 6, 135, 82, 46, 7, 29, 10, 225, 51, 248, 183, 134, 188, 118, 85, 242, 48, 52, 142, 111, 56, 232, 80, 1], +[1, 152, 231, 160, 162, 209, 157, 220, 30, 191, 248, 174, 234, 102, 84, 175, 129, 76, 244, 80, 81, 233, 207, 110, 15, 224, 124, 87, 117, 51, 42, 216, 193, 38, 122, 40, 169, 245, 232, 55, 136, 112, 62, 172, 187, 154, 21, 108, 225, 19, 61, 20, 213, 251, 116, 156, 68, 56, 31, 86, 222, 77, 139, 54, 241, 138, 159, 10, 235, 254, 58, 78, 34, 28, 144, 43, 111, 167, 198, 27, 249, 69, 208, 5, 246, 127, 29, 39, 17, 14, 72, 150, 184, 212, 99, 142, 253, 163, 104, 131, 123, 192, 143, 148, 137, 7, 36, 75, 92, 106, 178, 71, 255, 210, 52, 194, 190, 96, 200, 74, 197, 132, 18, 166, 46, 53, 89, 164, 256, 105, 26, 97, 95, 48, 100, 37, 227, 66, 9, 83, 23, 155, 173, 82, 128, 181, 13, 177, 176, 24, 50, 147, 242, 33, 133, 170, 140, 206, 215, 41, 64, 219, 135, 217, 88, 12, 25, 202, 121, 145, 195, 85, 70, 103, 236, 149, 32, 238, 196, 237, 44, 6, 141, 101, 189, 201, 226, 171, 35, 180, 118, 203, 16, 119, 98, 247, 22, 3, 199, 179, 223, 229, 113, 214, 146, 90, 59, 230, 8, 188, 49, 252, 11, 130, 228, 218, 240, 243, 185, 107, 73, 45, 158, 115, 4, 94, 153, 126, 134, 65, 114, 109, 120, 250, 221, 182, 165, 151, 79, 186, 2, 47, 205, 63, 67, 161, 57, 183, 60, 125, 239, 91, 211, 204, 168, 93, 1], +[1, 153, 22, 25, 227, 36, 111, 21, 129, 205, 11, 141, 242, 18, 184, 139, 193, 231, 134, 199, 121, 9, 92, 198, 225, 244, 67, 228, 189, 133, 46, 99, 241, 122, 162, 114, 223, 195, 23, 178, 249, 61, 81, 57, 240, 226, 140, 89, 253, 159, 169, 157, 120, 113, 70, 173, 255, 208, 213, 207, 60, 185, 35, 215, 256, 104, 235, 232, 30, 221, 146, 236, 128, 52, 246, 116, 15, 239, 73, 118, 64, 26, 123, 58, 136, 248, 165, 59, 32, 13, 190, 29, 68, 124, 211, 158, 16, 135, 95, 143, 34, 62, 234, 79, 8, 196, 176, 200, 17, 31, 117, 168, 4, 98, 88, 100, 137, 144, 187, 84, 2, 49, 44, 50, 197, 72, 222, 42, 1, 153, 22, 25, 227, 36, 111, 21, 129, 205, 11, 141, 242, 18, 184, 139, 193, 231, 134, 199, 121, 9, 92, 198, 225, 244, 67, 228, 189, 133, 46, 99, 241, 122, 162, 114, 223, 195, 23, 178, 249, 61, 81, 57, 240, 226, 140, 89, 253, 159, 169, 157, 120, 113, 70, 173, 255, 208, 213, 207, 60, 185, 35, 215, 256, 104, 235, 232, 30, 221, 146, 236, 128, 52, 246, 116, 15, 239, 73, 118, 64, 26, 123, 58, 136, 248, 165, 59, 32, 13, 190, 29, 68, 124, 211, 158, 16, 135, 95, 143, 34, 62, 234, 79, 8, 196, 176, 200, 17, 31, 117, 168, 4, 98, 88, 100, 137, 144, 187, 84, 2, 49, 44, 50, 197, 72, 222, 42, 1], +[1, 154, 72, 37, 44, 94, 84, 86, 137, 24, 98, 186, 117, 28, 200, 217, 8, 204, 62, 39, 95, 238, 158, 174, 68, 192, 13, 203, 165, 224, 58, 194, 64, 90, 239, 55, 246, 105, 236, 107, 30, 251, 104, 82, 35, 250, 207, 10, 255, 206, 113, 183, 169, 69, 89, 85, 240, 209, 61, 142, 23, 201, 114, 80, 241, 106, 133, 179, 67, 38, 198, 166, 121, 130, 231, 108, 184, 66, 141, 126, 129, 77, 36, 147, 22, 47, 42, 43, 197, 12, 49, 93, 187, 14, 100, 237, 4, 102, 31, 148, 176, 119, 79, 87, 34, 96, 135, 230, 211, 112, 29, 97, 32, 45, 248, 156, 123, 181, 118, 182, 15, 254, 52, 41, 146, 125, 232, 5, 256, 103, 185, 220, 213, 163, 173, 171, 120, 233, 159, 71, 140, 229, 57, 40, 249, 53, 195, 218, 162, 19, 99, 83, 189, 65, 244, 54, 92, 33, 199, 63, 193, 167, 18, 202, 11, 152, 21, 150, 227, 6, 153, 175, 222, 7, 50, 247, 2, 51, 144, 74, 88, 188, 168, 172, 17, 48, 196, 115, 234, 56, 143, 177, 16, 151, 124, 78, 190, 219, 59, 91, 136, 127, 26, 149, 73, 191, 116, 131, 128, 180, 221, 110, 235, 210, 215, 214, 60, 245, 208, 164, 70, 243, 157, 20, 253, 155, 226, 109, 81, 138, 178, 170, 223, 161, 122, 27, 46, 145, 228, 160, 225, 212, 9, 101, 134, 76, 139, 75, 242, 3, 205, 216, 111, 132, 25, 252, 1], +[1, 155, 124, 202, 213, 119, 198, 107, 137, 161, 26, 175, 140, 112, 141, 10, 8, 212, 221, 74, 162, 181, 42, 85, 68, 3, 208, 115, 92, 125, 100, 80, 64, 154, 226, 78, 11, 163, 79, 166, 30, 24, 122, 149, 222, 229, 29, 126, 255, 204, 9, 110, 88, 19, 118, 43, 240, 192, 205, 164, 234, 33, 232, 237, 241, 90, 72, 109, 190, 152, 173, 87, 121, 251, 98, 27, 73, 7, 57, 97, 129, 206, 62, 101, 235, 188, 99, 182, 197, 209, 13, 216, 70, 56, 199, 5, 4, 106, 239, 37, 81, 219, 21, 171, 34, 130, 104, 186, 46, 191, 50, 40, 32, 77, 113, 39, 134, 210, 168, 83, 15, 12, 61, 203, 111, 243, 143, 63, 256, 102, 133, 55, 44, 138, 59, 150, 120, 96, 231, 82, 117, 145, 116, 247, 249, 45, 36, 183, 95, 76, 215, 172, 189, 254, 49, 142, 165, 132, 157, 177, 193, 103, 31, 179, 246, 94, 178, 91, 227, 233, 135, 108, 35, 28, 228, 131, 2, 53, 248, 147, 169, 238, 139, 214, 17, 65, 52, 93, 23, 224, 25, 20, 16, 167, 185, 148, 67, 105, 84, 170, 136, 6, 159, 230, 184, 250, 200, 160, 128, 51, 195, 156, 22, 69, 158, 75, 60, 48, 244, 41, 187, 201, 58, 252, 253, 151, 18, 220, 176, 38, 236, 86, 223, 127, 153, 71, 211, 66, 207, 217, 225, 180, 144, 218, 123, 47, 89, 174, 242, 245, 196, 54, 146, 14, 114, 194, 1], +[1, 156, 178, 12, 73, 80, 144, 105, 189, 186, 232, 212, 176, 214, 231, 56, 255, 202, 158, 233, 111, 97, 226, 47, 136, 142, 50, 90, 162, 86, 52, 145, 4, 110, 198, 48, 35, 63, 62, 163, 242, 230, 157, 77, 190, 85, 153, 224, 249, 37, 118, 161, 187, 131, 133, 188, 30, 54, 200, 103, 134, 87, 208, 66, 16, 183, 21, 192, 140, 252, 248, 138, 197, 149, 114, 51, 246, 83, 98, 125, 225, 148, 215, 130, 234, 10, 18, 238, 120, 216, 29, 155, 22, 91, 61, 7, 64, 218, 84, 254, 46, 237, 221, 38, 17, 82, 199, 204, 213, 75, 135, 243, 129, 78, 89, 6, 165, 40, 72, 181, 223, 93, 116, 106, 88, 107, 244, 28, 256, 101, 79, 245, 184, 177, 113, 152, 68, 71, 25, 45, 81, 43, 26, 201, 2, 55, 99, 24, 146, 160, 31, 210, 121, 115, 207, 167, 95, 171, 205, 112, 253, 147, 59, 209, 222, 194, 195, 94, 15, 27, 100, 180, 67, 172, 104, 33, 8, 220, 139, 96, 70, 126, 124, 69, 227, 203, 57, 154, 123, 170, 49, 191, 241, 74, 236, 65, 117, 5, 9, 119, 60, 108, 143, 206, 11, 174, 159, 132, 32, 109, 42, 127, 23, 247, 239, 19, 137, 41, 228, 102, 235, 166, 196, 250, 193, 39, 173, 3, 211, 20, 36, 219, 240, 175, 58, 53, 44, 182, 122, 14, 128, 179, 168, 251, 92, 217, 185, 76, 34, 164, 141, 151, 169, 150, 13, 229, 1], +[1, 157, 234, 244, 15, 42, 169, 62, 225, 116, 222, 159, 34, 198, 246, 72, 253, 143, 92, 52, 197, 89, 95, 9, 128, 50, 140, 135, 121, 236, 44, 226, 16, 199, 146, 49, 240, 158, 134, 221, 2, 57, 211, 231, 30, 84, 81, 124, 193, 232, 187, 61, 68, 139, 235, 144, 249, 29, 184, 104, 137, 178, 190, 18, 256, 100, 23, 13, 242, 215, 88, 195, 32, 141, 35, 98, 223, 59, 11, 185, 4, 114, 165, 205, 60, 168, 162, 248, 129, 207, 117, 122, 136, 21, 213, 31, 241, 58, 111, 208, 17, 99, 123, 36, 255, 200, 46, 26, 227, 173, 176, 133, 64, 25, 70, 196, 189, 118, 22, 113, 8, 228, 73, 153, 120, 79, 67, 239, 1, 157, 234, 244, 15, 42, 169, 62, 225, 116, 222, 159, 34, 198, 246, 72, 253, 143, 92, 52, 197, 89, 95, 9, 128, 50, 140, 135, 121, 236, 44, 226, 16, 199, 146, 49, 240, 158, 134, 221, 2, 57, 211, 231, 30, 84, 81, 124, 193, 232, 187, 61, 68, 139, 235, 144, 249, 29, 184, 104, 137, 178, 190, 18, 256, 100, 23, 13, 242, 215, 88, 195, 32, 141, 35, 98, 223, 59, 11, 185, 4, 114, 165, 205, 60, 168, 162, 248, 129, 207, 117, 122, 136, 21, 213, 31, 241, 58, 111, 208, 17, 99, 123, 36, 255, 200, 46, 26, 227, 173, 176, 133, 64, 25, 70, 196, 189, 118, 22, 113, 8, 228, 73, 153, 120, 79, 67, 239, 1], +[1, 158, 35, 133, 197, 29, 213, 244, 2, 59, 70, 9, 137, 58, 169, 231, 4, 118, 140, 18, 17, 116, 81, 205, 8, 236, 23, 36, 34, 232, 162, 153, 16, 215, 46, 72, 68, 207, 67, 49, 32, 173, 92, 144, 136, 157, 134, 98, 64, 89, 184, 31, 15, 57, 11, 196, 128, 178, 111, 62, 30, 114, 22, 135, 256, 99, 222, 124, 60, 228, 44, 13, 255, 198, 187, 248, 120, 199, 88, 26, 253, 139, 117, 239, 240, 141, 176, 52, 249, 21, 234, 221, 223, 25, 95, 104, 241, 42, 211, 185, 189, 50, 190, 208, 225, 84, 165, 113, 121, 100, 123, 159, 193, 168, 73, 226, 242, 200, 246, 61, 129, 79, 146, 195, 227, 143, 235, 122, 1, 158, 35, 133, 197, 29, 213, 244, 2, 59, 70, 9, 137, 58, 169, 231, 4, 118, 140, 18, 17, 116, 81, 205, 8, 236, 23, 36, 34, 232, 162, 153, 16, 215, 46, 72, 68, 207, 67, 49, 32, 173, 92, 144, 136, 157, 134, 98, 64, 89, 184, 31, 15, 57, 11, 196, 128, 178, 111, 62, 30, 114, 22, 135, 256, 99, 222, 124, 60, 228, 44, 13, 255, 198, 187, 248, 120, 199, 88, 26, 253, 139, 117, 239, 240, 141, 176, 52, 249, 21, 234, 221, 223, 25, 95, 104, 241, 42, 211, 185, 189, 50, 190, 208, 225, 84, 165, 113, 121, 100, 123, 159, 193, 168, 73, 226, 242, 200, 246, 61, 129, 79, 146, 195, 227, 143, 235, 122, 1], +[1, 159, 95, 199, 30, 144, 23, 59, 129, 208, 176, 228, 15, 72, 140, 158, 193, 104, 88, 114, 136, 36, 70, 79, 225, 52, 44, 57, 68, 18, 35, 168, 241, 26, 22, 157, 34, 9, 146, 84, 249, 13, 11, 207, 17, 133, 73, 42, 253, 135, 134, 232, 137, 195, 165, 21, 255, 196, 67, 116, 197, 226, 211, 139, 256, 98, 162, 58, 227, 113, 234, 198, 128, 49, 81, 29, 242, 185, 117, 99, 64, 153, 169, 143, 121, 221, 187, 178, 32, 205, 213, 200, 189, 239, 222, 89, 16, 231, 235, 100, 223, 248, 111, 173, 8, 244, 246, 50, 240, 124, 184, 215, 4, 122, 123, 25, 120, 62, 92, 236, 2, 61, 190, 141, 60, 31, 46, 118, 1, 159, 95, 199, 30, 144, 23, 59, 129, 208, 176, 228, 15, 72, 140, 158, 193, 104, 88, 114, 136, 36, 70, 79, 225, 52, 44, 57, 68, 18, 35, 168, 241, 26, 22, 157, 34, 9, 146, 84, 249, 13, 11, 207, 17, 133, 73, 42, 253, 135, 134, 232, 137, 195, 165, 21, 255, 196, 67, 116, 197, 226, 211, 139, 256, 98, 162, 58, 227, 113, 234, 198, 128, 49, 81, 29, 242, 185, 117, 99, 64, 153, 169, 143, 121, 221, 187, 178, 32, 205, 213, 200, 189, 239, 222, 89, 16, 231, 235, 100, 223, 248, 111, 173, 8, 244, 246, 50, 240, 124, 184, 215, 4, 122, 123, 25, 120, 62, 92, 236, 2, 61, 190, 141, 60, 31, 46, 118, 1], +[1, 160, 157, 191, 234, 175, 244, 233, 15, 87, 42, 38, 169, 55, 62, 154, 225, 20, 116, 56, 222, 54, 159, 254, 34, 43, 198, 69, 246, 39, 72, 212, 253, 131, 143, 7, 92, 71, 52, 96, 197, 166, 89, 105, 95, 37, 9, 155, 128, 177, 50, 33, 140, 41, 135, 12, 121, 85, 236, 238, 44, 101, 226, 180, 16, 247, 199, 229, 146, 230, 49, 130, 240, 107, 158, 94, 134, 109, 221, 151, 2, 63, 57, 125, 211, 93, 231, 209, 30, 174, 84, 76, 81, 110, 124, 51, 193, 40, 232, 112, 187, 108, 61, 251, 68, 86, 139, 138, 235, 78, 144, 167, 249, 5, 29, 14, 184, 142, 104, 192, 137, 75, 178, 210, 190, 74, 18, 53, 256, 97, 100, 66, 23, 82, 13, 24, 242, 170, 215, 219, 88, 202, 195, 103, 32, 237, 141, 201, 35, 203, 98, 3, 223, 214, 59, 188, 11, 218, 185, 45, 4, 126, 114, 250, 165, 186, 205, 161, 60, 91, 168, 152, 162, 220, 248, 102, 129, 80, 207, 224, 117, 216, 122, 245, 136, 172, 21, 19, 213, 156, 31, 77, 241, 10, 58, 28, 111, 27, 208, 127, 17, 150, 99, 163, 123, 148, 36, 106, 255, 194, 200, 132, 46, 164, 26, 48, 227, 83, 173, 181, 176, 147, 133, 206, 64, 217, 25, 145, 70, 149, 196, 6, 189, 171, 118, 119, 22, 179, 113, 90, 8, 252, 228, 243, 73, 115, 153, 65, 120, 182, 79, 47, 67, 183, 239, 204, 1], +[1, 161, 221, 115, 11, 229, 118, 237, 121, 206, 13, 37, 46, 210, 143, 150, 249, 254, 31, 108, 169, 224, 84, 160, 60, 151, 153, 218, 146, 119, 141, 85, 64, 24, 9, 164, 190, 7, 99, 5, 34, 77, 61, 55, 117, 76, 157, 91, 2, 65, 185, 230, 22, 201, 236, 217, 242, 155, 26, 74, 92, 163, 29, 43, 241, 251, 62, 216, 81, 191, 168, 63, 120, 45, 49, 179, 35, 238, 25, 170, 128, 48, 18, 71, 123, 14, 198, 10, 68, 154, 122, 110, 234, 152, 57, 182, 4, 130, 113, 203, 44, 145, 215, 177, 227, 53, 52, 148, 184, 69, 58, 86, 225, 245, 124, 175, 162, 125, 79, 126, 240, 90, 98, 101, 70, 219, 50, 83, 256, 96, 36, 142, 246, 28, 139, 20, 136, 51, 244, 220, 211, 47, 114, 107, 8, 3, 226, 149, 88, 33, 173, 97, 197, 106, 104, 39, 111, 138, 116, 172, 193, 233, 248, 93, 67, 250, 158, 252, 223, 180, 196, 202, 140, 181, 100, 166, 255, 192, 72, 27, 235, 56, 21, 40, 15, 102, 231, 183, 165, 94, 228, 214, 16, 6, 195, 41, 176, 66, 89, 194, 137, 212, 208, 78, 222, 19, 232, 87, 129, 209, 239, 186, 134, 243, 59, 247, 189, 103, 135, 147, 23, 105, 200, 75, 253, 127, 144, 54, 213, 112, 42, 80, 30, 204, 205, 109, 73, 188, 199, 171, 32, 12, 133, 82, 95, 132, 178, 131, 17, 167, 159, 156, 187, 38, 207, 174, 1], +[1, 162, 30, 234, 129, 81, 15, 117, 193, 169, 136, 187, 225, 213, 68, 222, 241, 235, 34, 111, 249, 246, 17, 184, 253, 123, 137, 92, 255, 190, 197, 46, 256, 95, 227, 23, 128, 176, 242, 140, 64, 88, 121, 70, 32, 44, 189, 35, 16, 22, 223, 146, 8, 11, 240, 73, 4, 134, 120, 165, 2, 67, 60, 211, 1, 162, 30, 234, 129, 81, 15, 117, 193, 169, 136, 187, 225, 213, 68, 222, 241, 235, 34, 111, 249, 246, 17, 184, 253, 123, 137, 92, 255, 190, 197, 46, 256, 95, 227, 23, 128, 176, 242, 140, 64, 88, 121, 70, 32, 44, 189, 35, 16, 22, 223, 146, 8, 11, 240, 73, 4, 134, 120, 165, 2, 67, 60, 211, 1, 162, 30, 234, 129, 81, 15, 117, 193, 169, 136, 187, 225, 213, 68, 222, 241, 235, 34, 111, 249, 246, 17, 184, 253, 123, 137, 92, 255, 190, 197, 46, 256, 95, 227, 23, 128, 176, 242, 140, 64, 88, 121, 70, 32, 44, 189, 35, 16, 22, 223, 146, 8, 11, 240, 73, 4, 134, 120, 165, 2, 67, 60, 211, 1, 162, 30, 234, 129, 81, 15, 117, 193, 169, 136, 187, 225, 213, 68, 222, 241, 235, 34, 111, 249, 246, 17, 184, 253, 123, 137, 92, 255, 190, 197, 46, 256, 95, 227, 23, 128, 176, 242, 140, 64, 88, 121, 70, 32, 44, 189, 35, 16, 22, 223, 146, 8, 11, 240, 73, 4, 134, 120, 165, 2, 67, 60, 211, 1], +[1, 163, 98, 40, 95, 65, 58, 202, 30, 7, 113, 172, 23, 151, 198, 149, 129, 210, 49, 20, 176, 161, 29, 101, 15, 132, 185, 86, 140, 204, 99, 203, 193, 105, 153, 10, 88, 209, 143, 179, 136, 66, 221, 43, 70, 102, 178, 230, 225, 181, 205, 5, 44, 233, 200, 218, 68, 33, 239, 150, 35, 51, 89, 115, 241, 219, 231, 131, 22, 245, 100, 109, 34, 145, 248, 75, 146, 154, 173, 186, 249, 238, 244, 194, 11, 251, 50, 183, 17, 201, 124, 166, 73, 77, 215, 93, 253, 119, 122, 97, 134, 254, 25, 220, 137, 229, 62, 83, 165, 167, 236, 175, 255, 188, 61, 177, 67, 127, 141, 110, 197, 243, 31, 170, 211, 212, 118, 216, 256, 94, 159, 217, 162, 192, 199, 55, 227, 250, 144, 85, 234, 106, 59, 108, 128, 47, 208, 237, 81, 96, 228, 156, 242, 125, 72, 171, 117, 53, 158, 54, 64, 152, 104, 247, 169, 48, 114, 78, 121, 191, 36, 214, 187, 155, 79, 27, 32, 76, 52, 252, 213, 24, 57, 39, 189, 224, 18, 107, 222, 206, 168, 142, 16, 38, 26, 126, 235, 12, 157, 148, 223, 112, 9, 182, 111, 103, 84, 71, 8, 19, 13, 63, 246, 6, 207, 74, 240, 56, 133, 91, 184, 180, 42, 164, 4, 138, 135, 160, 123, 3, 232, 37, 120, 28, 195, 174, 92, 90, 21, 82, 2, 69, 196, 80, 190, 130, 116, 147, 60, 14, 226, 87, 46, 45, 139, 41, 1], +[1, 164, 168, 53, 211, 166, 239, 132, 60, 74, 57, 96, 67, 194, 205, 210, 2, 71, 79, 106, 165, 75, 221, 7, 120, 148, 114, 192, 134, 131, 153, 163, 4, 142, 158, 212, 73, 150, 185, 14, 240, 39, 228, 127, 11, 5, 49, 69, 8, 27, 59, 167, 146, 43, 113, 28, 223, 78, 199, 254, 22, 10, 98, 138, 16, 54, 118, 77, 35, 86, 226, 56, 189, 156, 141, 251, 44, 20, 196, 19, 32, 108, 236, 154, 70, 172, 195, 112, 121, 55, 25, 245, 88, 40, 135, 38, 64, 216, 215, 51, 140, 87, 133, 224, 242, 110, 50, 233, 176, 80, 13, 76, 128, 175, 173, 102, 23, 174, 9, 191, 227, 220, 100, 209, 95, 160, 26, 152, 256, 93, 89, 204, 46, 91, 18, 125, 197, 183, 200, 161, 190, 63, 52, 47, 255, 186, 178, 151, 92, 182, 36, 250, 137, 109, 143, 65, 123, 126, 104, 94, 253, 115, 99, 45, 184, 107, 72, 243, 17, 218, 29, 130, 246, 252, 208, 188, 249, 230, 198, 90, 111, 214, 144, 229, 34, 179, 58, 3, 235, 247, 159, 119, 241, 203, 139, 180, 222, 171, 31, 201, 68, 101, 116, 6, 213, 237, 61, 238, 225, 149, 21, 103, 187, 85, 62, 145, 136, 202, 232, 12, 169, 217, 122, 219, 193, 41, 42, 206, 117, 170, 124, 33, 15, 147, 207, 24, 81, 177, 244, 181, 129, 82, 84, 155, 234, 83, 248, 66, 30, 37, 157, 48, 162, 97, 231, 105, 1], +[1, 165, 240, 22, 32, 140, 227, 190, 253, 111, 68, 169, 129, 211, 120, 11, 16, 70, 242, 95, 255, 184, 34, 213, 193, 234, 60, 134, 8, 35, 121, 176, 256, 92, 17, 235, 225, 117, 30, 67, 4, 146, 189, 88, 128, 46, 137, 246, 241, 187, 15, 162, 2, 73, 223, 44, 64, 23, 197, 123, 249, 222, 136, 81, 1, 165, 240, 22, 32, 140, 227, 190, 253, 111, 68, 169, 129, 211, 120, 11, 16, 70, 242, 95, 255, 184, 34, 213, 193, 234, 60, 134, 8, 35, 121, 176, 256, 92, 17, 235, 225, 117, 30, 67, 4, 146, 189, 88, 128, 46, 137, 246, 241, 187, 15, 162, 2, 73, 223, 44, 64, 23, 197, 123, 249, 222, 136, 81, 1, 165, 240, 22, 32, 140, 227, 190, 253, 111, 68, 169, 129, 211, 120, 11, 16, 70, 242, 95, 255, 184, 34, 213, 193, 234, 60, 134, 8, 35, 121, 176, 256, 92, 17, 235, 225, 117, 30, 67, 4, 146, 189, 88, 128, 46, 137, 246, 241, 187, 15, 162, 2, 73, 223, 44, 64, 23, 197, 123, 249, 222, 136, 81, 1, 165, 240, 22, 32, 140, 227, 190, 253, 111, 68, 169, 129, 211, 120, 11, 16, 70, 242, 95, 255, 184, 34, 213, 193, 234, 60, 134, 8, 35, 121, 176, 256, 92, 17, 235, 225, 117, 30, 67, 4, 146, 189, 88, 128, 46, 137, 246, 241, 187, 15, 162, 2, 73, 223, 44, 64, 23, 197, 123, 249, 222, 136, 81, 1], +[1, 166, 57, 210, 165, 148, 153, 212, 240, 5, 59, 28, 22, 54, 226, 251, 32, 172, 25, 38, 140, 110, 13, 102, 227, 160, 89, 125, 190, 186, 36, 65, 253, 107, 29, 188, 111, 179, 159, 180, 68, 237, 21, 145, 169, 41, 124, 24, 129, 83, 157, 105, 211, 74, 205, 106, 120, 131, 158, 14, 11, 27, 113, 254, 16, 86, 141, 19, 70, 55, 135, 51, 242, 80, 173, 191, 95, 93, 18, 161, 255, 182, 143, 94, 184, 218, 208, 90, 34, 247, 139, 201, 213, 149, 62, 12, 193, 170, 207, 181, 234, 37, 231, 53, 60, 194, 79, 7, 134, 142, 185, 127, 8, 43, 199, 138, 35, 156, 196, 154, 121, 40, 215, 224, 176, 175, 9, 209, 256, 91, 200, 47, 92, 109, 104, 45, 17, 252, 198, 229, 235, 203, 31, 6, 225, 85, 232, 219, 117, 147, 244, 155, 30, 97, 168, 132, 67, 71, 221, 192, 4, 150, 228, 69, 146, 78, 98, 77, 189, 20, 236, 112, 88, 216, 133, 233, 128, 174, 100, 152, 46, 183, 52, 151, 137, 126, 99, 243, 246, 230, 144, 3, 241, 171, 116, 238, 187, 202, 122, 206, 15, 177, 84, 66, 162, 164, 239, 96, 2, 75, 114, 163, 73, 39, 49, 167, 223, 10, 118, 56, 44, 108, 195, 245, 64, 87, 50, 76, 23, 220, 26, 204, 197, 63, 178, 250, 123, 115, 72, 130, 249, 214, 58, 119, 222, 101, 61, 103, 136, 217, 42, 33, 81, 82, 248, 48, 1], +[1, 167, 133, 109, 213, 105, 59, 87, 137, 6, 231, 27, 140, 250, 116, 97, 8, 51, 36, 101, 162, 69, 215, 182, 68, 48, 49, 216, 92, 201, 157, 5, 64, 151, 31, 37, 11, 38, 178, 171, 30, 127, 135, 186, 222, 66, 228, 40, 255, 180, 248, 39, 88, 47, 139, 83, 240, 245, 52, 203, 234, 14, 25, 63, 241, 155, 185, 55, 190, 119, 84, 150, 121, 161, 159, 82, 73, 112, 200, 247, 129, 212, 195, 183, 235, 181, 158, 172, 197, 3, 244, 142, 70, 125, 58, 177, 4, 154, 18, 179, 81, 163, 236, 91, 34, 24, 153, 108, 46, 229, 207, 131, 32, 204, 144, 147, 134, 19, 89, 214, 15, 192, 196, 93, 111, 33, 114, 20, 256, 90, 124, 148, 44, 152, 198, 170, 120, 251, 26, 230, 117, 7, 141, 160, 249, 206, 221, 156, 95, 188, 42, 75, 189, 209, 208, 41, 165, 56, 100, 252, 193, 106, 226, 220, 246, 219, 79, 86, 227, 130, 122, 71, 35, 191, 29, 217, 2, 77, 9, 218, 169, 210, 118, 174, 17, 12, 205, 54, 23, 243, 232, 194, 16, 102, 72, 202, 67, 138, 173, 107, 136, 96, 98, 175, 184, 145, 57, 10, 128, 45, 62, 74, 22, 76, 99, 85, 60, 254, 13, 115, 187, 132, 199, 80, 253, 103, 239, 78, 176, 94, 21, 166, 223, 233, 104, 149, 211, 28, 50, 126, 225, 53, 113, 110, 123, 238, 168, 43, 242, 65, 61, 164, 146, 224, 143, 237, 1], +[1, 168, 211, 239, 60, 57, 67, 205, 2, 79, 165, 221, 120, 114, 134, 153, 4, 158, 73, 185, 240, 228, 11, 49, 8, 59, 146, 113, 223, 199, 22, 98, 16, 118, 35, 226, 189, 141, 44, 196, 32, 236, 70, 195, 121, 25, 88, 135, 64, 215, 140, 133, 242, 50, 176, 13, 128, 173, 23, 9, 227, 100, 95, 26, 256, 89, 46, 18, 197, 200, 190, 52, 255, 178, 92, 36, 137, 143, 123, 104, 253, 99, 184, 72, 17, 29, 246, 208, 249, 198, 111, 144, 34, 58, 235, 159, 241, 139, 222, 31, 68, 116, 213, 61, 225, 21, 187, 62, 136, 232, 169, 122, 193, 42, 117, 124, 15, 207, 81, 244, 129, 84, 234, 248, 30, 157, 162, 231, 1, 168, 211, 239, 60, 57, 67, 205, 2, 79, 165, 221, 120, 114, 134, 153, 4, 158, 73, 185, 240, 228, 11, 49, 8, 59, 146, 113, 223, 199, 22, 98, 16, 118, 35, 226, 189, 141, 44, 196, 32, 236, 70, 195, 121, 25, 88, 135, 64, 215, 140, 133, 242, 50, 176, 13, 128, 173, 23, 9, 227, 100, 95, 26, 256, 89, 46, 18, 197, 200, 190, 52, 255, 178, 92, 36, 137, 143, 123, 104, 253, 99, 184, 72, 17, 29, 246, 208, 249, 198, 111, 144, 34, 58, 235, 159, 241, 139, 222, 31, 68, 116, 213, 61, 225, 21, 187, 62, 136, 232, 169, 122, 193, 42, 117, 124, 15, 207, 81, 244, 129, 84, 234, 248, 30, 157, 162, 231, 1], +[1, 169, 34, 92, 128, 44, 240, 211, 193, 235, 137, 23, 32, 11, 60, 117, 241, 123, 227, 70, 8, 67, 15, 222, 253, 95, 121, 146, 2, 81, 68, 184, 256, 88, 223, 165, 129, 213, 17, 46, 64, 22, 120, 234, 225, 246, 197, 140, 16, 134, 30, 187, 249, 190, 242, 35, 4, 162, 136, 111, 255, 176, 189, 73, 1, 169, 34, 92, 128, 44, 240, 211, 193, 235, 137, 23, 32, 11, 60, 117, 241, 123, 227, 70, 8, 67, 15, 222, 253, 95, 121, 146, 2, 81, 68, 184, 256, 88, 223, 165, 129, 213, 17, 46, 64, 22, 120, 234, 225, 246, 197, 140, 16, 134, 30, 187, 249, 190, 242, 35, 4, 162, 136, 111, 255, 176, 189, 73, 1, 169, 34, 92, 128, 44, 240, 211, 193, 235, 137, 23, 32, 11, 60, 117, 241, 123, 227, 70, 8, 67, 15, 222, 253, 95, 121, 146, 2, 81, 68, 184, 256, 88, 223, 165, 129, 213, 17, 46, 64, 22, 120, 234, 225, 246, 197, 140, 16, 134, 30, 187, 249, 190, 242, 35, 4, 162, 136, 111, 255, 176, 189, 73, 1, 169, 34, 92, 128, 44, 240, 211, 193, 235, 137, 23, 32, 11, 60, 117, 241, 123, 227, 70, 8, 67, 15, 222, 253, 95, 121, 146, 2, 81, 68, 184, 256, 88, 223, 165, 129, 213, 17, 46, 64, 22, 120, 234, 225, 246, 197, 140, 16, 134, 30, 187, 249, 190, 242, 35, 4, 162, 136, 111, 255, 176, 189, 73, 1], +[1, 170, 116, 188, 92, 220, 135, 77, 240, 194, 84, 145, 235, 115, 18, 233, 32, 43, 114, 105, 117, 101, 208, 151, 227, 40, 118, 14, 67, 82, 62, 3, 253, 91, 50, 19, 146, 148, 231, 206, 68, 252, 178, 191, 88, 54, 185, 96, 129, 85, 58, 94, 46, 110, 196, 167, 120, 97, 42, 201, 246, 186, 9, 245, 16, 150, 57, 181, 187, 179, 104, 204, 242, 20, 59, 7, 162, 41, 31, 130, 255, 174, 25, 138, 73, 74, 244, 103, 34, 126, 89, 224, 44, 27, 221, 48, 193, 171, 29, 47, 23, 55, 98, 212, 60, 177, 21, 229, 123, 93, 133, 251, 8, 75, 157, 219, 222, 218, 52, 102, 121, 10, 158, 132, 81, 149, 144, 65, 256, 87, 141, 69, 165, 37, 122, 180, 17, 63, 173, 112, 22, 142, 239, 24, 225, 214, 143, 152, 140, 156, 49, 106, 30, 217, 139, 243, 190, 175, 195, 254, 4, 166, 207, 238, 111, 109, 26, 51, 189, 5, 79, 66, 169, 203, 72, 161, 128, 172, 199, 163, 211, 147, 61, 90, 137, 160, 215, 56, 11, 71, 248, 12, 241, 107, 200, 76, 70, 78, 153, 53, 15, 237, 198, 250, 95, 216, 226, 127, 2, 83, 232, 119, 184, 183, 13, 154, 223, 131, 168, 33, 213, 230, 36, 209, 64, 86, 228, 210, 234, 202, 159, 45, 197, 80, 236, 28, 134, 164, 124, 6, 249, 182, 100, 38, 35, 39, 205, 155, 136, 247, 99, 125, 176, 108, 113, 192, 1], +[1, 171, 200, 19, 165, 202, 104, 51, 240, 177, 198, 191, 22, 164, 31, 161, 32, 75, 232, 94, 140, 39, 244, 90, 227, 10, 168, 201, 190, 108, 221, 12, 253, 87, 228, 181, 111, 220, 98, 53, 68, 63, 236, 7, 169, 115, 133, 127, 129, 214, 100, 138, 211, 101, 52, 154, 120, 217, 99, 224, 11, 82, 144, 209, 16, 166, 116, 47, 70, 148, 122, 45, 242, 5, 84, 229, 95, 54, 239, 6, 255, 172, 114, 219, 184, 110, 49, 155, 34, 160, 118, 132, 213, 186, 195, 192, 193, 107, 50, 69, 234, 179, 26, 77, 60, 237, 178, 112, 134, 41, 72, 233, 8, 83, 58, 152, 35, 74, 61, 151, 121, 131, 42, 243, 176, 27, 248, 3, 256, 86, 57, 238, 92, 55, 153, 206, 17, 80, 59, 66, 235, 93, 226, 96, 225, 182, 25, 163, 117, 218, 13, 167, 30, 247, 89, 56, 67, 149, 36, 245, 4, 170, 29, 76, 146, 37, 159, 204, 189, 194, 21, 250, 88, 142, 124, 130, 128, 43, 157, 119, 46, 156, 205, 103, 137, 40, 158, 33, 246, 175, 113, 48, 241, 91, 141, 210, 187, 109, 135, 212, 15, 252, 173, 28, 162, 203, 18, 251, 2, 85, 143, 38, 73, 147, 208, 102, 223, 97, 139, 125, 44, 71, 62, 65, 64, 150, 207, 188, 23, 78, 231, 180, 197, 20, 79, 145, 123, 216, 185, 24, 249, 174, 199, 105, 222, 183, 196, 106, 136, 126, 215, 14, 81, 230, 9, 254, 1], +[1, 172, 29, 105, 70, 218, 231, 154, 17, 97, 236, 243, 162, 108, 72, 48, 32, 107, 157, 19, 184, 37, 196, 45, 30, 20, 99, 66, 44, 115, 248, 251, 253, 83, 141, 94, 234, 156, 104, 155, 189, 126, 84, 56, 123, 82, 226, 65, 129, 86, 143, 181, 35, 109, 244, 77, 137, 177, 118, 250, 81, 54, 36, 24, 16, 182, 207, 138, 92, 147, 98, 151, 15, 10, 178, 33, 22, 186, 124, 254, 255, 170, 199, 47, 117, 78, 52, 206, 223, 63, 42, 28, 190, 41, 113, 161, 193, 43, 200, 219, 146, 183, 122, 167, 197, 217, 59, 125, 169, 27, 18, 12, 8, 91, 232, 69, 46, 202, 49, 204, 136, 5, 89, 145, 11, 93, 62, 127, 256, 85, 228, 152, 187, 39, 26, 103, 240, 160, 21, 14, 95, 149, 185, 209, 225, 150, 100, 238, 73, 220, 61, 212, 227, 237, 158, 191, 213, 142, 9, 6, 4, 174, 116, 163, 23, 101, 153, 102, 68, 131, 173, 201, 134, 175, 31, 192, 128, 171, 114, 76, 222, 148, 13, 180, 120, 80, 139, 7, 176, 203, 221, 233, 241, 75, 50, 119, 165, 110, 159, 106, 242, 247, 79, 224, 235, 71, 133, 3, 2, 87, 58, 210, 140, 179, 205, 51, 34, 194, 215, 229, 67, 216, 144, 96, 64, 214, 57, 38, 111, 74, 135, 90, 60, 40, 198, 132, 88, 230, 239, 245, 249, 166, 25, 188, 211, 55, 208, 53, 121, 252, 168, 112, 246, 164, 195, 130, 1], +[1, 173, 117, 195, 68, 199, 246, 153, 255, 168, 23, 124, 121, 116, 22, 208, 4, 178, 211, 9, 15, 25, 213, 98, 249, 158, 92, 239, 227, 207, 88, 61, 16, 198, 73, 36, 60, 100, 81, 135, 225, 118, 111, 185, 137, 57, 95, 244, 64, 21, 35, 144, 240, 143, 67, 26, 129, 215, 187, 226, 34, 228, 123, 205, 256, 84, 140, 62, 189, 58, 11, 104, 2, 89, 234, 133, 136, 141, 235, 49, 253, 79, 46, 248, 242, 232, 44, 159, 8, 99, 165, 18, 30, 50, 169, 196, 241, 59, 184, 221, 197, 157, 176, 122, 32, 139, 146, 72, 120, 200, 162, 13, 193, 236, 222, 113, 17, 114, 190, 231, 128, 42, 70, 31, 223, 29, 134, 52, 1, 173, 117, 195, 68, 199, 246, 153, 255, 168, 23, 124, 121, 116, 22, 208, 4, 178, 211, 9, 15, 25, 213, 98, 249, 158, 92, 239, 227, 207, 88, 61, 16, 198, 73, 36, 60, 100, 81, 135, 225, 118, 111, 185, 137, 57, 95, 244, 64, 21, 35, 144, 240, 143, 67, 26, 129, 215, 187, 226, 34, 228, 123, 205, 256, 84, 140, 62, 189, 58, 11, 104, 2, 89, 234, 133, 136, 141, 235, 49, 253, 79, 46, 248, 242, 232, 44, 159, 8, 99, 165, 18, 30, 50, 169, 196, 241, 59, 184, 221, 197, 157, 176, 122, 32, 139, 146, 72, 120, 200, 162, 13, 193, 236, 222, 113, 17, 114, 190, 231, 128, 42, 70, 31, 223, 29, 134, 52, 1], +[1, 174, 207, 38, 187, 156, 159, 167, 17, 131, 178, 132, 95, 82, 133, 12, 32, 171, 199, 188, 73, 109, 205, 204, 30, 80, 42, 112, 213, 54, 144, 127, 253, 75, 200, 105, 23, 147, 135, 103, 189, 247, 59, 243, 134, 186, 239, 209, 129, 87, 232, 19, 222, 78, 208, 212, 137, 194, 89, 66, 176, 41, 195, 6, 16, 214, 228, 94, 165, 183, 231, 102, 15, 40, 21, 56, 235, 27, 72, 192, 255, 166, 100, 181, 140, 202, 196, 180, 223, 252, 158, 250, 67, 93, 248, 233, 193, 172, 116, 138, 111, 39, 104, 106, 197, 97, 173, 33, 88, 149, 226, 3, 8, 107, 114, 47, 211, 220, 244, 51, 136, 20, 139, 28, 246, 142, 36, 96, 256, 83, 50, 219, 70, 101, 98, 90, 240, 126, 79, 125, 162, 175, 124, 245, 225, 86, 58, 69, 184, 148, 52, 53, 227, 177, 215, 145, 44, 203, 113, 130, 4, 182, 57, 152, 234, 110, 122, 154, 68, 10, 198, 14, 123, 71, 18, 48, 128, 170, 25, 238, 35, 179, 49, 45, 120, 63, 168, 191, 81, 216, 62, 251, 241, 43, 29, 163, 92, 74, 26, 155, 242, 217, 236, 201, 22, 230, 185, 65, 2, 91, 157, 76, 117, 55, 61, 77, 34, 5, 99, 7, 190, 164, 9, 24, 64, 85, 141, 119, 146, 218, 153, 151, 60, 160, 84, 224, 169, 108, 31, 254, 249, 150, 143, 210, 46, 37, 13, 206, 121, 237, 118, 229, 11, 115, 221, 161, 1], +[1, 175, 42, 154, 222, 43, 72, 7, 197, 37, 50, 12, 44, 247, 49, 94, 2, 93, 84, 51, 187, 86, 144, 14, 137, 74, 100, 24, 88, 237, 98, 188, 4, 186, 168, 102, 117, 172, 31, 28, 17, 148, 200, 48, 176, 217, 196, 119, 8, 115, 79, 204, 234, 87, 62, 56, 34, 39, 143, 96, 95, 177, 135, 238, 16, 230, 158, 151, 211, 174, 124, 112, 68, 78, 29, 192, 190, 97, 13, 219, 32, 203, 59, 45, 165, 91, 248, 224, 136, 156, 58, 127, 123, 194, 26, 181, 64, 149, 118, 90, 73, 182, 239, 191, 15, 55, 116, 254, 246, 131, 52, 105, 128, 41, 236, 180, 146, 107, 221, 125, 30, 110, 232, 251, 235, 5, 104, 210, 256, 82, 215, 103, 35, 214, 185, 250, 60, 220, 207, 245, 213, 10, 208, 163, 255, 164, 173, 206, 70, 171, 113, 243, 120, 183, 157, 233, 169, 20, 159, 69, 253, 71, 89, 155, 140, 85, 226, 229, 240, 109, 57, 209, 81, 40, 61, 138, 249, 142, 178, 53, 23, 170, 195, 201, 223, 218, 114, 161, 162, 80, 122, 19, 241, 27, 99, 106, 46, 83, 133, 145, 189, 179, 228, 65, 67, 160, 244, 38, 225, 54, 198, 212, 92, 166, 9, 33, 121, 101, 199, 130, 134, 63, 231, 76, 193, 108, 139, 167, 184, 75, 18, 66, 242, 202, 141, 3, 11, 126, 205, 152, 129, 216, 21, 77, 111, 150, 36, 132, 227, 147, 25, 6, 22, 252, 153, 47, 1], +[1, 176, 136, 35, 249, 134, 197, 234, 64, 213, 223, 184, 2, 95, 15, 70, 241, 11, 137, 211, 128, 169, 189, 111, 4, 190, 30, 140, 225, 22, 17, 165, 256, 81, 121, 222, 8, 123, 60, 23, 193, 44, 34, 73, 255, 162, 242, 187, 16, 246, 120, 46, 129, 88, 68, 146, 253, 67, 227, 117, 32, 235, 240, 92, 1, 176, 136, 35, 249, 134, 197, 234, 64, 213, 223, 184, 2, 95, 15, 70, 241, 11, 137, 211, 128, 169, 189, 111, 4, 190, 30, 140, 225, 22, 17, 165, 256, 81, 121, 222, 8, 123, 60, 23, 193, 44, 34, 73, 255, 162, 242, 187, 16, 246, 120, 46, 129, 88, 68, 146, 253, 67, 227, 117, 32, 235, 240, 92, 1, 176, 136, 35, 249, 134, 197, 234, 64, 213, 223, 184, 2, 95, 15, 70, 241, 11, 137, 211, 128, 169, 189, 111, 4, 190, 30, 140, 225, 22, 17, 165, 256, 81, 121, 222, 8, 123, 60, 23, 193, 44, 34, 73, 255, 162, 242, 187, 16, 246, 120, 46, 129, 88, 68, 146, 253, 67, 227, 117, 32, 235, 240, 92, 1, 176, 136, 35, 249, 134, 197, 234, 64, 213, 223, 184, 2, 95, 15, 70, 241, 11, 137, 211, 128, 169, 189, 111, 4, 190, 30, 140, 225, 22, 17, 165, 256, 81, 121, 222, 8, 123, 60, 23, 193, 44, 34, 73, 255, 162, 242, 187, 16, 246, 120, 46, 129, 88, 68, 146, 253, 67, 227, 117, 32, 235, 240, 92, 1], +[1, 177, 232, 201, 111, 115, 52, 209, 242, 172, 118, 69, 134, 74, 248, 206, 225, 247, 29, 250, 46, 175, 135, 251, 223, 150, 79, 105, 81, 202, 31, 90, 253, 63, 100, 224, 70, 54, 49, 192, 60, 83, 42, 238, 235, 218, 36, 204, 128, 40, 141, 28, 73, 71, 231, 24, 136, 171, 198, 94, 190, 220, 133, 154, 16, 5, 114, 132, 234, 41, 61, 3, 17, 182, 89, 76, 88, 156, 113, 212, 2, 97, 207, 145, 222, 230, 104, 161, 227, 87, 236, 138, 11, 148, 239, 155, 193, 237, 58, 243, 92, 93, 13, 245, 189, 43, 158, 210, 162, 147, 62, 180, 249, 126, 200, 191, 140, 108, 98, 127, 120, 166, 84, 219, 213, 179, 72, 151, 256, 80, 25, 56, 146, 142, 205, 48, 15, 85, 139, 188, 123, 183, 9, 51, 32, 10, 228, 7, 211, 82, 122, 6, 34, 107, 178, 152, 176, 55, 226, 167, 4, 194, 157, 33, 187, 203, 208, 65, 197, 174, 215, 19, 22, 39, 221, 53, 129, 217, 116, 229, 184, 186, 26, 233, 121, 86, 59, 163, 67, 37, 124, 103, 241, 252, 143, 125, 23, 216, 196, 254, 240, 75, 168, 181, 169, 101, 144, 45, 255, 160, 50, 112, 35, 27, 153, 96, 30, 170, 21, 119, 246, 109, 18, 102, 64, 20, 199, 14, 165, 164, 244, 12, 68, 214, 99, 47, 95, 110, 195, 77, 8, 131, 57, 66, 117, 149, 159, 130, 137, 91, 173, 38, 44, 78, 185, 106, 1], +[1, 178, 73, 144, 189, 232, 176, 231, 255, 158, 111, 226, 136, 50, 162, 52, 4, 198, 35, 62, 242, 157, 190, 153, 249, 118, 187, 133, 30, 200, 134, 208, 16, 21, 140, 248, 197, 114, 246, 98, 225, 215, 234, 18, 120, 29, 22, 61, 64, 84, 46, 221, 17, 199, 213, 135, 129, 89, 165, 72, 223, 116, 88, 244, 256, 79, 184, 113, 68, 25, 81, 26, 2, 99, 146, 31, 121, 207, 95, 205, 253, 59, 222, 195, 15, 100, 67, 104, 8, 139, 70, 124, 227, 57, 123, 49, 241, 236, 117, 9, 60, 143, 11, 159, 32, 42, 23, 239, 137, 228, 235, 196, 193, 173, 211, 36, 240, 58, 44, 122, 128, 168, 92, 185, 34, 141, 169, 13, 1, 178, 73, 144, 189, 232, 176, 231, 255, 158, 111, 226, 136, 50, 162, 52, 4, 198, 35, 62, 242, 157, 190, 153, 249, 118, 187, 133, 30, 200, 134, 208, 16, 21, 140, 248, 197, 114, 246, 98, 225, 215, 234, 18, 120, 29, 22, 61, 64, 84, 46, 221, 17, 199, 213, 135, 129, 89, 165, 72, 223, 116, 88, 244, 256, 79, 184, 113, 68, 25, 81, 26, 2, 99, 146, 31, 121, 207, 95, 205, 253, 59, 222, 195, 15, 100, 67, 104, 8, 139, 70, 124, 227, 57, 123, 49, 241, 236, 117, 9, 60, 143, 11, 159, 32, 42, 23, 239, 137, 228, 235, 196, 193, 173, 211, 36, 240, 58, 44, 122, 128, 168, 92, 185, 34, 141, 169, 13, 1], +[1, 179, 173, 127, 117, 126, 195, 210, 68, 93, 199, 155, 246, 87, 153, 145, 255, 156, 168, 3, 23, 5, 124, 94, 121, 71, 116, 204, 22, 83, 208, 224, 4, 202, 178, 251, 211, 247, 9, 69, 15, 115, 25, 106, 213, 91, 98, 66, 249, 110, 158, 12, 92, 20, 239, 119, 227, 27, 207, 45, 88, 75, 61, 125, 16, 37, 198, 233, 73, 217, 36, 19, 60, 203, 100, 167, 81, 107, 135, 7, 225, 183, 118, 48, 111, 80, 185, 219, 137, 108, 57, 180, 95, 43, 244, 243, 64, 148, 21, 161, 35, 97, 144, 76, 240, 41, 143, 154, 67, 171, 26, 28, 129, 218, 215, 192, 187, 63, 226, 105, 34, 175, 228, 206, 123, 172, 205, 201, 256, 78, 84, 130, 140, 131, 62, 47, 189, 164, 58, 102, 11, 170, 104, 112, 2, 101, 89, 254, 234, 252, 133, 163, 136, 186, 141, 53, 235, 174, 49, 33, 253, 55, 79, 6, 46, 10, 248, 188, 242, 142, 232, 151, 44, 166, 159, 191, 8, 147, 99, 245, 165, 237, 18, 138, 30, 230, 50, 212, 169, 182, 196, 132, 241, 220, 59, 24, 184, 40, 221, 238, 197, 54, 157, 90, 176, 150, 122, 250, 32, 74, 139, 209, 146, 177, 72, 38, 120, 149, 200, 77, 162, 214, 13, 14, 193, 109, 236, 96, 222, 160, 113, 181, 17, 216, 114, 103, 190, 86, 231, 229, 128, 39, 42, 65, 70, 194, 31, 152, 223, 82, 29, 51, 134, 85, 52, 56, 1], +[1, 180, 18, 156, 67, 238, 178, 172, 120, 12, 104, 216, 73, 33, 29, 80, 8, 155, 144, 220, 22, 105, 139, 91, 189, 96, 61, 186, 70, 7, 232, 126, 64, 212, 124, 218, 176, 69, 84, 214, 227, 254, 231, 203, 46, 56, 57, 237, 255, 154, 221, 202, 123, 38, 158, 170, 17, 233, 49, 82, 111, 191, 199, 97, 241, 204, 226, 74, 213, 47, 236, 75, 136, 65, 135, 142, 117, 243, 50, 5, 129, 90, 9, 78, 162, 119, 89, 86, 60, 6, 52, 108, 165, 145, 143, 40, 4, 206, 72, 110, 11, 181, 198, 174, 223, 48, 159, 93, 35, 132, 116, 63, 32, 106, 62, 109, 88, 163, 42, 107, 242, 127, 244, 230, 23, 28, 157, 247, 256, 77, 239, 101, 190, 19, 79, 85, 137, 245, 153, 41, 184, 224, 228, 177, 249, 102, 113, 37, 235, 152, 118, 166, 68, 161, 196, 71, 187, 250, 25, 131, 193, 45, 133, 39, 81, 188, 173, 43, 30, 3, 26, 54, 211, 201, 200, 20, 2, 103, 36, 55, 134, 219, 99, 87, 240, 24, 208, 175, 146, 66, 58, 160, 16, 53, 31, 183, 44, 210, 21, 182, 121, 192, 122, 115, 140, 14, 207, 252, 128, 167, 248, 179, 95, 138, 168, 171, 197, 251, 205, 149, 92, 112, 114, 217, 253, 51, 185, 147, 246, 76, 59, 83, 34, 209, 98, 164, 222, 125, 141, 194, 225, 151, 195, 148, 169, 94, 215, 150, 15, 130, 13, 27, 234, 229, 100, 10, 1], +[1, 181, 122, 237, 235, 130, 143, 183, 227, 224, 195, 86, 146, 212, 79, 164, 129, 219, 61, 247, 246, 65, 200, 220, 242, 112, 226, 43, 73, 106, 168, 82, 193, 238, 159, 252, 123, 161, 100, 110, 121, 56, 113, 150, 165, 53, 84, 41, 225, 119, 208, 126, 190, 209, 50, 55, 189, 28, 185, 75, 211, 155, 42, 149, 241, 188, 104, 63, 95, 233, 25, 156, 223, 14, 221, 166, 234, 206, 21, 203, 249, 94, 52, 160, 176, 245, 141, 78, 240, 7, 239, 83, 117, 103, 139, 230, 253, 47, 26, 80, 88, 251, 199, 39, 120, 132, 248, 170, 187, 180, 198, 115, 255, 152, 13, 40, 44, 254, 228, 148, 60, 66, 124, 85, 222, 90, 99, 186, 256, 76, 135, 20, 22, 127, 114, 74, 30, 33, 62, 171, 111, 45, 178, 93, 128, 38, 196, 10, 11, 192, 57, 37, 15, 145, 31, 214, 184, 151, 89, 175, 64, 19, 98, 5, 134, 96, 157, 147, 136, 201, 144, 107, 92, 204, 173, 216, 32, 138, 49, 131, 67, 48, 207, 202, 68, 229, 72, 182, 46, 102, 215, 108, 16, 69, 153, 194, 162, 24, 232, 101, 34, 243, 36, 91, 23, 51, 236, 54, 8, 163, 205, 97, 81, 12, 116, 179, 17, 250, 18, 174, 140, 154, 118, 27, 4, 210, 231, 177, 169, 6, 58, 218, 137, 125, 9, 87, 70, 77, 59, 142, 2, 105, 244, 217, 213, 3, 29, 109, 197, 191, 133, 172, 35, 167, 158, 71, 1], +[1, 182, 228, 119, 70, 147, 26, 106, 17, 10, 21, 224, 162, 186, 185, 3, 32, 170, 100, 210, 184, 78, 61, 51, 30, 63, 158, 229, 44, 41, 9, 96, 253, 43, 116, 38, 234, 183, 153, 90, 189, 217, 173, 132, 123, 27, 31, 245, 129, 91, 114, 188, 35, 202, 13, 53, 137, 5, 139, 112, 81, 93, 221, 130, 16, 85, 50, 105, 92, 39, 159, 154, 15, 160, 79, 243, 22, 149, 133, 48, 255, 150, 58, 19, 117, 220, 205, 45, 223, 237, 215, 66, 190, 142, 144, 251, 193, 174, 57, 94, 146, 101, 135, 155, 197, 131, 198, 56, 169, 175, 239, 65, 8, 171, 25, 181, 46, 148, 208, 77, 136, 80, 168, 250, 11, 203, 195, 24, 256, 75, 29, 138, 187, 110, 231, 151, 240, 247, 236, 33, 95, 71, 72, 254, 225, 87, 157, 47, 73, 179, 196, 206, 227, 194, 99, 28, 213, 216, 248, 161, 4, 214, 141, 219, 23, 74, 104, 167, 68, 40, 84, 125, 134, 230, 226, 12, 128, 166, 143, 69, 222, 55, 244, 204, 120, 252, 118, 145, 176, 164, 36, 127, 241, 172, 207, 152, 165, 218, 98, 103, 242, 97, 178, 14, 235, 108, 124, 209, 2, 107, 199, 238, 140, 37, 52, 212, 34, 20, 42, 191, 67, 115, 113, 6, 64, 83, 200, 163, 111, 156, 122, 102, 60, 126, 59, 201, 88, 82, 18, 192, 249, 86, 232, 76, 211, 109, 49, 180, 121, 177, 89, 7, 246, 54, 62, 233, 1], +[1, 183, 79, 65, 73, 252, 113, 119, 189, 149, 25, 206, 176, 83, 26, 132, 255, 148, 99, 127, 111, 10, 31, 19, 136, 216, 207, 102, 162, 91, 205, 250, 4, 218, 59, 3, 35, 237, 195, 219, 242, 82, 100, 53, 190, 75, 104, 14, 249, 78, 139, 251, 187, 40, 124, 76, 30, 93, 57, 151, 134, 107, 49, 229, 16, 101, 236, 12, 140, 177, 9, 105, 197, 71, 143, 212, 246, 43, 159, 56, 225, 55, 42, 233, 234, 160, 239, 47, 120, 115, 228, 90, 22, 171, 196, 145, 64, 147, 173, 48, 46, 194, 36, 163, 17, 27, 58, 77, 213, 172, 122, 224, 129, 220, 168, 161, 165, 126, 185, 188, 223, 203, 141, 103, 88, 170, 13, 66, 256, 74, 178, 192, 184, 5, 144, 138, 68, 108, 232, 51, 81, 174, 231, 125, 2, 109, 158, 130, 146, 247, 226, 238, 121, 41, 50, 155, 95, 166, 52, 7, 253, 39, 198, 254, 222, 20, 62, 38, 15, 175, 157, 204, 67, 182, 153, 243, 8, 179, 118, 6, 70, 217, 133, 181, 227, 164, 200, 106, 123, 150, 208, 28, 241, 156, 21, 245, 117, 80, 248, 152, 60, 186, 114, 45, 11, 214, 98, 201, 32, 202, 215, 24, 23, 97, 18, 210, 137, 142, 29, 167, 235, 86, 61, 112, 193, 110, 84, 209, 211, 63, 221, 94, 240, 230, 199, 180, 44, 85, 135, 33, 128, 37, 89, 96, 92, 131, 72, 69, 34, 54, 116, 154, 169, 87, 244, 191, 1], +[1, 184, 189, 81, 255, 146, 136, 95, 4, 222, 242, 67, 249, 70, 30, 123, 16, 117, 197, 11, 225, 23, 120, 235, 64, 211, 17, 44, 129, 92, 223, 169, 256, 73, 68, 176, 2, 111, 121, 162, 253, 35, 15, 190, 8, 187, 227, 134, 241, 140, 60, 246, 32, 234, 137, 22, 193, 46, 240, 213, 128, 165, 34, 88, 1, 184, 189, 81, 255, 146, 136, 95, 4, 222, 242, 67, 249, 70, 30, 123, 16, 117, 197, 11, 225, 23, 120, 235, 64, 211, 17, 44, 129, 92, 223, 169, 256, 73, 68, 176, 2, 111, 121, 162, 253, 35, 15, 190, 8, 187, 227, 134, 241, 140, 60, 246, 32, 234, 137, 22, 193, 46, 240, 213, 128, 165, 34, 88, 1, 184, 189, 81, 255, 146, 136, 95, 4, 222, 242, 67, 249, 70, 30, 123, 16, 117, 197, 11, 225, 23, 120, 235, 64, 211, 17, 44, 129, 92, 223, 169, 256, 73, 68, 176, 2, 111, 121, 162, 253, 35, 15, 190, 8, 187, 227, 134, 241, 140, 60, 246, 32, 234, 137, 22, 193, 46, 240, 213, 128, 165, 34, 88, 1, 184, 189, 81, 255, 146, 136, 95, 4, 222, 242, 67, 249, 70, 30, 123, 16, 117, 197, 11, 225, 23, 120, 235, 64, 211, 17, 44, 129, 92, 223, 169, 256, 73, 68, 176, 2, 111, 121, 162, 253, 35, 15, 190, 8, 187, 227, 134, 241, 140, 60, 246, 32, 234, 137, 22, 193, 46, 240, 213, 128, 165, 34, 88, 1], +[1, 185, 44, 173, 137, 159, 117, 57, 8, 195, 95, 99, 68, 244, 165, 199, 64, 18, 246, 21, 30, 153, 35, 50, 255, 144, 169, 168, 240, 196, 23, 143, 241, 124, 67, 59, 121, 26, 184, 116, 129, 221, 22, 215, 197, 208, 187, 157, 4, 226, 176, 178, 34, 122, 211, 228, 32, 9, 123, 139, 15, 205, 146, 25, 256, 72, 213, 84, 120, 98, 140, 200, 249, 62, 162, 158, 189, 13, 92, 58, 193, 239, 11, 236, 227, 104, 222, 207, 2, 113, 88, 89, 17, 61, 234, 114, 16, 133, 190, 198, 136, 231, 73, 141, 128, 36, 235, 42, 60, 49, 70, 100, 253, 31, 81, 79, 223, 135, 46, 29, 225, 248, 134, 118, 242, 52, 111, 232, 1, 185, 44, 173, 137, 159, 117, 57, 8, 195, 95, 99, 68, 244, 165, 199, 64, 18, 246, 21, 30, 153, 35, 50, 255, 144, 169, 168, 240, 196, 23, 143, 241, 124, 67, 59, 121, 26, 184, 116, 129, 221, 22, 215, 197, 208, 187, 157, 4, 226, 176, 178, 34, 122, 211, 228, 32, 9, 123, 139, 15, 205, 146, 25, 256, 72, 213, 84, 120, 98, 140, 200, 249, 62, 162, 158, 189, 13, 92, 58, 193, 239, 11, 236, 227, 104, 222, 207, 2, 113, 88, 89, 17, 61, 234, 114, 16, 133, 190, 198, 136, 231, 73, 141, 128, 36, 235, 42, 60, 49, 70, 100, 253, 31, 81, 79, 223, 135, 46, 29, 225, 248, 134, 118, 242, 52, 111, 232, 1], +[1, 186, 158, 90, 35, 85, 133, 66, 197, 148, 29, 254, 213, 40, 244, 152, 2, 115, 59, 180, 70, 170, 9, 132, 137, 39, 58, 251, 169, 80, 231, 47, 4, 230, 118, 103, 140, 83, 18, 7, 17, 78, 116, 245, 81, 160, 205, 94, 8, 203, 236, 206, 23, 166, 36, 14, 34, 156, 232, 233, 162, 63, 153, 188, 16, 149, 215, 155, 46, 75, 72, 28, 68, 55, 207, 209, 67, 126, 49, 119, 32, 41, 173, 53, 92, 150, 144, 56, 136, 110, 157, 161, 134, 252, 98, 238, 64, 82, 89, 106, 184, 43, 31, 112, 15, 220, 57, 65, 11, 247, 196, 219, 128, 164, 178, 212, 111, 86, 62, 224, 30, 183, 114, 130, 22, 237, 135, 181, 256, 71, 99, 167, 222, 172, 124, 191, 60, 109, 228, 3, 44, 217, 13, 105, 255, 142, 198, 77, 187, 87, 248, 125, 120, 218, 199, 6, 88, 177, 26, 210, 253, 27, 139, 154, 117, 174, 239, 250, 240, 179, 141, 12, 176, 97, 52, 163, 249, 54, 21, 51, 234, 91, 221, 243, 223, 101, 25, 24, 95, 194, 104, 69, 241, 108, 42, 102, 211, 182, 185, 229, 189, 202, 50, 48, 190, 131, 208, 138, 225, 216, 84, 204, 165, 107, 113, 201, 121, 147, 100, 96, 123, 5, 159, 19, 193, 175, 168, 151, 73, 214, 226, 145, 242, 37, 200, 192, 246, 10, 61, 38, 129, 93, 79, 45, 146, 171, 195, 33, 227, 74, 143, 127, 235, 20, 122, 76, 1], +[1, 187, 17, 95, 32, 73, 30, 213, 253, 23, 189, 134, 129, 222, 137, 176, 16, 165, 15, 235, 255, 140, 223, 67, 193, 111, 197, 88, 8, 211, 136, 246, 256, 70, 240, 162, 225, 184, 227, 44, 4, 234, 68, 123, 128, 35, 120, 81, 241, 92, 242, 22, 2, 117, 34, 190, 64, 146, 60, 169, 249, 46, 121, 11, 1, 187, 17, 95, 32, 73, 30, 213, 253, 23, 189, 134, 129, 222, 137, 176, 16, 165, 15, 235, 255, 140, 223, 67, 193, 111, 197, 88, 8, 211, 136, 246, 256, 70, 240, 162, 225, 184, 227, 44, 4, 234, 68, 123, 128, 35, 120, 81, 241, 92, 242, 22, 2, 117, 34, 190, 64, 146, 60, 169, 249, 46, 121, 11, 1, 187, 17, 95, 32, 73, 30, 213, 253, 23, 189, 134, 129, 222, 137, 176, 16, 165, 15, 235, 255, 140, 223, 67, 193, 111, 197, 88, 8, 211, 136, 246, 256, 70, 240, 162, 225, 184, 227, 44, 4, 234, 68, 123, 128, 35, 120, 81, 241, 92, 242, 22, 2, 117, 34, 190, 64, 146, 60, 169, 249, 46, 121, 11, 1, 187, 17, 95, 32, 73, 30, 213, 253, 23, 189, 134, 129, 222, 137, 176, 16, 165, 15, 235, 255, 140, 223, 67, 193, 111, 197, 88, 8, 211, 136, 246, 256, 70, 240, 162, 225, 184, 227, 44, 4, 234, 68, 123, 128, 35, 120, 81, 241, 92, 242, 22, 2, 117, 34, 190, 64, 146, 60, 169, 249, 46, 121, 11, 1], +[1, 188, 135, 194, 235, 233, 114, 101, 227, 14, 62, 91, 146, 206, 178, 54, 129, 94, 196, 97, 246, 245, 57, 179, 242, 7, 31, 174, 73, 103, 89, 27, 193, 47, 98, 177, 123, 251, 157, 218, 121, 132, 144, 87, 165, 180, 173, 142, 225, 152, 49, 217, 190, 254, 207, 109, 189, 66, 72, 172, 211, 90, 215, 71, 241, 76, 153, 237, 95, 127, 232, 183, 223, 33, 36, 86, 234, 45, 236, 164, 249, 38, 205, 247, 176, 192, 116, 220, 240, 145, 18, 43, 117, 151, 118, 82, 253, 19, 231, 252, 88, 96, 58, 110, 120, 201, 9, 150, 187, 204, 59, 41, 255, 138, 244, 126, 44, 48, 29, 55, 60, 229, 133, 75, 222, 102, 158, 149, 256, 69, 122, 63, 22, 24, 143, 156, 30, 243, 195, 166, 111, 51, 79, 203, 128, 163, 61, 160, 11, 12, 200, 78, 15, 250, 226, 83, 184, 154, 168, 230, 64, 210, 159, 80, 134, 6, 100, 39, 136, 125, 113, 170, 92, 77, 84, 115, 32, 105, 208, 40, 67, 3, 50, 148, 68, 191, 185, 85, 46, 167, 42, 186, 16, 181, 104, 20, 162, 130, 25, 74, 34, 224, 221, 171, 23, 212, 21, 93, 8, 219, 52, 10, 81, 65, 141, 37, 17, 112, 239, 214, 140, 106, 139, 175, 4, 238, 26, 5, 169, 161, 199, 147, 137, 56, 248, 107, 70, 53, 198, 216, 2, 119, 13, 131, 213, 209, 228, 202, 197, 28, 124, 182, 35, 155, 99, 108, 1], +[1, 189, 255, 136, 4, 242, 249, 30, 16, 197, 225, 120, 64, 17, 129, 223, 256, 68, 2, 121, 253, 15, 8, 227, 241, 60, 32, 137, 193, 240, 128, 34, 1, 189, 255, 136, 4, 242, 249, 30, 16, 197, 225, 120, 64, 17, 129, 223, 256, 68, 2, 121, 253, 15, 8, 227, 241, 60, 32, 137, 193, 240, 128, 34, 1, 189, 255, 136, 4, 242, 249, 30, 16, 197, 225, 120, 64, 17, 129, 223, 256, 68, 2, 121, 253, 15, 8, 227, 241, 60, 32, 137, 193, 240, 128, 34, 1, 189, 255, 136, 4, 242, 249, 30, 16, 197, 225, 120, 64, 17, 129, 223, 256, 68, 2, 121, 253, 15, 8, 227, 241, 60, 32, 137, 193, 240, 128, 34, 1, 189, 255, 136, 4, 242, 249, 30, 16, 197, 225, 120, 64, 17, 129, 223, 256, 68, 2, 121, 253, 15, 8, 227, 241, 60, 32, 137, 193, 240, 128, 34, 1, 189, 255, 136, 4, 242, 249, 30, 16, 197, 225, 120, 64, 17, 129, 223, 256, 68, 2, 121, 253, 15, 8, 227, 241, 60, 32, 137, 193, 240, 128, 34, 1, 189, 255, 136, 4, 242, 249, 30, 16, 197, 225, 120, 64, 17, 129, 223, 256, 68, 2, 121, 253, 15, 8, 227, 241, 60, 32, 137, 193, 240, 128, 34, 1, 189, 255, 136, 4, 242, 249, 30, 16, 197, 225, 120, 64, 17, 129, 223, 256, 68, 2, 121, 253, 15, 8, 227, 241, 60, 32, 137, 193, 240, 128, 34, 1], +[1, 190, 120, 184, 8, 235, 189, 187, 64, 81, 227, 211, 255, 134, 17, 146, 241, 44, 136, 140, 129, 95, 60, 92, 4, 246, 223, 222, 32, 169, 242, 234, 256, 67, 137, 73, 249, 22, 68, 70, 193, 176, 30, 46, 2, 123, 240, 111, 16, 213, 121, 117, 128, 162, 197, 165, 253, 11, 34, 35, 225, 88, 15, 23, 1, 190, 120, 184, 8, 235, 189, 187, 64, 81, 227, 211, 255, 134, 17, 146, 241, 44, 136, 140, 129, 95, 60, 92, 4, 246, 223, 222, 32, 169, 242, 234, 256, 67, 137, 73, 249, 22, 68, 70, 193, 176, 30, 46, 2, 123, 240, 111, 16, 213, 121, 117, 128, 162, 197, 165, 253, 11, 34, 35, 225, 88, 15, 23, 1, 190, 120, 184, 8, 235, 189, 187, 64, 81, 227, 211, 255, 134, 17, 146, 241, 44, 136, 140, 129, 95, 60, 92, 4, 246, 223, 222, 32, 169, 242, 234, 256, 67, 137, 73, 249, 22, 68, 70, 193, 176, 30, 46, 2, 123, 240, 111, 16, 213, 121, 117, 128, 162, 197, 165, 253, 11, 34, 35, 225, 88, 15, 23, 1, 190, 120, 184, 8, 235, 189, 187, 64, 81, 227, 211, 255, 134, 17, 146, 241, 44, 136, 140, 129, 95, 60, 92, 4, 246, 223, 222, 32, 169, 242, 234, 256, 67, 137, 73, 249, 22, 68, 70, 193, 176, 30, 46, 2, 123, 240, 111, 16, 213, 121, 117, 128, 162, 197, 165, 253, 11, 34, 35, 225, 88, 15, 23, 1], +[1, 191, 244, 87, 169, 154, 116, 54, 34, 69, 72, 131, 92, 96, 89, 37, 128, 33, 135, 85, 44, 180, 199, 230, 240, 94, 221, 63, 211, 209, 84, 110, 193, 112, 61, 86, 235, 167, 29, 142, 137, 210, 18, 97, 23, 24, 215, 202, 32, 201, 98, 214, 11, 45, 114, 186, 60, 152, 248, 80, 117, 245, 21, 156, 241, 28, 208, 150, 123, 106, 200, 164, 227, 181, 133, 217, 70, 6, 118, 179, 8, 243, 153, 182, 67, 204, 157, 175, 15, 38, 62, 20, 222, 254, 198, 39, 253, 7, 52, 166, 95, 155, 50, 41, 121, 238, 226, 247, 146, 130, 158, 109, 2, 125, 231, 174, 81, 51, 232, 108, 68, 138, 144, 5, 184, 192, 178, 74, 256, 66, 13, 170, 88, 103, 141, 203, 223, 188, 185, 126, 165, 161, 168, 220, 129, 224, 122, 172, 213, 77, 58, 27, 17, 163, 36, 194, 46, 48, 173, 147, 64, 145, 196, 171, 22, 90, 228, 115, 120, 47, 239, 160, 234, 233, 42, 55, 225, 56, 159, 43, 246, 212, 143, 71, 197, 105, 9, 177, 140, 12, 236, 101, 16, 229, 49, 107, 134, 151, 57, 93, 30, 76, 124, 40, 187, 251, 139, 78, 249, 14, 104, 75, 190, 53, 100, 82, 242, 219, 195, 237, 35, 3, 59, 218, 4, 250, 205, 91, 162, 102, 207, 216, 136, 19, 31, 10, 111, 127, 99, 148, 255, 132, 26, 83, 176, 206, 25, 149, 189, 119, 113, 252, 73, 65, 79, 183, 1], +[1, 192, 113, 108, 176, 125, 99, 247, 136, 155, 205, 39, 35, 38, 100, 182, 249, 6, 124, 164, 134, 28, 236, 80, 197, 45, 159, 202, 234, 210, 228, 86, 64, 209, 36, 230, 213, 33, 168, 131, 223, 154, 13, 183, 184, 119, 232, 83, 2, 127, 226, 216, 95, 250, 198, 237, 15, 53, 153, 78, 70, 76, 200, 107, 241, 12, 248, 71, 11, 56, 215, 160, 137, 90, 61, 147, 211, 163, 199, 172, 128, 161, 72, 203, 169, 66, 79, 5, 189, 51, 26, 109, 111, 238, 207, 166, 4, 254, 195, 175, 190, 243, 139, 217, 30, 106, 49, 156, 140, 152, 143, 214, 225, 24, 239, 142, 22, 112, 173, 63, 17, 180, 122, 37, 165, 69, 141, 87, 256, 65, 144, 149, 81, 132, 158, 10, 121, 102, 52, 218, 222, 219, 157, 75, 8, 251, 133, 93, 123, 229, 21, 177, 60, 212, 98, 55, 23, 47, 29, 171, 193, 48, 221, 27, 44, 224, 89, 126, 34, 103, 244, 74, 73, 138, 25, 174, 255, 130, 31, 41, 162, 7, 59, 20, 242, 204, 104, 179, 187, 181, 57, 150, 16, 245, 9, 186, 246, 201, 42, 97, 120, 167, 196, 110, 46, 94, 58, 85, 129, 96, 185, 54, 88, 191, 178, 252, 68, 206, 231, 148, 146, 19, 50, 91, 253, 3, 62, 82, 67, 14, 118, 40, 227, 151, 208, 101, 117, 105, 114, 43, 32, 233, 18, 115, 235, 145, 84, 194, 240, 77, 135, 220, 92, 188, 116, 170, 1], +[1, 193, 241, 253, 256, 64, 16, 4, 1, 193, 241, 253, 256, 64, 16, 4, 1, 193, 241, 253, 256, 64, 16, 4, 1, 193, 241, 253, 256, 64, 16, 4, 1, 193, 241, 253, 256, 64, 16, 4, 1, 193, 241, 253, 256, 64, 16, 4, 1, 193, 241, 253, 256, 64, 16, 4, 1, 193, 241, 253, 256, 64, 16, 4, 1, 193, 241, 253, 256, 64, 16, 4, 1, 193, 241, 253, 256, 64, 16, 4, 1, 193, 241, 253, 256, 64, 16, 4, 1, 193, 241, 253, 256, 64, 16, 4, 1, 193, 241, 253, 256, 64, 16, 4, 1, 193, 241, 253, 256, 64, 16, 4, 1, 193, 241, 253, 256, 64, 16, 4, 1, 193, 241, 253, 256, 64, 16, 4, 1, 193, 241, 253, 256, 64, 16, 4, 1, 193, 241, 253, 256, 64, 16, 4, 1, 193, 241, 253, 256, 64, 16, 4, 1, 193, 241, 253, 256, 64, 16, 4, 1, 193, 241, 253, 256, 64, 16, 4, 1, 193, 241, 253, 256, 64, 16, 4, 1, 193, 241, 253, 256, 64, 16, 4, 1, 193, 241, 253, 256, 64, 16, 4, 1, 193, 241, 253, 256, 64, 16, 4, 1, 193, 241, 253, 256, 64, 16, 4, 1, 193, 241, 253, 256, 64, 16, 4, 1, 193, 241, 253, 256, 64, 16, 4, 1, 193, 241, 253, 256, 64, 16, 4, 1, 193, 241, 253, 256, 64, 16, 4, 1, 193, 241, 253, 256, 64, 16, 4, 1, 193, 241, 253, 256, 64, 16, 4, 1], +[1, 194, 114, 14, 146, 54, 196, 245, 242, 174, 89, 47, 123, 218, 144, 180, 225, 217, 207, 66, 211, 71, 153, 127, 223, 86, 236, 38, 176, 220, 18, 151, 253, 252, 58, 201, 187, 41, 244, 48, 60, 75, 158, 69, 22, 156, 195, 51, 128, 160, 200, 250, 184, 230, 159, 6, 136, 170, 84, 105, 67, 148, 185, 167, 16, 20, 25, 224, 23, 93, 52, 65, 17, 214, 139, 238, 169, 147, 248, 53, 2, 131, 228, 28, 35, 108, 135, 233, 227, 91, 178, 94, 246, 179, 31, 103, 193, 177, 157, 132, 165, 142, 49, 254, 189, 172, 215, 76, 95, 183, 36, 45, 249, 247, 116, 145, 117, 82, 231, 96, 120, 150, 59, 138, 44, 55, 133, 102, 256, 63, 143, 243, 111, 203, 61, 12, 15, 83, 168, 210, 134, 39, 113, 77, 32, 40, 50, 191, 46, 186, 104, 130, 34, 171, 21, 219, 81, 37, 239, 106, 4, 5, 199, 56, 70, 216, 13, 209, 197, 182, 99, 188, 235, 101, 62, 206, 129, 97, 57, 7, 73, 27, 98, 251, 121, 87, 173, 152, 190, 109, 72, 90, 241, 237, 232, 33, 234, 164, 205, 192, 240, 43, 118, 19, 88, 110, 9, 204, 255, 126, 29, 229, 222, 149, 122, 24, 30, 166, 79, 163, 11, 78, 226, 154, 64, 80, 100, 125, 92, 115, 208, 3, 68, 85, 42, 181, 162, 74, 221, 212, 8, 10, 141, 112, 140, 175, 26, 161, 137, 107, 198, 119, 213, 202, 124, 155, 1], +[1, 195, 246, 168, 121, 208, 211, 25, 249, 239, 88, 198, 60, 135, 111, 57, 64, 144, 67, 215, 34, 205, 140, 58, 2, 133, 235, 79, 242, 159, 165, 50, 241, 221, 176, 139, 120, 13, 222, 114, 128, 31, 134, 173, 68, 153, 23, 116, 4, 9, 213, 158, 227, 61, 73, 100, 225, 185, 95, 21, 240, 26, 187, 228, 256, 62, 11, 89, 136, 49, 46, 232, 8, 18, 169, 59, 197, 122, 146, 200, 193, 113, 190, 42, 223, 52, 117, 199, 255, 124, 22, 178, 15, 98, 92, 207, 16, 36, 81, 118, 137, 244, 35, 143, 129, 226, 123, 84, 189, 104, 234, 141, 253, 248, 44, 99, 30, 196, 184, 157, 32, 72, 162, 236, 17, 231, 70, 29, 1, 195, 246, 168, 121, 208, 211, 25, 249, 239, 88, 198, 60, 135, 111, 57, 64, 144, 67, 215, 34, 205, 140, 58, 2, 133, 235, 79, 242, 159, 165, 50, 241, 221, 176, 139, 120, 13, 222, 114, 128, 31, 134, 173, 68, 153, 23, 116, 4, 9, 213, 158, 227, 61, 73, 100, 225, 185, 95, 21, 240, 26, 187, 228, 256, 62, 11, 89, 136, 49, 46, 232, 8, 18, 169, 59, 197, 122, 146, 200, 193, 113, 190, 42, 223, 52, 117, 199, 255, 124, 22, 178, 15, 98, 92, 207, 16, 36, 81, 118, 137, 244, 35, 143, 129, 226, 123, 84, 189, 104, 234, 141, 253, 248, 44, 99, 30, 196, 184, 157, 32, 72, 162, 236, 17, 231, 70, 29, 1], +[1, 196, 123, 207, 223, 18, 187, 158, 128, 159, 67, 25, 17, 248, 35, 178, 193, 49, 95, 116, 120, 133, 111, 168, 32, 104, 81, 199, 197, 62, 73, 173, 241, 205, 88, 29, 30, 226, 92, 42, 8, 26, 213, 114, 242, 144, 211, 236, 253, 244, 22, 200, 136, 185, 23, 139, 2, 135, 246, 157, 189, 36, 117, 59, 256, 61, 134, 50, 34, 239, 70, 99, 129, 98, 190, 232, 240, 9, 222, 79, 64, 208, 162, 141, 137, 124, 146, 89, 225, 153, 176, 58, 60, 195, 184, 84, 16, 52, 169, 228, 227, 31, 165, 215, 249, 231, 44, 143, 15, 113, 46, 21, 4, 13, 235, 57, 121, 72, 234, 118, 255, 122, 11, 100, 68, 221, 140, 198, 1, 196, 123, 207, 223, 18, 187, 158, 128, 159, 67, 25, 17, 248, 35, 178, 193, 49, 95, 116, 120, 133, 111, 168, 32, 104, 81, 199, 197, 62, 73, 173, 241, 205, 88, 29, 30, 226, 92, 42, 8, 26, 213, 114, 242, 144, 211, 236, 253, 244, 22, 200, 136, 185, 23, 139, 2, 135, 246, 157, 189, 36, 117, 59, 256, 61, 134, 50, 34, 239, 70, 99, 129, 98, 190, 232, 240, 9, 222, 79, 64, 208, 162, 141, 137, 124, 146, 89, 225, 153, 176, 58, 60, 195, 184, 84, 16, 52, 169, 228, 227, 31, 165, 215, 249, 231, 44, 143, 15, 113, 46, 21, 4, 13, 235, 57, 121, 72, 234, 118, 255, 122, 11, 100, 68, 221, 140, 198, 1], +[1, 197, 2, 137, 4, 17, 8, 34, 16, 68, 32, 136, 64, 15, 128, 30, 256, 60, 255, 120, 253, 240, 249, 223, 241, 189, 225, 121, 193, 242, 129, 227, 1, 197, 2, 137, 4, 17, 8, 34, 16, 68, 32, 136, 64, 15, 128, 30, 256, 60, 255, 120, 253, 240, 249, 223, 241, 189, 225, 121, 193, 242, 129, 227, 1, 197, 2, 137, 4, 17, 8, 34, 16, 68, 32, 136, 64, 15, 128, 30, 256, 60, 255, 120, 253, 240, 249, 223, 241, 189, 225, 121, 193, 242, 129, 227, 1, 197, 2, 137, 4, 17, 8, 34, 16, 68, 32, 136, 64, 15, 128, 30, 256, 60, 255, 120, 253, 240, 249, 223, 241, 189, 225, 121, 193, 242, 129, 227, 1, 197, 2, 137, 4, 17, 8, 34, 16, 68, 32, 136, 64, 15, 128, 30, 256, 60, 255, 120, 253, 240, 249, 223, 241, 189, 225, 121, 193, 242, 129, 227, 1, 197, 2, 137, 4, 17, 8, 34, 16, 68, 32, 136, 64, 15, 128, 30, 256, 60, 255, 120, 253, 240, 249, 223, 241, 189, 225, 121, 193, 242, 129, 227, 1, 197, 2, 137, 4, 17, 8, 34, 16, 68, 32, 136, 64, 15, 128, 30, 256, 60, 255, 120, 253, 240, 249, 223, 241, 189, 225, 121, 193, 242, 129, 227, 1, 197, 2, 137, 4, 17, 8, 34, 16, 68, 32, 136, 64, 15, 128, 30, 256, 60, 255, 120, 253, 240, 249, 223, 241, 189, 225, 121, 193, 242, 129, 227, 1], +[1, 198, 140, 221, 68, 100, 11, 122, 255, 118, 234, 72, 121, 57, 235, 13, 4, 21, 46, 113, 15, 143, 44, 231, 249, 215, 165, 31, 227, 228, 169, 52, 16, 84, 184, 195, 60, 58, 176, 153, 225, 89, 146, 124, 137, 141, 162, 208, 64, 79, 222, 9, 240, 232, 190, 98, 129, 99, 70, 239, 34, 50, 134, 61, 256, 59, 117, 36, 189, 157, 246, 135, 2, 139, 23, 185, 136, 200, 22, 244, 253, 236, 211, 144, 242, 114, 213, 26, 8, 42, 92, 226, 30, 29, 88, 205, 241, 173, 73, 62, 197, 199, 81, 104, 32, 168, 111, 133, 120, 116, 95, 49, 193, 178, 35, 248, 17, 25, 67, 159, 128, 158, 187, 18, 223, 207, 123, 196, 1, 198, 140, 221, 68, 100, 11, 122, 255, 118, 234, 72, 121, 57, 235, 13, 4, 21, 46, 113, 15, 143, 44, 231, 249, 215, 165, 31, 227, 228, 169, 52, 16, 84, 184, 195, 60, 58, 176, 153, 225, 89, 146, 124, 137, 141, 162, 208, 64, 79, 222, 9, 240, 232, 190, 98, 129, 99, 70, 239, 34, 50, 134, 61, 256, 59, 117, 36, 189, 157, 246, 135, 2, 139, 23, 185, 136, 200, 22, 244, 253, 236, 211, 144, 242, 114, 213, 26, 8, 42, 92, 226, 30, 29, 88, 205, 241, 173, 73, 62, 197, 199, 81, 104, 32, 168, 111, 133, 120, 116, 95, 49, 193, 178, 35, 248, 17, 25, 67, 159, 128, 158, 187, 18, 223, 207, 123, 196, 1], +[1, 199, 23, 208, 15, 158, 88, 36, 225, 57, 35, 26, 34, 84, 11, 133, 253, 232, 165, 196, 197, 139, 162, 113, 128, 29, 117, 153, 121, 178, 213, 239, 16, 100, 111, 244, 240, 215, 123, 62, 2, 141, 46, 159, 30, 59, 176, 72, 193, 114, 70, 52, 68, 168, 22, 9, 249, 207, 73, 135, 137, 21, 67, 226, 256, 58, 234, 49, 242, 99, 169, 221, 32, 200, 222, 231, 223, 173, 246, 124, 4, 25, 92, 61, 60, 118, 95, 144, 129, 228, 140, 104, 136, 79, 44, 18, 241, 157, 146, 13, 17, 42, 134, 195, 255, 116, 211, 98, 227, 198, 81, 185, 64, 143, 187, 205, 189, 89, 235, 248, 8, 50, 184, 122, 120, 236, 190, 31, 1, 199, 23, 208, 15, 158, 88, 36, 225, 57, 35, 26, 34, 84, 11, 133, 253, 232, 165, 196, 197, 139, 162, 113, 128, 29, 117, 153, 121, 178, 213, 239, 16, 100, 111, 244, 240, 215, 123, 62, 2, 141, 46, 159, 30, 59, 176, 72, 193, 114, 70, 52, 68, 168, 22, 9, 249, 207, 73, 135, 137, 21, 67, 226, 256, 58, 234, 49, 242, 99, 169, 221, 32, 200, 222, 231, 223, 173, 246, 124, 4, 25, 92, 61, 60, 118, 95, 144, 129, 228, 140, 104, 136, 79, 44, 18, 241, 157, 146, 13, 17, 42, 134, 195, 255, 116, 211, 98, 227, 198, 81, 185, 64, 143, 187, 205, 189, 89, 235, 248, 8, 50, 184, 122, 120, 236, 190, 31, 1], +[1, 200, 165, 104, 240, 198, 22, 31, 32, 232, 140, 244, 227, 168, 190, 221, 253, 228, 111, 98, 68, 236, 169, 133, 129, 100, 211, 52, 120, 99, 11, 144, 16, 116, 70, 122, 242, 84, 95, 239, 255, 114, 184, 49, 34, 118, 213, 195, 193, 50, 234, 26, 60, 178, 134, 72, 8, 58, 35, 61, 121, 42, 176, 248, 256, 57, 92, 153, 17, 59, 235, 226, 225, 25, 117, 13, 30, 89, 67, 36, 4, 29, 146, 159, 189, 21, 88, 124, 128, 157, 46, 205, 137, 158, 246, 113, 241, 141, 187, 135, 15, 173, 162, 18, 2, 143, 73, 208, 223, 139, 44, 62, 64, 207, 23, 231, 197, 79, 123, 185, 249, 199, 222, 196, 136, 215, 81, 9, 1, 200, 165, 104, 240, 198, 22, 31, 32, 232, 140, 244, 227, 168, 190, 221, 253, 228, 111, 98, 68, 236, 169, 133, 129, 100, 211, 52, 120, 99, 11, 144, 16, 116, 70, 122, 242, 84, 95, 239, 255, 114, 184, 49, 34, 118, 213, 195, 193, 50, 234, 26, 60, 178, 134, 72, 8, 58, 35, 61, 121, 42, 176, 248, 256, 57, 92, 153, 17, 59, 235, 226, 225, 25, 117, 13, 30, 89, 67, 36, 4, 29, 146, 159, 189, 21, 88, 124, 128, 157, 46, 205, 137, 158, 246, 113, 241, 141, 187, 135, 15, 173, 162, 18, 2, 143, 73, 208, 223, 139, 44, 62, 64, 207, 23, 231, 197, 79, 123, 185, 249, 199, 222, 196, 136, 215, 81, 9, 1], +[1, 201, 52, 172, 134, 206, 29, 175, 223, 105, 31, 63, 70, 192, 42, 218, 128, 28, 231, 171, 190, 154, 114, 41, 17, 76, 113, 97, 222, 161, 236, 148, 193, 243, 13, 43, 162, 180, 200, 108, 120, 219, 72, 80, 146, 48, 139, 183, 32, 7, 122, 107, 176, 167, 157, 203, 197, 19, 221, 217, 184, 233, 59, 37, 241, 125, 196, 75, 169, 45, 50, 27, 30, 119, 18, 20, 165, 12, 99, 110, 8, 66, 159, 91, 44, 106, 232, 115, 242, 69, 248, 247, 46, 251, 79, 202, 253, 224, 49, 83, 235, 204, 141, 71, 136, 94, 133, 5, 234, 3, 89, 156, 2, 145, 104, 87, 11, 155, 58, 93, 189, 210, 62, 126, 140, 127, 84, 179, 256, 56, 205, 85, 123, 51, 228, 82, 34, 152, 226, 194, 187, 65, 215, 39, 129, 229, 26, 86, 67, 103, 143, 216, 240, 181, 144, 160, 35, 96, 21, 109, 64, 14, 244, 214, 95, 77, 57, 149, 137, 38, 185, 177, 111, 209, 118, 74, 225, 250, 135, 150, 81, 90, 100, 54, 60, 238, 36, 40, 73, 24, 198, 220, 16, 132, 61, 182, 88, 212, 207, 230, 227, 138, 239, 237, 92, 245, 158, 147, 249, 191, 98, 166, 213, 151, 25, 142, 15, 188, 9, 10, 211, 6, 178, 55, 4, 33, 208, 174, 22, 53, 116, 186, 121, 163, 124, 252, 23, 254, 168, 101, 255, 112, 153, 170, 246, 102, 199, 164, 68, 47, 195, 131, 117, 130, 173, 78, 1], +[1, 202, 198, 161, 140, 10, 221, 181, 68, 115, 100, 154, 11, 166, 122, 229, 255, 110, 118, 192, 234, 237, 72, 152, 121, 27, 57, 206, 235, 182, 13, 56, 4, 37, 21, 130, 46, 40, 113, 210, 15, 203, 143, 102, 44, 150, 231, 145, 249, 183, 215, 254, 165, 177, 31, 94, 227, 108, 228, 53, 169, 214, 52, 224, 16, 148, 84, 6, 184, 160, 195, 69, 60, 41, 58, 151, 176, 86, 153, 66, 225, 218, 89, 245, 146, 194, 124, 119, 137, 175, 141, 212, 162, 85, 208, 125, 64, 78, 79, 24, 222, 126, 9, 19, 240, 164, 232, 90, 190, 87, 98, 7, 129, 101, 99, 209, 70, 5, 239, 219, 34, 186, 50, 77, 134, 83, 61, 243, 256, 55, 59, 96, 117, 247, 36, 76, 189, 142, 157, 103, 246, 91, 135, 28, 2, 147, 139, 65, 23, 20, 185, 105, 136, 230, 200, 51, 22, 75, 244, 201, 253, 220, 236, 127, 211, 217, 144, 47, 242, 54, 114, 155, 213, 107, 26, 112, 8, 74, 42, 3, 92, 80, 226, 163, 30, 149, 29, 204, 88, 43, 205, 33, 241, 109, 173, 251, 73, 97, 62, 188, 197, 216, 199, 106, 81, 171, 104, 191, 32, 39, 168, 12, 111, 63, 133, 138, 120, 82, 116, 45, 95, 172, 49, 132, 193, 179, 178, 233, 35, 131, 248, 238, 17, 93, 25, 167, 67, 170, 159, 250, 128, 156, 158, 48, 187, 252, 18, 38, 223, 71, 207, 180, 123, 174, 196, 14, 1], +[1, 203, 89, 77, 211, 171, 18, 56, 60, 101, 200, 251, 67, 237, 52, 19, 2, 149, 178, 154, 165, 85, 36, 112, 120, 202, 143, 245, 134, 217, 104, 38, 4, 41, 99, 51, 73, 170, 72, 224, 240, 147, 29, 233, 11, 177, 208, 76, 8, 82, 198, 102, 146, 83, 144, 191, 223, 37, 58, 209, 22, 97, 159, 152, 16, 164, 139, 204, 35, 166, 31, 125, 189, 74, 116, 161, 44, 194, 61, 47, 32, 71, 21, 151, 70, 75, 62, 250, 121, 148, 232, 65, 88, 131, 122, 94, 64, 142, 42, 45, 140, 150, 124, 243, 242, 39, 207, 130, 176, 5, 244, 188, 128, 27, 84, 90, 23, 43, 248, 229, 227, 78, 157, 3, 95, 10, 231, 119, 256, 54, 168, 180, 46, 86, 239, 201, 197, 156, 57, 6, 190, 20, 205, 238, 255, 108, 79, 103, 92, 172, 221, 145, 137, 55, 114, 12, 123, 40, 153, 219, 253, 216, 158, 206, 184, 87, 185, 33, 17, 110, 228, 24, 246, 80, 49, 181, 249, 175, 59, 155, 111, 174, 113, 66, 34, 220, 199, 48, 235, 160, 98, 105, 241, 93, 118, 53, 222, 91, 226, 132, 68, 183, 141, 96, 213, 63, 196, 210, 225, 186, 236, 106, 187, 182, 195, 7, 136, 109, 25, 192, 169, 126, 135, 163, 193, 115, 215, 212, 117, 107, 133, 14, 15, 218, 50, 127, 81, 252, 13, 69, 129, 230, 173, 167, 234, 214, 9, 28, 30, 179, 100, 254, 162, 247, 26, 138, 1], +[1, 204, 239, 183, 67, 47, 79, 182, 120, 65, 153, 115, 73, 243, 228, 252, 8, 90, 113, 179, 22, 119, 118, 171, 189, 6, 196, 149, 70, 145, 25, 217, 64, 206, 133, 147, 176, 181, 173, 83, 227, 48, 26, 164, 46, 132, 200, 194, 255, 106, 36, 148, 123, 163, 99, 150, 17, 127, 208, 27, 111, 28, 58, 10, 241, 77, 31, 156, 213, 19, 21, 172, 136, 245, 122, 216, 117, 224, 207, 80, 129, 102, 248, 220, 162, 152, 168, 91, 60, 161, 205, 186, 165, 250, 114, 126, 4, 45, 185, 218, 11, 188, 59, 214, 223, 3, 98, 203, 35, 201, 141, 237, 32, 103, 195, 202, 88, 219, 215, 170, 242, 24, 13, 82, 23, 66, 100, 97, 256, 53, 18, 74, 190, 210, 178, 75, 137, 192, 104, 142, 184, 14, 29, 5, 249, 167, 144, 78, 235, 138, 139, 86, 68, 251, 61, 108, 187, 112, 232, 40, 193, 51, 124, 110, 81, 76, 84, 174, 30, 209, 231, 93, 211, 125, 57, 63, 2, 151, 221, 109, 134, 94, 158, 107, 240, 130, 49, 230, 146, 229, 199, 247, 16, 180, 226, 101, 44, 238, 236, 85, 121, 12, 135, 41, 140, 33, 50, 177, 128, 155, 9, 37, 95, 105, 89, 166, 197, 96, 52, 71, 92, 7, 143, 131, 253, 212, 72, 39, 246, 69, 198, 43, 34, 254, 159, 54, 222, 56, 116, 20, 225, 154, 62, 55, 169, 38, 42, 87, 15, 233, 244, 175, 234, 191, 157, 160, 1], +[1, 205, 134, 228, 223, 226, 70, 215, 128, 26, 190, 143, 17, 144, 222, 21, 193, 244, 162, 57, 120, 185, 146, 118, 32, 135, 176, 100, 197, 36, 184, 198, 241, 61, 169, 207, 30, 239, 165, 158, 8, 98, 44, 25, 242, 9, 46, 178, 253, 208, 235, 116, 136, 124, 234, 168, 2, 153, 11, 199, 189, 195, 140, 173, 256, 52, 123, 29, 34, 31, 187, 42, 129, 231, 67, 114, 240, 113, 35, 236, 64, 13, 95, 200, 137, 72, 111, 139, 225, 122, 81, 157, 60, 221, 73, 59, 16, 196, 88, 50, 227, 18, 92, 99, 249, 159, 213, 232, 15, 248, 211, 79, 4, 49, 22, 141, 121, 133, 23, 89, 255, 104, 246, 58, 68, 62, 117, 84, 1, 205, 134, 228, 223, 226, 70, 215, 128, 26, 190, 143, 17, 144, 222, 21, 193, 244, 162, 57, 120, 185, 146, 118, 32, 135, 176, 100, 197, 36, 184, 198, 241, 61, 169, 207, 30, 239, 165, 158, 8, 98, 44, 25, 242, 9, 46, 178, 253, 208, 235, 116, 136, 124, 234, 168, 2, 153, 11, 199, 189, 195, 140, 173, 256, 52, 123, 29, 34, 31, 187, 42, 129, 231, 67, 114, 240, 113, 35, 236, 64, 13, 95, 200, 137, 72, 111, 139, 225, 122, 81, 157, 60, 221, 73, 59, 16, 196, 88, 50, 227, 18, 92, 99, 249, 159, 213, 232, 15, 248, 211, 79, 4, 49, 22, 141, 121, 133, 23, 89, 255, 104, 246, 58, 68, 62, 117, 84, 1], +[1, 206, 31, 218, 190, 76, 236, 43, 120, 48, 122, 203, 184, 125, 50, 20, 8, 106, 248, 202, 235, 94, 89, 87, 189, 127, 205, 82, 187, 229, 143, 160, 64, 77, 185, 74, 81, 238, 198, 182, 227, 245, 98, 142, 211, 33, 116, 252, 255, 102, 195, 78, 134, 105, 42, 171, 17, 161, 13, 108, 146, 7, 157, 217, 241, 45, 18, 110, 44, 69, 79, 83, 136, 3, 104, 93, 140, 56, 228, 194, 129, 103, 144, 109, 95, 38, 118, 150, 60, 24, 61, 230, 92, 191, 25, 10, 4, 53, 124, 101, 246, 47, 173, 172, 223, 192, 231, 41, 222, 243, 200, 80, 32, 167, 221, 37, 169, 119, 99, 91, 242, 251, 49, 71, 234, 145, 58, 126, 256, 51, 226, 39, 67, 181, 21, 214, 137, 209, 135, 54, 73, 132, 207, 237, 249, 151, 9, 55, 22, 163, 168, 170, 68, 130, 52, 175, 70, 28, 114, 97, 193, 180, 72, 183, 176, 19, 59, 75, 30, 12, 159, 115, 46, 224, 141, 5, 2, 155, 62, 179, 123, 152, 215, 86, 240, 96, 244, 149, 111, 250, 100, 40, 16, 212, 239, 147, 213, 188, 178, 174, 121, 254, 153, 164, 117, 201, 29, 63, 128, 154, 113, 148, 162, 219, 139, 107, 197, 233, 196, 27, 165, 66, 232, 247, 253, 204, 133, 156, 11, 210, 84, 85, 34, 65, 26, 216, 35, 14, 57, 177, 225, 90, 36, 220, 88, 138, 158, 166, 15, 6, 208, 186, 23, 112, 199, 131, 1], +[1, 207, 187, 159, 17, 178, 95, 133, 32, 199, 73, 205, 30, 42, 213, 144, 253, 200, 23, 135, 189, 59, 134, 239, 129, 232, 222, 208, 137, 89, 176, 195, 16, 228, 165, 231, 15, 21, 235, 72, 255, 100, 140, 196, 223, 158, 67, 248, 193, 116, 111, 104, 197, 173, 88, 226, 8, 114, 211, 244, 136, 139, 246, 36, 256, 50, 70, 98, 240, 79, 162, 124, 225, 58, 184, 52, 227, 215, 44, 113, 4, 57, 234, 122, 68, 198, 123, 18, 128, 25, 35, 49, 120, 168, 81, 62, 241, 29, 92, 26, 242, 236, 22, 185, 2, 157, 117, 61, 34, 99, 190, 9, 64, 141, 146, 153, 60, 84, 169, 31, 249, 143, 46, 13, 121, 118, 11, 221, 1, 207, 187, 159, 17, 178, 95, 133, 32, 199, 73, 205, 30, 42, 213, 144, 253, 200, 23, 135, 189, 59, 134, 239, 129, 232, 222, 208, 137, 89, 176, 195, 16, 228, 165, 231, 15, 21, 235, 72, 255, 100, 140, 196, 223, 158, 67, 248, 193, 116, 111, 104, 197, 173, 88, 226, 8, 114, 211, 244, 136, 139, 246, 36, 256, 50, 70, 98, 240, 79, 162, 124, 225, 58, 184, 52, 227, 215, 44, 113, 4, 57, 234, 122, 68, 198, 123, 18, 128, 25, 35, 49, 120, 168, 81, 62, 241, 29, 92, 26, 242, 236, 22, 185, 2, 157, 117, 61, 34, 99, 190, 9, 64, 141, 146, 153, 60, 84, 169, 31, 249, 143, 46, 13, 121, 118, 11, 221, 1], +[1, 208, 88, 57, 34, 133, 165, 139, 128, 153, 213, 100, 240, 62, 46, 59, 193, 52, 22, 207, 137, 226, 234, 99, 32, 231, 246, 25, 60, 144, 140, 79, 241, 13, 134, 116, 227, 185, 187, 89, 8, 122, 190, 199, 15, 36, 35, 84, 253, 196, 162, 29, 121, 239, 111, 215, 2, 159, 176, 114, 68, 9, 73, 21, 256, 49, 169, 200, 223, 124, 92, 118, 129, 104, 44, 157, 17, 195, 211, 198, 64, 205, 235, 50, 120, 31, 23, 158, 225, 26, 11, 232, 197, 113, 117, 178, 16, 244, 123, 141, 30, 72, 70, 168, 249, 135, 67, 58, 242, 221, 222, 173, 4, 61, 95, 228, 136, 18, 146, 42, 255, 98, 81, 143, 189, 248, 184, 236, 1, 208, 88, 57, 34, 133, 165, 139, 128, 153, 213, 100, 240, 62, 46, 59, 193, 52, 22, 207, 137, 226, 234, 99, 32, 231, 246, 25, 60, 144, 140, 79, 241, 13, 134, 116, 227, 185, 187, 89, 8, 122, 190, 199, 15, 36, 35, 84, 253, 196, 162, 29, 121, 239, 111, 215, 2, 159, 176, 114, 68, 9, 73, 21, 256, 49, 169, 200, 223, 124, 92, 118, 129, 104, 44, 157, 17, 195, 211, 198, 64, 205, 235, 50, 120, 31, 23, 158, 225, 26, 11, 232, 197, 113, 117, 178, 16, 244, 123, 141, 30, 72, 70, 168, 249, 135, 67, 58, 242, 221, 222, 173, 4, 61, 95, 228, 136, 18, 146, 42, 255, 98, 81, 143, 189, 248, 184, 236, 1], +[1, 209, 248, 175, 81, 224, 42, 40, 136, 154, 61, 156, 222, 138, 58, 43, 249, 127, 72, 142, 123, 7, 178, 194, 197, 53, 26, 37, 23, 181, 50, 170, 64, 12, 195, 149, 44, 201, 118, 247, 223, 90, 49, 218, 73, 94, 114, 182, 2, 161, 239, 93, 162, 191, 84, 80, 15, 51, 122, 55, 187, 19, 116, 86, 241, 254, 144, 27, 246, 14, 99, 131, 137, 106, 52, 74, 46, 105, 100, 83, 128, 24, 133, 41, 88, 145, 236, 237, 189, 180, 98, 179, 146, 188, 228, 107, 4, 65, 221, 186, 67, 125, 168, 160, 30, 102, 244, 110, 117, 38, 232, 172, 225, 251, 31, 54, 235, 28, 198, 5, 17, 212, 104, 148, 92, 210, 200, 166, 256, 48, 9, 82, 176, 33, 215, 217, 121, 103, 196, 101, 35, 119, 199, 214, 8, 130, 185, 115, 134, 250, 79, 63, 60, 204, 231, 220, 234, 76, 207, 87, 193, 245, 62, 108, 213, 56, 139, 10, 34, 167, 208, 39, 184, 163, 143, 75, 255, 96, 18, 164, 95, 66, 173, 177, 242, 206, 135, 202, 70, 238, 141, 171, 16, 3, 113, 230, 11, 243, 158, 126, 120, 151, 205, 183, 211, 152, 157, 174, 129, 233, 124, 216, 169, 112, 21, 20, 68, 77, 159, 78, 111, 69, 29, 150, 253, 192, 36, 71, 190, 132, 89, 97, 227, 155, 13, 147, 140, 219, 25, 85, 32, 6, 226, 203, 22, 229, 59, 252, 240, 45, 153, 109, 165, 47, 57, 91, 1], +[1, 210, 153, 5, 22, 251, 25, 110, 227, 125, 36, 107, 111, 180, 21, 41, 129, 105, 205, 131, 11, 254, 141, 55, 242, 191, 18, 182, 184, 90, 139, 149, 193, 181, 231, 194, 134, 127, 199, 156, 121, 224, 9, 91, 92, 45, 198, 203, 225, 219, 244, 97, 67, 192, 228, 78, 189, 112, 133, 174, 46, 151, 99, 230, 241, 238, 122, 177, 162, 96, 114, 39, 223, 56, 195, 87, 23, 204, 178, 115, 249, 119, 61, 217, 81, 48, 57, 148, 240, 28, 226, 172, 140, 102, 89, 186, 253, 188, 159, 237, 169, 24, 157, 74, 120, 14, 113, 86, 70, 51, 173, 93, 255, 94, 208, 247, 213, 12, 207, 37, 60, 7, 185, 43, 35, 154, 215, 175, 256, 47, 104, 252, 235, 6, 232, 147, 30, 132, 221, 150, 146, 77, 236, 216, 128, 152, 52, 126, 246, 3, 116, 202, 15, 66, 239, 75, 73, 167, 118, 108, 64, 76, 26, 63, 123, 130, 58, 101, 136, 33, 248, 166, 165, 212, 59, 54, 32, 38, 13, 160, 190, 65, 29, 179, 68, 145, 124, 83, 211, 106, 158, 27, 16, 19, 135, 80, 95, 161, 143, 218, 34, 201, 62, 170, 234, 53, 79, 142, 8, 138, 196, 40, 176, 209, 200, 109, 17, 229, 31, 85, 117, 155, 168, 71, 4, 69, 98, 20, 88, 233, 100, 183, 137, 243, 144, 171, 187, 206, 84, 164, 2, 163, 49, 10, 44, 245, 50, 220, 197, 250, 72, 214, 222, 103, 42, 82, 1], +[1, 211, 60, 67, 2, 165, 120, 134, 4, 73, 240, 11, 8, 146, 223, 22, 16, 35, 189, 44, 32, 70, 121, 88, 64, 140, 242, 176, 128, 23, 227, 95, 256, 46, 197, 190, 255, 92, 137, 123, 253, 184, 17, 246, 249, 111, 34, 235, 241, 222, 68, 213, 225, 187, 136, 169, 193, 117, 15, 81, 129, 234, 30, 162, 1, 211, 60, 67, 2, 165, 120, 134, 4, 73, 240, 11, 8, 146, 223, 22, 16, 35, 189, 44, 32, 70, 121, 88, 64, 140, 242, 176, 128, 23, 227, 95, 256, 46, 197, 190, 255, 92, 137, 123, 253, 184, 17, 246, 249, 111, 34, 235, 241, 222, 68, 213, 225, 187, 136, 169, 193, 117, 15, 81, 129, 234, 30, 162, 1, 211, 60, 67, 2, 165, 120, 134, 4, 73, 240, 11, 8, 146, 223, 22, 16, 35, 189, 44, 32, 70, 121, 88, 64, 140, 242, 176, 128, 23, 227, 95, 256, 46, 197, 190, 255, 92, 137, 123, 253, 184, 17, 246, 249, 111, 34, 235, 241, 222, 68, 213, 225, 187, 136, 169, 193, 117, 15, 81, 129, 234, 30, 162, 1, 211, 60, 67, 2, 165, 120, 134, 4, 73, 240, 11, 8, 146, 223, 22, 16, 35, 189, 44, 32, 70, 121, 88, 64, 140, 242, 176, 128, 23, 227, 95, 256, 46, 197, 190, 255, 92, 137, 123, 253, 184, 17, 246, 249, 111, 34, 235, 241, 222, 68, 213, 225, 187, 136, 169, 193, 117, 15, 81, 129, 234, 30, 162, 1], +[1, 212, 226, 110, 190, 188, 21, 83, 120, 254, 135, 93, 184, 201, 207, 194, 8, 154, 9, 109, 235, 219, 168, 150, 189, 233, 52, 230, 187, 66, 114, 10, 64, 204, 72, 101, 81, 210, 59, 172, 227, 65, 159, 41, 211, 14, 141, 80, 255, 90, 62, 37, 134, 138, 215, 91, 17, 6, 244, 71, 146, 112, 100, 126, 241, 206, 239, 39, 44, 76, 178, 214, 136, 48, 153, 54, 140, 125, 29, 237, 129, 106, 113, 55, 95, 94, 139, 170, 60, 127, 196, 175, 92, 229, 232, 97, 4, 77, 133, 183, 246, 238, 84, 75, 223, 245, 26, 115, 222, 33, 57, 5, 32, 102, 36, 179, 169, 105, 158, 86, 242, 161, 208, 149, 234, 7, 199, 40, 256, 45, 31, 147, 67, 69, 236, 174, 137, 3, 122, 164, 73, 56, 50, 63, 249, 103, 248, 148, 22, 38, 89, 107, 68, 24, 205, 27, 70, 191, 143, 247, 193, 53, 185, 156, 176, 47, 198, 85, 30, 192, 98, 216, 46, 243, 116, 177, 2, 167, 195, 220, 123, 119, 42, 166, 240, 251, 13, 186, 111, 145, 157, 131, 16, 51, 18, 218, 213, 181, 79, 43, 121, 209, 104, 203, 117, 132, 228, 20, 128, 151, 144, 202, 162, 163, 118, 87, 197, 130, 61, 82, 165, 28, 25, 160, 253, 180, 124, 74, 11, 19, 173, 182, 34, 12, 231, 142, 35, 224, 200, 252, 225, 155, 221, 78, 88, 152, 99, 171, 15, 96, 49, 108, 23, 250, 58, 217, 1], +[1, 213, 137, 140, 8, 162, 68, 92, 64, 11, 30, 222, 255, 88, 240, 234, 241, 190, 121, 73, 129, 235, 197, 70, 4, 81, 34, 46, 32, 134, 15, 111, 256, 44, 120, 117, 249, 95, 189, 165, 193, 246, 227, 35, 2, 169, 17, 23, 16, 67, 136, 184, 128, 22, 60, 187, 253, 176, 223, 211, 225, 123, 242, 146, 1, 213, 137, 140, 8, 162, 68, 92, 64, 11, 30, 222, 255, 88, 240, 234, 241, 190, 121, 73, 129, 235, 197, 70, 4, 81, 34, 46, 32, 134, 15, 111, 256, 44, 120, 117, 249, 95, 189, 165, 193, 246, 227, 35, 2, 169, 17, 23, 16, 67, 136, 184, 128, 22, 60, 187, 253, 176, 223, 211, 225, 123, 242, 146, 1, 213, 137, 140, 8, 162, 68, 92, 64, 11, 30, 222, 255, 88, 240, 234, 241, 190, 121, 73, 129, 235, 197, 70, 4, 81, 34, 46, 32, 134, 15, 111, 256, 44, 120, 117, 249, 95, 189, 165, 193, 246, 227, 35, 2, 169, 17, 23, 16, 67, 136, 184, 128, 22, 60, 187, 253, 176, 223, 211, 225, 123, 242, 146, 1, 213, 137, 140, 8, 162, 68, 92, 64, 11, 30, 222, 255, 88, 240, 234, 241, 190, 121, 73, 129, 235, 197, 70, 4, 81, 34, 46, 32, 134, 15, 111, 256, 44, 120, 117, 249, 95, 189, 165, 193, 246, 227, 35, 2, 169, 17, 23, 16, 67, 136, 184, 128, 22, 60, 187, 253, 176, 223, 211, 225, 123, 242, 146, 1], +[1, 214, 50, 163, 187, 183, 98, 155, 17, 40, 79, 201, 95, 27, 124, 65, 32, 166, 58, 76, 73, 202, 52, 77, 30, 252, 215, 7, 213, 93, 113, 24, 253, 172, 57, 119, 23, 39, 122, 151, 189, 97, 198, 224, 134, 149, 18, 254, 129, 107, 25, 210, 222, 220, 49, 206, 137, 20, 168, 229, 176, 142, 62, 161, 16, 83, 29, 38, 165, 101, 26, 167, 15, 126, 236, 132, 235, 175, 185, 12, 255, 86, 157, 188, 140, 148, 61, 204, 223, 177, 99, 112, 67, 203, 9, 127, 193, 182, 141, 105, 111, 110, 153, 103, 197, 10, 84, 243, 88, 71, 31, 209, 8, 170, 143, 19, 211, 179, 13, 212, 136, 63, 118, 66, 246, 216, 221, 6, 256, 43, 207, 94, 70, 74, 159, 102, 240, 217, 178, 56, 162, 230, 133, 192, 225, 91, 199, 181, 184, 55, 205, 180, 227, 5, 42, 250, 44, 164, 144, 233, 4, 85, 200, 138, 234, 218, 135, 106, 68, 160, 59, 33, 123, 108, 239, 3, 128, 150, 232, 47, 35, 37, 208, 51, 120, 237, 89, 28, 81, 115, 195, 96, 241, 174, 228, 219, 92, 156, 231, 90, 242, 131, 21, 125, 22, 82, 72, 245, 2, 171, 100, 69, 117, 109, 196, 53, 34, 80, 158, 145, 190, 54, 248, 130, 64, 75, 116, 152, 146, 147, 104, 154, 60, 247, 173, 14, 169, 186, 226, 48, 249, 87, 114, 238, 46, 78, 244, 45, 121, 194, 139, 191, 11, 41, 36, 251, 1], +[1, 215, 222, 185, 197, 207, 44, 208, 2, 173, 187, 113, 137, 157, 88, 159, 4, 89, 117, 226, 17, 57, 176, 61, 8, 178, 234, 195, 34, 114, 95, 122, 16, 99, 211, 133, 68, 228, 190, 244, 32, 198, 165, 9, 136, 199, 123, 231, 64, 139, 73, 18, 15, 141, 246, 205, 128, 21, 146, 36, 30, 25, 235, 153, 256, 42, 35, 72, 60, 50, 213, 49, 255, 84, 70, 144, 120, 100, 169, 98, 253, 168, 140, 31, 240, 200, 81, 196, 249, 79, 23, 62, 223, 143, 162, 135, 241, 158, 46, 124, 189, 29, 67, 13, 225, 59, 92, 248, 121, 58, 134, 26, 193, 118, 184, 239, 242, 116, 11, 52, 129, 236, 111, 221, 227, 232, 22, 104, 1, 215, 222, 185, 197, 207, 44, 208, 2, 173, 187, 113, 137, 157, 88, 159, 4, 89, 117, 226, 17, 57, 176, 61, 8, 178, 234, 195, 34, 114, 95, 122, 16, 99, 211, 133, 68, 228, 190, 244, 32, 198, 165, 9, 136, 199, 123, 231, 64, 139, 73, 18, 15, 141, 246, 205, 128, 21, 146, 36, 30, 25, 235, 153, 256, 42, 35, 72, 60, 50, 213, 49, 255, 84, 70, 144, 120, 100, 169, 98, 253, 168, 140, 31, 240, 200, 81, 196, 249, 79, 23, 62, 223, 143, 162, 135, 241, 158, 46, 124, 189, 29, 67, 13, 225, 59, 92, 248, 121, 58, 134, 26, 193, 118, 184, 239, 242, 116, 11, 52, 129, 236, 111, 221, 227, 232, 22, 104, 1], +[1, 216, 139, 212, 46, 170, 226, 243, 60, 110, 116, 127, 190, 177, 196, 188, 2, 175, 21, 167, 92, 83, 195, 229, 120, 220, 232, 254, 123, 97, 135, 119, 4, 93, 42, 77, 184, 166, 133, 201, 240, 183, 207, 251, 246, 194, 13, 238, 8, 186, 84, 154, 111, 75, 9, 145, 223, 109, 157, 245, 235, 131, 26, 219, 16, 115, 168, 51, 222, 150, 18, 33, 189, 218, 57, 233, 213, 5, 52, 181, 32, 230, 79, 102, 187, 43, 36, 66, 121, 179, 114, 209, 169, 10, 104, 105, 64, 203, 158, 204, 117, 86, 72, 132, 242, 101, 228, 161, 81, 20, 208, 210, 128, 149, 59, 151, 234, 172, 144, 7, 227, 202, 199, 65, 162, 40, 159, 163, 256, 41, 118, 45, 211, 87, 31, 14, 197, 147, 141, 130, 67, 80, 61, 69, 255, 82, 236, 90, 165, 174, 62, 28, 137, 37, 25, 3, 134, 160, 122, 138, 253, 164, 215, 180, 73, 91, 124, 56, 17, 74, 50, 6, 11, 63, 244, 19, 249, 71, 173, 103, 146, 182, 248, 112, 34, 148, 100, 12, 22, 126, 231, 38, 241, 142, 89, 206, 35, 107, 239, 224, 68, 39, 200, 24, 44, 252, 205, 76, 225, 27, 178, 155, 70, 214, 221, 191, 136, 78, 143, 48, 88, 247, 153, 152, 193, 54, 99, 53, 140, 171, 185, 125, 15, 156, 29, 96, 176, 237, 49, 47, 129, 108, 198, 106, 23, 85, 113, 250, 30, 55, 58, 192, 95, 217, 98, 94, 1], +[1, 217, 58, 250, 23, 108, 49, 96, 15, 171, 99, 152, 88, 78, 221, 155, 225, 252, 200, 224, 35, 142, 231, 12, 34, 182, 173, 19, 11, 74, 124, 180, 253, 160, 25, 28, 165, 82, 61, 130, 197, 87, 118, 163, 162, 202, 144, 151, 128, 20, 228, 132, 117, 203, 104, 209, 121, 43, 79, 181, 213, 218, 18, 51, 16, 131, 157, 145, 111, 186, 13, 251, 240, 166, 42, 119, 123, 220, 195, 167, 2, 177, 116, 243, 46, 216, 98, 192, 30, 85, 198, 47, 176, 156, 185, 53, 193, 247, 143, 191, 70, 27, 205, 24, 68, 107, 89, 38, 22, 148, 248, 103, 249, 63, 50, 56, 73, 164, 122, 3, 137, 174, 236, 69, 67, 147, 31, 45, 256, 40, 199, 7, 234, 149, 208, 161, 242, 86, 158, 105, 169, 179, 36, 102, 32, 5, 57, 33, 222, 115, 26, 245, 223, 75, 84, 238, 246, 183, 133, 77, 4, 97, 232, 229, 92, 175, 196, 127, 60, 170, 139, 94, 95, 55, 113, 106, 129, 237, 29, 125, 140, 54, 153, 48, 136, 214, 178, 76, 44, 39, 239, 206, 241, 126, 100, 112, 146, 71, 244, 6, 17, 91, 215, 138, 134, 37, 62, 90, 255, 80, 141, 14, 211, 41, 159, 65, 227, 172, 59, 210, 81, 101, 72, 204, 64, 10, 114, 66, 187, 230, 52, 233, 189, 150, 168, 219, 235, 109, 9, 154, 8, 194, 207, 201, 184, 93, 135, 254, 120, 83, 21, 188, 190, 110, 226, 212, 1], +[1, 218, 236, 48, 184, 20, 248, 94, 189, 82, 143, 77, 81, 182, 98, 33, 255, 78, 42, 161, 146, 217, 18, 69, 136, 93, 228, 103, 95, 150, 61, 191, 4, 101, 173, 192, 222, 80, 221, 119, 242, 71, 58, 51, 67, 214, 135, 132, 249, 55, 168, 130, 70, 97, 72, 19, 30, 115, 141, 155, 123, 86, 244, 250, 16, 147, 178, 254, 117, 63, 113, 219, 197, 27, 232, 204, 11, 85, 26, 14, 225, 220, 158, 6, 23, 131, 31, 76, 120, 203, 50, 106, 235, 87, 205, 229, 64, 74, 198, 245, 211, 252, 195, 105, 17, 108, 157, 45, 44, 83, 104, 56, 129, 109, 118, 24, 92, 10, 124, 47, 223, 41, 200, 167, 169, 91, 49, 145, 256, 39, 21, 209, 73, 237, 9, 163, 68, 175, 114, 180, 176, 75, 159, 224, 2, 179, 215, 96, 111, 40, 239, 188, 121, 164, 29, 154, 162, 107, 196, 66, 253, 156, 84, 65, 35, 177, 36, 138, 15, 186, 199, 206, 190, 43, 122, 125, 8, 202, 89, 127, 187, 160, 185, 238, 227, 142, 116, 102, 134, 171, 13, 7, 241, 110, 79, 3, 140, 194, 144, 38, 60, 230, 25, 53, 246, 172, 231, 243, 32, 37, 99, 251, 234, 126, 226, 181, 137, 54, 207, 151, 22, 170, 52, 28, 193, 183, 59, 12, 46, 5, 62, 152, 240, 149, 100, 212, 213, 174, 153, 201, 128, 148, 139, 233, 165, 247, 133, 210, 34, 216, 57, 90, 88, 166, 208, 112, 1], +[1, 219, 159, 126, 95, 245, 199, 148, 30, 145, 144, 182, 23, 154, 59, 71, 129, 238, 208, 63, 176, 251, 228, 74, 15, 201, 72, 91, 140, 77, 158, 164, 193, 119, 104, 160, 88, 254, 114, 37, 136, 229, 36, 174, 70, 167, 79, 82, 225, 188, 52, 80, 44, 127, 57, 147, 68, 243, 18, 87, 35, 212, 168, 41, 241, 94, 26, 40, 22, 192, 157, 202, 34, 250, 9, 172, 146, 106, 84, 149, 249, 47, 13, 20, 11, 96, 207, 101, 17, 125, 133, 86, 73, 53, 42, 203, 253, 152, 135, 10, 134, 48, 232, 179, 137, 191, 195, 43, 165, 155, 21, 230, 255, 76, 196, 5, 67, 24, 116, 218, 197, 224, 226, 150, 211, 206, 139, 115, 256, 38, 98, 131, 162, 12, 58, 109, 227, 112, 113, 75, 234, 103, 198, 186, 128, 19, 49, 194, 81, 6, 29, 183, 242, 56, 185, 166, 117, 180, 99, 93, 64, 138, 153, 97, 169, 3, 143, 220, 121, 28, 221, 83, 187, 90, 178, 175, 32, 69, 205, 177, 213, 130, 200, 110, 189, 14, 239, 170, 222, 45, 89, 216, 16, 163, 231, 217, 235, 65, 100, 55, 223, 7, 248, 85, 111, 151, 173, 108, 8, 210, 244, 237, 246, 161, 50, 156, 240, 132, 124, 171, 184, 204, 215, 54, 4, 105, 122, 247, 123, 209, 25, 78, 120, 66, 62, 214, 92, 102, 236, 27, 2, 181, 61, 252, 190, 233, 141, 39, 60, 33, 31, 107, 46, 51, 118, 142, 1], +[1, 220, 84, 233, 117, 40, 62, 19, 68, 54, 58, 167, 246, 150, 104, 7, 255, 74, 89, 48, 23, 177, 133, 219, 121, 149, 141, 180, 22, 214, 49, 243, 4, 109, 79, 161, 211, 160, 248, 76, 15, 216, 232, 154, 213, 86, 159, 28, 249, 39, 99, 192, 92, 194, 18, 105, 227, 82, 50, 206, 88, 85, 196, 201, 16, 179, 59, 130, 73, 126, 221, 47, 60, 93, 157, 102, 81, 87, 122, 112, 225, 156, 139, 254, 111, 5, 72, 163, 137, 71, 200, 53, 95, 83, 13, 33, 64, 202, 236, 6, 35, 247, 113, 188, 240, 115, 114, 151, 67, 91, 231, 191, 129, 110, 42, 245, 187, 20, 31, 138, 34, 27, 29, 212, 123, 75, 52, 132, 256, 37, 173, 24, 140, 217, 195, 238, 189, 203, 199, 90, 11, 107, 153, 250, 2, 183, 168, 209, 234, 80, 124, 38, 136, 108, 116, 77, 235, 43, 208, 14, 253, 148, 178, 96, 46, 97, 9, 181, 242, 41, 25, 103, 44, 171, 98, 229, 8, 218, 158, 65, 165, 63, 239, 152, 30, 175, 207, 51, 169, 172, 61, 56, 241, 78, 198, 127, 184, 131, 36, 210, 197, 164, 100, 155, 176, 170, 135, 145, 32, 101, 118, 3, 146, 252, 185, 94, 120, 186, 57, 204, 162, 174, 244, 224, 193, 55, 21, 251, 222, 10, 144, 69, 17, 142, 143, 106, 190, 166, 26, 66, 128, 147, 215, 12, 70, 237, 226, 119, 223, 230, 228, 45, 134, 182, 205, 125, 1], +[1, 221, 11, 118, 121, 13, 46, 143, 249, 31, 169, 84, 60, 153, 146, 141, 64, 9, 190, 99, 34, 61, 117, 157, 2, 185, 22, 236, 242, 26, 92, 29, 241, 62, 81, 168, 120, 49, 35, 25, 128, 18, 123, 198, 68, 122, 234, 57, 4, 113, 44, 215, 227, 52, 184, 58, 225, 124, 162, 79, 240, 98, 70, 50, 256, 36, 246, 139, 136, 244, 211, 114, 8, 226, 88, 173, 197, 104, 111, 116, 193, 248, 67, 158, 223, 196, 140, 100, 255, 72, 235, 21, 15, 231, 165, 228, 16, 195, 176, 89, 137, 208, 222, 232, 129, 239, 134, 59, 189, 135, 23, 200, 253, 144, 213, 42, 30, 205, 73, 199, 32, 133, 95, 178, 17, 159, 187, 207, 1, 221, 11, 118, 121, 13, 46, 143, 249, 31, 169, 84, 60, 153, 146, 141, 64, 9, 190, 99, 34, 61, 117, 157, 2, 185, 22, 236, 242, 26, 92, 29, 241, 62, 81, 168, 120, 49, 35, 25, 128, 18, 123, 198, 68, 122, 234, 57, 4, 113, 44, 215, 227, 52, 184, 58, 225, 124, 162, 79, 240, 98, 70, 50, 256, 36, 246, 139, 136, 244, 211, 114, 8, 226, 88, 173, 197, 104, 111, 116, 193, 248, 67, 158, 223, 196, 140, 100, 255, 72, 235, 21, 15, 231, 165, 228, 16, 195, 176, 89, 137, 208, 222, 232, 129, 239, 134, 59, 189, 135, 23, 200, 253, 144, 213, 42, 30, 205, 73, 199, 32, 133, 95, 178, 17, 159, 187, 207, 1], +[1, 222, 197, 44, 2, 187, 137, 88, 4, 117, 17, 176, 8, 234, 34, 95, 16, 211, 68, 190, 32, 165, 136, 123, 64, 73, 15, 246, 128, 146, 30, 235, 256, 35, 60, 213, 255, 70, 120, 169, 253, 140, 240, 81, 249, 23, 223, 162, 241, 46, 189, 67, 225, 92, 121, 134, 193, 184, 242, 11, 129, 111, 227, 22, 1, 222, 197, 44, 2, 187, 137, 88, 4, 117, 17, 176, 8, 234, 34, 95, 16, 211, 68, 190, 32, 165, 136, 123, 64, 73, 15, 246, 128, 146, 30, 235, 256, 35, 60, 213, 255, 70, 120, 169, 253, 140, 240, 81, 249, 23, 223, 162, 241, 46, 189, 67, 225, 92, 121, 134, 193, 184, 242, 11, 129, 111, 227, 22, 1, 222, 197, 44, 2, 187, 137, 88, 4, 117, 17, 176, 8, 234, 34, 95, 16, 211, 68, 190, 32, 165, 136, 123, 64, 73, 15, 246, 128, 146, 30, 235, 256, 35, 60, 213, 255, 70, 120, 169, 253, 140, 240, 81, 249, 23, 223, 162, 241, 46, 189, 67, 225, 92, 121, 134, 193, 184, 242, 11, 129, 111, 227, 22, 1, 222, 197, 44, 2, 187, 137, 88, 4, 117, 17, 176, 8, 234, 34, 95, 16, 211, 68, 190, 32, 165, 136, 123, 64, 73, 15, 246, 128, 146, 30, 235, 256, 35, 60, 213, 255, 70, 120, 169, 253, 140, 240, 81, 249, 23, 223, 162, 241, 46, 189, 67, 225, 92, 121, 134, 193, 184, 242, 11, 129, 111, 227, 22, 1], +[1, 223, 128, 17, 193, 120, 32, 197, 241, 30, 8, 242, 253, 136, 2, 189, 256, 34, 129, 240, 64, 137, 225, 60, 16, 227, 249, 15, 4, 121, 255, 68, 1, 223, 128, 17, 193, 120, 32, 197, 241, 30, 8, 242, 253, 136, 2, 189, 256, 34, 129, 240, 64, 137, 225, 60, 16, 227, 249, 15, 4, 121, 255, 68, 1, 223, 128, 17, 193, 120, 32, 197, 241, 30, 8, 242, 253, 136, 2, 189, 256, 34, 129, 240, 64, 137, 225, 60, 16, 227, 249, 15, 4, 121, 255, 68, 1, 223, 128, 17, 193, 120, 32, 197, 241, 30, 8, 242, 253, 136, 2, 189, 256, 34, 129, 240, 64, 137, 225, 60, 16, 227, 249, 15, 4, 121, 255, 68, 1, 223, 128, 17, 193, 120, 32, 197, 241, 30, 8, 242, 253, 136, 2, 189, 256, 34, 129, 240, 64, 137, 225, 60, 16, 227, 249, 15, 4, 121, 255, 68, 1, 223, 128, 17, 193, 120, 32, 197, 241, 30, 8, 242, 253, 136, 2, 189, 256, 34, 129, 240, 64, 137, 225, 60, 16, 227, 249, 15, 4, 121, 255, 68, 1, 223, 128, 17, 193, 120, 32, 197, 241, 30, 8, 242, 253, 136, 2, 189, 256, 34, 129, 240, 64, 137, 225, 60, 16, 227, 249, 15, 4, 121, 255, 68, 1, 223, 128, 17, 193, 120, 32, 197, 241, 30, 8, 242, 253, 136, 2, 189, 256, 34, 129, 240, 64, 137, 225, 60, 16, 227, 249, 15, 4, 121, 255, 68, 1], +[1, 224, 61, 43, 123, 53, 50, 149, 223, 94, 239, 80, 187, 254, 99, 74, 128, 145, 98, 107, 67, 102, 232, 54, 17, 210, 9, 217, 35, 130, 79, 220, 193, 56, 208, 75, 95, 206, 141, 230, 120, 152, 124, 20, 111, 192, 89, 147, 32, 229, 153, 91, 81, 154, 58, 142, 197, 181, 195, 247, 73, 161, 84, 55, 241, 14, 52, 83, 88, 180, 228, 186, 30, 38, 31, 5, 92, 48, 215, 101, 8, 250, 231, 87, 213, 167, 143, 164, 242, 238, 113, 126, 211, 233, 21, 78, 253, 132, 13, 85, 22, 45, 57, 175, 136, 138, 72, 194, 23, 12, 118, 218, 2, 191, 122, 86, 246, 106, 100, 41, 189, 188, 221, 160, 117, 251, 198, 148, 256, 33, 196, 214, 134, 204, 207, 108, 34, 163, 18, 177, 70, 3, 158, 183, 129, 112, 159, 150, 190, 155, 25, 203, 240, 47, 248, 40, 222, 127, 178, 37, 64, 201, 49, 182, 162, 51, 116, 27, 137, 105, 133, 237, 146, 65, 168, 110, 225, 28, 104, 166, 176, 103, 199, 115, 60, 76, 62, 10, 184, 96, 173, 202, 16, 243, 205, 174, 169, 77, 29, 71, 227, 219, 226, 252, 165, 209, 42, 156, 249, 7, 26, 170, 44, 90, 114, 93, 15, 19, 144, 131, 46, 24, 236, 179, 4, 125, 244, 172, 235, 212, 200, 82, 121, 119, 185, 63, 234, 245, 139, 39, 255, 66, 135, 171, 11, 151, 157, 216, 68, 69, 36, 97, 140, 6, 59, 109, 1], +[1, 225, 253, 128, 16, 2, 193, 249, 256, 32, 4, 129, 241, 255, 64, 8, 1, 225, 253, 128, 16, 2, 193, 249, 256, 32, 4, 129, 241, 255, 64, 8, 1, 225, 253, 128, 16, 2, 193, 249, 256, 32, 4, 129, 241, 255, 64, 8, 1, 225, 253, 128, 16, 2, 193, 249, 256, 32, 4, 129, 241, 255, 64, 8, 1, 225, 253, 128, 16, 2, 193, 249, 256, 32, 4, 129, 241, 255, 64, 8, 1, 225, 253, 128, 16, 2, 193, 249, 256, 32, 4, 129, 241, 255, 64, 8, 1, 225, 253, 128, 16, 2, 193, 249, 256, 32, 4, 129, 241, 255, 64, 8, 1, 225, 253, 128, 16, 2, 193, 249, 256, 32, 4, 129, 241, 255, 64, 8, 1, 225, 253, 128, 16, 2, 193, 249, 256, 32, 4, 129, 241, 255, 64, 8, 1, 225, 253, 128, 16, 2, 193, 249, 256, 32, 4, 129, 241, 255, 64, 8, 1, 225, 253, 128, 16, 2, 193, 249, 256, 32, 4, 129, 241, 255, 64, 8, 1, 225, 253, 128, 16, 2, 193, 249, 256, 32, 4, 129, 241, 255, 64, 8, 1, 225, 253, 128, 16, 2, 193, 249, 256, 32, 4, 129, 241, 255, 64, 8, 1, 225, 253, 128, 16, 2, 193, 249, 256, 32, 4, 129, 241, 255, 64, 8, 1, 225, 253, 128, 16, 2, 193, 249, 256, 32, 4, 129, 241, 255, 64, 8, 1, 225, 253, 128, 16, 2, 193, 249, 256, 32, 4, 129, 241, 255, 64, 8, 1], +[1, 226, 190, 21, 120, 135, 184, 207, 8, 9, 235, 168, 189, 52, 187, 114, 64, 72, 81, 59, 227, 159, 211, 141, 255, 62, 134, 215, 17, 244, 146, 100, 241, 239, 44, 178, 136, 153, 140, 29, 129, 113, 95, 139, 60, 196, 92, 232, 4, 133, 246, 84, 223, 26, 222, 57, 32, 36, 169, 158, 242, 208, 234, 199, 256, 31, 67, 236, 137, 122, 73, 50, 249, 248, 22, 89, 68, 205, 70, 143, 193, 185, 176, 198, 30, 98, 46, 116, 2, 195, 123, 42, 240, 13, 111, 157, 16, 18, 213, 79, 121, 104, 117, 228, 128, 144, 162, 118, 197, 61, 165, 25, 253, 124, 11, 173, 34, 231, 35, 200, 225, 221, 88, 99, 15, 49, 23, 58, 1, 226, 190, 21, 120, 135, 184, 207, 8, 9, 235, 168, 189, 52, 187, 114, 64, 72, 81, 59, 227, 159, 211, 141, 255, 62, 134, 215, 17, 244, 146, 100, 241, 239, 44, 178, 136, 153, 140, 29, 129, 113, 95, 139, 60, 196, 92, 232, 4, 133, 246, 84, 223, 26, 222, 57, 32, 36, 169, 158, 242, 208, 234, 199, 256, 31, 67, 236, 137, 122, 73, 50, 249, 248, 22, 89, 68, 205, 70, 143, 193, 185, 176, 198, 30, 98, 46, 116, 2, 195, 123, 42, 240, 13, 111, 157, 16, 18, 213, 79, 121, 104, 117, 228, 128, 144, 162, 118, 197, 61, 165, 25, 253, 124, 11, 173, 34, 231, 35, 200, 225, 221, 88, 99, 15, 49, 23, 58, 1], +[1, 227, 129, 242, 193, 121, 225, 189, 241, 223, 249, 240, 253, 120, 255, 60, 256, 30, 128, 15, 64, 136, 32, 68, 16, 34, 8, 17, 4, 137, 2, 197, 1, 227, 129, 242, 193, 121, 225, 189, 241, 223, 249, 240, 253, 120, 255, 60, 256, 30, 128, 15, 64, 136, 32, 68, 16, 34, 8, 17, 4, 137, 2, 197, 1, 227, 129, 242, 193, 121, 225, 189, 241, 223, 249, 240, 253, 120, 255, 60, 256, 30, 128, 15, 64, 136, 32, 68, 16, 34, 8, 17, 4, 137, 2, 197, 1, 227, 129, 242, 193, 121, 225, 189, 241, 223, 249, 240, 253, 120, 255, 60, 256, 30, 128, 15, 64, 136, 32, 68, 16, 34, 8, 17, 4, 137, 2, 197, 1, 227, 129, 242, 193, 121, 225, 189, 241, 223, 249, 240, 253, 120, 255, 60, 256, 30, 128, 15, 64, 136, 32, 68, 16, 34, 8, 17, 4, 137, 2, 197, 1, 227, 129, 242, 193, 121, 225, 189, 241, 223, 249, 240, 253, 120, 255, 60, 256, 30, 128, 15, 64, 136, 32, 68, 16, 34, 8, 17, 4, 137, 2, 197, 1, 227, 129, 242, 193, 121, 225, 189, 241, 223, 249, 240, 253, 120, 255, 60, 256, 30, 128, 15, 64, 136, 32, 68, 16, 34, 8, 17, 4, 137, 2, 197, 1, 227, 129, 242, 193, 121, 225, 189, 241, 223, 249, 240, 253, 120, 255, 60, 256, 30, 128, 15, 64, 136, 32, 68, 16, 34, 8, 17, 4, 137, 2, 197, 1], +[1, 228, 70, 26, 17, 21, 162, 185, 32, 100, 184, 61, 30, 158, 44, 9, 253, 116, 234, 153, 189, 173, 123, 31, 129, 114, 35, 13, 137, 139, 81, 221, 16, 50, 92, 159, 15, 79, 22, 133, 255, 58, 117, 205, 223, 215, 190, 144, 193, 57, 146, 135, 197, 198, 169, 239, 8, 25, 46, 208, 136, 168, 11, 195, 256, 29, 187, 231, 240, 236, 95, 72, 225, 157, 73, 196, 227, 99, 213, 248, 4, 141, 23, 104, 68, 84, 134, 226, 128, 143, 222, 244, 120, 118, 176, 36, 241, 207, 165, 98, 242, 178, 235, 124, 2, 199, 140, 52, 34, 42, 67, 113, 64, 200, 111, 122, 60, 59, 88, 18, 249, 232, 211, 49, 121, 89, 246, 62, 1, 228, 70, 26, 17, 21, 162, 185, 32, 100, 184, 61, 30, 158, 44, 9, 253, 116, 234, 153, 189, 173, 123, 31, 129, 114, 35, 13, 137, 139, 81, 221, 16, 50, 92, 159, 15, 79, 22, 133, 255, 58, 117, 205, 223, 215, 190, 144, 193, 57, 146, 135, 197, 198, 169, 239, 8, 25, 46, 208, 136, 168, 11, 195, 256, 29, 187, 231, 240, 236, 95, 72, 225, 157, 73, 196, 227, 99, 213, 248, 4, 141, 23, 104, 68, 84, 134, 226, 128, 143, 222, 244, 120, 118, 176, 36, 241, 207, 165, 98, 242, 178, 235, 124, 2, 199, 140, 52, 34, 42, 67, 113, 64, 200, 111, 122, 60, 59, 88, 18, 249, 232, 211, 49, 121, 89, 246, 62, 1], +[1, 229, 13, 150, 169, 151, 141, 164, 34, 76, 185, 217, 92, 251, 168, 179, 128, 14, 122, 182, 44, 53, 58, 175, 240, 219, 36, 20, 211, 3, 173, 39, 193, 250, 196, 166, 235, 102, 228, 41, 137, 19, 239, 247, 23, 127, 42, 109, 32, 132, 159, 174, 11, 206, 143, 108, 60, 119, 9, 5, 117, 65, 236, 74, 241, 191, 49, 170, 123, 154, 57, 203, 227, 69, 124, 126, 70, 96, 139, 220, 8, 33, 104, 172, 67, 180, 100, 27, 15, 94, 195, 194, 222, 209, 59, 147, 253, 112, 205, 171, 95, 167, 207, 115, 121, 210, 31, 160, 146, 24, 99, 55, 2, 201, 26, 43, 81, 45, 25, 71, 68, 152, 113, 177, 184, 245, 79, 101, 256, 28, 244, 107, 88, 106, 116, 93, 223, 181, 72, 40, 165, 6, 89, 78, 129, 243, 135, 75, 213, 204, 199, 82, 17, 38, 221, 237, 46, 254, 84, 218, 64, 7, 61, 91, 22, 155, 29, 216, 120, 238, 18, 10, 234, 130, 215, 148, 225, 125, 98, 83, 246, 51, 114, 149, 197, 138, 248, 252, 140, 192, 21, 183, 16, 66, 208, 87, 134, 103, 200, 54, 30, 188, 133, 131, 187, 161, 118, 37, 249, 224, 153, 85, 190, 77, 157, 230, 242, 163, 62, 63, 35, 48, 198, 110, 4, 145, 52, 86, 162, 90, 50, 142, 136, 47, 226, 97, 111, 233, 158, 202, 255, 56, 231, 214, 176, 212, 232, 186, 189, 105, 144, 80, 73, 12, 178, 156, 1], +[1, 230, 215, 106, 222, 174, 185, 145, 197, 78, 207, 65, 44, 97, 208, 38, 2, 203, 173, 212, 187, 91, 113, 33, 137, 156, 157, 130, 88, 194, 159, 76, 4, 149, 89, 167, 117, 182, 226, 66, 17, 55, 57, 3, 176, 131, 61, 152, 8, 41, 178, 77, 234, 107, 195, 132, 34, 110, 114, 6, 95, 5, 122, 47, 16, 82, 99, 154, 211, 214, 133, 7, 68, 220, 228, 12, 190, 10, 244, 94, 32, 164, 198, 51, 165, 171, 9, 14, 136, 183, 199, 24, 123, 20, 231, 188, 64, 71, 139, 102, 73, 85, 18, 28, 15, 109, 141, 48, 246, 40, 205, 119, 128, 142, 21, 204, 146, 170, 36, 56, 30, 218, 25, 96, 235, 80, 153, 238, 256, 27, 42, 151, 35, 83, 72, 112, 60, 179, 50, 192, 213, 160, 49, 219, 255, 54, 84, 45, 70, 166, 144, 224, 120, 101, 100, 127, 169, 63, 98, 181, 253, 108, 168, 90, 140, 75, 31, 191, 240, 202, 200, 254, 81, 126, 196, 105, 249, 216, 79, 180, 23, 150, 62, 125, 223, 147, 143, 251, 162, 252, 135, 210, 241, 175, 158, 103, 46, 43, 124, 250, 189, 37, 29, 245, 67, 247, 13, 163, 225, 93, 59, 206, 92, 86, 248, 243, 121, 74, 58, 233, 134, 237, 26, 69, 193, 186, 118, 155, 184, 172, 239, 229, 242, 148, 116, 209, 11, 217, 52, 138, 129, 115, 236, 53, 111, 87, 221, 201, 227, 39, 232, 161, 22, 177, 104, 19, 1], +[1, 231, 162, 157, 30, 248, 234, 84, 129, 244, 81, 207, 15, 124, 117, 42, 193, 122, 169, 232, 136, 62, 187, 21, 225, 61, 213, 116, 68, 31, 222, 139, 241, 159, 235, 58, 34, 144, 111, 198, 249, 208, 246, 29, 17, 72, 184, 99, 253, 104, 123, 143, 137, 36, 92, 178, 255, 52, 190, 200, 197, 18, 46, 89, 256, 26, 95, 100, 227, 9, 23, 173, 128, 13, 176, 50, 242, 133, 140, 215, 64, 135, 88, 25, 121, 195, 70, 236, 32, 196, 44, 141, 189, 226, 35, 118, 16, 98, 22, 199, 223, 113, 146, 59, 8, 49, 11, 228, 240, 185, 73, 158, 4, 153, 134, 114, 120, 221, 165, 79, 2, 205, 67, 57, 60, 239, 211, 168, 1, 231, 162, 157, 30, 248, 234, 84, 129, 244, 81, 207, 15, 124, 117, 42, 193, 122, 169, 232, 136, 62, 187, 21, 225, 61, 213, 116, 68, 31, 222, 139, 241, 159, 235, 58, 34, 144, 111, 198, 249, 208, 246, 29, 17, 72, 184, 99, 253, 104, 123, 143, 137, 36, 92, 178, 255, 52, 190, 200, 197, 18, 46, 89, 256, 26, 95, 100, 227, 9, 23, 173, 128, 13, 176, 50, 242, 133, 140, 215, 64, 135, 88, 25, 121, 195, 70, 236, 32, 196, 44, 141, 189, 226, 35, 118, 16, 98, 22, 199, 223, 113, 146, 59, 8, 49, 11, 228, 240, 185, 73, 158, 4, 153, 134, 114, 120, 221, 165, 79, 2, 205, 67, 57, 60, 239, 211, 168, 1], +[1, 232, 111, 52, 242, 118, 134, 248, 225, 29, 46, 135, 223, 79, 81, 31, 253, 100, 70, 49, 60, 42, 235, 36, 128, 141, 73, 231, 136, 198, 190, 133, 16, 114, 234, 61, 17, 89, 88, 113, 2, 207, 222, 104, 227, 236, 11, 239, 193, 58, 92, 13, 189, 158, 162, 62, 249, 200, 140, 98, 120, 84, 213, 72, 256, 25, 146, 205, 15, 139, 123, 9, 32, 228, 211, 122, 34, 178, 176, 226, 4, 157, 187, 208, 197, 215, 22, 221, 129, 116, 184, 26, 121, 59, 67, 124, 241, 143, 23, 196, 240, 168, 169, 144, 255, 50, 35, 153, 30, 21, 246, 18, 64, 199, 165, 244, 68, 99, 95, 195, 8, 57, 117, 159, 137, 173, 44, 185, 1, 232, 111, 52, 242, 118, 134, 248, 225, 29, 46, 135, 223, 79, 81, 31, 253, 100, 70, 49, 60, 42, 235, 36, 128, 141, 73, 231, 136, 198, 190, 133, 16, 114, 234, 61, 17, 89, 88, 113, 2, 207, 222, 104, 227, 236, 11, 239, 193, 58, 92, 13, 189, 158, 162, 62, 249, 200, 140, 98, 120, 84, 213, 72, 256, 25, 146, 205, 15, 139, 123, 9, 32, 228, 211, 122, 34, 178, 176, 226, 4, 157, 187, 208, 197, 215, 22, 221, 129, 116, 184, 26, 121, 59, 67, 124, 241, 143, 23, 196, 240, 168, 169, 144, 255, 50, 35, 153, 30, 21, 246, 18, 64, 199, 165, 244, 68, 99, 95, 195, 8, 57, 117, 159, 137, 173, 44, 185, 1], +[1, 233, 62, 54, 246, 7, 89, 177, 121, 180, 49, 109, 211, 76, 232, 86, 249, 192, 18, 82, 88, 201, 59, 126, 60, 102, 122, 156, 111, 163, 200, 83, 64, 6, 113, 115, 67, 191, 42, 20, 34, 212, 52, 37, 140, 238, 199, 107, 2, 209, 124, 108, 235, 14, 178, 97, 242, 103, 98, 218, 165, 152, 207, 172, 241, 127, 36, 164, 176, 145, 118, 252, 120, 204, 244, 55, 222, 69, 143, 166, 128, 12, 226, 230, 134, 125, 84, 40, 68, 167, 104, 74, 23, 219, 141, 214, 4, 161, 248, 216, 213, 28, 99, 194, 227, 206, 196, 179, 73, 47, 157, 87, 225, 254, 72, 71, 95, 33, 236, 247, 240, 151, 231, 110, 187, 138, 29, 75, 256, 24, 195, 203, 11, 250, 168, 80, 136, 77, 208, 148, 46, 181, 25, 171, 8, 65, 239, 175, 169, 56, 198, 131, 197, 155, 135, 101, 146, 94, 57, 174, 193, 251, 144, 142, 190, 66, 215, 237, 223, 45, 205, 220, 117, 19, 58, 150, 255, 48, 133, 149, 22, 243, 79, 160, 15, 154, 159, 39, 92, 105, 50, 85, 16, 130, 221, 93, 81, 112, 139, 5, 137, 53, 13, 202, 35, 188, 114, 91, 129, 245, 31, 27, 123, 132, 173, 217, 189, 90, 153, 183, 234, 38, 116, 43, 253, 96, 9, 41, 44, 229, 158, 63, 30, 51, 61, 78, 184, 210, 100, 170, 32, 3, 185, 186, 162, 224, 21, 10, 17, 106, 26, 147, 70, 119, 228, 182, 1], +[1, 234, 15, 169, 225, 222, 34, 246, 253, 92, 197, 95, 128, 140, 121, 44, 16, 146, 240, 134, 2, 211, 30, 81, 193, 187, 68, 235, 249, 184, 137, 190, 256, 23, 242, 88, 32, 35, 223, 11, 4, 165, 60, 162, 129, 117, 136, 213, 241, 111, 17, 123, 255, 46, 227, 176, 64, 70, 189, 22, 8, 73, 120, 67, 1, 234, 15, 169, 225, 222, 34, 246, 253, 92, 197, 95, 128, 140, 121, 44, 16, 146, 240, 134, 2, 211, 30, 81, 193, 187, 68, 235, 249, 184, 137, 190, 256, 23, 242, 88, 32, 35, 223, 11, 4, 165, 60, 162, 129, 117, 136, 213, 241, 111, 17, 123, 255, 46, 227, 176, 64, 70, 189, 22, 8, 73, 120, 67, 1, 234, 15, 169, 225, 222, 34, 246, 253, 92, 197, 95, 128, 140, 121, 44, 16, 146, 240, 134, 2, 211, 30, 81, 193, 187, 68, 235, 249, 184, 137, 190, 256, 23, 242, 88, 32, 35, 223, 11, 4, 165, 60, 162, 129, 117, 136, 213, 241, 111, 17, 123, 255, 46, 227, 176, 64, 70, 189, 22, 8, 73, 120, 67, 1, 234, 15, 169, 225, 222, 34, 246, 253, 92, 197, 95, 128, 140, 121, 44, 16, 146, 240, 134, 2, 211, 30, 81, 193, 187, 68, 235, 249, 184, 137, 190, 256, 23, 242, 88, 32, 35, 223, 11, 4, 165, 60, 162, 129, 117, 136, 213, 241, 111, 17, 123, 255, 46, 227, 176, 64, 70, 189, 22, 8, 73, 120, 67, 1], +[1, 235, 227, 146, 129, 246, 242, 73, 193, 123, 121, 165, 225, 190, 189, 211, 241, 95, 223, 234, 249, 176, 240, 117, 253, 88, 120, 187, 255, 44, 60, 222, 256, 22, 30, 111, 128, 11, 15, 184, 64, 134, 136, 92, 32, 67, 68, 46, 16, 162, 34, 23, 8, 81, 17, 140, 4, 169, 137, 70, 2, 213, 197, 35, 1, 235, 227, 146, 129, 246, 242, 73, 193, 123, 121, 165, 225, 190, 189, 211, 241, 95, 223, 234, 249, 176, 240, 117, 253, 88, 120, 187, 255, 44, 60, 222, 256, 22, 30, 111, 128, 11, 15, 184, 64, 134, 136, 92, 32, 67, 68, 46, 16, 162, 34, 23, 8, 81, 17, 140, 4, 169, 137, 70, 2, 213, 197, 35, 1, 235, 227, 146, 129, 246, 242, 73, 193, 123, 121, 165, 225, 190, 189, 211, 241, 95, 223, 234, 249, 176, 240, 117, 253, 88, 120, 187, 255, 44, 60, 222, 256, 22, 30, 111, 128, 11, 15, 184, 64, 134, 136, 92, 32, 67, 68, 46, 16, 162, 34, 23, 8, 81, 17, 140, 4, 169, 137, 70, 2, 213, 197, 35, 1, 235, 227, 146, 129, 246, 242, 73, 193, 123, 121, 165, 225, 190, 189, 211, 241, 95, 223, 234, 249, 176, 240, 117, 253, 88, 120, 187, 255, 44, 60, 222, 256, 22, 30, 111, 128, 11, 15, 184, 64, 134, 136, 92, 32, 67, 68, 46, 16, 162, 34, 23, 8, 81, 17, 140, 4, 169, 137, 70, 2, 213, 197, 35, 1], +[1, 236, 184, 248, 189, 143, 81, 98, 255, 42, 146, 18, 136, 228, 95, 61, 4, 173, 222, 221, 242, 58, 67, 135, 249, 168, 70, 72, 30, 141, 123, 244, 16, 178, 117, 113, 197, 232, 11, 26, 225, 158, 23, 31, 120, 50, 235, 205, 64, 198, 211, 195, 17, 157, 44, 104, 129, 118, 92, 124, 223, 200, 169, 49, 256, 21, 73, 9, 68, 114, 176, 159, 2, 215, 111, 239, 121, 29, 162, 196, 253, 84, 35, 36, 15, 199, 190, 122, 8, 89, 187, 185, 227, 116, 134, 13, 241, 79, 140, 144, 60, 25, 246, 231, 32, 99, 234, 226, 137, 207, 22, 52, 193, 59, 46, 62, 240, 100, 213, 153, 128, 139, 165, 133, 34, 57, 88, 208, 1, 236, 184, 248, 189, 143, 81, 98, 255, 42, 146, 18, 136, 228, 95, 61, 4, 173, 222, 221, 242, 58, 67, 135, 249, 168, 70, 72, 30, 141, 123, 244, 16, 178, 117, 113, 197, 232, 11, 26, 225, 158, 23, 31, 120, 50, 235, 205, 64, 198, 211, 195, 17, 157, 44, 104, 129, 118, 92, 124, 223, 200, 169, 49, 256, 21, 73, 9, 68, 114, 176, 159, 2, 215, 111, 239, 121, 29, 162, 196, 253, 84, 35, 36, 15, 199, 190, 122, 8, 89, 187, 185, 227, 116, 134, 13, 241, 79, 140, 144, 60, 25, 246, 231, 32, 99, 234, 226, 137, 207, 22, 52, 193, 59, 46, 62, 240, 100, 213, 153, 128, 139, 165, 133, 34, 57, 88, 208, 1], +[1, 237, 143, 224, 146, 164, 61, 65, 242, 43, 168, 238, 123, 110, 113, 53, 225, 126, 50, 28, 211, 149, 104, 233, 223, 166, 21, 94, 176, 78, 239, 103, 253, 80, 199, 132, 187, 115, 13, 254, 60, 85, 99, 76, 22, 74, 62, 45, 128, 10, 57, 145, 184, 175, 98, 96, 136, 107, 173, 138, 67, 202, 72, 102, 16, 194, 232, 243, 23, 54, 205, 12, 17, 174, 118, 210, 169, 218, 9, 77, 2, 217, 29, 191, 35, 71, 122, 130, 227, 86, 79, 219, 246, 220, 226, 106, 193, 252, 100, 56, 165, 41, 208, 209, 189, 75, 42, 188, 95, 156, 221, 206, 249, 160, 141, 7, 117, 230, 26, 251, 120, 170, 198, 152, 44, 148, 124, 90, 256, 20, 114, 33, 111, 93, 196, 192, 15, 214, 89, 19, 134, 147, 144, 204, 32, 131, 207, 229, 46, 108, 153, 24, 34, 91, 236, 163, 81, 179, 18, 154, 4, 177, 58, 125, 70, 142, 244, 3, 197, 172, 158, 181, 235, 183, 195, 212, 129, 247, 200, 112, 73, 82, 159, 161, 121, 150, 84, 119, 190, 55, 185, 155, 241, 63, 25, 14, 234, 203, 52, 245, 240, 83, 139, 47, 88, 39, 248, 180, 255, 40, 228, 66, 222, 186, 135, 127, 30, 171, 178, 38, 11, 37, 31, 151, 64, 5, 157, 201, 92, 216, 49, 48, 68, 182, 215, 69, 162, 101, 36, 51, 8, 97, 116, 250, 140, 27, 231, 6, 137, 87, 59, 105, 213, 109, 133, 167, 1], +[1, 238, 104, 80, 22, 96, 232, 218, 227, 56, 221, 170, 111, 204, 236, 142, 129, 119, 52, 40, 11, 48, 116, 109, 242, 28, 239, 85, 184, 102, 118, 71, 193, 188, 26, 20, 134, 24, 58, 183, 121, 14, 248, 171, 92, 51, 59, 164, 225, 94, 13, 10, 67, 12, 29, 220, 189, 7, 124, 214, 46, 154, 158, 82, 241, 47, 135, 5, 162, 6, 143, 110, 223, 132, 62, 107, 23, 77, 79, 41, 249, 152, 196, 131, 81, 3, 200, 55, 240, 66, 31, 182, 140, 167, 168, 149, 253, 76, 98, 194, 169, 130, 100, 156, 120, 33, 144, 91, 70, 212, 84, 203, 255, 38, 49, 97, 213, 65, 50, 78, 60, 145, 72, 174, 35, 106, 42, 230, 256, 19, 153, 177, 235, 161, 25, 39, 30, 201, 36, 87, 146, 53, 21, 115, 128, 138, 205, 217, 246, 209, 141, 148, 15, 229, 18, 172, 73, 155, 139, 186, 64, 69, 231, 237, 123, 233, 199, 74, 136, 243, 9, 86, 165, 206, 198, 93, 32, 163, 244, 247, 190, 245, 228, 37, 68, 250, 133, 43, 211, 103, 99, 175, 16, 210, 122, 252, 95, 251, 114, 147, 34, 125, 195, 150, 234, 180, 178, 216, 8, 105, 61, 126, 176, 254, 57, 202, 17, 191, 226, 75, 117, 90, 89, 108, 4, 181, 159, 63, 88, 127, 157, 101, 137, 224, 113, 166, 187, 45, 173, 54, 2, 219, 208, 160, 44, 192, 207, 179, 197, 112, 185, 83, 222, 151, 215, 27, 1], +[1, 239, 67, 79, 120, 153, 73, 228, 8, 113, 22, 118, 189, 196, 70, 25, 64, 133, 176, 173, 227, 26, 46, 200, 255, 36, 123, 99, 17, 208, 111, 58, 241, 31, 213, 21, 136, 122, 117, 207, 129, 248, 162, 168, 60, 205, 165, 114, 4, 185, 11, 59, 223, 98, 35, 141, 32, 195, 88, 215, 242, 13, 23, 100, 256, 18, 190, 178, 137, 104, 184, 29, 249, 144, 235, 139, 68, 61, 187, 232, 193, 124, 81, 84, 30, 231, 211, 57, 2, 221, 134, 158, 240, 49, 146, 199, 16, 226, 44, 236, 121, 135, 140, 50, 128, 9, 95, 89, 197, 52, 92, 143, 253, 72, 246, 198, 34, 159, 222, 116, 225, 62, 169, 42, 15, 244, 234, 157, 1, 239, 67, 79, 120, 153, 73, 228, 8, 113, 22, 118, 189, 196, 70, 25, 64, 133, 176, 173, 227, 26, 46, 200, 255, 36, 123, 99, 17, 208, 111, 58, 241, 31, 213, 21, 136, 122, 117, 207, 129, 248, 162, 168, 60, 205, 165, 114, 4, 185, 11, 59, 223, 98, 35, 141, 32, 195, 88, 215, 242, 13, 23, 100, 256, 18, 190, 178, 137, 104, 184, 29, 249, 144, 235, 139, 68, 61, 187, 232, 193, 124, 81, 84, 30, 231, 211, 57, 2, 221, 134, 158, 240, 49, 146, 199, 16, 226, 44, 236, 121, 135, 140, 50, 128, 9, 95, 89, 197, 52, 92, 143, 253, 72, 246, 198, 34, 159, 222, 116, 225, 62, 169, 42, 15, 244, 234, 157, 1], +[1, 240, 32, 227, 253, 68, 129, 120, 16, 242, 255, 34, 193, 60, 8, 121, 256, 17, 225, 30, 4, 189, 128, 137, 241, 15, 2, 223, 64, 197, 249, 136, 1, 240, 32, 227, 253, 68, 129, 120, 16, 242, 255, 34, 193, 60, 8, 121, 256, 17, 225, 30, 4, 189, 128, 137, 241, 15, 2, 223, 64, 197, 249, 136, 1, 240, 32, 227, 253, 68, 129, 120, 16, 242, 255, 34, 193, 60, 8, 121, 256, 17, 225, 30, 4, 189, 128, 137, 241, 15, 2, 223, 64, 197, 249, 136, 1, 240, 32, 227, 253, 68, 129, 120, 16, 242, 255, 34, 193, 60, 8, 121, 256, 17, 225, 30, 4, 189, 128, 137, 241, 15, 2, 223, 64, 197, 249, 136, 1, 240, 32, 227, 253, 68, 129, 120, 16, 242, 255, 34, 193, 60, 8, 121, 256, 17, 225, 30, 4, 189, 128, 137, 241, 15, 2, 223, 64, 197, 249, 136, 1, 240, 32, 227, 253, 68, 129, 120, 16, 242, 255, 34, 193, 60, 8, 121, 256, 17, 225, 30, 4, 189, 128, 137, 241, 15, 2, 223, 64, 197, 249, 136, 1, 240, 32, 227, 253, 68, 129, 120, 16, 242, 255, 34, 193, 60, 8, 121, 256, 17, 225, 30, 4, 189, 128, 137, 241, 15, 2, 223, 64, 197, 249, 136, 1, 240, 32, 227, 253, 68, 129, 120, 16, 242, 255, 34, 193, 60, 8, 121, 256, 17, 225, 30, 4, 189, 128, 137, 241, 15, 2, 223, 64, 197, 249, 136, 1], +[1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1, 241, 256, 16, 1], +[1, 242, 225, 223, 253, 60, 128, 136, 16, 17, 2, 227, 193, 189, 249, 120, 256, 15, 32, 34, 4, 197, 129, 121, 241, 240, 255, 30, 64, 68, 8, 137, 1, 242, 225, 223, 253, 60, 128, 136, 16, 17, 2, 227, 193, 189, 249, 120, 256, 15, 32, 34, 4, 197, 129, 121, 241, 240, 255, 30, 64, 68, 8, 137, 1, 242, 225, 223, 253, 60, 128, 136, 16, 17, 2, 227, 193, 189, 249, 120, 256, 15, 32, 34, 4, 197, 129, 121, 241, 240, 255, 30, 64, 68, 8, 137, 1, 242, 225, 223, 253, 60, 128, 136, 16, 17, 2, 227, 193, 189, 249, 120, 256, 15, 32, 34, 4, 197, 129, 121, 241, 240, 255, 30, 64, 68, 8, 137, 1, 242, 225, 223, 253, 60, 128, 136, 16, 17, 2, 227, 193, 189, 249, 120, 256, 15, 32, 34, 4, 197, 129, 121, 241, 240, 255, 30, 64, 68, 8, 137, 1, 242, 225, 223, 253, 60, 128, 136, 16, 17, 2, 227, 193, 189, 249, 120, 256, 15, 32, 34, 4, 197, 129, 121, 241, 240, 255, 30, 64, 68, 8, 137, 1, 242, 225, 223, 253, 60, 128, 136, 16, 17, 2, 227, 193, 189, 249, 120, 256, 15, 32, 34, 4, 197, 129, 121, 241, 240, 255, 30, 64, 68, 8, 137, 1, 242, 225, 223, 253, 60, 128, 136, 16, 17, 2, 227, 193, 189, 249, 120, 256, 15, 32, 34, 4, 197, 129, 121, 241, 240, 255, 30, 64, 68, 8, 137, 1], +[1, 243, 196, 83, 123, 77, 207, 186, 223, 219, 18, 5, 187, 209, 158, 101, 128, 7, 159, 87, 67, 90, 25, 164, 17, 19, 248, 126, 35, 24, 178, 78, 193, 125, 49, 85, 95, 212, 116, 175, 120, 119, 133, 194, 111, 245, 168, 218, 32, 66, 104, 86, 81, 151, 199, 41, 197, 69, 62, 160, 73, 6, 173, 148, 241, 224, 205, 214, 88, 53, 29, 108, 30, 94, 226, 177, 92, 254, 42, 183, 8, 145, 26, 150, 213, 102, 114, 203, 242, 210, 144, 40, 211, 130, 236, 37, 253, 56, 244, 182, 22, 206, 200, 27, 136, 152, 185, 237, 23, 192, 139, 110, 2, 229, 135, 166, 246, 154, 157, 115, 189, 181, 36, 10, 117, 161, 59, 202, 256, 14, 61, 174, 134, 180, 50, 71, 34, 38, 239, 252, 70, 48, 99, 156, 129, 250, 98, 170, 190, 167, 232, 93, 240, 238, 9, 131, 222, 233, 79, 179, 64, 132, 208, 172, 162, 45, 141, 82, 137, 138, 124, 63, 146, 12, 89, 39, 225, 191, 153, 171, 176, 106, 58, 216, 60, 188, 195, 97, 184, 251, 84, 109, 16, 33, 52, 43, 169, 204, 228, 149, 227, 163, 31, 80, 165, 3, 215, 74, 249, 112, 231, 107, 44, 155, 143, 54, 15, 47, 113, 217, 46, 127, 21, 220, 4, 201, 13, 75, 235, 51, 57, 230, 121, 105, 72, 20, 234, 65, 118, 147, 255, 28, 122, 91, 11, 103, 100, 142, 68, 76, 221, 247, 140, 96, 198, 55, 1], +[1, 244, 169, 116, 34, 72, 92, 89, 128, 135, 44, 199, 240, 221, 211, 84, 193, 61, 235, 29, 137, 18, 23, 215, 32, 98, 11, 114, 60, 248, 117, 21, 241, 208, 123, 200, 227, 133, 70, 118, 8, 153, 67, 157, 15, 62, 222, 198, 253, 52, 95, 50, 121, 226, 146, 158, 2, 231, 81, 232, 68, 144, 184, 178, 256, 13, 88, 141, 223, 185, 165, 168, 129, 122, 213, 58, 17, 36, 46, 173, 64, 196, 22, 228, 120, 239, 234, 42, 225, 159, 246, 143, 197, 9, 140, 236, 16, 49, 134, 57, 30, 124, 187, 139, 249, 104, 190, 100, 242, 195, 35, 59, 4, 205, 162, 207, 136, 31, 111, 99, 255, 26, 176, 25, 189, 113, 73, 79, 1, 244, 169, 116, 34, 72, 92, 89, 128, 135, 44, 199, 240, 221, 211, 84, 193, 61, 235, 29, 137, 18, 23, 215, 32, 98, 11, 114, 60, 248, 117, 21, 241, 208, 123, 200, 227, 133, 70, 118, 8, 153, 67, 157, 15, 62, 222, 198, 253, 52, 95, 50, 121, 226, 146, 158, 2, 231, 81, 232, 68, 144, 184, 178, 256, 13, 88, 141, 223, 185, 165, 168, 129, 122, 213, 58, 17, 36, 46, 173, 64, 196, 22, 228, 120, 239, 234, 42, 225, 159, 246, 143, 197, 9, 140, 236, 16, 49, 134, 57, 30, 124, 187, 139, 249, 104, 190, 100, 242, 195, 35, 59, 4, 205, 162, 207, 136, 31, 111, 99, 255, 26, 176, 25, 189, 113, 73, 79, 1], +[1, 245, 144, 71, 176, 201, 158, 160, 136, 167, 52, 147, 35, 94, 157, 172, 249, 96, 133, 203, 134, 191, 21, 5, 197, 206, 98, 109, 234, 19, 29, 166, 64, 3, 221, 175, 213, 14, 89, 217, 223, 151, 244, 156, 184, 105, 25, 214, 2, 233, 31, 142, 95, 145, 59, 63, 15, 77, 104, 37, 70, 188, 57, 87, 241, 192, 9, 149, 11, 125, 42, 10, 137, 155, 196, 218, 211, 38, 58, 75, 128, 6, 185, 93, 169, 28, 178, 177, 189, 45, 231, 55, 111, 210, 50, 171, 4, 209, 62, 27, 190, 33, 118, 126, 30, 154, 208, 74, 140, 119, 114, 174, 225, 127, 18, 41, 22, 250, 84, 20, 17, 53, 135, 179, 165, 76, 116, 150, 256, 12, 113, 186, 81, 56, 99, 97, 121, 90, 205, 110, 222, 163, 100, 85, 8, 161, 124, 54, 123, 66, 236, 252, 60, 51, 159, 148, 23, 238, 228, 91, 193, 254, 36, 82, 44, 243, 168, 40, 34, 106, 13, 101, 73, 152, 232, 43, 255, 24, 226, 115, 162, 112, 198, 194, 242, 180, 153, 220, 187, 69, 200, 170, 16, 65, 248, 108, 246, 132, 215, 247, 120, 102, 61, 39, 46, 219, 199, 182, 129, 251, 72, 164, 88, 229, 79, 80, 68, 212, 26, 202, 146, 47, 207, 86, 253, 48, 195, 230, 67, 224, 139, 131, 227, 103, 49, 183, 117, 138, 143, 83, 32, 130, 239, 216, 235, 7, 173, 237, 240, 204, 122, 78, 92, 181, 141, 107, 1], +[1, 246, 121, 211, 249, 88, 60, 111, 64, 67, 34, 140, 2, 235, 242, 165, 241, 176, 120, 222, 128, 134, 68, 23, 4, 213, 227, 73, 225, 95, 240, 187, 256, 11, 136, 46, 8, 169, 197, 146, 193, 190, 223, 117, 255, 22, 15, 92, 16, 81, 137, 35, 129, 123, 189, 234, 253, 44, 30, 184, 32, 162, 17, 70, 1, 246, 121, 211, 249, 88, 60, 111, 64, 67, 34, 140, 2, 235, 242, 165, 241, 176, 120, 222, 128, 134, 68, 23, 4, 213, 227, 73, 225, 95, 240, 187, 256, 11, 136, 46, 8, 169, 197, 146, 193, 190, 223, 117, 255, 22, 15, 92, 16, 81, 137, 35, 129, 123, 189, 234, 253, 44, 30, 184, 32, 162, 17, 70, 1, 246, 121, 211, 249, 88, 60, 111, 64, 67, 34, 140, 2, 235, 242, 165, 241, 176, 120, 222, 128, 134, 68, 23, 4, 213, 227, 73, 225, 95, 240, 187, 256, 11, 136, 46, 8, 169, 197, 146, 193, 190, 223, 117, 255, 22, 15, 92, 16, 81, 137, 35, 129, 123, 189, 234, 253, 44, 30, 184, 32, 162, 17, 70, 1, 246, 121, 211, 249, 88, 60, 111, 64, 67, 34, 140, 2, 235, 242, 165, 241, 176, 120, 222, 128, 134, 68, 23, 4, 213, 227, 73, 225, 95, 240, 187, 256, 11, 136, 46, 8, 169, 197, 146, 193, 190, 223, 117, 255, 22, 15, 92, 16, 81, 137, 35, 129, 123, 189, 234, 253, 44, 30, 184, 32, 162, 17, 70, 1], +[1, 247, 100, 28, 234, 230, 13, 127, 15, 107, 215, 163, 169, 109, 195, 106, 225, 63, 141, 132, 222, 93, 98, 48, 34, 174, 59, 181, 246, 110, 185, 206, 253, 40, 114, 145, 92, 108, 205, 6, 197, 86, 168, 119, 95, 78, 248, 90, 128, 5, 207, 243, 140, 142, 122, 65, 121, 75, 21, 47, 44, 74, 31, 204, 16, 97, 58, 191, 146, 82, 208, 233, 240, 170, 99, 38, 134, 202, 36, 154, 2, 237, 200, 56, 211, 203, 26, 254, 30, 214, 173, 69, 81, 218, 133, 212, 193, 126, 25, 7, 187, 186, 196, 96, 68, 91, 118, 105, 235, 220, 113, 155, 249, 80, 228, 33, 184, 216, 153, 12, 137, 172, 79, 238, 190, 156, 239, 180, 256, 10, 157, 229, 23, 27, 244, 130, 242, 150, 42, 94, 88, 148, 62, 151, 32, 194, 116, 125, 35, 164, 159, 209, 223, 83, 198, 76, 11, 147, 72, 51, 4, 217, 143, 112, 165, 149, 52, 251, 60, 171, 89, 138, 162, 179, 9, 167, 129, 252, 50, 14, 117, 115, 135, 192, 136, 182, 236, 210, 213, 183, 226, 53, 241, 160, 199, 66, 111, 175, 49, 24, 17, 87, 158, 219, 123, 55, 221, 103, 255, 20, 57, 201, 46, 54, 231, 3, 227, 43, 84, 188, 176, 39, 124, 45, 64, 131, 232, 250, 70, 71, 61, 161, 189, 166, 139, 152, 22, 37, 144, 102, 8, 177, 29, 224, 73, 41, 104, 245, 120, 85, 178, 19, 67, 101, 18, 77, 1], +[1, 248, 81, 42, 136, 61, 222, 58, 249, 72, 123, 178, 197, 26, 23, 50, 64, 195, 44, 118, 223, 49, 73, 114, 2, 239, 162, 84, 15, 122, 187, 116, 241, 144, 246, 99, 137, 52, 46, 100, 128, 133, 88, 236, 189, 98, 146, 228, 4, 221, 67, 168, 30, 244, 117, 232, 225, 31, 235, 198, 17, 104, 92, 200, 256, 9, 176, 215, 121, 196, 35, 199, 8, 185, 134, 79, 60, 231, 234, 207, 193, 62, 213, 139, 34, 208, 184, 143, 255, 18, 95, 173, 242, 135, 70, 141, 16, 113, 11, 158, 120, 205, 211, 157, 129, 124, 169, 21, 68, 159, 111, 29, 253, 36, 190, 89, 227, 13, 140, 25, 32, 226, 22, 59, 240, 153, 165, 57, 1, 248, 81, 42, 136, 61, 222, 58, 249, 72, 123, 178, 197, 26, 23, 50, 64, 195, 44, 118, 223, 49, 73, 114, 2, 239, 162, 84, 15, 122, 187, 116, 241, 144, 246, 99, 137, 52, 46, 100, 128, 133, 88, 236, 189, 98, 146, 228, 4, 221, 67, 168, 30, 244, 117, 232, 225, 31, 235, 198, 17, 104, 92, 200, 256, 9, 176, 215, 121, 196, 35, 199, 8, 185, 134, 79, 60, 231, 234, 207, 193, 62, 213, 139, 34, 208, 184, 143, 255, 18, 95, 173, 242, 135, 70, 141, 16, 113, 11, 158, 120, 205, 211, 157, 129, 124, 169, 21, 68, 159, 111, 29, 253, 36, 190, 89, 227, 13, 140, 25, 32, 226, 22, 59, 240, 153, 165, 57, 1], +[1, 249, 64, 2, 241, 128, 4, 225, 256, 8, 193, 255, 16, 129, 253, 32, 1, 249, 64, 2, 241, 128, 4, 225, 256, 8, 193, 255, 16, 129, 253, 32, 1, 249, 64, 2, 241, 128, 4, 225, 256, 8, 193, 255, 16, 129, 253, 32, 1, 249, 64, 2, 241, 128, 4, 225, 256, 8, 193, 255, 16, 129, 253, 32, 1, 249, 64, 2, 241, 128, 4, 225, 256, 8, 193, 255, 16, 129, 253, 32, 1, 249, 64, 2, 241, 128, 4, 225, 256, 8, 193, 255, 16, 129, 253, 32, 1, 249, 64, 2, 241, 128, 4, 225, 256, 8, 193, 255, 16, 129, 253, 32, 1, 249, 64, 2, 241, 128, 4, 225, 256, 8, 193, 255, 16, 129, 253, 32, 1, 249, 64, 2, 241, 128, 4, 225, 256, 8, 193, 255, 16, 129, 253, 32, 1, 249, 64, 2, 241, 128, 4, 225, 256, 8, 193, 255, 16, 129, 253, 32, 1, 249, 64, 2, 241, 128, 4, 225, 256, 8, 193, 255, 16, 129, 253, 32, 1, 249, 64, 2, 241, 128, 4, 225, 256, 8, 193, 255, 16, 129, 253, 32, 1, 249, 64, 2, 241, 128, 4, 225, 256, 8, 193, 255, 16, 129, 253, 32, 1, 249, 64, 2, 241, 128, 4, 225, 256, 8, 193, 255, 16, 129, 253, 32, 1, 249, 64, 2, 241, 128, 4, 225, 256, 8, 193, 255, 16, 129, 253, 32, 1, 249, 64, 2, 241, 128, 4, 225, 256, 8, 193, 255, 16, 129, 253, 32, 1], +[1, 250, 49, 171, 88, 155, 200, 142, 34, 19, 124, 160, 165, 130, 118, 202, 128, 132, 104, 43, 213, 51, 157, 186, 240, 119, 195, 177, 46, 192, 198, 156, 193, 191, 205, 107, 22, 103, 50, 164, 137, 69, 31, 40, 234, 161, 158, 179, 32, 33, 26, 75, 246, 77, 232, 175, 60, 94, 113, 237, 140, 48, 178, 39, 241, 112, 244, 91, 134, 90, 141, 41, 227, 210, 72, 10, 187, 233, 168, 109, 8, 201, 135, 83, 190, 212, 58, 108, 15, 152, 221, 252, 35, 12, 173, 74, 253, 28, 61, 87, 162, 151, 228, 203, 121, 181, 18, 131, 111, 251, 42, 220, 2, 243, 98, 85, 176, 53, 143, 27, 68, 38, 248, 63, 73, 3, 236, 147, 256, 7, 208, 86, 169, 102, 57, 115, 223, 238, 133, 97, 92, 127, 139, 55, 129, 125, 153, 214, 44, 206, 100, 71, 17, 138, 62, 80, 211, 65, 59, 101, 64, 66, 52, 150, 235, 154, 207, 93, 120, 188, 226, 217, 23, 96, 99, 78, 225, 224, 231, 182, 11, 180, 25, 82, 197, 163, 144, 20, 117, 209, 79, 218, 16, 145, 13, 166, 123, 167, 116, 216, 30, 47, 185, 247, 70, 24, 89, 148, 249, 56, 122, 174, 67, 45, 199, 149, 242, 105, 36, 5, 222, 245, 84, 183, 4, 229, 196, 170, 95, 106, 29, 54, 136, 76, 239, 126, 146, 6, 215, 37, 255, 14, 159, 172, 81, 204, 114, 230, 189, 219, 9, 194, 184, 254, 21, 110, 1], +[1, 251, 36, 41, 11, 191, 139, 194, 121, 45, 244, 78, 46, 238, 114, 87, 249, 48, 226, 186, 169, 14, 173, 247, 60, 154, 104, 147, 146, 152, 116, 75, 64, 130, 248, 54, 190, 145, 158, 80, 34, 53, 196, 109, 117, 69, 100, 171, 2, 245, 72, 82, 22, 125, 21, 131, 242, 90, 231, 156, 92, 219, 228, 174, 241, 96, 195, 115, 81, 28, 89, 237, 120, 51, 208, 37, 35, 47, 232, 150, 128, 3, 239, 108, 123, 33, 59, 160, 68, 106, 135, 218, 234, 138, 200, 85, 4, 233, 144, 164, 44, 250, 42, 5, 227, 180, 205, 55, 184, 181, 199, 91, 225, 192, 133, 230, 162, 56, 178, 217, 240, 102, 159, 74, 70, 94, 207, 43, 256, 6, 221, 216, 246, 66, 118, 63, 136, 212, 13, 179, 211, 19, 143, 170, 8, 209, 31, 71, 88, 243, 84, 10, 197, 103, 153, 110, 111, 105, 141, 182, 193, 127, 9, 203, 67, 112, 99, 177, 223, 204, 61, 148, 140, 188, 157, 86, 255, 12, 185, 175, 235, 132, 236, 126, 15, 167, 26, 101, 165, 38, 29, 83, 16, 161, 62, 142, 176, 229, 168, 20, 137, 206, 49, 220, 222, 210, 25, 107, 129, 254, 18, 149, 134, 224, 198, 97, 189, 151, 122, 39, 23, 119, 57, 172, 253, 24, 113, 93, 213, 7, 215, 252, 30, 77, 52, 202, 73, 76, 58, 166, 32, 65, 124, 27, 95, 201, 79, 40, 17, 155, 98, 183, 187, 163, 50, 214, 1], +[1, 252, 25, 132, 111, 216, 205, 3, 242, 75, 139, 76, 134, 101, 9, 212, 225, 160, 228, 145, 46, 27, 122, 161, 223, 170, 178, 138, 81, 109, 226, 155, 253, 20, 157, 243, 70, 164, 208, 245, 60, 214, 215, 210, 235, 110, 221, 180, 128, 131, 116, 191, 73, 149, 26, 127, 136, 91, 59, 219, 190, 78, 124, 151, 16, 177, 143, 56, 234, 115, 196, 48, 17, 172, 168, 188, 88, 74, 144, 51, 2, 247, 50, 7, 222, 175, 153, 6, 227, 150, 21, 152, 11, 202, 18, 167, 193, 63, 199, 33, 92, 54, 244, 65, 189, 83, 99, 19, 162, 218, 195, 53, 249, 40, 57, 229, 140, 71, 159, 233, 120, 171, 173, 163, 213, 220, 185, 103, 256, 5, 232, 125, 146, 41, 52, 254, 15, 182, 118, 181, 123, 156, 248, 45, 32, 97, 29, 112, 211, 230, 135, 96, 34, 87, 79, 119, 176, 148, 31, 102, 4, 237, 100, 14, 187, 93, 49, 12, 197, 43, 42, 47, 22, 147, 36, 77, 129, 126, 141, 66, 184, 108, 231, 130, 121, 166, 198, 38, 67, 179, 133, 106, 241, 80, 114, 201, 23, 142, 61, 209, 240, 85, 89, 69, 169, 183, 113, 206, 255, 10, 207, 250, 35, 82, 104, 251, 30, 107, 236, 105, 246, 55, 239, 90, 64, 194, 58, 224, 165, 203, 13, 192, 68, 174, 158, 238, 95, 39, 62, 204, 8, 217, 200, 28, 117, 186, 98, 24, 137, 86, 84, 94, 44, 37, 72, 154, 1], +[1, 253, 16, 193, 256, 4, 241, 64, 1, 253, 16, 193, 256, 4, 241, 64, 1, 253, 16, 193, 256, 4, 241, 64, 1, 253, 16, 193, 256, 4, 241, 64, 1, 253, 16, 193, 256, 4, 241, 64, 1, 253, 16, 193, 256, 4, 241, 64, 1, 253, 16, 193, 256, 4, 241, 64, 1, 253, 16, 193, 256, 4, 241, 64, 1, 253, 16, 193, 256, 4, 241, 64, 1, 253, 16, 193, 256, 4, 241, 64, 1, 253, 16, 193, 256, 4, 241, 64, 1, 253, 16, 193, 256, 4, 241, 64, 1, 253, 16, 193, 256, 4, 241, 64, 1, 253, 16, 193, 256, 4, 241, 64, 1, 253, 16, 193, 256, 4, 241, 64, 1, 253, 16, 193, 256, 4, 241, 64, 1, 253, 16, 193, 256, 4, 241, 64, 1, 253, 16, 193, 256, 4, 241, 64, 1, 253, 16, 193, 256, 4, 241, 64, 1, 253, 16, 193, 256, 4, 241, 64, 1, 253, 16, 193, 256, 4, 241, 64, 1, 253, 16, 193, 256, 4, 241, 64, 1, 253, 16, 193, 256, 4, 241, 64, 1, 253, 16, 193, 256, 4, 241, 64, 1, 253, 16, 193, 256, 4, 241, 64, 1, 253, 16, 193, 256, 4, 241, 64, 1, 253, 16, 193, 256, 4, 241, 64, 1, 253, 16, 193, 256, 4, 241, 64, 1, 253, 16, 193, 256, 4, 241, 64, 1, 253, 16, 193, 256, 4, 241, 64, 1, 253, 16, 193, 256, 4, 241, 64, 1, 253, 16, 193, 256, 4, 241, 64, 1], +[1, 254, 9, 230, 81, 14, 215, 126, 136, 106, 196, 183, 222, 105, 199, 174, 249, 24, 185, 216, 123, 145, 79, 20, 197, 180, 231, 78, 23, 188, 207, 150, 64, 65, 62, 71, 44, 125, 139, 97, 223, 102, 208, 147, 73, 38, 143, 85, 2, 251, 18, 203, 162, 28, 173, 252, 15, 212, 135, 109, 187, 210, 141, 91, 241, 48, 113, 175, 246, 33, 158, 40, 137, 103, 205, 156, 46, 119, 157, 43, 128, 130, 124, 142, 88, 250, 21, 194, 189, 204, 159, 37, 146, 76, 29, 170, 4, 245, 36, 149, 67, 56, 89, 247, 30, 167, 13, 218, 117, 163, 25, 182, 225, 96, 226, 93, 235, 66, 59, 80, 17, 206, 153, 55, 92, 238, 57, 86, 256, 3, 248, 27, 176, 243, 42, 131, 121, 151, 61, 74, 35, 152, 58, 83, 8, 233, 72, 41, 134, 112, 178, 237, 60, 77, 26, 179, 234, 69, 50, 107, 193, 192, 195, 186, 213, 132, 118, 160, 34, 155, 49, 110, 184, 219, 114, 172, 255, 6, 239, 54, 95, 229, 84, 5, 242, 45, 122, 148, 70, 47, 116, 166, 16, 209, 144, 82, 11, 224, 99, 217, 120, 154, 52, 101, 211, 138, 100, 214, 129, 127, 133, 115, 169, 7, 236, 63, 68, 53, 98, 220, 111, 181, 228, 87, 253, 12, 221, 108, 190, 201, 168, 10, 227, 90, 244, 39, 140, 94, 232, 75, 32, 161, 31, 164, 22, 191, 198, 177, 240, 51, 104, 202, 165, 19, 200, 171, 1], +[1, 255, 4, 249, 16, 225, 64, 129, 256, 2, 253, 8, 241, 32, 193, 128, 1, 255, 4, 249, 16, 225, 64, 129, 256, 2, 253, 8, 241, 32, 193, 128, 1, 255, 4, 249, 16, 225, 64, 129, 256, 2, 253, 8, 241, 32, 193, 128, 1, 255, 4, 249, 16, 225, 64, 129, 256, 2, 253, 8, 241, 32, 193, 128, 1, 255, 4, 249, 16, 225, 64, 129, 256, 2, 253, 8, 241, 32, 193, 128, 1, 255, 4, 249, 16, 225, 64, 129, 256, 2, 253, 8, 241, 32, 193, 128, 1, 255, 4, 249, 16, 225, 64, 129, 256, 2, 253, 8, 241, 32, 193, 128, 1, 255, 4, 249, 16, 225, 64, 129, 256, 2, 253, 8, 241, 32, 193, 128, 1, 255, 4, 249, 16, 225, 64, 129, 256, 2, 253, 8, 241, 32, 193, 128, 1, 255, 4, 249, 16, 225, 64, 129, 256, 2, 253, 8, 241, 32, 193, 128, 1, 255, 4, 249, 16, 225, 64, 129, 256, 2, 253, 8, 241, 32, 193, 128, 1, 255, 4, 249, 16, 225, 64, 129, 256, 2, 253, 8, 241, 32, 193, 128, 1, 255, 4, 249, 16, 225, 64, 129, 256, 2, 253, 8, 241, 32, 193, 128, 1, 255, 4, 249, 16, 225, 64, 129, 256, 2, 253, 8, 241, 32, 193, 128, 1, 255, 4, 249, 16, 225, 64, 129, 256, 2, 253, 8, 241, 32, 193, 128, 1, 255, 4, 249, 16, 225, 64, 129, 256, 2, 253, 8, 241, 32, 193, 128, 1], +[1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1, 256, 1], +]; + +fn main(x: Field, y: pub Field) { + let mut acc: Field = 0; + for i in 0..257 { + for j in 0..257 { + acc += EXPONENTIATE[i][j]; + } + } + assert(!acc.lt(x)); + assert(x != y); +} diff --git a/test_programs/execution_success/regression_5045/Nargo.toml b/test_programs/execution_success/regression_5045/Nargo.toml new file mode 100644 index 00000000000..8f56d392fec --- /dev/null +++ b/test_programs/execution_success/regression_5045/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "regression_5045" +version = "0.1.0" +type = "bin" +authors = [""] + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/regression_5045/Prover.toml b/test_programs/execution_success/regression_5045/Prover.toml new file mode 100644 index 00000000000..5444a86ec82 --- /dev/null +++ b/test_programs/execution_success/regression_5045/Prover.toml @@ -0,0 +1 @@ +is_active = false \ No newline at end of file diff --git a/test_programs/execution_success/regression_5045/src/main.nr b/test_programs/execution_success/regression_5045/src/main.nr new file mode 100644 index 00000000000..015fb1b2555 --- /dev/null +++ b/test_programs/execution_success/regression_5045/src/main.nr @@ -0,0 +1,20 @@ +use dep::std::embedded_curve_ops::EmbeddedCurvePoint; +use dep::std::embedded_curve_ops::EmbeddedCurveScalar; + +fn main(is_active: bool) { + let a = EmbeddedCurvePoint { + x: 0x1d8eb4378a3bde41e0b6a9a8dcbd21b7ff9c51bdd6ca13ce989abbbf90df3666, + y: 0x06075b63354f2504f9cddba0b94ed0cef35fc88615e69ec1f853b51eb79a24a0, + is_infinite: false + }; + + if is_active { + let bad = EmbeddedCurvePoint { x: 0, y: 5, is_infinite: false }; + let d = bad.double(); + let e = dep::std::embedded_curve_ops::multi_scalar_mul( + [a, bad], + [EmbeddedCurveScalar { lo: 1, hi: 0 }, EmbeddedCurveScalar { lo: 1, hi: 0 }] + ); + assert(e[0] != d.x); + } +} diff --git a/test_programs/execution_success/regression_capacity_tracker/Nargo.toml b/test_programs/execution_success/regression_capacity_tracker/Nargo.toml new file mode 100644 index 00000000000..d5a3839626f --- /dev/null +++ b/test_programs/execution_success/regression_capacity_tracker/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "regression_capacity_tracker" +type = "bin" +authors = [""] +compiler_version = ">=0.26.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/regression_capacity_tracker/Prover.toml b/test_programs/execution_success/regression_capacity_tracker/Prover.toml new file mode 100644 index 00000000000..bbf35b23a0f --- /dev/null +++ b/test_programs/execution_success/regression_capacity_tracker/Prover.toml @@ -0,0 +1,3 @@ +expected = "10" +first = "10" +input = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] \ No newline at end of file diff --git a/test_programs/execution_success/regression_capacity_tracker/src/main.nr b/test_programs/execution_success/regression_capacity_tracker/src/main.nr new file mode 100644 index 00000000000..be645c811d2 --- /dev/null +++ b/test_programs/execution_success/regression_capacity_tracker/src/main.nr @@ -0,0 +1,19 @@ +// Reference https://github.com/noir-lang/noir/issues/4395#issuecomment-2018948631 +// for context. +// We were not accurately accounting for situations where the slice capacity tracker +// was expecting a capacity from slice intrinsic results. +fn main(expected: pub Field, first: Field, input: [Field; 20]) { + let mut hasher_slice = input.as_slice(); + hasher_slice = hasher_slice.push_front(first); + assert(hasher_slice[0] == expected); + // We need a conditional based upon witnesses + // to force a store of the slice. + // If this successfully compiles it means we have stored + // the results of the slice intrinsics used above. + if expected as u32 > 10 { + hasher_slice[expected - 10] = 100; + } else { + hasher_slice[expected] = 100; + } + assert(hasher_slice[0] == expected); +} diff --git a/test_programs/execution_success/regression_struct_array_conditional/Nargo.toml b/test_programs/execution_success/regression_struct_array_conditional/Nargo.toml new file mode 100644 index 00000000000..a0587210464 --- /dev/null +++ b/test_programs/execution_success/regression_struct_array_conditional/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "regression_struct_array_conditional" +version = "0.1.0" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/regression_struct_array_conditional/Prover.toml b/test_programs/execution_success/regression_struct_array_conditional/Prover.toml new file mode 100644 index 00000000000..ef97f9d482a --- /dev/null +++ b/test_programs/execution_success/regression_struct_array_conditional/Prover.toml @@ -0,0 +1,18 @@ +y = 1 +z = 1 + +[[x]] +value = "0x23de33be058ce5504e1ade738db8bdacfe268fa9dbde777092bf1d38519bdf59" +counter = "10" +dummy = "0" + +[[x]] +value = "3" +counter = "2" +dummy = "0" + +[[x]] +value = "2" +counter = "0" +dummy = "0" + diff --git a/test_programs/execution_success/regression_struct_array_conditional/src/main.nr b/test_programs/execution_success/regression_struct_array_conditional/src/main.nr new file mode 100644 index 00000000000..17502a9fe50 --- /dev/null +++ b/test_programs/execution_success/regression_struct_array_conditional/src/main.nr @@ -0,0 +1,38 @@ +struct foo { + value: Field, + counter: u8, + dummy: u8, +} +struct bar { + dummy: [u8;3], + value: Field, + counter: u8, +} +struct bar_field { + dummy: [Field;3], + value: Field, + counter: u8, +} +fn main(x: [foo; 3], y: u32, z: u32) -> pub u8 { + let a = [y, z, x[y].counter as u32]; + let mut b = [bar { value: 0, counter: 0, dummy: [0; 3] }; 3]; + let mut c = [bar_field { value: 0, counter: 0, dummy: [0; 3] }; 3]; + for i in 0..3 { + b[i].value = x[i].value; + b[i].counter = x[i].counter; + b[i].dummy[0] = x[i].dummy; + c[i].value = x[i].value; + c[i].counter = x[i].counter; + c[i].dummy[0] = x[i].dummy as Field; + } + if z == 0 { + // offset + assert(y as u8 < x[y].counter); + assert(y <= a[y]); + // first element is compatible + assert(y as u8 < b[y].counter); + // fallback + assert(y as u8 < c[y].counter); + } + x[0].counter +} diff --git a/test_programs/execution_success/scalar_mul/Prover.toml b/test_programs/execution_success/scalar_mul/Prover.toml deleted file mode 100644 index 69b91cb5f31..00000000000 --- a/test_programs/execution_success/scalar_mul/Prover.toml +++ /dev/null @@ -1,7 +0,0 @@ -a = "1" -a_pub_x = "0x0000000000000000000000000000000000000000000000000000000000000001" -a_pub_y = "0x0000000000000002cf135e7506a45d632d270d45f1181294833fc48d823f272c" - -b = "2" -b_pub_x = "0x06ce1b0827aafa85ddeb49cdaa36306d19a74caa311e13d46d8bc688cdbffffe" -b_pub_y = "0x1c122f81a3a14964909ede0ba2a6855fc93faf6fa1a788bf467be7e7a43f80ac" \ No newline at end of file diff --git a/test_programs/execution_success/scalar_mul/src/main.nr b/test_programs/execution_success/scalar_mul/src/main.nr deleted file mode 100644 index e20f47907db..00000000000 --- a/test_programs/execution_success/scalar_mul/src/main.nr +++ /dev/null @@ -1,31 +0,0 @@ -use dep::std; - -fn main( - a: Field, - a_pub_x: pub Field, - a_pub_y: pub Field, - b: Field, - b_pub_x: pub Field, - b_pub_y: pub Field -) { - let mut priv_key = a; - let mut pub_x: Field = a_pub_x; - let mut pub_y: Field = a_pub_y; - if a != 1 { - // Change `a` in Prover.toml to test input `b` - priv_key = b; - pub_x = b_pub_x; - pub_y = b_pub_y; - } - let res = std::scalar_mul::fixed_base_embedded_curve(priv_key, 0); - assert(res[0] == pub_x); - assert(res[1] == pub_y); - let pub_point= std::scalar_mul::EmbeddedCurvePoint { x: pub_x, y: pub_y }; - let g1_y = 17631683881184975370165255887551781615748388533673675138860; - let g1= std::scalar_mul::EmbeddedCurvePoint { x: 1, y: g1_y }; - - let res = pub_point.double(); - let double = g1.add(g1); - - assert(double.x == res.x); -} diff --git a/test_programs/execution_success/schnorr/src/main.nr b/test_programs/execution_success/schnorr/src/main.nr index 107af152625..1067d9707b2 100644 --- a/test_programs/execution_success/schnorr/src/main.nr +++ b/test_programs/execution_success/schnorr/src/main.nr @@ -1,4 +1,6 @@ use dep::std; +use dep::std::embedded_curve_ops; + // Note: If main has any unsized types, then the verifier will never be able // to figure out the circuit instance fn main( @@ -11,15 +13,117 @@ fn main( // Regression for issue #2421 // We want to make sure that we can accurately verify a signature whose message is a slice vs. an array let message_field_bytes = message_field.to_be_bytes(10); + let mut message2 = [0; 42]; for i in 0..10 { assert(message[i] == message_field_bytes[i]); + message2[i] = message[i]; } + // Is there ever a situation where someone would want // to ensure that a signature was invalid? // Check that passing a slice as the message is valid - let valid_signature = std::schnorr::verify_signature(pub_key_x, pub_key_y, signature, message_field_bytes); + let valid_signature = std::schnorr::verify_signature_slice(pub_key_x, pub_key_y, signature, message_field_bytes); assert(valid_signature); // Check that passing an array as the message is valid let valid_signature = std::schnorr::verify_signature(pub_key_x, pub_key_y, signature, message); assert(valid_signature); + let pub_key = embedded_curve_ops::EmbeddedCurvePoint { x: pub_key_x, y: pub_key_y, is_infinite: false }; + let valid_signature = verify_signature_noir(pub_key, signature, message2); + assert(valid_signature); + assert_valid_signature(pub_key, signature, message2); +} + +// TODO: to put in the stdlib once we have numeric generics +// Meanwhile, you have to use a message with 32 additional bytes: +// If you want to verify a signature on a message of 10 bytes, you need to pass a message of length 42, +// where the first 10 bytes are the one from the original message (the other bytes are not used) +pub fn verify_signature_noir( + public_key: embedded_curve_ops::EmbeddedCurvePoint, + signature: [u8; 64], + message: [u8; M] +) -> bool { + let N = message.len() - 32; + + //scalar lo/hi from bytes + let sig_s = bytes_to_scalar(signature, 0); + let sig_e = bytes_to_scalar(signature, 32); + // pub_key is on Grumpkin curve + let mut is_ok = (public_key.y * public_key.y == public_key.x * public_key.x * public_key.x - 17) + & (!public_key.is_infinite); + + if ((sig_s.lo != 0) | (sig_s.hi != 0)) & ((sig_e.lo != 0) | (sig_e.hi != 0)) { + let g1 = embedded_curve_ops::EmbeddedCurvePoint { x: 1, y: 17631683881184975370165255887551781615748388533673675138860, is_infinite: false }; + let r = embedded_curve_ops::multi_scalar_mul([g1, public_key], [sig_s, sig_e]); + // compare the _hashes_ rather than field elements modulo r + let pedersen_hash = std::hash::pedersen_hash([r[0], public_key.x, public_key.y]); + let mut hash_input = [0; M]; + let pde = pedersen_hash.to_be_bytes(32); + + for i in 0..32 { + hash_input[i] = pde[i]; + } + for i in 0..N { + hash_input[32+i] = message[i]; + } + let result = std::hash::blake2s(hash_input); + + is_ok = (r[2] == 0); + for i in 0..32 { + if result[i] != signature[32 + i] { + is_ok = false; + } + } + } + is_ok +} + +pub fn bytes_to_scalar(bytes: [u8; 64], offset: u32) -> embedded_curve_ops::EmbeddedCurveScalar { + let mut v = 1; + let mut lo = 0 as Field; + let mut hi = 0 as Field; + for i in 0..16 { + lo = lo + (bytes[offset+31 - i] as Field) * v; + hi = hi + (bytes[offset+15 - i] as Field) * v; + v = v * 256; + } + let sig_s = embedded_curve_ops::EmbeddedCurveScalar { lo, hi }; + sig_s +} + +pub fn assert_valid_signature( + public_key: embedded_curve_ops::EmbeddedCurvePoint, + signature: [u8; 64], + message: [u8; M] +) { + let N = message.len() - 32; + //scalar lo/hi from bytes + let sig_s = bytes_to_scalar(signature, 0); + let sig_e = bytes_to_scalar(signature, 32); + + // assert pub_key is on Grumpkin curve + assert(public_key.y * public_key.y == public_key.x * public_key.x * public_key.x - 17); + assert(public_key.is_infinite == false); + // assert signature is not null + assert((sig_s.lo != 0) | (sig_s.hi != 0)); + assert((sig_e.lo != 0) | (sig_e.hi != 0)); + + let g1 = embedded_curve_ops::EmbeddedCurvePoint { x: 1, y: 17631683881184975370165255887551781615748388533673675138860, is_infinite: false }; + let r = embedded_curve_ops::multi_scalar_mul([g1, public_key], [sig_s, sig_e]); + // compare the _hashes_ rather than field elements modulo r + let pedersen_hash = std::hash::pedersen_hash([r[0], public_key.x, public_key.y]); + let mut hash_input = [0; M]; + let pde = pedersen_hash.to_be_bytes(32); + + for i in 0..32 { + hash_input[i] = pde[i]; + } + for i in 0..N { + hash_input[32+i] = message[i]; + } + let result = std::hash::blake2s(hash_input); + + assert(r[2] == 0); + for i in 0..32 { + assert(result[i] == signature[32 + i]); + } } diff --git a/test_programs/execution_success/sha256/src/main.nr b/test_programs/execution_success/sha256/src/main.nr index fd5340e2384..d4240ded8b3 100644 --- a/test_programs/execution_success/sha256/src/main.nr +++ b/test_programs/execution_success/sha256/src/main.nr @@ -14,6 +14,8 @@ use dep::std; fn main(x: Field, result: [u8; 32]) { // We use the `as` keyword here to denote the fact that we want to take just the first byte from the x Field // The padding is taken care of by the program - let digest = std::hash::sha256([x as u8]); + // docs:start:sha256_var + let digest = std::hash::sha256_var([x as u8], 1); + // docs:end:sha256_var assert(digest == result); } diff --git a/test_programs/execution_success/scalar_mul/Nargo.toml b/test_programs/execution_success/signed_cmp/Nargo.toml similarity index 72% rename from test_programs/execution_success/scalar_mul/Nargo.toml rename to test_programs/execution_success/signed_cmp/Nargo.toml index 926114ec374..642a0924678 100644 --- a/test_programs/execution_success/scalar_mul/Nargo.toml +++ b/test_programs/execution_success/signed_cmp/Nargo.toml @@ -1,5 +1,5 @@ [package] -name = "scalar_mul" +name = "signed_cmp" type = "bin" authors = [""] diff --git a/test_programs/execution_success/signed_cmp/Prover.toml b/test_programs/execution_success/signed_cmp/Prover.toml new file mode 100644 index 00000000000..4b719f83c16 --- /dev/null +++ b/test_programs/execution_success/signed_cmp/Prover.toml @@ -0,0 +1 @@ +minus_one = 255 diff --git a/test_programs/execution_success/signed_cmp/src/main.nr b/test_programs/execution_success/signed_cmp/src/main.nr new file mode 100644 index 00000000000..85746ada8f4 --- /dev/null +++ b/test_programs/execution_success/signed_cmp/src/main.nr @@ -0,0 +1,8 @@ +fn main(minus_one: i8) { + assert(minus_one < 0); + assert(0 < minus_one as u8); + assert(0 > minus_one); + let most_negative_number = minus_one * 127 - 1; + assert(most_negative_number < 0); + assert(127 > most_negative_number); +} diff --git a/test_programs/execution_success/mock_oracle/Nargo.toml b/test_programs/execution_success/signed_div/Nargo.toml similarity index 72% rename from test_programs/execution_success/mock_oracle/Nargo.toml rename to test_programs/execution_success/signed_div/Nargo.toml index b2916487e8c..5ce137d8c0c 100644 --- a/test_programs/execution_success/mock_oracle/Nargo.toml +++ b/test_programs/execution_success/signed_div/Nargo.toml @@ -1,5 +1,5 @@ [package] -name = "mock_oracle" +name = "signed_div" type = "bin" authors = [""] diff --git a/test_programs/execution_success/signed_div/Prover.toml b/test_programs/execution_success/signed_div/Prover.toml new file mode 100644 index 00000000000..be93fec5cc3 --- /dev/null +++ b/test_programs/execution_success/signed_div/Prover.toml @@ -0,0 +1,75 @@ +[[ops]] +lhs = 4 +rhs = 255 # -1 +result = 252 # -4 + +[[ops]] +lhs = 4 +rhs = 254 # -2 +result = 254 # -2 + +[[ops]] +lhs = 4 +rhs = 253 # -3 +result = 255 # -1 + +[[ops]] +lhs = 4 +rhs = 252 # -4 +result = 255 # -1 + +[[ops]] +lhs = 4 +rhs = 251 # -5 +result = 0 + +[[ops]] +lhs = 252 # -4 +rhs = 255 # -1 +result = 4 + +[[ops]] +lhs = 252 # -4 +rhs = 254 # -2 +result = 2 + +[[ops]] +lhs = 252 # -4 +rhs = 253 # -3 +result = 1 + +[[ops]] +lhs = 252 # -4 +rhs = 252 # -4 +result = 1 + +[[ops]] +lhs = 252 # -4 +rhs = 251 # -5 +result = 0 + + +[[ops]] +lhs = 4 +rhs = 1 +result = 4 + +[[ops]] +lhs = 4 +rhs = 2 +result = 2 + +[[ops]] +lhs = 4 +rhs = 3 +result = 1 + +[[ops]] +lhs = 4 +rhs = 4 +result = 1 + +[[ops]] +lhs = 4 +rhs = 5 +result = 0 diff --git a/test_programs/execution_success/signed_div/src/main.nr b/test_programs/execution_success/signed_div/src/main.nr new file mode 100644 index 00000000000..04383a459bd --- /dev/null +++ b/test_programs/execution_success/signed_div/src/main.nr @@ -0,0 +1,11 @@ +struct SignedDivOp { + lhs: i8, + rhs: i8, + result: i8, +} + +fn main(ops: [SignedDivOp; 15]) { + for i in 0..15 { + assert_eq(ops[i].lhs / ops[i].rhs, ops[i].result); + } +} diff --git a/test_programs/compile_success_empty/simple_array_param/Nargo.toml b/test_programs/execution_success/simple_array_param/Nargo.toml similarity index 100% rename from test_programs/compile_success_empty/simple_array_param/Nargo.toml rename to test_programs/execution_success/simple_array_param/Nargo.toml diff --git a/test_programs/compile_success_empty/simple_array_param/Prover.toml b/test_programs/execution_success/simple_array_param/Prover.toml similarity index 100% rename from test_programs/compile_success_empty/simple_array_param/Prover.toml rename to test_programs/execution_success/simple_array_param/Prover.toml diff --git a/test_programs/compile_success_empty/simple_array_param/src/main.nr b/test_programs/execution_success/simple_array_param/src/main.nr similarity index 100% rename from test_programs/compile_success_empty/simple_array_param/src/main.nr rename to test_programs/execution_success/simple_array_param/src/main.nr diff --git a/test_programs/execution_success/simple_shield/src/main.nr b/test_programs/execution_success/simple_shield/src/main.nr index c46d3b4594c..548ba17d462 100644 --- a/test_programs/execution_success/simple_shield/src/main.nr +++ b/test_programs/execution_success/simple_shield/src/main.nr @@ -13,7 +13,7 @@ fn main( 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 = std::embedded_curve_ops::fixed_base_scalar_mul(priv_key, 0); let pubkey_x = pubkey[0]; let pubkey_y = pubkey[1]; // Compute input note commitment diff --git a/test_programs/execution_success/slice_coercion/Nargo.toml b/test_programs/execution_success/slice_coercion/Nargo.toml new file mode 100644 index 00000000000..659677cc560 --- /dev/null +++ b/test_programs/execution_success/slice_coercion/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "slice_coercion" +type = "bin" +authors = [""] +compiler_version = ">=0.25.0" + +[dependencies] diff --git a/test_programs/execution_success/slice_coercion/Prover.toml b/test_programs/execution_success/slice_coercion/Prover.toml new file mode 100644 index 00000000000..09c44a855b0 --- /dev/null +++ b/test_programs/execution_success/slice_coercion/Prover.toml @@ -0,0 +1,2 @@ +first = 3 +expected = 3 diff --git a/test_programs/execution_success/slice_coercion/src/main.nr b/test_programs/execution_success/slice_coercion/src/main.nr new file mode 100644 index 00000000000..a7ba0443bd1 --- /dev/null +++ b/test_programs/execution_success/slice_coercion/src/main.nr @@ -0,0 +1,27 @@ +struct Hasher { + fields: [Field], +} + +impl Hasher { + pub fn new() -> Self { + Self { fields: [] } + } + + pub fn add(&mut self, field: Field) { + self.fields = self.fields.push_back(field); + } +} + +fn main(expected: pub Field, first: Field) { + let mut hasher = Hasher::new(); + hasher.add(first); + assert(hasher.fields[0] == expected); + + regression_4967(); +} + +fn regression_4967() { + let var1: [(i32, u8)] = [(1, 2)]; + assert(var1.len() == 1); + dep::std::println(var1); +} diff --git a/test_programs/execution_success/slice_dynamic_index/src/main.nr b/test_programs/execution_success/slice_dynamic_index/src/main.nr index 41fc9a645c1..2ab633eb98c 100644 --- a/test_programs/execution_success/slice_dynamic_index/src/main.nr +++ b/test_programs/execution_success/slice_dynamic_index/src/main.nr @@ -4,7 +4,7 @@ fn main(x: Field) { } fn regression_dynamic_slice_index(x: Field, y: Field) { - let mut slice = []; + let mut slice = &[]; for i in 0..5 { slice = slice.push_back(i as Field); } @@ -124,12 +124,12 @@ fn dynamic_slice_merge_if(mut slice: [Field], x: Field) { assert(first_elem == 12); assert(rest_of_slice.len() == 6); - slice = rest_of_slice.insert(x as u64 - 2, 20); + slice = rest_of_slice.insert(x as u32 - 2, 20); assert(slice[2] == 20); assert(slice[6] == 30); assert(slice.len() == 7); - let (removed_slice, removed_elem) = slice.remove(x as u64 - 1); + let (removed_slice, removed_elem) = slice.remove(x as u32 - 1); // The deconstructed tuple assigns to the slice but is not seen outside of the if statement // without a direct assignment slice = removed_slice; diff --git a/test_programs/execution_success/slice_loop/Nargo.toml b/test_programs/execution_success/slice_loop/Nargo.toml new file mode 100644 index 00000000000..09ad90c4187 --- /dev/null +++ b/test_programs/execution_success/slice_loop/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "slice_loop" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/slice_loop/Prover.toml b/test_programs/execution_success/slice_loop/Prover.toml new file mode 100644 index 00000000000..089a1764b54 --- /dev/null +++ b/test_programs/execution_success/slice_loop/Prover.toml @@ -0,0 +1,11 @@ +[[points]] +x = "1" +y = "2" + +[[points]] +x = "3" +y = "4" + +[[points]] +x = "5" +y = "6" diff --git a/test_programs/execution_success/slice_loop/src/main.nr b/test_programs/execution_success/slice_loop/src/main.nr new file mode 100644 index 00000000000..4ff3e865b1f --- /dev/null +++ b/test_programs/execution_success/slice_loop/src/main.nr @@ -0,0 +1,32 @@ +struct Point { + x: Field, + y: Field, +} + +impl Point { + fn serialize(self) -> [Field; 2] { + [self.x, self.y] + } +} + +fn sum(values: [Field]) -> Field { + let mut sum = 0; + for value in values { + sum = sum + value; + } + sum +} + +fn main(points: [Point; 3]) { + let mut serialized_points = &[]; + for point in points { + serialized_points = serialized_points.append(point.serialize().as_slice()); + } + // Do a compile-time check that needs the previous loop to be unrolled + if serialized_points.len() > 5 { + let empty_point = Point { x: 0, y: 0 }; + serialized_points = serialized_points.append(empty_point.serialize().as_slice()); + } + // Do a sum that needs both the previous loop and the previous if to have been simplified + assert_eq(sum(serialized_points), 21); +} diff --git a/test_programs/execution_success/slices/src/main.nr b/test_programs/execution_success/slices/src/main.nr index eca42a660c4..b20e3478898 100644 --- a/test_programs/execution_success/slices/src/main.nr +++ b/test_programs/execution_success/slices/src/main.nr @@ -2,7 +2,7 @@ use dep::std::slice; use dep::std; fn main(x: Field, y: pub Field) { - let mut slice = [0; 2]; + let mut slice = &[0; 2]; assert(slice[0] == 0); assert(slice[0] != 1); slice[0] = x; @@ -13,7 +13,7 @@ fn main(x: Field, y: pub Field) { assert(slice_plus_10[2] != 8); assert(slice_plus_10.len() == 3); - let mut new_slice = []; + let mut new_slice = &[]; for i in 0..5 { new_slice = new_slice.push_back(i); } @@ -41,7 +41,7 @@ fn main(x: Field, y: pub Field) { assert(remove_slice[3] == 3); assert(remove_slice.len() == 4); - let append = [1, 2].append([3, 4, 5]); + let append = &[1, 2].append(&[3, 4, 5]); assert(append.len() == 5); assert(append[0] == 1); assert(append[4] == 5); @@ -50,10 +50,15 @@ fn main(x: Field, y: pub Field) { // The parameters to this function must come from witness values (inputs to main) regression_merge_slices(x, y); regression_2370(); + + regression_4418(x); + regression_slice_call_result(x, y); + regression_4506(); } + // Ensure that slices of struct/tuple values work. fn regression_2083() { - let y = [(1, 2)]; + let y = &[(1, 2)]; let y = y.push_back((3, 4)); // [(1, 2), (3, 4)] let y = y.push_back((5, 6)); // [(1, 2), (3, 4), (5, 6)] assert(y[2].1 == 6); @@ -82,6 +87,7 @@ 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); @@ -142,18 +148,20 @@ 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]; + let slice = &[0; 2]; if x != y { 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]; + let mut slice = &[0; 2]; if x != y { slice = slice.push_back(y); slice = slice.push_back(x); @@ -162,9 +170,10 @@ 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]; + let mut slice = &[0; 2]; if x != y { for i in 0..5 { slice = slice.push_back(i as Field); @@ -176,7 +185,7 @@ fn merge_slices_mutate_in_loop(x: Field, y: Field) -> [Field] { } fn merge_slices_mutate_two_ifs(x: Field, y: Field) -> [Field] { - let mut slice = [0; 2]; + let mut slice = &[0; 2]; if x != y { slice = slice.push_back(y); slice = slice.push_back(x); @@ -195,7 +204,7 @@ fn merge_slices_mutate_two_ifs(x: Field, y: Field) -> [Field] { } fn merge_slices_mutate_between_ifs(x: Field, y: Field) -> [Field] { - let mut slice = [0; 2]; + let mut slice = &[0; 2]; if x != y { slice = slice.push_back(y); slice = slice.push_back(x); @@ -221,7 +230,7 @@ fn merge_slices_mutate_between_ifs(x: Field, y: Field) -> [Field] { } fn merge_slices_push_then_pop(x: Field, y: Field) { - let mut slice = [0; 2]; + let mut slice = &[0; 2]; if x != y { slice = slice.push_back(y); slice = slice.push_back(x); @@ -245,7 +254,7 @@ fn merge_slices_push_then_pop(x: Field, y: Field) { } fn merge_slices_push_then_insert(x: Field, y: Field) -> [Field] { - let mut slice = [0; 2]; + let mut slice = &[0; 2]; if x != y { slice = slice.push_back(y); slice = slice.push_back(x); @@ -268,7 +277,7 @@ fn merge_slices_push_then_insert(x: Field, y: Field) -> [Field] { } fn merge_slices_remove_between_ifs(x: Field, y: Field) -> [Field] { - let mut slice = [0; 2]; + let mut slice = &[0; 2]; if x != y { slice = slice.push_back(y); slice = slice.push_back(x); @@ -294,6 +303,35 @@ fn merge_slices_remove_between_ifs(x: Field, y: Field) -> [Field] { // 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() { - let mut slice = []; - slice = [1, 2, 3]; + let mut slice = &[]; + slice = &[1, 2, 3]; +} + +fn regression_4418(x: Field) { + let mut crash = x.to_be_bytes(32); + + if x != 0 { + crash[0] = 10; + } +} + +fn regression_slice_call_result(x: Field, y: Field) { + let mut slice = merge_slices_return(x, y); + if x != 0 { + slice = slice.push_back(5); + slice = slice.push_back(10); + } else { + slice = slice.push_back(5); + } + assert(slice.len() == 5); + assert(slice[0] == 0); + assert(slice[1] == 0); + assert(slice[2] == 10); + assert(slice[3] == 5); + assert(slice[4] == 10); +} + +fn regression_4506() { + let slice: [Field] = &[1, 2, 3]; + assert(slice == slice); } diff --git a/test_programs/execution_success/to_bits/Nargo.toml b/test_programs/execution_success/to_bits/Nargo.toml new file mode 100644 index 00000000000..ef47f3b4ba1 --- /dev/null +++ b/test_programs/execution_success/to_bits/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "to_bits" +type = "bin" +authors = [""] +[dependencies] diff --git a/test_programs/execution_success/brillig_to_bits/src/main.nr b/test_programs/execution_success/to_bits/src/main.nr similarity index 94% rename from test_programs/execution_success/brillig_to_bits/src/main.nr rename to test_programs/execution_success/to_bits/src/main.nr index 7ff3d2467b5..18f65f0bd66 100644 --- a/test_programs/execution_success/brillig_to_bits/src/main.nr +++ b/test_programs/execution_success/to_bits/src/main.nr @@ -1,6 +1,6 @@ use dep::std; -unconstrained fn main() { +fn main() { let field = 1000; let be_bits = field.to_be_bits(16); let le_bits = field.to_le_bits(16); diff --git a/test_programs/execution_success/trait_method_mut_self/Nargo.toml b/test_programs/execution_success/trait_method_mut_self/Nargo.toml new file mode 100644 index 00000000000..d2fe9e8e137 --- /dev/null +++ b/test_programs/execution_success/trait_method_mut_self/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "trait_method_mut_self" +type = "bin" +authors = [""] +compiler_version = ">=0.29.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/trait_method_mut_self/Prover.toml b/test_programs/execution_success/trait_method_mut_self/Prover.toml new file mode 100644 index 00000000000..f28f2f8cc48 --- /dev/null +++ b/test_programs/execution_success/trait_method_mut_self/Prover.toml @@ -0,0 +1,2 @@ +x = "5" +y = "10" diff --git a/test_programs/execution_success/trait_method_mut_self/src/main.nr b/test_programs/execution_success/trait_method_mut_self/src/main.nr new file mode 100644 index 00000000000..fa47fd5d881 --- /dev/null +++ b/test_programs/execution_success/trait_method_mut_self/src/main.nr @@ -0,0 +1,74 @@ +use dep::std::hash::Hasher; +use dep::std::hash::poseidon2::Poseidon2Hasher; + +fn main(x: Field, y: pub Field) { + let mut a_mut_ref = AType { x }; + + pass_trait_by_value(a_mut_ref, y); + assert(a_mut_ref.x == x); + + pass_trait_by_value_impl_param(a_mut_ref, y); + assert(a_mut_ref.x == x); + + pass_trait_by_mut_ref(&mut a_mut_ref, y); + assert(a_mut_ref.x == y); + + let mut hasher = Poseidon2Hasher::default(); + hasher.write(x); + hasher.write(y); + let expected_hash = hasher.finish(); + // Check that we get the same result when using the hasher in a + // method that purely uses trait methods without a supplied implementation. + assert(hash_simple_array::([x, y]) == expected_hash); +} + +trait SomeTrait { + fn set_value(&mut self, new_value: Field) -> (); + + fn get_value(self) -> Field; +} + +struct AType { + x: Field +} + +impl SomeTrait for AType { + fn set_value(&mut self, new_value: Field) -> () { + self.x = new_value; + } + + fn get_value(self) -> Field { + self.x + } +} + +fn pass_trait_by_value_impl_param(mut a_mut_ref: impl SomeTrait, value: Field) { + // We auto add a mutable reference to the object type if the method call expects a mutable self + a_mut_ref.set_value(value); + assert(a_mut_ref.get_value() == value); +} + +fn pass_trait_by_value(mut a_mut_ref: T, value: Field) where T: SomeTrait { + // We auto add a mutable reference to the object type if the method call expects a mutable self + a_mut_ref.set_value(value); + assert(a_mut_ref.get_value() == value); +} + +fn pass_trait_by_mut_ref(a_mut_ref: &mut T, value: Field) where T: SomeTrait { + // We auto add a mutable reference to the object type if the method call expects a mutable self + a_mut_ref.set_value(value); +} + +fn hash_simple_array(input: [Field; 2]) -> Field where H: Hasher + Default { + // Check that we can call a trait method instead of a trait implementation + // TODO: Need to remove the need for this type annotation + // TODO: Curently, without the annotation we will get `Expression type is ambiguous` when trying to use the `hasher` + let mut hasher: H = H::default(); + // Regression that the object is converted to a mutable reference type `&mut _`. + // Otherwise will see `Expected type &mut _, found type H`. + // Then we need to make sure to also auto dereference later in the type checking process + // when searching for a matching impl or else we will get `No matching impl found for `&mut H: Hasher` + hasher.write(input[0]); + hasher.write(input[1]); + hasher.finish() +} diff --git a/test_programs/execution_success/turbofish_call_func_diff_types/Nargo.toml b/test_programs/execution_success/turbofish_call_func_diff_types/Nargo.toml new file mode 100644 index 00000000000..8624cda646b --- /dev/null +++ b/test_programs/execution_success/turbofish_call_func_diff_types/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "turbofish_call_func_diff_types" +type = "bin" +authors = [""] +compiler_version = ">=0.29.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/turbofish_call_func_diff_types/Prover.toml b/test_programs/execution_success/turbofish_call_func_diff_types/Prover.toml new file mode 100644 index 00000000000..f28f2f8cc48 --- /dev/null +++ b/test_programs/execution_success/turbofish_call_func_diff_types/Prover.toml @@ -0,0 +1,2 @@ +x = "5" +y = "10" diff --git a/test_programs/execution_success/turbofish_call_func_diff_types/src/main.nr b/test_programs/execution_success/turbofish_call_func_diff_types/src/main.nr new file mode 100644 index 00000000000..b880d3ae047 --- /dev/null +++ b/test_programs/execution_success/turbofish_call_func_diff_types/src/main.nr @@ -0,0 +1,34 @@ +use dep::std::hash::Hasher; +use dep::std::hash::poseidon2::Poseidon2Hasher; +use dep::std::hash::poseidon::PoseidonHasher; + +fn main(x: Field, y: pub Field) { + let mut hasher = PoseidonHasher::default(); + hasher.write(x); + hasher.write(y); + let poseidon_expected_hash = hasher.finish(); + // Check that we get the same result when using the hasher in a + // method that purely uses trait methods without a supplied implementation. + assert(hash_simple_array::([x, y]) == poseidon_expected_hash); + + // Now let's do the same logic but with a different `Hasher` supplied to the turbofish operator + // We want to make sure that we have correctly monomorphized a function with a trait generic + // where the generic is not used on any function parameters or the return value. + let mut hasher = Poseidon2Hasher::default(); + hasher.write(x); + hasher.write(y); + let poseidon2_expected_hash = hasher.finish(); + assert(hash_simple_array::([x, y]) == poseidon2_expected_hash); +} + +fn hash_simple_array(input: [Field; 2]) -> Field where H: Hasher + Default { + // Check that we can call a trait method instead of a trait implementation + let mut hasher = H::default(); + // Regression that the object is converted to a mutable reference type `&mut _`. + // Otherwise will see `Expected type &mut _, found type H`. + // Then we need to make sure to also auto dereference later in the type checking process + // when searching for a matching impl or else we will get `No matching impl found for `&mut H: Hasher` + hasher.write(input[0]); + hasher.write(input[1]); + hasher.finish() +} diff --git a/test_programs/execution_success/u128/src/main.nr b/test_programs/execution_success/u128/src/main.nr index dc586408795..a403571ea74 100644 --- a/test_programs/execution_success/u128/src/main.nr +++ b/test_programs/execution_success/u128/src/main.nr @@ -34,11 +34,11 @@ fn main(mut x: u32, y: u32, z: u32, big_int: U128, hexa: str<7>) { let mut small_int = U128::from_integer(x); assert(small_int.lo == x as Field); assert(x == small_int.to_integer()); - let shift = small_int << small_int; - assert(shift == U128::from_integer(x << x)); - assert(shift >> small_int == small_int); - assert(shift >> U128::from_integer(127) == U128::from_integer(0)); - assert(shift << U128::from_integer(127) == U128::from_integer(0)); + let shift = small_int << (x as u8); + assert(shift == U128::from_integer(x << (x as u8))); + assert(shift >> (x as u8) == small_int); + assert(shift >> 127 == U128::from_integer(0)); + assert(shift << 127 == U128::from_integer(0)); assert(U128::from_integer(3).to_integer() == 3); } diff --git a/test_programs/execution_success/u16_support/Nargo.toml b/test_programs/execution_success/u16_support/Nargo.toml new file mode 100644 index 00000000000..1c6b58e01e8 --- /dev/null +++ b/test_programs/execution_success/u16_support/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "u16_support" +type = "bin" +authors = [""] +compiler_version = ">=0.29.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/u16_support/Prover.toml b/test_programs/execution_success/u16_support/Prover.toml new file mode 100644 index 00000000000..a56a84e61a4 --- /dev/null +++ b/test_programs/execution_success/u16_support/Prover.toml @@ -0,0 +1 @@ +x = "2" diff --git a/test_programs/execution_success/u16_support/src/main.nr b/test_programs/execution_success/u16_support/src/main.nr new file mode 100644 index 00000000000..ca41c708077 --- /dev/null +++ b/test_programs/execution_success/u16_support/src/main.nr @@ -0,0 +1,26 @@ +fn main(x: u16) { + test_u16(x); + unsafe { + test_u16_unconstrained(x); + } +} + +unconstrained fn test_u16_unconstrained(x: u16) { + test_u16(x) +} + +fn test_u16(x: u16) { + let t1: u16 = 1234; + let t2: u16 = 4321; + let t = t1 + t2; + + let t4 = t - t2; + assert(t4 == t1); + + let mut small_int = x as u16; + let shift = small_int << (x as u8); + assert(shift == 8); + assert(shift >> (x as u8) == small_int); + assert(shift >> 15 == 0); + assert(shift << 15 == 0); +} diff --git a/test_programs/execution_success/unconstrained_empty/Nargo.toml b/test_programs/execution_success/unconstrained_empty/Nargo.toml deleted file mode 100644 index 48d0f5938d8..00000000000 --- a/test_programs/execution_success/unconstrained_empty/Nargo.toml +++ /dev/null @@ -1,5 +0,0 @@ -[package] -name = "unconstrained_empty" -type = "bin" -authors = [""] -[dependencies] diff --git a/test_programs/execution_success/unconstrained_empty/src/main.nr b/test_programs/execution_success/unconstrained_empty/src/main.nr deleted file mode 100644 index 5e5fb297236..00000000000 --- a/test_programs/execution_success/unconstrained_empty/src/main.nr +++ /dev/null @@ -1 +0,0 @@ -unconstrained fn main() {} diff --git a/test_programs/execution_success/unit_value/Nargo.toml b/test_programs/execution_success/unit_value/Nargo.toml new file mode 100644 index 00000000000..1f9c4524ec5 --- /dev/null +++ b/test_programs/execution_success/unit_value/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "unit_value" +type = "bin" +authors = [""] +compiler_version = ">=0.23.0" + +[dependencies] diff --git a/test_programs/execution_success/unit_value/src/main.nr b/test_programs/execution_success/unit_value/src/main.nr new file mode 100644 index 00000000000..f3844e03cf2 --- /dev/null +++ b/test_programs/execution_success/unit_value/src/main.nr @@ -0,0 +1,7 @@ +fn get_transaction() { + dep::std::unsafe::zeroed() +} + +fn main() { + get_transaction(); +} diff --git a/test_programs/execution_success/witness_compression/Nargo.toml b/test_programs/execution_success/witness_compression/Nargo.toml new file mode 100644 index 00000000000..7d6ba0c1938 --- /dev/null +++ b/test_programs/execution_success/witness_compression/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "witness_compression" +type = "bin" +authors = [""] +compiler_version = ">=0.24.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/workspace_missing_toml/crates/b/Prover.toml b/test_programs/execution_success/witness_compression/Prover.toml similarity index 50% rename from test_programs/compile_failure/workspace_missing_toml/crates/b/Prover.toml rename to test_programs/execution_success/witness_compression/Prover.toml index a0397e89477..8c12ebba6cf 100644 --- a/test_programs/compile_failure/workspace_missing_toml/crates/b/Prover.toml +++ b/test_programs/execution_success/witness_compression/Prover.toml @@ -1,2 +1,2 @@ x = "1" -y = "0" +y = "2" diff --git a/test_programs/execution_success/witness_compression/src/main.nr b/test_programs/execution_success/witness_compression/src/main.nr new file mode 100644 index 00000000000..3027d35b13a --- /dev/null +++ b/test_programs/execution_success/witness_compression/src/main.nr @@ -0,0 +1,7 @@ +// This test should be used to regenerate the serialized witness used in the `acvm_js` integration tests. +// The `acvm_js` test file containing the serialized witness should be also called `witness_compression`. +// After recompiling Noir, you can manually print the witness byte array to be written to file after execution. +fn main(x: Field, y: pub Field) -> pub Field { + assert(x != y); + x + y +} diff --git a/test_programs/execution_success/workspace/Prover.toml b/test_programs/execution_success/workspace/Prover.toml deleted file mode 100644 index a0397e89477..00000000000 --- a/test_programs/execution_success/workspace/Prover.toml +++ /dev/null @@ -1,2 +0,0 @@ -x = "1" -y = "0" diff --git a/test_programs/execution_success/wrapping_operations/Nargo.toml b/test_programs/execution_success/wrapping_operations/Nargo.toml new file mode 100644 index 00000000000..3a28b3461ec --- /dev/null +++ b/test_programs/execution_success/wrapping_operations/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "wrapping_operations" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/wrapping_operations/Prover.toml b/test_programs/execution_success/wrapping_operations/Prover.toml new file mode 100644 index 00000000000..346fd2764a7 --- /dev/null +++ b/test_programs/execution_success/wrapping_operations/Prover.toml @@ -0,0 +1,2 @@ +x = 0 +y = 255 diff --git a/test_programs/execution_success/wrapping_operations/src/main.nr b/test_programs/execution_success/wrapping_operations/src/main.nr new file mode 100644 index 00000000000..85fd65b193c --- /dev/null +++ b/test_programs/execution_success/wrapping_operations/src/main.nr @@ -0,0 +1,8 @@ +use dep::std; + +fn main(x: u8, y: u8) { + assert(std::wrapping_sub(x, 1) == y); + assert(std::wrapping_add(y, 1) == x); + assert(std::wrapping_mul(y, y) == 1); +} + diff --git a/test_programs/gates_report.sh b/test_programs/gates_report.sh index 3b0b4d9e148..b33e81b037c 100755 --- a/test_programs/gates_report.sh +++ b/test_programs/gates_report.sh @@ -1,36 +1,37 @@ #!/usr/bin/env bash set -e +BACKEND=${BACKEND:-bb} + # These tests are incompatible with gas reporting excluded_dirs=("workspace" "workspace_default_member" "double_verify_nested_proof") -# These tests cause failures in CI with a stack overflow for some reason. -ci_excluded_dirs=("eddsa") - current_dir=$(pwd) -base_path="$current_dir/execution_success" -test_dirs=$(ls $base_path) +artifacts_path="$current_dir/acir_artifacts" +test_dirs=$(ls $artifacts_path) -# We generate a Noir workspace which contains all of the test cases -# This allows us to generate a gates report using `nargo info` for all of them at once. +echo "{\"programs\": [" > gates_report.json -echo "[workspace]" > Nargo.toml -echo "members = [" >> Nargo.toml +# Bound for checking where to place last parentheses +NUM_ARTIFACTS=$(ls -1q "$artifacts_path" | wc -l) -for dir in $test_dirs; do - if [[ " ${excluded_dirs[@]} " =~ " ${dir} " ]]; then - continue - fi +ITER="1" +for pathname in $test_dirs; do + ARTIFACT_NAME=$(basename "$pathname") + + GATES_INFO=$($BACKEND gates -b "$artifacts_path/$ARTIFACT_NAME/target/program.json") + MAIN_FUNCTION_INFO=$(echo $GATES_INFO | jq -r '.functions[0] | .name = "main"') + echo "{\"package_name\": \"$ARTIFACT_NAME\", \"functions\": [$MAIN_FUNCTION_INFO]" >> gates_report.json - if [[ ${CI-false} = "true" ]] && [[ " ${ci_excluded_dirs[@]} " =~ " ${dir} " ]]; then - continue + if (($ITER == $NUM_ARTIFACTS)); then + echo "}" >> gates_report.json + else + echo "}, " >> gates_report.json fi - echo " \"execution_success/$dir\"," >> Nargo.toml + ITER=$(( $ITER + 1 )) done -echo "]" >> Nargo.toml +echo "]}" >> gates_report.json -nargo info --json > gates_report.json -rm Nargo.toml diff --git a/test_programs/noir_test_failure/should_fail_suite_with_one_failure/Nargo.toml b/test_programs/noir_test_failure/should_fail_suite_with_one_failure/Nargo.toml new file mode 100644 index 00000000000..3d2cf2c6096 --- /dev/null +++ b/test_programs/noir_test_failure/should_fail_suite_with_one_failure/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "should_fail_with_mismatch" +type = "bin" +authors = [""] +[dependencies] diff --git a/test_programs/compile_failure/dup_trait_implementation_5/Prover.toml b/test_programs/noir_test_failure/should_fail_suite_with_one_failure/Prover.toml similarity index 100% rename from test_programs/compile_failure/dup_trait_implementation_5/Prover.toml rename to test_programs/noir_test_failure/should_fail_suite_with_one_failure/Prover.toml diff --git a/test_programs/noir_test_failure/should_fail_suite_with_one_failure/src/main.nr b/test_programs/noir_test_failure/should_fail_suite_with_one_failure/src/main.nr new file mode 100644 index 00000000000..8ed9003164a --- /dev/null +++ b/test_programs/noir_test_failure/should_fail_suite_with_one_failure/src/main.nr @@ -0,0 +1,11 @@ +/// Test to make sure the entire test suite fails, even if some of the tests pass! + +#[test] +fn this_will_pass() { + assert(true); +} + +#[test] +fn this_will_fail() { + assert(false); +} diff --git a/test_programs/noir_test_success/bounded_vec/Prover.toml b/test_programs/noir_test_success/bounded_vec/Prover.toml deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/test_programs/noir_test_success/bounded_vec/src/main.nr b/test_programs/noir_test_success/bounded_vec/src/main.nr index 0e2c89c9064..22ec291f9d6 100644 --- a/test_programs/noir_test_success/bounded_vec/src/main.nr +++ b/test_programs/noir_test_success/bounded_vec/src/main.nr @@ -1,3 +1,31 @@ +#[test] +fn test_vec_new_foo() { + foo(); +} + +#[test(should_fail)] +fn test_vec_new_bad() { + bad(); +} + +// docs:start:new_example +fn foo() -> BoundedVec { + // Ok! MaxLen is specified with a type annotation + let v1: BoundedVec = BoundedVec::new(); + let v2 = BoundedVec::new(); + + // Ok! MaxLen is known from the type of foo's return value + v2 +} + +fn bad() { + let mut v3 = BoundedVec::new(); + + // Not Ok! We don't know if v3's MaxLen is at least 1, and the compiler often infers 0 by default. + v3.push(5); +} +// docs:end:new_example + #[test] fn test_vec_push_pop() { let mut vec: BoundedVec = BoundedVec::new(); @@ -15,13 +43,123 @@ fn test_vec_push_pop() { assert(vec.get(1) == 4); } +#[test] +fn test_vec_get_unchecked() { + let mut vec: BoundedVec = BoundedVec::new(); + vec.extend_from_array([1, 2, 3, 4]); + let sum = sum_of_first_three(vec); + assert_eq(sum, 6); +} + +// docs:start:get_unchecked_example +fn sum_of_first_three(v: BoundedVec) -> u32 { + // Always ensure the length is larger than the largest + // index passed to get_unchecked + assert(v.len() > 2); + let first = v.get_unchecked(0); + let second = v.get_unchecked(1); + let third = v.get_unchecked(2); + first + second + third +} +// docs:end:get_unchecked_example + +#[test(should_fail_with = "push out of bounds")] +fn push_docs_example() { + // docs:start:bounded-vec-push-example + let mut v: BoundedVec = BoundedVec::new(); + + v.push(1); + v.push(2); + + // Panics with failed assertion "push out of bounds" + v.push(3); + // docs:end:bounded-vec-push-example +} + +#[test] +fn pop_docs_example() { + // docs:start:bounded-vec-pop-example + let mut v: BoundedVec = BoundedVec::new(); + v.push(1); + v.push(2); + + let two = v.pop(); + let one = v.pop(); + + assert(two == 2); + assert(one == 1); + // error: cannot pop from an empty vector + // let _ = v.pop(); + // docs:end:bounded-vec-pop-example +} + +#[test] +fn len_docs_example() { + // docs:start:bounded-vec-len-example + let mut v: BoundedVec = BoundedVec::new(); + assert(v.len() == 0); + + v.push(100); + assert(v.len() == 1); + + v.push(200); + v.push(300); + v.push(400); + assert(v.len() == 4); + + let _ = v.pop(); + let _ = v.pop(); + assert(v.len() == 2); + // docs:end:bounded-vec-len-example +} + +#[test] +fn max_len_docs_example() { + // docs:start:bounded-vec-max-len-example + let mut v: BoundedVec = BoundedVec::new(); + + assert(v.max_len() == 5); + v.push(10); + assert(v.max_len() == 5); + // docs:end:bounded-vec-max-len-example +} + +#[test] +fn storage_docs_example() { + // docs:start:bounded-vec-storage-example + let mut v: BoundedVec = BoundedVec::new(); + + assert(v.storage() == [0, 0, 0, 0, 0]); + + v.push(57); + assert(v.storage() == [57, 0, 0, 0, 0]); + // docs:end:bounded-vec-storage-example +} + #[test] fn test_vec_extend_from_array() { + // docs:start:bounded-vec-extend-from-array-example let mut vec: BoundedVec = BoundedVec::new(); vec.extend_from_array([2, 4]); + assert(vec.len == 2); assert(vec.get(0) == 2); assert(vec.get(1) == 4); + // docs:end:bounded-vec-extend-from-array-example +} + +#[test] +fn test_vec_extend_from_bounded_vec() { + // docs:start:bounded-vec-extend-from-bounded-vec-example + let mut v1: BoundedVec = BoundedVec::new(); + let mut v2: BoundedVec = BoundedVec::new(); + + v2.extend_from_array([1, 2, 3]); + v1.extend_from_bounded_vec(v2); + + assert(v1.storage() == [1, 2, 3, 0, 0]); + assert(v2.storage() == [1, 2, 3, 0, 0, 0, 0]); + // docs:end:bounded-vec-extend-from-bounded-vec-example } #[test(should_fail_with="extend_from_array out of bounds")] @@ -88,12 +226,13 @@ fn test_vec_extend_from_bounded_vec_twice_out_of_bound() { #[test] fn test_vec_any() { - let mut vec: BoundedVec = BoundedVec::new(); - vec.extend_from_array([2, 4, 6]); - assert(vec.any(|v| v == 2) == true); - assert(vec.any(|v| v == 4) == true); - assert(vec.any(|v| v == 6) == true); - assert(vec.any(|v| v == 3) == false); + // docs:start:bounded-vec-any-example + let mut v: BoundedVec = BoundedVec::new(); + v.extend_from_array([2, 4, 6]); + + let all_even = !v.any(|elem: u32| elem % 2 != 0); + assert(all_even); + // docs:end:bounded-vec-any-example } #[test] @@ -101,5 +240,6 @@ fn test_vec_any_not_default() { let default_value = 0; let mut vec: BoundedVec = BoundedVec::new(); vec.extend_from_array([2, 4]); - assert(vec.any(|v| v == default_value) == false); + assert(!vec.any(|v| v == default_value)); } + diff --git a/test_programs/noir_test_success/brillig_overflow_checks/Nargo.toml b/test_programs/noir_test_success/brillig_overflow_checks/Nargo.toml new file mode 100644 index 00000000000..b2d47d258ed --- /dev/null +++ b/test_programs/noir_test_success/brillig_overflow_checks/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "brillig_overflow_checks" +type = "bin" +authors = [""] +[dependencies] diff --git a/test_programs/noir_test_success/brillig_overflow_checks/src/main.nr b/test_programs/noir_test_success/brillig_overflow_checks/src/main.nr new file mode 100644 index 00000000000..5d73ef96d49 --- /dev/null +++ b/test_programs/noir_test_success/brillig_overflow_checks/src/main.nr @@ -0,0 +1,23 @@ +use dep::std::field::bn254::{TWO_POW_128, assert_gt}; + +#[test(should_fail_with = "attempt to add with overflow")] +unconstrained fn test_overflow_add() { + let a: u8 = 255; + let b: u8 = 1; + assert_eq(a + b, 0); +} + +#[test(should_fail_with = "attempt to subtract with overflow")] +unconstrained fn test_overflow_sub() { + let a: u8 = 0; + let b: u8 = 1; + assert_eq(a - b, 255); +} + +#[test(should_fail_with = "attempt to multiply with overflow")] +unconstrained fn test_overflow_mul() { + let a: u8 = 128; + let b: u8 = 2; + assert_eq(a * b, 0); +} + diff --git a/test_programs/noir_test_success/comptime_globals/Nargo.toml b/test_programs/noir_test_success/comptime_globals/Nargo.toml new file mode 100644 index 00000000000..d4f349f537a --- /dev/null +++ b/test_programs/noir_test_success/comptime_globals/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "comptime_globals" +type = "bin" +authors = [""] +compiler_version = ">=0.27.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/noir_test_success/comptime_globals/src/main.nr b/test_programs/noir_test_success/comptime_globals/src/main.nr new file mode 100644 index 00000000000..efe9f0742b9 --- /dev/null +++ b/test_programs/noir_test_success/comptime_globals/src/main.nr @@ -0,0 +1,21 @@ +// Normal globals can be evaluated in a comptime context too, +// but comptime globals can only be evaluated in a comptime context. +comptime global FOO: Field = foo(); + +// Due to this function's mutability and branching, SSA currently fails +// to fold this function into a constant before the assert_constant check +// is evaluated before loop unrolling. +fn foo() -> Field { + let mut three = 3; + if three == 3 { 5 } else { 6 } +} + +#[test] +fn foo_global_constant() { + assert_constant(FOO); +} + +#[test(should_fail)] +fn foo_function_not_constant() { + assert_constant(foo()); +} diff --git a/test_programs/noir_test_success/embedded_curve_ops/Nargo.toml b/test_programs/noir_test_success/embedded_curve_ops/Nargo.toml new file mode 100644 index 00000000000..65e6efea538 --- /dev/null +++ b/test_programs/noir_test_success/embedded_curve_ops/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "embedded_curve_ops" +type = "bin" +authors = [""] +compiler_version = ">=0.23.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/noir_test_success/embedded_curve_ops/src/main.nr b/test_programs/noir_test_success/embedded_curve_ops/src/main.nr new file mode 100644 index 00000000000..9e3c5d87874 --- /dev/null +++ b/test_programs/noir_test_success/embedded_curve_ops/src/main.nr @@ -0,0 +1,37 @@ +use dep::std::embedded_curve_ops::{EmbeddedCurvePoint, EmbeddedCurveScalar, multi_scalar_mul}; + +#[test] + + fn test_infinite_point() { + let zero = EmbeddedCurvePoint::point_at_infinity(); + let zero = EmbeddedCurvePoint { x: 0, y: 0, is_infinite: true }; + let g1 = EmbeddedCurvePoint { x: 1, y: 17631683881184975370165255887551781615748388533673675138860, is_infinite: false }; + let g2 = g1 + g1; + + let s1 = EmbeddedCurveScalar { lo: 1, hi: 0 }; + let a = multi_scalar_mul([g1], [s1]); + assert(a[2] == 0); + assert(g1 + zero == g1); + assert(g1 - g1 == zero); + assert(g1 - zero == g1); + assert(zero + zero == zero); + assert( + multi_scalar_mul([g1], [s1]) + == [1, 17631683881184975370165255887551781615748388533673675138860, 0] + ); + assert(multi_scalar_mul([g1, g1], [s1, s1]) == [g2.x, g2.y, 0]); + assert( + multi_scalar_mul( + [g1, zero], + [EmbeddedCurveScalar { lo: 2, hi: 0 }, EmbeddedCurveScalar { lo: 42, hi: 25 }] + ) + == [g2.x, g2.y, 0] + ); + assert( + multi_scalar_mul( + [g1, g1, zero], + [s1, s1, EmbeddedCurveScalar { lo: 42, hi: 25 }] + ) + == [g2.x, g2.y, 0] + ); +} diff --git a/test_programs/noir_test_success/field_comparisons/Prover.toml b/test_programs/noir_test_success/field_comparisons/Prover.toml deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/test_programs/noir_test_success/ignored_oracle/Nargo.toml b/test_programs/noir_test_success/ignored_oracle/Nargo.toml new file mode 100644 index 00000000000..0d9b77c01d7 --- /dev/null +++ b/test_programs/noir_test_success/ignored_oracle/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "ignored_oracle" +type = "bin" +authors = [""] +compiler_version = ">=0.23.0" + +[dependencies] diff --git a/test_programs/noir_test_success/ignored_oracle/src/main.nr b/test_programs/noir_test_success/ignored_oracle/src/main.nr new file mode 100644 index 00000000000..9e0bc189939 --- /dev/null +++ b/test_programs/noir_test_success/ignored_oracle/src/main.nr @@ -0,0 +1,23 @@ +// In `nargo test` we want to avoid the need for an external oracle resolver service to be required in the situation +// where its existence doesn't affect whether the tests will pass or fail. We then want to be able to handle any +// oracles which return zero field elements. + +// Note that this custom oracle doesn't return any new values into the program. +// We can then safely continue execution even in the case where there is no oracle resolver to handle it. +#[oracle(custom_debug)] +unconstrained fn custom_debug() {} + +// However this oracle call should return a field element. We expect the ACVM to raise an error when it +// doesn't receive this value. +#[oracle(custom_getter)] +unconstrained fn custom_getter() -> Field {} + +#[test] +unconstrained fn unit_return_oracle_ignored() { + custom_debug(); +} + +#[test(should_fail_with = "0 output values were provided as a foreign call result for 1 destination slots")] +unconstrained fn field_return_oracle_fails() { + let _ = custom_getter(); +} diff --git a/test_programs/noir_test_success/mock_oracle/Nargo.toml b/test_programs/noir_test_success/mock_oracle/Nargo.toml new file mode 100644 index 00000000000..428e965899c --- /dev/null +++ b/test_programs/noir_test_success/mock_oracle/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "mock_oracle" +type = "bin" +authors = [""] +compiler_version = ">=0.23.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/noir_test_success/mock_oracle/src/main.nr b/test_programs/noir_test_success/mock_oracle/src/main.nr new file mode 100644 index 00000000000..d840ffaef66 --- /dev/null +++ b/test_programs/noir_test_success/mock_oracle/src/main.nr @@ -0,0 +1,130 @@ +use dep::std::test::OracleMock; + +struct Point { + x: Field, + y: Field, +} + +impl Eq for Point { + fn eq(self, other: Point) -> bool { + (self.x == other.x) & (self.y == other.y) + } +} + +#[oracle(void_field)] +unconstrained fn void_field_oracle() -> Field {} + +unconstrained fn void_field() -> Field { + void_field_oracle() +} + +#[oracle(field_field)] +unconstrained fn field_field_oracle(_x: Field) -> Field {} + +unconstrained fn field_field(x: Field) -> Field { + field_field_oracle(x) +} + +#[oracle(struct_field)] +unconstrained fn struct_field_oracle(_point: Point, _array: [Field; 4]) -> Field {} + +unconstrained fn struct_field(point: Point, array: [Field; 4]) -> Field { + struct_field_oracle(point, array) +} + +#[test(should_fail)] +fn test_mock_no_returns() { + OracleMock::mock("void_field"); + void_field(); // Some return value must be set +} + +#[test] +fn test_mock() { + OracleMock::mock("void_field").returns(10); + assert_eq(void_field(), 10); +} + +#[test] +fn test_multiple_mock() { + let first_mock = OracleMock::mock("void_field").returns(10); + OracleMock::mock("void_field").returns(42); + + // The mocks are searched for in creation order, so the first one prevents the second from being called. + assert_eq(void_field(), 10); + + first_mock.clear(); + assert_eq(void_field(), 42); +} + +#[test] +fn test_multiple_mock_times() { + OracleMock::mock("void_field").returns(10).times(2); + OracleMock::mock("void_field").returns(42); + + assert_eq(void_field(), 10); + assert_eq(void_field(), 10); + assert_eq(void_field(), 42); +} + +#[test] +fn test_mock_with_params() { + OracleMock::mock("field_field").with_params((5,)).returns(10); + assert_eq(field_field(5), 10); +} + +#[test] +fn test_multiple_mock_with_params() { + OracleMock::mock("field_field").with_params((5,)).returns(10); + OracleMock::mock("field_field").with_params((7,)).returns(14); + + assert_eq(field_field(5), 10); + assert_eq(field_field(7), 14); +} + +#[test] +fn test_mock_last_params() { + let mock = OracleMock::mock("field_field").returns(10); + assert_eq(field_field(5), 10); + + assert_eq(mock.get_last_params(), 5); +} + +#[test] +fn test_mock_last_params_many_calls() { + let mock = OracleMock::mock("field_field").returns(10); + assert_eq(field_field(5), 10); + assert_eq(field_field(7), 10); + + assert_eq(mock.get_last_params(), 7); +} + +#[test] +fn test_mock_struct_field() { + // Combination of simpler test cases + + let array = [1, 2, 3, 4]; + let another_array = [4, 3, 2, 1]; + let point = Point { x: 14, y: 27 }; + + OracleMock::mock("struct_field").returns(42).times(2); + let timeless_mock = OracleMock::mock("struct_field").returns(0); + + assert_eq(42, struct_field(point, array)); + assert_eq(42, struct_field(point, array)); + // The times(2) mock is now cleared + + assert_eq(0, struct_field(point, array)); + + let last_params: (Point, [Field; 4]) = timeless_mock.get_last_params(); + assert_eq(last_params.0, point); + assert_eq(last_params.1, array); + + // We clear the mock with no times() to allow other mocks to be callable + timeless_mock.clear(); + + OracleMock::mock("struct_field").with_params((point, array)).returns(10); + OracleMock::mock("struct_field").with_params((point, another_array)).returns(20); + assert_eq(10, struct_field(point, array)); + assert_eq(20, struct_field(point, another_array)); +} + diff --git a/test_programs/noir_test_success/out_of_bounds_alignment/Prover.toml b/test_programs/noir_test_success/out_of_bounds_alignment/Prover.toml deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/test_programs/noir_test_success/should_fail_with_matches/Prover.toml b/test_programs/noir_test_success/should_fail_with_matches/Prover.toml deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/test_programs/noir_test_success/should_fail_with_matches/src/main.nr b/test_programs/noir_test_success/should_fail_with_matches/src/main.nr index d2b7d155a32..1f5c29e58a2 100644 --- a/test_programs/noir_test_success/should_fail_with_matches/src/main.nr +++ b/test_programs/noir_test_success/should_fail_with_matches/src/main.nr @@ -17,3 +17,67 @@ fn test_should_fail_with_runtime_match() { fn test_should_fail_without_runtime_match() { assert_eq(dep::std::hash::pedersen_commitment([27]).x, 0); } + +struct InvalidPointError { + point: dep::std::embedded_curve_ops::EmbeddedCurvePoint, +} + +#[test(should_fail_with = "InvalidPointError { point: EmbeddedCurvePoint { x: 0x1cea3a116d01eb94d568ef04c3dfbc39f96f015ed801ab8958e360d406503ce0, y: 0x2721b237df87234acc36a238b8f231a3d31d18fe3845fff4cc59f0bd873818f8, is_infinite: false } }")] +fn test_should_fail_with_struct() { + let hash = dep::std::hash::pedersen_commitment([27]); + assert_eq(hash.x, 0, InvalidPointError { point: hash }); +} + +#[test(should_fail_with = "A: 0x00 is not 1!")] +fn test_should_fail_with_basic_type_fmt_string() { + let a = 0; + let b = 1; + assert_eq(a, b, f"A: {a} is not 1!"); +} + +#[test(should_fail_with = "Invalid hash: EmbeddedCurvePoint { x: 0x1cea3a116d01eb94d568ef04c3dfbc39f96f015ed801ab8958e360d406503ce0, y: 0x2721b237df87234acc36a238b8f231a3d31d18fe3845fff4cc59f0bd873818f8, is_infinite: false }")] +fn test_should_fail_with_struct_fmt_string() { + let hash = dep::std::hash::pedersen_commitment([27]); + assert_eq(hash.x, 0, f"Invalid hash: {hash}"); +} + +// Also test unconstrained versions + +#[test(should_fail_with = "Not equal")] +unconstrained fn unconstrained_test_should_fail_with_match() { + assert_eq(0, 1, "Not equal"); +} + +#[test(should_fail)] +unconstrained fn unconstrained_test_should_fail_without_match() { + assert_eq(0, 1); +} + +#[test(should_fail_with = "Not equal")] +unconstrained fn unconstrained_test_should_fail_with_runtime_match() { + assert_eq(dep::std::hash::pedersen_commitment([27]).x, 0, "Not equal"); +} + +#[test(should_fail)] +unconstrained fn unconstrained_test_should_fail_without_runtime_match() { + assert_eq(dep::std::hash::pedersen_commitment([27]).x, 0); +} + +#[test(should_fail_with = "InvalidPointError { point: EmbeddedCurvePoint { x: 0x1cea3a116d01eb94d568ef04c3dfbc39f96f015ed801ab8958e360d406503ce0, y: 0x2721b237df87234acc36a238b8f231a3d31d18fe3845fff4cc59f0bd873818f8, is_infinite: false } }")] +unconstrained fn unconstrained_test_should_fail_with_struct() { + let hash = dep::std::hash::pedersen_commitment([27]); + assert_eq(hash.x, 0, InvalidPointError { point: hash }); +} + +#[test(should_fail_with = "A: 0x00 is not 1!")] +unconstrained fn unconstrained_test_should_fail_with_basic_type_fmt_string() { + let a = 0; + let b = 1; + assert_eq(a, b, f"A: {a} is not 1!"); +} + +#[test(should_fail_with = "Invalid hash: EmbeddedCurvePoint { x: 0x1cea3a116d01eb94d568ef04c3dfbc39f96f015ed801ab8958e360d406503ce0, y: 0x2721b237df87234acc36a238b8f231a3d31d18fe3845fff4cc59f0bd873818f8, is_infinite: false }")] +unconstrained fn unconstrained_test_should_fail_with_struct_fmt_string() { + let hash = dep::std::hash::pedersen_commitment([27]); + assert_eq(hash.x, 0, f"Invalid hash: {hash}"); +} diff --git a/test_programs/rebuild.sh b/test_programs/rebuild.sh index a3137920fd5..cfc6479febf 100755 --- a/test_programs/rebuild.sh +++ b/test_programs/rebuild.sh @@ -1,11 +1,21 @@ #!/usr/bin/env bash set -e +NO_PARALLEL=${1:-} + process_dir() { local dir=$1 local current_dir=$2 local dir_name=$(basename "$dir") + if [[ ! -f "$dir/Nargo.toml" ]]; then + # This directory isn't a proper test but just hold some stale build artifacts + # We then delete it and carry on. + rm -rf $dir + return 0 + fi + + if [[ ! -d "$current_dir/acir_artifacts/$dir_name" ]]; then mkdir -p $current_dir/acir_artifacts/$dir_name fi @@ -14,13 +24,14 @@ process_dir() { if [ -d ./target/ ]; then rm -r ./target/ fi - nargo compile --only-acir && nargo execute witness + nargo execute witness if [ -d "$current_dir/acir_artifacts/$dir_name/target" ]; then rm -r "$current_dir/acir_artifacts/$dir_name/target" fi mkdir $current_dir/acir_artifacts/$dir_name/target + mv ./target/$dir_name.json $current_dir/acir_artifacts/$dir_name/target/program.json mv ./target/*.gz $current_dir/acir_artifacts/$dir_name/target/ cd $current_dir @@ -46,10 +57,17 @@ done # Process each directory in parallel pids=() +if [ -z $NO_PARALLEL ]; then for dir in "${dirs_to_process[@]}"; do process_dir "$dir" "$current_dir" & pids+=($!) done +else +for dir in "${dirs_to_process[@]}"; do + process_dir "$dir" "$current_dir" + pids+=($!) +done +fi # Check the exit status of each background job. for pid in "${pids[@]}"; do @@ -58,5 +76,7 @@ done # Exit with a failure status if any job failed. if [ ! -z "$exit_status" ]; then + echo "Rebuild failed!" exit $exit_status -fi \ No newline at end of file +fi +echo "Rebuild Succeeded!" diff --git a/test_programs/test_libraries/exporting_lib/src/lib.nr b/test_programs/test_libraries/exporting_lib/src/lib.nr index af1fd7a32de..bfb1819132a 100644 --- a/test_programs/test_libraries/exporting_lib/src/lib.nr +++ b/test_programs/test_libraries/exporting_lib/src/lib.nr @@ -1,4 +1,3 @@ - struct MyStruct { inner: Field } diff --git a/tooling/acvm_cli/Cargo.toml b/tooling/acvm_cli/Cargo.toml new file mode 100644 index 00000000000..72424405d36 --- /dev/null +++ b/tooling/acvm_cli/Cargo.toml @@ -0,0 +1,38 @@ +[package] +name = "acvm_cli" +description = "The entrypoint for executing the ACVM" +# x-release-please-start-version +version = "0.40.0" +# x-release-please-end +authors.workspace = true +edition.workspace = true +license.workspace = true +rust-version.workspace = true +repository.workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +# Rename binary from `acvm_cli` to `acvm` +[[bin]] +name = "acvm" +path = "src/main.rs" + +[dependencies] +thiserror.workspace = true +toml.workspace = true +color-eyre = "0.6.2" +clap.workspace = true +acvm.workspace = true +nargo.workspace = true +const_format.workspace = true +bn254_blackbox_solver.workspace = true +acir.workspace = true + +# Logs +tracing-subscriber.workspace = true +tracing-appender = "0.2.3" + +[dev-dependencies] +rand = "0.8.5" +proptest = "1.2.0" +paste = "1.0.14" diff --git a/tooling/acvm_cli/src/cli/execute_cmd.rs b/tooling/acvm_cli/src/cli/execute_cmd.rs new file mode 100644 index 00000000000..ac3af03684f --- /dev/null +++ b/tooling/acvm_cli/src/cli/execute_cmd.rs @@ -0,0 +1,80 @@ +use std::io::{self, Write}; + +use acir::circuit::Program; +use acir::native_types::{WitnessMap, WitnessStack}; +use acir::FieldElement; +use bn254_blackbox_solver::Bn254BlackBoxSolver; +use clap::Args; + +use crate::cli::fs::inputs::{read_bytecode_from_file, read_inputs_from_file}; +use crate::errors::CliError; +use nargo::ops::{execute_program, DefaultForeignCallExecutor}; + +use super::fs::witness::{create_output_witness_string, save_witness_to_dir}; + +/// Executes a circuit to calculate its return value +#[derive(Debug, Clone, Args)] +pub(crate) struct ExecuteCommand { + /// Write the execution witness to named file + #[clap(long, short)] + output_witness: Option, + + /// The name of the toml file which contains the input witness map + #[clap(long, short)] + input_witness: String, + + /// The name of the binary file containing circuit bytecode + #[clap(long, short)] + bytecode: String, + + /// The working directory + #[clap(long, short)] + working_directory: String, + + /// Set to print output witness to stdout + #[clap(long, short, action)] + print: bool, +} + +fn run_command(args: ExecuteCommand) -> Result { + let bytecode = read_bytecode_from_file(&args.working_directory, &args.bytecode)?; + let circuit_inputs = read_inputs_from_file(&args.working_directory, &args.input_witness)?; + let output_witness = execute_program_from_witness(circuit_inputs, &bytecode, None)?; + assert_eq!(output_witness.length(), 1, "ACVM CLI only supports a witness stack of size 1"); + let output_witness_string = create_output_witness_string( + &output_witness.peek().expect("Should have a witness stack item").witness, + )?; + if args.output_witness.is_some() { + save_witness_to_dir( + output_witness, + &args.output_witness.unwrap(), + &args.working_directory, + )?; + } + Ok(output_witness_string) +} + +pub(crate) fn run(args: ExecuteCommand) -> Result { + let print = args.print; + let output_witness_string = run_command(args)?; + if print { + io::stdout().write_all(output_witness_string.as_bytes()).unwrap(); + } + Ok(output_witness_string) +} + +pub(crate) fn execute_program_from_witness( + inputs_map: WitnessMap, + bytecode: &[u8], + foreign_call_resolver_url: Option<&str>, +) -> Result, CliError> { + let program: Program = Program::deserialize_program(bytecode) + .map_err(|_| CliError::CircuitDeserializationError())?; + execute_program( + &program, + inputs_map, + &Bn254BlackBoxSolver, + &mut DefaultForeignCallExecutor::new(true, foreign_call_resolver_url), + ) + .map_err(CliError::CircuitExecutionError) +} diff --git a/tooling/acvm_cli/src/cli/fs/inputs.rs b/tooling/acvm_cli/src/cli/fs/inputs.rs new file mode 100644 index 00000000000..a0b6e3a9545 --- /dev/null +++ b/tooling/acvm_cli/src/cli/fs/inputs.rs @@ -0,0 +1,54 @@ +use acir::{ + native_types::{Witness, WitnessMap}, + AcirField, FieldElement, +}; +use toml::Table; + +use crate::errors::{CliError, FilesystemError}; +use std::{fs::read, path::Path}; + +/// Returns the circuit's parameters parsed from a toml file at the given location +pub(crate) fn read_inputs_from_file>( + working_directory: P, + file_name: &String, +) -> Result, CliError> { + let file_path = working_directory.as_ref().join(file_name); + if !file_path.exists() { + return Err(CliError::FilesystemError(FilesystemError::MissingTomlFile( + file_name.to_owned(), + file_path, + ))); + } + + let input_string = std::fs::read_to_string(file_path) + .map_err(|_| FilesystemError::InvalidTomlFile(file_name.clone()))?; + let input_map = input_string + .parse::() + .map_err(|_| FilesystemError::InvalidTomlFile(file_name.clone()))?; + let mut witnesses: WitnessMap = WitnessMap::new(); + for (key, value) in input_map.into_iter() { + let index = + Witness(key.trim().parse().map_err(|_| CliError::WitnessIndexError(key.clone()))?); + if !value.is_str() { + return Err(CliError::WitnessValueError(key.clone())); + } + let field = FieldElement::from_hex(value.as_str().unwrap()).unwrap(); + witnesses.insert(index, field); + } + + Ok(witnesses) +} + +/// Returns the circuit's bytecode read from the file at the given location +pub(crate) fn read_bytecode_from_file>( + working_directory: P, + file_name: &String, +) -> Result, FilesystemError> { + let file_path = working_directory.as_ref().join(file_name); + if !file_path.exists() { + return Err(FilesystemError::MissingBytecodeFile(file_name.to_owned(), file_path)); + } + let bytecode: Vec = + read(file_path).map_err(|_| FilesystemError::InvalidBytecodeFile(file_name.clone()))?; + Ok(bytecode) +} diff --git a/tooling/acvm_cli/src/cli/fs/mod.rs b/tooling/acvm_cli/src/cli/fs/mod.rs new file mode 100644 index 00000000000..f23ba06fd8b --- /dev/null +++ b/tooling/acvm_cli/src/cli/fs/mod.rs @@ -0,0 +1,2 @@ +pub(super) mod inputs; +pub(super) mod witness; diff --git a/tooling/acvm_cli/src/cli/fs/witness.rs b/tooling/acvm_cli/src/cli/fs/witness.rs new file mode 100644 index 00000000000..6ecba9792c3 --- /dev/null +++ b/tooling/acvm_cli/src/cli/fs/witness.rs @@ -0,0 +1,63 @@ +use std::{ + collections::BTreeMap, + fs::File, + io::Write, + path::{Path, PathBuf}, +}; + +use acir::FieldElement; +use acvm::acir::{ + native_types::{WitnessMap, WitnessStack}, + AcirField, +}; + +use crate::errors::{CliError, FilesystemError}; + +fn create_named_dir(named_dir: &Path, name: &str) -> PathBuf { + std::fs::create_dir_all(named_dir) + .unwrap_or_else(|_| panic!("could not create the `{name}` directory")); + + PathBuf::from(named_dir) +} + +fn write_to_file(bytes: &[u8], path: &Path) -> String { + let display = path.display(); + + let mut file = match File::create(path) { + Err(why) => panic!("couldn't create {display}: {why}"), + Ok(file) => file, + }; + + match file.write_all(bytes) { + Err(why) => panic!("couldn't write to {display}: {why}"), + Ok(_) => display.to_string(), + } +} + +/// Creates a toml representation of the provided witness map +pub(crate) fn create_output_witness_string( + witnesses: &WitnessMap, +) -> Result { + let mut witness_map: BTreeMap = BTreeMap::new(); + for (key, value) in witnesses.clone().into_iter() { + witness_map.insert(key.0.to_string(), format!("0x{}", value.to_hex())); + } + + toml::to_string(&witness_map).map_err(|_| CliError::OutputWitnessSerializationFailed()) +} + +pub(crate) fn save_witness_to_dir>( + witnesses: WitnessStack, + witness_name: &str, + witness_dir: P, +) -> Result { + create_named_dir(witness_dir.as_ref(), "witness"); + let witness_path = witness_dir.as_ref().join(witness_name).with_extension("gz"); + + let buf: Vec = witnesses + .try_into() + .map_err(|_op| FilesystemError::OutputWitnessCreationFailed(witness_name.to_string()))?; + write_to_file(buf.as_slice(), &witness_path); + + Ok(witness_path) +} diff --git a/tooling/acvm_cli/src/cli/mod.rs b/tooling/acvm_cli/src/cli/mod.rs new file mode 100644 index 00000000000..a610b08ab77 --- /dev/null +++ b/tooling/acvm_cli/src/cli/mod.rs @@ -0,0 +1,41 @@ +use clap::{Parser, Subcommand}; +use color_eyre::eyre; +use const_format::formatcp; + +mod execute_cmd; +mod fs; + +const ACVM_VERSION: &str = env!("CARGO_PKG_VERSION"); + +static VERSION_STRING: &str = formatcp!("version = {}\n", ACVM_VERSION,); + +#[derive(Parser, Debug)] +#[command(name="acvm", author, version=VERSION_STRING, about, long_about = None)] +struct ACVMCli { + #[command(subcommand)] + command: ACVMCommand, +} + +#[non_exhaustive] +#[derive(Subcommand, Clone, Debug)] +enum ACVMCommand { + Execute(execute_cmd::ExecuteCommand), +} + +#[cfg(not(feature = "codegen-docs"))] +pub(crate) fn start_cli() -> eyre::Result<()> { + let ACVMCli { command } = ACVMCli::parse(); + + match command { + ACVMCommand::Execute(args) => execute_cmd::run(args), + }?; + + Ok(()) +} + +#[cfg(feature = "codegen-docs")] +pub(crate) fn start_cli() -> eyre::Result<()> { + let markdown: String = clap_markdown::help_markdown::(); + println!("{markdown}"); + Ok(()) +} diff --git a/tooling/acvm_cli/src/errors.rs b/tooling/acvm_cli/src/errors.rs new file mode 100644 index 00000000000..8bc79347159 --- /dev/null +++ b/tooling/acvm_cli/src/errors.rs @@ -0,0 +1,49 @@ +use nargo::NargoError; +use std::path::PathBuf; +use thiserror::Error; + +#[derive(Debug, Error)] +pub(crate) enum FilesystemError { + #[error( + " Error: cannot find {0} in expected location {1:?}.\n Please generate this file at the expected location." + )] + MissingTomlFile(String, PathBuf), + #[error(" Error: failed to parse toml file {0}.")] + InvalidTomlFile(String), + #[error( + " Error: cannot find {0} in expected location {1:?}.\n Please generate this file at the expected location." + )] + MissingBytecodeFile(String, PathBuf), + + #[error(" Error: failed to read bytecode file {0}.")] + InvalidBytecodeFile(String), + + #[error(" Error: failed to create output witness file {0}.")] + OutputWitnessCreationFailed(String), +} + +#[derive(Debug, Error)] +pub(crate) enum CliError { + /// Filesystem errors + #[error(transparent)] + FilesystemError(#[from] FilesystemError), + + /// Error related to circuit deserialization + #[error("Error: failed to deserialize circuit in ACVM CLI")] + CircuitDeserializationError(), + + /// Error related to circuit execution + #[error(transparent)] + CircuitExecutionError(#[from] NargoError), + + /// Input Witness Value Error + #[error("Error: failed to parse witness value {0}")] + WitnessValueError(String), + + /// Input Witness Index Error + #[error("Error: failed to parse witness index {0}")] + WitnessIndexError(String), + + #[error(" Error: failed to serialize output witness.")] + OutputWitnessSerializationFailed(), +} diff --git a/tooling/acvm_cli/src/main.rs b/tooling/acvm_cli/src/main.rs new file mode 100644 index 00000000000..33cadc73a7c --- /dev/null +++ b/tooling/acvm_cli/src/main.rs @@ -0,0 +1,36 @@ +#![forbid(unsafe_code)] +#![warn(unreachable_pub)] +#![warn(clippy::semicolon_if_nothing_returned)] +#![cfg_attr(not(test), warn(unused_crate_dependencies, unused_extern_crates))] + +mod cli; +mod errors; + +use std::env; + +use tracing_appender::rolling; +use tracing_subscriber::{fmt::format::FmtSpan, EnvFilter}; + +fn main() { + // Setup tracing + if let Ok(log_dir) = env::var("ACVM_LOG_DIR") { + let debug_file = rolling::daily(log_dir, "acvm-log"); + tracing_subscriber::fmt() + .with_span_events(FmtSpan::ACTIVE) + .with_writer(debug_file) + .with_ansi(false) + .with_env_filter(EnvFilter::from_default_env()) + .init(); + } else { + tracing_subscriber::fmt() + .with_span_events(FmtSpan::ACTIVE) + .with_ansi(true) + .with_env_filter(EnvFilter::from_env("NOIR_LOG")) + .init(); + } + + if let Err(report) = cli::start_cli() { + eprintln!("{report}"); + std::process::exit(1); + } +} diff --git a/tooling/backend_interface/CHANGELOG.md b/tooling/backend_interface/CHANGELOG.md deleted file mode 100644 index 9ebde989add..00000000000 --- a/tooling/backend_interface/CHANGELOG.md +++ /dev/null @@ -1,233 +0,0 @@ -# Changelog - -## [0.11.0](https://github.com/noir-lang/acvm-backend-barretenberg/compare/v0.10.1...v0.11.0) (2023-08-18) - - -### ⚠ BREAKING CHANGES - -* Update `acvm` to 0.22.0 ([#240](https://github.com/noir-lang/acvm-backend-barretenberg/issues/240)) - -### Features - -* Update `acvm` to 0.22.0 ([#240](https://github.com/noir-lang/acvm-backend-barretenberg/issues/240)) ([d8342fd](https://github.com/noir-lang/acvm-backend-barretenberg/commit/d8342fd6da605ac3bbd889edf89cd122bc4689ce)) - -## [0.10.1](https://github.com/noir-lang/acvm-backend-barretenberg/compare/v0.10.0...v0.10.1) (2023-08-18) - - -### Features - -* Migrate to `wasmer` 3.3.0 ([#236](https://github.com/noir-lang/acvm-backend-barretenberg/issues/236)) ([e115e38](https://github.com/noir-lang/acvm-backend-barretenberg/commit/e115e38856887c6b1eeead3534534ac7e6327ea9)) - -## [0.10.0](https://github.com/noir-lang/acvm-backend-barretenberg/compare/v0.9.1...v0.10.0) (2023-07-26) - - -### ⚠ BREAKING CHANGES - -* Migrate to ACVM 0.21.0 ([#234](https://github.com/noir-lang/acvm-backend-barretenberg/issues/234)) - -### Features - -* Migrate to ACVM 0.21.0 ([#234](https://github.com/noir-lang/acvm-backend-barretenberg/issues/234)) ([15c8676](https://github.com/noir-lang/acvm-backend-barretenberg/commit/15c86768685d2946a767c350f6ef5972c86677eb)) - -## [0.9.1](https://github.com/noir-lang/acvm-backend-barretenberg/compare/v0.9.0...v0.9.1) (2023-07-21) - - -### Features - -* add support for atomic memory opcodes ([#232](https://github.com/noir-lang/acvm-backend-barretenberg/issues/232)) ([a7aa6e9](https://github.com/noir-lang/acvm-backend-barretenberg/commit/a7aa6e9505bb402c1b3db0a990845ed26928e7aa)) - -## [0.9.0](https://github.com/noir-lang/acvm-backend-barretenberg/compare/v0.8.0...v0.9.0) (2023-07-17) - - -### ⚠ BREAKING CHANGES - -* update to ACVM 0.19.0 ([#230](https://github.com/noir-lang/acvm-backend-barretenberg/issues/230)) - -### Miscellaneous Chores - -* update to ACVM 0.19.0 ([#230](https://github.com/noir-lang/acvm-backend-barretenberg/issues/230)) ([3f1d967](https://github.com/noir-lang/acvm-backend-barretenberg/commit/3f1d9674b904acb02c2a3e52481be8a6104c3a9d)) - -## [0.8.0](https://github.com/noir-lang/acvm-backend-barretenberg/compare/v0.7.0...v0.8.0) (2023-07-12) - - -### ⚠ BREAKING CHANGES - -* Update to acvm 0.18.1 ([#228](https://github.com/noir-lang/acvm-backend-barretenberg/issues/228)) - -### Features - -* Update to acvm 0.18.1 ([#228](https://github.com/noir-lang/acvm-backend-barretenberg/issues/228)) ([397098b](https://github.com/noir-lang/acvm-backend-barretenberg/commit/397098b239efbe16785b1c9af108ca9fc4e24497)) - -## [0.7.0](https://github.com/noir-lang/acvm-backend-barretenberg/compare/v0.6.1...v0.7.0) (2023-07-08) - - -### ⚠ BREAKING CHANGES - -* **bberg:** add secp256r1 builtin to barretenberg ([#223](https://github.com/noir-lang/acvm-backend-barretenberg/issues/223)) - -### Features - -* **bberg:** add secp256r1 builtin to barretenberg ([#223](https://github.com/noir-lang/acvm-backend-barretenberg/issues/223)) ([ceb4770](https://github.com/noir-lang/acvm-backend-barretenberg/commit/ceb47705a492fcdcea1f3c098aaab42ea8edbf2e)) - -## [0.6.1](https://github.com/noir-lang/acvm-backend-barretenberg/compare/v0.6.0...v0.6.1) (2023-07-06) - - -### Features - -* switch RecursiveAggregation support to true ([#225](https://github.com/noir-lang/acvm-backend-barretenberg/issues/225)) ([e9462ae](https://github.com/noir-lang/acvm-backend-barretenberg/commit/e9462ae015ec0dfb0a23ccbb89562071f87940f5)) - -## [0.6.0](https://github.com/noir-lang/acvm-backend-barretenberg/compare/v0.5.1...v0.6.0) (2023-07-06) - - -### ⚠ BREAKING CHANGES - -* Update to ACVM 0.16.0 ([#221](https://github.com/noir-lang/acvm-backend-barretenberg/issues/221)) - -### Features - -* Update to ACVM 0.16.0 ([#221](https://github.com/noir-lang/acvm-backend-barretenberg/issues/221)) ([062d5ed](https://github.com/noir-lang/acvm-backend-barretenberg/commit/062d5ed9b476fab8ac8d3ca13371699fb2aac332)) - -## [0.5.1](https://github.com/noir-lang/acvm-backend-barretenberg/compare/v0.5.0...v0.5.1) (2023-06-20) - - -### Bug Fixes - -* Remove wasm32 target ([#219](https://github.com/noir-lang/acvm-backend-barretenberg/issues/219)) ([e4cbb6d](https://github.com/noir-lang/acvm-backend-barretenberg/commit/e4cbb6d476e8746de33c38506e2fcb970f1c866a)) - -## [0.5.0](https://github.com/noir-lang/acvm-backend-barretenberg/compare/v0.4.0...v0.5.0) (2023-06-15) - - -### ⚠ BREAKING CHANGES - -* Update to target ACVM 0.15.0 ([#217](https://github.com/noir-lang/acvm-backend-barretenberg/issues/217)) - -### Features - -* Update to target ACVM 0.15.0 ([#217](https://github.com/noir-lang/acvm-backend-barretenberg/issues/217)) ([9331898](https://github.com/noir-lang/acvm-backend-barretenberg/commit/9331898f161321c8b6a82d5ea850f197952b2ed2)) - -## [0.4.0](https://github.com/noir-lang/acvm-backend-barretenberg/compare/v0.3.0...v0.4.0) (2023-06-07) - - -### ⚠ BREAKING CHANGES - -* Recursion ([#207](https://github.com/noir-lang/acvm-backend-barretenberg/issues/207)) - -### Features - -* Recursion ([#207](https://github.com/noir-lang/acvm-backend-barretenberg/issues/207)) ([6fc479b](https://github.com/noir-lang/acvm-backend-barretenberg/commit/6fc479b9ae99d59bbfeb1b895d63cdbea469dcaa)) - -## [0.3.0](https://github.com/noir-lang/acvm-backend-barretenberg/compare/v0.2.0...v0.3.0) (2023-06-01) - - -### ⚠ BREAKING CHANGES - -* Update to ACVM 0.13.0 ([#205](https://github.com/noir-lang/acvm-backend-barretenberg/issues/205)) -* added keccakvar constraints ([#213](https://github.com/noir-lang/acvm-backend-barretenberg/issues/213)) -* update pedersen hashes for new implementation ([#212](https://github.com/noir-lang/acvm-backend-barretenberg/issues/212)) - -### Features - -* added keccakvar constraints ([91ea65f](https://github.com/noir-lang/acvm-backend-barretenberg/commit/91ea65f6af7039095c7a3af7bc1e4ce302a68a8d)) -* added keccakvar constraints ([#213](https://github.com/noir-lang/acvm-backend-barretenberg/issues/213)) ([91ea65f](https://github.com/noir-lang/acvm-backend-barretenberg/commit/91ea65f6af7039095c7a3af7bc1e4ce302a68a8d)) -* Update to ACVM 0.13.0 ([#205](https://github.com/noir-lang/acvm-backend-barretenberg/issues/205)) ([298446e](https://github.com/noir-lang/acvm-backend-barretenberg/commit/298446ef8b69f528b6e2fd2abb2298d7b0a8118e)) - - -### Bug Fixes - -* Add or cleanup implementations for JS target ([#199](https://github.com/noir-lang/acvm-backend-barretenberg/issues/199)) ([f6134b7](https://github.com/noir-lang/acvm-backend-barretenberg/commit/f6134b7b502cb74882300b0046ab91ab000daf3c)) -* update pedersen hashes for new impl ([9a233ce](https://github.com/noir-lang/acvm-backend-barretenberg/commit/9a233ce8db9984b29b9cce0603f758d5281c89c9)) -* update pedersen hashes for new implementation ([#212](https://github.com/noir-lang/acvm-backend-barretenberg/issues/212)) ([9a233ce](https://github.com/noir-lang/acvm-backend-barretenberg/commit/9a233ce8db9984b29b9cce0603f758d5281c89c9)) - -## [0.2.0](https://github.com/noir-lang/acvm-backend-barretenberg/compare/v0.1.2...v0.2.0) (2023-05-22) - - -### ⚠ BREAKING CHANGES - -* Update to acvm 0.12.0 ([#165](https://github.com/noir-lang/acvm-backend-barretenberg/issues/165)) -* Add serialization logic for RAM and ROM opcodes ([#153](https://github.com/noir-lang/acvm-backend-barretenberg/issues/153)) - -### Features - -* Add serde to `ConstraintSystem` types ([#196](https://github.com/noir-lang/acvm-backend-barretenberg/issues/196)) ([4c04a79](https://github.com/noir-lang/acvm-backend-barretenberg/commit/4c04a79e6d2b0115f3b4526c60f9f7dae8b464ae)) -* Add serialization logic for RAM and ROM opcodes ([#153](https://github.com/noir-lang/acvm-backend-barretenberg/issues/153)) ([3d3847d](https://github.com/noir-lang/acvm-backend-barretenberg/commit/3d3847de70e74a8f65c64e165ad15ae3d31f5350)) -* Update to acvm 0.12.0 ([#165](https://github.com/noir-lang/acvm-backend-barretenberg/issues/165)) ([d613c79](https://github.com/noir-lang/acvm-backend-barretenberg/commit/d613c79584a599f4adbd11d2ce3b61403c185b73)) - -## [0.1.2](https://github.com/noir-lang/acvm-backend-barretenberg/compare/v0.1.1...v0.1.2) (2023-05-11) - - -### Bug Fixes - -* Remove star dependencies to allow publishing ([#182](https://github.com/noir-lang/acvm-backend-barretenberg/issues/182)) ([1727a79](https://github.com/noir-lang/acvm-backend-barretenberg/commit/1727a79ce7e66d95528f70c445cb4ec1b1ece636)) - -## [0.1.1](https://github.com/noir-lang/acvm-backend-barretenberg/compare/v0.1.0...v0.1.1) (2023-05-11) - - -### Bug Fixes - -* Add description so crate can be published ([#180](https://github.com/noir-lang/acvm-backend-barretenberg/issues/180)) ([caabf94](https://github.com/noir-lang/acvm-backend-barretenberg/commit/caabf9434031c6023a5e3a436c87fba0a1072539)) - -## 0.1.0 (2023-05-10) - - -### ⚠ BREAKING CHANGES - -* Update to ACVM v0.11.0 ([#151](https://github.com/noir-lang/acvm-backend-barretenberg/issues/151)) -* Add Keccak constraints ([#150](https://github.com/noir-lang/acvm-backend-barretenberg/issues/150)) -* migrate to ACVM 0.10.3 ([#148](https://github.com/noir-lang/acvm-backend-barretenberg/issues/148)) -* remove all crates other than `acvm-backend-barretenberg` and remove workspace ([#147](https://github.com/noir-lang/acvm-backend-barretenberg/issues/147)) -* merge `barretenberg_static_lib` and `barretenberg_wasm` ([#117](https://github.com/noir-lang/acvm-backend-barretenberg/issues/117)) -* remove dead blake2 code ([#137](https://github.com/noir-lang/acvm-backend-barretenberg/issues/137)) -* Implement pseudo-builder pattern for ConstraintSystem & hide struct fields ([#120](https://github.com/noir-lang/acvm-backend-barretenberg/issues/120)) -* return boolean rather than `FieldElement` from `verify_signature` ([#123](https://github.com/noir-lang/acvm-backend-barretenberg/issues/123)) -* avoid exposing internals of Assignments type ([#119](https://github.com/noir-lang/acvm-backend-barretenberg/issues/119)) -* update to acvm 0.9.0 ([#106](https://github.com/noir-lang/acvm-backend-barretenberg/issues/106)) -* Depend upon upstream barretenberg & switch to UltraPlonk ([#84](https://github.com/noir-lang/acvm-backend-barretenberg/issues/84)) -* update to ACVM 0.7.0 ([#90](https://github.com/noir-lang/acvm-backend-barretenberg/issues/90)) -* Remove create_proof and verify functions ([#82](https://github.com/noir-lang/acvm-backend-barretenberg/issues/82)) -* update to acvm v0.5.0 ([#60](https://github.com/noir-lang/acvm-backend-barretenberg/issues/60)) - -### Features - -* **acvm_interop:** Updates to reflect new acvm methods using pk/vk ([#50](https://github.com/noir-lang/acvm-backend-barretenberg/issues/50)) ([cff757d](https://github.com/noir-lang/acvm-backend-barretenberg/commit/cff757dca7971161e4bd25e7a744d910c37c22be)) -* Add Keccak constraints ([#150](https://github.com/noir-lang/acvm-backend-barretenberg/issues/150)) ([ce2b9ed](https://github.com/noir-lang/acvm-backend-barretenberg/commit/ce2b9ed456bd8d2ad8357c15736d62c2a5812add)) -* allow overriding transcript location with BARRETENBERG_TRANSCRIPT env var ([#86](https://github.com/noir-lang/acvm-backend-barretenberg/issues/86)) ([af92b99](https://github.com/noir-lang/acvm-backend-barretenberg/commit/af92b99c7b5f37e9659931af378a851b3658a80b)) -* **ci:** add concurrency group for rust workflow ([#63](https://github.com/noir-lang/acvm-backend-barretenberg/issues/63)) ([5c936bc](https://github.com/noir-lang/acvm-backend-barretenberg/commit/5c936bc63cc3adcf9d43c9c4ce69053566089ad9)) -* Depend upon upstream barretenberg & switch to UltraPlonk ([#84](https://github.com/noir-lang/acvm-backend-barretenberg/issues/84)) ([8437bf7](https://github.com/noir-lang/acvm-backend-barretenberg/commit/8437bf7e08acadf43b55b307545336596a9fe766)) -* Implement pseudo-builder pattern for ConstraintSystem & hide struct fields ([#120](https://github.com/noir-lang/acvm-backend-barretenberg/issues/120)) ([8ed67d6](https://github.com/noir-lang/acvm-backend-barretenberg/commit/8ed67d68c71d655e1a6a5c38fa9ea1c3566f771d)) -* Leverage rustls when using downloader crate ([#46](https://github.com/noir-lang/acvm-backend-barretenberg/issues/46)) ([9de36b6](https://github.com/noir-lang/acvm-backend-barretenberg/commit/9de36b642d125d1fb4facd1bf60db67946be70ae)) -* merge `barretenberg_static_lib` and `barretenberg_wasm` ([#117](https://github.com/noir-lang/acvm-backend-barretenberg/issues/117)) ([ba1d0d6](https://github.com/noir-lang/acvm-backend-barretenberg/commit/ba1d0d61b94de91b15044d97608907c21bfb5299)) -* migrate to ACVM 0.10.3 ([#148](https://github.com/noir-lang/acvm-backend-barretenberg/issues/148)) ([c9fb9e8](https://github.com/noir-lang/acvm-backend-barretenberg/commit/c9fb9e806f1400a2ff7594a0669bec56025220bb)) -* remove all crates other than `acvm-backend-barretenberg` and remove workspace ([#147](https://github.com/noir-lang/acvm-backend-barretenberg/issues/147)) ([8fe7111](https://github.com/noir-lang/acvm-backend-barretenberg/commit/8fe7111ebdcb043764a83436744662e8c3ca5abc)) -* remove dead blake2 code ([#137](https://github.com/noir-lang/acvm-backend-barretenberg/issues/137)) ([14d8a5b](https://github.com/noir-lang/acvm-backend-barretenberg/commit/14d8a5b893eb1cb91d5bde908643b487b41809d6)) -* replace `downloader` dependency with `reqwest` ([#114](https://github.com/noir-lang/acvm-backend-barretenberg/issues/114)) ([dd62231](https://github.com/noir-lang/acvm-backend-barretenberg/commit/dd62231b8bfcee32e1029d31a07895b16159339c)) -* return boolean from `verify_signature` ([e560602](https://github.com/noir-lang/acvm-backend-barretenberg/commit/e560602ebbd547386ca4cab35735ffa92e98ac4b)) -* return boolean rather than `FieldElement` from `check_membership` ([#124](https://github.com/noir-lang/acvm-backend-barretenberg/issues/124)) ([a0a338e](https://github.com/noir-lang/acvm-backend-barretenberg/commit/a0a338e2295635a07f6b9e497c029160a5f323bc)) -* return boolean rather than `FieldElement` from `verify_signature` ([#123](https://github.com/noir-lang/acvm-backend-barretenberg/issues/123)) ([e560602](https://github.com/noir-lang/acvm-backend-barretenberg/commit/e560602ebbd547386ca4cab35735ffa92e98ac4b)) -* store transcript in `.nargo/backends` directory ([#91](https://github.com/noir-lang/acvm-backend-barretenberg/issues/91)) ([c6b5023](https://github.com/noir-lang/acvm-backend-barretenberg/commit/c6b50231da065e7550bfe8bddf8e46f4cd8002d7)) -* update `aztec_backend_wasm` to use new serialization ([#94](https://github.com/noir-lang/acvm-backend-barretenberg/issues/94)) ([28014d8](https://github.com/noir-lang/acvm-backend-barretenberg/commit/28014d803d052a7f459e03dbd7b5b9210449b1d0)) -* update to acvm 0.9.0 ([#106](https://github.com/noir-lang/acvm-backend-barretenberg/issues/106)) ([ff350fb](https://github.com/noir-lang/acvm-backend-barretenberg/commit/ff350fb111043964b8a14fc0df62508c87506423)) -* Update to ACVM v0.11.0 ([#151](https://github.com/noir-lang/acvm-backend-barretenberg/issues/151)) ([9202415](https://github.com/noir-lang/acvm-backend-barretenberg/commit/92024155532e15f25acb2f3ed8d5ca78da0fddd9)) -* update to acvm v0.5.0 ([#60](https://github.com/noir-lang/acvm-backend-barretenberg/issues/60)) ([74b4d8d](https://github.com/noir-lang/acvm-backend-barretenberg/commit/74b4d8d8b118e4477880c04149e5e9d93d388384)) - - -### Bug Fixes - -* Avoid exposing internals of Assignments type ([614c81b](https://github.com/noir-lang/acvm-backend-barretenberg/commit/614c81b0ea5e110bbf5a61a526bb0173f4fe377a)) -* avoid exposing internals of Assignments type ([#119](https://github.com/noir-lang/acvm-backend-barretenberg/issues/119)) ([614c81b](https://github.com/noir-lang/acvm-backend-barretenberg/commit/614c81b0ea5e110bbf5a61a526bb0173f4fe377a)) -* fix serialization of arithmetic expressions ([#145](https://github.com/noir-lang/acvm-backend-barretenberg/issues/145)) ([7f42535](https://github.com/noir-lang/acvm-backend-barretenberg/commit/7f4253570257d9dedcfa8c8fb96b9d097ef06419)) -* Implement random_get for wasm backend ([#102](https://github.com/noir-lang/acvm-backend-barretenberg/issues/102)) ([9c0f06e](https://github.com/noir-lang/acvm-backend-barretenberg/commit/9c0f06ef56f23e2b5794e810f433e36ff2c5d6b5)) -* rename gates to opcodes ([#59](https://github.com/noir-lang/acvm-backend-barretenberg/issues/59)) ([6e05307](https://github.com/noir-lang/acvm-backend-barretenberg/commit/6e053072d8b9c5d93c296f10782251ccb597f902)) -* reorganize and ensure contracts can be compiled in Remix ([#112](https://github.com/noir-lang/acvm-backend-barretenberg/issues/112)) ([7ec5693](https://github.com/noir-lang/acvm-backend-barretenberg/commit/7ec5693f194a79c379ae2952bc17a31ee63a42b9)) -* replace `serialize_circuit` function with `from<&Circuit>` ([#118](https://github.com/noir-lang/acvm-backend-barretenberg/issues/118)) ([94f83a7](https://github.com/noir-lang/acvm-backend-barretenberg/commit/94f83a78e32d91dfb7ae9824923695d9b4c425b0)) -* Replace serialize_circuit function with `from<&Circuit>` ([94f83a7](https://github.com/noir-lang/acvm-backend-barretenberg/commit/94f83a78e32d91dfb7ae9824923695d9b4c425b0)) -* Update bb-sys to resolve bugs in some environments ([#129](https://github.com/noir-lang/acvm-backend-barretenberg/issues/129)) ([e3d4504](https://github.com/noir-lang/acvm-backend-barretenberg/commit/e3d4504f15e1295e637c4da80b1d08c87c267c45)) -* Update dependency containing pk write fix for large general circuits ([#78](https://github.com/noir-lang/acvm-backend-barretenberg/issues/78)) ([2cb523d](https://github.com/noir-lang/acvm-backend-barretenberg/commit/2cb523d2ab95249157b22e198d9dcd6841c3eed8)) -* Update to bb-sys 0.1.1 and update bb in lockfile ([00bb157](https://github.com/noir-lang/acvm-backend-barretenberg/commit/00bb15779dfb64539eeb3f3bb4c4deeba106f2fe)) -* update to bb-sys 0.1.1 and update bb in lockfile ([#111](https://github.com/noir-lang/acvm-backend-barretenberg/issues/111)) ([00bb157](https://github.com/noir-lang/acvm-backend-barretenberg/commit/00bb15779dfb64539eeb3f3bb4c4deeba106f2fe)) -* use `Barretenberg.call` to query circuit size from wasm ([#121](https://github.com/noir-lang/acvm-backend-barretenberg/issues/121)) ([a775af1](https://github.com/noir-lang/acvm-backend-barretenberg/commit/a775af14137cc7bc2e9d8a063fa718a5a9abe6cb)) - - -### Miscellaneous Chores - -* Remove create_proof and verify functions ([#82](https://github.com/noir-lang/acvm-backend-barretenberg/issues/82)) ([ad0c422](https://github.com/noir-lang/acvm-backend-barretenberg/commit/ad0c4228488457bd155ff381186ecf583f18bfac)) -* update to ACVM 0.7.0 ([#90](https://github.com/noir-lang/acvm-backend-barretenberg/issues/90)) ([6c03687](https://github.com/noir-lang/acvm-backend-barretenberg/commit/6c036870a6a8e26612ab8b4f90a162f7540b42e2)) diff --git a/tooling/backend_interface/Cargo.toml b/tooling/backend_interface/Cargo.toml deleted file mode 100644 index 2d991f9ae6c..00000000000 --- a/tooling/backend_interface/Cargo.toml +++ /dev/null @@ -1,36 +0,0 @@ -[package] -name = "backend-interface" -description = "The definition of the backend CLI interface which Nargo uses for proving/verifying ACIR circuits." -version = "0.11.0" -authors.workspace = true -edition.workspace = true -rust-version.workspace = true -license.workspace = true - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -acvm.workspace = true -dirs.workspace = true -thiserror.workspace = true -serde.workspace = true -serde_json.workspace = true -bb_abstraction_leaks.workspace = true -tracing.workspace = true - -tempfile.workspace = true - -## bb binary downloading -tar = "~0.4.15" -flate2 = "~1.0.1" -reqwest = { version = "0.11.20", default-features = false, features = [ - "rustls-tls", - "blocking", -] } - -[dev-dependencies] -test-binary = "3.0.1" - -[build-dependencies] -build-target = "0.4.0" -const_format.workspace = true diff --git a/tooling/backend_interface/src/cli/contract.rs b/tooling/backend_interface/src/cli/contract.rs deleted file mode 100644 index e83fc1909b6..00000000000 --- a/tooling/backend_interface/src/cli/contract.rs +++ /dev/null @@ -1,71 +0,0 @@ -use std::path::{Path, PathBuf}; - -use crate::BackendError; - -use super::string_from_stderr; - -/// VerifyCommand will call the barretenberg binary -/// to return a solidity library with the verification key -/// that can be used to verify proofs on-chain. -/// -/// This does not return a Solidity file that is able -/// to verify a proof. See acvm_interop/contract.sol for the -/// remaining logic that is missing. -pub(crate) struct ContractCommand { - pub(crate) crs_path: PathBuf, - pub(crate) vk_path: PathBuf, -} - -impl ContractCommand { - pub(crate) fn run(self, binary_path: &Path) -> Result { - let mut command = std::process::Command::new(binary_path); - - command - .arg("contract") - .arg("-c") - .arg(self.crs_path) - .arg("-k") - .arg(self.vk_path) - .arg("-o") - .arg("-"); - - let output = command.output()?; - - if output.status.success() { - String::from_utf8(output.stdout) - .map_err(|error| BackendError::InvalidUTF8Vector(error.into_bytes())) - } else { - Err(BackendError::CommandFailed(string_from_stderr(&output.stderr))) - } - } -} - -#[test] -fn contract_command() -> Result<(), BackendError> { - use tempfile::tempdir; - - let backend = crate::get_mock_backend()?; - - let temp_directory = tempdir().expect("could not create a temporary directory"); - let temp_directory_path = temp_directory.path(); - let bytecode_path = temp_directory_path.join("acir.gz"); - let vk_path = temp_directory_path.join("vk"); - - let crs_path = backend.backend_directory(); - - std::fs::File::create(&bytecode_path).expect("file should be created"); - - let write_vk_command = super::WriteVkCommand { - bytecode_path, - vk_path_output: vk_path.clone(), - crs_path: crs_path.clone(), - }; - write_vk_command.run(backend.binary_path())?; - - let contract_command = ContractCommand { vk_path, crs_path }; - contract_command.run(backend.binary_path())?; - - drop(temp_directory); - - Ok(()) -} diff --git a/tooling/backend_interface/src/cli/gates.rs b/tooling/backend_interface/src/cli/gates.rs deleted file mode 100644 index aca05f0232a..00000000000 --- a/tooling/backend_interface/src/cli/gates.rs +++ /dev/null @@ -1,64 +0,0 @@ -use std::path::{Path, PathBuf}; - -use crate::BackendError; - -use super::string_from_stderr; - -/// GatesCommand will call the barretenberg binary -/// to return the number of gates needed to create a proof -/// for the given bytecode. -pub(crate) struct GatesCommand { - pub(crate) crs_path: PathBuf, - pub(crate) bytecode_path: PathBuf, -} - -impl GatesCommand { - pub(crate) fn run(self, binary_path: &Path) -> Result { - let output = std::process::Command::new(binary_path) - .arg("gates") - .arg("-c") - .arg(self.crs_path) - .arg("-b") - .arg(self.bytecode_path) - .output()?; - - if !output.status.success() { - return Err(BackendError::CommandFailed(string_from_stderr(&output.stderr))); - } - // Note: barretenberg includes the newline, so that subsequent prints to stdout - // are not on the same line as the gates output. - - const EXPECTED_BYTES: usize = 8; - let gates_bytes: [u8; EXPECTED_BYTES] = - output.stdout.as_slice().try_into().map_err(|_| { - BackendError::UnexpectedNumberOfBytes(EXPECTED_BYTES, output.stdout.clone()) - })?; - - // Convert bytes to u64 in little-endian format - let value = u64::from_le_bytes(gates_bytes); - - Ok(value as u32) - } -} - -#[test] -fn gate_command() -> Result<(), BackendError> { - use tempfile::tempdir; - - let backend = crate::get_mock_backend()?; - - let temp_directory = tempdir().expect("could not create a temporary directory"); - let temp_directory_path = temp_directory.path(); - let bytecode_path = temp_directory_path.join("acir.gz"); - let crs_path = backend.backend_directory(); - - std::fs::File::create(&bytecode_path).expect("file should be created"); - - let gate_command = GatesCommand { crs_path, bytecode_path }; - - let output = gate_command.run(backend.binary_path())?; - // Mock backend always returns zero gates. - assert_eq!(output, 0); - - Ok(()) -} diff --git a/tooling/backend_interface/src/cli/info.rs b/tooling/backend_interface/src/cli/info.rs deleted file mode 100644 index 8ca3d4dd0a3..00000000000 --- a/tooling/backend_interface/src/cli/info.rs +++ /dev/null @@ -1,62 +0,0 @@ -use acvm::acir::circuit::ExpressionWidth; - -use serde::Deserialize; -use std::path::{Path, PathBuf}; - -use crate::BackendError; - -use super::string_from_stderr; - -pub(crate) struct InfoCommand { - pub(crate) crs_path: PathBuf, -} - -#[derive(Deserialize)] -struct InfoResponse { - language: LanguageResponse, -} - -#[derive(Deserialize)] -struct LanguageResponse { - name: String, - width: Option, -} - -impl InfoCommand { - pub(crate) fn run(self, binary_path: &Path) -> Result { - let mut command = std::process::Command::new(binary_path); - - command.arg("info").arg("-c").arg(self.crs_path).arg("-o").arg("-"); - - let output = command.output()?; - - if !output.status.success() { - return Err(BackendError::CommandFailed(string_from_stderr(&output.stderr))); - } - - let backend_info: InfoResponse = - serde_json::from_slice(&output.stdout).expect("Backend should return valid json"); - let expression_width: ExpressionWidth = match backend_info.language.name.as_str() { - "PLONK-CSAT" => { - let width = backend_info.language.width.unwrap(); - ExpressionWidth::Bounded { width } - } - "R1CS" => ExpressionWidth::Unbounded, - _ => panic!("Unknown Expression width configuration"), - }; - - Ok(expression_width) - } -} - -#[test] -fn info_command() -> Result<(), BackendError> { - let backend = crate::get_mock_backend()?; - let crs_path = backend.backend_directory(); - - let expression_width = InfoCommand { crs_path }.run(backend.binary_path())?; - - assert!(matches!(expression_width, ExpressionWidth::Bounded { width: 3 })); - - Ok(()) -} diff --git a/tooling/backend_interface/src/cli/mod.rs b/tooling/backend_interface/src/cli/mod.rs deleted file mode 100644 index b4dec859839..00000000000 --- a/tooling/backend_interface/src/cli/mod.rs +++ /dev/null @@ -1,41 +0,0 @@ -// Reference: https://github.com/AztecProtocol/aztec-packages/blob/master/barretenberg/cpp/src/barretenberg/bb/main.cpp - -mod contract; -mod gates; -mod info; -mod proof_as_fields; -mod prove; -mod verify; -mod version; -mod vk_as_fields; -mod write_vk; - -pub(crate) use contract::ContractCommand; -pub(crate) use gates::GatesCommand; -pub(crate) use info::InfoCommand; -pub(crate) use proof_as_fields::ProofAsFieldsCommand; -pub(crate) use prove::ProveCommand; -pub(crate) use verify::VerifyCommand; -pub(crate) use version::VersionCommand; -pub(crate) use vk_as_fields::VkAsFieldsCommand; -pub(crate) use write_vk::WriteVkCommand; - -#[test] -fn no_command_provided_works() -> Result<(), crate::BackendError> { - // This is a simple test to check that the binaries work - - let backend = crate::get_mock_backend()?; - - let output = std::process::Command::new(backend.binary_path()).output()?; - - let stderr = string_from_stderr(&output.stderr); - // Assert help message is printed due to no command being provided. - assert!(stderr.contains("Usage: mock_backend ")); - - Ok(()) -} - -// Converts a stderr byte array to a string (including invalid characters) -fn string_from_stderr(stderr: &[u8]) -> String { - String::from_utf8_lossy(stderr).to_string() -} diff --git a/tooling/backend_interface/src/cli/proof_as_fields.rs b/tooling/backend_interface/src/cli/proof_as_fields.rs deleted file mode 100644 index 7eb1c1ef35c..00000000000 --- a/tooling/backend_interface/src/cli/proof_as_fields.rs +++ /dev/null @@ -1,38 +0,0 @@ -use std::path::{Path, PathBuf}; - -use acvm::FieldElement; - -use crate::BackendError; - -use super::string_from_stderr; - -/// `ProofAsFieldsCommand` will call the barretenberg binary -/// to split a proof into a representation as [`FieldElement`]s. -pub(crate) struct ProofAsFieldsCommand { - pub(crate) proof_path: PathBuf, - pub(crate) vk_path: PathBuf, -} - -impl ProofAsFieldsCommand { - pub(crate) fn run(self, binary_path: &Path) -> Result, BackendError> { - let mut command = std::process::Command::new(binary_path); - - command - .arg("proof_as_fields") - .arg("-p") - .arg(self.proof_path) - .arg("-k") - .arg(self.vk_path) - .arg("-o") - .arg("-"); - - let output = command.output()?; - if output.status.success() { - let string_output = String::from_utf8(output.stdout).unwrap(); - serde_json::from_str(&string_output) - .map_err(|err| BackendError::CommandFailed(err.to_string())) - } else { - Err(BackendError::CommandFailed(string_from_stderr(&output.stderr))) - } - } -} diff --git a/tooling/backend_interface/src/cli/prove.rs b/tooling/backend_interface/src/cli/prove.rs deleted file mode 100644 index c63d8afab54..00000000000 --- a/tooling/backend_interface/src/cli/prove.rs +++ /dev/null @@ -1,66 +0,0 @@ -use std::path::{Path, PathBuf}; - -use crate::BackendError; - -use super::string_from_stderr; - -/// ProveCommand will call the barretenberg binary -/// to create a proof, given the witness and the bytecode. -/// -/// Note:Internally barretenberg will create and discard the -/// proving key, so this is not returned. -/// -/// The proof will be written to the specified output file. -pub(crate) struct ProveCommand { - pub(crate) crs_path: PathBuf, - pub(crate) bytecode_path: PathBuf, - pub(crate) witness_path: PathBuf, -} - -impl ProveCommand { - pub(crate) fn run(self, binary_path: &Path) -> Result, BackendError> { - let mut command = std::process::Command::new(binary_path); - - command - .arg("prove") - .arg("-c") - .arg(self.crs_path) - .arg("-b") - .arg(self.bytecode_path) - .arg("-w") - .arg(self.witness_path) - .arg("-o") - .arg("-"); - - let output = command.output()?; - if output.status.success() { - Ok(output.stdout) - } else { - Err(BackendError::CommandFailed(string_from_stderr(&output.stderr))) - } - } -} - -#[test] -fn prove_command() -> Result<(), BackendError> { - use tempfile::tempdir; - - let backend = crate::get_mock_backend()?; - - let temp_directory = tempdir().expect("could not create a temporary directory"); - let temp_directory_path = temp_directory.path(); - let bytecode_path = temp_directory_path.join("acir.gz"); - let witness_path = temp_directory_path.join("witness.tr"); - - std::fs::File::create(&bytecode_path).expect("file should be created"); - std::fs::File::create(&witness_path).expect("file should be created"); - - let crs_path = backend.backend_directory(); - let prove_command = ProveCommand { crs_path, bytecode_path, witness_path }; - - let proof = prove_command.run(backend.binary_path())?; - assert_eq!(proof, "proof".as_bytes()); - drop(temp_directory); - - Ok(()) -} diff --git a/tooling/backend_interface/src/cli/verify.rs b/tooling/backend_interface/src/cli/verify.rs deleted file mode 100644 index 1a4ba50b7de..00000000000 --- a/tooling/backend_interface/src/cli/verify.rs +++ /dev/null @@ -1,74 +0,0 @@ -use std::path::{Path, PathBuf}; - -use crate::BackendError; - -/// VerifyCommand will call the barretenberg binary -/// to verify a proof -pub(crate) struct VerifyCommand { - pub(crate) crs_path: PathBuf, - pub(crate) proof_path: PathBuf, - pub(crate) vk_path: PathBuf, -} - -impl VerifyCommand { - pub(crate) fn run(self, binary_path: &Path) -> Result { - let mut command = std::process::Command::new(binary_path); - - command - .arg("verify") - .arg("-c") - .arg(self.crs_path) - .arg("-p") - .arg(self.proof_path) - .arg("-k") - .arg(self.vk_path); - - let output = command.output()?; - - // We currently do not distinguish between an invalid proof and an error inside the backend. - Ok(output.status.success()) - } -} - -#[test] -fn verify_command() -> Result<(), BackendError> { - use tempfile::tempdir; - - use super::{ProveCommand, WriteVkCommand}; - use crate::proof_system::write_to_file; - - let backend = crate::get_mock_backend()?; - - let temp_directory = tempdir().expect("could not create a temporary directory"); - let temp_directory_path = temp_directory.path(); - let bytecode_path = temp_directory_path.join("acir.gz"); - let witness_path = temp_directory_path.join("witness.tr"); - let proof_path = temp_directory_path.join("1_mul.proof"); - let vk_path_output = temp_directory_path.join("vk"); - - let crs_path = backend.backend_directory(); - - std::fs::File::create(&bytecode_path).expect("file should be created"); - std::fs::File::create(&witness_path).expect("file should be created"); - - let write_vk_command = WriteVkCommand { - bytecode_path: bytecode_path.clone(), - crs_path: crs_path.clone(), - vk_path_output: vk_path_output.clone(), - }; - - write_vk_command.run(backend.binary_path())?; - - let prove_command = ProveCommand { crs_path: crs_path.clone(), bytecode_path, witness_path }; - let proof = prove_command.run(backend.binary_path())?; - - write_to_file(&proof, &proof_path); - - let verify_command = VerifyCommand { crs_path, proof_path, vk_path: vk_path_output }; - - let verified = verify_command.run(backend.binary_path())?; - assert!(verified); - - drop(temp_directory); - Ok(()) -} diff --git a/tooling/backend_interface/src/cli/version.rs b/tooling/backend_interface/src/cli/version.rs deleted file mode 100644 index 83ab72a870e..00000000000 --- a/tooling/backend_interface/src/cli/version.rs +++ /dev/null @@ -1,29 +0,0 @@ -use std::path::Path; - -use crate::BackendError; - -use super::string_from_stderr; - -/// VersionCommand will call the backend binary -/// to query installed version. -pub(crate) struct VersionCommand; - -impl VersionCommand { - pub(crate) fn run(self, binary_path: &Path) -> Result { - let mut command = std::process::Command::new(binary_path); - - command.arg("--version"); - - let output = command.output()?; - if output.status.success() { - match String::from_utf8(output.stdout) { - Ok(result) => Ok(result), - Err(_) => Err(BackendError::CommandFailed( - "Unexpected output from --version check.".to_owned(), - )), - } - } else { - Err(BackendError::CommandFailed(string_from_stderr(&output.stderr))) - } - } -} diff --git a/tooling/backend_interface/src/cli/vk_as_fields.rs b/tooling/backend_interface/src/cli/vk_as_fields.rs deleted file mode 100644 index 1b0212241c4..00000000000 --- a/tooling/backend_interface/src/cli/vk_as_fields.rs +++ /dev/null @@ -1,39 +0,0 @@ -use std::path::{Path, PathBuf}; - -use acvm::FieldElement; - -use crate::BackendError; - -use super::string_from_stderr; - -/// VkAsFieldsCommand will call the barretenberg binary -/// to split a verification key into a representation as [`FieldElement`]s. -/// -/// The hash of the verification key will also be returned. -pub(crate) struct VkAsFieldsCommand { - pub(crate) vk_path: PathBuf, -} - -impl VkAsFieldsCommand { - pub(crate) fn run( - self, - binary_path: &Path, - ) -> Result<(FieldElement, Vec), BackendError> { - let mut command = std::process::Command::new(binary_path); - - command.arg("vk_as_fields").arg("-k").arg(self.vk_path).arg("-o").arg("-"); - - let output = command.output()?; - if output.status.success() { - let string_output = String::from_utf8(output.stdout).unwrap(); - let mut fields: Vec = serde_json::from_str(&string_output) - .map_err(|err| BackendError::CommandFailed(err.to_string()))?; - - // The first element of this vector is the hash of the verification key, we want to split that off. - let hash = fields.remove(0); - Ok((hash, fields)) - } else { - Err(BackendError::CommandFailed(string_from_stderr(&output.stderr))) - } - } -} diff --git a/tooling/backend_interface/src/cli/write_vk.rs b/tooling/backend_interface/src/cli/write_vk.rs deleted file mode 100644 index da9fc04cbef..00000000000 --- a/tooling/backend_interface/src/cli/write_vk.rs +++ /dev/null @@ -1,58 +0,0 @@ -use std::path::{Path, PathBuf}; - -use super::string_from_stderr; -use crate::BackendError; - -/// WriteCommand will call the barretenberg binary -/// to write a verification key to a file -pub(crate) struct WriteVkCommand { - pub(crate) crs_path: PathBuf, - pub(crate) bytecode_path: PathBuf, - pub(crate) vk_path_output: PathBuf, -} - -impl WriteVkCommand { - #[tracing::instrument(level = "trace", name = "vk_generation", skip_all)] - pub(crate) fn run(self, binary_path: &Path) -> Result<(), BackendError> { - let mut command = std::process::Command::new(binary_path); - - command - .arg("write_vk") - .arg("-c") - .arg(self.crs_path) - .arg("-b") - .arg(self.bytecode_path) - .arg("-o") - .arg(self.vk_path_output); - - let output = command.output()?; - if output.status.success() { - Ok(()) - } else { - Err(BackendError::CommandFailed(string_from_stderr(&output.stderr))) - } - } -} - -#[test] -fn write_vk_command() -> Result<(), BackendError> { - use tempfile::tempdir; - - let backend = crate::get_mock_backend()?; - - let temp_directory = tempdir().expect("could not create a temporary directory"); - let temp_directory_path = temp_directory.path(); - let bytecode_path = temp_directory_path.join("acir.gz"); - let vk_path_output = temp_directory.path().join("vk"); - - let crs_path = backend.backend_directory(); - - std::fs::File::create(&bytecode_path).expect("file should be created"); - - let write_vk_command = WriteVkCommand { bytecode_path, crs_path, vk_path_output }; - - write_vk_command.run(backend.binary_path())?; - drop(temp_directory); - - Ok(()) -} diff --git a/tooling/backend_interface/src/download.rs b/tooling/backend_interface/src/download.rs deleted file mode 100644 index 60ecb14e642..00000000000 --- a/tooling/backend_interface/src/download.rs +++ /dev/null @@ -1,58 +0,0 @@ -use std::{ - io::{Cursor, ErrorKind}, - path::Path, -}; - -/// Downloads a zipped archive and unpacks the backend binary to `destination_path`. -/// -/// # Backend Requirements -/// -/// In order for a backend to be compatible with this function: -/// - `backend_url` must serve a gzipped tarball. -/// - The tarball must only contain the backend's binary. -/// - The binary file must be located at the archive root. -pub fn download_backend(backend_url: &str, destination_path: &Path) -> std::io::Result<()> { - use flate2::read::GzDecoder; - use tar::Archive; - use tempfile::tempdir; - - // Download sources - let compressed_file: Cursor> = download_binary_from_url(backend_url).map_err(|_| { - std::io::Error::new( - ErrorKind::Other, - format!("Could not download backend from install url: {backend_url}"), - ) - })?; - - // Unpack the tarball - let gz_decoder = GzDecoder::new(compressed_file); - let mut archive = Archive::new(gz_decoder); - - let temp_directory = tempdir()?; - archive.unpack(&temp_directory)?; - - // Assume that the archive contains a single file which is the backend binary. - let mut archive_files = std::fs::read_dir(&temp_directory)?; - let temp_binary_path = archive_files.next().unwrap()?.path(); - - // Create directory to place binary in. - std::fs::create_dir_all(destination_path.parent().unwrap())?; - - // Rename the binary to the desired name - std::fs::copy(temp_binary_path, destination_path)?; - - drop(temp_directory); - - Ok(()) -} - -/// Try to download the specified URL into a buffer which is returned. -fn download_binary_from_url(url: &str) -> Result>, reqwest::Error> { - let response = reqwest::blocking::get(url)?; - - let bytes = response.bytes()?; - - // TODO: Check SHA of downloaded binary - - Ok(Cursor::new(bytes.to_vec())) -} diff --git a/tooling/backend_interface/src/lib.rs b/tooling/backend_interface/src/lib.rs deleted file mode 100644 index eab98852555..00000000000 --- a/tooling/backend_interface/src/lib.rs +++ /dev/null @@ -1,150 +0,0 @@ -#![warn(unused_crate_dependencies, unused_extern_crates)] -#![warn(unreachable_pub)] - -use std::path::PathBuf; - -mod cli; -mod download; -mod proof_system; -mod smart_contract; - -pub use bb_abstraction_leaks::ACVM_BACKEND_BARRETENBERG; -use bb_abstraction_leaks::BB_VERSION; -use cli::VersionCommand; -pub use download::download_backend; -use tracing::warn; - -const BACKENDS_DIR: &str = ".nargo/backends"; - -pub fn backends_directory() -> PathBuf { - let home_directory = dirs::home_dir().unwrap(); - home_directory.join(BACKENDS_DIR) -} - -#[cfg(test)] -test_binary::build_test_binary_once!(mock_backend, "test-binaries"); - -#[cfg(test)] -fn get_mock_backend() -> Result { - std::env::set_var("NARGO_BACKEND_PATH", path_to_mock_backend()); - - let mock_backend = Backend::new("mock_backend".to_string()); - mock_backend.assert_binary_exists()?; - - Ok(mock_backend) -} - -#[derive(Debug, thiserror::Error)] -pub enum BackendError { - #[error(transparent)] - IoError(#[from] std::io::Error), - - #[error("Backend binary does not exist")] - MissingBinary, - - #[error("The backend responded with a malformed UTF8 byte vector: {0:?}")] - InvalidUTF8Vector(Vec), - - #[error( - "The backend responded with a unexpected number of bytes. Expected: {0} but got {} ({1:?})", .1.len() - )] - UnexpectedNumberOfBytes(usize, Vec), - - #[error("The backend encountered an error: {0:?}")] - CommandFailed(String), -} - -#[derive(Debug)] -pub struct Backend { - name: String, - binary_path: PathBuf, -} - -impl Backend { - pub fn new(name: String) -> Backend { - let binary_path = if let Some(binary_path) = std::env::var_os("NARGO_BACKEND_PATH") { - PathBuf::from(binary_path) - } else { - const BINARY_NAME: &str = "backend_binary"; - - backends_directory().join(&name).join(BINARY_NAME) - }; - Backend { name, binary_path } - } - - pub fn name(&self) -> &str { - &self.name - } - - fn binary_path(&self) -> &PathBuf { - &self.binary_path - } - - fn assert_binary_exists(&self) -> Result<&PathBuf, BackendError> { - let binary_path = self.binary_path(); - if binary_path.is_file() { - Ok(binary_path) - } else { - if self.name == ACVM_BACKEND_BARRETENBERG { - // If we're trying to use barretenberg, automatically go and install it. - let bb_url = std::env::var("BB_BINARY_URL") - .unwrap_or_else(|_| bb_abstraction_leaks::BB_DOWNLOAD_URL.to_owned()); - download_backend(&bb_url, binary_path)?; - return Ok(binary_path); - } - Err(BackendError::MissingBinary) - } - } - - fn backend_directory(&self) -> PathBuf { - self.binary_path() - .parent() - .expect("backend binary should have a parent directory") - .to_path_buf() - } - - fn crs_directory(&self) -> PathBuf { - self.backend_directory().join("crs") - } - - fn assert_correct_version(&self) -> Result<&PathBuf, BackendError> { - let binary_path = self.binary_path(); - if binary_path.to_string_lossy().contains(ACVM_BACKEND_BARRETENBERG) { - match VersionCommand.run(binary_path) { - // If version matches then do nothing. - Ok(version_string) if version_string == BB_VERSION => (), - - // If version doesn't match then download the correct version. - Ok(version_string) => { - warn!("`{ACVM_BACKEND_BARRETENBERG}` version `{version_string}` is different from expected `{BB_VERSION}`. Downloading expected version..."); - let bb_url = std::env::var("BB_BINARY_URL") - .unwrap_or_else(|_| bb_abstraction_leaks::BB_DOWNLOAD_URL.to_owned()); - download_backend(&bb_url, binary_path)?; - } - - // If `bb` fails to report its version, then attempt to fix it by re-downloading the binary. - Err(_) => { - warn!("Could not determine version of `{ACVM_BACKEND_BARRETENBERG}`. Downloading expected version..."); - let bb_url = std::env::var("BB_BINARY_URL") - .unwrap_or_else(|_| bb_abstraction_leaks::BB_DOWNLOAD_URL.to_owned()); - download_backend(&bb_url, binary_path)?; - } - } - } - Ok(binary_path) - } -} - -#[cfg(test)] -mod backend { - use crate::{Backend, BackendError}; - - #[test] - fn raises_error_on_missing_binary() { - let bad_backend = Backend::new("i_don't_exist".to_string()); - - let binary_path = bad_backend.assert_binary_exists(); - - assert!(matches!(binary_path, Err(BackendError::MissingBinary))); - } -} diff --git a/tooling/backend_interface/src/proof_system.rs b/tooling/backend_interface/src/proof_system.rs deleted file mode 100644 index 485381006df..00000000000 --- a/tooling/backend_interface/src/proof_system.rs +++ /dev/null @@ -1,187 +0,0 @@ -use std::fs::File; -use std::io::Write; -use std::path::Path; - -use acvm::acir::{ - circuit::{Circuit, ExpressionWidth}, - native_types::WitnessMap, -}; -use acvm::FieldElement; -use tempfile::tempdir; -use tracing::warn; - -use crate::cli::{ - GatesCommand, InfoCommand, ProofAsFieldsCommand, ProveCommand, VerifyCommand, - VkAsFieldsCommand, WriteVkCommand, -}; -use crate::{Backend, BackendError}; - -impl Backend { - pub fn get_exact_circuit_size(&self, circuit: &Circuit) -> Result { - let binary_path = self.assert_binary_exists()?; - self.assert_correct_version()?; - - let temp_directory = tempdir().expect("could not create a temporary directory"); - let temp_directory = temp_directory.path().to_path_buf(); - - // Create a temporary file for the circuit - let circuit_path = temp_directory.join("circuit").with_extension("bytecode"); - let serialized_circuit = Circuit::serialize_circuit(circuit); - write_to_file(&serialized_circuit, &circuit_path); - - GatesCommand { crs_path: self.crs_directory(), bytecode_path: circuit_path } - .run(binary_path) - } - - pub fn get_backend_info(&self) -> Result { - let binary_path = self.assert_binary_exists()?; - self.assert_correct_version()?; - InfoCommand { crs_path: self.crs_directory() }.run(binary_path) - } - - /// If we cannot get a valid backend, returns `ExpressionWidth::Bound { width: 3 }`` - /// The function also prints a message saying we could not find a backend - pub fn get_backend_info_or_default(&self) -> ExpressionWidth { - if let Ok(expression_width) = self.get_backend_info() { - expression_width - } else { - warn!( - "No valid backend found, ExpressionWidth defaulting to Bounded with a width of 3" - ); - ExpressionWidth::Bounded { width: 3 } - } - } - - #[tracing::instrument(level = "trace", skip_all)] - pub fn prove( - &self, - circuit: &Circuit, - witness_values: WitnessMap, - ) -> Result, BackendError> { - let binary_path = self.assert_binary_exists()?; - self.assert_correct_version()?; - - let temp_directory = tempdir().expect("could not create a temporary directory"); - let temp_directory = temp_directory.path().to_path_buf(); - - // Create a temporary file for the witness - let serialized_witnesses: Vec = - witness_values.try_into().expect("could not serialize witness map"); - let witness_path = temp_directory.join("witness").with_extension("tr"); - write_to_file(&serialized_witnesses, &witness_path); - - // Create a temporary file for the circuit - // - let bytecode_path = temp_directory.join("circuit").with_extension("bytecode"); - let serialized_circuit = Circuit::serialize_circuit(circuit); - write_to_file(&serialized_circuit, &bytecode_path); - - // Create proof and store it in the specified path - let proof_with_public_inputs = - ProveCommand { crs_path: self.crs_directory(), bytecode_path, witness_path } - .run(binary_path)?; - - let proof = bb_abstraction_leaks::remove_public_inputs( - circuit.public_inputs().0.len(), - &proof_with_public_inputs, - ); - Ok(proof) - } - - #[tracing::instrument(level = "trace", skip_all)] - pub fn verify( - &self, - proof: &[u8], - public_inputs: WitnessMap, - circuit: &Circuit, - ) -> Result { - let binary_path = self.assert_binary_exists()?; - self.assert_correct_version()?; - - let temp_directory = tempdir().expect("could not create a temporary directory"); - let temp_directory = temp_directory.path().to_path_buf(); - - // Create a temporary file for the proof - let proof_with_public_inputs = - bb_abstraction_leaks::prepend_public_inputs(proof.to_vec(), public_inputs); - let proof_path = temp_directory.join("proof").with_extension("proof"); - write_to_file(&proof_with_public_inputs, &proof_path); - - // Create a temporary file for the circuit - let bytecode_path = temp_directory.join("circuit").with_extension("bytecode"); - 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 - let vk_path = temp_directory.join("vk"); - - WriteVkCommand { - crs_path: self.crs_directory(), - bytecode_path, - vk_path_output: vk_path.clone(), - } - .run(binary_path)?; - - // Verify the proof - VerifyCommand { crs_path: self.crs_directory(), proof_path, vk_path }.run(binary_path) - } - - pub fn get_intermediate_proof_artifacts( - &self, - circuit: &Circuit, - proof: &[u8], - public_inputs: WitnessMap, - ) -> Result<(Vec, FieldElement, Vec), BackendError> { - let binary_path = self.assert_binary_exists()?; - self.assert_correct_version()?; - - let temp_directory = tempdir().expect("could not create a temporary directory"); - let temp_directory = temp_directory.path().to_path_buf(); - - // Create a temporary file for the circuit - // - let bytecode_path = temp_directory.join("circuit").with_extension("bytecode"); - 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 - let vk_path = temp_directory.join("vk"); - - WriteVkCommand { - crs_path: self.crs_directory(), - bytecode_path, - vk_path_output: vk_path.clone(), - } - .run(binary_path)?; - - // Create a temporary file for the proof - - let proof_with_public_inputs = - bb_abstraction_leaks::prepend_public_inputs(proof.to_vec(), public_inputs); - let proof_path = temp_directory.join("proof").with_extension("proof"); - write_to_file(&proof_with_public_inputs, &proof_path); - - // Now ready to generate intermediate artifacts. - - let proof_as_fields = - ProofAsFieldsCommand { proof_path, vk_path: vk_path.clone() }.run(binary_path)?; - - let (vk_hash, vk_as_fields) = VkAsFieldsCommand { vk_path }.run(binary_path)?; - - Ok((proof_as_fields, vk_hash, vk_as_fields)) - } -} - -pub(super) fn write_to_file(bytes: &[u8], path: &Path) -> String { - let display = path.display(); - - let mut file = match File::create(path) { - Err(why) => panic!("couldn't create {display}: {why}"), - Ok(file) => file, - }; - - match file.write_all(bytes) { - Err(why) => panic!("couldn't write to {display}: {why}"), - Ok(_) => display.to_string(), - } -} diff --git a/tooling/backend_interface/src/smart_contract.rs b/tooling/backend_interface/src/smart_contract.rs deleted file mode 100644 index 5af75e48389..00000000000 --- a/tooling/backend_interface/src/smart_contract.rs +++ /dev/null @@ -1,69 +0,0 @@ -use super::proof_system::write_to_file; -use crate::{ - cli::{ContractCommand, WriteVkCommand}, - Backend, BackendError, -}; -use acvm::acir::circuit::Circuit; -use tempfile::tempdir; - -impl Backend { - pub fn eth_contract(&self, circuit: &Circuit) -> Result { - let binary_path = self.assert_binary_exists()?; - self.assert_correct_version()?; - - let temp_directory = tempdir().expect("could not create a temporary directory"); - let temp_directory_path = temp_directory.path().to_path_buf(); - - // Create a temporary file for the circuit - let bytecode_path = temp_directory_path.join("circuit").with_extension("bytecode"); - 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 - let vk_path = temp_directory_path.join("vk"); - - WriteVkCommand { - crs_path: self.crs_directory(), - bytecode_path, - vk_path_output: vk_path.clone(), - } - .run(binary_path)?; - - ContractCommand { crs_path: self.crs_directory(), vk_path }.run(binary_path) - } -} - -#[cfg(test)] -mod tests { - use std::collections::BTreeSet; - - use acvm::acir::{ - circuit::{Circuit, ExpressionWidth, Opcode, PublicInputs}, - native_types::{Expression, Witness}, - }; - - use crate::{get_mock_backend, BackendError}; - - #[test] - fn test_smart_contract() -> Result<(), BackendError> { - let expression = &(Witness(1) + Witness(2)) - &Expression::from(Witness(3)); - let constraint = Opcode::AssertZero(expression); - - let circuit = Circuit { - current_witness_index: 4, - expression_width: ExpressionWidth::Bounded { width: 3 }, - opcodes: vec![constraint], - private_parameters: BTreeSet::from([Witness(1), Witness(2)]), - public_parameters: PublicInputs::default(), - return_values: PublicInputs::default(), - assert_messages: Default::default(), - recursive: false, - }; - - let contract = get_mock_backend()?.eth_contract(&circuit)?; - - assert!(contract.contains("contract VerifierContract")); - - Ok(()) - } -} diff --git a/tooling/backend_interface/test-binaries/mock_backend/Cargo.lock b/tooling/backend_interface/test-binaries/mock_backend/Cargo.lock deleted file mode 100644 index 3c14a936907..00000000000 --- a/tooling/backend_interface/test-binaries/mock_backend/Cargo.lock +++ /dev/null @@ -1,223 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "anstream" -version = "0.6.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e2e1ebcb11de5c03c67de28a7df593d32191b44939c482e97702baaaa6ab6a5" -dependencies = [ - "anstyle", - "anstyle-parse", - "anstyle-query", - "anstyle-wincon", - "colorchoice", - "utf8parse", -] - -[[package]] -name = "anstyle" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" - -[[package]] -name = "anstyle-parse" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" -dependencies = [ - "utf8parse", -] - -[[package]] -name = "anstyle-query" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" -dependencies = [ - "windows-sys", -] - -[[package]] -name = "anstyle-wincon" -version = "3.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" -dependencies = [ - "anstyle", - "windows-sys", -] - -[[package]] -name = "clap" -version = "4.4.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e578d6ec4194633722ccf9544794b71b1385c3c027efe0c55db226fc880865c" -dependencies = [ - "clap_builder", - "clap_derive", -] - -[[package]] -name = "clap_builder" -version = "4.4.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4df4df40ec50c46000231c914968278b1eb05098cf8f1b3a518a95030e71d1c7" -dependencies = [ - "anstream", - "anstyle", - "clap_lex", - "strsim", -] - -[[package]] -name = "clap_derive" -version = "4.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "clap_lex" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" - -[[package]] -name = "colorchoice" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" - -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" - -[[package]] -name = "mock_backend" -version = "0.1.0" -dependencies = [ - "clap", -] - -[[package]] -name = "proc-macro2" -version = "1.0.76" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - -[[package]] -name = "syn" -version = "2.0.48" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "unicode-ident" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "utf8parse" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" - -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-targets" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" diff --git a/tooling/backend_interface/test-binaries/mock_backend/Cargo.toml b/tooling/backend_interface/test-binaries/mock_backend/Cargo.toml deleted file mode 100644 index f527b03a7b9..00000000000 --- a/tooling/backend_interface/test-binaries/mock_backend/Cargo.toml +++ /dev/null @@ -1,11 +0,0 @@ -[workspace] - -[package] -name = "mock_backend" -version = "0.1.0" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -clap = { version = "4.3.19", features = ["derive"] } diff --git a/tooling/backend_interface/test-binaries/mock_backend/src/contract_cmd.rs b/tooling/backend_interface/test-binaries/mock_backend/src/contract_cmd.rs deleted file mode 100644 index 7ee41121d61..00000000000 --- a/tooling/backend_interface/test-binaries/mock_backend/src/contract_cmd.rs +++ /dev/null @@ -1,21 +0,0 @@ -use clap::Args; -use std::io::Write; -use std::path::PathBuf; - -#[derive(Debug, Clone, Args)] -pub(crate) struct ContractCommand { - #[clap(short = 'c')] - pub(crate) crs_path: Option, - - #[clap(short = 'k')] - pub(crate) vk_path: PathBuf, - - #[clap(short = 'o')] - pub(crate) contract_path: PathBuf, -} - -pub(crate) fn run(args: ContractCommand) { - assert!(args.vk_path.is_file(), "Could not find vk file at provided path"); - - std::io::stdout().write_all(b"contract VerifierContract {}").unwrap(); -} diff --git a/tooling/backend_interface/test-binaries/mock_backend/src/gates_cmd.rs b/tooling/backend_interface/test-binaries/mock_backend/src/gates_cmd.rs deleted file mode 100644 index 3cc397d3292..00000000000 --- a/tooling/backend_interface/test-binaries/mock_backend/src/gates_cmd.rs +++ /dev/null @@ -1,18 +0,0 @@ -use clap::Args; -use std::io::Write; -use std::path::PathBuf; - -#[derive(Debug, Clone, Args)] -pub(crate) struct GatesCommand { - #[clap(short = 'c')] - pub(crate) crs_path: Option, - - #[clap(short = 'b')] - pub(crate) bytecode_path: PathBuf, -} - -pub(crate) fn run(args: GatesCommand) { - assert!(args.bytecode_path.is_file(), "Could not find bytecode file at provided path"); - - std::io::stdout().write_all(&0u64.to_le_bytes()).unwrap(); -} diff --git a/tooling/backend_interface/test-binaries/mock_backend/src/info_cmd.rs b/tooling/backend_interface/test-binaries/mock_backend/src/info_cmd.rs deleted file mode 100644 index fd8cf602125..00000000000 --- a/tooling/backend_interface/test-binaries/mock_backend/src/info_cmd.rs +++ /dev/null @@ -1,40 +0,0 @@ -use clap::Args; -use std::io::Write; -use std::path::PathBuf; - -const INFO_RESPONSE: &str = r#"{ - "language": { - "name": "PLONK-CSAT", - "width": 3 - }, - "opcodes_supported": ["arithmetic", "directive", "brillig", "memory_init", "memory_op"], - "black_box_functions_supported": [ - "and", - "xor", - "range", - "sha256", - "blake2s", - "blake3", - "keccak256", - "schnorr_verify", - "pedersen", - "pedersen_hash", - "ecdsa_secp256k1", - "ecdsa_secp256r1", - "fixed_base_scalar_mul", - "recursive_aggregation" - ] -}"#; - -#[derive(Debug, Clone, Args)] -pub(crate) struct InfoCommand { - #[clap(short = 'c')] - pub(crate) crs_path: Option, - - #[clap(short = 'o')] - pub(crate) info_path: Option, -} - -pub(crate) fn run(_args: InfoCommand) { - std::io::stdout().write_all(INFO_RESPONSE.as_bytes()).unwrap(); -} diff --git a/tooling/backend_interface/test-binaries/mock_backend/src/main.rs b/tooling/backend_interface/test-binaries/mock_backend/src/main.rs deleted file mode 100644 index ef8819af94b..00000000000 --- a/tooling/backend_interface/test-binaries/mock_backend/src/main.rs +++ /dev/null @@ -1,44 +0,0 @@ -#![forbid(unsafe_code)] -#![warn(unreachable_pub)] -#![warn(clippy::semicolon_if_nothing_returned)] -#![cfg_attr(not(test), warn(unused_crate_dependencies, unused_extern_crates))] - -use clap::{Parser, Subcommand}; - -mod contract_cmd; -mod gates_cmd; -mod info_cmd; -mod prove_cmd; -mod verify_cmd; -mod write_vk_cmd; - -#[derive(Parser, Debug)] -#[command(name = "mock_backend")] -struct BackendCli { - #[command(subcommand)] - command: BackendCommand, -} - -#[derive(Subcommand, Clone, Debug)] -enum BackendCommand { - Info(info_cmd::InfoCommand), - Contract(contract_cmd::ContractCommand), - Gates(gates_cmd::GatesCommand), - Prove(prove_cmd::ProveCommand), - Verify(verify_cmd::VerifyCommand), - #[command(name = "write_vk")] - WriteVk(write_vk_cmd::WriteVkCommand), -} - -fn main() { - let BackendCli { command } = BackendCli::parse(); - - match command { - BackendCommand::Info(args) => info_cmd::run(args), - BackendCommand::Contract(args) => contract_cmd::run(args), - BackendCommand::Gates(args) => gates_cmd::run(args), - BackendCommand::Prove(args) => prove_cmd::run(args), - BackendCommand::Verify(args) => verify_cmd::run(args), - BackendCommand::WriteVk(args) => write_vk_cmd::run(args), - }; -} diff --git a/tooling/backend_interface/test-binaries/mock_backend/src/prove_cmd.rs b/tooling/backend_interface/test-binaries/mock_backend/src/prove_cmd.rs deleted file mode 100644 index 3967778d4e8..00000000000 --- a/tooling/backend_interface/test-binaries/mock_backend/src/prove_cmd.rs +++ /dev/null @@ -1,25 +0,0 @@ -use clap::Args; -use std::io::Write; -use std::path::PathBuf; - -#[derive(Debug, Clone, Args)] -pub(crate) struct ProveCommand { - #[clap(short = 'c')] - pub(crate) crs_path: Option, - - #[clap(short = 'b')] - pub(crate) bytecode_path: PathBuf, - - #[clap(short = 'w')] - pub(crate) witness_path: PathBuf, - - #[clap(short = 'o')] - pub(crate) proof_path: PathBuf, -} - -pub(crate) fn run(args: ProveCommand) { - assert!(args.bytecode_path.is_file(), "Could not find bytecode file at provided path"); - assert!(args.witness_path.is_file(), "Could not find witness file at provided path"); - - std::io::stdout().write_all(b"proof").unwrap(); -} diff --git a/tooling/backend_interface/test-binaries/mock_backend/src/verify_cmd.rs b/tooling/backend_interface/test-binaries/mock_backend/src/verify_cmd.rs deleted file mode 100644 index 1a715eea880..00000000000 --- a/tooling/backend_interface/test-binaries/mock_backend/src/verify_cmd.rs +++ /dev/null @@ -1,24 +0,0 @@ -use clap::Args; -use std::path::PathBuf; - -#[derive(Debug, Clone, Args)] -pub(crate) struct VerifyCommand { - #[clap(short = 'c')] - pub(crate) crs_path: Option, - - #[clap(short = 'p')] - pub(crate) proof_path: PathBuf, - - #[clap(short = 'k')] - pub(crate) vk_path: PathBuf, - - #[clap(short = 'r')] - pub(crate) is_recursive: bool, -} - -pub(crate) fn run(args: VerifyCommand) { - assert!(args.vk_path.is_file(), "Could not find verification key file at provided path"); - assert!(args.proof_path.is_file(), "Could not find proof file at provided path"); - - std::fs::write(args.proof_path, "proof").unwrap(); -} diff --git a/tooling/backend_interface/test-binaries/mock_backend/src/write_vk_cmd.rs b/tooling/backend_interface/test-binaries/mock_backend/src/write_vk_cmd.rs deleted file mode 100644 index fcee224e85b..00000000000 --- a/tooling/backend_interface/test-binaries/mock_backend/src/write_vk_cmd.rs +++ /dev/null @@ -1,20 +0,0 @@ -use clap::Args; -use std::path::PathBuf; - -#[derive(Debug, Clone, Args)] -pub(crate) struct WriteVkCommand { - #[clap(short = 'c')] - pub(crate) crs_path: Option, - - #[clap(short = 'b')] - pub(crate) bytecode_path: PathBuf, - - #[clap(short = 'o')] - pub(crate) vk_path: PathBuf, -} - -pub(crate) fn run(args: WriteVkCommand) { - assert!(args.bytecode_path.is_file(), "Could not find bytecode file at provided path"); - - std::fs::write(args.vk_path, "vk").unwrap(); -} diff --git a/tooling/bb_abstraction_leaks/Cargo.toml b/tooling/bb_abstraction_leaks/Cargo.toml deleted file mode 100644 index 972c78831a7..00000000000 --- a/tooling/bb_abstraction_leaks/Cargo.toml +++ /dev/null @@ -1,17 +0,0 @@ -[package] -name = "bb_abstraction_leaks" -description = "A crate which encapsulates knowledge about Barretenberg which is currently leaking into Nargo" -version = "0.11.0" -authors.workspace = true -edition.workspace = true -rust-version.workspace = true -license.workspace = true - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -acvm.workspace = true - -[build-dependencies] -build-target = "0.4.0" -const_format.workspace = true diff --git a/tooling/bb_abstraction_leaks/build.rs b/tooling/bb_abstraction_leaks/build.rs deleted file mode 100644 index f9effd5d991..00000000000 --- a/tooling/bb_abstraction_leaks/build.rs +++ /dev/null @@ -1,58 +0,0 @@ -use build_target::{Arch, Os}; -use const_format::formatcp; - -// Useful for printing debugging messages during the build -// macro_rules! p { -// ($($tokens: tt)*) => { -// println!("cargo:warning={}", format!($($tokens)*)) -// } -// } - -const USERNAME: &str = "AztecProtocol"; -const REPO: &str = "aztec-packages"; -const VERSION: &str = "0.24.0"; -const TAG: &str = formatcp!("aztec-packages-v{}", VERSION); - -const API_URL: &str = - formatcp!("https://github.com/{}/{}/releases/download/{}", USERNAME, REPO, TAG); - -fn main() -> Result<(), String> { - // We need to inject which OS we're building for so that we can download the correct barretenberg binary. - let os = match build_target::target_os().unwrap() { - os @ (Os::Linux | Os::MacOs) => os, - Os::Windows => todo!("Windows is not currently supported"), - os_name => panic!("Unsupported OS {os_name}"), - }; - - let arch = match build_target::target_arch().unwrap() { - arch @ (Arch::X86_64 | Arch::AARCH64) => arch, - arch_name => panic!("Unsupported Architecture {arch_name}"), - }; - - // Arm builds of linux are not supported - // We do not panic because we allow users to run nargo without a backend. - if let (Os::Linux, Arch::AARCH64) = (&os, &arch) { - println!( - "cargo:warning=ARM64 builds of linux are not supported for the barretenberg binary" - ); - }; - - println!("cargo:rustc-env=BB_BINARY_URL={}", get_bb_download_url(arch, os)); - println!("cargo:rustc-env=BB_VERSION={}", VERSION); - - Ok(()) -} - -fn get_bb_download_url(target_arch: Arch, target_os: Os) -> String { - let archive_name = match target_os { - Os::Linux => "barretenberg-x86_64-linux-gnu.tar.gz", - Os::MacOs => match target_arch { - Arch::AARCH64 => "barretenberg-aarch64-apple-darwin.tar.gz", - Arch::X86_64 => "barretenberg-x86_64-apple-darwin.tar.gz", - arch => panic!("unsupported arch {arch}"), - }, - os => panic!("Unsupported OS {os}"), - }; - - format!("{API_URL}/{archive_name}") -} diff --git a/tooling/bb_abstraction_leaks/src/lib.rs b/tooling/bb_abstraction_leaks/src/lib.rs deleted file mode 100644 index 56a4f58cd21..00000000000 --- a/tooling/bb_abstraction_leaks/src/lib.rs +++ /dev/null @@ -1,26 +0,0 @@ -#![warn(unused_crate_dependencies, unused_extern_crates)] -#![warn(unreachable_pub)] - -use acvm::{acir::native_types::WitnessMap, FieldElement}; - -pub const ACVM_BACKEND_BARRETENBERG: &str = "acvm-backend-barretenberg"; -pub const BB_DOWNLOAD_URL: &str = env!("BB_BINARY_URL"); -pub const BB_VERSION: &str = env!("BB_VERSION"); - -/// Removes the public inputs which are prepended to a proof by Barretenberg. -pub fn remove_public_inputs(num_pub_inputs: usize, proof: &[u8]) -> Vec { - // Barretenberg prepends the public inputs onto the proof so we need to remove - // the first `num_pub_inputs` field elements. - let num_bytes_to_remove = num_pub_inputs * (FieldElement::max_num_bytes() as usize); - proof[num_bytes_to_remove..].to_vec() -} - -/// Prepends a set of public inputs to a proof. -pub fn prepend_public_inputs(proof: Vec, public_inputs: WitnessMap) -> Vec { - // We omit any unassigned witnesses. - // Witness values should be ordered by their index but we skip over any indices without an assignment. - let public_inputs_bytes = - public_inputs.into_iter().flat_map(|(_, assignment)| assignment.to_be_bytes()); - - public_inputs_bytes.chain(proof).collect() -} diff --git a/tooling/debugger/Cargo.toml b/tooling/debugger/Cargo.toml index 30d11db8cf3..a3bf12f5368 100644 --- a/tooling/debugger/Cargo.toml +++ b/tooling/debugger/Cargo.toml @@ -4,6 +4,7 @@ description = "Debugger for Noir" version.workspace = true authors.workspace = true edition.workspace = true +rust-version.workspace = true license.workspace = true [build-dependencies] diff --git a/tooling/debugger/build.rs b/tooling/debugger/build.rs index 26a8bc64b0e..ebdf2036894 100644 --- a/tooling/debugger/build.rs +++ b/tooling/debugger/build.rs @@ -7,8 +7,7 @@ use std::{env, fs}; const GIT_COMMIT: &&str = &"GIT_COMMIT"; fn main() { - // Only use build_data if the environment variable isn't set - // The environment variable is always set when working via Nix + // Only use build_data if the environment variable isn't set. if std::env::var(GIT_COMMIT).is_err() { build_data::set_GIT_COMMIT(); build_data::set_GIT_DIRTY(); diff --git a/tooling/debugger/ignored-tests.txt b/tooling/debugger/ignored-tests.txt index c472e828739..a9193896589 100644 --- a/tooling/debugger/ignored-tests.txt +++ b/tooling/debugger/ignored-tests.txt @@ -1,21 +1,17 @@ -array_dynamic_blackbox_input -array_sort -assign_ex -bit_shifts_comptime -brillig_cow -brillig_nested_arrays +bigint brillig_references brillig_to_bytes_integration debug_logs -double_verify_nested_proof -double_verify_proof +fold_after_inlined_calls +fold_basic +fold_basic_nested_call +fold_call_witness_condition +fold_complex_outputs +fold_distinct_return +fold_fibonacci +fold_numeric_generic_poseidon +is_unconstrained modulus -nested_array_dynamic -nested_array_in_slice -nested_arrays_from_brillig references -scalar_mul -signed_comparison -simple_2d_array -to_bytes_integration -bigint +regression_4709 +to_bytes_integration \ No newline at end of file diff --git a/tooling/debugger/src/context.rs b/tooling/debugger/src/context.rs index 515edf0bb06..9dc5c758c6f 100644 --- a/tooling/debugger/src/context.rs +++ b/tooling/debugger/src/context.rs @@ -1,18 +1,21 @@ use crate::foreign_calls::DebugForeignCallExecutor; +use acvm::acir::circuit::brillig::BrilligBytecode; use acvm::acir::circuit::{Circuit, Opcode, OpcodeLocation}; use acvm::acir::native_types::{Witness, WitnessMap}; -use acvm::brillig_vm::brillig::ForeignCallResult; -use acvm::brillig_vm::brillig::Value; +use acvm::brillig_vm::MemoryValue; use acvm::pwg::{ ACVMStatus, BrilligSolver, BrilligSolverStatus, ForeignCallWaitInfo, StepResult, ACVM, }; use acvm::{BlackBoxFunctionSolver, FieldElement}; -use nargo::artifacts::debug::DebugArtifact; +use codespan_reporting::files::{Files, SimpleFile}; +use fm::FileId; +use nargo::artifacts::debug::{DebugArtifact, StackFrame}; use nargo::errors::{ExecutionError, Location}; use nargo::NargoError; -use noirc_printable_type::{PrintableType, PrintableValue}; +use noirc_driver::DebugFile; +use std::collections::BTreeMap; use std::collections::{hash_set::Iter, HashSet}; #[derive(Debug)] @@ -23,36 +26,55 @@ pub(super) enum DebugCommandResult { Error(NargoError), } -pub(super) struct DebugContext<'a, B: BlackBoxFunctionSolver> { - acvm: ACVM<'a, B>, - brillig_solver: Option>, +pub(super) struct DebugContext<'a, B: BlackBoxFunctionSolver> { + acvm: ACVM<'a, FieldElement, B>, + brillig_solver: Option>, foreign_call_executor: Box, debug_artifact: &'a DebugArtifact, breakpoints: HashSet, + source_to_opcodes: BTreeMap>, + unconstrained_functions: &'a [BrilligBytecode], + + // Absolute (in terms of all the opcodes ACIR+Brillig) addresses of the ACIR + // opcodes with one additional entry for to indicate the last valid address. + acir_opcode_addresses: Vec, } -impl<'a, B: BlackBoxFunctionSolver> DebugContext<'a, B> { +impl<'a, B: BlackBoxFunctionSolver> DebugContext<'a, B> { pub(super) fn new( blackbox_solver: &'a B, - circuit: &'a Circuit, + circuit: &'a Circuit, debug_artifact: &'a DebugArtifact, - initial_witness: WitnessMap, + initial_witness: WitnessMap, foreign_call_executor: Box, + unconstrained_functions: &'a [BrilligBytecode], ) -> Self { + let source_to_opcodes = build_source_to_opcode_debug_mappings(debug_artifact); + let acir_opcode_addresses = build_acir_opcode_offsets(circuit, unconstrained_functions); Self { - acvm: ACVM::new(blackbox_solver, &circuit.opcodes, initial_witness), + // TODO: need to handle brillig pointer in the debugger + acvm: ACVM::new( + blackbox_solver, + &circuit.opcodes, + initial_witness, + unconstrained_functions, + &circuit.assert_messages, + ), brillig_solver: None, foreign_call_executor, debug_artifact, breakpoints: HashSet::new(), + source_to_opcodes, + unconstrained_functions, + acir_opcode_addresses, } } - pub(super) fn get_opcodes(&self) -> &[Opcode] { + pub(super) fn get_opcodes(&self) -> &[Opcode] { self.acvm.opcodes() } - pub(super) fn get_witness_map(&self) -> &WitnessMap { + pub(super) fn get_witness_map(&self) -> &WitnessMap { self.acvm.witness_map() } @@ -100,10 +122,48 @@ impl<'a, B: BlackBoxFunctionSolver> DebugContext<'a, B> { self.debug_artifact .file_map .get(&location.file) - .map(|file| file.path.starts_with("__debug/")) + .map(is_debug_file_in_debug_crate) .unwrap_or(false) } + /// Find an opcode location matching a source code location + // We apply some heuristics here, and there are four possibilities for the + // return value of this function: + // 1. the source location is not found -> None + // 2. an exact unique location is found (very rare) -> Some(opcode_location) + // 3. an exact but not unique location is found, ie. a source location may + // be mapped to multiple opcodes, and those may be disjoint, for example for + // functions called multiple times throughout the program + // -> return the first opcode in program order that matches the source location + // 4. exact location is not found, so an opcode for a nearby source location + // is returned (this again could actually be more than one opcodes) + // -> return the opcode for the next source line that is mapped + pub(super) fn find_opcode_for_source_location( + &self, + file_id: &FileId, + line: i64, + ) -> Option { + let line = line as usize; + let line_to_opcodes = self.source_to_opcodes.get(file_id)?; + let found_index = match line_to_opcodes.binary_search_by(|x| x.0.cmp(&line)) { + Ok(index) => { + // move backwards to find the first opcode which matches the line + let mut index = index; + while index > 0 && line_to_opcodes[index - 1].0 == line { + index -= 1; + } + line_to_opcodes[index].1 + } + Err(index) => { + if index >= line_to_opcodes.len() { + return None; + } + line_to_opcodes[index].1 + } + }; + Some(found_index) + } + /// 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 @@ -128,6 +188,9 @@ impl<'a, B: BlackBoxFunctionSolver> DebugContext<'a, B> { &self, opcode_location: &OpcodeLocation, ) -> Vec { + // TODO: this assumes we're debugging a program (ie. the DebugArtifact + // will contain a single DebugInfo), but this assumption doesn't hold + // for contracts self.debug_artifact.debug_symbols[0] .opcode_location(opcode_location) .map(|source_locations| { @@ -156,106 +219,55 @@ impl<'a, B: BlackBoxFunctionSolver> DebugContext<'a, B> { .collect() } - fn get_opcodes_sizes(&self) -> Vec { - self.get_opcodes() - .iter() - .map(|opcode| match opcode { - Opcode::Brillig(brillig_block) => brillig_block.bytecode.len(), - _ => 1, - }) - .collect() + /// Returns the absolute address of the opcode at the given location. + /// Absolute here means accounting for nested Brillig opcodes in BrilligCall + /// opcodes. + pub fn opcode_location_to_address(&self, location: &OpcodeLocation) -> usize { + match location { + OpcodeLocation::Acir(acir_index) => self.acir_opcode_addresses[*acir_index], + OpcodeLocation::Brillig { acir_index, brillig_index } => { + self.acir_opcode_addresses[*acir_index] + *brillig_index + } + } } - /// Offsets the given location by the given number of opcodes (including - /// Brillig opcodes). If the offset would move the location outside of a - /// valid circuit location, returns None and the number of remaining - /// opcodes/instructions left which span outside the valid range in the - /// second element of the returned tuple. - pub(super) fn offset_opcode_location( - &self, - location: &Option, - mut offset: i64, - ) -> (Option, i64) { - if offset == 0 { - return (*location, 0); + pub fn address_to_opcode_location(&self, address: usize) -> Option { + if address >= *self.acir_opcode_addresses.last().unwrap_or(&0) { + return None; } - let Some(location) = location else { - return (None, offset); - }; - - let (mut acir_index, mut brillig_index) = match location { - OpcodeLocation::Acir(acir_index) => (*acir_index, 0), - OpcodeLocation::Brillig { acir_index, brillig_index } => (*acir_index, *brillig_index), - }; - let opcode_sizes = self.get_opcodes_sizes(); - if offset > 0 { - while offset > 0 { - let opcode_size = opcode_sizes[acir_index] as i64 - brillig_index as i64; - if offset >= opcode_size { - acir_index += 1; - offset -= opcode_size; - brillig_index = 0; - } else { - brillig_index += offset as usize; - offset = 0; - } - if acir_index >= opcode_sizes.len() { - return (None, offset); - } + let location = match self.acir_opcode_addresses.binary_search(&address) { + Ok(found_index) => OpcodeLocation::Acir(found_index), + Err(insert_index) => { + let acir_index = insert_index - 1; + let base_offset = self.acir_opcode_addresses[acir_index]; + let brillig_index = address - base_offset; + OpcodeLocation::Brillig { acir_index, brillig_index } } - } else { - while offset < 0 { - if brillig_index > 0 { - if brillig_index > (-offset) as usize { - brillig_index -= (-offset) as usize; - offset = 0; - } else { - offset += brillig_index as i64; - brillig_index = 0; - } - } else { - if acir_index == 0 { - return (None, offset); - } - acir_index -= 1; - let opcode_size = opcode_sizes[acir_index] as i64; - if opcode_size <= -offset { - offset += opcode_size; - } else { - brillig_index = (opcode_size + offset) as usize; - offset = 0; - } - } - } - } - if brillig_index > 0 { - (Some(OpcodeLocation::Brillig { acir_index, brillig_index }), 0) - } else { - (Some(OpcodeLocation::Acir(acir_index)), 0) - } + }; + Some(location) } - pub(super) fn render_opcode_at_location(&self, location: &Option) -> String { + pub(super) fn render_opcode_at_location(&self, location: &OpcodeLocation) -> String { let opcodes = self.get_opcodes(); match location { - None => String::from("invalid"), - Some(OpcodeLocation::Acir(acir_index)) => { + OpcodeLocation::Acir(acir_index) => { let opcode = &opcodes[*acir_index]; - if let Opcode::Brillig(ref brillig) = opcode { - let first_opcode = &brillig.bytecode[0]; - format!("BRILLIG {first_opcode:?}") - } else { - format!("{opcode:?}") + match opcode { + Opcode::BrilligCall { id, .. } => { + let first_opcode = &self.unconstrained_functions[*id as usize].bytecode[0]; + format!("BRILLIG {first_opcode:?}") + } + _ => format!("{opcode:?}"), } } - Some(OpcodeLocation::Brillig { acir_index, brillig_index }) => { - if let Opcode::Brillig(ref brillig) = opcodes[*acir_index] { - let opcode = &brillig.bytecode[*brillig_index]; + OpcodeLocation::Brillig { acir_index, brillig_index } => match &opcodes[*acir_index] { + Opcode::BrilligCall { id, .. } => { + let bytecode = &self.unconstrained_functions[*id as usize].bytecode; + let opcode = &bytecode[*brillig_index]; format!(" | {opcode:?}") - } else { - String::from(" | invalid") } - } + _ => String::from(" | invalid"), + }, } } @@ -284,18 +296,19 @@ impl<'a, B: BlackBoxFunctionSolver> DebugContext<'a, B> { self.handle_foreign_call(foreign_call) } Err(err) => DebugCommandResult::Error(NargoError::ExecutionError( - ExecutionError::SolvingError(err), + // TODO: debugger does not not handle multiple acir calls + ExecutionError::SolvingError(err, None), )), } } - fn handle_foreign_call(&mut self, foreign_call: ForeignCallWaitInfo) -> DebugCommandResult { + 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) => { - let foreign_call_result = foreign_call_result - .get_brillig_output() - .unwrap_or(ForeignCallResult::default()); if let Some(mut solver) = self.brillig_solver.take() { solver.resolve_pending_foreign_call(foreign_call_result); self.brillig_solver = Some(solver); @@ -309,7 +322,7 @@ impl<'a, B: BlackBoxFunctionSolver> DebugContext<'a, B> { } } - fn handle_acvm_status(&mut self, status: ACVMStatus) -> DebugCommandResult { + fn handle_acvm_status(&mut self, status: ACVMStatus) -> DebugCommandResult { if let ACVMStatus::RequiresForeignCall(foreign_call) = status { return self.handle_foreign_call(foreign_call); } @@ -327,11 +340,15 @@ impl<'a, B: BlackBoxFunctionSolver> DebugContext<'a, B> { } } ACVMStatus::Failure(error) => DebugCommandResult::Error(NargoError::ExecutionError( - ExecutionError::SolvingError(error), + // TODO: debugger does not not handle multiple acir calls + ExecutionError::SolvingError(error, None), )), ACVMStatus::RequiresForeignCall(_) => { unreachable!("Unexpected pending foreign call resolution"); } + ACVMStatus::RequiresAcirCall(_) => { + todo!("Multiple ACIR calls are not supported"); + } } } @@ -340,7 +357,7 @@ impl<'a, B: BlackBoxFunctionSolver> DebugContext<'a, B> { return self.step_brillig_opcode(); } - match self.acvm.step_into_brillig_opcode() { + match self.acvm.step_into_brillig() { StepResult::IntoBrillig(solver) => { self.brillig_solver = Some(solver); self.step_brillig_opcode() @@ -349,20 +366,6 @@ impl<'a, B: BlackBoxFunctionSolver> DebugContext<'a, B> { } } - fn currently_executing_brillig(&self) -> bool { - if self.brillig_solver.is_some() { - return true; - } - - match self.get_current_opcode_location() { - Some(OpcodeLocation::Brillig { .. }) => true, - Some(OpcodeLocation::Acir(acir_index)) => { - matches!(self.get_opcodes()[acir_index], Opcode::Brillig(_)) - } - _ => false, - } - } - fn get_current_acir_index(&self) -> Option { self.get_current_opcode_location().map(|opcode_location| match opcode_location { OpcodeLocation::Acir(acir_index) => acir_index, @@ -386,8 +389,22 @@ impl<'a, B: BlackBoxFunctionSolver> DebugContext<'a, B> { } } + pub(super) fn is_executing_brillig(&self) -> bool { + if self.brillig_solver.is_some() { + return true; + } + + match self.get_current_opcode_location() { + Some(OpcodeLocation::Brillig { .. }) => true, + Some(OpcodeLocation::Acir(acir_index)) => { + matches!(self.get_opcodes()[acir_index], Opcode::BrilligCall { .. }) + } + _ => false, + } + } + pub(super) fn step_acir_opcode(&mut self) -> DebugCommandResult { - if self.currently_executing_brillig() { + if self.is_executing_brillig() { self.step_out_of_brillig_opcode() } else { let status = self.acvm.solve_opcode(); @@ -451,26 +468,28 @@ impl<'a, B: BlackBoxFunctionSolver> DebugContext<'a, B> { } } - 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_memory(&self) -> Option<&[Value]> { + pub(super) fn get_brillig_memory(&self) -> Option<&[MemoryValue]> { self.brillig_solver.as_ref().map(|solver| solver.get_memory()) } - pub(super) fn write_brillig_memory(&mut self, ptr: usize, value: FieldElement) { + pub(super) fn write_brillig_memory(&mut self, ptr: usize, value: FieldElement, bit_size: u32) { if let Some(solver) = self.brillig_solver.as_mut() { - solver.write_memory_at(ptr, value.into()); + solver.write_memory_at( + ptr, + MemoryValue::new_checked(value, bit_size) + .expect("Invalid value for the given bit size"), + ); } } - pub(super) fn get_variables(&self) -> Vec<(&str, &PrintableValue, &PrintableType)> { + pub(super) fn get_variables(&self) -> Vec { return self.foreign_call_executor.get_variables(); } + pub(super) fn current_stack_frame(&self) -> Option { + return self.foreign_call_executor.current_stack_frame(); + } + fn breakpoint_reached(&self) -> bool { if let Some(location) = self.get_current_opcode_location() { self.breakpoints.contains(&location) @@ -484,15 +503,17 @@ impl<'a, B: BlackBoxFunctionSolver> DebugContext<'a, B> { 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 + if acir_index < opcodes.len() { + match &opcodes[acir_index] { + Opcode::BrilligCall { id, .. } => { + let bytecode = &self.unconstrained_functions[*id as usize].bytecode; + brillig_index < bytecode.len() } + _ => false, } + } else { + false + } } } } @@ -521,32 +542,99 @@ impl<'a, B: BlackBoxFunctionSolver> DebugContext<'a, B> { matches!(self.acvm.get_status(), ACVMStatus::Solved) } - pub fn finalize(self) -> WitnessMap { + pub fn finalize(self) -> WitnessMap { self.acvm.finalize() } } +fn is_debug_file_in_debug_crate(debug_file: &DebugFile) -> bool { + debug_file.path.starts_with("__debug/") +} + +/// Builds a map from FileId to an ordered vector of tuples with line +/// numbers and opcode locations corresponding to those line numbers +fn build_source_to_opcode_debug_mappings( + debug_artifact: &DebugArtifact, +) -> BTreeMap> { + if debug_artifact.debug_symbols.is_empty() { + return BTreeMap::new(); + } + let locations = &debug_artifact.debug_symbols[0].locations; + let simple_files: BTreeMap<_, _> = debug_artifact + .file_map + .iter() + .filter(|(_, debug_file)| !is_debug_file_in_debug_crate(debug_file)) + .map(|(file_id, debug_file)| { + ( + file_id, + SimpleFile::new(debug_file.path.to_str().unwrap(), debug_file.source.as_str()), + ) + }) + .collect(); + + let mut result: BTreeMap> = BTreeMap::new(); + locations.iter().for_each(|(opcode_location, source_locations)| { + source_locations.iter().for_each(|source_location| { + let span = source_location.span; + let file_id = source_location.file; + let Some(file) = simple_files.get(&file_id) else { + return; + }; + let Ok(line_index) = file.line_index((), span.start() as usize) else { + return; + }; + let line_number = line_index + 1; + + result.entry(file_id).or_default().push((line_number, *opcode_location)); + }); + }); + result.iter_mut().for_each(|(_, file_locations)| file_locations.sort_by_key(|x| (x.0, x.1))); + + result +} + +fn build_acir_opcode_offsets( + circuit: &Circuit, + unconstrained_functions: &[BrilligBytecode], +) -> Vec { + let mut result = Vec::with_capacity(circuit.opcodes.len() + 1); + // address of the first opcode is always 0 + result.push(0); + circuit.opcodes.iter().fold(0, |acc, opcode| { + let acc = acc + + match opcode { + Opcode::BrilligCall { id, .. } => { + unconstrained_functions[*id as usize].bytecode.len() + } + _ => 1, + }; + // push the starting address of the next opcode + result.push(acc); + acc + }); + result +} + +// TODO: update all debugger tests to use unconstrained brillig pointers #[cfg(test)] mod tests { use super::*; - use crate::context::{DebugCommandResult, DebugContext}; use crate::foreign_calls::DefaultDebugForeignCallExecutor; use acvm::{ acir::{ circuit::{ - brillig::{Brillig, BrilligInputs, BrilligOutputs}, + brillig::{BrilligInputs, BrilligOutputs}, opcodes::BlockId, }, native_types::Expression, + AcirField, }, blackbox_solver::StubbedBlackBoxSolver, brillig_vm::brillig::{ BinaryFieldOp, HeapValueType, MemoryAddress, Opcode as BrilligOpcode, ValueOrArray, }, }; - use nargo::artifacts::debug::DebugArtifact; - use std::collections::BTreeMap; #[test] fn test_resolve_foreign_calls_stepping_into_brillig() { @@ -554,12 +642,7 @@ mod tests { let fe_1 = FieldElement::one(); let w_x = Witness(1); - let brillig_opcodes = Brillig { - inputs: vec![BrilligInputs::Single(Expression { - linear_combinations: vec![(fe_1, w_x)], - ..Expression::default() - })], - outputs: vec![], + let brillig_bytecode = BrilligBytecode { bytecode: vec![ BrilligOpcode::CalldataCopy { destination_address: MemoryAddress(0), @@ -568,7 +651,7 @@ mod tests { }, BrilligOpcode::Const { destination: MemoryAddress::from(1), - value: Value::from(fe_0), + value: fe_0, bit_size: 32, }, BrilligOpcode::ForeignCall { @@ -576,20 +659,27 @@ mod tests { destinations: vec![], destination_value_types: vec![], inputs: vec![ValueOrArray::MemoryAddress(MemoryAddress::from(0))], - input_value_types: vec![HeapValueType::Simple], + input_value_types: vec![HeapValueType::field()], }, BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 0 }, ], - predicate: None, }; - let opcodes = vec![Opcode::Brillig(brillig_opcodes)]; + let opcodes = vec![Opcode::BrilligCall { + id: 0, + inputs: vec![BrilligInputs::Single(Expression { + linear_combinations: vec![(fe_1, w_x)], + ..Expression::default() + })], + outputs: vec![], + predicate: None, + }]; + let brillig_funcs = &vec![brillig_bytecode]; let current_witness_index = 2; let circuit = &Circuit { current_witness_index, opcodes, ..Circuit::default() }; let debug_symbols = vec![]; let file_map = BTreeMap::new(); - let warnings = vec![]; - let debug_artifact = &DebugArtifact { debug_symbols, file_map, warnings }; + let debug_artifact = &DebugArtifact { debug_symbols, file_map }; let initial_witness = BTreeMap::from([(Witness(1), fe_1)]).into(); @@ -601,6 +691,7 @@ mod tests { debug_artifact, initial_witness, foreign_call_executor, + brillig_funcs, ); assert_eq!(context.get_current_opcode_location(), Some(OpcodeLocation::Acir(0))); @@ -652,18 +743,7 @@ mod tests { let w_z = Witness(3); // This Brillig block is equivalent to: z = x + y - let brillig_opcodes = Brillig { - inputs: vec![ - BrilligInputs::Single(Expression { - linear_combinations: vec![(fe_1, w_x)], - ..Expression::default() - }), - BrilligInputs::Single(Expression { - linear_combinations: vec![(fe_1, w_y)], - ..Expression::default() - }), - ], - outputs: vec![BrilligOutputs::Simple(w_z)], + let brillig_bytecode = BrilligBytecode { bytecode: vec![ BrilligOpcode::CalldataCopy { destination_address: MemoryAddress(0), @@ -678,11 +758,24 @@ mod tests { }, BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 1 }, ], - predicate: None, }; let opcodes = vec![ // z = x + y - Opcode::Brillig(brillig_opcodes), + Opcode::BrilligCall { + id: 0, + inputs: vec![ + BrilligInputs::Single(Expression { + linear_combinations: vec![(fe_1, w_x)], + ..Expression::default() + }), + BrilligInputs::Single(Expression { + linear_combinations: vec![(fe_1, w_y)], + ..Expression::default() + }), + ], + outputs: vec![BrilligOutputs::Simple(w_z)], + predicate: None, + }, // x + y - z = 0 Opcode::AssertZero(Expression { mul_terms: vec![], @@ -695,19 +788,20 @@ mod tests { let debug_symbols = vec![]; let file_map = BTreeMap::new(); - let warnings = vec![]; - let debug_artifact = &DebugArtifact { debug_symbols, file_map, warnings }; + let debug_artifact = &DebugArtifact { debug_symbols, file_map }; let initial_witness = BTreeMap::from([(Witness(1), fe_1), (Witness(2), fe_1)]).into(); let foreign_call_executor = Box::new(DefaultDebugForeignCallExecutor::from_artifact(true, debug_artifact)); + let brillig_funcs = &vec![brillig_bytecode]; let mut context = DebugContext::new( &StubbedBlackBoxSolver, circuit, debug_artifact, initial_witness, foreign_call_executor, + brillig_funcs, ); // set breakpoint @@ -731,121 +825,79 @@ mod tests { } #[test] - fn test_offset_opcode_location() { + fn test_address_opcode_location_mapping() { + let brillig_bytecode = BrilligBytecode { + bytecode: vec![ + BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 0 }, + BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 0 }, + BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 0 }, + ], + }; + let opcodes = vec![ - Opcode::Brillig(Brillig { - inputs: vec![], - outputs: vec![], - bytecode: vec![ - BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 0 }, - BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 0 }, - BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 0 }, - ], - predicate: None, - }), - Opcode::MemoryInit { block_id: BlockId(0), init: vec![] }, - Opcode::Brillig(Brillig { - inputs: vec![], - outputs: vec![], - bytecode: vec![ - BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 0 }, - BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 0 }, - BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 0 }, - ], - predicate: None, - }), + Opcode::BrilligCall { id: 0, inputs: vec![], outputs: vec![], predicate: None }, + Opcode::MemoryInit { + block_id: BlockId(0), + init: vec![], + block_type: acvm::acir::circuit::opcodes::BlockType::Memory, + }, + Opcode::BrilligCall { id: 0, inputs: vec![], outputs: vec![], predicate: None }, Opcode::AssertZero(Expression::default()), ]; let circuit = Circuit { opcodes, ..Circuit::default() }; - let debug_artifact = - DebugArtifact { debug_symbols: vec![], file_map: BTreeMap::new(), warnings: vec![] }; + let debug_artifact = DebugArtifact { debug_symbols: vec![], file_map: BTreeMap::new() }; + let brillig_funcs = &vec![brillig_bytecode]; let context = DebugContext::new( &StubbedBlackBoxSolver, &circuit, &debug_artifact, WitnessMap::new(), Box::new(DefaultDebugForeignCallExecutor::new(true)), + brillig_funcs, ); - assert_eq!(context.offset_opcode_location(&None, 0), (None, 0)); - assert_eq!(context.offset_opcode_location(&None, 2), (None, 2)); - assert_eq!(context.offset_opcode_location(&None, -2), (None, -2)); - assert_eq!( - context.offset_opcode_location(&Some(OpcodeLocation::Acir(0)), 0), - (Some(OpcodeLocation::Acir(0)), 0) - ); - assert_eq!( - context.offset_opcode_location(&Some(OpcodeLocation::Acir(0)), 1), - (Some(OpcodeLocation::Brillig { acir_index: 0, brillig_index: 1 }), 0) - ); - assert_eq!( - context.offset_opcode_location(&Some(OpcodeLocation::Acir(0)), 2), - (Some(OpcodeLocation::Brillig { acir_index: 0, brillig_index: 2 }), 0) - ); - assert_eq!( - context.offset_opcode_location(&Some(OpcodeLocation::Acir(0)), 3), - (Some(OpcodeLocation::Acir(1)), 0) - ); - assert_eq!( - context.offset_opcode_location(&Some(OpcodeLocation::Acir(0)), 4), - (Some(OpcodeLocation::Acir(2)), 0) - ); - assert_eq!( - context.offset_opcode_location(&Some(OpcodeLocation::Acir(0)), 5), - (Some(OpcodeLocation::Brillig { acir_index: 2, brillig_index: 1 }), 0) - ); - assert_eq!( - context.offset_opcode_location(&Some(OpcodeLocation::Acir(0)), 7), - (Some(OpcodeLocation::Acir(3)), 0) - ); - assert_eq!(context.offset_opcode_location(&Some(OpcodeLocation::Acir(0)), 8), (None, 0)); - assert_eq!(context.offset_opcode_location(&Some(OpcodeLocation::Acir(0)), 20), (None, 12)); - assert_eq!( - context.offset_opcode_location(&Some(OpcodeLocation::Acir(1)), 2), - (Some(OpcodeLocation::Brillig { acir_index: 2, brillig_index: 1 }), 0) - ); - assert_eq!(context.offset_opcode_location(&Some(OpcodeLocation::Acir(0)), -1), (None, -1)); - assert_eq!( - context.offset_opcode_location(&Some(OpcodeLocation::Acir(0)), -10), - (None, -10) - ); + let locations = + (0..=7).map(|address| context.address_to_opcode_location(address)).collect::>(); + // mapping from addresses to opcode locations assert_eq!( - context.offset_opcode_location( - &Some(OpcodeLocation::Brillig { acir_index: 0, brillig_index: 1 }), - -1 - ), - (Some(OpcodeLocation::Acir(0)), 0) - ); - assert_eq!( - context.offset_opcode_location( - &Some(OpcodeLocation::Brillig { acir_index: 0, brillig_index: 2 }), - -2 - ), - (Some(OpcodeLocation::Acir(0)), 0) - ); - assert_eq!( - context.offset_opcode_location(&Some(OpcodeLocation::Acir(1)), -3), - (Some(OpcodeLocation::Acir(0)), 0) - ); - assert_eq!( - context.offset_opcode_location(&Some(OpcodeLocation::Acir(2)), -4), - (Some(OpcodeLocation::Acir(0)), 0) - ); - assert_eq!( - context.offset_opcode_location( - &Some(OpcodeLocation::Brillig { acir_index: 2, brillig_index: 1 }), - -5 - ), - (Some(OpcodeLocation::Acir(0)), 0) + locations, + vec![ + Some(OpcodeLocation::Acir(0)), + Some(OpcodeLocation::Brillig { acir_index: 0, brillig_index: 1 }), + Some(OpcodeLocation::Brillig { acir_index: 0, brillig_index: 2 }), + Some(OpcodeLocation::Acir(1)), + Some(OpcodeLocation::Acir(2)), + Some(OpcodeLocation::Brillig { acir_index: 2, brillig_index: 1 }), + Some(OpcodeLocation::Brillig { acir_index: 2, brillig_index: 2 }), + Some(OpcodeLocation::Acir(3)), + ] ); + + let addresses = locations + .iter() + .flatten() + .map(|location| context.opcode_location_to_address(location)) + .collect::>(); + + // and vice-versa + assert_eq!(addresses, (0..=7).collect::>()); + + // check edge cases + assert_eq!(None, context.address_to_opcode_location(8)); assert_eq!( - context.offset_opcode_location(&Some(OpcodeLocation::Acir(3)), -7), - (Some(OpcodeLocation::Acir(0)), 0) + 0, + context.opcode_location_to_address(&OpcodeLocation::Brillig { + acir_index: 0, + brillig_index: 0 + }) ); assert_eq!( - context.offset_opcode_location(&Some(OpcodeLocation::Acir(2)), -2), - (Some(OpcodeLocation::Brillig { acir_index: 0, brillig_index: 2 }), 0) + 4, + context.opcode_location_to_address(&OpcodeLocation::Brillig { + acir_index: 2, + brillig_index: 0 + }) ); } } diff --git a/tooling/debugger/src/dap.rs b/tooling/debugger/src/dap.rs index 7e67a26b257..40b77f0ad2a 100644 --- a/tooling/debugger/src/dap.rs +++ b/tooling/debugger/src/dap.rs @@ -1,11 +1,10 @@ use std::collections::BTreeMap; use std::io::{Read, Write}; -use std::str::FromStr; +use acvm::acir::circuit::brillig::BrilligBytecode; use acvm::acir::circuit::{Circuit, OpcodeLocation}; use acvm::acir::native_types::WitnessMap; -use acvm::BlackBoxFunctionSolver; -use codespan_reporting::files::{Files, SimpleFile}; +use acvm::{BlackBoxFunctionSolver, FieldElement}; use crate::context::DebugCommandResult; use crate::context::DebugContext; @@ -30,15 +29,16 @@ use nargo::artifacts::debug::DebugArtifact; use fm::FileId; use noirc_driver::CompiledProgram; -pub struct DapSession<'a, R: Read, W: Write, B: BlackBoxFunctionSolver> { +type BreakpointId = i64; + +pub struct DapSession<'a, R: Read, W: Write, B: BlackBoxFunctionSolver> { server: Server, context: DebugContext<'a, B>, debug_artifact: &'a DebugArtifact, running: bool, - source_to_opcodes: BTreeMap>, - next_breakpoint_id: i64, - instruction_breakpoints: Vec<(OpcodeLocation, i64)>, - source_breakpoints: BTreeMap>, + next_breakpoint_id: BreakpointId, + instruction_breakpoints: Vec<(OpcodeLocation, BreakpointId)>, + source_breakpoints: BTreeMap>, } enum ScopeReferences { @@ -57,29 +57,27 @@ impl From for ScopeReferences { } } -// BTreeMap - -impl<'a, R: Read, W: Write, B: BlackBoxFunctionSolver> DapSession<'a, R, W, B> { +impl<'a, R: Read, W: Write, B: BlackBoxFunctionSolver> DapSession<'a, R, W, B> { pub fn new( server: Server, solver: &'a B, - circuit: &'a Circuit, + circuit: &'a Circuit, debug_artifact: &'a DebugArtifact, - initial_witness: WitnessMap, + initial_witness: WitnessMap, + unconstrained_functions: &'a [BrilligBytecode], ) -> Self { - let source_to_opcodes = Self::build_source_to_opcode_debug_mappings(debug_artifact); let context = DebugContext::new( solver, circuit, debug_artifact, initial_witness, Box::new(DefaultDebugForeignCallExecutor::from_artifact(true, debug_artifact)), + unconstrained_functions, ); Self { server, context, debug_artifact, - source_to_opcodes, running: false, next_breakpoint_id: 1, instruction_breakpoints: vec![], @@ -87,46 +85,6 @@ impl<'a, R: Read, W: Write, B: BlackBoxFunctionSolver> DapSession<'a, R, W, B> { } } - /// Builds a map from FileId to an ordered vector of tuples with line - /// numbers and opcode locations corresponding to those line numbers - fn build_source_to_opcode_debug_mappings( - debug_artifact: &'a DebugArtifact, - ) -> BTreeMap> { - if debug_artifact.debug_symbols.is_empty() { - return BTreeMap::new(); - } - let locations = &debug_artifact.debug_symbols[0].locations; - let simple_files: BTreeMap<_, _> = debug_artifact - .file_map - .iter() - .map(|(file_id, debug_file)| { - ( - file_id, - SimpleFile::new(debug_file.path.to_str().unwrap(), debug_file.source.as_str()), - ) - }) - .collect(); - - let mut result: BTreeMap> = BTreeMap::new(); - locations.iter().for_each(|(opcode_location, source_locations)| { - if source_locations.is_empty() { - return; - } - let source_location = source_locations[0]; - let span = source_location.span; - let file_id = source_location.file; - let Ok(line_index) = &simple_files[&file_id].line_index((), span.start() as usize) - else { - return; - }; - let line_number = line_index + 1; - - result.entry(file_id).or_default().push((line_number, *opcode_location)); - }); - result.iter_mut().for_each(|(_, file_locations)| file_locations.sort_by_key(|x| x.0)); - result - } - fn send_stopped_event(&mut self, reason: StoppedEventReason) -> Result<(), ServerError> { let description = format!("{:?}", &reason); self.server.send_event(Event::Stopped(StoppedEventBody { @@ -230,6 +188,8 @@ impl<'a, R: Read, W: Write, B: BlackBoxFunctionSolver> DapSession<'a, R, W, B> { } fn build_stack_trace(&self) -> Vec { + let stack_frames = self.context.get_variables(); + self.context .get_source_call_stack() .iter() @@ -239,9 +199,16 @@ impl<'a, R: Read, W: Write, B: BlackBoxFunctionSolver> DapSession<'a, R, W, B> { self.debug_artifact.location_line_number(*source_location).unwrap(); let column_number = self.debug_artifact.location_column_number(*source_location).unwrap(); + + let name = match stack_frames.get(index) { + Some(frame) => format!("{} {}", frame.function_name, index), + None => format!("frame #{index}"), + }; + let address = self.context.opcode_location_to_address(opcode_location); + StackFrame { id: index as i64, - name: format!("frame #{index}"), + name, source: Some(Source { path: self.debug_artifact.file_map[&source_location.file] .path @@ -251,7 +218,7 @@ impl<'a, R: Read, W: Write, B: BlackBoxFunctionSolver> DapSession<'a, R, W, B> { }), line: line_number as i64, column: column_number as i64, - instruction_pointer_reference: Some(opcode_location.to_string()), + instruction_pointer_reference: Some(address.to_string()), ..StackFrame::default() } }) @@ -273,50 +240,41 @@ impl<'a, R: Read, W: Write, B: BlackBoxFunctionSolver> DapSession<'a, R, W, B> { let Command::Disassemble(ref args) = req.command else { unreachable!("handle_disassemble called on a non disassemble request"); }; - let starting_ip = OpcodeLocation::from_str(args.memory_reference.as_str()).ok(); + + // we assume memory references are unsigned integers + let starting_address = args.memory_reference.parse::().unwrap_or(0); let instruction_offset = args.instruction_offset.unwrap_or(0); - let (mut opcode_location, mut invalid_count) = - self.context.offset_opcode_location(&starting_ip, instruction_offset); + + let mut address = starting_address + instruction_offset; let mut count = args.instruction_count; let mut instructions: Vec = vec![]; - // leading invalid locations (when the request goes back - // beyond the start of the program) - if invalid_count < 0 { - while invalid_count < 0 { + while count > 0 { + let opcode_location = if address >= 0 { + self.context.address_to_opcode_location(address as usize) + } else { + None + }; + + if let Some(opcode_location) = opcode_location { instructions.push(DisassembledInstruction { - address: String::from("---"), - instruction: String::from("---"), + address: address.to_string(), + // we'll use the instruction_bytes field to render the OpcodeLocation + instruction_bytes: Some(opcode_location.to_string()), + instruction: self.context.render_opcode_at_location(&opcode_location), + ..DisassembledInstruction::default() + }); + } else { + // entry for invalid location to fill up the request + instructions.push(DisassembledInstruction { + address: "---".to_owned(), + instruction: "---".to_owned(), ..DisassembledInstruction::default() }); - invalid_count += 1; - count -= 1; - } - if count > 0 { - opcode_location = Some(OpcodeLocation::Acir(0)); } - } - // the actual opcodes - while count > 0 && opcode_location.is_some() { - instructions.push(DisassembledInstruction { - address: format!("{}", opcode_location.unwrap()), - instruction: self.context.render_opcode_at_location(&opcode_location), - ..DisassembledInstruction::default() - }); - (opcode_location, _) = self.context.offset_opcode_location(&opcode_location, 1); - count -= 1; - } - // any remaining instruction count is beyond the valid opcode - // vector so return invalid placeholders - while count > 0 { - instructions.push(DisassembledInstruction { - address: String::from("---"), - instruction: String::from("---"), - ..DisassembledInstruction::default() - }); - invalid_count -= 1; count -= 1; + address += 1; } self.server.respond( @@ -422,7 +380,7 @@ impl<'a, R: Read, W: Write, B: BlackBoxFunctionSolver> DapSession<'a, R, W, B> { Ok(()) } - fn get_next_breakpoint_id(&mut self) -> i64 { + fn get_next_breakpoint_id(&mut self) -> BreakpointId { let id = self.next_breakpoint_id; self.next_breakpoint_id += 1; id @@ -451,25 +409,35 @@ impl<'a, R: Read, W: Write, B: BlackBoxFunctionSolver> DapSession<'a, R, W, B> { .breakpoints .iter() .map(|breakpoint| { - let Ok(location) = - OpcodeLocation::from_str(breakpoint.instruction_reference.as_str()) - else { + let offset = breakpoint.offset.unwrap_or(0); + let address = breakpoint.instruction_reference.parse::().unwrap_or(0) + offset; + let Ok(address): Result = address.try_into() else { return Breakpoint { verified: false, - message: Some(String::from("Missing instruction reference")), + message: Some(String::from("Invalid instruction reference/offset")), ..Breakpoint::default() }; }; - if !self.context.is_valid_opcode_location(&location) { + let Some(location) = self + .context + .address_to_opcode_location(address) + .filter(|location| self.context.is_valid_opcode_location(location)) + else { return Breakpoint { verified: false, message: Some(String::from("Invalid opcode location")), ..Breakpoint::default() }; - } + }; let id = self.get_next_breakpoint_id(); breakpoints_to_set.push((location, id)); - Breakpoint { id: Some(id), verified: true, ..Breakpoint::default() } + Breakpoint { + id: Some(id), + verified: true, + offset: Some(0), + instruction_reference: Some(address.to_string()), + ..Breakpoint::default() + } }) .collect(); @@ -493,36 +461,6 @@ impl<'a, R: Read, W: Write, B: BlackBoxFunctionSolver> DapSession<'a, R, W, B> { found.map(|iter| *iter.0) } - // TODO: there are four possibilities for the return value of this function: - // 1. the source location is not found -> None - // 2. an exact unique location is found -> Some(opcode_location) - // 3. an exact but not unique location is found (ie. a source location may - // be mapped to multiple opcodes, and those may be disjoint, for example for - // functions called multiple times throughout the program) - // 4. exact location is not found, so an opcode for a nearby source location - // is returned (this again could actually be more than one opcodes) - // Case 3 is not supported yet, and 4 is not correctly handled. - fn find_opcode_for_source_location( - &self, - file_id: &FileId, - line: i64, - ) -> Option { - let line = line as usize; - let Some(line_to_opcodes) = self.source_to_opcodes.get(file_id) else { - return None; - }; - let found_index = match line_to_opcodes.binary_search_by(|x| x.0.cmp(&line)) { - Ok(index) => line_to_opcodes[index].1, - Err(index) => { - if index >= line_to_opcodes.len() { - return None; - } - line_to_opcodes[index].1 - } - }; - Some(found_index) - } - fn map_source_breakpoints(&mut self, args: &SetBreakpointsArguments) -> Vec { let Some(ref source) = &args.source.path else { return vec![]; @@ -539,7 +477,8 @@ impl<'a, R: Read, W: Write, B: BlackBoxFunctionSolver> DapSession<'a, R, W, B> { .iter() .map(|breakpoint| { let line = breakpoint.line; - let Some(location) = self.find_opcode_for_source_location(&file_id, line) else { + let Some(location) = self.context.find_opcode_for_source_location(&file_id, line) + else { return Breakpoint { verified: false, message: Some(String::from( @@ -558,15 +497,17 @@ impl<'a, R: Read, W: Write, B: BlackBoxFunctionSolver> DapSession<'a, R, W, B> { ..Breakpoint::default() }; } - let instruction_reference = format!("{}", location); + let breakpoint_address = self.context.opcode_location_to_address(&location); + let instruction_reference = format!("{}", breakpoint_address); let breakpoint_id = self.get_next_breakpoint_id(); breakpoints_to_set.push((location, breakpoint_id)); Breakpoint { id: Some(breakpoint_id), verified: true, source: Some(args.source.clone()), - instruction_reference: Some(instruction_reference), line: Some(line), + instruction_reference: Some(instruction_reference), + offset: Some(0), ..Breakpoint::default() } }) @@ -608,16 +549,20 @@ impl<'a, R: Read, W: Write, B: BlackBoxFunctionSolver> DapSession<'a, R, W, B> { } fn build_local_variables(&self) -> Vec { - let mut variables: Vec<_> = self - .context - .get_variables() + let Some(current_stack_frame) = self.context.current_stack_frame() else { + return vec![]; + }; + + let mut variables = current_stack_frame + .variables .iter() .map(|(name, value, _var_type)| Variable { name: String::from(*name), value: format!("{:?}", *value), ..Variable::default() }) - .collect(); + .collect::>(); + variables.sort_by(|a, b| a.name.partial_cmp(&b.name).unwrap()); variables } @@ -657,19 +602,21 @@ impl<'a, R: Read, W: Write, B: BlackBoxFunctionSolver> DapSession<'a, R, W, B> { } } -pub fn run_session( +pub fn run_session>( server: Server, solver: &B, program: CompiledProgram, - initial_witness: WitnessMap, + initial_witness: WitnessMap, ) -> Result<(), ServerError> { - let debug_artifact = DebugArtifact { - debug_symbols: vec![program.debug], - file_map: program.file_map, - warnings: program.warnings, - }; - let mut session = - DapSession::new(server, solver, &program.circuit, &debug_artifact, initial_witness); + let debug_artifact = DebugArtifact { debug_symbols: program.debug, file_map: program.file_map }; + let mut session = DapSession::new( + server, + solver, + &program.program.functions[0], + &debug_artifact, + initial_witness, + &program.program.unconstrained_functions, + ); session.run_loop() } diff --git a/tooling/debugger/src/foreign_calls.rs b/tooling/debugger/src/foreign_calls.rs index 68c4d3947b0..6989936ae93 100644 --- a/tooling/debugger/src/foreign_calls.rs +++ b/tooling/debugger/src/foreign_calls.rs @@ -1,19 +1,22 @@ use acvm::{ - acir::brillig::{ForeignCallParam, ForeignCallResult, Value}, + acir::brillig::{ForeignCallParam, ForeignCallResult}, pwg::ForeignCallWaitInfo, + AcirField, FieldElement, }; use nargo::{ - artifacts::debug::{DebugArtifact, DebugVars}, - ops::{DefaultForeignCallExecutor, ForeignCallExecutor, NargoForeignCallResult}, + artifacts::debug::{DebugArtifact, DebugVars, StackFrame}, + ops::{DefaultForeignCallExecutor, ForeignCallExecutor}, }; -use noirc_errors::debug_info::DebugVarId; -use noirc_printable_type::{ForeignCallError, PrintableType, PrintableValue}; +use noirc_errors::debug_info::{DebugFnId, DebugVarId}; +use noirc_printable_type::ForeignCallError; pub(crate) enum DebugForeignCall { VarAssign, VarDrop, MemberAssign(u32), DerefAssign, + FnEnter, + FnExit, } impl DebugForeignCall { @@ -28,13 +31,16 @@ impl DebugForeignCall { "__debug_var_assign" => Some(DebugForeignCall::VarAssign), "__debug_var_drop" => Some(DebugForeignCall::VarDrop), "__debug_deref_assign" => Some(DebugForeignCall::DerefAssign), + "__debug_fn_enter" => Some(DebugForeignCall::FnEnter), + "__debug_fn_exit" => Some(DebugForeignCall::FnExit), _ => None, } } } pub trait DebugForeignCallExecutor: ForeignCallExecutor { - fn get_variables(&self) -> Vec<(&str, &PrintableValue, &PrintableType)>; + fn get_variables(&self) -> Vec; + fn current_stack_frame(&self) -> Option; } pub struct DefaultDebugForeignCallExecutor { @@ -57,39 +63,49 @@ impl DefaultDebugForeignCallExecutor { } pub fn load_artifact(&mut self, artifact: &DebugArtifact) { - artifact.debug_symbols.iter().for_each(|info| { - self.debug_vars.insert_variables(&info.variables); - self.debug_vars.insert_types(&info.types); - }); + // TODO: handle loading from the correct DebugInfo when we support + // debugging contracts + let Some(info) = artifact.debug_symbols.first() else { + return; + }; + self.debug_vars.insert_debug_info(info); } } impl DebugForeignCallExecutor for DefaultDebugForeignCallExecutor { - fn get_variables(&self) -> Vec<(&str, &PrintableValue, &PrintableType)> { + fn get_variables(&self) -> Vec { self.debug_vars.get_variables() } + + fn current_stack_frame(&self) -> Option { + self.debug_vars.current_stack_frame() + } } -fn debug_var_id(value: &Value) -> DebugVarId { +fn debug_var_id(value: &FieldElement) -> DebugVarId { DebugVarId(value.to_u128() as u32) } +fn debug_fn_id(value: &FieldElement) -> DebugFnId { + DebugFnId(value.to_u128() as u32) +} + impl ForeignCallExecutor for DefaultDebugForeignCallExecutor { fn execute( &mut self, - foreign_call: &ForeignCallWaitInfo, - ) -> Result { + foreign_call: &ForeignCallWaitInfo, + ) -> Result, ForeignCallError> { let foreign_call_name = foreign_call.function.as_str(); match DebugForeignCall::lookup(foreign_call_name) { Some(DebugForeignCall::VarAssign) => { let fcp_var_id = &foreign_call.inputs[0]; if let ForeignCallParam::Single(var_id_value) = fcp_var_id { let var_id = debug_var_id(var_id_value); - let values: Vec = - foreign_call.inputs[1..].iter().flat_map(|x| x.values()).collect(); + let values: Vec = + foreign_call.inputs[1..].iter().flat_map(|x| x.fields()).collect(); self.debug_vars.assign_var(var_id, &values); } - Ok(ForeignCallResult::default().into()) + Ok(ForeignCallResult::default()) } Some(DebugForeignCall::VarDrop) => { let fcp_var_id = &foreign_call.inputs[0]; @@ -97,7 +113,7 @@ impl ForeignCallExecutor for DefaultDebugForeignCallExecutor { let var_id = debug_var_id(var_id_value); self.debug_vars.drop_var(var_id); } - Ok(ForeignCallResult::default().into()) + Ok(ForeignCallResult::default()) } Some(DebugForeignCall::MemberAssign(arity)) => { if let Some(ForeignCallParam::Single(var_id_value)) = foreign_call.inputs.first() { @@ -114,27 +130,40 @@ impl ForeignCallExecutor for DefaultDebugForeignCallExecutor { } }) .collect(); - let values: Vec = (0..n - 1 - arity) + let values: Vec = (0..n - 1 - arity) .flat_map(|i| { foreign_call .inputs .get(1 + i) - .map(|fci| fci.values()) + .map(|fci| fci.fields()) .unwrap_or_default() }) .collect(); self.debug_vars.assign_field(var_id, indexes, &values); } - Ok(ForeignCallResult::default().into()) + Ok(ForeignCallResult::default()) } Some(DebugForeignCall::DerefAssign) => { let fcp_var_id = &foreign_call.inputs[0]; let fcp_value = &foreign_call.inputs[1]; if let ForeignCallParam::Single(var_id_value) = fcp_var_id { let var_id = debug_var_id(var_id_value); - self.debug_vars.assign_deref(var_id, &fcp_value.values()); + self.debug_vars.assign_deref(var_id, &fcp_value.fields()); } - Ok(ForeignCallResult::default().into()) + Ok(ForeignCallResult::default()) + } + Some(DebugForeignCall::FnEnter) => { + let fcp_fn_id = &foreign_call.inputs[0]; + let ForeignCallParam::Single(fn_id_value) = fcp_fn_id else { + panic!("unexpected foreign call parameter in fn enter: {fcp_fn_id:?}") + }; + let fn_id = debug_fn_id(fn_id_value); + self.debug_vars.push_fn(fn_id); + Ok(ForeignCallResult::default()) + } + Some(DebugForeignCall::FnExit) => { + self.debug_vars.pop_fn(); + Ok(ForeignCallResult::default()) } None => self.executor.execute(foreign_call), } diff --git a/tooling/debugger/src/lib.rs b/tooling/debugger/src/lib.rs index 4a25e3417a0..d7a1337c82f 100644 --- a/tooling/debugger/src/lib.rs +++ b/tooling/debugger/src/lib.rs @@ -9,28 +9,30 @@ use std::io::{Read, Write}; use ::dap::errors::ServerError; use ::dap::server::Server; -use acvm::BlackBoxFunctionSolver; +use acvm::acir::circuit::brillig::BrilligBytecode; use acvm::{acir::circuit::Circuit, acir::native_types::WitnessMap}; +use acvm::{BlackBoxFunctionSolver, FieldElement}; use nargo::artifacts::debug::DebugArtifact; use nargo::NargoError; use noirc_driver::CompiledProgram; -pub fn debug_circuit( +pub fn debug_circuit>( blackbox_solver: &B, - circuit: &Circuit, + circuit: &Circuit, debug_artifact: DebugArtifact, - initial_witness: WitnessMap, -) -> Result, NargoError> { - repl::run(blackbox_solver, circuit, &debug_artifact, initial_witness) + initial_witness: WitnessMap, + unconstrained_functions: &[BrilligBytecode], +) -> Result>, NargoError> { + repl::run(blackbox_solver, circuit, &debug_artifact, initial_witness, unconstrained_functions) } -pub fn run_dap_loop( +pub fn run_dap_loop>( server: Server, solver: &B, program: CompiledProgram, - initial_witness: WitnessMap, + initial_witness: WitnessMap, ) -> Result<(), ServerError> { dap::run_session(server, solver, program, initial_witness) } diff --git a/tooling/debugger/src/repl.rs b/tooling/debugger/src/repl.rs index 8441dbde9be..5aef12ad8d4 100644 --- a/tooling/debugger/src/repl.rs +++ b/tooling/debugger/src/repl.rs @@ -1,7 +1,9 @@ use crate::context::{DebugCommandResult, DebugContext}; +use acvm::acir::circuit::brillig::BrilligBytecode; use acvm::acir::circuit::{Circuit, Opcode, OpcodeLocation}; use acvm::acir::native_types::{Witness, WitnessMap}; +use acvm::brillig_vm::brillig::Opcode as BrilligOpcode; use acvm::{BlackBoxFunctionSolver, FieldElement}; use crate::foreign_calls::DefaultDebugForeignCallExecutor; @@ -13,21 +15,23 @@ use std::cell::RefCell; use crate::source_code_printer::print_source_code_location; -pub struct ReplDebugger<'a, B: BlackBoxFunctionSolver> { +pub struct ReplDebugger<'a, B: BlackBoxFunctionSolver> { context: DebugContext<'a, B>, blackbox_solver: &'a B, - circuit: &'a Circuit, + circuit: &'a Circuit, debug_artifact: &'a DebugArtifact, - initial_witness: WitnessMap, + initial_witness: WitnessMap, last_result: DebugCommandResult, + unconstrained_functions: &'a [BrilligBytecode], } -impl<'a, B: BlackBoxFunctionSolver> ReplDebugger<'a, B> { +impl<'a, B: BlackBoxFunctionSolver> ReplDebugger<'a, B> { pub fn new( blackbox_solver: &'a B, - circuit: &'a Circuit, + circuit: &'a Circuit, debug_artifact: &'a DebugArtifact, - initial_witness: WitnessMap, + initial_witness: WitnessMap, + unconstrained_functions: &'a [BrilligBytecode], ) -> Self { let foreign_call_executor = Box::new(DefaultDebugForeignCallExecutor::from_artifact(true, debug_artifact)); @@ -37,6 +41,7 @@ impl<'a, B: BlackBoxFunctionSolver> ReplDebugger<'a, B> { debug_artifact, initial_witness.clone(), foreign_call_executor, + unconstrained_functions, ); let last_result = if context.get_current_opcode_location().is_none() { // handle circuit with no opcodes @@ -44,7 +49,15 @@ impl<'a, B: BlackBoxFunctionSolver> ReplDebugger<'a, B> { } else { DebugCommandResult::Ok }; - Self { context, blackbox_solver, circuit, debug_artifact, initial_witness, last_result } + Self { + context, + blackbox_solver, + circuit, + debug_artifact, + initial_witness, + last_result, + unconstrained_functions, + } } pub fn show_current_vm_status(&self) { @@ -56,23 +69,18 @@ impl<'a, B: BlackBoxFunctionSolver> ReplDebugger<'a, B> { Some(location) => { match location { OpcodeLocation::Acir(ip) => { - // Default Brillig display is too bloated for this context, - // so we limit it to denoting it's the start of a Brillig - // block. The user can still use the `opcodes` command to - // take a look at the whole block. - let opcode_summary = match opcodes[ip] { - Opcode::Brillig(..) => "BRILLIG: ...".into(), - _ => format!("{}", opcodes[ip]), - }; - println!("At opcode {}: {}", ip, opcode_summary); + 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"); - }; + let brillig_bytecode = + if let Opcode::BrilligCall { id, .. } = opcodes[acir_index] { + &self.unconstrained_functions[id as usize].bytecode + } else { + unreachable!("Brillig location does not contain Brillig opcodes"); + }; println!( "At opcode {}.{}: {:?}", - acir_index, brillig_index, brillig.bytecode[brillig_index] + acir_index, brillig_index, brillig_bytecode[brillig_index] ); } } @@ -92,12 +100,15 @@ impl<'a, B: BlackBoxFunctionSolver> ReplDebugger<'a, B> { ) } OpcodeLocation::Brillig { acir_index, brillig_index } => { - let Opcode::Brillig(ref brillig) = opcodes[*acir_index] else { - unreachable!("Brillig location does not contain a Brillig block"); + let brillig_bytecode = if let Opcode::BrilligCall { id, .. } = opcodes[*acir_index] + { + &self.unconstrained_functions[id as usize].bytecode + } else { + unreachable!("Brillig location does not contain Brillig opcodes"); }; println!( "Frame #{index}, opcode {}.{}: {:?}", - acir_index, brillig_index, brillig.bytecode[*brillig_index] + acir_index, brillig_index, brillig_bytecode[*brillig_index] ); } } @@ -150,22 +161,30 @@ impl<'a, B: BlackBoxFunctionSolver> ReplDebugger<'a, B> { "" } }; + let print_brillig_bytecode = |acir_index, bytecode: &[BrilligOpcode]| { + for (brillig_index, brillig_opcode) in bytecode.iter().enumerate() { + println!( + "{:>3}.{:<2} |{:2} {:?}", + acir_index, + brillig_index, + brillig_marker(acir_index, brillig_index), + brillig_opcode + ); + } + }; 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() { + match &opcode { + Opcode::BrilligCall { id, inputs, outputs, .. } => { println!( - "{:>3}.{:<2} |{:2} {:?}", - acir_index, - brillig_index, - brillig_marker(acir_index, brillig_index), - brillig_opcode + "{:>3} {:2} BRILLIG CALL id={} inputs={:?}", + acir_index, marker, id, inputs ); + println!(" | outputs={:?}", outputs); + let bytecode = &self.unconstrained_functions[*id as usize].bytecode; + print_brillig_bytecode(acir_index, bytecode); } - } else { - println!("{:>3} {:2} {:?}", acir_index, marker, opcode); + _ => println!("{:>3} {:2} {:?}", acir_index, marker, opcode), } } } @@ -271,6 +290,7 @@ impl<'a, B: BlackBoxFunctionSolver> ReplDebugger<'a, B> { self.debug_artifact, self.initial_witness.clone(), foreign_call_executor, + self.unconstrained_functions, ); for opcode_location in breakpoints { self.context.add_breakpoint(opcode_location); @@ -319,12 +339,12 @@ impl<'a, B: BlackBoxFunctionSolver> ReplDebugger<'a, B> { return; }; - for (index, value) in memory.iter().enumerate() { - println!("{index} = {}", value.to_field()); + for (index, value) in memory.iter().enumerate().filter(|(_, value)| value.bit_size() > 0) { + println!("{index} = {}", value); } } - pub fn write_brillig_memory(&mut self, index: usize, value: String) { + pub fn write_brillig_memory(&mut self, index: usize, value: String, bit_size: u32) { let Some(field_value) = FieldElement::try_from_str(&value) else { println!("Invalid value: {value}"); return; @@ -333,15 +353,17 @@ impl<'a, B: BlackBoxFunctionSolver> ReplDebugger<'a, B> { println!("Not executing a Brillig block"); return; } - self.context.write_brillig_memory(index, field_value); + self.context.write_brillig_memory(index, field_value, bit_size); } pub fn show_vars(&self) { - let vars = self.context.get_variables(); - for (var_name, value, var_type) in vars.iter() { - let printable_value = - PrintableValueDisplay::Plain((*value).clone(), (*var_type).clone()); - println!("{var_name}:{var_type:?} = {}", printable_value); + for frame in self.context.get_variables() { + println!("{}({})", frame.function_name, frame.function_params.join(", ")); + for (var_name, value, var_type) in frame.variables.iter() { + let printable_value = + PrintableValueDisplay::Plain((*value).clone(), (*var_type).clone()); + println!(" {var_name}:{var_type:?} = {}", printable_value); + } } } @@ -349,19 +371,25 @@ impl<'a, B: BlackBoxFunctionSolver> ReplDebugger<'a, B> { self.context.is_solved() } - fn finalize(self) -> WitnessMap { + fn finalize(self) -> WitnessMap { self.context.finalize() } } -pub fn run( +pub fn run>( blackbox_solver: &B, - circuit: &Circuit, + circuit: &Circuit, debug_artifact: &DebugArtifact, - initial_witness: WitnessMap, -) -> Result, NargoError> { - let context = - RefCell::new(ReplDebugger::new(blackbox_solver, circuit, debug_artifact, initial_witness)); + initial_witness: WitnessMap, + unconstrained_functions: &[BrilligBytecode], +) -> Result>, NargoError> { + let context = RefCell::new(ReplDebugger::new( + blackbox_solver, + circuit, + debug_artifact, + initial_witness, + unconstrained_functions, + )); let ref_context = &context; ref_context.borrow().show_current_vm_status(); @@ -511,8 +539,8 @@ pub fn run( "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); + (index: usize, value: String, bit_size: u32) => |index, value, bit_size| { + ref_context.borrow_mut().write_brillig_memory(index, value, bit_size); Ok(CommandStatus::Done) } }, @@ -530,7 +558,7 @@ pub fn run( .add( "vars", command! { - "show variable values available at this point in execution", + "show variables for each function scope available at this point in execution", () => || { ref_context.borrow_mut().show_vars(); Ok(CommandStatus::Done) diff --git a/tooling/debugger/src/source_code_printer.rs b/tooling/debugger/src/source_code_printer.rs index b5ffdb12d01..e298eb8aadd 100644 --- a/tooling/debugger/src/source_code_printer.rs +++ b/tooling/debugger/src/source_code_printer.rs @@ -30,7 +30,7 @@ struct LocationPrintContext { // Given a DebugArtifact and an OpcodeLocation, prints all the source code // locations the OpcodeLocation maps to, with some surrounding context and // visual aids to highlight the location itself. -pub(crate) fn print_source_code_location(debug_artifact: &DebugArtifact, locations: &[Location]) { +pub(super) fn print_source_code_location(debug_artifact: &DebugArtifact, locations: &[Location]) { let locations = locations.iter(); for loc in locations { @@ -269,8 +269,12 @@ mod tests { let mut opcode_locations = BTreeMap::>::new(); opcode_locations.insert(OpcodeLocation::Acir(42), vec![loc]); - let debug_symbols = - vec![DebugInfo::new(opcode_locations, BTreeMap::default(), BTreeMap::default())]; + let debug_symbols = vec![DebugInfo::new( + opcode_locations, + BTreeMap::default(), + BTreeMap::default(), + BTreeMap::default(), + )]; let debug_artifact = DebugArtifact::new(debug_symbols, &fm); let location_rendered: Vec<_> = render_location(&debug_artifact, &loc).collect(); diff --git a/tooling/debugger/tests/debug.rs b/tooling/debugger/tests/debug.rs index 4cb678192b8..313b6b30591 100644 --- a/tooling/debugger/tests/debug.rs +++ b/tooling/debugger/tests/debug.rs @@ -12,13 +12,9 @@ mod tests { let nargo_bin = cargo_bin("nargo").into_os_string().into_string().expect("Cannot parse nargo path"); - let mut dbg_session = spawn_bash(Some(10000)).expect("Could not start bash session"); - - // Set backend to `/dev/null` to force an error if nargo tries to speak to a backend. - dbg_session - .send_line("export NARGO_BACKEND_PATH=/dev/null") - .expect("Could not export NARGO_BACKEND_PATH."); - dbg_session.wait_for_prompt().expect("Could not export NARGO_BACKEND_PATH."); + let timeout_seconds = 20; + let mut dbg_session = + spawn_bash(Some(timeout_seconds * 1000)).expect("Could not start bash session"); // Start debugger and test that it loads for the given program. dbg_session @@ -49,5 +45,8 @@ mod tests { dbg_session .exp_regex(".*Circuit witness successfully solved.*") .expect("Expected circuit witness to be successfully solved."); + + // Exit the bash session. + dbg_session.send_line("exit").expect("Failed to quit bash session"); } } diff --git a/tooling/lsp/Cargo.toml b/tooling/lsp/Cargo.toml index 750e85694e2..a599b096e52 100644 --- a/tooling/lsp/Cargo.toml +++ b/tooling/lsp/Cargo.toml @@ -3,7 +3,8 @@ name = "noir_lsp" description = "Language server for Noir" version.workspace = true authors.workspace = true -edition.workspace = true +edition.workspace = true# +rust-version.workspace = true license.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/tooling/lsp/src/lib.rs b/tooling/lsp/src/lib.rs index be9b83e02f6..304a2d34e47 100644 --- a/tooling/lsp/src/lib.rs +++ b/tooling/lsp/src/lib.rs @@ -13,7 +13,7 @@ use std::{ task::{self, Poll}, }; -use acvm::BlackBoxFunctionSolver; +use acvm::{BlackBoxFunctionSolver, FieldElement}; use async_lsp::{ router::Router, AnyEvent, AnyNotification, AnyRequest, ClientSocket, Error, LspService, ResponseError, @@ -79,7 +79,10 @@ pub struct LspState { } impl LspState { - fn new(client: &ClientSocket, solver: impl BlackBoxFunctionSolver + 'static) -> Self { + fn new( + client: &ClientSocket, + solver: impl BlackBoxFunctionSolver + 'static, + ) -> Self { Self { client: client.clone(), root_path: None, @@ -99,7 +102,10 @@ pub struct NargoLspService { } impl NargoLspService { - pub fn new(client: &ClientSocket, solver: impl BlackBoxFunctionSolver + 'static) -> Self { + pub fn new( + client: &ClientSocket, + solver: impl BlackBoxFunctionSolver + 'static, + ) -> Self { let state = LspState::new(client, solver); let mut router = Router::new(state); router @@ -345,7 +351,7 @@ fn prepare_package_from_source_string() { let mut state = LspState::new(&client, acvm::blackbox_solver::StubbedBlackBoxSolver); let (mut context, crate_id) = crate::prepare_source(source.to_string(), &mut state); - let _check_result = noirc_driver::check_crate(&mut context, crate_id, false, false); + let _check_result = noirc_driver::check_crate(&mut context, crate_id, false, false, false); let main_func_id = context.get_main_function(&crate_id); assert!(main_func_id.is_some()); } diff --git a/tooling/lsp/src/notifications/mod.rs b/tooling/lsp/src/notifications/mod.rs index 355bb7832c4..3856bdc79e9 100644 --- a/tooling/lsp/src/notifications/mod.rs +++ b/tooling/lsp/src/notifications/mod.rs @@ -56,7 +56,7 @@ pub(super) fn on_did_change_text_document( state.input_files.insert(params.text_document.uri.to_string(), text.clone()); let (mut context, crate_id) = prepare_source(text, state); - let _ = check_crate(&mut context, crate_id, false, false); + let _ = check_crate(&mut context, crate_id, false, false, false); let workspace = match resolve_workspace_for_source_path( params.text_document.uri.to_file_path().unwrap().as_path(), @@ -139,7 +139,7 @@ fn process_noir_document( let (mut context, crate_id) = prepare_package(&workspace_file_manager, &parsed_files, package); - let file_diagnostics = match check_crate(&mut context, crate_id, false, false) { + let file_diagnostics = match check_crate(&mut context, crate_id, false, false, false) { Ok(((), warnings)) => warnings, Err(errors_and_warnings) => errors_and_warnings, }; diff --git a/tooling/lsp/src/requests/code_lens_request.rs b/tooling/lsp/src/requests/code_lens_request.rs index 893ba33d845..744bddedd9d 100644 --- a/tooling/lsp/src/requests/code_lens_request.rs +++ b/tooling/lsp/src/requests/code_lens_request.rs @@ -67,7 +67,7 @@ fn on_code_lens_request_inner( let (mut context, crate_id) = prepare_source(source_string, state); // We ignore the warnings and errors produced by compilation for producing code lenses // because we can still get the test functions even if compilation fails - let _ = check_crate(&mut context, crate_id, false, false); + let _ = check_crate(&mut context, crate_id, false, false, false); let collected_lenses = collect_lenses_for_package(&context, crate_id, &workspace, package, None); diff --git a/tooling/lsp/src/requests/goto_declaration.rs b/tooling/lsp/src/requests/goto_declaration.rs index 8e6d519b895..4ffe6abf88a 100644 --- a/tooling/lsp/src/requests/goto_declaration.rs +++ b/tooling/lsp/src/requests/goto_declaration.rs @@ -5,12 +5,13 @@ use crate::LspState; use crate::{parse_diff, resolve_workspace_for_source_path}; use async_lsp::{ErrorCode, ResponseError}; +use fm::PathString; use lsp_types::request::{GotoDeclarationParams, GotoDeclarationResponse}; use nargo::insert_all_files_for_workspace_into_file_manager; use noirc_driver::file_manager_with_stdlib; -use super::{position_to_byte_index, to_lsp_location}; +use super::{position_to_location, to_lsp_location}; pub(crate) fn on_goto_declaration_request( state: &mut LspState, @@ -32,8 +33,6 @@ fn on_goto_definition_inner( let workspace = resolve_workspace_for_source_path(file_path.as_path()).unwrap(); let package = workspace.members.first().unwrap(); - let package_root_path: String = package.root_dir.as_os_str().to_string_lossy().into(); - let mut workspace_file_manager = file_manager_with_stdlib(&workspace.root_dir); insert_all_files_for_workspace_into_file_manager(&workspace, &mut workspace_file_manager); let parsed_files = parse_diff(&workspace_file_manager, state); @@ -41,40 +40,25 @@ fn on_goto_definition_inner( let (mut context, crate_id) = nargo::prepare_package(&workspace_file_manager, &parsed_files, package); - let interner; - if let Some(def_interner) = state.cached_definitions.get(&package_root_path) { - interner = def_interner; + let package_root_path = package.root_dir.as_os_str().to_string_lossy().into_owned(); + let interner = if let Some(def_interner) = state.cached_definitions.get(&package_root_path) { + def_interner } else { // We ignore the warnings and errors produced by compilation while resolving the definition - let _ = noirc_driver::check_crate(&mut context, crate_id, false, false); - interner = &context.def_interner; - } - - let files = context.file_manager.as_file_map(); - let file_id = context.file_manager.name_to_id(file_path.clone()).ok_or(ResponseError::new( - ErrorCode::REQUEST_FAILED, - format!("Could not find file in file manager. File path: {:?}", file_path), - ))?; - let byte_index = - position_to_byte_index(files, file_id, ¶ms.text_document_position_params.position) - .map_err(|err| { - ResponseError::new( - ErrorCode::REQUEST_FAILED, - format!("Could not convert position to byte index. Error: {:?}", err), - ) - })?; - - let search_for_location = noirc_errors::Location { - file: file_id, - span: noirc_errors::Span::single_char(byte_index as u32), + let _ = noirc_driver::check_crate(&mut context, crate_id, false, false, false); + &context.def_interner }; + let files = workspace_file_manager.as_file_map(); + let file_path = PathString::from(file_path); + let search_for_location = + position_to_location(files, &file_path, ¶ms.text_document_position_params.position)?; + let goto_declaration_response = interner.get_declaration_location_from(search_for_location).and_then(|found_location| { let file_id = found_location.file; let definition_position = to_lsp_location(files, file_id, found_location.span)?; - let response: GotoDeclarationResponse = - GotoDeclarationResponse::from(definition_position).to_owned(); + let response = GotoDeclarationResponse::from(definition_position).to_owned(); Some(response) }); diff --git a/tooling/lsp/src/requests/goto_definition.rs b/tooling/lsp/src/requests/goto_definition.rs index 88bb667f2e8..3a92e28cc11 100644 --- a/tooling/lsp/src/requests/goto_definition.rs +++ b/tooling/lsp/src/requests/goto_definition.rs @@ -4,12 +4,13 @@ use crate::{parse_diff, resolve_workspace_for_source_path}; use crate::{types::GotoDefinitionResult, LspState}; use async_lsp::{ErrorCode, ResponseError}; +use fm::PathString; use lsp_types::request::GotoTypeDefinitionParams; use lsp_types::{GotoDefinitionParams, GotoDefinitionResponse}; use nargo::insert_all_files_for_workspace_into_file_manager; use noirc_driver::file_manager_with_stdlib; -use super::{position_to_byte_index, to_lsp_location}; +use super::{position_to_location, to_lsp_location}; pub(crate) fn on_goto_definition_request( state: &mut LspState, @@ -40,8 +41,6 @@ fn on_goto_definition_inner( let workspace = resolve_workspace_for_source_path(file_path.as_path()).unwrap(); let package = workspace.members.first().unwrap(); - let package_root_path: String = package.root_dir.as_os_str().to_string_lossy().into(); - let mut workspace_file_manager = file_manager_with_stdlib(&workspace.root_dir); insert_all_files_for_workspace_into_file_manager(&workspace, &mut workspace_file_manager); let parsed_files = parse_diff(&workspace_file_manager, state); @@ -49,41 +48,26 @@ fn on_goto_definition_inner( let (mut context, crate_id) = nargo::prepare_package(&workspace_file_manager, &parsed_files, package); - let interner; - if let Some(def_interner) = state.cached_definitions.get(&package_root_path) { - interner = def_interner; + let package_root_path = package.root_dir.as_os_str().to_string_lossy().into_owned(); + let interner = if let Some(def_interner) = state.cached_definitions.get(&package_root_path) { + def_interner } else { // We ignore the warnings and errors produced by compilation while resolving the definition - let _ = noirc_driver::check_crate(&mut context, crate_id, false, false); - interner = &context.def_interner; - } - - let files = context.file_manager.as_file_map(); - let file_id = context.file_manager.name_to_id(file_path.clone()).ok_or(ResponseError::new( - ErrorCode::REQUEST_FAILED, - format!("Could not find file in file manager. File path: {:?}", file_path), - ))?; - let byte_index = - position_to_byte_index(files, file_id, ¶ms.text_document_position_params.position) - .map_err(|err| { - ResponseError::new( - ErrorCode::REQUEST_FAILED, - format!("Could not convert position to byte index. Error: {:?}", err), - ) - })?; - - let search_for_location = noirc_errors::Location { - file: file_id, - span: noirc_errors::Span::single_char(byte_index as u32), + let _ = noirc_driver::check_crate(&mut context, crate_id, false, false, false); + &context.def_interner }; + let files = workspace_file_manager.as_file_map(); + let file_path = PathString::from(file_path); + let search_for_location = + position_to_location(files, &file_path, ¶ms.text_document_position_params.position)?; + let goto_definition_response = interner .get_definition_location_from(search_for_location, return_type_location_instead) .and_then(|found_location| { let file_id = found_location.file; let definition_position = to_lsp_location(files, file_id, found_location.span)?; - let response: GotoDefinitionResponse = - GotoDefinitionResponse::from(definition_position).to_owned(); + let response = GotoDefinitionResponse::from(definition_position).to_owned(); Some(response) }); diff --git a/tooling/lsp/src/requests/mod.rs b/tooling/lsp/src/requests/mod.rs index ec56cf5045a..769e9ba17ce 100644 --- a/tooling/lsp/src/requests/mod.rs +++ b/tooling/lsp/src/requests/mod.rs @@ -1,8 +1,8 @@ use std::future::Future; use crate::types::{CodeLensOptions, InitializeParams}; -use async_lsp::ResponseError; -use fm::codespan_files::Error; +use async_lsp::{ErrorCode, ResponseError}; +use fm::{codespan_files::Error, FileMap, PathString}; use lsp_types::{ DeclarationCapability, Location, Position, TextDocumentSyncCapability, TextDocumentSyncKind, TypeDefinitionProviderCapability, Url, @@ -171,6 +171,30 @@ where } } +fn position_to_location( + files: &FileMap, + file_path: &PathString, + position: &Position, +) -> Result { + let file_id = files.get_file_id(file_path).ok_or(ResponseError::new( + ErrorCode::REQUEST_FAILED, + format!("Could not find file in file manager. File path: {:?}", file_path), + ))?; + let byte_index = position_to_byte_index(files, file_id, position).map_err(|err| { + ResponseError::new( + ErrorCode::REQUEST_FAILED, + format!("Could not convert position to byte index. Error: {:?}", err), + ) + })?; + + let location = noirc_errors::Location { + file: file_id, + span: noirc_errors::Span::single_char(byte_index as u32), + }; + + Ok(location) +} + fn character_to_line_offset(line: &str, character: u32) -> Result { let line_len = line.len(); let mut character_offset = 0; diff --git a/tooling/lsp/src/requests/profile_run.rs b/tooling/lsp/src/requests/profile_run.rs index 917c247410d..7d06bc87c85 100644 --- a/tooling/lsp/src/requests/profile_run.rs +++ b/tooling/lsp/src/requests/profile_run.rs @@ -5,7 +5,10 @@ use std::{ use acvm::acir::circuit::ExpressionWidth; use async_lsp::{ErrorCode, ResponseError}; -use nargo::{artifacts::debug::DebugArtifact, insert_all_files_for_workspace_into_file_manager}; +use nargo::{ + artifacts::debug::DebugArtifact, insert_all_files_for_workspace_into_file_manager, + ops::report_errors, +}; use nargo_toml::{find_package_manifest, resolve_workspace_from_toml, PackageSelection}; use noirc_driver::{ file_manager_with_stdlib, CompileOptions, DebugFile, NOIR_ARTIFACT_VERSION_STRING, @@ -60,11 +63,18 @@ fn on_profile_run_request_inner( Some(_package) => { let expression_width = ExpressionWidth::Bounded { width: 3 }; - let (compiled_programs, compiled_contracts) = nargo::ops::compile_workspace( + let compiled_workspace = nargo::ops::compile_workspace( &workspace_file_manager, &parsed_files, &workspace, &CompileOptions::default(), + ); + + let (compiled_programs, compiled_contracts) = report_errors( + compiled_workspace, + &workspace_file_manager, + CompileOptions::default().deny_warnings, + CompileOptions::default().silence_warnings, ) .map_err(|err| ResponseError::new(ErrorCode::REQUEST_FAILED, err))?; @@ -74,9 +84,11 @@ fn on_profile_run_request_inner( let compiled_program = nargo::ops::transform_program(compiled_program, expression_width); - let span_opcodes = compiled_program.debug.count_span_opcodes(); - let debug_artifact: DebugArtifact = compiled_program.clone().into(); - opcodes_counts.extend(span_opcodes); + for function_debug in compiled_program.debug.iter() { + let span_opcodes = function_debug.count_span_opcodes(); + opcodes_counts.extend(span_opcodes); + } + let debug_artifact: DebugArtifact = compiled_program.into(); file_map.extend(debug_artifact.file_map); } @@ -84,14 +96,17 @@ fn on_profile_run_request_inner( let compiled_contract = nargo::ops::transform_contract(compiled_contract, expression_width); - let function_debug_info: Vec<_> = - compiled_contract.functions.iter().map(|func| &func.debug).cloned().collect(); - let debug_artifact: DebugArtifact = compiled_contract.into(); - file_map.extend(debug_artifact.file_map); + let function_debug_info = compiled_contract + .functions + .iter() + .flat_map(|func| &func.debug) + .collect::>(); for contract_function_debug in function_debug_info { let span_opcodes = contract_function_debug.count_span_opcodes(); opcodes_counts.extend(span_opcodes); } + let debug_artifact: DebugArtifact = compiled_contract.into(); + file_map.extend(debug_artifact.file_map); } let result = NargoProfileRunResult { file_map, opcodes_counts }; diff --git a/tooling/lsp/src/requests/test_run.rs b/tooling/lsp/src/requests/test_run.rs index 0b88d814265..83b05ba06a2 100644 --- a/tooling/lsp/src/requests/test_run.rs +++ b/tooling/lsp/src/requests/test_run.rs @@ -60,7 +60,7 @@ fn on_test_run_request_inner( Some(package) => { let (mut context, crate_id) = prepare_package(&workspace_file_manager, &parsed_files, package); - if check_crate(&mut context, crate_id, false, false).is_err() { + if check_crate(&mut context, crate_id, false, false, false).is_err() { let result = NargoTestRunResult { id: params.id.clone(), result: "error".to_string(), @@ -84,7 +84,7 @@ fn on_test_run_request_inner( let test_result = run_test( &state.solver, &mut context, - test_function, + &test_function, false, None, &CompileOptions::default(), diff --git a/tooling/lsp/src/requests/tests.rs b/tooling/lsp/src/requests/tests.rs index 5b78fcc65c3..cdf4ad338c4 100644 --- a/tooling/lsp/src/requests/tests.rs +++ b/tooling/lsp/src/requests/tests.rs @@ -61,7 +61,7 @@ fn on_tests_request_inner( prepare_package(&workspace_file_manager, &parsed_files, package); // We ignore the warnings and errors produced by compilation for producing tests // because we can still get the test functions even if compilation fails - let _ = check_crate(&mut context, crate_id, false, false); + let _ = check_crate(&mut context, crate_id, false, false, false); // We don't add test headings for a package if it contains no `#[test]` functions get_package_tests_in_crate(&context, &crate_id, &package.name) diff --git a/tooling/lsp/src/solver.rs b/tooling/lsp/src/solver.rs index d0acbf1aec5..0fcac73b905 100644 --- a/tooling/lsp/src/solver.rs +++ b/tooling/lsp/src/solver.rs @@ -3,14 +3,14 @@ use acvm::BlackBoxFunctionSolver; // This is a struct that wraps a dynamically dispatched `BlackBoxFunctionSolver` // where we proxy the unimplemented stuff to the wrapped backend, but it // allows us to avoid changing function signatures to include the `Box` -pub(super) struct WrapperSolver(pub(super) Box); +pub(super) struct WrapperSolver(pub(super) Box>); -impl BlackBoxFunctionSolver for WrapperSolver { +impl BlackBoxFunctionSolver for WrapperSolver { fn schnorr_verify( &self, public_key_x: &acvm::FieldElement, public_key_y: &acvm::FieldElement, - signature: &[u8], + signature: &[u8; 64], message: &[u8], ) -> Result { self.0.schnorr_verify(public_key_x, public_key_y, signature, message) @@ -24,12 +24,16 @@ impl BlackBoxFunctionSolver for WrapperSolver { self.0.pedersen_commitment(inputs, domain_separator) } - fn fixed_base_scalar_mul( + fn multi_scalar_mul( &self, - low: &acvm::FieldElement, - high: &acvm::FieldElement, - ) -> Result<(acvm::FieldElement, acvm::FieldElement), acvm::BlackBoxResolutionError> { - self.0.fixed_base_scalar_mul(low, high) + points: &[acvm::FieldElement], + scalars_lo: &[acvm::FieldElement], + scalars_hi: &[acvm::FieldElement], + ) -> Result< + (acvm::FieldElement, acvm::FieldElement, acvm::FieldElement), + acvm::BlackBoxResolutionError, + > { + self.0.multi_scalar_mul(points, scalars_lo, scalars_hi) } fn pedersen_hash( @@ -44,10 +48,15 @@ impl BlackBoxFunctionSolver for WrapperSolver { &self, input1_x: &acvm::FieldElement, input1_y: &acvm::FieldElement, + input1_infinite: &acvm::FieldElement, input2_x: &acvm::FieldElement, input2_y: &acvm::FieldElement, - ) -> Result<(acvm::FieldElement, acvm::FieldElement), acvm::BlackBoxResolutionError> { - self.0.ec_add(input1_x, input1_y, input2_x, input2_y) + input2_infinite: &acvm::FieldElement, + ) -> Result< + (acvm::FieldElement, acvm::FieldElement, acvm::FieldElement), + acvm::BlackBoxResolutionError, + > { + self.0.ec_add(input1_x, input1_y, input1_infinite, input2_x, input2_y, input2_infinite) } fn poseidon2_permutation( diff --git a/tooling/nargo/Cargo.toml b/tooling/nargo/Cargo.toml index efd38a182e0..48047d10ea6 100644 --- a/tooling/nargo/Cargo.toml +++ b/tooling/nargo/Cargo.toml @@ -4,20 +4,17 @@ description = "Noir's package manager" version.workspace = true authors.workspace = true edition.workspace = true +rust-version.workspace = true license.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html -[build-dependencies] -rustc_version = "0.4.0" - [dependencies] acvm.workspace = true fm.workspace = true noirc_abi.workspace = true noirc_driver.workspace = true noirc_errors.workspace = true -noirc_evaluator.workspace = true noirc_frontend.workspace = true noirc_printable_type.workspace = true iter-extended.workspace = true diff --git a/tooling/nargo/build.rs b/tooling/nargo/build.rs deleted file mode 100644 index ab2b7579132..00000000000 --- a/tooling/nargo/build.rs +++ /dev/null @@ -1,12 +0,0 @@ -use rustc_version::{version, Version}; - -fn check_rustc_version() { - assert!( - version().unwrap() >= Version::parse("1.73.0").unwrap(), - "The minimal supported rustc version is 1.73.0." - ); -} - -fn main() { - check_rustc_version(); -} diff --git a/tooling/nargo/src/artifacts/contract.rs b/tooling/nargo/src/artifacts/contract.rs index d928b09fcb9..1afc7977aec 100644 --- a/tooling/nargo/src/artifacts/contract.rs +++ b/tooling/nargo/src/artifacts/contract.rs @@ -1,15 +1,27 @@ -use acvm::acir::circuit::Circuit; -use noirc_abi::{Abi, ContractEvent}; -use noirc_driver::{CompiledContract, ContractFunction, ContractFunctionType}; +use acvm::{acir::circuit::Program, FieldElement}; +use noirc_abi::{Abi, AbiType, AbiValue}; +use noirc_driver::{CompiledContract, CompiledContractOutputs, ContractFunction}; use serde::{Deserialize, Serialize}; use noirc_driver::DebugFile; -use noirc_errors::debug_info::DebugInfo; -use std::collections::BTreeMap; +use noirc_errors::debug_info::ProgramDebugInfo; +use std::collections::{BTreeMap, HashMap}; use fm::FileId; -#[derive(Serialize, Deserialize)] +#[derive(Clone, Serialize, Deserialize)] +pub struct ContractOutputsArtifact { + pub structs: HashMap>, + pub globals: HashMap>, +} + +impl From for ContractOutputsArtifact { + fn from(outputs: CompiledContractOutputs) -> Self { + ContractOutputsArtifact { structs: outputs.structs, globals: outputs.globals } + } +} + +#[derive(Clone, Serialize, Deserialize)] pub struct ContractArtifact { /// Version of noir used to compile this contract pub noir_version: String, @@ -17,8 +29,8 @@ pub struct ContractArtifact { pub name: String, /// Each of the contract's functions are compiled into a separate program stored in this `Vec`. pub functions: Vec, - /// All the events defined inside the contract scope. - pub events: Vec, + + pub outputs: ContractOutputsArtifact, /// Map of file Id to the source code so locations in debug info can be mapped to source code they point to. pub file_map: BTreeMap, } @@ -29,7 +41,7 @@ impl From for ContractArtifact { noir_version: contract.noir_version, name: contract.name, functions: contract.functions.into_iter().map(ContractFunctionArtifact::from).collect(), - events: contract.events, + outputs: contract.outputs.into(), file_map: contract.file_map, } } @@ -39,38 +51,38 @@ impl From for ContractArtifact { /// /// A contract function unlike a regular Noir program however can have additional properties. /// One of these being a function type. -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct ContractFunctionArtifact { pub name: String, - pub function_type: ContractFunctionType, + pub is_unconstrained: bool, - pub is_internal: bool, + pub custom_attributes: Vec, pub abi: Abi, #[serde( - serialize_with = "Circuit::serialize_circuit_base64", - deserialize_with = "Circuit::deserialize_circuit_base64" + serialize_with = "Program::serialize_program_base64", + deserialize_with = "Program::deserialize_program_base64" )] - pub bytecode: Circuit, + pub bytecode: Program, #[serde( - serialize_with = "DebugInfo::serialize_compressed_base64_json", - deserialize_with = "DebugInfo::deserialize_compressed_base64_json" + serialize_with = "ProgramDebugInfo::serialize_compressed_base64_json", + deserialize_with = "ProgramDebugInfo::deserialize_compressed_base64_json" )] - pub debug_symbols: DebugInfo, + pub debug_symbols: ProgramDebugInfo, } impl From for ContractFunctionArtifact { fn from(func: ContractFunction) -> Self { ContractFunctionArtifact { name: func.name, - function_type: func.function_type, - is_internal: func.is_internal, + is_unconstrained: func.is_unconstrained, + custom_attributes: func.custom_attributes, abi: func.abi, bytecode: func.bytecode, - debug_symbols: func.debug, + debug_symbols: ProgramDebugInfo { debug_infos: func.debug }, } } } diff --git a/tooling/nargo/src/artifacts/debug.rs b/tooling/nargo/src/artifacts/debug.rs index a249ecb03ad..21102c40fcf 100644 --- a/tooling/nargo/src/artifacts/debug.rs +++ b/tooling/nargo/src/artifacts/debug.rs @@ -1,14 +1,14 @@ use codespan_reporting::files::{Error, Files, SimpleFile}; 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}, ops::Range, }; -pub use super::debug_vars::DebugVars; +pub use super::debug_vars::{DebugVars, StackFrame}; +use super::{contract::ContractArtifact, program::ProgramArtifact}; use fm::{FileId, FileManager, PathString}; /// A Debug Artifact stores, for a given program, the debug info for every function @@ -17,7 +17,6 @@ use fm::{FileId, FileManager, PathString}; pub struct DebugArtifact { pub debug_symbols: Vec, pub file_map: BTreeMap, - pub warnings: Vec, } impl DebugArtifact { @@ -44,7 +43,7 @@ impl DebugArtifact { ); } - Self { debug_symbols, file_map, warnings: Vec::new() } + Self { debug_symbols, file_map } } /// Given a location, returns its file's source code @@ -120,10 +119,15 @@ impl DebugArtifact { impl From for DebugArtifact { fn from(compiled_program: CompiledProgram) -> Self { + DebugArtifact { debug_symbols: compiled_program.debug, file_map: compiled_program.file_map } + } +} + +impl From for DebugArtifact { + fn from(program_artifact: ProgramArtifact) -> Self { DebugArtifact { - debug_symbols: vec![compiled_program.debug], - file_map: compiled_program.file_map, - warnings: compiled_program.warnings, + debug_symbols: program_artifact.debug_symbols.debug_infos, + file_map: program_artifact.file_map, } } } @@ -133,14 +137,22 @@ impl From for DebugArtifact { let all_functions_debug: Vec = compiled_artifact .functions .into_iter() - .map(|contract_function| contract_function.debug) + .flat_map(|contract_function| contract_function.debug) .collect(); - DebugArtifact { - debug_symbols: all_functions_debug, - file_map: compiled_artifact.file_map, - warnings: compiled_artifact.warnings, - } + DebugArtifact { debug_symbols: all_functions_debug, file_map: compiled_artifact.file_map } + } +} + +impl From for DebugArtifact { + fn from(compiled_artifact: ContractArtifact) -> Self { + let all_functions_debug: Vec = compiled_artifact + .functions + .into_iter() + .flat_map(|contract_function| contract_function.debug_symbols.debug_infos) + .collect(); + + DebugArtifact { debug_symbols: all_functions_debug, file_map: compiled_artifact.file_map } } } @@ -231,8 +243,12 @@ mod tests { let mut opcode_locations = BTreeMap::>::new(); opcode_locations.insert(OpcodeLocation::Acir(42), vec![loc]); - let debug_symbols = - vec![DebugInfo::new(opcode_locations, BTreeMap::default(), BTreeMap::default())]; + let debug_symbols = vec![DebugInfo::new( + opcode_locations, + BTreeMap::default(), + BTreeMap::default(), + BTreeMap::default(), + )]; let debug_artifact = DebugArtifact::new(debug_symbols, &fm); let location_in_line = debug_artifact.location_in_line(loc).expect("Expected a range"); diff --git a/tooling/nargo/src/artifacts/debug_vars.rs b/tooling/nargo/src/artifacts/debug_vars.rs index 20f2637f7d6..d2c0bb3ea00 100644 --- a/tooling/nargo/src/artifacts/debug_vars.rs +++ b/tooling/nargo/src/artifacts/debug_vars.rs @@ -1,54 +1,83 @@ -use acvm::brillig_vm::brillig::Value; +use acvm::FieldElement; use noirc_errors::debug_info::{ - DebugTypeId, DebugTypes, DebugVarId, DebugVariable, DebugVariables, + DebugFnId, DebugFunction, DebugInfo, DebugTypeId, DebugVarId, DebugVariable, }; use noirc_printable_type::{decode_value, PrintableType, PrintableValue}; -use std::collections::{HashMap, HashSet}; +use std::collections::HashMap; #[derive(Debug, Default, Clone)] pub struct DebugVars { variables: HashMap, + functions: HashMap, types: HashMap, - active: HashSet, - values: HashMap, + frames: Vec<(DebugFnId, HashMap)>, +} + +pub struct StackFrame<'a> { + pub function_name: &'a str, + pub function_params: Vec<&'a str>, + pub variables: Vec<(&'a str, &'a PrintableValue, &'a PrintableType)>, } impl DebugVars { - pub fn get_variables(&self) -> Vec<(&str, &PrintableValue, &PrintableType)> { - self.active - .iter() - .filter_map(|var_id| { - self.variables.get(var_id).and_then(|debug_var| { - let Some(value) = self.values.get(var_id) else { - return None; - }; - let Some(ptype) = self.types.get(&debug_var.debug_type_id) else { - return None; - }; - Some((debug_var.name.as_str(), value, ptype)) - }) - }) - .collect() + pub fn insert_debug_info(&mut self, info: &DebugInfo) { + self.variables.extend(info.variables.clone()); + self.types.extend(info.types.clone()); + self.functions.extend(info.functions.clone()); + } + + pub fn get_variables(&self) -> Vec { + self.frames.iter().map(|(fn_id, frame)| self.build_stack_frame(fn_id, frame)).collect() + } + + pub fn current_stack_frame(&self) -> Option { + self.frames.last().map(|(fn_id, frame)| self.build_stack_frame(fn_id, frame)) } - pub fn insert_variables(&mut self, vars: &DebugVariables) { - self.variables.extend(vars.clone()); + fn lookup_var(&self, var_id: DebugVarId) -> Option<(&str, &PrintableType)> { + self.variables.get(&var_id).and_then(|debug_var| { + let ptype = self.types.get(&debug_var.debug_type_id)?; + Some((debug_var.name.as_str(), ptype)) + }) } - pub fn insert_types(&mut self, types: &DebugTypes) { - self.types.extend(types.clone()); + fn build_stack_frame<'a>( + &'a self, + fn_id: &DebugFnId, + frame: &'a HashMap, + ) -> StackFrame { + let debug_fn = &self.functions.get(fn_id).expect("failed to find function metadata"); + + let params: Vec<&str> = + debug_fn.arg_names.iter().map(|arg_name| arg_name.as_str()).collect(); + let vars: Vec<(&str, &PrintableValue, &PrintableType)> = frame + .iter() + .filter_map(|(var_id, var_value)| { + self.lookup_var(*var_id).map(|(name, typ)| (name, var_value, typ)) + }) + .collect(); + + StackFrame { + function_name: debug_fn.name.as_str(), + function_params: params, + variables: vars, + } } - pub fn assign_var(&mut self, var_id: DebugVarId, values: &[Value]) { - self.active.insert(var_id); + pub fn assign_var(&mut self, var_id: DebugVarId, values: &[FieldElement]) { let type_id = &self.variables.get(&var_id).unwrap().debug_type_id; let ptype = self.types.get(type_id).unwrap(); - self.values.insert(var_id, decode_value(&mut values.iter().map(|v| v.to_field()), ptype)); + + self.frames + .last_mut() + .expect("unexpected empty stack frames") + .1 + .insert(var_id, decode_value(&mut values.iter().copied(), ptype)); } - pub fn assign_field(&mut self, var_id: DebugVarId, indexes: Vec, values: &[Value]) { - let mut cursor: &mut PrintableValue = self - .values + pub fn assign_field(&mut self, var_id: DebugVarId, indexes: Vec, values: &[FieldElement]) { + let current_frame = &mut self.frames.last_mut().expect("unexpected empty stack frames").1; + let mut cursor: &mut PrintableValue = current_frame .get_mut(&var_id) .unwrap_or_else(|| panic!("value unavailable for var_id {var_id:?}")); let cursor_type_id = &self @@ -62,16 +91,25 @@ impl DebugVars { .unwrap_or_else(|| panic!("type unavailable for type id {cursor_type_id:?}")); for index in indexes.iter() { (cursor, cursor_type) = match (cursor, cursor_type) { - (PrintableValue::Vec(array), PrintableType::Array { length, typ }) => { - if let Some(len) = length { - if *index as u64 >= *len { - panic!("unexpected field index past array length") - } - if *len != array.len() as u64 { - panic!("type/array length mismatch") - } + ( + PrintableValue::Vec { array_elements, is_slice }, + PrintableType::Array { length, typ }, + ) => { + assert!(!*is_slice, "slice has array type"); + if *index >= *length { + panic!("unexpected field index past array length") + } + if *length != array_elements.len() as u32 { + panic!("type/array length mismatch") } - (array.get_mut(*index as usize).unwrap(), &*Box::leak(typ.clone())) + (array_elements.get_mut(*index as usize).unwrap(), &*Box::leak(typ.clone())) + } + ( + PrintableValue::Vec { array_elements, is_slice }, + PrintableType::Slice { typ }, + ) => { + assert!(*is_slice, "slice doesn't have slice type"); + (array_elements.get_mut(*index as usize).unwrap(), &*Box::leak(typ.clone())) } ( PrintableValue::Struct(field_map), @@ -83,29 +121,32 @@ impl DebugVars { let (key, typ) = fields.get(*index as usize).unwrap(); (field_map.get_mut(key).unwrap(), typ) } - (PrintableValue::Vec(array), PrintableType::Tuple { types }) => { + ( + PrintableValue::Vec { array_elements, is_slice }, + PrintableType::Tuple { types }, + ) => { + assert!(!*is_slice, "slice has tuple type"); if *index >= types.len() as u32 { panic!( "unexpected field index ({index}) past tuple length ({})", types.len() ); } - if types.len() != array.len() { + if types.len() != array_elements.len() { panic!("type/array length mismatch") } let typ = types.get(*index as usize).unwrap(); - (array.get_mut(*index as usize).unwrap(), typ) + (array_elements.get_mut(*index as usize).unwrap(), typ) } _ => { panic!("unexpected assign field of {cursor_type:?} type"); } }; } - *cursor = decode_value(&mut values.iter().map(|v| v.to_field()), cursor_type); - self.active.insert(var_id); + *cursor = decode_value(&mut values.iter().copied(), cursor_type); } - pub fn assign_deref(&mut self, _var_id: DebugVarId, _values: &[Value]) { + pub fn assign_deref(&mut self, _var_id: DebugVarId, _values: &[FieldElement]) { unimplemented![] } @@ -114,6 +155,14 @@ impl DebugVars { } pub fn drop_var(&mut self, var_id: DebugVarId) { - self.active.remove(&var_id); + self.frames.last_mut().expect("unexpected empty stack frames").1.remove(&var_id); + } + + pub fn push_fn(&mut self, fn_id: DebugFnId) { + self.frames.push((fn_id, HashMap::default())); + } + + pub fn pop_fn(&mut self) { + self.frames.pop(); } } diff --git a/tooling/nargo/src/artifacts/program.rs b/tooling/nargo/src/artifacts/program.rs index d8dc42ec214..91f02157414 100644 --- a/tooling/nargo/src/artifacts/program.rs +++ b/tooling/nargo/src/artifacts/program.rs @@ -1,14 +1,15 @@ use std::collections::BTreeMap; -use acvm::acir::circuit::Circuit; +use acvm::acir::circuit::Program; +use acvm::FieldElement; use fm::FileId; use noirc_abi::Abi; use noirc_driver::CompiledProgram; use noirc_driver::DebugFile; -use noirc_errors::debug_info::DebugInfo; +use noirc_errors::debug_info::ProgramDebugInfo; use serde::{Deserialize, Serialize}; -#[derive(Serialize, Deserialize, Debug)] +#[derive(Clone, Serialize, Deserialize, Debug)] pub struct ProgramArtifact { pub noir_version: String, @@ -21,30 +22,33 @@ pub struct ProgramArtifact { pub abi: Abi, #[serde( - serialize_with = "Circuit::serialize_circuit_base64", - deserialize_with = "Circuit::deserialize_circuit_base64" + serialize_with = "Program::serialize_program_base64", + deserialize_with = "Program::deserialize_program_base64" )] - pub bytecode: Circuit, + pub bytecode: Program, #[serde( - serialize_with = "DebugInfo::serialize_compressed_base64_json", - deserialize_with = "DebugInfo::deserialize_compressed_base64_json" + serialize_with = "ProgramDebugInfo::serialize_compressed_base64_json", + deserialize_with = "ProgramDebugInfo::deserialize_compressed_base64_json" )] - pub debug_symbols: DebugInfo, + pub debug_symbols: ProgramDebugInfo, /// Map of file Id to the source code so locations in debug info can be mapped to source code they point to. pub file_map: BTreeMap, + + pub names: Vec, } impl From for ProgramArtifact { - fn from(program: CompiledProgram) -> Self { + fn from(compiled_program: CompiledProgram) -> Self { ProgramArtifact { - hash: program.hash, - abi: program.abi, - noir_version: program.noir_version, - bytecode: program.circuit, - debug_symbols: program.debug, - file_map: program.file_map, + hash: compiled_program.hash, + abi: compiled_program.abi, + noir_version: compiled_program.noir_version, + bytecode: compiled_program.program, + debug_symbols: ProgramDebugInfo { debug_infos: compiled_program.debug }, + file_map: compiled_program.file_map, + names: compiled_program.names, } } } @@ -55,10 +59,11 @@ impl From for CompiledProgram { hash: program.hash, abi: program.abi, noir_version: program.noir_version, - circuit: program.bytecode, - debug: program.debug_symbols, + program: program.bytecode, + debug: program.debug_symbols.debug_infos, file_map: program.file_map, warnings: vec![], + names: program.names, } } } diff --git a/tooling/nargo/src/constants.rs b/tooling/nargo/src/constants.rs index 0b50d61fe37..1048d86fcd7 100644 --- a/tooling/nargo/src/constants.rs +++ b/tooling/nargo/src/constants.rs @@ -13,8 +13,6 @@ pub const EXPORT_DIR: &str = "export"; // Files /// The file from which Nargo pulls prover inputs pub const PROVER_INPUT_FILE: &str = "Prover"; -/// The file from which Nargo pulls verifier inputs -pub const VERIFIER_INPUT_FILE: &str = "Verifier"; /// The package definition file for a Noir project. pub const PKG_FILE: &str = "Nargo.toml"; diff --git a/tooling/nargo/src/errors.rs b/tooling/nargo/src/errors.rs index c743768bee2..200420e5ce5 100644 --- a/tooling/nargo/src/errors.rs +++ b/tooling/nargo/src/errors.rs @@ -1,7 +1,14 @@ +use std::collections::BTreeMap; + use acvm::{ - acir::circuit::OpcodeLocation, + acir::circuit::{ + ErrorSelector, OpcodeLocation, RawAssertionPayload, ResolvedAssertionPayload, + ResolvedOpcodeLocation, + }, pwg::{ErrorLocation, OpcodeResolutionError}, + FieldElement, }; +use noirc_abi::{display_abi_error, Abi, AbiErrorType}; use noirc_errors::{ debug_info::DebugInfo, reporter::ReportedErrors, CustomDiagnostic, FileDiagnostic, }; @@ -53,20 +60,34 @@ impl NargoError { /// /// We want to extract the user defined error so that we can compare it /// in tests to expected failure messages - pub fn user_defined_failure_message(&self) -> Option<&str> { + pub fn user_defined_failure_message( + &self, + error_types: &BTreeMap, + ) -> Option { let execution_error = match self { NargoError::ExecutionError(error) => error, _ => return None, }; match execution_error { - ExecutionError::AssertionFailed(message, _) => Some(message), - ExecutionError::SolvingError(error) => match error { + ExecutionError::AssertionFailed(payload, _) => match payload { + ResolvedAssertionPayload::String(message) => Some(message.to_string()), + ResolvedAssertionPayload::Raw(raw) => { + let abi_type = error_types.get(&raw.selector)?; + let decoded = display_abi_error(&raw.data, abi_type.clone()); + Some(decoded.to_string()) + } + }, + ExecutionError::SolvingError(error, _) => match error { OpcodeResolutionError::IndexOutOfBounds { .. } | OpcodeResolutionError::OpcodeNotSolvable(_) - | OpcodeResolutionError::UnsatisfiedConstrain { .. } => None, - OpcodeResolutionError::BrilligFunctionFailed { message, .. } => Some(message), - OpcodeResolutionError::BlackBoxFunctionFailed(_, reason) => Some(reason), + | OpcodeResolutionError::UnsatisfiedConstrain { .. } + | OpcodeResolutionError::AcirMainCallAttempted { .. } + | OpcodeResolutionError::BrilligFunctionFailed { .. } + | OpcodeResolutionError::AcirCallOutputsMismatch { .. } => None, + OpcodeResolutionError::BlackBoxFunctionFailed(_, reason) => { + Some(reason.to_string()) + } }, } } @@ -74,82 +95,123 @@ impl NargoError { #[derive(Debug, Error)] pub enum ExecutionError { - #[error("Failed assertion: '{}'", .0)] - AssertionFailed(String, Vec), + #[error("Failed assertion")] + AssertionFailed(ResolvedAssertionPayload, Vec), - #[error(transparent)] - SolvingError(#[from] OpcodeResolutionError), + #[error("Failed to solve program: '{}'", .0)] + SolvingError(OpcodeResolutionError, Option>), } /// Extracts the opcode locations from a nargo error. fn extract_locations_from_error( error: &ExecutionError, - debug: &DebugInfo, + debug: &[DebugInfo], ) -> Option> { let mut opcode_locations = match error { - ExecutionError::SolvingError(OpcodeResolutionError::BrilligFunctionFailed { - call_stack, - .. - }) - | ExecutionError::AssertionFailed(_, call_stack) => Some(call_stack.clone()), - ExecutionError::SolvingError(OpcodeResolutionError::IndexOutOfBounds { - opcode_location: error_location, - .. - }) - | ExecutionError::SolvingError(OpcodeResolutionError::UnsatisfiedConstrain { - opcode_location: error_location, - }) => match error_location { + ExecutionError::SolvingError( + OpcodeResolutionError::BrilligFunctionFailed { .. }, + acir_call_stack, + ) => acir_call_stack.clone(), + ExecutionError::AssertionFailed(_, call_stack) => Some(call_stack.clone()), + ExecutionError::SolvingError( + OpcodeResolutionError::IndexOutOfBounds { opcode_location: error_location, .. }, + acir_call_stack, + ) + | ExecutionError::SolvingError( + OpcodeResolutionError::UnsatisfiedConstrain { opcode_location: error_location, .. }, + acir_call_stack, + ) => match error_location { ErrorLocation::Unresolved => { unreachable!("Cannot resolve index for unsatisfied constraint") } - ErrorLocation::Resolved(opcode_location) => Some(vec![*opcode_location]), + ErrorLocation::Resolved(_) => acir_call_stack.clone(), }, _ => None, }?; - if let Some(OpcodeLocation::Brillig { acir_index, .. }) = opcode_locations.first() { - opcode_locations.insert(0, OpcodeLocation::Acir(*acir_index)); + // Insert the top-level Acir location where the Brillig function failed + for (i, resolved_location) in opcode_locations.iter().enumerate() { + if let ResolvedOpcodeLocation { + acir_function_index, + opcode_location: OpcodeLocation::Brillig { acir_index, .. }, + } = resolved_location + { + let acir_location = ResolvedOpcodeLocation { + acir_function_index: *acir_function_index, + opcode_location: OpcodeLocation::Acir(*acir_index), + }; + + opcode_locations.insert(i, acir_location); + // Go until the first brillig opcode as that means we have the start of a Brillig call stack. + // We have to loop through the opcode locations in case we had ACIR calls + // before the brillig function failure. + break; + } } Some( opcode_locations .iter() - .flat_map(|opcode_location| debug.opcode_location(opcode_location).unwrap_or_default()) + .flat_map(|resolved_location| { + debug[resolved_location.acir_function_index] + .opcode_location(&resolved_location.opcode_location) + .unwrap_or_default() + }) .collect(), ) } -/// Tries to generate a runtime diagnostic from a nargo error. It will successfully do so if it's a runtime error with a call stack. -pub fn try_to_diagnose_runtime_error( +fn extract_message_from_error( + error_types: &BTreeMap, nargo_err: &NargoError, - debug: &DebugInfo, -) -> Option { - let execution_error = match nargo_err { - NargoError::ExecutionError(execution_error) => execution_error, - _ => return None, - }; - - let source_locations = extract_locations_from_error(execution_error, debug)?; - - // The location of the error itself will be the location at the top - // of the call stack (the last item in the Vec). - let location = source_locations.last()?; - - let message = match nargo_err { - NargoError::ExecutionError(ExecutionError::AssertionFailed(message, _)) => { +) -> String { + match nargo_err { + NargoError::ExecutionError(ExecutionError::AssertionFailed( + ResolvedAssertionPayload::String(message), + _, + )) => { format!("Assertion failed: '{message}'") } + NargoError::ExecutionError(ExecutionError::AssertionFailed( + ResolvedAssertionPayload::Raw(RawAssertionPayload { selector, data }), + .., + )) => { + if let Some(error_type) = error_types.get(selector) { + format!("Assertion failed: {}", display_abi_error(data, error_type.clone())) + } else { + "Assertion failed".to_string() + } + } NargoError::ExecutionError(ExecutionError::SolvingError( OpcodeResolutionError::IndexOutOfBounds { index, array_size, .. }, + _, )) => { format!("Index out of bounds, array has size {array_size:?}, but index was {index:?}") } NargoError::ExecutionError(ExecutionError::SolvingError( OpcodeResolutionError::UnsatisfiedConstrain { .. }, + _, )) => "Failed constraint".into(), _ => nargo_err.to_string(), - }; + } +} +/// Tries to generate a runtime diagnostic from a nargo error. It will successfully do so if it's a runtime error with a call stack. +pub fn try_to_diagnose_runtime_error( + nargo_err: &NargoError, + abi: &Abi, + debug: &[DebugInfo], +) -> Option { + let source_locations = match nargo_err { + NargoError::ExecutionError(execution_error) => { + extract_locations_from_error(execution_error, debug)? + } + _ => return None, + }; + // The location of the error itself will be the location at the top + // of the call stack (the last item in the Vec). + let location = source_locations.last()?; + let message = extract_message_from_error(&abi.error_types, nargo_err); Some( CustomDiagnostic::simple_error(message, String::new(), location.span) .in_file(location.file) diff --git a/tooling/nargo/src/ops/compile.rs b/tooling/nargo/src/ops/compile.rs index bd1850649c4..d7c7cc2c123 100644 --- a/tooling/nargo/src/ops/compile.rs +++ b/tooling/nargo/src/ops/compile.rs @@ -21,7 +21,7 @@ pub fn compile_workspace( parsed_files: &ParsedFiles, workspace: &Workspace, compile_options: &CompileOptions, -) -> Result<(Vec, Vec), CompileError> { +) -> CompilationResult<(Vec, Vec)> { let (binary_packages, contract_packages): (Vec<_>, Vec<_>) = workspace .into_iter() .filter(|package| !package.is_library()) @@ -38,31 +38,20 @@ pub fn compile_workspace( .map(|package| compile_contract(file_manager, parsed_files, package, compile_options)) .collect(); - // Report any warnings/errors which were encountered during compilation. - let compiled_programs: Vec = program_results - .into_iter() - .map(|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(|compilation_result| { - report_errors( - compilation_result, - file_manager, - compile_options.deny_warnings, - compile_options.silence_warnings, - ) - }) - .collect::>()?; - - Ok((compiled_programs, compiled_contracts)) + // Collate any warnings/errors which were encountered during compilation. + let compiled_programs = collect_errors(program_results); + let compiled_contracts = collect_errors(contract_results); + + match (compiled_programs, compiled_contracts) { + (Ok((programs, program_warnings)), Ok((contracts, contract_warnings))) => { + let warnings = [program_warnings, contract_warnings].concat(); + Ok(((programs, contracts), warnings)) + } + (Err(program_errors), Err(contract_errors)) => { + Err([program_errors, contract_errors].concat()) + } + (Err(errors), _) | (_, Err(errors)) => Err(errors), + } } pub fn compile_program( @@ -107,7 +96,30 @@ pub fn compile_contract( noirc_driver::compile_contract(&mut context, crate_id, compile_options) } -pub(crate) fn report_errors( +/// Constructs a single `CompilationResult` for a collection of `CompilationResult`s, merging the set of warnings/errors. +pub fn collect_errors(results: Vec>) -> CompilationResult> { + let mut artifacts = Vec::new(); + let mut warnings = Vec::new(); + let mut errors = Vec::new(); + + for result in results { + match result { + Ok((new_artifact, new_warnings)) => { + artifacts.push(new_artifact); + warnings.extend(new_warnings); + } + Err(new_errors) => errors.extend(new_errors), + } + } + + if errors.is_empty() { + Ok((artifacts, warnings)) + } else { + Err(errors) + } +} + +pub fn report_errors( result: CompilationResult, file_manager: &FileManager, deny_warnings: bool, diff --git a/tooling/nargo/src/ops/execute.rs b/tooling/nargo/src/ops/execute.rs index 370393fea09..42e93e0e3cf 100644 --- a/tooling/nargo/src/ops/execute.rs +++ b/tooling/nargo/src/ops/execute.rs @@ -1,80 +1,193 @@ -use acvm::brillig_vm::brillig::ForeignCallResult; -use acvm::pwg::{ACVMStatus, ErrorLocation, OpcodeResolutionError, ACVM}; -use acvm::BlackBoxFunctionSolver; +use acvm::acir::circuit::brillig::BrilligBytecode; +use acvm::acir::circuit::{ + OpcodeLocation, Program, ResolvedAssertionPayload, ResolvedOpcodeLocation, +}; +use acvm::acir::native_types::WitnessStack; +use acvm::pwg::{ACVMStatus, ErrorLocation, OpcodeNotSolvable, OpcodeResolutionError, ACVM}; use acvm::{acir::circuit::Circuit, acir::native_types::WitnessMap}; +use acvm::{BlackBoxFunctionSolver, FieldElement}; use crate::errors::ExecutionError; use crate::NargoError; -use super::foreign_calls::{ForeignCallExecutor, NargoForeignCallResult}; +use super::foreign_calls::ForeignCallExecutor; -#[tracing::instrument(level = "trace", skip_all)] -pub fn execute_circuit( - circuit: &Circuit, - initial_witness: WitnessMap, - blackbox_solver: &B, - foreign_call_executor: &mut F, -) -> Result { - let mut acvm = ACVM::new(blackbox_solver, &circuit.opcodes, initial_witness); - - // This message should be resolved by a nargo foreign call only when we have an unsatisfied assertion. - let mut assert_message: Option = None; - loop { - let solver_status = acvm.solve(); - - match solver_status { - ACVMStatus::Solved => break, - ACVMStatus::InProgress => { - unreachable!("Execution should not stop while in `InProgress` state.") - } - 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, - }; - - return Err(NargoError::ExecutionError(match call_stack { - Some(call_stack) => { - // First check whether we have a runtime assertion message that should be resolved on an ACVM failure - // If we do not have a runtime assertion message, we should check whether the circuit has any hardcoded - // messages associated with a specific `OpcodeLocation`. - // Otherwise return the provided opcode resolution error. - if let Some(assert_message) = assert_message { - ExecutionError::AssertionFailed(assert_message.to_owned(), call_stack) - } else if let Some(assert_message) = 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) +struct ProgramExecutor<'a, B: BlackBoxFunctionSolver, F: ForeignCallExecutor> { + functions: &'a [Circuit], + + unconstrained_functions: &'a [BrilligBytecode], + + // This gets built as we run through the program looking at each function call + witness_stack: WitnessStack, + + blackbox_solver: &'a B, + + foreign_call_executor: &'a mut F, + + // The Noir compiler codegens per function and call stacks are not shared across ACIR function calls. + // We must rebuild a call stack when executing a program of many circuits. + call_stack: Vec, + + // Tracks the index of the current function we are executing. + // This is used to fetch the function we want to execute + // and to resolve call stack locations across many function calls. + current_function_index: usize, +} + +impl<'a, B: BlackBoxFunctionSolver, F: ForeignCallExecutor> + ProgramExecutor<'a, B, F> +{ + fn new( + functions: &'a [Circuit], + unconstrained_functions: &'a [BrilligBytecode], + blackbox_solver: &'a B, + foreign_call_executor: &'a mut F, + ) -> Self { + ProgramExecutor { + functions, + unconstrained_functions, + witness_stack: WitnessStack::default(), + blackbox_solver, + foreign_call_executor, + call_stack: Vec::default(), + current_function_index: 0, + } + } + + fn finalize(self) -> WitnessStack { + self.witness_stack + } + + #[tracing::instrument(level = "trace", skip_all)] + fn execute_circuit( + &mut self, + initial_witness: WitnessMap, + ) -> Result, NargoError> { + let circuit = &self.functions[self.current_function_index]; + let mut acvm = ACVM::new( + self.blackbox_solver, + &circuit.opcodes, + initial_witness, + self.unconstrained_functions, + &circuit.assert_messages, + ); + + loop { + let solver_status = acvm.solve(); + + match solver_status { + ACVMStatus::Solved => break, + ACVMStatus::InProgress => { + unreachable!("Execution should not stop while in `InProgress` state.") + } + ACVMStatus::Failure(error) => { + let call_stack = match &error { + OpcodeResolutionError::UnsatisfiedConstrain { + opcode_location: ErrorLocation::Resolved(opcode_location), + .. } - } - None => ExecutionError::SolvingError(error), - })); - } - ACVMStatus::RequiresForeignCall(foreign_call) => { - let foreign_call_result = foreign_call_executor.execute(&foreign_call)?; - match foreign_call_result { - NargoForeignCallResult::BrilligOutput(foreign_call_result) => { - acvm.resolve_pending_foreign_call(foreign_call_result); - } - NargoForeignCallResult::ResolvedAssertMessage(message) => { - if assert_message.is_some() { - unreachable!("Resolving an assert message should happen only once as the VM should have failed"); + | OpcodeResolutionError::IndexOutOfBounds { + opcode_location: ErrorLocation::Resolved(opcode_location), + .. + } => { + let resolved_location = ResolvedOpcodeLocation { + acir_function_index: self.current_function_index, + opcode_location: *opcode_location, + }; + self.call_stack.push(resolved_location); + Some(self.call_stack.clone()) } - assert_message = Some(message); + OpcodeResolutionError::BrilligFunctionFailed { call_stack, .. } => { + let brillig_call_stack = + call_stack.iter().map(|location| ResolvedOpcodeLocation { + acir_function_index: self.current_function_index, + opcode_location: *location, + }); + self.call_stack.extend(brillig_call_stack); + Some(self.call_stack.clone()) + } + _ => None, + }; + + let assertion_payload: Option> = + match &error { + OpcodeResolutionError::BrilligFunctionFailed { payload, .. } + | OpcodeResolutionError::UnsatisfiedConstrain { payload, .. } => { + payload.clone() + } + _ => None, + }; + + return Err(NargoError::ExecutionError(match assertion_payload { + Some(payload) => ExecutionError::AssertionFailed( + payload, + call_stack.expect("Should have call stack for an assertion failure"), + ), + None => ExecutionError::SolvingError(error, call_stack), + })); + } + ACVMStatus::RequiresForeignCall(foreign_call) => { + let foreign_call_result = self.foreign_call_executor.execute(&foreign_call)?; + acvm.resolve_pending_foreign_call(foreign_call_result); + } + ACVMStatus::RequiresAcirCall(call_info) => { + // Store the parent function index whose context we are currently executing + let acir_function_caller = self.current_function_index; + // Add call opcode to the call stack with a reference to the parent function index + self.call_stack.push(ResolvedOpcodeLocation { + acir_function_index: acir_function_caller, + opcode_location: OpcodeLocation::Acir(acvm.instruction_pointer()), + }); - acvm.resolve_pending_foreign_call(ForeignCallResult::default()); + // Set current function to the circuit we are about to execute + self.current_function_index = call_info.id as usize; + // Execute the ACIR call + let acir_to_call = &self.functions[call_info.id as usize]; + let initial_witness = call_info.initial_witness; + let call_solved_witness = self.execute_circuit(initial_witness)?; + + // Set tracking index back to the parent function after ACIR call execution + self.current_function_index = acir_function_caller; + + let mut call_resolved_outputs = Vec::new(); + for return_witness_index in acir_to_call.return_values.indices() { + if let Some(return_value) = + call_solved_witness.get_index(return_witness_index) + { + call_resolved_outputs.push(*return_value); + } else { + return Err(ExecutionError::SolvingError( + OpcodeNotSolvable::MissingAssignment(return_witness_index).into(), + None, // Missing assignment errors do not supply user-facing diagnostics so we do not need to attach a call stack + ) + .into()); + } } + acvm.resolve_pending_acir_call(call_resolved_outputs); + self.witness_stack.push(call_info.id, call_solved_witness); } } } + + Ok(acvm.finalize()) } +} + +#[tracing::instrument(level = "trace", skip_all)] +pub fn execute_program, F: ForeignCallExecutor>( + program: &Program, + initial_witness: WitnessMap, + blackbox_solver: &B, + foreign_call_executor: &mut F, +) -> Result, NargoError> { + let mut executor = ProgramExecutor::new( + &program.functions, + &program.unconstrained_functions, + blackbox_solver, + foreign_call_executor, + ); + let main_witness = executor.execute_circuit(initial_witness)?; + executor.witness_stack.push(0, main_witness); - Ok(acvm.finalize()) + Ok(executor.finalize()) } diff --git a/tooling/nargo/src/ops/foreign_calls.rs b/tooling/nargo/src/ops/foreign_calls.rs index f7f36c65c90..c6b284beb13 100644 --- a/tooling/nargo/src/ops/foreign_calls.rs +++ b/tooling/nargo/src/ops/foreign_calls.rs @@ -1,6 +1,7 @@ use acvm::{ - acir::brillig::{ForeignCallParam, ForeignCallResult, Value}, + acir::brillig::{ForeignCallParam, ForeignCallResult}, pwg::ForeignCallWaitInfo, + AcirField, FieldElement, }; use jsonrpc::{arg as build_json_rpc_arg, minreq_http::Builder, Client}; use noirc_printable_type::{decode_string_value, ForeignCallError, PrintableValueDisplay}; @@ -8,72 +9,17 @@ use noirc_printable_type::{decode_string_value, ForeignCallError, PrintableValue pub trait ForeignCallExecutor { fn execute( &mut self, - foreign_call: &ForeignCallWaitInfo, - ) -> Result; -} - -#[derive(Debug, PartialEq, Eq, Clone)] -pub enum NargoForeignCallResult { - BrilligOutput(ForeignCallResult), - ResolvedAssertMessage(String), -} - -impl NargoForeignCallResult { - pub fn get_assert_message(self) -> Option { - match self { - Self::ResolvedAssertMessage(msg) => Some(msg), - _ => None, - } - } - - pub fn get_brillig_output(self) -> Option { - match self { - Self::BrilligOutput(foreign_call_result) => Some(foreign_call_result), - _ => None, - } - } -} - -impl From for NargoForeignCallResult { - fn from(value: ForeignCallResult) -> Self { - Self::BrilligOutput(value) - } -} - -impl From for NargoForeignCallResult { - fn from(value: String) -> Self { - Self::ResolvedAssertMessage(value) - } -} - -impl From for NargoForeignCallResult { - fn from(value: Value) -> Self { - let foreign_call_result: ForeignCallResult = value.into(); - foreign_call_result.into() - } -} - -impl From> for NargoForeignCallResult { - fn from(values: Vec) -> Self { - let foreign_call_result: ForeignCallResult = values.into(); - foreign_call_result.into() - } -} - -impl From> for NargoForeignCallResult { - fn from(values: Vec) -> Self { - let foreign_call_result: ForeignCallResult = values.into(); - foreign_call_result.into() - } + foreign_call: &ForeignCallWaitInfo, + ) -> Result, ForeignCallError>; } /// This enumeration represents the Brillig foreign calls that are natively supported by nargo. /// After resolution of a foreign call, nargo will restart execution of the ACVM pub enum ForeignCall { Print, - AssertMessage, CreateMock, SetMockParams, + GetMockLastParams, SetMockReturns, SetMockTimes, ClearMock, @@ -89,9 +35,9 @@ impl ForeignCall { pub(crate) fn name(&self) -> &'static str { match self { ForeignCall::Print => "print", - ForeignCall::AssertMessage => "assert_message", ForeignCall::CreateMock => "create_mock", ForeignCall::SetMockParams => "set_mock_params", + ForeignCall::GetMockLastParams => "get_mock_last_params", ForeignCall::SetMockReturns => "set_mock_returns", ForeignCall::SetMockTimes => "set_mock_times", ForeignCall::ClearMock => "clear_mock", @@ -101,9 +47,9 @@ impl ForeignCall { pub(crate) fn lookup(op_name: &str) -> Option { match op_name { "print" => Some(ForeignCall::Print), - "assert_message" => Some(ForeignCall::AssertMessage), "create_mock" => Some(ForeignCall::CreateMock), "set_mock_params" => Some(ForeignCall::SetMockParams), + "get_mock_last_params" => Some(ForeignCall::GetMockLastParams), "set_mock_returns" => Some(ForeignCall::SetMockReturns), "set_mock_times" => Some(ForeignCall::SetMockTimes), "clear_mock" => Some(ForeignCall::ClearMock), @@ -120,9 +66,11 @@ struct MockedCall { /// The oracle it's mocking name: String, /// Optionally match the parameters - params: Option>, + params: Option>>, + /// The parameters with which the mock was last called + last_called_params: Option>>, /// The result to return when this mock is called - result: ForeignCallResult, + result: ForeignCallResult, /// How many times should this mock be called before it is removed times_left: Option, } @@ -133,6 +81,7 @@ impl MockedCall { id, name, params: None, + last_called_params: None, result: ForeignCallResult { values: vec![] }, times_left: None, } @@ -140,7 +89,7 @@ impl MockedCall { } impl MockedCall { - fn matches(&self, name: &str, params: &[ForeignCallParam]) -> bool { + fn matches(&self, name: &str, params: &[ForeignCallParam]) -> bool { self.name == name && (self.params.is_none() || self.params.as_deref() == Some(params)) } } @@ -160,8 +109,15 @@ pub struct DefaultForeignCallExecutor { impl DefaultForeignCallExecutor { pub fn new(show_output: bool, resolver_url: Option<&str>) -> Self { let oracle_resolver = resolver_url.map(|resolver_url| { - let transport_builder = + let mut transport_builder = Builder::new().url(resolver_url).expect("Invalid oracle resolver URL"); + + if let Some(Ok(timeout)) = + std::env::var("NARGO_FOREIGN_CALL_TIMEOUT").ok().map(|timeout| timeout.parse()) + { + let timeout_duration = std::time::Duration::from_millis(timeout); + transport_builder = transport_builder.timeout(timeout_duration); + }; Client::with_transport(transport_builder.build()) }); DefaultForeignCallExecutor { @@ -174,24 +130,33 @@ impl DefaultForeignCallExecutor { impl DefaultForeignCallExecutor { fn extract_mock_id( - foreign_call_inputs: &[ForeignCallParam], - ) -> Result<(usize, &[ForeignCallParam]), ForeignCallError> { + 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)) + let id = + usize::try_from(id.unwrap_field().try_to_u64().expect("value does not fit into u64")) + .expect("value does not fit into usize"); + Ok((id, params)) + } + + fn find_mock_by_id(&self, id: usize) -> Option<&MockedCall> { + self.mocked_responses.iter().find(|response| response.id == id) } - fn find_mock_by_id(&mut self, id: usize) -> Option<&mut MockedCall> { + fn find_mock_by_id_mut(&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(); + fn parse_string(param: &ForeignCallParam) -> String { + let fields: Vec<_> = param.fields().to_vec(); decode_string_value(&fields) } - fn execute_print(foreign_call_inputs: &[ForeignCallParam]) -> Result<(), ForeignCallError> { - let skip_newline = foreign_call_inputs[0].unwrap_value().is_zero(); + fn execute_print( + foreign_call_inputs: &[ForeignCallParam], + ) -> Result<(), ForeignCallError> { + let skip_newline = foreign_call_inputs[0].unwrap_field().is_zero(); let foreign_call_inputs = foreign_call_inputs.split_first().ok_or(ForeignCallError::MissingForeignCallInputs)?.1; @@ -202,15 +167,8 @@ impl DefaultForeignCallExecutor { Ok(()) } - fn execute_assert_message( - foreign_call_inputs: &[ForeignCallParam], - ) -> Result { - let display_string = Self::format_printable_value(foreign_call_inputs, true)?; - Ok(display_string.into()) - } - fn format_printable_value( - foreign_call_inputs: &[ForeignCallParam], + foreign_call_inputs: &[ForeignCallParam], skip_newline: bool, ) -> Result { let display_values: PrintableValueDisplay = foreign_call_inputs.try_into()?; @@ -224,17 +182,16 @@ impl DefaultForeignCallExecutor { impl ForeignCallExecutor for DefaultForeignCallExecutor { fn execute( &mut self, - foreign_call: &ForeignCallWaitInfo, - ) -> Result { + foreign_call: &ForeignCallWaitInfo, + ) -> Result, ForeignCallError> { let foreign_call_name = foreign_call.function.as_str(); match ForeignCall::lookup(foreign_call_name) { Some(ForeignCall::Print) => { if self.show_output { Self::execute_print(&foreign_call.inputs)?; } - Ok(ForeignCallResult::default().into()) + Ok(ForeignCallResult::default()) } - Some(ForeignCall::AssertMessage) => Self::execute_assert_message(&foreign_call.inputs), Some(ForeignCall::CreateMock) => { let mock_oracle_name = Self::parse_string(&foreign_call.inputs[0]); assert!(ForeignCall::lookup(&mock_oracle_name).is_none()); @@ -242,42 +199,51 @@ impl ForeignCallExecutor for DefaultForeignCallExecutor { self.mocked_responses.push(MockedCall::new(id, mock_oracle_name)); self.last_mock_id += 1; - Ok(Value::from(id).into()) + Ok(FieldElement::from(id).into()) } Some(ForeignCall::SetMockParams) => { let (id, params) = Self::extract_mock_id(&foreign_call.inputs)?; - self.find_mock_by_id(id) + self.find_mock_by_id_mut(id) .unwrap_or_else(|| panic!("Unknown mock id {}", id)) .params = Some(params.to_vec()); - Ok(ForeignCallResult::default().into()) + Ok(ForeignCallResult::default()) + } + Some(ForeignCall::GetMockLastParams) => { + let (id, _) = Self::extract_mock_id(&foreign_call.inputs)?; + let mock = + self.find_mock_by_id(id).unwrap_or_else(|| panic!("Unknown mock id {}", id)); + + let last_called_params = mock + .last_called_params + .clone() + .unwrap_or_else(|| panic!("Mock {} was never called", mock.name)); + + Ok(last_called_params.into()) } Some(ForeignCall::SetMockReturns) => { let (id, params) = Self::extract_mock_id(&foreign_call.inputs)?; - self.find_mock_by_id(id) + self.find_mock_by_id_mut(id) .unwrap_or_else(|| panic!("Unknown mock id {}", id)) .result = ForeignCallResult { values: params.to_vec() }; - Ok(ForeignCallResult::default().into()) + Ok(ForeignCallResult::default()) } Some(ForeignCall::SetMockTimes) => { let (id, params) = Self::extract_mock_id(&foreign_call.inputs)?; - let times = params[0] - .unwrap_value() - .to_field() - .try_to_u64() - .expect("Invalid bit size of times"); + let times = + params[0].unwrap_field().try_to_u64().expect("Invalid bit size of times"); - self.find_mock_by_id(id) + self.find_mock_by_id_mut(id) .unwrap_or_else(|| panic!("Unknown mock id {}", id)) .times_left = Some(times); - Ok(ForeignCallResult::default().into()) + Ok(ForeignCallResult::default()) } Some(ForeignCall::ClearMock) => { let (id, _) = Self::extract_mock_id(&foreign_call.inputs)?; self.mocked_responses.retain(|response| response.id != id); - Ok(ForeignCallResult::default().into()) + Ok(ForeignCallResult::default()) } None => { let mock_response_position = self @@ -285,37 +251,49 @@ impl ForeignCallExecutor for DefaultForeignCallExecutor { .iter() .position(|response| response.matches(foreign_call_name, &foreign_call.inputs)); - match (mock_response_position, &self.external_resolver) { - (Some(response_position), _) => { - let mock = self - .mocked_responses - .get_mut(response_position) - .expect("Invalid position of mocked response"); - let result = mock.result.values.clone(); - - if let Some(times_left) = &mut mock.times_left { - *times_left -= 1; - if *times_left == 0 { - self.mocked_responses.remove(response_position); - } - } + if let Some(response_position) = mock_response_position { + // If the program has registered a mocked response to this oracle call then we prefer responding + // with that. + + let mock = self + .mocked_responses + .get_mut(response_position) + .expect("Invalid position of mocked response"); + + mock.last_called_params = Some(foreign_call.inputs.clone()); - Ok(result.into()) + let result = mock.result.values.clone(); + + if let Some(times_left) = &mut mock.times_left { + *times_left -= 1; + if *times_left == 0 { + self.mocked_responses.remove(response_position); + } } - (None, Some(external_resolver)) => { - let encoded_params: Vec<_> = - foreign_call.inputs.iter().map(build_json_rpc_arg).collect(); - let req = - external_resolver.build_request(foreign_call_name, &encoded_params); + Ok(result.into()) + } else if let Some(external_resolver) = &self.external_resolver { + // If the user has registered an external resolver then we forward any remaining oracle calls there. - let response = external_resolver.send_request(req)?; + let encoded_params: Vec<_> = + foreign_call.inputs.iter().map(build_json_rpc_arg).collect(); - let parsed_response: ForeignCallResult = response.result()?; + let req = external_resolver.build_request(foreign_call_name, &encoded_params); - Ok(parsed_response.into()) - } - (None, None) => panic!("Unknown foreign call {}", foreign_call_name), + let response = external_resolver.send_request(req)?; + + let parsed_response: ForeignCallResult = response.result()?; + + Ok(parsed_response) + } else { + // If there's no registered mock oracle response and no registered resolver then we cannot + // return a correct response to the ACVM. The best we can do is to return an empty response, + // this allows us to ignore any foreign calls which exist solely to pass information from inside + // the circuit to the environment (e.g. custom logging) as the execution will still be able to progress. + // + // We optimistically return an empty response for all oracle calls as the ACVM will error + // should a response have been required. + Ok(ForeignCallResult::default()) } } } @@ -325,10 +303,8 @@ impl ForeignCallExecutor for DefaultForeignCallExecutor { #[cfg(test)] mod tests { use acvm::{ - acir::brillig::ForeignCallParam, - brillig_vm::brillig::{ForeignCallResult, Value}, - pwg::ForeignCallWaitInfo, - FieldElement, + acir::brillig::ForeignCallParam, brillig_vm::brillig::ForeignCallResult, + pwg::ForeignCallWaitInfo, FieldElement, }; use jsonrpc_core::Result as RpcResult; use jsonrpc_derive::rpc; @@ -340,27 +316,39 @@ mod tests { #[rpc] pub trait OracleResolver { #[rpc(name = "echo")] - fn echo(&self, param: ForeignCallParam) -> RpcResult; + fn echo( + &self, + param: ForeignCallParam, + ) -> RpcResult>; #[rpc(name = "sum")] - fn sum(&self, array: ForeignCallParam) -> RpcResult; + fn sum( + &self, + array: ForeignCallParam, + ) -> RpcResult>; } struct OracleResolverImpl; impl OracleResolver for OracleResolverImpl { - fn echo(&self, param: ForeignCallParam) -> RpcResult { + fn echo( + &self, + param: ForeignCallParam, + ) -> RpcResult> { Ok(vec![param].into()) } - fn sum(&self, array: ForeignCallParam) -> RpcResult { + fn sum( + &self, + array: ForeignCallParam, + ) -> RpcResult> { let mut res: FieldElement = 0_usize.into(); - for value in array.values() { - res += value.to_field(); + for value in array.fields() { + res += value; } - Ok(Value::from(res).into()) + Ok(res.into()) } } @@ -389,7 +377,7 @@ mod tests { }; let result = executor.execute(&foreign_call); - assert_eq!(result.unwrap(), ForeignCallResult { values: foreign_call.inputs }.into()); + assert_eq!(result.unwrap(), ForeignCallResult { values: foreign_call.inputs }); server.close(); } @@ -406,7 +394,7 @@ mod tests { }; let result = executor.execute(&foreign_call); - assert_eq!(result.unwrap(), Value::from(3_usize).into()); + assert_eq!(result.unwrap(), FieldElement::from(3_usize).into()); server.close(); } diff --git a/tooling/nargo/src/ops/mod.rs b/tooling/nargo/src/ops/mod.rs index 23dd0db15b9..cada2f0e915 100644 --- a/tooling/nargo/src/ops/mod.rs +++ b/tooling/nargo/src/ops/mod.rs @@ -1,10 +1,9 @@ pub use self::compile::{ - compile_contract, compile_program, compile_program_with_debug_instrumenter, compile_workspace, -}; -pub use self::execute::execute_circuit; -pub use self::foreign_calls::{ - DefaultForeignCallExecutor, ForeignCall, ForeignCallExecutor, NargoForeignCallResult, + collect_errors, compile_contract, compile_program, compile_program_with_debug_instrumenter, + compile_workspace, report_errors, }; +pub use self::execute::execute_program; +pub use self::foreign_calls::{DefaultForeignCallExecutor, ForeignCall, ForeignCallExecutor}; pub use self::optimize::{optimize_contract, optimize_program}; pub use self::transform::{transform_contract, transform_program}; diff --git a/tooling/nargo/src/ops/optimize.rs b/tooling/nargo/src/ops/optimize.rs index 2d0c4c43d25..07adfb57df4 100644 --- a/tooling/nargo/src/ops/optimize.rs +++ b/tooling/nargo/src/ops/optimize.rs @@ -1,20 +1,39 @@ +use acvm::{acir::circuit::Program, FieldElement}; use iter_extended::vecmap; use noirc_driver::{CompiledContract, CompiledProgram}; +use noirc_errors::debug_info::DebugInfo; -pub fn optimize_program(mut program: CompiledProgram) -> CompiledProgram { - let (optimized_circuit, location_map) = acvm::compiler::optimize(program.circuit); - program.circuit = optimized_circuit; - program.debug.update_acir(location_map); - program +pub fn optimize_program(mut compiled_program: CompiledProgram) -> CompiledProgram { + compiled_program.program = + optimize_program_internal(compiled_program.program, &mut compiled_program.debug); + compiled_program } pub fn optimize_contract(contract: CompiledContract) -> CompiledContract { let functions = vecmap(contract.functions, |mut func| { - let (optimized_bytecode, location_map) = acvm::compiler::optimize(func.bytecode); - func.bytecode = optimized_bytecode; - func.debug.update_acir(location_map); + func.bytecode = optimize_program_internal(func.bytecode, &mut func.debug); func }); CompiledContract { functions, ..contract } } + +fn optimize_program_internal( + mut program: Program, + debug: &mut [DebugInfo], +) -> Program { + let functions = std::mem::take(&mut program.functions); + + let optimized_functions = functions + .into_iter() + .enumerate() + .map(|(i, function)| { + let (optimized_circuit, location_map) = acvm::compiler::optimize(function); + debug[i].update_acir(location_map); + optimized_circuit + }) + .collect::>(); + + program.functions = optimized_functions; + program +} diff --git a/tooling/nargo/src/ops/test.rs b/tooling/nargo/src/ops/test.rs index 92c09ec889e..ed45251ac8a 100644 --- a/tooling/nargo/src/ops/test.rs +++ b/tooling/nargo/src/ops/test.rs @@ -1,12 +1,15 @@ -use acvm::{acir::native_types::WitnessMap, BlackBoxFunctionSolver}; +use acvm::{ + acir::native_types::{WitnessMap, WitnessStack}, + BlackBoxFunctionSolver, FieldElement, +}; +use noirc_abi::Abi; use noirc_driver::{compile_no_check, CompileError, CompileOptions}; use noirc_errors::{debug_info::DebugInfo, FileDiagnostic}; -use noirc_evaluator::errors::RuntimeError; use noirc_frontend::hir::{def_map::TestFunction, Context}; use crate::{errors::try_to_diagnose_runtime_error, NargoError}; -use super::{execute_circuit, DefaultForeignCallExecutor}; +use super::{execute_program, DefaultForeignCallExecutor}; pub enum TestStatus { Pass, @@ -14,26 +17,37 @@ pub enum TestStatus { CompileError(FileDiagnostic), } -pub fn run_test( +impl TestStatus { + pub fn failed(&self) -> bool { + !matches!(self, TestStatus::Pass) + } +} + +pub fn run_test>( blackbox_solver: &B, context: &mut Context, - test_function: TestFunction, + test_function: &TestFunction, show_output: bool, foreign_call_resolver_url: Option<&str>, config: &CompileOptions, ) -> TestStatus { - let program = compile_no_check(context, config, test_function.get_id(), None, false); - match program { - Ok(program) => { + let compiled_program = compile_no_check(context, config, test_function.get_id(), None, false); + match compiled_program { + Ok(compiled_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( - &program.circuit, + let circuit_execution = execute_program( + &compiled_program.program, WitnessMap::new(), blackbox_solver, &mut DefaultForeignCallExecutor::new(show_output, foreign_call_resolver_url), ); - test_status_program_compile_pass(test_function, program.debug, circuit_execution) + test_status_program_compile_pass( + test_function, + compiled_program.abi, + compiled_program.debug, + circuit_execution, + ) } Err(err) => test_status_program_compile_fail(err, test_function), } @@ -45,24 +59,13 @@ pub fn run_test( /// that a constraint was never satisfiable. /// An example of this is the program `assert(false)` /// In that case, we check if the test function should fail, and if so, we return `TestStatus::Pass`. -fn test_status_program_compile_fail(err: CompileError, test_function: TestFunction) -> TestStatus { +fn test_status_program_compile_fail(err: CompileError, test_function: &TestFunction) -> TestStatus { // The test has failed compilation, but it should never fail. Report error. if !test_function.should_fail() { return TestStatus::CompileError(err.into()); } - // The test has failed compilation, extract the assertion message if present and check if it's expected. - let assert_message = if let CompileError::RuntimeError(RuntimeError::FailedConstraint { - assert_message, - .. - }) = &err - { - assert_message.clone() - } else { - None - }; - - check_expected_failure_message(test_function, assert_message, Some(err.into())) + check_expected_failure_message(test_function, None, Some(err.into())) } /// The test function compiled successfully. @@ -70,9 +73,10 @@ fn test_status_program_compile_fail(err: CompileError, test_function: TestFuncti /// We now check whether execution passed/failed and whether it should have /// passed/failed to determine the test status. fn test_status_program_compile_pass( - test_function: TestFunction, - debug: DebugInfo, - circuit_execution: Result, + test_function: &TestFunction, + abi: Abi, + debug: Vec, + circuit_execution: Result, NargoError>, ) -> TestStatus { let circuit_execution_err = match circuit_execution { // Circuit execution was successful; ie no errors or unsatisfied constraints @@ -92,7 +96,7 @@ fn test_status_program_compile_pass( // If we reach here, then the circuit execution failed. // // Check if the function should have passed - let diagnostic = try_to_diagnose_runtime_error(&circuit_execution_err, &debug); + let diagnostic = try_to_diagnose_runtime_error(&circuit_execution_err, &abi, &debug); let test_should_have_passed = !test_function.should_fail(); if test_should_have_passed { return TestStatus::Fail { @@ -103,13 +107,13 @@ fn test_status_program_compile_pass( check_expected_failure_message( test_function, - circuit_execution_err.user_defined_failure_message().map(|s| s.to_string()), + circuit_execution_err.user_defined_failure_message(&abi.error_types), diagnostic, ) } fn check_expected_failure_message( - test_function: TestFunction, + test_function: &TestFunction, failed_assertion: Option, error_diagnostic: Option, ) -> TestStatus { diff --git a/tooling/nargo/src/ops/transform.rs b/tooling/nargo/src/ops/transform.rs index 9267ed7e045..9255ac3e0ec 100644 --- a/tooling/nargo/src/ops/transform.rs +++ b/tooling/nargo/src/ops/transform.rs @@ -1,17 +1,21 @@ -use acvm::acir::circuit::ExpressionWidth; +use acvm::{ + acir::circuit::{ExpressionWidth, Program}, + FieldElement, +}; use iter_extended::vecmap; use noirc_driver::{CompiledContract, CompiledProgram}; +use noirc_errors::debug_info::DebugInfo; pub fn transform_program( - mut program: CompiledProgram, + mut compiled_program: CompiledProgram, expression_width: ExpressionWidth, ) -> CompiledProgram { - let (optimized_circuit, location_map) = - acvm::compiler::compile(program.circuit, expression_width); - - program.circuit = optimized_circuit; - program.debug.update_acir(location_map); - program + compiled_program.program = transform_program_internal( + compiled_program.program, + &mut compiled_program.debug, + expression_width, + ); + compiled_program } pub fn transform_contract( @@ -19,12 +23,33 @@ pub fn transform_contract( expression_width: ExpressionWidth, ) -> CompiledContract { let functions = vecmap(contract.functions, |mut func| { - let (optimized_bytecode, location_map) = - acvm::compiler::compile(func.bytecode, expression_width); - func.bytecode = optimized_bytecode; - func.debug.update_acir(location_map); + func.bytecode = + transform_program_internal(func.bytecode, &mut func.debug, expression_width); + func }); CompiledContract { functions, ..contract } } + +fn transform_program_internal( + mut program: Program, + debug: &mut [DebugInfo], + expression_width: ExpressionWidth, +) -> Program { + let functions = std::mem::take(&mut program.functions); + + let optimized_functions = functions + .into_iter() + .enumerate() + .map(|(i, function)| { + let (optimized_circuit, location_map) = + acvm::compiler::compile(function, expression_width); + debug[i].update_acir(location_map); + optimized_circuit + }) + .collect::>(); + + program.functions = optimized_functions; + program +} diff --git a/tooling/nargo/src/package.rs b/tooling/nargo/src/package.rs index ecbf3585210..44f0a3504f7 100644 --- a/tooling/nargo/src/package.rs +++ b/tooling/nargo/src/package.rs @@ -2,7 +2,7 @@ use std::{collections::BTreeMap, fmt::Display, path::PathBuf}; use noirc_frontend::graph::CrateName; -use crate::constants::{PROVER_INPUT_FILE, VERIFIER_INPUT_FILE}; +use crate::constants::PROVER_INPUT_FILE; #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum PackageType { @@ -59,11 +59,6 @@ impl Package { // For now it is hard-coded to be toml. self.root_dir.join(format!("{PROVER_INPUT_FILE}.toml")) } - pub fn verifier_input_path(&self) -> PathBuf { - // TODO: This should be configurable, such as if we are looking for .json or .toml or custom paths - // For now it is hard-coded to be toml. - self.root_dir.join(format!("{VERIFIER_INPUT_FILE}.toml")) - } pub fn is_binary(&self) -> bool { self.package_type == PackageType::Binary diff --git a/tooling/nargo_cli/Cargo.toml b/tooling/nargo_cli/Cargo.toml index 57edbf5ae04..a9946c8700c 100644 --- a/tooling/nargo_cli/Cargo.toml +++ b/tooling/nargo_cli/Cargo.toml @@ -1,9 +1,11 @@ [package] name = "nargo_cli" description = "Noir's package manager" +default-run = "nargo" version.workspace = true authors.workspace = true edition.workspace = true +rust-version.workspace = true license.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -14,7 +16,6 @@ name = "nargo" path = "src/main.rs" [build-dependencies] -rustc_version = "0.4.0" build-data.workspace = true toml.workspace = true @@ -28,10 +29,10 @@ nargo_toml.workspace = true noir_lsp.workspace = true noir_debugger.workspace = true noirc_driver.workspace = true -noirc_frontend.workspace = true +noirc_frontend = { workspace = true, features = ["bn254"] } noirc_abi.workspace = true noirc_errors.workspace = true -acvm.workspace = true +acvm = { workspace = true, features = ["bn254"] } bn254_blackbox_solver.workspace = true toml.workspace = true serde.workspace = true @@ -42,16 +43,16 @@ thiserror.workspace = true tower.workspace = true async-lsp = { workspace = true, features = ["client-monitor", "stdio", "tracing", "tokio"] } const_format.workspace = true -hex.workspace = true similar-asserts.workspace = true termcolor = "1.1.2" color-eyre = "0.6.2" -tokio = { version = "1.0", features = ["io-std"] } +tokio = { version = "1.0", features = ["io-std", "rt"] } dap.workspace = true clap-markdown = { git = "https://github.com/noir-lang/clap-markdown", rev = "450d759532c88f0dba70891ceecdbc9ff8f25d2b", optional = true } -# Backends -backend-interface = { path = "../backend_interface" } +notify = "6.1.1" +notify-debouncer-full = "0.3.1" +termion = "3.0.0" # Logs tracing-subscriber.workspace = true @@ -67,13 +68,9 @@ assert_cmd = "2.0.8" assert_fs = "1.0.10" predicates = "2.1.5" fm.workspace = true -criterion = "0.5.0" +criterion.workspace = true +pprof.workspace = true paste = "1.0.14" -pprof = { version = "0.12", features = [ - "flamegraph", - "frame-pointer", - "criterion", -] } iai = "0.1.1" test-binary = "3.0.2" @@ -86,4 +83,4 @@ name = "iai" harness = false [features] -codegen-docs = ["dep:clap-markdown"] \ No newline at end of file +codegen-docs = ["dep:clap-markdown"] diff --git a/tooling/nargo_cli/benches/criterion.rs b/tooling/nargo_cli/benches/criterion.rs index a7b094fd7aa..9f67bcffd6e 100644 --- a/tooling/nargo_cli/benches/criterion.rs +++ b/tooling/nargo_cli/benches/criterion.rs @@ -1,9 +1,10 @@ //! Select representative tests to bench with criterion use assert_cmd::prelude::{CommandCargoExt, OutputAssertExt}; use criterion::{criterion_group, criterion_main, Criterion}; + use paste::paste; use pprof::criterion::{Output, PProfProfiler}; -use std::process::Command; +use std::{process::Command, time::Duration}; include!("./utils.rs"); macro_rules! criterion_command { @@ -15,9 +16,11 @@ macro_rules! criterion_command { let mut cmd = Command::cargo_bin("nargo").unwrap(); cmd.arg("--program-dir").arg(&test_program_dir); cmd.arg($command_string); + cmd.arg("--force"); - c.bench_function(&format!("{}_{}", test_program_dir.file_name().unwrap().to_str().unwrap(), $command_string), |b| { - b.iter(|| cmd.assert()) + let benchmark_name = format!("{}_{}", test_program_dir.file_name().unwrap().to_str().unwrap(), $command_string); + c.bench_function(&benchmark_name, |b| { + b.iter(|| cmd.assert().success()) }); } } @@ -25,9 +28,16 @@ macro_rules! criterion_command { }; } criterion_command!(execution, "execute"); +criterion_command!(prove, "prove"); + +criterion_group! { + name = execution_benches; + config = Criterion::default().sample_size(20).measurement_time(Duration::from_secs(20)).with_profiler(PProfProfiler::new(100, Output::Flamegraph(None))); + targets = criterion_selected_tests_execution +} criterion_group! { - name = benches; - config = Criterion::default().sample_size(20).with_profiler(PProfProfiler::new(100, Output::Flamegraph(None))); - targets = criterion_selected_tests_execution + name = prove_benches; + config = Criterion::default().sample_size(10).measurement_time(Duration::from_secs(20)).with_profiler(PProfProfiler::new(100, Output::Flamegraph(None))); + targets = criterion_selected_tests_prove } -criterion_main!(benches); +criterion_main!(execution_benches, prove_benches); diff --git a/tooling/nargo_cli/benches/utils.rs b/tooling/nargo_cli/benches/utils.rs index 52a6b718c44..47968f7e898 100644 --- a/tooling/nargo_cli/benches/utils.rs +++ b/tooling/nargo_cli/benches/utils.rs @@ -4,11 +4,16 @@ use std::path::PathBuf; fn get_selected_tests() -> Vec { let manifest_dir = match std::env::var("CARGO_MANIFEST_DIR") { Ok(dir) => PathBuf::from(dir), - Err(_) => std::env::current_dir().unwrap().join("crates").join("nargo_cli"), + Err(_) => std::env::current_dir().unwrap(), }; - let test_dir = manifest_dir.join("tests").join("execution_success"); + let test_dir = manifest_dir + .parent() + .unwrap() + .parent() + .unwrap() + .join("test_programs") + .join("execution_success"); - let selected_tests = - vec!["8_integration", "sha256_blocks", "struct", "eddsa", "regression", "regression_2099"]; + let selected_tests = vec!["struct", "eddsa", "regression"]; selected_tests.into_iter().map(|t| test_dir.join(t)).collect() } diff --git a/tooling/nargo_cli/build.rs b/tooling/nargo_cli/build.rs index 1ca12b75dfb..25a69489788 100644 --- a/tooling/nargo_cli/build.rs +++ b/tooling/nargo_cli/build.rs @@ -1,23 +1,12 @@ -use rustc_version::{version, Version}; use std::fs::File; use std::io::Write; use std::path::{Path, PathBuf}; use std::{env, fs}; -fn check_rustc_version() { - assert!( - version().unwrap() >= Version::parse("1.73.0").unwrap(), - "The minimal supported rustc version is 1.73.0." - ); -} - const GIT_COMMIT: &&str = &"GIT_COMMIT"; fn main() { - check_rustc_version(); - - // Only use build_data if the environment variable isn't set - // The environment variable is always set when working via Nix + // Only use build_data if the environment variable isn't set. if std::env::var(GIT_COMMIT).is_err() { build_data::set_GIT_COMMIT(); build_data::set_GIT_DIRTY(); @@ -41,6 +30,7 @@ fn main() { println!("cargo:rerun-if-changed={}", test_dir.as_os_str().to_str().unwrap()); generate_execution_success_tests(&mut test_file, &test_dir); + generate_execution_failure_tests(&mut test_file, &test_dir); generate_noir_test_success_tests(&mut test_file, &test_dir); generate_noir_test_failure_tests(&mut test_file, &test_dir); generate_compile_success_empty_tests(&mut test_file, &test_dir); @@ -48,6 +38,26 @@ fn main() { generate_compile_failure_tests(&mut test_file, &test_dir); } +/// Some tests are explicitly ignored in brillig due to them failing. +/// These should be fixed and removed from this list. +const IGNORED_BRILLIG_TESTS: [&str; 11] = [ + // Takes a very long time to execute as large loops do not get simplified. + &"regression_4709", + // bit sizes for bigint operation doesn't match up. + &"bigint", + // ICE due to looking for function which doesn't exist. + &"fold_after_inlined_calls", + &"fold_basic", + &"fold_basic_nested_call", + &"fold_call_witness_condition", + &"fold_complex_outputs", + &"fold_distinct_return", + &"fold_fibonacci", + &"fold_numeric_generic_poseidon", + // Expected to fail as test asserts on which runtime it is in. + &"is_unconstrained", +]; + fn generate_execution_success_tests(test_file: &mut File, test_data_dir: &Path) { let test_sub_dir = "execution_success"; let test_data_dir = test_data_dir.join(test_sub_dir); @@ -65,6 +75,9 @@ fn generate_execution_success_tests(test_file: &mut File, test_data_dir: &Path) }; let test_dir = &test_dir.path(); + let brillig_ignored = + if IGNORED_BRILLIG_TESTS.contains(&test_name.as_str()) { "\n#[ignore]" } else { "" }; + write!( test_file, r#" @@ -73,12 +86,81 @@ fn execution_success_{test_name}() {{ let test_program_dir = PathBuf::from("{test_dir}"); let mut cmd = Command::cargo_bin("nargo").unwrap(); - cmd.env("NARGO_BACKEND_PATH", path_to_mock_backend()); cmd.arg("--program-dir").arg(test_program_dir); cmd.arg("execute").arg("--force"); cmd.assert().success(); }} + +#[test] +fn execution_success_elaborator_{test_name}() {{ + let test_program_dir = PathBuf::from("{test_dir}"); + + let mut cmd = Command::cargo_bin("nargo").unwrap(); + cmd.arg("--program-dir").arg(test_program_dir); + cmd.arg("execute").arg("--force").arg("--use-elaborator"); + + cmd.assert().success(); +}} + +#[test]{brillig_ignored} +fn execution_success_{test_name}_brillig() {{ + let test_program_dir = PathBuf::from("{test_dir}"); + + let mut cmd = Command::cargo_bin("nargo").unwrap(); + cmd.arg("--program-dir").arg(test_program_dir); + cmd.arg("execute").arg("--force").arg("--force-brillig"); + + cmd.assert().success(); +}} + "#, + test_dir = test_dir.display(), + ) + .expect("Could not write templated test file."); + } +} + +fn generate_execution_failure_tests(test_file: &mut File, test_data_dir: &Path) { + let test_sub_dir = "execution_failure"; + let test_data_dir = test_data_dir.join(test_sub_dir); + + let test_case_dirs = + fs::read_dir(test_data_dir).unwrap().flatten().filter(|c| c.path().is_dir()); + + for test_dir in test_case_dirs { + let test_name = + test_dir.file_name().into_string().expect("Directory can't be converted to string"); + if test_name.contains('-') { + panic!( + "Invalid test directory: {test_name}. Cannot include `-`, please convert to `_`" + ); + }; + let test_dir = &test_dir.path(); + + write!( + test_file, + r#" +#[test] +fn execution_failure_{test_name}() {{ + let test_program_dir = PathBuf::from("{test_dir}"); + + let mut cmd = Command::cargo_bin("nargo").unwrap(); + cmd.arg("--program-dir").arg(test_program_dir); + cmd.arg("execute").arg("--force"); + + cmd.assert().failure().stderr(predicate::str::contains("The application panicked (crashed).").not()); +}} + +#[test] +fn execution_failure_elaborator_{test_name}() {{ + let test_program_dir = PathBuf::from("{test_dir}"); + + let mut cmd = Command::cargo_bin("nargo").unwrap(); + cmd.arg("--program-dir").arg(test_program_dir); + cmd.arg("execute").arg("--force").arg("--use-elaborator"); + + cmd.assert().failure().stderr(predicate::str::contains("The application panicked (crashed).").not()); +}} "#, test_dir = test_dir.display(), ) @@ -111,10 +193,20 @@ fn noir_test_success_{test_name}() {{ let test_program_dir = PathBuf::from("{test_dir}"); let mut cmd = Command::cargo_bin("nargo").unwrap(); - cmd.env("NARGO_BACKEND_PATH", path_to_mock_backend()); cmd.arg("--program-dir").arg(test_program_dir); cmd.arg("test"); + cmd.assert().success(); +}} + +#[test] +fn noir_test_success_elaborator_{test_name}() {{ + let test_program_dir = PathBuf::from("{test_dir}"); + + let mut cmd = Command::cargo_bin("nargo").unwrap(); + cmd.arg("--program-dir").arg(test_program_dir); + cmd.arg("test").arg("--use-elaborator"); + cmd.assert().success(); }} "#, @@ -149,10 +241,20 @@ fn noir_test_failure_{test_name}() {{ let test_program_dir = PathBuf::from("{test_dir}"); let mut cmd = Command::cargo_bin("nargo").unwrap(); - cmd.env("NARGO_BACKEND_PATH", path_to_mock_backend()); cmd.arg("--program-dir").arg(test_program_dir); cmd.arg("test"); + cmd.assert().failure(); +}} + +#[test] +fn noir_test_failure_elaborator_{test_name}() {{ + let test_program_dir = PathBuf::from("{test_dir}"); + + let mut cmd = Command::cargo_bin("nargo").unwrap(); + cmd.arg("--program-dir").arg(test_program_dir); + cmd.arg("test").arg("--use-elaborator"); + cmd.assert().failure(); }} "#, @@ -190,7 +292,6 @@ fn compile_success_empty_{test_name}() {{ let test_program_dir = PathBuf::from("{test_dir}"); let mut cmd = Command::cargo_bin("nargo").unwrap(); - cmd.env("NARGO_BACKEND_PATH", path_to_mock_backend()); cmd.arg("--program-dir").arg(test_program_dir); cmd.arg("info"); cmd.arg("--json"); @@ -203,10 +304,34 @@ fn compile_success_empty_{test_name}() {{ }} // `compile_success_empty` tests should be able to compile down to an empty circuit. - let json: serde_json::Value = serde_json::from_slice(&output.stdout).unwrap_or_else(|_| {{ - panic!("JSON was not well-formatted {{:?}}",output.stdout) + let json: serde_json::Value = serde_json::from_slice(&output.stdout).unwrap_or_else(|e| {{ + panic!("JSON was not well-formatted {{:?}}\n\n{{:?}}", e, std::str::from_utf8(&output.stdout)) + }}); + let num_opcodes = &json["programs"][0]["functions"][0]["acir_opcodes"]; + assert_eq!(num_opcodes.as_u64().expect("number of opcodes should fit in a u64"), 0); +}} + +#[test] +fn compile_success_empty_elaborator_{test_name}() {{ + let test_program_dir = PathBuf::from("{test_dir}"); + let mut cmd = Command::cargo_bin("nargo").unwrap(); + cmd.arg("--program-dir").arg(test_program_dir); + cmd.arg("info"); + cmd.arg("--json"); + cmd.arg("--force"); + cmd.arg("--use-elaborator"); + + let output = cmd.output().expect("Failed to execute command"); + + if !output.status.success() {{ + panic!("`nargo info` failed with: {{}}", String::from_utf8(output.stderr).unwrap_or_default()); + }} + + // `compile_success_empty` tests should be able to compile down to an empty circuit. + let json: serde_json::Value = serde_json::from_slice(&output.stdout).unwrap_or_else(|e| {{ + panic!("JSON was not well-formatted {{:?}}\n\n{{:?}}", e, std::str::from_utf8(&output.stdout)) }}); - let num_opcodes = &json["programs"][0]["acir_opcodes"]; + let num_opcodes = &json["programs"][0]["functions"][0]["acir_opcodes"]; assert_eq!(num_opcodes.as_u64().expect("number of opcodes should fit in a u64"), 0); }} "#, @@ -241,10 +366,19 @@ fn compile_success_contract_{test_name}() {{ let test_program_dir = PathBuf::from("{test_dir}"); let mut cmd = Command::cargo_bin("nargo").unwrap(); - cmd.env("NARGO_BACKEND_PATH", path_to_mock_backend()); cmd.arg("--program-dir").arg(test_program_dir); cmd.arg("compile").arg("--force"); + cmd.assert().success(); +}} +#[test] +fn compile_success_contract_elaborator_{test_name}() {{ + let test_program_dir = PathBuf::from("{test_dir}"); + + let mut cmd = Command::cargo_bin("nargo").unwrap(); + cmd.arg("--program-dir").arg(test_program_dir); + cmd.arg("compile").arg("--force").arg("--use-elaborator"); + cmd.assert().success(); }} "#, @@ -279,9 +413,18 @@ fn compile_failure_{test_name}() {{ let test_program_dir = PathBuf::from("{test_dir}"); let mut cmd = Command::cargo_bin("nargo").unwrap(); - cmd.env("NARGO_BACKEND_PATH", path_to_mock_backend()); cmd.arg("--program-dir").arg(test_program_dir); - cmd.arg("execute").arg("--force"); + cmd.arg("compile").arg("--force"); + + cmd.assert().failure().stderr(predicate::str::contains("The application panicked (crashed).").not()); +}} +#[test] +fn compile_failure_elaborator_{test_name}() {{ + let test_program_dir = PathBuf::from("{test_dir}"); + + let mut cmd = Command::cargo_bin("nargo").unwrap(); + cmd.arg("--program-dir").arg(test_program_dir); + cmd.arg("compile").arg("--force").arg("--use-elaborator"); cmd.assert().failure().stderr(predicate::str::contains("The application panicked (crashed).").not()); }} diff --git a/tooling/nargo_cli/src/backends.rs b/tooling/nargo_cli/src/backends.rs deleted file mode 100644 index 2b3e9d8861f..00000000000 --- a/tooling/nargo_cli/src/backends.rs +++ /dev/null @@ -1,39 +0,0 @@ -use std::path::PathBuf; - -use backend_interface::backends_directory; -pub(crate) use backend_interface::Backend; - -fn active_backend_file_path() -> PathBuf { - backends_directory().join(".selected_backend") -} - -pub(crate) use backend_interface::ACVM_BACKEND_BARRETENBERG; - -pub(crate) fn clear_active_backend() { - let active_backend_file = active_backend_file_path(); - if active_backend_file.is_file() { - std::fs::remove_file(active_backend_file_path()) - .expect("should delete active backend file"); - } -} - -pub(crate) fn set_active_backend(backend_name: &str) { - let active_backend_file = active_backend_file_path(); - let backends_directory = - active_backend_file.parent().expect("active backend file should have parent"); - - std::fs::create_dir_all(backends_directory).expect("Could not create backends directory"); - std::fs::write(active_backend_file, backend_name.as_bytes()) - .expect("Could not write to active backend file"); -} - -pub(crate) fn get_active_backend() -> String { - let active_backend_file = active_backend_file_path(); - - if !active_backend_file.is_file() { - set_active_backend(ACVM_BACKEND_BARRETENBERG); - return ACVM_BACKEND_BARRETENBERG.to_string(); - } - - std::fs::read_to_string(active_backend_file).expect("Could not read active backend file") -} diff --git a/tooling/nargo_cli/src/cli/backend_cmd/current_cmd.rs b/tooling/nargo_cli/src/cli/backend_cmd/current_cmd.rs deleted file mode 100644 index 5aba00764d3..00000000000 --- a/tooling/nargo_cli/src/cli/backend_cmd/current_cmd.rs +++ /dev/null @@ -1,13 +0,0 @@ -use clap::Args; - -use crate::{backends::get_active_backend, errors::CliError}; - -/// Prints the name of the currently active backend -#[derive(Debug, Clone, Args)] -pub(crate) struct CurrentCommand; - -pub(crate) fn run(_args: CurrentCommand) -> Result<(), CliError> { - println!("{}", get_active_backend()); - - Ok(()) -} diff --git a/tooling/nargo_cli/src/cli/backend_cmd/install_cmd.rs b/tooling/nargo_cli/src/cli/backend_cmd/install_cmd.rs deleted file mode 100644 index 974db9ff7f5..00000000000 --- a/tooling/nargo_cli/src/cli/backend_cmd/install_cmd.rs +++ /dev/null @@ -1,30 +0,0 @@ -use clap::Args; - -use backend_interface::{backends_directory, download_backend}; - -use crate::errors::{BackendError, CliError}; - -use super::ls_cmd::get_available_backends; - -/// Install a new backend from a URL. -#[derive(Debug, Clone, Args)] -pub(crate) struct InstallCommand { - /// The name of the backend to install. - backend: String, - - /// The URL from which to download the backend. - url: String, -} - -pub(crate) fn run(args: InstallCommand) -> Result<(), CliError> { - let installed_backends = get_available_backends(); - - if installed_backends.contains(&args.backend) { - return Err(BackendError::AlreadyInstalled(args.backend).into()); - } - - download_backend(&args.url, &backends_directory().join(args.backend).join("backend_binary")) - .map_err(BackendError::from)?; - - Ok(()) -} diff --git a/tooling/nargo_cli/src/cli/backend_cmd/ls_cmd.rs b/tooling/nargo_cli/src/cli/backend_cmd/ls_cmd.rs deleted file mode 100644 index da37b104d65..00000000000 --- a/tooling/nargo_cli/src/cli/backend_cmd/ls_cmd.rs +++ /dev/null @@ -1,34 +0,0 @@ -use backend_interface::backends_directory; -use clap::Args; - -use crate::errors::CliError; - -/// Prints the list of currently installed backends -#[derive(Debug, Clone, Args)] -pub(crate) struct LsCommand; - -pub(crate) fn run(_args: LsCommand) -> Result<(), CliError> { - for backend in get_available_backends() { - println!("{backend}"); - } - - Ok(()) -} - -pub(super) fn get_available_backends() -> Vec { - let backend_directory_contents = std::fs::read_dir(backends_directory()) - .expect("Could not read backends directory contents"); - - // TODO: Highlight the currently active backend. - backend_directory_contents - .into_iter() - .filter_map(|entry| { - let path = entry.ok()?.path(); - if path.is_dir() { - path.file_name().map(|name| name.to_string_lossy().to_string()) - } else { - None - } - }) - .collect() -} diff --git a/tooling/nargo_cli/src/cli/backend_cmd/mod.rs b/tooling/nargo_cli/src/cli/backend_cmd/mod.rs deleted file mode 100644 index 985dbbdb934..00000000000 --- a/tooling/nargo_cli/src/cli/backend_cmd/mod.rs +++ /dev/null @@ -1,41 +0,0 @@ -use clap::{Args, Subcommand}; - -use crate::errors::CliError; - -mod current_cmd; -mod install_cmd; -mod ls_cmd; -mod uninstall_cmd; -mod use_cmd; - -#[non_exhaustive] -#[derive(Args, Clone, Debug)] -/// Install and select custom backends used to generate and verify proofs. -pub(crate) struct BackendCommand { - #[command(subcommand)] - command: BackendCommands, -} - -#[non_exhaustive] -#[derive(Subcommand, Clone, Debug)] -pub(crate) enum BackendCommands { - Current(current_cmd::CurrentCommand), - Ls(ls_cmd::LsCommand), - Use(use_cmd::UseCommand), - Install(install_cmd::InstallCommand), - Uninstall(uninstall_cmd::UninstallCommand), -} - -pub(crate) fn run(cmd: BackendCommand) -> Result<(), CliError> { - let BackendCommand { command } = cmd; - - match command { - BackendCommands::Current(args) => current_cmd::run(args), - BackendCommands::Ls(args) => ls_cmd::run(args), - BackendCommands::Use(args) => use_cmd::run(args), - BackendCommands::Install(args) => install_cmd::run(args), - BackendCommands::Uninstall(args) => uninstall_cmd::run(args), - }?; - - Ok(()) -} diff --git a/tooling/nargo_cli/src/cli/backend_cmd/uninstall_cmd.rs b/tooling/nargo_cli/src/cli/backend_cmd/uninstall_cmd.rs deleted file mode 100644 index 7497f1bc2f6..00000000000 --- a/tooling/nargo_cli/src/cli/backend_cmd/uninstall_cmd.rs +++ /dev/null @@ -1,59 +0,0 @@ -use clap::Args; - -use backend_interface::backends_directory; - -use crate::{ - backends::{ - clear_active_backend, get_active_backend, set_active_backend, ACVM_BACKEND_BARRETENBERG, - }, - errors::{BackendError, CliError}, -}; - -use super::ls_cmd::get_available_backends; - -/// Uninstalls a backend -#[derive(Debug, Clone, Args)] -pub(crate) struct UninstallCommand { - /// The name of the backend to uninstall. - backend: String, -} - -pub(crate) fn run(args: UninstallCommand) -> Result<(), CliError> { - let installed_backends = get_available_backends(); - - if !installed_backends.contains(&args.backend) { - return Err(BackendError::UnknownBackend(args.backend).into()); - } - - let active_backend = get_active_backend(); - - // Handle the case where we're uninstalling the currently active backend. - if active_backend == args.backend { - let barretenberg_is_installed = - installed_backends.iter().any(|backend_name| backend_name == ACVM_BACKEND_BARRETENBERG); - - let new_active_backend = - if args.backend != ACVM_BACKEND_BARRETENBERG && barretenberg_is_installed { - // Prefer switching to barretenberg if possible. - Some(ACVM_BACKEND_BARRETENBERG) - } else { - // Otherwise pick the first backend which isn't being uninstalled. - installed_backends - .iter() - .find(|&backend_name| backend_name != &args.backend) - .map(|name| name.as_str()) - }; - - if let Some(backend) = new_active_backend { - set_active_backend(backend); - } else { - // We've deleted the last backend. Clear the active backend file to be recreated once we install a new one. - clear_active_backend(); - } - } - - std::fs::remove_dir_all(backends_directory().join(args.backend)) - .expect("backend directory should be deleted"); - - Ok(()) -} diff --git a/tooling/nargo_cli/src/cli/backend_cmd/use_cmd.rs b/tooling/nargo_cli/src/cli/backend_cmd/use_cmd.rs deleted file mode 100644 index 66a129c2148..00000000000 --- a/tooling/nargo_cli/src/cli/backend_cmd/use_cmd.rs +++ /dev/null @@ -1,26 +0,0 @@ -use clap::Args; - -use crate::{ - backends::set_active_backend, - errors::{BackendError, CliError}, -}; - -use super::ls_cmd::get_available_backends; - -/// Select the backend to use -#[derive(Debug, Clone, Args)] -pub(crate) struct UseCommand { - backend: String, -} - -pub(crate) fn run(args: UseCommand) -> Result<(), CliError> { - let backends = get_available_backends(); - - if !backends.contains(&args.backend) { - return Err(BackendError::UnknownBackend(args.backend).into()); - } - - set_active_backend(&args.backend); - - Ok(()) -} diff --git a/tooling/nargo_cli/src/cli/check_cmd.rs b/tooling/nargo_cli/src/cli/check_cmd.rs index 4da06d2536a..e2e1f147b90 100644 --- a/tooling/nargo_cli/src/cli/check_cmd.rs +++ b/tooling/nargo_cli/src/cli/check_cmd.rs @@ -1,12 +1,11 @@ -use crate::backends::Backend; use crate::errors::CliError; use clap::Args; use fm::FileManager; use iter_extended::btree_map; use nargo::{ - errors::CompileError, insert_all_files_for_workspace_into_file_manager, package::Package, - parse_all, prepare_package, + errors::CompileError, insert_all_files_for_workspace_into_file_manager, ops::report_errors, + package::Package, parse_all, prepare_package, }; use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection}; use noirc_abi::{AbiParameter, AbiType, MAIN_RETURN_NAME}; @@ -24,6 +23,7 @@ use super::NargoConfig; /// Checks the constraint system for errors #[derive(Debug, Clone, Args)] +#[clap(visible_alias = "c")] pub(crate) struct CheckCommand { /// The name of the package to check #[clap(long, conflicts_with = "workspace")] @@ -33,15 +33,15 @@ pub(crate) struct CheckCommand { #[clap(long, conflicts_with = "package")] workspace: bool, + /// Force overwrite of existing files + #[clap(long = "overwrite")] + allow_overwrite: bool, + #[clap(flatten)] compile_options: CompileOptions, } -pub(crate) fn run( - _backend: &Backend, - args: CheckCommand, - config: NargoConfig, -) -> Result<(), CliError> { +pub(crate) fn run(args: CheckCommand, config: NargoConfig) -> Result<(), CliError> { let toml_path = get_package_manifest(&config.program_dir)?; let default_selection = if args.workspace { PackageSelection::All } else { PackageSelection::DefaultOrAll }; @@ -57,18 +57,29 @@ pub(crate) fn run( let parsed_files = parse_all(&workspace_file_manager); for package in &workspace { - check_package(&workspace_file_manager, &parsed_files, package, &args.compile_options)?; - println!("[{}] Constraint system successfully built!", package.name); + let any_file_written = check_package( + &workspace_file_manager, + &parsed_files, + package, + &args.compile_options, + args.allow_overwrite, + )?; + if any_file_written { + println!("[{}] Constraint system successfully built!", package.name); + } } Ok(()) } +/// Evaluates the necessity to create or update Prover.toml and Verifier.toml based on the allow_overwrite flag and files' existence. +/// Returns `true` if any file was generated or updated, `false` otherwise. fn check_package( file_manager: &FileManager, parsed_files: &ParsedFiles, package: &Package, compile_options: &CompileOptions, -) -> Result<(), CompileError> { + allow_overwrite: bool, +) -> Result { let (mut context, crate_id) = prepare_package(file_manager, parsed_files, package); check_crate_and_report_errors( &mut context, @@ -76,31 +87,30 @@ fn check_package( compile_options.deny_warnings, compile_options.disable_macros, compile_options.silence_warnings, + compile_options.use_elaborator, )?; if package.is_library() || package.is_contract() { // Libraries do not have ABIs while contracts have many, so we cannot generate a `Prover.toml` file. - Ok(()) + Ok(false) } else { // XXX: We can have a --overwrite flag to determine if you want to overwrite the Prover/Verifier.toml files - if let Some((parameters, return_type)) = compute_function_abi(&context, &crate_id) { + if let Some((parameters, _)) = compute_function_abi(&context, &crate_id) { let path_to_prover_input = package.prover_input_path(); - let path_to_verifier_input = package.verifier_input_path(); - // If they are not available, then create them and populate them based on the ABI - if !path_to_prover_input.exists() { + // Before writing the file, check if it exists and whether overwrite is set + let should_write_prover = !path_to_prover_input.exists() || allow_overwrite; + + if should_write_prover { let prover_toml = create_input_toml_template(parameters.clone(), None); write_to_file(prover_toml.as_bytes(), &path_to_prover_input); + } else { + eprintln!("Note: Prover.toml already exists. Use --overwrite to force overwrite."); } - if !path_to_verifier_input.exists() { - let public_inputs = - parameters.into_iter().filter(|param| param.is_public()).collect(); - let verifier_toml = create_input_toml_template(public_inputs, return_type); - write_to_file(verifier_toml.as_bytes(), &path_to_verifier_input); - } + let any_file_written = should_write_prover; - Ok(()) + Ok(any_file_written) } else { Err(CompileError::MissingMainFunction(package.name.clone())) } @@ -150,14 +160,10 @@ pub(crate) fn check_crate_and_report_errors( deny_warnings: bool, disable_macros: bool, silence_warnings: bool, + use_elaborator: bool, ) -> Result<(), CompileError> { - let result = check_crate(context, crate_id, deny_warnings, disable_macros); - super::compile_cmd::report_errors( - result, - &context.file_manager, - deny_warnings, - silence_warnings, - ) + let result = check_crate(context, crate_id, deny_warnings, disable_macros, use_elaborator); + report_errors(result, &context.file_manager, deny_warnings, silence_warnings) } #[cfg(test)] diff --git a/tooling/nargo_cli/src/cli/codegen_verifier_cmd.rs b/tooling/nargo_cli/src/cli/codegen_verifier_cmd.rs deleted file mode 100644 index 63d27e30836..00000000000 --- a/tooling/nargo_cli/src/cli/codegen_verifier_cmd.rs +++ /dev/null @@ -1,79 +0,0 @@ -use super::fs::{create_named_dir, write_to_file}; -use super::NargoConfig; -use crate::backends::Backend; -use crate::cli::compile_cmd::report_errors; -use crate::errors::CliError; - -use clap::Args; -use nargo::ops::compile_program; -use nargo::{insert_all_files_for_workspace_into_file_manager, parse_all}; -use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection}; -use noirc_driver::{file_manager_with_stdlib, CompileOptions, NOIR_ARTIFACT_VERSION_STRING}; -use noirc_frontend::graph::CrateName; - -/// Generates a Solidity verifier smart contract for the program -#[derive(Debug, Clone, Args)] -pub(crate) struct CodegenVerifierCommand { - /// The name of the package to codegen - #[clap(long, conflicts_with = "workspace")] - package: Option, - - /// Codegen all packages in the workspace - #[clap(long, conflicts_with = "package")] - workspace: bool, - - #[clap(flatten)] - compile_options: CompileOptions, -} - -pub(crate) fn run( - backend: &Backend, - args: CodegenVerifierCommand, - config: NargoConfig, -) -> Result<(), CliError> { - let toml_path = get_package_manifest(&config.program_dir)?; - 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, - Some(NOIR_ARTIFACT_VERSION_STRING.to_string()), - )?; - - let mut workspace_file_manager = file_manager_with_stdlib(&workspace.root_dir); - insert_all_files_for_workspace_into_file_manager(&workspace, &mut workspace_file_manager); - let parsed_files = parse_all(&workspace_file_manager); - - let expression_width = backend.get_backend_info()?; - let binary_packages = workspace.into_iter().filter(|package| package.is_binary()); - for package in binary_packages { - let compilation_result = compile_program( - &workspace_file_manager, - &parsed_files, - package, - &args.compile_options, - None, - ); - - let program = report_errors( - compilation_result, - &workspace_file_manager, - args.compile_options.deny_warnings, - args.compile_options.silence_warnings, - )?; - - let program = nargo::ops::transform_program(program, expression_width); - - let smart_contract_string = backend.eth_contract(&program.circuit)?; - - let contract_dir = workspace.contracts_directory_path(package); - create_named_dir(&contract_dir, "contract"); - let contract_path = contract_dir.join("plonk_vk").with_extension("sol"); - - let path = write_to_file(smart_contract_string.as_bytes(), &contract_path); - println!("[{}] Contract successfully created and located at {path}", package.name); - } - - Ok(()) -} diff --git a/tooling/nargo_cli/src/cli/compile_cmd.rs b/tooling/nargo_cli/src/cli/compile_cmd.rs index 34fb05249b5..ecf2e2e9f53 100644 --- a/tooling/nargo_cli/src/cli/compile_cmd.rs +++ b/tooling/nargo_cli/src/cli/compile_cmd.rs @@ -1,9 +1,10 @@ +use std::io::Write; use std::path::Path; +use std::time::Duration; use fm::FileManager; use nargo::artifacts::program::ProgramArtifact; -use nargo::errors::CompileError; -use nargo::ops::{compile_contract, compile_program}; +use nargo::ops::{collect_errors, compile_contract, compile_program, report_errors}; use nargo::package::Package; use nargo::workspace::Workspace; use nargo::{insert_all_files_for_workspace_into_file_manager, parse_all}; @@ -16,11 +17,11 @@ use noirc_frontend::graph::CrateName; use clap::Args; use noirc_frontend::hir::ParsedFiles; +use notify::{EventKind, RecursiveMode, Watcher}; +use notify_debouncer_full::new_debouncer; -use crate::backends::Backend; use crate::errors::CliError; -use super::fs::program::only_acir; use super::fs::program::{read_program_from_file, save_contract_to_file, save_program_to_file}; use super::NargoConfig; use rayon::prelude::*; @@ -32,19 +33,19 @@ pub(crate) struct CompileCommand { #[clap(long, conflicts_with = "workspace")] package: Option, - /// Compile all packages in the workspace + /// Compile all packages in the workspace. #[clap(long, conflicts_with = "package")] workspace: bool, #[clap(flatten)] compile_options: CompileOptions, + + /// Watch workspace and recompile on changes. + #[clap(long, hide = true)] + watch: bool, } -pub(crate) fn run( - backend: &Backend, - args: CompileCommand, - config: NargoConfig, -) -> Result<(), CliError> { +pub(crate) fn run(args: CompileCommand, config: NargoConfig) -> Result<(), CliError> { let toml_path = get_package_manifest(&config.program_dir)?; let default_selection = if args.workspace { PackageSelection::All } else { PackageSelection::DefaultOrAll }; @@ -55,21 +56,76 @@ pub(crate) fn run( selection, Some(NOIR_ARTIFACT_VERSION_STRING.to_owned()), )?; - let circuit_dir = workspace.target_directory_path(); + if args.watch { + watch_workspace(&workspace, &args.compile_options) + .map_err(|err| CliError::Generic(err.to_string()))?; + } else { + compile_workspace_full(&workspace, &args.compile_options)?; + } + + Ok(()) +} + +fn watch_workspace(workspace: &Workspace, compile_options: &CompileOptions) -> notify::Result<()> { + let (tx, rx) = std::sync::mpsc::channel(); + + // No specific tickrate, max debounce time 1 seconds + let mut debouncer = new_debouncer(Duration::from_secs(1), None, tx)?; + + // Add a path to be watched. All files and directories at that path and + // below will be monitored for changes. + debouncer.watcher().watch(&workspace.root_dir, RecursiveMode::Recursive)?; + + let mut screen = std::io::stdout(); + write!(screen, "{}", termion::cursor::Save).unwrap(); + screen.flush().unwrap(); + let _ = compile_workspace_full(workspace, compile_options); + for res in rx { + let debounced_events = res.map_err(|mut err| err.remove(0))?; + + // We only want to trigger a rebuild if a noir source file has been modified. + let noir_files_modified = debounced_events.iter().any(|event| { + let mut event_paths = event.event.paths.iter(); + let event_affects_noir_file = + event_paths.any(|path| path.extension().map_or(false, |ext| ext == "nr")); + + let is_relevant_event_kind = matches!( + event.kind, + EventKind::Create(_) | EventKind::Modify(_) | EventKind::Remove(_) + ); + + is_relevant_event_kind && event_affects_noir_file + }); + + if noir_files_modified { + write!(screen, "{}{}", termion::cursor::Restore, termion::clear::AfterCursor).unwrap(); + screen.flush().unwrap(); + let _ = compile_workspace_full(workspace, compile_options); + } + } + + screen.flush().unwrap(); + + Ok(()) +} + +pub(super) fn compile_workspace_full( + workspace: &Workspace, + compile_options: &CompileOptions, +) -> Result<(), CliError> { let mut workspace_file_manager = file_manager_with_stdlib(&workspace.root_dir); - insert_all_files_for_workspace_into_file_manager(&workspace, &mut workspace_file_manager); + insert_all_files_for_workspace_into_file_manager(workspace, &mut workspace_file_manager); let parsed_files = parse_all(&workspace_file_manager); - let expression_width = args - .compile_options - .expression_width - .unwrap_or_else(|| backend.get_backend_info_or_default()); - let (compiled_program, compiled_contracts) = compile_workspace( + let compiled_workspace = + compile_workspace(&workspace_file_manager, &parsed_files, workspace, compile_options); + + let (compiled_programs, compiled_contracts) = report_errors( + compiled_workspace, &workspace_file_manager, - &parsed_files, - &workspace, - &args.compile_options, + compile_options.deny_warnings, + compile_options.silence_warnings, )?; let (binary_packages, contract_packages): (Vec<_>, Vec<_>) = workspace @@ -79,13 +135,13 @@ pub(crate) fn run( .partition(|package| package.is_binary()); // Save build artifacts to disk. - let only_acir = args.compile_options.only_acir; - for (package, program) in binary_packages.into_iter().zip(compiled_program) { - let program = nargo::ops::transform_program(program, expression_width); - save_program(program.clone(), &package, &workspace.target_directory_path(), only_acir); + for (package, program) in binary_packages.into_iter().zip(compiled_programs) { + let program = nargo::ops::transform_program(program, compile_options.expression_width); + save_program(program.clone(), &package, &workspace.target_directory_path()); } + let circuit_dir = workspace.target_directory_path(); for (package, contract) in contract_packages.into_iter().zip(compiled_contracts) { - let contract = nargo::ops::transform_contract(contract, expression_width); + let contract = nargo::ops::transform_contract(contract, compile_options.expression_width); save_contract(contract, &package, &circuit_dir); } @@ -97,7 +153,7 @@ pub(super) fn compile_workspace( parsed_files: &ParsedFiles, workspace: &Workspace, compile_options: &CompileOptions, -) -> Result<(Vec, Vec), CliError> { +) -> CompilationResult<(Vec, Vec)> { let (binary_packages, contract_packages): (Vec<_>, Vec<_>) = workspace .into_iter() .filter(|package| !package.is_library()) @@ -123,45 +179,25 @@ pub(super) fn compile_workspace( .map(|package| compile_contract(file_manager, parsed_files, package, compile_options)) .collect(); - // Report any warnings/errors which were encountered during compilation. - let compiled_programs: Vec = program_results - .into_iter() - .map(|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(|compilation_result| { - report_errors( - compilation_result, - file_manager, - compile_options.deny_warnings, - compile_options.silence_warnings, - ) - }) - .collect::>()?; - - Ok((compiled_programs, compiled_contracts)) + // Collate any warnings/errors which were encountered during compilation. + let compiled_programs = collect_errors(program_results); + let compiled_contracts = collect_errors(contract_results); + + match (compiled_programs, compiled_contracts) { + (Ok((programs, program_warnings)), Ok((contracts, contract_warnings))) => { + let warnings = [program_warnings, contract_warnings].concat(); + Ok(((programs, contracts), warnings)) + } + (Err(program_errors), Err(contract_errors)) => { + Err([program_errors, contract_errors].concat()) + } + (Err(errors), _) | (_, Err(errors)) => Err(errors), + } } -pub(super) fn save_program( - program: CompiledProgram, - package: &Package, - circuit_dir: &Path, - only_acir_opt: bool, -) { +pub(super) fn save_program(program: CompiledProgram, package: &Package, circuit_dir: &Path) { let program_artifact = ProgramArtifact::from(program.clone()); - if only_acir_opt { - only_acir(&program_artifact, circuit_dir); - } else { - save_program_to_file(&program_artifact, &package.name, circuit_dir); - } + save_program_to_file(&program_artifact, &package.name, circuit_dir); } fn save_contract(contract: CompiledContract, package: &Package, circuit_dir: &Path) { @@ -172,30 +208,3 @@ fn save_contract(contract: CompiledContract, package: &Package, circuit_dir: &Pa circuit_dir, ); } - -/// Helper function for reporting any errors in a `CompilationResult` -/// structure that is commonly used as a return result in this file. -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_cli/src/cli/dap_cmd.rs b/tooling/nargo_cli/src/cli/dap_cmd.rs index ba4f91609ef..a84e961cfe7 100644 --- a/tooling/nargo_cli/src/cli/dap_cmd.rs +++ b/tooling/nargo_cli/src/cli/dap_cmd.rs @@ -1,6 +1,7 @@ use acvm::acir::circuit::ExpressionWidth; use acvm::acir::native_types::WitnessMap; -use backend_interface::Backend; +use acvm::FieldElement; +use bn254_blackbox_solver::Bn254BlackBoxSolver; use clap::Args; use nargo::constants::PROVER_INPUT_FILE; use nargo::workspace::Workspace; @@ -29,8 +30,8 @@ use noir_debugger::errors::{DapError, LoadError}; #[derive(Debug, Clone, Args)] pub(crate) struct DapCommand { /// Override the expression width requested by the backend. - #[arg(long, value_parser = parse_expression_width)] - expression_width: Option, + #[arg(long, value_parser = parse_expression_width, default_value = "4")] + expression_width: ExpressionWidth, #[clap(long)] preflight_check: bool, @@ -101,7 +102,7 @@ fn load_and_compile_project( expression_width: ExpressionWidth, acir_mode: bool, skip_instrumentation: bool, -) -> Result<(CompiledProgram, WitnessMap), LoadError> { +) -> Result<(CompiledProgram, WitnessMap), LoadError> { let workspace = find_workspace(project_folder, package) .ok_or(LoadError::Generic(workspace_not_found_error_msg(project_folder, package)))?; let package = workspace @@ -194,11 +195,9 @@ fn loop_uninitialized_dap( Ok((compiled_program, initial_witness)) => { server.respond(req.ack()?)?; - let blackbox_solver = bn254_blackbox_solver::Bn254BlackBoxSolver::new(); - noir_debugger::run_dap_loop( server, - &blackbox_solver, + &Bn254BlackBoxSolver, compiled_program, initial_witness, )?; @@ -249,14 +248,7 @@ fn run_preflight_check( Ok(()) } -pub(crate) fn run( - backend: &Backend, - args: DapCommand, - _config: NargoConfig, -) -> Result<(), CliError> { - let expression_width = - args.expression_width.unwrap_or_else(|| backend.get_backend_info_or_default()); - +pub(crate) fn run(args: DapCommand, _config: NargoConfig) -> Result<(), CliError> { // When the --preflight-check flag is present, we run Noir's DAP server in "pre-flight mode", which test runs // the DAP initialization code without actually starting the DAP server. // @@ -270,12 +262,12 @@ pub(crate) fn run( // the DAP loop is established, which otherwise are considered "out of band" by the maintainers of the DAP spec. // More details here: https://github.com/microsoft/vscode/issues/108138 if args.preflight_check { - return run_preflight_check(expression_width, args).map_err(CliError::DapError); + return run_preflight_check(args.expression_width, args).map_err(CliError::DapError); } let output = BufWriter::new(std::io::stdout()); let input = BufReader::new(std::io::stdin()); let server = Server::new(input, output); - loop_uninitialized_dap(server, expression_width).map_err(CliError::DapError) + loop_uninitialized_dap(server, args.expression_width).map_err(CliError::DapError) } diff --git a/tooling/nargo_cli/src/cli/debug_cmd.rs b/tooling/nargo_cli/src/cli/debug_cmd.rs index 130a07b5c90..ebcd9ff6569 100644 --- a/tooling/nargo_cli/src/cli/debug_cmd.rs +++ b/tooling/nargo_cli/src/cli/debug_cmd.rs @@ -1,6 +1,7 @@ use std::path::PathBuf; -use acvm::acir::native_types::WitnessMap; +use acvm::acir::native_types::{WitnessMap, WitnessStack}; +use acvm::FieldElement; use bn254_blackbox_solver::Bn254BlackBoxSolver; use clap::Args; @@ -8,7 +9,7 @@ use fm::FileManager; use nargo::artifacts::debug::DebugArtifact; use nargo::constants::PROVER_INPUT_FILE; use nargo::errors::CompileError; -use nargo::ops::{compile_program, compile_program_with_debug_instrumenter}; +use nargo::ops::{compile_program, compile_program_with_debug_instrumenter, report_errors}; use nargo::package::Package; use nargo::workspace::Workspace; use nargo::{insert_all_files_for_workspace_into_file_manager, parse_all}; @@ -22,10 +23,8 @@ use noirc_frontend::debug::DebugInstrumenter; use noirc_frontend::graph::CrateName; use noirc_frontend::hir::ParsedFiles; -use super::compile_cmd::report_errors; use super::fs::{inputs::read_inputs_from_file, witness::save_witness_to_dir}; use super::NargoConfig; -use crate::backends::Backend; use crate::errors::CliError; /// Executes a circuit in debug mode @@ -54,11 +53,7 @@ pub(crate) struct DebugCommand { skip_instrumentation: Option, } -pub(crate) fn run( - backend: &Backend, - args: DebugCommand, - config: NargoConfig, -) -> Result<(), CliError> { +pub(crate) fn run(args: DebugCommand, config: NargoConfig) -> Result<(), CliError> { let acir_mode = args.acir_mode; let skip_instrumentation = args.skip_instrumentation.unwrap_or(acir_mode); @@ -70,10 +65,6 @@ pub(crate) fn run( Some(NOIR_ARTIFACT_VERSION_STRING.to_string()), )?; let target_dir = &workspace.target_directory_path(); - let expression_width = args - .compile_options - .expression_width - .unwrap_or_else(|| backend.get_backend_info_or_default()); let Some(package) = workspace.into_iter().find(|p| p.is_binary()) else { println!( @@ -90,7 +81,8 @@ pub(crate) fn run( args.compile_options.clone(), )?; - let compiled_program = nargo::ops::transform_program(compiled_program, expression_width); + let compiled_program = + nargo::ops::transform_program(compiled_program, args.compile_options.expression_width); run_async(package, compiled_program, &args.prover_name, &args.witness_name, target_dir) } @@ -188,7 +180,11 @@ fn run_async( } if let Some(witness_name) = witness_name { - let witness_path = save_witness_to_dir(solved_witness, witness_name, target_dir)?; + let witness_path = save_witness_to_dir( + WitnessStack::from(solved_witness), + witness_name, + target_dir, + )?; println!("[{}] Witness saved to {}", package.name, witness_path.display()); } @@ -204,7 +200,7 @@ fn debug_program_and_decode( program: CompiledProgram, package: &Package, prover_name: &str, -) -> Result<(Option, Option), CliError> { +) -> Result<(Option, Option>), CliError> { // Parse the initial witness values from Prover.toml let (inputs_map, _) = read_inputs_from_file(&package.root_dir, prover_name, Format::Toml, &program.abi)?; @@ -223,22 +219,20 @@ fn debug_program_and_decode( pub(crate) fn debug_program( compiled_program: &CompiledProgram, inputs_map: &InputMap, -) -> Result, CliError> { - let blackbox_solver = Bn254BlackBoxSolver::new(); - +) -> Result>, CliError> { let initial_witness = compiled_program.abi.encode(inputs_map, None)?; let debug_artifact = DebugArtifact { - debug_symbols: vec![compiled_program.debug.clone()], + debug_symbols: compiled_program.debug.clone(), file_map: compiled_program.file_map.clone(), - warnings: compiled_program.warnings.clone(), }; noir_debugger::debug_circuit( - &blackbox_solver, - &compiled_program.circuit, + &Bn254BlackBoxSolver, + &compiled_program.program.functions[0], debug_artifact, initial_witness, + &compiled_program.program.unconstrained_functions, ) .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 a3fcebab94f..5d6754b29f7 100644 --- a/tooling/nargo_cli/src/cli/execute_cmd.rs +++ b/tooling/nargo_cli/src/cli/execute_cmd.rs @@ -1,29 +1,28 @@ -use acvm::acir::native_types::WitnessMap; +use acvm::acir::native_types::WitnessStack; +use acvm::FieldElement; use bn254_blackbox_solver::Bn254BlackBoxSolver; 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::{compile_program, DefaultForeignCallExecutor}; +use nargo::ops::DefaultForeignCallExecutor; use nargo::package::Package; -use nargo::{insert_all_files_for_workspace_into_file_manager, parse_all}; 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::{ - file_manager_with_stdlib, CompileOptions, CompiledProgram, NOIR_ARTIFACT_VERSION_STRING, -}; +use noirc_driver::{CompileOptions, CompiledProgram, NOIR_ARTIFACT_VERSION_STRING}; use noirc_frontend::graph::CrateName; +use super::compile_cmd::compile_workspace_full; use super::fs::{inputs::read_inputs_from_file, witness::save_witness_to_dir}; use super::NargoConfig; -use crate::backends::Backend; -use crate::cli::compile_cmd::report_errors; +use crate::cli::fs::program::read_program_from_file; use crate::errors::CliError; /// Executes a circuit to calculate its return value #[derive(Debug, Clone, Args)] +#[clap(visible_alias = "e")] pub(crate) struct ExecuteCommand { /// Write the execution witness to named file witness_name: Option, @@ -48,11 +47,7 @@ pub(crate) struct ExecuteCommand { oracle_resolver: Option, } -pub(crate) fn run( - backend: &Backend, - args: ExecuteCommand, - config: NargoConfig, -) -> Result<(), CliError> { +pub(crate) fn run(args: ExecuteCommand, config: NargoConfig) -> Result<(), CliError> { let toml_path = get_package_manifest(&config.program_dir)?; let default_selection = if args.workspace { PackageSelection::All } else { PackageSelection::DefaultOrAll }; @@ -64,35 +59,16 @@ pub(crate) fn run( )?; let target_dir = &workspace.target_directory_path(); - let mut workspace_file_manager = file_manager_with_stdlib(&workspace.root_dir); - insert_all_files_for_workspace_into_file_manager(&workspace, &mut workspace_file_manager); - let parsed_files = parse_all(&workspace_file_manager); + // Compile the full workspace in order to generate any build artifacts. + compile_workspace_full(&workspace, &args.compile_options)?; - let expression_width = args - .compile_options - .expression_width - .unwrap_or_else(|| backend.get_backend_info_or_default()); let binary_packages = workspace.into_iter().filter(|package| package.is_binary()); for package in binary_packages { - let compilation_result = compile_program( - &workspace_file_manager, - &parsed_files, - package, - &args.compile_options, - None, - ); - - let compiled_program = report_errors( - compilation_result, - &workspace_file_manager, - args.compile_options.deny_warnings, - args.compile_options.silence_warnings, - )?; + let program_artifact_path = workspace.package_build_path(package); + let program: CompiledProgram = read_program_from_file(program_artifact_path)?.into(); - let compiled_program = nargo::ops::transform_program(compiled_program, expression_width); - - let (return_value, solved_witness) = execute_program_and_decode( - compiled_program, + let (return_value, witness_stack) = execute_program_and_decode( + program, package, &args.prover_name, args.oracle_resolver.as_deref(), @@ -103,7 +79,7 @@ pub(crate) fn run( println!("[{}] Circuit output: {return_value:?}", package.name); } if let Some(witness_name) = &args.witness_name { - let witness_path = save_witness_to_dir(solved_witness, witness_name, target_dir)?; + let witness_path = save_witness_to_dir(witness_stack, witness_name, target_dir)?; println!("[{}] Witness saved to {}", package.name, witness_path.display()); } @@ -116,42 +92,44 @@ fn execute_program_and_decode( package: &Package, prover_name: &str, foreign_call_resolver_url: Option<&str>, -) -> Result<(Option, WitnessMap), CliError> { +) -> Result<(Option, WitnessStack), CliError> { // Parse the initial witness values from Prover.toml let (inputs_map, _) = read_inputs_from_file(&package.root_dir, prover_name, Format::Toml, &program.abi)?; - let solved_witness = execute_program(&program, &inputs_map, foreign_call_resolver_url)?; + let witness_stack = execute_program(&program, &inputs_map, foreign_call_resolver_url)?; let public_abi = program.abi.public_abi(); - let (_, return_value) = public_abi.decode(&solved_witness)?; + // Get the entry point witness for the ABI + let main_witness = + &witness_stack.peek().expect("Should have at least one witness on the stack").witness; + let (_, return_value) = public_abi.decode(main_witness)?; - Ok((return_value, solved_witness)) + Ok((return_value, witness_stack)) } pub(crate) fn execute_program( compiled_program: &CompiledProgram, inputs_map: &InputMap, foreign_call_resolver_url: Option<&str>, -) -> Result { - let blackbox_solver = Bn254BlackBoxSolver::new(); - +) -> Result, CliError> { let initial_witness = compiled_program.abi.encode(inputs_map, None)?; - let solved_witness_err = nargo::ops::execute_circuit( - &compiled_program.circuit, + let solved_witness_stack_err = nargo::ops::execute_program( + &compiled_program.program, initial_witness, - &blackbox_solver, + &Bn254BlackBoxSolver, &mut DefaultForeignCallExecutor::new(true, foreign_call_resolver_url), ); - match solved_witness_err { - Ok(solved_witness) => Ok(solved_witness), + match solved_witness_stack_err { + Ok(solved_witness_stack) => Ok(solved_witness_stack), Err(err) => { let debug_artifact = DebugArtifact { - debug_symbols: vec![compiled_program.debug.clone()], + debug_symbols: 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) { + if let Some(diagnostic) = + try_to_diagnose_runtime_error(&err, &compiled_program.abi, &compiled_program.debug) + { diagnostic.report(&debug_artifact, false); } diff --git a/tooling/nargo_cli/src/cli/export_cmd.rs b/tooling/nargo_cli/src/cli/export_cmd.rs index 96b24796a2b..324eed340ad 100644 --- a/tooling/nargo_cli/src/cli/export_cmd.rs +++ b/tooling/nargo_cli/src/cli/export_cmd.rs @@ -1,4 +1,5 @@ use nargo::errors::CompileError; +use nargo::ops::report_errors; use noirc_errors::FileDiagnostic; use noirc_frontend::hir::ParsedFiles; use rayon::prelude::*; @@ -19,12 +20,10 @@ use noirc_frontend::graph::CrateName; use clap::Args; -use crate::backends::Backend; use crate::errors::CliError; use super::check_cmd::check_crate_and_report_errors; -use super::compile_cmd::report_errors; use super::fs::program::save_program_to_file; use super::NargoConfig; @@ -43,11 +42,7 @@ pub(crate) struct ExportCommand { compile_options: CompileOptions, } -pub(crate) fn run( - _backend: &Backend, - args: ExportCommand, - config: NargoConfig, -) -> Result<(), CliError> { +pub(crate) fn run(args: ExportCommand, config: NargoConfig) -> Result<(), CliError> { let toml_path = get_package_manifest(&config.program_dir)?; let default_selection = if args.workspace { PackageSelection::All } else { PackageSelection::DefaultOrAll }; @@ -94,6 +89,7 @@ fn compile_exported_functions( compile_options.deny_warnings, compile_options.disable_macros, compile_options.silence_warnings, + compile_options.use_elaborator, )?; let exported_functions = context.get_all_exported_functions_in_crate(&crate_id); diff --git a/tooling/nargo_cli/src/cli/fmt_cmd.rs b/tooling/nargo_cli/src/cli/fmt_cmd.rs index 0bd25a3a0ce..8f66a0a328f 100644 --- a/tooling/nargo_cli/src/cli/fmt_cmd.rs +++ b/tooling/nargo_cli/src/cli/fmt_cmd.rs @@ -1,7 +1,7 @@ use std::{fs::DirEntry, path::Path}; use clap::Args; -use nargo::insert_all_files_for_workspace_into_file_manager; +use nargo::{insert_all_files_for_workspace_into_file_manager, ops::report_errors}; use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection}; use noirc_driver::{file_manager_with_stdlib, NOIR_ARTIFACT_VERSION_STRING}; use noirc_errors::CustomDiagnostic; @@ -48,12 +48,12 @@ pub(crate) fn run(args: FormatCommand, config: NargoConfig) -> Result<(), CliErr let errors = errors .into_iter() .map(|error| { - let error: CustomDiagnostic = error.into(); + let error = CustomDiagnostic::from(&error); error.in_file(file_id) }) .collect(); - let _ = super::compile_cmd::report_errors::<()>( + let _ = report_errors::<()>( Err(errors), &workspace_file_manager, false, diff --git a/tooling/nargo_cli/src/cli/fs/inputs.rs b/tooling/nargo_cli/src/cli/fs/inputs.rs index 023195010ac..dee9a00507c 100644 --- a/tooling/nargo_cli/src/cli/fs/inputs.rs +++ b/tooling/nargo_cli/src/cli/fs/inputs.rs @@ -6,8 +6,6 @@ use std::{collections::BTreeMap, path::Path}; use crate::errors::FilesystemError; -use super::write_to_file; - /// Returns the circuit's parameters and its return value, if one exists. /// # Examples /// @@ -36,98 +34,3 @@ pub(crate) fn read_inputs_from_file>( Ok((input_map, return_value)) } - -pub(crate) fn write_inputs_to_file>( - input_map: &InputMap, - return_value: &Option, - abi: &Abi, - path: P, - file_name: &str, - format: Format, -) -> Result<(), FilesystemError> { - let file_path = path.as_ref().join(file_name).with_extension(format.ext()); - - // We must insert the return value into the `InputMap` in order for it to be written to file. - let serialized_output = match return_value { - // Parameters and return values are kept separate except for when they're being written to file. - // As a result, we don't want to modify the original map and must clone it before insertion. - Some(return_value) => { - let mut input_map = input_map.clone(); - input_map.insert(MAIN_RETURN_NAME.to_owned(), return_value.clone()); - format.serialize(&input_map, abi)? - } - // If no return value exists, then we can serialize the original map directly. - None => format.serialize(input_map, abi)?, - }; - - write_to_file(serialized_output.as_bytes(), &file_path); - - Ok(()) -} - -#[cfg(test)] -mod tests { - use std::{collections::BTreeMap, vec}; - - use acvm::FieldElement; - use nargo::constants::VERIFIER_INPUT_FILE; - use noirc_abi::{ - input_parser::{Format, InputValue}, - Abi, AbiParameter, AbiReturnType, AbiType, AbiVisibility, - }; - use tempfile::TempDir; - - use super::{read_inputs_from_file, write_inputs_to_file}; - - #[test] - fn write_and_read_recovers_inputs_and_return_value() { - let input_dir = TempDir::new().unwrap().into_path(); - - // We purposefully test a simple ABI here as we're focussing on `fs`. - // Tests for serializing complex types should exist in `noirc_abi`. - let abi = Abi { - parameters: vec![ - AbiParameter { - name: "foo".into(), - typ: AbiType::Field, - visibility: AbiVisibility::Public, - }, - AbiParameter { - name: "bar".into(), - typ: AbiType::String { length: 11 }, - visibility: AbiVisibility::Private, - }, - ], - return_type: Some(AbiReturnType { - abi_type: AbiType::Field, - visibility: AbiVisibility::Public, - }), - - // Input serialization is only dependent on types, not position in witness map. - // Neither of these should be relevant so we leave them empty. - param_witnesses: BTreeMap::new(), - return_witnesses: Vec::new(), - }; - let input_map = BTreeMap::from([ - ("foo".to_owned(), InputValue::Field(42u128.into())), - ("bar".to_owned(), InputValue::String("hello world".to_owned())), - ]); - let return_value = Some(InputValue::Field(FieldElement::zero())); - - write_inputs_to_file( - &input_map, - &return_value, - &abi, - &input_dir, - VERIFIER_INPUT_FILE, - Format::Toml, - ) - .unwrap(); - - let (loaded_inputs, loaded_return_value) = - read_inputs_from_file(input_dir, VERIFIER_INPUT_FILE, Format::Toml, &abi).unwrap(); - - assert_eq!(loaded_inputs, input_map); - assert_eq!(loaded_return_value, return_value); - } -} diff --git a/tooling/nargo_cli/src/cli/fs/mod.rs b/tooling/nargo_cli/src/cli/fs/mod.rs index 4ebce3b3325..8658bd5b248 100644 --- a/tooling/nargo_cli/src/cli/fs/mod.rs +++ b/tooling/nargo_cli/src/cli/fs/mod.rs @@ -4,11 +4,8 @@ use std::{ path::{Path, PathBuf}, }; -use crate::errors::FilesystemError; - pub(super) mod inputs; pub(super) mod program; -pub(super) mod proof; pub(super) mod witness; pub(super) fn create_named_dir(named_dir: &Path, name: &str) -> PathBuf { @@ -31,12 +28,3 @@ pub(super) fn write_to_file(bytes: &[u8], path: &Path) -> String { Ok(_) => display.to_string(), } } - -pub(super) fn load_hex_data>(path: P) -> Result, FilesystemError> { - let hex_data: Vec<_> = std::fs::read(&path) - .map_err(|_| FilesystemError::PathNotValid(path.as_ref().to_path_buf()))?; - - let raw_bytes = hex::decode(hex_data).map_err(FilesystemError::HexArtifactNotValid)?; - - Ok(raw_bytes) -} diff --git a/tooling/nargo_cli/src/cli/fs/program.rs b/tooling/nargo_cli/src/cli/fs/program.rs index 1fb57ae6685..ba017651667 100644 --- a/tooling/nargo_cli/src/cli/fs/program.rs +++ b/tooling/nargo_cli/src/cli/fs/program.rs @@ -1,6 +1,5 @@ use std::path::{Path, PathBuf}; -use acvm::acir::circuit::Circuit; use nargo::artifacts::{contract::ContractArtifact, program::ProgramArtifact}; use noirc_frontend::graph::CrateName; @@ -17,19 +16,6 @@ pub(crate) fn save_program_to_file>( save_build_artifact_to_file(program_artifact, &circuit_name, circuit_dir) } -/// Writes the bytecode as acir.gz -pub(crate) fn only_acir>( - program_artifact: &ProgramArtifact, - circuit_dir: P, -) -> PathBuf { - create_named_dir(circuit_dir.as_ref(), "target"); - let circuit_path = circuit_dir.as_ref().join("acir").with_extension("gz"); - let bytes = Circuit::serialize_circuit(&program_artifact.bytecode); - write_to_file(&bytes, &circuit_path); - - circuit_path -} - pub(crate) fn save_contract_to_file>( compiled_contract: &ContractArtifact, circuit_name: &str, diff --git a/tooling/nargo_cli/src/cli/fs/proof.rs b/tooling/nargo_cli/src/cli/fs/proof.rs deleted file mode 100644 index d2b3050708b..00000000000 --- a/tooling/nargo_cli/src/cli/fs/proof.rs +++ /dev/null @@ -1,20 +0,0 @@ -use std::path::{Path, PathBuf}; - -use nargo::constants::PROOF_EXT; - -use crate::errors::FilesystemError; - -use super::{create_named_dir, write_to_file}; - -pub(crate) fn save_proof_to_dir>( - proof: &[u8], - proof_name: &str, - proof_dir: P, -) -> Result { - create_named_dir(proof_dir.as_ref(), "proof"); - let proof_path = proof_dir.as_ref().join(proof_name).with_extension(PROOF_EXT); - - write_to_file(hex::encode(proof).as_bytes(), &proof_path); - - Ok(proof_path) -} diff --git a/tooling/nargo_cli/src/cli/fs/witness.rs b/tooling/nargo_cli/src/cli/fs/witness.rs index 1a2cf88f4a1..f95eb3d7a4c 100644 --- a/tooling/nargo_cli/src/cli/fs/witness.rs +++ b/tooling/nargo_cli/src/cli/fs/witness.rs @@ -1,20 +1,20 @@ use std::path::{Path, PathBuf}; -use acvm::acir::native_types::WitnessMap; +use acvm::{acir::native_types::WitnessStack, FieldElement}; use nargo::constants::WITNESS_EXT; use super::{create_named_dir, write_to_file}; use crate::errors::FilesystemError; pub(crate) fn save_witness_to_dir>( - witnesses: WitnessMap, + witness_stack: WitnessStack, witness_name: &str, witness_dir: P, ) -> Result { create_named_dir(witness_dir.as_ref(), "witness"); let witness_path = witness_dir.as_ref().join(witness_name).with_extension(WITNESS_EXT); - let buf: Vec = witnesses.try_into()?; + let buf: Vec = witness_stack.try_into()?; write_to_file(buf.as_slice(), &witness_path); diff --git a/tooling/nargo_cli/src/cli/info_cmd.rs b/tooling/nargo_cli/src/cli/info_cmd.rs index ef0df0bf25b..7c50e907dc9 100644 --- a/tooling/nargo_cli/src/cli/info_cmd.rs +++ b/tooling/nargo_cli/src/cli/info_cmd.rs @@ -1,35 +1,33 @@ use std::collections::HashMap; use acvm::acir::circuit::ExpressionWidth; -use backend_interface::BackendError; use clap::Args; use iter_extended::vecmap; use nargo::{ - artifacts::debug::DebugArtifact, insert_all_files_for_workspace_into_file_manager, - package::Package, parse_all, + artifacts::{debug::DebugArtifact, program::ProgramArtifact}, + package::Package, }; use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection}; -use noirc_driver::{ - file_manager_with_stdlib, CompileOptions, CompiledContract, CompiledProgram, - NOIR_ARTIFACT_VERSION_STRING, -}; +use noirc_driver::{CompileOptions, NOIR_ARTIFACT_VERSION_STRING}; use noirc_errors::{debug_info::OpCodesCount, Location}; use noirc_frontend::graph::CrateName; use prettytable::{row, table, Row}; use rayon::prelude::*; use serde::Serialize; -use crate::backends::Backend; use crate::errors::CliError; -use super::{compile_cmd::compile_workspace, NargoConfig}; +use super::{ + compile_cmd::compile_workspace_full, fs::program::read_program_from_file, NargoConfig, +}; -/// Provides detailed information on a circuit +/// Provides detailed information on each of a program's function (represented by a single circuit) /// -/// Current information provided: +/// Current information provided per circuit: /// 1. The number of ACIR opcodes /// 2. Counts the final number gates in the circuit used by a backend #[derive(Debug, Clone, Args)] +#[clap(visible_alias = "i")] pub(crate) struct InfoCommand { /// The name of the package to detail #[clap(long, conflicts_with = "workspace")] @@ -50,11 +48,7 @@ pub(crate) struct InfoCommand { compile_options: CompileOptions, } -pub(crate) fn run( - backend: &Backend, - args: InfoCommand, - config: NargoConfig, -) -> Result<(), CliError> { +pub(crate) fn run(args: InfoCommand, config: NargoConfig) -> Result<(), CliError> { let toml_path = get_package_manifest(&config.program_dir)?; let default_selection = if args.workspace { PackageSelection::All } else { PackageSelection::DefaultOrAll }; @@ -65,60 +59,42 @@ pub(crate) fn run( Some(NOIR_ARTIFACT_VERSION_STRING.to_string()), )?; - let mut workspace_file_manager = file_manager_with_stdlib(&workspace.root_dir); - insert_all_files_for_workspace_into_file_manager(&workspace, &mut workspace_file_manager); - let parsed_files = parse_all(&workspace_file_manager); - - let expression_width = args - .compile_options - .expression_width - .unwrap_or_else(|| backend.get_backend_info_or_default()); - let (compiled_programs, compiled_contracts) = compile_workspace( - &workspace_file_manager, - &parsed_files, - &workspace, - &args.compile_options, - )?; + // Compile the full workspace in order to generate any build artifacts. + compile_workspace_full(&workspace, &args.compile_options)?; - let compiled_programs = vecmap(compiled_programs, |program| { - nargo::ops::transform_program(program, expression_width) - }); - let compiled_contracts = vecmap(compiled_contracts, |contract| { - nargo::ops::transform_contract(contract, expression_width) - }); + let binary_packages: Vec<(Package, ProgramArtifact)> = workspace + .into_iter() + .filter(|package| package.is_binary()) + .map(|package| -> Result<(Package, ProgramArtifact), CliError> { + let program_artifact_path = workspace.package_build_path(package); + let program = read_program_from_file(program_artifact_path)?; + Ok((package.clone(), program)) + }) + .collect::>()?; if args.profile_info { - for compiled_program in &compiled_programs { - let span_opcodes = compiled_program.debug.count_span_opcodes(); + for (_, compiled_program) in &binary_packages { let debug_artifact = DebugArtifact::from(compiled_program.clone()); - print_span_opcodes(span_opcodes, &debug_artifact); - } - - for compiled_contract in &compiled_contracts { - let debug_artifact = DebugArtifact::from(compiled_contract.clone()); - let functions = &compiled_contract.functions; - for contract_function in functions { - let span_opcodes = contract_function.debug.count_span_opcodes(); + for function_debug in compiled_program.debug_symbols.debug_infos.iter() { + let span_opcodes = function_debug.count_span_opcodes(); print_span_opcodes(span_opcodes, &debug_artifact); } } } - let binary_packages = - workspace.into_iter().filter(|package| package.is_binary()).zip(compiled_programs); let program_info = binary_packages + .into_iter() .par_bridge() .map(|(package, program)| { - count_opcodes_and_gates_in_program(backend, program, package, expression_width) + count_opcodes_and_gates_in_program( + program, + &package, + args.compile_options.expression_width, + ) }) - .collect::>()?; + .collect(); - let contract_info = compiled_contracts - .into_par_iter() - .map(|contract| count_opcodes_and_gates_in_contract(backend, contract, expression_width)) - .collect::>()?; - - let info_report = InfoReport { programs: program_info, contracts: contract_info }; + let info_report = InfoReport { programs: program_info }; if args.json { // Expose machine-readable JSON data. @@ -126,29 +102,16 @@ pub(crate) fn run( } else { // Otherwise print human-readable table. if !info_report.programs.is_empty() { - let mut program_table = table!([Fm->"Package", Fm->"Expression Width", Fm->"ACIR Opcodes", Fm->"Backend Circuit Size"]); + let mut program_table = + table!([Fm->"Package", Fm->"Function", Fm->"Expression Width", Fm->"ACIR Opcodes"]); - for program in info_report.programs { - program_table.add_row(program.into()); - } - program_table.printstd(); - } - if !info_report.contracts.is_empty() { - let mut contract_table = table!([ - Fm->"Contract", - Fm->"Function", - Fm->"Expression Width", - Fm->"ACIR Opcodes", - Fm->"Backend Circuit Size" - ]); - for contract_info in info_report.contracts { - let contract_rows: Vec = contract_info.into(); - for row in contract_rows { - contract_table.add_row(row); + for program_info in info_report.programs { + let program_rows: Vec = program_info.into(); + for row in program_rows { + program_table.add_row(row); } } - - contract_table.printstd(); + program_table.printstd(); } } @@ -207,26 +170,26 @@ fn byte_index(string: &str, index: u32) -> usize { #[derive(Debug, Default, Serialize)] struct InfoReport { programs: Vec, - contracts: Vec, } #[derive(Debug, Serialize)] struct ProgramInfo { - name: String, + package_name: String, #[serde(skip)] expression_width: ExpressionWidth, - acir_opcodes: usize, - circuit_size: u32, + functions: Vec, } -impl From for Row { +impl From for Vec { fn from(program_info: ProgramInfo) -> Self { - row![ - Fm->format!("{}", program_info.name), - format!("{:?}", program_info.expression_width), - Fc->format!("{}", program_info.acir_opcodes), - Fc->format!("{}", program_info.circuit_size), - ] + vecmap(program_info.functions, |function| { + row![ + Fm->format!("{}", program_info.package_name), + Fc->format!("{}", function.name), + format!("{:?}", program_info.expression_width), + Fc->format!("{}", function.acir_opcodes), + ] + }) } } @@ -235,6 +198,7 @@ struct ContractInfo { name: String, #[serde(skip)] expression_width: ExpressionWidth, + // TODO(https://github.com/noir-lang/noir/issues/4720): Settle on how to display contract functions with non-inlined Acir calls functions: Vec, } @@ -242,7 +206,6 @@ struct ContractInfo { struct FunctionInfo { name: String, acir_opcodes: usize, - circuit_size: u32, } impl From for Vec { @@ -253,42 +216,26 @@ impl From for Vec { Fc->format!("{}", function.name), format!("{:?}", contract_info.expression_width), Fc->format!("{}", function.acir_opcodes), - Fc->format!("{}", function.circuit_size), ] }) } } fn count_opcodes_and_gates_in_program( - backend: &Backend, - compiled_program: CompiledProgram, + compiled_program: ProgramArtifact, package: &Package, expression_width: ExpressionWidth, -) -> Result { - Ok(ProgramInfo { - name: package.name.to_string(), - expression_width, - acir_opcodes: compiled_program.circuit.opcodes.len(), - circuit_size: backend.get_exact_circuit_size(&compiled_program.circuit)?, - }) -} - -fn count_opcodes_and_gates_in_contract( - backend: &Backend, - contract: CompiledContract, - expression_width: ExpressionWidth, -) -> Result { - let functions = contract +) -> ProgramInfo { + let functions = compiled_program + .bytecode .functions .into_par_iter() - .map(|function| -> Result<_, BackendError> { - Ok(FunctionInfo { - name: function.name, - acir_opcodes: function.bytecode.opcodes.len(), - circuit_size: backend.get_exact_circuit_size(&function.bytecode)?, - }) + .enumerate() + .map(|(i, function)| FunctionInfo { + name: compiled_program.names[i].clone(), + acir_opcodes: function.opcodes.len(), }) - .collect::>()?; + .collect(); - Ok(ContractInfo { name: contract.name, expression_width, functions }) + ProgramInfo { package_name: package.name.to_string(), expression_width, functions } } diff --git a/tooling/nargo_cli/src/cli/lsp_cmd.rs b/tooling/nargo_cli/src/cli/lsp_cmd.rs index 1428b8070c8..9ff7a42e5f5 100644 --- a/tooling/nargo_cli/src/cli/lsp_cmd.rs +++ b/tooling/nargo_cli/src/cli/lsp_cmd.rs @@ -8,7 +8,6 @@ use noir_lsp::NargoLspService; use tower::ServiceBuilder; use super::NargoConfig; -use crate::backends::Backend; use crate::errors::CliError; /// Starts the Noir LSP server @@ -19,20 +18,14 @@ use crate::errors::CliError; #[derive(Debug, Clone, Args)] pub(crate) struct LspCommand; -pub(crate) fn run( - // Backend is currently unused, but we might want to use it to inform the lsp in the future - _backend: &Backend, - _args: LspCommand, - _config: NargoConfig, -) -> Result<(), CliError> { +pub(crate) fn run(_args: LspCommand, _config: NargoConfig) -> Result<(), CliError> { use tokio::runtime::Builder; let runtime = Builder::new_current_thread().enable_all().build().unwrap(); runtime.block_on(async { let (server, _) = async_lsp::MainLoop::new_server(|client| { - let blackbox_solver = Bn254BlackBoxSolver::new(); - let router = NargoLspService::new(&client, blackbox_solver); + let router = NargoLspService::new(&client, Bn254BlackBoxSolver); ServiceBuilder::new() .layer(TracingLayer::default()) diff --git a/tooling/nargo_cli/src/cli/mod.rs b/tooling/nargo_cli/src/cli/mod.rs index e8e17893815..485ccc7abaf 100644 --- a/tooling/nargo_cli/src/cli/mod.rs +++ b/tooling/nargo_cli/src/cli/mod.rs @@ -6,13 +6,9 @@ use std::path::PathBuf; use color_eyre::eyre; -use crate::backends::get_active_backend; - mod fs; -mod backend_cmd; mod check_cmd; -mod codegen_verifier_cmd; mod compile_cmd; mod dap_cmd; mod debug_cmd; @@ -23,9 +19,7 @@ mod info_cmd; mod init_cmd; mod lsp_cmd; mod new_cmd; -mod prove_cmd; mod test_cmd; -mod verify_cmd; const GIT_HASH: &str = env!("GIT_COMMIT"); const IS_DIRTY: &str = env!("GIT_DIRTY"); @@ -60,10 +54,8 @@ pub(crate) struct NargoConfig { #[non_exhaustive] #[derive(Subcommand, Clone, Debug)] enum NargoCommand { - Backend(backend_cmd::BackendCommand), Check(check_cmd::CheckCommand), Fmt(fmt_cmd::FormatCommand), - CodegenVerifier(codegen_verifier_cmd::CodegenVerifierCommand), #[command(alias = "build")] Compile(compile_cmd::CompileCommand), New(new_cmd::NewCommand), @@ -73,8 +65,6 @@ enum NargoCommand { Export(export_cmd::ExportCommand), #[command(hide = true)] // Hidden while the feature is being built out Debug(debug_cmd::DebugCommand), - Prove(prove_cmd::ProveCommand), - Verify(verify_cmd::VerifyCommand), Test(test_cmd::TestCommand), Info(info_cmd::InfoCommand), Lsp(lsp_cmd::LspCommand), @@ -94,34 +84,23 @@ pub(crate) fn start_cli() -> eyre::Result<()> { // Search through parent directories to find package root if necessary. if !matches!( command, - NargoCommand::New(_) - | NargoCommand::Init(_) - | NargoCommand::Lsp(_) - | NargoCommand::Backend(_) - | NargoCommand::Dap(_) + NargoCommand::New(_) | NargoCommand::Init(_) | NargoCommand::Lsp(_) | NargoCommand::Dap(_) ) { config.program_dir = find_package_root(&config.program_dir)?; } - let active_backend = get_active_backend(); - let backend = crate::backends::Backend::new(active_backend); - match command { - NargoCommand::New(args) => new_cmd::run(&backend, args, config), + NargoCommand::New(args) => new_cmd::run(args, config), NargoCommand::Init(args) => init_cmd::run(args, config), - NargoCommand::Check(args) => check_cmd::run(&backend, args, config), - NargoCommand::Compile(args) => compile_cmd::run(&backend, args, config), - NargoCommand::Debug(args) => debug_cmd::run(&backend, args, config), - NargoCommand::Execute(args) => execute_cmd::run(&backend, args, config), - NargoCommand::Export(args) => export_cmd::run(&backend, args, config), - NargoCommand::Prove(args) => prove_cmd::run(&backend, args, config), - NargoCommand::Verify(args) => verify_cmd::run(&backend, args, config), - NargoCommand::Test(args) => test_cmd::run(&backend, args, config), - NargoCommand::Info(args) => info_cmd::run(&backend, args, config), - NargoCommand::CodegenVerifier(args) => codegen_verifier_cmd::run(&backend, args, config), - NargoCommand::Backend(args) => backend_cmd::run(args), - NargoCommand::Lsp(args) => lsp_cmd::run(&backend, args, config), - NargoCommand::Dap(args) => dap_cmd::run(&backend, args, config), + NargoCommand::Check(args) => check_cmd::run(args, config), + NargoCommand::Compile(args) => compile_cmd::run(args, config), + NargoCommand::Debug(args) => debug_cmd::run(args, config), + NargoCommand::Execute(args) => execute_cmd::run(args, config), + NargoCommand::Export(args) => export_cmd::run(args, config), + NargoCommand::Test(args) => test_cmd::run(args, config), + NargoCommand::Info(args) => info_cmd::run(args, config), + NargoCommand::Lsp(args) => lsp_cmd::run(args, config), + NargoCommand::Dap(args) => dap_cmd::run(args, config), NargoCommand::Fmt(args) => fmt_cmd::run(args, config), }?; diff --git a/tooling/nargo_cli/src/cli/new_cmd.rs b/tooling/nargo_cli/src/cli/new_cmd.rs index b4c823d0c1e..21951f27260 100644 --- a/tooling/nargo_cli/src/cli/new_cmd.rs +++ b/tooling/nargo_cli/src/cli/new_cmd.rs @@ -1,4 +1,3 @@ -use crate::backends::Backend; use crate::errors::CliError; use super::{init_cmd::initialize_project, NargoConfig}; @@ -30,12 +29,7 @@ pub(crate) struct NewCommand { pub(crate) contract: bool, } -pub(crate) fn run( - // Backend is currently unused, but we might want to use it to inform the "new" template in the future - _backend: &Backend, - args: NewCommand, - config: NargoConfig, -) -> Result<(), CliError> { +pub(crate) fn run(args: NewCommand, config: NargoConfig) -> Result<(), CliError> { let package_dir = config.program_dir.join(&args.path); if package_dir.exists() { diff --git a/tooling/nargo_cli/src/cli/noir_template_files/contract.nr b/tooling/nargo_cli/src/cli/noir_template_files/contract.nr index e126726393d..3cd3b5b3766 100644 --- a/tooling/nargo_cli/src/cli/noir_template_files/contract.nr +++ b/tooling/nargo_cli/src/cli/noir_template_files/contract.nr @@ -1,5 +1,5 @@ contract Main { - internal fn double(x: Field) -> pub Field { x * 2 } + fn double(x: Field) -> pub Field { x * 2 } fn triple(x: Field) -> pub Field { x * 3 } fn quadruple(x: Field) -> pub Field { double(double(x)) } } diff --git a/tooling/nargo_cli/src/cli/prove_cmd.rs b/tooling/nargo_cli/src/cli/prove_cmd.rs deleted file mode 100644 index cc39b0535bc..00000000000 --- a/tooling/nargo_cli/src/cli/prove_cmd.rs +++ /dev/null @@ -1,155 +0,0 @@ -use clap::Args; -use nargo::constants::{PROVER_INPUT_FILE, VERIFIER_INPUT_FILE}; -use nargo::ops::compile_program; -use nargo::package::Package; -use nargo::workspace::Workspace; -use nargo::{insert_all_files_for_workspace_into_file_manager, parse_all}; -use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection}; -use noirc_abi::input_parser::Format; -use noirc_driver::{ - file_manager_with_stdlib, CompileOptions, CompiledProgram, NOIR_ARTIFACT_VERSION_STRING, -}; -use noirc_frontend::graph::CrateName; - -use super::compile_cmd::report_errors; -use super::fs::{ - inputs::{read_inputs_from_file, write_inputs_to_file}, - proof::save_proof_to_dir, -}; -use super::NargoConfig; -use crate::{backends::Backend, cli::execute_cmd::execute_program, errors::CliError}; - -/// Create proof for this program. The proof is returned as a hex encoded string. -#[derive(Debug, Clone, Args)] -pub(crate) struct ProveCommand { - /// The name of the toml file which contains the inputs for the prover - #[clap(long, short, default_value = PROVER_INPUT_FILE)] - prover_name: String, - - /// The name of the toml file which contains the inputs for the verifier - #[clap(long, short, default_value = VERIFIER_INPUT_FILE)] - verifier_name: String, - - /// Verify proof after proving - #[arg(long)] - verify: bool, - - /// The name of the package to prove - #[clap(long, conflicts_with = "workspace")] - package: Option, - - /// Prove all packages in the workspace - #[clap(long, conflicts_with = "package")] - workspace: bool, - - #[clap(flatten)] - compile_options: CompileOptions, - - /// JSON RPC url to solve oracle calls - #[clap(long)] - oracle_resolver: Option, -} - -pub(crate) fn run( - backend: &Backend, - args: ProveCommand, - config: NargoConfig, -) -> Result<(), CliError> { - let toml_path = get_package_manifest(&config.program_dir)?; - 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, - Some(NOIR_ARTIFACT_VERSION_STRING.to_string()), - )?; - - let mut workspace_file_manager = file_manager_with_stdlib(&workspace.root_dir); - insert_all_files_for_workspace_into_file_manager(&workspace, &mut workspace_file_manager); - let parsed_files = parse_all(&workspace_file_manager); - - let expression_width = args - .compile_options - .expression_width - .unwrap_or_else(|| backend.get_backend_info_or_default()); - let binary_packages = workspace.into_iter().filter(|package| package.is_binary()); - for package in binary_packages { - let compilation_result = compile_program( - &workspace_file_manager, - &parsed_files, - package, - &args.compile_options, - None, - ); - - let compiled_program = report_errors( - compilation_result, - &workspace_file_manager, - args.compile_options.deny_warnings, - args.compile_options.silence_warnings, - )?; - - let compiled_program = nargo::ops::transform_program(compiled_program, expression_width); - - prove_package( - backend, - &workspace, - package, - compiled_program, - &args.prover_name, - &args.verifier_name, - args.verify, - args.oracle_resolver.as_deref(), - )?; - } - - Ok(()) -} - -#[allow(clippy::too_many_arguments)] -pub(crate) fn prove_package( - backend: &Backend, - workspace: &Workspace, - package: &Package, - compiled_program: CompiledProgram, - prover_name: &str, - verifier_name: &str, - check_proof: bool, - foreign_call_resolver_url: Option<&str>, -) -> Result<(), CliError> { - // Parse the initial witness values from Prover.toml - let (inputs_map, _) = - read_inputs_from_file(&package.root_dir, prover_name, Format::Toml, &compiled_program.abi)?; - - let solved_witness = - execute_program(&compiled_program, &inputs_map, foreign_call_resolver_url)?; - - // Write public inputs into Verifier.toml - let public_abi = compiled_program.abi.public_abi(); - let (public_inputs, return_value) = public_abi.decode(&solved_witness)?; - - write_inputs_to_file( - &public_inputs, - &return_value, - &public_abi, - &package.root_dir, - verifier_name, - Format::Toml, - )?; - - let proof = backend.prove(&compiled_program.circuit, solved_witness)?; - - if check_proof { - let public_inputs = public_abi.encode(&public_inputs, return_value)?; - let valid_proof = backend.verify(&proof, public_inputs, &compiled_program.circuit)?; - - if !valid_proof { - return Err(CliError::InvalidProof("".into())); - } - } - - save_proof_to_dir(&proof, &String::from(&package.name), workspace.proofs_directory_path())?; - - Ok(()) -} diff --git a/tooling/nargo_cli/src/cli/test_cmd.rs b/tooling/nargo_cli/src/cli/test_cmd.rs index 503fd5afdd4..99c284e5019 100644 --- a/tooling/nargo_cli/src/cli/test_cmd.rs +++ b/tooling/nargo_cli/src/cli/test_cmd.rs @@ -1,29 +1,31 @@ use std::io::Write; -use acvm::BlackBoxFunctionSolver; +use acvm::{BlackBoxFunctionSolver, FieldElement}; use bn254_blackbox_solver::Bn254BlackBoxSolver; use clap::Args; use fm::FileManager; use nargo::{ - insert_all_files_for_workspace_into_file_manager, - ops::{run_test, TestStatus}, - package::Package, - parse_all, prepare_package, + insert_all_files_for_workspace_into_file_manager, ops::TestStatus, package::Package, parse_all, + prepare_package, }; use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection}; -use noirc_driver::{file_manager_with_stdlib, CompileOptions, NOIR_ARTIFACT_VERSION_STRING}; +use noirc_driver::{ + check_crate, file_manager_with_stdlib, CompileOptions, NOIR_ARTIFACT_VERSION_STRING, +}; use noirc_frontend::{ graph::CrateName, hir::{FunctionNameMatch, ParsedFiles}, }; +use rayon::prelude::{IntoParallelIterator, ParallelBridge, ParallelIterator}; use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor}; -use crate::{backends::Backend, cli::check_cmd::check_crate_and_report_errors, errors::CliError}; +use crate::{cli::check_cmd::check_crate_and_report_errors, errors::CliError}; use super::NargoConfig; /// Run the tests for this program #[derive(Debug, Clone, Args)] +#[clap(visible_alias = "t")] pub(crate) struct TestCommand { /// If given, only tests with names containing this string will be run test_name: Option, @@ -52,11 +54,7 @@ pub(crate) struct TestCommand { oracle_resolver: Option, } -pub(crate) fn run( - _backend: &Backend, - args: TestCommand, - config: NargoConfig, -) -> Result<(), CliError> { +pub(crate) fn run(args: TestCommand, config: NargoConfig) -> Result<(), CliError> { let toml_path = get_package_manifest(&config.program_dir)?; let default_selection = if args.workspace { PackageSelection::All } else { PackageSelection::DefaultOrAll }; @@ -82,15 +80,13 @@ pub(crate) fn run( None => FunctionNameMatch::Anything, }; - let blackbox_solver = Bn254BlackBoxSolver::new(); - let test_reports: Vec> = workspace .into_iter() + .par_bridge() .map(|package| { - run_tests( + run_tests::( &workspace_file_manager, &parsed_files, - &blackbox_solver, package, pattern, args.show_output, @@ -116,24 +112,96 @@ pub(crate) fn run( }; } - if test_report.iter().any(|(_, status)| !matches!(status, TestStatus::Fail { .. })) { - Ok(()) - } else { + if test_report.iter().any(|(_, status)| status.failed()) { Err(CliError::Generic(String::new())) + } else { + Ok(()) } } -#[allow(clippy::too_many_arguments)] -fn run_tests( +fn run_tests + Default>( file_manager: &FileManager, parsed_files: &ParsedFiles, - blackbox_solver: &S, package: &Package, fn_name: FunctionNameMatch, show_output: bool, foreign_call_resolver_url: Option<&str>, compile_options: &CompileOptions, ) -> Result, CliError> { + let test_functions = + get_tests_in_package(file_manager, parsed_files, package, fn_name, compile_options)?; + + let count_all = test_functions.len(); + + let plural = if count_all == 1 { "" } else { "s" }; + println!("[{}] Running {count_all} test function{plural}", package.name); + + let test_report: Vec<(String, TestStatus)> = test_functions + .into_par_iter() + .map(|test_name| { + let status = run_test::( + file_manager, + parsed_files, + package, + &test_name, + show_output, + foreign_call_resolver_url, + compile_options, + ); + + (test_name, status) + }) + .collect(); + + display_test_report(file_manager, package, compile_options, &test_report)?; + Ok(test_report) +} + +fn run_test + Default>( + file_manager: &FileManager, + parsed_files: &ParsedFiles, + package: &Package, + fn_name: &str, + show_output: bool, + foreign_call_resolver_url: Option<&str>, + compile_options: &CompileOptions, +) -> TestStatus { + // This is really hacky but we can't share `Context` or `S` across threads. + // We then need to construct a separate copy for each test. + + let (mut context, crate_id) = prepare_package(file_manager, parsed_files, package); + check_crate( + &mut context, + crate_id, + compile_options.deny_warnings, + compile_options.disable_macros, + compile_options.use_elaborator, + ) + .expect("Any errors should have occurred when collecting test functions"); + + let test_functions = context + .get_all_test_functions_in_crate_matching(&crate_id, FunctionNameMatch::Exact(fn_name)); + let (_, test_function) = test_functions.first().expect("Test function should exist"); + + let blackbox_solver = S::default(); + + nargo::ops::run_test( + &blackbox_solver, + &mut context, + test_function, + show_output, + foreign_call_resolver_url, + compile_options, + ) +} + +fn get_tests_in_package( + file_manager: &FileManager, + parsed_files: &ParsedFiles, + package: &Package, + fn_name: FunctionNameMatch, + compile_options: &CompileOptions, +) -> Result, CliError> { let (mut context, crate_id) = prepare_package(file_manager, parsed_files, package); check_crate_and_report_errors( &mut context, @@ -141,32 +209,30 @@ fn run_tests( compile_options.deny_warnings, compile_options.disable_macros, compile_options.silence_warnings, + compile_options.use_elaborator, )?; - let test_functions = context.get_all_test_functions_in_crate_matching(&crate_id, fn_name); - let count_all = test_functions.len(); - - let plural = if count_all == 1 { "" } else { "s" }; - println!("[{}] Running {count_all} test function{plural}", package.name); + Ok(context + .get_all_test_functions_in_crate_matching(&crate_id, fn_name) + .into_iter() + .map(|(test_name, _)| test_name) + .collect()) +} +fn display_test_report( + file_manager: &FileManager, + package: &Package, + compile_options: &CompileOptions, + test_report: &[(String, TestStatus)], +) -> Result<(), CliError> { let writer = StandardStream::stderr(ColorChoice::Always); let mut writer = writer.lock(); - let mut test_report: Vec<(String, TestStatus)> = Vec::new(); - for (test_name, test_function) in test_functions { + for (test_name, test_status) in test_report { write!(writer, "[{}] Testing {test_name}... ", package.name) .expect("Failed to write to stderr"); writer.flush().expect("Failed to flush writer"); - let test_status = run_test( - blackbox_solver, - &mut context, - test_function, - show_output, - foreign_call_resolver_url, - compile_options, - ); - match &test_status { TestStatus::Pass { .. } => { writer @@ -181,7 +247,7 @@ fn run_tests( writeln!(writer, "FAIL\n{message}\n").expect("Failed to write to stderr"); if let Some(diag) = error_diagnostic { noirc_errors::reporter::report_all( - context.file_manager.as_file_map(), + file_manager.as_file_map(), &[diag.clone()], compile_options.deny_warnings, compile_options.silence_warnings, @@ -190,23 +256,21 @@ fn run_tests( } TestStatus::CompileError(err) => { noirc_errors::reporter::report_all( - context.file_manager.as_file_map(), + file_manager.as_file_map(), &[err.clone()], compile_options.deny_warnings, compile_options.silence_warnings, ); } } - - test_report.push((test_name, test_status)); - writer.reset().expect("Failed to reset writer"); } write!(writer, "[{}] ", package.name).expect("Failed to write to stderr"); - let count_failed = - test_report.iter().filter(|(_, status)| !matches!(status, TestStatus::Pass)).count(); + let count_all = test_report.len(); + let count_failed = test_report.iter().filter(|(_, status)| status.failed()).count(); + let plural = if count_all == 1 { "" } else { "s" }; if count_failed == 0 { writer.set_color(ColorSpec::new().set_fg(Some(Color::Green))).expect("Failed to set color"); write!(writer, "{count_all} test{plural} passed").expect("Failed to write to stderr"); @@ -231,5 +295,5 @@ fn run_tests( writer.reset().expect("Failed to reset writer"); } - Ok(test_report) + Ok(()) } diff --git a/tooling/nargo_cli/src/cli/verify_cmd.rs b/tooling/nargo_cli/src/cli/verify_cmd.rs deleted file mode 100644 index 66b88a22f2a..00000000000 --- a/tooling/nargo_cli/src/cli/verify_cmd.rs +++ /dev/null @@ -1,112 +0,0 @@ -use super::compile_cmd::report_errors; -use super::fs::{inputs::read_inputs_from_file, load_hex_data}; -use super::NargoConfig; -use crate::{backends::Backend, errors::CliError}; - -use clap::Args; -use nargo::constants::{PROOF_EXT, VERIFIER_INPUT_FILE}; -use nargo::ops::compile_program; -use nargo::package::Package; -use nargo::workspace::Workspace; -use nargo::{insert_all_files_for_workspace_into_file_manager, parse_all}; -use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection}; -use noirc_abi::input_parser::Format; -use noirc_driver::{ - file_manager_with_stdlib, CompileOptions, CompiledProgram, NOIR_ARTIFACT_VERSION_STRING, -}; -use noirc_frontend::graph::CrateName; - -/// Given a proof and a program, verify whether the proof is valid -#[derive(Debug, Clone, Args)] -pub(crate) struct VerifyCommand { - /// The name of the toml file which contains the inputs for the verifier - #[clap(long, short, default_value = VERIFIER_INPUT_FILE)] - verifier_name: String, - - /// The name of the package verify - #[clap(long, conflicts_with = "workspace")] - package: Option, - - /// Verify all packages in the workspace - #[clap(long, conflicts_with = "package")] - workspace: bool, - - #[clap(flatten)] - compile_options: CompileOptions, -} - -pub(crate) fn run( - backend: &Backend, - args: VerifyCommand, - config: NargoConfig, -) -> Result<(), CliError> { - let toml_path = get_package_manifest(&config.program_dir)?; - 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, - Some(NOIR_ARTIFACT_VERSION_STRING.to_string()), - )?; - - let mut workspace_file_manager = file_manager_with_stdlib(&workspace.root_dir); - insert_all_files_for_workspace_into_file_manager(&workspace, &mut workspace_file_manager); - let parsed_files = parse_all(&workspace_file_manager); - - let expression_width = args - .compile_options - .expression_width - .unwrap_or_else(|| backend.get_backend_info_or_default()); - let binary_packages = workspace.into_iter().filter(|package| package.is_binary()); - for package in binary_packages { - let compilation_result = compile_program( - &workspace_file_manager, - &parsed_files, - package, - &args.compile_options, - None, - ); - - let compiled_program = report_errors( - compilation_result, - &workspace_file_manager, - args.compile_options.deny_warnings, - args.compile_options.silence_warnings, - )?; - - let compiled_program = nargo::ops::transform_program(compiled_program, expression_width); - - verify_package(backend, &workspace, package, compiled_program, &args.verifier_name)?; - } - - Ok(()) -} - -fn verify_package( - backend: &Backend, - workspace: &Workspace, - package: &Package, - compiled_program: CompiledProgram, - verifier_name: &str, -) -> Result<(), CliError> { - // Load public inputs (if any) from `verifier_name`. - let public_abi = compiled_program.abi.public_abi(); - let (public_inputs_map, return_value) = - read_inputs_from_file(&package.root_dir, verifier_name, Format::Toml, &public_abi)?; - - let public_inputs = public_abi.encode(&public_inputs_map, return_value)?; - - let proof_path = - workspace.proofs_directory_path().join(package.name.to_string()).with_extension(PROOF_EXT); - - let proof = load_hex_data(&proof_path)?; - - let valid_proof = backend.verify(&proof, public_inputs, &compiled_program.circuit)?; - - if valid_proof { - Ok(()) - } else { - Err(CliError::InvalidProof(proof_path)) - } -} diff --git a/tooling/nargo_cli/src/errors.rs b/tooling/nargo_cli/src/errors.rs index c2996f53420..3e0b13a9cbc 100644 --- a/tooling/nargo_cli/src/errors.rs +++ b/tooling/nargo_cli/src/errors.rs @@ -1,5 +1,4 @@ -use acvm::acir::native_types::WitnessMapError; -use hex::FromHexError; +use acvm::acir::native_types::WitnessStackError; use nargo::{errors::CompileError, NargoError}; use nargo_toml::ManifestError; use noir_debugger::errors::DapError; @@ -11,8 +10,7 @@ use thiserror::Error; pub(crate) enum FilesystemError { #[error("Error: {} is not a valid path\nRun either `nargo compile` to generate missing build artifacts or `nargo prove` to construct a proof", .0.display())] PathNotValid(PathBuf), - #[error("Error: could not parse hex build artifact (proof, proving and/or verification keys, ACIR checksum) ({0})")] - HexArtifactNotValid(FromHexError), + #[error( " Error: cannot find {0}.toml file.\n Expected location: {1:?} \n Please generate this file at the expected location." )] @@ -22,9 +20,9 @@ pub(crate) enum FilesystemError { #[error(transparent)] InputParserError(#[from] InputParserError), - /// WitnessMap serialization error + /// WitnessStack serialization error #[error(transparent)] - WitnessMapSerialization(#[from] WitnessMapError), + WitnessStackSerialization(#[from] WitnessStackError), #[error("Error: could not deserialize build program: {0}")] ProgramSerializationError(String), @@ -37,9 +35,6 @@ pub(crate) enum CliError { #[error("Error: destination {} already exists", .0.display())] DestinationAlreadyExists(PathBuf), - #[error("Failed to verify proof {}", .0.display())] - InvalidProof(PathBuf), - #[error("Invalid package name {0}. Did you mean to use `--name`?")] InvalidPackageName(String), @@ -68,24 +63,4 @@ pub(crate) enum CliError { /// Error from the compilation pipeline #[error(transparent)] CompileError(#[from] CompileError), - - /// Error related to backend selection/installation. - #[error(transparent)] - BackendError(#[from] BackendError), - - /// Error related to communication with backend. - #[error(transparent)] - BackendCommunicationError(#[from] backend_interface::BackendError), -} - -#[derive(Debug, thiserror::Error)] -pub(crate) enum BackendError { - #[error("No backend is installed with the name {0}")] - UnknownBackend(String), - - #[error("The backend {0} is already installed")] - AlreadyInstalled(String), - - #[error("Backend installation failed: {0}")] - InstallationError(#[from] std::io::Error), } diff --git a/tooling/nargo_cli/src/main.rs b/tooling/nargo_cli/src/main.rs index 3f797b0bf0c..a407d467ced 100644 --- a/tooling/nargo_cli/src/main.rs +++ b/tooling/nargo_cli/src/main.rs @@ -7,7 +7,6 @@ //! This name was used because it sounds like `cargo` and //! Noir Package Manager abbreviated is npm, which is already taken. -mod backends; mod cli; mod errors; @@ -25,14 +24,14 @@ fn main() { if let Ok(log_dir) = env::var("NARGO_LOG_DIR") { let debug_file = rolling::daily(log_dir, "nargo-log"); tracing_subscriber::fmt() - .with_span_events(FmtSpan::ACTIVE) + .with_span_events(FmtSpan::ENTER | FmtSpan::CLOSE) .with_writer(debug_file) .with_ansi(false) .with_env_filter(EnvFilter::from_default_env()) .init(); } else { tracing_subscriber::fmt() - .with_span_events(FmtSpan::ACTIVE) + .with_span_events(FmtSpan::ENTER | FmtSpan::CLOSE) .with_ansi(true) .with_env_filter(EnvFilter::from_env("NOIR_LOG")) .init(); diff --git a/tooling/nargo_cli/tests/codegen-verifier.rs b/tooling/nargo_cli/tests/codegen-verifier.rs deleted file mode 100644 index f991f72b108..00000000000 --- a/tooling/nargo_cli/tests/codegen-verifier.rs +++ /dev/null @@ -1,37 +0,0 @@ -//! This integration test aims to check that the `nargo codegen-verifier` will successfully create a -//! file containing a verifier for a simple program. - -use assert_cmd::prelude::*; -use predicates::prelude::*; -use std::process::Command; - -use assert_fs::prelude::{PathAssert, PathChild}; - -#[test] -fn simple_verifier_codegen() { - let test_dir = assert_fs::TempDir::new().unwrap(); - std::env::set_current_dir(&test_dir).unwrap(); - - // Create trivial program - let project_name = "hello_world"; - let project_dir = test_dir.child(project_name); - - let mut cmd = Command::cargo_bin("nargo").unwrap(); - cmd.arg("new").arg(project_name); - cmd.assert().success(); - - std::env::set_current_dir(&project_dir).unwrap(); - - // Run `nargo codegen-verifier` - let mut cmd = Command::cargo_bin("nargo").unwrap(); - cmd.arg("codegen-verifier"); - cmd.assert() - .success() - .stdout(predicate::str::contains("Contract successfully created and located at")); - - project_dir - .child("contract") - .child("hello_world") - .child("plonk_vk.sol") - .assert(predicate::path::is_file()); -} diff --git a/tooling/nargo_cli/tests/hello_world.rs b/tooling/nargo_cli/tests/hello_world.rs index 9fcb0c873e1..6b6931542b5 100644 --- a/tooling/nargo_cli/tests/hello_world.rs +++ b/tooling/nargo_cli/tests/hello_world.rs @@ -34,22 +34,11 @@ fn hello_world_example() { .stdout(predicate::str::contains("Constraint system successfully built!")); project_dir.child("Prover.toml").assert(predicate::path::is_file()); - project_dir.child("Verifier.toml").assert(predicate::path::is_file()); - // `nargo prove` + // `nargo execute` project_dir.child("Prover.toml").write_str("x = 1\ny = 2").unwrap(); let mut cmd = Command::cargo_bin("nargo").unwrap(); - cmd.arg("prove"); - cmd.assert().success(); - - project_dir - .child("proofs") - .child(format!("{project_name}.proof")) - .assert(predicate::path::is_file()); - - // `nargo verify p` - let mut cmd = Command::cargo_bin("nargo").unwrap(); - cmd.arg("verify"); + cmd.arg("execute"); cmd.assert().success(); } diff --git a/tooling/nargo_cli/tests/stdlib-tests.rs b/tooling/nargo_cli/tests/stdlib-tests.rs new file mode 100644 index 00000000000..0bb967e7502 --- /dev/null +++ b/tooling/nargo_cli/tests/stdlib-tests.rs @@ -0,0 +1,62 @@ +use std::{collections::BTreeMap, path::PathBuf}; + +use acvm::blackbox_solver::StubbedBlackBoxSolver; +use noirc_driver::{check_crate, file_manager_with_stdlib, CompileOptions}; +use noirc_frontend::hir::FunctionNameMatch; + +use nargo::{ + ops::{report_errors, run_test, TestStatus}, + package::{Package, PackageType}, + parse_all, prepare_package, +}; + +#[test] +fn run_stdlib_tests() { + let mut file_manager = file_manager_with_stdlib(&PathBuf::from(".")); + file_manager.add_file_with_source_canonical_path(&PathBuf::from("main.nr"), "".to_owned()); + let parsed_files = parse_all(&file_manager); + + // We need a dummy package as we cannot compile the stdlib on its own. + let dummy_package = Package { + version: None, + compiler_required_version: None, + root_dir: PathBuf::from("."), + package_type: PackageType::Binary, + entry_path: PathBuf::from("main.nr"), + name: "dummy".parse().unwrap(), + dependencies: BTreeMap::new(), + }; + + let (mut context, dummy_crate_id) = + prepare_package(&file_manager, &parsed_files, &dummy_package); + + let result = check_crate(&mut context, dummy_crate_id, true, false, false); + report_errors(result, &context.file_manager, true, false) + .expect("Error encountered while compiling standard library"); + + // We can now search within the stdlib for any test functions to compile. + + let test_functions = context.get_all_test_functions_in_crate_matching( + context.stdlib_crate_id(), + FunctionNameMatch::Anything, + ); + + let test_report: Vec<(String, TestStatus)> = test_functions + .into_iter() + .map(|(test_name, test_function)| { + let status = run_test( + &StubbedBlackBoxSolver, + &mut context, + &test_function, + false, + None, + &CompileOptions::default(), + ); + + (test_name, status) + }) + .collect(); + + assert!(!test_report.is_empty(), "Could not find any tests within the stdlib"); + assert!(test_report.iter().all(|(_, status)| !status.failed())); +} diff --git a/tooling/nargo_fmt/Cargo.toml b/tooling/nargo_fmt/Cargo.toml index 374413ac9f2..05b2fdb7d52 100644 --- a/tooling/nargo_fmt/Cargo.toml +++ b/tooling/nargo_fmt/Cargo.toml @@ -3,6 +3,7 @@ name = "nargo_fmt" version.workspace = true authors.workspace = true edition.workspace = true +rust-version.workspace = true license.workspace = true [dependencies] diff --git a/tooling/nargo_fmt/build.rs b/tooling/nargo_fmt/build.rs index c356b403ae5..7d5f07c43bf 100644 --- a/tooling/nargo_fmt/build.rs +++ b/tooling/nargo_fmt/build.rs @@ -49,28 +49,55 @@ fn generate_formatter_tests(test_file: &mut File, test_data_dir: &Path) { let output_source_path = outputs_dir.join(file_name).display().to_string(); let output_source = std::fs::read_to_string(output_source_path.clone()).unwrap(); + let skip_idempotent_test = + // TODO(https://github.com/noir-lang/noir/issues/4766): spurious trailing space + test_name == "array" || + // TODO(https://github.com/noir-lang/noir/issues/4767): pre-comment space + // TODO(https://github.com/noir-lang/noir/issues/4768): spurious newline + test_name == "tuple"; + write!( test_file, r##" -#[test] -fn format_{test_name}() {{ - let input = r#"{input_source}"#; - let expected_output = r#"{output_source}"#; + #[test] + fn format_{test_name}() {{ + let input = r#"{input_source}"#; + let expected_output = r#"{output_source}"#; - let (parsed_module, _errors) = noirc_frontend::parse_program(&input); + let (parsed_module, _errors) = noirc_frontend::parse_program(input); - let config = nargo_fmt::Config::of("{config}").unwrap(); - let fmt_text = nargo_fmt::format(&input, parsed_module, &config); + let config = nargo_fmt::Config::of("{config}").unwrap(); + let fmt_text = nargo_fmt::format(input, parsed_module, &config); - if std::env::var("UPDATE_EXPECT").is_ok() {{ - std::fs::write("{output_source_path}", fmt_text.clone()).unwrap(); - }} + if std::env::var("UPDATE_EXPECT").is_ok() {{ + std::fs::write("{output_source_path}", fmt_text.clone()).unwrap(); + }} - similar_asserts::assert_eq!(fmt_text, expected_output); -}} + similar_asserts::assert_eq!(fmt_text, expected_output); + }} "## ) .expect("Could not write templated test file."); + + if !skip_idempotent_test { + write!( + test_file, + r##" + #[test] + fn format_idempotent_{test_name}() {{ + let expected_output = r#"{output_source}"#; + + let (parsed_module, _errors) = noirc_frontend::parse_program(expected_output); + + let config = nargo_fmt::Config::of("{config}").unwrap(); + let fmt_text = nargo_fmt::format(expected_output, parsed_module, &config); + + similar_asserts::assert_eq!(fmt_text, expected_output); + }} + "## + ) + .expect("Could not write templated test file."); + } } } diff --git a/tooling/nargo_fmt/src/config.rs b/tooling/nargo_fmt/src/config.rs index 2bb5d97c0af..5e38dc7d8b0 100644 --- a/tooling/nargo_fmt/src/config.rs +++ b/tooling/nargo_fmt/src/config.rs @@ -45,7 +45,7 @@ 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"; + error_on_lost_comment: bool, false, "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"; fn_call_width: usize, 60, "Maximum width of the args of a function call before falling back to vertical formatting"; diff --git a/tooling/nargo_fmt/src/rewrite/array.rs b/tooling/nargo_fmt/src/rewrite/array.rs index 77e5e756f19..011e775a018 100644 --- a/tooling/nargo_fmt/src/rewrite/array.rs +++ b/tooling/nargo_fmt/src/rewrite/array.rs @@ -1,4 +1,4 @@ -use noirc_frontend::{hir::resolution::errors::Span, token::Token, Expression}; +use noirc_frontend::{ast::Expression, hir::resolution::errors::Span, token::Token}; use crate::{ items::Item, @@ -6,7 +6,12 @@ use crate::{ visitor::{expr::NewlineMode, FmtVisitor}, }; -pub(crate) fn rewrite(mut visitor: FmtVisitor, array: Vec, array_span: Span) -> String { +pub(crate) fn rewrite( + mut visitor: FmtVisitor, + array: Vec, + array_span: Span, + is_slice: bool, +) -> String { let pattern: &[_] = &[' ', '\t']; visitor.indent.block_indent(visitor.config); @@ -75,8 +80,9 @@ pub(crate) fn rewrite(mut visitor: FmtVisitor, array: Vec, array_spa } } + let open_bracket = if is_slice { "&[" } else { "[" }; crate::visitor::expr::wrap_exprs( - "[", + open_bracket, "]", items_str.trim().into(), nested_indent, diff --git a/tooling/nargo_fmt/src/rewrite/expr.rs b/tooling/nargo_fmt/src/rewrite/expr.rs index 32d104f559b..9a704717ade 100644 --- a/tooling/nargo_fmt/src/rewrite/expr.rs +++ b/tooling/nargo_fmt/src/rewrite/expr.rs @@ -1,5 +1,9 @@ -use noirc_frontend::{token::Token, ArrayLiteral, Expression, ExpressionKind, Literal, UnaryOp}; +use noirc_frontend::ast::{ + ArrayLiteral, BlockExpression, Expression, ExpressionKind, Literal, UnaryOp, UnresolvedType, +}; +use noirc_frontend::{macros_api::Span, token::Token}; +use crate::rewrite; use crate::visitor::{ expr::{format_brackets, format_parens, NewlineMode}, ExpressionType, FmtVisitor, Indent, Shape, @@ -20,11 +24,7 @@ pub(crate) fn rewrite( shape: Shape, ) -> String { match kind { - ExpressionKind::Block(block) => { - let mut visitor = visitor.fork(); - visitor.visit_block(block, span); - visitor.finish() - } + ExpressionKind::Block(block) => rewrite_block(visitor, block, span), ExpressionKind::Prefix(prefix) => { let op = match prefix.operator { UnaryOp::Minus => "-", @@ -73,6 +73,7 @@ pub(crate) fn rewrite( let object = rewrite_sub_expr(visitor, shape, method_call_expr.object); let method = method_call_expr.method_name.to_string(); + let turbofish = rewrite_turbofish(visitor, shape, method_call_expr.generics); let args = format_parens( visitor.config.fn_call_width.into(), visitor.fork(), @@ -84,7 +85,7 @@ pub(crate) fn rewrite( NewlineMode::IfContainsNewLineAndWidth, ); - format!("{object}.{method}{args}") + format!("{object}.{method}{turbofish}{args}") } ExpressionKind::MemberAccess(member_access_expr) => { let lhs_str = rewrite_sub_expr(visitor, shape, member_access_expr.lhs); @@ -122,7 +123,16 @@ pub(crate) fn rewrite( format!("[{repeated}; {length}]") } Literal::Array(ArrayLiteral::Standard(exprs)) => { - super::array(visitor.fork(), exprs, span) + super::array(visitor.fork(), exprs, span, false) + } + Literal::Slice(ArrayLiteral::Repeated { repeated_element, length }) => { + let repeated = rewrite_sub_expr(visitor, shape, *repeated_element); + let length = rewrite_sub_expr(visitor, shape, *length); + + format!("&[{repeated}; {length}]") + } + Literal::Slice(ArrayLiteral::Standard(exprs)) => { + super::array(visitor.fork(), exprs, span, true) } Literal::Unit => "()".to_string(), }, @@ -149,7 +159,47 @@ pub(crate) fn rewrite( visitor.format_if(*if_expr) } - ExpressionKind::Lambda(_) | ExpressionKind::Variable(_) => visitor.slice(span).to_string(), + ExpressionKind::Variable(path, generics) => { + let path_string = visitor.slice(path.span); + + let turbofish = rewrite_turbofish(visitor, shape, generics); + format!("{path_string}{turbofish}") + } + ExpressionKind::Lambda(_) => visitor.slice(span).to_string(), + ExpressionKind::Quote(block) => format!("quote {}", rewrite_block(visitor, block, span)), + ExpressionKind::Comptime(block) => { + format!("comptime {}", rewrite_block(visitor, block, span)) + } ExpressionKind::Error => unreachable!(), + ExpressionKind::Resolved(_) => { + unreachable!("ExpressionKind::Resolved should only emitted by the comptime interpreter") + } + } +} + +fn rewrite_block(visitor: &FmtVisitor, block: BlockExpression, span: Span) -> String { + let mut visitor = visitor.fork(); + visitor.visit_block(block, span); + visitor.finish() +} + +fn rewrite_turbofish( + visitor: &FmtVisitor, + shape: Shape, + generics: Option>, +) -> String { + if let Some(generics) = generics { + let mut turbofish = "".to_owned(); + for (i, generic) in generics.into_iter().enumerate() { + let generic = rewrite::typ(visitor, shape, generic); + turbofish = if i == 0 { + format!("::<{}", generic) + } else { + format!("{turbofish}, {}", generic) + }; + } + format!("{turbofish}>") + } else { + "".to_owned() } } diff --git a/tooling/nargo_fmt/src/rewrite/imports.rs b/tooling/nargo_fmt/src/rewrite/imports.rs index 2788f778140..564ef3fa370 100644 --- a/tooling/nargo_fmt/src/rewrite/imports.rs +++ b/tooling/nargo_fmt/src/rewrite/imports.rs @@ -1,4 +1,4 @@ -use noirc_frontend::{PathKind, UseTreeKind}; +use noirc_frontend::ast; use crate::{ items::Item, @@ -60,13 +60,13 @@ pub(crate) struct UseTree { } impl UseTree { - pub(crate) fn from_ast(use_tree: noirc_frontend::UseTree) -> Self { + pub(crate) fn from_ast(use_tree: ast::UseTree) -> Self { let mut result = UseTree { path: vec![] }; match use_tree.prefix.kind { - PathKind::Crate => result.path.push(UseSegment::Crate), - PathKind::Dep => result.path.push(UseSegment::Dep), - PathKind::Plain => {} + ast::PathKind::Crate => result.path.push(UseSegment::Crate), + ast::PathKind::Dep => result.path.push(UseSegment::Dep), + ast::PathKind::Plain => {} }; result.path.extend( @@ -78,13 +78,13 @@ impl UseTree { ); match use_tree.kind { - UseTreeKind::Path(name, alias) => { + ast::UseTreeKind::Path(name, alias) => { result.path.push(UseSegment::Ident( name.to_string(), alias.map(|rename| rename.to_string()), )); } - UseTreeKind::List(list) => { + ast::UseTreeKind::List(list) => { let segment = UseSegment::List(list.into_iter().map(UseTree::from_ast).collect()); result.path.push(segment); } @@ -102,7 +102,14 @@ impl UseTree { let mut iter = self.path.iter().peekable(); while let Some(segment) = iter.next() { - let segment_str = segment.rewrite(visitor, shape); + let mut segment_str = segment.rewrite(visitor, shape); + if segment_str.contains('{') + && !segment_str.contains(',') + && !segment_str.contains("::") + { + let empty = ""; + segment_str = segment_str.replace(['{', '}'], empty); + } result.push_str(&segment_str); if iter.peek().is_some() { diff --git a/tooling/nargo_fmt/src/rewrite/infix.rs b/tooling/nargo_fmt/src/rewrite/infix.rs index 5d2b387496a..e2555f21187 100644 --- a/tooling/nargo_fmt/src/rewrite/infix.rs +++ b/tooling/nargo_fmt/src/rewrite/infix.rs @@ -1,6 +1,6 @@ use std::iter::zip; -use noirc_frontend::{Expression, ExpressionKind}; +use noirc_frontend::ast::{Expression, ExpressionKind}; use crate::{ rewrite, diff --git a/tooling/nargo_fmt/src/rewrite/parenthesized.rs b/tooling/nargo_fmt/src/rewrite/parenthesized.rs index 3926b52cb73..93e1538b042 100644 --- a/tooling/nargo_fmt/src/rewrite/parenthesized.rs +++ b/tooling/nargo_fmt/src/rewrite/parenthesized.rs @@ -1,4 +1,5 @@ -use noirc_frontend::{hir::resolution::errors::Span, Expression, ExpressionKind}; +use noirc_frontend::ast::{Expression, ExpressionKind}; +use noirc_frontend::hir::resolution::errors::Span; use crate::visitor::{FmtVisitor, Shape}; diff --git a/tooling/nargo_fmt/src/rewrite/typ.rs b/tooling/nargo_fmt/src/rewrite/typ.rs index aaa77b0bea5..278457f82d1 100644 --- a/tooling/nargo_fmt/src/rewrite/typ.rs +++ b/tooling/nargo_fmt/src/rewrite/typ.rs @@ -1,4 +1,4 @@ -use noirc_frontend::{UnresolvedType, UnresolvedTypeData}; +use noirc_frontend::ast::{UnresolvedType, UnresolvedTypeData}; use crate::{ utils::span_is_empty, @@ -9,12 +9,12 @@ pub(crate) fn rewrite(visitor: &FmtVisitor, _shape: Shape, typ: UnresolvedType) match typ.typ { UnresolvedTypeData::Array(length, element) => { let typ = rewrite(visitor, _shape, *element); - if let Some(length) = length { - let length = visitor.slice(length.span()); - format!("[{typ}; {length}]") - } else { - format!("[{typ}]") - } + let length = visitor.slice(length.span()); + format!("[{typ}; {length}]") + } + UnresolvedTypeData::Slice(element) => { + let typ = rewrite(visitor, _shape, *element); + format!("[{typ}]") } UnresolvedTypeData::Parenthesized(typ) => { let typ = rewrite(visitor, _shape, *typ); @@ -64,6 +64,7 @@ pub(crate) fn rewrite(visitor: &FmtVisitor, _shape: Shape, typ: UnresolvedType) | UnresolvedTypeData::Expression(_) | UnresolvedTypeData::String(_) | UnresolvedTypeData::FormatString(_, _) + | UnresolvedTypeData::Code | UnresolvedTypeData::TraitAsType(_, _) => visitor.slice(typ.span.unwrap()).into(), UnresolvedTypeData::Error => unreachable!(), } diff --git a/tooling/nargo_fmt/src/utils.rs b/tooling/nargo_fmt/src/utils.rs index 94969d45e81..2c5c3085e66 100644 --- a/tooling/nargo_fmt/src/utils.rs +++ b/tooling/nargo_fmt/src/utils.rs @@ -3,10 +3,10 @@ use std::borrow::Cow; use crate::items::HasItem; use crate::rewrite; use crate::visitor::{FmtVisitor, Shape}; +use noirc_frontend::ast::{Expression, Ident, Param, Visibility}; use noirc_frontend::hir::resolution::errors::Span; use noirc_frontend::lexer::Lexer; use noirc_frontend::token::Token; -use noirc_frontend::{Expression, Ident, Param, Visibility}; pub(crate) fn changed_comment_content(original: &str, new: &str) -> bool { comments(original).ne(comments(new)) diff --git a/tooling/nargo_fmt/src/visitor/expr.rs b/tooling/nargo_fmt/src/visitor/expr.rs index f9836adda18..18b962a7f85 100644 --- a/tooling/nargo_fmt/src/visitor/expr.rs +++ b/tooling/nargo_fmt/src/visitor/expr.rs @@ -1,7 +1,8 @@ -use noirc_frontend::{ - hir::resolution::errors::Span, lexer::Lexer, token::Token, BlockExpression, - ConstructorExpression, Expression, ExpressionKind, IfExpression, Statement, StatementKind, +use noirc_frontend::ast::Expression; +use noirc_frontend::ast::{ + BlockExpression, ConstructorExpression, ExpressionKind, IfExpression, Statement, StatementKind, }; +use noirc_frontend::{hir::resolution::errors::Span, lexer::Lexer, token::Token}; use super::{ExpressionType, FmtVisitor, Shape}; use crate::{ diff --git a/tooling/nargo_fmt/src/visitor/item.rs b/tooling/nargo_fmt/src/visitor/item.rs index 28aad3c551f..a5d042dc71e 100644 --- a/tooling/nargo_fmt/src/visitor/item.rs +++ b/tooling/nargo_fmt/src/visitor/item.rs @@ -1,10 +1,3 @@ -use noirc_frontend::{ - hir::resolution::errors::Span, - parser::{Item, ItemKind}, - token::{Keyword, Token}, - Distinctness, NoirFunction, ParsedModule, Visibility, -}; - use crate::{ rewrite::{self, UseTree}, utils::{ @@ -13,6 +6,13 @@ use crate::{ }, visitor::expr::{format_seq, NewlineMode}, }; +use noirc_frontend::ast::{NoirFunction, Visibility}; +use noirc_frontend::{ + hir::resolution::errors::Span, + parser::{Item, ItemKind}, + token::{Keyword, Token}, + ParsedModule, +}; use super::{ expr::Tactic::{HorizontalVertical, LimitedHorizontalVertical}, @@ -118,10 +118,6 @@ impl super::FmtVisitor<'_> { if let Some(span) = return_type_span { result.push_str(" -> "); - if let Distinctness::Distinct = func.def.return_distinctness { - result.push_str("distinct "); - } - let visibility = match func.def.return_visibility { Visibility::Public => "pub", Visibility::DataBus => "return_data", diff --git a/tooling/nargo_fmt/src/visitor/stmt.rs b/tooling/nargo_fmt/src/visitor/stmt.rs index 44c5dad6b5d..8e05fe3f5c5 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::{ +use noirc_frontend::macros_api::Span; + +use noirc_frontend::ast::{ ConstrainKind, ConstrainStatement, ExpressionKind, ForRange, Statement, StatementKind, }; @@ -14,90 +16,94 @@ impl super::FmtVisitor<'_> { for (Statement { kind, span }, index) in zip(stmts, 1..) { let is_last = index == len; + self.visit_stmt(kind, span, is_last); + self.last_position = span.end(); + } + } - match kind { - StatementKind::Expression(expr) => self.visit_expr( - expr, - if is_last { ExpressionType::SubExpression } else { ExpressionType::Statement }, - ), - StatementKind::Semi(expr) => { - self.visit_expr(expr, ExpressionType::Statement); - self.push_str(";"); - } - StatementKind::Let(let_stmt) => { - let let_str = - self.slice(span.start()..let_stmt.expression.span.start()).trim_end(); - - let expr_str = rewrite::sub_expr(self, self.shape(), let_stmt.expression); - - self.push_rewrite(format!("{let_str} {expr_str};"), span); - } - StatementKind::Constrain(ConstrainStatement(expr, message, kind)) => { - let mut nested_shape = self.shape(); - let shape = nested_shape; - - nested_shape.indent.block_indent(self.config); - - let message = message.map_or(String::new(), |message| { - let message = rewrite::sub_expr(self, nested_shape, message); - format!(", {message}") - }); - - let (callee, args) = match kind { - ConstrainKind::Assert | ConstrainKind::Constrain => { - let assertion = rewrite::sub_expr(self, nested_shape, expr); - let args = format!("{assertion}{message}"); - - ("assert", args) - } - ConstrainKind::AssertEq => { - if let ExpressionKind::Infix(infix) = expr.kind { - let lhs = rewrite::sub_expr(self, nested_shape, infix.lhs); - let rhs = rewrite::sub_expr(self, nested_shape, infix.rhs); + fn visit_stmt(&mut self, kind: StatementKind, span: Span, is_last: bool) { + match kind { + StatementKind::Expression(expr) => self.visit_expr( + expr, + if is_last { ExpressionType::SubExpression } else { ExpressionType::Statement }, + ), + StatementKind::Semi(expr) => { + self.visit_expr(expr, ExpressionType::Statement); + self.push_str(";"); + } + StatementKind::Let(let_stmt) => { + let let_str = self.slice(span.start()..let_stmt.expression.span.start()).trim_end(); - let args = format!("{lhs}, {rhs}{message}"); + let expr_str = rewrite::sub_expr(self, self.shape(), let_stmt.expression); - ("assert_eq", args) - } else { - unreachable!() - } + self.push_rewrite(format!("{let_str} {expr_str};"), span); + } + StatementKind::Constrain(ConstrainStatement(expr, message, kind)) => { + let mut nested_shape = self.shape(); + let shape = nested_shape; + + nested_shape.indent.block_indent(self.config); + + let message = message.map_or(String::new(), |message| { + let message = rewrite::sub_expr(self, nested_shape, message); + format!(", {message}") + }); + + let (callee, args) = match kind { + ConstrainKind::Assert | ConstrainKind::Constrain => { + let assertion = rewrite::sub_expr(self, nested_shape, expr); + let args = format!("{assertion}{message}"); + + ("assert", args) + } + ConstrainKind::AssertEq => { + if let ExpressionKind::Infix(infix) = expr.kind { + let lhs = rewrite::sub_expr(self, nested_shape, infix.lhs); + let rhs = rewrite::sub_expr(self, nested_shape, infix.rhs); + + let args = format!("{lhs}, {rhs}{message}"); + + ("assert_eq", args) + } else { + unreachable!() } - }; - - let args = wrap_exprs( - "(", - ")", - args, - nested_shape, - shape, - NewlineMode::IfContainsNewLineAndWidth, - ); - let constrain = format!("{callee}{args};"); - - self.push_rewrite(constrain, span); - } - StatementKind::For(for_stmt) => { - let identifier = self.slice(for_stmt.identifier.span()); - let range = match for_stmt.range { - ForRange::Range(start, end) => format!( - "{}..{}", - rewrite::sub_expr(self, self.shape(), start), - rewrite::sub_expr(self, self.shape(), end) - ), - ForRange::Array(array) => rewrite::sub_expr(self, self.shape(), array), - }; - let block = rewrite::sub_expr(self, self.shape(), 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!(), + } + }; + + let args = wrap_exprs( + "(", + ")", + args, + nested_shape, + shape, + NewlineMode::IfContainsNewLineAndWidth, + ); + let constrain = format!("{callee}{args};"); + + self.push_rewrite(constrain, span); } - - self.last_position = 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!( + "{}..{}", + rewrite::sub_expr(self, self.shape(), start), + rewrite::sub_expr(self, self.shape(), end) + ), + ForRange::Array(array) => rewrite::sub_expr(self, self.shape(), array), + }; + let block = rewrite::sub_expr(self, self.shape(), 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!(), + StatementKind::Break => self.push_rewrite("break;".into(), span), + StatementKind::Continue => self.push_rewrite("continue;".into(), span), + StatementKind::Comptime(statement) => self.visit_stmt(statement.kind, span, is_last), } } } diff --git a/tooling/nargo_fmt/tests/expected/contract.nr b/tooling/nargo_fmt/tests/expected/contract.nr index a03b8774700..97a6ebd6b77 100644 --- a/tooling/nargo_fmt/tests/expected/contract.nr +++ b/tooling/nargo_fmt/tests/expected/contract.nr @@ -8,11 +8,10 @@ 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}, + context::Context, note::{note_getter_options::NoteGetterOptions, note_header::NoteHeader}, log::emit_unencrypted_log, state_vars::{Map, PublicMutable, PrivateSet}, types::type_serialization::field_serialization::{FieldSerializationMethods, FIELD_SERIALIZED_LEN}, - types::address::{AztecAddress} + types::address::AztecAddress }; struct Storage { diff --git a/tooling/nargo_fmt/tests/expected/fn.nr b/tooling/nargo_fmt/tests/expected/fn.nr index 0088dba6a8f..3d231cd3f7f 100644 --- a/tooling/nargo_fmt/tests/expected/fn.nr +++ b/tooling/nargo_fmt/tests/expected/fn.nr @@ -36,7 +36,7 @@ fn apply_binary_field_op( registers: &mut Registers ) -> bool {} -fn main() -> distinct pub [Field; 2] {} +fn main() -> pub [Field; 2] {} fn ret_normal_lambda1() -> ((fn() -> Field)) {} diff --git a/tooling/nargo_fmt/tests/expected/impl_trait_fn_parameter.nr b/tooling/nargo_fmt/tests/expected/impl_trait_fn_parameter.nr new file mode 100644 index 00000000000..5ace5c60dcf --- /dev/null +++ b/tooling/nargo_fmt/tests/expected/impl_trait_fn_parameter.nr @@ -0,0 +1,3 @@ +fn func_name(x: impl Eq) {} + +fn func_name(x: impl Eq, y: T) where T: SomeTrait + Eq {} diff --git a/tooling/nargo_fmt/tests/expected/import_braces.nr b/tooling/nargo_fmt/tests/expected/import_braces.nr new file mode 100644 index 00000000000..49c9d09001e --- /dev/null +++ b/tooling/nargo_fmt/tests/expected/import_braces.nr @@ -0,0 +1 @@ +use dep::std::hash::sha256; diff --git a/tooling/nargo_fmt/tests/expected/turbofish_call.nr b/tooling/nargo_fmt/tests/expected/turbofish_call.nr new file mode 100644 index 00000000000..bcf0df9a969 --- /dev/null +++ b/tooling/nargo_fmt/tests/expected/turbofish_call.nr @@ -0,0 +1,8 @@ +fn foo() { + my_function::(10, some_value, another_func(20, 30)); + + outer_function::( + some_function(), // Original inner function call + another_function() // Original inner function call + ); +} diff --git a/tooling/nargo_fmt/tests/expected/turbofish_method_call.nr b/tooling/nargo_fmt/tests/expected/turbofish_method_call.nr new file mode 100644 index 00000000000..52fa3db2ac9 --- /dev/null +++ b/tooling/nargo_fmt/tests/expected/turbofish_method_call.nr @@ -0,0 +1,12 @@ +fn foo() { + my_object.some_method::(10, var_value, inner_method::(20, 30)); + + 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 index a03b8774700..97a6ebd6b77 100644 --- a/tooling/nargo_fmt/tests/input/contract.nr +++ b/tooling/nargo_fmt/tests/input/contract.nr @@ -8,11 +8,10 @@ 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}, + context::Context, note::{note_getter_options::NoteGetterOptions, note_header::NoteHeader}, log::emit_unencrypted_log, state_vars::{Map, PublicMutable, PrivateSet}, types::type_serialization::field_serialization::{FieldSerializationMethods, FIELD_SERIALIZED_LEN}, - types::address::{AztecAddress} + types::address::AztecAddress }; struct Storage { diff --git a/tooling/nargo_fmt/tests/input/fn.nr b/tooling/nargo_fmt/tests/input/fn.nr index 26ff5933802..1c6d201fa39 100644 --- a/tooling/nargo_fmt/tests/input/fn.nr +++ b/tooling/nargo_fmt/tests/input/fn.nr @@ -23,7 +23,7 @@ fn main(tape: [Field; TAPE_LEN], initial_registers: [Field; REGISTER_COUNT], ini fn apply_binary_field_op(lhs: RegisterIndex, rhs: RegisterIndex, result: RegisterIndex, op: u8, registers: &mut Registers) -> bool {} -fn main() -> distinct pub [Field;2] {} +fn main() -> pub [Field;2] {} fn ret_normal_lambda1() -> ((fn() -> Field)) {} diff --git a/tooling/nargo_fmt/tests/input/impl_trait_fn_parameter.nr b/tooling/nargo_fmt/tests/input/impl_trait_fn_parameter.nr new file mode 100644 index 00000000000..5ace5c60dcf --- /dev/null +++ b/tooling/nargo_fmt/tests/input/impl_trait_fn_parameter.nr @@ -0,0 +1,3 @@ +fn func_name(x: impl Eq) {} + +fn func_name(x: impl Eq, y: T) where T: SomeTrait + Eq {} diff --git a/tooling/nargo_fmt/tests/input/import_braces.nr b/tooling/nargo_fmt/tests/input/import_braces.nr new file mode 100644 index 00000000000..88c7e9562a8 --- /dev/null +++ b/tooling/nargo_fmt/tests/input/import_braces.nr @@ -0,0 +1 @@ +use dep::std::hash::{sha256}; \ No newline at end of file diff --git a/tooling/nargo_fmt/tests/input/turbofish_call.nr b/tooling/nargo_fmt/tests/input/turbofish_call.nr new file mode 100644 index 00000000000..03abde789fe --- /dev/null +++ b/tooling/nargo_fmt/tests/input/turbofish_call.nr @@ -0,0 +1,7 @@ +fn foo() { + my_function :: ( 10,some_value,another_func( 20 , 30) ); + + outer_function :: (some_function(), // Original inner function call + another_function(), // Original inner function call + ); +} \ No newline at end of file diff --git a/tooling/nargo_fmt/tests/input/turbofish_method_call.nr b/tooling/nargo_fmt/tests/input/turbofish_method_call.nr new file mode 100644 index 00000000000..aa7ae87f23a --- /dev/null +++ b/tooling/nargo_fmt/tests/input/turbofish_method_call.nr @@ -0,0 +1,5 @@ +fn foo() { + my_object . some_method :: ( 10,var_value,inner_method:: ( 20 , 30) ); + + assert(p4_affine.eq::(Gaffine::new::(6890855772600357754907169075114257697580319025794532037257385534741338397365, 4338620300185947561074059802482547481416142213883829469920100239455078257889))); +} \ No newline at end of file diff --git a/tooling/nargo_toml/Cargo.toml b/tooling/nargo_toml/Cargo.toml index c835ddd936c..574972d99e7 100644 --- a/tooling/nargo_toml/Cargo.toml +++ b/tooling/nargo_toml/Cargo.toml @@ -4,6 +4,7 @@ description = "Utilities for working with Nargo.toml files" version.workspace = true authors.workspace = true edition.workspace = true +rust-version.workspace = true license.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/tooling/noir_codegen/package.json b/tooling/noir_codegen/package.json index 6bb9d06f718..5d3a7d6315e 100644 --- a/tooling/noir_codegen/package.json +++ b/tooling/noir_codegen/package.json @@ -3,7 +3,7 @@ "contributors": [ "The Noir Team " ], - "version": "0.24.0", + "version": "0.30.0", "packageManager": "yarn@3.5.1", "license": "(MIT OR Apache-2.0)", "type": "module", @@ -51,13 +51,13 @@ "@types/mocha": "^10.0.1", "@types/node": "^20.6.2", "@types/prettier": "^3", - "chai": "^4.3.8", - "eslint": "^8.56.0", - "eslint-plugin-prettier": "^5.0.0", + "chai": "^4.4.1", + "eslint": "^8.57.0", + "eslint-plugin-prettier": "^5.1.3", "mocha": "^10.2.0", - "prettier": "3.0.3", + "prettier": "3.2.5", "ts-node": "^10.9.1", "tsx": "^4.6.2", - "typescript": "^5.2.2" + "typescript": "^5.4.2" } } diff --git a/tooling/noir_codegen/src/index.ts b/tooling/noir_codegen/src/index.ts index fbbab07bcfe..d00990f01bc 100644 --- a/tooling/noir_codegen/src/index.ts +++ b/tooling/noir_codegen/src/index.ts @@ -1,66 +1,17 @@ -import { AbiType } from '@noir-lang/noirc_abi'; import { CompiledCircuit } from '@noir-lang/types'; -import { PrimitiveTypesUsed, generateTsInterface, codegenStructDefinitions } from './noir_types.js'; - -// TODO: reenable this. See `abiTypeToTs` for reasoning. -// export type FixedLengthArray = L extends 0 ? never[]: T[] & { length: L }; - -const codegenPrelude = `/* Autogenerated file, do not edit! */ - -/* eslint-disable */ - -import { Noir, InputMap, CompiledCircuit, ForeignCallHandler } from "@noir-lang/noir_js" - -export { ForeignCallHandler } from "@noir-lang/noir_js" -`; - -const codegenFunction = ( - name: string, - compiled_program: CompiledCircuit, - function_signature: { inputs: [string, string][]; returnValue: string | null }, -) => { - const args = function_signature.inputs.map(([name]) => `${name}`).join(', '); - const args_with_types = function_signature.inputs.map(([name, type]) => `${name}: ${type}`).join(', '); - - return `export const ${name}_circuit: CompiledCircuit = ${JSON.stringify(compiled_program)}; - -export async function ${name}(${args_with_types}, foreignCallHandler?: ForeignCallHandler): Promise<${ - function_signature.returnValue - }> { - const program = new Noir(${name}_circuit); - const args: InputMap = { ${args} }; - const { returnValue } = await program.execute(args, foreignCallHandler); - return returnValue as ${function_signature.returnValue}; -} -`; +import { TypingsGenerator } from './utils/typings_generator.js'; + +export const codegen = ( + programs: [string, CompiledCircuit][], + embedArtifact: boolean, + useFixedLengthArrays: boolean, +): string => { + return new TypingsGenerator( + programs.map((program) => ({ + circuitName: program[0], + artifact: embedArtifact ? program[1] : undefined, + abi: structuredClone(program[1].abi), // We'll mutate the ABI types when doing typescript codegen, so we clone it to avoid mutating the artifact. + })), + useFixedLengthArrays, + ).codegen(); }; - -export const codegen = (programs: [string, CompiledCircuit][]): string => { - let results = [codegenPrelude]; - const primitiveTypeMap = new Map(); - const structTypeMap = new Map(); - - const functions: string[] = []; - for (const [name, program] of programs) { - const function_sig = generateTsInterface(program.abi, structTypeMap, primitiveTypeMap); - functions.push(codegenFunction(name, stripUnwantedFields(program), function_sig)); - } - - const structTypeDefinitions: string = codegenStructDefinitions(structTypeMap, primitiveTypeMap); - - // Add the primitive Noir types that do not have a 1-1 mapping to TypeScript. - const primitiveTypeAliases: string[] = []; - for (const value of primitiveTypeMap.values()) { - primitiveTypeAliases.push(`export type ${value.aliasName} = ${value.tsType};`); - } - - results = results.concat(...primitiveTypeAliases, '', structTypeDefinitions, ...functions); - - return results.join('\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 index 591e7420dba..835b24a9e48 100644 --- a/tooling/noir_codegen/src/main.ts +++ b/tooling/noir_codegen/src/main.ts @@ -24,7 +24,7 @@ function main() { return [program_name, { abi, bytecode }]; }); - const result = codegen(programs); + const result = codegen(programs, !cliConfig.externalArtifact, cliConfig.useFixedLengthArrays); const outputDir = path.resolve(cliConfig.outDir ?? './codegen'); const outputFile = path.join(outputDir, 'index.ts'); diff --git a/tooling/noir_codegen/src/noir_types.ts b/tooling/noir_codegen/src/noir_types.ts deleted file mode 100644 index 0c0e2b7c60f..00000000000 --- a/tooling/noir_codegen/src/noir_types.ts +++ /dev/null @@ -1,187 +0,0 @@ -import { AbiType, Abi } from '@noir-lang/noirc_abi'; - -/** - * Keep track off all of the Noir primitive types that were used. - * Most of these will not have a 1-1 definition in TypeScript, - * so we will need to generate type aliases for them. - * - * We want to generate type aliases - * for specific types that are used in the ABI. - * - * For example: - * - If `Field` is used we want to alias that - * with `number`. - * - If `u32` is used we want to alias that with `number` too. - */ -export type PrimitiveTypesUsed = { - /** - * The name of the type alias that we will generate. - */ - aliasName: string; - /** - * The TypeScript type that we will alias to. - */ - tsType: string; -}; - -/** - * Typescript does not allow us to check for equality of non-primitive types - * easily, so we create a addIfUnique function that will only add an item - * to the map if it is not already there by using JSON.stringify. - * @param item - The item to add to the map. - */ -function addIfUnique(primitiveTypeMap: Map, item: PrimitiveTypesUsed) { - const key = JSON.stringify(item); - if (!primitiveTypeMap.has(key)) { - primitiveTypeMap.set(key, item); - } -} - -/** - * Converts an ABI type to a TypeScript type. - * @param type - The ABI type to convert. - * @returns The typescript code to define the type. - */ -function abiTypeToTs(type: AbiType, primitiveTypeMap: Map): string { - switch (type.kind) { - case 'field': - addIfUnique(primitiveTypeMap, { aliasName: 'Field', tsType: 'string' }); - return 'Field'; - case 'integer': { - const typeName = type.sign === 'signed' ? `i${type.width}` : `u${type.width}`; - // Javascript cannot safely represent the full range of Noir's integer types as numbers. - // `Number.MAX_SAFE_INTEGER == 2**53 - 1` so we disallow passing numbers to types which may exceed this. - // 52 has been chosen as the cutoff rather than 53 for safety. - const tsType = type.width <= 52 ? `string | number` : `string`; - - addIfUnique(primitiveTypeMap, { aliasName: typeName, tsType }); - return typeName; - } - case 'boolean': - return `boolean`; - case 'array': - // We can't force the usage of fixed length arrays as this currently throws errors in TS. - // The array would need to be `as const` to support this whereas that's unlikely to happen in user code. - // return `FixedLengthArray<${abiTypeToTs(type.type, primitiveTypeMap)}, ${type.length}>`; - return `${abiTypeToTs(type.type, primitiveTypeMap)}[]`; - case 'string': - // We could enforce that literals are the correct length but not generally. - // This would run into similar problems to above. - return `string`; - case 'struct': - return getLastComponentOfPath(type.path); - case 'tuple': { - const field_types = type.fields.map((field) => abiTypeToTs(field, primitiveTypeMap)); - return `[${field_types.join(', ')}]`; - } - default: - throw new Error(`Unknown ABI type ${JSON.stringify(type)}`); - } -} - -/** - * Returns the last component of a path, e.g. "foo::bar::baz" -\> "baz" - * Note: that if we have a path such as "Baz", we will return "Baz". - * - * Since these paths corresponds to structs, we can assume that we - * cannot have "foo::bar::". - * - * We also make the assumption that since these paths are coming from - * Noir, then we will not have two paths that look like this: - * - foo::bar::Baz - * - cat::dog::Baz - * ie the last component of the path (struct name) is enough to uniquely identify - * the whole path. - * - * TODO: We should double check this assumption when we use type aliases, - * I expect that `foo::bar::Baz as Dog` would effectively give `foo::bar::Dog` - * @param str - The path to get the last component of. - * @returns The last component of the path. - */ -function getLastComponentOfPath(str: string): string { - const parts = str.split('::'); - const lastPart = parts[parts.length - 1]; - return lastPart; -} - -/** - * Generates TypeScript interfaces for the structs used in the ABI. - * @param type - The ABI type to generate the interface for. - * @param output - The set of structs that we have already generated bindings for. - * @returns The TypeScript code to define the struct. - */ -function generateStructInterfaces( - type: AbiType, - structsEncountered: Map, - primitiveTypeMap: Map, -) { - // Edge case to handle the array of structs case. - if ( - type.kind === 'array' && - type.type.kind === 'struct' && - !structsEncountered.has(getLastComponentOfPath(type.type.path)) - ) { - generateStructInterfaces(type.type, structsEncountered, primitiveTypeMap); - } - if (type.kind !== 'struct') return; - - const structName = getLastComponentOfPath(type.path); - if (!structsEncountered.has(structName)) { - for (const field of type.fields) { - generateStructInterfaces(field.type, structsEncountered, primitiveTypeMap); - } - structsEncountered.set(structName, type.fields); - } -} - -/** - * Generates a TypeScript interface for the ABI. - * @param abiObj - The ABI to generate the interface for. - * @returns The TypeScript code to define the interface. - */ -export function generateTsInterface( - abiObj: Abi, - structsEncountered: Map, - primitiveTypeMap: Map, -): { inputs: [string, string][]; returnValue: string | null } { - // Define structs for composite types - for (const param of abiObj.parameters) { - generateStructInterfaces(param.type, structsEncountered, primitiveTypeMap); - } - - // Generating Return type, if it exists - if (abiObj.return_type != null) { - generateStructInterfaces(abiObj.return_type.abi_type, structsEncountered, primitiveTypeMap); - } - - return getTsFunctionSignature(abiObj, primitiveTypeMap); -} - -export function codegenStructDefinitions( - structsEncountered: Map, - primitiveTypeMap: Map, -): string { - let codeGeneratedStruct = ''; - - for (const [structName, structFields] of structsEncountered) { - codeGeneratedStruct += `export type ${structName} = {\n`; - for (const field of structFields) { - codeGeneratedStruct += ` ${field.name}: ${abiTypeToTs(field.type, primitiveTypeMap)};\n`; - } - codeGeneratedStruct += `};\n\n`; - } - - return codeGeneratedStruct; -} - -function getTsFunctionSignature( - abi: Abi, - primitiveTypeMap: Map, -): { inputs: [string, string][]; returnValue: string | null } { - const inputs: [string, string][] = abi.parameters.map((param) => [ - param.name, - abiTypeToTs(param.type, primitiveTypeMap), - ]); - const returnValue = abi.return_type ? abiTypeToTs(abi.return_type.abi_type, primitiveTypeMap) : null; - return { inputs, returnValue }; -} diff --git a/tooling/noir_codegen/src/parseArgs.ts b/tooling/noir_codegen/src/parseArgs.ts index 58468c1b8f8..83b6c8bcdb2 100644 --- a/tooling/noir_codegen/src/parseArgs.ts +++ b/tooling/noir_codegen/src/parseArgs.ts @@ -6,6 +6,8 @@ export interface ParsedArgs { files: string[]; outDir?: string | undefined; inputDir?: string | undefined; + externalArtifact: boolean; + useFixedLengthArrays: boolean; } export function parseArgs(): ParsedArgs { @@ -27,6 +29,17 @@ export function parseArgs(): ParsedArgs { '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.' }, + 'external-artifact': { + type: Boolean, + defaultValue: false, + description: + 'Does not embed the circuit artifact in the code, instead requiring passing the circuit artifact as an argument to the generated functions.', + }, + 'fixed-length-arrays': { + type: Boolean, + defaultValue: false, + description: 'Use fixed-length arrays for inputs and outputs.', + }, }, { helpArg: 'help', @@ -53,6 +66,8 @@ export function parseArgs(): ParsedArgs { files: rawOptions.glob, outDir: rawOptions['out-dir'], inputDir: rawOptions['input-dir'], + externalArtifact: rawOptions['external-artifact'], + useFixedLengthArrays: rawOptions['fixed-length-arrays'], }; } @@ -61,4 +76,6 @@ interface CommandLineArgs { 'out-dir'?: string; 'input-dir'?: string; help: boolean; + 'external-artifact': boolean; + 'fixed-length-arrays': boolean; } diff --git a/tooling/noir_codegen/src/utils/abi_type_with_generics.ts b/tooling/noir_codegen/src/utils/abi_type_with_generics.ts new file mode 100644 index 00000000000..844e116f444 --- /dev/null +++ b/tooling/noir_codegen/src/utils/abi_type_with_generics.ts @@ -0,0 +1,139 @@ +import { AbiType } from '@noir-lang/noirc_abi'; + +/** + * Represents a binding to a generic. + */ +export class BindingId { + constructor( + public id: number, + public isNumeric: boolean, + ) {} +} + +export type StructType = { + path: string; + fields: { name: string; type: AbiTypeWithGenerics }[]; + /** The generics of the struct, bound to the fields */ + generics: BindingId[]; +}; + +export type StringType = { + kind: 'string'; + length: number | BindingId | null; +}; + +export type Constant = { + kind: 'constant'; + value: number; +}; + +export type ArrayType = { + kind: 'array'; + length: number | BindingId | null; + type: AbiTypeWithGenerics; +}; + +export type Tuple = { + kind: 'tuple'; + fields: AbiTypeWithGenerics[]; +}; + +export type Struct = { + kind: 'struct'; + structType: StructType; + /** The arguments are the concrete instantiation of the generics in the struct type. */ + args: AbiTypeWithGenerics[]; +}; + +export type AbiTypeWithGenerics = + | { kind: 'field' } + | { kind: 'boolean' } + | { kind: 'integer'; sign: string; width: number } + | { kind: 'binding'; id: BindingId } + | { kind: 'constant'; value: number } + | StringType + | ArrayType + | Tuple + | Struct; + +/** + * Maps an ABI type to an ABI type with generics. + * This performs pure type conversion, and does not generate any bindings. + */ +export function mapAbiTypeToAbiTypeWithGenerics(abiType: AbiType): AbiTypeWithGenerics { + switch (abiType.kind) { + case 'field': + case 'boolean': + case 'string': + case 'integer': + return abiType; + case 'array': + return { + kind: 'array', + length: abiType.length, + type: mapAbiTypeToAbiTypeWithGenerics(abiType.type), + }; + case 'struct': { + const structType = { + path: abiType.path, + fields: abiType.fields.map((field) => ({ + name: field.name, + type: mapAbiTypeToAbiTypeWithGenerics(field.type), + })), + generics: [], + }; + return { + kind: 'struct', + structType, + args: [], + }; + } + case 'tuple': + return { + kind: 'tuple', + fields: abiType.fields.map(mapAbiTypeToAbiTypeWithGenerics), + }; + default: { + const exhaustiveCheck: never = abiType; + throw new Error(`Unhandled abi type: ${exhaustiveCheck}`); + } + } +} + +/** + * Finds the structs in an ABI type. + * This won't explore nested structs. + */ +export function findStructsInType(abiType: AbiTypeWithGenerics): Struct[] { + switch (abiType.kind) { + case 'field': + case 'boolean': + case 'string': + case 'integer': + return []; + case 'array': + return findStructsInType(abiType.type); + case 'tuple': + return abiType.fields.flatMap(findStructsInType); + case 'struct': + return [abiType]; + default: { + return []; + } + } +} + +/** + * Finds all the structs in an ABI type, including nested structs. + */ +export function findAllStructsInType(abiType: AbiTypeWithGenerics): Struct[] { + let allStructs: Struct[] = []; + let lastStructs = findStructsInType(abiType); + while (lastStructs.length > 0) { + allStructs = allStructs.concat(lastStructs); + lastStructs = lastStructs.flatMap((struct) => + struct.structType.fields.flatMap((field) => findStructsInType(field.type)), + ); + } + return allStructs; +} diff --git a/tooling/noir_codegen/src/utils/demonomorphizer.ts b/tooling/noir_codegen/src/utils/demonomorphizer.ts new file mode 100644 index 00000000000..2b33b574557 --- /dev/null +++ b/tooling/noir_codegen/src/utils/demonomorphizer.ts @@ -0,0 +1,284 @@ +import { + type AbiTypeWithGenerics, + type ArrayType, + BindingId, + type Constant, + type StringType, + type Struct, + type StructType, + type Tuple, + findAllStructsInType, + findStructsInType, +} from './abi_type_with_generics.js'; + +export interface DemonomorphizerConfig { + leaveArrayLengthsUnbounded: boolean; + leaveStringLengthsUnbounded: boolean; +} + +/** + * Demonomorphizes a list of ABI types adding generics to structs. + * Since monomorphization of the generics destroys information, this process is not guaranteed to return the original structure. + * However, it should successfully unify all struct types that share the same name and field names. + */ +export class Demonomorphizer { + private variantsMap: Map; + private visitedStructs: Map; + private lastBindingId = 0; + + /** + * Demonomorphizes the passed in ABI types, mutating them. + */ + public static demonomorphize(abiTypes: AbiTypeWithGenerics[], config: DemonomorphizerConfig) { + new Demonomorphizer(abiTypes, config); + } + + private constructor( + private types: AbiTypeWithGenerics[], + private config: DemonomorphizerConfig, + ) { + this.variantsMap = new Map(); + this.fillVariantsMap(); + + this.visitedStructs = new Map(); + this.demonomorphizeStructs(); + } + + /** + * Finds all the variants of the structs in the types. + * A variant is every use of a struct with the same name and fields. + */ + private fillVariantsMap() { + const allStructs = this.types.flatMap(findAllStructsInType); + for (const struct of allStructs) { + const id = Demonomorphizer.buildIdForStruct(struct.structType); + const variants = this.variantsMap.get(id) ?? []; + variants.push(struct); + this.variantsMap.set(id, variants); + } + } + + private demonomorphizeStructs() { + for (const type of this.types) { + const topLevelStructs = findStructsInType(type); + for (const struct of topLevelStructs) { + this.demonomorphizeStruct(struct); + } + } + } + + /** + * Demonomorphizes a struct, by demonomorphizing its dependencies first. + * Then it'll unify the types of the variants generating a unique generic type. + * It'll also generate args that instantiate the generic type with the concrete arguments for each variant. + */ + private demonomorphizeStruct(struct: Struct) { + const id = Demonomorphizer.buildIdForStruct(struct.structType); + if (this.visitedStructs.has(id)) { + return; + } + const dependencies = struct.structType.fields.flatMap((field) => findStructsInType(field.type)); + for (const dependency of dependencies) { + this.demonomorphizeStruct(dependency); + } + if (this.visitedStructs.has(id)) { + throw new Error('Circular dependency detected'); + } + + const variants = this.variantsMap.get(id)!; + const mappedStructType = struct.structType; + + for (let i = 0; i < struct.structType.fields.length; i++) { + const variantTypes = variants.map((variant) => variant.structType.fields[i].type); + const mappedType = this.unifyTypes(variantTypes, mappedStructType.generics, variants); + mappedStructType.fields[i].type = mappedType; + } + + // Mutate variants setting the new struct type + variants.forEach((variant) => (variant.structType = mappedStructType)); + + this.visitedStructs.set(id, mappedStructType); + } + + /** + * Tries to unify the types of a set of variants recursively. + * Unification will imply replacing some properties with bindings and pushing bindings to the generics of the struct. + */ + private unifyTypes( + types: AbiTypeWithGenerics[], + generics: BindingId[], // Mutates generics adding new bindings + variants: Struct[], // mutates variants adding different args to the variants + ): AbiTypeWithGenerics { + const kinds = new Set(types.map((type) => type.kind)); + if (kinds.size > 1) { + return this.buildBindingAndPushToVariants(types, generics, variants); + } + switch (types[0].kind) { + case 'field': + case 'boolean': + case 'binding': + return types[0]; + case 'integer': { + if (allDeepEqual(types)) { + return types[0]; + } else { + return this.buildBindingAndPushToVariants(types, generics, variants); + } + } + case 'string': { + const strings = types as StringType[]; + const unifiedStringType = strings[0]; + if (strings.every((string) => string.length === unifiedStringType.length)) { + return unifiedStringType; + } else if (!this.config.leaveStringLengthsUnbounded) { + unifiedStringType.length = this.buildNumericBindingAndPushToVariants( + strings.map((string) => { + if (typeof string.length !== 'number') { + throw new Error('Trying to unify strings with bindings'); + } + return string.length; + }), + generics, + variants, + ); + return unifiedStringType; + } else { + unifiedStringType.length = null; + return unifiedStringType; + } + } + case 'array': { + const arrays = types as ArrayType[]; + const unifiedArrayType: ArrayType = arrays[0]; + if (!arrays.every((array) => array.length === unifiedArrayType.length)) { + if (!this.config.leaveArrayLengthsUnbounded) { + unifiedArrayType.length = this.buildNumericBindingAndPushToVariants( + arrays.map((array) => { + if (typeof array.length !== 'number') { + throw new Error('Trying to unify arrays with bindings'); + } + return array.length; + }), + generics, + variants, + ); + } else { + unifiedArrayType.length = null; + } + } + + unifiedArrayType.type = this.unifyTypes( + arrays.map((array) => array.type), + generics, + variants, + ); + return unifiedArrayType; + } + case 'tuple': { + const tuples = types as Tuple[]; + const unifiedTupleType: Tuple = tuples[0]; + for (let i = 0; i < unifiedTupleType.fields.length; i++) { + unifiedTupleType.fields[i] = this.unifyTypes( + tuples.map((tuple) => tuple.fields[i]), + generics, + variants, + ); + } + return unifiedTupleType; + } + case 'struct': { + const structs = types as Struct[]; + const ids = new Set(structs.map((struct) => Demonomorphizer.buildIdForStruct(struct.structType))); + if (ids.size > 1) { + // If the types are different structs, we can only unify them by creating a new binding. + // For example, if we have a struct A { x: u32 } and a struct A { x: Field }, the only possible unification is A { x: T } + return this.buildBindingAndPushToVariants(types, generics, variants); + } else { + // If the types are the same struct, we must unify the arguments to the struct. + // For example, if we have A and A, we need to unify to A and push T to the generics of the struct type. + const unifiedStruct = structs[0]; + + if (!structs.every((struct) => struct.args.length === unifiedStruct.args.length)) { + throw new Error('Same struct with different number of args encountered'); + } + for (let i = 0; i < unifiedStruct.args.length; i++) { + const argTypes = structs.map((struct) => struct.args[i]); + unifiedStruct.args[i] = this.unifyTypes(argTypes, generics, variants); + } + return unifiedStruct; + } + } + + case 'constant': { + const constants = types as Constant[]; + if (constants.every((constant) => constant.value === constants[0].value)) { + return constants[0]; + } else { + return this.buildBindingAndPushToVariants(types, generics, variants, true); + } + } + + default: { + const exhaustiveCheck: never = types[0]; + throw new Error(`Unhandled abi type: ${exhaustiveCheck}`); + } + } + } + + /** + * We consider a struct to be the same if it has the same name and field names. + * Structs with the same id will be unified into a single type by the demonomorphizer. + */ + public static buildIdForStruct(struct: StructType): string { + const name = struct.path.split('::').pop()!; + const fields = struct.fields.map((field) => field.name).join(','); + return `${name}(${fields})`; + } + + private buildBindingAndPushToVariants( + concreteTypes: AbiTypeWithGenerics[], + generics: BindingId[], + variants: Struct[], + isNumeric = false, + ): AbiTypeWithGenerics { + const bindingId = new BindingId(this.lastBindingId++, isNumeric); + + for (let i = 0; i < variants.length; i++) { + const variant = variants[i]; + const concreteType = concreteTypes[i]; + variant.args.push(concreteType); + } + + generics.push(bindingId); + return { kind: 'binding', id: bindingId }; + } + + private buildNumericBindingAndPushToVariants( + concreteNumbers: number[], + generics: BindingId[], + variants: Struct[], + ): BindingId { + const bindingId = new BindingId(this.lastBindingId++, true); + + for (let i = 0; i < variants.length; i++) { + const variant = variants[i]; + variant.args.push({ kind: 'constant', value: concreteNumbers[i] }); + } + + generics.push(bindingId); + return bindingId; + } +} + +function allDeepEqual(arr: T[]): boolean { + if (arr.length === 0) { + return true; + } + const first = JSON.stringify(arr[0]); + for (let i = 0; i < arr.length; i++) { + if (JSON.stringify(arr[i]) !== first) { + return false; + } + } + return true; +} diff --git a/tooling/noir_codegen/src/utils/typings_generator.ts b/tooling/noir_codegen/src/utils/typings_generator.ts new file mode 100644 index 00000000000..36d2de140f0 --- /dev/null +++ b/tooling/noir_codegen/src/utils/typings_generator.ts @@ -0,0 +1,324 @@ +import { CompiledCircuit } from '@noir-lang/types'; +import { + AbiTypeWithGenerics, + BindingId, + StructType, + findAllStructsInType, + mapAbiTypeToAbiTypeWithGenerics, +} from './abi_type_with_generics.js'; +import { Demonomorphizer } from './demonomorphizer.js'; +import { Abi } from '@noir-lang/noirc_abi'; + +const codegenPrelude = `/* Autogenerated file, do not edit! */ + +/* eslint-disable */ + +import { Noir, InputMap, CompiledCircuit, ForeignCallHandler } from "@noir-lang/noir_js" + +export { ForeignCallHandler } from "@noir-lang/noir_js" +`; +/** + * Keep track off all of the Noir primitive types that were used. + * Most of these will not have a 1-1 definition in TypeScript, + * so we will need to generate type aliases for them. + * + * We want to generate type aliases + * for specific types that are used in the ABI. + * + * For example: + * - If `Field` is used we want to alias that + * with `number`. + * - If `u32` is used we want to alias that with `number` too. + */ +type PrimitiveTypesUsed = { + /** + * The name of the type alias that we will generate. + */ + aliasName: string; + /** + * The TypeScript type that we will alias to. + */ + tsType: string; +}; + +/** + * Returns the last component of a path, e.g. "foo::bar::baz" -\> "baz" + * Note: that if we have a path such as "Baz", we will return "Baz". + * + * Since these paths corresponds to structs, we can assume that we + * cannot have "foo::bar::". + * + * We also make the assumption that since these paths are coming from + * Noir, then we will not have two paths that look like this: + * - foo::bar::Baz + * - cat::dog::Baz + * ie the last component of the path (struct name) is enough to uniquely identify + * the whole path. + * + * TODO: We should double check this assumption when we use type aliases, + * I expect that `foo::bar::Baz as Dog` would effectively give `foo::bar::Dog` + * @param str - The path to get the last component of. + * @returns The last component of the path. + */ +function getLastComponentOfPath(str: string): string { + const parts = str.split('::'); + const lastPart = parts[parts.length - 1]; + return lastPart; +} + +/** + * Replaces a numeric binding with the corresponding generics name or the actual value. + */ +function replaceNumericBinding(id: number | BindingId, genericsNameMap: Map): string { + if (typeof id === 'number') { + return id.toString(); + } else { + return genericsNameMap.get(id.id) ?? 'unknown'; + } +} + +export class TypingsGenerator { + /** All the types in the ABIs */ + private allTypes: AbiTypeWithGenerics[] = []; + /** The demonomorphized ABIs of the circuits */ + private demonomorphizedAbis: { + circuitName: string; + params: { name: string; type: AbiTypeWithGenerics }[]; + returnType?: AbiTypeWithGenerics; + artifact?: CompiledCircuit; + }[] = []; + /** Maps struct id to name for structs with the same name and different field sets */ + private structIdToTsName = new Map(); + /** Collect all the primitives used in the types to add them to the codegen */ + private primitiveTypesUsed = new Map(); + + constructor( + circuits: { abi: Abi; circuitName: string; artifact?: CompiledCircuit }[], + private useFixedLengthArrays: boolean, + ) { + // Map all the types used in the ABIs to the demonomorphized types + for (const { abi, circuitName, artifact } of circuits) { + const params = abi.parameters.map((param) => { + const type = mapAbiTypeToAbiTypeWithGenerics(param.type); + this.allTypes.push(type); + return { name: param.name, type }; + }); + if (abi.return_type) { + const returnType = mapAbiTypeToAbiTypeWithGenerics(abi.return_type.abi_type); + this.allTypes.push(returnType); + this.demonomorphizedAbis.push({ circuitName, params, returnType, artifact }); + } else { + this.demonomorphizedAbis.push({ circuitName, params, artifact }); + } + } + // Demonomorphize the types + Demonomorphizer.demonomorphize(this.allTypes, { + leaveArrayLengthsUnbounded: !useFixedLengthArrays, + leaveStringLengthsUnbounded: true, + }); + } + + public codegen(): string { + this.primitiveTypesUsed = new Map(); + const structsCode = this.codegenAllStructs(); + const interfacesCode = this.codegenAllInterfaces(); + const primitivesCode = this.codegenAllPrimitives(); + + return ` +${codegenPrelude} +${primitivesCode} +${structsCode} +${interfacesCode}`; + } + + private codegenAllStructs(): string { + const allStructs = this.allTypes.flatMap(findAllStructsInType); + // First, deduplicate the structs used + const structTypesToExport = new Map(); + for (const struct of allStructs) { + const id = Demonomorphizer.buildIdForStruct(struct.structType); + if (structTypesToExport.has(id)) { + continue; + } + structTypesToExport.set(id, struct.structType); + } + + // Then, we have to consider the case where we have struct with the same name but different fields. + // For those, we'll naively append a number to the name. + const idsPerName = new Map(); + for (const [id, structType] of structTypesToExport.entries()) { + const name = getLastComponentOfPath(structType.path); + const ids = idsPerName.get(name) ?? []; + ids.push(id); + idsPerName.set(name, ids); + } + + this.structIdToTsName = new Map(); + for (const [name, ids] of idsPerName.entries()) { + if (ids.length !== 1) { + ids.forEach((id, index) => { + this.structIdToTsName.set(id, `${name}${index + 1}`); + }); + } + } + // Now we can just generate the code for the structs + let resultCode = ''; + + for (const structType of structTypesToExport.values()) { + resultCode += this.codegenStructType(structType); + } + + return resultCode; + } + + private getStructName(structType: StructType): string { + return ( + this.structIdToTsName.get(Demonomorphizer.buildIdForStruct(structType)) || getLastComponentOfPath(structType.path) + ); + } + + private codegenStructType(structType: StructType): string { + // Generate names for the generic bindings. + const genericsNameMap = new Map(); + structType.generics.forEach((generic, index) => { + genericsNameMap.set(generic.id, String.fromCharCode('A'.charCodeAt(0) + index)); + }); + + const name = this.getStructName(structType); + const generics = structType.generics.length + ? `<${structType.generics + .map((generic) => `${genericsNameMap.get(generic.id)}${generic.isNumeric ? ' extends number' : ''}`) + .join(', ')}>` + : ''; + + let resultCode = `export type ${name}${generics} = {\n`; + + for (const field of structType.fields) { + resultCode += ` ${field.name}: ${this.codegenType(field.type, genericsNameMap)};\n`; + } + + resultCode += '}\n\n'; + + return resultCode; + } + + private codegenType(type: AbiTypeWithGenerics, genericsNameMap: Map): string { + switch (type.kind) { + case 'field': + this.addIfUnique({ aliasName: 'Field', tsType: 'string' }); + return 'Field'; + case 'boolean': + return 'boolean'; + case 'integer': { + const typeName = type.sign === 'signed' ? `i${type.width}` : `u${type.width}`; + // Even though noir accepts numbers or strings for integers, it always returns strings + // So we must use string as the type here. + this.addIfUnique({ aliasName: typeName, tsType: 'string' }); + return typeName; + } + case 'binding': + return genericsNameMap.get(type.id.id) ?? 'unknown'; + case 'constant': + return type.value.toString(); + case 'string': + return `string`; + case 'array': + if (this.useFixedLengthArrays) { + if (type.length === null) { + throw new Error('Got unbounded array with fixed length arrays enabled'); + } + return `FixedLengthArray<${this.codegenType(type.type, genericsNameMap)}, ${replaceNumericBinding( + type.length, + genericsNameMap, + )}>`; + } else { + return `${this.codegenType(type.type, genericsNameMap)}[]`; + } + case 'tuple': { + const fieldTypes = type.fields.map((field) => this.codegenType(field, genericsNameMap)); + return `[${fieldTypes.join(', ')}]`; + } + case 'struct': { + const name = this.getStructName(type.structType); + if (type.args.length) { + const args = type.args.map((arg) => this.codegenType(arg, genericsNameMap)).join(', '); + return `${name}<${args}>`; + } else { + return name; + } + } + } + } + + /** + * Typescript does not allow us to check for equality of non-primitive types + * easily, so we create a addIfUnique function that will only add an item + * to the map if it is not already there by using JSON.stringify. + * @param item - The item to add to the map. + */ + private addIfUnique(item: PrimitiveTypesUsed) { + const key = JSON.stringify(item); + if (!this.primitiveTypesUsed.has(key)) { + this.primitiveTypesUsed.set(key, item); + } + } + + /** + * Codegen all the interfaces for the circuits. + * For a circuit named Foo, we'll codegen FooInputType and FooReturnType. + */ + private codegenAllInterfaces(): string { + let resultCode = ''; + for (const { circuitName, params, returnType, artifact } of this.demonomorphizedAbis) { + const functionSignature = { + inputs: params.map((param): [string, string] => [param.name, this.codegenType(param.type, new Map())]), + returnValue: returnType ? this.codegenType(returnType, new Map()) : null, + }; + resultCode += this.codegenStructType({ + path: `${circuitName}InputType`, + fields: params, + generics: [], + }); + + if (returnType) { + resultCode += `export type ${circuitName}ReturnType = ${this.codegenType(returnType, new Map())};\n`; + } + + resultCode += codegenFunction(circuitName, functionSignature, artifact); + } + return resultCode; + } + + private codegenAllPrimitives(): string { + let primitiveTypeAliases = this.useFixedLengthArrays + ? 'export type FixedLengthArray = L extends 0 ? never[]: T[] & { length: L }\n' + : ''; + for (const [, value] of this.primitiveTypesUsed) { + primitiveTypeAliases += `export type ${value.aliasName} = ${value.tsType};\n`; + } + return primitiveTypeAliases; + } +} + +const codegenFunction = ( + name: string, + function_signature: { inputs: [string, string][]; returnValue: string | null }, + compiled_program?: CompiledCircuit, +): string => { + const args = function_signature.inputs.map(([name]) => `${name}`).join(', '); + const args_with_types = function_signature.inputs.map(([name, type]) => `${name}: ${type}`).join(', '); + + const artifact = compiled_program + ? `export const ${name}_circuit: CompiledCircuit = ${JSON.stringify(compiled_program)};` + : ''; + + return `${artifact} + +export async function ${name}(${args_with_types}${compiled_program ? '' : `, ${name}_circuit: CompiledCircuit`}, foreignCallHandler?: ForeignCallHandler): Promise<${function_signature.returnValue}> { + const program = new Noir(${name}_circuit); + const args: InputMap = { ${args} }; + const { returnValue } = await program.execute(args, foreignCallHandler); + return returnValue as ${function_signature.returnValue}; +} +`; +}; diff --git a/tooling/noir_codegen/test/index.test.ts b/tooling/noir_codegen/test/index.test.ts index 03fb680a537..afc7769ed9e 100644 --- a/tooling/noir_codegen/test/index.test.ts +++ b/tooling/noir_codegen/test/index.test.ts @@ -1,18 +1,18 @@ import { expect } from 'chai'; // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore File is codegenned at test time. -import { exported_function_foo, MyStruct, u64, ForeignCallHandler } from './codegen/index.js'; +import { exported_function_foo, MyStruct, u64, u32, ForeignCallHandler } from './codegen/index.js'; it('codegens a callable function', async () => { - const my_struct = { foo: true, bar: ['12345', '12345', '12345'], baz: '0x00' }; + const my_struct = { foo: true, bar: ['123', '123', '123', '123'], baz: '0x00' }; - const [sum, constant, struct]: [u64, u64, MyStruct] = await exported_function_foo( + const [sum, constant, struct]: [u64, u32, MyStruct] = await exported_function_foo( '2', '3', - [0, 0, 0, 0, 0], + ['0x00', '0x00', '0x00', '0x00', '0x00'], { foo: my_struct, - bar: [my_struct, my_struct, my_struct], + bar: [my_struct, my_struct], baz: '64', }, '12345', @@ -35,15 +35,15 @@ it('allows passing a custom foreign call handler', async () => { return []; }; - const my_struct = { foo: true, bar: ['12345', '12345', '12345'], baz: '0x00' }; + const my_struct = { foo: true, bar: ['123', '123', '123', '123'], baz: '0x00' }; - const [sum, constant, struct]: [u64, u64, MyStruct] = await exported_function_foo( + const [sum, constant, struct]: [u64, u32, MyStruct] = await exported_function_foo( '2', '3', - [0, 0, 0, 0, 0], + ['0x00', '0x00', '0x00', '0x00', '0x00'], { foo: my_struct, - bar: [my_struct, my_struct, my_struct], + bar: [my_struct, my_struct], baz: '64', }, '12345', diff --git a/tooling/noir_codegen/test/test_lib/src/lib.nr b/tooling/noir_codegen/test/test_lib/src/lib.nr index 23607c6f65f..4915b0a2c49 100644 --- a/tooling/noir_codegen/test/test_lib/src/lib.nr +++ b/tooling/noir_codegen/test/test_lib/src/lib.nr @@ -1,17 +1,23 @@ -struct MyStruct { +struct MyStruct { foo: bool, - bar: [str<5>; 3], + bar: [str; BAR_SIZE], baz: Field } -struct NestedStruct { - foo: MyStruct, - bar: [MyStruct; 3], - baz: u64 +struct NestedStruct { + foo: MyStruct, + bar: [MyStruct; BAR_SIZE], + baz: BAZ_TYP } #[export] -fn exported_function_foo(x: u64, y: u64, array: [u8; 5], my_struct: NestedStruct, string: str<5>) -> (u64, u64, MyStruct) { +fn exported_function_foo( + x: u64, + y: u64, + array: [u8; 5], + my_struct: NestedStruct<2,3,4, Field>, + string: str<5> +) -> (u64, u32, MyStruct<3, 4>) { assert(array.len() == 5); assert(my_struct.foo.foo); assert(string == "12345"); @@ -22,6 +28,6 @@ fn exported_function_foo(x: u64, y: u64, array: [u8; 5], my_struct: NestedStruct } #[export] -fn exported_function_bar(my_struct: NestedStruct) -> (u64) { +fn exported_function_bar(my_struct: NestedStruct<1,2,3, u64>) -> (u64) { my_struct.baz } diff --git a/tooling/noir_js/package.json b/tooling/noir_js/package.json index 6f1899fae52..eca3f29957f 100644 --- a/tooling/noir_js/package.json +++ b/tooling/noir_js/package.json @@ -3,7 +3,7 @@ "contributors": [ "The Noir Team " ], - "version": "0.24.0", + "version": "0.30.0", "packageManager": "yarn@3.5.1", "license": "(MIT OR Apache-2.0)", "type": "module", @@ -53,14 +53,14 @@ "@types/mocha": "^10.0.1", "@types/node": "^20.6.2", "@types/prettier": "^3", - "chai": "^4.3.8", - "eslint": "^8.56.0", - "eslint-plugin-prettier": "^5.0.0", + "chai": "^4.4.1", + "eslint": "^8.57.0", + "eslint-plugin-prettier": "^5.1.3", "mocha": "^10.2.0", - "prettier": "3.0.3", + "prettier": "3.2.5", "ts-node": "^10.9.1", "tsc-multi": "^1.1.0", "tsx": "^4.6.2", - "typescript": "^5.2.2" + "typescript": "^5.4.2" } } diff --git a/tooling/noir_js/scripts/compile_test_programs.sh b/tooling/noir_js/scripts/compile_test_programs.sh index 5257aaae696..0642159aa69 100755 --- a/tooling/noir_js/scripts/compile_test_programs.sh +++ b/tooling/noir_js/scripts/compile_test_programs.sh @@ -3,3 +3,5 @@ rm -rf ./test/noir_compiled_examples/**/target nargo --program-dir ./test/noir_compiled_examples/assert_lt compile --force nargo --program-dir ./test/noir_compiled_examples/assert_msg_runtime compile --force +nargo --program-dir ./test/noir_compiled_examples/fold_fibonacci compile --force +nargo --program-dir ./test/noir_compiled_examples/assert_raw_payload compile --force diff --git a/tooling/noir_js/src/index.ts b/tooling/noir_js/src/index.ts index bacb391a464..1feca8fa275 100644 --- a/tooling/noir_js/src/index.ts +++ b/tooling/noir_js/src/index.ts @@ -1,6 +1,6 @@ import * as acvm from '@noir-lang/acvm_js'; import * as abi from '@noir-lang/noirc_abi'; -import { CompiledCircuit, ProofData } from '@noir-lang/types'; +import { CompiledCircuit } from '@noir-lang/types'; export { ecdsa_secp256r1_verify, @@ -16,9 +16,10 @@ export { InputMap } from '@noir-lang/noirc_abi'; export { WitnessMap, ForeignCallHandler, ForeignCallInput, ForeignCallOutput } from '@noir-lang/acvm_js'; export { Noir } from './program.js'; +export { ErrorWithPayload } from './witness_generation.js'; /** @ignore */ export { acvm, abi }; // type exports for typedoc -export { CompiledCircuit, ProofData }; +export { CompiledCircuit }; diff --git a/tooling/noir_js/src/program.ts b/tooling/noir_js/src/program.ts index 8d80ec3a247..accd89dc385 100644 --- a/tooling/noir_js/src/program.ts +++ b/tooling/noir_js/src/program.ts @@ -1,14 +1,10 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -import { Backend, CompiledCircuit, ProofData } from '@noir-lang/types'; +import { CompiledCircuit } from '@noir-lang/types'; import { generateWitness } from './witness_generation.js'; import initAbi, { abiDecode, InputMap, InputValue } from '@noir-lang/noirc_abi'; -import initACVM, { compressWitness, ForeignCallHandler } from '@noir-lang/acvm_js'; +import initACVM, { compressWitnessStack, ForeignCallHandler } from '@noir-lang/acvm_js'; export class Noir { - constructor( - private circuit: CompiledCircuit, - private backend?: Backend, - ) {} + constructor(private circuit: CompiledCircuit) {} /** @ignore */ async init(): Promise { @@ -20,27 +16,6 @@ export class Noir { } } - /** - * - * @description - * Destroys the underlying backend instance. - * - * @example - * ```typescript - * await noir.destroy(); - * ``` - * - */ - async destroy(): Promise { - await this.backend?.destroy(); - } - - private getBackend(): Backend { - if (this.backend === undefined) throw new Error('Operation requires a backend but none was provided'); - return this.backend; - } - - // Initial inputs to your program /** * @description * Allows to execute a circuit to get its witness and return value. @@ -55,40 +30,9 @@ export class Noir { foreignCallHandler?: ForeignCallHandler, ): Promise<{ witness: Uint8Array; returnValue: InputValue }> { await this.init(); - const witness = await generateWitness(this.circuit, inputs, foreignCallHandler); - const { return_value: returnValue } = abiDecode(this.circuit.abi, witness); - return { witness: compressWitness(witness), returnValue }; - } - - /** - * - * @description - * Generates a witness and a proof given an object as input. - * - * @example - * ```typescript - * async generateProof(input) - * ``` - * - */ - async generateProof(inputs: InputMap, foreignCallHandler?: ForeignCallHandler): Promise { - const { witness } = await this.execute(inputs, foreignCallHandler); - return this.getBackend().generateProof(witness); - } - - /** - * - * @description - * Instantiates the verification key and verifies a proof. - * - * - * @example - * ```typescript - * async verifyProof(proof) - * ``` - * - */ - async verifyProof(proofData: ProofData): Promise { - return this.getBackend().verifyProof(proofData); + const witness_stack = await generateWitness(this.circuit, inputs, foreignCallHandler); + const main_witness = witness_stack[0].witness; + const { return_value: returnValue } = abiDecode(this.circuit.abi, main_witness); + return { witness: compressWitnessStack(witness_stack), returnValue }; } } diff --git a/tooling/noir_js/src/witness_generation.ts b/tooling/noir_js/src/witness_generation.ts index cef1d817d9b..c84cb2e83b3 100644 --- a/tooling/noir_js/src/witness_generation.ts +++ b/tooling/noir_js/src/witness_generation.ts @@ -1,23 +1,7 @@ -import { abiEncode, InputMap } from '@noir-lang/noirc_abi'; +import { abiDecodeError, abiEncode, InputMap } from '@noir-lang/noirc_abi'; import { base64Decode } from './base64_decode.js'; -import { - WitnessMap, - ForeignCallHandler, - ForeignCallInput, - createBlackBoxSolver, - WasmBlackBoxFunctionSolver, - executeCircuitWithBlackBoxSolver, -} from '@noir-lang/acvm_js'; -import { CompiledCircuit } from '@noir-lang/types'; - -let solver: Promise; - -const getSolver = (): Promise => { - if (!solver) { - solver = createBlackBoxSolver(); - } - return solver; -}; +import { WitnessStack, ForeignCallHandler, ForeignCallInput, ExecutionError, executeProgram } from '@noir-lang/acvm_js'; +import { Abi, CompiledCircuit } from '@noir-lang/types'; const defaultForeignCallHandler: ForeignCallHandler = async (name: string, args: ForeignCallInput[]) => { if (name == 'print') { @@ -26,36 +10,56 @@ const defaultForeignCallHandler: ForeignCallHandler = async (name: string, args: // // If a user needs to print values then they should provide a custom foreign call handler. return []; - } else if (name == 'assert_message') { - // By default we do not do anything for `assert_message` foreign calls due to a need for formatting, - // however we provide an empty response in order to not halt execution. - // - // If a user needs to use dynamic assertion messages then they should provide a custom foreign call handler. - return []; } throw Error(`Unexpected oracle during execution: ${name}(${args.join(', ')})`); }; +// Payload is any since it can be of any type defined by the circuit dev. +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export type ErrorWithPayload = ExecutionError & { decodedAssertionPayload?: any }; + +function parseErrorPayload(abi: Abi, originalError: ExecutionError): Error { + const payload = originalError.rawAssertionPayload; + if (!payload) return originalError; + const enrichedError = originalError as ErrorWithPayload; + + try { + // Decode the payload + const decodedPayload = abiDecodeError(abi, payload); + + if (typeof decodedPayload === 'string') { + // If it's a string, just add it to the error message + enrichedError.message = `Circuit execution failed: ${decodedPayload}`; + } else { + // If not, attach the payload to the original error + enrichedError.decodedAssertionPayload = decodedPayload; + } + } catch (_errorDecoding) { + // Ignore errors decoding the payload + } + + return enrichedError; +} + // Generates the witnesses needed to feed into the chosen proving system export async function generateWitness( compiledProgram: CompiledCircuit, inputs: InputMap, foreignCallHandler: ForeignCallHandler = defaultForeignCallHandler, -): Promise { +): 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 executeCircuitWithBlackBoxSolver( - await getSolver(), - base64Decode(compiledProgram.bytecode), - witnessMap, - foreignCallHandler, - ); + const solvedWitness = await executeProgram(base64Decode(compiledProgram.bytecode), witnessMap, foreignCallHandler); return solvedWitness; } catch (err) { + // Typescript types catched errors as unknown or any, so we need to narrow its type to check if it has raw assertion payload. + if (typeof err === 'object' && err !== null && 'rawAssertionPayload' in err) { + throw parseErrorPayload(compiledProgram.abi, err as ExecutionError); + } throw new Error(`Circuit execution failed: ${err}`); } } diff --git a/tooling/noir_js/test/node/execute.test.ts b/tooling/noir_js/test/node/execute.test.ts index 491bcb0dfc4..7c93a911042 100644 --- a/tooling/noir_js/test/node/execute.test.ts +++ b/tooling/noir_js/test/node/execute.test.ts @@ -1,13 +1,17 @@ import assert_lt_json from '../noir_compiled_examples/assert_lt/target/assert_lt.json' assert { type: 'json' }; import assert_msg_json from '../noir_compiled_examples/assert_msg_runtime/target/assert_msg_runtime.json' assert { type: 'json' }; -import { Noir } from '@noir-lang/noir_js'; +import fold_fibonacci_json from '../noir_compiled_examples/fold_fibonacci/target/fold_fibonacci.json' assert { type: 'json' }; +import assert_raw_payload_json from '../noir_compiled_examples/assert_raw_payload/target/assert_raw_payload.json' assert { type: 'json' }; + +import { Noir, ErrorWithPayload } from '@noir-lang/noir_js'; import { CompiledCircuit } from '@noir-lang/types'; import { expect } from 'chai'; const assert_lt_program = assert_lt_json as CompiledCircuit; const assert_msg_runtime = assert_msg_json as CompiledCircuit; +const fold_fibonacci_program = fold_fibonacci_json as CompiledCircuit; -it('returns the return value of the circuit', async () => { +it('executes a single-ACIR program correctly', async () => { const inputs = { x: '2', y: '3', @@ -17,13 +21,109 @@ it('returns the return value of the circuit', async () => { expect(returnValue).to.be.eq('0x05'); }); -it('circuit with a dynamic assert message should fail on an assert failure not the foreign call handler', async () => { +it('circuit with a fmt string assert message should fail with the resolved assertion message', async () => { const inputs = { x: '10', y: '5', }; try { await new Noir(assert_msg_runtime).execute(inputs); + } catch (error) { + const knownError = error as Error; + expect(knownError.message).to.equal('Circuit execution failed: Expected x < y but got 10 < 5'); + } +}); + +it('circuit with a raw assert payload should fail with the decoded payload', async () => { + const inputs = { + x: '7', + y: '5', + }; + try { + await new Noir(assert_raw_payload_json).execute(inputs); + } catch (error) { + const knownError = error as ErrorWithPayload; + const invalidXYErrorSelector = Object.keys(assert_raw_payload_json.abi.error_types)[0]; + expect(knownError.rawAssertionPayload!.selector).to.equal(invalidXYErrorSelector); + expect(knownError.decodedAssertionPayload).to.deep.equal({ + x: '0x07', + y: '0x05', + }); + } +}); + +it('successfully executes a program with multiple acir circuits', async () => { + const inputs = { + x: '10', + }; + try { + await new Noir(fold_fibonacci_program).execute(inputs); + } catch (error) { + const knownError = error as Error; + expect(knownError.message).to.equal('Circuit execution failed: Expected x < y but got 10 < 5'); + } +}); + +it('circuit with a raw assert payload should fail with the decoded payload', async () => { + const inputs = { + x: '7', + y: '5', + }; + try { + await new Noir(assert_raw_payload_json).execute(inputs); + } catch (error) { + const knownError = error as ErrorWithPayload; + const invalidXYErrorSelector = Object.keys(assert_raw_payload_json.abi.error_types)[0]; + expect(knownError.rawAssertionPayload!.selector).to.equal(invalidXYErrorSelector); + expect(knownError.decodedAssertionPayload).to.deep.equal({ + x: '0x07', + y: '0x05', + }); + } +}); + +it('successfully executes a program with multiple acir circuits', async () => { + const inputs = { + x: '10', + }; + try { + await new Noir(fold_fibonacci_program).execute(inputs); + } catch (error) { + const knownError = error as Error; + expect(knownError.message).to.equal('Circuit execution failed: Error: Cannot satisfy constraint'); + } +}); + +it('successfully executes a program with multiple acir circuits', async () => { + const inputs = { + x: '10', + }; + try { + await new Noir(fold_fibonacci_program).execute(inputs); + } catch (error) { + const knownError = error as Error; + expect(knownError.message).to.equal('Circuit execution failed: Error: Cannot satisfy constraint'); + } +}); + +it('successfully executes a program with multiple acir circuits', async () => { + const inputs = { + x: '10', + }; + try { + await new Noir(fold_fibonacci_program).execute(inputs); + } catch (error) { + const knownError = error as Error; + expect(knownError.message).to.equal('Circuit execution failed: Error: Cannot satisfy constraint'); + } +}); + +it('successfully executes a program with multiple acir circuits', async () => { + const inputs = { + x: '10', + }; + try { + await new Noir(fold_fibonacci_program).execute(inputs); } catch (error) { const knownError = error as Error; expect(knownError.message).to.equal('Circuit execution failed: Error: Cannot satisfy constraint'); diff --git a/tooling/noir_js/test/noir_compiled_examples/assert_msg_runtime/src/main.nr b/tooling/noir_js/test/noir_compiled_examples/assert_msg_runtime/src/main.nr index 40e447cad02..0bcd5c58c24 100644 --- a/tooling/noir_js/test/noir_compiled_examples/assert_msg_runtime/src/main.nr +++ b/tooling/noir_js/test/noir_compiled_examples/assert_msg_runtime/src/main.nr @@ -1,6 +1,4 @@ fn main(x: u64, y: pub u64) { - // A dynamic assertion message is used to show that noirJS will ignore the call and continue execution - // We need this assertion to fail as the `assert_message` oracle in Noir is only called - // upon a failing condition in an assert. + // A fmtstr assertion message is used to show that noirJS will decode the error payload as a string. assert(x < y, f"Expected x < y but got {x} < {y}"); } diff --git a/tooling/noir_js/test/noir_compiled_examples/assert_raw_payload/Nargo.toml b/tooling/noir_js/test/noir_compiled_examples/assert_raw_payload/Nargo.toml new file mode 100644 index 00000000000..f88832264ea --- /dev/null +++ b/tooling/noir_js/test/noir_compiled_examples/assert_raw_payload/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "assert_raw_payload" +type = "bin" +authors = [""] +compiler_version = ">=0.23.0" + +[dependencies] diff --git a/tooling/noir_js/test/noir_compiled_examples/assert_raw_payload/src/main.nr b/tooling/noir_js/test/noir_compiled_examples/assert_raw_payload/src/main.nr new file mode 100644 index 00000000000..4c981330b31 --- /dev/null +++ b/tooling/noir_js/test/noir_compiled_examples/assert_raw_payload/src/main.nr @@ -0,0 +1,9 @@ +struct InvalidXYError { + x: u64, + y: u64, +} + +fn main(x: u64, y: pub u64) { + // A raw assertion payload is used to show that noirJS will decode the error payload as a struct. + assert(x < y, InvalidXYError { x, y }); +} diff --git a/tooling/noir_js/test/noir_compiled_examples/fold_fibonacci/Nargo.toml b/tooling/noir_js/test/noir_compiled_examples/fold_fibonacci/Nargo.toml new file mode 100644 index 00000000000..6d8214689b0 --- /dev/null +++ b/tooling/noir_js/test/noir_compiled_examples/fold_fibonacci/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "fold_fibonacci" +type = "bin" +authors = [""] +compiler_version = ">=0.28.0" + +[dependencies] \ No newline at end of file diff --git a/tooling/noir_js/test/noir_compiled_examples/fold_fibonacci/src/main.nr b/tooling/noir_js/test/noir_compiled_examples/fold_fibonacci/src/main.nr new file mode 100644 index 00000000000..e150a586086 --- /dev/null +++ b/tooling/noir_js/test/noir_compiled_examples/fold_fibonacci/src/main.nr @@ -0,0 +1,12 @@ +fn main(x: u32) { + assert(fibonacci(x) == 55); +} + +#[fold] +fn fibonacci(x: u32) -> u32 { + if x <= 1 { + x + } else { + fibonacci(x - 1) + fibonacci(x - 2) + } +} diff --git a/tooling/noir_js_backend_barretenberg/package.json b/tooling/noir_js_backend_barretenberg/package.json index 28c3609fd14..10fd14a0090 100644 --- a/tooling/noir_js_backend_barretenberg/package.json +++ b/tooling/noir_js_backend_barretenberg/package.json @@ -3,7 +3,7 @@ "contributors": [ "The Noir Team " ], - "version": "0.24.0", + "version": "0.30.0", "packageManager": "yarn@3.5.1", "license": "(MIT OR Apache-2.0)", "type": "module", @@ -42,19 +42,19 @@ "lint": "NODE_NO_WARNINGS=1 eslint . --ext .ts --ignore-path ./.eslintignore --max-warnings 0" }, "dependencies": { - "@aztec/bb.js": "0.24.0", + "@aztec/bb.js": "0.41.0", "@noir-lang/types": "workspace:*", "fflate": "^0.8.0" }, "devDependencies": { "@types/node": "^20.6.2", "@types/prettier": "^3", - "chai": "^4.3.8", - "eslint": "^8.56.0", - "eslint-plugin-prettier": "^5.0.0", + "chai": "^4.4.1", + "eslint": "^8.57.0", + "eslint-plugin-prettier": "^5.1.3", "mocha": "^10.2.0", - "prettier": "3.0.3", + "prettier": "3.2.5", "ts-node": "^10.9.1", - "typescript": "5.1.5" + "typescript": "5.4.2" } } diff --git a/tooling/noir_js_backend_barretenberg/src/backend.ts b/tooling/noir_js_backend_barretenberg/src/backend.ts new file mode 100644 index 00000000000..d07681dd8c1 --- /dev/null +++ b/tooling/noir_js_backend_barretenberg/src/backend.ts @@ -0,0 +1,143 @@ +import { decompressSync as gunzip } from 'fflate'; +import { acirToUint8Array } from './serialize.js'; +import { Backend, CompiledCircuit, ProofData, VerifierBackend } from '@noir-lang/types'; +import { BackendOptions } from './types.js'; +import { deflattenPublicInputs } from './public_inputs.js'; +import { reconstructProofWithPublicInputs } from './verifier.js'; +import { type Barretenberg } from '@aztec/bb.js'; + +// This is the number of bytes in a UltraPlonk proof +// minus the public inputs. +const numBytesInProofWithoutPublicInputs: number = 2144; + +export class BarretenbergVerifierBackend implements VerifierBackend { + // These type assertions are used so that we don't + // have to initialize `api` and `acirComposer` in the constructor. + // These are initialized asynchronously in the `init` function, + // constructors cannot be asynchronous which is why we do this. + + protected api!: Barretenberg; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + protected acirComposer: any; + protected acirUncompressedBytecode: Uint8Array; + + constructor( + acirCircuit: CompiledCircuit, + protected options: BackendOptions = { threads: 1 }, + ) { + const acirBytecodeBase64 = acirCircuit.bytecode; + this.acirUncompressedBytecode = acirToUint8Array(acirBytecodeBase64); + } + + /** @ignore */ + async instantiate(): Promise { + if (!this.api) { + if (typeof navigator !== 'undefined' && navigator.hardwareConcurrency) { + this.options.threads = navigator.hardwareConcurrency; + } else { + try { + const os = await import('os'); + this.options.threads = os.cpus().length; + } catch (e) { + console.log('Could not detect environment. Falling back to one thread.', e); + } + } + const { Barretenberg, RawBuffer, Crs } = await import('@aztec/bb.js'); + const api = await Barretenberg.new(this.options); + + const [_exact, _total, subgroupSize] = await api.acirGetCircuitSizes(this.acirUncompressedBytecode); + const crs = await Crs.new(subgroupSize + 1); + await api.commonInitSlabAllocator(subgroupSize); + 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; + } + } + + /** @description Verifies a proof */ + async verifyProof(proofData: ProofData): Promise { + const proof = reconstructProofWithPublicInputs(proofData); + await this.instantiate(); + await this.api.acirInitVerificationKey(this.acirComposer); + return await this.api.acirVerifyProof(this.acirComposer, proof); + } + + async getVerificationKey(): Promise { + await this.instantiate(); + await this.api.acirInitVerificationKey(this.acirComposer); + return await this.api.acirGetVerificationKey(this.acirComposer); + } + + async destroy(): Promise { + if (!this.api) { + return; + } + await this.api.destroy(); + } +} + +export class BarretenbergBackend extends BarretenbergVerifierBackend implements Backend { + /** @description Generates a proof */ + async generateProof(compressedWitness: Uint8Array): Promise { + await this.instantiate(); + const proofWithPublicInputs = await this.api.acirCreateProof( + this.acirComposer, + this.acirUncompressedBytecode, + gunzip(compressedWitness), + ); + + const splitIndex = proofWithPublicInputs.length - numBytesInProofWithoutPublicInputs; + + const publicInputsConcatenated = proofWithPublicInputs.slice(0, splitIndex); + const proof = proofWithPublicInputs.slice(splitIndex); + const publicInputs = deflattenPublicInputs(publicInputsConcatenated); + + return { proof, publicInputs }; + } + + /** + * Generates artifacts that will be passed to a circuit that will verify this proof. + * + * Instead of passing the proof and verification key as a byte array, we pass them + * as fields which makes it cheaper to verify in a circuit. + * + * The proof that is passed here will have been created using a circuit + * that has the #[recursive] attribute on its `main` method. + * + * The number of public inputs denotes how many public inputs are in the inner proof. + * + * @example + * ```typescript + * const artifacts = await backend.generateRecursiveProofArtifacts(proof, numOfPublicInputs); + * ``` + */ + async generateRecursiveProofArtifacts( + proofData: ProofData, + numOfPublicInputs = 0, + ): Promise<{ + proofAsFields: string[]; + vkAsFields: string[]; + vkHash: string; + }> { + await this.instantiate(); + const proof = reconstructProofWithPublicInputs(proofData); + const proofAsFields = ( + await this.api.acirSerializeProofIntoFields(this.acirComposer, proof, numOfPublicInputs) + ).slice(numOfPublicInputs); + + // TODO: perhaps we should put this in the init function. Need to benchmark + // TODO how long it takes. + await this.api.acirInitVerificationKey(this.acirComposer); + + // Note: If you don't init verification key, `acirSerializeVerificationKeyIntoFields`` will just hang on serialization + const vk = await this.api.acirSerializeVerificationKeyIntoFields(this.acirComposer); + + return { + proofAsFields: proofAsFields.map((p) => p.toString()), + vkAsFields: vk[0].map((vk) => vk.toString()), + vkHash: vk[1].toString(), + }; + } +} diff --git a/tooling/noir_js_backend_barretenberg/src/index.ts b/tooling/noir_js_backend_barretenberg/src/index.ts index d79b487c3cf..f28abb9a658 100644 --- a/tooling/noir_js_backend_barretenberg/src/index.ts +++ b/tooling/noir_js_backend_barretenberg/src/index.ts @@ -1,141 +1,7 @@ -import { decompressSync as gunzip } from 'fflate'; -import { acirToUint8Array } from './serialize.js'; -import { Backend, CompiledCircuit, ProofData } from '@noir-lang/types'; -import { BackendOptions } from './types.js'; -import { deflattenPublicInputs, flattenPublicInputsAsArray } from './public_inputs.js'; -import { type Barretenberg } from '@aztec/bb.js'; - +export { BarretenbergBackend } from './backend.js'; +export { BarretenbergVerifier } from './verifier.js'; export { publicInputsToWitnessMap } from './public_inputs.js'; -// This is the number of bytes in a UltraPlonk proof -// minus the public inputs. -const numBytesInProofWithoutPublicInputs: number = 2144; - -export class BarretenbergBackend implements Backend { - // These type assertions are used so that we don't - // have to initialize `api` and `acirComposer` in the constructor. - // These are initialized asynchronously in the `init` function, - // constructors cannot be asynchronous which is why we do this. - - private api!: Barretenberg; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - private acirComposer: any; - private acirUncompressedBytecode: Uint8Array; - - constructor( - acirCircuit: CompiledCircuit, - private options: BackendOptions = { threads: 1 }, - ) { - const acirBytecodeBase64 = acirCircuit.bytecode; - this.acirUncompressedBytecode = acirToUint8Array(acirBytecodeBase64); - } - - /** @ignore */ - async instantiate(): Promise { - if (!this.api) { - const { Barretenberg, RawBuffer, Crs } = await import('@aztec/bb.js'); - const api = await Barretenberg.new({ threads: this.options.threads }); - - const [_exact, _total, subgroupSize] = await api.acirGetCircuitSizes(this.acirUncompressedBytecode); - const crs = await Crs.new(subgroupSize + 1); - await api.commonInitSlabAllocator(subgroupSize); - 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; - } - } - - /** @description Generates a proof */ - async generateProof(compressedWitness: Uint8Array): Promise { - await this.instantiate(); - // TODO: Change once `@aztec/bb.js` version is updated to use methods without isRecursive flag - const proofWithPublicInputs = await this.api.acirCreateProof( - this.acirComposer, - this.acirUncompressedBytecode, - gunzip(compressedWitness), - ); - - const splitIndex = proofWithPublicInputs.length - numBytesInProofWithoutPublicInputs; - - const publicInputsConcatenated = proofWithPublicInputs.slice(0, splitIndex); - const proof = proofWithPublicInputs.slice(splitIndex); - const publicInputs = deflattenPublicInputs(publicInputsConcatenated); - - return { proof, publicInputs }; - } - - /** - * Generates artifacts that will be passed to a circuit that will verify this proof. - * - * Instead of passing the proof and verification key as a byte array, we pass them - * as fields which makes it cheaper to verify in a circuit. - * - * The proof that is passed here will have been created using a circuit - * that has the #[recursive] attribute on its `main` method. - * - * The number of public inputs denotes how many public inputs are in the inner proof. - * - * @example - * ```typescript - * const artifacts = await backend.generateRecursiveProofArtifacts(proof, numOfPublicInputs); - * ``` - */ - async generateRecursiveProofArtifacts( - proofData: ProofData, - numOfPublicInputs = 0, - ): Promise<{ - proofAsFields: string[]; - vkAsFields: string[]; - vkHash: string; - }> { - await this.instantiate(); - const proof = reconstructProofWithPublicInputs(proofData); - const proofAsFields = ( - await this.api.acirSerializeProofIntoFields(this.acirComposer, proof, numOfPublicInputs) - ).slice(numOfPublicInputs); - - // TODO: perhaps we should put this in the init function. Need to benchmark - // TODO how long it takes. - await this.api.acirInitVerificationKey(this.acirComposer); - - // Note: If you don't init verification key, `acirSerializeVerificationKeyIntoFields`` will just hang on serialization - const vk = await this.api.acirSerializeVerificationKeyIntoFields(this.acirComposer); - - return { - proofAsFields: proofAsFields.map((p) => p.toString()), - vkAsFields: vk[0].map((vk) => vk.toString()), - vkHash: vk[1].toString(), - }; - } - - /** @description Verifies a proof */ - async verifyProof(proofData: ProofData): Promise { - const proof = reconstructProofWithPublicInputs(proofData); - await this.instantiate(); - await this.api.acirInitVerificationKey(this.acirComposer); - // TODO: Change once `@aztec/bb.js` version is updated to use methods without isRecursive flag - return await this.api.acirVerifyProof(this.acirComposer, proof); - } - - async destroy(): Promise { - if (!this.api) { - return; - } - await this.api.destroy(); - } -} - -function reconstructProofWithPublicInputs(proofData: ProofData): Uint8Array { - // Flatten publicInputs - const publicInputsConcatenated = flattenPublicInputsAsArray(proofData.publicInputs); - - // Concatenate publicInputs and proof - const proofWithPublicInputs = Uint8Array.from([...publicInputsConcatenated, ...proofData.proof]); - - return proofWithPublicInputs; -} - // typedoc exports -export { Backend, BackendOptions, CompiledCircuit, ProofData }; +export { Backend, CompiledCircuit, ProofData } from '@noir-lang/types'; +export { BackendOptions } from './types.js'; diff --git a/tooling/noir_js_backend_barretenberg/src/types.ts b/tooling/noir_js_backend_barretenberg/src/types.ts index 041e36fdf91..fac23030aad 100644 --- a/tooling/noir_js_backend_barretenberg/src/types.ts +++ b/tooling/noir_js_backend_barretenberg/src/types.ts @@ -5,4 +5,5 @@ export type BackendOptions = { /** @description Number of threads */ threads: number; + memory?: { maximum: number }; }; diff --git a/tooling/noir_js_backend_barretenberg/src/verifier.ts b/tooling/noir_js_backend_barretenberg/src/verifier.ts new file mode 100644 index 00000000000..fe9fa9cfffd --- /dev/null +++ b/tooling/noir_js_backend_barretenberg/src/verifier.ts @@ -0,0 +1,78 @@ +import { ProofData } from '@noir-lang/types'; +import { BackendOptions } from './types.js'; +import { flattenPublicInputsAsArray } from './public_inputs.js'; +import { type Barretenberg } from '@aztec/bb.js'; + +export class BarretenbergVerifier { + // These type assertions are used so that we don't + // have to initialize `api` and `acirComposer` in the constructor. + // These are initialized asynchronously in the `init` function, + // constructors cannot be asynchronous which is why we do this. + + private api!: Barretenberg; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + private acirComposer: any; + + constructor(private options: BackendOptions = { threads: 1 }) {} + + /** @ignore */ + async instantiate(): Promise { + if (!this.api) { + if (typeof navigator !== 'undefined' && navigator.hardwareConcurrency) { + this.options.threads = navigator.hardwareConcurrency; + } else { + try { + const os = await import('os'); + this.options.threads = os.cpus().length; + } catch (e) { + console.log('Could not detect environment. Falling back to one thread.', e); + } + } + const { Barretenberg, RawBuffer, Crs } = await import('@aztec/bb.js'); + + // This is the number of CRS points necessary to verify a Barretenberg proof. + const NUM_CRS_POINTS_FOR_VERIFICATION: number = 0; + const [api, crs] = await Promise.all([Barretenberg.new(this.options), Crs.new(NUM_CRS_POINTS_FOR_VERIFICATION)]); + + await api.commonInitSlabAllocator(NUM_CRS_POINTS_FOR_VERIFICATION); + await api.srsInitSrs( + new RawBuffer([] /* crs.getG1Data() */), + NUM_CRS_POINTS_FOR_VERIFICATION, + new RawBuffer(crs.getG2Data()), + ); + + this.acirComposer = await api.acirNewAcirComposer(NUM_CRS_POINTS_FOR_VERIFICATION); + this.api = api; + } + } + + /** @description Verifies a proof */ + async verifyProof(proofData: ProofData, verificationKey: Uint8Array): Promise { + const { RawBuffer } = await import('@aztec/bb.js'); + + await this.instantiate(); + // The verifier can be used for a variety of ACIR programs so we should not assume that it + // is preloaded with the correct verification key. + await this.api.acirLoadVerificationKey(this.acirComposer, new RawBuffer(verificationKey)); + + const proof = reconstructProofWithPublicInputs(proofData); + return await this.api.acirVerifyProof(this.acirComposer, proof); + } + + async destroy(): Promise { + if (!this.api) { + return; + } + await this.api.destroy(); + } +} + +export function reconstructProofWithPublicInputs(proofData: ProofData): Uint8Array { + // Flatten publicInputs + const publicInputsConcatenated = flattenPublicInputsAsArray(proofData.publicInputs); + + // Concatenate publicInputs and proof + const proofWithPublicInputs = Uint8Array.from([...publicInputsConcatenated, ...proofData.proof]); + + return proofWithPublicInputs; +} diff --git a/tooling/noir_js_backend_barretenberg/test/public_input_deflattening.test.ts b/tooling/noir_js_backend_barretenberg/test/public_input_deflattening.test.ts index 079a1ad268b..cfd43eff250 100644 --- a/tooling/noir_js_backend_barretenberg/test/public_input_deflattening.test.ts +++ b/tooling/noir_js_backend_barretenberg/test/public_input_deflattening.test.ts @@ -55,6 +55,7 @@ const abi: Abi = { visibility: 'public', }, return_witnesses: [2, 13, 13], + error_types: {}, }; it('flattens a witness map in order of its witness indices', async () => { diff --git a/tooling/noir_js_backend_barretenberg/tsconfig.cjs.json b/tooling/noir_js_backend_barretenberg/tsconfig.cjs.json index 15d273af62e..ac1e3784480 100644 --- a/tooling/noir_js_backend_barretenberg/tsconfig.cjs.json +++ b/tooling/noir_js_backend_barretenberg/tsconfig.cjs.json @@ -2,6 +2,7 @@ "extends": "./tsconfig.json", "compilerOptions": { "module": "CommonJS", + "moduleResolution": "Node", "outDir": "./lib/cjs" }, } diff --git a/tooling/noir_js_types/package.json b/tooling/noir_js_types/package.json index a3b5c85897a..b2b84b640a5 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.24.0", + "version": "0.30.0", "license": "(MIT OR Apache-2.0)", "homepage": "https://noir-lang.org/", "repository": { @@ -40,9 +40,9 @@ }, "devDependencies": { "@types/prettier": "^3", - "eslint": "^8.56.0", - "eslint-plugin-prettier": "^5.0.0", - "prettier": "3.0.3", - "typescript": "^5.2.2" + "eslint": "^8.57.0", + "eslint-plugin-prettier": "^5.1.3", + "prettier": "3.2.5", + "typescript": "^5.4.2" } } diff --git a/tooling/noir_js_types/src/types.ts b/tooling/noir_js_types/src/types.ts index 3a62d79a807..0258f2f90c9 100644 --- a/tooling/noir_js_types/src/types.ts +++ b/tooling/noir_js_types/src/types.ts @@ -19,6 +19,20 @@ export type AbiParameter = { visibility: Visibility; }; +export type AbiErrorType = + | { + error_kind: 'fmtstring'; + length: number; + item_types: AbiType[]; + } + | ({ error_kind: 'custom' } & AbiType); + +// The payload for a raw assertion error returned on execution. +export type RawAssertionPayload = { + selector: string; + data: string[]; +}; + // Map from witness index to hex string value of witness. export type WitnessMap = Map; @@ -27,9 +41,20 @@ export type Abi = { param_witnesses: Record; return_type: { abi_type: AbiType; visibility: Visibility } | null; return_witnesses: number[]; + error_types: Record; }; -export interface Backend { +export interface VerifierBackend { + /** + * @description Verifies a proof */ + verifyProof(proofData: ProofData): Promise; + + /** + * @description Destroys the backend */ + destroy(): Promise; +} + +export interface Backend extends VerifierBackend { /** * @description Generates a proof */ generateProof(decompressedWitness: Uint8Array): Promise; @@ -49,14 +74,6 @@ export interface Backend { /** @description A Field containing the verification key hash */ vkHash: string; }>; - - /** - * @description Verifies a proof */ - verifyProof(proofData: ProofData): Promise; - - /** - * @description Destroys the backend */ - destroy(): Promise; } /** diff --git a/tooling/noirc_abi/Cargo.toml b/tooling/noirc_abi/Cargo.toml index b7fe1ef8084..baae2dfa35e 100644 --- a/tooling/noirc_abi/Cargo.toml +++ b/tooling/noirc_abi/Cargo.toml @@ -3,6 +3,7 @@ name = "noirc_abi" version.workspace = true authors.workspace = true edition.workspace = true +rust-version.workspace = true license.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -11,6 +12,7 @@ license.workspace = true acvm.workspace = true iter-extended.workspace = true noirc_frontend.workspace = true +noirc_printable_type.workspace = true toml.workspace = true serde_json = "1.0" serde.workspace = true @@ -21,3 +23,13 @@ num-traits = "0.2" [dev-dependencies] strum = "0.24" strum_macros = "0.24" + +[features] +bn254 = [ + "acvm/bn254", + "noirc_frontend/bn254", +] +bls12_381 = [ + "acvm/bls12_381", + "noirc_frontend/bls12_381", +] \ No newline at end of file diff --git a/tooling/noirc_abi/src/errors.rs b/tooling/noirc_abi/src/errors.rs index 687fecfcc1d..4209a9e218b 100644 --- a/tooling/noirc_abi/src/errors.rs +++ b/tooling/noirc_abi/src/errors.rs @@ -1,4 +1,7 @@ -use crate::{input_parser::InputValue, AbiParameter, AbiType}; +use crate::{ + input_parser::{InputTypecheckingError, InputValue}, + AbiType, +}; use acvm::acir::native_types::Witness; use thiserror::Error; @@ -38,8 +41,8 @@ impl From for InputParserError { pub enum AbiError { #[error("Received parameters not expected by ABI: {0:?}")] UnexpectedParams(Vec), - #[error("The parameter {} is expected to be a {:?} but found incompatible value {value:?}", .param.name, .param.typ)] - TypeMismatch { param: AbiParameter, value: InputValue }, + #[error("The value passed for parameter `{}` does not match the specified type:\n{0}", .0.path())] + TypeMismatch(#[from] InputTypecheckingError), #[error("ABI expects the parameter `{0}`, but this was not found")] MissingParam(String), #[error( diff --git a/tooling/noirc_abi/src/input_parser/json.rs b/tooling/noirc_abi/src/input_parser/json.rs index 7618cd6c15a..070f9effe42 100644 --- a/tooling/noirc_abi/src/input_parser/json.rs +++ b/tooling/noirc_abi/src/input_parser/json.rs @@ -1,6 +1,6 @@ use super::{parse_str_to_field, InputValue}; use crate::{errors::InputParserError, Abi, AbiType, MAIN_RETURN_NAME}; -use acvm::FieldElement; +use acvm::{AcirField, FieldElement}; use iter_extended::{try_btree_map, try_vecmap}; use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; diff --git a/tooling/noirc_abi/src/input_parser/mod.rs b/tooling/noirc_abi/src/input_parser/mod.rs index f66e069d487..14d92bc71b3 100644 --- a/tooling/noirc_abi/src/input_parser/mod.rs +++ b/tooling/noirc_abi/src/input_parser/mod.rs @@ -1,8 +1,9 @@ use num_bigint::{BigInt, BigUint}; use num_traits::{Num, Zero}; -use std::collections::BTreeMap; +use std::collections::{BTreeMap, HashSet}; +use thiserror::Error; -use acvm::FieldElement; +use acvm::{AcirField, FieldElement}; use serde::Serialize; use crate::errors::InputParserError; @@ -22,63 +23,165 @@ pub enum InputValue { Struct(BTreeMap), } +#[derive(Debug, Error)] +pub enum InputTypecheckingError { + #[error("Value {value:?} does not fall within range of allowable values for a {typ:?}")] + OutsideOfValidRange { path: String, typ: AbiType, value: InputValue }, + #[error("Type {typ:?} is expected to have length {expected_length} but value {value:?} has length {actual_length}")] + LengthMismatch { + path: String, + typ: AbiType, + value: InputValue, + expected_length: usize, + actual_length: usize, + }, + #[error("Could not find value for required field `{expected_field}`. Found values for fields {found_fields:?}")] + MissingField { path: String, expected_field: String, found_fields: Vec }, + #[error("Additional unexpected field was provided for type {typ:?}. Found field named `{extra_field}`")] + UnexpectedField { path: String, typ: AbiType, extra_field: String }, + #[error("Type {typ:?} and value {value:?} do not match")] + IncompatibleTypes { path: String, typ: AbiType, value: InputValue }, +} + +impl InputTypecheckingError { + pub(crate) fn path(&self) -> &str { + match self { + InputTypecheckingError::OutsideOfValidRange { path, .. } + | InputTypecheckingError::LengthMismatch { path, .. } + | InputTypecheckingError::MissingField { path, .. } + | InputTypecheckingError::UnexpectedField { path, .. } + | InputTypecheckingError::IncompatibleTypes { path, .. } => path, + } + } +} + impl InputValue { /// Checks whether the ABI type matches the InputValue type - /// and also their arity - pub fn matches_abi(&self, abi_param: &AbiType) -> bool { + pub(crate) fn find_type_mismatch( + &self, + abi_param: &AbiType, + path: String, + ) -> Result<(), InputTypecheckingError> { match (self, abi_param) { - (InputValue::Field(_), AbiType::Field) => true, + (InputValue::Field(_), AbiType::Field) => Ok(()), (InputValue::Field(field_element), AbiType::Integer { width, .. }) => { - field_element.num_bits() <= *width + if field_element.num_bits() <= *width { + Ok(()) + } else { + Err(InputTypecheckingError::OutsideOfValidRange { + path, + typ: abi_param.clone(), + value: self.clone(), + }) + } } (InputValue::Field(field_element), AbiType::Boolean) => { - field_element.is_one() || field_element.is_zero() + if field_element.is_one() || field_element.is_zero() { + Ok(()) + } else { + Err(InputTypecheckingError::OutsideOfValidRange { + path, + typ: abi_param.clone(), + value: self.clone(), + }) + } } (InputValue::Vec(array_elements), AbiType::Array { length, typ, .. }) => { if array_elements.len() != *length as usize { - return false; + return Err(InputTypecheckingError::LengthMismatch { + path, + typ: abi_param.clone(), + value: self.clone(), + expected_length: *length as usize, + actual_length: array_elements.len(), + }); } // Check that all of the array's elements' values match the ABI as well. - array_elements.iter().all(|input_value| input_value.matches_abi(typ)) + for (i, element) in array_elements.iter().enumerate() { + let mut path = path.clone(); + path.push_str(&format!("[{i}]")); + + element.find_type_mismatch(typ, path)?; + } + Ok(()) } (InputValue::String(string), AbiType::String { length }) => { - string.len() == *length as usize + if string.len() == *length as usize { + Ok(()) + } else { + Err(InputTypecheckingError::LengthMismatch { + path, + typ: abi_param.clone(), + value: self.clone(), + actual_length: string.len(), + expected_length: *length as usize, + }) + } } (InputValue::Struct(map), AbiType::Struct { fields, .. }) => { - if map.len() != fields.len() { - return false; + for (field_name, field_type) in fields { + if let Some(value) = map.get(field_name) { + let mut path = path.clone(); + path.push_str(&format!(".{field_name}")); + value.find_type_mismatch(field_type, path)?; + } else { + return Err(InputTypecheckingError::MissingField { + path, + expected_field: field_name.to_string(), + found_fields: map.keys().cloned().collect(), + }); + } } - let field_types = BTreeMap::from_iter(fields.iter().cloned()); + if map.len() > fields.len() { + let expected_fields: HashSet = + fields.iter().map(|(field, _)| field.to_string()).collect(); + let extra_field = map.keys().find(|&key| !expected_fields.contains(key)).cloned().expect("`map` is larger than the expected type's `fields` so it must contain an unexpected field"); + return Err(InputTypecheckingError::UnexpectedField { + path, + typ: abi_param.clone(), + extra_field: extra_field.to_string(), + }); + } - // Check that all of the struct's fields' values match the ABI as well. - map.iter().all(|(field_name, field_value)| { - if let Some(field_type) = field_types.get(field_name) { - field_value.matches_abi(field_type) - } else { - false - } - }) + Ok(()) } (InputValue::Vec(vec_elements), AbiType::Tuple { fields }) => { if vec_elements.len() != fields.len() { - return false; + return Err(InputTypecheckingError::LengthMismatch { + path, + typ: abi_param.clone(), + value: self.clone(), + actual_length: vec_elements.len(), + expected_length: fields.len(), + }); } - - vec_elements - .iter() - .zip(fields) - .all(|(input_value, abi_param)| input_value.matches_abi(abi_param)) + // Check that all of the array's elements' values match the ABI as well. + for (i, (element, expected_typ)) in vec_elements.iter().zip(fields).enumerate() { + let mut path = path.clone(); + path.push_str(&format!(".{i}")); + element.find_type_mismatch(expected_typ, path)?; + } + Ok(()) } // All other InputValue-AbiType combinations are fundamentally incompatible. - _ => false, + _ => Err(InputTypecheckingError::IncompatibleTypes { + path, + typ: abi_param.clone(), + value: self.clone(), + }), } } + + /// Checks whether the ABI type matches the InputValue type. + pub fn matches_abi(&self, abi_param: &AbiType) -> bool { + self.find_type_mismatch(abi_param, String::new()).is_ok() + } } /// The different formats that are supported when parsing @@ -126,7 +229,7 @@ impl Format { mod serialization_tests { use std::collections::BTreeMap; - use acvm::FieldElement; + use acvm::{AcirField, FieldElement}; use strum::IntoEnumIterator; use crate::{ @@ -167,6 +270,7 @@ mod serialization_tests { // These two fields are unused when serializing/deserializing to file. param_witnesses: BTreeMap::new(), return_witnesses: Vec::new(), + error_types: Default::default(), }; let input_map: BTreeMap = BTreeMap::from([ @@ -258,7 +362,7 @@ fn field_from_big_int(bigint: BigInt) -> FieldElement { #[cfg(test)] mod test { - use acvm::FieldElement; + use acvm::{AcirField, FieldElement}; use num_bigint::BigUint; use super::parse_str_to_field; diff --git a/tooling/noirc_abi/src/input_parser/toml.rs b/tooling/noirc_abi/src/input_parser/toml.rs index b216fe58794..321d3511b5d 100644 --- a/tooling/noirc_abi/src/input_parser/toml.rs +++ b/tooling/noirc_abi/src/input_parser/toml.rs @@ -1,6 +1,6 @@ use super::{parse_str_to_field, parse_str_to_signed, InputValue}; use crate::{errors::InputParserError, Abi, AbiType, MAIN_RETURN_NAME}; -use acvm::FieldElement; +use acvm::{AcirField, FieldElement}; use iter_extended::{try_btree_map, try_vecmap}; use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; diff --git a/tooling/noirc_abi/src/lib.rs b/tooling/noirc_abi/src/lib.rs index 26feab65d83..b1ddba26f15 100644 --- a/tooling/noirc_abi/src/lib.rs +++ b/tooling/noirc_abi/src/lib.rs @@ -4,17 +4,23 @@ #![warn(clippy::semicolon_if_nothing_returned)] use acvm::{ - acir::native_types::{Witness, WitnessMap}, - FieldElement, + acir::{ + circuit::ErrorSelector, + native_types::{Witness, WitnessMap}, + }, + AcirField, FieldElement, }; use errors::AbiError; use input_parser::InputValue; use iter_extended::{try_btree_map, try_vecmap, vecmap}; -use noirc_frontend::{ - hir::Context, Signedness, StructType, Type, TypeBinding, TypeVariableKind, Visibility, +use noirc_frontend::ast::{Signedness, Visibility}; +use noirc_frontend::{hir::Context, Type, TypeBinding, TypeVariableKind}; +use noirc_printable_type::{ + decode_value as printable_type_decode_value, PrintableType, PrintableValue, + PrintableValueDisplay, }; use serde::{Deserialize, Serialize}; -use std::ops::Range; +use std::{borrow::Borrow, 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. @@ -45,7 +51,7 @@ pub const MAIN_RETURN_NAME: &str = "return"; pub enum AbiType { Field, Array { - length: u64, + length: u32, #[serde(rename = "type")] typ: Box, }, @@ -66,7 +72,7 @@ pub enum AbiType { fields: Vec, }, String { - length: u64, + length: u32, }, } @@ -131,7 +137,7 @@ impl AbiType { Type::FieldElement => Self::Field, Type::Array(size, typ) => { let length = size - .evaluate_to_u64() + .evaluate_to_u32() .expect("Cannot have variable sized arrays as a parameter to main"); let typ = typ.as_ref(); Self::Array { length, typ: Box::new(Self::from_type(context, typ)) } @@ -147,12 +153,14 @@ impl AbiType { Type::TypeVariable(binding, TypeVariableKind::IntegerOrField) | Type::TypeVariable(binding, TypeVariableKind::Integer) => match &*binding.borrow() { TypeBinding::Bound(typ) => Self::from_type(context, typ), - TypeBinding::Unbound(_) => Self::from_type(context, &Type::default_int_type()), + TypeBinding::Unbound(_) => { + Self::from_type(context, &Type::default_int_or_field_type()) + } }, Type::Bool => Self::Boolean, Type::String(size) => { let size = size - .evaluate_to_u64() + .evaluate_to_u32() .expect("Cannot have variable sized strings as a parameter to main"); Self::String { length: size } } @@ -178,8 +186,9 @@ impl AbiType { | Type::TypeVariable(_, _) | Type::NamedGeneric(..) | Type::Forall(..) - | Type::NotConstant - | Type::Function(_, _, _) => unreachable!("Type cannot be used in the abi"), + | Type::Code + | Type::Slice(_) + | Type::Function(_, _, _) => unreachable!("{typ} cannot be used in the abi"), Type::FmtString(_, _) => unreachable!("format strings cannot be used in the abi"), Type::MutableReference(_) => unreachable!("&mut cannot be used in the abi"), } @@ -189,14 +198,46 @@ impl AbiType { pub fn field_count(&self) -> u32 { match self { AbiType::Field | AbiType::Integer { .. } | AbiType::Boolean => 1, - AbiType::Array { length, typ } => typ.field_count() * (*length as u32), + AbiType::Array { length, typ } => typ.field_count() * *length, AbiType::Struct { fields, .. } => { fields.iter().fold(0, |acc, (_, field_type)| acc + field_type.field_count()) } AbiType::Tuple { fields } => { fields.iter().fold(0, |acc, field_typ| acc + field_typ.field_count()) } - AbiType::String { length } => *length as u32, + AbiType::String { length } => *length, + } + } +} + +impl From<&AbiType> for PrintableType { + fn from(value: &AbiType) -> Self { + match value { + AbiType::Field => PrintableType::Field, + AbiType::String { length } => PrintableType::String { length: *length }, + AbiType::Tuple { fields } => { + let fields = fields.iter().map(|field| field.into()).collect(); + PrintableType::Tuple { types: fields } + } + AbiType::Array { length, typ } => { + let borrowed: &AbiType = typ.borrow(); + PrintableType::Array { length: *length, typ: Box::new(borrowed.into()) } + } + AbiType::Boolean => PrintableType::Boolean, + AbiType::Struct { path, fields } => { + let fields = + fields.iter().map(|(name, field)| (name.clone(), field.into())).collect(); + PrintableType::Struct { + name: path.split("::").last().unwrap_or_default().to_string(), + fields, + } + } + AbiType::Integer { sign: Sign::Unsigned, width } => { + PrintableType::UnsignedInteger { width: *width } + } + AbiType::Integer { sign: Sign::Signed, width } => { + PrintableType::SignedInteger { width: *width } + } } } } @@ -221,6 +262,7 @@ pub struct AbiReturnType { pub abi_type: AbiType, pub visibility: AbiVisibility, } + #[derive(Clone, Debug, Serialize, Deserialize)] pub struct Abi { /// An ordered list of the arguments to the program's `main` function, specifying their types and visibility. @@ -230,6 +272,7 @@ pub struct Abi { pub param_witnesses: BTreeMap>>, pub return_type: Option, pub return_witnesses: Vec, + pub error_types: BTreeMap, } impl Abi { @@ -279,6 +322,7 @@ impl Abi { param_witnesses, return_type: self.return_type, return_witnesses: self.return_witnesses, + error_types: self.error_types, } } @@ -287,7 +331,7 @@ impl Abi { &self, input_map: &InputMap, return_value: Option, - ) -> Result { + ) -> Result, AbiError> { // Check that no extra witness values have been provided. let param_names = self.parameter_names(); if param_names.len() < input_map.len() { @@ -306,15 +350,7 @@ impl Abi { .ok_or_else(|| AbiError::MissingParam(param_name.clone()))? .clone(); - if !value.matches_abi(&expected_type) { - let param = self - .parameters - .iter() - .find(|param| param.name == param_name) - .unwrap() - .clone(); - return Err(AbiError::TypeMismatch { param, value }); - } + value.find_type_mismatch(&expected_type, param_name.clone())?; Self::encode_value(value, &expected_type).map(|v| (param_name, v)) }) @@ -403,7 +439,7 @@ impl Abi { /// Decode a `WitnessMap` into the types specified in the ABI. pub fn decode( &self, - witness_map: &WitnessMap, + witness_map: &WitnessMap, ) -> Result<(InputMap, Option), AbiError> { let public_inputs_map = try_btree_map(self.parameters.clone(), |AbiParameter { name, typ, .. }| { @@ -435,7 +471,15 @@ impl Abi { .copied() }) { - Some(decode_value(&mut return_witness_values.into_iter(), &return_type.abi_type)?) + // We do not return value for the data bus. + if return_type.visibility == AbiVisibility::DataBus { + None + } else { + Some(decode_value( + &mut return_witness_values.into_iter(), + &return_type.abi_type, + )?) + } } else { // Unlike for the circuit inputs, we tolerate not being able to find the witness values for the return value. // This is because the user may be decoding a partial witness map for which is hasn't been calculated yet. @@ -450,7 +494,7 @@ impl Abi { } } -fn decode_value( +pub fn decode_value( field_iterator: &mut impl Iterator, value_type: &AbiType, ) -> Result { @@ -512,31 +556,35 @@ fn decode_string_value(field_elements: &[FieldElement]) -> String { final_string.to_owned() } -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct ContractEvent { - /// Event name - name: String, - /// The fully qualified path to the event definition - path: String, - - /// Fields of the event - #[serde( - serialize_with = "serialization::serialize_struct_fields", - deserialize_with = "serialization::deserialize_struct_fields" - )] - fields: Vec<(String, AbiType)>, -} - -impl ContractEvent { - pub fn from_struct_type(context: &Context, struct_type: &StructType) -> Self { - let fields = vecmap(struct_type.get_fields(&[]), |(name, typ)| { - (name, AbiType::from_type(context, &typ)) - }); - // For the ABI, we always want to resolve the struct paths from the root crate - let path = context.fully_qualified_struct_path(context.root_crate_id(), struct_type.id); - - Self { name: struct_type.name.0.contents.clone(), path, fields } - } +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "kind", rename_all = "lowercase")] +pub enum AbiValue { + Field { + value: FieldElement, + }, + Integer { + sign: bool, + value: String, + }, + Boolean { + value: bool, + }, + String { + value: String, + }, + Array { + value: Vec, + }, + Struct { + #[serde( + serialize_with = "serialization::serialize_struct_field_values", + deserialize_with = "serialization::deserialize_struct_field_values" + )] + fields: Vec<(String, AbiValue)>, + }, + Tuple { + fields: Vec, + }, } fn range_to_vec(ranges: &[Range]) -> Vec { @@ -549,11 +597,62 @@ fn range_to_vec(ranges: &[Range]) -> Vec { result } +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "error_kind", rename_all = "lowercase")] +pub enum AbiErrorType { + FmtString { length: u32, item_types: Vec }, + Custom(AbiType), +} +impl AbiErrorType { + pub fn from_type(context: &Context, typ: &Type) -> Self { + match typ { + Type::FmtString(len, item_types) => { + let length = len.evaluate_to_u32().expect("Cannot evaluate fmt length"); + let Type::Tuple(item_types) = item_types.as_ref() else { + unreachable!("FmtString items must be a tuple") + }; + let item_types = + item_types.iter().map(|typ| AbiType::from_type(context, typ)).collect(); + Self::FmtString { length, item_types } + } + _ => Self::Custom(AbiType::from_type(context, typ)), + } + } +} + +pub fn display_abi_error( + fields: &[FieldElement], + error_type: AbiErrorType, +) -> PrintableValueDisplay { + match error_type { + AbiErrorType::FmtString { length, item_types } => { + let mut fields_iter = fields.iter().copied(); + let PrintableValue::String(string) = + printable_type_decode_value(&mut fields_iter, &PrintableType::String { length }) + else { + unreachable!("Got non-string from string decoding"); + }; + let _length_of_items = fields_iter.next(); + let items = item_types.into_iter().map(|abi_type| { + let printable_typ = (&abi_type).into(); + let decoded = printable_type_decode_value(&mut fields_iter, &printable_typ); + (decoded, printable_typ) + }); + PrintableValueDisplay::FmtString(string, items.collect()) + } + AbiErrorType::Custom(abi_typ) => { + let printable_type = (&abi_typ).into(); + let decoded = printable_type_decode_value(&mut fields.iter().copied(), &printable_type); + PrintableValueDisplay::Plain(decoded, printable_type) + } + } +} + #[cfg(test)] mod test { use std::collections::BTreeMap; - use acvm::{acir::native_types::Witness, FieldElement}; + use acvm::{acir::native_types::Witness, AcirField, FieldElement}; use crate::{ input_parser::InputValue, Abi, AbiParameter, AbiReturnType, AbiType, AbiVisibility, @@ -585,6 +684,7 @@ mod test { visibility: AbiVisibility::Public, }), return_witnesses: vec![Witness(3)], + error_types: BTreeMap::default(), }; // Note we omit return value from inputs diff --git a/tooling/noirc_abi/src/serialization.rs b/tooling/noirc_abi/src/serialization.rs index ed838803fab..4f91d9b7dfd 100644 --- a/tooling/noirc_abi/src/serialization.rs +++ b/tooling/noirc_abi/src/serialization.rs @@ -1,8 +1,7 @@ +use crate::{AbiType, AbiValue}; use iter_extended::vecmap; use serde::{Deserialize, Deserializer, Serialize, Serializer}; -use crate::AbiType; - // This module exposes a custom serializer and deserializer for `BTreeMap` // (representing the fields of a struct) to serialize it as a `Vec`. // @@ -41,6 +40,37 @@ where Ok(vecmap(fields_vector, |StructField { name, typ }| (name, typ))) } +#[derive(Serialize, Deserialize)] +struct StructFieldValue { + name: String, + value: AbiValue, +} + +pub(crate) fn serialize_struct_field_values( + fields: &[(String, AbiValue)], + s: S, +) -> Result +where + S: Serializer, +{ + let fields_vector = vecmap(fields, |(name, value)| StructFieldValue { + name: name.to_owned(), + value: value.to_owned(), + }); + + fields_vector.serialize(s) +} + +pub(crate) fn deserialize_struct_field_values<'de, D>( + deserializer: D, +) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + let fields_vector = Vec::::deserialize(deserializer)?; + Ok(vecmap(fields_vector, |StructFieldValue { name, value }| (name, value))) +} + #[cfg(test)] mod tests { use crate::{AbiParameter, AbiType, AbiVisibility, Sign}; diff --git a/tooling/noirc_abi_wasm/Cargo.toml b/tooling/noirc_abi_wasm/Cargo.toml index c78c3ead0c3..daa619ca01d 100644 --- a/tooling/noirc_abi_wasm/Cargo.toml +++ b/tooling/noirc_abi_wasm/Cargo.toml @@ -12,8 +12,8 @@ license.workspace = true crate-type = ["cdylib"] [dependencies] -acvm.workspace = true -noirc_abi.workspace = true +acvm = { workspace = true, features = ["bn254"] } +noirc_abi = { workspace = true, features = ["bn254"] } iter-extended.workspace = true wasm-bindgen.workspace = true serde.workspace = true diff --git a/tooling/noirc_abi_wasm/README.md b/tooling/noirc_abi_wasm/README.md index 77bc1f5fae2..2b0cf9b74d4 100644 --- a/tooling/noirc_abi_wasm/README.md +++ b/tooling/noirc_abi_wasm/README.md @@ -1,17 +1,3 @@ # Noir Lang ABI JavaScript Package This JavaScript package enables users to ABI encode inputs to a Noir program, i.e. generating an initial witness. - -## Building from source - -Outside of the [noir repo](https://github.com/noir-lang/noir), this package can be built using the command below: - -```bash -nix build -L github:noir-lang/noir/master#abi_wasm -``` - -If you are within the noir repo and would like to build local changes, you can use: - -```bash -nix build -L #abi_wasm -``` diff --git a/tooling/noirc_abi_wasm/build.rs b/tooling/noirc_abi_wasm/build.rs index 3b96be74ef3..7a6eb861de2 100644 --- a/tooling/noirc_abi_wasm/build.rs +++ b/tooling/noirc_abi_wasm/build.rs @@ -1,8 +1,7 @@ const GIT_COMMIT: &&str = &"GIT_COMMIT"; fn main() { - // Only use build_data if the environment variable isn't set - // The environment variable is always set when working via Nix + // Only use build_data if the environment variable isn't set. if std::env::var(GIT_COMMIT).is_err() { build_data::set_GIT_COMMIT(); build_data::set_GIT_DIRTY(); diff --git a/tooling/noirc_abi_wasm/build.sh b/tooling/noirc_abi_wasm/build.sh index 24af149bcea..c07d2d8a4c1 100755 --- a/tooling/noirc_abi_wasm/build.sh +++ b/tooling/noirc_abi_wasm/build.sh @@ -6,13 +6,6 @@ function require_command { exit 1 fi } -function check_installed { - if ! command -v "$1" >/dev/null 2>&1; then - echo "$1 is not installed. Please install it." >&2 - return 1 - fi - return 0 -} function run_or_fail { "$@" local status=$? @@ -21,27 +14,40 @@ function run_or_fail { exit $status fi } +function run_if_available { + if command -v "$1" >/dev/null 2>&1; then + "$@" + else + echo "$1 is not installed. Please install it to use this feature." >&2 + fi +} require_command jq require_command cargo require_command wasm-bindgen -check_installed wasm-opt +#require_command wasm-opt self_path=$(dirname "$(readlink -f "$0")") -export pname=$(cargo read-manifest | jq -r '.name') -export CARGO_TARGET_DIR=$self_path/target +pname=$(cargo read-manifest | jq -r '.name') -rm -rf $self_path/outputs >/dev/null 2>&1 -rm -rf $self_path/result >/dev/null 2>&1 +NODE_DIR=$self_path/nodejs +BROWSER_DIR=$self_path/web -if [ -n "$out" ]; then - echo "Will install package to $out (defined outside installPhase.sh script)" -else - export out="$self_path/outputs/out" - echo "Will install package to $out" +# Clear out the existing build artifacts as these aren't automatically removed by wasm-bindgen. +if [ -d ./pkg/ ]; then + rm -r $NODE_DIR + rm -r $BROWSER_DIR fi -run_or_fail $self_path/buildPhaseCargoCommand.sh -run_or_fail $self_path/installPhase.sh +TARGET=wasm32-unknown-unknown +WASM_BINARY=${self_path}/../../target/$TARGET/release/${pname}.wasm + +NODE_WASM=${NODE_DIR}/${pname}_bg.wasm +BROWSER_WASM=${BROWSER_DIR}/${pname}_bg.wasm -ln -s $out $self_path/result +# Build the new wasm package +run_or_fail cargo build --lib --release --target $TARGET --package ${pname} +run_or_fail wasm-bindgen $WASM_BINARY --out-dir $NODE_DIR --typescript --target nodejs +run_or_fail wasm-bindgen $WASM_BINARY --out-dir $BROWSER_DIR --typescript --target web +run_if_available wasm-opt $NODE_WASM -o $NODE_WASM -O +run_if_available wasm-opt $BROWSER_WASM -o $BROWSER_WASM -O diff --git a/tooling/noirc_abi_wasm/buildPhaseCargoCommand.sh b/tooling/noirc_abi_wasm/buildPhaseCargoCommand.sh deleted file mode 100755 index 1188d00953e..00000000000 --- a/tooling/noirc_abi_wasm/buildPhaseCargoCommand.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env bash - -function run_or_fail { - "$@" - local status=$? - if [ $status -ne 0 ]; then - echo "Command '$*' failed with exit code $status" >&2 - exit $status - fi -} -function run_if_available { - if command -v "$1" >/dev/null 2>&1; then - "$@" - else - echo "$1 is not installed. Please install it to use this feature." >&2 - fi -} - -export self_path=$(dirname "$(readlink -f "$0")") - -# Clear out the existing build artifacts as these aren't automatically removed by wasm-pack. -if [ -d ./pkg/ ]; then - rm -rf $self_path/pkg/ -fi - -TARGET=wasm32-unknown-unknown -WASM_BINARY=$CARGO_TARGET_DIR/$TARGET/release/${pname}.wasm - -NODE_DIR=$self_path/nodejs/ -BROWSER_DIR=$self_path/web/ -NODE_WASM=${NODE_DIR}/${pname}_bg.wasm -BROWSER_WASM=${BROWSER_DIR}/${pname}_bg.wasm - -# Build the new wasm package -run_or_fail cargo build --lib --release --target $TARGET --package ${pname} -run_or_fail wasm-bindgen $WASM_BINARY --out-dir $NODE_DIR --typescript --target nodejs -run_or_fail wasm-bindgen $WASM_BINARY --out-dir $BROWSER_DIR --typescript --target web -run_if_available wasm-opt $NODE_WASM -o $NODE_WASM -O -run_if_available wasm-opt $BROWSER_WASM -o $BROWSER_WASM -O \ No newline at end of file diff --git a/tooling/noirc_abi_wasm/installPhase.sh b/tooling/noirc_abi_wasm/installPhase.sh deleted file mode 100755 index d9b94f2d171..00000000000 --- a/tooling/noirc_abi_wasm/installPhase.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env bash -export self_path=$(dirname "$(readlink -f "$0")") - -export out_path=$out/noirc_abi_wasm - -mkdir -p $out_path -cp $self_path/README.md $out_path/ -cp $self_path/package.json $out_path/ -cp -r $self_path/nodejs $out_path/ -cp -r $self_path/web $out_path/ diff --git a/tooling/noirc_abi_wasm/package.json b/tooling/noirc_abi_wasm/package.json index 05fcc270402..399a333f157 100644 --- a/tooling/noirc_abi_wasm/package.json +++ b/tooling/noirc_abi_wasm/package.json @@ -3,7 +3,7 @@ "contributors": [ "The Noir Team " ], - "version": "0.24.0", + "version": "0.30.0", "license": "(MIT OR Apache-2.0)", "homepage": "https://noir-lang.org/", "repository": { @@ -33,9 +33,7 @@ "clean": "chmod u+w web nodejs || true && rm -rf ./nodejs ./web ./target ./result", "nightly:version": "jq --arg new_version \"-$(git rev-parse --short HEAD)$1\" '.version = .version + $new_version' package.json > package-tmp.json && mv package-tmp.json package.json", "publish": "echo 📡 publishing `$npm_package_name` && yarn npm publish", - "lint": "NODE_NO_WARNINGS=1 eslint . --ext .ts --ignore-path ./.eslintignore --max-warnings 0", - "build:nix": "nix build -L .#noirc_abi_wasm", - "install:from:nix": "yarn clean && yarn build:nix && cp -rL ./result/noirc_abi_wasm/nodejs ./ && cp -rL ./result/noirc_abi_wasm/web ./" + "lint": "NODE_NO_WARNINGS=1 eslint . --ext .ts --ignore-path ./.eslintignore --max-warnings 0" }, "dependencies": { "@noir-lang/types": "workspace:*" @@ -43,9 +41,9 @@ "devDependencies": { "@esm-bundle/chai": "^4.3.4-fix.0", "@web/dev-server-esbuild": "^0.3.6", - "@web/test-runner": "^0.15.3", + "@web/test-runner": "^0.18.1", "@web/test-runner-playwright": "^0.10.0", - "eslint": "^8.56.0", + "eslint": "^8.57.0", "mocha": "^10.2.0" } } diff --git a/tooling/noirc_abi_wasm/src/js_witness_map.rs b/tooling/noirc_abi_wasm/src/js_witness_map.rs index 293c5c089f8..a82621822e4 100644 --- a/tooling/noirc_abi_wasm/src/js_witness_map.rs +++ b/tooling/noirc_abi_wasm/src/js_witness_map.rs @@ -2,7 +2,7 @@ use acvm::{ acir::native_types::{Witness, WitnessMap}, - FieldElement, + AcirField, FieldElement, }; use js_sys::{JsString, Map}; use wasm_bindgen::prelude::{wasm_bindgen, JsValue}; @@ -25,8 +25,8 @@ impl Default for JsWitnessMap { } } -impl From for JsWitnessMap { - fn from(witness_map: WitnessMap) -> Self { +impl From> for JsWitnessMap { + fn from(witness_map: WitnessMap) -> Self { let js_map = JsWitnessMap::new(); for (key, value) in witness_map { js_map.set( @@ -38,7 +38,7 @@ impl From for JsWitnessMap { } } -impl From for WitnessMap { +impl From for WitnessMap { fn from(js_map: JsWitnessMap) -> Self { let mut witness_map = WitnessMap::new(); js_map.for_each(&mut |value, key| { @@ -73,7 +73,7 @@ mod test { use acvm::{ acir::native_types::{Witness, WitnessMap}, - FieldElement, + AcirField, FieldElement, }; use wasm_bindgen::JsValue; diff --git a/tooling/noirc_abi_wasm/src/lib.rs b/tooling/noirc_abi_wasm/src/lib.rs index ce15f6d502e..ef4a468b661 100644 --- a/tooling/noirc_abi_wasm/src/lib.rs +++ b/tooling/noirc_abi_wasm/src/lib.rs @@ -5,12 +5,19 @@ // See Cargo.toml for explanation. use getrandom as _; -use acvm::acir::native_types::WitnessMap; +use acvm::{ + acir::{ + circuit::RawAssertionPayload, + native_types::{WitnessMap, WitnessStack}, + }, + FieldElement, +}; use iter_extended::try_btree_map; use noirc_abi::{ + decode_value, display_abi_error, errors::InputParserError, input_parser::{json::JsonTypes, InputValue}, - Abi, MAIN_RETURN_NAME, + Abi, AbiErrorType, MAIN_RETURN_NAME, }; use serde::Serialize; use std::collections::BTreeMap; @@ -26,8 +33,8 @@ use js_witness_map::JsWitnessMap; #[wasm_bindgen(typescript_custom_section)] const INPUT_MAP: &'static str = r#" -import { Field, InputValue, InputMap, Visibility, Sign, AbiType, AbiParameter, Abi, WitnessMap } from "@noir-lang/types"; -export { Field, InputValue, InputMap, Visibility, Sign, AbiType, AbiParameter, Abi, WitnessMap } from "@noir-lang/types"; +import { Field, InputValue, InputMap, Visibility, Sign, AbiType, AbiParameter, Abi, WitnessMap, RawAssertionPayload } from "@noir-lang/types"; +export { Field, InputValue, InputMap, Visibility, Sign, AbiType, AbiParameter, Abi, WitnessMap, RawAssertionPayload } from "@noir-lang/types"; "#; #[wasm_bindgen] @@ -40,6 +47,10 @@ extern "C" { #[derive(Clone, Debug, PartialEq, Eq)] pub type JsInputValue; + #[wasm_bindgen(extends = js_sys::Object, js_name = "RawAssertionPayload", typescript_type = "RawAssertionPayload")] + #[derive(Clone, Debug, PartialEq, Eq)] + pub type JsRawAssertionPayload; + #[wasm_bindgen(extends = js_sys::Object, js_name = "Abi", typescript_type = "Abi")] #[derive(Clone, Debug, PartialEq, Eq)] pub type JsAbi; @@ -113,3 +124,39 @@ pub fn abi_decode(abi: JsAbi, witness_map: JsWitnessMap) -> Result::from_serde(&return_struct) .map_err(|err| err.to_string().into()) } + +#[wasm_bindgen(js_name = serializeWitness)] +pub fn serialise_witness(witness_map: JsWitnessMap) -> Result, JsAbiError> { + console_error_panic_hook::set_once(); + let converted_witness: WitnessMap = witness_map.into(); + let witness_stack: WitnessStack = converted_witness.into(); + let output = witness_stack.try_into(); + output.map_err(|_| JsAbiError::new("Failed to convert to Vec".to_string())) +} + +#[wasm_bindgen(js_name = abiDecodeError)] +pub fn abi_decode_error( + abi: JsAbi, + raw_error: JsRawAssertionPayload, +) -> Result { + console_error_panic_hook::set_once(); + let mut abi: Abi = + JsValueSerdeExt::into_serde(&JsValue::from(abi)).map_err(|err| err.to_string())?; + + let raw_error: RawAssertionPayload = + JsValueSerdeExt::into_serde(&JsValue::from(raw_error)).map_err(|err| err.to_string())?; + + let error_type = abi.error_types.remove(&raw_error.selector).expect("Missing error type"); + match error_type { + AbiErrorType::FmtString { .. } => { + let string = display_abi_error(&raw_error.data, error_type).to_string(); + Ok(JsValue::from_str(&string)) + } + AbiErrorType::Custom(typ) => { + let input_value = decode_value(&mut raw_error.data.into_iter(), &typ)?; + let json_types = JsonTypes::try_from_input_value(&input_value, &typ)?; + ::from_serde(&json_types) + .map_err(|err| err.to_string().into()) + } + } +} diff --git a/tooling/noirc_abi_wasm/test/browser/decode_error.test.ts b/tooling/noirc_abi_wasm/test/browser/decode_error.test.ts new file mode 100644 index 00000000000..2407ddc6535 --- /dev/null +++ b/tooling/noirc_abi_wasm/test/browser/decode_error.test.ts @@ -0,0 +1,64 @@ +import { expect } from '@esm-bundle/chai'; +import initNoirAbi, { RawAssertionPayload, abiDecodeError } from '@noir-lang/noirc_abi'; + +beforeEach(async () => { + await initNoirAbi(); +}); + +it('Recovers custom field errors', async () => { + const { FAKE_FIELD_SELECTOR, abi } = await import('../shared/decode_error'); + + const payload: RawAssertionPayload = { + selector: FAKE_FIELD_SELECTOR, + data: ['0x000001'], + }; + + const decoded = abiDecodeError(abi, payload); + expect(decoded).to.equal('0x01'); +}); + +it('Recovers custom tuple errors', async () => { + const { FAKE_TUPLE_SELECTOR, abi } = await import('../shared/decode_error'); + + const payload: RawAssertionPayload = { + selector: FAKE_TUPLE_SELECTOR, + data: ['0x000001', '0x000002'], + }; + + const decoded = abiDecodeError(abi, payload); + expect(decoded).to.deep.equal(['0x01', '0x02']); +}); + +it('Recovers custom fmt string errors', async () => { + const { FAKE_FMT_STRING_SELECTOR, abi, SAMPLE_FMT_STRING } = await import('../shared/decode_error'); + + // FmtStrings contain the string serialized to fields + const data = [...SAMPLE_FMT_STRING].map((c) => `0x${c.charCodeAt(0).toString(16)}`); + // Then they contain the length of the values to replace + data.push('0x01'); + // And then the value to replace + data.push('0x07'); + + const payload: RawAssertionPayload = { + selector: FAKE_FMT_STRING_SELECTOR, + data, + }; + + const decoded = abiDecodeError(abi, payload); + expect(decoded).to.equal('hello 0x07'); +}); + +it('Recovers struct errors', async () => { + const { FAKE_STRUCT_SELECTOR, abi } = await import('../shared/decode_error'); + + const payload: RawAssertionPayload = { + selector: FAKE_STRUCT_SELECTOR, + data: ['0x01', '0x02'], + }; + + const decoded = abiDecodeError(abi, payload); + expect(decoded).to.deep.equal({ + a: '0x01', + b: '0x02', + }); +}); diff --git a/tooling/noirc_abi_wasm/test/browser/errors.test.ts b/tooling/noirc_abi_wasm/test/browser/errors.test.ts index 429a2d446a3..0f75ff64a3e 100644 --- a/tooling/noirc_abi_wasm/test/browser/errors.test.ts +++ b/tooling/noirc_abi_wasm/test/browser/errors.test.ts @@ -9,7 +9,7 @@ it('errors when an integer input overflows', async () => { const { abi, inputs } = await import('../shared/uint_overflow'); expect(() => abiEncode(abi, inputs)).to.throw( - 'The parameter foo is expected to be a Integer { sign: Unsigned, width: 32 } but found incompatible value Field(2³⁸)', + 'The value passed for parameter `foo` does not match the specified type:\nValue Field(2³⁸) does not fall within range of allowable values for a Integer { sign: Unsigned, width: 32 }', ); }); diff --git a/tooling/noirc_abi_wasm/test/node/decode_error.test.ts b/tooling/noirc_abi_wasm/test/node/decode_error.test.ts new file mode 100644 index 00000000000..711653ad077 --- /dev/null +++ b/tooling/noirc_abi_wasm/test/node/decode_error.test.ts @@ -0,0 +1,60 @@ +import { expect } from 'chai'; +import { RawAssertionPayload, abiDecodeError } from '@noir-lang/noirc_abi'; + +it('Recovers custom field errors', async () => { + const { FAKE_FIELD_SELECTOR, abi } = await import('../shared/decode_error'); + + const payload: RawAssertionPayload = { + selector: FAKE_FIELD_SELECTOR, + data: ['0x000001'], + }; + + const decoded = abiDecodeError(abi, payload); + expect(decoded).to.equal('0x01'); +}); + +it('Recovers custom tuple errors', async () => { + const { FAKE_TUPLE_SELECTOR, abi } = await import('../shared/decode_error'); + + const payload: RawAssertionPayload = { + selector: FAKE_TUPLE_SELECTOR, + data: ['0x000001', '0x000002'], + }; + + const decoded = abiDecodeError(abi, payload); + expect(decoded).to.deep.equal(['0x01', '0x02']); +}); + +it('Recovers custom fmt string errors', async () => { + const { FAKE_FMT_STRING_SELECTOR, abi, SAMPLE_FMT_STRING } = await import('../shared/decode_error'); + + // FmtStrings contain the string serialized to fields + const data = [...SAMPLE_FMT_STRING].map((c) => `0x${c.charCodeAt(0).toString(16)}`); + // Then they contain the length of the values to replace + data.push('0x01'); + // And then the value to replace + data.push('0x07'); + + const payload: RawAssertionPayload = { + selector: FAKE_FMT_STRING_SELECTOR, + data, + }; + + const decoded = abiDecodeError(abi, payload); + expect(decoded).to.equal('hello 0x07'); +}); + +it('Recovers struct errors', async () => { + const { FAKE_STRUCT_SELECTOR, abi } = await import('../shared/decode_error'); + + const payload: RawAssertionPayload = { + selector: FAKE_STRUCT_SELECTOR, + data: ['0x01', '0x02'], + }; + + const decoded = abiDecodeError(abi, payload); + expect(decoded).to.deep.equal({ + a: '0x01', + b: '0x02', + }); +}); diff --git a/tooling/noirc_abi_wasm/test/node/errors.test.ts b/tooling/noirc_abi_wasm/test/node/errors.test.ts index 0d007e64803..fba451b4a8c 100644 --- a/tooling/noirc_abi_wasm/test/node/errors.test.ts +++ b/tooling/noirc_abi_wasm/test/node/errors.test.ts @@ -5,7 +5,7 @@ it('errors when an integer input overflows', async () => { const { abi, inputs } = await import('../shared/uint_overflow'); expect(() => abiEncode(abi, inputs)).to.throw( - 'The parameter foo is expected to be a Integer { sign: Unsigned, width: 32 } but found incompatible value Field(2³⁸)', + 'The value passed for parameter `foo` does not match the specified type:\nValue Field(2³⁸) does not fall within range of allowable values for a Integer { sign: Unsigned, width: 32 }', ); }); diff --git a/tooling/noirc_abi_wasm/test/shared/abi_encode.ts b/tooling/noirc_abi_wasm/test/shared/abi_encode.ts index cb80c6710ba..f4ab8175700 100644 --- a/tooling/noirc_abi_wasm/test/shared/abi_encode.ts +++ b/tooling/noirc_abi_wasm/test/shared/abi_encode.ts @@ -12,6 +12,7 @@ export const abi: Abi = { param_witnesses: { foo: [{ start: 1, end: 2 }], bar: [{ start: 2, end: 4 }] }, return_type: null, return_witnesses: [], + error_types: {}, }; export const inputs: InputMap = { 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 0cc0035fa68..3698b913c66 100644 --- a/tooling/noirc_abi_wasm/test/shared/array_as_field.ts +++ b/tooling/noirc_abi_wasm/test/shared/array_as_field.ts @@ -11,6 +11,7 @@ export const abi: Abi = { param_witnesses: { foo: [{ start: 1, end: 3 }] }, return_type: null, return_witnesses: [], + error_types: {}, }; export const inputs: InputMap = { diff --git a/tooling/noirc_abi_wasm/test/shared/decode_error.ts b/tooling/noirc_abi_wasm/test/shared/decode_error.ts new file mode 100644 index 00000000000..36eb18b5210 --- /dev/null +++ b/tooling/noirc_abi_wasm/test/shared/decode_error.ts @@ -0,0 +1,46 @@ +import { Abi } from '@noir-lang/noirc_abi'; + +export const FAKE_FIELD_SELECTOR = '1'; +export const FAKE_TUPLE_SELECTOR = '2'; +export const FAKE_FMT_STRING_SELECTOR = '3'; +export const FAKE_STRUCT_SELECTOR = '4'; + +export const SAMPLE_FMT_STRING = 'hello {a}'; + +export const abi: Abi = { + parameters: [ + { + name: 'foo', + type: { kind: 'array', length: 2, type: { kind: 'field' } }, + visibility: 'private', + }, + ], + param_witnesses: { foo: [{ start: 1, end: 3 }] }, + return_type: null, + return_witnesses: [], + error_types: { + [FAKE_FIELD_SELECTOR]: { + error_kind: 'custom', + kind: 'field', + }, + [FAKE_TUPLE_SELECTOR]: { + error_kind: 'custom', + kind: 'tuple', + fields: [{ kind: 'field' }, { kind: 'field' }], + }, + [FAKE_FMT_STRING_SELECTOR]: { + error_kind: 'fmtstring', + length: SAMPLE_FMT_STRING.length, + item_types: [{ kind: 'field' }], + }, + [FAKE_STRUCT_SELECTOR]: { + error_kind: 'custom', + kind: 'struct', + path: 'foo', + fields: [ + { name: 'a', type: { kind: 'field' } }, + { name: 'b', type: { kind: 'field' } }, + ], + }, + }, +}; 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 6ae709459de..4e3e2fd12a8 100644 --- a/tooling/noirc_abi_wasm/test/shared/field_as_array.ts +++ b/tooling/noirc_abi_wasm/test/shared/field_as_array.ts @@ -11,6 +11,7 @@ export const abi: Abi = { param_witnesses: { foo: [{ start: 1, end: 3 }] }, return_type: null, return_witnesses: [], + error_types: {}, }; export const inputs: InputMap = { diff --git a/tooling/noirc_abi_wasm/test/shared/structs.ts b/tooling/noirc_abi_wasm/test/shared/structs.ts index 6614f8f278e..ee666e40e87 100644 --- a/tooling/noirc_abi_wasm/test/shared/structs.ts +++ b/tooling/noirc_abi_wasm/test/shared/structs.ts @@ -54,6 +54,7 @@ export const abi: Abi = { }, return_type: null, return_witnesses: [], + error_types: {}, }; export const inputs: InputMap = { diff --git a/tooling/noirc_abi_wasm/test/shared/uint_overflow.ts b/tooling/noirc_abi_wasm/test/shared/uint_overflow.ts index c6e066e2bcd..82a3e3998ca 100644 --- a/tooling/noirc_abi_wasm/test/shared/uint_overflow.ts +++ b/tooling/noirc_abi_wasm/test/shared/uint_overflow.ts @@ -11,6 +11,7 @@ export const abi: Abi = { param_witnesses: { foo: [{ start: 1, end: 2 }] }, return_type: null, return_witnesses: [], + error_types: {}, }; export const inputs: InputMap = { diff --git a/compiler/utils/iter-extended/Cargo.toml b/utils/iter-extended/Cargo.toml similarity index 89% rename from compiler/utils/iter-extended/Cargo.toml rename to utils/iter-extended/Cargo.toml index c91e5ea6d77..4343311506e 100644 --- a/compiler/utils/iter-extended/Cargo.toml +++ b/utils/iter-extended/Cargo.toml @@ -3,6 +3,7 @@ name = "iter-extended" version.workspace = true authors.workspace = true edition.workspace = true +rust-version.workspace = true license.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/compiler/utils/iter-extended/src/lib.rs b/utils/iter-extended/src/lib.rs similarity index 100% rename from compiler/utils/iter-extended/src/lib.rs rename to utils/iter-extended/src/lib.rs diff --git a/wasm-bindgen-cli.nix b/wasm-bindgen-cli.nix deleted file mode 100644 index 7c3910f032e..00000000000 --- a/wasm-bindgen-cli.nix +++ /dev/null @@ -1,43 +0,0 @@ -{ lib -, rustPlatform -, fetchCrate -, nodejs -, pkg-config -, openssl -, stdenv -, curl -, darwin -, libiconv -, runCommand -}: - -rustPlatform.buildRustPackage rec { - pname = "wasm-bindgen-cli"; - version = "0.2.86"; - - src = fetchCrate { - inherit pname version; - sha256 = "sha256-56EOiLbdgAcoTrkyvB3t9TjtLaRvGxFUXx4haLwE2QY="; - }; - - cargoSha256 = "sha256-4CPBmz92PuPN6KeGDTdYPAf5+vTFk9EN5Cmx4QJy6yI="; - - nativeBuildInputs = [ pkg-config ]; - - buildInputs = [ openssl ] ++ lib.optionals stdenv.isDarwin [ - curl - # Need libiconv and apple Security on Darwin. See https://github.com/ipetkov/crane/issues/156 - libiconv - darwin.apple_sdk.frameworks.Security - ]; - - doCheck = false; - - meta = with lib; { - homepage = "https://rustwasm.github.io/docs/wasm-bindgen/"; - license = with licenses; [ asl20 /* or */ mit ]; - description = "Facilitating high-level interactions between wasm modules and JavaScript"; - maintainers = with maintainers; [ nitsky rizary ]; - mainProgram = "wasm-bindgen"; - }; -} diff --git a/yarn.lock b/yarn.lock index ace7959279f..8fb574afa30 100644 --- a/yarn.lock +++ b/yarn.lock @@ -221,9 +221,9 @@ __metadata: languageName: node linkType: hard -"@aztec/bb.js@npm:0.24.0": - version: 0.24.0 - resolution: "@aztec/bb.js@npm:0.24.0" +"@aztec/bb.js@npm:0.41.0": + version: 0.41.0 + resolution: "@aztec/bb.js@npm:0.41.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: a086dabf30084cfa526e512148b9c02f0a0770dcc19b7dca4af9a3e98612b716acc7eaac6b52c0f12d985932e866d1cb9e534ded6ac9d747f3dd021afe25de27 + checksum: e5e0095eaff3de45726366726337b131bb6ff7cf2cb53be705572c7d6715dae4c948bf86a03cfad68bc98c0c2d83e64cbe3723cc72260c8dbfa262af8cb81f9b languageName: node linkType: hard @@ -3485,10 +3485,10 @@ __metadata: languageName: node linkType: hard -"@eslint/js@npm:8.56.0": - version: 8.56.0 - resolution: "@eslint/js@npm:8.56.0" - checksum: 5804130574ef810207bdf321c265437814e7a26f4e6fac9b496de3206afd52f533e09ec002a3be06cd9adcc9da63e727f1883938e663c4e4751c007d5b58e539 +"@eslint/js@npm:8.57.0": + version: 8.57.0 + resolution: "@eslint/js@npm:8.57.0" + checksum: 315dc65b0e9893e2bff139bddace7ea601ad77ed47b4550e73da8c9c2d2766c7a575c3cddf17ef85b8fd6a36ff34f91729d0dcca56e73ca887c10df91a41b0bb languageName: node linkType: hard @@ -3926,14 +3926,14 @@ __metadata: languageName: node linkType: hard -"@humanwhocodes/config-array@npm:^0.11.13": - version: 0.11.13 - resolution: "@humanwhocodes/config-array@npm:0.11.13" +"@humanwhocodes/config-array@npm:^0.11.14": + version: 0.11.14 + resolution: "@humanwhocodes/config-array@npm:0.11.14" dependencies: - "@humanwhocodes/object-schema": ^2.0.1 - debug: ^4.1.1 + "@humanwhocodes/object-schema": ^2.0.2 + debug: ^4.3.1 minimatch: ^3.0.5 - checksum: f8ea57b0d7ed7f2d64cd3944654976829d9da91c04d9c860e18804729a33f7681f78166ef4c761850b8c324d362f7d53f14c5c44907a6b38b32c703ff85e4805 + checksum: 861ccce9eaea5de19546653bccf75bf09fe878bc39c3aab00aeee2d2a0e654516adad38dd1098aab5e3af0145bbcbf3f309bdf4d964f8dab9dcd5834ae4c02f2 languageName: node linkType: hard @@ -3944,10 +3944,17 @@ __metadata: languageName: node linkType: hard -"@humanwhocodes/object-schema@npm:^2.0.1": - version: 2.0.1 - resolution: "@humanwhocodes/object-schema@npm:2.0.1" - checksum: 24929487b1ed48795d2f08346a0116cc5ee4634848bce64161fb947109352c562310fd159fc64dda0e8b853307f5794605191a9547f7341158559ca3c8262a45 +"@humanwhocodes/object-schema@npm:^2.0.2": + version: 2.0.2 + resolution: "@humanwhocodes/object-schema@npm:2.0.2" + checksum: 2fc11503361b5fb4f14714c700c02a3f4c7c93e9acd6b87a29f62c522d90470f364d6161b03d1cc618b979f2ae02aed1106fd29d302695d8927e2fc8165ba8ee + languageName: node + linkType: hard + +"@import-maps/resolve@npm:^1.0.1": + version: 1.0.1 + resolution: "@import-maps/resolve@npm:1.0.1" + checksum: 17ee033e26a0fd82294de87eae76d32b553a130fdbf0fb8c70d39f2087a3e8a4a5908970a99aa32bd175153efe9b7dfee6b7f99df36f41abed08c1911dbdb19c languageName: node linkType: hard @@ -4373,15 +4380,15 @@ __metadata: dependencies: "@esm-bundle/chai": ^4.3.4-fix.0 "@web/dev-server-esbuild": ^0.3.6 - "@web/test-runner": ^0.15.3 + "@web/test-runner": ^0.18.1 "@web/test-runner-playwright": ^0.10.0 - chai: ^4.3.7 - eslint: ^8.56.0 - eslint-plugin-prettier: ^5.0.0 + chai: ^4.4.1 + eslint: ^8.57.0 + eslint-plugin-prettier: ^5.1.3 mocha: ^10.2.0 - prettier: 3.0.3 + prettier: 3.2.5 ts-node: ^10.9.1 - typescript: ^5.0.4 + typescript: ^5.4.2 languageName: unknown linkType: soft @@ -4389,18 +4396,18 @@ __metadata: version: 0.0.0-use.local resolution: "@noir-lang/backend_barretenberg@workspace:tooling/noir_js_backend_barretenberg" dependencies: - "@aztec/bb.js": 0.24.0 + "@aztec/bb.js": 0.41.0 "@noir-lang/types": "workspace:*" "@types/node": ^20.6.2 "@types/prettier": ^3 - chai: ^4.3.8 - eslint: ^8.56.0 - eslint-plugin-prettier: ^5.0.0 + chai: ^4.4.1 + eslint: ^8.57.0 + eslint-plugin-prettier: ^5.1.3 fflate: ^0.8.0 mocha: ^10.2.0 - prettier: 3.0.3 + prettier: 3.2.5 ts-node: ^10.9.1 - typescript: 5.1.5 + typescript: 5.4.2 languageName: unknown linkType: soft @@ -4414,16 +4421,16 @@ __metadata: "@types/mocha": ^10.0.1 "@types/node": ^20.6.2 "@types/prettier": ^3 - chai: ^4.3.8 - eslint: ^8.56.0 - eslint-plugin-prettier: ^5.0.0 + chai: ^4.4.1 + eslint: ^8.57.0 + eslint-plugin-prettier: ^5.1.3 glob: ^10.3.10 mocha: ^10.2.0 - prettier: 3.0.3 + prettier: 3.2.5 ts-command-line-args: ^2.5.1 ts-node: ^10.9.1 tsx: ^4.6.2 - typescript: ^5.2.2 + typescript: ^5.4.2 bin: noir-codegen: lib/main.js languageName: unknown @@ -4440,15 +4447,15 @@ __metadata: "@types/mocha": ^10.0.1 "@types/node": ^20.6.2 "@types/prettier": ^3 - chai: ^4.3.8 - eslint: ^8.56.0 - eslint-plugin-prettier: ^5.0.0 + chai: ^4.4.1 + eslint: ^8.57.0 + eslint-plugin-prettier: ^5.1.3 mocha: ^10.2.0 - prettier: 3.0.3 + prettier: 3.2.5 ts-node: ^10.9.1 tsc-multi: ^1.1.0 tsx: ^4.6.2 - typescript: ^5.2.2 + typescript: ^5.4.2 languageName: unknown linkType: soft @@ -4470,28 +4477,28 @@ __metadata: "@types/sinon": ^17 "@wasm-tool/wasm-pack-plugin": ^1.7.0 "@web/dev-server-esbuild": ^0.3.6 - "@web/test-runner": ^0.18.0 + "@web/test-runner": ^0.18.1 "@web/test-runner-playwright": ^0.11.0 adm-zip: ^0.5.0 assert: ^2.1.0 browserify-fs: ^1.0.0 - chai: ^4.3.10 + chai: ^4.4.1 copy-webpack-plugin: ^12.0.2 - eslint: ^8.56.0 - eslint-plugin-prettier: ^5.0.0 + eslint: ^8.57.0 + eslint-plugin-prettier: ^5.1.3 html-webpack-plugin: ^5.6.0 memfs: ^4.6.0 mocha: ^10.2.0 mocha-each: ^2.0.1 pako: ^2.1.0 path-browserify: ^1.0.1 - prettier: 3.0.3 + prettier: 3.2.5 process: ^0.11.10 readable-stream: ^4.4.2 sinon: ^17.0.1 ts-loader: ^9.5.1 ts-node: ^10.9.1 - typescript: ~5.2.2 + typescript: ^5.4.2 unzipit: ^1.4.3 url: ^0.11.3 webpack: ^5.90.1 @@ -4507,9 +4514,9 @@ __metadata: "@esm-bundle/chai": ^4.3.4-fix.0 "@noir-lang/types": "workspace:*" "@web/dev-server-esbuild": ^0.3.6 - "@web/test-runner": ^0.15.3 + "@web/test-runner": ^0.18.1 "@web/test-runner-playwright": ^0.10.0 - eslint: ^8.56.0 + eslint: ^8.57.0 mocha: ^10.2.0 languageName: unknown linkType: soft @@ -4520,14 +4527,14 @@ __metadata: dependencies: "@typescript-eslint/eslint-plugin": ^6.7.3 "@typescript-eslint/parser": ^6.7.3 - chai: ^4.3.7 + chai: ^4.4.1 cspell: ^8.3.2 - eslint: ^8.56.0 - eslint-plugin-prettier: ^5.0.0 + eslint: ^8.57.0 + eslint-plugin-prettier: ^5.1.3 mocha: ^10.2.0 - prettier: 3.0.3 + prettier: 3.2.5 ts-node: ^10.9.1 - typescript: ^5.0.4 + typescript: ^5.4.2 languageName: unknown linkType: soft @@ -4536,10 +4543,10 @@ __metadata: resolution: "@noir-lang/types@workspace:tooling/noir_js_types" dependencies: "@types/prettier": ^3 - eslint: ^8.56.0 - eslint-plugin-prettier: ^5.0.0 - prettier: 3.0.3 - typescript: ^5.2.2 + eslint: ^8.57.0 + eslint-plugin-prettier: ^5.1.3 + prettier: 3.2.5 + typescript: ^5.4.2 languageName: unknown linkType: soft @@ -4869,17 +4876,10 @@ __metadata: languageName: node linkType: hard -"@pkgr/utils@npm:^2.4.2": - version: 2.4.2 - resolution: "@pkgr/utils@npm:2.4.2" - dependencies: - cross-spawn: ^7.0.3 - fast-glob: ^3.3.0 - is-glob: ^4.0.3 - open: ^9.1.0 - picocolors: ^1.0.0 - tslib: ^2.6.0 - checksum: 24e04c121269317d259614cd32beea3af38277151c4002df5883c4be920b8e3490bb897748e844f9d46bf68230f86dabd4e8f093773130e7e60529a769a132fc +"@pkgr/core@npm:^0.1.0": + version: 0.1.1 + resolution: "@pkgr/core@npm:0.1.1" + checksum: 6f25fd2e3008f259c77207ac9915b02f1628420403b2630c92a07ff963129238c9262afc9e84344c7a23b5cc1f3965e2cd17e3798219f5fd78a63d144d3cceba languageName: node linkType: hard @@ -4917,64 +4917,21 @@ __metadata: languageName: node linkType: hard -"@puppeteer/browsers@npm:0.5.0": - version: 0.5.0 - resolution: "@puppeteer/browsers@npm:0.5.0" - dependencies: - debug: 4.3.4 - extract-zip: 2.0.1 - https-proxy-agent: 5.0.1 - progress: 2.0.3 - proxy-from-env: 1.1.0 - tar-fs: 2.1.1 - unbzip2-stream: 1.4.3 - yargs: 17.7.1 - peerDependencies: - typescript: ">= 4.7.4" - peerDependenciesMeta: - typescript: - optional: true - bin: - browsers: lib/cjs/main-cli.js - checksum: d75fde03be4be106ca907834739251c2bb0b33a09fa23315c5dbe8b8b4cfed2f1b26af62e1dbe5fccc227e9bc87b51da0815461b982477eb01439bfdd6e7b01a - languageName: node - linkType: hard - -"@puppeteer/browsers@npm:1.4.6": - version: 1.4.6 - resolution: "@puppeteer/browsers@npm:1.4.6" +"@puppeteer/browsers@npm:2.1.0": + version: 2.1.0 + resolution: "@puppeteer/browsers@npm:2.1.0" dependencies: debug: 4.3.4 extract-zip: 2.0.1 progress: 2.0.3 - proxy-agent: 6.3.0 - tar-fs: 3.0.4 + proxy-agent: 6.4.0 + semver: 7.6.0 + tar-fs: 3.0.5 unbzip2-stream: 1.4.3 - yargs: 17.7.1 - peerDependencies: - typescript: ">= 4.7.4" - peerDependenciesMeta: - typescript: - optional: true + yargs: 17.7.2 bin: browsers: lib/cjs/main-cli.js - checksum: 29569dd8a8a41737bb0dd40cce6279cfc8764afc6242d2f9d8ae610bed7e466fc77eeb27b9b3ac53dd04927a1a0e26389f282f6ba057210979b36ab455009d64 - languageName: node - linkType: hard - -"@rollup/plugin-node-resolve@npm:^13.0.4": - version: 13.3.0 - resolution: "@rollup/plugin-node-resolve@npm:13.3.0" - dependencies: - "@rollup/pluginutils": ^3.1.0 - "@types/resolve": 1.17.1 - deepmerge: ^4.2.2 - is-builtin-module: ^3.1.0 - is-module: ^1.0.0 - resolve: ^1.19.0 - peerDependencies: - rollup: ^2.42.0 - checksum: ec5418e6b3c23a9e30683056b3010e9d325316dcfae93fbc673ae64dad8e56a2ce761c15c48f5e2dcfe0c822fdc4a4905ee6346e3dcf90603ba2260afef5a5e6 + checksum: 318740056fc716cf26179f053eb47e119bc01658f59382a19fb7d39e5b9232a7ad7d82e33445e0519683c13e22b328193fc9952c99d09cdc09f6539391d4749c languageName: node linkType: hard @@ -4997,19 +4954,6 @@ __metadata: languageName: node linkType: hard -"@rollup/pluginutils@npm:^3.1.0": - version: 3.1.0 - resolution: "@rollup/pluginutils@npm:3.1.0" - dependencies: - "@types/estree": 0.0.39 - estree-walker: ^1.0.1 - picomatch: ^2.2.2 - peerDependencies: - rollup: ^1.20.0||^2.0.0 - checksum: 8be16e27863c219edbb25a4e6ec2fe0e1e451d9e917b6a43cf2ae5bc025a6b8faaa40f82a6e53b66d0de37b58ff472c6c3d57a83037ae635041f8df959d6d9aa - languageName: node - linkType: hard - "@rollup/pluginutils@npm:^5.0.1": version: 5.1.0 resolution: "@rollup/pluginutils@npm:5.1.0" @@ -5778,13 +5722,6 @@ __metadata: languageName: node linkType: hard -"@types/estree@npm:0.0.39": - version: 0.0.39 - resolution: "@types/estree@npm:0.0.39" - checksum: 412fb5b9868f2c418126451821833414189b75cc6bf84361156feed733e3d92ec220b9d74a89e52722e03d5e241b2932732711b7497374a404fad49087adc248 - languageName: node - linkType: hard - "@types/express-serve-static-core@npm:*, @types/express-serve-static-core@npm:^4.17.33": version: 4.17.41 resolution: "@types/express-serve-static-core@npm:4.17.41" @@ -6020,13 +5957,6 @@ __metadata: languageName: node linkType: hard -"@types/mocha@npm:^8.2.0": - version: 8.2.3 - resolution: "@types/mocha@npm:8.2.3" - checksum: b43ed1b642a2ee62bf10792a07d5d21d66ab8b4d2cf5d822c8a7643e77b90009aecc000eefab5f6ddc9eb69004192f84119a6f97a8499e1a13ea082e7a5e71bf - languageName: node - linkType: hard - "@types/ms@npm:*": version: 0.7.34 resolution: "@types/ms@npm:0.7.34" @@ -6219,15 +6149,6 @@ __metadata: languageName: node linkType: hard -"@types/resolve@npm:1.17.1": - version: 1.17.1 - resolution: "@types/resolve@npm:1.17.1" - dependencies: - "@types/node": "*" - checksum: dc6a6df507656004e242dcb02c784479deca516d5f4b58a1707e708022b269ae147e1da0521f3e8ad0d63638869d87e0adc023f0bd5454aa6f72ac66c7525cf5 - languageName: node - linkType: hard - "@types/resolve@npm:1.20.2": version: 1.20.2 resolution: "@types/resolve@npm:1.20.2" @@ -6543,15 +6464,6 @@ __metadata: languageName: node linkType: hard -"@web/browser-logs@npm:^0.2.6": - version: 0.2.6 - resolution: "@web/browser-logs@npm:0.2.6" - dependencies: - errorstacks: ^2.2.0 - checksum: 82693e37a7e5a3c3df255e1e4feef6e6c2f2b7f5f883e1a9fd233d09a22c4f3e9e3dfd2ec809d7a02f0894156f26b89f1759bf4e9317640ee3630e9a3d9ec2a8 - languageName: node - linkType: hard - "@web/browser-logs@npm:^0.3.4": version: 0.3.4 resolution: "@web/browser-logs@npm:0.3.4" @@ -6570,15 +6482,6 @@ __metadata: languageName: node linkType: hard -"@web/config-loader@npm:^0.1.3": - version: 0.1.3 - resolution: "@web/config-loader@npm:0.1.3" - dependencies: - semver: ^7.3.4 - checksum: 278554bd00b757eaf296ba904a224c61d4698df1a5d6c04931c40bc6bb308e81e767055cbf283b763cc530aae6b200bb950aa19eb41aa8979a3a2b29e5f0ac7a - languageName: node - linkType: hard - "@web/config-loader@npm:^0.3.0": version: 0.3.1 resolution: "@web/config-loader@npm:0.3.1" @@ -6677,17 +6580,17 @@ __metadata: languageName: node linkType: hard -"@web/dev-server-rollup@npm:^0.4.1": - version: 0.4.1 - resolution: "@web/dev-server-rollup@npm:0.4.1" +"@web/dev-server-import-maps@npm:^0.2.0": + version: 0.2.0 + resolution: "@web/dev-server-import-maps@npm:0.2.0" dependencies: - "@rollup/plugin-node-resolve": ^13.0.4 - "@web/dev-server-core": ^0.4.1 - nanocolors: ^0.2.1 + "@import-maps/resolve": ^1.0.1 + "@types/parse5": ^6.0.1 + "@web/dev-server-core": ^0.7.0 + "@web/parse5-utils": ^2.1.0 parse5: ^6.0.1 - rollup: ^2.67.0 - whatwg-url: ^11.0.0 - checksum: a0c3566f67b5a5ead3822431302ddcaa9d043b18fdcf1190056a4e0539e5d5b545ebfecaf6021412eb4b5b6e074c2b1eff35c71e859195623c7c07e065f9df58 + picomatch: ^2.2.2 + checksum: 15dabfa385f023bab70758b80cc09443455830799793c1a404a7230d90ebf60e40984a10d8a6ceea2afb8f057e90a9f7356a76f867d5e5a2eeacbc397e41535a languageName: node linkType: hard @@ -6705,31 +6608,6 @@ __metadata: languageName: node linkType: hard -"@web/dev-server@npm:^0.1.38": - version: 0.1.38 - resolution: "@web/dev-server@npm:0.1.38" - dependencies: - "@babel/code-frame": ^7.12.11 - "@types/command-line-args": ^5.0.0 - "@web/config-loader": ^0.1.3 - "@web/dev-server-core": ^0.4.1 - "@web/dev-server-rollup": ^0.4.1 - camelcase: ^6.2.0 - command-line-args: ^5.1.1 - command-line-usage: ^7.0.1 - debounce: ^1.2.0 - deepmerge: ^4.2.2 - ip: ^1.1.5 - nanocolors: ^0.2.1 - open: ^8.0.2 - portfinder: ^1.0.32 - bin: - wds: dist/bin.js - web-dev-server: dist/bin.js - checksum: eeaf34f8744f58cfb9493155ad8548a87cae4e445a2fa894610b070f66cb303614d247bb609e378b9df342935ad980a259630317c444d19f9796abfcfb20bb13 - languageName: node - linkType: hard - "@web/dev-server@npm:^0.4.0": version: 0.4.1 resolution: "@web/dev-server@npm:0.4.1" @@ -6775,38 +6653,16 @@ __metadata: languageName: node linkType: hard -"@web/test-runner-chrome@npm:^0.12.1": - version: 0.12.1 - resolution: "@web/test-runner-chrome@npm:0.12.1" - dependencies: - "@web/test-runner-core": ^0.10.29 - "@web/test-runner-coverage-v8": ^0.5.0 - chrome-launcher: ^0.15.0 - puppeteer-core: ^19.8.1 - checksum: 08964e4c22c286231a6bdc003393316a7e0c7878560a9394d8bb9212c3c2e37799bc0aaf4732921213647c3dc89169146f65746d381feaa9c281c0373bf9da59 - languageName: node - linkType: hard - -"@web/test-runner-chrome@npm:^0.15.0": - version: 0.15.0 - resolution: "@web/test-runner-chrome@npm:0.15.0" +"@web/test-runner-chrome@npm:^0.16.0": + version: 0.16.0 + resolution: "@web/test-runner-chrome@npm:0.16.0" dependencies: "@web/test-runner-core": ^0.13.0 "@web/test-runner-coverage-v8": ^0.8.0 async-mutex: 0.4.0 chrome-launcher: ^0.15.0 - puppeteer-core: ^20.0.0 - checksum: 091aa83707aa1a6ade8074c37050f9a0fae2729f223b5e7d756f86ccdadcd85e738cc47d0a4ae8ac6ea930142cc20e341f5d3ad30a3a81d6666b353a7e8c2dd4 - languageName: node - linkType: hard - -"@web/test-runner-commands@npm:^0.6.6": - version: 0.6.6 - resolution: "@web/test-runner-commands@npm:0.6.6" - dependencies: - "@web/test-runner-core": ^0.10.29 - mkdirp: ^1.0.4 - checksum: b25533edd9ec59aeec28756a52ae4c6730388c336fa94e0c21eedf208012efd9aedf96c47ebad9a98cce9d87c4ee539b318a571e1e2bfb1bf8e5f1f6889c98e4 + puppeteer-core: ^22.0.0 + checksum: 99cfa93d12e8854fb2d104de1f8c5a73403e39fc56e5ed78e24f63e903299521750c7b475253dfb75293a2e604ed83d5cfdc1e593a72e9208a99a511bdb6169a languageName: node linkType: hard @@ -6820,40 +6676,6 @@ __metadata: languageName: node linkType: hard -"@web/test-runner-core@npm:^0.10.20, @web/test-runner-core@npm:^0.10.29": - version: 0.10.29 - resolution: "@web/test-runner-core@npm:0.10.29" - dependencies: - "@babel/code-frame": ^7.12.11 - "@types/babel__code-frame": ^7.0.2 - "@types/co-body": ^6.1.0 - "@types/convert-source-map": ^2.0.0 - "@types/debounce": ^1.2.0 - "@types/istanbul-lib-coverage": ^2.0.3 - "@types/istanbul-reports": ^3.0.0 - "@web/browser-logs": ^0.2.6 - "@web/dev-server-core": ^0.4.1 - chokidar: ^3.4.3 - cli-cursor: ^3.1.0 - co-body: ^6.1.0 - convert-source-map: ^2.0.0 - debounce: ^1.2.0 - dependency-graph: ^0.11.0 - globby: ^11.0.1 - ip: ^1.1.5 - istanbul-lib-coverage: ^3.0.0 - istanbul-lib-report: ^3.0.0 - istanbul-reports: ^3.0.2 - log-update: ^4.0.0 - nanocolors: ^0.2.1 - nanoid: ^3.1.25 - open: ^8.0.2 - picomatch: ^2.2.2 - source-map: ^0.7.3 - checksum: 635a510442bea3bce97596a2aed1c58a6154b4b83a44bf3e9c9497a751f42426cae5f67555916c4fd63064a4e91a5e26755e3090887ebac38ec0ab2691e1fe6c - languageName: node - linkType: hard - "@web/test-runner-core@npm:^0.12.0": version: 0.12.0 resolution: "@web/test-runner-core@npm:0.12.0" @@ -6922,18 +6744,6 @@ __metadata: languageName: node linkType: hard -"@web/test-runner-coverage-v8@npm:^0.5.0": - version: 0.5.0 - resolution: "@web/test-runner-coverage-v8@npm:0.5.0" - dependencies: - "@web/test-runner-core": ^0.10.20 - istanbul-lib-coverage: ^3.0.0 - picomatch: ^2.2.2 - v8-to-istanbul: ^9.0.1 - checksum: e69dc6379cff24f28bd21cc37a661945fbf7f3fd532da813e74f4042efe17fc191cdb7c09f1e1ea276167952b0116478ba0fe7af0966fa4867278c3a2cd772df - languageName: node - linkType: hard - "@web/test-runner-coverage-v8@npm:^0.7.3": version: 0.7.3 resolution: "@web/test-runner-coverage-v8@npm:0.7.3" @@ -6960,16 +6770,6 @@ __metadata: languageName: node linkType: hard -"@web/test-runner-mocha@npm:^0.7.5": - version: 0.7.5 - resolution: "@web/test-runner-mocha@npm:0.7.5" - dependencies: - "@types/mocha": ^8.2.0 - "@web/test-runner-core": ^0.10.20 - checksum: 12f87299945d230815bb783de2953ac4239306c1a67145ef5b78cfb0b361ae7f659e5d3e5150af2cedc6f2c55adf10652b761f016430a7ac2d7f77b91ecb9cd1 - languageName: node - linkType: hard - "@web/test-runner-mocha@npm:^0.9.0": version: 0.9.0 resolution: "@web/test-runner-mocha@npm:0.9.0" @@ -7001,41 +6801,14 @@ __metadata: languageName: node linkType: hard -"@web/test-runner@npm:^0.15.3": - version: 0.15.3 - resolution: "@web/test-runner@npm:0.15.3" - dependencies: - "@web/browser-logs": ^0.2.6 - "@web/config-loader": ^0.1.3 - "@web/dev-server": ^0.1.38 - "@web/test-runner-chrome": ^0.12.1 - "@web/test-runner-commands": ^0.6.6 - "@web/test-runner-core": ^0.10.29 - "@web/test-runner-mocha": ^0.7.5 - camelcase: ^6.2.0 - command-line-args: ^5.1.1 - command-line-usage: ^7.0.1 - convert-source-map: ^2.0.0 - diff: ^5.0.0 - globby: ^11.0.1 - nanocolors: ^0.2.1 - portfinder: ^1.0.32 - source-map: ^0.7.3 - bin: - web-test-runner: dist/bin.js - wtr: dist/bin.js - checksum: 75d00d4f15f9977ff4e8fca84e1c7f9d834073688df06d9e4b62bf43cad65a36b2ae21b9ebab5706e4d3b07fc639bb90758b1be1df036c8b80137ec3407a8f08 - languageName: node - linkType: hard - -"@web/test-runner@npm:^0.18.0": - version: 0.18.0 - resolution: "@web/test-runner@npm:0.18.0" +"@web/test-runner@npm:^0.18.1": + version: 0.18.1 + resolution: "@web/test-runner@npm:0.18.1" dependencies: "@web/browser-logs": ^0.4.0 "@web/config-loader": ^0.3.0 "@web/dev-server": ^0.4.0 - "@web/test-runner-chrome": ^0.15.0 + "@web/test-runner-chrome": ^0.16.0 "@web/test-runner-commands": ^0.9.0 "@web/test-runner-core": ^0.13.0 "@web/test-runner-mocha": ^0.9.0 @@ -7051,7 +6824,7 @@ __metadata: bin: web-test-runner: dist/bin.js wtr: dist/bin.js - checksum: d5e410f08cb954f9854a3d837f5f704b578376ee8b0452cff66aeca2eb3cb98e50556ca3b958bda567b42af2ef2cd0a7424eaea40f9b3e80362ae788fbd33118 + checksum: eb21fc5978da2ccbfd6ffac0f61b519036d68a9cdcf211c1dbafa9c6b6f92bb10a9267dec02f4d71dfc45e636166d98712ff9a347af951eabff99b0d7e5899b5 languageName: node linkType: hard @@ -7937,6 +7710,41 @@ __metadata: languageName: node linkType: hard +"bare-events@npm:^2.0.0, bare-events@npm:^2.2.0": + version: 2.2.1 + resolution: "bare-events@npm:2.2.1" + checksum: f4f830fe780b105fce189180761cf69ac60848212133ca7d29eb94f8888f813bf70f339e4e651b200aa8304fc9dc77ca7443756cc68b43294367b5867ad4536b + languageName: node + linkType: hard + +"bare-fs@npm:^2.1.1": + version: 2.2.2 + resolution: "bare-fs@npm:2.2.2" + dependencies: + bare-events: ^2.0.0 + bare-os: ^2.0.0 + bare-path: ^2.0.0 + streamx: ^2.13.0 + checksum: 5b6d26690ee4de93b559f6a1187b6ff553224fe4faea5ef9cbd235b13e033ef96a598dc28eb10aad17d1f35baed24e14e18436534041913f905a0c50ed27713a + languageName: node + linkType: hard + +"bare-os@npm:^2.0.0, bare-os@npm:^2.1.0": + version: 2.2.1 + resolution: "bare-os@npm:2.2.1" + checksum: 7d870d8955531809253dfbceeda5b68e8396ef640166f8ff6c4c5e344f18a6bc9253f6d5e7d9ae2841426b66e9b7b1a39b2a102e6b23e1ddff26ad8a8981af81 + languageName: node + linkType: hard + +"bare-path@npm:^2.0.0, bare-path@npm:^2.1.0": + version: 2.1.0 + resolution: "bare-path@npm:2.1.0" + dependencies: + bare-os: ^2.1.0 + checksum: 03f260e72bd0ae0df4cd712322a2d3c8c16701ffaa55cf2d517ae62b7f78c64b7ec5bba81ec579367f966472481f5160db282e6663bd0fc8cfb09ebe272d8bba + languageName: node + linkType: hard + "base-x@npm:^3.0.2": version: 3.0.9 resolution: "base-x@npm:3.0.9" @@ -7974,13 +7782,6 @@ __metadata: languageName: node linkType: hard -"big-integer@npm:^1.6.44": - version: 1.6.52 - resolution: "big-integer@npm:1.6.52" - checksum: 6e86885787a20fed96521958ae9086960e4e4b5e74d04f3ef7513d4d0ad631a9f3bde2730fc8aaa4b00419fc865f6ec573e5320234531ef37505da7da192c40b - languageName: node - linkType: hard - "big.js@npm:^5.2.2": version: 5.2.2 resolution: "big.js@npm:5.2.2" @@ -8002,17 +7803,6 @@ __metadata: languageName: node linkType: hard -"bl@npm:^4.0.3": - version: 4.1.0 - resolution: "bl@npm:4.1.0" - dependencies: - buffer: ^5.5.0 - inherits: ^2.0.4 - readable-stream: ^3.4.0 - checksum: 9e8521fa7e83aa9427c6f8ccdcba6e8167ef30cc9a22df26effcc5ab682ef91d2cbc23a239f945d099289e4bbcfae7a192e9c28c84c6202e710a0dfec3722662 - languageName: node - linkType: hard - "bl@npm:~0.8.1": version: 0.8.2 resolution: "bl@npm:0.8.2" @@ -8156,15 +7946,6 @@ __metadata: languageName: node linkType: hard -"bplist-parser@npm:^0.2.0": - version: 0.2.0 - resolution: "bplist-parser@npm:0.2.0" - dependencies: - big-integer: ^1.6.44 - checksum: d5339dd16afc51de6c88f88f58a45b72ed6a06aa31f5557d09877575f220b7c1d3fbe375da0b62e6a10d4b8ed80523567e351f24014f5bc886ad523758142cdd - languageName: node - linkType: hard - "brace-expansion@npm:^1.1.7": version: 1.1.11 resolution: "brace-expansion@npm:1.1.11" @@ -8299,7 +8080,7 @@ __metadata: languageName: node linkType: hard -"buffer@npm:^5.2.1, buffer@npm:^5.5.0": +"buffer@npm:^5.2.1": version: 5.7.1 resolution: "buffer@npm:5.7.1" dependencies: @@ -8326,15 +8107,6 @@ __metadata: languageName: node linkType: hard -"bundle-name@npm:^3.0.0": - version: 3.0.0 - resolution: "bundle-name@npm:3.0.0" - dependencies: - run-applescript: ^5.0.0 - checksum: edf2b1fbe6096ed32e7566947ace2ea937ee427391744d7510a2880c4b9a5b3543d3f6c551236a29e5c87d3195f8e2912516290e638c15bcbede7b37cc375615 - languageName: node - linkType: hard - "bundle-name@npm:^4.1.0": version: 4.1.0 resolution: "bundle-name@npm:4.1.0" @@ -8532,9 +8304,9 @@ __metadata: languageName: node linkType: hard -"chai@npm:^4.3.10, chai@npm:^4.3.7, chai@npm:^4.3.8": - version: 4.3.10 - resolution: "chai@npm:4.3.10" +"chai@npm:^4.4.1": + version: 4.4.1 + resolution: "chai@npm:4.4.1" dependencies: assertion-error: ^1.1.0 check-error: ^1.0.3 @@ -8543,7 +8315,7 @@ __metadata: loupe: ^2.3.6 pathval: ^1.1.1 type-detect: ^4.0.8 - checksum: 536668c60a0d985a0fbd94418028e388d243a925d7c5e858c7443e334753511614a3b6a124bac9ca077dfc4c37acc367d62f8c294960f440749536dc181dfc6d + checksum: 9ab84f36eb8e0b280c56c6c21ca4da5933132cd8a0c89c384f1497f77953640db0bc151edd47f81748240a9fab57b78f7d925edfeedc8e8fc98016d71f40c36e languageName: node linkType: hard @@ -8732,13 +8504,6 @@ __metadata: languageName: node linkType: hard -"chownr@npm:^1.1.1": - version: 1.1.4 - resolution: "chownr@npm:1.1.4" - checksum: 115648f8eb38bac5e41c3857f3e663f9c39ed6480d1349977c4d96c95a47266fcacc5a5aabf3cb6c481e22d72f41992827db47301851766c4fd77ac21a4f081d - languageName: node - linkType: hard - "chownr@npm:^2.0.0": version: 2.0.0 resolution: "chownr@npm:2.0.0" @@ -8767,25 +8532,15 @@ __metadata: languageName: node linkType: hard -"chromium-bidi@npm:0.4.16": - version: 0.4.16 - resolution: "chromium-bidi@npm:0.4.16" - dependencies: - mitt: 3.0.0 - peerDependencies: - devtools-protocol: "*" - checksum: 9cbb362fdf589dbdfd1618499c5bbdac45a3aa1291c1d2faa2f1ea3768738677985175d1bb1511dfe3e188bc78e6ea2acb453564ece7e09f535bbcd2253ce06a - languageName: node - linkType: hard - -"chromium-bidi@npm:0.4.7": - version: 0.4.7 - resolution: "chromium-bidi@npm:0.4.7" +"chromium-bidi@npm:0.5.12": + version: 0.5.12 + resolution: "chromium-bidi@npm:0.5.12" dependencies: - mitt: 3.0.0 + mitt: 3.0.1 + urlpattern-polyfill: 10.0.0 peerDependencies: devtools-protocol: "*" - checksum: eec7581e2eddd2c95014c6edc5aae0b036c79bbeadee05166436b16139b6932c902c5ce21d95ed919a592f58d3a47c5469dc5f3de2a300700b2748ab119ad65e + checksum: c14aedc9725a813d82ce66423750757383af6d7580b4f22f8756d31a340b8d6d77dd30a4de0e213f2f89e63faf54a333431acc07675791f1c176d2275e499525 languageName: node linkType: hard @@ -9522,15 +9277,6 @@ __metadata: languageName: node linkType: hard -"cross-fetch@npm:3.1.5": - version: 3.1.5 - resolution: "cross-fetch@npm:3.1.5" - dependencies: - node-fetch: 2.6.7 - checksum: f6b8c6ee3ef993ace6277fd789c71b6acf1b504fd5f5c7128df4ef2f125a429e29cd62dc8c127523f04a5f2fa4771ed80e3f3d9695617f441425045f505cf3bb - languageName: node - linkType: hard - "cross-fetch@npm:4.0.0": version: 4.0.0 resolution: "cross-fetch@npm:4.0.0" @@ -9926,7 +9672,7 @@ __metadata: languageName: node linkType: hard -"debug@npm:4, debug@npm:4.3.4, debug@npm:^4.0.0, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.2.0, debug@npm:^4.3.2, debug@npm:^4.3.3, debug@npm:^4.3.4": +"debug@npm:4, debug@npm:4.3.4, debug@npm:^4.0.0, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.2.0, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.3, debug@npm:^4.3.4": version: 4.3.4 resolution: "debug@npm:4.3.4" dependencies: @@ -10018,16 +9764,6 @@ __metadata: languageName: node linkType: hard -"default-browser-id@npm:^3.0.0": - version: 3.0.0 - resolution: "default-browser-id@npm:3.0.0" - dependencies: - bplist-parser: ^0.2.0 - untildify: ^4.0.0 - checksum: 279c7ad492542e5556336b6c254a4eaf31b2c63a5433265655ae6e47301197b6cfb15c595a6fdc6463b2ff8e1a1a1ed3cba56038a60e1527ba4ab1628c6b9941 - languageName: node - linkType: hard - "default-browser-id@npm:^5.0.0": version: 5.0.0 resolution: "default-browser-id@npm:5.0.0" @@ -10035,18 +9771,6 @@ __metadata: languageName: node linkType: hard -"default-browser@npm:^4.0.0": - version: 4.0.0 - resolution: "default-browser@npm:4.0.0" - dependencies: - bundle-name: ^3.0.0 - default-browser-id: ^3.0.0 - execa: ^7.1.1 - titleize: ^3.0.0 - checksum: 40c5af984799042b140300be5639c9742599bda76dc9eba5ac9ad5943c83dd36cebc4471eafcfddf8e0ec817166d5ba89d56f08e66a126c7c7908a179cead1a7 - languageName: node - linkType: hard - "default-browser@npm:^5.2.1": version: 5.2.1 resolution: "default-browser@npm:5.2.1" @@ -10252,17 +9976,10 @@ __metadata: languageName: node linkType: hard -"devtools-protocol@npm:0.0.1107588": - version: 0.0.1107588 - resolution: "devtools-protocol@npm:0.0.1107588" - checksum: 9064fd643f39ae0adabb8f425b746899ff24371d89a5047d38752653259e6afcb6bcb2d9759ff727eb5885cfc0f9ba8eb384850a2af00694135622e88080e3e5 - languageName: node - linkType: hard - -"devtools-protocol@npm:0.0.1147663": - version: 0.0.1147663 - resolution: "devtools-protocol@npm:0.0.1147663" - checksum: 0631f2b6c6cd7f56e7d62a85bfc291f7e167f0f2de90969ef61fb24e2bd546b2e9530043d2bc3fe6c4d7a9e00473004272d2c2832a10a05e4b75c03a22f549fc +"devtools-protocol@npm:0.0.1249869": + version: 0.0.1249869 + resolution: "devtools-protocol@npm:0.0.1249869" + checksum: 549dda02f6d778741930e5abdde3f8e5d39e16fdbe8af38597a974e9c239798dd464250bd7ab4360d77e3d059620e95be7cf05150142473bf9b661ed28a616ed languageName: node linkType: hard @@ -10330,9 +10047,9 @@ __metadata: axios: ^1.4.0 clsx: ^1.2.1 docusaurus-plugin-typedoc: 1.0.0-next.18 - eslint-plugin-prettier: ^5.0.0 + eslint-plugin-prettier: ^5.1.3 hast-util-is-element: ^1.1.0 - prettier: 3.0.3 + prettier: 3.2.5 prism-react-renderer: ^2.1.0 react: ^18.2.0 react-dom: ^18.2.0 @@ -10345,7 +10062,7 @@ __metadata: typedoc-plugin-frontmatter: ^0.0.2 typedoc-plugin-markdown: 4.0.0-next.25 typedoc-plugin-merge-modules: ^5.1.0 - typescript: ~5.2.2 + typescript: ^5.4.2 languageName: unknown linkType: soft @@ -10583,7 +10300,7 @@ __metadata: languageName: node linkType: hard -"end-of-stream@npm:^1.1.0, end-of-stream@npm:^1.4.1": +"end-of-stream@npm:^1.1.0": version: 1.4.4 resolution: "end-of-stream@npm:1.4.4" dependencies: @@ -10904,22 +10621,23 @@ __metadata: languageName: node linkType: hard -"eslint-plugin-prettier@npm:^5.0.0": - version: 5.0.1 - resolution: "eslint-plugin-prettier@npm:5.0.1" +"eslint-plugin-prettier@npm:^5.1.3": + version: 5.1.3 + resolution: "eslint-plugin-prettier@npm:5.1.3" dependencies: prettier-linter-helpers: ^1.0.0 - synckit: ^0.8.5 + synckit: ^0.8.6 peerDependencies: "@types/eslint": ">=8.0.0" eslint: ">=8.0.0" + eslint-config-prettier: "*" prettier: ">=3.0.0" peerDependenciesMeta: "@types/eslint": optional: true eslint-config-prettier: optional: true - checksum: c2261033b97bafe99ccb7cc47c2fac6fa85b8bbc8b128042e52631f906b69e12afed2cdd9d7e3021cc892ee8dd4204a3574e1f32a0b718b4bb3b440944b6983b + checksum: eb2a7d46a1887e1b93788ee8f8eb81e0b6b2a6f5a66a62bc6f375b033fc4e7ca16448da99380be800042786e76cf5c0df9c87a51a2c9b960ed47acbd7c0b9381 languageName: node linkType: hard @@ -10950,15 +10668,15 @@ __metadata: languageName: node linkType: hard -"eslint@npm:^8.56.0": - version: 8.56.0 - resolution: "eslint@npm:8.56.0" +"eslint@npm:^8.57.0": + version: 8.57.0 + resolution: "eslint@npm:8.57.0" dependencies: "@eslint-community/eslint-utils": ^4.2.0 "@eslint-community/regexpp": ^4.6.1 "@eslint/eslintrc": ^2.1.4 - "@eslint/js": 8.56.0 - "@humanwhocodes/config-array": ^0.11.13 + "@eslint/js": 8.57.0 + "@humanwhocodes/config-array": ^0.11.14 "@humanwhocodes/module-importer": ^1.0.1 "@nodelib/fs.walk": ^1.2.8 "@ungap/structured-clone": ^1.2.0 @@ -10994,7 +10712,7 @@ __metadata: text-table: ^0.2.0 bin: eslint: bin/eslint.js - checksum: 883436d1e809b4a25d9eb03d42f584b84c408dbac28b0019f6ea07b5177940bf3cca86208f749a6a1e0039b63e085ee47aca1236c30721e91f0deef5cc5a5136 + checksum: 3a48d7ff85ab420a8447e9810d8087aea5b1df9ef68c9151732b478de698389ee656fd895635b5f2871c89ee5a2652b3f343d11e9db6f8486880374ebc74a2d9 languageName: node linkType: hard @@ -11110,13 +10828,6 @@ __metadata: languageName: node linkType: hard -"estree-walker@npm:^1.0.1": - version: 1.0.1 - resolution: "estree-walker@npm:1.0.1" - checksum: 7e70da539691f6db03a08e7ce94f394ce2eef4180e136d251af299d41f92fb2d28ebcd9a6e393e3728d7970aeb5358705ddf7209d52fbcb2dd4693f95dcf925f - languageName: node - linkType: hard - "estree-walker@npm:^2.0.2": version: 2.0.2 resolution: "estree-walker@npm:2.0.2" @@ -11336,23 +11047,6 @@ __metadata: languageName: node linkType: hard -"execa@npm:^7.1.1": - version: 7.2.0 - resolution: "execa@npm:7.2.0" - dependencies: - cross-spawn: ^7.0.3 - get-stream: ^6.0.1 - human-signals: ^4.3.0 - is-stream: ^3.0.0 - merge-stream: ^2.0.0 - npm-run-path: ^5.1.0 - onetime: ^6.0.0 - signal-exit: ^3.0.7 - strip-final-newline: ^3.0.0 - checksum: 14fd17ba0ca8c87b277584d93b1d9fc24f2a65e5152b31d5eb159a3b814854283eaae5f51efa9525e304447e2f757c691877f7adff8fde5746aae67eb1edd1cc - languageName: node - linkType: hard - "exponential-backoff@npm:^3.1.1": version: 3.1.1 resolution: "exponential-backoff@npm:3.1.1" @@ -11866,13 +11560,6 @@ __metadata: languageName: node linkType: hard -"fs-constants@npm:^1.0.0": - version: 1.0.0 - resolution: "fs-constants@npm:1.0.0" - checksum: 18f5b718371816155849475ac36c7d0b24d39a11d91348cfcb308b4494824413e03572c403c86d3a260e049465518c4f0d5bd00f0371cdfcad6d4f30a85b350d - languageName: node - linkType: hard - "fs-extra@npm:^0.30.0": version: 0.30.0 resolution: "fs-extra@npm:0.30.0" @@ -13109,6 +12796,16 @@ __metadata: languageName: node linkType: hard +"http-proxy-agent@npm:^7.0.1": + version: 7.0.2 + resolution: "http-proxy-agent@npm:7.0.2" + dependencies: + agent-base: ^7.1.0 + debug: ^4.3.4 + checksum: 670858c8f8f3146db5889e1fa117630910101db601fff7d5a8aa637da0abedf68c899f03d3451cac2f83bcc4c3d2dabf339b3aa00ff8080571cceb02c3ce02f3 + languageName: node + linkType: hard + "http-proxy-middleware@npm:^2.0.3": version: 2.0.6 resolution: "http-proxy-middleware@npm:2.0.6" @@ -13148,7 +12845,7 @@ __metadata: languageName: node linkType: hard -"https-proxy-agent@npm:5.0.1, https-proxy-agent@npm:^5.0.0": +"https-proxy-agent@npm:^5.0.0": version: 5.0.1 resolution: "https-proxy-agent@npm:5.0.1" dependencies: @@ -13158,7 +12855,7 @@ __metadata: languageName: node linkType: hard -"https-proxy-agent@npm:^7.0.0, https-proxy-agent@npm:^7.0.1, https-proxy-agent@npm:^7.0.2": +"https-proxy-agent@npm:^7.0.1, https-proxy-agent@npm:^7.0.2": version: 7.0.2 resolution: "https-proxy-agent@npm:7.0.2" dependencies: @@ -13168,6 +12865,16 @@ __metadata: languageName: node linkType: hard +"https-proxy-agent@npm:^7.0.3": + version: 7.0.4 + resolution: "https-proxy-agent@npm:7.0.4" + dependencies: + agent-base: ^7.0.2 + debug: 4 + checksum: daaab857a967a2519ddc724f91edbbd388d766ff141b9025b629f92b9408fc83cee8a27e11a907aede392938e9c398e240d643e178408a59e4073539cde8cfe9 + languageName: node + linkType: hard + "human-signals@npm:^2.1.0": version: 2.1.0 resolution: "human-signals@npm:2.1.0" @@ -13175,13 +12882,6 @@ __metadata: languageName: node linkType: hard -"human-signals@npm:^4.3.0": - version: 4.3.1 - resolution: "human-signals@npm:4.3.1" - checksum: 6f12958df3f21b6fdaf02d90896c271df00636a31e2bbea05bddf817a35c66b38a6fdac5863e2df85bd52f34958997f1f50350ff97249e1dff8452865d5235d1 - languageName: node - linkType: hard - "hyperdyperid@npm:^1.2.0": version: 1.2.0 resolution: "hyperdyperid@npm:1.2.0" @@ -13416,13 +13116,14 @@ __metadata: "@nomicfoundation/hardhat-chai-matchers": ^2.0.0 "@nomicfoundation/hardhat-ethers": ^3.0.0 "@web/dev-server-esbuild": ^0.3.6 - "@web/test-runner": ^0.15.3 + "@web/dev-server-import-maps": ^0.2.0 + "@web/test-runner": ^0.18.1 "@web/test-runner-playwright": ^0.10.0 - eslint: ^8.56.0 - eslint-plugin-prettier: ^5.0.0 + eslint: ^8.57.0 + eslint-plugin-prettier: ^5.1.3 ethers: ^6.7.1 hardhat: ^2.17.4 - prettier: 3.0.3 + prettier: 3.2.5 smol-toml: ^1.1.2 toml: ^3.0.0 tslog: ^4.9.2 @@ -13556,7 +13257,7 @@ __metadata: languageName: node linkType: hard -"is-builtin-module@npm:^3.1.0, is-builtin-module@npm:^3.2.1": +"is-builtin-module@npm:^3.2.1": version: 3.2.1 resolution: "is-builtin-module@npm:3.2.1" dependencies: @@ -13877,13 +13578,6 @@ __metadata: languageName: node linkType: hard -"is-stream@npm:^3.0.0": - version: 3.0.0 - resolution: "is-stream@npm:3.0.0" - checksum: 172093fe99119ffd07611ab6d1bcccfe8bc4aa80d864b15f43e63e54b7abc71e779acd69afdb854c4e2a67fdc16ae710e370eda40088d1cfc956a50ed82d8f16 - languageName: node - linkType: hard - "is-typed-array@npm:^1.1.3": version: 1.1.12 resolution: "is-typed-array@npm:1.1.12" @@ -16012,13 +15706,6 @@ __metadata: languageName: node linkType: hard -"mimic-fn@npm:^4.0.0": - version: 4.0.0 - resolution: "mimic-fn@npm:4.0.0" - checksum: 995dcece15ee29aa16e188de6633d43a3db4611bcf93620e7e62109ec41c79c0f34277165b8ce5e361205049766e371851264c21ac64ca35499acb5421c2ba56 - languageName: node - linkType: hard - "mimic-response@npm:^1.0.0, mimic-response@npm:^1.0.1": version: 1.0.1 resolution: "mimic-response@npm:1.0.1" @@ -16183,17 +15870,10 @@ __metadata: languageName: node linkType: hard -"mitt@npm:3.0.0": - version: 3.0.0 - resolution: "mitt@npm:3.0.0" - checksum: f7be5049d27d18b1dbe9408452d66376fa60ae4a79fe9319869d1b90ae8cbaedadc7e9dab30b32d781411256d468be5538996bb7368941c09009ef6bbfa6bfc7 - languageName: node - linkType: hard - -"mkdirp-classic@npm:^0.5.2": - version: 0.5.3 - resolution: "mkdirp-classic@npm:0.5.3" - checksum: 3f4e088208270bbcc148d53b73e9a5bd9eef05ad2cbf3b3d0ff8795278d50dd1d11a8ef1875ff5aea3fa888931f95bfcb2ad5b7c1061cfefd6284d199e6776ac +"mitt@npm:3.0.1": + version: 3.0.1 + resolution: "mitt@npm:3.0.1" + checksum: b55a489ac9c2949ab166b7f060601d3b6d893a852515ae9eca4e11df01c013876df777ea109317622b5c1c60e8aae252558e33c8c94e14124db38f64a39614b1 languageName: node linkType: hard @@ -16427,20 +16107,6 @@ __metadata: languageName: node linkType: hard -"node-fetch@npm:2.6.7": - version: 2.6.7 - resolution: "node-fetch@npm:2.6.7" - dependencies: - whatwg-url: ^5.0.0 - peerDependencies: - encoding: ^0.1.0 - peerDependenciesMeta: - encoding: - optional: true - checksum: 8d816ffd1ee22cab8301c7756ef04f3437f18dace86a1dae22cf81db8ef29c0bf6655f3215cb0cdb22b420b6fe141e64b26905e7f33f9377a7fa59135ea3e10b - languageName: node - linkType: hard - "node-fetch@npm:^2.6.12": version: 2.7.0 resolution: "node-fetch@npm:2.7.0" @@ -16555,15 +16221,6 @@ __metadata: languageName: node linkType: hard -"npm-run-path@npm:^5.1.0": - version: 5.1.0 - resolution: "npm-run-path@npm:5.1.0" - dependencies: - path-key: ^4.0.0 - checksum: dc184eb5ec239d6a2b990b43236845332ef12f4e0beaa9701de724aa797fe40b6bbd0157fb7639d24d3ab13f5d5cf22d223a19c6300846b8126f335f788bee66 - languageName: node - linkType: hard - "nprogress@npm:^0.2.0": version: 0.2.0 resolution: "nprogress@npm:0.2.0" @@ -16696,15 +16353,6 @@ __metadata: languageName: node linkType: hard -"onetime@npm:^6.0.0": - version: 6.0.0 - resolution: "onetime@npm:6.0.0" - dependencies: - mimic-fn: ^4.0.0 - checksum: 0846ce78e440841335d4e9182ef69d5762e9f38aa7499b19f42ea1c4cd40f0b4446094c455c713f9adac3f4ae86f613bb5e30c99e52652764d06a89f709b3788 - languageName: node - linkType: hard - "only@npm:~0.0.2": version: 0.0.2 resolution: "only@npm:0.0.2" @@ -16735,18 +16383,6 @@ __metadata: languageName: node linkType: hard -"open@npm:^9.1.0": - version: 9.1.0 - resolution: "open@npm:9.1.0" - dependencies: - default-browser: ^4.0.0 - define-lazy-prop: ^3.0.0 - is-inside-container: ^1.0.0 - is-wsl: ^2.2.0 - checksum: 3993c0f61d51fed8ac290e99c9c3cf45d3b6cfb3e2aa2b74cafd312c3486c22fd81df16ac8f3ab91dd8a4e3e729a16fc2480cfc406c4833416cf908acf1ae7c9 - languageName: node - linkType: hard - "opener@npm:^1.5.2": version: 1.5.2 resolution: "opener@npm:1.5.2" @@ -16932,7 +16568,7 @@ __metadata: languageName: node linkType: hard -"pac-proxy-agent@npm:^7.0.0": +"pac-proxy-agent@npm:^7.0.1": version: 7.0.1 resolution: "pac-proxy-agent@npm:7.0.1" dependencies: @@ -17159,13 +16795,6 @@ __metadata: languageName: node linkType: hard -"path-key@npm:^4.0.0": - version: 4.0.0 - resolution: "path-key@npm:4.0.0" - checksum: 8e6c314ae6d16b83e93032c61020129f6f4484590a777eed709c4a01b50e498822b00f76ceaf94bc64dbd90b327df56ceadce27da3d83393790f1219e07721d7 - languageName: node - linkType: hard - "path-parse@npm:^1.0.6, path-parse@npm:^1.0.7": version: 1.0.7 resolution: "path-parse@npm:1.0.7" @@ -17811,12 +17440,12 @@ __metadata: languageName: node linkType: hard -"prettier@npm:3.0.3": - version: 3.0.3 - resolution: "prettier@npm:3.0.3" +"prettier@npm:3.2.5": + version: 3.2.5 + resolution: "prettier@npm:3.2.5" bin: prettier: bin/prettier.cjs - checksum: e10b9af02b281f6c617362ebd2571b1d7fc9fb8a3bd17e371754428cda992e5e8d8b7a046e8f7d3e2da1dcd21aa001e2e3c797402ebb6111b5cd19609dd228e0 + checksum: 2ee4e1417572372afb7a13bb446b34f20f1bf1747db77cf6ccaf57a9be005f2f15c40f903d41a6b79eec3f57fff14d32a20fb6dee1f126da48908926fe43c311 languageName: node linkType: hard @@ -17948,23 +17577,23 @@ __metadata: languageName: node linkType: hard -"proxy-agent@npm:6.3.0": - version: 6.3.0 - resolution: "proxy-agent@npm:6.3.0" +"proxy-agent@npm:6.4.0": + version: 6.4.0 + resolution: "proxy-agent@npm:6.4.0" dependencies: agent-base: ^7.0.2 debug: ^4.3.4 - http-proxy-agent: ^7.0.0 - https-proxy-agent: ^7.0.0 + http-proxy-agent: ^7.0.1 + https-proxy-agent: ^7.0.3 lru-cache: ^7.14.1 - pac-proxy-agent: ^7.0.0 + pac-proxy-agent: ^7.0.1 proxy-from-env: ^1.1.0 - socks-proxy-agent: ^8.0.1 - checksum: e3fb0633d665e352ed4efe23ae5616b8301423dfa4ff1c5975d093da8a636181a97391f7a91c6a7ffae17c1a305df855e95507f73bcdafda8876198c64b88f5b + socks-proxy-agent: ^8.0.2 + checksum: 4d3794ad5e07486298902f0a7f250d0f869fa0e92d790767ca3f793a81374ce0ab6c605f8ab8e791c4d754da96656b48d1c24cb7094bfd310a15867e4a0841d7 languageName: node linkType: hard -"proxy-from-env@npm:1.1.0, proxy-from-env@npm:^1.1.0": +"proxy-from-env@npm:^1.1.0": version: 1.1.0 resolution: "proxy-from-env@npm:1.1.0" checksum: ed7fcc2ba0a33404958e34d95d18638249a68c430e30fcb6c478497d72739ba64ce9810a24f53a7d921d0c065e5b78e3822759800698167256b04659366ca4d4 @@ -18027,46 +17656,17 @@ __metadata: languageName: node linkType: hard -"puppeteer-core@npm:^19.8.1": - version: 19.11.1 - resolution: "puppeteer-core@npm:19.11.1" - dependencies: - "@puppeteer/browsers": 0.5.0 - chromium-bidi: 0.4.7 - cross-fetch: 3.1.5 - debug: 4.3.4 - devtools-protocol: 0.0.1107588 - extract-zip: 2.0.1 - https-proxy-agent: 5.0.1 - proxy-from-env: 1.1.0 - tar-fs: 2.1.1 - unbzip2-stream: 1.4.3 - ws: 8.13.0 - peerDependencies: - typescript: ">= 4.7.4" - peerDependenciesMeta: - typescript: - optional: true - checksum: 06126e478b8b653e83b98b51cec35dceef8ab576abd1369afd45360c5bac3711443e58ebe3b852d40801a118e4cb7ddf5d3154518b5a9294ee93f7a42d9f22d4 - languageName: node - linkType: hard - -"puppeteer-core@npm:^20.0.0": - version: 20.9.0 - resolution: "puppeteer-core@npm:20.9.0" +"puppeteer-core@npm:^22.0.0": + version: 22.4.1 + resolution: "puppeteer-core@npm:22.4.1" dependencies: - "@puppeteer/browsers": 1.4.6 - chromium-bidi: 0.4.16 + "@puppeteer/browsers": 2.1.0 + chromium-bidi: 0.5.12 cross-fetch: 4.0.0 debug: 4.3.4 - devtools-protocol: 0.0.1147663 - ws: 8.13.0 - peerDependencies: - typescript: ">= 4.7.4" - peerDependenciesMeta: - typescript: - optional: true - checksum: d298598445b0f2032c02d0ed7d1d18a8d2d2fcaf6fc31fc96e93e2669a7fc6fbee0338bd9b8c8f8822887f18a8fb680b77bb56e96fe1928baadb52292bbd93b4 + devtools-protocol: 0.0.1249869 + ws: 8.16.0 + checksum: 01c28c4f0f66a4ed6c7fee14871920fd25c60ae3507c1b8aed37968b240021f8d0cdd37cb863cebb88fde792ae9fea453e3b943931ae075c99f8e90303d2625f languageName: node linkType: hard @@ -18389,7 +17989,7 @@ __metadata: languageName: node linkType: hard -"readable-stream@npm:^3.0.6, readable-stream@npm:^3.1.1, readable-stream@npm:^3.4.0, readable-stream@npm:^3.6.0": +"readable-stream@npm:^3.0.6, readable-stream@npm:^3.4.0, readable-stream@npm:^3.6.0": version: 3.6.2 resolution: "readable-stream@npm:3.6.2" dependencies: @@ -18907,7 +18507,7 @@ __metadata: languageName: node linkType: hard -"resolve@npm:^1.1.6, resolve@npm:^1.14.2, resolve@npm:^1.19.0, resolve@npm:^1.20.0, resolve@npm:^1.22.1, resolve@npm:^1.3.2": +"resolve@npm:^1.1.6, resolve@npm:^1.14.2, resolve@npm:^1.20.0, resolve@npm:^1.22.1, resolve@npm:^1.3.2": version: 1.22.8 resolution: "resolve@npm:1.22.8" dependencies: @@ -18929,7 +18529,7 @@ __metadata: languageName: node linkType: hard -"resolve@patch:resolve@^1.1.6#~builtin, resolve@patch:resolve@^1.14.2#~builtin, resolve@patch:resolve@^1.19.0#~builtin, resolve@patch:resolve@^1.20.0#~builtin, resolve@patch:resolve@^1.22.1#~builtin, resolve@patch:resolve@^1.3.2#~builtin": +"resolve@patch:resolve@^1.1.6#~builtin, resolve@patch:resolve@^1.14.2#~builtin, resolve@patch:resolve@^1.20.0#~builtin, resolve@patch:resolve@^1.22.1#~builtin, resolve@patch:resolve@^1.3.2#~builtin": version: 1.22.8 resolution: "resolve@patch:resolve@npm%3A1.22.8#~builtin::version=1.22.8&hash=c3c19d" dependencies: @@ -19045,20 +18645,6 @@ __metadata: languageName: node linkType: hard -"rollup@npm:^2.67.0": - version: 2.79.1 - resolution: "rollup@npm:2.79.1" - dependencies: - fsevents: ~2.3.2 - dependenciesMeta: - fsevents: - optional: true - bin: - rollup: dist/bin/rollup - checksum: 6a2bf167b3587d4df709b37d149ad0300692cc5deb510f89ac7bdc77c8738c9546ae3de9322b0968e1ed2b0e984571f5f55aae28fa7de4cfcb1bc5402a4e2be6 - languageName: node - linkType: hard - "rollup@npm:^4.4.0": version: 4.9.4 resolution: "rollup@npm:4.9.4" @@ -19134,15 +18720,6 @@ __metadata: languageName: node linkType: hard -"run-applescript@npm:^5.0.0": - version: 5.0.0 - resolution: "run-applescript@npm:5.0.0" - dependencies: - execa: ^5.0.0 - checksum: d00c2dbfa5b2d774de7451194b8b125f40f65fc183de7d9dcae97f57f59433586d3c39b9001e111c38bfa24c3436c99df1bb4066a2a0c90d39a8c4cd6889af77 - languageName: node - linkType: hard - "run-applescript@npm:^7.0.0": version: 7.0.0 resolution: "run-applescript@npm:7.0.0" @@ -19330,6 +18907,17 @@ __metadata: languageName: node linkType: hard +"semver@npm:7.6.0": + version: 7.6.0 + resolution: "semver@npm:7.6.0" + dependencies: + lru-cache: ^6.0.0 + bin: + semver: bin/semver.js + checksum: 7427f05b70786c696640edc29fdd4bc33b2acf3bbe1740b955029044f80575fc664e1a512e4113c3af21e767154a94b4aa214bf6cd6e42a1f6dba5914e0b208c + languageName: node + linkType: hard + "semver@npm:^5.4.1, semver@npm:^5.5.0": version: 5.7.2 resolution: "semver@npm:5.7.2" @@ -19933,6 +19521,20 @@ __metadata: languageName: node linkType: hard +"streamx@npm:^2.13.0": + version: 2.16.1 + resolution: "streamx@npm:2.16.1" + dependencies: + bare-events: ^2.2.0 + fast-fifo: ^1.1.0 + queue-tick: ^1.0.1 + dependenciesMeta: + bare-events: + optional: true + checksum: 6bbb4c38c0ab6ddbe0857d55e72f71288f308f2a9f4413b7b07391cdf9f94232ffc2bbe40a1212d2e09634ecdbd5052b444c73cc8d67ae1c97e2b7e553dad559 + languageName: node + linkType: hard + "streamx@npm:^2.15.0": version: 2.15.6 resolution: "streamx@npm:2.15.6" @@ -20066,13 +19668,6 @@ __metadata: languageName: node linkType: hard -"strip-final-newline@npm:^3.0.0": - version: 3.0.0 - resolution: "strip-final-newline@npm:3.0.0" - checksum: 23ee263adfa2070cd0f23d1ac14e2ed2f000c9b44229aec9c799f1367ec001478469560abefd00c5c99ee6f0b31c137d53ec6029c53e9f32a93804e18c201050 - languageName: node - linkType: hard - "strip-hex-prefix@npm:1.0.0": version: 1.0.0 resolution: "strip-hex-prefix@npm:1.0.0" @@ -20200,13 +19795,13 @@ __metadata: languageName: node linkType: hard -"synckit@npm:^0.8.5": - version: 0.8.6 - resolution: "synckit@npm:0.8.6" +"synckit@npm:^0.8.6": + version: 0.8.8 + resolution: "synckit@npm:0.8.8" dependencies: - "@pkgr/utils": ^2.4.2 + "@pkgr/core": ^0.1.0 tslib: ^2.6.2 - checksum: 7c1f4991d0afd63c090c0537f1cf8619dd5777a40cf83bf46beadbf4eb0f9e400d92044e90a177a305df4bcb56efbaf1b689877f301f2672d865b6eecf1be75a + checksum: 9ed5d33abb785f5f24e2531efd53b2782ca77abf7912f734d170134552b99001915531be5a50297aa45c5701b5c9041e8762e6cd7a38e41e2461c1e7fccdedf8 languageName: node linkType: hard @@ -20253,39 +19848,20 @@ __metadata: languageName: node linkType: hard -"tar-fs@npm:2.1.1": - version: 2.1.1 - resolution: "tar-fs@npm:2.1.1" - dependencies: - chownr: ^1.1.1 - mkdirp-classic: ^0.5.2 - pump: ^3.0.0 - tar-stream: ^2.1.4 - checksum: f5b9a70059f5b2969e65f037b4e4da2daf0fa762d3d232ffd96e819e3f94665dbbbe62f76f084f1acb4dbdcce16c6e4dac08d12ffc6d24b8d76720f4d9cf032d - languageName: node - linkType: hard - -"tar-fs@npm:3.0.4": - version: 3.0.4 - resolution: "tar-fs@npm:3.0.4" +"tar-fs@npm:3.0.5": + version: 3.0.5 + resolution: "tar-fs@npm:3.0.5" dependencies: - mkdirp-classic: ^0.5.2 + bare-fs: ^2.1.1 + bare-path: ^2.1.0 pump: ^3.0.0 tar-stream: ^3.1.5 - checksum: dcf4054f9e92ca0efe61c2b3f612914fb259a47900aa908a63106513a6d006c899b426ada53eb88d9dbbf089b5724c8e90b96a2c4ca6171845fa14203d734e30 - languageName: node - linkType: hard - -"tar-stream@npm:^2.1.4": - version: 2.2.0 - resolution: "tar-stream@npm:2.2.0" - dependencies: - bl: ^4.0.3 - end-of-stream: ^1.4.1 - fs-constants: ^1.0.0 - inherits: ^2.0.3 - readable-stream: ^3.1.1 - checksum: 699831a8b97666ef50021c767f84924cfee21c142c2eb0e79c63254e140e6408d6d55a065a2992548e72b06de39237ef2b802b99e3ece93ca3904a37622a66f3 + dependenciesMeta: + bare-fs: + optional: true + bare-path: + optional: true + checksum: e31c7e3e525fec0afecdec1cac58071809e396187725f2eba442f08a4c5649c8cd6b7ce25982f9a91bb0f055628df47c08177dd2ea4f5dafd3c22f42f8da8f00 languageName: node linkType: hard @@ -20430,13 +20006,6 @@ __metadata: languageName: node linkType: hard -"titleize@npm:^3.0.0": - version: 3.0.0 - resolution: "titleize@npm:3.0.0" - checksum: 71fbbeabbfb36ccd840559f67f21e356e1d03da2915b32d2ae1a60ddcc13a124be2739f696d2feb884983441d159a18649e8d956648d591bdad35c430a6b6d28 - languageName: node - linkType: hard - "tmp@npm:0.0.33": version: 0.0.33 resolution: "tmp@npm:0.0.33" @@ -20839,63 +20408,23 @@ __metadata: languageName: node linkType: hard -"typescript@npm:5.1.5": - version: 5.1.5 - resolution: "typescript@npm:5.1.5" +"typescript@npm:5.4.2, typescript@npm:^5.4.2": + version: 5.4.2 + resolution: "typescript@npm:5.4.2" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 0eef8699e05ae767096924dbed633c340b4d36e953bb8ed87fb12e9dd9dcea5055ceac7182c614a556dbd346a8a82df799d330e1e286ae66e17c84e1710f6a6f + checksum: 96d80fde25a09bcb04d399082fb27a808a9e17c2111e43849d2aafbd642d835e4f4ef0de09b0ba795ec2a700be6c4c2c3f62bf4660c05404c948727b5bbfb32a languageName: node linkType: hard -"typescript@npm:^5.0.4, typescript@npm:^5.2.2": - version: 5.3.3 - resolution: "typescript@npm:5.3.3" +"typescript@patch:typescript@5.4.2#~builtin, typescript@patch:typescript@^5.4.2#~builtin": + version: 5.4.2 + resolution: "typescript@patch:typescript@npm%3A5.4.2#~builtin::version=5.4.2&hash=f3b441" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 2007ccb6e51bbbf6fde0a78099efe04dc1c3dfbdff04ca3b6a8bc717991862b39fd6126c0c3ebf2d2d98ac5e960bcaa873826bb2bb241f14277034148f41f6a2 - languageName: node - linkType: hard - -"typescript@npm:~5.2.2": - version: 5.2.2 - resolution: "typescript@npm:5.2.2" - bin: - tsc: bin/tsc - tsserver: bin/tsserver - checksum: 7912821dac4d962d315c36800fe387cdc0a6298dba7ec171b350b4a6e988b51d7b8f051317786db1094bd7431d526b648aba7da8236607febb26cf5b871d2d3c - languageName: node - linkType: hard - -"typescript@patch:typescript@5.1.5#~builtin": - version: 5.1.5 - resolution: "typescript@patch:typescript@npm%3A5.1.5#~builtin::version=5.1.5&hash=5da071" - bin: - tsc: bin/tsc - tsserver: bin/tsserver - checksum: 12ff5d14888805f24479e54bc8a3f83647107a6345f6c29dffcd429fb345be55f584a37e262cca58a0105203e41d4cb4e31b1b9096c9abeca0e2ace8eb00935e - languageName: node - linkType: hard - -"typescript@patch:typescript@^5.0.4#~builtin, typescript@patch:typescript@^5.2.2#~builtin": - version: 5.3.3 - resolution: "typescript@patch:typescript@npm%3A5.3.3#~builtin::version=5.3.3&hash=f3b441" - bin: - tsc: bin/tsc - tsserver: bin/tsserver - checksum: f61375590b3162599f0f0d5b8737877ac0a7bc52761dbb585d67e7b8753a3a4c42d9a554c4cc929f591ffcf3a2b0602f65ae3ce74714fd5652623a816862b610 - languageName: node - linkType: hard - -"typescript@patch:typescript@~5.2.2#~builtin": - version: 5.2.2 - resolution: "typescript@patch:typescript@npm%3A5.2.2#~builtin::version=5.2.2&hash=f3b441" - bin: - tsc: bin/tsc - tsserver: bin/tsserver - checksum: 0f4da2f15e6f1245e49db15801dbee52f2bbfb267e1c39225afdab5afee1a72839cd86000e65ee9d7e4dfaff12239d28beaf5ee431357fcced15fb08583d72ca + checksum: c1b669146bca5529873aae60870e243fa8140c85f57ca32c42f898f586d73ce4a6b4f6bb02ae312729e214d7f5859a0c70da3e527a116fdf5ad00c9fc733ecc6 languageName: node linkType: hard @@ -21261,13 +20790,6 @@ __metadata: languageName: node linkType: hard -"untildify@npm:^4.0.0": - version: 4.0.0 - resolution: "untildify@npm:4.0.0" - checksum: 39ced9c418a74f73f0a56e1ba4634b4d959422dff61f4c72a8e39f60b99380c1b45ed776fbaa0a4101b157e4310d873ad7d114e8534ca02609b4916bb4187fb9 - languageName: node - linkType: hard - "unzipit@npm:^1.4.3": version: 1.4.3 resolution: "unzipit@npm:1.4.3" @@ -21390,6 +20912,13 @@ __metadata: languageName: node linkType: hard +"urlpattern-polyfill@npm:10.0.0": + version: 10.0.0 + resolution: "urlpattern-polyfill@npm:10.0.0" + checksum: 61d890f151ea4ecf34a3dcab32c65ad1f3cda857c9d154af198260c6e5b2ad96d024593409baaa6d4428dd1ab206c14799bf37fe011117ac93a6a44913ac5aa4 + languageName: node + linkType: hard + "util-deprecate@npm:^1.0.1, util-deprecate@npm:^1.0.2, util-deprecate@npm:~1.0.1": version: 1.0.2 resolution: "util-deprecate@npm:1.0.2" @@ -22117,9 +21646,9 @@ __metadata: languageName: node linkType: hard -"ws@npm:8.13.0": - version: 8.13.0 - resolution: "ws@npm:8.13.0" +"ws@npm:8.16.0, ws@npm:^8.16.0": + version: 8.16.0 + resolution: "ws@npm:8.16.0" peerDependencies: bufferutil: ^4.0.1 utf-8-validate: ">=5.0.2" @@ -22128,7 +21657,7 @@ __metadata: optional: true utf-8-validate: optional: true - checksum: 53e991bbf928faf5dc6efac9b8eb9ab6497c69feeb94f963d648b7a3530a720b19ec2e0ec037344257e05a4f35bd9ad04d9de6f289615ffb133282031b18c61c + checksum: feb3eecd2bae82fa8a8beef800290ce437d8b8063bdc69712725f21aef77c49cb2ff45c6e5e7fce622248f9c7abaee506bae0a9064067ffd6935460c7357321b languageName: node linkType: hard @@ -22177,21 +21706,6 @@ __metadata: languageName: node linkType: hard -"ws@npm:^8.16.0": - version: 8.16.0 - resolution: "ws@npm:8.16.0" - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ">=5.0.2" - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - checksum: feb3eecd2bae82fa8a8beef800290ce437d8b8063bdc69712725f21aef77c49cb2ff45c6e5e7fce622248f9c7abaee506bae0a9064067ffd6935460c7357321b - languageName: node - linkType: hard - "xdg-basedir@npm:^4.0.0": version: 4.0.0 resolution: "xdg-basedir@npm:4.0.0" @@ -22340,22 +21854,7 @@ __metadata: languageName: node linkType: hard -"yargs@npm:17.7.1": - version: 17.7.1 - resolution: "yargs@npm:17.7.1" - dependencies: - cliui: ^8.0.1 - escalade: ^3.1.1 - get-caller-file: ^2.0.5 - require-directory: ^2.1.1 - string-width: ^4.2.3 - y18n: ^5.0.5 - yargs-parser: ^21.1.1 - checksum: 3d8a43c336a4942bc68080768664aca85c7bd406f018bad362fd255c41c8f4e650277f42fd65d543fce99e084124ddafee7bbfc1a5c6a8fda4cec78609dcf8d4 - languageName: node - linkType: hard - -"yargs@npm:^17.7.1": +"yargs@npm:17.7.2, yargs@npm:^17.7.1": version: 17.7.2 resolution: "yargs@npm:17.7.2" dependencies: